Skip to content

Commit 9ad716b

Browse files
Jakub Kicinskidavem330
authored andcommitted
nfp: wait for posted reconfigs when disabling the device
To avoid leaking a running timer we need to wait for the posted reconfigs after netdev is unregistered. In common case the process of deinitializing the device will perform synchronous reconfigs which wait for posted requests, but especially with VXLAN ports being actively added and removed there can be a race condition leaving a timer running after adapter structure is freed leading to a crash. Add an explicit flush after deregistering and for a good measure a warning to check if timer is running just before structures are freed. Fixes: 3d780b9 ("nfp: add async reconfiguration mechanism") Signed-off-by: Jakub Kicinski <[email protected]> Reviewed-by: Dirk van der Merwe <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 3a7ad06 commit 9ad716b

File tree

1 file changed

+33
-15
lines changed

1 file changed

+33
-15
lines changed

drivers/net/ethernet/netronome/nfp/nfp_net_common.c

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -229,29 +229,16 @@ static void nfp_net_reconfig_post(struct nfp_net *nn, u32 update)
229229
spin_unlock_bh(&nn->reconfig_lock);
230230
}
231231

232-
/**
233-
* nfp_net_reconfig() - Reconfigure the firmware
234-
* @nn: NFP Net device to reconfigure
235-
* @update: The value for the update field in the BAR config
236-
*
237-
* Write the update word to the BAR and ping the reconfig queue. The
238-
* poll until the firmware has acknowledged the update by zeroing the
239-
* update word.
240-
*
241-
* Return: Negative errno on error, 0 on success
242-
*/
243-
int nfp_net_reconfig(struct nfp_net *nn, u32 update)
232+
static void nfp_net_reconfig_sync_enter(struct nfp_net *nn)
244233
{
245234
bool cancelled_timer = false;
246235
u32 pre_posted_requests;
247-
int ret;
248236

249237
spin_lock_bh(&nn->reconfig_lock);
250238

251239
nn->reconfig_sync_present = true;
252240

253241
if (nn->reconfig_timer_active) {
254-
del_timer(&nn->reconfig_timer);
255242
nn->reconfig_timer_active = false;
256243
cancelled_timer = true;
257244
}
@@ -260,14 +247,43 @@ int nfp_net_reconfig(struct nfp_net *nn, u32 update)
260247

261248
spin_unlock_bh(&nn->reconfig_lock);
262249

263-
if (cancelled_timer)
250+
if (cancelled_timer) {
251+
del_timer_sync(&nn->reconfig_timer);
264252
nfp_net_reconfig_wait(nn, nn->reconfig_timer.expires);
253+
}
265254

266255
/* Run the posted reconfigs which were issued before we started */
267256
if (pre_posted_requests) {
268257
nfp_net_reconfig_start(nn, pre_posted_requests);
269258
nfp_net_reconfig_wait(nn, jiffies + HZ * NFP_NET_POLL_TIMEOUT);
270259
}
260+
}
261+
262+
static void nfp_net_reconfig_wait_posted(struct nfp_net *nn)
263+
{
264+
nfp_net_reconfig_sync_enter(nn);
265+
266+
spin_lock_bh(&nn->reconfig_lock);
267+
nn->reconfig_sync_present = false;
268+
spin_unlock_bh(&nn->reconfig_lock);
269+
}
270+
271+
/**
272+
* nfp_net_reconfig() - Reconfigure the firmware
273+
* @nn: NFP Net device to reconfigure
274+
* @update: The value for the update field in the BAR config
275+
*
276+
* Write the update word to the BAR and ping the reconfig queue. The
277+
* poll until the firmware has acknowledged the update by zeroing the
278+
* update word.
279+
*
280+
* Return: Negative errno on error, 0 on success
281+
*/
282+
int nfp_net_reconfig(struct nfp_net *nn, u32 update)
283+
{
284+
int ret;
285+
286+
nfp_net_reconfig_sync_enter(nn);
271287

272288
nfp_net_reconfig_start(nn, update);
273289
ret = nfp_net_reconfig_wait(nn, jiffies + HZ * NFP_NET_POLL_TIMEOUT);
@@ -3633,6 +3649,7 @@ struct nfp_net *nfp_net_alloc(struct pci_dev *pdev, bool needs_netdev,
36333649
*/
36343650
void nfp_net_free(struct nfp_net *nn)
36353651
{
3652+
WARN_ON(timer_pending(&nn->reconfig_timer) || nn->reconfig_posted);
36363653
if (nn->dp.netdev)
36373654
free_netdev(nn->dp.netdev);
36383655
else
@@ -3920,4 +3937,5 @@ void nfp_net_clean(struct nfp_net *nn)
39203937
return;
39213938

39223939
unregister_netdev(nn->dp.netdev);
3940+
nfp_net_reconfig_wait_posted(nn);
39233941
}

0 commit comments

Comments
 (0)