LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Software > Linux - Kernel
User Name
Password
Linux - Kernel This forum is for all discussion relating to the Linux kernel.

Notices


Reply
  Search this Thread
Old 03-29-2011, 03:37 PM   #1
Sink0
LQ Newbie
 
Registered: Sep 2010
Posts: 6

Rep: Reputation: 0
Help with DMA on PCI Driver Options


Hi, i am developing a driver for a custom PCI board. I am following
the example on Essential Linux Device Drivers, but when i am calling
the pci_alloc_consitent i get the following error:

Code:
Mar 29 15:18:42 luis-desktop kernel: [ 4520.075823] BUG: unable to 
handle kernel NULL pointer dereference at 00000004 
Mar 29 15:18:42 luis-desktop kernel: [ 4520.078277] IP: [<c010797f>] 
dma_generic_alloc_coherent+0xaf/0xc0 
Mar 29 15:18:42 luis-desktop kernel: [ 4520.078277] *pde = 0a417067 
*pte = 00000000 
Mar 29 15:18:42 luis-desktop kernel: [ 4520.078277] Oops: 0002 [#1] 
SMP

I am running on a x86 (Pentium III) with Ubuntu Kernel 2.6.32-24


I tryed to take a look at ldd3 but no answer so far...


The driver code is:


Code:
/* 
 * pci_bridge-driver.c - template Linux driver for the opencores' pci 
bridge . Works on * kernel 2.6.x 
 * 
 * tested on Xubuntu, kernel 2.6.20-15-generic 
 * 
 * 
 * Permission to use, copy, modify, and distribute this software for 
any 
 * purpose with or without fee is hereby granted. 
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
EXPRESS OR 
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
MERCHANTABILITY, 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY 
 * RIGHTS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, 
DAMAGES 
 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
OTHERWISE, 
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE 
OR 
 * OTHER DEALINGS IN THE SOFTWARE. 
 */ 


/* 
 * Build/use notes (you'll probably need to be superuser to run most 
of 
 * the steps below): 
 * 
 * 1) How to build the driver: 
 * 
 *      $ make 
 * 
 * 2) How to install the driver: 
 * 
 *      $ insmod pci_bridge-driver.ko 
 * 
 * TODO: change the code and use misc device and udev, so to avoid the 
stuff below (3-4) !! 
 * 3) If pci_bridge_init_major (below) is 0, then obtain the major 
number: 
 * 
 *      $ cat /proc/devices 
 * 
 * Look for the line that contains the string "pci_bridge". The major 
 * number is to the left. 
 * 
 * 4) Make the pci_bridge device special file. Substitute the major 
 * number obtained above for <major_number>. 
 * 
 *      $ mknod /dev/pci_bridge c <major_number> 0 
 * 
 * 5) How to remove the driver: 
 * 
 *      $ rmmod pci_bridge-driver 
 */ 


#include <linux/kernel.h> 
#include <linux/module.h> 
#include <linux/pci.h> 
#include <linux/init.h> 
#include <linux/cdev.h> 
#include <linux/fs.h> 
#include <linux/ioctl.h> 


//#include <asm/byteorder.h>              /* PCI is little endian */ 
#include <asm/uaccess.h>                /* copy to/from user */ 


#include "kint.h" 


#define PCI_BRIDGE_DEVICE_ID 0x0001 
#define PCI_BRIDGE_VENDOR_ID 0x1895 
#define PCI_DRIVER_NAME "pci_bridge" /* driver name */ 
#define BRIDGE_MEM_MAPPED 0 
#define BRIDGE_IO_MAPPED 1 


/* 
 * PCI device IDs supported by this driver. The PCI_DEVICE macro sets 
 * the vendor and device fields to its input arguments, sets subvendor 
 * and subdevice to PCI_ANY_ID. It does not set the class fields. 
 */ 
static struct pci_device_id pci_bridge_ids[] = 
{ 
        { PCI_DEVICE(PCI_BRIDGE_VENDOR_ID, PCI_BRIDGE_DEVICE_ID), }, 
        { 0, } 



}; 


/* 
 * For completeness, tell the module loading and hotplug systems 
 * what PCI devices this module supports. 
 */ 
MODULE_DEVICE_TABLE(pci, pci_bridge_ids); 

/* 
 * pci_register_driver parameter. 
 */ 
static int pci_bridge_probe(struct pci_dev *, const struct 
pci_device_id *); 
static void pci_bridge_remove(struct pci_dev *); 


static struct pci_driver pci_bridge_driver = 
{ 
        .name = PCI_DRIVER_NAME, 
        .id_table = pci_bridge_ids, 
        .probe = pci_bridge_probe, 
        .remove = pci_bridge_remove, 



}; 


/* 
 * File operations i/f. 
 */ 
int pci_bridge_open(struct inode *, struct file *); 
int pci_bridge_release(struct inode *, struct file *); 
ssize_t pci_bridge_read(struct file *, char __user *, size_t, loff_t 
*); 
ssize_t pci_bridge_write(struct file *, const char __user *, size_t, 
loff_t *); 
int pci_bridge_ioctl(struct inode *pnode, struct file *filp, unsigned 
int cmd, unsigned long arg); 
// seek file operation function 
loff_t  bridge_lseek(struct file *filp, loff_t offset, int origin); 

static void dma_descriptor_release(struct pci_dev *pdev); 
static void dma_descriptor_setup(struct pci_dev *pdev); 


static struct file_operations pci_bridge_fops = 
{ 
        read: pci_bridge_read, 
        write: pci_bridge_write, 
        open: pci_bridge_open, 
        release: pci_bridge_release, 
        ioctl: pci_bridge_ioctl, 
        llseek: bridge_lseek 



}; 


static int __init pci_bridge_init(void); 
static void __exit pci_bridge_exit(void); 

/* 
 * Driver major number. 0 = allocate dynamically. 
 */ 
static int pci_bridge_init_major = 0; 
static int pci_bridge_major; 


/* 
 * Per-device structure. 
 */ 
static struct pci_bridge_dev 
{ 
        struct cdev cdev;               /* Char device structure        */ 
        struct pci_dev *pcidev;         /* PCI device pointer           */ 
        int current_resource; 
        u32 page_addr; 
        u8 num_of_bases; 
        int base_map[6]; 
        u32 bases[6]; 
        u32 base_size[6]; 
        u32 base_page_offset; 
        u32 offset; 
        u8  interrupt_line; 



} *pci_bridge_devices; 


static struct device_data 
{ 
        void *dma_buffer_rx; 
        dma_addr_t dma_bus_rx; 
        void *dma_buffer_tx; 
        dma_addr_t dma_bus_tx; 


}*c_memory_map; 


/* 
 * pci_bridge_probe - pci_driver probe function. Just enable the PCI 
device. 
 * Could also check various configuration registers, find a specific 
PCI 
 * device, request a specific region, etc. 
 */ 
static int pci_bridge_probe(struct pci_dev *pcidev, const struct 
pci_device_id *id) 
{ 
        struct pci_bridge_dev *dev; 
        printk("pci_bridge_probe called ...\n"); 
        if(pcidev == NULL) 
        { 
                printk(KERN_NOTICE "pci_bridge_probe: PCI DEV is NULL\n"); 
                return -EINVAL; 
        } 

        dev = pci_bridge_devices; // only one device for now 
        if(dev == NULL) 
                printk("pci_bridge_probe: device structure not allocated\n"); 
        else 
        { 
                pci_enable_device(pcidev); 
                pci_set_master(pcidev); 
                dev->pcidev = pcidev; 
        } 


        return 0; 



} 


/* 
 * pci_bridge_remove - pci_driver remove function. Release allocated 
resources, 
 * etc. 
 */ 
static void __devexit pci_bridge_remove(struct pci_dev *dev) 
{ 
    printk("pci_bridge_remove called ...\n"); 


} 


/* 
 * pci_bridge_init - module init function. By convention, the function 
is 
 * declared static, even though it is not exported to the rest of the 
 * kernel unless explicitly requested via the EXPORT_SYMBOL macro. The 
 * __init qualifier tells the loader that the function is only used at 
 * module initialization time. 
 */ 
static int __init pci_bridge_init(void) 
{ 
        struct pci_bridge_dev *dev; 
        dev_t devno; 
        int result; 
        unsigned short num_of_bases; 
        u32 base_address; 
        printk("pci_bridge_init called ...\n"); 

        /* 
        * Allocate the per-device structure(s). 
        */ 
        pci_bridge_devices = kmalloc(sizeof(struct pci_bridge_dev), 
GFP_KERNEL); 
        if(pci_bridge_devices == NULL) 
        { 
                result = -ENOMEM; 
                goto fail; 
        } 


        /* 
        * Get a range of minor numbers to work with, asking for a dynamic 
        * major unless directed otherwise at load time. 
        */ 
        if(pci_bridge_init_major) 
        { 
                pci_bridge_major = pci_bridge_init_major; 
                devno = MKDEV(pci_bridge_major, 0); 
                result = register_chrdev_region(devno, 1, PCI_DRIVER_NAME); 
        } 
        else 
        { 
                result = alloc_chrdev_region(&devno, 0, 1, PCI_DRIVER_NAME); 
                pci_bridge_major = MAJOR(devno); 
        } 
        if(result < 0) 
        { 
                printk(KERN_NOTICE "pci_bridge: can't get major %d\n", 
pci_bridge_major); 
                goto fail; 
        } 


        dev = pci_bridge_devices;/* only one device for now */ 


        /* 
        * Initialize and add this device's character device table entry. 
        */ 
        dev->pcidev = NULL; 
        cdev_init(&dev->cdev, &pci_bridge_fops); 
        dev->cdev.owner = THIS_MODULE; 
        dev->cdev.ops = &pci_bridge_fops; 
        dev->offset = 0; 
        result = cdev_add(&dev->cdev, devno, 1); 
        if(result) 
        { 
                printk(KERN_NOTICE "Error %d adding %s device", result, 
PCI_DRIVER_NAME); 
                goto fail; 
        } 


        if((result = pci_register_driver(&pci_bridge_driver)) != 0) 
        { 
                printk(KERN_NOTICE "Error %d registering %s PCI device",result, 
PCI_DRIVER_NAME); 
                goto fail; 
        } 


        if(dev->pcidev == NULL) 
        { 
                printk(KERN_NOTICE "PCI DEV is NULL, probe failed?\n"); 
                goto fail; 
        } 


        base_address = pci_resource_start(dev->pcidev, 0); 


        printk("<1> First base address register found at %08X \n ", 
pci_resource_start(dev->pcidev, 0)); 
        num_of_bases = 0; 


        while 
        ((base_address = pci_resource_start(dev->pcidev, num_of_bases))!= 
0x00000000 && (num_of_bases < 6)) 
        { 
                unsigned long flags; 
                flags = pci_resource_flags(dev->pcidev, num_of_bases); 
                dev->bases[num_of_bases] = base_address; 
                dev->base_size[num_of_bases] = pci_resource_end(dev->pcidev, 
num_of_bases) - base_address + 1; 
                // check if resource is IO mapped 
                if (flags & IORESOURCE_IO) 
                    dev->base_map[num_of_bases] = BRIDGE_IO_MAPPED; 
                else 
                    dev->base_map[num_of_bases] = BRIDGE_MEM_MAPPED; 
                num_of_bases++; 
        } 


        if (num_of_bases < 1) 
                printk("<1>No implemented base address registers found! \n "); 


        dev->current_resource = - 1; 


        // store number of bases in structure 
        dev->num_of_bases = num_of_bases; 
        printk("num_of_bases found %d \n", num_of_bases); 
        // display information about all base addresses found in this 
procedure 
        for (num_of_bases = 0; num_of_bases < dev->num_of_bases; num_of_bases+ 
+) 
        { 
                printk("<1>BAR%d range from %08X to %08X \n ", num_of_bases, dev- 


>bases[num_of_bases], dev->bases[num_of_bases] + dev- 
>base_size[num_of_bases]); 


        } 

        if(pci_read_config_byte(dev->pcidev,PCI_INTERRUPT_LINE, &dev- 


>interrupt_line)) 


        { 
                printk("Could not get interrupt line"); 
                } 
        else 
        { 
                printk("Interrupt Line is %d \n", dev->interrupt_line); 
                } 
        dma_descriptor_setup(dev->pcidev); 

        return 0; 


fail: 
                pci_bridge_exit(); 
                return result; 



} 


/* 
 * pci_bridge_exit - module exit function. Release resources allocated 
 * by pci_bridge_init. 
 */ 
static void __exit pci_bridge_exit(void) 
{ 
        printk("pci_bridge_exit called ...\n"); 

        if(pci_bridge_devices) 
        { 
                struct pci_bridge_dev *dev; 
                dev = &pci_bridge_devices[0]; 
                dma_descriptor_release(dev->pcidev); 
                cdev_del(&dev->cdev); 
                kfree(pci_bridge_devices); 
                pci_bridge_devices = NULL; 
        } 
        unregister_chrdev_region(MKDEV(pci_bridge_major, 0), 1); 
        pci_bridge_major = 0; 
        pci_unregister_driver(&pci_bridge_driver); 



} 


/* 
 * pci_bridge_open - open file processing. 
 */ 
int pci_bridge_open(struct inode *inode, struct file *filep) 
{ 
        struct pci_bridge_dev *dev; 
        dev = container_of(inode->i_cdev, struct pci_bridge_dev, cdev); 
        filep->private_data = dev; // used by read, write, etc 
        dev->current_resource = -1; 
        /* Success */ 
        return 0; 


} 


/* 
 * pci_bridge_release - close processing. 
 */ 
int pci_bridge_release(struct inode *inode, struct file *filep) 
{ 
        /* Success */ 
        return 0; 


} 


/* 
 * seek file operation function 
 */ 
loff_t  bridge_lseek(struct file *filp, loff_t offset, int origin) 
{ 
        struct pci_bridge_dev *dev; 
        loff_t requested_offset; 
        int resource_num; 

        dev = filp->private_data; 
        resource_num = dev->current_resource; 
        switch (origin) 
        { 
                case SEEK_CUR:requested_offset = dev->offset + offset; break; 
                case SEEK_END:requested_offset = dev->base_size[resource_num] + 
offset; break; 
                default:requested_offset  = offset; break; 
        } 


        if ((requested_offset < 0) || (requested_offset > dev- 


>base_size[resource_num])) 


                return -EFAULT; 

        dev->offset = requested_offset; 
        return requested_offset; 



} 


/* 
 * pci_bridge_read - read processing. 
 */ 
ssize_t pci_bridge_read (struct file *filp, char *buf, size_t count, 
loff_t *offset_out ) 
{ 
        struct pci_bridge_dev *dev; 
        unsigned long current_address; 
        unsigned long actual_count; 
        unsigned long offset; 
        int resource_num; 
        int i; 
        unsigned int value; 
        unsigned int *kern_buf; 
        unsigned int *kern_buf_tmp; 
        unsigned long size; 
        int result; 

        dev = filp->private_data; 
        offset = dev->offset; 
        resource_num = dev->current_resource; 
        size   = dev->base_size[resource_num]; 
        current_address = dev->page_addr + dev->base_page_offset + dev- 



>offset; 


        if (dev->current_resource < 0) 
                return -ENODEV; 

        if (offset == size) 
                return 0; 


        if ( (offset + count) > size ) 
                actual_count = size - offset; 
        else 
                actual_count = count; 


        // verify range if it is OK to copy from 
        if ((result = access_ok(VERIFY_WRITE, buf, actual_count)) ==0) 
                return result; 


        kern_buf = kmalloc(actual_count, GFP_KERNEL | GFP_DMA); 
        kern_buf_tmp = kern_buf; 
        if (kern_buf <= 0) 
                return 0; 


        memcpy_fromio(kern_buf, current_address, actual_count); 
        i = actual_count/4; 
        while(i--) 
        { 
//              value = readl(current_address); 
                value = *(kern_buf); 
                put_user(value, ((unsigned int *)buf)); 
                buf += 4; 
                ++kern_buf; 
//              current_address += 4; 
        } 


        kfree(kern_buf_tmp); 
        dev->offset = dev->offset + actual_count; 
        *(offset_out) = dev->offset; 


        return actual_count; 
 } 


/* 
 * pci_bridge_write - write processing. 
 */ 
ssize_t pci_bridge_write (struct file *filp, const char *buf, size_t 
count, loff_t *offset_out) 
{ 
        struct pci_bridge_dev *dev; 
        unsigned long current_address; 
        unsigned long actual_count; 
        unsigned long offset; 
        int resource_num; 
        int i; 
        int value; 
        unsigned long size; 
        int result; 
        int *kern_buf; 
        int *kern_buf_tmp; 


        dev = filp->private_data; 
        current_address = dev->page_addr + dev->base_page_offset + dev- 


>offset; 


        resource_num = dev->current_resource; 
        size  = dev->base_size[resource_num]; 
        offset = dev->offset; 

        if (dev->current_resource < 0) 
                return -ENODEV; 


        if (offset == size) 
                return 0; 


        if ( (offset + count) > size ) 
                actual_count = size - offset; 
        else 
                actual_count = count; 


        // verify range if it is OK to copy from 
        if ((result = access_ok(VERIFY_READ, buf, actual_count)) == 0) 
                return result; 
        kern_buf = kmalloc(actual_count, GFP_KERNEL | GFP_DMA); 
        kern_buf_tmp = kern_buf; 
        if (kern_buf <= 0) 
                return 0; 
        i = actual_count/4; 
        while(i--) 
        { 
                get_user(value, ((int *)buf)); 
//              writel(value, current_address); 
                *kern_buf = value; 
                buf += 4; 
                //current_address += 4; 
                ++kern_buf; 
        } 


        memcpy_toio(current_address, kern_buf_tmp, actual_count); 
        kfree(kern_buf_tmp); 
        dev->offset = dev->offset + actual_count; 
        *(offset_out) = dev->offset; 


        return actual_count; 



} 


/* 
 * helper function for memory remaping 
 */ 
int open_mem_mapped(struct pci_bridge_dev *dev) 
{ 
        int resource_num = dev->current_resource; 
        unsigned long num_of_pages = 0; 
        unsigned long base = dev->bases[resource_num]; 
        unsigned long size = dev->base_size[resource_num]; 
        //printk("\n current resource=%d , size = %d, base=%08X", dev- 

>current_resource , size, dev->bases[resource_num]); 


        if (!(num_of_pages = (unsigned long)(size/PAGE_SIZE))); 
                num_of_pages++; 

        dev->base_page_offset = base & ~PAGE_MASK; 


        if ((dev->base_page_offset + size) < (num_of_pages*PAGE_SIZE)) 
                num_of_pages++; 


        // remap memory mapped space 
        dev->page_addr = (unsigned long)ioremap(base & PAGE_MASK, 
num_of_pages * PAGE_SIZE); 


        if (dev->page_addr == 0x00000000) 
                return -ENOMEM; 


        return 0; 



} 


/* 
 * ioctl: see kint.h for the meaning of args 
 */ 
int pci_bridge_ioctl(struct inode *pnode, struct file *filp, unsigned 
int cmd, unsigned long arg) 
{ 

        int error = 0; 
        unsigned long base; 
        unsigned long base_size; 
        struct pci_bridge_dev *dev; 
        dev = filp->private_data; 


        if (_IOC_TYPE(cmd) != BRIDGE_IOC_NUM) return -EINVAL; 
        if (_IOC_NR(cmd) > BRIDGE_IOC_MAX_NUM) return -EINVAL; 


        switch (cmd) 
        { 
                case BRIDGE_IOC_CURRESGET: 
                        // current resource - they start at 1 
                        return (dev->current_resource + 1); 


                case BRIDGE_IOC_CURRESSET: 
                        // check if resource is in a range of implemented resources 
                        if (arg < 0 ) 
                                return -EINVAL; 


                        // unmap previous resource if it was mapped 
                        if (dev->current_resource >= 0) 
                        { 
                                iounmap((void *)dev->page_addr); 
                        } 


                        if (arg == 0) 
                        { 
                                // previous resource unmaped - that's all 
                                dev->current_resource = -1; 
                                return 0; 
                        } 


                        if (dev->num_of_bases < arg) 
                                return -ENODEV; 


                        // IO mapped not supported yet 
                        if (dev->base_map[arg-1] == BRIDGE_IO_MAPPED) 
                        { 
                                // set current resource to none, since it was unmapped 
                                dev->current_resource = -1; 
                                return -ENODEV; 
                        } 
                        dev->current_resource= (int)(arg-1); 
                        // remap new resource 
                        if ( (error = open_mem_mapped(dev)) ) 
                        { 
                                dev->current_resource = -1; 
                                return error; 
                        } 
                        return 0; 


                case BRIDGE_IOC_CURBASE: 
                        // check if any resource is currently activated 
                        if (dev->current_resource>=0) 
                        { 
                                base = dev->bases[dev->current_resource]; 
                                printk("\n CURR_RES = %d",dev->current_resource ); 
                        } 
                        else 
                                base = 0x00000000; 


                        *(unsigned long *)arg = base; 
                        return 0; 


                case BRIDGE_IOC_CURBASEMAP: 
                        // check if any resource is currently activated 
                        if (dev->current_resource>=0) 
                                base = dev->page_addr; 
                        else 
                                base = 0x00000000; 


                        *(unsigned long *)arg = base; 


                        return 0; 


                case BRIDGE_IOC_CURBASESIZE: 
                        // check if any resource is currently activated 
                        if (dev->current_resource>=0) 
                                base_size = dev->base_size[dev->current_resource]; 
                        else 
                                base_size = 0x00000000; 


                        *(unsigned long *)arg = base_size; 
                        return 0; 


                case BRIDGE_IOC_NUMOFRES: 
                        return (dev->num_of_bases); 


                default: 
                        return -EINVAL; 


        } 



} 


#define TX_BUFFER_FLAGS         0x00 
#define RX_BUFFER_FLAGS         0x00 
#define TX_DATA_LEN             0x04 
#define RX_DATA_LEN             0x04 
#define TX_BUFFER_OFFSET        0x0c 
#define RX_BUFFER_OFFSET        0x0c 
#define TX_BUFFER_SIZE          4096 
#define RX_BUFFER_SIZE          4096 
#define WB_RX_BUFFER_AM         0xFF000000 
#define WB_TX_BUFFER_AM         0xFF000000 

static void dma_descriptor_setup(struct pci_dev *pdev) 
{ 
        unsigned long current_address; 
        unsigned int  register_value; 
        int error = 0; 
        unsigned int c_tx_data; 
        printk("DMA ALLOC ROUTINE STARTED\n"); 
        c_memory_map->dma_buffer_rx = pci_alloc_consistent(pdev, 
RX_BUFFER_SIZE+RX_BUFFER_OFFSET, &c_memory_map->dma_bus_rx); 
        printk("RX DMA BUFFER READY\n"); 
        c_memory_map->dma_buffer_tx = pci_alloc_consistent(pdev, 
TX_BUFFER_SIZE+TX_BUFFER_OFFSET, &c_memory_map->dma_bus_tx); 
        printk("TX DMA BUFFER READY\n"); 
        pci_bridge_devices->current_resource = 0; 
        if ( (error = open_mem_mapped(pci_bridge_devices)) ) 
        { 
                pci_bridge_devices->current_resource = -1; 
                printk("Could not set BAR0 on DMA alloc\n"); 
                return; 
        } 
        printk("PCI ADDRESS FOR TX IS %d AND PCI ADDRESS FOR RX IS %d\n", 
c_memory_map->dma_bus_rx, c_memory_map->dma_bus_tx); 
        current_address = pci_bridge_devices->page_addr + pci_bridge_devices- 


>base_page_offset + BRIDGE_W_AM1_ADDR; 


        register_value = WB_RX_BUFFER_AM; 
        memcpy_toio(current_address, &register_value, 4); 
        current_address = pci_bridge_devices->page_addr + pci_bridge_devices- 

>base_page_offset + BRIDGE_W_AM2_ADDR; 


        register_value = WB_TX_BUFFER_AM; 
        memcpy_toio(current_address, &register_value, 4); 


} 


static void dma_descriptor_release(struct pci_dev *pdev) 
{ 
        pci_free_consistent(pdev, RX_BUFFER_SIZE+RX_BUFFER_OFFSET, 
c_memory_map->dma_buffer_rx, c_memory_map->dma_bus_rx); 
        pci_free_consistent(pdev, TX_BUFFER_SIZE+TX_BUFFER_OFFSET, 
c_memory_map->dma_buffer_tx, c_memory_map->dma_bus_tx); 


} 


MODULE_LICENSE("GPL"); 

module_init(pci_bridge_init); 
module_exit(pci_bridge_exit);

Any help would be apreciated.


Thank you
 
Old 03-30-2011, 02:33 PM   #2
nini09
Senior Member
 
Registered: Apr 2009
Posts: 1,853

Rep: Reputation: 161Reputation: 161
Where do you call pci_alloc_consitent?
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Example of PCI + DMA + Interruptdriver. Sink0 Linux - Kernel 1 12-17-2010 06:58 PM
PCI-DMA not syncing: high address but no IOMMU joe_merchant Linux - Hardware 4 09-30-2008 05:16 AM
About the DMA and PCI bus question boer Linux - Kernel 0 08-28-2006 07:31 PM
PCI IDE adapter and DMA Dee-ehn Linux - Software 0 12-28-2004 10:09 AM
DMA over PCI ashutoshsharma Programming 0 03-07-2004 10:13 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Software > Linux - Kernel

All times are GMT -5. The time now is 01:32 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration