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.c91
1 files changed, 88 insertions, 3 deletions
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index f93dc029dfde..8332e97a9de3 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
@@ -64,6 +65,8 @@ const struct ata_port_operations ata_sff_port_ops = {
64 .sff_irq_on = ata_sff_irq_on, 65 .sff_irq_on = ata_sff_irq_on,
65 .sff_irq_clear = ata_sff_irq_clear, 66 .sff_irq_clear = ata_sff_irq_clear,
66 67
68 .lost_interrupt = ata_sff_lost_interrupt,
69
67 .port_start = ata_sff_port_start, 70 .port_start = ata_sff_port_start,
68}; 71};
69EXPORT_SYMBOL_GPL(ata_sff_port_ops); 72EXPORT_SYMBOL_GPL(ata_sff_port_ops);
@@ -1646,7 +1649,7 @@ EXPORT_SYMBOL_GPL(ata_sff_qc_fill_rtf);
1646 * RETURNS: 1649 * RETURNS:
1647 * One if interrupt was handled, zero if not (shared irq). 1650 * One if interrupt was handled, zero if not (shared irq).
1648 */ 1651 */
1649inline unsigned int ata_sff_host_intr(struct ata_port *ap, 1652unsigned int ata_sff_host_intr(struct ata_port *ap,
1650 struct ata_queued_cmd *qc) 1653 struct ata_queued_cmd *qc)
1651{ 1654{
1652 struct ata_eh_info *ehi = &ap->link.eh_info; 1655 struct ata_eh_info *ehi = &ap->link.eh_info;
@@ -1775,6 +1778,48 @@ irqreturn_t ata_sff_interrupt(int irq, void *dev_instance)
1775EXPORT_SYMBOL_GPL(ata_sff_interrupt); 1778EXPORT_SYMBOL_GPL(ata_sff_interrupt);
1776 1779
1777/** 1780/**
1781 * ata_sff_lost_interrupt - Check for an apparent lost interrupt
1782 * @ap: port that appears to have timed out
1783 *
1784 * Called from the libata error handlers when the core code suspects
1785 * an interrupt has been lost. If it has complete anything we can and
1786 * then return. Interface must support altstatus for this faster
1787 * recovery to occur.
1788 *
1789 * Locking:
1790 * Caller holds host lock
1791 */
1792
1793void ata_sff_lost_interrupt(struct ata_port *ap)
1794{
1795 u8 status;
1796 struct ata_queued_cmd *qc;
1797
1798 /* Only one outstanding command per SFF channel */
1799 qc = ata_qc_from_tag(ap, ap->link.active_tag);
1800 /* Check we have a live one.. */
1801 if (qc == NULL || !(qc->flags & ATA_QCFLAG_ACTIVE))
1802 return;
1803 /* We cannot lose an interrupt on a polled command */
1804 if (qc->tf.flags & ATA_TFLAG_POLLING)
1805 return;
1806 /* See if the controller thinks it is still busy - if so the command
1807 isn't a lost IRQ but is still in progress */
1808 status = ata_sff_altstatus(ap);
1809 if (status & ATA_BUSY)
1810 return;
1811
1812 /* There was a command running, we are no longer busy and we have
1813 no interrupt. */
1814 ata_port_printk(ap, KERN_WARNING, "lost interrupt (Status 0x%x)\n",
1815 status);
1816 /* Run the host interrupt logic as if the interrupt had not been
1817 lost */
1818 ata_sff_host_intr(ap, qc);
1819}
1820EXPORT_SYMBOL_GPL(ata_sff_lost_interrupt);
1821
1822/**
1778 * ata_sff_freeze - Freeze SFF controller port 1823 * ata_sff_freeze - Freeze SFF controller port
1779 * @ap: port to freeze 1824 * @ap: port to freeze
1780 * 1825 *
@@ -2199,6 +2244,39 @@ void ata_sff_postreset(struct ata_link *link, unsigned int *classes)
2199EXPORT_SYMBOL_GPL(ata_sff_postreset); 2244EXPORT_SYMBOL_GPL(ata_sff_postreset);
2200 2245
2201/** 2246/**
2247 * ata_sff_drain_fifo - Stock FIFO drain logic for SFF controllers
2248 * @qc: command
2249 *
2250 * Drain the FIFO and device of any stuck data following a command
2251 * failing to complete. In some cases this is neccessary before a
2252 * reset will recover the device.
2253 *
2254 */
2255
2256void ata_sff_drain_fifo(struct ata_queued_cmd *qc)
2257{
2258 int count;
2259 struct ata_port *ap;
2260
2261 /* We only need to flush incoming data when a command was running */
2262 if (qc == NULL || qc->dma_dir == DMA_TO_DEVICE)
2263 return;
2264
2265 ap = qc->ap;
2266 /* Drain up to 64K of data before we give up this recovery method */
2267 for (count = 0; (ap->ops->sff_check_status(ap) & ATA_DRQ)
2268 && count < 32768; count++)
2269 ioread16(ap->ioaddr.data_addr);
2270
2271 /* Can become DEBUG later */
2272 if (count)
2273 ata_port_printk(ap, KERN_DEBUG,
2274 "drained %d bytes to clear DRQ.\n", count);
2275
2276}
2277EXPORT_SYMBOL_GPL(ata_sff_drain_fifo);
2278
2279/**
2202 * ata_sff_error_handler - Stock error handler for BMDMA controller 2280 * ata_sff_error_handler - Stock error handler for BMDMA controller
2203 * @ap: port to handle error for 2281 * @ap: port to handle error for
2204 * 2282 *
@@ -2239,7 +2317,8 @@ void ata_sff_error_handler(struct ata_port *ap)
2239 * really a timeout event, adjust error mask and 2317 * really a timeout event, adjust error mask and
2240 * cancel frozen state. 2318 * cancel frozen state.
2241 */ 2319 */
2242 if (qc->err_mask == AC_ERR_TIMEOUT && (host_stat & ATA_DMA_ERR)) { 2320 if (qc->err_mask == AC_ERR_TIMEOUT
2321 && (host_stat & ATA_DMA_ERR)) {
2243 qc->err_mask = AC_ERR_HOST_BUS; 2322 qc->err_mask = AC_ERR_HOST_BUS;
2244 thaw = 1; 2323 thaw = 1;
2245 } 2324 }
@@ -2250,6 +2329,13 @@ void ata_sff_error_handler(struct ata_port *ap)
2250 ata_sff_sync(ap); /* FIXME: We don't need this */ 2329 ata_sff_sync(ap); /* FIXME: We don't need this */
2251 ap->ops->sff_check_status(ap); 2330 ap->ops->sff_check_status(ap);
2252 ap->ops->sff_irq_clear(ap); 2331 ap->ops->sff_irq_clear(ap);
2332 /* We *MUST* do FIFO draining before we issue a reset as several
2333 * devices helpfully clear their internal state and will lock solid
2334 * if we touch the data port post reset. Pass qc in case anyone wants
2335 * to do different PIO/DMA recovery or has per command fixups
2336 */
2337 if (ap->ops->drain_fifo)
2338 ap->ops->drain_fifo(qc);
2253 2339
2254 spin_unlock_irqrestore(ap->lock, flags); 2340 spin_unlock_irqrestore(ap->lock, flags);
2255 2341
@@ -2959,4 +3045,3 @@ out:
2959EXPORT_SYMBOL_GPL(ata_pci_sff_init_one); 3045EXPORT_SYMBOL_GPL(ata_pci_sff_init_one);
2960 3046
2961#endif /* CONFIG_PCI */ 3047#endif /* CONFIG_PCI */
2962