Commit 5457f219 authored by zhao, forrest's avatar zhao, forrest Committed by Jeff Garzik

[PATCH] The redefinition of ahci_start_engine() and ahci_stop_engine()

- Make ahci_start_engine() and ahci_stop_engine() more consistent with
  AHCI spec 1.1
- Change their input parameter from ap to port_mmio
- Update the existing users of ahci_start_engine() and ahci_stop_engine()
Signed-off-by: default avatarForrest Zhao <forrest.zhao@intel.com>
Signed-off-by: default avatarHannes Reinecke <hare@suse.de>
Signed-off-by: default avatarJens Axboe <axboe@suse.de>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent 13abf50d
...@@ -205,6 +205,8 @@ static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs * ...@@ -205,6 +205,8 @@ static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *
static void ahci_irq_clear(struct ata_port *ap); static void ahci_irq_clear(struct ata_port *ap);
static int ahci_port_start(struct ata_port *ap); static int ahci_port_start(struct ata_port *ap);
static void ahci_port_stop(struct ata_port *ap); static void ahci_port_stop(struct ata_port *ap);
static int ahci_start_engine(void __iomem *port_mmio);
static int ahci_stop_engine(void __iomem *port_mmio);
static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf); static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
static void ahci_qc_prep(struct ata_queued_cmd *qc); static void ahci_qc_prep(struct ata_queued_cmd *qc);
static u8 ahci_check_status(struct ata_port *ap); static u8 ahci_check_status(struct ata_port *ap);
...@@ -508,41 +510,64 @@ static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg_in, ...@@ -508,41 +510,64 @@ static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg_in,
writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4)); writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
} }
static int ahci_stop_engine(struct ata_port *ap) static int ahci_stop_engine(void __iomem *port_mmio)
{ {
void __iomem *mmio = ap->host_set->mmio_base;
void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
int work;
u32 tmp; u32 tmp;
tmp = readl(port_mmio + PORT_CMD); tmp = readl(port_mmio + PORT_CMD);
/* Check if the HBA is idle */
if ((tmp & (PORT_CMD_START | PORT_CMD_LIST_ON)) == 0)
return 0;
/* Setting HBA to idle */
tmp &= ~PORT_CMD_START; tmp &= ~PORT_CMD_START;
writel(tmp, port_mmio + PORT_CMD); writel(tmp, port_mmio + PORT_CMD);
/* wait for engine to stop. TODO: this could be /* wait for engine to stop. This could be
* as long as 500 msec * as long as 500 msec
*/ */
work = 1000; tmp = ata_wait_register(port_mmio + PORT_CMD,
while (work-- > 0) { PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500);
tmp = readl(port_mmio + PORT_CMD); if(tmp & PORT_CMD_LIST_ON)
if ((tmp & PORT_CMD_LIST_ON) == 0) return -EIO;
return 0;
udelay(10);
}
return -EIO; return 0;
} }
static void ahci_start_engine(struct ata_port *ap) static int ahci_start_engine(void __iomem *port_mmio)
{ {
void __iomem *mmio = ap->host_set->mmio_base;
void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
u32 tmp; u32 tmp;
/*
* Get current status
*/
tmp = readl(port_mmio + PORT_CMD); tmp = readl(port_mmio + PORT_CMD);
/*
* AHCI rev 1.1 section 10.3.1:
* Software shall not set PxCMD.ST to '1' until it verifies
* that PxCMD.CR is '0' and has set PxCMD.FRE to '1'
*/
if ((tmp & PORT_CMD_FIS_RX) == 0)
return -EPERM;
/*
* wait for engine to become idle.
*/
tmp = ata_wait_register(port_mmio + PORT_CMD,
PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1,500);
if(tmp & PORT_CMD_LIST_ON)
return -EBUSY;
/*
* Start DMA
*/
tmp |= PORT_CMD_START; tmp |= PORT_CMD_START;
writel(tmp, port_mmio + PORT_CMD); writel(tmp, port_mmio + PORT_CMD);
readl(port_mmio + PORT_CMD); /* flush */ readl(port_mmio + PORT_CMD); /* flush */
return 0;
} }
static unsigned int ahci_dev_classify(struct ata_port *ap) static unsigned int ahci_dev_classify(struct ata_port *ap)
...@@ -626,7 +651,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class) ...@@ -626,7 +651,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class)
} }
/* prepare for SRST (AHCI-1.1 10.4.1) */ /* prepare for SRST (AHCI-1.1 10.4.1) */
rc = ahci_stop_engine(ap); rc = ahci_stop_engine(port_mmio);
if (rc) { if (rc) {
reason = "failed to stop engine"; reason = "failed to stop engine";
goto fail_restart; goto fail_restart;
...@@ -647,7 +672,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class) ...@@ -647,7 +672,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class)
} }
/* restart engine */ /* restart engine */
ahci_start_engine(ap); ahci_start_engine(port_mmio);
ata_tf_init(ap->device, &tf); ata_tf_init(ap->device, &tf);
fis = pp->cmd_tbl; fis = pp->cmd_tbl;
...@@ -706,7 +731,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class) ...@@ -706,7 +731,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class)
return 0; return 0;
fail_restart: fail_restart:
ahci_start_engine(ap); ahci_start_engine(port_mmio);
fail: fail:
ata_port_printk(ap, KERN_ERR, "softreset failed (%s)\n", reason); ata_port_printk(ap, KERN_ERR, "softreset failed (%s)\n", reason);
return rc; return rc;
...@@ -717,11 +742,13 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class) ...@@ -717,11 +742,13 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class)
struct ahci_port_priv *pp = ap->private_data; struct ahci_port_priv *pp = ap->private_data;
u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
struct ata_taskfile tf; struct ata_taskfile tf;
void __iomem *mmio = ap->host_set->mmio_base;
void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
int rc; int rc;
DPRINTK("ENTER\n"); DPRINTK("ENTER\n");
ahci_stop_engine(ap); ahci_stop_engine(port_mmio);
/* clear D2H reception area to properly wait for D2H FIS */ /* clear D2H reception area to properly wait for D2H FIS */
ata_tf_init(ap->device, &tf); ata_tf_init(ap->device, &tf);
...@@ -730,7 +757,7 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class) ...@@ -730,7 +757,7 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class)
rc = sata_std_hardreset(ap, class); rc = sata_std_hardreset(ap, class);
ahci_start_engine(ap); ahci_start_engine(port_mmio);
if (rc == 0 && ata_port_online(ap)) if (rc == 0 && ata_port_online(ap))
*class = ahci_dev_classify(ap); *class = ahci_dev_classify(ap);
...@@ -1052,10 +1079,13 @@ static void ahci_thaw(struct ata_port *ap) ...@@ -1052,10 +1079,13 @@ static void ahci_thaw(struct ata_port *ap)
static void ahci_error_handler(struct ata_port *ap) static void ahci_error_handler(struct ata_port *ap)
{ {
void __iomem *mmio = ap->host_set->mmio_base;
void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
if (!(ap->pflags & ATA_PFLAG_FROZEN)) { if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
/* restart engine */ /* restart engine */
ahci_stop_engine(ap); ahci_stop_engine(port_mmio);
ahci_start_engine(ap); ahci_start_engine(port_mmio);
} }
/* perform recovery */ /* perform recovery */
...@@ -1066,14 +1096,16 @@ static void ahci_error_handler(struct ata_port *ap) ...@@ -1066,14 +1096,16 @@ static void ahci_error_handler(struct ata_port *ap)
static void ahci_post_internal_cmd(struct ata_queued_cmd *qc) static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
{ {
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
void __iomem *mmio = ap->host_set->mmio_base;
void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
if (qc->flags & ATA_QCFLAG_FAILED) if (qc->flags & ATA_QCFLAG_FAILED)
qc->err_mask |= AC_ERR_OTHER; qc->err_mask |= AC_ERR_OTHER;
if (qc->err_mask) { if (qc->err_mask) {
/* make DMA engine forget about the failed command */ /* make DMA engine forget about the failed command */
ahci_stop_engine(ap); ahci_stop_engine(port_mmio);
ahci_start_engine(ap); ahci_start_engine(port_mmio);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment