diff options
Diffstat (limited to 'drivers/ata/libata-sff.c')
-rw-r--r-- | drivers/ata/libata-sff.c | 45 |
1 files changed, 43 insertions, 2 deletions
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index f93dc029dfde..9a10cb055ac2 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c | |||
@@ -52,6 +52,7 @@ const struct ata_port_operations ata_sff_port_ops = { | |||
52 | .softreset = ata_sff_softreset, | 52 | .softreset = ata_sff_softreset, |
53 | .hardreset = sata_sff_hardreset, | 53 | .hardreset = sata_sff_hardreset, |
54 | .postreset = ata_sff_postreset, | 54 | .postreset = ata_sff_postreset, |
55 | .drain_fifo = ata_sff_drain_fifo, | ||
55 | .error_handler = ata_sff_error_handler, | 56 | .error_handler = ata_sff_error_handler, |
56 | .post_internal_cmd = ata_sff_post_internal_cmd, | 57 | .post_internal_cmd = ata_sff_post_internal_cmd, |
57 | 58 | ||
@@ -2199,6 +2200,39 @@ void ata_sff_postreset(struct ata_link *link, unsigned int *classes) | |||
2199 | EXPORT_SYMBOL_GPL(ata_sff_postreset); | 2200 | EXPORT_SYMBOL_GPL(ata_sff_postreset); |
2200 | 2201 | ||
2201 | /** | 2202 | /** |
2203 | * ata_sff_drain_fifo - Stock FIFO drain logic for SFF controllers | ||
2204 | * @qc: command | ||
2205 | * | ||
2206 | * Drain the FIFO and device of any stuck data following a command | ||
2207 | * failing to complete. In some cases this is neccessary before a | ||
2208 | * reset will recover the device. | ||
2209 | * | ||
2210 | */ | ||
2211 | |||
2212 | void ata_sff_drain_fifo(struct ata_queued_cmd *qc) | ||
2213 | { | ||
2214 | int count; | ||
2215 | struct ata_port *ap; | ||
2216 | |||
2217 | /* We only need to flush incoming data when a command was running */ | ||
2218 | if (qc == NULL || qc->dma_dir == DMA_TO_DEVICE) | ||
2219 | return; | ||
2220 | |||
2221 | ap = qc->ap; | ||
2222 | /* Drain up to 64K of data before we give up this recovery method */ | ||
2223 | for (count = 0; (ap->ops->sff_check_status(ap) & ATA_DRQ) | ||
2224 | && count < 32768; count++) | ||
2225 | ioread16(ap->ioaddr.data_addr); | ||
2226 | |||
2227 | /* Can become DEBUG later */ | ||
2228 | if (count) | ||
2229 | ata_port_printk(ap, KERN_DEBUG, | ||
2230 | "drained %d bytes to clear DRQ.\n", count); | ||
2231 | |||
2232 | } | ||
2233 | EXPORT_SYMBOL_GPL(ata_sff_drain_fifo); | ||
2234 | |||
2235 | /** | ||
2202 | * ata_sff_error_handler - Stock error handler for BMDMA controller | 2236 | * ata_sff_error_handler - Stock error handler for BMDMA controller |
2203 | * @ap: port to handle error for | 2237 | * @ap: port to handle error for |
2204 | * | 2238 | * |
@@ -2239,7 +2273,8 @@ void ata_sff_error_handler(struct ata_port *ap) | |||
2239 | * really a timeout event, adjust error mask and | 2273 | * really a timeout event, adjust error mask and |
2240 | * cancel frozen state. | 2274 | * cancel frozen state. |
2241 | */ | 2275 | */ |
2242 | if (qc->err_mask == AC_ERR_TIMEOUT && (host_stat & ATA_DMA_ERR)) { | 2276 | if (qc->err_mask == AC_ERR_TIMEOUT |
2277 | && (host_stat & ATA_DMA_ERR)) { | ||
2243 | qc->err_mask = AC_ERR_HOST_BUS; | 2278 | qc->err_mask = AC_ERR_HOST_BUS; |
2244 | thaw = 1; | 2279 | thaw = 1; |
2245 | } | 2280 | } |
@@ -2250,6 +2285,13 @@ void ata_sff_error_handler(struct ata_port *ap) | |||
2250 | ata_sff_sync(ap); /* FIXME: We don't need this */ | 2285 | ata_sff_sync(ap); /* FIXME: We don't need this */ |
2251 | ap->ops->sff_check_status(ap); | 2286 | ap->ops->sff_check_status(ap); |
2252 | ap->ops->sff_irq_clear(ap); | 2287 | ap->ops->sff_irq_clear(ap); |
2288 | /* We *MUST* do FIFO draining before we issue a reset as several | ||
2289 | * devices helpfully clear their internal state and will lock solid | ||
2290 | * if we touch the data port post reset. Pass qc in case anyone wants | ||
2291 | * to do different PIO/DMA recovery or has per command fixups | ||
2292 | */ | ||
2293 | if (ap->ops->drain_fifo) | ||
2294 | ap->ops->drain_fifo(qc); | ||
2253 | 2295 | ||
2254 | spin_unlock_irqrestore(ap->lock, flags); | 2296 | spin_unlock_irqrestore(ap->lock, flags); |
2255 | 2297 | ||
@@ -2959,4 +3001,3 @@ out: | |||
2959 | EXPORT_SYMBOL_GPL(ata_pci_sff_init_one); | 3001 | EXPORT_SYMBOL_GPL(ata_pci_sff_init_one); |
2960 | 3002 | ||
2961 | #endif /* CONFIG_PCI */ | 3003 | #endif /* CONFIG_PCI */ |
2962 | |||