}
 EXPORT_SYMBOL_GPL(devl_unlock);
 
+/**
+ * devlink_try_get() - try to obtain a reference on a devlink instance
+ * @devlink: instance to reference
+ *
+ * Obtain a reference on a devlink instance. A reference on a devlink instance
+ * only implies that it's safe to take the instance lock. It does not imply
+ * that the instance is registered, use devl_is_registered() after taking
+ * the instance lock to check registration status.
+ */
 struct devlink *__must_check devlink_try_get(struct devlink *devlink)
 {
        if (refcount_inc_not_zero(&devlink->refcount))
        devlinks_xa_for_each_registered_get(net, index, devlink) {
                WARN_ON(!(devlink->features & DEVLINK_F_RELOAD));
                devl_lock(devlink);
-               err = devlink_reload(devlink, &init_net,
-                                    DEVLINK_RELOAD_ACTION_DRIVER_REINIT,
-                                    DEVLINK_RELOAD_LIMIT_UNSPEC,
-                                    &actions_performed, NULL);
+               err = 0;
+               if (devl_is_registered(devlink))
+                       err = devlink_reload(devlink, &init_net,
+                                            DEVLINK_RELOAD_ACTION_DRIVER_REINIT,
+                                            DEVLINK_RELOAD_LIMIT_UNSPEC,
+                                            &actions_performed, NULL);
                devl_unlock(devlink);
                devlink_put(devlink);
 
 
 
 struct devlink *devlinks_xa_find_get(struct net *net, unsigned long *indexp);
 
+static inline bool devl_is_registered(struct devlink *devlink)
+{
+       /* To prevent races the caller must hold the instance lock
+        * or another lock taken during unregistration.
+        */
+       return xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED);
+}
+
 /* Netlink */
 #define DEVLINK_NL_FLAG_NEED_PORT              BIT(0)
 #define DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT   BIT(1)
 
                int idx = 0;
 
                mutex_lock(&devlink->linecards_lock);
+               if (!devl_is_registered(devlink))
+                       goto next_devlink;
+
                list_for_each_entry(linecard, &devlink->linecard_list, list) {
                        if (idx < state->idx) {
                                idx++;
                        }
                        idx++;
                }
+next_devlink:
                mutex_unlock(&devlink->linecards_lock);
                devlink_put(devlink);
        }
                int idx = 0;
 
                mutex_lock(&devlink->reporters_lock);
+               if (!devl_is_registered(devlink)) {
+                       mutex_unlock(&devlink->reporters_lock);
+                       devlink_put(devlink);
+                       continue;
+               }
+
                list_for_each_entry(reporter, &devlink->reporter_list,
                                    list) {
                        if (idx < state->idx) {
                mutex_unlock(&devlink->reporters_lock);
 
                devl_lock(devlink);
+               if (!devl_is_registered(devlink))
+                       goto next_devlink;
+
                xa_for_each(&devlink->ports, port_index, port) {
                        mutex_lock(&port->reporters_lock);
                        list_for_each_entry(reporter, &port->reporter_list, list) {
                        }
                        mutex_unlock(&port->reporters_lock);
                }
+next_devlink:
                devl_unlock(devlink);
                devlink_put(devlink);
        }
                return;
 
        devl_lock(devlink);
-       __devlink_compat_running_version(devlink, buf, len);
+       if (devl_is_registered(devlink))
+               __devlink_compat_running_version(devlink, buf, len);
        devl_unlock(devlink);
 }
 
        struct devlink_flash_update_params params = {};
        int ret;
 
-       if (!devlink->ops->flash_update)
-               return -EOPNOTSUPP;
+       devl_lock(devlink);
+       if (!devl_is_registered(devlink)) {
+               ret = -ENODEV;
+               goto out_unlock;
+       }
+
+       if (!devlink->ops->flash_update) {
+               ret = -EOPNOTSUPP;
+               goto out_unlock;
+       }
 
        ret = request_firmware(¶ms.fw, file_name, devlink->dev);
        if (ret)
-               return ret;
+               goto out_unlock;
 
-       devl_lock(devlink);
        devlink_flash_update_begin_notify(devlink);
        ret = devlink->ops->flash_update(devlink, ¶ms, NULL);
        devlink_flash_update_end_notify(devlink);
-       devl_unlock(devlink);
 
        release_firmware(params.fw);
+out_unlock:
+       devl_unlock(devlink);
 
        return ret;
 }
 
 
        devlinks_xa_for_each_registered_get(net, index, devlink) {
                devl_lock(devlink);
-               if (strcmp(devlink->dev->bus->name, busname) == 0 &&
+               if (devl_is_registered(devlink) &&
+                   strcmp(devlink->dev->bus->name, busname) == 0 &&
                    strcmp(dev_name(devlink->dev), devname) == 0)
                        return devlink;
                devl_unlock(devlink);
 
        devlink_dump_for_each_instance_get(msg, state, devlink) {
                devl_lock(devlink);
-               err = cmd->dump_one(msg, devlink, cb);
+
+               if (devl_is_registered(devlink))
+                       err = cmd->dump_one(msg, devlink, cb);
+               else
+                       err = 0;
+
                devl_unlock(devlink);
                devlink_put(devlink);