Re: [PATCH v2] staging: kpc2000: Add DMA driver
On Mon, Apr 22, 2019 at 10:05:58PM +, Matt Sickler wrote: > Add Daktronics DMA driver. I've added the SPDX license identifiers, Kconfig > entry, and cleaned up as many of the warnings as I could. > > The AIO support code will be removed in a future patch. > > Signed-off-by: Matt Sickler Looks good, now applied, thanks for doing this. greg k-h ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
Re: [PATCH v2] staging: kpc2000: Add DMA driver
Hi Matt, Thank you for the patch! Perhaps something to improve: [auto build test WARNING on staging/staging-testing] [cannot apply to v5.1-rc6 next-20190418] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Matt-Sickler/staging-kpc2000-Add-DMA-driver/20190423-120446 config: parisc-allmodconfig (attached as .config) compiler: hppa-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree GCC_VERSION=7.2.0 make.cross ARCH=parisc If you fix the issue, kindly add following tag Reported-by: kbuild test robot All warnings (new ones prefixed by >>): In file included from include/linux/printk.h:330:0, from include/linux/kernel.h:15, from include/linux/list.h:9, from include/linux/module.h:9, from drivers/staging/kpc2000/kpc_dma/fileops.c:2: drivers/staging/kpc2000/kpc_dma/fileops.c: In function 'kpc_dma_transfer': drivers/staging/kpc2000/kpc_dma/fileops.c:58:35: warning: format '%ld' expects argument of type 'long int', but argument 7 has type 'size_t {aka unsigned int}' [-Wformat=] dev_dbg(>ldev->pldev->dev, "kpc_dma_transfer(priv = [%p], kcb = [%p], iov_base = [%p], iov_len = %ld) ldev = [%p]\n", priv, kcb, (void*)iov_base, iov_len, ldev); ^ include/linux/dynamic_debug.h:118:15: note: in definition of macro '__dynamic_func_call' func(, ##__VA_ARGS__); \ ^~~ include/linux/dynamic_debug.h:150:2: note: in expansion of macro '_dynamic_func_call' _dynamic_func_call(fmt,__dynamic_dev_dbg, \ ^~ include/linux/device.h:1493:2: note: in expansion of macro 'dynamic_dev_dbg' dynamic_dev_dbg(dev, dev_fmt(fmt), ##__VA_ARGS__) ^~~ include/linux/device.h:1493:23: note: in expansion of macro 'dev_fmt' dynamic_dev_dbg(dev, dev_fmt(fmt), ##__VA_ARGS__) ^~~ >> drivers/staging/kpc2000/kpc_dma/fileops.c:58:2: note: in expansion of macro >> 'dev_dbg' dev_dbg(>ldev->pldev->dev, "kpc_dma_transfer(priv = [%p], kcb = [%p], iov_base = [%p], iov_len = %ld) ldev = [%p]\n", priv, kcb, (void*)iov_base, iov_len, ldev); ^~~ vim +/dev_dbg +58 drivers/staging/kpc2000/kpc_dma/fileops.c 34 35 /** Transfer Helpers **/ 36 static 37 int kpc_dma_transfer(struct dev_private_data *priv, struct kiocb *kcb, unsigned long iov_base, size_t iov_len) 38 { 39 unsigned int i = 0; 40 long rv = 0; 41 struct kpc_dma_device *ldev; 42 struct aio_cb_data *acd; 43 DECLARE_COMPLETION_ONSTACK(done); 44 u32 desc_needed = 0; 45 struct scatterlist *sg; 46 u32 num_descrs_avail; 47 struct kpc_dma_descriptor *desc; 48 unsigned int pcnt; 49 unsigned int p; 50 u64 card_addr; 51 u64 dma_addr; 52 u64 user_ctl; 53 54 BUG_ON(priv == NULL); 55 ldev = priv->ldev; 56 BUG_ON(ldev == NULL); 57 > 58 dev_dbg(>ldev->pldev->dev, "kpc_dma_transfer(priv = [%p], kcb = [%p], iov_base = [%p], iov_len = %ld) ldev = [%p]\n", priv, kcb, (void*)iov_base, iov_len, ldev); 59 60 acd = (struct aio_cb_data *) kzalloc(sizeof(struct aio_cb_data), GFP_KERNEL); 61 if (!acd){ 62 dev_err(>ldev->pldev->dev, "Couldn't kmalloc space for for the aio data\n"); 63 return -ENOMEM; 64 } 65 memset(acd, 0x66, sizeof(struct aio_cb_data)); 66 67 acd->priv = priv; 68 acd->ldev = priv->ldev; 69 acd->cpl = 70 acd->flags = 0; 71 acd->kcb = kcb; 72 acd->len = iov_len; 73 acd->page_count = count_pages(iov_base, iov_len); 74 75 // Allocate an array of page pointers 76 acd->user_pages = kzalloc(sizeof(struct page *) * acd->page_count, GFP_KERNEL); 77 if (!acd->user_pages){ 78 dev_err(>ldev->pldev->dev, "Couldn't kmalloc space for for the page pointers\n"); 79 rv = -ENOMEM; 80 goto err_alloc_userpages; 81 } 82 83 // Lock the user buffer pages in memory, and hold on to the page pointers (for the sglist) 84 down_read(>mm->mmap_sem); /* get memory map semaphore */ 85 rv = get_user_pages(iov_base, acd->page_count, FOLL_TOUCH | FOLL_WRITE | FOLL_GET,
Re: [PATCH v2] staging: kpc2000: Add DMA driver
Hi Matt, Thank you for the patch! Perhaps something to improve: [auto build test WARNING on staging/staging-testing] [cannot apply to v5.1-rc6 next-20190418] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Matt-Sickler/staging-kpc2000-Add-DMA-driver/20190423-120446 config: arm-allmodconfig (attached as .config) compiler: arm-linux-gnueabi-gcc (Debian 7.2.0-11) 7.2.0 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree GCC_VERSION=7.2.0 make.cross ARCH=arm If you fix the issue, kindly add following tag Reported-by: kbuild test robot All warnings (new ones prefixed by >>): In file included from include/linux/printk.h:330:0, from include/linux/kernel.h:15, from include/linux/list.h:9, from include/linux/module.h:9, from drivers/staging//kpc2000/kpc_dma/fileops.c:2: drivers/staging//kpc2000/kpc_dma/fileops.c: In function 'kpc_dma_transfer': >> drivers/staging//kpc2000/kpc_dma/fileops.c:58:35: warning: format '%ld' >> expects argument of type 'long int', but argument 7 has type 'size_t {aka >> unsigned int}' [-Wformat=] dev_dbg(>ldev->pldev->dev, "kpc_dma_transfer(priv = [%p], kcb = [%p], iov_base = [%p], iov_len = %ld) ldev = [%p]\n", priv, kcb, (void*)iov_base, iov_len, ldev); ^ include/linux/dynamic_debug.h:118:15: note: in definition of macro '__dynamic_func_call' func(, ##__VA_ARGS__); \ ^~~ include/linux/dynamic_debug.h:150:2: note: in expansion of macro '_dynamic_func_call' _dynamic_func_call(fmt,__dynamic_dev_dbg, \ ^~ include/linux/device.h:1493:2: note: in expansion of macro 'dynamic_dev_dbg' dynamic_dev_dbg(dev, dev_fmt(fmt), ##__VA_ARGS__) ^~~ include/linux/device.h:1493:23: note: in expansion of macro 'dev_fmt' dynamic_dev_dbg(dev, dev_fmt(fmt), ##__VA_ARGS__) ^~~ drivers/staging//kpc2000/kpc_dma/fileops.c:58:2: note: in expansion of macro 'dev_dbg' dev_dbg(>ldev->pldev->dev, "kpc_dma_transfer(priv = [%p], kcb = [%p], iov_base = [%p], iov_len = %ld) ldev = [%p]\n", priv, kcb, (void*)iov_base, iov_len, ldev); ^~~ vim +58 drivers/staging//kpc2000/kpc_dma/fileops.c > 2 #include 3 #include 4 #include 5 #include/* printk() */ 6 #include /* kmalloc() */ 7 #include/* everything... */ 8 #include /* error codes */ 9 #include /* size_t */ 10 #include 11 #include /* copy_*_user */ 12 #include /* aio stuff */ 13 #include 14 #include 15 #include "kpc_dma_driver.h" 16 #include "uapi.h" 17 18 /** Helper Functions **/ 19 static inline 20 unsigned int count_pages(unsigned long iov_base, size_t iov_len) 21 { 22 unsigned long first = (iov_base & PAGE_MASK) >> PAGE_SHIFT; 23 unsigned long last = ((iov_base+iov_len-1) & PAGE_MASK) >> PAGE_SHIFT; 24 return last - first + 1; 25 } 26 27 static inline 28 unsigned int count_parts_for_sge(struct scatterlist *sg) 29 { 30 unsigned int sg_length = sg_dma_len(sg); 31 sg_length += (0x8-1); 32 return (sg_length / 0x8); 33 } 34 35 /** Transfer Helpers **/ 36 static 37 int kpc_dma_transfer(struct dev_private_data *priv, struct kiocb *kcb, unsigned long iov_base, size_t iov_len) 38 { 39 unsigned int i = 0; 40 long rv = 0; 41 struct kpc_dma_device *ldev; 42 struct aio_cb_data *acd; 43 DECLARE_COMPLETION_ONSTACK(done); 44 u32 desc_needed = 0; 45 struct scatterlist *sg; 46 u32 num_descrs_avail; 47 struct kpc_dma_descriptor *desc; 48 unsigned int pcnt; 49 unsigned int p; 50 u64 card_addr; 51 u64 dma_addr; 52 u64 user_ctl; 53 54 BUG_ON(priv == NULL); 55 ldev = priv->ldev; 56 BUG_ON(ldev == NULL); 57 > 58 dev_dbg(>ldev->pldev->dev, "kpc_dma_transfer(priv = [%p], kcb = [%p], iov_base = [%p], iov_len = %ld) ldev = [%p]\n", priv, kcb, (void*)iov_base, iov_len, ldev); 59 60 acd = (struct aio_cb_data *) kzalloc(sizeof(struct aio_cb_data), GFP_KERNEL); 61 if (!acd){ 62 dev_err(>ldev->pldev->dev, "Couldn't kmalloc space for for the aio data\n"); 63 return -ENOMEM;
[PATCH v2] staging: kpc2000: Add DMA driver
Add Daktronics DMA driver. I've added the SPDX license identifiers, Kconfig entry, and cleaned up as many of the warnings as I could. The AIO support code will be removed in a future patch. Signed-off-by: Matt Sickler --- drivers/staging/kpc2000/Kconfig | 11 + drivers/staging/kpc2000/Makefile | 1 + drivers/staging/kpc2000/kpc_dma/Makefile | 6 + drivers/staging/kpc2000/kpc_dma/dma.c| 264 ++ drivers/staging/kpc2000/kpc_dma/fileops.c| 420 +++ drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.c | 248 + drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.h | 220 drivers/staging/kpc2000/kpc_dma/uapi.h | 11 + 8 files changed, 1181 insertions(+) create mode 100644 drivers/staging/kpc2000/kpc_dma/Makefile create mode 100644 drivers/staging/kpc2000/kpc_dma/dma.c create mode 100644 drivers/staging/kpc2000/kpc_dma/fileops.c create mode 100644 drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.c create mode 100644 drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.h create mode 100644 drivers/staging/kpc2000/kpc_dma/uapi.h diff --git a/drivers/staging/kpc2000/Kconfig b/drivers/staging/kpc2000/Kconfig index 926e770d6e0e..fb5922928f47 100644 --- a/drivers/staging/kpc2000/Kconfig +++ b/drivers/staging/kpc2000/Kconfig @@ -44,3 +44,14 @@ config KPC2000_I2C If unsure, say N. +config KPC2000_DMA + tristate "Daktronics KPC DMA controller" + depends on KPC2000 + help + Say Y here if you wish to support the Daktronics DMA controller. + + To compile this driver as a module, choose M here: the module + will be called kpc2000_dma + + If unsure, say N. + diff --git a/drivers/staging/kpc2000/Makefile b/drivers/staging/kpc2000/Makefile index 6fcb2ee7b27d..1e48e9df1329 100644 --- a/drivers/staging/kpc2000/Makefile +++ b/drivers/staging/kpc2000/Makefile @@ -3,3 +3,4 @@ obj-$(CONFIG_KPC2000) += kpc2000/ obj-$(CONFIG_KPC2000_I2C) += kpc_i2c/ obj-$(CONFIG_KPC2000_SPI) += kpc_spi/ +obj-$(CONFIG_KPC2000_DMA) += kpc_dma/ diff --git a/drivers/staging/kpc2000/kpc_dma/Makefile b/drivers/staging/kpc2000/kpc_dma/Makefile new file mode 100644 index ..fe5db532c8c8 --- /dev/null +++ b/drivers/staging/kpc2000/kpc_dma/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-m := kpc_dma.o +kpc_dma-objs += dma.o +kpc_dma-objs += fileops.o +kpc_dma-objs += kpc_dma_driver.o diff --git a/drivers/staging/kpc2000/kpc_dma/dma.c b/drivers/staging/kpc2000/kpc_dma/dma.c new file mode 100644 index ..6959bac11388 --- /dev/null +++ b/drivers/staging/kpc2000/kpc_dma/dma.c @@ -0,0 +1,264 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "kpc_dma_driver.h" + +/** IRQ Handlers **/ +static +irqreturn_t ndd_irq_handler(int irq, void *dev_id) +{ + struct kpc_dma_device *ldev = (struct kpc_dma_device*)dev_id; + + if ((GetEngineControl(ldev) & ENG_CTL_IRQ_ACTIVE) || (ldev->desc_completed->MyDMAAddr != GetEngineCompletePtr(ldev))) + schedule_work(>irq_work); + + return IRQ_HANDLED; +} + +static +void ndd_irq_worker(struct work_struct *ws) +{ + struct kpc_dma_descriptor *cur; + struct kpc_dma_device *eng = container_of(ws, struct kpc_dma_device, irq_work); + lock_engine(eng); + + if (GetEngineCompletePtr(eng) == 0) + goto out; + + if (eng->desc_completed->MyDMAAddr == GetEngineCompletePtr(eng)) + goto out; + + cur = eng->desc_completed; + do { + cur = cur->Next; + dev_dbg(>pldev->dev, "Handling completed descriptor %p (acd = %p)\n", cur, cur->acd); + BUG_ON(cur == eng->desc_next); // Ordering failure. + + if (cur->DescControlFlags & DMA_DESC_CTL_SOP){ + eng->accumulated_bytes = 0; + eng->accumulated_flags = 0; + } + + eng->accumulated_bytes += cur->DescByteCount; + if (cur->DescStatusFlags & DMA_DESC_STS_ERROR) + eng->accumulated_flags |= ACD_FLAG_ENG_ACCUM_ERROR; + + if (cur->DescStatusFlags & DMA_DESC_STS_SHORT) + eng->accumulated_flags |= ACD_FLAG_ENG_ACCUM_SHORT; + + if (cur->DescControlFlags & DMA_DESC_CTL_EOP){ + if (cur->acd) + transfer_complete_cb(cur->acd, eng->accumulated_bytes, eng->accumulated_flags | ACD_FLAG_DONE); + } + + eng->desc_completed = cur; + } while (cur->MyDMAAddr != GetEngineCompletePtr(eng)); + + out: + SetClearEngineControl(eng, ENG_CTL_IRQ_ACTIVE, 0); + +