diff options
author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2007-10-19 18:32:35 -0400 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2007-10-19 18:32:35 -0400 |
commit | 69e88d2a754fcaf7ef8ca465586b811cf40dc479 (patch) | |
tree | 547d37f38507edf5e94672ef898c2f7757e6ccae /drivers/ide/legacy | |
parent | 5bbcf9242d4d15027cbee9618fca4b88b7327c28 (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/ide/legacy')
-rw-r--r-- | drivers/ide/legacy/ht6560b.c | 31 |
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 | ||
250 | static 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 |