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)
return drive->disk;
}
/*
* 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)
static int alloc_disks(ide_hwif_t *hwif)
{
unsigned int unit, units;
extern devfs_handle_t ide_devfs_handle;
unsigned int unit;
struct gendisk *disks[MAX_DRIVES];
units = MAX_DRIVES;
for (unit = 0; unit < MAX_DRIVES; unit++) {
disks[unit] = alloc_disk(1 << PARTN_BITS);
if (!disks[unit])
goto err_kmalloc_gd;
goto Enomem;
}
for (unit = 0; unit < units; ++unit) {
for (unit = 0; unit < MAX_DRIVES; ++unit) {
ide_drive_t *drive = &hwif->drives[unit];
struct gendisk *disk = disks[unit];
disk->major = hwif->major;
......@@ -1039,48 +1029,57 @@ static void init_gendisk (ide_hwif_t *hwif)
disk->queue = &drive->queue;
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];
ide_add_generic_settings(hwif->drives + unit);
sprintf (name, "host%d/bus%d/target%d/lun%d",
(hwif->channel && hwif->mate) ?
hwif->mate->index : hwif->index,
hwif->channel, unit, hwif->drives[unit].lun);
if (hwif->drives[unit].present)
hwif->drives[unit].de = devfs_mk_dir(ide_devfs_handle, name, NULL);
}
for (unit = 0; unit < units; ++unit) {
ide_drive_t * drive = &hwif->drives[unit];
/*
* 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;
extern devfs_handle_t ide_devfs_handle;
for (unit = 0; unit < MAX_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",
hwif->index,unit);
snprintf(drive->gendev.name,DEVICE_NAME_SIZE,
"%s","IDE Drive");
drive->gendev.parent = &hwif->gendev;
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);
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);
return;
err_kmalloc_gd:
printk(KERN_WARNING "(ide::init_gendisk) Out of memory\n");
while (unit--)
put_disk(disks[unit]);
}
EXPORT_SYMBOL(init_gendisk);
int hwif_init (ide_hwif_t *hwif)
{
int old_irq, unit;
if (!hwif->present)
return 0;
if (!hwif->irq) {
if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET])))
{
......@@ -1102,33 +1101,47 @@ int hwif_init (ide_hwif_t *hwif)
if (register_blkdev (hwif->major, hwif->name, ide_fops)) {
printk("%s: UNABLE TO GET MAJOR NUMBER %d\n",
hwif->name, hwif->major);
return (hwif->present = 0);
return 0;
}
if (alloc_disks(hwif) < 0)
goto out;
if (init_irq(hwif) == 0)
goto done;
old_irq = hwif->irq;
/*
* It failed to initialise. Find the default IRQ for
* this port and try that.
*/
if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]))) {
printk("%s: Disabled unable to get IRQ %d.\n",
hwif->name, old_irq);
goto out_disks;
}
if (init_irq(hwif)) {
int i = hwif->irq;
/*
* It failed to initialise. Find the default IRQ for
* this port and try that.
*/
if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]))) {
printk("%s: Disabled unable to get IRQ %d.\n",
hwif->name, i);
(void) unregister_blkdev(hwif->major, hwif->name);
return (hwif->present = 0);
}
if (init_irq(hwif)) {
printk("%s: probed IRQ %d and default IRQ %d failed.\n",
hwif->name, i, hwif->irq);
(void) unregister_blkdev(hwif->major, hwif->name);
return (hwif->present = 0);
}
printk("%s: probed IRQ %d failed, using default.\n",
hwif->name, hwif->irq);
printk("%s: probed IRQ %d and default IRQ %d failed.\n",
hwif->name, old_irq, hwif->irq);
goto out_disks;
}
printk("%s: probed IRQ %d failed, using default.\n",
hwif->name, hwif->irq);
done:
init_gendisk(hwif);
hwif->present = 1; /* success */
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);
......
......@@ -1315,7 +1315,6 @@ int ide_diag_taskfile (ide_drive_t *drive, ide_task_t *args, unsigned long data_
struct request *rq;
unsigned long flags;
ide_hwgroup_t *hwgroup = HWGROUP(drive);
unsigned int major = HWIF(drive)->major;
struct list_head *queue_head = &drive->queue.queue_head;
DECLARE_COMPLETION(wait);
......@@ -1357,7 +1356,8 @@ int ide_diag_taskfile (ide_drive_t *drive, ide_task_t *args, unsigned long data_
rq->special = args;
rq->errors = 0;
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;
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
rq->errors = 0;
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);
else {
printk("IDE init is ugly:");
dump_stack();
rq->rq_dev = mk_kdev(HWIF(drive)->major, (drive->select.b.unit) << PARTN_BITS);
}
rq->rq_dev = mk_kdev(drive->disk->major, drive->disk->first_minor);
rq->rq_disk = drive->disk;
/*
......@@ -1819,12 +1808,12 @@ void ide_unregister (unsigned int index)
* Remove us from the kernel's knowledge
*/
blk_unregister_region(MKDEV(hwif->major, 0), MAX_DRIVES<<PARTN_BITS);
unregister_blkdev(hwif->major, hwif->name);
for (i = 0; i < MAX_DRIVES; i++) {
struct gendisk *disk = hwif->drives[i].disk;
hwif->drives[i].disk = NULL;
put_disk(disk);
}
unregister_blkdev(hwif->major, hwif->name);
old_hwif = *hwif;
init_hwif_data(index); /* restore hwif data to pristine status */
hwif->hwgroup = old_hwif.hwgroup;
......
......@@ -1583,7 +1583,8 @@ idepmac_wake_device(ide_drive_t *drive, int used_dma)
DRIVER(drive)->media_change(drive);
/* 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
/* 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