Skip to content

Commit 3d47aa8

Browse files
Alan CoxJeff Garzik
authored andcommitted
[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>
1 parent c0f2ee3 commit 3d47aa8

File tree

3 files changed

+79
-3
lines changed

3 files changed

+79
-3
lines changed

drivers/ata/libata-sff.c

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ const struct ata_port_operations ata_sff_port_ops = {
5252
.softreset = ata_sff_softreset,
5353
.hardreset = sata_sff_hardreset,
5454
.postreset = ata_sff_postreset,
55+
.drain_fifo = ata_sff_drain_fifo,
5556
.error_handler = ata_sff_error_handler,
5657
.post_internal_cmd = ata_sff_post_internal_cmd,
5758

@@ -2198,6 +2199,39 @@ void ata_sff_postreset(struct ata_link *link, unsigned int *classes)
21982199
}
21992200
EXPORT_SYMBOL_GPL(ata_sff_postreset);
22002201

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+
22012235
/**
22022236
* ata_sff_error_handler - Stock error handler for BMDMA controller
22032237
* @ap: port to handle error for
@@ -2239,7 +2273,8 @@ void ata_sff_error_handler(struct ata_port *ap)
22392273
* really a timeout event, adjust error mask and
22402274
* cancel frozen state.
22412275
*/
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)) {
22432278
qc->err_mask = AC_ERR_HOST_BUS;
22442279
thaw = 1;
22452280
}
@@ -2250,6 +2285,13 @@ void ata_sff_error_handler(struct ata_port *ap)
22502285
ata_sff_sync(ap); /* FIXME: We don't need this */
22512286
ap->ops->sff_check_status(ap);
22522287
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);
22532295

22542296
spin_unlock_irqrestore(ap->lock, flags);
22552297

@@ -2959,4 +3001,3 @@ int ata_pci_sff_init_one(struct pci_dev *pdev,
29593001
EXPORT_SYMBOL_GPL(ata_pci_sff_init_one);
29603002

29613003
#endif /* CONFIG_PCI */
2962-

drivers/ata/pata_pcmcia.c

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242

4343

4444
#define DRV_NAME "pata_pcmcia"
45-
#define DRV_VERSION "0.3.3"
45+
#define DRV_VERSION "0.3.5"
4646

4747
/*
4848
* Private data structure to glue stuff together
@@ -126,6 +126,37 @@ static unsigned int ata_data_xfer_8bit(struct ata_device *dev,
126126
return buflen;
127127
}
128128

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+
139+
void 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+
}
129160

130161
static struct scsi_host_template pcmcia_sht = {
131162
ATA_PIO_SHT(DRV_NAME),
@@ -143,6 +174,7 @@ static struct ata_port_operations pcmcia_8bit_port_ops = {
143174
.sff_data_xfer = ata_data_xfer_8bit,
144175
.cable_detect = ata_cable_40wire,
145176
.set_mode = pcmcia_set_mode_8bit,
177+
.drain_fifo = pcmcia_8bit_drain_fifo,
146178
};
147179

148180
#define CS_CHECK(fn, ret) \

include/linux/libata.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,8 @@ struct ata_port_operations {
836836
void (*bmdma_start)(struct ata_queued_cmd *qc);
837837
void (*bmdma_stop)(struct ata_queued_cmd *qc);
838838
u8 (*bmdma_status)(struct ata_port *ap);
839+
840+
void (*drain_fifo)(struct ata_queued_cmd *qc);
839841
#endif /* CONFIG_ATA_SFF */
840842

841843
ssize_t (*em_show)(struct ata_port *ap, char *buf);
@@ -1587,6 +1589,7 @@ extern int ata_sff_softreset(struct ata_link *link, unsigned int *classes,
15871589
extern int sata_sff_hardreset(struct ata_link *link, unsigned int *class,
15881590
unsigned long deadline);
15891591
extern void ata_sff_postreset(struct ata_link *link, unsigned int *classes);
1592+
extern void ata_sff_drain_fifo(struct ata_queued_cmd *qc);
15901593
extern void ata_sff_error_handler(struct ata_port *ap);
15911594
extern void ata_sff_post_internal_cmd(struct ata_queued_cmd *qc);
15921595
extern int ata_sff_port_start(struct ata_port *ap);

0 commit comments

Comments
 (0)