* [git pull] IDE updates part 1
@ 2008-12-29 19:49 Bartlomiej Zolnierkiewicz
0 siblings, 0 replies; 3+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2008-12-29 19:49 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Andrew Morton, Stephen Rothwell, linux-ide, linux-kernel
Inside:
* Fix for IDE ACPI regression breaking suspend on some machines
(kernel.org bug #12279).
* tx493[89]ide host drivers fixes (from Atsushi Nemoto).
* Locking sanitizations/improvements.
* Replacement of global ide_lock by per-hwgroup locks
(based on previous patch from Ravikiran G Thirumalai).
* Misc fixes and housekeeping patches...
All patches have been in linux-next tree for few weeks now
(except regression fix and tx493[89] fixes but they're all
obviously correct).
Linus, please pull from:
master.kernel.org:/pub/scm/linux/kernel/git/bart/ide-2.6.git/
to receive the following updates:
drivers/ide/Kconfig | 8 ++
drivers/ide/Makefile | 3 +-
drivers/ide/cmd64x.c | 4 +-
drivers/ide/cy82c693.c | 1 -
drivers/ide/gayle.c | 6 +-
drivers/ide/hpt366.c | 8 +-
drivers/ide/ide-acpi.c | 4 +-
drivers/ide/ide-cd.c | 142 ++++-----------------
drivers/ide/ide-cd.h | 2 -
drivers/ide/ide-dma-sff.c | 54 ++++-----
drivers/ide/ide-io.c | 292 ++++++++------------------------------------
drivers/ide/ide-ioctls.c | 5 +-
drivers/ide/ide-iops.c | 48 ++++----
drivers/ide/ide-legacy.c | 58 +++++++++
drivers/ide/ide-lib.c | 105 ++++++++--------
drivers/ide/ide-park.c | 16 ++--
drivers/ide/ide-pm.c | 235 +++++++++++++++++++++++++++++++++++
drivers/ide/ide-probe.c | 166 +++++--------------------
drivers/ide/ide-proc.c | 29 +----
drivers/ide/ide.c | 89 +-------------
drivers/ide/pdc202xx_old.c | 9 +-
drivers/ide/rz1000.c | 36 ++++--
drivers/ide/trm290.c | 4 +-
drivers/ide/tx4938ide.c | 4 +-
drivers/ide/tx4939ide.c | 10 ++-
drivers/ide/umc8672.c | 11 +-
drivers/scsi/ide-scsi.c | 32 +++--
include/linux/ide.h | 37 +++---
28 files changed, 635 insertions(+), 783 deletions(-)
create mode 100644 drivers/ide/ide-legacy.c
create mode 100644 drivers/ide/ide-pm.c
Atsushi Nemoto (2):
tx4939ide: Do not use zero count PRD entry
tx493[89]ide: Fix length for __ide_flush_dcache_range
Bartlomiej Zolnierkiewicz (30):
ide: fix IDE ACPI regression breaking suspend
ide: unify ide_intr()'s exit points
ide: IDE settings don't need an ide_lock held
ide: __ide_port_unregister_devices() doesn't need an ide_lock held
ide: ide_hwgroup_t.rq doesn't need an ide_lock held
ide: push ide_lock to __ide_end_request()
ide: ide_lock + __blk_end_request() -> blk_end_request()
ide: use queue lock instead of ide_lock when possible
ide: replace the global ide_lock spinlock by per-hwgroup spinlocks (v2)
ide: cleanup ide_do_request()
ide-cd: remove obsolete seek optimization
ali14xx: doesn't use shared IRQs
cmd64x: set IDE_HFLAG_SERIALIZE explictly for CMD646
gayle: set IDE_HFLAG_SERIALIZE explictly
ide: fix ->quirk_list checking in ide_do_request()
ide: always set nIEN on idle devices
rz1000: apply chipset quirks early (v2)
ide: add ->max_sectors field to struct ide_port_info
trm290: add IDE_HFLAG_TRM290 host flag
cy82c693: remove superfluous ide_cy82c693 chipset type
ide: rework handling of serialized ports (v2)
ide: remove redundant code from ide_end_drive_cmd()
ide: remove inline tags from ide-probe.c
ide: checkpatch.pl fixes for ide-lib.c
ide: use ATA_DMA_* defines in ide-dma-sff.c
ide: move Power Management support to ide-pm.c
ide: move legacy ISA/VLB ports handling to ide-legacy.c (v2)
ide: remove superfluous local_irq_{save,restore}() from ide_dump_status()
ide: push local_irq_{save,restore}() to do_identify()
ide-cd: remove dead dsc_overlap setting
Kay Sievers (1):
ide: struct device - replace bus_id with dev_name(), dev_set_name()
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index e6857e0..7a0a84b 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -62,6 +62,9 @@ config IDE_TIMINGS
config IDE_ATAPI
bool
+config IDE_LEGACY
+ bool
+
config BLK_DEV_IDE_SATA
bool "Support for SATA (deprecated; conflicts with libata SATA driver)"
default n
@@ -856,6 +859,7 @@ config BLK_DEV_4DRIVES
config BLK_DEV_ALI14XX
tristate "ALI M14xx support"
select IDE_TIMINGS
+ select IDE_LEGACY
help
This driver is enabled at runtime using the "ali14xx.probe" kernel
boot parameter. It enables support for the secondary IDE interface
@@ -866,6 +870,7 @@ config BLK_DEV_ALI14XX
config BLK_DEV_DTC2278
tristate "DTC-2278 support"
+ select IDE_LEGACY
help
This driver is enabled at runtime using the "dtc2278.probe" kernel
boot parameter. It enables support for the secondary IDE interface
@@ -876,6 +881,7 @@ config BLK_DEV_DTC2278
config BLK_DEV_HT6560B
tristate "Holtek HT6560B support"
select IDE_TIMINGS
+ select IDE_LEGACY
help
This driver is enabled at runtime using the "ht6560b.probe" kernel
boot parameter. It enables support for the secondary IDE interface
@@ -886,6 +892,7 @@ config BLK_DEV_HT6560B
config BLK_DEV_QD65XX
tristate "QDI QD65xx support"
select IDE_TIMINGS
+ select IDE_LEGACY
help
This driver is enabled at runtime using the "qd65xx.probe" kernel
boot parameter. It permits faster I/O speeds to be set. See the
@@ -894,6 +901,7 @@ config BLK_DEV_QD65XX
config BLK_DEV_UMC8672
tristate "UMC-8672 support"
+ select IDE_LEGACY
help
This driver is enabled at runtime using the "umc8672.probe" kernel
boot parameter. It enables support for the secondary IDE interface
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile
index 7818d40..177e3f8 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-park.o ide-pio-blacklist.o
+ ide-taskfile.o ide-pm.o ide-park.o ide-pio-blacklist.o
# core IDE code
ide-core-$(CONFIG_IDE_TIMINGS) += ide-timings.o
@@ -15,6 +15,7 @@ ide-core-$(CONFIG_BLK_DEV_IDEDMA) += ide-dma.o
ide-core-$(CONFIG_BLK_DEV_IDEDMA_SFF) += ide-dma-sff.o
ide-core-$(CONFIG_IDE_PROC_FS) += ide-proc.o
ide-core-$(CONFIG_BLK_DEV_IDEACPI) += ide-acpi.o
+ide-core-$(CONFIG_IDE_LEGACY) += ide-legacy.o
obj-$(CONFIG_IDE) += ide-core.o
diff --git a/drivers/ide/cmd64x.c b/drivers/ide/cmd64x.c
index 935385c..3623bf0 100644
--- a/drivers/ide/cmd64x.c
+++ b/drivers/ide/cmd64x.c
@@ -424,10 +424,10 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
.name = DRV_NAME,
.init_chipset = init_chipset_cmd64x,
.enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
- .chipset = ide_cmd646,
.port_ops = &cmd64x_port_ops,
.dma_ops = &cmd648_dma_ops,
- .host_flags = IDE_HFLAG_ABUSE_PREFETCH,
+ .host_flags = IDE_HFLAG_SERIALIZE |
+ IDE_HFLAG_ABUSE_PREFETCH,
.pio_mask = ATA_PIO5,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA2,
diff --git a/drivers/ide/cy82c693.c b/drivers/ide/cy82c693.c
index 5297f07..d37baf8 100644
--- a/drivers/ide/cy82c693.c
+++ b/drivers/ide/cy82c693.c
@@ -292,7 +292,6 @@ static const struct ide_port_info cy82c693_chipset __devinitdata = {
.name = DRV_NAME,
.init_iops = init_iops_cy82c693,
.port_ops = &cy82c693_port_ops,
- .chipset = ide_cy82c693,
.host_flags = IDE_HFLAG_SINGLE,
.pio_mask = ATA_PIO4,
.swdma_mask = ATA_SWDMA2,
diff --git a/drivers/ide/gayle.c b/drivers/ide/gayle.c
index 6915068..59bd0be 100644
--- a/drivers/ide/gayle.c
+++ b/drivers/ide/gayle.c
@@ -117,6 +117,10 @@ static void __init gayle_setup_ports(hw_regs_t *hw, unsigned long base,
hw->chipset = ide_generic;
}
+static const struct ide_port_info gayle_port_info = {
+ .host_flags = IDE_HFLAG_SERIALIZE | IDE_HFLAG_NO_DMA,
+};
+
/*
* Probe for a Gayle IDE interface (and optionally for an IDE doubler)
*/
@@ -178,7 +182,7 @@ found:
hws[i] = &hw[i];
}
- rc = ide_host_add(NULL, hws, NULL);
+ rc = ide_host_add(&gayle_port_info, hws, NULL);
if (rc)
release_mem_region(res_start, res_n);
diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c
index f5afd46..b18e10d 100644
--- a/drivers/ide/hpt366.c
+++ b/drivers/ide/hpt366.c
@@ -135,7 +135,6 @@
/* various tuning parameters */
#define HPT_RESET_STATE_ENGINE
#undef HPT_DELAY_INTERRUPT
-#define HPT_SERIALIZE_IO 0
static const char *quirk_drives[] = {
"QUANTUM FIREBALLlct08 08",
@@ -1288,7 +1287,6 @@ static u8 hpt3xx_cable_detect(ide_hwif_t *hwif)
static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
{
struct hpt_info *info = hpt3xx_get_info(hwif->dev);
- int serialize = HPT_SERIALIZE_IO;
u8 chip_type = info->chip_type;
/* Cache the channel's MISC. control registers' offset */
@@ -1305,13 +1303,9 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
* Clock is shared between the channels,
* so we'll have to serialize them... :-(
*/
- serialize = 1;
+ hwif->host->host_flags |= IDE_HFLAG_SERIALIZE;
hwif->rw_disk = &hpt3xxn_rw_disk;
}
-
- /* Serialize access to this device if needed */
- if (serialize && hwif->mate)
- hwif->serialized = hwif->mate->serialized = 1;
}
static int __devinit init_dma_hpt366(ide_hwif_t *hwif,
diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c
index 244a8a0..fd4a364 100644
--- a/drivers/ide/ide-acpi.c
+++ b/drivers/ide/ide-acpi.c
@@ -615,10 +615,10 @@ void ide_acpi_push_timing(ide_hwif_t *hwif)
in_params[0].buffer.length = sizeof(struct GTM_buffer);
in_params[0].buffer.pointer = (u8 *)&hwif->acpidata->gtm;
in_params[1].type = ACPI_TYPE_BUFFER;
- in_params[1].buffer.length = sizeof(ATA_ID_WORDS * 2);
+ in_params[1].buffer.length = ATA_ID_WORDS * 2;
in_params[1].buffer.pointer = (u8 *)&master->idbuff;
in_params[2].type = ACPI_TYPE_BUFFER;
- in_params[2].buffer.length = sizeof(ATA_ID_WORDS * 2);
+ in_params[2].buffer.length = ATA_ID_WORDS * 2;
in_params[2].buffer.pointer = (u8 *)&slave->idbuff;
/* Output buffer: _STM has no output */
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 42ab6d8..5daa4dd 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -262,7 +262,6 @@ static void cdrom_end_request(ide_drive_t *drive, int uptodate)
struct request *failed = (struct request *) rq->buffer;
struct cdrom_info *info = drive->driver_data;
void *sense = &info->sense_data;
- unsigned long flags;
if (failed) {
if (failed->sense) {
@@ -278,11 +277,9 @@ static void cdrom_end_request(ide_drive_t *drive, int uptodate)
failed->hard_nr_sectors))
BUG();
} else {
- spin_lock_irqsave(&ide_lock, flags);
- if (__blk_end_request(failed, -EIO,
- failed->data_len))
+ if (blk_end_request(failed, -EIO,
+ failed->data_len))
BUG();
- spin_unlock_irqrestore(&ide_lock, flags);
}
} else
cdrom_analyze_sense_data(drive, NULL, sense);
@@ -317,7 +314,8 @@ static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 st)
static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
{
ide_hwif_t *hwif = drive->hwif;
- struct request *rq = hwif->hwgroup->rq;
+ ide_hwgroup_t *hwgroup = hwif->hwgroup;
+ struct request *rq = hwgroup->rq;
int stat, err, sense_key;
/* check for errors */
@@ -426,16 +424,17 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
if (time_after(jiffies, info->write_timeout))
do_end_request = 1;
else {
+ struct request_queue *q = drive->queue;
unsigned long flags;
/*
* take a breather relying on the unplug
* timer to kick us again
*/
- spin_lock_irqsave(&ide_lock, flags);
- blk_plug_device(drive->queue);
- spin_unlock_irqrestore(&ide_lock,
- flags);
+ spin_lock_irqsave(q->queue_lock, flags);
+ blk_plug_device(q);
+ spin_unlock_irqrestore(q->queue_lock, flags);
+
return 1;
}
}
@@ -504,12 +503,14 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
end_request:
if (stat & ATA_ERR) {
+ struct request_queue *q = drive->queue;
unsigned long flags;
- spin_lock_irqsave(&ide_lock, flags);
+ spin_lock_irqsave(q->queue_lock, flags);
blkdev_dequeue_request(rq);
- HWGROUP(drive)->rq = NULL;
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(q->queue_lock, flags);
+
+ hwgroup->rq = NULL;
cdrom_queue_request_sense(drive, rq->sense, rq);
} else
@@ -773,52 +774,6 @@ static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive)
return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr);
}
-#define IDECD_SEEK_THRESHOLD (1000) /* 1000 blocks */
-#define IDECD_SEEK_TIMER (5 * WAIT_MIN_SLEEP) /* 100 ms */
-#define IDECD_SEEK_TIMEOUT (2 * WAIT_CMD) /* 20 sec */
-
-static ide_startstop_t cdrom_seek_intr(ide_drive_t *drive)
-{
- struct cdrom_info *info = drive->driver_data;
- int stat;
- static int retry = 10;
-
- ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
-
- if (cdrom_decode_status(drive, 0, &stat))
- return ide_stopped;
-
- drive->atapi_flags |= IDE_AFLAG_SEEKING;
-
- if (retry && time_after(jiffies, info->start_seek + IDECD_SEEK_TIMER)) {
- if (--retry == 0)
- drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
- }
- return ide_stopped;
-}
-
-static void ide_cd_prepare_seek_request(ide_drive_t *drive, struct request *rq)
-{
- sector_t frame = rq->sector;
-
- ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
-
- sector_div(frame, queue_hardsect_size(drive->queue) >> SECTOR_BITS);
-
- memset(rq->cmd, 0, BLK_MAX_CDB);
- rq->cmd[0] = GPCMD_SEEK;
- put_unaligned(cpu_to_be32(frame), (unsigned int *) &rq->cmd[2]);
-
- rq->timeout = ATAPI_WAIT_PC;
-}
-
-static ide_startstop_t cdrom_start_seek_continuation(ide_drive_t *drive)
-{
- struct request *rq = drive->hwif->hwgroup->rq;
-
- return cdrom_transfer_packet_command(drive, rq, &cdrom_seek_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.
@@ -950,7 +905,8 @@ static int cdrom_newpc_intr_dummy_cb(struct request *rq)
static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
- struct request *rq = HWGROUP(drive)->rq;
+ ide_hwgroup_t *hwgroup = hwif->hwgroup;
+ struct request *rq = hwgroup->rq;
xfer_func_t *xferfunc;
ide_expiry_t *expiry = NULL;
int dma_error = 0, dma, stat, thislen, uptodate = 0;
@@ -1148,17 +1104,15 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
end_request:
if (blk_pc_request(rq)) {
- unsigned long flags;
unsigned int dlen = rq->data_len;
if (dma)
rq->data_len = 0;
- spin_lock_irqsave(&ide_lock, flags);
- if (__blk_end_request(rq, 0, dlen))
+ if (blk_end_request(rq, 0, dlen))
BUG();
- HWGROUP(drive)->rq = NULL;
- spin_unlock_irqrestore(&ide_lock, flags);
+
+ hwgroup->rq = NULL;
} else {
if (!uptodate)
rq->cmd_flags |= REQ_FAILED;
@@ -1260,7 +1214,6 @@ 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)
{
- struct cdrom_info *info = drive->driver_data;
ide_handler_t *fn;
int xferlen;
@@ -1270,44 +1223,14 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
(unsigned long long)block);
if (blk_fs_request(rq)) {
- if (drive->atapi_flags & IDE_AFLAG_SEEKING) {
- ide_hwif_t *hwif = drive->hwif;
- unsigned long elapsed = jiffies - info->start_seek;
- int stat = hwif->tp_ops->read_status(hwif);
-
- if ((stat & ATA_DSC) != ATA_DSC) {
- if (elapsed < IDECD_SEEK_TIMEOUT) {
- ide_stall_queue(drive,
- IDECD_SEEK_TIMER);
- return ide_stopped;
- }
- printk(KERN_ERR PFX "%s: DSC timeout\n",
- drive->name);
- }
- drive->atapi_flags &= ~IDE_AFLAG_SEEKING;
- }
- if (rq_data_dir(rq) == READ &&
- IDE_LARGE_SEEK(info->last_block, block,
- IDECD_SEEK_THRESHOLD) &&
- (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP)) {
- xferlen = 0;
- fn = cdrom_start_seek_continuation;
+ xferlen = 32768;
+ fn = cdrom_start_rw_cont;
- drive->dma = 0;
- info->start_seek = jiffies;
-
- ide_cd_prepare_seek_request(drive, rq);
- } else {
- xferlen = 32768;
- fn = cdrom_start_rw_cont;
-
- if (cdrom_start_rw(drive, rq) == ide_stopped)
- return ide_stopped;
+ if (cdrom_start_rw(drive, rq) == ide_stopped)
+ return ide_stopped;
- if (ide_cd_prepare_rw_request(drive, rq) == ide_stopped)
- return ide_stopped;
- }
- info->last_block = block;
+ if (ide_cd_prepare_rw_request(drive, rq) == ide_stopped)
+ return ide_stopped;
} else if (blk_sense_request(rq) || blk_pc_request(rq) ||
rq->cmd_type == REQ_TYPE_ATA_PC) {
xferlen = rq->data_len;
@@ -1908,13 +1831,6 @@ static ide_proc_entry_t idecd_proc[] = {
{ NULL, 0, NULL, NULL }
};
-ide_devset_rw_flag(dsc_overlap, IDE_DFLAG_DSC_OVERLAP);
-
-static const struct ide_proc_devset idecd_settings[] = {
- IDE_PROC_DEVSET(dsc_overlap, 0, 1),
- { 0 },
-};
-
static ide_proc_entry_t *ide_cd_proc_entries(ide_drive_t *drive)
{
return idecd_proc;
@@ -1922,7 +1838,7 @@ static ide_proc_entry_t *ide_cd_proc_entries(ide_drive_t *drive)
static const struct ide_proc_devset *ide_cd_proc_devsets(ide_drive_t *drive)
{
- return idecd_settings;
+ return NULL;
}
#endif
@@ -2022,11 +1938,6 @@ static int ide_cdrom_setup(ide_drive_t *drive)
/* set correct block size */
blk_queue_hardsect_size(drive->queue, CD_FRAMESIZE);
- if (drive->next != drive)
- drive->dev_flags |= IDE_DFLAG_DSC_OVERLAP;
- else
- drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
-
if (ide_cdrom_register(drive, nslots)) {
printk(KERN_ERR PFX "%s: %s failed to register device with the"
" cdrom driver.\n", drive->name, __func__);
@@ -2063,7 +1974,6 @@ static void ide_cd_release(struct kref *kref)
kfree(info->toc);
if (devinfo->handle == drive)
unregister_cdrom(devinfo);
- drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
drive->driver_data = NULL;
blk_queue_prep_rq(drive->queue, NULL);
g->private_data = NULL;
diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h
index 5882b9a..d5ce336 100644
--- a/drivers/ide/ide-cd.h
+++ b/drivers/ide/ide-cd.h
@@ -88,8 +88,6 @@ struct cdrom_info {
struct request_sense sense_data;
struct request request_sense_request;
- unsigned long last_block;
- unsigned long start_seek;
u8 max_speed; /* Max speed of the drive. */
u8 current_speed; /* Current speed of the drive. */
diff --git a/drivers/ide/ide-dma-sff.c b/drivers/ide/ide-dma-sff.c
index cac431f..f6d2d44 100644
--- a/drivers/ide/ide-dma-sff.c
+++ b/drivers/ide/ide-dma-sff.c
@@ -98,10 +98,10 @@ int ide_build_dmatable(ide_drive_t *drive, struct request *rq)
{
ide_hwif_t *hwif = drive->hwif;
__le32 *table = (__le32 *)hwif->dmatable_cpu;
- unsigned int is_trm290 = (hwif->chipset == ide_trm290) ? 1 : 0;
unsigned int count = 0;
int i;
struct scatterlist *sg;
+ u8 is_trm290 = !!(hwif->host_flags & IDE_HFLAG_TRM290);
hwif->sg_nents = ide_build_sglist(drive, rq);
if (hwif->sg_nents == 0)
@@ -176,15 +176,10 @@ int ide_dma_setup(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
struct request *rq = hwif->hwgroup->rq;
- unsigned int reading;
+ unsigned int reading = rq_data_dir(rq) ? 0 : ATA_DMA_WR;
u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
u8 dma_stat;
- if (rq_data_dir(rq))
- reading = 0;
- else
- reading = 1 << 3;
-
/* fall back to pio! */
if (!ide_build_dmatable(drive, rq)) {
ide_map_sg(drive, rq);
@@ -209,10 +204,11 @@ int ide_dma_setup(ide_drive_t *drive)
/* clear INTR & ERROR flags */
if (mmio)
- writeb(dma_stat | 6,
+ writeb(dma_stat | ATA_DMA_ERR | ATA_DMA_INTR,
(void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
else
- outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS);
+ outb(dma_stat | ATA_DMA_ERR | ATA_DMA_INTR,
+ hwif->dma_base + ATA_DMA_STATUS);
drive->waiting_for_dma = 1;
return 0;
@@ -246,14 +242,13 @@ static int dma_timer_expiry(ide_drive_t *drive)
hwif->hwgroup->expiry = NULL; /* one free ride for now */
- /* 1 dmaing, 2 error, 4 intr */
- if (dma_stat & 2) /* ERROR */
+ if (dma_stat & ATA_DMA_ERR) /* ERROR */
return -1;
- if (dma_stat & 1) /* DMAing */
+ if (dma_stat & ATA_DMA_ACTIVE) /* DMAing */
return WAIT_CMD;
- if (dma_stat & 4) /* Got an Interrupt */
+ if (dma_stat & ATA_DMA_INTR) /* Got an Interrupt */
return WAIT_CMD;
return 0; /* Status is unknown -- reset the bus */
@@ -279,12 +274,11 @@ void ide_dma_start(ide_drive_t *drive)
*/
if (hwif->host_flags & IDE_HFLAG_MMIO) {
dma_cmd = readb((void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
- /* start DMA */
- writeb(dma_cmd | 1,
+ writeb(dma_cmd | ATA_DMA_START,
(void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
} else {
dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
- outb(dma_cmd | 1, hwif->dma_base + ATA_DMA_CMD);
+ outb(dma_cmd | ATA_DMA_START, hwif->dma_base + ATA_DMA_CMD);
}
wmb();
@@ -296,19 +290,18 @@ int ide_dma_end(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
- u8 dma_stat = 0, dma_cmd = 0;
+ u8 dma_stat = 0, dma_cmd = 0, mask;
drive->waiting_for_dma = 0;
+ /* stop DMA */
if (mmio) {
- /* get DMA command mode */
dma_cmd = readb((void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
- /* stop DMA */
- writeb(dma_cmd & ~1,
+ writeb(dma_cmd & ~ATA_DMA_START,
(void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
} else {
dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
- outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD);
+ outb(dma_cmd & ~ATA_DMA_START, hwif->dma_base + ATA_DMA_CMD);
}
/* get DMA status */
@@ -316,16 +309,21 @@ int ide_dma_end(ide_drive_t *drive)
if (mmio)
/* clear the INTR & ERROR bits */
- writeb(dma_stat | 6,
+ writeb(dma_stat | ATA_DMA_ERR | ATA_DMA_INTR,
(void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
else
- outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS);
+ outb(dma_stat | ATA_DMA_ERR | ATA_DMA_INTR,
+ hwif->dma_base + ATA_DMA_STATUS);
/* purge DMA mappings */
ide_destroy_dmatable(drive);
- /* verify good DMA status */
wmb();
- return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0;
+
+ /* verify good DMA status */
+ mask = ATA_DMA_ACTIVE | ATA_DMA_ERR | ATA_DMA_INTR;
+ if ((dma_stat & mask) != ATA_DMA_INTR)
+ return 0x10 | dma_stat;
+ return 0;
}
EXPORT_SYMBOL_GPL(ide_dma_end);
@@ -335,11 +333,7 @@ int ide_dma_test_irq(ide_drive_t *drive)
ide_hwif_t *hwif = drive->hwif;
u8 dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
- /* return 1 if INTR asserted */
- if ((dma_stat & 4) == 4)
- return 1;
-
- return 0;
+ return (dma_stat & ATA_DMA_INTR) ? 1 : 0;
}
EXPORT_SYMBOL_GPL(ide_dma_test_irq);
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index cc35d6d..ecacc00 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -84,11 +84,11 @@ static int __ide_end_request(ide_drive_t *drive, struct request *rq,
ide_dma_on(drive);
}
- if (!__blk_end_request(rq, error, nr_bytes)) {
- if (dequeue)
- HWGROUP(drive)->rq = NULL;
+ if (!blk_end_request(rq, error, nr_bytes))
ret = 0;
- }
+
+ if (ret == 0 && dequeue)
+ drive->hwif->hwgroup->rq = NULL;
return ret;
}
@@ -107,16 +107,7 @@ static int __ide_end_request(ide_drive_t *drive, struct request *rq,
int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors)
{
unsigned int nr_bytes = nr_sectors << 9;
- struct request *rq;
- unsigned long flags;
- int ret = 1;
-
- /*
- * room for locking improvements here, the calls below don't
- * need the queue lock held at all
- */
- spin_lock_irqsave(&ide_lock, flags);
- rq = HWGROUP(drive)->rq;
+ struct request *rq = drive->hwif->hwgroup->rq;
if (!nr_bytes) {
if (blk_pc_request(rq))
@@ -125,105 +116,10 @@ int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors)
nr_bytes = rq->hard_cur_sectors << 9;
}
- ret = __ide_end_request(drive, rq, uptodate, nr_bytes, 1);
-
- spin_unlock_irqrestore(&ide_lock, flags);
- return ret;
+ return __ide_end_request(drive, rq, uptodate, nr_bytes, 1);
}
EXPORT_SYMBOL(ide_end_request);
-static void ide_complete_power_step(ide_drive_t *drive, struct request *rq)
-{
- struct request_pm_state *pm = rq->data;
-
-#ifdef DEBUG_PM
- printk(KERN_INFO "%s: complete_power_step(step: %d)\n",
- drive->name, pm->pm_step);
-#endif
- if (drive->media != ide_disk)
- return;
-
- switch (pm->pm_step) {
- case IDE_PM_FLUSH_CACHE: /* Suspend step 1 (flush cache) */
- if (pm->pm_state == PM_EVENT_FREEZE)
- pm->pm_step = IDE_PM_COMPLETED;
- else
- pm->pm_step = IDE_PM_STANDBY;
- break;
- case IDE_PM_STANDBY: /* Suspend step 2 (standby) */
- pm->pm_step = IDE_PM_COMPLETED;
- break;
- case IDE_PM_RESTORE_PIO: /* Resume step 1 (restore PIO) */
- pm->pm_step = IDE_PM_IDLE;
- break;
- case IDE_PM_IDLE: /* Resume step 2 (idle)*/
- pm->pm_step = IDE_PM_RESTORE_DMA;
- break;
- }
-}
-
-static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq)
-{
- struct request_pm_state *pm = rq->data;
- ide_task_t *args = rq->special;
-
- memset(args, 0, sizeof(*args));
-
- switch (pm->pm_step) {
- case IDE_PM_FLUSH_CACHE: /* Suspend step 1 (flush cache) */
- if (drive->media != ide_disk)
- break;
- /* Not supported? Switch to next step now. */
- if (ata_id_flush_enabled(drive->id) == 0 ||
- (drive->dev_flags & IDE_DFLAG_WCACHE) == 0) {
- ide_complete_power_step(drive, rq);
- return ide_stopped;
- }
- if (ata_id_flush_ext_enabled(drive->id))
- args->tf.command = ATA_CMD_FLUSH_EXT;
- else
- args->tf.command = ATA_CMD_FLUSH;
- goto out_do_tf;
- case IDE_PM_STANDBY: /* Suspend step 2 (standby) */
- args->tf.command = ATA_CMD_STANDBYNOW1;
- goto out_do_tf;
- case IDE_PM_RESTORE_PIO: /* Resume step 1 (restore PIO) */
- ide_set_max_pio(drive);
- /*
- * skip IDE_PM_IDLE for ATAPI devices
- */
- if (drive->media != ide_disk)
- pm->pm_step = IDE_PM_RESTORE_DMA;
- else
- ide_complete_power_step(drive, rq);
- return ide_stopped;
- case IDE_PM_IDLE: /* Resume step 2 (idle) */
- args->tf.command = ATA_CMD_IDLEIMMEDIATE;
- goto out_do_tf;
- case IDE_PM_RESTORE_DMA: /* Resume step 3 (restore DMA) */
- /*
- * Right now, all we do is call ide_set_dma(drive),
- * we could be smarter and check for current xfer_speed
- * in struct drive etc...
- */
- if (drive->hwif->dma_ops == NULL)
- break;
- /*
- * TODO: respect IDE_DFLAG_USING_DMA
- */
- ide_set_dma(drive);
- break;
- }
-
- pm->pm_step = IDE_PM_COMPLETED;
- return ide_stopped;
-
-out_do_tf:
- args->tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
- args->data_phase = TASKFILE_NO_DATA;
- return do_rw_taskfile(drive, args);
-}
-
/**
* ide_end_dequeued_request - complete an IDE I/O
* @drive: IDE device for the I/O
@@ -242,48 +138,12 @@ out_do_tf:
int ide_end_dequeued_request(ide_drive_t *drive, struct request *rq,
int uptodate, int nr_sectors)
{
- unsigned long flags;
- int ret;
-
- spin_lock_irqsave(&ide_lock, flags);
BUG_ON(!blk_rq_started(rq));
- ret = __ide_end_request(drive, rq, uptodate, nr_sectors << 9, 0);
- spin_unlock_irqrestore(&ide_lock, flags);
- return ret;
+ return __ide_end_request(drive, rq, uptodate, nr_sectors << 9, 0);
}
EXPORT_SYMBOL_GPL(ide_end_dequeued_request);
-
-/**
- * ide_complete_pm_request - end the current Power Management request
- * @drive: target drive
- * @rq: request
- *
- * This function cleans up the current PM request and stops the queue
- * if necessary.
- */
-static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq)
-{
- unsigned long flags;
-
-#ifdef DEBUG_PM
- printk("%s: completing PM request, %s\n", drive->name,
- blk_pm_suspend_request(rq) ? "suspend" : "resume");
-#endif
- spin_lock_irqsave(&ide_lock, flags);
- if (blk_pm_suspend_request(rq)) {
- blk_stop_queue(drive->queue);
- } else {
- drive->dev_flags &= ~IDE_DFLAG_BLOCKED;
- blk_start_queue(drive->queue);
- }
- HWGROUP(drive)->rq = NULL;
- if (__blk_end_request(rq, 0, 0))
- BUG();
- spin_unlock_irqrestore(&ide_lock, flags);
-}
-
/**
* ide_end_drive_cmd - end an explicit drive command
* @drive: command
@@ -300,19 +160,12 @@ static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq)
void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
{
- unsigned long flags;
- struct request *rq;
-
- spin_lock_irqsave(&ide_lock, flags);
- rq = HWGROUP(drive)->rq;
- spin_unlock_irqrestore(&ide_lock, flags);
+ ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;
+ struct request *rq = hwgroup->rq;
if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
ide_task_t *task = (ide_task_t *)rq->special;
- if (rq->errors == 0)
- rq->errors = !OK_STAT(stat, ATA_DRDY, BAD_STAT);
-
if (task) {
struct ide_taskfile *tf = &task->tf;
@@ -333,15 +186,14 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
return;
}
- spin_lock_irqsave(&ide_lock, flags);
- HWGROUP(drive)->rq = NULL;
+ hwgroup->rq = NULL;
+
rq->errors = err;
- if (unlikely(__blk_end_request(rq, (rq->errors ? -EIO : 0),
- blk_rq_bytes(rq))))
+
+ if (unlikely(blk_end_request(rq, (rq->errors ? -EIO : 0),
+ blk_rq_bytes(rq))))
BUG();
- spin_unlock_irqrestore(&ide_lock, flags);
}
-
EXPORT_SYMBOL(ide_end_drive_cmd);
static void ide_kill_rq(ide_drive_t *drive, struct request *rq)
@@ -720,40 +572,6 @@ static ide_startstop_t ide_special_rq(ide_drive_t *drive, struct request *rq)
}
}
-static void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
-{
- struct request_pm_state *pm = rq->data;
-
- if (blk_pm_suspend_request(rq) &&
- pm->pm_step == IDE_PM_START_SUSPEND)
- /* Mark drive blocked when starting the suspend sequence. */
- drive->dev_flags |= IDE_DFLAG_BLOCKED;
- else if (blk_pm_resume_request(rq) &&
- pm->pm_step == IDE_PM_START_RESUME) {
- /*
- * The first thing we do on wakeup is to wait for BSY bit to
- * go away (with a looong timeout) as a drive on this hwif may
- * just be POSTing itself.
- * We do that before even selecting as the "other" device on
- * the bus may be broken enough to walk on our toes at this
- * point.
- */
- ide_hwif_t *hwif = drive->hwif;
- int rc;
-#ifdef DEBUG_PM
- printk("%s: Wakeup request inited, waiting for !BSY...\n", drive->name);
-#endif
- rc = ide_wait_not_busy(hwif, 35000);
- if (rc)
- printk(KERN_WARNING "%s: bus not ready on wakeup\n", drive->name);
- SELECT_DRIVE(drive);
- hwif->tp_ops->set_irq(hwif, 1);
- rc = ide_wait_not_busy(hwif, 100000);
- if (rc)
- printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name);
- }
-}
-
/**
* start_request - start of I/O and command issuing for IDE
*
@@ -927,7 +745,7 @@ repeat:
/*
* Issue a new request to a drive from hwgroup
- * Caller must have already done spin_lock_irqsave(&ide_lock, ..);
+ * 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)
@@ -939,7 +757,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 the single global ide_lock spinlock to protect
+ * The IDE driver uses a per-hwgroup spinlock to protect
* access to the request queues, and to protect the hwgroup->busy flag.
*
* The first thread into the driver for a particular hwgroup sets the
@@ -955,7 +773,7 @@ repeat:
* will start the next request from the queue. If no more work remains,
* the driver will clear the hwgroup->busy flag and exit.
*
- * The ide_lock (spinlock) is used to protect all access to the
+ * The per-hwgroup spinlock is used to protect all access to the
* hwgroup->busy flag, but is otherwise not needed for most processing in
* the driver. This makes the driver much more friendlier to shared IRQs
* than previous designs, while remaining 100% (?) SMP safe and capable.
@@ -968,7 +786,7 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
ide_startstop_t startstop;
int loops = 0;
- /* caller must own ide_lock */
+ /* caller must own hwgroup->lock */
BUG_ON(!irqs_disabled());
while (!hwgroup->busy) {
@@ -1023,12 +841,12 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
}
again:
hwif = HWIF(drive);
- if (hwgroup->hwif->sharing_irq && hwif != hwgroup->hwif) {
+ if (hwif != hwgroup->hwif) {
/*
* set nIEN for previous hwif, drives in the
* quirk_list may not like intr setups/cleanups
*/
- if (drive->quirk_list != 1)
+ if (drive->quirk_list == 0)
hwif->tp_ops->set_irq(hwif, 0);
}
hwgroup->hwif = hwif;
@@ -1036,11 +854,6 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
drive->dev_flags &= ~(IDE_DFLAG_SLEEPING | IDE_DFLAG_PARKED);
drive->service_start = jiffies;
- if (blk_queue_plugged(drive->queue)) {
- printk(KERN_ERR "ide: huh? queue was plugged!\n");
- break;
- }
-
/*
* we know that the queue isn't empty, but this can happen
* if the q->prep_rq_fn() decides to kill a request
@@ -1090,11 +903,11 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
*/
if (masked_irq != IDE_NO_IRQ && hwif->irq != masked_irq)
disable_irq_nosync(hwif->irq);
- spin_unlock(&ide_lock);
+ spin_unlock(&hwgroup->lock);
local_irq_enable_in_hardirq();
/* allow other IRQs while we start this request */
startstop = start_request(drive, rq);
- spin_lock_irq(&ide_lock);
+ spin_lock_irq(&hwgroup->lock);
if (masked_irq != IDE_NO_IRQ && hwif->irq != masked_irq)
enable_irq(hwif->irq);
if (startstop == ide_stopped)
@@ -1192,7 +1005,7 @@ void ide_timer_expiry (unsigned long data)
unsigned long flags;
unsigned long wait = -1;
- spin_lock_irqsave(&ide_lock, flags);
+ spin_lock_irqsave(&hwgroup->lock, flags);
if (((handler = hwgroup->handler) == NULL) ||
(hwgroup->req_gen != hwgroup->req_gen_timer)) {
@@ -1225,7 +1038,7 @@ void ide_timer_expiry (unsigned long data)
hwgroup->timer.expires = jiffies + wait;
hwgroup->req_gen_timer = hwgroup->req_gen;
add_timer(&hwgroup->timer);
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&hwgroup->lock, flags);
return;
}
}
@@ -1235,7 +1048,7 @@ void ide_timer_expiry (unsigned long data)
* the handler() function, which means we need to
* globally mask the specific IRQ:
*/
- spin_unlock(&ide_lock);
+ spin_unlock(&hwgroup->lock);
hwif = HWIF(drive);
/* disable_irq_nosync ?? */
disable_irq(hwif->irq);
@@ -1259,14 +1072,14 @@ void ide_timer_expiry (unsigned long data)
hwif->tp_ops->read_status(hwif));
}
drive->service_time = jiffies - drive->service_start;
- spin_lock_irq(&ide_lock);
+ spin_lock_irq(&hwgroup->lock);
enable_irq(hwif->irq);
if (startstop == ide_stopped)
hwgroup->busy = 0;
}
}
ide_do_request(hwgroup, IDE_NO_IRQ);
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&hwgroup->lock, flags);
}
/**
@@ -1359,18 +1172,16 @@ 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;
+ ide_hwif_t *hwif = hwgroup->hwif;
ide_drive_t *drive;
ide_handler_t *handler;
ide_startstop_t startstop;
+ irqreturn_t irq_ret = IRQ_NONE;
- spin_lock_irqsave(&ide_lock, flags);
- hwif = hwgroup->hwif;
+ spin_lock_irqsave(&hwgroup->lock, flags);
- if (!ide_ack_intr(hwif)) {
- spin_unlock_irqrestore(&ide_lock, flags);
- return IRQ_NONE;
- }
+ if (!ide_ack_intr(hwif))
+ goto out;
if ((handler = hwgroup->handler) == NULL || hwgroup->polling) {
/*
@@ -1406,9 +1217,9 @@ irqreturn_t ide_intr (int irq, void *dev_id)
(void)hwif->tp_ops->read_status(hwif);
#endif /* CONFIG_BLK_DEV_IDEPCI */
}
- spin_unlock_irqrestore(&ide_lock, flags);
- return IRQ_NONE;
+ goto out;
}
+
drive = hwgroup->drive;
if (!drive) {
/*
@@ -1417,10 +1228,10 @@ irqreturn_t ide_intr (int irq, void *dev_id)
*
* [Note - this can occur if the drive is hot unplugged]
*/
- spin_unlock_irqrestore(&ide_lock, flags);
- return IRQ_HANDLED;
+ goto out_handled;
}
- if (!drive_is_ready(drive)) {
+
+ if (!drive_is_ready(drive))
/*
* This happens regularly when we share a PCI IRQ with
* another device. Unfortunately, it can also happen
@@ -1428,9 +1239,8 @@ irqreturn_t ide_intr (int irq, void *dev_id)
* their status register is up to date. Hopefully we have
* enough advance overhead that the latter isn't a problem.
*/
- spin_unlock_irqrestore(&ide_lock, flags);
- return IRQ_NONE;
- }
+ goto out;
+
if (!hwgroup->busy) {
hwgroup->busy = 1; /* paranoia */
printk(KERN_ERR "%s: ide_intr: hwgroup->busy was 0 ??\n", drive->name);
@@ -1438,7 +1248,7 @@ irqreturn_t ide_intr (int irq, void *dev_id)
hwgroup->handler = NULL;
hwgroup->req_gen++;
del_timer(&hwgroup->timer);
- spin_unlock(&ide_lock);
+ spin_unlock(&hwgroup->lock);
if (hwif->port_ops && hwif->port_ops->clear_irq)
hwif->port_ops->clear_irq(drive);
@@ -1449,7 +1259,7 @@ irqreturn_t ide_intr (int irq, void *dev_id)
/* service this interrupt, may set handler for next interrupt */
startstop = handler(drive);
- spin_lock_irq(&ide_lock);
+ spin_lock_irq(&hwgroup->lock);
/*
* Note that handler() may have set things up for another
* interrupt to occur soon, but it cannot happen until
@@ -1467,8 +1277,11 @@ irqreturn_t ide_intr (int irq, void *dev_id)
"on exit\n", drive->name);
}
}
- spin_unlock_irqrestore(&ide_lock, flags);
- return IRQ_HANDLED;
+out_handled:
+ irq_ret = IRQ_HANDLED;
+out:
+ spin_unlock_irqrestore(&hwgroup->lock, flags);
+ return irq_ret;
}
/**
@@ -1488,16 +1301,17 @@ irqreturn_t ide_intr (int irq, void *dev_id)
void ide_do_drive_cmd(ide_drive_t *drive, struct request *rq)
{
+ ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;
+ struct request_queue *q = drive->queue;
unsigned long flags;
- ide_hwgroup_t *hwgroup = HWGROUP(drive);
- spin_lock_irqsave(&ide_lock, flags);
hwgroup->rq = NULL;
- __elv_add_request(drive->queue, rq, ELEVATOR_INSERT_FRONT, 0);
- blk_start_queueing(drive->queue);
- spin_unlock_irqrestore(&ide_lock, flags);
-}
+ spin_lock_irqsave(q->queue_lock, flags);
+ __elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0);
+ blk_start_queueing(q);
+ spin_unlock_irqrestore(q->queue_lock, flags);
+}
EXPORT_SYMBOL(ide_do_drive_cmd);
void ide_pktcmd_tf_load(ide_drive_t *drive, u32 tf_flags, u16 bcount, u8 dma)
diff --git a/drivers/ide/ide-ioctls.c b/drivers/ide/ide-ioctls.c
index fcde16b..28232c6 100644
--- a/drivers/ide/ide-ioctls.c
+++ b/drivers/ide/ide-ioctls.c
@@ -19,7 +19,6 @@ int ide_setting_ioctl(ide_drive_t *drive, struct block_device *bdev,
const struct ide_ioctl_devset *s)
{
const struct ide_devset *ds;
- unsigned long flags;
int err = -EOPNOTSUPP;
for (; (ds = s->setting); s++) {
@@ -33,9 +32,7 @@ int ide_setting_ioctl(ide_drive_t *drive, struct block_device *bdev,
read_val:
mutex_lock(&ide_setting_mtx);
- spin_lock_irqsave(&ide_lock, flags);
err = ds->get(drive);
- spin_unlock_irqrestore(&ide_lock, flags);
mutex_unlock(&ide_setting_mtx);
return err >= 0 ? put_user(err, (long __user *)arg) : err;
@@ -98,7 +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_disk || drive->media == ide_floppy ||
+ (drive->media != ide_tape ||
(drive->dev_flags & IDE_DFLAG_SCSI)))
return -EPERM;
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index c41c3b9..ad8bd65 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -835,10 +835,12 @@ static void __ide_set_handler (ide_drive_t *drive, ide_handler_t *handler,
void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler,
unsigned int timeout, ide_expiry_t *expiry)
{
+ ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;
unsigned long flags;
- spin_lock_irqsave(&ide_lock, flags);
+
+ spin_lock_irqsave(&hwgroup->lock, flags);
__ide_set_handler(drive, handler, timeout, expiry);
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&hwgroup->lock, flags);
}
EXPORT_SYMBOL(ide_set_handler);
@@ -860,10 +862,11 @@ EXPORT_SYMBOL(ide_set_handler);
void ide_execute_command(ide_drive_t *drive, u8 cmd, ide_handler_t *handler,
unsigned timeout, ide_expiry_t *expiry)
{
+ ide_hwif_t *hwif = drive->hwif;
+ ide_hwgroup_t *hwgroup = hwif->hwgroup;
unsigned long flags;
- ide_hwif_t *hwif = HWIF(drive);
- spin_lock_irqsave(&ide_lock, flags);
+ spin_lock_irqsave(&hwgroup->lock, flags);
__ide_set_handler(drive, handler, timeout, expiry);
hwif->tp_ops->exec_command(hwif, cmd);
/*
@@ -873,19 +876,20 @@ void ide_execute_command(ide_drive_t *drive, u8 cmd, ide_handler_t *handler,
* FIXME: we could skip this delay with care on non shared devices
*/
ndelay(400);
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&hwgroup->lock, flags);
}
EXPORT_SYMBOL(ide_execute_command);
void ide_execute_pkt_cmd(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
+ ide_hwgroup_t *hwgroup = hwif->hwgroup;
unsigned long flags;
- spin_lock_irqsave(&ide_lock, flags);
+ spin_lock_irqsave(&hwgroup->lock, flags);
hwif->tp_ops->exec_command(hwif, ATA_CMD_PACKET);
ndelay(400);
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&hwgroup->lock, flags);
}
EXPORT_SYMBOL_GPL(ide_execute_pkt_cmd);
@@ -1076,22 +1080,16 @@ static void pre_reset(ide_drive_t *drive)
*/
static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
{
- unsigned int unit;
- unsigned long flags, timeout;
- ide_hwif_t *hwif;
- ide_hwgroup_t *hwgroup;
- struct ide_io_ports *io_ports;
- const struct ide_tp_ops *tp_ops;
+ ide_hwif_t *hwif = drive->hwif;
+ ide_hwgroup_t *hwgroup = hwif->hwgroup;
+ struct ide_io_ports *io_ports = &hwif->io_ports;
+ const struct ide_tp_ops *tp_ops = hwif->tp_ops;
const struct ide_port_ops *port_ops;
+ unsigned long flags, timeout;
+ unsigned int unit;
DEFINE_WAIT(wait);
- spin_lock_irqsave(&ide_lock, flags);
- hwif = HWIF(drive);
- hwgroup = HWGROUP(drive);
-
- io_ports = &hwif->io_ports;
-
- tp_ops = hwif->tp_ops;
+ spin_lock_irqsave(&hwgroup->lock, flags);
/* We must not reset with running handlers */
BUG_ON(hwgroup->handler != NULL);
@@ -1106,7 +1104,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
hwgroup->polling = 1;
__ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL);
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&hwgroup->lock, flags);
return ide_started;
}
@@ -1129,9 +1127,9 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
if (time_before_eq(timeout, now))
break;
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&hwgroup->lock, flags);
timeout = schedule_timeout_uninterruptible(timeout - now);
- spin_lock_irqsave(&ide_lock, flags);
+ spin_lock_irqsave(&hwgroup->lock, flags);
} while (timeout);
finish_wait(&ide_park_wq, &wait);
@@ -1143,7 +1141,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
pre_reset(&hwif->drives[unit]);
if (io_ports->ctl_addr == 0) {
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&hwgroup->lock, flags);
ide_complete_drive_reset(drive, -ENXIO);
return ide_stopped;
}
@@ -1179,7 +1177,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
if (port_ops && port_ops->resetproc)
port_ops->resetproc(drive);
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&hwgroup->lock, flags);
return ide_started;
}
diff --git a/drivers/ide/ide-legacy.c b/drivers/ide/ide-legacy.c
new file mode 100644
index 0000000..8c5dcbf
--- /dev/null
+++ b/drivers/ide/ide-legacy.c
@@ -0,0 +1,58 @@
+#include <linux/kernel.h>
+#include <linux/ide.h>
+
+static void ide_legacy_init_one(hw_regs_t **hws, hw_regs_t *hw,
+ u8 port_no, const struct ide_port_info *d,
+ unsigned long config)
+{
+ unsigned long base, ctl;
+ int irq;
+
+ if (port_no == 0) {
+ base = 0x1f0;
+ ctl = 0x3f6;
+ irq = 14;
+ } else {
+ base = 0x170;
+ ctl = 0x376;
+ irq = 15;
+ }
+
+ if (!request_region(base, 8, d->name)) {
+ printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
+ d->name, base, base + 7);
+ return;
+ }
+
+ if (!request_region(ctl, 1, d->name)) {
+ printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n",
+ d->name, ctl);
+ release_region(base, 8);
+ return;
+ }
+
+ ide_std_init_ports(hw, base, ctl);
+ hw->irq = irq;
+ hw->chipset = d->chipset;
+ hw->config = config;
+
+ hws[port_no] = hw;
+}
+
+int ide_legacy_device_add(const struct ide_port_info *d, unsigned long config)
+{
+ hw_regs_t hw[2], *hws[] = { NULL, NULL, NULL, NULL };
+
+ memset(&hw, 0, sizeof(hw));
+
+ if ((d->host_flags & IDE_HFLAG_QD_2ND_PORT) == 0)
+ ide_legacy_init_one(hws, &hw[0], 0, d, config);
+ ide_legacy_init_one(hws, &hw[1], 1, d, config);
+
+ if (hws[0] == NULL && hws[1] == NULL &&
+ (d->host_flags & IDE_HFLAG_SINGLE))
+ return -ENOENT;
+
+ return ide_host_add(d, hws, NULL);
+}
+EXPORT_SYMBOL_GPL(ide_legacy_device_add);
diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c
index 9fc4cfb..9f6e33d 100644
--- a/drivers/ide/ide-lib.c
+++ b/drivers/ide/ide-lib.c
@@ -43,7 +43,6 @@ const char *ide_xfer_verbose(u8 mode)
return s;
}
-
EXPORT_SYMBOL(ide_xfer_verbose);
/**
@@ -87,7 +86,7 @@ static u8 ide_rate_filter(ide_drive_t *drive, u8 speed)
* This is used by most chipset support modules when "auto-tuning".
*/
-u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode)
+u8 ide_get_best_pio_mode(ide_drive_t *drive, u8 mode_wanted, u8 max_mode)
{
u16 *id = drive->id;
int pio_mode = -1, overridden = 0;
@@ -131,7 +130,6 @@ u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode)
return pio_mode;
}
-
EXPORT_SYMBOL_GPL(ide_get_best_pio_mode);
/* req_pio == "255" for auto-tune */
@@ -162,7 +160,6 @@ void ide_set_pio(ide_drive_t *drive, u8 req_pio)
(void)ide_set_pio_mode(drive, XFER_PIO_0 + pio);
}
-
EXPORT_SYMBOL_GPL(ide_set_pio);
/**
@@ -173,7 +170,7 @@ EXPORT_SYMBOL_GPL(ide_set_pio);
* Enable or disable bounce buffering for the device. Drives move
* between PIO and DMA and that changes the rules we need.
*/
-
+
void ide_toggle_bounce(ide_drive_t *drive, int on)
{
u64 addr = BLK_BOUNCE_HIGH; /* dma64_addr_t */
@@ -243,14 +240,13 @@ int ide_set_dma_mode(ide_drive_t *drive, const u8 mode)
return ide_config_drive_speed(drive, mode);
}
}
-
EXPORT_SYMBOL_GPL(ide_set_dma_mode);
/**
* ide_set_xfer_rate - set transfer rate
* @drive: drive to set
* @rate: speed to attempt to set
- *
+ *
* General helper for setting the speed of an IDE device. This
* function knows about user enforced limits from the configuration
* which ->set_pio_mode/->set_dma_mode does not.
@@ -277,21 +273,16 @@ int ide_set_xfer_rate(ide_drive_t *drive, u8 rate)
static void ide_dump_opcode(ide_drive_t *drive)
{
- struct request *rq;
+ struct request *rq = drive->hwif->hwgroup->rq;
ide_task_t *task = NULL;
- spin_lock(&ide_lock);
- rq = NULL;
- if (HWGROUP(drive))
- rq = HWGROUP(drive)->rq;
- spin_unlock(&ide_lock);
if (!rq)
return;
if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE)
task = rq->special;
- printk("ide: failed opcode was: ");
+ printk(KERN_ERR "ide: failed opcode was: ");
if (task == NULL)
printk(KERN_CONT "unknown\n");
else
@@ -329,44 +320,55 @@ static void ide_dump_sector(ide_drive_t *drive)
drive->hwif->tp_ops->tf_read(drive, &task);
if (lba48 || (tf->device & ATA_LBA))
- printk(", LBAsect=%llu",
+ printk(KERN_CONT ", LBAsect=%llu",
(unsigned long long)ide_get_lba_addr(tf, lba48));
else
- printk(", CHS=%d/%d/%d", (tf->lbah << 8) + tf->lbam,
- tf->device & 0xf, tf->lbal);
+ printk(KERN_CONT ", CHS=%d/%d/%d", (tf->lbah << 8) + tf->lbam,
+ tf->device & 0xf, tf->lbal);
}
static void ide_dump_ata_error(ide_drive_t *drive, u8 err)
{
- printk("{ ");
- if (err & ATA_ABORTED) printk("DriveStatusError ");
+ printk(KERN_ERR "{ ");
+ if (err & ATA_ABORTED)
+ printk(KERN_CONT "DriveStatusError ");
if (err & ATA_ICRC)
- printk((err & ATA_ABORTED) ? "BadCRC " : "BadSector ");
- if (err & ATA_UNC) printk("UncorrectableError ");
- if (err & ATA_IDNF) printk("SectorIdNotFound ");
- if (err & ATA_TRK0NF) printk("TrackZeroNotFound ");
- if (err & ATA_AMNF) printk("AddrMarkNotFound ");
- printk("}");
+ printk(KERN_CONT "%s",
+ (err & ATA_ABORTED) ? "BadCRC " : "BadSector ");
+ if (err & ATA_UNC)
+ printk(KERN_CONT "UncorrectableError ");
+ if (err & ATA_IDNF)
+ printk(KERN_CONT "SectorIdNotFound ");
+ if (err & ATA_TRK0NF)
+ printk(KERN_CONT "TrackZeroNotFound ");
+ if (err & ATA_AMNF)
+ printk(KERN_CONT "AddrMarkNotFound ");
+ printk(KERN_CONT "}");
if ((err & (ATA_BBK | ATA_ABORTED)) == ATA_BBK ||
(err & (ATA_UNC | ATA_IDNF | ATA_AMNF))) {
ide_dump_sector(drive);
if (HWGROUP(drive) && HWGROUP(drive)->rq)
- printk(", sector=%llu",
+ printk(KERN_CONT ", sector=%llu",
(unsigned long long)HWGROUP(drive)->rq->sector);
}
- printk("\n");
+ printk(KERN_CONT "\n");
}
static void ide_dump_atapi_error(ide_drive_t *drive, u8 err)
{
- printk("{ ");
- if (err & ATAPI_ILI) printk("IllegalLengthIndication ");
- if (err & ATAPI_EOM) printk("EndOfMedia ");
- if (err & ATA_ABORTED) printk("AbortedCommand ");
- if (err & ATA_MCR) printk("MediaChangeRequested ");
- if (err & ATAPI_LFS) printk("LastFailedSense=0x%02x ",
- (err & ATAPI_LFS) >> 4);
- printk("}\n");
+ printk(KERN_ERR "{ ");
+ if (err & ATAPI_ILI)
+ printk(KERN_CONT "IllegalLengthIndication ");
+ if (err & ATAPI_EOM)
+ printk(KERN_CONT "EndOfMedia ");
+ if (err & ATA_ABORTED)
+ printk(KERN_CONT "AbortedCommand ");
+ if (err & ATA_MCR)
+ printk(KERN_CONT "MediaChangeRequested ");
+ if (err & ATAPI_LFS)
+ printk(KERN_CONT "LastFailedSense=0x%02x ",
+ (err & ATAPI_LFS) >> 4);
+ printk(KERN_CONT "}\n");
}
/**
@@ -382,34 +384,37 @@ static void ide_dump_atapi_error(ide_drive_t *drive, u8 err)
u8 ide_dump_status(ide_drive_t *drive, const char *msg, u8 stat)
{
- unsigned long flags;
u8 err = 0;
- local_irq_save(flags);
- printk("%s: %s: status=0x%02x { ", drive->name, msg, stat);
+ printk(KERN_ERR "%s: %s: status=0x%02x { ", drive->name, msg, stat);
if (stat & ATA_BUSY)
- printk("Busy ");
+ printk(KERN_CONT "Busy ");
else {
- if (stat & ATA_DRDY) printk("DriveReady ");
- if (stat & ATA_DF) printk("DeviceFault ");
- if (stat & ATA_DSC) printk("SeekComplete ");
- if (stat & ATA_DRQ) printk("DataRequest ");
- if (stat & ATA_CORR) printk("CorrectedError ");
- if (stat & ATA_IDX) printk("Index ");
- if (stat & ATA_ERR) printk("Error ");
+ if (stat & ATA_DRDY)
+ printk(KERN_CONT "DriveReady ");
+ if (stat & ATA_DF)
+ printk(KERN_CONT "DeviceFault ");
+ if (stat & ATA_DSC)
+ printk(KERN_CONT "SeekComplete ");
+ if (stat & ATA_DRQ)
+ printk(KERN_CONT "DataRequest ");
+ if (stat & ATA_CORR)
+ printk(KERN_CONT "CorrectedError ");
+ if (stat & ATA_IDX)
+ printk(KERN_CONT "Index ");
+ if (stat & ATA_ERR)
+ printk(KERN_CONT "Error ");
}
- printk("}\n");
+ printk(KERN_CONT "}\n");
if ((stat & (ATA_BUSY | ATA_ERR)) == ATA_ERR) {
err = ide_read_error(drive);
- printk("%s: %s: error=0x%02x ", drive->name, msg, err);
+ printk(KERN_ERR "%s: %s: error=0x%02x ", drive->name, msg, err);
if (drive->media == ide_disk)
ide_dump_ata_error(drive, err);
else
ide_dump_atapi_error(drive, err);
}
ide_dump_opcode(drive);
- local_irq_restore(flags);
return err;
}
-
EXPORT_SYMBOL(ide_dump_status);
diff --git a/drivers/ide/ide-park.c b/drivers/ide/ide-park.c
index 03b00e5..63d01c5 100644
--- a/drivers/ide/ide-park.c
+++ b/drivers/ide/ide-park.c
@@ -7,17 +7,16 @@ DECLARE_WAIT_QUEUE_HEAD(ide_park_wq);
static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout)
{
+ ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;
struct request_queue *q = drive->queue;
struct request *rq;
int rc;
timeout += jiffies;
- spin_lock_irq(&ide_lock);
+ spin_lock_irq(&hwgroup->lock);
if (drive->dev_flags & IDE_DFLAG_PARKED) {
- ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;
- int reset_timer;
+ int reset_timer = time_before(timeout, drive->sleep);
- reset_timer = time_before(timeout, drive->sleep);
drive->sleep = timeout;
wake_up_all(&ide_park_wq);
if (reset_timer && hwgroup->sleeping &&
@@ -26,10 +25,10 @@ static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout)
hwgroup->busy = 0;
blk_start_queueing(q);
}
- spin_unlock_irq(&ide_lock);
+ spin_unlock_irq(&hwgroup->lock);
return;
}
- spin_unlock_irq(&ide_lock);
+ spin_unlock_irq(&hwgroup->lock);
rq = blk_get_request(q, READ, __GFP_WAIT);
rq->cmd[0] = REQ_PARK_HEADS;
@@ -62,20 +61,21 @@ ssize_t ide_park_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
ide_drive_t *drive = to_ide_device(dev);
+ ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;
unsigned long now;
unsigned int msecs;
if (drive->dev_flags & IDE_DFLAG_NO_UNLOAD)
return -EOPNOTSUPP;
- spin_lock_irq(&ide_lock);
+ spin_lock_irq(&hwgroup->lock);
now = jiffies;
if (drive->dev_flags & IDE_DFLAG_PARKED &&
time_after(drive->sleep, now))
msecs = jiffies_to_msecs(drive->sleep - now);
else
msecs = 0;
- spin_unlock_irq(&ide_lock);
+ spin_unlock_irq(&hwgroup->lock);
return snprintf(buf, 20, "%u\n", msecs);
}
diff --git a/drivers/ide/ide-pm.c b/drivers/ide/ide-pm.c
new file mode 100644
index 0000000..8282c60
--- /dev/null
+++ b/drivers/ide/ide-pm.c
@@ -0,0 +1,235 @@
+#include <linux/kernel.h>
+#include <linux/ide.h>
+#include <linux/hdreg.h>
+
+int generic_ide_suspend(struct device *dev, pm_message_t mesg)
+{
+ ide_drive_t *drive = dev->driver_data, *pair = ide_get_pair_dev(drive);
+ ide_hwif_t *hwif = HWIF(drive);
+ struct request *rq;
+ struct request_pm_state rqpm;
+ ide_task_t args;
+ int ret;
+
+ /* call ACPI _GTM only once */
+ if ((drive->dn & 1) == 0 || pair == NULL)
+ ide_acpi_get_timing(hwif);
+
+ memset(&rqpm, 0, sizeof(rqpm));
+ memset(&args, 0, sizeof(args));
+ rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
+ rq->cmd_type = REQ_TYPE_PM_SUSPEND;
+ rq->special = &args;
+ rq->data = &rqpm;
+ rqpm.pm_step = IDE_PM_START_SUSPEND;
+ if (mesg.event == PM_EVENT_PRETHAW)
+ mesg.event = PM_EVENT_FREEZE;
+ rqpm.pm_state = mesg.event;
+
+ ret = blk_execute_rq(drive->queue, NULL, rq, 0);
+ blk_put_request(rq);
+
+ /* call ACPI _PS3 only after both devices are suspended */
+ if (ret == 0 && ((drive->dn & 1) || pair == NULL))
+ ide_acpi_set_state(hwif, 0);
+
+ return ret;
+}
+
+int generic_ide_resume(struct device *dev)
+{
+ ide_drive_t *drive = dev->driver_data, *pair = ide_get_pair_dev(drive);
+ ide_hwif_t *hwif = HWIF(drive);
+ struct request *rq;
+ struct request_pm_state rqpm;
+ ide_task_t args;
+ int err;
+
+ /* call ACPI _PS0 / _STM only once */
+ if ((drive->dn & 1) == 0 || pair == NULL) {
+ ide_acpi_set_state(hwif, 1);
+ ide_acpi_push_timing(hwif);
+ }
+
+ ide_acpi_exec_tfs(drive);
+
+ memset(&rqpm, 0, sizeof(rqpm));
+ memset(&args, 0, sizeof(args));
+ rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
+ rq->cmd_type = REQ_TYPE_PM_RESUME;
+ rq->cmd_flags |= REQ_PREEMPT;
+ rq->special = &args;
+ rq->data = &rqpm;
+ rqpm.pm_step = IDE_PM_START_RESUME;
+ rqpm.pm_state = PM_EVENT_ON;
+
+ err = blk_execute_rq(drive->queue, NULL, rq, 1);
+ blk_put_request(rq);
+
+ if (err == 0 && dev->driver) {
+ ide_driver_t *drv = to_ide_driver(dev->driver);
+
+ if (drv->resume)
+ drv->resume(drive);
+ }
+
+ return err;
+}
+
+void ide_complete_power_step(ide_drive_t *drive, struct request *rq)
+{
+ struct request_pm_state *pm = rq->data;
+
+#ifdef DEBUG_PM
+ printk(KERN_INFO "%s: complete_power_step(step: %d)\n",
+ drive->name, pm->pm_step);
+#endif
+ if (drive->media != ide_disk)
+ return;
+
+ switch (pm->pm_step) {
+ case IDE_PM_FLUSH_CACHE: /* Suspend step 1 (flush cache) */
+ if (pm->pm_state == PM_EVENT_FREEZE)
+ pm->pm_step = IDE_PM_COMPLETED;
+ else
+ pm->pm_step = IDE_PM_STANDBY;
+ break;
+ case IDE_PM_STANDBY: /* Suspend step 2 (standby) */
+ pm->pm_step = IDE_PM_COMPLETED;
+ break;
+ case IDE_PM_RESTORE_PIO: /* Resume step 1 (restore PIO) */
+ pm->pm_step = IDE_PM_IDLE;
+ break;
+ case IDE_PM_IDLE: /* Resume step 2 (idle)*/
+ pm->pm_step = IDE_PM_RESTORE_DMA;
+ break;
+ }
+}
+
+ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq)
+{
+ struct request_pm_state *pm = rq->data;
+ ide_task_t *args = rq->special;
+
+ memset(args, 0, sizeof(*args));
+
+ switch (pm->pm_step) {
+ case IDE_PM_FLUSH_CACHE: /* Suspend step 1 (flush cache) */
+ if (drive->media != ide_disk)
+ break;
+ /* Not supported? Switch to next step now. */
+ if (ata_id_flush_enabled(drive->id) == 0 ||
+ (drive->dev_flags & IDE_DFLAG_WCACHE) == 0) {
+ ide_complete_power_step(drive, rq);
+ return ide_stopped;
+ }
+ if (ata_id_flush_ext_enabled(drive->id))
+ args->tf.command = ATA_CMD_FLUSH_EXT;
+ else
+ args->tf.command = ATA_CMD_FLUSH;
+ goto out_do_tf;
+ case IDE_PM_STANDBY: /* Suspend step 2 (standby) */
+ args->tf.command = ATA_CMD_STANDBYNOW1;
+ goto out_do_tf;
+ case IDE_PM_RESTORE_PIO: /* Resume step 1 (restore PIO) */
+ ide_set_max_pio(drive);
+ /*
+ * skip IDE_PM_IDLE for ATAPI devices
+ */
+ if (drive->media != ide_disk)
+ pm->pm_step = IDE_PM_RESTORE_DMA;
+ else
+ ide_complete_power_step(drive, rq);
+ return ide_stopped;
+ case IDE_PM_IDLE: /* Resume step 2 (idle) */
+ args->tf.command = ATA_CMD_IDLEIMMEDIATE;
+ goto out_do_tf;
+ case IDE_PM_RESTORE_DMA: /* Resume step 3 (restore DMA) */
+ /*
+ * Right now, all we do is call ide_set_dma(drive),
+ * we could be smarter and check for current xfer_speed
+ * in struct drive etc...
+ */
+ if (drive->hwif->dma_ops == NULL)
+ break;
+ /*
+ * TODO: respect IDE_DFLAG_USING_DMA
+ */
+ ide_set_dma(drive);
+ break;
+ }
+
+ pm->pm_step = IDE_PM_COMPLETED;
+ return ide_stopped;
+
+out_do_tf:
+ args->tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+ args->data_phase = TASKFILE_NO_DATA;
+ return do_rw_taskfile(drive, args);
+}
+
+/**
+ * ide_complete_pm_request - end the current Power Management request
+ * @drive: target drive
+ * @rq: request
+ *
+ * This function cleans up the current PM request and stops the queue
+ * if necessary.
+ */
+void ide_complete_pm_request(ide_drive_t *drive, struct request *rq)
+{
+ struct request_queue *q = drive->queue;
+ unsigned long flags;
+
+#ifdef DEBUG_PM
+ printk("%s: completing PM request, %s\n", drive->name,
+ blk_pm_suspend_request(rq) ? "suspend" : "resume");
+#endif
+ spin_lock_irqsave(q->queue_lock, flags);
+ if (blk_pm_suspend_request(rq)) {
+ blk_stop_queue(q);
+ } else {
+ drive->dev_flags &= ~IDE_DFLAG_BLOCKED;
+ blk_start_queue(q);
+ }
+ spin_unlock_irqrestore(q->queue_lock, flags);
+
+ drive->hwif->hwgroup->rq = NULL;
+
+ if (blk_end_request(rq, 0, 0))
+ BUG();
+}
+
+void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
+{
+ struct request_pm_state *pm = rq->data;
+
+ if (blk_pm_suspend_request(rq) &&
+ pm->pm_step == IDE_PM_START_SUSPEND)
+ /* Mark drive blocked when starting the suspend sequence. */
+ drive->dev_flags |= IDE_DFLAG_BLOCKED;
+ else if (blk_pm_resume_request(rq) &&
+ pm->pm_step == IDE_PM_START_RESUME) {
+ /*
+ * The first thing we do on wakeup is to wait for BSY bit to
+ * go away (with a looong timeout) as a drive on this hwif may
+ * just be POSTing itself.
+ * We do that before even selecting as the "other" device on
+ * the bus may be broken enough to walk on our toes at this
+ * point.
+ */
+ ide_hwif_t *hwif = drive->hwif;
+ int rc;
+#ifdef DEBUG_PM
+ printk("%s: Wakeup request inited, waiting for !BSY...\n", drive->name);
+#endif
+ rc = ide_wait_not_busy(hwif, 35000);
+ if (rc)
+ printk(KERN_WARNING "%s: bus not ready on wakeup\n", drive->name);
+ SELECT_DRIVE(drive);
+ hwif->tp_ops->set_irq(hwif, 1);
+ rc = ide_wait_not_busy(hwif, 100000);
+ if (rc)
+ printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name);
+ }
+}
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index c55bdbd..a64ec25 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -110,20 +110,22 @@ static void ide_disk_init_mult_count(ide_drive_t *drive)
* read and parse the results. This function is run with
* interrupts disabled.
*/
-
-static inline void do_identify (ide_drive_t *drive, u8 cmd)
+
+static void do_identify(ide_drive_t *drive, u8 cmd)
{
ide_hwif_t *hwif = HWIF(drive);
u16 *id = drive->id;
char *m = (char *)&id[ATA_ID_PROD];
+ unsigned long flags;
int bswap = 1, is_cfa;
+ /* local CPU only; some systems need this */
+ local_irq_save(flags);
/* read 512 bytes of id info */
hwif->tp_ops->input_data(drive, NULL, id, SECTOR_SIZE);
+ local_irq_restore(flags);
drive->dev_flags |= IDE_DFLAG_ID_READ;
-
- local_irq_enable();
#ifdef DEBUG
printk(KERN_INFO "%s: dumping identify data\n", drive->name);
ide_dump_identify((u8 *)id);
@@ -306,17 +308,12 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
s = tp_ops->read_status(hwif);
if (OK_STAT(s, ATA_DRQ, BAD_R_STAT)) {
- unsigned long flags;
-
- /* local CPU only; some systems need this */
- local_irq_save(flags);
/* drive returned ID */
do_identify(drive, cmd);
/* drive responded with ID */
rc = 0;
/* clear drive IRQ */
(void)tp_ops->read_status(hwif);
- local_irq_restore(flags);
} else {
/* drive refused ID */
rc = 2;
@@ -554,8 +551,8 @@ static void enable_nest (ide_drive_t *drive)
* 1 device was found
* (note: IDE_DFLAG_PRESENT might still be not set)
*/
-
-static inline u8 probe_for_drive (ide_drive_t *drive)
+
+static u8 probe_for_drive(ide_drive_t *drive)
{
char *m;
@@ -642,7 +639,7 @@ static int ide_register_port(ide_hwif_t *hwif)
int ret;
/* register with global device tree */
- strlcpy(hwif->gendev.bus_id,hwif->name,BUS_ID_SIZE);
+ dev_set_name(&hwif->gendev, hwif->name);
hwif->gendev.driver_data = hwif;
if (hwif->gendev.parent == NULL) {
if (hwif->dev)
@@ -864,31 +861,6 @@ static void ide_port_tune_devices(ide_hwif_t *hwif)
}
/*
- * save_match() is used to simplify logic in init_irq() below.
- *
- * A loophole here is that we may not know about a particular
- * hwif's irq until after that hwif is actually probed/initialized..
- * This could be a problem for the case where an hwif is on a
- * dual interface that requires serialization (eg. cmd640) and another
- * hwif using one of the same irqs is initialized beforehand.
- *
- * This routine detects and reports such situations, but does not fix them.
- */
-static void save_match(ide_hwif_t *hwif, ide_hwif_t *new, ide_hwif_t **match)
-{
- ide_hwif_t *m = *match;
-
- if (m && m->hwgroup && m->hwgroup != new->hwgroup) {
- if (!new->hwgroup)
- return;
- printk(KERN_WARNING "%s: potential IRQ problem with %s and %s\n",
- hwif->name, new->name, m->name);
- }
- if (!m || m->irq != hwif->irq) /* don't undo a prior perfect match */
- *match = new;
-}
-
-/*
* init request queue
*/
static int ide_init_queue(ide_drive_t *drive)
@@ -906,7 +878,8 @@ static int ide_init_queue(ide_drive_t *drive)
* do not.
*/
- q = blk_init_queue_node(do_ide_request, &ide_lock, hwif_to_node(hwif));
+ q = blk_init_queue_node(do_ide_request, &hwif->hwgroup->lock,
+ hwif_to_node(hwif));
if (!q)
return 1;
@@ -947,7 +920,7 @@ static void ide_add_drive_to_hwgroup(ide_drive_t *drive)
{
ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;
- spin_lock_irq(&ide_lock);
+ spin_lock_irq(&hwgroup->lock);
if (!hwgroup->drive) {
/* first drive for hwgroup. */
drive->next = drive;
@@ -957,7 +930,7 @@ static void ide_add_drive_to_hwgroup(ide_drive_t *drive)
drive->next = hwgroup->drive->next;
hwgroup->drive->next = drive;
}
- spin_unlock_irq(&ide_lock);
+ spin_unlock_irq(&hwgroup->lock);
}
/*
@@ -1002,7 +975,7 @@ void ide_remove_port_from_hwgroup(ide_hwif_t *hwif)
ide_ports[hwif->index] = NULL;
- spin_lock_irq(&ide_lock);
+ spin_lock_irq(&hwgroup->lock);
/*
* Remove us from the hwgroup, and free
* the hwgroup if we were the only member
@@ -1030,7 +1003,7 @@ void ide_remove_port_from_hwgroup(ide_hwif_t *hwif)
}
BUG_ON(hwgroup->hwif == hwif);
}
- spin_unlock_irq(&ide_lock);
+ spin_unlock_irq(&hwgroup->lock);
}
/*
@@ -1051,27 +1024,13 @@ static int init_irq (ide_hwif_t *hwif)
mutex_lock(&ide_cfg_mtx);
hwif->hwgroup = NULL;
- /*
- * Group up with any other hwifs that share our irq(s).
- */
for (index = 0; index < MAX_HWIFS; index++) {
ide_hwif_t *h = ide_ports[index];
if (h && h->hwgroup) { /* scan only initialized ports */
- if (hwif->irq == h->irq) {
- hwif->sharing_irq = h->sharing_irq = 1;
- if (hwif->chipset != ide_pci ||
- h->chipset != ide_pci) {
- save_match(hwif, h, &match);
- }
- }
- if (hwif->serialized) {
- if (hwif->mate && hwif->mate->irq == h->irq)
- save_match(hwif, h, &match);
- }
- if (h->serialized) {
- if (h->mate && hwif->irq == h->mate->irq)
- save_match(hwif, h, &match);
+ if (hwif->host->host_flags & IDE_HFLAG_SERIALIZE) {
+ if (hwif->host == h->host)
+ match = h;
}
}
}
@@ -1092,17 +1051,19 @@ static int init_irq (ide_hwif_t *hwif)
* linked list, the first entry is the hwif that owns
* hwgroup->handler - do not change that.
*/
- spin_lock_irq(&ide_lock);
+ spin_lock_irq(&hwgroup->lock);
hwif->next = hwgroup->hwif->next;
hwgroup->hwif->next = hwif;
BUG_ON(hwif->next == hwif);
- spin_unlock_irq(&ide_lock);
+ spin_unlock_irq(&hwgroup->lock);
} else {
hwgroup = kmalloc_node(sizeof(*hwgroup), GFP_KERNEL|__GFP_ZERO,
hwif_to_node(hwif));
if (hwgroup == NULL)
goto out_up;
+ spin_lock_init(&hwgroup->lock);
+
hwif->hwgroup = hwgroup;
hwgroup->hwif = hwif->next = hwif;
@@ -1122,8 +1083,7 @@ static int init_irq (ide_hwif_t *hwif)
sa = IRQF_SHARED;
#endif /* __mc68000__ */
- if (hwif->chipset == ide_pci || hwif->chipset == ide_cmd646 ||
- hwif->chipset == ide_ali14xx)
+ if (hwif->chipset == ide_pci)
sa = IRQF_SHARED;
if (io_ports->ctl_addr)
@@ -1150,8 +1110,7 @@ static int init_irq (ide_hwif_t *hwif)
io_ports->data_addr, hwif->irq);
#endif /* __mc68000__ */
if (match)
- printk(KERN_CONT " (%sed with %s)",
- hwif->sharing_irq ? "shar" : "serializ", match->name);
+ printk(KERN_CONT " (serialized with %s)", match->name);
printk(KERN_CONT "\n");
mutex_unlock(&ide_cfg_mtx);
@@ -1263,20 +1222,21 @@ static void ide_remove_drive_from_hwgroup(ide_drive_t *drive)
static void drive_release_dev (struct device *dev)
{
ide_drive_t *drive = container_of(dev, ide_drive_t, gendev);
+ ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;
ide_proc_unregister_device(drive);
- spin_lock_irq(&ide_lock);
+ spin_lock_irq(&hwgroup->lock);
ide_remove_drive_from_hwgroup(drive);
kfree(drive->id);
drive->id = NULL;
drive->dev_flags &= ~IDE_DFLAG_PRESENT;
/* Messed up locking ... */
- spin_unlock_irq(&ide_lock);
+ spin_unlock_irq(&hwgroup->lock);
blk_cleanup_queue(drive->queue);
- spin_lock_irq(&ide_lock);
+ spin_lock_irq(&hwgroup->lock);
drive->queue = NULL;
- spin_unlock_irq(&ide_lock);
+ spin_unlock_irq(&hwgroup->lock);
complete(&drive->gendev_rel_comp);
}
@@ -1352,7 +1312,7 @@ static void hwif_register_devices(ide_hwif_t *hwif)
if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
continue;
- snprintf(dev->bus_id, BUS_ID_SIZE, "%u.%u", hwif->index, i);
+ dev_set_name(dev, "%u.%u", hwif->index, i);
dev->parent = &hwif->gendev;
dev->bus = &ide_bus_type;
dev->driver_data = drive;
@@ -1436,13 +1396,11 @@ static void ide_init_port(ide_hwif_t *hwif, unsigned int port,
}
if ((d->host_flags & IDE_HFLAG_SERIALIZE) ||
- ((d->host_flags & IDE_HFLAG_SERIALIZE_DMA) && hwif->dma_base)) {
- if (hwif->mate)
- hwif->mate->serialized = hwif->serialized = 1;
- }
+ ((d->host_flags & IDE_HFLAG_SERIALIZE_DMA) && hwif->dma_base))
+ hwif->host->host_flags |= IDE_HFLAG_SERIALIZE;
- if (d->host_flags & IDE_HFLAG_RQSIZE_256)
- hwif->rqsize = 256;
+ if (d->max_sectors)
+ hwif->rqsize = d->max_sectors;
/* call chipset specific routine for each enabled port */
if (d->init_hwif)
@@ -1794,59 +1752,3 @@ void ide_port_scan(ide_hwif_t *hwif)
ide_proc_port_register_devices(hwif);
}
EXPORT_SYMBOL_GPL(ide_port_scan);
-
-static void ide_legacy_init_one(hw_regs_t **hws, hw_regs_t *hw,
- u8 port_no, const struct ide_port_info *d,
- unsigned long config)
-{
- unsigned long base, ctl;
- int irq;
-
- if (port_no == 0) {
- base = 0x1f0;
- ctl = 0x3f6;
- irq = 14;
- } else {
- base = 0x170;
- ctl = 0x376;
- irq = 15;
- }
-
- if (!request_region(base, 8, d->name)) {
- printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n",
- d->name, base, base + 7);
- return;
- }
-
- if (!request_region(ctl, 1, d->name)) {
- printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n",
- d->name, ctl);
- release_region(base, 8);
- return;
- }
-
- ide_std_init_ports(hw, base, ctl);
- hw->irq = irq;
- hw->chipset = d->chipset;
- hw->config = config;
-
- hws[port_no] = hw;
-}
-
-int ide_legacy_device_add(const struct ide_port_info *d, unsigned long config)
-{
- hw_regs_t hw[2], *hws[] = { NULL, NULL, NULL, NULL };
-
- memset(&hw, 0, sizeof(hw));
-
- if ((d->host_flags & IDE_HFLAG_QD_2ND_PORT) == 0)
- ide_legacy_init_one(hws, &hw[0], 0, d, config);
- ide_legacy_init_one(hws, &hw[1], 1, d, config);
-
- if (hws[0] == NULL && hws[1] == NULL &&
- (d->host_flags & IDE_HFLAG_SINGLE))
- return -ENOENT;
-
- return ide_host_add(d, hws, NULL);
-}
-EXPORT_SYMBOL_GPL(ide_legacy_device_add);
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index f3cddd1..a14e293 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -46,10 +46,6 @@ static int proc_ide_read_imodel
case ide_qd65xx: name = "qd65xx"; break;
case ide_umc8672: name = "umc8672"; break;
case ide_ht6560b: name = "ht6560b"; break;
- case ide_rz1000: name = "rz1000"; break;
- case ide_trm290: name = "trm290"; break;
- case ide_cmd646: name = "cmd646"; break;
- case ide_cy82c693: name = "cy82c693"; break;
case ide_4drives: name = "4drives"; break;
case ide_pmac: name = "mac-io"; break;
case ide_au1xxx: name = "au1xxx"; break;
@@ -155,13 +151,8 @@ static int ide_read_setting(ide_drive_t *drive,
const struct ide_devset *ds = setting->setting;
int val = -EINVAL;
- if (ds->get) {
- unsigned long flags;
-
- spin_lock_irqsave(&ide_lock, flags);
+ if (ds->get)
val = ds->get(drive);
- spin_unlock_irqrestore(&ide_lock, flags);
- }
return val;
}
@@ -583,31 +574,19 @@ EXPORT_SYMBOL(ide_proc_register_driver);
* Clean up the driver specific /proc files and IDE settings
* for a given drive.
*
- * Takes ide_setting_mtx and ide_lock.
- * Caller must hold none of the locks.
+ * Takes ide_setting_mtx.
*/
void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver)
{
- unsigned long flags;
-
ide_remove_proc_entries(drive->proc, driver->proc_entries(drive));
mutex_lock(&ide_setting_mtx);
- spin_lock_irqsave(&ide_lock, flags);
/*
- * ide_setting_mtx protects the settings list
- * ide_lock protects the use of settings
- *
- * so we need to hold both, ide_settings_sem because we want to
- * modify the settings list, and ide_lock because we cannot take
- * a setting out that is being used.
- *
- * OTOH both ide_{read,write}_setting are only ever used under
- * ide_setting_mtx.
+ * ide_setting_mtx protects both the settings list and the use
+ * of settings (we cannot take a setting out that is being used).
*/
drive->settings = NULL;
- spin_unlock_irqrestore(&ide_lock, flags);
mutex_unlock(&ide_setting_mtx);
}
EXPORT_SYMBOL(ide_proc_unregister_driver);
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 04f8f13..f0f09f7 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -74,9 +74,6 @@ static const u8 ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR,
DEFINE_MUTEX(ide_cfg_mtx);
-__cacheline_aligned_in_smp DEFINE_SPINLOCK(ide_lock);
-EXPORT_SYMBOL(ide_lock);
-
static void ide_port_init_devices_data(ide_hwif_t *);
/*
@@ -130,7 +127,6 @@ static void ide_port_init_devices_data(ide_hwif_t *hwif)
}
}
-/* Called with ide_lock held. */
static void __ide_port_unregister_devices(ide_hwif_t *hwif)
{
int i;
@@ -139,10 +135,8 @@ static void __ide_port_unregister_devices(ide_hwif_t *hwif)
ide_drive_t *drive = &hwif->drives[i];
if (drive->dev_flags & IDE_DFLAG_PRESENT) {
- spin_unlock_irq(&ide_lock);
device_unregister(&drive->gendev);
wait_for_completion(&drive->gendev_rel_comp);
- spin_lock_irq(&ide_lock);
}
}
}
@@ -150,11 +144,9 @@ static void __ide_port_unregister_devices(ide_hwif_t *hwif)
void ide_port_unregister_devices(ide_hwif_t *hwif)
{
mutex_lock(&ide_cfg_mtx);
- spin_lock_irq(&ide_lock);
__ide_port_unregister_devices(hwif);
hwif->present = 0;
ide_port_init_devices_data(hwif);
- spin_unlock_irq(&ide_lock);
mutex_unlock(&ide_cfg_mtx);
}
EXPORT_SYMBOL_GPL(ide_port_unregister_devices);
@@ -192,12 +184,10 @@ void ide_unregister(ide_hwif_t *hwif)
mutex_lock(&ide_cfg_mtx);
- spin_lock_irq(&ide_lock);
if (hwif->present) {
__ide_port_unregister_devices(hwif);
hwif->present = 0;
}
- spin_unlock_irq(&ide_lock);
ide_proc_unregister_port(hwif);
@@ -340,6 +330,7 @@ static int set_pio_mode_abuse(ide_hwif_t *hwif, u8 req_pio)
static int set_pio_mode(ide_drive_t *drive, int arg)
{
ide_hwif_t *hwif = drive->hwif;
+ ide_hwgroup_t *hwgroup = hwif->hwgroup;
const struct ide_port_ops *port_ops = hwif->port_ops;
if (arg < 0 || arg > 255)
@@ -354,9 +345,9 @@ static int set_pio_mode(ide_drive_t *drive, int arg)
unsigned long flags;
/* take lock for IDE_DFLAG_[NO_]UNMASK/[NO_]IO_32BIT */
- spin_lock_irqsave(&ide_lock, flags);
+ spin_lock_irqsave(&hwgroup->lock, flags);
port_ops->set_pio_mode(drive, arg);
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&hwgroup->lock, flags);
} else
port_ops->set_pio_mode(drive, arg);
} else {
@@ -397,80 +388,6 @@ ide_ext_devset_rw_sync(unmaskirq, unmaskirq);
ide_ext_devset_rw_sync(using_dma, using_dma);
__IDE_DEVSET(pio_mode, DS_SYNC, NULL, set_pio_mode);
-static int generic_ide_suspend(struct device *dev, pm_message_t mesg)
-{
- ide_drive_t *drive = dev->driver_data, *pair = ide_get_pair_dev(drive);
- ide_hwif_t *hwif = HWIF(drive);
- struct request *rq;
- struct request_pm_state rqpm;
- ide_task_t args;
- int ret;
-
- /* call ACPI _GTM only once */
- if ((drive->dn & 1) == 0 || pair == NULL)
- ide_acpi_get_timing(hwif);
-
- memset(&rqpm, 0, sizeof(rqpm));
- memset(&args, 0, sizeof(args));
- rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
- rq->cmd_type = REQ_TYPE_PM_SUSPEND;
- rq->special = &args;
- rq->data = &rqpm;
- rqpm.pm_step = IDE_PM_START_SUSPEND;
- if (mesg.event == PM_EVENT_PRETHAW)
- mesg.event = PM_EVENT_FREEZE;
- rqpm.pm_state = mesg.event;
-
- ret = blk_execute_rq(drive->queue, NULL, rq, 0);
- blk_put_request(rq);
-
- /* call ACPI _PS3 only after both devices are suspended */
- if (ret == 0 && ((drive->dn & 1) || pair == NULL))
- ide_acpi_set_state(hwif, 0);
-
- return ret;
-}
-
-static int generic_ide_resume(struct device *dev)
-{
- ide_drive_t *drive = dev->driver_data, *pair = ide_get_pair_dev(drive);
- ide_hwif_t *hwif = HWIF(drive);
- struct request *rq;
- struct request_pm_state rqpm;
- ide_task_t args;
- int err;
-
- /* call ACPI _PS0 / _STM only once */
- if ((drive->dn & 1) == 0 || pair == NULL) {
- ide_acpi_set_state(hwif, 1);
- ide_acpi_push_timing(hwif);
- }
-
- ide_acpi_exec_tfs(drive);
-
- memset(&rqpm, 0, sizeof(rqpm));
- memset(&args, 0, sizeof(args));
- rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
- rq->cmd_type = REQ_TYPE_PM_RESUME;
- rq->cmd_flags |= REQ_PREEMPT;
- rq->special = &args;
- rq->data = &rqpm;
- rqpm.pm_step = IDE_PM_START_RESUME;
- rqpm.pm_state = PM_EVENT_ON;
-
- err = blk_execute_rq(drive->queue, NULL, rq, 1);
- blk_put_request(rq);
-
- if (err == 0 && dev->driver) {
- ide_driver_t *drv = to_ide_driver(dev->driver);
-
- if (drv->resume)
- drv->resume(drive);
- }
-
- return err;
-}
-
/**
* ide_device_get - get an additional reference to a ide_drive_t
* @drive: device to get a reference to
diff --git a/drivers/ide/pdc202xx_old.c b/drivers/ide/pdc202xx_old.c
index 799557c..624e62e 100644
--- a/drivers/ide/pdc202xx_old.c
+++ b/drivers/ide/pdc202xx_old.c
@@ -350,16 +350,17 @@ static const struct ide_dma_ops pdc2026x_dma_ops = {
.dma_timeout = pdc202xx_dma_timeout,
};
-#define DECLARE_PDC2026X_DEV(udma, extra_flags) \
+#define DECLARE_PDC2026X_DEV(udma, sectors) \
{ \
.name = DRV_NAME, \
.init_chipset = init_chipset_pdc202xx, \
.port_ops = &pdc2026x_port_ops, \
.dma_ops = &pdc2026x_dma_ops, \
- .host_flags = IDE_HFLAGS_PDC202XX | extra_flags, \
+ .host_flags = IDE_HFLAGS_PDC202XX, \
.pio_mask = ATA_PIO4, \
.mwdma_mask = ATA_MWDMA2, \
.udma_mask = udma, \
+ .max_sectors = sectors, \
}
static const struct ide_port_info pdc202xx_chipsets[] __devinitdata = {
@@ -376,8 +377,8 @@ static const struct ide_port_info pdc202xx_chipsets[] __devinitdata = {
/* 1: PDC2026{2,3} */
DECLARE_PDC2026X_DEV(ATA_UDMA4, 0),
- /* 2: PDC2026{5,7} */
- DECLARE_PDC2026X_DEV(ATA_UDMA5, IDE_HFLAG_RQSIZE_256),
+ /* 2: PDC2026{5,7}: UDMA5, limit LBA48 requests to 256 sectors */
+ DECLARE_PDC2026X_DEV(ATA_UDMA5, 256),
};
/**
diff --git a/drivers/ide/rz1000.c b/drivers/ide/rz1000.c
index 7daf013..a6414a8 100644
--- a/drivers/ide/rz1000.c
+++ b/drivers/ide/rz1000.c
@@ -22,34 +22,48 @@
#define DRV_NAME "rz1000"
-static void __devinit init_hwif_rz1000 (ide_hwif_t *hwif)
+static int __devinit rz1000_disable_readahead(struct pci_dev *dev)
{
- struct pci_dev *dev = to_pci_dev(hwif->dev);
u16 reg;
if (!pci_read_config_word (dev, 0x40, ®) &&
!pci_write_config_word(dev, 0x40, reg & 0xdfff)) {
printk(KERN_INFO "%s: disabled chipset read-ahead "
- "(buggy RZ1000/RZ1001)\n", hwif->name);
+ "(buggy RZ1000/RZ1001)\n", pci_name(dev));
+ return 0;
} else {
- if (hwif->mate)
- hwif->mate->serialized = hwif->serialized = 1;
- hwif->host_flags |= IDE_HFLAG_NO_UNMASK_IRQS;
printk(KERN_INFO "%s: serialized, disabled unmasking "
- "(buggy RZ1000/RZ1001)\n", hwif->name);
+ "(buggy RZ1000/RZ1001)\n", pci_name(dev));
+ return 1;
}
}
static const struct ide_port_info rz1000_chipset __devinitdata = {
.name = DRV_NAME,
- .init_hwif = init_hwif_rz1000,
- .chipset = ide_rz1000,
.host_flags = IDE_HFLAG_NO_DMA,
};
static int __devinit rz1000_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- return ide_pci_init_one(dev, &rz1000_chipset, NULL);
+ struct ide_port_info d = rz1000_chipset;
+ int rc;
+
+ rc = pci_enable_device(dev);
+ if (rc)
+ return rc;
+
+ if (rz1000_disable_readahead(dev)) {
+ d.host_flags |= IDE_HFLAG_SERIALIZE;
+ d.host_flags |= IDE_HFLAG_NO_UNMASK_IRQS;
+ }
+
+ return ide_pci_init_one(dev, &d, NULL);
+}
+
+static void rz1000_remove(struct pci_dev *dev)
+{
+ ide_pci_remove(dev);
+ pci_disable_device(dev);
}
static const struct pci_device_id rz1000_pci_tbl[] = {
@@ -63,7 +77,7 @@ static struct pci_driver rz1000_pci_driver = {
.name = "RZ1000_IDE",
.id_table = rz1000_pci_tbl,
.probe = rz1000_init_one,
- .remove = ide_pci_remove,
+ .remove = rz1000_remove,
};
static int __init rz1000_ide_init(void)
diff --git a/drivers/ide/trm290.c b/drivers/ide/trm290.c
index 75ea615..2a5ea90 100644
--- a/drivers/ide/trm290.c
+++ b/drivers/ide/trm290.c
@@ -328,10 +328,10 @@ static struct ide_dma_ops trm290_dma_ops = {
static const struct ide_port_info trm290_chipset __devinitdata = {
.name = DRV_NAME,
.init_hwif = init_hwif_trm290,
- .chipset = ide_trm290,
.port_ops = &trm290_port_ops,
.dma_ops = &trm290_dma_ops,
- .host_flags = IDE_HFLAG_NO_ATAPI_DMA |
+ .host_flags = IDE_HFLAG_TRM290 |
+ IDE_HFLAG_NO_ATAPI_DMA |
#if 0 /* play it safe for now */
IDE_HFLAG_TRUST_BIOS_FOR_DMA |
#endif
diff --git a/drivers/ide/tx4938ide.c b/drivers/ide/tx4938ide.c
index 9120063..13b63e7 100644
--- a/drivers/ide/tx4938ide.c
+++ b/drivers/ide/tx4938ide.c
@@ -181,7 +181,7 @@ static void tx4938ide_input_data_swap(ide_drive_t *drive, struct request *rq,
while (count--)
*ptr++ = cpu_to_le16(__raw_readw((void __iomem *)port));
- __ide_flush_dcache_range((unsigned long)buf, count * 2);
+ __ide_flush_dcache_range((unsigned long)buf, roundup(len, 2));
}
static void tx4938ide_output_data_swap(ide_drive_t *drive, struct request *rq,
@@ -195,7 +195,7 @@ static void tx4938ide_output_data_swap(ide_drive_t *drive, struct request *rq,
__raw_writew(le16_to_cpu(*ptr), (void __iomem *)port);
ptr++;
}
- __ide_flush_dcache_range((unsigned long)buf, count * 2);
+ __ide_flush_dcache_range((unsigned long)buf, roundup(len, 2));
}
static const struct ide_tp_ops tx4938ide_tp_ops = {
diff --git a/drivers/ide/tx4939ide.c b/drivers/ide/tx4939ide.c
index bafb7d1..97cd9e0 100644
--- a/drivers/ide/tx4939ide.c
+++ b/drivers/ide/tx4939ide.c
@@ -259,6 +259,12 @@ static int tx4939ide_build_dmatable(ide_drive_t *drive, struct request *rq)
bcount = 0x10000 - (cur_addr & 0xffff);
if (bcount > cur_len)
bcount = cur_len;
+ /*
+ * This workaround for zero count seems required.
+ * (standard ide_build_dmatable do it too)
+ */
+ if ((bcount & 0xffff) == 0x0000)
+ bcount = 0x8000;
*table++ = bcount & 0xffff;
*table++ = cur_addr;
cur_addr += bcount;
@@ -558,7 +564,7 @@ static void tx4939ide_input_data_swap(ide_drive_t *drive, struct request *rq,
while (count--)
*ptr++ = cpu_to_le16(__raw_readw((void __iomem *)port));
- __ide_flush_dcache_range((unsigned long)buf, count * 2);
+ __ide_flush_dcache_range((unsigned long)buf, roundup(len, 2));
}
static void tx4939ide_output_data_swap(ide_drive_t *drive, struct request *rq,
@@ -572,7 +578,7 @@ static void tx4939ide_output_data_swap(ide_drive_t *drive, struct request *rq,
__raw_writew(le16_to_cpu(*ptr), (void __iomem *)port);
ptr++;
}
- __ide_flush_dcache_range((unsigned long)buf, count * 2);
+ __ide_flush_dcache_range((unsigned long)buf, roundup(len, 2));
}
static const struct ide_tp_ops tx4939ide_tp_ops = {
diff --git a/drivers/ide/umc8672.c b/drivers/ide/umc8672.c
index 1da076e..e29978c 100644
--- a/drivers/ide/umc8672.c
+++ b/drivers/ide/umc8672.c
@@ -107,18 +107,21 @@ static void umc_set_speeds(u8 speeds[])
static void umc_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
ide_hwif_t *hwif = drive->hwif;
- unsigned long flags;
+ ide_hwgroup_t *mate_hwgroup = hwif->mate ? hwif->mate->hwgroup : NULL;
+ unsigned long uninitialized_var(flags);
printk("%s: setting umc8672 to PIO mode%d (speed %d)\n",
drive->name, pio, pio_to_umc[pio]);
- spin_lock_irqsave(&ide_lock, flags);
- if (hwif->mate && hwif->mate->hwgroup->handler) {
+ if (mate_hwgroup)
+ spin_lock_irqsave(&mate_hwgroup->lock, flags);
+ if (mate_hwgroup && mate_hwgroup->handler) {
printk(KERN_ERR "umc8672: other interface is busy: exiting tune_umc()\n");
} else {
current_speeds[drive->name[2] - 'a'] = pio_to_umc[pio];
umc_set_speeds(current_speeds);
}
- spin_unlock_irqrestore(&ide_lock, flags);
+ if (mate_hwgroup)
+ spin_unlock_irqrestore(&mate_hwgroup->lock, flags);
}
static const struct ide_port_ops umc8672_port_ops = {
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index 2370fd8..c24140a 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -578,6 +578,8 @@ 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;
@@ -594,13 +596,16 @@ static int idescsi_eh_abort (struct scsi_cmnd *cmd)
goto no_drive;
}
- /* First give it some more time, how much is "right" is hard to say :-( */
+ hwif = drive->hwif;
+ hwgroup = hwif->hwgroup;
- busy = ide_wait_not_busy(HWIF(drive), 100); /* FIXME - uses mdelay which causes latency? */
+ /* 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(&ide_lock);
+ spin_lock_irq(&hwgroup->lock);
/* If there is no pc running we're done (our interrupt took care of it) */
pc = drive->pc;
@@ -629,7 +634,7 @@ static int idescsi_eh_abort (struct scsi_cmnd *cmd)
}
ide_unlock:
- spin_unlock_irq(&ide_lock);
+ 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");
@@ -642,6 +647,7 @@ 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;
@@ -658,14 +664,18 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd)
return FAILED;
}
+ hwgroup = drive->hwif->hwgroup;
+
spin_lock_irq(cmd->device->host->host_lock);
- spin_lock(&ide_lock);
+ spin_lock(&hwgroup->lock);
pc = drive->pc;
+ if (pc)
+ req = pc->rq;
- if (pc == NULL || (req = pc->rq) != HWGROUP(drive)->rq || !HWGROUP(drive)->handler) {
+ if (pc == NULL || req != hwgroup->rq || hwgroup->handler == NULL) {
printk (KERN_WARNING "ide-scsi: No active request in idescsi_eh_reset\n");
- spin_unlock(&ide_lock);
+ spin_unlock(&hwgroup->lock);
spin_unlock_irq(cmd->device->host->host_lock);
return FAILED;
}
@@ -685,10 +695,10 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd)
BUG();
}
- HWGROUP(drive)->rq = NULL;
- HWGROUP(drive)->handler = NULL;
- HWGROUP(drive)->busy = 1; /* will set this to zero when ide reset finished */
- spin_unlock(&ide_lock);
+ 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);
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 010fb26..e99c56d 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -122,8 +122,6 @@ struct ide_io_ports {
#define MAX_DRIVES 2 /* per interface; 2 assumed by lots of code */
#define SECTOR_SIZE 512
-#define IDE_LARGE_SEEK(b1,b2,t) (((b1) > (b2) + (t)) || ((b2) > (b1) + (t)))
-
/*
* Timeouts for various operations:
*/
@@ -172,9 +170,7 @@ typedef int (ide_ack_intr_t)(struct hwif_s *);
enum { ide_unknown, ide_generic, ide_pci,
ide_cmd640, ide_dtc2278, ide_ali14xx,
ide_qd65xx, ide_umc8672, ide_ht6560b,
- ide_rz1000, ide_trm290,
- ide_cmd646, ide_cy82c693, ide_4drives,
- ide_pmac, ide_acorn,
+ ide_4drives, ide_pmac, ide_acorn,
ide_au1xxx, ide_palm3710
};
@@ -496,8 +492,6 @@ enum {
* when more than one interrupt is needed.
*/
IDE_AFLAG_LIMIT_NFRAMES = (1 << 7),
- /* Seeking in progress. */
- IDE_AFLAG_SEEKING = (1 << 8),
/* Saved TOC information is current. */
IDE_AFLAG_TOC_VALID = (1 << 9),
/* We think that the drive door is locked. */
@@ -845,8 +839,6 @@ typedef struct hwif_s {
unsigned extra_ports; /* number of extra dma ports */
unsigned present : 1; /* this interface exists */
- unsigned serialized : 1; /* serialized all channel operation */
- unsigned sharing_irq: 1; /* 1 = sharing irq with another hwif */
unsigned sg_mapped : 1; /* sg_table and sg_nents are ready */
struct device gendev;
@@ -909,6 +901,8 @@ typedef struct hwgroup_s {
int req_gen;
int req_gen_timer;
+
+ spinlock_t lock;
} ide_hwgroup_t;
typedef struct ide_driver_s ide_driver_t;
@@ -1122,6 +1116,14 @@ enum {
IDE_PM_COMPLETED,
};
+int generic_ide_suspend(struct device *, pm_message_t);
+int generic_ide_resume(struct device *);
+
+void ide_complete_power_step(ide_drive_t *, struct request *);
+ide_startstop_t ide_start_power_step(ide_drive_t *, struct request *);
+void ide_complete_pm_request(ide_drive_t *, struct request *);
+void ide_check_pm_state(ide_drive_t *, struct request *);
+
/*
* Subdrivers support.
*
@@ -1376,8 +1378,8 @@ enum {
IDE_HFLAG_LEGACY_IRQS = (1 << 21),
/* force use of legacy IRQs */
IDE_HFLAG_FORCE_LEGACY_IRQS = (1 << 22),
- /* limit LBA48 requests to 256 sectors */
- IDE_HFLAG_RQSIZE_256 = (1 << 23),
+ /* host is TRM290 */
+ IDE_HFLAG_TRM290 = (1 << 23),
/* use 32-bit I/O ops */
IDE_HFLAG_IO_32BIT = (1 << 24),
/* unmask IRQs */
@@ -1415,6 +1417,9 @@ struct ide_port_info {
ide_pci_enablebit_t enablebits[2];
hwif_chipset_t chipset;
+
+ u16 max_sectors; /* if < than the default one */
+
u32 host_flags;
u8 pio_mask;
u8 swdma_mask;
@@ -1610,13 +1615,13 @@ extern struct mutex ide_cfg_mtx;
/*
* Structure locking:
*
- * ide_cfg_mtx and ide_lock together protect changes to
- * ide_hwif_t->{next,hwgroup}
+ * ide_cfg_mtx and hwgroup->lock together protect changes to
+ * ide_hwif_t->next
* ide_drive_t->next
*
- * ide_hwgroup_t->busy: ide_lock
- * ide_hwgroup_t->hwif: ide_lock
- * ide_hwif_t->mate: constant, no locking
+ * ide_hwgroup_t->busy: hwgroup->lock
+ * ide_hwgroup_t->hwif: hwgroup->lock
+ * ide_hwif_t->{hwgroup,mate}: constant, no locking
* ide_drive_t->hwif: constant, no locking
*/
\0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [git pull] IDE updates part 1
@ 2009-03-24 23:07 Bartlomiej Zolnierkiewicz
0 siblings, 0 replies; 3+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2009-03-24 23:07 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Andrew Morton, Stephen Rothwell, linux-ide, linux-kernel
Hi,
Nothing really earthshaking here:
- IDE ACPI cleanup
- IRQ setup sanitization
- saner code layout
- unified IDENTIFY handling
- by-the-way fixes/cleanups
Linus, please pull from:
master.kernel.org:/pub/scm/linux/kernel/git/bart/ide-2.6.git/
to receive the following updates:
drivers/ide/Kconfig | 8 +
drivers/ide/Makefile | 4 +-
drivers/ide/aec62xx.c | 4 +-
drivers/ide/alim15x3.c | 2 +-
drivers/ide/amd74xx.c | 14 +-
drivers/ide/atiixp.c | 3 +-
drivers/ide/cmd64x.c | 2 +-
drivers/ide/cs5520.c | 3 +-
drivers/ide/cs5530.c | 2 +-
drivers/ide/delkin_cb.c | 2 +-
drivers/ide/hpt366.c | 4 +-
drivers/ide/ide-acpi.c | 214 +++---------
drivers/ide/ide-atapi.c | 41 +++-
drivers/ide/ide-cd.c | 4 +-
drivers/ide/ide-devsets.c | 190 +++++++++++
drivers/ide/ide-dma.c | 57 ++++
drivers/ide/ide-eh.c | 428 ++++++++++++++++++++++++
drivers/ide/ide-io-std.c | 316 ++++++++++++++++++
drivers/ide/ide-io.c | 320 ++----------------
drivers/ide/ide-iops.c | 742 ++---------------------------------------
drivers/ide/ide-lib.c | 240 -------------
drivers/ide/ide-park.c | 25 ++
drivers/ide/ide-pci-generic.c | 4 +-
drivers/ide/ide-probe.c | 248 +++-----------
drivers/ide/ide-proc.c | 2 +-
drivers/ide/ide-xfer-mode.c | 246 ++++++++++++++
drivers/ide/ide.c | 156 +---------
drivers/ide/it821x.c | 2 +-
drivers/ide/ns87415.c | 4 +-
drivers/ide/pdc202xx_new.c | 4 +-
drivers/ide/pdc202xx_old.c | 4 +-
drivers/ide/piix.c | 13 +-
drivers/ide/serverworks.c | 13 +-
drivers/ide/setup-pci.c | 27 +-
drivers/ide/siimage.c | 2 +-
drivers/ide/sis5513.c | 4 +-
drivers/ide/sl82c105.c | 4 +-
drivers/ide/slc90e66.c | 1 -
drivers/ide/trm290.c | 3 -
drivers/ide/via82cxxx.c | 12 +-
include/asm-frv/ide.h | 24 --
include/asm-mn10300/ide.h | 39 ---
include/asm-mn10300/pci.h | 5 +
include/linux/ata.h | 2 -
include/linux/ide.h | 78 ++---
45 files changed, 1571 insertions(+), 1951 deletions(-)
create mode 100644 drivers/ide/ide-devsets.c
create mode 100644 drivers/ide/ide-eh.c
create mode 100644 drivers/ide/ide-io-std.c
create mode 100644 drivers/ide/ide-xfer-mode.c
delete mode 100644 include/asm-frv/ide.h
delete mode 100644 include/asm-mn10300/ide.h
Bartlomiej Zolnierkiewicz (52):
ide: move ide_pktcmd_tf_load() to ide-atapi.c
ide: no need to touch local IRQs in ide_probe_port()
ide: move ->lock and ->timer init from init_irq() to ide_init_port_data()
ide: init_irq() doesn't need to hold ide_cfg_mtx
ide: remove superfluous check from ide_proc_port_register_devices()
ide-acpi: no need to zero ->acpidata for devices
ide-acpi: init ACPI handles early for devices
ide: add ide_for_each_present_dev() iterator
ide: sanitize ACPI initialization
ide-acpi: cleanup do_drive_get_GTF()
ide-acpi: cleanup do_drive_set_taskfiles()
ide-acpi: remove taskfile_load_raw()
ide: remove stale comments from drive_is_ready()
ide: unexport ide_devset_execute()
ide: move drive_is_ready() to ide-io.c
ide: move ide_dma_timeout_retry() to ide-dma.c
ide: remove ide_do_drive_cmd()
ide: factor out processing of special commands from ide_special_rq()
ide: move ide_do_park_unpark() to ide-park.c
ide: move device settings code to ide-devsets.c
ide: move xfer mode tuning code to ide-xfer-mode.c
ide: move ide_read_bcount_and_ireason() to ide-atapi.c
ide: move standard I/O code to ide-io-std.c
ide: fix printk() levels in [atapi_]reset_pollfunc()
ide: fix comments in ide_config_drive_speed()
ide: checkpatch.pl fixes for ide-iops.c
ide: move error handling code to ide-eh.c (v2)
mn10300: add pci_get_legacy_ide_irq() to <asm/pci.h>
amd74xx: use ide_pci_is_in_compatibility_mode()
ns87415: use pci_get_legacy_ide_irq()
ns87415: small ->init_hwif cleanup
trm290: small ->init_hwif cleanup
ide: handle IDE_HFLAG[_FORCE]_LEGACY_IRQS in ide_pci_init_{one,two}()
ide: use pci_get_legacy_ide_irq() in ide_pci_init_{one,two}()
ide: use ide_pci_is_in_compatibility_mode() in ide_pci_init_{one,two}()
ide: remove no longer needed IDE_HFLAG[_FORCE]_LEGACY_IRQS
amd74xx: remove no longer needed ->init_hwif method
ide: remove no longer needed IRQ fallback code from hwif_init()
ide: remove no longer needed IRQ auto-probing from try_to_identify() (v2)
ide: remove try_to_identify() wrapper
ide: fix ->init_chipset method to return 'int' value
ide: remove pciirq argument from ide_pci_setup_ports()
frv: remove <asm/ide.h>
mn10300: remove <asm/ide.h>
ide: fix kmalloc() failure handling in ide_driveid_update()
ide: propagate AltStatus workarounds to ide_driveid_update()
ide: shorten timeout value in ide_driveid_update()
ide: remove broken EXABYTENEST support
ide: classify device type in do_probe()
ide: sanitize SELECT_MASK() usage in ide_driveid_update()
ide: clear drive IRQ after re-enabling local IRQs in ide_driveid_update()
ide: use try_to_identify() in ide_driveid_update()
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index 5ea3bfa..640c992 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -56,8 +56,12 @@ if IDE
comment "Please see Documentation/ide/ide.txt for help/info on IDE drives"
+config IDE_XFER_MODE
+ bool
+
config IDE_TIMINGS
bool
+ select IDE_XFER_MODE
config IDE_ATAPI
bool
@@ -698,6 +702,7 @@ config BLK_DEV_IDE_PMAC_ATA100FIRST
config BLK_DEV_IDE_AU1XXX
bool "IDE for AMD Alchemy Au1200"
depends on SOC_AU1200
+ select IDE_XFER_MODE
choice
prompt "IDE Mode for AMD Alchemy Au1200"
default CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA
@@ -871,6 +876,7 @@ config BLK_DEV_ALI14XX
config BLK_DEV_DTC2278
tristate "DTC-2278 support"
+ select IDE_XFER_MODE
select IDE_LEGACY
help
This driver is enabled at runtime using the "dtc2278.probe" kernel
@@ -902,6 +908,7 @@ config BLK_DEV_QD65XX
config BLK_DEV_UMC8672
tristate "UMC-8672 support"
+ select IDE_XFER_MODE
select IDE_LEGACY
help
This driver is enabled at runtime using the "umc8672.probe" kernel
@@ -915,5 +922,6 @@ endif
config BLK_DEV_IDEDMA
def_bool BLK_DEV_IDEDMA_SFF || \
BLK_DEV_IDEDMA_ICS || BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+ select IDE_XFER_MODE
endif # IDE
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile
index 1c326d9..9b4bbe1 100644
--- a/drivers/ide/Makefile
+++ b/drivers/ide/Makefile
@@ -5,9 +5,11 @@
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-sysfs.o
+ ide-taskfile.o ide-pm.o ide-park.o ide-sysfs.o ide-devsets.o \
+ ide-io-std.o ide-eh.o
# core IDE code
+ide-core-$(CONFIG_IDE_XFER_MODE) += ide-pio-blacklist.o ide-xfer-mode.o
ide-core-$(CONFIG_IDE_TIMINGS) += ide-timings.o
ide-core-$(CONFIG_IDE_ATAPI) += ide-atapi.o
ide-core-$(CONFIG_BLK_DEV_IDEPCI) += setup-pci.o
diff --git a/drivers/ide/aec62xx.c b/drivers/ide/aec62xx.c
index 4485b9c..878f8ec 100644
--- a/drivers/ide/aec62xx.c
+++ b/drivers/ide/aec62xx.c
@@ -139,7 +139,7 @@ static void aec_set_pio_mode(ide_drive_t *drive, const u8 pio)
drive->hwif->port_ops->set_dma_mode(drive, pio + XFER_PIO_0);
}
-static unsigned int init_chipset_aec62xx(struct pci_dev *dev)
+static int init_chipset_aec62xx(struct pci_dev *dev)
{
/* These are necessary to get AEC6280 Macintosh cards to work */
if ((dev->device == PCI_DEVICE_ID_ARTOP_ATP865) ||
@@ -156,7 +156,7 @@ static unsigned int init_chipset_aec62xx(struct pci_dev *dev)
pci_write_config_byte(dev, 0x4a, reg4ah | 0x80);
}
- return dev->irq;
+ return 0;
}
static u8 atp86x_cable_detect(ide_hwif_t *hwif)
diff --git a/drivers/ide/alim15x3.c b/drivers/ide/alim15x3.c
index 66f4308..d3513b6 100644
--- a/drivers/ide/alim15x3.c
+++ b/drivers/ide/alim15x3.c
@@ -212,7 +212,7 @@ static int ali15x3_dma_setup(ide_drive_t *drive)
* appropriate also sets up the 1533 southbridge.
*/
-static unsigned int init_chipset_ali15x3(struct pci_dev *dev)
+static int init_chipset_ali15x3(struct pci_dev *dev)
{
unsigned long flags;
u8 tmpbyte;
diff --git a/drivers/ide/amd74xx.c b/drivers/ide/amd74xx.c
index 77267c8..628cd2e 100644
--- a/drivers/ide/amd74xx.c
+++ b/drivers/ide/amd74xx.c
@@ -140,7 +140,7 @@ static void amd7411_cable_detect(struct pci_dev *dev)
* The initialization callback. Initialize drive independent registers.
*/
-static unsigned int init_chipset_amd74xx(struct pci_dev *dev)
+static int init_chipset_amd74xx(struct pci_dev *dev)
{
u8 t = 0, offset = amd_offset(dev);
@@ -172,7 +172,7 @@ static unsigned int init_chipset_amd74xx(struct pci_dev *dev)
t |= 0xf0;
pci_write_config_byte(dev, AMD_IDE_CONFIG + offset, t);
- return dev->irq;
+ return 0;
}
static u8 amd_cable_detect(ide_hwif_t *hwif)
@@ -183,14 +183,6 @@ static u8 amd_cable_detect(ide_hwif_t *hwif)
return ATA_CBL_PATA40;
}
-static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif)
-{
- struct pci_dev *dev = to_pci_dev(hwif->dev);
-
- if (hwif->irq == 0) /* 0 is bogus but will do for now */
- hwif->irq = pci_get_legacy_ide_irq(dev, hwif->channel);
-}
-
static const struct ide_port_ops amd_port_ops = {
.set_pio_mode = amd_set_pio_mode,
.set_dma_mode = amd_set_drive,
@@ -207,7 +199,6 @@ static const struct ide_port_ops amd_port_ops = {
{ \
.name = DRV_NAME, \
.init_chipset = init_chipset_amd74xx, \
- .init_hwif = init_hwif_amd74xx, \
.enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, \
.port_ops = &amd_port_ops, \
.host_flags = IDE_HFLAGS_AMD, \
@@ -221,7 +212,6 @@ static const struct ide_port_ops amd_port_ops = {
{ \
.name = DRV_NAME, \
.init_chipset = init_chipset_amd74xx, \
- .init_hwif = init_hwif_amd74xx, \
.enablebits = {{0x50,0x02,0x02}, {0x50,0x01,0x01}}, \
.port_ops = &amd_port_ops, \
.host_flags = IDE_HFLAGS_AMD, \
diff --git a/drivers/ide/atiixp.c b/drivers/ide/atiixp.c
index ecd1e62..923cbfe 100644
--- a/drivers/ide/atiixp.c
+++ b/drivers/ide/atiixp.c
@@ -142,7 +142,6 @@ static const struct ide_port_info atiixp_pci_info[] __devinitdata = {
.name = DRV_NAME,
.enablebits = {{0x48,0x01,0x00}, {0x48,0x08,0x00}},
.port_ops = &atiixp_port_ops,
- .host_flags = IDE_HFLAG_LEGACY_IRQS,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
@@ -151,7 +150,7 @@ static const struct ide_port_info atiixp_pci_info[] __devinitdata = {
.name = DRV_NAME,
.enablebits = {{0x48,0x01,0x00}, {0x00,0x00,0x00}},
.port_ops = &atiixp_port_ops,
- .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_LEGACY_IRQS,
+ .host_flags = IDE_HFLAG_SINGLE,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
diff --git a/drivers/ide/cmd64x.c b/drivers/ide/cmd64x.c
index 2f9688d..aeee036 100644
--- a/drivers/ide/cmd64x.c
+++ b/drivers/ide/cmd64x.c
@@ -333,7 +333,7 @@ static int cmd646_1_dma_end(ide_drive_t *drive)
return (dma_stat & 7) != 4;
}
-static unsigned int init_chipset_cmd64x(struct pci_dev *dev)
+static int init_chipset_cmd64x(struct pci_dev *dev)
{
u8 mrdmode = 0;
diff --git a/drivers/ide/cs5520.c b/drivers/ide/cs5520.c
index d003bec..58fb90e 100644
--- a/drivers/ide/cs5520.c
+++ b/drivers/ide/cs5520.c
@@ -133,7 +133,8 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic
* do all the device setup for us
*/
- ide_pci_setup_ports(dev, d, 14, &hw[0], &hws[0]);
+ ide_pci_setup_ports(dev, d, &hw[0], &hws[0]);
+ hw[0].irq = 14;
return ide_host_add(d, hws, NULL);
}
diff --git a/drivers/ide/cs5530.c b/drivers/ide/cs5530.c
index d8ede85..8e8b35a 100644
--- a/drivers/ide/cs5530.c
+++ b/drivers/ide/cs5530.c
@@ -135,7 +135,7 @@ static void cs5530_set_dma_mode(ide_drive_t *drive, const u8 mode)
* Initialize the cs5530 bridge for reliable IDE DMA operation.
*/
-static unsigned int init_chipset_cs5530(struct pci_dev *dev)
+static int init_chipset_cs5530(struct pci_dev *dev)
{
struct pci_dev *master_0 = NULL, *cs5530_0 = NULL;
diff --git a/drivers/ide/delkin_cb.c b/drivers/ide/delkin_cb.c
index 8f1b2d9..bacb119 100644
--- a/drivers/ide/delkin_cb.c
+++ b/drivers/ide/delkin_cb.c
@@ -46,7 +46,7 @@ static const struct ide_port_ops delkin_cb_port_ops = {
.quirkproc = ide_undecoded_slave,
};
-static unsigned int delkin_cb_init_chipset(struct pci_dev *dev)
+static int delkin_cb_init_chipset(struct pci_dev *dev)
{
unsigned long base = pci_resource_start(dev, 0);
int i;
diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c
index 3eb9b5c..d3b3e82 100644
--- a/drivers/ide/hpt366.c
+++ b/drivers/ide/hpt366.c
@@ -995,7 +995,7 @@ static void hpt3xx_disable_fast_irq(struct pci_dev *dev, u8 mcr_addr)
pci_write_config_byte(dev, mcr_addr + 1, new_mcr);
}
-static unsigned int init_chipset_hpt366(struct pci_dev *dev)
+static int init_chipset_hpt366(struct pci_dev *dev)
{
unsigned long io_base = pci_resource_start(dev, 4);
struct hpt_info *info = hpt3xx_get_info(&dev->dev);
@@ -1237,7 +1237,7 @@ static unsigned int init_chipset_hpt366(struct pci_dev *dev)
hpt3xx_disable_fast_irq(dev, 0x50);
hpt3xx_disable_fast_irq(dev, 0x54);
- return dev->irq;
+ return 0;
}
static u8 hpt3xx_cable_detect(ide_hwif_t *hwif)
diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c
index ec7d07f..5b704f1 100644
--- a/drivers/ide/ide-acpi.c
+++ b/drivers/ide/ide-acpi.c
@@ -20,9 +20,6 @@
#include <acpi/acpi_bus.h>
#define REGS_PER_GTF 7
-struct taskfile_array {
- u8 tfa[REGS_PER_GTF]; /* regs. 0x1f1 - 0x1f7 */
-};
struct GTM_buffer {
u32 PIO_speed0;
@@ -89,12 +86,8 @@ static const struct dmi_system_id ide_acpi_dmi_table[] = {
{ } /* terminate list */
};
-static int ide_acpi_blacklist(void)
+int ide_acpi_init(void)
{
- static int done;
- if (done)
- return 0;
- done = 1;
dmi_check_system(ide_acpi_dmi_table);
return 0;
}
@@ -202,40 +195,6 @@ static acpi_handle ide_acpi_hwif_get_handle(ide_hwif_t *hwif)
}
/**
- * ide_acpi_drive_get_handle - Get ACPI object handle for a given drive
- * @drive: device to locate
- *
- * Retrieves the object handle of a given drive. According to the ACPI
- * spec the drive is a child of the hwif.
- *
- * Returns handle on success, 0 on error.
- */
-static acpi_handle ide_acpi_drive_get_handle(ide_drive_t *drive)
-{
- ide_hwif_t *hwif = drive->hwif;
- int port;
- acpi_handle drive_handle;
-
- if (!hwif->acpidata)
- return NULL;
-
- if (!hwif->acpidata->obj_handle)
- return NULL;
-
- port = hwif->channel ? drive->dn - 2: drive->dn;
-
- DEBPRINT("ENTER: %s at channel#: %d port#: %d\n",
- drive->name, hwif->channel, port);
-
-
- /* TBD: could also check ACPI object VALID bits */
- drive_handle = acpi_get_child(hwif->acpidata->obj_handle, port);
- DEBPRINT("drive %s handle 0x%p\n", drive->name, drive_handle);
-
- return drive_handle;
-}
-
-/**
* do_drive_get_GTF - get the drive bootup default taskfile settings
* @drive: the drive for which the taskfile settings should be retrieved
* @gtf_length: number of bytes of _GTF data returned at @gtf_address
@@ -257,47 +216,15 @@ static int do_drive_get_GTF(ide_drive_t *drive,
acpi_status status;
struct acpi_buffer output;
union acpi_object *out_obj;
- ide_hwif_t *hwif = drive->hwif;
- struct device *dev = hwif->gendev.parent;
int err = -ENODEV;
- int port;
*gtf_length = 0;
*gtf_address = 0UL;
*obj_loc = 0UL;
- if (ide_noacpi)
- return 0;
-
- if (!dev) {
- DEBPRINT("no PCI device for %s\n", hwif->name);
- goto out;
- }
-
- if (!hwif->acpidata) {
- DEBPRINT("no ACPI data for %s\n", hwif->name);
- goto out;
- }
-
- port = hwif->channel ? drive->dn - 2: drive->dn;
-
- DEBPRINT("ENTER: %s at %s, port#: %d, hard_port#: %d\n",
- hwif->name, dev_name(dev), port, hwif->channel);
-
- if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) {
- DEBPRINT("%s drive %d:%d not present\n",
- hwif->name, hwif->channel, port);
- goto out;
- }
-
- /* Get this drive's _ADR info. if not already known. */
if (!drive->acpidata->obj_handle) {
- drive->acpidata->obj_handle = ide_acpi_drive_get_handle(drive);
- if (!drive->acpidata->obj_handle) {
- DEBPRINT("No ACPI object found for %s\n",
- drive->name);
- goto out;
- }
+ DEBPRINT("No ACPI object found for %s\n", drive->name);
+ goto out;
}
/* Setting up output buffer */
@@ -355,43 +282,6 @@ out:
}
/**
- * taskfile_load_raw - send taskfile registers to drive
- * @drive: drive to which output is sent
- * @gtf: raw ATA taskfile register set (0x1f1 - 0x1f7)
- *
- * Outputs IDE taskfile to the drive.
- */
-static int taskfile_load_raw(ide_drive_t *drive,
- const struct taskfile_array *gtf)
-{
- ide_task_t args;
- int err = 0;
-
- DEBPRINT("(0x1f1-1f7): hex: "
- "%02x %02x %02x %02x %02x %02x %02x\n",
- gtf->tfa[0], gtf->tfa[1], gtf->tfa[2],
- gtf->tfa[3], gtf->tfa[4], gtf->tfa[5], gtf->tfa[6]);
-
- memset(&args, 0, sizeof(ide_task_t));
-
- /* convert gtf to IDE Taskfile */
- memcpy(&args.tf_array[7], >f->tfa, 7);
- args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
-
- if (!ide_acpigtf) {
- DEBPRINT("_GTF execution disabled\n");
- return err;
- }
-
- err = ide_no_data_taskfile(drive, &args);
- if (err)
- printk(KERN_ERR "%s: ide_no_data_taskfile failed: %u\n",
- __func__, err);
-
- return err;
-}
-
-/**
* do_drive_set_taskfiles - write the drive taskfile settings from _GTF
* @drive: the drive to which the taskfile command should be sent
* @gtf_length: total number of bytes of _GTF taskfiles
@@ -404,43 +294,41 @@ static int do_drive_set_taskfiles(ide_drive_t *drive,
unsigned int gtf_length,
unsigned long gtf_address)
{
- int rc = -ENODEV, err;
+ int rc = 0, err;
int gtf_count = gtf_length / REGS_PER_GTF;
int ix;
- struct taskfile_array *gtf;
-
- if (ide_noacpi)
- return 0;
-
- DEBPRINT("ENTER: %s, hard_port#: %d\n", drive->name, drive->dn);
-
- if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
- goto out;
-
- if (!gtf_count) /* shouldn't be here */
- goto out;
DEBPRINT("total GTF bytes=%u (0x%x), gtf_count=%d, addr=0x%lx\n",
gtf_length, gtf_length, gtf_count, gtf_address);
- if (gtf_length % REGS_PER_GTF) {
- printk(KERN_ERR "%s: unexpected GTF length (%d)\n",
- __func__, gtf_length);
- goto out;
- }
-
- rc = 0;
+ /* send all taskfile registers (0x1f1-0x1f7) *in*that*order* */
for (ix = 0; ix < gtf_count; ix++) {
- gtf = (struct taskfile_array *)
- (gtf_address + ix * REGS_PER_GTF);
+ u8 *gtf = (u8 *)(gtf_address + ix * REGS_PER_GTF);
+ ide_task_t task;
- /* send all TaskFile registers (0x1f1-0x1f7) *in*that*order* */
- err = taskfile_load_raw(drive, gtf);
- if (err)
+ DEBPRINT("(0x1f1-1f7): "
+ "hex: %02x %02x %02x %02x %02x %02x %02x\n",
+ gtf[0], gtf[1], gtf[2],
+ gtf[3], gtf[4], gtf[5], gtf[6]);
+
+ if (!ide_acpigtf) {
+ DEBPRINT("_GTF execution disabled\n");
+ continue;
+ }
+
+ /* convert GTF to taskfile */
+ memset(&task, 0, sizeof(ide_task_t));
+ memcpy(&task.tf_array[7], gtf, REGS_PER_GTF);
+ task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+
+ err = ide_no_data_taskfile(drive, &task);
+ if (err) {
+ printk(KERN_ERR "%s: ide_no_data_taskfile failed: %u\n",
+ __func__, err);
rc = err;
+ }
}
-out:
return rc;
}
@@ -647,26 +535,23 @@ void ide_acpi_set_state(ide_hwif_t *hwif, int on)
DEBPRINT("no ACPI data for %s\n", hwif->name);
return;
}
+
/* channel first and then drives for power on and verse versa for power off */
if (on)
acpi_bus_set_power(hwif->acpidata->obj_handle, ACPI_STATE_D0);
- ide_port_for_each_dev(i, drive, hwif) {
- if (!drive->acpidata->obj_handle)
- drive->acpidata->obj_handle = ide_acpi_drive_get_handle(drive);
-
- if (drive->acpidata->obj_handle &&
- (drive->dev_flags & IDE_DFLAG_PRESENT)) {
+ ide_port_for_each_present_dev(i, drive, hwif) {
+ if (drive->acpidata->obj_handle)
acpi_bus_set_power(drive->acpidata->obj_handle,
- on? ACPI_STATE_D0: ACPI_STATE_D3);
- }
+ on ? ACPI_STATE_D0 : ACPI_STATE_D3);
}
+
if (!on)
acpi_bus_set_power(hwif->acpidata->obj_handle, ACPI_STATE_D3);
}
/**
- * ide_acpi_init - initialize the ACPI link for an IDE interface
+ * ide_acpi_init_port - initialize the ACPI link for an IDE interface
* @hwif: target IDE interface (channel)
*
* The ACPI spec is not quite clear when the drive identify buffer
@@ -676,10 +561,8 @@ void ide_acpi_set_state(ide_hwif_t *hwif, int on)
* So we get the information during startup; but this means that
* any changes during run-time will be lost after resume.
*/
-void ide_acpi_init(ide_hwif_t *hwif)
+void ide_acpi_init_port(ide_hwif_t *hwif)
{
- ide_acpi_blacklist();
-
hwif->acpidata = kzalloc(sizeof(struct ide_acpi_hwif_link), GFP_KERNEL);
if (!hwif->acpidata)
return;
@@ -708,15 +591,24 @@ void ide_acpi_port_init_devices(ide_hwif_t *hwif)
hwif->devices[0]->acpidata = &hwif->acpidata->master;
hwif->devices[1]->acpidata = &hwif->acpidata->slave;
- /*
- * Send IDENTIFY for each drive
- */
- ide_port_for_each_dev(i, drive, hwif) {
- memset(drive->acpidata, 0, sizeof(*drive->acpidata));
+ /* get _ADR info for each device */
+ ide_port_for_each_present_dev(i, drive, hwif) {
+ acpi_handle dev_handle;
- if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
- continue;
+ DEBPRINT("ENTER: %s at channel#: %d port#: %d\n",
+ drive->name, hwif->channel, drive->dn & 1);
+
+ /* TBD: could also check ACPI object VALID bits */
+ dev_handle = acpi_get_child(hwif->acpidata->obj_handle,
+ drive->dn & 1);
+
+ DEBPRINT("drive %s handle 0x%p\n", drive->name, dev_handle);
+
+ drive->acpidata->obj_handle = dev_handle;
+ }
+ /* send IDENTIFY for each device */
+ ide_port_for_each_present_dev(i, drive, hwif) {
err = taskfile_lib_get_identify(drive, drive->acpidata->idbuff);
if (err)
DEBPRINT("identify device %s failed (%d)\n",
@@ -736,9 +628,7 @@ void ide_acpi_port_init_devices(ide_hwif_t *hwif)
ide_acpi_get_timing(hwif);
ide_acpi_push_timing(hwif);
- ide_port_for_each_dev(i, drive, hwif) {
- if (drive->dev_flags & IDE_DFLAG_PRESENT)
- /* Execute ACPI startup code */
- ide_acpi_exec_tfs(drive);
+ ide_port_for_each_present_dev(i, drive, hwif) {
+ ide_acpi_exec_tfs(drive);
}
}
diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c
index e9d042d..6adc5b4 100644
--- a/drivers/ide/ide-atapi.c
+++ b/drivers/ide/ide-atapi.c
@@ -149,7 +149,10 @@ static void ide_queue_pc_head(ide_drive_t *drive, struct gendisk *disk,
memcpy(rq->cmd, pc->c, 12);
if (drive->media == ide_tape)
rq->cmd[13] = REQ_IDETAPE_PC1;
- ide_do_drive_cmd(drive, rq);
+
+ drive->hwif->rq = NULL;
+
+ elv_add_request(drive->queue, rq, ELEVATOR_INSERT_FRONT, 0);
}
/*
@@ -297,6 +300,21 @@ int ide_cd_get_xferlen(struct request *rq)
}
EXPORT_SYMBOL_GPL(ide_cd_get_xferlen);
+void ide_read_bcount_and_ireason(ide_drive_t *drive, u16 *bcount, u8 *ireason)
+{
+ ide_task_t task;
+
+ memset(&task, 0, sizeof(task));
+ task.tf_flags = IDE_TFLAG_IN_LBAH | IDE_TFLAG_IN_LBAM |
+ IDE_TFLAG_IN_NSECT;
+
+ drive->hwif->tp_ops->tf_read(drive, &task);
+
+ *bcount = (task.tf.lbah << 8) | task.tf.lbam;
+ *ireason = task.tf.nsect & 3;
+}
+EXPORT_SYMBOL_GPL(ide_read_bcount_and_ireason);
+
/*
* This is the usual interrupt handler which will be called during a packet
* command. We will transfer some of the data (as requested by the drive)
@@ -456,6 +474,25 @@ next_irq:
return ide_started;
}
+static void ide_pktcmd_tf_load(ide_drive_t *drive, u32 tf_flags, u16 bcount)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ ide_task_t task;
+ u8 dma = drive->dma;
+
+ memset(&task, 0, sizeof(task));
+ task.tf_flags = IDE_TFLAG_OUT_LBAH | IDE_TFLAG_OUT_LBAM |
+ IDE_TFLAG_OUT_FEATURE | tf_flags;
+ task.tf.feature = dma; /* Use PIO/DMA */
+ task.tf.lbam = bcount & 0xff;
+ task.tf.lbah = (bcount >> 8) & 0xff;
+
+ ide_tf_dump(drive->name, &task.tf);
+ hwif->tp_ops->set_irq(hwif, 1);
+ SELECT_MASK(drive, 0);
+ hwif->tp_ops->tf_load(drive, &task);
+}
+
static u8 ide_read_ireason(ide_drive_t *drive)
{
ide_task_t task;
@@ -629,7 +666,7 @@ ide_startstop_t ide_issue_pc(ide_drive_t *drive)
: WAIT_TAPE_CMD;
}
- ide_pktcmd_tf_load(drive, tf_flags, bcount, drive->dma);
+ ide_pktcmd_tf_load(drive, tf_flags, bcount);
/* Issue the packet command */
if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index ddfbea4..2177cd1 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -242,7 +242,9 @@ static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
ide_debug_log(IDE_DBG_SENSE, "failed_cmd: 0x%x\n",
failed_command->cmd[0]);
- ide_do_drive_cmd(drive, rq);
+ drive->hwif->rq = NULL;
+
+ elv_add_request(drive->queue, rq, ELEVATOR_INSERT_FRONT, 0);
}
static void cdrom_end_request(ide_drive_t *drive, int uptodate)
diff --git a/drivers/ide/ide-devsets.c b/drivers/ide/ide-devsets.c
new file mode 100644
index 0000000..7c39534
--- /dev/null
+++ b/drivers/ide/ide-devsets.c
@@ -0,0 +1,190 @@
+
+#include <linux/kernel.h>
+#include <linux/ide.h>
+
+DEFINE_MUTEX(ide_setting_mtx);
+
+ide_devset_get(io_32bit, io_32bit);
+
+static int set_io_32bit(ide_drive_t *drive, int arg)
+{
+ if (drive->dev_flags & IDE_DFLAG_NO_IO_32BIT)
+ return -EPERM;
+
+ if (arg < 0 || arg > 1 + (SUPPORT_VLB_SYNC << 1))
+ return -EINVAL;
+
+ drive->io_32bit = arg;
+
+ return 0;
+}
+
+ide_devset_get_flag(ksettings, IDE_DFLAG_KEEP_SETTINGS);
+
+static int set_ksettings(ide_drive_t *drive, int arg)
+{
+ if (arg < 0 || arg > 1)
+ return -EINVAL;
+
+ if (arg)
+ drive->dev_flags |= IDE_DFLAG_KEEP_SETTINGS;
+ else
+ drive->dev_flags &= ~IDE_DFLAG_KEEP_SETTINGS;
+
+ return 0;
+}
+
+ide_devset_get_flag(using_dma, IDE_DFLAG_USING_DMA);
+
+static int set_using_dma(ide_drive_t *drive, int arg)
+{
+#ifdef CONFIG_BLK_DEV_IDEDMA
+ int err = -EPERM;
+
+ if (arg < 0 || arg > 1)
+ return -EINVAL;
+
+ if (ata_id_has_dma(drive->id) == 0)
+ goto out;
+
+ if (drive->hwif->dma_ops == NULL)
+ goto out;
+
+ err = 0;
+
+ if (arg) {
+ if (ide_set_dma(drive))
+ err = -EIO;
+ } else
+ ide_dma_off(drive);
+
+out:
+ return err;
+#else
+ if (arg < 0 || arg > 1)
+ return -EINVAL;
+
+ return -EPERM;
+#endif
+}
+
+/*
+ * handle HDIO_SET_PIO_MODE ioctl abusers here, eventually it will go away
+ */
+static int set_pio_mode_abuse(ide_hwif_t *hwif, u8 req_pio)
+{
+ switch (req_pio) {
+ case 202:
+ case 201:
+ case 200:
+ case 102:
+ case 101:
+ case 100:
+ return (hwif->host_flags & IDE_HFLAG_ABUSE_DMA_MODES) ? 1 : 0;
+ case 9:
+ case 8:
+ return (hwif->host_flags & IDE_HFLAG_ABUSE_PREFETCH) ? 1 : 0;
+ case 7:
+ case 6:
+ return (hwif->host_flags & IDE_HFLAG_ABUSE_FAST_DEVSEL) ? 1 : 0;
+ default:
+ return 0;
+ }
+}
+
+static int set_pio_mode(ide_drive_t *drive, int arg)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ const struct ide_port_ops *port_ops = hwif->port_ops;
+
+ if (arg < 0 || arg > 255)
+ return -EINVAL;
+
+ if (port_ops == NULL || port_ops->set_pio_mode == NULL ||
+ (hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
+ return -ENOSYS;
+
+ if (set_pio_mode_abuse(drive->hwif, arg)) {
+ if (arg == 8 || arg == 9) {
+ unsigned long flags;
+
+ /* take lock for IDE_DFLAG_[NO_]UNMASK/[NO_]IO_32BIT */
+ spin_lock_irqsave(&hwif->lock, flags);
+ port_ops->set_pio_mode(drive, arg);
+ spin_unlock_irqrestore(&hwif->lock, flags);
+ } else
+ port_ops->set_pio_mode(drive, arg);
+ } else {
+ int keep_dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
+
+ ide_set_pio(drive, arg);
+
+ if (hwif->host_flags & IDE_HFLAG_SET_PIO_MODE_KEEP_DMA) {
+ if (keep_dma)
+ ide_dma_on(drive);
+ }
+ }
+
+ return 0;
+}
+
+ide_devset_get_flag(unmaskirq, IDE_DFLAG_UNMASK);
+
+static int set_unmaskirq(ide_drive_t *drive, int arg)
+{
+ if (drive->dev_flags & IDE_DFLAG_NO_UNMASK)
+ return -EPERM;
+
+ if (arg < 0 || arg > 1)
+ return -EINVAL;
+
+ if (arg)
+ drive->dev_flags |= IDE_DFLAG_UNMASK;
+ else
+ drive->dev_flags &= ~IDE_DFLAG_UNMASK;
+
+ return 0;
+}
+
+ide_ext_devset_rw_sync(io_32bit, io_32bit);
+ide_ext_devset_rw_sync(keepsettings, ksettings);
+ide_ext_devset_rw_sync(unmaskirq, unmaskirq);
+ide_ext_devset_rw_sync(using_dma, using_dma);
+__IDE_DEVSET(pio_mode, DS_SYNC, NULL, set_pio_mode);
+
+int ide_devset_execute(ide_drive_t *drive, const struct ide_devset *setting,
+ int arg)
+{
+ struct request_queue *q = drive->queue;
+ struct request *rq;
+ int ret = 0;
+
+ if (!(setting->flags & DS_SYNC))
+ return setting->set(drive, arg);
+
+ rq = blk_get_request(q, READ, __GFP_WAIT);
+ rq->cmd_type = REQ_TYPE_SPECIAL;
+ rq->cmd_len = 5;
+ rq->cmd[0] = REQ_DEVSET_EXEC;
+ *(int *)&rq->cmd[1] = arg;
+ rq->special = setting->set;
+
+ if (blk_execute_rq(q, NULL, rq, 0))
+ ret = rq->errors;
+ blk_put_request(rq);
+
+ return ret;
+}
+
+ide_startstop_t ide_do_devset(ide_drive_t *drive, struct request *rq)
+{
+ int err, (*setfunc)(ide_drive_t *, int) = rq->special;
+
+ err = setfunc(drive, *(int *)&rq->cmd[1]);
+ if (err)
+ rq->errors = err;
+ else
+ err = 1;
+ ide_end_request(drive, err, 0);
+ return ide_stopped;
+}
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index 059c90b..a878f47 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -470,6 +470,63 @@ void ide_dma_timeout(ide_drive_t *drive)
}
EXPORT_SYMBOL_GPL(ide_dma_timeout);
+/*
+ * un-busy the port etc, and clear any pending DMA status. we want to
+ * retry the current request in pio mode instead of risking tossing it
+ * all away
+ */
+ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ struct request *rq;
+ ide_startstop_t ret = ide_stopped;
+
+ /*
+ * end current dma transaction
+ */
+
+ if (error < 0) {
+ printk(KERN_WARNING "%s: DMA timeout error\n", drive->name);
+ (void)hwif->dma_ops->dma_end(drive);
+ ret = ide_error(drive, "dma timeout error",
+ hwif->tp_ops->read_status(hwif));
+ } else {
+ printk(KERN_WARNING "%s: DMA timeout retry\n", drive->name);
+ hwif->dma_ops->dma_timeout(drive);
+ }
+
+ /*
+ * disable dma for now, but remember that we did so because of
+ * a timeout -- we'll reenable after we finish this next request
+ * (or rather the first chunk of it) in pio.
+ */
+ drive->dev_flags |= IDE_DFLAG_DMA_PIO_RETRY;
+ drive->retry_pio++;
+ ide_dma_off_quietly(drive);
+
+ /*
+ * un-busy drive etc and make sure request is sane
+ */
+
+ rq = hwif->rq;
+ if (!rq)
+ goto out;
+
+ hwif->rq = NULL;
+
+ rq->errors = 0;
+
+ if (!rq->bio)
+ goto out;
+
+ rq->sector = rq->bio->bi_sector;
+ rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9;
+ rq->hard_cur_sectors = rq->current_nr_sectors;
+ rq->buffer = bio_data(rq->bio);
+out:
+ return ret;
+}
+
void ide_release_dma_engine(ide_hwif_t *hwif)
{
if (hwif->dmatable_cpu) {
diff --git a/drivers/ide/ide-eh.c b/drivers/ide/ide-eh.c
new file mode 100644
index 0000000..1231b5e
--- /dev/null
+++ b/drivers/ide/ide-eh.c
@@ -0,0 +1,428 @@
+
+#include <linux/kernel.h>
+#include <linux/ide.h>
+#include <linux/delay.h>
+
+static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq,
+ u8 stat, u8 err)
+{
+ ide_hwif_t *hwif = drive->hwif;
+
+ if ((stat & ATA_BUSY) ||
+ ((stat & ATA_DF) && (drive->dev_flags & IDE_DFLAG_NOWERR) == 0)) {
+ /* other bits are useless when BUSY */
+ rq->errors |= ERROR_RESET;
+ } else if (stat & ATA_ERR) {
+ /* err has different meaning on cdrom and tape */
+ if (err == ATA_ABORTED) {
+ if ((drive->dev_flags & IDE_DFLAG_LBA) &&
+ /* some newer drives don't support ATA_CMD_INIT_DEV_PARAMS */
+ hwif->tp_ops->read_status(hwif) == ATA_CMD_INIT_DEV_PARAMS)
+ return ide_stopped;
+ } else if ((err & BAD_CRC) == BAD_CRC) {
+ /* UDMA crc error, just retry the operation */
+ drive->crc_count++;
+ } else if (err & (ATA_BBK | ATA_UNC)) {
+ /* retries won't help these */
+ rq->errors = ERROR_MAX;
+ } else if (err & ATA_TRK0NF) {
+ /* help it find track zero */
+ rq->errors |= ERROR_RECAL;
+ }
+ }
+
+ if ((stat & ATA_DRQ) && rq_data_dir(rq) == READ &&
+ (hwif->host_flags & IDE_HFLAG_ERROR_STOPS_FIFO) == 0) {
+ int nsect = drive->mult_count ? drive->mult_count : 1;
+
+ ide_pad_transfer(drive, READ, nsect * SECTOR_SIZE);
+ }
+
+ if (rq->errors >= ERROR_MAX || blk_noretry_request(rq)) {
+ ide_kill_rq(drive, rq);
+ return ide_stopped;
+ }
+
+ if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ))
+ rq->errors |= ERROR_RESET;
+
+ if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
+ ++rq->errors;
+ return ide_do_reset(drive);
+ }
+
+ if ((rq->errors & ERROR_RECAL) == ERROR_RECAL)
+ drive->special.b.recalibrate = 1;
+
+ ++rq->errors;
+
+ return ide_stopped;
+}
+
+static ide_startstop_t ide_atapi_error(ide_drive_t *drive, struct request *rq,
+ u8 stat, u8 err)
+{
+ ide_hwif_t *hwif = drive->hwif;
+
+ if ((stat & ATA_BUSY) ||
+ ((stat & ATA_DF) && (drive->dev_flags & IDE_DFLAG_NOWERR) == 0)) {
+ /* other bits are useless when BUSY */
+ rq->errors |= ERROR_RESET;
+ } else {
+ /* add decoding error stuff */
+ }
+
+ if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ))
+ /* force an abort */
+ hwif->tp_ops->exec_command(hwif, ATA_CMD_IDLEIMMEDIATE);
+
+ if (rq->errors >= ERROR_MAX) {
+ ide_kill_rq(drive, rq);
+ } else {
+ if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
+ ++rq->errors;
+ return ide_do_reset(drive);
+ }
+ ++rq->errors;
+ }
+
+ return ide_stopped;
+}
+
+static ide_startstop_t __ide_error(ide_drive_t *drive, struct request *rq,
+ u8 stat, u8 err)
+{
+ if (drive->media == ide_disk)
+ return ide_ata_error(drive, rq, stat, err);
+ return ide_atapi_error(drive, rq, stat, err);
+}
+
+/**
+ * ide_error - handle an error on the IDE
+ * @drive: drive the error occurred on
+ * @msg: message to report
+ * @stat: status bits
+ *
+ * ide_error() takes action based on the error returned by the drive.
+ * For normal I/O that may well include retries. We deal with
+ * both new-style (taskfile) and old style command handling here.
+ * In the case of taskfile command handling there is work left to
+ * do
+ */
+
+ide_startstop_t ide_error(ide_drive_t *drive, const char *msg, u8 stat)
+{
+ struct request *rq;
+ u8 err;
+
+ err = ide_dump_status(drive, msg, stat);
+
+ rq = drive->hwif->rq;
+ if (rq == NULL)
+ return ide_stopped;
+
+ /* retry only "normal" I/O: */
+ if (!blk_fs_request(rq)) {
+ rq->errors = 1;
+ ide_end_drive_cmd(drive, stat, err);
+ return ide_stopped;
+ }
+
+ return __ide_error(drive, rq, stat, err);
+}
+EXPORT_SYMBOL_GPL(ide_error);
+
+static inline void ide_complete_drive_reset(ide_drive_t *drive, int err)
+{
+ struct request *rq = drive->hwif->rq;
+
+ if (rq && blk_special_request(rq) && rq->cmd[0] == REQ_DRIVE_RESET)
+ ide_end_request(drive, err ? err : 1, 0);
+}
+
+/* needed below */
+static ide_startstop_t do_reset1(ide_drive_t *, int);
+
+/*
+ * atapi_reset_pollfunc() gets invoked to poll the interface for completion
+ * every 50ms during an atapi drive reset operation. If the drive has not yet
+ * responded, and we have not yet hit our maximum waiting time, then the timer
+ * is restarted for another 50ms.
+ */
+static ide_startstop_t atapi_reset_pollfunc(ide_drive_t *drive)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ u8 stat;
+
+ SELECT_DRIVE(drive);
+ udelay(10);
+ stat = hwif->tp_ops->read_status(hwif);
+
+ if (OK_STAT(stat, 0, ATA_BUSY))
+ printk(KERN_INFO "%s: ATAPI reset complete\n", drive->name);
+ else {
+ if (time_before(jiffies, hwif->poll_timeout)) {
+ ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20,
+ NULL);
+ /* continue polling */
+ return ide_started;
+ }
+ /* end of polling */
+ hwif->polling = 0;
+ printk(KERN_ERR "%s: ATAPI reset timed-out, status=0x%02x\n",
+ drive->name, stat);
+ /* do it the old fashioned way */
+ return do_reset1(drive, 1);
+ }
+ /* done polling */
+ hwif->polling = 0;
+ ide_complete_drive_reset(drive, 0);
+ return ide_stopped;
+}
+
+static void ide_reset_report_error(ide_hwif_t *hwif, u8 err)
+{
+ static const char *err_master_vals[] =
+ { NULL, "passed", "formatter device error",
+ "sector buffer error", "ECC circuitry error",
+ "controlling MPU error" };
+
+ u8 err_master = err & 0x7f;
+
+ printk(KERN_ERR "%s: reset: master: ", hwif->name);
+ if (err_master && err_master < 6)
+ printk(KERN_CONT "%s", err_master_vals[err_master]);
+ else
+ printk(KERN_CONT "error (0x%02x?)", err);
+ if (err & 0x80)
+ printk(KERN_CONT "; slave: failed");
+ printk(KERN_CONT "\n");
+}
+
+/*
+ * reset_pollfunc() gets invoked to poll the interface for completion every 50ms
+ * during an ide reset operation. If the drives have not yet responded,
+ * and we have not yet hit our maximum waiting time, then the timer is restarted
+ * for another 50ms.
+ */
+static ide_startstop_t reset_pollfunc(ide_drive_t *drive)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ const struct ide_port_ops *port_ops = hwif->port_ops;
+ u8 tmp;
+ int err = 0;
+
+ if (port_ops && port_ops->reset_poll) {
+ err = port_ops->reset_poll(drive);
+ if (err) {
+ printk(KERN_ERR "%s: host reset_poll failure for %s.\n",
+ hwif->name, drive->name);
+ goto out;
+ }
+ }
+
+ tmp = hwif->tp_ops->read_status(hwif);
+
+ if (!OK_STAT(tmp, 0, ATA_BUSY)) {
+ if (time_before(jiffies, hwif->poll_timeout)) {
+ ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL);
+ /* continue polling */
+ return ide_started;
+ }
+ printk(KERN_ERR "%s: reset timed-out, status=0x%02x\n",
+ hwif->name, tmp);
+ drive->failures++;
+ err = -EIO;
+ } else {
+ tmp = ide_read_error(drive);
+
+ if (tmp == 1) {
+ printk(KERN_INFO "%s: reset: success\n", hwif->name);
+ drive->failures = 0;
+ } else {
+ ide_reset_report_error(hwif, tmp);
+ drive->failures++;
+ err = -EIO;
+ }
+ }
+out:
+ hwif->polling = 0; /* done polling */
+ ide_complete_drive_reset(drive, err);
+ return ide_stopped;
+}
+
+static void ide_disk_pre_reset(ide_drive_t *drive)
+{
+ int legacy = (drive->id[ATA_ID_CFS_ENABLE_2] & 0x0400) ? 0 : 1;
+
+ drive->special.all = 0;
+ drive->special.b.set_geometry = legacy;
+ drive->special.b.recalibrate = legacy;
+
+ drive->mult_count = 0;
+ drive->dev_flags &= ~IDE_DFLAG_PARKED;
+
+ if ((drive->dev_flags & IDE_DFLAG_KEEP_SETTINGS) == 0 &&
+ (drive->dev_flags & IDE_DFLAG_USING_DMA) == 0)
+ drive->mult_req = 0;
+
+ if (drive->mult_req != drive->mult_count)
+ drive->special.b.set_multmode = 1;
+}
+
+static void pre_reset(ide_drive_t *drive)
+{
+ const struct ide_port_ops *port_ops = drive->hwif->port_ops;
+
+ if (drive->media == ide_disk)
+ ide_disk_pre_reset(drive);
+ else
+ drive->dev_flags |= IDE_DFLAG_POST_RESET;
+
+ if (drive->dev_flags & IDE_DFLAG_USING_DMA) {
+ if (drive->crc_count)
+ ide_check_dma_crc(drive);
+ else
+ ide_dma_off(drive);
+ }
+
+ if ((drive->dev_flags & IDE_DFLAG_KEEP_SETTINGS) == 0) {
+ if ((drive->dev_flags & IDE_DFLAG_USING_DMA) == 0) {
+ drive->dev_flags &= ~IDE_DFLAG_UNMASK;
+ drive->io_32bit = 0;
+ }
+ return;
+ }
+
+ if (port_ops && port_ops->pre_reset)
+ port_ops->pre_reset(drive);
+
+ if (drive->current_speed != 0xff)
+ drive->desired_speed = drive->current_speed;
+ drive->current_speed = 0xff;
+}
+
+/*
+ * do_reset1() attempts to recover a confused drive by resetting it.
+ * Unfortunately, resetting a disk drive actually resets all devices on
+ * the same interface, so it can really be thought of as resetting the
+ * interface rather than resetting the drive.
+ *
+ * ATAPI devices have their own reset mechanism which allows them to be
+ * individually reset without clobbering other devices on the same interface.
+ *
+ * Unfortunately, the IDE interface does not generate an interrupt to let
+ * us know when the reset operation has finished, so we must poll for this.
+ * Equally poor, though, is the fact that this may a very long time to complete,
+ * (up to 30 seconds worstcase). So, instead of busy-waiting here for it,
+ * we set a timer to poll at 50ms intervals.
+ */
+static ide_startstop_t do_reset1(ide_drive_t *drive, int do_not_try_atapi)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ struct ide_io_ports *io_ports = &hwif->io_ports;
+ const struct ide_tp_ops *tp_ops = hwif->tp_ops;
+ const struct ide_port_ops *port_ops;
+ ide_drive_t *tdrive;
+ unsigned long flags, timeout;
+ int i;
+ DEFINE_WAIT(wait);
+
+ spin_lock_irqsave(&hwif->lock, flags);
+
+ /* We must not reset with running handlers */
+ BUG_ON(hwif->handler != NULL);
+
+ /* For an ATAPI device, first try an ATAPI SRST. */
+ if (drive->media != ide_disk && !do_not_try_atapi) {
+ pre_reset(drive);
+ SELECT_DRIVE(drive);
+ udelay(20);
+ tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET);
+ ndelay(400);
+ hwif->poll_timeout = jiffies + WAIT_WORSTCASE;
+ hwif->polling = 1;
+ __ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL);
+ spin_unlock_irqrestore(&hwif->lock, flags);
+ return ide_started;
+ }
+
+ /* We must not disturb devices in the IDE_DFLAG_PARKED state. */
+ do {
+ unsigned long now;
+
+ prepare_to_wait(&ide_park_wq, &wait, TASK_UNINTERRUPTIBLE);
+ timeout = jiffies;
+ ide_port_for_each_present_dev(i, tdrive, hwif) {
+ if ((tdrive->dev_flags & IDE_DFLAG_PARKED) &&
+ time_after(tdrive->sleep, timeout))
+ timeout = tdrive->sleep;
+ }
+
+ now = jiffies;
+ if (time_before_eq(timeout, now))
+ break;
+
+ spin_unlock_irqrestore(&hwif->lock, flags);
+ timeout = schedule_timeout_uninterruptible(timeout - now);
+ spin_lock_irqsave(&hwif->lock, flags);
+ } while (timeout);
+ finish_wait(&ide_park_wq, &wait);
+
+ /*
+ * First, reset any device state data we were maintaining
+ * for any of the drives on this interface.
+ */
+ ide_port_for_each_dev(i, tdrive, hwif)
+ pre_reset(tdrive);
+
+ if (io_ports->ctl_addr == 0) {
+ spin_unlock_irqrestore(&hwif->lock, flags);
+ ide_complete_drive_reset(drive, -ENXIO);
+ return ide_stopped;
+ }
+
+ /*
+ * Note that we also set nIEN while resetting the device,
+ * to mask unwanted interrupts from the interface during the reset.
+ * However, due to the design of PC hardware, this will cause an
+ * immediate interrupt due to the edge transition it produces.
+ * This single interrupt gives us a "fast poll" for drives that
+ * recover from reset very quickly, saving us the first 50ms wait time.
+ *
+ * TODO: add ->softreset method and stop abusing ->set_irq
+ */
+ /* set SRST and nIEN */
+ tp_ops->set_irq(hwif, 4);
+ /* more than enough time */
+ udelay(10);
+ /* clear SRST, leave nIEN (unless device is on the quirk list) */
+ tp_ops->set_irq(hwif, drive->quirk_list == 2);
+ /* more than enough time */
+ udelay(10);
+ hwif->poll_timeout = jiffies + WAIT_WORSTCASE;
+ hwif->polling = 1;
+ __ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL);
+
+ /*
+ * Some weird controller like resetting themselves to a strange
+ * state when the disks are reset this way. At least, the Winbond
+ * 553 documentation says that
+ */
+ port_ops = hwif->port_ops;
+ if (port_ops && port_ops->resetproc)
+ port_ops->resetproc(drive);
+
+ spin_unlock_irqrestore(&hwif->lock, flags);
+ return ide_started;
+}
+
+/*
+ * ide_do_reset() is the entry point to the drive/interface reset code.
+ */
+
+ide_startstop_t ide_do_reset(ide_drive_t *drive)
+{
+ return do_reset1(drive, 0);
+}
+EXPORT_SYMBOL(ide_do_reset);
diff --git a/drivers/ide/ide-io-std.c b/drivers/ide/ide-io-std.c
new file mode 100644
index 0000000..45b43dd
--- /dev/null
+++ b/drivers/ide/ide-io-std.c
@@ -0,0 +1,316 @@
+
+#include <linux/kernel.h>
+#include <linux/ide.h>
+
+/*
+ * Conventional PIO operations for ATA devices
+ */
+
+static u8 ide_inb(unsigned long port)
+{
+ return (u8) inb(port);
+}
+
+static void ide_outb(u8 val, unsigned long port)
+{
+ outb(val, port);
+}
+
+/*
+ * MMIO operations, typically used for SATA controllers
+ */
+
+static u8 ide_mm_inb(unsigned long port)
+{
+ return (u8) readb((void __iomem *) port);
+}
+
+static void ide_mm_outb(u8 value, unsigned long port)
+{
+ writeb(value, (void __iomem *) port);
+}
+
+void ide_exec_command(ide_hwif_t *hwif, u8 cmd)
+{
+ if (hwif->host_flags & IDE_HFLAG_MMIO)
+ writeb(cmd, (void __iomem *)hwif->io_ports.command_addr);
+ else
+ outb(cmd, hwif->io_ports.command_addr);
+}
+EXPORT_SYMBOL_GPL(ide_exec_command);
+
+u8 ide_read_status(ide_hwif_t *hwif)
+{
+ if (hwif->host_flags & IDE_HFLAG_MMIO)
+ return readb((void __iomem *)hwif->io_ports.status_addr);
+ else
+ return inb(hwif->io_ports.status_addr);
+}
+EXPORT_SYMBOL_GPL(ide_read_status);
+
+u8 ide_read_altstatus(ide_hwif_t *hwif)
+{
+ if (hwif->host_flags & IDE_HFLAG_MMIO)
+ return readb((void __iomem *)hwif->io_ports.ctl_addr);
+ else
+ return inb(hwif->io_ports.ctl_addr);
+}
+EXPORT_SYMBOL_GPL(ide_read_altstatus);
+
+void ide_set_irq(ide_hwif_t *hwif, int on)
+{
+ u8 ctl = ATA_DEVCTL_OBS;
+
+ if (on == 4) { /* hack for SRST */
+ ctl |= 4;
+ on &= ~4;
+ }
+
+ ctl |= on ? 0 : 2;
+
+ if (hwif->host_flags & IDE_HFLAG_MMIO)
+ writeb(ctl, (void __iomem *)hwif->io_ports.ctl_addr);
+ else
+ outb(ctl, hwif->io_ports.ctl_addr);
+}
+EXPORT_SYMBOL_GPL(ide_set_irq);
+
+void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ struct ide_io_ports *io_ports = &hwif->io_ports;
+ struct ide_taskfile *tf = &task->tf;
+ void (*tf_outb)(u8 addr, unsigned long port);
+ u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
+ u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF;
+
+ if (mmio)
+ tf_outb = ide_mm_outb;
+ else
+ tf_outb = ide_outb;
+
+ if (task->tf_flags & IDE_TFLAG_FLAGGED)
+ HIHI = 0xFF;
+
+ if (task->tf_flags & IDE_TFLAG_OUT_DATA) {
+ u16 data = (tf->hob_data << 8) | tf->data;
+
+ if (mmio)
+ writew(data, (void __iomem *)io_ports->data_addr);
+ else
+ outw(data, io_ports->data_addr);
+ }
+
+ if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
+ tf_outb(tf->hob_feature, io_ports->feature_addr);
+ if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
+ tf_outb(tf->hob_nsect, io_ports->nsect_addr);
+ if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
+ tf_outb(tf->hob_lbal, io_ports->lbal_addr);
+ if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
+ tf_outb(tf->hob_lbam, io_ports->lbam_addr);
+ if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
+ tf_outb(tf->hob_lbah, io_ports->lbah_addr);
+
+ if (task->tf_flags & IDE_TFLAG_OUT_FEATURE)
+ tf_outb(tf->feature, io_ports->feature_addr);
+ if (task->tf_flags & IDE_TFLAG_OUT_NSECT)
+ tf_outb(tf->nsect, io_ports->nsect_addr);
+ if (task->tf_flags & IDE_TFLAG_OUT_LBAL)
+ tf_outb(tf->lbal, io_ports->lbal_addr);
+ if (task->tf_flags & IDE_TFLAG_OUT_LBAM)
+ tf_outb(tf->lbam, io_ports->lbam_addr);
+ if (task->tf_flags & IDE_TFLAG_OUT_LBAH)
+ tf_outb(tf->lbah, io_ports->lbah_addr);
+
+ if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
+ tf_outb((tf->device & HIHI) | drive->select,
+ io_ports->device_addr);
+}
+EXPORT_SYMBOL_GPL(ide_tf_load);
+
+void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ struct ide_io_ports *io_ports = &hwif->io_ports;
+ struct ide_taskfile *tf = &task->tf;
+ void (*tf_outb)(u8 addr, unsigned long port);
+ u8 (*tf_inb)(unsigned long port);
+ u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
+
+ if (mmio) {
+ tf_outb = ide_mm_outb;
+ tf_inb = ide_mm_inb;
+ } else {
+ tf_outb = ide_outb;
+ tf_inb = ide_inb;
+ }
+
+ if (task->tf_flags & IDE_TFLAG_IN_DATA) {
+ u16 data;
+
+ if (mmio)
+ data = readw((void __iomem *)io_ports->data_addr);
+ else
+ data = inw(io_ports->data_addr);
+
+ tf->data = data & 0xff;
+ tf->hob_data = (data >> 8) & 0xff;
+ }
+
+ /* be sure we're looking at the low order bits */
+ tf_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
+
+ if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
+ tf->feature = tf_inb(io_ports->feature_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_NSECT)
+ tf->nsect = tf_inb(io_ports->nsect_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_LBAL)
+ tf->lbal = tf_inb(io_ports->lbal_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_LBAM)
+ tf->lbam = tf_inb(io_ports->lbam_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_LBAH)
+ tf->lbah = tf_inb(io_ports->lbah_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
+ tf->device = tf_inb(io_ports->device_addr);
+
+ if (task->tf_flags & IDE_TFLAG_LBA48) {
+ tf_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr);
+
+ if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
+ tf->hob_feature = tf_inb(io_ports->feature_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
+ tf->hob_nsect = tf_inb(io_ports->nsect_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
+ tf->hob_lbal = tf_inb(io_ports->lbal_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
+ tf->hob_lbam = tf_inb(io_ports->lbam_addr);
+ if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
+ tf->hob_lbah = tf_inb(io_ports->lbah_addr);
+ }
+}
+EXPORT_SYMBOL_GPL(ide_tf_read);
+
+/*
+ * Some localbus EIDE interfaces require a special access sequence
+ * when using 32-bit I/O instructions to transfer data. We call this
+ * the "vlb_sync" sequence, which consists of three successive reads
+ * of the sector count register location, with interrupts disabled
+ * to ensure that the reads all happen together.
+ */
+static void ata_vlb_sync(unsigned long port)
+{
+ (void)inb(port);
+ (void)inb(port);
+ (void)inb(port);
+}
+
+/*
+ * This is used for most PIO data transfers *from* the IDE interface
+ *
+ * These routines will round up any request for an odd number of bytes,
+ * so if an odd len is specified, be sure that there's at least one
+ * extra byte allocated for the buffer.
+ */
+void ide_input_data(ide_drive_t *drive, struct request *rq, void *buf,
+ unsigned int len)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ struct ide_io_ports *io_ports = &hwif->io_ports;
+ unsigned long data_addr = io_ports->data_addr;
+ u8 io_32bit = drive->io_32bit;
+ u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
+
+ len++;
+
+ if (io_32bit) {
+ unsigned long uninitialized_var(flags);
+
+ if ((io_32bit & 2) && !mmio) {
+ local_irq_save(flags);
+ ata_vlb_sync(io_ports->nsect_addr);
+ }
+
+ if (mmio)
+ __ide_mm_insl((void __iomem *)data_addr, buf, len / 4);
+ else
+ insl(data_addr, buf, len / 4);
+
+ if ((io_32bit & 2) && !mmio)
+ local_irq_restore(flags);
+
+ if ((len & 3) >= 2) {
+ if (mmio)
+ __ide_mm_insw((void __iomem *)data_addr,
+ (u8 *)buf + (len & ~3), 1);
+ else
+ insw(data_addr, (u8 *)buf + (len & ~3), 1);
+ }
+ } else {
+ if (mmio)
+ __ide_mm_insw((void __iomem *)data_addr, buf, len / 2);
+ else
+ insw(data_addr, buf, len / 2);
+ }
+}
+EXPORT_SYMBOL_GPL(ide_input_data);
+
+/*
+ * This is used for most PIO data transfers *to* the IDE interface
+ */
+void ide_output_data(ide_drive_t *drive, struct request *rq, void *buf,
+ unsigned int len)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ struct ide_io_ports *io_ports = &hwif->io_ports;
+ unsigned long data_addr = io_ports->data_addr;
+ u8 io_32bit = drive->io_32bit;
+ u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
+
+ len++;
+
+ if (io_32bit) {
+ unsigned long uninitialized_var(flags);
+
+ if ((io_32bit & 2) && !mmio) {
+ local_irq_save(flags);
+ ata_vlb_sync(io_ports->nsect_addr);
+ }
+
+ if (mmio)
+ __ide_mm_outsl((void __iomem *)data_addr, buf, len / 4);
+ else
+ outsl(data_addr, buf, len / 4);
+
+ if ((io_32bit & 2) && !mmio)
+ local_irq_restore(flags);
+
+ if ((len & 3) >= 2) {
+ if (mmio)
+ __ide_mm_outsw((void __iomem *)data_addr,
+ (u8 *)buf + (len & ~3), 1);
+ else
+ outsw(data_addr, (u8 *)buf + (len & ~3), 1);
+ }
+ } else {
+ if (mmio)
+ __ide_mm_outsw((void __iomem *)data_addr, buf, len / 2);
+ else
+ outsw(data_addr, buf, len / 2);
+ }
+}
+EXPORT_SYMBOL_GPL(ide_output_data);
+
+const struct ide_tp_ops default_tp_ops = {
+ .exec_command = ide_exec_command,
+ .read_status = ide_read_status,
+ .read_altstatus = ide_read_altstatus,
+
+ .set_irq = ide_set_irq,
+
+ .tf_load = ide_tf_load,
+ .tf_read = ide_tf_read,
+
+ .input_data = ide_input_data,
+ .output_data = ide_output_data,
+};
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index a9a6c20..2e92497 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -196,7 +196,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
}
EXPORT_SYMBOL(ide_end_drive_cmd);
-static void ide_kill_rq(ide_drive_t *drive, struct request *rq)
+void ide_kill_rq(ide_drive_t *drive, struct request *rq)
{
if (rq->rq_disk) {
struct ide_driver *drv;
@@ -207,133 +207,6 @@ static void ide_kill_rq(ide_drive_t *drive, struct request *rq)
ide_end_request(drive, 0, 0);
}
-static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
-{
- ide_hwif_t *hwif = drive->hwif;
-
- if ((stat & ATA_BUSY) ||
- ((stat & ATA_DF) && (drive->dev_flags & IDE_DFLAG_NOWERR) == 0)) {
- /* other bits are useless when BUSY */
- rq->errors |= ERROR_RESET;
- } else if (stat & ATA_ERR) {
- /* err has different meaning on cdrom and tape */
- if (err == ATA_ABORTED) {
- if ((drive->dev_flags & IDE_DFLAG_LBA) &&
- /* some newer drives don't support ATA_CMD_INIT_DEV_PARAMS */
- hwif->tp_ops->read_status(hwif) == ATA_CMD_INIT_DEV_PARAMS)
- return ide_stopped;
- } else if ((err & BAD_CRC) == BAD_CRC) {
- /* UDMA crc error, just retry the operation */
- drive->crc_count++;
- } else if (err & (ATA_BBK | ATA_UNC)) {
- /* retries won't help these */
- rq->errors = ERROR_MAX;
- } else if (err & ATA_TRK0NF) {
- /* help it find track zero */
- rq->errors |= ERROR_RECAL;
- }
- }
-
- if ((stat & ATA_DRQ) && rq_data_dir(rq) == READ &&
- (hwif->host_flags & IDE_HFLAG_ERROR_STOPS_FIFO) == 0) {
- int nsect = drive->mult_count ? drive->mult_count : 1;
-
- ide_pad_transfer(drive, READ, nsect * SECTOR_SIZE);
- }
-
- if (rq->errors >= ERROR_MAX || blk_noretry_request(rq)) {
- ide_kill_rq(drive, rq);
- return ide_stopped;
- }
-
- if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ))
- rq->errors |= ERROR_RESET;
-
- if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
- ++rq->errors;
- return ide_do_reset(drive);
- }
-
- if ((rq->errors & ERROR_RECAL) == ERROR_RECAL)
- drive->special.b.recalibrate = 1;
-
- ++rq->errors;
-
- return ide_stopped;
-}
-
-static ide_startstop_t ide_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
-{
- ide_hwif_t *hwif = drive->hwif;
-
- if ((stat & ATA_BUSY) ||
- ((stat & ATA_DF) && (drive->dev_flags & IDE_DFLAG_NOWERR) == 0)) {
- /* other bits are useless when BUSY */
- rq->errors |= ERROR_RESET;
- } else {
- /* add decoding error stuff */
- }
-
- if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ))
- /* force an abort */
- hwif->tp_ops->exec_command(hwif, ATA_CMD_IDLEIMMEDIATE);
-
- if (rq->errors >= ERROR_MAX) {
- ide_kill_rq(drive, rq);
- } else {
- if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
- ++rq->errors;
- return ide_do_reset(drive);
- }
- ++rq->errors;
- }
-
- return ide_stopped;
-}
-
-static ide_startstop_t
-__ide_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
-{
- if (drive->media == ide_disk)
- return ide_ata_error(drive, rq, stat, err);
- return ide_atapi_error(drive, rq, stat, err);
-}
-
-/**
- * ide_error - handle an error on the IDE
- * @drive: drive the error occurred on
- * @msg: message to report
- * @stat: status bits
- *
- * ide_error() takes action based on the error returned by the drive.
- * For normal I/O that may well include retries. We deal with
- * both new-style (taskfile) and old style command handling here.
- * In the case of taskfile command handling there is work left to
- * do
- */
-
-ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, u8 stat)
-{
- struct request *rq;
- u8 err;
-
- err = ide_dump_status(drive, msg, stat);
-
- rq = drive->hwif->rq;
- if (rq == NULL)
- return ide_stopped;
-
- /* retry only "normal" I/O: */
- if (!blk_fs_request(rq)) {
- rq->errors = 1;
- ide_end_drive_cmd(drive, stat, err);
- return ide_stopped;
- }
-
- return __ide_error(drive, rq, stat, err);
-}
-EXPORT_SYMBOL_GPL(ide_error);
-
static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
{
tf->nsect = drive->sect;
@@ -490,71 +363,16 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
return ide_stopped;
}
-int ide_devset_execute(ide_drive_t *drive, const struct ide_devset *setting,
- int arg)
-{
- struct request_queue *q = drive->queue;
- struct request *rq;
- int ret = 0;
-
- if (!(setting->flags & DS_SYNC))
- return setting->set(drive, arg);
-
- rq = blk_get_request(q, READ, __GFP_WAIT);
- rq->cmd_type = REQ_TYPE_SPECIAL;
- rq->cmd_len = 5;
- rq->cmd[0] = REQ_DEVSET_EXEC;
- *(int *)&rq->cmd[1] = arg;
- rq->special = setting->set;
-
- if (blk_execute_rq(q, NULL, rq, 0))
- ret = rq->errors;
- blk_put_request(rq);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(ide_devset_execute);
-
static ide_startstop_t ide_special_rq(ide_drive_t *drive, struct request *rq)
{
u8 cmd = rq->cmd[0];
- if (cmd == REQ_PARK_HEADS || cmd == REQ_UNPARK_HEADS) {
- ide_task_t task;
- struct ide_taskfile *tf = &task.tf;
-
- memset(&task, 0, sizeof(task));
- if (cmd == REQ_PARK_HEADS) {
- drive->sleep = *(unsigned long *)rq->special;
- drive->dev_flags |= IDE_DFLAG_SLEEPING;
- tf->command = ATA_CMD_IDLEIMMEDIATE;
- tf->feature = 0x44;
- tf->lbal = 0x4c;
- tf->lbam = 0x4e;
- tf->lbah = 0x55;
- task.tf_flags |= IDE_TFLAG_CUSTOM_HANDLER;
- } else /* cmd == REQ_UNPARK_HEADS */
- tf->command = ATA_CMD_CHK_POWER;
-
- task.tf_flags |= IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
- task.rq = rq;
- drive->hwif->data_phase = task.data_phase = TASKFILE_NO_DATA;
- return do_rw_taskfile(drive, &task);
- }
-
switch (cmd) {
+ case REQ_PARK_HEADS:
+ case REQ_UNPARK_HEADS:
+ return ide_do_park_unpark(drive, rq);
case REQ_DEVSET_EXEC:
- {
- int err, (*setfunc)(ide_drive_t *, int) = rq->special;
-
- err = setfunc(drive, *(int *)&rq->cmd[1]);
- if (err)
- rq->errors = err;
- else
- err = 1;
- ide_end_request(drive, err, 0);
- return ide_stopped;
- }
+ return ide_do_devset(drive, rq);
case REQ_DRIVE_RESET:
return ide_do_reset(drive);
default:
@@ -820,63 +638,6 @@ plug_device_2:
blk_plug_device(q);
}
-/*
- * un-busy the port etc, and clear any pending DMA status. we want to
- * retry the current request in pio mode instead of risking tossing it
- * all away
- */
-static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
-{
- ide_hwif_t *hwif = drive->hwif;
- struct request *rq;
- ide_startstop_t ret = ide_stopped;
-
- /*
- * end current dma transaction
- */
-
- if (error < 0) {
- printk(KERN_WARNING "%s: DMA timeout error\n", drive->name);
- (void)hwif->dma_ops->dma_end(drive);
- ret = ide_error(drive, "dma timeout error",
- hwif->tp_ops->read_status(hwif));
- } else {
- printk(KERN_WARNING "%s: DMA timeout retry\n", drive->name);
- hwif->dma_ops->dma_timeout(drive);
- }
-
- /*
- * disable dma for now, but remember that we did so because of
- * a timeout -- we'll reenable after we finish this next request
- * (or rather the first chunk of it) in pio.
- */
- drive->dev_flags |= IDE_DFLAG_DMA_PIO_RETRY;
- drive->retry_pio++;
- ide_dma_off_quietly(drive);
-
- /*
- * un-busy drive etc and make sure request is sane
- */
-
- rq = hwif->rq;
- if (!rq)
- goto out;
-
- hwif->rq = NULL;
-
- rq->errors = 0;
-
- if (!rq->bio)
- goto out;
-
- rq->sector = rq->bio->bi_sector;
- rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9;
- rq->hard_cur_sectors = rq->current_nr_sectors;
- rq->buffer = bio_data(rq->bio);
-out:
- return ret;
-}
-
static void ide_plug_device(ide_drive_t *drive)
{
struct request_queue *q = drive->queue;
@@ -888,6 +649,29 @@ static void ide_plug_device(ide_drive_t *drive)
spin_unlock_irqrestore(q->queue_lock, flags);
}
+static int drive_is_ready(ide_drive_t *drive)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ u8 stat = 0;
+
+ if (drive->waiting_for_dma)
+ return hwif->dma_ops->dma_test_irq(drive);
+
+ if (hwif->io_ports.ctl_addr &&
+ (hwif->host_flags & IDE_HFLAG_BROKEN_ALTSTATUS) == 0)
+ stat = hwif->tp_ops->read_altstatus(hwif);
+ else
+ /* Note: this may clear a pending IRQ!! */
+ stat = hwif->tp_ops->read_status(hwif);
+
+ if (stat & ATA_BUSY)
+ /* drive busy: definitely not interrupting */
+ return 0;
+
+ /* drive ready: *might* be interrupting */
+ return 1;
+}
+
/**
* ide_timer_expiry - handle lack of an IDE interrupt
* @data: timer callback magic (hwif)
@@ -1164,54 +948,6 @@ out_early:
}
EXPORT_SYMBOL_GPL(ide_intr);
-/**
- * ide_do_drive_cmd - issue IDE special command
- * @drive: device to issue command
- * @rq: request to issue
- *
- * This function issues a special IDE device request
- * onto the request queue.
- *
- * the rq is queued at the head of the request queue, displacing
- * the currently-being-processed request and this function
- * returns immediately without waiting for the new rq to be
- * completed. This is VERY DANGEROUS, and is intended for
- * careful use by the ATAPI tape/cdrom driver code.
- */
-
-void ide_do_drive_cmd(ide_drive_t *drive, struct request *rq)
-{
- struct request_queue *q = drive->queue;
- unsigned long flags;
-
- drive->hwif->rq = NULL;
-
- spin_lock_irqsave(q->queue_lock, flags);
- __elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0);
- spin_unlock_irqrestore(q->queue_lock, flags);
-}
-EXPORT_SYMBOL(ide_do_drive_cmd);
-
-void ide_pktcmd_tf_load(ide_drive_t *drive, u32 tf_flags, u16 bcount, u8 dma)
-{
- ide_hwif_t *hwif = drive->hwif;
- ide_task_t task;
-
- memset(&task, 0, sizeof(task));
- task.tf_flags = IDE_TFLAG_OUT_LBAH | IDE_TFLAG_OUT_LBAM |
- IDE_TFLAG_OUT_FEATURE | tf_flags;
- task.tf.feature = dma; /* Use PIO/DMA */
- task.tf.lbam = bcount & 0xff;
- task.tf.lbah = (bcount >> 8) & 0xff;
-
- ide_tf_dump(drive->name, &task.tf);
- hwif->tp_ops->set_irq(hwif, 1);
- SELECT_MASK(drive, 0);
- hwif->tp_ops->tf_load(drive, &task);
-}
-
-EXPORT_SYMBOL_GPL(ide_pktcmd_tf_load);
-
void ide_pad_transfer(ide_drive_t *drive, int write, int len)
{
ide_hwif_t *hwif = drive->hwif;
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index b1892bd..317c5da 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -27,35 +27,7 @@
#include <asm/uaccess.h>
#include <asm/io.h>
-/*
- * Conventional PIO operations for ATA devices
- */
-
-static u8 ide_inb (unsigned long port)
-{
- return (u8) inb(port);
-}
-
-static void ide_outb (u8 val, unsigned long port)
-{
- outb(val, port);
-}
-
-/*
- * MMIO operations, typically used for SATA controllers
- */
-
-static u8 ide_mm_inb (unsigned long port)
-{
- return (u8) readb((void __iomem *) port);
-}
-
-static void ide_mm_outb (u8 value, unsigned long port)
-{
- writeb(value, (void __iomem *) port);
-}
-
-void SELECT_DRIVE (ide_drive_t *drive)
+void SELECT_DRIVE(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
const struct ide_port_ops *port_ops = hwif->port_ops;
@@ -78,277 +50,6 @@ void SELECT_MASK(ide_drive_t *drive, int mask)
port_ops->maskproc(drive, mask);
}
-void ide_exec_command(ide_hwif_t *hwif, u8 cmd)
-{
- if (hwif->host_flags & IDE_HFLAG_MMIO)
- writeb(cmd, (void __iomem *)hwif->io_ports.command_addr);
- else
- outb(cmd, hwif->io_ports.command_addr);
-}
-EXPORT_SYMBOL_GPL(ide_exec_command);
-
-u8 ide_read_status(ide_hwif_t *hwif)
-{
- if (hwif->host_flags & IDE_HFLAG_MMIO)
- return readb((void __iomem *)hwif->io_ports.status_addr);
- else
- return inb(hwif->io_ports.status_addr);
-}
-EXPORT_SYMBOL_GPL(ide_read_status);
-
-u8 ide_read_altstatus(ide_hwif_t *hwif)
-{
- if (hwif->host_flags & IDE_HFLAG_MMIO)
- return readb((void __iomem *)hwif->io_ports.ctl_addr);
- else
- return inb(hwif->io_ports.ctl_addr);
-}
-EXPORT_SYMBOL_GPL(ide_read_altstatus);
-
-void ide_set_irq(ide_hwif_t *hwif, int on)
-{
- u8 ctl = ATA_DEVCTL_OBS;
-
- if (on == 4) { /* hack for SRST */
- ctl |= 4;
- on &= ~4;
- }
-
- ctl |= on ? 0 : 2;
-
- if (hwif->host_flags & IDE_HFLAG_MMIO)
- writeb(ctl, (void __iomem *)hwif->io_ports.ctl_addr);
- else
- outb(ctl, hwif->io_ports.ctl_addr);
-}
-EXPORT_SYMBOL_GPL(ide_set_irq);
-
-void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
-{
- ide_hwif_t *hwif = drive->hwif;
- struct ide_io_ports *io_ports = &hwif->io_ports;
- struct ide_taskfile *tf = &task->tf;
- void (*tf_outb)(u8 addr, unsigned long port);
- u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
- u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF;
-
- if (mmio)
- tf_outb = ide_mm_outb;
- else
- tf_outb = ide_outb;
-
- if (task->tf_flags & IDE_TFLAG_FLAGGED)
- HIHI = 0xFF;
-
- if (task->tf_flags & IDE_TFLAG_OUT_DATA) {
- u16 data = (tf->hob_data << 8) | tf->data;
-
- if (mmio)
- writew(data, (void __iomem *)io_ports->data_addr);
- else
- outw(data, io_ports->data_addr);
- }
-
- if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
- tf_outb(tf->hob_feature, io_ports->feature_addr);
- if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
- tf_outb(tf->hob_nsect, io_ports->nsect_addr);
- if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
- tf_outb(tf->hob_lbal, io_ports->lbal_addr);
- if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
- tf_outb(tf->hob_lbam, io_ports->lbam_addr);
- if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
- tf_outb(tf->hob_lbah, io_ports->lbah_addr);
-
- if (task->tf_flags & IDE_TFLAG_OUT_FEATURE)
- tf_outb(tf->feature, io_ports->feature_addr);
- if (task->tf_flags & IDE_TFLAG_OUT_NSECT)
- tf_outb(tf->nsect, io_ports->nsect_addr);
- if (task->tf_flags & IDE_TFLAG_OUT_LBAL)
- tf_outb(tf->lbal, io_ports->lbal_addr);
- if (task->tf_flags & IDE_TFLAG_OUT_LBAM)
- tf_outb(tf->lbam, io_ports->lbam_addr);
- if (task->tf_flags & IDE_TFLAG_OUT_LBAH)
- tf_outb(tf->lbah, io_ports->lbah_addr);
-
- if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
- tf_outb((tf->device & HIHI) | drive->select,
- io_ports->device_addr);
-}
-EXPORT_SYMBOL_GPL(ide_tf_load);
-
-void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
-{
- ide_hwif_t *hwif = drive->hwif;
- struct ide_io_ports *io_ports = &hwif->io_ports;
- struct ide_taskfile *tf = &task->tf;
- void (*tf_outb)(u8 addr, unsigned long port);
- u8 (*tf_inb)(unsigned long port);
- u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
-
- if (mmio) {
- tf_outb = ide_mm_outb;
- tf_inb = ide_mm_inb;
- } else {
- tf_outb = ide_outb;
- tf_inb = ide_inb;
- }
-
- if (task->tf_flags & IDE_TFLAG_IN_DATA) {
- u16 data;
-
- if (mmio)
- data = readw((void __iomem *)io_ports->data_addr);
- else
- data = inw(io_ports->data_addr);
-
- tf->data = data & 0xff;
- tf->hob_data = (data >> 8) & 0xff;
- }
-
- /* be sure we're looking at the low order bits */
- tf_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
-
- if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
- tf->feature = tf_inb(io_ports->feature_addr);
- if (task->tf_flags & IDE_TFLAG_IN_NSECT)
- tf->nsect = tf_inb(io_ports->nsect_addr);
- if (task->tf_flags & IDE_TFLAG_IN_LBAL)
- tf->lbal = tf_inb(io_ports->lbal_addr);
- if (task->tf_flags & IDE_TFLAG_IN_LBAM)
- tf->lbam = tf_inb(io_ports->lbam_addr);
- if (task->tf_flags & IDE_TFLAG_IN_LBAH)
- tf->lbah = tf_inb(io_ports->lbah_addr);
- if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
- tf->device = tf_inb(io_ports->device_addr);
-
- if (task->tf_flags & IDE_TFLAG_LBA48) {
- tf_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr);
-
- if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
- tf->hob_feature = tf_inb(io_ports->feature_addr);
- if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
- tf->hob_nsect = tf_inb(io_ports->nsect_addr);
- if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
- tf->hob_lbal = tf_inb(io_ports->lbal_addr);
- if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
- tf->hob_lbam = tf_inb(io_ports->lbam_addr);
- if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
- tf->hob_lbah = tf_inb(io_ports->lbah_addr);
- }
-}
-EXPORT_SYMBOL_GPL(ide_tf_read);
-
-/*
- * Some localbus EIDE interfaces require a special access sequence
- * when using 32-bit I/O instructions to transfer data. We call this
- * the "vlb_sync" sequence, which consists of three successive reads
- * of the sector count register location, with interrupts disabled
- * to ensure that the reads all happen together.
- */
-static void ata_vlb_sync(unsigned long port)
-{
- (void)inb(port);
- (void)inb(port);
- (void)inb(port);
-}
-
-/*
- * This is used for most PIO data transfers *from* the IDE interface
- *
- * These routines will round up any request for an odd number of bytes,
- * so if an odd len is specified, be sure that there's at least one
- * extra byte allocated for the buffer.
- */
-void ide_input_data(ide_drive_t *drive, struct request *rq, void *buf,
- unsigned int len)
-{
- ide_hwif_t *hwif = drive->hwif;
- struct ide_io_ports *io_ports = &hwif->io_ports;
- unsigned long data_addr = io_ports->data_addr;
- u8 io_32bit = drive->io_32bit;
- u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
-
- len++;
-
- if (io_32bit) {
- unsigned long uninitialized_var(flags);
-
- if ((io_32bit & 2) && !mmio) {
- local_irq_save(flags);
- ata_vlb_sync(io_ports->nsect_addr);
- }
-
- if (mmio)
- __ide_mm_insl((void __iomem *)data_addr, buf, len / 4);
- else
- insl(data_addr, buf, len / 4);
-
- if ((io_32bit & 2) && !mmio)
- local_irq_restore(flags);
-
- if ((len & 3) >= 2) {
- if (mmio)
- __ide_mm_insw((void __iomem *)data_addr,
- (u8 *)buf + (len & ~3), 1);
- else
- insw(data_addr, (u8 *)buf + (len & ~3), 1);
- }
- } else {
- if (mmio)
- __ide_mm_insw((void __iomem *)data_addr, buf, len / 2);
- else
- insw(data_addr, buf, len / 2);
- }
-}
-EXPORT_SYMBOL_GPL(ide_input_data);
-
-/*
- * This is used for most PIO data transfers *to* the IDE interface
- */
-void ide_output_data(ide_drive_t *drive, struct request *rq, void *buf,
- unsigned int len)
-{
- ide_hwif_t *hwif = drive->hwif;
- struct ide_io_ports *io_ports = &hwif->io_ports;
- unsigned long data_addr = io_ports->data_addr;
- u8 io_32bit = drive->io_32bit;
- u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
-
- len++;
-
- if (io_32bit) {
- unsigned long uninitialized_var(flags);
-
- if ((io_32bit & 2) && !mmio) {
- local_irq_save(flags);
- ata_vlb_sync(io_ports->nsect_addr);
- }
-
- if (mmio)
- __ide_mm_outsl((void __iomem *)data_addr, buf, len / 4);
- else
- outsl(data_addr, buf, len / 4);
-
- if ((io_32bit & 2) && !mmio)
- local_irq_restore(flags);
-
- if ((len & 3) >= 2) {
- if (mmio)
- __ide_mm_outsw((void __iomem *)data_addr,
- (u8 *)buf + (len & ~3), 1);
- else
- outsw(data_addr, (u8 *)buf + (len & ~3), 1);
- }
- } else {
- if (mmio)
- __ide_mm_outsw((void __iomem *)data_addr, buf, len / 2);
- else
- outsw(data_addr, buf, len / 2);
- }
-}
-EXPORT_SYMBOL_GPL(ide_output_data);
-
u8 ide_read_error(ide_drive_t *drive)
{
ide_task_t task;
@@ -362,35 +63,6 @@ u8 ide_read_error(ide_drive_t *drive)
}
EXPORT_SYMBOL_GPL(ide_read_error);
-void ide_read_bcount_and_ireason(ide_drive_t *drive, u16 *bcount, u8 *ireason)
-{
- ide_task_t task;
-
- memset(&task, 0, sizeof(task));
- task.tf_flags = IDE_TFLAG_IN_LBAH | IDE_TFLAG_IN_LBAM |
- IDE_TFLAG_IN_NSECT;
-
- drive->hwif->tp_ops->tf_read(drive, &task);
-
- *bcount = (task.tf.lbah << 8) | task.tf.lbam;
- *ireason = task.tf.nsect & 3;
-}
-EXPORT_SYMBOL_GPL(ide_read_bcount_and_ireason);
-
-const struct ide_tp_ops default_tp_ops = {
- .exec_command = ide_exec_command,
- .read_status = ide_read_status,
- .read_altstatus = ide_read_altstatus,
-
- .set_irq = ide_set_irq,
-
- .tf_load = ide_tf_load,
- .tf_read = ide_tf_read,
-
- .input_data = ide_input_data,
- .output_data = ide_output_data,
-};
-
void ide_fix_driveid(u16 *id)
{
#ifndef __LITTLE_ENDIAN
@@ -412,7 +84,7 @@ void ide_fix_driveid(u16 *id)
* returned by the ATA_CMD_ID_ATA[PI] commands.
*/
-void ide_fixstring (u8 *s, const int bytecount, const int byteswap)
+void ide_fixstring(u8 *s, const int bytecount, const int byteswap)
{
u8 *p, *end = &s[bytecount & ~1]; /* bytecount must be even */
@@ -435,44 +107,9 @@ void ide_fixstring (u8 *s, const int bytecount, const int byteswap)
while (p != end)
*p++ = '\0';
}
-
EXPORT_SYMBOL(ide_fixstring);
/*
- * Needed for PCI irq sharing
- */
-int drive_is_ready (ide_drive_t *drive)
-{
- ide_hwif_t *hwif = drive->hwif;
- u8 stat = 0;
-
- if (drive->waiting_for_dma)
- return hwif->dma_ops->dma_test_irq(drive);
-
- /*
- * We do a passive status test under shared PCI interrupts on
- * cards that truly share the ATA side interrupt, but may also share
- * an interrupt with another pci card/device. We make no assumptions
- * about possible isa-pnp and pci-pnp issues yet.
- */
- if (hwif->io_ports.ctl_addr &&
- (hwif->host_flags & IDE_HFLAG_BROKEN_ALTSTATUS) == 0)
- stat = hwif->tp_ops->read_altstatus(hwif);
- else
- /* Note: this may clear a pending IRQ!! */
- stat = hwif->tp_ops->read_status(hwif);
-
- if (stat & ATA_BUSY)
- /* drive busy: definitely not interrupting */
- return 0;
-
- /* drive ready: *might* be interrupting */
- return 1;
-}
-
-EXPORT_SYMBOL(drive_is_ready);
-
-/*
* This routine busy-waits for the drive status to be not "busy".
* It then checks the status for all of the "good" bits and none
* of the "bad" bits, and if all is okay it returns 0. All other
@@ -483,7 +120,8 @@ EXPORT_SYMBOL(drive_is_ready);
* setting a timer to wake up at half second intervals thereafter,
* until timeout is achieved, before timing out.
*/
-static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long timeout, u8 *rstat)
+static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad,
+ unsigned long timeout, u8 *rstat)
{
ide_hwif_t *hwif = drive->hwif;
const struct ide_tp_ops *tp_ops = hwif->tp_ops;
@@ -541,7 +179,8 @@ static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long ti
* The caller should return the updated value of "startstop" in this case,
* "startstop" is unchanged when the function returns 0.
*/
-int ide_wait_stat(ide_startstop_t *startstop, ide_drive_t *drive, u8 good, u8 bad, unsigned long timeout)
+int ide_wait_stat(ide_startstop_t *startstop, ide_drive_t *drive, u8 good,
+ u8 bad, unsigned long timeout)
{
int err;
u8 stat;
@@ -561,7 +200,6 @@ int ide_wait_stat(ide_startstop_t *startstop, ide_drive_t *drive, u8 good, u8 ba
return err;
}
-
EXPORT_SYMBOL(ide_wait_stat);
/**
@@ -582,7 +220,6 @@ int ide_in_drive_list(u16 *id, const struct drive_list_entry *table)
return 1;
return 0;
}
-
EXPORT_SYMBOL_GPL(ide_in_drive_list);
/*
@@ -607,7 +244,7 @@ static const struct drive_list_entry ivb_list[] = {
* All hosts that use the 80c ribbon must use!
* The name is derived from upper byte of word 93 and the 80c ribbon.
*/
-u8 eighty_ninty_three (ide_drive_t *drive)
+u8 eighty_ninty_three(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
u16 *id = drive->id;
@@ -652,47 +289,19 @@ no_80w:
int ide_driveid_update(ide_drive_t *drive)
{
- ide_hwif_t *hwif = drive->hwif;
- const struct ide_tp_ops *tp_ops = hwif->tp_ops;
u16 *id;
- unsigned long flags;
- u8 stat;
-
- /*
- * Re-read drive->id for possible DMA mode
- * change (copied from ide-probe.c)
- */
-
- SELECT_MASK(drive, 1);
- tp_ops->set_irq(hwif, 0);
- msleep(50);
- tp_ops->exec_command(hwif, ATA_CMD_ID_ATA);
+ int rc;
- if (ide_busy_sleep(hwif, WAIT_WORSTCASE, 1)) {
- SELECT_MASK(drive, 0);
+ id = kmalloc(SECTOR_SIZE, GFP_ATOMIC);
+ if (id == NULL)
return 0;
- }
-
- msleep(50); /* wait for IRQ and ATA_DRQ */
- stat = tp_ops->read_status(hwif);
- if (!OK_STAT(stat, ATA_DRQ, BAD_R_STAT)) {
- SELECT_MASK(drive, 0);
- printk("%s: CHECK for good STATUS\n", drive->name);
- return 0;
- }
- local_irq_save(flags);
+ SELECT_MASK(drive, 1);
+ rc = ide_dev_read_id(drive, ATA_CMD_ID_ATA, id);
SELECT_MASK(drive, 0);
- id = kmalloc(SECTOR_SIZE, GFP_ATOMIC);
- if (!id) {
- local_irq_restore(flags);
- return 0;
- }
- tp_ops->input_data(drive, NULL, id, SECTOR_SIZE);
- (void)tp_ops->read_status(hwif); /* clear drive IRQ */
- local_irq_enable();
- local_irq_restore(flags);
- ide_fix_driveid(id);
+
+ if (rc)
+ goto out_err;
drive->id[ATA_ID_UDMA_MODES] = id[ATA_ID_UDMA_MODES];
drive->id[ATA_ID_MWDMA_MODES] = id[ATA_ID_MWDMA_MODES];
@@ -705,6 +314,12 @@ int ide_driveid_update(ide_drive_t *drive)
ide_dma_off(drive);
return 1;
+out_err:
+ SELECT_MASK(drive, 0);
+ if (rc == 2)
+ printk(KERN_ERR "%s: %s: bad status\n", drive->name, __func__);
+ kfree(id);
+ return 0;
}
int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
@@ -731,18 +346,15 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
* but for some reason these don't work at
* this point (lost interrupt).
*/
- /*
- * Select the drive, and issue the SETFEATURES command
- */
- disable_irq_nosync(hwif->irq);
-
+
/*
* FIXME: we race against the running IRQ here if
* this is called from non IRQ context. If we use
* disable_irq() we hang on the error path. Work
* is needed.
*/
-
+ disable_irq_nosync(hwif->irq);
+
udelay(1);
SELECT_DRIVE(drive);
SELECT_MASK(drive, 1);
@@ -812,8 +424,8 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
*
* See also ide_execute_command
*/
-static void __ide_set_handler (ide_drive_t *drive, ide_handler_t *handler,
- unsigned int timeout, ide_expiry_t *expiry)
+void __ide_set_handler(ide_drive_t *drive, ide_handler_t *handler,
+ unsigned int timeout, ide_expiry_t *expiry)
{
ide_hwif_t *hwif = drive->hwif;
@@ -835,9 +447,8 @@ void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler,
__ide_set_handler(drive, handler, timeout, expiry);
spin_unlock_irqrestore(&hwif->lock, flags);
}
-
EXPORT_SYMBOL(ide_set_handler);
-
+
/**
* ide_execute_command - execute an IDE command
* @drive: IDE drive to issue the command against
@@ -847,7 +458,7 @@ EXPORT_SYMBOL(ide_set_handler);
* @expiry: handler to run on timeout
*
* Helper function to issue an IDE command. This handles the
- * atomicity requirements, command timing and ensures that the
+ * atomicity requirements, command timing and ensures that the
* handler and IRQ setup do not race. All IDE command kick off
* should go via this function or do equivalent locking.
*/
@@ -884,301 +495,6 @@ void ide_execute_pkt_cmd(ide_drive_t *drive)
}
EXPORT_SYMBOL_GPL(ide_execute_pkt_cmd);
-static inline void ide_complete_drive_reset(ide_drive_t *drive, int err)
-{
- struct request *rq = drive->hwif->rq;
-
- if (rq && blk_special_request(rq) && rq->cmd[0] == REQ_DRIVE_RESET)
- ide_end_request(drive, err ? err : 1, 0);
-}
-
-/* needed below */
-static ide_startstop_t do_reset1 (ide_drive_t *, int);
-
-/*
- * atapi_reset_pollfunc() gets invoked to poll the interface for completion every 50ms
- * during an atapi drive reset operation. If the drive has not yet responded,
- * and we have not yet hit our maximum waiting time, then the timer is restarted
- * for another 50ms.
- */
-static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive)
-{
- ide_hwif_t *hwif = drive->hwif;
- u8 stat;
-
- SELECT_DRIVE(drive);
- udelay (10);
- stat = hwif->tp_ops->read_status(hwif);
-
- if (OK_STAT(stat, 0, ATA_BUSY))
- printk("%s: ATAPI reset complete\n", drive->name);
- else {
- if (time_before(jiffies, hwif->poll_timeout)) {
- ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL);
- /* continue polling */
- return ide_started;
- }
- /* end of polling */
- hwif->polling = 0;
- printk("%s: ATAPI reset timed-out, status=0x%02x\n",
- drive->name, stat);
- /* do it the old fashioned way */
- return do_reset1(drive, 1);
- }
- /* done polling */
- hwif->polling = 0;
- ide_complete_drive_reset(drive, 0);
- return ide_stopped;
-}
-
-static void ide_reset_report_error(ide_hwif_t *hwif, u8 err)
-{
- static const char *err_master_vals[] =
- { NULL, "passed", "formatter device error",
- "sector buffer error", "ECC circuitry error",
- "controlling MPU error" };
-
- u8 err_master = err & 0x7f;
-
- printk(KERN_ERR "%s: reset: master: ", hwif->name);
- if (err_master && err_master < 6)
- printk(KERN_CONT "%s", err_master_vals[err_master]);
- else
- printk(KERN_CONT "error (0x%02x?)", err);
- if (err & 0x80)
- printk(KERN_CONT "; slave: failed");
- printk(KERN_CONT "\n");
-}
-
-/*
- * reset_pollfunc() gets invoked to poll the interface for completion every 50ms
- * during an ide reset operation. If the drives have not yet responded,
- * and we have not yet hit our maximum waiting time, then the timer is restarted
- * for another 50ms.
- */
-static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
-{
- ide_hwif_t *hwif = drive->hwif;
- const struct ide_port_ops *port_ops = hwif->port_ops;
- u8 tmp;
- int err = 0;
-
- if (port_ops && port_ops->reset_poll) {
- err = port_ops->reset_poll(drive);
- if (err) {
- printk(KERN_ERR "%s: host reset_poll failure for %s.\n",
- hwif->name, drive->name);
- goto out;
- }
- }
-
- tmp = hwif->tp_ops->read_status(hwif);
-
- if (!OK_STAT(tmp, 0, ATA_BUSY)) {
- if (time_before(jiffies, hwif->poll_timeout)) {
- ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL);
- /* continue polling */
- return ide_started;
- }
- printk("%s: reset timed-out, status=0x%02x\n", hwif->name, tmp);
- drive->failures++;
- err = -EIO;
- } else {
- tmp = ide_read_error(drive);
-
- if (tmp == 1) {
- printk(KERN_INFO "%s: reset: success\n", hwif->name);
- drive->failures = 0;
- } else {
- ide_reset_report_error(hwif, tmp);
- drive->failures++;
- err = -EIO;
- }
- }
-out:
- hwif->polling = 0; /* done polling */
- ide_complete_drive_reset(drive, err);
- return ide_stopped;
-}
-
-static void ide_disk_pre_reset(ide_drive_t *drive)
-{
- int legacy = (drive->id[ATA_ID_CFS_ENABLE_2] & 0x0400) ? 0 : 1;
-
- drive->special.all = 0;
- drive->special.b.set_geometry = legacy;
- drive->special.b.recalibrate = legacy;
-
- drive->mult_count = 0;
- drive->dev_flags &= ~IDE_DFLAG_PARKED;
-
- if ((drive->dev_flags & IDE_DFLAG_KEEP_SETTINGS) == 0 &&
- (drive->dev_flags & IDE_DFLAG_USING_DMA) == 0)
- drive->mult_req = 0;
-
- if (drive->mult_req != drive->mult_count)
- drive->special.b.set_multmode = 1;
-}
-
-static void pre_reset(ide_drive_t *drive)
-{
- const struct ide_port_ops *port_ops = drive->hwif->port_ops;
-
- if (drive->media == ide_disk)
- ide_disk_pre_reset(drive);
- else
- drive->dev_flags |= IDE_DFLAG_POST_RESET;
-
- if (drive->dev_flags & IDE_DFLAG_USING_DMA) {
- if (drive->crc_count)
- ide_check_dma_crc(drive);
- else
- ide_dma_off(drive);
- }
-
- if ((drive->dev_flags & IDE_DFLAG_KEEP_SETTINGS) == 0) {
- if ((drive->dev_flags & IDE_DFLAG_USING_DMA) == 0) {
- drive->dev_flags &= ~IDE_DFLAG_UNMASK;
- drive->io_32bit = 0;
- }
- return;
- }
-
- if (port_ops && port_ops->pre_reset)
- port_ops->pre_reset(drive);
-
- if (drive->current_speed != 0xff)
- drive->desired_speed = drive->current_speed;
- drive->current_speed = 0xff;
-}
-
-/*
- * do_reset1() attempts to recover a confused drive by resetting it.
- * Unfortunately, resetting a disk drive actually resets all devices on
- * the same interface, so it can really be thought of as resetting the
- * interface rather than resetting the drive.
- *
- * ATAPI devices have their own reset mechanism which allows them to be
- * individually reset without clobbering other devices on the same interface.
- *
- * Unfortunately, the IDE interface does not generate an interrupt to let
- * us know when the reset operation has finished, so we must poll for this.
- * Equally poor, though, is the fact that this may a very long time to complete,
- * (up to 30 seconds worstcase). So, instead of busy-waiting here for it,
- * we set a timer to poll at 50ms intervals.
- */
-static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
-{
- ide_hwif_t *hwif = drive->hwif;
- struct ide_io_ports *io_ports = &hwif->io_ports;
- const struct ide_tp_ops *tp_ops = hwif->tp_ops;
- const struct ide_port_ops *port_ops;
- ide_drive_t *tdrive;
- unsigned long flags, timeout;
- int i;
- DEFINE_WAIT(wait);
-
- spin_lock_irqsave(&hwif->lock, flags);
-
- /* We must not reset with running handlers */
- BUG_ON(hwif->handler != NULL);
-
- /* For an ATAPI device, first try an ATAPI SRST. */
- if (drive->media != ide_disk && !do_not_try_atapi) {
- pre_reset(drive);
- SELECT_DRIVE(drive);
- udelay (20);
- tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET);
- ndelay(400);
- hwif->poll_timeout = jiffies + WAIT_WORSTCASE;
- hwif->polling = 1;
- __ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL);
- spin_unlock_irqrestore(&hwif->lock, flags);
- return ide_started;
- }
-
- /* We must not disturb devices in the IDE_DFLAG_PARKED state. */
- do {
- unsigned long now;
-
- prepare_to_wait(&ide_park_wq, &wait, TASK_UNINTERRUPTIBLE);
- timeout = jiffies;
- ide_port_for_each_dev(i, tdrive, hwif) {
- if (tdrive->dev_flags & IDE_DFLAG_PRESENT &&
- tdrive->dev_flags & IDE_DFLAG_PARKED &&
- time_after(tdrive->sleep, timeout))
- timeout = tdrive->sleep;
- }
-
- now = jiffies;
- if (time_before_eq(timeout, now))
- break;
-
- spin_unlock_irqrestore(&hwif->lock, flags);
- timeout = schedule_timeout_uninterruptible(timeout - now);
- spin_lock_irqsave(&hwif->lock, flags);
- } while (timeout);
- finish_wait(&ide_park_wq, &wait);
-
- /*
- * First, reset any device state data we were maintaining
- * for any of the drives on this interface.
- */
- ide_port_for_each_dev(i, tdrive, hwif)
- pre_reset(tdrive);
-
- if (io_ports->ctl_addr == 0) {
- spin_unlock_irqrestore(&hwif->lock, flags);
- ide_complete_drive_reset(drive, -ENXIO);
- return ide_stopped;
- }
-
- /*
- * Note that we also set nIEN while resetting the device,
- * to mask unwanted interrupts from the interface during the reset.
- * However, due to the design of PC hardware, this will cause an
- * immediate interrupt due to the edge transition it produces.
- * This single interrupt gives us a "fast poll" for drives that
- * recover from reset very quickly, saving us the first 50ms wait time.
- *
- * TODO: add ->softreset method and stop abusing ->set_irq
- */
- /* set SRST and nIEN */
- tp_ops->set_irq(hwif, 4);
- /* more than enough time */
- udelay(10);
- /* clear SRST, leave nIEN (unless device is on the quirk list) */
- tp_ops->set_irq(hwif, drive->quirk_list == 2);
- /* more than enough time */
- udelay(10);
- hwif->poll_timeout = jiffies + WAIT_WORSTCASE;
- hwif->polling = 1;
- __ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL);
-
- /*
- * Some weird controller like resetting themselves to a strange
- * state when the disks are reset this way. At least, the Winbond
- * 553 documentation says that
- */
- port_ops = hwif->port_ops;
- if (port_ops && port_ops->resetproc)
- port_ops->resetproc(drive);
-
- spin_unlock_irqrestore(&hwif->lock, flags);
- return ide_started;
-}
-
-/*
- * ide_do_reset() is the entry point to the drive/interface reset code.
- */
-
-ide_startstop_t ide_do_reset (ide_drive_t *drive)
-{
- return do_reset1(drive, 0);
-}
-
-EXPORT_SYMBOL(ide_do_reset);
-
/*
* ide_wait_not_busy() waits for the currently selected device on the hwif
* to report a non-busy status, see comments in ide_probe_port().
@@ -1187,7 +503,7 @@ int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout)
{
u8 stat = 0;
- while(timeout--) {
+ while (timeout--) {
/*
* Turn this into a schedule() sleep once I'm sure
* about locking issues (2.5 work ?).
diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c
index 09526a0..f6c683d 100644
--- a/drivers/ide/ide-lib.c
+++ b/drivers/ide/ide-lib.c
@@ -5,163 +5,6 @@
#include <linux/ide.h>
#include <linux/bitops.h>
-static const char *udma_str[] =
- { "UDMA/16", "UDMA/25", "UDMA/33", "UDMA/44",
- "UDMA/66", "UDMA/100", "UDMA/133", "UDMA7" };
-static const char *mwdma_str[] =
- { "MWDMA0", "MWDMA1", "MWDMA2" };
-static const char *swdma_str[] =
- { "SWDMA0", "SWDMA1", "SWDMA2" };
-static const char *pio_str[] =
- { "PIO0", "PIO1", "PIO2", "PIO3", "PIO4", "PIO5" };
-
-/**
- * ide_xfer_verbose - return IDE mode names
- * @mode: transfer mode
- *
- * Returns a constant string giving the name of the mode
- * requested.
- */
-
-const char *ide_xfer_verbose(u8 mode)
-{
- const char *s;
- u8 i = mode & 0xf;
-
- if (mode >= XFER_UDMA_0 && mode <= XFER_UDMA_7)
- s = udma_str[i];
- else if (mode >= XFER_MW_DMA_0 && mode <= XFER_MW_DMA_2)
- s = mwdma_str[i];
- else if (mode >= XFER_SW_DMA_0 && mode <= XFER_SW_DMA_2)
- s = swdma_str[i];
- else if (mode >= XFER_PIO_0 && mode <= XFER_PIO_5)
- s = pio_str[i & 0x7];
- else if (mode == XFER_PIO_SLOW)
- s = "PIO SLOW";
- else
- s = "XFER ERROR";
-
- return s;
-}
-EXPORT_SYMBOL(ide_xfer_verbose);
-
-/**
- * ide_rate_filter - filter transfer mode
- * @drive: IDE device
- * @speed: desired speed
- *
- * Given the available transfer modes this function returns
- * the best available speed at or below the speed requested.
- *
- * TODO: check device PIO capabilities
- */
-
-static u8 ide_rate_filter(ide_drive_t *drive, u8 speed)
-{
- ide_hwif_t *hwif = drive->hwif;
- u8 mode = ide_find_dma_mode(drive, speed);
-
- if (mode == 0) {
- if (hwif->pio_mask)
- mode = fls(hwif->pio_mask) - 1 + XFER_PIO_0;
- else
- mode = XFER_PIO_4;
- }
-
-/* printk("%s: mode 0x%02x, speed 0x%02x\n", __func__, mode, speed); */
-
- return min(speed, mode);
-}
-
-/**
- * ide_get_best_pio_mode - get PIO mode from drive
- * @drive: drive to consider
- * @mode_wanted: preferred mode
- * @max_mode: highest allowed mode
- *
- * This routine returns the recommended PIO settings for a given drive,
- * based on the drive->id information and the ide_pio_blacklist[].
- *
- * Drive PIO mode is auto-selected if 255 is passed as mode_wanted.
- * This is used by most chipset support modules when "auto-tuning".
- */
-
-u8 ide_get_best_pio_mode(ide_drive_t *drive, u8 mode_wanted, u8 max_mode)
-{
- u16 *id = drive->id;
- int pio_mode = -1, overridden = 0;
-
- if (mode_wanted != 255)
- return min_t(u8, mode_wanted, max_mode);
-
- if ((drive->hwif->host_flags & IDE_HFLAG_PIO_NO_BLACKLIST) == 0)
- pio_mode = ide_scan_pio_blacklist((char *)&id[ATA_ID_PROD]);
-
- if (pio_mode != -1) {
- printk(KERN_INFO "%s: is on PIO blacklist\n", drive->name);
- } else {
- pio_mode = id[ATA_ID_OLD_PIO_MODES] >> 8;
- if (pio_mode > 2) { /* 2 is maximum allowed tPIO value */
- pio_mode = 2;
- overridden = 1;
- }
-
- if (id[ATA_ID_FIELD_VALID] & 2) { /* ATA2? */
- if (ata_id_has_iordy(id)) {
- if (id[ATA_ID_PIO_MODES] & 7) {
- overridden = 0;
- if (id[ATA_ID_PIO_MODES] & 4)
- pio_mode = 5;
- else if (id[ATA_ID_PIO_MODES] & 2)
- pio_mode = 4;
- else
- pio_mode = 3;
- }
- }
- }
-
- if (overridden)
- printk(KERN_INFO "%s: tPIO > 2, assuming tPIO = 2\n",
- drive->name);
- }
-
- if (pio_mode > max_mode)
- pio_mode = max_mode;
-
- return pio_mode;
-}
-EXPORT_SYMBOL_GPL(ide_get_best_pio_mode);
-
-/* req_pio == "255" for auto-tune */
-void ide_set_pio(ide_drive_t *drive, u8 req_pio)
-{
- ide_hwif_t *hwif = drive->hwif;
- const struct ide_port_ops *port_ops = hwif->port_ops;
- u8 host_pio, pio;
-
- if (port_ops == NULL || port_ops->set_pio_mode == NULL ||
- (hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
- return;
-
- BUG_ON(hwif->pio_mask == 0x00);
-
- host_pio = fls(hwif->pio_mask) - 1;
-
- pio = ide_get_best_pio_mode(drive, req_pio, host_pio);
-
- /*
- * TODO:
- * - report device max PIO mode
- * - check req_pio != 255 against device max PIO mode
- */
- printk(KERN_DEBUG "%s: host max PIO%d wanted PIO%d%s selected PIO%d\n",
- drive->name, host_pio, req_pio,
- req_pio == 255 ? "(auto-tune)" : "", pio);
-
- (void)ide_set_pio_mode(drive, XFER_PIO_0 + pio);
-}
-EXPORT_SYMBOL_GPL(ide_set_pio);
-
/**
* ide_toggle_bounce - handle bounce buffering
* @drive: drive to update
@@ -188,89 +31,6 @@ void ide_toggle_bounce(ide_drive_t *drive, int on)
blk_queue_bounce_limit(drive->queue, addr);
}
-int ide_set_pio_mode(ide_drive_t *drive, const u8 mode)
-{
- ide_hwif_t *hwif = drive->hwif;
- const struct ide_port_ops *port_ops = hwif->port_ops;
-
- if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)
- return 0;
-
- if (port_ops == NULL || port_ops->set_pio_mode == NULL)
- return -1;
-
- /*
- * TODO: temporary hack for some legacy host drivers that didn't
- * set transfer mode on the device in ->set_pio_mode method...
- */
- if (port_ops->set_dma_mode == NULL) {
- port_ops->set_pio_mode(drive, mode - XFER_PIO_0);
- return 0;
- }
-
- if (hwif->host_flags & IDE_HFLAG_POST_SET_MODE) {
- if (ide_config_drive_speed(drive, mode))
- return -1;
- port_ops->set_pio_mode(drive, mode - XFER_PIO_0);
- return 0;
- } else {
- port_ops->set_pio_mode(drive, mode - XFER_PIO_0);
- return ide_config_drive_speed(drive, mode);
- }
-}
-
-int ide_set_dma_mode(ide_drive_t *drive, const u8 mode)
-{
- ide_hwif_t *hwif = drive->hwif;
- const struct ide_port_ops *port_ops = hwif->port_ops;
-
- if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)
- return 0;
-
- if (port_ops == NULL || port_ops->set_dma_mode == NULL)
- return -1;
-
- if (hwif->host_flags & IDE_HFLAG_POST_SET_MODE) {
- if (ide_config_drive_speed(drive, mode))
- return -1;
- port_ops->set_dma_mode(drive, mode);
- return 0;
- } else {
- port_ops->set_dma_mode(drive, mode);
- return ide_config_drive_speed(drive, mode);
- }
-}
-EXPORT_SYMBOL_GPL(ide_set_dma_mode);
-
-/**
- * ide_set_xfer_rate - set transfer rate
- * @drive: drive to set
- * @rate: speed to attempt to set
- *
- * General helper for setting the speed of an IDE device. This
- * function knows about user enforced limits from the configuration
- * which ->set_pio_mode/->set_dma_mode does not.
- */
-
-int ide_set_xfer_rate(ide_drive_t *drive, u8 rate)
-{
- ide_hwif_t *hwif = drive->hwif;
- const struct ide_port_ops *port_ops = hwif->port_ops;
-
- if (port_ops == NULL || port_ops->set_dma_mode == NULL ||
- (hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
- return -1;
-
- rate = ide_rate_filter(drive, rate);
-
- BUG_ON(rate < XFER_PIO_0);
-
- if (rate >= XFER_PIO_0 && rate <= XFER_PIO_5)
- return ide_set_pio_mode(drive, rate);
-
- return ide_set_dma_mode(drive, rate);
-}
-
static void ide_dump_opcode(ide_drive_t *drive)
{
struct request *rq = drive->hwif->rq;
diff --git a/drivers/ide/ide-park.c b/drivers/ide/ide-park.c
index c875a95..f30e521 100644
--- a/drivers/ide/ide-park.c
+++ b/drivers/ide/ide-park.c
@@ -1,5 +1,6 @@
#include <linux/kernel.h>
#include <linux/ide.h>
+#include <linux/hdreg.h>
#include <linux/jiffies.h>
#include <linux/blkdev.h>
@@ -60,6 +61,30 @@ out:
return;
}
+ide_startstop_t ide_do_park_unpark(ide_drive_t *drive, struct request *rq)
+{
+ ide_task_t task;
+ struct ide_taskfile *tf = &task.tf;
+
+ memset(&task, 0, sizeof(task));
+ if (rq->cmd[0] == REQ_PARK_HEADS) {
+ drive->sleep = *(unsigned long *)rq->special;
+ drive->dev_flags |= IDE_DFLAG_SLEEPING;
+ tf->command = ATA_CMD_IDLEIMMEDIATE;
+ tf->feature = 0x44;
+ tf->lbal = 0x4c;
+ tf->lbam = 0x4e;
+ tf->lbah = 0x55;
+ task.tf_flags |= IDE_TFLAG_CUSTOM_HANDLER;
+ } else /* cmd == REQ_UNPARK_HEADS */
+ tf->command = ATA_CMD_CHK_POWER;
+
+ task.tf_flags |= IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+ task.rq = rq;
+ drive->hwif->data_phase = task.data_phase = TASKFILE_NO_DATA;
+ return do_rw_taskfile(drive, &task);
+}
+
ssize_t ide_park_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
diff --git a/drivers/ide/ide-pci-generic.c b/drivers/ide/ide-pci-generic.c
index bddae2b..61111fd 100644
--- a/drivers/ide/ide-pci-generic.c
+++ b/drivers/ide/ide-pci-generic.c
@@ -33,8 +33,6 @@ static int ide_generic_all; /* Set to claim all devices */
module_param_named(all_generic_ide, ide_generic_all, bool, 0444);
MODULE_PARM_DESC(all_generic_ide, "IDE generic will claim all unknown PCI IDE storage controllers.");
-#define IDE_HFLAGS_UMC (IDE_HFLAG_NO_DMA | IDE_HFLAG_FORCE_LEGACY_IRQS)
-
#define DECLARE_GENERIC_PCI_DEV(extra_flags) \
{ \
.name = DRV_NAME, \
@@ -61,7 +59,7 @@ static const struct ide_port_info generic_chipsets[] __devinitdata = {
/* 2: SAMURAI / HT6565 / HINT_IDE */
DECLARE_GENERIC_PCI_DEV(0),
/* 3: UM8673F / UM8886A / UM8886BF */
- DECLARE_GENERIC_PCI_DEV(IDE_HFLAGS_UMC),
+ DECLARE_GENERIC_PCI_DEV(IDE_HFLAG_NO_DMA),
/* 4: VIA_IDE / OPTI621V / Piccolo010{2,3,5} */
DECLARE_GENERIC_PCI_DEV(IDE_HFLAG_NO_AUTODMA),
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 97ea532..9740670 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -181,16 +181,16 @@ static void ide_classify_atapi_dev(ide_drive_t *drive)
* do_identify - identify a drive
* @drive: drive to identify
* @cmd: command used
+ * @id: buffer for IDENTIFY data
*
* Called when we have issued a drive identify command to
* read and parse the results. This function is run with
* interrupts disabled.
*/
-static void do_identify(ide_drive_t *drive, u8 cmd)
+static void do_identify(ide_drive_t *drive, u8 cmd, u16 *id)
{
ide_hwif_t *hwif = drive->hwif;
- u16 *id = drive->id;
char *m = (char *)&id[ATA_ID_PROD];
unsigned long flags;
int bswap = 1;
@@ -233,16 +233,6 @@ static void do_identify(ide_drive_t *drive, u8 cmd)
drive->dev_flags |= IDE_DFLAG_PRESENT;
drive->dev_flags &= ~IDE_DFLAG_DEAD;
- /*
- * Check for an ATAPI device
- */
- if (cmd == ATA_CMD_ID_ATAPI)
- ide_classify_atapi_dev(drive);
- else
- /*
- * Not an ATAPI device: looks like a "regular" hard disk
- */
- ide_classify_ata_dev(drive);
return;
err_misc:
kfree(id);
@@ -250,21 +240,19 @@ err_misc:
}
/**
- * actual_try_to_identify - send ata/atapi identify
+ * ide_dev_read_id - send ATA/ATAPI IDENTIFY command
* @drive: drive to identify
* @cmd: command to use
+ * @id: buffer for IDENTIFY data
*
- * try_to_identify() sends an ATA(PI) IDENTIFY request to a drive
- * and waits for a response. It also monitors irqs while this is
- * happening, in hope of automatically determining which one is
- * being used by the interface.
+ * Sends an ATA(PI) IDENTIFY request to a drive and waits for a response.
*
* Returns: 0 device was identified
* 1 device timed-out (no response to identify request)
* 2 device aborted the command (refused to identify itself)
*/
-static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
+int ide_dev_read_id(ide_drive_t *drive, u8 cmd, u16 *id)
{
ide_hwif_t *hwif = drive->hwif;
struct ide_io_ports *io_ports = &hwif->io_ports;
@@ -273,6 +261,13 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
unsigned long timeout;
u8 s = 0, a = 0;
+ /*
+ * Disable device IRQ. Otherwise we'll get spurious interrupts
+ * during the identify phase that the IRQ handler isn't expecting.
+ */
+ if (io_ports->ctl_addr)
+ tp_ops->set_irq(hwif, 0);
+
/* take a deep breath */
msleep(50);
@@ -317,7 +312,7 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
if (OK_STAT(s, ATA_DRQ, BAD_R_STAT)) {
/* drive returned ID */
- do_identify(drive, cmd);
+ do_identify(drive, cmd, id);
/* drive responded with ID */
rc = 0;
/* clear drive IRQ */
@@ -329,63 +324,6 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
return rc;
}
-/**
- * try_to_identify - try to identify a drive
- * @drive: drive to probe
- * @cmd: command to use
- *
- * Issue the identify command and then do IRQ probing to
- * complete the identification when needed by finding the
- * IRQ the drive is attached to
- */
-
-static int try_to_identify (ide_drive_t *drive, u8 cmd)
-{
- ide_hwif_t *hwif = drive->hwif;
- const struct ide_tp_ops *tp_ops = hwif->tp_ops;
- int retval;
- int autoprobe = 0;
- unsigned long cookie = 0;
-
- /*
- * Disable device irq unless we need to
- * probe for it. Otherwise we'll get spurious
- * interrupts during the identify-phase that
- * the irq handler isn't expecting.
- */
- if (hwif->io_ports.ctl_addr) {
- if (!hwif->irq) {
- autoprobe = 1;
- cookie = probe_irq_on();
- }
- tp_ops->set_irq(hwif, autoprobe);
- }
-
- retval = actual_try_to_identify(drive, cmd);
-
- if (autoprobe) {
- int irq;
-
- tp_ops->set_irq(hwif, 0);
- /* clear drive IRQ */
- (void)tp_ops->read_status(hwif);
- udelay(5);
- irq = probe_irq_off(cookie);
- if (!hwif->irq) {
- if (irq > 0) {
- hwif->irq = irq;
- } else {
- /* Mmmm.. multiple IRQs..
- * don't know which was ours
- */
- printk(KERN_ERR "%s: IRQ probe failed (0x%lx)\n",
- drive->name, cookie);
- }
- }
- }
- return retval;
-}
-
int ide_busy_sleep(ide_hwif_t *hwif, unsigned long timeout, int altstatus)
{
u8 stat;
@@ -440,6 +378,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
{
ide_hwif_t *hwif = drive->hwif;
const struct ide_tp_ops *tp_ops = hwif->tp_ops;
+ u16 *id = drive->id;
int rc;
u8 present = !!(drive->dev_flags & IDE_DFLAG_PRESENT), stat;
@@ -475,11 +414,10 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
if (OK_STAT(stat, ATA_DRDY, ATA_BUSY) ||
present || cmd == ATA_CMD_ID_ATAPI) {
- /* send cmd and wait */
- if ((rc = try_to_identify(drive, cmd))) {
+ rc = ide_dev_read_id(drive, cmd, id);
+ if (rc)
/* failed: try again */
- rc = try_to_identify(drive,cmd);
- }
+ rc = ide_dev_read_id(drive, cmd, id);
stat = tp_ops->read_status(hwif);
@@ -494,7 +432,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
msleep(50);
tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET);
(void)ide_busy_sleep(hwif, WAIT_WORSTCASE, 0);
- rc = try_to_identify(drive, cmd);
+ rc = ide_dev_read_id(drive, cmd, id);
}
/* ensure drive IRQ is clear */
@@ -517,37 +455,6 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
return rc;
}
-/*
- *
- */
-static void enable_nest (ide_drive_t *drive)
-{
- ide_hwif_t *hwif = drive->hwif;
- const struct ide_tp_ops *tp_ops = hwif->tp_ops;
- u8 stat;
-
- printk(KERN_INFO "%s: enabling %s -- ",
- hwif->name, (char *)&drive->id[ATA_ID_PROD]);
-
- SELECT_DRIVE(drive);
- msleep(50);
- tp_ops->exec_command(hwif, ATA_EXABYTE_ENABLE_NEST);
-
- if (ide_busy_sleep(hwif, WAIT_WORSTCASE, 0)) {
- printk(KERN_CONT "failed (timeout)\n");
- return;
- }
-
- msleep(50);
-
- stat = tp_ops->read_status(hwif);
-
- if (!OK_STAT(stat, 0, BAD_STAT))
- printk(KERN_CONT "failed (status = 0x%02x)\n", stat);
- else
- printk(KERN_CONT "success\n");
-}
-
/**
* probe_for_drives - upper level drive probe
* @drive: drive to probe for
@@ -563,6 +470,8 @@ static void enable_nest (ide_drive_t *drive)
static u8 probe_for_drive(ide_drive_t *drive)
{
char *m;
+ int rc;
+ u8 cmd;
/*
* In order to keep things simple we have an id
@@ -586,21 +495,19 @@ static u8 probe_for_drive(ide_drive_t *drive)
/* skip probing? */
if ((drive->dev_flags & IDE_DFLAG_NOPROBE) == 0) {
-retry:
/* if !(success||timed-out) */
- if (do_probe(drive, ATA_CMD_ID_ATA) >= 2)
+ cmd = ATA_CMD_ID_ATA;
+ rc = do_probe(drive, cmd);
+ if (rc >= 2) {
/* look for ATAPI device */
- (void)do_probe(drive, ATA_CMD_ID_ATAPI);
+ cmd = ATA_CMD_ID_ATAPI;
+ rc = do_probe(drive, cmd);
+ }
if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
/* drive not found */
return 0;
- if (strstr(m, "E X A B Y T E N E S T")) {
- enable_nest(drive);
- goto retry;
- }
-
/* identification failed? */
if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) {
if (drive->media == ide_disk) {
@@ -614,8 +521,12 @@ retry:
printk(KERN_WARNING "%s: Unknown device on bus refused identification. Ignoring.\n", drive->name);
drive->dev_flags &= ~IDE_DFLAG_PRESENT;
}
+ } else {
+ if (cmd == ATA_CMD_ID_ATAPI)
+ ide_classify_atapi_dev(drive);
+ else
+ ide_classify_ata_dev(drive);
}
- /* drive was found */
}
if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
@@ -779,7 +690,6 @@ EXPORT_SYMBOL_GPL(ide_undecoded_slave);
static int ide_probe_port(ide_hwif_t *hwif)
{
ide_drive_t *drive;
- unsigned long flags;
unsigned int irqd;
int i, rc = -ENODEV;
@@ -797,9 +707,6 @@ static int ide_probe_port(ide_hwif_t *hwif)
if (irqd)
disable_irq(hwif->irq);
- local_save_flags(flags);
- local_irq_enable_in_hardirq();
-
if (ide_port_wait_ready(hwif) == -EBUSY)
printk(KERN_DEBUG "%s: Wait for ready failed before probe !\n", hwif->name);
@@ -813,8 +720,6 @@ static int ide_probe_port(ide_hwif_t *hwif)
rc = 0;
}
- local_irq_restore(flags);
-
/*
* Use cached IRQ number. It might be (and is...) changed by probe
* code above
@@ -831,22 +736,18 @@ static void ide_port_tune_devices(ide_hwif_t *hwif)
ide_drive_t *drive;
int i;
- ide_port_for_each_dev(i, drive, hwif) {
- if (drive->dev_flags & IDE_DFLAG_PRESENT) {
- if (port_ops && port_ops->quirkproc)
- port_ops->quirkproc(drive);
- }
+ ide_port_for_each_present_dev(i, drive, hwif) {
+ if (port_ops && port_ops->quirkproc)
+ port_ops->quirkproc(drive);
}
- ide_port_for_each_dev(i, drive, hwif) {
- if (drive->dev_flags & IDE_DFLAG_PRESENT) {
- ide_set_max_pio(drive);
+ ide_port_for_each_present_dev(i, drive, hwif) {
+ ide_set_max_pio(drive);
- drive->dev_flags |= IDE_DFLAG_NICE1;
+ drive->dev_flags |= IDE_DFLAG_NICE1;
- if (hwif->dma_ops)
- ide_set_dma(drive);
- }
+ if (hwif->dma_ops)
+ ide_set_dma(drive);
}
}
@@ -917,10 +818,7 @@ static int ide_port_setup_devices(ide_hwif_t *hwif)
int i, j = 0;
mutex_lock(&ide_cfg_mtx);
- ide_port_for_each_dev(i, drive, hwif) {
- if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
- continue;
-
+ ide_port_for_each_present_dev(i, drive, hwif) {
if (ide_init_queue(drive)) {
printk(KERN_ERR "ide: failed to init %s\n",
drive->name);
@@ -946,13 +844,6 @@ static int init_irq (ide_hwif_t *hwif)
irq_handler_t irq_handler;
int sa = 0;
- mutex_lock(&ide_cfg_mtx);
- spin_lock_init(&hwif->lock);
-
- init_timer(&hwif->timer);
- hwif->timer.function = &ide_timer_expiry;
- hwif->timer.data = (unsigned long)hwif;
-
irq_handler = hwif->host->irq_handler;
if (irq_handler == NULL)
irq_handler = ide_intr;
@@ -990,10 +881,8 @@ static int init_irq (ide_hwif_t *hwif)
printk(KERN_CONT " (serialized)");
printk(KERN_CONT "\n");
- mutex_unlock(&ide_cfg_mtx);
return 0;
out_up:
- mutex_unlock(&ide_cfg_mtx);
return 1;
}
@@ -1092,14 +981,9 @@ static void drive_release_dev (struct device *dev)
static int hwif_init(ide_hwif_t *hwif)
{
- int old_irq;
-
if (!hwif->irq) {
- hwif->irq = __ide_default_irq(hwif->io_ports.data_addr);
- if (!hwif->irq) {
- printk(KERN_ERR "%s: disabled, no IRQ\n", hwif->name);
- return 0;
- }
+ printk(KERN_ERR "%s: disabled, no IRQ\n", hwif->name);
+ return 0;
}
if (register_blkdev(hwif->major, hwif->name))
@@ -1117,29 +1001,12 @@ static int hwif_init(ide_hwif_t *hwif)
sg_init_table(hwif->sg_table, hwif->sg_max_nents);
- if (init_irq(hwif) == 0)
- goto done;
-
- old_irq = hwif->irq;
- /*
- * It failed to initialise. Find the default IRQ for
- * this port and try that.
- */
- hwif->irq = __ide_default_irq(hwif->io_ports.data_addr);
- if (!hwif->irq) {
- printk(KERN_ERR "%s: disabled, unable to get IRQ %d\n",
- hwif->name, old_irq);
- goto out;
- }
if (init_irq(hwif)) {
- printk(KERN_ERR "%s: probed IRQ %d and default IRQ %d failed\n",
- hwif->name, old_irq, hwif->irq);
+ printk(KERN_ERR "%s: disabled, unable to get IRQ %d\n",
+ hwif->name, hwif->irq);
goto out;
}
- printk(KERN_WARNING "%s: probed IRQ %d failed, using default\n",
- hwif->name, hwif->irq);
-done:
blk_register_region(MKDEV(hwif->major, 0), MAX_DRIVES << PARTN_BITS,
THIS_MODULE, ata_probe, ata_lock, hwif);
return 1;
@@ -1154,13 +1021,10 @@ static void hwif_register_devices(ide_hwif_t *hwif)
ide_drive_t *drive;
unsigned int i;
- ide_port_for_each_dev(i, drive, hwif) {
+ ide_port_for_each_present_dev(i, drive, hwif) {
struct device *dev = &drive->gendev;
int ret;
- if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
- continue;
-
dev_set_name(dev, "%u.%u", hwif->index, i);
dev->parent = &hwif->gendev;
dev->bus = &ide_bus_type;
@@ -1208,10 +1072,6 @@ static void ide_init_port(ide_hwif_t *hwif, unsigned int port,
if (d->init_iops)
d->init_iops(hwif);
- if ((!hwif->irq && (d->host_flags & IDE_HFLAG_LEGACY_IRQS)) ||
- (d->host_flags & IDE_HFLAG_FORCE_LEGACY_IRQS))
- hwif->irq = port ? 15 : 14;
-
/* ->host_flags may be set by ->init_iops (or even earlier...) */
hwif->host_flags |= d->host_flags;
hwif->pio_mask = d->pio_mask;
@@ -1312,6 +1172,12 @@ static void ide_init_port_data(ide_hwif_t *hwif, unsigned int index)
hwif->name[2] = 'e';
hwif->name[3] = '0' + index;
+ spin_lock_init(&hwif->lock);
+
+ init_timer(&hwif->timer);
+ hwif->timer.function = &ide_timer_expiry;
+ hwif->timer.data = (unsigned long)hwif;
+
init_completion(&hwif->gendev_rel_comp);
hwif->tp_ops = &default_tp_ops;
@@ -1562,7 +1428,7 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
j++;
- ide_acpi_init(hwif);
+ ide_acpi_init_port(hwif);
if (hwif->present)
ide_acpi_port_init_devices(hwif);
@@ -1619,11 +1485,9 @@ static void __ide_port_unregister_devices(ide_hwif_t *hwif)
ide_drive_t *drive;
int i;
- ide_port_for_each_dev(i, drive, hwif) {
- if (drive->dev_flags & IDE_DFLAG_PRESENT) {
- device_unregister(&drive->gendev);
- wait_for_completion(&drive->gendev_rel_comp);
- }
+ ide_port_for_each_present_dev(i, drive, hwif) {
+ device_unregister(&drive->gendev);
+ wait_for_completion(&drive->gendev_rel_comp);
}
}
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index a7b9287..417cde5 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -600,7 +600,7 @@ void ide_proc_port_register_devices(ide_hwif_t *hwif)
int i;
ide_port_for_each_dev(i, drive, hwif) {
- if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0 || drive->proc)
+ if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
continue;
drive->proc = proc_mkdir(drive->name, parent);
diff --git a/drivers/ide/ide-xfer-mode.c b/drivers/ide/ide-xfer-mode.c
new file mode 100644
index 0000000..6910f6a
--- /dev/null
+++ b/drivers/ide/ide-xfer-mode.c
@@ -0,0 +1,246 @@
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/ide.h>
+#include <linux/bitops.h>
+
+static const char *udma_str[] =
+ { "UDMA/16", "UDMA/25", "UDMA/33", "UDMA/44",
+ "UDMA/66", "UDMA/100", "UDMA/133", "UDMA7" };
+static const char *mwdma_str[] =
+ { "MWDMA0", "MWDMA1", "MWDMA2" };
+static const char *swdma_str[] =
+ { "SWDMA0", "SWDMA1", "SWDMA2" };
+static const char *pio_str[] =
+ { "PIO0", "PIO1", "PIO2", "PIO3", "PIO4", "PIO5" };
+
+/**
+ * ide_xfer_verbose - return IDE mode names
+ * @mode: transfer mode
+ *
+ * Returns a constant string giving the name of the mode
+ * requested.
+ */
+
+const char *ide_xfer_verbose(u8 mode)
+{
+ const char *s;
+ u8 i = mode & 0xf;
+
+ if (mode >= XFER_UDMA_0 && mode <= XFER_UDMA_7)
+ s = udma_str[i];
+ else if (mode >= XFER_MW_DMA_0 && mode <= XFER_MW_DMA_2)
+ s = mwdma_str[i];
+ else if (mode >= XFER_SW_DMA_0 && mode <= XFER_SW_DMA_2)
+ s = swdma_str[i];
+ else if (mode >= XFER_PIO_0 && mode <= XFER_PIO_5)
+ s = pio_str[i & 0x7];
+ else if (mode == XFER_PIO_SLOW)
+ s = "PIO SLOW";
+ else
+ s = "XFER ERROR";
+
+ return s;
+}
+EXPORT_SYMBOL(ide_xfer_verbose);
+
+/**
+ * ide_get_best_pio_mode - get PIO mode from drive
+ * @drive: drive to consider
+ * @mode_wanted: preferred mode
+ * @max_mode: highest allowed mode
+ *
+ * This routine returns the recommended PIO settings for a given drive,
+ * based on the drive->id information and the ide_pio_blacklist[].
+ *
+ * Drive PIO mode is auto-selected if 255 is passed as mode_wanted.
+ * This is used by most chipset support modules when "auto-tuning".
+ */
+
+u8 ide_get_best_pio_mode(ide_drive_t *drive, u8 mode_wanted, u8 max_mode)
+{
+ u16 *id = drive->id;
+ int pio_mode = -1, overridden = 0;
+
+ if (mode_wanted != 255)
+ return min_t(u8, mode_wanted, max_mode);
+
+ if ((drive->hwif->host_flags & IDE_HFLAG_PIO_NO_BLACKLIST) == 0)
+ pio_mode = ide_scan_pio_blacklist((char *)&id[ATA_ID_PROD]);
+
+ if (pio_mode != -1) {
+ printk(KERN_INFO "%s: is on PIO blacklist\n", drive->name);
+ } else {
+ pio_mode = id[ATA_ID_OLD_PIO_MODES] >> 8;
+ if (pio_mode > 2) { /* 2 is maximum allowed tPIO value */
+ pio_mode = 2;
+ overridden = 1;
+ }
+
+ if (id[ATA_ID_FIELD_VALID] & 2) { /* ATA2? */
+ if (ata_id_has_iordy(id)) {
+ if (id[ATA_ID_PIO_MODES] & 7) {
+ overridden = 0;
+ if (id[ATA_ID_PIO_MODES] & 4)
+ pio_mode = 5;
+ else if (id[ATA_ID_PIO_MODES] & 2)
+ pio_mode = 4;
+ else
+ pio_mode = 3;
+ }
+ }
+ }
+
+ if (overridden)
+ printk(KERN_INFO "%s: tPIO > 2, assuming tPIO = 2\n",
+ drive->name);
+ }
+
+ if (pio_mode > max_mode)
+ pio_mode = max_mode;
+
+ return pio_mode;
+}
+EXPORT_SYMBOL_GPL(ide_get_best_pio_mode);
+
+int ide_set_pio_mode(ide_drive_t *drive, const u8 mode)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ const struct ide_port_ops *port_ops = hwif->port_ops;
+
+ if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)
+ return 0;
+
+ if (port_ops == NULL || port_ops->set_pio_mode == NULL)
+ return -1;
+
+ /*
+ * TODO: temporary hack for some legacy host drivers that didn't
+ * set transfer mode on the device in ->set_pio_mode method...
+ */
+ if (port_ops->set_dma_mode == NULL) {
+ port_ops->set_pio_mode(drive, mode - XFER_PIO_0);
+ return 0;
+ }
+
+ if (hwif->host_flags & IDE_HFLAG_POST_SET_MODE) {
+ if (ide_config_drive_speed(drive, mode))
+ return -1;
+ port_ops->set_pio_mode(drive, mode - XFER_PIO_0);
+ return 0;
+ } else {
+ port_ops->set_pio_mode(drive, mode - XFER_PIO_0);
+ return ide_config_drive_speed(drive, mode);
+ }
+}
+
+int ide_set_dma_mode(ide_drive_t *drive, const u8 mode)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ const struct ide_port_ops *port_ops = hwif->port_ops;
+
+ if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)
+ return 0;
+
+ if (port_ops == NULL || port_ops->set_dma_mode == NULL)
+ return -1;
+
+ if (hwif->host_flags & IDE_HFLAG_POST_SET_MODE) {
+ if (ide_config_drive_speed(drive, mode))
+ return -1;
+ port_ops->set_dma_mode(drive, mode);
+ return 0;
+ } else {
+ port_ops->set_dma_mode(drive, mode);
+ return ide_config_drive_speed(drive, mode);
+ }
+}
+EXPORT_SYMBOL_GPL(ide_set_dma_mode);
+
+/* req_pio == "255" for auto-tune */
+void ide_set_pio(ide_drive_t *drive, u8 req_pio)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ const struct ide_port_ops *port_ops = hwif->port_ops;
+ u8 host_pio, pio;
+
+ if (port_ops == NULL || port_ops->set_pio_mode == NULL ||
+ (hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
+ return;
+
+ BUG_ON(hwif->pio_mask == 0x00);
+
+ host_pio = fls(hwif->pio_mask) - 1;
+
+ pio = ide_get_best_pio_mode(drive, req_pio, host_pio);
+
+ /*
+ * TODO:
+ * - report device max PIO mode
+ * - check req_pio != 255 against device max PIO mode
+ */
+ printk(KERN_DEBUG "%s: host max PIO%d wanted PIO%d%s selected PIO%d\n",
+ drive->name, host_pio, req_pio,
+ req_pio == 255 ? "(auto-tune)" : "", pio);
+
+ (void)ide_set_pio_mode(drive, XFER_PIO_0 + pio);
+}
+EXPORT_SYMBOL_GPL(ide_set_pio);
+
+/**
+ * ide_rate_filter - filter transfer mode
+ * @drive: IDE device
+ * @speed: desired speed
+ *
+ * Given the available transfer modes this function returns
+ * the best available speed at or below the speed requested.
+ *
+ * TODO: check device PIO capabilities
+ */
+
+static u8 ide_rate_filter(ide_drive_t *drive, u8 speed)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ u8 mode = ide_find_dma_mode(drive, speed);
+
+ if (mode == 0) {
+ if (hwif->pio_mask)
+ mode = fls(hwif->pio_mask) - 1 + XFER_PIO_0;
+ else
+ mode = XFER_PIO_4;
+ }
+
+/* printk("%s: mode 0x%02x, speed 0x%02x\n", __func__, mode, speed); */
+
+ return min(speed, mode);
+}
+
+/**
+ * ide_set_xfer_rate - set transfer rate
+ * @drive: drive to set
+ * @rate: speed to attempt to set
+ *
+ * General helper for setting the speed of an IDE device. This
+ * function knows about user enforced limits from the configuration
+ * which ->set_pio_mode/->set_dma_mode does not.
+ */
+
+int ide_set_xfer_rate(ide_drive_t *drive, u8 rate)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ const struct ide_port_ops *port_ops = hwif->port_ops;
+
+ if (port_ops == NULL || port_ops->set_dma_mode == NULL ||
+ (hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
+ return -1;
+
+ rate = ide_rate_filter(drive, rate);
+
+ BUG_ON(rate < XFER_PIO_0);
+
+ if (rate >= XFER_PIO_0 && rate <= XFER_PIO_5)
+ return ide_set_pio_mode(drive, rate);
+
+ return ide_set_dma_mode(drive, rate);
+}
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 0920e3b..92c9b90 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -62,160 +62,6 @@
struct class *ide_port_class;
-/*
- * Locks for IDE setting functionality
- */
-
-DEFINE_MUTEX(ide_setting_mtx);
-
-ide_devset_get(io_32bit, io_32bit);
-
-static int set_io_32bit(ide_drive_t *drive, int arg)
-{
- if (drive->dev_flags & IDE_DFLAG_NO_IO_32BIT)
- return -EPERM;
-
- if (arg < 0 || arg > 1 + (SUPPORT_VLB_SYNC << 1))
- return -EINVAL;
-
- drive->io_32bit = arg;
-
- return 0;
-}
-
-ide_devset_get_flag(ksettings, IDE_DFLAG_KEEP_SETTINGS);
-
-static int set_ksettings(ide_drive_t *drive, int arg)
-{
- if (arg < 0 || arg > 1)
- return -EINVAL;
-
- if (arg)
- drive->dev_flags |= IDE_DFLAG_KEEP_SETTINGS;
- else
- drive->dev_flags &= ~IDE_DFLAG_KEEP_SETTINGS;
-
- return 0;
-}
-
-ide_devset_get_flag(using_dma, IDE_DFLAG_USING_DMA);
-
-static int set_using_dma(ide_drive_t *drive, int arg)
-{
-#ifdef CONFIG_BLK_DEV_IDEDMA
- int err = -EPERM;
-
- if (arg < 0 || arg > 1)
- return -EINVAL;
-
- if (ata_id_has_dma(drive->id) == 0)
- goto out;
-
- if (drive->hwif->dma_ops == NULL)
- goto out;
-
- err = 0;
-
- if (arg) {
- if (ide_set_dma(drive))
- err = -EIO;
- } else
- ide_dma_off(drive);
-
-out:
- return err;
-#else
- if (arg < 0 || arg > 1)
- return -EINVAL;
-
- return -EPERM;
-#endif
-}
-
-/*
- * handle HDIO_SET_PIO_MODE ioctl abusers here, eventually it will go away
- */
-static int set_pio_mode_abuse(ide_hwif_t *hwif, u8 req_pio)
-{
- switch (req_pio) {
- case 202:
- case 201:
- case 200:
- case 102:
- case 101:
- case 100:
- return (hwif->host_flags & IDE_HFLAG_ABUSE_DMA_MODES) ? 1 : 0;
- case 9:
- case 8:
- return (hwif->host_flags & IDE_HFLAG_ABUSE_PREFETCH) ? 1 : 0;
- case 7:
- case 6:
- return (hwif->host_flags & IDE_HFLAG_ABUSE_FAST_DEVSEL) ? 1 : 0;
- default:
- return 0;
- }
-}
-
-static int set_pio_mode(ide_drive_t *drive, int arg)
-{
- ide_hwif_t *hwif = drive->hwif;
- const struct ide_port_ops *port_ops = hwif->port_ops;
-
- if (arg < 0 || arg > 255)
- return -EINVAL;
-
- if (port_ops == NULL || port_ops->set_pio_mode == NULL ||
- (hwif->host_flags & IDE_HFLAG_NO_SET_MODE))
- return -ENOSYS;
-
- if (set_pio_mode_abuse(drive->hwif, arg)) {
- if (arg == 8 || arg == 9) {
- unsigned long flags;
-
- /* take lock for IDE_DFLAG_[NO_]UNMASK/[NO_]IO_32BIT */
- spin_lock_irqsave(&hwif->lock, flags);
- port_ops->set_pio_mode(drive, arg);
- spin_unlock_irqrestore(&hwif->lock, flags);
- } else
- port_ops->set_pio_mode(drive, arg);
- } else {
- int keep_dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
-
- ide_set_pio(drive, arg);
-
- if (hwif->host_flags & IDE_HFLAG_SET_PIO_MODE_KEEP_DMA) {
- if (keep_dma)
- ide_dma_on(drive);
- }
- }
-
- return 0;
-}
-
-ide_devset_get_flag(unmaskirq, IDE_DFLAG_UNMASK);
-
-static int set_unmaskirq(ide_drive_t *drive, int arg)
-{
- if (drive->dev_flags & IDE_DFLAG_NO_UNMASK)
- return -EPERM;
-
- if (arg < 0 || arg > 1)
- return -EINVAL;
-
- if (arg)
- drive->dev_flags |= IDE_DFLAG_UNMASK;
- else
- drive->dev_flags &= ~IDE_DFLAG_UNMASK;
-
- return 0;
-}
-
-ide_ext_devset_rw_sync(io_32bit, io_32bit);
-ide_ext_devset_rw_sync(keepsettings, ksettings);
-ide_ext_devset_rw_sync(unmaskirq, unmaskirq);
-ide_ext_devset_rw_sync(using_dma, using_dma);
-__IDE_DEVSET(pio_mode, DS_SYNC, NULL, set_pio_mode);
-
/**
* ide_device_get - get an additional reference to a ide_drive_t
* @drive: device to get a reference to
@@ -527,6 +373,8 @@ static int __init ide_init(void)
goto out_port_class;
}
+ ide_acpi_init();
+
proc_ide_create();
return 0;
diff --git a/drivers/ide/it821x.c b/drivers/ide/it821x.c
index 13b8153..6b9fc95 100644
--- a/drivers/ide/it821x.c
+++ b/drivers/ide/it821x.c
@@ -603,7 +603,7 @@ static void it8212_disable_raid(struct pci_dev *dev)
pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20);
}
-static unsigned int init_chipset_it821x(struct pci_dev *dev)
+static int init_chipset_it821x(struct pci_dev *dev)
{
u8 conf;
static char *mode[2] = { "pass through", "smart" };
diff --git a/drivers/ide/ns87415.c b/drivers/ide/ns87415.c
index 83643ed..ea48a3e 100644
--- a/drivers/ide/ns87415.c
+++ b/drivers/ide/ns87415.c
@@ -286,9 +286,7 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
}
if (!using_inta)
- hwif->irq = __ide_default_irq(hwif->io_ports.data_addr);
- else if (!hwif->irq && hwif->mate && hwif->mate->irq)
- hwif->irq = hwif->mate->irq; /* share IRQ with mate */
+ hwif->irq = pci_get_legacy_ide_irq(dev, hwif->channel);
if (!hwif->dma_base)
return;
diff --git a/drivers/ide/pdc202xx_new.c b/drivers/ide/pdc202xx_new.c
index f21290c..b68906c 100644
--- a/drivers/ide/pdc202xx_new.c
+++ b/drivers/ide/pdc202xx_new.c
@@ -325,7 +325,7 @@ static void apple_kiwi_init(struct pci_dev *pdev)
}
#endif /* CONFIG_PPC_PMAC */
-static unsigned int init_chipset_pdcnew(struct pci_dev *dev)
+static int init_chipset_pdcnew(struct pci_dev *dev)
{
const char *name = DRV_NAME;
unsigned long dma_base = pci_resource_start(dev, 4);
@@ -444,7 +444,7 @@ static unsigned int init_chipset_pdcnew(struct pci_dev *dev)
#endif
out:
- return dev->irq;
+ return 0;
}
static struct pci_dev * __devinit pdc20270_get_dev2(struct pci_dev *dev)
diff --git a/drivers/ide/pdc202xx_old.c b/drivers/ide/pdc202xx_old.c
index 9719332..cba66eb 100644
--- a/drivers/ide/pdc202xx_old.c
+++ b/drivers/ide/pdc202xx_old.c
@@ -264,7 +264,7 @@ static void pdc202xx_dma_timeout(ide_drive_t *drive)
ide_dma_timeout(drive);
}
-static unsigned int init_chipset_pdc202xx(struct pci_dev *dev)
+static int init_chipset_pdc202xx(struct pci_dev *dev)
{
unsigned long dmabase = pci_resource_start(dev, 4);
u8 udma_speed_flag = 0, primary_mode = 0, secondary_mode = 0;
@@ -290,7 +290,7 @@ static unsigned int init_chipset_pdc202xx(struct pci_dev *dev)
printk("%sACTIVE\n", (inb(dmabase | 0x1f) & 1) ? "" : "IN");
}
out:
- return dev->irq;
+ return 0;
}
static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev,
diff --git a/drivers/ide/piix.c b/drivers/ide/piix.c
index f1e2e4e..2aa6999 100644
--- a/drivers/ide/piix.c
+++ b/drivers/ide/piix.c
@@ -204,7 +204,7 @@ static void piix_set_dma_mode(ide_drive_t *drive, const u8 speed)
* out to be nice and simple.
*/
-static unsigned int init_chipset_ich(struct pci_dev *dev)
+static int init_chipset_ich(struct pci_dev *dev)
{
u32 extra = 0;
@@ -318,19 +318,12 @@ static const struct ide_port_ops ich_port_ops = {
.cable_detect = piix_cable_detect,
};
-#ifndef CONFIG_IA64
- #define IDE_HFLAGS_PIIX IDE_HFLAG_LEGACY_IRQS
-#else
- #define IDE_HFLAGS_PIIX 0
-#endif
-
#define DECLARE_PIIX_DEV(udma) \
{ \
.name = DRV_NAME, \
.init_hwif = init_hwif_piix, \
.enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \
.port_ops = &piix_port_ops, \
- .host_flags = IDE_HFLAGS_PIIX, \
.pio_mask = ATA_PIO4, \
.swdma_mask = ATA_SWDMA2_ONLY, \
.mwdma_mask = ATA_MWDMA12_ONLY, \
@@ -344,7 +337,6 @@ static const struct ide_port_ops ich_port_ops = {
.init_hwif = init_hwif_piix, \
.enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \
.port_ops = &ich_port_ops, \
- .host_flags = IDE_HFLAGS_PIIX, \
.pio_mask = ATA_PIO4, \
.swdma_mask = ATA_SWDMA2_ONLY, \
.mwdma_mask = ATA_MWDMA12_ONLY, \
@@ -360,8 +352,7 @@ static const struct ide_port_info piix_pci_info[] __devinitdata = {
*/
.name = DRV_NAME,
.enablebits = {{0x6d,0xc0,0x80}, {0x6d,0xc0,0xc0}},
- .host_flags = IDE_HFLAG_ISA_PORTS | IDE_HFLAG_NO_DMA |
- IDE_HFLAGS_PIIX,
+ .host_flags = IDE_HFLAG_ISA_PORTS | IDE_HFLAG_NO_DMA,
.pio_mask = ATA_PIO4,
/* This is a painful system best to let it self tune for now */
},
diff --git a/drivers/ide/serverworks.c b/drivers/ide/serverworks.c
index 382102b..b6554ef 100644
--- a/drivers/ide/serverworks.c
+++ b/drivers/ide/serverworks.c
@@ -175,7 +175,7 @@ static void svwks_set_dma_mode(ide_drive_t *drive, const u8 speed)
pci_write_config_byte(dev, 0x54, ultra_enable);
}
-static unsigned int init_chipset_svwks(struct pci_dev *dev)
+static int init_chipset_svwks(struct pci_dev *dev)
{
unsigned int reg;
u8 btr;
@@ -270,7 +270,7 @@ static unsigned int init_chipset_svwks(struct pci_dev *dev)
pci_write_config_byte(dev, 0x5A, btr);
}
- return dev->irq;
+ return 0;
}
static u8 ata66_svwks_svwks(ide_hwif_t *hwif)
@@ -353,14 +353,11 @@ static const struct ide_port_ops svwks_port_ops = {
.cable_detect = svwks_cable_detect,
};
-#define IDE_HFLAGS_SVWKS IDE_HFLAG_LEGACY_IRQS
-
static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
{ /* 0: OSB4 */
.name = DRV_NAME,
.init_chipset = init_chipset_svwks,
.port_ops = &osb4_port_ops,
- .host_flags = IDE_HFLAGS_SVWKS,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = 0x00, /* UDMA is problematic on OSB4 */
@@ -369,7 +366,6 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
.name = DRV_NAME,
.init_chipset = init_chipset_svwks,
.port_ops = &svwks_port_ops,
- .host_flags = IDE_HFLAGS_SVWKS,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
@@ -378,7 +374,6 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
.name = DRV_NAME,
.init_chipset = init_chipset_svwks,
.port_ops = &svwks_port_ops,
- .host_flags = IDE_HFLAGS_SVWKS,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
@@ -387,7 +382,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
.name = DRV_NAME,
.init_chipset = init_chipset_svwks,
.port_ops = &svwks_port_ops,
- .host_flags = IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE,
+ .host_flags = IDE_HFLAG_SINGLE,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
@@ -396,7 +391,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
.name = DRV_NAME,
.init_chipset = init_chipset_svwks,
.port_ops = &svwks_port_ops,
- .host_flags = IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE,
+ .host_flags = IDE_HFLAG_SINGLE,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA5,
diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c
index e85d1ed..24bc884 100644
--- a/drivers/ide/setup-pci.c
+++ b/drivers/ide/setup-pci.c
@@ -305,7 +305,6 @@ static int ide_pci_check_iomem(struct pci_dev *dev, const struct ide_port_info *
* @dev: PCI device holding interface
* @d: IDE port info
* @port: port number
- * @irq: PCI IRQ
* @hw: hw_regs_t instance corresponding to this port
*
* Perform the initial set up for the hardware interface structure. This
@@ -316,7 +315,7 @@ static int ide_pci_check_iomem(struct pci_dev *dev, const struct ide_port_info *
*/
static int ide_hw_configure(struct pci_dev *dev, const struct ide_port_info *d,
- unsigned int port, int irq, hw_regs_t *hw)
+ unsigned int port, hw_regs_t *hw)
{
unsigned long ctl = 0, base = 0;
@@ -344,7 +343,6 @@ static int ide_hw_configure(struct pci_dev *dev, const struct ide_port_info *d,
}
memset(hw, 0, sizeof(*hw));
- hw->irq = irq;
hw->dev = &dev->dev;
hw->chipset = d->chipset ? d->chipset : ide_pci;
ide_std_init_ports(hw, base, ctl | 2);
@@ -448,7 +446,6 @@ out:
* ide_pci_setup_ports - configure ports/devices on PCI IDE
* @dev: PCI device
* @d: IDE port info
- * @pciirq: IRQ line
* @hw: hw_regs_t instances corresponding to this PCI IDE device
* @hws: hw_regs_t pointers table to update
*
@@ -462,7 +459,7 @@ out:
*/
void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d,
- int pciirq, hw_regs_t *hw, hw_regs_t **hws)
+ hw_regs_t *hw, hw_regs_t **hws)
{
int channels = (d->host_flags & IDE_HFLAG_SINGLE) ? 1 : 2, port;
u8 tmp;
@@ -481,7 +478,7 @@ void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d,
continue; /* port not enabled */
}
- if (ide_hw_configure(dev, d, port, pciirq, hw + port))
+ if (ide_hw_configure(dev, d, port, hw + port))
continue;
*(hws + port) = hw + port;
@@ -524,7 +521,7 @@ static int do_ide_setup_pci_device(struct pci_dev *dev,
if (noisy)
printk(KERN_INFO "%s %s: not 100%% native mode: will "
"probe irqs later\n", d->name, pci_name(dev));
- pciirq = ret;
+ pciirq = 0;
} else if (!pciirq && noisy) {
printk(KERN_WARNING "%s %s: bad irq (%d): will probe later\n",
d->name, pci_name(dev), pciirq);
@@ -549,7 +546,7 @@ int ide_pci_init_one(struct pci_dev *dev, const struct ide_port_info *d,
if (ret < 0)
goto out;
- ide_pci_setup_ports(dev, d, 0, &hw[0], &hws[0]);
+ ide_pci_setup_ports(dev, d, &hw[0], &hws[0]);
host = ide_host_alloc(d, hws);
if (host == NULL) {
@@ -568,7 +565,11 @@ int ide_pci_init_one(struct pci_dev *dev, const struct ide_port_info *d,
goto out;
/* fixup IRQ */
- hw[1].irq = hw[0].irq = ret;
+ if (ide_pci_is_in_compatibility_mode(dev)) {
+ hw[0].irq = pci_get_legacy_ide_irq(dev, 0);
+ hw[1].irq = pci_get_legacy_ide_irq(dev, 1);
+ } else
+ hw[1].irq = hw[0].irq = ret;
ret = ide_host_register(host, d, hws);
if (ret)
@@ -591,7 +592,7 @@ int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2,
if (ret < 0)
goto out;
- ide_pci_setup_ports(pdev[i], d, 0, &hw[i*2], &hws[i*2]);
+ ide_pci_setup_ports(pdev[i], d, &hw[i*2], &hws[i*2]);
}
host = ide_host_alloc(d, hws);
@@ -619,7 +620,11 @@ int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2,
goto out;
/* fixup IRQ */
- hw[i*2 + 1].irq = hw[i*2].irq = ret;
+ if (ide_pci_is_in_compatibility_mode(pdev[i])) {
+ hw[i*2].irq = pci_get_legacy_ide_irq(pdev[i], 0);
+ hw[i*2 + 1].irq = pci_get_legacy_ide_irq(pdev[i], 1);
+ } else
+ hw[i*2 + 1].irq = hw[i*2].irq = ret;
}
ret = ide_host_register(host, d, hws);
diff --git a/drivers/ide/siimage.c b/drivers/ide/siimage.c
index cb2b352..1811ae9 100644
--- a/drivers/ide/siimage.c
+++ b/drivers/ide/siimage.c
@@ -464,7 +464,7 @@ static void sil_sata_pre_reset(ide_drive_t *drive)
* to 133 MHz clocking if the system isn't already set up to do it.
*/
-static unsigned int init_chipset_siimage(struct pci_dev *dev)
+static int init_chipset_siimage(struct pci_dev *dev)
{
struct ide_host *host = pci_get_drvdata(dev);
void __iomem *ioaddr = host->host_priv;
diff --git a/drivers/ide/sis5513.c b/drivers/ide/sis5513.c
index 9ec1a4a..afca22b 100644
--- a/drivers/ide/sis5513.c
+++ b/drivers/ide/sis5513.c
@@ -447,7 +447,7 @@ static int __devinit sis_find_family(struct pci_dev *dev)
return chipset_family;
}
-static unsigned int init_chipset_sis5513(struct pci_dev *dev)
+static int init_chipset_sis5513(struct pci_dev *dev)
{
/* Make general config ops here
1/ tell IDE channels to operate in Compatibility mode only
@@ -563,7 +563,7 @@ static const struct ide_port_info sis5513_chipset __devinitdata = {
.name = DRV_NAME,
.init_chipset = init_chipset_sis5513,
.enablebits = { {0x4a, 0x02, 0x02}, {0x4a, 0x04, 0x04} },
- .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_NO_AUTODMA,
+ .host_flags = IDE_HFLAG_NO_AUTODMA,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
};
diff --git a/drivers/ide/sl82c105.c b/drivers/ide/sl82c105.c
index 6297956..dba213c 100644
--- a/drivers/ide/sl82c105.c
+++ b/drivers/ide/sl82c105.c
@@ -271,7 +271,7 @@ static u8 sl82c105_bridge_revision(struct pci_dev *dev)
* channel 0 here at least, but channel 1 has to be enabled by
* firmware or arch code. We still set both to 16 bits mode.
*/
-static unsigned int init_chipset_sl82c105(struct pci_dev *dev)
+static int init_chipset_sl82c105(struct pci_dev *dev)
{
u32 val;
@@ -281,7 +281,7 @@ static unsigned int init_chipset_sl82c105(struct pci_dev *dev)
val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16;
pci_write_config_dword(dev, 0x40, val);
- return dev->irq;
+ return 0;
}
static const struct ide_port_ops sl82c105_port_ops = {
diff --git a/drivers/ide/slc90e66.c b/drivers/ide/slc90e66.c
index 40b4b94..f55d7d6 100644
--- a/drivers/ide/slc90e66.c
+++ b/drivers/ide/slc90e66.c
@@ -136,7 +136,6 @@ static const struct ide_port_info slc90e66_chipset __devinitdata = {
.name = DRV_NAME,
.enablebits = { {0x41, 0x80, 0x80}, {0x43, 0x80, 0x80} },
.port_ops = &slc90e66_port_ops,
- .host_flags = IDE_HFLAG_LEGACY_IRQS,
.pio_mask = ATA_PIO4,
.swdma_mask = ATA_SWDMA2_ONLY,
.mwdma_mask = ATA_MWDMA12_ONLY,
diff --git a/drivers/ide/trm290.c b/drivers/ide/trm290.c
index b6a1285..1c09e54 100644
--- a/drivers/ide/trm290.c
+++ b/drivers/ide/trm290.c
@@ -277,9 +277,6 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif)
if (reg & 0x10)
/* legacy mode */
hwif->irq = hwif->channel ? 15 : 14;
- else if (!hwif->irq && hwif->mate && hwif->mate->irq)
- /* sharing IRQ with mate */
- hwif->irq = hwif->mate->irq;
#if 1
{
diff --git a/drivers/ide/via82cxxx.c b/drivers/ide/via82cxxx.c
index 6092fe3..3ff7231 100644
--- a/drivers/ide/via82cxxx.c
+++ b/drivers/ide/via82cxxx.c
@@ -267,7 +267,7 @@ static void via_cable_detect(struct via82cxxx_dev *vdev, u32 u)
* and initialize its drive independent registers.
*/
-static unsigned int init_chipset_via82cxxx(struct pci_dev *dev)
+static int init_chipset_via82cxxx(struct pci_dev *dev)
{
struct ide_host *host = pci_get_drvdata(dev);
struct via82cxxx_dev *vdev = host->host_priv;
@@ -443,16 +443,6 @@ static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_i
if ((via_config->flags & VIA_NO_UNMASK) == 0)
d.host_flags |= IDE_HFLAG_UNMASK_IRQS;
-#ifdef CONFIG_PPC_CHRP
- if (machine_is(chrp) && _chrp_type == _CHRP_Pegasos)
- d.host_flags |= IDE_HFLAG_FORCE_LEGACY_IRQS;
-#endif
-
-#ifdef CONFIG_AMIGAONE
- if (machine_is(amigaone))
- d.host_flags |= IDE_HFLAG_FORCE_LEGACY_IRQS;
-#endif
-
d.udma_mask = via_config->udma_mask;
vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
diff --git a/include/asm-frv/ide.h b/include/asm-frv/ide.h
deleted file mode 100644
index 3610766..0000000
--- a/include/asm-frv/ide.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* ide.h: FRV IDE declarations
- *
- * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#ifndef _ASM_IDE_H
-#define _ASM_IDE_H
-
-#ifdef __KERNEL__
-
-#include <asm/setup.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#include <asm-generic/ide_iops.h>
-
-#endif /* __KERNEL__ */
-#endif /* _ASM_IDE_H */
diff --git a/include/asm-mn10300/ide.h b/include/asm-mn10300/ide.h
deleted file mode 100644
index 6adcdd9..0000000
--- a/include/asm-mn10300/ide.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* MN10300 Arch-specific IDE code
- *
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- * - Derived from include/asm-i386/ide.h
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
- */
-
-#ifndef _ASM_IDE_H
-#define _ASM_IDE_H
-
-#ifdef __KERNEL__
-
-#include <asm/intctl-regs.h>
-
-#undef SUPPORT_SLOW_DATA_PORTS
-#define SUPPORT_SLOW_DATA_PORTS 0
-
-#undef SUPPORT_VLB_SYNC
-#define SUPPORT_VLB_SYNC 0
-
-/*
- * some bits needed for parts of the IDE subsystem to compile
- */
-#define __ide_mm_insw(port, addr, n) \
- insw((unsigned long) (port), (addr), (n))
-#define __ide_mm_insl(port, addr, n) \
- insl((unsigned long) (port), (addr), (n))
-#define __ide_mm_outsw(port, addr, n) \
- outsw((unsigned long) (port), (addr), (n))
-#define __ide_mm_outsl(port, addr, n) \
- outsl((unsigned long) (port), (addr), (n))
-
-#endif /* __KERNEL__ */
-#endif /* _ASM_IDE_H */
diff --git a/include/asm-mn10300/pci.h b/include/asm-mn10300/pci.h
index cd9cc5c..0517b45 100644
--- a/include/asm-mn10300/pci.h
+++ b/include/asm-mn10300/pci.h
@@ -121,4 +121,9 @@ pcibios_select_root(struct pci_dev *pdev, struct resource *res)
#define pcibios_scan_all_fns(a, b) 0
+static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
+{
+ return channel ? 15 : 14;
+}
+
#endif /* _ASM_PCI_H */
diff --git a/include/linux/ata.h b/include/linux/ata.h
index 9a061ac..68132c4 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -244,8 +244,6 @@ enum {
ATA_CMD_MEDIA_UNLOCK = 0xDF,
/* marked obsolete in the ATA/ATAPI-7 spec */
ATA_CMD_RESTORE = 0x10,
- /* EXABYTE specific */
- ATA_EXABYTE_ENABLE_NEST = 0xF0,
/* READ_LOG_EXT pages */
ATA_LOG_SATA_NCQ = 0x10,
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 25087ae..854eba8 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -26,7 +26,7 @@
#include <asm/io.h>
#include <asm/mutex.h>
-#if defined(CONFIG_CRIS) || defined(CONFIG_FRV)
+#if defined(CONFIG_CRIS) || defined(CONFIG_FRV) || defined(CONFIG_MN10300)
# define SUPPORT_VLB_SYNC 0
#else
# define SUPPORT_VLB_SYNC 1
@@ -193,24 +193,8 @@ static inline void ide_std_init_ports(hw_regs_t *hw,
hw->io_ports.ctl_addr = ctl_addr;
}
-/* for IDE PCI controllers in legacy mode, temporary */
-static inline int __ide_default_irq(unsigned long base)
-{
- switch (base) {
-#ifdef CONFIG_IA64
- case 0x1f0: return isa_irq_to_vector(14);
- case 0x170: return isa_irq_to_vector(15);
-#else
- case 0x1f0: return 14;
- case 0x170: return 15;
-#endif
- }
- return 0;
-}
-
-#if defined(CONFIG_ARM) || defined(CONFIG_FRV) || defined(CONFIG_M68K) || \
- defined(CONFIG_MIPS) || defined(CONFIG_MN10300) || defined(CONFIG_PARISC) \
- || defined(CONFIG_PPC) || defined(CONFIG_SPARC) || defined(CONFIG_SPARC64)
+#if defined(CONFIG_ARM) || defined(CONFIG_M68K) || defined(CONFIG_MIPS) || \
+ defined(CONFIG_PARISC) || defined(CONFIG_PPC) || defined(CONFIG_SPARC)
#include <asm/ide.h>
#else
#include <asm-generic/ide_iops.h>
@@ -866,7 +850,7 @@ struct ide_host {
ide_hwif_t *ports[MAX_HOST_PORTS + 1];
unsigned int n_ports;
struct device *dev[2];
- unsigned int (*init_chipset)(struct pci_dev *);
+ int (*init_chipset)(struct pci_dev *);
irq_handler_t irq_handler;
unsigned long host_flags;
void *host_priv;
@@ -1146,11 +1130,14 @@ int generic_ide_ioctl(ide_drive_t *, struct block_device *, unsigned, unsigned l
extern int ide_vlb_clk;
extern int ide_pci_clk;
-extern int ide_end_request (ide_drive_t *drive, int uptodate, int nrsecs);
-int ide_end_dequeued_request(ide_drive_t *drive, struct request *rq,
- int uptodate, int nr_sectors);
+int ide_end_request(ide_drive_t *, int, int);
+int ide_end_dequeued_request(ide_drive_t *, struct request *, int, int);
+void ide_kill_rq(ide_drive_t *, struct request *);
-extern void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigned int timeout, ide_expiry_t *expiry);
+void __ide_set_handler(ide_drive_t *, ide_handler_t *, unsigned int,
+ ide_expiry_t *);
+void ide_set_handler(ide_drive_t *, ide_handler_t *, unsigned int,
+ ide_expiry_t *);
void ide_execute_command(ide_drive_t *, u8, ide_handler_t *, unsigned int,
ide_expiry_t *);
@@ -1169,13 +1156,14 @@ int ide_busy_sleep(ide_hwif_t *, unsigned long, int);
int ide_wait_stat(ide_startstop_t *, ide_drive_t *, u8, u8, unsigned long);
+ide_startstop_t ide_do_park_unpark(ide_drive_t *, struct request *);
+ide_startstop_t ide_do_devset(ide_drive_t *, struct request *);
+
extern ide_startstop_t ide_do_reset (ide_drive_t *);
extern int ide_devset_execute(ide_drive_t *drive,
const struct ide_devset *setting, int arg);
-extern void ide_do_drive_cmd(ide_drive_t *, struct request *);
-
extern void ide_end_drive_cmd(ide_drive_t *, u8, u8);
void ide_tf_dump(const char *, struct ide_taskfile *);
@@ -1200,10 +1188,6 @@ void SELECT_MASK(ide_drive_t *, int);
u8 ide_read_error(ide_drive_t *);
void ide_read_bcount_and_ireason(ide_drive_t *, u16 *, u8 *);
-extern int drive_is_ready(ide_drive_t *);
-
-void ide_pktcmd_tf_load(ide_drive_t *, u32, u16, u8);
-
int ide_check_atapi_device(ide_drive_t *, const char *);
void ide_init_pc(struct ide_atapi_pc *);
@@ -1251,6 +1235,8 @@ int ide_no_data_taskfile(ide_drive_t *, ide_task_t *);
int ide_taskfile_ioctl(ide_drive_t *, unsigned int, unsigned long);
+int ide_dev_read_id(ide_drive_t *, u8, u16 *);
+
extern int ide_driveid_update(ide_drive_t *);
extern int ide_config_drive_speed(ide_drive_t *, u8);
extern u8 eighty_ninty_three (ide_drive_t *);
@@ -1280,7 +1266,7 @@ static inline int ide_pci_is_in_compatibility_mode(struct pci_dev *dev)
return 0;
}
-void ide_pci_setup_ports(struct pci_dev *, const struct ide_port_info *, int,
+void ide_pci_setup_ports(struct pci_dev *, const struct ide_port_info *,
hw_regs_t *, hw_regs_t **);
void ide_setup_pci_noise(struct pci_dev *, const struct ide_port_info *);
@@ -1349,10 +1335,6 @@ enum {
IDE_HFLAG_ERROR_STOPS_FIFO = (1 << 19),
/* serialize ports */
IDE_HFLAG_SERIALIZE = (1 << 20),
- /* use legacy IRQs */
- IDE_HFLAG_LEGACY_IRQS = (1 << 21),
- /* force use of legacy IRQs */
- IDE_HFLAG_FORCE_LEGACY_IRQS = (1 << 22),
/* host is TRM290 */
IDE_HFLAG_TRM290 = (1 << 23),
/* use 32-bit I/O ops */
@@ -1380,7 +1362,7 @@ enum {
struct ide_port_info {
char *name;
- unsigned int (*init_chipset)(struct pci_dev *);
+ int (*init_chipset)(struct pci_dev *);
void (*init_iops)(ide_hwif_t *);
void (*init_hwif)(ide_hwif_t *);
int (*init_dma)(ide_hwif_t *,
@@ -1471,6 +1453,7 @@ static inline int config_drive_for_dma(ide_drive_t *drive) { return 0; }
void ide_dma_lost_irq(ide_drive_t *);
void ide_dma_timeout(ide_drive_t *);
+ide_startstop_t ide_dma_timeout_retry(ide_drive_t *, int);
#else
static inline int ide_id_dma_bug(ide_drive_t *drive) { return 0; }
@@ -1482,21 +1465,24 @@ static inline void ide_dma_on(ide_drive_t *drive) { ; }
static inline void ide_dma_verbose(ide_drive_t *drive) { ; }
static inline int ide_set_dma(ide_drive_t *drive) { return 1; }
static inline void ide_check_dma_crc(ide_drive_t *drive) { ; }
+static inline ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error) { return ide_stopped; }
static inline void ide_release_dma_engine(ide_hwif_t *hwif) { ; }
#endif /* CONFIG_BLK_DEV_IDEDMA */
#ifdef CONFIG_BLK_DEV_IDEACPI
+int ide_acpi_init(void);
extern int ide_acpi_exec_tfs(ide_drive_t *drive);
extern void ide_acpi_get_timing(ide_hwif_t *hwif);
extern void ide_acpi_push_timing(ide_hwif_t *hwif);
-extern void ide_acpi_init(ide_hwif_t *hwif);
+void ide_acpi_init_port(ide_hwif_t *);
void ide_acpi_port_init_devices(ide_hwif_t *);
extern void ide_acpi_set_state(ide_hwif_t *hwif, int on);
#else
+static inline int ide_acpi_init(void) { return 0; }
static inline int ide_acpi_exec_tfs(ide_drive_t *drive) { return 0; }
static inline void ide_acpi_get_timing(ide_hwif_t *hwif) { ; }
static inline void ide_acpi_push_timing(ide_hwif_t *hwif) { ; }
-static inline void ide_acpi_init(ide_hwif_t *hwif) { ; }
+static inline void ide_acpi_init_port(ide_hwif_t *hwif) { ; }
static inline void ide_acpi_port_init_devices(ide_hwif_t *hwif) { ; }
static inline void ide_acpi_set_state(ide_hwif_t *hwif, int on) {}
#endif
@@ -1530,9 +1516,7 @@ static inline void ide_set_hwifdata (ide_hwif_t * hwif, void *data)
hwif->hwif_data = data;
}
-const char *ide_xfer_verbose(u8 mode);
extern void ide_toggle_bounce(ide_drive_t *drive, int on);
-extern int ide_set_xfer_rate(ide_drive_t *drive, u8 rate);
u64 ide_get_lba_addr(struct ide_taskfile *, int);
u8 ide_dump_status(ide_drive_t *, const char *, u8);
@@ -1571,14 +1555,18 @@ void ide_timing_merge(struct ide_timing *, struct ide_timing *,
struct ide_timing *, unsigned int);
int ide_timing_compute(ide_drive_t *, u8, struct ide_timing *, int, int);
+#ifdef CONFIG_IDE_XFER_MODE
int ide_scan_pio_blacklist(char *);
-
+const char *ide_xfer_verbose(u8);
u8 ide_get_best_pio_mode(ide_drive_t *, u8, u8);
-
int ide_set_pio_mode(ide_drive_t *, u8);
int ide_set_dma_mode(ide_drive_t *, u8);
-
void ide_set_pio(ide_drive_t *, u8);
+int ide_set_xfer_rate(ide_drive_t *, u8);
+#else
+static inline void ide_set_pio(ide_drive_t *drive, u8 pio) { ; }
+static inline int ide_set_xfer_rate(ide_drive_t *drive, u8 rate) { return -1; }
+#endif
static inline void ide_set_max_pio(ide_drive_t *drive)
{
@@ -1611,6 +1599,10 @@ static inline ide_drive_t *ide_get_pair_dev(ide_drive_t *drive)
#define ide_port_for_each_dev(i, dev, port) \
for ((i) = 0; ((dev) = (port)->devices[i]) || (i) < MAX_DRIVES; (i)++)
+#define ide_port_for_each_present_dev(i, dev, port) \
+ for ((i) = 0; ((dev) = (port)->devices[i]) || (i) < MAX_DRIVES; (i)++) \
+ if ((dev)->dev_flags & IDE_DFLAG_PRESENT)
+
#define ide_host_for_each_port(i, port, host) \
for ((i) = 0; ((port) = (host)->ports[i]) || (i) < MAX_HOST_PORTS; (i)++)
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [git pull] IDE updates part 1
@ 2009-06-10 21:35 Bartlomiej Zolnierkiewicz
0 siblings, 0 replies; 3+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2009-06-10 21:35 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Andrew Morton, Stephen Rothwell, linux-ide, linux-kernel
Hi,
Mostly fixes/cleanups for ATAPI support from Tejun and Borislav
(block layer change has been acked by Jens).
Linus, please pull from 'for-2.6.31' branch of:
master.kernel.org:/pub/scm/linux/kernel/git/bart/ide-2.6.git for-2.6.31
to receive the following updates:
block/blk-core.c | 10 +-
drivers/ide/alim15x3.c | 10 +-
drivers/ide/ide-atapi.c | 168 +++++++----
drivers/ide/ide-cd.c | 88 ++----
drivers/ide/ide-cd.h | 4 -
drivers/ide/ide-disk.c | 1 -
drivers/ide/ide-dma.c | 20 +-
drivers/ide/ide-floppy.c | 24 +-
drivers/ide/ide-io.c | 14 +-
drivers/ide/ide-ioctls.c | 1 -
drivers/ide/ide-park.c | 7 +-
drivers/ide/ide-pm.c | 38 +--
drivers/ide/ide-tape.c | 734 ++++++++++----------------------------------
drivers/ide/ide-taskfile.c | 18 +-
include/linux/ide.h | 27 +-
15 files changed, 369 insertions(+), 795 deletions(-)
Anton Vorontsov (1):
alim15x3: Remove historical hacks, re-enable init_hwif for PowerPC
Bartlomiej Zolnierkiewicz (5):
Merge branch 'for-linus' into for-next
Merge branch 'for-linus' into for-next
Merge branch 'for-linus' into for-next
Merge branch 'for-linus' into for-next
Merge branch 'for-2.6.31' into 2.6.30
Borislav Petkov (3):
ide: add helpers for preparing sense requests
ide-cd: convert to using generic sense request
ide-atapi: convert ide-{floppy,tape} to using preallocated sense buffer
Mark de Wever (1):
ide-tape: fix debug call
Tejun Heo (23):
block: clear req->errors on bio completion only for fs requests
ide-tape: remove back-to-back REQUEST_SENSE detection
ide: use blk_run_queue() instead of blk_start_queueing()
ide: don't set REQ_SOFTBARRIER
ide kill unused ide_cmd->special
ide-cd: clear sense buffer before issuing request sense
ide-floppy: block pc always uses bio
ide-taskfile: don't abuse rq->buffer
ide-atapi: don't abuse rq->buffer
ide-cd: don't abuse rq->buffer
ide-cd,atapi: use bio for internal commands
ide-pm: don't abuse rq->data
ide-tape,floppy: fix failed command completion after request sense
ide-atapi,tape,floppy: allow ->pc_callback() to change rq->data_len
ide-tape: use single continuous buffer
ide-tape: use standard data transfer mechanism
ide-tape: kill idetape_bh
ide-tape: unify r/w init paths
ide-tape: use byte size instead of sectors on rw issue functions
ide-tape: simplify read/write functions
ide-atapi: kill unused fields and callbacks
ide: drop rq->data handling from ide_map_sg()
ide-dma: don't reset request fields on dma_timeout_retry()
diff --git a/block/blk-core.c b/block/blk-core.c
index c89883b..4bc34b6 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -1741,10 +1741,14 @@ static int __end_that_request_first(struct request *req, int error,
trace_block_rq_complete(req->q, req);
/*
- * for a REQ_TYPE_BLOCK_PC request, we want to carry any eventual
- * sense key with us all the way through
+ * For fs requests, rq is just carrier of independent bio's
+ * and each partial completion should be handled separately.
+ * Reset per-request error on each partial completion.
+ *
+ * TODO: tj: This is too subtle. It would be better to let
+ * low level drivers do what they see fit.
*/
- if (!blk_pc_request(req))
+ if (blk_fs_request(req))
req->errors = 0;
if (error && (blk_fs_request(req) && !(req->cmd_flags & REQ_QUIET))) {
diff --git a/drivers/ide/alim15x3.c b/drivers/ide/alim15x3.c
index 537da1c..e59b6de 100644
--- a/drivers/ide/alim15x3.c
+++ b/drivers/ide/alim15x3.c
@@ -402,27 +402,23 @@ static u8 ali_cable_detect(ide_hwif_t *hwif)
return cbl;
}
-#if !defined(CONFIG_SPARC64) && !defined(CONFIG_PPC)
+#ifndef CONFIG_SPARC64
/**
* init_hwif_ali15x3 - Initialize the ALI IDE x86 stuff
* @hwif: interface to configure
*
* Obtain the IRQ tables for an ALi based IDE solution on the PC
* class platforms. This part of the code isn't applicable to the
- * Sparc and PowerPC systems.
+ * Sparc systems.
*/
static void __devinit init_hwif_ali15x3 (ide_hwif_t *hwif)
{
- struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 ideic, inmir;
s8 irq_routing_table[] = { -1, 9, 3, 10, 4, 5, 7, 6,
1, 11, 0, 12, 0, 14, 0, 15 };
int irq = -1;
- if (dev->device == PCI_DEVICE_ID_AL_M5229)
- hwif->irq = hwif->channel ? 15 : 14;
-
if (isa_dev) {
/*
* read IDE interface control
@@ -455,7 +451,7 @@ static void __devinit init_hwif_ali15x3 (ide_hwif_t *hwif)
}
#else
#define init_hwif_ali15x3 NULL
-#endif /* !defined(CONFIG_SPARC64) && !defined(CONFIG_PPC) */
+#endif /* CONFIG_SPARC64 */
/**
* init_dma_ali15x3 - set up DMA on ALi15x3
diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c
index 7201b17..afe5a43 100644
--- a/drivers/ide/ide-atapi.c
+++ b/drivers/ide/ide-atapi.c
@@ -80,34 +80,6 @@ void ide_init_pc(struct ide_atapi_pc *pc)
EXPORT_SYMBOL_GPL(ide_init_pc);
/*
- * Generate a new packet command request in front of the request queue, before
- * the current request, so that it will be processed immediately, on the next
- * pass through the driver.
- */
-static void ide_queue_pc_head(ide_drive_t *drive, struct gendisk *disk,
- struct ide_atapi_pc *pc, struct request *rq)
-{
- blk_rq_init(NULL, rq);
- rq->cmd_type = REQ_TYPE_SPECIAL;
- rq->cmd_flags |= REQ_PREEMPT;
- rq->buffer = (char *)pc;
- rq->rq_disk = disk;
-
- if (pc->req_xfer) {
- rq->data = pc->buf;
- rq->data_len = pc->req_xfer;
- }
-
- memcpy(rq->cmd, pc->c, 12);
- if (drive->media == ide_tape)
- rq->cmd[13] = REQ_IDETAPE_PC1;
-
- drive->hwif->rq = NULL;
-
- elv_add_request(drive->queue, rq, ELEVATOR_INSERT_FRONT, 0);
-}
-
-/*
* Add a special packet command request to the tail of the request queue,
* and wait for it to be serviced.
*/
@@ -119,19 +91,21 @@ int ide_queue_pc_tail(ide_drive_t *drive, struct gendisk *disk,
rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
rq->cmd_type = REQ_TYPE_SPECIAL;
- rq->buffer = (char *)pc;
+ rq->special = (char *)pc;
if (pc->req_xfer) {
- rq->data = pc->buf;
- rq->data_len = pc->req_xfer;
+ error = blk_rq_map_kern(drive->queue, rq, pc->buf, pc->req_xfer,
+ GFP_NOIO);
+ if (error)
+ goto put_req;
}
memcpy(rq->cmd, pc->c, 12);
if (drive->media == ide_tape)
rq->cmd[13] = REQ_IDETAPE_PC1;
error = blk_execute_rq(drive->queue, disk, rq, 0);
+put_req:
blk_put_request(rq);
-
return error;
}
EXPORT_SYMBOL_GPL(ide_queue_pc_tail);
@@ -191,20 +165,103 @@ void ide_create_request_sense_cmd(ide_drive_t *drive, struct ide_atapi_pc *pc)
}
EXPORT_SYMBOL_GPL(ide_create_request_sense_cmd);
+void ide_prep_sense(ide_drive_t *drive, struct request *rq)
+{
+ struct request_sense *sense = &drive->sense_data;
+ struct request *sense_rq = &drive->sense_rq;
+ unsigned int cmd_len, sense_len;
+ int err;
+
+ debug_log("%s: enter\n", __func__);
+
+ switch (drive->media) {
+ case ide_floppy:
+ cmd_len = 255;
+ sense_len = 18;
+ break;
+ case ide_tape:
+ cmd_len = 20;
+ sense_len = 20;
+ break;
+ default:
+ cmd_len = 18;
+ sense_len = 18;
+ }
+
+ BUG_ON(sense_len > sizeof(*sense));
+
+ if (blk_sense_request(rq) || drive->sense_rq_armed)
+ return;
+
+ memset(sense, 0, sizeof(*sense));
+
+ blk_rq_init(rq->q, sense_rq);
+
+ err = blk_rq_map_kern(drive->queue, sense_rq, sense, sense_len,
+ GFP_NOIO);
+ if (unlikely(err)) {
+ if (printk_ratelimit())
+ printk(KERN_WARNING "%s: failed to map sense buffer\n",
+ drive->name);
+ return;
+ }
+
+ sense_rq->rq_disk = rq->rq_disk;
+ sense_rq->cmd[0] = GPCMD_REQUEST_SENSE;
+ sense_rq->cmd[4] = cmd_len;
+ sense_rq->cmd_type = REQ_TYPE_SENSE;
+ sense_rq->cmd_flags |= REQ_PREEMPT;
+
+ if (drive->media == ide_tape)
+ sense_rq->cmd[13] = REQ_IDETAPE_PC1;
+
+ drive->sense_rq_armed = true;
+}
+EXPORT_SYMBOL_GPL(ide_prep_sense);
+
+int ide_queue_sense_rq(ide_drive_t *drive, void *special)
+{
+ /* deferred failure from ide_prep_sense() */
+ if (!drive->sense_rq_armed) {
+ printk(KERN_WARNING "%s: failed queue sense request\n",
+ drive->name);
+ return -ENOMEM;
+ }
+
+ drive->sense_rq.special = special;
+ drive->sense_rq_armed = false;
+
+ drive->hwif->rq = NULL;
+
+ elv_add_request(drive->queue, &drive->sense_rq,
+ ELEVATOR_INSERT_FRONT, 0);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ide_queue_sense_rq);
+
/*
* Called when an error was detected during the last packet command.
- * We queue a request sense packet command in the head of the request list.
+ * We queue a request sense packet command at the head of the request
+ * queue.
*/
-void ide_retry_pc(ide_drive_t *drive, struct gendisk *disk)
+void ide_retry_pc(ide_drive_t *drive)
{
- struct request *rq = &drive->request_sense_rq;
+ struct request *sense_rq = &drive->sense_rq;
struct ide_atapi_pc *pc = &drive->request_sense_pc;
(void)ide_read_error(drive);
- ide_create_request_sense_cmd(drive, pc);
+
+ /* init pc from sense_rq */
+ ide_init_pc(pc);
+ memcpy(pc->c, sense_rq->cmd, 12);
+ pc->buf = bio_data(sense_rq->bio); /* pointer to mapped address */
+ pc->req_xfer = sense_rq->data_len;
+
if (drive->media == ide_tape)
set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags);
- ide_queue_pc_head(drive, disk, pc, rq);
+
+ if (ide_queue_sense_rq(drive, pc))
+ ide_complete_rq(drive, -EIO, blk_rq_bytes(drive->hwif->rq));
}
EXPORT_SYMBOL_GPL(ide_retry_pc);
@@ -276,7 +333,6 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
struct ide_cmd *cmd = &hwif->cmd;
struct request *rq = hwif->rq;
const struct ide_tp_ops *tp_ops = hwif->tp_ops;
- xfer_func_t *xferfunc;
unsigned int timeout, done;
u16 bcount;
u8 stat, ireason, dsc = 0;
@@ -303,11 +359,8 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
drive->name, rq_data_dir(pc->rq)
? "write" : "read");
pc->flags |= PC_FLAG_DMA_ERROR;
- } else {
+ } else
pc->xferred = pc->req_xfer;
- if (drive->pc_update_buffers)
- drive->pc_update_buffers(drive, pc);
- }
debug_log("%s: DMA finished\n", drive->name);
}
@@ -343,7 +396,7 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
debug_log("[cmd %x]: check condition\n", rq->cmd[0]);
/* Retry operation */
- ide_retry_pc(drive, rq->rq_disk);
+ ide_retry_pc(drive);
/* queued, but not started */
return ide_stopped;
@@ -353,6 +406,12 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) && (stat & ATA_DSC) == 0)
dsc = 1;
+ /*
+ * ->pc_callback() might change rq->data_len for
+ * residual count, cache total length.
+ */
+ done = blk_rq_bytes(rq);
+
/* Command finished - Call the callback function */
uptodate = drive->pc_callback(drive, dsc);
@@ -361,7 +420,6 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
if (blk_special_request(rq)) {
rq->errors = 0;
- done = blk_rq_bytes(rq);
error = 0;
} else {
@@ -370,11 +428,6 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
rq->errors = -EIO;
}
- if (drive->media == ide_tape)
- done = ide_rq_bytes(rq); /* FIXME */
- else
- done = blk_rq_bytes(rq);
-
error = uptodate ? 0 : -EIO;
}
@@ -407,21 +460,11 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
return ide_do_reset(drive);
}
- xferfunc = write ? tp_ops->output_data : tp_ops->input_data;
-
- if (drive->media == ide_floppy && pc->buf == NULL) {
- done = min_t(unsigned int, bcount, cmd->nleft);
- ide_pio_bytes(drive, cmd, write, done);
- } else if (drive->media == ide_tape && pc->bh) {
- done = drive->pc_io_buffers(drive, pc, bcount, write);
- } else {
- done = min_t(unsigned int, bcount, pc->req_xfer - pc->xferred);
- xferfunc(drive, NULL, pc->cur_pos, done);
- }
+ done = min_t(unsigned int, bcount, cmd->nleft);
+ ide_pio_bytes(drive, cmd, write, done);
- /* Update the current position */
+ /* Update transferred byte count */
pc->xferred += done;
- pc->cur_pos += done;
bcount -= done;
@@ -599,7 +642,6 @@ ide_startstop_t ide_issue_pc(ide_drive_t *drive, struct ide_cmd *cmd)
/* We haven't transferred any data yet */
pc->xferred = 0;
- pc->cur_pos = pc->buf;
valid_tf = IDE_VALID_DEVICE;
bcount = ((drive->media == ide_tape) ?
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 925eb9e..a75e4ee 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -206,54 +206,25 @@ static void cdrom_analyze_sense_data(ide_drive_t *drive,
ide_cd_log_error(drive->name, failed_command, sense);
}
-static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
- struct request *failed_command)
-{
- struct cdrom_info *info = drive->driver_data;
- struct request *rq = &drive->request_sense_rq;
-
- ide_debug_log(IDE_DBG_SENSE, "enter");
-
- if (sense == NULL)
- sense = &info->sense_data;
-
- /* stuff the sense request in front of our current request */
- blk_rq_init(NULL, rq);
- rq->cmd_type = REQ_TYPE_ATA_PC;
- rq->rq_disk = info->disk;
-
- rq->data = sense;
- rq->cmd[0] = GPCMD_REQUEST_SENSE;
- rq->cmd[4] = 18;
- rq->data_len = 18;
-
- rq->cmd_type = REQ_TYPE_SENSE;
- rq->cmd_flags |= REQ_PREEMPT;
-
- /* NOTE! Save the failed command in "rq->buffer" */
- rq->buffer = (void *) failed_command;
-
- if (failed_command)
- ide_debug_log(IDE_DBG_SENSE, "failed_cmd: 0x%x",
- failed_command->cmd[0]);
-
- drive->hwif->rq = NULL;
-
- elv_add_request(drive->queue, rq, ELEVATOR_INSERT_FRONT, 0);
-}
-
static void ide_cd_complete_failed_rq(ide_drive_t *drive, struct request *rq)
{
/*
- * For REQ_TYPE_SENSE, "rq->buffer" points to the original
- * failed request
+ * For REQ_TYPE_SENSE, "rq->special" points to the original
+ * failed request. Also, the sense data should be read
+ * directly from rq which might be different from the original
+ * sense buffer if it got copied during mapping.
*/
- struct request *failed = (struct request *)rq->buffer;
- struct cdrom_info *info = drive->driver_data;
- void *sense = &info->sense_data;
+ struct request *failed = (struct request *)rq->special;
+ void *sense = bio_data(rq->bio);
if (failed) {
if (failed->sense) {
+ /*
+ * Sense is always read into drive->sense_data.
+ * Copy back if the failed request has its
+ * sense pointer set.
+ */
+ memcpy(failed->sense, sense, 18);
sense = failed->sense;
failed->sense_len = rq->sense_len;
}
@@ -428,7 +399,7 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat)
/* if we got a CHECK_CONDITION status, queue a request sense command */
if (stat & ATA_ERR)
- cdrom_queue_request_sense(drive, NULL, NULL);
+ return ide_queue_sense_rq(drive, NULL) ? 2 : 1;
return 1;
end_request:
@@ -442,8 +413,7 @@ end_request:
hwif->rq = NULL;
- cdrom_queue_request_sense(drive, rq->sense, rq);
- return 1;
+ return ide_queue_sense_rq(drive, rq) ? 2 : 1;
} else
return 2;
}
@@ -503,14 +473,8 @@ static void ide_cd_request_sense_fixup(ide_drive_t *drive, struct ide_cmd *cmd)
* and some drives don't send them. Sigh.
*/
if (rq->cmd[0] == GPCMD_REQUEST_SENSE &&
- cmd->nleft > 0 && cmd->nleft <= 5) {
- unsigned int ofs = cmd->nbytes - cmd->nleft;
-
- while (cmd->nleft > 0) {
- *((u8 *)rq->data + ofs++) = 0;
- cmd->nleft--;
- }
- }
+ cmd->nleft > 0 && cmd->nleft <= 5)
+ cmd->nleft = 0;
}
int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd,
@@ -543,8 +507,12 @@ int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd,
rq->cmd_flags |= cmd_flags;
rq->timeout = timeout;
if (buffer) {
- rq->data = buffer;
- rq->data_len = *bufflen;
+ error = blk_rq_map_kern(drive->queue, rq, buffer,
+ *bufflen, GFP_NOIO);
+ if (error) {
+ blk_put_request(rq);
+ return error;
+ }
}
error = blk_execute_rq(drive->queue, info->disk, rq, 0);
@@ -838,15 +806,10 @@ static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
drive->dma = 0;
/* sg request */
- if (rq->bio || ((rq->cmd_type == REQ_TYPE_ATA_PC) && rq->data_len)) {
+ if (rq->bio) {
struct request_queue *q = drive->queue;
+ char *buf = bio_data(rq->bio);
unsigned int alignment;
- char *buf;
-
- if (rq->bio)
- buf = bio_data(rq->bio);
- else
- buf = rq->data;
drive->dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
@@ -896,6 +859,9 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
goto out_end;
}
+ /* prepare sense request for this command */
+ ide_prep_sense(drive, rq);
+
memset(&cmd, 0, sizeof(cmd));
if (rq_data_dir(rq))
diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h
index 1d97101..93a3cf1 100644
--- a/drivers/ide/ide-cd.h
+++ b/drivers/ide/ide-cd.h
@@ -87,10 +87,6 @@ struct cdrom_info {
struct atapi_toc *toc;
- /* The result of the last successful request sense command
- on this device. */
- struct request_sense sense_data;
-
u8 max_speed; /* Max speed of the drive. */
u8 current_speed; /* Current speed of the drive. */
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index a9fbe2c..c243880 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -411,7 +411,6 @@ static void idedisk_prepare_flush(struct request_queue *q, struct request *rq)
cmd->protocol = ATA_PROT_NODATA;
rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
- rq->cmd_flags |= REQ_SOFTBARRIER;
rq->special = cmd;
}
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index a0b8cab..d9123ec 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -510,23 +510,11 @@ ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
/*
* un-busy drive etc and make sure request is sane
*/
-
rq = hwif->rq;
- if (!rq)
- goto out;
-
- hwif->rq = NULL;
-
- rq->errors = 0;
-
- if (!rq->bio)
- goto out;
-
- rq->sector = rq->bio->bi_sector;
- rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9;
- rq->hard_cur_sectors = rq->current_nr_sectors;
- rq->buffer = bio_data(rq->bio);
-out:
+ if (rq) {
+ hwif->rq = NULL;
+ rq->errors = 0;
+ }
return ret;
}
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index 2b4868d..537b7c5 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -134,13 +134,17 @@ static ide_startstop_t ide_floppy_issue_pc(ide_drive_t *drive,
drive->pc = pc;
if (pc->retries > IDEFLOPPY_MAX_PC_RETRIES) {
+ unsigned int done = blk_rq_bytes(drive->hwif->rq);
+
if (!(pc->flags & PC_FLAG_SUPPRESS_ERROR))
ide_floppy_report_error(floppy, pc);
+
/* Giving up */
pc->error = IDE_DRV_ERROR_GENERAL;
drive->failed_pc = NULL;
drive->pc_callback(drive, 0);
+ ide_complete_rq(drive, -EIO, done);
return ide_stopped;
}
@@ -216,15 +220,13 @@ static void idefloppy_blockpc_cmd(struct ide_disk_obj *floppy,
ide_init_pc(pc);
memcpy(pc->c, rq->cmd, sizeof(pc->c));
pc->rq = rq;
- if (rq->data_len && rq_data_dir(rq) == WRITE)
- pc->flags |= PC_FLAG_WRITING;
- pc->buf = rq->data;
- if (rq->bio)
+ if (rq->data_len) {
pc->flags |= PC_FLAG_DMA_OK;
- /*
- * possibly problematic, doesn't look like ide-floppy correctly
- * handled scattered requests if dma fails...
- */
+ if (rq_data_dir(rq) == WRITE)
+ pc->flags |= PC_FLAG_WRITING;
+ }
+ /* pio will be performed by ide_pio_bytes() which handles sg fine */
+ pc->buf = NULL;
pc->req_xfer = pc->buf_size = rq->data_len;
}
@@ -265,8 +267,8 @@ static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive,
}
pc = &floppy->queued_pc;
idefloppy_create_rw_cmd(drive, pc, rq, (unsigned long)block);
- } else if (blk_special_request(rq)) {
- pc = (struct ide_atapi_pc *) rq->buffer;
+ } else if (blk_special_request(rq) || blk_sense_request(rq)) {
+ pc = (struct ide_atapi_pc *)rq->special;
} else if (blk_pc_request(rq)) {
pc = &floppy->queued_pc;
idefloppy_blockpc_cmd(floppy, pc, rq);
@@ -275,6 +277,8 @@ static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive,
goto out_end;
}
+ ide_prep_sense(drive, rq);
+
memset(&cmd, 0, sizeof(cmd));
if (rq_data_dir(rq))
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index 6415a2e..41d8040 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -248,14 +248,7 @@ void ide_map_sg(ide_drive_t *drive, struct ide_cmd *cmd)
struct scatterlist *sg = hwif->sg_table;
struct request *rq = cmd->rq;
- if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
- sg_init_one(sg, rq->buffer, rq->nr_sectors * SECTOR_SIZE);
- cmd->sg_nents = 1;
- } else if (!rq->bio) {
- sg_init_one(sg, rq->data, rq->data_len);
- cmd->sg_nents = 1;
- } else
- cmd->sg_nents = blk_rq_map_sg(drive->queue, rq, sg);
+ cmd->sg_nents = blk_rq_map_sg(drive->queue, rq, sg);
}
EXPORT_SYMBOL_GPL(ide_map_sg);
@@ -371,7 +364,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE)
return execute_drive_cmd(drive, rq);
else if (blk_pm_request(rq)) {
- struct request_pm_state *pm = rq->data;
+ struct request_pm_state *pm = rq->special;
#ifdef DEBUG_PM
printk("%s: start_power_step(step: %d)\n",
drive->name, pm->pm_step);
@@ -484,6 +477,9 @@ void do_ide_request(struct request_queue *q)
spin_unlock_irq(q->queue_lock);
+ /* HLD do_request() callback might sleep, make sure it's okay */
+ might_sleep();
+
if (ide_lock_host(host, hwif))
goto plug_device_2;
diff --git a/drivers/ide/ide-ioctls.c b/drivers/ide/ide-ioctls.c
index c1c25eb..5991b23 100644
--- a/drivers/ide/ide-ioctls.c
+++ b/drivers/ide/ide-ioctls.c
@@ -231,7 +231,6 @@ static int generic_drive_reset(ide_drive_t *drive)
rq->cmd_type = REQ_TYPE_SPECIAL;
rq->cmd_len = 1;
rq->cmd[0] = REQ_DRIVE_RESET;
- rq->cmd_flags |= REQ_SOFTBARRIER;
if (blk_execute_rq(drive->queue, NULL, rq, 1))
ret = rq->errors;
blk_put_request(rq);
diff --git a/drivers/ide/ide-park.c b/drivers/ide/ide-park.c
index 310d03f..a914023 100644
--- a/drivers/ide/ide-park.c
+++ b/drivers/ide/ide-park.c
@@ -24,11 +24,8 @@ static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout)
start_queue = 1;
spin_unlock_irq(&hwif->lock);
- if (start_queue) {
- spin_lock_irq(q->queue_lock);
- blk_start_queueing(q);
- spin_unlock_irq(q->queue_lock);
- }
+ if (start_queue)
+ blk_run_queue(q);
return;
}
spin_unlock_irq(&hwif->lock);
diff --git a/drivers/ide/ide-pm.c b/drivers/ide/ide-pm.c
index 0d8a151..ba1488b 100644
--- a/drivers/ide/ide-pm.c
+++ b/drivers/ide/ide-pm.c
@@ -7,7 +7,6 @@ int generic_ide_suspend(struct device *dev, pm_message_t mesg)
ide_hwif_t *hwif = drive->hwif;
struct request *rq;
struct request_pm_state rqpm;
- struct ide_cmd cmd;
int ret;
/* call ACPI _GTM only once */
@@ -15,11 +14,9 @@ int generic_ide_suspend(struct device *dev, pm_message_t mesg)
ide_acpi_get_timing(hwif);
memset(&rqpm, 0, sizeof(rqpm));
- memset(&cmd, 0, sizeof(cmd));
rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
rq->cmd_type = REQ_TYPE_PM_SUSPEND;
- rq->special = &cmd;
- rq->data = &rqpm;
+ rq->special = &rqpm;
rqpm.pm_step = IDE_PM_START_SUSPEND;
if (mesg.event == PM_EVENT_PRETHAW)
mesg.event = PM_EVENT_FREEZE;
@@ -41,7 +38,6 @@ int generic_ide_resume(struct device *dev)
ide_hwif_t *hwif = drive->hwif;
struct request *rq;
struct request_pm_state rqpm;
- struct ide_cmd cmd;
int err;
/* call ACPI _PS0 / _STM only once */
@@ -53,12 +49,10 @@ int generic_ide_resume(struct device *dev)
ide_acpi_exec_tfs(drive);
memset(&rqpm, 0, sizeof(rqpm));
- memset(&cmd, 0, sizeof(cmd));
rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
rq->cmd_type = REQ_TYPE_PM_RESUME;
rq->cmd_flags |= REQ_PREEMPT;
- rq->special = &cmd;
- rq->data = &rqpm;
+ rq->special = &rqpm;
rqpm.pm_step = IDE_PM_START_RESUME;
rqpm.pm_state = PM_EVENT_ON;
@@ -77,7 +71,7 @@ int generic_ide_resume(struct device *dev)
void ide_complete_power_step(ide_drive_t *drive, struct request *rq)
{
- struct request_pm_state *pm = rq->data;
+ struct request_pm_state *pm = rq->special;
#ifdef DEBUG_PM
printk(KERN_INFO "%s: complete_power_step(step: %d)\n",
@@ -107,10 +101,8 @@ void ide_complete_power_step(ide_drive_t *drive, struct request *rq)
ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq)
{
- struct request_pm_state *pm = rq->data;
- struct ide_cmd *cmd = rq->special;
-
- memset(cmd, 0, sizeof(*cmd));
+ struct request_pm_state *pm = rq->special;
+ struct ide_cmd cmd = { };
switch (pm->pm_step) {
case IDE_PM_FLUSH_CACHE: /* Suspend step 1 (flush cache) */
@@ -123,12 +115,12 @@ ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq)
return ide_stopped;
}
if (ata_id_flush_ext_enabled(drive->id))
- cmd->tf.command = ATA_CMD_FLUSH_EXT;
+ cmd.tf.command = ATA_CMD_FLUSH_EXT;
else
- cmd->tf.command = ATA_CMD_FLUSH;
+ cmd.tf.command = ATA_CMD_FLUSH;
goto out_do_tf;
case IDE_PM_STANDBY: /* Suspend step 2 (standby) */
- cmd->tf.command = ATA_CMD_STANDBYNOW1;
+ cmd.tf.command = ATA_CMD_STANDBYNOW1;
goto out_do_tf;
case IDE_PM_RESTORE_PIO: /* Resume step 1 (restore PIO) */
ide_set_max_pio(drive);
@@ -141,7 +133,7 @@ ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq)
ide_complete_power_step(drive, rq);
return ide_stopped;
case IDE_PM_IDLE: /* Resume step 2 (idle) */
- cmd->tf.command = ATA_CMD_IDLEIMMEDIATE;
+ cmd.tf.command = ATA_CMD_IDLEIMMEDIATE;
goto out_do_tf;
case IDE_PM_RESTORE_DMA: /* Resume step 3 (restore DMA) */
/*
@@ -163,11 +155,11 @@ ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq)
return ide_stopped;
out_do_tf:
- cmd->valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
- cmd->valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE;
- cmd->protocol = ATA_PROT_NODATA;
+ cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
+ cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE;
+ cmd.protocol = ATA_PROT_NODATA;
- return do_rw_taskfile(drive, cmd);
+ return do_rw_taskfile(drive, &cmd);
}
/**
@@ -181,7 +173,7 @@ out_do_tf:
void ide_complete_pm_rq(ide_drive_t *drive, struct request *rq)
{
struct request_queue *q = drive->queue;
- struct request_pm_state *pm = rq->data;
+ struct request_pm_state *pm = rq->special;
unsigned long flags;
ide_complete_power_step(drive, rq);
@@ -207,7 +199,7 @@ void ide_complete_pm_rq(ide_drive_t *drive, struct request *rq)
void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
{
- struct request_pm_state *pm = rq->data;
+ struct request_pm_state *pm = rq->special;
if (blk_pm_suspend_request(rq) &&
pm->pm_step == IDE_PM_START_SUSPEND)
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index 3a53e08..203bbea 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -131,13 +131,6 @@ enum {
IDETAPE_DIR_WRITE = (1 << 2),
};
-struct idetape_bh {
- u32 b_size;
- atomic_t b_count;
- struct idetape_bh *b_reqnext;
- char *b_data;
-};
-
/* Tape door status */
#define DOOR_UNLOCKED 0
#define DOOR_LOCKED 1
@@ -219,18 +212,12 @@ typedef struct ide_tape_obj {
/* Data buffer size chosen based on the tape's recommendation */
int buffer_size;
- /* merge buffer */
- struct idetape_bh *merge_bh;
- /* size of the merge buffer */
- int merge_bh_size;
- /* pointer to current buffer head within the merge buffer */
- struct idetape_bh *bh;
- char *b_data;
- int b_count;
-
- int pages_per_buffer;
- /* Wasted space in each stage */
- int excess_bh_size;
+ /* Staging buffer of buffer_size bytes */
+ void *buf;
+ /* The read/write cursor */
+ void *cur;
+ /* The number of valid bytes in buf */
+ size_t valid;
/* Measures average tape speed */
unsigned long avg_time;
@@ -297,84 +284,6 @@ static struct ide_tape_obj *ide_tape_chrdev_get(unsigned int i)
return tape;
}
-static int idetape_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
- unsigned int bcount)
-{
- struct idetape_bh *bh = pc->bh;
- int count;
-
- while (bcount) {
- if (bh == NULL)
- break;
- count = min(
- (unsigned int)(bh->b_size - atomic_read(&bh->b_count)),
- bcount);
- drive->hwif->tp_ops->input_data(drive, NULL, bh->b_data +
- atomic_read(&bh->b_count), count);
- bcount -= count;
- atomic_add(count, &bh->b_count);
- if (atomic_read(&bh->b_count) == bh->b_size) {
- bh = bh->b_reqnext;
- if (bh)
- atomic_set(&bh->b_count, 0);
- }
- }
-
- pc->bh = bh;
-
- return bcount;
-}
-
-static int idetape_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
- unsigned int bcount)
-{
- struct idetape_bh *bh = pc->bh;
- int count;
-
- while (bcount) {
- if (bh == NULL)
- break;
- count = min((unsigned int)pc->b_count, (unsigned int)bcount);
- drive->hwif->tp_ops->output_data(drive, NULL, pc->b_data, count);
- bcount -= count;
- pc->b_data += count;
- pc->b_count -= count;
- if (!pc->b_count) {
- bh = bh->b_reqnext;
- pc->bh = bh;
- if (bh) {
- pc->b_data = bh->b_data;
- pc->b_count = atomic_read(&bh->b_count);
- }
- }
- }
-
- return bcount;
-}
-
-static void idetape_update_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc)
-{
- struct idetape_bh *bh = pc->bh;
- int count;
- unsigned int bcount = pc->xferred;
-
- if (pc->flags & PC_FLAG_WRITING)
- return;
- while (bcount) {
- if (bh == NULL) {
- printk(KERN_ERR "ide-tape: bh == NULL in %s\n",
- __func__);
- return;
- }
- count = min((unsigned int)bh->b_size, (unsigned int)bcount);
- atomic_set(&bh->b_count, count);
- if (atomic_read(&bh->b_count) == bh->b_size)
- bh = bh->b_reqnext;
- bcount -= count;
- }
- pc->bh = bh;
-}
-
/*
* called on each failed packet command retry to analyze the request sense. We
* currently do not utilize this information.
@@ -392,12 +301,10 @@ static void idetape_analyze_error(ide_drive_t *drive, u8 *sense)
pc->c[0], tape->sense_key, tape->asc, tape->ascq);
/* Correct pc->xferred by asking the tape. */
- if (pc->flags & PC_FLAG_DMA_ERROR) {
+ if (pc->flags & PC_FLAG_DMA_ERROR)
pc->xferred = pc->req_xfer -
tape->blk_size *
get_unaligned_be32(&sense[3]);
- idetape_update_buffers(drive, pc);
- }
/*
* If error was the result of a zero-length read or write command,
@@ -436,29 +343,6 @@ static void idetape_analyze_error(ide_drive_t *drive, u8 *sense)
}
}
-/* Free data buffers completely. */
-static void ide_tape_kfree_buffer(idetape_tape_t *tape)
-{
- struct idetape_bh *prev_bh, *bh = tape->merge_bh;
-
- while (bh) {
- u32 size = bh->b_size;
-
- while (size) {
- unsigned int order = fls(size >> PAGE_SHIFT)-1;
-
- if (bh->b_data)
- free_pages((unsigned long)bh->b_data, order);
-
- size &= (order-1);
- bh->b_data += (1 << order) * PAGE_SIZE;
- }
- prev_bh = bh;
- bh = bh->b_reqnext;
- kfree(prev_bh);
- }
-}
-
static void ide_tape_handle_dsc(ide_drive_t *);
static int ide_tape_callback(ide_drive_t *drive, int dsc)
@@ -496,7 +380,7 @@ static int ide_tape_callback(ide_drive_t *drive, int dsc)
}
tape->first_frame += blocks;
- rq->current_nr_sectors -= blocks;
+ rq->data_len -= blocks * tape->blk_size;
if (pc->error) {
uptodate = 0;
@@ -558,19 +442,6 @@ static void ide_tape_handle_dsc(ide_drive_t *drive)
idetape_postpone_request(drive);
}
-static int ide_tape_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
- unsigned int bcount, int write)
-{
- unsigned int bleft;
-
- if (write)
- bleft = idetape_output_buffers(drive, pc, bcount);
- else
- bleft = idetape_input_buffers(drive, pc, bcount);
-
- return bcount - bleft;
-}
-
/*
* Packet Command Interface
*
@@ -622,6 +493,8 @@ static ide_startstop_t ide_tape_issue_pc(ide_drive_t *drive,
if (pc->retries > IDETAPE_MAX_PC_RETRIES ||
(pc->flags & PC_FLAG_ABORT)) {
+ unsigned int done = blk_rq_bytes(drive->hwif->rq);
+
/*
* We will "abort" retrying a packet command in case legitimate
* error code was received (crossing a filemark, or end of the
@@ -641,8 +514,10 @@ static ide_startstop_t ide_tape_issue_pc(ide_drive_t *drive,
/* Giving up */
pc->error = IDE_DRV_ERROR_GENERAL;
}
+
drive->failed_pc = NULL;
drive->pc_callback(drive, 0);
+ ide_complete_rq(drive, -EIO, done);
return ide_stopped;
}
debug_log(DBG_SENSE, "Retry #%d, cmd = %02X\n", pc->retries, pc->c[0]);
@@ -695,7 +570,7 @@ static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive)
printk(KERN_ERR "ide-tape: %s: I/O error, ",
tape->name);
/* Retry operation */
- ide_retry_pc(drive, tape->disk);
+ ide_retry_pc(drive);
return ide_stopped;
}
pc->error = 0;
@@ -711,27 +586,22 @@ static void ide_tape_create_rw_cmd(idetape_tape_t *tape,
struct ide_atapi_pc *pc, struct request *rq,
u8 opcode)
{
- struct idetape_bh *bh = (struct idetape_bh *)rq->special;
- unsigned int length = rq->current_nr_sectors;
+ unsigned int length = rq->nr_sectors;
ide_init_pc(pc);
put_unaligned(cpu_to_be32(length), (unsigned int *) &pc->c[1]);
pc->c[1] = 1;
- pc->bh = bh;
pc->buf = NULL;
pc->buf_size = length * tape->blk_size;
pc->req_xfer = pc->buf_size;
if (pc->req_xfer == tape->buffer_size)
pc->flags |= PC_FLAG_DMA_OK;
- if (opcode == READ_6) {
+ if (opcode == READ_6)
pc->c[0] = READ_6;
- atomic_set(&bh->b_count, 0);
- } else if (opcode == WRITE_6) {
+ else if (opcode == WRITE_6) {
pc->c[0] = WRITE_6;
pc->flags |= PC_FLAG_WRITING;
- pc->b_data = bh->b_data;
- pc->b_count = atomic_read(&bh->b_count);
}
memcpy(rq->cmd, pc->c, 12);
@@ -747,12 +617,10 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
struct ide_cmd cmd;
u8 stat;
- debug_log(DBG_SENSE, "sector: %llu, nr_sectors: %lu,"
- " current_nr_sectors: %u\n",
- (unsigned long long)rq->sector, rq->nr_sectors,
- rq->current_nr_sectors);
+ debug_log(DBG_SENSE, "sector: %llu, nr_sectors: %lu\n",
+ (unsigned long long)rq->sector, rq->nr_sectors);
- if (!blk_special_request(rq)) {
+ if (!(blk_special_request(rq) || blk_sense_request(rq))) {
/* We do not support buffer cache originated requests. */
printk(KERN_NOTICE "ide-tape: %s: Unsupported request in "
"request queue (%d)\n", drive->name, rq->cmd_type);
@@ -828,7 +696,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
goto out;
}
if (rq->cmd[13] & REQ_IDETAPE_PC1) {
- pc = (struct ide_atapi_pc *) rq->buffer;
+ pc = (struct ide_atapi_pc *)rq->special;
rq->cmd[13] &= ~(REQ_IDETAPE_PC1);
rq->cmd[13] |= REQ_IDETAPE_PC2;
goto out;
@@ -840,6 +708,9 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
BUG();
out:
+ /* prepare sense request for this command */
+ ide_prep_sense(drive, rq);
+
memset(&cmd, 0, sizeof(cmd));
if (rq_data_dir(rq))
@@ -847,167 +718,10 @@ out:
cmd.rq = rq;
- return ide_tape_issue_pc(drive, &cmd, pc);
-}
-
-/*
- * The function below uses __get_free_pages to allocate a data buffer of size
- * tape->buffer_size (or a bit more). We attempt to combine sequential pages as
- * much as possible.
- *
- * It returns a pointer to the newly allocated buffer, or NULL in case of
- * failure.
- */
-static struct idetape_bh *ide_tape_kmalloc_buffer(idetape_tape_t *tape,
- int full, int clear)
-{
- struct idetape_bh *prev_bh, *bh, *merge_bh;
- int pages = tape->pages_per_buffer;
- unsigned int order, b_allocd;
- char *b_data = NULL;
-
- merge_bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL);
- bh = merge_bh;
- if (bh == NULL)
- goto abort;
-
- order = fls(pages) - 1;
- bh->b_data = (char *) __get_free_pages(GFP_KERNEL, order);
- if (!bh->b_data)
- goto abort;
- b_allocd = (1 << order) * PAGE_SIZE;
- pages &= (order-1);
-
- if (clear)
- memset(bh->b_data, 0, b_allocd);
- bh->b_reqnext = NULL;
- bh->b_size = b_allocd;
- atomic_set(&bh->b_count, full ? bh->b_size : 0);
-
- while (pages) {
- order = fls(pages) - 1;
- b_data = (char *) __get_free_pages(GFP_KERNEL, order);
- if (!b_data)
- goto abort;
- b_allocd = (1 << order) * PAGE_SIZE;
-
- if (clear)
- memset(b_data, 0, b_allocd);
-
- /* newly allocated page frames below buffer header or ...*/
- if (bh->b_data == b_data + b_allocd) {
- bh->b_size += b_allocd;
- bh->b_data -= b_allocd;
- if (full)
- atomic_add(b_allocd, &bh->b_count);
- continue;
- }
- /* they are above the header */
- if (b_data == bh->b_data + bh->b_size) {
- bh->b_size += b_allocd;
- if (full)
- atomic_add(b_allocd, &bh->b_count);
- continue;
- }
- prev_bh = bh;
- bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL);
- if (!bh) {
- free_pages((unsigned long) b_data, order);
- goto abort;
- }
- bh->b_reqnext = NULL;
- bh->b_data = b_data;
- bh->b_size = b_allocd;
- atomic_set(&bh->b_count, full ? bh->b_size : 0);
- prev_bh->b_reqnext = bh;
-
- pages &= (order-1);
- }
-
- bh->b_size -= tape->excess_bh_size;
- if (full)
- atomic_sub(tape->excess_bh_size, &bh->b_count);
- return merge_bh;
-abort:
- ide_tape_kfree_buffer(tape);
- return NULL;
-}
+ ide_init_sg_cmd(&cmd, pc->req_xfer);
+ ide_map_sg(drive, &cmd);
-static int idetape_copy_stage_from_user(idetape_tape_t *tape,
- const char __user *buf, int n)
-{
- struct idetape_bh *bh = tape->bh;
- int count;
- int ret = 0;
-
- while (n) {
- if (bh == NULL) {
- printk(KERN_ERR "ide-tape: bh == NULL in %s\n",
- __func__);
- return 1;
- }
- count = min((unsigned int)
- (bh->b_size - atomic_read(&bh->b_count)),
- (unsigned int)n);
- if (copy_from_user(bh->b_data + atomic_read(&bh->b_count), buf,
- count))
- ret = 1;
- n -= count;
- atomic_add(count, &bh->b_count);
- buf += count;
- if (atomic_read(&bh->b_count) == bh->b_size) {
- bh = bh->b_reqnext;
- if (bh)
- atomic_set(&bh->b_count, 0);
- }
- }
- tape->bh = bh;
- return ret;
-}
-
-static int idetape_copy_stage_to_user(idetape_tape_t *tape, char __user *buf,
- int n)
-{
- struct idetape_bh *bh = tape->bh;
- int count;
- int ret = 0;
-
- while (n) {
- if (bh == NULL) {
- printk(KERN_ERR "ide-tape: bh == NULL in %s\n",
- __func__);
- return 1;
- }
- count = min(tape->b_count, n);
- if (copy_to_user(buf, tape->b_data, count))
- ret = 1;
- n -= count;
- tape->b_data += count;
- tape->b_count -= count;
- buf += count;
- if (!tape->b_count) {
- bh = bh->b_reqnext;
- tape->bh = bh;
- if (bh) {
- tape->b_data = bh->b_data;
- tape->b_count = atomic_read(&bh->b_count);
- }
- }
- }
- return ret;
-}
-
-static void idetape_init_merge_buffer(idetape_tape_t *tape)
-{
- struct idetape_bh *bh = tape->merge_bh;
- tape->bh = tape->merge_bh;
-
- if (tape->chrdev_dir == IDETAPE_DIR_WRITE)
- atomic_set(&bh->b_count, 0);
- else {
- tape->b_data = bh->b_data;
- tape->b_count = atomic_read(&bh->b_count);
- }
+ return ide_tape_issue_pc(drive, &cmd, pc);
}
/*
@@ -1107,10 +821,10 @@ static void __ide_tape_discard_merge_buffer(ide_drive_t *drive)
return;
clear_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags);
- tape->merge_bh_size = 0;
- if (tape->merge_bh != NULL) {
- ide_tape_kfree_buffer(tape);
- tape->merge_bh = NULL;
+ tape->valid = 0;
+ if (tape->buf != NULL) {
+ kfree(tape->buf);
+ tape->buf = NULL;
}
tape->chrdev_dir = IDETAPE_DIR_NONE;
@@ -1164,36 +878,44 @@ static void ide_tape_discard_merge_buffer(ide_drive_t *drive,
* Generate a read/write request for the block device interface and wait for it
* to be serviced.
*/
-static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int blocks,
- struct idetape_bh *bh)
+static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int size)
{
idetape_tape_t *tape = drive->driver_data;
struct request *rq;
- int ret, errors;
+ int ret;
debug_log(DBG_SENSE, "%s: cmd=%d\n", __func__, cmd);
+ BUG_ON(cmd != REQ_IDETAPE_READ && cmd != REQ_IDETAPE_WRITE);
+ BUG_ON(size < 0 || size % tape->blk_size);
rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
rq->cmd_type = REQ_TYPE_SPECIAL;
rq->cmd[13] = cmd;
rq->rq_disk = tape->disk;
- rq->special = (void *)bh;
rq->sector = tape->first_frame;
- rq->nr_sectors = blocks;
- rq->current_nr_sectors = blocks;
- blk_execute_rq(drive->queue, tape->disk, rq, 0);
- errors = rq->errors;
- ret = tape->blk_size * (blocks - rq->current_nr_sectors);
- blk_put_request(rq);
+ if (size) {
+ ret = blk_rq_map_kern(drive->queue, rq, tape->buf, size,
+ __GFP_WAIT);
+ if (ret)
+ goto out_put;
+ }
- if ((cmd & (REQ_IDETAPE_READ | REQ_IDETAPE_WRITE)) == 0)
- return 0;
+ blk_execute_rq(drive->queue, tape->disk, rq, 0);
- if (tape->merge_bh)
- idetape_init_merge_buffer(tape);
- if (errors == IDE_DRV_ERROR_GENERAL)
- return -EIO;
+ /* calculate the number of transferred bytes and update buffer state */
+ size -= rq->data_len;
+ tape->cur = tape->buf;
+ if (cmd == REQ_IDETAPE_READ)
+ tape->valid = size;
+ else
+ tape->valid = 0;
+
+ ret = size;
+ if (rq->errors == IDE_DRV_ERROR_GENERAL)
+ ret = -EIO;
+out_put:
+ blk_put_request(rq);
return ret;
}
@@ -1230,153 +952,87 @@ static void idetape_create_space_cmd(struct ide_atapi_pc *pc, int count, u8 cmd)
pc->flags |= PC_FLAG_WAIT_FOR_DSC;
}
-/* Queue up a character device originated write request. */
-static int idetape_add_chrdev_write_request(ide_drive_t *drive, int blocks)
-{
- idetape_tape_t *tape = drive->driver_data;
-
- debug_log(DBG_CHRDEV, "Enter %s\n", __func__);
-
- return idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE,
- blocks, tape->merge_bh);
-}
-
static void ide_tape_flush_merge_buffer(ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
- int blocks, min;
- struct idetape_bh *bh;
if (tape->chrdev_dir != IDETAPE_DIR_WRITE) {
printk(KERN_ERR "ide-tape: bug: Trying to empty merge buffer"
" but we are not writing.\n");
return;
}
- if (tape->merge_bh_size > tape->buffer_size) {
- printk(KERN_ERR "ide-tape: bug: merge_buffer too big\n");
- tape->merge_bh_size = tape->buffer_size;
- }
- if (tape->merge_bh_size) {
- blocks = tape->merge_bh_size / tape->blk_size;
- if (tape->merge_bh_size % tape->blk_size) {
- unsigned int i;
-
- blocks++;
- i = tape->blk_size - tape->merge_bh_size %
- tape->blk_size;
- bh = tape->bh->b_reqnext;
- while (bh) {
- atomic_set(&bh->b_count, 0);
- bh = bh->b_reqnext;
- }
- bh = tape->bh;
- while (i) {
- if (bh == NULL) {
- printk(KERN_INFO "ide-tape: bug,"
- " bh NULL\n");
- break;
- }
- min = min(i, (unsigned int)(bh->b_size -
- atomic_read(&bh->b_count)));
- memset(bh->b_data + atomic_read(&bh->b_count),
- 0, min);
- atomic_add(min, &bh->b_count);
- i -= min;
- bh = bh->b_reqnext;
- }
- }
- (void) idetape_add_chrdev_write_request(drive, blocks);
- tape->merge_bh_size = 0;
- }
- if (tape->merge_bh != NULL) {
- ide_tape_kfree_buffer(tape);
- tape->merge_bh = NULL;
+ if (tape->buf) {
+ size_t aligned = roundup(tape->valid, tape->blk_size);
+
+ memset(tape->cur, 0, aligned - tape->valid);
+ idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, aligned);
+ kfree(tape->buf);
+ tape->buf = NULL;
}
tape->chrdev_dir = IDETAPE_DIR_NONE;
}
-static int idetape_init_read(ide_drive_t *drive)
+static int idetape_init_rw(ide_drive_t *drive, int dir)
{
idetape_tape_t *tape = drive->driver_data;
- int bytes_read;
+ int rc;
- /* Initialize read operation */
- if (tape->chrdev_dir != IDETAPE_DIR_READ) {
- if (tape->chrdev_dir == IDETAPE_DIR_WRITE) {
- ide_tape_flush_merge_buffer(drive);
- idetape_flush_tape_buffers(drive);
- }
- if (tape->merge_bh || tape->merge_bh_size) {
- printk(KERN_ERR "ide-tape: merge_bh_size should be"
- " 0 now\n");
- tape->merge_bh_size = 0;
- }
- tape->merge_bh = ide_tape_kmalloc_buffer(tape, 0, 0);
- if (!tape->merge_bh)
- return -ENOMEM;
- tape->chrdev_dir = IDETAPE_DIR_READ;
+ BUG_ON(dir != IDETAPE_DIR_READ && dir != IDETAPE_DIR_WRITE);
- /*
- * Issue a read 0 command to ensure that DSC handshake is
- * switched from completion mode to buffer available mode.
- * No point in issuing this if DSC overlap isn't supported, some
- * drives (Seagate STT3401A) will return an error.
- */
- if (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) {
- bytes_read = idetape_queue_rw_tail(drive,
- REQ_IDETAPE_READ, 0,
- tape->merge_bh);
- if (bytes_read < 0) {
- ide_tape_kfree_buffer(tape);
- tape->merge_bh = NULL;
- tape->chrdev_dir = IDETAPE_DIR_NONE;
- return bytes_read;
- }
- }
- }
+ if (tape->chrdev_dir == dir)
+ return 0;
- return 0;
-}
+ if (tape->chrdev_dir == IDETAPE_DIR_READ)
+ ide_tape_discard_merge_buffer(drive, 1);
+ else if (tape->chrdev_dir == IDETAPE_DIR_WRITE) {
+ ide_tape_flush_merge_buffer(drive);
+ idetape_flush_tape_buffers(drive);
+ }
-/* called from idetape_chrdev_read() to service a chrdev read request. */
-static int idetape_add_chrdev_read_request(ide_drive_t *drive, int blocks)
-{
- idetape_tape_t *tape = drive->driver_data;
+ if (tape->buf || tape->valid) {
+ printk(KERN_ERR "ide-tape: valid should be 0 now\n");
+ tape->valid = 0;
+ }
- debug_log(DBG_PROCS, "Enter %s, %d blocks\n", __func__, blocks);
+ tape->buf = kmalloc(tape->buffer_size, GFP_KERNEL);
+ if (!tape->buf)
+ return -ENOMEM;
+ tape->chrdev_dir = dir;
+ tape->cur = tape->buf;
- /* If we are at a filemark, return a read length of 0 */
- if (test_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags))
- return 0;
-
- idetape_init_read(drive);
+ /*
+ * Issue a 0 rw command to ensure that DSC handshake is
+ * switched from completion mode to buffer available mode. No
+ * point in issuing this if DSC overlap isn't supported, some
+ * drives (Seagate STT3401A) will return an error.
+ */
+ if (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) {
+ int cmd = dir == IDETAPE_DIR_READ ? REQ_IDETAPE_READ
+ : REQ_IDETAPE_WRITE;
+
+ rc = idetape_queue_rw_tail(drive, cmd, 0);
+ if (rc < 0) {
+ kfree(tape->buf);
+ tape->buf = NULL;
+ tape->chrdev_dir = IDETAPE_DIR_NONE;
+ return rc;
+ }
+ }
- return idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, blocks,
- tape->merge_bh);
+ return 0;
}
static void idetape_pad_zeros(ide_drive_t *drive, int bcount)
{
idetape_tape_t *tape = drive->driver_data;
- struct idetape_bh *bh;
- int blocks;
+
+ memset(tape->buf, 0, tape->buffer_size);
while (bcount) {
- unsigned int count;
+ unsigned int count = min(tape->buffer_size, bcount);
- bh = tape->merge_bh;
- count = min(tape->buffer_size, bcount);
+ idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, count);
bcount -= count;
- blocks = count / tape->blk_size;
- while (count) {
- atomic_set(&bh->b_count,
- min(count, (unsigned int)bh->b_size));
- memset(bh->b_data, 0, atomic_read(&bh->b_count));
- count -= atomic_read(&bh->b_count);
- bh = bh->b_reqnext;
- }
- idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, blocks,
- tape->merge_bh);
}
}
@@ -1456,7 +1112,7 @@ static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op,
}
if (tape->chrdev_dir == IDETAPE_DIR_READ) {
- tape->merge_bh_size = 0;
+ tape->valid = 0;
if (test_and_clear_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags))
++count;
ide_tape_discard_merge_buffer(drive, 0);
@@ -1505,9 +1161,9 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf,
{
struct ide_tape_obj *tape = file->private_data;
ide_drive_t *drive = tape->drive;
- ssize_t bytes_read, temp, actually_read = 0, rc;
+ size_t done = 0;
ssize_t ret = 0;
- u16 ctl = *(u16 *)&tape->caps[12];
+ int rc;
debug_log(DBG_CHRDEV, "Enter %s, count %Zd\n", __func__, count);
@@ -1517,49 +1173,43 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf,
(count % tape->blk_size) == 0)
tape->user_bs_factor = count / tape->blk_size;
}
- rc = idetape_init_read(drive);
+
+ rc = idetape_init_rw(drive, IDETAPE_DIR_READ);
if (rc < 0)
return rc;
- if (count == 0)
- return (0);
- if (tape->merge_bh_size) {
- actually_read = min((unsigned int)(tape->merge_bh_size),
- (unsigned int)count);
- if (idetape_copy_stage_to_user(tape, buf, actually_read))
- ret = -EFAULT;
- buf += actually_read;
- tape->merge_bh_size -= actually_read;
- count -= actually_read;
- }
- while (count >= tape->buffer_size) {
- bytes_read = idetape_add_chrdev_read_request(drive, ctl);
- if (bytes_read <= 0)
- goto finish;
- if (idetape_copy_stage_to_user(tape, buf, bytes_read))
- ret = -EFAULT;
- buf += bytes_read;
- count -= bytes_read;
- actually_read += bytes_read;
- }
- if (count) {
- bytes_read = idetape_add_chrdev_read_request(drive, ctl);
- if (bytes_read <= 0)
- goto finish;
- temp = min((unsigned long)count, (unsigned long)bytes_read);
- if (idetape_copy_stage_to_user(tape, buf, temp))
+
+ while (done < count) {
+ size_t todo;
+
+ /* refill if staging buffer is empty */
+ if (!tape->valid) {
+ /* If we are at a filemark, nothing more to read */
+ if (test_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags))
+ break;
+ /* read */
+ if (idetape_queue_rw_tail(drive, REQ_IDETAPE_READ,
+ tape->buffer_size) <= 0)
+ break;
+ }
+
+ /* copy out */
+ todo = min_t(size_t, count - done, tape->valid);
+ if (copy_to_user(buf + done, tape->cur, todo))
ret = -EFAULT;
- actually_read += temp;
- tape->merge_bh_size = bytes_read-temp;
+
+ tape->cur += todo;
+ tape->valid -= todo;
+ done += todo;
}
-finish:
- if (!actually_read && test_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags)) {
+
+ if (!done && test_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags)) {
debug_log(DBG_SENSE, "%s: spacing over filemark\n", tape->name);
idetape_space_over_filemarks(drive, MTFSF, 1);
return 0;
}
- return ret ? ret : actually_read;
+ return ret ? ret : done;
}
static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
@@ -1567,9 +1217,9 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
{
struct ide_tape_obj *tape = file->private_data;
ide_drive_t *drive = tape->drive;
- ssize_t actually_written = 0;
+ size_t done = 0;
ssize_t ret = 0;
- u16 ctl = *(u16 *)&tape->caps[12];
+ int rc;
/* The drive is write protected. */
if (tape->write_prot)
@@ -1578,80 +1228,31 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
debug_log(DBG_CHRDEV, "Enter %s, count %Zd\n", __func__, count);
/* Initialize write operation */
- if (tape->chrdev_dir != IDETAPE_DIR_WRITE) {
- if (tape->chrdev_dir == IDETAPE_DIR_READ)
- ide_tape_discard_merge_buffer(drive, 1);
- if (tape->merge_bh || tape->merge_bh_size) {
- printk(KERN_ERR "ide-tape: merge_bh_size "
- "should be 0 now\n");
- tape->merge_bh_size = 0;
- }
- tape->merge_bh = ide_tape_kmalloc_buffer(tape, 0, 0);
- if (!tape->merge_bh)
- return -ENOMEM;
- tape->chrdev_dir = IDETAPE_DIR_WRITE;
- idetape_init_merge_buffer(tape);
+ rc = idetape_init_rw(drive, IDETAPE_DIR_WRITE);
+ if (rc < 0)
+ return rc;
- /*
- * Issue a write 0 command to ensure that DSC handshake is
- * switched from completion mode to buffer available mode. No
- * point in issuing this if DSC overlap isn't supported, some
- * drives (Seagate STT3401A) will return an error.
- */
- if (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) {
- ssize_t retval = idetape_queue_rw_tail(drive,
- REQ_IDETAPE_WRITE, 0,
- tape->merge_bh);
- if (retval < 0) {
- ide_tape_kfree_buffer(tape);
- tape->merge_bh = NULL;
- tape->chrdev_dir = IDETAPE_DIR_NONE;
- return retval;
- }
- }
- }
- if (count == 0)
- return (0);
- if (tape->merge_bh_size) {
- if (tape->merge_bh_size >= tape->buffer_size) {
- printk(KERN_ERR "ide-tape: bug: merge buf too big\n");
- tape->merge_bh_size = 0;
- }
- actually_written = min((unsigned int)
- (tape->buffer_size - tape->merge_bh_size),
- (unsigned int)count);
- if (idetape_copy_stage_from_user(tape, buf, actually_written))
- ret = -EFAULT;
- buf += actually_written;
- tape->merge_bh_size += actually_written;
- count -= actually_written;
-
- if (tape->merge_bh_size == tape->buffer_size) {
- ssize_t retval;
- tape->merge_bh_size = 0;
- retval = idetape_add_chrdev_write_request(drive, ctl);
- if (retval <= 0)
- return (retval);
- }
- }
- while (count >= tape->buffer_size) {
- ssize_t retval;
- if (idetape_copy_stage_from_user(tape, buf, tape->buffer_size))
- ret = -EFAULT;
- buf += tape->buffer_size;
- count -= tape->buffer_size;
- retval = idetape_add_chrdev_write_request(drive, ctl);
- actually_written += tape->buffer_size;
- if (retval <= 0)
- return (retval);
- }
- if (count) {
- actually_written += count;
- if (idetape_copy_stage_from_user(tape, buf, count))
+ while (done < count) {
+ size_t todo;
+
+ /* flush if staging buffer is full */
+ if (tape->valid == tape->buffer_size &&
+ idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE,
+ tape->buffer_size) <= 0)
+ return rc;
+
+ /* copy in */
+ todo = min_t(size_t, count - done,
+ tape->buffer_size - tape->valid);
+ if (copy_from_user(tape->cur, buf + done, todo))
ret = -EFAULT;
- tape->merge_bh_size += count;
+
+ tape->cur += todo;
+ tape->valid += todo;
+ done += todo;
}
- return ret ? ret : actually_written;
+
+ return ret ? ret : done;
}
static int idetape_write_filemark(ide_drive_t *drive)
@@ -1812,7 +1413,7 @@ static int idetape_chrdev_ioctl(struct inode *inode, struct file *file,
idetape_flush_tape_buffers(drive);
}
if (cmd == MTIOCGET || cmd == MTIOCPOS) {
- block_offset = tape->merge_bh_size /
+ block_offset = tape->valid /
(tape->blk_size * tape->user_bs_factor);
position = idetape_read_position(drive);
if (position < 0)
@@ -1960,12 +1561,12 @@ static void idetape_write_release(ide_drive_t *drive, unsigned int minor)
idetape_tape_t *tape = drive->driver_data;
ide_tape_flush_merge_buffer(drive);
- tape->merge_bh = ide_tape_kmalloc_buffer(tape, 1, 0);
- if (tape->merge_bh != NULL) {
+ tape->buf = kmalloc(tape->buffer_size, GFP_KERNEL);
+ if (tape->buf != NULL) {
idetape_pad_zeros(drive, tape->blk_size *
(tape->user_bs_factor - 1));
- ide_tape_kfree_buffer(tape);
- tape->merge_bh = NULL;
+ kfree(tape->buf);
+ tape->buf = NULL;
}
idetape_write_filemark(drive);
idetape_flush_tape_buffers(drive);
@@ -2159,8 +1760,6 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
u16 *ctl = (u16 *)&tape->caps[12];
drive->pc_callback = ide_tape_callback;
- drive->pc_update_buffers = idetape_update_buffers;
- drive->pc_io_buffers = ide_tape_io_buffers;
drive->dev_flags |= IDE_DFLAG_DSC_OVERLAP;
@@ -2191,11 +1790,6 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
tape->buffer_size = *ctl * tape->blk_size;
}
buffer_size = tape->buffer_size;
- tape->pages_per_buffer = buffer_size / PAGE_SIZE;
- if (buffer_size % PAGE_SIZE) {
- tape->pages_per_buffer++;
- tape->excess_bh_size = PAGE_SIZE - buffer_size % PAGE_SIZE;
- }
/* select the "best" DSC read/write polling freq */
speed = max(*(u16 *)&tape->caps[14], *(u16 *)&tape->caps[8]);
@@ -2238,7 +1832,7 @@ static void ide_tape_release(struct device *dev)
ide_drive_t *drive = tape->drive;
struct gendisk *g = tape->disk;
- BUG_ON(tape->merge_bh_size);
+ BUG_ON(tape->valid);
drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
drive->driver_data = NULL;
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index 4aa6223..f400eb4 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -424,7 +424,9 @@ int ide_raw_taskfile(ide_drive_t *drive, struct ide_cmd *cmd, u8 *buf,
rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
- rq->buffer = buf;
+
+ if (cmd->tf_flags & IDE_TFLAG_WRITE)
+ rq->cmd_flags |= REQ_RW;
/*
* (ks) We transfer currently only whole sectors.
@@ -432,18 +434,20 @@ int ide_raw_taskfile(ide_drive_t *drive, struct ide_cmd *cmd, u8 *buf,
* if we would find a solution to transfer any size.
* To support special commands like READ LONG.
*/
- rq->hard_nr_sectors = rq->nr_sectors = nsect;
- rq->hard_cur_sectors = rq->current_nr_sectors = nsect;
-
- if (cmd->tf_flags & IDE_TFLAG_WRITE)
- rq->cmd_flags |= REQ_RW;
+ if (nsect) {
+ error = blk_rq_map_kern(drive->queue, rq, buf,
+ nsect * SECTOR_SIZE, __GFP_WAIT);
+ if (error)
+ goto put_req;
+ }
rq->special = cmd;
cmd->rq = rq;
error = blk_execute_rq(drive->queue, NULL, rq, 0);
- blk_put_request(rq);
+put_req:
+ blk_put_request(rq);
return error;
}
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 9fed365..867cb68 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -26,6 +26,9 @@
#include <asm/io.h>
#include <asm/mutex.h>
+/* for request_sense */
+#include <linux/cdrom.h>
+
#if defined(CONFIG_CRIS) || defined(CONFIG_FRV) || defined(CONFIG_MN10300)
# define SUPPORT_VLB_SYNC 0
#else
@@ -324,7 +327,6 @@ struct ide_cmd {
unsigned int cursg_ofs;
struct request *rq; /* copy of request */
- void *special; /* valid_t generally */
};
/* ATAPI packet command flags */
@@ -360,11 +362,7 @@ struct ide_atapi_pc {
/* data buffer */
u8 *buf;
- /* current buffer position */
- u8 *cur_pos;
int buf_size;
- /* missing/available data on the current buffer */
- int b_count;
/* the corresponding request */
struct request *rq;
@@ -377,10 +375,6 @@ struct ide_atapi_pc {
*/
u8 pc_buf[IDE_PC_BUFFER_SIZE];
- /* idetape only */
- struct idetape_bh *bh;
- char *b_data;
-
unsigned long timeout;
};
@@ -593,16 +587,16 @@ struct ide_drive_s {
/* callback for packet commands */
int (*pc_callback)(struct ide_drive_s *, int);
- void (*pc_update_buffers)(struct ide_drive_s *, struct ide_atapi_pc *);
- int (*pc_io_buffers)(struct ide_drive_s *, struct ide_atapi_pc *,
- unsigned int, int);
-
ide_startstop_t (*irq_handler)(struct ide_drive_s *);
unsigned long atapi_flags;
struct ide_atapi_pc request_sense_pc;
- struct request request_sense_rq;
+
+ /* current sense rq and buffer */
+ bool sense_rq_armed;
+ struct request sense_rq;
+ struct request_sense sense_data;
};
typedef struct ide_drive_s ide_drive_t;
@@ -1174,7 +1168,10 @@ int ide_do_test_unit_ready(ide_drive_t *, struct gendisk *);
int ide_do_start_stop(ide_drive_t *, struct gendisk *, int);
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 *);
+void ide_retry_pc(ide_drive_t *drive);
+
+void ide_prep_sense(ide_drive_t *drive, struct request *rq);
+int ide_queue_sense_rq(ide_drive_t *drive, void *special);
int ide_cd_expiry(ide_drive_t *);
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2009-06-10 21:30 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-12-29 19:49 [git pull] IDE updates part 1 Bartlomiej Zolnierkiewicz
-- strict thread matches above, loose matches on Subject: below --
2009-03-24 23:07 Bartlomiej Zolnierkiewicz
2009-06-10 21:35 Bartlomiej Zolnierkiewicz
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).