summaryrefslogtreecommitdiff
path: root/drivers/scsi/qla2xxx/qla_os.c
diff options
context:
space:
mode:
authorQuinn Tran <quinn.tran@cavium.com>2017-08-23 15:05:07 -0700
committerMartin K. Petersen <martin.petersen@oracle.com>2017-08-24 22:29:24 -0400
commite4e3a2ce9556cc4da40dadaf94c0d3395b6e91d9 (patch)
treeec62e4e40a506f2ce542d2d9a70306183ceb6f75 /drivers/scsi/qla2xxx/qla_os.c
parentb2e8ae3f0e342a3308b4573790bd42528e51885a (diff)
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_os.c')
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c36
1 files changed, 35 insertions, 1 deletions
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index fe5148899117..b6b070db5891 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -262,6 +262,12 @@ MODULE_PARM_DESC(ql2xmvasynctoatio,
"0 (Default). Do not move IOCBs"
"1 - Move IOCBs.");
+int ql2xautodetectsfp = 1;
+module_param(ql2xautodetectsfp, int, 0444);
+MODULE_PARM_DESC(ql2xautodetectsfp,
+ "Detect SFP range and set appropriate distance.\n"
+ "1 (Default): Enable\n");
+
/*
* SCSI host template entry points
*/
@@ -3330,6 +3336,13 @@ skip_dpc:
if (test_bit(UNLOADING, &base_vha->dpc_flags))
return -ENODEV;
+ if (ha->flags.detected_lr_sfp) {
+ ql_log(ql_log_info, base_vha, 0xffff,
+ "Reset chip to pick up LR SFP setting\n");
+ set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags);
+ qla2xxx_wake_dpc(base_vha);
+ }
+
return 0;
probe_init_failed:
@@ -4019,8 +4032,18 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
"loop_id_map=%p.\n", ha->loop_id_map);
}
+ ha->sfp_data = dma_alloc_coherent(&ha->pdev->dev,
+ SFP_DEV_SIZE, &ha->sfp_data_dma, GFP_KERNEL);
+ if (!ha->sfp_data) {
+ ql_dbg_pci(ql_dbg_init, ha->pdev, 0x011b,
+ "Unable to allocate memory for SFP read-data.\n");
+ goto fail_sfp_data;
+ }
+
return 0;
+fail_sfp_data:
+ kfree(ha->loop_id_map);
fail_loop_id_map:
dma_pool_free(ha->s_dma_pool, ha->async_pd, ha->async_pd_dma);
fail_async_pd:
@@ -4358,7 +4381,8 @@ qla2x00_mem_free(struct qla_hw_data *ha)
ha->ct_sns, ha->ct_sns_dma);
if (ha->sfp_data)
- dma_pool_free(ha->s_dma_pool, ha->sfp_data, ha->sfp_data_dma);
+ dma_free_coherent(&ha->pdev->dev, SFP_DEV_SIZE, ha->sfp_data,
+ ha->sfp_data_dma);
if (ha->ms_iocb)
dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma);
@@ -5707,6 +5731,16 @@ qla2x00_do_dpc(void *data)
}
}
+ if (test_and_clear_bit(DETECT_SFP_CHANGE,
+ &base_vha->dpc_flags) &&
+ !test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags)) {
+ qla24xx_detect_sfp(base_vha);
+
+ if (ha->flags.detected_lr_sfp !=
+ ha->flags.using_lr_setting)
+ set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags);
+ }
+
if (test_and_clear_bit(ISP_ABORT_NEEDED,
&base_vha->dpc_flags)) {