scsi: qla2xxx: Add support for minimum link speed
authorSawan Chandak <sawan.chandak@cavium.com>
Wed, 23 Aug 2017 22:05:16 +0000 (15:05 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Fri, 25 Aug 2017 02:29:29 +0000 (22:29 -0400)
Signed-off-by: Sawan Chandak <sawan.chandak@cavium.com>
Signed-off-by: Joe Carnuccio <joe.carnuccio@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/qla2xxx/qla_attr.c
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_fw.h
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_mbx.c

index 9d2862233e3c04920b9a22bca8809f6607673925..75c4b312645e4ed9792eb5ec97268893cefd4f49 100644 (file)
@@ -1481,6 +1481,38 @@ qla2x00_pep_version_show(struct device *dev, struct device_attribute *attr,
            ha->pep_version[0], ha->pep_version[1], ha->pep_version[2]);
 }
 
+static ssize_t
+qla2x00_min_link_speed_show(struct device *dev, struct device_attribute *attr,
+    char *buf)
+{
+       scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
+       struct qla_hw_data *ha = vha->hw;
+
+       if (!IS_QLA27XX(ha))
+               return scnprintf(buf, PAGE_SIZE, "\n");
+
+       return scnprintf(buf, PAGE_SIZE, "%s\n",
+           ha->min_link_speed == 5 ? "32Gps" :
+           ha->min_link_speed == 4 ? "16Gps" :
+           ha->min_link_speed == 3 ? "8Gps" :
+           ha->min_link_speed == 2 ? "4Gps" :
+           ha->min_link_speed != 0 ? "unknown" : "");
+}
+
+static ssize_t
+qla2x00_max_speed_sup_show(struct device *dev, struct device_attribute *attr,
+    char *buf)
+{
+       scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
+       struct qla_hw_data *ha = vha->hw;
+
+       if (!IS_QLA27XX(ha))
+               return scnprintf(buf, PAGE_SIZE, "\n");
+
+       return scnprintf(buf, PAGE_SIZE, "%s\n",
+           ha->max_speed_sup ? "32Gps" : "16Gps");
+}
+
 static DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, NULL);
 static DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL);
 static DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL);
@@ -1526,6 +1558,8 @@ static DEVICE_ATTR(allow_cna_fw_dump, S_IRUGO | S_IWUSR,
                   qla2x00_allow_cna_fw_dump_show,
                   qla2x00_allow_cna_fw_dump_store);
 static DEVICE_ATTR(pep_version, S_IRUGO, qla2x00_pep_version_show, NULL);
+static DEVICE_ATTR(min_link_speed, S_IRUGO, qla2x00_min_link_speed_show, NULL);
+static DEVICE_ATTR(max_speed_sup, S_IRUGO, qla2x00_max_speed_sup_show, NULL);
 
 struct device_attribute *qla2x00_host_attrs[] = {
        &dev_attr_driver_version,
@@ -1560,6 +1594,8 @@ struct device_attribute *qla2x00_host_attrs[] = {
        &dev_attr_fw_dump_size,
        &dev_attr_allow_cna_fw_dump,
        &dev_attr_pep_version,
+       &dev_attr_min_link_speed,
+       &dev_attr_max_speed_sup,
        NULL,
 };
 
index 609687d04e3c715cb90fc50a2c32b7af9190ee8b..0f80b812f4a761539a852d38843037dac12f1246 100644 (file)
@@ -902,6 +902,7 @@ struct mbx_cmd_32 {
 #define MBA_SHUTDOWN_REQUESTED 0x8062  /* Shutdown Requested */
 #define MBA_TEMPERATURE_ALERT  0x8070  /* Temperature Alert */
 #define MBA_DPORT_DIAGNOSTICS  0x8080  /* D-port Diagnostics */
+#define MBA_TRANS_INSERT       0x8130  /* Transceiver Insertion */
 #define MBA_FW_INIT_FAILURE    0x8401  /* Firmware initialization failure */
 #define MBA_MIRROR_LUN_CHANGE  0x8402  /* Mirror LUN State Change
                                           Notification */
@@ -4026,6 +4027,8 @@ struct qla_hw_data {
 
        struct qlt_hw_data tgt;
        int     allow_cna_fw_dump;
+       uint16_t min_link_speed;
+       uint16_t max_speed_sup;
 
        atomic_t        nvme_active_aen_cnt;
        uint16_t        nvme_last_rptd_aen;             /* Last recorded aen count */
@@ -4212,6 +4215,7 @@ typedef struct scsi_qla_host {
        int fcport_count;
        wait_queue_head_t fcport_waitQ;
        wait_queue_head_t vref_waitq;
+       uint8_t min_link_speed_feat;
 } scsi_qla_host_t;
 
 struct qla27xx_image_status {
index b9c9886e8b1da6fd6f4fe7bc8937a254352935ba..94eb1694fc3e0170dfc3ed052de6c353198284ae 100644 (file)
@@ -1745,7 +1745,9 @@ struct nvram_81xx {
        uint16_t reserved_6_3[14];
 
        /* Offset 192. */
-       uint16_t reserved_7[32];
+       uint8_t min_link_speed;
+       uint8_t reserved_7_0;
+       uint16_t reserved_7[31];
 
        /*
         * BIT 0  = Enable spinup delay
index c58fb493dbd9f4e167a1d2e3371e6828f6b414de..527c5218e10b1c0d7549c07a0f04c7333eeb2742 100644 (file)
@@ -1233,6 +1233,11 @@ global_port_update:
                        schedule_work(&ha->board_disable);
                break;
 
+       case MBA_TRANS_INSERT:
+               ql_dbg(ql_dbg_async, vha, 0x5091,
+                   "Transceiver Insertion: %04x\n", mb[1]);
+               break;
+
        default:
                ql_dbg(ql_dbg_async, vha, 0x5057,
                    "Unknown AEN:%04x %04x %04x %04x\n",
index da992b761402353ee495adce3bb70a7ee5b4ed5d..32bbbd50567d16f7008801a5088b78a761484483 100644 (file)
@@ -628,6 +628,19 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr)
                if (ql2xnvmeenable && IS_QLA27XX(ha))
                        mcp->mb[4] |= NVME_ENABLE_FLAG;
 
+               if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+                       struct nvram_81xx *nv = ha->nvram;
+                       /* set minimum speed if specified in nvram */
+                       if (nv->min_link_speed >= 2 &&
+                           nv->min_link_speed <= 5) {
+                               mcp->mb[4] |= BIT_4;
+                               mcp->mb[11] = nv->min_link_speed;
+                               mcp->out_mb |= MBX_11;
+                               mcp->in_mb |= BIT_5;
+                               vha->min_link_speed_feat = nv->min_link_speed;
+                       }
+               }
+
                if (ha->flags.exlogins_enabled)
                        mcp->mb[4] |= ENABLE_EXTENDED_LOGIN;
 
@@ -654,8 +667,26 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr)
                    "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
        } else {
                if (IS_FWI2_CAPABLE(ha)) {
+                       ql_dbg(ql_dbg_mbx, vha, 0x1027,
+                           "exchanges=%x.\n", mcp->mb[1]);
+                       if (IS_QLA27XX(ha)) {
+                               ha->max_speed_sup = mcp->mb[2] & 1;
+                               ql_dbg(ql_dbg_mbx, vha, 0x119b,
+                                   "Maximum speed supported=%s.\n",
+                                   ha->max_speed_sup ? "32Gps" : "16Gps");
+                               if (vha->min_link_speed_feat) {
+                                       ha->min_link_speed = mcp->mb[5];
+                                       ql_dbg(ql_dbg_mbx, vha, 0x119c,
+                                           "Minimum speed set=%s.\n",
+                                           mcp->mb[5] == 5 ? "32Gps" :
+                                           mcp->mb[5] == 4 ? "16Gps" :
+                                           mcp->mb[5] == 3 ? "8Gps" :
+                                           mcp->mb[5] == 2 ? "4Gps" :
+                                           "unknown");
+                               }
+                       }
                        ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1027,
-                           "Done exchanges=%x.\n", mcp->mb[1]);
+                           "Done.\n");
                } else {
                        ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1028,
                            "Done %s.\n", __func__);
@@ -1687,7 +1718,11 @@ qla2x00_init_firmware(scsi_qla_host_t *vha, uint16_t size)
                    "Failed=%x mb[0]=%x, mb[1]=%x, mb[2]=%x, mb[3]=%x,.\n",
                    rval, mcp->mb[0], mcp->mb[1], mcp->mb[2], mcp->mb[3]);
        } else {
-               /*EMPTY*/
+               if (IS_QLA27XX(ha)) {
+                       if (mcp->mb[2] == 6 || mcp->mb[3] == 2)
+                               ql_dbg(ql_dbg_mbx, vha, 0x119d,
+                                   "Invalid SFP/Validation Failed\n");
+               }
                ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x104e,
                    "Done %s.\n", __func__);
        }
@@ -1892,6 +1927,7 @@ qla2x00_get_firmware_state(scsi_qla_host_t *vha, uint16_t *states)
        int rval;
        mbx_cmd_t mc;
        mbx_cmd_t *mcp = &mc;
+       struct qla_hw_data *ha = vha->hw;
 
        ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1054,
            "Entered %s.\n", __func__);
@@ -1920,7 +1956,11 @@ qla2x00_get_firmware_state(scsi_qla_host_t *vha, uint16_t *states)
                /*EMPTY*/
                ql_dbg(ql_dbg_mbx, vha, 0x1055, "Failed=%x.\n", rval);
        } else {
-               /*EMPTY*/
+               if (IS_QLA27XX(ha)) {
+                       if (mcp->mb[2] == 6 || mcp->mb[3] == 2)
+                               ql_dbg(ql_dbg_mbx, vha, 0x119e,
+                                   "Invalid SFP/Validation Failed\n");
+               }
                ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1056,
                    "Done %s.\n", __func__);
        }