Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=02a121da5a53d415b6596bc19cc6999d295d32a4
Commit:     02a121da5a53d415b6596bc19cc6999d295d32a4
Parent:     0f9fe9b7148f95f018ae2c97f7fa1a35364ea785
Author:     Mark Lord <[EMAIL PROTECTED]>
AuthorDate: Sat Dec 1 13:07:22 2007 -0500
Committer:  Jeff Garzik <[EMAIL PROTECTED]>
CommitDate: Sat Dec 1 17:44:10 2007 -0500

    sata_mv: Fix broken Marvell 7042 support.
    
    sata_mv:  Fix broken Marvell 7042 support.
    
    The Marvell 7042 chip is more or less the same as the 6042 internally,
    but sports a PCIe bus.  Despite having identical SATA cores, the 7042
    does differ from its PCI bus counterparts in placment and layout of
    certain bus related registers.
    
    This patch fixes sata_mv to distinguish between the PCI bus registers
    of earlier chips, and the PCIe bus registers of the 7042.
    
    Specifically, move the offsets and bit patterns for the
    PCI/PCIe interrupt cause/mask registers into the struct mv_host_priv,
    as these values differ between the 6xxx and 7xxx series chips.
    
    This fixes the driver to not access reserved PCI addresses,
    and prevents the lockups reported in linux-2.6.24 with 7042 boards.
    
    Also add a new PCI ID for the Highpoint 2300 7042-based board
    that I'm using for testing this stuff here.
    
    Tested with Marvell 6081 + 7042 chips, on x86 & x86_64.
    
    Signed-off-by: Mark Lord <[EMAIL PROTECTED]>
    Signed-off-by: Jeff Garzik <[EMAIL PROTECTED]>
---
 drivers/ata/sata_mv.c |   62 +++++++++++++++++++++++++++++++++---------------
 1 files changed, 42 insertions(+), 20 deletions(-)

diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index 97c3e11..8d864e5 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -164,10 +164,14 @@ enum {
        MV_PCI_ERR_ATTRIBUTE    = 0x1d48,
        MV_PCI_ERR_COMMAND      = 0x1d50,
 
-       PCI_IRQ_CAUSE_OFS               = 0x1d58,
-       PCI_IRQ_MASK_OFS                = 0x1d5c,
+       PCI_IRQ_CAUSE_OFS       = 0x1d58,
+       PCI_IRQ_MASK_OFS        = 0x1d5c,
        PCI_UNMASK_ALL_IRQS     = 0x7fffff,     /* bits 22-0 */
 
+       PCIE_IRQ_CAUSE_OFS      = 0x1900,
+       PCIE_IRQ_MASK_OFS       = 0x1910,
+       PCIE_UNMASK_ALL_IRQS    = 0x70a,        /* assorted bits */
+
        HC_MAIN_IRQ_CAUSE_OFS   = 0x1d60,
        HC_MAIN_IRQ_MASK_OFS    = 0x1d64,
        PORT0_ERR               = (1 << 0),     /* shift by port # */
@@ -303,6 +307,7 @@ enum {
        MV_HP_GEN_I             = (1 << 6),     /* Generation I: 50xx */
        MV_HP_GEN_II            = (1 << 7),     /* Generation II: 60xx */
        MV_HP_GEN_IIE           = (1 << 8),     /* Generation IIE: 6042/7042 */
+       MV_HP_PCIE              = (1 << 9),     /* PCIe bus/regs: 7042 */
 
        /* Port private flags (pp_flags) */
        MV_PP_FLAG_EDMA_EN      = (1 << 0),     /* is EDMA engine enabled? */
@@ -388,7 +393,15 @@ struct mv_port_signal {
        u32                     pre;
 };
 
-struct mv_host_priv;
+struct mv_host_priv {
+       u32                     hp_flags;
+       struct mv_port_signal   signal[8];
+       const struct mv_hw_ops  *ops;
+       u32                     irq_cause_ofs;
+       u32                     irq_mask_ofs;
+       u32                     unmask_all_irqs;
+};
+
 struct mv_hw_ops {
        void (*phy_errata)(struct mv_host_priv *hpriv, void __iomem *mmio,
                           unsigned int port);
@@ -401,12 +414,6 @@ struct mv_hw_ops {
        void (*reset_bus)(struct pci_dev *pdev, void __iomem *mmio);
 };
 
-struct mv_host_priv {
-       u32                     hp_flags;
-       struct mv_port_signal   signal[8];
-       const struct mv_hw_ops  *ops;
-};
-
 static void mv_irq_clear(struct ata_port *ap);
 static int mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val);
 static int mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
@@ -631,11 +638,13 @@ static const struct pci_device_id mv_pci_tbl[] = {
        /* Adaptec 1430SA */
        { PCI_VDEVICE(ADAPTEC2, 0x0243), chip_7042 },
 
-       { PCI_VDEVICE(TTI, 0x2310), chip_7042 },
-
-       /* add Marvell 7042 support */
+       /* Marvell 7042 support */
        { PCI_VDEVICE(MARVELL, 0x7042), chip_7042 },
 
+       /* Highpoint RocketRAID PCIe series */
+       { PCI_VDEVICE(TTI, 0x2300), chip_7042 },
+       { PCI_VDEVICE(TTI, 0x2310), chip_7042 },
+
        { }                     /* terminate list */
 };
 
@@ -1648,13 +1657,14 @@ static void mv_host_intr(struct ata_host *host, u32 
relevant, unsigned int hc)
 
 static void mv_pci_error(struct ata_host *host, void __iomem *mmio)
 {
+       struct mv_host_priv *hpriv = host->private_data;
        struct ata_port *ap;
        struct ata_queued_cmd *qc;
        struct ata_eh_info *ehi;
        unsigned int i, err_mask, printed = 0;
        u32 err_cause;
 
-       err_cause = readl(mmio + PCI_IRQ_CAUSE_OFS);
+       err_cause = readl(mmio + hpriv->irq_cause_ofs);
 
        dev_printk(KERN_ERR, host->dev, "PCI ERROR; PCI IRQ cause=0x%08x\n",
                   err_cause);
@@ -1662,7 +1672,7 @@ static void mv_pci_error(struct ata_host *host, void 
__iomem *mmio)
        DPRINTK("All regs @ PCI error\n");
        mv_dump_all_regs(mmio, -1, to_pci_dev(host->dev));
 
-       writelfl(0, mmio + PCI_IRQ_CAUSE_OFS);
+       writelfl(0, mmio + hpriv->irq_cause_ofs);
 
        for (i = 0; i < host->n_ports; i++) {
                ap = host->ports[i];
@@ -1926,6 +1936,8 @@ static int mv5_reset_hc(struct mv_host_priv *hpriv, void 
__iomem *mmio,
 #define ZERO(reg) writel(0, mmio + (reg))
 static void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio)
 {
+       struct ata_host     *host = dev_get_drvdata(&pdev->dev);
+       struct mv_host_priv *hpriv = host->private_data;
        u32 tmp;
 
        tmp = readl(mmio + MV_PCI_MODE);
@@ -1937,8 +1949,8 @@ static void mv_reset_pci_bus(struct pci_dev *pdev, void 
__iomem *mmio)
        writel(0x000100ff, mmio + MV_PCI_XBAR_TMOUT);
        ZERO(HC_MAIN_IRQ_MASK_OFS);
        ZERO(MV_PCI_SERR_MASK);
-       ZERO(PCI_IRQ_CAUSE_OFS);
-       ZERO(PCI_IRQ_MASK_OFS);
+       ZERO(hpriv->irq_cause_ofs);
+       ZERO(hpriv->irq_mask_ofs);
        ZERO(MV_PCI_ERR_LOW_ADDRESS);
        ZERO(MV_PCI_ERR_HIGH_ADDRESS);
        ZERO(MV_PCI_ERR_ATTRIBUTE);
@@ -2490,6 +2502,7 @@ static int mv_chip_id(struct ata_host *host, unsigned int 
board_idx)
                break;
 
        case chip_7042:
+               hp_flags |= MV_HP_PCIE;
        case chip_6042:
                hpriv->ops = &mv6xxx_ops;
                hp_flags |= MV_HP_GEN_IIE;
@@ -2516,6 +2529,15 @@ static int mv_chip_id(struct ata_host *host, unsigned 
int board_idx)
        }
 
        hpriv->hp_flags = hp_flags;
+       if (hp_flags & MV_HP_PCIE) {
+               hpriv->irq_cause_ofs    = PCIE_IRQ_CAUSE_OFS;
+               hpriv->irq_mask_ofs     = PCIE_IRQ_MASK_OFS;
+               hpriv->unmask_all_irqs  = PCIE_UNMASK_ALL_IRQS;
+       } else {
+               hpriv->irq_cause_ofs    = PCI_IRQ_CAUSE_OFS;
+               hpriv->irq_mask_ofs     = PCI_IRQ_MASK_OFS;
+               hpriv->unmask_all_irqs  = PCI_UNMASK_ALL_IRQS;
+       }
 
        return 0;
 }
@@ -2595,10 +2617,10 @@ static int mv_init_host(struct ata_host *host, unsigned 
int board_idx)
        }
 
        /* Clear any currently outstanding host interrupt conditions */
-       writelfl(0, mmio + PCI_IRQ_CAUSE_OFS);
+       writelfl(0, mmio + hpriv->irq_cause_ofs);
 
        /* and unmask interrupt generation for host regs */
-       writelfl(PCI_UNMASK_ALL_IRQS, mmio + PCI_IRQ_MASK_OFS);
+       writelfl(hpriv->unmask_all_irqs, mmio + hpriv->irq_mask_ofs);
 
        if (IS_GEN_I(hpriv))
                writelfl(~HC_MAIN_MASKED_IRQS_5, mmio + HC_MAIN_IRQ_MASK_OFS);
@@ -2609,8 +2631,8 @@ static int mv_init_host(struct ata_host *host, unsigned 
int board_idx)
                "PCI int cause/mask=0x%08x/0x%08x\n",
                readl(mmio + HC_MAIN_IRQ_CAUSE_OFS),
                readl(mmio + HC_MAIN_IRQ_MASK_OFS),
-               readl(mmio + PCI_IRQ_CAUSE_OFS),
-               readl(mmio + PCI_IRQ_MASK_OFS));
+               readl(mmio + hpriv->irq_cause_ofs),
+               readl(mmio + hpriv->irq_mask_ofs));
 
 done:
        return rc;
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to