scsi: qla2xxx: Add LR distance support from nvram bit
authorJoe Carnuccio <joe.carnuccio@cavium.com>
Wed, 23 Aug 2017 22:05:17 +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: 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_def.h
drivers/scsi/qla2xxx/qla_fw.h
drivers/scsi/qla2xxx/qla_mbx.c

index 0f80b812f4a761539a852d38843037dac12f1246..486c075998f635e34b95d7ce1ea20ee632abfcd2 100644 (file)
@@ -3471,7 +3471,7 @@ struct qla_hw_data {
                uint32_t        using_lr_setting:1;
        } flags;
 
-       u8 long_range_distance; /* 32G & above */
+       uint16_t long_range_distance;   /* 32G & above */
 #define LR_DISTANCE_5K  1
 #define LR_DISTANCE_10K 0
 
@@ -4027,6 +4027,7 @@ struct qla_hw_data {
 
        struct qlt_hw_data tgt;
        int     allow_cna_fw_dump;
+       uint32_t fw_ability_mask;
        uint16_t min_link_speed;
        uint16_t max_speed_sup;
 
@@ -4034,6 +4035,12 @@ struct qla_hw_data {
        uint16_t        nvme_last_rptd_aen;             /* Last recorded aen count */
 };
 
+#define FW_ABILITY_MAX_SPEED_MASK      0xFUL
+#define FW_ABILITY_MAX_SPEED_16G       0x0
+#define FW_ABILITY_MAX_SPEED_32G       0x1
+#define FW_ABILITY_MAX_SPEED(ha)       \
+       (ha->fw_ability_mask & FW_ABILITY_MAX_SPEED_MASK)
+
 /*
  * Qlogic scsi host structure
  */
index 94eb1694fc3e0170dfc3ed052de6c353198284ae..bec641aae7b35e69b18f0411d5906c385b247e09 100644 (file)
@@ -1699,6 +1699,15 @@ struct access_chip_rsp_84xx {
 #define FAC_OPT_CMD_UNLOCK_SEMAPHORE   0x04
 #define FAC_OPT_CMD_GET_SECTOR_SIZE    0x05
 
+/* enhanced features bit definitions */
+#define NEF_LR_DIST_ENABLE     BIT_0
+
+/* LR Distance bit positions */
+#define LR_DIST_NV_POS         2
+#define LR_DIST_FW_POS         12
+#define LR_DIST_FW_SHIFT       (LR_DIST_FW_POS - LR_DIST_NV_POS)
+#define LR_DIST_FW_FIELD(x)    ((x) << LR_DIST_FW_SHIFT & 0xf000)
+
 struct nvram_81xx {
        /* NVRAM header. */
        uint8_t id[4];
@@ -1841,16 +1850,13 @@ struct nvram_81xx {
        uint8_t reserved_21[16];
        uint16_t reserved_22[3];
 
-       /*
-        * BIT 0 = Extended BB credits for LR
-        * BIT 1 = Virtual Fabric Enable
-        * BIT 2 = Enhanced Features Unused
-        * BIT 3-7 = Enhanced Features Reserved
+       /* Offset 406 (0x196) Enhanced Features
+        * BIT 0    = Extended BB credits for LR
+        * BIT 1    = Virtual Fabric Enable
+        * BIT 2-5  = Distance Support if BIT 0 is on
+        * BIT 6-15 = Unused
         */
-       /* Enhanced Features */
-       uint8_t enhanced_features;
-
-       uint8_t reserved_23;
+       uint16_t enhanced_features;
        uint16_t reserved_24[4];
 
        /* Offset 416. */
index 32bbbd50567d16f7008801a5088b78a761484483..99502fa908103f39d10cd1930d994f9067f445a4 100644 (file)
@@ -567,6 +567,28 @@ qla2x00_load_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t risc_addr,
 
 #define        EXTENDED_BB_CREDITS     BIT_0
 #define        NVME_ENABLE_FLAG        BIT_3
+static inline uint16_t qla25xx_set_sfp_lr_dist(struct qla_hw_data *ha)
+{
+       uint16_t mb4 = BIT_0;
+
+       if (IS_QLA83XX(ha) || IS_QLA27XX(ha))
+               mb4 |= ha->long_range_distance << LR_DIST_FW_POS;
+
+       return mb4;
+}
+
+static inline uint16_t qla25xx_set_nvr_lr_dist(struct qla_hw_data *ha)
+{
+       uint16_t mb4 = BIT_0;
+
+       if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+               struct nvram_81xx *nv = ha->nvram;
+
+               mb4 |= LR_DIST_FW_FIELD(nv->enhanced_features);
+       }
+
+       return mb4;
+}
 
 /*
  * qla2x00_execute_fw
@@ -602,27 +624,25 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr)
                mcp->mb[2] = LSW(risc_addr);
                mcp->mb[3] = 0;
                mcp->mb[4] = 0;
+               ha->flags.using_lr_setting = 0;
                if (IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) ||
                    IS_QLA27XX(ha)) {
                        if (ql2xautodetectsfp) {
                                if (ha->flags.detected_lr_sfp) {
-                                       mcp->mb[4] |= EXTENDED_BB_CREDITS;
-                                       if (IS_QLA27XX(ha))
-                                               mcp->mb[4] |=
-                                       (u16)ha->long_range_distance << 12;
+                                       mcp->mb[4] |=
+                                           qla25xx_set_sfp_lr_dist(ha);
                                        ha->flags.using_lr_setting = 1;
                                }
                        } else {
                                struct nvram_81xx *nv = ha->nvram;
-
+                               /* set LR distance if specified in nvram */
                                if (nv->enhanced_features &
-                                   EXTENDED_BB_CREDITS) {
-                                       mcp->mb[4] |= EXTENDED_BB_CREDITS;
+                                   NEF_LR_DIST_ENABLE) {
+                                       mcp->mb[4] |=
+                                           qla25xx_set_nvr_lr_dist(ha);
                                        ha->flags.using_lr_setting = 1;
                                }
                        }
-               } else {
-                       ha->flags.using_lr_setting = 0;
                }
 
                if (ql2xnvmeenable && IS_QLA27XX(ha))
@@ -648,7 +668,7 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr)
                        mcp->mb[4] |= ENABLE_EXCHANGE_OFFLD;
 
                mcp->out_mb |= MBX_4|MBX_3|MBX_2|MBX_1;
-               mcp->in_mb |= MBX_1;
+               mcp->in_mb |= MBX_3 | MBX_2 | MBX_1;
        } else {
                mcp->mb[1] = LSW(risc_addr);
                mcp->out_mb |= MBX_1;
@@ -667,10 +687,13 @@ 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)) {
+                       ha->fw_ability_mask = mcp->mb[3] << 16 | mcp->mb[2];
+                       ql_dbg(ql_dbg_mbx, vha, 0x119a,
+                           "fw_ability_mask=%x.\n", ha->fw_ability_mask);
                        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;
+                       if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+                               ha->max_speed_sup = mcp->mb[2] & BIT_0;
                                ql_dbg(ql_dbg_mbx, vha, 0x119b,
                                    "Maximum speed supported=%s.\n",
                                    ha->max_speed_sup ? "32Gps" : "16Gps");
@@ -682,15 +705,12 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr)
                                            mcp->mb[5] == 4 ? "16Gps" :
                                            mcp->mb[5] == 3 ? "8Gps" :
                                            mcp->mb[5] == 2 ? "4Gps" :
-                                           "unknown");
+                                               "unknown");
                                }
                        }
-                       ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1027,
-                           "Done.\n");
-               } else {
-                       ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1028,
-                           "Done %s.\n", __func__);
                }
+               ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1028,
+                   "Done.\n");
        }
 
        return rval;