diff options
author | Andrew Vasquez <andrew.vasquez@qlogic.com> | 2006-10-13 12:33:39 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-10-25 18:13:08 -0400 |
commit | df7baa506c2db1c2d12abd6f05c43f911da55a2e (patch) | |
tree | 0914b8f01b031312246fc7ddbadb358f3bdff667 /drivers/scsi/qla2xxx | |
parent | 18c6c12759813c988bb05796d1b3352e98ae77de (diff) |
[SCSI] qla2xxx: Correct QUEUE_FULL handling.
- Drop queue-depths across all luns for a given fcport
during TASK_SET_FULL statuses.
- Ramp-up I/Os after throttling.
- Consolidate completion-status handling of CS_QUEUE_FULL with
CS_COMPLETE as ISP24xx firmware no longer reports
CS_QUEUE_FULL.
Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/qla2xxx')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_def.h | 4 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_gbl.h | 1 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 91 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 21 |
4 files changed, 104 insertions, 13 deletions
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index bab33f6d0bdb..c4fc40f8e8ca 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h | |||
@@ -1545,6 +1545,9 @@ typedef struct fc_port { | |||
1545 | spinlock_t rport_lock; | 1545 | spinlock_t rport_lock; |
1546 | struct fc_rport *rport, *drport; | 1546 | struct fc_rport *rport, *drport; |
1547 | u32 supported_classes; | 1547 | u32 supported_classes; |
1548 | |||
1549 | unsigned long last_queue_full; | ||
1550 | unsigned long last_ramp_up; | ||
1548 | } fc_port_t; | 1551 | } fc_port_t; |
1549 | 1552 | ||
1550 | /* | 1553 | /* |
@@ -2255,6 +2258,7 @@ typedef struct scsi_qla_host { | |||
2255 | uint16_t mgmt_svr_loop_id; | 2258 | uint16_t mgmt_svr_loop_id; |
2256 | 2259 | ||
2257 | uint32_t login_retry_count; | 2260 | uint32_t login_retry_count; |
2261 | int max_q_depth; | ||
2258 | 2262 | ||
2259 | /* Fibre Channel Device List. */ | 2263 | /* Fibre Channel Device List. */ |
2260 | struct list_head fcports; | 2264 | struct list_head fcports; |
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index ca2f660a5438..32ebeec45ff0 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h | |||
@@ -62,6 +62,7 @@ extern int ql2xloginretrycount; | |||
62 | extern int ql2xfdmienable; | 62 | extern int ql2xfdmienable; |
63 | extern int ql2xallocfwdump; | 63 | extern int ql2xallocfwdump; |
64 | extern int ql2xextended_error_logging; | 64 | extern int ql2xextended_error_logging; |
65 | extern int ql2xqfullrampup; | ||
65 | 66 | ||
66 | extern void qla2x00_sp_compl(scsi_qla_host_t *, srb_t *); | 67 | extern void qla2x00_sp_compl(scsi_qla_host_t *, srb_t *); |
67 | 68 | ||
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 626c7178a434..d3b6df4d55c8 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c | |||
@@ -6,6 +6,8 @@ | |||
6 | */ | 6 | */ |
7 | #include "qla_def.h" | 7 | #include "qla_def.h" |
8 | 8 | ||
9 | #include <scsi/scsi_tcq.h> | ||
10 | |||
9 | static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t); | 11 | static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t); |
10 | static void qla2x00_async_event(scsi_qla_host_t *, uint16_t *); | 12 | static void qla2x00_async_event(scsi_qla_host_t *, uint16_t *); |
11 | static void qla2x00_process_completed_request(struct scsi_qla_host *, uint32_t); | 13 | static void qla2x00_process_completed_request(struct scsi_qla_host *, uint32_t); |
@@ -593,6 +595,67 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) | |||
593 | } | 595 | } |
594 | } | 596 | } |
595 | 597 | ||
598 | static void | ||
599 | qla2x00_adjust_sdev_qdepth_up(struct scsi_device *sdev, void *data) | ||
600 | { | ||
601 | fc_port_t *fcport = data; | ||
602 | |||
603 | if (fcport->ha->max_q_depth <= sdev->queue_depth) | ||
604 | return; | ||
605 | |||
606 | if (sdev->ordered_tags) | ||
607 | scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, | ||
608 | sdev->queue_depth + 1); | ||
609 | else | ||
610 | scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, | ||
611 | sdev->queue_depth + 1); | ||
612 | |||
613 | fcport->last_ramp_up = jiffies; | ||
614 | |||
615 | DEBUG2(qla_printk(KERN_INFO, fcport->ha, | ||
616 | "scsi(%ld:%d:%d:%d): Queue depth adjusted-up to %d.\n", | ||
617 | fcport->ha->host_no, sdev->channel, sdev->id, sdev->lun, | ||
618 | sdev->queue_depth)); | ||
619 | } | ||
620 | |||
621 | static void | ||
622 | qla2x00_adjust_sdev_qdepth_down(struct scsi_device *sdev, void *data) | ||
623 | { | ||
624 | fc_port_t *fcport = data; | ||
625 | |||
626 | if (!scsi_track_queue_full(sdev, sdev->queue_depth - 1)) | ||
627 | return; | ||
628 | |||
629 | DEBUG2(qla_printk(KERN_INFO, fcport->ha, | ||
630 | "scsi(%ld:%d:%d:%d): Queue depth adjusted-down to %d.\n", | ||
631 | fcport->ha->host_no, sdev->channel, sdev->id, sdev->lun, | ||
632 | sdev->queue_depth)); | ||
633 | } | ||
634 | |||
635 | static inline void | ||
636 | qla2x00_ramp_up_queue_depth(scsi_qla_host_t *ha, srb_t *sp) | ||
637 | { | ||
638 | fc_port_t *fcport; | ||
639 | struct scsi_device *sdev; | ||
640 | |||
641 | sdev = sp->cmd->device; | ||
642 | if (sdev->queue_depth >= ha->max_q_depth) | ||
643 | return; | ||
644 | |||
645 | fcport = sp->fcport; | ||
646 | if (time_before(jiffies, | ||
647 | fcport->last_ramp_up + ql2xqfullrampup * HZ)) | ||
648 | return; | ||
649 | if (time_before(jiffies, | ||
650 | fcport->last_queue_full + ql2xqfullrampup * HZ)) | ||
651 | return; | ||
652 | |||
653 | spin_unlock_irq(&ha->hardware_lock); | ||
654 | starget_for_each_device(sdev->sdev_target, fcport, | ||
655 | qla2x00_adjust_sdev_qdepth_up); | ||
656 | spin_lock_irq(&ha->hardware_lock); | ||
657 | } | ||
658 | |||
596 | /** | 659 | /** |
597 | * qla2x00_process_completed_request() - Process a Fast Post response. | 660 | * qla2x00_process_completed_request() - Process a Fast Post response. |
598 | * @ha: SCSI driver HA context | 661 | * @ha: SCSI driver HA context |
@@ -624,6 +687,8 @@ qla2x00_process_completed_request(struct scsi_qla_host *ha, uint32_t index) | |||
624 | 687 | ||
625 | /* Save ISP completion status */ | 688 | /* Save ISP completion status */ |
626 | sp->cmd->result = DID_OK << 16; | 689 | sp->cmd->result = DID_OK << 16; |
690 | |||
691 | qla2x00_ramp_up_queue_depth(ha, sp); | ||
627 | qla2x00_sp_compl(ha, sp); | 692 | qla2x00_sp_compl(ha, sp); |
628 | } else { | 693 | } else { |
629 | DEBUG2(printk("scsi(%ld): Invalid ISP SCSI completion handle\n", | 694 | DEBUG2(printk("scsi(%ld): Invalid ISP SCSI completion handle\n", |
@@ -823,6 +888,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) | |||
823 | */ | 888 | */ |
824 | switch (comp_status) { | 889 | switch (comp_status) { |
825 | case CS_COMPLETE: | 890 | case CS_COMPLETE: |
891 | case CS_QUEUE_FULL: | ||
826 | if (scsi_status == 0) { | 892 | if (scsi_status == 0) { |
827 | cp->result = DID_OK << 16; | 893 | cp->result = DID_OK << 16; |
828 | break; | 894 | break; |
@@ -849,6 +915,20 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) | |||
849 | } | 915 | } |
850 | cp->result = DID_OK << 16 | lscsi_status; | 916 | cp->result = DID_OK << 16 | lscsi_status; |
851 | 917 | ||
918 | if (lscsi_status == SAM_STAT_TASK_SET_FULL) { | ||
919 | DEBUG2(printk(KERN_INFO | ||
920 | "scsi(%ld): QUEUE FULL status detected " | ||
921 | "0x%x-0x%x.\n", ha->host_no, comp_status, | ||
922 | scsi_status)); | ||
923 | |||
924 | /* Adjust queue depth for all luns on the port. */ | ||
925 | fcport->last_queue_full = jiffies; | ||
926 | spin_unlock_irq(&ha->hardware_lock); | ||
927 | starget_for_each_device(cp->device->sdev_target, | ||
928 | fcport, qla2x00_adjust_sdev_qdepth_down); | ||
929 | spin_lock_irq(&ha->hardware_lock); | ||
930 | break; | ||
931 | } | ||
852 | if (lscsi_status != SS_CHECK_CONDITION) | 932 | if (lscsi_status != SS_CHECK_CONDITION) |
853 | break; | 933 | break; |
854 | 934 | ||
@@ -1066,17 +1146,6 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) | |||
1066 | qla2x00_mark_device_lost(ha, fcport, 1, 1); | 1146 | qla2x00_mark_device_lost(ha, fcport, 1, 1); |
1067 | break; | 1147 | break; |
1068 | 1148 | ||
1069 | case CS_QUEUE_FULL: | ||
1070 | DEBUG2(printk(KERN_INFO | ||
1071 | "scsi(%ld): QUEUE FULL status detected 0x%x-0x%x.\n", | ||
1072 | ha->host_no, comp_status, scsi_status)); | ||
1073 | |||
1074 | /* SCSI Mid-Layer handles device queue full */ | ||
1075 | |||
1076 | cp->result = DID_OK << 16 | lscsi_status; | ||
1077 | |||
1078 | break; | ||
1079 | |||
1080 | default: | 1149 | default: |
1081 | DEBUG3(printk("scsi(%ld): Error detected (unknown status) " | 1150 | DEBUG3(printk("scsi(%ld): Error detected (unknown status) " |
1082 | "0x%x-0x%x.\n", ha->host_no, comp_status, scsi_status)); | 1151 | "0x%x-0x%x.\n", ha->host_no, comp_status, scsi_status)); |
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 54f561d9c7a7..208607be78c7 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
@@ -77,6 +77,19 @@ MODULE_PARM_DESC(ql2xfdmienable, | |||
77 | "Enables FDMI registratons " | 77 | "Enables FDMI registratons " |
78 | "Default is 0 - no FDMI. 1 - perfom FDMI."); | 78 | "Default is 0 - no FDMI. 1 - perfom FDMI."); |
79 | 79 | ||
80 | #define MAX_Q_DEPTH 32 | ||
81 | static int ql2xmaxqdepth = MAX_Q_DEPTH; | ||
82 | module_param(ql2xmaxqdepth, int, S_IRUGO|S_IWUSR); | ||
83 | MODULE_PARM_DESC(ql2xmaxqdepth, | ||
84 | "Maximum queue depth to report for target devices."); | ||
85 | |||
86 | int ql2xqfullrampup = 120; | ||
87 | module_param(ql2xqfullrampup, int, S_IRUGO|S_IWUSR); | ||
88 | MODULE_PARM_DESC(ql2xqfullrampup, | ||
89 | "Number of seconds to wait to begin to ramp-up the queue " | ||
90 | "depth for a device after a queue-full condition has been " | ||
91 | "detected. Default is 120 seconds."); | ||
92 | |||
80 | /* | 93 | /* |
81 | * SCSI host template entry points | 94 | * SCSI host template entry points |
82 | */ | 95 | */ |
@@ -1104,9 +1117,9 @@ qla2xxx_slave_configure(struct scsi_device *sdev) | |||
1104 | struct fc_rport *rport = starget_to_rport(sdev->sdev_target); | 1117 | struct fc_rport *rport = starget_to_rport(sdev->sdev_target); |
1105 | 1118 | ||
1106 | if (sdev->tagged_supported) | 1119 | if (sdev->tagged_supported) |
1107 | scsi_activate_tcq(sdev, 32); | 1120 | scsi_activate_tcq(sdev, ha->max_q_depth); |
1108 | else | 1121 | else |
1109 | scsi_deactivate_tcq(sdev, 32); | 1122 | scsi_deactivate_tcq(sdev, ha->max_q_depth); |
1110 | 1123 | ||
1111 | rport->dev_loss_tmo = ha->port_down_retry_count + 5; | 1124 | rport->dev_loss_tmo = ha->port_down_retry_count + 5; |
1112 | 1125 | ||
@@ -1413,6 +1426,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1413 | ha->link_data_rate = PORT_SPEED_UNKNOWN; | 1426 | ha->link_data_rate = PORT_SPEED_UNKNOWN; |
1414 | ha->optrom_size = OPTROM_SIZE_2300; | 1427 | ha->optrom_size = OPTROM_SIZE_2300; |
1415 | 1428 | ||
1429 | ha->max_q_depth = MAX_Q_DEPTH; | ||
1430 | if (ql2xmaxqdepth != 0 && ql2xmaxqdepth <= 0xffffU) | ||
1431 | ha->max_q_depth = ql2xmaxqdepth; | ||
1432 | |||
1416 | /* Assign ISP specific operations. */ | 1433 | /* Assign ISP specific operations. */ |
1417 | ha->isp_ops.pci_config = qla2100_pci_config; | 1434 | ha->isp_ops.pci_config = qla2100_pci_config; |
1418 | ha->isp_ops.reset_chip = qla2x00_reset_chip; | 1435 | ha->isp_ops.reset_chip = qla2x00_reset_chip; |