media: cec: use call_op and check for !unregistered
[ Upstream commit e2ed5024ac2bc27d4bfc99fd58f5ab54de8fa965 ] Use call_(void_)op consistently in the CEC core framework. Ditto for the cec pin ops. And check if !adap->devnode.unregistered before calling each op. This avoids calls to ops when the device has been unregistered and the underlying hardware may be gone. Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org> Stable-dep-of: 47c82aac10a6 ("media: cec: core: avoid recursive cec_claim_log_addrs") Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:

committed by
Greg Kroah-Hartman

parent
8fa7e4896f
commit
73ef9ae980
@@ -39,15 +39,6 @@ static void cec_fill_msg_report_features(struct cec_adapter *adap,
|
|||||||
*/
|
*/
|
||||||
#define CEC_XFER_TIMEOUT_MS (5 * 400 + 100)
|
#define CEC_XFER_TIMEOUT_MS (5 * 400 + 100)
|
||||||
|
|
||||||
#define call_op(adap, op, arg...) \
|
|
||||||
(adap->ops->op ? adap->ops->op(adap, ## arg) : 0)
|
|
||||||
|
|
||||||
#define call_void_op(adap, op, arg...) \
|
|
||||||
do { \
|
|
||||||
if (adap->ops->op) \
|
|
||||||
adap->ops->op(adap, ## arg); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
static int cec_log_addr2idx(const struct cec_adapter *adap, u8 log_addr)
|
static int cec_log_addr2idx(const struct cec_adapter *adap, u8 log_addr)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -405,9 +396,9 @@ static void cec_data_cancel(struct cec_data *data, u8 tx_status, u8 rx_status)
|
|||||||
/* Queue transmitted message for monitoring purposes */
|
/* Queue transmitted message for monitoring purposes */
|
||||||
cec_queue_msg_monitor(adap, &data->msg, 1);
|
cec_queue_msg_monitor(adap, &data->msg, 1);
|
||||||
|
|
||||||
if (!data->blocking && data->msg.sequence && adap->ops->received)
|
if (!data->blocking && data->msg.sequence)
|
||||||
/* Allow drivers to process the message first */
|
/* Allow drivers to process the message first */
|
||||||
adap->ops->received(adap, &data->msg);
|
call_op(adap, received, &data->msg);
|
||||||
|
|
||||||
cec_data_completed(data);
|
cec_data_completed(data);
|
||||||
}
|
}
|
||||||
@@ -584,8 +575,8 @@ int cec_thread_func(void *_adap)
|
|||||||
|
|
||||||
adap->transmit_in_progress_aborted = false;
|
adap->transmit_in_progress_aborted = false;
|
||||||
/* Tell the adapter to transmit, cancel on error */
|
/* Tell the adapter to transmit, cancel on error */
|
||||||
if (adap->ops->adap_transmit(adap, data->attempts,
|
if (call_op(adap, adap_transmit, data->attempts,
|
||||||
signal_free_time, &data->msg))
|
signal_free_time, &data->msg))
|
||||||
cec_data_cancel(data, CEC_TX_STATUS_ABORTED, 0);
|
cec_data_cancel(data, CEC_TX_STATUS_ABORTED, 0);
|
||||||
else
|
else
|
||||||
adap->transmit_in_progress = true;
|
adap->transmit_in_progress = true;
|
||||||
@@ -1311,7 +1302,7 @@ static int cec_config_log_addr(struct cec_adapter *adap,
|
|||||||
* Message not acknowledged, so this logical
|
* Message not acknowledged, so this logical
|
||||||
* address is free to use.
|
* address is free to use.
|
||||||
*/
|
*/
|
||||||
err = adap->ops->adap_log_addr(adap, log_addr);
|
err = call_op(adap, adap_log_addr, log_addr);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
@@ -1328,9 +1319,8 @@ static int cec_config_log_addr(struct cec_adapter *adap,
|
|||||||
*/
|
*/
|
||||||
static void cec_adap_unconfigure(struct cec_adapter *adap)
|
static void cec_adap_unconfigure(struct cec_adapter *adap)
|
||||||
{
|
{
|
||||||
if (!adap->needs_hpd ||
|
if (!adap->needs_hpd || adap->phys_addr != CEC_PHYS_ADDR_INVALID)
|
||||||
adap->phys_addr != CEC_PHYS_ADDR_INVALID)
|
WARN_ON(call_op(adap, adap_log_addr, CEC_LOG_ADDR_INVALID));
|
||||||
WARN_ON(adap->ops->adap_log_addr(adap, CEC_LOG_ADDR_INVALID));
|
|
||||||
adap->log_addrs.log_addr_mask = 0;
|
adap->log_addrs.log_addr_mask = 0;
|
||||||
adap->is_configured = false;
|
adap->is_configured = false;
|
||||||
cec_flush(adap);
|
cec_flush(adap);
|
||||||
@@ -1573,7 +1563,7 @@ static int cec_activate_cnt_inc(struct cec_adapter *adap)
|
|||||||
mutex_lock(&adap->devnode.lock);
|
mutex_lock(&adap->devnode.lock);
|
||||||
adap->last_initiator = 0xff;
|
adap->last_initiator = 0xff;
|
||||||
adap->transmit_in_progress = false;
|
adap->transmit_in_progress = false;
|
||||||
ret = adap->ops->adap_enable(adap, true);
|
ret = call_op(adap, adap_enable, true);
|
||||||
if (ret)
|
if (ret)
|
||||||
adap->activate_cnt--;
|
adap->activate_cnt--;
|
||||||
mutex_unlock(&adap->devnode.lock);
|
mutex_unlock(&adap->devnode.lock);
|
||||||
@@ -1590,7 +1580,7 @@ static void cec_activate_cnt_dec(struct cec_adapter *adap)
|
|||||||
|
|
||||||
/* serialize adap_enable */
|
/* serialize adap_enable */
|
||||||
mutex_lock(&adap->devnode.lock);
|
mutex_lock(&adap->devnode.lock);
|
||||||
WARN_ON(adap->ops->adap_enable(adap, false));
|
WARN_ON(call_op(adap, adap_enable, false));
|
||||||
adap->last_initiator = 0xff;
|
adap->last_initiator = 0xff;
|
||||||
adap->transmit_in_progress = false;
|
adap->transmit_in_progress = false;
|
||||||
adap->transmit_in_progress_aborted = false;
|
adap->transmit_in_progress_aborted = false;
|
||||||
@@ -1964,11 +1954,10 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg,
|
|||||||
msg->msg[1] != CEC_MSG_CDC_MESSAGE)
|
msg->msg[1] != CEC_MSG_CDC_MESSAGE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (adap->ops->received) {
|
/* Allow drivers to process the message first */
|
||||||
/* Allow drivers to process the message first */
|
if (adap->ops->received && !adap->devnode.unregistered &&
|
||||||
if (adap->ops->received(adap, msg) != -ENOMSG)
|
adap->ops->received(adap, msg) != -ENOMSG)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* REPORT_PHYSICAL_ADDR, CEC_MSG_USER_CONTROL_PRESSED and
|
* REPORT_PHYSICAL_ADDR, CEC_MSG_USER_CONTROL_PRESSED and
|
||||||
|
@@ -595,7 +595,8 @@ static int cec_open(struct inode *inode, struct file *filp)
|
|||||||
adap->conn_info.type != CEC_CONNECTOR_TYPE_NO_CONNECTOR;
|
adap->conn_info.type != CEC_CONNECTOR_TYPE_NO_CONNECTOR;
|
||||||
cec_queue_event_fh(fh, &ev, 0);
|
cec_queue_event_fh(fh, &ev, 0);
|
||||||
#ifdef CONFIG_CEC_PIN
|
#ifdef CONFIG_CEC_PIN
|
||||||
if (adap->pin && adap->pin->ops->read_hpd) {
|
if (adap->pin && adap->pin->ops->read_hpd &&
|
||||||
|
!adap->devnode.unregistered) {
|
||||||
err = adap->pin->ops->read_hpd(adap);
|
err = adap->pin->ops->read_hpd(adap);
|
||||||
if (err >= 0) {
|
if (err >= 0) {
|
||||||
ev.event = err ? CEC_EVENT_PIN_HPD_HIGH :
|
ev.event = err ? CEC_EVENT_PIN_HPD_HIGH :
|
||||||
@@ -603,7 +604,8 @@ static int cec_open(struct inode *inode, struct file *filp)
|
|||||||
cec_queue_event_fh(fh, &ev, 0);
|
cec_queue_event_fh(fh, &ev, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (adap->pin && adap->pin->ops->read_5v) {
|
if (adap->pin && adap->pin->ops->read_5v &&
|
||||||
|
!adap->devnode.unregistered) {
|
||||||
err = adap->pin->ops->read_5v(adap);
|
err = adap->pin->ops->read_5v(adap);
|
||||||
if (err >= 0) {
|
if (err >= 0) {
|
||||||
ev.event = err ? CEC_EVENT_PIN_5V_HIGH :
|
ev.event = err ? CEC_EVENT_PIN_5V_HIGH :
|
||||||
|
@@ -204,7 +204,7 @@ static ssize_t cec_error_inj_write(struct file *file,
|
|||||||
line = strsep(&p, "\n");
|
line = strsep(&p, "\n");
|
||||||
if (!*line || *line == '#')
|
if (!*line || *line == '#')
|
||||||
continue;
|
continue;
|
||||||
if (!adap->ops->error_inj_parse_line(adap, line)) {
|
if (!call_op(adap, error_inj_parse_line, line)) {
|
||||||
kfree(buf);
|
kfree(buf);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@@ -217,7 +217,7 @@ static int cec_error_inj_show(struct seq_file *sf, void *unused)
|
|||||||
{
|
{
|
||||||
struct cec_adapter *adap = sf->private;
|
struct cec_adapter *adap = sf->private;
|
||||||
|
|
||||||
return adap->ops->error_inj_show(adap, sf);
|
return call_op(adap, error_inj_show, sf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cec_error_inj_open(struct inode *inode, struct file *file)
|
static int cec_error_inj_open(struct inode *inode, struct file *file)
|
||||||
|
@@ -12,6 +12,17 @@
|
|||||||
#include <linux/atomic.h>
|
#include <linux/atomic.h>
|
||||||
#include <media/cec-pin.h>
|
#include <media/cec-pin.h>
|
||||||
|
|
||||||
|
#define call_pin_op(pin, op, arg...) \
|
||||||
|
((pin && pin->ops->op && !pin->adap->devnode.unregistered) ? \
|
||||||
|
pin->ops->op(pin->adap, ## arg) : 0)
|
||||||
|
|
||||||
|
#define call_void_pin_op(pin, op, arg...) \
|
||||||
|
do { \
|
||||||
|
if (pin && pin->ops->op && \
|
||||||
|
!pin->adap->devnode.unregistered) \
|
||||||
|
pin->ops->op(pin->adap, ## arg); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
enum cec_pin_state {
|
enum cec_pin_state {
|
||||||
/* CEC is off */
|
/* CEC is off */
|
||||||
CEC_ST_OFF,
|
CEC_ST_OFF,
|
||||||
|
@@ -135,7 +135,7 @@ static void cec_pin_update(struct cec_pin *pin, bool v, bool force)
|
|||||||
|
|
||||||
static bool cec_pin_read(struct cec_pin *pin)
|
static bool cec_pin_read(struct cec_pin *pin)
|
||||||
{
|
{
|
||||||
bool v = pin->ops->read(pin->adap);
|
bool v = call_pin_op(pin, read);
|
||||||
|
|
||||||
cec_pin_update(pin, v, false);
|
cec_pin_update(pin, v, false);
|
||||||
return v;
|
return v;
|
||||||
@@ -143,13 +143,13 @@ static bool cec_pin_read(struct cec_pin *pin)
|
|||||||
|
|
||||||
static void cec_pin_low(struct cec_pin *pin)
|
static void cec_pin_low(struct cec_pin *pin)
|
||||||
{
|
{
|
||||||
pin->ops->low(pin->adap);
|
call_void_pin_op(pin, low);
|
||||||
cec_pin_update(pin, false, false);
|
cec_pin_update(pin, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cec_pin_high(struct cec_pin *pin)
|
static bool cec_pin_high(struct cec_pin *pin)
|
||||||
{
|
{
|
||||||
pin->ops->high(pin->adap);
|
call_void_pin_op(pin, high);
|
||||||
return cec_pin_read(pin);
|
return cec_pin_read(pin);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1086,7 +1086,7 @@ static int cec_pin_thread_func(void *_adap)
|
|||||||
CEC_PIN_IRQ_UNCHANGED)) {
|
CEC_PIN_IRQ_UNCHANGED)) {
|
||||||
case CEC_PIN_IRQ_DISABLE:
|
case CEC_PIN_IRQ_DISABLE:
|
||||||
if (irq_enabled) {
|
if (irq_enabled) {
|
||||||
pin->ops->disable_irq(adap);
|
call_void_pin_op(pin, disable_irq);
|
||||||
irq_enabled = false;
|
irq_enabled = false;
|
||||||
}
|
}
|
||||||
cec_pin_high(pin);
|
cec_pin_high(pin);
|
||||||
@@ -1097,7 +1097,7 @@ static int cec_pin_thread_func(void *_adap)
|
|||||||
case CEC_PIN_IRQ_ENABLE:
|
case CEC_PIN_IRQ_ENABLE:
|
||||||
if (irq_enabled)
|
if (irq_enabled)
|
||||||
break;
|
break;
|
||||||
pin->enable_irq_failed = !pin->ops->enable_irq(adap);
|
pin->enable_irq_failed = !call_pin_op(pin, enable_irq);
|
||||||
if (pin->enable_irq_failed) {
|
if (pin->enable_irq_failed) {
|
||||||
cec_pin_to_idle(pin);
|
cec_pin_to_idle(pin);
|
||||||
hrtimer_start(&pin->timer, ns_to_ktime(0),
|
hrtimer_start(&pin->timer, ns_to_ktime(0),
|
||||||
@@ -1112,8 +1112,8 @@ static int cec_pin_thread_func(void *_adap)
|
|||||||
if (kthread_should_stop())
|
if (kthread_should_stop())
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (pin->ops->disable_irq && irq_enabled)
|
if (irq_enabled)
|
||||||
pin->ops->disable_irq(adap);
|
call_void_pin_op(pin, disable_irq);
|
||||||
hrtimer_cancel(&pin->timer);
|
hrtimer_cancel(&pin->timer);
|
||||||
cec_pin_read(pin);
|
cec_pin_read(pin);
|
||||||
cec_pin_to_idle(pin);
|
cec_pin_to_idle(pin);
|
||||||
@@ -1208,7 +1208,7 @@ static void cec_pin_adap_status(struct cec_adapter *adap,
|
|||||||
seq_printf(file, "state: %s\n", states[pin->state].name);
|
seq_printf(file, "state: %s\n", states[pin->state].name);
|
||||||
seq_printf(file, "tx_bit: %d\n", pin->tx_bit);
|
seq_printf(file, "tx_bit: %d\n", pin->tx_bit);
|
||||||
seq_printf(file, "rx_bit: %d\n", pin->rx_bit);
|
seq_printf(file, "rx_bit: %d\n", pin->rx_bit);
|
||||||
seq_printf(file, "cec pin: %d\n", pin->ops->read(adap));
|
seq_printf(file, "cec pin: %d\n", call_pin_op(pin, read));
|
||||||
seq_printf(file, "cec pin events dropped: %u\n",
|
seq_printf(file, "cec pin events dropped: %u\n",
|
||||||
pin->work_pin_events_dropped_cnt);
|
pin->work_pin_events_dropped_cnt);
|
||||||
seq_printf(file, "irq failed: %d\n", pin->enable_irq_failed);
|
seq_printf(file, "irq failed: %d\n", pin->enable_irq_failed);
|
||||||
@@ -1261,8 +1261,7 @@ static void cec_pin_adap_status(struct cec_adapter *adap,
|
|||||||
pin->rx_data_bit_too_long_cnt = 0;
|
pin->rx_data_bit_too_long_cnt = 0;
|
||||||
pin->rx_low_drive_cnt = 0;
|
pin->rx_low_drive_cnt = 0;
|
||||||
pin->tx_low_drive_cnt = 0;
|
pin->tx_low_drive_cnt = 0;
|
||||||
if (pin->ops->status)
|
call_void_pin_op(pin, status, file);
|
||||||
pin->ops->status(adap, file);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cec_pin_adap_monitor_all_enable(struct cec_adapter *adap,
|
static int cec_pin_adap_monitor_all_enable(struct cec_adapter *adap,
|
||||||
@@ -1278,7 +1277,7 @@ static void cec_pin_adap_free(struct cec_adapter *adap)
|
|||||||
{
|
{
|
||||||
struct cec_pin *pin = adap->pin;
|
struct cec_pin *pin = adap->pin;
|
||||||
|
|
||||||
if (pin->ops->free)
|
if (pin && pin->ops->free)
|
||||||
pin->ops->free(adap);
|
pin->ops->free(adap);
|
||||||
adap->pin = NULL;
|
adap->pin = NULL;
|
||||||
kfree(pin);
|
kfree(pin);
|
||||||
@@ -1288,7 +1287,7 @@ static int cec_pin_received(struct cec_adapter *adap, struct cec_msg *msg)
|
|||||||
{
|
{
|
||||||
struct cec_pin *pin = adap->pin;
|
struct cec_pin *pin = adap->pin;
|
||||||
|
|
||||||
if (pin->ops->received)
|
if (pin->ops->received && !adap->devnode.unregistered)
|
||||||
return pin->ops->received(adap, msg);
|
return pin->ops->received(adap, msg);
|
||||||
return -ENOMSG;
|
return -ENOMSG;
|
||||||
}
|
}
|
||||||
|
@@ -17,6 +17,16 @@
|
|||||||
pr_info("cec-%s: " fmt, adap->name, ## arg); \
|
pr_info("cec-%s: " fmt, adap->name, ## arg); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#define call_op(adap, op, arg...) \
|
||||||
|
((adap->ops->op && !adap->devnode.unregistered) ? \
|
||||||
|
adap->ops->op(adap, ## arg) : 0)
|
||||||
|
|
||||||
|
#define call_void_op(adap, op, arg...) \
|
||||||
|
do { \
|
||||||
|
if (adap->ops->op && !adap->devnode.unregistered) \
|
||||||
|
adap->ops->op(adap, ## arg); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
/* devnode to cec_adapter */
|
/* devnode to cec_adapter */
|
||||||
#define to_cec_adapter(node) container_of(node, struct cec_adapter, devnode)
|
#define to_cec_adapter(node) container_of(node, struct cec_adapter, devnode)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user