[git pull] IDE updates part 2

Bartlomiej Zolnierkiewicz
2009-01-02T17:01:15Z

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¥