ide: Remove ide_spin_wait_hwgroup() and use special requests instead
Use a special request for serialisation purposes and get rid of the awkward ide_spin_wait_hwgroup(). This also involves converting the ide_devset structure so it can be shared by the /proc and the ioctl code. Signed-off-by: Elias Oltmanns <eo@nebensachen.de> [bart: use rq->cmd[] directly] Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
This commit is contained in:
Родитель
d6e2955a6b
Коммит
92f1f8fd80
|
@ -1809,11 +1809,11 @@ static ide_proc_entry_t idecd_proc[] = {
|
|||
{ NULL, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
ide_devset_rw(dsc_overlap, 0, 1, dsc_overlap);
|
||||
ide_devset_rw_field(dsc_overlap, dsc_overlap);
|
||||
|
||||
static const struct ide_devset *idecd_settings[] = {
|
||||
&ide_devset_dsc_overlap,
|
||||
NULL
|
||||
static const struct ide_proc_devset idecd_settings[] = {
|
||||
IDE_PROC_DEVSET(dsc_overlap, 0, 1),
|
||||
{ 0 },
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
|
@ -575,11 +575,8 @@ static int set_nowerr(ide_drive_t *drive, int arg)
|
|||
if (arg < 0 || arg > 1)
|
||||
return -EINVAL;
|
||||
|
||||
if (ide_spin_wait_hwgroup(drive))
|
||||
return -EBUSY;
|
||||
drive->nowerr = arg;
|
||||
drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
|
||||
spin_unlock_irq(&ide_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -702,33 +699,34 @@ static int set_addressing(ide_drive_t *drive, int arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
ide_devset_rw(acoustic, acoustic);
|
||||
ide_devset_rw(address, addressing);
|
||||
ide_devset_rw(multcount, multcount);
|
||||
ide_devset_rw(wcache, wcache);
|
||||
|
||||
ide_devset_rw_sync(nowerr, nowerr);
|
||||
|
||||
#ifdef CONFIG_IDE_PROC_FS
|
||||
ide_devset_rw_nolock(acoustic, 0, 254, acoustic);
|
||||
ide_devset_rw_nolock(address, 0, 2, addressing);
|
||||
ide_devset_rw_nolock(multcount, 0, 16, multcount);
|
||||
ide_devset_rw_nolock(nowerr, 0, 1, nowerr);
|
||||
ide_devset_rw_nolock(wcache, 0, 1, wcache);
|
||||
ide_devset_rw_field(bios_cyl, bios_cyl);
|
||||
ide_devset_rw_field(bios_head, bios_head);
|
||||
ide_devset_rw_field(bios_sect, bios_sect);
|
||||
ide_devset_rw_field(failures, failures);
|
||||
ide_devset_rw_field(lun, lun);
|
||||
ide_devset_rw_field(max_failures, max_failures);
|
||||
|
||||
ide_devset_rw(bios_cyl, 0, 65535, bios_cyl);
|
||||
ide_devset_rw(bios_head, 0, 255, bios_head);
|
||||
ide_devset_rw(bios_sect, 0, 63, bios_sect);
|
||||
ide_devset_rw(failures, 0, 65535, failures);
|
||||
ide_devset_rw(lun, 0, 7, lun);
|
||||
ide_devset_rw(max_failures, 0, 65535, max_failures);
|
||||
|
||||
static const struct ide_devset *idedisk_settings[] = {
|
||||
&ide_devset_acoustic,
|
||||
&ide_devset_address,
|
||||
&ide_devset_bios_cyl,
|
||||
&ide_devset_bios_head,
|
||||
&ide_devset_bios_sect,
|
||||
&ide_devset_failures,
|
||||
&ide_devset_lun,
|
||||
&ide_devset_max_failures,
|
||||
&ide_devset_multcount,
|
||||
&ide_devset_nowerr,
|
||||
&ide_devset_wcache,
|
||||
NULL
|
||||
static const struct ide_proc_devset idedisk_settings[] = {
|
||||
IDE_PROC_DEVSET(acoustic, 0, 254),
|
||||
IDE_PROC_DEVSET(address, 0, 2),
|
||||
IDE_PROC_DEVSET(bios_cyl, 0, 65535),
|
||||
IDE_PROC_DEVSET(bios_head, 0, 255),
|
||||
IDE_PROC_DEVSET(bios_sect, 0, 63),
|
||||
IDE_PROC_DEVSET(failures, 0, 65535),
|
||||
IDE_PROC_DEVSET(lun, 0, 7),
|
||||
IDE_PROC_DEVSET(max_failures, 0, 65535),
|
||||
IDE_PROC_DEVSET(multcount, 0, 16),
|
||||
IDE_PROC_DEVSET(nowerr, 0, 1),
|
||||
IDE_PROC_DEVSET(wcache, 0, 1),
|
||||
{ 0 },
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -1001,11 +999,11 @@ static int idedisk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
|
|||
}
|
||||
|
||||
static const struct ide_ioctl_devset ide_disk_ioctl_settings[] = {
|
||||
{ HDIO_GET_ADDRESS, HDIO_SET_ADDRESS, get_addressing, set_addressing },
|
||||
{ HDIO_GET_MULTCOUNT, HDIO_SET_MULTCOUNT, get_multcount, set_multcount },
|
||||
{ HDIO_GET_NOWERR, HDIO_SET_NOWERR, get_nowerr, set_nowerr },
|
||||
{ HDIO_GET_WCACHE, HDIO_SET_WCACHE, get_wcache, set_wcache },
|
||||
{ HDIO_GET_ACOUSTIC, HDIO_SET_ACOUSTIC, get_acoustic, set_acoustic },
|
||||
{ HDIO_GET_ADDRESS, HDIO_SET_ADDRESS, &ide_devset_address },
|
||||
{ HDIO_GET_MULTCOUNT, HDIO_SET_MULTCOUNT, &ide_devset_multcount },
|
||||
{ HDIO_GET_NOWERR, HDIO_SET_NOWERR, &ide_devset_nowerr },
|
||||
{ HDIO_GET_WCACHE, HDIO_SET_WCACHE, &ide_devset_wcache },
|
||||
{ HDIO_GET_ACOUSTIC, HDIO_SET_ACOUSTIC, &ide_devset_acoustic },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
|
|
@ -629,9 +629,9 @@ static sector_t idefloppy_capacity(ide_drive_t *drive)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_IDE_PROC_FS
|
||||
ide_devset_rw(bios_cyl, 0, 1023, bios_cyl);
|
||||
ide_devset_rw(bios_head, 0, 255, bios_head);
|
||||
ide_devset_rw(bios_sect, 0, 63, bios_sect);
|
||||
ide_devset_rw_field(bios_cyl, bios_cyl);
|
||||
ide_devset_rw_field(bios_head, bios_head);
|
||||
ide_devset_rw_field(bios_sect, bios_sect);
|
||||
|
||||
static int get_ticks(ide_drive_t *drive)
|
||||
{
|
||||
|
@ -646,14 +646,14 @@ static int set_ticks(ide_drive_t *drive, int arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
IDE_DEVSET(ticks, S_RW, 0, 255, get_ticks, set_ticks);
|
||||
IDE_DEVSET(ticks, DS_SYNC, get_ticks, set_ticks);
|
||||
|
||||
static const struct ide_devset *idefloppy_settings[] = {
|
||||
&ide_devset_bios_cyl,
|
||||
&ide_devset_bios_head,
|
||||
&ide_devset_bios_sect,
|
||||
&ide_devset_ticks,
|
||||
NULL
|
||||
static const struct ide_proc_devset idefloppy_settings[] = {
|
||||
IDE_PROC_DEVSET(bios_cyl, 0, 1023),
|
||||
IDE_PROC_DEVSET(bios_head, 0, 255),
|
||||
IDE_PROC_DEVSET(bios_sect, 0, 63),
|
||||
IDE_PROC_DEVSET(ticks, 0, 255),
|
||||
{ 0 },
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
|
@ -716,9 +716,49 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
|
|||
return ide_stopped;
|
||||
}
|
||||
|
||||
int ide_devset_execute(ide_drive_t *drive, const struct ide_devset *setting,
|
||||
int arg)
|
||||
{
|
||||
struct request_queue *q = drive->queue;
|
||||
struct request *rq;
|
||||
int ret = 0;
|
||||
|
||||
if (!(setting->flags & DS_SYNC))
|
||||
return setting->set(drive, arg);
|
||||
|
||||
rq = blk_get_request(q, READ, GFP_KERNEL);
|
||||
if (!rq)
|
||||
return -ENOMEM;
|
||||
|
||||
rq->cmd_type = REQ_TYPE_SPECIAL;
|
||||
rq->cmd_len = 5;
|
||||
rq->cmd[0] = REQ_DEVSET_EXEC;
|
||||
*(int *)&rq->cmd[1] = arg;
|
||||
rq->special = setting->set;
|
||||
|
||||
if (blk_execute_rq(q, NULL, rq, 0))
|
||||
ret = rq->errors;
|
||||
blk_put_request(rq);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ide_devset_execute);
|
||||
|
||||
static ide_startstop_t ide_special_rq(ide_drive_t *drive, struct request *rq)
|
||||
{
|
||||
switch (rq->cmd[0]) {
|
||||
case REQ_DEVSET_EXEC:
|
||||
{
|
||||
int err, (*setfunc)(ide_drive_t *, int) = rq->special;
|
||||
|
||||
err = setfunc(drive, *(int *)&rq->cmd[1]);
|
||||
if (err)
|
||||
rq->errors = err;
|
||||
else
|
||||
err = 1;
|
||||
ide_end_request(drive, err, 0);
|
||||
return ide_stopped;
|
||||
}
|
||||
case REQ_DRIVE_RESET:
|
||||
return ide_do_reset(drive);
|
||||
default:
|
||||
|
|
|
@ -6,11 +6,11 @@
|
|||
#include <linux/ide.h>
|
||||
|
||||
static const struct ide_ioctl_devset ide_ioctl_settings[] = {
|
||||
{ HDIO_GET_32BIT, HDIO_SET_32BIT, get_io_32bit, set_io_32bit },
|
||||
{ HDIO_GET_KEEPSETTINGS, HDIO_SET_KEEPSETTINGS, get_ksettings, set_ksettings },
|
||||
{ HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, get_unmaskirq, set_unmaskirq },
|
||||
{ HDIO_GET_DMA, HDIO_SET_DMA, get_using_dma, set_using_dma },
|
||||
{ -1, HDIO_SET_PIO_MODE, NULL, set_pio_mode },
|
||||
{ HDIO_GET_32BIT, HDIO_SET_32BIT, &ide_devset_io_32bit },
|
||||
{ HDIO_GET_KEEPSETTINGS, HDIO_SET_KEEPSETTINGS, &ide_devset_keepsettings },
|
||||
{ HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, &ide_devset_unmaskirq },
|
||||
{ HDIO_GET_DMA, HDIO_SET_DMA, &ide_devset_using_dma },
|
||||
{ -1, HDIO_SET_PIO_MODE, &ide_devset_pio_mode },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
@ -18,13 +18,14 @@ int ide_setting_ioctl(ide_drive_t *drive, struct block_device *bdev,
|
|||
unsigned int cmd, unsigned long arg,
|
||||
const struct ide_ioctl_devset *s)
|
||||
{
|
||||
const struct ide_devset *ds;
|
||||
unsigned long flags;
|
||||
int err = -EOPNOTSUPP;
|
||||
|
||||
for (; s->get_ioctl; s++) {
|
||||
if (s->get && s->get_ioctl == cmd)
|
||||
for (; (ds = s->setting); s++) {
|
||||
if (ds->get && s->get_ioctl == cmd)
|
||||
goto read_val;
|
||||
else if (s->set && s->set_ioctl == cmd)
|
||||
else if (ds->set && s->set_ioctl == cmd)
|
||||
goto set_val;
|
||||
}
|
||||
|
||||
|
@ -33,7 +34,7 @@ int ide_setting_ioctl(ide_drive_t *drive, struct block_device *bdev,
|
|||
read_val:
|
||||
mutex_lock(&ide_setting_mtx);
|
||||
spin_lock_irqsave(&ide_lock, flags);
|
||||
err = s->get(drive);
|
||||
err = ds->get(drive);
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
mutex_unlock(&ide_setting_mtx);
|
||||
return err >= 0 ? put_user(err, (long __user *)arg) : err;
|
||||
|
@ -46,7 +47,7 @@ set_val:
|
|||
err = -EACCES;
|
||||
else {
|
||||
mutex_lock(&ide_setting_mtx);
|
||||
err = s->set(drive, arg);
|
||||
err = ide_devset_execute(drive, ds, arg);
|
||||
mutex_unlock(&ide_setting_mtx);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -124,15 +124,16 @@ static int proc_ide_read_identify
|
|||
* setting semaphore
|
||||
*/
|
||||
|
||||
static const struct ide_devset *ide_find_setting(const struct ide_devset **st,
|
||||
static
|
||||
const struct ide_proc_devset *ide_find_setting(const struct ide_proc_devset *st,
|
||||
char *name)
|
||||
{
|
||||
while (*st) {
|
||||
if (strcmp((*st)->name, name) == 0)
|
||||
while (st->name) {
|
||||
if (strcmp(st->name, name) == 0)
|
||||
break;
|
||||
st++;
|
||||
}
|
||||
return *st;
|
||||
return st->name ? st : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -149,15 +150,16 @@ static const struct ide_devset *ide_find_setting(const struct ide_devset **st,
|
|||
*/
|
||||
|
||||
static int ide_read_setting(ide_drive_t *drive,
|
||||
const struct ide_devset *setting)
|
||||
const struct ide_proc_devset *setting)
|
||||
{
|
||||
const struct ide_devset *ds = setting->setting;
|
||||
int val = -EINVAL;
|
||||
|
||||
if ((setting->flags & S_READ)) {
|
||||
if (ds->get) {
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&ide_lock, flags);
|
||||
val = setting->get(drive);
|
||||
val = ds->get(drive);
|
||||
spin_unlock_irqrestore(&ide_lock, flags);
|
||||
}
|
||||
|
||||
|
@ -183,24 +185,21 @@ static int ide_read_setting(ide_drive_t *drive,
|
|||
*/
|
||||
|
||||
static int ide_write_setting(ide_drive_t *drive,
|
||||
const struct ide_devset *setting, int val)
|
||||
const struct ide_proc_devset *setting, int val)
|
||||
{
|
||||
const struct ide_devset *ds = setting->setting;
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EACCES;
|
||||
if (setting->set && (setting->flags & S_NOLOCK))
|
||||
return setting->set(drive, val);
|
||||
if (!(setting->flags & S_WRITE))
|
||||
if (!ds->set)
|
||||
return -EPERM;
|
||||
if (val < setting->min || val > setting->max)
|
||||
if ((ds->flags & DS_SYNC)
|
||||
&& (val < setting->min || val > setting->max))
|
||||
return -EINVAL;
|
||||
if (ide_spin_wait_hwgroup(drive))
|
||||
return -EBUSY;
|
||||
setting->set(drive, val);
|
||||
spin_unlock_irq(&ide_lock);
|
||||
return 0;
|
||||
return ide_devset_execute(drive, ds, val);
|
||||
}
|
||||
|
||||
static ide_devset_get(xfer_rate, current_speed);
|
||||
ide_devset_get(xfer_rate, current_speed);
|
||||
|
||||
static int set_xfer_rate (ide_drive_t *drive, int arg)
|
||||
{
|
||||
|
@ -226,29 +225,22 @@ static int set_xfer_rate (ide_drive_t *drive, int arg)
|
|||
return err;
|
||||
}
|
||||
|
||||
ide_devset_rw_nolock(current_speed, 0, 70, xfer_rate);
|
||||
ide_devset_rw_nolock(io_32bit, 0, 1 + (SUPPORT_VLB_SYNC << 1), io_32bit);
|
||||
ide_devset_rw_nolock(keepsettings, 0, 1, ksettings);
|
||||
ide_devset_rw_nolock(unmaskirq, 0, 1, unmaskirq);
|
||||
ide_devset_rw_nolock(using_dma, 0, 1, using_dma);
|
||||
ide_devset_rw(current_speed, xfer_rate);
|
||||
ide_devset_rw_field(init_speed, init_speed);
|
||||
ide_devset_rw_field(nice1, nice1);
|
||||
ide_devset_rw_field(number, dn);
|
||||
|
||||
ide_devset_w_nolock(pio_mode, 0, 255, pio_mode);
|
||||
|
||||
ide_devset_rw(init_speed, 0, 70, init_speed);
|
||||
ide_devset_rw(nice1, 0, 1, nice1);
|
||||
ide_devset_rw(number, 0, 3, dn);
|
||||
|
||||
static const struct ide_devset *ide_generic_settings[] = {
|
||||
&ide_devset_current_speed,
|
||||
&ide_devset_init_speed,
|
||||
&ide_devset_io_32bit,
|
||||
&ide_devset_keepsettings,
|
||||
&ide_devset_nice1,
|
||||
&ide_devset_number,
|
||||
&ide_devset_pio_mode,
|
||||
&ide_devset_unmaskirq,
|
||||
&ide_devset_using_dma,
|
||||
NULL
|
||||
static const struct ide_proc_devset ide_generic_settings[] = {
|
||||
IDE_PROC_DEVSET(current_speed, 0, 70),
|
||||
IDE_PROC_DEVSET(init_speed, 0, 70),
|
||||
IDE_PROC_DEVSET(io_32bit, 0, 1 + (SUPPORT_VLB_SYNC << 1)),
|
||||
IDE_PROC_DEVSET(keepsettings, 0, 1),
|
||||
IDE_PROC_DEVSET(nice1, 0, 1),
|
||||
IDE_PROC_DEVSET(number, 0, 3),
|
||||
IDE_PROC_DEVSET(pio_mode, 0, 255),
|
||||
IDE_PROC_DEVSET(unmaskirq, 0, 1),
|
||||
IDE_PROC_DEVSET(using_dma, 0, 1),
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
static void proc_ide_settings_warn(void)
|
||||
|
@ -266,7 +258,8 @@ static void proc_ide_settings_warn(void)
|
|||
static int proc_ide_read_settings
|
||||
(char *page, char **start, off_t off, int count, int *eof, void *data)
|
||||
{
|
||||
const struct ide_devset *setting, **g, **d;
|
||||
const struct ide_proc_devset *setting, *g, *d;
|
||||
const struct ide_devset *ds;
|
||||
ide_drive_t *drive = (ide_drive_t *) data;
|
||||
char *out = page;
|
||||
int len, rc, mul_factor, div_factor;
|
||||
|
@ -278,17 +271,17 @@ static int proc_ide_read_settings
|
|||
d = drive->settings;
|
||||
out += sprintf(out, "name\t\t\tvalue\t\tmin\t\tmax\t\tmode\n");
|
||||
out += sprintf(out, "----\t\t\t-----\t\t---\t\t---\t\t----\n");
|
||||
while (*g || (d && *d)) {
|
||||
while (g->name || (d && d->name)) {
|
||||
/* read settings in the alphabetical order */
|
||||
if (*g && d && *d) {
|
||||
if (strcmp((*d)->name, (*g)->name) < 0)
|
||||
setting = *d++;
|
||||
if (g->name && d && d->name) {
|
||||
if (strcmp(d->name, g->name) < 0)
|
||||
setting = d++;
|
||||
else
|
||||
setting = *g++;
|
||||
} else if (d && *d) {
|
||||
setting = *d++;
|
||||
setting = g++;
|
||||
} else if (d && d->name) {
|
||||
setting = d++;
|
||||
} else
|
||||
setting = *g++;
|
||||
setting = g++;
|
||||
mul_factor = setting->mulf ? setting->mulf(drive) : 1;
|
||||
div_factor = setting->divf ? setting->divf(drive) : 1;
|
||||
out += sprintf(out, "%-24s", setting->name);
|
||||
|
@ -298,9 +291,10 @@ static int proc_ide_read_settings
|
|||
else
|
||||
out += sprintf(out, "%-16s", "write-only");
|
||||
out += sprintf(out, "%-16d%-16d", (setting->min * mul_factor + div_factor - 1) / div_factor, setting->max * mul_factor / div_factor);
|
||||
if (setting->flags & S_READ)
|
||||
ds = setting->setting;
|
||||
if (ds->get)
|
||||
out += sprintf(out, "r");
|
||||
if (setting->flags & S_WRITE)
|
||||
if (ds->set)
|
||||
out += sprintf(out, "w");
|
||||
out += sprintf(out, "\n");
|
||||
}
|
||||
|
@ -319,7 +313,7 @@ static int proc_ide_write_settings(struct file *file, const char __user *buffer,
|
|||
int for_real = 0, mul_factor, div_factor;
|
||||
unsigned long n;
|
||||
|
||||
const struct ide_devset *setting;
|
||||
const struct ide_proc_devset *setting;
|
||||
char *buf, *s;
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
|
|
|
@ -2188,40 +2188,40 @@ static int set_##name(ide_drive_t *drive, int arg) \
|
|||
return 0; \
|
||||
}
|
||||
|
||||
#define ide_tape_devset_rw(_name, _min, _max, _field, _mulf, _divf) \
|
||||
#define ide_tape_devset_rw_field(_name, _field) \
|
||||
ide_tape_devset_get(_name, _field) \
|
||||
ide_tape_devset_set(_name, _field) \
|
||||
__IDE_DEVSET(_name, S_RW, _min, _max, get_##_name, set_##_name, _mulf, _divf)
|
||||
IDE_DEVSET(_name, DS_SYNC, get_##_name, set_##_name)
|
||||
|
||||
#define ide_tape_devset_r(_name, _min, _max, _field, _mulf, _divf) \
|
||||
#define ide_tape_devset_r_field(_name, _field) \
|
||||
ide_tape_devset_get(_name, _field) \
|
||||
__IDE_DEVSET(_name, S_READ, _min, _max, get_##_name, NULL, _mulf, _divf)
|
||||
IDE_DEVSET(_name, 0, get_##_name, NULL)
|
||||
|
||||
static int mulf_tdsc(ide_drive_t *drive) { return 1000; }
|
||||
static int divf_tdsc(ide_drive_t *drive) { return HZ; }
|
||||
static int divf_buffer(ide_drive_t *drive) { return 2; }
|
||||
static int divf_buffer_size(ide_drive_t *drive) { return 1024; }
|
||||
|
||||
ide_devset_rw(dsc_overlap, 0, 1, dsc_overlap);
|
||||
ide_devset_rw_field(dsc_overlap, dsc_overlap);
|
||||
|
||||
ide_tape_devset_rw(debug_mask, 0, 0xffff, debug_mask, NULL, NULL);
|
||||
ide_tape_devset_rw(tdsc, IDETAPE_DSC_RW_MIN, IDETAPE_DSC_RW_MAX,
|
||||
best_dsc_rw_freq, mulf_tdsc, divf_tdsc);
|
||||
ide_tape_devset_rw_field(debug_mask, debug_mask);
|
||||
ide_tape_devset_rw_field(tdsc, best_dsc_rw_freq);
|
||||
|
||||
ide_tape_devset_r(avg_speed, 0, 0xffff, avg_speed, NULL, NULL);
|
||||
ide_tape_devset_r(speed, 0, 0xffff, caps[14], NULL, NULL);
|
||||
ide_tape_devset_r(buffer, 0, 0xffff, caps[16], NULL, divf_buffer);
|
||||
ide_tape_devset_r(buffer_size, 0, 0xffff, buffer_size, NULL, divf_buffer_size);
|
||||
ide_tape_devset_r_field(avg_speed, avg_speed);
|
||||
ide_tape_devset_r_field(speed, caps[14]);
|
||||
ide_tape_devset_r_field(buffer, caps[16]);
|
||||
ide_tape_devset_r_field(buffer_size, buffer_size);
|
||||
|
||||
static const struct ide_devset *idetape_settings[] = {
|
||||
&ide_devset_avg_speed,
|
||||
&ide_devset_buffer,
|
||||
&ide_devset_buffer_size,
|
||||
&ide_devset_debug_mask,
|
||||
&ide_devset_dsc_overlap,
|
||||
&ide_devset_speed,
|
||||
&ide_devset_tdsc,
|
||||
NULL
|
||||
static const struct ide_proc_devset idetape_settings[] = {
|
||||
__IDE_PROC_DEVSET(avg_speed, 0, 0xffff, NULL, NULL),
|
||||
__IDE_PROC_DEVSET(buffer, 0, 0xffff, NULL, divf_buffer),
|
||||
__IDE_PROC_DEVSET(buffer_size, 0, 0xffff, NULL, divf_buffer_size),
|
||||
__IDE_PROC_DEVSET(debug_mask, 0, 0xffff, NULL, NULL),
|
||||
__IDE_PROC_DEVSET(dsc_overlap, 0, 1, NULL, NULL),
|
||||
__IDE_PROC_DEVSET(speed, 0, 0xffff, NULL, NULL),
|
||||
__IDE_PROC_DEVSET(tdsc, IDETAPE_DSC_RW_MIN, IDETAPE_DSC_RW_MAX,
|
||||
mulf_tdsc, divf_tdsc),
|
||||
{ 0 },
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
|
@ -250,42 +250,9 @@ void ide_init_port_hw(ide_hwif_t *hwif, hw_regs_t *hw)
|
|||
|
||||
DEFINE_MUTEX(ide_setting_mtx);
|
||||
|
||||
/**
|
||||
* ide_spin_wait_hwgroup - wait for group
|
||||
* @drive: drive in the group
|
||||
*
|
||||
* Wait for an IDE device group to go non busy and then return
|
||||
* holding the ide_lock which guards the hwgroup->busy status
|
||||
* and right to use it.
|
||||
*/
|
||||
|
||||
int ide_spin_wait_hwgroup (ide_drive_t *drive)
|
||||
{
|
||||
ide_hwgroup_t *hwgroup = HWGROUP(drive);
|
||||
unsigned long timeout = jiffies + (3 * HZ);
|
||||
|
||||
spin_lock_irq(&ide_lock);
|
||||
|
||||
while (hwgroup->busy) {
|
||||
unsigned long lflags;
|
||||
spin_unlock_irq(&ide_lock);
|
||||
local_irq_set(lflags);
|
||||
if (time_after(jiffies, timeout)) {
|
||||
local_irq_restore(lflags);
|
||||
printk(KERN_ERR "%s: channel busy\n", drive->name);
|
||||
return -EBUSY;
|
||||
}
|
||||
local_irq_restore(lflags);
|
||||
spin_lock_irq(&ide_lock);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(ide_spin_wait_hwgroup);
|
||||
|
||||
ide_devset_get(io_32bit, io_32bit);
|
||||
|
||||
int set_io_32bit(ide_drive_t *drive, int arg)
|
||||
static int set_io_32bit(ide_drive_t *drive, int arg)
|
||||
{
|
||||
if (drive->no_io_32bit)
|
||||
return -EPERM;
|
||||
|
@ -293,37 +260,28 @@ int set_io_32bit(ide_drive_t *drive, int arg)
|
|||
if (arg < 0 || arg > 1 + (SUPPORT_VLB_SYNC << 1))
|
||||
return -EINVAL;
|
||||
|
||||
if (ide_spin_wait_hwgroup(drive))
|
||||
return -EBUSY;
|
||||
|
||||
drive->io_32bit = arg;
|
||||
|
||||
spin_unlock_irq(&ide_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ide_devset_get(ksettings, keep_settings);
|
||||
|
||||
int set_ksettings(ide_drive_t *drive, int arg)
|
||||
static int set_ksettings(ide_drive_t *drive, int arg)
|
||||
{
|
||||
if (arg < 0 || arg > 1)
|
||||
return -EINVAL;
|
||||
|
||||
if (ide_spin_wait_hwgroup(drive))
|
||||
return -EBUSY;
|
||||
drive->keep_settings = arg;
|
||||
spin_unlock_irq(&ide_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ide_devset_get(using_dma, using_dma);
|
||||
|
||||
int set_using_dma(ide_drive_t *drive, int arg)
|
||||
static int set_using_dma(ide_drive_t *drive, int arg)
|
||||
{
|
||||
#ifdef CONFIG_BLK_DEV_IDEDMA
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
int err = -EPERM;
|
||||
|
||||
if (arg < 0 || arg > 1)
|
||||
|
@ -332,18 +290,9 @@ int set_using_dma(ide_drive_t *drive, int arg)
|
|||
if (ata_id_has_dma(drive->id) == 0)
|
||||
goto out;
|
||||
|
||||
if (hwif->dma_ops == NULL)
|
||||
if (drive->hwif->dma_ops == NULL)
|
||||
goto out;
|
||||
|
||||
err = -EBUSY;
|
||||
if (ide_spin_wait_hwgroup(drive))
|
||||
goto out;
|
||||
/*
|
||||
* set ->busy flag, unlock and let it ride
|
||||
*/
|
||||
hwif->hwgroup->busy = 1;
|
||||
spin_unlock_irq(&ide_lock);
|
||||
|
||||
err = 0;
|
||||
|
||||
if (arg) {
|
||||
|
@ -352,12 +301,6 @@ int set_using_dma(ide_drive_t *drive, int arg)
|
|||
} else
|
||||
ide_dma_off(drive);
|
||||
|
||||
/*
|
||||
* lock, clear ->busy flag and unlock before leaving
|
||||
*/
|
||||
spin_lock_irq(&ide_lock);
|
||||
hwif->hwgroup->busy = 0;
|
||||
spin_unlock_irq(&ide_lock);
|
||||
out:
|
||||
return err;
|
||||
#else
|
||||
|
@ -368,7 +311,7 @@ out:
|
|||
#endif
|
||||
}
|
||||
|
||||
int set_pio_mode(ide_drive_t *drive, int arg)
|
||||
static int set_pio_mode(ide_drive_t *drive, int arg)
|
||||
{
|
||||
struct request *rq;
|
||||
ide_hwif_t *hwif = drive->hwif;
|
||||
|
@ -398,7 +341,7 @@ int set_pio_mode(ide_drive_t *drive, int arg)
|
|||
|
||||
ide_devset_get(unmaskirq, unmask);
|
||||
|
||||
int set_unmaskirq(ide_drive_t *drive, int arg)
|
||||
static int set_unmaskirq(ide_drive_t *drive, int arg)
|
||||
{
|
||||
if (drive->no_unmask)
|
||||
return -EPERM;
|
||||
|
@ -406,14 +349,20 @@ int set_unmaskirq(ide_drive_t *drive, int arg)
|
|||
if (arg < 0 || arg > 1)
|
||||
return -EINVAL;
|
||||
|
||||
if (ide_spin_wait_hwgroup(drive))
|
||||
return -EBUSY;
|
||||
drive->unmask = arg;
|
||||
spin_unlock_irq(&ide_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define ide_gen_devset_rw(_name, _func) \
|
||||
__IDE_DEVSET(_name, DS_SYNC, get_##_func, set_##_func)
|
||||
|
||||
ide_gen_devset_rw(io_32bit, io_32bit);
|
||||
ide_gen_devset_rw(keepsettings, ksettings);
|
||||
ide_gen_devset_rw(unmaskirq, unmaskirq);
|
||||
ide_gen_devset_rw(using_dma, using_dma);
|
||||
__IDE_DEVSET(pio_mode, 0, NULL, set_pio_mode);
|
||||
|
||||
static int generic_ide_suspend(struct device *dev, pm_message_t mesg)
|
||||
{
|
||||
ide_drive_t *drive = dev->driver_data;
|
||||
|
|
|
@ -400,25 +400,25 @@ static int set_##name(ide_drive_t *drive, int arg) \
|
|||
return 0; \
|
||||
}
|
||||
|
||||
#define ide_scsi_devset_rw(_name, _min, _max, _field) \
|
||||
#define ide_scsi_devset_rw_field(_name, _field) \
|
||||
ide_scsi_devset_get(_name, _field); \
|
||||
ide_scsi_devset_set(_name, _field); \
|
||||
IDE_DEVSET(_name, S_RW, _min, _max, get_##_name, set_##_name)
|
||||
IDE_DEVSET(_name, DS_SYNC, get_##_name, set_##_name);
|
||||
|
||||
ide_devset_rw(bios_cyl, 0, 1023, bios_cyl);
|
||||
ide_devset_rw(bios_head, 0, 255, bios_head);
|
||||
ide_devset_rw(bios_sect, 0, 63, bios_sect);
|
||||
ide_devset_rw_field(bios_cyl, bios_cyl);
|
||||
ide_devset_rw_field(bios_head, bios_head);
|
||||
ide_devset_rw_field(bios_sect, bios_sect);
|
||||
|
||||
ide_scsi_devset_rw(transform, 0, 3, transform);
|
||||
ide_scsi_devset_rw(log, 0, 1, log);
|
||||
ide_scsi_devset_rw_field(transform, transform);
|
||||
ide_scsi_devset_rw_field(log, log);
|
||||
|
||||
static const struct ide_devset *idescsi_settings[] = {
|
||||
&ide_devset_bios_cyl,
|
||||
&ide_devset_bios_head,
|
||||
&ide_devset_bios_sect,
|
||||
&ide_devset_log,
|
||||
&ide_devset_transform,
|
||||
NULL
|
||||
static const struct ide_proc_devset idescsi_settings[] = {
|
||||
IDE_PROC_DEVSET(bios_cyl, 0, 1023),
|
||||
IDE_PROC_DEVSET(bios_head, 0, 255),
|
||||
IDE_PROC_DEVSET(bios_sect, 0, 63),
|
||||
IDE_PROC_DEVSET(log, 0, 1),
|
||||
IDE_PROC_DEVSET(transform, 0, 3),
|
||||
{ 0 },
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
|
@ -161,6 +161,7 @@ enum {
|
|||
* Values should be in the range of 0x20 to 0x3f.
|
||||
*/
|
||||
#define REQ_DRIVE_RESET 0x20
|
||||
#define REQ_DEVSET_EXEC 0x21
|
||||
|
||||
/*
|
||||
* Check for an interrupt and acknowledge the interrupt status
|
||||
|
@ -405,7 +406,7 @@ struct ide_drive_s {
|
|||
u16 *id; /* identification info */
|
||||
#ifdef CONFIG_IDE_PROC_FS
|
||||
struct proc_dir_entry *proc; /* /proc/ide/ directory entry */
|
||||
const struct ide_devset **settings; /* /proc/ide/ drive settings */
|
||||
const struct ide_proc_devset *settings; /* /proc/ide/ drive settings */
|
||||
#endif
|
||||
struct hwif_s *hwif; /* actually (ide_hwif_t *) */
|
||||
|
||||
|
@ -707,29 +708,62 @@ typedef struct ide_driver_s ide_driver_t;
|
|||
|
||||
extern struct mutex ide_setting_mtx;
|
||||
|
||||
int get_io_32bit(ide_drive_t *);
|
||||
int set_io_32bit(ide_drive_t *, int);
|
||||
int get_ksettings(ide_drive_t *);
|
||||
int set_ksettings(ide_drive_t *, int);
|
||||
int set_pio_mode(ide_drive_t *, int);
|
||||
int get_unmaskirq(ide_drive_t *);
|
||||
int set_unmaskirq(ide_drive_t *, int);
|
||||
int get_using_dma(ide_drive_t *);
|
||||
int set_using_dma(ide_drive_t *, int);
|
||||
/*
|
||||
* configurable drive settings
|
||||
*/
|
||||
|
||||
#define DS_SYNC (1 << 0)
|
||||
|
||||
struct ide_devset {
|
||||
int (*get)(ide_drive_t *);
|
||||
int (*set)(ide_drive_t *, int);
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
#define __DEVSET(_flags, _get, _set) { \
|
||||
.flags = _flags, \
|
||||
.get = _get, \
|
||||
.set = _set, \
|
||||
}
|
||||
|
||||
#define ide_devset_get(name, field) \
|
||||
int get_##name(ide_drive_t *drive) \
|
||||
static int get_##name(ide_drive_t *drive) \
|
||||
{ \
|
||||
return drive->field; \
|
||||
}
|
||||
|
||||
#define ide_devset_set(name, field) \
|
||||
int set_##name(ide_drive_t *drive, int arg) \
|
||||
static int set_##name(ide_drive_t *drive, int arg) \
|
||||
{ \
|
||||
drive->field = arg; \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
#define __IDE_DEVSET(_name, _flags, _get, _set) \
|
||||
const struct ide_devset ide_devset_##_name = \
|
||||
__DEVSET(_flags, _get, _set)
|
||||
|
||||
#define IDE_DEVSET(_name, _flags, _get, _set) \
|
||||
static __IDE_DEVSET(_name, _flags, _get, _set)
|
||||
|
||||
#define ide_devset_rw(_name, _func) \
|
||||
IDE_DEVSET(_name, 0, get_##_func, set_##_func)
|
||||
|
||||
#define ide_devset_w(_name, _func) \
|
||||
IDE_DEVSET(_name, 0, NULL, set_##_func)
|
||||
|
||||
#define ide_devset_rw_sync(_name, _func) \
|
||||
IDE_DEVSET(_name, DS_SYNC, get_##_func, set_##_func)
|
||||
|
||||
#define ide_decl_devset(_name) \
|
||||
extern const struct ide_devset ide_devset_##_name
|
||||
|
||||
ide_decl_devset(io_32bit);
|
||||
ide_decl_devset(keepsettings);
|
||||
ide_decl_devset(pio_mode);
|
||||
ide_decl_devset(unmaskirq);
|
||||
ide_decl_devset(using_dma);
|
||||
|
||||
/* ATAPI packet command flags */
|
||||
enum {
|
||||
/* set when an error is considered normal - no retry (ide-tape) */
|
||||
|
@ -797,60 +831,34 @@ struct ide_atapi_pc {
|
|||
|
||||
#ifdef CONFIG_IDE_PROC_FS
|
||||
/*
|
||||
* configurable drive settings
|
||||
* /proc/ide interface
|
||||
*/
|
||||
|
||||
#define S_READ (1 << 0)
|
||||
#define S_WRITE (1 << 1)
|
||||
#define S_RW (S_READ | S_WRITE)
|
||||
#define S_NOLOCK (1 << 2)
|
||||
#define ide_devset_rw_field(_name, _field) \
|
||||
ide_devset_get(_name, _field); \
|
||||
ide_devset_set(_name, _field); \
|
||||
IDE_DEVSET(_name, DS_SYNC, get_##_name, set_##_name)
|
||||
|
||||
struct ide_devset {
|
||||
struct ide_proc_devset {
|
||||
const char *name;
|
||||
unsigned int flags;
|
||||
const struct ide_devset *setting;
|
||||
int min, max;
|
||||
int (*get)(ide_drive_t *);
|
||||
int (*set)(ide_drive_t *, int);
|
||||
int (*mulf)(ide_drive_t *);
|
||||
int (*divf)(ide_drive_t *);
|
||||
};
|
||||
|
||||
#define __DEVSET(_name, _flags, _min, _max, _get, _set, _mulf, _divf) { \
|
||||
#define __IDE_PROC_DEVSET(_name, _min, _max, _mulf, _divf) { \
|
||||
.name = __stringify(_name), \
|
||||
.flags = _flags, \
|
||||
.setting = &ide_devset_##_name, \
|
||||
.min = _min, \
|
||||
.max = _max, \
|
||||
.get = _get, \
|
||||
.set = _set, \
|
||||
.mulf = _mulf, \
|
||||
.divf = _divf, \
|
||||
}
|
||||
|
||||
#define __IDE_DEVSET(_name, _flags, _min, _max, _get, _set, _mulf, _divf) \
|
||||
static const struct ide_devset ide_devset_##_name = \
|
||||
__DEVSET(_name, _flags, _min, _max, _get, _set, _mulf, _divf)
|
||||
#define IDE_PROC_DEVSET(_name, _min, _max) \
|
||||
__IDE_PROC_DEVSET(_name, _min, _max, NULL, NULL)
|
||||
|
||||
#define IDE_DEVSET(_name, _flags, _min, _max, _get, _set) \
|
||||
__IDE_DEVSET(_name, _flags, _min, _max, _get, _set, NULL, NULL)
|
||||
|
||||
#define ide_devset_rw_nolock(_name, _min, _max, _func) \
|
||||
IDE_DEVSET(_name, S_RW | S_NOLOCK, _min, _max, get_##_func, set_##_func)
|
||||
|
||||
#define ide_devset_w_nolock(_name, _min, _max, _func) \
|
||||
IDE_DEVSET(_name, S_WRITE | S_NOLOCK, _min, _max, NULL, set_##_func)
|
||||
|
||||
#define ide_devset_rw(_name, _min, _max, _field) \
|
||||
static ide_devset_get(_name, _field); \
|
||||
static ide_devset_set(_name, _field); \
|
||||
IDE_DEVSET(_name, S_RW, _min, _max, get_##_name, set_##_name)
|
||||
|
||||
#define ide_devset_r(_name, _min, _max, _field) \
|
||||
ide_devset_get(_name, _field) \
|
||||
IDE_DEVSET(_name, S_READ, _min, _max, get_##_name, NULL)
|
||||
|
||||
/*
|
||||
* /proc/ide interface
|
||||
*/
|
||||
typedef struct {
|
||||
const char *name;
|
||||
mode_t mode;
|
||||
|
@ -949,7 +957,7 @@ struct ide_driver_s {
|
|||
void (*shutdown)(ide_drive_t *);
|
||||
#ifdef CONFIG_IDE_PROC_FS
|
||||
ide_proc_entry_t *proc;
|
||||
const struct ide_devset **settings;
|
||||
const struct ide_proc_devset *settings;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -961,9 +969,7 @@ void ide_device_put(ide_drive_t *);
|
|||
struct ide_ioctl_devset {
|
||||
unsigned int get_ioctl;
|
||||
unsigned int set_ioctl;
|
||||
|
||||
int (*get)(ide_drive_t *);
|
||||
int (*set)(ide_drive_t *, int);
|
||||
const struct ide_devset *setting;
|
||||
};
|
||||
|
||||
int ide_setting_ioctl(ide_drive_t *, struct block_device *, unsigned int,
|
||||
|
@ -1002,6 +1008,9 @@ int ide_wait_stat(ide_startstop_t *, ide_drive_t *, u8, u8, unsigned long);
|
|||
|
||||
extern ide_startstop_t ide_do_reset (ide_drive_t *);
|
||||
|
||||
extern int ide_devset_execute(ide_drive_t *drive,
|
||||
const struct ide_devset *setting, int arg);
|
||||
|
||||
extern void ide_do_drive_cmd(ide_drive_t *, struct request *);
|
||||
|
||||
extern void ide_end_drive_cmd(ide_drive_t *, u8, u8);
|
||||
|
@ -1191,7 +1200,6 @@ extern int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout);
|
|||
|
||||
extern void ide_stall_queue(ide_drive_t *drive, unsigned long timeout);
|
||||
|
||||
extern int ide_spin_wait_hwgroup(ide_drive_t *);
|
||||
extern void ide_timer_expiry(unsigned long);
|
||||
extern irqreturn_t ide_intr(int irq, void *dev_id);
|
||||
extern void do_ide_request(struct request_queue *);
|
||||
|
|
Загрузка…
Ссылка в новой задаче