aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx
diff options
context:
space:
mode:
authorAndrew Vasquez <andrew.vasquez@qlogic.com>2008-04-03 16:13:24 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-04-07 13:19:15 -0400
commit523ec773b8ffb1c607bc3a54c9526558e3b1eab1 (patch)
tree9cb3fc8a68af97a6359704e4341652aad9cc65d1 /drivers/scsi/qla2xxx
parent3fe7cfb910ea138ae623d1320c71e2a7a0bdc527 (diff)
[SCSI] qla2xxx: Add midlayer target/device reset support.
Now that infrastructure is present within the midlayer and there is a clear distinction between what is expected from a device and target reset, convert the current device-reset codes to a target-reset, and add codes to perform a proper device-reset (LUN reset). In the process of adding reset support, collapse and consolidate large sections of mailbox-command (TMF issuance) codes, generalize the two 'wait-for-commands-to-complete' functions, and add a generic-reset routine for use by midlayer reset functions. Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/qla2xxx')
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h3
-rw-r--r--drivers/scsi/qla2xxx/qla_fw.h2
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h8
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c123
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c254
5 files changed, 192 insertions, 198 deletions
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 3843eaa3af06..f7919d348ccd 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2062,7 +2062,8 @@ struct isp_operations {
2062 void (*disable_intrs) (struct scsi_qla_host *); 2062 void (*disable_intrs) (struct scsi_qla_host *);
2063 2063
2064 int (*abort_command) (struct scsi_qla_host *, srb_t *); 2064 int (*abort_command) (struct scsi_qla_host *, srb_t *);
2065 int (*abort_target) (struct fc_port *); 2065 int (*target_reset) (struct fc_port *, unsigned int);
2066 int (*lun_reset) (struct fc_port *, unsigned int);
2066 int (*fabric_login) (struct scsi_qla_host *, uint16_t, uint8_t, 2067 int (*fabric_login) (struct scsi_qla_host *, uint16_t, uint8_t,
2067 uint8_t, uint8_t, uint16_t *, uint8_t); 2068 uint8_t, uint8_t, uint16_t *, uint8_t);
2068 int (*fabric_logout) (struct scsi_qla_host *, uint16_t, uint8_t, 2069 int (*fabric_logout) (struct scsi_qla_host *, uint16_t, uint8_t,
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
index 38adc0f06e93..c6a5e49a25be 100644
--- a/drivers/scsi/qla2xxx/qla_fw.h
+++ b/drivers/scsi/qla2xxx/qla_fw.h
@@ -719,7 +719,7 @@ struct tsk_mgmt_entry {
719 719
720 uint16_t timeout; /* Command timeout. */ 720 uint16_t timeout; /* Command timeout. */
721 721
722 uint8_t lun[8]; /* FCP LUN (BE). */ 722 struct scsi_lun lun; /* FCP LUN (BE). */
723 723
724 uint32_t control_flags; /* Control Flags. */ 724 uint32_t control_flags; /* Control Flags. */
725#define TCF_NOTMCMD_TO_TARGET BIT_31 725#define TCF_NOTMCMD_TO_TARGET BIT_31
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index f25aa63ad191..f2133647bf25 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -153,7 +153,10 @@ extern int
153qla2x00_abort_command(scsi_qla_host_t *, srb_t *); 153qla2x00_abort_command(scsi_qla_host_t *, srb_t *);
154 154
155extern int 155extern int
156qla2x00_abort_target(fc_port_t *); 156qla2x00_abort_target(struct fc_port *, unsigned int);
157
158extern int
159qla2x00_lun_reset(struct fc_port *, unsigned int);
157 160
158extern int 161extern int
159qla2x00_get_adapter_id(scsi_qla_host_t *, uint16_t *, uint8_t *, uint8_t *, 162qla2x00_get_adapter_id(scsi_qla_host_t *, uint16_t *, uint8_t *, uint8_t *,
@@ -219,7 +222,8 @@ qla24xx_get_isp_stats(scsi_qla_host_t *, struct link_statistics *,
219 dma_addr_t); 222 dma_addr_t);
220 223
221extern int qla24xx_abort_command(scsi_qla_host_t *, srb_t *); 224extern int qla24xx_abort_command(scsi_qla_host_t *, srb_t *);
222extern int qla24xx_abort_target(fc_port_t *); 225extern int qla24xx_abort_target(struct fc_port *, unsigned int);
226extern int qla24xx_lun_reset(struct fc_port *, unsigned int);
223 227
224extern int 228extern int
225qla2x00_set_serdes_params(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t); 229qla2x00_set_serdes_params(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t);
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index b25c15a86c7f..c1af56dec4d4 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -784,35 +784,20 @@ qla2x00_abort_command(scsi_qla_host_t *ha, srb_t *sp)
784 return rval; 784 return rval;
785} 785}
786 786
787/*
788 * qla2x00_abort_target
789 * Issue abort target mailbox command.
790 *
791 * Input:
792 * ha = adapter block pointer.
793 *
794 * Returns:
795 * qla2x00 local function return status code.
796 *
797 * Context:
798 * Kernel context.
799 */
800int 787int
801qla2x00_abort_target(fc_port_t *fcport) 788qla2x00_abort_target(struct fc_port *fcport, unsigned int l)
802{ 789{
803 int rval; 790 int rval, rval2;
804 mbx_cmd_t mc; 791 mbx_cmd_t mc;
805 mbx_cmd_t *mcp = &mc; 792 mbx_cmd_t *mcp = &mc;
806 scsi_qla_host_t *ha; 793 scsi_qla_host_t *ha;
807 794
808 if (fcport == NULL)
809 return 0;
810
811 DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->ha->host_no)); 795 DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->ha->host_no));
812 796
797 l = l;
813 ha = fcport->ha; 798 ha = fcport->ha;
814 mcp->mb[0] = MBC_ABORT_TARGET; 799 mcp->mb[0] = MBC_ABORT_TARGET;
815 mcp->out_mb = MBX_2|MBX_1|MBX_0; 800 mcp->out_mb = MBX_9|MBX_2|MBX_1|MBX_0;
816 if (HAS_EXTENDED_IDS(ha)) { 801 if (HAS_EXTENDED_IDS(ha)) {
817 mcp->mb[1] = fcport->loop_id; 802 mcp->mb[1] = fcport->loop_id;
818 mcp->mb[10] = 0; 803 mcp->mb[10] = 0;
@@ -821,22 +806,66 @@ qla2x00_abort_target(fc_port_t *fcport)
821 mcp->mb[1] = fcport->loop_id << 8; 806 mcp->mb[1] = fcport->loop_id << 8;
822 } 807 }
823 mcp->mb[2] = ha->loop_reset_delay; 808 mcp->mb[2] = ha->loop_reset_delay;
809 mcp->mb[9] = ha->vp_idx;
824 810
825 mcp->in_mb = MBX_0; 811 mcp->in_mb = MBX_0;
826 mcp->tov = 30; 812 mcp->tov = 30;
827 mcp->flags = 0; 813 mcp->flags = 0;
828 rval = qla2x00_mailbox_command(ha, mcp); 814 rval = qla2x00_mailbox_command(ha, mcp);
815 if (rval != QLA_SUCCESS) {
816 DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
817 ha->host_no, rval));
818 }
819
820 /* Issue marker IOCB. */
821 rval2 = qla2x00_marker(ha, fcport->loop_id, 0, MK_SYNC_ID);
822 if (rval2 != QLA_SUCCESS) {
823 DEBUG2_3_11(printk("%s(%ld): failed to issue Marker IOCB "
824 "(%x).\n", __func__, ha->host_no, rval2));
825 } else {
826 DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
827 }
828
829 return rval;
830}
831
832int
833qla2x00_lun_reset(struct fc_port *fcport, unsigned int l)
834{
835 int rval, rval2;
836 mbx_cmd_t mc;
837 mbx_cmd_t *mcp = &mc;
838 scsi_qla_host_t *ha;
839
840 DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->ha->host_no));
829 841
830 /* Issue marker command. */ 842 ha = fcport->ha;
831 ha->marker_needed = 1; 843 mcp->mb[0] = MBC_LUN_RESET;
844 mcp->out_mb = MBX_9|MBX_3|MBX_2|MBX_1|MBX_0;
845 if (HAS_EXTENDED_IDS(ha))
846 mcp->mb[1] = fcport->loop_id;
847 else
848 mcp->mb[1] = fcport->loop_id << 8;
849 mcp->mb[2] = l;
850 mcp->mb[3] = 0;
851 mcp->mb[9] = ha->vp_idx;
832 852
853 mcp->in_mb = MBX_0;
854 mcp->tov = 30;
855 mcp->flags = 0;
856 rval = qla2x00_mailbox_command(ha, mcp);
833 if (rval != QLA_SUCCESS) { 857 if (rval != QLA_SUCCESS) {
834 DEBUG2_3_11(printk("qla2x00_abort_target(%ld): failed=%x.\n", 858 DEBUG2_3_11(printk("%s(%ld): failed=%x.\n", __func__,
835 ha->host_no, rval)); 859 ha->host_no, rval));
860 }
861
862 /* Issue marker IOCB. */
863 rval2 = qla2x00_marker(ha, fcport->loop_id, l, MK_SYNC_ID_LUN);
864 if (rval2 != QLA_SUCCESS) {
865 DEBUG2_3_11(printk("%s(%ld): failed to issue Marker IOCB "
866 "(%x).\n", __func__, ha->host_no, rval2));
836 } else { 867 } else {
837 /*EMPTY*/ 868 DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
838 DEBUG11(printk("qla2x00_abort_target(%ld): done.\n",
839 ha->host_no));
840 } 869 }
841 870
842 return rval; 871 return rval;
@@ -2186,17 +2215,15 @@ struct tsk_mgmt_cmd {
2186 } p; 2215 } p;
2187}; 2216};
2188 2217
2189int 2218static int
2190qla24xx_abort_target(fc_port_t *fcport) 2219__qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport,
2220 unsigned int l)
2191{ 2221{
2192 int rval; 2222 int rval, rval2;
2193 struct tsk_mgmt_cmd *tsk; 2223 struct tsk_mgmt_cmd *tsk;
2194 dma_addr_t tsk_dma; 2224 dma_addr_t tsk_dma;
2195 scsi_qla_host_t *ha, *pha; 2225 scsi_qla_host_t *ha, *pha;
2196 2226
2197 if (fcport == NULL)
2198 return 0;
2199
2200 DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->ha->host_no)); 2227 DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->ha->host_no));
2201 2228
2202 ha = fcport->ha; 2229 ha = fcport->ha;
@@ -2213,47 +2240,61 @@ qla24xx_abort_target(fc_port_t *fcport)
2213 tsk->p.tsk.entry_count = 1; 2240 tsk->p.tsk.entry_count = 1;
2214 tsk->p.tsk.nport_handle = cpu_to_le16(fcport->loop_id); 2241 tsk->p.tsk.nport_handle = cpu_to_le16(fcport->loop_id);
2215 tsk->p.tsk.timeout = cpu_to_le16(ha->r_a_tov / 10 * 2); 2242 tsk->p.tsk.timeout = cpu_to_le16(ha->r_a_tov / 10 * 2);
2216 tsk->p.tsk.control_flags = __constant_cpu_to_le32(TCF_TARGET_RESET); 2243 tsk->p.tsk.control_flags = cpu_to_le32(type);
2217 tsk->p.tsk.port_id[0] = fcport->d_id.b.al_pa; 2244 tsk->p.tsk.port_id[0] = fcport->d_id.b.al_pa;
2218 tsk->p.tsk.port_id[1] = fcport->d_id.b.area; 2245 tsk->p.tsk.port_id[1] = fcport->d_id.b.area;
2219 tsk->p.tsk.port_id[2] = fcport->d_id.b.domain; 2246 tsk->p.tsk.port_id[2] = fcport->d_id.b.domain;
2220 tsk->p.tsk.vp_index = fcport->vp_idx; 2247 tsk->p.tsk.vp_index = fcport->vp_idx;
2248 if (type == TCF_LUN_RESET) {
2249 int_to_scsilun(l, &tsk->p.tsk.lun);
2250 host_to_fcp_swap((uint8_t *)&tsk->p.tsk.lun,
2251 sizeof(tsk->p.tsk.lun));
2252 }
2221 2253
2222 rval = qla2x00_issue_iocb(ha, tsk, tsk_dma, 0); 2254 rval = qla2x00_issue_iocb(ha, tsk, tsk_dma, 0);
2223 if (rval != QLA_SUCCESS) { 2255 if (rval != QLA_SUCCESS) {
2224 DEBUG2_3_11(printk("%s(%ld): failed to issue Target Reset IOCB " 2256 DEBUG2_3_11(printk("%s(%ld): failed to issue %s Reset IOCB "
2225 "(%x).\n", __func__, ha->host_no, rval)); 2257 "(%x).\n", __func__, ha->host_no, name, rval));
2226 goto atarget_done;
2227 } else if (tsk->p.sts.entry_status != 0) { 2258 } else if (tsk->p.sts.entry_status != 0) {
2228 DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB " 2259 DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
2229 "-- error status (%x).\n", __func__, ha->host_no, 2260 "-- error status (%x).\n", __func__, ha->host_no,
2230 tsk->p.sts.entry_status)); 2261 tsk->p.sts.entry_status));
2231 rval = QLA_FUNCTION_FAILED; 2262 rval = QLA_FUNCTION_FAILED;
2232 goto atarget_done;
2233 } else if (tsk->p.sts.comp_status != 2263 } else if (tsk->p.sts.comp_status !=
2234 __constant_cpu_to_le16(CS_COMPLETE)) { 2264 __constant_cpu_to_le16(CS_COMPLETE)) {
2235 DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB " 2265 DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
2236 "-- completion status (%x).\n", __func__, 2266 "-- completion status (%x).\n", __func__,
2237 ha->host_no, le16_to_cpu(tsk->p.sts.comp_status))); 2267 ha->host_no, le16_to_cpu(tsk->p.sts.comp_status)));
2238 rval = QLA_FUNCTION_FAILED; 2268 rval = QLA_FUNCTION_FAILED;
2239 goto atarget_done;
2240 } 2269 }
2241 2270
2242 /* Issue marker IOCB. */ 2271 /* Issue marker IOCB. */
2243 rval = qla2x00_marker(ha, fcport->loop_id, 0, MK_SYNC_ID); 2272 rval2 = qla2x00_marker(ha, fcport->loop_id, l,
2244 if (rval != QLA_SUCCESS) { 2273 type == TCF_LUN_RESET ? MK_SYNC_ID_LUN: MK_SYNC_ID);
2274 if (rval2 != QLA_SUCCESS) {
2245 DEBUG2_3_11(printk("%s(%ld): failed to issue Marker IOCB " 2275 DEBUG2_3_11(printk("%s(%ld): failed to issue Marker IOCB "
2246 "(%x).\n", __func__, ha->host_no, rval)); 2276 "(%x).\n", __func__, ha->host_no, rval2));
2247 } else { 2277 } else {
2248 DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no)); 2278 DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
2249 } 2279 }
2250 2280
2251atarget_done:
2252 dma_pool_free(pha->s_dma_pool, tsk, tsk_dma); 2281 dma_pool_free(pha->s_dma_pool, tsk, tsk_dma);
2253 2282
2254 return rval; 2283 return rval;
2255} 2284}
2256 2285
2286int
2287qla24xx_abort_target(struct fc_port *fcport, unsigned int l)
2288{
2289 return __qla24xx_issue_tmf("Target", TCF_TARGET_RESET, fcport, l);
2290}
2291
2292int
2293qla24xx_lun_reset(struct fc_port *fcport, unsigned int l)
2294{
2295 return __qla24xx_issue_tmf("Lun", TCF_LUN_RESET, fcport, l);
2296}
2297
2257#if 0 2298#if 0
2258 2299
2259int 2300int
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index ba7d2ca3a0e8..5cddc503bd2b 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -100,6 +100,7 @@ static int qla24xx_queuecommand(struct scsi_cmnd *cmd,
100 void (*fn)(struct scsi_cmnd *)); 100 void (*fn)(struct scsi_cmnd *));
101static int qla2xxx_eh_abort(struct scsi_cmnd *); 101static int qla2xxx_eh_abort(struct scsi_cmnd *);
102static int qla2xxx_eh_device_reset(struct scsi_cmnd *); 102static int qla2xxx_eh_device_reset(struct scsi_cmnd *);
103static int qla2xxx_eh_target_reset(struct scsi_cmnd *);
103static int qla2xxx_eh_bus_reset(struct scsi_cmnd *); 104static int qla2xxx_eh_bus_reset(struct scsi_cmnd *);
104static int qla2xxx_eh_host_reset(struct scsi_cmnd *); 105static int qla2xxx_eh_host_reset(struct scsi_cmnd *);
105 106
@@ -113,6 +114,7 @@ static struct scsi_host_template qla2x00_driver_template = {
113 114
114 .eh_abort_handler = qla2xxx_eh_abort, 115 .eh_abort_handler = qla2xxx_eh_abort,
115 .eh_device_reset_handler = qla2xxx_eh_device_reset, 116 .eh_device_reset_handler = qla2xxx_eh_device_reset,
117 .eh_target_reset_handler = qla2xxx_eh_target_reset,
116 .eh_bus_reset_handler = qla2xxx_eh_bus_reset, 118 .eh_bus_reset_handler = qla2xxx_eh_bus_reset,
117 .eh_host_reset_handler = qla2xxx_eh_host_reset, 119 .eh_host_reset_handler = qla2xxx_eh_host_reset,
118 120
@@ -144,6 +146,7 @@ struct scsi_host_template qla24xx_driver_template = {
144 146
145 .eh_abort_handler = qla2xxx_eh_abort, 147 .eh_abort_handler = qla2xxx_eh_abort,
146 .eh_device_reset_handler = qla2xxx_eh_device_reset, 148 .eh_device_reset_handler = qla2xxx_eh_device_reset,
149 .eh_target_reset_handler = qla2xxx_eh_target_reset,
147 .eh_bus_reset_handler = qla2xxx_eh_bus_reset, 150 .eh_bus_reset_handler = qla2xxx_eh_bus_reset,
148 .eh_host_reset_handler = qla2xxx_eh_host_reset, 151 .eh_host_reset_handler = qla2xxx_eh_host_reset,
149 152
@@ -566,8 +569,6 @@ qla2x00_wait_for_hba_online(scsi_qla_host_t *ha)
566 else 569 else
567 return_status = QLA_FUNCTION_FAILED; 570 return_status = QLA_FUNCTION_FAILED;
568 571
569 DEBUG2(printk("%s return_status=%d\n",__func__,return_status));
570
571 return (return_status); 572 return (return_status);
572} 573}
573 574
@@ -714,181 +715,122 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
714 return ret; 715 return ret;
715} 716}
716 717
717/************************************************************************** 718enum nexus_wait_type {
718* qla2x00_eh_wait_for_pending_target_commands 719 WAIT_HOST = 0,
719* 720 WAIT_TARGET,
720* Description: 721 WAIT_LUN,
721* Waits for all the commands to come back from the specified target. 722};
722* 723
723* Input:
724* ha - pointer to scsi_qla_host structure.
725* t - target
726* Returns:
727* Either SUCCESS or FAILED.
728*
729* Note:
730**************************************************************************/
731static int 724static int
732qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, unsigned int t) 725qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha, unsigned int t,
726 unsigned int l, enum nexus_wait_type type)
733{ 727{
734 int cnt; 728 int cnt, match, status;
735 int status; 729 srb_t *sp;
736 srb_t *sp;
737 struct scsi_cmnd *cmd;
738 unsigned long flags; 730 unsigned long flags;
739 scsi_qla_host_t *pha = to_qla_parent(ha); 731 scsi_qla_host_t *pha = to_qla_parent(ha);
740 732
741 status = 0; 733 status = QLA_SUCCESS;
742 734 spin_lock_irqsave(&pha->hardware_lock, flags);
743 /* 735 for (cnt = 1; status == QLA_SUCCESS && cnt < MAX_OUTSTANDING_COMMANDS;
744 * Waiting for all commands for the designated target in the active 736 cnt++) {
745 * array
746 */
747 for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
748 spin_lock_irqsave(&pha->hardware_lock, flags);
749 sp = pha->outstanding_cmds[cnt]; 737 sp = pha->outstanding_cmds[cnt];
750 if (sp) { 738 if (!sp)
751 cmd = sp->cmd; 739 continue;
752 spin_unlock_irqrestore(&pha->hardware_lock, flags); 740 if (ha->vp_idx != sp->ha->vp_idx)
753 if (cmd->device->id == t && 741 continue;
754 ha->vp_idx == sp->ha->vp_idx) { 742 match = 0;
755 if (!qla2x00_eh_wait_on_command(ha, cmd)) { 743 switch (type) {
756 status = 1; 744 case WAIT_HOST:
757 break; 745 match = 1;
758 } 746 break;
759 } 747 case WAIT_TARGET:
760 } else { 748 match = sp->cmd->device->id == t;
761 spin_unlock_irqrestore(&pha->hardware_lock, flags); 749 break;
750 case WAIT_LUN:
751 match = (sp->cmd->device->id == t &&
752 sp->cmd->device->lun == l);
753 break;
762 } 754 }
755 if (!match)
756 continue;
757
758 spin_unlock_irqrestore(&pha->hardware_lock, flags);
759 status = qla2x00_eh_wait_on_command(ha, sp->cmd);
760 spin_lock_irqsave(&pha->hardware_lock, flags);
763 } 761 }
764 return (status); 762 spin_unlock_irqrestore(&pha->hardware_lock, flags);
763
764 return status;
765} 765}
766 766
767static char *reset_errors[] = {
768 "HBA not online",
769 "HBA not ready",
770 "Task management failed",
771 "Waiting for command completions",
772};
767 773
768/**************************************************************************
769* qla2xxx_eh_device_reset
770*
771* Description:
772* The device reset function will reset the target and abort any
773* executing commands.
774*
775* NOTE: The use of SP is undefined within this context. Do *NOT*
776* attempt to use this value, even if you determine it is
777* non-null.
778*
779* Input:
780* cmd = Linux SCSI command packet of the command that cause the
781* bus device reset.
782*
783* Returns:
784* SUCCESS/FAILURE (defined as macro in scsi.h).
785*
786**************************************************************************/
787static int 774static int
788qla2xxx_eh_device_reset(struct scsi_cmnd *cmd) 775__qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type,
776 struct scsi_cmnd *cmd, int (*do_reset)(struct fc_port *, unsigned int))
789{ 777{
790 scsi_qla_host_t *ha = shost_priv(cmd->device->host); 778 scsi_qla_host_t *ha = shost_priv(cmd->device->host);
791 fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; 779 fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
792 int ret = FAILED; 780 int err;
793 unsigned int id, lun;
794 unsigned long serial;
795 781
796 qla2x00_block_error_handler(cmd); 782 qla2x00_block_error_handler(cmd);
797 783
798 id = cmd->device->id;
799 lun = cmd->device->lun;
800 serial = cmd->serial_number;
801
802 if (!fcport) 784 if (!fcport)
803 return ret; 785 return FAILED;
804 786
805 qla_printk(KERN_INFO, ha, 787 qla_printk(KERN_INFO, ha, "scsi(%ld:%d:%d): %s RESET ISSUED.\n",
806 "scsi(%ld:%d:%d): DEVICE RESET ISSUED.\n", ha->host_no, id, lun); 788 ha->host_no, cmd->device->id, cmd->device->lun, name);
807 789
790 err = 0;
808 if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS) 791 if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS)
809 goto eh_dev_reset_done; 792 goto eh_reset_failed;
810 793 err = 1;
811 if (qla2x00_wait_for_loop_ready(ha) == QLA_SUCCESS) { 794 if (qla2x00_wait_for_loop_ready(ha) != QLA_SUCCESS)
812 if (ha->isp_ops->abort_target(fcport) == 0) 795 goto eh_reset_failed;
813 ret = SUCCESS; 796 err = 2;
814 } else { 797 if (do_reset(fcport, cmd->device->lun) != QLA_SUCCESS)
815 DEBUG2(printk(KERN_INFO 798 goto eh_reset_failed;
816 "%s failed: loop not ready\n",__func__)); 799 err = 3;
817 } 800 if (qla2x00_eh_wait_for_pending_commands(ha, cmd->device->id,
818 801 cmd->device->lun, type) != QLA_SUCCESS)
819 if (ret == FAILED) { 802 goto eh_reset_failed;
820 DEBUG3(printk("%s(%ld): device reset failed\n", 803
821 __func__, ha->host_no)); 804 qla_printk(KERN_INFO, ha, "scsi(%ld:%d:%d): %s RESET SUCCEEDED.\n",
822 qla_printk(KERN_INFO, ha, "%s: device reset failed\n", 805 ha->host_no, cmd->device->id, cmd->device->lun, name);
823 __func__); 806
807 return SUCCESS;
808
809 eh_reset_failed:
810 qla_printk(KERN_INFO, ha, "scsi(%ld:%d:%d): %s RESET FAILED: %s.\n",
811 ha->host_no, cmd->device->id, cmd->device->lun, name,
812 reset_errors[err]);
813 return FAILED;
814}
824 815
825 goto eh_dev_reset_done; 816static int
826 } 817qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
818{
819 scsi_qla_host_t *ha = shost_priv(cmd->device->host);
827 820
828 /* Flush outstanding commands. */ 821 return __qla2xxx_eh_generic_reset("DEVICE", WAIT_LUN, cmd,
829 if (qla2x00_eh_wait_for_pending_target_commands(ha, id)) 822 ha->isp_ops->lun_reset);
830 ret = FAILED;
831 if (ret == FAILED) {
832 DEBUG3(printk("%s(%ld): failed while waiting for commands\n",
833 __func__, ha->host_no));
834 qla_printk(KERN_INFO, ha,
835 "%s: failed while waiting for commands\n", __func__);
836 } else
837 qla_printk(KERN_INFO, ha,
838 "scsi(%ld:%d:%d): DEVICE RESET SUCCEEDED.\n", ha->host_no,
839 id, lun);
840 eh_dev_reset_done:
841 return ret;
842} 823}
843 824
844/**************************************************************************
845* qla2x00_eh_wait_for_pending_commands
846*
847* Description:
848* Waits for all the commands to come back from the specified host.
849*
850* Input:
851* ha - pointer to scsi_qla_host structure.
852*
853* Returns:
854* 1 : SUCCESS
855* 0 : FAILED
856*
857* Note:
858**************************************************************************/
859static int 825static int
860qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha) 826qla2xxx_eh_target_reset(struct scsi_cmnd *cmd)
861{ 827{
862 int cnt; 828 scsi_qla_host_t *ha = shost_priv(cmd->device->host);
863 int status;
864 srb_t *sp;
865 struct scsi_cmnd *cmd;
866 unsigned long flags;
867
868 status = 1;
869 829
870 /* 830 return __qla2xxx_eh_generic_reset("TARGET", WAIT_TARGET, cmd,
871 * Waiting for all commands for the designated target in the active 831 ha->isp_ops->target_reset);
872 * array
873 */
874 for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
875 spin_lock_irqsave(&ha->hardware_lock, flags);
876 sp = ha->outstanding_cmds[cnt];
877 if (sp) {
878 cmd = sp->cmd;
879 spin_unlock_irqrestore(&ha->hardware_lock, flags);
880 status = qla2x00_eh_wait_on_command(ha, cmd);
881 if (status == 0)
882 break;
883 }
884 else {
885 spin_unlock_irqrestore(&ha->hardware_lock, flags);
886 }
887 }
888 return (status);
889} 832}
890 833
891
892/************************************************************************** 834/**************************************************************************
893* qla2xxx_eh_bus_reset 835* qla2xxx_eh_bus_reset
894* 836*
@@ -939,7 +881,8 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd)
939 goto eh_bus_reset_done; 881 goto eh_bus_reset_done;
940 882
941 /* Flush outstanding commands. */ 883 /* Flush outstanding commands. */
942 if (!qla2x00_eh_wait_for_pending_commands(pha)) 884 if (qla2x00_eh_wait_for_pending_commands(pha, 0, 0, WAIT_HOST) !=
885 QLA_SUCCESS)
943 ret = FAILED; 886 ret = FAILED;
944 887
945eh_bus_reset_done: 888eh_bus_reset_done:
@@ -1010,7 +953,8 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
1010 clear_bit(ABORT_ISP_ACTIVE, &pha->dpc_flags); 953 clear_bit(ABORT_ISP_ACTIVE, &pha->dpc_flags);
1011 954
1012 /* Waiting for our command in done_queue to be returned to OS.*/ 955 /* Waiting for our command in done_queue to be returned to OS.*/
1013 if (qla2x00_eh_wait_for_pending_commands(pha)) 956 if (qla2x00_eh_wait_for_pending_commands(pha, 0, 0, WAIT_HOST) ==
957 QLA_SUCCESS)
1014 ret = SUCCESS; 958 ret = SUCCESS;
1015 959
1016 if (ha->parent) 960 if (ha->parent)
@@ -1066,7 +1010,7 @@ qla2x00_loop_reset(scsi_qla_host_t *ha)
1066 if (fcport->port_type != FCT_TARGET) 1010 if (fcport->port_type != FCT_TARGET)
1067 continue; 1011 continue;
1068 1012
1069 ret = ha->isp_ops->abort_target(fcport); 1013 ret = ha->isp_ops->target_reset(fcport, 0);
1070 if (ret != QLA_SUCCESS) { 1014 if (ret != QLA_SUCCESS) {
1071 DEBUG2_3(printk("%s(%ld): bus_reset failed: " 1015 DEBUG2_3(printk("%s(%ld): bus_reset failed: "
1072 "target_reset=%d d_id=%x.\n", __func__, 1016 "target_reset=%d d_id=%x.\n", __func__,
@@ -1258,7 +1202,8 @@ static struct isp_operations qla2100_isp_ops = {
1258 .enable_intrs = qla2x00_enable_intrs, 1202 .enable_intrs = qla2x00_enable_intrs,
1259 .disable_intrs = qla2x00_disable_intrs, 1203 .disable_intrs = qla2x00_disable_intrs,
1260 .abort_command = qla2x00_abort_command, 1204 .abort_command = qla2x00_abort_command,
1261 .abort_target = qla2x00_abort_target, 1205 .target_reset = qla2x00_abort_target,
1206 .lun_reset = qla2x00_lun_reset,
1262 .fabric_login = qla2x00_login_fabric, 1207 .fabric_login = qla2x00_login_fabric,
1263 .fabric_logout = qla2x00_fabric_logout, 1208 .fabric_logout = qla2x00_fabric_logout,
1264 .calc_req_entries = qla2x00_calc_iocbs_32, 1209 .calc_req_entries = qla2x00_calc_iocbs_32,
@@ -1291,7 +1236,8 @@ static struct isp_operations qla2300_isp_ops = {
1291 .enable_intrs = qla2x00_enable_intrs, 1236 .enable_intrs = qla2x00_enable_intrs,
1292 .disable_intrs = qla2x00_disable_intrs, 1237 .disable_intrs = qla2x00_disable_intrs,
1293 .abort_command = qla2x00_abort_command, 1238 .abort_command = qla2x00_abort_command,
1294 .abort_target = qla2x00_abort_target, 1239 .target_reset = qla2x00_abort_target,
1240 .lun_reset = qla2x00_lun_reset,
1295 .fabric_login = qla2x00_login_fabric, 1241 .fabric_login = qla2x00_login_fabric,
1296 .fabric_logout = qla2x00_fabric_logout, 1242 .fabric_logout = qla2x00_fabric_logout,
1297 .calc_req_entries = qla2x00_calc_iocbs_32, 1243 .calc_req_entries = qla2x00_calc_iocbs_32,
@@ -1324,7 +1270,8 @@ static struct isp_operations qla24xx_isp_ops = {
1324 .enable_intrs = qla24xx_enable_intrs, 1270 .enable_intrs = qla24xx_enable_intrs,
1325 .disable_intrs = qla24xx_disable_intrs, 1271 .disable_intrs = qla24xx_disable_intrs,
1326 .abort_command = qla24xx_abort_command, 1272 .abort_command = qla24xx_abort_command,
1327 .abort_target = qla24xx_abort_target, 1273 .target_reset = qla24xx_abort_target,
1274 .lun_reset = qla24xx_lun_reset,
1328 .fabric_login = qla24xx_login_fabric, 1275 .fabric_login = qla24xx_login_fabric,
1329 .fabric_logout = qla24xx_fabric_logout, 1276 .fabric_logout = qla24xx_fabric_logout,
1330 .calc_req_entries = NULL, 1277 .calc_req_entries = NULL,
@@ -1357,7 +1304,8 @@ static struct isp_operations qla25xx_isp_ops = {
1357 .enable_intrs = qla24xx_enable_intrs, 1304 .enable_intrs = qla24xx_enable_intrs,
1358 .disable_intrs = qla24xx_disable_intrs, 1305 .disable_intrs = qla24xx_disable_intrs,
1359 .abort_command = qla24xx_abort_command, 1306 .abort_command = qla24xx_abort_command,
1360 .abort_target = qla24xx_abort_target, 1307 .target_reset = qla24xx_abort_target,
1308 .lun_reset = qla24xx_lun_reset,
1361 .fabric_login = qla24xx_login_fabric, 1309 .fabric_login = qla24xx_login_fabric,
1362 .fabric_logout = qla24xx_fabric_logout, 1310 .fabric_logout = qla24xx_fabric_logout,
1363 .calc_req_entries = NULL, 1311 .calc_req_entries = NULL,