diff options
author | Hugh Dickins <hugh.dickins@tiscali.co.uk> | 2009-06-10 08:37:20 -0400 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2009-06-10 08:37:20 -0400 |
commit | 5f4417a156a6e44359effa9492de3ed5638a9b13 (patch) | |
tree | 7868d60ce2c0b38b07727090c865d04fa93a622d /drivers | |
parent | a20b2a44eca52818ef52a94959480b7e6ea2f528 (diff) |
ide: fix PowerMac bootup oops
PowerMac bootup with CONFIG_IDE=y oopses in ide_pio_cycle_time():
because "ide: try to use PIO Mode 0 during probe if possible" causes
pmac_ide_set_pio_mode() to be called before drive->id has been set.
Bart points out other places which now need drive->id set earlier,
so follow his advice to allocate it in ide_port_alloc_devices()
(using kzalloc_node, without error message, as when allocating drive)
and memset it for reuse in ide_port_init_devices_data().
Fixed in passing: ide_host_alloc() was missing ide_port_free_devices()
from an error path.
Signed-off-by: Hugh Dickins <hugh.dickins@tiscali.co.uk>
Cc: Joao Ramos <joao.ramos@inov.pt>
Cc: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ide/ide-probe.c | 47 |
1 files changed, 21 insertions, 26 deletions
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index f9c2fb7d0005..f371b0de314f 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c | |||
@@ -465,23 +465,8 @@ static u8 probe_for_drive(ide_drive_t *drive) | |||
465 | int rc; | 465 | int rc; |
466 | u8 cmd; | 466 | u8 cmd; |
467 | 467 | ||
468 | /* | ||
469 | * In order to keep things simple we have an id | ||
470 | * block for all drives at all times. If the device | ||
471 | * is pre ATA or refuses ATA/ATAPI identify we | ||
472 | * will add faked data to this. | ||
473 | * | ||
474 | * Also note that 0 everywhere means "can't do X" | ||
475 | */ | ||
476 | |||
477 | drive->dev_flags &= ~IDE_DFLAG_ID_READ; | 468 | drive->dev_flags &= ~IDE_DFLAG_ID_READ; |
478 | 469 | ||
479 | drive->id = kzalloc(SECTOR_SIZE, GFP_KERNEL); | ||
480 | if (drive->id == NULL) { | ||
481 | printk(KERN_ERR "ide: out of memory for id data.\n"); | ||
482 | return 0; | ||
483 | } | ||
484 | |||
485 | m = (char *)&drive->id[ATA_ID_PROD]; | 470 | m = (char *)&drive->id[ATA_ID_PROD]; |
486 | strcpy(m, "UNKNOWN"); | 471 | strcpy(m, "UNKNOWN"); |
487 | 472 | ||
@@ -497,7 +482,7 @@ static u8 probe_for_drive(ide_drive_t *drive) | |||
497 | } | 482 | } |
498 | 483 | ||
499 | if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) | 484 | if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) |
500 | goto out_free; | 485 | return 0; |
501 | 486 | ||
502 | /* identification failed? */ | 487 | /* identification failed? */ |
503 | if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) { | 488 | if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) { |
@@ -521,7 +506,7 @@ static u8 probe_for_drive(ide_drive_t *drive) | |||
521 | } | 506 | } |
522 | 507 | ||
523 | if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) | 508 | if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) |
524 | goto out_free; | 509 | return 0; |
525 | 510 | ||
526 | /* The drive wasn't being helpful. Add generic info only */ | 511 | /* The drive wasn't being helpful. Add generic info only */ |
527 | if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) { | 512 | if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) { |
@@ -535,9 +520,6 @@ static u8 probe_for_drive(ide_drive_t *drive) | |||
535 | } | 520 | } |
536 | 521 | ||
537 | return 1; | 522 | return 1; |
538 | out_free: | ||
539 | kfree(drive->id); | ||
540 | return 0; | ||
541 | } | 523 | } |
542 | 524 | ||
543 | static void hwif_release_dev(struct device *dev) | 525 | static void hwif_release_dev(struct device *dev) |
@@ -825,8 +807,6 @@ static int ide_port_setup_devices(ide_hwif_t *hwif) | |||
825 | if (ide_init_queue(drive)) { | 807 | if (ide_init_queue(drive)) { |
826 | printk(KERN_ERR "ide: failed to init %s\n", | 808 | printk(KERN_ERR "ide: failed to init %s\n", |
827 | drive->name); | 809 | drive->name); |
828 | kfree(drive->id); | ||
829 | drive->id = NULL; | ||
830 | drive->dev_flags &= ~IDE_DFLAG_PRESENT; | 810 | drive->dev_flags &= ~IDE_DFLAG_PRESENT; |
831 | continue; | 811 | continue; |
832 | } | 812 | } |
@@ -955,9 +935,6 @@ static void drive_release_dev (struct device *dev) | |||
955 | blk_cleanup_queue(drive->queue); | 935 | blk_cleanup_queue(drive->queue); |
956 | drive->queue = NULL; | 936 | drive->queue = NULL; |
957 | 937 | ||
958 | kfree(drive->id); | ||
959 | drive->id = NULL; | ||
960 | |||
961 | drive->dev_flags &= ~IDE_DFLAG_PRESENT; | 938 | drive->dev_flags &= ~IDE_DFLAG_PRESENT; |
962 | 939 | ||
963 | complete(&drive->gendev_rel_comp); | 940 | complete(&drive->gendev_rel_comp); |
@@ -1140,8 +1117,11 @@ static void ide_port_init_devices_data(ide_hwif_t *hwif) | |||
1140 | 1117 | ||
1141 | ide_port_for_each_dev(i, drive, hwif) { | 1118 | ide_port_for_each_dev(i, drive, hwif) { |
1142 | u8 j = (hwif->index * MAX_DRIVES) + i; | 1119 | u8 j = (hwif->index * MAX_DRIVES) + i; |
1120 | u16 *saved_id = drive->id; | ||
1143 | 1121 | ||
1144 | memset(drive, 0, sizeof(*drive)); | 1122 | memset(drive, 0, sizeof(*drive)); |
1123 | memset(saved_id, 0, SECTOR_SIZE); | ||
1124 | drive->id = saved_id; | ||
1145 | 1125 | ||
1146 | drive->media = ide_disk; | 1126 | drive->media = ide_disk; |
1147 | drive->select = (i << 4) | ATA_DEVICE_OBS; | 1127 | drive->select = (i << 4) | ATA_DEVICE_OBS; |
@@ -1248,8 +1228,10 @@ static void ide_port_free_devices(ide_hwif_t *hwif) | |||
1248 | ide_drive_t *drive; | 1228 | ide_drive_t *drive; |
1249 | int i; | 1229 | int i; |
1250 | 1230 | ||
1251 | ide_port_for_each_dev(i, drive, hwif) | 1231 | ide_port_for_each_dev(i, drive, hwif) { |
1232 | kfree(drive->id); | ||
1252 | kfree(drive); | 1233 | kfree(drive); |
1234 | } | ||
1253 | } | 1235 | } |
1254 | 1236 | ||
1255 | static int ide_port_alloc_devices(ide_hwif_t *hwif, int node) | 1237 | static int ide_port_alloc_devices(ide_hwif_t *hwif, int node) |
@@ -1263,6 +1245,18 @@ static int ide_port_alloc_devices(ide_hwif_t *hwif, int node) | |||
1263 | if (drive == NULL) | 1245 | if (drive == NULL) |
1264 | goto out_nomem; | 1246 | goto out_nomem; |
1265 | 1247 | ||
1248 | /* | ||
1249 | * In order to keep things simple we have an id | ||
1250 | * block for all drives at all times. If the device | ||
1251 | * is pre ATA or refuses ATA/ATAPI identify we | ||
1252 | * will add faked data to this. | ||
1253 | * | ||
1254 | * Also note that 0 everywhere means "can't do X" | ||
1255 | */ | ||
1256 | drive->id = kzalloc_node(SECTOR_SIZE, GFP_KERNEL, node); | ||
1257 | if (drive->id == NULL) | ||
1258 | goto out_nomem; | ||
1259 | |||
1266 | hwif->devices[i] = drive; | 1260 | hwif->devices[i] = drive; |
1267 | } | 1261 | } |
1268 | return 0; | 1262 | return 0; |
@@ -1304,6 +1298,7 @@ struct ide_host *ide_host_alloc(const struct ide_port_info *d, | |||
1304 | if (idx < 0) { | 1298 | if (idx < 0) { |
1305 | printk(KERN_ERR "%s: no free slot for interface\n", | 1299 | printk(KERN_ERR "%s: no free slot for interface\n", |
1306 | d ? d->name : "ide"); | 1300 | d ? d->name : "ide"); |
1301 | ide_port_free_devices(hwif); | ||
1307 | kfree(hwif); | 1302 | kfree(hwif); |
1308 | continue; | 1303 | continue; |
1309 | } | 1304 | } |