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 allobviously 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/Kconfigindex 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 interfacediff --git a/drivers/ide/Makefile b/drivers/ide/Makefileindex 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.cindex 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.cindex 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.cindex 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.cindex 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.cindex 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.cindex 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.hindex 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.cindex 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.cindex 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.cindex 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.cindex 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.cnew file mode 100644index 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.cindex 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.cindex 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.cnew file mode 100644index 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.cindex 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.cindex 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.cindex 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 todiff --git a/drivers/ide/pdc202xx_old.c b/drivers/ide/pdc202xx_old.cindex 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.cindex 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.cindex 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 | #endifdiff --git a/drivers/ide/tx4938ide.c b/drivers/ide/tx4938ide.cindex 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.cindex 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.cindex 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.cindex 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.hindex 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 */ ÿôèº{.nÇ+?·?®??+%?Ëÿ±éݶ¥?wÿº{.nÇ+?·¥?{±þ'^þ)í?æèw*jg¬±¨¶????Ý¢jÿ¾«þG«?éÿ¢¸¢·¦j:+v?¨?wèjØm¶?ÿþø¯ù®w¥þ?àþf£¢·h??â?úÿ?Ù¥