Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
[safe/jmp/linux-2.6] / drivers / ata / sata_sil24.c
index 79952f8..4621807 100644 (file)
@@ -336,15 +336,12 @@ static struct sil24_cerr_info {
 struct sil24_port_priv {
        union sil24_cmd_block *cmd_block;       /* 32 cmd blocks */
        dma_addr_t cmd_block_dma;               /* DMA base addr for them */
-       struct ata_taskfile tf;                 /* Cached taskfile registers */
        int do_port_rst;
 };
 
 static void sil24_dev_config(struct ata_device *dev);
-static u8 sil24_check_status(struct ata_port *ap);
-static int sil24_scr_read(struct ata_port *ap, unsigned sc_reg, u32 *val);
-static int sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val);
-static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
+static int sil24_scr_read(struct ata_link *link, unsigned sc_reg, u32 *val);
+static int sil24_scr_write(struct ata_link *link, unsigned sc_reg, u32 val);
 static int sil24_qc_defer(struct ata_queued_cmd *qc);
 static void sil24_qc_prep(struct ata_queued_cmd *qc);
 static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc);
@@ -357,8 +354,6 @@ static int sil24_softreset(struct ata_link *link, unsigned int *class,
                           unsigned long deadline);
 static int sil24_hardreset(struct ata_link *link, unsigned int *class,
                           unsigned long deadline);
-static int sil24_pmp_softreset(struct ata_link *link, unsigned int *class,
-                              unsigned long deadline);
 static int sil24_pmp_hardreset(struct ata_link *link, unsigned int *class,
                               unsigned long deadline);
 static void sil24_error_handler(struct ata_port *ap);
@@ -375,6 +370,7 @@ static const struct pci_device_id sil24_pci_tbl[] = {
        { PCI_VDEVICE(INTEL, 0x3124), BID_SIL3124 },
        { PCI_VDEVICE(CMD, 0x3132), BID_SIL3132 },
        { PCI_VDEVICE(CMD, 0x0242), BID_SIL3132 },
+       { PCI_VDEVICE(CMD, 0x0244), BID_SIL3132 },
        { PCI_VDEVICE(CMD, 0x3131), BID_SIL3131 },
        { PCI_VDEVICE(CMD, 0x3531), BID_SIL3131 },
 
@@ -402,9 +398,6 @@ static struct scsi_host_template sil24_sht = {
 static struct ata_port_operations sil24_ops = {
        .inherits               = &sata_pmp_port_ops,
 
-       .sff_check_status       = sil24_check_status,
-       .sff_check_altstatus    = sil24_check_status,
-       .sff_tf_read            = sil24_tf_read,
        .qc_defer               = sil24_qc_defer,
        .qc_prep                = sil24_qc_prep,
        .qc_issue               = sil24_qc_issue,
@@ -414,7 +407,7 @@ static struct ata_port_operations sil24_ops = {
        .thaw                   = sil24_thaw,
        .softreset              = sil24_softreset,
        .hardreset              = sil24_hardreset,
-       .pmp_softreset          = sil24_pmp_softreset,
+       .pmp_softreset          = sil24_softreset,
        .pmp_hardreset          = sil24_pmp_hardreset,
        .error_handler          = sil24_error_handler,
        .post_internal_cmd      = sil24_post_internal_cmd,
@@ -473,9 +466,19 @@ static int sil24_tag(int tag)
        return tag;
 }
 
+static unsigned long sil24_port_offset(struct ata_port *ap)
+{
+       return ap->port_no * PORT_REGS_SIZE;
+}
+
+static void __iomem *sil24_port_base(struct ata_port *ap)
+{
+       return ap->host->iomap[SIL24_PORT_BAR] + sil24_port_offset(ap);
+}
+
 static void sil24_dev_config(struct ata_device *dev)
 {
-       void __iomem *port = dev->link->ap->ioaddr.cmd_addr;
+       void __iomem *port = sil24_port_base(dev->link->ap);
 
        if (dev->cdb_len == 16)
                writel(PORT_CS_CDB16, port + PORT_CTRL_STAT);
@@ -485,7 +488,7 @@ static void sil24_dev_config(struct ata_device *dev)
 
 static void sil24_read_tf(struct ata_port *ap, int tag, struct ata_taskfile *tf)
 {
-       void __iomem *port = ap->ioaddr.cmd_addr;
+       void __iomem *port = sil24_port_base(ap);
        struct sil24_prb __iomem *prb;
        u8 fis[6 * 4];
 
@@ -494,12 +497,6 @@ static void sil24_read_tf(struct ata_port *ap, int tag, struct ata_taskfile *tf)
        ata_tf_from_fis(fis, tf);
 }
 
-static u8 sil24_check_status(struct ata_port *ap)
-{
-       struct sil24_port_priv *pp = ap->private_data;
-       return pp->tf.command;
-}
-
 static int sil24_scr_map[] = {
        [SCR_CONTROL]   = 0,
        [SCR_STATUS]    = 1,
@@ -507,9 +504,9 @@ static int sil24_scr_map[] = {
        [SCR_ACTIVE]    = 3,
 };
 
-static int sil24_scr_read(struct ata_port *ap, unsigned sc_reg, u32 *val)
+static int sil24_scr_read(struct ata_link *link, unsigned sc_reg, u32 *val)
 {
-       void __iomem *scr_addr = ap->ioaddr.scr_addr;
+       void __iomem *scr_addr = sil24_port_base(link->ap) + PORT_SCONTROL;
 
        if (sc_reg < ARRAY_SIZE(sil24_scr_map)) {
                void __iomem *addr;
@@ -520,9 +517,9 @@ static int sil24_scr_read(struct ata_port *ap, unsigned sc_reg, u32 *val)
        return -EINVAL;
 }
 
-static int sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val)
+static int sil24_scr_write(struct ata_link *link, unsigned sc_reg, u32 val)
 {
-       void __iomem *scr_addr = ap->ioaddr.scr_addr;
+       void __iomem *scr_addr = sil24_port_base(link->ap) + PORT_SCONTROL;
 
        if (sc_reg < ARRAY_SIZE(sil24_scr_map)) {
                void __iomem *addr;
@@ -533,15 +530,9 @@ static int sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val)
        return -EINVAL;
 }
 
-static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
-{
-       struct sil24_port_priv *pp = ap->private_data;
-       *tf = pp->tf;
-}
-
 static void sil24_config_port(struct ata_port *ap)
 {
-       void __iomem *port = ap->ioaddr.cmd_addr;
+       void __iomem *port = sil24_port_base(ap);
 
        /* configure IRQ WoC */
        if (ap->flags & SIL24_FLAG_PCIX_IRQ_WOC)
@@ -566,7 +557,7 @@ static void sil24_config_port(struct ata_port *ap)
 
 static void sil24_config_pmp(struct ata_port *ap, int attached)
 {
-       void __iomem *port = ap->ioaddr.cmd_addr;
+       void __iomem *port = sil24_port_base(ap);
 
        if (attached)
                writel(PORT_CS_PMP_EN, port + PORT_CTRL_STAT);
@@ -576,7 +567,7 @@ static void sil24_config_pmp(struct ata_port *ap, int attached)
 
 static void sil24_clear_pmp(struct ata_port *ap)
 {
-       void __iomem *port = ap->ioaddr.cmd_addr;
+       void __iomem *port = sil24_port_base(ap);
        int i;
 
        writel(PORT_CS_PMP_RESUME, port + PORT_CTRL_CLR);
@@ -591,12 +582,12 @@ static void sil24_clear_pmp(struct ata_port *ap)
 
 static int sil24_init_port(struct ata_port *ap)
 {
-       void __iomem *port = ap->ioaddr.cmd_addr;
+       void __iomem *port = sil24_port_base(ap);
        struct sil24_port_priv *pp = ap->private_data;
        u32 tmp;
 
        /* clear PMP error status */
-       if (ap->nr_pmp_links)
+       if (sata_pmp_attached(ap))
                sil24_clear_pmp(ap);
 
        writel(PORT_CS_INIT, port + PORT_CTRL_STAT);
@@ -619,7 +610,7 @@ static int sil24_exec_polled_cmd(struct ata_port *ap, int pmp,
                                 int is_cmd, u32 ctrl,
                                 unsigned long timeout_msec)
 {
-       void __iomem *port = ap->ioaddr.cmd_addr;
+       void __iomem *port = sil24_port_base(ap);
        struct sil24_port_priv *pp = ap->private_data;
        struct sil24_prb *prb = &pp->cmd_block[0].ata.prb;
        dma_addr_t paddr = pp->cmd_block_dma;
@@ -661,10 +652,11 @@ static int sil24_exec_polled_cmd(struct ata_port *ap, int pmp,
        return rc;
 }
 
-static int sil24_do_softreset(struct ata_link *link, unsigned int *class,
-                             int pmp, unsigned long deadline)
+static int sil24_softreset(struct ata_link *link, unsigned int *class,
+                          unsigned long deadline)
 {
        struct ata_port *ap = link->ap;
+       int pmp = sata_srst_pmp(link);
        unsigned long timeout_msec = 0;
        struct ata_taskfile tf;
        const char *reason;
@@ -672,12 +664,6 @@ static int sil24_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;
-               goto out;
-       }
-
        /* put the port into known state */
        if (sil24_init_port(ap)) {
                reason = "port not ready";
@@ -702,10 +688,6 @@ static int sil24_do_softreset(struct ata_link *link, unsigned int *class,
        sil24_read_tf(ap, 0, &tf);
        *class = ata_dev_classify(&tf);
 
-       if (*class == ATA_DEV_UNKNOWN)
-               *class = ATA_DEV_NONE;
-
- out:
        DPRINTK("EXIT, class=%u\n", *class);
        return 0;
 
@@ -714,17 +696,11 @@ static int sil24_do_softreset(struct ata_link *link, unsigned int *class,
        return -EIO;
 }
 
-static int sil24_softreset(struct ata_link *link, unsigned int *class,
-                          unsigned long deadline)
-{
-       return sil24_do_softreset(link, class, SATA_PMP_CTRL_PORT, deadline);
-}
-
 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;
+       void __iomem *port = sil24_port_base(ap);
        struct sil24_port_priv *pp = ap->private_data;
        int did_port_rst = 0;
        const char *reason;
@@ -902,7 +878,7 @@ static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
        struct sil24_port_priv *pp = ap->private_data;
-       void __iomem *port = ap->ioaddr.cmd_addr;
+       void __iomem *port = sil24_port_base(ap);
        unsigned int tag = sil24_tag(qc->tag);
        dma_addr_t paddr;
        void __iomem *activate;
@@ -924,20 +900,25 @@ static bool sil24_qc_fill_rtf(struct ata_queued_cmd *qc)
 
 static void sil24_pmp_attach(struct ata_port *ap)
 {
+       u32 *gscr = ap->link.device->gscr;
+
        sil24_config_pmp(ap, 1);
        sil24_init_port(ap);
+
+       if (sata_pmp_gscr_vendor(gscr) == 0x11ab &&
+           sata_pmp_gscr_devid(gscr) == 0x4140) {
+               ata_port_printk(ap, KERN_INFO,
+                       "disabling NCQ support due to sil24-mv4140 quirk\n");
+               ap->flags &= ~ATA_FLAG_NCQ;
+       }
 }
 
 static void sil24_pmp_detach(struct ata_port *ap)
 {
        sil24_init_port(ap);
        sil24_config_pmp(ap, 0);
-}
 
-static int sil24_pmp_softreset(struct ata_link *link, unsigned int *class,
-                              unsigned long deadline)
-{
-       return sil24_do_softreset(link, class, link->pmp, deadline);
+       ap->flags |= ATA_FLAG_NCQ;
 }
 
 static int sil24_pmp_hardreset(struct ata_link *link, unsigned int *class,
@@ -957,7 +938,7 @@ static int sil24_pmp_hardreset(struct ata_link *link, unsigned int *class,
 
 static void sil24_freeze(struct ata_port *ap)
 {
-       void __iomem *port = ap->ioaddr.cmd_addr;
+       void __iomem *port = sil24_port_base(ap);
 
        /* Port-wide IRQ mask in HOST_CTRL doesn't really work, clear
         * PORT_IRQ_ENABLE instead.
@@ -967,7 +948,7 @@ static void sil24_freeze(struct ata_port *ap)
 
 static void sil24_thaw(struct ata_port *ap)
 {
-       void __iomem *port = ap->ioaddr.cmd_addr;
+       void __iomem *port = sil24_port_base(ap);
        u32 tmp;
 
        /* clear IRQ */
@@ -980,7 +961,7 @@ static void sil24_thaw(struct ata_port *ap)
 
 static void sil24_error_intr(struct ata_port *ap)
 {
-       void __iomem *port = ap->ioaddr.cmd_addr;
+       void __iomem *port = sil24_port_base(ap);
        struct sil24_port_priv *pp = ap->private_data;
        struct ata_queued_cmd *qc = NULL;
        struct ata_link *link;
@@ -1042,7 +1023,7 @@ static void sil24_error_intr(struct ata_port *ap)
                }
 
                /* find out the offending link and qc */
-               if (ap->nr_pmp_links) {
+               if (sata_pmp_attached(ap)) {
                        context = readl(port + PORT_CONTEXT);
                        pmp = (context >> 5) & 0xf;
 
@@ -1082,16 +1063,15 @@ static void sil24_error_intr(struct ata_port *ap)
                }
 
                /* record error info */
-               if (qc) {
-                       sil24_read_tf(ap, qc->tag, &pp->tf);
+               if (qc)
                        qc->err_mask |= err_mask;
-               else
+               else
                        ehi->err_mask |= err_mask;
 
                ehi->action |= action;
 
                /* if PMP, resume */
-               if (ap->nr_pmp_links)
+               if (sata_pmp_attached(ap))
                        writel(PORT_CS_PMP_RESUME, port + PORT_CTRL_STAT);
        }
 
@@ -1108,7 +1088,7 @@ static void sil24_error_intr(struct ata_port *ap)
 
 static inline void sil24_host_intr(struct ata_port *ap)
 {
-       void __iomem *port = ap->ioaddr.cmd_addr;
+       void __iomem *port = sil24_port_base(ap);
        u32 slot_stat, qc_active;
        int rc;
 
@@ -1218,8 +1198,6 @@ static int sil24_port_start(struct ata_port *ap)
        if (!pp)
                return -ENOMEM;
 
-       pp->tf.command = ATA_DRDY;
-
        cb = dmam_alloc_coherent(dev, cb_size, &cb_dma, GFP_KERNEL);
        if (!cb)
                return -ENOMEM;
@@ -1230,6 +1208,9 @@ static int sil24_port_start(struct ata_port *ap)
 
        ap->private_data = pp;
 
+       ata_port_pbar_desc(ap, SIL24_HOST_BAR, -1, "host");
+       ata_port_pbar_desc(ap, SIL24_PORT_BAR, sil24_port_offset(ap), "port");
+
        return 0;
 }
 
@@ -1248,7 +1229,8 @@ static void sil24_init_controller(struct ata_host *host)
        /* init ports */
        for (i = 0; i < host->n_ports; i++) {
                struct ata_port *ap = host->ports[i];
-               void __iomem *port = ap->ioaddr.cmd_addr;
+               void __iomem *port = sil24_port_base(ap);
+
 
                /* Initial PHY setting */
                writel(0x20c, port + PORT_PHY_CFG);
@@ -1281,7 +1263,7 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        const struct ata_port_info *ppi[] = { &pi, NULL };
        void __iomem * const *iomap;
        struct ata_host *host;
-       int i, rc;
+       int rc;
        u32 tmp;
 
        /* cause link error if sil24_cmd_block is sized wrongly */
@@ -1321,18 +1303,6 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                return -ENOMEM;
        host->iomap = iomap;
 
-       for (i = 0; i < host->n_ports; i++) {
-               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_port_pbar_desc(ap, SIL24_HOST_BAR, -1, "host");
-               ata_port_pbar_desc(ap, SIL24_PORT_BAR, offset, "port");
-       }
-
        /* configure and activate the device */
        if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
                rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);