devlink: pass devlink_port to port_split / port_unsplit callbacks
[linux-2.6-microblaze.git] / net / core / devlink.c
index fcd9f6d..f2a2770 100644 (file)
@@ -225,6 +225,33 @@ struct devlink *__must_check devlink_try_get(struct devlink *devlink)
        return NULL;
 }
 
+void devl_assert_locked(struct devlink *devlink)
+{
+       lockdep_assert_held(&devlink->lock);
+}
+EXPORT_SYMBOL_GPL(devl_assert_locked);
+
+#ifdef CONFIG_LOCKDEP
+/* For use in conjunction with LOCKDEP only e.g. rcu_dereference_protected() */
+bool devl_lock_is_held(struct devlink *devlink)
+{
+       return lockdep_is_held(&devlink->lock);
+}
+EXPORT_SYMBOL_GPL(devl_lock_is_held);
+#endif
+
+void devl_lock(struct devlink *devlink)
+{
+       mutex_lock(&devlink->lock);
+}
+EXPORT_SYMBOL_GPL(devl_lock);
+
+void devl_unlock(struct devlink *devlink)
+{
+       mutex_unlock(&devlink->lock);
+}
+EXPORT_SYMBOL_GPL(devl_unlock);
+
 static struct devlink *devlink_get_from_attrs(struct net *net,
                                              struct nlattr **attrs)
 {
@@ -1541,35 +1568,20 @@ static int devlink_nl_cmd_port_set_doit(struct sk_buff *skb,
        return 0;
 }
 
-static int devlink_port_split(struct devlink *devlink, u32 port_index,
-                             u32 count, struct netlink_ext_ack *extack)
-
-{
-       if (devlink->ops->port_split)
-               return devlink->ops->port_split(devlink, port_index, count,
-                                               extack);
-       return -EOPNOTSUPP;
-}
-
 static int devlink_nl_cmd_port_split_doit(struct sk_buff *skb,
                                          struct genl_info *info)
 {
+       struct devlink_port *devlink_port = info->user_ptr[1];
        struct devlink *devlink = info->user_ptr[0];
-       struct devlink_port *devlink_port;
-       u32 port_index;
        u32 count;
 
-       if (!info->attrs[DEVLINK_ATTR_PORT_INDEX] ||
-           !info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT])
+       if (!info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT])
                return -EINVAL;
+       if (!devlink->ops->port_split)
+               return -EOPNOTSUPP;
 
-       devlink_port = devlink_port_get_from_info(devlink, info);
-       port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
        count = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT]);
 
-       if (IS_ERR(devlink_port))
-               return -EINVAL;
-
        if (!devlink_port->attrs.splittable) {
                /* Split ports cannot be split. */
                if (devlink_port->attrs.split)
@@ -1584,29 +1596,19 @@ static int devlink_nl_cmd_port_split_doit(struct sk_buff *skb,
                return -EINVAL;
        }
 
-       return devlink_port_split(devlink, port_index, count, info->extack);
-}
-
-static int devlink_port_unsplit(struct devlink *devlink, u32 port_index,
-                               struct netlink_ext_ack *extack)
-
-{
-       if (devlink->ops->port_unsplit)
-               return devlink->ops->port_unsplit(devlink, port_index, extack);
-       return -EOPNOTSUPP;
+       return devlink->ops->port_split(devlink, devlink_port, count,
+                                       info->extack);
 }
 
 static int devlink_nl_cmd_port_unsplit_doit(struct sk_buff *skb,
                                            struct genl_info *info)
 {
+       struct devlink_port *devlink_port = info->user_ptr[1];
        struct devlink *devlink = info->user_ptr[0];
-       u32 port_index;
-
-       if (!info->attrs[DEVLINK_ATTR_PORT_INDEX])
-               return -EINVAL;
 
-       port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
-       return devlink_port_unsplit(devlink, port_index, info->extack);
+       if (!devlink->ops->port_unsplit)
+               return -EOPNOTSUPP;
+       return devlink->ops->port_unsplit(devlink, devlink_port, info->extack);
 }
 
 static int devlink_port_new_notifiy(struct devlink *devlink,
@@ -8645,14 +8647,14 @@ static const struct genl_small_ops devlink_nl_ops[] = {
                .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
                .doit = devlink_nl_cmd_port_split_doit,
                .flags = GENL_ADMIN_PERM,
-               .internal_flags = DEVLINK_NL_FLAG_NO_LOCK,
+               .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
        },
        {
                .cmd = DEVLINK_CMD_PORT_UNSPLIT,
                .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
                .doit = devlink_nl_cmd_port_unsplit_doit,
                .flags = GENL_ADMIN_PERM,
-               .internal_flags = DEVLINK_NL_FLAG_NO_LOCK,
+               .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
        },
        {
                .cmd = DEVLINK_CMD_PORT_NEW,
@@ -9249,6 +9251,32 @@ static void devlink_port_type_warn_cancel(struct devlink_port *devlink_port)
        cancel_delayed_work_sync(&devlink_port->type_warn_dw);
 }
 
+int devl_port_register(struct devlink *devlink,
+                      struct devlink_port *devlink_port,
+                      unsigned int port_index)
+{
+       lockdep_assert_held(&devlink->lock);
+
+       if (devlink_port_index_exists(devlink, port_index))
+               return -EEXIST;
+
+       WARN_ON(devlink_port->devlink);
+       devlink_port->devlink = devlink;
+       devlink_port->index = port_index;
+       spin_lock_init(&devlink_port->type_lock);
+       INIT_LIST_HEAD(&devlink_port->reporter_list);
+       mutex_init(&devlink_port->reporters_lock);
+       list_add_tail(&devlink_port->list, &devlink->port_list);
+       INIT_LIST_HEAD(&devlink_port->param_list);
+       INIT_LIST_HEAD(&devlink_port->region_list);
+
+       INIT_DELAYED_WORK(&devlink_port->type_warn_dw, &devlink_port_type_warn);
+       devlink_port_type_warn_schedule(devlink_port);
+       devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(devl_port_register);
+
 /**
  *     devlink_port_register - Register devlink port
  *
@@ -9266,29 +9294,28 @@ int devlink_port_register(struct devlink *devlink,
                          struct devlink_port *devlink_port,
                          unsigned int port_index)
 {
-       mutex_lock(&devlink->lock);
-       if (devlink_port_index_exists(devlink, port_index)) {
-               mutex_unlock(&devlink->lock);
-               return -EEXIST;
-       }
+       int err;
 
-       WARN_ON(devlink_port->devlink);
-       devlink_port->devlink = devlink;
-       devlink_port->index = port_index;
-       spin_lock_init(&devlink_port->type_lock);
-       INIT_LIST_HEAD(&devlink_port->reporter_list);
-       mutex_init(&devlink_port->reporters_lock);
-       list_add_tail(&devlink_port->list, &devlink->port_list);
-       INIT_LIST_HEAD(&devlink_port->param_list);
-       INIT_LIST_HEAD(&devlink_port->region_list);
+       mutex_lock(&devlink->lock);
+       err = devl_port_register(devlink, devlink_port, port_index);
        mutex_unlock(&devlink->lock);
-       INIT_DELAYED_WORK(&devlink_port->type_warn_dw, &devlink_port_type_warn);
-       devlink_port_type_warn_schedule(devlink_port);
-       devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
-       return 0;
+       return err;
 }
 EXPORT_SYMBOL_GPL(devlink_port_register);
 
+void devl_port_unregister(struct devlink_port *devlink_port)
+{
+       lockdep_assert_held(&devlink_port->devlink->lock);
+
+       devlink_port_type_warn_cancel(devlink_port);
+       devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_DEL);
+       list_del(&devlink_port->list);
+       WARN_ON(!list_empty(&devlink_port->reporter_list));
+       WARN_ON(!list_empty(&devlink_port->region_list));
+       mutex_destroy(&devlink_port->reporters_lock);
+}
+EXPORT_SYMBOL_GPL(devl_port_unregister);
+
 /**
  *     devlink_port_unregister - Unregister devlink port
  *
@@ -9298,14 +9325,9 @@ void devlink_port_unregister(struct devlink_port *devlink_port)
 {
        struct devlink *devlink = devlink_port->devlink;
 
-       devlink_port_type_warn_cancel(devlink_port);
-       devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_DEL);
        mutex_lock(&devlink->lock);
-       list_del(&devlink_port->list);
+       devl_port_unregister(devlink_port);
        mutex_unlock(&devlink->lock);
-       WARN_ON(!list_empty(&devlink_port->reporter_list));
-       WARN_ON(!list_empty(&devlink_port->region_list));
-       mutex_destroy(&devlink_port->reporters_lock);
 }
 EXPORT_SYMBOL_GPL(devlink_port_unregister);