aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-03 06:02:24 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-03 06:02:24 -0700
commitc753237cb5783cd92b01fbfb6e6028dcac28b113 (patch)
treeacc4225515c921abef8d607e9fa622a5b93d009a
parent184a2f07d38d9bde2119d867c851efe9a2dcb382 (diff)
parenta04780b2d7f0c71486a6c3e4b452ff8b05f2bd59 (diff)
downloadhistory-c753237cb5783cd92b01fbfb6e6028dcac28b113.tar.gz
Merge bk://bart.bkbits.net/ide-2.6
into ppc970.osdl.org:/home/torvalds/v2.6/linux
-rw-r--r--drivers/ide/Makefile3
-rw-r--r--drivers/ide/ide-cd.c71
-rw-r--r--drivers/ide/ide-cd.h2
-rw-r--r--drivers/ide/ide-default.c76
-rw-r--r--drivers/ide/ide-disk.c30
-rw-r--r--drivers/ide/ide-dma.c8
-rw-r--r--drivers/ide/ide-floppy.c48
-rw-r--r--drivers/ide/ide-io.c46
-rw-r--r--drivers/ide/ide-probe.c122
-rw-r--r--drivers/ide/ide-proc.c12
-rw-r--r--drivers/ide/ide-tape.c41
-rw-r--r--drivers/ide/ide-taskfile.c11
-rw-r--r--drivers/ide/ide.c86
-rw-r--r--drivers/ide/pci/via82cxxx.c7
-rw-r--r--drivers/scsi/ide-scsi.c44
-rw-r--r--include/linux/ide.h6
16 files changed, 338 insertions, 275 deletions
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile
index eb3c8087764732..5be8ad6dc9edcf 100644
--- a/drivers/ide/Makefile
+++ b/drivers/ide/Makefile
@@ -13,8 +13,7 @@ EXTRA_CFLAGS += -Idrivers/ide
obj-$(CONFIG_BLK_DEV_IDE) += pci/
-ide-core-y += ide.o ide-default.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \
- ide-taskfile.o
+ide-core-y += ide.o ide-io.o ide-iops.o ide-lib.o ide-probe.o ide-taskfile.o
ide-core-$(CONFIG_BLK_DEV_CMD640) += pci/cmd640.o
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 4b96aa193161fb..33a020faeabde2 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -328,7 +328,8 @@ static DECLARE_MUTEX(idecd_ref_sem);
#define to_ide_cd(obj) container_of(obj, struct cdrom_info, kref)
-#define ide_cd_g(disk) ((disk)->private_data)
+#define ide_cd_g(disk) \
+ container_of((disk)->private_data, struct cdrom_info, driver)
static struct cdrom_info *ide_cd_get(struct gendisk *disk)
{
@@ -556,10 +557,13 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
/*
* Initialize a ide-cd packet command request
*/
-static void cdrom_prepare_request(struct request *rq)
+static void cdrom_prepare_request(ide_drive_t *drive, struct request *rq)
{
+ struct cdrom_info *cd = drive->driver_data;
+
ide_init_drive_cmd(rq);
rq->flags = REQ_PC;
+ rq->rq_disk = cd->disk;
}
static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
@@ -572,7 +576,7 @@ static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
sense = &info->sense_data;
/* stuff the sense request in front of our current request */
- cdrom_prepare_request(rq);
+ cdrom_prepare_request(drive, rq);
rq->data = sense;
rq->cmd[0] = GPCMD_REQUEST_SENSE;
@@ -1856,7 +1860,7 @@ static ide_startstop_t cdrom_start_write_cont(ide_drive_t *drive)
static ide_startstop_t cdrom_start_write(ide_drive_t *drive, struct request *rq)
{
struct cdrom_info *info = drive->driver_data;
- struct gendisk *g = drive->disk;
+ struct gendisk *g = info->disk;
unsigned short sectors_per_frame = queue_hardsect_size(drive->queue) >> SECTOR_BITS;
/*
@@ -2048,7 +2052,7 @@ static int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense)
struct cdrom_info *info = drive->driver_data;
struct cdrom_device_info *cdi = &info->devinfo;
- cdrom_prepare_request(&req);
+ cdrom_prepare_request(drive, &req);
req.sense = sense;
req.cmd[0] = GPCMD_TEST_UNIT_READY;
@@ -2080,7 +2084,7 @@ cdrom_lockdoor(ide_drive_t *drive, int lockflag, struct request_sense *sense)
if (CDROM_CONFIG_FLAGS(drive)->no_doorlock) {
stat = 0;
} else {
- cdrom_prepare_request(&req);
+ cdrom_prepare_request(drive, &req);
req.sense = sense;
req.cmd[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;
req.cmd[4] = lockflag ? 1 : 0;
@@ -2124,7 +2128,7 @@ static int cdrom_eject(ide_drive_t *drive, int ejectflag,
if (CDROM_STATE_FLAGS(drive)->door_locked && ejectflag)
return 0;
- cdrom_prepare_request(&req);
+ cdrom_prepare_request(drive, &req);
/* only tell drive to close tray if open, if it can do that */
if (ejectflag && !CDROM_CONFIG_FLAGS(drive)->close_tray)
@@ -2148,7 +2152,7 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
int stat;
struct request req;
- cdrom_prepare_request(&req);
+ cdrom_prepare_request(drive, &req);
req.sense = sense;
req.cmd[0] = GPCMD_READ_CDVD_CAPACITY;
@@ -2171,7 +2175,7 @@ static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag,
{
struct request req;
- cdrom_prepare_request(&req);
+ cdrom_prepare_request(drive, &req);
req.sense = sense;
req.data = buf;
@@ -2228,7 +2232,7 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
if (stat)
toc->capacity = 0x1fffff;
- set_capacity(drive->disk, toc->capacity * sectors_per_frame);
+ set_capacity(info->disk, toc->capacity * sectors_per_frame);
blk_queue_hardsect_size(drive->queue,
sectors_per_frame << SECTOR_BITS);
@@ -2348,7 +2352,7 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
stat = cdrom_get_last_written(cdi, &last_written);
if (!stat && (last_written > toc->capacity)) {
toc->capacity = last_written;
- set_capacity(drive->disk, toc->capacity * sectors_per_frame);
+ set_capacity(info->disk, toc->capacity * sectors_per_frame);
}
/* Remember that we've read this stuff. */
@@ -2363,7 +2367,7 @@ static int cdrom_read_subchannel(ide_drive_t *drive, int format, char *buf,
{
struct request req;
- cdrom_prepare_request(&req);
+ cdrom_prepare_request(drive, &req);
req.sense = sense;
req.data = buf;
@@ -2383,7 +2387,7 @@ static int cdrom_select_speed(ide_drive_t *drive, int speed,
struct request_sense *sense)
{
struct request req;
- cdrom_prepare_request(&req);
+ cdrom_prepare_request(drive, &req);
req.sense = sense;
if (speed == 0)
@@ -2413,7 +2417,7 @@ static int cdrom_play_audio(ide_drive_t *drive, int lba_start, int lba_end)
struct request_sense sense;
struct request req;
- cdrom_prepare_request(&req);
+ cdrom_prepare_request(drive, &req);
req.sense = &sense;
req.cmd[0] = GPCMD_PLAY_AUDIO_MSF;
@@ -2463,7 +2467,7 @@ static int ide_cdrom_packet(struct cdrom_device_info *cdi,
/* here we queue the commands from the uniform CD-ROM
layer. the packet must be complete, as we do not
touch it at all. */
- cdrom_prepare_request(&req);
+ cdrom_prepare_request(drive, &req);
memcpy(req.cmd, cgc->cmd, CDROM_PACKET_SIZE);
if (cgc->sense)
memset(cgc->sense, 0, sizeof(struct request_sense));
@@ -2613,7 +2617,7 @@ int ide_cdrom_reset (struct cdrom_device_info *cdi)
struct request req;
int ret;
- cdrom_prepare_request(&req);
+ cdrom_prepare_request(drive, &req);
req.flags = REQ_SPECIAL | REQ_QUIET;
ret = ide_do_drive_cmd(drive, &req, ide_wait);
@@ -2857,7 +2861,7 @@ static int ide_cdrom_register (ide_drive_t *drive, int nslots)
if (!CDROM_CONFIG_FLAGS(drive)->mo_drive)
devinfo->mask |= CDC_MO_DRIVE;
- devinfo->disk = drive->disk;
+ devinfo->disk = info->disk;
return register_cdrom(devinfo);
}
@@ -3219,6 +3223,9 @@ int ide_cdrom_setup (ide_drive_t *drive)
*/
blk_queue_hardsect_size(drive->queue, CD_FRAMESIZE);
+ if (drive->autotune == IDE_TUNE_DEFAULT ||
+ drive->autotune == IDE_TUNE_AUTO)
+ drive->dsc_overlap = (drive->next != drive);
#if 0
drive->dsc_overlap = (HWIF(drive)->no_dsc) ? 0 : 1;
if (HWIF(drive)->no_dsc) {
@@ -3259,7 +3266,7 @@ int ide_cdrom_cleanup(ide_drive_t *drive)
return 1;
}
- del_gendisk(drive->disk);
+ del_gendisk(info->disk);
ide_cd_put(info);
@@ -3271,7 +3278,7 @@ static void ide_cd_release(struct kref *kref)
struct cdrom_info *info = to_ide_cd(kref);
struct cdrom_device_info *devinfo = &info->devinfo;
ide_drive_t *drive = info->drive;
- struct gendisk *g = drive->disk;
+ struct gendisk *g = info->disk;
if (info->buffer != NULL)
kfree(info->buffer);
@@ -3282,10 +3289,11 @@ static void ide_cd_release(struct kref *kref)
if (devinfo->handle == drive && unregister_cdrom(devinfo))
printk(KERN_ERR "%s: %s failed to unregister device from the cdrom "
"driver.\n", __FUNCTION__, drive->name);
+ drive->dsc_overlap = 0;
drive->driver_data = NULL;
blk_queue_prep_rq(drive->queue, NULL);
g->private_data = NULL;
- g->fops = ide_fops;
+ put_disk(g);
kfree(info);
}
@@ -3413,7 +3421,7 @@ MODULE_DESCRIPTION("ATAPI CD-ROM Driver");
static int ide_cdrom_attach (ide_drive_t *drive)
{
struct cdrom_info *info;
- struct gendisk *g = drive->disk;
+ struct gendisk *g;
struct request_sense sense;
if (!strstr("ide-cdrom", drive->driver_req))
@@ -3438,17 +3446,28 @@ static int ide_cdrom_attach (ide_drive_t *drive)
printk(KERN_ERR "%s: Can't allocate a cdrom structure\n", drive->name);
goto failed;
}
+
+ g = alloc_disk(1 << PARTN_BITS);
+ if (!g)
+ goto out_free_cd;
+
+ ide_init_disk(g, drive);
+
if (ide_register_subdriver(drive, &ide_cdrom_driver)) {
printk(KERN_ERR "%s: Failed to register the driver with ide.c\n",
drive->name);
- kfree(info);
- goto failed;
+ goto out_put_disk;
}
memset(info, 0, sizeof (struct cdrom_info));
kref_init(&info->kref);
info->drive = drive;
+ info->driver = &ide_cdrom_driver;
+ info->disk = g;
+
+ g->private_data = &info->driver;
+
drive->driver_data = info;
DRIVER(drive)->busy++;
@@ -3477,10 +3496,14 @@ static int ide_cdrom_attach (ide_drive_t *drive)
cdrom_read_toc(drive, &sense);
g->fops = &idecd_ops;
- g->private_data = info;
g->flags |= GENHD_FL_REMOVABLE;
add_disk(g);
return 0;
+
+out_put_disk:
+ put_disk(g);
+out_free_cd:
+ kfree(info);
failed:
return 1;
}
diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h
index 171c65eb313852..7ca3e5afc66551 100644
--- a/drivers/ide/ide-cd.h
+++ b/drivers/ide/ide-cd.h
@@ -461,6 +461,8 @@ struct atapi_changer_info {
/* Extra per-device info for cdrom drives. */
struct cdrom_info {
ide_drive_t *drive;
+ ide_driver_t *driver;
+ struct gendisk *disk;
struct kref kref;
/* Buffer for table of contents. NULL if we haven't allocated
diff --git a/drivers/ide/ide-default.c b/drivers/ide/ide-default.c
deleted file mode 100644
index 8b0c8520f7ce66..00000000000000
--- a/drivers/ide/ide-default.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * ide-default - Driver for unbound ide devices
- *
- * This provides a clean way to bind a device to default operations
- * by having an actual driver class that rather than special casing
- * "no driver" all over the IDE code
- *
- * Copyright (C) 2003, Red Hat <alan@redhat.com>
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/major.h>
-#include <linux/errno.h>
-#include <linux/genhd.h>
-#include <linux/slab.h>
-#include <linux/cdrom.h>
-#include <linux/ide.h>
-#include <linux/bitops.h>
-
-#include <asm/byteorder.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/unaligned.h>
-
-#define IDEDEFAULT_VERSION "0.9.newide"
-/*
- * Driver initialization.
- */
-
-static int idedefault_attach(ide_drive_t *drive);
-
-static ide_startstop_t idedefault_do_request(ide_drive_t *drive, struct request *rq, sector_t block)
-{
- ide_end_request(drive, 0, 0);
- return ide_stopped;
-}
-
-/*
- * IDE subdriver functions, registered with ide.c
- */
-
-ide_driver_t idedefault_driver = {
- .name = "ide-default",
- .version = IDEDEFAULT_VERSION,
- .attach = idedefault_attach,
- .cleanup = ide_unregister_subdriver,
- .do_request = idedefault_do_request,
- .end_request = ide_end_request,
- .error = __ide_error,
- .abort = __ide_abort,
- .drives = LIST_HEAD_INIT(idedefault_driver.drives)
-};
-
-static int idedefault_attach (ide_drive_t *drive)
-{
- if (ide_register_subdriver(drive, &idedefault_driver)) {
- printk(KERN_ERR "ide-default: %s: Failed to register the "
- "driver with ide.c\n", drive->name);
- return 1;
- }
-
- return 0;
-}
-
-MODULE_DESCRIPTION("IDE Default Driver");
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 9636135ee07790..5d54f77561007f 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -73,6 +73,8 @@
struct ide_disk_obj {
ide_drive_t *drive;
+ ide_driver_t *driver;
+ struct gendisk *disk;
struct kref kref;
};
@@ -80,7 +82,8 @@ static DECLARE_MUTEX(idedisk_ref_sem);
#define to_ide_disk(obj) container_of(obj, struct ide_disk_obj, kref)
-#define ide_disk_g(disk) ((disk)->private_data)
+#define ide_disk_g(disk) \
+ container_of((disk)->private_data, struct ide_disk_obj, driver)
static struct ide_disk_obj *ide_disk_get(struct gendisk *disk)
{
@@ -1024,7 +1027,7 @@ static void ide_cacheflush_p(ide_drive_t *drive)
static int idedisk_cleanup (ide_drive_t *drive)
{
struct ide_disk_obj *idkp = drive->driver_data;
- struct gendisk *g = drive->disk;
+ struct gendisk *g = idkp->disk;
ide_cacheflush_p(drive);
if (ide_unregister_subdriver(drive))
@@ -1040,12 +1043,12 @@ static void ide_disk_release(struct kref *kref)
{
struct ide_disk_obj *idkp = to_ide_disk(kref);
ide_drive_t *drive = idkp->drive;
- struct gendisk *g = drive->disk;
+ struct gendisk *g = idkp->disk;
drive->driver_data = NULL;
drive->devfs_name[0] = '\0';
g->private_data = NULL;
- g->fops = ide_fops;
+ put_disk(g);
kfree(idkp);
}
@@ -1199,7 +1202,7 @@ MODULE_DESCRIPTION("ATA DISK Driver");
static int idedisk_attach(ide_drive_t *drive)
{
struct ide_disk_obj *idkp;
- struct gendisk *g = drive->disk;
+ struct gendisk *g;
/* strstr("foo", "") is non-NULL */
if (!strstr("ide-disk", drive->driver_req))
@@ -1213,9 +1216,15 @@ static int idedisk_attach(ide_drive_t *drive)
if (!idkp)
goto failed;
+ g = alloc_disk(1 << PARTN_BITS);
+ if (!g)
+ goto out_free_idkp;
+
+ ide_init_disk(g, drive);
+
if (ide_register_subdriver(drive, &idedisk_driver)) {
printk (KERN_ERR "ide-disk: %s: Failed to register the driver with ide.c\n", drive->name);
- goto out_free_idkp;
+ goto out_put_disk;
}
memset(idkp, 0, sizeof(*idkp));
@@ -1223,6 +1232,11 @@ static int idedisk_attach(ide_drive_t *drive)
kref_init(&idkp->kref);
idkp->drive = drive;
+ idkp->driver = &idedisk_driver;
+ idkp->disk = g;
+
+ g->private_data = &idkp->driver;
+
drive->driver_data = idkp;
DRIVER(drive)->busy++;
@@ -1240,9 +1254,11 @@ static int idedisk_attach(ide_drive_t *drive)
g->flags = drive->removable ? GENHD_FL_REMOVABLE : 0;
set_capacity(g, idedisk_capacity(drive));
g->fops = &idedisk_ops;
- g->private_data = idkp;
add_disk(g);
return 0;
+
+out_put_disk:
+ put_disk(g);
out_free_idkp:
kfree(idkp);
failed:
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index 1179a31f81405a..2d2eefb610dd80 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -176,7 +176,13 @@ ide_startstop_t ide_dma_intr (ide_drive_t *drive)
if (!dma_stat) {
struct request *rq = HWGROUP(drive)->rq;
- DRIVER(drive)->end_request(drive, 1, rq->nr_sectors);
+ if (rq->rq_disk) {
+ ide_driver_t *drv;
+
+ drv = *(ide_driver_t **)rq->rq_disk->private_data;;
+ drv->end_request(drive, 1, rq->nr_sectors);
+ } else
+ ide_end_request(drive, 1, rq->nr_sectors);
return ide_stopped;
}
printk(KERN_ERR "%s: dma_intr: bad DMA status (dma_stat=%x)\n",
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index 0e9421b57cc5a7..36c0b74a4e45b6 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -276,6 +276,8 @@ typedef struct {
*/
typedef struct ide_floppy_obj {
ide_drive_t *drive;
+ ide_driver_t *driver;
+ struct gendisk *disk;
struct kref kref;
/* Current packet command */
@@ -519,7 +521,8 @@ static DECLARE_MUTEX(idefloppy_ref_sem);
#define to_ide_floppy(obj) container_of(obj, struct ide_floppy_obj, kref)
-#define ide_floppy_g(disk) ((disk)->private_data)
+#define ide_floppy_g(disk) \
+ container_of((disk)->private_data, struct ide_floppy_obj, driver)
static struct ide_floppy_obj *ide_floppy_get(struct gendisk *disk)
{
@@ -680,9 +683,12 @@ static void idefloppy_update_buffers (ide_drive_t *drive, idefloppy_pc_t *pc)
*/
static void idefloppy_queue_pc_head (ide_drive_t *drive,idefloppy_pc_t *pc,struct request *rq)
{
+ struct ide_floppy_obj *floppy = drive->driver_data;
+
ide_init_drive_cmd(rq);
rq->buffer = (char *) pc;
rq->flags = REQ_SPECIAL; //rq->cmd = IDEFLOPPY_PC_RQ;
+ rq->rq_disk = floppy->disk;
(void) ide_do_drive_cmd(drive, rq, ide_preempt);
}
@@ -1274,7 +1280,8 @@ static ide_startstop_t idefloppy_do_request (ide_drive_t *drive, struct request
unsigned long block = (unsigned long)block_s;
debug_log(KERN_INFO "rq_status: %d, dev: %s, flags: %lx, errors: %d\n",
- rq->rq_status, rq->rq_disk->disk_name,
+ rq->rq_status,
+ rq->rq_disk ? rq->rq_disk->disk_name ? "?",
rq->flags, rq->errors);
debug_log(KERN_INFO "sector: %ld, nr_sectors: %ld, "
"current_nr_sectors: %d\n", (long)rq->sector,
@@ -1329,11 +1336,13 @@ static ide_startstop_t idefloppy_do_request (ide_drive_t *drive, struct request
*/
static int idefloppy_queue_pc_tail (ide_drive_t *drive,idefloppy_pc_t *pc)
{
+ struct ide_floppy_obj *floppy = drive->driver_data;
struct request rq;
ide_init_drive_cmd (&rq);
rq.buffer = (char *) pc;
rq.flags = REQ_SPECIAL; // rq.cmd = IDEFLOPPY_PC_RQ;
+ rq.rq_disk = floppy->disk;
return ide_do_drive_cmd(drive, &rq, ide_wait);
}
@@ -1358,7 +1367,7 @@ static int idefloppy_get_flexible_disk_page (ide_drive_t *drive)
}
header = (idefloppy_mode_parameter_header_t *) pc.buffer;
floppy->wp = header->wp;
- set_disk_ro(drive->disk, floppy->wp);
+ set_disk_ro(floppy->disk, floppy->wp);
page = (idefloppy_flexible_disk_page_t *) (header + 1);
page->transfer_rate = ntohs(page->transfer_rate);
@@ -1424,7 +1433,7 @@ static int idefloppy_get_capacity (ide_drive_t *drive)
drive->bios_cyl = 0;
drive->bios_head = drive->bios_sect = 0;
floppy->blocks = floppy->bs_factor = 0;
- set_capacity(drive->disk, 0);
+ set_capacity(floppy->disk, 0);
idefloppy_create_read_capacity_cmd(&pc);
if (idefloppy_queue_pc_tail(drive, &pc)) {
@@ -1498,7 +1507,7 @@ static int idefloppy_get_capacity (ide_drive_t *drive)
(void) idefloppy_get_flexible_disk_page(drive);
}
- set_capacity(drive->disk, floppy->blocks * floppy->bs_factor);
+ set_capacity(floppy->disk, floppy->blocks * floppy->bs_factor);
return rc;
}
@@ -1859,7 +1868,7 @@ static void idefloppy_setup (ide_drive_t *drive, idefloppy_floppy_t *floppy)
static int idefloppy_cleanup (ide_drive_t *drive)
{
idefloppy_floppy_t *floppy = drive->driver_data;
- struct gendisk *g = drive->disk;
+ struct gendisk *g = floppy->disk;
if (ide_unregister_subdriver(drive))
return 1;
@@ -1875,11 +1884,11 @@ static void ide_floppy_release(struct kref *kref)
{
struct ide_floppy_obj *floppy = to_ide_floppy(kref);
ide_drive_t *drive = floppy->drive;
- struct gendisk *g = drive->disk;
+ struct gendisk *g = floppy->disk;
drive->driver_data = NULL;
g->private_data = NULL;
- g->fops = ide_fops;
+ put_disk(g);
kfree(floppy);
}
@@ -2116,7 +2125,8 @@ static struct block_device_operations idefloppy_ops = {
static int idefloppy_attach (ide_drive_t *drive)
{
idefloppy_floppy_t *floppy;
- struct gendisk *g = drive->disk;
+ struct gendisk *g;
+
if (!strstr("ide-floppy", drive->driver_req))
goto failed;
if (!drive->present)
@@ -2135,10 +2145,16 @@ static int idefloppy_attach (ide_drive_t *drive)
printk (KERN_ERR "ide-floppy: %s: Can't allocate a floppy structure\n", drive->name);
goto failed;
}
+
+ g = alloc_disk(1 << PARTN_BITS);
+ if (!g)
+ goto out_free_floppy;
+
+ ide_init_disk(g, drive);
+
if (ide_register_subdriver(drive, &idefloppy_driver)) {
printk (KERN_ERR "ide-floppy: %s: Failed to register the driver with ide.c\n", drive->name);
- kfree (floppy);
- goto failed;
+ goto out_put_disk;
}
memset(floppy, 0, sizeof(*floppy));
@@ -2146,6 +2162,10 @@ static int idefloppy_attach (ide_drive_t *drive)
kref_init(&floppy->kref);
floppy->drive = drive;
+ floppy->driver = &idefloppy_driver;
+ floppy->disk = g;
+
+ g->private_data = &floppy->driver;
drive->driver_data = floppy;
@@ -2157,10 +2177,14 @@ static int idefloppy_attach (ide_drive_t *drive)
strcpy(g->devfs_name, drive->devfs_name);
g->flags = drive->removable ? GENHD_FL_REMOVABLE : 0;
g->fops = &idefloppy_ops;
- g->private_data = floppy;
drive->attach = 1;
add_disk(g);
return 0;
+
+out_put_disk:
+ put_disk(g);
+out_free_floppy:
+ kfree(floppy);
failed:
return 1;
}
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index 65f5267992dc9c..248e3cc8b3527d 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -410,6 +410,17 @@ static void try_to_flush_leftover_data (ide_drive_t *drive)
}
}
+static void ide_kill_rq(ide_drive_t *drive, struct request *rq)
+{
+ if (rq->rq_disk) {
+ ide_driver_t *drv;
+
+ drv = *(ide_driver_t **)rq->rq_disk->private_data;
+ drv->end_request(drive, 0, 0);
+ } else
+ ide_end_request(drive, 0, 0);
+}
+
static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
{
ide_hwif_t *hwif = drive->hwif;
@@ -444,7 +455,7 @@ static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8
hwif->OUTB(WIN_IDLEIMMEDIATE, IDE_COMMAND_REG);
if (rq->errors >= ERROR_MAX || blk_noretry_request(rq))
- drive->driver->end_request(drive, 0, 0);
+ ide_kill_rq(drive, rq);
else {
if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
++rq->errors;
@@ -473,7 +484,7 @@ static ide_startstop_t ide_atapi_error(ide_drive_t *drive, struct request *rq, u
hwif->OUTB(WIN_IDLEIMMEDIATE, IDE_COMMAND_REG);
if (rq->errors >= ERROR_MAX) {
- drive->driver->end_request(drive, 0, 0);
+ ide_kill_rq(drive, rq);
} else {
if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
++rq->errors;
@@ -525,7 +536,13 @@ ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, u8 stat)
return ide_stopped;
}
- return drive->driver->error(drive, rq, stat, err);
+ if (rq->rq_disk) {
+ ide_driver_t *drv;
+
+ drv = *(ide_driver_t **)rq->rq_disk->private_data;
+ return drv->error(drive, rq, stat, err);
+ } else
+ return __ide_error(drive, rq, stat, err);
}
EXPORT_SYMBOL_GPL(ide_error);
@@ -535,7 +552,8 @@ ide_startstop_t __ide_abort(ide_drive_t *drive, struct request *rq)
if (drive->media != ide_disk)
rq->errors |= ERROR_RESET;
- DRIVER(drive)->end_request(drive, 0, 0);
+ ide_kill_rq(drive, rq);
+
return ide_stopped;
}
@@ -569,7 +587,13 @@ ide_startstop_t ide_abort(ide_drive_t *drive, const char *msg)
return ide_stopped;
}
- return drive->driver->abort(drive, rq);
+ if (rq->rq_disk) {
+ ide_driver_t *drv;
+
+ drv = *(ide_driver_t **)rq->rq_disk->private_data;
+ return drv->abort(drive, rq);
+ } else
+ return __ide_abort(drive, rq);
}
/**
@@ -622,7 +646,7 @@ static ide_startstop_t drive_cmd_intr (ide_drive_t *drive)
udelay(100);
}
- if (!OK_STAT(stat, READY_STAT, BAD_STAT) && DRIVER(drive) != NULL)
+ if (!OK_STAT(stat, READY_STAT, BAD_STAT))
return ide_error(drive, "drive_cmd", stat);
/* calls ide_end_drive_cmd */
ide_end_drive_cmd(drive, stat, hwif->INB(IDE_ERROR_REG));
@@ -922,6 +946,8 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
return startstop;
}
if (!drive->special.all) {
+ ide_driver_t *drv;
+
if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK))
return execute_drive_cmd(drive, rq);
else if (rq->flags & REQ_DRIVE_TASKFILE)
@@ -937,11 +963,13 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
ide_complete_pm_request(drive, rq);
return startstop;
}
- return (DRIVER(drive)->do_request(drive, rq, block));
+
+ drv = *(ide_driver_t **)rq->rq_disk->private_data;
+ return drv->do_request(drive, rq, block);
}
return do_special(drive);
kill_rq:
- DRIVER(drive)->end_request(drive, 0, 0);
+ ide_kill_rq(drive, rq);
return ide_stopped;
}
@@ -1616,8 +1644,6 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio
rq->errors = 0;
rq->rq_status = RQ_ACTIVE;
- rq->rq_disk = drive->disk;
-
/*
* we need to hold an extra reference to request for safe inspection
* after completion
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index cb158558d20125..554473a95cf747 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -862,6 +862,13 @@ static void probe_hwif(ide_hwif_t *hwif)
drive->autotune == IDE_TUNE_AUTO)
/* auto-tune PIO mode */
hwif->tuneproc(drive, 255);
+
+ if (drive->autotune != IDE_TUNE_DEFAULT &&
+ drive->autotune != IDE_TUNE_AUTO)
+ continue;
+
+ drive->nice1 = 1;
+
/*
* MAJOR HACK BARF :-/
*
@@ -871,9 +878,7 @@ static void probe_hwif(ide_hwif_t *hwif)
* Move here to prevent module loading clashing.
*/
// drive->autodma = hwif->autodma;
- if ((hwif->ide_dma_check) &&
- ((drive->autotune == IDE_TUNE_DEFAULT) ||
- (drive->autotune == IDE_TUNE_AUTO))) {
+ if (hwif->ide_dma_check) {
/*
* Force DMAing for the beginning of the check.
* Some chipsets appear to do interesting
@@ -1006,10 +1011,8 @@ static int ide_init_queue(ide_drive_t *drive)
blk_queue_max_hw_segments(q, max_sg_entries);
blk_queue_max_phys_segments(q, max_sg_entries);
- /* assign drive and gendisk queue */
+ /* assign drive queue */
drive->queue = q;
- if (drive->disk)
- drive->disk->queue = drive->queue;
/* needs drive->queue to be set */
ide_toggle_bounce(drive, 1);
@@ -1209,8 +1212,6 @@ static int ata_lock(dev_t dev, void *data)
return 0;
}
-extern ide_driver_t idedefault_driver;
-
static struct kobject *ata_probe(dev_t dev, int *part, void *data)
{
ide_hwif_t *hwif = data;
@@ -1218,52 +1219,66 @@ static struct kobject *ata_probe(dev_t dev, int *part, void *data)
ide_drive_t *drive = &hwif->drives[unit];
if (!drive->present)
return NULL;
- if (drive->driver == &idedefault_driver) {
- if (drive->media == ide_disk)
- (void) request_module("ide-disk");
- if (drive->scsi)
- (void) request_module("ide-scsi");
- if (drive->media == ide_cdrom || drive->media == ide_optical)
- (void) request_module("ide-cd");
- if (drive->media == ide_tape)
- (void) request_module("ide-tape");
- if (drive->media == ide_floppy)
- (void) request_module("ide-floppy");
- }
- if (drive->driver == &idedefault_driver)
- return NULL;
+
+ if (drive->media == ide_disk)
+ request_module("ide-disk");
+ if (drive->scsi)
+ request_module("ide-scsi");
+ if (drive->media == ide_cdrom || drive->media == ide_optical)
+ request_module("ide-cd");
+ if (drive->media == ide_tape)
+ request_module("ide-tape");
+ if (drive->media == ide_floppy)
+ request_module("ide-floppy");
+
+ return NULL;
+}
+
+static struct kobject *exact_match(dev_t dev, int *part, void *data)
+{
+ struct gendisk *p = data;
*part &= (1 << PARTN_BITS) - 1;
- return get_disk(drive->disk);
+ return &p->kobj;
}
-static int alloc_disks(ide_hwif_t *hwif)
+static int exact_lock(dev_t dev, void *data)
{
- unsigned int unit;
- struct gendisk *disks[MAX_DRIVES];
+ struct gendisk *p = data;
- for (unit = 0; unit < MAX_DRIVES; unit++) {
- disks[unit] = alloc_disk(1 << PARTN_BITS);
- if (!disks[unit])
- goto Enomem;
- }
- for (unit = 0; unit < MAX_DRIVES; ++unit) {
- ide_drive_t *drive = &hwif->drives[unit];
- struct gendisk *disk = disks[unit];
- disk->major = hwif->major;
- disk->first_minor = unit << PARTN_BITS;
- sprintf(disk->disk_name,"hd%c",'a'+hwif->index*MAX_DRIVES+unit);
- disk->fops = ide_fops;
- disk->private_data = drive;
- drive->disk = disk;
- }
+ if (!get_disk(p))
+ return -1;
return 0;
-Enomem:
- printk(KERN_WARNING "(ide::init_gendisk) Out of memory\n");
- while (unit--)
- put_disk(disks[unit]);
- return -ENOMEM;
}
+void ide_register_region(struct gendisk *disk)
+{
+ blk_register_region(MKDEV(disk->major, disk->first_minor),
+ disk->minors, NULL, exact_match, exact_lock, disk);
+}
+
+EXPORT_SYMBOL_GPL(ide_register_region);
+
+void ide_unregister_region(struct gendisk *disk)
+{
+ blk_unregister_region(MKDEV(disk->major, disk->first_minor),
+ disk->minors);
+}
+
+EXPORT_SYMBOL_GPL(ide_unregister_region);
+
+void ide_init_disk(struct gendisk *disk, ide_drive_t *drive)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ unsigned int unit = (drive->select.all >> 4) & 1;
+
+ disk->major = hwif->major;
+ disk->first_minor = unit << PARTN_BITS;
+ sprintf(disk->disk_name, "hd%c", 'a' + hwif->index * MAX_DRIVES + unit);
+ disk->queue = drive->queue;
+}
+
+EXPORT_SYMBOL_GPL(ide_init_disk);
+
static void drive_release_dev (struct device *dev)
{
ide_drive_t *drive = container_of(dev, ide_drive_t, gendev);
@@ -1304,7 +1319,7 @@ static void init_gendisk (ide_hwif_t *hwif)
static int hwif_init(ide_hwif_t *hwif)
{
- int old_irq, unit;
+ int old_irq;
/* Return success if no device is connected */
if (!hwif->present)
@@ -1340,9 +1355,6 @@ static int hwif_init(ide_hwif_t *hwif)
printk(KERN_ERR "%s: unable to allocate SG table.\n", hwif->name);
goto out;
}
-
- if (alloc_disks(hwif) < 0)
- goto out;
if (init_irq(hwif) == 0)
goto done;
@@ -1355,12 +1367,12 @@ static int hwif_init(ide_hwif_t *hwif)
if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]))) {
printk("%s: Disabled unable to get IRQ %d.\n",
hwif->name, old_irq);
- goto out_disks;
+ goto out;
}
if (init_irq(hwif)) {
printk("%s: probed IRQ %d and default IRQ %d failed.\n",
hwif->name, old_irq, hwif->irq);
- goto out_disks;
+ goto out;
}
printk("%s: probed IRQ %d failed, using default.\n",
hwif->name, hwif->irq);
@@ -1370,12 +1382,6 @@ done:
hwif->present = 1; /* success */
return 1;
-out_disks:
- for (unit = 0; unit < MAX_DRIVES; unit++) {
- struct gendisk *disk = hwif->drives[unit].disk;
- hwif->drives[unit].disk = NULL;
- put_disk(disk);
- }
out:
unregister_blkdev(hwif->major, hwif->name);
return 0;
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index 30e9611fc728de..bdff5ac580531c 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -107,8 +107,6 @@ static int proc_ide_read_identify
if (drive) {
unsigned short *val = (unsigned short *) page;
- BUG_ON(!drive->driver);
-
err = taskfile_lib_get_identify(drive, page);
if (!err) {
char *out = ((char *)page) + (SECTOR_WORDS * 4);
@@ -312,8 +310,11 @@ static int proc_ide_read_driver
ide_driver_t *driver = drive->driver;
int len;
- len = sprintf(page, "%s version %s\n",
- driver->name, driver->version);
+ if (driver) {
+ len = sprintf(page, "%s version %s\n",
+ driver->name, driver->version);
+ } else
+ len = sprintf(page, "ide-default version 0.9.newide\n");
PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
}
@@ -421,10 +422,7 @@ static void create_proc_ide_drives(ide_hwif_t *hwif)
static void destroy_proc_ide_device(ide_hwif_t *hwif, ide_drive_t *drive)
{
- ide_driver_t *driver = drive->driver;
-
if (drive->proc) {
- ide_remove_proc_entries(drive->proc, driver->proc);
ide_remove_proc_entries(drive->proc, generic_drive_entries);
remove_proc_entry(drive->name, proc_ide_root);
remove_proc_entry(drive->name, hwif->proc);
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index 913d762c5220d4..4825448549850d 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -783,6 +783,8 @@ typedef struct {
*/
typedef struct ide_tape_obj {
ide_drive_t *drive;
+ ide_driver_t *driver;
+ struct gendisk *disk;
struct kref kref;
/*
@@ -1013,7 +1015,8 @@ static DECLARE_MUTEX(idetape_ref_sem);
#define to_ide_tape(obj) container_of(obj, struct ide_tape_obj, kref)
-#define ide_tape_g(disk) ((disk)->private_data)
+#define ide_tape_g(disk) \
+ container_of((disk)->private_data, struct ide_tape_obj, driver)
static struct ide_tape_obj *ide_tape_get(struct gendisk *disk)
{
@@ -1543,6 +1546,7 @@ static void idetape_active_next_stage (ide_drive_t *drive)
}
#endif /* IDETAPE_DEBUG_BUGS */
+ rq->rq_disk = tape->disk;
rq->buffer = NULL;
rq->special = (void *)stage->bh;
tape->active_data_request = rq;
@@ -1795,8 +1799,11 @@ static void idetape_init_rq(struct request *rq, u8 cmd)
*/
static void idetape_queue_pc_head (ide_drive_t *drive, idetape_pc_t *pc,struct request *rq)
{
+ struct ide_tape_obj *tape = drive->driver_data;
+
idetape_init_rq(rq, REQ_IDETAPE_PC1);
rq->buffer = (char *) pc;
+ rq->rq_disk = tape->disk;
(void) ide_do_drive_cmd(drive, rq, ide_preempt);
}
@@ -2852,10 +2859,12 @@ static void idetape_create_test_unit_ready_cmd(idetape_pc_t *pc)
*/
static int __idetape_queue_pc_tail (ide_drive_t *drive, idetape_pc_t *pc)
{
+ struct ide_tape_obj *tape = drive->driver_data;
struct request rq;
idetape_init_rq(&rq, REQ_IDETAPE_PC1);
rq.buffer = (char *) pc;
+ rq.rq_disk = tape->disk;
return ide_do_drive_cmd(drive, &rq, ide_wait);
}
@@ -3079,6 +3088,7 @@ static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int blocks, struct
#endif /* IDETAPE_DEBUG_BUGS */
idetape_init_rq(&rq, cmd);
+ rq.rq_disk = tape->disk;
rq.special = (void *)bh;
rq.sector = tape->first_frame_position;
rq.nr_sectors = rq.current_nr_sectors = blocks;
@@ -4687,6 +4697,8 @@ static int idetape_cleanup (ide_drive_t *drive)
DRIVER(drive)->busy = 0;
(void) ide_unregister_subdriver(drive);
+ ide_unregister_region(tape->disk);
+
ide_tape_put(tape);
return 0;
@@ -4696,15 +4708,16 @@ static void ide_tape_release(struct kref *kref)
{
struct ide_tape_obj *tape = to_ide_tape(kref);
ide_drive_t *drive = tape->drive;
- struct gendisk *g = drive->disk;
+ struct gendisk *g = tape->disk;
+ drive->dsc_overlap = 0;
drive->driver_data = NULL;
devfs_remove("%s/mt", drive->devfs_name);
devfs_remove("%s/mtn", drive->devfs_name);
devfs_unregister_tape(g->number);
idetape_devs[tape->minor] = NULL;
g->private_data = NULL;
- g->fops = ide_fops;
+ put_disk(g);
kfree(tape);
}
@@ -4819,7 +4832,7 @@ static struct block_device_operations idetape_block_ops = {
static int idetape_attach (ide_drive_t *drive)
{
idetape_tape_t *tape;
- struct gendisk *g = drive->disk;
+ struct gendisk *g;
int minor;
if (!strstr("ide-tape", drive->driver_req))
@@ -4845,10 +4858,16 @@ static int idetape_attach (ide_drive_t *drive)
printk(KERN_ERR "ide-tape: %s: Can't allocate a tape structure\n", drive->name);
goto failed;
}
+
+ g = alloc_disk(1 << PARTN_BITS);
+ if (!g)
+ goto out_free_tape;
+
+ ide_init_disk(g, drive);
+
if (ide_register_subdriver(drive, &idetape_driver)) {
printk(KERN_ERR "ide-tape: %s: Failed to register the driver with ide.c\n", drive->name);
- kfree(tape);
- goto failed;
+ goto out_put_disk;
}
memset(tape, 0, sizeof(*tape));
@@ -4856,6 +4875,10 @@ static int idetape_attach (ide_drive_t *drive)
kref_init(&tape->kref);
tape->drive = drive;
+ tape->driver = &idetape_driver;
+ tape->disk = g;
+
+ g->private_data = &tape->driver;
drive->driver_data = tape;
@@ -4876,9 +4899,13 @@ static int idetape_attach (ide_drive_t *drive)
g->number = devfs_register_tape(drive->devfs_name);
g->fops = &idetape_block_ops;
- g->private_data = tape;
+ ide_register_region(g);
return 0;
+out_put_disk:
+ put_disk(g);
+out_free_tape:
+ kfree(tape);
failed:
return 1;
}
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index 246a1a1bd46577..d04f62ab5de199 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -354,8 +354,12 @@ static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq,
break;
}
- if (sectors > 0)
- drive->driver->end_request(drive, 1, sectors);
+ if (sectors > 0) {
+ ide_driver_t *drv;
+
+ drv = *(ide_driver_t **)rq->rq_disk->private_data;
+ drv->end_request(drive, 1, sectors);
+ }
}
return ide_error(drive, s, stat);
}
@@ -371,7 +375,8 @@ static void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat)
return;
}
}
- drive->driver->end_request(drive, 1, rq->hard_nr_sectors);
+
+ ide_end_request(drive, 1, rq->hard_nr_sectors);
}
/*
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 20da2d61b200f9..973dec799b5c8b 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -196,7 +196,7 @@ ide_hwif_t ide_hwifs[MAX_HWIFS]; /* master data repository */
EXPORT_SYMBOL(ide_hwifs);
-extern ide_driver_t idedefault_driver;
+static struct list_head ide_drives = LIST_HEAD_INIT(ide_drives);
/*
* Do not even *think* about calling this!
@@ -245,7 +245,6 @@ static void init_hwif_data(ide_hwif_t *hwif, unsigned int index)
drive->max_failures = IDE_DEFAULT_MAX_FAILURES;
drive->using_dma = 0;
drive->is_flash = 0;
- drive->driver = &idedefault_driver;
drive->vdma = 0;
INIT_LIST_HEAD(&drive->list);
sema_init(&drive->gendev_rel_sem, 0);
@@ -359,11 +358,6 @@ static int ide_system_bus_speed(void)
return system_bus_speed;
}
-static int ide_open (struct inode * inode, struct file * filp)
-{
- return -ENXIO;
-}
-
/*
* drives_lock protects the list of drives, drivers_lock the
* list of drivers. Currently nobody takes both at once.
@@ -763,11 +757,6 @@ void ide_unregister(unsigned int index)
* Remove us from the kernel's knowledge
*/
blk_unregister_region(MKDEV(hwif->major, 0), MAX_DRIVES<<PARTN_BITS);
- for (i = 0; i < MAX_DRIVES; i++) {
- struct gendisk *disk = hwif->drives[i].disk;
- hwif->drives[i].disk = NULL;
- put_disk(disk);
- }
kfree(hwif->sg_table);
unregister_blkdev(hwif->major, hwif->name);
spin_lock_irq(&ide_lock);
@@ -931,7 +920,7 @@ EXPORT_SYMBOL(ide_register_hw);
DECLARE_MUTEX(ide_setting_sem);
/**
- * ide_add_setting - add an ide setting option
+ * __ide_add_setting - add an ide setting option
* @drive: drive to use
* @name: setting name
* @rw: true if the function is read write
@@ -944,6 +933,7 @@ DECLARE_MUTEX(ide_setting_sem);
* @div_factor: divison scale
* @data: private data field
* @set: setting
+ * @auto_remove: setting auto removal flag
*
* Removes the setting named from the device if it is present.
* The function takes the settings_lock to protect against
@@ -955,8 +945,8 @@ DECLARE_MUTEX(ide_setting_sem);
* a driver is attached we assume the driver settings are auto
* remove.
*/
-
-int ide_add_setting (ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set)
+
+static int __ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set, int auto_remove)
{
ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL;
@@ -981,7 +971,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 != &idedefault_driver)
+ if (auto_remove)
setting->auto_remove = 1;
*p = setting;
up(&ide_setting_sem);
@@ -993,6 +983,11 @@ abort:
return -1;
}
+int ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set)
+{
+ return __ide_add_setting(drive, name, rw, read_ioctl, write_ioctl, data_type, min, max, mul_factor, div_factor, data, set, 1);
+}
+
EXPORT_SYMBOL(ide_add_setting);
/**
@@ -1282,17 +1277,17 @@ static int set_xfer_rate (ide_drive_t *drive, int arg)
void ide_add_generic_settings (ide_drive_t *drive)
{
/*
- * drive setting name read/write access read ioctl write ioctl data type min max mul_factor div_factor data pointer set function
+ * drive setting name read/write access read ioctl write ioctl data type min max mul_factor div_factor data pointer set function
*/
- ide_add_setting(drive, "io_32bit", drive->no_io_32bit ? SETTING_READ : SETTING_RW, HDIO_GET_32BIT, HDIO_SET_32BIT, TYPE_BYTE, 0, 1 + (SUPPORT_VLB_SYNC << 1), 1, 1, &drive->io_32bit, set_io_32bit);
- ide_add_setting(drive, "keepsettings", SETTING_RW, HDIO_GET_KEEPSETTINGS, HDIO_SET_KEEPSETTINGS, TYPE_BYTE, 0, 1, 1, 1, &drive->keep_settings, NULL);
- ide_add_setting(drive, "nice1", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->nice1, NULL);
- ide_add_setting(drive, "pio_mode", SETTING_WRITE, -1, HDIO_SET_PIO_MODE, TYPE_BYTE, 0, 255, 1, 1, NULL, set_pio_mode);
- ide_add_setting(drive, "unmaskirq", drive->no_unmask ? SETTING_READ : SETTING_RW, HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, NULL);
- ide_add_setting(drive, "using_dma", SETTING_RW, HDIO_GET_DMA, HDIO_SET_DMA, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma);
- ide_add_setting(drive, "init_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 70, 1, 1, &drive->init_speed, NULL);
- ide_add_setting(drive, "current_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 70, 1, 1, &drive->current_speed, set_xfer_rate);
- ide_add_setting(drive, "number", SETTING_RW, -1, -1, TYPE_BYTE, 0, 3, 1, 1, &drive->dn, NULL);
+ __ide_add_setting(drive, "io_32bit", drive->no_io_32bit ? SETTING_READ : SETTING_RW, HDIO_GET_32BIT, HDIO_SET_32BIT, TYPE_BYTE, 0, 1 + (SUPPORT_VLB_SYNC << 1), 1, 1, &drive->io_32bit, set_io_32bit, 0);
+ __ide_add_setting(drive, "keepsettings", SETTING_RW, HDIO_GET_KEEPSETTINGS, HDIO_SET_KEEPSETTINGS, TYPE_BYTE, 0, 1, 1, 1, &drive->keep_settings, NULL, 0);
+ __ide_add_setting(drive, "nice1", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->nice1, NULL, 0);
+ __ide_add_setting(drive, "pio_mode", SETTING_WRITE, -1, HDIO_SET_PIO_MODE, TYPE_BYTE, 0, 255, 1, 1, NULL, set_pio_mode, 0);
+ __ide_add_setting(drive, "unmaskirq", drive->no_unmask ? SETTING_READ : SETTING_RW, HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, NULL, 0);
+ __ide_add_setting(drive, "using_dma", SETTING_RW, HDIO_GET_DMA, HDIO_SET_DMA, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma, 0);
+ __ide_add_setting(drive, "init_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 70, 1, 1, &drive->init_speed, NULL, 0);
+ __ide_add_setting(drive, "current_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 70, 1, 1, &drive->current_speed, set_xfer_rate, 0);
+ __ide_add_setting(drive, "number", SETTING_RW, -1, -1, TYPE_BYTE, 0, 3, 1, 1, &drive->dn, NULL, 0);
}
/**
@@ -1330,7 +1325,7 @@ int ide_replace_subdriver (ide_drive_t *drive, const char *driver)
} else {
drive->driver_req[0] = 0;
}
- if (DRIVER(drive)!= &idedefault_driver && !strcmp(DRIVER(drive)->name, driver))
+ if (drive->driver && !strcmp(drive->driver->name, driver))
return 0;
abort:
return 1;
@@ -1369,9 +1364,9 @@ int ata_attach(ide_drive_t *drive)
spin_lock(&drivers_lock);
module_put(driver->owner);
}
- drive->gendev.driver = &idedefault_driver.gen_driver;
+ drive->gendev.driver = NULL;
spin_unlock(&drivers_lock);
- if(idedefault_driver.attach(drive) != 0)
+ if (ide_register_subdriver(drive, NULL))
panic("ide: default attach failed");
return 1;
}
@@ -1418,6 +1413,7 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
unsigned int cmd, unsigned long arg)
{
ide_settings_t *setting;
+ ide_driver_t *drv;
int err = 0;
void __user *p = (void __user *)arg;
@@ -1517,7 +1513,8 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP) | (1 << IDE_NICE_1))))
return -EPERM;
drive->dsc_overlap = (arg >> IDE_NICE_DSC_OVERLAP) & 1;
- if (drive->dsc_overlap && !DRIVER(drive)->supports_dsc_overlap) {
+ drv = *(ide_driver_t **)bdev->bd_disk->private_data;
+ if (drive->dsc_overlap && !drv->supports_dsc_overlap) {
drive->dsc_overlap = 0;
return -EPERM;
}
@@ -2020,10 +2017,8 @@ int ide_register_subdriver(ide_drive_t *drive, ide_driver_t *driver)
{
unsigned long flags;
- BUG_ON(!drive->driver);
-
spin_lock_irqsave(&ide_lock, flags);
- if (!drive->present || drive->driver != &idedefault_driver ||
+ if (!drive->present || drive->driver != NULL ||
drive->usage || drive->dead) {
spin_unlock_irqrestore(&ide_lock, flags);
return 1;
@@ -2031,17 +2026,11 @@ int ide_register_subdriver(ide_drive_t *drive, ide_driver_t *driver)
drive->driver = driver;
spin_unlock_irqrestore(&ide_lock, flags);
spin_lock(&drives_lock);
- list_add_tail(&drive->list, &driver->drives);
+ list_add_tail(&drive->list, driver ? &driver->drives : &ide_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 */
- drive->dsc_overlap = (drive->next != drive && driver->supports_dsc_overlap);
- drive->nice1 = 1;
- }
#ifdef CONFIG_PROC_FS
- if (drive->driver != &idedefault_driver)
+ if (driver)
ide_add_proc_entries(drive->proc, driver->proc, drive);
#endif
return 0;
@@ -2069,7 +2058,7 @@ int ide_unregister_subdriver (ide_drive_t *drive)
down(&ide_setting_sem);
spin_lock_irqsave(&ide_lock, flags);
- if (drive->usage || drive->driver == &idedefault_driver || DRIVER(drive)->busy) {
+ if (drive->usage || drive->driver == NULL || DRIVER(drive)->busy) {
spin_unlock_irqrestore(&ide_lock, flags);
up(&ide_setting_sem);
return 1;
@@ -2078,13 +2067,13 @@ int ide_unregister_subdriver (ide_drive_t *drive)
ide_remove_proc_entries(drive->proc, DRIVER(drive)->proc);
#endif
auto_remove_settings(drive);
- drive->driver = &idedefault_driver;
+ drive->driver = NULL;
spin_unlock_irqrestore(&ide_lock, flags);
up(&ide_setting_sem);
spin_lock(&drives_lock);
list_del_init(&drive->list);
spin_unlock(&drives_lock);
- /* drive will be added to &idedefault_driver->drives in ata_attach() */
+ /* drive will be added to &ide_drives in ata_attach() */
return 0;
}
@@ -2120,7 +2109,7 @@ int ide_register_driver(ide_driver_t *driver)
INIT_LIST_HEAD(&list);
spin_lock(&drives_lock);
- list_splice_init(&idedefault_driver.drives, &list);
+ list_splice_init(&ide_drives, &list);
spin_unlock(&drives_lock);
list_for_each_safe(list_loop, tmp_storage, &list) {
@@ -2170,13 +2159,6 @@ void ide_unregister_driver(ide_driver_t *driver)
EXPORT_SYMBOL(ide_unregister_driver);
-struct block_device_operations ide_fops[] = {{
- .owner = THIS_MODULE,
- .open = ide_open,
-}};
-
-EXPORT_SYMBOL(ide_fops);
-
/*
* Probe module
*/
diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
index d90f4d2251ab0f..069dbffe211667 100644
--- a/drivers/ide/pci/via82cxxx.c
+++ b/drivers/ide/pci/via82cxxx.c
@@ -332,11 +332,8 @@ static int via_set_drive(ide_drive_t *drive, u8 speed)
struct ide_timing t, p;
unsigned int T, UT;
- if (speed != XFER_PIO_SLOW && speed != drive->current_speed)
- if (ide_config_drive_speed(drive, speed))
- printk(KERN_WARNING "ide%d: Drive %d didn't "
- "accept speed setting. Oh, well.\n",
- drive->dn >> 1, drive->dn & 1);
+ if (speed != XFER_PIO_SLOW)
+ ide_config_drive_speed(drive, speed);
T = 1000000000 / via_clock;
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index 805cccd042b671..2e2486b035dd95 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -98,6 +98,8 @@ typedef struct idescsi_pc_s {
typedef struct ide_scsi_obj {
ide_drive_t *drive;
+ ide_driver_t *driver;
+ struct gendisk *disk;
struct Scsi_Host *host;
idescsi_pc_t *pc; /* Current packet command */
@@ -108,7 +110,8 @@ typedef struct ide_scsi_obj {
static DECLARE_MUTEX(idescsi_ref_sem);
-#define ide_scsi_g(disk) ((disk)->private_data)
+#define ide_scsi_g(disk) \
+ container_of((disk)->private_data, struct ide_scsi_obj, driver)
static struct ide_scsi_obj *ide_scsi_get(struct gendisk *disk)
{
@@ -323,9 +326,12 @@ static int idescsi_check_condition(ide_drive_t *drive, struct request *failed_co
printk ("ide-scsi: %s: queue cmd = ", drive->name);
hexdump(pc->c, 6);
}
+ rq->rq_disk = scsi->disk;
return ide_do_drive_cmd(drive, rq, ide_preempt);
}
+static int idescsi_end_request(ide_drive_t *, int, int);
+
static ide_startstop_t
idescsi_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
{
@@ -334,7 +340,9 @@ idescsi_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
HWIF(drive)->OUTB(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG);
rq->errors++;
- DRIVER(drive)->end_request(drive, 0, 0);
+
+ idescsi_end_request(drive, 0, 0);
+
return ide_stopped;
}
@@ -346,7 +354,9 @@ idescsi_atapi_abort(ide_drive_t *drive, struct request *rq)
((idescsi_pc_t *) rq->special)->scsi_cmd->serial_number);
#endif
rq->errors |= ERROR_MAX;
- DRIVER(drive)->end_request(drive, 0, 0);
+
+ idescsi_end_request(drive, 0, 0);
+
return ide_stopped;
}
@@ -718,17 +728,20 @@ static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi)
static int idescsi_cleanup (ide_drive_t *drive)
{
struct Scsi_Host *scsihost = drive->driver_data;
- struct gendisk *g = drive->disk;
+ struct ide_scsi_obj *scsi = scsihost_to_idescsi(scsihost);
+ struct gendisk *g = scsi->disk;
if (ide_unregister_subdriver(drive))
return 1;
+ ide_unregister_region(g);
+
drive->driver_data = NULL;
g->private_data = NULL;
- g->fops = ide_fops;
+ put_disk(g);
scsi_remove_host(scsihost);
- ide_scsi_put(scsihost_to_idescsi(scsihost));
+ ide_scsi_put(scsi);
return 0;
}
@@ -910,6 +923,7 @@ static int idescsi_queue (struct scsi_cmnd *cmd,
rq->special = (char *) pc;
rq->flags = REQ_SPECIAL;
spin_unlock_irq(host->host_lock);
+ rq->rq_disk = scsi->disk;
(void) ide_do_drive_cmd (drive, rq, ide_end);
spin_lock_irq(host->host_lock);
return 0;
@@ -1085,9 +1099,9 @@ static int idescsi_attach(ide_drive_t *drive)
{
idescsi_scsi_t *idescsi;
struct Scsi_Host *host;
- struct gendisk *g = drive->disk;
+ struct gendisk *g;
static int warned;
- int err;
+ int err = -ENOMEM;
if (!warned && drive->media == ide_cdrom) {
printk(KERN_WARNING "ide-scsi is deprecated for cd burning! Use ide-cd and give dev=/dev/hdX as device\n");
@@ -1100,6 +1114,12 @@ static int idescsi_attach(ide_drive_t *drive)
!(host = scsi_host_alloc(&idescsi_template,sizeof(idescsi_scsi_t))))
return 1;
+ g = alloc_disk(1 << PARTN_BITS);
+ if (!g)
+ goto out_host_put;
+
+ ide_init_disk(g, drive);
+
host->max_id = 1;
#if IDESCSI_DEBUG_LOG
@@ -1114,21 +1134,27 @@ static int idescsi_attach(ide_drive_t *drive)
drive->driver_data = host;
idescsi = scsihost_to_idescsi(host);
idescsi->drive = drive;
+ idescsi->driver = &idescsi_driver;
idescsi->host = host;
+ idescsi->disk = g;
+ g->private_data = &idescsi->driver;
err = ide_register_subdriver(drive, &idescsi_driver);
if (!err) {
idescsi_setup (drive, idescsi);
g->fops = &idescsi_ops;
- g->private_data = idescsi;
+ ide_register_region(g);
err = scsi_add_host(host, &drive->gendev);
if (!err) {
scsi_scan_host(host);
return 0;
}
/* fall through on error */
+ ide_unregister_region(g);
ide_unregister_subdriver(drive);
}
+ put_disk(g);
+out_host_put:
scsi_host_put(host);
return err;
}
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 58d91a9d533256..9cfc0999becba7 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -756,7 +756,6 @@ typedef struct ide_drive_s {
struct list_head list;
struct device gendev;
struct semaphore gendev_rel_sem; /* to deal with device release() */
- struct gendisk *disk;
} ide_drive_t;
#define IDE_CHIPSET_PCI_MASK \
@@ -1327,7 +1326,7 @@ extern irqreturn_t ide_intr(int irq, void *dev_id, struct pt_regs *regs);
extern void do_ide_request(request_queue_t *);
extern void ide_init_subdrivers(void);
-extern struct block_device_operations ide_fops[];
+void ide_init_disk(struct gendisk *, ide_drive_t *);
extern int ata_attach(ide_drive_t *);
@@ -1442,6 +1441,9 @@ extern int ide_hwif_request_regions(ide_hwif_t *hwif);
extern void ide_hwif_release_regions(ide_hwif_t* hwif);
extern void ide_unregister (unsigned int index);
+void ide_register_region(struct gendisk *);
+void ide_unregister_region(struct gendisk *);
+
void ide_undecoded_slave(ide_hwif_t *);
int probe_hwif_init_with_fixup(ide_hwif_t *, void (*)(ide_hwif_t *));