diff options
author | Quinn Tran <quinn.tran@cavium.com> | 2017-08-23 15:05:07 -0700 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2017-08-24 22:29:24 -0400 |
commit | e4e3a2ce9556cc4da40dadaf94c0d3395b6e91d9 (patch) | |
tree | ec62e4e40a506f2ce542d2d9a70306183ceb6f75 /drivers/scsi/qla2xxx/qla_mbx.c | |
parent | b2e8ae3f0e342a3308b4573790bd42528e51885a (diff) | |
download | linux-e4e3a2ce9556cc4da40dadaf94c0d3395b6e91d9.tar.bz2 |
scsi: qla2xxx: Add ability to autodetect SFP type
SFP can come in 2 formats: short range/SR and long range/LR. For LR,
user the can increase the number of Buffer to Buffer credits between end
points via Cavium's command line tool. By default, FW uses a lower BB
Credit value optimized for SR. This patch will read the SFP for each
link up event and during chip reset sequence. If the SFP type and
setting are mismatch, then the chip is reset 1 time to use the
appropriate setting.
Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_mbx.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mbx.c | 83 |
1 files changed, 78 insertions, 5 deletions
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index f101aaa5254b..52cb9882bf31 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -57,6 +57,7 @@ static struct rom_cmd { { MBC_INITIALIZE_MULTIQ }, { MBC_IOCB_COMMAND_A64 }, { MBC_GET_ADAPTER_LOOP_ID }, + { MBC_READ_SFP }, }; static int is_rom_cmd(uint16_t cmd) @@ -598,13 +599,29 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr) mcp->mb[1] = MSW(risc_addr); mcp->mb[2] = LSW(risc_addr); mcp->mb[3] = 0; + mcp->mb[4] = 0; if (IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha)) { - struct nvram_81xx *nv = ha->nvram; - mcp->mb[4] = (nv->enhanced_features & - EXTENDED_BB_CREDITS); - } else - mcp->mb[4] = 0; + 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; + ha->flags.using_lr_setting = 1; + } + } else { + struct nvram_81xx *nv = ha->nvram; + + if (nv->enhanced_features & + EXTENDED_BB_CREDITS) { + mcp->mb[4] |= EXTENDED_BB_CREDITS; + ha->flags.using_lr_setting = 1; + } + } + } else { + ha->flags.using_lr_setting = 0; + } if (ql2xnvmeenable && IS_QLA27XX(ha)) mcp->mb[4] |= NVME_ENABLE_FLAG; @@ -4585,6 +4602,10 @@ qla2x00_read_sfp(scsi_qla_host_t *vha, dma_addr_t sfp_dma, uint8_t *sfp, if (rval != QLA_SUCCESS) { ql_dbg(ql_dbg_mbx, vha, 0x10e9, "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]); + if (mcp->mb[0] == MBS_COMMAND_ERROR && + mcp->mb[1] == 0x22) + /* sfp is not there */ + rval = QLA_INTERFACE_ERROR; } else { ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ea, "Done %s.\n", __func__); @@ -6133,3 +6154,55 @@ int qla27xx_get_zio_threshold(scsi_qla_host_t *vha, uint16_t *value) return rval; } + +int +qla2x00_read_sfp_dev(struct scsi_qla_host *vha, char *buf, int count) +{ + struct qla_hw_data *ha = vha->hw; + uint16_t iter, addr, offset; + dma_addr_t phys_addr; + int rval, c; + u8 *sfp_data; + + memset(ha->sfp_data, 0, SFP_DEV_SIZE); + addr = 0xa0; + phys_addr = ha->sfp_data_dma; + sfp_data = ha->sfp_data; + offset = c = 0; + + for (iter = 0; iter < SFP_DEV_SIZE / SFP_BLOCK_SIZE; iter++) { + if (iter == 4) { + /* Skip to next device address. */ + addr = 0xa2; + offset = 0; + } + + rval = qla2x00_read_sfp(vha, phys_addr, sfp_data, + addr, offset, SFP_BLOCK_SIZE, BIT_1); + if (rval != QLA_SUCCESS) { + ql_log(ql_log_warn, vha, 0x706d, + "Unable to read SFP data (%x/%x/%x).\n", rval, + addr, offset); + + return rval; + } + + if (buf && (c < count)) { + u16 sz; + + if ((count - c) >= SFP_BLOCK_SIZE) + sz = SFP_BLOCK_SIZE; + else + sz = count - c; + + memcpy(buf, sfp_data, sz); + buf += SFP_BLOCK_SIZE; + c += sz; + } + phys_addr += SFP_BLOCK_SIZE; + sfp_data += SFP_BLOCK_SIZE; + offset += SFP_BLOCK_SIZE; + } + + return rval; +} |