提交 375d65db 编写于 作者: A Alan Cox 提交者: Greg Kroah-Hartman

Staging: rar and memrar updates

rar: perform a clean up pass

- Move to a registration model where each RAR is claimed/unclaimed
- Use that to fix the client stuff (one client per RAR so no need to queue stuff)
- Support unregister so drivers can rmmod themselves safely
- Fix locking hang on calling rar lock from rar callback
- Clean up
- Kerneldoc

Folded in the memrar update as Greg asked

- Fix various unload related bugs
- Use the per RAR allocator/deallocator
- Add kerneldoc
Signed-off-by: NAlan Cox <alan@linux.intel.com>
Signed-off-by: NGreg Kroah-Hartman <gregkh@suse.de>
上级 a9d26f00
...@@ -114,6 +114,7 @@ struct memrar_rar_info { ...@@ -114,6 +114,7 @@ struct memrar_rar_info {
struct memrar_allocator *allocator; struct memrar_allocator *allocator;
struct memrar_buffer_info buffers; struct memrar_buffer_info buffers;
struct mutex lock; struct mutex lock;
int allocated; /* True if we own this RAR */
}; };
/* /*
...@@ -150,11 +151,13 @@ static struct memrar_rar_info *memrar_get_rar_info(u32 vaddr) ...@@ -150,11 +151,13 @@ static struct memrar_rar_info *memrar_get_rar_info(u32 vaddr)
return NULL; return NULL;
} }
/* /**
* Retrieve bus address from given handle. * memrar_get_bus address - handle to bus address
*
* Retrieve bus address from given handle.
* *
* Returns address corresponding to given handle. Zero if handle is * Returns address corresponding to given handle. Zero if handle is
* invalid. * invalid.
*/ */
static dma_addr_t memrar_get_bus_address( static dma_addr_t memrar_get_bus_address(
struct memrar_rar_info *rar, struct memrar_rar_info *rar,
...@@ -176,11 +179,13 @@ static dma_addr_t memrar_get_bus_address( ...@@ -176,11 +179,13 @@ static dma_addr_t memrar_get_bus_address(
return rar->base + (vaddr - iobase); return rar->base + (vaddr - iobase);
} }
/* /**
* Retrieve physical address from given handle. * memrar_get_physical_address - handle to physical address
*
* Retrieve physical address from given handle.
* *
* Returns address corresponding to given handle. Zero if handle is * Returns address corresponding to given handle. Zero if handle is
* invalid. * invalid.
*/ */
static dma_addr_t memrar_get_physical_address( static dma_addr_t memrar_get_physical_address(
struct memrar_rar_info *rar, struct memrar_rar_info *rar,
...@@ -195,11 +200,15 @@ static dma_addr_t memrar_get_physical_address( ...@@ -195,11 +200,15 @@ static dma_addr_t memrar_get_physical_address(
return memrar_get_bus_address(rar, vaddr); return memrar_get_bus_address(rar, vaddr);
} }
/* /**
* Core block release code. * memrar_release_block - release a block to the pool
* @kref: kref of block
*
* Core block release code. A node has hit zero references so can
* be released and the lists must be updated.
* *
* Note: This code removes the node from a list. Make sure any list * Note: This code removes the node from a list. Make sure any list
* iteration is performed using list_for_each_safe(). * iteration is performed using list_for_each_safe().
*/ */
static void memrar_release_block_i(struct kref *ref) static void memrar_release_block_i(struct kref *ref)
{ {
...@@ -224,10 +233,15 @@ static void memrar_release_block_i(struct kref *ref) ...@@ -224,10 +233,15 @@ static void memrar_release_block_i(struct kref *ref)
kfree(node); kfree(node);
} }
/* /**
* Initialize RAR parameters, such as bus addresses, etc. * memrar_init_rar_resources - configure a RAR
* @rarnum: rar that has been allocated
* @devname: name of our device
*
* Initialize RAR parameters, such as bus addresses, etc and make
* the resource accessible.
*/ */
static int memrar_init_rar_resources(char const *devname) static int memrar_init_rar_resources(int rarnum, char const *devname)
{ {
/* ---- Sanity Checks ---- /* ---- Sanity Checks ----
* 1. RAR bus addresses in both Lincroft and Langwell RAR * 1. RAR bus addresses in both Lincroft and Langwell RAR
...@@ -258,162 +272,95 @@ static int memrar_init_rar_resources(char const *devname) ...@@ -258,162 +272,95 @@ static int memrar_init_rar_resources(char const *devname)
*/ */
static size_t const RAR_BLOCK_SIZE = PAGE_SIZE; static size_t const RAR_BLOCK_SIZE = PAGE_SIZE;
int z; dma_addr_t low, high;
int found_rar = 0; struct memrar_rar_info * const rar = &memrars[rarnum];
BUG_ON(MRST_NUM_RAR != ARRAY_SIZE(memrars)); BUG_ON(MRST_NUM_RAR != ARRAY_SIZE(memrars));
BUG_ON(!memrar_is_valid_rar_type(rarnum));
BUG_ON(rar->allocated);
for (z = 0; z != MRST_NUM_RAR; ++z) { mutex_init(&rar->lock);
dma_addr_t low, high;
struct memrar_rar_info * const rar = &memrars[z];
BUG_ON(!memrar_is_valid_rar_type(z));
mutex_init(&rar->lock);
/*
* Initialize the process table before we reach any
* code that exit on failure since the finalization
* code requires an initialized list.
*/
INIT_LIST_HEAD(&rar->buffers.list);
if (rar_get_address(z, &low, &high) != 0) {
/* No RAR is available. */
break;
} else if (low == 0 || high == 0) {
/*
* We don't immediately break out of the loop
* since the next type of RAR may be enabled.
*/
rar->base = 0;
rar->length = 0;
rar->iobase = NULL;
rar->allocator = NULL;
continue;
}
/*
* @todo Verify that LNC and LNW RAR register contents
* addresses, security, etc are compatible and
* consistent).
*/
rar->length = high - low + 1;
/* Claim RAR memory as our own. */
if (request_mem_region(low, rar->length, devname) == NULL) {
rar->length = 0;
pr_err("%s: Unable to claim RAR[%d] memory.\n",
devname,
z);
pr_err("%s: RAR[%d] disabled.\n", devname, z);
/*
* Rather than break out of the loop by
* returning -EBUSY, for example, we may be
* able to claim memory of the next RAR region
* as our own.
*/
continue;
}
rar->base = low;
/*
* Now map it into the kernel address space.
*
* Note that the RAR memory may only be accessed by IA
* when debugging. Otherwise attempts to access the
* RAR memory when it is locked down will result in
* behavior similar to writing to /dev/null and
* reading from /dev/zero. This behavior is enforced
* by the hardware. Even if we don't access the
* memory, mapping it into the kernel provides us with
* a convenient RAR handle to bus address mapping.
*/
rar->iobase = ioremap_nocache(rar->base, rar->length);
if (rar->iobase == NULL) {
pr_err("%s: Unable to map RAR memory.\n",
devname);
return -ENOMEM;
}
/* Initialize corresponding memory allocator. */
rar->allocator = memrar_create_allocator(
(unsigned long) rar->iobase,
rar->length,
RAR_BLOCK_SIZE);
if (rar->allocator == NULL)
return -1;
/* /*
* ------------------------------------------------- * Initialize the process table before we reach any
* Make sure all RARs handled by us are locked down. * code that exit on failure since the finalization
* ------------------------------------------------- * code requires an initialized list.
*/ */
INIT_LIST_HEAD(&rar->buffers.list);
/* Enable RAR protection on the Lincroft side. */ if (rar_get_address(rarnum, &low, &high) != 0)
if (0) { /* No RAR is available. */
/* return -ENODEV;
* This is mostly a sanity check since the
* vendor should have locked down RAR in the if (low == 0 || high == 0) {
* SMIP header RAR configuration. rar->base = 0;
*/ rar->length = 0;
rar_lock(z); rar->iobase = NULL;
} else { rar->allocator = NULL;
pr_warning("%s: LNC RAR[%d] no lock sanity check.\n", return -ENOSPC;
devname, }
z);
}
/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */ /*
/* |||||||||||||||||||||||||||||||||||||||||||||||||| */ * @todo Verify that LNC and LNW RAR register contents
* addresses, security, etc are compatible and
* consistent).
*/
/* rar->length = high - low + 1;
* It would be nice if we could verify that RAR
* protection on the Langwell side is enabled, but
* there is no way to do that from here. The
* necessary Langwell RAR registers are not accessible
* from the Lincroft (IA) side.
*
* Hopefully the ODM did the right thing and enabled
* Langwell side RAR protection in the integrated
* firmware SMIP header.
*/
pr_info("%s: BRAR[%d] bus address range = " /* Claim RAR memory as our own. */
"[0x%lx, 0x%lx]\n", if (request_mem_region(low, rar->length, devname) == NULL) {
devname, rar->length = 0;
z, pr_err("%s: Unable to claim RAR[%d] memory.\n", devname, rarnum);
(unsigned long) low, pr_err("%s: RAR[%d] disabled.\n", devname, rarnum);
(unsigned long) high); return -EBUSY;
}
pr_info("%s: BRAR[%d] size = %zu KiB\n", rar->base = low;
devname,
z,
rar->allocator->capacity / 1024);
found_rar = 1; /*
* Now map it into the kernel address space.
*
* Note that the RAR memory may only be accessed by IA
* when debugging. Otherwise attempts to access the
* RAR memory when it is locked down will result in
* behavior similar to writing to /dev/null and
* reading from /dev/zero. This behavior is enforced
* by the hardware. Even if we don't access the
* memory, mapping it into the kernel provides us with
* a convenient RAR handle to bus address mapping.
*/
rar->iobase = ioremap_nocache(rar->base, rar->length);
if (rar->iobase == NULL) {
pr_err("%s: Unable to map RAR memory.\n", devname);
release_mem_region(low, rar->length);
return -ENOMEM;
} }
if (!found_rar) { /* Initialize corresponding memory allocator. */
/* rar->allocator = memrar_create_allocator((unsigned long) rar->iobase,
* No RAR support. Don't bother continuing. rar->length, RAR_BLOCK_SIZE);
* if (rar->allocator == NULL) {
* Note that this is not a failure. iounmap(rar->iobase);
*/ release_mem_region(low, rar->length);
pr_info("%s: No Moorestown RAR support available.\n", return -ENOMEM;
devname);
return -ENODEV;
} }
pr_info("%s: BRAR[%d] bus address range = [0x%lx, 0x%lx]\n",
devname, rarnum, (unsigned long) low, (unsigned long) high);
pr_info("%s: BRAR[%d] size = %zu KiB\n",
devname, rarnum, rar->allocator->capacity / 1024);
rar->allocated = 1;
return 0; return 0;
} }
/* /**
* Finalize RAR resources. * memrar_fini_rar_resources - free up RAR resources
*
* Finalize RAR resources. Free up the resource tables, hand the memory
* back to the kernel, unmap the device and release the address space.
*/ */
static void memrar_fini_rar_resources(void) static void memrar_fini_rar_resources(void)
{ {
...@@ -429,6 +376,9 @@ static void memrar_fini_rar_resources(void) ...@@ -429,6 +376,9 @@ static void memrar_fini_rar_resources(void)
for (z = MRST_NUM_RAR; z-- != 0; ) { for (z = MRST_NUM_RAR; z-- != 0; ) {
struct memrar_rar_info * const rar = &memrars[z]; struct memrar_rar_info * const rar = &memrars[z];
if (!rar->allocated)
continue;
/* Clean up remaining resources. */ /* Clean up remaining resources. */
list_for_each_entry_safe(pos, list_for_each_entry_safe(pos,
...@@ -442,15 +392,25 @@ static void memrar_fini_rar_resources(void) ...@@ -442,15 +392,25 @@ static void memrar_fini_rar_resources(void)
rar->allocator = NULL; rar->allocator = NULL;
iounmap(rar->iobase); iounmap(rar->iobase);
rar->iobase = NULL;
release_mem_region(rar->base, rar->length); release_mem_region(rar->base, rar->length);
rar->base = 0;
rar->iobase = NULL;
rar->base = 0;
rar->length = 0; rar->length = 0;
unregister_rar(z);
} }
} }
/**
* memrar_reserve_block - handle an allocation request
* @request: block being requested
* @filp: owner it is tied to
*
* Allocate a block of the requested RAR. If successful return the
* request object filled in and zero, if not report an error code
*/
static long memrar_reserve_block(struct RAR_buffer *request, static long memrar_reserve_block(struct RAR_buffer *request,
struct file *filp) struct file *filp)
{ {
...@@ -465,6 +425,8 @@ static long memrar_reserve_block(struct RAR_buffer *request, ...@@ -465,6 +425,8 @@ static long memrar_reserve_block(struct RAR_buffer *request,
return -EINVAL; return -EINVAL;
rar = &memrars[rinfo->type]; rar = &memrars[rinfo->type];
if (!rar->allocated)
return -ENODEV;
/* Reserve memory in RAR. */ /* Reserve memory in RAR. */
handle = memrar_allocator_alloc(rar->allocator, rinfo->size); handle = memrar_allocator_alloc(rar->allocator, rinfo->size);
...@@ -504,6 +466,14 @@ static long memrar_reserve_block(struct RAR_buffer *request, ...@@ -504,6 +466,14 @@ static long memrar_reserve_block(struct RAR_buffer *request,
return 0; return 0;
} }
/**
* memrar_release_block - release a RAR block
* @addr: address in RAR space
*
* Release a previously allocated block. Releases act on complete
* blocks, partially freeing a block is not supported
*/
static long memrar_release_block(u32 addr) static long memrar_release_block(u32 addr)
{ {
struct memrar_buffer_info *pos; struct memrar_buffer_info *pos;
...@@ -512,7 +482,7 @@ static long memrar_release_block(u32 addr) ...@@ -512,7 +482,7 @@ static long memrar_release_block(u32 addr)
long result = -EINVAL; long result = -EINVAL;
if (rar == NULL) if (rar == NULL)
return -EFAULT; return -ENOENT;
mutex_lock(&rar->lock); mutex_lock(&rar->lock);
...@@ -550,34 +520,48 @@ static long memrar_release_block(u32 addr) ...@@ -550,34 +520,48 @@ static long memrar_release_block(u32 addr)
return result; return result;
} }
/**
* memrar_get_stats - read statistics for a RAR
* @r: statistics to be filled in
*
* Returns the statistics data for the RAR, or an error code if
* the request cannot be completed
*/
static long memrar_get_stat(struct RAR_stat *r) static long memrar_get_stat(struct RAR_stat *r)
{ {
long result = -EINVAL; struct memrar_allocator *allocator;
if (likely(r != NULL) && memrar_is_valid_rar_type(r->type)) {
struct memrar_allocator * const allocator =
memrars[r->type].allocator;
BUG_ON(allocator == NULL);
/* if (!memrar_is_valid_rar_type(r->type))
* Allocator capacity doesn't change over time. No return -EINVAL;
* need to synchronize.
*/
r->capacity = allocator->capacity;
mutex_lock(&allocator->lock); if (!memrars[r->type].allocated)
return -ENODEV;
r->largest_block_size = allocator->largest_free_area; allocator = memrars[r->type].allocator;
mutex_unlock(&allocator->lock); BUG_ON(allocator == NULL);
result = 0; /*
} * Allocator capacity doesn't change over time. No
* need to synchronize.
*/
r->capacity = allocator->capacity;
return result; mutex_lock(&allocator->lock);
r->largest_block_size = allocator->largest_free_area;
mutex_unlock(&allocator->lock);
return 0;
} }
/**
* memrar_ioctl - ioctl callback
* @filp: file issuing the request
* @cmd: command
* @arg: pointer to control information
*
* Perform one of the ioctls supported by the memrar device
*/
static long memrar_ioctl(struct file *filp, static long memrar_ioctl(struct file *filp,
unsigned int cmd, unsigned int cmd,
unsigned long arg) unsigned long arg)
...@@ -640,6 +624,15 @@ static long memrar_ioctl(struct file *filp, ...@@ -640,6 +624,15 @@ static long memrar_ioctl(struct file *filp,
return 0; return 0;
} }
/**
* memrar_mmap - mmap helper for deubgging
* @filp: handle doing the mapping
* @vma: memory area
*
* Support the mmap operation on the RAR space for debugging systems
* when the memory is not locked down.
*/
static int memrar_mmap(struct file *filp, struct vm_area_struct *vma) static int memrar_mmap(struct file *filp, struct vm_area_struct *vma)
{ {
/* /*
...@@ -660,9 +653,12 @@ static int memrar_mmap(struct file *filp, struct vm_area_struct *vma) ...@@ -660,9 +653,12 @@ static int memrar_mmap(struct file *filp, struct vm_area_struct *vma)
unsigned long const handle = vma->vm_pgoff << PAGE_SHIFT; unsigned long const handle = vma->vm_pgoff << PAGE_SHIFT;
struct memrar_rar_info * const rar = memrar_get_rar_info(handle); struct memrar_rar_info * const rar = memrar_get_rar_info(handle);
unsigned long pfn; unsigned long pfn;
/* Only allow priviledged apps to go poking around this way */
if (!capable(CAP_SYS_RAWIO))
return -EPERM;
/* Invalid RAR handle or size passed to mmap(). */ /* Invalid RAR handle or size passed to mmap(). */
if (rar == NULL if (rar == NULL
|| handle == 0 || handle == 0
...@@ -698,13 +694,32 @@ static int memrar_mmap(struct file *filp, struct vm_area_struct *vma) ...@@ -698,13 +694,32 @@ static int memrar_mmap(struct file *filp, struct vm_area_struct *vma)
return 0; return 0;
} }
/**
* memrar_open - device open method
* @inode: inode to open
* @filp: file handle
*
* As we support multiple arbitary opens there is no work to be done
* really.
*/
static int memrar_open(struct inode *inode, struct file *filp) static int memrar_open(struct inode *inode, struct file *filp)
{ {
/* Nothing to do yet. */ nonseekable_open(inode, filp);
return 0; return 0;
} }
/**
* memrar_release - close method for miscev
* @inode: inode of device
* @filp: handle that is going away
*
* Free up all the regions that belong to this file handle. We use
* the handle as a natural Linux style 'lifetime' indicator and to
* ensure resources are not leaked when their owner explodes in an
* unplanned fashion.
*/
static int memrar_release(struct inode *inode, struct file *filp) static int memrar_release(struct inode *inode, struct file *filp)
{ {
/* Free all regions associated with the given file handle. */ /* Free all regions associated with the given file handle. */
...@@ -733,9 +748,15 @@ static int memrar_release(struct inode *inode, struct file *filp) ...@@ -733,9 +748,15 @@ static int memrar_release(struct inode *inode, struct file *filp)
return 0; return 0;
} }
/* /**
* This function is part of the kernel space memrar driver API. * rar_reserve - reserve RAR memory
* @buffers: buffers to reserve
* @count: number wanted
*
* Reserve a series of buffers in the RAR space. Returns the number of
* buffers successfully allocated
*/ */
size_t rar_reserve(struct RAR_buffer *buffers, size_t count) size_t rar_reserve(struct RAR_buffer *buffers, size_t count)
{ {
struct RAR_buffer * const end = struct RAR_buffer * const end =
...@@ -755,9 +776,14 @@ size_t rar_reserve(struct RAR_buffer *buffers, size_t count) ...@@ -755,9 +776,14 @@ size_t rar_reserve(struct RAR_buffer *buffers, size_t count)
} }
EXPORT_SYMBOL(rar_reserve); EXPORT_SYMBOL(rar_reserve);
/* /**
* This function is part of the kernel space memrar driver API. * rar_release - return RAR buffers
* @buffers: buffers to release
* @size: size of released block
*
* Return a set of buffers to the RAR pool
*/ */
size_t rar_release(struct RAR_buffer *buffers, size_t count) size_t rar_release(struct RAR_buffer *buffers, size_t count)
{ {
struct RAR_buffer * const end = struct RAR_buffer * const end =
...@@ -786,9 +812,16 @@ size_t rar_release(struct RAR_buffer *buffers, size_t count) ...@@ -786,9 +812,16 @@ size_t rar_release(struct RAR_buffer *buffers, size_t count)
} }
EXPORT_SYMBOL(rar_release); EXPORT_SYMBOL(rar_release);
/* /**
* This function is part of the kernel space driver API. * rar_handle_to_bus - RAR to bus address
* @buffers: RAR buffer structure
* @count: number of buffers to convert
*
* Turn a list of RAR handle mappings into actual bus addresses. Note
* that when the device is locked down the bus addresses in question
* are not CPU accessible.
*/ */
size_t rar_handle_to_bus(struct RAR_buffer *buffers, size_t count) size_t rar_handle_to_bus(struct RAR_buffer *buffers, size_t count)
{ {
struct RAR_buffer * const end = struct RAR_buffer * const end =
...@@ -878,43 +911,70 @@ static char const banner[] __initdata = ...@@ -878,43 +911,70 @@ static char const banner[] __initdata =
KERN_INFO KERN_INFO
"Intel RAR Handler: " MEMRAR_VER " initialized.\n"; "Intel RAR Handler: " MEMRAR_VER " initialized.\n";
static int memrar_registration_callback(void *ctx) /**
* memrar_registration_callback - RAR obtained
* @rar: RAR number
*
* We have been granted ownership of the RAR. Add it to our memory
* management tables
*/
static int memrar_registration_callback(unsigned long rar)
{ {
/* /*
* We initialize the RAR parameters early on so that we can * We initialize the RAR parameters early on so that we can
* discontinue memrar device initialization and registration * discontinue memrar device initialization and registration
* if suitably configured RARs are not available. * if suitably configured RARs are not available.
*/ */
int result = memrar_init_rar_resources(memrar_miscdev.name); return memrar_init_rar_resources(rar, memrar_miscdev.name);
}
if (result != 0) /**
return result; * memrar_init - initialise RAR support
*
* Initialise support for RAR handlers. This may get loaded before
* the RAR support is activated, but the callbacks on the registration
* will handle that situation for us anyway.
*/
result = misc_register(&memrar_miscdev); static int __init memrar_init(void)
{
int err;
if (result != 0) { printk(banner);
pr_err("%s: misc_register() failed.\n",
memrar_miscdev.name);
/* Clean up resources previously reserved. */ err = misc_register(&memrar_miscdev);
memrar_fini_rar_resources(); if (err)
} return err;
return result; /* Now claim the two RARs we want */
} err = register_rar(0, memrar_registration_callback, 0);
if (err)
goto fail;
static int __init memrar_init(void) err = register_rar(1, memrar_registration_callback, 1);
{ if (err == 0)
printk(banner); return 0;
return register_rar(&memrar_registration_callback, 0); /* It is possible rar 0 registered and allocated resources then rar 1
failed so do a full resource free */
memrar_fini_rar_resources();
fail:
misc_deregister(&memrar_miscdev);
return err;
} }
/**
* memrar_exit - unregister and unload
*
* Unregister the device and then unload any mappings and release
* the RAR resources
*/
static void __exit memrar_exit(void) static void __exit memrar_exit(void)
{ {
memrar_fini_rar_resources();
misc_deregister(&memrar_miscdev); misc_deregister(&memrar_miscdev);
memrar_fini_rar_resources();
} }
...@@ -925,7 +985,6 @@ module_exit(memrar_exit); ...@@ -925,7 +985,6 @@ module_exit(memrar_exit);
MODULE_AUTHOR("Ossama Othman <ossama.othman@intel.com>"); MODULE_AUTHOR("Ossama Othman <ossama.othman@intel.com>");
MODULE_DESCRIPTION("Intel Restricted Access Region Handler"); MODULE_DESCRIPTION("Intel Restricted Access Region Handler");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(MISC_DYNAMIC_MINOR);
MODULE_VERSION(MEMRAR_VER); MODULE_VERSION(MEMRAR_VER);
......
...@@ -21,63 +21,23 @@ ...@@ -21,63 +21,23 @@
#ifndef _RAR_REGISTER_H #ifndef _RAR_REGISTER_H
#define _RAR_REGISTER_H #define _RAR_REGISTER_H
# include <linux/types.h> #include <linux/types.h>
/* following are used both in drivers as well as user space apps */ /* following are used both in drivers as well as user space apps */
enum RAR_type {
RAR_TYPE_VIDEO = 0,
RAR_TYPE_AUDIO,
RAR_TYPE_IMAGE,
RAR_TYPE_DATA
};
#ifdef __KERNEL__ #define RAR_TYPE_VIDEO 0
#define RAR_TYPE_AUDIO 1
#define RAR_TYPE_IMAGE 2
#define RAR_TYPE_DATA 3
/* PCI device id for controller */ #ifdef __KERNEL__
#define PCI_RAR_DEVICE_ID 0x4110
/* The register_rar function is to used by other device drivers struct rar_device;
* to ensure that this driver is ready. As we cannot be sure of
* the compile/execute order of dirvers in ther kernel, it is
* best to give this driver a callback function to call when
* it is ready to give out addresses. The callback function
* would have those steps that continue the initialization of
* a driver that do require a valid RAR address. One of those
* steps would be to call get_rar_address()
* This function return 0 on success an -1 on failure.
*/
int register_rar(int (*callback)(void *yourparameter), void *yourparameter);
/* The get_rar_address function is used by other device drivers int register_rar(int num,
* to obtain RAR address information on a RAR. It takes two int (*callback)(unsigned long data), unsigned long data);
* parameter: void unregister_rar(int num);
* int rar_get_address(int rar_index, dma_addr_t *start, dma_addr_t *end);
* int rar_index
* The rar_index is an index to the rar for which you wish to retrieve
* the address information.
* Values can be 0,1, or 2.
*
* struct RAR_address_struct is a pointer to a place to which the function
* can return the address structure for the RAR.
*
* The function returns a 0 upon success or a -1 if there is no RAR
* facility on this system.
*/
int rar_get_address(int rar_index,
dma_addr_t *start_address,
dma_addr_t *end_address);
/* The lock_rar function is ued by other device drivers to lock an RAR.
* once an RAR is locked, it stays locked until the next system reboot.
* The function takes one parameter:
*
* int rar_index
* The rar_index is an index to the rar that you want to lock.
* Values can be 0,1, or 2.
*
* The function returns a 0 upon success or a -1 if there is no RAR
* facility on this system.
*/
int rar_lock(int rar_index); int rar_lock(int rar_index);
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册