diff options
31 files changed, 1075 insertions, 1296 deletions
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index 57630402ea67..8d84fe440da1 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 @@ -864,6 +867,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 @@ -874,6 +878,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 @@ -884,6 +889,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 @@ -894,6 +900,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 @@ -902,6 +909,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 7818d402b188..410728992e6a 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 ide-sysfs.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/amd74xx.c b/drivers/ide/amd74xx.c index 81ec73134eda..c6bcd3014a29 100644 --- a/drivers/ide/amd74xx.c +++ b/drivers/ide/amd74xx.c @@ -3,7 +3,7 @@ * IDE driver for Linux. * * Copyright (c) 2000-2002 Vojtech Pavlik - * Copyright (c) 2007 Bartlomiej Zolnierkiewicz + * Copyright (c) 2007-2008 Bartlomiej Zolnierkiewicz * * Based on the work of: * Andre Hedrick @@ -263,6 +263,15 @@ static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_ d.udma_mask = ATA_UDMA5; } + /* + * It seems that on some nVidia controllers using AltStatus + * register can be unreliable so default to Status register + * if the device is in Compatibility Mode. + */ + if (dev->vendor == PCI_VENDOR_ID_NVIDIA && + ide_pci_is_in_compatibility_mode(dev)) + d.host_flags |= IDE_HFLAG_BROKEN_ALTSTATUS; + printk(KERN_INFO "%s %s: UDMA%s controller\n", d.name, pci_name(dev), amd_dma[fls(d.udma_mask) - 1]); diff --git a/drivers/ide/cmd64x.c b/drivers/ide/cmd64x.c index 935385c77e06..3623bf013bcf 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 5297f07d2933..d37baf8ecc5f 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 691506886561..59bd0be9dcb3 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 f5afd46ed51c..b18e10d99d2e 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-cd.c b/drivers/ide/ide-cd.c index 42ab6d8715f2..65e5513758b0 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -53,14 +53,6 @@ #include "ide-cd.h" -#define IDECD_DEBUG_LOG 1 - -#if IDECD_DEBUG_LOG -#define ide_debug_log(lvl, fmt, args...) __ide_debug_log(lvl, fmt, args) -#else -#define ide_debug_log(lvl, fmt, args...) do {} while (0) -#endif - static DEFINE_MUTEX(idecd_ref_mutex); static void ide_cd_release(struct kref *); @@ -262,7 +254,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 +269,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 +306,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 +416,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 +495,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 +766,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 +897,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 +1096,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 +1206,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 +1215,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 +1823,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 +1830,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 +1930,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 +1966,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 5882b9a9ea8b..389faa42eaa1 100644 --- a/drivers/ide/ide-cd.h +++ b/drivers/ide/ide-cd.h @@ -8,6 +8,14 @@ #include <linux/cdrom.h> #include <asm/byteorder.h> +#define IDECD_DEBUG_LOG 0 + +#if IDECD_DEBUG_LOG +#define ide_debug_log(lvl, fmt, args...) __ide_debug_log(lvl, fmt, args) +#else +#define ide_debug_log(lvl, fmt, args...) do {} while (0) +#endif + /* * typical timeout for packet command */ @@ -88,8 +96,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 cac431f0df17..f6d2d44d8a9a 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-floppy.c b/drivers/ide/ide-floppy.c index aeb1ad782f54..1f07f3818938 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -342,38 +342,38 @@ static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive, * Look at the flexible disk page parameters. We ignore the CHS capacity * parameters and use the LBA parameters instead. */ -static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive) +static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive, + struct ide_atapi_pc *pc) { struct ide_disk_obj *floppy = drive->driver_data; struct gendisk *disk = floppy->disk; - struct ide_atapi_pc pc; u8 *page; int capacity, lba_capacity; u16 transfer_rate, sector_size, cyls, rpm; u8 heads, sectors; - ide_floppy_create_mode_sense_cmd(&pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE); + ide_floppy_create_mode_sense_cmd(pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE); - if (ide_queue_pc_tail(drive, disk, &pc)) { + if (ide_queue_pc_tail(drive, disk, pc)) { printk(KERN_ERR PFX "Can't get flexible disk page params\n"); return 1; } - if (pc.buf[3] & 0x80) + if (pc->buf[3] & 0x80) drive->dev_flags |= IDE_DFLAG_WP; else drive->dev_flags &= ~IDE_DFLAG_WP; set_disk_ro(disk, !!(drive->dev_flags & IDE_DFLAG_WP)); - page = &pc.buf[8]; + page = &pc->buf[8]; - transfer_rate = be16_to_cpup((__be16 *)&pc.buf[8 + 2]); - sector_size = be16_to_cpup((__be16 *)&pc.buf[8 + 6]); - cyls = be16_to_cpup((__be16 *)&pc.buf[8 + 8]); - rpm = be16_to_cpup((__be16 *)&pc.buf[8 + 28]); - heads = pc.buf[8 + 4]; - sectors = pc.buf[8 + 5]; + transfer_rate = be16_to_cpup((__be16 *)&pc->buf[8 + 2]); + sector_size = be16_to_cpup((__be16 *)&pc->buf[8 + 6]); + cyls = be16_to_cpup((__be16 *)&pc->buf[8 + 8]); + rpm = be16_to_cpup((__be16 *)&pc->buf[8 + 28]); + heads = pc->buf[8 + 4]; + sectors = pc->buf[8 + 5]; capacity = cyls * heads * sectors * sector_size; @@ -499,7 +499,7 @@ static int ide_floppy_get_capacity(ide_drive_t *drive) /* Clik! disk does not support get_flexible_disk_page */ if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE)) - (void) ide_floppy_get_flexible_disk_page(drive); + (void) ide_floppy_get_flexible_disk_page(drive, &pc); return rc; } diff --git a/drivers/ide/ide-floppy_ioctl.c b/drivers/ide/ide-floppy_ioctl.c index 2bc51ff73fee..8f8be8546038 100644 --- a/drivers/ide/ide-floppy_ioctl.c +++ b/drivers/ide/ide-floppy_ioctl.c @@ -31,10 +31,11 @@ * On exit we set nformats to the number of records we've actually initialized. */ -static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg) +static int ide_floppy_get_format_capacities(ide_drive_t *drive, + struct ide_atapi_pc *pc, + int __user *arg) { struct ide_disk_obj *floppy = drive->driver_data; - struct ide_atapi_pc pc; u8 header_len, desc_cnt; int i, blocks, length, u_array_size, u_index; int __user *argp; @@ -45,13 +46,13 @@ static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg) if (u_array_size <= 0) return -EINVAL; - ide_floppy_create_read_capacity_cmd(&pc); - if (ide_queue_pc_tail(drive, floppy->disk, &pc)) { + ide_floppy_create_read_capacity_cmd(pc); + if (ide_queue_pc_tail(drive, floppy->disk, pc)) { printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n"); return -EIO; } - header_len = pc.buf[3]; + header_len = pc->buf[3]; desc_cnt = header_len / 8; /* capacity descriptor of 8 bytes */ u_index = 0; @@ -68,8 +69,8 @@ static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg) if (u_index >= u_array_size) break; /* User-supplied buffer too small */ - blocks = be32_to_cpup((__be32 *)&pc.buf[desc_start]); - length = be16_to_cpup((__be16 *)&pc.buf[desc_start + 6]); + blocks = be32_to_cpup((__be32 *)&pc->buf[desc_start]); + length = be16_to_cpup((__be16 *)&pc->buf[desc_start + 6]); if (put_user(blocks, argp)) return -EFAULT; @@ -111,29 +112,28 @@ static void ide_floppy_create_format_unit_cmd(struct ide_atapi_pc *pc, int b, pc->flags |= PC_FLAG_WRITING; } -static int ide_floppy_get_sfrp_bit(ide_drive_t *drive) +static int ide_floppy_get_sfrp_bit(ide_drive_t *drive, struct ide_atapi_pc *pc) { struct ide_disk_obj *floppy = drive->driver_data; - struct ide_atapi_pc pc; drive->atapi_flags &= ~IDE_AFLAG_SRFP; - ide_floppy_create_mode_sense_cmd(&pc, IDEFLOPPY_CAPABILITIES_PAGE); - pc.flags |= PC_FLAG_SUPPRESS_ERROR; + ide_floppy_create_mode_sense_cmd(pc, IDEFLOPPY_CAPABILITIES_PAGE); + pc->flags |= PC_FLAG_SUPPRESS_ERROR; - if (ide_queue_pc_tail(drive, floppy->disk, &pc)) + if (ide_queue_pc_tail(drive, floppy->disk, pc)) return 1; - if (pc.buf[8 + 2] & 0x40) + if (pc->buf[8 + 2] & 0x40) drive->atapi_flags |= IDE_AFLAG_SRFP; return 0; } -static int ide_floppy_format_unit(ide_drive_t *drive, int __user *arg) +static int ide_floppy_format_unit(ide_drive_t *drive, struct ide_atapi_pc *pc, + int __user *arg) { struct ide_disk_obj *floppy = drive->driver_data; - struct ide_atapi_pc pc; int blocks, length, flags, err = 0; if (floppy->openers > 1) { @@ -166,10 +166,10 @@ static int ide_floppy_format_unit(ide_drive_t *drive, int __user *arg) goto out; } - (void)ide_floppy_get_sfrp_bit(drive); - ide_floppy_create_format_unit_cmd(&pc, blocks, length, flags); + ide_floppy_get_sfrp_bit(drive, pc); + ide_floppy_create_format_unit_cmd(pc, blocks, length, flags); - if (ide_queue_pc_tail(drive, floppy->disk, &pc)) + if (ide_queue_pc_tail(drive, floppy->disk, pc)) err = -EIO; out: @@ -188,15 +188,16 @@ out: * the dsc bit, and return either 0 or 65536. */ -static int ide_floppy_get_format_progress(ide_drive_t *drive, int __user *arg) +static int ide_floppy_get_format_progress(ide_drive_t *drive, + struct ide_atapi_pc *pc, + int __user *arg) { struct ide_disk_obj *floppy = drive->driver_data; - struct ide_atapi_pc pc; int progress_indication = 0x10000; if (drive->atapi_flags & IDE_AFLAG_SRFP) { - ide_create_request_sense_cmd(drive, &pc); - if (ide_queue_pc_tail(drive, floppy->disk, &pc)) + ide_create_request_sense_cmd(drive, pc); + if (ide_queue_pc_tail(drive, floppy->disk, pc)) return -EIO; if (floppy->sense_key == 2 && @@ -241,20 +242,21 @@ static int ide_floppy_lockdoor(ide_drive_t *drive, struct ide_atapi_pc *pc, return 0; } -static int ide_floppy_format_ioctl(ide_drive_t *drive, fmode_t mode, - unsigned int cmd, void __user *argp) +static int ide_floppy_format_ioctl(ide_drive_t *drive, struct ide_atapi_pc *pc, + fmode_t mode, unsigned int cmd, + void __user *argp) { switch (cmd) { case IDEFLOPPY_IOCTL_FORMAT_SUPPORTED: return 0; case IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY: - return ide_floppy_get_format_capacities(drive, argp); + return ide_floppy_get_format_capacities(drive, pc, argp); case IDEFLOPPY_IOCTL_FORMAT_START: if (!(mode & FMODE_WRITE)) return -EPERM; - return ide_floppy_format_unit(drive, (int __user *)argp); + return ide_floppy_format_unit(drive, pc, (int __user *)argp); case IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS: - return ide_floppy_get_format_progress(drive, argp); + return ide_floppy_get_format_progress(drive, pc, argp); default: return -ENOTTY; } @@ -270,7 +272,7 @@ int ide_floppy_ioctl(ide_drive_t *drive, struct block_device *bdev, if (cmd == CDROMEJECT || cmd == CDROM_LOCKDOOR) return ide_floppy_lockdoor(drive, &pc, arg, cmd); - err = ide_floppy_format_ioctl(drive, mode, cmd, argp); + err = ide_floppy_format_ioctl(drive, &pc, mode, cmd, argp); if (err != -ENOTTY) return err; diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 7162d67562af..7743b0f2b290 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,101 +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, u8 stat, u8 error) -{ - struct request_pm_state *pm = rq->data; - - 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, 0, 0); - 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, 0, 0); - 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 @@ -238,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 @@ -296,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; @@ -322,25 +179,21 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err) } } else if (blk_pm_request(rq)) { struct request_pm_state *pm = rq->data; -#ifdef DEBUG_PM - printk("%s: complete_power_step(step: %d, stat: %x, err: %x)\n", - drive->name, rq->pm->pm_step, stat, err); -#endif - ide_complete_power_step(drive, rq, stat, err); + + ide_complete_power_step(drive, rq); if (pm->pm_step == IDE_PM_COMPLETED) ide_complete_pm_request(drive, rq); 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) @@ -719,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 * @@ -804,7 +623,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) struct request_pm_state *pm = rq->data; #ifdef DEBUG_PM printk("%s: start_power_step(step: %d)\n", - drive->name, rq->pm->pm_step); + drive->name, pm->pm_step); #endif startstop = ide_start_power_step(drive, rq); if (startstop == ide_stopped && @@ -848,85 +667,10 @@ void ide_stall_queue (ide_drive_t *drive, unsigned long timeout) drive->sleep = timeout + jiffies; drive->dev_flags |= IDE_DFLAG_SLEEPING; } - EXPORT_SYMBOL(ide_stall_queue); -#define WAKEUP(drive) ((drive)->service_start + 2 * (drive)->service_time) - -/** - * choose_drive - select a drive to service - * @hwgroup: hardware group to select on - * - * choose_drive() selects the next drive which will be serviced. - * This is necessary because the IDE layer can't issue commands - * to both drives on the same cable, unlike SCSI. - */ - -static inline ide_drive_t *choose_drive (ide_hwgroup_t *hwgroup) -{ - ide_drive_t *drive, *best; - -repeat: - best = NULL; - drive = hwgroup->drive; - - /* - * drive is doing pre-flush, ordered write, post-flush sequence. even - * though that is 3 requests, it must be seen as a single transaction. - * we must not preempt this drive until that is complete - */ - if (blk_queue_flushing(drive->queue)) { - /* - * small race where queue could get replugged during - * the 3-request flush cycle, just yank the plug since - * we want it to finish asap - */ - blk_remove_plug(drive->queue); - return drive; - } - - do { - u8 dev_s = !!(drive->dev_flags & IDE_DFLAG_SLEEPING); - u8 best_s = (best && !!(best->dev_flags & IDE_DFLAG_SLEEPING)); - - if ((dev_s == 0 || time_after_eq(jiffies, drive->sleep)) && - !elv_queue_empty(drive->queue)) { - if (best == NULL || - (dev_s && (best_s == 0 || time_before(drive->sleep, best->sleep))) || - (best_s == 0 && time_before(WAKEUP(drive), WAKEUP(best)))) { - if (!blk_queue_plugged(drive->queue)) - best = drive; - } - } - } while ((drive = drive->next) != hwgroup->drive); - - if (best && (best->dev_flags & IDE_DFLAG_NICE1) && - (best->dev_flags & IDE_DFLAG_SLEEPING) == 0 && - best != hwgroup->drive && best->service_time > WAIT_MIN_SLEEP) { - long t = (signed long)(WAKEUP(best) - jiffies); - if (t >= WAIT_MIN_SLEEP) { - /* - * We *may* have some time to spare, but first let's see if - * someone can potentially benefit from our nice mood today.. - */ - drive = best->next; - do { - if ((drive->dev_flags & IDE_DFLAG_SLEEPING) == 0 - && time_before(jiffies - best->service_time, WAKEUP(drive)) - && time_before(WAKEUP(drive), jiffies + t)) - { - ide_stall_queue(best, min_t(long, t, 10 * WAIT_MIN_SLEEP)); - goto repeat; - } - } while ((drive = drive->next) != best); - } - } - return best; -} - /* * Issue a new request to a drive from hwgroup - * Caller must have already done spin_lock_irqsave(&ide_lock, ..); * * A hwgroup is a serialized group of IDE interfaces. Usually there is * exactly one hwif (interface) per hwgroup, but buggy controllers (eg. CMD640) @@ -938,8 +682,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 - * access to the request queues, and to protect the hwgroup->busy flag. + * The IDE driver uses a per-hwgroup lock to protect the hwgroup->busy flag. * * The first thread into the driver for a particular hwgroup sets the * hwgroup->busy flag to indicate that this hwgroup is now active, @@ -954,101 +697,73 @@ 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. */ -static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq) +void do_ide_request(struct request_queue *q) { - ide_drive_t *drive; - ide_hwif_t *hwif; + ide_drive_t *drive = q->queuedata; + ide_hwif_t *hwif = drive->hwif; + ide_hwgroup_t *hwgroup = hwif->hwgroup; struct request *rq; ide_startstop_t startstop; - int loops = 0; - /* for atari only: POSSIBLY BROKEN HERE(?) */ - ide_get_lock(ide_intr, hwgroup); + /* + * drive is doing pre-flush, ordered write, post-flush sequence. even + * though that is 3 requests, it must be seen as a single transaction. + * we must not preempt this drive until that is complete + */ + if (blk_queue_flushing(q)) + /* + * small race where queue could get replugged during + * the 3-request flush cycle, just yank the plug since + * we want it to finish asap + */ + blk_remove_plug(q); - /* caller must own ide_lock */ + spin_unlock_irq(q->queue_lock); + spin_lock_irq(&hwgroup->lock); + + /* caller must own hwgroup->lock */ BUG_ON(!irqs_disabled()); - while (!hwgroup->busy) { - hwgroup->busy = 1; - drive = choose_drive(hwgroup); - if (drive == NULL) { - int sleeping = 0; - unsigned long sleep = 0; /* shut up, gcc */ - hwgroup->rq = NULL; - drive = hwgroup->drive; - do { - if ((drive->dev_flags & IDE_DFLAG_SLEEPING) && - (sleeping == 0 || - time_before(drive->sleep, sleep))) { - sleeping = 1; - sleep = drive->sleep; - } - } while ((drive = drive->next) != hwgroup->drive); - if (sleeping) { - /* - * Take a short snooze, and then wake up this hwgroup again. - * This gives other hwgroups on the same a chance to - * play fairly with us, just in case there are big differences - * in relative throughputs.. don't want to hog the cpu too much. - */ - if (time_before(sleep, jiffies + WAIT_MIN_SLEEP)) - sleep = jiffies + WAIT_MIN_SLEEP; -#if 1 - if (timer_pending(&hwgroup->timer)) - printk(KERN_CRIT "ide_set_handler: timer already active\n"); -#endif - /* so that ide_timer_expiry knows what to do */ - hwgroup->sleeping = 1; - hwgroup->req_gen_timer = hwgroup->req_gen; - mod_timer(&hwgroup->timer, sleep); - /* we purposely leave hwgroup->busy==1 - * while sleeping */ - } else { - /* Ugly, but how can we sleep for the lock - * otherwise? perhaps from tq_disk? - */ + if (!ide_lock_hwgroup(hwgroup)) { + hwgroup->rq = NULL; - /* for atari only */ - ide_release_lock(); - hwgroup->busy = 0; + if (drive->dev_flags & IDE_DFLAG_SLEEPING) { + if (time_before(drive->sleep, jiffies)) { + ide_unlock_hwgroup(hwgroup); + goto plug_device; } - - /* no more work for this hwgroup (for now) */ - return; } - 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; hwgroup->drive = drive; 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; - } + spin_unlock_irq(&hwgroup->lock); + spin_lock_irq(q->queue_lock); /* * we know that the queue isn't empty, but this can happen * if the q->prep_rq_fn() decides to kill a request */ rq = elv_next_request(drive->queue); + spin_unlock_irq(q->queue_lock); + spin_lock_irq(&hwgroup->lock); + if (!rq) { - hwgroup->busy = 0; - break; + ide_unlock_hwgroup(hwgroup); + goto out; } /* @@ -1063,53 +778,39 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq) * though. I hope that doesn't happen too much, hopefully not * unless the subdriver triggers such a thing in its own PM * state machine. - * - * We count how many times we loop here to make sure we service - * all drives in the hwgroup without looping for ever */ if ((drive->dev_flags & IDE_DFLAG_BLOCKED) && blk_pm_request(rq) == 0 && (rq->cmd_flags & REQ_PREEMPT) == 0) { - drive = drive->next ? drive->next : hwgroup->drive; - if (loops++ < 4 && !blk_queue_plugged(drive->queue)) - goto again; - /* We clear busy, there should be no pending ATA command at this point. */ - hwgroup->busy = 0; - break; + /* there should be no pending command at this point */ + ide_unlock_hwgroup(hwgroup); + goto plug_device; } hwgroup->rq = rq; - /* - * Some systems have trouble with IDE IRQs arriving while - * the driver is still setting things up. So, here we disable - * the IRQ used by this interface while the request is being started. - * This may look bad at first, but pretty much the same thing - * happens anyway when any interrupt comes in, IDE or otherwise - * -- the kernel masks the IRQ while it is being handled. - */ - if (masked_irq != IDE_NO_IRQ && hwif->irq != masked_irq) - disable_irq_nosync(hwif->irq); - spin_unlock(&ide_lock); - local_irq_enable_in_hardirq(); - /* allow other IRQs while we start this request */ + spin_unlock_irq(&hwgroup->lock); startstop = start_request(drive, rq); - spin_lock_irq(&ide_lock); - if (masked_irq != IDE_NO_IRQ && hwif->irq != masked_irq) - enable_irq(hwif->irq); - if (startstop == ide_stopped) - hwgroup->busy = 0; - } -} + spin_lock_irq(&hwgroup->lock); -/* - * Passes the stuff to ide_do_request - */ -void do_ide_request(struct request_queue *q) -{ - ide_drive_t *drive = q->queuedata; + if (startstop == ide_stopped) { + ide_unlock_hwgroup(hwgroup); + /* give other devices a chance */ + goto plug_device; + } + } else + goto plug_device; +out: + spin_unlock_irq(&hwgroup->lock); + spin_lock_irq(q->queue_lock); + return; - ide_do_request(HWGROUP(drive), IDE_NO_IRQ); +plug_device: + spin_unlock_irq(&hwgroup->lock); + spin_lock_irq(q->queue_lock); + + if (!elv_queue_empty(q)) + blk_plug_device(q); } /* @@ -1170,6 +871,17 @@ out: return ret; } +static void ide_plug_device(ide_drive_t *drive) +{ + struct request_queue *q = drive->queue; + unsigned long flags; + + spin_lock_irqsave(q->queue_lock, flags); + if (!elv_queue_empty(q)) + blk_plug_device(q); + spin_unlock_irqrestore(q->queue_lock, flags); +} + /** * ide_timer_expiry - handle lack of an IDE interrupt * @data: timer callback magic (hwgroup) @@ -1187,12 +899,14 @@ out: void ide_timer_expiry (unsigned long data) { ide_hwgroup_t *hwgroup = (ide_hwgroup_t *) data; + ide_drive_t *uninitialized_var(drive); ide_handler_t *handler; ide_expiry_t *expiry; unsigned long flags; unsigned long wait = -1; + int plug_device = 0; - spin_lock_irqsave(&ide_lock, flags); + spin_lock_irqsave(&hwgroup->lock, flags); if (((handler = hwgroup->handler) == NULL) || (hwgroup->req_gen != hwgroup->req_gen_timer)) { @@ -1202,22 +916,15 @@ void ide_timer_expiry (unsigned long data) * or we were "sleeping" to give other devices a chance. * Either way, we don't really want to complain about anything. */ - if (hwgroup->sleeping) { - hwgroup->sleeping = 0; - hwgroup->busy = 0; - } } else { - ide_drive_t *drive = hwgroup->drive; + drive = hwgroup->drive; if (!drive) { printk(KERN_ERR "ide_timer_expiry: hwgroup->drive was NULL\n"); hwgroup->handler = NULL; } else { ide_hwif_t *hwif; ide_startstop_t startstop = ide_stopped; - if (!hwgroup->busy) { - hwgroup->busy = 1; /* paranoia */ - printk(KERN_ERR "%s: ide_timer_expiry: hwgroup->busy was 0 ??\n", drive->name); - } + if ((expiry = hwgroup->expiry) != NULL) { /* continue */ if ((wait = expiry(drive)) > 0) { @@ -1225,7 +932,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 +942,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); @@ -1258,15 +965,18 @@ void ide_timer_expiry (unsigned long data) ide_error(drive, "irq timeout", hwif->tp_ops->read_status(hwif)); } - drive->service_time = jiffies - drive->service_start; - spin_lock_irq(&ide_lock); + spin_lock_irq(&hwgroup->lock); enable_irq(hwif->irq); - if (startstop == ide_stopped) - hwgroup->busy = 0; + if (startstop == ide_stopped) { + ide_unlock_hwgroup(hwgroup); + plug_device = 1; + } } } - ide_do_request(hwgroup, IDE_NO_IRQ); - spin_unlock_irqrestore(&ide_lock, flags); + spin_unlock_irqrestore(&hwgroup->lock, flags); + + if (plug_device) + ide_plug_device(drive); } /** @@ -1359,18 +1069,17 @@ 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_drive_t *drive; + ide_hwif_t *hwif = hwgroup->hwif; + ide_drive_t *uninitialized_var(drive); ide_handler_t *handler; ide_startstop_t startstop; + irqreturn_t irq_ret = IRQ_NONE; + int plug_device = 0; - spin_lock_irqsave(&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 +1115,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 +1126,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,17 +1137,12 @@ 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; - } - if (!hwgroup->busy) { - hwgroup->busy = 1; /* paranoia */ - printk(KERN_ERR "%s: ide_intr: hwgroup->busy was 0 ??\n", drive->name); - } + goto out; + 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 +1153,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 @@ -1457,18 +1161,23 @@ irqreturn_t ide_intr (int irq, void *dev_id) * same irq as is currently being serviced here, and Linux * won't allow another of the same (on any CPU) until we return. */ - drive->service_time = jiffies - drive->service_start; if (startstop == ide_stopped) { if (hwgroup->handler == NULL) { /* paranoia */ - hwgroup->busy = 0; - ide_do_request(hwgroup, hwif->irq); - } else { - printk(KERN_ERR "%s: ide_intr: huh? expected NULL handler " - "on exit\n", drive->name); - } + ide_unlock_hwgroup(hwgroup); + plug_device = 1; + } else + printk(KERN_ERR "%s: %s: huh? expected NULL handler " + "on exit\n", __func__, drive->name); } - spin_unlock_irqrestore(&ide_lock, flags); - return IRQ_HANDLED; +out_handled: + irq_ret = IRQ_HANDLED; +out: + spin_unlock_irqrestore(&hwgroup->lock, flags); + + if (plug_device) + ide_plug_device(drive); + + return irq_ret; } /** @@ -1488,16 +1197,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 fcde16bb53a7..28232c64c346 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 5d6ba14e211d..ad8bd6539283 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -457,18 +457,14 @@ int drive_is_ready (ide_drive_t *drive) if (drive->waiting_for_dma) return hwif->dma_ops->dma_test_irq(drive); -#if 0 - /* need to guarantee 400ns since last command was issued */ - udelay(1); -#endif - /* * 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) + 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!! */ @@ -610,6 +606,7 @@ static const struct drive_list_entry ivb_list[] = { { "TSSTcorp CDDVDW SH-S202N" , "SB01" }, { "TSSTcorp CDDVDW SH-S202H" , "SB00" }, { "TSSTcorp CDDVDW SH-S202H" , "SB01" }, + { "SAMSUNG SP0822N" , "WA100-10" }, { NULL , NULL } }; @@ -838,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); @@ -863,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); /* @@ -876,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); @@ -1079,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); @@ -1109,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; } @@ -1132,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); @@ -1146,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; } @@ -1182,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 000000000000..8c5dcbf22547 --- /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 9fc4cfb2a272..9f6e33d8a8b2 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 03b00e57e93f..678454ac2483 100644 --- a/drivers/ide/ide-park.c +++ b/drivers/ide/ide-park.c @@ -7,29 +7,31 @@ 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); + int start_queue = 0; - reset_timer = time_before(timeout, drive->sleep); drive->sleep = timeout; wake_up_all(&ide_park_wq); - if (reset_timer && hwgroup->sleeping && - del_timer(&hwgroup->timer)) { - hwgroup->sleeping = 0; - hwgroup->busy = 0; + if (reset_timer && del_timer(&hwgroup->timer)) + start_queue = 1; + spin_unlock_irq(&hwgroup->lock); + + if (start_queue) { + spin_lock_irq(q->queue_lock); blk_start_queueing(q); + spin_unlock_irq(q->queue_lock); } - spin_unlock_irq(&ide_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 +64,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 000000000000..58e520e6b93f --- /dev/null +++ b/drivers/ide/ide-pm.c @@ -0,0 +1,233 @@ +#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; + if (drive->dev_flags & 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 1649ea54f76c..966b74c15773 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -101,6 +101,82 @@ static void ide_disk_init_mult_count(ide_drive_t *drive) } } +static void ide_classify_ata_dev(ide_drive_t *drive) +{ + u16 *id = drive->id; + char *m = (char *)&id[ATA_ID_PROD]; + int is_cfa = ata_id_is_cfa(id); + + /* CF devices are *not* removable in Linux definition of the term */ + if (is_cfa == 0 && (id[ATA_ID_CONFIG] & (1 << 7))) + drive->dev_flags |= IDE_DFLAG_REMOVABLE; + + drive->media = ide_disk; + + if (!ata_id_has_unload(drive->id)) + drive->dev_flags |= IDE_DFLAG_NO_UNLOAD; + + printk(KERN_INFO "%s: %s, %s DISK drive\n", drive->name, m, + is_cfa ? "CFA" : "ATA"); +} + +static void ide_classify_atapi_dev(ide_drive_t *drive) +{ + u16 *id = drive->id; + char *m = (char *)&id[ATA_ID_PROD]; + u8 type = (id[ATA_ID_CONFIG] >> 8) & 0x1f; + + printk(KERN_INFO "%s: %s, ATAPI ", drive->name, m); + switch (type) { + case ide_floppy: + if (!strstr(m, "CD-ROM")) { + if (!strstr(m, "oppy") && + !strstr(m, "poyp") && + !strstr(m, "ZIP")) + printk(KERN_CONT "cdrom or floppy?, assuming "); + if (drive->media != ide_cdrom) { + printk(KERN_CONT "FLOPPY"); + drive->dev_flags |= IDE_DFLAG_REMOVABLE; + break; + } + } + /* Early cdrom models used zero */ + type = ide_cdrom; + case ide_cdrom: + drive->dev_flags |= IDE_DFLAG_REMOVABLE; +#ifdef CONFIG_PPC + /* kludge for Apple PowerBook internal zip */ + if (!strstr(m, "CD-ROM") && strstr(m, "ZIP")) { + printk(KERN_CONT "FLOPPY"); + type = ide_floppy; + break; + } +#endif + printk(KERN_CONT "CD/DVD-ROM"); + break; + case ide_tape: + printk(KERN_CONT "TAPE"); + break; + case ide_optical: + printk(KERN_CONT "OPTICAL"); + drive->dev_flags |= IDE_DFLAG_REMOVABLE; + break; + default: + printk(KERN_CONT "UNKNOWN (type %d)", type); + break; + } + + printk(KERN_CONT " drive\n"); + drive->media = type; + /* an ATAPI device ignores DRDY */ + drive->ready_stat = 0; + if (ata_id_cdb_intr(id)) + drive->atapi_flags |= IDE_AFLAG_DRQ_INTERRUPT; + drive->dev_flags |= IDE_DFLAG_DOORLOCKING; + /* we don't do head unloading on ATAPI devices */ + drive->dev_flags |= IDE_DFLAG_NO_UNLOAD; +} + /** * do_identify - identify a drive * @drive: drive to identify @@ -110,20 +186,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]; - int bswap = 1, is_cfa; + unsigned long flags; + int bswap = 1; + /* 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); @@ -152,91 +230,23 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd) if (strstr(m, "E X A B Y T E N E S T")) goto err_misc; - printk(KERN_INFO "%s: %s, ", drive->name, m); - drive->dev_flags |= IDE_DFLAG_PRESENT; drive->dev_flags &= ~IDE_DFLAG_DEAD; /* * Check for an ATAPI device */ - if (cmd == ATA_CMD_ID_ATAPI) { - u8 type = (id[ATA_ID_CONFIG] >> 8) & 0x1f; - - printk(KERN_CONT "ATAPI "); - switch (type) { - case ide_floppy: - if (!strstr(m, "CD-ROM")) { - if (!strstr(m, "oppy") && - !strstr(m, "poyp") && - !strstr(m, "ZIP")) - printk(KERN_CONT "cdrom or floppy?, assuming "); - if (drive->media != ide_cdrom) { - printk(KERN_CONT "FLOPPY"); - drive->dev_flags |= IDE_DFLAG_REMOVABLE; - break; - } - } - /* Early cdrom models used zero */ - type = ide_cdrom; - case ide_cdrom: - drive->dev_flags |= IDE_DFLAG_REMOVABLE; -#ifdef CONFIG_PPC - /* kludge for Apple PowerBook internal zip */ - if (!strstr(m, "CD-ROM") && strstr(m, "ZIP")) { - printk(KERN_CONT "FLOPPY"); - type = ide_floppy; - break; - } -#endif - printk(KERN_CONT "CD/DVD-ROM"); - break; - case ide_tape: - printk(KERN_CONT "TAPE"); - break; - case ide_optical: - printk(KERN_CONT "OPTICAL"); - drive->dev_flags |= IDE_DFLAG_REMOVABLE; - break; - default: - printk(KERN_CONT "UNKNOWN (type %d)", type); - break; - } - printk(KERN_CONT " drive\n"); - drive->media = type; - /* an ATAPI device ignores DRDY */ - drive->ready_stat = 0; - if (ata_id_cdb_intr(id)) - drive->atapi_flags |= IDE_AFLAG_DRQ_INTERRUPT; - drive->dev_flags |= IDE_DFLAG_DOORLOCKING; - /* we don't do head unloading on ATAPI devices */ - drive->dev_flags |= IDE_DFLAG_NO_UNLOAD; - return; - } - + if (cmd == ATA_CMD_ID_ATAPI) + ide_classify_atapi_dev(drive); + else /* * Not an ATAPI device: looks like a "regular" hard disk */ - - is_cfa = ata_id_is_cfa(id); - - /* CF devices are *not* removable in Linux definition of the term */ - if (is_cfa == 0 && (id[ATA_ID_CONFIG] & (1 << 7))) - drive->dev_flags |= IDE_DFLAG_REMOVABLE; - - drive->media = ide_disk; - - if (!ata_id_has_unload(drive->id)) - drive->dev_flags |= IDE_DFLAG_NO_UNLOAD; - - printk(KERN_CONT "%s DISK drive\n", is_cfa ? "CFA" : "ATA"); - + ide_classify_ata_dev(drive); return; - err_misc: kfree(id); drive->dev_flags &= ~IDE_DFLAG_PRESENT; - return; } /** @@ -266,7 +276,8 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd) /* take a deep breath */ msleep(50); - if (io_ports->ctl_addr) { + if (io_ports->ctl_addr && + (hwif->host_flags & IDE_HFLAG_BROKEN_ALTSTATUS) == 0) { a = tp_ops->read_altstatus(hwif); s = tp_ops->read_status(hwif); if ((a ^ s) & ~ATA_IDX) @@ -305,17 +316,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; @@ -553,8 +559,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; @@ -641,16 +647,11 @@ 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) - hwif->gendev.parent = hwif->dev; - else - /* Would like to do = &device_legacy */ - hwif->gendev.parent = NULL; - } + hwif->gendev.parent = hwif->dev; hwif->gendev.release = hwif_release_dev; + ret = device_register(&hwif->gendev); if (ret < 0) { printk(KERN_WARNING "IDE: %s: device_register error: %d\n", @@ -863,31 +864,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) @@ -905,7 +881,7 @@ 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, NULL, hwif_to_node(hwif)); if (!q) return 1; @@ -946,7 +922,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; @@ -956,7 +932,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); } /* @@ -1001,7 +977,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 @@ -1029,7 +1005,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); } /* @@ -1050,27 +1026,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; } } } @@ -1091,17 +1053,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; @@ -1121,8 +1085,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) @@ -1149,8 +1112,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); @@ -1262,20 +1224,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); } @@ -1351,7 +1314,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; @@ -1435,13 +1398,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) @@ -1458,58 +1419,6 @@ static void ide_port_cable_detect(ide_hwif_t *hwif) } } -static ssize_t store_delete_devices(struct device *portdev, - struct device_attribute *attr, - const char *buf, size_t n) -{ - ide_hwif_t *hwif = dev_get_drvdata(portdev); - - if (strncmp(buf, "1", n)) - return -EINVAL; - - ide_port_unregister_devices(hwif); - - return n; -}; - -static DEVICE_ATTR(delete_devices, S_IWUSR, NULL, store_delete_devices); - -static ssize_t store_scan(struct device *portdev, - struct device_attribute *attr, - const char *buf, size_t n) -{ - ide_hwif_t *hwif = dev_get_drvdata(portdev); - - if (strncmp(buf, "1", n)) - return -EINVAL; - - ide_port_unregister_devices(hwif); - ide_port_scan(hwif); - - return n; -}; - -static DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan); - -static struct device_attribute *ide_port_attrs[] = { - &dev_attr_delete_devices, - &dev_attr_scan, - NULL -}; - -static int ide_sysfs_register_port(ide_hwif_t *hwif) -{ - int i, uninitialized_var(rc); - - for (i = 0; ide_port_attrs[i]; i++) { - rc = device_create_file(hwif->portdev, ide_port_attrs[i]); - if (rc) - break; - } - - return rc; -} - static unsigned int ide_indexes; /** @@ -1696,9 +1605,6 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d, if (hwif == NULL) continue; - if (hwif->chipset == ide_unknown) - hwif->chipset = ide_generic; - if (hwif->present) hwif_register_devices(hwif); } @@ -1793,59 +1699,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 f3cddd1b2f8f..a14e2938e4f3 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-sysfs.c b/drivers/ide/ide-sysfs.c new file mode 100644 index 000000000000..883ffacaf45a --- /dev/null +++ b/drivers/ide/ide-sysfs.c @@ -0,0 +1,125 @@ +#include <linux/kernel.h> +#include <linux/ide.h> + +char *ide_media_string(ide_drive_t *drive) +{ + switch (drive->media) { + case ide_disk: + return "disk"; + case ide_cdrom: + return "cdrom"; + case ide_tape: + return "tape"; + case ide_floppy: + return "floppy"; + case ide_optical: + return "optical"; + default: + return "UNKNOWN"; + } +} + +static ssize_t media_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + ide_drive_t *drive = to_ide_device(dev); + return sprintf(buf, "%s\n", ide_media_string(drive)); +} + +static ssize_t drivename_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + ide_drive_t *drive = to_ide_device(dev); + return sprintf(buf, "%s\n", drive->name); +} + +static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + ide_drive_t *drive = to_ide_device(dev); + return sprintf(buf, "ide:m-%s\n", ide_media_string(drive)); +} + +static ssize_t model_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + ide_drive_t *drive = to_ide_device(dev); + return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_PROD]); +} + +static ssize_t firmware_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + ide_drive_t *drive = to_ide_device(dev); + return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_FW_REV]); +} + +static ssize_t serial_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + ide_drive_t *drive = to_ide_device(dev); + return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_SERNO]); +} + +struct device_attribute ide_dev_attrs[] = { + __ATTR_RO(media), + __ATTR_RO(drivename), + __ATTR_RO(modalias), + __ATTR_RO(model), + __ATTR_RO(firmware), + __ATTR(serial, 0400, serial_show, NULL), + __ATTR(unload_heads, 0644, ide_park_show, ide_park_store), + __ATTR_NULL +}; + +static ssize_t store_delete_devices(struct device *portdev, + struct device_attribute *attr, + const char *buf, size_t n) +{ + ide_hwif_t *hwif = dev_get_drvdata(portdev); + + if (strncmp(buf, "1", n)) + return -EINVAL; + + ide_port_unregister_devices(hwif); + + return n; +}; + +static DEVICE_ATTR(delete_devices, S_IWUSR, NULL, store_delete_devices); + +static ssize_t store_scan(struct device *portdev, + struct device_attribute *attr, + const char *buf, size_t n) +{ + ide_hwif_t *hwif = dev_get_drvdata(portdev); + + if (strncmp(buf, "1", n)) + return -EINVAL; + + ide_port_unregister_devices(hwif); + ide_port_scan(hwif); + + return n; +}; + +static DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan); + +static struct device_attribute *ide_port_attrs[] = { + &dev_attr_delete_devices, + &dev_attr_scan, + NULL +}; + +int ide_sysfs_register_port(ide_hwif_t *hwif) +{ + int i, uninitialized_var(rc); + + for (i = 0; ide_port_attrs[i]; i++) { + rc = device_create_file(hwif->portdev, ide_port_attrs[i]); + if (rc) + break; + } + + return rc; +} diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 04f8f13cb9d7..46a2d4ca812b 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 @@ -523,81 +440,13 @@ static int ide_bus_match(struct device *dev, struct device_driver *drv) return 1; } -static char *media_string(ide_drive_t *drive) -{ - switch (drive->media) { - case ide_disk: - return "disk"; - case ide_cdrom: - return "cdrom"; - case ide_tape: - return "tape"; - case ide_floppy: - return "floppy"; - case ide_optical: - return "optical"; - default: - return "UNKNOWN"; - } -} - -static ssize_t media_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - ide_drive_t *drive = to_ide_device(dev); - return sprintf(buf, "%s\n", media_string(drive)); -} - -static ssize_t drivename_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - ide_drive_t *drive = to_ide_device(dev); - return sprintf(buf, "%s\n", drive->name); -} - -static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - ide_drive_t *drive = to_ide_device(dev); - return sprintf(buf, "ide:m-%s\n", media_string(drive)); -} - -static ssize_t model_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - ide_drive_t *drive = to_ide_device(dev); - return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_PROD]); -} - -static ssize_t firmware_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - ide_drive_t *drive = to_ide_device(dev); - return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_FW_REV]); -} - -static ssize_t serial_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - ide_drive_t *drive = to_ide_device(dev); - return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_SERNO]); -} - -static struct device_attribute ide_dev_attrs[] = { - __ATTR_RO(media), - __ATTR_RO(drivename), - __ATTR_RO(modalias), - __ATTR_RO(model), - __ATTR_RO(firmware), - __ATTR(serial, 0400, serial_show, NULL), - __ATTR(unload_heads, 0644, ide_park_show, ide_park_store), - __ATTR_NULL -}; - static int ide_uevent(struct device *dev, struct kobj_uevent_env *env) { ide_drive_t *drive = to_ide_device(dev); - add_uevent_var(env, "MEDIA=%s", media_string(drive)); + add_uevent_var(env, "MEDIA=%s", ide_media_string(drive)); add_uevent_var(env, "DRIVENAME=%s", drive->name); - add_uevent_var(env, "MODALIAS=ide:m-%s", media_string(drive)); + add_uevent_var(env, "MODALIAS=ide:m-%s", ide_media_string(drive)); return 0; } diff --git a/drivers/ide/pdc202xx_old.c b/drivers/ide/pdc202xx_old.c index 799557c25eef..624e62e5cc9a 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 7daf0135cbac..a6414a884eb1 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 75ea61526566..2a5ea90cf8b8 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 9120063e8f87..e61fa01345d7 100644 --- a/drivers/ide/tx4938ide.c +++ b/drivers/ide/tx4938ide.c @@ -216,16 +216,17 @@ static const struct ide_tp_ops tx4938ide_tp_ops = { #endif /* __BIG_ENDIAN */ static const struct ide_port_ops tx4938ide_port_ops = { - .set_pio_mode = tx4938ide_set_pio_mode, + .set_pio_mode = tx4938ide_set_pio_mode, }; static const struct ide_port_info tx4938ide_port_info __initdata = { - .port_ops = &tx4938ide_port_ops, + .port_ops = &tx4938ide_port_ops, #ifdef __BIG_ENDIAN - .tp_ops = &tx4938ide_tp_ops, + .tp_ops = &tx4938ide_tp_ops, #endif - .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA, - .pio_mask = ATA_PIO5, + .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA, + .pio_mask = ATA_PIO5, + .chipset = ide_generic, }; static int __init tx4938ide_probe(struct platform_device *pdev) diff --git a/drivers/ide/tx4939ide.c b/drivers/ide/tx4939ide.c index bafb7d1a22e2..c32e42293681 100644 --- a/drivers/ide/tx4939ide.c +++ b/drivers/ide/tx4939ide.c @@ -617,33 +617,34 @@ static const struct ide_tp_ops tx4939ide_tp_ops = { #endif /* __LITTLE_ENDIAN */ static const struct ide_port_ops tx4939ide_port_ops = { - .set_pio_mode = tx4939ide_set_pio_mode, - .set_dma_mode = tx4939ide_set_dma_mode, - .clear_irq = tx4939ide_clear_irq, - .cable_detect = tx4939ide_cable_detect, + .set_pio_mode = tx4939ide_set_pio_mode, + .set_dma_mode = tx4939ide_set_dma_mode, + .clear_irq = tx4939ide_clear_irq, + .cable_detect = tx4939ide_cable_detect, }; static const struct ide_dma_ops tx4939ide_dma_ops = { - .dma_host_set = tx4939ide_dma_host_set, - .dma_setup = tx4939ide_dma_setup, - .dma_exec_cmd = ide_dma_exec_cmd, - .dma_start = ide_dma_start, - .dma_end = tx4939ide_dma_end, - .dma_test_irq = tx4939ide_dma_test_irq, - .dma_lost_irq = ide_dma_lost_irq, - .dma_timeout = ide_dma_timeout, + .dma_host_set = tx4939ide_dma_host_set, + .dma_setup = tx4939ide_dma_setup, + .dma_exec_cmd = ide_dma_exec_cmd, + .dma_start = ide_dma_start, + .dma_end = tx4939ide_dma_end, + .dma_test_irq = tx4939ide_dma_test_irq, + .dma_lost_irq = ide_dma_lost_irq, + .dma_timeout = ide_dma_timeout, }; static const struct ide_port_info tx4939ide_port_info __initdata = { - .init_hwif = tx4939ide_init_hwif, - .init_dma = tx4939ide_init_dma, - .port_ops = &tx4939ide_port_ops, - .dma_ops = &tx4939ide_dma_ops, - .tp_ops = &tx4939ide_tp_ops, - .host_flags = IDE_HFLAG_MMIO, - .pio_mask = ATA_PIO4, - .mwdma_mask = ATA_MWDMA2, - .udma_mask = ATA_UDMA5, + .init_hwif = tx4939ide_init_hwif, + .init_dma = tx4939ide_init_dma, + .port_ops = &tx4939ide_port_ops, + .dma_ops = &tx4939ide_dma_ops, + .tp_ops = &tx4939ide_tp_ops, + .host_flags = IDE_HFLAG_MMIO, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA5, + .chipset = ide_generic, }; static int __init tx4939ide_probe(struct platform_device *pdev) diff --git a/drivers/ide/umc8672.c b/drivers/ide/umc8672.c index 1da076e0c917..e29978cf6197 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 2370fd82ebfe..c24140aff8e7 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 54525be4b5f8..eb4c01f7f253 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -32,13 +32,6 @@ # define SUPPORT_VLB_SYNC 1 #endif -/* - * Used to indicate "no IRQ", should be a value that cannot be an IRQ - * number. - */ - -#define IDE_NO_IRQ (-1) - typedef unsigned char byte; /* used everywhere */ /* @@ -122,8 +115,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 +163,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 }; @@ -484,55 +473,53 @@ enum { /* ide-cd */ /* Drive cannot eject the disc. */ - IDE_AFLAG_NO_EJECT = (1 << 3), + IDE_AFLAG_NO_EJECT = (1 << 1), /* Drive is a pre ATAPI 1.2 drive. */ - IDE_AFLAG_PRE_ATAPI12 = (1 << 4), + IDE_AFLAG_PRE_ATAPI12 = (1 << 2), /* TOC addresses are in BCD. */ - IDE_AFLAG_TOCADDR_AS_BCD = (1 << 5), + IDE_AFLAG_TOCADDR_AS_BCD = (1 << 3), /* TOC track numbers are in BCD. */ - IDE_AFLAG_TOCTRACKS_AS_BCD = (1 << 6), + IDE_AFLAG_TOCTRACKS_AS_BCD = (1 << 4), /* * Drive does not provide data in multiples of SECTOR_SIZE * when more than one interrupt is needed. */ - IDE_AFLAG_LIMIT_NFRAMES = (1 << 7), - /* Seeking in progress. */ - IDE_AFLAG_SEEKING = (1 << 8), + IDE_AFLAG_LIMIT_NFRAMES = (1 << 5), /* Saved TOC information is current. */ - IDE_AFLAG_TOC_VALID = (1 << 9), + IDE_AFLAG_TOC_VALID = (1 << 6), /* We think that the drive door is locked. */ - IDE_AFLAG_DOOR_LOCKED = (1 << 10), + IDE_AFLAG_DOOR_LOCKED = (1 << 7), /* SET_CD_SPEED command is unsupported. */ - IDE_AFLAG_NO_SPEED_SELECT = (1 << 11), - IDE_AFLAG_VERTOS_300_SSD = (1 << 12), - IDE_AFLAG_VERTOS_600_ESD = (1 << 13), - IDE_AFLAG_SANYO_3CD = (1 << 14), - IDE_AFLAG_FULL_CAPS_PAGE = (1 << 15), - IDE_AFLAG_PLAY_AUDIO_OK = (1 << 16), - IDE_AFLAG_LE_SPEED_FIELDS = (1 << 17), + IDE_AFLAG_NO_SPEED_SELECT = (1 << 8), + IDE_AFLAG_VERTOS_300_SSD = (1 << 9), + IDE_AFLAG_VERTOS_600_ESD = (1 << 10), + IDE_AFLAG_SANYO_3CD = (1 << 11), + IDE_AFLAG_FULL_CAPS_PAGE = (1 << 12), + IDE_AFLAG_PLAY_AUDIO_OK = (1 << 13), + IDE_AFLAG_LE_SPEED_FIELDS = (1 << 14), /* ide-floppy */ /* Avoid commands not supported in Clik drive */ - IDE_AFLAG_CLIK_DRIVE = (1 << 19), + IDE_AFLAG_CLIK_DRIVE = (1 << 15), /* Requires BH algorithm for packets */ - IDE_AFLAG_ZIP_DRIVE = (1 << 20), + IDE_AFLAG_ZIP_DRIVE = (1 << 16), /* Supports format progress report */ - IDE_AFLAG_SRFP = (1 << 22), + IDE_AFLAG_SRFP = (1 << 17), /* ide-tape */ - IDE_AFLAG_IGNORE_DSC = (1 << 23), + IDE_AFLAG_IGNORE_DSC = (1 << 18), /* 0 When the tape position is unknown */ - IDE_AFLAG_ADDRESS_VALID = (1 << 24), + IDE_AFLAG_ADDRESS_VALID = (1 << 19), /* Device already opened */ - IDE_AFLAG_BUSY = (1 << 25), + IDE_AFLAG_BUSY = (1 << 20), /* Attempt to auto-detect the current user block size */ - IDE_AFLAG_DETECT_BS = (1 << 26), + IDE_AFLAG_DETECT_BS = (1 << 21), /* Currently on a filemark */ - IDE_AFLAG_FILEMARK = (1 << 27), + IDE_AFLAG_FILEMARK = (1 << 22), /* 0 = no tape is loaded, so we don't rewind after ejecting */ - IDE_AFLAG_MEDIUM_PRESENT = (1 << 28), + IDE_AFLAG_MEDIUM_PRESENT = (1 << 23), - IDE_AFLAG_NO_AUTOCLOSE = (1 << 29), + IDE_AFLAG_NO_AUTOCLOSE = (1 << 24), }; /* device flags */ @@ -616,8 +603,6 @@ struct ide_drive_s { unsigned long dev_flags; unsigned long sleep; /* sleep until this time */ - unsigned long service_start; /* time we started last request */ - unsigned long service_time; /* service time of last request */ unsigned long timeout; /* max time to wait for irq */ special_t special; /* special action flags */ @@ -845,8 +830,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; @@ -887,8 +870,6 @@ typedef struct hwgroup_s { /* BOOL: protects all fields below */ volatile int busy; - /* BOOL: wake us up on timer expiry */ - unsigned int sleeping : 1; /* BOOL: polling active & poll_timeout field valid */ unsigned int polling : 1; @@ -909,6 +890,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 +1105,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. * @@ -1285,6 +1276,26 @@ extern void ide_stall_queue(ide_drive_t *drive, unsigned long timeout); extern void ide_timer_expiry(unsigned long); extern irqreturn_t ide_intr(int irq, void *dev_id); + +static inline int ide_lock_hwgroup(ide_hwgroup_t *hwgroup) +{ + if (hwgroup->busy) + return 1; + + hwgroup->busy = 1; + /* for atari only */ + ide_get_lock(ide_intr, hwgroup); + + return 0; +} + +static inline void ide_unlock_hwgroup(ide_hwgroup_t *hwgroup) +{ + /* for atari only */ + ide_release_lock(); + hwgroup->busy = 0; +} + extern void do_ide_request(struct request_queue *); void ide_init_disk(struct gendisk *, ide_drive_t *); @@ -1296,6 +1307,13 @@ extern int __ide_pci_register_driver(struct pci_driver *driver, struct module *o #define ide_pci_register_driver(d) pci_register_driver(d) #endif +static inline int ide_pci_is_in_compatibility_mode(struct pci_dev *dev) +{ + if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 5) != 5) + return 1; + return 0; +} + void ide_pci_setup_ports(struct pci_dev *, const struct ide_port_info *, int, hw_regs_t *, hw_regs_t **); void ide_setup_pci_noise(struct pci_dev *, const struct ide_port_info *); @@ -1369,12 +1387,13 @@ 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 */ IDE_HFLAG_UNMASK_IRQS = (1 << 25), + IDE_HFLAG_BROKEN_ALTSTATUS = (1 << 26), /* serialize ports if DMA is possible (for sl82c105) */ IDE_HFLAG_SERIALIZE_DMA = (1 << 27), /* force host out of "simplex" mode */ @@ -1407,6 +1426,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; @@ -1520,6 +1542,7 @@ void ide_unregister_region(struct gendisk *); void ide_undecoded_slave(ide_drive_t *); void ide_port_apply_params(ide_hwif_t *); +int ide_sysfs_register_port(ide_hwif_t *); struct ide_host *ide_host_alloc(const struct ide_port_info *, hw_regs_t **); void ide_host_free(struct ide_host *); @@ -1602,18 +1625,21 @@ 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 */ #define local_irq_set(flags) do { local_save_flags((flags)); local_irq_enable_in_hardirq(); } while (0) +char *ide_media_string(ide_drive_t *); + +extern struct device_attribute ide_dev_attrs[]; extern struct bus_type ide_bus_type; extern struct class *ide_port_class; |