diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-13 14:15:06 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-13 14:15:06 -0700 |
commit | 7591103c08abade60aeddb432ed0686ddd0de1c6 (patch) | |
tree | 523343b43b0c420666da18c64e1e9f21ff63dea5 | |
parent | 2be4ff2f084842839b041b793ed6237e8d1d315a (diff) | |
parent | 9c6102d446985bca9c426cb2d9b478ed21d2b024 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bart/ide-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/bart/ide-2.6: (66 commits)
ata: Add documentation for hard disk shock protection interface (v3)
ide: Implement disk shock protection support (v4)
ide-cd: fix printk format warning
piix: add Hercules EC-900 mini-notebook to ich_laptop short cable list
ide-atapi: assign taskfile flags per device type
ide-cd: move cdrom_info.dma to ide_drive_t.dma
ide: add ide_drive_t.dma flag
ide-cd: add a debug_mask module parameter
ide-cd: convert driver to new ide debugging macro (v3)
ide: move SFF DMA code to ide-dma-sff.c
ide: cleanup ide-dma.c
ide: cleanup ide_build_dmatable()
ide: remove needless includes from ide-dma.c
ide: switch to DMA-mapping API part #2
ide: make ide_dma_timeout() available also for CONFIG_BLK_DEV_IDEDMA_SFF=n
ide: make ide_dma_lost_irq() available also for CONFIG_BLK_DEV_IDEDMA_SFF=n
ide: __ide_dma_end() -> ide_dma_end()
pmac: remove needless pmac_ide_destroy_dmatable() wrapper
pmac: remove superfluous pmif == NULL checks
ide: Two fixes regarding memory allocation
...
75 files changed, 2656 insertions, 2574 deletions
diff --git a/Documentation/laptops/disk-shock-protection.txt b/Documentation/laptops/disk-shock-protection.txt new file mode 100644 index 00000000000..0e6ba266383 --- /dev/null +++ b/Documentation/laptops/disk-shock-protection.txt @@ -0,0 +1,149 @@ +Hard disk shock protection +========================== + +Author: Elias Oltmanns <eo@nebensachen.de> +Last modified: 2008-10-03 + + +0. Contents +----------- + +1. Intro +2. The interface +3. References +4. CREDITS + + +1. Intro +-------- + +ATA/ATAPI-7 specifies the IDLE IMMEDIATE command with unload feature. +Issuing this command should cause the drive to switch to idle mode and +unload disk heads. This feature is being used in modern laptops in +conjunction with accelerometers and appropriate software to implement +a shock protection facility. The idea is to stop all I/O operations on +the internal hard drive and park its heads on the ramp when critical +situations are anticipated. The desire to have such a feature +available on GNU/Linux systems has been the original motivation to +implement a generic disk head parking interface in the Linux kernel. +Please note, however, that other components have to be set up on your +system in order to get disk shock protection working (see +section 3. References below for pointers to more information about +that). + + +2. The interface +---------------- + +For each ATA device, the kernel exports the file +block/*/device/unload_heads in sysfs (here assumed to be mounted under +/sys). Access to /sys/block/*/device/unload_heads is denied with +-EOPNOTSUPP if the device does not support the unload feature. +Otherwise, writing an integer value to this file will take the heads +of the respective drive off the platter and block all I/O operations +for the specified number of milliseconds. When the timeout expires and +no further disk head park request has been issued in the meantime, +normal operation will be resumed. The maximal value accepted for a +timeout is 30000 milliseconds. Exceeding this limit will return +-EOVERFLOW, but heads will be parked anyway and the timeout will be +set to 30 seconds. However, you can always change a timeout to any +value between 0 and 30000 by issuing a subsequent head park request +before the timeout of the previous one has expired. In particular, the +total timeout can exceed 30 seconds and, more importantly, you can +cancel a previously set timeout and resume normal operation +immediately by specifying a timeout of 0. Values below -2 are rejected +with -EINVAL (see below for the special meaning of -1 and -2). If the +timeout specified for a recent head park request has not yet expired, +reading from /sys/block/*/device/unload_heads will report the number +of milliseconds remaining until normal operation will be resumed; +otherwise, reading the unload_heads attribute will return 0. + +For example, do the following in order to park the heads of drive +/dev/sda and stop all I/O operations for five seconds: + +# echo 5000 > /sys/block/sda/device/unload_heads + +A simple + +# cat /sys/block/sda/device/unload_heads + +will show you how many milliseconds are left before normal operation +will be resumed. + +A word of caution: The fact that the interface operates on a basis of +milliseconds may raise expectations that cannot be satisfied in +reality. In fact, the ATA specs clearly state that the time for an +unload operation to complete is vendor specific. The hint in ATA-7 +that this will typically be within 500 milliseconds apparently has +been dropped in ATA-8. + +There is a technical detail of this implementation that may cause some +confusion and should be discussed here. When a head park request has +been issued to a device successfully, all I/O operations on the +controller port this device is attached to will be deferred. That is +to say, any other device that may be connected to the same port will +be affected too. The only exception is that a subsequent head unload +request to that other device will be executed immediately. Further +operations on that port will be deferred until the timeout specified +for either device on the port has expired. As far as PATA (old style +IDE) configurations are concerned, there can only be two devices +attached to any single port. In SATA world we have port multipliers +which means that a user-issued head parking request to one device may +actually result in stopping I/O to a whole bunch of devices. However, +since this feature is supposed to be used on laptops and does not seem +to be very useful in any other environment, there will be mostly one +device per port. Even if the CD/DVD writer happens to be connected to +the same port as the hard drive, it generally *should* recover just +fine from the occasional buffer under-run incurred by a head park +request to the HD. Actually, when you are using an ide driver rather +than its libata counterpart (i.e. your disk is called /dev/hda +instead of /dev/sda), then parking the heads of one drive (drive X) +will generally not affect the mode of operation of another drive +(drive Y) on the same port as described above. It is only when a port +reset is required to recover from an exception on drive Y that further +I/O operations on that drive (and the reset itself) will be delayed +until drive X is no longer in the parked state. + +Finally, there are some hard drives that only comply with an earlier +version of the ATA standard than ATA-7, but do support the unload +feature nonetheless. Unfortunately, there is no safe way Linux can +detect these devices, so you won't be able to write to the +unload_heads attribute. If you know that your device really does +support the unload feature (for instance, because the vendor of your +laptop or the hard drive itself told you so), then you can tell the +kernel to enable the usage of this feature for that drive by writing +the special value -1 to the unload_heads attribute: + +# echo -1 > /sys/block/sda/device/unload_heads + +will enable the feature for /dev/sda, and giving -2 instead of -1 will +disable it again. + + +3. References +------------- + +There are several laptops from different vendors featuring shock +protection capabilities. As manufacturers have refused to support open +source development of the required software components so far, Linux +support for shock protection varies considerably between different +hardware implementations. Ideally, this section should contain a list +of pointers at different projects aiming at an implementation of shock +protection on different systems. Unfortunately, I only know of a +single project which, although still considered experimental, is fit +for use. Please feel free to add projects that have been the victims +of my ignorance. + +- http://www.thinkwiki.org/wiki/HDAPS + See this page for information about Linux support of the hard disk + active protection system as implemented in IBM/Lenovo Thinkpads. + + +4. CREDITS +---------- + +This implementation of disk head parking has been inspired by a patch +originally published by Jon Escombe <lists@dresco.co.uk>. My efforts +to develop an implementation of this feature that is fit to be merged +into mainline have been aided by various kernel developers, in +particular by Tejun Heo and Bartlomiej Zolnierkiewicz. diff --git a/arch/mips/include/asm/mach-generic/ide.h b/arch/mips/include/asm/mach-generic/ide.h index 73008f7bdc9..9c93a5b36f2 100644 --- a/arch/mips/include/asm/mach-generic/ide.h +++ b/arch/mips/include/asm/mach-generic/ide.h @@ -19,35 +19,6 @@ #include <linux/stddef.h> #include <asm/processor.h> -static __inline__ int ide_probe_legacy(void) -{ -#ifdef CONFIG_PCI - struct pci_dev *dev; - /* - * This can be called on the ide_setup() path, super-early in - * boot. But the down_read() will enable local interrupts, - * which can cause some machines to crash. So here we detect - * and flag that situation and bail out early. - */ - if (no_pci_devices()) - return 0; - dev = pci_get_class(PCI_CLASS_BRIDGE_EISA << 8, NULL); - if (dev) - goto found; - dev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL); - if (dev) - goto found; - return 0; -found: - pci_dev_put(dev); - return 1; -#elif defined(CONFIG_EISA) || defined(CONFIG_ISA) - return 1; -#else - return 0; -#endif -} - /* MIPS port and memory-mapped I/O string operations. */ static inline void __ide_flush_prologue(void) { diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c index a00359e8f7a..9606d2bd1dd 100644 --- a/arch/xtensa/kernel/setup.c +++ b/arch/xtensa/kernel/setup.c @@ -53,11 +53,6 @@ extern struct fd_ops no_fd_ops; struct fd_ops *fd_ops; #endif -#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) -extern struct ide_ops no_ide_ops; -struct ide_ops *ide_ops; -#endif - extern struct rtc_ops no_rtc_ops; struct rtc_ops *rtc_ops; diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index b50b5dac95b..6c6dd2faced 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -54,38 +54,6 @@ menuconfig IDE if IDE -config BLK_DEV_IDE - tristate "Enhanced IDE/MFM/RLL disk/cdrom/tape/floppy support" - ---help--- - If you say Y here, you will use the full-featured IDE driver to - control up to ten ATA/IDE interfaces, each being able to serve a - "master" and a "slave" device, for a total of up to twenty ATA/IDE - disk/cdrom/tape/floppy drives. - - Useful information about large (>540 MB) IDE disks, multiple - interfaces, what to do if ATA/IDE devices are not automatically - detected, sound card ATA/IDE ports, module support, and other - topics, is contained in <file:Documentation/ide/ide.txt>. For detailed - information about hard drives, consult the Disk-HOWTO and the - Multi-Disk-HOWTO, available from - <http://www.tldp.org/docs.html#howto>. - - To fine-tune ATA/IDE drive/interface parameters for improved - performance, look for the hdparm package at - <ftp://ibiblio.org/pub/Linux/system/hardware/>. - - To compile this driver as a module, choose M here and read - <file:Documentation/ide/ide.txt>. The module will be called ide-mod. - Do not compile this driver as a module if your root file system (the - one containing the directory /) is located on an IDE device. - - If you have one or more IDE drives, say Y or M here. If your system - has no IDE drives, or if memory requirements are really tight, you - could say N here, and select the "Old hard disk driver" below - instead to save about 13 KB of memory in the kernel. - -if BLK_DEV_IDE - comment "Please see Documentation/ide/ide.txt for help/info on IDE drives" config IDE_TIMINGS @@ -348,7 +316,7 @@ config BLK_DEV_IDEPCI config IDEPCI_PCIBUS_ORDER bool "Probe IDE PCI devices in the PCI bus order (DEPRECATED)" - depends on BLK_DEV_IDE=y && BLK_DEV_IDEPCI + depends on IDE=y && BLK_DEV_IDEPCI default y help Probe IDE PCI devices in the order in which they appear on the @@ -729,7 +697,7 @@ endif config BLK_DEV_IDE_PMAC tristate "PowerMac on-board IDE support" - depends on PPC_PMAC && IDE=y && BLK_DEV_IDE=y + depends on PPC_PMAC && IDE=y select IDE_TIMINGS help This driver provides support for the on-board IDE controller on @@ -963,6 +931,4 @@ config BLK_DEV_IDEDMA def_bool BLK_DEV_IDEDMA_SFF || BLK_DEV_IDEDMA_PMAC || \ BLK_DEV_IDEDMA_ICS || BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA -endif - endif # IDE diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index 308b8a12f31..ceaf779054e 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile @@ -5,24 +5,25 @@ 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-pio-blacklist.o + ide-taskfile.o ide-park.o ide-pio-blacklist.o # core IDE code ide-core-$(CONFIG_IDE_TIMINGS) += ide-timings.o ide-core-$(CONFIG_IDE_ATAPI) += ide-atapi.o ide-core-$(CONFIG_BLK_DEV_IDEPCI) += setup-pci.o 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 -obj-$(CONFIG_BLK_DEV_IDE) += ide-core.o +obj-$(CONFIG_IDE) += ide-core.o ifeq ($(CONFIG_IDE_ARM), y) ide-arm-core-y += arm/ide_arm.o obj-y += ide-arm-core.o endif -obj-$(CONFIG_BLK_DEV_IDE) += legacy/ pci/ +obj-$(CONFIG_IDE) += legacy/ pci/ obj-$(CONFIG_IDEPCI_PCIBUS_ORDER) += ide-scan-pci.o @@ -31,15 +32,21 @@ ifeq ($(CONFIG_BLK_DEV_CMD640), y) obj-y += cmd640-core.o endif -obj-$(CONFIG_BLK_DEV_IDE) += ppc/ +obj-$(CONFIG_IDE) += ppc/ obj-$(CONFIG_IDE_H8300) += h8300/ obj-$(CONFIG_IDE_GENERIC) += ide-generic.o obj-$(CONFIG_BLK_DEV_IDEPNP) += ide-pnp.o +ide-disk_mod-y += ide-disk.o ide-disk_ioctl.o ide-cd_mod-y += ide-cd.o ide-cd_ioctl.o ide-cd_verbose.o ide-floppy_mod-y += ide-floppy.o ide-floppy_ioctl.o -obj-$(CONFIG_BLK_DEV_IDEDISK) += ide-disk.o +ifeq ($(CONFIG_IDE_PROC_FS), y) + ide-disk_mod-y += ide-disk_proc.o + ide-floppy_mod-y += ide-floppy_proc.o +endif + +obj-$(CONFIG_BLK_DEV_IDEDISK) += ide-disk_mod.o obj-$(CONFIG_BLK_DEV_IDECD) += ide-cd_mod.o obj-$(CONFIG_BLK_DEV_IDEFLOPPY) += ide-floppy_mod.o obj-$(CONFIG_BLK_DEV_IDETAPE) += ide-tape.o @@ -54,4 +61,4 @@ ifeq ($(CONFIG_BLK_DEV_PLATFORM), y) obj-y += ide-platform-core.o endif -obj-$(CONFIG_BLK_DEV_IDE) += arm/ mips/ +obj-$(CONFIG_IDE) += arm/ mips/ diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c index 70f5b164828..76bdc9a27f6 100644 --- a/drivers/ide/arm/icside.c +++ b/drivers/ide/arm/icside.c @@ -372,25 +372,6 @@ static int icside_dma_test_irq(ide_drive_t *drive) ICS_ARCIN_V6_INTRSTAT_1)) & 1; } -static void icside_dma_timeout(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - - printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name); - - if (icside_dma_test_irq(drive)) - return; - - ide_dump_status(drive, "DMA timeout", hwif->tp_ops->read_status(hwif)); - - icside_dma_end(drive); -} - -static void icside_dma_lost_irq(ide_drive_t *drive) -{ - printk(KERN_ERR "%s: IRQ lost\n", drive->name); -} - static int icside_dma_init(ide_hwif_t *hwif, const struct ide_port_info *d) { hwif->dmatable_cpu = NULL; @@ -406,8 +387,8 @@ static const struct ide_dma_ops icside_v6_dma_ops = { .dma_start = icside_dma_start, .dma_end = icside_dma_end, .dma_test_irq = icside_dma_test_irq, - .dma_timeout = icside_dma_timeout, - .dma_lost_irq = icside_dma_lost_irq, + .dma_timeout = ide_dma_timeout, + .dma_lost_irq = ide_dma_lost_irq, }; #else #define icside_v6_dma_ops NULL diff --git a/drivers/ide/h8300/ide-h8300.c b/drivers/ide/h8300/ide-h8300.c index bde7a585f19..e2cdd2e9cde 100644 --- a/drivers/ide/h8300/ide-h8300.c +++ b/drivers/ide/h8300/ide-h8300.c @@ -80,7 +80,7 @@ static void h8300_tf_load(ide_drive_t *drive, ide_task_t *task) outb(tf->lbah, io_ports->lbah_addr); if (task->tf_flags & IDE_TFLAG_OUT_DEVICE) - outb((tf->device & HIHI) | drive->select.all, + outb((tf->device & HIHI) | drive->select, io_ports->device_addr); } diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c index 2427c380b3d..244a8a052ce 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c @@ -290,7 +290,7 @@ static int do_drive_get_GTF(ide_drive_t *drive, DEBPRINT("ENTER: %s at %s, port#: %d, hard_port#: %d\n", hwif->name, dev->bus_id, port, hwif->channel); - if (!drive->present) { + if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) { DEBPRINT("%s drive %d:%d not present\n", hwif->name, hwif->channel, port); goto out; @@ -420,8 +420,9 @@ static int do_drive_set_taskfiles(ide_drive_t *drive, DEBPRINT("ENTER: %s, hard_port#: %d\n", drive->name, drive->dn); - if (!drive->present) + if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) goto out; + if (!gtf_count) /* shouldn't be here */ goto out; @@ -660,7 +661,8 @@ void ide_acpi_set_state(ide_hwif_t *hwif, int on) if (!drive->acpidata->obj_handle) drive->acpidata->obj_handle = ide_acpi_drive_get_handle(drive); - if (drive->acpidata->obj_handle && drive->present) { + if (drive->acpidata->obj_handle && |