From e30eddc0aeb368814d2bbe0031e6b6ed768bdfcf Mon Sep 17 00:00:00 2001 From: "Suren A. Chilingaryan" Date: Wed, 18 Nov 2015 06:28:28 +0100 Subject: Enforce 64-bit dma mask from IPEDMA if supported --- dma/ipe.c | 12 ++++++++++++ dma/ipe_private.h | 3 ++- driver/ioctl.c | 30 ++++++++++++++++++++++++++++++ driver/pciDriver.h | 3 +++ pcilib/pci.c | 7 +++++++ pcilib/pci.h | 2 ++ 6 files changed, 56 insertions(+), 1 deletion(-) 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 -- cgit v1.2.3