diff options
author | Mark Lord <liml@rtr.ca> | 2007-11-07 10:54:15 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-11-08 13:08:41 -0500 |
commit | 6004bda1cce51273ac9e71a39e680831b9ff4503 (patch) | |
tree | c1a27e4485f7ec2c06aeaaec8b0878a0dd115398 /drivers | |
parent | 904c7bad994e6e7f9997174e0b33fcc521862136 (diff) |
libata sata_qstor conversion to new error handling (EH).
sata_qstor conversion to new error handling (EH).
Convert sata_qstor to use the newer libata EH mechanisms.
Based on earlier work by Jeff Garzik.
Signed-off-by: Mark Lord <mlord@pobox.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ata/sata_qstor.c | 65 |
1 files changed, 51 insertions, 14 deletions
diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c index 7446a335fc92..2f1de6ec044c 100644 --- a/drivers/ata/sata_qstor.c +++ b/drivers/ata/sata_qstor.c | |||
@@ -116,14 +116,15 @@ static int qs_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val); | |||
116 | static int qs_ata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); | 116 | static int qs_ata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); |
117 | static int qs_port_start(struct ata_port *ap); | 117 | static int qs_port_start(struct ata_port *ap); |
118 | static void qs_host_stop(struct ata_host *host); | 118 | static void qs_host_stop(struct ata_host *host); |
119 | static void qs_phy_reset(struct ata_port *ap); | ||
120 | static void qs_qc_prep(struct ata_queued_cmd *qc); | 119 | static void qs_qc_prep(struct ata_queued_cmd *qc); |
121 | static unsigned int qs_qc_issue(struct ata_queued_cmd *qc); | 120 | static unsigned int qs_qc_issue(struct ata_queued_cmd *qc); |
122 | static int qs_check_atapi_dma(struct ata_queued_cmd *qc); | 121 | static int qs_check_atapi_dma(struct ata_queued_cmd *qc); |
123 | static void qs_bmdma_stop(struct ata_queued_cmd *qc); | 122 | static void qs_bmdma_stop(struct ata_queued_cmd *qc); |
124 | static u8 qs_bmdma_status(struct ata_port *ap); | 123 | static u8 qs_bmdma_status(struct ata_port *ap); |
125 | static void qs_irq_clear(struct ata_port *ap); | 124 | static void qs_irq_clear(struct ata_port *ap); |
126 | static void qs_eng_timeout(struct ata_port *ap); | 125 | static void qs_freeze(struct ata_port *ap); |
126 | static void qs_thaw(struct ata_port *ap); | ||
127 | static void qs_error_handler(struct ata_port *ap); | ||
127 | 128 | ||
128 | static struct scsi_host_template qs_ata_sht = { | 129 | static struct scsi_host_template qs_ata_sht = { |
129 | .module = THIS_MODULE, | 130 | .module = THIS_MODULE, |
@@ -150,11 +151,12 @@ static const struct ata_port_operations qs_ata_ops = { | |||
150 | .check_atapi_dma = qs_check_atapi_dma, | 151 | .check_atapi_dma = qs_check_atapi_dma, |
151 | .exec_command = ata_exec_command, | 152 | .exec_command = ata_exec_command, |
152 | .dev_select = ata_std_dev_select, | 153 | .dev_select = ata_std_dev_select, |
153 | .phy_reset = qs_phy_reset, | ||
154 | .qc_prep = qs_qc_prep, | 154 | .qc_prep = qs_qc_prep, |
155 | .qc_issue = qs_qc_issue, | 155 | .qc_issue = qs_qc_issue, |
156 | .data_xfer = ata_data_xfer, | 156 | .data_xfer = ata_data_xfer, |
157 | .eng_timeout = qs_eng_timeout, | 157 | .freeze = qs_freeze, |
158 | .thaw = qs_thaw, | ||
159 | .error_handler = qs_error_handler, | ||
158 | .irq_clear = qs_irq_clear, | 160 | .irq_clear = qs_irq_clear, |
159 | .irq_on = ata_irq_on, | 161 | .irq_on = ata_irq_on, |
160 | .scr_read = qs_scr_read, | 162 | .scr_read = qs_scr_read, |
@@ -169,8 +171,6 @@ static const struct ata_port_info qs_port_info[] = { | |||
169 | /* board_2068_idx */ | 171 | /* board_2068_idx */ |
170 | { | 172 | { |
171 | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | | 173 | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | |
172 | ATA_FLAG_SATA_RESET | | ||
173 | //FIXME ATA_FLAG_SRST | | ||
174 | ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING, | 174 | ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING, |
175 | .pio_mask = 0x10, /* pio4 */ | 175 | .pio_mask = 0x10, /* pio4 */ |
176 | .udma_mask = ATA_UDMA6, | 176 | .udma_mask = ATA_UDMA6, |
@@ -235,16 +235,28 @@ static inline void qs_reset_channel_logic(struct ata_port *ap) | |||
235 | qs_enter_reg_mode(ap); | 235 | qs_enter_reg_mode(ap); |
236 | } | 236 | } |
237 | 237 | ||
238 | static void qs_phy_reset(struct ata_port *ap) | 238 | static void qs_freeze(struct ata_port *ap) |
239 | { | 239 | { |
240 | qs_reset_channel_logic(ap); | 240 | u8 __iomem *mmio_base = qs_mmio_base(ap->host); |
241 | sata_phy_reset(ap); | 241 | |
242 | writeb(0, mmio_base + QS_HCT_CTRL); /* disable host interrupts */ | ||
243 | qs_enter_reg_mode(ap); | ||
244 | } | ||
245 | |||
246 | static void qs_thaw(struct ata_port *ap) | ||
247 | { | ||
248 | u8 __iomem *mmio_base = qs_mmio_base(ap->host); | ||
249 | |||
250 | qs_enter_reg_mode(ap); | ||
251 | writeb(1, mmio_base + QS_HCT_CTRL); /* enable host interrupts */ | ||
242 | } | 252 | } |
243 | 253 | ||
244 | static void qs_eng_timeout(struct ata_port *ap) | 254 | static int qs_prereset(struct ata_link *link, unsigned long deadline) |
245 | { | 255 | { |
256 | struct ata_port *ap = link->ap; | ||
257 | |||
246 | qs_reset_channel_logic(ap); | 258 | qs_reset_channel_logic(ap); |
247 | ata_eng_timeout(ap); | 259 | return ata_std_prereset(link, deadline); |
248 | } | 260 | } |
249 | 261 | ||
250 | static int qs_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val) | 262 | static int qs_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val) |
@@ -255,6 +267,13 @@ static int qs_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val) | |||
255 | return 0; | 267 | return 0; |
256 | } | 268 | } |
257 | 269 | ||
270 | static void qs_error_handler(struct ata_port *ap) | ||
271 | { | ||
272 | qs_enter_reg_mode(ap); | ||
273 | ata_do_eh(ap, qs_prereset, ata_std_softreset, NULL, | ||
274 | ata_std_postreset); | ||
275 | } | ||
276 | |||
258 | static int qs_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val) | 277 | static int qs_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val) |
259 | { | 278 | { |
260 | if (sc_reg > SCR_CONTROL) | 279 | if (sc_reg > SCR_CONTROL) |
@@ -353,7 +372,6 @@ static unsigned int qs_qc_issue(struct ata_queued_cmd *qc) | |||
353 | 372 | ||
354 | switch (qc->tf.protocol) { | 373 | switch (qc->tf.protocol) { |
355 | case ATA_PROT_DMA: | 374 | case ATA_PROT_DMA: |
356 | |||
357 | pp->state = qs_state_pkt; | 375 | pp->state = qs_state_pkt; |
358 | qs_packet_start(qc); | 376 | qs_packet_start(qc); |
359 | return 0; | 377 | return 0; |
@@ -370,6 +388,26 @@ static unsigned int qs_qc_issue(struct ata_queued_cmd *qc) | |||
370 | return ata_qc_issue_prot(qc); | 388 | return ata_qc_issue_prot(qc); |
371 | } | 389 | } |
372 | 390 | ||
391 | static void qs_do_or_die(struct ata_queued_cmd *qc, u8 status) | ||
392 | { | ||
393 | qc->err_mask |= ac_err_mask(status); | ||
394 | |||
395 | if (!qc->err_mask) { | ||
396 | ata_qc_complete(qc); | ||
397 | } else { | ||
398 | struct ata_port *ap = qc->ap; | ||
399 | struct ata_eh_info *ehi = &ap->link.eh_info; | ||
400 | |||
401 | ata_ehi_clear_desc(ehi); | ||
402 | ata_ehi_push_desc(ehi, "status 0x%02X", status); | ||
403 | |||
404 | if (qc->err_mask == AC_ERR_DEV) | ||
405 | ata_port_abort(ap); | ||
406 | else | ||
407 | ata_port_freeze(ap); | ||
408 | } | ||
409 | } | ||
410 | |||
373 | static inline unsigned int qs_intr_pkt(struct ata_host *host) | 411 | static inline unsigned int qs_intr_pkt(struct ata_host *host) |
374 | { | 412 | { |
375 | unsigned int handled = 0; | 413 | unsigned int handled = 0; |
@@ -402,8 +440,7 @@ static inline unsigned int qs_intr_pkt(struct ata_host *host) | |||
402 | case 0: /* successful CPB */ | 440 | case 0: /* successful CPB */ |
403 | case 3: /* device error */ | 441 | case 3: /* device error */ |
404 | qs_enter_reg_mode(qc->ap); | 442 | qs_enter_reg_mode(qc->ap); |
405 | qc->err_mask |= ac_err_mask(sDST); | 443 | qs_do_or_die(qc, sDST); |
406 | ata_qc_complete(qc); | ||
407 | break; | 444 | break; |
408 | default: | 445 | default: |
409 | break; | 446 | break; |