aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/pata_efar.c
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2010-02-17 08:16:58 -0500
committerJeff Garzik <jgarzik@redhat.com>2010-03-01 15:04:58 -0500
commit303f1a76ae792885af8a4a0e784e22e31e850e9a (patch)
treed390d5ca09c5fc0ddb8ac3c1d09361c1bfa3a1f5 /drivers/ata/pata_efar.c
parent16ea0fc98d53c72cb4e1a9edcb685a87e3a81430 (diff)
[libata] pata_efar: add locking for parallel scanning
Add clearing of UDMA enable bit also for PIO modes and then add extra locking for parallel scanning. This is similar change as commit 60c3be3 for ata_piix host driver and while pata_efar doesn't enable parallel scan yet the race could probably also be triggered by requesting re-scanning of both ports at the same time using SCSI sysfs interface. [Ported to current kernel without other patch dependancies by Alan Cox] Original is Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> This one is Signed-off-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/ata/pata_efar.c')
-rw-r--r--drivers/ata/pata_efar.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c
index 5556163c80de..1617421f7e76 100644
--- a/drivers/ata/pata_efar.c
+++ b/drivers/ata/pata_efar.c
@@ -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
71static 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
222static struct scsi_host_template efar_sht = { 237static struct scsi_host_template efar_sht = {