summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuren A. Chilingaryan <csa@suren.me>2015-11-18 06:28:28 +0100
committerSuren A. Chilingaryan <csa@suren.me>2015-11-18 06:28:28 +0100
commite30eddc0aeb368814d2bbe0031e6b6ed768bdfcf (patch)
treedf52925dedd955f40b7f861fc223a9766ae3fe15
parent815924bac97aed5e4b662d5aafeed9634b82af4a (diff)
downloadpcitool-e30eddc0aeb368814d2bbe0031e6b6ed768bdfcf.tar.gz
pcitool-e30eddc0aeb368814d2bbe0031e6b6ed768bdfcf.tar.bz2
pcitool-e30eddc0aeb368814d2bbe0031e6b6ed768bdfcf.tar.xz
pcitool-e30eddc0aeb368814d2bbe0031e6b6ed768bdfcf.zip
Enforce 64-bit dma mask from IPEDMA if supported
-rw-r--r--dma/ipe.c12
-rw-r--r--dma/ipe_private.h3
-rw-r--r--driver/ioctl.c30
-rw-r--r--driver/pciDriver.h3
-rw-r--r--pcilib/pci.c7
-rw-r--r--pcilib/pci.h2
6 files changed, 56 insertions, 1 deletions
diff --git a/dma/ipe.c b/dma/ipe.c
index 56c65ca..460d2a0 100644
--- a/dma/ipe.c
+++ b/dma/ipe.c
@@ -111,6 +111,8 @@ void dma_ipe_free(pcilib_dma_context_t *vctx) {
int dma_ipe_start(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, pcilib_dma_flags_t flags) {
+ int err;
+ int mask = 32;
size_t i, num_pages;
ipe_dma_t *ctx = (ipe_dma_t*)vctx;
@@ -160,6 +162,16 @@ int dma_ipe_start(pcilib_dma_context_t *vctx, pcilib_dma_engine_t dma, pcilib_dm
else
ctx->dma_flags = 0;
+#ifdef IPEDMA_CONFIGURE_DMA_MASK
+ if (ctx->version >= 3) mask = 64;
+
+ err = pcilib_set_dma_mask(ctx->dmactx.pcilib, mask);
+ if (err) {
+ pcilib_error("Error (%i) configuring dma mask (%i)", err, mask);
+ return err;
+ }
+#endif /* IPEDMA_CONFIGURE_DMA_MASK */
+
kflags = PCILIB_KMEM_FLAG_REUSE|PCILIB_KMEM_FLAG_EXCLUSIVE|PCILIB_KMEM_FLAG_HARDWARE|(ctx->preserve?PCILIB_KMEM_FLAG_PERSISTENT:0);
pcilib_kmem_handle_t *desc = pcilib_alloc_kernel_memory(ctx->dmactx.pcilib, PCILIB_KMEM_TYPE_CONSISTENT, 1, IPEDMA_DESCRIPTOR_SIZE, IPEDMA_DESCRIPTOR_ALIGNMENT, PCILIB_KMEM_USE(PCILIB_KMEM_USE_DMA_RING, 0x00), kflags);
pcilib_kmem_handle_t *pages = pcilib_alloc_kernel_memory(ctx->dmactx.pcilib, PCILIB_KMEM_TYPE_DMA_C2S_PAGE, IPEDMA_DMA_PAGES, 0, 0, PCILIB_KMEM_USE(PCILIB_KMEM_USE_DMA_PAGES, 0x00), kflags);
diff --git a/dma/ipe_private.h b/dma/ipe_private.h
index 640b6a0..655a485 100644
--- a/dma/ipe_private.h
+++ b/dma/ipe_private.h
@@ -17,7 +17,8 @@
//#define IPEDMA_BUG_LAST_READ /**< We should forbid writting the second last available DMA buffer (the last is forbidden by design) */
//#define IPEDMA_DETECT_PACKETS /**< Using empty_deceted flag */
-#define IPEDMA_SUPPORT_EMPTY_DETECTED /**< Avoid waiting for data when empty_detected flag is set in hardware */
+#define IPEDMA_SUPPORT_EMPTY_DETECTED /**< Avoid waiting for data when empty_detected flag is set in hardware */
+#define IPEDMA_CONFIGURE_DMA_MASK /**< Enforce maximal DMA mask (to avoid bounce-buffers) */
#define IPEDMA_REG_ADDR_MASK 0xFFF
#define IPEDMA_REG_BANK_MASK 0xF000
diff --git a/driver/ioctl.c b/driver/ioctl.c
index 2d4af73..a78d366 100644
--- a/driver/ioctl.c
+++ b/driver/ioctl.c
@@ -406,6 +406,33 @@ static int ioctl_clear_ioq(pcidriver_privdata_t *privdata, unsigned long arg)
#endif
}
+
+/**
+ *
+ * Sets DMA mask for the following DMA mappings.
+ *
+ * @param arg Not a pointer, but a number of bits
+ *
+ */
+static int ioctl_set_dma_mask(pcidriver_privdata_t *privdata, unsigned long arg)
+{
+ int err;
+
+ if ((arg < 24) && (arg > 63))
+ return -EINVAL;
+
+ err = pci_set_dma_mask(privdata->pdev, DMA_BIT_MASK(arg));
+ if (err < 0) {
+ printk(KERN_ERR "pci_set_dma_mask(%lu) failed\n", arg);
+ return err;
+ }
+
+ printk(KERN_ERR "pci_set_dma_mask(%lu) successeded\n", arg);
+
+ return 0;
+}
+
+
/**
*
* This function handles all ioctl file operations.
@@ -465,6 +492,9 @@ long pcidriver_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
case PCIDRIVER_IOC_CLEAR_IOQ:
return ioctl_clear_ioq(privdata, arg);
+ case PCIDRIVER_IOC_SET_DMA_MASK:
+ return ioctl_set_dma_mask(privdata, arg);
+
default:
return -EINVAL;
}
diff --git a/driver/pciDriver.h b/driver/pciDriver.h
index f16b721..845fc15 100644
--- a/driver/pciDriver.h
+++ b/driver/pciDriver.h
@@ -217,4 +217,7 @@ typedef struct {
/* Clear interrupt queues */
#define PCIDRIVER_IOC_CLEAR_IOQ _IO( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 13 )
+#define PCIDRIVER_IOC_SET_DMA_MASK _IO( PCIDRIVER_IOC_MAGIC, PCIDRIVER_IOC_BASE + 14 )
+
+
#endif
diff --git a/pcilib/pci.c b/pcilib/pci.c
index 4b8b8bb..e45aaba 100644
--- a/pcilib/pci.c
+++ b/pcilib/pci.c
@@ -431,3 +431,10 @@ const pcilib_pcie_link_info_t *pcilib_get_pcie_link_info(pcilib_t *ctx) {
return &ctx->link_info;
}
+
+int pcilib_set_dma_mask(pcilib_t *ctx, int mask) {
+ if (ioctl( ctx->handle, PCIDRIVER_IOC_SET_DMA_MASK, mask ) < 0)
+ return PCILIB_ERROR_FAILED;
+
+ return 0;
+}
diff --git a/pcilib/pci.h b/pcilib/pci.h
index 50c6c0e..bf977fc 100644
--- a/pcilib/pci.h
+++ b/pcilib/pci.h
@@ -118,6 +118,8 @@ const pcilib_pcie_link_info_t *pcilib_get_pcie_link_info(pcilib_t *ctx);
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);
+
#ifdef __cplusplus
}
#endif