diff options
| author | Suren A. Chilingaryan <csa@suren.me> | 2015-11-19 03:19:51 +0100 | 
|---|---|---|
| committer | Suren A. Chilingaryan <csa@suren.me> | 2015-11-19 03:19:51 +0100 | 
| commit | 6191a86bf2de5413cc9100e1450b541e5dfcb8f9 (patch) | |
| tree | c4edeb5e91aa4098c55d01a00f2d292d0635ae61 | |
| parent | 46754246bddd1c15d61e915bd860448bab8d7400 (diff) | |
Support setting payload size
| -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 | ||||
| -rw-r--r-- | pcilib/pci.c | 7 | ||||
| -rw-r--r-- | pcilib/pci.h | 1 | ||||
| -rw-r--r-- | pcitool/cli.c | 19 | 
8 files changed, 88 insertions, 8 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 diff --git a/pcilib/pci.c b/pcilib/pci.c index 26dfdbf..eaf41ac 100644 --- a/pcilib/pci.c +++ b/pcilib/pci.c @@ -483,3 +483,10 @@ int pcilib_set_dma_mask(pcilib_t *ctx, int mask) {      return 0;  } + +int pcilib_set_mps(pcilib_t *ctx, int mps) { +    if (ioctl(ctx->handle, PCIDRIVER_IOC_MPS, mps) < 0) +	return PCILIB_ERROR_FAILED; + +    return 0; +} diff --git a/pcilib/pci.h b/pcilib/pci.h index b81d295..43de485 100644 --- a/pcilib/pci.h +++ b/pcilib/pci.h @@ -124,6 +124,7 @@ int pcilib_map_register_space(pcilib_t *ctx);  int pcilib_map_data_space(pcilib_t *ctx, uintptr_t addr);  int pcilib_set_dma_mask(pcilib_t *ctx, int mask); +int pcilib_set_mps(pcilib_t *ctx, int mps);  #ifdef __cplusplus  } diff --git a/pcitool/cli.c b/pcitool/cli.c index 65e24dc..dbc7f47 100644 --- a/pcitool/cli.c +++ b/pcitool/cli.c @@ -97,6 +97,7 @@ typedef enum {      MODE_ACK_IRQ,      MODE_WAIT_IRQ,      MODE_SET_DMASK, +    MODE_SET_MPS,      MODE_ALLOC_KMEM,      MODE_LIST_KMEM,      MODE_READ_KMEM, @@ -173,6 +174,7 @@ typedef enum {      OPT_WAIT_IRQ,      OPT_ITERATIONS,      OPT_SET_DMASK, +    OPT_SET_MPS,      OPT_ALLOC_KMEM,      OPT_LIST_KMEM,      OPT_FREE_KMEM, @@ -227,6 +229,7 @@ static struct option long_options[] = {      {"acknowledge-irq",		optional_argument, 0, OPT_ACK_IRQ },      {"wait-irq",		optional_argument, 0, OPT_WAIT_IRQ },      {"set-dma-mask",		required_argument, 0, OPT_SET_DMASK }, +    {"set-mps",			required_argument, 0, OPT_SET_MPS },      {"list-kernel-memory",	optional_argument, 0, OPT_LIST_KMEM },      {"read-kernel-memory",	required_argument, 0, OPT_READ_KMEM },      {"alloc-kernel-memory",	required_argument, 0, OPT_ALLOC_KMEM }, @@ -303,8 +306,11 @@ void Usage(int argc, char *argv[], const char *format, ...) {  "   --list-dma-buffers <dma>	- List buffers for specified DMA engine\n"  "   --read-dma-buffer <dma:buf>	- Read the specified buffer\n"  "\n" -"  Kernel Modes:\n" +"  PCI Configuration:\n"  "   --set-dma-mask [bits]	- Set DMA address width (DANGEROUS)\n" +"   --set-mps [bits]		- Set PCIe Payload Size (DANGEROUS)\n" +"\n" +"  Kernel Memory Modes:\n"  "   --list-kernel-memory [use] 	- List kernel buffers\n"  "   --read-kernel-memory <blk>	- Read the specified block of the kernel memory\n"  "				  block is specified as: use:block_number\n" @@ -3089,6 +3095,7 @@ int main(int argc, char **argv) {      size_t iterations = BENCHMARK_ITERATIONS;      unsigned long dma_mask = 0; +    unsigned long pcie_mps = 0;      pcilib_t *handle; @@ -3290,6 +3297,13 @@ int main(int argc, char **argv) {  		if ((!isnumber(optarg))||(sscanf(optarg, "%lu", &dma_mask) != 1)||(dma_mask<24)||(dma_mask>64))  			Usage(argc, argv, "Invalid DMA mask is specified (%s)", optarg);  	    break; +	    case OPT_SET_MPS: +		if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported"); +		mode = MODE_SET_MPS; + +		if ((!isnumber(optarg))||(sscanf(optarg, "%lu", &pcie_mps) != 1)||(pcie_mps<128)||(pcie_mps>2048)) +			Usage(argc, argv, "Invalid payload size is specified (%s)", optarg); +	    break;  	    case OPT_LIST_KMEM:  		if (mode != MODE_INVALID) Usage(argc, argv, "Multiple operations are not supported");  		mode = MODE_LIST_KMEM; @@ -3888,6 +3902,9 @@ int main(int argc, char **argv) {       case MODE_SET_DMASK:          pcilib_set_dma_mask(handle, dma_mask);       break; +     case MODE_SET_MPS: +        pcilib_set_mps(handle, pcie_mps); +     break;       case MODE_LIST_KMEM:          if (use) DetailKMEM(handle, fpga_device, use, block);          else ListKMEM(handle, fpga_device); | 
