diff options
Diffstat (limited to 'drivers/ide/ide-probe.c')
-rw-r--r-- | drivers/ide/ide-probe.c | 87 |
1 files changed, 13 insertions, 74 deletions
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 68f3c87b8284..e953b70706c2 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c | |||
@@ -949,79 +949,20 @@ static int ide_port_setup_devices(ide_hwif_t *hwif) | |||
949 | return j; | 949 | return j; |
950 | } | 950 | } |
951 | 951 | ||
952 | static ide_hwif_t *ide_ports[MAX_HWIFS]; | ||
953 | |||
954 | void ide_remove_port_from_hwgroup(ide_hwif_t *hwif) | ||
955 | { | ||
956 | ide_hwgroup_t *hwgroup = hwif->hwgroup; | ||
957 | |||
958 | ide_ports[hwif->index] = NULL; | ||
959 | |||
960 | spin_lock_irq(&hwgroup->lock); | ||
961 | /* Free the hwgroup if we were the only member. */ | ||
962 | if (--hwgroup->port_count == 0) | ||
963 | kfree(hwgroup); | ||
964 | spin_unlock_irq(&hwgroup->lock); | ||
965 | } | ||
966 | |||
967 | /* | 952 | /* |
968 | * This routine sets up the irq for an ide interface, and creates a new | 953 | * This routine sets up the IRQ for an IDE interface. |
969 | * hwgroup for the irq/hwif if none was previously assigned. | ||
970 | * | ||
971 | * Much of the code is for correctly detecting/handling irq sharing | ||
972 | * and irq serialization situations. This is somewhat complex because | ||
973 | * it handles static as well as dynamic (PCMCIA) IDE interfaces. | ||
974 | */ | 954 | */ |
975 | static int init_irq (ide_hwif_t *hwif) | 955 | static int init_irq (ide_hwif_t *hwif) |
976 | { | 956 | { |
977 | struct ide_io_ports *io_ports = &hwif->io_ports; | 957 | struct ide_io_ports *io_ports = &hwif->io_ports; |
978 | unsigned int index; | ||
979 | ide_hwgroup_t *hwgroup; | ||
980 | ide_hwif_t *match = NULL; | ||
981 | int sa = 0; | 958 | int sa = 0; |
982 | 959 | ||
983 | mutex_lock(&ide_cfg_mtx); | 960 | mutex_lock(&ide_cfg_mtx); |
984 | hwif->hwgroup = NULL; | 961 | spin_lock_init(&hwif->lock); |
985 | |||
986 | for (index = 0; index < MAX_HWIFS; index++) { | ||
987 | ide_hwif_t *h = ide_ports[index]; | ||
988 | 962 | ||
989 | if (h && h->hwgroup) { /* scan only initialized ports */ | 963 | init_timer(&hwif->timer); |
990 | if (hwif->host->host_flags & IDE_HFLAG_SERIALIZE) { | 964 | hwif->timer.function = &ide_timer_expiry; |
991 | if (hwif->host == h->host) | 965 | hwif->timer.data = (unsigned long)hwif; |
992 | match = h; | ||
993 | } | ||
994 | } | ||
995 | } | ||
996 | |||
997 | /* | ||
998 | * If we are still without a hwgroup, then form a new one | ||
999 | */ | ||
1000 | if (match) { | ||
1001 | hwgroup = match->hwgroup; | ||
1002 | hwif->hwgroup = hwgroup; | ||
1003 | |||
1004 | spin_lock_irq(&hwgroup->lock); | ||
1005 | hwgroup->port_count++; | ||
1006 | spin_unlock_irq(&hwgroup->lock); | ||
1007 | } else { | ||
1008 | hwgroup = kmalloc_node(sizeof(*hwgroup), GFP_KERNEL|__GFP_ZERO, | ||
1009 | hwif_to_node(hwif)); | ||
1010 | if (hwgroup == NULL) | ||
1011 | goto out_up; | ||
1012 | |||
1013 | spin_lock_init(&hwgroup->lock); | ||
1014 | |||
1015 | hwif->hwgroup = hwgroup; | ||
1016 | |||
1017 | hwgroup->port_count = 1; | ||
1018 | |||
1019 | init_timer(&hwgroup->timer); | ||
1020 | hwgroup->timer.function = &ide_timer_expiry; | ||
1021 | hwgroup->timer.data = (unsigned long) hwgroup; | ||
1022 | } | ||
1023 | |||
1024 | ide_ports[hwif->index] = hwif; | ||
1025 | 966 | ||
1026 | #if defined(__mc68000__) | 967 | #if defined(__mc68000__) |
1027 | sa = IRQF_SHARED; | 968 | sa = IRQF_SHARED; |
@@ -1034,7 +975,7 @@ static int init_irq (ide_hwif_t *hwif) | |||
1034 | hwif->tp_ops->set_irq(hwif, 1); | 975 | hwif->tp_ops->set_irq(hwif, 1); |
1035 | 976 | ||
1036 | if (request_irq(hwif->irq, &ide_intr, sa, hwif->name, hwif)) | 977 | if (request_irq(hwif->irq, &ide_intr, sa, hwif->name, hwif)) |
1037 | goto out_unlink; | 978 | goto out_up; |
1038 | 979 | ||
1039 | if (!hwif->rqsize) { | 980 | if (!hwif->rqsize) { |
1040 | if ((hwif->host_flags & IDE_HFLAG_NO_LBA48) || | 981 | if ((hwif->host_flags & IDE_HFLAG_NO_LBA48) || |
@@ -1052,14 +993,12 @@ static int init_irq (ide_hwif_t *hwif) | |||
1052 | printk(KERN_INFO "%s at 0x%08lx on irq %d", hwif->name, | 993 | printk(KERN_INFO "%s at 0x%08lx on irq %d", hwif->name, |
1053 | io_ports->data_addr, hwif->irq); | 994 | io_ports->data_addr, hwif->irq); |
1054 | #endif /* __mc68000__ */ | 995 | #endif /* __mc68000__ */ |
1055 | if (match) | 996 | if (hwif->host->host_flags & IDE_HFLAG_SERIALIZE) |
1056 | printk(KERN_CONT " (serialized with %s)", match->name); | 997 | printk(KERN_CONT " (serialized)"); |
1057 | printk(KERN_CONT "\n"); | 998 | printk(KERN_CONT "\n"); |
1058 | 999 | ||
1059 | mutex_unlock(&ide_cfg_mtx); | 1000 | mutex_unlock(&ide_cfg_mtx); |
1060 | return 0; | 1001 | return 0; |
1061 | out_unlink: | ||
1062 | ide_remove_port_from_hwgroup(hwif); | ||
1063 | out_up: | 1002 | out_up: |
1064 | mutex_unlock(&ide_cfg_mtx); | 1003 | mutex_unlock(&ide_cfg_mtx); |
1065 | return 1; | 1004 | return 1; |
@@ -1140,20 +1079,20 @@ EXPORT_SYMBOL_GPL(ide_init_disk); | |||
1140 | static void drive_release_dev (struct device *dev) | 1079 | static void drive_release_dev (struct device *dev) |
1141 | { | 1080 | { |
1142 | ide_drive_t *drive = container_of(dev, ide_drive_t, gendev); | 1081 | ide_drive_t *drive = container_of(dev, ide_drive_t, gendev); |
1143 | ide_hwgroup_t *hwgroup = drive->hwif->hwgroup; | 1082 | ide_hwif_t *hwif = drive->hwif; |
1144 | 1083 | ||
1145 | ide_proc_unregister_device(drive); | 1084 | ide_proc_unregister_device(drive); |
1146 | 1085 | ||
1147 | spin_lock_irq(&hwgroup->lock); | 1086 | spin_lock_irq(&hwif->lock); |
1148 | kfree(drive->id); | 1087 | kfree(drive->id); |
1149 | drive->id = NULL; | 1088 | drive->id = NULL; |
1150 | drive->dev_flags &= ~IDE_DFLAG_PRESENT; | 1089 | drive->dev_flags &= ~IDE_DFLAG_PRESENT; |
1151 | /* Messed up locking ... */ | 1090 | /* Messed up locking ... */ |
1152 | spin_unlock_irq(&hwgroup->lock); | 1091 | spin_unlock_irq(&hwif->lock); |
1153 | blk_cleanup_queue(drive->queue); | 1092 | blk_cleanup_queue(drive->queue); |
1154 | spin_lock_irq(&hwgroup->lock); | 1093 | spin_lock_irq(&hwif->lock); |
1155 | drive->queue = NULL; | 1094 | drive->queue = NULL; |
1156 | spin_unlock_irq(&hwgroup->lock); | 1095 | spin_unlock_irq(&hwif->lock); |
1157 | 1096 | ||
1158 | complete(&drive->gendev_rel_comp); | 1097 | complete(&drive->gendev_rel_comp); |
1159 | } | 1098 | } |