Revert "media: cec: fix a deadlock situation"
This reverts commit 0ab74ae99f
which is
commit a9e6107616bb8108aa4fc22584a05e69761a91f7 upstream.
It breaks the Android kernel abi and can be brought back in the future
in an abi-safe way if it is really needed.
Bug: 161946584
Change-Id: I8abbf69a8f0812b07813ba1b94b5457d4fa27f7b
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
@@ -161,10 +161,10 @@ static void cec_queue_event(struct cec_adapter *adap,
|
|||||||
u64 ts = ktime_get_ns();
|
u64 ts = ktime_get_ns();
|
||||||
struct cec_fh *fh;
|
struct cec_fh *fh;
|
||||||
|
|
||||||
mutex_lock(&adap->devnode.lock_fhs);
|
mutex_lock(&adap->devnode.lock);
|
||||||
list_for_each_entry(fh, &adap->devnode.fhs, list)
|
list_for_each_entry(fh, &adap->devnode.fhs, list)
|
||||||
cec_queue_event_fh(fh, ev, ts);
|
cec_queue_event_fh(fh, ev, ts);
|
||||||
mutex_unlock(&adap->devnode.lock_fhs);
|
mutex_unlock(&adap->devnode.lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Notify userspace that the CEC pin changed state at the given time. */
|
/* Notify userspace that the CEC pin changed state at the given time. */
|
||||||
@@ -178,12 +178,11 @@ void cec_queue_pin_cec_event(struct cec_adapter *adap, bool is_high,
|
|||||||
};
|
};
|
||||||
struct cec_fh *fh;
|
struct cec_fh *fh;
|
||||||
|
|
||||||
mutex_lock(&adap->devnode.lock_fhs);
|
mutex_lock(&adap->devnode.lock);
|
||||||
list_for_each_entry(fh, &adap->devnode.fhs, list) {
|
list_for_each_entry(fh, &adap->devnode.fhs, list)
|
||||||
if (fh->mode_follower == CEC_MODE_MONITOR_PIN)
|
if (fh->mode_follower == CEC_MODE_MONITOR_PIN)
|
||||||
cec_queue_event_fh(fh, &ev, ktime_to_ns(ts));
|
cec_queue_event_fh(fh, &ev, ktime_to_ns(ts));
|
||||||
}
|
mutex_unlock(&adap->devnode.lock);
|
||||||
mutex_unlock(&adap->devnode.lock_fhs);
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(cec_queue_pin_cec_event);
|
EXPORT_SYMBOL_GPL(cec_queue_pin_cec_event);
|
||||||
|
|
||||||
@@ -196,10 +195,10 @@ void cec_queue_pin_hpd_event(struct cec_adapter *adap, bool is_high, ktime_t ts)
|
|||||||
};
|
};
|
||||||
struct cec_fh *fh;
|
struct cec_fh *fh;
|
||||||
|
|
||||||
mutex_lock(&adap->devnode.lock_fhs);
|
mutex_lock(&adap->devnode.lock);
|
||||||
list_for_each_entry(fh, &adap->devnode.fhs, list)
|
list_for_each_entry(fh, &adap->devnode.fhs, list)
|
||||||
cec_queue_event_fh(fh, &ev, ktime_to_ns(ts));
|
cec_queue_event_fh(fh, &ev, ktime_to_ns(ts));
|
||||||
mutex_unlock(&adap->devnode.lock_fhs);
|
mutex_unlock(&adap->devnode.lock);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(cec_queue_pin_hpd_event);
|
EXPORT_SYMBOL_GPL(cec_queue_pin_hpd_event);
|
||||||
|
|
||||||
@@ -212,10 +211,10 @@ void cec_queue_pin_5v_event(struct cec_adapter *adap, bool is_high, ktime_t ts)
|
|||||||
};
|
};
|
||||||
struct cec_fh *fh;
|
struct cec_fh *fh;
|
||||||
|
|
||||||
mutex_lock(&adap->devnode.lock_fhs);
|
mutex_lock(&adap->devnode.lock);
|
||||||
list_for_each_entry(fh, &adap->devnode.fhs, list)
|
list_for_each_entry(fh, &adap->devnode.fhs, list)
|
||||||
cec_queue_event_fh(fh, &ev, ktime_to_ns(ts));
|
cec_queue_event_fh(fh, &ev, ktime_to_ns(ts));
|
||||||
mutex_unlock(&adap->devnode.lock_fhs);
|
mutex_unlock(&adap->devnode.lock);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(cec_queue_pin_5v_event);
|
EXPORT_SYMBOL_GPL(cec_queue_pin_5v_event);
|
||||||
|
|
||||||
@@ -287,12 +286,12 @@ static void cec_queue_msg_monitor(struct cec_adapter *adap,
|
|||||||
u32 monitor_mode = valid_la ? CEC_MODE_MONITOR :
|
u32 monitor_mode = valid_la ? CEC_MODE_MONITOR :
|
||||||
CEC_MODE_MONITOR_ALL;
|
CEC_MODE_MONITOR_ALL;
|
||||||
|
|
||||||
mutex_lock(&adap->devnode.lock_fhs);
|
mutex_lock(&adap->devnode.lock);
|
||||||
list_for_each_entry(fh, &adap->devnode.fhs, list) {
|
list_for_each_entry(fh, &adap->devnode.fhs, list) {
|
||||||
if (fh->mode_follower >= monitor_mode)
|
if (fh->mode_follower >= monitor_mode)
|
||||||
cec_queue_msg_fh(fh, msg);
|
cec_queue_msg_fh(fh, msg);
|
||||||
}
|
}
|
||||||
mutex_unlock(&adap->devnode.lock_fhs);
|
mutex_unlock(&adap->devnode.lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -303,12 +302,12 @@ static void cec_queue_msg_followers(struct cec_adapter *adap,
|
|||||||
{
|
{
|
||||||
struct cec_fh *fh;
|
struct cec_fh *fh;
|
||||||
|
|
||||||
mutex_lock(&adap->devnode.lock_fhs);
|
mutex_lock(&adap->devnode.lock);
|
||||||
list_for_each_entry(fh, &adap->devnode.fhs, list) {
|
list_for_each_entry(fh, &adap->devnode.fhs, list) {
|
||||||
if (fh->mode_follower == CEC_MODE_FOLLOWER)
|
if (fh->mode_follower == CEC_MODE_FOLLOWER)
|
||||||
cec_queue_msg_fh(fh, msg);
|
cec_queue_msg_fh(fh, msg);
|
||||||
}
|
}
|
||||||
mutex_unlock(&adap->devnode.lock_fhs);
|
mutex_unlock(&adap->devnode.lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Notify userspace of an adapter state change. */
|
/* Notify userspace of an adapter state change. */
|
||||||
@@ -1560,7 +1559,6 @@ void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block)
|
|||||||
/* Disabling monitor all mode should always succeed */
|
/* Disabling monitor all mode should always succeed */
|
||||||
if (adap->monitor_all_cnt)
|
if (adap->monitor_all_cnt)
|
||||||
WARN_ON(call_op(adap, adap_monitor_all_enable, false));
|
WARN_ON(call_op(adap, adap_monitor_all_enable, false));
|
||||||
/* serialize adap_enable */
|
|
||||||
mutex_lock(&adap->devnode.lock);
|
mutex_lock(&adap->devnode.lock);
|
||||||
if (adap->needs_hpd || list_empty(&adap->devnode.fhs)) {
|
if (adap->needs_hpd || list_empty(&adap->devnode.fhs)) {
|
||||||
WARN_ON(adap->ops->adap_enable(adap, false));
|
WARN_ON(adap->ops->adap_enable(adap, false));
|
||||||
@@ -1572,16 +1570,14 @@ void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* serialize adap_enable */
|
|
||||||
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;
|
||||||
|
|
||||||
if (adap->needs_hpd || list_empty(&adap->devnode.fhs)) {
|
if ((adap->needs_hpd || list_empty(&adap->devnode.fhs)) &&
|
||||||
if (adap->ops->adap_enable(adap, true)) {
|
adap->ops->adap_enable(adap, true)) {
|
||||||
mutex_unlock(&adap->devnode.lock);
|
mutex_unlock(&adap->devnode.lock);
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (adap->monitor_all_cnt &&
|
if (adap->monitor_all_cnt &&
|
||||||
|
@@ -586,7 +586,6 @@ static int cec_open(struct inode *inode, struct file *filp)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* serialize adap_enable */
|
|
||||||
mutex_lock(&devnode->lock);
|
mutex_lock(&devnode->lock);
|
||||||
if (list_empty(&devnode->fhs) &&
|
if (list_empty(&devnode->fhs) &&
|
||||||
!adap->needs_hpd &&
|
!adap->needs_hpd &&
|
||||||
@@ -625,9 +624,7 @@ static int cec_open(struct inode *inode, struct file *filp)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mutex_lock(&devnode->lock_fhs);
|
|
||||||
list_add(&fh->list, &devnode->fhs);
|
list_add(&fh->list, &devnode->fhs);
|
||||||
mutex_unlock(&devnode->lock_fhs);
|
|
||||||
mutex_unlock(&devnode->lock);
|
mutex_unlock(&devnode->lock);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -656,11 +653,8 @@ static int cec_release(struct inode *inode, struct file *filp)
|
|||||||
cec_monitor_all_cnt_dec(adap);
|
cec_monitor_all_cnt_dec(adap);
|
||||||
mutex_unlock(&adap->lock);
|
mutex_unlock(&adap->lock);
|
||||||
|
|
||||||
/* serialize adap_enable */
|
|
||||||
mutex_lock(&devnode->lock);
|
mutex_lock(&devnode->lock);
|
||||||
mutex_lock(&devnode->lock_fhs);
|
|
||||||
list_del(&fh->list);
|
list_del(&fh->list);
|
||||||
mutex_unlock(&devnode->lock_fhs);
|
|
||||||
if (cec_is_registered(adap) && list_empty(&devnode->fhs) &&
|
if (cec_is_registered(adap) && list_empty(&devnode->fhs) &&
|
||||||
!adap->needs_hpd && adap->phys_addr == CEC_PHYS_ADDR_INVALID) {
|
!adap->needs_hpd && adap->phys_addr == CEC_PHYS_ADDR_INVALID) {
|
||||||
WARN_ON(adap->ops->adap_enable(adap, false));
|
WARN_ON(adap->ops->adap_enable(adap, false));
|
||||||
|
@@ -167,10 +167,8 @@ static void cec_devnode_unregister(struct cec_adapter *adap)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_lock(&devnode->lock_fhs);
|
|
||||||
list_for_each_entry(fh, &devnode->fhs, list)
|
list_for_each_entry(fh, &devnode->fhs, list)
|
||||||
wake_up_interruptible(&fh->wait);
|
wake_up_interruptible(&fh->wait);
|
||||||
mutex_unlock(&devnode->lock_fhs);
|
|
||||||
|
|
||||||
devnode->registered = false;
|
devnode->registered = false;
|
||||||
devnode->unregistered = true;
|
devnode->unregistered = true;
|
||||||
@@ -274,7 +272,6 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops,
|
|||||||
|
|
||||||
/* adap->devnode initialization */
|
/* adap->devnode initialization */
|
||||||
INIT_LIST_HEAD(&adap->devnode.fhs);
|
INIT_LIST_HEAD(&adap->devnode.fhs);
|
||||||
mutex_init(&adap->devnode.lock_fhs);
|
|
||||||
mutex_init(&adap->devnode.lock);
|
mutex_init(&adap->devnode.lock);
|
||||||
|
|
||||||
adap->kthread = kthread_run(cec_thread_func, adap, "cec-%s", name);
|
adap->kthread = kthread_run(cec_thread_func, adap, "cec-%s", name);
|
||||||
|
@@ -26,17 +26,13 @@
|
|||||||
* @dev: cec device
|
* @dev: cec device
|
||||||
* @cdev: cec character device
|
* @cdev: cec character device
|
||||||
* @minor: device node minor number
|
* @minor: device node minor number
|
||||||
* @lock: lock to serialize open/release and registration
|
|
||||||
* @registered: the device was correctly registered
|
* @registered: the device was correctly registered
|
||||||
* @unregistered: the device was unregistered
|
* @unregistered: the device was unregistered
|
||||||
* @lock_fhs: lock to control access to @fhs
|
|
||||||
* @fhs: the list of open filehandles (cec_fh)
|
* @fhs: the list of open filehandles (cec_fh)
|
||||||
|
* @lock: lock to control access to this structure
|
||||||
*
|
*
|
||||||
* This structure represents a cec-related device node.
|
* This structure represents a cec-related device node.
|
||||||
*
|
*
|
||||||
* To add or remove filehandles from @fhs the @lock must be taken first,
|
|
||||||
* followed by @lock_fhs. It is safe to access @fhs if either lock is held.
|
|
||||||
*
|
|
||||||
* The @parent is a physical device. It must be set by core or device drivers
|
* The @parent is a physical device. It must be set by core or device drivers
|
||||||
* before registering the node.
|
* before registering the node.
|
||||||
*/
|
*/
|
||||||
@@ -47,13 +43,10 @@ struct cec_devnode {
|
|||||||
|
|
||||||
/* device info */
|
/* device info */
|
||||||
int minor;
|
int minor;
|
||||||
/* serialize open/release and registration */
|
|
||||||
struct mutex lock;
|
|
||||||
bool registered;
|
bool registered;
|
||||||
bool unregistered;
|
bool unregistered;
|
||||||
/* protect access to fhs */
|
|
||||||
struct mutex lock_fhs;
|
|
||||||
struct list_head fhs;
|
struct list_head fhs;
|
||||||
|
struct mutex lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cec_adapter;
|
struct cec_adapter;
|
||||||
|
Reference in New Issue
Block a user