scsi: cxlflash: Support dynamic number of FC ports
authorMatthew R. Ochs <mrochs@linux.vnet.ibm.com>
Wed, 12 Apr 2017 19:13:50 +0000 (14:13 -0500)
committerMartin K. Petersen <martin.petersen@oracle.com>
Fri, 14 Apr 2017 02:55:41 +0000 (22:55 -0400)
Transition from a static number of FC ports to a value that is derived during
probe. For now, a static value is used but this will later be based on the
type of card being configured.

Signed-off-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>
Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/cxlflash/common.h
drivers/scsi/cxlflash/main.c
drivers/scsi/cxlflash/main.h
drivers/scsi/cxlflash/sislite.h
drivers/scsi/cxlflash/superpipe.h

index 3ff05f15b417c0ef3a9208c03dd63919511d9a64..6a04867a0eec669c6feb718c8faf4e4527b0c8c0 100644 (file)
@@ -25,7 +25,9 @@
 
 extern const struct file_operations cxlflash_cxl_fops;
 
-#define MAX_CONTEXT  CXLFLASH_MAX_CONTEXT       /* num contexts per afu */
+#define MAX_CONTEXT    CXLFLASH_MAX_CONTEXT    /* num contexts per afu */
+#define NUM_FC_PORTS   CXLFLASH_NUM_FC_PORTS   /* ports per AFU */
+#define MAX_FC_PORTS   CXLFLASH_MAX_FC_PORTS   /* ports per AFU */
 
 #define CXLFLASH_BLOCK_SIZE    4096    /* 4K blocks */
 #define CXLFLASH_MAX_XFER_SIZE 16777216        /* 16MB transfer */
@@ -98,6 +100,7 @@ struct cxlflash_cfg {
        struct pci_dev *dev;
        struct pci_device_id *dev_id;
        struct Scsi_Host *host;
+       int num_fc_ports;
 
        ulong cxlflash_regs_pci;
 
@@ -118,7 +121,7 @@ struct cxlflash_cfg {
        struct file_operations cxl_fops;
 
        /* Parameters that are LUN table related */
-       int last_lun_index[CXLFLASH_NUM_FC_PORTS];
+       int last_lun_index[MAX_FC_PORTS];
        int promote_lun_index;
        struct list_head lluns; /* list of llun_info structs */
 
index 157d806c97fc51c4b3eb2511e72d69c2d33bddd6..3f9c8690af0d6be07fdb746fe34a09960070b359 100644 (file)
@@ -689,7 +689,7 @@ static void notify_shutdown(struct cxlflash_cfg *cfg, bool wait)
        global = &afu->afu_map->global;
 
        /* Notify AFU */
-       for (i = 0; i < NUM_FC_PORTS; i++) {
+       for (i = 0; i < cfg->num_fc_ports; i++) {
                reg = readq_be(&global->fc_regs[i][FC_CONFIG2 / 8]);
                reg |= SISL_FC_SHUTDOWN_NORMAL;
                writeq_be(reg, &global->fc_regs[i][FC_CONFIG2 / 8]);
@@ -699,7 +699,7 @@ static void notify_shutdown(struct cxlflash_cfg *cfg, bool wait)
                return;
 
        /* Wait up to 1.5 seconds for shutdown processing to complete */
-       for (i = 0; i < NUM_FC_PORTS; i++) {
+       for (i = 0; i < cfg->num_fc_ports; i++) {
                retry_cnt = 0;
                while (true) {
                        status = readq_be(&global->fc_regs[i][FC_STATUS / 8]);
@@ -1072,6 +1072,7 @@ static const struct asyc_intr_info *find_ainfo(u64 status)
  */
 static void afu_err_intr_init(struct afu *afu)
 {
+       struct cxlflash_cfg *cfg = afu->parent;
        int i;
        u64 reg;
 
@@ -1107,7 +1108,7 @@ static void afu_err_intr_init(struct afu *afu)
        writeq_be(reg, &afu->afu_map->global.fc_regs[0][FC_CONFIG2 / 8]);
 
        /* now clear FC errors */
-       for (i = 0; i < NUM_FC_PORTS; i++) {
+       for (i = 0; i < cfg->num_fc_ports; i++) {
                writeq_be(0xFFFFFFFFU,
                          &afu->afu_map->global.fc_regs[i][FC_ERROR / 8]);
                writeq_be(0, &afu->afu_map->global.fc_regs[i][FC_ERRCAP / 8]);
@@ -1394,7 +1395,7 @@ static int start_context(struct cxlflash_cfg *cfg)
 /**
  * read_vpd() - obtains the WWPNs from VPD
  * @cfg:       Internal structure associated with the host.
- * @wwpn:      Array of size NUM_FC_PORTS to pass back WWPNs
+ * @wwpn:      Array of size MAX_FC_PORTS to pass back WWPNs
  *
  * Return: 0 on success, -errno on failure
  */
@@ -1407,7 +1408,7 @@ static int read_vpd(struct cxlflash_cfg *cfg, u64 wwpn[])
        ssize_t vpd_size;
        char vpd_data[CXLFLASH_VPD_LEN];
        char tmp_buf[WWPN_BUF_LEN] = { 0 };
-       char *wwpn_vpd_tags[NUM_FC_PORTS] = { "V5", "V6" };
+       char *wwpn_vpd_tags[MAX_FC_PORTS] = { "V5", "V6" };
 
        /* Get the VPD data from the device */
        vpd_size = cxl_read_adapter_vpd(pdev, vpd_data, sizeof(vpd_data));
@@ -1445,7 +1446,7 @@ static int read_vpd(struct cxlflash_cfg *cfg, u64 wwpn[])
         * because the conversion service requires that the ASCII
         * string be terminated.
         */
-       for (k = 0; k < NUM_FC_PORTS; k++) {
+       for (k = 0; k < cfg->num_fc_ports; k++) {
                j = ro_size;
                i = ro_start + PCI_VPD_LRDT_TAG_SIZE;
 
@@ -1474,6 +1475,8 @@ static int read_vpd(struct cxlflash_cfg *cfg, u64 wwpn[])
                        rc = -ENODEV;
                        goto out;
                }
+
+               dev_dbg(dev, "%s: wwpn%d=%016llx\n", __func__, k, wwpn[k]);
        }
 
 out:
@@ -1520,7 +1523,7 @@ static int init_global(struct cxlflash_cfg *cfg)
 {
        struct afu *afu = cfg->afu;
        struct device *dev = &cfg->dev->dev;
-       u64 wwpn[NUM_FC_PORTS]; /* wwpn of AFU ports */
+       u64 wwpn[MAX_FC_PORTS]; /* wwpn of AFU ports */
        int i = 0, num_ports = 0;
        int rc = 0;
        u64 reg;
@@ -1531,9 +1534,6 @@ static int init_global(struct cxlflash_cfg *cfg)
                goto out;
        }
 
-       dev_dbg(dev, "%s: wwpn0=%016llx wwpn1=%016llx\n",
-               __func__, wwpn[0], wwpn[1]);
-
        /* Set up RRQ and SQ in AFU for master issued cmds */
        writeq_be((u64) afu->hrrq_start, &afu->host_map->rrq_start);
        writeq_be((u64) afu->hrrq_end, &afu->host_map->rrq_end);
@@ -1556,10 +1556,10 @@ static int init_global(struct cxlflash_cfg *cfg)
        if (afu->internal_lun) {
                /* Only use port 0 */
                writeq_be(PORT0, &afu->afu_map->global.regs.afu_port_sel);
-               num_ports = NUM_FC_PORTS - 1;
+               num_ports = 0;
        } else {
                writeq_be(BOTH_PORTS, &afu->afu_map->global.regs.afu_port_sel);
-               num_ports = NUM_FC_PORTS;
+               num_ports = cfg->num_fc_ports;
        }
 
        for (i = 0; i < num_ports; i++) {
@@ -2061,19 +2061,25 @@ static int cxlflash_change_queue_depth(struct scsi_device *sdev, int qdepth)
  * @cfg:       Internal structure associated with the host.
  * @buf:       Buffer of length PAGE_SIZE to report back port status in ASCII.
  *
- * Return: The size of the ASCII string returned in @buf.
+ * Return: The size of the ASCII string returned in @buf or -EINVAL.
  */
 static ssize_t cxlflash_show_port_status(u32 port,
                                         struct cxlflash_cfg *cfg,
                                         char *buf)
 {
+       struct device *dev = &cfg->dev->dev;
        struct afu *afu = cfg->afu;
        char *disp_status;
        u64 status;
        __be64 __iomem *fc_regs;
 
-       if (port >= NUM_FC_PORTS)
-               return 0;
+       WARN_ON(port >= MAX_FC_PORTS);
+
+       if (port >= cfg->num_fc_ports) {
+               dev_info(dev, "%s: Port %d not supported on this card.\n",
+                       __func__, port);
+               return -EINVAL;
+       }
 
        fc_regs = &afu->afu_map->global.fc_regs[port][0];
        status = readq_be(&fc_regs[FC_MTIP_STATUS / 8]);
@@ -2178,12 +2184,13 @@ static ssize_t lun_mode_store(struct device *dev,
 
                /*
                 * When configured for internal LUN, there is only one channel,
-                * channel number 0, else there will be 2 (default).
+                * channel number 0, else there will be one less than the number
+                * of fc ports for this card.
                 */
                if (afu->internal_lun)
                        shost->max_channel = 0;
                else
-                       shost->max_channel = NUM_FC_PORTS - 1;
+                       shost->max_channel = cfg->num_fc_ports - 1;
 
                afu_reset(cfg);
                scsi_scan_host(cfg->host);
@@ -2212,19 +2219,25 @@ static ssize_t ioctl_version_show(struct device *dev,
  * @cfg:       Internal structure associated with the host.
  * @buf:       Buffer of length PAGE_SIZE to report back port status in ASCII.
  *
- * Return: The size of the ASCII string returned in @buf.
+ * Return: The size of the ASCII string returned in @buf or -EINVAL.
  */
 static ssize_t cxlflash_show_port_lun_table(u32 port,
                                            struct cxlflash_cfg *cfg,
                                            char *buf)
 {
+       struct device *dev = &cfg->dev->dev;
        struct afu *afu = cfg->afu;
        int i;
        ssize_t bytes = 0;
        __be64 __iomem *fc_port;
 
-       if (port >= NUM_FC_PORTS)
-               return 0;
+       WARN_ON(port >= MAX_FC_PORTS);
+
+       if (port >= cfg->num_fc_ports) {
+               dev_info(dev, "%s: Port %d not supported on this card.\n",
+                       __func__, port);
+               return -EINVAL;
+       }
 
        fc_port = &afu->afu_map->global.fc_port[port][0];
 
@@ -2499,6 +2512,7 @@ static int cxlflash_probe(struct pci_dev *pdev,
        struct device *dev = &pdev->dev;
        struct dev_dependent_vals *ddv;
        int rc = 0;
+       int k;
 
        dev_dbg(&pdev->dev, "%s: Found CXLFLASH with IRQ: %d\n",
                __func__, pdev->irq);
@@ -2531,17 +2545,20 @@ static int cxlflash_probe(struct pci_dev *pdev,
 
        cfg->init_state = INIT_STATE_NONE;
        cfg->dev = pdev;
+       cfg->num_fc_ports = NUM_FC_PORTS;
        cfg->cxl_fops = cxlflash_cxl_fops;
 
        /*
-        * The promoted LUNs move to the top of the LUN table. The rest stay
-        * on the bottom half. The bottom half grows from the end
-        * (index = 255), whereas the top half grows from the beginning
-        * (index = 0).
+        * Promoted LUNs move to the top of the LUN table. The rest stay on
+        * the bottom half. The bottom half grows from the end (index = 255),
+        * whereas the top half grows from the beginning (index = 0).
+        *
+        * Initialize the last LUN index for all possible ports.
         */
-       cfg->promote_lun_index  = 0;
-       cfg->last_lun_index[0] = CXLFLASH_NUM_VLUNS/2 - 1;
-       cfg->last_lun_index[1] = CXLFLASH_NUM_VLUNS/2 - 1;
+       cfg->promote_lun_index = 0;
+
+       for (k = 0; k < MAX_FC_PORTS; k++)
+               cfg->last_lun_index[k] = CXLFLASH_NUM_VLUNS/2 - 1;
 
        cfg->dev_id = (struct pci_device_id *)dev_id;
 
index 0be2261e6312240d44ab54f021dcc13346f96704..49657f1f409eb129a1807eb128c30fe140378124 100644 (file)
@@ -37,8 +37,6 @@
 
 #define CXLFLASH_PCI_ERROR_RECOVERY_TIMEOUT    (120 * HZ)
 
-#define NUM_FC_PORTS   CXLFLASH_NUM_FC_PORTS   /* ports per AFU */
-
 /* FC defines */
 #define FC_MTIP_CMDCONFIG 0x010
 #define FC_MTIP_STATUS 0x018
index a6e48a893fefb6659136c2a81959acd036070d70..0db4bc1f4e2303ce0606a652fd0720087a6476e0 100644 (file)
@@ -367,6 +367,7 @@ struct sisl_global_regs {
 #define SISL_INTVER_CAP_RESERVED_CMD_MODE_B    0x100000000000ULL
 };
 
+#define CXLFLASH_MAX_FC_PORTS   2
 #define CXLFLASH_NUM_FC_PORTS   2
 #define CXLFLASH_MAX_CONTEXT  512      /* how many contexts per afu */
 #define CXLFLASH_NUM_VLUNS    512
index 9e62ff304e4b9778b2dd17c743afad43280bf8b6..690ce9c652b202e23bfeafc96fab48b9a7861b6a 100644 (file)
@@ -59,7 +59,7 @@ struct glun_info {
 
 /* Local (per-adapter) lun_info structure */
 struct llun_info {
-       u64 lun_id[CXLFLASH_NUM_FC_PORTS]; /* from REPORT_LUNS */
+       u64 lun_id[MAX_FC_PORTS]; /* from REPORT_LUNS */
        u32 lun_index;          /* Index in the LUN table */
        u32 host_no;            /* host_no from Scsi_host */
        u32 port_sel;           /* What port to use for this LUN */