diff options
Diffstat (limited to 'drivers')
| -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 | ||
