]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] saner initialization order in IDE (gendisks allocated slightly earlier)
authorAlexander Viro <viro@math.psu.edu>
Mon, 28 Oct 2002 10:50:50 +0000 (02:50 -0800)
committerJames Bottomley <jejb@mulgrave.(none)>
Mon, 28 Oct 2002 10:50:50 +0000 (02:50 -0800)
* 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

drivers/ide/ide-probe.c
drivers/ide/ide-taskfile.c
drivers/ide/ide.c
drivers/ide/ppc/pmac.c

index 356999a5e878d9e6e5a0563ebeaf96b0026a1096..aca1bde71642d99e6622e798be47e0551efcb9f8 100644 (file)
@@ -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);
index 550c3ae73e5a18402876529776055606567ad67a..4d9811321a9d09089bb57c33e6e8c5e6977f2544 100644 (file)
@@ -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);
index 544b1cd654a3af8ca0f6c7e3e48cdecc5d92fe0a..85313595e62a65b2d19311afb920741413bc8fab 100644 (file)
@@ -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;
index db8b9655d6ec6afc2c0b4302aa1e6bb36029a8d6..3f24d5da69a3a01f56840a991c6ff511c2b0112a 100644 (file)
@@ -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. */