~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/devlink/linecard.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-or-later
  2 /*
  3  * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
  4  * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com>
  5  */
  6 
  7 #include "devl_internal.h"
  8 
  9 struct devlink_linecard {
 10         struct list_head list;
 11         struct devlink *devlink;
 12         unsigned int index;
 13         const struct devlink_linecard_ops *ops;
 14         void *priv;
 15         enum devlink_linecard_state state;
 16         struct mutex state_lock; /* Protects state */
 17         const char *type;
 18         struct devlink_linecard_type *types;
 19         unsigned int types_count;
 20         u32 rel_index;
 21 };
 22 
 23 unsigned int devlink_linecard_index(struct devlink_linecard *linecard)
 24 {
 25         return linecard->index;
 26 }
 27 
 28 static struct devlink_linecard *
 29 devlink_linecard_get_by_index(struct devlink *devlink,
 30                               unsigned int linecard_index)
 31 {
 32         struct devlink_linecard *devlink_linecard;
 33 
 34         list_for_each_entry(devlink_linecard, &devlink->linecard_list, list) {
 35                 if (devlink_linecard->index == linecard_index)
 36                         return devlink_linecard;
 37         }
 38         return NULL;
 39 }
 40 
 41 static bool devlink_linecard_index_exists(struct devlink *devlink,
 42                                           unsigned int linecard_index)
 43 {
 44         return devlink_linecard_get_by_index(devlink, linecard_index);
 45 }
 46 
 47 static struct devlink_linecard *
 48 devlink_linecard_get_from_attrs(struct devlink *devlink, struct nlattr **attrs)
 49 {
 50         if (attrs[DEVLINK_ATTR_LINECARD_INDEX]) {
 51                 u32 linecard_index = nla_get_u32(attrs[DEVLINK_ATTR_LINECARD_INDEX]);
 52                 struct devlink_linecard *linecard;
 53 
 54                 linecard = devlink_linecard_get_by_index(devlink, linecard_index);
 55                 if (!linecard)
 56                         return ERR_PTR(-ENODEV);
 57                 return linecard;
 58         }
 59         return ERR_PTR(-EINVAL);
 60 }
 61 
 62 static struct devlink_linecard *
 63 devlink_linecard_get_from_info(struct devlink *devlink, struct genl_info *info)
 64 {
 65         return devlink_linecard_get_from_attrs(devlink, info->attrs);
 66 }
 67 
 68 struct devlink_linecard_type {
 69         const char *type;
 70         const void *priv;
 71 };
 72 
 73 static int devlink_nl_linecard_fill(struct sk_buff *msg,
 74                                     struct devlink *devlink,
 75                                     struct devlink_linecard *linecard,
 76                                     enum devlink_command cmd, u32 portid,
 77                                     u32 seq, int flags,
 78                                     struct netlink_ext_ack *extack)
 79 {
 80         struct devlink_linecard_type *linecard_type;
 81         struct nlattr *attr;
 82         void *hdr;
 83         int i;
 84 
 85         hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
 86         if (!hdr)
 87                 return -EMSGSIZE;
 88 
 89         if (devlink_nl_put_handle(msg, devlink))
 90                 goto nla_put_failure;
 91         if (nla_put_u32(msg, DEVLINK_ATTR_LINECARD_INDEX, linecard->index))
 92                 goto nla_put_failure;
 93         if (nla_put_u8(msg, DEVLINK_ATTR_LINECARD_STATE, linecard->state))
 94                 goto nla_put_failure;
 95         if (linecard->type &&
 96             nla_put_string(msg, DEVLINK_ATTR_LINECARD_TYPE, linecard->type))
 97                 goto nla_put_failure;
 98 
 99         if (linecard->types_count) {
100                 attr = nla_nest_start(msg,
101                                       DEVLINK_ATTR_LINECARD_SUPPORTED_TYPES);
102                 if (!attr)
103                         goto nla_put_failure;
104                 for (i = 0; i < linecard->types_count; i++) {
105                         linecard_type = &linecard->types[i];
106                         if (nla_put_string(msg, DEVLINK_ATTR_LINECARD_TYPE,
107                                            linecard_type->type)) {
108                                 nla_nest_cancel(msg, attr);
109                                 goto nla_put_failure;
110                         }
111                 }
112                 nla_nest_end(msg, attr);
113         }
114 
115         if (devlink_rel_devlink_handle_put(msg, devlink,
116                                            linecard->rel_index,
117                                            DEVLINK_ATTR_NESTED_DEVLINK,
118                                            NULL))
119                 goto nla_put_failure;
120 
121         genlmsg_end(msg, hdr);
122         return 0;
123 
124 nla_put_failure:
125         genlmsg_cancel(msg, hdr);
126         return -EMSGSIZE;
127 }
128 
129 static void devlink_linecard_notify(struct devlink_linecard *linecard,
130                                     enum devlink_command cmd)
131 {
132         struct devlink *devlink = linecard->devlink;
133         struct sk_buff *msg;
134         int err;
135 
136         WARN_ON(cmd != DEVLINK_CMD_LINECARD_NEW &&
137                 cmd != DEVLINK_CMD_LINECARD_DEL);
138 
139         if (!__devl_is_registered(devlink) || !devlink_nl_notify_need(devlink))
140                 return;
141 
142         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
143         if (!msg)
144                 return;
145 
146         err = devlink_nl_linecard_fill(msg, devlink, linecard, cmd, 0, 0, 0,
147                                        NULL);
148         if (err) {
149                 nlmsg_free(msg);
150                 return;
151         }
152 
153         devlink_nl_notify_send(devlink, msg);
154 }
155 
156 void devlink_linecards_notify_register(struct devlink *devlink)
157 {
158         struct devlink_linecard *linecard;
159 
160         list_for_each_entry(linecard, &devlink->linecard_list, list)
161                 devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
162 }
163 
164 void devlink_linecards_notify_unregister(struct devlink *devlink)
165 {
166         struct devlink_linecard *linecard;
167 
168         list_for_each_entry_reverse(linecard, &devlink->linecard_list, list)
169                 devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_DEL);
170 }
171 
172 int devlink_nl_linecard_get_doit(struct sk_buff *skb, struct genl_info *info)
173 {
174         struct devlink *devlink = info->user_ptr[0];
175         struct devlink_linecard *linecard;
176         struct sk_buff *msg;
177         int err;
178 
179         linecard = devlink_linecard_get_from_info(devlink, info);
180         if (IS_ERR(linecard))
181                 return PTR_ERR(linecard);
182 
183         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
184         if (!msg)
185                 return -ENOMEM;
186 
187         mutex_lock(&linecard->state_lock);
188         err = devlink_nl_linecard_fill(msg, devlink, linecard,
189                                        DEVLINK_CMD_LINECARD_NEW,
190                                        info->snd_portid, info->snd_seq, 0,
191                                        info->extack);
192         mutex_unlock(&linecard->state_lock);
193         if (err) {
194                 nlmsg_free(msg);
195                 return err;
196         }
197 
198         return genlmsg_reply(msg, info);
199 }
200 
201 static int devlink_nl_linecard_get_dump_one(struct sk_buff *msg,
202                                             struct devlink *devlink,
203                                             struct netlink_callback *cb,
204                                             int flags)
205 {
206         struct devlink_nl_dump_state *state = devlink_dump_state(cb);
207         struct devlink_linecard *linecard;
208         int idx = 0;
209         int err = 0;
210 
211         list_for_each_entry(linecard, &devlink->linecard_list, list) {
212                 if (idx < state->idx) {
213                         idx++;
214                         continue;
215                 }
216                 mutex_lock(&linecard->state_lock);
217                 err = devlink_nl_linecard_fill(msg, devlink, linecard,
218                                                DEVLINK_CMD_LINECARD_NEW,
219                                                NETLINK_CB(cb->skb).portid,
220                                                cb->nlh->nlmsg_seq, flags,
221                                                cb->extack);
222                 mutex_unlock(&linecard->state_lock);
223                 if (err) {
224                         state->idx = idx;
225                         break;
226                 }
227                 idx++;
228         }
229 
230         return err;
231 }
232 
233 int devlink_nl_linecard_get_dumpit(struct sk_buff *skb,
234                                    struct netlink_callback *cb)
235 {
236         return devlink_nl_dumpit(skb, cb, devlink_nl_linecard_get_dump_one);
237 }
238 
239 static struct devlink_linecard_type *
240 devlink_linecard_type_lookup(struct devlink_linecard *linecard,
241                              const char *type)
242 {
243         struct devlink_linecard_type *linecard_type;
244         int i;
245 
246         for (i = 0; i < linecard->types_count; i++) {
247                 linecard_type = &linecard->types[i];
248                 if (!strcmp(type, linecard_type->type))
249                         return linecard_type;
250         }
251         return NULL;
252 }
253 
254 static int devlink_linecard_type_set(struct devlink_linecard *linecard,
255                                      const char *type,
256                                      struct netlink_ext_ack *extack)
257 {
258         const struct devlink_linecard_ops *ops = linecard->ops;
259         struct devlink_linecard_type *linecard_type;
260         int err;
261 
262         mutex_lock(&linecard->state_lock);
263         if (linecard->state == DEVLINK_LINECARD_STATE_PROVISIONING) {
264                 NL_SET_ERR_MSG(extack, "Line card is currently being provisioned");
265                 err = -EBUSY;
266                 goto out;
267         }
268         if (linecard->state == DEVLINK_LINECARD_STATE_UNPROVISIONING) {
269                 NL_SET_ERR_MSG(extack, "Line card is currently being unprovisioned");
270                 err = -EBUSY;
271                 goto out;
272         }
273 
274         linecard_type = devlink_linecard_type_lookup(linecard, type);
275         if (!linecard_type) {
276                 NL_SET_ERR_MSG(extack, "Unsupported line card type provided");
277                 err = -EINVAL;
278                 goto out;
279         }
280 
281         if (linecard->state != DEVLINK_LINECARD_STATE_UNPROVISIONED &&
282             linecard->state != DEVLINK_LINECARD_STATE_PROVISIONING_FAILED) {
283                 NL_SET_ERR_MSG(extack, "Line card already provisioned");
284                 err = -EBUSY;
285                 /* Check if the line card is provisioned in the same
286                  * way the user asks. In case it is, make the operation
287                  * to return success.
288                  */
289                 if (ops->same_provision &&
290                     ops->same_provision(linecard, linecard->priv,
291                                         linecard_type->type,
292                                         linecard_type->priv))
293                         err = 0;
294                 goto out;
295         }
296 
297         linecard->state = DEVLINK_LINECARD_STATE_PROVISIONING;
298         linecard->type = linecard_type->type;
299         devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
300         mutex_unlock(&linecard->state_lock);
301         err = ops->provision(linecard, linecard->priv, linecard_type->type,
302                              linecard_type->priv, extack);
303         if (err) {
304                 /* Provisioning failed. Assume the linecard is unprovisioned
305                  * for future operations.
306                  */
307                 mutex_lock(&linecard->state_lock);
308                 linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONED;
309                 linecard->type = NULL;
310                 devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
311                 mutex_unlock(&linecard->state_lock);
312         }
313         return err;
314 
315 out:
316         mutex_unlock(&linecard->state_lock);
317         return err;
318 }
319 
320 static int devlink_linecard_type_unset(struct devlink_linecard *linecard,
321                                        struct netlink_ext_ack *extack)
322 {
323         int err;
324 
325         mutex_lock(&linecard->state_lock);
326         if (linecard->state == DEVLINK_LINECARD_STATE_PROVISIONING) {
327                 NL_SET_ERR_MSG(extack, "Line card is currently being provisioned");
328                 err = -EBUSY;
329                 goto out;
330         }
331         if (linecard->state == DEVLINK_LINECARD_STATE_UNPROVISIONING) {
332                 NL_SET_ERR_MSG(extack, "Line card is currently being unprovisioned");
333                 err = -EBUSY;
334                 goto out;
335         }
336         if (linecard->state == DEVLINK_LINECARD_STATE_PROVISIONING_FAILED) {
337                 linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONED;
338                 linecard->type = NULL;
339                 devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
340                 err = 0;
341                 goto out;
342         }
343 
344         if (linecard->state == DEVLINK_LINECARD_STATE_UNPROVISIONED) {
345                 NL_SET_ERR_MSG(extack, "Line card is not provisioned");
346                 err = 0;
347                 goto out;
348         }
349         linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONING;
350         devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
351         mutex_unlock(&linecard->state_lock);
352         err = linecard->ops->unprovision(linecard, linecard->priv,
353                                          extack);
354         if (err) {
355                 /* Unprovisioning failed. Assume the linecard is unprovisioned
356                  * for future operations.
357                  */
358                 mutex_lock(&linecard->state_lock);
359                 linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONED;
360                 linecard->type = NULL;
361                 devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
362                 mutex_unlock(&linecard->state_lock);
363         }
364         return err;
365 
366 out:
367         mutex_unlock(&linecard->state_lock);
368         return err;
369 }
370 
371 int devlink_nl_linecard_set_doit(struct sk_buff *skb, struct genl_info *info)
372 {
373         struct netlink_ext_ack *extack = info->extack;
374         struct devlink *devlink = info->user_ptr[0];
375         struct devlink_linecard *linecard;
376         int err;
377 
378         linecard = devlink_linecard_get_from_info(devlink, info);
379         if (IS_ERR(linecard))
380                 return PTR_ERR(linecard);
381 
382         if (info->attrs[DEVLINK_ATTR_LINECARD_TYPE]) {
383                 const char *type;
384 
385                 type = nla_data(info->attrs[DEVLINK_ATTR_LINECARD_TYPE]);
386                 if (strcmp(type, "")) {
387                         err = devlink_linecard_type_set(linecard, type, extack);
388                         if (err)
389                                 return err;
390                 } else {
391                         err = devlink_linecard_type_unset(linecard, extack);
392                         if (err)
393                                 return err;
394                 }
395         }
396 
397         return 0;
398 }
399 
400 static int devlink_linecard_types_init(struct devlink_linecard *linecard)
401 {
402         struct devlink_linecard_type *linecard_type;
403         unsigned int count;
404         int i;
405 
406         count = linecard->ops->types_count(linecard, linecard->priv);
407         linecard->types = kmalloc_array(count, sizeof(*linecard_type),
408                                         GFP_KERNEL);
409         if (!linecard->types)
410                 return -ENOMEM;
411         linecard->types_count = count;
412 
413         for (i = 0; i < count; i++) {
414                 linecard_type = &linecard->types[i];
415                 linecard->ops->types_get(linecard, linecard->priv, i,
416                                          &linecard_type->type,
417                                          &linecard_type->priv);
418         }
419         return 0;
420 }
421 
422 static void devlink_linecard_types_fini(struct devlink_linecard *linecard)
423 {
424         kfree(linecard->types);
425 }
426 
427 /**
428  *      devl_linecard_create - Create devlink linecard
429  *
430  *      @devlink: devlink
431  *      @linecard_index: driver-specific numerical identifier of the linecard
432  *      @ops: linecards ops
433  *      @priv: user priv pointer
434  *
435  *      Create devlink linecard instance with provided linecard index.
436  *      Caller can use any indexing, even hw-related one.
437  *
438  *      Return: Line card structure or an ERR_PTR() encoded error code.
439  */
440 struct devlink_linecard *
441 devl_linecard_create(struct devlink *devlink, unsigned int linecard_index,
442                      const struct devlink_linecard_ops *ops, void *priv)
443 {
444         struct devlink_linecard *linecard;
445         int err;
446 
447         if (WARN_ON(!ops || !ops->provision || !ops->unprovision ||
448                     !ops->types_count || !ops->types_get))
449                 return ERR_PTR(-EINVAL);
450 
451         if (devlink_linecard_index_exists(devlink, linecard_index))
452                 return ERR_PTR(-EEXIST);
453 
454         linecard = kzalloc(sizeof(*linecard), GFP_KERNEL);
455         if (!linecard)
456                 return ERR_PTR(-ENOMEM);
457 
458         linecard->devlink = devlink;
459         linecard->index = linecard_index;
460         linecard->ops = ops;
461         linecard->priv = priv;
462         linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONED;
463         mutex_init(&linecard->state_lock);
464 
465         err = devlink_linecard_types_init(linecard);
466         if (err) {
467                 mutex_destroy(&linecard->state_lock);
468                 kfree(linecard);
469                 return ERR_PTR(err);
470         }
471 
472         list_add_tail(&linecard->list, &devlink->linecard_list);
473         devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
474         return linecard;
475 }
476 EXPORT_SYMBOL_GPL(devl_linecard_create);
477 
478 /**
479  *      devl_linecard_destroy - Destroy devlink linecard
480  *
481  *      @linecard: devlink linecard
482  */
483 void devl_linecard_destroy(struct devlink_linecard *linecard)
484 {
485         devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_DEL);
486         list_del(&linecard->list);
487         devlink_linecard_types_fini(linecard);
488         mutex_destroy(&linecard->state_lock);
489         kfree(linecard);
490 }
491 EXPORT_SYMBOL_GPL(devl_linecard_destroy);
492 
493 /**
494  *      devlink_linecard_provision_set - Set provisioning on linecard
495  *
496  *      @linecard: devlink linecard
497  *      @type: linecard type
498  *
499  *      This is either called directly from the provision() op call or
500  *      as a result of the provision() op call asynchronously.
501  */
502 void devlink_linecard_provision_set(struct devlink_linecard *linecard,
503                                     const char *type)
504 {
505         mutex_lock(&linecard->state_lock);
506         WARN_ON(linecard->type && strcmp(linecard->type, type));
507         linecard->state = DEVLINK_LINECARD_STATE_PROVISIONED;
508         linecard->type = type;
509         devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
510         mutex_unlock(&linecard->state_lock);
511 }
512 EXPORT_SYMBOL_GPL(devlink_linecard_provision_set);
513 
514 /**
515  *      devlink_linecard_provision_clear - Clear provisioning on linecard
516  *
517  *      @linecard: devlink linecard
518  *
519  *      This is either called directly from the unprovision() op call or
520  *      as a result of the unprovision() op call asynchronously.
521  */
522 void devlink_linecard_provision_clear(struct devlink_linecard *linecard)
523 {
524         mutex_lock(&linecard->state_lock);
525         linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONED;
526         linecard->type = NULL;
527         devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
528         mutex_unlock(&linecard->state_lock);
529 }
530 EXPORT_SYMBOL_GPL(devlink_linecard_provision_clear);
531 
532 /**
533  *      devlink_linecard_provision_fail - Fail provisioning on linecard
534  *
535  *      @linecard: devlink linecard
536  *
537  *      This is either called directly from the provision() op call or
538  *      as a result of the provision() op call asynchronously.
539  */
540 void devlink_linecard_provision_fail(struct devlink_linecard *linecard)
541 {
542         mutex_lock(&linecard->state_lock);
543         linecard->state = DEVLINK_LINECARD_STATE_PROVISIONING_FAILED;
544         devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
545         mutex_unlock(&linecard->state_lock);
546 }
547 EXPORT_SYMBOL_GPL(devlink_linecard_provision_fail);
548 
549 /**
550  *      devlink_linecard_activate - Set linecard active
551  *
552  *      @linecard: devlink linecard
553  */
554 void devlink_linecard_activate(struct devlink_linecard *linecard)
555 {
556         mutex_lock(&linecard->state_lock);
557         WARN_ON(linecard->state != DEVLINK_LINECARD_STATE_PROVISIONED);
558         linecard->state = DEVLINK_LINECARD_STATE_ACTIVE;
559         devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
560         mutex_unlock(&linecard->state_lock);
561 }
562 EXPORT_SYMBOL_GPL(devlink_linecard_activate);
563 
564 /**
565  *      devlink_linecard_deactivate - Set linecard inactive
566  *
567  *      @linecard: devlink linecard
568  */
569 void devlink_linecard_deactivate(struct devlink_linecard *linecard)
570 {
571         mutex_lock(&linecard->state_lock);
572         switch (linecard->state) {
573         case DEVLINK_LINECARD_STATE_ACTIVE:
574                 linecard->state = DEVLINK_LINECARD_STATE_PROVISIONED;
575                 devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
576                 break;
577         case DEVLINK_LINECARD_STATE_UNPROVISIONING:
578                 /* Line card is being deactivated as part
579                  * of unprovisioning flow.
580                  */
581                 break;
582         default:
583                 WARN_ON(1);
584                 break;
585         }
586         mutex_unlock(&linecard->state_lock);
587 }
588 EXPORT_SYMBOL_GPL(devlink_linecard_deactivate);
589 
590 static void devlink_linecard_rel_notify_cb(struct devlink *devlink,
591                                            u32 linecard_index)
592 {
593         struct devlink_linecard *linecard;
594 
595         linecard = devlink_linecard_get_by_index(devlink, linecard_index);
596         if (!linecard)
597                 return;
598         devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
599 }
600 
601 static void devlink_linecard_rel_cleanup_cb(struct devlink *devlink,
602                                             u32 linecard_index, u32 rel_index)
603 {
604         struct devlink_linecard *linecard;
605 
606         linecard = devlink_linecard_get_by_index(devlink, linecard_index);
607         if (linecard && linecard->rel_index == rel_index)
608                 linecard->rel_index = 0;
609 }
610 
611 /**
612  *      devlink_linecard_nested_dl_set - Attach/detach nested devlink
613  *                                       instance to linecard.
614  *
615  *      @linecard: devlink linecard
616  *      @nested_devlink: devlink instance to attach or NULL to detach
617  */
618 int devlink_linecard_nested_dl_set(struct devlink_linecard *linecard,
619                                    struct devlink *nested_devlink)
620 {
621         return devlink_rel_nested_in_add(&linecard->rel_index,
622                                          linecard->devlink->index,
623                                          linecard->index,
624                                          devlink_linecard_rel_notify_cb,
625                                          devlink_linecard_rel_cleanup_cb,
626                                          nested_devlink);
627 }
628 EXPORT_SYMBOL_GPL(devlink_linecard_nested_dl_set);
629 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php