libata-pmp-prep: implement sata_async_notification()
[safe/jmp/linux-2.6] / drivers / ata / sata_sil24.c
index 2d8334e..b4f81eb 100644 (file)
@@ -168,7 +168,7 @@ enum {
 
        DEF_PORT_IRQ            = PORT_IRQ_COMPLETE | PORT_IRQ_ERROR |
                                  PORT_IRQ_PHYRDY_CHG | PORT_IRQ_DEV_XCHG |
-                                 PORT_IRQ_UNK_FIS,
+                                 PORT_IRQ_UNK_FIS | PORT_IRQ_SDB_NOTIFY,
 
        /* bits[27:16] are unmasked (raw) */
        PORT_IRQ_RAW_SHIFT      = 16,
@@ -237,8 +237,9 @@ enum {
        /* host flags */
        SIL24_COMMON_FLAGS      = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
                                  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
-                                 ATA_FLAG_NCQ | ATA_FLAG_SKIP_D2H_BSY |
-                                 ATA_FLAG_ACPI_SATA,
+                                 ATA_FLAG_NCQ | ATA_FLAG_ACPI_SATA |
+                                 ATA_FLAG_AN,
+       SIL24_COMMON_LFLAGS     = ATA_LFLAG_SKIP_D2H_BSY,
        SIL24_FLAG_PCIX_IRQ_WOC = (1 << 24), /* IRQ loss errata on PCI-X */
 
        IRQ_STAT_4PORTS         = 0xf,
@@ -384,8 +385,6 @@ static struct scsi_host_template sil24_sht = {
 };
 
 static const struct ata_port_operations sil24_ops = {
-       .port_disable           = ata_port_disable,
-
        .dev_config             = sil24_dev_config,
 
        .check_status           = sil24_check_status,
@@ -394,12 +393,11 @@ static const struct ata_port_operations sil24_ops = {
 
        .tf_read                = sil24_tf_read,
 
+       .qc_defer               = ata_std_qc_defer,
        .qc_prep                = sil24_qc_prep,
        .qc_issue               = sil24_qc_issue,
 
        .irq_clear              = sil24_irq_clear,
-       .irq_on                 = ata_dummy_irq_on,
-       .irq_ack                = ata_dummy_irq_ack,
 
        .scr_read               = sil24_scr_read,
        .scr_write              = sil24_scr_write,
@@ -424,6 +422,7 @@ static const struct ata_port_info sil24_port_info[] = {
        {
                .flags          = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(4) |
                                  SIL24_FLAG_PCIX_IRQ_WOC,
+               .link_flags     = SIL24_COMMON_LFLAGS,
                .pio_mask       = 0x1f,                 /* pio0-4 */
                .mwdma_mask     = 0x07,                 /* mwdma0-2 */
                .udma_mask      = ATA_UDMA5,            /* udma0-5 */
@@ -432,6 +431,7 @@ static const struct ata_port_info sil24_port_info[] = {
        /* sil_3132 */
        {
                .flags          = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(2),
+               .link_flags     = SIL24_COMMON_LFLAGS,
                .pio_mask       = 0x1f,                 /* pio0-4 */
                .mwdma_mask     = 0x07,                 /* mwdma0-2 */
                .udma_mask      = ATA_UDMA5,            /* udma0-5 */
@@ -440,6 +440,7 @@ static const struct ata_port_info sil24_port_info[] = {
        /* sil_3131/sil_3531 */
        {
                .flags          = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(1),
+               .link_flags     = SIL24_COMMON_LFLAGS,
                .pio_mask       = 0x1f,                 /* pio0-4 */
                .mwdma_mask     = 0x07,                 /* mwdma0-2 */
                .udma_mask      = ATA_UDMA5,            /* udma0-5 */
@@ -583,9 +584,10 @@ static int sil24_exec_polled_cmd(struct ata_port *ap, int pmp,
        return rc;
 }
 
-static int sil24_do_softreset(struct ata_port *ap, unsigned int *class,
+static int sil24_do_softreset(struct ata_link *link, unsigned int *class,
                              int pmp, unsigned long deadline)
 {
+       struct ata_port *ap = link->ap;
        unsigned long timeout_msec = 0;
        struct ata_taskfile tf;
        const char *reason;
@@ -593,7 +595,7 @@ static int sil24_do_softreset(struct ata_port *ap, unsigned int *class,
 
        DPRINTK("ENTER\n");
 
-       if (ata_port_offline(ap)) {
+       if (ata_link_offline(link)) {
                DPRINTK("PHY reports no device\n");
                *class = ATA_DEV_NONE;
                goto out;
@@ -609,7 +611,7 @@ static int sil24_do_softreset(struct ata_port *ap, unsigned int *class,
        if (time_after(deadline, jiffies))
                timeout_msec = jiffies_to_msecs(deadline - jiffies);
 
-       ata_tf_init(ap->link.device, &tf);      /* doesn't really matter */
+       ata_tf_init(link->device, &tf); /* doesn't really matter */
        rc = sil24_exec_polled_cmd(ap, pmp, &tf, 0, PRB_CTRL_SRST,
                                   timeout_msec);
        if (rc == -EBUSY) {
@@ -631,29 +633,30 @@ static int sil24_do_softreset(struct ata_port *ap, unsigned int *class,
        return 0;
 
  err:
-       ata_port_printk(ap, KERN_ERR, "softreset failed (%s)\n", reason);
+       ata_link_printk(link, KERN_ERR, "softreset failed (%s)\n", reason);
        return -EIO;
 }
 
-static int sil24_softreset(struct ata_port *ap, unsigned int *class,
+static int sil24_softreset(struct ata_link *link, unsigned int *class,
                           unsigned long deadline)
 {
-       return sil24_do_softreset(ap, class, 0, deadline);
+       return sil24_do_softreset(link, class, 0, deadline);
 }
 
-static int sil24_hardreset(struct ata_port *ap, unsigned int *class,
+static int sil24_hardreset(struct ata_link *link, unsigned int *class,
                           unsigned long deadline)
 {
+       struct ata_port *ap = link->ap;
        void __iomem *port = ap->ioaddr.cmd_addr;
        const char *reason;
        int tout_msec, rc;
        u32 tmp;
 
        /* sil24 does the right thing(tm) without any protection */
-       sata_set_spd(ap);
+       sata_set_spd(link);
 
        tout_msec = 100;
-       if (ata_port_online(ap))
+       if (ata_link_online(link))
                tout_msec = 5000;
 
        writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT);
@@ -663,14 +666,14 @@ static int sil24_hardreset(struct ata_port *ap, unsigned int *class,
        /* SStatus oscillates between zero and valid status after
         * DEV_RST, debounce it.
         */
-       rc = sata_phy_debounce(ap, sata_deb_timing_long, deadline);
+       rc = sata_link_debounce(link, sata_deb_timing_long, deadline);
        if (rc) {
                reason = "PHY debouncing failed";
                goto err;
        }
 
        if (tmp & PORT_CS_DEV_RST) {
-               if (ata_port_offline(ap))
+               if (ata_link_offline(link))
                        return 0;
                reason = "link not ready";
                goto err;
@@ -685,7 +688,7 @@ static int sil24_hardreset(struct ata_port *ap, unsigned int *class,
        return -EAGAIN;
 
  err:
-       ata_port_printk(ap, KERN_ERR, "hardreset failed (%s)\n", reason);
+       ata_link_printk(link, KERN_ERR, "hardreset failed (%s)\n", reason);
        return -EIO;
 }
 
@@ -817,6 +820,11 @@ static void sil24_error_intr(struct ata_port *ap)
 
        ata_ehi_push_desc(ehi, "irq_stat 0x%08x", irq_stat);
 
+       if (irq_stat & PORT_IRQ_SDB_NOTIFY) {
+               ata_ehi_push_desc(ehi, "SDB notify");
+               sata_async_notification(ap);
+       }
+
        if (irq_stat & (PORT_IRQ_PHYRDY_CHG | PORT_IRQ_DEV_XCHG)) {
                ata_ehi_hotplugged(ehi);
                ata_ehi_push_desc(ehi, "%s",
@@ -1118,12 +1126,15 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        host->iomap = iomap;
 
        for (i = 0; i < host->n_ports; i++) {
-               void __iomem *port = iomap[SIL24_PORT_BAR] + i * PORT_REGS_SIZE;
+               struct ata_port *ap = host->ports[i];
+               size_t offset = ap->port_no * PORT_REGS_SIZE;
+               void __iomem *port = iomap[SIL24_PORT_BAR] + offset;
 
                host->ports[i]->ioaddr.cmd_addr = port;
                host->ports[i]->ioaddr.scr_addr = port + PORT_SCONTROL;
 
-               ata_std_ports(&host->ports[i]->ioaddr);
+               ata_port_pbar_desc(ap, SIL24_HOST_BAR, -1, "host");
+               ata_port_pbar_desc(ap, SIL24_PORT_BAR, offset, "port");
        }
 
        /* configure and activate the device */