diff options
Diffstat (limited to 'drivers/ata/pata_efar.c')
-rw-r--r-- | drivers/ata/pata_efar.c | 22 |
1 files changed, 19 insertions, 3 deletions
diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c index b2e71e6473ed..3bac0e079691 100644 --- a/drivers/ata/pata_efar.c +++ b/drivers/ata/pata_efar.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * pata_efar.c - EFAR PIIX clone controller driver | 2 | * pata_efar.c - EFAR PIIX clone controller driver |
3 | * | 3 | * |
4 | * (C) 2005 Red Hat | 4 | * (C) 2005 Red Hat |
5 | * (C) 2009 Bartlomiej Zolnierkiewicz | 5 | * (C) 2009-2010 Bartlomiej Zolnierkiewicz |
6 | * | 6 | * |
7 | * Some parts based on ata_piix.c by Jeff Garzik and others. | 7 | * Some parts based on ata_piix.c by Jeff Garzik and others. |
8 | * | 8 | * |
@@ -68,6 +68,8 @@ static int efar_cable_detect(struct ata_port *ap) | |||
68 | return ATA_CBL_PATA80; | 68 | return ATA_CBL_PATA80; |
69 | } | 69 | } |
70 | 70 | ||
71 | static DEFINE_SPINLOCK(efar_lock); | ||
72 | |||
71 | /** | 73 | /** |
72 | * efar_set_piomode - Initialize host controller PATA PIO timings | 74 | * efar_set_piomode - Initialize host controller PATA PIO timings |
73 | * @ap: Port whose timings we are configuring | 75 | * @ap: Port whose timings we are configuring |
@@ -84,7 +86,9 @@ static void efar_set_piomode (struct ata_port *ap, struct ata_device *adev) | |||
84 | unsigned int pio = adev->pio_mode - XFER_PIO_0; | 86 | unsigned int pio = adev->pio_mode - XFER_PIO_0; |
85 | struct pci_dev *dev = to_pci_dev(ap->host->dev); | 87 | struct pci_dev *dev = to_pci_dev(ap->host->dev); |
86 | unsigned int idetm_port= ap->port_no ? 0x42 : 0x40; | 88 | unsigned int idetm_port= ap->port_no ? 0x42 : 0x40; |
89 | unsigned long flags; | ||
87 | u16 idetm_data; | 90 | u16 idetm_data; |
91 | u8 udma_enable; | ||
88 | int control = 0; | 92 | int control = 0; |
89 | 93 | ||
90 | /* | 94 | /* |
@@ -107,6 +111,8 @@ static void efar_set_piomode (struct ata_port *ap, struct ata_device *adev) | |||
107 | if (adev->class == ATA_DEV_ATA) | 111 | if (adev->class == ATA_DEV_ATA) |
108 | control |= 4; /* PPE */ | 112 | control |= 4; /* PPE */ |
109 | 113 | ||
114 | spin_lock_irqsave(&efar_lock, flags); | ||
115 | |||
110 | pci_read_config_word(dev, idetm_port, &idetm_data); | 116 | pci_read_config_word(dev, idetm_port, &idetm_data); |
111 | 117 | ||
112 | /* Set PPE, IE, and TIME as appropriate */ | 118 | /* Set PPE, IE, and TIME as appropriate */ |
@@ -131,6 +137,11 @@ static void efar_set_piomode (struct ata_port *ap, struct ata_device *adev) | |||
131 | 137 | ||
132 | idetm_data |= 0x4000; /* Ensure SITRE is set */ | 138 | idetm_data |= 0x4000; /* Ensure SITRE is set */ |
133 | pci_write_config_word(dev, idetm_port, idetm_data); | 139 | pci_write_config_word(dev, idetm_port, idetm_data); |
140 | |||
141 | pci_read_config_byte(dev, 0x48, &udma_enable); | ||
142 | udma_enable &= ~(1 << (2 * ap->port_no + adev->devno)); | ||
143 | pci_write_config_byte(dev, 0x48, udma_enable); | ||
144 | spin_unlock_irqrestore(&efar_lock, flags); | ||
134 | } | 145 | } |
135 | 146 | ||
136 | /** | 147 | /** |
@@ -151,6 +162,7 @@ static void efar_set_dmamode (struct ata_port *ap, struct ata_device *adev) | |||
151 | u16 master_data; | 162 | u16 master_data; |
152 | u8 speed = adev->dma_mode; | 163 | u8 speed = adev->dma_mode; |
153 | int devid = adev->devno + 2 * ap->port_no; | 164 | int devid = adev->devno + 2 * ap->port_no; |
165 | unsigned long flags; | ||
154 | u8 udma_enable; | 166 | u8 udma_enable; |
155 | 167 | ||
156 | static const /* ISP RTC */ | 168 | static const /* ISP RTC */ |
@@ -160,6 +172,8 @@ static void efar_set_dmamode (struct ata_port *ap, struct ata_device *adev) | |||
160 | { 2, 1 }, | 172 | { 2, 1 }, |
161 | { 2, 3 }, }; | 173 | { 2, 3 }, }; |
162 | 174 | ||
175 | spin_lock_irqsave(&efar_lock, flags); | ||
176 | |||
163 | pci_read_config_word(dev, master_port, &master_data); | 177 | pci_read_config_word(dev, master_port, &master_data); |
164 | pci_read_config_byte(dev, 0x48, &udma_enable); | 178 | pci_read_config_byte(dev, 0x48, &udma_enable); |
165 | 179 | ||
@@ -217,6 +231,7 @@ static void efar_set_dmamode (struct ata_port *ap, struct ata_device *adev) | |||
217 | pci_write_config_word(dev, master_port, master_data); | 231 | pci_write_config_word(dev, master_port, master_data); |
218 | } | 232 | } |
219 | pci_write_config_byte(dev, 0x48, udma_enable); | 233 | pci_write_config_byte(dev, 0x48, udma_enable); |
234 | spin_unlock_irqrestore(&efar_lock, flags); | ||
220 | } | 235 | } |
221 | 236 | ||
222 | static struct scsi_host_template efar_sht = { | 237 | static struct scsi_host_template efar_sht = { |
@@ -256,13 +271,14 @@ static int efar_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
256 | .udma_mask = ATA_UDMA4, | 271 | .udma_mask = ATA_UDMA4, |
257 | .port_ops = &efar_ops, | 272 | .port_ops = &efar_ops, |
258 | }; | 273 | }; |
259 | const struct ata_port_info *ppi[] = { &info, NULL }; | 274 | const struct ata_port_info *ppi[] = { &info, &info }; |
260 | 275 | ||
261 | if (!printed_version++) | 276 | if (!printed_version++) |
262 | dev_printk(KERN_DEBUG, &pdev->dev, | 277 | dev_printk(KERN_DEBUG, &pdev->dev, |
263 | "version " DRV_VERSION "\n"); | 278 | "version " DRV_VERSION "\n"); |
264 | 279 | ||
265 | return ata_pci_sff_init_one(pdev, ppi, &efar_sht, NULL); | 280 | return ata_pci_sff_init_one(pdev, ppi, &efar_sht, NULL, |
281 | ATA_HOST_PARALLEL_SCAN); | ||
266 | } | 282 | } |
267 | 283 | ||
268 | static const struct pci_device_id efar_pci_tbl[] = { | 284 | static const struct pci_device_id efar_pci_tbl[] = { |