V4L/DVB (8130): split dvb_ringbuffer dual-use functions

split the suckers into kernel-memory and user-memory versions,
annotate both properly.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index df5bef6..1cf9fcb 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -96,7 +96,7 @@
 		if (avail > todo)
 			avail = todo;
 
-		ret = dvb_ringbuffer_read(src, (u8 *)buf, avail, 1);
+		ret = dvb_ringbuffer_read_user(src, buf, avail);
 		if (ret < 0)
 			break;
 
diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
index 588fbe1..8e5dd7b 100644
--- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
+++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
@@ -1357,7 +1357,7 @@
 
 		idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, -1, &fraglen);
 		while (idx != -1) {
-			dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 0, hdr, 2, 0);
+			dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 0, hdr, 2);
 			if (connection_id == -1)
 				connection_id = hdr[0];
 			if ((hdr[0] == connection_id) && ((hdr[1] & 0x80) == 0)) {
@@ -1438,7 +1438,7 @@
 			goto exit;
 		}
 
-		dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 0, hdr, 2, 0);
+		dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 0, hdr, 2);
 		if (connection_id == -1)
 			connection_id = hdr[0];
 		if (hdr[0] == connection_id) {
@@ -1449,8 +1449,8 @@
 					fraglen -= 2;
 				}
 
-				if ((status = dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 2,
-								      (u8 *)buf + pktlen, fraglen, 1)) < 0) {
+				if ((status = dvb_ringbuffer_pkt_read_user(&ca->slot_info[slot].rx_buffer, idx, 2,
+								      buf + pktlen, fraglen)) < 0) {
 					goto exit;
 				}
 				pktlen += fraglen;
diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
index 872985b..584bbd1 100644
--- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
+++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
@@ -107,35 +107,43 @@
 	wake_up(&rbuf->queue);
 }
 
-
-
-ssize_t dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, size_t len, int usermem)
+ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf, u8 __user *buf, size_t len)
 {
 	size_t todo = len;
 	size_t split;
 
 	split = (rbuf->pread + len > rbuf->size) ? rbuf->size - rbuf->pread : 0;
 	if (split > 0) {
-		if (!usermem)
-			memcpy(buf, rbuf->data+rbuf->pread, split);
-		else
-			if (copy_to_user(buf, rbuf->data+rbuf->pread, split))
-				return -EFAULT;
+		if (copy_to_user(buf, rbuf->data+rbuf->pread, split))
+			return -EFAULT;
 		buf += split;
 		todo -= split;
 		rbuf->pread = 0;
 	}
-	if (!usermem)
-		memcpy(buf, rbuf->data+rbuf->pread, todo);
-	else
-		if (copy_to_user(buf, rbuf->data+rbuf->pread, todo))
-			return -EFAULT;
+	if (copy_to_user(buf, rbuf->data+rbuf->pread, todo))
+		return -EFAULT;
 
 	rbuf->pread = (rbuf->pread + todo) % rbuf->size;
 
 	return len;
 }
 
+void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, size_t len)
+{
+	size_t todo = len;
+	size_t split;
+
+	split = (rbuf->pread + len > rbuf->size) ? rbuf->size - rbuf->pread : 0;
+	if (split > 0) {
+		memcpy(buf, rbuf->data+rbuf->pread, split);
+		buf += split;
+		todo -= split;
+		rbuf->pread = 0;
+	}
+	memcpy(buf, rbuf->data+rbuf->pread, todo);
+
+	rbuf->pread = (rbuf->pread + todo) % rbuf->size;
+}
 
 
 ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf, size_t len)
@@ -171,8 +179,8 @@
 	return status;
 }
 
-ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
-				int offset, u8* buf, size_t len, int usermem)
+ssize_t dvb_ringbuffer_pkt_read_user(struct dvb_ringbuffer *rbuf, size_t idx,
+				int offset, u8 __user *buf, size_t len)
 {
 	size_t todo;
 	size_t split;
@@ -187,24 +195,43 @@
 	todo = len;
 	split = ((idx + len) > rbuf->size) ? rbuf->size - idx : 0;
 	if (split > 0) {
-		if (!usermem)
-			memcpy(buf, rbuf->data+idx, split);
-		else
-			if (copy_to_user(buf, rbuf->data+idx, split))
-				return -EFAULT;
+		if (copy_to_user(buf, rbuf->data+idx, split))
+			return -EFAULT;
 		buf += split;
 		todo -= split;
 		idx = 0;
 	}
-	if (!usermem)
-		memcpy(buf, rbuf->data+idx, todo);
-	else
-		if (copy_to_user(buf, rbuf->data+idx, todo))
-			return -EFAULT;
+	if (copy_to_user(buf, rbuf->data+idx, todo))
+		return -EFAULT;
 
 	return len;
 }
 
+ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
+				int offset, u8* buf, size_t len)
+{
+	size_t todo;
+	size_t split;
+	size_t pktlen;
+
+	pktlen = rbuf->data[idx] << 8;
+	pktlen |= rbuf->data[(idx + 1) % rbuf->size];
+	if (offset > pktlen) return -EINVAL;
+	if ((offset + len) > pktlen) len = pktlen - offset;
+
+	idx = (idx + DVB_RINGBUFFER_PKTHDRSIZE + offset) % rbuf->size;
+	todo = len;
+	split = ((idx + len) > rbuf->size) ? rbuf->size - idx : 0;
+	if (split > 0) {
+		memcpy(buf, rbuf->data+idx, split);
+		buf += split;
+		todo -= split;
+		idx = 0;
+	}
+	memcpy(buf, rbuf->data+idx, todo);
+	return len;
+}
+
 void dvb_ringbuffer_pkt_dispose(struct dvb_ringbuffer *rbuf, size_t idx)
 {
 	size_t pktlen;
@@ -266,5 +293,6 @@
 EXPORT_SYMBOL(dvb_ringbuffer_free);
 EXPORT_SYMBOL(dvb_ringbuffer_avail);
 EXPORT_SYMBOL(dvb_ringbuffer_flush_spinlock_wakeup);
+EXPORT_SYMBOL(dvb_ringbuffer_read_user);
 EXPORT_SYMBOL(dvb_ringbuffer_read);
 EXPORT_SYMBOL(dvb_ringbuffer_write);
diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.h b/drivers/media/dvb/dvb-core/dvb_ringbuffer.h
index 8908262..41f04da 100644
--- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.h
+++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.h
@@ -61,7 +61,7 @@
 **     *** read min. 1000, max. <bufsize> bytes ***
 **     avail = dvb_ringbuffer_avail(rbuf);
 **     if (avail >= 1000)
-**         count = dvb_ringbuffer_read(rbuf, buffer, min(avail, bufsize), 0);
+**         count = dvb_ringbuffer_read(rbuf, buffer, min(avail, bufsize));
 **     else
 **         ...
 **
@@ -114,8 +114,10 @@
 ** <usermem> specifies whether <buf> resides in user space
 ** returns number of bytes transferred or -EFAULT
 */
-extern ssize_t dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf,
-				   size_t len, int usermem);
+extern ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf,
+				   u8 __user *buf, size_t len);
+extern void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf,
+				   u8 *buf, size_t len);
 
 
 /* write routines & macros */
@@ -157,8 +159,10 @@
  * <usermem> Set to 1 if <buf> is in userspace.
  * returns Number of bytes read, or -EFAULT.
  */
+extern ssize_t dvb_ringbuffer_pkt_read_user(struct dvb_ringbuffer *rbuf, size_t idx,
+				       int offset, u8 __user *buf, size_t len);
 extern ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
-				       int offset, u8* buf, size_t len, int usermem);
+				       int offset, u8 *buf, size_t len);
 
 /**
  * Dispose of a packet in the ring buffer.
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
index 6d7b9f6..dfe03cb 100644
--- a/drivers/media/dvb/ttpci/av7110.c
+++ b/drivers/media/dvb/ttpci/av7110.c
@@ -587,7 +587,7 @@
 		}
 		DVB_RINGBUFFER_SKIP(cibuf, 2);
 
-		dvb_ringbuffer_read(cibuf, av7110->debi_virt, len, 0);
+		dvb_ringbuffer_read(cibuf, av7110->debi_virt, len);
 
 		iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
 		iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
diff --git a/drivers/media/dvb/ttpci/av7110_av.c b/drivers/media/dvb/ttpci/av7110_av.c
index ec55a968..184647ad 100644
--- a/drivers/media/dvb/ttpci/av7110_av.c
+++ b/drivers/media/dvb/ttpci/av7110_av.c
@@ -269,7 +269,7 @@
 		return -1;
 	}
 
-	dvb_ringbuffer_read(buf, dest, (size_t) blen, 0);
+	dvb_ringbuffer_read(buf, dest, (size_t) blen);
 
 	dprintk(2, "pread=0x%08lx, pwrite=0x%08lx\n",
 	       (unsigned long) buf->pread, (unsigned long) buf->pwrite);
diff --git a/drivers/media/dvb/ttpci/av7110_ca.c b/drivers/media/dvb/ttpci/av7110_ca.c
index c58e3fc..261135d 100644
--- a/drivers/media/dvb/ttpci/av7110_ca.c
+++ b/drivers/media/dvb/ttpci/av7110_ca.c
@@ -208,7 +208,7 @@
 		return -EINVAL;
 	DVB_RINGBUFFER_SKIP(cibuf, 2);
 
-	return dvb_ringbuffer_read(cibuf, (u8 *)buf, len, 1);
+	return dvb_ringbuffer_read_user(cibuf, buf, len);
 }
 
 static int dvb_ca_open(struct inode *inode, struct file *file)