Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5f4417a1 authored by Hugh Dickins's avatar Hugh Dickins Committed by Bartlomiej Zolnierkiewicz
Browse files

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: default avatarHugh 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: default avatarBartlomiej Zolnierkiewicz <bzolnier@gmail.com>
parent a20b2a44
Loading
Loading
Loading
Loading
+21 −26
Original line number Diff line number Diff line
@@ -465,23 +465,8 @@ static u8 probe_for_drive(ide_drive_t *drive)
	int rc;
	u8 cmd;

	/*
	 *	In order to keep things simple we have an id
	 *	block for all drives at all times. If the device
	 *	is pre ATA or refuses ATA/ATAPI identify we
	 *	will add faked data to this.
	 *
	 *	Also note that 0 everywhere means "can't do X"
	 */
 
	drive->dev_flags &= ~IDE_DFLAG_ID_READ;

	drive->id = kzalloc(SECTOR_SIZE, GFP_KERNEL);
	if (drive->id == NULL) {
		printk(KERN_ERR "ide: out of memory for id data.\n");
		return 0;
	}

	m = (char *)&drive->id[ATA_ID_PROD];
	strcpy(m, "UNKNOWN");

@@ -497,7 +482,7 @@ static u8 probe_for_drive(ide_drive_t *drive)
		}

		if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
			goto out_free;
			return 0;

		/* identification failed? */
		if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) {
@@ -521,7 +506,7 @@ static u8 probe_for_drive(ide_drive_t *drive)
	}

	if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
		goto out_free;
		return 0;

	/* The drive wasn't being helpful. Add generic info only */
	if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) {
@@ -535,9 +520,6 @@ static u8 probe_for_drive(ide_drive_t *drive)
	}

	return 1;
out_free:
	kfree(drive->id);
	return 0;
}

static void hwif_release_dev(struct device *dev)
@@ -825,8 +807,6 @@ static int ide_port_setup_devices(ide_hwif_t *hwif)
		if (ide_init_queue(drive)) {
			printk(KERN_ERR "ide: failed to init %s\n",
					drive->name);
			kfree(drive->id);
			drive->id = NULL;
			drive->dev_flags &= ~IDE_DFLAG_PRESENT;
			continue;
		}
@@ -955,9 +935,6 @@ static void drive_release_dev (struct device *dev)
	blk_cleanup_queue(drive->queue);
	drive->queue = NULL;

	kfree(drive->id);
	drive->id = NULL;

	drive->dev_flags &= ~IDE_DFLAG_PRESENT;

	complete(&drive->gendev_rel_comp);
@@ -1140,8 +1117,11 @@ static void ide_port_init_devices_data(ide_hwif_t *hwif)

	ide_port_for_each_dev(i, drive, hwif) {
		u8 j = (hwif->index * MAX_DRIVES) + i;
		u16 *saved_id = drive->id;

		memset(drive, 0, sizeof(*drive));
		memset(saved_id, 0, SECTOR_SIZE);
		drive->id = saved_id;

		drive->media			= ide_disk;
		drive->select			= (i << 4) | ATA_DEVICE_OBS;
@@ -1248,9 +1228,11 @@ static void ide_port_free_devices(ide_hwif_t *hwif)
	ide_drive_t *drive;
	int i;

	ide_port_for_each_dev(i, drive, hwif)
	ide_port_for_each_dev(i, drive, hwif) {
		kfree(drive->id);
		kfree(drive);
	}
}

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)
		if (drive == NULL)
			goto out_nomem;

		/*
		 * In order to keep things simple we have an id
		 * block for all drives at all times. If the device
		 * is pre ATA or refuses ATA/ATAPI identify we
		 * will add faked data to this.
		 *
		 * Also note that 0 everywhere means "can't do X"
		 */
		drive->id = kzalloc_node(SECTOR_SIZE, GFP_KERNEL, node);
		if (drive->id == NULL)
			goto out_nomem;

		hwif->devices[i] = drive;
	}
	return 0;
@@ -1304,6 +1298,7 @@ struct ide_host *ide_host_alloc(const struct ide_port_info *d,
		if (idx < 0) {
			printk(KERN_ERR "%s: no free slot for interface\n",
					d ? d->name : "ide");
			ide_port_free_devices(hwif);
			kfree(hwif);
			continue;
		}