diff options
Diffstat (limited to 'drivers/ide/ide-probe.c')
-rw-r--r-- | drivers/ide/ide-probe.c | 166 |
1 files changed, 34 insertions, 132 deletions
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index c55bdbd22314..a64ec259f3d1 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c | |||
@@ -110,20 +110,22 @@ static void ide_disk_init_mult_count(ide_drive_t *drive) | |||
110 | * read and parse the results. This function is run with | 110 | * read and parse the results. This function is run with |
111 | * interrupts disabled. | 111 | * interrupts disabled. |
112 | */ | 112 | */ |
113 | 113 | ||
114 | static inline void do_identify (ide_drive_t *drive, u8 cmd) | 114 | static void do_identify(ide_drive_t *drive, u8 cmd) |
115 | { | 115 | { |
116 | ide_hwif_t *hwif = HWIF(drive); | 116 | ide_hwif_t *hwif = HWIF(drive); |
117 | u16 *id = drive->id; | 117 | u16 *id = drive->id; |
118 | char *m = (char *)&id[ATA_ID_PROD]; | 118 | char *m = (char *)&id[ATA_ID_PROD]; |
119 | unsigned long flags; | ||
119 | int bswap = 1, is_cfa; | 120 | int bswap = 1, is_cfa; |
120 | 121 | ||
122 | /* local CPU only; some systems need this */ | ||
123 | local_irq_save(flags); | ||
121 | /* read 512 bytes of id info */ | 124 | /* read 512 bytes of id info */ |
122 | hwif->tp_ops->input_data(drive, NULL, id, SECTOR_SIZE); | 125 | hwif->tp_ops->input_data(drive, NULL, id, SECTOR_SIZE); |
126 | local_irq_restore(flags); | ||
123 | 127 | ||
124 | drive->dev_flags |= IDE_DFLAG_ID_READ; | 128 | drive->dev_flags |= IDE_DFLAG_ID_READ; |
125 | |||
126 | local_irq_enable(); | ||
127 | #ifdef DEBUG | 129 | #ifdef DEBUG |
128 | printk(KERN_INFO "%s: dumping identify data\n", drive->name); | 130 | printk(KERN_INFO "%s: dumping identify data\n", drive->name); |
129 | ide_dump_identify((u8 *)id); | 131 | ide_dump_identify((u8 *)id); |
@@ -306,17 +308,12 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd) | |||
306 | s = tp_ops->read_status(hwif); | 308 | s = tp_ops->read_status(hwif); |
307 | 309 | ||
308 | if (OK_STAT(s, ATA_DRQ, BAD_R_STAT)) { | 310 | if (OK_STAT(s, ATA_DRQ, BAD_R_STAT)) { |
309 | unsigned long flags; | ||
310 | |||
311 | /* local CPU only; some systems need this */ | ||
312 | local_irq_save(flags); | ||
313 | /* drive returned ID */ | 311 | /* drive returned ID */ |
314 | do_identify(drive, cmd); | 312 | do_identify(drive, cmd); |
315 | /* drive responded with ID */ | 313 | /* drive responded with ID */ |
316 | rc = 0; | 314 | rc = 0; |
317 | /* clear drive IRQ */ | 315 | /* clear drive IRQ */ |
318 | (void)tp_ops->read_status(hwif); | 316 | (void)tp_ops->read_status(hwif); |
319 | local_irq_restore(flags); | ||
320 | } else { | 317 | } else { |
321 | /* drive refused ID */ | 318 | /* drive refused ID */ |
322 | rc = 2; | 319 | rc = 2; |
@@ -554,8 +551,8 @@ static void enable_nest (ide_drive_t *drive) | |||
554 | * 1 device was found | 551 | * 1 device was found |
555 | * (note: IDE_DFLAG_PRESENT might still be not set) | 552 | * (note: IDE_DFLAG_PRESENT might still be not set) |
556 | */ | 553 | */ |
557 | 554 | ||
558 | static inline u8 probe_for_drive (ide_drive_t *drive) | 555 | static u8 probe_for_drive(ide_drive_t *drive) |
559 | { | 556 | { |
560 | char *m; | 557 | char *m; |
561 | 558 | ||
@@ -642,7 +639,7 @@ static int ide_register_port(ide_hwif_t *hwif) | |||
642 | int ret; | 639 | int ret; |
643 | 640 | ||
644 | /* register with global device tree */ | 641 | /* register with global device tree */ |
645 | strlcpy(hwif->gendev.bus_id,hwif->name,BUS_ID_SIZE); | 642 | dev_set_name(&hwif->gendev, hwif->name); |
646 | hwif->gendev.driver_data = hwif; | 643 | hwif->gendev.driver_data = hwif; |
647 | if (hwif->gendev.parent == NULL) { | 644 | if (hwif->gendev.parent == NULL) { |
648 | if (hwif->dev) | 645 | if (hwif->dev) |
@@ -864,31 +861,6 @@ static void ide_port_tune_devices(ide_hwif_t *hwif) | |||
864 | } | 861 | } |
865 | 862 | ||
866 | /* | 863 | /* |
867 | * save_match() is used to simplify logic in init_irq() below. | ||
868 | * | ||
869 | * A loophole here is that we may not know about a particular | ||
870 | * hwif's irq until after that hwif is actually probed/initialized.. | ||
871 | * This could be a problem for the case where an hwif is on a | ||
872 | * dual interface that requires serialization (eg. cmd640) and another | ||
873 | * hwif using one of the same irqs is initialized beforehand. | ||
874 | * | ||
875 | * This routine detects and reports such situations, but does not fix them. | ||
876 | */ | ||
877 | static void save_match(ide_hwif_t *hwif, ide_hwif_t *new, ide_hwif_t **match) | ||
878 | { | ||
879 | ide_hwif_t *m = *match; | ||
880 | |||
881 | if (m && m->hwgroup && m->hwgroup != new->hwgroup) { | ||
882 | if (!new->hwgroup) | ||
883 | return; | ||
884 | printk(KERN_WARNING "%s: potential IRQ problem with %s and %s\n", | ||
885 | hwif->name, new->name, m->name); | ||
886 | } | ||
887 | if (!m || m->irq != hwif->irq) /* don't undo a prior perfect match */ | ||
888 | *match = new; | ||
889 | } | ||
890 | |||
891 | /* | ||
892 | * init request queue | 864 | * init request queue |
893 | */ | 865 | */ |
894 | static int ide_init_queue(ide_drive_t *drive) | 866 | static int ide_init_queue(ide_drive_t *drive) |
@@ -906,7 +878,8 @@ static int ide_init_queue(ide_drive_t *drive) | |||
906 | * do not. | 878 | * do not. |
907 | */ | 879 | */ |
908 | 880 | ||
909 | q = blk_init_queue_node(do_ide_request, &ide_lock, hwif_to_node(hwif)); | 881 | q = blk_init_queue_node(do_ide_request, &hwif->hwgroup->lock, |
882 | hwif_to_node(hwif)); | ||
910 | if (!q) | 883 | if (!q) |
911 | return 1; | 884 | return 1; |
912 | 885 | ||
@@ -947,7 +920,7 @@ static void ide_add_drive_to_hwgroup(ide_drive_t *drive) | |||
947 | { | 920 | { |
948 | ide_hwgroup_t *hwgroup = drive->hwif->hwgroup; | 921 | ide_hwgroup_t *hwgroup = drive->hwif->hwgroup; |
949 | 922 | ||
950 | spin_lock_irq(&ide_lock); | 923 | spin_lock_irq(&hwgroup->lock); |
951 | if (!hwgroup->drive) { | 924 | if (!hwgroup->drive) { |
952 | /* first drive for hwgroup. */ | 925 | /* first drive for hwgroup. */ |
953 | drive->next = drive; | 926 | drive->next = drive; |
@@ -957,7 +930,7 @@ static void ide_add_drive_to_hwgroup(ide_drive_t *drive) | |||
957 | drive->next = hwgroup->drive->next; | 930 | drive->next = hwgroup->drive->next; |
958 | hwgroup->drive->next = drive; | 931 | hwgroup->drive->next = drive; |
959 | } | 932 | } |
960 | spin_unlock_irq(&ide_lock); | 933 | spin_unlock_irq(&hwgroup->lock); |
961 | } | 934 | } |
962 | 935 | ||
963 | /* | 936 | /* |
@@ -1002,7 +975,7 @@ void ide_remove_port_from_hwgroup(ide_hwif_t *hwif) | |||
1002 | 975 | ||
1003 | ide_ports[hwif->index] = NULL; | 976 | ide_ports[hwif->index] = NULL; |
1004 | 977 | ||
1005 | spin_lock_irq(&ide_lock); | 978 | spin_lock_irq(&hwgroup->lock); |
1006 | /* | 979 | /* |
1007 | * Remove us from the hwgroup, and free | 980 | * Remove us from the hwgroup, and free |
1008 | * the hwgroup if we were the only member | 981 | * the hwgroup if we were the only member |
@@ -1030,7 +1003,7 @@ void ide_remove_port_from_hwgroup(ide_hwif_t *hwif) | |||
1030 | } | 1003 | } |
1031 | BUG_ON(hwgroup->hwif == hwif); | 1004 | BUG_ON(hwgroup->hwif == hwif); |
1032 | } | 1005 | } |
1033 | spin_unlock_irq(&ide_lock); | 1006 | spin_unlock_irq(&hwgroup->lock); |
1034 | } | 1007 | } |
1035 | 1008 | ||
1036 | /* | 1009 | /* |
@@ -1051,27 +1024,13 @@ static int init_irq (ide_hwif_t *hwif) | |||
1051 | mutex_lock(&ide_cfg_mtx); | 1024 | mutex_lock(&ide_cfg_mtx); |
1052 | hwif->hwgroup = NULL; | 1025 | hwif->hwgroup = NULL; |
1053 | 1026 | ||
1054 | /* | ||
1055 | * Group up with any other hwifs that share our irq(s). | ||
1056 | */ | ||
1057 | for (index = 0; index < MAX_HWIFS; index++) { | 1027 | for (index = 0; index < MAX_HWIFS; index++) { |
1058 | ide_hwif_t *h = ide_ports[index]; | 1028 | ide_hwif_t *h = ide_ports[index]; |
1059 | 1029 | ||
1060 | if (h && h->hwgroup) { /* scan only initialized ports */ | 1030 | if (h && h->hwgroup) { /* scan only initialized ports */ |
1061 | if (hwif->irq == h->irq) { | 1031 | if (hwif->host->host_flags & IDE_HFLAG_SERIALIZE) { |
1062 | hwif->sharing_irq = h->sharing_irq = 1; | 1032 | if (hwif->host == h->host) |
1063 | if (hwif->chipset != ide_pci || | 1033 | match = h; |
1064 | h->chipset != ide_pci) { | ||
1065 | save_match(hwif, h, &match); | ||
1066 | } | ||
1067 | } | ||
1068 | if (hwif->serialized) { | ||
1069 | if (hwif->mate && hwif->mate->irq == h->irq) | ||
1070 | save_match(hwif, h, &match); | ||
1071 | } | ||
1072 | if (h->serialized) { | ||
1073 | if (h->mate && hwif->irq == h->mate->irq) | ||
1074 | save_match(hwif, h, &match); | ||
1075 | } | 1034 | } |
1076 | } | 1035 | } |
1077 | } | 1036 | } |
@@ -1092,17 +1051,19 @@ static int init_irq (ide_hwif_t *hwif) | |||
1092 | * linked list, the first entry is the hwif that owns | 1051 | * linked list, the first entry is the hwif that owns |
1093 | * hwgroup->handler - do not change that. | 1052 | * hwgroup->handler - do not change that. |
1094 | */ | 1053 | */ |
1095 | spin_lock_irq(&ide_lock); | 1054 | spin_lock_irq(&hwgroup->lock); |
1096 | hwif->next = hwgroup->hwif->next; | 1055 | hwif->next = hwgroup->hwif->next; |
1097 | hwgroup->hwif->next = hwif; | 1056 | hwgroup->hwif->next = hwif; |
1098 | BUG_ON(hwif->next == hwif); | 1057 | BUG_ON(hwif->next == hwif); |
1099 | spin_unlock_irq(&ide_lock); | 1058 | spin_unlock_irq(&hwgroup->lock); |
1100 | } else { | 1059 | } else { |
1101 | hwgroup = kmalloc_node(sizeof(*hwgroup), GFP_KERNEL|__GFP_ZERO, | 1060 | hwgroup = kmalloc_node(sizeof(*hwgroup), GFP_KERNEL|__GFP_ZERO, |
1102 | hwif_to_node(hwif)); | 1061 | hwif_to_node(hwif)); |
1103 | if (hwgroup == NULL) | 1062 | if (hwgroup == NULL) |
1104 | goto out_up; | 1063 | goto out_up; |
1105 | 1064 | ||
1065 | spin_lock_init(&hwgroup->lock); | ||
1066 | |||
1106 | hwif->hwgroup = hwgroup; | 1067 | hwif->hwgroup = hwgroup; |
1107 | hwgroup->hwif = hwif->next = hwif; | 1068 | hwgroup->hwif = hwif->next = hwif; |
1108 | 1069 | ||
@@ -1122,8 +1083,7 @@ static int init_irq (ide_hwif_t *hwif) | |||
1122 | sa = IRQF_SHARED; | 1083 | sa = IRQF_SHARED; |
1123 | #endif /* __mc68000__ */ | 1084 | #endif /* __mc68000__ */ |
1124 | 1085 | ||
1125 | if (hwif->chipset == ide_pci || hwif->chipset == ide_cmd646 || | 1086 | if (hwif->chipset == ide_pci) |
1126 | hwif->chipset == ide_ali14xx) | ||
1127 | sa = IRQF_SHARED; | 1087 | sa = IRQF_SHARED; |
1128 | 1088 | ||
1129 | if (io_ports->ctl_addr) | 1089 | if (io_ports->ctl_addr) |
@@ -1150,8 +1110,7 @@ static int init_irq (ide_hwif_t *hwif) | |||
1150 | io_ports->data_addr, hwif->irq); | 1110 | io_ports->data_addr, hwif->irq); |
1151 | #endif /* __mc68000__ */ | 1111 | #endif /* __mc68000__ */ |
1152 | if (match) | 1112 | if (match) |
1153 | printk(KERN_CONT " (%sed with %s)", | 1113 | printk(KERN_CONT " (serialized with %s)", match->name); |
1154 | hwif->sharing_irq ? "shar" : "serializ", match->name); | ||
1155 | printk(KERN_CONT "\n"); | 1114 | printk(KERN_CONT "\n"); |
1156 | 1115 | ||
1157 | mutex_unlock(&ide_cfg_mtx); | 1116 | mutex_unlock(&ide_cfg_mtx); |
@@ -1263,20 +1222,21 @@ static void ide_remove_drive_from_hwgroup(ide_drive_t *drive) | |||
1263 | static void drive_release_dev (struct device *dev) | 1222 | static void drive_release_dev (struct device *dev) |
1264 | { | 1223 | { |
1265 | ide_drive_t *drive = container_of(dev, ide_drive_t, gendev); | 1224 | ide_drive_t *drive = container_of(dev, ide_drive_t, gendev); |
1225 | ide_hwgroup_t *hwgroup = drive->hwif->hwgroup; | ||
1266 | 1226 | ||
1267 | ide_proc_unregister_device(drive); | 1227 | ide_proc_unregister_device(drive); |
1268 | 1228 | ||
1269 | spin_lock_irq(&ide_lock); | 1229 | spin_lock_irq(&hwgroup->lock); |
1270 | ide_remove_drive_from_hwgroup(drive); | 1230 | ide_remove_drive_from_hwgroup(drive); |
1271 | kfree(drive->id); | 1231 | kfree(drive->id); |
1272 | drive->id = NULL; | 1232 | drive->id = NULL; |
1273 | drive->dev_flags &= ~IDE_DFLAG_PRESENT; | 1233 | drive->dev_flags &= ~IDE_DFLAG_PRESENT; |
1274 | /* Messed up locking ... */ | 1234 | /* Messed up locking ... */ |
1275 | spin_unlock_irq(&ide_lock); | 1235 | spin_unlock_irq(&hwgroup->lock); |
1276 | blk_cleanup_queue(drive->queue); | 1236 | blk_cleanup_queue(drive->queue); |
1277 | spin_lock_irq(&ide_lock); | 1237 | spin_lock_irq(&hwgroup->lock); |
1278 | drive->queue = NULL; | 1238 | drive->queue = NULL; |
1279 | spin_unlock_irq(&ide_lock); | 1239 | spin_unlock_irq(&hwgroup->lock); |
1280 | 1240 | ||
1281 | complete(&drive->gendev_rel_comp); | 1241 | complete(&drive->gendev_rel_comp); |
1282 | } | 1242 | } |
@@ -1352,7 +1312,7 @@ static void hwif_register_devices(ide_hwif_t *hwif) | |||
1352 | if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) | 1312 | if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) |
1353 | continue; | 1313 | continue; |
1354 | 1314 | ||
1355 | snprintf(dev->bus_id, BUS_ID_SIZE, "%u.%u", hwif->index, i); | 1315 | dev_set_name(dev, "%u.%u", hwif->index, i); |
1356 | dev->parent = &hwif->gendev; | 1316 | dev->parent = &hwif->gendev; |
1357 | dev->bus = &ide_bus_type; | 1317 | dev->bus = &ide_bus_type; |
1358 | dev->driver_data = drive; | 1318 | dev->driver_data = drive; |
@@ -1436,13 +1396,11 @@ static void ide_init_port(ide_hwif_t *hwif, unsigned int port, | |||
1436 | } | 1396 | } |
1437 | 1397 | ||
1438 | if ((d->host_flags & IDE_HFLAG_SERIALIZE) || | 1398 | if ((d->host_flags & IDE_HFLAG_SERIALIZE) || |
1439 | ((d->host_flags & IDE_HFLAG_SERIALIZE_DMA) && hwif->dma_base)) { | 1399 | ((d->host_flags & IDE_HFLAG_SERIALIZE_DMA) && hwif->dma_base)) |
1440 | if (hwif->mate) | 1400 | hwif->host->host_flags |= IDE_HFLAG_SERIALIZE; |
1441 | hwif->mate->serialized = hwif->serialized = 1; | ||
1442 | } | ||
1443 | 1401 | ||
1444 | if (d->host_flags & IDE_HFLAG_RQSIZE_256) | 1402 | if (d->max_sectors) |
1445 | hwif->rqsize = 256; | 1403 | hwif->rqsize = d->max_sectors; |
1446 | 1404 | ||
1447 | /* call chipset specific routine for each enabled port */ | 1405 | /* call chipset specific routine for each enabled port */ |
1448 | if (d->init_hwif) | 1406 | if (d->init_hwif) |
@@ -1794,59 +1752,3 @@ void ide_port_scan(ide_hwif_t *hwif) | |||
1794 | ide_proc_port_register_devices(hwif); | 1752 | ide_proc_port_register_devices(hwif); |
1795 | } | 1753 | } |
1796 | EXPORT_SYMBOL_GPL(ide_port_scan); | 1754 | EXPORT_SYMBOL_GPL(ide_port_scan); |
1797 | |||
1798 | static void ide_legacy_init_one(hw_regs_t **hws, hw_regs_t *hw, | ||
1799 | u8 port_no, const struct ide_port_info *d, | ||
1800 | unsigned long config) | ||
1801 | { | ||
1802 | unsigned long base, ctl; | ||
1803 | int irq; | ||
1804 | |||
1805 | if (port_no == 0) { | ||
1806 | base = 0x1f0; | ||
1807 | ctl = 0x3f6; | ||
1808 | irq = 14; | ||
1809 | } else { | ||
1810 | base = 0x170; | ||
1811 | ctl = 0x376; | ||
1812 | irq = 15; | ||
1813 | } | ||
1814 | |||
1815 | if (!request_region(base, 8, d->name)) { | ||
1816 | printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n", | ||
1817 | d->name, base, base + 7); | ||
1818 | return; | ||
1819 | } | ||
1820 | |||
1821 | if (!request_region(ctl, 1, d->name)) { | ||
1822 | printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n", | ||
1823 | d->name, ctl); | ||
1824 | release_region(base, 8); | ||
1825 | return; | ||
1826 | } | ||
1827 | |||
1828 | ide_std_init_ports(hw, base, ctl); | ||
1829 | hw->irq = irq; | ||
1830 | hw->chipset = d->chipset; | ||
1831 | hw->config = config; | ||
1832 | |||
1833 | hws[port_no] = hw; | ||
1834 | } | ||
1835 | |||
1836 | int ide_legacy_device_add(const struct ide_port_info *d, unsigned long config) | ||
1837 | { | ||
1838 | hw_regs_t hw[2], *hws[] = { NULL, NULL, NULL, NULL }; | ||
1839 | |||
1840 | memset(&hw, 0, sizeof(hw)); | ||
1841 | |||
1842 | if ((d->host_flags & IDE_HFLAG_QD_2ND_PORT) == 0) | ||
1843 | ide_legacy_init_one(hws, &hw[0], 0, d, config); | ||
1844 | ide_legacy_init_one(hws, &hw[1], 1, d, config); | ||
1845 | |||
1846 | if (hws[0] == NULL && hws[1] == NULL && | ||
1847 | (d->host_flags & IDE_HFLAG_SINGLE)) | ||
1848 | return -ENOENT; | ||
1849 | |||
1850 | return ide_host_add(d, hws, NULL); | ||
1851 | } | ||
1852 | EXPORT_SYMBOL_GPL(ide_legacy_device_add); | ||