aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2007-10-19 18:32:35 -0400
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2007-10-19 18:32:35 -0400
commit69e88d2a754fcaf7ef8ca465586b811cf40dc479 (patch)
tree547d37f38507edf5e94672ef898c2f7757e6ccae /drivers
parent5bbcf9242d4d15027cbee9618fca4b88b7327c28 (diff)
ht6560b: fix deadlock on error handling
Stop abusing ide_lock lock (switch to a private locking). Fixes same issue as fixed by Alan Cox in atiixp host driver with commit 6c5f8cc33eb2e10b6ab788bbe259fc142a068627. ht6560b is a bit special cause we still need to leave ide_lock for ->set_pio_mode with 'pio' argument == 8/9 (prefetch disable/enable). Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ide/legacy/ht6560b.c31
1 files changed, 18 insertions, 13 deletions
diff --git a/drivers/ide/legacy/ht6560b.c b/drivers/ide/legacy/ht6560b.c
index 7f0d433cb9d8..4a93adbab1de 100644
--- a/drivers/ide/legacy/ht6560b.c
+++ b/drivers/ide/legacy/ht6560b.c
@@ -247,6 +247,8 @@ static u8 ht_pio2timings(ide_drive_t *drive, const u8 pio)
247 } 247 }
248} 248}
249 249
250static DEFINE_SPINLOCK(ht6560b_lock);
251
250/* 252/*
251 * Enable/Disable so called prefetch mode 253 * Enable/Disable so called prefetch mode
252 */ 254 */
@@ -254,9 +256,9 @@ static void ht_set_prefetch(ide_drive_t *drive, u8 state)
254{ 256{
255 unsigned long flags; 257 unsigned long flags;
256 int t = HT_PREFETCH_MODE << 8; 258 int t = HT_PREFETCH_MODE << 8;
257 259
258 spin_lock_irqsave(&ide_lock, flags); 260 spin_lock_irqsave(&ht6560b_lock, flags);
259 261
260 /* 262 /*
261 * Prefetch mode and unmask irq seems to conflict 263 * Prefetch mode and unmask irq seems to conflict
262 */ 264 */
@@ -268,9 +270,9 @@ static void ht_set_prefetch(ide_drive_t *drive, u8 state)
268 drive->drive_data &= ~t; /* disable prefetch mode */ 270 drive->drive_data &= ~t; /* disable prefetch mode */
269 drive->no_unmask = 0; 271 drive->no_unmask = 0;
270 } 272 }
271 273
272 spin_unlock_irqrestore(&ide_lock, flags); 274 spin_unlock_irqrestore(&ht6560b_lock, flags);
273 275
274#ifdef DEBUG 276#ifdef DEBUG
275 printk("ht6560b: drive %s prefetch mode %sabled\n", drive->name, (state ? "en" : "dis")); 277 printk("ht6560b: drive %s prefetch mode %sabled\n", drive->name, (state ? "en" : "dis"));
276#endif 278#endif
@@ -284,19 +286,22 @@ static void ht6560b_set_pio_mode(ide_drive_t *drive, const u8 pio)
284 switch (pio) { 286 switch (pio) {
285 case 8: /* set prefetch off */ 287 case 8: /* set prefetch off */
286 case 9: /* set prefetch on */ 288 case 9: /* set prefetch on */
289 /*
290 * take ide_lock for drive->[no_]unmask
291 */
292 spin_lock_irqsave(&ide_lock, flags);
287 ht_set_prefetch(drive, pio & 1); 293 ht_set_prefetch(drive, pio & 1);
294 spin_unlock_irqrestore(&ide_lock, flags);
288 return; 295 return;
289 } 296 }
290 297
291 timing = ht_pio2timings(drive, pio); 298 timing = ht_pio2timings(drive, pio);
292 299
293 spin_lock_irqsave(&ide_lock, flags); 300 spin_lock_irqsave(&ht6560b_lock, flags);
294
295 drive->drive_data &= 0xff00; 301 drive->drive_data &= 0xff00;
296 drive->drive_data |= timing; 302 drive->drive_data |= timing;
297 303 spin_unlock_irqrestore(&ht6560b_lock, flags);
298 spin_unlock_irqrestore(&ide_lock, flags); 304
299
300#ifdef DEBUG 305#ifdef DEBUG
301 printk("ht6560b: drive %s tuned to pio mode %#x timing=%#x\n", drive->name, pio, timing); 306 printk("ht6560b: drive %s tuned to pio mode %#x timing=%#x\n", drive->name, pio, timing);
302#endif 307#endif