}
 EXPORT_SYMBOL_GPL(devlink_net);
 
+static void devlink_put(struct devlink *devlink)
+{
+       if (refcount_dec_and_test(&devlink->refcount))
+               complete(&devlink->comp);
+}
+
+static bool __must_check devlink_try_get(struct devlink *devlink)
+{
+       return refcount_inc_not_zero(&devlink->refcount);
+}
+
 static struct devlink *devlink_get_from_attrs(struct net *net,
                                              struct nlattr **attrs)
 {
        struct devlink *devlink;
+       bool found = false;
        char *busname;
        char *devname;
 
        list_for_each_entry(devlink, &devlink_list, list) {
                if (strcmp(devlink->dev->bus->name, busname) == 0 &&
                    strcmp(dev_name(devlink->dev), devname) == 0 &&
-                   net_eq(devlink_net(devlink), net))
-                       return devlink;
+                   net_eq(devlink_net(devlink), net)) {
+                       found = true;
+                       break;
+               }
        }
 
-       return ERR_PTR(-ENODEV);
-}
+       if (!found || !devlink_try_get(devlink))
+               devlink = ERR_PTR(-ENODEV);
 
-static struct devlink *devlink_get_from_info(struct genl_info *info)
-{
-       return devlink_get_from_attrs(genl_info_net(info), info->attrs);
+       return devlink;
 }
 
 static struct devlink_port *devlink_port_get_by_index(struct devlink *devlink,
        int err;
 
        mutex_lock(&devlink_mutex);
-       devlink = devlink_get_from_info(info);
+       devlink = devlink_get_from_attrs(genl_info_net(info), info->attrs);
        if (IS_ERR(devlink)) {
                mutex_unlock(&devlink_mutex);
                return PTR_ERR(devlink);
 unlock:
        if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK)
                mutex_unlock(&devlink->lock);
+       devlink_put(devlink);
        mutex_unlock(&devlink_mutex);
        return err;
 }
        devlink = info->user_ptr[0];
        if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK)
                mutex_unlock(&devlink->lock);
+       devlink_put(devlink);
        mutex_unlock(&devlink_mutex);
 }
 
 
        mutex_lock(&devlink_mutex);
        list_for_each_entry(devlink, &devlink_list, list) {
-               if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
+               if (!devlink_try_get(devlink))
                        continue;
+
+               if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
+                       goto retry;
+
                mutex_lock(&devlink->lock);
                list_for_each_entry(devlink_rate, &devlink->rate_list, list) {
                        enum devlink_command cmd = DEVLINK_CMD_RATE_NEW;
                                                   NLM_F_MULTI, NULL);
                        if (err) {
                                mutex_unlock(&devlink->lock);
+                               devlink_put(devlink);
                                goto out;
                        }
                        idx++;
                }
                mutex_unlock(&devlink->lock);
+retry:
+               devlink_put(devlink);
        }
 out:
        mutex_unlock(&devlink_mutex);
 
        mutex_lock(&devlink_mutex);
        list_for_each_entry(devlink, &devlink_list, list) {
-               if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
+               if (!devlink_try_get(devlink))
                        continue;
+
+               if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) {
+                       devlink_put(devlink);
+                       continue;
+               }
+
                if (idx < start) {
                        idx++;
+                       devlink_put(devlink);
                        continue;
                }
+
                err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW,
                                      NETLINK_CB(cb->skb).portid,
                                      cb->nlh->nlmsg_seq, NLM_F_MULTI);
+               devlink_put(devlink);
                if (err)
                        goto out;
                idx++;
 
        mutex_lock(&devlink_mutex);
        list_for_each_entry(devlink, &devlink_list, list) {
-               if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
+               if (!devlink_try_get(devlink))
                        continue;
+
+               if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
+                       goto retry;
+
                mutex_lock(&devlink->lock);
                list_for_each_entry(devlink_port, &devlink->port_list, list) {
                        if (idx < start) {
                                                   NLM_F_MULTI, cb->extack);
                        if (err) {
                                mutex_unlock(&devlink->lock);
+                               devlink_put(devlink);
                                goto out;
                        }
                        idx++;
                }
                mutex_unlock(&devlink->lock);
+retry:
+               devlink_put(devlink);
        }
 out:
        mutex_unlock(&devlink_mutex);
 
        mutex_lock(&devlink_mutex);
        list_for_each_entry(devlink, &devlink_list, list) {
-               if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
+               if (!devlink_try_get(devlink))
                        continue;
+
+               if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
+                       goto retry;
+
                mutex_lock(&devlink->lock);
                list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
                        if (idx < start) {
                                                 NLM_F_MULTI);
                        if (err) {
                                mutex_unlock(&devlink->lock);
+                               devlink_put(devlink);
                                goto out;
                        }
                        idx++;
                }
                mutex_unlock(&devlink->lock);
+retry:
+               devlink_put(devlink);
        }
 out:
        mutex_unlock(&devlink_mutex);
 
        mutex_lock(&devlink_mutex);
        list_for_each_entry(devlink, &devlink_list, list) {
+               if (!devlink_try_get(devlink))
+                       continue;
+
                if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) ||
                    !devlink->ops->sb_pool_get)
-                       continue;
+                       goto retry;
+
                mutex_lock(&devlink->lock);
                list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
                        err = __sb_pool_get_dumpit(msg, start, &idx, devlink,
                                err = 0;
                        } else if (err) {
                                mutex_unlock(&devlink->lock);
+                               devlink_put(devlink);
                                goto out;
                        }
                }
                mutex_unlock(&devlink->lock);
+retry:
+               devlink_put(devlink);
        }
 out:
        mutex_unlock(&devlink_mutex);
 
        mutex_lock(&devlink_mutex);
        list_for_each_entry(devlink, &devlink_list, list) {
+               if (!devlink_try_get(devlink))
+                       continue;
+
                if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) ||
                    !devlink->ops->sb_port_pool_get)
-                       continue;
+                       goto retry;
+
                mutex_lock(&devlink->lock);
                list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
                        err = __sb_port_pool_get_dumpit(msg, start, &idx,
                                err = 0;
                        } else if (err) {
                                mutex_unlock(&devlink->lock);
+                               devlink_put(devlink);
                                goto out;
                        }
                }
                mutex_unlock(&devlink->lock);
+retry:
+               devlink_put(devlink);
        }
 out:
        mutex_unlock(&devlink_mutex);
 
        mutex_lock(&devlink_mutex);
        list_for_each_entry(devlink, &devlink_list, list) {
+               if (!devlink_try_get(devlink))
+                       continue;
+
                if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) ||
                    !devlink->ops->sb_tc_pool_bind_get)
-                       continue;
+                       goto retry;
 
                mutex_lock(&devlink->lock);
                list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
                                err = 0;
                        } else if (err) {
                                mutex_unlock(&devlink->lock);
+                               devlink_put(devlink);
                                goto out;
                        }
                }
                mutex_unlock(&devlink->lock);
+retry:
+               devlink_put(devlink);
        }
 out:
        mutex_unlock(&devlink_mutex);
 
        mutex_lock(&devlink_mutex);
        list_for_each_entry(devlink, &devlink_list, list) {
-               if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
+               if (!devlink_try_get(devlink))
                        continue;
+
+               if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
+                       goto retry;
+
                mutex_lock(&devlink->lock);
                list_for_each_entry(param_item, &devlink->param_list, list) {
                        if (idx < start) {
                                err = 0;
                        } else if (err) {
                                mutex_unlock(&devlink->lock);
+                               devlink_put(devlink);
                                goto out;
                        }
                        idx++;
                }
                mutex_unlock(&devlink->lock);
+retry:
+               devlink_put(devlink);
        }
 out:
        mutex_unlock(&devlink_mutex);
 
        mutex_lock(&devlink_mutex);
        list_for_each_entry(devlink, &devlink_list, list) {
-               if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
+               if (!devlink_try_get(devlink))
                        continue;
+
+               if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
+                       goto retry;
+
                mutex_lock(&devlink->lock);
                list_for_each_entry(devlink_port, &devlink->port_list, list) {
                        list_for_each_entry(param_item,
                                        err = 0;
                                } else if (err) {
                                        mutex_unlock(&devlink->lock);
+                                       devlink_put(devlink);
                                        goto out;
                                }
                                idx++;
                        }
                }
                mutex_unlock(&devlink->lock);
+retry:
+               devlink_put(devlink);
        }
 out:
        mutex_unlock(&devlink_mutex);
        struct devlink *devlink;
        int start = cb->args[0];
        int idx = 0;
-       int err;
+       int err = 0;
 
        mutex_lock(&devlink_mutex);
        list_for_each_entry(devlink, &devlink_list, list) {
-               if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
+               if (!devlink_try_get(devlink))
                        continue;
+
+               if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
+                       goto retry;
+
                err = devlink_nl_cmd_region_get_devlink_dumpit(msg, cb, devlink,
                                                               &idx, start);
+retry:
+               devlink_put(devlink);
                if (err)
                        goto out;
        }
        nla_nest_end(skb, chunks_attr);
        genlmsg_end(skb, hdr);
        mutex_unlock(&devlink->lock);
+       devlink_put(devlink);
        mutex_unlock(&devlink_mutex);
 
        return skb->len;
        genlmsg_cancel(skb, hdr);
 out_unlock:
        mutex_unlock(&devlink->lock);
+       devlink_put(devlink);
 out_dev:
        mutex_unlock(&devlink_mutex);
        return err;
 
        mutex_lock(&devlink_mutex);
        list_for_each_entry(devlink, &devlink_list, list) {
-               if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
+               if (!devlink_try_get(devlink))
                        continue;
-               if (idx < start) {
-                       idx++;
-                       continue;
-               }
 
-               if (!devlink->ops->info_get) {
-                       idx++;
-                       continue;
-               }
+               if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
+                       goto retry;
+
+               if (idx < start || !devlink->ops->info_get)
+                       goto inc;
 
                mutex_lock(&devlink->lock);
                err = devlink_nl_info_fill(msg, devlink, DEVLINK_CMD_INFO_GET,
                mutex_unlock(&devlink->lock);
                if (err == -EOPNOTSUPP)
                        err = 0;
-               else if (err)
+               else if (err) {
+                       devlink_put(devlink);
                        break;
+               }
+inc:
                idx++;
+retry:
+               devlink_put(devlink);
        }
        mutex_unlock(&devlink_mutex);
 
                goto unlock;
 
        reporter = devlink_health_reporter_get_from_attrs(devlink, attrs);
+       devlink_put(devlink);
        mutex_unlock(&devlink_mutex);
        return reporter;
 unlock:
 
        mutex_lock(&devlink_mutex);
        list_for_each_entry(devlink, &devlink_list, list) {
-               if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
+               if (!devlink_try_get(devlink))
                        continue;
+
+               if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
+                       goto retry_rep;
+
                mutex_lock(&devlink->reporters_lock);
                list_for_each_entry(reporter, &devlink->reporter_list,
                                    list) {
                                NLM_F_MULTI);
                        if (err) {
                                mutex_unlock(&devlink->reporters_lock);
+                               devlink_put(devlink);
                                goto out;
                        }
                        idx++;
                }
                mutex_unlock(&devlink->reporters_lock);
+retry_rep:
+               devlink_put(devlink);
        }
 
        list_for_each_entry(devlink, &devlink_list, list) {
-               if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
+               if (!devlink_try_get(devlink))
                        continue;
+
+               if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
+                       goto retry_port;
+
                mutex_lock(&devlink->lock);
                list_for_each_entry(port, &devlink->port_list, list) {
                        mutex_lock(&port->reporters_lock);
                                if (err) {
                                        mutex_unlock(&port->reporters_lock);
                                        mutex_unlock(&devlink->lock);
+                                       devlink_put(devlink);
                                        goto out;
                                }
                                idx++;
                        mutex_unlock(&port->reporters_lock);
                }
                mutex_unlock(&devlink->lock);
+retry_port:
+               devlink_put(devlink);
        }
 out:
        mutex_unlock(&devlink_mutex);
 
        mutex_lock(&devlink_mutex);
        list_for_each_entry(devlink, &devlink_list, list) {
-               if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
+               if (!devlink_try_get(devlink))
                        continue;
+
+               if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
+                       goto retry;
+
                mutex_lock(&devlink->lock);
                list_for_each_entry(trap_item, &devlink->trap_list, list) {
                        if (idx < start) {
                                                   NLM_F_MULTI);
                        if (err) {
                                mutex_unlock(&devlink->lock);
+                               devlink_put(devlink);
                                goto out;
                        }
                        idx++;
                }
                mutex_unlock(&devlink->lock);
+retry:
+               devlink_put(devlink);
        }
 out:
        mutex_unlock(&devlink_mutex);
 
        mutex_lock(&devlink_mutex);
        list_for_each_entry(devlink, &devlink_list, list) {
-               if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
+               if (!devlink_try_get(devlink))
                        continue;
+
+               if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
+                       goto retry;
+
                mutex_lock(&devlink->lock);
                list_for_each_entry(group_item, &devlink->trap_group_list,
                                    list) {
                                                         NLM_F_MULTI);
                        if (err) {
                                mutex_unlock(&devlink->lock);
+                               devlink_put(devlink);
                                goto out;
                        }
                        idx++;
                }
                mutex_unlock(&devlink->lock);
+retry:
+               devlink_put(devlink);
        }
 out:
        mutex_unlock(&devlink_mutex);
 
        mutex_lock(&devlink_mutex);
        list_for_each_entry(devlink, &devlink_list, list) {
-               if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
+               if (!devlink_try_get(devlink))
                        continue;
+
+               if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
+                       goto retry;
+
                mutex_lock(&devlink->lock);
                list_for_each_entry(policer_item, &devlink->trap_policer_list,
                                    list) {
                                                           NLM_F_MULTI);
                        if (err) {
                                mutex_unlock(&devlink->lock);
+                               devlink_put(devlink);
                                goto out;
                        }
                        idx++;
                }
                mutex_unlock(&devlink->lock);
+retry:
+               devlink_put(devlink);
        }
 out:
        mutex_unlock(&devlink_mutex);
        INIT_LIST_HEAD(&devlink->trap_policer_list);
        mutex_init(&devlink->lock);
        mutex_init(&devlink->reporters_lock);
+       refcount_set(&devlink->refcount, 1);
+       init_completion(&devlink->comp);
+
        return devlink;
 }
 EXPORT_SYMBOL_GPL(devlink_alloc_ns);
  */
 void devlink_unregister(struct devlink *devlink)
 {
+       devlink_put(devlink);
+       wait_for_completion(&devlink->comp);
+
        mutex_lock(&devlink_mutex);
        WARN_ON(devlink_reload_supported(devlink->ops) &&
                devlink->reload_enabled);
         */
        mutex_lock(&devlink_mutex);
        list_for_each_entry(devlink, &devlink_list, list) {
-               if (!net_eq(devlink_net(devlink), net))
+               if (!devlink_try_get(devlink))
                        continue;
 
+               if (!net_eq(devlink_net(devlink), net))
+                       goto retry;
+
                WARN_ON(!devlink_reload_supported(devlink->ops));
                err = devlink_reload(devlink, &init_net,
                                     DEVLINK_RELOAD_ACTION_DRIVER_REINIT,
                                     &actions_performed, NULL);
                if (err && err != -EOPNOTSUPP)
                        pr_warn("Failed to reload devlink instance into init_net\n");
+retry:
+               devlink_put(devlink);
        }
        mutex_unlock(&devlink_mutex);
 }