X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fata%2Fahci.c;h=8cace9aa9c0398bafe101115ba511bb5dd29f0fb;hb=3eb6753e20af1803d7784efc36e8208e8d5fac05;hp=1389c64e0027c4d7c088cb08ee19d45f2a6fa82d;hpb=79f97dadfe9b4b561634d202225ba2fa910dc225;p=linux-2.6 diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 1389c64e00..8cace9aa9c 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -243,11 +243,10 @@ static int ahci_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val); static int 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 bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc); static int ahci_port_start(struct ata_port *ap); static void ahci_port_stop(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 void ahci_freeze(struct ata_port *ap); static void ahci_thaw(struct ata_port *ap); static void ahci_pmp_attach(struct ata_port *ap); @@ -261,8 +260,6 @@ static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class, static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, unsigned long deadline); static void ahci_postreset(struct ata_link *link, unsigned int *class); -static int ahci_pmp_softreset(struct ata_link *link, unsigned int *class, - unsigned long deadline); static void ahci_error_handler(struct ata_port *ap); static void ahci_post_internal_cmd(struct ata_queued_cmd *qc); static int ahci_port_resume(struct ata_port *ap); @@ -276,8 +273,8 @@ static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg); static int ahci_pci_device_resume(struct pci_dev *pdev); #endif -static struct class_device_attribute *ahci_shost_attrs[] = { - &class_device_attr_link_power_management_policy, +static struct device_attribute *ahci_shost_attrs[] = { + &dev_attr_link_power_management_policy, NULL }; @@ -292,20 +289,17 @@ static struct scsi_host_template ahci_sht = { static struct ata_port_operations ahci_ops = { .inherits = &sata_pmp_port_ops, - .sff_check_status = ahci_check_status, - .sff_check_altstatus = ahci_check_status, - - .sff_tf_read = ahci_tf_read, .qc_defer = sata_pmp_qc_defer_cmd_switch, .qc_prep = ahci_qc_prep, .qc_issue = ahci_qc_issue, + .qc_fill_rtf = ahci_qc_fill_rtf, .freeze = ahci_freeze, .thaw = ahci_thaw, .softreset = ahci_softreset, .hardreset = ahci_hardreset, .postreset = ahci_postreset, - .pmp_softreset = ahci_pmp_softreset, + .pmp_softreset = ahci_softreset, .error_handler = ahci_error_handler, .post_internal_cmd = ahci_post_internal_cmd, .dev_config = ahci_dev_config, @@ -364,7 +358,7 @@ static const struct ata_port_info ahci_port_info[] = { /* board_ahci_sb600 */ { AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL | - AHCI_HFLAG_32BIT_ONLY | + AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255 | AHCI_HFLAG_NO_PMP), .flags = AHCI_FLAG_COMMON, .pio_mask = 0x1f, /* pio0-4 */ @@ -562,16 +556,27 @@ static inline void __iomem *ahci_port_base(struct ata_port *ap) static void ahci_enable_ahci(void __iomem *mmio) { + int i; u32 tmp; /* turn on AHCI_EN */ tmp = readl(mmio + HOST_CTL); - if (!(tmp & HOST_AHCI_EN)) { + if (tmp & HOST_AHCI_EN) + return; + + /* Some controllers need AHCI_EN to be written multiple times. + * Try a few times before giving up. + */ + for (i = 0; i < 5; i++) { tmp |= HOST_AHCI_EN; writel(tmp, mmio + HOST_CTL); tmp = readl(mmio + HOST_CTL); /* flush && sanity check */ - WARN_ON(!(tmp & HOST_AHCI_EN)); + if (tmp & HOST_AHCI_EN) + return; + msleep(10); } + + WARN_ON(1); } /** @@ -1183,13 +1188,14 @@ static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag, static int ahci_kick_engine(struct ata_port *ap, int force_restart) { - void __iomem *port_mmio = ap->ioaddr.cmd_addr; + void __iomem *port_mmio = ahci_port_base(ap); struct ahci_host_priv *hpriv = ap->host->private_data; + u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF; u32 tmp; int busy, rc; /* do we need to kick the port? */ - busy = ahci_check_status(ap) & (ATA_BUSY | ATA_DRQ); + busy = status & (ATA_BUSY | ATA_DRQ); if (!busy && !force_restart) return 0; @@ -1258,18 +1264,19 @@ static int ahci_exec_polled_cmd(struct ata_port *ap, int pmp, static int ahci_check_ready(struct ata_link *link) { - void __iomem *mmio = link->ap->ioaddr.cmd_addr; - u8 status = readl(mmio + PORT_TFDATA) & 0xFF; + void __iomem *port_mmio = ahci_port_base(link->ap); + u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF; if (!(status & ATA_BUSY)) return 1; return 0; } -static int ahci_do_softreset(struct ata_link *link, unsigned int *class, - int pmp, unsigned long deadline) +static int ahci_softreset(struct ata_link *link, unsigned int *class, + unsigned long deadline) { struct ata_port *ap = link->ap; + int pmp = sata_srst_pmp(link); const char *reason = NULL; unsigned long now, msecs; struct ata_taskfile tf; @@ -1277,12 +1284,6 @@ static int ahci_do_softreset(struct ata_link *link, unsigned int *class, DPRINTK("ENTER\n"); - if (ata_link_offline(link)) { - DPRINTK("PHY reports no device\n"); - *class = ATA_DEV_NONE; - return 0; - } - /* prepare for SRST (AHCI-1.1 10.4.1) */ rc = ahci_kick_engine(ap, 1); if (rc && rc != -EOPNOTSUPP) @@ -1329,17 +1330,6 @@ static int ahci_do_softreset(struct ata_link *link, unsigned int *class, return rc; } -static int ahci_softreset(struct ata_link *link, unsigned int *class, - unsigned long deadline) -{ - int pmp = 0; - - if (link->ap->flags & ATA_FLAG_PMP) - pmp = SATA_PMP_CTRL_PORT; - - return ahci_do_softreset(link, class, pmp, deadline); -} - static int ahci_hardreset(struct ata_link *link, unsigned int *class, unsigned long deadline) { @@ -1460,27 +1450,6 @@ static void ahci_postreset(struct ata_link *link, unsigned int *class) } } -static int ahci_pmp_softreset(struct ata_link *link, unsigned int *class, - unsigned long deadline) -{ - return ahci_do_softreset(link, class, link->pmp, deadline); -} - -static u8 ahci_check_status(struct ata_port *ap) -{ - void __iomem *mmio = ap->ioaddr.cmd_addr; - - return readl(mmio + PORT_TFDATA) & 0xFF; -} - -static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf) -{ - struct ahci_port_priv *pp = ap->private_data; - u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; - - ata_tf_from_fis(d2h_fis, tf); -} - static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl) { struct scatterlist *sg; @@ -1599,7 +1568,7 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) unk[0], unk[1], unk[2], unk[3]); } - if (ap->nr_pmp_links && (irq_stat & PORT_IRQ_BAD_PMP)) { + if (sata_pmp_attached(ap) && (irq_stat & PORT_IRQ_BAD_PMP)) { active_ehi->err_mask |= AC_ERR_HSM; active_ehi->action |= ATA_EH_RESET; ata_ehi_push_desc(active_ehi, "incorrect PMP"); @@ -1634,7 +1603,7 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) static void ahci_port_intr(struct ata_port *ap) { - void __iomem *port_mmio = ap->ioaddr.cmd_addr; + void __iomem *port_mmio = ahci_port_base(ap); struct ata_eh_info *ehi = &ap->link.eh_info; struct ahci_port_priv *pp = ap->private_data; struct ahci_host_priv *hpriv = ap->host->private_data; @@ -1779,6 +1748,15 @@ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc) return 0; } +static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc) +{ + struct ahci_port_priv *pp = qc->ap->private_data; + u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; + + ata_tf_from_fis(d2h_fis, &qc->result_tf); + return true; +} + static void ahci_freeze(struct ata_port *ap) { void __iomem *port_mmio = ahci_port_base(ap); @@ -1856,7 +1834,7 @@ static int ahci_port_resume(struct ata_port *ap) ahci_power_up(ap); ahci_start_port(ap); - if (ap->nr_pmp_links) + if (sata_pmp_attached(ap)) ahci_pmp_attach(ap); else ahci_pmp_detach(ap); @@ -2219,7 +2197,6 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) for (i = 0; i < host->n_ports; i++) { struct ata_port *ap = host->ports[i]; - void __iomem *port_mmio = ahci_port_base(ap); ata_port_pbar_desc(ap, AHCI_PCI_BAR, -1, "abar"); ata_port_pbar_desc(ap, AHCI_PCI_BAR, @@ -2228,12 +2205,8 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) /* set initial link pm policy */ ap->pm_policy = NOT_AVAILABLE; - /* standard SATA port setup */ - if (hpriv->port_map & (1 << i)) - ap->ioaddr.cmd_addr = port_mmio; - /* disabled/not-implemented port */ - else + if (!(hpriv->port_map & (1 << i))) ap->ops = &ata_dummy_port_ops; }