diff options
Diffstat (limited to 'drivers/ata/ahci.c')
-rw-r--r-- | drivers/ata/ahci.c | 327 |
1 files changed, 135 insertions, 192 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index fe4f0fe..7c61bc7 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -211,7 +211,6 @@ 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 irqreturn_t ahci_interrupt (int irq, void *dev_instance); static void ahci_irq_clear(struct ata_port *ap); static int ahci_port_start(struct ata_port *ap); static void ahci_port_stop(struct ata_port *ap); @@ -265,7 +264,6 @@ static const struct ata_port_operations ahci_ops = { .qc_prep = ahci_qc_prep, .qc_issue = ahci_qc_issue, - .irq_handler = ahci_interrupt, .irq_clear = ahci_irq_clear, .irq_on = ata_dummy_irq_on, .irq_ack = ata_dummy_irq_ack, @@ -300,7 +298,6 @@ static const struct ata_port_operations ahci_vt8251_ops = { .qc_prep = ahci_qc_prep, .qc_issue = ahci_qc_issue, - .irq_handler = ahci_interrupt, .irq_clear = ahci_irq_clear, .irq_on = ata_dummy_irq_on, .irq_ack = ata_dummy_irq_ack, @@ -326,7 +323,6 @@ static const struct ata_port_operations ahci_vt8251_ops = { static const struct ata_port_info ahci_port_info[] = { /* board_ahci */ { - .sht = &ahci_sht, .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | ATA_FLAG_SKIP_D2H_BSY, @@ -336,7 +332,6 @@ static const struct ata_port_info ahci_port_info[] = { }, /* board_ahci_pi */ { - .sht = &ahci_sht, .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | ATA_FLAG_SKIP_D2H_BSY | AHCI_FLAG_HONOR_PI, @@ -346,7 +341,6 @@ static const struct ata_port_info ahci_port_info[] = { }, /* board_ahci_vt8251 */ { - .sht = &ahci_sht, .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | ATA_FLAG_SKIP_D2H_BSY | @@ -357,7 +351,6 @@ static const struct ata_port_info ahci_port_info[] = { }, /* board_ahci_ign_iferr */ { - .sht = &ahci_sht, .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | ATA_FLAG_SKIP_D2H_BSY | @@ -473,15 +466,18 @@ static inline int ahci_nr_ports(u32 cap) return (cap & 0x1f) + 1; } -static inline void __iomem *ahci_port_base(void __iomem *base, - unsigned int port) +static inline void __iomem *ahci_port_base(struct ata_port *ap) { - return base + 0x100 + (port * 0x80); + void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR]; + + return mmio + 0x100 + (ap->port_no * 0x80); } /** * ahci_save_initial_config - Save and fixup initial config values - * @probe_ent: probe_ent of target device + * @pdev: target PCI device + * @pi: associated ATA port info + * @hpriv: host private area to store config values * * Some registers containing configuration info might be setup by * BIOS and might be cleared on reset. This function saves the @@ -493,10 +489,11 @@ static inline void __iomem *ahci_port_base(void __iomem *base, * LOCKING: * None. */ -static void ahci_save_initial_config(struct ata_probe_ent *probe_ent) +static void ahci_save_initial_config(struct pci_dev *pdev, + const struct ata_port_info *pi, + struct ahci_host_priv *hpriv) { - struct ahci_host_priv *hpriv = probe_ent->private_data; - void __iomem *mmio = probe_ent->iomap[AHCI_PCI_BAR]; + void __iomem *mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR]; u32 cap, port_map; int i; @@ -509,7 +506,7 @@ static void ahci_save_initial_config(struct ata_probe_ent *probe_ent) /* fixup zero port_map */ if (!port_map) { port_map = (1 << ahci_nr_ports(hpriv->cap)) - 1; - dev_printk(KERN_WARNING, probe_ent->dev, + dev_printk(KERN_WARNING, &pdev->dev, "PORTS_IMPL is zero, forcing 0x%x\n", port_map); /* write the fixed up value to the PI register */ @@ -517,7 +514,7 @@ static void ahci_save_initial_config(struct ata_probe_ent *probe_ent) } /* cross check port_map and cap.n_ports */ - if (probe_ent->port_flags & AHCI_FLAG_HONOR_PI) { + if (pi->flags & AHCI_FLAG_HONOR_PI) { u32 tmp_port_map = port_map; int n_ports = ahci_nr_ports(cap); @@ -532,7 +529,7 @@ static void ahci_save_initial_config(struct ata_probe_ent *probe_ent) * port_map is used to determine number of ports. */ if (n_ports || tmp_port_map) - dev_printk(KERN_WARNING, probe_ent->dev, + dev_printk(KERN_WARNING, &pdev->dev, "nr_ports (%u) and implemented port map " "(0x%x) don't match\n", ahci_nr_ports(cap), port_map); @@ -548,17 +545,18 @@ static void ahci_save_initial_config(struct ata_probe_ent *probe_ent) /** * ahci_restore_initial_config - Restore initial config - * @mmio: MMIO base for the host - * @hpriv: host private data + * @host: target ATA host * * Restore initial config stored by ahci_save_initial_config(). * * LOCKING: * None. */ -static void ahci_restore_initial_config(void __iomem *mmio, - struct ahci_host_priv *hpriv) +static void ahci_restore_initial_config(struct ata_host *host) { + struct ahci_host_priv *hpriv = host->private_data; + void __iomem *mmio = host->iomap[AHCI_PCI_BAR]; + writel(hpriv->saved_cap, mmio + HOST_CAP); writel(hpriv->saved_port_map, mmio + HOST_PORTS_IMPL); (void) readl(mmio + HOST_PORTS_IMPL); /* flush */ @@ -598,8 +596,9 @@ static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg_in, writel(val, ap->ioaddr.scr_addr + (sc_reg * 4)); } -static void ahci_start_engine(void __iomem *port_mmio) +static void ahci_start_engine(struct ata_port *ap) { + void __iomem *port_mmio = ahci_port_base(ap); u32 tmp; /* start DMA */ @@ -609,8 +608,9 @@ static void ahci_start_engine(void __iomem *port_mmio) readl(port_mmio + PORT_CMD); /* flush */ } -static int ahci_stop_engine(void __iomem *port_mmio) +static int ahci_stop_engine(struct ata_port *ap) { + void __iomem *port_mmio = ahci_port_base(ap); u32 tmp; tmp = readl(port_mmio + PORT_CMD); @@ -632,19 +632,23 @@ static int ahci_stop_engine(void __iomem *port_mmio) return 0; } -static void ahci_start_fis_rx(void __iomem *port_mmio, u32 cap, - dma_addr_t cmd_slot_dma, dma_addr_t rx_fis_dma) +static void ahci_start_fis_rx(struct ata_port *ap) { + void __iomem *port_mmio = ahci_port_base(ap); + struct ahci_host_priv *hpriv = ap->host->private_data; + struct ahci_port_priv *pp = ap->private_data; u32 tmp; /* set FIS registers */ - if (cap & HOST_CAP_64) - writel((cmd_slot_dma >> 16) >> 16, port_mmio + PORT_LST_ADDR_HI); - writel(cmd_slot_dma & 0xffffffff, port_mmio + PORT_LST_ADDR); + 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); - if (cap & HOST_CAP_64) - writel((rx_fis_dma >> 16) >> 16, port_mmio + PORT_FIS_ADDR_HI); - writel(rx_fis_dma & 0xffffffff, port_mmio + PORT_FIS_ADDR); + 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); /* enable FIS reception */ tmp = readl(port_mmio + PORT_CMD); @@ -655,8 +659,9 @@ static void ahci_start_fis_rx(void __iomem *port_mmio, u32 cap, readl(port_mmio + PORT_CMD); } -static int ahci_stop_fis_rx(void __iomem *port_mmio) +static int ahci_stop_fis_rx(struct ata_port *ap) { + void __iomem *port_mmio = ahci_port_base(ap); u32 tmp; /* disable FIS reception */ @@ -673,14 +678,16 @@ static int ahci_stop_fis_rx(void __iomem *port_mmio) return 0; } -static void ahci_power_up(void __iomem *port_mmio, u32 cap) +static void ahci_power_up(struct ata_port *ap) { + struct ahci_host_priv *hpriv = ap->host->private_data; + void __iomem *port_mmio = ahci_port_base(ap); u32 cmd; cmd = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK; /* spin up device */ - if (cap & HOST_CAP_SSS) { + if (hpriv->cap & HOST_CAP_SSS) { cmd |= PORT_CMD_SPIN_UP; writel(cmd, port_mmio + PORT_CMD); } @@ -690,11 +697,13 @@ static void ahci_power_up(void __iomem *port_mmio, u32 cap) } #ifdef CONFIG_PM -static void ahci_power_down(void __iomem *port_mmio, u32 cap) +static void ahci_power_down(struct ata_port *ap) { + struct ahci_host_priv *hpriv = ap->host->private_data; + void __iomem *port_mmio = ahci_port_base(ap); u32 cmd, scontrol; - if (!(cap & HOST_CAP_SSS)) + if (!(hpriv->cap & HOST_CAP_SSS)) return; /* put device into listen mode, first set PxSCTL.DET to 0 */ @@ -709,29 +718,28 @@ static void ahci_power_down(void __iomem *port_mmio, u32 cap) } #endif -static void ahci_init_port(void __iomem *port_mmio, u32 cap, - dma_addr_t cmd_slot_dma, dma_addr_t rx_fis_dma) +static void ahci_init_port(struct ata_port *ap) { /* enable FIS reception */ - ahci_start_fis_rx(port_mmio, cap, cmd_slot_dma, rx_fis_dma); + ahci_start_fis_rx(ap); /* enable DMA */ - ahci_start_engine(port_mmio); + ahci_start_engine(ap); } -static int ahci_deinit_port(void __iomem *port_mmio, u32 cap, const char **emsg) +static int ahci_deinit_port(struct ata_port *ap, const char **emsg) { int rc; /* disable DMA */ - rc = ahci_stop_engine(port_mmio); + rc = ahci_stop_engine(ap); if (rc) { *emsg = "failed to stop engine"; return rc; } /* disable FIS reception */ - rc = ahci_stop_fis_rx(port_mmio); + rc = ahci_stop_fis_rx(ap); if (rc) { *emsg = "failed stop FIS RX"; return rc; @@ -740,9 +748,10 @@ static int ahci_deinit_port(void __iomem *port_mmio, u32 cap, const char **emsg) return 0; } -static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev, - struct ahci_host_priv *hpriv) +static int ahci_reset_controller(struct ata_host *host) { + struct pci_dev *pdev = to_pci_dev(host->dev); + void __iomem *mmio = host->iomap[AHCI_PCI_BAR]; u32 tmp; /* global controller reset */ @@ -759,7 +768,7 @@ static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev, tmp = readl(mmio + HOST_CTL); if (tmp & HOST_RESET) { - dev_printk(KERN_ERR, &pdev->dev, + dev_printk(KERN_ERR, host->dev, "controller reset failed (0x%x)\n", tmp); return -EIO; } @@ -769,7 +778,7 @@ static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev, (void) readl(mmio + HOST_CTL); /* flush */ /* some registers might be cleared on reset. restore initial values */ - ahci_restore_initial_config(mmio, hpriv); + ahci_restore_initial_config(host); if (pdev->vendor == PCI_VENDOR_ID_INTEL) { u16 tmp16; @@ -783,23 +792,23 @@ static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev, return 0; } -static void ahci_init_controller(void __iomem *mmio, struct pci_dev *pdev, - int n_ports, unsigned int port_flags, - struct ahci_host_priv *hpriv) +static void ahci_init_controller(struct ata_host *host) { + struct pci_dev *pdev = to_pci_dev(host->dev); + void __iomem *mmio = host->iomap[AHCI_PCI_BAR]; int i, rc; u32 tmp; - for (i = 0; i < n_ports; i++) { - void __iomem *port_mmio = ahci_port_base(mmio, i); + for (i = 0; i < host->n_ports; i++) { + struct ata_port *ap = host->ports[i]; + void __iomem *port_mmio = ahci_port_base(ap); const char *emsg = NULL; - if ((port_flags & AHCI_FLAG_HONOR_PI) && - !(hpriv->port_map & (1 << i))) + if (ata_port_is_dummy(ap)) continue; /* make sure port is not active */ - rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg); + rc = ahci_deinit_port(ap, &emsg); if (rc) dev_printk(KERN_WARNING, &pdev->dev, "%s (%d)\n", emsg, rc); @@ -827,7 +836,7 @@ static void ahci_init_controller(void __iomem *mmio, struct pci_dev *pdev, static unsigned int ahci_dev_classify(struct ata_port *ap) { - void __iomem *port_mmio = ap->ioaddr.cmd_addr; + void __iomem *port_mmio = ahci_port_base(ap); struct ata_taskfile tf; u32 tmp; @@ -877,8 +886,7 @@ static int ahci_clo(struct ata_port *ap) static int ahci_softreset(struct ata_port *ap, unsigned int *class) { struct ahci_port_priv *pp = ap->private_data; - void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR]; - void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); + void __iomem *port_mmio = ahci_port_base(ap); const u32 cmd_fis_len = 5; /* five dwords */ const char *reason = NULL; struct ata_taskfile tf; @@ -895,7 +903,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class) } /* prepare for SRST (AHCI-1.1 10.4.1) */ - rc = ahci_stop_engine(port_mmio); + rc = ahci_stop_engine(ap); if (rc) { reason = "failed to stop engine"; goto fail_restart; @@ -915,7 +923,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class) } /* restart engine */ - ahci_start_engine(port_mmio); + ahci_start_engine(ap); ata_tf_init(ap->device, &tf); fis = pp->cmd_tbl; @@ -974,7 +982,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class) return 0; fail_restart: - ahci_start_engine(port_mmio); + ahci_start_engine(ap); fail: ata_port_printk(ap, KERN_ERR, "softreset failed (%s)\n", reason); return rc; @@ -985,13 +993,11 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class) struct ahci_port_priv *pp = ap->private_data; u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; struct ata_taskfile tf; - void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR]; - void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); int rc; DPRINTK("ENTER\n"); - ahci_stop_engine(port_mmio); + ahci_stop_engine(ap); /* clear D2H reception area to properly wait for D2H FIS */ ata_tf_init(ap->device, &tf); @@ -1000,7 +1006,7 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class) rc = sata_std_hardreset(ap, class); - ahci_start_engine(port_mmio); + ahci_start_engine(ap); if (rc == 0 && ata_port_online(ap)) *class = ahci_dev_classify(ap); @@ -1013,20 +1019,18 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class) static int ahci_vt8251_hardreset(struct ata_port *ap, unsigned int *class) { - void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR]; - void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); int rc; DPRINTK("ENTER\n"); - ahci_stop_engine(port_mmio); + ahci_stop_engine(ap); rc = sata_port_hardreset(ap, sata_ehc_deb_timing(&ap->eh_context)); /* vt8251 needs SError cleared for the port to operate */ ahci_scr_write(ap, SCR_ERROR, ahci_scr_read(ap, SCR_ERROR)); - ahci_start_engine(port_mmio); + ahci_start_engine(ap); DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); @@ -1038,7 +1042,7 @@ static int ahci_vt8251_hardreset(struct ata_port *ap, unsigned int *class) static void ahci_postreset(struct ata_port *ap, unsigned int *class) { - void __iomem *port_mmio = ap->ioaddr.cmd_addr; + void __iomem *port_mmio = ahci_port_base(ap); u32 new_tmp, tmp; ata_std_postreset(ap, class); @@ -1206,8 +1210,7 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) static void ahci_host_intr(struct ata_port *ap) { - void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR]; - void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); + void __iomem *port_mmio = ap->ioaddr.cmd_addr; struct ata_eh_info *ehi = &ap->eh_info; struct ahci_port_priv *pp = ap->private_data; u32 status, qc_active; @@ -1358,7 +1361,7 @@ static irqreturn_t ahci_interrupt(int irq, void *dev_instance) static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; - void __iomem *port_mmio = ap->ioaddr.cmd_addr; + void __iomem *port_mmio = ahci_port_base(ap); if (qc->tf.protocol == ATA_PROT_NCQ) writel(1 << qc->tag, port_mmio + PORT_SCR_ACT); @@ -1370,8 +1373,7 @@ static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc) static void ahci_freeze(struct ata_port *ap) { - void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR]; - void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); + void __iomem *port_mmio = ahci_port_base(ap); /* turn IRQ off */ writel(0, port_mmio + PORT_IRQ_MASK); @@ -1380,7 +1382,7 @@ static void ahci_freeze(struct ata_port *ap) static void ahci_thaw(struct ata_port *ap) { void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR]; - void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); + void __iomem *port_mmio = ahci_port_base(ap); u32 tmp; /* clear IRQ */ @@ -1394,13 +1396,10 @@ static void ahci_thaw(struct ata_port *ap) static void ahci_error_handler(struct ata_port *ap) { - void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR]; - void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); - if (!(ap->pflags & ATA_PFLAG_FROZEN)) { /* restart engine */ - ahci_stop_engine(port_mmio); - ahci_start_engine(port_mmio); + ahci_stop_engine(ap); + ahci_start_engine(ap); } /* perform recovery */ @@ -1410,13 +1409,10 @@ static void ahci_error_handler(struct ata_port *ap) static void ahci_vt8251_error_handler(struct ata_port *ap) { - void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR]; - void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); - if (!(ap->pflags & ATA_PFLAG_FROZEN)) { /* restart engine */ - ahci_stop_engine(port_mmio); - ahci_start_engine(port_mmio); + ahci_stop_engine(ap); + ahci_start_engine(ap); } /* perform recovery */ @@ -1427,33 +1423,26 @@ static void ahci_vt8251_error_handler(struct ata_port *ap) static void ahci_post_internal_cmd(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; - void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR]; - void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); if (qc->flags & ATA_QCFLAG_FAILED) { /* make DMA engine forget about the failed command */ - ahci_stop_engine(port_mmio); - ahci_start_engine(port_mmio); + ahci_stop_engine(ap); + ahci_start_engine(ap); } } #ifdef CONFIG_PM static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg) { - struct ahci_host_priv *hpriv = ap->host->private_data; - struct ahci_port_priv *pp = ap->private_data; - void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR]; - void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); const char *emsg = NULL; int rc; - rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg); + rc = ahci_deinit_port(ap, &emsg); if (rc == 0) - ahci_power_down(port_mmio, hpriv->cap); + ahci_power_down(ap); else { ata_port_printk(ap, KERN_ERR, "%s (%d)\n", emsg, rc); - ahci_init_port(port_mmio, hpriv->cap, - pp->cmd_slot_dma, pp->rx_fis_dma); + ahci_init_port(ap); } return rc; @@ -1461,13 +1450,8 @@ static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg) static int ahci_port_resume(struct ata_port *ap) { - struct ahci_port_priv *pp = ap->private_data; - struct ahci_host_priv *hpriv = ap->host->private_data; - void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR]; - void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); - - ahci_power_up(port_mmio, hpriv->cap); - ahci_init_port(port_mmio, hpriv->cap, pp->cmd_slot_dma, pp->rx_fis_dma); + ahci_power_up(ap); + ahci_init_port(ap); return 0; } @@ -1495,8 +1479,6 @@ static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg) static int ahci_pci_device_resume(struct pci_dev *pdev) { struct ata_host *host = dev_get_drvdata(&pdev->dev); - struct ahci_host_priv *hpriv = host->private_data; - void __iomem *mmio = host->iomap[AHCI_PCI_BAR]; int rc; rc = ata_pci_device_do_resume(pdev); @@ -1504,12 +1486,11 @@ static int ahci_pci_device_resume(struct pci_dev *pdev) return rc; if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { - rc = ahci_reset_controller(mmio, pdev, hpriv); + rc = ahci_reset_controller(host); if (rc) return rc; - ahci_init_controller(mmio, pdev, host->n_ports, - host->ports[0]->flags, hpriv); + ahci_init_controller(host); } ata_host_resume(host); @@ -1521,10 +1502,7 @@ static int ahci_pci_device_resume(struct pci_dev *pdev) static int ahci_port_start(struct ata_port *ap) { struct device *dev = ap->host->dev; - struct ahci_host_priv *hpriv = ap->host->private_data; struct ahci_port_priv *pp; - void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR]; - void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); void *mem; dma_addr_t mem_dma; int rc; @@ -1572,60 +1550,29 @@ static int ahci_port_start(struct ata_port *ap) ap->private_data = pp; /* power up port */ - ahci_power_up(port_mmio, hpriv->cap); + ahci_power_up(ap); /* initialize port */ - ahci_init_port(port_mmio, hpriv->cap, pp->cmd_slot_dma, pp->rx_fis_dma); + ahci_init_port(ap); return 0; } static void ahci_port_stop(struct ata_port *ap) { - struct ahci_host_priv *hpriv = ap->host->private_data; - void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR]; - void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); const char *emsg = NULL; int rc; /* de-initialize port */ - rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg); + rc = ahci_deinit_port(ap, &emsg); if (rc) ata_port_printk(ap, KERN_WARNING, "%s (%d)\n", emsg, rc); } -static void ahci_setup_port(struct ata_ioports *port, void __iomem *base, - unsigned int port_idx) +static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac) { - VPRINTK("ENTER, base==0x%lx, port_idx %u\n", base, port_idx); - base = ahci_port_base(base, port_idx); - VPRINTK("base now==0x%lx\n", base); - - port->cmd_addr = base; - port->scr_addr = base + PORT_SCR; - - VPRINTK("EXIT\n"); -} - -static int ahci_host_init(struct ata_probe_ent *probe_ent) -{ - struct ahci_host_priv *hpriv = probe_ent->private_data; - struct pci_dev *pdev = to_pci_dev(probe_ent->dev); - void __iomem *mmio = probe_ent->iomap[AHCI_PCI_BAR]; - unsigned int i, using_dac; int rc; - rc = ahci_reset_controller(mmio, pdev, hpriv); - if (rc) - return rc; - - probe_ent->n_ports = fls(hpriv->port_map); - probe_ent->dummy_port_mask = ~hpriv->port_map; - - VPRINTK("cap 0x%x port_map 0x%x n_ports %d\n", - hpriv->cap, hpriv->port_map, probe_ent->n_ports); - - using_dac = hpriv->cap & HOST_CAP_64; if (using_dac && !pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); @@ -1651,23 +1598,14 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent) return rc; } } - - for (i = 0; i < probe_ent->n_ports; i++) - ahci_setup_port(&probe_ent->port[i], mmio, i); - - ahci_init_controller(mmio, pdev, probe_ent->n_ports, - probe_ent->port_flags, hpriv); - - pci_set_master(pdev); - return 0; } -static void ahci_print_info(struct ata_probe_ent *probe_ent) +static void ahci_print_info(struct ata_host *host) { - struct ahci_host_priv *hpriv = probe_ent->private_data; - struct pci_dev *pdev = to_pci_dev(probe_ent->dev); - void __iomem *mmio = probe_ent->iomap[AHCI_PCI_BAR]; + struct ahci_host_priv *hpriv = host->private_data; + struct pci_dev *pdev = to_pci_dev(host->dev); + void __iomem *mmio = host->iomap[AHCI_PCI_BAR]; u32 vers, cap, impl, speed; const char *speed_s; u16 cc; @@ -1737,11 +1675,12 @@ static void ahci_print_info(struct ata_probe_ent *probe_ent) static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { static int printed_version; - unsigned int board_idx = (unsigned int) ent->driver_data; + struct ata_port_info pi = ahci_port_info[ent->driver_data]; + const struct ata_port_info *ppi[] = { &pi, NULL }; struct device *dev = &pdev->dev; - struct ata_probe_ent *probe_ent; struct ahci_host_priv *hpriv; - int rc; + struct ata_host *host; + int i, rc; VPRINTK("ENTER\n"); @@ -1750,6 +1689,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (!printed_version++) dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); + /* acquire resources */ rc = pcim_enable_device(pdev); if (rc) return rc; @@ -1763,46 +1703,49 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (pci_enable_msi(pdev)) pci_intx(pdev, 1); - probe_ent = devm_kzalloc(dev, sizeof(*probe_ent), GFP_KERNEL); - if (probe_ent == NULL) - return -ENOMEM; - - probe_ent->dev = pci_dev_to_dev(pdev); - INIT_LIST_HEAD(&probe_ent->node); - hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); if (!hpriv) return -ENOMEM; - probe_ent->sht = ahci_port_info[board_idx].sht; - probe_ent->port_flags = ahci_port_info[board_idx].flags; - probe_ent->pio_mask = ahci_port_info[board_idx].pio_mask; - probe_ent->udma_mask = ahci_port_info[board_idx].udma_mask; - probe_ent->port_ops = ahci_port_info[board_idx].port_ops; + /* save initial config */ + ahci_save_initial_config(pdev, &pi, hpriv); - probe_ent->irq = pdev->irq; - probe_ent->irq_flags = IRQF_SHARED; - probe_ent->iomap = pcim_iomap_table(pdev); - probe_ent->private_data = hpriv; + /* prepare host */ + if (!(pi.flags & AHCI_FLAG_NO_NCQ) && (hpriv->cap & HOST_CAP_NCQ)) + pi.flags |= ATA_FLAG_NCQ; - /* initialize adapter */ - ahci_save_initial_config(probe_ent); + host = ata_host_alloc_pinfo(&pdev->dev, ppi, fls(hpriv->port_map)); + if (!host) + return -ENOMEM; + host->iomap = pcim_iomap_table(pdev); + host->private_data = hpriv; + + for (i = 0; i < host->n_ports; i++) { + if (hpriv->port_map & (1 << i)) { + struct ata_port *ap = host->ports[i]; + void __iomem *port_mmio = ahci_port_base(ap); + + ap->ioaddr.cmd_addr = port_mmio; + ap->ioaddr.scr_addr = port_mmio + PORT_SCR; + } else + host->ports[i]->ops = &ata_dummy_port_ops; + } - rc = ahci_host_init(probe_ent); + /* initialize adapter */ + rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64); if (rc) return rc; - if (!(probe_ent->port_flags & AHCI_FLAG_NO_NCQ) && - (hpriv->cap & HOST_CAP_NCQ)) - probe_ent->port_flags |= ATA_FLAG_NCQ; - - ahci_print_info(probe_ent); + rc = ahci_reset_controller(host); + if (rc) + return rc; - if (!ata_device_add(probe_ent)) - return -ENODEV; + ahci_init_controller(host); + ahci_print_info(host); - devm_kfree(dev, probe_ent); - return 0; + pci_set_master(pdev); + return ata_host_activate(host, pdev->irq, ahci_interrupt, IRQF_SHARED, + &ahci_sht); } static int __init ahci_init(void) |