aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/ide.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ide/ide.c')
-rw-r--r--drivers/ide/ide.c65
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
464static 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