Commit e2ed5024 authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab

media: cec: use call_op and check for !unregistered

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: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@kernel.org>
parent 567f882a
...@@ -39,15 +39,6 @@ static void cec_fill_msg_report_features(struct cec_adapter *adap, ...@@ -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) ...@@ -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) ...@@ -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;
...@@ -1331,7 +1322,7 @@ static int cec_config_log_addr(struct cec_adapter *adap, ...@@ -1331,7 +1322,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;
...@@ -1348,9 +1339,8 @@ static int cec_config_log_addr(struct cec_adapter *adap, ...@@ -1348,9 +1339,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_configuring = false; adap->is_configuring = false;
adap->is_configured = false; adap->is_configured = false;
...@@ -1593,7 +1583,7 @@ static int cec_activate_cnt_inc(struct cec_adapter *adap) ...@@ -1593,7 +1583,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);
...@@ -1610,7 +1600,7 @@ static void cec_activate_cnt_dec(struct cec_adapter *adap) ...@@ -1610,7 +1600,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;
...@@ -1984,11 +1974,10 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg, ...@@ -1984,11 +1974,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) ...@@ -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) ...@@ -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, ...@@ -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) ...@@ -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 @@ ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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);
...@@ -1207,7 +1207,7 @@ static void cec_pin_adap_status(struct cec_adapter *adap, ...@@ -1207,7 +1207,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);
...@@ -1260,8 +1260,7 @@ static void cec_pin_adap_status(struct cec_adapter *adap, ...@@ -1260,8 +1260,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,
...@@ -1277,7 +1276,7 @@ static void cec_pin_adap_free(struct cec_adapter *adap) ...@@ -1277,7 +1276,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);
...@@ -1287,7 +1286,7 @@ static int cec_pin_received(struct cec_adapter *adap, struct cec_msg *msg) ...@@ -1287,7 +1286,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 @@ ...@@ -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)
......
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