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) * Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
*/ */
...@@ -65,23 +65,14 @@ ...@@ -65,23 +65,14 @@
* and make drive properties unconditional outside of this file * 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->cyls = drive->cyl;
drive->id->heads = drive->head; drive->id->heads = drive->head;
drive->id->sectors = drive->sect; drive->id->sectors = drive->sect;
drive->id->cur_cyls = drive->cyl; drive->id->cur_cyls = drive->cyl;
drive->id->cur_heads = drive->head; drive->id->cur_heads = drive->head;
drive->id->cur_sectors = drive->sect; 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) ...@@ -107,7 +98,7 @@ static inline int drive_is_flashcard (ide_drive_t *drive)
{ {
struct hd_driveid *id = drive->id; struct hd_driveid *id = drive->id;
if (drive->removable && id != NULL) { if (drive->removable) {
if (id->config == 0x848a) return 1; /* CompactFlash */ if (id->config == 0x848a) return 1; /* CompactFlash */
if (!strncmp(id->model, "KODAK ATA_FLASH", 15) /* Kodak */ if (!strncmp(id->model, "KODAK ATA_FLASH", 15) /* Kodak */
|| !strncmp(id->model, "Hitachi CV", 10) /* Hitachi */ || !strncmp(id->model, "Hitachi CV", 10) /* Hitachi */
...@@ -138,16 +129,11 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) ...@@ -138,16 +129,11 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
int bswap = 1; int bswap = 1;
struct hd_driveid *id; struct hd_driveid *id;
/* called with interrupts disabled! */ id = drive->id;
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;
}
/* read 512 bytes of id info */ /* read 512 bytes of id info */
hwif->ata_input_data(drive, id, SECTOR_WORDS); hwif->ata_input_data(drive, id, SECTOR_WORDS);
drive->id_read = 1;
local_irq_enable(); local_irq_enable();
ide_fix_driveid(id); ide_fix_driveid(id);
...@@ -290,7 +276,6 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) ...@@ -290,7 +276,6 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
err_misc: err_misc:
kfree(id); kfree(id);
err_kmalloc:
drive->present = 0; drive->present = 0;
return; return;
} }
...@@ -592,6 +577,25 @@ static void enable_nest (ide_drive_t *drive) ...@@ -592,6 +577,25 @@ static void enable_nest (ide_drive_t *drive)
static inline u8 probe_for_drive (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? */ /* skip probing? */
if (!drive->noprobe) if (!drive->noprobe)
{ {
...@@ -600,14 +604,14 @@ static inline u8 probe_for_drive (ide_drive_t *drive) ...@@ -600,14 +604,14 @@ static inline u8 probe_for_drive (ide_drive_t *drive)
/* look for ATAPI device */ /* look for ATAPI device */
(void) do_probe(drive, WIN_PIDENTIFY); (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); enable_nest(drive);
if (!drive->present) if (!drive->present)
/* drive not found */ /* drive not found */
return 0; return 0;
/* identification failed? */ /* identification failed? */
if (drive->id == NULL) { if (!drive->id_read) {
if (drive->media == ide_disk) { if (drive->media == ide_disk) {
printk(KERN_INFO "%s: non-IDE drive, CHS=%d/%d/%d\n", printk(KERN_INFO "%s: non-IDE drive, CHS=%d/%d/%d\n",
drive->name, drive->cyl, drive->name, drive->cyl,
...@@ -616,6 +620,7 @@ static inline u8 probe_for_drive (ide_drive_t *drive) ...@@ -616,6 +620,7 @@ static inline u8 probe_for_drive (ide_drive_t *drive)
printk(KERN_INFO "%s: ATAPI cdrom (?)\n", drive->name); printk(KERN_INFO "%s: ATAPI cdrom (?)\n", drive->name);
} else { } else {
/* nuke it */ /* nuke it */
printk(KERN_WARNING "%s: Unknown device on bus refused identification. Ignoring.\n", drive->name);
drive->present = 0; drive->present = 0;
} }
} }
...@@ -623,9 +628,9 @@ static inline u8 probe_for_drive (ide_drive_t *drive) ...@@ -623,9 +628,9 @@ static inline u8 probe_for_drive (ide_drive_t *drive)
} }
if(!drive->present) if(!drive->present)
return 0; return 0;
if(drive->id == NULL) /* The drive wasn't being helpful. Add generic info only */
if(generic_id(drive) < 0) if(!drive->id_read)
drive->present = 0; generic_id(drive);
return drive->present; return drive->present;
} }
...@@ -945,6 +950,9 @@ int probe_hwif_init (ide_hwif_t *hwif) ...@@ -945,6 +950,9 @@ int probe_hwif_init (ide_hwif_t *hwif)
u16 unit = 0; u16 unit = 0;
for (unit = 0; unit < MAX_DRIVES; ++unit) { for (unit = 0; unit < MAX_DRIVES; ++unit) {
ide_drive_t *drive = &hwif->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) { if (drive->present) {
ata_attach(drive); ata_attach(drive);
} }
...@@ -990,18 +998,23 @@ EXPORT_SYMBOL(save_match); ...@@ -990,18 +998,23 @@ EXPORT_SYMBOL(save_match);
static void ide_init_queue(ide_drive_t *drive) static void ide_init_queue(ide_drive_t *drive)
{ {
request_queue_t *q = &drive->queue; 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); q->queuedata = HWGROUP(drive);
blk_init_queue(q, do_ide_request, &ide_lock); blk_init_queue(q, do_ide_request, &ide_lock);
drive->queue_setup = 1; drive->queue_setup = 1;
blk_queue_segment_boundary(q, 0xffff); blk_queue_segment_boundary(q, 0xffff);
#ifdef CONFIG_BLK_DEV_PDC4030 if (HWIF(drive)->rqsize)
max_sectors = 127; max_sectors = HWIF(drive)->rqsize;
#else
max_sectors = 255;
#endif
blk_queue_max_sectors(q, max_sectors); blk_queue_max_sectors(q, max_sectors);
/* IDE DMA can do PRD_ENTRIES number of segments. */ /* IDE DMA can do PRD_ENTRIES number of segments. */
...@@ -1009,7 +1022,13 @@ static void ide_init_queue(ide_drive_t *drive) ...@@ -1009,7 +1022,13 @@ static void ide_init_queue(ide_drive_t *drive)
/* This is a driver limit and could be eliminated. */ /* This is a driver limit and could be eliminated. */
blk_queue_max_phys_segments(q, PRD_ENTRIES); 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); ide_toggle_bounce(drive, 1);
#ifdef CONFIG_BLK_DEV_IDE_TCQ_DEFAULT #ifdef CONFIG_BLK_DEV_IDE_TCQ_DEFAULT
...@@ -1032,16 +1051,14 @@ static void ide_init_queue(ide_drive_t *drive) ...@@ -1032,16 +1051,14 @@ static void ide_init_queue(ide_drive_t *drive)
*/ */
static int init_irq (ide_hwif_t *hwif) static int init_irq (ide_hwif_t *hwif)
{ {
unsigned long flags;
unsigned int index; unsigned int index;
ide_hwgroup_t *hwgroup, *new_hwgroup; ide_hwgroup_t *hwgroup;
ide_hwif_t *match = NULL; 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; hwif->hwgroup = NULL;
#if MAX_HWIFS > 1 #if MAX_HWIFS > 1
/* /*
...@@ -1073,14 +1090,28 @@ static int init_irq (ide_hwif_t *hwif) ...@@ -1073,14 +1090,28 @@ static int init_irq (ide_hwif_t *hwif)
*/ */
if (match) { if (match) {
hwgroup = match->hwgroup; hwgroup = match->hwgroup;
if(new_hwgroup) hwif->hwgroup = hwgroup;
kfree(new_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 { } else {
hwgroup = new_hwgroup; hwgroup = kmalloc(sizeof(ide_hwgroup_t),GFP_KERNEL);
if (!hwgroup) { if (!hwgroup)
spin_unlock_irqrestore(&ide_lock, flags); goto out_up;
return 1;
} hwif->hwgroup = hwgroup;
memset(hwgroup, 0, sizeof(ide_hwgroup_t)); memset(hwgroup, 0, sizeof(ide_hwgroup_t));
hwgroup->hwif = hwif->next = hwif; hwgroup->hwif = hwif->next = hwif;
hwgroup->rq = NULL; hwgroup->rq = NULL;
...@@ -1112,44 +1143,35 @@ static int init_irq (ide_hwif_t *hwif) ...@@ -1112,44 +1143,35 @@ static int init_irq (ide_hwif_t *hwif)
/* clear nIEN */ /* clear nIEN */
hwif->OUTB(0x08, hwif->io_ports[IDE_CONTROL_OFFSET]); hwif->OUTB(0x08, hwif->io_ports[IDE_CONTROL_OFFSET]);
if (request_irq(hwif->irq,&ide_intr,sa,hwif->name,hwgroup)) { if (request_irq(hwif->irq,&ide_intr,sa,hwif->name,hwgroup))
if (!match) goto out_unlink;
kfree(hwgroup);
spin_unlock_irqrestore(&ide_lock, flags);
return 1;
}
} }
/* /*
* 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) { for (index = 0; index < MAX_DRIVES; ++index) {
ide_drive_t *drive = &hwif->drives[index]; ide_drive_t *drive = &hwif->drives[index];
if (!drive->present) if (!drive->present)
continue; continue;
if (!hwgroup->drive) ide_init_queue(drive);
spin_lock_irq(&ide_lock);
if (!hwgroup->drive) {
/* first drive for hwgroup. */
drive->next = drive;
hwgroup->drive = drive; hwgroup->drive = drive;
hwgroup->hwif = HWIF(hwgroup->drive);
} else {
drive->next = hwgroup->drive->next; drive->next = hwgroup->drive->next;
hwgroup->drive->next = drive; hwgroup->drive->next = drive;
spin_unlock_irqrestore(&ide_lock, flags);
ide_init_queue(drive);
spin_lock_irqsave(&ide_lock, flags);
} }
spin_unlock_irq(&ide_lock);
if (!hwgroup->hwif) { ide_init_drive(drive);
hwgroup->hwif = HWIF(hwgroup->drive);
#ifdef DEBUG
printk("%s : Adding missed hwif to hwgroup!!\n", hwif->name);
#endif
} }
/* all CPUs; safe now that hwif->hwgroup is set up */
spin_unlock_irqrestore(&ide_lock, flags);
#if !defined(__mc68000__) && !defined(CONFIG_APUS) && !defined(__sparc__) #if !defined(__mc68000__) && !defined(CONFIG_APUS) && !defined(__sparc__)
printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name, printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name,
hwif->io_ports[IDE_DATA_OFFSET], hwif->io_ports[IDE_DATA_OFFSET],
...@@ -1168,6 +1190,30 @@ static int init_irq (ide_hwif_t *hwif) ...@@ -1168,6 +1190,30 @@ static int init_irq (ide_hwif_t *hwif)
printk(" (%sed with %s)", printk(" (%sed with %s)",
hwif->sharing_irq ? "shar" : "serializ", match->name); hwif->sharing_irq ? "shar" : "serializ", match->name);
printk("\n"); 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; return 0;
} }
...@@ -1340,6 +1386,7 @@ EXPORT_SYMBOL(hwif_init); ...@@ -1340,6 +1386,7 @@ EXPORT_SYMBOL(hwif_init);
void export_ide_init_queue (ide_drive_t *drive) void export_ide_init_queue (ide_drive_t *drive)
{ {
ide_init_queue(drive); ide_init_queue(drive);
ide_init_drive(drive);
} }
EXPORT_SYMBOL(export_ide_init_queue); EXPORT_SYMBOL(export_ide_init_queue);
...@@ -1384,6 +1431,7 @@ int ideprobe_init (void) ...@@ -1384,6 +1431,7 @@ int ideprobe_init (void)
if (!hwif->present) if (!hwif->present)
continue; continue;
for (unit = 0; unit < MAX_DRIVES; ++unit) for (unit = 0; unit < MAX_DRIVES; ++unit)
if (hwif->drives[unit].present)
ata_attach(&hwif->drives[unit]); ata_attach(&hwif->drives[unit]);
} }
} }
......
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