summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--driver/Makefile2
-rw-r--r--driver/compat.c26
-rw-r--r--driver/compat.h3
-rw-r--r--driver/ioctl.c30
-rw-r--r--driver/pciDriver.h8
-rw-r--r--pcilib/pci.c7
-rw-r--r--pcilib/pci.h1
-rw-r--r--pcitool/cli.c19
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);