X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fscsi%2Fahci.c;h=559ff7aae3f113e4f61e551050c289b73f7fa6d6;hb=987b0145d94eecf292d8b301228356f44611ab7c;hp=7f54d5da6d191505539579769001c7d032054110;hpb=f7ed79d23a47594e7834d66a8f14449796d4f3e6;p=linux-2.6.git diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 7f54d5da6..559ff7aae 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -44,7 +44,6 @@ #include #include #include -#include #include #include @@ -67,9 +66,6 @@ enum { AHCI_IRQ_ON_SG = (1 << 31), AHCI_CMD_ATAPI = (1 << 5), AHCI_CMD_WRITE = (1 << 6), - AHCI_CMD_PREFETCH = (1 << 7), - AHCI_CMD_RESET = (1 << 8), - AHCI_CMD_CLR_BUSY = (1 << 10), RX_FIS_D2H_REG = 0x40, /* offset of D2H Register FIS data */ @@ -89,9 +85,6 @@ enum { /* HOST_CAP bits */ HOST_CAP_64 = (1 << 31), /* PCI DAC (64-bit DMA) support */ - HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */ - HOST_CAP_CLO = (1 << 24), /* Command List Override support */ - HOST_CAP_SSC = (1 << 14), /* Slumber capable */ /* registers for each SATA port */ PORT_LST_ADDR = 0x00, /* command list DMA addr */ @@ -142,16 +135,13 @@ enum { /* PORT_CMD bits */ PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */ - PORT_CMD_CPD = (1 << 20), /* Cold presence detection */ PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */ PORT_CMD_FIS_ON = (1 << 14), /* FIS DMA engine running */ PORT_CMD_FIS_RX = (1 << 4), /* Enable FIS receive DMA engine */ - PORT_CMD_CLO = (1 << 3), /* Command list override */ PORT_CMD_POWER_ON = (1 << 2), /* Power up device */ PORT_CMD_SPIN_UP = (1 << 1), /* Spin up device */ PORT_CMD_START = (1 << 0), /* Enable port DMA engine */ - PORT_CMD_ICC_MASK = (0xf << 28), /* i/f ICC state mask */ PORT_CMD_ICC_ACTIVE = (0x1 << 28), /* Put i/f in active state */ PORT_CMD_ICC_PARTIAL = (0x2 << 28), /* Put i/f in partial state */ PORT_CMD_ICC_SLUMBER = (0x6 << 28), /* Put i/f in slumber state */ @@ -179,7 +169,6 @@ struct ahci_host_priv { unsigned long flags; u32 cap; /* cache of HOST_CAP register */ u32 port_map; /* cache of HOST_PORTS_IMPL reg */ - u32 dev_map; /* connected devices */ }; struct ahci_port_priv { @@ -195,32 +184,17 @@ struct ahci_port_priv { static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg); static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); -static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc); +static int ahci_qc_issue(struct ata_queued_cmd *qc); static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *regs); -static int ahci_start_engine(void __iomem *port_mmio); -static int ahci_stop_engine(void __iomem *port_mmio); -static int ahci_stop_fis_rx(void __iomem *port_mmio); -static void ahci_start_fis_rx(void __iomem *port_mmio, - struct ahci_port_priv *pp, - struct ahci_host_priv *hpriv); -static int ahci_probe_reset(struct ata_port *ap, unsigned int *classes); +static void ahci_phy_reset(struct ata_port *ap); static void ahci_irq_clear(struct ata_port *ap); static void ahci_eng_timeout(struct ata_port *ap); static int ahci_port_start(struct ata_port *ap); static void ahci_port_stop(struct ata_port *ap); -static int ahci_port_suspend(struct ata_port *ap, pm_message_t state); -static int ahci_port_resume(struct ata_port *ap); -static int ahci_port_standby(void __iomem *port_mmio, u32 cap); -static int ahci_port_spinup(void __iomem *port_mmio, u32 cap); -static void ahci_port_disable(struct ata_port *ap); static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf); static void ahci_qc_prep(struct ata_queued_cmd *qc); static u8 ahci_check_status(struct ata_port *ap); static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); -static int ahci_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state); -static int ahci_scsi_device_resume(struct scsi_device *sdev); -static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t state); -static int ahci_pci_device_resume(struct pci_dev *pdev); static void ahci_remove_one (struct pci_dev *pdev); static struct scsi_host_template ahci_sht = { @@ -228,9 +202,11 @@ static struct scsi_host_template ahci_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, + .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = AHCI_MAX_SG, + .max_sectors = ATA_MAX_SECTORS, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, .emulated = ATA_SHT_EMULATED, .use_clustering = AHCI_USE_CLUSTERING, @@ -238,12 +214,10 @@ static struct scsi_host_template ahci_sht = { .dma_boundary = AHCI_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .bios_param = ata_std_bios_param, - .resume = ahci_scsi_device_resume, - .suspend = ahci_scsi_device_suspend, }; static const struct ata_port_operations ahci_ops = { - .port_disable = ahci_port_disable, + .port_disable = ata_port_disable, .check_status = ahci_check_status, .check_altstatus = ahci_check_status, @@ -251,7 +225,7 @@ static const struct ata_port_operations ahci_ops = { .tf_read = ahci_tf_read, - .probe_reset = ahci_probe_reset, + .phy_reset = ahci_phy_reset, .qc_prep = ahci_qc_prep, .qc_issue = ahci_qc_issue, @@ -273,7 +247,8 @@ static const struct ata_port_info ahci_port_info[] = { { .sht = &ahci_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA, + ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO | + ATA_FLAG_PIO_DMA, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &ahci_ops, @@ -315,10 +290,6 @@ static const struct pci_device_id ahci_pci_tbl[] = { board_ahci }, /* JMicron JMB360 */ { 0x197b, 0x2363, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_ahci }, /* JMicron JMB363 */ - { PCI_VENDOR_ID_ATI, 0x4380, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - board_ahci }, /* ATI SB600 non-raid */ - { PCI_VENDOR_ID_ATI, 0x4381, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - board_ahci }, /* ATI SB600 raid */ { } /* terminate list */ }; @@ -328,8 +299,6 @@ static struct pci_driver ahci_pci_driver = { .id_table = ahci_pci_tbl, .probe = ahci_init_one, .remove = ahci_remove_one, - .suspend = ahci_pci_device_suspend, - .resume = ahci_pci_device_resume, }; @@ -403,23 +372,21 @@ static int ahci_port_start(struct ata_port *ap) ap->private_data = pp; - /* - * Driver is setup; initialize the HBA - */ - ahci_start_fis_rx(port_mmio, pp, hpriv); - rc = ahci_port_spinup(port_mmio, hpriv->cap); - if (rc) - printk(KERN_WARNING "ata%d: could not spinup device (%d)\n", - ap->id, rc); - - /* - * Do not enable DMA here; according to the spec - * (section 10.1.1) we should first enable FIS reception, - * then check if the port is enabled before we try to - * switch on DMA. - * And as the port check is done during probe - * we really shouldn't be doing it here. - */ + if (hpriv->cap & HOST_CAP_64) + writel((pp->cmd_slot_dma >> 16) >> 16, port_mmio + PORT_LST_ADDR_HI); + writel(pp->cmd_slot_dma & 0xffffffff, port_mmio + PORT_LST_ADDR); + readl(port_mmio + PORT_LST_ADDR); /* flush */ + + if (hpriv->cap & HOST_CAP_64) + writel((pp->rx_fis_dma >> 16) >> 16, port_mmio + PORT_FIS_ADDR_HI); + writel(pp->rx_fis_dma & 0xffffffff, port_mmio + PORT_FIS_ADDR); + readl(port_mmio + PORT_FIS_ADDR); /* flush */ + + writel(PORT_CMD_ICC_ACTIVE | PORT_CMD_FIS_RX | + PORT_CMD_POWER_ON | PORT_CMD_SPIN_UP | + PORT_CMD_START, port_mmio + PORT_CMD); + readl(port_mmio + PORT_CMD); /* flush */ + return 0; } @@ -428,114 +395,25 @@ static void ahci_port_stop(struct ata_port *ap) { struct device *dev = ap->host_set->dev; struct ahci_port_priv *pp = ap->private_data; - - ahci_port_suspend(ap, PMSG_SUSPEND); - - ap->private_data = NULL; - dma_free_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, - pp->cmd_slot, pp->cmd_slot_dma); - ata_pad_free(ap, dev); - kfree(pp); -} - -static int ahci_port_suspend(struct ata_port *ap, pm_message_t state) -{ void __iomem *mmio = ap->host_set->mmio_base; void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); - struct ahci_host_priv *hpriv = ap->host_set->private_data; - int rc; - - /* - * Disable DMA - */ - rc = ahci_stop_engine(port_mmio); - if (rc) { - printk(KERN_WARNING "ata%u: DMA engine busy\n", ap->id); - return rc; - } - - /* - * Disable FIS reception - */ - rc = ahci_stop_fis_rx(port_mmio); - if (rc) - printk(KERN_WARNING "ata%d: FIS RX still running (rc %d)\n", - ap->id, rc); - - /* - * Put device into slumber mode - */ - if (!rc && state.event != PM_EVENT_FREEZE) - ahci_port_standby(port_mmio, hpriv->cap); - - return rc; -} - -static int ahci_port_resume(struct ata_port *ap) -{ - void __iomem *mmio = ap->host_set->mmio_base; - void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); - struct ahci_host_priv *hpriv = ap->host_set->private_data; - struct ahci_port_priv *pp = ap->private_data; - int rc; u32 tmp; - /* - * Enable FIS reception - */ - ahci_start_fis_rx(port_mmio, pp, hpriv); - - rc = ahci_port_spinup(port_mmio, hpriv->cap); - if (rc) - printk(KERN_WARNING "ata%d: could not spinup device (%d)\n", - ap->id, rc); - - /* - * Clear error status - */ - tmp = readl(port_mmio + PORT_SCR_ERR); - writel(tmp, port_mmio + PORT_SCR_ERR); - /* - * Clear interrupt status - */ - tmp = readl(mmio + HOST_CTL); - if (!(tmp & HOST_IRQ_EN)) { - u32 irq_stat; - - /* ack any pending irq events for this port */ - irq_stat = readl(port_mmio + PORT_IRQ_STAT); - if (irq_stat) - writel(irq_stat, port_mmio + PORT_IRQ_STAT); - - /* set irq mask (enables interrupts) */ - writel(DEF_PORT_IRQ, port_mmio + PORT_IRQ_MASK); - - if ((hpriv->dev_map >> (ap->port_no + 1)) == 0) { - /* - * Enable interrupts if this was the last port - */ - printk(KERN_WARNING "ata%d: enabling interrupts\n", - ap->id); - - irq_stat = readl(mmio + HOST_IRQ_STAT); - if (irq_stat) - writel(irq_stat, mmio + HOST_IRQ_STAT); - - tmp |= HOST_IRQ_EN; - writel(tmp, mmio + HOST_CTL); - (void) readl(mmio + HOST_CTL); - } - } + tmp = readl(port_mmio + PORT_CMD); + tmp &= ~(PORT_CMD_START | PORT_CMD_FIS_RX); + writel(tmp, port_mmio + PORT_CMD); + readl(port_mmio + PORT_CMD); /* flush */ - /* - * Enable DMA + /* spec says 500 msecs for each PORT_CMD_{START,FIS_RX} bit, so + * this is slightly incorrect. */ - rc = ahci_start_engine(port_mmio); - if (rc) - printk(KERN_WARNING "ata%d: cannot start DMA engine (rc %d)\n", - ap->id, rc); + msleep(500); - return rc; + ap->private_data = NULL; + dma_free_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, + pp->cmd_slot, pp->cmd_slot_dma); + ata_pad_free(ap, dev); + kfree(pp); } static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg_in) @@ -572,268 +450,17 @@ 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)); } -static int ahci_stop_engine(void __iomem *port_mmio) -{ - int work; - u32 tmp; - - 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; - writel(tmp, port_mmio + PORT_CMD); - - /* - * wait for engine to become idle - */ - work = 1000; - while (work-- > 0) { - tmp = readl(port_mmio + PORT_CMD); - if ((tmp & PORT_CMD_LIST_ON) == 0) - return 0; - udelay(10); - } - - return -EIO; -} - -static int ahci_start_engine(void __iomem *port_mmio) -{ - u32 tmp; - int work = 1000; - - /* - * Get current status - */ - 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. - */ - while (work-- > 0) { - tmp = readl(port_mmio + PORT_CMD); - if ((tmp & PORT_CMD_LIST_ON) == 0) - break; - udelay(10); - } - - if (!work) { - /* - * We need to do a port reset / HBA reset here - */ - return -EBUSY; - } - - /* - * Start DMA - */ - tmp |= PORT_CMD_START; - writel(tmp, port_mmio + PORT_CMD); - readl(port_mmio + PORT_CMD); /* flush */ - - return 0; -} - -static int ahci_stop_fis_rx(void __iomem *port_mmio) -{ - u32 tmp; - int work = 1000; - - /* - * Get current status - */ - tmp = readl(port_mmio + PORT_CMD); - - /* Check if FIS RX is already disabled */ - if ((tmp & PORT_CMD_FIS_RX) == 0) - return 0; - - /* - * AHCI Rev 1.1 section 10.3.2 - * Software shall not clear PxCMD.FRE while - * PxCMD.ST or PxCMD.CR is set to '1' - */ - if (tmp & (PORT_CMD_LIST_ON | PORT_CMD_START)) { - return -EPERM; - } - - /* - * Disable FIS reception - * - * AHCI Rev 1.1 Section 10.1.2: - * If PxCMD.FRE is set to '1', software should clear it - * to '0' and wait at least 500 milliseconds for PxCMD.FR - * to return '0' when read. If PxCMD.FR does not clear - * '0' correctly, then software may attempt a port reset - * of a full HBA reset to recover. - */ - tmp &= ~(PORT_CMD_FIS_RX); - writel(tmp, port_mmio + PORT_CMD); - - mdelay(500); - work = 1000; - while (work-- > 0) { - tmp = readl(port_mmio + PORT_CMD); - if ((tmp & PORT_CMD_FIS_ON) == 0) - return 0; - udelay(10); - } - - return -EBUSY; -} - -static void ahci_start_fis_rx(void __iomem *port_mmio, - struct ahci_port_priv *pp, - struct ahci_host_priv *hpriv) -{ - u32 tmp; - - /* - * Set FIS registers - */ - if (hpriv->cap & HOST_CAP_64) - writel((pp->cmd_slot_dma >> 16) >> 16, port_mmio + PORT_LST_ADDR_HI); - writel(pp->cmd_slot_dma & 0xffffffff, port_mmio + PORT_LST_ADDR); - readl(port_mmio + PORT_LST_ADDR); /* flush */ - - if (hpriv->cap & HOST_CAP_64) - writel((pp->rx_fis_dma >> 16) >> 16, port_mmio + PORT_FIS_ADDR_HI); - writel(pp->rx_fis_dma & 0xffffffff, port_mmio + PORT_FIS_ADDR); - readl(port_mmio + PORT_FIS_ADDR); /* flush */ - - /* - * Enable FIS reception - */ - tmp = readl(port_mmio + PORT_CMD); - tmp |= PORT_CMD_FIS_RX; - writel(tmp, port_mmio + PORT_CMD); - readl(port_mmio + PORT_CMD); /* flush */ -} - -static int ahci_port_standby(void __iomem *port_mmio, u32 cap) -{ - u32 tmp, scontrol, sstatus; - - tmp = readl(port_mmio + PORT_CMD); - /* - * AHCI Rev1.1 Section 5.3.2.3: - * Software is only allowed to program the PxCMD.FRE, - * PxCMD.POD, PxSCTL.DET, and PxCMD.SUD register bits - * when PxCMD.ST is set to '0' - */ - if (tmp & PORT_CMD_START) - return -EBUSY; - - if (cap & HOST_CAP_SSC) { - /* - * Enable transitions to slumber mode - */ - scontrol = readl(port_mmio + PORT_SCR_CTL); - if ((scontrol & 0x0f00) > 0x100) { - scontrol &= ~0xf00; - writel(scontrol, port_mmio + PORT_SCR_CTL); - } - /* - * Put device into slumber mode - */ - tmp |= PORT_CMD_ICC_SLUMBER; - writel(tmp, port_mmio + PORT_CMD); - tmp = readl(port_mmio + PORT_CMD); - - /* - * Actually, we should wait for the device to - * enter slumber mode by checking - * sstatus & 0xf00 == 6 - */ - sstatus = readl(port_mmio + PORT_SCR_STAT); - } - - /* - * Put device into listen mode - */ - scontrol = readl(port_mmio + PORT_SCR_CTL); - scontrol &= ~0xf; - writel(scontrol, port_mmio + PORT_SCR_CTL); - - tmp = readl(port_mmio + PORT_CMD); - if (cap & HOST_CAP_SSS) { - /* - * Spin down the device for staggered spin-up support - */ - tmp &= ~PORT_CMD_SPIN_UP; - writel(tmp, port_mmio + PORT_CMD); - readl(port_mmio + PORT_CMD); /* flush */ - } - - return 0; -} - -static int ahci_port_spinup(void __iomem *port_mmio, u32 cap) -{ - u32 tmp; - - tmp = readl(port_mmio + PORT_CMD); - /* - * AHCI Rev1.1 Section 5.3.2.3: - * Software is only allowed to program the PxCMD.FRE, - * PxCMD.POD, PxSCTL.DET, and PxCMD.SUD register bits - * when PxCMD.ST is set to '0' - */ - if (tmp & PORT_CMD_START) - return -EBUSY; - - /* - * Power on device if supported - */ - if (tmp & PORT_CMD_CPD) { - tmp |= PORT_CMD_POWER_ON; - writel(tmp, port_mmio + PORT_CMD); - tmp = readl(port_mmio + PORT_CMD); - } - - /* - * Spin up device - */ - if (cap & HOST_CAP_SSS) { - tmp |= PORT_CMD_SPIN_UP; - writel(tmp, port_mmio + PORT_CMD); - tmp = readl(port_mmio + PORT_CMD); - } - - if ((tmp & PORT_CMD_ICC_MASK) != PORT_CMD_ICC_ACTIVE) { - tmp |= PORT_CMD_ICC_ACTIVE; - writel(tmp, port_mmio + PORT_CMD); - tmp = readl(port_mmio + PORT_CMD); - } - - return 0; -} - -static void ahci_port_disable(struct ata_port *ap) -{ - struct ahci_host_priv *hpriv = ap->host_set->private_data; - - ata_port_disable(ap); - - hpriv->dev_map &= ~(1 << ap->port_no); -} - -static unsigned int ahci_dev_classify(struct ata_port *ap) +static void ahci_phy_reset(struct ata_port *ap) { void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr; struct ata_taskfile tf; - u32 tmp; + struct ata_device *dev = &ap->device[0]; + u32 new_tmp, tmp; + + __sata_phy_reset(ap); + + if (ap->flags & ATA_FLAG_PORT_DISABLED) + return; tmp = readl(port_mmio + PORT_SIG); tf.lbah = (tmp >> 24) & 0xff; @@ -841,182 +468,15 @@ static unsigned int ahci_dev_classify(struct ata_port *ap) tf.lbal = (tmp >> 8) & 0xff; tf.nsect = (tmp) & 0xff; - return ata_dev_classify(&tf); -} - -static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, u32 opts) -{ - pp->cmd_slot[0].opts = cpu_to_le32(opts); - pp->cmd_slot[0].status = 0; - pp->cmd_slot[0].tbl_addr = cpu_to_le32(pp->cmd_tbl_dma & 0xffffffff); - pp->cmd_slot[0].tbl_addr_hi = cpu_to_le32((pp->cmd_tbl_dma >> 16) >> 16); -} - -static int ahci_poll_register(void __iomem *reg, u32 mask, u32 val, - unsigned long interval_msec, - unsigned long timeout_msec) -{ - unsigned long timeout; - u32 tmp; - - timeout = jiffies + (timeout_msec * HZ) / 1000; - do { - tmp = readl(reg); - if ((tmp & mask) == val) - return 0; - msleep(interval_msec); - } while (time_before(jiffies, timeout)); - - return -1; -} - -static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class) -{ - struct ahci_host_priv *hpriv = ap->host_set->private_data; - struct ahci_port_priv *pp = ap->private_data; - void __iomem *mmio = ap->host_set->mmio_base; - void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); - const u32 cmd_fis_len = 5; /* five dwords */ - const char *reason = NULL; - struct ata_taskfile tf; - u8 *fis; - int rc; - - DPRINTK("ENTER\n"); - - /* prepare for SRST (AHCI-1.1 10.4.1) */ - rc = ahci_stop_engine(port_mmio); - if (rc) { - reason = "failed to stop engine"; - goto fail_restart; - } - - /* check BUSY/DRQ, perform Command List Override if necessary */ - ahci_tf_read(ap, &tf); - if (tf.command & (ATA_BUSY | ATA_DRQ)) { - u32 tmp; - - if (!(hpriv->cap & HOST_CAP_CLO)) { - rc = -EIO; - reason = "port busy but no CLO"; - goto fail_restart; - } - - tmp = readl(port_mmio + PORT_CMD); - tmp |= PORT_CMD_CLO; - writel(tmp, port_mmio + PORT_CMD); - readl(port_mmio + PORT_CMD); /* flush */ - - if (ahci_poll_register(port_mmio + PORT_CMD, PORT_CMD_CLO, 0x0, - 1, 500)) { - rc = -EIO; - reason = "CLO failed"; - goto fail_restart; - } - } - - /* restart engine */ - ahci_start_engine(port_mmio); - - ata_tf_init(ap, &tf, 0); - fis = pp->cmd_tbl; - - /* issue the first D2H Register FIS */ - ahci_fill_cmd_slot(pp, cmd_fis_len | AHCI_CMD_RESET | AHCI_CMD_CLR_BUSY); - - tf.ctl |= ATA_SRST; - ata_tf_to_fis(&tf, fis, 0); - fis[1] &= ~(1 << 7); /* turn off Command FIS bit */ - - writel(1, port_mmio + PORT_CMD_ISSUE); - readl(port_mmio + PORT_CMD_ISSUE); /* flush */ - - if (ahci_poll_register(port_mmio + PORT_CMD_ISSUE, 0x1, 0x0, 1, 500)) { - rc = -EIO; - reason = "1st FIS failed"; - goto fail; - } - - /* spec says at least 5us, but be generous and sleep for 1ms */ - msleep(1); - - /* issue the second D2H Register FIS */ - ahci_fill_cmd_slot(pp, cmd_fis_len); - - tf.ctl &= ~ATA_SRST; - ata_tf_to_fis(&tf, fis, 0); - fis[1] &= ~(1 << 7); /* turn off Command FIS bit */ - - writel(1, port_mmio + PORT_CMD_ISSUE); - readl(port_mmio + PORT_CMD_ISSUE); /* flush */ - - /* spec mandates ">= 2ms" before checking status. - * We wait 150ms, because that was the magic delay used for - * ATAPI devices in Hale Landis's ATADRVR, for the period of time - * between when the ATA command register is written, and then - * status is checked. Because waiting for "a while" before - * checking status is fine, post SRST, we perform this magic - * delay here as well. - */ - msleep(150); - - *class = ATA_DEV_NONE; - if (sata_dev_present(ap)) { - if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) { - rc = -EIO; - reason = "device not ready"; - goto fail; - } - *class = ahci_dev_classify(ap); + dev->class = ata_dev_classify(&tf); + if (!ata_dev_present(dev)) { + ata_port_disable(ap); + return; } - DPRINTK("EXIT, class=%u\n", *class); - return 0; - - fail_restart: - ahci_start_engine(port_mmio); - fail: - if (verbose) - printk(KERN_ERR "ata%u: softreset failed (%s)\n", - ap->id, reason); - else - DPRINTK("EXIT, rc=%d reason=\"%s\"\n", rc, reason); - return rc; -} - -static int ahci_hardreset(struct ata_port *ap, int verbose, unsigned int *class) -{ - int rc; - void __iomem *mmio = ap->host_set->mmio_base; - void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); - - - DPRINTK("ENTER\n"); - - ahci_stop_engine(port_mmio); - rc = sata_std_hardreset(ap, verbose, class); - ahci_start_engine(port_mmio); - - if (rc == 0) - *class = ahci_dev_classify(ap); - if (*class == ATA_DEV_UNKNOWN) - *class = ATA_DEV_NONE; - - DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); - return rc; -} - -static void ahci_postreset(struct ata_port *ap, unsigned int *class) -{ - void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr; - struct ahci_host_priv *hpriv = ap->host_set->private_data; - u32 new_tmp, tmp; - - ata_std_postreset(ap, class); - /* Make sure port's ATAPI bit is set appropriately */ new_tmp = tmp = readl(port_mmio + PORT_CMD); - if (*class == ATA_DEV_ATAPI) + if (dev->class == ATA_DEV_ATAPI) new_tmp |= PORT_CMD_ATAPI; else new_tmp &= ~PORT_CMD_ATAPI; @@ -1024,16 +484,6 @@ static void ahci_postreset(struct ata_port *ap, unsigned int *class) writel(new_tmp, port_mmio + PORT_CMD); readl(port_mmio + PORT_CMD); /* flush */ } - - if (*class != ATA_DEV_NONE) - hpriv->dev_map |= (1 << ap->port_no); -} - -static int ahci_probe_reset(struct ata_port *ap, unsigned int *classes) -{ - return ata_drive_probe_reset(ap, ata_std_probeinit, - ahci_softreset, ahci_hardreset, - ahci_postreset, classes); } static u8 ahci_check_status(struct ata_port *ap) @@ -1083,36 +533,42 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; struct ahci_port_priv *pp = ap->private_data; - int is_atapi = is_atapi_taskfile(&qc->tf); u32 opts; const u32 cmd_fis_len = 5; /* five dwords */ unsigned int n_elem; + /* + * Fill in command slot information (currently only one slot, + * slot 0, is currently since we don't do queueing) + */ + + opts = cmd_fis_len; + if (qc->tf.flags & ATA_TFLAG_WRITE) + opts |= AHCI_CMD_WRITE; + if (is_atapi_taskfile(&qc->tf)) + opts |= AHCI_CMD_ATAPI; + + pp->cmd_slot[0].opts = cpu_to_le32(opts); + pp->cmd_slot[0].status = 0; + pp->cmd_slot[0].tbl_addr = cpu_to_le32(pp->cmd_tbl_dma & 0xffffffff); + pp->cmd_slot[0].tbl_addr_hi = cpu_to_le32((pp->cmd_tbl_dma >> 16) >> 16); + /* * Fill in command table information. First, the header, * a SATA Register - Host to Device command FIS. */ ata_tf_to_fis(&qc->tf, pp->cmd_tbl, 0); - if (is_atapi) { + if (opts & AHCI_CMD_ATAPI) { memset(pp->cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32); - memcpy(pp->cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, - qc->dev->cdb_len); + memcpy(pp->cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, ap->cdb_len); } - n_elem = 0; - if (qc->flags & ATA_QCFLAG_DMAMAP) - n_elem = ahci_fill_sg(qc); + if (!(qc->flags & ATA_QCFLAG_DMAMAP)) + return; - /* - * Fill in command slot information. - */ - opts = cmd_fis_len | n_elem << 16; - if (qc->tf.flags & ATA_TFLAG_WRITE) - opts |= AHCI_CMD_WRITE; - if (is_atapi) - opts |= AHCI_CMD_ATAPI | AHCI_CMD_PREFETCH; + n_elem = ahci_fill_sg(qc); - ahci_fill_cmd_slot(pp, opts); + pp->cmd_slot[0].opts |= cpu_to_le32(n_elem << 16); } static void ahci_restart_port(struct ata_port *ap, u32 irq_stat) @@ -1120,6 +576,7 @@ static void ahci_restart_port(struct ata_port *ap, u32 irq_stat) void __iomem *mmio = ap->host_set->mmio_base; void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); u32 tmp; + int work; if ((ap->device[0].class != ATA_DEV_ATAPI) || ((irq_stat & PORT_IRQ_TF_ERR) == 0)) @@ -1135,7 +592,20 @@ static void ahci_restart_port(struct ata_port *ap, u32 irq_stat) readl(port_mmio + PORT_SCR_ERR)); /* stop DMA */ - ahci_stop_engine(port_mmio); + tmp = readl(port_mmio + PORT_CMD); + tmp &= ~PORT_CMD_START; + writel(tmp, port_mmio + PORT_CMD); + + /* wait for engine to stop. TODO: this could be + * as long as 500 msec + */ + work = 1000; + while (work-- > 0) { + tmp = readl(port_mmio + PORT_CMD); + if ((tmp & PORT_CMD_LIST_ON) == 0) + break; + udelay(10); + } /* clear SATA phy error, if any */ tmp = readl(port_mmio + PORT_SCR_ERR); @@ -1154,7 +624,10 @@ static void ahci_restart_port(struct ata_port *ap, u32 irq_stat) } /* re-start DMA */ - ahci_start_engine(port_mmio); + tmp = readl(port_mmio + PORT_CMD); + tmp |= PORT_CMD_START; + writel(tmp, port_mmio + PORT_CMD); + readl(port_mmio + PORT_CMD); /* flush */ } static void ahci_eng_timeout(struct ata_port *ap) @@ -1169,78 +642,25 @@ static void ahci_eng_timeout(struct ata_port *ap) spin_lock_irqsave(&host_set->lock, flags); - ahci_restart_port(ap, readl(port_mmio + PORT_IRQ_STAT)); qc = ata_qc_from_tag(ap, ap->active_tag); - qc->err_mask |= AC_ERR_TIMEOUT; - - spin_unlock_irqrestore(&host_set->lock, flags); - - ata_eh_qc_complete(qc); -} - -int ahci_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state) -{ - struct ata_port *ap = (struct ata_port *) &sdev->host->hostdata[0]; - struct ata_device *dev = &ap->device[sdev->id]; - int rc; - - rc = ata_device_suspend(ap, dev, state); - - if (!rc) - rc = ahci_port_suspend(ap, state); - - return rc; -} - -int ahci_scsi_device_resume(struct scsi_device *sdev) -{ - struct ata_port *ap = (struct ata_port *) &sdev->host->hostdata[0]; - struct ata_device *dev = &ap->device[sdev->id]; - - ahci_port_resume(ap); - - return ata_device_resume(ap, dev); -} - -int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct device *dev = pci_dev_to_dev(pdev); - struct ata_host_set *host_set = dev_get_drvdata(dev); - void __iomem *mmio = host_set->mmio_base; - u32 tmp; - - /* - * AHCI spec rev1.1 section 8.3.3: - * Software must disable interrupts prior to - * requesting a transition of the HBA to - * D3 state. - */ - tmp = readl(mmio + HOST_CTL); - tmp &= ~HOST_IRQ_EN; - writel(tmp, mmio + HOST_CTL); - tmp = readl(mmio + HOST_CTL); /* flush */ - - return ata_pci_device_suspend(pdev, state); -} - -int ahci_pci_device_resume(struct pci_dev *pdev) -{ - struct device *dev = pci_dev_to_dev(pdev); - struct ata_host_set *host_set = dev_get_drvdata(dev); - void __iomem *mmio = host_set->mmio_base; - u32 tmp; - - /* - * Enabling AHCI mode - */ - tmp = readl(mmio + HOST_CTL); - if (!(tmp & HOST_AHCI_EN)) { - tmp |= HOST_AHCI_EN; - writel(tmp, mmio + HOST_CTL); - tmp = readl(mmio + HOST_CTL); + if (!qc) { + printk(KERN_ERR "ata%u: BUG: timeout without command\n", + ap->id); + } else { + ahci_restart_port(ap, readl(port_mmio + PORT_IRQ_STAT)); + + /* hack alert! We cannot use the supplied completion + * function from inside the ->eh_strategy_handler() thread. + * libata is the only user of ->eh_strategy_handler() in + * any kernel, so the default scsi_done() assumes it is + * not being called from the SCSI EH. + */ + qc->scsidone = scsi_finish_command; + qc->err_mask |= AC_ERR_OTHER; + ata_qc_complete(qc); } - return ata_pci_device_resume(pdev); + spin_unlock_irqrestore(&host_set->lock, flags); } static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc) @@ -1258,7 +678,7 @@ static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc) ci = readl(port_mmio + PORT_CMD_ISSUE); if (likely((ci & 0x1) == 0)) { if (qc) { - WARN_ON(qc->err_mask); + assert(qc->err_mask == 0); ata_qc_complete(qc); qc = NULL; } @@ -1277,7 +697,7 @@ static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc) ahci_restart_port(ap, status); if (qc) { - qc->err_mask |= err_mask; + qc->err_mask |= AC_ERR_OTHER; ata_qc_complete(qc); } } @@ -1350,7 +770,7 @@ static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs * return IRQ_RETVAL(handled); } -static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc) +static int ahci_qc_issue(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr; @@ -1423,7 +843,6 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent) hpriv->cap = readl(mmio + HOST_CAP); hpriv->port_map = readl(mmio + HOST_PORTS_IMPL); - hpriv->dev_map = 0; probe_ent->n_ports = (hpriv->cap & 0x1f) + 1; VPRINTK("cap 0x%x port_map 0x%x n_ports %d\n", @@ -1469,29 +888,23 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent) (unsigned long) mmio, i); /* make sure port is not active */ - rc = ahci_stop_engine(port_mmio); - if (rc) - printk(KERN_WARNING "ata%u: DMA engine busy (rc %d)\n", - i, rc); - - rc = ahci_stop_fis_rx(port_mmio); - if (rc) - printk(KERN_WARNING "ata%u: FIS RX not stopped (rc %d)\n", - i, rc); - - /* - * Actually, this is wrong again. - * AHCI spec says that we first should - * enable FIS reception before sending - * SPIN_UP to the device ... - */ + tmp = readl(port_mmio + PORT_CMD); + VPRINTK("PORT_CMD 0x%x\n", tmp); + if (tmp & (PORT_CMD_LIST_ON | PORT_CMD_FIS_ON | + PORT_CMD_FIS_RX | PORT_CMD_START)) { + tmp &= ~(PORT_CMD_LIST_ON | PORT_CMD_FIS_ON | + PORT_CMD_FIS_RX | PORT_CMD_START); + writel(tmp, port_mmio + PORT_CMD); + readl(port_mmio + PORT_CMD); /* flush */ + + /* spec says 500 msecs for each bit, so + * this is slightly incorrect. + */ + msleep(500); + } writel(PORT_CMD_SPIN_UP, port_mmio + PORT_CMD); - /* - * Wait for the communications link to establish - */ - j = 0; while (j < 100) { msleep(10);