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

Merge branch 'implement-dev-info-and-dev-flash-for-line-cards'

Jiri Pirko says:

====================
Implement dev info and dev flash for line cards

This patchset implements two features:
1) "devlink dev info" is exposed for line card (patches 6-9)
2) "devlink dev flash" is implemented for line card gearbox
flashing (patch 10)

For every line card, "a nested" auxiliary device is created which
allows to bind the features mentioned above (patch 4).

The relationship between line card and its auxiliary dev devlink
is carried over extra line card netlink attribute (patches 3 and 5).

The first patch removes devlink_mutex from devlink_register/unregister()
which eliminates possible deadlock during devlink reload command. The
second patchset follows up with putting net pointer check into new
helper.

Examples:

$ devlink lc show pci/0000:01:00.0 lc 1
pci/0000:01:00.0:
lc 1 state active type 16x100G nested_devlink auxiliary/mlxsw_core.lc.0
supported_types:
16x100G

$ devlink dev show auxiliary/mlxsw_core.lc.0
auxiliary/mlxsw_core.lc.0

$ devlink dev info auxiliary/mlxsw_core.lc.0
auxiliary/mlxsw_core.lc.0:
versions:
fixed:
hw.revision 0
fw.psid MT_0000000749
running:
ini.version 4
fw 19.2010.1312

$ devlink dev flash auxiliary/mlxsw_core.lc.0 file mellanox/fw-AGB-rel-19_2010_1312-022-EVB.mfa2
====================

Link: https://lore.kernel.org/r/20220725082925.366455-1-jiri@resnulli.us
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+1043 -171
+24
Documentation/networking/devlink/mlxsw.rst
··· 58 58 - running 59 59 - Three digit firmware version 60 60 61 + Line card auxiliary device info versions 62 + ======================================== 63 + 64 + The ``mlxsw`` driver reports the following versions for line card auxiliary device 65 + 66 + .. list-table:: devlink info versions implemented 67 + :widths: 5 5 90 68 + 69 + * - Name 70 + - Type 71 + - Description 72 + * - ``hw.revision`` 73 + - fixed 74 + - The hardware revision for this line card 75 + * - ``ini.version`` 76 + - running 77 + - Version of line card INI loaded 78 + * - ``fw.psid`` 79 + - fixed 80 + - Line card device PSID 81 + * - ``fw.version`` 82 + - running 83 + - Three digit firmware version of line card device 84 + 61 85 Driver-specific Traps 62 86 ===================== 63 87
+1
drivers/net/ethernet/mellanox/mlxsw/Kconfig
··· 7 7 tristate "Mellanox Technologies Switch ASICs support" 8 8 select NET_DEVLINK 9 9 select MLXFW 10 + select AUXILIARY_BUS 10 11 help 11 12 This driver supports Mellanox Technologies Switch ASICs family. 12 13
+1 -1
drivers/net/ethernet/mellanox/mlxsw/Makefile
··· 2 2 obj-$(CONFIG_MLXSW_CORE) += mlxsw_core.o 3 3 mlxsw_core-objs := core.o core_acl_flex_keys.o \ 4 4 core_acl_flex_actions.o core_env.o \ 5 - core_linecards.o 5 + core_linecards.o core_linecard_dev.o 6 6 mlxsw_core-$(CONFIG_MLXSW_CORE_HWMON) += core_hwmon.o 7 7 mlxsw_core-$(CONFIG_MLXSW_CORE_THERMAL) += core_thermal.o 8 8 obj-$(CONFIG_MLXSW_PCI) += mlxsw_pci.o
+32 -12
drivers/net/ethernet/mellanox/mlxsw/core.c
··· 951 951 return mlxsw_driver; 952 952 } 953 953 954 + int mlxsw_core_fw_flash(struct mlxsw_core *mlxsw_core, 955 + struct mlxfw_dev *mlxfw_dev, 956 + const struct firmware *firmware, 957 + struct netlink_ext_ack *extack) 958 + { 959 + int err; 960 + 961 + mlxsw_core->fw_flash_in_progress = true; 962 + err = mlxfw_firmware_flash(mlxfw_dev, firmware, extack); 963 + mlxsw_core->fw_flash_in_progress = false; 964 + 965 + return err; 966 + } 967 + 954 968 struct mlxsw_core_fw_info { 955 969 struct mlxfw_dev mlxfw_dev; 956 970 struct mlxsw_core *mlxsw_core; ··· 1119 1105 .fsm_release = mlxsw_core_fw_fsm_release, 1120 1106 }; 1121 1107 1122 - static int mlxsw_core_fw_flash(struct mlxsw_core *mlxsw_core, const struct firmware *firmware, 1123 - struct netlink_ext_ack *extack) 1108 + static int mlxsw_core_dev_fw_flash(struct mlxsw_core *mlxsw_core, 1109 + const struct firmware *firmware, 1110 + struct netlink_ext_ack *extack) 1124 1111 { 1125 1112 struct mlxsw_core_fw_info mlxsw_core_fw_info = { 1126 1113 .mlxfw_dev = { ··· 1132 1117 }, 1133 1118 .mlxsw_core = mlxsw_core 1134 1119 }; 1135 - int err; 1136 1120 1137 - mlxsw_core->fw_flash_in_progress = true; 1138 - err = mlxfw_firmware_flash(&mlxsw_core_fw_info.mlxfw_dev, firmware, extack); 1139 - mlxsw_core->fw_flash_in_progress = false; 1140 - 1141 - return err; 1121 + return mlxsw_core_fw_flash(mlxsw_core, &mlxsw_core_fw_info.mlxfw_dev, 1122 + firmware, extack); 1142 1123 } 1143 1124 1144 1125 static int mlxsw_core_fw_rev_validate(struct mlxsw_core *mlxsw_core, ··· 1180 1169 return err; 1181 1170 } 1182 1171 1183 - err = mlxsw_core_fw_flash(mlxsw_core, firmware, NULL); 1172 + err = mlxsw_core_dev_fw_flash(mlxsw_core, firmware, NULL); 1184 1173 release_firmware(firmware); 1185 1174 if (err) 1186 1175 dev_err(mlxsw_bus_info->dev, "Could not upgrade firmware\n"); ··· 1198 1187 struct devlink_flash_update_params *params, 1199 1188 struct netlink_ext_ack *extack) 1200 1189 { 1201 - return mlxsw_core_fw_flash(mlxsw_core, params->fw, extack); 1190 + return mlxsw_core_dev_fw_flash(mlxsw_core, params->fw, extack); 1202 1191 } 1203 1192 1204 1193 static int mlxsw_core_devlink_param_fw_load_policy_validate(struct devlink *devlink, u32 id, ··· 3345 3334 { 3346 3335 int err; 3347 3336 3337 + err = mlxsw_linecard_driver_register(); 3338 + if (err) 3339 + return err; 3340 + 3348 3341 mlxsw_wq = alloc_workqueue(mlxsw_core_driver_name, 0, 0); 3349 - if (!mlxsw_wq) 3350 - return -ENOMEM; 3342 + if (!mlxsw_wq) { 3343 + err = -ENOMEM; 3344 + goto err_alloc_workqueue; 3345 + } 3351 3346 mlxsw_owq = alloc_ordered_workqueue("%s_ordered", 0, 3352 3347 mlxsw_core_driver_name); 3353 3348 if (!mlxsw_owq) { ··· 3364 3347 3365 3348 err_alloc_ordered_workqueue: 3366 3349 destroy_workqueue(mlxsw_wq); 3350 + err_alloc_workqueue: 3351 + mlxsw_linecard_driver_unregister(); 3367 3352 return err; 3368 3353 } 3369 3354 ··· 3373 3354 { 3374 3355 destroy_workqueue(mlxsw_owq); 3375 3356 destroy_workqueue(mlxsw_wq); 3357 + mlxsw_linecard_driver_unregister(); 3376 3358 } 3377 3359 3378 3360 module_init(mlxsw_core_module_init);
+35
drivers/net/ethernet/mellanox/mlxsw/core.h
··· 12 12 #include <linux/skbuff.h> 13 13 #include <linux/workqueue.h> 14 14 #include <linux/net_namespace.h> 15 + #include <linux/auxiliary_bus.h> 15 16 #include <net/devlink.h> 16 17 17 18 #include "trap.h" 18 19 #include "reg.h" 19 20 #include "cmd.h" 20 21 #include "resources.h" 22 + #include "../mlxfw/mlxfw.h" 21 23 22 24 enum mlxsw_core_resource_id { 23 25 MLXSW_CORE_RESOURCE_PORTS = 1, ··· 48 46 49 47 int mlxsw_core_driver_register(struct mlxsw_driver *mlxsw_driver); 50 48 void mlxsw_core_driver_unregister(struct mlxsw_driver *mlxsw_driver); 49 + 50 + int mlxsw_core_fw_flash(struct mlxsw_core *mlxsw_core, 51 + struct mlxfw_dev *mlxfw_dev, 52 + const struct firmware *firmware, 53 + struct netlink_ext_ack *extack); 51 54 52 55 int mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info, 53 56 const struct mlxsw_bus *mlxsw_bus, ··· 570 563 MLXSW_LINECARD_STATUS_EVENT_TYPE_UNPROVISION, 571 564 }; 572 565 566 + struct mlxsw_linecard_bdev; 567 + 568 + struct mlxsw_linecard_device_info { 569 + u16 fw_major; 570 + u16 fw_minor; 571 + u16 fw_sub_minor; 572 + char psid[MLXSW_REG_MGIR_FW_INFO_PSID_SIZE]; 573 + }; 574 + 573 575 struct mlxsw_linecard { 574 576 u8 slot_index; 575 577 struct mlxsw_linecards *linecards; ··· 593 577 active:1; 594 578 u16 hw_revision; 595 579 u16 ini_version; 580 + struct mlxsw_linecard_bdev *bdev; 581 + struct { 582 + struct mlxsw_linecard_device_info info; 583 + u8 index; 584 + } device; 596 585 }; 597 586 598 587 struct mlxsw_linecard_types_info; ··· 618 597 return &linecards->linecards[slot_index - 1]; 619 598 } 620 599 600 + int mlxsw_linecard_devlink_info_get(struct mlxsw_linecard *linecard, 601 + struct devlink_info_req *req, 602 + struct netlink_ext_ack *extack); 603 + int mlxsw_linecard_flash_update(struct devlink *linecard_devlink, 604 + struct mlxsw_linecard *linecard, 605 + const struct firmware *firmware, 606 + struct netlink_ext_ack *extack); 607 + 621 608 int mlxsw_linecards_init(struct mlxsw_core *mlxsw_core, 622 609 const struct mlxsw_bus_info *bus_info); 623 610 void mlxsw_linecards_fini(struct mlxsw_core *mlxsw_core); ··· 644 615 void mlxsw_linecards_event_ops_unregister(struct mlxsw_core *mlxsw_core, 645 616 struct mlxsw_linecards_event_ops *ops, 646 617 void *priv); 618 + 619 + int mlxsw_linecard_bdev_add(struct mlxsw_linecard *linecard); 620 + void mlxsw_linecard_bdev_del(struct mlxsw_linecard *linecard); 621 + 622 + int mlxsw_linecard_driver_register(void); 623 + void mlxsw_linecard_driver_unregister(void); 647 624 648 625 #endif
+184
drivers/net/ethernet/mellanox/mlxsw/core_linecard_dev.c
··· 1 + // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2 + /* Copyright (c) 2022 NVIDIA Corporation and Mellanox Technologies. All rights reserved */ 3 + 4 + #include <linux/kernel.h> 5 + #include <linux/module.h> 6 + #include <linux/err.h> 7 + #include <linux/types.h> 8 + #include <linux/err.h> 9 + #include <linux/auxiliary_bus.h> 10 + #include <linux/idr.h> 11 + #include <linux/gfp.h> 12 + #include <linux/slab.h> 13 + #include <net/devlink.h> 14 + #include "core.h" 15 + 16 + #define MLXSW_LINECARD_DEV_ID_NAME "lc" 17 + 18 + struct mlxsw_linecard_dev { 19 + struct mlxsw_linecard *linecard; 20 + }; 21 + 22 + struct mlxsw_linecard_bdev { 23 + struct auxiliary_device adev; 24 + struct mlxsw_linecard *linecard; 25 + struct mlxsw_linecard_dev *linecard_dev; 26 + }; 27 + 28 + static DEFINE_IDA(mlxsw_linecard_bdev_ida); 29 + 30 + static int mlxsw_linecard_bdev_id_alloc(void) 31 + { 32 + return ida_alloc(&mlxsw_linecard_bdev_ida, GFP_KERNEL); 33 + } 34 + 35 + static void mlxsw_linecard_bdev_id_free(int id) 36 + { 37 + ida_free(&mlxsw_linecard_bdev_ida, id); 38 + } 39 + 40 + static void mlxsw_linecard_bdev_release(struct device *device) 41 + { 42 + struct auxiliary_device *adev = 43 + container_of(device, struct auxiliary_device, dev); 44 + struct mlxsw_linecard_bdev *linecard_bdev = 45 + container_of(adev, struct mlxsw_linecard_bdev, adev); 46 + 47 + mlxsw_linecard_bdev_id_free(adev->id); 48 + kfree(linecard_bdev); 49 + } 50 + 51 + int mlxsw_linecard_bdev_add(struct mlxsw_linecard *linecard) 52 + { 53 + struct mlxsw_linecard_bdev *linecard_bdev; 54 + int err; 55 + int id; 56 + 57 + id = mlxsw_linecard_bdev_id_alloc(); 58 + if (id < 0) 59 + return id; 60 + 61 + linecard_bdev = kzalloc(sizeof(*linecard_bdev), GFP_KERNEL); 62 + if (!linecard_bdev) { 63 + mlxsw_linecard_bdev_id_free(id); 64 + return -ENOMEM; 65 + } 66 + linecard_bdev->adev.id = id; 67 + linecard_bdev->adev.name = MLXSW_LINECARD_DEV_ID_NAME; 68 + linecard_bdev->adev.dev.release = mlxsw_linecard_bdev_release; 69 + linecard_bdev->adev.dev.parent = linecard->linecards->bus_info->dev; 70 + linecard_bdev->linecard = linecard; 71 + 72 + err = auxiliary_device_init(&linecard_bdev->adev); 73 + if (err) { 74 + mlxsw_linecard_bdev_id_free(id); 75 + kfree(linecard_bdev); 76 + return err; 77 + } 78 + 79 + err = auxiliary_device_add(&linecard_bdev->adev); 80 + if (err) { 81 + auxiliary_device_uninit(&linecard_bdev->adev); 82 + return err; 83 + } 84 + 85 + linecard->bdev = linecard_bdev; 86 + return 0; 87 + } 88 + 89 + void mlxsw_linecard_bdev_del(struct mlxsw_linecard *linecard) 90 + { 91 + struct mlxsw_linecard_bdev *linecard_bdev = linecard->bdev; 92 + 93 + if (!linecard_bdev) 94 + /* Unprovisioned line cards do not have an auxiliary device. */ 95 + return; 96 + auxiliary_device_delete(&linecard_bdev->adev); 97 + auxiliary_device_uninit(&linecard_bdev->adev); 98 + linecard->bdev = NULL; 99 + } 100 + 101 + static int mlxsw_linecard_dev_devlink_info_get(struct devlink *devlink, 102 + struct devlink_info_req *req, 103 + struct netlink_ext_ack *extack) 104 + { 105 + struct mlxsw_linecard_dev *linecard_dev = devlink_priv(devlink); 106 + struct mlxsw_linecard *linecard = linecard_dev->linecard; 107 + 108 + return mlxsw_linecard_devlink_info_get(linecard, req, extack); 109 + } 110 + 111 + static int 112 + mlxsw_linecard_dev_devlink_flash_update(struct devlink *devlink, 113 + struct devlink_flash_update_params *params, 114 + struct netlink_ext_ack *extack) 115 + { 116 + struct mlxsw_linecard_dev *linecard_dev = devlink_priv(devlink); 117 + struct mlxsw_linecard *linecard = linecard_dev->linecard; 118 + 119 + return mlxsw_linecard_flash_update(devlink, linecard, 120 + params->fw, extack); 121 + } 122 + 123 + static const struct devlink_ops mlxsw_linecard_dev_devlink_ops = { 124 + .info_get = mlxsw_linecard_dev_devlink_info_get, 125 + .flash_update = mlxsw_linecard_dev_devlink_flash_update, 126 + }; 127 + 128 + static int mlxsw_linecard_bdev_probe(struct auxiliary_device *adev, 129 + const struct auxiliary_device_id *id) 130 + { 131 + struct mlxsw_linecard_bdev *linecard_bdev = 132 + container_of(adev, struct mlxsw_linecard_bdev, adev); 133 + struct mlxsw_linecard *linecard = linecard_bdev->linecard; 134 + struct mlxsw_linecard_dev *linecard_dev; 135 + struct devlink *devlink; 136 + 137 + devlink = devlink_alloc(&mlxsw_linecard_dev_devlink_ops, 138 + sizeof(*linecard_dev), &adev->dev); 139 + if (!devlink) 140 + return -ENOMEM; 141 + linecard_dev = devlink_priv(devlink); 142 + linecard_dev->linecard = linecard_bdev->linecard; 143 + linecard_bdev->linecard_dev = linecard_dev; 144 + 145 + devlink_register(devlink); 146 + devlink_linecard_nested_dl_set(linecard->devlink_linecard, devlink); 147 + return 0; 148 + } 149 + 150 + static void mlxsw_linecard_bdev_remove(struct auxiliary_device *adev) 151 + { 152 + struct mlxsw_linecard_bdev *linecard_bdev = 153 + container_of(adev, struct mlxsw_linecard_bdev, adev); 154 + struct devlink *devlink = priv_to_devlink(linecard_bdev->linecard_dev); 155 + struct mlxsw_linecard *linecard = linecard_bdev->linecard; 156 + 157 + devlink_linecard_nested_dl_set(linecard->devlink_linecard, NULL); 158 + devlink_unregister(devlink); 159 + devlink_free(devlink); 160 + } 161 + 162 + static const struct auxiliary_device_id mlxsw_linecard_bdev_id_table[] = { 163 + { .name = KBUILD_MODNAME "." MLXSW_LINECARD_DEV_ID_NAME }, 164 + {}, 165 + }; 166 + 167 + MODULE_DEVICE_TABLE(auxiliary, mlxsw_linecard_bdev_id_table); 168 + 169 + static struct auxiliary_driver mlxsw_linecard_driver = { 170 + .name = MLXSW_LINECARD_DEV_ID_NAME, 171 + .probe = mlxsw_linecard_bdev_probe, 172 + .remove = mlxsw_linecard_bdev_remove, 173 + .id_table = mlxsw_linecard_bdev_id_table, 174 + }; 175 + 176 + int mlxsw_linecard_driver_register(void) 177 + { 178 + return auxiliary_driver_register(&mlxsw_linecard_driver); 179 + } 180 + 181 + void mlxsw_linecard_driver_unregister(void) 182 + { 183 + auxiliary_driver_unregister(&mlxsw_linecard_driver); 184 + }
+405
drivers/net/ethernet/mellanox/mlxsw/core_linecards.c
··· 13 13 #include <linux/vmalloc.h> 14 14 15 15 #include "core.h" 16 + #include "../mlxfw/mlxfw.h" 16 17 17 18 struct mlxsw_linecard_ini_file { 18 19 __le16 size; ··· 86 85 return ERR_PTR(err); 87 86 mlxsw_reg_mddq_slot_name_unpack(mddq_pl, linecard->name); 88 87 return linecard->name; 88 + } 89 + 90 + struct mlxsw_linecard_device_fw_info { 91 + struct mlxfw_dev mlxfw_dev; 92 + struct mlxsw_core *mlxsw_core; 93 + struct mlxsw_linecard *linecard; 94 + }; 95 + 96 + static int mlxsw_linecard_device_fw_component_query(struct mlxfw_dev *mlxfw_dev, 97 + u16 component_index, 98 + u32 *p_max_size, 99 + u8 *p_align_bits, 100 + u16 *p_max_write_size) 101 + { 102 + struct mlxsw_linecard_device_fw_info *info = 103 + container_of(mlxfw_dev, struct mlxsw_linecard_device_fw_info, 104 + mlxfw_dev); 105 + struct mlxsw_linecard *linecard = info->linecard; 106 + struct mlxsw_core *mlxsw_core = info->mlxsw_core; 107 + char mddt_pl[MLXSW_REG_MDDT_LEN]; 108 + char *mcqi_pl; 109 + int err; 110 + 111 + mlxsw_reg_mddt_pack(mddt_pl, linecard->slot_index, 112 + linecard->device.index, 113 + MLXSW_REG_MDDT_METHOD_QUERY, 114 + MLXSW_REG(mcqi), &mcqi_pl); 115 + 116 + mlxsw_reg_mcqi_pack(mcqi_pl, component_index); 117 + err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mddt), mddt_pl); 118 + if (err) 119 + return err; 120 + mlxsw_reg_mcqi_unpack(mcqi_pl, p_max_size, p_align_bits, 121 + p_max_write_size); 122 + 123 + *p_align_bits = max_t(u8, *p_align_bits, 2); 124 + *p_max_write_size = min_t(u16, *p_max_write_size, 125 + MLXSW_REG_MCDA_MAX_DATA_LEN); 126 + return 0; 127 + } 128 + 129 + static int mlxsw_linecard_device_fw_fsm_lock(struct mlxfw_dev *mlxfw_dev, 130 + u32 *fwhandle) 131 + { 132 + struct mlxsw_linecard_device_fw_info *info = 133 + container_of(mlxfw_dev, struct mlxsw_linecard_device_fw_info, 134 + mlxfw_dev); 135 + struct mlxsw_linecard *linecard = info->linecard; 136 + struct mlxsw_core *mlxsw_core = info->mlxsw_core; 137 + char mddt_pl[MLXSW_REG_MDDT_LEN]; 138 + u8 control_state; 139 + char *mcc_pl; 140 + int err; 141 + 142 + mlxsw_reg_mddt_pack(mddt_pl, linecard->slot_index, 143 + linecard->device.index, 144 + MLXSW_REG_MDDT_METHOD_QUERY, 145 + MLXSW_REG(mcc), &mcc_pl); 146 + mlxsw_reg_mcc_pack(mcc_pl, 0, 0, 0, 0); 147 + err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mddt), mddt_pl); 148 + if (err) 149 + return err; 150 + 151 + mlxsw_reg_mcc_unpack(mcc_pl, fwhandle, NULL, &control_state); 152 + if (control_state != MLXFW_FSM_STATE_IDLE) 153 + return -EBUSY; 154 + 155 + mlxsw_reg_mddt_pack(mddt_pl, linecard->slot_index, 156 + linecard->device.index, 157 + MLXSW_REG_MDDT_METHOD_WRITE, 158 + MLXSW_REG(mcc), &mcc_pl); 159 + mlxsw_reg_mcc_pack(mcc_pl, MLXSW_REG_MCC_INSTRUCTION_LOCK_UPDATE_HANDLE, 160 + 0, *fwhandle, 0); 161 + return mlxsw_reg_write(mlxsw_core, MLXSW_REG(mddt), mddt_pl); 162 + } 163 + 164 + static int 165 + mlxsw_linecard_device_fw_fsm_component_update(struct mlxfw_dev *mlxfw_dev, 166 + u32 fwhandle, 167 + u16 component_index, 168 + u32 component_size) 169 + { 170 + struct mlxsw_linecard_device_fw_info *info = 171 + container_of(mlxfw_dev, struct mlxsw_linecard_device_fw_info, 172 + mlxfw_dev); 173 + struct mlxsw_linecard *linecard = info->linecard; 174 + struct mlxsw_core *mlxsw_core = info->mlxsw_core; 175 + char mddt_pl[MLXSW_REG_MDDT_LEN]; 176 + char *mcc_pl; 177 + 178 + mlxsw_reg_mddt_pack(mddt_pl, linecard->slot_index, 179 + linecard->device.index, 180 + MLXSW_REG_MDDT_METHOD_WRITE, 181 + MLXSW_REG(mcc), &mcc_pl); 182 + mlxsw_reg_mcc_pack(mcc_pl, MLXSW_REG_MCC_INSTRUCTION_UPDATE_COMPONENT, 183 + component_index, fwhandle, component_size); 184 + return mlxsw_reg_write(mlxsw_core, MLXSW_REG(mddt), mddt_pl); 185 + } 186 + 187 + static int 188 + mlxsw_linecard_device_fw_fsm_block_download(struct mlxfw_dev *mlxfw_dev, 189 + u32 fwhandle, u8 *data, 190 + u16 size, u32 offset) 191 + { 192 + struct mlxsw_linecard_device_fw_info *info = 193 + container_of(mlxfw_dev, struct mlxsw_linecard_device_fw_info, 194 + mlxfw_dev); 195 + struct mlxsw_linecard *linecard = info->linecard; 196 + struct mlxsw_core *mlxsw_core = info->mlxsw_core; 197 + char mddt_pl[MLXSW_REG_MDDT_LEN]; 198 + char *mcda_pl; 199 + 200 + mlxsw_reg_mddt_pack(mddt_pl, linecard->slot_index, 201 + linecard->device.index, 202 + MLXSW_REG_MDDT_METHOD_WRITE, 203 + MLXSW_REG(mcda), &mcda_pl); 204 + mlxsw_reg_mcda_pack(mcda_pl, fwhandle, offset, size, data); 205 + return mlxsw_reg_write(mlxsw_core, MLXSW_REG(mddt), mddt_pl); 206 + } 207 + 208 + static int 209 + mlxsw_linecard_device_fw_fsm_component_verify(struct mlxfw_dev *mlxfw_dev, 210 + u32 fwhandle, u16 component_index) 211 + { 212 + struct mlxsw_linecard_device_fw_info *info = 213 + container_of(mlxfw_dev, struct mlxsw_linecard_device_fw_info, 214 + mlxfw_dev); 215 + struct mlxsw_linecard *linecard = info->linecard; 216 + struct mlxsw_core *mlxsw_core = info->mlxsw_core; 217 + char mddt_pl[MLXSW_REG_MDDT_LEN]; 218 + char *mcc_pl; 219 + 220 + mlxsw_reg_mddt_pack(mddt_pl, linecard->slot_index, 221 + linecard->device.index, 222 + MLXSW_REG_MDDT_METHOD_WRITE, 223 + MLXSW_REG(mcc), &mcc_pl); 224 + mlxsw_reg_mcc_pack(mcc_pl, MLXSW_REG_MCC_INSTRUCTION_VERIFY_COMPONENT, 225 + component_index, fwhandle, 0); 226 + return mlxsw_reg_write(mlxsw_core, MLXSW_REG(mddt), mddt_pl); 227 + } 228 + 229 + static int mlxsw_linecard_device_fw_fsm_activate(struct mlxfw_dev *mlxfw_dev, 230 + u32 fwhandle) 231 + { 232 + struct mlxsw_linecard_device_fw_info *info = 233 + container_of(mlxfw_dev, struct mlxsw_linecard_device_fw_info, 234 + mlxfw_dev); 235 + struct mlxsw_linecard *linecard = info->linecard; 236 + struct mlxsw_core *mlxsw_core = info->mlxsw_core; 237 + char mddt_pl[MLXSW_REG_MDDT_LEN]; 238 + char *mcc_pl; 239 + 240 + mlxsw_reg_mddt_pack(mddt_pl, linecard->slot_index, 241 + linecard->device.index, 242 + MLXSW_REG_MDDT_METHOD_WRITE, 243 + MLXSW_REG(mcc), &mcc_pl); 244 + mlxsw_reg_mcc_pack(mcc_pl, MLXSW_REG_MCC_INSTRUCTION_ACTIVATE, 245 + 0, fwhandle, 0); 246 + return mlxsw_reg_write(mlxsw_core, MLXSW_REG(mddt), mddt_pl); 247 + } 248 + 249 + static int 250 + mlxsw_linecard_device_fw_fsm_query_state(struct mlxfw_dev *mlxfw_dev, 251 + u32 fwhandle, 252 + enum mlxfw_fsm_state *fsm_state, 253 + enum mlxfw_fsm_state_err *fsm_state_err) 254 + { 255 + struct mlxsw_linecard_device_fw_info *info = 256 + container_of(mlxfw_dev, struct mlxsw_linecard_device_fw_info, 257 + mlxfw_dev); 258 + struct mlxsw_linecard *linecard = info->linecard; 259 + struct mlxsw_core *mlxsw_core = info->mlxsw_core; 260 + char mddt_pl[MLXSW_REG_MDDT_LEN]; 261 + u8 control_state; 262 + u8 error_code; 263 + char *mcc_pl; 264 + int err; 265 + 266 + mlxsw_reg_mddt_pack(mddt_pl, linecard->slot_index, 267 + linecard->device.index, 268 + MLXSW_REG_MDDT_METHOD_QUERY, 269 + MLXSW_REG(mcc), &mcc_pl); 270 + mlxsw_reg_mcc_pack(mcc_pl, 0, 0, fwhandle, 0); 271 + err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mddt), mddt_pl); 272 + if (err) 273 + return err; 274 + 275 + mlxsw_reg_mcc_unpack(mcc_pl, NULL, &error_code, &control_state); 276 + *fsm_state = control_state; 277 + *fsm_state_err = min_t(enum mlxfw_fsm_state_err, error_code, 278 + MLXFW_FSM_STATE_ERR_MAX); 279 + return 0; 280 + } 281 + 282 + static void mlxsw_linecard_device_fw_fsm_cancel(struct mlxfw_dev *mlxfw_dev, 283 + u32 fwhandle) 284 + { 285 + struct mlxsw_linecard_device_fw_info *info = 286 + container_of(mlxfw_dev, struct mlxsw_linecard_device_fw_info, 287 + mlxfw_dev); 288 + struct mlxsw_linecard *linecard = info->linecard; 289 + struct mlxsw_core *mlxsw_core = info->mlxsw_core; 290 + char mddt_pl[MLXSW_REG_MDDT_LEN]; 291 + char *mcc_pl; 292 + 293 + mlxsw_reg_mddt_pack(mddt_pl, linecard->slot_index, 294 + linecard->device.index, 295 + MLXSW_REG_MDDT_METHOD_WRITE, 296 + MLXSW_REG(mcc), &mcc_pl); 297 + mlxsw_reg_mcc_pack(mcc_pl, MLXSW_REG_MCC_INSTRUCTION_CANCEL, 298 + 0, fwhandle, 0); 299 + mlxsw_reg_write(mlxsw_core, MLXSW_REG(mddt), mddt_pl); 300 + } 301 + 302 + static void mlxsw_linecard_device_fw_fsm_release(struct mlxfw_dev *mlxfw_dev, 303 + u32 fwhandle) 304 + { 305 + struct mlxsw_linecard_device_fw_info *info = 306 + container_of(mlxfw_dev, struct mlxsw_linecard_device_fw_info, 307 + mlxfw_dev); 308 + struct mlxsw_linecard *linecard = info->linecard; 309 + struct mlxsw_core *mlxsw_core = info->mlxsw_core; 310 + char mddt_pl[MLXSW_REG_MDDT_LEN]; 311 + char *mcc_pl; 312 + 313 + mlxsw_reg_mddt_pack(mddt_pl, linecard->slot_index, 314 + linecard->device.index, 315 + MLXSW_REG_MDDT_METHOD_WRITE, 316 + MLXSW_REG(mcc), &mcc_pl); 317 + mlxsw_reg_mcc_pack(mcc_pl, 318 + MLXSW_REG_MCC_INSTRUCTION_RELEASE_UPDATE_HANDLE, 319 + 0, fwhandle, 0); 320 + mlxsw_reg_write(mlxsw_core, MLXSW_REG(mddt), mddt_pl); 321 + } 322 + 323 + static const struct mlxfw_dev_ops mlxsw_linecard_device_dev_ops = { 324 + .component_query = mlxsw_linecard_device_fw_component_query, 325 + .fsm_lock = mlxsw_linecard_device_fw_fsm_lock, 326 + .fsm_component_update = mlxsw_linecard_device_fw_fsm_component_update, 327 + .fsm_block_download = mlxsw_linecard_device_fw_fsm_block_download, 328 + .fsm_component_verify = mlxsw_linecard_device_fw_fsm_component_verify, 329 + .fsm_activate = mlxsw_linecard_device_fw_fsm_activate, 330 + .fsm_query_state = mlxsw_linecard_device_fw_fsm_query_state, 331 + .fsm_cancel = mlxsw_linecard_device_fw_fsm_cancel, 332 + .fsm_release = mlxsw_linecard_device_fw_fsm_release, 333 + }; 334 + 335 + int mlxsw_linecard_flash_update(struct devlink *linecard_devlink, 336 + struct mlxsw_linecard *linecard, 337 + const struct firmware *firmware, 338 + struct netlink_ext_ack *extack) 339 + { 340 + struct mlxsw_core *mlxsw_core = linecard->linecards->mlxsw_core; 341 + struct mlxsw_linecard_device_fw_info info = { 342 + .mlxfw_dev = { 343 + .ops = &mlxsw_linecard_device_dev_ops, 344 + .psid = linecard->device.info.psid, 345 + .psid_size = strlen(linecard->device.info.psid), 346 + .devlink = linecard_devlink, 347 + }, 348 + .mlxsw_core = mlxsw_core, 349 + .linecard = linecard, 350 + }; 351 + int err; 352 + 353 + mutex_lock(&linecard->lock); 354 + if (!linecard->active) { 355 + NL_SET_ERR_MSG_MOD(extack, "Only active line cards can be flashed"); 356 + err = -EINVAL; 357 + goto unlock; 358 + } 359 + err = mlxsw_core_fw_flash(mlxsw_core, &info.mlxfw_dev, 360 + firmware, extack); 361 + unlock: 362 + mutex_unlock(&linecard->lock); 363 + return err; 364 + } 365 + 366 + static int mlxsw_linecard_device_psid_get(struct mlxsw_linecard *linecard, 367 + u8 device_index, char *psid) 368 + { 369 + struct mlxsw_core *mlxsw_core = linecard->linecards->mlxsw_core; 370 + char mddt_pl[MLXSW_REG_MDDT_LEN]; 371 + char *mgir_pl; 372 + int err; 373 + 374 + mlxsw_reg_mddt_pack(mddt_pl, linecard->slot_index, device_index, 375 + MLXSW_REG_MDDT_METHOD_QUERY, 376 + MLXSW_REG(mgir), &mgir_pl); 377 + 378 + mlxsw_reg_mgir_pack(mgir_pl); 379 + err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mddt), mddt_pl); 380 + if (err) 381 + return err; 382 + 383 + mlxsw_reg_mgir_fw_info_psid_memcpy_from(mgir_pl, psid); 384 + return 0; 385 + } 386 + 387 + static int mlxsw_linecard_device_info_update(struct mlxsw_linecard *linecard) 388 + { 389 + struct mlxsw_core *mlxsw_core = linecard->linecards->mlxsw_core; 390 + bool flashable_found = false; 391 + u8 msg_seq = 0; 392 + 393 + do { 394 + struct mlxsw_linecard_device_info info; 395 + char mddq_pl[MLXSW_REG_MDDQ_LEN]; 396 + bool flash_owner; 397 + bool data_valid; 398 + u8 device_index; 399 + int err; 400 + 401 + mlxsw_reg_mddq_device_info_pack(mddq_pl, linecard->slot_index, 402 + msg_seq); 403 + err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mddq), mddq_pl); 404 + if (err) 405 + return err; 406 + mlxsw_reg_mddq_device_info_unpack(mddq_pl, &msg_seq, 407 + &data_valid, &flash_owner, 408 + &device_index, 409 + &info.fw_major, 410 + &info.fw_minor, 411 + &info.fw_sub_minor); 412 + if (!data_valid) 413 + break; 414 + if (!flash_owner) /* We care only about flashable ones. */ 415 + continue; 416 + if (flashable_found) { 417 + dev_warn_once(linecard->linecards->bus_info->dev, "linecard %u: More flashable devices present, exposing only the first one\n", 418 + linecard->slot_index); 419 + return 0; 420 + } 421 + 422 + err = mlxsw_linecard_device_psid_get(linecard, device_index, 423 + info.psid); 424 + if (err) 425 + return err; 426 + 427 + linecard->device.info = info; 428 + linecard->device.index = device_index; 429 + flashable_found = true; 430 + } while (msg_seq); 431 + 432 + return 0; 89 433 } 90 434 91 435 static void mlxsw_linecard_provision_fail(struct mlxsw_linecard *linecard) ··· 572 226 } 573 227 EXPORT_SYMBOL(mlxsw_linecards_event_ops_unregister); 574 228 229 + int mlxsw_linecard_devlink_info_get(struct mlxsw_linecard *linecard, 230 + struct devlink_info_req *req, 231 + struct netlink_ext_ack *extack) 232 + { 233 + char buf[32]; 234 + int err; 235 + 236 + mutex_lock(&linecard->lock); 237 + if (WARN_ON(!linecard->provisioned)) { 238 + err = -EOPNOTSUPP; 239 + goto unlock; 240 + } 241 + 242 + sprintf(buf, "%d", linecard->hw_revision); 243 + err = devlink_info_version_fixed_put(req, "hw.revision", buf); 244 + if (err) 245 + goto unlock; 246 + 247 + sprintf(buf, "%d", linecard->ini_version); 248 + err = devlink_info_version_running_put(req, "ini.version", buf); 249 + if (err) 250 + goto unlock; 251 + 252 + if (linecard->active) { 253 + struct mlxsw_linecard_device_info *info = &linecard->device.info; 254 + 255 + err = devlink_info_version_fixed_put(req, 256 + DEVLINK_INFO_VERSION_GENERIC_FW_PSID, 257 + info->psid); 258 + 259 + sprintf(buf, "%u.%u.%u", info->fw_major, info->fw_minor, 260 + info->fw_sub_minor); 261 + err = devlink_info_version_running_put(req, 262 + DEVLINK_INFO_VERSION_GENERIC_FW, 263 + buf); 264 + if (err) 265 + goto unlock; 266 + } 267 + 268 + unlock: 269 + mutex_unlock(&linecard->lock); 270 + return err; 271 + } 272 + 575 273 static int 576 274 mlxsw_linecard_provision_set(struct mlxsw_linecard *linecard, u8 card_type, 577 275 u16 hw_revision, u16 ini_version) 578 276 { 579 277 struct mlxsw_linecards *linecards = linecard->linecards; 580 278 const char *type; 279 + int err; 581 280 582 281 type = mlxsw_linecard_types_lookup(linecards, card_type); 583 282 mlxsw_linecard_status_event_done(linecard, ··· 643 252 linecard->provisioned = true; 644 253 linecard->hw_revision = hw_revision; 645 254 linecard->ini_version = ini_version; 255 + 256 + err = mlxsw_linecard_bdev_add(linecard); 257 + if (err) { 258 + linecard->provisioned = false; 259 + mlxsw_linecard_provision_fail(linecard); 260 + return err; 261 + } 262 + 646 263 devlink_linecard_provision_set(linecard->devlink_linecard, type); 647 264 return 0; 648 265 } ··· 659 260 { 660 261 mlxsw_linecard_status_event_done(linecard, 661 262 MLXSW_LINECARD_STATUS_EVENT_TYPE_UNPROVISION); 263 + mlxsw_linecard_bdev_del(linecard); 662 264 linecard->provisioned = false; 663 265 devlink_linecard_provision_clear(linecard->devlink_linecard); 664 266 } ··· 669 269 struct mlxsw_core *mlxsw_core = linecard->linecards->mlxsw_core; 670 270 char mddc_pl[MLXSW_REG_MDDC_LEN]; 671 271 int err; 272 + 273 + err = mlxsw_linecard_device_info_update(linecard); 274 + if (err) 275 + return err; 672 276 673 277 mlxsw_reg_mddc_pack(mddc_pl, linecard->slot_index, false, true); 674 278 err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(mddc), mddc_pl); ··· 1289 885 mlxsw_core_flush_owq(); 1290 886 if (linecard->active) 1291 887 mlxsw_linecard_active_clear(linecard); 888 + mlxsw_linecard_bdev_del(linecard); 1292 889 devlink_linecard_destroy(linecard->devlink_linecard); 1293 890 mutex_destroy(&linecard->lock); 1294 891 }
+172 -1
drivers/net/ethernet/mellanox/mlxsw/reg.h
··· 11364 11364 *p_fsm_state = mlxsw_reg_mbct_fsm_state_get(payload); 11365 11365 } 11366 11366 11367 + /* MDDT - Management DownStream Device Tunneling Register 11368 + * ------------------------------------------------------ 11369 + * This register allows to deliver query and request messages (PRM registers, 11370 + * commands) to a DownStream device. 11371 + */ 11372 + #define MLXSW_REG_MDDT_ID 0x9160 11373 + #define MLXSW_REG_MDDT_LEN 0x110 11374 + 11375 + MLXSW_REG_DEFINE(mddt, MLXSW_REG_MDDT_ID, MLXSW_REG_MDDT_LEN); 11376 + 11377 + /* reg_mddt_slot_index 11378 + * Slot index. 11379 + * Access: Index 11380 + */ 11381 + MLXSW_ITEM32(reg, mddt, slot_index, 0x00, 8, 4); 11382 + 11383 + /* reg_mddt_device_index 11384 + * Device index. 11385 + * Access: Index 11386 + */ 11387 + MLXSW_ITEM32(reg, mddt, device_index, 0x00, 0, 8); 11388 + 11389 + /* reg_mddt_read_size 11390 + * Read size in D-Words. 11391 + * Access: OP 11392 + */ 11393 + MLXSW_ITEM32(reg, mddt, read_size, 0x04, 24, 8); 11394 + 11395 + /* reg_mddt_write_size 11396 + * Write size in D-Words. 11397 + * Access: OP 11398 + */ 11399 + MLXSW_ITEM32(reg, mddt, write_size, 0x04, 16, 8); 11400 + 11401 + enum mlxsw_reg_mddt_status { 11402 + MLXSW_REG_MDDT_STATUS_OK, 11403 + }; 11404 + 11405 + /* reg_mddt_status 11406 + * Return code of the Downstream Device to the register that was sent. 11407 + * Access: RO 11408 + */ 11409 + MLXSW_ITEM32(reg, mddt, status, 0x0C, 24, 8); 11410 + 11411 + enum mlxsw_reg_mddt_method { 11412 + MLXSW_REG_MDDT_METHOD_QUERY, 11413 + MLXSW_REG_MDDT_METHOD_WRITE, 11414 + }; 11415 + 11416 + /* reg_mddt_method 11417 + * Access: OP 11418 + */ 11419 + MLXSW_ITEM32(reg, mddt, method, 0x0C, 22, 2); 11420 + 11421 + /* reg_mddt_register_id 11422 + * Access: Index 11423 + */ 11424 + MLXSW_ITEM32(reg, mddt, register_id, 0x0C, 0, 16); 11425 + 11426 + #define MLXSW_REG_MDDT_PAYLOAD_OFFSET 0x0C 11427 + #define MLXSW_REG_MDDT_PRM_REGISTER_HEADER_LEN 4 11428 + 11429 + static inline char *mlxsw_reg_mddt_inner_payload(char *payload) 11430 + { 11431 + return payload + MLXSW_REG_MDDT_PAYLOAD_OFFSET + 11432 + MLXSW_REG_MDDT_PRM_REGISTER_HEADER_LEN; 11433 + } 11434 + 11435 + static inline void mlxsw_reg_mddt_pack(char *payload, u8 slot_index, 11436 + u8 device_index, 11437 + enum mlxsw_reg_mddt_method method, 11438 + const struct mlxsw_reg_info *reg, 11439 + char **inner_payload) 11440 + { 11441 + int len = reg->len + MLXSW_REG_MDDT_PRM_REGISTER_HEADER_LEN; 11442 + 11443 + if (WARN_ON(len + MLXSW_REG_MDDT_PAYLOAD_OFFSET > MLXSW_REG_MDDT_LEN)) 11444 + len = MLXSW_REG_MDDT_LEN - MLXSW_REG_MDDT_PAYLOAD_OFFSET; 11445 + 11446 + MLXSW_REG_ZERO(mddt, payload); 11447 + mlxsw_reg_mddt_slot_index_set(payload, slot_index); 11448 + mlxsw_reg_mddt_device_index_set(payload, device_index); 11449 + mlxsw_reg_mddt_method_set(payload, method); 11450 + mlxsw_reg_mddt_register_id_set(payload, reg->id); 11451 + mlxsw_reg_mddt_read_size_set(payload, len / 4); 11452 + mlxsw_reg_mddt_write_size_set(payload, len / 4); 11453 + *inner_payload = mlxsw_reg_mddt_inner_payload(payload); 11454 + } 11455 + 11367 11456 /* MDDQ - Management DownStream Device Query Register 11368 11457 * -------------------------------------------------- 11369 11458 * This register allows to query the DownStream device properties. The desired ··· 11474 11385 11475 11386 enum mlxsw_reg_mddq_query_type { 11476 11387 MLXSW_REG_MDDQ_QUERY_TYPE_SLOT_INFO = 1, 11477 - MLXSW_REG_MDDQ_QUERY_TYPE_SLOT_NAME = 3, 11388 + MLXSW_REG_MDDQ_QUERY_TYPE_DEVICE_INFO, /* If there are no devices 11389 + * on the slot, data_valid 11390 + * will be '0'. 11391 + */ 11392 + MLXSW_REG_MDDQ_QUERY_TYPE_SLOT_NAME, 11478 11393 }; 11479 11394 11480 11395 /* reg_mddq_query_type ··· 11491 11398 * Access: Index 11492 11399 */ 11493 11400 MLXSW_ITEM32(reg, mddq, slot_index, 0x00, 0, 4); 11401 + 11402 + /* reg_mddq_response_msg_seq 11403 + * Response message sequential number. For a specific request, the response 11404 + * message sequential number is the following one. In addition, the last 11405 + * message should be 0. 11406 + * Access: RO 11407 + */ 11408 + MLXSW_ITEM32(reg, mddq, response_msg_seq, 0x04, 16, 8); 11409 + 11410 + /* reg_mddq_request_msg_seq 11411 + * Request message sequential number. 11412 + * The first message number should be 0. 11413 + * Access: Index 11414 + */ 11415 + MLXSW_ITEM32(reg, mddq, request_msg_seq, 0x04, 0, 8); 11416 + 11417 + /* reg_mddq_data_valid 11418 + * If set, the data in the data field is valid and contain the information 11419 + * for the queried index. 11420 + * Access: RO 11421 + */ 11422 + MLXSW_ITEM32(reg, mddq, data_valid, 0x08, 31, 1); 11494 11423 11495 11424 /* reg_mddq_slot_info_provisioned 11496 11425 * If set, the INI file is applied and the card is provisioned. ··· 11598 11483 *p_hw_revision = mlxsw_reg_mddq_slot_info_hw_revision_get(payload); 11599 11484 *p_ini_file_version = mlxsw_reg_mddq_slot_info_ini_file_version_get(payload); 11600 11485 *p_card_type = mlxsw_reg_mddq_slot_info_card_type_get(payload); 11486 + } 11487 + 11488 + /* reg_mddq_device_info_flash_owner 11489 + * If set, the device is the flash owner. Otherwise, a shared flash 11490 + * is used by this device (another device is the flash owner). 11491 + * Access: RO 11492 + */ 11493 + MLXSW_ITEM32(reg, mddq, device_info_flash_owner, 0x10, 30, 1); 11494 + 11495 + /* reg_mddq_device_info_device_index 11496 + * Device index. The first device should number 0. 11497 + * Access: RO 11498 + */ 11499 + MLXSW_ITEM32(reg, mddq, device_info_device_index, 0x10, 0, 8); 11500 + 11501 + /* reg_mddq_device_info_fw_major 11502 + * Major FW version number. 11503 + * Access: RO 11504 + */ 11505 + MLXSW_ITEM32(reg, mddq, device_info_fw_major, 0x14, 16, 16); 11506 + 11507 + /* reg_mddq_device_info_fw_minor 11508 + * Minor FW version number. 11509 + * Access: RO 11510 + */ 11511 + MLXSW_ITEM32(reg, mddq, device_info_fw_minor, 0x18, 16, 16); 11512 + 11513 + /* reg_mddq_device_info_fw_sub_minor 11514 + * Sub-minor FW version number. 11515 + * Access: RO 11516 + */ 11517 + MLXSW_ITEM32(reg, mddq, device_info_fw_sub_minor, 0x18, 0, 16); 11518 + 11519 + static inline void 11520 + mlxsw_reg_mddq_device_info_pack(char *payload, u8 slot_index, 11521 + u8 request_msg_seq) 11522 + { 11523 + __mlxsw_reg_mddq_pack(payload, slot_index, 11524 + MLXSW_REG_MDDQ_QUERY_TYPE_DEVICE_INFO); 11525 + mlxsw_reg_mddq_request_msg_seq_set(payload, request_msg_seq); 11526 + } 11527 + 11528 + static inline void 11529 + mlxsw_reg_mddq_device_info_unpack(const char *payload, u8 *p_response_msg_seq, 11530 + bool *p_data_valid, bool *p_flash_owner, 11531 + u8 *p_device_index, u16 *p_fw_major, 11532 + u16 *p_fw_minor, u16 *p_fw_sub_minor) 11533 + { 11534 + *p_response_msg_seq = mlxsw_reg_mddq_response_msg_seq_get(payload); 11535 + *p_data_valid = mlxsw_reg_mddq_data_valid_get(payload); 11536 + *p_flash_owner = mlxsw_reg_mddq_device_info_flash_owner_get(payload); 11537 + *p_device_index = mlxsw_reg_mddq_device_info_device_index_get(payload); 11538 + *p_fw_major = mlxsw_reg_mddq_device_info_fw_major_get(payload); 11539 + *p_fw_minor = mlxsw_reg_mddq_device_info_fw_minor_get(payload); 11540 + *p_fw_sub_minor = mlxsw_reg_mddq_device_info_fw_sub_minor_get(payload); 11601 11541 } 11602 11542 11603 11543 #define MLXSW_REG_MDDQ_SLOT_ASCII_NAME_LEN 20 ··· 13032 12862 MLXSW_REG(mfgd), 13033 12863 MLXSW_REG(mgpir), 13034 12864 MLXSW_REG(mbct), 12865 + MLXSW_REG(mddt), 13035 12866 MLXSW_REG(mddq), 13036 12867 MLXSW_REG(mddc), 13037 12868 MLXSW_REG(mfde),
+2
include/net/devlink.h
··· 1580 1580 void devlink_linecard_provision_fail(struct devlink_linecard *linecard); 1581 1581 void devlink_linecard_activate(struct devlink_linecard *linecard); 1582 1582 void devlink_linecard_deactivate(struct devlink_linecard *linecard); 1583 + void devlink_linecard_nested_dl_set(struct devlink_linecard *linecard, 1584 + struct devlink *nested_devlink); 1583 1585 int devl_sb_register(struct devlink *devlink, unsigned int sb_index, 1584 1586 u32 size, u16 ingress_pools_count, 1585 1587 u16 egress_pools_count, u16 ingress_tc_count,
+2
include/uapi/linux/devlink.h
··· 576 576 DEVLINK_ATTR_LINECARD_TYPE, /* string */ 577 577 DEVLINK_ATTR_LINECARD_SUPPORTED_TYPES, /* nested */ 578 578 579 + DEVLINK_ATTR_NESTED_DEVLINK, /* nested */ 580 + 579 581 /* add new attributes above here, update the policy in devlink.c */ 580 582 581 583 __DEVLINK_ATTR_MAX,
+131 -157
net/core/devlink.c
··· 70 70 u8 reload_failed:1; 71 71 refcount_t refcount; 72 72 struct completion comp; 73 + struct rcu_head rcu; 73 74 char priv[] __aligned(NETDEV_ALIGN); 74 75 }; 75 76 ··· 89 88 const char *type; 90 89 struct devlink_linecard_type *types; 91 90 unsigned int types_count; 91 + struct devlink *nested_devlink; 92 92 }; 93 93 94 94 /** ··· 223 221 /* devlink_mutex 224 222 * 225 223 * An overall lock guarding every operation coming from userspace. 226 - * It also guards devlink devices list and it is taken when 227 - * driver registers/unregisters it. 228 224 */ 229 225 static DEFINE_MUTEX(devlink_mutex); 230 226 ··· 232 232 } 233 233 EXPORT_SYMBOL_GPL(devlink_net); 234 234 235 + static void __devlink_put_rcu(struct rcu_head *head) 236 + { 237 + struct devlink *devlink = container_of(head, struct devlink, rcu); 238 + 239 + complete(&devlink->comp); 240 + } 241 + 235 242 void devlink_put(struct devlink *devlink) 236 243 { 237 244 if (refcount_dec_and_test(&devlink->refcount)) 238 - complete(&devlink->comp); 245 + /* Make sure unregister operation that may await the completion 246 + * is unblocked only after all users are after the end of 247 + * RCU grace period. 248 + */ 249 + call_rcu(&devlink->rcu, __devlink_put_rcu); 239 250 } 240 251 241 252 struct devlink *__must_check devlink_try_get(struct devlink *devlink) ··· 289 278 } 290 279 EXPORT_SYMBOL_GPL(devl_unlock); 291 280 281 + static struct devlink * 282 + devlinks_xa_find_get(struct net *net, unsigned long *indexp, xa_mark_t filter, 283 + void * (*xa_find_fn)(struct xarray *, unsigned long *, 284 + unsigned long, xa_mark_t)) 285 + { 286 + struct devlink *devlink; 287 + 288 + rcu_read_lock(); 289 + retry: 290 + devlink = xa_find_fn(&devlinks, indexp, ULONG_MAX, DEVLINK_REGISTERED); 291 + if (!devlink) 292 + goto unlock; 293 + /* For a possible retry, the xa_find_after() should be always used */ 294 + xa_find_fn = xa_find_after; 295 + if (!devlink_try_get(devlink)) 296 + goto retry; 297 + if (!net_eq(devlink_net(devlink), net)) { 298 + devlink_put(devlink); 299 + goto retry; 300 + } 301 + unlock: 302 + rcu_read_unlock(); 303 + return devlink; 304 + } 305 + 306 + static struct devlink *devlinks_xa_find_get_first(struct net *net, 307 + unsigned long *indexp, 308 + xa_mark_t filter) 309 + { 310 + return devlinks_xa_find_get(net, indexp, filter, xa_find); 311 + } 312 + 313 + static struct devlink *devlinks_xa_find_get_next(struct net *net, 314 + unsigned long *indexp, 315 + xa_mark_t filter) 316 + { 317 + return devlinks_xa_find_get(net, indexp, filter, xa_find_after); 318 + } 319 + 320 + /* Iterate over devlink pointers which were possible to get reference to. 321 + * devlink_put() needs to be called for each iterated devlink pointer 322 + * in loop body in order to release the reference. 323 + */ 324 + #define devlinks_xa_for_each_get(net, index, devlink, filter) \ 325 + for (index = 0, \ 326 + devlink = devlinks_xa_find_get_first(net, &index, filter); \ 327 + devlink; devlink = devlinks_xa_find_get_next(net, &index, filter)) 328 + 329 + #define devlinks_xa_for_each_registered_get(net, index, devlink) \ 330 + devlinks_xa_for_each_get(net, index, devlink, DEVLINK_REGISTERED) 331 + 292 332 static struct devlink *devlink_get_from_attrs(struct net *net, 293 333 struct nlattr **attrs) 294 334 { 295 335 struct devlink *devlink; 296 336 unsigned long index; 297 - bool found = false; 298 337 char *busname; 299 338 char *devname; 300 339 ··· 354 293 busname = nla_data(attrs[DEVLINK_ATTR_BUS_NAME]); 355 294 devname = nla_data(attrs[DEVLINK_ATTR_DEV_NAME]); 356 295 357 - lockdep_assert_held(&devlink_mutex); 358 - 359 - xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { 296 + devlinks_xa_for_each_registered_get(net, index, devlink) { 360 297 if (strcmp(devlink->dev->bus->name, busname) == 0 && 361 - strcmp(dev_name(devlink->dev), devname) == 0 && 362 - net_eq(devlink_net(devlink), net)) { 363 - found = true; 364 - break; 365 - } 298 + strcmp(dev_name(devlink->dev), devname) == 0) 299 + return devlink; 300 + devlink_put(devlink); 366 301 } 367 302 368 - if (!found || !devlink_try_get(devlink)) 369 - devlink = ERR_PTR(-ENODEV); 370 - 371 - return devlink; 303 + return ERR_PTR(-ENODEV); 372 304 } 373 305 374 306 static struct devlink_port *devlink_port_get_by_index(struct devlink *devlink, ··· 855 801 if (nla_put_string(msg, DEVLINK_ATTR_DEV_NAME, dev_name(devlink->dev))) 856 802 return -EMSGSIZE; 857 803 return 0; 804 + } 805 + 806 + static int devlink_nl_put_nested_handle(struct sk_buff *msg, struct devlink *devlink) 807 + { 808 + struct nlattr *nested_attr; 809 + 810 + nested_attr = nla_nest_start(msg, DEVLINK_ATTR_NESTED_DEVLINK); 811 + if (!nested_attr) 812 + return -EMSGSIZE; 813 + if (devlink_nl_put_handle(msg, devlink)) 814 + goto nla_put_failure; 815 + 816 + nla_nest_end(msg, nested_attr); 817 + return 0; 818 + 819 + nla_put_failure: 820 + nla_nest_cancel(msg, nested_attr); 821 + return -EMSGSIZE; 858 822 } 859 823 860 824 struct devlink_reload_combination { ··· 1401 1329 int err = 0; 1402 1330 1403 1331 mutex_lock(&devlink_mutex); 1404 - xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { 1405 - if (!devlink_try_get(devlink)) 1406 - continue; 1407 - 1408 - if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 1409 - goto retry; 1410 - 1332 + devlinks_xa_for_each_registered_get(sock_net(msg->sk), index, devlink) { 1411 1333 devl_lock(devlink); 1412 1334 list_for_each_entry(devlink_rate, &devlink->rate_list, list) { 1413 1335 enum devlink_command cmd = DEVLINK_CMD_RATE_NEW; ··· 1422 1356 idx++; 1423 1357 } 1424 1358 devl_unlock(devlink); 1425 - retry: 1426 1359 devlink_put(devlink); 1427 1360 } 1428 1361 out: ··· 1497 1432 int err; 1498 1433 1499 1434 mutex_lock(&devlink_mutex); 1500 - xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { 1501 - if (!devlink_try_get(devlink)) 1502 - continue; 1503 - 1504 - if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) { 1505 - devlink_put(devlink); 1506 - continue; 1507 - } 1508 - 1435 + devlinks_xa_for_each_registered_get(sock_net(msg->sk), index, devlink) { 1509 1436 if (idx < start) { 1510 1437 idx++; 1511 1438 devlink_put(devlink); ··· 1552 1495 int err; 1553 1496 1554 1497 mutex_lock(&devlink_mutex); 1555 - xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { 1556 - if (!devlink_try_get(devlink)) 1557 - continue; 1558 - 1559 - if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 1560 - goto retry; 1561 - 1498 + devlinks_xa_for_each_registered_get(sock_net(msg->sk), index, devlink) { 1562 1499 devl_lock(devlink); 1563 1500 list_for_each_entry(devlink_port, &devlink->port_list, list) { 1564 1501 if (idx < start) { ··· 1572 1521 idx++; 1573 1522 } 1574 1523 devl_unlock(devlink); 1575 - retry: 1576 1524 devlink_put(devlink); 1577 1525 } 1578 1526 out: ··· 2154 2104 nla_nest_end(msg, attr); 2155 2105 } 2156 2106 2107 + if (linecard->nested_devlink && 2108 + devlink_nl_put_nested_handle(msg, linecard->nested_devlink)) 2109 + goto nla_put_failure; 2110 + 2157 2111 genlmsg_end(msg, hdr); 2158 2112 return 0; 2159 2113 ··· 2231 2177 int err; 2232 2178 2233 2179 mutex_lock(&devlink_mutex); 2234 - xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { 2235 - if (!devlink_try_get(devlink)) 2236 - continue; 2237 - 2238 - if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 2239 - goto retry; 2240 - 2180 + devlinks_xa_for_each_registered_get(sock_net(msg->sk), index, devlink) { 2241 2181 mutex_lock(&devlink->linecards_lock); 2242 2182 list_for_each_entry(linecard, &devlink->linecard_list, list) { 2243 2183 if (idx < start) { ··· 2254 2206 idx++; 2255 2207 } 2256 2208 mutex_unlock(&devlink->linecards_lock); 2257 - retry: 2258 2209 devlink_put(devlink); 2259 2210 } 2260 2211 out: ··· 2496 2449 int err; 2497 2450 2498 2451 mutex_lock(&devlink_mutex); 2499 - xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { 2500 - if (!devlink_try_get(devlink)) 2501 - continue; 2502 - 2503 - if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 2504 - goto retry; 2505 - 2452 + devlinks_xa_for_each_registered_get(sock_net(msg->sk), index, devlink) { 2506 2453 devl_lock(devlink); 2507 2454 list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 2508 2455 if (idx < start) { ··· 2516 2475 idx++; 2517 2476 } 2518 2477 devl_unlock(devlink); 2519 - retry: 2520 2478 devlink_put(devlink); 2521 2479 } 2522 2480 out: ··· 2641 2601 int err = 0; 2642 2602 2643 2603 mutex_lock(&devlink_mutex); 2644 - xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { 2645 - if (!devlink_try_get(devlink)) 2646 - continue; 2647 - 2604 + devlinks_xa_for_each_registered_get(sock_net(msg->sk), index, devlink) { 2648 2605 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) || 2649 2606 !devlink->ops->sb_pool_get) 2650 2607 goto retry; ··· 2859 2822 int err = 0; 2860 2823 2861 2824 mutex_lock(&devlink_mutex); 2862 - xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { 2863 - if (!devlink_try_get(devlink)) 2864 - continue; 2865 - 2866 - if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) || 2867 - !devlink->ops->sb_port_pool_get) 2825 + devlinks_xa_for_each_registered_get(sock_net(msg->sk), index, devlink) { 2826 + if (!devlink->ops->sb_port_pool_get) 2868 2827 goto retry; 2869 2828 2870 2829 devl_lock(devlink); ··· 3104 3071 int err = 0; 3105 3072 3106 3073 mutex_lock(&devlink_mutex); 3107 - xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { 3108 - if (!devlink_try_get(devlink)) 3109 - continue; 3110 - 3111 - if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) || 3112 - !devlink->ops->sb_tc_pool_bind_get) 3074 + devlinks_xa_for_each_registered_get(sock_net(msg->sk), index, devlink) { 3075 + if (!devlink->ops->sb_tc_pool_bind_get) 3113 3076 goto retry; 3114 3077 3115 3078 devl_lock(devlink); ··· 5187 5158 int err = 0; 5188 5159 5189 5160 mutex_lock(&devlink_mutex); 5190 - xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { 5191 - if (!devlink_try_get(devlink)) 5192 - continue; 5193 - 5194 - if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 5195 - goto retry; 5196 - 5161 + devlinks_xa_for_each_registered_get(sock_net(msg->sk), index, devlink) { 5197 5162 devl_lock(devlink); 5198 5163 list_for_each_entry(param_item, &devlink->param_list, list) { 5199 5164 if (idx < start) { ··· 5209 5186 idx++; 5210 5187 } 5211 5188 devl_unlock(devlink); 5212 - retry: 5213 5189 devlink_put(devlink); 5214 5190 } 5215 5191 out: ··· 5415 5393 int err = 0; 5416 5394 5417 5395 mutex_lock(&devlink_mutex); 5418 - xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { 5419 - if (!devlink_try_get(devlink)) 5420 - continue; 5421 - 5422 - if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 5423 - goto retry; 5424 - 5396 + devlinks_xa_for_each_registered_get(sock_net(msg->sk), index, devlink) { 5425 5397 devl_lock(devlink); 5426 5398 list_for_each_entry(devlink_port, &devlink->port_list, list) { 5427 5399 list_for_each_entry(param_item, ··· 5442 5426 } 5443 5427 } 5444 5428 devl_unlock(devlink); 5445 - retry: 5446 5429 devlink_put(devlink); 5447 5430 } 5448 5431 out: ··· 5992 5977 int err = 0; 5993 5978 5994 5979 mutex_lock(&devlink_mutex); 5995 - xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { 5996 - if (!devlink_try_get(devlink)) 5997 - continue; 5998 - 5999 - if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 6000 - goto retry; 6001 - 5980 + devlinks_xa_for_each_registered_get(sock_net(msg->sk), index, devlink) { 6002 5981 err = devlink_nl_cmd_region_get_devlink_dumpit(msg, cb, devlink, 6003 5982 &idx, start); 6004 - retry: 6005 5983 devlink_put(devlink); 6006 5984 if (err) 6007 5985 goto out; ··· 6519 6511 int err = 0; 6520 6512 6521 6513 mutex_lock(&devlink_mutex); 6522 - xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { 6523 - if (!devlink_try_get(devlink)) 6524 - continue; 6525 - 6526 - if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 6527 - goto retry; 6528 - 6514 + devlinks_xa_for_each_registered_get(sock_net(msg->sk), index, devlink) { 6529 6515 if (idx < start || !devlink->ops->info_get) 6530 6516 goto inc; 6531 6517 ··· 6537 6535 } 6538 6536 inc: 6539 6537 idx++; 6540 - retry: 6541 6538 devlink_put(devlink); 6542 6539 } 6543 6540 mutex_unlock(&devlink_mutex); ··· 7692 7691 int err; 7693 7692 7694 7693 mutex_lock(&devlink_mutex); 7695 - xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { 7696 - if (!devlink_try_get(devlink)) 7697 - continue; 7698 - 7699 - if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 7700 - goto retry_rep; 7701 - 7694 + devlinks_xa_for_each_registered_get(sock_net(msg->sk), index, devlink) { 7702 7695 mutex_lock(&devlink->reporters_lock); 7703 7696 list_for_each_entry(reporter, &devlink->reporter_list, 7704 7697 list) { ··· 7712 7717 idx++; 7713 7718 } 7714 7719 mutex_unlock(&devlink->reporters_lock); 7715 - retry_rep: 7716 7720 devlink_put(devlink); 7717 7721 } 7718 7722 7719 - xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { 7720 - if (!devlink_try_get(devlink)) 7721 - continue; 7722 - 7723 - if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 7724 - goto retry_port; 7725 - 7723 + devlinks_xa_for_each_registered_get(sock_net(msg->sk), index, devlink) { 7726 7724 devl_lock(devlink); 7727 7725 list_for_each_entry(port, &devlink->port_list, list) { 7728 7726 mutex_lock(&port->reporters_lock); ··· 7740 7752 mutex_unlock(&port->reporters_lock); 7741 7753 } 7742 7754 devl_unlock(devlink); 7743 - retry_port: 7744 7755 devlink_put(devlink); 7745 7756 } 7746 7757 out: ··· 8278 8291 int err; 8279 8292 8280 8293 mutex_lock(&devlink_mutex); 8281 - xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { 8282 - if (!devlink_try_get(devlink)) 8283 - continue; 8284 - 8285 - if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 8286 - goto retry; 8287 - 8294 + devlinks_xa_for_each_registered_get(sock_net(msg->sk), index, devlink) { 8288 8295 devl_lock(devlink); 8289 8296 list_for_each_entry(trap_item, &devlink->trap_list, list) { 8290 8297 if (idx < start) { ··· 8298 8317 idx++; 8299 8318 } 8300 8319 devl_unlock(devlink); 8301 - retry: 8302 8320 devlink_put(devlink); 8303 8321 } 8304 8322 out: ··· 8498 8518 int err; 8499 8519 8500 8520 mutex_lock(&devlink_mutex); 8501 - xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { 8502 - if (!devlink_try_get(devlink)) 8503 - continue; 8504 - 8505 - if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 8506 - goto retry; 8507 - 8521 + devlinks_xa_for_each_registered_get(sock_net(msg->sk), index, devlink) { 8508 8522 devl_lock(devlink); 8509 8523 list_for_each_entry(group_item, &devlink->trap_group_list, 8510 8524 list) { ··· 8519 8545 idx++; 8520 8546 } 8521 8547 devl_unlock(devlink); 8522 - retry: 8523 8548 devlink_put(devlink); 8524 8549 } 8525 8550 out: ··· 8805 8832 int err; 8806 8833 8807 8834 mutex_lock(&devlink_mutex); 8808 - xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { 8809 - if (!devlink_try_get(devlink)) 8810 - continue; 8811 - 8812 - if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 8813 - goto retry; 8814 - 8835 + devlinks_xa_for_each_registered_get(sock_net(msg->sk), index, devlink) { 8815 8836 devl_lock(devlink); 8816 8837 list_for_each_entry(policer_item, &devlink->trap_policer_list, 8817 8838 list) { ··· 8826 8859 idx++; 8827 8860 } 8828 8861 devl_unlock(devlink); 8829 - retry: 8830 8862 devlink_put(devlink); 8831 8863 } 8832 8864 out: ··· 9555 9589 ASSERT_DEVLINK_NOT_REGISTERED(devlink); 9556 9590 /* Make sure that we are in .probe() routine */ 9557 9591 9558 - mutex_lock(&devlink_mutex); 9559 9592 xa_set_mark(&devlinks, devlink->index, DEVLINK_REGISTERED); 9560 9593 devlink_notify_register(devlink); 9561 - mutex_unlock(&devlink_mutex); 9562 9594 } 9563 9595 EXPORT_SYMBOL_GPL(devlink_register); 9564 9596 ··· 9573 9609 devlink_put(devlink); 9574 9610 wait_for_completion(&devlink->comp); 9575 9611 9576 - mutex_lock(&devlink_mutex); 9577 9612 devlink_notify_unregister(devlink); 9578 9613 xa_clear_mark(&devlinks, devlink->index, DEVLINK_REGISTERED); 9579 - mutex_unlock(&devlink_mutex); 9580 9614 } 9581 9615 EXPORT_SYMBOL_GPL(devlink_unregister); 9582 9616 ··· 10278 10316 void devlink_linecard_provision_clear(struct devlink_linecard *linecard) 10279 10317 { 10280 10318 mutex_lock(&linecard->state_lock); 10319 + WARN_ON(linecard->nested_devlink); 10281 10320 linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONED; 10282 10321 linecard->type = NULL; 10283 10322 devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); ··· 10297 10334 void devlink_linecard_provision_fail(struct devlink_linecard *linecard) 10298 10335 { 10299 10336 mutex_lock(&linecard->state_lock); 10337 + WARN_ON(linecard->nested_devlink); 10300 10338 linecard->state = DEVLINK_LINECARD_STATE_PROVISIONING_FAILED; 10301 10339 devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); 10302 10340 mutex_unlock(&linecard->state_lock); ··· 10344 10380 mutex_unlock(&linecard->state_lock); 10345 10381 } 10346 10382 EXPORT_SYMBOL_GPL(devlink_linecard_deactivate); 10383 + 10384 + /** 10385 + * devlink_linecard_nested_dl_set - Attach/detach nested devlink 10386 + * instance to linecard. 10387 + * 10388 + * @linecard: devlink linecard 10389 + * @nested_devlink: devlink instance to attach or NULL to detach 10390 + */ 10391 + void devlink_linecard_nested_dl_set(struct devlink_linecard *linecard, 10392 + struct devlink *nested_devlink) 10393 + { 10394 + mutex_lock(&linecard->state_lock); 10395 + linecard->nested_devlink = nested_devlink; 10396 + devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); 10397 + mutex_unlock(&linecard->state_lock); 10398 + } 10399 + EXPORT_SYMBOL_GPL(devlink_linecard_nested_dl_set); 10347 10400 10348 10401 int devl_sb_register(struct devlink *devlink, unsigned int sb_index, 10349 10402 u32 size, u16 ingress_pools_count, ··· 12262 12281 * all devlink instances from this namespace into init_net. 12263 12282 */ 12264 12283 mutex_lock(&devlink_mutex); 12265 - xa_for_each_marked(&devlinks, index, devlink, DEVLINK_REGISTERED) { 12266 - if (!devlink_try_get(devlink)) 12267 - continue; 12268 - 12269 - if (!net_eq(devlink_net(devlink), net)) 12270 - goto retry; 12271 - 12284 + devlinks_xa_for_each_registered_get(net, index, devlink) { 12272 12285 WARN_ON(!(devlink->features & DEVLINK_F_RELOAD)); 12273 12286 err = devlink_reload(devlink, &init_net, 12274 12287 DEVLINK_RELOAD_ACTION_DRIVER_REINIT, ··· 12270 12295 &actions_performed, NULL); 12271 12296 if (err && err != -EOPNOTSUPP) 12272 12297 pr_warn("Failed to reload devlink instance into init_net\n"); 12273 - retry: 12274 12298 devlink_put(devlink); 12275 12299 } 12276 12300 mutex_unlock(&devlink_mutex);