aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorAlan Cox <alan@redhat.com>2009-03-24 06:23:19 -0400
committerJeff Garzik <jgarzik@redhat.com>2009-03-24 22:48:26 -0400
commit3d47aa8e7e7b2aa09256590388aa8dddc79280f9 (patch)
tree82f4c85842e5e02489eb0533609dabb865e55198 /drivers/ata
parentc0f2ee34a5a0b79fd98d965ad8ae765d4639bfa5 (diff)
[libata] Drain data on errors
If the device is signalling that there is data to drain after an error we should read the bytes out and throw them away. Without this some devices and controllers get wedged and don't recover. Based on earlier work by Mark Lord Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/libata-sff.c45
-rw-r--r--drivers/ata/pata_pcmcia.c34
2 files changed, 76 insertions, 3 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
diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c
index a5cbcc280b23..f4d009ed50ac 100644
--- a/drivers/ata/pata_pcmcia.c
+++ b/drivers/ata/pata_pcmcia.c
@@ -42,7 +42,7 @@
42 42
43 43
44#define DRV_NAME "pata_pcmcia" 44#define DRV_NAME "pata_pcmcia"
45#define DRV_VERSION "0.3.3" 45#define DRV_VERSION "0.3.5"
46 46
47/* 47/*
48 * Private data structure to glue stuff together 48 * Private data structure to glue stuff together
@@ -126,6 +126,37 @@ static unsigned int ata_data_xfer_8bit(struct ata_device *dev,
126 return buflen; 126 return buflen;
127} 127}
128 128
129/**
130 * pcmcia_8bit_drain_fifo - Stock FIFO drain logic for SFF controllers
131 * @qc: command
132 *
133 * Drain the FIFO and device of any stuck data following a command
134 * failing to complete. In some cases this is neccessary before a
135 * reset will recover the device.
136 *
137 */
138
139void pcmcia_8bit_drain_fifo(struct ata_queued_cmd *qc)
140{
141 int count;
142 struct ata_port *ap;
143
144 /* We only need to flush incoming data when a command was running */
145 if (qc == NULL || qc->dma_dir == DMA_TO_DEVICE)
146 return;
147
148 ap = qc->ap;
149
150 /* Drain up to 64K of data before we give up this recovery method */
151 for (count = 0; (ap->ops->sff_check_status(ap) & ATA_DRQ)
152 && count++ < 65536;)
153 ioread8(ap->ioaddr.data_addr);
154
155 if (count)
156 ata_port_printk(ap, KERN_WARNING, "drained %d bytes to clear DRQ.\n",
157 count);
158
159}
129 160
130static struct scsi_host_template pcmcia_sht = { 161static struct scsi_host_template pcmcia_sht = {
131 ATA_PIO_SHT(DRV_NAME), 162 ATA_PIO_SHT(DRV_NAME),
@@ -143,6 +174,7 @@ static struct ata_port_operations pcmcia_8bit_port_ops = {
143 .sff_data_xfer = ata_data_xfer_8bit, 174 .sff_data_xfer = ata_data_xfer_8bit,
144 .cable_detect = ata_cable_40wire, 175 .cable_detect = ata_cable_40wire,
145 .set_mode = pcmcia_set_mode_8bit, 176 .set_mode = pcmcia_set_mode_8bit,
177 .drain_fifo = pcmcia_8bit_drain_fifo,
146}; 178};
147 179
148#define CS_CHECK(fn, ret) \ 180#define CS_CHECK(fn, ret) \