aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/dt3155/allocator.README
blob: 05700b6c926c15016d7d930d3da43a64ac31aecf (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
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.