| |
| The allocator shown here exploits high memory. This document explains |
| how a user can deal with drivers uses this allocator and how a |
| programmer can link in the module. |
| |
| The module is being used by my pxc and pxdrv device drivers (as well as |
| other ones), available from ftp.systemy.it/pub/develop and |
| ftp.linux.it/pub/People/Rubini |
| |
| User's manual |
| ============= |
| |
| |
| One of the most compelling problems with any DMA-capable device is the |
| allocation of a suitable memory buffer. The "allocator" module tries |
| to deal with the problem in a clean way. The module is able to use |
| high memory (above the one used in normal operation) for DMA |
| allocation. |
| |
| To prevent the kernel for using high memory, so that it remains |
| available for DMA, you should pass a command line argument to the |
| kernel. Command line arguments can be passed to Lilo, to Loadlin or |
| to whichever loader you are using (unless it's very poor in design). |
| For Lilo, either use "append=" in /etc/lilo.conf or add commandline |
| arguments to the interactive prompt. For example, I have a 32MB box |
| and reserve two megs for DMA: |
| |
| In lilo.conf: |
| image = /zImage |
| label = linux |
| append = "mem=30M" |
| |
| Or, interactively: |
| LILO: linux mem=30M |
| |
| Once the kernel is booted with the right command-line argument, any |
| driver linked with the allocator module will be able to get |
| DMA-capable memory without much trouble (unless the various drivers |
| need more memory than available). |
| |
| The module implements an alloc/free mechanism, so that it can serve |
| multiple drivers at the same time. Note however that the allocator |
| uses all of high memory and assumes to be the only piece of software |
| using such memory. |
| |
| |
| Programmer's manual |
| =================== |
| |
| The allocator, as released, is designed to be linked to a device |
| driver. In this case, the driver must call allocator_init() before |
| using the allocator and must call allocator_cleanup() before |
| unloading. This is usually done from within init_module() and |
| cleanup_module(). If the allocator is linked to a driver, it won't be |
| possible for several drivers to allocate high DMA memory, as explained |
| above. |
| |
| It is possible, on the other hand, to compile the module as a standalone |
| module, so that several modules can rely on the allocator for they DMA |
| buffers. To compile the allocator as a standalone module, do the |
| following in this directory (or provide a suitable Makefile, or edit |
| the source code): |
| |
| make allocator.o CC="gcc -Dallocator_init=init_module -Dallocator_cleanup=cleanup_module -include /usr/include/linux/module.h" |
| |
| The previous commandline tells to include <linux/module.h> in the |
| first place, and to rename the init and cleanup function to the ones |
| needed for module loading and unloading. Drivers using a standalone |
| allocator won't need to call allocator_init() nor allocator_cleanup(). |
| |
| The allocator exports the following functions (declared in allocator.h): |
| |
| unsigned long allocator_allocate_dma (unsigned long kilobytes, |
| int priority); |
| |
| This function returns a physical address, over high_memory, |
| which corresponds to an area of at least "kilobytes" kilobytes. |
| The area will be owned by the module calling the function. |
| The returned address can be passed to device boards, to instruct |
| their DMA controllers, via phys_to_bus(). The address can be used |
| by C code after vremap()/ioremap(). The "priority" argument should |
| be GFP_KERNEL or GFP_ATOMIC, according to the context of the |
| caller; it is used to call kmalloc(), as the allocator must keep |
| track of any region it gives away. In case of error the function |
| returns 0, and the caller is expected to issue a -ENOMEM error. |
| |
| |
| void allocator_free_dma (unsigned long address); |
| |
| This function is the reverse of the previous one. If a driver |
| doesn't free the DMA memory it allocated, the allocator will |
| consider such memory as busy. Note, however, that |
| allocator_cleanup() calls kfree() on every region it reclaimed, |
| so that a driver with the allocator linked in can avoid calling |
| allocator_free_dma() at unload time. |
| |
| |
| |