@@ -13,7 +13,7 @@ static LIST_HEAD(devcom_list);
13
13
14
14
struct mlx5_devcom_component {
15
15
struct {
16
- void * data ;
16
+ void __rcu * data ;
17
17
} device [MLX5_DEVCOM_PORTS_SUPPORTED ];
18
18
19
19
mlx5_devcom_event_handler_t handler ;
@@ -162,7 +162,7 @@ void mlx5_devcom_register_component(struct mlx5_devcom *devcom,
162
162
comp = & devcom -> priv -> components [id ];
163
163
down_write (& comp -> sem );
164
164
comp -> handler = handler ;
165
- comp -> device [devcom -> idx ].data = data ;
165
+ rcu_assign_pointer ( comp -> device [devcom -> idx ].data , data ) ;
166
166
up_write (& comp -> sem );
167
167
}
168
168
@@ -176,8 +176,9 @@ void mlx5_devcom_unregister_component(struct mlx5_devcom *devcom,
176
176
177
177
comp = & devcom -> priv -> components [id ];
178
178
down_write (& comp -> sem );
179
- comp -> device [devcom -> idx ].data = NULL ;
179
+ RCU_INIT_POINTER ( comp -> device [devcom -> idx ].data , NULL ) ;
180
180
up_write (& comp -> sem );
181
+ synchronize_rcu ();
181
182
}
182
183
183
184
int mlx5_devcom_send_event (struct mlx5_devcom * devcom ,
@@ -193,12 +194,15 @@ int mlx5_devcom_send_event(struct mlx5_devcom *devcom,
193
194
194
195
comp = & devcom -> priv -> components [id ];
195
196
down_write (& comp -> sem );
196
- for (i = 0 ; i < MLX5_DEVCOM_PORTS_SUPPORTED ; i ++ )
197
- if (i != devcom -> idx && comp -> device [i ].data ) {
198
- err = comp -> handler (event , comp -> device [i ].data ,
199
- event_data );
197
+ for (i = 0 ; i < MLX5_DEVCOM_PORTS_SUPPORTED ; i ++ ) {
198
+ void * data = rcu_dereference_protected (comp -> device [i ].data ,
199
+ lockdep_is_held (& comp -> sem ));
200
+
201
+ if (i != devcom -> idx && data ) {
202
+ err = comp -> handler (event , data , event_data );
200
203
break ;
201
204
}
205
+ }
202
206
203
207
up_write (& comp -> sem );
204
208
return err ;
@@ -213,7 +217,7 @@ void mlx5_devcom_set_paired(struct mlx5_devcom *devcom,
213
217
comp = & devcom -> priv -> components [id ];
214
218
WARN_ON (!rwsem_is_locked (& comp -> sem ));
215
219
216
- comp -> paired = paired ;
220
+ WRITE_ONCE ( comp -> paired , paired ) ;
217
221
}
218
222
219
223
bool mlx5_devcom_is_paired (struct mlx5_devcom * devcom ,
@@ -222,7 +226,7 @@ bool mlx5_devcom_is_paired(struct mlx5_devcom *devcom,
222
226
if (IS_ERR_OR_NULL (devcom ))
223
227
return false;
224
228
225
- return devcom -> priv -> components [id ].paired ;
229
+ return READ_ONCE ( devcom -> priv -> components [id ].paired ) ;
226
230
}
227
231
228
232
void * mlx5_devcom_get_peer_data (struct mlx5_devcom * devcom ,
@@ -236,7 +240,7 @@ void *mlx5_devcom_get_peer_data(struct mlx5_devcom *devcom,
236
240
237
241
comp = & devcom -> priv -> components [id ];
238
242
down_read (& comp -> sem );
239
- if (!comp -> paired ) {
243
+ if (!READ_ONCE ( comp -> paired ) ) {
240
244
up_read (& comp -> sem );
241
245
return NULL ;
242
246
}
@@ -245,7 +249,29 @@ void *mlx5_devcom_get_peer_data(struct mlx5_devcom *devcom,
245
249
if (i != devcom -> idx )
246
250
break ;
247
251
248
- return comp -> device [i ].data ;
252
+ return rcu_dereference_protected (comp -> device [i ].data , lockdep_is_held (& comp -> sem ));
253
+ }
254
+
255
+ void * mlx5_devcom_get_peer_data_rcu (struct mlx5_devcom * devcom , enum mlx5_devcom_components id )
256
+ {
257
+ struct mlx5_devcom_component * comp ;
258
+ int i ;
259
+
260
+ if (IS_ERR_OR_NULL (devcom ))
261
+ return NULL ;
262
+
263
+ for (i = 0 ; i < MLX5_DEVCOM_PORTS_SUPPORTED ; i ++ )
264
+ if (i != devcom -> idx )
265
+ break ;
266
+
267
+ comp = & devcom -> priv -> components [id ];
268
+ /* This can change concurrently, however 'data' pointer will remain
269
+ * valid for the duration of RCU read section.
270
+ */
271
+ if (!READ_ONCE (comp -> paired ))
272
+ return NULL ;
273
+
274
+ return rcu_dereference (comp -> device [i ].data );
249
275
}
250
276
251
277
void mlx5_devcom_release_peer_data (struct mlx5_devcom * devcom ,
0 commit comments