aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/carma/carma-fpga.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-12-14 19:43:47 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-12-14 19:43:47 -0500
commit6ae840e7cc4be0be3aa40d9f67c35c75cfc67d83 (patch)
tree9c83c87a8670ef678d95f8d6f76a07f24a09a49f /drivers/misc/carma/carma-fpga.c
parente6b5be2be4e30037eb551e0ed09dd97bd00d85d3 (diff)
parent91905b6f4afe51e23a3f58df93e4cdc5e49cf40c (diff)
Merge tag 'char-misc-3.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char/misc driver updates from Greg KH: "Here's the big char/misc driver update for 3.19-rc1 Lots of little things all over the place in different drivers, and a new subsystem, "coresight" has been added. Full details are in the shortlog" * tag 'char-misc-3.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (73 commits) parport: parport_pc, do not remove parent devices early spmi: Remove shutdown/suspend/resume kernel-doc carma-fpga-program: drop videobuf dependency carma-fpga: drop videobuf dependency carma-fpga-program.c: fix compile errors i8k: Fix temperature bug handling in i8k_get_temp() cxl: Name interrupts in /proc/interrupt CXL: Return error to PSL if IRQ demultiplexing fails & print clearer warning coresight-replicator: remove .owner field for driver coresight: fixed comments in coresight.h coresight: fix typo in comment in coresight-priv.h coresight: bindings for coresight drivers coresight: Adding ABI documentation w1: support auto-load of w1_bq27000 module. w1: avoid potential u16 overflow cn: verify msg->len before making callback mei: export fw status registers through sysfs mei: read and print all six FW status registers mei: txe: add cherrytrail device id mei: kill cached host and me csr values ...
Diffstat (limited to 'drivers/misc/carma/carma-fpga.c')
-rw-r--r--drivers/misc/carma/carma-fpga.c98
1 files changed, 81 insertions, 17 deletions
diff --git a/drivers/misc/carma/carma-fpga.c b/drivers/misc/carma/carma-fpga.c
index cdf2d7b902bb..68cdfe151bdb 100644
--- a/drivers/misc/carma/carma-fpga.c
+++ b/drivers/misc/carma/carma-fpga.c
@@ -98,6 +98,7 @@
98#include <linux/seq_file.h> 98#include <linux/seq_file.h>
99#include <linux/highmem.h> 99#include <linux/highmem.h>
100#include <linux/debugfs.h> 100#include <linux/debugfs.h>
101#include <linux/vmalloc.h>
101#include <linux/kernel.h> 102#include <linux/kernel.h>
102#include <linux/module.h> 103#include <linux/module.h>
103#include <linux/poll.h> 104#include <linux/poll.h>
@@ -105,8 +106,6 @@
105#include <linux/kref.h> 106#include <linux/kref.h>
106#include <linux/io.h> 107#include <linux/io.h>
107 108
108#include <media/videobuf-dma-sg.h>
109
110/* system controller registers */ 109/* system controller registers */
111#define SYS_IRQ_SOURCE_CTL 0x24 110#define SYS_IRQ_SOURCE_CTL 0x24
112#define SYS_IRQ_OUTPUT_EN 0x28 111#define SYS_IRQ_OUTPUT_EN 0x28
@@ -142,7 +141,10 @@ struct fpga_info {
142 141
143struct data_buf { 142struct data_buf {
144 struct list_head entry; 143 struct list_head entry;
145 struct videobuf_dmabuf vb; 144 void *vaddr;
145 struct scatterlist *sglist;
146 int sglen;
147 int nr_pages;
146 size_t size; 148 size_t size;
147}; 149};
148 150
@@ -207,6 +209,68 @@ static void fpga_device_release(struct kref *ref)
207 * Data Buffer Allocation Helpers 209 * Data Buffer Allocation Helpers
208 */ 210 */
209 211
212static int carma_dma_init(struct data_buf *buf, int nr_pages)
213{
214 struct page *pg;
215 int i;
216
217 buf->vaddr = vmalloc_32(nr_pages << PAGE_SHIFT);
218 if (NULL == buf->vaddr) {
219 pr_debug("vmalloc_32(%d pages) failed\n", nr_pages);
220 return -ENOMEM;
221 }
222
223 pr_debug("vmalloc is at addr 0x%08lx, size=%d\n",
224 (unsigned long)buf->vaddr,
225 nr_pages << PAGE_SHIFT);
226
227 memset(buf->vaddr, 0, nr_pages << PAGE_SHIFT);
228 buf->nr_pages = nr_pages;
229
230 buf->sglist = vzalloc(buf->nr_pages * sizeof(*buf->sglist));
231 if (NULL == buf->sglist)
232 goto vzalloc_err;
233
234 sg_init_table(buf->sglist, buf->nr_pages);
235 for (i = 0; i < buf->nr_pages; i++) {
236 pg = vmalloc_to_page(buf->vaddr + i * PAGE_SIZE);
237 if (NULL == pg)
238 goto vmalloc_to_page_err;
239 sg_set_page(&buf->sglist[i], pg, PAGE_SIZE, 0);
240 }
241 return 0;
242
243vmalloc_to_page_err:
244 vfree(buf->sglist);
245 buf->sglist = NULL;
246vzalloc_err:
247 vfree(buf->vaddr);
248 buf->vaddr = NULL;
249 return -ENOMEM;
250}
251
252static int carma_dma_map(struct device *dev, struct data_buf *buf)
253{
254 buf->sglen = dma_map_sg(dev, buf->sglist,
255 buf->nr_pages, DMA_FROM_DEVICE);
256
257 if (0 == buf->sglen) {
258 pr_warn("%s: dma_map_sg failed\n", __func__);
259 return -ENOMEM;
260 }
261 return 0;
262}
263
264static int carma_dma_unmap(struct device *dev, struct data_buf *buf)
265{
266 if (!buf->sglen)
267 return 0;
268
269 dma_unmap_sg(dev, buf->sglist, buf->sglen, DMA_FROM_DEVICE);
270 buf->sglen = 0;
271 return 0;
272}
273
210/** 274/**
211 * data_free_buffer() - free a single data buffer and all allocated memory 275 * data_free_buffer() - free a single data buffer and all allocated memory
212 * @buf: the buffer to free 276 * @buf: the buffer to free
@@ -221,7 +285,8 @@ static void data_free_buffer(struct data_buf *buf)
221 return; 285 return;
222 286
223 /* free all memory */ 287 /* free all memory */
224 videobuf_dma_free(&buf->vb); 288 vfree(buf->sglist);
289 vfree(buf->vaddr);
225 kfree(buf); 290 kfree(buf);
226} 291}
227 292
@@ -230,7 +295,7 @@ static void data_free_buffer(struct data_buf *buf)
230 * @bytes: the number of bytes required 295 * @bytes: the number of bytes required
231 * 296 *
232 * This allocates all space needed for a data buffer. It must be mapped before 297 * This allocates all space needed for a data buffer. It must be mapped before
233 * use in a DMA transaction using videobuf_dma_map(). 298 * use in a DMA transaction using carma_dma_map().
234 * 299 *
235 * Returns NULL on failure 300 * Returns NULL on failure
236 */ 301 */
@@ -252,9 +317,8 @@ static struct data_buf *data_alloc_buffer(const size_t bytes)
252 INIT_LIST_HEAD(&buf->entry); 317 INIT_LIST_HEAD(&buf->entry);
253 buf->size = bytes; 318 buf->size = bytes;
254 319
255 /* allocate the videobuf */ 320 /* allocate the buffer */
256 videobuf_dma_init(&buf->vb); 321 ret = carma_dma_init(buf, nr_pages);
257 ret = videobuf_dma_init_kernel(&buf->vb, DMA_FROM_DEVICE, nr_pages);
258 if (ret) 322 if (ret)
259 goto out_free_buf; 323 goto out_free_buf;
260 324
@@ -285,13 +349,13 @@ static void data_free_buffers(struct fpga_device *priv)
285 349
286 list_for_each_entry_safe(buf, tmp, &priv->free, entry) { 350 list_for_each_entry_safe(buf, tmp, &priv->free, entry) {
287 list_del_init(&buf->entry); 351 list_del_init(&buf->entry);
288 videobuf_dma_unmap(priv->dev, &buf->vb); 352 carma_dma_unmap(priv->dev, buf);
289 data_free_buffer(buf); 353 data_free_buffer(buf);
290 } 354 }
291 355
292 list_for_each_entry_safe(buf, tmp, &priv->used, entry) { 356 list_for_each_entry_safe(buf, tmp, &priv->used, entry) {
293 list_del_init(&buf->entry); 357 list_del_init(&buf->entry);
294 videobuf_dma_unmap(priv->dev, &buf->vb); 358 carma_dma_unmap(priv->dev, buf);
295 data_free_buffer(buf); 359 data_free_buffer(buf);
296 } 360 }
297 361
@@ -330,7 +394,7 @@ static int data_alloc_buffers(struct fpga_device *priv)
330 break; 394 break;
331 395
332 /* map it for DMA */ 396 /* map it for DMA */
333 ret = videobuf_dma_map(priv->dev, &buf->vb); 397 ret = carma_dma_map(priv->dev, buf);
334 if (ret) { 398 if (ret) {
335 data_free_buffer(buf); 399 data_free_buffer(buf);
336 break; 400 break;
@@ -634,8 +698,8 @@ static int data_submit_dma(struct fpga_device *priv, struct data_buf *buf)
634 dma_addr_t dst, src; 698 dma_addr_t dst, src;
635 unsigned long dma_flags = 0; 699 unsigned long dma_flags = 0;
636 700
637 dst_sg = buf->vb.sglist; 701 dst_sg = buf->sglist;
638 dst_nents = buf->vb.sglen; 702 dst_nents = buf->sglen;
639 703
640 src_sg = priv->corl_table.sgl; 704 src_sg = priv->corl_table.sgl;
641 src_nents = priv->corl_nents; 705 src_nents = priv->corl_nents;
@@ -1134,7 +1198,7 @@ static ssize_t data_read(struct file *filp, char __user *ubuf, size_t count,
1134 spin_unlock_irq(&priv->lock); 1198 spin_unlock_irq(&priv->lock);
1135 1199
1136 /* Buffers are always mapped: unmap it */ 1200 /* Buffers are always mapped: unmap it */
1137 videobuf_dma_unmap(priv->dev, &dbuf->vb); 1201 carma_dma_unmap(priv->dev, dbuf);
1138 1202
1139 /* save the buffer for later */ 1203 /* save the buffer for later */
1140 reader->buf = dbuf; 1204 reader->buf = dbuf;
@@ -1143,7 +1207,7 @@ static ssize_t data_read(struct file *filp, char __user *ubuf, size_t count,
1143have_buffer: 1207have_buffer:
1144 /* Get the number of bytes available */ 1208 /* Get the number of bytes available */
1145 avail = dbuf->size - reader->buf_start; 1209 avail = dbuf->size - reader->buf_start;
1146 data = dbuf->vb.vaddr + reader->buf_start; 1210 data = dbuf->vaddr + reader->buf_start;
1147 1211
1148 /* Get the number of bytes we can transfer */ 1212 /* Get the number of bytes we can transfer */
1149 count = min(count, avail); 1213 count = min(count, avail);
@@ -1171,7 +1235,7 @@ have_buffer:
1171 * If it fails, we pretend that the read never happed and return 1235 * If it fails, we pretend that the read never happed and return
1172 * -EFAULT to userspace. The read will be retried. 1236 * -EFAULT to userspace. The read will be retried.
1173 */ 1237 */
1174 ret = videobuf_dma_map(priv->dev, &dbuf->vb); 1238 ret = carma_dma_map(priv->dev, dbuf);
1175 if (ret) { 1239 if (ret) {
1176 dev_err(priv->dev, "unable to remap buffer for DMA\n"); 1240 dev_err(priv->dev, "unable to remap buffer for DMA\n");
1177 return -EFAULT; 1241 return -EFAULT;
@@ -1203,7 +1267,7 @@ out_unlock:
1203 spin_unlock_irq(&priv->lock); 1267 spin_unlock_irq(&priv->lock);
1204 1268
1205 if (drop_buffer) { 1269 if (drop_buffer) {
1206 videobuf_dma_unmap(priv->dev, &dbuf->vb); 1270 carma_dma_unmap(priv->dev, dbuf);
1207 data_free_buffer(dbuf); 1271 data_free_buffer(dbuf);
1208 } 1272 }
1209 1273