aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-sff.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ata/libata-sff.c')
-rw-r--r--drivers/ata/libata-sff.c45
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)
2199EXPORT_SYMBOL_GPL(ata_sff_postreset); 2200EXPORT_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
2212void 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}
2233EXPORT_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:
2959EXPORT_SYMBOL_GPL(ata_pci_sff_init_one); 3001EXPORT_SYMBOL_GPL(ata_pci_sff_init_one);
2960 3002
2961#endif /* CONFIG_PCI */ 3003#endif /* CONFIG_PCI */
2962