Merge tag 'mm-nonmm-stable-2023-11-02-14-08' of git://git.kernel.org/pub/scm/linux...
[linux-2.6-microblaze.git] / net / devlink / linecard.c
index 85c32c3..2f1c317 100644 (file)
@@ -6,6 +6,25 @@
 
 #include "devl_internal.h"
 
+struct devlink_linecard {
+       struct list_head list;
+       struct devlink *devlink;
+       unsigned int index;
+       const struct devlink_linecard_ops *ops;
+       void *priv;
+       enum devlink_linecard_state state;
+       struct mutex state_lock; /* Protects state */
+       const char *type;
+       struct devlink_linecard_type *types;
+       unsigned int types_count;
+       u32 rel_index;
+};
+
+unsigned int devlink_linecard_index(struct devlink_linecard *linecard)
+{
+       return linecard->index;
+}
+
 static struct devlink_linecard *
 devlink_linecard_get_by_index(struct devlink *devlink,
                              unsigned int linecard_index)
@@ -46,24 +65,6 @@ devlink_linecard_get_from_info(struct devlink *devlink, struct genl_info *info)
        return devlink_linecard_get_from_attrs(devlink, info->attrs);
 }
 
-static int devlink_nl_put_nested_handle(struct sk_buff *msg, struct devlink *devlink)
-{
-       struct nlattr *nested_attr;
-
-       nested_attr = nla_nest_start(msg, DEVLINK_ATTR_NESTED_DEVLINK);
-       if (!nested_attr)
-               return -EMSGSIZE;
-       if (devlink_nl_put_handle(msg, devlink))
-               goto nla_put_failure;
-
-       nla_nest_end(msg, nested_attr);
-       return 0;
-
-nla_put_failure:
-       nla_nest_cancel(msg, nested_attr);
-       return -EMSGSIZE;
-}
-
 struct devlink_linecard_type {
        const char *type;
        const void *priv;
@@ -111,8 +112,10 @@ static int devlink_nl_linecard_fill(struct sk_buff *msg,
                nla_nest_end(msg, attr);
        }
 
-       if (linecard->nested_devlink &&
-           devlink_nl_put_nested_handle(msg, linecard->nested_devlink))
+       if (devlink_rel_devlink_handle_put(msg, devlink,
+                                          linecard->rel_index,
+                                          DEVLINK_ATTR_NESTED_DEVLINK,
+                                          NULL))
                goto nla_put_failure;
 
        genlmsg_end(msg, hdr);
@@ -366,8 +369,7 @@ out:
        return err;
 }
 
-int devlink_nl_cmd_linecard_set_doit(struct sk_buff *skb,
-                                    struct genl_info *info)
+int devlink_nl_linecard_set_doit(struct sk_buff *skb, struct genl_info *info)
 {
        struct netlink_ext_ack *extack = info->extack;
        struct devlink *devlink = info->user_ptr[0];
@@ -521,7 +523,6 @@ EXPORT_SYMBOL_GPL(devlink_linecard_provision_set);
 void devlink_linecard_provision_clear(struct devlink_linecard *linecard)
 {
        mutex_lock(&linecard->state_lock);
-       WARN_ON(linecard->nested_devlink);
        linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONED;
        linecard->type = NULL;
        devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
@@ -540,7 +541,6 @@ EXPORT_SYMBOL_GPL(devlink_linecard_provision_clear);
 void devlink_linecard_provision_fail(struct devlink_linecard *linecard)
 {
        mutex_lock(&linecard->state_lock);
-       WARN_ON(linecard->nested_devlink);
        linecard->state = DEVLINK_LINECARD_STATE_PROVISIONING_FAILED;
        devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
        mutex_unlock(&linecard->state_lock);
@@ -588,6 +588,27 @@ void devlink_linecard_deactivate(struct devlink_linecard *linecard)
 }
 EXPORT_SYMBOL_GPL(devlink_linecard_deactivate);
 
+static void devlink_linecard_rel_notify_cb(struct devlink *devlink,
+                                          u32 linecard_index)
+{
+       struct devlink_linecard *linecard;
+
+       linecard = devlink_linecard_get_by_index(devlink, linecard_index);
+       if (!linecard)
+               return;
+       devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
+}
+
+static void devlink_linecard_rel_cleanup_cb(struct devlink *devlink,
+                                           u32 linecard_index, u32 rel_index)
+{
+       struct devlink_linecard *linecard;
+
+       linecard = devlink_linecard_get_by_index(devlink, linecard_index);
+       if (linecard && linecard->rel_index == rel_index)
+               linecard->rel_index = 0;
+}
+
 /**
  *     devlink_linecard_nested_dl_set - Attach/detach nested devlink
  *                                      instance to linecard.
@@ -595,12 +616,14 @@ EXPORT_SYMBOL_GPL(devlink_linecard_deactivate);
  *     @linecard: devlink linecard
  *     @nested_devlink: devlink instance to attach or NULL to detach
  */
-void devlink_linecard_nested_dl_set(struct devlink_linecard *linecard,
-                                   struct devlink *nested_devlink)
+int devlink_linecard_nested_dl_set(struct devlink_linecard *linecard,
+                                  struct devlink *nested_devlink)
 {
-       mutex_lock(&linecard->state_lock);
-       linecard->nested_devlink = nested_devlink;
-       devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
-       mutex_unlock(&linecard->state_lock);
+       return devlink_rel_nested_in_add(&linecard->rel_index,
+                                        linecard->devlink->index,
+                                        linecard->index,
+                                        devlink_linecard_rel_notify_cb,
+                                        devlink_linecard_rel_cleanup_cb,
+                                        nested_devlink);
 }
 EXPORT_SYMBOL_GPL(devlink_linecard_nested_dl_set);