diff options
author | Chad Dupuis <chad.dupuis@qlogic.com> | 2013-01-30 03:34:38 -0500 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2013-02-22 06:29:49 -0500 |
commit | 3c290d0b5f8ff7b0fd2c964c5ec2c14191a9e790 (patch) | |
tree | aeabbf158d1efef3689782c996685a2630de289c | |
parent | 8d93f5502221cc8eb420da65dc86a5ef07b038d0 (diff) |
[SCSI] qla2xxx: Ramp down queue depth for attached SCSI devices when driver resources are low.
Signed-off-by: Chad Dupuis <chad.dupuis@qlogic.com>
Signed-off-by: Saurav Kashyap <saurav.kashyap@qlogic.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r-- | drivers/scsi/qla2xxx/qla_dbg.c | 2 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_def.h | 9 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_gbl.h | 1 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_inline.h | 19 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 4 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 107 |
6 files changed, 135 insertions, 7 deletions
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 2f3e7655db0d..f7cdd259ef0b 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c | |||
@@ -17,7 +17,7 @@ | |||
17 | * | | | 0x113a | | 17 | * | | | 0x113a | |
18 | * | Device Discovery | 0x2087 | 0x2020-0x2022, | | 18 | * | Device Discovery | 0x2087 | 0x2020-0x2022, | |
19 | * | | | 0x2016 | | 19 | * | | | 0x2016 | |
20 | * | Queue Command and IO tracing | 0x3030 | 0x3006-0x300b | | 20 | * | Queue Command and IO tracing | 0x3031 | 0x3006-0x300b | |
21 | * | | | 0x3027-0x3028 | | 21 | * | | | 0x3027-0x3028 | |
22 | * | | | 0x302d-0x302e | | 22 | * | | | 0x302d-0x302e | |
23 | * | DPC Thread | 0x401d | 0x4002,0x4013 | | 23 | * | DPC Thread | 0x401d | 0x4002,0x4013 | |
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index a84bb8d6ff74..06c6271d5911 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h | |||
@@ -2536,6 +2536,7 @@ struct req_que { | |||
2536 | srb_t **outstanding_cmds; | 2536 | srb_t **outstanding_cmds; |
2537 | uint32_t current_outstanding_cmd; | 2537 | uint32_t current_outstanding_cmd; |
2538 | uint16_t num_outstanding_cmds; | 2538 | uint16_t num_outstanding_cmds; |
2539 | #define MAX_Q_DEPTH 32 | ||
2539 | int max_q_depth; | 2540 | int max_q_depth; |
2540 | }; | 2541 | }; |
2541 | 2542 | ||
@@ -3058,6 +3059,12 @@ struct qla_hw_data { | |||
3058 | struct work_struct idc_state_handler; | 3059 | struct work_struct idc_state_handler; |
3059 | struct work_struct nic_core_unrecoverable; | 3060 | struct work_struct nic_core_unrecoverable; |
3060 | 3061 | ||
3062 | #define HOST_QUEUE_RAMPDOWN_INTERVAL (60 * HZ) | ||
3063 | #define HOST_QUEUE_RAMPUP_INTERVAL (30 * HZ) | ||
3064 | unsigned long host_last_rampdown_time; | ||
3065 | unsigned long host_last_rampup_time; | ||
3066 | int cfg_lun_q_depth; | ||
3067 | |||
3061 | struct qlt_hw_data tgt; | 3068 | struct qlt_hw_data tgt; |
3062 | }; | 3069 | }; |
3063 | 3070 | ||
@@ -3117,6 +3124,8 @@ typedef struct scsi_qla_host { | |||
3117 | #define MPI_RESET_NEEDED 19 /* Initiate MPI FW reset */ | 3124 | #define MPI_RESET_NEEDED 19 /* Initiate MPI FW reset */ |
3118 | #define ISP_QUIESCE_NEEDED 20 /* Driver need some quiescence */ | 3125 | #define ISP_QUIESCE_NEEDED 20 /* Driver need some quiescence */ |
3119 | #define SCR_PENDING 21 /* SCR in target mode */ | 3126 | #define SCR_PENDING 21 /* SCR in target mode */ |
3127 | #define HOST_RAMP_DOWN_QUEUE_DEPTH 22 | ||
3128 | #define HOST_RAMP_UP_QUEUE_DEPTH 23 | ||
3120 | 3129 | ||
3121 | uint32_t device_flags; | 3130 | uint32_t device_flags; |
3122 | #define SWITCH_FOUND BIT_0 | 3131 | #define SWITCH_FOUND BIT_0 |
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index fba0651f678e..1732713e80cc 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h | |||
@@ -97,6 +97,7 @@ extern int qlport_down_retry; | |||
97 | extern int ql2xplogiabsentdevice; | 97 | extern int ql2xplogiabsentdevice; |
98 | extern int ql2xloginretrycount; | 98 | extern int ql2xloginretrycount; |
99 | extern int ql2xfdmienable; | 99 | extern int ql2xfdmienable; |
100 | extern int ql2xmaxqdepth; | ||
100 | extern int ql2xallocfwdump; | 101 | extern int ql2xallocfwdump; |
101 | extern int ql2xextended_error_logging; | 102 | extern int ql2xextended_error_logging; |
102 | extern int ql2xiidmaenable; | 103 | extern int ql2xiidmaenable; |
diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h index c0462c04c885..deb8618d1b81 100644 --- a/drivers/scsi/qla2xxx/qla_inline.h +++ b/drivers/scsi/qla2xxx/qla_inline.h | |||
@@ -213,3 +213,22 @@ qla2x00_gid_list_size(struct qla_hw_data *ha) | |||
213 | { | 213 | { |
214 | return sizeof(struct gid_list_info) * ha->max_fibre_devices; | 214 | return sizeof(struct gid_list_info) * ha->max_fibre_devices; |
215 | } | 215 | } |
216 | |||
217 | static inline void | ||
218 | qla2x00_do_host_ramp_up(scsi_qla_host_t *vha) | ||
219 | { | ||
220 | if (vha->hw->cfg_lun_q_depth >= ql2xmaxqdepth) | ||
221 | return; | ||
222 | |||
223 | /* Wait at least HOST_QUEUE_RAMPDOWN_INTERVAL before ramping up */ | ||
224 | if (time_before(jiffies, (vha->hw->host_last_rampdown_time + | ||
225 | HOST_QUEUE_RAMPDOWN_INTERVAL))) | ||
226 | return; | ||
227 | |||
228 | /* Wait at least HOST_QUEUE_RAMPUP_INTERVAL between each ramp up */ | ||
229 | if (time_before(jiffies, (vha->hw->host_last_rampup_time + | ||
230 | HOST_QUEUE_RAMPUP_INTERVAL))) | ||
231 | return; | ||
232 | |||
233 | set_bit(HOST_RAMP_UP_QUEUE_DEPTH, &vha->dpc_flags); | ||
234 | } | ||
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 45130738c2bf..1b192c8bb133 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c | |||
@@ -1934,6 +1934,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) | |||
1934 | 1934 | ||
1935 | /* Fast path completion. */ | 1935 | /* Fast path completion. */ |
1936 | if (comp_status == CS_COMPLETE && scsi_status == 0) { | 1936 | if (comp_status == CS_COMPLETE && scsi_status == 0) { |
1937 | qla2x00_do_host_ramp_up(vha); | ||
1937 | qla2x00_process_completed_request(vha, req, handle); | 1938 | qla2x00_process_completed_request(vha, req, handle); |
1938 | 1939 | ||
1939 | return; | 1940 | return; |
@@ -2193,6 +2194,9 @@ out: | |||
2193 | cp->cmnd[8], cp->cmnd[9], scsi_bufflen(cp), rsp_info_len, | 2194 | cp->cmnd[8], cp->cmnd[9], scsi_bufflen(cp), rsp_info_len, |
2194 | resid_len, fw_resid_len); | 2195 | resid_len, fw_resid_len); |
2195 | 2196 | ||
2197 | if (!res) | ||
2198 | qla2x00_do_host_ramp_up(vha); | ||
2199 | |||
2196 | if (rsp->status_srb == NULL) | 2200 | if (rsp->status_srb == NULL) |
2197 | sp->done(ha, sp, res); | 2201 | sp->done(ha, sp, res); |
2198 | } | 2202 | } |
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 53efffce13a2..da86d3828c1d 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
@@ -111,8 +111,7 @@ MODULE_PARM_DESC(ql2xfdmienable, | |||
111 | "Enables FDMI registrations. " | 111 | "Enables FDMI registrations. " |
112 | "0 - no FDMI. Default is 1 - perform FDMI."); | 112 | "0 - no FDMI. Default is 1 - perform FDMI."); |
113 | 113 | ||
114 | #define MAX_Q_DEPTH 32 | 114 | int ql2xmaxqdepth = MAX_Q_DEPTH; |
115 | static int ql2xmaxqdepth = MAX_Q_DEPTH; | ||
116 | module_param(ql2xmaxqdepth, int, S_IRUGO|S_IWUSR); | 115 | module_param(ql2xmaxqdepth, int, S_IRUGO|S_IWUSR); |
117 | MODULE_PARM_DESC(ql2xmaxqdepth, | 116 | MODULE_PARM_DESC(ql2xmaxqdepth, |
118 | "Maximum queue depth to set for each LUN. " | 117 | "Maximum queue depth to set for each LUN. " |
@@ -720,8 +719,10 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) | |||
720 | } | 719 | } |
721 | 720 | ||
722 | sp = qla2x00_get_sp(base_vha, fcport, GFP_ATOMIC); | 721 | sp = qla2x00_get_sp(base_vha, fcport, GFP_ATOMIC); |
723 | if (!sp) | 722 | if (!sp) { |
723 | set_bit(HOST_RAMP_DOWN_QUEUE_DEPTH, &vha->dpc_flags); | ||
724 | goto qc24_host_busy; | 724 | goto qc24_host_busy; |
725 | } | ||
725 | 726 | ||
726 | sp->u.scmd.cmd = cmd; | 727 | sp->u.scmd.cmd = cmd; |
727 | sp->type = SRB_SCSI_CMD; | 728 | sp->type = SRB_SCSI_CMD; |
@@ -734,6 +735,7 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) | |||
734 | if (rval != QLA_SUCCESS) { | 735 | if (rval != QLA_SUCCESS) { |
735 | ql_dbg(ql_dbg_io + ql_dbg_verbose, vha, 0x3013, | 736 | ql_dbg(ql_dbg_io + ql_dbg_verbose, vha, 0x3013, |
736 | "Start scsi failed rval=%d for cmd=%p.\n", rval, cmd); | 737 | "Start scsi failed rval=%d for cmd=%p.\n", rval, cmd); |
738 | set_bit(HOST_RAMP_DOWN_QUEUE_DEPTH, &vha->dpc_flags); | ||
737 | goto qc24_host_busy_free_sp; | 739 | goto qc24_host_busy_free_sp; |
738 | } | 740 | } |
739 | 741 | ||
@@ -1458,6 +1460,81 @@ qla2x00_change_queue_type(struct scsi_device *sdev, int tag_type) | |||
1458 | return tag_type; | 1460 | return tag_type; |
1459 | } | 1461 | } |
1460 | 1462 | ||
1463 | static void | ||
1464 | qla2x00_host_ramp_down_queuedepth(scsi_qla_host_t *vha) | ||
1465 | { | ||
1466 | scsi_qla_host_t *vp; | ||
1467 | struct Scsi_Host *shost; | ||
1468 | struct scsi_device *sdev; | ||
1469 | struct qla_hw_data *ha = vha->hw; | ||
1470 | unsigned long flags; | ||
1471 | |||
1472 | ha->host_last_rampdown_time = jiffies; | ||
1473 | |||
1474 | if (ha->cfg_lun_q_depth <= vha->host->cmd_per_lun) | ||
1475 | return; | ||
1476 | |||
1477 | if ((ha->cfg_lun_q_depth / 2) < vha->host->cmd_per_lun) | ||
1478 | ha->cfg_lun_q_depth = vha->host->cmd_per_lun; | ||
1479 | else | ||
1480 | ha->cfg_lun_q_depth = ha->cfg_lun_q_depth / 2; | ||
1481 | |||
1482 | /* | ||
1483 | * Geometrically ramp down the queue depth for all devices on this | ||
1484 | * adapter | ||
1485 | */ | ||
1486 | spin_lock_irqsave(&ha->vport_slock, flags); | ||
1487 | list_for_each_entry(vp, &ha->vp_list, list) { | ||
1488 | shost = vp->host; | ||
1489 | shost_for_each_device(sdev, shost) { | ||
1490 | if (sdev->queue_depth > shost->cmd_per_lun) { | ||
1491 | if (sdev->queue_depth < ha->cfg_lun_q_depth) | ||
1492 | continue; | ||
1493 | ql_log(ql_log_warn, vp, 0x3031, | ||
1494 | "%ld:%d:%d: Ramping down queue depth to %d", | ||
1495 | vp->host_no, sdev->id, sdev->lun, | ||
1496 | ha->cfg_lun_q_depth); | ||
1497 | qla2x00_change_queue_depth(sdev, | ||
1498 | ha->cfg_lun_q_depth, SCSI_QDEPTH_DEFAULT); | ||
1499 | } | ||
1500 | } | ||
1501 | } | ||
1502 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
1503 | |||
1504 | return; | ||
1505 | } | ||
1506 | |||
1507 | static void | ||
1508 | qla2x00_host_ramp_up_queuedepth(scsi_qla_host_t *vha) | ||
1509 | { | ||
1510 | scsi_qla_host_t *vp; | ||
1511 | struct Scsi_Host *shost; | ||
1512 | struct scsi_device *sdev; | ||
1513 | struct qla_hw_data *ha = vha->hw; | ||
1514 | unsigned long flags; | ||
1515 | |||
1516 | ha->host_last_rampup_time = jiffies; | ||
1517 | ha->cfg_lun_q_depth++; | ||
1518 | |||
1519 | /* | ||
1520 | * Linearly ramp up the queue depth for all devices on this | ||
1521 | * adapter | ||
1522 | */ | ||
1523 | spin_lock_irqsave(&ha->vport_slock, flags); | ||
1524 | list_for_each_entry(vp, &ha->vp_list, list) { | ||
1525 | shost = vp->host; | ||
1526 | shost_for_each_device(sdev, shost) { | ||
1527 | if (sdev->queue_depth > ha->cfg_lun_q_depth) | ||
1528 | continue; | ||
1529 | qla2x00_change_queue_depth(sdev, ha->cfg_lun_q_depth, | ||
1530 | SCSI_QDEPTH_RAMP_UP); | ||
1531 | } | ||
1532 | } | ||
1533 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
1534 | |||
1535 | return; | ||
1536 | } | ||
1537 | |||
1461 | /** | 1538 | /** |
1462 | * qla2x00_config_dma_addressing() - Configure OS DMA addressing method. | 1539 | * qla2x00_config_dma_addressing() - Configure OS DMA addressing method. |
1463 | * @ha: HA context | 1540 | * @ha: HA context |
@@ -2235,6 +2312,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2235 | ha->init_cb_size = sizeof(init_cb_t); | 2312 | ha->init_cb_size = sizeof(init_cb_t); |
2236 | ha->link_data_rate = PORT_SPEED_UNKNOWN; | 2313 | ha->link_data_rate = PORT_SPEED_UNKNOWN; |
2237 | ha->optrom_size = OPTROM_SIZE_2300; | 2314 | ha->optrom_size = OPTROM_SIZE_2300; |
2315 | ha->cfg_lun_q_depth = ql2xmaxqdepth; | ||
2238 | 2316 | ||
2239 | /* Assign ISP specific operations. */ | 2317 | /* Assign ISP specific operations. */ |
2240 | if (IS_QLA2100(ha)) { | 2318 | if (IS_QLA2100(ha)) { |
@@ -4610,6 +4688,18 @@ qla2x00_do_dpc(void *data) | |||
4610 | qla2xxx_flash_npiv_conf(base_vha); | 4688 | qla2xxx_flash_npiv_conf(base_vha); |
4611 | } | 4689 | } |
4612 | 4690 | ||
4691 | if (test_and_clear_bit(HOST_RAMP_DOWN_QUEUE_DEPTH, | ||
4692 | &base_vha->dpc_flags)) { | ||
4693 | /* Prevents simultaneous ramp up and down */ | ||
4694 | clear_bit(HOST_RAMP_UP_QUEUE_DEPTH, | ||
4695 | &base_vha->dpc_flags); | ||
4696 | qla2x00_host_ramp_down_queuedepth(base_vha); | ||
4697 | } | ||
4698 | |||
4699 | if (test_and_clear_bit(HOST_RAMP_UP_QUEUE_DEPTH, | ||
4700 | &base_vha->dpc_flags)) | ||
4701 | qla2x00_host_ramp_up_queuedepth(base_vha); | ||
4702 | |||
4613 | if (!ha->interrupts_on) | 4703 | if (!ha->interrupts_on) |
4614 | ha->isp_ops->enable_intrs(ha); | 4704 | ha->isp_ops->enable_intrs(ha); |
4615 | 4705 | ||
@@ -4807,7 +4897,9 @@ qla2x00_timer(scsi_qla_host_t *vha) | |||
4807 | test_bit(ISP_UNRECOVERABLE, &vha->dpc_flags) || | 4897 | test_bit(ISP_UNRECOVERABLE, &vha->dpc_flags) || |
4808 | test_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags) || | 4898 | test_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags) || |
4809 | test_bit(VP_DPC_NEEDED, &vha->dpc_flags) || | 4899 | test_bit(VP_DPC_NEEDED, &vha->dpc_flags) || |
4810 | test_bit(RELOGIN_NEEDED, &vha->dpc_flags))) { | 4900 | test_bit(RELOGIN_NEEDED, &vha->dpc_flags) || |
4901 | test_bit(HOST_RAMP_DOWN_QUEUE_DEPTH, &vha->dpc_flags) || | ||
4902 | test_bit(HOST_RAMP_UP_QUEUE_DEPTH, &vha->dpc_flags))) { | ||
4811 | ql_dbg(ql_dbg_timer, vha, 0x600b, | 4903 | ql_dbg(ql_dbg_timer, vha, 0x600b, |
4812 | "isp_abort_needed=%d loop_resync_needed=%d " | 4904 | "isp_abort_needed=%d loop_resync_needed=%d " |
4813 | "fcport_update_needed=%d start_dpc=%d " | 4905 | "fcport_update_needed=%d start_dpc=%d " |
@@ -4820,12 +4912,15 @@ qla2x00_timer(scsi_qla_host_t *vha) | |||
4820 | ql_dbg(ql_dbg_timer, vha, 0x600c, | 4912 | ql_dbg(ql_dbg_timer, vha, 0x600c, |
4821 | "beacon_blink_needed=%d isp_unrecoverable=%d " | 4913 | "beacon_blink_needed=%d isp_unrecoverable=%d " |
4822 | "fcoe_ctx_reset_needed=%d vp_dpc_needed=%d " | 4914 | "fcoe_ctx_reset_needed=%d vp_dpc_needed=%d " |
4823 | "relogin_needed=%d.\n", | 4915 | "relogin_needed=%d, host_ramp_down_needed=%d " |
4916 | "host_ramp_up_needed=%d.\n", | ||
4824 | test_bit(BEACON_BLINK_NEEDED, &vha->dpc_flags), | 4917 | test_bit(BEACON_BLINK_NEEDED, &vha->dpc_flags), |
4825 | test_bit(ISP_UNRECOVERABLE, &vha->dpc_flags), | 4918 | test_bit(ISP_UNRECOVERABLE, &vha->dpc_flags), |
4826 | test_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags), | 4919 | test_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags), |
4827 | test_bit(VP_DPC_NEEDED, &vha->dpc_flags), | 4920 | test_bit(VP_DPC_NEEDED, &vha->dpc_flags), |
4828 | test_bit(RELOGIN_NEEDED, &vha->dpc_flags)); | 4921 | test_bit(RELOGIN_NEEDED, &vha->dpc_flags), |
4922 | test_bit(HOST_RAMP_UP_QUEUE_DEPTH, &vha->dpc_flags), | ||
4923 | test_bit(HOST_RAMP_DOWN_QUEUE_DEPTH, &vha->dpc_flags)); | ||
4829 | qla2xxx_wake_dpc(vha); | 4924 | qla2xxx_wake_dpc(vha); |
4830 | } | 4925 | } |
4831 | 4926 | ||