-static void ahci_freeze(struct ata_port *ap)
-{
- void __iomem *mmio = ap->host_set->mmio_base;
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
-
- /* turn IRQ off */
- writel(0, port_mmio + PORT_IRQ_MASK);
-}
-
-static void ahci_thaw(struct ata_port *ap)
-{
- void __iomem *mmio = ap->host_set->mmio_base;
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
- u32 tmp;
-
- /* clear IRQ */
- tmp = readl(port_mmio + PORT_IRQ_STAT);
- writel(tmp, port_mmio + PORT_IRQ_STAT);
- writel(1 << ap->id, mmio + HOST_IRQ_STAT);
-
- /* turn IRQ back on */
- writel(DEF_PORT_IRQ, port_mmio + PORT_IRQ_MASK);
-}
-
-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)) {
- /* restart engine */
- ahci_stop_engine(port_mmio);
- ahci_start_engine(port_mmio);
- }
-
- /* perform recovery */
- ata_do_eh(ap, ahci_prereset, ahci_softreset, ahci_hardreset,
- ahci_postreset);
-}
-
-static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
-{
- 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)
- qc->err_mask |= AC_ERR_OTHER;
-
- if (qc->err_mask) {
- /* make DMA engine forget about the failed command */
- ahci_stop_engine(port_mmio);
- ahci_start_engine(port_mmio);
- }
-}
-
-static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
-{
- 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 char *emsg = NULL;
- int rc;
-
- rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg);
- if (rc) {
- 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);
- }
-
- return rc;
-}
-
-static int ahci_port_resume(struct ata_port *ap)
-{
- struct ahci_port_priv *pp = ap->private_data;
- struct ahci_host_priv *hpriv = ap->host_set->private_data;
- void __iomem *mmio = ap->host_set->mmio_base;
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
-
- ahci_init_port(port_mmio, hpriv->cap, pp->cmd_slot_dma, pp->rx_fis_dma);
-
- return 0;
-}
-
-static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
-{
- struct ata_host_set *host_set = dev_get_drvdata(&pdev->dev);
- void __iomem *mmio = host_set->mmio_base;
- u32 ctl;
-
- if (mesg.event == PM_EVENT_SUSPEND) {
- /* AHCI spec rev1.1 section 8.3.3:
- * Software must disable interrupts prior to requesting a
- * transition of the HBA to D3 state.
- */
- ctl = readl(mmio + HOST_CTL);
- ctl &= ~HOST_IRQ_EN;
- writel(ctl, mmio + HOST_CTL);
- readl(mmio + HOST_CTL); /* flush */
- }
-
- return ata_pci_device_suspend(pdev, mesg);
-}
-
-static int ahci_pci_device_resume(struct pci_dev *pdev)
-{
- struct ata_host_set *host_set = dev_get_drvdata(&pdev->dev);
- struct ahci_host_priv *hpriv = host_set->private_data;
- void __iomem *mmio = host_set->mmio_base;
- int rc;
-
- ata_pci_device_do_resume(pdev);
-
- if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
- rc = ahci_reset_controller(mmio, pdev);
- if (rc)
- return rc;
-
- ahci_init_controller(mmio, pdev, host_set->n_ports, hpriv->cap);
- }
-
- ata_host_set_resume(host_set);
-
- return 0;
-}
-
-static int ahci_port_start(struct ata_port *ap)
-{
- struct device *dev = ap->host_set->dev;
- struct ahci_host_priv *hpriv = ap->host_set->private_data;
- struct ahci_port_priv *pp;
- void __iomem *mmio = ap->host_set->mmio_base;
- void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
- void *mem;
- dma_addr_t mem_dma;
- int rc;
-
- pp = kmalloc(sizeof(*pp), GFP_KERNEL);
- if (!pp)
- return -ENOMEM;
- memset(pp, 0, sizeof(*pp));
-
- rc = ata_pad_alloc(ap, dev);
- if (rc) {
- kfree(pp);
- return rc;
- }
-
- mem = dma_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma, GFP_KERNEL);
- if (!mem) {
- ata_pad_free(ap, dev);
- kfree(pp);
- return -ENOMEM;
- }
- memset(mem, 0, AHCI_PORT_PRIV_DMA_SZ);
-
- /*
- * First item in chunk of DMA memory: 32-slot command table,
- * 32 bytes each in size
- */
- pp->cmd_slot = mem;
- pp->cmd_slot_dma = mem_dma;
-
- mem += AHCI_CMD_SLOT_SZ;
- mem_dma += AHCI_CMD_SLOT_SZ;
-
- /*
- * Second item: Received-FIS area
- */
- pp->rx_fis = mem;
- pp->rx_fis_dma = mem_dma;
-
- mem += AHCI_RX_FIS_SZ;
- mem_dma += AHCI_RX_FIS_SZ;
-
- /*
- * Third item: data area for storing a single command
- * and its scatter-gather table
- */
- pp->cmd_tbl = mem;
- pp->cmd_tbl_dma = mem_dma;
-
- ap->private_data = pp;
-
- /* initialize port */
- ahci_init_port(port_mmio, hpriv->cap, pp->cmd_slot_dma, pp->rx_fis_dma);
-
- return 0;
-}
-
-static void ahci_port_stop(struct ata_port *ap)
-{
- struct device *dev = ap->host_set->dev;
- 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 char *emsg = NULL;
- int rc;
-
- /* de-initialize port */
- rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg);
- if (rc)
- ata_port_printk(ap, KERN_WARNING, "%s (%d)\n", emsg, 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);
-}
-