فهرست منبع

Enforce 64-bit dma mask from IPEDMA if supported

Suren A. Chilingaryan 8 سال پیش
والد
کامیت
e30eddc0ae
6فایلهای تغییر یافته به همراه56 افزوده شده و 1 حذف شده
  1. 12 0
      dma/ipe.c
  2. 2 1
      dma/ipe_private.h
  3. 30 0
      driver/ioctl.c
  4. 3 0
      driver/pciDriver.h
  5. 7 0
      pcilib/pci.c
  6. 2 0
      pcilib/pci.h

+ 12 - 0
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);

+ 2 - 1
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

+ 30 - 0
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;
 	}

+ 3 - 0
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

+ 7 - 0
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;
+}

+ 2 - 0
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