Commit 20e51ffc authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

[PATCH] ide-probe update

Make drive->id not NULL an invariant
Clean up a few things from that
hwif specific queue length
initialisation/IRQ cleanups

Note: this changes the default blocks limit per I/O to 256. I've still seen
no credible evidence that its a problem and "other OS's" do it.
parent c5ced320
/*
* linux/drivers/ide/ide-probe.c Version 1.10 Feb 11, 2003
* linux/drivers/ide/ide-probe.c Version 1.11 Mar 05, 2003
*
* Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
*/
......@@ -65,23 +65,14 @@
* and make drive properties unconditional outside of this file
*/
static int generic_id(ide_drive_t *drive)
static void generic_id(ide_drive_t *drive)
{
drive->id = kmalloc(SECTOR_WORDS *4, GFP_KERNEL);
if(drive->id == NULL)
{
printk(KERN_ERR "ide: out of memory for id data.\n");
return -ENOMEM;
}
memset(drive->id, 0, SECTOR_WORDS * 4);
drive->id->cyls = drive->cyl;
drive->id->heads = drive->head;
drive->id->sectors = drive->sect;
drive->id->cur_cyls = drive->cyl;
drive->id->cur_heads = drive->head;
drive->id->cur_sectors = drive->sect;
strcpy(drive->id->model, "UNKNOWN");
return 0;
}
/**
......@@ -107,7 +98,7 @@ static inline int drive_is_flashcard (ide_drive_t *drive)
{
struct hd_driveid *id = drive->id;
if (drive->removable && id != NULL) {
if (drive->removable) {
if (id->config == 0x848a) return 1; /* CompactFlash */
if (!strncmp(id->model, "KODAK ATA_FLASH", 15) /* Kodak */
|| !strncmp(id->model, "Hitachi CV", 10) /* Hitachi */
......@@ -138,16 +129,11 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
int bswap = 1;
struct hd_driveid *id;
/* called with interrupts disabled! */
id = drive->id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC);
if (!id) {
printk(KERN_WARNING "(ide-probe::do_identify) "
"Out of memory.\n");
goto err_kmalloc;
}
id = drive->id;
/* read 512 bytes of id info */
hwif->ata_input_data(drive, id, SECTOR_WORDS);
drive->id_read = 1;
local_irq_enable();
ide_fix_driveid(id);
......@@ -290,7 +276,6 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
err_misc:
kfree(id);
err_kmalloc:
drive->present = 0;
return;
}
......@@ -592,6 +577,25 @@ static void enable_nest (ide_drive_t *drive)
static inline u8 probe_for_drive (ide_drive_t *drive)
{
/*
* 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 = kmalloc(SECTOR_WORDS *4, GFP_KERNEL);
drive->id_read = 0;
if(drive->id == NULL)
{
printk(KERN_ERR "ide: out of memory for id data.\n");
return 0;
}
memset(drive->id, 0, SECTOR_WORDS * 4);
strcpy(drive->id->model, "UNKNOWN");
/* skip probing? */
if (!drive->noprobe)
{
......@@ -600,14 +604,14 @@ static inline u8 probe_for_drive (ide_drive_t *drive)
/* look for ATAPI device */
(void) do_probe(drive, WIN_PIDENTIFY);
}
if (drive->id && strstr(drive->id->model, "E X A B Y T E N E S T"))
if (strstr(drive->id->model, "E X A B Y T E N E S T"))
enable_nest(drive);
if (!drive->present)
/* drive not found */
return 0;
/* identification failed? */
if (drive->id == NULL) {
if (!drive->id_read) {
if (drive->media == ide_disk) {
printk(KERN_INFO "%s: non-IDE drive, CHS=%d/%d/%d\n",
drive->name, drive->cyl,
......@@ -616,6 +620,7 @@ static inline u8 probe_for_drive (ide_drive_t *drive)
printk(KERN_INFO "%s: ATAPI cdrom (?)\n", drive->name);
} else {
/* nuke it */
printk(KERN_WARNING "%s: Unknown device on bus refused identification. Ignoring.\n", drive->name);
drive->present = 0;
}
}
......@@ -623,9 +628,9 @@ static inline u8 probe_for_drive (ide_drive_t *drive)
}
if(!drive->present)
return 0;
if(drive->id == NULL)
if(generic_id(drive) < 0)
drive->present = 0;
/* The drive wasn't being helpful. Add generic info only */
if(!drive->id_read)
generic_id(drive);
return drive->present;
}
......@@ -945,6 +950,9 @@ int probe_hwif_init (ide_hwif_t *hwif)
u16 unit = 0;
for (unit = 0; unit < MAX_DRIVES; ++unit) {
ide_drive_t *drive = &hwif->drives[unit];
/* For now don't attach absent drives, we may
want them on default or a new "empty" class
for hotplug reprobing ? */
if (drive->present) {
ata_attach(drive);
}
......@@ -990,18 +998,23 @@ EXPORT_SYMBOL(save_match);
static void ide_init_queue(ide_drive_t *drive)
{
request_queue_t *q = &drive->queue;
int max_sectors;
int max_sectors = 256;
/*
* Our default set up assumes the normal IDE case,
* that is 64K segmenting, standard PRD setup
* and LBA28. Some drivers then impose their own
* limits and LBA48 we could raise it but as yet
* do not.
*/
q->queuedata = HWGROUP(drive);
blk_init_queue(q, do_ide_request, &ide_lock);
drive->queue_setup = 1;
blk_queue_segment_boundary(q, 0xffff);
#ifdef CONFIG_BLK_DEV_PDC4030
max_sectors = 127;
#else
max_sectors = 255;
#endif
if (HWIF(drive)->rqsize)
max_sectors = HWIF(drive)->rqsize;
blk_queue_max_sectors(q, max_sectors);
/* IDE DMA can do PRD_ENTRIES number of segments. */
......@@ -1009,7 +1022,13 @@ static void ide_init_queue(ide_drive_t *drive)
/* This is a driver limit and could be eliminated. */
blk_queue_max_phys_segments(q, PRD_ENTRIES);
}
/*
* Setup the drive for request handling.
*/
static void ide_init_drive(ide_drive_t *drive)
{
ide_toggle_bounce(drive, 1);
#ifdef CONFIG_BLK_DEV_IDE_TCQ_DEFAULT
......@@ -1032,16 +1051,14 @@ static void ide_init_queue(ide_drive_t *drive)
*/
static int init_irq (ide_hwif_t *hwif)
{
unsigned long flags;
unsigned int index;
ide_hwgroup_t *hwgroup, *new_hwgroup;
ide_hwgroup_t *hwgroup;
ide_hwif_t *match = NULL;
/* Allocate the buffer and potentially sleep first */
new_hwgroup = kmalloc(sizeof(ide_hwgroup_t),GFP_KERNEL);
spin_lock_irqsave(&ide_lock, flags);
BUG_ON(in_interrupt());
BUG_ON(irqs_disabled());
down(&ide_cfg_sem);
hwif->hwgroup = NULL;
#if MAX_HWIFS > 1
/*
......@@ -1073,14 +1090,28 @@ static int init_irq (ide_hwif_t *hwif)
*/
if (match) {
hwgroup = match->hwgroup;
if(new_hwgroup)
kfree(new_hwgroup);
hwif->hwgroup = hwgroup;
/*
* Link us into the hwgroup.
* This must be done early, do ensure that unexpected_intr
* can find the hwif and prevent irq storms.
* No drives are attached to the new hwif, choose_drive
* can't do anything stupid (yet).
* Add ourself as the 2nd entry to the hwgroup->hwif
* linked list, the first entry is the hwif that owns
* hwgroup->handler - do not change that.
*/
spin_lock_irq(&ide_lock);
hwif->next = hwgroup->hwif->next;
hwgroup->hwif->next = hwif;
spin_unlock_irq(&ide_lock);
} else {
hwgroup = new_hwgroup;
if (!hwgroup) {
spin_unlock_irqrestore(&ide_lock, flags);
return 1;
}
hwgroup = kmalloc(sizeof(ide_hwgroup_t),GFP_KERNEL);
if (!hwgroup)
goto out_up;
hwif->hwgroup = hwgroup;
memset(hwgroup, 0, sizeof(ide_hwgroup_t));
hwgroup->hwif = hwif->next = hwif;
hwgroup->rq = NULL;
......@@ -1112,44 +1143,35 @@ static int init_irq (ide_hwif_t *hwif)
/* clear nIEN */
hwif->OUTB(0x08, hwif->io_ports[IDE_CONTROL_OFFSET]);
if (request_irq(hwif->irq,&ide_intr,sa,hwif->name,hwgroup)) {
if (!match)
kfree(hwgroup);
spin_unlock_irqrestore(&ide_lock, flags);
return 1;
}
if (request_irq(hwif->irq,&ide_intr,sa,hwif->name,hwgroup))
goto out_unlink;
}
/*
* Everything is okay, so link us into the hwgroup
* Link any new drives into the hwgroup, allocate
* the block device queue and initialize the drive.
* Note that ide_init_drive sends commands to the new
* drive.
*/
hwif->hwgroup = hwgroup;
hwif->next = hwgroup->hwif->next;
hwgroup->hwif->next = hwif;
for (index = 0; index < MAX_DRIVES; ++index) {
ide_drive_t *drive = &hwif->drives[index];
if (!drive->present)
continue;
if (!hwgroup->drive)
hwgroup->drive = drive;
drive->next = hwgroup->drive->next;
hwgroup->drive->next = drive;
spin_unlock_irqrestore(&ide_lock, flags);
ide_init_queue(drive);
spin_lock_irqsave(&ide_lock, flags);
}
if (!hwgroup->hwif) {
hwgroup->hwif = HWIF(hwgroup->drive);
#ifdef DEBUG
printk("%s : Adding missed hwif to hwgroup!!\n", hwif->name);
#endif
spin_lock_irq(&ide_lock);
if (!hwgroup->drive) {
/* first drive for hwgroup. */
drive->next = drive;
hwgroup->drive = drive;
hwgroup->hwif = HWIF(hwgroup->drive);
} else {
drive->next = hwgroup->drive->next;
hwgroup->drive->next = drive;
}
spin_unlock_irq(&ide_lock);
ide_init_drive(drive);
}
/* all CPUs; safe now that hwif->hwgroup is set up */
spin_unlock_irqrestore(&ide_lock, flags);
#if !defined(__mc68000__) && !defined(CONFIG_APUS) && !defined(__sparc__)
printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name,
hwif->io_ports[IDE_DATA_OFFSET],
......@@ -1168,6 +1190,30 @@ static int init_irq (ide_hwif_t *hwif)
printk(" (%sed with %s)",
hwif->sharing_irq ? "shar" : "serializ", match->name);
printk("\n");
up(&ide_cfg_sem);
return 0;
out_unlink:
spin_lock_irq(&ide_lock);
if (hwif->next == hwif) {
BUG_ON(match);
BUG_ON(hwgroup->hwif != hwif);
kfree(hwgroup);
} else {
ide_hwif_t *g;
g = hwgroup->hwif;
while (g->next != hwif)
g = g->next;
g->next = hwif->next;
if (hwgroup->hwif == hwif) {
/* Impossible. */
printk(KERN_ERR "Duh. Uninitialized hwif listed as active hwif.\n");
hwgroup->hwif = g;
}
BUG_ON(hwgroup->hwif == hwif);
}
spin_unlock_irq(&ide_lock);
out_up:
up(&ide_cfg_sem);
return 0;
}
......@@ -1340,6 +1386,7 @@ EXPORT_SYMBOL(hwif_init);
void export_ide_init_queue (ide_drive_t *drive)
{
ide_init_queue(drive);
ide_init_drive(drive);
}
EXPORT_SYMBOL(export_ide_init_queue);
......@@ -1384,7 +1431,8 @@ int ideprobe_init (void)
if (!hwif->present)
continue;
for (unit = 0; unit < MAX_DRIVES; ++unit)
ata_attach(&hwif->drives[unit]);
if (hwif->drives[unit].present)
ata_attach(&hwif->drives[unit]);
}
}
if (!ide_probe)
......
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