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

netdevsim: convert driver to use unlocked devlink API during init/fini

Prepare for devlink reload being called with devlink->lock held and
convert the netdevsim driver to use unlocked devlink API during init and
fini flows. Take devl_lock() in reload_down() and reload_up() ops in the
meantime before reload cmd is converted to take the lock itself.

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Jiri Pirko and committed by
Jakub Kicinski
012ec02a eb0e9fa2

+102 -123
-19
drivers/net/netdevsim/bus.c
··· 72 72 if (ret) 73 73 return ret; 74 74 75 - if (!mutex_trylock(&nsim_bus_dev->nsim_bus_reload_lock)) 76 - return -EBUSY; 77 - 78 - if (nsim_bus_dev->in_reload) { 79 - mutex_unlock(&nsim_bus_dev->nsim_bus_reload_lock); 80 - return -EBUSY; 81 - } 82 - 83 75 ret = nsim_drv_port_add(nsim_bus_dev, NSIM_DEV_PORT_TYPE_PF, port_index); 84 - mutex_unlock(&nsim_bus_dev->nsim_bus_reload_lock); 85 76 return ret ? ret : count; 86 77 } 87 78 ··· 93 102 if (ret) 94 103 return ret; 95 104 96 - if (!mutex_trylock(&nsim_bus_dev->nsim_bus_reload_lock)) 97 - return -EBUSY; 98 - 99 - if (nsim_bus_dev->in_reload) { 100 - mutex_unlock(&nsim_bus_dev->nsim_bus_reload_lock); 101 - return -EBUSY; 102 - } 103 - 104 105 ret = nsim_drv_port_del(nsim_bus_dev, NSIM_DEV_PORT_TYPE_PF, port_index); 105 - mutex_unlock(&nsim_bus_dev->nsim_bus_reload_lock); 106 106 return ret ? ret : count; 107 107 } 108 108 ··· 280 298 nsim_bus_dev->num_queues = num_queues; 281 299 nsim_bus_dev->initial_net = current->nsproxy->net_ns; 282 300 nsim_bus_dev->max_vfs = NSIM_BUS_DEV_MAX_VFS; 283 - mutex_init(&nsim_bus_dev->nsim_bus_reload_lock); 284 301 /* Disallow using nsim_bus_dev */ 285 302 smp_store_release(&nsim_bus_dev->init, false); 286 303
+64 -70
drivers/net/netdevsim/dev.c
··· 436 436 int err; 437 437 438 438 /* Resources for IPv4 */ 439 - err = devlink_resource_register(devlink, "IPv4", (u64)-1, 440 - NSIM_RESOURCE_IPV4, 441 - DEVLINK_RESOURCE_ID_PARENT_TOP, 442 - &params); 439 + err = devl_resource_register(devlink, "IPv4", (u64)-1, 440 + NSIM_RESOURCE_IPV4, 441 + DEVLINK_RESOURCE_ID_PARENT_TOP, 442 + &params); 443 443 if (err) { 444 444 pr_err("Failed to register IPv4 top resource\n"); 445 445 goto out; 446 446 } 447 447 448 - err = devlink_resource_register(devlink, "fib", (u64)-1, 449 - NSIM_RESOURCE_IPV4_FIB, 450 - NSIM_RESOURCE_IPV4, &params); 448 + err = devl_resource_register(devlink, "fib", (u64)-1, 449 + NSIM_RESOURCE_IPV4_FIB, 450 + NSIM_RESOURCE_IPV4, &params); 451 451 if (err) { 452 452 pr_err("Failed to register IPv4 FIB resource\n"); 453 453 return err; 454 454 } 455 455 456 - err = devlink_resource_register(devlink, "fib-rules", (u64)-1, 457 - NSIM_RESOURCE_IPV4_FIB_RULES, 458 - NSIM_RESOURCE_IPV4, &params); 456 + err = devl_resource_register(devlink, "fib-rules", (u64)-1, 457 + NSIM_RESOURCE_IPV4_FIB_RULES, 458 + NSIM_RESOURCE_IPV4, &params); 459 459 if (err) { 460 460 pr_err("Failed to register IPv4 FIB rules resource\n"); 461 461 return err; 462 462 } 463 463 464 464 /* Resources for IPv6 */ 465 - err = devlink_resource_register(devlink, "IPv6", (u64)-1, 466 - NSIM_RESOURCE_IPV6, 467 - DEVLINK_RESOURCE_ID_PARENT_TOP, 468 - &params); 465 + err = devl_resource_register(devlink, "IPv6", (u64)-1, 466 + NSIM_RESOURCE_IPV6, 467 + DEVLINK_RESOURCE_ID_PARENT_TOP, 468 + &params); 469 469 if (err) { 470 470 pr_err("Failed to register IPv6 top resource\n"); 471 471 goto out; 472 472 } 473 473 474 - err = devlink_resource_register(devlink, "fib", (u64)-1, 475 - NSIM_RESOURCE_IPV6_FIB, 476 - NSIM_RESOURCE_IPV6, &params); 474 + err = devl_resource_register(devlink, "fib", (u64)-1, 475 + NSIM_RESOURCE_IPV6_FIB, 476 + NSIM_RESOURCE_IPV6, &params); 477 477 if (err) { 478 478 pr_err("Failed to register IPv6 FIB resource\n"); 479 479 return err; 480 480 } 481 481 482 - err = devlink_resource_register(devlink, "fib-rules", (u64)-1, 483 - NSIM_RESOURCE_IPV6_FIB_RULES, 484 - NSIM_RESOURCE_IPV6, &params); 482 + err = devl_resource_register(devlink, "fib-rules", (u64)-1, 483 + NSIM_RESOURCE_IPV6_FIB_RULES, 484 + NSIM_RESOURCE_IPV6, &params); 485 485 if (err) { 486 486 pr_err("Failed to register IPv6 FIB rules resource\n"); 487 487 return err; 488 488 } 489 489 490 490 /* Resources for nexthops */ 491 - err = devlink_resource_register(devlink, "nexthops", (u64)-1, 492 - NSIM_RESOURCE_NEXTHOPS, 493 - DEVLINK_RESOURCE_ID_PARENT_TOP, 494 - &params); 491 + err = devl_resource_register(devlink, "nexthops", (u64)-1, 492 + NSIM_RESOURCE_NEXTHOPS, 493 + DEVLINK_RESOURCE_ID_PARENT_TOP, 494 + &params); 495 495 496 496 out: 497 497 return err; ··· 557 557 struct devlink *devlink) 558 558 { 559 559 nsim_dev->dummy_region = 560 - devlink_region_create(devlink, &dummy_region_ops, 561 - NSIM_DEV_DUMMY_REGION_SNAPSHOT_MAX, 562 - NSIM_DEV_DUMMY_REGION_SIZE); 560 + devl_region_create(devlink, &dummy_region_ops, 561 + NSIM_DEV_DUMMY_REGION_SNAPSHOT_MAX, 562 + NSIM_DEV_DUMMY_REGION_SIZE); 563 563 return PTR_ERR_OR_ZERO(nsim_dev->dummy_region); 564 564 } 565 565 566 566 static void nsim_dev_dummy_region_exit(struct nsim_dev *nsim_dev) 567 567 { 568 - devlink_region_destroy(nsim_dev->dummy_region); 568 + devl_region_destroy(nsim_dev->dummy_region); 569 569 } 570 570 571 571 static int ··· 832 832 /* For each running port and enabled packet trap, generate a UDP 833 833 * packet with a random 5-tuple and report it. 834 834 */ 835 - devl_lock(priv_to_devlink(nsim_dev)); 835 + if (!devl_trylock(priv_to_devlink(nsim_dev))) { 836 + schedule_delayed_work(&nsim_dev->trap_data->trap_report_dw, 0); 837 + return; 838 + } 839 + 836 840 list_for_each_entry(nsim_dev_port, &nsim_dev->port_list, list) { 837 841 if (!netif_running(nsim_dev_port->ns->netdev)) 838 842 continue; ··· 884 880 nsim_trap_data->nsim_dev = nsim_dev; 885 881 nsim_dev->trap_data = nsim_trap_data; 886 882 887 - err = devlink_trap_policers_register(devlink, nsim_trap_policers_arr, 888 - policers_count); 883 + err = devl_trap_policers_register(devlink, nsim_trap_policers_arr, 884 + policers_count); 889 885 if (err) 890 886 goto err_trap_policers_cnt_free; 891 887 892 - err = devlink_trap_groups_register(devlink, nsim_trap_groups_arr, 893 - ARRAY_SIZE(nsim_trap_groups_arr)); 888 + err = devl_trap_groups_register(devlink, nsim_trap_groups_arr, 889 + ARRAY_SIZE(nsim_trap_groups_arr)); 894 890 if (err) 895 891 goto err_trap_policers_unregister; 896 892 897 - err = devlink_traps_register(devlink, nsim_traps_arr, 898 - ARRAY_SIZE(nsim_traps_arr), NULL); 893 + err = devl_traps_register(devlink, nsim_traps_arr, 894 + ARRAY_SIZE(nsim_traps_arr), NULL); 899 895 if (err) 900 896 goto err_trap_groups_unregister; 901 897 ··· 907 903 return 0; 908 904 909 905 err_trap_groups_unregister: 910 - devlink_trap_groups_unregister(devlink, nsim_trap_groups_arr, 911 - ARRAY_SIZE(nsim_trap_groups_arr)); 906 + devl_trap_groups_unregister(devlink, nsim_trap_groups_arr, 907 + ARRAY_SIZE(nsim_trap_groups_arr)); 912 908 err_trap_policers_unregister: 913 - devlink_trap_policers_unregister(devlink, nsim_trap_policers_arr, 914 - ARRAY_SIZE(nsim_trap_policers_arr)); 909 + devl_trap_policers_unregister(devlink, nsim_trap_policers_arr, 910 + ARRAY_SIZE(nsim_trap_policers_arr)); 915 911 err_trap_policers_cnt_free: 916 912 kfree(nsim_trap_data->trap_policers_cnt_arr); 917 913 err_trap_items_free: ··· 927 923 928 924 /* caution, trap work takes devlink lock */ 929 925 cancel_delayed_work_sync(&nsim_dev->trap_data->trap_report_dw); 930 - devlink_traps_unregister(devlink, nsim_traps_arr, 931 - ARRAY_SIZE(nsim_traps_arr)); 932 - devlink_trap_groups_unregister(devlink, nsim_trap_groups_arr, 933 - ARRAY_SIZE(nsim_trap_groups_arr)); 934 - devlink_trap_policers_unregister(devlink, nsim_trap_policers_arr, 935 - ARRAY_SIZE(nsim_trap_policers_arr)); 926 + devl_traps_unregister(devlink, nsim_traps_arr, 927 + ARRAY_SIZE(nsim_traps_arr)); 928 + devl_trap_groups_unregister(devlink, nsim_trap_groups_arr, 929 + ARRAY_SIZE(nsim_trap_groups_arr)); 930 + devl_trap_policers_unregister(devlink, nsim_trap_policers_arr, 931 + ARRAY_SIZE(nsim_trap_policers_arr)); 936 932 kfree(nsim_dev->trap_data->trap_policers_cnt_arr); 937 933 kfree(nsim_dev->trap_data->trap_items_arr); 938 934 kfree(nsim_dev->trap_data); ··· 947 943 struct netlink_ext_ack *extack) 948 944 { 949 945 struct nsim_dev *nsim_dev = devlink_priv(devlink); 950 - struct nsim_bus_dev *nsim_bus_dev; 951 946 952 - nsim_bus_dev = nsim_dev->nsim_bus_dev; 953 - if (!mutex_trylock(&nsim_bus_dev->nsim_bus_reload_lock)) 954 - return -EOPNOTSUPP; 955 - 947 + devl_lock(devlink); 956 948 if (nsim_dev->dont_allow_reload) { 957 949 /* For testing purposes, user set debugfs dont_allow_reload 958 950 * value to true. So forbid it. 959 951 */ 960 952 NL_SET_ERR_MSG_MOD(extack, "User forbid the reload for testing purposes"); 961 - mutex_unlock(&nsim_bus_dev->nsim_bus_reload_lock); 953 + devl_unlock(devlink); 962 954 return -EOPNOTSUPP; 963 955 } 964 - nsim_bus_dev->in_reload = true; 965 956 966 957 nsim_dev_reload_destroy(nsim_dev); 967 - mutex_unlock(&nsim_bus_dev->nsim_bus_reload_lock); 958 + devl_unlock(devlink); 968 959 return 0; 969 960 } 970 961 ··· 968 969 struct netlink_ext_ack *extack) 969 970 { 970 971 struct nsim_dev *nsim_dev = devlink_priv(devlink); 971 - struct nsim_bus_dev *nsim_bus_dev; 972 972 int ret; 973 973 974 - nsim_bus_dev = nsim_dev->nsim_bus_dev; 975 - mutex_lock(&nsim_bus_dev->nsim_bus_reload_lock); 976 - nsim_bus_dev->in_reload = false; 977 - 974 + devl_lock(devlink); 978 975 if (nsim_dev->fail_reload) { 979 976 /* For testing purposes, user set debugfs fail_reload 980 977 * value to true. Fail right away. 981 978 */ 982 979 NL_SET_ERR_MSG_MOD(extack, "User setup the reload to fail for testing purposes"); 983 - mutex_unlock(&nsim_bus_dev->nsim_bus_reload_lock); 980 + devl_unlock(devlink); 984 981 return -EINVAL; 985 982 } 986 983 987 984 *actions_performed = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT); 988 985 ret = nsim_dev_reload_create(nsim_dev, extack); 989 - mutex_unlock(&nsim_bus_dev->nsim_bus_reload_lock); 986 + devl_unlock(devlink); 990 987 return ret; 991 988 } 992 989 ··· 1429 1434 { 1430 1435 struct nsim_dev_port *nsim_dev_port, *tmp; 1431 1436 1432 - devl_lock(priv_to_devlink(nsim_dev)); 1433 1437 list_for_each_entry_safe(nsim_dev_port, tmp, 1434 1438 &nsim_dev->port_list, list) 1435 1439 __nsim_dev_port_del(nsim_dev_port); 1436 - devl_unlock(priv_to_devlink(nsim_dev)); 1437 1440 } 1438 1441 1439 1442 static int nsim_dev_port_add_all(struct nsim_dev *nsim_dev, ··· 1440 1447 int i, err; 1441 1448 1442 1449 for (i = 0; i < port_count; i++) { 1443 - devl_lock(priv_to_devlink(nsim_dev)); 1444 1450 err = __nsim_dev_port_add(nsim_dev, NSIM_DEV_PORT_TYPE_PF, i); 1445 - devl_unlock(priv_to_devlink(nsim_dev)); 1446 1451 if (err) 1447 1452 goto err_port_del_all; 1448 1453 } ··· 1528 1537 nsim_bus_dev->initial_net, &nsim_bus_dev->dev); 1529 1538 if (!devlink) 1530 1539 return -ENOMEM; 1540 + devl_lock(devlink); 1531 1541 nsim_dev = devlink_priv(devlink); 1532 1542 nsim_dev->nsim_bus_dev = nsim_bus_dev; 1533 1543 nsim_dev->switch_id.id_len = sizeof(nsim_dev->switch_id.id); ··· 1547 1555 GFP_KERNEL | __GFP_NOWARN); 1548 1556 if (!nsim_dev->vfconfigs) { 1549 1557 err = -ENOMEM; 1550 - goto err_devlink_free; 1558 + goto err_devlink_unlock; 1551 1559 } 1552 1560 1553 1561 err = nsim_dev_resources_register(devlink); ··· 1600 1608 1601 1609 nsim_dev->esw_mode = DEVLINK_ESWITCH_MODE_LEGACY; 1602 1610 devlink_set_features(devlink, DEVLINK_F_RELOAD); 1611 + devl_unlock(devlink); 1603 1612 devlink_register(devlink); 1604 1613 return 0; 1605 1614 ··· 1624 1631 devlink_params_unregister(devlink, nsim_devlink_params, 1625 1632 ARRAY_SIZE(nsim_devlink_params)); 1626 1633 err_dl_unregister: 1627 - devlink_resources_unregister(devlink); 1634 + devl_resources_unregister(devlink); 1628 1635 err_vfc_free: 1629 1636 kfree(nsim_dev->vfconfigs); 1630 - err_devlink_free: 1637 + err_devlink_unlock: 1638 + devl_unlock(devlink); 1631 1639 devlink_free(devlink); 1632 1640 dev_set_drvdata(&nsim_bus_dev->dev, NULL); 1633 1641 return err; ··· 1642 1648 return; 1643 1649 debugfs_remove(nsim_dev->take_snapshot); 1644 1650 1645 - devl_lock(devlink); 1646 1651 if (nsim_dev_get_vfs(nsim_dev)) { 1647 1652 nsim_bus_dev_set_vfs(nsim_dev->nsim_bus_dev, 0); 1648 1653 if (nsim_esw_mode_is_switchdev(nsim_dev)) 1649 1654 nsim_esw_legacy_enable(nsim_dev, NULL); 1650 1655 } 1651 - devl_unlock(devlink); 1652 1656 1653 1657 nsim_dev_port_del_all(nsim_dev); 1654 1658 nsim_dev_hwstats_exit(nsim_dev); ··· 1663 1671 struct devlink *devlink = priv_to_devlink(nsim_dev); 1664 1672 1665 1673 devlink_unregister(devlink); 1674 + devl_lock(devlink); 1666 1675 nsim_dev_reload_destroy(nsim_dev); 1667 1676 1668 1677 nsim_bpf_dev_exit(nsim_dev); 1669 1678 nsim_dev_debugfs_exit(nsim_dev); 1670 1679 devlink_params_unregister(devlink, nsim_devlink_params, 1671 1680 ARRAY_SIZE(nsim_devlink_params)); 1672 - devlink_resources_unregister(devlink); 1681 + devl_resources_unregister(devlink); 1673 1682 kfree(nsim_dev->vfconfigs); 1683 + devl_unlock(devlink); 1674 1684 devlink_free(devlink); 1675 1685 dev_set_drvdata(&nsim_bus_dev->dev, NULL); 1676 1686 }
+31 -31
drivers/net/netdevsim/fib.c
··· 1453 1453 int err; 1454 1454 u64 val; 1455 1455 1456 - err = devlink_resource_size_get(devlink, res_ids[i], &val); 1456 + err = devl_resource_size_get(devlink, res_ids[i], &val); 1457 1457 if (err) 1458 1458 val = (u64) -1; 1459 1459 nsim_fib_set_max(data, res_ids[i], val); ··· 1562 1562 goto err_nexthop_nb_unregister; 1563 1563 } 1564 1564 1565 - devlink_resource_occ_get_register(devlink, 1566 - NSIM_RESOURCE_IPV4_FIB, 1567 - nsim_fib_ipv4_resource_occ_get, 1568 - data); 1569 - devlink_resource_occ_get_register(devlink, 1570 - NSIM_RESOURCE_IPV4_FIB_RULES, 1571 - nsim_fib_ipv4_rules_res_occ_get, 1572 - data); 1573 - devlink_resource_occ_get_register(devlink, 1574 - NSIM_RESOURCE_IPV6_FIB, 1575 - nsim_fib_ipv6_resource_occ_get, 1576 - data); 1577 - devlink_resource_occ_get_register(devlink, 1578 - NSIM_RESOURCE_IPV6_FIB_RULES, 1579 - nsim_fib_ipv6_rules_res_occ_get, 1580 - data); 1581 - devlink_resource_occ_get_register(devlink, 1582 - NSIM_RESOURCE_NEXTHOPS, 1583 - nsim_fib_nexthops_res_occ_get, 1584 - data); 1565 + devl_resource_occ_get_register(devlink, 1566 + NSIM_RESOURCE_IPV4_FIB, 1567 + nsim_fib_ipv4_resource_occ_get, 1568 + data); 1569 + devl_resource_occ_get_register(devlink, 1570 + NSIM_RESOURCE_IPV4_FIB_RULES, 1571 + nsim_fib_ipv4_rules_res_occ_get, 1572 + data); 1573 + devl_resource_occ_get_register(devlink, 1574 + NSIM_RESOURCE_IPV6_FIB, 1575 + nsim_fib_ipv6_resource_occ_get, 1576 + data); 1577 + devl_resource_occ_get_register(devlink, 1578 + NSIM_RESOURCE_IPV6_FIB_RULES, 1579 + nsim_fib_ipv6_rules_res_occ_get, 1580 + data); 1581 + devl_resource_occ_get_register(devlink, 1582 + NSIM_RESOURCE_NEXTHOPS, 1583 + nsim_fib_nexthops_res_occ_get, 1584 + data); 1585 1585 return data; 1586 1586 1587 1587 err_nexthop_nb_unregister: ··· 1604 1604 1605 1605 void nsim_fib_destroy(struct devlink *devlink, struct nsim_fib_data *data) 1606 1606 { 1607 - devlink_resource_occ_get_unregister(devlink, 1608 - NSIM_RESOURCE_NEXTHOPS); 1609 - devlink_resource_occ_get_unregister(devlink, 1610 - NSIM_RESOURCE_IPV6_FIB_RULES); 1611 - devlink_resource_occ_get_unregister(devlink, 1612 - NSIM_RESOURCE_IPV6_FIB); 1613 - devlink_resource_occ_get_unregister(devlink, 1614 - NSIM_RESOURCE_IPV4_FIB_RULES); 1615 - devlink_resource_occ_get_unregister(devlink, 1616 - NSIM_RESOURCE_IPV4_FIB); 1607 + devl_resource_occ_get_unregister(devlink, 1608 + NSIM_RESOURCE_NEXTHOPS); 1609 + devl_resource_occ_get_unregister(devlink, 1610 + NSIM_RESOURCE_IPV6_FIB_RULES); 1611 + devl_resource_occ_get_unregister(devlink, 1612 + NSIM_RESOURCE_IPV6_FIB); 1613 + devl_resource_occ_get_unregister(devlink, 1614 + NSIM_RESOURCE_IPV4_FIB_RULES); 1615 + devl_resource_occ_get_unregister(devlink, 1616 + NSIM_RESOURCE_IPV4_FIB); 1617 1617 unregister_fib_notifier(devlink_net(devlink), &data->fib_nb); 1618 1618 unregister_nexthop_notifier(devlink_net(devlink), &data->nexthop_nb); 1619 1619 flush_work(&data->fib_event_work);
-3
drivers/net/netdevsim/netdevsim.h
··· 376 376 */ 377 377 unsigned int max_vfs; 378 378 unsigned int num_vfs; 379 - /* Lock for devlink->reload_enabled in netdevsim module */ 380 - struct mutex nsim_bus_reload_lock; 381 - bool in_reload; 382 379 bool init; 383 380 }; 384 381
+1
include/net/devlink.h
··· 1517 1517 1518 1518 /* Devlink instance explicit locking */ 1519 1519 void devl_lock(struct devlink *devlink); 1520 + int devl_trylock(struct devlink *devlink); 1520 1521 void devl_unlock(struct devlink *devlink); 1521 1522 void devl_assert_locked(struct devlink *devlink); 1522 1523 bool devl_lock_is_held(struct devlink *devlink);
+6
net/core/devlink.c
··· 266 266 } 267 267 EXPORT_SYMBOL_GPL(devl_lock); 268 268 269 + int devl_trylock(struct devlink *devlink) 270 + { 271 + return mutex_trylock(&devlink->lock); 272 + } 273 + EXPORT_SYMBOL_GPL(devl_trylock); 274 + 269 275 void devl_unlock(struct devlink *devlink) 270 276 { 271 277 mutex_unlock(&devlink->lock);