]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blobdiff - drivers/nvme/target/configfs.c
nvmet: use type-name map for address treq
[mirror_ubuntu-jammy-kernel.git] / drivers / nvme / target / configfs.c
index 7aa10788b7c87e6e722e65194ed1da0d8a5ff264..9c808f4185a0a26f9898fed7bde2f33f61165886 100644 (file)
@@ -20,41 +20,48 @@ static const struct config_item_type nvmet_subsys_type;
 static LIST_HEAD(nvmet_ports_list);
 struct list_head *nvmet_ports = &nvmet_ports_list;
 
-static const struct nvmet_transport_name {
+struct nvmet_type_name_map {
        u8              type;
        const char      *name;
-} nvmet_transport_names[] = {
+};
+
+static struct nvmet_type_name_map nvmet_transport[] = {
        { NVMF_TRTYPE_RDMA,     "rdma" },
        { NVMF_TRTYPE_FC,       "fc" },
        { NVMF_TRTYPE_TCP,      "tcp" },
        { NVMF_TRTYPE_LOOP,     "loop" },
 };
 
+static const struct nvmet_type_name_map nvmet_addr_family[] = {
+       { NVMF_ADDR_FAMILY_PCI, "pcie" },
+       { NVMF_ADDR_FAMILY_IP4, "ipv4" },
+       { NVMF_ADDR_FAMILY_IP6, "ipv6" },
+       { NVMF_ADDR_FAMILY_IB,  "ib" },
+       { NVMF_ADDR_FAMILY_FC,  "fc" },
+};
+
 /*
  * nvmet_port Generic ConfigFS definitions.
  * Used in any place in the ConfigFS tree that refers to an address.
  */
-static ssize_t nvmet_addr_adrfam_show(struct config_item *item,
-               char *page)
+static ssize_t nvmet_addr_adrfam_show(struct config_item *item, char *page)
 {
-       switch (to_nvmet_port(item)->disc_addr.adrfam) {
-       case NVMF_ADDR_FAMILY_IP4:
-               return sprintf(page, "ipv4\n");
-       case NVMF_ADDR_FAMILY_IP6:
-               return sprintf(page, "ipv6\n");
-       case NVMF_ADDR_FAMILY_IB:
-               return sprintf(page, "ib\n");
-       case NVMF_ADDR_FAMILY_FC:
-               return sprintf(page, "fc\n");
-       default:
-               return sprintf(page, "\n");
+       u8 adrfam = to_nvmet_port(item)->disc_addr.adrfam;
+       int i;
+
+       for (i = 1; i < ARRAY_SIZE(nvmet_addr_family); i++) {
+               if (nvmet_addr_family[i].type == adrfam)
+                       return sprintf(page, "%s\n", nvmet_addr_family[i].name);
        }
+
+       return sprintf(page, "\n");
 }
 
 static ssize_t nvmet_addr_adrfam_store(struct config_item *item,
                const char *page, size_t count)
 {
        struct nvmet_port *port = to_nvmet_port(item);
+       int i;
 
        if (port->enabled) {
                pr_err("Cannot modify address while enabled\n");
@@ -62,19 +69,16 @@ static ssize_t nvmet_addr_adrfam_store(struct config_item *item,
                return -EACCES;
        }
 
-       if (sysfs_streq(page, "ipv4")) {
-               port->disc_addr.adrfam = NVMF_ADDR_FAMILY_IP4;
-       } else if (sysfs_streq(page, "ipv6")) {
-               port->disc_addr.adrfam = NVMF_ADDR_FAMILY_IP6;
-       } else if (sysfs_streq(page, "ib")) {
-               port->disc_addr.adrfam = NVMF_ADDR_FAMILY_IB;
-       } else if (sysfs_streq(page, "fc")) {
-               port->disc_addr.adrfam = NVMF_ADDR_FAMILY_FC;
-       } else {
-               pr_err("Invalid value '%s' for adrfam\n", page);
-               return -EINVAL;
+       for (i = 1; i < ARRAY_SIZE(nvmet_addr_family); i++) {
+               if (sysfs_streq(page, nvmet_addr_family[i].name))
+                       goto found;
        }
 
+       pr_err("Invalid value '%s' for adrfam\n", page);
+       return -EINVAL;
+
+found:
+       port->disc_addr.adrfam = i;
        return count;
 }
 
@@ -143,20 +147,24 @@ static ssize_t nvmet_addr_traddr_store(struct config_item *item,
 
 CONFIGFS_ATTR(nvmet_, addr_traddr);
 
-static ssize_t nvmet_addr_treq_show(struct config_item *item,
-               char *page)
+static const struct nvmet_type_name_map nvmet_addr_treq[] = {
+       { NVMF_TREQ_NOT_SPECIFIED,      "not specified" },
+       { NVMF_TREQ_REQUIRED,           "required" },
+       { NVMF_TREQ_NOT_REQUIRED,       "not required" },
+};
+
+static ssize_t nvmet_addr_treq_show(struct config_item *item, char *page)
 {
-       switch (to_nvmet_port(item)->disc_addr.treq &
-               NVME_TREQ_SECURE_CHANNEL_MASK) {
-       case NVMF_TREQ_NOT_SPECIFIED:
-               return sprintf(page, "not specified\n");
-       case NVMF_TREQ_REQUIRED:
-               return sprintf(page, "required\n");
-       case NVMF_TREQ_NOT_REQUIRED:
-               return sprintf(page, "not required\n");
-       default:
-               return sprintf(page, "\n");
+       u8 treq = to_nvmet_port(item)->disc_addr.treq &
+               NVME_TREQ_SECURE_CHANNEL_MASK;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(nvmet_addr_treq); i++) {
+               if (treq == nvmet_addr_treq[i].type)
+                       return sprintf(page, "%s\n", nvmet_addr_treq[i].name);
        }
+
+       return sprintf(page, "\n");
 }
 
 static ssize_t nvmet_addr_treq_store(struct config_item *item,
@@ -164,6 +172,7 @@ static ssize_t nvmet_addr_treq_store(struct config_item *item,
 {
        struct nvmet_port *port = to_nvmet_port(item);
        u8 treq = port->disc_addr.treq & ~NVME_TREQ_SECURE_CHANNEL_MASK;
+       int i;
 
        if (port->enabled) {
                pr_err("Cannot modify address while enabled\n");
@@ -171,18 +180,17 @@ static ssize_t nvmet_addr_treq_store(struct config_item *item,
                return -EACCES;
        }
 
-       if (sysfs_streq(page, "not specified")) {
-               treq |= NVMF_TREQ_NOT_SPECIFIED;
-       } else if (sysfs_streq(page, "required")) {
-               treq |= NVMF_TREQ_REQUIRED;
-       } else if (sysfs_streq(page, "not required")) {
-               treq |= NVMF_TREQ_NOT_REQUIRED;
-       } else {
-               pr_err("Invalid value '%s' for treq\n", page);
-               return -EINVAL;
+       for (i = 0; i < ARRAY_SIZE(nvmet_addr_treq); i++) {
+               if (sysfs_streq(page, nvmet_addr_treq[i].name))
+                       goto found;
        }
-       port->disc_addr.treq = treq;
 
+       pr_err("Invalid value '%s' for treq\n", page);
+       return -EINVAL;
+
+found:
+       treq |= nvmet_addr_treq[i].type;
+       port->disc_addr.treq = treq;
        return count;
 }
 
@@ -254,10 +262,9 @@ static ssize_t nvmet_addr_trtype_show(struct config_item *item,
        struct nvmet_port *port = to_nvmet_port(item);
        int i;
 
-       for (i = 0; i < ARRAY_SIZE(nvmet_transport_names); i++) {
-               if (port->disc_addr.trtype != nvmet_transport_names[i].type)
-                       continue;
-               return sprintf(page, "%s\n", nvmet_transport_names[i].name);
+       for (i = 0; i < ARRAY_SIZE(nvmet_transport); i++) {
+               if (port->disc_addr.trtype == nvmet_transport[i].type)
+                       return sprintf(page, "%s\n", nvmet_transport[i].name);
        }
 
        return sprintf(page, "\n");
@@ -282,16 +289,17 @@ static ssize_t nvmet_addr_trtype_store(struct config_item *item,
                return -EACCES;
        }
 
-       for (i = 0; i < ARRAY_SIZE(nvmet_transport_names); i++) {
-               if (sysfs_streq(page, nvmet_transport_names[i].name))
+       for (i = 0; i < ARRAY_SIZE(nvmet_transport); i++) {
+               if (sysfs_streq(page, nvmet_transport[i].name))
                        goto found;
        }
 
        pr_err("Invalid value '%s' for trtype\n", page);
        return -EINVAL;
+
 found:
        memset(&port->disc_addr.tsas, 0, NVMF_TSAS_SIZE);
-       port->disc_addr.trtype = nvmet_transport_names[i].type;
+       port->disc_addr.trtype = nvmet_transport[i].type;
        if (port->disc_addr.trtype == NVMF_TRTYPE_RDMA)
                nvmet_port_init_tsas_rdma(port);
        return count;
@@ -1098,12 +1106,19 @@ static struct configfs_attribute *nvmet_referral_attrs[] = {
        NULL,
 };
 
-static void nvmet_referral_release(struct config_item *item)
+static void nvmet_referral_notify(struct config_group *group,
+               struct config_item *item)
 {
        struct nvmet_port *parent = to_nvmet_port(item->ci_parent->ci_parent);
        struct nvmet_port *port = to_nvmet_port(item);
 
        nvmet_referral_disable(parent, port);
+}
+
+static void nvmet_referral_release(struct config_item *item)
+{
+       struct nvmet_port *port = to_nvmet_port(item);
+
        kfree(port);
 }
 
@@ -1134,6 +1149,7 @@ static struct config_group *nvmet_referral_make(
 
 static struct configfs_group_operations nvmet_referral_group_ops = {
        .make_group             = nvmet_referral_make,
+       .disconnect_notify      = nvmet_referral_notify,
 };
 
 static const struct config_item_type nvmet_referrals_type = {
@@ -1141,10 +1157,7 @@ static const struct config_item_type nvmet_referrals_type = {
        .ct_group_ops   = &nvmet_referral_group_ops,
 };
 
-static struct {
-       enum nvme_ana_state     state;
-       const char              *name;
-} nvmet_ana_state_names[] = {
+struct nvmet_type_name_map nvmet_ana_state[] = {
        { NVME_ANA_OPTIMIZED,           "optimized" },
        { NVME_ANA_NONOPTIMIZED,        "non-optimized" },
        { NVME_ANA_INACCESSIBLE,        "inaccessible" },
@@ -1159,10 +1172,9 @@ static ssize_t nvmet_ana_group_ana_state_show(struct config_item *item,
        enum nvme_ana_state state = grp->port->ana_state[grp->grpid];
        int i;
 
-       for (i = 0; i < ARRAY_SIZE(nvmet_ana_state_names); i++) {
-               if (state != nvmet_ana_state_names[i].state)
-                       continue;
-               return sprintf(page, "%s\n", nvmet_ana_state_names[i].name);
+       for (i = 0; i < ARRAY_SIZE(nvmet_ana_state); i++) {
+               if (state == nvmet_ana_state[i].type)
+                       return sprintf(page, "%s\n", nvmet_ana_state[i].name);
        }
 
        return sprintf(page, "\n");
@@ -1172,10 +1184,11 @@ static ssize_t nvmet_ana_group_ana_state_store(struct config_item *item,
                const char *page, size_t count)
 {
        struct nvmet_ana_group *grp = to_ana_group(item);
+       enum nvme_ana_state *ana_state = grp->port->ana_state;
        int i;
 
-       for (i = 0; i < ARRAY_SIZE(nvmet_ana_state_names); i++) {
-               if (sysfs_streq(page, nvmet_ana_state_names[i].name))
+       for (i = 0; i < ARRAY_SIZE(nvmet_ana_state); i++) {
+               if (sysfs_streq(page, nvmet_ana_state[i].name))
                        goto found;
        }
 
@@ -1184,10 +1197,9 @@ static ssize_t nvmet_ana_group_ana_state_store(struct config_item *item,
 
 found:
        down_write(&nvmet_ana_sem);
-       grp->port->ana_state[grp->grpid] = nvmet_ana_state_names[i].state;
+       ana_state[grp->grpid] = (enum nvme_ana_state) nvmet_ana_state[i].type;
        nvmet_ana_chgcnt++;
        up_write(&nvmet_ana_sem);
-
        nvmet_port_send_ana_event(grp->port);
        return count;
 }