summaryrefslogtreecommitdiff
path: root/drivers/media/rc/lirc_dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/rc/lirc_dev.c')
-rw-r--r--drivers/media/rc/lirc_dev.c48
1 files changed, 19 insertions, 29 deletions
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index 91f9bb87ce68..1688893a65bb 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -13,17 +13,13 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/sched.h>
+#include <linux/sched/signal.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/fs.h>
@@ -150,9 +146,6 @@ static const struct file_operations lirc_dev_fops = {
.write = lirc_dev_fop_write,
.poll = lirc_dev_fop_poll,
.unlocked_ioctl = lirc_dev_fop_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = lirc_dev_fop_ioctl,
-#endif
.open = lirc_dev_fop_open,
.release = lirc_dev_fop_close,
.llseek = noop_llseek,
@@ -160,19 +153,19 @@ static const struct file_operations lirc_dev_fops = {
static int lirc_cdev_add(struct irctl *ir)
{
- int retval = -ENOMEM;
struct lirc_driver *d = &ir->d;
struct cdev *cdev;
+ int retval;
- cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
+ cdev = cdev_alloc();
if (!cdev)
- goto err_out;
+ return -ENOMEM;
if (d->fops) {
- cdev_init(cdev, d->fops);
+ cdev->ops = d->fops;
cdev->owner = d->owner;
} else {
- cdev_init(cdev, &lirc_dev_fops);
+ cdev->ops = &lirc_dev_fops;
cdev->owner = THIS_MODULE;
}
retval = kobject_set_name(&cdev->kobj, "lirc%d", d->minor);
@@ -180,17 +173,15 @@ static int lirc_cdev_add(struct irctl *ir)
goto err_out;
retval = cdev_add(cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1);
- if (retval) {
- kobject_put(&cdev->kobj);
+ if (retval)
goto err_out;
- }
ir->cdev = cdev;
return 0;
err_out:
- kfree(cdev);
+ cdev_del(cdev);
return retval;
}
@@ -420,7 +411,6 @@ int lirc_unregister_driver(int minor)
} else {
lirc_irctl_cleanup(ir);
cdev_del(cdev);
- kfree(cdev);
kfree(ir);
irctls[minor] = NULL;
}
@@ -446,6 +436,8 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file)
return -ERESTARTSYS;
ir = irctls[iminor(inode)];
+ mutex_unlock(&lirc_dev_lock);
+
if (!ir) {
retval = -ENODEV;
goto error;
@@ -478,7 +470,7 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file)
if (retval) {
module_put(cdev->owner);
ir->open--;
- } else {
+ } else if (ir->buf) {
lirc_buffer_clear(ir->buf);
}
if (ir->task)
@@ -486,8 +478,6 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file)
}
error:
- mutex_unlock(&lirc_dev_lock);
-
nonseekable_open(inode, file);
return retval;
@@ -521,7 +511,6 @@ int lirc_dev_fop_close(struct inode *inode, struct file *file)
lirc_irctl_cleanup(ir);
cdev_del(cdev);
irctls[ir->d.minor] = NULL;
- kfree(cdev);
kfree(ir);
}
@@ -589,7 +578,7 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
result = put_user(ir->d.features, (__u32 __user *)arg);
break;
case LIRC_GET_REC_MODE:
- if (LIRC_CAN_REC(ir->d.features)) {
+ if (!LIRC_CAN_REC(ir->d.features)) {
result = -ENOTTY;
break;
}
@@ -599,7 +588,7 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
(__u32 __user *)arg);
break;
case LIRC_SET_REC_MODE:
- if (LIRC_CAN_REC(ir->d.features)) {
+ if (!LIRC_CAN_REC(ir->d.features)) {
result = -ENOTTY;
break;
}
@@ -658,6 +647,9 @@ ssize_t lirc_dev_fop_read(struct file *file,
return -ENODEV;
}
+ if (!LIRC_CAN_REC(ir->d.features))
+ return -EINVAL;
+
dev_dbg(ir->d.dev, LOGHEAD "read called\n", ir->d.name, ir->d.minor);
buf = kzalloc(ir->chunk_size, GFP_KERNEL);
@@ -684,7 +676,6 @@ ssize_t lirc_dev_fop_read(struct file *file,
* between while condition checking and scheduling)
*/
add_wait_queue(&ir->buf->wait_poll, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
/*
* while we didn't provide 'length' bytes, device is opened in blocking
@@ -709,19 +700,19 @@ ssize_t lirc_dev_fop_read(struct file *file,
}
mutex_unlock(&ir->irctl_lock);
- schedule();
set_current_state(TASK_INTERRUPTIBLE);
+ schedule();
+ set_current_state(TASK_RUNNING);
if (mutex_lock_interruptible(&ir->irctl_lock)) {
ret = -ERESTARTSYS;
remove_wait_queue(&ir->buf->wait_poll, &wait);
- set_current_state(TASK_RUNNING);
goto out_unlocked;
}
if (!ir->attached) {
ret = -ENODEV;
- break;
+ goto out_locked;
}
} else {
lirc_buffer_read(ir->buf, buf);
@@ -735,7 +726,6 @@ ssize_t lirc_dev_fop_read(struct file *file,
}
remove_wait_queue(&ir->buf->wait_poll, &wait);
- set_current_state(TASK_RUNNING);
out_locked:
mutex_unlock(&ir->irctl_lock);