diff options
author | Tejun Heo <htejun@gmail.com> | 2006-05-15 07:58:05 -0400 |
---|---|---|
committer | Tejun Heo <htejun@gmail.com> | 2006-05-15 07:58:05 -0400 |
commit | f686bcb8078ac7505ec88818886c2c72639f4fc5 (patch) | |
tree | 7c563e0032b2d85b631b617b8bb2a7a648607468 | |
parent | f69499f42caf74194df678c9c293f2ee0fe90bc3 (diff) |
[PATCH] libata-eh-fw: implement new EH scheduling via error completion
There are several ways a qc can get schedule for EH in new EH. This
patch implements one of them - completing a qc with ATA_QCFLAG_FAILED
set or with non-zero qc->err_mask. ALL such qc's are examined by EH.
New EH schedules a qc for EH from completion iff ->error_handler is
implemented, qc is marked as failed or qc->err_mask is non-zero and
the command is not an internal command (internal cmd is handled via
->post_internal_cmd). The EH scheduling itself is performed by asking
SCSI midlayer to schedule EH for the specified scmd.
For drivers implementing old-EH, nothing changes. As this change
makes ata_qc_complete() rather large, it's not inlined anymore and
__ata_qc_complete() is exported to other parts of libata for later
use.
Signed-off-by: Tejun Heo <htejun@gmail.com>
-rw-r--r-- | drivers/scsi/libata-core.c | 62 | ||||
-rw-r--r-- | drivers/scsi/libata-eh.c | 27 | ||||
-rw-r--r-- | drivers/scsi/libata.h | 2 | ||||
-rw-r--r-- | include/linux/libata.h | 27 |
4 files changed, 91 insertions, 27 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 1c34c1427aa3..1f5c3270992a 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c | |||
@@ -4123,6 +4123,66 @@ void __ata_qc_complete(struct ata_queued_cmd *qc) | |||
4123 | qc->complete_fn(qc); | 4123 | qc->complete_fn(qc); |
4124 | } | 4124 | } |
4125 | 4125 | ||
4126 | /** | ||
4127 | * ata_qc_complete - Complete an active ATA command | ||
4128 | * @qc: Command to complete | ||
4129 | * @err_mask: ATA Status register contents | ||
4130 | * | ||
4131 | * Indicate to the mid and upper layers that an ATA | ||
4132 | * command has completed, with either an ok or not-ok status. | ||
4133 | * | ||
4134 | * LOCKING: | ||
4135 | * spin_lock_irqsave(host_set lock) | ||
4136 | */ | ||
4137 | void ata_qc_complete(struct ata_queued_cmd *qc) | ||
4138 | { | ||
4139 | struct ata_port *ap = qc->ap; | ||
4140 | |||
4141 | /* XXX: New EH and old EH use different mechanisms to | ||
4142 | * synchronize EH with regular execution path. | ||
4143 | * | ||
4144 | * In new EH, a failed qc is marked with ATA_QCFLAG_FAILED. | ||
4145 | * Normal execution path is responsible for not accessing a | ||
4146 | * failed qc. libata core enforces the rule by returning NULL | ||
4147 | * from ata_qc_from_tag() for failed qcs. | ||
4148 | * | ||
4149 | * Old EH depends on ata_qc_complete() nullifying completion | ||
4150 | * requests if ATA_QCFLAG_EH_SCHEDULED is set. Old EH does | ||
4151 | * not synchronize with interrupt handler. Only PIO task is | ||
4152 | * taken care of. | ||
4153 | */ | ||
4154 | if (ap->ops->error_handler) { | ||
4155 | WARN_ON(ap->flags & ATA_FLAG_FROZEN); | ||
4156 | |||
4157 | if (unlikely(qc->err_mask)) | ||
4158 | qc->flags |= ATA_QCFLAG_FAILED; | ||
4159 | |||
4160 | if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) { | ||
4161 | if (!ata_tag_internal(qc->tag)) { | ||
4162 | /* always fill result TF for failed qc */ | ||
4163 | ap->ops->tf_read(ap, &qc->result_tf); | ||
4164 | ata_qc_schedule_eh(qc); | ||
4165 | return; | ||
4166 | } | ||
4167 | } | ||
4168 | |||
4169 | /* read result TF if requested */ | ||
4170 | if (qc->flags & ATA_QCFLAG_RESULT_TF) | ||
4171 | ap->ops->tf_read(ap, &qc->result_tf); | ||
4172 | |||
4173 | __ata_qc_complete(qc); | ||
4174 | } else { | ||
4175 | if (qc->flags & ATA_QCFLAG_EH_SCHEDULED) | ||
4176 | return; | ||
4177 | |||
4178 | /* read result TF if failed or requested */ | ||
4179 | if (qc->err_mask || qc->flags & ATA_QCFLAG_RESULT_TF) | ||
4180 | ap->ops->tf_read(ap, &qc->result_tf); | ||
4181 | |||
4182 | __ata_qc_complete(qc); | ||
4183 | } | ||
4184 | } | ||
4185 | |||
4126 | static inline int ata_should_dma_map(struct ata_queued_cmd *qc) | 4186 | static inline int ata_should_dma_map(struct ata_queued_cmd *qc) |
4127 | { | 4187 | { |
4128 | struct ata_port *ap = qc->ap; | 4188 | struct ata_port *ap = qc->ap; |
@@ -5245,7 +5305,7 @@ EXPORT_SYMBOL_GPL(ata_device_add); | |||
5245 | EXPORT_SYMBOL_GPL(ata_host_set_remove); | 5305 | EXPORT_SYMBOL_GPL(ata_host_set_remove); |
5246 | EXPORT_SYMBOL_GPL(ata_sg_init); | 5306 | EXPORT_SYMBOL_GPL(ata_sg_init); |
5247 | EXPORT_SYMBOL_GPL(ata_sg_init_one); | 5307 | EXPORT_SYMBOL_GPL(ata_sg_init_one); |
5248 | EXPORT_SYMBOL_GPL(__ata_qc_complete); | 5308 | EXPORT_SYMBOL_GPL(ata_qc_complete); |
5249 | EXPORT_SYMBOL_GPL(ata_qc_issue_prot); | 5309 | EXPORT_SYMBOL_GPL(ata_qc_issue_prot); |
5250 | EXPORT_SYMBOL_GPL(ata_tf_load); | 5310 | EXPORT_SYMBOL_GPL(ata_tf_load); |
5251 | EXPORT_SYMBOL_GPL(ata_tf_read); | 5311 | EXPORT_SYMBOL_GPL(ata_tf_read); |
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index 959a1cdffac2..471846fe4b73 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c | |||
@@ -210,6 +210,33 @@ void ata_eng_timeout(struct ata_port *ap) | |||
210 | DPRINTK("EXIT\n"); | 210 | DPRINTK("EXIT\n"); |
211 | } | 211 | } |
212 | 212 | ||
213 | /** | ||
214 | * ata_qc_schedule_eh - schedule qc for error handling | ||
215 | * @qc: command to schedule error handling for | ||
216 | * | ||
217 | * Schedule error handling for @qc. EH will kick in as soon as | ||
218 | * other commands are drained. | ||
219 | * | ||
220 | * LOCKING: | ||
221 | * spin_lock_irqsave(host_set lock) | ||
222 | */ | ||
223 | void ata_qc_schedule_eh(struct ata_queued_cmd *qc) | ||
224 | { | ||
225 | struct ata_port *ap = qc->ap; | ||
226 | |||
227 | WARN_ON(!ap->ops->error_handler); | ||
228 | |||
229 | qc->flags |= ATA_QCFLAG_FAILED; | ||
230 | qc->ap->flags |= ATA_FLAG_EH_PENDING; | ||
231 | |||
232 | /* The following will fail if timeout has already expired. | ||
233 | * ata_scsi_error() takes care of such scmds on EH entry. | ||
234 | * Note that ATA_QCFLAG_FAILED is unconditionally set after | ||
235 | * this function completes. | ||
236 | */ | ||
237 | scsi_req_abort_cmd(qc->scsicmd); | ||
238 | } | ||
239 | |||
213 | static void ata_eh_scsidone(struct scsi_cmnd *scmd) | 240 | static void ata_eh_scsidone(struct scsi_cmnd *scmd) |
214 | { | 241 | { |
215 | /* nada */ | 242 | /* nada */ |
diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index c9ff83bbcfae..52622b7f8a9e 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h | |||
@@ -57,6 +57,7 @@ extern int ata_do_reset(struct ata_port *ap, ata_reset_fn_t reset, | |||
57 | unsigned int *classes); | 57 | unsigned int *classes); |
58 | extern void ata_qc_free(struct ata_queued_cmd *qc); | 58 | extern void ata_qc_free(struct ata_queued_cmd *qc); |
59 | extern void ata_qc_issue(struct ata_queued_cmd *qc); | 59 | extern void ata_qc_issue(struct ata_queued_cmd *qc); |
60 | extern void __ata_qc_complete(struct ata_queued_cmd *qc); | ||
60 | extern int ata_check_atapi_dma(struct ata_queued_cmd *qc); | 61 | extern int ata_check_atapi_dma(struct ata_queued_cmd *qc); |
61 | extern void ata_dev_select(struct ata_port *ap, unsigned int device, | 62 | extern void ata_dev_select(struct ata_port *ap, unsigned int device, |
62 | unsigned int wait, unsigned int can_sleep); | 63 | unsigned int wait, unsigned int can_sleep); |
@@ -101,5 +102,6 @@ extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args, | |||
101 | /* libata-eh.c */ | 102 | /* libata-eh.c */ |
102 | extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); | 103 | extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); |
103 | extern void ata_scsi_error(struct Scsi_Host *host); | 104 | extern void ata_scsi_error(struct Scsi_Host *host); |
105 | extern void ata_qc_schedule_eh(struct ata_queued_cmd *qc); | ||
104 | 106 | ||
105 | #endif /* __LIBATA_H__ */ | 107 | #endif /* __LIBATA_H__ */ |
diff --git a/include/linux/libata.h b/include/linux/libata.h index bfcefdca0616..6023f324e68e 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h | |||
@@ -605,7 +605,7 @@ extern void ata_bmdma_start (struct ata_queued_cmd *qc); | |||
605 | extern void ata_bmdma_stop(struct ata_queued_cmd *qc); | 605 | extern void ata_bmdma_stop(struct ata_queued_cmd *qc); |
606 | extern u8 ata_bmdma_status(struct ata_port *ap); | 606 | extern u8 ata_bmdma_status(struct ata_port *ap); |
607 | extern void ata_bmdma_irq_clear(struct ata_port *ap); | 607 | extern void ata_bmdma_irq_clear(struct ata_port *ap); |
608 | extern void __ata_qc_complete(struct ata_queued_cmd *qc); | 608 | extern void ata_qc_complete(struct ata_queued_cmd *qc); |
609 | extern void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd, | 609 | extern void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd, |
610 | void (*done)(struct scsi_cmnd *)); | 610 | void (*done)(struct scsi_cmnd *)); |
611 | extern int ata_std_bios_param(struct scsi_device *sdev, | 611 | extern int ata_std_bios_param(struct scsi_device *sdev, |
@@ -883,31 +883,6 @@ static inline void ata_qc_reinit(struct ata_queued_cmd *qc) | |||
883 | } | 883 | } |
884 | 884 | ||
885 | /** | 885 | /** |
886 | * ata_qc_complete - Complete an active ATA command | ||
887 | * @qc: Command to complete | ||
888 | * @err_mask: ATA Status register contents | ||
889 | * | ||
890 | * Indicate to the mid and upper layers that an ATA | ||
891 | * command has completed, with either an ok or not-ok status. | ||
892 | * | ||
893 | * LOCKING: | ||
894 | * spin_lock_irqsave(host_set lock) | ||
895 | */ | ||
896 | static inline void ata_qc_complete(struct ata_queued_cmd *qc) | ||
897 | { | ||
898 | struct ata_port *ap = qc->ap; | ||
899 | |||
900 | if (unlikely(qc->flags & ATA_QCFLAG_EH_SCHEDULED)) | ||
901 | return; | ||
902 | |||
903 | /* read result TF if failed or requested */ | ||
904 | if (qc->err_mask || qc->flags & ATA_QCFLAG_RESULT_TF) | ||
905 | ap->ops->tf_read(ap, &qc->result_tf); | ||
906 | |||
907 | __ata_qc_complete(qc); | ||
908 | } | ||
909 | |||
910 | /** | ||
911 | * ata_irq_on - Enable interrupts on a port. | 886 | * ata_irq_on - Enable interrupts on a port. |
912 | * @ap: Port on which interrupts are enabled. | 887 | * @ap: Port on which interrupts are enabled. |
913 | * | 888 | * |