PATCH: update ide core

Alan Cox (alan@lxorguk.ukuu.org.uk)
Fri, 21 Mar 2003 20:45:21 GMT


- New style ide-default driver
- Don't attach non existant drives
- DRIVER()==NULL checks can go
- Ioctl checks that were missing are now in
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux-2.5.65/drivers/ide/ide.c linux-2.5.65-ac2/drivers/ide/ide.c
--- linux-2.5.65/drivers/ide/ide.c 2003-03-03 19:20:09.000000000 +0000
+++ linux-2.5.65-ac2/drivers/ide/ide.c 2003-03-20 18:23:19.000000000 +0000
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/ide.c Version 7.00alpha1 August 19 2002
+ * linux/drivers/ide/ide.c Version 7.00beta2 Mar 05 2003
*
* Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
*/
@@ -177,6 +177,7 @@
static int system_bus_speed; /* holds what we think is VESA/PCI bus speed */
static int initializing; /* set while initializing built-in drivers */

+DECLARE_MUTEX(ide_cfg_sem);
spinlock_t ide_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;

static int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */
@@ -214,6 +215,8 @@
EXPORT_SYMBOL(idetape);
EXPORT_SYMBOL(idescsi);

+extern ide_driver_t idedefault_driver;
+static void setup_driver_defaults (ide_drive_t *drive);

/*
* Do not even *think* about calling this!
@@ -271,6 +274,8 @@
drive->max_failures = IDE_DEFAULT_MAX_FAILURES;
drive->using_dma = 0;
drive->is_flash = 0;
+ drive->driver = &idedefault_driver;
+ setup_driver_defaults(drive);
drive->vdma = 0;
INIT_LIST_HEAD(&drive->list);
}
@@ -349,9 +354,7 @@
{
if (!drive->present)
return 0;
- if (drive->driver != NULL)
- return DRIVER(drive)->capacity(drive);
- return 0;
+ return DRIVER(drive)->capacity(drive);
}

EXPORT_SYMBOL(current_capacity);
@@ -580,17 +583,19 @@

void ide_unregister (unsigned int index)
{
- ide_drive_t *drive, *d;
+ ide_drive_t *drive;
ide_hwif_t *hwif, *g;
ide_hwgroup_t *hwgroup;
int irq_count = 0, unit, i;
- unsigned long flags;
ide_hwif_t old_hwif;

if (index >= MAX_HWIFS)
BUG();

- spin_lock_irqsave(&ide_lock, flags);
+ BUG_ON(in_interrupt());
+ BUG_ON(irqs_disabled());
+ down(&ide_cfg_sem);
+ spin_lock_irq(&ide_lock);
hwif = &ide_hwifs[index];
if (!hwif->present)
goto abort;
@@ -600,25 +605,23 @@
continue;
if (drive->usage)
goto abort;
- if (drive->driver != NULL && DRIVER(drive)->shutdown(drive))
+ if (DRIVER(drive)->shutdown(drive))
goto abort;
}
hwif->present = 0;

- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irq(&ide_lock);

for (unit = 0; unit < MAX_DRIVES; ++unit) {
drive = &hwif->drives[unit];
if (!drive->present)
continue;
- if (drive->driver != NULL)
- DRIVER(drive)->cleanup(drive);
+ DRIVER(drive)->cleanup(drive);
}

#ifdef CONFIG_PROC_FS
destroy_proc_ide_drives(hwif);
#endif
- spin_lock_irqsave(&ide_lock, flags);
hwgroup = hwif->hwgroup;

/*
@@ -633,6 +636,7 @@
if (irq_count == 1)
free_irq(hwif->irq, hwgroup);

+ spin_lock_irq(&ide_lock);
/*
* Note that we only release the standard ports,
* and do not even try to handle any extra ports
@@ -644,7 +648,6 @@
* Remove us from the hwgroup, and free
* the hwgroup if we were the only member
*/
- d = hwgroup->drive;
for (i = 0; i < MAX_DRIVES; ++i) {
drive = &hwif->drives[i];
if (drive->de) {
@@ -653,11 +656,23 @@
}
if (!drive->present)
continue;
- while (hwgroup->drive->next != drive)
- hwgroup->drive = hwgroup->drive->next;
- hwgroup->drive->next = drive->next;
- if (hwgroup->drive == drive)
+ if (drive == drive->next) {
+ /* special case: last drive from hwgroup. */
+ BUG_ON(hwgroup->drive != drive);
hwgroup->drive = NULL;
+ } else {
+ ide_drive_t *walk;
+
+ walk = hwgroup->drive;
+ while (walk->next != drive)
+ walk = walk->next;
+ walk->next = drive->next;
+ if (hwgroup->drive == drive) {
+ hwgroup->drive = drive->next;
+ hwgroup->hwif = HWIF(hwgroup->drive);
+ }
+ }
+ BUG_ON(hwgroup->drive == drive);
if (drive->id != NULL) {
kfree(drive->id);
drive->id = NULL;
@@ -665,15 +680,28 @@
drive->present = 0;
blk_cleanup_queue(&drive->queue);
}
- if (d->present)
- hwgroup->drive = d;
- while (hwgroup->hwif->next != hwif)
- hwgroup->hwif = hwgroup->hwif->next;
- hwgroup->hwif->next = hwif->next;
- if (hwgroup->hwif == hwif)
+ if (hwif->next == hwif) {
kfree(hwgroup);
- else
- hwgroup->hwif = HWIF(hwgroup->drive);
+ BUG_ON(hwgroup->hwif != hwif);
+ } else {
+ /* There is another interface in hwgroup.
+ * Unlink us, and set hwgroup->drive and ->hwif to
+ * something sane.
+ */
+ g = hwgroup->hwif;
+ while (g->next != hwif)
+ g = g->next;
+ g->next = hwif->next;
+ if (hwgroup->hwif == hwif) {
+ /* Chose a random hwif for hwgroup->hwif.
+ * It's guaranteed that there are no drives
+ * left in the hwgroup.
+ */
+ BUG_ON(hwgroup->drive != NULL);
+ hwgroup->hwif = g;
+ }
+ BUG_ON(hwgroup->hwif == hwif);
+ }

#if !defined(CONFIG_DMA_NONPCI)
if (hwif->dma_base) {
@@ -813,7 +841,8 @@

hwif->hwif_data = old_hwif.hwif_data;
abort:
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irq(&ide_lock);
+ up(&ide_cfg_sem);
}

EXPORT_SYMBOL(ide_unregister);
@@ -998,7 +1027,7 @@
setting->set = set;

setting->next = *p;
- if (drive->driver)
+ if (drive->driver != &idedefault_driver)
setting->auto_remove = 1;
*p = setting;
up(&ide_setting_sem);
@@ -1304,15 +1334,9 @@
return 0;
}

- if (drive->driver != NULL) {
-#if 0
- ide_unregister_subdriver(drive);
-#else
- if (DRIVER(drive)->cleanup(drive)) {
- drive->scsi = 0;
- return 0;
- }
-#endif
+ if (DRIVER(drive)->cleanup(drive)) {
+ drive->scsi = 0;
+ return 0;
}

drive->scsi = (u8) arg;
@@ -1353,7 +1377,7 @@
mdelay(50);
#else
__set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ/20);
+ schedule_timeout(1+HZ/20);
#endif /* CONFIG_BLK_DEV_IDECS */
}

@@ -1375,7 +1399,7 @@
{
if (!drive->present || drive->usage || drive->dead)
goto abort;
- if (drive->driver != NULL && DRIVER(drive)->cleanup(drive))
+ if (DRIVER(drive)->cleanup(drive))
goto abort;
strncpy(drive->driver_req, driver, 9);
if (ata_attach(drive)) {
@@ -1387,7 +1411,7 @@
} else {
drive->driver_req[0] = 0;
}
- if (DRIVER(drive) && !strcmp(DRIVER(drive)->name, driver))
+ if (DRIVER(drive)!= &idedefault_driver && !strcmp(DRIVER(drive)->name, driver))
return 0;
abort:
return 1;
@@ -1412,10 +1436,12 @@
spin_lock(&drivers_lock);
module_put(driver->owner);
}
+ drive->gendev.driver = &idedefault_driver.gen_driver;
spin_unlock(&drivers_lock);
+ if(idedefault_driver.attach(drive) != 0)
+ panic("ide: default attach failed");
spin_lock(&drives_lock);
list_add_tail(&drive->list, &ata_unused);
- drive->gendev.driver = NULL;
spin_unlock(&drives_lock);
return 1;
}
@@ -1476,7 +1502,7 @@
case HDIO_GET_IDENTITY:
if (bdev != bdev->bd_contains)
return -EINVAL;
- if (drive->id == NULL)
+ if (drive->id_read == 0)
return -ENOMSG;
if (copy_to_user((char *)arg, (char *)drive->id, (cmd == HDIO_GET_IDENTITY) ? sizeof(*drive->id) : 142))
return -EFAULT;
@@ -1521,7 +1547,7 @@
case HDIO_SCAN_HWIF:
{
int args[3];
- if (!capable(CAP_SYS_ADMIN)) return -EACCES;
+ if (!capable(CAP_SYS_RAWIO)) return -EACCES;
if (copy_from_user(args, (void *)arg, 3 * sizeof(int)))
return -EFAULT;
if (ide_register(args[0], args[1], args[2]) == -1)
@@ -1529,14 +1555,12 @@
return 0;
}
case HDIO_UNREGISTER_HWIF:
- if (!capable(CAP_SYS_ADMIN)) return -EACCES;
+ if (!capable(CAP_SYS_RAWIO)) return -EACCES;
/* (arg > MAX_HWIFS) checked in function */
ide_unregister(arg);
return 0;
case HDIO_SET_NICE:
if (!capable(CAP_SYS_ADMIN)) return -EACCES;
- if (drive->driver == NULL)
- return -EPERM;
if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP) | (1 << IDE_NICE_1))))
return -EPERM;
drive->dsc_overlap = (arg >> IDE_NICE_DSC_OVERLAP) & 1;
@@ -1550,18 +1574,26 @@
{
unsigned long flags;
if (!capable(CAP_SYS_ADMIN)) return -EACCES;
-#if 1
+
+ /*
+ * Abort the current command on the
+ * group if there is one, taking
+ * care not to allow anything else
+ * to be queued and to die on the
+ * spot if we miss one somehow
+ */
+
spin_lock_irqsave(&ide_lock, flags);
- if ( HWGROUP(drive)->handler != NULL) {
- printk(KERN_ERR "%s: ide_set_handler: handler not null; %p\n", drive->name, HWGROUP(drive)->handler);
- (void) HWGROUP(drive)->handler(drive);
-// HWGROUP(drive)->handler = NULL;
- HWGROUP(drive)->expiry = NULL;
- del_timer(&HWGROUP(drive)->timer);
- }
+
+ DRIVER(drive)->abort(drive, "drive reset");
+ if(HWGROUP(drive)->handler)
+ BUG();
+
+ /* Ensure nothing gets queued after we
+ drop the lock. Reset will clear the busy */
+
+ HWGROUP(drive)->busy = 1;
spin_unlock_irqrestore(&ide_lock, flags);
-
-#endif
(void) ide_do_reset(drive);
if (drive->suspend_reset) {
/*
@@ -1593,9 +1625,8 @@
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
if (HWIF(drive)->busproc)
- HWIF(drive)->busproc(drive, (int)arg);
- return 0;
-
+ return HWIF(drive)->busproc(drive, (int)arg);
+ return -EOPNOTSUPP;
default:
return -EINVAL;
}
@@ -2193,7 +2224,7 @@

static int default_shutdown(ide_drive_t *drive)
{
- if (drive->usage || drive->driver == NULL || DRIVER(drive)->busy) {
+ if (drive->usage || DRIVER(drive)->busy) {
return 1;
}
drive->dead = 1;
@@ -2261,6 +2292,11 @@
return 0;
}

+static ide_startstop_t default_abort (ide_drive_t *drive, const char *msg)
+{
+ return ide_abort(drive, msg);
+}
+
static void setup_driver_defaults (ide_drive_t *drive)
{
ide_driver_t *d = drive->driver;
@@ -2272,6 +2308,7 @@
if (d->end_request == NULL) d->end_request = default_end_request;
if (d->sense == NULL) d->sense = default_sense;
if (d->error == NULL) d->error = default_error;
+ if (d->abort == NULL) d->abort = default_abort;
if (d->pre_reset == NULL) d->pre_reset = default_pre_reset;
if (d->capacity == NULL) d->capacity = default_capacity;
if (d->special == NULL) d->special = default_special;
@@ -2282,9 +2319,11 @@
{
unsigned long flags;

+ BUG_ON(drive->driver == NULL);
+
spin_lock_irqsave(&ide_lock, flags);
if (version != IDE_SUBDRIVER_VERSION || !drive->present ||
- drive->driver != NULL || drive->usage || drive->dead) {
+ drive->driver != &idedefault_driver || drive->usage || drive->dead) {
spin_unlock_irqrestore(&ide_lock, flags);
return 1;
}
@@ -2294,6 +2333,7 @@
spin_lock(&drives_lock);
list_add(&drive->list, &driver->drives);
spin_unlock(&drives_lock);
+// printk(KERN_INFO "%s: attached %s driver.\n", drive->name, driver->name);
if ((drive->autotune == IDE_TUNE_DEFAULT) ||
(drive->autotune == IDE_TUNE_AUTO)) {
/* DMA timings and setup moved to ide-probe.c */
@@ -2318,7 +2358,7 @@
unsigned long flags;

spin_lock_irqsave(&ide_lock, flags);
- if (drive->usage || drive->driver == NULL || DRIVER(drive)->busy) {
+ if (drive->usage || drive->driver == &idedefault_driver || DRIVER(drive)->busy) {
spin_unlock_irqrestore(&ide_lock, flags);
return 1;
}
@@ -2330,10 +2370,12 @@
ide_remove_proc_entries(drive->proc, generic_subdriver_entries);
#endif
auto_remove_settings(drive);
- drive->driver = NULL;
+ drive->driver = &idedefault_driver;
+ setup_driver_defaults(drive);
spin_unlock_irqrestore(&ide_lock, flags);
spin_lock(&drives_lock);
list_del_init(&drive->list);
+ list_add(&drive->list, &drive->driver->drives);
spin_unlock(&drives_lock);
return 0;
}
@@ -2343,10 +2385,7 @@
static int ide_drive_remove(struct device * dev)
{
ide_drive_t * drive = container_of(dev,ide_drive_t,gendev);
- ide_driver_t * driver = drive->driver;
-
- if (driver && driver->cleanup)
- driver->cleanup(drive);
+ DRIVER(drive)->cleanup(drive);
return 0;
}

@@ -2366,7 +2405,8 @@
while (!list_empty(&list)) {
ide_drive_t *drive = list_entry(list.next, ide_drive_t, list);
list_del_init(&drive->list);
- ata_attach(drive);
+ if (drive->present)
+ ata_attach(drive);
}
driver->gen_driver.name = (char *) driver->name;
driver->gen_driver.bus = &ide_bus_type;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/