pata_hpt{37x|3x2n}: SATA mode filtering
authorSergei Shtylyov <sshtylyov@ru.mvista.com>
Sat, 25 Dec 2010 19:44:01 +0000 (22:44 +0300)
committerJeff Garzik <jgarzik@redhat.com>
Sat, 8 Jan 2011 03:33:10 +0000 (22:33 -0500)
The Marvell bridge chips used on HighPoint SATA cards do not seem to support
the UltraDMA modes 1, 2, and 3 as well as any MWDMA modes;  these cards are
based on HPT372/372A/372N/374 chips (judging from the vendor drivers), so
the Linux drivers need to have a mode_filter() method for these chips...

Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
drivers/ata/pata_hpt37x.c
drivers/ata/pata_hpt3x2n.c

index 9ae4c08305779a4cad19fbe466eb1ab48bc3053b..9c62951c3e26b0e4b7627af638cfb7d2137ba964 100644 (file)
@@ -8,7 +8,7 @@
  * Copyright (C) 1999-2003             Andre Hedrick <andre@linux-ide.org>
  * Portions Copyright (C) 2001         Sun Microsystems, Inc.
  * Portions Copyright (C) 2003         Red Hat Inc
- * Portions Copyright (C) 2005-2009    MontaVista Software, Inc.
+ * Portions Copyright (C) 2005-2010    MontaVista Software, Inc.
  *
  * TODO
  *     Look into engine reset on timeout errors. Should not be required.
@@ -24,7 +24,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME       "pata_hpt37x"
-#define DRV_VERSION    "0.6.15"
+#define DRV_VERSION    "0.6.16"
 
 struct hpt_clock {
        u8      xfer_speed;
@@ -301,6 +301,22 @@ static unsigned long hpt370a_filter(struct ata_device *adev, unsigned long mask)
        return mask;
 }
 
+/**
+ *     hpt372_filter   -       mode selection filter
+ *     @adev: ATA device
+ *     @mask: mode mask
+ *
+ *     The Marvell bridge chips used on the HighPoint SATA cards do not seem
+ *     to support the UltraDMA modes 1, 2, and 3 as well as any MWDMA modes...
+ */
+static unsigned long hpt372_filter(struct ata_device *adev, unsigned long mask)
+{
+       if (ata_id_is_sata(adev->id))
+               mask &= ~((0xE << ATA_SHIFT_UDMA) | ATA_MASK_MWDMA);
+
+       return mask;
+}
+
 /**
  *     hpt37x_cable_detect     -       Detect the cable type
  *     @ap: ATA port to detect on
@@ -586,11 +602,11 @@ static struct ata_port_operations hpt370a_port_ops = {
 };
 
 /*
- *     Configuration for HPT372, HPT371, HPT302. Slightly different PIO
- *     and DMA mode setting functionality.
+ *     Configuration for HPT371 and HPT302. Slightly different PIO and DMA
+ *     mode setting functionality.
  */
 
-static struct ata_port_operations hpt372_port_ops = {
+static struct ata_port_operations hpt302_port_ops = {
        .inherits       = &ata_bmdma_port_ops,
 
        .bmdma_stop     = hpt37x_bmdma_stop,
@@ -602,7 +618,17 @@ static struct ata_port_operations hpt372_port_ops = {
 };
 
 /*
- *     Configuration for HPT374. Mode setting works like 372 and friends
+ *     Configuration for HPT372. Mode setting works like 371 and 302
+ *     but we have a mode filter.
+ */
+
+static struct ata_port_operations hpt372_port_ops = {
+       .inherits       = &hpt302_port_ops,
+       .mode_filter    = hpt372_filter,
+};
+
+/*
+ *     Configuration for HPT374. Mode setting and filtering works like 372
  *     but we have a different cable detection procedure for function 1.
  */
 
@@ -753,7 +779,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
                .udma_mask = ATA_UDMA5,
                .port_ops = &hpt370a_port_ops
        };
-       /* HPT371, 372 and friends - UDMA133 */
+       /* HPT372 - UDMA133 */
        static const struct ata_port_info info_hpt372 = {
                .flags = ATA_FLAG_SLAVE_POSS,
                .pio_mask = ATA_PIO4,
@@ -761,6 +787,14 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
                .udma_mask = ATA_UDMA6,
                .port_ops = &hpt372_port_ops
        };
+       /* HPT371, 302 - UDMA133 */
+       static const struct ata_port_info info_hpt302 = {
+               .flags = ATA_FLAG_SLAVE_POSS,
+               .pio_mask = ATA_PIO4,
+               .mwdma_mask = ATA_MWDMA2,
+               .udma_mask = ATA_UDMA6,
+               .port_ops = &hpt302_port_ops
+       };
        /* HPT374 - UDMA100, function 1 uses different prereset method */
        static const struct ata_port_info info_hpt374_fn0 = {
                .flags = ATA_FLAG_SLAVE_POSS,
@@ -828,7 +862,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
        } else {
                switch(dev->device) {
                        case PCI_DEVICE_ID_TTI_HPT372:
-                               /* 372N if rev >= 2*/
+                               /* 372N if rev >= 2 */
                                if (rev >= 2)
                                        return -ENODEV;
                                ppi[0] = &info_hpt372;
@@ -838,14 +872,14 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
                                /* 302N if rev > 1 */
                                if (rev > 1)
                                        return -ENODEV;
-                               ppi[0] = &info_hpt372;
+                               ppi[0] = &info_hpt302;
                                /* Check this */
                                chip_table = &hpt302;
                                break;
                        case PCI_DEVICE_ID_TTI_HPT371:
                                if (rev > 1)
                                        return -ENODEV;
-                               ppi[0] = &info_hpt372;
+                               ppi[0] = &info_hpt302;
                                chip_table = &hpt371;
                                /* Single channel device, master is not present
                                   but the BIOS (or us for non x86) must mark it
index 32f3463216b8df8b095b6af3dcc79c7142dbfda3..97c6ded047b8574574cd152ce5a8689465969a26 100644 (file)
@@ -8,7 +8,7 @@
  * Copyright (C) 1999-2003             Andre Hedrick <andre@linux-ide.org>
  * Portions Copyright (C) 2001         Sun Microsystems, Inc.
  * Portions Copyright (C) 2003         Red Hat Inc
- * Portions Copyright (C) 2005-2009    MontaVista Software, Inc.
+ * Portions Copyright (C) 2005-2010    MontaVista Software, Inc.
  *
  *
  * TODO
@@ -25,7 +25,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME       "pata_hpt3x2n"
-#define DRV_VERSION    "0.3.10"
+#define DRV_VERSION    "0.3.11"
 
 enum {
        HPT_PCI_FAST    =       (1 << 31),
@@ -112,6 +112,22 @@ static u32 hpt3x2n_find_mode(struct ata_port *ap, int speed)
        return 0xffffffffU;     /* silence compiler warning */
 }
 
+/**
+ *     hpt372n_filter  -       mode selection filter
+ *     @adev: ATA device
+ *     @mask: mode mask
+ *
+ *     The Marvell bridge chips used on the HighPoint SATA cards do not seem
+ *     to support the UltraDMA modes 1, 2, and 3 as well as any MWDMA modes...
+ */
+static unsigned long hpt372n_filter(struct ata_device *adev, unsigned long mask)
+{
+       if (ata_id_is_sata(adev->id))
+               mask &= ~((0xE << ATA_SHIFT_UDMA) | ATA_MASK_MWDMA);
+
+       return mask;
+}
+
 /**
  *     hpt3x2n_cable_detect    -       Detect the cable type
  *     @ap: ATA port to detect on
@@ -328,10 +344,10 @@ static struct scsi_host_template hpt3x2n_sht = {
 };
 
 /*
- *     Configuration for HPT3x2n.
+ *     Configuration for HPT302N/371N.
  */
 
-static struct ata_port_operations hpt3x2n_port_ops = {
+static struct ata_port_operations hpt3xxn_port_ops = {
        .inherits       = &ata_bmdma_port_ops,
 
        .bmdma_stop     = hpt3x2n_bmdma_stop,
@@ -345,6 +361,15 @@ static struct ata_port_operations hpt3x2n_port_ops = {
        .prereset       = hpt3x2n_pre_reset,
 };
 
+/*
+ *     Configuration for HPT372N. Same as 302N/371N but we have a mode filter.
+ */
+
+static struct ata_port_operations hpt372n_port_ops = {
+       .inherits       = &hpt3xxn_port_ops,
+       .mode_filter    = &hpt372n_filter,
+};
+
 /**
  *     hpt3xn_calibrate_dpll           -       Calibrate the DPLL loop
  *     @dev: PCI device
@@ -437,15 +462,23 @@ static int hpt3x2n_pci_clock(struct pci_dev *pdev)
 
 static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
-       /* HPT372N and friends - UDMA133 */
-       static const struct ata_port_info info = {
+       /* HPT372N - UDMA133 */
+       static const struct ata_port_info info_hpt372n = {
                .flags = ATA_FLAG_SLAVE_POSS,
                .pio_mask = ATA_PIO4,
                .mwdma_mask = ATA_MWDMA2,
                .udma_mask = ATA_UDMA6,
-               .port_ops = &hpt3x2n_port_ops
+               .port_ops = &hpt372n_port_ops
        };
-       const struct ata_port_info *ppi[] = { &info, NULL };
+       /* HPT302N and HPT371N - UDMA133 */
+       static const struct ata_port_info info_hpt3xxn = {
+               .flags = ATA_FLAG_SLAVE_POSS,
+               .pio_mask = ATA_PIO4,
+               .mwdma_mask = ATA_MWDMA2,
+               .udma_mask = ATA_UDMA6,
+               .port_ops = &hpt3xxn_port_ops
+       };
+       const struct ata_port_info *ppi[] = { &info_hpt3xxn, NULL };
        u8 rev = dev->revision;
        u8 irqmask;
        unsigned int pci_mhz;
@@ -461,24 +494,28 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 
        switch(dev->device) {
                case PCI_DEVICE_ID_TTI_HPT366:
+                       /* 372N if rev >= 6 */
                        if (rev < 6)
                                return -ENODEV;
-                       break;
+                       goto hpt372n;
                case PCI_DEVICE_ID_TTI_HPT371:
+                       /* 371N if rev >= 2 */
                        if (rev < 2)
                                return -ENODEV;
-                       /* 371N if rev > 1 */
                        break;
                case PCI_DEVICE_ID_TTI_HPT372:
-                       /* 372N if rev >= 2*/
+                       /* 372N if rev >= 2 */
                        if (rev < 2)
                                return -ENODEV;
-                       break;
+                       goto hpt372n;
                case PCI_DEVICE_ID_TTI_HPT302:
+                       /* 302N if rev >= 2 */
                        if (rev < 2)
                                return -ENODEV;
                        break;
                case PCI_DEVICE_ID_TTI_HPT372N:
+hpt372n:
+                       ppi[0] = &info_hpt372n;
                        break;
                default:
                        printk(KERN_ERR "pata_hpt3x2n: PCI table is bogus please report (%d).\n", dev->device);