diff options
Diffstat (limited to 'driver')
| -rw-r--r-- | driver/Makefile | 2 | ||||
| -rw-r--r-- | driver/compat.c | 26 | ||||
| -rw-r--r-- | driver/compat.h | 3 | ||||
| -rw-r--r-- | driver/ioctl.c | 30 | ||||
| -rw-r--r-- | driver/pciDriver.h | 8 | 
5 files changed, 62 insertions, 7 deletions
diff --git a/driver/Makefile b/driver/Makefile index 3a242dd..83a8c46 100644 --- a/driver/Makefile +++ b/driver/Makefile @@ -1,6 +1,6 @@  obj-m := pciDriver.o -pciDriver-objs := base.o int.o umem.o kmem.o sysfs.o ioctl.o +pciDriver-objs := base.o int.o umem.o kmem.o sysfs.o ioctl.o compat.o  KERNELDIR ?= /lib/modules/$(shell uname -r)/build  INSTALLDIR ?= /lib/modules/$(shell uname -r)/kernel/extra diff --git a/driver/compat.c b/driver/compat.c new file mode 100644 index 0000000..a632781 --- /dev/null +++ b/driver/compat.c @@ -0,0 +1,26 @@ +#include <linux/pci.h> + +int pcidriver_pcie_get_mps(struct pci_dev *dev) +{ +        u16 ctl; + +        pcie_capability_read_word(dev, PCI_EXP_DEVCTL, &ctl); + +        return 128 << ((ctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5); +} + +int pcidriver_pcie_set_mps(struct pci_dev *dev, int mps) +{ +        u16 v; + +        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; + +        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 25e402a..fd3f188 100644 --- a/driver/compat.h +++ b/driver/compat.h @@ -195,4 +195,7 @@ static inline void set_pages_reserved_compat(unsigned long cpua, unsigned long s  #endif  } +int pcidriver_pcie_get_mps(struct pci_dev *dev); +int pcidriver_pcie_set_mps(struct pci_dev *dev, int mps); +  #endif diff --git a/driver/ioctl.c b/driver/ioctl.c index e003476..67cdc52 100644 --- a/driver/ioctl.c +++ b/driver/ioctl.c @@ -433,7 +433,6 @@ static int ioctl_version(pcidriver_privdata_t *privdata, unsigned long arg)  	return 0;  } -  /**   *   * Gets current device and driver configuration @@ -448,6 +447,7 @@ static int ioctl_device_state(pcidriver_privdata_t *privdata, unsigned long arg)  	info = (pcilib_device_state_t) {  	    .iommu = iommu_present(privdata->pdev->dev.bus), +	    .mps = pcidriver_pcie_get_mps(privdata->pdev),  	    .dma_mask = privdata->pdev->dma_mask  	}; @@ -468,7 +468,7 @@ static int ioctl_set_dma_mask(pcidriver_privdata_t *privdata, unsigned long arg)  {  	int err; -	if ((arg < 24) && (arg > 63)) +	if ((arg < 24) || (arg > 64))  		return -EINVAL;  	err = pci_set_dma_mask(privdata->pdev, DMA_BIT_MASK(arg)); @@ -477,8 +477,29 @@ static int ioctl_set_dma_mask(pcidriver_privdata_t *privdata, unsigned long arg)  	    return err;  	} -	printk(KERN_ERR "pci_set_dma_mask(%lu) successeded\n", arg); +	return 0; +} + +/** + * + * Sets Max Payload Size. + * + * @param arg Not a pointer, but payload size in bits + * + */ +static int ioctl_set_mps(pcidriver_privdata_t *privdata, unsigned long arg) +{ +	int err; +	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; +	} +	  	return 0;  } @@ -551,6 +572,9 @@ long pcidriver_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)  		case PCIDRIVER_IOC_DMA_MASK:  			return ioctl_set_dma_mask(privdata, arg); +		case PCIDRIVER_IOC_MPS: +			return ioctl_set_mps(privdata, arg); +  		default:  			return -EINVAL;  	} diff --git a/driver/pciDriver.h b/driver/pciDriver.h index d314952..2fda0ff 100644 --- a/driver/pciDriver.h +++ b/driver/pciDriver.h @@ -130,8 +130,9 @@ typedef struct {  } pcilib_driver_version_t;  typedef struct { -    unsigned long iommu; -    unsigned long dma_mask; +    int iommu;						/**< Specifies if IOMMU is enabled or disabled */ +    int mps;						/**< Maximum payload size */ +    unsigned long dma_mask;				/**< DMA mask */  } pcilib_device_state_t;  typedef struct { @@ -235,7 +236,8 @@ typedef struct {  #define PCIDRIVER_IOC_VERSION		_IOR(  PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 14, pcilib_driver_version_t * )  #define PCIDRIVER_IOC_DEVICE_STATE	_IOR(  PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 15, pcilib_device_state_t * )  #define PCIDRIVER_IOC_DMA_MASK		_IO(   PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 16) +#define PCIDRIVER_IOC_MPS		_IO(   PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 17) -#define PCIDRIVER_IOC_MAX 16 +#define PCIDRIVER_IOC_MAX 17  #endif  | 
