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:
Greg Kroah-Hartman
2024-07-15 17:20:18 +00:00
parent 12d97237e4
commit e4f3376872
4 changed files with 19 additions and 39 deletions

View File

@@ -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,17 +1570,15 @@ 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 &&
call_op(adap, adap_monitor_all_enable, true)) { call_op(adap, adap_monitor_all_enable, true)) {

View File

@@ -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));

View File

@@ -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);

View File

@@ -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;