Commit bb61ce54 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'media/v4.11-2' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media

Pull media fixes from Mauro Carvalho Chehab:
 "Media regression fixes:

   - serial_ir: fix a Kernel crash during boot on Kernel 4.11-rc1, due
     to an IRQ code called too early

   - other IR regression fixes at lirc and at the raw IR decoding

   - a deadlock fix at the RC nuvoton driver

   - fix another issue with DMA on stack at dw2102 driver

  There's an extra patch there that change a driver interface for the
  SoC VSP1 driver, with is shared between the DRM and V4L2 driver. The
  patch itself is trivial, and was acked by David Arlie"

* tag 'media/v4.11-2' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media:
  [media] v4l: vsp1: Adapt vsp1_du_setup_lif() interface to use a structure
  [media] dw2102: don't do DMA on stack
  [media] rc: protocol is not set on register for raw IR devices
  [media] rc: raw decoder for keymap protocol is not loaded on register
  [media] rc: nuvoton: fix deadlock in nvt_write_wakeup_codes
  [media] lirc: fix dead lock between open and wakeup_filter
  [media] serial_ir: ensure we're ready to receive interrupts
parents cb2113cb 8c71fff4
...@@ -32,6 +32,10 @@ void rcar_du_vsp_enable(struct rcar_du_crtc *crtc) ...@@ -32,6 +32,10 @@ void rcar_du_vsp_enable(struct rcar_du_crtc *crtc)
{ {
const struct drm_display_mode *mode = &crtc->crtc.state->adjusted_mode; const struct drm_display_mode *mode = &crtc->crtc.state->adjusted_mode;
struct rcar_du_device *rcdu = crtc->group->dev; struct rcar_du_device *rcdu = crtc->group->dev;
struct vsp1_du_lif_config cfg = {
.width = mode->hdisplay,
.height = mode->vdisplay,
};
struct rcar_du_plane_state state = { struct rcar_du_plane_state state = {
.state = { .state = {
.crtc = &crtc->crtc, .crtc = &crtc->crtc,
...@@ -66,12 +70,12 @@ void rcar_du_vsp_enable(struct rcar_du_crtc *crtc) ...@@ -66,12 +70,12 @@ void rcar_du_vsp_enable(struct rcar_du_crtc *crtc)
*/ */
crtc->group->need_restart = true; crtc->group->need_restart = true;
vsp1_du_setup_lif(crtc->vsp->vsp, mode->hdisplay, mode->vdisplay); vsp1_du_setup_lif(crtc->vsp->vsp, &cfg);
} }
void rcar_du_vsp_disable(struct rcar_du_crtc *crtc) void rcar_du_vsp_disable(struct rcar_du_crtc *crtc)
{ {
vsp1_du_setup_lif(crtc->vsp->vsp, 0, 0); vsp1_du_setup_lif(crtc->vsp->vsp, NULL);
} }
void rcar_du_vsp_atomic_begin(struct rcar_du_crtc *crtc) void rcar_du_vsp_atomic_begin(struct rcar_du_crtc *crtc)
......
...@@ -54,12 +54,11 @@ EXPORT_SYMBOL_GPL(vsp1_du_init); ...@@ -54,12 +54,11 @@ EXPORT_SYMBOL_GPL(vsp1_du_init);
/** /**
* vsp1_du_setup_lif - Setup the output part of the VSP pipeline * vsp1_du_setup_lif - Setup the output part of the VSP pipeline
* @dev: the VSP device * @dev: the VSP device
* @width: output frame width in pixels * @cfg: the LIF configuration
* @height: output frame height in pixels
* *
* Configure the output part of VSP DRM pipeline for the given frame @width and * Configure the output part of VSP DRM pipeline for the given frame @cfg.width
* @height. This sets up formats on the BRU source pad, the WPF0 sink and source * and @cfg.height. This sets up formats on the BRU source pad, the WPF0 sink
* pads, and the LIF sink pad. * and source pads, and the LIF sink pad.
* *
* As the media bus code on the BRU source pad is conditioned by the * As the media bus code on the BRU source pad is conditioned by the
* configuration of the BRU sink 0 pad, we also set up the formats on all BRU * configuration of the BRU sink 0 pad, we also set up the formats on all BRU
...@@ -69,8 +68,7 @@ EXPORT_SYMBOL_GPL(vsp1_du_init); ...@@ -69,8 +68,7 @@ EXPORT_SYMBOL_GPL(vsp1_du_init);
* *
* Return 0 on success or a negative error code on failure. * Return 0 on success or a negative error code on failure.
*/ */
int vsp1_du_setup_lif(struct device *dev, unsigned int width, int vsp1_du_setup_lif(struct device *dev, const struct vsp1_du_lif_config *cfg)
unsigned int height)
{ {
struct vsp1_device *vsp1 = dev_get_drvdata(dev); struct vsp1_device *vsp1 = dev_get_drvdata(dev);
struct vsp1_pipeline *pipe = &vsp1->drm->pipe; struct vsp1_pipeline *pipe = &vsp1->drm->pipe;
...@@ -79,11 +77,8 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int width, ...@@ -79,11 +77,8 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int width,
unsigned int i; unsigned int i;
int ret; int ret;
dev_dbg(vsp1->dev, "%s: configuring LIF with format %ux%u\n", if (!cfg) {
__func__, width, height); /* NULL configuration means the CRTC is being disabled, stop
if (width == 0 || height == 0) {
/* Zero width or height means the CRTC is being disabled, stop
* the pipeline and turn the light off. * the pipeline and turn the light off.
*/ */
ret = vsp1_pipeline_stop(pipe); ret = vsp1_pipeline_stop(pipe);
...@@ -108,6 +103,9 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int width, ...@@ -108,6 +103,9 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int width,
return 0; return 0;
} }
dev_dbg(vsp1->dev, "%s: configuring LIF with format %ux%u\n",
__func__, cfg->width, cfg->height);
/* Configure the format at the BRU sinks and propagate it through the /* Configure the format at the BRU sinks and propagate it through the
* pipeline. * pipeline.
*/ */
...@@ -117,8 +115,8 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int width, ...@@ -117,8 +115,8 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int width,
for (i = 0; i < bru->entity.source_pad; ++i) { for (i = 0; i < bru->entity.source_pad; ++i) {
format.pad = i; format.pad = i;
format.format.width = width; format.format.width = cfg->width;
format.format.height = height; format.format.height = cfg->height;
format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32; format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
format.format.field = V4L2_FIELD_NONE; format.format.field = V4L2_FIELD_NONE;
...@@ -133,8 +131,8 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int width, ...@@ -133,8 +131,8 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int width,
} }
format.pad = bru->entity.source_pad; format.pad = bru->entity.source_pad;
format.format.width = width; format.format.width = cfg->width;
format.format.height = height; format.format.height = cfg->height;
format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32; format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32;
format.format.field = V4L2_FIELD_NONE; format.format.field = V4L2_FIELD_NONE;
...@@ -180,7 +178,8 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int width, ...@@ -180,7 +178,8 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int width,
/* Verify that the format at the output of the pipeline matches the /* Verify that the format at the output of the pipeline matches the
* requested frame size and media bus code. * requested frame size and media bus code.
*/ */
if (format.format.width != width || format.format.height != height || if (format.format.width != cfg->width ||
format.format.height != cfg->height ||
format.format.code != MEDIA_BUS_FMT_ARGB8888_1X32) { format.format.code != MEDIA_BUS_FMT_ARGB8888_1X32) {
dev_dbg(vsp1->dev, "%s: format mismatch\n", __func__); dev_dbg(vsp1->dev, "%s: format mismatch\n", __func__);
return -EPIPE; return -EPIPE;
......
...@@ -436,6 +436,8 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file) ...@@ -436,6 +436,8 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file)
return -ERESTARTSYS; return -ERESTARTSYS;
ir = irctls[iminor(inode)]; ir = irctls[iminor(inode)];
mutex_unlock(&lirc_dev_lock);
if (!ir) { if (!ir) {
retval = -ENODEV; retval = -ENODEV;
goto error; goto error;
...@@ -476,8 +478,6 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file) ...@@ -476,8 +478,6 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file)
} }
error: error:
mutex_unlock(&lirc_dev_lock);
nonseekable_open(inode, file); nonseekable_open(inode, file);
return retval; return retval;
......
...@@ -176,12 +176,13 @@ static void nvt_write_wakeup_codes(struct rc_dev *dev, ...@@ -176,12 +176,13 @@ static void nvt_write_wakeup_codes(struct rc_dev *dev,
{ {
u8 tolerance, config; u8 tolerance, config;
struct nvt_dev *nvt = dev->priv; struct nvt_dev *nvt = dev->priv;
unsigned long flags;
int i; int i;
/* hardcode the tolerance to 10% */ /* hardcode the tolerance to 10% */
tolerance = DIV_ROUND_UP(count, 10); tolerance = DIV_ROUND_UP(count, 10);
spin_lock(&nvt->lock); spin_lock_irqsave(&nvt->lock, flags);
nvt_clear_cir_wake_fifo(nvt); nvt_clear_cir_wake_fifo(nvt);
nvt_cir_wake_reg_write(nvt, count, CIR_WAKE_FIFO_CMP_DEEP); nvt_cir_wake_reg_write(nvt, count, CIR_WAKE_FIFO_CMP_DEEP);
...@@ -203,7 +204,7 @@ static void nvt_write_wakeup_codes(struct rc_dev *dev, ...@@ -203,7 +204,7 @@ static void nvt_write_wakeup_codes(struct rc_dev *dev,
nvt_cir_wake_reg_write(nvt, config, CIR_WAKE_IRCON); nvt_cir_wake_reg_write(nvt, config, CIR_WAKE_IRCON);
spin_unlock(&nvt->lock); spin_unlock_irqrestore(&nvt->lock, flags);
} }
static ssize_t wakeup_data_show(struct device *dev, static ssize_t wakeup_data_show(struct device *dev,
......
...@@ -1663,6 +1663,7 @@ static int rc_setup_rx_device(struct rc_dev *dev) ...@@ -1663,6 +1663,7 @@ static int rc_setup_rx_device(struct rc_dev *dev)
{ {
int rc; int rc;
struct rc_map *rc_map; struct rc_map *rc_map;
u64 rc_type;
if (!dev->map_name) if (!dev->map_name)
return -EINVAL; return -EINVAL;
...@@ -1677,15 +1678,18 @@ static int rc_setup_rx_device(struct rc_dev *dev) ...@@ -1677,15 +1678,18 @@ static int rc_setup_rx_device(struct rc_dev *dev)
if (rc) if (rc)
return rc; return rc;
if (dev->change_protocol) { rc_type = BIT_ULL(rc_map->rc_type);
u64 rc_type = (1ll << rc_map->rc_type);
if (dev->change_protocol) {
rc = dev->change_protocol(dev, &rc_type); rc = dev->change_protocol(dev, &rc_type);
if (rc < 0) if (rc < 0)
goto out_table; goto out_table;
dev->enabled_protocols = rc_type; dev->enabled_protocols = rc_type;
} }
if (dev->driver_type == RC_DRIVER_IR_RAW)
ir_raw_load_modules(&rc_type);
set_bit(EV_KEY, dev->input_dev->evbit); set_bit(EV_KEY, dev->input_dev->evbit);
set_bit(EV_REP, dev->input_dev->evbit); set_bit(EV_REP, dev->input_dev->evbit);
set_bit(EV_MSC, dev->input_dev->evbit); set_bit(EV_MSC, dev->input_dev->evbit);
...@@ -1777,12 +1781,6 @@ int rc_register_device(struct rc_dev *dev) ...@@ -1777,12 +1781,6 @@ int rc_register_device(struct rc_dev *dev)
dev->input_name ?: "Unspecified device", path ?: "N/A"); dev->input_name ?: "Unspecified device", path ?: "N/A");
kfree(path); kfree(path);
if (dev->driver_type != RC_DRIVER_IR_RAW_TX) {
rc = rc_setup_rx_device(dev);
if (rc)
goto out_dev;
}
if (dev->driver_type == RC_DRIVER_IR_RAW || if (dev->driver_type == RC_DRIVER_IR_RAW ||
dev->driver_type == RC_DRIVER_IR_RAW_TX) { dev->driver_type == RC_DRIVER_IR_RAW_TX) {
if (!raw_init) { if (!raw_init) {
...@@ -1791,7 +1789,13 @@ int rc_register_device(struct rc_dev *dev) ...@@ -1791,7 +1789,13 @@ int rc_register_device(struct rc_dev *dev)
} }
rc = ir_raw_event_register(dev); rc = ir_raw_event_register(dev);
if (rc < 0) if (rc < 0)
goto out_rx; goto out_dev;
}
if (dev->driver_type != RC_DRIVER_IR_RAW_TX) {
rc = rc_setup_rx_device(dev);
if (rc)
goto out_raw;
} }
/* Allow the RC sysfs nodes to be accessible */ /* Allow the RC sysfs nodes to be accessible */
...@@ -1803,8 +1807,8 @@ int rc_register_device(struct rc_dev *dev) ...@@ -1803,8 +1807,8 @@ int rc_register_device(struct rc_dev *dev)
return 0; return 0;
out_rx: out_raw:
rc_free_rx_device(dev); ir_raw_event_unregister(dev);
out_dev: out_dev:
device_del(&dev->dev); device_del(&dev->dev);
out_unlock: out_unlock:
......
...@@ -487,10 +487,69 @@ static void serial_ir_timeout(unsigned long arg) ...@@ -487,10 +487,69 @@ static void serial_ir_timeout(unsigned long arg)
ir_raw_event_handle(serial_ir.rcdev); ir_raw_event_handle(serial_ir.rcdev);
} }
/* Needed by serial_ir_probe() */
static int serial_ir_tx(struct rc_dev *dev, unsigned int *txbuf,
unsigned int count);
static int serial_ir_tx_duty_cycle(struct rc_dev *dev, u32 cycle);
static int serial_ir_tx_carrier(struct rc_dev *dev, u32 carrier);
static int serial_ir_open(struct rc_dev *rcdev);
static void serial_ir_close(struct rc_dev *rcdev);
static int serial_ir_probe(struct platform_device *dev) static int serial_ir_probe(struct platform_device *dev)
{ {
struct rc_dev *rcdev;
int i, nlow, nhigh, result; int i, nlow, nhigh, result;
rcdev = devm_rc_allocate_device(&dev->dev, RC_DRIVER_IR_RAW);
if (!rcdev)
return -ENOMEM;
if (hardware[type].send_pulse && hardware[type].send_space)
rcdev->tx_ir = serial_ir_tx;
if (hardware[type].set_send_carrier)
rcdev->s_tx_carrier = serial_ir_tx_carrier;
if (hardware[type].set_duty_cycle)
rcdev->s_tx_duty_cycle = serial_ir_tx_duty_cycle;
switch (type) {
case IR_HOMEBREW:
rcdev->input_name = "Serial IR type home-brew";
break;
case IR_IRDEO:
rcdev->input_name = "Serial IR type IRdeo";
break;
case IR_IRDEO_REMOTE:
rcdev->input_name = "Serial IR type IRdeo remote";
break;
case IR_ANIMAX:
rcdev->input_name = "Serial IR type AnimaX";
break;
case IR_IGOR:
rcdev->input_name = "Serial IR type IgorPlug";
break;
}
rcdev->input_phys = KBUILD_MODNAME "/input0";
rcdev->input_id.bustype = BUS_HOST;
rcdev->input_id.vendor = 0x0001;
rcdev->input_id.product = 0x0001;
rcdev->input_id.version = 0x0100;
rcdev->open = serial_ir_open;
rcdev->close = serial_ir_close;
rcdev->dev.parent = &serial_ir.pdev->dev;
rcdev->allowed_protocols = RC_BIT_ALL_IR_DECODER;
rcdev->driver_name = KBUILD_MODNAME;
rcdev->map_name = RC_MAP_RC6_MCE;
rcdev->min_timeout = 1;
rcdev->timeout = IR_DEFAULT_TIMEOUT;
rcdev->max_timeout = 10 * IR_DEFAULT_TIMEOUT;
rcdev->rx_resolution = 250000;
serial_ir.rcdev = rcdev;
setup_timer(&serial_ir.timeout_timer, serial_ir_timeout,
(unsigned long)&serial_ir);
result = devm_request_irq(&dev->dev, irq, serial_ir_irq_handler, result = devm_request_irq(&dev->dev, irq, serial_ir_irq_handler,
share_irq ? IRQF_SHARED : 0, share_irq ? IRQF_SHARED : 0,
KBUILD_MODNAME, &hardware); KBUILD_MODNAME, &hardware);
...@@ -516,9 +575,6 @@ static int serial_ir_probe(struct platform_device *dev) ...@@ -516,9 +575,6 @@ static int serial_ir_probe(struct platform_device *dev)
return -EBUSY; return -EBUSY;
} }
setup_timer(&serial_ir.timeout_timer, serial_ir_timeout,
(unsigned long)&serial_ir);
result = hardware_init_port(); result = hardware_init_port();
if (result < 0) if (result < 0)
return result; return result;
...@@ -552,7 +608,8 @@ static int serial_ir_probe(struct platform_device *dev) ...@@ -552,7 +608,8 @@ static int serial_ir_probe(struct platform_device *dev)
sense ? "low" : "high"); sense ? "low" : "high");
dev_dbg(&dev->dev, "Interrupt %d, port %04x obtained\n", irq, io); dev_dbg(&dev->dev, "Interrupt %d, port %04x obtained\n", irq, io);
return 0;
return devm_rc_register_device(&dev->dev, rcdev);
} }
static int serial_ir_open(struct rc_dev *rcdev) static int serial_ir_open(struct rc_dev *rcdev)
...@@ -723,7 +780,6 @@ static void serial_ir_exit(void) ...@@ -723,7 +780,6 @@ static void serial_ir_exit(void)
static int __init serial_ir_init_module(void) static int __init serial_ir_init_module(void)
{ {
struct rc_dev *rcdev;
int result; int result;
switch (type) { switch (type) {
...@@ -754,63 +810,9 @@ static int __init serial_ir_init_module(void) ...@@ -754,63 +810,9 @@ static int __init serial_ir_init_module(void)
sense = !!sense; sense = !!sense;
result = serial_ir_init(); result = serial_ir_init();
if (result)
return result;
rcdev = devm_rc_allocate_device(&serial_ir.pdev->dev, RC_DRIVER_IR_RAW);
if (!rcdev) {
result = -ENOMEM;
goto serial_cleanup;
}
if (hardware[type].send_pulse && hardware[type].send_space)
rcdev->tx_ir = serial_ir_tx;
if (hardware[type].set_send_carrier)
rcdev->s_tx_carrier = serial_ir_tx_carrier;
if (hardware[type].set_duty_cycle)
rcdev->s_tx_duty_cycle = serial_ir_tx_duty_cycle;
switch (type) {
case IR_HOMEBREW:
rcdev->input_name = "Serial IR type home-brew";
break;
case IR_IRDEO:
rcdev->input_name = "Serial IR type IRdeo";
break;
case IR_IRDEO_REMOTE:
rcdev->input_name = "Serial IR type IRdeo remote";
break;
case IR_ANIMAX:
rcdev->input_name = "Serial IR type AnimaX";
break;
case IR_IGOR:
rcdev->input_name = "Serial IR type IgorPlug";
break;
}
rcdev->input_phys = KBUILD_MODNAME "/input0";
rcdev->input_id.bustype = BUS_HOST;
rcdev->input_id.vendor = 0x0001;
rcdev->input_id.product = 0x0001;
rcdev->input_id.version = 0x0100;
rcdev->open = serial_ir_open;
rcdev->close = serial_ir_close;
rcdev->dev.parent = &serial_ir.pdev->dev;
rcdev->allowed_protocols = RC_BIT_ALL_IR_DECODER;
rcdev->driver_name = KBUILD_MODNAME;
rcdev->map_name = RC_MAP_RC6_MCE;
rcdev->min_timeout = 1;
rcdev->timeout = IR_DEFAULT_TIMEOUT;
rcdev->max_timeout = 10 * IR_DEFAULT_TIMEOUT;
rcdev->rx_resolution = 250000;
serial_ir.rcdev = rcdev;
result = rc_register_device(rcdev);
if (!result) if (!result)
return 0; return 0;
serial_cleanup:
serial_ir_exit(); serial_ir_exit();
return result; return result;
} }
...@@ -818,7 +820,6 @@ static int __init serial_ir_init_module(void) ...@@ -818,7 +820,6 @@ static int __init serial_ir_init_module(void)
static void __exit serial_ir_exit_module(void) static void __exit serial_ir_exit_module(void)
{ {
del_timer_sync(&serial_ir.timeout_timer); del_timer_sync(&serial_ir.timeout_timer);
rc_unregister_device(serial_ir.rcdev);
serial_ir_exit(); serial_ir_exit();
} }
......
This diff is collapsed.
...@@ -20,8 +20,17 @@ struct device; ...@@ -20,8 +20,17 @@ struct device;
int vsp1_du_init(struct device *dev); int vsp1_du_init(struct device *dev);
int vsp1_du_setup_lif(struct device *dev, unsigned int width, /**
unsigned int height); * struct vsp1_du_lif_config - VSP LIF configuration
* @width: output frame width
* @height: output frame height
*/
struct vsp1_du_lif_config {
unsigned int width;
unsigned int height;
};
int vsp1_du_setup_lif(struct device *dev, const struct vsp1_du_lif_config *cfg);
struct vsp1_du_atomic_config { struct vsp1_du_atomic_config {
u32 pixelformat; u32 pixelformat;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment