diff options
Diffstat (limited to 'driver')
| -rw-r--r-- | driver/base.c | 789 | ||||
| -rw-r--r-- | driver/base.h | 8 | ||||
| -rw-r--r-- | driver/common.h | 110 | ||||
| -rw-r--r-- | driver/compat.c | 23 | ||||
| -rw-r--r-- | driver/compat.h | 198 | ||||
| -rw-r--r-- | driver/int.c | 226 | ||||
| -rw-r--r-- | driver/ioctl.c | 512 | ||||
| -rw-r--r-- | driver/ioctl.h | 4 | ||||
| -rw-r--r-- | driver/kmem.c | 1017 | ||||
| -rw-r--r-- | driver/pciDriver.h | 114 | ||||
| -rw-r--r-- | driver/rdma.c | 20 | ||||
| -rw-r--r-- | driver/sysfs.c | 293 | ||||
| -rw-r--r-- | driver/umem.c | 625 | 
13 files changed, 1724 insertions, 2215 deletions
diff --git a/driver/base.c b/driver/base.c index dfd82c6..220f1f3 100644 --- a/driver/base.c +++ b/driver/base.c @@ -5,144 +5,9 @@   * @date 2009-04-05   * @brief Contains the main code which connects all the different parts and does   * basic driver tasks like initialization. - * - * This is a full rewrite of the pciDriver. - * New default is to support kernel 2.6, using kernel 2.6 APIs. - *   */ -/* - * Change History: - * - * $Log: not supported by cvs2svn $ - * Revision 1.13  2008-05-30 11:38:15  marcus - * Added patches for kernel 2.6.24 - * - * Revision 1.12  2008-01-24 14:21:36  marcus - * Added a CLEAR_INTERRUPT_QUEUE ioctl. - * Added a sysfs attribute to show the outstanding IRQ queues. - * - * Revision 1.11  2008-01-24 12:53:11  marcus - * Corrected wait_event condition in waiti_ioctl. Improved the loop too. - * - * Revision 1.10  2008-01-14 10:39:39  marcus - * Set some messages as debug instead of normal. - * - * Revision 1.9  2008-01-11 10:18:28  marcus - * Modified interrupt mechanism. Added atomic functions and queues, to address race conditions. Removed unused interrupt code. - * - * Revision 1.8  2007-07-17 13:15:55  marcus - * Removed Tasklets. - * Using newest map for the ABB interrupts. - * - * Revision 1.7  2007-07-06 15:56:04  marcus - * Change default status for OLD_REGISTERS to not defined. - * - * Revision 1.6  2007-07-05 15:29:59  marcus - * Corrected issue with the bar mapping for interrupt handling. - * Added support up to kernel 2.6.20 - * - * Revision 1.5  2007-05-29 07:50:18  marcus - * Split code into 2 files. May get merged in the future again.... - * - * Revision 1.4  2007/03/01 17:47:34  marcus - * Fixed bug when the kernel memory was less than one page, it was not locked properly, recalling an old mapping issue in this case. - * - * Revision 1.3  2007/03/01 17:01:22  marcus - * comment fix (again). - * - * Revision 1.2  2007/03/01 17:00:25  marcus - * Changed some comment in the log. - * - * Revision 1.1  2007/03/01 16:57:43  marcus - * Divided driver file to ease the interrupt hooks for the user of the driver. - * Modified Makefile accordingly. - * - * From pciDriver.c: - * Revision 1.11  2006/12/11 16:15:43  marcus - * Fixed kernel buffer mmapping, and driver crash when application crashes. - * Buffer memory is now marked reserved during allocation, and mmaped with - * remap_xx_range. - * - * Revision 1.10  2006/11/21 09:50:49  marcus - * Added PROGRAPE4 vendor/device IDs. - * - * Revision 1.9  2006/11/17 18:47:36  marcus - * Removed MERGE_SGENTRIES flag, now it is selected at runtime with 'type'. - * Removed noncached in non-prefetchable areas, to allow the use of MTRRs. - * - * Revision 1.8  2006/11/17 16:41:21  marcus - * Added slot number to the PCI info IOctl. - * - * Revision 1.7  2006/11/13 12:30:34  marcus - * Added a IOctl call, to confiure the interrupt response. (testing pending). - * Basic interrupts are now supported, using a Tasklet and Completions. - * - * Revision 1.6  2006/11/08 21:30:02  marcus - * Added changes after compile tests in kernel 2.6.16 - * - * Revision 1.5  2006/10/31 07:57:38  marcus - * Improved the pfn calculation in nopage(), to deal with some possible border - * conditions. It was really no issue, because they are normally page-aligned - * anyway, but to be on the safe side. - * - * Revision 1.4  2006/10/30 19:37:40  marcus - * Solved bug on kernel memory not mapping properly. - * - * Revision 1.3  2006/10/18 11:19:20  marcus - * Added kernel 2.6.8 support based on comments from Joern Adamczewski (GSI). - * - * Revision 1.2  2006/10/18 11:04:15  marcus - * Bus Master is only activated when we detect a specific board. - * - * Revision 1.1  2006/10/10 14:46:51  marcus - * Initial commit of the new pciDriver for kernel 2.6 - * - * Revision 1.9  2006/10/05 11:30:46  marcus - * Prerelease. Added bus and devfn to pciInfo for compatibility. - * - * Revision 1.8  2006/09/25 16:51:07  marcus - * Added PCI config IOctls, and implemented basic mmap functions. - * - * Revision 1.7  2006/09/20 11:12:41  marcus - * Added Merge SG entries - * - * Revision 1.6  2006/09/19 17:22:18  marcus - * backup commit. - * - * Revision 1.5  2006/09/18 17:13:11  marcus - * backup commit. - * - * Revision 1.4  2006/09/15 15:44:41  marcus - * backup commit. - * - * Revision 1.3  2006/08/15 11:40:02  marcus - * backup commit. - * - * Revision 1.2  2006/08/12 18:28:42  marcus - * Sync with the laptop - * - * Revision 1.1  2006/08/11 15:30:46  marcus - * Sync with the laptop - * - */ - -#include <linux/version.h> -/* Check macros and kernel version first */ -#ifndef KERNEL_VERSION -#error "No KERNEL_VERSION macro! Stopping." -#endif - -#ifndef LINUX_VERSION_CODE -#error "No LINUX_VERSION_CODE macro! Stopping." -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) -#error "This driver has been tested only for Kernel 2.6.8 or above." -#endif - -/* Required includes */  #include <linux/string.h>  #include <linux/slab.h>  #include <linux/types.h> @@ -166,32 +31,15 @@  #include "../pcilib/version.h" -/* Configuration for the driver (what should be compiled in, module name, etc...) */  #include "config.h" - -/* Compatibility functions/definitions (provides functions which are not available on older kernels) */  #include "compat.h" - -/* External interface for the driver */  #include "pciDriver.h" - -/* Internal definitions for all parts (prototypes, data, macros) */  #include "common.h" - -/* Internal definitions for the base part */  #include "base.h" - -/* Internal definitions of the IRQ handling part */  #include "int.h" - -/* Internal definitions for kernel memory */  #include "kmem.h" - -/* Internal definitions for user space memory */  #include "umem.h" -  #include "ioctl.h" -  #include "build.h"  /*************************************************************************/ @@ -221,54 +69,54 @@ pcidriver_privdata_t *pcidriver_dummydata = NULL;   */  static int __init pcidriver_init(void)  { -	int err = 0; - -	/* Initialize the device count */ -	atomic_set(&pcidriver_deviceCount, 0); -	 -	memset(pcidriver_privdata, 0, sizeof(pcidriver_privdata)); - -	/* Allocate character device region dynamically */ -	if ((err = alloc_chrdev_region(&pcidriver_devt, MINORNR, MAXDEVICES, NODENAME)) != 0) { -		mod_info("Couldn't allocate chrdev region. Module not loaded.\n"); -		goto init_alloc_fail; -	} -	mod_info("Major %d allocated to nodename '%s'\n", MAJOR(pcidriver_devt), NODENAME); - -	/* Register driver class */ -	pcidriver_class = class_create(THIS_MODULE, NODENAME); - -	if (IS_ERR(pcidriver_class)) { -		mod_info("No sysfs support. Module not loaded.\n"); -		goto init_class_fail; -	} - -	/* Register PCI driver. This function returns the number of devices on some -	 * systems, therefore check for errors as < 0. */ +    int err = 0; + +    /* Initialize the device count */ +    atomic_set(&pcidriver_deviceCount, 0); + +    memset(pcidriver_privdata, 0, sizeof(pcidriver_privdata)); + +    /* Allocate character device region dynamically */ +    if ((err = alloc_chrdev_region(&pcidriver_devt, MINORNR, MAXDEVICES, NODENAME)) != 0) { +        mod_info("Couldn't allocate chrdev region. Module not loaded.\n"); +        goto init_alloc_fail; +    } +    mod_info("Major %d allocated to nodename '%s'\n", MAJOR(pcidriver_devt), NODENAME); + +    /* Register driver class */ +    pcidriver_class = class_create(THIS_MODULE, NODENAME); + +    if (IS_ERR(pcidriver_class)) { +        mod_info("No sysfs support. Module not loaded.\n"); +        goto init_class_fail; +    } + +    /* Register PCI driver. This function returns the number of devices on some +     * systems, therefore check for errors as < 0. */  #ifdef PCIDRIVER_DUMMY_DEVICE -	if ((err = pcidriver_probe(NULL, NULL)) < 0) { +    if ((err = pcidriver_probe(NULL, NULL)) < 0) {  #else /* PCIDRIVER_DUMMY_DEVICE */ -	if ((err = pci_register_driver(&pcidriver_driver)) < 0) { +    if ((err = pci_register_driver(&pcidriver_driver)) < 0) {  #endif /* PCIDRIVER_DUMMY_DEVICE */ -		mod_info("Couldn't register PCI driver. Module not loaded.\n"); -		goto init_pcireg_fail; -	} +        mod_info("Couldn't register PCI driver. Module not loaded.\n"); +        goto init_pcireg_fail; +    } -	mod_info("pcidriver %u.%u.%u loaded\n", PCILIB_VERSION_GET_MAJOR(PCILIB_VERSION), PCILIB_VERSION_GET_MINOR(PCILIB_VERSION), PCILIB_VERSION_GET_MICRO(PCILIB_VERSION)); -	mod_info("%s\n", PCIDRIVER_BUILD); -	mod_info("%s\n", PCIDRIVER_REVISION); -	if (strlen(PCIDRIVER_CHANGES)) { -	    mod_info("Extra changes - %s\n", PCIDRIVER_CHANGES); -	} +    mod_info("pcidriver %u.%u.%u loaded\n", PCILIB_VERSION_GET_MAJOR(PCILIB_VERSION), PCILIB_VERSION_GET_MINOR(PCILIB_VERSION), PCILIB_VERSION_GET_MICRO(PCILIB_VERSION)); +    mod_info("%s\n", PCIDRIVER_BUILD); +    mod_info("%s\n", PCIDRIVER_REVISION); +    if (strlen(PCIDRIVER_CHANGES)) { +        mod_info("Extra changes - %s\n", PCIDRIVER_CHANGES); +    } -	return 0; +    return 0;  init_pcireg_fail: -	class_destroy(pcidriver_class); +    class_destroy(pcidriver_class);  init_class_fail: -	unregister_chrdev_region(pcidriver_devt, MAXDEVICES); +    unregister_chrdev_region(pcidriver_devt, MAXDEVICES);  init_alloc_fail: -	return err; +    return err;  }  /** @@ -279,17 +127,17 @@ init_alloc_fail:  static void pcidriver_exit(void)  {  #ifdef PCIDRIVER_DUMMY_DEVICE -	pcidriver_remove(NULL); +    pcidriver_remove(NULL);  #else -	pci_unregister_driver(&pcidriver_driver); +    pci_unregister_driver(&pcidriver_driver);  #endif /* PCIDRIVER_DUMMY_DEVICE */ -	unregister_chrdev_region(pcidriver_devt, MAXDEVICES); +    unregister_chrdev_region(pcidriver_devt, MAXDEVICES); -	if (pcidriver_class != NULL) -		class_destroy(pcidriver_class); +    if (pcidriver_class != NULL) +        class_destroy(pcidriver_class); -	mod_info("Module unloaded\n"); +    mod_info("Module unloaded\n");  }  /*************************************************************************/ @@ -303,10 +151,10 @@ static void pcidriver_exit(void)   */  #ifndef PCIDRIVER_DUMMY_DEVICE  static struct pci_driver pcidriver_driver = { -	.name = MODNAME, -	.id_table = pcidriver_ids, -	.probe = pcidriver_probe, -	.remove = pcidriver_remove, +    .name = MODNAME, +    .id_table = pcidriver_ids, +    .probe = pcidriver_probe, +    .remove = pcidriver_remove,  };  #endif /* ! PCIDRIVER_DUMMY_DEVICE */ @@ -318,155 +166,155 @@ static struct pci_driver pcidriver_driver = {   */  static int __devinit pcidriver_probe(struct pci_dev *pdev, const struct pci_device_id *id)  { -	int err = 0; -	int devno; -	pcidriver_privdata_t *privdata; -	int devid; - -	/* At the moment there is no difference between these boards here, other than -	 * printing a different message in the log. -	 * -	 * However, there is some difference in the interrupt handling functions. -	 */ +    int err = 0; +    int devno; +    pcidriver_privdata_t *privdata; +    int devid; + +    /* At the moment there is no difference between these boards here, other than +     * printing a different message in the log. +     * +     * However, there is some difference in the interrupt handling functions. +     */  #ifdef PCIDRIVER_DUMMY_DEVICE -	mod_info("Emulated device\n"); +    mod_info("Emulated device\n");  #else /* PCIDRIVER_DUMMY_DEVICE */ -	if (id->vendor == PCIE_XILINX_VENDOR_ID) { -	    if (id->device == PCIE_ML605_DEVICE_ID) { -		mod_info("Found ML605 board at %s\n", dev_name(&pdev->dev)); -	    } else if (id->device == PCIE_IPECAMERA_DEVICE_ID) { -		mod_info("Found IPE Camera at %s\n", dev_name(&pdev->dev)); -	    } else if (id->device == PCIE_KAPTURE_DEVICE_ID) { -		mod_info("Found KAPTURE board at %s\n", dev_name(&pdev->dev)); -	    } else { -		mod_info("Found unknown Xilinx device (%x) at %s\n", id->device, dev_name(&pdev->dev)); -	    } -	} else { -	    /* It is something else */ -	    mod_info("Found unknown board (%x:%x) at %s\n", id->vendor, id->device, dev_name(&pdev->dev)); -	} - -	/* Enable the device */ -	if ((err = pci_enable_device(pdev)) != 0) { -	    mod_info("Couldn't enable device\n"); -	    goto probe_pcien_fail; -	} -	 -	/* Bus master & dma */ -	pci_set_master(pdev); -	     -	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); -	if (err < 0) { -	    printk(KERN_ERR "pci_set_dma_mask failed\n"); -	    goto probe_dma_fail; -	} - -	/* Set Memory-Write-Invalidate support */ -	if ((err = pci_set_mwi(pdev)) != 0) -	    mod_info("MWI not supported. Continue without enabling MWI.\n"); +    if (id->vendor == PCIE_XILINX_VENDOR_ID) { +        if (id->device == PCIE_ML605_DEVICE_ID) { +            mod_info("Found ML605 board at %s\n", dev_name(&pdev->dev)); +        } else if (id->device == PCIE_IPECAMERA_DEVICE_ID) { +            mod_info("Found IPE Camera at %s\n", dev_name(&pdev->dev)); +        } else if (id->device == PCIE_KAPTURE_DEVICE_ID) { +            mod_info("Found KAPTURE board at %s\n", dev_name(&pdev->dev)); +        } else { +            mod_info("Found unknown Xilinx device (%x) at %s\n", id->device, dev_name(&pdev->dev)); +        } +    } else { +        /* It is something else */ +        mod_info("Found unknown board (%x:%x) at %s\n", id->vendor, id->device, dev_name(&pdev->dev)); +    } + +    /* Enable the device */ +    if ((err = pci_enable_device(pdev)) != 0) { +        mod_info("Couldn't enable device\n"); +        goto probe_pcien_fail; +    } + +    /* Bus master & dma */ +    pci_set_master(pdev); + +    err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); +    if (err < 0) { +        printk(KERN_ERR "pci_set_dma_mask failed\n"); +        goto probe_dma_fail; +    } + +    /* Set Memory-Write-Invalidate support */ +    if ((err = pci_set_mwi(pdev)) != 0) +        mod_info("MWI not supported. Continue without enabling MWI.\n");  #endif /* PCIDRIVER_DUMMY_DEVICE */ -	/* Get / Increment the device id */ -	devid = atomic_inc_return(&pcidriver_deviceCount) - 1; -	if (devid >= MAXDEVICES) { -		mod_info("Maximum number of devices reached! Increase MAXDEVICES.\n"); -		err = -ENOMSG; -		goto probe_maxdevices_fail; -	} - -	/* Allocate and initialize the private data for this device */ -	if ((privdata = kcalloc(1, sizeof(*privdata), GFP_KERNEL)) == NULL) { -		err = -ENOMEM; -		goto probe_nomem; -	} -	 -	privdata->devid = devid; - -	INIT_LIST_HEAD(&(privdata->kmem_list)); -	spin_lock_init(&(privdata->kmemlist_lock)); -	atomic_set(&privdata->kmem_count, 0); -	 -	INIT_LIST_HEAD(&(privdata->umem_list)); -	spin_lock_init(&(privdata->umemlist_lock)); -	atomic_set(&privdata->umem_count, 0); +    /* Get / Increment the device id */ +    devid = atomic_inc_return(&pcidriver_deviceCount) - 1; +    if (devid >= MAXDEVICES) { +        mod_info("Maximum number of devices reached! Increase MAXDEVICES.\n"); +        err = -ENOMSG; +        goto probe_maxdevices_fail; +    } + +    /* Allocate and initialize the private data for this device */ +    if ((privdata = kcalloc(1, sizeof(*privdata), GFP_KERNEL)) == NULL) { +        err = -ENOMEM; +        goto probe_nomem; +    } + +    privdata->devid = devid; + +    INIT_LIST_HEAD(&(privdata->kmem_list)); +    spin_lock_init(&(privdata->kmemlist_lock)); +    atomic_set(&privdata->kmem_count, 0); + +    INIT_LIST_HEAD(&(privdata->umem_list)); +    spin_lock_init(&(privdata->umemlist_lock)); +    atomic_set(&privdata->umem_count, 0);  #ifdef PCIDRIVER_DUMMY_DEVICE -	pcidriver_dummydata = privdata; +    pcidriver_dummydata = privdata;  #else /* PCIDRIVER_DUMMY_DEVICE */ -	pci_set_drvdata(pdev, privdata); -	privdata->pdev = pdev; +    pci_set_drvdata(pdev, privdata); +    privdata->pdev = pdev;  #endif /* PCIDRIVER_DUMMY_DEVICE */ -	/* Device add to sysfs */ -	devno = MKDEV(MAJOR(pcidriver_devt), MINOR(pcidriver_devt) + devid); -	privdata->devno = devno; +    /* Device add to sysfs */ +    devno = MKDEV(MAJOR(pcidriver_devt), MINOR(pcidriver_devt) + devid); +    privdata->devno = devno; -	/* FIXME: some error checking missing here */ +    /* FIXME: some error checking missing here */  #ifdef PCIDRIVER_DUMMY_DEVICE -	privdata->class_dev = class_device_create(pcidriver_class, NULL, devno, NULL, NODENAMEFMT, MINOR(pcidriver_devt) + devid, privdata); +    privdata->class_dev = class_device_create(pcidriver_class, NULL, devno, NULL, NODENAMEFMT, MINOR(pcidriver_devt) + devid, privdata);  #else /* PCIDRIVER_DUMMY_DEVICE */ -	privdata->class_dev = class_device_create(pcidriver_class, NULL, devno, &(pdev->dev), NODENAMEFMT, MINOR(pcidriver_devt) + devid, privdata); +    privdata->class_dev = class_device_create(pcidriver_class, NULL, devno, &(pdev->dev), NODENAMEFMT, MINOR(pcidriver_devt) + devid, privdata);  #endif /* PCIDRIVER_DUMMY_DEVICE */ -	class_set_devdata( privdata->class_dev, privdata ); -	mod_info("Device /dev/%s%d added\n",NODENAME,MINOR(pcidriver_devt) + devid); +    class_set_devdata( privdata->class_dev, privdata ); +    mod_info("Device /dev/%s%d added\n",NODENAME,MINOR(pcidriver_devt) + devid);  #ifndef PCIDRIVER_DUMMY_DEVICE -	/* Setup mmaped BARs into kernel space */ -	if ((err = pcidriver_probe_irq(privdata)) != 0) -		goto probe_irq_probe_fail; +    /* Setup mmaped BARs into kernel space */ +    if ((err = pcidriver_probe_irq(privdata)) != 0) +        goto probe_irq_probe_fail;  #endif /* ! PCIDRIVER_DUMMY_DEVICE */ -	/* Populate sysfs attributes for the class device */ -	/* TODO: correct errorhandling. ewww. must remove the files in reversed order :-( */ -	#define sysfs_attr(name) do { \ +    /* Populate sysfs attributes for the class device */ +    /* TODO: correct errorhandling. ewww. must remove the files in reversed order :-( */ +#define sysfs_attr(name) do { \  			if (class_device_create_file(sysfs_attr_def_pointer, &sysfs_attr_def_name(name)) != 0) \  				goto probe_device_create_fail; \  			} while (0) -	#ifdef ENABLE_IRQ -	sysfs_attr(irq_count); -	sysfs_attr(irq_queues); -	#endif - -	sysfs_attr(mmap_mode); -	sysfs_attr(mmap_area); -	sysfs_attr(kmem_count); -	sysfs_attr(kmem_alloc); -	sysfs_attr(kmem_free); -	sysfs_attr(kbuffers); -	sysfs_attr(umappings); -	sysfs_attr(umem_unmap); -	#undef sysfs_attr - -	/* Register character device */ -	cdev_init( &(privdata->cdev), &pcidriver_fops ); -	privdata->cdev.owner = THIS_MODULE; -	privdata->cdev.ops = &pcidriver_fops; -	err = cdev_add( &privdata->cdev, devno, 1 ); -	if (err) { -		mod_info( "Couldn't add character device.\n" ); -		goto probe_cdevadd_fail; -	} - -        pcidriver_privdata[devid] = privdata; - -	return 0; +#ifdef ENABLE_IRQ +    sysfs_attr(irq_count); +    sysfs_attr(irq_queues); +#endif + +    sysfs_attr(mmap_mode); +    sysfs_attr(mmap_area); +    sysfs_attr(kmem_count); +    sysfs_attr(kmem_alloc); +    sysfs_attr(kmem_free); +    sysfs_attr(kbuffers); +    sysfs_attr(umappings); +    sysfs_attr(umem_unmap); +#undef sysfs_attr + +    /* Register character device */ +    cdev_init( &(privdata->cdev), &pcidriver_fops ); +    privdata->cdev.owner = THIS_MODULE; +    privdata->cdev.ops = &pcidriver_fops; +    err = cdev_add( &privdata->cdev, devno, 1 ); +    if (err) { +        mod_info( "Couldn't add character device.\n" ); +        goto probe_cdevadd_fail; +    } + +    pcidriver_privdata[devid] = privdata; + +    return 0;  probe_device_create_fail:  probe_cdevadd_fail:  #ifndef PCIDRIVER_DUMMY_DEVICE  probe_irq_probe_fail: -	pcidriver_irq_unmap_bars(privdata); +    pcidriver_irq_unmap_bars(privdata);  #endif /* ! PCIDRIVER_DUMMY_DEVICE */ -	kfree(privdata); +    kfree(privdata);  probe_nomem: -	atomic_dec(&pcidriver_deviceCount); +    atomic_dec(&pcidriver_deviceCount);  probe_maxdevices_fail:  #ifndef PCIDRIVER_DUMMY_DEVICE  probe_dma_fail: -	pci_disable_device(pdev); +    pci_disable_device(pdev);  probe_pcien_fail:  #endif /* ! PCIDRIVER_DUMMY_DEVICE */ - 	return err; +    return err;  }  /** @@ -476,62 +324,62 @@ probe_pcien_fail:   */  static void __devexit pcidriver_remove(struct pci_dev *pdev)  { -	pcidriver_privdata_t *privdata; +    pcidriver_privdata_t *privdata;  #ifdef PCIDRIVER_DUMMY_DEVICE -	privdata = pcidriver_dummydata; -	pcidriver_dummydata = NULL; +    privdata = pcidriver_dummydata; +    pcidriver_dummydata = NULL;  #else /* PCIDRIVER_DUMMY_DEVICE */ -	/* Get private data from the device */ -	privdata = pci_get_drvdata(pdev); +    /* Get private data from the device */ +    privdata = pci_get_drvdata(pdev);  #endif /* PCIDRIVER_DUMMY_DEVICE */ -            // Theoretically we should lock here and when using... -        pcidriver_privdata[privdata->devid] = NULL; +    // Theoretically we should lock here and when using... +    pcidriver_privdata[privdata->devid] = NULL; -	/* Removing sysfs attributes from class device */ -	#define sysfs_attr(name) do { \ +    /* Removing sysfs attributes from class device */ +#define sysfs_attr(name) do { \  			class_device_remove_file(sysfs_attr_def_pointer, &sysfs_attr_def_name(name)); \  			} while (0) -	#ifdef ENABLE_IRQ -	sysfs_attr(irq_count); -	sysfs_attr(irq_queues); -	#endif - -	sysfs_attr(mmap_mode); -	sysfs_attr(mmap_area); -	sysfs_attr(kmem_count); -	sysfs_attr(kmem_alloc); -	sysfs_attr(kmem_free); -	sysfs_attr(kbuffers); -	sysfs_attr(umappings); -	sysfs_attr(umem_unmap); -	#undef sysfs_attr - -	/* Free all allocated kmem buffers before leaving */ -	pcidriver_kmem_free_all( privdata ); +#ifdef ENABLE_IRQ +    sysfs_attr(irq_count); +    sysfs_attr(irq_queues); +#endif + +    sysfs_attr(mmap_mode); +    sysfs_attr(mmap_area); +    sysfs_attr(kmem_count); +    sysfs_attr(kmem_alloc); +    sysfs_attr(kmem_free); +    sysfs_attr(kbuffers); +    sysfs_attr(umappings); +    sysfs_attr(umem_unmap); +#undef sysfs_attr + +    /* Free all allocated kmem buffers before leaving */ +    pcidriver_kmem_free_all( privdata );  #ifndef PCIDRIVER_DUMMY_DEVICE  # ifdef ENABLE_IRQ -	pcidriver_remove_irq(privdata); +    pcidriver_remove_irq(privdata);  # endif  #endif /* ! PCIDRIVER_DUMMY_DEVICE */ -	/* Removing Character device */ -	cdev_del(&(privdata->cdev)); +    /* Removing Character device */ +    cdev_del(&(privdata->cdev)); -	/* Removing the device from sysfs */ -	class_device_destroy(pcidriver_class, privdata->devno); +    /* Removing the device from sysfs */ +    class_device_destroy(pcidriver_class, privdata->devno); -	/* Releasing privdata */ -	kfree(privdata); +    /* Releasing privdata */ +    kfree(privdata);  #ifdef PCIDRIVER_DUMMY_DEVICE -	mod_info("Device at " NODENAMEFMT " removed\n", 0); +    mod_info("Device at " NODENAMEFMT " removed\n", 0);  #else /* PCIDRIVER_DUMMY_DEVICE */ -	/* Disabling PCI device */ -	pci_disable_device(pdev); -	mod_info("Device at %s removed\n", dev_name(&pdev->dev)); +    /* Disabling PCI device */ +    pci_disable_device(pdev); +    mod_info("Device at %s removed\n", dev_name(&pdev->dev));  #endif /* PCIDRIVER_DUMMY_DEVICE */  } @@ -550,15 +398,11 @@ static void __devexit pcidriver_remove(struct pci_dev *pdev)   *   */  static struct file_operations pcidriver_fops = { -	.owner = THIS_MODULE, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) -	.ioctl = pcidriver_ioctl, -#else -	.unlocked_ioctl = pcidriver_ioctl, -#endif  -	.mmap = pcidriver_mmap, -	.open = pcidriver_open, -	.release = pcidriver_release, +    .owner = THIS_MODULE, +    .unlocked_ioctl = pcidriver_ioctl, +    .mmap = pcidriver_mmap, +    .open = pcidriver_open, +    .release = pcidriver_release,  };  void pcidriver_module_get(pcidriver_privdata_t *privdata) { @@ -568,8 +412,8 @@ void pcidriver_module_get(pcidriver_privdata_t *privdata) {  void pcidriver_module_put(pcidriver_privdata_t *privdata) {      if (atomic_add_negative(-1, &(privdata->refs))) { -	atomic_inc(&(privdata->refs)); -	mod_info("Reference counting error..."); +        atomic_inc(&(privdata->refs)); +        mod_info("Reference counting error...");      } else {  //	mod_info("Unref: %i\n", atomic_read(&(privdata->refs)));      } @@ -583,15 +427,15 @@ void pcidriver_module_put(pcidriver_privdata_t *privdata) {   */  int pcidriver_open(struct inode *inode, struct file *filp)  { -	pcidriver_privdata_t *privdata; +    pcidriver_privdata_t *privdata; -	/* Set the private data area for the file */ -	privdata = container_of( inode->i_cdev, pcidriver_privdata_t, cdev); -	filp->private_data = privdata; +    /* Set the private data area for the file */ +    privdata = container_of( inode->i_cdev, pcidriver_privdata_t, cdev); +    filp->private_data = privdata; -	pcidriver_module_get(privdata); +    pcidriver_module_get(privdata); -	return 0; +    return 0;  }  /** @@ -602,14 +446,14 @@ int pcidriver_open(struct inode *inode, struct file *filp)   */  int pcidriver_release(struct inode *inode, struct file *filp)  { -	pcidriver_privdata_t *privdata; +    pcidriver_privdata_t *privdata; -	/* Get the private data area */ -	privdata = filp->private_data; +    /* Get the private data area */ +    privdata = filp->private_data; -	pcidriver_module_put(privdata); +    pcidriver_module_put(privdata); -	return 0; +    return 0;  }  /** @@ -623,42 +467,54 @@ int pcidriver_release(struct inode *inode, struct file *filp)   */  int pcidriver_mmap(struct file *filp, struct vm_area_struct *vma)  { -	pcidriver_privdata_t *privdata; -	int ret = 0, bar; - -	mod_info_dbg("Entering mmap\n"); - -	/* Get the private data area */ -	privdata = filp->private_data; - -	/* Check the current mmap mode */ -	switch (privdata->mmap_mode) { -		case PCIDRIVER_MMAP_PCI: -			/* Mmap a PCI region */ -			switch (privdata->mmap_area) { -				case PCIDRIVER_BAR0:	bar = 0; break; -				case PCIDRIVER_BAR1:	bar = 1; break; -				case PCIDRIVER_BAR2:	bar = 2; break; -				case PCIDRIVER_BAR3:	bar = 3; break; -				case PCIDRIVER_BAR4:	bar = 4; break; -				case PCIDRIVER_BAR5:	bar = 5; break; -				default: -					mod_info("Attempted to mmap a PCI area with the wrong mmap_area value: %d\n",privdata->mmap_area); -					return -EINVAL;			/* invalid parameter */ -					break; -			} -			ret = pcidriver_mmap_pci(privdata, vma, bar); -			break; -		case PCIDRIVER_MMAP_KMEM: -			/* mmap a Kernel buffer */ -			ret = pcidriver_mmap_kmem(privdata, vma); -			break; -		default: -			mod_info( "Invalid mmap_mode value (%d)\n",privdata->mmap_mode ); -			return -EINVAL;			/* Invalid parameter (mode) */ -	} - -	return ret; +    pcidriver_privdata_t *privdata; +    int ret = 0, bar; + +    mod_info_dbg("Entering mmap\n"); + +    /* Get the private data area */ +    privdata = filp->private_data; + +    /* Check the current mmap mode */ +    switch (privdata->mmap_mode) { +    case PCIDRIVER_MMAP_PCI: +        /* Mmap a PCI region */ +        switch (privdata->mmap_area) { +        case PCIDRIVER_BAR0: +            bar = 0; +            break; +        case PCIDRIVER_BAR1: +            bar = 1; +            break; +        case PCIDRIVER_BAR2: +            bar = 2; +            break; +        case PCIDRIVER_BAR3: +            bar = 3; +            break; +        case PCIDRIVER_BAR4: +            bar = 4; +            break; +        case PCIDRIVER_BAR5: +            bar = 5; +            break; +        default: +            mod_info("Attempted to mmap a PCI area with the wrong mmap_area value: %d\n",privdata->mmap_area); +            return -EINVAL;			/* invalid parameter */ +            break; +        } +        ret = pcidriver_mmap_pci(privdata, vma, bar); +        break; +    case PCIDRIVER_MMAP_KMEM: +        /* mmap a Kernel buffer */ +        ret = pcidriver_mmap_kmem(privdata, vma); +        break; +    default: +        mod_info( "Invalid mmap_mode value (%d)\n",privdata->mmap_mode ); +        return -EINVAL;			/* Invalid parameter (mode) */ +    } + +    return ret;  }  /*************************************************************************/ @@ -666,76 +522,65 @@ int pcidriver_mmap(struct file *filp, struct vm_area_struct *vma)  int pcidriver_mmap_pci(pcidriver_privdata_t *privdata, struct vm_area_struct *vmap, int bar)  {  #ifdef PCIDRIVER_DUMMY_DEVICE -	return -ENXIO; +    return -ENXIO;  #else /* PCIDRIVER_DUMMY_DEVICE */ -	int ret = 0; -	unsigned long bar_addr; -	unsigned long bar_length, vma_size; -	unsigned long bar_flags; +    int ret = 0; +    unsigned long bar_addr; +    unsigned long bar_length, vma_size; +    unsigned long bar_flags; -	mod_info_dbg("Entering mmap_pci\n"); +    mod_info_dbg("Entering mmap_pci\n"); -	/* Get info of the BAR to be mapped */ -	bar_addr = pci_resource_start(privdata->pdev, bar); -	bar_length = pci_resource_len(privdata->pdev, bar); -	bar_flags = pci_resource_flags(privdata->pdev, bar); +    /* Get info of the BAR to be mapped */ +    bar_addr = pci_resource_start(privdata->pdev, bar); +    bar_length = pci_resource_len(privdata->pdev, bar); +    bar_flags = pci_resource_flags(privdata->pdev, bar); -	/* Check sizes */ -	vma_size = (vmap->vm_end - vmap->vm_start); +    /* Check sizes */ +    vma_size = (vmap->vm_end - vmap->vm_start); -	if ((vma_size != bar_length) && -	   ((bar_length < PAGE_SIZE) && (vma_size != PAGE_SIZE))) { -		mod_info( "mmap size is not correct! bar: %lu - vma: %lu\n", bar_length, vma_size ); -		return -EINVAL; -	} +    if ((vma_size != bar_length) && +            ((bar_length < PAGE_SIZE) && (vma_size != PAGE_SIZE))) { +        mod_info( "mmap size is not correct! bar: %lu - vma: %lu\n", bar_length, vma_size ); +        return -EINVAL; +    } -	if (bar_flags & IORESOURCE_IO) { -		/* Unlikely case, we will mmap a IO region */ +    if (bar_flags & IORESOURCE_IO) { +        /* Unlikely case, we will mmap a IO region */ -		/* IO regions are never cacheable */ -#ifdef pgprot_noncached -		vmap->vm_page_prot = pgprot_noncached(vmap->vm_page_prot); -#endif +        /* IO regions are never cacheable */ +        vmap->vm_page_prot = pgprot_noncached(vmap->vm_page_prot); -		/* Map the BAR */ -		ret = io_remap_pfn_range_compat( -					vmap, -					vmap->vm_start, -					bar_addr, -					bar_length, -					vmap->vm_page_prot); -	} else { -		/* Normal case, mmap a memory region */ - -		/* Ensure this VMA is non-cached, if it is not flaged as prefetchable. -		 * If it is prefetchable, caching is allowed and will give better performance. -		 * This should be set properly by the BIOS, but we want to be sure. */ -		/* adapted from drivers/char/mem.c, mmap function. */ -#ifdef pgprot_noncached -/* Setting noncached disables MTRR registers, and we want to use them. - * So we take this code out. This can lead to caching problems if and only if - * the System BIOS set something wrong. Check LDDv3, page 425. - */ -//		if (!(bar_flags & IORESOURCE_PREFETCH)) +        /* Map the BAR */ +        ret = io_remap_pfn_range_compat(vmap, vmap->vm_start, bar_addr, bar_length, vmap->vm_page_prot); +    } else { +        /* Normal case, mmap a memory region */ + +        /* Ensure this VMA is non-cached, if it is not flaged as prefetchable. +         * If it is prefetchable, caching is allowed and will give better performance. +         * This should be set properly by the BIOS, but we want to be sure. */ +        /* adapted from drivers/char/mem.c, mmap function. */ + +        /* Setting noncached disables MTRR registers, and we want to use them. +         * So we take this code out. This can lead to caching problems if and only if +         * the System BIOS set something wrong. Check LDDv3, page 425. +         */ + +//                if (!(bar_flags & IORESOURCE_PREFETCH))  //			vmap->vm_page_prot = pgprot_noncached(vmap->vm_page_prot); -#endif -		/* Map the BAR */ -		ret = remap_pfn_range_compat( -					vmap, -					vmap->vm_start, -					bar_addr, -					bar_length, -					vmap->vm_page_prot); -	} - -	if (ret) { -		mod_info("remap_pfn_range failed\n"); -		return -EAGAIN; -	} - -	return 0;	/* success */ + +        /* Map the BAR */ +        ret = remap_pfn_range_compat(vmap, vmap->vm_start, bar_addr, bar_length, vmap->vm_page_prot); +    } + +    if (ret) { +        mod_info("remap_pfn_range failed\n"); +        return -EAGAIN; +    } + +    return 0;	/* success */  #endif /* PCIDRIVER_DUMMY_DEVICE */  } diff --git a/driver/base.h b/driver/base.h index dce865f..8556480 100644 --- a/driver/base.h +++ b/driver/base.h @@ -47,10 +47,10 @@ static void pcidriver_exit(void);   */  static const __devinitdata struct pci_device_id pcidriver_ids[] = { -	{ PCI_DEVICE( PCIE_XILINX_VENDOR_ID, PCIE_ML605_DEVICE_ID ) },          // PCI-E Xilinx ML605 -	{ PCI_DEVICE( PCIE_XILINX_VENDOR_ID, PCIE_IPECAMERA_DEVICE_ID ) },      // PCI-E IPE Camera -	{ PCI_DEVICE( PCIE_XILINX_VENDOR_ID, PCIE_KAPTURE_DEVICE_ID ) },        // PCI-E KAPTURE board for HEB -	{0,0,0,0}, +    { PCI_DEVICE( PCIE_XILINX_VENDOR_ID, PCIE_ML605_DEVICE_ID ) },          // PCI-E Xilinx ML605 +    { PCI_DEVICE( PCIE_XILINX_VENDOR_ID, PCIE_IPECAMERA_DEVICE_ID ) },      // PCI-E IPE Camera +    { PCI_DEVICE( PCIE_XILINX_VENDOR_ID, PCIE_KAPTURE_DEVICE_ID ) },        // PCI-E KAPTURE board for HEB +    {0,0,0,0},  };  /* prototypes for internal driver functions */ diff --git a/driver/common.h b/driver/common.h index a83fd5e..48b2769 100644 --- a/driver/common.h +++ b/driver/common.h @@ -9,70 +9,70 @@  /* Define an entry in the kmem list (this list is per device) */  /* This list keeps references to the allocated kernel buffers */  typedef struct { -	int id; -	enum dma_data_direction direction; -	 -	struct list_head list; -	dma_addr_t dma_handle; -	unsigned long cpua; -	unsigned long size; -	unsigned long type; -	unsigned long align; - -	unsigned long use; -	unsigned long item; - -	spinlock_t lock; -	unsigned long mode; -	unsigned long refs; - -	struct class_device_attribute sysfs_attr;	/* initialized when adding the entry */ +    int id; +    enum dma_data_direction direction; + +    struct list_head list; +    dma_addr_t dma_handle; +    unsigned long cpua; +    unsigned long size; +    unsigned long type; +    unsigned long align; + +    unsigned long use; +    unsigned long item; + +    spinlock_t lock; +    unsigned long mode; +    unsigned long refs; + +    struct class_device_attribute sysfs_attr;	/* initialized when adding the entry */  } pcidriver_kmem_entry_t;  /* Define an entry in the umem list (this list is per device) */  /* This list keeps references to the SG lists for each mapped userspace region */  typedef struct { -	int id; -	struct list_head list; -	unsigned int nr_pages;		/* number of pages for this user memeory area */ -	struct page **pages;		/* list of pointers to the pages */ -	unsigned int nents;		/* actual entries in the scatter/gatter list (NOT nents for the map function, but the result) */ -	struct scatterlist *sg;		/* list of sg entries */ -	struct class_device_attribute sysfs_attr;	/* initialized when adding the entry */ +    int id; +    struct list_head list; +    unsigned int nr_pages;		/* number of pages for this user memeory area */ +    struct page **pages;		/* list of pointers to the pages */ +    unsigned int nents;		/* actual entries in the scatter/gatter list (NOT nents for the map function, but the result) */ +    struct scatterlist *sg;		/* list of sg entries */ +    struct class_device_attribute sysfs_attr;	/* initialized when adding the entry */  } pcidriver_umem_entry_t;  /* Hold the driver private data */  typedef struct  { -        int devid;                                      /* the device id */ -	dev_t devno;					/* device number (major and minor) */ -	struct pci_dev *pdev;				/* PCI device */ -	struct class_device *class_dev;                 /* Class device */ -	struct cdev cdev;				/* char device struct */ -	int mmap_mode;					/* current mmap mode */ -	int mmap_area;					/* current PCI mmap area */ +    int devid;                                      /* the device id */ +    dev_t devno;					/* device number (major and minor) */ +    struct pci_dev *pdev;				/* PCI device */ +    struct class_device *class_dev;                 /* Class device */ +    struct cdev cdev;				/* char device struct */ +    int mmap_mode;					/* current mmap mode */ +    int mmap_area;					/* current PCI mmap area */  #ifdef ENABLE_IRQ -	int irq_enabled;				/* Non-zero if IRQ is enabled */ -	int irq_count;					/* Just an IRQ counter */ +    int irq_enabled;				/* Non-zero if IRQ is enabled */ +    int irq_count;					/* Just an IRQ counter */ -	wait_queue_head_t irq_queues[ PCIDRIVER_INT_MAXSOURCES ];       /* One queue per interrupt source */ -	atomic_t irq_outstanding[ PCIDRIVER_INT_MAXSOURCES ];           /* Outstanding interrupts per queue */ -	volatile unsigned int *bars_kmapped[6];		                /* PCI BARs mmapped in kernel space */ +    wait_queue_head_t irq_queues[ PCIDRIVER_INT_MAXSOURCES ];       /* One queue per interrupt source */ +    atomic_t irq_outstanding[ PCIDRIVER_INT_MAXSOURCES ];           /* Outstanding interrupts per queue */ +    volatile unsigned int *bars_kmapped[6];		                /* PCI BARs mmapped in kernel space */  #endif -	 -	spinlock_t kmemlist_lock;			/* Spinlock to lock kmem list operations */ -	struct list_head kmem_list;			/* List of 'kmem_list_entry's associated with this device */ -	pcidriver_kmem_entry_t *kmem_last_sync;		/* Last accessed kmem entry */ -	atomic_t kmem_count;				/* id for next kmem entry */ - -	int kmem_cur_id;				/* Currently selected kmem buffer, for mmap */ -	 -	spinlock_t umemlist_lock;			/* Spinlock to lock umem list operations */ -	struct list_head umem_list;			/* List of 'umem_list_entry's associated with this device */ -	atomic_t umem_count;				/* id for next umem entry */ - -	int msi_mode;					/* Flag specifying if interrupt have been initialized in MSI mode */ -	atomic_t refs;					/* Reference counter */ + +    spinlock_t kmemlist_lock;			/* Spinlock to lock kmem list operations */ +    struct list_head kmem_list;			/* List of 'kmem_list_entry's associated with this device */ +    pcidriver_kmem_entry_t *kmem_last_sync;		/* Last accessed kmem entry */ +    atomic_t kmem_count;				/* id for next kmem entry */ + +    int kmem_cur_id;				/* Currently selected kmem buffer, for mmap */ + +    spinlock_t umemlist_lock;			/* Spinlock to lock umem list operations */ +    struct list_head umem_list;			/* List of 'umem_list_entry's associated with this device */ +    atomic_t umem_count;				/* id for next umem entry */ + +    int msi_mode;					/* Flag specifying if interrupt have been initialized in MSI mode */ +    atomic_t refs;					/* Reference counter */  } pcidriver_privdata_t; @@ -88,17 +88,17 @@ void pcidriver_put_privdata(pcidriver_privdata_t *privdata);  /* This is to print nice info in the log */  #ifdef DEBUG - #define mod_info( args... ) \ +#define mod_info( args... ) \      do { printk( KERN_INFO "%s - %s : ", MODNAME , __FUNCTION__ );\      printk( args ); } while(0) - #define mod_info_dbg( args... ) \ +#define mod_info_dbg( args... ) \      do { printk( KERN_INFO "%s - %s : ", MODNAME , __FUNCTION__ );\      printk( args ); } while(0)  #else - #define mod_info( args... ) \ +#define mod_info( args... ) \      do { printk( KERN_INFO "%s: ", MODNAME );\      printk( args ); } while(0) - #define mod_info_dbg( args... )  +#define mod_info_dbg( args... )  #endif  #define mod_crit( args... ) \ diff --git a/driver/compat.c b/driver/compat.c index a632781..f28f527 100644 --- a/driver/compat.c +++ b/driver/compat.c @@ -2,25 +2,24 @@  int pcidriver_pcie_get_mps(struct pci_dev *dev)  { -        u16 ctl; +    u16 ctl; -        pcie_capability_read_word(dev, PCI_EXP_DEVCTL, &ctl); +    pcie_capability_read_word(dev, PCI_EXP_DEVCTL, &ctl); -        return 128 << ((ctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5); +    return 128 << ((ctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5);  }  int pcidriver_pcie_set_mps(struct pci_dev *dev, int mps)  { -        u16 v; +    u16 v; -        if (mps < 128 || mps > 4096 || !is_power_of_2(mps)) -                return -EINVAL; +    if (mps < 128 || mps > 4096 || !is_power_of_2(mps)) +        return -EINVAL; -        v = ffs(mps) - 8; -        if (v > dev->pcie_mpss) -                return -EINVAL; -        v <<= 5; +    v = ffs(mps) - 8; +    if (v > dev->pcie_mpss) +        return -EINVAL; +    v <<= 5; -        return pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL, -                                                  PCI_EXP_DEVCTL_PAYLOAD, v); +    return pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_PAYLOAD, v);  } diff --git a/driver/compat.h b/driver/compat.h index 5232a22..a8a2cf0 100644 --- a/driver/compat.h +++ b/driver/compat.h @@ -10,196 +10,72 @@  #ifndef _COMPAT_H  #define _COMPAT_H -/* -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) -# error "Linux 3.0 and latter are supported" -#endif -*/ +#include <linux/version.h> -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) -# define __devinit -# define __devexit -# define __devinitdata +/* Check macros and kernel version first */ +#ifndef KERNEL_VERSION +# error "No KERNEL_VERSION macro! Stopping."  #endif -/* dev_name is the wrapper one needs to use to access what was formerly called - * bus_id in struct device. However, before 2.6.27, direct access was necessary, - * so we provide our own version. */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) -static inline const char *dev_name(struct device *dev) { -	return dev->bus_id; -} +#ifndef LINUX_VERSION_CODE +# error "No LINUX_VERSION_CODE macro! Stopping."  #endif -/* SetPageLocked disappeared in v2.6.27 */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) -	#define compat_lock_page SetPageLocked -	#define compat_unlock_page ClearPageLocked -#else -	/* in v2.6.28, __set_page_locked and __clear_page_locked was introduced */ -	#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) -		#define compat_lock_page __set_page_locked -		#define compat_unlock_page __clear_page_locked -	#else -		/* However, in v2.6.27 itself, neither of them is there, so -		 * we need to use our own function fiddling with bits inside -		 * the page struct :-\ */ -		static inline void compat_lock_page(struct page *page) { -			__set_bit(PG_locked, &page->flags); -		} - -		static inline void compat_unlock_page(struct page *page) { -			__clear_bit(PG_locked, &page->flags); -		} -	#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) +# error "Linux 3.2 and latter are supported"  #endif -/* Before 2.6.13, simple_class was the standard interface. Nowadays, it's just called class */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) - -	#define class_compat class_simple - -	/* These functions are redirected to their old corresponding functions */ -	#define class_create(module, name) class_simple_create(module, name) -	#define class_destroy(type) class_simple_destroy(type) -	#define class_device_destroy(unused, devno) class_simple_device_remove(devno) -	#define class_device_create(type, unused, devno, devpointer, nameformat, minor, unused) \ -		class_simple_device_add(type, devno, devpointer, nameformat, minor) -	#define class_set_devdata(classdev, privdata) classdev->class_data = privdata -	#define DEVICE_ATTR_COMPAT -	#define sysfs_attr_def_name(name) class_device_attr_##name -	#define sysfs_attr_def_pointer privdata->class_dev -	#define SYSFS_GET_FUNCTION(name) ssize_t name(struct class_device *cls, char *buf) -	#define SYSFS_SET_FUNCTION(name) ssize_t name(struct class_device *cls, const char *buf, size_t count) -	#define SYSFS_GET_PRIVDATA (pcidriver_privdata_t*)cls->class_data - -#else - -/* In 2.6.26, device.h was changed quite significantly. Luckily, it only affected -   type/function names, for the most part. */ -//#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) -	#define class_device_attribute device_attribute -	#define CLASS_DEVICE_ATTR DEVICE_ATTR -	#define class_device device -	#define class_data dev -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) -	#define class_device_create(type, parent, devno, devpointer, nameformat, minor, privdata) \ -		device_create(type, parent, devno, privdata, nameformat, minor) -#else -	#define class_device_create(type, parent, devno, devpointer, nameformat, minor, unused) \ -		device_create(type, parent, devno, nameformat, minor) +/* VM_RESERVED is removed in 3.7-rc1 */ +#ifndef VM_RESERVED +# define  VM_RESERVED   (VM_DONTEXPAND | VM_DONTDUMP)  #endif -	#define class_device_create_file device_create_file -	#define class_device_remove_file device_remove_file -	#define class_device_destroy device_destroy -	#define DEVICE_ATTR_COMPAT struct device_attribute *attr, -	#define class_set_devdata dev_set_drvdata - -	#define sysfs_attr_def_name(name) dev_attr_##name -	#define sysfs_attr_def_pointer privdata->class_dev -	#define SYSFS_GET_FUNCTION(name) ssize_t name(struct device *dev, struct device_attribute *attr, char *buf) -	#define SYSFS_SET_FUNCTION(name) ssize_t name(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -	#define SYSFS_GET_PRIVDATA dev_get_drvdata(dev) - -//#endif -#define class_compat class +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) +# define __devinit +# define __devexit +# define __devinitdata  #endif -/* The arguments of IRQ handlers have been changed in 2.6.19. It's very likely that -   int irq will disappear somewhen in the future (current is 2.6.29), too. */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19) -	#define IRQ_HANDLER_FUNC(name) irqreturn_t name(int irq, void *dev_id) -#else -	#define IRQ_HANDLER_FUNC(name) irqreturn_t name(int irq, void *dev_id, struct pt_regs *regs) -#endif +#define compat_lock_page __set_page_locked +#define compat_unlock_page __clear_page_locked -/* atomic_inc_return appeared in 2.6.9, at least in CERN scientific linux, provide -   compatibility wrapper for older kernels */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) -static int atomic_inc_return(atomic_t *variable) { -	atomic_inc(variable); -	return atomic_read(variable); -} -#endif -/* sg_set_page is available starting at 2.6.24 */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) +#define class_device_attribute device_attribute +#define CLASS_DEVICE_ATTR DEVICE_ATTR +#define class_device device +#define class_data dev +#define class_device_create(type, parent, devno, devpointer, nameformat, minor, privdata) \ +		device_create(type, parent, devno, privdata, nameformat, minor) +#define class_device_create_file device_create_file +#define class_device_remove_file device_remove_file +#define class_device_destroy device_destroy +#define DEVICE_ATTR_COMPAT struct device_attribute *attr, +#define class_set_devdata dev_set_drvdata + +#define sysfs_attr_def_name(name) dev_attr_##name +#define sysfs_attr_def_pointer privdata->class_dev +#define SYSFS_GET_FUNCTION(name) ssize_t name(struct device *dev, struct device_attribute *attr, char *buf) +#define SYSFS_SET_FUNCTION(name) ssize_t name(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +#define SYSFS_GET_PRIVDATA dev_get_drvdata(dev) -#define sg_set_page(sg, set_page, set_length, set_offset) do { \ -	(sg)->page = set_page; \ -	(sg)->length = set_length; \ -	(sg)->offset = set_offset; \ -} while (0) +#define class_compat class -#endif -/* Before 2.6.20, disable was not an atomic counter, so this check was needed */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -#define pci_disable_device(pdev) do { \ -	if (pdev->is_enabled) \ -		pci_disable_device(pdev); \ -} while (0) -#endif +#define IRQ_HANDLER_FUNC(name) irqreturn_t name(int irq, void *dev_id) -/* Before 2.6.24, scatter/gather lists did not need to be initialized */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) -	#define sg_init_table(sg, nr_pages) -#endif +#define request_irq(irq, irq_handler, modname, privdata) request_irq(irq, irq_handler, IRQF_SHARED, modname, privdata) -/* SA_SHIRQ was renamed to IRQF_SHARED in 2.6.24 */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) -	#define request_irq(irq, irq_handler, modname, privdata) request_irq(irq, irq_handler, IRQF_SHARED, modname, privdata) -#else -	#define request_irq(irq, irq_handler, modname, privdata) request_irq(irq, irq_handler, SA_SHIRQ, modname, privdata) -#endif -/* In 2.6.13, io_remap_page_range was removed in favor for io_remap_pfn_range which works on -   more platforms and allows more memory space */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)  #define io_remap_pfn_range_compat(vmap, vm_start, bar_addr, bar_length, vm_page_prot) \  	io_remap_pfn_range(vmap, vm_start, (bar_addr >> PAGE_SHIFT), bar_length, vm_page_prot) -#else -#define io_remap_pfn_range_compat(vmap, vm_start, bar_addr, bar_length, vm_page_prot) \ -	io_remap_page_range(vmap, vm_start, bar_addr, bar_length, vm_page_prot) -#endif -/* In 2.6.10, remap_pfn_range was introduced, see io_remap_pfn_range_compat */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)  #define remap_pfn_range_compat(vmap, vm_start, bar_addr, bar_length, vm_page_prot) \  	remap_pfn_range(vmap, vm_start, (bar_addr >> PAGE_SHIFT), bar_length, vm_page_prot)  #define remap_pfn_range_cpua_compat(vmap, vm_start, cpua, size, vm_page_prot) \  	remap_pfn_range(vmap, vm_start, page_to_pfn(virt_to_page((void*)cpua)), size, vm_page_prot) -#else -#define remap_pfn_range_compat(vmap, vm_start, bar_addr, bar_length, vm_page_prot) \ -	remap_page_range(vmap, vm_start, bar_addr, bar_length, vm_page_prot) - -#define remap_pfn_range_cpua_compat(vmap, vm_start, cpua, size, vm_page_prot) \ -	remap_page_range(vmap, vm_start, virt_to_phys((void*)cpua), size, vm_page_prot) -#endif - -/** - * Go over the pages of the kmem buffer, and mark them as reserved. - * This is needed, otherwise mmaping the kernel memory to user space - * will fail silently (mmaping /dev/null) when using remap_xx_range. - */ -static inline void set_pages_reserved_compat(unsigned long cpua, unsigned long size) -{ -	/* Starting in 2.6.15, the PG_RESERVED bit was removed. -	   See also http://lwn.net/Articles/161204/ */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) -	struct page *page, *last_page; - -	page = virt_to_page(cpua); -	last_page = virt_to_page(cpua + size - 1); - -	for (; page <= last_page; page++) -               SetPageReserved(page); -#endif -}  int pcidriver_pcie_get_mps(struct pci_dev *dev);  int pcidriver_pcie_set_mps(struct pci_dev *dev, int mps); diff --git a/driver/int.c b/driver/int.c index 5dbcb7f..f78c6ec 100644 --- a/driver/int.c +++ b/driver/int.c @@ -9,7 +9,7 @@  /*   * Change History: - *  + *   * $Log: not supported by cvs2svn $   * Revision 1.7  2008-01-11 10:18:28  marcus   * Modified interrupt mechanism. Added atomic functions and queues, to address race conditions. Removed unused interrupt code. @@ -60,7 +60,7 @@  /*   * The ID between IRQ_SOURCE in irq_outstanding and the actual source is arbitrary. - * Therefore, be careful when communicating with multiple implementations.  + * Therefore, be careful when communicating with multiple implementations.   */  /* IRQ_SOURCES */ @@ -92,90 +92,90 @@   */  int pcidriver_probe_irq(pcidriver_privdata_t *privdata)  { -	unsigned char int_pin, int_line; -	unsigned long bar_addr, bar_len, bar_flags; -	int i; -	int err; - -	for (i = 0; i < 6; i++) -		privdata->bars_kmapped[i] = NULL; - -	for (i = 0; i < 6; i++) { -		bar_addr = pci_resource_start(privdata->pdev, i); -		bar_len = pci_resource_len(privdata->pdev, i); -		bar_flags = pci_resource_flags(privdata->pdev, i); - -		/* check if it is a valid BAR, skip if not */ -		if ((bar_addr == 0) || (bar_len == 0)) -			continue; - -		/* Skip IO regions (map only mem regions) */ -		if (bar_flags & IORESOURCE_IO) -			continue; - -		/* Check if the region is available */ -		if ((err = pci_request_region(privdata->pdev, i, NULL)) != 0) { -			mod_info( "Failed to request BAR memory region.\n" ); -			return err; -		} - -		/* Map it into kernel space. */ -		/* For x86 this is just a dereference of the pointer, but that is -		 * not portable. So we need to do the portable way. Thanks Joern! -		 */ - -		/* respect the cacheable-bility of the region */ -		if (bar_flags & IORESOURCE_PREFETCH) -			privdata->bars_kmapped[i] = ioremap(bar_addr, bar_len); -		else -			privdata->bars_kmapped[i] = ioremap_nocache(bar_addr, bar_len); - -		/* check for error */ -		if (privdata->bars_kmapped[i] == NULL) { -			mod_info( "Failed to remap BAR%d into kernel space.\n", i ); -			return -EIO; -		} -	} - -	/* Initialize the interrupt handler for this device */ -	/* Initialize the wait queues */ -	for (i = 0; i < PCIDRIVER_INT_MAXSOURCES; i++) { -		init_waitqueue_head(&(privdata->irq_queues[i])); -		atomic_set(&(privdata->irq_outstanding[i]), 0); -	} - -	/* Initialize the irq config */ -	if ((err = pci_read_config_byte(privdata->pdev, PCI_INTERRUPT_PIN, &int_pin)) != 0) { -		/* continue without interrupts */ -		int_pin = 0; -		mod_info("Error getting the interrupt pin. Disabling interrupts for this device\n"); -	} - -	/* Disable interrupts and activate them if everything can be set up properly */ -	privdata->irq_enabled = 0; - -	if (int_pin == 0) -		return 0; - -	if ((err = pci_read_config_byte(privdata->pdev, PCI_INTERRUPT_LINE, &int_line)) != 0) { -		mod_info("Error getting the interrupt line. Disabling interrupts for this device\n"); -		return 0; -	} - -	/* Enable interrupts using MSI mode */ -	if (!pci_enable_msi(privdata->pdev))  -		privdata->msi_mode = 1; -	 -	/* register interrupt handler */ -	if ((err = request_irq(privdata->pdev->irq, pcidriver_irq_handler, MODNAME, privdata)) != 0) { -		mod_info("Error registering the interrupt handler. Disabling interrupts for this device\n"); -		return 0; -	} - -	privdata->irq_enabled = 1; -	mod_info("Registered Interrupt Handler at pin %i, line %i, IRQ %i\n", int_pin, int_line, privdata->pdev->irq ); - -	return 0; +    unsigned char int_pin, int_line; +    unsigned long bar_addr, bar_len, bar_flags; +    int i; +    int err; + +    for (i = 0; i < 6; i++) +        privdata->bars_kmapped[i] = NULL; + +    for (i = 0; i < 6; i++) { +        bar_addr = pci_resource_start(privdata->pdev, i); +        bar_len = pci_resource_len(privdata->pdev, i); +        bar_flags = pci_resource_flags(privdata->pdev, i); + +        /* check if it is a valid BAR, skip if not */ +        if ((bar_addr == 0) || (bar_len == 0)) +            continue; + +        /* Skip IO regions (map only mem regions) */ +        if (bar_flags & IORESOURCE_IO) +            continue; + +        /* Check if the region is available */ +        if ((err = pci_request_region(privdata->pdev, i, NULL)) != 0) { +            mod_info( "Failed to request BAR memory region.\n" ); +            return err; +        } + +        /* Map it into kernel space. */ +        /* For x86 this is just a dereference of the pointer, but that is +         * not portable. So we need to do the portable way. Thanks Joern! +         */ + +        /* respect the cacheable-bility of the region */ +        if (bar_flags & IORESOURCE_PREFETCH) +            privdata->bars_kmapped[i] = ioremap(bar_addr, bar_len); +        else +            privdata->bars_kmapped[i] = ioremap_nocache(bar_addr, bar_len); + +        /* check for error */ +        if (privdata->bars_kmapped[i] == NULL) { +            mod_info( "Failed to remap BAR%d into kernel space.\n", i ); +            return -EIO; +        } +    } + +    /* Initialize the interrupt handler for this device */ +    /* Initialize the wait queues */ +    for (i = 0; i < PCIDRIVER_INT_MAXSOURCES; i++) { +        init_waitqueue_head(&(privdata->irq_queues[i])); +        atomic_set(&(privdata->irq_outstanding[i]), 0); +    } + +    /* Initialize the irq config */ +    if ((err = pci_read_config_byte(privdata->pdev, PCI_INTERRUPT_PIN, &int_pin)) != 0) { +        /* continue without interrupts */ +        int_pin = 0; +        mod_info("Error getting the interrupt pin. Disabling interrupts for this device\n"); +    } + +    /* Disable interrupts and activate them if everything can be set up properly */ +    privdata->irq_enabled = 0; + +    if (int_pin == 0) +        return 0; + +    if ((err = pci_read_config_byte(privdata->pdev, PCI_INTERRUPT_LINE, &int_line)) != 0) { +        mod_info("Error getting the interrupt line. Disabling interrupts for this device\n"); +        return 0; +    } + +    /* Enable interrupts using MSI mode */ +    if (!pci_enable_msi(privdata->pdev)) +        privdata->msi_mode = 1; + +    /* register interrupt handler */ +    if ((err = request_irq(privdata->pdev->irq, pcidriver_irq_handler, MODNAME, privdata)) != 0) { +        mod_info("Error registering the interrupt handler. Disabling interrupts for this device\n"); +        return 0; +    } + +    privdata->irq_enabled = 1; +    mod_info("Registered Interrupt Handler at pin %i, line %i, IRQ %i\n", int_pin, int_line, privdata->pdev->irq ); + +    return 0;  }  /** @@ -185,16 +185,16 @@ int pcidriver_probe_irq(pcidriver_privdata_t *privdata)   */  void pcidriver_remove_irq(pcidriver_privdata_t *privdata)  { -	/* Release the IRQ handler */ -	if (privdata->irq_enabled != 0) -		free_irq(privdata->pdev->irq, privdata); -	 -	if (privdata->msi_mode) { -		pci_disable_msi(privdata->pdev); -		privdata->msi_mode = 0; -	} - -	pcidriver_irq_unmap_bars(privdata); +    /* Release the IRQ handler */ +    if (privdata->irq_enabled != 0) +        free_irq(privdata->pdev->irq, privdata); + +    if (privdata->msi_mode) { +        pci_disable_msi(privdata->pdev); +        privdata->msi_mode = 0; +    } + +    pcidriver_irq_unmap_bars(privdata);  }  /** @@ -204,15 +204,15 @@ void pcidriver_remove_irq(pcidriver_privdata_t *privdata)   */  void pcidriver_irq_unmap_bars(pcidriver_privdata_t *privdata)  { -	int i; +    int i; -	for (i = 0; i < 6; i++) { -		if (privdata->bars_kmapped[i] == NULL) -			continue; +    for (i = 0; i < 6; i++) { +        if (privdata->bars_kmapped[i] == NULL) +            continue; -		iounmap((void*)privdata->bars_kmapped[i]); -		pci_release_region(privdata->pdev, i); -	} +        iounmap((void*)privdata->bars_kmapped[i]); +        pci_release_region(privdata->pdev, i); +    }  }  /** @@ -227,15 +227,15 @@ void pcidriver_irq_unmap_bars(pcidriver_privdata_t *privdata)   */  static bool pcidriver_irq_acknowledge(pcidriver_privdata_t *privdata)  { -	int channel = 0; +    int channel = 0;  //	volatile unsigned int *bar;  //	bar = privdata->bars_kmapped[0];  //	mod_info_dbg("interrupt registers. ISR: %x, IER: %x\n", bar[ABB_INT_STAT], bar[ABB_INT_ENABLE]); -	atomic_inc(&(privdata->irq_outstanding[channel])); -	wake_up_interruptible(&(privdata->irq_queues[channel])); -	 -	return true; +    atomic_inc(&(privdata->irq_outstanding[channel])); +    wake_up_interruptible(&(privdata->irq_queues[channel])); + +    return true;  }  /** @@ -248,11 +248,11 @@ static bool pcidriver_irq_acknowledge(pcidriver_privdata_t *privdata)   */  IRQ_HANDLER_FUNC(pcidriver_irq_handler)  { -	pcidriver_privdata_t *privdata = (pcidriver_privdata_t *)dev_id; +    pcidriver_privdata_t *privdata = (pcidriver_privdata_t *)dev_id; -	if (!pcidriver_irq_acknowledge(privdata)) -		return IRQ_NONE; +    if (!pcidriver_irq_acknowledge(privdata)) +        return IRQ_NONE; -	privdata->irq_count++; -	return IRQ_HANDLED; +    privdata->irq_count++; +    return IRQ_HANDLED;  } diff --git a/driver/ioctl.c b/driver/ioctl.c index f957561..4fef5f9 100644 --- a/driver/ioctl.c +++ b/driver/ioctl.c @@ -60,13 +60,13 @@   */  static int ioctl_mmap_mode(pcidriver_privdata_t *privdata, unsigned long arg)  { -	if ((arg != PCIDRIVER_MMAP_PCI) && (arg != PCIDRIVER_MMAP_KMEM)) -		return -EINVAL; +    if ((arg != PCIDRIVER_MMAP_PCI) && (arg != PCIDRIVER_MMAP_KMEM)) +        return -EINVAL; -	/* change the mode */ -	privdata->mmap_mode = arg; +    /* change the mode */ +    privdata->mmap_mode = arg; -	return 0; +    return 0;  }  /** @@ -76,14 +76,14 @@ static int ioctl_mmap_mode(pcidriver_privdata_t *privdata, unsigned long arg)   */  static int ioctl_mmap_area(pcidriver_privdata_t *privdata, unsigned long arg)  { -	/* validate input */ -	if ((arg < PCIDRIVER_BAR0) || (arg > PCIDRIVER_BAR5)) -		return -EINVAL; +    /* validate input */ +    if ((arg < PCIDRIVER_BAR0) || (arg > PCIDRIVER_BAR5)) +        return -EINVAL; -	/* change the PCI area to mmap */ -	privdata->mmap_area = arg; +    /* change the PCI area to mmap */ +    privdata->mmap_area = arg; -	return 0; +    return 0;  }  /** @@ -97,45 +97,45 @@ static int ioctl_mmap_area(pcidriver_privdata_t *privdata, unsigned long arg)  static int ioctl_pci_config_read_write(pcidriver_privdata_t *privdata, unsigned int cmd, unsigned long arg)  {  #ifdef PCIDRIVER_DUMMY_DEVICE -	return -ENXIO; +    return -ENXIO;  #else /* PCIDRIVER_DUMMY_DEVICE */ -	int ret; -	READ_FROM_USER(pci_cfg_cmd, pci_cmd); - -	if (cmd == PCIDRIVER_IOC_PCI_CFG_RD) { -		switch (pci_cmd.size) { -			case PCIDRIVER_PCI_CFG_SZ_BYTE: -				ret = pci_read_config_byte( privdata->pdev, pci_cmd.addr, &(pci_cmd.val.byte) ); -				break; -			case PCIDRIVER_PCI_CFG_SZ_WORD: -				ret = pci_read_config_word( privdata->pdev, pci_cmd.addr, &(pci_cmd.val.word) ); -				break; -			case PCIDRIVER_PCI_CFG_SZ_DWORD: -				ret = pci_read_config_dword( privdata->pdev, pci_cmd.addr, &(pci_cmd.val.dword) ); -				break; -			default: -				return -EINVAL;		/* Wrong size setting */ -		} -	} else { -		switch (pci_cmd.size) { -			case PCIDRIVER_PCI_CFG_SZ_BYTE: -				ret = pci_write_config_byte( privdata->pdev, pci_cmd.addr, pci_cmd.val.byte ); -				break; -			case PCIDRIVER_PCI_CFG_SZ_WORD: -				ret = pci_write_config_word( privdata->pdev, pci_cmd.addr, pci_cmd.val.word ); -				break; -			case PCIDRIVER_PCI_CFG_SZ_DWORD: -				ret = pci_write_config_dword( privdata->pdev, pci_cmd.addr, pci_cmd.val.dword ); -				break; -			default: -				return -EINVAL;		/* Wrong size setting */ -				break; -		} -	} - -	WRITE_TO_USER(pci_cfg_cmd, pci_cmd); - -	return 0; +    int ret; +    READ_FROM_USER(pci_cfg_cmd, pci_cmd); + +    if (cmd == PCIDRIVER_IOC_PCI_CFG_RD) { +        switch (pci_cmd.size) { +        case PCIDRIVER_PCI_CFG_SZ_BYTE: +            ret = pci_read_config_byte( privdata->pdev, pci_cmd.addr, &(pci_cmd.val.byte) ); +            break; +        case PCIDRIVER_PCI_CFG_SZ_WORD: +            ret = pci_read_config_word( privdata->pdev, pci_cmd.addr, &(pci_cmd.val.word) ); +            break; +        case PCIDRIVER_PCI_CFG_SZ_DWORD: +            ret = pci_read_config_dword( privdata->pdev, pci_cmd.addr, &(pci_cmd.val.dword) ); +            break; +        default: +            return -EINVAL;		/* Wrong size setting */ +        } +    } else { +        switch (pci_cmd.size) { +        case PCIDRIVER_PCI_CFG_SZ_BYTE: +            ret = pci_write_config_byte( privdata->pdev, pci_cmd.addr, pci_cmd.val.byte ); +            break; +        case PCIDRIVER_PCI_CFG_SZ_WORD: +            ret = pci_write_config_word( privdata->pdev, pci_cmd.addr, pci_cmd.val.word ); +            break; +        case PCIDRIVER_PCI_CFG_SZ_DWORD: +            ret = pci_write_config_dword( privdata->pdev, pci_cmd.addr, pci_cmd.val.dword ); +            break; +        default: +            return -EINVAL;		/* Wrong size setting */ +            break; +        } +    } + +    WRITE_TO_USER(pci_cfg_cmd, pci_cmd); + +    return 0;  #endif /* PCIDRIVER_DUMMY_DEVICE */  } @@ -148,40 +148,40 @@ static int ioctl_pci_config_read_write(pcidriver_privdata_t *privdata, unsigned   */  static int ioctl_pci_info(pcidriver_privdata_t *privdata, unsigned long arg)  { -	int ret; +    int ret;  #ifdef PCIDRIVER_DUMMY_DEVICE -	READ_FROM_USER(pcilib_board_info_t, pci_info); -	memset(&pci_info, 0, sizeof(pci_info)); -	WRITE_TO_USER(pcilib_board_info_t, pci_info); +    READ_FROM_USER(pcilib_board_info_t, pci_info); +    memset(&pci_info, 0, sizeof(pci_info)); +    WRITE_TO_USER(pcilib_board_info_t, pci_info);  #else /* PCIDRIVER_DUMMY_DEVICE */ -	int bar; +    int bar; -	READ_FROM_USER(pcilib_board_info_t, pci_info); +    READ_FROM_USER(pcilib_board_info_t, pci_info); -	pci_info.vendor_id = privdata->pdev->vendor; -	pci_info.device_id = privdata->pdev->device; -	pci_info.bus = privdata->pdev->bus->number; -	pci_info.slot = PCI_SLOT(privdata->pdev->devfn); -	pci_info.devfn = privdata->pdev->devfn; -	pci_info.func = PCI_FUNC(privdata->pdev->devfn); +    pci_info.vendor_id = privdata->pdev->vendor; +    pci_info.device_id = privdata->pdev->device; +    pci_info.bus = privdata->pdev->bus->number; +    pci_info.slot = PCI_SLOT(privdata->pdev->devfn); +    pci_info.devfn = privdata->pdev->devfn; +    pci_info.func = PCI_FUNC(privdata->pdev->devfn); -	if ((ret = pci_read_config_byte(privdata->pdev, PCI_INTERRUPT_PIN, &(pci_info.interrupt_pin))) != 0) -		return ret; +    if ((ret = pci_read_config_byte(privdata->pdev, PCI_INTERRUPT_PIN, &(pci_info.interrupt_pin))) != 0) +        return ret; -	if ((ret = pci_read_config_byte(privdata->pdev, PCI_INTERRUPT_LINE, &(pci_info.interrupt_line))) != 0) -		return ret; +    if ((ret = pci_read_config_byte(privdata->pdev, PCI_INTERRUPT_LINE, &(pci_info.interrupt_line))) != 0) +        return ret; -	for (bar = 0; bar < 6; bar++) { -		pci_info.bar_start[bar] = pci_resource_start(privdata->pdev, bar); -		pci_info.bar_length[bar] = pci_resource_len(privdata->pdev, bar); -		pci_info.bar_flags[bar] = pci_resource_flags(privdata->pdev, bar); -	} +    for (bar = 0; bar < 6; bar++) { +        pci_info.bar_start[bar] = pci_resource_start(privdata->pdev, bar); +        pci_info.bar_length[bar] = pci_resource_len(privdata->pdev, bar); +        pci_info.bar_flags[bar] = pci_resource_flags(privdata->pdev, bar); +    } -	WRITE_TO_USER(pcilib_board_info_t, pci_info); +    WRITE_TO_USER(pcilib_board_info_t, pci_info);  #endif /* PCIDRIVER_DUMMY_DEVICE */ -	return 0; +    return 0;  }  /** @@ -193,13 +193,13 @@ static int ioctl_pci_info(pcidriver_privdata_t *privdata, unsigned long arg)   */  static int ioctl_kmem_alloc(pcidriver_privdata_t *privdata, unsigned long arg)  { -	int err, ret; +    int err, ret; -	READ_FROM_USER(kmem_handle_t, khandle); -	err = pcidriver_kmem_alloc(privdata, &khandle); -	WRITE_TO_USER(kmem_handle_t, khandle); +    READ_FROM_USER(kmem_handle_t, khandle); +    err = pcidriver_kmem_alloc(privdata, &khandle); +    WRITE_TO_USER(kmem_handle_t, khandle); -	return err; +    return err;  }  /** @@ -211,13 +211,13 @@ static int ioctl_kmem_alloc(pcidriver_privdata_t *privdata, unsigned long arg)   */  static int ioctl_kmem_free(pcidriver_privdata_t *privdata, unsigned long arg)  { -	int ret; -	READ_FROM_USER(kmem_handle_t, khandle); +    int ret; +    READ_FROM_USER(kmem_handle_t, khandle); -	if ((ret = pcidriver_kmem_free(privdata, &khandle)) != 0) -		return ret; +    if ((ret = pcidriver_kmem_free(privdata, &khandle)) != 0) +        return ret; -	return 0; +    return 0;  }  /** @@ -229,15 +229,15 @@ static int ioctl_kmem_free(pcidriver_privdata_t *privdata, unsigned long arg)   */  static int ioctl_kmem_sync(pcidriver_privdata_t *privdata, unsigned long arg)  { -	int ret; -	READ_FROM_USER(kmem_sync_t, ksync); - -	if ((ret =  pcidriver_kmem_sync(privdata, &ksync)) != 0) -	    return ret; -	 -	WRITE_TO_USER(kmem_sync_t, ksync); -	 -	return 0; +    int ret; +    READ_FROM_USER(kmem_sync_t, ksync); + +    if ((ret =  pcidriver_kmem_sync(privdata, &ksync)) != 0) +        return ret; + +    WRITE_TO_USER(kmem_sync_t, ksync); + +    return 0;  }  /* @@ -249,15 +249,15 @@ static int ioctl_kmem_sync(pcidriver_privdata_t *privdata, unsigned long arg)   */  static int ioctl_umem_sgmap(pcidriver_privdata_t *privdata, unsigned long arg)  { -	int ret; -	READ_FROM_USER(umem_handle_t, uhandle); +    int ret; +    READ_FROM_USER(umem_handle_t, uhandle); -	if ((ret = pcidriver_umem_sgmap(privdata, &uhandle)) != 0) -		return ret; +    if ((ret = pcidriver_umem_sgmap(privdata, &uhandle)) != 0) +        return ret; -	WRITE_TO_USER(umem_handle_t, uhandle); +    WRITE_TO_USER(umem_handle_t, uhandle); -	return 0; +    return 0;  }  /** @@ -269,19 +269,19 @@ static int ioctl_umem_sgmap(pcidriver_privdata_t *privdata, unsigned long arg)   */  static int ioctl_umem_sgunmap(pcidriver_privdata_t *privdata, unsigned long arg)  { -	int ret; -	pcidriver_umem_entry_t *umem_entry; -	READ_FROM_USER(umem_handle_t, uhandle); +    int ret; +    pcidriver_umem_entry_t *umem_entry; +    READ_FROM_USER(umem_handle_t, uhandle); -	/* Find the associated umem_entry for this buffer, -	 * return -EINVAL if the specified handle id is invalid */ -	if ((umem_entry = pcidriver_umem_find_entry_id(privdata, uhandle.handle_id)) == NULL) -		return -EINVAL; +    /* Find the associated umem_entry for this buffer, +     * return -EINVAL if the specified handle id is invalid */ +    if ((umem_entry = pcidriver_umem_find_entry_id(privdata, uhandle.handle_id)) == NULL) +        return -EINVAL; -	if ((ret = pcidriver_umem_sgunmap(privdata, umem_entry)) != 0) -		return ret; +    if ((ret = pcidriver_umem_sgunmap(privdata, umem_entry)) != 0) +        return ret; -	return 0; +    return 0;  }  /** @@ -293,35 +293,35 @@ static int ioctl_umem_sgunmap(pcidriver_privdata_t *privdata, unsigned long arg)   */  static int ioctl_umem_sgget(pcidriver_privdata_t *privdata, unsigned long arg)  { -	int ret; -	READ_FROM_USER(umem_sglist_t, usglist); +    int ret; +    READ_FROM_USER(umem_sglist_t, usglist); -	/* The umem_sglist_t has a pointer to the scatter/gather list itself which -	 * needs to be copied separately. The number of elements is stored in ->nents. -	 * As the list can get very big, we need to use vmalloc. */ -	if ((usglist.sg = vmalloc(usglist.nents * sizeof(umem_sgentry_t))) == NULL) -		return -ENOMEM; +    /* The umem_sglist_t has a pointer to the scatter/gather list itself which +     * needs to be copied separately. The number of elements is stored in ->nents. +     * As the list can get very big, we need to use vmalloc. */ +    if ((usglist.sg = vmalloc(usglist.nents * sizeof(umem_sgentry_t))) == NULL) +        return -ENOMEM; -	/* copy array to kernel structure */ -	ret = copy_from_user(usglist.sg, ((umem_sglist_t *)arg)->sg, (usglist.nents)*sizeof(umem_sgentry_t)); -	if (ret) return -EFAULT; +    /* copy array to kernel structure */ +    ret = copy_from_user(usglist.sg, ((umem_sglist_t *)arg)->sg, (usglist.nents)*sizeof(umem_sgentry_t)); +    if (ret) return -EFAULT; -	if ((ret = pcidriver_umem_sgget(privdata, &usglist)) != 0) -		return ret; +    if ((ret = pcidriver_umem_sgget(privdata, &usglist)) != 0) +        return ret; -	/* write data to user space */ -	ret = copy_to_user(((umem_sglist_t *)arg)->sg, usglist.sg, (usglist.nents)*sizeof(umem_sgentry_t)); -	if (ret) return -EFAULT; +    /* write data to user space */ +    ret = copy_to_user(((umem_sglist_t *)arg)->sg, usglist.sg, (usglist.nents)*sizeof(umem_sgentry_t)); +    if (ret) return -EFAULT; -	/* free array memory */ -	vfree(usglist.sg); +    /* free array memory */ +    vfree(usglist.sg); -	/* restore sg pointer to vma address in user space before copying */ -	usglist.sg = ((umem_sglist_t *)arg)->sg; +    /* restore sg pointer to vma address in user space before copying */ +    usglist.sg = ((umem_sglist_t *)arg)->sg; -	WRITE_TO_USER(umem_sglist_t, usglist); +    WRITE_TO_USER(umem_sglist_t, usglist); -	return 0; +    return 0;  }  /** @@ -333,10 +333,10 @@ static int ioctl_umem_sgget(pcidriver_privdata_t *privdata, unsigned long arg)   */  static int ioctl_umem_sync(pcidriver_privdata_t *privdata, unsigned long arg)  { -	int ret; -	READ_FROM_USER(umem_handle_t, uhandle); +    int ret; +    READ_FROM_USER(umem_handle_t, uhandle); -	return pcidriver_umem_sync( privdata, &uhandle ); +    return pcidriver_umem_sync( privdata, &uhandle );  }  /** @@ -349,47 +349,47 @@ static int ioctl_umem_sync(pcidriver_privdata_t *privdata, unsigned long arg)  static int ioctl_wait_interrupt(pcidriver_privdata_t *privdata, unsigned long arg)  {  #ifdef ENABLE_IRQ -	int ret; -	unsigned long timeout; -	unsigned int irq_source; -	unsigned long temp = 0; +    int ret; +    unsigned long timeout; +    unsigned int irq_source; +    unsigned long temp = 0; -	READ_FROM_USER(interrupt_wait_t, irq_handle); +    READ_FROM_USER(interrupt_wait_t, irq_handle); -	irq_source = irq_handle.source; +    irq_source = irq_handle.source; -	if (irq_source >= PCIDRIVER_INT_MAXSOURCES) -		return -EFAULT;						/* User tried to overrun the IRQ_SOURCES array */ +    if (irq_source >= PCIDRIVER_INT_MAXSOURCES) +        return -EFAULT;						/* User tried to overrun the IRQ_SOURCES array */ -	timeout = jiffies + (irq_handle.timeout * HZ / 1000000); +    timeout = jiffies + (irq_handle.timeout * HZ / 1000000); -	/* Thanks to Joern for the correction and tips! */ -	/* done this way to avoid wrong behaviour (endless loop) of the compiler in AMD platforms */ -	do { -		/* We wait here with an interruptible timeout. This will be interrupted +    /* Thanks to Joern for the correction and tips! */ +    /* done this way to avoid wrong behaviour (endless loop) of the compiler in AMD platforms */ +    do { +        /* We wait here with an interruptible timeout. This will be interrupted                   * by int.c:check_acknowledge_channel() as soon as in interrupt for                   * the specified source arrives. */ -		wait_event_interruptible_timeout( (privdata->irq_queues[irq_source]), (atomic_read(&(privdata->irq_outstanding[irq_source])) > 0), (10*HZ/1000) ); - -		if (atomic_add_negative( -1, &(privdata->irq_outstanding[irq_source])) ) -			atomic_inc( &(privdata->irq_outstanding[irq_source]) ); -		else -			temp = 1; -	} while ((!temp)&&(jiffies < timeout)); -	 -	if ((temp)&&(irq_handle.count)) { -	    while (!atomic_add_negative( -1, &(privdata->irq_outstanding[irq_source]))) temp++; -	    atomic_inc( &(privdata->irq_outstanding[irq_source]) ); -	} -	 -	irq_handle.count = temp; - -	WRITE_TO_USER(interrupt_wait_t, irq_handle); - -	return 0; +        wait_event_interruptible_timeout( (privdata->irq_queues[irq_source]), (atomic_read(&(privdata->irq_outstanding[irq_source])) > 0), (10*HZ/1000) ); + +        if (atomic_add_negative( -1, &(privdata->irq_outstanding[irq_source])) ) +            atomic_inc( &(privdata->irq_outstanding[irq_source]) ); +        else +            temp = 1; +    } while ((!temp)&&(jiffies < timeout)); + +    if ((temp)&&(irq_handle.count)) { +        while (!atomic_add_negative( -1, &(privdata->irq_outstanding[irq_source]))) temp++; +        atomic_inc( &(privdata->irq_outstanding[irq_source]) ); +    } + +    irq_handle.count = temp; + +    WRITE_TO_USER(interrupt_wait_t, irq_handle); + +    return 0;  #else -	mod_info("Asked to wait for interrupt but interrupts are not enabled in the driver\n"); -	return -EFAULT; +    mod_info("Asked to wait for interrupt but interrupts are not enabled in the driver\n"); +    return -EFAULT;  #endif  } @@ -404,18 +404,18 @@ static int ioctl_wait_interrupt(pcidriver_privdata_t *privdata, unsigned long ar  static int ioctl_clear_ioq(pcidriver_privdata_t *privdata, unsigned long arg)  {  #ifdef ENABLE_IRQ -	unsigned int irq_source; +    unsigned int irq_source; -	if (arg >= PCIDRIVER_INT_MAXSOURCES) -		return -EFAULT; +    if (arg >= PCIDRIVER_INT_MAXSOURCES) +        return -EFAULT; -	irq_source = arg; -	atomic_set(&(privdata->irq_outstanding[irq_source]), 0); +    irq_source = arg; +    atomic_set(&(privdata->irq_outstanding[irq_source]), 0); -	return 0; +    return 0;  #else -	mod_info("Asked to wait for interrupt but interrupts are not enabled in the driver\n"); -	return -EFAULT; +    mod_info("Asked to wait for interrupt but interrupts are not enabled in the driver\n"); +    return -EFAULT;  #endif  } @@ -429,18 +429,18 @@ static int ioctl_clear_ioq(pcidriver_privdata_t *privdata, unsigned long arg)   */  static int ioctl_version(pcidriver_privdata_t *privdata, unsigned long arg)  { -	int ret; -	pcilib_driver_version_t info; +    int ret; +    pcilib_driver_version_t info; -	info = (pcilib_driver_version_t) { -	    .version = PCILIB_VERSION, -	    .interface = PCIDRIVER_INTERFACE_VERSION, -	    .ioctls = PCIDRIVER_IOC_MAX + 1 -	}; +    info = (pcilib_driver_version_t) { +        .version = PCILIB_VERSION, +         .interface = PCIDRIVER_INTERFACE_VERSION, +          .ioctls = PCIDRIVER_IOC_MAX + 1 +    }; -	WRITE_TO_USER(pcilib_driver_version_t, info); +    WRITE_TO_USER(pcilib_driver_version_t, info); -	return 0; +    return 0;  }  /** @@ -452,24 +452,24 @@ static int ioctl_version(pcidriver_privdata_t *privdata, unsigned long arg)   */  static int ioctl_device_state(pcidriver_privdata_t *privdata, unsigned long arg)  { -	int ret; -	pcilib_device_state_t info; +    int ret; +    pcilib_device_state_t info;  #ifdef PCIDRIVER_DUMMY_DEVICE -	memset(&info, 0, sizeof(info)); +    memset(&info, 0, sizeof(info));  #else /* PCIDRIVER_DUMMY_DEVICE */ -	info = (pcilib_device_state_t) { -	    .iommu = iommu_present(privdata->pdev->dev.bus), -	    .mps = pcidriver_pcie_get_mps(privdata->pdev), -	    .readrq = pcie_get_readrq(privdata->pdev), -	    .dma_mask = privdata->pdev->dma_mask -	}; +    info = (pcilib_device_state_t) { +        .iommu = iommu_present(privdata->pdev->dev.bus), +         .mps = pcidriver_pcie_get_mps(privdata->pdev), +          .readrq = pcie_get_readrq(privdata->pdev), +           .dma_mask = privdata->pdev->dma_mask +    };  #endif /* PCIDRIVER_DUMMY_DEVICE */ -	WRITE_TO_USER(pcilib_device_state_t, info); +    WRITE_TO_USER(pcilib_device_state_t, info); -	return 0; +    return 0;  } @@ -483,19 +483,19 @@ static int ioctl_device_state(pcidriver_privdata_t *privdata, unsigned long arg)  static int ioctl_set_dma_mask(pcidriver_privdata_t *privdata, unsigned long arg)  {  #ifndef PCIDRIVER_DUMMY_DEVICE -	int err; +    int err; -	if ((arg < 24) || (arg > 64)) -		return -EINVAL; +    if ((arg < 24) || (arg > 64)) +        return -EINVAL; -	err = pci_set_dma_mask(privdata->pdev, DMA_BIT_MASK(arg)); -	if (err < 0) { -	    printk(KERN_ERR "pci_set_dma_mask(%lu) failed\n", arg); -	    return err; -	} +    err = pci_set_dma_mask(privdata->pdev, DMA_BIT_MASK(arg)); +    if (err < 0) { +        printk(KERN_ERR "pci_set_dma_mask(%lu) failed\n", arg); +        return err; +    }  #endif /* ! PCIDRIVER_DUMMY_DEVICE */ -	 -	return 0; + +    return 0;  }  /** @@ -508,19 +508,19 @@ static int ioctl_set_dma_mask(pcidriver_privdata_t *privdata, unsigned long arg)  static int ioctl_set_mps(pcidriver_privdata_t *privdata, unsigned long arg)  {  #ifndef PCIDRIVER_DUMMY_DEVICE -	int err; +    int err; -	if ((arg != 128) && (arg != 256) && (arg != 512)) -		return -EINVAL; +    if ((arg != 128) && (arg != 256) && (arg != 512)) +        return -EINVAL; -	err = pcidriver_pcie_set_mps(privdata->pdev, arg); -	if (err < 0) { -	    printk(KERN_ERR "pcie_set_mps(%lu) failed\n", arg); -	    return err; -	} +    err = pcidriver_pcie_set_mps(privdata->pdev, arg); +    if (err < 0) { +        printk(KERN_ERR "pcie_set_mps(%lu) failed\n", arg); +        return err; +    }  #endif /* ! PCIDRIVER_DUMMY_DEVICE */ -	 -	return 0; + +    return 0;  } @@ -533,69 +533,65 @@ static int ioctl_set_mps(pcidriver_privdata_t *privdata, unsigned long arg)   * @returns -EFAULT when an invalid memory pointer is passed   *   */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) -int pcidriver_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) -#else  long pcidriver_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -#endif  { -	pcidriver_privdata_t *privdata = filp->private_data; +    pcidriver_privdata_t *privdata = filp->private_data; + +    /* Select the appropiate command */ +    switch (cmd) { +    case PCIDRIVER_IOC_MMAP_MODE: +        return ioctl_mmap_mode(privdata, arg); -	/* Select the appropiate command */ -	switch (cmd) { -		case PCIDRIVER_IOC_MMAP_MODE: -			return ioctl_mmap_mode(privdata, arg); +    case PCIDRIVER_IOC_MMAP_AREA: +        return ioctl_mmap_area(privdata, arg); -		case PCIDRIVER_IOC_MMAP_AREA: -			return ioctl_mmap_area(privdata, arg); +    case PCIDRIVER_IOC_PCI_CFG_RD: +    case PCIDRIVER_IOC_PCI_CFG_WR: +        return ioctl_pci_config_read_write(privdata, cmd, arg); -		case PCIDRIVER_IOC_PCI_CFG_RD: -		case PCIDRIVER_IOC_PCI_CFG_WR: -			return ioctl_pci_config_read_write(privdata, cmd, arg); +    case PCIDRIVER_IOC_PCI_INFO: +        return ioctl_pci_info(privdata, arg); -		case PCIDRIVER_IOC_PCI_INFO: -			return ioctl_pci_info(privdata, arg); +    case PCIDRIVER_IOC_KMEM_ALLOC: +        return ioctl_kmem_alloc(privdata, arg); -		case PCIDRIVER_IOC_KMEM_ALLOC: -			return ioctl_kmem_alloc(privdata, arg); +    case PCIDRIVER_IOC_KMEM_FREE: +        return ioctl_kmem_free(privdata, arg); -		case PCIDRIVER_IOC_KMEM_FREE: -			return ioctl_kmem_free(privdata, arg); +    case PCIDRIVER_IOC_KMEM_SYNC: +        return ioctl_kmem_sync(privdata, arg); -		case PCIDRIVER_IOC_KMEM_SYNC: -			return ioctl_kmem_sync(privdata, arg); +    case PCIDRIVER_IOC_UMEM_SGMAP: +        return ioctl_umem_sgmap(privdata, arg); -		case PCIDRIVER_IOC_UMEM_SGMAP: -			return ioctl_umem_sgmap(privdata, arg); +    case PCIDRIVER_IOC_UMEM_SGUNMAP: +        return ioctl_umem_sgunmap(privdata, arg); -		case PCIDRIVER_IOC_UMEM_SGUNMAP: -			return ioctl_umem_sgunmap(privdata, arg); +    case PCIDRIVER_IOC_UMEM_SGGET: +        return ioctl_umem_sgget(privdata, arg); -		case PCIDRIVER_IOC_UMEM_SGGET: -			return ioctl_umem_sgget(privdata, arg); +    case PCIDRIVER_IOC_UMEM_SYNC: +        return ioctl_umem_sync(privdata, arg); -		case PCIDRIVER_IOC_UMEM_SYNC: -			return ioctl_umem_sync(privdata, arg); +    case PCIDRIVER_IOC_WAITI: +        return ioctl_wait_interrupt(privdata, arg); -		case PCIDRIVER_IOC_WAITI: -			return ioctl_wait_interrupt(privdata, arg); +    case PCIDRIVER_IOC_CLEAR_IOQ: +        return ioctl_clear_ioq(privdata, arg); -		case PCIDRIVER_IOC_CLEAR_IOQ: -			return ioctl_clear_ioq(privdata, arg); -		 -		case PCIDRIVER_IOC_VERSION: -			return ioctl_version(privdata, arg); +    case PCIDRIVER_IOC_VERSION: +        return ioctl_version(privdata, arg); -		case PCIDRIVER_IOC_DEVICE_STATE: -			return ioctl_device_state(privdata, arg); +    case PCIDRIVER_IOC_DEVICE_STATE: +        return ioctl_device_state(privdata, arg); -		case PCIDRIVER_IOC_DMA_MASK: -			return ioctl_set_dma_mask(privdata, arg); +    case PCIDRIVER_IOC_DMA_MASK: +        return ioctl_set_dma_mask(privdata, arg); -		case PCIDRIVER_IOC_MPS: -			return ioctl_set_mps(privdata, arg); +    case PCIDRIVER_IOC_MPS: +        return ioctl_set_mps(privdata, arg); -		default: -			return -EINVAL; -	} +    default: +        return -EINVAL; +    }  } diff --git a/driver/ioctl.h b/driver/ioctl.h index 696fb8b..e989f95 100644 --- a/driver/ioctl.h +++ b/driver/ioctl.h @@ -1,5 +1 @@ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) -int pcidriver_ioctl(struct inode  *inode, struct file *filp, unsigned int cmd, unsigned long arg); -#else  long pcidriver_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); -#endif diff --git a/driver/kmem.c b/driver/kmem.c index 9bc1eb7..e3b0a97 100644 --- a/driver/kmem.c +++ b/driver/kmem.c @@ -24,10 +24,6 @@  #include "kmem.h"			/* prototypes for kernel memory */  #include "sysfs.h"			/* prototypes for sysfs */ -/* VM_RESERVED is removed in 3.7-rc1 */ -#ifndef VM_RESERVED -# define  VM_RESERVED   (VM_DONTEXPAND | VM_DONTDUMP) -#endif  /**   * @@ -37,270 +33,268 @@   */  int pcidriver_kmem_alloc(pcidriver_privdata_t *privdata, kmem_handle_t *kmem_handle)  { -	int flags; -	pcidriver_kmem_entry_t *kmem_entry; -	void *retptr; - -	if (kmem_handle->flags&KMEM_FLAG_REUSE) { -	    kmem_entry = pcidriver_kmem_find_entry_use(privdata, kmem_handle->use, kmem_handle->item); -	    if (kmem_entry) { -		unsigned long flags = kmem_handle->flags; -		 -		if (flags&KMEM_FLAG_TRY) { -		    kmem_handle->type = kmem_entry->type; -		    kmem_handle->size = kmem_entry->size; -		    kmem_handle->align = kmem_entry->align; -		} else { -		    if (kmem_handle->type != kmem_entry->type) { -		    	mod_info("Invalid type of reusable kmem_entry, currently: %lu, but requested: %lu\n", kmem_entry->type, kmem_handle->type); -		    	kmem_handle->type = kmem_entry->type; -			return -EINVAL; -		    } - -		    if (((kmem_handle->type&PCILIB_KMEM_TYPE_MASK) == PCILIB_KMEM_TYPE_PAGE)&&(kmem_handle->size == 0)) { -			kmem_handle->size = kmem_entry->size; -		    } else if (kmem_handle->size != kmem_entry->size) { -			mod_info("Invalid size of reusable kmem_entry, currently: %lu, but requested: %lu\n", kmem_entry->size, kmem_handle->size); -			kmem_handle->size = kmem_entry->size; -			return -EINVAL; -		    } - -		    if (kmem_handle->align != kmem_entry->align) { -			mod_info("Invalid alignment of reusable kmem_entry, currently: %lu, but requested: %lu\n", kmem_entry->align, kmem_handle->align); -			kmem_handle->align = kmem_entry->align; -			return -EINVAL; -		    } - -		    if (((kmem_entry->mode&KMEM_MODE_EXCLUSIVE)?1:0) != ((flags&KMEM_FLAG_EXCLUSIVE)?1:0)) { -			mod_info("Invalid mode of reusable kmem_entry\n"); -			kmem_handle->flags = (kmem_entry->mode&KMEM_MODE_EXCLUSIVE)?KMEM_FLAG_EXCLUSIVE:0; -			return -EINVAL; -		    } -		} -		 - -		if ((kmem_entry->mode&KMEM_MODE_COUNT)==KMEM_MODE_COUNT) { -			mod_info("Reuse counter of kmem_entry is overflown"); -			return -EBUSY; -		} -		 -		 -		kmem_handle->handle_id = kmem_entry->id; -		kmem_handle->ba = (unsigned long)(kmem_entry->dma_handle); -		kmem_handle->pa = virt_to_phys((void*)kmem_entry->cpua); - -		kmem_handle->flags = KMEM_FLAG_REUSED; -		if (kmem_entry->refs&KMEM_REF_HW) kmem_handle->flags |= KMEM_FLAG_REUSED_HW; -		if (kmem_entry->mode&KMEM_MODE_PERSISTENT) kmem_handle->flags |= KMEM_FLAG_REUSED_PERSISTENT; - -		kmem_entry->mode += 1; -		if (flags&KMEM_FLAG_HW) { -		    if ((kmem_entry->refs&KMEM_REF_HW)==0) -			pcidriver_module_get(privdata); -			 -		    kmem_entry->refs |= KMEM_REF_HW; -		} -		if (flags&KMEM_FLAG_PERSISTENT) kmem_entry->mode |= KMEM_MODE_PERSISTENT; - -		privdata->kmem_cur_id = kmem_entry->id; -		 -		return 0; -	    } -	     -	    if (kmem_handle->flags&KMEM_FLAG_TRY) return -ENOENT; -	} - -	/* First, allocate zeroed memory for the kmem_entry */ -	if ((kmem_entry = kcalloc(1, sizeof(pcidriver_kmem_entry_t), GFP_KERNEL)) == NULL) -		goto kmem_alloc_entry_fail; - -	/* Initialize the kmem_entry */ -	kmem_entry->id = atomic_inc_return(&privdata->kmem_count) - 1; -	privdata->kmem_cur_id = kmem_entry->id; -	kmem_handle->handle_id = kmem_entry->id; - -	kmem_entry->use = kmem_handle->use; -	kmem_entry->item = kmem_handle->item; -	kmem_entry->type = kmem_handle->type; -	kmem_entry->align = kmem_handle->align; -	kmem_entry->direction = PCI_DMA_NONE; - -	/* Initialize sysfs if possible */ -	if (pcidriver_sysfs_initialize_kmem(privdata, kmem_entry->id, &(kmem_entry->sysfs_attr)) != 0) -		goto kmem_alloc_mem_fail; - -	/* ...and allocate the DMA memory */ -	/* note this is a memory pair, referencing the same area: the cpu address (cpua) -	 * and the PCI bus address (pa). The CPU and PCI addresses may not be the same. -	 * The CPU sees only CPU addresses, while the device sees only PCI addresses. -	 * CPU address is used for the mmap (internal to the driver), and -	 * PCI address is the address passed to the DMA Controller in the device. -	 */ -	switch (kmem_entry->type&PCILIB_KMEM_TYPE_MASK) { -	 case PCILIB_KMEM_TYPE_CONSISTENT: +    int flags; +    pcidriver_kmem_entry_t *kmem_entry; +    void *retptr; + +    if (kmem_handle->flags&KMEM_FLAG_REUSE) { +        kmem_entry = pcidriver_kmem_find_entry_use(privdata, kmem_handle->use, kmem_handle->item); +        if (kmem_entry) { +            unsigned long flags = kmem_handle->flags; + +            if (flags&KMEM_FLAG_TRY) { +                kmem_handle->type = kmem_entry->type; +                kmem_handle->size = kmem_entry->size; +                kmem_handle->align = kmem_entry->align; +            } else { +                if (kmem_handle->type != kmem_entry->type) { +                    mod_info("Invalid type of reusable kmem_entry, currently: %lu, but requested: %lu\n", kmem_entry->type, kmem_handle->type); +                    kmem_handle->type = kmem_entry->type; +                    return -EINVAL; +                } + +                if (((kmem_handle->type&PCILIB_KMEM_TYPE_MASK) == PCILIB_KMEM_TYPE_PAGE)&&(kmem_handle->size == 0)) { +                    kmem_handle->size = kmem_entry->size; +                } else if (kmem_handle->size != kmem_entry->size) { +                    mod_info("Invalid size of reusable kmem_entry, currently: %lu, but requested: %lu\n", kmem_entry->size, kmem_handle->size); +                    kmem_handle->size = kmem_entry->size; +                    return -EINVAL; +                } + +                if (kmem_handle->align != kmem_entry->align) { +                    mod_info("Invalid alignment of reusable kmem_entry, currently: %lu, but requested: %lu\n", kmem_entry->align, kmem_handle->align); +                    kmem_handle->align = kmem_entry->align; +                    return -EINVAL; +                } + +                if (((kmem_entry->mode&KMEM_MODE_EXCLUSIVE)?1:0) != ((flags&KMEM_FLAG_EXCLUSIVE)?1:0)) { +                    mod_info("Invalid mode of reusable kmem_entry\n"); +                    kmem_handle->flags = (kmem_entry->mode&KMEM_MODE_EXCLUSIVE)?KMEM_FLAG_EXCLUSIVE:0; +                    return -EINVAL; +                } +            } + + +            if ((kmem_entry->mode&KMEM_MODE_COUNT)==KMEM_MODE_COUNT) { +                mod_info("Reuse counter of kmem_entry is overflown"); +                return -EBUSY; +            } + + +            kmem_handle->handle_id = kmem_entry->id; +            kmem_handle->ba = (unsigned long)(kmem_entry->dma_handle); +            kmem_handle->pa = virt_to_phys((void*)kmem_entry->cpua); + +            kmem_handle->flags = KMEM_FLAG_REUSED; +            if (kmem_entry->refs&KMEM_REF_HW) kmem_handle->flags |= KMEM_FLAG_REUSED_HW; +            if (kmem_entry->mode&KMEM_MODE_PERSISTENT) kmem_handle->flags |= KMEM_FLAG_REUSED_PERSISTENT; + +            kmem_entry->mode += 1; +            if (flags&KMEM_FLAG_HW) { +                if ((kmem_entry->refs&KMEM_REF_HW)==0) +                    pcidriver_module_get(privdata); + +                kmem_entry->refs |= KMEM_REF_HW; +            } +            if (flags&KMEM_FLAG_PERSISTENT) kmem_entry->mode |= KMEM_MODE_PERSISTENT; + +            privdata->kmem_cur_id = kmem_entry->id; + +            return 0; +        } + +        if (kmem_handle->flags&KMEM_FLAG_TRY) return -ENOENT; +    } + +    /* First, allocate zeroed memory for the kmem_entry */ +    if ((kmem_entry = kcalloc(1, sizeof(pcidriver_kmem_entry_t), GFP_KERNEL)) == NULL) +        goto kmem_alloc_entry_fail; + +    /* Initialize the kmem_entry */ +    kmem_entry->id = atomic_inc_return(&privdata->kmem_count) - 1; +    privdata->kmem_cur_id = kmem_entry->id; +    kmem_handle->handle_id = kmem_entry->id; + +    kmem_entry->use = kmem_handle->use; +    kmem_entry->item = kmem_handle->item; +    kmem_entry->type = kmem_handle->type; +    kmem_entry->align = kmem_handle->align; +    kmem_entry->direction = PCI_DMA_NONE; + +    /* Initialize sysfs if possible */ +    if (pcidriver_sysfs_initialize_kmem(privdata, kmem_entry->id, &(kmem_entry->sysfs_attr)) != 0) +        goto kmem_alloc_mem_fail; + +    /* ...and allocate the DMA memory */ +    /* note this is a memory pair, referencing the same area: the cpu address (cpua) +     * and the PCI bus address (pa). The CPU and PCI addresses may not be the same. +     * The CPU sees only CPU addresses, while the device sees only PCI addresses. +     * CPU address is used for the mmap (internal to the driver), and +     * PCI address is the address passed to the DMA Controller in the device. +     */ +    switch (kmem_entry->type&PCILIB_KMEM_TYPE_MASK) { +    case PCILIB_KMEM_TYPE_CONSISTENT:  #ifdef PCIDRIVER_DUMMY_DEVICE -	    retptr = kmalloc( kmem_handle->size, GFP_KERNEL); +        retptr = kmalloc( kmem_handle->size, GFP_KERNEL);  #else /* PCIDRIVER_DUMMY_DEVICE */ -	    retptr = pci_alloc_consistent( privdata->pdev, kmem_handle->size, &(kmem_entry->dma_handle) ); +        retptr = pci_alloc_consistent( privdata->pdev, kmem_handle->size, &(kmem_entry->dma_handle) );  #endif /* PCIDRIVER_DUMMY_DEVICE */ -	    break; -	 case PCILIB_KMEM_TYPE_REGION: -	    retptr = ioremap(kmem_handle->pa,  kmem_handle->size); -	    kmem_entry->dma_handle = kmem_handle->pa; -	    if (kmem_entry->type == PCILIB_KMEM_TYPE_REGION_S2C) { -		kmem_entry->direction = PCI_DMA_TODEVICE; -	    } else if (kmem_entry->type == PCILIB_KMEM_TYPE_REGION_C2S) { -		kmem_entry->direction = PCI_DMA_FROMDEVICE; -	    } -	    break; -	 case PCILIB_KMEM_TYPE_PAGE: -	    flags = GFP_KERNEL; - -	    if (kmem_handle->size == 0) -		kmem_handle->size = PAGE_SIZE; -	    else if (kmem_handle->size%PAGE_SIZE) -		goto kmem_alloc_mem_fail; -	    else  -		flags |= __GFP_COMP; -	 -	    retptr = (void*)__get_free_pages(flags, get_order(kmem_handle->size)); -	    kmem_entry->dma_handle = 0; - -	    if (retptr) { +        break; +    case PCILIB_KMEM_TYPE_REGION: +        retptr = ioremap(kmem_handle->pa,  kmem_handle->size); +        kmem_entry->dma_handle = kmem_handle->pa; +        if (kmem_entry->type == PCILIB_KMEM_TYPE_REGION_S2C) { +            kmem_entry->direction = PCI_DMA_TODEVICE; +        } else if (kmem_entry->type == PCILIB_KMEM_TYPE_REGION_C2S) { +            kmem_entry->direction = PCI_DMA_FROMDEVICE; +        } +        break; +    case PCILIB_KMEM_TYPE_PAGE: +        flags = GFP_KERNEL; + +        if (kmem_handle->size == 0) +            kmem_handle->size = PAGE_SIZE; +        else if (kmem_handle->size%PAGE_SIZE) +            goto kmem_alloc_mem_fail; +        else +            flags |= __GFP_COMP; + +        retptr = (void*)__get_free_pages(flags, get_order(kmem_handle->size)); +        kmem_entry->dma_handle = 0; + +        if (retptr) {  #ifndef PCIDRIVER_DUMMY_DEVICE -	        if (kmem_entry->type == PCILIB_KMEM_TYPE_DMA_S2C_PAGE) { -		    kmem_entry->direction = PCI_DMA_TODEVICE; -    		    kmem_entry->dma_handle = pci_map_single(privdata->pdev, retptr, kmem_handle->size, PCI_DMA_TODEVICE); -		    if (pci_dma_mapping_error(privdata->pdev, kmem_entry->dma_handle)) { -			free_pages((unsigned long)retptr, get_order(kmem_handle->size)); -			goto kmem_alloc_mem_fail; -		    } -		} else if (kmem_entry->type == PCILIB_KMEM_TYPE_DMA_C2S_PAGE) { -		    kmem_entry->direction = PCI_DMA_FROMDEVICE; -    		    kmem_entry->dma_handle = pci_map_single(privdata->pdev, retptr, kmem_handle->size, PCI_DMA_FROMDEVICE); -		    if (pci_dma_mapping_error(privdata->pdev, kmem_entry->dma_handle)) { -			free_pages((unsigned long)retptr, get_order(kmem_handle->size)); -			goto kmem_alloc_mem_fail; -		     -		    } -		} +            if (kmem_entry->type == PCILIB_KMEM_TYPE_DMA_S2C_PAGE) { +                kmem_entry->direction = PCI_DMA_TODEVICE; +                kmem_entry->dma_handle = pci_map_single(privdata->pdev, retptr, kmem_handle->size, PCI_DMA_TODEVICE); +                if (pci_dma_mapping_error(privdata->pdev, kmem_entry->dma_handle)) { +                    free_pages((unsigned long)retptr, get_order(kmem_handle->size)); +                    goto kmem_alloc_mem_fail; +                } +            } else if (kmem_entry->type == PCILIB_KMEM_TYPE_DMA_C2S_PAGE) { +                kmem_entry->direction = PCI_DMA_FROMDEVICE; +                kmem_entry->dma_handle = pci_map_single(privdata->pdev, retptr, kmem_handle->size, PCI_DMA_FROMDEVICE); +                if (pci_dma_mapping_error(privdata->pdev, kmem_entry->dma_handle)) { +                    free_pages((unsigned long)retptr, get_order(kmem_handle->size)); +                    goto kmem_alloc_mem_fail; + +                } +            }  #endif /* ! PCIDRIVER_DUMMY_DEVICE */ -	    } -	     -	    break; -	 default: -	    goto kmem_alloc_mem_fail; -	} -	 -	 -	if (retptr == NULL) -		goto kmem_alloc_mem_fail; - -	kmem_entry->size = kmem_handle->size; -	kmem_entry->cpua = (unsigned long)retptr; -	kmem_handle->ba = (unsigned long)(kmem_entry->dma_handle); -	kmem_handle->pa = virt_to_phys(retptr); - -	kmem_entry->mode = 1; -	if (kmem_handle->flags&KMEM_FLAG_REUSE) { -	    kmem_entry->mode |= KMEM_MODE_REUSABLE; -	    if (kmem_handle->flags&KMEM_FLAG_EXCLUSIVE) kmem_entry->mode |= KMEM_MODE_EXCLUSIVE; -	    if (kmem_handle->flags&KMEM_FLAG_PERSISTENT) kmem_entry->mode |= KMEM_MODE_PERSISTENT; -	} -	 -	kmem_entry->refs = 0; -	if (kmem_handle->flags&KMEM_FLAG_HW) { -	    pcidriver_module_get(privdata); - -	    kmem_entry->refs |= KMEM_REF_HW; -	} - -        kmem_handle->flags = 0; -	 -	set_pages_reserved_compat(kmem_entry->cpua, kmem_entry->size); - -	/* Add the kmem_entry to the list of the device */ -	spin_lock( &(privdata->kmemlist_lock) ); -	list_add_tail( &(kmem_entry->list), &(privdata->kmem_list) ); -	spin_unlock( &(privdata->kmemlist_lock) ); - -	return 0; +        } + +        break; +    default: +        goto kmem_alloc_mem_fail; +    } + + +    if (retptr == NULL) +        goto kmem_alloc_mem_fail; + +    kmem_entry->size = kmem_handle->size; +    kmem_entry->cpua = (unsigned long)retptr; +    kmem_handle->ba = (unsigned long)(kmem_entry->dma_handle); +    kmem_handle->pa = virt_to_phys(retptr); + +    kmem_entry->mode = 1; +    if (kmem_handle->flags&KMEM_FLAG_REUSE) { +        kmem_entry->mode |= KMEM_MODE_REUSABLE; +        if (kmem_handle->flags&KMEM_FLAG_EXCLUSIVE) kmem_entry->mode |= KMEM_MODE_EXCLUSIVE; +        if (kmem_handle->flags&KMEM_FLAG_PERSISTENT) kmem_entry->mode |= KMEM_MODE_PERSISTENT; +    } + +    kmem_entry->refs = 0; +    if (kmem_handle->flags&KMEM_FLAG_HW) { +        pcidriver_module_get(privdata); + +        kmem_entry->refs |= KMEM_REF_HW; +    } + +    kmem_handle->flags = 0; + +    /* Add the kmem_entry to the list of the device */ +    spin_lock( &(privdata->kmemlist_lock) ); +    list_add_tail( &(kmem_entry->list), &(privdata->kmem_list) ); +    spin_unlock( &(privdata->kmemlist_lock) ); + +    return 0;  kmem_alloc_mem_fail: -		kfree(kmem_entry); +    kfree(kmem_entry);  kmem_alloc_entry_fail: -		return -ENOMEM; +    return -ENOMEM;  }  static int pcidriver_kmem_free_check(pcidriver_privdata_t *privdata, kmem_handle_t *kmem_handle, pcidriver_kmem_entry_t *kmem_entry) { -	if ((kmem_handle->flags & KMEM_FLAG_FORCE) == 0) { -	    if (kmem_entry->mode&KMEM_MODE_COUNT) -		kmem_entry->mode -= 1; - -	    if (kmem_handle->flags&KMEM_FLAG_HW) { -		if (kmem_entry->refs&KMEM_REF_HW)  -		    pcidriver_module_put(privdata); - -		kmem_entry->refs &= ~KMEM_REF_HW; -	    } -	 -	    if (kmem_handle->flags&KMEM_FLAG_PERSISTENT) -		kmem_entry->mode &= ~KMEM_MODE_PERSISTENT; -	 -	    if (kmem_handle->flags&KMEM_FLAG_REUSE)  -		return 0; - -	    if (kmem_entry->refs) { -		kmem_entry->mode += 1; -		mod_info("can't free referenced kmem_entry, refs = %lx\n", kmem_entry->refs); -		return -EBUSY; -	    } -	 -	    if (kmem_entry->mode & KMEM_MODE_PERSISTENT) { -		kmem_entry->mode += 1; -		mod_info("can't free persistent kmem_entry\n"); -		return -EBUSY; -	    } - -	    if (((kmem_entry->mode&KMEM_MODE_EXCLUSIVE)==0)&&(kmem_entry->mode&KMEM_MODE_COUNT)&&((kmem_handle->flags&KMEM_FLAG_EXCLUSIVE)==0))  -		return 0; -	} else { -	    if (kmem_entry->refs&KMEM_REF_HW) -		    pcidriver_module_put(privdata); -		 -	    while (!atomic_add_negative(-1, &(privdata->refs))) pcidriver_module_put(privdata); -	    atomic_inc(&(privdata->refs)); -		 -	} -	 -	return 1; +    if ((kmem_handle->flags & KMEM_FLAG_FORCE) == 0) { +        if (kmem_entry->mode&KMEM_MODE_COUNT) +            kmem_entry->mode -= 1; + +        if (kmem_handle->flags&KMEM_FLAG_HW) { +            if (kmem_entry->refs&KMEM_REF_HW) +                pcidriver_module_put(privdata); + +            kmem_entry->refs &= ~KMEM_REF_HW; +        } + +        if (kmem_handle->flags&KMEM_FLAG_PERSISTENT) +            kmem_entry->mode &= ~KMEM_MODE_PERSISTENT; + +        if (kmem_handle->flags&KMEM_FLAG_REUSE) +            return 0; + +        if (kmem_entry->refs) { +            kmem_entry->mode += 1; +            mod_info("can't free referenced kmem_entry, refs = %lx\n", kmem_entry->refs); +            return -EBUSY; +        } + +        if (kmem_entry->mode & KMEM_MODE_PERSISTENT) { +            kmem_entry->mode += 1; +            mod_info("can't free persistent kmem_entry\n"); +            return -EBUSY; +        } + +        if (((kmem_entry->mode&KMEM_MODE_EXCLUSIVE)==0)&&(kmem_entry->mode&KMEM_MODE_COUNT)&&((kmem_handle->flags&KMEM_FLAG_EXCLUSIVE)==0)) +            return 0; +    } else { +        if (kmem_entry->refs&KMEM_REF_HW) +            pcidriver_module_put(privdata); + +        while (!atomic_add_negative(-1, &(privdata->refs))) pcidriver_module_put(privdata); +        atomic_inc(&(privdata->refs)); + +    } + +    return 1;  }  static int pcidriver_kmem_free_use(pcidriver_privdata_t *privdata, kmem_handle_t *kmem_handle)  { -	int err; -	int failed = 0; -	struct list_head *ptr, *next; -	pcidriver_kmem_entry_t *kmem_entry; - -	/* iterate safely over the entries and delete them */ -	list_for_each_safe(ptr, next, &(privdata->kmem_list)) { -		kmem_entry = list_entry(ptr, pcidriver_kmem_entry_t, list); -		if (kmem_entry->use == kmem_handle->use) { -		    err = pcidriver_kmem_free_check(privdata, kmem_handle, kmem_entry); -		    if (err > 0) -			pcidriver_kmem_free_entry(privdata, kmem_entry); 		/* spin lock inside! */ -		    else -			failed = 1; -		} -	} -	 -	if (failed) { -		mod_info("Some kmem_entries for use %lx are still referenced\n", kmem_handle->use); -		return -EBUSY; -	}	 - -	return 0; +    int err; +    int failed = 0; +    struct list_head *ptr, *next; +    pcidriver_kmem_entry_t *kmem_entry; + +    /* iterate safely over the entries and delete them */ +    list_for_each_safe(ptr, next, &(privdata->kmem_list)) { +        kmem_entry = list_entry(ptr, pcidriver_kmem_entry_t, list); +        if (kmem_entry->use == kmem_handle->use) { +            err = pcidriver_kmem_free_check(privdata, kmem_handle, kmem_entry); +            if (err > 0) +                pcidriver_kmem_free_entry(privdata, kmem_entry); 		/* spin lock inside! */ +            else +                failed = 1; +        } +    } + +    if (failed) { +        mod_info("Some kmem_entries for use %lx are still referenced\n", kmem_handle->use); +        return -EBUSY; +    } + +    return 0;  }  /** @@ -310,24 +304,24 @@ static int pcidriver_kmem_free_use(pcidriver_privdata_t *privdata, kmem_handle_t   */  int pcidriver_kmem_free( pcidriver_privdata_t *privdata, kmem_handle_t *kmem_handle )  { -	int err; -	pcidriver_kmem_entry_t *kmem_entry; - -	if (kmem_handle->flags&KMEM_FLAG_MASS) { -	    kmem_handle->flags &= ~KMEM_FLAG_MASS; -	    return pcidriver_kmem_free_use(privdata, kmem_handle); -	} -	 -	/* Find the associated kmem_entry for this buffer */ -	if ((kmem_entry = pcidriver_kmem_find_entry(privdata, kmem_handle)) == NULL) -		return -EINVAL;					/* kmem_handle is not valid */ - -	err = pcidriver_kmem_free_check(privdata, kmem_handle, kmem_entry); -	 -	if (err > 0) -		return pcidriver_kmem_free_entry(privdata, kmem_entry); -	 -	return err; +    int err; +    pcidriver_kmem_entry_t *kmem_entry; + +    if (kmem_handle->flags&KMEM_FLAG_MASS) { +        kmem_handle->flags &= ~KMEM_FLAG_MASS; +        return pcidriver_kmem_free_use(privdata, kmem_handle); +    } + +    /* Find the associated kmem_entry for this buffer */ +    if ((kmem_entry = pcidriver_kmem_find_entry(privdata, kmem_handle)) == NULL) +        return -EINVAL;					/* kmem_handle is not valid */ + +    err = pcidriver_kmem_free_check(privdata, kmem_handle, kmem_entry); + +    if (err > 0) +        return pcidriver_kmem_free_entry(privdata, kmem_entry); + +    return err;  }  /** @@ -338,24 +332,24 @@ int pcidriver_kmem_free( pcidriver_privdata_t *privdata, kmem_handle_t *kmem_han  int pcidriver_kmem_free_all(pcidriver_privdata_t *privdata)  {  //	int failed = 0; -	struct list_head *ptr, *next; -	pcidriver_kmem_entry_t *kmem_entry; - -	/* iterate safely over the entries and delete them */ -	list_for_each_safe(ptr, next, &(privdata->kmem_list)) { -		kmem_entry = list_entry(ptr, pcidriver_kmem_entry_t, list); -		/*if (kmem_entry->refs) -			failed = 1; -		else*/ -			pcidriver_kmem_free_entry(privdata, kmem_entry); 		/* spin lock inside! */ -	} -/*	 -	if (failed) { -		mod_info("Some kmem_entries are still referenced\n"); -		return -EBUSY; -	}	 -*/ -	return 0; +    struct list_head *ptr, *next; +    pcidriver_kmem_entry_t *kmem_entry; + +    /* iterate safely over the entries and delete them */ +    list_for_each_safe(ptr, next, &(privdata->kmem_list)) { +        kmem_entry = list_entry(ptr, pcidriver_kmem_entry_t, list); +        /*if (kmem_entry->refs) +        	failed = 1; +        else*/ +        pcidriver_kmem_free_entry(privdata, kmem_entry); 		/* spin lock inside! */ +    } +    /* +    	if (failed) { +    		mod_info("Some kmem_entries are still referenced\n"); +    		return -EBUSY; +    	} +    */ +    return 0;  } @@ -366,43 +360,27 @@ int pcidriver_kmem_free_all(pcidriver_privdata_t *privdata)   */  int pcidriver_kmem_sync_entry( pcidriver_privdata_t *privdata, pcidriver_kmem_entry_t *kmem_entry, int direction)  { -	if (kmem_entry->direction == PCI_DMA_NONE) -		return -EINVAL; +    if (kmem_entry->direction == PCI_DMA_NONE) +        return -EINVAL;  #ifndef PCIDRIVER_DUMMY_DEVICE -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) -	switch (direction) { -		case PCILIB_KMEM_SYNC_TODEVICE: -			pci_dma_sync_single_for_device( privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, kmem_entry->direction ); -			break; -		case PCILIB_KMEM_SYNC_FROMDEVICE: -			pci_dma_sync_single_for_cpu( privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, kmem_entry->direction ); -			break; -		case PCILIB_KMEM_SYNC_BIDIRECTIONAL: -			pci_dma_sync_single_for_device( privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, kmem_entry->direction ); -			pci_dma_sync_single_for_cpu( privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, kmem_entry->direction ); -			break; -		default: -			return -EINVAL;				/* wrong direction parameter */ -	} -#else -	switch (direction) { -		case PCILIB_KMEM_SYNC_TODEVICE: -			pci_dma_sync_single( privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, kmem_entry->direction ); -			break; -		case PCILIB_KMEM_SYNC_FROMDEVICE: -			pci_dma_sync_single( privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, kmem_entry->direction ); -			break; -		case PCILIB_KMEM_SYNC_BIDIRECTIONAL: -			pci_dma_sync_single( privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, kmem_entry->direction ); -			break; -		default: -			return -EINVAL;				/* wrong direction parameter */ -	} -#endif +    switch (direction) { +    case PCILIB_KMEM_SYNC_TODEVICE: +        pci_dma_sync_single_for_device( privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, kmem_entry->direction ); +        break; +    case PCILIB_KMEM_SYNC_FROMDEVICE: +        pci_dma_sync_single_for_cpu( privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, kmem_entry->direction ); +        break; +    case PCILIB_KMEM_SYNC_BIDIRECTIONAL: +        pci_dma_sync_single_for_device( privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, kmem_entry->direction ); +        pci_dma_sync_single_for_cpu( privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, kmem_entry->direction ); +        break; +    default: +        return -EINVAL;				/* wrong direction parameter */ +    }  #endif /* ! PCIDRIVER_DUMMY_DEVICE */ -	return 0;	/* success */ +    return 0;	/* success */  }  /** @@ -412,41 +390,41 @@ int pcidriver_kmem_sync_entry( pcidriver_privdata_t *privdata, pcidriver_kmem_en   */  int pcidriver_kmem_sync( pcidriver_privdata_t *privdata, kmem_sync_t *kmem_sync )  { -	pcidriver_kmem_entry_t *kmem_entry = NULL; - -	    /* -	     * This is a shortcut to quickly find a next item in big multi-page kernel buffers  -	     */ -	spin_lock(&(privdata->kmemlist_lock)); -	if (privdata->kmem_last_sync) { -	    if (privdata->kmem_last_sync->id == kmem_sync->handle.handle_id)  -		kmem_entry = privdata->kmem_last_sync; -	    else { -		 privdata->kmem_last_sync = container_of(privdata->kmem_last_sync->list.next, pcidriver_kmem_entry_t, list); -		 -		if (privdata->kmem_last_sync) { -		    if (privdata->kmem_last_sync->id == kmem_sync->handle.handle_id)  -			kmem_entry = privdata->kmem_last_sync; -		    else -			privdata->kmem_last_sync = NULL; -		} -	    } -	} -	spin_unlock(&(privdata->kmemlist_lock)); -	 -	    /* -	     * If not found go the standard way -	     */ -	if (!kmem_entry) { -	    if ((kmem_entry = pcidriver_kmem_find_entry(privdata, &(kmem_sync->handle))) == NULL) -		return -EINVAL;					/* kmem_handle is not valid */ -	 -	    spin_lock(&(privdata->kmemlist_lock)); -	    privdata->kmem_last_sync = kmem_entry; -	    spin_unlock(&(privdata->kmemlist_lock)); -	}  - -	return pcidriver_kmem_sync_entry(privdata, kmem_entry, kmem_sync->dir); +    pcidriver_kmem_entry_t *kmem_entry = NULL; + +    /* +     * This is a shortcut to quickly find a next item in big multi-page kernel buffers +     */ +    spin_lock(&(privdata->kmemlist_lock)); +    if (privdata->kmem_last_sync) { +        if (privdata->kmem_last_sync->id == kmem_sync->handle.handle_id) +            kmem_entry = privdata->kmem_last_sync; +        else { +            privdata->kmem_last_sync = container_of(privdata->kmem_last_sync->list.next, pcidriver_kmem_entry_t, list); + +            if (privdata->kmem_last_sync) { +                if (privdata->kmem_last_sync->id == kmem_sync->handle.handle_id) +                    kmem_entry = privdata->kmem_last_sync; +                else +                    privdata->kmem_last_sync = NULL; +            } +        } +    } +    spin_unlock(&(privdata->kmemlist_lock)); + +    /* +     * If not found go the standard way +     */ +    if (!kmem_entry) { +        if ((kmem_entry = pcidriver_kmem_find_entry(privdata, &(kmem_sync->handle))) == NULL) +            return -EINVAL;					/* kmem_handle is not valid */ + +        spin_lock(&(privdata->kmemlist_lock)); +        privdata->kmem_last_sync = kmem_entry; +        spin_unlock(&(privdata->kmemlist_lock)); +    } + +    return pcidriver_kmem_sync_entry(privdata, kmem_entry, kmem_sync->dir);  }  /** @@ -456,75 +434,46 @@ int pcidriver_kmem_sync( pcidriver_privdata_t *privdata, kmem_sync_t *kmem_sync   */  int pcidriver_kmem_free_entry(pcidriver_privdata_t *privdata, pcidriver_kmem_entry_t *kmem_entry)  { -	pcidriver_sysfs_remove(privdata, &(kmem_entry->sysfs_attr)); - -	/* Go over the pages of the kmem buffer, and mark them as not reserved */ -#if 0 -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) -	/* -	 * This code is DISABLED. -	 * Apparently, it is not needed to unreserve them. Doing so here -	 * hangs the machine. Why? -	 * -	 * Uhm.. see links: -	 * -	 * http://lwn.net/Articles/161204/ -	 * http://lists.openfabrics.org/pipermail/general/2007-March/034101.html -	 * -	 * I insist, this should be enabled, but doing so hangs the machine. -	 * Literature supports the point, and there is even a similar problem (see link) -	 * But this is not the case. It seems right to me. but obviously is not. -	 * -	 * Anyway, this goes away in kernel >=2.6.15. -	 */ -	unsigned long start = __pa(kmem_entry->cpua) >> PAGE_SHIFT; -	unsigned long end = __pa(kmem_entry->cpua + kmem_entry->size) >> PAGE_SHIFT; -	unsigned long i; -	for(i=start;i<end;i++) { -		struct page *kpage = pfn_to_page(i); -		ClearPageReserved(kpage); -	} -#endif -#endif - -	/* Release DMA memory */ -	switch (kmem_entry->type&PCILIB_KMEM_TYPE_MASK) { -	 case PCILIB_KMEM_TYPE_CONSISTENT: +    pcidriver_sysfs_remove(privdata, &(kmem_entry->sysfs_attr)); + +    /* Release DMA memory */ +    switch (kmem_entry->type&PCILIB_KMEM_TYPE_MASK) { +    case PCILIB_KMEM_TYPE_CONSISTENT:  #ifdef PCIDRIVER_DUMMY_DEVICE -	    kfree((void*)(kmem_entry->cpua)); +        kfree((void*)(kmem_entry->cpua));  #else /* PCIDRIVER_DUMMY_DEVICE */ -	    pci_free_consistent( privdata->pdev, kmem_entry->size, (void *)(kmem_entry->cpua), kmem_entry->dma_handle ); +        pci_free_consistent( privdata->pdev, kmem_entry->size, (void *)(kmem_entry->cpua), kmem_entry->dma_handle );  #endif /* PCIDRIVER_DUMMY_DEVICE */ -	    break; -	 case PCILIB_KMEM_TYPE_REGION: -	    iounmap((void *)(kmem_entry->cpua)); -	    break; -	 case PCILIB_KMEM_TYPE_PAGE: +        break; +    case PCILIB_KMEM_TYPE_REGION: +        iounmap((void *)(kmem_entry->cpua)); +        break; +    case PCILIB_KMEM_TYPE_PAGE:  #ifndef PCIDRIVER_DUMMY_DEVICE -	    if (kmem_entry->dma_handle) { -		if (kmem_entry->type == PCILIB_KMEM_TYPE_DMA_S2C_PAGE) { -		    pci_unmap_single(privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, PCI_DMA_TODEVICE); -		} else if (kmem_entry->type == PCILIB_KMEM_TYPE_DMA_C2S_PAGE) { -		    pci_unmap_single(privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, PCI_DMA_FROMDEVICE); -		} -	    } +        if (kmem_entry->dma_handle) { +            if (kmem_entry->type == PCILIB_KMEM_TYPE_DMA_S2C_PAGE) { +                pci_unmap_single(privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, PCI_DMA_TODEVICE); +            } else if (kmem_entry->type == PCILIB_KMEM_TYPE_DMA_C2S_PAGE) { +                pci_unmap_single(privdata->pdev, kmem_entry->dma_handle, kmem_entry->size, PCI_DMA_FROMDEVICE); +            } +        }  #endif /* ! PCIDRIVER_DUMMY_DEVICE */ -	    free_pages((unsigned long)kmem_entry->cpua, get_order(kmem_entry->size)); -	    break; -	} +        free_pages((unsigned long)kmem_entry->cpua, get_order(kmem_entry->size)); +        break; +    } -	/* Remove the kmem list entry */ -	spin_lock( &(privdata->kmemlist_lock) ); -	if (privdata->kmem_last_sync == kmem_entry) -	    privdata->kmem_last_sync = NULL; -	list_del( &(kmem_entry->list) ); -	spin_unlock( &(privdata->kmemlist_lock) ); +    /* Remove the kmem list entry */ +    spin_lock( &(privdata->kmemlist_lock) ); +    if (privdata->kmem_last_sync == kmem_entry) +        privdata->kmem_last_sync = NULL; +    list_del( &(kmem_entry->list) ); +    spin_unlock( &(privdata->kmemlist_lock) ); -	/* Release kmem_entry memory */ -	kfree(kmem_entry); +    /* Release kmem_entry memory */ +    kfree(kmem_entry); -	return 0; +    return 0;  }  /** @@ -534,23 +483,23 @@ int pcidriver_kmem_free_entry(pcidriver_privdata_t *privdata, pcidriver_kmem_ent   */  pcidriver_kmem_entry_t *pcidriver_kmem_find_entry(pcidriver_privdata_t *privdata, kmem_handle_t *kmem_handle)  { -	struct list_head *ptr; -	pcidriver_kmem_entry_t *entry, *result = NULL; +    struct list_head *ptr; +    pcidriver_kmem_entry_t *entry, *result = NULL; -	/* should I implement it better using the handle_id? */ +    /* should I implement it better using the handle_id? */ -	spin_lock(&(privdata->kmemlist_lock)); -	list_for_each(ptr, &(privdata->kmem_list)) { -		entry = list_entry(ptr, pcidriver_kmem_entry_t, list); +    spin_lock(&(privdata->kmemlist_lock)); +    list_for_each(ptr, &(privdata->kmem_list)) { +        entry = list_entry(ptr, pcidriver_kmem_entry_t, list); -		if (entry->id == kmem_handle->handle_id) { -			result = entry; -			break; -		} -	} +        if (entry->id == kmem_handle->handle_id) { +            result = entry; +            break; +        } +    } -	spin_unlock(&(privdata->kmemlist_lock)); -	return result; +    spin_unlock(&(privdata->kmemlist_lock)); +    return result;  }  /** @@ -560,21 +509,21 @@ pcidriver_kmem_entry_t *pcidriver_kmem_find_entry(pcidriver_privdata_t *privdata   */  pcidriver_kmem_entry_t *pcidriver_kmem_find_entry_id(pcidriver_privdata_t *privdata, int id)  { -	struct list_head *ptr; -	pcidriver_kmem_entry_t *entry, *result = NULL; +    struct list_head *ptr; +    pcidriver_kmem_entry_t *entry, *result = NULL; -	spin_lock(&(privdata->kmemlist_lock)); -	list_for_each(ptr, &(privdata->kmem_list)) { -		entry = list_entry(ptr, pcidriver_kmem_entry_t, list); +    spin_lock(&(privdata->kmemlist_lock)); +    list_for_each(ptr, &(privdata->kmem_list)) { +        entry = list_entry(ptr, pcidriver_kmem_entry_t, list); -		if (entry->id == id) { -			result = entry; -			break; -		} -	} +        if (entry->id == id) { +            result = entry; +            break; +        } +    } -	spin_unlock(&(privdata->kmemlist_lock)); -	return result; +    spin_unlock(&(privdata->kmemlist_lock)); +    return result;  }  /** @@ -584,21 +533,21 @@ pcidriver_kmem_entry_t *pcidriver_kmem_find_entry_id(pcidriver_privdata_t *privd   */  pcidriver_kmem_entry_t *pcidriver_kmem_find_entry_use(pcidriver_privdata_t *privdata, unsigned long use, unsigned long item)  { -	struct list_head *ptr; -	pcidriver_kmem_entry_t *entry, *result = NULL; +    struct list_head *ptr; +    pcidriver_kmem_entry_t *entry, *result = NULL; -	spin_lock(&(privdata->kmemlist_lock)); -	list_for_each(ptr, &(privdata->kmem_list)) { -		entry = list_entry(ptr, pcidriver_kmem_entry_t, list); +    spin_lock(&(privdata->kmemlist_lock)); +    list_for_each(ptr, &(privdata->kmem_list)) { +        entry = list_entry(ptr, pcidriver_kmem_entry_t, list); -		if ((entry->use == use)&&(entry->item == item)&&(entry->mode&KMEM_MODE_REUSABLE)) { -			result = entry; -			break; -		} -	} +        if ((entry->use == use)&&(entry->item == item)&&(entry->mode&KMEM_MODE_REUSABLE)) { +            result = entry; +            break; +        } +    } -	spin_unlock(&(privdata->kmemlist_lock)); -	return result; +    spin_unlock(&(privdata->kmemlist_lock)); +    return result;  } @@ -606,18 +555,18 @@ void pcidriver_kmem_mmap_close(struct vm_area_struct *vma) {      unsigned long vma_size;      pcidriver_kmem_entry_t *kmem_entry = (pcidriver_kmem_entry_t*)vma->vm_private_data;      if (kmem_entry) { -/* -	if (kmem_entry->id == 0) { -	    mod_info("refs: %p %p %lx\n", vma, vma->vm_private_data, kmem_entry->refs); -	    mod_info("kmem_size: %lu vma_size: %lu, s: %lx, e: %lx\n", kmem_entry->size, (vma->vm_end - vma->vm_start), vma->vm_start, vma->vm_end); -	} -*/ - -	vma_size = (vma->vm_end - vma->vm_start); -	 -	if (kmem_entry->refs&KMEM_REF_COUNT) { -	    kmem_entry->refs -= vma_size / PAGE_SIZE; -	} +        /* +        	if (kmem_entry->id == 0) { +        	    mod_info("refs: %p %p %lx\n", vma, vma->vm_private_data, kmem_entry->refs); +        	    mod_info("kmem_size: %lu vma_size: %lu, s: %lx, e: %lx\n", kmem_entry->size, (vma->vm_end - vma->vm_start), vma->vm_start, vma->vm_end); +        	} +        */ + +        vma_size = (vma->vm_end - vma->vm_start); + +        if (kmem_entry->refs&KMEM_REF_COUNT) { +            kmem_entry->refs -= vma_size / PAGE_SIZE; +        }      }  } @@ -632,78 +581,66 @@ static struct vm_operations_struct pcidriver_kmem_mmap_ops = {   */  int pcidriver_mmap_kmem(pcidriver_privdata_t *privdata, struct vm_area_struct *vma)  { -	unsigned long vma_size; -	pcidriver_kmem_entry_t *kmem_entry; -	int ret; - -	mod_info_dbg("Entering mmap_kmem\n"); - -	/* FIXME: Is this really right? Always just the latest one? Can't we identify one? */ -	/* Get latest entry on the kmem_list */ -	kmem_entry = pcidriver_kmem_find_entry_id(privdata, privdata->kmem_cur_id); -	if (!kmem_entry) { -		mod_info("Trying to mmap a kernel memory buffer without creating it first!\n"); -		return -EFAULT; -	} - -	mod_info_dbg("Got kmem_entry with id: %d\n", kmem_entry->id); - -	/* Check sizes */ -	vma_size = (vma->vm_end - vma->vm_start); -	 -	if ((vma_size > kmem_entry->size) && -		((kmem_entry->size < PAGE_SIZE) && (vma_size != PAGE_SIZE))) { -		mod_info("kem_entry size(%lu) and vma size do not match(%lu)\n", kmem_entry->size, vma_size); -		return -EINVAL; -	} - -	/* reference counting */ -	if ((kmem_entry->mode&KMEM_MODE_EXCLUSIVE)&&(kmem_entry->refs&KMEM_REF_COUNT)) { -		mod_info("can't make second mmaping for exclusive kmem_entry\n"); -		return -EBUSY; -	} -	if (((kmem_entry->refs&KMEM_REF_COUNT) + (vma_size / PAGE_SIZE)) > KMEM_REF_COUNT) { -		mod_info("maximal amount of references is reached by kmem_entry\n"); -		return -EBUSY; -	} -	 -	kmem_entry->refs += vma_size / PAGE_SIZE; - -	vma->vm_flags |= (VM_RESERVED); - -#ifdef pgprot_noncached -	// This is coherent memory, so it must not be cached. -	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); -#endif - -	mod_info_dbg("Mapping address %08lx / PFN %08lx\n", -			virt_to_phys((void*)kmem_entry->cpua), -			page_to_pfn(virt_to_page((void*)kmem_entry->cpua))); - -	 if ((kmem_entry->type&PCILIB_KMEM_TYPE_MASK) == PCILIB_KMEM_TYPE_REGION) { -		ret = remap_pfn_range_compat( -					vma, -					vma->vm_start, -					kmem_entry->dma_handle, -					(vma_size < kmem_entry->size)?vma_size:kmem_entry->size, -					vma->vm_page_prot); -	 } else { -		ret = remap_pfn_range_cpua_compat( -					vma, -					vma->vm_start, -					kmem_entry->cpua, -					(vma_size < kmem_entry->size)?vma_size:kmem_entry->size, -					vma->vm_page_prot ); -	} - -	if (ret) { -		mod_info("kmem remap failed: %d (%lx)\n", ret,kmem_entry->cpua); -		kmem_entry->refs -= 1; -		return -EAGAIN; -	} - -	vma->vm_ops = &pcidriver_kmem_mmap_ops; -	vma->vm_private_data = (void*)kmem_entry; -	 -	return ret; +    unsigned long vma_size; +    pcidriver_kmem_entry_t *kmem_entry; +    int ret; + +    mod_info_dbg("Entering mmap_kmem\n"); + +    /* FIXME: Is this really right? Always just the latest one? Can't we identify one? */ +    /* Get latest entry on the kmem_list */ +    kmem_entry = pcidriver_kmem_find_entry_id(privdata, privdata->kmem_cur_id); +    if (!kmem_entry) { +        mod_info("Trying to mmap a kernel memory buffer without creating it first!\n"); +        return -EFAULT; +    } + +    mod_info_dbg("Got kmem_entry with id: %d\n", kmem_entry->id); + +    /* Check sizes */ +    vma_size = (vma->vm_end - vma->vm_start); + +    if ((vma_size > kmem_entry->size) && +            ((kmem_entry->size < PAGE_SIZE) && (vma_size != PAGE_SIZE))) { +        mod_info("kem_entry size(%lu) and vma size do not match(%lu)\n", kmem_entry->size, vma_size); +        return -EINVAL; +    } + +    /* reference counting */ +    if ((kmem_entry->mode&KMEM_MODE_EXCLUSIVE)&&(kmem_entry->refs&KMEM_REF_COUNT)) { +        mod_info("can't make second mmaping for exclusive kmem_entry\n"); +        return -EBUSY; +    } +    if (((kmem_entry->refs&KMEM_REF_COUNT) + (vma_size / PAGE_SIZE)) > KMEM_REF_COUNT) { +        mod_info("maximal amount of references is reached by kmem_entry\n"); +        return -EBUSY; +    } + +    kmem_entry->refs += vma_size / PAGE_SIZE; + +    vma->vm_flags |= (VM_RESERVED); + +    // This is coherent memory, so it must not be cached. +    vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + +    mod_info_dbg("Mapping address %08lx / PFN %08lx\n", +                 virt_to_phys((void*)kmem_entry->cpua), +                 page_to_pfn(virt_to_page((void*)kmem_entry->cpua))); + +    if ((kmem_entry->type&PCILIB_KMEM_TYPE_MASK) == PCILIB_KMEM_TYPE_REGION) { +        ret = remap_pfn_range_compat(vma, vma->vm_start, kmem_entry->dma_handle, (vma_size < kmem_entry->size)?vma_size:kmem_entry->size, vma->vm_page_prot); +    } else { +        ret = remap_pfn_range_cpua_compat(vma, vma->vm_start, kmem_entry->cpua, (vma_size < kmem_entry->size)?vma_size:kmem_entry->size, vma->vm_page_prot); +    } + +    if (ret) { +        mod_info("kmem remap failed: %d (%lx)\n", ret,kmem_entry->cpua); +        kmem_entry->refs -= 1; +        return -EAGAIN; +    } + +    vma->vm_ops = &pcidriver_kmem_mmap_ops; +    vma->vm_private_data = (void*)kmem_entry; + +    return ret;  } diff --git a/driver/pciDriver.h b/driver/pciDriver.h index 371bd88..3a231bd 100644 --- a/driver/pciDriver.h +++ b/driver/pciDriver.h @@ -1,60 +1,6 @@  #ifndef PCIDRIVER_H_  #define PCIDRIVER_H_ -/** - * This is a full rewrite of the pciDriver. - * New default is to support kernel 2.6, using kernel 2.6 APIs. - *  - * This header defines the interface to the outside world. - *  - * $Revision: 1.6 $ - * $Date: 2008-01-24 14:21:36 $ - *  - */ - -/* - * Change History: - *  - * $Log: not supported by cvs2svn $ - * Revision 1.5  2008-01-11 10:15:14  marcus - * Removed unused interrupt code. - * Added intSource to the wait interrupt call. - * - * Revision 1.4  2006/11/17 18:44:42  marcus - * Type of SG list can now be selected at runtime. Added type to sglist. - * - * Revision 1.3  2006/11/17 16:23:02  marcus - * Added slot number to the PCI info IOctl. - * - * Revision 1.2  2006/11/13 12:29:09  marcus - * Added a IOctl call, to confiure the interrupt response. (testing pending). - * Basic interrupts are now supported. - * - * Revision 1.1  2006/10/10 14:46:52  marcus - * Initial commit of the new pciDriver for kernel 2.6 - * - * Revision 1.7  2006/10/06 15:18:06  marcus - * Updated PCI info and PCI cmd - * - * Revision 1.6  2006/09/25 16:51:07  marcus - * Added PCI config IOctls, and implemented basic mmap functions. - * - * Revision 1.5  2006/09/18 17:13:12  marcus - * backup commit. - * - * Revision 1.4  2006/09/15 15:44:41  marcus - * backup commit. - * - * Revision 1.3  2006/08/15 11:40:02  marcus - * backup commit. - * - * Revision 1.2  2006/08/12 18:28:42  marcus - * Sync with the laptop - * - * Revision 1.1  2006/08/11 15:30:46  marcus - * Sync with the laptop - * - */  #include <linux/ioctl.h> @@ -152,39 +98,39 @@ typedef struct {  } pcilib_board_info_t;  typedef struct { -	unsigned long type; -	unsigned long pa; -	unsigned long ba; -	unsigned long size; -	unsigned long align; -	unsigned long use; -	unsigned long item; -	int flags; -	int handle_id; +    unsigned long type; +    unsigned long pa; +    unsigned long ba; +    unsigned long size; +    unsigned long align; +    unsigned long use; +    unsigned long item; +    int flags; +    int handle_id;  } kmem_handle_t;  typedef struct { -	unsigned long addr; -	unsigned long size; +    unsigned long addr; +    unsigned long size;  } umem_sgentry_t;  typedef struct { -	int handle_id; -	int type; -	int nents; -	umem_sgentry_t *sg; +    int handle_id; +    int type; +    int nents; +    umem_sgentry_t *sg;  } umem_sglist_t;  typedef struct { -	unsigned long vma; -	unsigned long size; -	int handle_id; -	int dir; +    unsigned long vma; +    unsigned long size; +    int handle_id; +    int dir;  } umem_handle_t;  typedef struct { -	kmem_handle_t handle; -	int dir; +    kmem_handle_t handle; +    int dir;  } kmem_sync_t;  typedef struct { @@ -194,21 +140,21 @@ typedef struct {  } interrupt_wait_t;  typedef struct { -	int size; -	int addr; -	union { -		unsigned char byte; -		unsigned short word; -		unsigned int dword; 	/* not strict C, but if not can have problems */ -	} val; +    int size; +    int addr; +    union { +        unsigned char byte; +        unsigned short word; +        unsigned int dword; 	/* not strict C, but if not can have problems */ +    } val;  } pci_cfg_cmd;  /* ioctl interface */  /* See documentation for a detailed usage explanation */ -/*  +/*   * one of the problems of ioctl, is that requires a type definition. - * This type is only 8-bits wide, and half-documented in  + * This type is only 8-bits wide, and half-documented in   * <linux-src>/Documentation/ioctl-number.txt.   * previous SHL -> 'S' definition, conflicts with several devices,   * so I changed it to be pci -> 'p', in the range 0xA0-BF diff --git a/driver/rdma.c b/driver/rdma.c index 78c6d69..c08eef9 100644 --- a/driver/rdma.c +++ b/driver/rdma.c @@ -22,26 +22,26 @@ static unsigned long pcidriver_follow_pte(struct mm_struct *mm, unsigned long ad      pmd_t *pmd;      pte_t *pte; -    spinlock_t *ptl;  +    spinlock_t *ptl;      unsigned long pfn = 0;      pgd = pgd_offset(mm, address); -    if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))  -	return 0; -         +    if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd))) +        return 0; +      pud = pud_offset(pgd, address); -    if (pud_none(*pud) || unlikely(pud_bad(*pud)))      -	return 0; +    if (pud_none(*pud) || unlikely(pud_bad(*pud))) +        return 0;      pmd = pmd_offset(pud, address); -    if (pmd_none(*pmd))  -	return 0; +    if (pmd_none(*pmd)) +        return 0;      pte = pte_offset_map_lock(mm, pmd, address, &ptl);      if (!pte_none(*pte)) -	pfn = (pte_pfn(*pte) << PAGE_SHIFT); -    pte_unmap_unlock(pte, ptl);  +        pfn = (pte_pfn(*pte) << PAGE_SHIFT); +    pte_unmap_unlock(pte, ptl);      return pfn;  } diff --git a/driver/sysfs.c b/driver/sysfs.c index abc1c8a..19865fc 100644 --- a/driver/sysfs.c +++ b/driver/sysfs.c @@ -35,46 +35,40 @@ static SYSFS_GET_FUNCTION(pcidriver_show_umem_entry);   *   */  static int _pcidriver_sysfs_initialize(pcidriver_privdata_t *privdata, -					int id, -					struct class_device_attribute *sysfs_attr, -					const char *fmtstring, -					SYSFS_GET_FUNCTION((*callback))) +                                       int id, +                                       struct class_device_attribute *sysfs_attr, +                                       const char *fmtstring, +                                       SYSFS_GET_FUNCTION((*callback)))  { -	/* sysfs attributes for kmem buffers don’t make sense before 2.6.13, as -	   we have no mmap support before */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13) -	char namebuffer[16]; +    /* sysfs attributes for kmem buffers don’t make sense before 2.6.13, as +       we have no mmap support before */ +    char namebuffer[16]; -	/* allocate space for the name of the attribute */ -	snprintf(namebuffer, sizeof(namebuffer), fmtstring, id); +    /* allocate space for the name of the attribute */ +    snprintf(namebuffer, sizeof(namebuffer), fmtstring, id); -	if ((sysfs_attr->attr.name = kstrdup(namebuffer, GFP_KERNEL)) == NULL) -		return -ENOMEM; +    if ((sysfs_attr->attr.name = kstrdup(namebuffer, GFP_KERNEL)) == NULL) +        return -ENOMEM; -	sysfs_attr->attr.mode = S_IRUGO; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) -	    // DS: Shall we lock now while accessing driver data structures??? -	sysfs_attr->attr.owner = THIS_MODULE; -#endif -	sysfs_attr->show = callback; -	sysfs_attr->store = NULL; -			 -	/* name and add attribute */ -	if (class_device_create_file(privdata->class_dev, sysfs_attr) != 0) -		return -ENXIO; /* Device not configured. Not the really best choice, but hm. */ -#endif +    sysfs_attr->attr.mode = S_IRUGO; +    sysfs_attr->show = callback; +    sysfs_attr->store = NULL; -	return 0; +    /* name and add attribute */ +    if (class_device_create_file(privdata->class_dev, sysfs_attr) != 0) +        return -ENXIO; /* Device not configured. Not the really best choice, but hm. */ + +    return 0;  }  int pcidriver_sysfs_initialize_kmem(pcidriver_privdata_t *privdata, int id, struct class_device_attribute *sysfs_attr)  { -	return _pcidriver_sysfs_initialize(privdata, id, sysfs_attr, "kbuf%d", pcidriver_show_kmem_entry); +    return _pcidriver_sysfs_initialize(privdata, id, sysfs_attr, "kbuf%d", pcidriver_show_kmem_entry);  }  int pcidriver_sysfs_initialize_umem(pcidriver_privdata_t *privdata, int id, struct class_device_attribute *sysfs_attr)  { -	return _pcidriver_sysfs_initialize(privdata, id, sysfs_attr, "umem%d", pcidriver_show_umem_entry); +    return _pcidriver_sysfs_initialize(privdata, id, sysfs_attr, "umem%d", pcidriver_show_umem_entry);  }  /** @@ -84,225 +78,210 @@ int pcidriver_sysfs_initialize_umem(pcidriver_privdata_t *privdata, int id, stru   */  void pcidriver_sysfs_remove(pcidriver_privdata_t *privdata, struct class_device_attribute *sysfs_attr)  { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13) -	class_device_remove_file(privdata->class_dev, sysfs_attr); -	kfree(sysfs_attr->attr.name); -#endif +    class_device_remove_file(privdata->class_dev, sysfs_attr); +    kfree(sysfs_attr->attr.name);  }  static SYSFS_GET_FUNCTION(pcidriver_show_kmem_entry)  { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13) -	pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; - -        /* As we can be sure that attr.name contains a filename which we -         * created (see _pcidriver_sysfs_initialize), we do not need to have -         * sanity checks but can directly call simple_strtol() */ -        int id = simple_strtol(attr->attr.name + strlen("kbuf"), NULL, 10); -	pcidriver_kmem_entry_t *entry = pcidriver_kmem_find_entry_id(privdata, id); -	if (entry) { -	    unsigned long addr = entry->cpua; -	    unsigned long dma_addr = entry->dma_handle; -	     -	    if (entry->size >= 16) { -		pcidriver_kmem_sync_entry(privdata, entry, PCILIB_KMEM_SYNC_FROMDEVICE); -		return snprintf(buf, PAGE_SIZE, "buffer: %d\naddr: %lx\nhw addr: %llx\nbus addr: %lx\ntype: %lx\nuse: 0x%lx\nitem: %lu\nsize: %lu\nrefs: %lu\nhw ref: %i\nmode: 0x%lx\ndata: %8x %8x %8x %8x\n", id, addr, virt_to_phys((void*)addr), dma_addr, entry->type, entry->use, entry->item, entry->size, entry->refs&KMEM_REF_COUNT, (entry->refs&KMEM_REF_HW)?1:0, entry->mode, *(u32*)(entry->cpua), *(u32*)(entry->cpua + 4),  *(u32*)(entry->cpua + 8), *(u32*)(entry->cpua + 12)); -	    } else -		return snprintf(buf, PAGE_SIZE, "buffer: %d\naddr: %lx\nhw addr: %llx\nbus addr: %lx\ntype: %lx\nuse: 0x%lx\nitem: %lu\nsize: %lu\nrefs: %lu\nhw ref: %i\nmode: 0x%lx\n", id, addr, virt_to_phys((void*)addr), dma_addr, entry->type, entry->use, entry->item, entry->size, entry->refs&KMEM_REF_COUNT, (entry->refs&KMEM_REF_HW)?1:0, entry->mode); -	} else -	    return snprintf(buf, PAGE_SIZE, "I am in the kmem_entry show function for buffer %d\n", id); -#else -	return 0; -#endif +    pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; + +    /* As we can be sure that attr.name contains a filename which we +     * created (see _pcidriver_sysfs_initialize), we do not need to have +     * sanity checks but can directly call simple_strtol() */ +    int id = simple_strtol(attr->attr.name + strlen("kbuf"), NULL, 10); +    pcidriver_kmem_entry_t *entry = pcidriver_kmem_find_entry_id(privdata, id); +    if (entry) { +        unsigned long addr = entry->cpua; +        unsigned long dma_addr = entry->dma_handle; + +        if (entry->size >= 16) { +            pcidriver_kmem_sync_entry(privdata, entry, PCILIB_KMEM_SYNC_FROMDEVICE); +            return snprintf(buf, PAGE_SIZE, "buffer: %d\naddr: %lx\nhw addr: %llx\nbus addr: %lx\ntype: %lx\nuse: 0x%lx\nitem: %lu\nsize: %lu\nrefs: %lu\nhw ref: %i\nmode: 0x%lx\ndata: %8x %8x %8x %8x\n", id, addr, virt_to_phys((void*)addr), dma_addr, entry->type, entry->use, entry->item, entry->size, entry->refs&KMEM_REF_COUNT, (entry->refs&KMEM_REF_HW)?1:0, entry->mode, *(u32*)(entry->cpua), *(u32*)(entry->cpua + 4),  *(u32*)(entry->cpua + 8), *(u32*)(entry->cpua + 12)); +        } else +            return snprintf(buf, PAGE_SIZE, "buffer: %d\naddr: %lx\nhw addr: %llx\nbus addr: %lx\ntype: %lx\nuse: 0x%lx\nitem: %lu\nsize: %lu\nrefs: %lu\nhw ref: %i\nmode: 0x%lx\n", id, addr, virt_to_phys((void*)addr), dma_addr, entry->type, entry->use, entry->item, entry->size, entry->refs&KMEM_REF_COUNT, (entry->refs&KMEM_REF_HW)?1:0, entry->mode); +    } else +        return snprintf(buf, PAGE_SIZE, "I am in the kmem_entry show function for buffer %d\n", id);  }  static SYSFS_GET_FUNCTION(pcidriver_show_umem_entry)  { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13) -#if 0 -	pcidriver_privdata_t *privdata = (pcidriver_privdata_t *)cls->class_data; - -	return snprintf(buf, PAGE_SIZE, "I am in the umem_entry show function, class_device_kobj_name: %s\n", cls->kobj.name); -#endif -	return 0; -#else -	return 0; -#endif +    return 0;  }  #ifdef ENABLE_IRQ  SYSFS_GET_FUNCTION(pcidriver_show_irq_count)  { -	pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; +    pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; -	return snprintf(buf, PAGE_SIZE, "%d\n", privdata->irq_count); +    return snprintf(buf, PAGE_SIZE, "%d\n", privdata->irq_count);  }  SYSFS_GET_FUNCTION(pcidriver_show_irq_queues)  { -	pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; -	int i, offset; +    pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; +    int i, offset; -	/* output will be truncated to PAGE_SIZE */ -	offset = snprintf(buf, PAGE_SIZE, "Queue\tOutstanding IRQs\n"); -	for (i = 0; i < PCIDRIVER_INT_MAXSOURCES; i++) -		offset += snprintf(buf+offset, PAGE_SIZE-offset, "%d\t%d\n", i, atomic_read(&(privdata->irq_outstanding[i])) ); +    /* output will be truncated to PAGE_SIZE */ +    offset = snprintf(buf, PAGE_SIZE, "Queue\tOutstanding IRQs\n"); +    for (i = 0; i < PCIDRIVER_INT_MAXSOURCES; i++) +        offset += snprintf(buf+offset, PAGE_SIZE-offset, "%d\t%d\n", i, atomic_read(&(privdata->irq_outstanding[i])) ); -	return (offset > PAGE_SIZE ? PAGE_SIZE : offset+1); +    return (offset > PAGE_SIZE ? PAGE_SIZE : offset+1);  }  #endif  SYSFS_GET_FUNCTION(pcidriver_show_mmap_mode)  { -	pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; +    pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; -	return snprintf(buf, PAGE_SIZE, "%d\n", privdata->mmap_mode); +    return snprintf(buf, PAGE_SIZE, "%d\n", privdata->mmap_mode);  }  SYSFS_SET_FUNCTION(pcidriver_store_mmap_mode)  { -	pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; -	int mode = -1; +    pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; +    int mode = -1; -	/* Set the mmap-mode if it is either PCIDRIVER_MMAP_PCI or PCIDRIVER_MMAP_KMEM */ -	if (sscanf(buf, "%d", &mode) == 1 && -	    (mode == PCIDRIVER_MMAP_PCI || mode == PCIDRIVER_MMAP_KMEM)) -		privdata->mmap_mode = mode; +    /* Set the mmap-mode if it is either PCIDRIVER_MMAP_PCI or PCIDRIVER_MMAP_KMEM */ +    if (sscanf(buf, "%d", &mode) == 1 && +            (mode == PCIDRIVER_MMAP_PCI || mode == PCIDRIVER_MMAP_KMEM)) +        privdata->mmap_mode = mode; -	return strlen(buf); +    return strlen(buf);  }  SYSFS_GET_FUNCTION(pcidriver_show_mmap_area)  { -	pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; +    pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; -	return snprintf(buf, PAGE_SIZE, "%d\n", privdata->mmap_area); +    return snprintf(buf, PAGE_SIZE, "%d\n", privdata->mmap_area);  }  SYSFS_SET_FUNCTION(pcidriver_store_mmap_area)  { -	pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; -	int temp = -1; +    pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; +    int temp = -1; -	sscanf(buf, "%d", &temp); +    sscanf(buf, "%d", &temp); -	if ((temp >= PCIDRIVER_BAR0) && (temp <= PCIDRIVER_BAR5)) -		privdata->mmap_area = temp; +    if ((temp >= PCIDRIVER_BAR0) && (temp <= PCIDRIVER_BAR5)) +        privdata->mmap_area = temp; -	return strlen(buf); +    return strlen(buf);  }  SYSFS_GET_FUNCTION(pcidriver_show_kmem_count)  { -	pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; +    pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; -	return snprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&(privdata->kmem_count))); +    return snprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&(privdata->kmem_count)));  }  SYSFS_SET_FUNCTION(pcidriver_store_kmem_alloc)  { -	pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; -	kmem_handle_t kmem_handle; +    pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; +    kmem_handle_t kmem_handle; -	/* FIXME: guillermo: is validation of parsing an unsigned int enough? */ -	if (sscanf(buf, "%lu", &kmem_handle.size) == 1) -		pcidriver_kmem_alloc(privdata, &kmem_handle); +    /* FIXME: guillermo: is validation of parsing an unsigned int enough? */ +    if (sscanf(buf, "%lu", &kmem_handle.size) == 1) +        pcidriver_kmem_alloc(privdata, &kmem_handle); -	return strlen(buf); +    return strlen(buf);  }  SYSFS_SET_FUNCTION(pcidriver_store_kmem_free)  { -	pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; -	unsigned int id; -	pcidriver_kmem_entry_t *kmem_entry; +    pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; +    unsigned int id; +    pcidriver_kmem_entry_t *kmem_entry; -	/* Parse the ID of the kernel memory to be freed, check bounds */ -	if (sscanf(buf, "%u", &id) != 1 || -	    (id >= atomic_read(&(privdata->kmem_count)))) -		goto err; +    /* Parse the ID of the kernel memory to be freed, check bounds */ +    if (sscanf(buf, "%u", &id) != 1 || +            (id >= atomic_read(&(privdata->kmem_count)))) +        goto err; -	if ((kmem_entry = pcidriver_kmem_find_entry_id(privdata,id)) == NULL) -		goto err; +    if ((kmem_entry = pcidriver_kmem_find_entry_id(privdata,id)) == NULL) +        goto err; -	pcidriver_kmem_free_entry(privdata, kmem_entry ); +    pcidriver_kmem_free_entry(privdata, kmem_entry );  err: -	return strlen(buf); +    return strlen(buf);  }  SYSFS_GET_FUNCTION(pcidriver_show_kbuffers)  { -	pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; -	int offset = 0; -	struct list_head *ptr; -	pcidriver_kmem_entry_t *entry; +    pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; +    int offset = 0; +    struct list_head *ptr; +    pcidriver_kmem_entry_t *entry; -	/* print the header */ -	offset += snprintf(buf, PAGE_SIZE, "kbuf#\tcpu addr\tsize\n"); +    /* print the header */ +    offset += snprintf(buf, PAGE_SIZE, "kbuf#\tcpu addr\tsize\n"); -	spin_lock(&(privdata->kmemlist_lock)); -	list_for_each(ptr, &(privdata->kmem_list)) { -		entry = list_entry(ptr, pcidriver_kmem_entry_t, list); +    spin_lock(&(privdata->kmemlist_lock)); +    list_for_each(ptr, &(privdata->kmem_list)) { +        entry = list_entry(ptr, pcidriver_kmem_entry_t, list); -		/* print entry info */ -		if (offset > PAGE_SIZE) { -			spin_unlock( &(privdata->kmemlist_lock) ); -			return PAGE_SIZE; -		} +        /* print entry info */ +        if (offset > PAGE_SIZE) { +            spin_unlock( &(privdata->kmemlist_lock) ); +            return PAGE_SIZE; +        } -		offset += snprintf(buf+offset, PAGE_SIZE-offset, "%3d\t%08lx\t%lu\n", entry->id, (unsigned long)(entry->dma_handle), entry->size ); -	} +        offset += snprintf(buf+offset, PAGE_SIZE-offset, "%3d\t%08lx\t%lu\n", entry->id, (unsigned long)(entry->dma_handle), entry->size ); +    } -	spin_unlock(&(privdata->kmemlist_lock)); +    spin_unlock(&(privdata->kmemlist_lock)); -	/* output will be truncated to PAGE_SIZE */ -	return (offset > PAGE_SIZE ? PAGE_SIZE : offset+1); +    /* output will be truncated to PAGE_SIZE */ +    return (offset > PAGE_SIZE ? PAGE_SIZE : offset+1);  }  SYSFS_GET_FUNCTION(pcidriver_show_umappings)  { -	int offset = 0; -	pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; -	struct list_head *ptr; -	pcidriver_umem_entry_t *entry; +    int offset = 0; +    pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; +    struct list_head *ptr; +    pcidriver_umem_entry_t *entry; -	/* print the header */ -	offset += snprintf(buf, PAGE_SIZE, "umap#\tn_pages\tsg_ents\n"); +    /* print the header */ +    offset += snprintf(buf, PAGE_SIZE, "umap#\tn_pages\tsg_ents\n"); -	spin_lock( &(privdata->umemlist_lock) ); -	list_for_each( ptr, &(privdata->umem_list) ) { -		entry = list_entry(ptr, pcidriver_umem_entry_t, list ); +    spin_lock( &(privdata->umemlist_lock) ); +    list_for_each( ptr, &(privdata->umem_list) ) { +        entry = list_entry(ptr, pcidriver_umem_entry_t, list ); -		/* print entry info */ -		if (offset > PAGE_SIZE) { -			spin_unlock( &(privdata->umemlist_lock) ); -			return PAGE_SIZE; -		} +        /* print entry info */ +        if (offset > PAGE_SIZE) { +            spin_unlock( &(privdata->umemlist_lock) ); +            return PAGE_SIZE; +        } -		offset += snprintf(buf+offset, PAGE_SIZE-offset, "%3d\t%lu\t%lu\n", entry->id, -				(unsigned long)(entry->nr_pages), (unsigned long)(entry->nents)); -	} +        offset += snprintf(buf+offset, PAGE_SIZE-offset, "%3d\t%lu\t%lu\n", entry->id, +                           (unsigned long)(entry->nr_pages), (unsigned long)(entry->nents)); +    } -	spin_unlock( &(privdata->umemlist_lock) ); +    spin_unlock( &(privdata->umemlist_lock) ); -	/* output will be truncated to PAGE_SIZE */ -	return (offset > PAGE_SIZE ? PAGE_SIZE : offset+1); +    /* output will be truncated to PAGE_SIZE */ +    return (offset > PAGE_SIZE ? PAGE_SIZE : offset+1);  }  SYSFS_SET_FUNCTION(pcidriver_store_umem_unmap)  { -	pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; -	pcidriver_umem_entry_t *umem_entry; -	unsigned int id; +    pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA; +    pcidriver_umem_entry_t *umem_entry; +    unsigned int id; -	if (sscanf(buf, "%u", &id) != 1 || -	    (id >= atomic_read(&(privdata->umem_count)))) -		goto err; +    if (sscanf(buf, "%u", &id) != 1 || +            (id >= atomic_read(&(privdata->umem_count)))) +        goto err; -	if ((umem_entry = pcidriver_umem_find_entry_id(privdata, id)) == NULL) -		goto err; +    if ((umem_entry = pcidriver_umem_find_entry_id(privdata, id)) == NULL) +        goto err; -	pcidriver_umem_sgunmap(privdata, umem_entry); +    pcidriver_umem_sgunmap(privdata, umem_entry);  err: -	return strlen(buf); +    return strlen(buf);  } diff --git a/driver/umem.c b/driver/umem.c index 7a8dcc1..bb9af1e 100644 --- a/driver/umem.c +++ b/driver/umem.c @@ -32,153 +32,153 @@   */  int pcidriver_umem_sgmap(pcidriver_privdata_t *privdata, umem_handle_t *umem_handle)  { -	int i, res, nr_pages; -	struct page **pages; -	struct scatterlist *sg = NULL; -	pcidriver_umem_entry_t *umem_entry; -	unsigned int nents; -	unsigned long count,offset,length; - -	/* -	 * We do some checks first. Then, the following is necessary to create a -	 * Scatter/Gather list from a user memory area: -	 *  - Determine the number of pages -	 *  - Get the pages for the memory area -	 * 	- Lock them. -	 *  - Create a scatter/gather list of the pages -	 *  - Map the list from memory to PCI bus addresses -	 * -	 * Then, we: -	 *  - Create an entry on the umem list of the device, to cache the mapping. -	 *  - Create a sysfs attribute that gives easy access to the SG list -	 */ - -	/* zero-size?? */ -	if (umem_handle->size == 0) -		return -EINVAL; - -	/* Direction is better ignoring during mapping. */ -	/* We assume bidirectional buffers always, except when sync'ing */ - -	/* calculate the number of pages */ -	nr_pages = ((umem_handle->vma & ~PAGE_MASK) + umem_handle->size + ~PAGE_MASK) >> PAGE_SHIFT; - -	mod_info_dbg("nr_pages computed: %u\n", nr_pages); - -	/* Allocate space for the page information */ -	/* This can be very big, so we use vmalloc */ -	if ((pages = vmalloc(nr_pages * sizeof(*pages))) == NULL) -		return -ENOMEM; - -	mod_info_dbg("allocated space for the pages.\n"); - -	/* Allocate space for the scatterlist */ -	/* We do not know how many entries will be, but the maximum is nr_pages. */ -	/* This can be very big, so we use vmalloc */ -	if ((sg = vmalloc(nr_pages * sizeof(*sg))) == NULL) -		goto umem_sgmap_pages; - -	sg_init_table(sg, nr_pages); - -	mod_info_dbg("allocated space for the SG list.\n"); - -	/* Get the page information */ -	down_read(¤t->mm->mmap_sem); -	res = get_user_pages( -				current, -				current->mm, -				umem_handle->vma, -				nr_pages, -				1, -				0,  /* do not force, FIXME: shall I? */ -				pages, -				NULL ); -	up_read(¤t->mm->mmap_sem); - -	/* Error, not all pages mapped */ -	if (res < (int)nr_pages) { -		mod_info("Could not map all user pages (%d of %d)\n", res, nr_pages); -		/* If only some pages could be mapped, we release those. If a real -		 * error occured, we set nr_pages to 0 */ -		nr_pages = (res > 0 ? res : 0); -		goto umem_sgmap_unmap; -	} - -	mod_info_dbg("Got the pages (%d).\n", res); - -	/* Lock the pages, then populate the SG list with the pages */ -	/* page0 is different */ -	if ( !PageReserved(pages[0]) ) -		compat_lock_page(pages[0]); - -	offset = (umem_handle->vma & ~PAGE_MASK); -	length = (umem_handle->size > (PAGE_SIZE-offset) ? (PAGE_SIZE-offset) : umem_handle->size); - -	sg_set_page(&sg[0], pages[0], length, offset); - -	count = umem_handle->size - length; -	for(i=1;i<nr_pages;i++) { -		/* Lock page first */ -		if ( !PageReserved(pages[i]) ) -			compat_lock_page(pages[i]); - -		/* Populate the list */ -		sg_set_page(&sg[i], pages[i], ((count > PAGE_SIZE) ? PAGE_SIZE : count), 0); -		count -= sg[i].length; -	} - -	/* Use the page list to populate the SG list */ -	/* SG entries may be merged, res is the number of used entries */ -	/* We have originally nr_pages entries in the sg list */ -	if ((nents = pci_map_sg(privdata->pdev, sg, nr_pages, PCI_DMA_BIDIRECTIONAL)) == 0) -		goto umem_sgmap_unmap; - -	mod_info_dbg("Mapped SG list (%d entries).\n", nents); - -	/* Add an entry to the umem_list of the device, and update the handle with the id */ -	/* Allocate space for the new umem entry */ -	if ((umem_entry = kmalloc(sizeof(*umem_entry), GFP_KERNEL)) == NULL) -		goto umem_sgmap_entry; - -	/* Fill entry to be added to the umem list */ -	umem_entry->id = atomic_inc_return(&privdata->umem_count) - 1; -	umem_entry->nr_pages = nr_pages;	/* Will be needed when unmapping */ -	umem_entry->pages = pages; -	umem_entry->nents = nents; -	umem_entry->sg = sg; - -	if (pcidriver_sysfs_initialize_umem(privdata, umem_entry->id, &(umem_entry->sysfs_attr)) != 0) -		goto umem_sgmap_name_fail; - -	/* Add entry to the umem list */ -	spin_lock( &(privdata->umemlist_lock) ); -	list_add_tail( &(umem_entry->list), &(privdata->umem_list) ); -	spin_unlock( &(privdata->umemlist_lock) ); - -	/* Update the Handle with the Handle ID of the entry */ -	umem_handle->handle_id = umem_entry->id; - -	return 0; +    int i, res, nr_pages; +    struct page **pages; +    struct scatterlist *sg = NULL; +    pcidriver_umem_entry_t *umem_entry; +    unsigned int nents; +    unsigned long count,offset,length; + +    /* +     * We do some checks first. Then, the following is necessary to create a +     * Scatter/Gather list from a user memory area: +     *  - Determine the number of pages +     *  - Get the pages for the memory area +     * 	- Lock them. +     *  - Create a scatter/gather list of the pages +     *  - Map the list from memory to PCI bus addresses +     * +     * Then, we: +     *  - Create an entry on the umem list of the device, to cache the mapping. +     *  - Create a sysfs attribute that gives easy access to the SG list +     */ + +    /* zero-size?? */ +    if (umem_handle->size == 0) +        return -EINVAL; + +    /* Direction is better ignoring during mapping. */ +    /* We assume bidirectional buffers always, except when sync'ing */ + +    /* calculate the number of pages */ +    nr_pages = ((umem_handle->vma & ~PAGE_MASK) + umem_handle->size + ~PAGE_MASK) >> PAGE_SHIFT; + +    mod_info_dbg("nr_pages computed: %u\n", nr_pages); + +    /* Allocate space for the page information */ +    /* This can be very big, so we use vmalloc */ +    if ((pages = vmalloc(nr_pages * sizeof(*pages))) == NULL) +        return -ENOMEM; + +    mod_info_dbg("allocated space for the pages.\n"); + +    /* Allocate space for the scatterlist */ +    /* We do not know how many entries will be, but the maximum is nr_pages. */ +    /* This can be very big, so we use vmalloc */ +    if ((sg = vmalloc(nr_pages * sizeof(*sg))) == NULL) +        goto umem_sgmap_pages; + +    sg_init_table(sg, nr_pages); + +    mod_info_dbg("allocated space for the SG list.\n"); + +    /* Get the page information */ +    down_read(¤t->mm->mmap_sem); +    res = get_user_pages( +              current, +              current->mm, +              umem_handle->vma, +              nr_pages, +              1, +              0,  /* do not force, FIXME: shall I? */ +              pages, +              NULL ); +    up_read(¤t->mm->mmap_sem); + +    /* Error, not all pages mapped */ +    if (res < (int)nr_pages) { +        mod_info("Could not map all user pages (%d of %d)\n", res, nr_pages); +        /* If only some pages could be mapped, we release those. If a real +         * error occured, we set nr_pages to 0 */ +        nr_pages = (res > 0 ? res : 0); +        goto umem_sgmap_unmap; +    } + +    mod_info_dbg("Got the pages (%d).\n", res); + +    /* Lock the pages, then populate the SG list with the pages */ +    /* page0 is different */ +    if ( !PageReserved(pages[0]) ) +        compat_lock_page(pages[0]); + +    offset = (umem_handle->vma & ~PAGE_MASK); +    length = (umem_handle->size > (PAGE_SIZE-offset) ? (PAGE_SIZE-offset) : umem_handle->size); + +    sg_set_page(&sg[0], pages[0], length, offset); + +    count = umem_handle->size - length; +    for(i=1; i<nr_pages; i++) { +        /* Lock page first */ +        if ( !PageReserved(pages[i]) ) +            compat_lock_page(pages[i]); + +        /* Populate the list */ +        sg_set_page(&sg[i], pages[i], ((count > PAGE_SIZE) ? PAGE_SIZE : count), 0); +        count -= sg[i].length; +    } + +    /* Use the page list to populate the SG list */ +    /* SG entries may be merged, res is the number of used entries */ +    /* We have originally nr_pages entries in the sg list */ +    if ((nents = pci_map_sg(privdata->pdev, sg, nr_pages, PCI_DMA_BIDIRECTIONAL)) == 0) +        goto umem_sgmap_unmap; + +    mod_info_dbg("Mapped SG list (%d entries).\n", nents); + +    /* Add an entry to the umem_list of the device, and update the handle with the id */ +    /* Allocate space for the new umem entry */ +    if ((umem_entry = kmalloc(sizeof(*umem_entry), GFP_KERNEL)) == NULL) +        goto umem_sgmap_entry; + +    /* Fill entry to be added to the umem list */ +    umem_entry->id = atomic_inc_return(&privdata->umem_count) - 1; +    umem_entry->nr_pages = nr_pages;	/* Will be needed when unmapping */ +    umem_entry->pages = pages; +    umem_entry->nents = nents; +    umem_entry->sg = sg; + +    if (pcidriver_sysfs_initialize_umem(privdata, umem_entry->id, &(umem_entry->sysfs_attr)) != 0) +        goto umem_sgmap_name_fail; + +    /* Add entry to the umem list */ +    spin_lock( &(privdata->umemlist_lock) ); +    list_add_tail( &(umem_entry->list), &(privdata->umem_list) ); +    spin_unlock( &(privdata->umemlist_lock) ); + +    /* Update the Handle with the Handle ID of the entry */ +    umem_handle->handle_id = umem_entry->id; + +    return 0;  umem_sgmap_name_fail: -	kfree(umem_entry); +    kfree(umem_entry);  umem_sgmap_entry: -	pci_unmap_sg( privdata->pdev, sg, nr_pages, PCI_DMA_BIDIRECTIONAL ); +    pci_unmap_sg( privdata->pdev, sg, nr_pages, PCI_DMA_BIDIRECTIONAL );  umem_sgmap_unmap: -	/* release pages */ -	if (nr_pages > 0) { -		for(i=0;i<nr_pages;i++) { -			if (PageLocked(pages[i])) -				compat_unlock_page(pages[i]); -			if (!PageReserved(pages[i])) -				set_page_dirty(pages[i]); -			page_cache_release(pages[i]); -		} -	} -	vfree(sg); +    /* release pages */ +    if (nr_pages > 0) { +        for(i=0; i<nr_pages; i++) { +            if (PageLocked(pages[i])) +                compat_unlock_page(pages[i]); +            if (!PageReserved(pages[i])) +                set_page_dirty(pages[i]); +            page_cache_release(pages[i]); +        } +    } +    vfree(sg);  umem_sgmap_pages: -	vfree(pages); -	return -ENOMEM; +    vfree(pages); +    return -ENOMEM;  } @@ -189,39 +189,39 @@ umem_sgmap_pages:   */  int pcidriver_umem_sgunmap(pcidriver_privdata_t *privdata, pcidriver_umem_entry_t *umem_entry)  { -	int i; -	pcidriver_sysfs_remove(privdata, &(umem_entry->sysfs_attr)); - -	/* Unmap user memory */ -	pci_unmap_sg( privdata->pdev, umem_entry->sg, umem_entry->nr_pages, PCI_DMA_BIDIRECTIONAL ); - -	/* Release the pages */ -	if (umem_entry->nr_pages > 0) { -		for(i=0;i<(umem_entry->nr_pages);i++) { -			/* Mark pages as Dirty and unlock it */ -			if ( !PageReserved( umem_entry->pages[i] )) { -				SetPageDirty( umem_entry->pages[i] ); -				compat_unlock_page(umem_entry->pages[i]); -			} -			/* and release it from the cache */ -			page_cache_release( umem_entry->pages[i] ); -		} -	} - -	/* Remove the umem list entry */ -	spin_lock( &(privdata->umemlist_lock) ); -	list_del( &(umem_entry->list) ); -	spin_unlock( &(privdata->umemlist_lock) ); - -	/* Release SG list and page list memory */ -	/* These two are in the vm area of the kernel */ -	vfree(umem_entry->pages); -	vfree(umem_entry->sg); - -	/* Release umem_entry memory */ -	kfree(umem_entry); - -	return 0; +    int i; +    pcidriver_sysfs_remove(privdata, &(umem_entry->sysfs_attr)); + +    /* Unmap user memory */ +    pci_unmap_sg( privdata->pdev, umem_entry->sg, umem_entry->nr_pages, PCI_DMA_BIDIRECTIONAL ); + +    /* Release the pages */ +    if (umem_entry->nr_pages > 0) { +        for(i=0; i<(umem_entry->nr_pages); i++) { +            /* Mark pages as Dirty and unlock it */ +            if ( !PageReserved( umem_entry->pages[i] )) { +                SetPageDirty( umem_entry->pages[i] ); +                compat_unlock_page(umem_entry->pages[i]); +            } +            /* and release it from the cache */ +            page_cache_release( umem_entry->pages[i] ); +        } +    } + +    /* Remove the umem list entry */ +    spin_lock( &(privdata->umemlist_lock) ); +    list_del( &(umem_entry->list) ); +    spin_unlock( &(privdata->umemlist_lock) ); + +    /* Release SG list and page list memory */ +    /* These two are in the vm area of the kernel */ +    vfree(umem_entry->pages); +    vfree(umem_entry->sg); + +    /* Release umem_entry memory */ +    kfree(umem_entry); + +    return 0;  }  /** @@ -231,16 +231,16 @@ int pcidriver_umem_sgunmap(pcidriver_privdata_t *privdata, pcidriver_umem_entry_   */  int pcidriver_umem_sgunmap_all(pcidriver_privdata_t *privdata)  { -	struct list_head *ptr, *next; -	pcidriver_umem_entry_t *umem_entry; +    struct list_head *ptr, *next; +    pcidriver_umem_entry_t *umem_entry; -	/* iterate safely over the entries and delete them */ -	list_for_each_safe( ptr, next, &(privdata->umem_list) ) { -		umem_entry = list_entry(ptr, pcidriver_umem_entry_t, list ); -		pcidriver_umem_sgunmap( privdata, umem_entry ); 		/* spin lock inside! */ -	} +    /* iterate safely over the entries and delete them */ +    list_for_each_safe( ptr, next, &(privdata->umem_list) ) { +        umem_entry = list_entry(ptr, pcidriver_umem_entry_t, list ); +        pcidriver_umem_sgunmap( privdata, umem_entry ); 		/* spin lock inside! */ +    } -	return 0; +    return 0;  }  /** @@ -250,117 +250,68 @@ int pcidriver_umem_sgunmap_all(pcidriver_privdata_t *privdata)   */  int pcidriver_umem_sgget(pcidriver_privdata_t *privdata, umem_sglist_t *umem_sglist)  { -	int i; -	pcidriver_umem_entry_t *umem_entry; -	struct scatterlist *sg; -	int idx = 0; -	dma_addr_t cur_addr; -	unsigned int cur_size; - -	/* Find the associated umem_entry for this buffer */ -	umem_entry = pcidriver_umem_find_entry_id( privdata, umem_sglist->handle_id ); -	if (umem_entry == NULL) -		return -EINVAL;					/* umem_handle is not valid */ - -	/* Check if passed SG list is enough */ -	if (umem_sglist->nents < umem_entry->nents) -		return -EINVAL;					/* sg has not enough entries */ - -	/* Copy the SG list to the user format */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) -	if (umem_sglist->type == PCIDRIVER_SG_MERGED) { -		for_each_sg(umem_entry->sg, sg, umem_entry->nents, i ) { -			if (i==0) { -				umem_sglist->sg[0].addr = sg_dma_address( sg ); -				umem_sglist->sg[0].size = sg_dma_len( sg ); -				idx = 0; -			} -			else { -				cur_addr = sg_dma_address( sg ); -				cur_size = sg_dma_len( sg ); - -				/* Check if entry fits after current entry */ -				if (cur_addr == (umem_sglist->sg[idx].addr + umem_sglist->sg[idx].size)) { -					umem_sglist->sg[idx].size += cur_size; -					continue; -				} - -				/* Skip if the entry is zero-length (yes, it can happen.... at the end of the list) */ -				if (cur_size == 0) -					continue; - -				/* None of the above, add new entry */ -				idx++; -				umem_sglist->sg[idx].addr = cur_addr; -				umem_sglist->sg[idx].size = cur_size; -			} -		} -		/* Set the used size of the SG list */ -		umem_sglist->nents = idx+1; -	} else { -		for_each_sg(umem_entry->sg, sg, umem_entry->nents, i ) { -			mod_info("entry: %d\n",i); -			umem_sglist->sg[i].addr = sg_dma_address( sg ); -			umem_sglist->sg[i].size = sg_dma_len( sg ); -		} - -		/* Set the used size of the SG list */ -		/* Check if the last one is zero-length */ -		if ( umem_sglist->sg[ umem_entry->nents - 1].size == 0) -			umem_sglist->nents = umem_entry->nents -1; -		else -			umem_sglist->nents = umem_entry->nents; -	} -#else -	if (umem_sglist->type == PCIDRIVER_SG_MERGED) { -		/* Merge entries that are contiguous into a single entry */ -		/* Non-optimal but fast for most cases */ -		/* First one always true */ -		sg=umem_entry->sg; -		umem_sglist->sg[0].addr = sg_dma_address( sg ); -		umem_sglist->sg[0].size = sg_dma_len( sg ); -		sg++; -		idx = 0; - -		/* Iterate over the SG entries */ -		for(i=1; i< umem_entry->nents; i++, sg++ ) { -			cur_addr = sg_dma_address( sg ); -			cur_size = sg_dma_len( sg ); - -			/* Check if entry fits after current entry */ -			if (cur_addr == (umem_sglist->sg[idx].addr + umem_sglist->sg[idx].size)) { -				umem_sglist->sg[idx].size += cur_size; -				continue; -			} - -			/* Skip if the entry is zero-length (yes, it can happen.... at the end of the list) */ -			if (cur_size == 0) -				continue; - -			/* None of the above, add new entry */ -			idx++; -			umem_sglist->sg[idx].addr = cur_addr; -			umem_sglist->sg[idx].size = cur_size; -		} -		/* Set the used size of the SG list */ -		umem_sglist->nents = idx+1; -	} else { -		/* Assume pci_map_sg made a good job (ehem..) and just copy it. -		 * actually, now I assume it just gives them plainly to me. */ -		for(i=0, sg=umem_entry->sg ; i< umem_entry->nents; i++, sg++ ) { -			umem_sglist->sg[i].addr = sg_dma_address( sg ); -			umem_sglist->sg[i].size = sg_dma_len( sg ); -		} -		/* Set the used size of the SG list */ -		/* Check if the last one is zero-length */ -		if ( umem_sglist->sg[ umem_entry->nents - 1].size == 0) -			umem_sglist->nents = umem_entry->nents -1; -		else -			umem_sglist->nents = umem_entry->nents; -	} -#endif - -	return 0; +    int i; +    pcidriver_umem_entry_t *umem_entry; +    struct scatterlist *sg; +    int idx = 0; +    dma_addr_t cur_addr; +    unsigned int cur_size; + +    /* Find the associated umem_entry for this buffer */ +    umem_entry = pcidriver_umem_find_entry_id( privdata, umem_sglist->handle_id ); +    if (umem_entry == NULL) +        return -EINVAL;					/* umem_handle is not valid */ + +    /* Check if passed SG list is enough */ +    if (umem_sglist->nents < umem_entry->nents) +        return -EINVAL;					/* sg has not enough entries */ + +    /* Copy the SG list to the user format */ +    if (umem_sglist->type == PCIDRIVER_SG_MERGED) { +        for_each_sg(umem_entry->sg, sg, umem_entry->nents, i ) { +            if (i==0) { +                umem_sglist->sg[0].addr = sg_dma_address( sg ); +                umem_sglist->sg[0].size = sg_dma_len( sg ); +                idx = 0; +            } +            else { +                cur_addr = sg_dma_address( sg ); +                cur_size = sg_dma_len( sg ); + +                /* Check if entry fits after current entry */ +                if (cur_addr == (umem_sglist->sg[idx].addr + umem_sglist->sg[idx].size)) { +                    umem_sglist->sg[idx].size += cur_size; +                    continue; +                } + +                /* Skip if the entry is zero-length (yes, it can happen.... at the end of the list) */ +                if (cur_size == 0) +                    continue; + +                /* None of the above, add new entry */ +                idx++; +                umem_sglist->sg[idx].addr = cur_addr; +                umem_sglist->sg[idx].size = cur_size; +            } +        } +        /* Set the used size of the SG list */ +        umem_sglist->nents = idx+1; +    } else { +        for_each_sg(umem_entry->sg, sg, umem_entry->nents, i ) { +            mod_info("entry: %d\n",i); +            umem_sglist->sg[i].addr = sg_dma_address( sg ); +            umem_sglist->sg[i].size = sg_dma_len( sg ); +        } + +        /* Set the used size of the SG list */ +        /* Check if the last one is zero-length */ +        if ( umem_sglist->sg[ umem_entry->nents - 1].size == 0) +            umem_sglist->nents = umem_entry->nents -1; +        else +            umem_sglist->nents = umem_entry->nents; +    } + +    return 0;  }  /** @@ -370,45 +321,29 @@ int pcidriver_umem_sgget(pcidriver_privdata_t *privdata, umem_sglist_t *umem_sgl   */  int pcidriver_umem_sync( pcidriver_privdata_t *privdata, umem_handle_t *umem_handle )  { -	pcidriver_umem_entry_t *umem_entry; - -	/* Find the associated umem_entry for this buffer */ -	umem_entry = pcidriver_umem_find_entry_id( privdata, umem_handle->handle_id ); -	if (umem_entry == NULL) -		return -EINVAL;					/* umem_handle is not valid */ - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) -	switch (umem_handle->dir) { -		case PCIDRIVER_DMA_TODEVICE: -			pci_dma_sync_sg_for_device( privdata->pdev, umem_entry->sg, umem_entry->nents, PCI_DMA_TODEVICE ); -			break; -		case PCIDRIVER_DMA_FROMDEVICE: -			pci_dma_sync_sg_for_cpu( privdata->pdev, umem_entry->sg, umem_entry->nents, PCI_DMA_FROMDEVICE ); -			break; -		case PCIDRIVER_DMA_BIDIRECTIONAL: -			pci_dma_sync_sg_for_device( privdata->pdev, umem_entry->sg, umem_entry->nents, PCI_DMA_BIDIRECTIONAL ); -			pci_dma_sync_sg_for_cpu( privdata->pdev, umem_entry->sg, umem_entry->nents, PCI_DMA_BIDIRECTIONAL ); -			break; -		default: -			return -EINVAL;				/* wrong direction parameter */ -	} -#else -	switch (umem_handle->dir) { -		case PCIDRIVER_DMA_TODEVICE: -			pci_dma_sync_sg( privdata->pdev, umem_entry->sg, umem_entry->nents, PCI_DMA_TODEVICE ); -			break; -		case PCIDRIVER_DMA_FROMDEVICE: -			pci_dma_sync_sg( privdata->pdev, umem_entry->sg, umem_entry->nents, PCI_DMA_FROMDEVICE ); -			break; -		case PCIDRIVER_DMA_BIDIRECTIONAL: -			pci_dma_sync_sg( privdata->pdev, umem_entry->sg, umem_entry->nents, PCI_DMA_BIDIRECTIONAL ); -			break; -		default: -			return -EINVAL;				/* wrong direction parameter */ -	} -#endif - -	return 0; +    pcidriver_umem_entry_t *umem_entry; + +    /* Find the associated umem_entry for this buffer */ +    umem_entry = pcidriver_umem_find_entry_id( privdata, umem_handle->handle_id ); +    if (umem_entry == NULL) +        return -EINVAL;					/* umem_handle is not valid */ + +    switch (umem_handle->dir) { +    case PCIDRIVER_DMA_TODEVICE: +        pci_dma_sync_sg_for_device( privdata->pdev, umem_entry->sg, umem_entry->nents, PCI_DMA_TODEVICE ); +        break; +    case PCIDRIVER_DMA_FROMDEVICE: +        pci_dma_sync_sg_for_cpu( privdata->pdev, umem_entry->sg, umem_entry->nents, PCI_DMA_FROMDEVICE ); +        break; +    case PCIDRIVER_DMA_BIDIRECTIONAL: +        pci_dma_sync_sg_for_device( privdata->pdev, umem_entry->sg, umem_entry->nents, PCI_DMA_BIDIRECTIONAL ); +        pci_dma_sync_sg_for_cpu( privdata->pdev, umem_entry->sg, umem_entry->nents, PCI_DMA_BIDIRECTIONAL ); +        break; +    default: +        return -EINVAL;				/* wrong direction parameter */ +    } + +    return 0;  }  /* @@ -420,19 +355,19 @@ int pcidriver_umem_sync( pcidriver_privdata_t *privdata, umem_handle_t *umem_han   */  pcidriver_umem_entry_t *pcidriver_umem_find_entry_id(pcidriver_privdata_t *privdata, int id)  { -	struct list_head *ptr; -	pcidriver_umem_entry_t *entry; +    struct list_head *ptr; +    pcidriver_umem_entry_t *entry; -	spin_lock(&(privdata->umemlist_lock)); -	list_for_each(ptr, &(privdata->umem_list)) { -		entry = list_entry(ptr, pcidriver_umem_entry_t, list ); +    spin_lock(&(privdata->umemlist_lock)); +    list_for_each(ptr, &(privdata->umem_list)) { +        entry = list_entry(ptr, pcidriver_umem_entry_t, list ); -		if (entry->id == id) { -			spin_unlock( &(privdata->umemlist_lock) ); -			return entry; -		} -	} +        if (entry->id == id) { +            spin_unlock( &(privdata->umemlist_lock) ); +            return entry; +        } +    } -	spin_unlock(&(privdata->umemlist_lock)); -	return NULL; +    spin_unlock(&(privdata->umemlist_lock)); +    return NULL;  }  | 
