Commit 4015c949 authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

[PATCH] update ide core

- New style ide-default driver
- Don't attach non existant drives
- DRIVER()==NULL checks can go
- Ioctl checks that were missing are now in
parent 54f8af28
/*
* 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 idebus_parameter; /* holds the "idebus=" parameter */
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(idefloppy);
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 @@ static void init_hwif_data (unsigned int index)
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 @@ unsigned long current_capacity (ide_drive_t *drive)
{
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 @@ extern void init_hwif_data(unsigned int index);
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 @@ void ide_unregister (unsigned int index)
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 @@ void ide_unregister (unsigned int index)
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 @@ void ide_unregister (unsigned int index)
* 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 @@ void ide_unregister (unsigned int index)
}
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 @@ void ide_unregister (unsigned int index)
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 @@ void ide_unregister (unsigned int index)
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 @@ int ide_add_setting (ide_drive_t *drive, const char *name, int rw, int read_ioct
setting->set = set;
setting->next = *p;
if (drive->driver)
if (drive->driver != &idedefault_driver)
setting->auto_remove = 1;
*p = setting;
up(&ide_setting_sem);
......@@ -1305,15 +1334,9 @@ int ide_atapi_to_scsi (ide_drive_t *drive, int arg)
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;
......@@ -1354,7 +1377,7 @@ void ide_delay_50ms (void)
mdelay(50);
#else
__set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ/20);
schedule_timeout(1+HZ/20);
#endif /* CONFIG_BLK_DEV_IDECS */
}
......@@ -1376,7 +1399,7 @@ int ide_replace_subdriver (ide_drive_t *drive, const char *driver)
{
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)) {
......@@ -1388,7 +1411,7 @@ int ide_replace_subdriver (ide_drive_t *drive, const char *driver)
} 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;
......@@ -1413,10 +1436,12 @@ int ata_attach(ide_drive_t *drive)
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;
}
......@@ -1477,7 +1502,7 @@ int generic_ide_ioctl(struct block_device *bdev, unsigned int cmd,
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;
......@@ -1522,7 +1547,7 @@ int generic_ide_ioctl(struct block_device *bdev, unsigned int cmd,
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)
......@@ -1530,14 +1555,12 @@ int generic_ide_ioctl(struct block_device *bdev, unsigned int cmd,
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;
......@@ -1551,18 +1574,26 @@ int generic_ide_ioctl(struct block_device *bdev, unsigned int cmd,
{
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) {
/*
......@@ -1594,9 +1625,8 @@ int generic_ide_ioctl(struct block_device *bdev, unsigned int cmd,
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;
}
......@@ -2194,7 +2224,7 @@ static int default_cleanup (ide_drive_t *drive)
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;
......@@ -2262,6 +2292,11 @@ static int default_attach (ide_drive_t *drive)
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;
......@@ -2273,6 +2308,7 @@ static void setup_driver_defaults (ide_drive_t *drive)
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;
......@@ -2283,9 +2319,11 @@ int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver, int versio
{
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;
}
......@@ -2295,6 +2333,7 @@ int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver, int versio
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 */
......@@ -2319,7 +2358,7 @@ int ide_unregister_subdriver (ide_drive_t *drive)
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;
}
......@@ -2331,10 +2370,12 @@ int ide_unregister_subdriver (ide_drive_t *drive)
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;
}
......@@ -2344,10 +2385,7 @@ EXPORT_SYMBOL(ide_unregister_subdriver);
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;
}
......@@ -2367,7 +2405,8 @@ int ide_register_driver(ide_driver_t *driver)
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;
......
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