diff mbox

[v3,12/19,media] lirc: exorcise struct irctl

Message ID 2dda8e75a2827d44117860b1798c27b8df517711.1488023302.git.sean@mess.org (mailing list archive)
State New, archived
Headers show

Commit Message

Sean Young Feb. 25, 2017, 11:51 a.m. UTC
lirc_register_driver() takes a struct lirc_driver argument, it then
allocates a new struct irctl which contains another struct lirc_driver
and then copies it over.

By moving the members of struct irctl to struct lirc_driver, we avoid the
extra allocation and we can remove struct irctl completely. We also
remove the duplicate chunk_size member.

In addition, the members of irctl are now visible elsewhere.

Tested send, receive and rmmod with lirc_zilog and various rc-core
devices.

Signed-off-by: Sean Young <sean@mess.org>
---
 drivers/media/rc/ir-lirc-codec.c        |   3 +-
 drivers/media/rc/lirc_dev.c             | 353 +++++++++++++++-----------------
 drivers/staging/media/lirc/lirc_sasem.c |   3 +-
 drivers/staging/media/lirc/lirc_zilog.c | 167 ++++++++-------
 include/media/lirc_dev.h                |  33 ++-
 5 files changed, 288 insertions(+), 271 deletions(-)
diff mbox

Patch

diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
index 16ac65a..78f354a 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -407,7 +407,7 @@  int ir_lirc_register(struct rc_dev *dev)
 	drv->set_use_dec = &ir_lirc_close;
 	drv->code_length = sizeof(struct ir_raw_event) * 8;
 	drv->fops = &lirc_fops;
-	drv->dev = &dev->dev;
+	drv->dev.parent = &dev->dev;
 	drv->rdev = dev;
 	drv->owner = THIS_MODULE;
 
@@ -437,5 +437,4 @@  void ir_lirc_unregister(struct rc_dev *dev)
 	lirc_unregister_driver(lirc->drv->minor);
 	lirc_buffer_free(lirc->drv->rbuf);
 	kfree(lirc->drv->rbuf);
-	kfree(lirc->drv);
 }
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index 26e1983..44650e4 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -43,25 +43,9 @@ 
 
 static dev_t lirc_base_dev;
 
-struct irctl {
-	struct lirc_driver d;
-	int attached;
-	int open;
-
-	struct mutex irctl_lock;
-	struct lirc_buffer *buf;
-	unsigned int chunk_size;
-
-	struct device dev;
-	struct cdev cdev;
-
-	struct task_struct *task;
-	long jiffies_to_wait;
-};
-
 static DEFINE_MUTEX(lirc_dev_lock);
 
-static struct irctl *irctls[MAX_IRCTL_DEVICES];
+static struct lirc_driver *irctls[MAX_IRCTL_DEVICES];
 
 /* Only used for sysfs but defined to void otherwise */
 static struct class *lirc_class;
@@ -69,39 +53,39 @@  static struct class *lirc_class;
 /*  helper function
  *  initializes the irctl structure
  */
-static void lirc_irctl_init(struct irctl *ir)
+static void lirc_irctl_init(struct lirc_driver *d)
 {
-	mutex_init(&ir->irctl_lock);
-	ir->d.minor = NOPLUG;
+	mutex_init(&d->irctl_lock);
+	d->minor = NOPLUG;
 }
 
 static void lirc_release(struct device *ld)
 {
-	struct irctl *ir = container_of(ld, struct irctl, dev);
+	struct lirc_driver *d = container_of(ld, struct lirc_driver, dev);
 
-	put_device(ir->dev.parent);
+	put_device(d->dev.parent);
 
-	if (ir->buf != ir->d.rbuf) {
-		lirc_buffer_free(ir->buf);
-		kfree(ir->buf);
+	if (d->buf != d->rbuf) {
+		lirc_buffer_free(d->buf);
+		kfree(d->buf);
 	}
 
 	mutex_lock(&lirc_dev_lock);
-	irctls[ir->d.minor] = NULL;
+	irctls[d->minor] = NULL;
 	mutex_unlock(&lirc_dev_lock);
-	kfree(ir);
+	kfree(d);
 }
 
 /*  helper function
  *  reads key codes from driver and puts them into buffer
  *  returns 0 on success
  */
-static int lirc_add_to_buf(struct irctl *ir)
+static int lirc_add_to_buf(struct lirc_driver *d)
 {
 	int res;
 	int got_data = -1;
 
-	if (!ir->d.add_to_buf)
+	if (!d->add_to_buf)
 		return 0;
 
 	/*
@@ -110,31 +94,31 @@  static int lirc_add_to_buf(struct irctl *ir)
 	 */
 	do {
 		got_data++;
-		res = ir->d.add_to_buf(ir->d.data, ir->buf);
+		res = d->add_to_buf(d->data, d->buf);
 	} while (!res);
 
 	if (res == -ENODEV)
-		kthread_stop(ir->task);
+		kthread_stop(d->task);
 
 	return got_data ? 0 : res;
 }
 
 /* main function of the polling thread
  */
-static int lirc_thread(void *irctl)
+static int lirc_thread(void *lirc_driver)
 {
-	struct irctl *ir = irctl;
+	struct lirc_driver *d = lirc_driver;
 
 	do {
-		if (ir->open) {
-			if (ir->jiffies_to_wait) {
+		if (d->open) {
+			if (d->jiffies_to_wait) {
 				set_current_state(TASK_INTERRUPTIBLE);
-				schedule_timeout(ir->jiffies_to_wait);
+				schedule_timeout(d->jiffies_to_wait);
 			}
 			if (kthread_should_stop())
 				break;
-			if (!lirc_add_to_buf(ir))
-				wake_up_interruptible(&ir->buf->wait_poll);
+			if (!lirc_add_to_buf(d))
+				wake_up_interruptible(&d->buf->wait_poll);
 		} else {
 			set_current_state(TASK_INTERRUPTIBLE);
 			schedule();
@@ -144,7 +128,6 @@  static int lirc_thread(void *irctl)
 	return 0;
 }
 
-
 static const struct file_operations lirc_dev_fops = {
 	.owner		= THIS_MODULE,
 	.read		= lirc_dev_fop_read,
@@ -156,13 +139,12 @@  static const struct file_operations lirc_dev_fops = {
 	.llseek		= noop_llseek,
 };
 
-static int lirc_cdev_add(struct irctl *ir)
+static int lirc_cdev_add(struct lirc_driver *d)
 {
-	struct lirc_driver *d = &ir->d;
 	struct cdev *cdev;
 	int retval;
 
-	cdev = &ir->cdev;
+	cdev = &d->cdev;
 
 	if (d->fops) {
 		cdev_init(cdev, d->fops);
@@ -175,17 +157,16 @@  static int lirc_cdev_add(struct irctl *ir)
 	if (retval)
 		return retval;
 
-	cdev->kobj.parent = &ir->dev.kobj;
-	return cdev_add(cdev, ir->dev.devt, 1);
+	cdev->kobj.parent = &d->dev.kobj;
+	return cdev_add(cdev, d->dev.devt, 1);
 }
 
-static int lirc_allocate_buffer(struct irctl *ir)
+static int lirc_allocate_buffer(struct lirc_driver *d)
 {
 	int err = 0;
 	int bytes_in_key;
 	unsigned int chunk_size;
 	unsigned int buffer_size;
-	struct lirc_driver *d = &ir->d;
 
 	mutex_lock(&lirc_dev_lock);
 
@@ -195,21 +176,21 @@  static int lirc_allocate_buffer(struct irctl *ir)
 	chunk_size  = d->chunk_size  ? d->chunk_size  : bytes_in_key;
 
 	if (d->rbuf) {
-		ir->buf = d->rbuf;
+		d->buf = d->rbuf;
 	} else {
-		ir->buf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
-		if (!ir->buf) {
+		d->buf = kmalloc(sizeof(*d->buf), GFP_KERNEL);
+		if (!d->buf) {
 			err = -ENOMEM;
 			goto out;
 		}
 
-		err = lirc_buffer_init(ir->buf, chunk_size, buffer_size);
+		err = lirc_buffer_init(d->buf, chunk_size, buffer_size);
 		if (err) {
-			kfree(ir->buf);
+			kfree(d->buf);
 			goto out;
 		}
 	}
-	ir->chunk_size = ir->buf->chunk_size;
+	d->chunk_size = d->buf->chunk_size;
 
 out:
 	mutex_unlock(&lirc_dev_lock);
@@ -219,7 +200,6 @@  static int lirc_allocate_buffer(struct irctl *ir)
 
 static int lirc_allocate_driver(struct lirc_driver *d)
 {
-	struct irctl *ir;
 	int minor;
 	int err;
 
@@ -228,36 +208,36 @@  static int lirc_allocate_driver(struct lirc_driver *d)
 		return -EBADRQC;
 	}
 
-	if (!d->dev) {
+	if (!d->dev.parent) {
 		pr_err("dev pointer not filled in!\n");
 		return -EINVAL;
 	}
 
 	if (d->minor >= MAX_IRCTL_DEVICES) {
-		dev_err(d->dev, "minor must be between 0 and %d!\n",
-						MAX_IRCTL_DEVICES - 1);
+		dev_err(d->dev.parent, "minor must be between 0 and %d!\n",
+			MAX_IRCTL_DEVICES - 1);
 		return -EBADRQC;
 	}
 
 	if (d->code_length < 1 || d->code_length > (BUFLEN * 8)) {
-		dev_err(d->dev, "code length must be less than %d bits\n",
-								BUFLEN * 8);
+		dev_err(d->dev.parent, "code length must be less than %d bits\n",
+			BUFLEN * 8);
 		return -EBADRQC;
 	}
 
 	if (d->sample_rate) {
 		if (2 > d->sample_rate || HZ < d->sample_rate) {
-			dev_err(d->dev, "invalid %d sample rate\n",
-							d->sample_rate);
+			dev_err(d->dev.parent, "invalid %d sample rate\n",
+				d->sample_rate);
 			return -EBADRQC;
 		}
 		if (!d->add_to_buf) {
-			dev_err(d->dev, "add_to_buf not set\n");
+			dev_err(d->dev.parent, "add_to_buf not set\n");
 			return -EBADRQC;
 		}
 	} else if (!d->rbuf && !(d->fops && d->fops->read &&
 				d->fops->poll && d->fops->unlocked_ioctl)) {
-		dev_err(d->dev, "undefined read, poll, ioctl\n");
+		dev_err(d->dev.parent, "undefined read, poll, ioctl\n");
 		return -EBADRQC;
 	}
 
@@ -271,23 +251,18 @@  static int lirc_allocate_driver(struct lirc_driver *d)
 			if (!irctls[minor])
 				break;
 		if (minor == MAX_IRCTL_DEVICES) {
-			dev_err(d->dev, "no free slots for drivers!\n");
+			dev_err(d->dev.parent, "no free slots for drivers!\n");
 			err = -ENOMEM;
 			goto out_lock;
 		}
 	} else if (irctls[minor]) {
-		dev_err(d->dev, "minor (%d) just registered!\n", minor);
+		dev_err(d->dev.parent, "minor (%d) just registered!\n", minor);
 		err = -EBUSY;
 		goto out_lock;
 	}
 
-	ir = kzalloc(sizeof(struct irctl), GFP_KERNEL);
-	if (!ir) {
-		err = -ENOMEM;
-		goto out_lock;
-	}
-	lirc_irctl_init(ir);
-	irctls[minor] = ir;
+	lirc_irctl_init(d);
+	irctls[minor] = d;
 	d->minor = minor;
 
 	/* some safety check 8-) */
@@ -296,52 +271,49 @@  static int lirc_allocate_driver(struct lirc_driver *d)
 	if (d->features == 0)
 		d->features = LIRC_CAN_REC_LIRCCODE;
 
-	ir->d = *d;
-
-	ir->dev.devt = MKDEV(MAJOR(lirc_base_dev), ir->d.minor);
-	ir->dev.class = lirc_class;
-	ir->dev.parent = d->dev;
-	ir->dev.release = lirc_release;
-	dev_set_name(&ir->dev, "lirc%d", ir->d.minor);
-	device_initialize(&ir->dev);
+	d->dev.devt = MKDEV(MAJOR(lirc_base_dev), d->minor);
+	d->dev.class = lirc_class;
+	d->dev.release = lirc_release;
+	dev_set_name(&d->dev, "lirc%d", d->minor);
+	device_initialize(&d->dev);
 
 	if (d->sample_rate) {
-		ir->jiffies_to_wait = HZ / d->sample_rate;
+		d->jiffies_to_wait = HZ / d->sample_rate;
 
 		/* try to fire up polling thread */
-		ir->task = kthread_run(lirc_thread, (void *)ir, "lirc_dev");
-		if (IS_ERR(ir->task)) {
-			dev_err(d->dev, "cannot run thread for minor = %d\n",
-								d->minor);
+		d->task = kthread_run(lirc_thread, d, "lirc_dev");
+		if (IS_ERR(d->task)) {
+			dev_err(d->dev.parent, "cannot run thread for minor = %d\n",
+				d->minor);
 			err = -ECHILD;
 			goto out_sysfs;
 		}
 	} else {
 		/* it means - wait for external event in task queue */
-		ir->jiffies_to_wait = 0;
+		d->jiffies_to_wait = 0;
 	}
 
-	err = lirc_cdev_add(ir);
+	err = lirc_cdev_add(d);
 	if (err)
 		goto out_sysfs;
 
-	ir->attached = 1;
+	d->attached = 1;
 
-	err = device_add(&ir->dev);
+	err = device_add(&d->dev);
 	if (err)
 		goto out_cdev;
 
 	mutex_unlock(&lirc_dev_lock);
 
-	get_device(ir->dev.parent);
+	get_device(d->dev.parent);
 
-	dev_info(ir->d.dev, "lirc_dev: driver %s registered at minor = %d\n",
-		 ir->d.name, ir->d.minor);
+	dev_info(d->dev.parent, "lirc_dev: driver %s registered at minor = %d\n",
+		 d->name, d->minor);
 	return minor;
 out_cdev:
-	cdev_del(&ir->cdev);
+	cdev_del(&d->cdev);
 out_sysfs:
-	put_device(&ir->dev);
+	put_device(&d->dev);
 out_lock:
 	mutex_unlock(&lirc_dev_lock);
 
@@ -368,7 +340,7 @@  EXPORT_SYMBOL(lirc_register_driver);
 
 int lirc_unregister_driver(int minor)
 {
-	struct irctl *ir;
+	struct lirc_driver *d;
 
 	if (minor < 0 || minor >= MAX_IRCTL_DEVICES) {
 		pr_err("minor (%d) must be between 0 and %d!\n",
@@ -376,46 +348,46 @@  int lirc_unregister_driver(int minor)
 		return -EBADRQC;
 	}
 
-	ir = irctls[minor];
-	if (!ir) {
+	d = irctls[minor];
+	if (!d) {
 		pr_err("failed to get irctl\n");
 		return -ENOENT;
 	}
 
 	mutex_lock(&lirc_dev_lock);
 
-	if (ir->d.minor != minor) {
-		dev_err(ir->d.dev, "lirc_dev: minor %d device not registered\n",
-									minor);
+	if (d->minor != minor) {
+		dev_err(d->dev.parent, "lirc_dev: minor %d device not registered\n",
+			minor);
 		mutex_unlock(&lirc_dev_lock);
 		return -ENOENT;
 	}
 
 	/* end up polling thread */
-	if (ir->task)
-		kthread_stop(ir->task);
+	if (d->task)
+		kthread_stop(d->task);
 
-	dev_dbg(ir->d.dev, "lirc_dev: driver %s unregistered from minor = %d\n",
-		ir->d.name, ir->d.minor);
+	dev_dbg(d->dev.parent, "lirc_dev: driver %s unregistered from minor = %d\n",
+		d->name, d->minor);
 
-	ir->attached = 0;
-	if (ir->open) {
-		dev_dbg(ir->d.dev, LOGHEAD "releasing opened driver\n",
-			ir->d.name, ir->d.minor);
-		wake_up_interruptible(&ir->buf->wait_poll);
+	d->attached = 0;
+	if (d->open) {
+		dev_dbg(d->dev.parent, LOGHEAD "releasing opened driver\n",
+			d->name, d->minor);
+		wake_up_interruptible(&d->buf->wait_poll);
 	}
 
-	mutex_lock(&ir->irctl_lock);
+	mutex_lock(&d->irctl_lock);
 
-	if (ir->d.set_use_dec)
-		ir->d.set_use_dec(ir->d.data);
+	if (d->set_use_dec)
+		d->set_use_dec(d->data);
 
-	mutex_unlock(&ir->irctl_lock);
+	mutex_unlock(&d->irctl_lock);
 	mutex_unlock(&lirc_dev_lock);
 
-	device_del(&ir->dev);
-	cdev_del(&ir->cdev);
-	put_device(&ir->dev);
+	device_del(&d->dev);
+	cdev_del(&d->cdev);
+	put_device(&d->dev);
 
 	return 0;
 }
@@ -423,7 +395,7 @@  EXPORT_SYMBOL(lirc_unregister_driver);
 
 int lirc_dev_fop_open(struct inode *inode, struct file *file)
 {
-	struct irctl *ir;
+	struct lirc_driver *d;
 	int retval = 0;
 
 	if (iminor(inode) >= MAX_IRCTL_DEVICES) {
@@ -434,40 +406,40 @@  int lirc_dev_fop_open(struct inode *inode, struct file *file)
 	if (mutex_lock_interruptible(&lirc_dev_lock))
 		return -ERESTARTSYS;
 
-	ir = irctls[iminor(inode)];
-	if (!ir) {
+	d = irctls[iminor(inode)];
+	if (!d) {
 		retval = -ENODEV;
 		goto error;
 	}
 
-	dev_dbg(ir->d.dev, LOGHEAD "open called\n", ir->d.name, ir->d.minor);
+	dev_dbg(d->dev.parent, LOGHEAD "open called\n", d->name, d->minor);
 
-	if (ir->d.minor == NOPLUG) {
+	if (d->minor == NOPLUG) {
 		retval = -ENODEV;
 		goto error;
 	}
 
-	if (ir->open) {
+	if (d->open) {
 		retval = -EBUSY;
 		goto error;
 	}
 
-	if (ir->d.rdev) {
-		retval = rc_open(ir->d.rdev);
+	if (d->rdev) {
+		retval = rc_open(d->rdev);
 		if (retval)
 			goto error;
 	}
 
-	ir->open++;
-	if (ir->d.set_use_inc)
-		retval = ir->d.set_use_inc(ir->d.data);
+	d->open++;
+	if (d->set_use_inc)
+		retval = d->set_use_inc(d->data);
 	if (retval) {
-		ir->open--;
+		d->open--;
 	} else {
-		if (ir->buf)
-			lirc_buffer_clear(ir->buf);
-		if (ir->task)
-			wake_up_process(ir->task);
+		if (d->buf)
+			lirc_buffer_clear(d->buf);
+		if (d->task)
+			wake_up_process(d->task);
 	}
 
 error:
@@ -481,10 +453,10 @@  EXPORT_SYMBOL(lirc_dev_fop_open);
 
 int lirc_dev_fop_close(struct inode *inode, struct file *file)
 {
-	struct irctl *ir = irctls[iminor(inode)];
+	struct lirc_driver *d = irctls[iminor(inode)];
 	int ret;
 
-	if (!ir) {
+	if (!d) {
 		pr_err("called with invalid irctl\n");
 		return -EINVAL;
 	}
@@ -492,11 +464,11 @@  int lirc_dev_fop_close(struct inode *inode, struct file *file)
 	ret = mutex_lock_killable(&lirc_dev_lock);
 	WARN_ON(ret);
 
-	rc_close(ir->d.rdev);
+	rc_close(d->rdev);
 
-	ir->open--;
-	if (ir->d.set_use_dec)
-		ir->d.set_use_dec(ir->d.data);
+	d->open--;
+	if (d->set_use_dec)
+		d->set_use_dec(d->data);
 	if (!ret)
 		mutex_unlock(&lirc_dev_lock);
 
@@ -506,29 +478,30 @@  EXPORT_SYMBOL(lirc_dev_fop_close);
 
 unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait)
 {
-	struct irctl *ir = irctls[iminor(file_inode(file))];
+	struct lirc_driver *d = irctls[iminor(file_inode(file))];
 	unsigned int ret;
 
-	if (!ir) {
+	if (!d) {
 		pr_err("called with invalid irctl\n");
 		return POLLERR;
 	}
 
-	if (!ir->attached)
+	if (!d->attached)
 		return POLLERR;
 
-	if (ir->buf) {
-		poll_wait(file, &ir->buf->wait_poll, wait);
+	if (d->buf) {
+		poll_wait(file, &d->buf->wait_poll, wait);
 
-		if (lirc_buffer_empty(ir->buf))
+		if (lirc_buffer_empty(d->buf))
 			ret = 0;
 		else
 			ret = POLLIN | POLLRDNORM;
-	} else
+	} else {
 		ret = POLLERR;
+	}
 
-	dev_dbg(ir->d.dev, LOGHEAD "poll result = %d\n",
-		ir->d.name, ir->d.minor, ret);
+	dev_dbg(d->dev.parent, LOGHEAD "poll result = %d\n",
+		d->name, d->minor, ret);
 
 	return ret;
 }
@@ -538,46 +511,46 @@  long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	__u32 mode;
 	int result = 0;
-	struct irctl *ir = irctls[iminor(file_inode(file))];
+	struct lirc_driver *d = irctls[iminor(file_inode(file))];
 
-	if (!ir) {
+	if (!d) {
 		pr_err("no irctl found!\n");
 		return -ENODEV;
 	}
 
-	dev_dbg(ir->d.dev, LOGHEAD "ioctl called (0x%x)\n",
-		ir->d.name, ir->d.minor, cmd);
+	dev_dbg(d->dev.parent, LOGHEAD "ioctl called (0x%x)\n",
+		d->name, d->minor, cmd);
 
-	if (ir->d.minor == NOPLUG || !ir->attached) {
-		dev_err(ir->d.dev, LOGHEAD "ioctl result = -ENODEV\n",
-			ir->d.name, ir->d.minor);
+	if (d->minor == NOPLUG || !d->attached) {
+		dev_err(d->dev.parent, LOGHEAD "ioctl result = -ENODEV\n",
+			d->name, d->minor);
 		return -ENODEV;
 	}
 
-	mutex_lock(&ir->irctl_lock);
+	mutex_lock(&d->irctl_lock);
 
 	switch (cmd) {
 	case LIRC_GET_FEATURES:
-		result = put_user(ir->d.features, (__u32 __user *)arg);
+		result = put_user(d->features, (__u32 __user *)arg);
 		break;
 	case LIRC_GET_REC_MODE:
-		if (!LIRC_CAN_REC(ir->d.features)) {
+		if (!LIRC_CAN_REC(d->features)) {
 			result = -ENOTTY;
 			break;
 		}
 
 		result = put_user(LIRC_REC2MODE
-				  (ir->d.features & LIRC_CAN_REC_MASK),
+				  (d->features & LIRC_CAN_REC_MASK),
 				  (__u32 __user *)arg);
 		break;
 	case LIRC_SET_REC_MODE:
-		if (!LIRC_CAN_REC(ir->d.features)) {
+		if (!LIRC_CAN_REC(d->features)) {
 			result = -ENOTTY;
 			break;
 		}
 
 		result = get_user(mode, (__u32 __user *)arg);
-		if (!result && !(LIRC_MODE2REC(mode) & ir->d.features))
+		if (!result && !(LIRC_MODE2REC(mode) & d->features))
 			result = -EINVAL;
 		/*
 		 * FIXME: We should actually set the mode somehow but
@@ -585,31 +558,31 @@  long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 		 */
 		break;
 	case LIRC_GET_LENGTH:
-		result = put_user(ir->d.code_length, (__u32 __user *)arg);
+		result = put_user(d->code_length, (__u32 __user *)arg);
 		break;
 	case LIRC_GET_MIN_TIMEOUT:
-		if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) ||
-		    ir->d.min_timeout == 0) {
+		if (!(d->features & LIRC_CAN_SET_REC_TIMEOUT) ||
+		    d->min_timeout == 0) {
 			result = -ENOTTY;
 			break;
 		}
 
-		result = put_user(ir->d.min_timeout, (__u32 __user *)arg);
+		result = put_user(d->min_timeout, (__u32 __user *)arg);
 		break;
 	case LIRC_GET_MAX_TIMEOUT:
-		if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) ||
-		    ir->d.max_timeout == 0) {
+		if (!(d->features & LIRC_CAN_SET_REC_TIMEOUT) ||
+		    d->max_timeout == 0) {
 			result = -ENOTTY;
 			break;
 		}
 
-		result = put_user(ir->d.max_timeout, (__u32 __user *)arg);
+		result = put_user(d->max_timeout, (__u32 __user *)arg);
 		break;
 	default:
 		result = -ENOTTY;
 	}
 
-	mutex_unlock(&ir->irctl_lock);
+	mutex_unlock(&d->irctl_lock);
 
 	return result;
 }
@@ -620,35 +593,35 @@  ssize_t lirc_dev_fop_read(struct file *file,
 			  size_t length,
 			  loff_t *ppos)
 {
-	struct irctl *ir = irctls[iminor(file_inode(file))];
+	struct lirc_driver *d = irctls[iminor(file_inode(file))];
 	unsigned char *buf;
 	int ret = 0, written = 0;
 	DECLARE_WAITQUEUE(wait, current);
 
-	if (!ir) {
+	if (!d) {
 		pr_err("called with invalid irctl\n");
 		return -ENODEV;
 	}
 
-	if (!LIRC_CAN_REC(ir->d.features))
+	if (!LIRC_CAN_REC(d->features))
 		return -EINVAL;
 
-	dev_dbg(ir->d.dev, LOGHEAD "read called\n", ir->d.name, ir->d.minor);
+	dev_dbg(d->dev.parent, LOGHEAD "read called\n", d->name, d->minor);
 
-	buf = kzalloc(ir->chunk_size, GFP_KERNEL);
+	buf = kzalloc(d->chunk_size, GFP_KERNEL);
 	if (!buf)
 		return -ENOMEM;
 
-	if (mutex_lock_interruptible(&ir->irctl_lock)) {
+	if (mutex_lock_interruptible(&d->irctl_lock)) {
 		ret = -ERESTARTSYS;
 		goto out_unlocked;
 	}
-	if (!ir->attached) {
+	if (!d->attached) {
 		ret = -ENODEV;
 		goto out_locked;
 	}
 
-	if (length % ir->chunk_size) {
+	if (length % d->chunk_size) {
 		ret = -EINVAL;
 		goto out_locked;
 	}
@@ -658,14 +631,14 @@  ssize_t lirc_dev_fop_read(struct file *file,
 	 * to avoid losing scan code (in case when queue is awaken somewhere
 	 * between while condition checking and scheduling)
 	 */
-	add_wait_queue(&ir->buf->wait_poll, &wait);
+	add_wait_queue(&d->buf->wait_poll, &wait);
 
 	/*
 	 * while we didn't provide 'length' bytes, device is opened in blocking
 	 * mode and 'copy_to_user' is happy, wait for data.
 	 */
 	while (written < length && ret == 0) {
-		if (lirc_buffer_empty(ir->buf)) {
+		if (lirc_buffer_empty(d->buf)) {
 			/* According to the read(2) man page, 'written' can be
 			 * returned as less than 'length', instead of blocking
 			 * again, returning -EWOULDBLOCK, or returning
@@ -682,36 +655,36 @@  ssize_t lirc_dev_fop_read(struct file *file,
 				break;
 			}
 
-			mutex_unlock(&ir->irctl_lock);
+			mutex_unlock(&d->irctl_lock);
 			set_current_state(TASK_INTERRUPTIBLE);
 			schedule();
 			set_current_state(TASK_RUNNING);
 
-			if (mutex_lock_interruptible(&ir->irctl_lock)) {
+			if (mutex_lock_interruptible(&d->irctl_lock)) {
 				ret = -ERESTARTSYS;
-				remove_wait_queue(&ir->buf->wait_poll, &wait);
+				remove_wait_queue(&d->buf->wait_poll, &wait);
 				goto out_unlocked;
 			}
 
-			if (!ir->attached) {
+			if (!d->attached) {
 				ret = -ENODEV;
 				goto out_locked;
 			}
 		} else {
-			lirc_buffer_read(ir->buf, buf);
+			lirc_buffer_read(d->buf, buf);
 			ret = copy_to_user((void __user *)buffer+written, buf,
-					   ir->buf->chunk_size);
+					   d->buf->chunk_size);
 			if (!ret)
-				written += ir->buf->chunk_size;
+				written += d->buf->chunk_size;
 			else
 				ret = -EFAULT;
 		}
 	}
 
-	remove_wait_queue(&ir->buf->wait_poll, &wait);
+	remove_wait_queue(&d->buf->wait_poll, &wait);
 
 out_locked:
-	mutex_unlock(&ir->irctl_lock);
+	mutex_unlock(&d->irctl_lock);
 
 out_unlocked:
 	kfree(buf);
@@ -722,7 +695,7 @@  EXPORT_SYMBOL(lirc_dev_fop_read);
 
 void *lirc_get_pdata(struct file *file)
 {
-	return irctls[iminor(file_inode(file))]->d.data;
+	return irctls[iminor(file_inode(file))]->data;
 }
 EXPORT_SYMBOL(lirc_get_pdata);
 
@@ -730,14 +703,14 @@  EXPORT_SYMBOL(lirc_get_pdata);
 ssize_t lirc_dev_fop_write(struct file *file, const char __user *buffer,
 			   size_t length, loff_t *ppos)
 {
-	struct irctl *ir = irctls[iminor(file_inode(file))];
+	struct lirc_driver *d = irctls[iminor(file_inode(file))];
 
-	if (!ir) {
+	if (!d) {
 		pr_err("called with invalid irctl\n");
 		return -ENODEV;
 	}
 
-	if (!ir->attached)
+	if (!d->attached)
 		return -ENODEV;
 
 	return -EINVAL;
diff --git a/drivers/staging/media/lirc/lirc_sasem.c b/drivers/staging/media/lirc/lirc_sasem.c
index b0c176e..583e12e 100644
--- a/drivers/staging/media/lirc/lirc_sasem.c
+++ b/drivers/staging/media/lirc/lirc_sasem.c
@@ -167,7 +167,6 @@  static void delete_context(struct sasem_context *context)
 	usb_free_urb(context->rx_urb);  /* IR */
 	lirc_buffer_free(context->driver->rbuf);
 	kfree(context->driver->rbuf);
-	kfree(context->driver);
 	kfree(context);
 }
 
@@ -771,7 +770,7 @@  static int sasem_probe(struct usb_interface *interface,
 	driver->rbuf = rbuf;
 	driver->set_use_inc = ir_open;
 	driver->set_use_dec = ir_close;
-	driver->dev   = &interface->dev;
+	driver->dev.parent = &interface->dev;
 	driver->owner = THIS_MODULE;
 
 	mutex_lock(&context->ctx_lock);
diff --git a/drivers/staging/media/lirc/lirc_zilog.c b/drivers/staging/media/lirc/lirc_zilog.c
index 34aac3e..5deb67db 100644
--- a/drivers/staging/media/lirc/lirc_zilog.c
+++ b/drivers/staging/media/lirc/lirc_zilog.c
@@ -100,7 +100,7 @@  struct IR {
 	struct list_head list;
 
 	/* FIXME spinlock access to l.features */
-	struct lirc_driver l;
+	struct lirc_driver *l;
 	struct lirc_buffer rbuf;
 
 	struct mutex ir_lock;
@@ -184,9 +184,9 @@  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
 	 */
-	if (ir->l.minor >= 0 && ir->l.minor < MAX_IRCTL_DEVICES) {
-		lirc_unregister_driver(ir->l.minor);
-		ir->l.minor = MAX_IRCTL_DEVICES;
+	if (ir->l->minor >= 0 && ir->l->minor < MAX_IRCTL_DEVICES) {
+		lirc_unregister_driver(ir->l->minor);
+		ir->l->minor = MAX_IRCTL_DEVICES;
 	}
 	if (kfifo_initialized(&ir->rbuf.fifo))
 		lirc_buffer_free(&ir->rbuf);
@@ -243,7 +243,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 */
@@ -288,7 +288,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_PULSE;
+	ir->l->features &= ~LIRC_CAN_SEND_PULSE;
 	/* Don't put_ir_device(tx->ir) here, so our lock doesn't get freed */
 	ir->tx = NULL;
 	kfree(tx);
@@ -317,12 +317,12 @@  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;
 
 	if (lirc_buffer_full(rbuf)) {
-		dev_dbg(ir->l.dev, "buffer overflow\n");
+		dev_dbg(&ir->adapter->dev, "buffer overflow\n");
 		return -EOVERFLOW;
 	}
 
@@ -368,17 +368,17 @@  static int add_to_buf(struct IR *ir)
 		 */
 		ret = i2c_master_send(rx->c, sendbuf, 1);
 		if (ret != 1) {
-			dev_err(ir->l.dev, "i2c_master_send failed with %d\n",
+			dev_err(&ir->adapter->dev, "i2c_master_send failed with %d\n",
 				ret);
 			if (failures >= 3) {
 				mutex_unlock(&ir->ir_lock);
-				dev_err(ir->l.dev,
+				dev_err(&ir->adapter->dev,
 					"unable to read from the IR chip after 3 resets, giving up\n");
 				break;
 			}
 
 			/* Looks like the chip crashed, reset it */
-			dev_err(ir->l.dev,
+			dev_err(&ir->adapter->dev,
 				"polling the IR receiver chip failed, trying reset\n");
 
 			set_current_state(TASK_UNINTERRUPTIBLE);
@@ -405,14 +405,14 @@  static int add_to_buf(struct IR *ir)
 		ret = i2c_master_recv(rx->c, keybuf, sizeof(keybuf));
 		mutex_unlock(&ir->ir_lock);
 		if (ret != sizeof(keybuf)) {
-			dev_err(ir->l.dev,
+			dev_err(&ir->adapter->dev,
 				"i2c_master_recv failed with %d -- keeping last read buffer\n",
 				ret);
 		} else {
 			rx->b[0] = keybuf[3];
 			rx->b[1] = keybuf[4];
 			rx->b[2] = keybuf[5];
-			dev_dbg(ir->l.dev,
+			dev_dbg(&ir->adapter->dev,
 				"key (0x%02x/0x%02x)\n",
 				rx->b[0], rx->b[1]);
 		}
@@ -463,9 +463,9 @@  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->l.dev, "poll thread started\n");
+	dev_dbg(&ir->adapter->dev, "poll thread started\n");
 
 	while (!kthread_should_stop()) {
 		set_current_state(TASK_INTERRUPTIBLE);
@@ -493,7 +493,7 @@  static int lirc_thread(void *arg)
 			wake_up_interruptible(&rbuf->wait_poll);
 	}
 
-	dev_dbg(ir->l.dev, "poll thread ended\n");
+	dev_dbg(&ir->adapter->dev, "poll thread ended\n");
 	return 0;
 }
 
@@ -655,10 +655,10 @@  static int send_data_block(struct IR_tx *tx, unsigned char *data_block)
 		buf[0] = (unsigned char)(i + 1);
 		for (j = 0; j < tosend; ++j)
 			buf[1 + j] = data_block[i + j];
-		dev_dbg(tx->ir->l.dev, "%*ph", 5, buf);
+		dev_dbg(&tx->ir->adapter->dev, "%*ph", 5, buf);
 		ret = i2c_master_send(tx->c, buf, tosend + 1);
 		if (ret != tosend + 1) {
-			dev_err(tx->ir->l.dev,
+			dev_err(&tx->ir->adapter->dev,
 				"i2c_master_send failed with %d\n", ret);
 			return ret < 0 ? ret : -EFAULT;
 		}
@@ -683,7 +683,8 @@  static int send_boot_data(struct IR_tx *tx)
 	buf[1] = 0x20;
 	ret = i2c_master_send(tx->c, buf, 2);
 	if (ret != 2) {
-		dev_err(tx->ir->l.dev, "i2c_master_send failed with %d\n", ret);
+		dev_err(&tx->ir->adapter->dev, "i2c_master_send failed with %d\n",
+			ret);
 		return ret < 0 ? ret : -EFAULT;
 	}
 
@@ -700,22 +701,24 @@  static int send_boot_data(struct IR_tx *tx)
 	}
 
 	if (ret != 1) {
-		dev_err(tx->ir->l.dev, "i2c_master_send failed with %d\n", ret);
+		dev_err(&tx->ir->adapter->dev, "i2c_master_send failed with %d\n",
+			ret);
 		return ret < 0 ? ret : -EFAULT;
 	}
 
 	/* Here comes the firmware version... (hopefully) */
 	ret = i2c_master_recv(tx->c, buf, 4);
 	if (ret != 4) {
-		dev_err(tx->ir->l.dev, "i2c_master_recv failed with %d\n", ret);
+		dev_err(&tx->ir->adapter->dev, "i2c_master_recv failed with %d\n",
+			ret);
 		return 0;
 	}
 	if ((buf[0] != 0x80) && (buf[0] != 0xa0)) {
-		dev_err(tx->ir->l.dev, "unexpected IR TX init response: %02x\n",
+		dev_err(&tx->ir->adapter->dev, "unexpected IR TX init response: %02x\n",
 			buf[0]);
 		return 0;
 	}
-	dev_notice(tx->ir->l.dev,
+	dev_notice(&tx->ir->adapter->dev,
 		   "Zilog/Hauppauge IR blaster firmware version %d.%d.%d loaded\n",
 		   buf[1], buf[2], buf[3]);
 
@@ -760,15 +763,17 @@  static int fw_load(struct IR_tx *tx)
 	}
 
 	/* Request codeset data file */
-	ret = request_firmware(&fw_entry, "haup-ir-blaster.bin", tx->ir->l.dev);
+	ret = request_firmware(&fw_entry, "haup-ir-blaster.bin",
+			       &tx->ir->adapter->dev);
 	if (ret != 0) {
-		dev_err(tx->ir->l.dev,
+		dev_err(&tx->ir->adapter->dev,
 			"firmware haup-ir-blaster.bin not available (%d)\n",
 			ret);
 		ret = ret < 0 ? ret : -EFAULT;
 		goto out;
 	}
-	dev_dbg(tx->ir->l.dev, "firmware of size %zu loaded\n", fw_entry->size);
+	dev_dbg(&tx->ir->adapter->dev, "firmware of size %zu loaded\n",
+		fw_entry->size);
 
 	/* Parse the file */
 	tx_data = vmalloc(sizeof(*tx_data));
@@ -796,7 +801,7 @@  static int fw_load(struct IR_tx *tx)
 	if (!read_uint8(&data, tx_data->endp, &version))
 		goto corrupt;
 	if (version != 1) {
-		dev_err(tx->ir->l.dev,
+		dev_err(&tx->ir->adapter->dev,
 			"unsupported code set file version (%u, expected 1) -- please upgrade to a newer driver\n",
 			version);
 		fw_unload_locked();
@@ -813,7 +818,7 @@  static int fw_load(struct IR_tx *tx)
 			      &tx_data->num_code_sets))
 		goto corrupt;
 
-	dev_dbg(tx->ir->l.dev, "%u IR blaster codesets loaded\n",
+	dev_dbg(&tx->ir->adapter->dev, "%u IR blaster codesets loaded\n",
 		tx_data->num_code_sets);
 
 	tx_data->code_sets = vmalloc(
@@ -878,7 +883,7 @@  static int fw_load(struct IR_tx *tx)
 	goto out;
 
 corrupt:
-	dev_err(tx->ir->l.dev, "firmware is corrupt\n");
+	dev_err(&tx->ir->adapter->dev, "firmware is corrupt\n");
 	fw_unload_locked();
 	ret = -EFAULT;
 
@@ -893,14 +898,14 @@  static ssize_t read(struct file *filep, char __user *outbuf, size_t n,
 {
 	struct IR *ir = filep->private_data;
 	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);
 
-	dev_dbg(ir->l.dev, "read called\n");
+	dev_dbg(&ir->adapter->dev, "read called\n");
 	if (n % rbuf->chunk_size) {
-		dev_dbg(ir->l.dev, "read result = -EINVAL\n");
+		dev_dbg(&ir->adapter->dev, "read result = -EINVAL\n");
 		return -EINVAL;
 	}
 
@@ -944,7 +949,7 @@  static ssize_t read(struct file *filep, char __user *outbuf, size_t n,
 			unsigned char buf[MAX_XFER_SIZE];
 
 			if (rbuf->chunk_size > sizeof(buf)) {
-				dev_err(ir->l.dev,
+				dev_err(&ir->adapter->dev,
 					"chunk_size is too big (%d)!\n",
 					rbuf->chunk_size);
 				ret = -EINVAL;
@@ -959,7 +964,7 @@  static ssize_t read(struct file *filep, char __user *outbuf, size_t n,
 				retries++;
 			}
 			if (retries >= 5) {
-				dev_err(ir->l.dev, "Buffer read failed!\n");
+				dev_err(&ir->adapter->dev, "Buffer read failed!\n");
 				ret = -EIO;
 			}
 		}
@@ -969,7 +974,7 @@  static ssize_t read(struct file *filep, char __user *outbuf, size_t n,
 	put_ir_rx(rx, false);
 	set_current_state(TASK_RUNNING);
 
-	dev_dbg(ir->l.dev, "read result = %d (%s)\n", ret,
+	dev_dbg(&ir->adapter->dev, "read result = %d (%s)\n", ret,
 		ret ? "Error" : "OK");
 
 	return ret ? ret : written;
@@ -986,7 +991,7 @@  static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key)
 	ret = get_key_data(data_block, code, key);
 
 	if (ret == -EPROTO) {
-		dev_err(tx->ir->l.dev,
+		dev_err(&tx->ir->adapter->dev,
 			"failed to get data for code %u, key %u -- check lircd.conf entries\n",
 			code, key);
 		return ret;
@@ -1003,7 +1008,8 @@  static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key)
 	buf[1] = 0x40;
 	ret = i2c_master_send(tx->c, buf, 2);
 	if (ret != 2) {
-		dev_err(tx->ir->l.dev, "i2c_master_send failed with %d\n", ret);
+		dev_err(&tx->ir->adapter->dev, "i2c_master_send failed with %d\n",
+			ret);
 		return ret < 0 ? ret : -EFAULT;
 	}
 
@@ -1016,18 +1022,20 @@  static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key)
 	}
 
 	if (ret != 1) {
-		dev_err(tx->ir->l.dev, "i2c_master_send failed with %d\n", ret);
+		dev_err(&tx->ir->adapter->dev, "i2c_master_send failed with %d\n",
+			ret);
 		return ret < 0 ? ret : -EFAULT;
 	}
 
 	/* Send finished download? */
 	ret = i2c_master_recv(tx->c, buf, 1);
 	if (ret != 1) {
-		dev_err(tx->ir->l.dev, "i2c_master_recv failed with %d\n", ret);
+		dev_err(&tx->ir->adapter->dev, "i2c_master_recv failed with %d\n",
+			ret);
 		return ret < 0 ? ret : -EFAULT;
 	}
 	if (buf[0] != 0xA0) {
-		dev_err(tx->ir->l.dev, "unexpected IR TX response #1: %02x\n",
+		dev_err(&tx->ir->adapter->dev, "unexpected IR TX response #1: %02x\n",
 			buf[0]);
 		return -EFAULT;
 	}
@@ -1037,7 +1045,8 @@  static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key)
 	buf[1] = 0x80;
 	ret = i2c_master_send(tx->c, buf, 2);
 	if (ret != 2) {
-		dev_err(tx->ir->l.dev, "i2c_master_send failed with %d\n", ret);
+		dev_err(&tx->ir->adapter->dev, "i2c_master_send failed with %d\n",
+			ret);
 		return ret < 0 ? ret : -EFAULT;
 	}
 
@@ -1047,7 +1056,8 @@  static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key)
 	 * going to skip this whole mess and say we're done on the HD PVR
 	 */
 	if (!tx->post_tx_ready_poll) {
-		dev_dbg(tx->ir->l.dev, "sent code %u, key %u\n", code, key);
+		dev_dbg(&tx->ir->adapter->dev, "sent code %u, key %u\n",
+			code, key);
 		return 0;
 	}
 
@@ -1063,12 +1073,12 @@  static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key)
 		ret = i2c_master_send(tx->c, buf, 1);
 		if (ret == 1)
 			break;
-		dev_dbg(tx->ir->l.dev,
+		dev_dbg(&tx->ir->adapter->dev,
 			"NAK expected: i2c_master_send failed with %d (try %d)\n",
 			ret, i+1);
 	}
 	if (ret != 1) {
-		dev_err(tx->ir->l.dev,
+		dev_err(&tx->ir->adapter->dev,
 			"IR TX chip never got ready: last i2c_master_send failed with %d\n",
 			ret);
 		return ret < 0 ? ret : -EFAULT;
@@ -1077,17 +1087,18 @@  static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key)
 	/* Seems to be an 'ok' response */
 	i = i2c_master_recv(tx->c, buf, 1);
 	if (i != 1) {
-		dev_err(tx->ir->l.dev, "i2c_master_recv failed with %d\n", ret);
+		dev_err(&tx->ir->adapter->dev, "i2c_master_recv failed with %d\n",
+			ret);
 		return -EFAULT;
 	}
 	if (buf[0] != 0x80) {
-		dev_err(tx->ir->l.dev, "unexpected IR TX response #2: %02x\n",
+		dev_err(&tx->ir->adapter->dev, "unexpected IR TX response #2: %02x\n",
 			buf[0]);
 		return -EFAULT;
 	}
 
 	/* Oh good, it worked */
-	dev_dbg(tx->ir->l.dev, "sent code %u, key %u\n", code, key);
+	dev_dbg(&tx->ir->adapter->dev, "sent code %u, key %u\n", code, key);
 	return 0;
 }
 
@@ -1173,11 +1184,11 @@  static ssize_t write(struct file *filep, const char __user *buf, size_t n,
 		 */
 		if (ret != 0) {
 			/* Looks like the chip crashed, reset it */
-			dev_err(tx->ir->l.dev,
+			dev_err(&tx->ir->adapter->dev,
 				"sending to the IR transmitter chip failed, trying reset\n");
 
 			if (failures >= 3) {
-				dev_err(tx->ir->l.dev,
+				dev_err(&tx->ir->adapter->dev,
 					"unable to send to the IR chip after 3 resets, giving up\n");
 				mutex_unlock(&ir->ir_lock);
 				mutex_unlock(&tx->client_lock);
@@ -1209,10 +1220,10 @@  static unsigned int poll(struct file *filep, poll_table *wait)
 {
 	struct IR *ir = filep->private_data;
 	struct IR_rx *rx;
-	struct lirc_buffer *rbuf = ir->l.rbuf;
+	struct lirc_buffer *rbuf = ir->l->rbuf;
 	unsigned int ret;
 
-	dev_dbg(ir->l.dev, "poll called\n");
+	dev_dbg(&ir->adapter->dev, "poll called\n");
 
 	rx = get_ir_rx(ir);
 	if (rx == NULL) {
@@ -1220,7 +1231,7 @@  static unsigned int poll(struct file *filep, poll_table *wait)
 		 * Revisit this, if our poll function ever reports writeable
 		 * status for Tx
 		 */
-		dev_dbg(ir->l.dev, "poll result = POLLERR\n");
+		dev_dbg(&ir->adapter->dev, "poll result = POLLERR\n");
 		return POLLERR;
 	}
 
@@ -1233,7 +1244,7 @@  static unsigned int poll(struct file *filep, poll_table *wait)
 	/* Indicate what ops could happen immediately without blocking */
 	ret = lirc_buffer_empty(rbuf) ? 0 : (POLLIN|POLLRDNORM);
 
-	dev_dbg(ir->l.dev, "poll result = %s\n",
+	dev_dbg(&ir->adapter->dev, "poll result = %s\n",
 		ret ? "POLLIN|POLLRDNORM" : "none");
 	return ret;
 }
@@ -1245,7 +1256,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:
@@ -1299,7 +1310,7 @@  static struct IR *get_ir_device_by_minor(unsigned int minor)
 
 	if (!list_empty(&ir_devices_list)) {
 		list_for_each_entry(ir, &ir_devices_list, list) {
-			if (ir->l.minor == minor) {
+			if (ir->l->minor == minor) {
 				ret = get_ir_device(ir, true);
 				break;
 			}
@@ -1475,11 +1486,17 @@  static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	ir = get_ir_device_by_adapter(adap);
 	if (ir == NULL) {
 		ir = kzalloc(sizeof(struct IR), GFP_KERNEL);
-		if (ir == NULL) {
+		if (!ir) {
 			ret = -ENOMEM;
 			goto out_no_ir;
 		}
 		kref_init(&ir->ref);
+		ir->l = kzalloc(sizeof(*ir->l), GFP_KERNEL);
+		if (!ir) {
+			ret = -ENOMEM;
+			kfree(ir);
+			goto out_no_ir;
+		}
 
 		/* store for use in ir_probe() again, and open() later on */
 		INIT_LIST_HEAD(&ir->list);
@@ -1492,19 +1509,19 @@  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_driver));
+		memcpy(ir->l, &lirc_template, sizeof(struct lirc_driver));
 		/*
 		 * 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;
-		ret = lirc_buffer_init(ir->l.rbuf,
-				       ir->l.chunk_size, ir->l.buffer_size);
+		ir->l->rbuf = &ir->rbuf;
+		ir->l->dev.parent = &adap->dev;
+		ret = lirc_buffer_init(ir->l->rbuf,
+				       ir->l->chunk_size, ir->l->buffer_size);
 		if (ret)
 			goto out_put_ir;
 	}
@@ -1522,7 +1539,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_PULSE;
+		ir->l->features |= LIRC_CAN_SEND_PULSE;
 		mutex_init(&tx->client_lock);
 		tx->c = client;
 		tx->need_boot = 1;
@@ -1548,7 +1565,7 @@  static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
 
 		/* Proceed only if the Rx client is also ready or not needed */
 		if (rx == NULL && !tx_only) {
-			dev_info(tx->ir->l.dev,
+			dev_info(&tx->ir->adapter->dev,
 				 "probe of IR Tx on %s (i2c-%d) done. Waiting on IR Rx.\n",
 				 adap->name, adap->nr);
 			goto out_ok;
@@ -1566,7 +1583,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 =
@@ -1588,7 +1605,7 @@  static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
 				       "zilog-rx-i2c-%d", adap->nr);
 		if (IS_ERR(rx->task)) {
 			ret = PTR_ERR(rx->task);
-			dev_err(tx->ir->l.dev,
+			dev_err(&tx->ir->adapter->dev,
 				"%s: could not start IR Rx polling thread\n",
 				__func__);
 			/* Failed kthread, so put back the ir ref */
@@ -1596,7 +1613,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_xx;
 		}
 
@@ -1609,18 +1626,18 @@  static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	}
 
 	/* register with lirc */
-	ir->l.minor = minor; /* module option: user requested minor number */
-	ir->l.minor = lirc_register_driver(&ir->l);
-	if (ir->l.minor < 0 || ir->l.minor >= MAX_IRCTL_DEVICES) {
-		dev_err(tx->ir->l.dev,
+	ir->l->minor = minor; /* module option: user requested minor number */
+	ir->l->minor = lirc_register_driver(ir->l);
+	if (ir->l->minor < 0 || ir->l->minor >= MAX_IRCTL_DEVICES) {
+		dev_err(&tx->ir->adapter->dev,
 			"%s: \"minor\" must be between 0 and %d (%d)!\n",
-			__func__, MAX_IRCTL_DEVICES-1, ir->l.minor);
+			__func__, MAX_IRCTL_DEVICES - 1, ir->l->minor);
 		ret = -EBADRQC;
 		goto out_put_xx;
 	}
-	dev_info(ir->l.dev,
+	dev_info(&ir->adapter->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 != NULL)
@@ -1628,7 +1645,7 @@  static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	if (tx != NULL)
 		put_ir_tx(tx, true);
 	put_ir_device(ir, true);
-	dev_info(ir->l.dev,
+	dev_info(&ir->adapter->dev,
 		 "probe of IR %s on %s (i2c-%d) done\n",
 		 tx_probe ? "Tx" : "Rx", adap->name, adap->nr);
 	mutex_unlock(&ir_devices_lock);
diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h
index cec7d35..98d4ed0 100644
--- a/include/media/lirc_dev.h
+++ b/include/media/lirc_dev.h
@@ -15,6 +15,8 @@ 
 #define mod(n, div) ((n) % (div))
 
 #include <linux/slab.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
 #include <linux/fs.h>
 #include <linux/ioctl.h>
 #include <linux/poll.h>
@@ -182,6 +184,20 @@  static inline unsigned int lirc_buffer_write(struct lirc_buffer *buf,
  *			device.
  *
  * @owner:		the module owning this struct
+ *
+ * @attached:		1 if the device is still attached, 0 otherwise
+ *
+ * @open:		1 if the lirc char device has been opened
+ *
+ * @irctl_lock:		mutex for the structure
+ *
+ * @buf:		read buffer used if rbuf is not set
+ *
+ * @cdev:		the char device structure
+ *
+ * @task:		thread performing read polling, if present
+ *
+ * @jiffies_to_wait:	jiffies to sleep in read polling thread
  */
 struct lirc_driver {
 	char name[40];
@@ -202,15 +218,28 @@  struct lirc_driver {
 	void (*set_use_dec)(void *data);
 	struct rc_dev *rdev;
 	const struct file_operations *fops;
-	struct device *dev;
+	struct device dev;
 	struct module *owner;
+
+	int attached;
+	int open;
+
+	struct mutex irctl_lock; /* locks this driver */
+	struct lirc_buffer *buf;
+
+	struct cdev cdev;
+
+	struct task_struct *task;
+	long jiffies_to_wait;
 };
 
 /* following functions can be called ONLY from user context
  *
  * returns negative value on error or minor number
  * of the registered device if success
- * contents of the structure pointed by p is copied
+ * contents of the structure pointed by will be freed once
+ * lirc_unregister_driver is called and all open file descriptors
+ * are closed.
  */
 extern int lirc_register_driver(struct lirc_driver *d);