aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/pci/cmd640.c
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
commit5bbcf9242d4d15027cbee9618fca4b88b7327c28 (patch)
treeea5ce460326ae3e4061e707de9a4f8bd7e1e13fa /drivers/ide/pci/cmd640.c
parenta482958bf60c434dc12ea0491938c8853d9774fb (diff)
cmd640: 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. cmd640 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/pci/cmd640.c')
-rw-r--r--drivers/ide/pci/cmd640.c48
1 files changed, 28 insertions, 20 deletions
diff --git a/drivers/ide/pci/cmd640.c b/drivers/ide/pci/cmd640.c
index f369645e4d16..0e9275d7459c 100644
--- a/drivers/ide/pci/cmd640.c
+++ b/drivers/ide/pci/cmd640.c
@@ -185,6 +185,8 @@ static u8 recovery_counts[4] = {16, 16, 16, 16}; /* Recovery count (encoded) */
185 185
186#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ 186#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
187 187
188static DEFINE_SPINLOCK(cmd640_lock);
189
188/* 190/*
189 * These are initialized to point at the devices we control 191 * These are initialized to point at the devices we control
190 */ 192 */
@@ -258,12 +260,12 @@ static u8 get_cmd640_reg_vlb (u16 reg)
258 260
259static u8 get_cmd640_reg(u16 reg) 261static u8 get_cmd640_reg(u16 reg)
260{ 262{
261 u8 b;
262 unsigned long flags; 263 unsigned long flags;
264 u8 b;
263 265
264 spin_lock_irqsave(&ide_lock, flags); 266 spin_lock_irqsave(&cmd640_lock, flags);
265 b = __get_cmd640_reg(reg); 267 b = __get_cmd640_reg(reg);
266 spin_unlock_irqrestore(&ide_lock, flags); 268 spin_unlock_irqrestore(&cmd640_lock, flags);
267 return b; 269 return b;
268} 270}
269 271
@@ -271,9 +273,9 @@ static void put_cmd640_reg(u16 reg, u8 val)
271{ 273{
272 unsigned long flags; 274 unsigned long flags;
273 275
274 spin_lock_irqsave(&ide_lock, flags); 276 spin_lock_irqsave(&cmd640_lock, flags);
275 __put_cmd640_reg(reg,val); 277 __put_cmd640_reg(reg,val);
276 spin_unlock_irqrestore(&ide_lock, flags); 278 spin_unlock_irqrestore(&cmd640_lock, flags);
277} 279}
278 280
279static int __init match_pci_cmd640_device (void) 281static int __init match_pci_cmd640_device (void)
@@ -351,7 +353,7 @@ static int __init secondary_port_responding (void)
351{ 353{
352 unsigned long flags; 354 unsigned long flags;
353 355
354 spin_lock_irqsave(&ide_lock, flags); 356 spin_lock_irqsave(&cmd640_lock, flags);
355 357
356 outb_p(0x0a, 0x170 + IDE_SELECT_OFFSET); /* select drive0 */ 358 outb_p(0x0a, 0x170 + IDE_SELECT_OFFSET); /* select drive0 */
357 udelay(100); 359 udelay(100);
@@ -359,11 +361,11 @@ static int __init secondary_port_responding (void)
359 outb_p(0x1a, 0x170 + IDE_SELECT_OFFSET); /* select drive1 */ 361 outb_p(0x1a, 0x170 + IDE_SELECT_OFFSET); /* select drive1 */
360 udelay(100); 362 udelay(100);
361 if ((inb_p(0x170 + IDE_SELECT_OFFSET) & 0x1f) != 0x1a) { 363 if ((inb_p(0x170 + IDE_SELECT_OFFSET) & 0x1f) != 0x1a) {
362 spin_unlock_irqrestore(&ide_lock, flags); 364 spin_unlock_irqrestore(&cmd640_lock, flags);
363 return 0; /* nothing responded */ 365 return 0; /* nothing responded */
364 } 366 }
365 } 367 }
366 spin_unlock_irqrestore(&ide_lock, flags); 368 spin_unlock_irqrestore(&cmd640_lock, flags);
367 return 1; /* success */ 369 return 1; /* success */
368} 370}
369 371
@@ -440,11 +442,11 @@ static void __init setup_device_ptrs (void)
440static void set_prefetch_mode (unsigned int index, int mode) 442static void set_prefetch_mode (unsigned int index, int mode)
441{ 443{
442 ide_drive_t *drive = cmd_drives[index]; 444 ide_drive_t *drive = cmd_drives[index];
445 unsigned long flags;
443 int reg = prefetch_regs[index]; 446 int reg = prefetch_regs[index];
444 u8 b; 447 u8 b;
445 unsigned long flags;
446 448
447 spin_lock_irqsave(&ide_lock, flags); 449 spin_lock_irqsave(&cmd640_lock, flags);
448 b = __get_cmd640_reg(reg); 450 b = __get_cmd640_reg(reg);
449 if (mode) { /* want prefetch on? */ 451 if (mode) { /* want prefetch on? */
450#if CMD640_PREFETCH_MASKS 452#if CMD640_PREFETCH_MASKS
@@ -460,7 +462,7 @@ static void set_prefetch_mode (unsigned int index, int mode)
460 b |= prefetch_masks[index]; /* disable prefetch */ 462 b |= prefetch_masks[index]; /* disable prefetch */
461 } 463 }
462 __put_cmd640_reg(reg, b); 464 __put_cmd640_reg(reg, b);
463 spin_unlock_irqrestore(&ide_lock, flags); 465 spin_unlock_irqrestore(&cmd640_lock, flags);
464} 466}
465 467
466/* 468/*
@@ -561,7 +563,7 @@ static void program_drive_counts (unsigned int index)
561 /* 563 /*
562 * Now that everything is ready, program the new timings 564 * Now that everything is ready, program the new timings
563 */ 565 */
564 spin_lock_irqsave(&ide_lock, flags); 566 spin_lock_irqsave(&cmd640_lock, flags);
565 /* 567 /*
566 * Program the address_setup clocks into ARTTIM reg, 568 * Program the address_setup clocks into ARTTIM reg,
567 * and then the active/recovery counts into the DRWTIM reg 569 * and then the active/recovery counts into the DRWTIM reg
@@ -570,7 +572,7 @@ static void program_drive_counts (unsigned int index)
570 setup_count |= __get_cmd640_reg(arttim_regs[index]) & 0x3f; 572 setup_count |= __get_cmd640_reg(arttim_regs[index]) & 0x3f;
571 __put_cmd640_reg(arttim_regs[index], setup_count); 573 __put_cmd640_reg(arttim_regs[index], setup_count);
572 __put_cmd640_reg(drwtim_regs[index], pack_nibbles(active_count, recovery_count)); 574 __put_cmd640_reg(drwtim_regs[index], pack_nibbles(active_count, recovery_count));
573 spin_unlock_irqrestore(&ide_lock, flags); 575 spin_unlock_irqrestore(&cmd640_lock, flags);
574} 576}
575 577
576/* 578/*
@@ -630,6 +632,7 @@ static void cmd640_set_mode (unsigned int index, u8 pio_mode, unsigned int cycle
630 632
631static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio) 633static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio)
632{ 634{
635 unsigned long flags;
633 unsigned int index = 0, cycle_time; 636 unsigned int index = 0, cycle_time;
634 u8 b; 637 u8 b;
635 638
@@ -652,7 +655,12 @@ static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio)
652 655
653 case 8: /* set prefetch off */ 656 case 8: /* set prefetch off */
654 case 9: /* set prefetch on */ 657 case 9: /* set prefetch on */
658 /*
659 * take ide_lock for drive->[no_]unmask/[no_]io_32bit
660 */
661 spin_lock_irqsave(&ide_lock, flags);
655 set_prefetch_mode(index, pio & 1); 662 set_prefetch_mode(index, pio & 1);
663 spin_unlock_irqrestore(&ide_lock, flags);
656 printk("%s: %sabled cmd640 prefetch\n", drive->name, (pio & 1) ? "en" : "dis"); 664 printk("%s: %sabled cmd640 prefetch\n", drive->name, (pio & 1) ? "en" : "dis");
657 return; 665 return;
658 } 666 }
@@ -670,20 +678,20 @@ static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio)
670 678
671static int pci_conf1(void) 679static int pci_conf1(void)
672{ 680{
673 u32 tmp;
674 unsigned long flags; 681 unsigned long flags;
682 u32 tmp;
675 683
676 spin_lock_irqsave(&ide_lock, flags); 684 spin_lock_irqsave(&cmd640_lock, flags);
677 outb(0x01, 0xCFB); 685 outb(0x01, 0xCFB);
678 tmp = inl(0xCF8); 686 tmp = inl(0xCF8);
679 outl(0x80000000, 0xCF8); 687 outl(0x80000000, 0xCF8);
680 if (inl(0xCF8) == 0x80000000) { 688 if (inl(0xCF8) == 0x80000000) {
681 outl(tmp, 0xCF8); 689 outl(tmp, 0xCF8);
682 spin_unlock_irqrestore(&ide_lock, flags); 690 spin_unlock_irqrestore(&cmd640_lock, flags);
683 return 1; 691 return 1;
684 } 692 }
685 outl(tmp, 0xCF8); 693 outl(tmp, 0xCF8);
686 spin_unlock_irqrestore(&ide_lock, flags); 694 spin_unlock_irqrestore(&cmd640_lock, flags);
687 return 0; 695 return 0;
688} 696}
689 697
@@ -691,15 +699,15 @@ static int pci_conf2(void)
691{ 699{
692 unsigned long flags; 700 unsigned long flags;
693 701
694 spin_lock_irqsave(&ide_lock, flags); 702 spin_lock_irqsave(&cmd640_lock, flags);
695 outb(0x00, 0xCFB); 703 outb(0x00, 0xCFB);
696 outb(0x00, 0xCF8); 704 outb(0x00, 0xCF8);
697 outb(0x00, 0xCFA); 705 outb(0x00, 0xCFA);
698 if (inb(0xCF8) == 0x00 && inb(0xCF8) == 0x00) { 706 if (inb(0xCF8) == 0x00 && inb(0xCF8) == 0x00) {
699 spin_unlock_irqrestore(&ide_lock, flags); 707 spin_unlock_irqrestore(&cmd640_lock, flags);
700 return 1; 708 return 1;
701 } 709 }
702 spin_unlock_irqrestore(&ide_lock, flags); 710 spin_unlock_irqrestore(&cmd640_lock, flags);
703 return 0; 711 return 0;
704} 712}
705 713