Commit | Line | Data |
---|---|---|
aa337ef1 SS |
1 | |
2 | The allocator shown here exploits high memory. This document explains | |
3 | how a user can deal with drivers uses this allocator and how a | |
4 | programmer can link in the module. | |
5 | ||
6 | The module is being used by my pxc and pxdrv device drivers (as well as | |
7 | other ones), available from ftp.systemy.it/pub/develop and | |
8 | ftp.linux.it/pub/People/Rubini | |
9 | ||
10 | User's manual | |
11 | ============= | |
12 | ||
13 | ||
14 | One of the most compelling problems with any DMA-capable device is the | |
15 | allocation of a suitable memory buffer. The "allocator" module tries | |
16 | to deal with the problem in a clean way. The module is able to use | |
17 | high memory (above the one used in normal operation) for DMA | |
18 | allocation. | |
19 | ||
20 | To prevent the kernel for using high memory, so that it remains | |
21 | available for DMA, you should pass a command line argument to the | |
22 | kernel. Command line arguments can be passed to Lilo, to Loadlin or | |
23 | to whichever loader you are using (unless it's very poor in design). | |
24 | For Lilo, either use "append=" in /etc/lilo.conf or add commandline | |
25 | arguments to the interactive prompt. For example, I have a 32MB box | |
26 | and reserve two megs for DMA: | |
27 | ||
28 | In lilo.conf: | |
29 | image = /zImage | |
30 | label = linux | |
31 | append = "mem=30M" | |
32 | ||
33 | Or, interactively: | |
34 | LILO: linux mem=30M | |
35 | ||
36 | Once the kernel is booted with the right command-line argument, any | |
37 | driver linked with the allocator module will be able to get | |
38 | DMA-capable memory without much trouble (unless the various drivers | |
39 | need more memory than available). | |
40 | ||
41 | The module implements an alloc/free mechanism, so that it can serve | |
42 | multiple drivers at the same time. Note however that the allocator | |
43 | uses all of high memory and assumes to be the only piece of software | |
44 | using such memory. | |
45 | ||
46 | ||
47 | Programmer's manual | |
48 | =================== | |
49 | ||
50 | The allocator, as released, is designed to be linked to a device | |
51 | driver. In this case, the driver must call allocator_init() before | |
52 | using the allocator and must call allocator_cleanup() before | |
53 | unloading. This is usually done from within init_module() and | |
54 | cleanup_module(). If the allocator is linked to a driver, it won't be | |
55 | possible for several drivers to allocate high DMA memory, as explained | |
56 | above. | |
57 | ||
58 | It is possible, on the other hand, to compile the module as a standalone | |
59 | module, so that several modules can rely on the allocator for they DMA | |
60 | buffers. To compile the allocator as a standalone module, do the | |
61 | following in this directory (or provide a suitable Makefile, or edit | |
62 | the source code): | |
63 | ||
64 | make allocator.o CC="gcc -Dallocator_init=init_module -Dallocator_cleanup=cleanup_module -include /usr/include/linux/module.h" | |
65 | ||
66 | The previous commandline tells to include <linux/module.h> in the | |
67 | first place, and to rename the init and cleanup function to the ones | |
68 | needed for module loading and unloading. Drivers using a standalone | |
69 | allocator won't need to call allocator_init() nor allocator_cleanup(). | |
70 | ||
71 | The allocator exports the following functions (declared in allocator.h): | |
72 | ||
73 | unsigned long allocator_allocate_dma (unsigned long kilobytes, | |
74 | int priority); | |
75 | ||
76 | This function returns a physical address, over high_memory, | |
77 | which corresponds to an area of at least "kilobytes" kilobytes. | |
78 | The area will be owned by the module calling the function. | |
79 | The returned address can be passed to device boards, to instruct | |
80 | their DMA controllers, via phys_to_bus(). The address can be used | |
81 | by C code after vremap()/ioremap(). The "priority" argument should | |
82 | be GFP_KERNEL or GFP_ATOMIC, according to the context of the | |
83 | caller; it is used to call kmalloc(), as the allocator must keep | |
84 | track of any region it gives away. In case of error the function | |
85 | returns 0, and the caller is expected to issue a -ENOMEM error. | |
86 | ||
87 | ||
88 | void allocator_free_dma (unsigned long address); | |
89 | ||
90 | This function is the reverse of the previous one. If a driver | |
91 | doesn't free the DMA memory it allocated, the allocator will | |
92 | consider such memory as busy. Note, however, that | |
93 | allocator_cleanup() calls kfree() on every region it reclaimed, | |
94 | so that a driver with the allocator linked in can avoid calling | |
95 | allocator_free_dma() at unload time. | |
96 | ||
97 | ||
98 |