diff options
author | Tejun Heo <htejun@gmail.com> | 2006-04-02 05:51:53 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-04-02 10:09:21 -0400 |
commit | ece1d63619df010b8c4f08e43755e2a03f3b6eed (patch) | |
tree | c6474fe7541d479bf19c36c79700dfa9f6093a8d /drivers/scsi | |
parent | 35e86b53b1a38e78ff0d70dae4aeb25f4572e433 (diff) |
[PATCH] libata: separate out libata-eh.c
A lot of EH codes are about to be added to libata. Separate out
libata-eh.c. ata_scsi_timed_out(), ata_scsi_error(),
ata_qc_timeout(), ata_eng_timeout(), ata_eh_qc_complete() and
ata_eh_qc_retry() are moved. No code is changed by this patch.
Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/Makefile | 2 | ||||
-rw-r--r-- | drivers/scsi/libata-core.c | 102 | ||||
-rw-r--r-- | drivers/scsi/libata-eh.c | 264 | ||||
-rw-r--r-- | drivers/scsi/libata-scsi.c | 130 | ||||
-rw-r--r-- | drivers/scsi/libata.h | 4 |
5 files changed, 273 insertions, 229 deletions
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index e513c3158ad9..503f189dab3b 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile | |||
@@ -165,7 +165,7 @@ ncr53c8xx-flags-$(CONFIG_SCSI_ZALON) \ | |||
165 | CFLAGS_ncr53c8xx.o := $(ncr53c8xx-flags-y) $(ncr53c8xx-flags-m) | 165 | CFLAGS_ncr53c8xx.o := $(ncr53c8xx-flags-y) $(ncr53c8xx-flags-m) |
166 | zalon7xx-objs := zalon.o ncr53c8xx.o | 166 | zalon7xx-objs := zalon.o ncr53c8xx.o |
167 | NCR_Q720_mod-objs := NCR_Q720.o ncr53c8xx.o | 167 | NCR_Q720_mod-objs := NCR_Q720.o ncr53c8xx.o |
168 | libata-objs := libata-core.o libata-scsi.o libata-bmdma.o | 168 | libata-objs := libata-core.o libata-scsi.o libata-bmdma.o libata-eh.o |
169 | oktagon_esp_mod-objs := oktagon_esp.o oktagon_io.o | 169 | oktagon_esp_mod-objs := oktagon_esp.o oktagon_io.o |
170 | 170 | ||
171 | # Files generated that shall be removed upon make clean | 171 | # Files generated that shall be removed upon make clean |
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 66b48b11fa0e..186a9ce4f072 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c | |||
@@ -4016,99 +4016,6 @@ err_out: | |||
4016 | } | 4016 | } |
4017 | 4017 | ||
4018 | /** | 4018 | /** |
4019 | * ata_qc_timeout - Handle timeout of queued command | ||
4020 | * @qc: Command that timed out | ||
4021 | * | ||
4022 | * Some part of the kernel (currently, only the SCSI layer) | ||
4023 | * has noticed that the active command on port @ap has not | ||
4024 | * completed after a specified length of time. Handle this | ||
4025 | * condition by disabling DMA (if necessary) and completing | ||
4026 | * transactions, with error if necessary. | ||
4027 | * | ||
4028 | * This also handles the case of the "lost interrupt", where | ||
4029 | * for some reason (possibly hardware bug, possibly driver bug) | ||
4030 | * an interrupt was not delivered to the driver, even though the | ||
4031 | * transaction completed successfully. | ||
4032 | * | ||
4033 | * LOCKING: | ||
4034 | * Inherited from SCSI layer (none, can sleep) | ||
4035 | */ | ||
4036 | |||
4037 | static void ata_qc_timeout(struct ata_queued_cmd *qc) | ||
4038 | { | ||
4039 | struct ata_port *ap = qc->ap; | ||
4040 | struct ata_host_set *host_set = ap->host_set; | ||
4041 | u8 host_stat = 0, drv_stat; | ||
4042 | unsigned long flags; | ||
4043 | |||
4044 | DPRINTK("ENTER\n"); | ||
4045 | |||
4046 | ap->hsm_task_state = HSM_ST_IDLE; | ||
4047 | |||
4048 | spin_lock_irqsave(&host_set->lock, flags); | ||
4049 | |||
4050 | switch (qc->tf.protocol) { | ||
4051 | |||
4052 | case ATA_PROT_DMA: | ||
4053 | case ATA_PROT_ATAPI_DMA: | ||
4054 | host_stat = ap->ops->bmdma_status(ap); | ||
4055 | |||
4056 | /* before we do anything else, clear DMA-Start bit */ | ||
4057 | ap->ops->bmdma_stop(qc); | ||
4058 | |||
4059 | /* fall through */ | ||
4060 | |||
4061 | default: | ||
4062 | ata_altstatus(ap); | ||
4063 | drv_stat = ata_chk_status(ap); | ||
4064 | |||
4065 | /* ack bmdma irq events */ | ||
4066 | ap->ops->irq_clear(ap); | ||
4067 | |||
4068 | printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x host_stat 0x%x\n", | ||
4069 | ap->id, qc->tf.command, drv_stat, host_stat); | ||
4070 | |||
4071 | /* complete taskfile transaction */ | ||
4072 | qc->err_mask |= ac_err_mask(drv_stat); | ||
4073 | break; | ||
4074 | } | ||
4075 | |||
4076 | spin_unlock_irqrestore(&host_set->lock, flags); | ||
4077 | |||
4078 | ata_eh_qc_complete(qc); | ||
4079 | |||
4080 | DPRINTK("EXIT\n"); | ||
4081 | } | ||
4082 | |||
4083 | /** | ||
4084 | * ata_eng_timeout - Handle timeout of queued command | ||
4085 | * @ap: Port on which timed-out command is active | ||
4086 | * | ||
4087 | * Some part of the kernel (currently, only the SCSI layer) | ||
4088 | * has noticed that the active command on port @ap has not | ||
4089 | * completed after a specified length of time. Handle this | ||
4090 | * condition by disabling DMA (if necessary) and completing | ||
4091 | * transactions, with error if necessary. | ||
4092 | * | ||
4093 | * This also handles the case of the "lost interrupt", where | ||
4094 | * for some reason (possibly hardware bug, possibly driver bug) | ||
4095 | * an interrupt was not delivered to the driver, even though the | ||
4096 | * transaction completed successfully. | ||
4097 | * | ||
4098 | * LOCKING: | ||
4099 | * Inherited from SCSI layer (none, can sleep) | ||
4100 | */ | ||
4101 | |||
4102 | void ata_eng_timeout(struct ata_port *ap) | ||
4103 | { | ||
4104 | DPRINTK("ENTER\n"); | ||
4105 | |||
4106 | ata_qc_timeout(ata_qc_from_tag(ap, ap->active_tag)); | ||
4107 | |||
4108 | DPRINTK("EXIT\n"); | ||
4109 | } | ||
4110 | |||
4111 | /** | ||
4112 | * ata_qc_new - Request an available ATA command, for queueing | 4019 | * ata_qc_new - Request an available ATA command, for queueing |
4113 | * @ap: Port associated with device @dev | 4020 | * @ap: Port associated with device @dev |
4114 | * @dev: Device from whom we request an available command structure | 4021 | * @dev: Device from whom we request an available command structure |
@@ -5145,7 +5052,6 @@ EXPORT_SYMBOL_GPL(ata_sg_init); | |||
5145 | EXPORT_SYMBOL_GPL(ata_sg_init_one); | 5052 | EXPORT_SYMBOL_GPL(ata_sg_init_one); |
5146 | EXPORT_SYMBOL_GPL(__ata_qc_complete); | 5053 | EXPORT_SYMBOL_GPL(__ata_qc_complete); |
5147 | EXPORT_SYMBOL_GPL(ata_qc_issue_prot); | 5054 | EXPORT_SYMBOL_GPL(ata_qc_issue_prot); |
5148 | EXPORT_SYMBOL_GPL(ata_eng_timeout); | ||
5149 | EXPORT_SYMBOL_GPL(ata_tf_load); | 5055 | EXPORT_SYMBOL_GPL(ata_tf_load); |
5150 | EXPORT_SYMBOL_GPL(ata_tf_read); | 5056 | EXPORT_SYMBOL_GPL(ata_tf_read); |
5151 | EXPORT_SYMBOL_GPL(ata_noop_dev_select); | 5057 | EXPORT_SYMBOL_GPL(ata_noop_dev_select); |
@@ -5185,15 +5091,12 @@ EXPORT_SYMBOL_GPL(ata_busy_sleep); | |||
5185 | EXPORT_SYMBOL_GPL(ata_port_queue_task); | 5091 | EXPORT_SYMBOL_GPL(ata_port_queue_task); |
5186 | EXPORT_SYMBOL_GPL(ata_scsi_ioctl); | 5092 | EXPORT_SYMBOL_GPL(ata_scsi_ioctl); |
5187 | EXPORT_SYMBOL_GPL(ata_scsi_queuecmd); | 5093 | EXPORT_SYMBOL_GPL(ata_scsi_queuecmd); |
5188 | EXPORT_SYMBOL_GPL(ata_scsi_error); | ||
5189 | EXPORT_SYMBOL_GPL(ata_scsi_slave_config); | 5094 | EXPORT_SYMBOL_GPL(ata_scsi_slave_config); |
5190 | EXPORT_SYMBOL_GPL(ata_scsi_release); | 5095 | EXPORT_SYMBOL_GPL(ata_scsi_release); |
5191 | EXPORT_SYMBOL_GPL(ata_host_intr); | 5096 | EXPORT_SYMBOL_GPL(ata_host_intr); |
5192 | EXPORT_SYMBOL_GPL(ata_id_string); | 5097 | EXPORT_SYMBOL_GPL(ata_id_string); |
5193 | EXPORT_SYMBOL_GPL(ata_id_c_string); | 5098 | EXPORT_SYMBOL_GPL(ata_id_c_string); |
5194 | EXPORT_SYMBOL_GPL(ata_scsi_simulate); | 5099 | EXPORT_SYMBOL_GPL(ata_scsi_simulate); |
5195 | EXPORT_SYMBOL_GPL(ata_eh_qc_complete); | ||
5196 | EXPORT_SYMBOL_GPL(ata_eh_qc_retry); | ||
5197 | 5100 | ||
5198 | EXPORT_SYMBOL_GPL(ata_pio_need_iordy); | 5101 | EXPORT_SYMBOL_GPL(ata_pio_need_iordy); |
5199 | EXPORT_SYMBOL_GPL(ata_timing_compute); | 5102 | EXPORT_SYMBOL_GPL(ata_timing_compute); |
@@ -5215,3 +5118,8 @@ EXPORT_SYMBOL_GPL(ata_device_suspend); | |||
5215 | EXPORT_SYMBOL_GPL(ata_device_resume); | 5118 | EXPORT_SYMBOL_GPL(ata_device_resume); |
5216 | EXPORT_SYMBOL_GPL(ata_scsi_device_suspend); | 5119 | EXPORT_SYMBOL_GPL(ata_scsi_device_suspend); |
5217 | EXPORT_SYMBOL_GPL(ata_scsi_device_resume); | 5120 | EXPORT_SYMBOL_GPL(ata_scsi_device_resume); |
5121 | |||
5122 | EXPORT_SYMBOL_GPL(ata_scsi_error); | ||
5123 | EXPORT_SYMBOL_GPL(ata_eng_timeout); | ||
5124 | EXPORT_SYMBOL_GPL(ata_eh_qc_complete); | ||
5125 | EXPORT_SYMBOL_GPL(ata_eh_qc_retry); | ||
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c new file mode 100644 index 000000000000..e73f5612aea8 --- /dev/null +++ b/drivers/scsi/libata-eh.c | |||
@@ -0,0 +1,264 @@ | |||
1 | /* | ||
2 | * libata-eh.c - libata error handling | ||
3 | * | ||
4 | * Maintained by: Jeff Garzik <jgarzik@pobox.com> | ||
5 | * Please ALWAYS copy linux-ide@vger.kernel.org | ||
6 | * on emails. | ||
7 | * | ||
8 | * Copyright 2006 Tejun Heo <htejun@gmail.com> | ||
9 | * | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or | ||
12 | * modify it under the terms of the GNU General Public License as | ||
13 | * published by the Free Software Foundation; either version 2, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
19 | * General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; see the file COPYING. If not, write to | ||
23 | * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, | ||
24 | * USA. | ||
25 | * | ||
26 | * | ||
27 | * libata documentation is available via 'make {ps|pdf}docs', | ||
28 | * as Documentation/DocBook/libata.* | ||
29 | * | ||
30 | * Hardware documentation available from http://www.t13.org/ and | ||
31 | * http://www.sata-io.org/ | ||
32 | * | ||
33 | */ | ||
34 | |||
35 | #include <linux/config.h> | ||
36 | #include <linux/kernel.h> | ||
37 | #include <scsi/scsi.h> | ||
38 | #include <scsi/scsi_host.h> | ||
39 | #include <scsi/scsi_eh.h> | ||
40 | #include <scsi/scsi_device.h> | ||
41 | #include <scsi/scsi_cmnd.h> | ||
42 | |||
43 | #include <linux/libata.h> | ||
44 | |||
45 | #include "libata.h" | ||
46 | |||
47 | /** | ||
48 | * ata_scsi_timed_out - SCSI layer time out callback | ||
49 | * @cmd: timed out SCSI command | ||
50 | * | ||
51 | * Handles SCSI layer timeout. We race with normal completion of | ||
52 | * the qc for @cmd. If the qc is already gone, we lose and let | ||
53 | * the scsi command finish (EH_HANDLED). Otherwise, the qc has | ||
54 | * timed out and EH should be invoked. Prevent ata_qc_complete() | ||
55 | * from finishing it by setting EH_SCHEDULED and return | ||
56 | * EH_NOT_HANDLED. | ||
57 | * | ||
58 | * LOCKING: | ||
59 | * Called from timer context | ||
60 | * | ||
61 | * RETURNS: | ||
62 | * EH_HANDLED or EH_NOT_HANDLED | ||
63 | */ | ||
64 | enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd) | ||
65 | { | ||
66 | struct Scsi_Host *host = cmd->device->host; | ||
67 | struct ata_port *ap = (struct ata_port *) &host->hostdata[0]; | ||
68 | unsigned long flags; | ||
69 | struct ata_queued_cmd *qc; | ||
70 | enum scsi_eh_timer_return ret = EH_HANDLED; | ||
71 | |||
72 | DPRINTK("ENTER\n"); | ||
73 | |||
74 | spin_lock_irqsave(&ap->host_set->lock, flags); | ||
75 | qc = ata_qc_from_tag(ap, ap->active_tag); | ||
76 | if (qc) { | ||
77 | WARN_ON(qc->scsicmd != cmd); | ||
78 | qc->flags |= ATA_QCFLAG_EH_SCHEDULED; | ||
79 | qc->err_mask |= AC_ERR_TIMEOUT; | ||
80 | ret = EH_NOT_HANDLED; | ||
81 | } | ||
82 | spin_unlock_irqrestore(&ap->host_set->lock, flags); | ||
83 | |||
84 | DPRINTK("EXIT, ret=%d\n", ret); | ||
85 | return ret; | ||
86 | } | ||
87 | |||
88 | /** | ||
89 | * ata_scsi_error - SCSI layer error handler callback | ||
90 | * @host: SCSI host on which error occurred | ||
91 | * | ||
92 | * Handles SCSI-layer-thrown error events. | ||
93 | * | ||
94 | * LOCKING: | ||
95 | * Inherited from SCSI layer (none, can sleep) | ||
96 | * | ||
97 | * RETURNS: | ||
98 | * Zero. | ||
99 | */ | ||
100 | int ata_scsi_error(struct Scsi_Host *host) | ||
101 | { | ||
102 | struct ata_port *ap = (struct ata_port *)&host->hostdata[0]; | ||
103 | |||
104 | DPRINTK("ENTER\n"); | ||
105 | |||
106 | /* synchronize with IRQ handler and port task */ | ||
107 | spin_unlock_wait(&ap->host_set->lock); | ||
108 | ata_port_flush_task(ap); | ||
109 | |||
110 | WARN_ON(ata_qc_from_tag(ap, ap->active_tag) == NULL); | ||
111 | |||
112 | ap->ops->eng_timeout(ap); | ||
113 | |||
114 | WARN_ON(host->host_failed || !list_empty(&host->eh_cmd_q)); | ||
115 | |||
116 | scsi_eh_flush_done_q(&ap->eh_done_q); | ||
117 | |||
118 | DPRINTK("EXIT\n"); | ||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | /** | ||
123 | * ata_qc_timeout - Handle timeout of queued command | ||
124 | * @qc: Command that timed out | ||
125 | * | ||
126 | * Some part of the kernel (currently, only the SCSI layer) | ||
127 | * has noticed that the active command on port @ap has not | ||
128 | * completed after a specified length of time. Handle this | ||
129 | * condition by disabling DMA (if necessary) and completing | ||
130 | * transactions, with error if necessary. | ||
131 | * | ||
132 | * This also handles the case of the "lost interrupt", where | ||
133 | * for some reason (possibly hardware bug, possibly driver bug) | ||
134 | * an interrupt was not delivered to the driver, even though the | ||
135 | * transaction completed successfully. | ||
136 | * | ||
137 | * LOCKING: | ||
138 | * Inherited from SCSI layer (none, can sleep) | ||
139 | */ | ||
140 | static void ata_qc_timeout(struct ata_queued_cmd *qc) | ||
141 | { | ||
142 | struct ata_port *ap = qc->ap; | ||
143 | struct ata_host_set *host_set = ap->host_set; | ||
144 | u8 host_stat = 0, drv_stat; | ||
145 | unsigned long flags; | ||
146 | |||
147 | DPRINTK("ENTER\n"); | ||
148 | |||
149 | ap->hsm_task_state = HSM_ST_IDLE; | ||
150 | |||
151 | spin_lock_irqsave(&host_set->lock, flags); | ||
152 | |||
153 | switch (qc->tf.protocol) { | ||
154 | |||
155 | case ATA_PROT_DMA: | ||
156 | case ATA_PROT_ATAPI_DMA: | ||
157 | host_stat = ap->ops->bmdma_status(ap); | ||
158 | |||
159 | /* before we do anything else, clear DMA-Start bit */ | ||
160 | ap->ops->bmdma_stop(qc); | ||
161 | |||
162 | /* fall through */ | ||
163 | |||
164 | default: | ||
165 | ata_altstatus(ap); | ||
166 | drv_stat = ata_chk_status(ap); | ||
167 | |||
168 | /* ack bmdma irq events */ | ||
169 | ap->ops->irq_clear(ap); | ||
170 | |||
171 | printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x host_stat 0x%x\n", | ||
172 | ap->id, qc->tf.command, drv_stat, host_stat); | ||
173 | |||
174 | /* complete taskfile transaction */ | ||
175 | qc->err_mask |= ac_err_mask(drv_stat); | ||
176 | break; | ||
177 | } | ||
178 | |||
179 | spin_unlock_irqrestore(&host_set->lock, flags); | ||
180 | |||
181 | ata_eh_qc_complete(qc); | ||
182 | |||
183 | DPRINTK("EXIT\n"); | ||
184 | } | ||
185 | |||
186 | /** | ||
187 | * ata_eng_timeout - Handle timeout of queued command | ||
188 | * @ap: Port on which timed-out command is active | ||
189 | * | ||
190 | * Some part of the kernel (currently, only the SCSI layer) | ||
191 | * has noticed that the active command on port @ap has not | ||
192 | * completed after a specified length of time. Handle this | ||
193 | * condition by disabling DMA (if necessary) and completing | ||
194 | * transactions, with error if necessary. | ||
195 | * | ||
196 | * This also handles the case of the "lost interrupt", where | ||
197 | * for some reason (possibly hardware bug, possibly driver bug) | ||
198 | * an interrupt was not delivered to the driver, even though the | ||
199 | * transaction completed successfully. | ||
200 | * | ||
201 | * LOCKING: | ||
202 | * Inherited from SCSI layer (none, can sleep) | ||
203 | */ | ||
204 | void ata_eng_timeout(struct ata_port *ap) | ||
205 | { | ||
206 | DPRINTK("ENTER\n"); | ||
207 | |||
208 | ata_qc_timeout(ata_qc_from_tag(ap, ap->active_tag)); | ||
209 | |||
210 | DPRINTK("EXIT\n"); | ||
211 | } | ||
212 | |||
213 | static void ata_eh_scsidone(struct scsi_cmnd *scmd) | ||
214 | { | ||
215 | /* nada */ | ||
216 | } | ||
217 | |||
218 | static void __ata_eh_qc_complete(struct ata_queued_cmd *qc) | ||
219 | { | ||
220 | struct ata_port *ap = qc->ap; | ||
221 | struct scsi_cmnd *scmd = qc->scsicmd; | ||
222 | unsigned long flags; | ||
223 | |||
224 | spin_lock_irqsave(&ap->host_set->lock, flags); | ||
225 | qc->scsidone = ata_eh_scsidone; | ||
226 | __ata_qc_complete(qc); | ||
227 | WARN_ON(ata_tag_valid(qc->tag)); | ||
228 | spin_unlock_irqrestore(&ap->host_set->lock, flags); | ||
229 | |||
230 | scsi_eh_finish_cmd(scmd, &ap->eh_done_q); | ||
231 | } | ||
232 | |||
233 | /** | ||
234 | * ata_eh_qc_complete - Complete an active ATA command from EH | ||
235 | * @qc: Command to complete | ||
236 | * | ||
237 | * Indicate to the mid and upper layers that an ATA command has | ||
238 | * completed. To be used from EH. | ||
239 | */ | ||
240 | void ata_eh_qc_complete(struct ata_queued_cmd *qc) | ||
241 | { | ||
242 | struct scsi_cmnd *scmd = qc->scsicmd; | ||
243 | scmd->retries = scmd->allowed; | ||
244 | __ata_eh_qc_complete(qc); | ||
245 | } | ||
246 | |||
247 | /** | ||
248 | * ata_eh_qc_retry - Tell midlayer to retry an ATA command after EH | ||
249 | * @qc: Command to retry | ||
250 | * | ||
251 | * Indicate to the mid and upper layers that an ATA command | ||
252 | * should be retried. To be used from EH. | ||
253 | * | ||
254 | * SCSI midlayer limits the number of retries to scmd->allowed. | ||
255 | * scmd->retries is decremented for commands which get retried | ||
256 | * due to unrelated failures (qc->err_mask is zero). | ||
257 | */ | ||
258 | void ata_eh_qc_retry(struct ata_queued_cmd *qc) | ||
259 | { | ||
260 | struct scsi_cmnd *scmd = qc->scsicmd; | ||
261 | if (!qc->err_mask && scmd->retries) | ||
262 | scmd->retries--; | ||
263 | __ata_eh_qc_complete(qc); | ||
264 | } | ||
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 44008150d310..745fc263feeb 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c | |||
@@ -53,7 +53,6 @@ | |||
53 | typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, const u8 *scsicmd); | 53 | typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, const u8 *scsicmd); |
54 | static struct ata_device * | 54 | static struct ata_device * |
55 | ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev); | 55 | ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev); |
56 | enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); | ||
57 | 56 | ||
58 | #define RW_RECOVERY_MPAGE 0x1 | 57 | #define RW_RECOVERY_MPAGE 0x1 |
59 | #define RW_RECOVERY_MPAGE_LEN 12 | 58 | #define RW_RECOVERY_MPAGE_LEN 12 |
@@ -714,135 +713,6 @@ int ata_scsi_slave_config(struct scsi_device *sdev) | |||
714 | } | 713 | } |
715 | 714 | ||
716 | /** | 715 | /** |
717 | * ata_scsi_timed_out - SCSI layer time out callback | ||
718 | * @cmd: timed out SCSI command | ||
719 | * | ||
720 | * Handles SCSI layer timeout. We race with normal completion of | ||
721 | * the qc for @cmd. If the qc is already gone, we lose and let | ||
722 | * the scsi command finish (EH_HANDLED). Otherwise, the qc has | ||
723 | * timed out and EH should be invoked. Prevent ata_qc_complete() | ||
724 | * from finishing it by setting EH_SCHEDULED and return | ||
725 | * EH_NOT_HANDLED. | ||
726 | * | ||
727 | * LOCKING: | ||
728 | * Called from timer context | ||
729 | * | ||
730 | * RETURNS: | ||
731 | * EH_HANDLED or EH_NOT_HANDLED | ||
732 | */ | ||
733 | enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd) | ||
734 | { | ||
735 | struct Scsi_Host *host = cmd->device->host; | ||
736 | struct ata_port *ap = (struct ata_port *) &host->hostdata[0]; | ||
737 | unsigned long flags; | ||
738 | struct ata_queued_cmd *qc; | ||
739 | enum scsi_eh_timer_return ret = EH_HANDLED; | ||
740 | |||
741 | DPRINTK("ENTER\n"); | ||
742 | |||
743 | spin_lock_irqsave(&ap->host_set->lock, flags); | ||
744 | qc = ata_qc_from_tag(ap, ap->active_tag); | ||
745 | if (qc) { | ||
746 | WARN_ON(qc->scsicmd != cmd); | ||
747 | qc->flags |= ATA_QCFLAG_EH_SCHEDULED; | ||
748 | qc->err_mask |= AC_ERR_TIMEOUT; | ||
749 | ret = EH_NOT_HANDLED; | ||
750 | } | ||
751 | spin_unlock_irqrestore(&ap->host_set->lock, flags); | ||
752 | |||
753 | DPRINTK("EXIT, ret=%d\n", ret); | ||
754 | return ret; | ||
755 | } | ||
756 | |||
757 | /** | ||
758 | * ata_scsi_error - SCSI layer error handler callback | ||
759 | * @host: SCSI host on which error occurred | ||
760 | * | ||
761 | * Handles SCSI-layer-thrown error events. | ||
762 | * | ||
763 | * LOCKING: | ||
764 | * Inherited from SCSI layer (none, can sleep) | ||
765 | * | ||
766 | * RETURNS: | ||
767 | * Zero. | ||
768 | */ | ||
769 | |||
770 | int ata_scsi_error(struct Scsi_Host *host) | ||
771 | { | ||
772 | struct ata_port *ap = (struct ata_port *)&host->hostdata[0]; | ||
773 | |||
774 | DPRINTK("ENTER\n"); | ||
775 | |||
776 | /* synchronize with IRQ handler and port task */ | ||
777 | spin_unlock_wait(&ap->host_set->lock); | ||
778 | ata_port_flush_task(ap); | ||
779 | |||
780 | WARN_ON(ata_qc_from_tag(ap, ap->active_tag) == NULL); | ||
781 | |||
782 | ap->ops->eng_timeout(ap); | ||
783 | |||
784 | WARN_ON(host->host_failed || !list_empty(&host->eh_cmd_q)); | ||
785 | |||
786 | scsi_eh_flush_done_q(&ap->eh_done_q); | ||
787 | |||
788 | DPRINTK("EXIT\n"); | ||
789 | return 0; | ||
790 | } | ||
791 | |||
792 | static void ata_eh_scsidone(struct scsi_cmnd *scmd) | ||
793 | { | ||
794 | /* nada */ | ||
795 | } | ||
796 | |||
797 | static void __ata_eh_qc_complete(struct ata_queued_cmd *qc) | ||
798 | { | ||
799 | struct ata_port *ap = qc->ap; | ||
800 | struct scsi_cmnd *scmd = qc->scsicmd; | ||
801 | unsigned long flags; | ||
802 | |||
803 | spin_lock_irqsave(&ap->host_set->lock, flags); | ||
804 | qc->scsidone = ata_eh_scsidone; | ||
805 | __ata_qc_complete(qc); | ||
806 | WARN_ON(ata_tag_valid(qc->tag)); | ||
807 | spin_unlock_irqrestore(&ap->host_set->lock, flags); | ||
808 | |||
809 | scsi_eh_finish_cmd(scmd, &ap->eh_done_q); | ||
810 | } | ||
811 | |||
812 | /** | ||
813 | * ata_eh_qc_complete - Complete an active ATA command from EH | ||
814 | * @qc: Command to complete | ||
815 | * | ||
816 | * Indicate to the mid and upper layers that an ATA command has | ||
817 | * completed. To be used from EH. | ||
818 | */ | ||
819 | void ata_eh_qc_complete(struct ata_queued_cmd *qc) | ||
820 | { | ||
821 | struct scsi_cmnd *scmd = qc->scsicmd; | ||
822 | scmd->retries = scmd->allowed; | ||
823 | __ata_eh_qc_complete(qc); | ||
824 | } | ||
825 | |||
826 | /** | ||
827 | * ata_eh_qc_retry - Tell midlayer to retry an ATA command after EH | ||
828 | * @qc: Command to retry | ||
829 | * | ||
830 | * Indicate to the mid and upper layers that an ATA command | ||
831 | * should be retried. To be used from EH. | ||
832 | * | ||
833 | * SCSI midlayer limits the number of retries to scmd->allowed. | ||
834 | * scmd->retries is decremented for commands which get retried | ||
835 | * due to unrelated failures (qc->err_mask is zero). | ||
836 | */ | ||
837 | void ata_eh_qc_retry(struct ata_queued_cmd *qc) | ||
838 | { | ||
839 | struct scsi_cmnd *scmd = qc->scsicmd; | ||
840 | if (!qc->err_mask && scmd->retries) | ||
841 | scmd->retries--; | ||
842 | __ata_eh_qc_complete(qc); | ||
843 | } | ||
844 | |||
845 | /** | ||
846 | * ata_scsi_start_stop_xlat - Translate SCSI START STOP UNIT command | 716 | * ata_scsi_start_stop_xlat - Translate SCSI START STOP UNIT command |
847 | * @qc: Storage for translated ATA taskfile | 717 | * @qc: Storage for translated ATA taskfile |
848 | * @scsicmd: SCSI command to translate | 718 | * @scsicmd: SCSI command to translate |
diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index 1c755b14521a..75e9bd5833da 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h | |||
@@ -60,7 +60,6 @@ extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg); | |||
60 | extern struct scsi_transport_template ata_scsi_transport_template; | 60 | extern struct scsi_transport_template ata_scsi_transport_template; |
61 | 61 | ||
62 | extern void ata_scsi_scan_host(struct ata_port *ap); | 62 | extern void ata_scsi_scan_host(struct ata_port *ap); |
63 | extern int ata_scsi_error(struct Scsi_Host *host); | ||
64 | extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, | 63 | extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, |
65 | unsigned int buflen); | 64 | unsigned int buflen); |
66 | 65 | ||
@@ -90,4 +89,7 @@ extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args, | |||
90 | unsigned int (*actor) (struct ata_scsi_args *args, | 89 | unsigned int (*actor) (struct ata_scsi_args *args, |
91 | u8 *rbuf, unsigned int buflen)); | 90 | u8 *rbuf, unsigned int buflen)); |
92 | 91 | ||
92 | /* libata-eh.c */ | ||
93 | extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); | ||
94 | |||
93 | #endif /* __LIBATA_H__ */ | 95 | #endif /* __LIBATA_H__ */ |