diff options
-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); |