From: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
To: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>,
Stephen Rothwell <sfr@canb.auug.org.au>,
linux-ide@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [git pull] IDE updates part 2
Date: Fri, 2 Jan 2009 17:59:45 +0100 [thread overview]
Message-ID: <200901021759.46260.bzolnier@gmail.com> (raw)
First IDE updates in 2009, this time:
* Fix IDE to not process commands in IRQ-context and than switch the
subsystem to use per-device request queue locks instead of (ab)using
hwgroup locks for this purpose. Besides being obvious IRQ-latency
and scalability improvement this decreases complexity of core code
greatly (~100 LOC of very tricky code gone) and makes maintainance
work much easier.
[ Thanks to Elias Oltmanns for his work on reviewing these changes
and catching some issues early. ]
* Scheduled removal of deprecated ide-scsi device driver.
We've been discouraging using ide-scsi since early 2.5.x days as the
driver contains unfixable problems with error handling and lifetimes
of IDE/SCSI objects. There is now consensus between IDE/SCSI people
that both (recently rewritten) native ide-{cd,gd,tape} drivers from
IDE side and proper ATA-SCSI emulation (libata) from SCSI side offer
a better alternative.
The driver has been officially orphaned for a year and then scheduled
for removal for the last 4 months so this shouldn't come as surprise
(I didn't got a single user complaint about this and ide-scsi has even
been broken by some unrelated kernel changes for few kernel releases
in the past without anybody noticing).
(from FUJITA Tomonori and Borislav Petkov)
* Fix multiple nested big stack usage in ide-floppy.c.
(from Linus himself, testing/merging handled by Borislav)
* Preparations to switch ide-cd device driver to use generic ATAPI code
which will happen in the next IDE updates pull request.
(from Borislav)
* Misc fixups/cleanups.
All above changes have been in linux-next for some time now...
Linus, please pull from:
master.kernel.org:/pub/scm/linux/kernel/git/bart/ide-2.6.git/
to receive the following updates:
Documentation/feature-removal-schedule.txt | 9 -
MAINTAINERS | 5 -
drivers/ide/Kconfig | 18 +-
drivers/ide/Makefile | 2 +-
drivers/ide/ide-atapi.c | 248 +++++----
drivers/ide/ide-cd.c | 99 +---
drivers/ide/ide-cd.h | 12 +-
drivers/ide/ide-floppy.c | 28 +-
drivers/ide/ide-floppy_ioctl.c | 58 +-
drivers/ide/ide-io.c | 282 +++-------
drivers/ide/ide-ioctls.c | 3 +-
drivers/ide/ide-park.c | 13 +-
drivers/ide/ide-probe.c | 223 +++-----
drivers/ide/ide-sysfs.c | 125 ++++
drivers/ide/ide-tape.c | 2 +-
drivers/ide/ide.c | 72 +---
drivers/ide/tx4938ide.c | 11 +-
drivers/ide/tx4939ide.c | 43 +-
drivers/scsi/Kconfig | 8 +-
drivers/scsi/Makefile | 1 -
drivers/scsi/ide-scsi.c | 840 ----------------------------
include/linux/ide.h | 121 +++--
22 files changed, 614 insertions(+), 1609 deletions(-)
create mode 100644 drivers/ide/ide-sysfs.c
delete mode 100644 drivers/scsi/ide-scsi.c
Bartlomiej Zolnierkiewicz (10):
tx493x: fix indentation
ide: remove chipset type fixup from ide_host_register()
ide: small ide_register_port() cleanup
ide: factor out device type classifying from do_identify()
ide: move sysfs support to ide-sysfs.c
ide: don't execute the next queued command from the hard-IRQ context (v2)
ide: remove IDE PM hack from do_ide_request()
ide: remove "paranoia" checks for hwgroup->busy
ide: add ide_[un]lock_hwgroup() helpers
ide: use per-device request queue locks (v2)
Borislav Petkov (20):
ide-cd: move debug defines into header
ide: make IDE_AFLAG_.. numbering continuous again
ide-atapi: add a dev_is_idecd-inline
ide-atapi: combine drive-specific assignments
ide-atapi: setup dma for ide-cd
ide-atapi: accomodate transfer length calculation for ide-cd
ide-atapi: teach ide atapi about drive->waiting_for_dma
ide-cd: move cdrom_timer_expiry to ide-atapi.c
ide-atapi: remove ide-scsi remnants from ide_issue_pc
ide-atapi: remove ide-scsi remnants from ide_transfer_pc()
ide-atapi: remove ide-scsi remnants from ide_pc_intr()
ide: remove the last ide-scsi remnants
ide-atapi: compute cmd_len based on device type in ide_transfer_pc
ide-atapi: assign expiry and timeout based on device type
ide-atapi: split drive-specific functionality in ide_issue_pc
ide-cd: remove xferlen arg to cdrom_start_packet_command
ide-cd: remove handler wrappers
ide-atapi: remove timeout arg to ide_issue_pc
ide-atapi: put the rest of non-ide-cd code into the else-clause of ide_transfer_pc
ide-atapi: start dma in a drive-specific way
FUJITA Tomonori (1):
remove ide-scsi
Linus Torvalds (1):
ide-floppy: allocate only toplevel packet commands
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index dc7c681..df18d87 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -310,15 +310,6 @@ Who: Krzysztof Piotr Oledzki <ole@ans.pl>
---------------------------
-What: ide-scsi (BLK_DEV_IDESCSI)
-When: 2.6.29
-Why: The 2.6 kernel supports direct writing to ide CD drives, which
- eliminates the need for ide-scsi. The new method is more
- efficient in every way.
-Who: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-
----------------------------
-
What: i2c_attach_client(), i2c_detach_client(), i2c_driver->detach_client()
When: 2.6.29 (ideally) or 2.6.30 (more likely)
Why: Deprecated by the new (standard) device driver binding model. Use
diff --git a/MAINTAINERS b/MAINTAINERS
index ceb32ee..144766c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2146,11 +2146,6 @@ M: Gadi Oxman <gadio@netvision.net.il>
L: linux-kernel@vger.kernel.org
S: Maintained
-IDE-SCSI DRIVER
-L: linux-ide@vger.kernel.org
-L: linux-scsi@vger.kernel.org
-S: Orphan
-
IDLE-I7300
P: Andy Henroid
M: andrew.d.henroid@intel.com
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index c9f21e3..4ee85fc 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -137,6 +137,7 @@ config BLK_DEV_DELKIN
config BLK_DEV_IDECD
tristate "Include IDE/ATAPI CDROM support"
+ select IDE_ATAPI
---help---
If you have a CD-ROM drive using the ATAPI protocol, say Y. ATAPI is
a newer protocol used by IDE CD-ROM and TAPE drives, similar to the
@@ -185,23 +186,6 @@ config BLK_DEV_IDETAPE
To compile this driver as a module, choose M here: the
module will be called ide-tape.
-config BLK_DEV_IDESCSI
- tristate "SCSI emulation support (DEPRECATED)"
- depends on SCSI
- select IDE_ATAPI
- ---help---
- WARNING: ide-scsi is no longer needed for cd writing applications!
- The 2.6 kernel supports direct writing to ide-cd, which eliminates
- the need for ide-scsi + the entire scsi stack just for writing a
- cd. The new method is more efficient in every way.
-
- This will provide SCSI host adapter emulation for IDE ATAPI devices,
- and will allow you to use a SCSI device driver instead of a native
- ATAPI driver.
-
- If both this SCSI emulation and native ATAPI support are compiled
- into the kernel, the native support will be used.
-
config BLK_DEV_IDEACPI
bool "IDE ACPI support"
depends on ACPI
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile
index 177e3f8..4107289 100644
--- a/drivers/ide/Makefile
+++ b/drivers/ide/Makefile
@@ -5,7 +5,7 @@
EXTRA_CFLAGS += -Idrivers/ide
ide-core-y += ide.o ide-ioctls.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \
- ide-taskfile.o ide-pm.o ide-park.o ide-pio-blacklist.o
+ ide-taskfile.o ide-pm.o ide-park.o ide-pio-blacklist.o ide-sysfs.o
# core IDE code
ide-core-$(CONFIG_IDE_TIMINGS) += ide-timings.o
diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c
index 4e58b9e..e8688c0 100644
--- a/drivers/ide/ide-atapi.c
+++ b/drivers/ide/ide-atapi.c
@@ -3,6 +3,7 @@
*/
#include <linux/kernel.h>
+#include <linux/cdrom.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <scsi/scsi.h>
@@ -14,6 +15,13 @@
#define debug_log(fmt, args...) do {} while (0)
#endif
+#define ATAPI_MIN_CDB_BYTES 12
+
+static inline int dev_is_idecd(ide_drive_t *drive)
+{
+ return drive->media == ide_cdrom || drive->media == ide_optical;
+}
+
/*
* Check whether we can support a device,
* based on the ATAPI IDENTIFY command results.
@@ -233,18 +241,49 @@ void ide_retry_pc(ide_drive_t *drive, struct gendisk *disk)
}
EXPORT_SYMBOL_GPL(ide_retry_pc);
-int ide_scsi_expiry(ide_drive_t *drive)
+int ide_cd_expiry(ide_drive_t *drive)
{
- struct ide_atapi_pc *pc = drive->pc;
+ struct request *rq = HWGROUP(drive)->rq;
+ unsigned long wait = 0;
- debug_log("%s called for %lu at %lu\n", __func__,
- pc->scsi_cmd->serial_number, jiffies);
+ debug_log("%s: rq->cmd[0]: 0x%x\n", __func__, rq->cmd[0]);
- pc->flags |= PC_FLAG_TIMEDOUT;
+ /*
+ * Some commands are *slow* and normally take a long time to complete.
+ * Usually we can use the ATAPI "disconnect" to bypass this, but not all
+ * commands/drives support that. Let ide_timer_expiry keep polling us
+ * for these.
+ */
+ switch (rq->cmd[0]) {
+ case GPCMD_BLANK:
+ case GPCMD_FORMAT_UNIT:
+ case GPCMD_RESERVE_RZONE_TRACK:
+ case GPCMD_CLOSE_TRACK:
+ case GPCMD_FLUSH_CACHE:
+ wait = ATAPI_WAIT_PC;
+ break;
+ default:
+ if (!(rq->cmd_flags & REQ_QUIET))
+ printk(KERN_INFO "cmd 0x%x timed out\n",
+ rq->cmd[0]);
+ wait = 0;
+ break;
+ }
+ return wait;
+}
+EXPORT_SYMBOL_GPL(ide_cd_expiry);
- return 0; /* we do not want the IDE subsystem to retry */
+int ide_cd_get_xferlen(struct request *rq)
+{
+ if (blk_fs_request(rq))
+ return 32768;
+ else if (blk_sense_request(rq) || blk_pc_request(rq) ||
+ rq->cmd_type == REQ_TYPE_ATA_PC)
+ return rq->data_len;
+ else
+ return 0;
}
-EXPORT_SYMBOL_GPL(ide_scsi_expiry);
+EXPORT_SYMBOL_GPL(ide_cd_get_xferlen);
/*
* This is the usual interrupt handler which will be called during a packet
@@ -258,21 +297,14 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
struct request *rq = hwif->hwgroup->rq;
const struct ide_tp_ops *tp_ops = hwif->tp_ops;
xfer_func_t *xferfunc;
- ide_expiry_t *expiry;
unsigned int timeout, temp;
u16 bcount;
- u8 stat, ireason, scsi = !!(drive->dev_flags & IDE_DFLAG_SCSI), dsc = 0;
+ u8 stat, ireason, dsc = 0;
debug_log("Enter %s - interrupt handler\n", __func__);
- if (scsi) {
- timeout = ide_scsi_get_timeout(pc);
- expiry = ide_scsi_expiry;
- } else {
- timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD
- : WAIT_TAPE_CMD;
- expiry = NULL;
- }
+ timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD
+ : WAIT_TAPE_CMD;
if (pc->flags & PC_FLAG_TIMEDOUT) {
drive->pc_callback(drive, 0);
@@ -284,8 +316,8 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
if (hwif->dma_ops->dma_end(drive) ||
- (drive->media == ide_tape && !scsi && (stat & ATA_ERR))) {
- if (drive->media == ide_floppy && !scsi)
+ (drive->media == ide_tape && (stat & ATA_ERR))) {
+ if (drive->media == ide_floppy)
printk(KERN_ERR "%s: DMA %s error\n",
drive->name, rq_data_dir(pc->rq)
? "write" : "read");
@@ -307,7 +339,7 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
local_irq_enable_in_hardirq();
- if (drive->media == ide_tape && !scsi &&
+ if (drive->media == ide_tape &&
(stat & ATA_ERR) && rq->cmd[0] == REQUEST_SENSE)
stat &= ~ATA_ERR;
@@ -315,11 +347,8 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
/* Error detected */
debug_log("%s: I/O error\n", drive->name);
- if (drive->media != ide_tape || scsi) {
+ if (drive->media != ide_tape)
pc->rq->errors++;
- if (scsi)
- goto cmd_finished;
- }
if (rq->cmd[0] == REQUEST_SENSE) {
printk(KERN_ERR "%s: I/O error in request sense"
@@ -335,7 +364,6 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
/* queued, but not started */
return ide_stopped;
}
-cmd_finished:
pc->error = 0;
if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) && (stat & ATA_DSC) == 0)
@@ -382,25 +410,8 @@ cmd_finished:
"us more data than expected - "
"discarding data\n",
drive->name);
- if (scsi)
- temp = pc->buf_size - pc->xferred;
- else
- temp = 0;
- if (temp) {
- if (pc->sg)
- drive->pc_io_buffers(drive, pc,
- temp, 0);
- else
- tp_ops->input_data(drive, NULL,
- pc->cur_pos, temp);
- printk(KERN_ERR "%s: transferred %d of "
- "%d bytes\n",
- drive->name,
- temp, bcount);
- }
- pc->xferred += temp;
- pc->cur_pos += temp;
- ide_pad_transfer(drive, 0, bcount - temp);
+
+ ide_pad_transfer(drive, 0, bcount);
goto next_irq;
}
debug_log("The device wants to send us more data than "
@@ -410,14 +421,13 @@ cmd_finished:
} else
xferfunc = tp_ops->output_data;
- if ((drive->media == ide_floppy && !scsi && !pc->buf) ||
- (drive->media == ide_tape && !scsi && pc->bh) ||
- (scsi && pc->sg)) {
+ if ((drive->media == ide_floppy && !pc->buf) ||
+ (drive->media == ide_tape && pc->bh)) {
int done = drive->pc_io_buffers(drive, pc, bcount,
!!(pc->flags & PC_FLAG_WRITING));
/* FIXME: don't do partial completions */
- if (drive->media == ide_floppy && !scsi)
+ if (drive->media == ide_floppy)
ide_end_request(drive, 1, done >> 9);
} else
xferfunc(drive, NULL, pc->cur_pos, bcount);
@@ -430,7 +440,7 @@ cmd_finished:
rq->cmd[0], bcount);
next_irq:
/* And set the interrupt handler again */
- ide_set_handler(drive, ide_pc_intr, timeout, expiry);
+ ide_set_handler(drive, ide_pc_intr, timeout, NULL);
return ide_started;
}
@@ -479,11 +489,12 @@ static int ide_delayed_transfer_pc(ide_drive_t *drive)
static ide_startstop_t ide_transfer_pc(ide_drive_t *drive)
{
- struct ide_atapi_pc *pc = drive->pc;
+ struct ide_atapi_pc *uninitialized_var(pc);
ide_hwif_t *hwif = drive->hwif;
struct request *rq = hwif->hwgroup->rq;
ide_expiry_t *expiry;
unsigned int timeout;
+ int cmd_len;
ide_startstop_t startstop;
u8 ireason;
@@ -493,101 +504,124 @@ static ide_startstop_t ide_transfer_pc(ide_drive_t *drive)
return startstop;
}
- ireason = ide_read_ireason(drive);
- if (drive->media == ide_tape &&
- (drive->dev_flags & IDE_DFLAG_SCSI) == 0)
- ireason = ide_wait_ireason(drive, ireason);
-
- if ((ireason & ATAPI_COD) == 0 || (ireason & ATAPI_IO)) {
- printk(KERN_ERR "%s: (IO,CoD) != (0,1) while issuing "
- "a packet command\n", drive->name);
- return ide_do_reset(drive);
+ if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
+ if (drive->dma)
+ drive->waiting_for_dma = 1;
}
- /*
- * If necessary schedule the packet transfer to occur 'timeout'
- * miliseconds later in ide_delayed_transfer_pc() after the device
- * says it's ready for a packet.
- */
- if (drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) {
- timeout = drive->pc_delay;
- expiry = &ide_delayed_transfer_pc;
+ if (dev_is_idecd(drive)) {
+ /* ATAPI commands get padded out to 12 bytes minimum */
+ cmd_len = COMMAND_SIZE(rq->cmd[0]);
+ if (cmd_len < ATAPI_MIN_CDB_BYTES)
+ cmd_len = ATAPI_MIN_CDB_BYTES;
+
+ timeout = rq->timeout;
+ expiry = ide_cd_expiry;
} else {
- if (drive->dev_flags & IDE_DFLAG_SCSI) {
- timeout = ide_scsi_get_timeout(pc);
- expiry = ide_scsi_expiry;
+ pc = drive->pc;
+
+ cmd_len = ATAPI_MIN_CDB_BYTES;
+
+ /*
+ * If necessary schedule the packet transfer to occur 'timeout'
+ * miliseconds later in ide_delayed_transfer_pc() after the
+ * device says it's ready for a packet.
+ */
+ if (drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) {
+ timeout = drive->pc_delay;
+ expiry = &ide_delayed_transfer_pc;
} else {
timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD
: WAIT_TAPE_CMD;
expiry = NULL;
}
+
+ ireason = ide_read_ireason(drive);
+ if (drive->media == ide_tape)
+ ireason = ide_wait_ireason(drive, ireason);
+
+ if ((ireason & ATAPI_COD) == 0 || (ireason & ATAPI_IO)) {
+ printk(KERN_ERR "%s: (IO,CoD) != (0,1) while issuing "
+ "a packet command\n", drive->name);
+
+ return ide_do_reset(drive);
+ }
}
/* Set the interrupt routine */
ide_set_handler(drive, ide_pc_intr, timeout, expiry);
/* Begin DMA, if necessary */
- if (pc->flags & PC_FLAG_DMA_OK) {
- pc->flags |= PC_FLAG_DMA_IN_PROGRESS;
- hwif->dma_ops->dma_start(drive);
+ if (dev_is_idecd(drive)) {
+ if (drive->dma)
+ hwif->dma_ops->dma_start(drive);
+ } else {
+ if (pc->flags & PC_FLAG_DMA_OK) {
+ pc->flags |= PC_FLAG_DMA_IN_PROGRESS;
+ hwif->dma_ops->dma_start(drive);
+ }
}
/* Send the actual packet */
if ((drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) == 0)
- hwif->tp_ops->output_data(drive, NULL, rq->cmd, 12);
+ hwif->tp_ops->output_data(drive, NULL, rq->cmd, cmd_len);
return ide_started;
}
-ide_startstop_t ide_issue_pc(ide_drive_t *drive, unsigned int timeout,
- ide_expiry_t *expiry)
+ide_startstop_t ide_issue_pc(ide_drive_t *drive)
{
- struct ide_atapi_pc *pc = drive->pc;
+ struct ide_atapi_pc *pc;
ide_hwif_t *hwif = drive->hwif;
+ ide_expiry_t *expiry = NULL;
+ unsigned int timeout;
u32 tf_flags;
u16 bcount;
- u8 scsi = !!(drive->dev_flags & IDE_DFLAG_SCSI);
- /* We haven't transferred any data yet */
- pc->xferred = 0;
- pc->cur_pos = pc->buf;
+ if (dev_is_idecd(drive)) {
+ tf_flags = IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL;
+ bcount = ide_cd_get_xferlen(hwif->hwgroup->rq);
+ expiry = ide_cd_expiry;
+ timeout = ATAPI_WAIT_PC;
- /* Request to transfer the entire buffer at once */
- if (drive->media == ide_tape && scsi == 0)
- bcount = pc->req_xfer;
- else
- bcount = min(pc->req_xfer, 63 * 1024);
+ if (drive->dma)
+ drive->dma = !hwif->dma_ops->dma_setup(drive);
+ } else {
+ pc = drive->pc;
- if (pc->flags & PC_FLAG_DMA_ERROR) {
- pc->flags &= ~PC_FLAG_DMA_ERROR;
- ide_dma_off(drive);
- }
+ /* We haven't transferred any data yet */
+ pc->xferred = 0;
+ pc->cur_pos = pc->buf;
- if ((pc->flags & PC_FLAG_DMA_OK) &&
- (drive->dev_flags & IDE_DFLAG_USING_DMA)) {
- if (scsi)
- hwif->sg_mapped = 1;
- drive->dma = !hwif->dma_ops->dma_setup(drive);
- if (scsi)
- hwif->sg_mapped = 0;
- }
+ tf_flags = IDE_TFLAG_OUT_DEVICE;
+ bcount = ((drive->media == ide_tape) ?
+ pc->req_xfer :
+ min(pc->req_xfer, 63 * 1024));
- if (!drive->dma)
- pc->flags &= ~PC_FLAG_DMA_OK;
+ if (pc->flags & PC_FLAG_DMA_ERROR) {
+ pc->flags &= ~PC_FLAG_DMA_ERROR;
+ ide_dma_off(drive);
+ }
- if (scsi)
- tf_flags = 0;
- else if (drive->media == ide_cdrom || drive->media == ide_optical)
- tf_flags = IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL;
- else
- tf_flags = IDE_TFLAG_OUT_DEVICE;
+ if ((pc->flags & PC_FLAG_DMA_OK) &&
+ (drive->dev_flags & IDE_DFLAG_USING_DMA))
+ drive->dma = !hwif->dma_ops->dma_setup(drive);
+
+ if (!drive->dma)
+ pc->flags &= ~PC_FLAG_DMA_OK;
+
+ timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD
+ : WAIT_TAPE_CMD;
+ }
ide_pktcmd_tf_load(drive, tf_flags, bcount, drive->dma);
/* Issue the packet command */
if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
+ if (drive->dma)
+ drive->waiting_for_dma = 0;
ide_execute_command(drive, ATA_CMD_PACKET, ide_transfer_pc,
- timeout, NULL);
+ timeout, expiry);
return ide_started;
} else {
ide_execute_pkt_cmd(drive);
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 5daa4dd..1a7410f 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -53,14 +53,6 @@
#include "ide-cd.h"
-#define IDECD_DEBUG_LOG 1
-
-#if IDECD_DEBUG_LOG
-#define ide_debug_log(lvl, fmt, args...) __ide_debug_log(lvl, fmt, args)
-#else
-#define ide_debug_log(lvl, fmt, args...) do {} while (0)
-#endif
-
static DEFINE_MUTEX(idecd_ref_mutex);
static void ide_cd_release(struct kref *);
@@ -519,37 +511,8 @@ end_request:
return 1;
}
-static int cdrom_timer_expiry(ide_drive_t *drive)
-{
- struct request *rq = HWGROUP(drive)->rq;
- unsigned long wait = 0;
-
- ide_debug_log(IDE_DBG_RQ, "Call %s: rq->cmd[0]: 0x%x\n", __func__,
- rq->cmd[0]);
-
- /*
- * Some commands are *slow* and normally take a long time to complete.
- * Usually we can use the ATAPI "disconnect" to bypass this, but not all
- * commands/drives support that. Let ide_timer_expiry keep polling us
- * for these.
- */
- switch (rq->cmd[0]) {
- case GPCMD_BLANK:
- case GPCMD_FORMAT_UNIT:
- case GPCMD_RESERVE_RZONE_TRACK:
- case GPCMD_CLOSE_TRACK:
- case GPCMD_FLUSH_CACHE:
- wait = ATAPI_WAIT_PC;
- break;
- default:
- if (!(rq->cmd_flags & REQ_QUIET))
- printk(KERN_INFO PFX "cmd 0x%x timed out\n",
- rq->cmd[0]);
- wait = 0;
- break;
- }
- return wait;
-}
+static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *);
+static ide_startstop_t cdrom_newpc_intr(ide_drive_t *);
/*
* Set up the device registers for transferring a packet command on DEV,
@@ -559,11 +522,13 @@ static int cdrom_timer_expiry(ide_drive_t *drive)
* called when the interrupt from the drive arrives. Otherwise, HANDLER
* will be called immediately after the drive is prepared for the transfer.
*/
-static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
- int xferlen,
- ide_handler_t *handler)
+static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
+ struct request *rq = hwif->hwgroup->rq;
+ int xferlen;
+
+ xferlen = ide_cd_get_xferlen(rq);
ide_debug_log(IDE_DBG_PC, "Call %s, xferlen: %d\n", __func__, xferlen);
@@ -581,13 +546,14 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
drive->waiting_for_dma = 0;
/* packet command */
- ide_execute_command(drive, ATA_CMD_PACKET, handler,
- ATAPI_WAIT_PC, cdrom_timer_expiry);
+ ide_execute_command(drive, ATA_CMD_PACKET,
+ cdrom_transfer_packet_command,
+ ATAPI_WAIT_PC, ide_cd_expiry);
return ide_started;
} else {
ide_execute_pkt_cmd(drive);
- return (*handler) (drive);
+ return cdrom_transfer_packet_command(drive);
}
}
@@ -598,11 +564,10 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
* there's data ready.
*/
#define ATAPI_MIN_CDB_BYTES 12
-static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive,
- struct request *rq,
- ide_handler_t *handler)
+static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
+ struct request *rq = hwif->hwgroup->rq;
int cmd_len;
ide_startstop_t startstop;
@@ -629,7 +594,7 @@ static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive,
}
/* arm the interrupt handler */
- ide_set_handler(drive, handler, rq->timeout, cdrom_timer_expiry);
+ ide_set_handler(drive, cdrom_newpc_intr, rq->timeout, ide_cd_expiry);
/* ATAPI commands get padded out to 12 bytes minimum */
cmd_len = COMMAND_SIZE(rq->cmd[0]);
@@ -717,8 +682,6 @@ static int ide_cd_check_transfer_size(ide_drive_t *drive, int len)
return 1;
}
-static ide_startstop_t cdrom_newpc_intr(ide_drive_t *);
-
static ide_startstop_t ide_cd_prepare_rw_request(ide_drive_t *drive,
struct request *rq)
{
@@ -761,20 +724,6 @@ static ide_startstop_t ide_cd_prepare_rw_request(ide_drive_t *drive,
}
/*
- * Routine to send a read/write packet command to the drive. This is usually
- * called directly from cdrom_start_{read,write}(). However, for drq_interrupt
- * devices, it is called from an interrupt when the drive is ready to accept
- * the command.
- */
-static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive)
-{
- struct request *rq = drive->hwif->hwgroup->rq;
-
- /* send the command to the drive and return */
- return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr);
-}
-
-/*
* Fix up a possibly partially-processed request so that we can start it over
* entirely, or even put it back on the request queue.
*/
@@ -1096,7 +1045,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
} else {
timeout = ATAPI_WAIT_PC;
if (!blk_fs_request(rq))
- expiry = cdrom_timer_expiry;
+ expiry = ide_cd_expiry;
}
ide_set_handler(drive, cdrom_newpc_intr, timeout, expiry);
@@ -1163,13 +1112,6 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
return ide_started;
}
-static ide_startstop_t cdrom_do_newpc_cont(ide_drive_t *drive)
-{
- struct request *rq = HWGROUP(drive)->rq;
-
- return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr);
-}
-
static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
{
@@ -1214,18 +1156,12 @@ static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
sector_t block)
{
- ide_handler_t *fn;
- int xferlen;
-
ide_debug_log(IDE_DBG_RQ, "Call %s, rq->cmd[0]: 0x%x, "
"rq->cmd_type: 0x%x, block: %llu\n",
__func__, rq->cmd[0], rq->cmd_type,
(unsigned long long)block);
if (blk_fs_request(rq)) {
- xferlen = 32768;
- fn = cdrom_start_rw_cont;
-
if (cdrom_start_rw(drive, rq) == ide_stopped)
return ide_stopped;
@@ -1233,9 +1169,6 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
return ide_stopped;
} else if (blk_sense_request(rq) || blk_pc_request(rq) ||
rq->cmd_type == REQ_TYPE_ATA_PC) {
- xferlen = rq->data_len;
- fn = cdrom_do_newpc_cont;
-
if (!rq->timeout)
rq->timeout = ATAPI_WAIT_PC;
@@ -1250,7 +1183,7 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
return ide_stopped;
}
- return cdrom_start_packet_command(drive, xferlen, fn);
+ return cdrom_start_packet_command(drive);
}
/*
diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h
index d5ce336..bf676b2 100644
--- a/drivers/ide/ide-cd.h
+++ b/drivers/ide/ide-cd.h
@@ -8,10 +8,14 @@
#include <linux/cdrom.h>
#include <asm/byteorder.h>
-/*
- * typical timeout for packet command
- */
-#define ATAPI_WAIT_PC (60 * HZ)
+#define IDECD_DEBUG_LOG 0
+
+#if IDECD_DEBUG_LOG
+#define ide_debug_log(lvl, fmt, args...) __ide_debug_log(lvl, fmt, args)
+#else
+#define ide_debug_log(lvl, fmt, args...) do {} while (0)
+#endif
+
#define ATAPI_WAIT_WRITE_BUSY (10 * HZ)
/************************************************************************/
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index aeb1ad7..0a48e2d 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -197,7 +197,7 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
pc->retries++;
- return ide_issue_pc(drive, WAIT_FLOPPY_CMD, NULL);
+ return ide_issue_pc(drive);
}
void ide_floppy_create_read_capacity_cmd(struct ide_atapi_pc *pc)
@@ -342,38 +342,38 @@ static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive,
* Look at the flexible disk page parameters. We ignore the CHS capacity
* parameters and use the LBA parameters instead.
*/
-static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive)
+static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive,
+ struct ide_atapi_pc *pc)
{
struct ide_disk_obj *floppy = drive->driver_data;
struct gendisk *disk = floppy->disk;
- struct ide_atapi_pc pc;
u8 *page;
int capacity, lba_capacity;
u16 transfer_rate, sector_size, cyls, rpm;
u8 heads, sectors;
- ide_floppy_create_mode_sense_cmd(&pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE);
+ ide_floppy_create_mode_sense_cmd(pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE);
- if (ide_queue_pc_tail(drive, disk, &pc)) {
+ if (ide_queue_pc_tail(drive, disk, pc)) {
printk(KERN_ERR PFX "Can't get flexible disk page params\n");
return 1;
}
- if (pc.buf[3] & 0x80)
+ if (pc->buf[3] & 0x80)
drive->dev_flags |= IDE_DFLAG_WP;
else
drive->dev_flags &= ~IDE_DFLAG_WP;
set_disk_ro(disk, !!(drive->dev_flags & IDE_DFLAG_WP));
- page = &pc.buf[8];
+ page = &pc->buf[8];
- transfer_rate = be16_to_cpup((__be16 *)&pc.buf[8 + 2]);
- sector_size = be16_to_cpup((__be16 *)&pc.buf[8 + 6]);
- cyls = be16_to_cpup((__be16 *)&pc.buf[8 + 8]);
- rpm = be16_to_cpup((__be16 *)&pc.buf[8 + 28]);
- heads = pc.buf[8 + 4];
- sectors = pc.buf[8 + 5];
+ transfer_rate = be16_to_cpup((__be16 *)&pc->buf[8 + 2]);
+ sector_size = be16_to_cpup((__be16 *)&pc->buf[8 + 6]);
+ cyls = be16_to_cpup((__be16 *)&pc->buf[8 + 8]);
+ rpm = be16_to_cpup((__be16 *)&pc->buf[8 + 28]);
+ heads = pc->buf[8 + 4];
+ sectors = pc->buf[8 + 5];
capacity = cyls * heads * sectors * sector_size;
@@ -499,7 +499,7 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
/* Clik! disk does not support get_flexible_disk_page */
if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE))
- (void) ide_floppy_get_flexible_disk_page(drive);
+ (void) ide_floppy_get_flexible_disk_page(drive, &pc);
return rc;
}
diff --git a/drivers/ide/ide-floppy_ioctl.c b/drivers/ide/ide-floppy_ioctl.c
index 2bc51ff..8f8be85 100644
--- a/drivers/ide/ide-floppy_ioctl.c
+++ b/drivers/ide/ide-floppy_ioctl.c
@@ -31,10 +31,11 @@
* On exit we set nformats to the number of records we've actually initialized.
*/
-static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg)
+static int ide_floppy_get_format_capacities(ide_drive_t *drive,
+ struct ide_atapi_pc *pc,
+ int __user *arg)
{
struct ide_disk_obj *floppy = drive->driver_data;
- struct ide_atapi_pc pc;
u8 header_len, desc_cnt;
int i, blocks, length, u_array_size, u_index;
int __user *argp;
@@ -45,13 +46,13 @@ static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg)
if (u_array_size <= 0)
return -EINVAL;
- ide_floppy_create_read_capacity_cmd(&pc);
- if (ide_queue_pc_tail(drive, floppy->disk, &pc)) {
+ ide_floppy_create_read_capacity_cmd(pc);
+ if (ide_queue_pc_tail(drive, floppy->disk, pc)) {
printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n");
return -EIO;
}
- header_len = pc.buf[3];
+ header_len = pc->buf[3];
desc_cnt = header_len / 8; /* capacity descriptor of 8 bytes */
u_index = 0;
@@ -68,8 +69,8 @@ static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg)
if (u_index >= u_array_size)
break; /* User-supplied buffer too small */
- blocks = be32_to_cpup((__be32 *)&pc.buf[desc_start]);
- length = be16_to_cpup((__be16 *)&pc.buf[desc_start + 6]);
+ blocks = be32_to_cpup((__be32 *)&pc->buf[desc_start]);
+ length = be16_to_cpup((__be16 *)&pc->buf[desc_start + 6]);
if (put_user(blocks, argp))
return -EFAULT;
@@ -111,29 +112,28 @@ static void ide_floppy_create_format_unit_cmd(struct ide_atapi_pc *pc, int b,
pc->flags |= PC_FLAG_WRITING;
}
-static int ide_floppy_get_sfrp_bit(ide_drive_t *drive)
+static int ide_floppy_get_sfrp_bit(ide_drive_t *drive, struct ide_atapi_pc *pc)
{
struct ide_disk_obj *floppy = drive->driver_data;
- struct ide_atapi_pc pc;
drive->atapi_flags &= ~IDE_AFLAG_SRFP;
- ide_floppy_create_mode_sense_cmd(&pc, IDEFLOPPY_CAPABILITIES_PAGE);
- pc.flags |= PC_FLAG_SUPPRESS_ERROR;
+ ide_floppy_create_mode_sense_cmd(pc, IDEFLOPPY_CAPABILITIES_PAGE);
+ pc->flags |= PC_FLAG_SUPPRESS_ERROR;
- if (ide_queue_pc_tail(drive, floppy->disk, &pc))
+ if (ide_queue_pc_tail(drive, floppy->disk, pc))
return 1;
- if (pc.buf[8 + 2] & 0x40)
+ if (pc->buf[8 + 2] & 0x40)
drive->atapi_flags |= IDE_AFLAG_SRFP;
return 0;
}
-static int ide_floppy_format_unit(ide_drive_t *drive, int __user *arg)
+static int ide_floppy_format_unit(ide_drive_t *drive, struct ide_atapi_pc *pc,
+ int __user *arg)
{
struct ide_disk_obj *floppy = drive->driver_data;
- struct ide_atapi_pc pc;
int blocks, length, flags, err = 0;
if (floppy->openers > 1) {
@@ -166,10 +166,10 @@ static int ide_floppy_format_unit(ide_drive_t *drive, int __user *arg)
goto out;
}
- (void)ide_floppy_get_sfrp_bit(drive);
- ide_floppy_create_format_unit_cmd(&pc, blocks, length, flags);
+ ide_floppy_get_sfrp_bit(drive, pc);
+ ide_floppy_create_format_unit_cmd(pc, blocks, length, flags);
- if (ide_queue_pc_tail(drive, floppy->disk, &pc))
+ if (ide_queue_pc_tail(drive, floppy->disk, pc))
err = -EIO;
out:
@@ -188,15 +188,16 @@ out:
* the dsc bit, and return either 0 or 65536.
*/
-static int ide_floppy_get_format_progress(ide_drive_t *drive, int __user *arg)
+static int ide_floppy_get_format_progress(ide_drive_t *drive,
+ struct ide_atapi_pc *pc,
+ int __user *arg)
{
struct ide_disk_obj *floppy = drive->driver_data;
- struct ide_atapi_pc pc;
int progress_indication = 0x10000;
if (drive->atapi_flags & IDE_AFLAG_SRFP) {
- ide_create_request_sense_cmd(drive, &pc);
- if (ide_queue_pc_tail(drive, floppy->disk, &pc))
+ ide_create_request_sense_cmd(drive, pc);
+ if (ide_queue_pc_tail(drive, floppy->disk, pc))
return -EIO;
if (floppy->sense_key == 2 &&
@@ -241,20 +242,21 @@ static int ide_floppy_lockdoor(ide_drive_t *drive, struct ide_atapi_pc *pc,
return 0;
}
-static int ide_floppy_format_ioctl(ide_drive_t *drive, fmode_t mode,
- unsigned int cmd, void __user *argp)
+static int ide_floppy_format_ioctl(ide_drive_t *drive, struct ide_atapi_pc *pc,
+ fmode_t mode, unsigned int cmd,
+ void __user *argp)
{
switch (cmd) {
case IDEFLOPPY_IOCTL_FORMAT_SUPPORTED:
return 0;
case IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY:
- return ide_floppy_get_format_capacities(drive, argp);
+ return ide_floppy_get_format_capacities(drive, pc, argp);
case IDEFLOPPY_IOCTL_FORMAT_START:
if (!(mode & FMODE_WRITE))
return -EPERM;
- return ide_floppy_format_unit(drive, (int __user *)argp);
+ return ide_floppy_format_unit(drive, pc, (int __user *)argp);
case IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS:
- return ide_floppy_get_format_progress(drive, argp);
+ return ide_floppy_get_format_progress(drive, pc, argp);
default:
return -ENOTTY;
}
@@ -270,7 +272,7 @@ int ide_floppy_ioctl(ide_drive_t *drive, struct block_device *bdev,
if (cmd == CDROMEJECT || cmd == CDROM_LOCKDOOR)
return ide_floppy_lockdoor(drive, &pc, arg, cmd);
- err = ide_floppy_format_ioctl(drive, mode, cmd, argp);
+ err = ide_floppy_format_ioctl(drive, &pc, mode, cmd, argp);
if (err != -ENOTTY)
return err;
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index ecacc00..1c36a8e 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -426,9 +426,6 @@ void ide_map_sg(ide_drive_t *drive, struct request *rq)
ide_hwif_t *hwif = drive->hwif;
struct scatterlist *sg = hwif->sg_table;
- if (hwif->sg_mapped) /* needed by ide-scsi */
- return;
-
if (rq->cmd_type != REQ_TYPE_ATA_TASKFILE) {
hwif->sg_nents = blk_rq_map_sg(drive->queue, rq, sg);
} else {
@@ -667,85 +664,10 @@ void ide_stall_queue (ide_drive_t *drive, unsigned long timeout)
drive->sleep = timeout + jiffies;
drive->dev_flags |= IDE_DFLAG_SLEEPING;
}
-
EXPORT_SYMBOL(ide_stall_queue);
-#define WAKEUP(drive) ((drive)->service_start + 2 * (drive)->service_time)
-
-/**
- * choose_drive - select a drive to service
- * @hwgroup: hardware group to select on
- *
- * choose_drive() selects the next drive which will be serviced.
- * This is necessary because the IDE layer can't issue commands
- * to both drives on the same cable, unlike SCSI.
- */
-
-static inline ide_drive_t *choose_drive (ide_hwgroup_t *hwgroup)
-{
- ide_drive_t *drive, *best;
-
-repeat:
- best = NULL;
- drive = hwgroup->drive;
-
- /*
- * drive is doing pre-flush, ordered write, post-flush sequence. even
- * though that is 3 requests, it must be seen as a single transaction.
- * we must not preempt this drive until that is complete
- */
- if (blk_queue_flushing(drive->queue)) {
- /*
- * small race where queue could get replugged during
- * the 3-request flush cycle, just yank the plug since
- * we want it to finish asap
- */
- blk_remove_plug(drive->queue);
- return drive;
- }
-
- do {
- u8 dev_s = !!(drive->dev_flags & IDE_DFLAG_SLEEPING);
- u8 best_s = (best && !!(best->dev_flags & IDE_DFLAG_SLEEPING));
-
- if ((dev_s == 0 || time_after_eq(jiffies, drive->sleep)) &&
- !elv_queue_empty(drive->queue)) {
- if (best == NULL ||
- (dev_s && (best_s == 0 || time_before(drive->sleep, best->sleep))) ||
- (best_s == 0 && time_before(WAKEUP(drive), WAKEUP(best)))) {
- if (!blk_queue_plugged(drive->queue))
- best = drive;
- }
- }
- } while ((drive = drive->next) != hwgroup->drive);
-
- if (best && (best->dev_flags & IDE_DFLAG_NICE1) &&
- (best->dev_flags & IDE_DFLAG_SLEEPING) == 0 &&
- best != hwgroup->drive && best->service_time > WAIT_MIN_SLEEP) {
- long t = (signed long)(WAKEUP(best) - jiffies);
- if (t >= WAIT_MIN_SLEEP) {
- /*
- * We *may* have some time to spare, but first let's see if
- * someone can potentially benefit from our nice mood today..
- */
- drive = best->next;
- do {
- if ((drive->dev_flags & IDE_DFLAG_SLEEPING) == 0
- && time_before(jiffies - best->service_time, WAKEUP(drive))
- && time_before(WAKEUP(drive), jiffies + t))
- {
- ide_stall_queue(best, min_t(long, t, 10 * WAIT_MIN_SLEEP));
- goto repeat;
- }
- } while ((drive = drive->next) != best);
- }
- }
- return best;
-}
-
/*
* Issue a new request to a drive from hwgroup
- * Caller must have already done spin_lock_irqsave(&hwgroup->lock, ..);
*
* A hwgroup is a serialized group of IDE interfaces. Usually there is
* exactly one hwif (interface) per hwgroup, but buggy controllers (eg. CMD640)
@@ -757,8 +679,7 @@ repeat:
* possibly along with many other devices. This is especially common in
* PCI-based systems with off-board IDE controller cards.
*
- * The IDE driver uses a per-hwgroup spinlock to protect
- * access to the request queues, and to protect the hwgroup->busy flag.
+ * The IDE driver uses a per-hwgroup lock to protect the hwgroup->busy flag.
*
* The first thread into the driver for a particular hwgroup sets the
* hwgroup->busy flag to indicate that this hwgroup is now active,
@@ -778,69 +699,41 @@ repeat:
* the driver. This makes the driver much more friendlier to shared IRQs
* than previous designs, while remaining 100% (?) SMP safe and capable.
*/
-static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
+void do_ide_request(struct request_queue *q)
{
- ide_drive_t *drive;
- ide_hwif_t *hwif;
+ ide_drive_t *drive = q->queuedata;
+ ide_hwif_t *hwif = drive->hwif;
+ ide_hwgroup_t *hwgroup = hwif->hwgroup;
struct request *rq;
ide_startstop_t startstop;
- int loops = 0;
-
- /* caller must own hwgroup->lock */
- BUG_ON(!irqs_disabled());
-
- while (!hwgroup->busy) {
- hwgroup->busy = 1;
- /* for atari only */
- ide_get_lock(ide_intr, hwgroup);
- drive = choose_drive(hwgroup);
- if (drive == NULL) {
- int sleeping = 0;
- unsigned long sleep = 0; /* shut up, gcc */
- hwgroup->rq = NULL;
- drive = hwgroup->drive;
- do {
- if ((drive->dev_flags & IDE_DFLAG_SLEEPING) &&
- (sleeping == 0 ||
- time_before(drive->sleep, sleep))) {
- sleeping = 1;
- sleep = drive->sleep;
- }
- } while ((drive = drive->next) != hwgroup->drive);
- if (sleeping) {
+
+ /*
+ * drive is doing pre-flush, ordered write, post-flush sequence. even
+ * though that is 3 requests, it must be seen as a single transaction.
+ * we must not preempt this drive until that is complete
+ */
+ if (blk_queue_flushing(q))
/*
- * Take a short snooze, and then wake up this hwgroup again.
- * This gives other hwgroups on the same a chance to
- * play fairly with us, just in case there are big differences
- * in relative throughputs.. don't want to hog the cpu too much.
+ * small race where queue could get replugged during
+ * the 3-request flush cycle, just yank the plug since
+ * we want it to finish asap
*/
- if (time_before(sleep, jiffies + WAIT_MIN_SLEEP))
- sleep = jiffies + WAIT_MIN_SLEEP;
-#if 1
- if (timer_pending(&hwgroup->timer))
- printk(KERN_CRIT "ide_set_handler: timer already active\n");
-#endif
- /* so that ide_timer_expiry knows what to do */
- hwgroup->sleeping = 1;
- hwgroup->req_gen_timer = hwgroup->req_gen;
- mod_timer(&hwgroup->timer, sleep);
- /* we purposely leave hwgroup->busy==1
- * while sleeping */
- } else {
- /* Ugly, but how can we sleep for the lock
- * otherwise? perhaps from tq_disk?
- */
+ blk_remove_plug(q);
- /* for atari only */
- ide_release_lock();
- hwgroup->busy = 0;
- }
+ spin_unlock_irq(q->queue_lock);
+ spin_lock_irq(&hwgroup->lock);
+
+ if (!ide_lock_hwgroup(hwgroup)) {
+repeat:
+ hwgroup->rq = NULL;
- /* no more work for this hwgroup (for now) */
- return;
+ if (drive->dev_flags & IDE_DFLAG_SLEEPING) {
+ if (time_before(drive->sleep, jiffies)) {
+ ide_unlock_hwgroup(hwgroup);
+ goto plug_device;
+ }
}
- again:
- hwif = HWIF(drive);
+
if (hwif != hwgroup->hwif) {
/*
* set nIEN for previous hwif, drives in the
@@ -852,16 +745,20 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
hwgroup->hwif = hwif;
hwgroup->drive = drive;
drive->dev_flags &= ~(IDE_DFLAG_SLEEPING | IDE_DFLAG_PARKED);
- drive->service_start = jiffies;
+ spin_unlock_irq(&hwgroup->lock);
+ spin_lock_irq(q->queue_lock);
/*
* we know that the queue isn't empty, but this can happen
* if the q->prep_rq_fn() decides to kill a request
*/
rq = elv_next_request(drive->queue);
+ spin_unlock_irq(q->queue_lock);
+ spin_lock_irq(&hwgroup->lock);
+
if (!rq) {
- hwgroup->busy = 0;
- break;
+ ide_unlock_hwgroup(hwgroup);
+ goto out;
}
/*
@@ -876,53 +773,36 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
* though. I hope that doesn't happen too much, hopefully not
* unless the subdriver triggers such a thing in its own PM
* state machine.
- *
- * We count how many times we loop here to make sure we service
- * all drives in the hwgroup without looping for ever
*/
if ((drive->dev_flags & IDE_DFLAG_BLOCKED) &&
blk_pm_request(rq) == 0 &&
(rq->cmd_flags & REQ_PREEMPT) == 0) {
- drive = drive->next ? drive->next : hwgroup->drive;
- if (loops++ < 4 && !blk_queue_plugged(drive->queue))
- goto again;
- /* We clear busy, there should be no pending ATA command at this point. */
- hwgroup->busy = 0;
- break;
+ /* there should be no pending command at this point */
+ ide_unlock_hwgroup(hwgroup);
+ goto plug_device;
}
hwgroup->rq = rq;
- /*
- * Some systems have trouble with IDE IRQs arriving while
- * the driver is still setting things up. So, here we disable
- * the IRQ used by this interface while the request is being started.
- * This may look bad at first, but pretty much the same thing
- * happens anyway when any interrupt comes in, IDE or otherwise
- * -- the kernel masks the IRQ while it is being handled.
- */
- if (masked_irq != IDE_NO_IRQ && hwif->irq != masked_irq)
- disable_irq_nosync(hwif->irq);
- spin_unlock(&hwgroup->lock);
- local_irq_enable_in_hardirq();
- /* allow other IRQs while we start this request */
+ spin_unlock_irq(&hwgroup->lock);
startstop = start_request(drive, rq);
spin_lock_irq(&hwgroup->lock);
- if (masked_irq != IDE_NO_IRQ && hwif->irq != masked_irq)
- enable_irq(hwif->irq);
+
if (startstop == ide_stopped)
- hwgroup->busy = 0;
- }
-}
+ goto repeat;
+ } else
+ goto plug_device;
+out:
+ spin_unlock_irq(&hwgroup->lock);
+ spin_lock_irq(q->queue_lock);
+ return;
-/*
- * Passes the stuff to ide_do_request
- */
-void do_ide_request(struct request_queue *q)
-{
- ide_drive_t *drive = q->queuedata;
+plug_device:
+ spin_unlock_irq(&hwgroup->lock);
+ spin_lock_irq(q->queue_lock);
- ide_do_request(HWGROUP(drive), IDE_NO_IRQ);
+ if (!elv_queue_empty(q))
+ blk_plug_device(q);
}
/*
@@ -983,6 +863,17 @@ out:
return ret;
}
+static void ide_plug_device(ide_drive_t *drive)
+{
+ struct request_queue *q = drive->queue;
+ unsigned long flags;
+
+ spin_lock_irqsave(q->queue_lock, flags);
+ if (!elv_queue_empty(q))
+ blk_plug_device(q);
+ spin_unlock_irqrestore(q->queue_lock, flags);
+}
+
/**
* ide_timer_expiry - handle lack of an IDE interrupt
* @data: timer callback magic (hwgroup)
@@ -1000,10 +891,12 @@ out:
void ide_timer_expiry (unsigned long data)
{
ide_hwgroup_t *hwgroup = (ide_hwgroup_t *) data;
+ ide_drive_t *uninitialized_var(drive);
ide_handler_t *handler;
ide_expiry_t *expiry;
unsigned long flags;
unsigned long wait = -1;
+ int plug_device = 0;
spin_lock_irqsave(&hwgroup->lock, flags);
@@ -1015,22 +908,15 @@ void ide_timer_expiry (unsigned long data)
* or we were "sleeping" to give other devices a chance.
* Either way, we don't really want to complain about anything.
*/
- if (hwgroup->sleeping) {
- hwgroup->sleeping = 0;
- hwgroup->busy = 0;
- }
} else {
- ide_drive_t *drive = hwgroup->drive;
+ drive = hwgroup->drive;
if (!drive) {
printk(KERN_ERR "ide_timer_expiry: hwgroup->drive was NULL\n");
hwgroup->handler = NULL;
} else {
ide_hwif_t *hwif;
ide_startstop_t startstop = ide_stopped;
- if (!hwgroup->busy) {
- hwgroup->busy = 1; /* paranoia */
- printk(KERN_ERR "%s: ide_timer_expiry: hwgroup->busy was 0 ??\n", drive->name);
- }
+
if ((expiry = hwgroup->expiry) != NULL) {
/* continue */
if ((wait = expiry(drive)) > 0) {
@@ -1071,15 +957,18 @@ void ide_timer_expiry (unsigned long data)
ide_error(drive, "irq timeout",
hwif->tp_ops->read_status(hwif));
}
- drive->service_time = jiffies - drive->service_start;
spin_lock_irq(&hwgroup->lock);
enable_irq(hwif->irq);
- if (startstop == ide_stopped)
- hwgroup->busy = 0;
+ if (startstop == ide_stopped) {
+ ide_unlock_hwgroup(hwgroup);
+ plug_device = 1;
+ }
}
}
- ide_do_request(hwgroup, IDE_NO_IRQ);
spin_unlock_irqrestore(&hwgroup->lock, flags);
+
+ if (plug_device)
+ ide_plug_device(drive);
}
/**
@@ -1173,10 +1062,11 @@ irqreturn_t ide_intr (int irq, void *dev_id)
unsigned long flags;
ide_hwgroup_t *hwgroup = (ide_hwgroup_t *)dev_id;
ide_hwif_t *hwif = hwgroup->hwif;
- ide_drive_t *drive;
+ ide_drive_t *uninitialized_var(drive);
ide_handler_t *handler;
ide_startstop_t startstop;
irqreturn_t irq_ret = IRQ_NONE;
+ int plug_device = 0;
spin_lock_irqsave(&hwgroup->lock, flags);
@@ -1241,10 +1131,6 @@ irqreturn_t ide_intr (int irq, void *dev_id)
*/
goto out;
- if (!hwgroup->busy) {
- hwgroup->busy = 1; /* paranoia */
- printk(KERN_ERR "%s: ide_intr: hwgroup->busy was 0 ??\n", drive->name);
- }
hwgroup->handler = NULL;
hwgroup->req_gen++;
del_timer(&hwgroup->timer);
@@ -1267,20 +1153,22 @@ irqreturn_t ide_intr (int irq, void *dev_id)
* same irq as is currently being serviced here, and Linux
* won't allow another of the same (on any CPU) until we return.
*/
- drive->service_time = jiffies - drive->service_start;
if (startstop == ide_stopped) {
if (hwgroup->handler == NULL) { /* paranoia */
- hwgroup->busy = 0;
- ide_do_request(hwgroup, hwif->irq);
- } else {
- printk(KERN_ERR "%s: ide_intr: huh? expected NULL handler "
- "on exit\n", drive->name);
- }
+ ide_unlock_hwgroup(hwgroup);
+ plug_device = 1;
+ } else
+ printk(KERN_ERR "%s: %s: huh? expected NULL handler "
+ "on exit\n", __func__, drive->name);
}
out_handled:
irq_ret = IRQ_HANDLED;
out:
spin_unlock_irqrestore(&hwgroup->lock, flags);
+
+ if (plug_device)
+ ide_plug_device(drive);
+
return irq_ret;
}
diff --git a/drivers/ide/ide-ioctls.c b/drivers/ide/ide-ioctls.c
index 28232c6..1be263e 100644
--- a/drivers/ide/ide-ioctls.c
+++ b/drivers/ide/ide-ioctls.c
@@ -95,8 +95,7 @@ static int ide_set_nice_ioctl(ide_drive_t *drive, unsigned long arg)
return -EPERM;
if (((arg >> IDE_NICE_DSC_OVERLAP) & 1) &&
- (drive->media != ide_tape ||
- (drive->dev_flags & IDE_DFLAG_SCSI)))
+ (drive->media != ide_tape))
return -EPERM;
if ((arg >> IDE_NICE_DSC_OVERLAP) & 1)
diff --git a/drivers/ide/ide-park.c b/drivers/ide/ide-park.c
index 63d01c5..678454a 100644
--- a/drivers/ide/ide-park.c
+++ b/drivers/ide/ide-park.c
@@ -16,16 +16,19 @@ static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout)
spin_lock_irq(&hwgroup->lock);
if (drive->dev_flags & IDE_DFLAG_PARKED) {
int reset_timer = time_before(timeout, drive->sleep);
+ int start_queue = 0;
drive->sleep = timeout;
wake_up_all(&ide_park_wq);
- if (reset_timer && hwgroup->sleeping &&
- del_timer(&hwgroup->timer)) {
- hwgroup->sleeping = 0;
- hwgroup->busy = 0;
+ if (reset_timer && del_timer(&hwgroup->timer))
+ start_queue = 1;
+ spin_unlock_irq(&hwgroup->lock);
+
+ if (start_queue) {
+ spin_lock_irq(q->queue_lock);
blk_start_queueing(q);
+ spin_unlock_irq(q->queue_lock);
}
- spin_unlock_irq(&hwgroup->lock);
return;
}
spin_unlock_irq(&hwgroup->lock);
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index a64ec25..c5adb7b 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -101,6 +101,82 @@ static void ide_disk_init_mult_count(ide_drive_t *drive)
}
}
+static void ide_classify_ata_dev(ide_drive_t *drive)
+{
+ u16 *id = drive->id;
+ char *m = (char *)&id[ATA_ID_PROD];
+ int is_cfa = ata_id_is_cfa(id);
+
+ /* CF devices are *not* removable in Linux definition of the term */
+ if (is_cfa == 0 && (id[ATA_ID_CONFIG] & (1 << 7)))
+ drive->dev_flags |= IDE_DFLAG_REMOVABLE;
+
+ drive->media = ide_disk;
+
+ if (!ata_id_has_unload(drive->id))
+ drive->dev_flags |= IDE_DFLAG_NO_UNLOAD;
+
+ printk(KERN_INFO "%s: %s, %s DISK drive\n", drive->name, m,
+ is_cfa ? "CFA" : "ATA");
+}
+
+static void ide_classify_atapi_dev(ide_drive_t *drive)
+{
+ u16 *id = drive->id;
+ char *m = (char *)&id[ATA_ID_PROD];
+ u8 type = (id[ATA_ID_CONFIG] >> 8) & 0x1f;
+
+ printk(KERN_INFO "%s: %s, ATAPI ", drive->name, m);
+ switch (type) {
+ case ide_floppy:
+ if (!strstr(m, "CD-ROM")) {
+ if (!strstr(m, "oppy") &&
+ !strstr(m, "poyp") &&
+ !strstr(m, "ZIP"))
+ printk(KERN_CONT "cdrom or floppy?, assuming ");
+ if (drive->media != ide_cdrom) {
+ printk(KERN_CONT "FLOPPY");
+ drive->dev_flags |= IDE_DFLAG_REMOVABLE;
+ break;
+ }
+ }
+ /* Early cdrom models used zero */
+ type = ide_cdrom;
+ case ide_cdrom:
+ drive->dev_flags |= IDE_DFLAG_REMOVABLE;
+#ifdef CONFIG_PPC
+ /* kludge for Apple PowerBook internal zip */
+ if (!strstr(m, "CD-ROM") && strstr(m, "ZIP")) {
+ printk(KERN_CONT "FLOPPY");
+ type = ide_floppy;
+ break;
+ }
+#endif
+ printk(KERN_CONT "CD/DVD-ROM");
+ break;
+ case ide_tape:
+ printk(KERN_CONT "TAPE");
+ break;
+ case ide_optical:
+ printk(KERN_CONT "OPTICAL");
+ drive->dev_flags |= IDE_DFLAG_REMOVABLE;
+ break;
+ default:
+ printk(KERN_CONT "UNKNOWN (type %d)", type);
+ break;
+ }
+
+ printk(KERN_CONT " drive\n");
+ drive->media = type;
+ /* an ATAPI device ignores DRDY */
+ drive->ready_stat = 0;
+ if (ata_id_cdb_intr(id))
+ drive->atapi_flags |= IDE_AFLAG_DRQ_INTERRUPT;
+ drive->dev_flags |= IDE_DFLAG_DOORLOCKING;
+ /* we don't do head unloading on ATAPI devices */
+ drive->dev_flags |= IDE_DFLAG_NO_UNLOAD;
+}
+
/**
* do_identify - identify a drive
* @drive: drive to identify
@@ -117,7 +193,7 @@ static void do_identify(ide_drive_t *drive, u8 cmd)
u16 *id = drive->id;
char *m = (char *)&id[ATA_ID_PROD];
unsigned long flags;
- int bswap = 1, is_cfa;
+ int bswap = 1;
/* local CPU only; some systems need this */
local_irq_save(flags);
@@ -154,91 +230,23 @@ static void do_identify(ide_drive_t *drive, u8 cmd)
if (strstr(m, "E X A B Y T E N E S T"))
goto err_misc;
- printk(KERN_INFO "%s: %s, ", drive->name, m);
-
drive->dev_flags |= IDE_DFLAG_PRESENT;
drive->dev_flags &= ~IDE_DFLAG_DEAD;
/*
* Check for an ATAPI device
*/
- if (cmd == ATA_CMD_ID_ATAPI) {
- u8 type = (id[ATA_ID_CONFIG] >> 8) & 0x1f;
-
- printk(KERN_CONT "ATAPI ");
- switch (type) {
- case ide_floppy:
- if (!strstr(m, "CD-ROM")) {
- if (!strstr(m, "oppy") &&
- !strstr(m, "poyp") &&
- !strstr(m, "ZIP"))
- printk(KERN_CONT "cdrom or floppy?, assuming ");
- if (drive->media != ide_cdrom) {
- printk(KERN_CONT "FLOPPY");
- drive->dev_flags |= IDE_DFLAG_REMOVABLE;
- break;
- }
- }
- /* Early cdrom models used zero */
- type = ide_cdrom;
- case ide_cdrom:
- drive->dev_flags |= IDE_DFLAG_REMOVABLE;
-#ifdef CONFIG_PPC
- /* kludge for Apple PowerBook internal zip */
- if (!strstr(m, "CD-ROM") && strstr(m, "ZIP")) {
- printk(KERN_CONT "FLOPPY");
- type = ide_floppy;
- break;
- }
-#endif
- printk(KERN_CONT "CD/DVD-ROM");
- break;
- case ide_tape:
- printk(KERN_CONT "TAPE");
- break;
- case ide_optical:
- printk(KERN_CONT "OPTICAL");
- drive->dev_flags |= IDE_DFLAG_REMOVABLE;
- break;
- default:
- printk(KERN_CONT "UNKNOWN (type %d)", type);
- break;
- }
- printk(KERN_CONT " drive\n");
- drive->media = type;
- /* an ATAPI device ignores DRDY */
- drive->ready_stat = 0;
- if (ata_id_cdb_intr(id))
- drive->atapi_flags |= IDE_AFLAG_DRQ_INTERRUPT;
- drive->dev_flags |= IDE_DFLAG_DOORLOCKING;
- /* we don't do head unloading on ATAPI devices */
- drive->dev_flags |= IDE_DFLAG_NO_UNLOAD;
- return;
- }
-
+ if (cmd == ATA_CMD_ID_ATAPI)
+ ide_classify_atapi_dev(drive);
+ else
/*
* Not an ATAPI device: looks like a "regular" hard disk
*/
-
- is_cfa = ata_id_is_cfa(id);
-
- /* CF devices are *not* removable in Linux definition of the term */
- if (is_cfa == 0 && (id[ATA_ID_CONFIG] & (1 << 7)))
- drive->dev_flags |= IDE_DFLAG_REMOVABLE;
-
- drive->media = ide_disk;
-
- if (!ata_id_has_unload(drive->id))
- drive->dev_flags |= IDE_DFLAG_NO_UNLOAD;
-
- printk(KERN_CONT "%s DISK drive\n", is_cfa ? "CFA" : "ATA");
-
+ ide_classify_ata_dev(drive);
return;
-
err_misc:
kfree(id);
drive->dev_flags &= ~IDE_DFLAG_PRESENT;
- return;
}
/**
@@ -641,14 +649,9 @@ static int ide_register_port(ide_hwif_t *hwif)
/* register with global device tree */
dev_set_name(&hwif->gendev, hwif->name);
hwif->gendev.driver_data = hwif;
- if (hwif->gendev.parent == NULL) {
- if (hwif->dev)
- hwif->gendev.parent = hwif->dev;
- else
- /* Would like to do = &device_legacy */
- hwif->gendev.parent = NULL;
- }
+ hwif->gendev.parent = hwif->dev;
hwif->gendev.release = hwif_release_dev;
+
ret = device_register(&hwif->gendev);
if (ret < 0) {
printk(KERN_WARNING "IDE: %s: device_register error: %d\n",
@@ -878,8 +881,7 @@ static int ide_init_queue(ide_drive_t *drive)
* do not.
*/
- q = blk_init_queue_node(do_ide_request, &hwif->hwgroup->lock,
- hwif_to_node(hwif));
+ q = blk_init_queue_node(do_ide_request, NULL, hwif_to_node(hwif));
if (!q)
return 1;
@@ -1139,8 +1141,6 @@ static struct kobject *ata_probe(dev_t dev, int *part, void *data)
if (drive->media == ide_disk)
request_module("ide-disk");
- if (drive->dev_flags & IDE_DFLAG_SCSI)
- request_module("ide-scsi");
if (drive->media == ide_cdrom || drive->media == ide_optical)
request_module("ide-cd");
if (drive->media == ide_tape)
@@ -1417,58 +1417,6 @@ static void ide_port_cable_detect(ide_hwif_t *hwif)
}
}
-static ssize_t store_delete_devices(struct device *portdev,
- struct device_attribute *attr,
- const char *buf, size_t n)
-{
- ide_hwif_t *hwif = dev_get_drvdata(portdev);
-
- if (strncmp(buf, "1", n))
- return -EINVAL;
-
- ide_port_unregister_devices(hwif);
-
- return n;
-};
-
-static DEVICE_ATTR(delete_devices, S_IWUSR, NULL, store_delete_devices);
-
-static ssize_t store_scan(struct device *portdev,
- struct device_attribute *attr,
- const char *buf, size_t n)
-{
- ide_hwif_t *hwif = dev_get_drvdata(portdev);
-
- if (strncmp(buf, "1", n))
- return -EINVAL;
-
- ide_port_unregister_devices(hwif);
- ide_port_scan(hwif);
-
- return n;
-};
-
-static DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan);
-
-static struct device_attribute *ide_port_attrs[] = {
- &dev_attr_delete_devices,
- &dev_attr_scan,
- NULL
-};
-
-static int ide_sysfs_register_port(ide_hwif_t *hwif)
-{
- int i, uninitialized_var(rc);
-
- for (i = 0; ide_port_attrs[i]; i++) {
- rc = device_create_file(hwif->portdev, ide_port_attrs[i]);
- if (rc)
- break;
- }
-
- return rc;
-}
-
static unsigned int ide_indexes;
/**
@@ -1655,9 +1603,6 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
if (hwif == NULL)
continue;
- if (hwif->chipset == ide_unknown)
- hwif->chipset = ide_generic;
-
if (hwif->present)
hwif_register_devices(hwif);
}
diff --git a/drivers/ide/ide-sysfs.c b/drivers/ide/ide-sysfs.c
new file mode 100644
index 0000000..883ffac
--- /dev/null
+++ b/drivers/ide/ide-sysfs.c
@@ -0,0 +1,125 @@
+#include <linux/kernel.h>
+#include <linux/ide.h>
+
+char *ide_media_string(ide_drive_t *drive)
+{
+ switch (drive->media) {
+ case ide_disk:
+ return "disk";
+ case ide_cdrom:
+ return "cdrom";
+ case ide_tape:
+ return "tape";
+ case ide_floppy:
+ return "floppy";
+ case ide_optical:
+ return "optical";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+static ssize_t media_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ ide_drive_t *drive = to_ide_device(dev);
+ return sprintf(buf, "%s\n", ide_media_string(drive));
+}
+
+static ssize_t drivename_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ ide_drive_t *drive = to_ide_device(dev);
+ return sprintf(buf, "%s\n", drive->name);
+}
+
+static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ ide_drive_t *drive = to_ide_device(dev);
+ return sprintf(buf, "ide:m-%s\n", ide_media_string(drive));
+}
+
+static ssize_t model_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ ide_drive_t *drive = to_ide_device(dev);
+ return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_PROD]);
+}
+
+static ssize_t firmware_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ ide_drive_t *drive = to_ide_device(dev);
+ return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_FW_REV]);
+}
+
+static ssize_t serial_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ ide_drive_t *drive = to_ide_device(dev);
+ return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_SERNO]);
+}
+
+struct device_attribute ide_dev_attrs[] = {
+ __ATTR_RO(media),
+ __ATTR_RO(drivename),
+ __ATTR_RO(modalias),
+ __ATTR_RO(model),
+ __ATTR_RO(firmware),
+ __ATTR(serial, 0400, serial_show, NULL),
+ __ATTR(unload_heads, 0644, ide_park_show, ide_park_store),
+ __ATTR_NULL
+};
+
+static ssize_t store_delete_devices(struct device *portdev,
+ struct device_attribute *attr,
+ const char *buf, size_t n)
+{
+ ide_hwif_t *hwif = dev_get_drvdata(portdev);
+
+ if (strncmp(buf, "1", n))
+ return -EINVAL;
+
+ ide_port_unregister_devices(hwif);
+
+ return n;
+};
+
+static DEVICE_ATTR(delete_devices, S_IWUSR, NULL, store_delete_devices);
+
+static ssize_t store_scan(struct device *portdev,
+ struct device_attribute *attr,
+ const char *buf, size_t n)
+{
+ ide_hwif_t *hwif = dev_get_drvdata(portdev);
+
+ if (strncmp(buf, "1", n))
+ return -EINVAL;
+
+ ide_port_unregister_devices(hwif);
+ ide_port_scan(hwif);
+
+ return n;
+};
+
+static DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan);
+
+static struct device_attribute *ide_port_attrs[] = {
+ &dev_attr_delete_devices,
+ &dev_attr_scan,
+ NULL
+};
+
+int ide_sysfs_register_port(ide_hwif_t *hwif)
+{
+ int i, uninitialized_var(rc);
+
+ for (i = 0; ide_port_attrs[i]; i++) {
+ rc = device_create_file(hwif->portdev, ide_port_attrs[i]);
+ if (rc)
+ break;
+ }
+
+ return rc;
+}
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index a2d470e..5d2aa22 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -694,7 +694,7 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive,
pc->retries++;
- return ide_issue_pc(drive, WAIT_TAPE_CMD, NULL);
+ return ide_issue_pc(drive);
}
/* A mode sense command is used to "sense" tape parameters. */
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index f0f09f7..46a2d4c 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -440,81 +440,13 @@ static int ide_bus_match(struct device *dev, struct device_driver *drv)
return 1;
}
-static char *media_string(ide_drive_t *drive)
-{
- switch (drive->media) {
- case ide_disk:
- return "disk";
- case ide_cdrom:
- return "cdrom";
- case ide_tape:
- return "tape";
- case ide_floppy:
- return "floppy";
- case ide_optical:
- return "optical";
- default:
- return "UNKNOWN";
- }
-}
-
-static ssize_t media_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
- ide_drive_t *drive = to_ide_device(dev);
- return sprintf(buf, "%s\n", media_string(drive));
-}
-
-static ssize_t drivename_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
- ide_drive_t *drive = to_ide_device(dev);
- return sprintf(buf, "%s\n", drive->name);
-}
-
-static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
- ide_drive_t *drive = to_ide_device(dev);
- return sprintf(buf, "ide:m-%s\n", media_string(drive));
-}
-
-static ssize_t model_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- ide_drive_t *drive = to_ide_device(dev);
- return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_PROD]);
-}
-
-static ssize_t firmware_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- ide_drive_t *drive = to_ide_device(dev);
- return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_FW_REV]);
-}
-
-static ssize_t serial_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- ide_drive_t *drive = to_ide_device(dev);
- return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_SERNO]);
-}
-
-static struct device_attribute ide_dev_attrs[] = {
- __ATTR_RO(media),
- __ATTR_RO(drivename),
- __ATTR_RO(modalias),
- __ATTR_RO(model),
- __ATTR_RO(firmware),
- __ATTR(serial, 0400, serial_show, NULL),
- __ATTR(unload_heads, 0644, ide_park_show, ide_park_store),
- __ATTR_NULL
-};
-
static int ide_uevent(struct device *dev, struct kobj_uevent_env *env)
{
ide_drive_t *drive = to_ide_device(dev);
- add_uevent_var(env, "MEDIA=%s", media_string(drive));
+ add_uevent_var(env, "MEDIA=%s", ide_media_string(drive));
add_uevent_var(env, "DRIVENAME=%s", drive->name);
- add_uevent_var(env, "MODALIAS=ide:m-%s", media_string(drive));
+ add_uevent_var(env, "MODALIAS=ide:m-%s", ide_media_string(drive));
return 0;
}
diff --git a/drivers/ide/tx4938ide.c b/drivers/ide/tx4938ide.c
index 13b63e7..b4ef218 100644
--- a/drivers/ide/tx4938ide.c
+++ b/drivers/ide/tx4938ide.c
@@ -216,16 +216,17 @@ static const struct ide_tp_ops tx4938ide_tp_ops = {
#endif /* __BIG_ENDIAN */
static const struct ide_port_ops tx4938ide_port_ops = {
- .set_pio_mode = tx4938ide_set_pio_mode,
+ .set_pio_mode = tx4938ide_set_pio_mode,
};
static const struct ide_port_info tx4938ide_port_info __initdata = {
- .port_ops = &tx4938ide_port_ops,
+ .port_ops = &tx4938ide_port_ops,
#ifdef __BIG_ENDIAN
- .tp_ops = &tx4938ide_tp_ops,
+ .tp_ops = &tx4938ide_tp_ops,
#endif
- .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA,
- .pio_mask = ATA_PIO5,
+ .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA,
+ .pio_mask = ATA_PIO5,
+ .chipset = ide_generic,
};
static int __init tx4938ide_probe(struct platform_device *pdev)
diff --git a/drivers/ide/tx4939ide.c b/drivers/ide/tx4939ide.c
index 97cd9e0..4a8c5a2 100644
--- a/drivers/ide/tx4939ide.c
+++ b/drivers/ide/tx4939ide.c
@@ -623,33 +623,34 @@ static const struct ide_tp_ops tx4939ide_tp_ops = {
#endif /* __LITTLE_ENDIAN */
static const struct ide_port_ops tx4939ide_port_ops = {
- .set_pio_mode = tx4939ide_set_pio_mode,
- .set_dma_mode = tx4939ide_set_dma_mode,
- .clear_irq = tx4939ide_clear_irq,
- .cable_detect = tx4939ide_cable_detect,
+ .set_pio_mode = tx4939ide_set_pio_mode,
+ .set_dma_mode = tx4939ide_set_dma_mode,
+ .clear_irq = tx4939ide_clear_irq,
+ .cable_detect = tx4939ide_cable_detect,
};
static const struct ide_dma_ops tx4939ide_dma_ops = {
- .dma_host_set = tx4939ide_dma_host_set,
- .dma_setup = tx4939ide_dma_setup,
- .dma_exec_cmd = ide_dma_exec_cmd,
- .dma_start = ide_dma_start,
- .dma_end = tx4939ide_dma_end,
- .dma_test_irq = tx4939ide_dma_test_irq,
- .dma_lost_irq = ide_dma_lost_irq,
- .dma_timeout = ide_dma_timeout,
+ .dma_host_set = tx4939ide_dma_host_set,
+ .dma_setup = tx4939ide_dma_setup,
+ .dma_exec_cmd = ide_dma_exec_cmd,
+ .dma_start = ide_dma_start,
+ .dma_end = tx4939ide_dma_end,
+ .dma_test_irq = tx4939ide_dma_test_irq,
+ .dma_lost_irq = ide_dma_lost_irq,
+ .dma_timeout = ide_dma_timeout,
};
static const struct ide_port_info tx4939ide_port_info __initdata = {
- .init_hwif = tx4939ide_init_hwif,
- .init_dma = tx4939ide_init_dma,
- .port_ops = &tx4939ide_port_ops,
- .dma_ops = &tx4939ide_dma_ops,
- .tp_ops = &tx4939ide_tp_ops,
- .host_flags = IDE_HFLAG_MMIO,
- .pio_mask = ATA_PIO4,
- .mwdma_mask = ATA_MWDMA2,
- .udma_mask = ATA_UDMA5,
+ .init_hwif = tx4939ide_init_hwif,
+ .init_dma = tx4939ide_init_dma,
+ .port_ops = &tx4939ide_port_ops,
+ .dma_ops = &tx4939ide_dma_ops,
+ .tp_ops = &tx4939ide_tp_ops,
+ .host_flags = IDE_HFLAG_MMIO,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA5,
+ .chipset = ide_generic,
};
static int __init tx4939ide_probe(struct platform_device *pdev)
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 152d4aa..b732297 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -21,7 +21,7 @@ config SCSI
You also need to say Y here if you have a device which speaks
the SCSI protocol. Examples of this include the parallel port
version of the IOMEGA ZIP drive, USB storage devices, Fibre
- Channel, FireWire storage and the IDE-SCSI emulation driver.
+ Channel, and FireWire storage.
To compile this driver as a module, choose M here and read
<file:Documentation/scsi/scsi.txt>.
@@ -101,9 +101,9 @@ config CHR_DEV_OSST
---help---
The OnStream SC-x0 SCSI tape drives cannot be driven by the
standard st driver, but instead need this special osst driver and
- use the /dev/osstX char device nodes (major 206). Via usb-storage
- and ide-scsi, you may be able to drive the USB-x0 and DI-x0 drives
- as well. Note that there is also a second generation of OnStream
+ use the /dev/osstX char device nodes (major 206). Via usb-storage,
+ you may be able to drive the USB-x0 and DI-x0 drives as well.
+ Note that there is also a second generation of OnStream
tape drives (ADR-x0) that supports the standard SCSI-2 commands for
tapes (QIC-157) and can be driven by the standard driver st.
For more information, you may have a look at the SCSI-HOWTO
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 1410697..7461eb0 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -105,7 +105,6 @@ obj-$(CONFIG_SCSI_GDTH) += gdth.o
obj-$(CONFIG_SCSI_INITIO) += initio.o
obj-$(CONFIG_SCSI_INIA100) += a100u2w.o
obj-$(CONFIG_SCSI_QLOGICPTI) += qlogicpti.o
-obj-$(CONFIG_BLK_DEV_IDESCSI) += ide-scsi.o
obj-$(CONFIG_SCSI_MESH) += mesh.o
obj-$(CONFIG_SCSI_MAC53C94) += mac53c94.o
obj-$(CONFIG_BLK_DEV_3W_XXXX_RAID) += 3w-xxxx.o
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
deleted file mode 100644
index c24140a..0000000
--- a/drivers/scsi/ide-scsi.c
+++ /dev/null
@@ -1,840 +0,0 @@
-/*
- * Copyright (C) 1996-1999 Gadi Oxman <gadio@netvision.net.il>
- * Copyright (C) 2004-2005 Bartlomiej Zolnierkiewicz
- */
-
-/*
- * Emulation of a SCSI host adapter for IDE ATAPI devices.
- *
- * With this driver, one can use the Linux SCSI drivers instead of the
- * native IDE ATAPI drivers.
- *
- * Ver 0.1 Dec 3 96 Initial version.
- * Ver 0.2 Jan 26 97 Fixed bug in cleanup_module() and added emulation
- * of MODE_SENSE_6/MODE_SELECT_6 for cdroms. Thanks
- * to Janos Farkas for pointing this out.
- * Avoid using bitfields in structures for m68k.
- * Added Scatter/Gather and DMA support.
- * Ver 0.4 Dec 7 97 Add support for ATAPI PD/CD drives.
- * Use variable timeout for each command.
- * Ver 0.5 Jan 2 98 Fix previous PD/CD support.
- * Allow disabling of SCSI-6 to SCSI-10 transformation.
- * Ver 0.6 Jan 27 98 Allow disabling of SCSI command translation layer
- * for access through /dev/sg.
- * Fix MODE_SENSE_6/MODE_SELECT_6/INQUIRY translation.
- * Ver 0.7 Dec 04 98 Ignore commands where lun != 0 to avoid multiple
- * detection of devices with CONFIG_SCSI_MULTI_LUN
- * Ver 0.8 Feb 05 99 Optical media need translation too. Reverse 0.7.
- * Ver 0.9 Jul 04 99 Fix a bug in SG_SET_TRANSFORM.
- * Ver 0.91 Jun 10 02 Fix "off by one" error in transforms
- * Ver 0.92 Dec 31 02 Implement new SCSI mid level API
- */
-
-#define IDESCSI_VERSION "0.92"
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/ioport.h>
-#include <linux/blkdev.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/ide.h>
-#include <linux/scatterlist.h>
-#include <linux/delay.h>
-#include <linux/mutex.h>
-#include <linux/bitops.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#include <scsi/scsi.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_device.h>
-#include <scsi/scsi_host.h>
-#include <scsi/scsi_tcq.h>
-#include <scsi/sg.h>
-
-#define IDESCSI_DEBUG_LOG 0
-
-#if IDESCSI_DEBUG_LOG
-#define debug_log(fmt, args...) \
- printk(KERN_INFO "ide-scsi: " fmt, ## args)
-#else
-#define debug_log(fmt, args...) do {} while (0)
-#endif
-
-/*
- * SCSI command transformation layer
- */
-#define IDESCSI_SG_TRANSFORM 1 /* /dev/sg transformation */
-
-/*
- * Log flags
- */
-#define IDESCSI_LOG_CMD 0 /* Log SCSI commands */
-
-typedef struct ide_scsi_obj {
- ide_drive_t *drive;
- ide_driver_t *driver;
- struct gendisk *disk;
- struct Scsi_Host *host;
-
- unsigned long transform; /* SCSI cmd translation layer */
- unsigned long log; /* log flags */
-} idescsi_scsi_t;
-
-static DEFINE_MUTEX(idescsi_ref_mutex);
-/* Set by module param to skip cd */
-static int idescsi_nocd;
-
-#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)
-{
- struct ide_scsi_obj *scsi = NULL;
-
- mutex_lock(&idescsi_ref_mutex);
- scsi = ide_scsi_g(disk);
- if (scsi) {
- if (ide_device_get(scsi->drive))
- scsi = NULL;
- else
- scsi_host_get(scsi->host);
- }
- mutex_unlock(&idescsi_ref_mutex);
- return scsi;
-}
-
-static void ide_scsi_put(struct ide_scsi_obj *scsi)
-{
- ide_drive_t *drive = scsi->drive;
-
- mutex_lock(&idescsi_ref_mutex);
- scsi_host_put(scsi->host);
- ide_device_put(drive);
- mutex_unlock(&idescsi_ref_mutex);
-}
-
-static inline idescsi_scsi_t *scsihost_to_idescsi(struct Scsi_Host *host)
-{
- return (idescsi_scsi_t*) (&host[1]);
-}
-
-static inline idescsi_scsi_t *drive_to_idescsi(ide_drive_t *ide_drive)
-{
- return scsihost_to_idescsi(ide_drive->driver_data);
-}
-
-static void ide_scsi_hex_dump(u8 *data, int len)
-{
- print_hex_dump(KERN_CONT, "", DUMP_PREFIX_NONE, 16, 1, data, len, 0);
-}
-
-static int idescsi_end_request(ide_drive_t *, int, int);
-
-static void ide_scsi_callback(ide_drive_t *drive, int dsc)
-{
- idescsi_scsi_t *scsi = drive_to_idescsi(drive);
- struct ide_atapi_pc *pc = drive->pc;
-
- if (pc->flags & PC_FLAG_TIMEDOUT)
- debug_log("%s: got timed out packet %lu at %lu\n", __func__,
- pc->scsi_cmd->serial_number, jiffies);
- /* end this request now - scsi should retry it*/
- else if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
- printk(KERN_INFO "Packet command completed, %d bytes"
- " transferred\n", pc->xferred);
-
- idescsi_end_request(drive, 1, 0);
-}
-
-static int idescsi_check_condition(ide_drive_t *drive,
- struct request *failed_cmd)
-{
- idescsi_scsi_t *scsi = drive_to_idescsi(drive);
- struct ide_atapi_pc *pc;
- struct request *rq;
- u8 *buf;
-
- /* stuff a sense request in front of our current request */
- pc = kzalloc(sizeof(struct ide_atapi_pc), GFP_ATOMIC);
- rq = blk_get_request(drive->queue, READ, GFP_ATOMIC);
- buf = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_ATOMIC);
- if (!pc || !rq || !buf) {
- kfree(buf);
- if (rq)
- blk_put_request(rq);
- kfree(pc);
- return -ENOMEM;
- }
- rq->special = (char *) pc;
- pc->rq = rq;
- pc->buf = buf;
- pc->c[0] = REQUEST_SENSE;
- pc->c[4] = pc->req_xfer = pc->buf_size = SCSI_SENSE_BUFFERSIZE;
- rq->cmd_type = REQ_TYPE_SENSE;
- rq->cmd_flags |= REQ_PREEMPT;
- pc->timeout = jiffies + WAIT_READY;
- /* NOTE! Save the failed packet command in "rq->buffer" */
- rq->buffer = (void *) failed_cmd->special;
- pc->scsi_cmd = ((struct ide_atapi_pc *) failed_cmd->special)->scsi_cmd;
- if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) {
- printk ("ide-scsi: %s: queue cmd = ", drive->name);
- ide_scsi_hex_dump(pc->c, 6);
- }
- rq->rq_disk = scsi->disk;
- rq->ref_count++;
- memcpy(rq->cmd, pc->c, 12);
- ide_do_drive_cmd(drive, rq);
- return 0;
-}
-
-static ide_startstop_t
-idescsi_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
-{
- ide_hwif_t *hwif = drive->hwif;
-
- if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ))
- /* force an abort */
- hwif->tp_ops->exec_command(hwif, ATA_CMD_IDLEIMMEDIATE);
-
- rq->errors++;
-
- idescsi_end_request(drive, 0, 0);
-
- return ide_stopped;
-}
-
-static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs)
-{
- idescsi_scsi_t *scsi = drive_to_idescsi(drive);
- struct request *rq = HWGROUP(drive)->rq;
- struct ide_atapi_pc *pc = (struct ide_atapi_pc *) rq->special;
- int log = test_bit(IDESCSI_LOG_CMD, &scsi->log);
- struct Scsi_Host *host;
- int errors = rq->errors;
- unsigned long flags;
-
- if (!blk_special_request(rq) && !blk_sense_request(rq)) {
- ide_end_request(drive, uptodate, nrsecs);
- return 0;
- }
- ide_end_drive_cmd (drive, 0, 0);
- if (blk_sense_request(rq)) {
- struct ide_atapi_pc *opc = (struct ide_atapi_pc *) rq->buffer;
- if (log) {
- printk ("ide-scsi: %s: wrap up check %lu, rst = ", drive->name, opc->scsi_cmd->serial_number);
- ide_scsi_hex_dump(pc->buf, 16);
- }
- memcpy((void *) opc->scsi_cmd->sense_buffer, pc->buf,
- SCSI_SENSE_BUFFERSIZE);
- kfree(pc->buf);
- kfree(pc);
- blk_put_request(rq);
- pc = opc;
- rq = pc->rq;
- pc->scsi_cmd->result = (CHECK_CONDITION << 1) |
- (((pc->flags & PC_FLAG_TIMEDOUT) ?
- DID_TIME_OUT :
- DID_OK) << 16);
- } else if (pc->flags & PC_FLAG_TIMEDOUT) {
- if (log)
- printk (KERN_WARNING "ide-scsi: %s: timed out for %lu\n",
- drive->name, pc->scsi_cmd->serial_number);
- pc->scsi_cmd->result = DID_TIME_OUT << 16;
- } else if (errors >= ERROR_MAX) {
- pc->scsi_cmd->result = DID_ERROR << 16;
- if (log)
- printk ("ide-scsi: %s: I/O error for %lu\n", drive->name, pc->scsi_cmd->serial_number);
- } else if (errors) {
- if (log)
- printk ("ide-scsi: %s: check condition for %lu\n", drive->name, pc->scsi_cmd->serial_number);
- if (!idescsi_check_condition(drive, rq))
- /* we started a request sense, so we'll be back, exit for now */
- return 0;
- pc->scsi_cmd->result = (CHECK_CONDITION << 1) | (DID_OK << 16);
- } else {
- pc->scsi_cmd->result = DID_OK << 16;
- }
- host = pc->scsi_cmd->device->host;
- spin_lock_irqsave(host->host_lock, flags);
- pc->done(pc->scsi_cmd);
- spin_unlock_irqrestore(host->host_lock, flags);
- kfree(pc);
- blk_put_request(rq);
- drive->pc = NULL;
- return 0;
-}
-
-static inline int idescsi_set_direction(struct ide_atapi_pc *pc)
-{
- switch (pc->c[0]) {
- case READ_6: case READ_10: case READ_12:
- pc->flags &= ~PC_FLAG_WRITING;
- return 0;
- case WRITE_6: case WRITE_10: case WRITE_12:
- pc->flags |= PC_FLAG_WRITING;
- return 0;
- default:
- return 1;
- }
-}
-
-static int idescsi_map_sg(ide_drive_t *drive, struct ide_atapi_pc *pc)
-{
- ide_hwif_t *hwif = drive->hwif;
- struct scatterlist *sg, *scsi_sg;
- int segments;
-
- if (!pc->req_xfer || pc->req_xfer % 1024)
- return 1;
-
- if (idescsi_set_direction(pc))
- return 1;
-
- sg = hwif->sg_table;
- scsi_sg = scsi_sglist(pc->scsi_cmd);
- segments = scsi_sg_count(pc->scsi_cmd);
-
- if (segments > hwif->sg_max_nents)
- return 1;
-
- hwif->sg_nents = segments;
- memcpy(sg, scsi_sg, sizeof(*sg) * segments);
-
- return 0;
-}
-
-static ide_startstop_t idescsi_issue_pc(ide_drive_t *drive,
- struct ide_atapi_pc *pc)
-{
- /* Set the current packet command */
- drive->pc = pc;
-
- return ide_issue_pc(drive, ide_scsi_get_timeout(pc), ide_scsi_expiry);
-}
-
-/*
- * idescsi_do_request is our request handling function.
- */
-static ide_startstop_t idescsi_do_request (ide_drive_t *drive, struct request *rq, sector_t block)
-{
- debug_log("dev: %s, cmd: %x, errors: %d\n", rq->rq_disk->disk_name,
- rq->cmd[0], rq->errors);
- debug_log("sector: %ld, nr_sectors: %ld, current_nr_sectors: %d\n",
- rq->sector, rq->nr_sectors, rq->current_nr_sectors);
-
- if (blk_sense_request(rq) || blk_special_request(rq)) {
- struct ide_atapi_pc *pc = (struct ide_atapi_pc *)rq->special;
-
- if ((drive->dev_flags & IDE_DFLAG_USING_DMA) &&
- idescsi_map_sg(drive, pc) == 0)
- pc->flags |= PC_FLAG_DMA_OK;
-
- return idescsi_issue_pc(drive, pc);
- }
- blk_dump_rq_flags(rq, "ide-scsi: unsup command");
- idescsi_end_request (drive, 0, 0);
- return ide_stopped;
-}
-
-#ifdef CONFIG_IDE_PROC_FS
-static ide_proc_entry_t idescsi_proc[] = {
- { "capacity", S_IFREG|S_IRUGO, proc_ide_read_capacity, NULL },
- { NULL, 0, NULL, NULL }
-};
-
-#define ide_scsi_devset_get(name, field) \
-static int get_##name(ide_drive_t *drive) \
-{ \
- idescsi_scsi_t *scsi = drive_to_idescsi(drive); \
- return scsi->field; \
-}
-
-#define ide_scsi_devset_set(name, field) \
-static int set_##name(ide_drive_t *drive, int arg) \
-{ \
- idescsi_scsi_t *scsi = drive_to_idescsi(drive); \
- scsi->field = arg; \
- return 0; \
-}
-
-#define ide_scsi_devset_rw_field(_name, _field) \
-ide_scsi_devset_get(_name, _field); \
-ide_scsi_devset_set(_name, _field); \
-IDE_DEVSET(_name, DS_SYNC, get_##_name, set_##_name);
-
-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_field(transform, transform);
-ide_scsi_devset_rw_field(log, log);
-
-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 },
-};
-
-static ide_proc_entry_t *ide_scsi_proc_entries(ide_drive_t *drive)
-{
- return idescsi_proc;
-}
-
-static const struct ide_proc_devset *ide_scsi_proc_devsets(ide_drive_t *drive)
-{
- return idescsi_settings;
-}
-#endif
-
-/*
- * Driver initialization.
- */
-static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi)
-{
- clear_bit(IDESCSI_SG_TRANSFORM, &scsi->transform);
-#if IDESCSI_DEBUG_LOG
- set_bit(IDESCSI_LOG_CMD, &scsi->log);
-#endif /* IDESCSI_DEBUG_LOG */
-
- drive->pc_callback = ide_scsi_callback;
- drive->pc_update_buffers = NULL;
- drive->pc_io_buffers = ide_io_buffers;
-
- ide_proc_register_driver(drive, scsi->driver);
-}
-
-static void ide_scsi_remove(ide_drive_t *drive)
-{
- struct Scsi_Host *scsihost = drive->driver_data;
- struct ide_scsi_obj *scsi = scsihost_to_idescsi(scsihost);
- struct gendisk *g = scsi->disk;
-
- scsi_remove_host(scsihost);
- ide_proc_unregister_driver(drive, scsi->driver);
-
- ide_unregister_region(g);
-
- drive->driver_data = NULL;
- g->private_data = NULL;
- put_disk(g);
-
- ide_scsi_put(scsi);
-
- drive->dev_flags &= ~IDE_DFLAG_SCSI;
-}
-
-static int ide_scsi_probe(ide_drive_t *);
-
-static ide_driver_t idescsi_driver = {
- .gen_driver = {
- .owner = THIS_MODULE,
- .name = "ide-scsi",
- .bus = &ide_bus_type,
- },
- .probe = ide_scsi_probe,
- .remove = ide_scsi_remove,
- .version = IDESCSI_VERSION,
- .do_request = idescsi_do_request,
- .end_request = idescsi_end_request,
- .error = idescsi_atapi_error,
-#ifdef CONFIG_IDE_PROC_FS
- .proc_entries = ide_scsi_proc_entries,
- .proc_devsets = ide_scsi_proc_devsets,
-#endif
-};
-
-static int idescsi_ide_open(struct block_device *bdev, fmode_t mode)
-{
- struct ide_scsi_obj *scsi = ide_scsi_get(bdev->bd_disk);
-
- if (!scsi)
- return -ENXIO;
-
- return 0;
-}
-
-static int idescsi_ide_release(struct gendisk *disk, fmode_t mode)
-{
- ide_scsi_put(ide_scsi_g(disk));
- return 0;
-}
-
-static int idescsi_ide_ioctl(struct block_device *bdev, fmode_t mode,
- unsigned int cmd, unsigned long arg)
-{
- struct ide_scsi_obj *scsi = ide_scsi_g(bdev->bd_disk);
- return generic_ide_ioctl(scsi->drive, bdev, cmd, arg);
-}
-
-static struct block_device_operations idescsi_ops = {
- .owner = THIS_MODULE,
- .open = idescsi_ide_open,
- .release = idescsi_ide_release,
- .locked_ioctl = idescsi_ide_ioctl,
-};
-
-static int idescsi_slave_configure(struct scsi_device * sdp)
-{
- /* Configure detected device */
- sdp->use_10_for_rw = 1;
- sdp->use_10_for_ms = 1;
- scsi_adjust_queue_depth(sdp, MSG_SIMPLE_TAG, sdp->host->cmd_per_lun);
- return 0;
-}
-
-static const char *idescsi_info (struct Scsi_Host *host)
-{
- return "SCSI host adapter emulation for IDE ATAPI devices";
-}
-
-static int idescsi_ioctl (struct scsi_device *dev, int cmd, void __user *arg)
-{
- idescsi_scsi_t *scsi = scsihost_to_idescsi(dev->host);
-
- if (cmd == SG_SET_TRANSFORM) {
- if (arg)
- set_bit(IDESCSI_SG_TRANSFORM, &scsi->transform);
- else
- clear_bit(IDESCSI_SG_TRANSFORM, &scsi->transform);
- return 0;
- } else if (cmd == SG_GET_TRANSFORM)
- return put_user(test_bit(IDESCSI_SG_TRANSFORM, &scsi->transform), (int __user *) arg);
- return -EINVAL;
-}
-
-static int idescsi_queue (struct scsi_cmnd *cmd,
- void (*done)(struct scsi_cmnd *))
-{
- struct Scsi_Host *host = cmd->device->host;
- idescsi_scsi_t *scsi = scsihost_to_idescsi(host);
- ide_drive_t *drive = scsi->drive;
- struct request *rq = NULL;
- struct ide_atapi_pc *pc = NULL;
- int write = cmd->sc_data_direction == DMA_TO_DEVICE;
-
- if (!drive) {
- scmd_printk (KERN_ERR, cmd, "drive not present\n");
- goto abort;
- }
- scsi = drive_to_idescsi(drive);
- pc = kmalloc(sizeof(struct ide_atapi_pc), GFP_ATOMIC);
- rq = blk_get_request(drive->queue, write, GFP_ATOMIC);
- if (rq == NULL || pc == NULL) {
- printk (KERN_ERR "ide-scsi: %s: out of memory\n", drive->name);
- goto abort;
- }
-
- memset (pc->c, 0, 12);
- pc->flags = 0;
- if (cmd->sc_data_direction == DMA_TO_DEVICE)
- pc->flags |= PC_FLAG_WRITING;
- pc->rq = rq;
- memcpy (pc->c, cmd->cmnd, cmd->cmd_len);
- pc->buf = NULL;
- pc->sg = scsi_sglist(cmd);
- pc->sg_cnt = scsi_sg_count(cmd);
- pc->b_count = 0;
- pc->req_xfer = pc->buf_size = scsi_bufflen(cmd);
- pc->scsi_cmd = cmd;
- pc->done = done;
- pc->timeout = jiffies + cmd->request->timeout;
-
- if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) {
- printk ("ide-scsi: %s: que %lu, cmd = ", drive->name, cmd->serial_number);
- ide_scsi_hex_dump(cmd->cmnd, cmd->cmd_len);
- if (memcmp(pc->c, cmd->cmnd, cmd->cmd_len)) {
- printk ("ide-scsi: %s: que %lu, tsl = ", drive->name, cmd->serial_number);
- ide_scsi_hex_dump(pc->c, 12);
- }
- }
-
- rq->special = (char *) pc;
- rq->cmd_type = REQ_TYPE_SPECIAL;
- spin_unlock_irq(host->host_lock);
- rq->ref_count++;
- memcpy(rq->cmd, pc->c, 12);
- blk_execute_rq_nowait(drive->queue, scsi->disk, rq, 0, NULL);
- spin_lock_irq(host->host_lock);
- return 0;
-abort:
- kfree (pc);
- if (rq)
- blk_put_request(rq);
- cmd->result = DID_ERROR << 16;
- done(cmd);
- return 0;
-}
-
-static int idescsi_eh_abort (struct scsi_cmnd *cmd)
-{
- idescsi_scsi_t *scsi = scsihost_to_idescsi(cmd->device->host);
- ide_drive_t *drive = scsi->drive;
- ide_hwif_t *hwif;
- ide_hwgroup_t *hwgroup;
- int busy;
- int ret = FAILED;
-
- struct ide_atapi_pc *pc;
-
- /* In idescsi_eh_abort we try to gently pry our command from the ide subsystem */
-
- if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
- printk (KERN_WARNING "ide-scsi: abort called for %lu\n", cmd->serial_number);
-
- if (!drive) {
- printk (KERN_WARNING "ide-scsi: Drive not set in idescsi_eh_abort\n");
- WARN_ON(1);
- goto no_drive;
- }
-
- hwif = drive->hwif;
- hwgroup = hwif->hwgroup;
-
- /* First give it some more time, how much is "right" is hard to say :-(
- FIXME - uses mdelay which causes latency? */
- busy = ide_wait_not_busy(hwif, 100);
- if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
- printk (KERN_WARNING "ide-scsi: drive did%s become ready\n", busy?" not":"");
-
- spin_lock_irq(&hwgroup->lock);
-
- /* If there is no pc running we're done (our interrupt took care of it) */
- pc = drive->pc;
- if (pc == NULL) {
- ret = SUCCESS;
- goto ide_unlock;
- }
-
- /* It's somewhere in flight. Does ide subsystem agree? */
- if (pc->scsi_cmd->serial_number == cmd->serial_number && !busy &&
- elv_queue_empty(drive->queue) && HWGROUP(drive)->rq != pc->rq) {
- /*
- * FIXME - not sure this condition can ever occur
- */
- printk (KERN_ERR "ide-scsi: cmd aborted!\n");
-
- if (blk_sense_request(pc->rq))
- kfree(pc->buf);
- /* we need to call blk_put_request twice. */
- blk_put_request(pc->rq);
- blk_put_request(pc->rq);
- kfree(pc);
- drive->pc = NULL;
-
- ret = SUCCESS;
- }
-
-ide_unlock:
- spin_unlock_irq(&hwgroup->lock);
-no_drive:
- if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
- printk (KERN_WARNING "ide-scsi: abort returns %s\n", ret == SUCCESS?"success":"failed");
-
- return ret;
-}
-
-static int idescsi_eh_reset (struct scsi_cmnd *cmd)
-{
- struct request *req;
- idescsi_scsi_t *scsi = scsihost_to_idescsi(cmd->device->host);
- ide_drive_t *drive = scsi->drive;
- ide_hwgroup_t *hwgroup;
- int ready = 0;
- int ret = SUCCESS;
-
- struct ide_atapi_pc *pc;
-
- /* In idescsi_eh_reset we forcefully remove the command from the ide subsystem and reset the device. */
-
- if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
- printk (KERN_WARNING "ide-scsi: reset called for %lu\n", cmd->serial_number);
-
- if (!drive) {
- printk (KERN_WARNING "ide-scsi: Drive not set in idescsi_eh_reset\n");
- WARN_ON(1);
- return FAILED;
- }
-
- hwgroup = drive->hwif->hwgroup;
-
- spin_lock_irq(cmd->device->host->host_lock);
- spin_lock(&hwgroup->lock);
-
- pc = drive->pc;
- if (pc)
- req = pc->rq;
-
- if (pc == NULL || req != hwgroup->rq || hwgroup->handler == NULL) {
- printk (KERN_WARNING "ide-scsi: No active request in idescsi_eh_reset\n");
- spin_unlock(&hwgroup->lock);
- spin_unlock_irq(cmd->device->host->host_lock);
- return FAILED;
- }
-
- /* kill current request */
- if (__blk_end_request(req, -EIO, 0))
- BUG();
- if (blk_sense_request(req))
- kfree(pc->buf);
- kfree(pc);
- drive->pc = NULL;
- blk_put_request(req);
-
- /* now nuke the drive queue */
- while ((req = elv_next_request(drive->queue))) {
- if (__blk_end_request(req, -EIO, 0))
- BUG();
- }
-
- hwgroup->rq = NULL;
- hwgroup->handler = NULL;
- hwgroup->busy = 1; /* will set this to zero when ide reset finished */
- spin_unlock(&hwgroup->lock);
-
- ide_do_reset(drive);
-
- /* ide_do_reset starts a polling handler which restarts itself every 50ms until the reset finishes */
-
- do {
- spin_unlock_irq(cmd->device->host->host_lock);
- msleep(50);
- spin_lock_irq(cmd->device->host->host_lock);
- } while ( HWGROUP(drive)->handler );
-
- ready = drive_is_ready(drive);
- HWGROUP(drive)->busy--;
- if (!ready) {
- printk (KERN_ERR "ide-scsi: reset failed!\n");
- ret = FAILED;
- }
-
- spin_unlock_irq(cmd->device->host->host_lock);
- return ret;
-}
-
-static int idescsi_bios(struct scsi_device *sdev, struct block_device *bdev,
- sector_t capacity, int *parm)
-{
- idescsi_scsi_t *idescsi = scsihost_to_idescsi(sdev->host);
- ide_drive_t *drive = idescsi->drive;
-
- if (drive->bios_cyl && drive->bios_head && drive->bios_sect) {
- parm[0] = drive->bios_head;
- parm[1] = drive->bios_sect;
- parm[2] = drive->bios_cyl;
- }
- return 0;
-}
-
-static struct scsi_host_template idescsi_template = {
- .module = THIS_MODULE,
- .name = "idescsi",
- .info = idescsi_info,
- .slave_configure = idescsi_slave_configure,
- .ioctl = idescsi_ioctl,
- .queuecommand = idescsi_queue,
- .eh_abort_handler = idescsi_eh_abort,
- .eh_host_reset_handler = idescsi_eh_reset,
- .bios_param = idescsi_bios,
- .can_queue = 40,
- .this_id = -1,
- .sg_tablesize = 256,
- .cmd_per_lun = 5,
- .max_sectors = 128,
- .use_clustering = DISABLE_CLUSTERING,
- .emulated = 1,
- .proc_name = "ide-scsi",
-};
-
-static int ide_scsi_probe(ide_drive_t *drive)
-{
- idescsi_scsi_t *idescsi;
- struct Scsi_Host *host;
- struct gendisk *g;
- static int warned;
- int err = -ENOMEM;
- u16 last_lun;
-
- 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");
- warned = 1;
- }
-
- if (idescsi_nocd && drive->media == ide_cdrom)
- return -ENODEV;
-
- if (!strstr("ide-scsi", drive->driver_req) ||
- drive->media == ide_disk ||
- !(host = scsi_host_alloc(&idescsi_template,sizeof(idescsi_scsi_t))))
- return -ENODEV;
-
- drive->dev_flags |= IDE_DFLAG_SCSI;
-
- g = alloc_disk(1 << PARTN_BITS);
- if (!g)
- goto out_host_put;
-
- ide_init_disk(g, drive);
-
- host->max_id = 1;
-
- last_lun = drive->id[ATA_ID_LAST_LUN];
- if (last_lun)
- debug_log("%s: last_lun=%u\n", drive->name, last_lun);
-
- if ((last_lun & 7) != 7)
- host->max_lun = (last_lun & 7) + 1;
- else
- host->max_lun = 1;
-
- 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 = 0;
- idescsi_setup(drive, idescsi);
- g->fops = &idescsi_ops;
- 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_proc_unregister_driver(drive, &idescsi_driver);
-
- put_disk(g);
-out_host_put:
- drive->dev_flags &= ~IDE_DFLAG_SCSI;
- scsi_host_put(host);
- return err;
-}
-
-static int __init init_idescsi_module(void)
-{
- return driver_register(&idescsi_driver.gen_driver);
-}
-
-static void __exit exit_idescsi_module(void)
-{
- driver_unregister(&idescsi_driver.gen_driver);
-}
-
-module_param(idescsi_nocd, int, 0600);
-MODULE_PARM_DESC(idescsi_nocd, "Disable handling of CD-ROMs so they may be driven by ide-cd");
-module_init(init_idescsi_module);
-module_exit(exit_idescsi_module);
-MODULE_LICENSE("GPL");
diff --git a/include/linux/ide.h b/include/linux/ide.h
index e99c56d..db5ef8a 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -32,13 +32,6 @@
# define SUPPORT_VLB_SYNC 1
#endif
-/*
- * Used to indicate "no IRQ", should be a value that cannot be an IRQ
- * number.
- */
-
-#define IDE_NO_IRQ (-1)
-
typedef unsigned char byte; /* used everywhere */
/*
@@ -403,6 +396,7 @@ enum {
* This is used for several packet commands (not for READ/WRITE commands).
*/
#define IDE_PC_BUFFER_SIZE 256
+#define ATAPI_WAIT_PC (60 * HZ)
struct ide_atapi_pc {
/* actual packet bytes */
@@ -480,53 +474,53 @@ enum {
/* ide-cd */
/* Drive cannot eject the disc. */
- IDE_AFLAG_NO_EJECT = (1 << 3),
+ IDE_AFLAG_NO_EJECT = (1 << 1),
/* Drive is a pre ATAPI 1.2 drive. */
- IDE_AFLAG_PRE_ATAPI12 = (1 << 4),
+ IDE_AFLAG_PRE_ATAPI12 = (1 << 2),
/* TOC addresses are in BCD. */
- IDE_AFLAG_TOCADDR_AS_BCD = (1 << 5),
+ IDE_AFLAG_TOCADDR_AS_BCD = (1 << 3),
/* TOC track numbers are in BCD. */
- IDE_AFLAG_TOCTRACKS_AS_BCD = (1 << 6),
+ IDE_AFLAG_TOCTRACKS_AS_BCD = (1 << 4),
/*
* Drive does not provide data in multiples of SECTOR_SIZE
* when more than one interrupt is needed.
*/
- IDE_AFLAG_LIMIT_NFRAMES = (1 << 7),
+ IDE_AFLAG_LIMIT_NFRAMES = (1 << 5),
/* Saved TOC information is current. */
- IDE_AFLAG_TOC_VALID = (1 << 9),
+ IDE_AFLAG_TOC_VALID = (1 << 6),
/* We think that the drive door is locked. */
- IDE_AFLAG_DOOR_LOCKED = (1 << 10),
+ IDE_AFLAG_DOOR_LOCKED = (1 << 7),
/* SET_CD_SPEED command is unsupported. */
- IDE_AFLAG_NO_SPEED_SELECT = (1 << 11),
- IDE_AFLAG_VERTOS_300_SSD = (1 << 12),
- IDE_AFLAG_VERTOS_600_ESD = (1 << 13),
- IDE_AFLAG_SANYO_3CD = (1 << 14),
- IDE_AFLAG_FULL_CAPS_PAGE = (1 << 15),
- IDE_AFLAG_PLAY_AUDIO_OK = (1 << 16),
- IDE_AFLAG_LE_SPEED_FIELDS = (1 << 17),
+ IDE_AFLAG_NO_SPEED_SELECT = (1 << 8),
+ IDE_AFLAG_VERTOS_300_SSD = (1 << 9),
+ IDE_AFLAG_VERTOS_600_ESD = (1 << 10),
+ IDE_AFLAG_SANYO_3CD = (1 << 11),
+ IDE_AFLAG_FULL_CAPS_PAGE = (1 << 12),
+ IDE_AFLAG_PLAY_AUDIO_OK = (1 << 13),
+ IDE_AFLAG_LE_SPEED_FIELDS = (1 << 14),
/* ide-floppy */
/* Avoid commands not supported in Clik drive */
- IDE_AFLAG_CLIK_DRIVE = (1 << 19),
+ IDE_AFLAG_CLIK_DRIVE = (1 << 15),
/* Requires BH algorithm for packets */
- IDE_AFLAG_ZIP_DRIVE = (1 << 20),
+ IDE_AFLAG_ZIP_DRIVE = (1 << 16),
/* Supports format progress report */
- IDE_AFLAG_SRFP = (1 << 22),
+ IDE_AFLAG_SRFP = (1 << 17),
/* ide-tape */
- IDE_AFLAG_IGNORE_DSC = (1 << 23),
+ IDE_AFLAG_IGNORE_DSC = (1 << 18),
/* 0 When the tape position is unknown */
- IDE_AFLAG_ADDRESS_VALID = (1 << 24),
+ IDE_AFLAG_ADDRESS_VALID = (1 << 19),
/* Device already opened */
- IDE_AFLAG_BUSY = (1 << 25),
+ IDE_AFLAG_BUSY = (1 << 20),
/* Attempt to auto-detect the current user block size */
- IDE_AFLAG_DETECT_BS = (1 << 26),
+ IDE_AFLAG_DETECT_BS = (1 << 21),
/* Currently on a filemark */
- IDE_AFLAG_FILEMARK = (1 << 27),
+ IDE_AFLAG_FILEMARK = (1 << 22),
/* 0 = no tape is loaded, so we don't rewind after ejecting */
- IDE_AFLAG_MEDIUM_PRESENT = (1 << 28),
+ IDE_AFLAG_MEDIUM_PRESENT = (1 << 23),
- IDE_AFLAG_NO_AUTOCLOSE = (1 << 29),
+ IDE_AFLAG_NO_AUTOCLOSE = (1 << 24),
};
/* device flags */
@@ -565,28 +559,26 @@ enum {
IDE_DFLAG_NODMA = (1 << 16),
/* powermanagment told us not to do anything, so sleep nicely */
IDE_DFLAG_BLOCKED = (1 << 17),
- /* ide-scsi emulation */
- IDE_DFLAG_SCSI = (1 << 18),
/* sleeping & sleep field valid */
- IDE_DFLAG_SLEEPING = (1 << 19),
- IDE_DFLAG_POST_RESET = (1 << 20),
- IDE_DFLAG_UDMA33_WARNED = (1 << 21),
- IDE_DFLAG_LBA48 = (1 << 22),
+ IDE_DFLAG_SLEEPING = (1 << 18),
+ IDE_DFLAG_POST_RESET = (1 << 19),
+ IDE_DFLAG_UDMA33_WARNED = (1 << 20),
+ IDE_DFLAG_LBA48 = (1 << 21),
/* status of write cache */
- IDE_DFLAG_WCACHE = (1 << 23),
+ IDE_DFLAG_WCACHE = (1 << 22),
/* used for ignoring ATA_DF */
- IDE_DFLAG_NOWERR = (1 << 24),
+ IDE_DFLAG_NOWERR = (1 << 23),
/* retrying in PIO */
- IDE_DFLAG_DMA_PIO_RETRY = (1 << 25),
- IDE_DFLAG_LBA = (1 << 26),
+ IDE_DFLAG_DMA_PIO_RETRY = (1 << 24),
+ IDE_DFLAG_LBA = (1 << 25),
/* don't unload heads */
- IDE_DFLAG_NO_UNLOAD = (1 << 27),
+ IDE_DFLAG_NO_UNLOAD = (1 << 26),
/* heads unloaded, please don't reset port */
- IDE_DFLAG_PARKED = (1 << 28),
- IDE_DFLAG_MEDIA_CHANGED = (1 << 29),
+ IDE_DFLAG_PARKED = (1 << 27),
+ IDE_DFLAG_MEDIA_CHANGED = (1 << 28),
/* write protect */
- IDE_DFLAG_WP = (1 << 30),
- IDE_DFLAG_FORMAT_IN_PROGRESS = (1 << 31),
+ IDE_DFLAG_WP = (1 << 29),
+ IDE_DFLAG_FORMAT_IN_PROGRESS = (1 << 30),
};
struct ide_drive_s {
@@ -610,8 +602,6 @@ struct ide_drive_s {
unsigned long dev_flags;
unsigned long sleep; /* sleep until this time */
- unsigned long service_start; /* time we started last request */
- unsigned long service_time; /* service time of last request */
unsigned long timeout; /* max time to wait for irq */
special_t special; /* special action flags */
@@ -879,8 +869,6 @@ typedef struct hwgroup_s {
/* BOOL: protects all fields below */
volatile int busy;
- /* BOOL: wake us up on timer expiry */
- unsigned int sleeping : 1;
/* BOOL: polling active & poll_timeout field valid */
unsigned int polling : 1;
@@ -1258,14 +1246,11 @@ int ide_set_media_lock(ide_drive_t *, struct gendisk *, int);
void ide_create_request_sense_cmd(ide_drive_t *, struct ide_atapi_pc *);
void ide_retry_pc(ide_drive_t *, struct gendisk *);
-static inline unsigned long ide_scsi_get_timeout(struct ide_atapi_pc *pc)
-{
- return max_t(unsigned long, WAIT_CMD, pc->timeout - jiffies);
-}
+int ide_cd_expiry(ide_drive_t *);
-int ide_scsi_expiry(ide_drive_t *);
+int ide_cd_get_xferlen(struct request *);
-ide_startstop_t ide_issue_pc(ide_drive_t *, unsigned int, ide_expiry_t *);
+ide_startstop_t ide_issue_pc(ide_drive_t *);
ide_startstop_t do_rw_taskfile(ide_drive_t *, ide_task_t *);
@@ -1287,6 +1272,26 @@ extern void ide_stall_queue(ide_drive_t *drive, unsigned long timeout);
extern void ide_timer_expiry(unsigned long);
extern irqreturn_t ide_intr(int irq, void *dev_id);
+
+static inline int ide_lock_hwgroup(ide_hwgroup_t *hwgroup)
+{
+ if (hwgroup->busy)
+ return 1;
+
+ hwgroup->busy = 1;
+ /* for atari only */
+ ide_get_lock(ide_intr, hwgroup);
+
+ return 0;
+}
+
+static inline void ide_unlock_hwgroup(ide_hwgroup_t *hwgroup)
+{
+ /* for atari only */
+ ide_release_lock();
+ hwgroup->busy = 0;
+}
+
extern void do_ide_request(struct request_queue *);
void ide_init_disk(struct gendisk *, ide_drive_t *);
@@ -1533,6 +1538,7 @@ void ide_unregister_region(struct gendisk *);
void ide_undecoded_slave(ide_drive_t *);
void ide_port_apply_params(ide_hwif_t *);
+int ide_sysfs_register_port(ide_hwif_t *);
struct ide_host *ide_host_alloc(const struct ide_port_info *, hw_regs_t **);
void ide_host_free(struct ide_host *);
@@ -1627,6 +1633,9 @@ extern struct mutex ide_cfg_mtx;
#define local_irq_set(flags) do { local_save_flags((flags)); local_irq_enable_in_hardirq(); } while (0)
+char *ide_media_string(ide_drive_t *);
+
+extern struct device_attribute ide_dev_attrs[];
extern struct bus_type ide_bus_type;
extern struct class *ide_port_class;
\0
WARNING: multiple messages have this Message-ID (diff)
From: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
To: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>,
Stephen Rothwell <sfr@canb.auug.org.au>,
linux-ide@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [git pull] IDE updates part 2
Date: Fri, 2 Jan 2009 17:59:45 +0100 [thread overview]
Message-ID: <200901021759.46260.bzolnier@gmail.com> (raw)
First IDE updates in 2009, this time:
* Fix IDE to not process commands in IRQ-context and than switch the subsystem to use per-device request queue locks instead of (ab)using hwgroup locks for this purpose. Besides being obvious IRQ-latency and scalability improvement this decreases complexity of core code greatly (~100 LOC of very tricky code gone) and makes maintainance work much easier.
[ Thanks to Elias Oltmanns for his work on reviewing these changes and catching some issues early. ]
* Scheduled removal of deprecated ide-scsi device driver.
We've been discouraging using ide-scsi since early 2.5.x days as the driver contains unfixable problems with error handling and lifetimes of IDE/SCSI objects. There is now consensus between IDE/SCSI people that both (recently rewritten) native ide-{cd,gd,tape} drivers from IDE side and proper ATA-SCSI emulation (libata) from SCSI side offer a better alternative.
The driver has been officially orphaned for a year and then scheduled for removal for the last 4 months so this shouldn't come as surprise (I didn't got a single user complaint about this and ide-scsi has even been broken by some unrelated kernel changes for few kernel releases in the past without anybody noticing).
(from FUJITA Tomonori and Borislav Petkov)
* Fix multiple nested big stack usage in ide-floppy.c.
(from Linus himself, testing/merging handled by Borislav)
* Preparations to switch ide-cd device driver to use generic ATAPI code which will happen in the next IDE updates pull request.
(from Borislav)
* Misc fixups/cleanups.
All above changes have been in linux-next for some time now...
Linus, please pull from:
master.kernel.org:/pub/scm/linux/kernel/git/bart/ide-2.6.git/
to receive the following updates:
Documentation/feature-removal-schedule.txt | 9 - MAINTAINERS | 5 - drivers/ide/Kconfig | 18 +- drivers/ide/Makefile | 2 +- drivers/ide/ide-atapi.c | 248 +++++---- drivers/ide/ide-cd.c | 99 +--- drivers/ide/ide-cd.h | 12 +- drivers/ide/ide-floppy.c | 28 +- drivers/ide/ide-floppy_ioctl.c | 58 +- drivers/ide/ide-io.c | 282 +++------- drivers/ide/ide-ioctls.c | 3 +- drivers/ide/ide-park.c | 13 +- drivers/ide/ide-probe.c | 223 +++----- drivers/ide/ide-sysfs.c | 125 ++++ drivers/ide/ide-tape.c | 2 +- drivers/ide/ide.c | 72 +--- drivers/ide/tx4938ide.c | 11 +- drivers/ide/tx4939ide.c | 43 +- drivers/scsi/Kconfig | 8 +- drivers/scsi/Makefile | 1 - drivers/scsi/ide-scsi.c | 840 ---------------------------- include/linux/ide.h | 121 +++-- 22 files changed, 614 insertions(+), 1609 deletions(-) create mode 100644 drivers/ide/ide-sysfs.c delete mode 100644 drivers/scsi/ide-scsi.c
Bartlomiej Zolnierkiewicz (10): tx493x: fix indentation ide: remove chipset type fixup from ide_host_register() ide: small ide_register_port() cleanup ide: factor out device type classifying from do_identify() ide: move sysfs support to ide-sysfs.c ide: don't execute the next queued command from the hard-IRQ context (v2) ide: remove IDE PM hack from do_ide_request() ide: remove "paranoia" checks for hwgroup->busy ide: add ide_[un]lock_hwgroup() helpers ide: use per-device request queue locks (v2)
Borislav Petkov (20): ide-cd: move debug defines into header ide: make IDE_AFLAG_.. numbering continuous again ide-atapi: add a dev_is_idecd-inline ide-atapi: combine drive-specific assignments ide-atapi: setup dma for ide-cd ide-atapi: accomodate transfer length calculation for ide-cd ide-atapi: teach ide atapi about drive->waiting_for_dma ide-cd: move cdrom_timer_expiry to ide-atapi.c ide-atapi: remove ide-scsi remnants from ide_issue_pc ide-atapi: remove ide-scsi remnants from ide_transfer_pc() ide-atapi: remove ide-scsi remnants from ide_pc_intr() ide: remove the last ide-scsi remnants ide-atapi: compute cmd_len based on device type in ide_transfer_pc ide-atapi: assign expiry and timeout based on device type ide-atapi: split drive-specific functionality in ide_issue_pc ide-cd: remove xferlen arg to cdrom_start_packet_command ide-cd: remove handler wrappers ide-atapi: remove timeout arg to ide_issue_pc ide-atapi: put the rest of non-ide-cd code into the else-clause of ide_transfer_pc ide-atapi: start dma in a drive-specific way
FUJITA Tomonori (1): remove ide-scsi
Linus Torvalds (1): ide-floppy: allocate only toplevel packet commands
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txtindex dc7c681..df18d87 100644--- a/Documentation/feature-removal-schedule.txt+++ b/Documentation/feature-removal-schedule.txt@@ -310,15 +310,6 @@ Who: Krzysztof Piotr Oledzki <ole@ans.pl> --------------------------- -What: ide-scsi (BLK_DEV_IDESCSI)-When: 2.6.29-Why: The 2.6 kernel supports direct writing to ide CD drives, which- eliminates the need for ide-scsi. The new method is more- efficient in every way.-Who: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>------------------------------ What: i2c_attach_client(), i2c_detach_client(), i2c_driver->detach_client() When: 2.6.29 (ideally) or 2.6.30 (more likely) Why: Deprecated by the new (standard) device driver binding model. Usediff --git a/MAINTAINERS b/MAINTAINERSindex ceb32ee..144766c 100644--- a/MAINTAINERS+++ b/MAINTAINERS@@ -2146,11 +2146,6 @@ M: Gadi Oxman <gadio@netvision.net.il> L: linux-kernel@vger.kernel.org S: Maintained -IDE-SCSI DRIVER-L: linux-ide@vger.kernel.org-L: linux-scsi@vger.kernel.org-S: Orphan- IDLE-I7300 P: Andy Henroid M: andrew.d.henroid@intel.comdiff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfigindex c9f21e3..4ee85fc 100644--- a/drivers/ide/Kconfig+++ b/drivers/ide/Kconfig@@ -137,6 +137,7 @@ config BLK_DEV_DELKIN config BLK_DEV_IDECD tristate "Include IDE/ATAPI CDROM support"+ select IDE_ATAPI ---help--- If you have a CD-ROM drive using the ATAPI protocol, say Y. ATAPI is a newer protocol used by IDE CD-ROM and TAPE drives, similar to the@@ -185,23 +186,6 @@ config BLK_DEV_IDETAPE To compile this driver as a module, choose M here: the module will be called ide-tape. -config BLK_DEV_IDESCSI- tristate "SCSI emulation support (DEPRECATED)"- depends on SCSI- select IDE_ATAPI- ---help---- WARNING: ide-scsi is no longer needed for cd writing applications!- The 2.6 kernel supports direct writing to ide-cd, which eliminates- the need for ide-scsi + the entire scsi stack just for writing a- cd. The new method is more efficient in every way.-- This will provide SCSI host adapter emulation for IDE ATAPI devices,- and will allow you to use a SCSI device driver instead of a native- ATAPI driver.-- If both this SCSI emulation and native ATAPI support are compiled- into the kernel, the native support will be used.- config BLK_DEV_IDEACPI bool "IDE ACPI support" depends on ACPIdiff --git a/drivers/ide/Makefile b/drivers/ide/Makefileindex 177e3f8..4107289 100644--- a/drivers/ide/Makefile+++ b/drivers/ide/Makefile@@ -5,7 +5,7 @@ EXTRA_CFLAGS += -Idrivers/ide ide-core-y += ide.o ide-ioctls.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \- ide-taskfile.o ide-pm.o ide-park.o ide-pio-blacklist.o+ ide-taskfile.o ide-pm.o ide-park.o ide-pio-blacklist.o ide-sysfs.o # core IDE code ide-core-$(CONFIG_IDE_TIMINGS) += ide-timings.odiff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.cindex 4e58b9e..e8688c0 100644--- a/drivers/ide/ide-atapi.c+++ b/drivers/ide/ide-atapi.c@@ -3,6 +3,7 @@ */ #include <linux/kernel.h>+#include <linux/cdrom.h> #include <linux/delay.h> #include <linux/ide.h> #include <scsi/scsi.h>@@ -14,6 +15,13 @@ #define debug_log(fmt, args...) do {} while (0) #endif +#define ATAPI_MIN_CDB_BYTES 12++static inline int dev_is_idecd(ide_drive_t *drive)+{+ return drive->media == ide_cdrom || drive->media == ide_optical;+}+ /* * Check whether we can support a device, * based on the ATAPI IDENTIFY command results.@@ -233,18 +241,49 @@ void ide_retry_pc(ide_drive_t *drive, struct gendisk *disk) } EXPORT_SYMBOL_GPL(ide_retry_pc); -int ide_scsi_expiry(ide_drive_t *drive)+int ide_cd_expiry(ide_drive_t *drive) {- struct ide_atapi_pc *pc = drive->pc;+ struct request *rq = HWGROUP(drive)->rq;+ unsigned long wait = 0; - debug_log("%s called for %lu at %lu\n", __func__,- pc->scsi_cmd->serial_number, jiffies);+ debug_log("%s: rq->cmd[0]: 0x%x\n", __func__, rq->cmd[0]); - pc->flags |= PC_FLAG_TIMEDOUT;+ /*+ * Some commands are *slow* and normally take a long time to complete.+ * Usually we can use the ATAPI "disconnect" to bypass this, but not all+ * commands/drives support that. Let ide_timer_expiry keep polling us+ * for these.+ */+ switch (rq->cmd[0]) {+ case GPCMD_BLANK:+ case GPCMD_FORMAT_UNIT:+ case GPCMD_RESERVE_RZONE_TRACK:+ case GPCMD_CLOSE_TRACK:+ case GPCMD_FLUSH_CACHE:+ wait = ATAPI_WAIT_PC;+ break;+ default:+ if (!(rq->cmd_flags & REQ_QUIET))+ printk(KERN_INFO "cmd 0x%x timed out\n",+ rq->cmd[0]);+ wait = 0;+ break;+ }+ return wait;+}+EXPORT_SYMBOL_GPL(ide_cd_expiry); - return 0; /* we do not want the IDE subsystem to retry */+int ide_cd_get_xferlen(struct request *rq)+{+ if (blk_fs_request(rq))+ return 32768;+ else if (blk_sense_request(rq) || blk_pc_request(rq) ||+ rq->cmd_type == REQ_TYPE_ATA_PC)+ return rq->data_len;+ else+ return 0; }-EXPORT_SYMBOL_GPL(ide_scsi_expiry);+EXPORT_SYMBOL_GPL(ide_cd_get_xferlen); /* * This is the usual interrupt handler which will be called during a packet@@ -258,21 +297,14 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) struct request *rq = hwif->hwgroup->rq; const struct ide_tp_ops *tp_ops = hwif->tp_ops; xfer_func_t *xferfunc;- ide_expiry_t *expiry; unsigned int timeout, temp; u16 bcount;- u8 stat, ireason, scsi = !!(drive->dev_flags & IDE_DFLAG_SCSI), dsc = 0;+ u8 stat, ireason, dsc = 0; debug_log("Enter %s - interrupt handler\n", __func__); - if (scsi) {- timeout = ide_scsi_get_timeout(pc);- expiry = ide_scsi_expiry;- } else {- timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD- : WAIT_TAPE_CMD;- expiry = NULL;- }+ timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD+ : WAIT_TAPE_CMD; if (pc->flags & PC_FLAG_TIMEDOUT) { drive->pc_callback(drive, 0);@@ -284,8 +316,8 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) { if (hwif->dma_ops->dma_end(drive) ||- (drive->media == ide_tape && !scsi && (stat & ATA_ERR))) {- if (drive->media == ide_floppy && !scsi)+ (drive->media == ide_tape && (stat & ATA_ERR))) {+ if (drive->media == ide_floppy) printk(KERN_ERR "%s: DMA %s error\n", drive->name, rq_data_dir(pc->rq) ? "write" : "read");@@ -307,7 +339,7 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) local_irq_enable_in_hardirq(); - if (drive->media == ide_tape && !scsi &&+ if (drive->media == ide_tape && (stat & ATA_ERR) && rq->cmd[0] == REQUEST_SENSE) stat &= ~ATA_ERR; @@ -315,11 +347,8 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) /* Error detected */ debug_log("%s: I/O error\n", drive->name); - if (drive->media != ide_tape || scsi) {+ if (drive->media != ide_tape) pc->rq->errors++;- if (scsi)- goto cmd_finished;- } if (rq->cmd[0] == REQUEST_SENSE) { printk(KERN_ERR "%s: I/O error in request sense"@@ -335,7 +364,6 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) /* queued, but not started */ return ide_stopped; }-cmd_finished: pc->error = 0; if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) && (stat & ATA_DSC) == 0)@@ -382,25 +410,8 @@ cmd_finished: "us more data than expected - " "discarding data\n", drive->name);- if (scsi)- temp = pc->buf_size - pc->xferred;- else- temp = 0;- if (temp) {- if (pc->sg)- drive->pc_io_buffers(drive, pc,- temp, 0);- else- tp_ops->input_data(drive, NULL,- pc->cur_pos, temp);- printk(KERN_ERR "%s: transferred %d of "- "%d bytes\n",- drive->name,- temp, bcount);- }- pc->xferred += temp;- pc->cur_pos += temp;- ide_pad_transfer(drive, 0, bcount - temp);++ ide_pad_transfer(drive, 0, bcount); goto next_irq; } debug_log("The device wants to send us more data than "@@ -410,14 +421,13 @@ cmd_finished: } else xferfunc = tp_ops->output_data; - if ((drive->media == ide_floppy && !scsi && !pc->buf) ||- (drive->media == ide_tape && !scsi && pc->bh) ||- (scsi && pc->sg)) {+ if ((drive->media == ide_floppy && !pc->buf) ||+ (drive->media == ide_tape && pc->bh)) { int done = drive->pc_io_buffers(drive, pc, bcount, !!(pc->flags & PC_FLAG_WRITING)); /* FIXME: don't do partial completions */- if (drive->media == ide_floppy && !scsi)+ if (drive->media == ide_floppy) ide_end_request(drive, 1, done >> 9); } else xferfunc(drive, NULL, pc->cur_pos, bcount);@@ -430,7 +440,7 @@ cmd_finished: rq->cmd[0], bcount); next_irq: /* And set the interrupt handler again */- ide_set_handler(drive, ide_pc_intr, timeout, expiry);+ ide_set_handler(drive, ide_pc_intr, timeout, NULL); return ide_started; } @@ -479,11 +489,12 @@ static int ide_delayed_transfer_pc(ide_drive_t *drive) static ide_startstop_t ide_transfer_pc(ide_drive_t *drive) {- struct ide_atapi_pc *pc = drive->pc;+ struct ide_atapi_pc *uninitialized_var(pc); ide_hwif_t *hwif = drive->hwif; struct request *rq = hwif->hwgroup->rq; ide_expiry_t *expiry; unsigned int timeout;+ int cmd_len; ide_startstop_t startstop; u8 ireason; @@ -493,101 +504,124 @@ static ide_startstop_t ide_transfer_pc(ide_drive_t *drive) return startstop; } - ireason = ide_read_ireason(drive);- if (drive->media == ide_tape &&- (drive->dev_flags & IDE_DFLAG_SCSI) == 0)- ireason = ide_wait_ireason(drive, ireason);-- if ((ireason & ATAPI_COD) == 0 || (ireason & ATAPI_IO)) {- printk(KERN_ERR "%s: (IO,CoD) != (0,1) while issuing "- "a packet command\n", drive->name);- return ide_do_reset(drive);+ if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {+ if (drive->dma)+ drive->waiting_for_dma = 1; } - /*- * If necessary schedule the packet transfer to occur 'timeout'- * miliseconds later in ide_delayed_transfer_pc() after the device- * says it's ready for a packet.- */- if (drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) {- timeout = drive->pc_delay;- expiry = &ide_delayed_transfer_pc;+ if (dev_is_idecd(drive)) {+ /* ATAPI commands get padded out to 12 bytes minimum */+ cmd_len = COMMAND_SIZE(rq->cmd[0]);+ if (cmd_len < ATAPI_MIN_CDB_BYTES)+ cmd_len = ATAPI_MIN_CDB_BYTES;++ timeout = rq->timeout;+ expiry = ide_cd_expiry; } else {- if (drive->dev_flags & IDE_DFLAG_SCSI) {- timeout = ide_scsi_get_timeout(pc);- expiry = ide_scsi_expiry;+ pc = drive->pc;++ cmd_len = ATAPI_MIN_CDB_BYTES;++ /*+ * If necessary schedule the packet transfer to occur 'timeout'+ * miliseconds later in ide_delayed_transfer_pc() after the+ * device says it's ready for a packet.+ */+ if (drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) {+ timeout = drive->pc_delay;+ expiry = &ide_delayed_transfer_pc; } else { timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD : WAIT_TAPE_CMD; expiry = NULL; }++ ireason = ide_read_ireason(drive);+ if (drive->media == ide_tape)+ ireason = ide_wait_ireason(drive, ireason);++ if ((ireason & ATAPI_COD) == 0 || (ireason & ATAPI_IO)) {+ printk(KERN_ERR "%s: (IO,CoD) != (0,1) while issuing "+ "a packet command\n", drive->name);++ return ide_do_reset(drive);+ } } /* Set the interrupt routine */ ide_set_handler(drive, ide_pc_intr, timeout, expiry); /* Begin DMA, if necessary */- if (pc->flags & PC_FLAG_DMA_OK) {- pc->flags |= PC_FLAG_DMA_IN_PROGRESS;- hwif->dma_ops->dma_start(drive);+ if (dev_is_idecd(drive)) {+ if (drive->dma)+ hwif->dma_ops->dma_start(drive);+ } else {+ if (pc->flags & PC_FLAG_DMA_OK) {+ pc->flags |= PC_FLAG_DMA_IN_PROGRESS;+ hwif->dma_ops->dma_start(drive);+ } } /* Send the actual packet */ if ((drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) == 0)- hwif->tp_ops->output_data(drive, NULL, rq->cmd, 12);+ hwif->tp_ops->output_data(drive, NULL, rq->cmd, cmd_len); return ide_started; } -ide_startstop_t ide_issue_pc(ide_drive_t *drive, unsigned int timeout,- ide_expiry_t *expiry)+ide_startstop_t ide_issue_pc(ide_drive_t *drive) {- struct ide_atapi_pc *pc = drive->pc;+ struct ide_atapi_pc *pc; ide_hwif_t *hwif = drive->hwif;+ ide_expiry_t *expiry = NULL;+ unsigned int timeout; u32 tf_flags; u16 bcount;- u8 scsi = !!(drive->dev_flags & IDE_DFLAG_SCSI); - /* We haven't transferred any data yet */- pc->xferred = 0;- pc->cur_pos = pc->buf;+ if (dev_is_idecd(drive)) {+ tf_flags = IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL;+ bcount = ide_cd_get_xferlen(hwif->hwgroup->rq);+ expiry = ide_cd_expiry;+ timeout = ATAPI_WAIT_PC; - /* Request to transfer the entire buffer at once */- if (drive->media == ide_tape && scsi == 0)- bcount = pc->req_xfer;- else- bcount = min(pc->req_xfer, 63 * 1024);+ if (drive->dma)+ drive->dma = !hwif->dma_ops->dma_setup(drive);+ } else {+ pc = drive->pc; - if (pc->flags & PC_FLAG_DMA_ERROR) {- pc->flags &= ~PC_FLAG_DMA_ERROR;- ide_dma_off(drive);- }+ /* We haven't transferred any data yet */+ pc->xferred = 0;+ pc->cur_pos = pc->buf; - if ((pc->flags & PC_FLAG_DMA_OK) &&- (drive->dev_flags & IDE_DFLAG_USING_DMA)) {- if (scsi)- hwif->sg_mapped = 1;- drive->dma = !hwif->dma_ops->dma_setup(drive);- if (scsi)- hwif->sg_mapped = 0;- }+ tf_flags = IDE_TFLAG_OUT_DEVICE;+ bcount = ((drive->media == ide_tape) ?+ pc->req_xfer :+ min(pc->req_xfer, 63 * 1024)); - if (!drive->dma)- pc->flags &= ~PC_FLAG_DMA_OK;+ if (pc->flags & PC_FLAG_DMA_ERROR) {+ pc->flags &= ~PC_FLAG_DMA_ERROR;+ ide_dma_off(drive);+ } - if (scsi)- tf_flags = 0;- else if (drive->media == ide_cdrom || drive->media == ide_optical)- tf_flags = IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL;- else- tf_flags = IDE_TFLAG_OUT_DEVICE;+ if ((pc->flags & PC_FLAG_DMA_OK) &&+ (drive->dev_flags & IDE_DFLAG_USING_DMA))+ drive->dma = !hwif->dma_ops->dma_setup(drive);++ if (!drive->dma)+ pc->flags &= ~PC_FLAG_DMA_OK;++ timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD+ : WAIT_TAPE_CMD;+ } ide_pktcmd_tf_load(drive, tf_flags, bcount, drive->dma); /* Issue the packet command */ if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {+ if (drive->dma)+ drive->waiting_for_dma = 0; ide_execute_command(drive, ATA_CMD_PACKET, ide_transfer_pc,- timeout, NULL);+ timeout, expiry); return ide_started; } else { ide_execute_pkt_cmd(drive);diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.cindex 5daa4dd..1a7410f 100644--- a/drivers/ide/ide-cd.c+++ b/drivers/ide/ide-cd.c@@ -53,14 +53,6 @@ #include "ide-cd.h" -#define IDECD_DEBUG_LOG 1--#if IDECD_DEBUG_LOG-#define ide_debug_log(lvl, fmt, args...) __ide_debug_log(lvl, fmt, args)-#else-#define ide_debug_log(lvl, fmt, args...) do {} while (0)-#endif- static DEFINE_MUTEX(idecd_ref_mutex); static void ide_cd_release(struct kref *);@@ -519,37 +511,8 @@ end_request: return 1; } -static int cdrom_timer_expiry(ide_drive_t *drive)-{- struct request *rq = HWGROUP(drive)->rq;- unsigned long wait = 0;-- ide_debug_log(IDE_DBG_RQ, "Call %s: rq->cmd[0]: 0x%x\n", __func__,- rq->cmd[0]);-- /*- * Some commands are *slow* and normally take a long time to complete.- * Usually we can use the ATAPI "disconnect" to bypass this, but not all- * commands/drives support that. Let ide_timer_expiry keep polling us- * for these.- */- switch (rq->cmd[0]) {- case GPCMD_BLANK:- case GPCMD_FORMAT_UNIT:- case GPCMD_RESERVE_RZONE_TRACK:- case GPCMD_CLOSE_TRACK:- case GPCMD_FLUSH_CACHE:- wait = ATAPI_WAIT_PC;- break;- default:- if (!(rq->cmd_flags & REQ_QUIET))- printk(KERN_INFO PFX "cmd 0x%x timed out\n",- rq->cmd[0]);- wait = 0;- break;- }- return wait;-}+static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *);+static ide_startstop_t cdrom_newpc_intr(ide_drive_t *); /* * Set up the device registers for transferring a packet command on DEV,@@ -559,11 +522,13 @@ static int cdrom_timer_expiry(ide_drive_t *drive) * called when the interrupt from the drive arrives. Otherwise, HANDLER * will be called immediately after the drive is prepared for the transfer. */-static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,- int xferlen,- ide_handler_t *handler)+static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif;+ struct request *rq = hwif->hwgroup->rq;+ int xferlen;++ xferlen = ide_cd_get_xferlen(rq); ide_debug_log(IDE_DBG_PC, "Call %s, xferlen: %d\n", __func__, xferlen); @@ -581,13 +546,14 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive, drive->waiting_for_dma = 0; /* packet command */- ide_execute_command(drive, ATA_CMD_PACKET, handler,- ATAPI_WAIT_PC, cdrom_timer_expiry);+ ide_execute_command(drive, ATA_CMD_PACKET,+ cdrom_transfer_packet_command,+ ATAPI_WAIT_PC, ide_cd_expiry); return ide_started; } else { ide_execute_pkt_cmd(drive); - return (*handler) (drive);+ return cdrom_transfer_packet_command(drive); } } @@ -598,11 +564,10 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive, * there's data ready. */ #define ATAPI_MIN_CDB_BYTES 12-static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive,- struct request *rq,- ide_handler_t *handler)+static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif;+ struct request *rq = hwif->hwgroup->rq; int cmd_len; ide_startstop_t startstop; @@ -629,7 +594,7 @@ static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive, } /* arm the interrupt handler */- ide_set_handler(drive, handler, rq->timeout, cdrom_timer_expiry);+ ide_set_handler(drive, cdrom_newpc_intr, rq->timeout, ide_cd_expiry); /* ATAPI commands get padded out to 12 bytes minimum */ cmd_len = COMMAND_SIZE(rq->cmd[0]);@@ -717,8 +682,6 @@ static int ide_cd_check_transfer_size(ide_drive_t *drive, int len) return 1; } -static ide_startstop_t cdrom_newpc_intr(ide_drive_t *);- static ide_startstop_t ide_cd_prepare_rw_request(ide_drive_t *drive, struct request *rq) {@@ -761,20 +724,6 @@ static ide_startstop_t ide_cd_prepare_rw_request(ide_drive_t *drive, } /*- * Routine to send a read/write packet command to the drive. This is usually- * called directly from cdrom_start_{read,write}(). However, for drq_interrupt- * devices, it is called from an interrupt when the drive is ready to accept- * the command.- */-static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive)-{- struct request *rq = drive->hwif->hwgroup->rq;-- /* send the command to the drive and return */- return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr);-}--/* * Fix up a possibly partially-processed request so that we can start it over * entirely, or even put it back on the request queue. */@@ -1096,7 +1045,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) } else { timeout = ATAPI_WAIT_PC; if (!blk_fs_request(rq))- expiry = cdrom_timer_expiry;+ expiry = ide_cd_expiry; } ide_set_handler(drive, cdrom_newpc_intr, timeout, expiry);@@ -1163,13 +1112,6 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq) return ide_started; } -static ide_startstop_t cdrom_do_newpc_cont(ide_drive_t *drive)-{- struct request *rq = HWGROUP(drive)->rq;-- return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr);-}- static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq) { @@ -1214,18 +1156,12 @@ static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq) static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq, sector_t block) {- ide_handler_t *fn;- int xferlen;- ide_debug_log(IDE_DBG_RQ, "Call %s, rq->cmd[0]: 0x%x, " "rq->cmd_type: 0x%x, block: %llu\n", __func__, rq->cmd[0], rq->cmd_type, (unsigned long long)block); if (blk_fs_request(rq)) {- xferlen = 32768;- fn = cdrom_start_rw_cont;- if (cdrom_start_rw(drive, rq) == ide_stopped) return ide_stopped; @@ -1233,9 +1169,6 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq, return ide_stopped; } else if (blk_sense_request(rq) || blk_pc_request(rq) || rq->cmd_type == REQ_TYPE_ATA_PC) {- xferlen = rq->data_len;- fn = cdrom_do_newpc_cont;- if (!rq->timeout) rq->timeout = ATAPI_WAIT_PC; @@ -1250,7 +1183,7 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq, return ide_stopped; } - return cdrom_start_packet_command(drive, xferlen, fn);+ return cdrom_start_packet_command(drive); } /*diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.hindex d5ce336..bf676b2 100644--- a/drivers/ide/ide-cd.h+++ b/drivers/ide/ide-cd.h@@ -8,10 +8,14 @@ #include <linux/cdrom.h> #include <asm/byteorder.h> -/*- * typical timeout for packet command- */-#define ATAPI_WAIT_PC (60 * HZ)+#define IDECD_DEBUG_LOG 0++#if IDECD_DEBUG_LOG+#define ide_debug_log(lvl, fmt, args...) __ide_debug_log(lvl, fmt, args)+#else+#define ide_debug_log(lvl, fmt, args...) do {} while (0)+#endif+ #define ATAPI_WAIT_WRITE_BUSY (10 * HZ) /************************************************************************/diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.cindex aeb1ad7..0a48e2d 100644--- a/drivers/ide/ide-floppy.c+++ b/drivers/ide/ide-floppy.c@@ -197,7 +197,7 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive, pc->retries++; - return ide_issue_pc(drive, WAIT_FLOPPY_CMD, NULL);+ return ide_issue_pc(drive); } void ide_floppy_create_read_capacity_cmd(struct ide_atapi_pc *pc)@@ -342,38 +342,38 @@ static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive, * Look at the flexible disk page parameters. We ignore the CHS capacity * parameters and use the LBA parameters instead. */-static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive)+static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive,+ struct ide_atapi_pc *pc) { struct ide_disk_obj *floppy = drive->driver_data; struct gendisk *disk = floppy->disk;- struct ide_atapi_pc pc; u8 *page; int capacity, lba_capacity; u16 transfer_rate, sector_size, cyls, rpm; u8 heads, sectors; - ide_floppy_create_mode_sense_cmd(&pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE);+ ide_floppy_create_mode_sense_cmd(pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE); - if (ide_queue_pc_tail(drive, disk, &pc)) {+ if (ide_queue_pc_tail(drive, disk, pc)) { printk(KERN_ERR PFX "Can't get flexible disk page params\n"); return 1; } - if (pc.buf[3] & 0x80)+ if (pc->buf[3] & 0x80) drive->dev_flags |= IDE_DFLAG_WP; else drive->dev_flags &= ~IDE_DFLAG_WP; set_disk_ro(disk, !!(drive->dev_flags & IDE_DFLAG_WP)); - page = &pc.buf[8];+ page = &pc->buf[8]; - transfer_rate = be16_to_cpup((__be16 *)&pc.buf[8 + 2]);- sector_size = be16_to_cpup((__be16 *)&pc.buf[8 + 6]);- cyls = be16_to_cpup((__be16 *)&pc.buf[8 + 8]);- rpm = be16_to_cpup((__be16 *)&pc.buf[8 + 28]);- heads = pc.buf[8 + 4];- sectors = pc.buf[8 + 5];+ transfer_rate = be16_to_cpup((__be16 *)&pc->buf[8 + 2]);+ sector_size = be16_to_cpup((__be16 *)&pc->buf[8 + 6]);+ cyls = be16_to_cpup((__be16 *)&pc->buf[8 + 8]);+ rpm = be16_to_cpup((__be16 *)&pc->buf[8 + 28]);+ heads = pc->buf[8 + 4];+ sectors = pc->buf[8 + 5]; capacity = cyls * heads * sectors * sector_size; @@ -499,7 +499,7 @@ static int ide_floppy_get_capacity(ide_drive_t *drive) /* Clik! disk does not support get_flexible_disk_page */ if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE))- (void) ide_floppy_get_flexible_disk_page(drive);+ (void) ide_floppy_get_flexible_disk_page(drive, &pc); return rc; }diff --git a/drivers/ide/ide-floppy_ioctl.c b/drivers/ide/ide-floppy_ioctl.cindex 2bc51ff..8f8be85 100644--- a/drivers/ide/ide-floppy_ioctl.c+++ b/drivers/ide/ide-floppy_ioctl.c@@ -31,10 +31,11 @@ * On exit we set nformats to the number of records we've actually initialized. */ -static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg)+static int ide_floppy_get_format_capacities(ide_drive_t *drive,+ struct ide_atapi_pc *pc,+ int __user *arg) { struct ide_disk_obj *floppy = drive->driver_data;- struct ide_atapi_pc pc; u8 header_len, desc_cnt; int i, blocks, length, u_array_size, u_index; int __user *argp;@@ -45,13 +46,13 @@ static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg) if (u_array_size <= 0) return -EINVAL; - ide_floppy_create_read_capacity_cmd(&pc);- if (ide_queue_pc_tail(drive, floppy->disk, &pc)) {+ ide_floppy_create_read_capacity_cmd(pc);+ if (ide_queue_pc_tail(drive, floppy->disk, pc)) { printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n"); return -EIO; } - header_len = pc.buf[3];+ header_len = pc->buf[3]; desc_cnt = header_len / 8; /* capacity descriptor of 8 bytes */ u_index = 0;@@ -68,8 +69,8 @@ static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg) if (u_index >= u_array_size) break; /* User-supplied buffer too small */ - blocks = be32_to_cpup((__be32 *)&pc.buf[desc_start]);- length = be16_to_cpup((__be16 *)&pc.buf[desc_start + 6]);+ blocks = be32_to_cpup((__be32 *)&pc->buf[desc_start]);+ length = be16_to_cpup((__be16 *)&pc->buf[desc_start + 6]); if (put_user(blocks, argp)) return -EFAULT;@@ -111,29 +112,28 @@ static void ide_floppy_create_format_unit_cmd(struct ide_atapi_pc *pc, int b, pc->flags |= PC_FLAG_WRITING; } -static int ide_floppy_get_sfrp_bit(ide_drive_t *drive)+static int ide_floppy_get_sfrp_bit(ide_drive_t *drive, struct ide_atapi_pc *pc) { struct ide_disk_obj *floppy = drive->driver_data;- struct ide_atapi_pc pc; drive->atapi_flags &= ~IDE_AFLAG_SRFP; - ide_floppy_create_mode_sense_cmd(&pc, IDEFLOPPY_CAPABILITIES_PAGE);- pc.flags |= PC_FLAG_SUPPRESS_ERROR;+ ide_floppy_create_mode_sense_cmd(pc, IDEFLOPPY_CAPABILITIES_PAGE);+ pc->flags |= PC_FLAG_SUPPRESS_ERROR; - if (ide_queue_pc_tail(drive, floppy->disk, &pc))+ if (ide_queue_pc_tail(drive, floppy->disk, pc)) return 1; - if (pc.buf[8 + 2] & 0x40)+ if (pc->buf[8 + 2] & 0x40) drive->atapi_flags |= IDE_AFLAG_SRFP; return 0; } -static int ide_floppy_format_unit(ide_drive_t *drive, int __user *arg)+static int ide_floppy_format_unit(ide_drive_t *drive, struct ide_atapi_pc *pc,+ int __user *arg) { struct ide_disk_obj *floppy = drive->driver_data;- struct ide_atapi_pc pc; int blocks, length, flags, err = 0; if (floppy->openers > 1) {@@ -166,10 +166,10 @@ static int ide_floppy_format_unit(ide_drive_t *drive, int __user *arg) goto out; } - (void)ide_floppy_get_sfrp_bit(drive);- ide_floppy_create_format_unit_cmd(&pc, blocks, length, flags);+ ide_floppy_get_sfrp_bit(drive, pc);+ ide_floppy_create_format_unit_cmd(pc, blocks, length, flags); - if (ide_queue_pc_tail(drive, floppy->disk, &pc))+ if (ide_queue_pc_tail(drive, floppy->disk, pc)) err = -EIO; out:@@ -188,15 +188,16 @@ out: * the dsc bit, and return either 0 or 65536. */ -static int ide_floppy_get_format_progress(ide_drive_t *drive, int __user *arg)+static int ide_floppy_get_format_progress(ide_drive_t *drive,+ struct ide_atapi_pc *pc,+ int __user *arg) { struct ide_disk_obj *floppy = drive->driver_data;- struct ide_atapi_pc pc; int progress_indication = 0x10000; if (drive->atapi_flags & IDE_AFLAG_SRFP) {- ide_create_request_sense_cmd(drive, &pc);- if (ide_queue_pc_tail(drive, floppy->disk, &pc))+ ide_create_request_sense_cmd(drive, pc);+ if (ide_queue_pc_tail(drive, floppy->disk, pc)) return -EIO; if (floppy->sense_key == 2 &&@@ -241,20 +242,21 @@ static int ide_floppy_lockdoor(ide_drive_t *drive, struct ide_atapi_pc *pc, return 0; } -static int ide_floppy_format_ioctl(ide_drive_t *drive, fmode_t mode,- unsigned int cmd, void __user *argp)+static int ide_floppy_format_ioctl(ide_drive_t *drive, struct ide_atapi_pc *pc,+ fmode_t mode, unsigned int cmd,+ void __user *argp) { switch (cmd) { case IDEFLOPPY_IOCTL_FORMAT_SUPPORTED: return 0; case IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY:- return ide_floppy_get_format_capacities(drive, argp);+ return ide_floppy_get_format_capacities(drive, pc, argp); case IDEFLOPPY_IOCTL_FORMAT_START: if (!(mode & FMODE_WRITE)) return -EPERM;- return ide_floppy_format_unit(drive, (int __user *)argp);+ return ide_floppy_format_unit(drive, pc, (int __user *)argp); case IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS:- return ide_floppy_get_format_progress(drive, argp);+ return ide_floppy_get_format_progress(drive, pc, argp); default: return -ENOTTY; }@@ -270,7 +272,7 @@ int ide_floppy_ioctl(ide_drive_t *drive, struct block_device *bdev, if (cmd == CDROMEJECT || cmd == CDROM_LOCKDOOR) return ide_floppy_lockdoor(drive, &pc, arg, cmd); - err = ide_floppy_format_ioctl(drive, mode, cmd, argp);+ err = ide_floppy_format_ioctl(drive, &pc, mode, cmd, argp); if (err != -ENOTTY) return err; diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.cindex ecacc00..1c36a8e 100644--- a/drivers/ide/ide-io.c+++ b/drivers/ide/ide-io.c@@ -426,9 +426,6 @@ void ide_map_sg(ide_drive_t *drive, struct request *rq) ide_hwif_t *hwif = drive->hwif; struct scatterlist *sg = hwif->sg_table; - if (hwif->sg_mapped) /* needed by ide-scsi */- return;- if (rq->cmd_type != REQ_TYPE_ATA_TASKFILE) { hwif->sg_nents = blk_rq_map_sg(drive->queue, rq, sg); } else {@@ -667,85 +664,10 @@ void ide_stall_queue (ide_drive_t *drive, unsigned long timeout) drive->sleep = timeout + jiffies; drive->dev_flags |= IDE_DFLAG_SLEEPING; }- EXPORT_SYMBOL(ide_stall_queue); -#define WAKEUP(drive) ((drive)->service_start + 2 * (drive)->service_time)--/**- * choose_drive - select a drive to service- * @hwgroup: hardware group to select on- *- * choose_drive() selects the next drive which will be serviced.- * This is necessary because the IDE layer can't issue commands- * to both drives on the same cable, unlike SCSI.- */- -static inline ide_drive_t *choose_drive (ide_hwgroup_t *hwgroup)-{- ide_drive_t *drive, *best;--repeat: - best = NULL;- drive = hwgroup->drive;-- /*- * drive is doing pre-flush, ordered write, post-flush sequence. even- * though that is 3 requests, it must be seen as a single transaction.- * we must not preempt this drive until that is complete- */- if (blk_queue_flushing(drive->queue)) {- /*- * small race where queue could get replugged during- * the 3-request flush cycle, just yank the plug since- * we want it to finish asap- */- blk_remove_plug(drive->queue);- return drive;- }-- do {- u8 dev_s = !!(drive->dev_flags & IDE_DFLAG_SLEEPING);- u8 best_s = (best && !!(best->dev_flags & IDE_DFLAG_SLEEPING));-- if ((dev_s == 0 || time_after_eq(jiffies, drive->sleep)) &&- !elv_queue_empty(drive->queue)) {- if (best == NULL ||- (dev_s && (best_s == 0 || time_before(drive->sleep, best->sleep))) ||- (best_s == 0 && time_before(WAKEUP(drive), WAKEUP(best)))) {- if (!blk_queue_plugged(drive->queue))- best = drive;- }- }- } while ((drive = drive->next) != hwgroup->drive);-- if (best && (best->dev_flags & IDE_DFLAG_NICE1) &&- (best->dev_flags & IDE_DFLAG_SLEEPING) == 0 &&- best != hwgroup->drive && best->service_time > WAIT_MIN_SLEEP) {- long t = (signed long)(WAKEUP(best) - jiffies);- if (t >= WAIT_MIN_SLEEP) {- /*- * We *may* have some time to spare, but first let's see if- * someone can potentially benefit from our nice mood today..- */- drive = best->next;- do {- if ((drive->dev_flags & IDE_DFLAG_SLEEPING) == 0- && time_before(jiffies - best->service_time, WAKEUP(drive))- && time_before(WAKEUP(drive), jiffies + t))- {- ide_stall_queue(best, min_t(long, t, 10 * WAIT_MIN_SLEEP));- goto repeat;- }- } while ((drive = drive->next) != best);- }- }- return best;-}- /* * Issue a new request to a drive from hwgroup- * Caller must have already done spin_lock_irqsave(&hwgroup->lock, ..); * * A hwgroup is a serialized group of IDE interfaces. Usually there is * exactly one hwif (interface) per hwgroup, but buggy controllers (eg. CMD640)@@ -757,8 +679,7 @@ repeat: * possibly along with many other devices. This is especially common in * PCI-based systems with off-board IDE controller cards. *- * The IDE driver uses a per-hwgroup spinlock to protect- * access to the request queues, and to protect the hwgroup->busy flag.+ * The IDE driver uses a per-hwgroup lock to protect the hwgroup->busy flag. * * The first thread into the driver for a particular hwgroup sets the * hwgroup->busy flag to indicate that this hwgroup is now active,@@ -778,69 +699,41 @@ repeat: * the driver. This makes the driver much more friendlier to shared IRQs * than previous designs, while remaining 100% (?) SMP safe and capable. */-static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)+void do_ide_request(struct request_queue *q) {- ide_drive_t *drive;- ide_hwif_t *hwif;+ ide_drive_t *drive = q->queuedata;+ ide_hwif_t *hwif = drive->hwif;+ ide_hwgroup_t *hwgroup = hwif->hwgroup; struct request *rq; ide_startstop_t startstop;- int loops = 0;-- /* caller must own hwgroup->lock */- BUG_ON(!irqs_disabled());-- while (!hwgroup->busy) {- hwgroup->busy = 1;- /* for atari only */- ide_get_lock(ide_intr, hwgroup);- drive = choose_drive(hwgroup);- if (drive == NULL) {- int sleeping = 0;- unsigned long sleep = 0; /* shut up, gcc */- hwgroup->rq = NULL;- drive = hwgroup->drive;- do {- if ((drive->dev_flags & IDE_DFLAG_SLEEPING) &&- (sleeping == 0 ||- time_before(drive->sleep, sleep))) {- sleeping = 1;- sleep = drive->sleep;- }- } while ((drive = drive->next) != hwgroup->drive);- if (sleeping) {++ /*+ * drive is doing pre-flush, ordered write, post-flush sequence. even+ * though that is 3 requests, it must be seen as a single transaction.+ * we must not preempt this drive until that is complete+ */+ if (blk_queue_flushing(q)) /*- * Take a short snooze, and then wake up this hwgroup again.- * This gives other hwgroups on the same a chance to- * play fairly with us, just in case there are big differences- * in relative throughputs.. don't want to hog the cpu too much.+ * small race where queue could get replugged during+ * the 3-request flush cycle, just yank the plug since+ * we want it to finish asap */- if (time_before(sleep, jiffies + WAIT_MIN_SLEEP))- sleep = jiffies + WAIT_MIN_SLEEP;-#if 1- if (timer_pending(&hwgroup->timer))- printk(KERN_CRIT "ide_set_handler: timer already active\n");-#endif- /* so that ide_timer_expiry knows what to do */- hwgroup->sleeping = 1;- hwgroup->req_gen_timer = hwgroup->req_gen;- mod_timer(&hwgroup->timer, sleep);- /* we purposely leave hwgroup->busy==1- * while sleeping */- } else {- /* Ugly, but how can we sleep for the lock- * otherwise? perhaps from tq_disk?- */+ blk_remove_plug(q); - /* for atari only */- ide_release_lock();- hwgroup->busy = 0;- }+ spin_unlock_irq(q->queue_lock);+ spin_lock_irq(&hwgroup->lock);++ if (!ide_lock_hwgroup(hwgroup)) {+repeat:+ hwgroup->rq = NULL; - /* no more work for this hwgroup (for now) */- return;+ if (drive->dev_flags & IDE_DFLAG_SLEEPING) {+ if (time_before(drive->sleep, jiffies)) {+ ide_unlock_hwgroup(hwgroup);+ goto plug_device;+ } }- again:- hwif = HWIF(drive);+ if (hwif != hwgroup->hwif) { /* * set nIEN for previous hwif, drives in the@@ -852,16 +745,20 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq) hwgroup->hwif = hwif; hwgroup->drive = drive; drive->dev_flags &= ~(IDE_DFLAG_SLEEPING | IDE_DFLAG_PARKED);- drive->service_start = jiffies; + spin_unlock_irq(&hwgroup->lock);+ spin_lock_irq(q->queue_lock); /* * we know that the queue isn't empty, but this can happen * if the q->prep_rq_fn() decides to kill a request */ rq = elv_next_request(drive->queue);+ spin_unlock_irq(q->queue_lock);+ spin_lock_irq(&hwgroup->lock);+ if (!rq) {- hwgroup->busy = 0;- break;+ ide_unlock_hwgroup(hwgroup);+ goto out; } /*@@ -876,53 +773,36 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq) * though. I hope that doesn't happen too much, hopefully not * unless the subdriver triggers such a thing in its own PM * state machine.- *- * We count how many times we loop here to make sure we service- * all drives in the hwgroup without looping for ever */ if ((drive->dev_flags & IDE_DFLAG_BLOCKED) && blk_pm_request(rq) == 0 && (rq->cmd_flags & REQ_PREEMPT) == 0) {- drive = drive->next ? drive->next : hwgroup->drive;- if (loops++ < 4 && !blk_queue_plugged(drive->queue))- goto again;- /* We clear busy, there should be no pending ATA command at this point. */- hwgroup->busy = 0;- break;+ /* there should be no pending command at this point */+ ide_unlock_hwgroup(hwgroup);+ goto plug_device; } hwgroup->rq = rq; - /*- * Some systems have trouble with IDE IRQs arriving while- * the driver is still setting things up. So, here we disable- * the IRQ used by this interface while the request is being started.- * This may look bad at first, but pretty much the same thing- * happens anyway when any interrupt comes in, IDE or otherwise- * -- the kernel masks the IRQ while it is being handled.- */- if (masked_irq != IDE_NO_IRQ && hwif->irq != masked_irq)- disable_irq_nosync(hwif->irq);- spin_unlock(&hwgroup->lock);- local_irq_enable_in_hardirq();- /* allow other IRQs while we start this request */+ spin_unlock_irq(&hwgroup->lock); startstop = start_request(drive, rq); spin_lock_irq(&hwgroup->lock);- if (masked_irq != IDE_NO_IRQ && hwif->irq != masked_irq)- enable_irq(hwif->irq);+ if (startstop == ide_stopped)- hwgroup->busy = 0;- }-}+ goto repeat;+ } else+ goto plug_device;+out:+ spin_unlock_irq(&hwgroup->lock);+ spin_lock_irq(q->queue_lock);+ return; -/*- * Passes the stuff to ide_do_request- */-void do_ide_request(struct request_queue *q)-{- ide_drive_t *drive = q->queuedata;+plug_device:+ spin_unlock_irq(&hwgroup->lock);+ spin_lock_irq(q->queue_lock); - ide_do_request(HWGROUP(drive), IDE_NO_IRQ);+ if (!elv_queue_empty(q))+ blk_plug_device(q); } /*@@ -983,6 +863,17 @@ out: return ret; } +static void ide_plug_device(ide_drive_t *drive)+{+ struct request_queue *q = drive->queue;+ unsigned long flags;++ spin_lock_irqsave(q->queue_lock, flags);+ if (!elv_queue_empty(q))+ blk_plug_device(q);+ spin_unlock_irqrestore(q->queue_lock, flags);+}+ /** * ide_timer_expiry - handle lack of an IDE interrupt * @data: timer callback magic (hwgroup)@@ -1000,10 +891,12 @@ out: void ide_timer_expiry (unsigned long data) { ide_hwgroup_t *hwgroup = (ide_hwgroup_t *) data;+ ide_drive_t *uninitialized_var(drive); ide_handler_t *handler; ide_expiry_t *expiry; unsigned long flags; unsigned long wait = -1;+ int plug_device = 0; spin_lock_irqsave(&hwgroup->lock, flags); @@ -1015,22 +908,15 @@ void ide_timer_expiry (unsigned long data) * or we were "sleeping" to give other devices a chance. * Either way, we don't really want to complain about anything. */- if (hwgroup->sleeping) {- hwgroup->sleeping = 0;- hwgroup->busy = 0;- } } else {- ide_drive_t *drive = hwgroup->drive;+ drive = hwgroup->drive; if (!drive) { printk(KERN_ERR "ide_timer_expiry: hwgroup->drive was NULL\n"); hwgroup->handler = NULL; } else { ide_hwif_t *hwif; ide_startstop_t startstop = ide_stopped;- if (!hwgroup->busy) {- hwgroup->busy = 1; /* paranoia */- printk(KERN_ERR "%s: ide_timer_expiry: hwgroup->busy was 0 ??\n", drive->name);- }+ if ((expiry = hwgroup->expiry) != NULL) { /* continue */ if ((wait = expiry(drive)) > 0) {@@ -1071,15 +957,18 @@ void ide_timer_expiry (unsigned long data) ide_error(drive, "irq timeout", hwif->tp_ops->read_status(hwif)); }- drive->service_time = jiffies - drive->service_start; spin_lock_irq(&hwgroup->lock); enable_irq(hwif->irq);- if (startstop == ide_stopped)- hwgroup->busy = 0;+ if (startstop == ide_stopped) {+ ide_unlock_hwgroup(hwgroup);+ plug_device = 1;+ } } }- ide_do_request(hwgroup, IDE_NO_IRQ); spin_unlock_irqrestore(&hwgroup->lock, flags);++ if (plug_device)+ ide_plug_device(drive); } /**@@ -1173,10 +1062,11 @@ irqreturn_t ide_intr (int irq, void *dev_id) unsigned long flags; ide_hwgroup_t *hwgroup = (ide_hwgroup_t *)dev_id; ide_hwif_t *hwif = hwgroup->hwif;- ide_drive_t *drive;+ ide_drive_t *uninitialized_var(drive); ide_handler_t *handler; ide_startstop_t startstop; irqreturn_t irq_ret = IRQ_NONE;+ int plug_device = 0; spin_lock_irqsave(&hwgroup->lock, flags); @@ -1241,10 +1131,6 @@ irqreturn_t ide_intr (int irq, void *dev_id) */ goto out; - if (!hwgroup->busy) {- hwgroup->busy = 1; /* paranoia */- printk(KERN_ERR "%s: ide_intr: hwgroup->busy was 0 ??\n", drive->name);- } hwgroup->handler = NULL; hwgroup->req_gen++; del_timer(&hwgroup->timer);@@ -1267,20 +1153,22 @@ irqreturn_t ide_intr (int irq, void *dev_id) * same irq as is currently being serviced here, and Linux * won't allow another of the same (on any CPU) until we return. */- drive->service_time = jiffies - drive->service_start; if (startstop == ide_stopped) { if (hwgroup->handler == NULL) { /* paranoia */- hwgroup->busy = 0;- ide_do_request(hwgroup, hwif->irq);- } else {- printk(KERN_ERR "%s: ide_intr: huh? expected NULL handler "- "on exit\n", drive->name);- }+ ide_unlock_hwgroup(hwgroup);+ plug_device = 1;+ } else+ printk(KERN_ERR "%s: %s: huh? expected NULL handler "+ "on exit\n", __func__, drive->name); } out_handled: irq_ret = IRQ_HANDLED; out: spin_unlock_irqrestore(&hwgroup->lock, flags);++ if (plug_device)+ ide_plug_device(drive);+ return irq_ret; } diff --git a/drivers/ide/ide-ioctls.c b/drivers/ide/ide-ioctls.cindex 28232c6..1be263e 100644--- a/drivers/ide/ide-ioctls.c+++ b/drivers/ide/ide-ioctls.c@@ -95,8 +95,7 @@ static int ide_set_nice_ioctl(ide_drive_t *drive, unsigned long arg) return -EPERM; if (((arg >> IDE_NICE_DSC_OVERLAP) & 1) &&- (drive->media != ide_tape ||- (drive->dev_flags & IDE_DFLAG_SCSI)))+ (drive->media != ide_tape)) return -EPERM; if ((arg >> IDE_NICE_DSC_OVERLAP) & 1)diff --git a/drivers/ide/ide-park.c b/drivers/ide/ide-park.cindex 63d01c5..678454a 100644--- a/drivers/ide/ide-park.c+++ b/drivers/ide/ide-park.c@@ -16,16 +16,19 @@ static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout) spin_lock_irq(&hwgroup->lock); if (drive->dev_flags & IDE_DFLAG_PARKED) { int reset_timer = time_before(timeout, drive->sleep);+ int start_queue = 0; drive->sleep = timeout; wake_up_all(&ide_park_wq);- if (reset_timer && hwgroup->sleeping &&- del_timer(&hwgroup->timer)) {- hwgroup->sleeping = 0;- hwgroup->busy = 0;+ if (reset_timer && del_timer(&hwgroup->timer))+ start_queue = 1;+ spin_unlock_irq(&hwgroup->lock);++ if (start_queue) {+ spin_lock_irq(q->queue_lock); blk_start_queueing(q);+ spin_unlock_irq(q->queue_lock); }- spin_unlock_irq(&hwgroup->lock); return; } spin_unlock_irq(&hwgroup->lock);diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.cindex a64ec25..c5adb7b 100644--- a/drivers/ide/ide-probe.c+++ b/drivers/ide/ide-probe.c@@ -101,6 +101,82 @@ static void ide_disk_init_mult_count(ide_drive_t *drive) } } +static void ide_classify_ata_dev(ide_drive_t *drive)+{+ u16 *id = drive->id;+ char *m = (char *)&id[ATA_ID_PROD];+ int is_cfa = ata_id_is_cfa(id);++ /* CF devices are *not* removable in Linux definition of the term */+ if (is_cfa == 0 && (id[ATA_ID_CONFIG] & (1 << 7)))+ drive->dev_flags |= IDE_DFLAG_REMOVABLE;++ drive->media = ide_disk;++ if (!ata_id_has_unload(drive->id))+ drive->dev_flags |= IDE_DFLAG_NO_UNLOAD;++ printk(KERN_INFO "%s: %s, %s DISK drive\n", drive->name, m,+ is_cfa ? "CFA" : "ATA");+}++static void ide_classify_atapi_dev(ide_drive_t *drive)+{+ u16 *id = drive->id;+ char *m = (char *)&id[ATA_ID_PROD];+ u8 type = (id[ATA_ID_CONFIG] >> 8) & 0x1f;++ printk(KERN_INFO "%s: %s, ATAPI ", drive->name, m);+ switch (type) {+ case ide_floppy:+ if (!strstr(m, "CD-ROM")) {+ if (!strstr(m, "oppy") &&+ !strstr(m, "poyp") &&+ !strstr(m, "ZIP"))+ printk(KERN_CONT "cdrom or floppy?, assuming ");+ if (drive->media != ide_cdrom) {+ printk(KERN_CONT "FLOPPY");+ drive->dev_flags |= IDE_DFLAG_REMOVABLE;+ break;+ }+ }+ /* Early cdrom models used zero */+ type = ide_cdrom;+ case ide_cdrom:+ drive->dev_flags |= IDE_DFLAG_REMOVABLE;+#ifdef CONFIG_PPC+ /* kludge for Apple PowerBook internal zip */+ if (!strstr(m, "CD-ROM") && strstr(m, "ZIP")) {+ printk(KERN_CONT "FLOPPY");+ type = ide_floppy;+ break;+ }+#endif+ printk(KERN_CONT "CD/DVD-ROM");+ break;+ case ide_tape:+ printk(KERN_CONT "TAPE");+ break;+ case ide_optical:+ printk(KERN_CONT "OPTICAL");+ drive->dev_flags |= IDE_DFLAG_REMOVABLE;+ break;+ default:+ printk(KERN_CONT "UNKNOWN (type %d)", type);+ break;+ }++ printk(KERN_CONT " drive\n");+ drive->media = type;+ /* an ATAPI device ignores DRDY */+ drive->ready_stat = 0;+ if (ata_id_cdb_intr(id))+ drive->atapi_flags |= IDE_AFLAG_DRQ_INTERRUPT;+ drive->dev_flags |= IDE_DFLAG_DOORLOCKING;+ /* we don't do head unloading on ATAPI devices */+ drive->dev_flags |= IDE_DFLAG_NO_UNLOAD;+}+ /** * do_identify - identify a drive * @drive: drive to identify @@ -117,7 +193,7 @@ static void do_identify(ide_drive_t *drive, u8 cmd) u16 *id = drive->id; char *m = (char *)&id[ATA_ID_PROD]; unsigned long flags;- int bswap = 1, is_cfa;+ int bswap = 1; /* local CPU only; some systems need this */ local_irq_save(flags);@@ -154,91 +230,23 @@ static void do_identify(ide_drive_t *drive, u8 cmd) if (strstr(m, "E X A B Y T E N E S T")) goto err_misc; - printk(KERN_INFO "%s: %s, ", drive->name, m);- drive->dev_flags |= IDE_DFLAG_PRESENT; drive->dev_flags &= ~IDE_DFLAG_DEAD; /* * Check for an ATAPI device */- if (cmd == ATA_CMD_ID_ATAPI) {- u8 type = (id[ATA_ID_CONFIG] >> 8) & 0x1f;-- printk(KERN_CONT "ATAPI ");- switch (type) {- case ide_floppy:- if (!strstr(m, "CD-ROM")) {- if (!strstr(m, "oppy") &&- !strstr(m, "poyp") &&- !strstr(m, "ZIP"))- printk(KERN_CONT "cdrom or floppy?, assuming ");- if (drive->media != ide_cdrom) {- printk(KERN_CONT "FLOPPY");- drive->dev_flags |= IDE_DFLAG_REMOVABLE;- break;- }- }- /* Early cdrom models used zero */- type = ide_cdrom;- case ide_cdrom:- drive->dev_flags |= IDE_DFLAG_REMOVABLE;-#ifdef CONFIG_PPC- /* kludge for Apple PowerBook internal zip */- if (!strstr(m, "CD-ROM") && strstr(m, "ZIP")) {- printk(KERN_CONT "FLOPPY");- type = ide_floppy;- break;- }-#endif- printk(KERN_CONT "CD/DVD-ROM");- break;- case ide_tape:- printk(KERN_CONT "TAPE");- break;- case ide_optical:- printk(KERN_CONT "OPTICAL");- drive->dev_flags |= IDE_DFLAG_REMOVABLE;- break;- default:- printk(KERN_CONT "UNKNOWN (type %d)", type);- break;- }- printk(KERN_CONT " drive\n");- drive->media = type;- /* an ATAPI device ignores DRDY */- drive->ready_stat = 0;- if (ata_id_cdb_intr(id))- drive->atapi_flags |= IDE_AFLAG_DRQ_INTERRUPT;- drive->dev_flags |= IDE_DFLAG_DOORLOCKING;- /* we don't do head unloading on ATAPI devices */- drive->dev_flags |= IDE_DFLAG_NO_UNLOAD;- return;- }-+ if (cmd == ATA_CMD_ID_ATAPI)+ ide_classify_atapi_dev(drive);+ else /* * Not an ATAPI device: looks like a "regular" hard disk */-- is_cfa = ata_id_is_cfa(id);-- /* CF devices are *not* removable in Linux definition of the term */- if (is_cfa == 0 && (id[ATA_ID_CONFIG] & (1 << 7)))- drive->dev_flags |= IDE_DFLAG_REMOVABLE;-- drive->media = ide_disk;-- if (!ata_id_has_unload(drive->id))- drive->dev_flags |= IDE_DFLAG_NO_UNLOAD;-- printk(KERN_CONT "%s DISK drive\n", is_cfa ? "CFA" : "ATA");-+ ide_classify_ata_dev(drive); return;- err_misc: kfree(id); drive->dev_flags &= ~IDE_DFLAG_PRESENT;- return; } /**@@ -641,14 +649,9 @@ static int ide_register_port(ide_hwif_t *hwif) /* register with global device tree */ dev_set_name(&hwif->gendev, hwif->name); hwif->gendev.driver_data = hwif;- if (hwif->gendev.parent == NULL) {- if (hwif->dev)- hwif->gendev.parent = hwif->dev;- else- /* Would like to do = &device_legacy */- hwif->gendev.parent = NULL;- }+ hwif->gendev.parent = hwif->dev; hwif->gendev.release = hwif_release_dev;+ ret = device_register(&hwif->gendev); if (ret < 0) { printk(KERN_WARNING "IDE: %s: device_register error: %d\n",@@ -878,8 +881,7 @@ static int ide_init_queue(ide_drive_t *drive) * do not. */ - q = blk_init_queue_node(do_ide_request, &hwif->hwgroup->lock,- hwif_to_node(hwif));+ q = blk_init_queue_node(do_ide_request, NULL, hwif_to_node(hwif)); if (!q) return 1; @@ -1139,8 +1141,6 @@ static struct kobject *ata_probe(dev_t dev, int *part, void *data) if (drive->media == ide_disk) request_module("ide-disk");- if (drive->dev_flags & IDE_DFLAG_SCSI)- request_module("ide-scsi"); if (drive->media == ide_cdrom || drive->media == ide_optical) request_module("ide-cd"); if (drive->media == ide_tape)@@ -1417,58 +1417,6 @@ static void ide_port_cable_detect(ide_hwif_t *hwif) } } -static ssize_t store_delete_devices(struct device *portdev,- struct device_attribute *attr,- const char *buf, size_t n)-{- ide_hwif_t *hwif = dev_get_drvdata(portdev);-- if (strncmp(buf, "1", n))- return -EINVAL;-- ide_port_unregister_devices(hwif);-- return n;-};--static DEVICE_ATTR(delete_devices, S_IWUSR, NULL, store_delete_devices);--static ssize_t store_scan(struct device *portdev,- struct device_attribute *attr,- const char *buf, size_t n)-{- ide_hwif_t *hwif = dev_get_drvdata(portdev);-- if (strncmp(buf, "1", n))- return -EINVAL;-- ide_port_unregister_devices(hwif);- ide_port_scan(hwif);-- return n;-};--static DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan);--static struct device_attribute *ide_port_attrs[] = {- &dev_attr_delete_devices,- &dev_attr_scan,- NULL-};--static int ide_sysfs_register_port(ide_hwif_t *hwif)-{- int i, uninitialized_var(rc);-- for (i = 0; ide_port_attrs[i]; i++) {- rc = device_create_file(hwif->portdev, ide_port_attrs[i]);- if (rc)- break;- }-- return rc;-}- static unsigned int ide_indexes; /**@@ -1655,9 +1603,6 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d, if (hwif == NULL) continue; - if (hwif->chipset == ide_unknown)- hwif->chipset = ide_generic;- if (hwif->present) hwif_register_devices(hwif); }diff --git a/drivers/ide/ide-sysfs.c b/drivers/ide/ide-sysfs.cnew file mode 100644index 0000000..883ffac--- /dev/null+++ b/drivers/ide/ide-sysfs.c@@ -0,0 +1,125 @@+#include <linux/kernel.h>+#include <linux/ide.h>++char *ide_media_string(ide_drive_t *drive)+{+ switch (drive->media) {+ case ide_disk:+ return "disk";+ case ide_cdrom:+ return "cdrom";+ case ide_tape:+ return "tape";+ case ide_floppy:+ return "floppy";+ case ide_optical:+ return "optical";+ default:+ return "UNKNOWN";+ }+}++static ssize_t media_show(struct device *dev, struct device_attribute *attr,+ char *buf)+{+ ide_drive_t *drive = to_ide_device(dev);+ return sprintf(buf, "%s\n", ide_media_string(drive));+}++static ssize_t drivename_show(struct device *dev, struct device_attribute *attr,+ char *buf)+{+ ide_drive_t *drive = to_ide_device(dev);+ return sprintf(buf, "%s\n", drive->name);+}++static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,+ char *buf)+{+ ide_drive_t *drive = to_ide_device(dev);+ return sprintf(buf, "ide:m-%s\n", ide_media_string(drive));+}++static ssize_t model_show(struct device *dev, struct device_attribute *attr,+ char *buf)+{+ ide_drive_t *drive = to_ide_device(dev);+ return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_PROD]);+}++static ssize_t firmware_show(struct device *dev, struct device_attribute *attr,+ char *buf)+{+ ide_drive_t *drive = to_ide_device(dev);+ return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_FW_REV]);+}++static ssize_t serial_show(struct device *dev, struct device_attribute *attr,+ char *buf)+{+ ide_drive_t *drive = to_ide_device(dev);+ return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_SERNO]);+}++struct device_attribute ide_dev_attrs[] = {+ __ATTR_RO(media),+ __ATTR_RO(drivename),+ __ATTR_RO(modalias),+ __ATTR_RO(model),+ __ATTR_RO(firmware),+ __ATTR(serial, 0400, serial_show, NULL),+ __ATTR(unload_heads, 0644, ide_park_show, ide_park_store),+ __ATTR_NULL+};++static ssize_t store_delete_devices(struct device *portdev,+ struct device_attribute *attr,+ const char *buf, size_t n)+{+ ide_hwif_t *hwif = dev_get_drvdata(portdev);++ if (strncmp(buf, "1", n))+ return -EINVAL;++ ide_port_unregister_devices(hwif);++ return n;+};++static DEVICE_ATTR(delete_devices, S_IWUSR, NULL, store_delete_devices);++static ssize_t store_scan(struct device *portdev,+ struct device_attribute *attr,+ const char *buf, size_t n)+{+ ide_hwif_t *hwif = dev_get_drvdata(portdev);++ if (strncmp(buf, "1", n))+ return -EINVAL;++ ide_port_unregister_devices(hwif);+ ide_port_scan(hwif);++ return n;+};++static DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan);++static struct device_attribute *ide_port_attrs[] = {+ &dev_attr_delete_devices,+ &dev_attr_scan,+ NULL+};++int ide_sysfs_register_port(ide_hwif_t *hwif)+{+ int i, uninitialized_var(rc);++ for (i = 0; ide_port_attrs[i]; i++) {+ rc = device_create_file(hwif->portdev, ide_port_attrs[i]);+ if (rc)+ break;+ }++ return rc;+}diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.cindex a2d470e..5d2aa22 100644--- a/drivers/ide/ide-tape.c+++ b/drivers/ide/ide-tape.c@@ -694,7 +694,7 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive, pc->retries++; - return ide_issue_pc(drive, WAIT_TAPE_CMD, NULL);+ return ide_issue_pc(drive); } /* A mode sense command is used to "sense" tape parameters. */diff --git a/drivers/ide/ide.c b/drivers/ide/ide.cindex f0f09f7..46a2d4c 100644--- a/drivers/ide/ide.c+++ b/drivers/ide/ide.c@@ -440,81 +440,13 @@ static int ide_bus_match(struct device *dev, struct device_driver *drv) return 1; } -static char *media_string(ide_drive_t *drive)-{- switch (drive->media) {- case ide_disk:- return "disk";- case ide_cdrom:- return "cdrom";- case ide_tape:- return "tape";- case ide_floppy:- return "floppy";- case ide_optical:- return "optical";- default:- return "UNKNOWN";- }-}--static ssize_t media_show(struct device *dev, struct device_attribute *attr, char *buf)-{- ide_drive_t *drive = to_ide_device(dev);- return sprintf(buf, "%s\n", media_string(drive));-}--static ssize_t drivename_show(struct device *dev, struct device_attribute *attr, char *buf)-{- ide_drive_t *drive = to_ide_device(dev);- return sprintf(buf, "%s\n", drive->name);-}--static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf)-{- ide_drive_t *drive = to_ide_device(dev);- return sprintf(buf, "ide:m-%s\n", media_string(drive));-}--static ssize_t model_show(struct device *dev, struct device_attribute *attr,- char *buf)-{- ide_drive_t *drive = to_ide_device(dev);- return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_PROD]);-}--static ssize_t firmware_show(struct device *dev, struct device_attribute *attr,- char *buf)-{- ide_drive_t *drive = to_ide_device(dev);- return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_FW_REV]);-}--static ssize_t serial_show(struct device *dev, struct device_attribute *attr,- char *buf)-{- ide_drive_t *drive = to_ide_device(dev);- return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_SERNO]);-}--static struct device_attribute ide_dev_attrs[] = {- __ATTR_RO(media),- __ATTR_RO(drivename),- __ATTR_RO(modalias),- __ATTR_RO(model),- __ATTR_RO(firmware),- __ATTR(serial, 0400, serial_show, NULL),- __ATTR(unload_heads, 0644, ide_park_show, ide_park_store),- __ATTR_NULL-};- static int ide_uevent(struct device *dev, struct kobj_uevent_env *env) { ide_drive_t *drive = to_ide_device(dev); - add_uevent_var(env, "MEDIA=%s", media_string(drive));+ add_uevent_var(env, "MEDIA=%s", ide_media_string(drive)); add_uevent_var(env, "DRIVENAME=%s", drive->name);- add_uevent_var(env, "MODALIAS=ide:m-%s", media_string(drive));+ add_uevent_var(env, "MODALIAS=ide:m-%s", ide_media_string(drive)); return 0; } diff --git a/drivers/ide/tx4938ide.c b/drivers/ide/tx4938ide.cindex 13b63e7..b4ef218 100644--- a/drivers/ide/tx4938ide.c+++ b/drivers/ide/tx4938ide.c@@ -216,16 +216,17 @@ static const struct ide_tp_ops tx4938ide_tp_ops = { #endif /* __BIG_ENDIAN */ static const struct ide_port_ops tx4938ide_port_ops = {- .set_pio_mode = tx4938ide_set_pio_mode,+ .set_pio_mode = tx4938ide_set_pio_mode, }; static const struct ide_port_info tx4938ide_port_info __initdata = {- .port_ops = &tx4938ide_port_ops,+ .port_ops = &tx4938ide_port_ops, #ifdef __BIG_ENDIAN- .tp_ops = &tx4938ide_tp_ops,+ .tp_ops = &tx4938ide_tp_ops, #endif- .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA,- .pio_mask = ATA_PIO5,+ .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA,+ .pio_mask = ATA_PIO5,+ .chipset = ide_generic, }; static int __init tx4938ide_probe(struct platform_device *pdev)diff --git a/drivers/ide/tx4939ide.c b/drivers/ide/tx4939ide.cindex 97cd9e0..4a8c5a2 100644--- a/drivers/ide/tx4939ide.c+++ b/drivers/ide/tx4939ide.c@@ -623,33 +623,34 @@ static const struct ide_tp_ops tx4939ide_tp_ops = { #endif /* __LITTLE_ENDIAN */ static const struct ide_port_ops tx4939ide_port_ops = {- .set_pio_mode = tx4939ide_set_pio_mode,- .set_dma_mode = tx4939ide_set_dma_mode,- .clear_irq = tx4939ide_clear_irq,- .cable_detect = tx4939ide_cable_detect,+ .set_pio_mode = tx4939ide_set_pio_mode,+ .set_dma_mode = tx4939ide_set_dma_mode,+ .clear_irq = tx4939ide_clear_irq,+ .cable_detect = tx4939ide_cable_detect, }; static const struct ide_dma_ops tx4939ide_dma_ops = {- .dma_host_set = tx4939ide_dma_host_set,- .dma_setup = tx4939ide_dma_setup,- .dma_exec_cmd = ide_dma_exec_cmd,- .dma_start = ide_dma_start,- .dma_end = tx4939ide_dma_end,- .dma_test_irq = tx4939ide_dma_test_irq,- .dma_lost_irq = ide_dma_lost_irq,- .dma_timeout = ide_dma_timeout,+ .dma_host_set = tx4939ide_dma_host_set,+ .dma_setup = tx4939ide_dma_setup,+ .dma_exec_cmd = ide_dma_exec_cmd,+ .dma_start = ide_dma_start,+ .dma_end = tx4939ide_dma_end,+ .dma_test_irq = tx4939ide_dma_test_irq,+ .dma_lost_irq = ide_dma_lost_irq,+ .dma_timeout = ide_dma_timeout, }; static const struct ide_port_info tx4939ide_port_info __initdata = {- .init_hwif = tx4939ide_init_hwif,- .init_dma = tx4939ide_init_dma,- .port_ops = &tx4939ide_port_ops,- .dma_ops = &tx4939ide_dma_ops,- .tp_ops = &tx4939ide_tp_ops,- .host_flags = IDE_HFLAG_MMIO,- .pio_mask = ATA_PIO4,- .mwdma_mask = ATA_MWDMA2,- .udma_mask = ATA_UDMA5,+ .init_hwif = tx4939ide_init_hwif,+ .init_dma = tx4939ide_init_dma,+ .port_ops = &tx4939ide_port_ops,+ .dma_ops = &tx4939ide_dma_ops,+ .tp_ops = &tx4939ide_tp_ops,+ .host_flags = IDE_HFLAG_MMIO,+ .pio_mask = ATA_PIO4,+ .mwdma_mask = ATA_MWDMA2,+ .udma_mask = ATA_UDMA5,+ .chipset = ide_generic, }; static int __init tx4939ide_probe(struct platform_device *pdev)diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfigindex 152d4aa..b732297 100644--- a/drivers/scsi/Kconfig+++ b/drivers/scsi/Kconfig@@ -21,7 +21,7 @@ config SCSI You also need to say Y here if you have a device which speaks the SCSI protocol. Examples of this include the parallel port version of the IOMEGA ZIP drive, USB storage devices, Fibre- Channel, FireWire storage and the IDE-SCSI emulation driver.+ Channel, and FireWire storage. To compile this driver as a module, choose M here and read <file:Documentation/scsi/scsi.txt>.@@ -101,9 +101,9 @@ config CHR_DEV_OSST ---help--- The OnStream SC-x0 SCSI tape drives cannot be driven by the standard st driver, but instead need this special osst driver and- use the /dev/osstX char device nodes (major 206). Via usb-storage- and ide-scsi, you may be able to drive the USB-x0 and DI-x0 drives- as well. Note that there is also a second generation of OnStream+ use the /dev/osstX char device nodes (major 206). Via usb-storage,+ you may be able to drive the USB-x0 and DI-x0 drives as well.+ Note that there is also a second generation of OnStream tape drives (ADR-x0) that supports the standard SCSI-2 commands for tapes (QIC-157) and can be driven by the standard driver st. For more information, you may have a look at the SCSI-HOWTOdiff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefileindex 1410697..7461eb0 100644--- a/drivers/scsi/Makefile+++ b/drivers/scsi/Makefile@@ -105,7 +105,6 @@ obj-$(CONFIG_SCSI_GDTH) += gdth.o obj-$(CONFIG_SCSI_INITIO) += initio.o obj-$(CONFIG_SCSI_INIA100) += a100u2w.o obj-$(CONFIG_SCSI_QLOGICPTI) += qlogicpti.o-obj-$(CONFIG_BLK_DEV_IDESCSI) += ide-scsi.o obj-$(CONFIG_SCSI_MESH) += mesh.o obj-$(CONFIG_SCSI_MAC53C94) += mac53c94.o obj-$(CONFIG_BLK_DEV_3W_XXXX_RAID) += 3w-xxxx.odiff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.cdeleted file mode 100644index c24140a..0000000--- a/drivers/scsi/ide-scsi.c+++ /dev/null@@ -1,840 +0,0 @@-/*- * Copyright (C) 1996-1999 Gadi Oxman <gadio@netvision.net.il>- * Copyright (C) 2004-2005 Bartlomiej Zolnierkiewicz- */--/*- * Emulation of a SCSI host adapter for IDE ATAPI devices.- *- * With this driver, one can use the Linux SCSI drivers instead of the- * native IDE ATAPI drivers.- *- * Ver 0.1 Dec 3 96 Initial version.- * Ver 0.2 Jan 26 97 Fixed bug in cleanup_module() and added emulation- * of MODE_SENSE_6/MODE_SELECT_6 for cdroms. Thanks- * to Janos Farkas for pointing this out.- * Avoid using bitfields in structures for m68k.- * Added Scatter/Gather and DMA support.- * Ver 0.4 Dec 7 97 Add support for ATAPI PD/CD drives.- * Use variable timeout for each command.- * Ver 0.5 Jan 2 98 Fix previous PD/CD support.- * Allow disabling of SCSI-6 to SCSI-10 transformation.- * Ver 0.6 Jan 27 98 Allow disabling of SCSI command translation layer- * for access through /dev/sg.- * Fix MODE_SENSE_6/MODE_SELECT_6/INQUIRY translation.- * Ver 0.7 Dec 04 98 Ignore commands where lun != 0 to avoid multiple- * detection of devices with CONFIG_SCSI_MULTI_LUN- * Ver 0.8 Feb 05 99 Optical media need translation too. Reverse 0.7.- * Ver 0.9 Jul 04 99 Fix a bug in SG_SET_TRANSFORM.- * Ver 0.91 Jun 10 02 Fix "off by one" error in transforms- * Ver 0.92 Dec 31 02 Implement new SCSI mid level API- */--#define IDESCSI_VERSION "0.92"--#include <linux/module.h>-#include <linux/types.h>-#include <linux/string.h>-#include <linux/kernel.h>-#include <linux/mm.h>-#include <linux/ioport.h>-#include <linux/blkdev.h>-#include <linux/errno.h>-#include <linux/slab.h>-#include <linux/ide.h>-#include <linux/scatterlist.h>-#include <linux/delay.h>-#include <linux/mutex.h>-#include <linux/bitops.h>--#include <asm/io.h>-#include <asm/uaccess.h>--#include <scsi/scsi.h>-#include <scsi/scsi_cmnd.h>-#include <scsi/scsi_device.h>-#include <scsi/scsi_host.h>-#include <scsi/scsi_tcq.h>-#include <scsi/sg.h>--#define IDESCSI_DEBUG_LOG 0--#if IDESCSI_DEBUG_LOG-#define debug_log(fmt, args...) \- printk(KERN_INFO "ide-scsi: " fmt, ## args)-#else-#define debug_log(fmt, args...) do {} while (0)-#endif--/*- * SCSI command transformation layer- */-#define IDESCSI_SG_TRANSFORM 1 /* /dev/sg transformation */--/*- * Log flags- */-#define IDESCSI_LOG_CMD 0 /* Log SCSI commands */--typedef struct ide_scsi_obj {- ide_drive_t *drive;- ide_driver_t *driver;- struct gendisk *disk;- struct Scsi_Host *host;-- unsigned long transform; /* SCSI cmd translation layer */- unsigned long log; /* log flags */-} idescsi_scsi_t;--static DEFINE_MUTEX(idescsi_ref_mutex);-/* Set by module param to skip cd */-static int idescsi_nocd;--#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)-{- struct ide_scsi_obj *scsi = NULL;-- mutex_lock(&idescsi_ref_mutex);- scsi = ide_scsi_g(disk);- if (scsi) {- if (ide_device_get(scsi->drive))- scsi = NULL;- else- scsi_host_get(scsi->host);- }- mutex_unlock(&idescsi_ref_mutex);- return scsi;-}--static void ide_scsi_put(struct ide_scsi_obj *scsi)-{- ide_drive_t *drive = scsi->drive;-- mutex_lock(&idescsi_ref_mutex);- scsi_host_put(scsi->host);- ide_device_put(drive);- mutex_unlock(&idescsi_ref_mutex);-}--static inline idescsi_scsi_t *scsihost_to_idescsi(struct Scsi_Host *host)-{- return (idescsi_scsi_t*) (&host[1]);-}--static inline idescsi_scsi_t *drive_to_idescsi(ide_drive_t *ide_drive)-{- return scsihost_to_idescsi(ide_drive->driver_data);-}--static void ide_scsi_hex_dump(u8 *data, int len)-{- print_hex_dump(KERN_CONT, "", DUMP_PREFIX_NONE, 16, 1, data, len, 0);-}--static int idescsi_end_request(ide_drive_t *, int, int);--static void ide_scsi_callback(ide_drive_t *drive, int dsc)-{- idescsi_scsi_t *scsi = drive_to_idescsi(drive);- struct ide_atapi_pc *pc = drive->pc;-- if (pc->flags & PC_FLAG_TIMEDOUT)- debug_log("%s: got timed out packet %lu at %lu\n", __func__,- pc->scsi_cmd->serial_number, jiffies);- /* end this request now - scsi should retry it*/- else if (test_bit(IDESCSI_LOG_CMD, &scsi->log))- printk(KERN_INFO "Packet command completed, %d bytes"- " transferred\n", pc->xferred);-- idescsi_end_request(drive, 1, 0);-}--static int idescsi_check_condition(ide_drive_t *drive,- struct request *failed_cmd)-{- idescsi_scsi_t *scsi = drive_to_idescsi(drive);- struct ide_atapi_pc *pc;- struct request *rq;- u8 *buf;-- /* stuff a sense request in front of our current request */- pc = kzalloc(sizeof(struct ide_atapi_pc), GFP_ATOMIC);- rq = blk_get_request(drive->queue, READ, GFP_ATOMIC);- buf = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_ATOMIC);- if (!pc || !rq || !buf) {- kfree(buf);- if (rq)- blk_put_request(rq);- kfree(pc);- return -ENOMEM;- }- rq->special = (char *) pc;- pc->rq = rq;- pc->buf = buf;- pc->c[0] = REQUEST_SENSE;- pc->c[4] = pc->req_xfer = pc->buf_size = SCSI_SENSE_BUFFERSIZE;- rq->cmd_type = REQ_TYPE_SENSE;- rq->cmd_flags |= REQ_PREEMPT;- pc->timeout = jiffies + WAIT_READY;- /* NOTE! Save the failed packet command in "rq->buffer" */- rq->buffer = (void *) failed_cmd->special;- pc->scsi_cmd = ((struct ide_atapi_pc *) failed_cmd->special)->scsi_cmd;- if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) {- printk ("ide-scsi: %s: queue cmd = ", drive->name);- ide_scsi_hex_dump(pc->c, 6);- }- rq->rq_disk = scsi->disk;- rq->ref_count++;- memcpy(rq->cmd, pc->c, 12);- ide_do_drive_cmd(drive, rq);- return 0;-}--static ide_startstop_t-idescsi_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)-{- ide_hwif_t *hwif = drive->hwif;-- if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ))- /* force an abort */- hwif->tp_ops->exec_command(hwif, ATA_CMD_IDLEIMMEDIATE);-- rq->errors++;-- idescsi_end_request(drive, 0, 0);-- return ide_stopped;-}--static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs)-{- idescsi_scsi_t *scsi = drive_to_idescsi(drive);- struct request *rq = HWGROUP(drive)->rq;- struct ide_atapi_pc *pc = (struct ide_atapi_pc *) rq->special;- int log = test_bit(IDESCSI_LOG_CMD, &scsi->log);- struct Scsi_Host *host;- int errors = rq->errors;- unsigned long flags;-- if (!blk_special_request(rq) && !blk_sense_request(rq)) {- ide_end_request(drive, uptodate, nrsecs);- return 0;- }- ide_end_drive_cmd (drive, 0, 0);- if (blk_sense_request(rq)) {- struct ide_atapi_pc *opc = (struct ide_atapi_pc *) rq->buffer;- if (log) {- printk ("ide-scsi: %s: wrap up check %lu, rst = ", drive->name, opc->scsi_cmd->serial_number);- ide_scsi_hex_dump(pc->buf, 16);- }- memcpy((void *) opc->scsi_cmd->sense_buffer, pc->buf,- SCSI_SENSE_BUFFERSIZE);- kfree(pc->buf);- kfree(pc);- blk_put_request(rq);- pc = opc;- rq = pc->rq;- pc->scsi_cmd->result = (CHECK_CONDITION << 1) |- (((pc->flags & PC_FLAG_TIMEDOUT) ?- DID_TIME_OUT :- DID_OK) << 16);- } else if (pc->flags & PC_FLAG_TIMEDOUT) {- if (log)- printk (KERN_WARNING "ide-scsi: %s: timed out for %lu\n",- drive->name, pc->scsi_cmd->serial_number);- pc->scsi_cmd->result = DID_TIME_OUT << 16;- } else if (errors >= ERROR_MAX) {- pc->scsi_cmd->result = DID_ERROR << 16;- if (log)- printk ("ide-scsi: %s: I/O error for %lu\n", drive->name, pc->scsi_cmd->serial_number);- } else if (errors) {- if (log)- printk ("ide-scsi: %s: check condition for %lu\n", drive->name, pc->scsi_cmd->serial_number);- if (!idescsi_check_condition(drive, rq))- /* we started a request sense, so we'll be back, exit for now */- return 0;- pc->scsi_cmd->result = (CHECK_CONDITION << 1) | (DID_OK << 16);- } else {- pc->scsi_cmd->result = DID_OK << 16;- }- host = pc->scsi_cmd->device->host;- spin_lock_irqsave(host->host_lock, flags);- pc->done(pc->scsi_cmd);- spin_unlock_irqrestore(host->host_lock, flags);- kfree(pc);- blk_put_request(rq);- drive->pc = NULL;- return 0;-}--static inline int idescsi_set_direction(struct ide_atapi_pc *pc)-{- switch (pc->c[0]) {- case READ_6: case READ_10: case READ_12:- pc->flags &= ~PC_FLAG_WRITING;- return 0;- case WRITE_6: case WRITE_10: case WRITE_12:- pc->flags |= PC_FLAG_WRITING;- return 0;- default:- return 1;- }-}--static int idescsi_map_sg(ide_drive_t *drive, struct ide_atapi_pc *pc)-{- ide_hwif_t *hwif = drive->hwif;- struct scatterlist *sg, *scsi_sg;- int segments;-- if (!pc->req_xfer || pc->req_xfer % 1024)- return 1;-- if (idescsi_set_direction(pc))- return 1;-- sg = hwif->sg_table;- scsi_sg = scsi_sglist(pc->scsi_cmd);- segments = scsi_sg_count(pc->scsi_cmd);-- if (segments > hwif->sg_max_nents)- return 1;-- hwif->sg_nents = segments;- memcpy(sg, scsi_sg, sizeof(*sg) * segments);-- return 0;-}--static ide_startstop_t idescsi_issue_pc(ide_drive_t *drive,- struct ide_atapi_pc *pc)-{- /* Set the current packet command */- drive->pc = pc;-- return ide_issue_pc(drive, ide_scsi_get_timeout(pc), ide_scsi_expiry);-}--/*- * idescsi_do_request is our request handling function.- */-static ide_startstop_t idescsi_do_request (ide_drive_t *drive, struct request *rq, sector_t block)-{- debug_log("dev: %s, cmd: %x, errors: %d\n", rq->rq_disk->disk_name,- rq->cmd[0], rq->errors);- debug_log("sector: %ld, nr_sectors: %ld, current_nr_sectors: %d\n",- rq->sector, rq->nr_sectors, rq->current_nr_sectors);-- if (blk_sense_request(rq) || blk_special_request(rq)) {- struct ide_atapi_pc *pc = (struct ide_atapi_pc *)rq->special;-- if ((drive->dev_flags & IDE_DFLAG_USING_DMA) &&- idescsi_map_sg(drive, pc) == 0)- pc->flags |= PC_FLAG_DMA_OK;-- return idescsi_issue_pc(drive, pc);- }- blk_dump_rq_flags(rq, "ide-scsi: unsup command");- idescsi_end_request (drive, 0, 0);- return ide_stopped;-}--#ifdef CONFIG_IDE_PROC_FS-static ide_proc_entry_t idescsi_proc[] = {- { "capacity", S_IFREG|S_IRUGO, proc_ide_read_capacity, NULL },- { NULL, 0, NULL, NULL }-};--#define ide_scsi_devset_get(name, field) \-static int get_##name(ide_drive_t *drive) \-{ \- idescsi_scsi_t *scsi = drive_to_idescsi(drive); \- return scsi->field; \-}--#define ide_scsi_devset_set(name, field) \-static int set_##name(ide_drive_t *drive, int arg) \-{ \- idescsi_scsi_t *scsi = drive_to_idescsi(drive); \- scsi->field = arg; \- return 0; \-}--#define ide_scsi_devset_rw_field(_name, _field) \-ide_scsi_devset_get(_name, _field); \-ide_scsi_devset_set(_name, _field); \-IDE_DEVSET(_name, DS_SYNC, get_##_name, set_##_name);--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_field(transform, transform);-ide_scsi_devset_rw_field(log, log);--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 },-};--static ide_proc_entry_t *ide_scsi_proc_entries(ide_drive_t *drive)-{- return idescsi_proc;-}--static const struct ide_proc_devset *ide_scsi_proc_devsets(ide_drive_t *drive)-{- return idescsi_settings;-}-#endif--/*- * Driver initialization.- */-static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi)-{- clear_bit(IDESCSI_SG_TRANSFORM, &scsi->transform);-#if IDESCSI_DEBUG_LOG- set_bit(IDESCSI_LOG_CMD, &scsi->log);-#endif /* IDESCSI_DEBUG_LOG */-- drive->pc_callback = ide_scsi_callback;- drive->pc_update_buffers = NULL;- drive->pc_io_buffers = ide_io_buffers;-- ide_proc_register_driver(drive, scsi->driver);-}--static void ide_scsi_remove(ide_drive_t *drive)-{- struct Scsi_Host *scsihost = drive->driver_data;- struct ide_scsi_obj *scsi = scsihost_to_idescsi(scsihost);- struct gendisk *g = scsi->disk;-- scsi_remove_host(scsihost);- ide_proc_unregister_driver(drive, scsi->driver);-- ide_unregister_region(g);-- drive->driver_data = NULL;- g->private_data = NULL;- put_disk(g);-- ide_scsi_put(scsi);-- drive->dev_flags &= ~IDE_DFLAG_SCSI;-}--static int ide_scsi_probe(ide_drive_t *);--static ide_driver_t idescsi_driver = {- .gen_driver = {- .owner = THIS_MODULE,- .name = "ide-scsi",- .bus = &ide_bus_type,- },- .probe = ide_scsi_probe,- .remove = ide_scsi_remove,- .version = IDESCSI_VERSION,- .do_request = idescsi_do_request,- .end_request = idescsi_end_request,- .error = idescsi_atapi_error,-#ifdef CONFIG_IDE_PROC_FS- .proc_entries = ide_scsi_proc_entries,- .proc_devsets = ide_scsi_proc_devsets,-#endif-};--static int idescsi_ide_open(struct block_device *bdev, fmode_t mode)-{- struct ide_scsi_obj *scsi = ide_scsi_get(bdev->bd_disk);-- if (!scsi)- return -ENXIO;-- return 0;-}--static int idescsi_ide_release(struct gendisk *disk, fmode_t mode)-{- ide_scsi_put(ide_scsi_g(disk));- return 0;-}--static int idescsi_ide_ioctl(struct block_device *bdev, fmode_t mode,- unsigned int cmd, unsigned long arg)-{- struct ide_scsi_obj *scsi = ide_scsi_g(bdev->bd_disk);- return generic_ide_ioctl(scsi->drive, bdev, cmd, arg);-}--static struct block_device_operations idescsi_ops = {- .owner = THIS_MODULE,- .open = idescsi_ide_open,- .release = idescsi_ide_release,- .locked_ioctl = idescsi_ide_ioctl,-};--static int idescsi_slave_configure(struct scsi_device * sdp)-{- /* Configure detected device */- sdp->use_10_for_rw = 1;- sdp->use_10_for_ms = 1;- scsi_adjust_queue_depth(sdp, MSG_SIMPLE_TAG, sdp->host->cmd_per_lun);- return 0;-}--static const char *idescsi_info (struct Scsi_Host *host)-{- return "SCSI host adapter emulation for IDE ATAPI devices";-}--static int idescsi_ioctl (struct scsi_device *dev, int cmd, void __user *arg)-{- idescsi_scsi_t *scsi = scsihost_to_idescsi(dev->host);-- if (cmd == SG_SET_TRANSFORM) {- if (arg)- set_bit(IDESCSI_SG_TRANSFORM, &scsi->transform);- else- clear_bit(IDESCSI_SG_TRANSFORM, &scsi->transform);- return 0;- } else if (cmd == SG_GET_TRANSFORM)- return put_user(test_bit(IDESCSI_SG_TRANSFORM, &scsi->transform), (int __user *) arg);- return -EINVAL;-}--static int idescsi_queue (struct scsi_cmnd *cmd,- void (*done)(struct scsi_cmnd *))-{- struct Scsi_Host *host = cmd->device->host;- idescsi_scsi_t *scsi = scsihost_to_idescsi(host);- ide_drive_t *drive = scsi->drive;- struct request *rq = NULL;- struct ide_atapi_pc *pc = NULL;- int write = cmd->sc_data_direction == DMA_TO_DEVICE;-- if (!drive) {- scmd_printk (KERN_ERR, cmd, "drive not present\n");- goto abort;- }- scsi = drive_to_idescsi(drive);- pc = kmalloc(sizeof(struct ide_atapi_pc), GFP_ATOMIC);- rq = blk_get_request(drive->queue, write, GFP_ATOMIC);- if (rq == NULL || pc == NULL) {- printk (KERN_ERR "ide-scsi: %s: out of memory\n", drive->name);- goto abort;- }-- memset (pc->c, 0, 12);- pc->flags = 0;- if (cmd->sc_data_direction == DMA_TO_DEVICE)- pc->flags |= PC_FLAG_WRITING;- pc->rq = rq;- memcpy (pc->c, cmd->cmnd, cmd->cmd_len);- pc->buf = NULL;- pc->sg = scsi_sglist(cmd);- pc->sg_cnt = scsi_sg_count(cmd);- pc->b_count = 0;- pc->req_xfer = pc->buf_size = scsi_bufflen(cmd);- pc->scsi_cmd = cmd;- pc->done = done;- pc->timeout = jiffies + cmd->request->timeout;-- if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) {- printk ("ide-scsi: %s: que %lu, cmd = ", drive->name, cmd->serial_number);- ide_scsi_hex_dump(cmd->cmnd, cmd->cmd_len);- if (memcmp(pc->c, cmd->cmnd, cmd->cmd_len)) {- printk ("ide-scsi: %s: que %lu, tsl = ", drive->name, cmd->serial_number);- ide_scsi_hex_dump(pc->c, 12);- }- }-- rq->special = (char *) pc;- rq->cmd_type = REQ_TYPE_SPECIAL;- spin_unlock_irq(host->host_lock);- rq->ref_count++;- memcpy(rq->cmd, pc->c, 12);- blk_execute_rq_nowait(drive->queue, scsi->disk, rq, 0, NULL);- spin_lock_irq(host->host_lock);- return 0;-abort:- kfree (pc);- if (rq)- blk_put_request(rq);- cmd->result = DID_ERROR << 16;- done(cmd);- return 0;-}--static int idescsi_eh_abort (struct scsi_cmnd *cmd)-{- idescsi_scsi_t *scsi = scsihost_to_idescsi(cmd->device->host);- ide_drive_t *drive = scsi->drive;- ide_hwif_t *hwif;- ide_hwgroup_t *hwgroup;- int busy;- int ret = FAILED;-- struct ide_atapi_pc *pc;-- /* In idescsi_eh_abort we try to gently pry our command from the ide subsystem */-- if (test_bit(IDESCSI_LOG_CMD, &scsi->log))- printk (KERN_WARNING "ide-scsi: abort called for %lu\n", cmd->serial_number);-- if (!drive) {- printk (KERN_WARNING "ide-scsi: Drive not set in idescsi_eh_abort\n");- WARN_ON(1);- goto no_drive;- }-- hwif = drive->hwif;- hwgroup = hwif->hwgroup;-- /* First give it some more time, how much is "right" is hard to say :-(- FIXME - uses mdelay which causes latency? */- busy = ide_wait_not_busy(hwif, 100);- if (test_bit(IDESCSI_LOG_CMD, &scsi->log))- printk (KERN_WARNING "ide-scsi: drive did%s become ready\n", busy?" not":"");-- spin_lock_irq(&hwgroup->lock);-- /* If there is no pc running we're done (our interrupt took care of it) */- pc = drive->pc;- if (pc == NULL) {- ret = SUCCESS;- goto ide_unlock;- }-- /* It's somewhere in flight. Does ide subsystem agree? */- if (pc->scsi_cmd->serial_number == cmd->serial_number && !busy &&- elv_queue_empty(drive->queue) && HWGROUP(drive)->rq != pc->rq) {- /*- * FIXME - not sure this condition can ever occur- */- printk (KERN_ERR "ide-scsi: cmd aborted!\n");-- if (blk_sense_request(pc->rq))- kfree(pc->buf);- /* we need to call blk_put_request twice. */- blk_put_request(pc->rq);- blk_put_request(pc->rq);- kfree(pc);- drive->pc = NULL;-- ret = SUCCESS;- }--ide_unlock:- spin_unlock_irq(&hwgroup->lock);-no_drive:- if (test_bit(IDESCSI_LOG_CMD, &scsi->log))- printk (KERN_WARNING "ide-scsi: abort returns %s\n", ret == SUCCESS?"success":"failed");-- return ret;-}--static int idescsi_eh_reset (struct scsi_cmnd *cmd)-{- struct request *req;- idescsi_scsi_t *scsi = scsihost_to_idescsi(cmd->device->host);- ide_drive_t *drive = scsi->drive;- ide_hwgroup_t *hwgroup;- int ready = 0;- int ret = SUCCESS;-- struct ide_atapi_pc *pc;-- /* In idescsi_eh_reset we forcefully remove the command from the ide subsystem and reset the device. */-- if (test_bit(IDESCSI_LOG_CMD, &scsi->log))- printk (KERN_WARNING "ide-scsi: reset called for %lu\n", cmd->serial_number);-- if (!drive) {- printk (KERN_WARNING "ide-scsi: Drive not set in idescsi_eh_reset\n");- WARN_ON(1);- return FAILED;- }-- hwgroup = drive->hwif->hwgroup;-- spin_lock_irq(cmd->device->host->host_lock);- spin_lock(&hwgroup->lock);-- pc = drive->pc;- if (pc)- req = pc->rq;-- if (pc == NULL || req != hwgroup->rq || hwgroup->handler == NULL) {- printk (KERN_WARNING "ide-scsi: No active request in idescsi_eh_reset\n");- spin_unlock(&hwgroup->lock);- spin_unlock_irq(cmd->device->host->host_lock);- return FAILED;- }-- /* kill current request */- if (__blk_end_request(req, -EIO, 0))- BUG();- if (blk_sense_request(req))- kfree(pc->buf);- kfree(pc);- drive->pc = NULL;- blk_put_request(req);-- /* now nuke the drive queue */- while ((req = elv_next_request(drive->queue))) {- if (__blk_end_request(req, -EIO, 0))- BUG();- }-- hwgroup->rq = NULL;- hwgroup->handler = NULL;- hwgroup->busy = 1; /* will set this to zero when ide reset finished */- spin_unlock(&hwgroup->lock);-- ide_do_reset(drive);-- /* ide_do_reset starts a polling handler which restarts itself every 50ms until the reset finishes */-- do {- spin_unlock_irq(cmd->device->host->host_lock);- msleep(50);- spin_lock_irq(cmd->device->host->host_lock);- } while ( HWGROUP(drive)->handler );-- ready = drive_is_ready(drive);- HWGROUP(drive)->busy--;- if (!ready) {- printk (KERN_ERR "ide-scsi: reset failed!\n");- ret = FAILED;- }-- spin_unlock_irq(cmd->device->host->host_lock);- return ret;-}--static int idescsi_bios(struct scsi_device *sdev, struct block_device *bdev,- sector_t capacity, int *parm)-{- idescsi_scsi_t *idescsi = scsihost_to_idescsi(sdev->host);- ide_drive_t *drive = idescsi->drive;-- if (drive->bios_cyl && drive->bios_head && drive->bios_sect) {- parm[0] = drive->bios_head;- parm[1] = drive->bios_sect;- parm[2] = drive->bios_cyl;- }- return 0;-}--static struct scsi_host_template idescsi_template = {- .module = THIS_MODULE,- .name = "idescsi",- .info = idescsi_info,- .slave_configure = idescsi_slave_configure,- .ioctl = idescsi_ioctl,- .queuecommand = idescsi_queue,- .eh_abort_handler = idescsi_eh_abort,- .eh_host_reset_handler = idescsi_eh_reset,- .bios_param = idescsi_bios,- .can_queue = 40,- .this_id = -1,- .sg_tablesize = 256,- .cmd_per_lun = 5,- .max_sectors = 128,- .use_clustering = DISABLE_CLUSTERING,- .emulated = 1,- .proc_name = "ide-scsi",-};--static int ide_scsi_probe(ide_drive_t *drive)-{- idescsi_scsi_t *idescsi;- struct Scsi_Host *host;- struct gendisk *g;- static int warned;- int err = -ENOMEM;- u16 last_lun;-- 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");- warned = 1;- }-- if (idescsi_nocd && drive->media == ide_cdrom)- return -ENODEV;-- if (!strstr("ide-scsi", drive->driver_req) ||- drive->media == ide_disk ||- !(host = scsi_host_alloc(&idescsi_template,sizeof(idescsi_scsi_t))))- return -ENODEV;-- drive->dev_flags |= IDE_DFLAG_SCSI;-- g = alloc_disk(1 << PARTN_BITS);- if (!g)- goto out_host_put;-- ide_init_disk(g, drive);-- host->max_id = 1;-- last_lun = drive->id[ATA_ID_LAST_LUN];- if (last_lun)- debug_log("%s: last_lun=%u\n", drive->name, last_lun);-- if ((last_lun & 7) != 7)- host->max_lun = (last_lun & 7) + 1;- else- host->max_lun = 1;-- 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 = 0;- idescsi_setup(drive, idescsi);- g->fops = &idescsi_ops;- 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_proc_unregister_driver(drive, &idescsi_driver);-- put_disk(g);-out_host_put:- drive->dev_flags &= ~IDE_DFLAG_SCSI;- scsi_host_put(host);- return err;-}--static int __init init_idescsi_module(void)-{- return driver_register(&idescsi_driver.gen_driver);-}--static void __exit exit_idescsi_module(void)-{- driver_unregister(&idescsi_driver.gen_driver);-}--module_param(idescsi_nocd, int, 0600);-MODULE_PARM_DESC(idescsi_nocd, "Disable handling of CD-ROMs so they may be driven by ide-cd");-module_init(init_idescsi_module);-module_exit(exit_idescsi_module);-MODULE_LICENSE("GPL");diff --git a/include/linux/ide.h b/include/linux/ide.hindex e99c56d..db5ef8a 100644--- a/include/linux/ide.h+++ b/include/linux/ide.h@@ -32,13 +32,6 @@ # define SUPPORT_VLB_SYNC 1 #endif -/*- * Used to indicate "no IRQ", should be a value that cannot be an IRQ- * number.- */- -#define IDE_NO_IRQ (-1)- typedef unsigned char byte; /* used everywhere */ /*@@ -403,6 +396,7 @@ enum { * This is used for several packet commands (not for READ/WRITE commands). */ #define IDE_PC_BUFFER_SIZE 256+#define ATAPI_WAIT_PC (60 * HZ) struct ide_atapi_pc { /* actual packet bytes */@@ -480,53 +474,53 @@ enum { /* ide-cd */ /* Drive cannot eject the disc. */- IDE_AFLAG_NO_EJECT = (1 << 3),+ IDE_AFLAG_NO_EJECT = (1 << 1), /* Drive is a pre ATAPI 1.2 drive. */- IDE_AFLAG_PRE_ATAPI12 = (1 << 4),+ IDE_AFLAG_PRE_ATAPI12 = (1 << 2), /* TOC addresses are in BCD. */- IDE_AFLAG_TOCADDR_AS_BCD = (1 << 5),+ IDE_AFLAG_TOCADDR_AS_BCD = (1 << 3), /* TOC track numbers are in BCD. */- IDE_AFLAG_TOCTRACKS_AS_BCD = (1 << 6),+ IDE_AFLAG_TOCTRACKS_AS_BCD = (1 << 4), /* * Drive does not provide data in multiples of SECTOR_SIZE * when more than one interrupt is needed. */- IDE_AFLAG_LIMIT_NFRAMES = (1 << 7),+ IDE_AFLAG_LIMIT_NFRAMES = (1 << 5), /* Saved TOC information is current. */- IDE_AFLAG_TOC_VALID = (1 << 9),+ IDE_AFLAG_TOC_VALID = (1 << 6), /* We think that the drive door is locked. */- IDE_AFLAG_DOOR_LOCKED = (1 << 10),+ IDE_AFLAG_DOOR_LOCKED = (1 << 7), /* SET_CD_SPEED command is unsupported. */- IDE_AFLAG_NO_SPEED_SELECT = (1 << 11),- IDE_AFLAG_VERTOS_300_SSD = (1 << 12),- IDE_AFLAG_VERTOS_600_ESD = (1 << 13),- IDE_AFLAG_SANYO_3CD = (1 << 14),- IDE_AFLAG_FULL_CAPS_PAGE = (1 << 15),- IDE_AFLAG_PLAY_AUDIO_OK = (1 << 16),- IDE_AFLAG_LE_SPEED_FIELDS = (1 << 17),+ IDE_AFLAG_NO_SPEED_SELECT = (1 << 8),+ IDE_AFLAG_VERTOS_300_SSD = (1 << 9),+ IDE_AFLAG_VERTOS_600_ESD = (1 << 10),+ IDE_AFLAG_SANYO_3CD = (1 << 11),+ IDE_AFLAG_FULL_CAPS_PAGE = (1 << 12),+ IDE_AFLAG_PLAY_AUDIO_OK = (1 << 13),+ IDE_AFLAG_LE_SPEED_FIELDS = (1 << 14), /* ide-floppy */ /* Avoid commands not supported in Clik drive */- IDE_AFLAG_CLIK_DRIVE = (1 << 19),+ IDE_AFLAG_CLIK_DRIVE = (1 << 15), /* Requires BH algorithm for packets */- IDE_AFLAG_ZIP_DRIVE = (1 << 20),+ IDE_AFLAG_ZIP_DRIVE = (1 << 16), /* Supports format progress report */- IDE_AFLAG_SRFP = (1 << 22),+ IDE_AFLAG_SRFP = (1 << 17), /* ide-tape */- IDE_AFLAG_IGNORE_DSC = (1 << 23),+ IDE_AFLAG_IGNORE_DSC = (1 << 18), /* 0 When the tape position is unknown */- IDE_AFLAG_ADDRESS_VALID = (1 << 24),+ IDE_AFLAG_ADDRESS_VALID = (1 << 19), /* Device already opened */- IDE_AFLAG_BUSY = (1 << 25),+ IDE_AFLAG_BUSY = (1 << 20), /* Attempt to auto-detect the current user block size */- IDE_AFLAG_DETECT_BS = (1 << 26),+ IDE_AFLAG_DETECT_BS = (1 << 21), /* Currently on a filemark */- IDE_AFLAG_FILEMARK = (1 << 27),+ IDE_AFLAG_FILEMARK = (1 << 22), /* 0 = no tape is loaded, so we don't rewind after ejecting */- IDE_AFLAG_MEDIUM_PRESENT = (1 << 28),+ IDE_AFLAG_MEDIUM_PRESENT = (1 << 23), - IDE_AFLAG_NO_AUTOCLOSE = (1 << 29),+ IDE_AFLAG_NO_AUTOCLOSE = (1 << 24), }; /* device flags */@@ -565,28 +559,26 @@ enum { IDE_DFLAG_NODMA = (1 << 16), /* powermanagment told us not to do anything, so sleep nicely */ IDE_DFLAG_BLOCKED = (1 << 17),- /* ide-scsi emulation */- IDE_DFLAG_SCSI = (1 << 18), /* sleeping & sleep field valid */- IDE_DFLAG_SLEEPING = (1 << 19),- IDE_DFLAG_POST_RESET = (1 << 20),- IDE_DFLAG_UDMA33_WARNED = (1 << 21),- IDE_DFLAG_LBA48 = (1 << 22),+ IDE_DFLAG_SLEEPING = (1 << 18),+ IDE_DFLAG_POST_RESET = (1 << 19),+ IDE_DFLAG_UDMA33_WARNED = (1 << 20),+ IDE_DFLAG_LBA48 = (1 << 21), /* status of write cache */- IDE_DFLAG_WCACHE = (1 << 23),+ IDE_DFLAG_WCACHE = (1 << 22), /* used for ignoring ATA_DF */- IDE_DFLAG_NOWERR = (1 << 24),+ IDE_DFLAG_NOWERR = (1 << 23), /* retrying in PIO */- IDE_DFLAG_DMA_PIO_RETRY = (1 << 25),- IDE_DFLAG_LBA = (1 << 26),+ IDE_DFLAG_DMA_PIO_RETRY = (1 << 24),+ IDE_DFLAG_LBA = (1 << 25), /* don't unload heads */- IDE_DFLAG_NO_UNLOAD = (1 << 27),+ IDE_DFLAG_NO_UNLOAD = (1 << 26), /* heads unloaded, please don't reset port */- IDE_DFLAG_PARKED = (1 << 28),- IDE_DFLAG_MEDIA_CHANGED = (1 << 29),+ IDE_DFLAG_PARKED = (1 << 27),+ IDE_DFLAG_MEDIA_CHANGED = (1 << 28), /* write protect */- IDE_DFLAG_WP = (1 << 30),- IDE_DFLAG_FORMAT_IN_PROGRESS = (1 << 31),+ IDE_DFLAG_WP = (1 << 29),+ IDE_DFLAG_FORMAT_IN_PROGRESS = (1 << 30), }; struct ide_drive_s {@@ -610,8 +602,6 @@ struct ide_drive_s { unsigned long dev_flags; unsigned long sleep; /* sleep until this time */- unsigned long service_start; /* time we started last request */- unsigned long service_time; /* service time of last request */ unsigned long timeout; /* max time to wait for irq */ special_t special; /* special action flags */@@ -879,8 +869,6 @@ typedef struct hwgroup_s { /* BOOL: protects all fields below */ volatile int busy;- /* BOOL: wake us up on timer expiry */- unsigned int sleeping : 1; /* BOOL: polling active & poll_timeout field valid */ unsigned int polling : 1; @@ -1258,14 +1246,11 @@ int ide_set_media_lock(ide_drive_t *, struct gendisk *, int); void ide_create_request_sense_cmd(ide_drive_t *, struct ide_atapi_pc *); void ide_retry_pc(ide_drive_t *, struct gendisk *); -static inline unsigned long ide_scsi_get_timeout(struct ide_atapi_pc *pc)-{- return max_t(unsigned long, WAIT_CMD, pc->timeout - jiffies);-}+int ide_cd_expiry(ide_drive_t *); -int ide_scsi_expiry(ide_drive_t *);+int ide_cd_get_xferlen(struct request *); -ide_startstop_t ide_issue_pc(ide_drive_t *, unsigned int, ide_expiry_t *);+ide_startstop_t ide_issue_pc(ide_drive_t *); ide_startstop_t do_rw_taskfile(ide_drive_t *, ide_task_t *); @@ -1287,6 +1272,26 @@ extern void ide_stall_queue(ide_drive_t *drive, unsigned long timeout); extern void ide_timer_expiry(unsigned long); extern irqreturn_t ide_intr(int irq, void *dev_id);++static inline int ide_lock_hwgroup(ide_hwgroup_t *hwgroup)+{+ if (hwgroup->busy)+ return 1;++ hwgroup->busy = 1;+ /* for atari only */+ ide_get_lock(ide_intr, hwgroup);++ return 0;+}++static inline void ide_unlock_hwgroup(ide_hwgroup_t *hwgroup)+{+ /* for atari only */+ ide_release_lock();+ hwgroup->busy = 0;+}+ extern void do_ide_request(struct request_queue *); void ide_init_disk(struct gendisk *, ide_drive_t *);@@ -1533,6 +1538,7 @@ void ide_unregister_region(struct gendisk *); void ide_undecoded_slave(ide_drive_t *); void ide_port_apply_params(ide_hwif_t *);+int ide_sysfs_register_port(ide_hwif_t *); struct ide_host *ide_host_alloc(const struct ide_port_info *, hw_regs_t **); void ide_host_free(struct ide_host *);@@ -1627,6 +1633,9 @@ extern struct mutex ide_cfg_mtx; #define local_irq_set(flags) do { local_save_flags((flags)); local_irq_enable_in_hardirq(); } while (0) +char *ide_media_string(ide_drive_t *);++extern struct device_attribute ide_dev_attrs[]; extern struct bus_type ide_bus_type; extern struct class *ide_port_class; \0ÿôèº{.nÇ+·®+%Ëÿ±éݶ\x17¥wÿº{.nÇ+·¥{±þG«éÿ{ayº\x1dÊÚë,j\a¢f£¢·hïêÿêçz_è®\x03(éÝ¢j"ú\x1a¶^[m§ÿÿ¾\a«þG«éÿ¢¸?¨èÚ&£ø§~á¶iOæ¬z·vØ^\x14\x04\x1a¶^[m§ÿÿÃ\fÿ¶ìÿ¢¸?I¥
next reply other threads:[~2009-01-02 17:00 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-01-02 16:59 Bartlomiej Zolnierkiewicz [this message]
2009-01-02 16:59 ` [git pull] IDE updates part 2 Bartlomiej Zolnierkiewicz
-- strict thread matches above, loose matches on Subject: below --
2009-03-27 12:02 Bartlomiej Zolnierkiewicz
2009-03-30 14:33 ` Bartlomiej Zolnierkiewicz
2009-06-12 12:01 Bartlomiej Zolnierkiewicz
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200901021759.46260.bzolnier@gmail.com \
--to=bzolnier@gmail.com \
--cc=akpm@linux-foundation.org \
--cc=linux-ide@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=sfr@canb.auug.org.au \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.