How to hotswap Ultrabay devices
The following discusses hotswap (AKA "hotplug") of devices in the Ultrabay.
Contents
Which driver?
This may be confusing, so first a quick history lesson.
Older ThinkPads (up to the R51, T42p and X40) where fully IDE (PATA) for both the internal HDD and Ultrabay. For this there are two drivers, the modern libata based ata_piix and the old legacy ide-disk driver. Most modern distributions will default to the ata_piix driver, which is really what you want anyway.
ThinkPads like the R52, T43, T43p, X41 and X41 Tablet are strange hybrids, they have a Serial-ATA (SATA) chipset for the internal disk controller, but through a separate SATA-PATA bridge chip the actual disk is still legacy IDE. The Ultrabay though is still connected to the legacy IDE host controller. This results in a setup where the internal disk is handled by a SATA driver and the Ultrabay is handled by either ata_piix or ide-disk.
ThinkPads like the R60, T60 and Z60 series are also hybrids, but they use a native SATA HDD internal. Just like with the previous models though you end up with two separate drivers for the internal HDD and the Ultrabay.
The latest generation ThinkPads like the R400, R500, T400, T500, W500, W700, X200, and X300 are all fully SATA for both the internal HDD and the Ultrabay device, so both are handled by the same SATA driver.
TODO
|
Figure out in which category the X60 series ThinkPads truly belong. Some of these machines might have been shipped with a 1.8" HDD which is likely to be PATA, in fact the HMM even states so. But tabook and ltwbook only lists SATA models, so the 1.8" model might never have shipped. But even if it did there will be a SATA-PATA bridge chip, so from the OS it will look like SATA.
|
Thinkpad | internal HDD | Ultrabay | Driver |
---|---|---|---|
R30, R31, R32, R40, R50, R50e, R50p, R51 | Legacy 2.5" IDE (PATA) | Legacy IDE (PATA) | ata_piix |
R52 | Legacy 2.5" PATA HDD with conversion to SATA | Legacy IDE (PATA) | ahci + ata_piix |
R400, R500 | 2.5" SATA | SATA | ahci |
R60, R61 | 2.5" SATA | Legacy 2.5" IDE (PATA) | ahci + ata_piix |
T20, T21, T22, T23, T30, T40, T40p, T41, T41p, T42, T42p | Legacy 2.5" IDE (PATA) | Legacy IDE (PATA) | ata_piix |
T43, T43p | Legacy 2.5" PATA HDD with conversion to SATA | Legacy IDE (PATA) | ahci + ata_piix |
T60, T60p, T61, T61p | 2.5" SATA | Legacy 2.5" IDE (PATA) | ahci + ata_piix |
T400, T500 | 2.5" SATA | SATA | ahci |
X20, X21, X22, X23, X24, X30, X31, X32 | Legacy 2.5" IDE (PATA) | Legacy IDE (PATA) | ata_piix |
X40 | Legacy 1.8" IDE (PATA) | Legacy IDE (PATA) | ata_piix |
X41, X41 Tablet | Legacy 1.8" PATA HDD with conversion to SATA | Legacy IDE (PATA) | ahci + ata_piix |
X60, X60s, X60 Tablet, X61, X61s, X61 Tablet | 2.5" HDD is SATA, 1.8" HDD is PATA with SATA conversion | Legacy IDE (PATA) | ahci + ata_piix |
X200, X200 Tablet, X300, X301 | 2.5" SATA | SATA | ahci |
W500, W700 | 2.5" SATA | SATA | ahci |
Choosing the right driver: new style ata_piix vs old style piix together with ide-disk
For ICH5,6,7,8, systems, whether you have an older IDE only thinkpad, or a newer thinkpad like the T/Z61p, there is one SATA bus for the system hard drive and an IDE bus for the Ultrabay (even if your Ultrabay happens to have a SATA drive, as it'll be seen as an IDE device), you'll have two drivers to chose from for your ultrabay: the old IDE/piix+ide-disk driver, and the newer PATA (=IDE) support of the newer ata_piix driver.
piix+ide-disk are part of the old original IDE driver and your Ultrabay device will show up as /dev/hda.
ata-piix is the new SATA/PATA (=IDE) driver that will cause your Ultrabay hard drive to show up as /dev/sda and your CD-ROM as /dev/sr0.
The two things to know are: (1) you want to use ata_piix and (2) if you build piix in (CONFIG_BLK_DEV_PIIX enabled), or load it as a module, it'll take over the IDE bus and prevent ATA_PIIX from seeing your Ultrabay. You don't want that.
The longer details are:
You don't want the piix+ide-disk combo because even as modules, you will not be able to unload piix to reset the bus if there are issues swapping devices (with ata_piix, even if you forget to unregister a drive before removing it, you can unload the module and reload it to reset the bus after the fact if you have a newer ThinkPad with a separate AHCI/SATA bus for the boot drive).
As for hotswap, with piix+ide-disk, you can read the section below, but after more than one day of trying on 2.6.22.15 (as piix+ide-disk was taking over my IDE bus, and stopping me from using ata_piix before I removed it), I was not able to get hotswapping to work with piix+ide-disk (lt_hotswap would not even build on 2.6.22.15).
hotswap just works with ata_pixx on 2.6.22, and reportedly with anything newer than 2.6.18, so you want to get rid of piix+ide-disk. There are several ways to do that:
- if piix is built in your kernel (CONFIG_BLK_DEV_PIIX):
- rebuild your kernel with CONFIG_BLK_DEV_PIIX turned off.
- if you don't want to rebuild your kernel, try disabling the IDE bus grabbing by that driver with ide0=noprobe hda=noprobe hdb=noprobe in your grub/lilo config (adjust the drive letters as appropriate, but note that this did not work for me on 2.6.22.15: the drive didn't show up on the piix bus, but it didn't show up on the ata_piix bus either).
- if piix is built in as a module
- you can move out the module in /lib/modules/ver/kernel/drivers/ide/pci/piix.ko and reboot.
- or build a new kernel, again with CONFIG_BLK_DEV_PIIX turned off.
- or add options ide_core options="ide0=noprobe hda=noprobe hdb=noprobe" to your modprobe.conf is supposed to work too (but didn't work on 2.6.22.15, see comment above)
Then, continue this document to see how to do hotswap with ata_piix (if you are lucky enough to have a newer SATA ThinkPad where the ata_piix driver only runs the Ultrabay, and you have a separate bus and ahci driver for your main drive, it is recommended to have ata_piix as a module (CONFIG_ATA_PIIX=m) so that you can unload/reload it if your bus gets in a bad state after a failed hotswap)
When using the ata_piix driver
The following applies when using the ata_piix driver, which is necessary for many recent ThinkPad models that use an Intel ICH6-M controller. See also Problems with SATA and Linux.
Mainline kernels before 2.6.18 cannot reliably recognize newly (re-)inserted Ultrabay drives without a reboot. There are experimental hotplug patches against pre-2.6.18 mainline kernels here.
- Available hotplug patches
- Confirmed to work on the following laptops, with bus the following ID
ID will typically be 1 if you only have an IDE bus (0 is boot drive, 1 is Ultrabay), and it'll be 4 if you have a SATA bus your system boots from (ID 0-3) and an IDE bus for your Ultrabay (ID 4-5).
Note that even on a given laptop model the ID can vary depending on whether your kernel has drivers that configure your boot drive is using the old style IDE driver (which doesn't add IDs before your Ultrabay), or whether your boot drive is using the new style driver (which adds IDs before your Ultrabay)
Hotplug just works with kernels newer than 2.6.18 ( or older kernels that were patched to support ata_piix hotplug (don't try it otherwise!))
First, it is recommended you find the right SCSI ID for your drive to hotswap and unregister it before removing it (this works with all recent mainline kernels):
# echo 1 > /sys/class/scsi_device/$ID:0:0:0/device/delete
# echo eject > /proc/acpi/ibm/bay
The drive can now be ejected (without this, your IDE bus may complain if you just yank a drive, but you can usually recover by unloading/reloading the ata_piix module on a SATA laptop if your main drive is not on the ata_piix bus)
You can then issue the following after inserting an Ultrabay drive to rescan the port:
# echo 0 0 0 > /sys/class/scsi_host/host$ID/scan
The inserted drive should now be recognized by the kernel, and appropriate /dev/* entries created automatically (e.g., by udev).
Ted T'so has also written this hotswap patch, which may or may not be needed for you, see hotswap patch and report back
Scripts for hotswapping
The following scripts and acpid daemon configuration files do the following:
- Automatically unmounts the relevant filesystems and power off the Ultrabay when the Ultrabay eject lever is released. Screams if some filesystem can't be unmounted.
- Rescans the Ultrabay port when then Ultrabay eject lever is pushed back in.
They assumes you're using the ata_piix driver with an appropriate kernel (see above).
Create /usr/local/sbin/ultrabay_insert with permissions 755:
#!/bin/bash echo 12 > /proc/acpi/ibm/beep sync echo 0 0 0 > /sys/class/scsi_host/host1/scan
Create /usr/local/sbin/ultrabay_eject with permissions 755:
#!/bin/bash ULTRABAY_SYSDIR='/sys/class/scsi_device/1:0:0:0/device' shopt -s nullglob # Umount the filesystem(s) backed by the given major:minor device(s) unmount_rdev() { perl - "$@" <<'EOPERL' # let's do it in Perl for $major_minor (@ARGV) { $major_minor =~ m/^(\d+):(\d+)$/ or die; push(@tgt_rdevs, ($1<<8)|$2); } # Sort by reverse length of mount point, to unmount sub-directories first open MOUNTS,"</proc/mounts" or die "$!"; @mounts=sort { length($b->[1]) <=> length($a->[1]) } map { [ split ] } <MOUNTS>; close MOUNTS; foreach $m (@mounts) { ($dev,$dir)=@$m; next unless -b $dev; $rdev=(stat($dev))[6]; next unless grep($_==$rdev, @tgt_rdevs); system("umount","-v","$dir")==0 or $bad=1; } exit 1 if $bad; EOPERL } # Get the UltraBay's /dev/foo block device node ultrabay_dev_node() { UDEV_PATH="`readlink -e "$ULTRABAY_SYSDIR/block:"*`" || return 1 UDEV_NAME="`udevinfo -q name -p $UDEV_PATH`" || return 1 echo /dev/$UDEV_NAME } if [ -d $ULTRABAY_SYSDIR ]; then sync # Unmount filesystems backed by this device unmount_rdev `cat $ULTRABAY_SYSDIR/block\:*/dev \ $ULTRABAY_SYSDIR/block\:*/*/dev` \ || { echo 10 > /proc/acpi/ibm/beep; # error tone exit 1; } sync # Nicely power off the device DEVNODE=`ultrabay_dev_node` && hdparm -Y $DEVNODE # Let HAL+KDE notice the unmount and let the disk spin down sleep 0.5 # Unregister this SCSI device: sync echo 1 > $ULTRABAY_SYSDIR/delete fi sync # We really need a 3 sec pause here otherwise the system will freeze.. sleep 3 # Turn off power to the UltraBay: if [ -d /sys/devices/platform/bay.0 ]; then echo 1 > /sys/devices/platform/bay.0/eject elif [ -e /proc/acpi/ibm/bay ]; then echo eject > /proc/acpi/ibm/bay fi # Tell the user we're OK echo 12 > /proc/acpi/ibm/beep
Use the modified version below if the above doesn't work for you (for kernels 2.6.25+ due to "ULTRABAY_SYSDIR/block\:*/dev" path change). It was tested on a Thinkpad X41 with Fedora 9 and kernel 2.6.25.11:
#!/bin/bash ULTRABAY_SYSDIR='/sys/class/scsi_device/1:0:0:0/device' shopt -s nullglob # Umount the filesystem(s) backed by the given major:minor device(s) unmount_rdev() { perl - "$@" <<'EOPERL' # let's do it in Perl for $major_minor (@ARGV) { $major_minor =~ m/^(\d+):(\d+)$/ or die; push(@tgt_rdevs, ($1<<8)|$2); } # Sort by reverse length of mount point, to unmount sub-directories first open MOUNTS,"</proc/mounts" or die "$!"; @mounts=sort { length($b->[1]) <=> length($a->[1]) } map { [ split ] } <MOUNTS>; close MOUNTS; foreach $m (@mounts) { ($dev,$dir)=@$m; next unless -b $dev; $rdev=(stat($dev))[6]; next unless grep($_==$rdev, @tgt_rdevs); system("umount","-v","$dir")==0 or $bad=1; } exit 1 if $bad; EOPERL } # Get the UltraBay's /dev/foo block device node ultrabay_dev_node() { UDEV_PATH="`readlink -e "$ULTRABAY_SYSDIR/block/"*`" || return 1 UDEV_NAME="`udevinfo -q name -p $UDEV_PATH`" || return 1 echo /dev/$UDEV_NAME } if [ -d $ULTRABAY_SYSDIR ]; then sync # Unmount filesystems backed by this device unmount_rdev `cat $ULTRABAY_SYSDIR/block/*/dev \ $ULTRABAY_SYSDIR/block/*/*/dev` \ || { echo 10 > /proc/acpi/ibm/beep; # error tone exit 1; } sync # Nicely power off the device DEVNODE=`ultrabay_dev_node` && hdparm -Y $DEVNODE # Let HAL+KDE notice the unmount and let the disk spin down sleep 0.5 # Unregister this SCSI device: sync echo 1 > $ULTRABAY_SYSDIR/delete fi # We really need a 3 sec pause here otherwise the system will freeze.. sleep 3 # Turn off power to the UltraBay: dock=$( /bin/grep ata_bay /sys/devices/platform/dock.?/type ) dock=${dock%%/type:ata_bay} # needed for 2.6.27 and later if [ -n "$dock" -a -d "$dock" ]; then echo 1 > $dock/undock elif [ -d /sys/devices/platform/bay.0 ]; then echo 1 > /sys/devices/platform/bay.0/eject elif [ -e /proc/acpi/ibm/bay ]; then echo eject > /proc/acpi/ibm/bay fi # Tell the user we're OK echo 12 > /proc/acpi/ibm/beep
Create /etc/acpi/events/ultrabay-insert:
event=ibm/bay MSTR 00000001 00000000 action=/usr/local/sbin/ultrabay_insert
Create /etc/acpi/events/ultrabay-eject:
event=ibm/bay MSTR 00000003 00000000 action=/usr/local/sbin/ultrabay_eject
Restart acpid.
If the ata_piix driver is built in the kernel, it will catch bay events and you will see the following message in your system log:
thinkpad_acpi: another device driver is already handling bay events thinkpad_acpi: disabling subdriver bay
You should load thinkpad_acpi before ata_piix if you want it to handle bay events.
Using the generic bay driver and udev
Starting from kernel 2.6.23-rc3, it's possible to use the generic bay driver in combination with udev to hotswap. Please check if CONFIG_ACPI_BAY is enabled (module or built-in) in your kernel configuration.
Create /etc/udev/rules.d/ibm-ultrabay.rules:
ENV{BAY_EVENT}=="3", KERNEL=="bay.0", ACTION=="change", SUBSYSTEM=="platform", RUN+="/usr/local/sbin/ultrabay_eject" ENV{BAY_EVENT}=="1", KERNEL=="bay.0", ACTION=="change", SUBSYSTEM=="platform", RUN+="/usr/local/sbin/ultrabay_insert"
Starting with kernel 2.6.28, the bay driver was removed from the mainline kernel. The dock driver replaced it completely. Make sure CONFIG_ACPI_DOCK is enabled in the kernel, and use the following udev rules:
ENV{EVENT}=="undock", KERNEL=="dock.2", ACTION=="change", SUBSYSTEM=="platform", RUN+="/usr/local/sbin/ultrabay_eject" ENV{EVENT}=="dock", KERNEL=="dock.2", ACTION=="change", SUBSYSTEM=="platform", RUN+="/usr/local/sbin/ultrabay_insert"
However, the ultra_eject script needs to be changed, otherwise udev goes into an infinite event loop. It will send undock events every few seconds forever. That means as soon as the ultrabay is plugged in again, it will be immediately ejected. For kernels 2.6.28 and higher, the bay cannot be powered off using this method, so change the end of the script to read:
# Turn off power to the UltraBay: if [ -d /sys/devices/platform/bay.0 ]; then echo 1 > /sys/devices/platform/bay.0/eject elif [ -e /proc/acpi/ibm/bay ]; then echo eject > /proc/acpi/ibm/bay fi # Tell the user we're OK echo 12 > /proc/acpi/ibm/beep
Alternatively, instead of modifying the script, use the libata-acpi method below. This was tested on a T61p running Gentoo with tuxonice 2.6.28-r8 without any issues.
Using libata-acpi and udev
Starting from kernel 2.6.26-rc5, it's possible to use libata-acpi in combination with udev to hotswap. Please check if CONFIG_ATA_ACPI is enabled in your kernel configuration.
For 2.6.25, you need two patches which can be easily backported ([1],[2]).
Create /etc/udev/rules.d/ibm-ultrabay.rules:
ENV{BAY_EVENT}=="3", ACTION=="change", SUBSYSTEM=="scsi", RUN+="/usr/local/sbin/ultrabay_eject"
Model-specific notes
See the table above for a list of ata_piix supported laptops and the bus ID to use.
HAL support
Many programs, KDE included, rely on HAL to get notifications and information about device hotplugging. You need to tell HAL that devices connected the UltraBay port are hotpluggable. To do so, create the file /etc/hal/fdi/information/10-ultrabay.fdi as follows:
<?xml version="1.0" encoding="UTF-8"?> <!-- -*- SGML -*- --> <deviceinfo version="0.2"> <device> <!-- UltraBay Devices --> <match key="storage.bus" string="scsi"> <match key="storage.physical_device" string="/org/freedesktop/Hal/devices/pci_8086_2653_scsi_host_0_scsi_device_lun0"> <merge key="storage.hotpluggable" type="bool">true</merge> </match> </match> </device> </deviceinfo>
The string "8086_2653" may need to be changed to match your ThinkPad model; see below.
Details
By default, HAL doesn't know that UltraBay devices are hotpluggable:
# PHYSDEV=/org/freedesktop/Hal/devices/pci_8086_2653_scsi_host_0_scsi_device_lun0 # UDI=`hal-find-by-property --key storage.physical_device --string $PHYSDEV` || echo Failed # hal-get-property --udi $UDI --key block.device /dev/sdb # hal-get-property --udi $UDI --key storage.hotpluggable false
After creating /etc/hal/fdi/information/10-ultrabay.fdi as above and re-plugging the device, it will get marked correctly:
# PHYSDEV=/org/freedesktop/Hal/devices/pci_8086_2653_scsi_host_0_scsi_device_lun0 # UDI=`hal-find-by-property --key storage.physical_device --string $PHYSDEV` || echo Failed # hal-get-property --udi $UDI --key block.device /dev/sdb # hal-get-property --udi $UDI --key storage.hotpluggable true
The string "8086_2653" gives the PCI ID of the Intel 82801FBM southbridge. If your model has a different southbridge, or the UltraBay is attached to a different port, then you can find the appropriate storage.physical_device value by finding out the block device of the currently running UltraBay device (/dev/sdb in the following example) and then running:
# DEVICE=/dev/sdb # UDI=`hal-find-by-property --key block.device --string $DEVICE` || echo Failed # hal-get-property --udi $UDI --key storage.physical_device /org/freedesktop/Hal/devices/pci_8086_2653_scsi_host_0_scsi_device_lun0
If you have a different storage.physical_device value, please report your findings.
ID | ThinkPad model | South Bridge chip |
---|---|---|
8086_248a | 2366-83U (T30), 2647-MG3 (T23) | Intel 82801CAM IDE U100 (rev 2) |
8086_2653 | 2525FAG (X41), ? (T43) | Intel 82801FBM (ICH6-M) |
8086_24ca | 237358U (T40), 2373KXU (T42p) | Intel 82801DBM (ICH4-M) |
8086_27c4 | X60 | Intel 82801GBM (ICH7 Family) |
8086_27df | Z61p, T60, T60p | Intel 82801GBM/GHM (ICH7 Family) |
8086_2850 | T61, T61p | Intel 82801H (ICH8 Family) |
When using the ide-disk driver
The following applies if you use the ide-disk driver for the UltraBay device.
Note that essentially, you shouldn't be using this driver, and use ata_piix instead unless you're running an older kernel where ata_piix won't work for you
Hotswapping is supposed to be supported as well, using either hdparm/Debian hotswap or lt_hotswap to (un)register IDE devices. The latter is the recommended method with kernels from 2.6, since it will leave DMA working. However, for recent models (R52, T43, X41, Z60 and later) no method is known to work while maintaining DMA support; see Problems with SATA and Linux.
Only IDE devices (HDD's, optical drives, zip drives) require special treatment - batteries, floppies and other devices can just be pulled from the bay, provided they are not mounted or in use at the time. However, you should still power them down first using the ibm-acpi eject function.
The ibm-acpi kernel module has an eject function (# echo eject > /proc/acpi/ibm/bay
). This only manages the ACPI calls to power down the device and the bay. It does not actually unregister the device from the IDE driver. # cat /proc/acpi/ibm/bay
shows "unoccupied" unless an IDE device is present, but the eject function still works and should still be used.
To unregister the device, you can either use the Debian hotswap package, or lt_hotswap. Note that lt_hotswap doesn't seem to even build on recent (at 2.6.22 or newer, although it probably broke before 2.6.22) and on newer kernels, you should not build/load the old IDE PIIX (CONFIG_BLK_DEV_PIIX) and use the natively hotswapping ata_piix (CONFIG_ATA_PIIX) as explained on the top of this page.
Debian hotswap also allows the drive to be swapped as a normal user by default, which is useful. You should use hotswap to unregister the device and then # echo eject > /proc/acpi/ibm/bay
. However, if you use this method on a 2.6 kernel, you will lose DMA support for the reinserted drive. This is due to kernel issues. This method was reported to work on a ThinkPad T23 (kernels 2.6.8.1, 2.6.14.2 and 2.6.15-arch) and T42 (kernel 2.6.13), but fails on a ThinkPad T43 (kernel 2.6.14.3).
lt_hotswap is now the recommended method to un- and reregister the IDE device. It installs as a kernel module and has support for automatically unregistering (if loaded with the auto_eject=1 option) the device when the eject event is generated by ibm-acpi. It will leave DMA support intact. It has supported to work on a ThinkPad T22 and T40 and should work with many other models (but not recent models which require the ata_piix driver for disk DMA support). With the lt_hotswap kernel module loaded, run: # modprobe -r ide_cd && modprobe -r cdrom && echo "MSTR eject" > /proc/acpi/lths
HAL support
HAL support also can also be configured To do so, create the file /etc/hal/fdi/information/10-ultrabay.fdi as follows:
<?xml version="1.0" encoding="UTF-8"?> <!-- -*- SGML -*- --> <deviceinfo version="0.2"> <device> <!-- UltraBay Devices --> <match key="storage.bus" string="ide"> <match key="storage.physical_device" string="/org/freedesktop/Hal/devices/pci_8086_24ca_ide_1_0"> <merge key="storage.hotpluggable" type="bool">true</merge> </match> </match> </device> </deviceinfo>
For more details see HAL section for ata driver.
Other comments
If you are hot-swapping a hard disk on a disk tray, make sure the disk does not have a password set, otherwise it will not be recognized on reinsertion.