Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 133602
b: refs/heads/master
c: 3d47aa8
h: refs/heads/master
v: v3
  • Loading branch information
Alan Cox authored and Jeff Garzik committed Mar 25, 2009
1 parent 9651ed0 commit ddea408
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 4 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: c0f2ee34a5a0b79fd98d965ad8ae765d4639bfa5
refs/heads/master: 3d47aa8e7e7b2aa09256590388aa8dddc79280f9
45 changes: 43 additions & 2 deletions trunk/drivers/ata/libata-sff.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ const struct ata_port_operations ata_sff_port_ops = {
.softreset = ata_sff_softreset,
.hardreset = sata_sff_hardreset,
.postreset = ata_sff_postreset,
.drain_fifo = ata_sff_drain_fifo,
.error_handler = ata_sff_error_handler,
.post_internal_cmd = ata_sff_post_internal_cmd,

Expand Down Expand Up @@ -2198,6 +2199,39 @@ void ata_sff_postreset(struct ata_link *link, unsigned int *classes)
}
EXPORT_SYMBOL_GPL(ata_sff_postreset);

/**
* ata_sff_drain_fifo - Stock FIFO drain logic for SFF controllers
* @qc: command
*
* Drain the FIFO and device of any stuck data following a command
* failing to complete. In some cases this is neccessary before a
* reset will recover the device.
*
*/

void ata_sff_drain_fifo(struct ata_queued_cmd *qc)
{
int count;
struct ata_port *ap;

/* We only need to flush incoming data when a command was running */
if (qc == NULL || qc->dma_dir == DMA_TO_DEVICE)
return;

ap = qc->ap;
/* Drain up to 64K of data before we give up this recovery method */
for (count = 0; (ap->ops->sff_check_status(ap) & ATA_DRQ)
&& count < 32768; count++)
ioread16(ap->ioaddr.data_addr);

/* Can become DEBUG later */
if (count)
ata_port_printk(ap, KERN_DEBUG,
"drained %d bytes to clear DRQ.\n", count);

}
EXPORT_SYMBOL_GPL(ata_sff_drain_fifo);

/**
* ata_sff_error_handler - Stock error handler for BMDMA controller
* @ap: port to handle error for
Expand Down Expand Up @@ -2239,7 +2273,8 @@ void ata_sff_error_handler(struct ata_port *ap)
* really a timeout event, adjust error mask and
* cancel frozen state.
*/
if (qc->err_mask == AC_ERR_TIMEOUT && (host_stat & ATA_DMA_ERR)) {
if (qc->err_mask == AC_ERR_TIMEOUT
&& (host_stat & ATA_DMA_ERR)) {
qc->err_mask = AC_ERR_HOST_BUS;
thaw = 1;
}
Expand All @@ -2250,6 +2285,13 @@ void ata_sff_error_handler(struct ata_port *ap)
ata_sff_sync(ap); /* FIXME: We don't need this */
ap->ops->sff_check_status(ap);
ap->ops->sff_irq_clear(ap);
/* We *MUST* do FIFO draining before we issue a reset as several
* devices helpfully clear their internal state and will lock solid
* if we touch the data port post reset. Pass qc in case anyone wants
* to do different PIO/DMA recovery or has per command fixups
*/
if (ap->ops->drain_fifo)
ap->ops->drain_fifo(qc);

spin_unlock_irqrestore(ap->lock, flags);

Expand Down Expand Up @@ -2959,4 +3001,3 @@ int ata_pci_sff_init_one(struct pci_dev *pdev,
EXPORT_SYMBOL_GPL(ata_pci_sff_init_one);

#endif /* CONFIG_PCI */

34 changes: 33 additions & 1 deletion trunk/drivers/ata/pata_pcmcia.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@


#define DRV_NAME "pata_pcmcia"
#define DRV_VERSION "0.3.3"
#define DRV_VERSION "0.3.5"

/*
* Private data structure to glue stuff together
Expand Down Expand Up @@ -126,6 +126,37 @@ static unsigned int ata_data_xfer_8bit(struct ata_device *dev,
return buflen;
}

/**
* pcmcia_8bit_drain_fifo - Stock FIFO drain logic for SFF controllers
* @qc: command
*
* Drain the FIFO and device of any stuck data following a command
* failing to complete. In some cases this is neccessary before a
* reset will recover the device.
*
*/

void pcmcia_8bit_drain_fifo(struct ata_queued_cmd *qc)
{
int count;
struct ata_port *ap;

/* We only need to flush incoming data when a command was running */
if (qc == NULL || qc->dma_dir == DMA_TO_DEVICE)
return;

ap = qc->ap;

/* Drain up to 64K of data before we give up this recovery method */
for (count = 0; (ap->ops->sff_check_status(ap) & ATA_DRQ)
&& count++ < 65536;)
ioread8(ap->ioaddr.data_addr);

if (count)
ata_port_printk(ap, KERN_WARNING, "drained %d bytes to clear DRQ.\n",
count);

}

static struct scsi_host_template pcmcia_sht = {
ATA_PIO_SHT(DRV_NAME),
Expand All @@ -143,6 +174,7 @@ static struct ata_port_operations pcmcia_8bit_port_ops = {
.sff_data_xfer = ata_data_xfer_8bit,
.cable_detect = ata_cable_40wire,
.set_mode = pcmcia_set_mode_8bit,
.drain_fifo = pcmcia_8bit_drain_fifo,
};

#define CS_CHECK(fn, ret) \
Expand Down
3 changes: 3 additions & 0 deletions trunk/include/linux/libata.h
Original file line number Diff line number Diff line change
Expand Up @@ -836,6 +836,8 @@ struct ata_port_operations {
void (*bmdma_start)(struct ata_queued_cmd *qc);
void (*bmdma_stop)(struct ata_queued_cmd *qc);
u8 (*bmdma_status)(struct ata_port *ap);

void (*drain_fifo)(struct ata_queued_cmd *qc);
#endif /* CONFIG_ATA_SFF */

ssize_t (*em_show)(struct ata_port *ap, char *buf);
Expand Down Expand Up @@ -1587,6 +1589,7 @@ extern int ata_sff_softreset(struct ata_link *link, unsigned int *classes,
extern int sata_sff_hardreset(struct ata_link *link, unsigned int *class,
unsigned long deadline);
extern void ata_sff_postreset(struct ata_link *link, unsigned int *classes);
extern void ata_sff_drain_fifo(struct ata_queued_cmd *qc);
extern void ata_sff_error_handler(struct ata_port *ap);
extern void ata_sff_post_internal_cmd(struct ata_queued_cmd *qc);
extern int ata_sff_port_start(struct ata_port *ap);
Expand Down

0 comments on commit ddea408

Please sign in to comment.