aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/ide-probe.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ide/ide-probe.c')
-rw-r--r--drivers/ide/ide-probe.c87
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
952static ide_hwif_t *ide_ports[MAX_HWIFS];
953
954void 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 */
975static int init_irq (ide_hwif_t *hwif) 955static 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;
1061out_unlink:
1062 ide_remove_port_from_hwgroup(hwif);
1063out_up: 1002out_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);
1140static void drive_release_dev (struct device *dev) 1079static 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}