History

devlink: introduce line card devices support

Line card can contain one or more devices that makes sense to make visible to the user. For example, this can be a gearbox with flash memory, which could be updated. Provide the driver possibility to attach such devices to a line card and expose those to user. Example: $ devlink lc show pci/0000:01:00.0 lc 8 pci/0000:01:00.0: lc 8 state active type 16x100G supported_types: 16x100G devices: device 0 device 1 device 2 device 3

Jiri Pirko committed 4 years ago

Commit 8d92e4f1 parent cfc1d913 files · +113 −1Browse files

Unified · Split

3 files
  1. include/net/devlink.h +7 −0
  2. include/uapi/linux/devlink.h +3 −0
  3. net/core/devlink.c +103 −1
include/net/devlink.h+7−0
@@ -1578,6 +1578,13 @@ struct devlink_linecard * · 1577 unmodified lines
1578devlink_linecard_create(struct devlink *devlink, unsigned int linecard_index,1578devlink_linecard_create(struct devlink *devlink, unsigned int linecard_index,
1579 const struct devlink_linecard_ops *ops, void *priv);1579 const struct devlink_linecard_ops *ops, void *priv);
1580void devlink_linecard_destroy(struct devlink_linecard *linecard);1580void devlink_linecard_destroy(struct devlink_linecard *linecard);
1581struct devlink_linecard_device;
1582struct devlink_linecard_device *
1583devlink_linecard_device_create(struct devlink_linecard *linecard,
1584 unsigned int device_index);
1585void
1586devlink_linecard_device_destroy(struct devlink_linecard *linecard,
1587 struct devlink_linecard_device *linecard_device);
1581void devlink_linecard_provision_set(struct devlink_linecard *linecard,1588void devlink_linecard_provision_set(struct devlink_linecard *linecard,
1582 const char *type);1589 const char *type);
1583void devlink_linecard_provision_clear(struct devlink_linecard *linecard);1590void devlink_linecard_provision_clear(struct devlink_linecard *linecard);
include/uapi/linux/devlink.h+3−0
@@ -575,6 +575,9 @@ enum devlink_attr { · 574 unmodified lines
575 DEVLINK_ATTR_LINECARD_STATE, /* u8 */575 DEVLINK_ATTR_LINECARD_STATE, /* u8 */
576 DEVLINK_ATTR_LINECARD_TYPE, /* string */576 DEVLINK_ATTR_LINECARD_TYPE, /* string */
577 DEVLINK_ATTR_LINECARD_SUPPORTED_TYPES, /* nested */577 DEVLINK_ATTR_LINECARD_SUPPORTED_TYPES, /* nested */
578 DEVLINK_ATTR_LINECARD_DEVICE_LIST, /* nested */
579 DEVLINK_ATTR_LINECARD_DEVICE, /* nested */
580 DEVLINK_ATTR_LINECARD_DEVICE_INDEX, /* u32 */
578 581
579 /* add new attributes above here, update the policy in devlink.c */582 /* add new attributes above here, update the policy in devlink.c */
580 583
net/core/devlink.c+103−1
@@ -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
2062struct devlink_linecard_device {
2063 struct list_head list;
2064 unsigned int index;
2065};
2066
2067static int
2068devlink_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
2086static 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
2061static int devlink_nl_linecard_fill(struct sk_buff *msg,2111static 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}
10300EXPORT_SYMBOL_GPL(devlink_linecard_destroy);10357EXPORT_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 */
10367struct devlink_linecard_device *
10368devlink_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}
10383EXPORT_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 */
10391void
10392devlink_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}
10401EXPORT_SYMBOL_GPL(devlink_linecard_device_destroy);
10402
10302/**10403/**
10303 * devlink_linecard_provision_set - Set provisioning on linecard10404 * devlink_linecard_provision_set - Set provisioning on linecard
10304 *10405 *
@@ -10331,6 +10432,7 @@ EXPORT_SYMBOL_GPL(devlink_linecard_provision_set); · 26 unmodified lines
10331void devlink_linecard_provision_clear(struct devlink_linecard *linecard)10432void 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);