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

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'net-mlx5-move-notifiers-outside-the-devlink-lock'

Tariq Toukan says:

====================
net/mlx5: Move notifiers outside the devlink lock

This series by Cosmin moves blocking notifier registration in the mlx5
driver outside the devlink lock during probe.

This is mostly a no-op refactoring that consists of multiple pieces.
It is necessary because upcoming code will introduce a potential locking
cycle between the devlink lock and the blocking notifier head mutexes,
so these notifiers must move out of the devlink-locked critical section.
====================

Link: https://patch.msgid.link/1763325940-1231508-1-git-send-email-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+253 -151
+7 -6
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
··· 1474 1474 1475 1475 info.new_mode = mode; 1476 1476 1477 - blocking_notifier_call_chain(&esw->n_head, 0, &info); 1477 + blocking_notifier_call_chain(&esw->dev->priv.esw_n_head, 0, &info); 1478 1478 } 1479 1479 1480 1480 static int mlx5_esw_egress_acls_init(struct mlx5_core_dev *dev) ··· 2050 2050 esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_BASIC; 2051 2051 else 2052 2052 esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_NONE; 2053 - BLOCKING_INIT_NOTIFIER_HEAD(&esw->n_head); 2054 2053 2055 2054 esw_info(dev, 2056 2055 "Total vports %d, per vport: max uc(%d) max mc(%d)\n", ··· 2378 2379 dev1->priv.eswitch->mode == MLX5_ESWITCH_OFFLOADS); 2379 2380 } 2380 2381 2381 - int mlx5_esw_event_notifier_register(struct mlx5_eswitch *esw, struct notifier_block *nb) 2382 + int mlx5_esw_event_notifier_register(struct mlx5_core_dev *dev, 2383 + struct notifier_block *nb) 2382 2384 { 2383 - return blocking_notifier_chain_register(&esw->n_head, nb); 2385 + return blocking_notifier_chain_register(&dev->priv.esw_n_head, nb); 2384 2386 } 2385 2387 2386 - void mlx5_esw_event_notifier_unregister(struct mlx5_eswitch *esw, struct notifier_block *nb) 2388 + void mlx5_esw_event_notifier_unregister(struct mlx5_core_dev *dev, 2389 + struct notifier_block *nb) 2387 2390 { 2388 - blocking_notifier_chain_unregister(&esw->n_head, nb); 2391 + blocking_notifier_chain_unregister(&dev->priv.esw_n_head, nb); 2389 2392 } 2390 2393 2391 2394 /**
+4 -3
drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
··· 403 403 struct { 404 404 u32 large_group_num; 405 405 } params; 406 - struct blocking_notifier_head n_head; 407 406 struct xarray paired; 408 407 struct mlx5_devcom_comp_dev *devcom; 409 408 u16 enabled_ipsec_vf_count; ··· 863 864 u16 new_mode; 864 865 }; 865 866 866 - int mlx5_esw_event_notifier_register(struct mlx5_eswitch *esw, struct notifier_block *n); 867 - void mlx5_esw_event_notifier_unregister(struct mlx5_eswitch *esw, struct notifier_block *n); 867 + int mlx5_esw_event_notifier_register(struct mlx5_core_dev *dev, 868 + struct notifier_block *n); 869 + void mlx5_esw_event_notifier_unregister(struct mlx5_core_dev *dev, 870 + struct notifier_block *n); 868 871 869 872 bool mlx5_esw_hold(struct mlx5_core_dev *dev); 870 873 void mlx5_esw_release(struct mlx5_core_dev *dev);
+51 -19
drivers/net/ethernet/mellanox/mlx5/core/main.c
··· 1010 1010 goto err_irq_cleanup; 1011 1011 } 1012 1012 1013 - err = mlx5_events_init(dev); 1014 - if (err) { 1015 - mlx5_core_err(dev, "failed to initialize events\n"); 1016 - goto err_eq_cleanup; 1017 - } 1018 - 1019 1013 err = mlx5_fw_reset_init(dev); 1020 1014 if (err) { 1021 1015 mlx5_core_err(dev, "failed to initialize fw reset events\n"); 1022 - goto err_events_cleanup; 1016 + goto err_eq_cleanup; 1023 1017 } 1024 1018 1025 1019 mlx5_cq_debugfs_init(dev); ··· 1115 1121 mlx5_cleanup_reserved_gids(dev); 1116 1122 mlx5_cq_debugfs_cleanup(dev); 1117 1123 mlx5_fw_reset_cleanup(dev); 1118 - err_events_cleanup: 1119 - mlx5_events_cleanup(dev); 1120 1124 err_eq_cleanup: 1121 1125 mlx5_eq_table_cleanup(dev); 1122 1126 err_irq_cleanup: ··· 1147 1155 mlx5_cleanup_reserved_gids(dev); 1148 1156 mlx5_cq_debugfs_cleanup(dev); 1149 1157 mlx5_fw_reset_cleanup(dev); 1150 - mlx5_events_cleanup(dev); 1151 1158 mlx5_eq_table_cleanup(dev); 1152 1159 mlx5_irq_table_cleanup(dev); 1153 1160 mlx5_devcom_unregister_device(dev->priv.devc); ··· 1377 1386 1378 1387 mlx5_vhca_event_start(dev); 1379 1388 1380 - err = mlx5_sf_hw_table_create(dev); 1381 - if (err) { 1382 - mlx5_core_err(dev, "sf table create failed %d\n", err); 1383 - goto err_vhca; 1384 - } 1385 - 1386 1389 err = mlx5_ec_init(dev); 1387 1390 if (err) { 1388 1391 mlx5_core_err(dev, "Failed to init embedded CPU\n"); ··· 1405 1420 mlx5_lag_remove_mdev(dev); 1406 1421 mlx5_ec_cleanup(dev); 1407 1422 err_ec: 1408 - mlx5_sf_hw_table_destroy(dev); 1409 - err_vhca: 1410 1423 mlx5_vhca_event_stop(dev); 1411 1424 err_set_hca: 1412 1425 mlx5_fs_core_cleanup(dev); ··· 1430 1447 { 1431 1448 mlx5_eswitch_disable(dev->priv.eswitch); 1432 1449 mlx5_devlink_traps_unregister(priv_to_devlink(dev)); 1450 + mlx5_vhca_event_stop(dev); 1433 1451 mlx5_sf_dev_table_destroy(dev); 1434 1452 mlx5_sriov_detach(dev); 1435 1453 mlx5_lag_remove_mdev(dev); 1436 1454 mlx5_ec_cleanup(dev); 1437 1455 mlx5_sf_hw_table_destroy(dev); 1438 - mlx5_vhca_event_stop(dev); 1439 1456 mlx5_fs_core_cleanup(dev); 1440 1457 mlx5_fpga_device_stop(dev); 1441 1458 mlx5_rsc_dump_cleanup(dev); ··· 1816 1833 1817 1834 DEFINE_SHOW_ATTRIBUTE(vhca_id); 1818 1835 1836 + static int mlx5_notifiers_init(struct mlx5_core_dev *dev) 1837 + { 1838 + int err; 1839 + 1840 + err = mlx5_events_init(dev); 1841 + if (err) { 1842 + mlx5_core_err(dev, "failed to initialize events\n"); 1843 + return err; 1844 + } 1845 + 1846 + BLOCKING_INIT_NOTIFIER_HEAD(&dev->priv.esw_n_head); 1847 + mlx5_vhca_state_notifier_init(dev); 1848 + 1849 + err = mlx5_sf_hw_notifier_init(dev); 1850 + if (err) 1851 + goto err_sf_hw_notifier; 1852 + 1853 + err = mlx5_sf_notifiers_init(dev); 1854 + if (err) 1855 + goto err_sf_notifiers; 1856 + 1857 + err = mlx5_sf_dev_notifier_init(dev); 1858 + if (err) 1859 + goto err_sf_dev_notifier; 1860 + 1861 + return 0; 1862 + 1863 + err_sf_dev_notifier: 1864 + mlx5_sf_notifiers_cleanup(dev); 1865 + err_sf_notifiers: 1866 + mlx5_sf_hw_notifier_cleanup(dev); 1867 + err_sf_hw_notifier: 1868 + mlx5_events_cleanup(dev); 1869 + return err; 1870 + } 1871 + 1872 + static void mlx5_notifiers_cleanup(struct mlx5_core_dev *dev) 1873 + { 1874 + mlx5_sf_dev_notifier_cleanup(dev); 1875 + mlx5_sf_notifiers_cleanup(dev); 1876 + mlx5_sf_hw_notifier_cleanup(dev); 1877 + mlx5_events_cleanup(dev); 1878 + } 1879 + 1819 1880 int mlx5_mdev_init(struct mlx5_core_dev *dev, int profile_idx) 1820 1881 { 1821 1882 struct mlx5_priv *priv = &dev->priv; ··· 1915 1888 if (err) 1916 1889 goto err_hca_caps; 1917 1890 1891 + err = mlx5_notifiers_init(dev); 1892 + if (err) 1893 + goto err_hca_caps; 1894 + 1918 1895 /* The conjunction of sw_vhca_id with sw_owner_id will be a global 1919 1896 * unique id per function which uses mlx5_core. 1920 1897 * Those values are supplied to FW as part of the init HCA command to ··· 1961 1930 if (priv->sw_vhca_id > 0) 1962 1931 ida_free(&sw_vhca_ida, dev->priv.sw_vhca_id); 1963 1932 1933 + mlx5_notifiers_cleanup(dev); 1964 1934 mlx5_hca_caps_free(dev); 1965 1935 mlx5_adev_cleanup(dev); 1966 1936 mlx5_pagealloc_cleanup(dev);
+30 -18
drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.c
··· 16 16 struct xarray devices; 17 17 phys_addr_t base_address; 18 18 u64 sf_bar_length; 19 - struct notifier_block nb; 20 19 struct workqueue_struct *active_wq; 21 20 struct work_struct work; 22 21 u8 stop_active_wq:1; ··· 155 156 static int 156 157 mlx5_sf_dev_state_change_handler(struct notifier_block *nb, unsigned long event_code, void *data) 157 158 { 158 - struct mlx5_sf_dev_table *table = container_of(nb, struct mlx5_sf_dev_table, nb); 159 + struct mlx5_core_dev *dev = container_of(nb, struct mlx5_core_dev, 160 + priv.sf_dev_nb); 161 + struct mlx5_sf_dev_table *table = dev->priv.sf_dev_table; 159 162 const struct mlx5_vhca_state_event *event = data; 160 163 struct mlx5_sf_dev *sf_dev; 161 164 u16 max_functions; 162 165 u16 sf_index; 163 166 u16 base_id; 164 167 165 - max_functions = mlx5_sf_max_functions(table->dev); 168 + if (!table) 169 + return 0; 170 + 171 + max_functions = mlx5_sf_max_functions(dev); 166 172 if (!max_functions) 167 173 return 0; 168 174 169 - base_id = mlx5_sf_start_function_id(table->dev); 175 + base_id = mlx5_sf_start_function_id(dev); 170 176 if (event->function_id < base_id || event->function_id >= (base_id + max_functions)) 171 177 return 0; 172 178 ··· 181 177 case MLX5_VHCA_STATE_INVALID: 182 178 case MLX5_VHCA_STATE_ALLOCATED: 183 179 if (sf_dev) 184 - mlx5_sf_dev_del(table->dev, sf_dev, sf_index); 180 + mlx5_sf_dev_del(dev, sf_dev, sf_index); 185 181 break; 186 182 case MLX5_VHCA_STATE_TEARDOWN_REQUEST: 187 183 if (sf_dev) 188 - mlx5_sf_dev_del(table->dev, sf_dev, sf_index); 184 + mlx5_sf_dev_del(dev, sf_dev, sf_index); 189 185 else 190 - mlx5_core_err(table->dev, 186 + mlx5_core_err(dev, 191 187 "SF DEV: teardown state for invalid dev index=%d sfnum=0x%x\n", 192 188 sf_index, event->sw_function_id); 193 189 break; 194 190 case MLX5_VHCA_STATE_ACTIVE: 195 191 if (!sf_dev) 196 - mlx5_sf_dev_add(table->dev, sf_index, event->function_id, 192 + mlx5_sf_dev_add(dev, sf_index, event->function_id, 197 193 event->sw_function_id); 198 194 break; 199 195 default: ··· 319 315 } 320 316 } 321 317 318 + int mlx5_sf_dev_notifier_init(struct mlx5_core_dev *dev) 319 + { 320 + if (mlx5_core_is_sf(dev)) 321 + return 0; 322 + 323 + dev->priv.sf_dev_nb.notifier_call = mlx5_sf_dev_state_change_handler; 324 + return mlx5_vhca_event_notifier_register(dev, &dev->priv.sf_dev_nb); 325 + } 326 + 322 327 void mlx5_sf_dev_table_create(struct mlx5_core_dev *dev) 323 328 { 324 329 struct mlx5_sf_dev_table *table; ··· 342 329 goto table_err; 343 330 } 344 331 345 - table->nb.notifier_call = mlx5_sf_dev_state_change_handler; 346 332 table->dev = dev; 347 333 table->sf_bar_length = 1 << (MLX5_CAP_GEN(dev, log_min_sf_size) + 12); 348 334 table->base_address = pci_resource_start(dev->pdev, 2); 349 335 xa_init(&table->devices); 350 336 dev->priv.sf_dev_table = table; 351 - 352 - err = mlx5_vhca_event_notifier_register(dev, &table->nb); 353 - if (err) 354 - goto vhca_err; 355 337 356 338 err = mlx5_sf_dev_create_active_works(table); 357 339 if (err) ··· 359 351 360 352 arm_err: 361 353 mlx5_sf_dev_destroy_active_works(table); 362 - add_active_err: 363 - mlx5_vhca_event_notifier_unregister(dev, &table->nb); 364 354 mlx5_vhca_event_work_queues_flush(dev); 365 - vhca_err: 355 + add_active_err: 366 356 kfree(table); 367 357 dev->priv.sf_dev_table = NULL; 368 358 table_err: ··· 378 372 } 379 373 } 380 374 375 + void mlx5_sf_dev_notifier_cleanup(struct mlx5_core_dev *dev) 376 + { 377 + if (mlx5_core_is_sf(dev)) 378 + return; 379 + 380 + mlx5_vhca_event_notifier_unregister(dev, &dev->priv.sf_dev_nb); 381 + } 382 + 381 383 void mlx5_sf_dev_table_destroy(struct mlx5_core_dev *dev) 382 384 { 383 385 struct mlx5_sf_dev_table *table = dev->priv.sf_dev_table; ··· 394 380 return; 395 381 396 382 mlx5_sf_dev_destroy_active_works(table); 397 - mlx5_vhca_event_notifier_unregister(dev, &table->nb); 398 - mlx5_vhca_event_work_queues_flush(dev); 399 383 400 384 /* Now that event handler is not running, it is safe to destroy 401 385 * the sf device without race.
+11
drivers/net/ethernet/mellanox/mlx5/core/sf/dev/dev.h
··· 25 25 int err; 26 26 }; 27 27 28 + int mlx5_sf_dev_notifier_init(struct mlx5_core_dev *dev); 28 29 void mlx5_sf_dev_table_create(struct mlx5_core_dev *dev); 30 + void mlx5_sf_dev_notifier_cleanup(struct mlx5_core_dev *dev); 29 31 void mlx5_sf_dev_table_destroy(struct mlx5_core_dev *dev); 30 32 31 33 int mlx5_sf_driver_register(void); ··· 37 35 38 36 #else 39 37 38 + static inline int mlx5_sf_dev_notifier_init(struct mlx5_core_dev *dev) 39 + { 40 + return 0; 41 + } 42 + 40 43 static inline void mlx5_sf_dev_table_create(struct mlx5_core_dev *dev) 44 + { 45 + } 46 + 47 + static inline void mlx5_sf_dev_notifier_cleanup(struct mlx5_core_dev *dev) 41 48 { 42 49 } 43 50
+57 -33
drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c
··· 31 31 struct mlx5_core_dev *dev; /* To refer from notifier context. */ 32 32 struct xarray function_ids; /* function id based lookup. */ 33 33 struct mutex sf_state_lock; /* Serializes sf state among user cmds & vhca event handler. */ 34 - struct notifier_block esw_nb; 35 - struct notifier_block vhca_nb; 36 - struct notifier_block mdev_nb; 37 34 }; 38 35 39 36 static struct mlx5_sf * ··· 388 391 389 392 static int mlx5_sf_vhca_event(struct notifier_block *nb, unsigned long opcode, void *data) 390 393 { 391 - struct mlx5_sf_table *table = container_of(nb, struct mlx5_sf_table, vhca_nb); 394 + struct mlx5_core_dev *dev = container_of(nb, struct mlx5_core_dev, 395 + priv.sf_table_vhca_nb); 396 + struct mlx5_sf_table *table = dev->priv.sf_table; 392 397 const struct mlx5_vhca_state_event *event = data; 393 398 bool update = false; 394 399 struct mlx5_sf *sf; 400 + 401 + if (!table) 402 + return 0; 395 403 396 404 mutex_lock(&table->sf_state_lock); 397 405 sf = mlx5_sf_lookup_by_function_id(table, event->function_id); ··· 409 407 update = mlx5_sf_state_update_check(sf, event->new_vhca_state); 410 408 if (update) 411 409 sf->hw_state = event->new_vhca_state; 412 - trace_mlx5_sf_update_state(table->dev, sf->port_index, sf->controller, 410 + trace_mlx5_sf_update_state(dev, sf->port_index, sf->controller, 413 411 sf->hw_fn_id, sf->hw_state); 414 412 unlock: 415 413 mutex_unlock(&table->sf_state_lock); ··· 427 425 428 426 static int mlx5_sf_esw_event(struct notifier_block *nb, unsigned long event, void *data) 429 427 { 430 - struct mlx5_sf_table *table = container_of(nb, struct mlx5_sf_table, esw_nb); 428 + struct mlx5_core_dev *dev = container_of(nb, struct mlx5_core_dev, 429 + priv.sf_table_esw_nb); 431 430 const struct mlx5_esw_event_info *mode = data; 431 + 432 + if (!dev->priv.sf_table) 433 + return 0; 432 434 433 435 switch (mode->new_mode) { 434 436 case MLX5_ESWITCH_LEGACY: 435 - mlx5_sf_del_all(table); 437 + mlx5_sf_del_all(dev->priv.sf_table); 436 438 break; 437 439 default: 438 440 break; ··· 447 441 448 442 static int mlx5_sf_mdev_event(struct notifier_block *nb, unsigned long event, void *data) 449 443 { 450 - struct mlx5_sf_table *table = container_of(nb, struct mlx5_sf_table, mdev_nb); 444 + struct mlx5_core_dev *dev = container_of(nb, struct mlx5_core_dev, 445 + priv.sf_table_mdev_nb); 451 446 struct mlx5_sf_peer_devlink_event_ctx *event_ctx = data; 447 + struct mlx5_sf_table *table = dev->priv.sf_table; 452 448 int ret = NOTIFY_DONE; 453 449 struct mlx5_sf *sf; 454 450 455 - if (event != MLX5_DRIVER_EVENT_SF_PEER_DEVLINK) 451 + if (!table || event != MLX5_DRIVER_EVENT_SF_PEER_DEVLINK) 456 452 return NOTIFY_DONE; 457 - 458 453 459 454 mutex_lock(&table->sf_state_lock); 460 455 sf = mlx5_sf_lookup_by_function_id(table, event_ctx->fn_id); ··· 471 464 return ret; 472 465 } 473 466 467 + int mlx5_sf_notifiers_init(struct mlx5_core_dev *dev) 468 + { 469 + int err; 470 + 471 + if (mlx5_core_is_sf(dev)) 472 + return 0; 473 + 474 + dev->priv.sf_table_esw_nb.notifier_call = mlx5_sf_esw_event; 475 + err = mlx5_esw_event_notifier_register(dev, &dev->priv.sf_table_esw_nb); 476 + if (err) 477 + return err; 478 + 479 + dev->priv.sf_table_vhca_nb.notifier_call = mlx5_sf_vhca_event; 480 + err = mlx5_vhca_event_notifier_register(dev, 481 + &dev->priv.sf_table_vhca_nb); 482 + if (err) 483 + goto vhca_err; 484 + 485 + dev->priv.sf_table_mdev_nb.notifier_call = mlx5_sf_mdev_event; 486 + err = mlx5_blocking_notifier_register(dev, &dev->priv.sf_table_mdev_nb); 487 + if (err) 488 + goto mdev_err; 489 + 490 + return 0; 491 + mdev_err: 492 + mlx5_vhca_event_notifier_unregister(dev, &dev->priv.sf_table_vhca_nb); 493 + vhca_err: 494 + mlx5_esw_event_notifier_unregister(dev, &dev->priv.sf_table_esw_nb); 495 + return err; 496 + } 497 + 474 498 int mlx5_sf_table_init(struct mlx5_core_dev *dev) 475 499 { 476 500 struct mlx5_sf_table *table; 477 - int err; 478 501 479 502 if (!mlx5_sf_table_supported(dev) || !mlx5_vhca_event_supported(dev)) 480 503 return 0; ··· 517 480 table->dev = dev; 518 481 xa_init(&table->function_ids); 519 482 dev->priv.sf_table = table; 520 - table->esw_nb.notifier_call = mlx5_sf_esw_event; 521 - err = mlx5_esw_event_notifier_register(dev->priv.eswitch, &table->esw_nb); 522 - if (err) 523 - goto reg_err; 524 - 525 - table->vhca_nb.notifier_call = mlx5_sf_vhca_event; 526 - err = mlx5_vhca_event_notifier_register(table->dev, &table->vhca_nb); 527 - if (err) 528 - goto vhca_err; 529 - 530 - table->mdev_nb.notifier_call = mlx5_sf_mdev_event; 531 - mlx5_blocking_notifier_register(dev, &table->mdev_nb); 532 483 533 484 return 0; 485 + } 534 486 535 - vhca_err: 536 - mlx5_esw_event_notifier_unregister(dev->priv.eswitch, &table->esw_nb); 537 - reg_err: 538 - mutex_destroy(&table->sf_state_lock); 539 - kfree(table); 540 - dev->priv.sf_table = NULL; 541 - return err; 487 + void mlx5_sf_notifiers_cleanup(struct mlx5_core_dev *dev) 488 + { 489 + if (mlx5_core_is_sf(dev)) 490 + return; 491 + 492 + mlx5_blocking_notifier_unregister(dev, &dev->priv.sf_table_mdev_nb); 493 + mlx5_vhca_event_notifier_unregister(dev, &dev->priv.sf_table_vhca_nb); 494 + mlx5_esw_event_notifier_unregister(dev, &dev->priv.sf_table_esw_nb); 542 495 } 543 496 544 497 void mlx5_sf_table_cleanup(struct mlx5_core_dev *dev) ··· 538 511 if (!table) 539 512 return; 540 513 541 - mlx5_blocking_notifier_unregister(dev, &table->mdev_nb); 542 - mlx5_vhca_event_notifier_unregister(table->dev, &table->vhca_nb); 543 - mlx5_esw_event_notifier_unregister(dev->priv.eswitch, &table->esw_nb); 544 514 mutex_destroy(&table->sf_state_lock); 545 515 WARN_ON(!xa_empty(&table->function_ids)); 546 516 kfree(table);
+37 -24
drivers/net/ethernet/mellanox/mlx5/core/sf/hw_table.c
··· 30 30 }; 31 31 32 32 struct mlx5_sf_hw_table { 33 - struct mlx5_core_dev *dev; 34 33 struct mutex table_lock; /* Serializes sf deletion and vhca state change handler. */ 35 - struct notifier_block vhca_nb; 36 34 struct mlx5_sf_hwc_table hwc[MLX5_SF_HWC_MAX]; 37 35 }; 38 36 ··· 69 71 return NULL; 70 72 } 71 73 72 - static int mlx5_sf_hw_table_id_alloc(struct mlx5_sf_hw_table *table, u32 controller, 74 + static int mlx5_sf_hw_table_id_alloc(struct mlx5_core_dev *dev, 75 + struct mlx5_sf_hw_table *table, 76 + u32 controller, 73 77 u32 usr_sfnum) 74 78 { 75 79 struct mlx5_sf_hwc_table *hwc; 76 80 int free_idx = -1; 77 81 int i; 78 82 79 - hwc = mlx5_sf_controller_to_hwc(table->dev, controller); 83 + hwc = mlx5_sf_controller_to_hwc(dev, controller); 80 84 if (!hwc->sfs) 81 85 return -ENOSPC; 82 86 ··· 100 100 return free_idx; 101 101 } 102 102 103 - static void mlx5_sf_hw_table_id_free(struct mlx5_sf_hw_table *table, u32 controller, int id) 103 + static void mlx5_sf_hw_table_id_free(struct mlx5_core_dev *dev, 104 + struct mlx5_sf_hw_table *table, 105 + u32 controller, int id) 104 106 { 105 107 struct mlx5_sf_hwc_table *hwc; 106 108 107 - hwc = mlx5_sf_controller_to_hwc(table->dev, controller); 109 + hwc = mlx5_sf_controller_to_hwc(dev, controller); 108 110 hwc->sfs[id].allocated = false; 109 111 hwc->sfs[id].pending_delete = false; 110 112 } ··· 122 120 return -EOPNOTSUPP; 123 121 124 122 mutex_lock(&table->table_lock); 125 - sw_id = mlx5_sf_hw_table_id_alloc(table, controller, usr_sfnum); 123 + sw_id = mlx5_sf_hw_table_id_alloc(dev, table, controller, usr_sfnum); 126 124 if (sw_id < 0) { 127 125 err = sw_id; 128 126 goto exist_err; ··· 153 151 vhca_err: 154 152 mlx5_cmd_dealloc_sf(dev, hw_fn_id); 155 153 err: 156 - mlx5_sf_hw_table_id_free(table, controller, sw_id); 154 + mlx5_sf_hw_table_id_free(dev, table, controller, sw_id); 157 155 exist_err: 158 156 mutex_unlock(&table->table_lock); 159 157 return err; ··· 167 165 mutex_lock(&table->table_lock); 168 166 hw_fn_id = mlx5_sf_sw_to_hw_id(dev, controller, id); 169 167 mlx5_cmd_dealloc_sf(dev, hw_fn_id); 170 - mlx5_sf_hw_table_id_free(table, controller, id); 168 + mlx5_sf_hw_table_id_free(dev, table, controller, id); 171 169 mutex_unlock(&table->table_lock); 172 170 } 173 171 ··· 218 216 } 219 217 } 220 218 221 - static void mlx5_sf_hw_table_dealloc_all(struct mlx5_sf_hw_table *table) 219 + static void mlx5_sf_hw_table_dealloc_all(struct mlx5_core_dev *dev, 220 + struct mlx5_sf_hw_table *table) 222 221 { 223 - mlx5_sf_hw_table_hwc_dealloc_all(table->dev, &table->hwc[MLX5_SF_HWC_EXTERNAL]); 224 - mlx5_sf_hw_table_hwc_dealloc_all(table->dev, &table->hwc[MLX5_SF_HWC_LOCAL]); 222 + mlx5_sf_hw_table_hwc_dealloc_all(dev, 223 + &table->hwc[MLX5_SF_HWC_EXTERNAL]); 224 + mlx5_sf_hw_table_hwc_dealloc_all(dev, &table->hwc[MLX5_SF_HWC_LOCAL]); 225 225 } 226 226 227 227 static int mlx5_sf_hw_table_hwc_init(struct mlx5_sf_hwc_table *hwc, u16 max_fn, u16 base_id) ··· 305 301 } 306 302 307 303 mutex_init(&table->table_lock); 308 - table->dev = dev; 309 304 dev->priv.sf_hw_table = table; 310 305 311 306 base_id = mlx5_sf_start_function_id(dev); ··· 341 338 mlx5_sf_hw_table_hwc_cleanup(&table->hwc[MLX5_SF_HWC_LOCAL]); 342 339 mutex_destroy(&table->table_lock); 343 340 kfree(table); 341 + dev->priv.sf_hw_table = NULL; 344 342 res_unregister: 345 343 mlx5_sf_hw_table_res_unregister(dev); 346 344 } 347 345 348 346 static int mlx5_sf_hw_vhca_event(struct notifier_block *nb, unsigned long opcode, void *data) 349 347 { 350 - struct mlx5_sf_hw_table *table = container_of(nb, struct mlx5_sf_hw_table, vhca_nb); 348 + struct mlx5_core_dev *dev = container_of(nb, struct mlx5_core_dev, 349 + priv.sf_hw_table_vhca_nb); 350 + struct mlx5_sf_hw_table *table = dev->priv.sf_hw_table; 351 351 const struct mlx5_vhca_state_event *event = data; 352 352 struct mlx5_sf_hwc_table *hwc; 353 353 struct mlx5_sf_hw *sf_hw; 354 354 u16 sw_id; 355 355 356 - if (event->new_vhca_state != MLX5_VHCA_STATE_ALLOCATED) 356 + if (!table || event->new_vhca_state != MLX5_VHCA_STATE_ALLOCATED) 357 357 return 0; 358 358 359 359 hwc = mlx5_sf_table_fn_to_hwc(table, event->function_id); ··· 371 365 * Hence recycle the sf hardware id for reuse. 372 366 */ 373 367 if (sf_hw->allocated && sf_hw->pending_delete) 374 - mlx5_sf_hw_table_hwc_sf_free(table->dev, hwc, sw_id); 368 + mlx5_sf_hw_table_hwc_sf_free(dev, hwc, sw_id); 375 369 mutex_unlock(&table->table_lock); 376 370 return 0; 377 371 } 378 372 379 - int mlx5_sf_hw_table_create(struct mlx5_core_dev *dev) 373 + int mlx5_sf_hw_notifier_init(struct mlx5_core_dev *dev) 380 374 { 381 - struct mlx5_sf_hw_table *table = dev->priv.sf_hw_table; 382 - 383 - if (!table) 375 + if (mlx5_core_is_sf(dev)) 384 376 return 0; 385 377 386 - table->vhca_nb.notifier_call = mlx5_sf_hw_vhca_event; 387 - return mlx5_vhca_event_notifier_register(dev, &table->vhca_nb); 378 + dev->priv.sf_hw_table_vhca_nb.notifier_call = mlx5_sf_hw_vhca_event; 379 + return mlx5_vhca_event_notifier_register(dev, 380 + &dev->priv.sf_hw_table_vhca_nb); 381 + } 382 + 383 + void mlx5_sf_hw_notifier_cleanup(struct mlx5_core_dev *dev) 384 + { 385 + if (mlx5_core_is_sf(dev)) 386 + return; 387 + 388 + mlx5_vhca_event_notifier_unregister(dev, 389 + &dev->priv.sf_hw_table_vhca_nb); 388 390 } 389 391 390 392 void mlx5_sf_hw_table_destroy(struct mlx5_core_dev *dev) ··· 402 388 if (!table) 403 389 return; 404 390 405 - mlx5_vhca_event_notifier_unregister(dev, &table->vhca_nb); 406 391 /* Dealloc SFs whose firmware event has been missed. */ 407 - mlx5_sf_hw_table_dealloc_all(table); 392 + mlx5_sf_hw_table_dealloc_all(dev, table); 408 393 } 409 394 410 395 bool mlx5_sf_hw_table_supported(const struct mlx5_core_dev *dev)
+18 -2
drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h
··· 12 12 int mlx5_sf_hw_table_init(struct mlx5_core_dev *dev); 13 13 void mlx5_sf_hw_table_cleanup(struct mlx5_core_dev *dev); 14 14 15 - int mlx5_sf_hw_table_create(struct mlx5_core_dev *dev); 15 + int mlx5_sf_hw_notifier_init(struct mlx5_core_dev *dev); 16 + void mlx5_sf_hw_notifier_cleanup(struct mlx5_core_dev *dev); 16 17 void mlx5_sf_hw_table_destroy(struct mlx5_core_dev *dev); 17 18 19 + int mlx5_sf_notifiers_init(struct mlx5_core_dev *dev); 18 20 int mlx5_sf_table_init(struct mlx5_core_dev *dev); 21 + void mlx5_sf_notifiers_cleanup(struct mlx5_core_dev *dev); 19 22 void mlx5_sf_table_cleanup(struct mlx5_core_dev *dev); 20 23 bool mlx5_sf_table_empty(const struct mlx5_core_dev *dev); 21 24 ··· 47 44 { 48 45 } 49 46 50 - static inline int mlx5_sf_hw_table_create(struct mlx5_core_dev *dev) 47 + static inline int mlx5_sf_hw_notifier_init(struct mlx5_core_dev *dev) 51 48 { 52 49 return 0; 50 + } 51 + 52 + static inline void mlx5_sf_hw_notifier_cleanup(struct mlx5_core_dev *dev) 53 + { 53 54 } 54 55 55 56 static inline void mlx5_sf_hw_table_destroy(struct mlx5_core_dev *dev) 56 57 { 57 58 } 58 59 60 + static inline int mlx5_sf_notifiers_init(struct mlx5_core_dev *dev) 61 + { 62 + return 0; 63 + } 64 + 59 65 static inline int mlx5_sf_table_init(struct mlx5_core_dev *dev) 60 66 { 61 67 return 0; 68 + } 69 + 70 + static inline void mlx5_sf_notifiers_cleanup(struct mlx5_core_dev *dev) 71 + { 62 72 } 63 73 64 74 static inline void mlx5_sf_table_cleanup(struct mlx5_core_dev *dev)
+25 -44
drivers/net/ethernet/mellanox/mlx5/core/sf/vhca_event.c
··· 9 9 #define CREATE_TRACE_POINTS 10 10 #include "diag/vhca_tracepoint.h" 11 11 12 - struct mlx5_vhca_state_notifier { 13 - struct mlx5_core_dev *dev; 14 - struct mlx5_nb nb; 15 - struct blocking_notifier_head n_head; 16 - }; 17 - 18 12 struct mlx5_vhca_event_work { 19 13 struct work_struct work; 20 - struct mlx5_vhca_state_notifier *notifier; 14 + struct mlx5_core_dev *dev; 21 15 struct mlx5_vhca_state_event event; 22 16 }; 23 17 ··· 89 95 mlx5_vhca_event_arm(dev, event->function_id); 90 96 trace_mlx5_sf_vhca_event(dev, event); 91 97 92 - blocking_notifier_call_chain(&dev->priv.vhca_state_notifier->n_head, 0, event); 98 + blocking_notifier_call_chain(&dev->priv.vhca_state_n_head, 0, event); 93 99 } 94 100 95 101 static void mlx5_vhca_state_work_handler(struct work_struct *_work) 96 102 { 97 103 struct mlx5_vhca_event_work *work = container_of(_work, struct mlx5_vhca_event_work, work); 98 - struct mlx5_vhca_state_notifier *notifier = work->notifier; 99 - struct mlx5_core_dev *dev = notifier->dev; 100 104 101 - mlx5_vhca_event_notify(dev, &work->event); 105 + mlx5_vhca_event_notify(work->dev, &work->event); 102 106 kfree(work); 103 107 } 104 108 ··· 108 116 static int 109 117 mlx5_vhca_state_change_notifier(struct notifier_block *nb, unsigned long type, void *data) 110 118 { 111 - struct mlx5_vhca_state_notifier *notifier = 112 - mlx5_nb_cof(nb, struct mlx5_vhca_state_notifier, nb); 119 + struct mlx5_core_dev *dev = mlx5_nb_cof(nb, struct mlx5_core_dev, 120 + priv.vhca_state_nb); 113 121 struct mlx5_vhca_event_work *work; 114 122 struct mlx5_eqe *eqe = data; 115 123 int wq_idx; ··· 118 126 if (!work) 119 127 return NOTIFY_DONE; 120 128 INIT_WORK(&work->work, &mlx5_vhca_state_work_handler); 121 - work->notifier = notifier; 129 + work->dev = dev; 122 130 work->event.function_id = be16_to_cpu(eqe->data.vhca_state.function_id); 123 131 wq_idx = work->event.function_id % MLX5_DEV_MAX_WQS; 124 - mlx5_vhca_events_work_enqueue(notifier->dev, wq_idx, &work->work); 132 + mlx5_vhca_events_work_enqueue(dev, wq_idx, &work->work); 125 133 return NOTIFY_OK; 126 134 } 127 135 ··· 137 145 MLX5_SET(cmd_hca_cap, set_hca_cap, event_on_vhca_state_teardown_request, 1); 138 146 } 139 147 148 + void mlx5_vhca_state_notifier_init(struct mlx5_core_dev *dev) 149 + { 150 + BLOCKING_INIT_NOTIFIER_HEAD(&dev->priv.vhca_state_n_head); 151 + MLX5_NB_INIT(&dev->priv.vhca_state_nb, mlx5_vhca_state_change_notifier, 152 + VHCA_STATE_CHANGE); 153 + } 154 + 140 155 int mlx5_vhca_event_init(struct mlx5_core_dev *dev) 141 156 { 142 - struct mlx5_vhca_state_notifier *notifier; 143 157 char wq_name[MLX5_CMD_WQ_MAX_NAME]; 144 158 struct mlx5_vhca_events *events; 145 159 int err, i; ··· 158 160 return -ENOMEM; 159 161 160 162 events->dev = dev; 161 - dev->priv.vhca_events = events; 162 163 for (i = 0; i < MLX5_DEV_MAX_WQS; i++) { 163 164 snprintf(wq_name, MLX5_CMD_WQ_MAX_NAME, "mlx5_vhca_event%d", i); 164 165 events->handler[i].wq = create_singlethread_workqueue(wq_name); ··· 166 169 goto err_create_wq; 167 170 } 168 171 } 172 + dev->priv.vhca_events = events; 169 173 170 - notifier = kzalloc(sizeof(*notifier), GFP_KERNEL); 171 - if (!notifier) { 172 - err = -ENOMEM; 173 - goto err_notifier; 174 - } 175 - 176 - dev->priv.vhca_state_notifier = notifier; 177 - notifier->dev = dev; 178 - BLOCKING_INIT_NOTIFIER_HEAD(&notifier->n_head); 179 - MLX5_NB_INIT(&notifier->nb, mlx5_vhca_state_change_notifier, VHCA_STATE_CHANGE); 180 174 return 0; 181 175 182 - err_notifier: 183 176 err_create_wq: 184 177 for (--i; i >= 0; i--) 185 178 destroy_workqueue(events->handler[i].wq); ··· 198 211 if (!mlx5_vhca_event_supported(dev)) 199 212 return; 200 213 201 - kfree(dev->priv.vhca_state_notifier); 202 - dev->priv.vhca_state_notifier = NULL; 203 214 vhca_events = dev->priv.vhca_events; 204 215 for (i = 0; i < MLX5_DEV_MAX_WQS; i++) 205 216 destroy_workqueue(vhca_events->handler[i].wq); ··· 206 221 207 222 void mlx5_vhca_event_start(struct mlx5_core_dev *dev) 208 223 { 209 - struct mlx5_vhca_state_notifier *notifier; 210 - 211 - if (!dev->priv.vhca_state_notifier) 224 + if (!mlx5_vhca_event_supported(dev)) 212 225 return; 213 226 214 - notifier = dev->priv.vhca_state_notifier; 215 - mlx5_eq_notifier_register(dev, &notifier->nb); 227 + mlx5_eq_notifier_register(dev, &dev->priv.vhca_state_nb); 216 228 } 217 229 218 230 void mlx5_vhca_event_stop(struct mlx5_core_dev *dev) 219 231 { 220 - struct mlx5_vhca_state_notifier *notifier; 221 - 222 - if (!dev->priv.vhca_state_notifier) 232 + if (!mlx5_vhca_event_supported(dev)) 223 233 return; 224 234 225 - notifier = dev->priv.vhca_state_notifier; 226 - mlx5_eq_notifier_unregister(dev, &notifier->nb); 235 + mlx5_eq_notifier_unregister(dev, &dev->priv.vhca_state_nb); 236 + 237 + /* Flush workqueues of all pending events. */ 238 + mlx5_vhca_event_work_queues_flush(dev); 227 239 } 228 240 229 241 int mlx5_vhca_event_notifier_register(struct mlx5_core_dev *dev, struct notifier_block *nb) 230 242 { 231 - if (!dev->priv.vhca_state_notifier) 232 - return -EOPNOTSUPP; 233 - return blocking_notifier_chain_register(&dev->priv.vhca_state_notifier->n_head, nb); 243 + return blocking_notifier_chain_register(&dev->priv.vhca_state_n_head, 244 + nb); 234 245 } 235 246 236 247 void mlx5_vhca_event_notifier_unregister(struct mlx5_core_dev *dev, struct notifier_block *nb) 237 248 { 238 - blocking_notifier_chain_unregister(&dev->priv.vhca_state_notifier->n_head, nb); 249 + blocking_notifier_chain_unregister(&dev->priv.vhca_state_n_head, nb); 239 250 }
+5
drivers/net/ethernet/mellanox/mlx5/core/sf/vhca_event.h
··· 18 18 } 19 19 20 20 void mlx5_vhca_state_cap_handle(struct mlx5_core_dev *dev, void *set_hca_cap); 21 + void mlx5_vhca_state_notifier_init(struct mlx5_core_dev *dev); 21 22 int mlx5_vhca_event_init(struct mlx5_core_dev *dev); 22 23 void mlx5_vhca_event_cleanup(struct mlx5_core_dev *dev); 23 24 void mlx5_vhca_event_start(struct mlx5_core_dev *dev); ··· 35 34 #else 36 35 37 36 static inline void mlx5_vhca_state_cap_handle(struct mlx5_core_dev *dev, void *set_hca_cap) 37 + { 38 + } 39 + 40 + static inline void mlx5_vhca_state_notifier_init(struct mlx5_core_dev *dev) 38 41 { 39 42 } 40 43
+8 -2
include/linux/mlx5/driver.h
··· 488 488 struct mlx5_fw_reset; 489 489 struct mlx5_eq_table; 490 490 struct mlx5_irq_table; 491 - struct mlx5_vhca_state_notifier; 492 491 struct mlx5_sf_dev_table; 493 492 struct mlx5_sf_hw_table; 494 493 struct mlx5_sf_table; ··· 598 599 599 600 struct mlx5_flow_steering *steering; 600 601 struct mlx5_mpfs *mpfs; 602 + struct blocking_notifier_head esw_n_head; 601 603 struct mlx5_eswitch *eswitch; 602 604 struct mlx5_core_sriov sriov; 603 605 struct mlx5_lag *lag; ··· 614 614 struct mlx5_bfreg_data bfregs; 615 615 struct mlx5_sq_bfreg bfreg; 616 616 #ifdef CONFIG_MLX5_SF 617 - struct mlx5_vhca_state_notifier *vhca_state_notifier; 617 + struct mlx5_nb vhca_state_nb; 618 + struct blocking_notifier_head vhca_state_n_head; 619 + struct notifier_block sf_dev_nb; 618 620 struct mlx5_sf_dev_table *sf_dev_table; 619 621 struct mlx5_core_dev *parent_mdev; 620 622 #endif 621 623 #ifdef CONFIG_MLX5_SF_MANAGER 624 + struct notifier_block sf_hw_table_vhca_nb; 622 625 struct mlx5_sf_hw_table *sf_hw_table; 626 + struct notifier_block sf_table_esw_nb; 627 + struct notifier_block sf_table_vhca_nb; 628 + struct notifier_block sf_table_mdev_nb; 623 629 struct mlx5_sf_table *sf_table; 624 630 #endif 625 631 struct blocking_notifier_head lag_nh;