aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ide')
-rw-r--r--drivers/ide/ide-io.c12
-rw-r--r--drivers/ide/ide-probe.c90
2 files changed, 12 insertions, 90 deletions
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index 1fc739f4415..4ce793c0562 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -742,12 +742,12 @@ repeat:
742 * set nIEN for previous port, drives in the 742 * set nIEN for previous port, drives in the
743 * quirk_list may not like intr setups/cleanups 743 * quirk_list may not like intr setups/cleanups
744 */ 744 */
745 if (prev_port && hwgroup->drive->quirk_list == 0) 745 if (prev_port && hwgroup->cur_dev->quirk_list == 0)
746 prev_port->tp_ops->set_irq(prev_port, 0); 746 prev_port->tp_ops->set_irq(prev_port, 0);
747 747
748 hwif->host->cur_port = hwif; 748 hwif->host->cur_port = hwif;
749 } 749 }
750 hwgroup->drive = drive; 750 hwgroup->cur_dev = drive;
751 drive->dev_flags &= ~(IDE_DFLAG_SLEEPING | IDE_DFLAG_PARKED); 751 drive->dev_flags &= ~(IDE_DFLAG_SLEEPING | IDE_DFLAG_PARKED);
752 752
753 spin_unlock_irq(&hwgroup->lock); 753 spin_unlock_irq(&hwgroup->lock);
@@ -913,9 +913,9 @@ void ide_timer_expiry (unsigned long data)
913 * Either way, we don't really want to complain about anything. 913 * Either way, we don't really want to complain about anything.
914 */ 914 */
915 } else { 915 } else {
916 drive = hwgroup->drive; 916 drive = hwgroup->cur_dev;
917 if (!drive) { 917 if (!drive) {
918 printk(KERN_ERR "ide_timer_expiry: hwgroup->drive was NULL\n"); 918 printk(KERN_ERR "%s: ->cur_dev was NULL\n", __func__);
919 hwgroup->handler = NULL; 919 hwgroup->handler = NULL;
920 } else { 920 } else {
921 ide_hwif_t *hwif; 921 ide_hwif_t *hwif;
@@ -1033,7 +1033,7 @@ static void unexpected_intr(int irq, ide_hwif_t *hwif)
1033 * places 1033 * places
1034 * 1034 *
1035 * hwif is the interface in the group currently performing 1035 * hwif is the interface in the group currently performing
1036 * a command. hwgroup->drive is the drive and hwgroup->handler is 1036 * a command. hwgroup->cur_dev is the drive and hwgroup->handler is
1037 * the IRQ handler to call. As we issue a command the handlers 1037 * the IRQ handler to call. As we issue a command the handlers
1038 * step through multiple states, reassigning the handler to the 1038 * step through multiple states, reassigning the handler to the
1039 * next step in the process. Unlike a smart SCSI controller IDE 1039 * next step in the process. Unlike a smart SCSI controller IDE
@@ -1105,7 +1105,7 @@ irqreturn_t ide_intr (int irq, void *dev_id)
1105 goto out; 1105 goto out;
1106 } 1106 }
1107 1107
1108 drive = hwgroup->drive; 1108 drive = hwgroup->cur_dev;
1109 if (!drive) { 1109 if (!drive) {
1110 /* 1110 /*
1111 * This should NEVER happen, and there isn't much 1111 * This should NEVER happen, and there isn't much
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 2752509531b..68f3c87b828 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -918,27 +918,9 @@ static int ide_init_queue(ide_drive_t *drive)
918 return 0; 918 return 0;
919} 919}
920 920
921static void ide_add_drive_to_hwgroup(ide_drive_t *drive)
922{
923 ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;
924
925 spin_lock_irq(&hwgroup->lock);
926 if (!hwgroup->drive) {
927 /* first drive for hwgroup. */
928 drive->next = drive;
929 hwgroup->drive = drive;
930 hwgroup->hwif = HWIF(hwgroup->drive);
931 } else {
932 drive->next = hwgroup->drive->next;
933 hwgroup->drive->next = drive;
934 }
935 spin_unlock_irq(&hwgroup->lock);
936}
937
938/* 921/*
939 * For any present drive: 922 * For any present drive:
940 * - allocate the block device queue 923 * - allocate the block device queue
941 * - link drive into the hwgroup
942 */ 924 */
943static int ide_port_setup_devices(ide_hwif_t *hwif) 925static int ide_port_setup_devices(ide_hwif_t *hwif)
944{ 926{
@@ -961,8 +943,6 @@ static int ide_port_setup_devices(ide_hwif_t *hwif)
961 } 943 }
962 944
963 j++; 945 j++;
964
965 ide_add_drive_to_hwgroup(drive);
966 } 946 }
967 mutex_unlock(&ide_cfg_mtx); 947 mutex_unlock(&ide_cfg_mtx);
968 948
@@ -978,33 +958,9 @@ void ide_remove_port_from_hwgroup(ide_hwif_t *hwif)
978 ide_ports[hwif->index] = NULL; 958 ide_ports[hwif->index] = NULL;
979 959
980 spin_lock_irq(&hwgroup->lock); 960 spin_lock_irq(&hwgroup->lock);
981 /* 961 /* Free the hwgroup if we were the only member. */
982 * Remove us from the hwgroup, and free 962 if (--hwgroup->port_count == 0)
983 * the hwgroup if we were the only member
984 */
985 if (hwif->next == hwif) {
986 BUG_ON(hwgroup->hwif != hwif);
987 kfree(hwgroup); 963 kfree(hwgroup);
988 } else {
989 /* There is another interface in hwgroup.
990 * Unlink us, and set hwgroup->drive and ->hwif to
991 * something sane.
992 */
993 ide_hwif_t *g = hwgroup->hwif;
994
995 while (g->next != hwif)
996 g = g->next;
997 g->next = hwif->next;
998 if (hwgroup->hwif == hwif) {
999 /* Chose a random hwif for hwgroup->hwif.
1000 * It's guaranteed that there are no drives
1001 * left in the hwgroup.
1002 */
1003 BUG_ON(hwgroup->drive != NULL);
1004 hwgroup->hwif = g;
1005 }
1006 BUG_ON(hwgroup->hwif == hwif);
1007 }
1008 spin_unlock_irq(&hwgroup->lock); 964 spin_unlock_irq(&hwgroup->lock);
1009} 965}
1010 966
@@ -1044,20 +1000,9 @@ static int init_irq (ide_hwif_t *hwif)
1044 if (match) { 1000 if (match) {
1045 hwgroup = match->hwgroup; 1001 hwgroup = match->hwgroup;
1046 hwif->hwgroup = hwgroup; 1002 hwif->hwgroup = hwgroup;
1047 /* 1003
1048 * Link us into the hwgroup.
1049 * This must be done early, do ensure that unexpected_intr
1050 * can find the hwif and prevent irq storms.
1051 * No drives are attached to the new hwif, choose_drive
1052 * can't do anything stupid (yet).
1053 * Add ourself as the 2nd entry to the hwgroup->hwif
1054 * linked list, the first entry is the hwif that owns
1055 * hwgroup->handler - do not change that.
1056 */
1057 spin_lock_irq(&hwgroup->lock); 1004 spin_lock_irq(&hwgroup->lock);
1058 hwif->next = hwgroup->hwif->next; 1005 hwgroup->port_count++;
1059 hwgroup->hwif->next = hwif;
1060 BUG_ON(hwif->next == hwif);
1061 spin_unlock_irq(&hwgroup->lock); 1006 spin_unlock_irq(&hwgroup->lock);
1062 } else { 1007 } else {
1063 hwgroup = kmalloc_node(sizeof(*hwgroup), GFP_KERNEL|__GFP_ZERO, 1008 hwgroup = kmalloc_node(sizeof(*hwgroup), GFP_KERNEL|__GFP_ZERO,
@@ -1068,7 +1013,8 @@ static int init_irq (ide_hwif_t *hwif)
1068 spin_lock_init(&hwgroup->lock); 1013 spin_lock_init(&hwgroup->lock);
1069 1014
1070 hwif->hwgroup = hwgroup; 1015 hwif->hwgroup = hwgroup;
1071 hwgroup->hwif = hwif->next = hwif; 1016
1017 hwgroup->port_count = 1;
1072 1018
1073 init_timer(&hwgroup->timer); 1019 init_timer(&hwgroup->timer);
1074 hwgroup->timer.function = &ide_timer_expiry; 1020 hwgroup->timer.function = &ide_timer_expiry;
@@ -1191,29 +1137,6 @@ void ide_init_disk(struct gendisk *disk, ide_drive_t *drive)
1191 1137
1192EXPORT_SYMBOL_GPL(ide_init_disk); 1138EXPORT_SYMBOL_GPL(ide_init_disk);
1193 1139
1194static void ide_remove_drive_from_hwgroup(ide_drive_t *drive)
1195{
1196 ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;
1197
1198 if (drive == drive->next) {
1199 /* special case: last drive from hwgroup. */
1200 BUG_ON(hwgroup->drive != drive);
1201 hwgroup->drive = NULL;
1202 } else {
1203 ide_drive_t *walk;
1204
1205 walk = hwgroup->drive;
1206 while (walk->next != drive)
1207 walk = walk->next;
1208 walk->next = drive->next;
1209 if (hwgroup->drive == drive) {
1210 hwgroup->drive = drive->next;
1211 hwgroup->hwif = hwgroup->drive->hwif;
1212 }
1213 }
1214 BUG_ON(hwgroup->drive == drive);
1215}
1216
1217static void drive_release_dev (struct device *dev) 1140static void drive_release_dev (struct device *dev)
1218{ 1141{
1219 ide_drive_t *drive = container_of(dev, ide_drive_t, gendev); 1142 ide_drive_t *drive = container_of(dev, ide_drive_t, gendev);
@@ -1222,7 +1145,6 @@ static void drive_release_dev (struct device *dev)
1222 ide_proc_unregister_device(drive); 1145 ide_proc_unregister_device(drive);
1223 1146
1224 spin_lock_irq(&hwgroup->lock); 1147 spin_lock_irq(&hwgroup->lock);
1225 ide_remove_drive_from_hwgroup(drive);
1226 kfree(drive->id); 1148 kfree(drive->id);
1227 drive->id = NULL; 1149 drive->id = NULL;
1228 drive->dev_flags &= ~IDE_DFLAG_PRESENT; 1150 drive->dev_flags &= ~IDE_DFLAG_PRESENT;