]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
[media] media: lirc_zilog: use a dynamically allocated lirc_dev
authorDavid Härdeman <david@hardeman.nu>
Sun, 25 Jun 2017 12:32:31 +0000 (09:32 -0300)
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>
Wed, 4 Oct 2017 17:24:17 +0000 (14:24 -0300)
lirc_zilog currently embeds a struct lirc_dev in its own struct IR,
but subsequent patches will make the lifetime of struct lirc_dev
dynamic (i.e.  it will be free():d once lirc_dev is sure there are
no users of the struct).

Therefore, change lirc_zilog to use a pointer to a dynamically
allocated struct lirc_dev.

Signed-off-by: David Härdeman <david@hardeman.nu>
Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
drivers/staging/media/lirc/lirc_zilog.c

index cd2eeb365cd7b286fda0f5b23888649c1da16e3e..00e8c8f224b7878406287013aec695f08dac64f6 100644 (file)
@@ -99,8 +99,8 @@ struct IR {
        struct kref ref;
        struct list_head list;
 
-       /* FIXME spinlock access to l.features */
-       struct lirc_dev l;
+       /* FIXME spinlock access to l->features */
+       struct lirc_dev *l;
        struct lirc_buffer rbuf;
 
        struct mutex ir_lock;
@@ -184,7 +184,10 @@ static void release_ir_device(struct kref *ref)
         * ir->open_count ==  0 - happens on final close()
         * ir_lock, tx_ref_lock, rx_ref_lock, all released
         */
-       lirc_unregister_device(&ir->l);
+       if (ir->l) {
+               lirc_unregister_device(ir->l);
+               lirc_free_device(ir->l);
+       }
 
        if (kfifo_initialized(&ir->rbuf.fifo))
                lirc_buffer_free(&ir->rbuf);
@@ -241,7 +244,7 @@ static void release_ir_rx(struct kref *ref)
         * and releasing the ir reference can cause a sleep.  That work is
         * performed by put_ir_rx()
         */
-       ir->l.features &= ~LIRC_CAN_REC_LIRCCODE;
+       ir->l->features &= ~LIRC_CAN_REC_LIRCCODE;
        /* Don't put_ir_device(rx->ir) here; lock can't be freed yet */
        ir->rx = NULL;
        /* Don't do the kfree(rx) here; we still need to kill the poll thread */
@@ -286,7 +289,7 @@ static void release_ir_tx(struct kref *ref)
        struct IR_tx *tx = container_of(ref, struct IR_tx, ref);
        struct IR *ir = tx->ir;
 
-       ir->l.features &= ~LIRC_CAN_SEND_LIRCCODE;
+       ir->l->features &= ~LIRC_CAN_SEND_LIRCCODE;
        /* Don't put_ir_device(tx->ir) here, so our lock doesn't get freed */
        ir->tx = NULL;
        kfree(tx);
@@ -315,7 +318,7 @@ static int add_to_buf(struct IR *ir)
        int ret;
        int failures = 0;
        unsigned char sendbuf[1] = { 0 };
-       struct lirc_buffer *rbuf = ir->l.rbuf;
+       struct lirc_buffer *rbuf = ir->l->rbuf;
        struct IR_rx *rx;
        struct IR_tx *tx;
 
@@ -461,7 +464,7 @@ static int add_to_buf(struct IR *ir)
 static int lirc_thread(void *arg)
 {
        struct IR *ir = arg;
-       struct lirc_buffer *rbuf = ir->l.rbuf;
+       struct lirc_buffer *rbuf = ir->l->rbuf;
 
        dev_dbg(ir->dev, "poll thread started\n");
 
@@ -882,7 +885,7 @@ static ssize_t read(struct file *filep, char __user *outbuf, size_t n,
 {
        struct IR *ir = lirc_get_pdata(filep);
        struct IR_rx *rx;
-       struct lirc_buffer *rbuf = ir->l.rbuf;
+       struct lirc_buffer *rbuf = ir->l->rbuf;
        int ret = 0, written = 0, retries = 0;
        unsigned int m;
        DECLARE_WAITQUEUE(wait, current);
@@ -1200,7 +1203,7 @@ static unsigned int poll(struct file *filep, poll_table *wait)
 {
        struct IR *ir = lirc_get_pdata(filep);
        struct IR_rx *rx;
-       struct lirc_buffer *rbuf = ir->l.rbuf;
+       struct lirc_buffer *rbuf = ir->l->rbuf;
        unsigned int ret;
 
        dev_dbg(ir->dev, "%s called\n", __func__);
@@ -1236,7 +1239,7 @@ static long ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
        int result;
        unsigned long mode, features;
 
-       features = ir->l.features;
+       features = ir->l->features;
 
        switch (cmd) {
        case LIRC_GET_LENGTH:
@@ -1346,13 +1349,6 @@ static const struct file_operations lirc_fops = {
        .release        = close
 };
 
-static struct lirc_dev lirc_template = {
-       .name           = "lirc_zilog",
-       .code_length    = 13,
-       .fops           = &lirc_fops,
-       .owner          = THIS_MODULE,
-};
-
 static int ir_remove(struct i2c_client *client)
 {
        if (strncmp("ir_tx_z8", client->name, 8) == 0) {
@@ -1443,22 +1439,35 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
                spin_lock_init(&ir->rx_ref_lock);
 
                /* set lirc_dev stuff */
-               memcpy(&ir->l, &lirc_template, sizeof(struct lirc_dev));
+               ir->l = lirc_allocate_device();
+               if (!ir->l) {
+                       ret = -ENOMEM;
+                       goto out_put_ir;
+               }
+
+               snprintf(ir->l->name, sizeof(ir->l->name), "lirc_zilog");
+               ir->l->code_length = 13;
+               ir->l->fops = &lirc_fops;
+               ir->l->owner = THIS_MODULE;
+
                /*
                 * FIXME this is a pointer reference to us, but no refcount.
                 *
                 * This OK for now, since lirc_dev currently won't touch this
                 * buffer as we provide our own lirc_fops.
                 *
-                * Currently our own lirc_fops rely on this ir->l.rbuf pointer
+                * Currently our own lirc_fops rely on this ir->l->rbuf pointer
                 */
-               ir->l.rbuf = &ir->rbuf;
-               ir->l.dev  = &adap->dev;
+               ir->l->rbuf = &ir->rbuf;
+               ir->l->dev  = &adap->dev;
                /* This will be returned by lirc_get_pdata() */
-               ir->l.data = ir;
-               ret = lirc_buffer_init(ir->l.rbuf, 2, BUFLEN / 2);
-               if (ret)
+               ir->l->data = ir;
+               ret = lirc_buffer_init(ir->l->rbuf, 2, BUFLEN / 2);
+               if (ret) {
+                       lirc_free_device(ir->l);
+                       ir->l = NULL;
                        goto out_put_ir;
+               }
        }
 
        if (tx_probe) {
@@ -1474,7 +1483,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
                kref_init(&tx->ref);
                ir->tx = tx;
 
-               ir->l.features |= LIRC_CAN_SEND_LIRCCODE;
+               ir->l->features |= LIRC_CAN_SEND_LIRCCODE;
                mutex_init(&tx->client_lock);
                tx->c = client;
                tx->need_boot = 1;
@@ -1518,7 +1527,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
                kref_init(&rx->ref);
                ir->rx = rx;
 
-               ir->l.features |= LIRC_CAN_REC_LIRCCODE;
+               ir->l->features |= LIRC_CAN_REC_LIRCCODE;
                mutex_init(&rx->client_lock);
                rx->c = client;
                rx->hdpvr_data_fmt =
@@ -1548,7 +1557,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
                        /* Failure exit, so put back rx ref from i2c_client */
                        i2c_set_clientdata(client, NULL);
                        put_ir_rx(rx, true);
-                       ir->l.features &= ~LIRC_CAN_REC_LIRCCODE;
+                       ir->l->features &= ~LIRC_CAN_REC_LIRCCODE;
                        goto out_put_tx;
                }
 
@@ -1561,17 +1570,19 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
        }
 
        /* register with lirc */
-       ret = lirc_register_device(&ir->l);
+       ret = lirc_register_device(ir->l);
        if (ret < 0) {
                dev_err(tx->ir->dev,
                        "%s: lirc_register_device() failed: %i\n",
                        __func__, ret);
+               lirc_free_device(ir->l);
+               ir->l = NULL;
                goto out_put_xx;
        }
 
        dev_info(ir->dev,
                 "IR unit on %s (i2c-%d) registered as lirc%d and ready\n",
-                adap->name, adap->nr, ir->l.minor);
+                adap->name, adap->nr, ir->l->minor);
 
 out_ok:
        if (rx)