| @@ -83,10 +83,11 @@ struct devlink_linecard { · 82 unmodified lines |
| 83 | const struct devlink_linecard_ops *ops; | 83 | const struct devlink_linecard_ops *ops; |
| 84 | void *priv; | 84 | void *priv; |
| 85 | enum devlink_linecard_state state; | 85 | enum devlink_linecard_state state; |
| 86 | struct mutex state_lock; /* Protects state */ | 86 | struct mutex state_lock; /* Protects state and device_list */ |
| 87 | const char *type; | 87 | const char *type; |
| 88 | struct devlink_linecard_type *types; | 88 | struct devlink_linecard_type *types; |
| 89 | unsigned int types_count; | 89 | unsigned int types_count; |
| | 90 | struct list_head device_list; |
| 90 | }; | 91 | }; |
| 91 | | 92 | |
| 92 | /** | 93 | /** |
| @@ -2058,6 +2059,55 @@ struct devlink_linecard_type { · 1965 unmodified lines |
| 2058 | const void *priv; | 2059 | const void *priv; |
| 2059 | }; | 2060 | }; |
| 2060 | | 2061 | |
| | 2062 | struct devlink_linecard_device { |
| | 2063 | struct list_head list; |
| | 2064 | unsigned int index; |
| | 2065 | }; |
| | 2066 | |
| | 2067 | static int |
| | 2068 | devlink_nl_linecard_device_fill(struct sk_buff *msg, |
| | 2069 | struct devlink_linecard_device *linecard_device) |
| | 2070 | { |
| | 2071 | struct nlattr *attr; |
| | 2072 | |
| | 2073 | attr = nla_nest_start(msg, DEVLINK_ATTR_LINECARD_DEVICE); |
| | 2074 | if (!attr) |
| | 2075 | return -EMSGSIZE; |
| | 2076 | if (nla_put_u32(msg, DEVLINK_ATTR_LINECARD_DEVICE_INDEX, |
| | 2077 | linecard_device->index)) { |
| | 2078 | nla_nest_cancel(msg, attr); |
| | 2079 | return -EMSGSIZE; |
| | 2080 | } |
| | 2081 | nla_nest_end(msg, attr); |
| | 2082 | |
| | 2083 | return 0; |
| | 2084 | } |
| | 2085 | |
| | 2086 | static int devlink_nl_linecard_devices_fill(struct sk_buff *msg, |
| | 2087 | struct devlink_linecard *linecard) |
| | 2088 | { |
| | 2089 | struct devlink_linecard_device *linecard_device; |
| | 2090 | struct nlattr *attr; |
| | 2091 | int err; |
| | 2092 | |
| | 2093 | if (list_empty(&linecard->device_list)) |
| | 2094 | return 0; |
| | 2095 | |
| | 2096 | attr = nla_nest_start(msg, DEVLINK_ATTR_LINECARD_DEVICE_LIST); |
| | 2097 | if (!attr) |
| | 2098 | return -EMSGSIZE; |
| | 2099 | list_for_each_entry(linecard_device, &linecard->device_list, list) { |
| | 2100 | err = devlink_nl_linecard_device_fill(msg, linecard_device); |
| | 2101 | if (err) { |
| | 2102 | nla_nest_cancel(msg, attr); |
| | 2103 | return err; |
| | 2104 | } |
| | 2105 | } |
| | 2106 | nla_nest_end(msg, attr); |
| | 2107 | |
| | 2108 | return 0; |
| | 2109 | } |
| | 2110 | |
| 2061 | static int devlink_nl_linecard_fill(struct sk_buff *msg, | 2111 | static int devlink_nl_linecard_fill(struct sk_buff *msg, |
| 2062 | struct devlink *devlink, | 2112 | struct devlink *devlink, |
| 2063 | struct devlink_linecard *linecard, | 2113 | struct devlink_linecard *linecard, |
| @@ -2068,6 +2118,7 @@ static int devlink_nl_linecard_fill(struct sk_buff *msg, · 4 unmodified lines |
| 2068 | struct devlink_linecard_type *linecard_type; | 2118 | struct devlink_linecard_type *linecard_type; |
| 2069 | struct nlattr *attr; | 2119 | struct nlattr *attr; |
| 2070 | void *hdr; | 2120 | void *hdr; |
| | 2121 | int err; |
| 2071 | int i; | 2122 | int i; |
| 2072 | | 2123 | |
| 2073 | hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); | 2124 | hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); |
| @@ -2100,6 +2151,10 @@ static int devlink_nl_linecard_fill(struct sk_buff *msg, · 26 unmodified lines |
| 2100 | nla_nest_end(msg, attr); | 2151 | nla_nest_end(msg, attr); |
| 2101 | } | 2152 | } |
| 2102 | | 2153 | |
| | 2154 | err = devlink_nl_linecard_devices_fill(msg, linecard); |
| | 2155 | if (err) |
| | 2156 | goto nla_put_failure; |
| | 2157 | |
| 2103 | genlmsg_end(msg, hdr); | 2158 | genlmsg_end(msg, hdr); |
| 2104 | return 0; | 2159 | return 0; |
| 2105 | | 2160 | |
| @@ -10264,6 +10319,7 @@ devlink_linecard_create(struct devlink *devlink, unsigned int linecard_index, · 8158 unmodified lines |
| 10264 | linecard->priv = priv; | 10319 | linecard->priv = priv; |
| 10265 | linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONED; | 10320 | linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONED; |
| 10266 | mutex_init(&linecard->state_lock); | 10321 | mutex_init(&linecard->state_lock); |
| | 10322 | INIT_LIST_HEAD(&linecard->device_list); |
| 10267 | | 10323 | |
| 10268 | err = devlink_linecard_types_init(linecard); | 10324 | err = devlink_linecard_types_init(linecard); |
| 10269 | if (err) { | 10325 | if (err) { |
| @@ -10291,6 +10347,7 @@ void devlink_linecard_destroy(struct devlink_linecard *linecard) · 21 unmodified lines |
| 10291 | struct devlink *devlink = linecard->devlink; | 10347 | struct devlink *devlink = linecard->devlink; |
| 10292 | | 10348 | |
| 10293 | devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_DEL); | 10349 | devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_DEL); |
| | 10350 | WARN_ON(!list_empty(&linecard->device_list)); |
| 10294 | mutex_lock(&devlink->linecards_lock); | 10351 | mutex_lock(&devlink->linecards_lock); |
| 10295 | list_del(&linecard->list); | 10352 | list_del(&linecard->list); |
| 10296 | devlink_linecard_types_fini(linecard); | 10353 | devlink_linecard_types_fini(linecard); |
| @@ -10299,6 +10356,50 @@ void devlink_linecard_destroy(struct devlink_linecard *linecard) · 2 unmodified lines |
| 10299 | } | 10356 | } |
| 10300 | EXPORT_SYMBOL_GPL(devlink_linecard_destroy); | 10357 | EXPORT_SYMBOL_GPL(devlink_linecard_destroy); |
| 10301 | | 10358 | |
| | 10359 | /** |
| | 10360 | * devlink_linecard_device_create - Create a device on linecard |
| | 10361 | * |
| | 10362 | * @linecard: devlink linecard |
| | 10363 | * @device_index: index of the linecard device |
| | 10364 | * |
| | 10365 | * Return: Line card device structure or an ERR_PTR() encoded error code. |
| | 10366 | */ |
| | 10367 | struct devlink_linecard_device * |
| | 10368 | devlink_linecard_device_create(struct devlink_linecard *linecard, |
| | 10369 | unsigned int device_index) |
| | 10370 | { |
| | 10371 | struct devlink_linecard_device *linecard_device; |
| | 10372 | |
| | 10373 | linecard_device = kzalloc(sizeof(*linecard_device), GFP_KERNEL); |
| | 10374 | if (!linecard_device) |
| | 10375 | return ERR_PTR(-ENOMEM); |
| | 10376 | linecard_device->index = device_index; |
| | 10377 | mutex_lock(&linecard->state_lock); |
| | 10378 | list_add_tail(&linecard_device->list, &linecard->device_list); |
| | 10379 | devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); |
| | 10380 | mutex_unlock(&linecard->state_lock); |
| | 10381 | return linecard_device; |
| | 10382 | } |
| | 10383 | EXPORT_SYMBOL_GPL(devlink_linecard_device_create); |
| | 10384 | |
| | 10385 | /** |
| | 10386 | * devlink_linecard_device_destroy - Destroy device on linecard |
| | 10387 | * |
| | 10388 | * @linecard: devlink linecard |
| | 10389 | * @linecard_device: devlink linecard device |
| | 10390 | */ |
| | 10391 | void |
| | 10392 | devlink_linecard_device_destroy(struct devlink_linecard *linecard, |
| | 10393 | struct devlink_linecard_device *linecard_device) |
| | 10394 | { |
| | 10395 | mutex_lock(&linecard->state_lock); |
| | 10396 | list_del(&linecard_device->list); |
| | 10397 | devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); |
| | 10398 | mutex_unlock(&linecard->state_lock); |
| | 10399 | kfree(linecard_device); |
| | 10400 | } |
| | 10401 | EXPORT_SYMBOL_GPL(devlink_linecard_device_destroy); |
| | 10402 | |
| 10302 | /** | 10403 | /** |
| 10303 | * devlink_linecard_provision_set - Set provisioning on linecard | 10404 | * devlink_linecard_provision_set - Set provisioning on linecard |
| 10304 | * | 10405 | * |
| @@ -10331,6 +10432,7 @@ EXPORT_SYMBOL_GPL(devlink_linecard_provision_set); · 26 unmodified lines |
| 10331 | void devlink_linecard_provision_clear(struct devlink_linecard *linecard) | 10432 | void devlink_linecard_provision_clear(struct devlink_linecard *linecard) |
| 10332 | { | 10433 | { |
| 10333 | mutex_lock(&linecard->state_lock); | 10434 | mutex_lock(&linecard->state_lock); |
| | 10435 | WARN_ON(!list_empty(&linecard->device_list)); |
| 10334 | linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONED; | 10436 | linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONED; |
| 10335 | linecard->type = NULL; | 10437 | linecard->type = NULL; |
| 10336 | devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); | 10438 | devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW); |