summaryrefslogtreecommitdiffstats
path: root/driver
diff options
context:
space:
mode:
authorSuren A. Chilingaryan <csa@suren.me>2015-11-19 03:19:51 +0100
committerSuren A. Chilingaryan <csa@suren.me>2015-11-19 03:19:51 +0100
commit6191a86bf2de5413cc9100e1450b541e5dfcb8f9 (patch)
treec4edeb5e91aa4098c55d01a00f2d292d0635ae61 /driver
parent46754246bddd1c15d61e915bd860448bab8d7400 (diff)
downloadpcitool-6191a86bf2de5413cc9100e1450b541e5dfcb8f9.tar.gz
pcitool-6191a86bf2de5413cc9100e1450b541e5dfcb8f9.tar.bz2
pcitool-6191a86bf2de5413cc9100e1450b541e5dfcb8f9.tar.xz
pcitool-6191a86bf2de5413cc9100e1450b541e5dfcb8f9.zip
Support setting payload size
Diffstat (limited to 'driver')
-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
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