summaryrefslogtreecommitdiff
path: root/drivers/media/rc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/rc')
-rw-r--r--drivers/media/rc/gpio-ir-recv.c4
-rw-r--r--drivers/media/rc/imon.c99
-rw-r--r--drivers/media/rc/ir-spi.c40
-rw-r--r--drivers/media/rc/lirc_dev.c9
-rw-r--r--drivers/media/rc/pwm-ir-tx.c5
-rw-r--r--drivers/media/rc/redrat3.c2
6 files changed, 94 insertions, 65 deletions
diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c
index bf6d8fa983bf..a6418ef782bc 100644
--- a/drivers/media/rc/gpio-ir-recv.c
+++ b/drivers/media/rc/gpio-ir-recv.c
@@ -48,10 +48,8 @@ static irqreturn_t gpio_ir_recv_irq(int irq, void *dev_id)
if (val >= 0)
ir_raw_event_store_edge(gpio_dev->rcdev, val == 1);
- if (pmdev) {
- pm_runtime_mark_last_busy(pmdev);
+ if (pmdev)
pm_runtime_put_autosuspend(pmdev);
- }
return IRQ_HANDLED;
}
diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c
index f5221b018808..35b9e07003d8 100644
--- a/drivers/media/rc/imon.c
+++ b/drivers/media/rc/imon.c
@@ -39,11 +39,6 @@
#define DISPLAY_MINOR_BASE 144
#define DEVICE_NAME "lcd%d"
-#define BUF_CHUNK_SIZE 8
-#define BUF_SIZE 128
-
-#define BIT_DURATION 250 /* each bit received is 250us */
-
#define IMON_CLOCK_ENABLE_PACKETS 2
/*** P R O T O T Y P E S ***/
@@ -536,7 +531,9 @@ static int display_open(struct inode *inode, struct file *file)
mutex_lock(&ictx->lock);
- if (!ictx->display_supported) {
+ if (ictx->disconnected) {
+ retval = -ENODEV;
+ } else if (!ictx->display_supported) {
pr_err("display not supported by device\n");
retval = -ENODEV;
} else if (ictx->display_isopen) {
@@ -598,6 +595,11 @@ static int send_packet(struct imon_context *ictx)
int retval = 0;
struct usb_ctrlrequest *control_req = NULL;
+ lockdep_assert_held(&ictx->lock);
+
+ if (ictx->disconnected)
+ return -ENODEV;
+
/* Check if we need to use control or interrupt urb */
if (!ictx->tx_control) {
pipe = usb_sndintpipe(ictx->usbdev_intf0,
@@ -645,12 +647,15 @@ static int send_packet(struct imon_context *ictx)
smp_rmb(); /* ensure later readers know we're not busy */
pr_err_ratelimited("error submitting urb(%d)\n", retval);
} else {
- /* Wait for transmission to complete (or abort) */
- retval = wait_for_completion_interruptible(
- &ictx->tx.finished);
- if (retval) {
+ /* Wait for transmission to complete (or abort or timeout) */
+ retval = wait_for_completion_interruptible_timeout(&ictx->tx.finished, 10 * HZ);
+ if (retval <= 0) {
usb_kill_urb(ictx->tx_urb);
pr_err_ratelimited("task interrupted\n");
+ if (retval < 0)
+ ictx->tx.status = retval;
+ else
+ ictx->tx.status = -ETIMEDOUT;
}
ictx->tx.busy = false;
@@ -949,12 +954,14 @@ static ssize_t vfd_write(struct file *file, const char __user *buf,
static const unsigned char vfd_packet6[] = {
0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF };
- if (ictx->disconnected)
- return -ENODEV;
-
if (mutex_lock_interruptible(&ictx->lock))
return -ERESTARTSYS;
+ if (ictx->disconnected) {
+ retval = -ENODEV;
+ goto exit;
+ }
+
if (!ictx->dev_present_intf0) {
pr_err_ratelimited("no iMON device present\n");
retval = -ENODEV;
@@ -1029,11 +1036,13 @@ static ssize_t lcd_write(struct file *file, const char __user *buf,
int retval = 0;
struct imon_context *ictx = file->private_data;
- if (ictx->disconnected)
- return -ENODEV;
-
mutex_lock(&ictx->lock);
+ if (ictx->disconnected) {
+ retval = -ENODEV;
+ goto exit;
+ }
+
if (!ictx->display_supported) {
pr_err_ratelimited("no iMON display present\n");
retval = -ENODEV;
@@ -1121,7 +1130,7 @@ static int imon_ir_change_protocol(struct rc_dev *rc, u64 *rc_proto)
int retval;
struct imon_context *ictx = rc->priv;
struct device *dev = ictx->dev;
- bool unlock = false;
+ const bool unlock = mutex_trylock(&ictx->lock);
unsigned char ir_proto_packet[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86 };
@@ -1148,8 +1157,6 @@ static int imon_ir_change_protocol(struct rc_dev *rc, u64 *rc_proto)
memcpy(ictx->usb_tx_buf, &ir_proto_packet, sizeof(ir_proto_packet));
- unlock = mutex_trylock(&ictx->lock);
-
retval = send_packet(ictx);
if (retval)
goto out;
@@ -1745,14 +1752,6 @@ static void usb_rx_callback_intf0(struct urb *urb)
if (!ictx)
return;
- /*
- * if we get a callback before we're done configuring the hardware, we
- * can't yet process the data, as there's nowhere to send it, but we
- * still need to submit a new rx URB to avoid wedging the hardware
- */
- if (!ictx->dev_present_intf0)
- goto out;
-
switch (urb->status) {
case -ENOENT: /* usbcore unlink successful! */
return;
@@ -1761,16 +1760,29 @@ static void usb_rx_callback_intf0(struct urb *urb)
break;
case 0:
- imon_incoming_packet(ictx, urb, intfnum);
+ /*
+ * if we get a callback before we're done configuring the hardware, we
+ * can't yet process the data, as there's nowhere to send it, but we
+ * still need to submit a new rx URB to avoid wedging the hardware
+ */
+ if (ictx->dev_present_intf0)
+ imon_incoming_packet(ictx, urb, intfnum);
break;
+ case -ECONNRESET:
+ case -EILSEQ:
+ case -EPROTO:
+ case -EPIPE:
+ dev_warn(ictx->dev, "imon %s: status(%d)\n",
+ __func__, urb->status);
+ return;
+
default:
dev_warn(ictx->dev, "imon %s: status(%d): ignored\n",
__func__, urb->status);
break;
}
-out:
usb_submit_urb(ictx->rx_urb_intf0, GFP_ATOMIC);
}
@@ -1786,14 +1798,6 @@ static void usb_rx_callback_intf1(struct urb *urb)
if (!ictx)
return;
- /*
- * if we get a callback before we're done configuring the hardware, we
- * can't yet process the data, as there's nowhere to send it, but we
- * still need to submit a new rx URB to avoid wedging the hardware
- */
- if (!ictx->dev_present_intf1)
- goto out;
-
switch (urb->status) {
case -ENOENT: /* usbcore unlink successful! */
return;
@@ -1802,16 +1806,29 @@ static void usb_rx_callback_intf1(struct urb *urb)
break;
case 0:
- imon_incoming_packet(ictx, urb, intfnum);
+ /*
+ * if we get a callback before we're done configuring the hardware, we
+ * can't yet process the data, as there's nowhere to send it, but we
+ * still need to submit a new rx URB to avoid wedging the hardware
+ */
+ if (ictx->dev_present_intf1)
+ imon_incoming_packet(ictx, urb, intfnum);
break;
+ case -ECONNRESET:
+ case -EILSEQ:
+ case -EPROTO:
+ case -EPIPE:
+ dev_warn(ictx->dev, "imon %s: status(%d)\n",
+ __func__, urb->status);
+ return;
+
default:
dev_warn(ictx->dev, "imon %s: status(%d): ignored\n",
__func__, urb->status);
break;
}
-out:
usb_submit_urb(ictx->rx_urb_intf1, GFP_ATOMIC);
}
@@ -2499,7 +2516,11 @@ static void imon_disconnect(struct usb_interface *interface)
int ifnum;
ictx = usb_get_intfdata(interface);
+
+ mutex_lock(&ictx->lock);
ictx->disconnected = true;
+ mutex_unlock(&ictx->lock);
+
dev = ictx->dev;
ifnum = interface->cur_altsetting->desc.bInterfaceNumber;
diff --git a/drivers/media/rc/ir-spi.c b/drivers/media/rc/ir-spi.c
index 8fc8e496e6aa..392441e0c116 100644
--- a/drivers/media/rc/ir-spi.c
+++ b/drivers/media/rc/ir-spi.c
@@ -21,13 +21,12 @@
#define IR_SPI_DRIVER_NAME "ir-spi"
#define IR_SPI_DEFAULT_FREQUENCY 38000
-#define IR_SPI_MAX_BUFSIZE 4096
+#define IR_SPI_BITS_PER_PULSE 16
struct ir_spi_data {
u32 freq;
bool negated;
- u16 tx_buf[IR_SPI_MAX_BUFSIZE];
u16 pulse;
u16 space;
@@ -43,17 +42,23 @@ static int ir_spi_tx(struct rc_dev *dev, unsigned int *buffer, unsigned int coun
unsigned int len = 0;
struct ir_spi_data *idata = dev->priv;
struct spi_transfer xfer;
+ u16 *tx_buf;
/* convert the pulse/space signal to raw binary signal */
for (i = 0; i < count; i++) {
- unsigned int periods;
- int j;
- u16 val;
+ buffer[i] = DIV_ROUND_CLOSEST_ULL((u64)buffer[i] * idata->freq,
+ 1000000);
+ len += buffer[i];
+ }
- periods = DIV_ROUND_CLOSEST(buffer[i] * idata->freq, 1000000);
+ tx_buf = kmalloc_array(len, sizeof(*tx_buf), GFP_KERNEL);
+ if (!tx_buf)
+ return -ENOMEM;
- if (len + periods >= IR_SPI_MAX_BUFSIZE)
- return -EINVAL;
+ len = 0;
+ for (i = 0; i < count; i++) {
+ int j;
+ u16 val;
/*
* The first value in buffer is a pulse, so that 0, 2, 4, ...
@@ -61,19 +66,19 @@ static int ir_spi_tx(struct rc_dev *dev, unsigned int *buffer, unsigned int coun
* contain a space duration.
*/
val = (i % 2) ? idata->space : idata->pulse;
- for (j = 0; j < periods; j++)
- idata->tx_buf[len++] = val;
+ for (j = 0; j < buffer[i]; j++)
+ tx_buf[len++] = val;
}
memset(&xfer, 0, sizeof(xfer));
- xfer.speed_hz = idata->freq * 16;
- xfer.len = len * sizeof(*idata->tx_buf);
- xfer.tx_buf = idata->tx_buf;
+ xfer.speed_hz = idata->freq * IR_SPI_BITS_PER_PULSE;
+ xfer.len = len * sizeof(*tx_buf);
+ xfer.tx_buf = tx_buf;
ret = regulator_enable(idata->regulator);
if (ret)
- return ret;
+ goto err_free_tx_buf;
ret = spi_sync_transfer(idata->spi, &xfer, 1);
if (ret)
@@ -81,6 +86,10 @@ static int ir_spi_tx(struct rc_dev *dev, unsigned int *buffer, unsigned int coun
regulator_disable(idata->regulator);
+err_free_tx_buf:
+
+ kfree(tx_buf);
+
return ret ? ret : count;
}
@@ -91,6 +100,9 @@ static int ir_spi_set_tx_carrier(struct rc_dev *dev, u32 carrier)
if (!carrier)
return -EINVAL;
+ if (carrier > idata->spi->max_speed_hz / IR_SPI_BITS_PER_PULSE)
+ return -EINVAL;
+
idata->freq = carrier;
return 0;
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index a2257dc2f25d..7d4942925993 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -736,11 +736,11 @@ int lirc_register(struct rc_dev *dev)
cdev_init(&dev->lirc_cdev, &lirc_fops);
+ get_device(&dev->dev);
+
err = cdev_device_add(&dev->lirc_cdev, &dev->lirc_dev);
if (err)
- goto out_ida;
-
- get_device(&dev->dev);
+ goto out_put_device;
switch (dev->driver_type) {
case RC_DRIVER_SCANCODE:
@@ -764,7 +764,8 @@ int lirc_register(struct rc_dev *dev)
return 0;
-out_ida:
+out_put_device:
+ put_device(&dev->lirc_dev);
ida_free(&lirc_ida, minor);
return err;
}
diff --git a/drivers/media/rc/pwm-ir-tx.c b/drivers/media/rc/pwm-ir-tx.c
index 84533fdd61aa..047472dc9244 100644
--- a/drivers/media/rc/pwm-ir-tx.c
+++ b/drivers/media/rc/pwm-ir-tx.c
@@ -117,7 +117,6 @@ static int pwm_ir_tx_atomic(struct rc_dev *dev, unsigned int *txbuf,
static enum hrtimer_restart pwm_ir_timer(struct hrtimer *timer)
{
struct pwm_ir *pwm_ir = container_of(timer, struct pwm_ir, timer);
- ktime_t now;
/*
* If we happen to hit an odd latency spike, loop through the
@@ -139,9 +138,7 @@ static enum hrtimer_restart pwm_ir_timer(struct hrtimer *timer)
hrtimer_add_expires_ns(timer, ns);
pwm_ir->txbuf_index++;
-
- now = timer->base->get_time();
- } while (hrtimer_get_expires_tv64(timer) < now);
+ } while (hrtimer_expires_remaining(timer) > 0);
return HRTIMER_RESTART;
}
diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c
index d89a4cfe3c89..a49173f54a4d 100644
--- a/drivers/media/rc/redrat3.c
+++ b/drivers/media/rc/redrat3.c
@@ -422,7 +422,7 @@ static int redrat3_send_cmd(int cmd, struct redrat3_dev *rr3)
static int redrat3_enable_detector(struct redrat3_dev *rr3)
{
struct device *dev = rr3->dev;
- u8 ret;
+ int ret;
ret = redrat3_send_cmd(RR3_RC_DET_ENABLE, rr3);
if (ret != 0)