Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 97605
b: refs/heads/master
c: a57c1ba
h: refs/heads/master
i:
  97603: ccbf048
v: v3
  • Loading branch information
Alan Cox authored and Jeff Garzik committed Jun 4, 2008
1 parent 092dde6 commit b5780ca
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 34 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: 4f0ebe3cc57f18ba26317b56b80b108c2848b1de
refs/heads/master: a57c1bade5a0ee5cd8b74502db9cbebb7f5780b2
115 changes: 100 additions & 15 deletions trunk/drivers/ata/libata-sff.c
Original file line number Diff line number Diff line change
Expand Up @@ -247,14 +247,101 @@ u8 ata_sff_check_status(struct ata_port *ap)
* LOCKING:
* Inherited from caller.
*/
u8 ata_sff_altstatus(struct ata_port *ap)
static u8 ata_sff_altstatus(struct ata_port *ap)
{
if (ap->ops->sff_check_altstatus)
return ap->ops->sff_check_altstatus(ap);

return ioread8(ap->ioaddr.altstatus_addr);
}

/**
* ata_sff_irq_status - Check if the device is busy
* @ap: port where the device is
*
* Determine if the port is currently busy. Uses altstatus
* if available in order to avoid clearing shared IRQ status
* when finding an IRQ source. Non ctl capable devices don't
* share interrupt lines fortunately for us.
*
* LOCKING:
* Inherited from caller.
*/
static u8 ata_sff_irq_status(struct ata_port *ap)
{
u8 status;

if (ap->ops->sff_check_altstatus || ap->ioaddr.altstatus_addr) {
status = ata_sff_altstatus(ap);
/* Not us: We are busy */
if (status & ATA_BUSY)
return status;
}
/* Clear INTRQ latch */
status = ata_sff_check_status(ap);
return status;
}

/**
* ata_sff_sync - Flush writes
* @ap: Port to wait for.
*
* CAUTION:
* If we have an mmio device with no ctl and no altstatus
* method this will fail. No such devices are known to exist.
*
* LOCKING:
* Inherited from caller.
*/

static void ata_sff_sync(struct ata_port *ap)
{
if (ap->ops->sff_check_altstatus)
ap->ops->sff_check_altstatus(ap);
else if (ap->ioaddr.altstatus_addr)
ioread8(ap->ioaddr.altstatus_addr);
}

/**
* ata_sff_pause - Flush writes and wait 400nS
* @ap: Port to pause for.
*
* CAUTION:
* If we have an mmio device with no ctl and no altstatus
* method this will fail. No such devices are known to exist.
*
* LOCKING:
* Inherited from caller.
*/

void ata_sff_pause(struct ata_port *ap)
{
ata_sff_sync(ap);
ndelay(400);
}

/**
* ata_sff_dma_pause - Pause before commencing DMA
* @ap: Port to pause for.
*
* Perform I/O fencing and ensure sufficient cycle delays occur
* for the HDMA1:0 transition
*/

void ata_sff_dma_pause(struct ata_port *ap)
{
if (ap->ops->sff_check_altstatus || ap->ioaddr.altstatus_addr) {
/* An altstatus read will cause the needed delay without
messing up the IRQ status */
ata_sff_altstatus(ap);
return;
}
/* There are no DMA controllers without ctl. BUG here to ensure
we never violate the HDMA1:0 transition timing and risk
corruption. */
BUG();
}

/**
* ata_sff_busy_sleep - sleep until BSY clears, or timeout
* @ap: port containing status register to be polled
Expand Down Expand Up @@ -742,7 +829,7 @@ static void ata_pio_sectors(struct ata_queued_cmd *qc)
} else
ata_pio_sector(qc);

ata_sff_altstatus(qc->ap); /* flush */
ata_sff_sync(qc->ap); /* flush */
}

/**
Expand All @@ -763,8 +850,9 @@ static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc)
WARN_ON(qc->dev->cdb_len < 12);

ap->ops->sff_data_xfer(qc->dev, qc->cdb, qc->dev->cdb_len, 1);
ata_sff_altstatus(ap); /* flush */

ata_sff_sync(ap);
/* FIXME: If the CDB is for DMA do we need to do the transition delay
or is bmdma_start guaranteed to do it ? */
switch (qc->tf.protocol) {
case ATAPI_PROT_PIO:
ap->hsm_task_state = HSM_ST;
Expand Down Expand Up @@ -905,7 +993,7 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc)

if (unlikely(__atapi_pio_bytes(qc, bytes)))
goto err_out;
ata_sff_altstatus(ap); /* flush */
ata_sff_sync(ap); /* flush */

return;

Expand Down Expand Up @@ -1489,14 +1577,10 @@ inline unsigned int ata_sff_host_intr(struct ata_port *ap,
goto idle_irq;
}

/* check altstatus */
status = ata_sff_altstatus(ap);
if (status & ATA_BUSY)
goto idle_irq;

/* check main status, clearing INTRQ */
status = ap->ops->sff_check_status(ap);
if (unlikely(status & ATA_BUSY))
/* check main status, clearing INTRQ if needed */
status = ata_sff_irq_status(ap);
if (status & ATA_BUSY)
goto idle_irq;

/* ack bmdma irq events */
Expand Down Expand Up @@ -2030,7 +2114,7 @@ void ata_sff_error_handler(struct ata_port *ap)
ap->ops->bmdma_stop(qc);
}

ata_sff_altstatus(ap);
ata_sff_sync(ap); /* FIXME: We don't need this */
ap->ops->sff_check_status(ap);
ap->ops->sff_irq_clear(ap);

Expand Down Expand Up @@ -2203,7 +2287,7 @@ void ata_bmdma_stop(struct ata_queued_cmd *qc)
mmio + ATA_DMA_CMD);

/* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
ata_sff_altstatus(ap); /* dummy read */
ata_sff_dma_pause(ap);
}

/**
Expand Down Expand Up @@ -2722,7 +2806,8 @@ EXPORT_SYMBOL_GPL(ata_sff_qc_prep);
EXPORT_SYMBOL_GPL(ata_sff_dumb_qc_prep);
EXPORT_SYMBOL_GPL(ata_sff_dev_select);
EXPORT_SYMBOL_GPL(ata_sff_check_status);
EXPORT_SYMBOL_GPL(ata_sff_altstatus);
EXPORT_SYMBOL_GPL(ata_sff_dma_pause);
EXPORT_SYMBOL_GPL(ata_sff_pause);
EXPORT_SYMBOL_GPL(ata_sff_busy_sleep);
EXPORT_SYMBOL_GPL(ata_sff_wait_ready);
EXPORT_SYMBOL_GPL(ata_sff_tf_load);
Expand Down
2 changes: 1 addition & 1 deletion trunk/drivers/ata/pata_icside.c
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ static void pata_icside_bmdma_stop(struct ata_queued_cmd *qc)
disable_dma(state->dma);

/* see ata_bmdma_stop */
ata_sff_altstatus(ap);
ata_sff_dma_pause(ap);
}

static u8 pata_icside_bmdma_status(struct ata_port *ap)
Expand Down
4 changes: 3 additions & 1 deletion trunk/drivers/ata/pata_rb532_cf.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ static inline void rb532_pata_finish_io(struct ata_port *ap)
struct ata_host *ah = ap->host;
struct rb532_cf_info *info = ah->private_data;

ata_sff_altstatus(ap);
/* FIXME: Keep previous delay. If this is merely a fence then
ata_sff_sync might be sufficient. */
ata_sff_dma_pause(ap);
ndelay(RB500_CF_IO_DELAY);

set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH);
Expand Down
5 changes: 3 additions & 2 deletions trunk/drivers/ata/pata_scc.c
Original file line number Diff line number Diff line change
Expand Up @@ -726,7 +726,7 @@ static void scc_bmdma_stop (struct ata_queued_cmd *qc)
in_be32(bmid_base + SCC_DMA_CMD) & ~ATA_DMA_START);

/* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
ata_sff_altstatus(ap); /* dummy read */
ata_sff_dma_pause(ap); /* dummy read */
}

/**
Expand All @@ -747,7 +747,8 @@ static u8 scc_bmdma_status (struct ata_port *ap)
return host_stat;

/* errata A252,A308 workaround: Step4 */
if ((ata_sff_altstatus(ap) & ATA_ERR) && (int_status & INTSTS_INTRQ))
if ((scc_check_altstatus(ap) & ATA_ERR)
&& (int_status & INTSTS_INTRQ))
return (host_stat | ATA_DMA_INTR);

/* errata A308 workaround Step5 */
Expand Down
16 changes: 2 additions & 14 deletions trunk/include/linux/libata.h
Original file line number Diff line number Diff line change
Expand Up @@ -1432,7 +1432,8 @@ extern void ata_sff_qc_prep(struct ata_queued_cmd *qc);
extern void ata_sff_dumb_qc_prep(struct ata_queued_cmd *qc);
extern void ata_sff_dev_select(struct ata_port *ap, unsigned int device);
extern u8 ata_sff_check_status(struct ata_port *ap);
extern u8 ata_sff_altstatus(struct ata_port *ap);
extern void ata_sff_pause(struct ata_port *ap);
extern void ata_sff_dma_pause(struct ata_port *ap);
extern int ata_sff_busy_sleep(struct ata_port *ap,
unsigned long timeout_pat, unsigned long timeout);
extern int ata_sff_wait_ready(struct ata_link *link, unsigned long deadline);
Expand Down Expand Up @@ -1492,19 +1493,6 @@ extern int ata_pci_sff_init_one(struct pci_dev *pdev,
struct scsi_host_template *sht, void *host_priv);
#endif /* CONFIG_PCI */

/**
* ata_sff_pause - Flush writes and pause 400 nanoseconds.
* @ap: Port to wait for.
*
* LOCKING:
* Inherited from caller.
*/
static inline void ata_sff_pause(struct ata_port *ap)
{
ata_sff_altstatus(ap);
ndelay(400);
}

/**
* ata_sff_busy_wait - Wait for a port status register
* @ap: Port to wait for.
Expand Down

0 comments on commit b5780ca

Please sign in to comment.