return genlmsg_reply(msg, info);
 }
 
-static int devlink_nl_cmd_linecard_get_dumpit(struct sk_buff *msg,
-                                             struct netlink_callback *cb)
+static int devlink_nl_cmd_linecard_get_dump_one(struct sk_buff *msg,
+                                               struct devlink *devlink,
+                                               struct netlink_callback *cb)
 {
        struct devlink_nl_dump_state *state = devlink_dump_state(cb);
        struct devlink_linecard *linecard;
-       struct devlink *devlink;
-       int err;
-
-       devlink_dump_for_each_instance_get(msg, state, devlink) {
-               int idx = 0;
-
-               devl_lock(devlink);
-               if (!devl_is_registered(devlink))
-                       goto next_devlink;
+       int idx = 0;
+       int err = 0;
 
-               list_for_each_entry(linecard, &devlink->linecard_list, list) {
-                       if (idx < state->idx) {
-                               idx++;
-                               continue;
-                       }
-                       mutex_lock(&linecard->state_lock);
-                       err = devlink_nl_linecard_fill(msg, devlink, linecard,
-                                                      DEVLINK_CMD_LINECARD_NEW,
-                                                      NETLINK_CB(cb->skb).portid,
-                                                      cb->nlh->nlmsg_seq,
-                                                      NLM_F_MULTI,
-                                                      cb->extack);
-                       mutex_unlock(&linecard->state_lock);
-                       if (err) {
-                               devl_unlock(devlink);
-                               devlink_put(devlink);
-                               state->idx = idx;
-                               goto out;
-                       }
+       list_for_each_entry(linecard, &devlink->linecard_list, list) {
+               if (idx < state->idx) {
                        idx++;
+                       continue;
                }
-next_devlink:
-               devl_unlock(devlink);
-               devlink_put(devlink);
+               mutex_lock(&linecard->state_lock);
+               err = devlink_nl_linecard_fill(msg, devlink, linecard,
+                                              DEVLINK_CMD_LINECARD_NEW,
+                                              NETLINK_CB(cb->skb).portid,
+                                              cb->nlh->nlmsg_seq,
+                                              NLM_F_MULTI,
+                                              cb->extack);
+               mutex_unlock(&linecard->state_lock);
+               if (err) {
+                       state->idx = idx;
+                       break;
+               }
+               idx++;
        }
-out:
-       return msg->len;
+
+       return err;
 }
 
+const struct devlink_gen_cmd devl_gen_linecard = {
+       .dump_one               = devlink_nl_cmd_linecard_get_dump_one,
+};
+
 static struct devlink_linecard_type *
 devlink_linecard_type_lookup(struct devlink_linecard *linecard,
                             const char *type)
        {
                .cmd = DEVLINK_CMD_LINECARD_GET,
                .doit = devlink_nl_cmd_linecard_get_doit,
-               .dumpit = devlink_nl_cmd_linecard_get_dumpit,
+               .dumpit = devlink_nl_instance_iter_dump,
                .internal_flags = DEVLINK_NL_FLAG_NEED_LINECARD,
                /* can be retrieved by unprivileged users */
        },