Commit 3728e6a2 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull media fixes from Mauro Carvalho Chehab:
 "Core fixes:
   - cec: Respond to unregistered initiators, when applicable
   - dvb_frontend: only use kref after initialized

  Driver-specific fixes:
   - qcom, camss: Make function vfe_set_selection static
   - qcom: VIDEO_QCOM_CAMSS should depend on HAS_DMA
   - s5p-cec: add NACK detection support
   - media: staging/imx: Fix uninitialized variable warning
   - dib3000mc: i2c transfers over usb cannot be done from stack
   - venus: init registered list on streamoff"

* tag 'media/v4.14-2' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media:
  media: dvb_frontend: only use kref after initialized
  media: platform: VIDEO_QCOM_CAMSS should depend on HAS_DMA
  media: cec: Respond to unregistered initiators, when applicable
  media: s5p-cec: add NACK detection support
  media: staging/imx: Fix uninitialized variable warning
  media: qcom: camss: Make function vfe_set_selection static
  media: venus: init registered list on streamoff
  media: dvb: i2c transfers over usb cannot be done from stack
parents 33d930e5 ead66600
...@@ -1797,12 +1797,19 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg, ...@@ -1797,12 +1797,19 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg,
*/ */
switch (msg->msg[1]) { switch (msg->msg[1]) {
case CEC_MSG_GET_CEC_VERSION: case CEC_MSG_GET_CEC_VERSION:
case CEC_MSG_GIVE_DEVICE_VENDOR_ID:
case CEC_MSG_ABORT: case CEC_MSG_ABORT:
case CEC_MSG_GIVE_DEVICE_POWER_STATUS: case CEC_MSG_GIVE_DEVICE_POWER_STATUS:
case CEC_MSG_GIVE_PHYSICAL_ADDR:
case CEC_MSG_GIVE_OSD_NAME: case CEC_MSG_GIVE_OSD_NAME:
/*
* These messages reply with a directed message, so ignore if
* the initiator is Unregistered.
*/
if (!adap->passthrough && from_unregistered)
return 0;
/* Fall through */
case CEC_MSG_GIVE_DEVICE_VENDOR_ID:
case CEC_MSG_GIVE_FEATURES: case CEC_MSG_GIVE_FEATURES:
case CEC_MSG_GIVE_PHYSICAL_ADDR:
/* /*
* Skip processing these messages if the passthrough mode * Skip processing these messages if the passthrough mode
* is on. * is on.
...@@ -1810,7 +1817,7 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg, ...@@ -1810,7 +1817,7 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg,
if (adap->passthrough) if (adap->passthrough)
goto skip_processing; goto skip_processing;
/* Ignore if addressing is wrong */ /* Ignore if addressing is wrong */
if (is_broadcast || from_unregistered) if (is_broadcast)
return 0; return 0;
break; break;
......
...@@ -141,22 +141,39 @@ struct dvb_frontend_private { ...@@ -141,22 +141,39 @@ struct dvb_frontend_private {
static void dvb_frontend_invoke_release(struct dvb_frontend *fe, static void dvb_frontend_invoke_release(struct dvb_frontend *fe,
void (*release)(struct dvb_frontend *fe)); void (*release)(struct dvb_frontend *fe));
static void dvb_frontend_free(struct kref *ref) static void __dvb_frontend_free(struct dvb_frontend *fe)
{ {
struct dvb_frontend *fe =
container_of(ref, struct dvb_frontend, refcount);
struct dvb_frontend_private *fepriv = fe->frontend_priv; struct dvb_frontend_private *fepriv = fe->frontend_priv;
if (!fepriv)
return;
dvb_free_device(fepriv->dvbdev); dvb_free_device(fepriv->dvbdev);
dvb_frontend_invoke_release(fe, fe->ops.release); dvb_frontend_invoke_release(fe, fe->ops.release);
kfree(fepriv); kfree(fepriv);
fe->frontend_priv = NULL;
}
static void dvb_frontend_free(struct kref *ref)
{
struct dvb_frontend *fe =
container_of(ref, struct dvb_frontend, refcount);
__dvb_frontend_free(fe);
} }
static void dvb_frontend_put(struct dvb_frontend *fe) static void dvb_frontend_put(struct dvb_frontend *fe)
{ {
kref_put(&fe->refcount, dvb_frontend_free); /*
* Check if the frontend was registered, as otherwise
* kref was not initialized yet.
*/
if (fe->frontend_priv)
kref_put(&fe->refcount, dvb_frontend_free);
else
__dvb_frontend_free(fe);
} }
static void dvb_frontend_get(struct dvb_frontend *fe) static void dvb_frontend_get(struct dvb_frontend *fe)
......
...@@ -55,29 +55,57 @@ struct dib3000mc_state { ...@@ -55,29 +55,57 @@ struct dib3000mc_state {
static u16 dib3000mc_read_word(struct dib3000mc_state *state, u16 reg) static u16 dib3000mc_read_word(struct dib3000mc_state *state, u16 reg)
{ {
u8 wb[2] = { (reg >> 8) | 0x80, reg & 0xff };
u8 rb[2];
struct i2c_msg msg[2] = { struct i2c_msg msg[2] = {
{ .addr = state->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2 }, { .addr = state->i2c_addr >> 1, .flags = 0, .len = 2 },
{ .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 }, { .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .len = 2 },
}; };
u16 word;
u8 *b;
b = kmalloc(4, GFP_KERNEL);
if (!b)
return 0;
b[0] = (reg >> 8) | 0x80;
b[1] = reg;
b[2] = 0;
b[3] = 0;
msg[0].buf = b;
msg[1].buf = b + 2;
if (i2c_transfer(state->i2c_adap, msg, 2) != 2) if (i2c_transfer(state->i2c_adap, msg, 2) != 2)
dprintk("i2c read error on %d\n",reg); dprintk("i2c read error on %d\n",reg);
return (rb[0] << 8) | rb[1]; word = (b[2] << 8) | b[3];
kfree(b);
return word;
} }
static int dib3000mc_write_word(struct dib3000mc_state *state, u16 reg, u16 val) static int dib3000mc_write_word(struct dib3000mc_state *state, u16 reg, u16 val)
{ {
u8 b[4] = {
(reg >> 8) & 0xff, reg & 0xff,
(val >> 8) & 0xff, val & 0xff,
};
struct i2c_msg msg = { struct i2c_msg msg = {
.addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4 .addr = state->i2c_addr >> 1, .flags = 0, .len = 4
}; };
return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; int rc;
u8 *b;
b = kmalloc(4, GFP_KERNEL);
if (!b)
return -ENOMEM;
b[0] = reg >> 8;
b[1] = reg;
b[2] = val >> 8;
b[3] = val;
msg.buf = b;
rc = i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
kfree(b);
return rc;
} }
static int dib3000mc_identify(struct dib3000mc_state *state) static int dib3000mc_identify(struct dib3000mc_state *state)
......
...@@ -753,13 +753,19 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, ...@@ -753,13 +753,19 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr,
struct i2c_adapter *i2c, struct i2c_adapter *i2c,
unsigned int pll_desc_id) unsigned int pll_desc_id)
{ {
u8 b1 [] = { 0 }; u8 *b1;
struct i2c_msg msg = { .addr = pll_addr, .flags = I2C_M_RD, struct i2c_msg msg = { .addr = pll_addr, .flags = I2C_M_RD, .len = 1 };
.buf = b1, .len = 1 };
struct dvb_pll_priv *priv = NULL; struct dvb_pll_priv *priv = NULL;
int ret; int ret;
const struct dvb_pll_desc *desc; const struct dvb_pll_desc *desc;
b1 = kmalloc(1, GFP_KERNEL);
if (!b1)
return NULL;
b1[0] = 0;
msg.buf = b1;
if ((id[dvb_pll_devcount] > DVB_PLL_UNDEFINED) && if ((id[dvb_pll_devcount] > DVB_PLL_UNDEFINED) &&
(id[dvb_pll_devcount] < ARRAY_SIZE(pll_list))) (id[dvb_pll_devcount] < ARRAY_SIZE(pll_list)))
pll_desc_id = id[dvb_pll_devcount]; pll_desc_id = id[dvb_pll_devcount];
...@@ -773,15 +779,19 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, ...@@ -773,15 +779,19 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr,
fe->ops.i2c_gate_ctrl(fe, 1); fe->ops.i2c_gate_ctrl(fe, 1);
ret = i2c_transfer (i2c, &msg, 1); ret = i2c_transfer (i2c, &msg, 1);
if (ret != 1) if (ret != 1) {
kfree(b1);
return NULL; return NULL;
}
if (fe->ops.i2c_gate_ctrl) if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0); fe->ops.i2c_gate_ctrl(fe, 0);
} }
priv = kzalloc(sizeof(struct dvb_pll_priv), GFP_KERNEL); priv = kzalloc(sizeof(struct dvb_pll_priv), GFP_KERNEL);
if (priv == NULL) if (!priv) {
kfree(b1);
return NULL; return NULL;
}
priv->pll_i2c_address = pll_addr; priv->pll_i2c_address = pll_addr;
priv->i2c = i2c; priv->i2c = i2c;
...@@ -811,6 +821,8 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, ...@@ -811,6 +821,8 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr,
"insmod option" : "autodetected"); "insmod option" : "autodetected");
} }
kfree(b1);
return fe; return fe;
} }
EXPORT_SYMBOL(dvb_pll_attach); EXPORT_SYMBOL(dvb_pll_attach);
......
...@@ -112,7 +112,7 @@ config VIDEO_PXA27x ...@@ -112,7 +112,7 @@ config VIDEO_PXA27x
config VIDEO_QCOM_CAMSS config VIDEO_QCOM_CAMSS
tristate "Qualcomm 8x16 V4L2 Camera Subsystem driver" tristate "Qualcomm 8x16 V4L2 Camera Subsystem driver"
depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && HAS_DMA
depends on (ARCH_QCOM && IOMMU_DMA) || COMPILE_TEST depends on (ARCH_QCOM && IOMMU_DMA) || COMPILE_TEST
select VIDEOBUF2_DMA_SG select VIDEOBUF2_DMA_SG
select V4L2_FWNODE select V4L2_FWNODE
......
...@@ -2660,7 +2660,7 @@ static int vfe_get_selection(struct v4l2_subdev *sd, ...@@ -2660,7 +2660,7 @@ static int vfe_get_selection(struct v4l2_subdev *sd,
* *
* Return -EINVAL or zero on success * Return -EINVAL or zero on success
*/ */
int vfe_set_selection(struct v4l2_subdev *sd, static int vfe_set_selection(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_selection *sel) struct v4l2_subdev_selection *sel)
{ {
......
...@@ -682,6 +682,7 @@ void venus_helper_vb2_stop_streaming(struct vb2_queue *q) ...@@ -682,6 +682,7 @@ void venus_helper_vb2_stop_streaming(struct vb2_queue *q)
hfi_session_abort(inst); hfi_session_abort(inst);
load_scale_clocks(core); load_scale_clocks(core);
INIT_LIST_HEAD(&inst->registeredbufs);
} }
venus_helper_buffers_done(inst, VB2_BUF_STATE_ERROR); venus_helper_buffers_done(inst, VB2_BUF_STATE_ERROR);
......
...@@ -172,7 +172,8 @@ u32 s5p_cec_get_status(struct s5p_cec_dev *cec) ...@@ -172,7 +172,8 @@ u32 s5p_cec_get_status(struct s5p_cec_dev *cec)
{ {
u32 status = 0; u32 status = 0;
status = readb(cec->reg + S5P_CEC_STATUS_0); status = readb(cec->reg + S5P_CEC_STATUS_0) & 0xf;
status |= (readb(cec->reg + S5P_CEC_TX_STAT1) & 0xf) << 4;
status |= readb(cec->reg + S5P_CEC_STATUS_1) << 8; status |= readb(cec->reg + S5P_CEC_STATUS_1) << 8;
status |= readb(cec->reg + S5P_CEC_STATUS_2) << 16; status |= readb(cec->reg + S5P_CEC_STATUS_2) << 16;
status |= readb(cec->reg + S5P_CEC_STATUS_3) << 24; status |= readb(cec->reg + S5P_CEC_STATUS_3) << 24;
......
...@@ -92,7 +92,10 @@ static irqreturn_t s5p_cec_irq_handler(int irq, void *priv) ...@@ -92,7 +92,10 @@ static irqreturn_t s5p_cec_irq_handler(int irq, void *priv)
dev_dbg(cec->dev, "irq received\n"); dev_dbg(cec->dev, "irq received\n");
if (status & CEC_STATUS_TX_DONE) { if (status & CEC_STATUS_TX_DONE) {
if (status & CEC_STATUS_TX_ERROR) { if (status & CEC_STATUS_TX_NACK) {
dev_dbg(cec->dev, "CEC_STATUS_TX_NACK set\n");
cec->tx = STATE_NACK;
} else if (status & CEC_STATUS_TX_ERROR) {
dev_dbg(cec->dev, "CEC_STATUS_TX_ERROR set\n"); dev_dbg(cec->dev, "CEC_STATUS_TX_ERROR set\n");
cec->tx = STATE_ERROR; cec->tx = STATE_ERROR;
} else { } else {
...@@ -135,6 +138,12 @@ static irqreturn_t s5p_cec_irq_handler_thread(int irq, void *priv) ...@@ -135,6 +138,12 @@ static irqreturn_t s5p_cec_irq_handler_thread(int irq, void *priv)
cec_transmit_done(cec->adap, CEC_TX_STATUS_OK, 0, 0, 0, 0); cec_transmit_done(cec->adap, CEC_TX_STATUS_OK, 0, 0, 0, 0);
cec->tx = STATE_IDLE; cec->tx = STATE_IDLE;
break; break;
case STATE_NACK:
cec_transmit_done(cec->adap,
CEC_TX_STATUS_MAX_RETRIES | CEC_TX_STATUS_NACK,
0, 1, 0, 0);
cec->tx = STATE_IDLE;
break;
case STATE_ERROR: case STATE_ERROR:
cec_transmit_done(cec->adap, cec_transmit_done(cec->adap,
CEC_TX_STATUS_MAX_RETRIES | CEC_TX_STATUS_ERROR, CEC_TX_STATUS_MAX_RETRIES | CEC_TX_STATUS_ERROR,
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#define CEC_STATUS_TX_TRANSFERRING (1 << 1) #define CEC_STATUS_TX_TRANSFERRING (1 << 1)
#define CEC_STATUS_TX_DONE (1 << 2) #define CEC_STATUS_TX_DONE (1 << 2)
#define CEC_STATUS_TX_ERROR (1 << 3) #define CEC_STATUS_TX_ERROR (1 << 3)
#define CEC_STATUS_TX_NACK (1 << 4)
#define CEC_STATUS_TX_BYTES (0xFF << 8) #define CEC_STATUS_TX_BYTES (0xFF << 8)
#define CEC_STATUS_RX_RUNNING (1 << 16) #define CEC_STATUS_RX_RUNNING (1 << 16)
#define CEC_STATUS_RX_RECEIVING (1 << 17) #define CEC_STATUS_RX_RECEIVING (1 << 17)
...@@ -55,6 +56,7 @@ enum cec_state { ...@@ -55,6 +56,7 @@ enum cec_state {
STATE_IDLE, STATE_IDLE,
STATE_BUSY, STATE_BUSY,
STATE_DONE, STATE_DONE,
STATE_NACK,
STATE_ERROR STATE_ERROR
}; };
......
...@@ -38,41 +38,74 @@ MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); ...@@ -38,41 +38,74 @@ MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
static int mt2060_readreg(struct mt2060_priv *priv, u8 reg, u8 *val) static int mt2060_readreg(struct mt2060_priv *priv, u8 reg, u8 *val)
{ {
struct i2c_msg msg[2] = { struct i2c_msg msg[2] = {
{ .addr = priv->cfg->i2c_address, .flags = 0, .buf = &reg, .len = 1 }, { .addr = priv->cfg->i2c_address, .flags = 0, .len = 1 },
{ .addr = priv->cfg->i2c_address, .flags = I2C_M_RD, .buf = val, .len = 1 }, { .addr = priv->cfg->i2c_address, .flags = I2C_M_RD, .len = 1 },
}; };
int rc = 0;
u8 *b;
b = kmalloc(2, GFP_KERNEL);
if (!b)
return -ENOMEM;
b[0] = reg;
b[1] = 0;
msg[0].buf = b;
msg[1].buf = b + 1;
if (i2c_transfer(priv->i2c, msg, 2) != 2) { if (i2c_transfer(priv->i2c, msg, 2) != 2) {
printk(KERN_WARNING "mt2060 I2C read failed\n"); printk(KERN_WARNING "mt2060 I2C read failed\n");
return -EREMOTEIO; rc = -EREMOTEIO;
} }
return 0; *val = b[1];
kfree(b);
return rc;
} }
// Writes a single register // Writes a single register
static int mt2060_writereg(struct mt2060_priv *priv, u8 reg, u8 val) static int mt2060_writereg(struct mt2060_priv *priv, u8 reg, u8 val)
{ {
u8 buf[2] = { reg, val };
struct i2c_msg msg = { struct i2c_msg msg = {
.addr = priv->cfg->i2c_address, .flags = 0, .buf = buf, .len = 2 .addr = priv->cfg->i2c_address, .flags = 0, .len = 2
}; };
u8 *buf;
int rc = 0;
buf = kmalloc(2, GFP_KERNEL);
if (!buf)
return -ENOMEM;
buf[0] = reg;
buf[1] = val;
msg.buf = buf;
if (i2c_transfer(priv->i2c, &msg, 1) != 1) { if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
printk(KERN_WARNING "mt2060 I2C write failed\n"); printk(KERN_WARNING "mt2060 I2C write failed\n");
return -EREMOTEIO; rc = -EREMOTEIO;
} }
return 0; kfree(buf);
return rc;
} }
// Writes a set of consecutive registers // Writes a set of consecutive registers
static int mt2060_writeregs(struct mt2060_priv *priv,u8 *buf, u8 len) static int mt2060_writeregs(struct mt2060_priv *priv,u8 *buf, u8 len)
{ {
int rem, val_len; int rem, val_len;
u8 xfer_buf[16]; u8 *xfer_buf;
int rc = 0;
struct i2c_msg msg = { struct i2c_msg msg = {
.addr = priv->cfg->i2c_address, .flags = 0, .buf = xfer_buf .addr = priv->cfg->i2c_address, .flags = 0
}; };
xfer_buf = kmalloc(16, GFP_KERNEL);
if (!xfer_buf)
return -ENOMEM;
msg.buf = xfer_buf;
for (rem = len - 1; rem > 0; rem -= priv->i2c_max_regs) { for (rem = len - 1; rem > 0; rem -= priv->i2c_max_regs) {
val_len = min_t(int, rem, priv->i2c_max_regs); val_len = min_t(int, rem, priv->i2c_max_regs);
msg.len = 1 + val_len; msg.len = 1 + val_len;
...@@ -81,11 +114,13 @@ static int mt2060_writeregs(struct mt2060_priv *priv,u8 *buf, u8 len) ...@@ -81,11 +114,13 @@ static int mt2060_writeregs(struct mt2060_priv *priv,u8 *buf, u8 len)
if (i2c_transfer(priv->i2c, &msg, 1) != 1) { if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
printk(KERN_WARNING "mt2060 I2C write failed (len=%i)\n", val_len); printk(KERN_WARNING "mt2060 I2C write failed (len=%i)\n", val_len);
return -EREMOTEIO; rc = -EREMOTEIO;
break;
} }
} }
return 0; kfree(xfer_buf);
return rc;
} }
// Initialisation sequences // Initialisation sequences
......
...@@ -400,10 +400,10 @@ static int imx_media_create_pad_vdev_lists(struct imx_media_dev *imxmd) ...@@ -400,10 +400,10 @@ static int imx_media_create_pad_vdev_lists(struct imx_media_dev *imxmd)
struct media_link, list); struct media_link, list);
ret = imx_media_add_vdev_to_pad(imxmd, vdev, link->source); ret = imx_media_add_vdev_to_pad(imxmd, vdev, link->source);
if (ret) if (ret)
break; return ret;
} }
return ret; return 0;
} }
/* async subdev complete notifier */ /* async subdev complete notifier */
......
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