Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

sfc: move table locking into filter_table_{probe,remove} methods

We need to be able to drop the efx->filter_sem in ef100_filter_table_up()
so that we can call functions that insert filters (and thus take that
rwsem for read), which means the efx->type->filter_table_probe method
needs to be responsible for taking the lock in the first place.

Signed-off-by: Edward Cree <ecree.xilinx@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Edward Cree and committed by
Jakub Kicinski
77eb4074 67ab160e

+33 -36
+15 -11
drivers/net/ethernet/sfc/ef10.c
··· 2538 2538 2539 2539 if (rc) 2540 2540 return rc; 2541 + down_write(&efx->filter_sem); 2541 2542 rc = efx_mcdi_filter_table_probe(efx, nic_data->workaround_26807); 2542 2543 2543 2544 if (rc) 2544 - return rc; 2545 + goto out_unlock; 2545 2546 2546 2547 list_for_each_entry(vlan, &nic_data->vlan_list, list) { 2547 2548 rc = efx_mcdi_filter_add_vlan(efx, vlan->vid); 2548 2549 if (rc) 2549 2550 goto fail_add_vlan; 2550 2551 } 2551 - return 0; 2552 + goto out_unlock; 2552 2553 2553 2554 fail_add_vlan: 2554 2555 efx_mcdi_filter_table_remove(efx); 2556 + out_unlock: 2557 + up_write(&efx->filter_sem); 2555 2558 return rc; 2559 + } 2560 + 2561 + static void efx_ef10_filter_table_remove(struct efx_nic *efx) 2562 + { 2563 + down_write(&efx->filter_sem); 2564 + efx_mcdi_filter_table_remove(efx); 2565 + up_write(&efx->filter_sem); 2556 2566 } 2557 2567 2558 2568 /* This creates an entry in the RX descriptor queue */ ··· 3221 3211 3222 3212 efx_device_detach_sync(efx); 3223 3213 efx_net_stop(efx->net_dev); 3224 - down_write(&efx->filter_sem); 3225 - efx_mcdi_filter_table_remove(efx); 3226 - up_write(&efx->filter_sem); 3214 + efx_ef10_filter_table_remove(efx); 3227 3215 3228 3216 rc = efx_ef10_vadaptor_free(efx, efx->vport_id); 3229 3217 if (rc) ··· 3251 3243 if (rc2) 3252 3244 goto reset_nic; 3253 3245 restore_filters: 3254 - down_write(&efx->filter_sem); 3255 3246 rc2 = efx_ef10_filter_table_probe(efx); 3256 - up_write(&efx->filter_sem); 3257 3247 if (rc2) 3258 3248 goto reset_nic; 3259 3249 ··· 3281 3275 efx_net_stop(efx->net_dev); 3282 3276 3283 3277 mutex_lock(&efx->mac_lock); 3284 - down_write(&efx->filter_sem); 3285 - efx_mcdi_filter_table_remove(efx); 3278 + efx_ef10_filter_table_remove(efx); 3286 3279 3287 3280 ether_addr_copy(MCDI_PTR(inbuf, VADAPTOR_SET_MAC_IN_MACADDR), 3288 3281 efx->net_dev->dev_addr); ··· 3291 3286 sizeof(inbuf), NULL, 0, NULL); 3292 3287 3293 3288 efx_ef10_filter_table_probe(efx); 3294 - up_write(&efx->filter_sem); 3295 3289 mutex_unlock(&efx->mac_lock); 3296 3290 3297 3291 if (was_enabled) ··· 4096 4092 .ev_test_generate = efx_ef10_ev_test_generate, 4097 4093 .filter_table_probe = efx_ef10_filter_table_probe, 4098 4094 .filter_table_restore = efx_mcdi_filter_table_restore, 4099 - .filter_table_remove = efx_mcdi_filter_table_remove, 4095 + .filter_table_remove = efx_ef10_filter_table_remove, 4100 4096 .filter_update_rx_scatter = efx_mcdi_update_rx_scatter, 4101 4097 .filter_insert = efx_mcdi_filter_insert, 4102 4098 .filter_remove_safe = efx_mcdi_filter_remove_safe,
+14 -8
drivers/net/ethernet/sfc/ef100_nic.c
··· 375 375 { 376 376 int rc; 377 377 378 + down_write(&efx->filter_sem); 378 379 rc = efx_mcdi_filter_add_vlan(efx, EFX_FILTER_VID_UNSPEC); 379 - if (rc) { 380 - efx_mcdi_filter_table_down(efx); 381 - return rc; 382 - } 380 + if (rc) 381 + goto fail_unspec; 383 382 384 383 rc = efx_mcdi_filter_add_vlan(efx, 0); 385 - if (rc) { 386 - efx_mcdi_filter_del_vlan(efx, EFX_FILTER_VID_UNSPEC); 387 - efx_mcdi_filter_table_down(efx); 388 - } 384 + if (rc) 385 + goto fail_vlan0; 386 + up_write(&efx->filter_sem); 387 + return 0; 389 388 389 + fail_vlan0: 390 + efx_mcdi_filter_del_vlan(efx, EFX_FILTER_VID_UNSPEC); 391 + fail_unspec: 392 + efx_mcdi_filter_table_down(efx); 393 + up_write(&efx->filter_sem); 390 394 return rc; 391 395 } 392 396 393 397 static void ef100_filter_table_down(struct efx_nic *efx) 394 398 { 399 + down_write(&efx->filter_sem); 395 400 efx_mcdi_filter_del_vlan(efx, 0); 396 401 efx_mcdi_filter_del_vlan(efx, EFX_FILTER_VID_UNSPEC); 397 402 efx_mcdi_filter_table_down(efx); 403 + up_write(&efx->filter_sem); 398 404 } 399 405 400 406 /* Other
+3 -13
drivers/net/ethernet/sfc/ef10_sriov.c
··· 501 501 efx_device_detach_sync(vf->efx); 502 502 efx_net_stop(vf->efx->net_dev); 503 503 504 - down_write(&vf->efx->filter_sem); 505 504 vf->efx->type->filter_table_remove(vf->efx); 506 505 507 506 rc = efx_ef10_vadaptor_free(vf->efx, EVB_PORT_ID_ASSIGNED); 508 - if (rc) { 509 - up_write(&vf->efx->filter_sem); 507 + if (rc) 510 508 return rc; 511 - } 512 509 } 513 510 514 511 rc = efx_ef10_evb_port_assign(efx, EVB_PORT_ID_NULL, vf_i); ··· 536 539 if (vf->efx) { 537 540 /* VF cannot use the vport_id that the PF created */ 538 541 rc = efx_ef10_vadaptor_alloc(vf->efx, EVB_PORT_ID_ASSIGNED); 539 - if (rc) { 540 - up_write(&vf->efx->filter_sem); 542 + if (rc) 541 543 return rc; 542 - } 543 544 vf->efx->type->filter_table_probe(vf->efx); 544 - up_write(&vf->efx->filter_sem); 545 545 efx_net_open(vf->efx->net_dev); 546 546 efx_device_attach_if_not_resetting(vf->efx); 547 547 } ··· 574 580 efx_net_stop(vf->efx->net_dev); 575 581 576 582 mutex_lock(&vf->efx->mac_lock); 577 - down_write(&vf->efx->filter_sem); 578 583 vf->efx->type->filter_table_remove(vf->efx); 579 584 580 585 rc = efx_ef10_vadaptor_free(vf->efx, EVB_PORT_ID_ASSIGNED); ··· 647 654 if (rc2) 648 655 goto reset_nic_up_write; 649 656 650 - up_write(&vf->efx->filter_sem); 651 657 mutex_unlock(&vf->efx->mac_lock); 652 658 653 659 rc2 = efx_net_open(vf->efx->net_dev); ··· 658 666 return rc; 659 667 660 668 reset_nic_up_write: 661 - if (vf->efx) { 662 - up_write(&vf->efx->filter_sem); 669 + if (vf->efx) 663 670 mutex_unlock(&vf->efx->mac_lock); 664 - } 665 671 reset_nic: 666 672 if (vf->efx) { 667 673 netif_err(efx, drv, efx->net_dev,
+1
drivers/net/ethernet/sfc/mcdi_filters.h
··· 89 89 */ 90 90 bool mc_chaining; 91 91 bool vlan_filter; 92 + /* Entries on the vlan_list are added/removed under filter_sem */ 92 93 struct list_head vlan_list; 93 94 }; 94 95
-4
drivers/net/ethernet/sfc/rx_common.c
··· 793 793 int rc; 794 794 795 795 mutex_lock(&efx->mac_lock); 796 - down_write(&efx->filter_sem); 797 796 rc = efx->type->filter_table_probe(efx); 798 797 if (rc) 799 798 goto out_unlock; ··· 829 830 } 830 831 #endif 831 832 out_unlock: 832 - up_write(&efx->filter_sem); 833 833 mutex_unlock(&efx->mac_lock); 834 834 return rc; 835 835 } ··· 844 846 channel->rps_flow_id = NULL; 845 847 } 846 848 #endif 847 - down_write(&efx->filter_sem); 848 849 efx->type->filter_table_remove(efx); 849 - up_write(&efx->filter_sem); 850 850 } 851 851 852 852 #ifdef CONFIG_RFS_ACCEL