Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bart/ide-2.6
Browse files Browse the repository at this point in the history
* 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
  ...
  • Loading branch information
Linus Torvalds committed Oct 13, 2008
2 parents 2be4ff2 + 9c6102d commit 7591103
Show file tree
Hide file tree
Showing 75 changed files with 2,656 additions and 2,574 deletions.
149 changes: 149 additions & 0 deletions Documentation/laptops/disk-shock-protection.txt
Original file line number Diff line number Diff line change
@@ -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.
29 changes: 0 additions & 29 deletions arch/mips/include/asm/mach-generic/ide.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
5 changes: 0 additions & 5 deletions arch/xtensa/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
38 changes: 2 additions & 36 deletions drivers/ide/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
19 changes: 13 additions & 6 deletions drivers/ide/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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
Expand All @@ -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/
23 changes: 2 additions & 21 deletions drivers/ide/arm/icside.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion drivers/ide/h8300/ide-h8300.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
Loading

0 comments on commit 7591103

Please sign in to comment.