提交 b0ba0e3a 编写于 作者: A Al Viro 提交者: Mauro Carvalho Chehab

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: NAl Viro <viro@zeniv.linux.org.uk>
Signed-off-by: NMauro Carvalho Chehab <mchehab@infradead.org>
上级 67778b32
...@@ -96,7 +96,7 @@ static ssize_t dvb_dmxdev_buffer_read(struct dvb_ringbuffer *src, ...@@ -96,7 +96,7 @@ static ssize_t dvb_dmxdev_buffer_read(struct dvb_ringbuffer *src,
if (avail > todo) if (avail > todo)
avail = todo; avail = todo;
ret = dvb_ringbuffer_read(src, (u8 *)buf, avail, 1); ret = dvb_ringbuffer_read_user(src, buf, avail);
if (ret < 0) if (ret < 0)
break; break;
......
...@@ -1357,7 +1357,7 @@ static int dvb_ca_en50221_io_read_condition(struct dvb_ca_private *ca, ...@@ -1357,7 +1357,7 @@ static int dvb_ca_en50221_io_read_condition(struct dvb_ca_private *ca,
idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, -1, &fraglen); idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, -1, &fraglen);
while (idx != -1) { 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) if (connection_id == -1)
connection_id = hdr[0]; connection_id = hdr[0];
if ((hdr[0] == connection_id) && ((hdr[1] & 0x80) == 0)) { if ((hdr[0] == connection_id) && ((hdr[1] & 0x80) == 0)) {
...@@ -1438,7 +1438,7 @@ static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user * buf, ...@@ -1438,7 +1438,7 @@ static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user * buf,
goto exit; 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) if (connection_id == -1)
connection_id = hdr[0]; connection_id = hdr[0];
if (hdr[0] == connection_id) { if (hdr[0] == connection_id) {
...@@ -1449,8 +1449,8 @@ static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user * buf, ...@@ -1449,8 +1449,8 @@ static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user * buf,
fraglen -= 2; fraglen -= 2;
} }
if ((status = dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 2, if ((status = dvb_ringbuffer_pkt_read_user(&ca->slot_info[slot].rx_buffer, idx, 2,
(u8 *)buf + pktlen, fraglen, 1)) < 0) { buf + pktlen, fraglen)) < 0) {
goto exit; goto exit;
} }
pktlen += fraglen; pktlen += fraglen;
......
...@@ -107,35 +107,43 @@ void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf) ...@@ -107,35 +107,43 @@ void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf)
wake_up(&rbuf->queue); wake_up(&rbuf->queue);
} }
ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf, u8 __user *buf, size_t len)
ssize_t dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, size_t len, int usermem)
{ {
size_t todo = len; size_t todo = len;
size_t split; size_t split;
split = (rbuf->pread + len > rbuf->size) ? rbuf->size - rbuf->pread : 0; split = (rbuf->pread + len > rbuf->size) ? rbuf->size - rbuf->pread : 0;
if (split > 0) { if (split > 0) {
if (!usermem) if (copy_to_user(buf, rbuf->data+rbuf->pread, split))
memcpy(buf, rbuf->data+rbuf->pread, split); return -EFAULT;
else
if (copy_to_user(buf, rbuf->data+rbuf->pread, split))
return -EFAULT;
buf += split; buf += split;
todo -= split; todo -= split;
rbuf->pread = 0; rbuf->pread = 0;
} }
if (!usermem) if (copy_to_user(buf, rbuf->data+rbuf->pread, todo))
memcpy(buf, rbuf->data+rbuf->pread, todo); return -EFAULT;
else
if (copy_to_user(buf, rbuf->data+rbuf->pread, todo))
return -EFAULT;
rbuf->pread = (rbuf->pread + todo) % rbuf->size; rbuf->pread = (rbuf->pread + todo) % rbuf->size;
return len; 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) ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf, size_t len)
...@@ -171,8 +179,8 @@ ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf, size_t le ...@@ -171,8 +179,8 @@ ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf, size_t le
return status; return status;
} }
ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx, ssize_t dvb_ringbuffer_pkt_read_user(struct dvb_ringbuffer *rbuf, size_t idx,
int offset, u8* buf, size_t len, int usermem) int offset, u8 __user *buf, size_t len)
{ {
size_t todo; size_t todo;
size_t split; size_t split;
...@@ -187,21 +195,40 @@ ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx, ...@@ -187,21 +195,40 @@ ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
todo = len; todo = len;
split = ((idx + len) > rbuf->size) ? rbuf->size - idx : 0; split = ((idx + len) > rbuf->size) ? rbuf->size - idx : 0;
if (split > 0) { if (split > 0) {
if (!usermem) if (copy_to_user(buf, rbuf->data+idx, split))
memcpy(buf, rbuf->data+idx, split); return -EFAULT;
else
if (copy_to_user(buf, rbuf->data+idx, split))
return -EFAULT;
buf += split; buf += split;
todo -= split; todo -= split;
idx = 0; idx = 0;
} }
if (!usermem) if (copy_to_user(buf, rbuf->data+idx, todo))
memcpy(buf, rbuf->data+idx, todo); return -EFAULT;
else
if (copy_to_user(buf, rbuf->data+idx, todo)) return len;
return -EFAULT; }
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; return len;
} }
...@@ -266,5 +293,6 @@ EXPORT_SYMBOL(dvb_ringbuffer_empty); ...@@ -266,5 +293,6 @@ EXPORT_SYMBOL(dvb_ringbuffer_empty);
EXPORT_SYMBOL(dvb_ringbuffer_free); EXPORT_SYMBOL(dvb_ringbuffer_free);
EXPORT_SYMBOL(dvb_ringbuffer_avail); EXPORT_SYMBOL(dvb_ringbuffer_avail);
EXPORT_SYMBOL(dvb_ringbuffer_flush_spinlock_wakeup); EXPORT_SYMBOL(dvb_ringbuffer_flush_spinlock_wakeup);
EXPORT_SYMBOL(dvb_ringbuffer_read_user);
EXPORT_SYMBOL(dvb_ringbuffer_read); EXPORT_SYMBOL(dvb_ringbuffer_read);
EXPORT_SYMBOL(dvb_ringbuffer_write); EXPORT_SYMBOL(dvb_ringbuffer_write);
...@@ -61,7 +61,7 @@ struct dvb_ringbuffer { ...@@ -61,7 +61,7 @@ struct dvb_ringbuffer {
** *** read min. 1000, max. <bufsize> bytes *** ** *** read min. 1000, max. <bufsize> bytes ***
** avail = dvb_ringbuffer_avail(rbuf); ** avail = dvb_ringbuffer_avail(rbuf);
** if (avail >= 1000) ** if (avail >= 1000)
** count = dvb_ringbuffer_read(rbuf, buffer, min(avail, bufsize), 0); ** count = dvb_ringbuffer_read(rbuf, buffer, min(avail, bufsize));
** else ** else
** ... ** ...
** **
...@@ -114,8 +114,10 @@ extern void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf); ...@@ -114,8 +114,10 @@ extern void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf);
** <usermem> specifies whether <buf> resides in user space ** <usermem> specifies whether <buf> resides in user space
** returns number of bytes transferred or -EFAULT ** returns number of bytes transferred or -EFAULT
*/ */
extern ssize_t dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, extern ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf,
size_t len, int usermem); u8 __user *buf, size_t len);
extern void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf,
u8 *buf, size_t len);
/* write routines & macros */ /* write routines & macros */
...@@ -157,8 +159,10 @@ extern ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf, ...@@ -157,8 +159,10 @@ extern ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf,
* <usermem> Set to 1 if <buf> is in userspace. * <usermem> Set to 1 if <buf> is in userspace.
* returns Number of bytes read, or -EFAULT. * 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, 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. * Dispose of a packet in the ring buffer.
......
...@@ -587,7 +587,7 @@ static void gpioirq(unsigned long data) ...@@ -587,7 +587,7 @@ static void gpioirq(unsigned long data)
} }
DVB_RINGBUFFER_SKIP(cibuf, 2); 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, TX_LEN, len, 2);
iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2); iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
......
...@@ -269,7 +269,7 @@ int av7110_pes_play(void *dest, struct dvb_ringbuffer *buf, int dlen) ...@@ -269,7 +269,7 @@ int av7110_pes_play(void *dest, struct dvb_ringbuffer *buf, int dlen)
return -1; 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", dprintk(2, "pread=0x%08lx, pwrite=0x%08lx\n",
(unsigned long) buf->pread, (unsigned long) buf->pwrite); (unsigned long) buf->pread, (unsigned long) buf->pwrite);
......
...@@ -208,7 +208,7 @@ static ssize_t ci_ll_read(struct dvb_ringbuffer *cibuf, struct file *file, ...@@ -208,7 +208,7 @@ static ssize_t ci_ll_read(struct dvb_ringbuffer *cibuf, struct file *file,
return -EINVAL; return -EINVAL;
DVB_RINGBUFFER_SKIP(cibuf, 2); 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) static int dvb_ca_open(struct inode *inode, struct file *file)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册