Enabling Disk DMA

by Glenn Burkhardt

At the last Boston Linux User's Group Installfest, I happened to overhear a conversation about enabling disk DMA. One person was explaining that he always regenerated the kernel after an installation in order to turn IDE DMA on, so he would get the most out of the machine. This was very interesting, since I've almost always found computers to be I/O bound for my applications. Even if I didn't use the speed, I'd want to have my machine running as fast as it could, just because it feels better.

After a bit of checking, I found that IDE DMA can be turned on without rebuilding the kernel. Most users probably would prefer not to change the kernel anyway, if it wasn't necessary.

There is also an easy way to determine if a system has IDE DMA already enabled. You can do this by checking the /proc entry for the drive, cat /proc/ide/hda/settings, and looking for the using_dma line. If the value is set to 1, DMA is turned on. Also, the hdparm command has a query option that will tell you if the drive supports DMA operation in the first place. If you try hdparm -i /dev/hda, the DMA modes line will report the possible IDE access modes the drive supports. For example:

DMA modes: mdma0 mdma1 mdma2 udma0 udma1 udma2 udma3 *udma4

Kernels can be configured to enable DMA for hardware that supports it by setting the CONFIG_IDEDMA_AUTO macro during configuration. Unfortunately, most distributions don't turn on this feature for their stock kernels. At least, the three I checked, Mandrake 7.2, Red Hat 7.0 and SuSE 7.1, didn't have it turned on.

I've found two different techniques that can be used to enable DMA for the disks, with the 2.2 and 2.4 kernels, when the kernel hasn't been configured for auto-enable.

The first method is to include the boot prompt argument idex=dma, where * idex= is recognized for all x from 0 to 3, such as ide1. This is functionally equivalent to defining CONFIG_IDEDMA_AUTO during kernel configuration. The hwif->autodma flag in the IDE driver is set, and queries of the drive and controller chip set determine whether DMA is used with the drive.

A better way is to use hdparm. It can enable DMA while the system is running and, thus, can be added to a start up script, like rc.local. The command would be something like hdparm -d1 /dev/hda.

Whenever DMA is enabled, should errors occur while accessing the drive, the DMA mode will be disabled by the driver.

The computer I have at home doesn't work in DMA mode at all; The IDE driver kept turning DMA off. This computer is not a newly manufactured system, but it has relatively standard components, Intel Celeron, 440LX chipset and an Intel IDE controller. A query of /proc/pci revealed that the IDE controller billed itself as "Master Capable", and hdparm-i indicates that the disk drive prefers UDMA mode 4. I did notice that I had a standard 40 conductor IDE cable installed, so I ran out to buy an 80 conductor UDMA cable. It didn't help. When I enabled DMA, the disk chattered for a few seconds, then went silent. The file /var/log/messages had lines in it like:

        kernel: hda: dma_intr: status=0x51 { DriveReady SeekComplete Error } 
        kernel: hda: dma_intr: error=0x84 { DriveStatusError BadCRC } 
        kernel: hda: DMA disabled 
        kernel: ide0: reset: success 

But newer systems at the office responded quite well and now run with DMA enabled. I checked the performance with the hdparm command, which conveniently includes a performance test. To run the test, type /sbin/hdparm -t -T /dev/hda.

Here are the test results for a couple of systems we have in the office (units are MB/s):

                             |     System A       |      System B
             Test            |  w/o DMA   w/DMA   |  w/o DMA   w/DMA
         buffer-cache reads  |  185.51    134.74  |  26.34     34.50
         buffered disk reads |    3.38     20.32  |   2.75      9.92

Of course, this new enlightenment is going to cost me. Now I need to put $300 into my home system to bring it up to snuff.


Linux Ultra-DMA Mini-Howto, Brion Vibber, v3.0, 9 November 1999 hdparm(8) man page

Load Disqus comments