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 ...
This commit is contained in:
@@ -98,6 +98,7 @@
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/poll.h>
|
||||
@@ -105,8 +106,6 @@
|
||||
#include <linux/kref.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <media/videobuf-dma-sg.h>
|
||||
|
||||
/* system controller registers */
|
||||
#define SYS_IRQ_SOURCE_CTL 0x24
|
||||
#define SYS_IRQ_OUTPUT_EN 0x28
|
||||
@@ -142,7 +141,10 @@ struct fpga_info {
|
||||
|
||||
struct data_buf {
|
||||
struct list_head entry;
|
||||
struct videobuf_dmabuf vb;
|
||||
void *vaddr;
|
||||
struct scatterlist *sglist;
|
||||
int sglen;
|
||||
int nr_pages;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
@@ -207,6 +209,68 @@ static void fpga_device_release(struct kref *ref)
|
||||
* Data Buffer Allocation Helpers
|
||||
*/
|
||||
|
||||
static int carma_dma_init(struct data_buf *buf, int nr_pages)
|
||||
{
|
||||
struct page *pg;
|
||||
int i;
|
||||
|
||||
buf->vaddr = vmalloc_32(nr_pages << PAGE_SHIFT);
|
||||
if (NULL == buf->vaddr) {
|
||||
pr_debug("vmalloc_32(%d pages) failed\n", nr_pages);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pr_debug("vmalloc is at addr 0x%08lx, size=%d\n",
|
||||
(unsigned long)buf->vaddr,
|
||||
nr_pages << PAGE_SHIFT);
|
||||
|
||||
memset(buf->vaddr, 0, nr_pages << PAGE_SHIFT);
|
||||
buf->nr_pages = nr_pages;
|
||||
|
||||
buf->sglist = vzalloc(buf->nr_pages * sizeof(*buf->sglist));
|
||||
if (NULL == buf->sglist)
|
||||
goto vzalloc_err;
|
||||
|
||||
sg_init_table(buf->sglist, buf->nr_pages);
|
||||
for (i = 0; i < buf->nr_pages; i++) {
|
||||
pg = vmalloc_to_page(buf->vaddr + i * PAGE_SIZE);
|
||||
if (NULL == pg)
|
||||
goto vmalloc_to_page_err;
|
||||
sg_set_page(&buf->sglist[i], pg, PAGE_SIZE, 0);
|
||||
}
|
||||
return 0;
|
||||
|
||||
vmalloc_to_page_err:
|
||||
vfree(buf->sglist);
|
||||
buf->sglist = NULL;
|
||||
vzalloc_err:
|
||||
vfree(buf->vaddr);
|
||||
buf->vaddr = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static int carma_dma_map(struct device *dev, struct data_buf *buf)
|
||||
{
|
||||
buf->sglen = dma_map_sg(dev, buf->sglist,
|
||||
buf->nr_pages, DMA_FROM_DEVICE);
|
||||
|
||||
if (0 == buf->sglen) {
|
||||
pr_warn("%s: dma_map_sg failed\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int carma_dma_unmap(struct device *dev, struct data_buf *buf)
|
||||
{
|
||||
if (!buf->sglen)
|
||||
return 0;
|
||||
|
||||
dma_unmap_sg(dev, buf->sglist, buf->sglen, DMA_FROM_DEVICE);
|
||||
buf->sglen = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* data_free_buffer() - free a single data buffer and all allocated memory
|
||||
* @buf: the buffer to free
|
||||
@@ -221,7 +285,8 @@ static void data_free_buffer(struct data_buf *buf)
|
||||
return;
|
||||
|
||||
/* free all memory */
|
||||
videobuf_dma_free(&buf->vb);
|
||||
vfree(buf->sglist);
|
||||
vfree(buf->vaddr);
|
||||
kfree(buf);
|
||||
}
|
||||
|
||||
@@ -230,7 +295,7 @@ static void data_free_buffer(struct data_buf *buf)
|
||||
* @bytes: the number of bytes required
|
||||
*
|
||||
* This allocates all space needed for a data buffer. It must be mapped before
|
||||
* use in a DMA transaction using videobuf_dma_map().
|
||||
* use in a DMA transaction using carma_dma_map().
|
||||
*
|
||||
* Returns NULL on failure
|
||||
*/
|
||||
@@ -252,9 +317,8 @@ static struct data_buf *data_alloc_buffer(const size_t bytes)
|
||||
INIT_LIST_HEAD(&buf->entry);
|
||||
buf->size = bytes;
|
||||
|
||||
/* allocate the videobuf */
|
||||
videobuf_dma_init(&buf->vb);
|
||||
ret = videobuf_dma_init_kernel(&buf->vb, DMA_FROM_DEVICE, nr_pages);
|
||||
/* allocate the buffer */
|
||||
ret = carma_dma_init(buf, nr_pages);
|
||||
if (ret)
|
||||
goto out_free_buf;
|
||||
|
||||
@@ -285,13 +349,13 @@ static void data_free_buffers(struct fpga_device *priv)
|
||||
|
||||
list_for_each_entry_safe(buf, tmp, &priv->free, entry) {
|
||||
list_del_init(&buf->entry);
|
||||
videobuf_dma_unmap(priv->dev, &buf->vb);
|
||||
carma_dma_unmap(priv->dev, buf);
|
||||
data_free_buffer(buf);
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(buf, tmp, &priv->used, entry) {
|
||||
list_del_init(&buf->entry);
|
||||
videobuf_dma_unmap(priv->dev, &buf->vb);
|
||||
carma_dma_unmap(priv->dev, buf);
|
||||
data_free_buffer(buf);
|
||||
}
|
||||
|
||||
@@ -330,7 +394,7 @@ static int data_alloc_buffers(struct fpga_device *priv)
|
||||
break;
|
||||
|
||||
/* map it for DMA */
|
||||
ret = videobuf_dma_map(priv->dev, &buf->vb);
|
||||
ret = carma_dma_map(priv->dev, buf);
|
||||
if (ret) {
|
||||
data_free_buffer(buf);
|
||||
break;
|
||||
@@ -634,8 +698,8 @@ static int data_submit_dma(struct fpga_device *priv, struct data_buf *buf)
|
||||
dma_addr_t dst, src;
|
||||
unsigned long dma_flags = 0;
|
||||
|
||||
dst_sg = buf->vb.sglist;
|
||||
dst_nents = buf->vb.sglen;
|
||||
dst_sg = buf->sglist;
|
||||
dst_nents = buf->sglen;
|
||||
|
||||
src_sg = priv->corl_table.sgl;
|
||||
src_nents = priv->corl_nents;
|
||||
@@ -1134,7 +1198,7 @@ static ssize_t data_read(struct file *filp, char __user *ubuf, size_t count,
|
||||
spin_unlock_irq(&priv->lock);
|
||||
|
||||
/* Buffers are always mapped: unmap it */
|
||||
videobuf_dma_unmap(priv->dev, &dbuf->vb);
|
||||
carma_dma_unmap(priv->dev, dbuf);
|
||||
|
||||
/* save the buffer for later */
|
||||
reader->buf = dbuf;
|
||||
@@ -1143,7 +1207,7 @@ static ssize_t data_read(struct file *filp, char __user *ubuf, size_t count,
|
||||
have_buffer:
|
||||
/* Get the number of bytes available */
|
||||
avail = dbuf->size - reader->buf_start;
|
||||
data = dbuf->vb.vaddr + reader->buf_start;
|
||||
data = dbuf->vaddr + reader->buf_start;
|
||||
|
||||
/* Get the number of bytes we can transfer */
|
||||
count = min(count, avail);
|
||||
@@ -1171,7 +1235,7 @@ have_buffer:
|
||||
* If it fails, we pretend that the read never happed and return
|
||||
* -EFAULT to userspace. The read will be retried.
|
||||
*/
|
||||
ret = videobuf_dma_map(priv->dev, &dbuf->vb);
|
||||
ret = carma_dma_map(priv->dev, dbuf);
|
||||
if (ret) {
|
||||
dev_err(priv->dev, "unable to remap buffer for DMA\n");
|
||||
return -EFAULT;
|
||||
@@ -1203,7 +1267,7 @@ out_unlock:
|
||||
spin_unlock_irq(&priv->lock);
|
||||
|
||||
if (drop_buffer) {
|
||||
videobuf_dma_unmap(priv->dev, &dbuf->vb);
|
||||
carma_dma_unmap(priv->dev, dbuf);
|
||||
data_free_buffer(dbuf);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user