From 8e834c2e6d51e053c6bd23fec1d95529f618f760 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sat, 25 Dec 2010 22:44:01 +0300 Subject: pata_hpt{37x|3x2n}: SATA mode filtering 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 Signed-off-by: Jeff Garzik --- drivers/ata/pata_hpt37x.c | 54 ++++++++++++++++++++++++++++++++-------- drivers/ata/pata_hpt3x2n.c | 61 +++++++++++++++++++++++++++++++++++++--------- 2 files changed, 93 insertions(+), 22 deletions(-) (limited to 'drivers/ata') diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c index 9ae4c0830577..9c62951c3e26 100644 --- a/drivers/ata/pata_hpt37x.c +++ b/drivers/ata/pata_hpt37x.c @@ -8,7 +8,7 @@ * Copyright (C) 1999-2003 Andre Hedrick * 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 #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 diff --git a/drivers/ata/pata_hpt3x2n.c b/drivers/ata/pata_hpt3x2n.c index 32f3463216b8..97c6ded047b8 100644 --- a/drivers/ata/pata_hpt3x2n.c +++ b/drivers/ata/pata_hpt3x2n.c @@ -8,7 +8,7 @@ * Copyright (C) 1999-2003 Andre Hedrick * 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 #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); -- cgit v1.2.1