diff options
Diffstat (limited to 'drivers/ide/ide.c')
-rw-r--r-- | drivers/ide/ide.c | 65 |
1 files changed, 36 insertions, 29 deletions
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index ea7512d99dec..1a3c89471175 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c | |||
@@ -461,6 +461,41 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif) | |||
461 | hwif->hwif_data = tmp_hwif->hwif_data; | 461 | hwif->hwif_data = tmp_hwif->hwif_data; |
462 | } | 462 | } |
463 | 463 | ||
464 | static void ide_remove_port_from_hwgroup(ide_hwif_t *hwif) | ||
465 | { | ||
466 | ide_hwgroup_t *hwgroup = hwif->hwgroup; | ||
467 | |||
468 | spin_lock_irq(&ide_lock); | ||
469 | /* | ||
470 | * Remove us from the hwgroup, and free | ||
471 | * the hwgroup if we were the only member | ||
472 | */ | ||
473 | if (hwif->next == hwif) { | ||
474 | BUG_ON(hwgroup->hwif != hwif); | ||
475 | kfree(hwgroup); | ||
476 | } else { | ||
477 | /* There is another interface in hwgroup. | ||
478 | * Unlink us, and set hwgroup->drive and ->hwif to | ||
479 | * something sane. | ||
480 | */ | ||
481 | ide_hwif_t *g = hwgroup->hwif; | ||
482 | |||
483 | while (g->next != hwif) | ||
484 | g = g->next; | ||
485 | g->next = hwif->next; | ||
486 | if (hwgroup->hwif == hwif) { | ||
487 | /* Chose a random hwif for hwgroup->hwif. | ||
488 | * It's guaranteed that there are no drives | ||
489 | * left in the hwgroup. | ||
490 | */ | ||
491 | BUG_ON(hwgroup->drive != NULL); | ||
492 | hwgroup->hwif = g; | ||
493 | } | ||
494 | BUG_ON(hwgroup->hwif == hwif); | ||
495 | } | ||
496 | spin_unlock_irq(&ide_lock); | ||
497 | } | ||
498 | |||
464 | /** | 499 | /** |
465 | * ide_unregister - free an IDE interface | 500 | * ide_unregister - free an IDE interface |
466 | * @index: index of interface (will change soon to a pointer) | 501 | * @index: index of interface (will change soon to a pointer) |
@@ -528,36 +563,8 @@ void ide_unregister(unsigned int index) | |||
528 | if (irq_count == 1) | 563 | if (irq_count == 1) |
529 | free_irq(hwif->irq, hwgroup); | 564 | free_irq(hwif->irq, hwgroup); |
530 | 565 | ||
531 | spin_lock_irq(&ide_lock); | 566 | ide_remove_port_from_hwgroup(hwif); |
532 | /* | ||
533 | * Remove us from the hwgroup, and free | ||
534 | * the hwgroup if we were the only member | ||
535 | */ | ||
536 | if (hwif->next == hwif) { | ||
537 | BUG_ON(hwgroup->hwif != hwif); | ||
538 | kfree(hwgroup); | ||
539 | } else { | ||
540 | /* There is another interface in hwgroup. | ||
541 | * Unlink us, and set hwgroup->drive and ->hwif to | ||
542 | * something sane. | ||
543 | */ | ||
544 | g = hwgroup->hwif; | ||
545 | while (g->next != hwif) | ||
546 | g = g->next; | ||
547 | g->next = hwif->next; | ||
548 | if (hwgroup->hwif == hwif) { | ||
549 | /* Chose a random hwif for hwgroup->hwif. | ||
550 | * It's guaranteed that there are no drives | ||
551 | * left in the hwgroup. | ||
552 | */ | ||
553 | BUG_ON(hwgroup->drive != NULL); | ||
554 | hwgroup->hwif = g; | ||
555 | } | ||
556 | BUG_ON(hwgroup->hwif == hwif); | ||
557 | } | ||
558 | 567 | ||
559 | /* More messed up locking ... */ | ||
560 | spin_unlock_irq(&ide_lock); | ||
561 | device_unregister(&hwif->gendev); | 568 | device_unregister(&hwif->gendev); |
562 | wait_for_completion(&hwif->gendev_rel_comp); | 569 | wait_for_completion(&hwif->gendev_rel_comp); |
563 | 570 | ||