Commit 0b0f135d authored by Alexander Viro's avatar Alexander Viro Committed by James Bottomley

[PATCH] saner initialization order in IDE (gendisks allocated slightly earlier)

	* we move allocation of gendisks in ide-probe to the moment when
queues are set up, so everything that wants to feed requests in one of
IDE queues can safely set ->rq_disk
parent 5e40b913
...@@ -1008,27 +1008,17 @@ struct gendisk *ata_probe(dev_t dev, int *part, void *data) ...@@ -1008,27 +1008,17 @@ struct gendisk *ata_probe(dev_t dev, int *part, void *data)
return drive->disk; return drive->disk;
} }
/* static int alloc_disks(ide_hwif_t *hwif)
* init_gendisk() (as opposed to ide_geninit) is called for each major device,
* after probing for drives, to allocate partition tables and other data
* structures needed for the routines in genhd.c. ide_geninit() gets called
* somewhat later, during the partition check.
*/
static void init_gendisk (ide_hwif_t *hwif)
{ {
unsigned int unit, units; unsigned int unit;
extern devfs_handle_t ide_devfs_handle;
struct gendisk *disks[MAX_DRIVES]; struct gendisk *disks[MAX_DRIVES];
units = MAX_DRIVES;
for (unit = 0; unit < MAX_DRIVES; unit++) { for (unit = 0; unit < MAX_DRIVES; unit++) {
disks[unit] = alloc_disk(1 << PARTN_BITS); disks[unit] = alloc_disk(1 << PARTN_BITS);
if (!disks[unit]) if (!disks[unit])
goto err_kmalloc_gd; goto Enomem;
} }
for (unit = 0; unit < MAX_DRIVES; ++unit) {
for (unit = 0; unit < units; ++unit) {
ide_drive_t *drive = &hwif->drives[unit]; ide_drive_t *drive = &hwif->drives[unit];
struct gendisk *disk = disks[unit]; struct gendisk *disk = disks[unit];
disk->major = hwif->major; disk->major = hwif->major;
...@@ -1039,48 +1029,57 @@ static void init_gendisk (ide_hwif_t *hwif) ...@@ -1039,48 +1029,57 @@ static void init_gendisk (ide_hwif_t *hwif)
disk->queue = &drive->queue; disk->queue = &drive->queue;
drive->disk = disk; drive->disk = disk;
} }
return 0;
Enomem:
printk(KERN_WARNING "(ide::init_gendisk) Out of memory\n");
while (unit--)
put_disk(disks[unit]);
return -ENOMEM;
}
for (unit = 0; unit < units; ++unit) { /*
char name[64]; * init_gendisk() (as opposed to ide_geninit) is called for each major device,
ide_add_generic_settings(hwif->drives + unit); * after probing for drives, to allocate partition tables and other data
sprintf (name, "host%d/bus%d/target%d/lun%d", * structures needed for the routines in genhd.c. ide_geninit() gets called
(hwif->channel && hwif->mate) ? * somewhat later, during the partition check.
hwif->mate->index : hwif->index, */
hwif->channel, unit, hwif->drives[unit].lun); static void init_gendisk (ide_hwif_t *hwif)
if (hwif->drives[unit].present) {
hwif->drives[unit].de = devfs_mk_dir(ide_devfs_handle, name, NULL); unsigned int unit;
} extern devfs_handle_t ide_devfs_handle;
for (unit = 0; unit < units; ++unit) { for (unit = 0; unit < MAX_DRIVES; ++unit) {
ide_drive_t * drive = &hwif->drives[unit]; ide_drive_t * drive = &hwif->drives[unit];
char name[64];
ide_add_generic_settings(drive);
snprintf(drive->gendev.bus_id,BUS_ID_SIZE,"%u.%u", snprintf(drive->gendev.bus_id,BUS_ID_SIZE,"%u.%u",
hwif->index,unit); hwif->index,unit);
snprintf(drive->gendev.name,DEVICE_NAME_SIZE, snprintf(drive->gendev.name,DEVICE_NAME_SIZE,
"%s","IDE Drive"); "%s","IDE Drive");
drive->gendev.parent = &hwif->gendev; drive->gendev.parent = &hwif->gendev;
drive->gendev.bus = &ide_bus_type; drive->gendev.bus = &ide_bus_type;
if (drive->present) sprintf (name, "host%d/bus%d/target%d/lun%d",
(hwif->channel && hwif->mate) ?
hwif->mate->index : hwif->index,
hwif->channel, unit, drive->lun);
if (drive->present) {
device_register(&drive->gendev); device_register(&drive->gendev);
drive->de = devfs_mk_dir(ide_devfs_handle, name, NULL);
} }
}
blk_register_region(MKDEV(hwif->major, 0), units << PARTN_BITS, blk_register_region(MKDEV(hwif->major, 0), MAX_DRIVES << PARTN_BITS,
THIS_MODULE, ata_probe, ata_lock, hwif); THIS_MODULE, ata_probe, ata_lock, hwif);
return;
err_kmalloc_gd:
printk(KERN_WARNING "(ide::init_gendisk) Out of memory\n");
while (unit--)
put_disk(disks[unit]);
} }
EXPORT_SYMBOL(init_gendisk); EXPORT_SYMBOL(init_gendisk);
int hwif_init (ide_hwif_t *hwif) int hwif_init (ide_hwif_t *hwif)
{ {
int old_irq, unit;
if (!hwif->present) if (!hwif->present)
return 0; return 0;
if (!hwif->irq) { if (!hwif->irq) {
if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]))) if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET])))
{ {
...@@ -1102,33 +1101,47 @@ int hwif_init (ide_hwif_t *hwif) ...@@ -1102,33 +1101,47 @@ int hwif_init (ide_hwif_t *hwif)
if (register_blkdev (hwif->major, hwif->name, ide_fops)) { if (register_blkdev (hwif->major, hwif->name, ide_fops)) {
printk("%s: UNABLE TO GET MAJOR NUMBER %d\n", printk("%s: UNABLE TO GET MAJOR NUMBER %d\n",
hwif->name, hwif->major); hwif->name, hwif->major);
return (hwif->present = 0); return 0;
} }
if (init_irq(hwif)) { if (alloc_disks(hwif) < 0)
int i = hwif->irq; goto out;
if (init_irq(hwif) == 0)
goto done;
old_irq = hwif->irq;
/* /*
* It failed to initialise. Find the default IRQ for * It failed to initialise. Find the default IRQ for
* this port and try that. * this port and try that.
*/ */
if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]))) { if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]))) {
printk("%s: Disabled unable to get IRQ %d.\n", printk("%s: Disabled unable to get IRQ %d.\n",
hwif->name, i); hwif->name, old_irq);
(void) unregister_blkdev(hwif->major, hwif->name); goto out_disks;
return (hwif->present = 0);
} }
if (init_irq(hwif)) { if (init_irq(hwif)) {
printk("%s: probed IRQ %d and default IRQ %d failed.\n", printk("%s: probed IRQ %d and default IRQ %d failed.\n",
hwif->name, i, hwif->irq); hwif->name, old_irq, hwif->irq);
(void) unregister_blkdev(hwif->major, hwif->name); goto out_disks;
return (hwif->present = 0);
} }
printk("%s: probed IRQ %d failed, using default.\n", printk("%s: probed IRQ %d failed, using default.\n",
hwif->name, hwif->irq); hwif->name, hwif->irq);
}
done:
init_gendisk(hwif); init_gendisk(hwif);
hwif->present = 1; /* success */ hwif->present = 1; /* success */
return 1; return 1;
out_disks:
for (unit = 0; unit < MAX_DRIVES; unit++) {
struct gendisk *disk = hwif->drives[unit].disk;
hwif->drives[unit].disk = NULL;
put_disk(disk);
}
out:
unregister_blkdev(hwif->major, hwif->name);
return 0;
} }
EXPORT_SYMBOL(hwif_init); EXPORT_SYMBOL(hwif_init);
......
...@@ -1315,7 +1315,6 @@ int ide_diag_taskfile (ide_drive_t *drive, ide_task_t *args, unsigned long data_ ...@@ -1315,7 +1315,6 @@ int ide_diag_taskfile (ide_drive_t *drive, ide_task_t *args, unsigned long data_
struct request *rq; struct request *rq;
unsigned long flags; unsigned long flags;
ide_hwgroup_t *hwgroup = HWGROUP(drive); ide_hwgroup_t *hwgroup = HWGROUP(drive);
unsigned int major = HWIF(drive)->major;
struct list_head *queue_head = &drive->queue.queue_head; struct list_head *queue_head = &drive->queue.queue_head;
DECLARE_COMPLETION(wait); DECLARE_COMPLETION(wait);
...@@ -1357,7 +1356,8 @@ int ide_diag_taskfile (ide_drive_t *drive, ide_task_t *args, unsigned long data_ ...@@ -1357,7 +1356,8 @@ int ide_diag_taskfile (ide_drive_t *drive, ide_task_t *args, unsigned long data_
rq->special = args; rq->special = args;
rq->errors = 0; rq->errors = 0;
rq->rq_status = RQ_ACTIVE; rq->rq_status = RQ_ACTIVE;
rq->rq_dev = MKDEV(major,(drive->select.b.unit)<<PARTN_BITS); rq->rq_dev = mk_kdev(disk->major, disk->first_minor);
rq->rq_disk = drive->disk;
rq->waiting = &wait; rq->waiting = &wait;
spin_lock_irqsave(&ide_lock, flags); spin_lock_irqsave(&ide_lock, flags);
......
...@@ -1530,18 +1530,7 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio ...@@ -1530,18 +1530,7 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio
rq->errors = 0; rq->errors = 0;
rq->rq_status = RQ_ACTIVE; rq->rq_status = RQ_ACTIVE;
/*
* Aiee. This is ugly, but it gets called before "drive->disk"
* has been initialized. Al will fix it, I'm sure.
*/
if (drive->disk)
rq->rq_dev = mk_kdev(drive->disk->major, drive->disk->first_minor); rq->rq_dev = mk_kdev(drive->disk->major, drive->disk->first_minor);
else {
printk("IDE init is ugly:");
dump_stack();
rq->rq_dev = mk_kdev(HWIF(drive)->major, (drive->select.b.unit) << PARTN_BITS);
}
rq->rq_disk = drive->disk; rq->rq_disk = drive->disk;
/* /*
...@@ -1819,12 +1808,12 @@ void ide_unregister (unsigned int index) ...@@ -1819,12 +1808,12 @@ void ide_unregister (unsigned int index)
* Remove us from the kernel's knowledge * Remove us from the kernel's knowledge
*/ */
blk_unregister_region(MKDEV(hwif->major, 0), MAX_DRIVES<<PARTN_BITS); blk_unregister_region(MKDEV(hwif->major, 0), MAX_DRIVES<<PARTN_BITS);
unregister_blkdev(hwif->major, hwif->name);
for (i = 0; i < MAX_DRIVES; i++) { for (i = 0; i < MAX_DRIVES; i++) {
struct gendisk *disk = hwif->drives[i].disk; struct gendisk *disk = hwif->drives[i].disk;
hwif->drives[i].disk = NULL; hwif->drives[i].disk = NULL;
put_disk(disk); put_disk(disk);
} }
unregister_blkdev(hwif->major, hwif->name);
old_hwif = *hwif; old_hwif = *hwif;
init_hwif_data(index); /* restore hwif data to pristine status */ init_hwif_data(index); /* restore hwif data to pristine status */
hwif->hwgroup = old_hwif.hwgroup; hwif->hwgroup = old_hwif.hwgroup;
......
...@@ -1583,7 +1583,8 @@ idepmac_wake_device(ide_drive_t *drive, int used_dma) ...@@ -1583,7 +1583,8 @@ idepmac_wake_device(ide_drive_t *drive, int used_dma)
DRIVER(drive)->media_change(drive); DRIVER(drive)->media_change(drive);
/* We kick the VFS too (see fix in ide.c revalidate) */ /* We kick the VFS too (see fix in ide.c revalidate) */
check_disk_change(MKDEV(HWIF(drive)->major, (drive->select.b.unit) << PARTN_BITS)); if (DRIVER(drive))
check_disk_change(MKDEV(drive->disk->major, drive->disk->first_minor));
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
/* We re-enable DMA on the drive if it was active. */ /* We re-enable DMA on the drive if it was active. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment