X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fmedia%2Fdvb%2Fttpci%2Fav7110_ca.c;h=dd9aee314e0a389b72f2347c347c5e45ad8df3ee;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=7c9a5c84e1e96c60cfa40d160b70989a04d044b1;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/media/dvb/ttpci/av7110_ca.c b/drivers/media/dvb/ttpci/av7110_ca.c index 7c9a5c84e..dd9aee314 100644 --- a/drivers/media/dvb/ttpci/av7110_ca.c +++ b/drivers/media/dvb/ttpci/av7110_ca.c @@ -35,21 +35,16 @@ #include #include #include -#include #include -#define DEBUG_VARIABLE av7110_debug -extern int av7110_debug; - -#include "dvb_i2c.h" #include "av7110.h" #include "av7110_hw.h" -#include "dvb_functions.h" +#include "av7110_ca.h" void CI_handle(struct av7110 *av7110, u8 *data, u16 len) { - DEB_EE(("av7110: %p\n", av7110)); + dprintk(8, "av7110:%p\n",av7110); if (len < 3) return; @@ -85,7 +80,7 @@ void ci_get_data(struct dvb_ringbuffer *cibuf, u8 *data, int len) DVB_RINGBUFFER_WRITE_BYTE(cibuf, len >> 8); DVB_RINGBUFFER_WRITE_BYTE(cibuf, len & 0xff); - dvb_ringbuffer_write(cibuf, data, len, 0); + dvb_ringbuffer_write(cibuf, data, len); wake_up_interruptible(&cibuf->queue); } @@ -94,29 +89,41 @@ void ci_get_data(struct dvb_ringbuffer *cibuf, u8 *data, int len) * CI link layer file ops ******************************************************************************/ -int ci_ll_init(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf, int size) +static int ci_ll_init(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf, int size) { - dvb_ringbuffer_init(cirbuf, vmalloc(size), size); - dvb_ringbuffer_init(ciwbuf, vmalloc(size), size); + struct dvb_ringbuffer *tab[] = { cirbuf, ciwbuf, NULL }, **p; + void *data; + + for (p = tab; *p; p++) { + data = vmalloc(size); + if (!data) { + while (p-- != tab) { + vfree(p[0]->data); + p[0]->data = NULL; + } + return -ENOMEM; + } + dvb_ringbuffer_init(*p, data, size); + } return 0; } -void ci_ll_flush(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf) +static void ci_ll_flush(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf) { dvb_ringbuffer_flush_spinlock_wakeup(cirbuf); dvb_ringbuffer_flush_spinlock_wakeup(ciwbuf); } -void ci_ll_release(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf) +static void ci_ll_release(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf) { vfree(cirbuf->data); - cirbuf->data = 0; + cirbuf->data = NULL; vfree(ciwbuf->data); - ciwbuf->data = 0; + ciwbuf->data = NULL; } -int ci_ll_reset(struct dvb_ringbuffer *cibuf, struct file *file, - int slots, ca_slot_info_t *slot) +static int ci_ll_reset(struct dvb_ringbuffer *cibuf, struct file *file, + int slots, ca_slot_info_t *slot) { int i; int len = 0; @@ -133,7 +140,7 @@ int ci_ll_reset(struct dvb_ringbuffer *cibuf, struct file *file, for (i = 0; i < 2; i++) { if (slots & (1 << i)) { msg[2] = i; - dvb_ringbuffer_write(cibuf, msg, 8, 0); + dvb_ringbuffer_write(cibuf, msg, 8); slot[i].flags = 0; } } @@ -142,30 +149,46 @@ int ci_ll_reset(struct dvb_ringbuffer *cibuf, struct file *file, } static ssize_t ci_ll_write(struct dvb_ringbuffer *cibuf, struct file *file, - const char *buf, size_t count, loff_t *ppos) + const char __user *buf, size_t count, loff_t *ppos) { int free; int non_blocking = file->f_flags & O_NONBLOCK; + char *page = (char *)__get_free_page(GFP_USER); + int res; + if (!page) + return -ENOMEM; + + res = -EINVAL; if (count > 2048) - return -EINVAL; + goto out; + + res = -EFAULT; + if (copy_from_user(page, buf, count)) + goto out; + free = dvb_ringbuffer_free(cibuf); if (count + 2 > free) { + res = -EWOULDBLOCK; if (non_blocking) - return -EWOULDBLOCK; + goto out; + res = -ERESTARTSYS; if (wait_event_interruptible(cibuf->queue, (dvb_ringbuffer_free(cibuf) >= count + 2))) - return -ERESTARTSYS; + goto out; } DVB_RINGBUFFER_WRITE_BYTE(cibuf, count >> 8); DVB_RINGBUFFER_WRITE_BYTE(cibuf, count & 0xff); - return dvb_ringbuffer_write(cibuf, buf, count, 1); + res = dvb_ringbuffer_write(cibuf, page, count); +out: + free_page((unsigned long)page); + return res; } static ssize_t ci_ll_read(struct dvb_ringbuffer *cibuf, struct file *file, - char *buf, size_t count, loff_t *ppos) + char __user *buf, size_t count, loff_t *ppos) { int avail; int non_blocking = file->f_flags & O_NONBLOCK; @@ -196,7 +219,7 @@ static int dvb_ca_open(struct inode *inode, struct file *file) struct av7110 *av7110 = (struct av7110 *) dvbdev->priv; int err = dvb_generic_open(inode, file); - DEB_EE(("av7110: %p\n", av7110)); + dprintk(8, "av7110:%p\n",av7110); if (err < 0) return err; @@ -212,13 +235,16 @@ static unsigned int dvb_ca_poll (struct file *file, poll_table *wait) struct dvb_ringbuffer *wbuf = &av7110->ci_wbuffer; unsigned int mask = 0; - DEB_EE(("av7110: %p\n", av7110)); + dprintk(8, "av7110:%p\n",av7110); poll_wait(file, &rbuf->queue, wait); + poll_wait(file, &wbuf->queue, wait); + if (!dvb_ringbuffer_empty(rbuf)) - mask |= POLLIN; - if (dvb_ringbuffer_avail(wbuf) > 1024) - mask |= POLLOUT; + mask |= (POLLIN | POLLRDNORM); + + if (dvb_ringbuffer_free(wbuf) > 1024) + mask |= (POLLOUT | POLLWRNORM); return mask; } @@ -230,7 +256,7 @@ static int dvb_ca_ioctl(struct inode *inode, struct file *file, struct av7110 *av7110 = (struct av7110 *) dvbdev->priv; unsigned long arg = (unsigned long) parg; - DEB_EE(("av7110: %p\n", av7110)); + dprintk(8, "av7110:%p\n",av7110); switch (cmd) { case CA_RESET: @@ -301,23 +327,23 @@ static int dvb_ca_ioctl(struct inode *inode, struct file *file, return 0; } -static ssize_t dvb_ca_write(struct file *file, const char *buf, +static ssize_t dvb_ca_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { struct dvb_device *dvbdev = (struct dvb_device *) file->private_data; struct av7110 *av7110 = (struct av7110 *) dvbdev->priv; - DEB_EE(("av7110: %p\n", av7110)); + dprintk(8, "av7110:%p\n",av7110); return ci_ll_write(&av7110->ci_wbuffer, file, buf, count, ppos); } -static ssize_t dvb_ca_read(struct file *file, char *buf, +static ssize_t dvb_ca_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { struct dvb_device *dvbdev = (struct dvb_device *) file->private_data; struct av7110 *av7110 = (struct av7110 *) dvbdev->priv; - DEB_EE(("av7110: %p\n", av7110)); + dprintk(8, "av7110:%p\n",av7110); return ci_ll_read(&av7110->ci_rbuffer, file, buf, count, ppos); } @@ -334,7 +360,7 @@ static struct file_operations dvb_ca_fops = { }; static struct dvb_device dvbdev_ca = { - .priv = 0, + .priv = NULL, .users = 1, .writers = 1, .fops = &dvb_ca_fops, @@ -344,7 +370,7 @@ static struct dvb_device dvbdev_ca = { int av7110_ca_register(struct av7110 *av7110) { - return dvb_register_device(av7110->dvb_adapter, &av7110->ca_dev, + return dvb_register_device(&av7110->dvb_adapter, &av7110->ca_dev, &dvbdev_ca, av7110, DVB_DEVICE_CA); } @@ -353,9 +379,9 @@ void av7110_ca_unregister(struct av7110 *av7110) dvb_unregister_device(av7110->ca_dev); } -void av7110_ca_init(struct av7110* av7110) +int av7110_ca_init(struct av7110* av7110) { - ci_ll_init(&av7110->ci_rbuffer, &av7110->ci_wbuffer, 8192); + return ci_ll_init(&av7110->ci_rbuffer, &av7110->ci_wbuffer, 8192); } void av7110_ca_exit(struct av7110* av7110)