[PATCH 3/3] cec: correctly cancel delayed work when the CEC adapter is disabled

Hans Verkuil hverkuil at xs4all.nl
Wed May 11 07:11:28 UTC 2016


From: Hans Verkuil <hans.verkuil at cisco.com>

When cleaning up pending work from the wait_queue list, make sure to cancel the
delayed work. Otherwise nasty kernel oopses will occur when the timer goes off
and the cec_data struct has disappeared.

Signed-off-by: Hans Verkuil <hans.verkuil at cisco.com>
---
 drivers/staging/media/cec/cec.c | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/drivers/staging/media/cec/cec.c b/drivers/staging/media/cec/cec.c
index 9a62aa2..c2a876e 100644
--- a/drivers/staging/media/cec/cec.c
+++ b/drivers/staging/media/cec/cec.c
@@ -393,13 +393,28 @@ static int cec_thread_func(void *_adap)
 							struct cec_data, list);
 				cec_data_cancel(data);
 			}
+			if (adap->transmitting)
+				cec_data_cancel(adap->transmitting);
+
+			/*
+			 * Cancel the pending timeout work. We have to unlock
+			 * the mutex when flushing the work since
+			 * cec_wait_timeout() will take it. This is OK since
+			 * no new entries can be added to wait_queue as long
+			 * as adap->transmitting is NULL, which it is due to
+			 * the cec_data_cancel() above.
+			 */
 			while (!list_empty(&adap->wait_queue)) {
 				data = list_first_entry(&adap->wait_queue,
 							struct cec_data, list);
+
+				if (!cancel_delayed_work(&data->work)) {
+					mutex_unlock(&adap->lock);
+					flush_scheduled_work();
+					mutex_lock(&adap->lock);
+				}
 				cec_data_cancel(data);
 			}
-			if (adap->transmitting)
-				cec_data_cancel(adap->transmitting);
 			goto unlock;
 		}
 
-- 
2.8.1



More information about the dri-devel mailing list