| From 00e61fd87447fb1b63e20ad317c1eb5c21538357 Mon Sep 17 00:00:00 2001 |
| From: Hans Verkuil <hverkuil-cisco@xs4all.nl> |
| Date: Sat, 7 Dec 2019 23:48:09 +0100 |
| Subject: [PATCH] media: cec: avoid decrementing transmit_queue_sz if it is 0 |
| |
| commit 95c29d46ab2a517e4c26d0a07300edca6768db17 upstream. |
| |
| WARN if transmit_queue_sz is 0 but do not decrement it. |
| The CEC adapter will become unresponsive if it goes below |
| 0 since then it thinks there are 4 billion messages in the |
| queue. |
| |
| Obviously this should not happen, but a driver bug could |
| cause this. |
| |
| Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> |
| Cc: <stable@vger.kernel.org> # for v4.12 and up |
| Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/media/cec/cec-adap.c b/drivers/media/cec/cec-adap.c |
| index 4f66618e902f..f0e5ebabcb05 100644 |
| --- a/drivers/media/cec/cec-adap.c |
| +++ b/drivers/media/cec/cec-adap.c |
| @@ -365,7 +365,8 @@ static void cec_data_cancel(struct cec_data *data, u8 tx_status) |
| } else { |
| list_del_init(&data->list); |
| if (!(data->msg.tx_status & CEC_TX_STATUS_OK)) |
| - data->adap->transmit_queue_sz--; |
| + if (!WARN_ON(!data->adap->transmit_queue_sz)) |
| + data->adap->transmit_queue_sz--; |
| } |
| |
| if (data->msg.tx_status & CEC_TX_STATUS_OK) { |
| @@ -417,6 +418,14 @@ static void cec_flush(struct cec_adapter *adap) |
| * need to do anything special in that case. |
| */ |
| } |
| + /* |
| + * If something went wrong and this counter isn't what it should |
| + * be, then this will reset it back to 0. Warn if it is not 0, |
| + * since it indicates a bug, either in this framework or in a |
| + * CEC driver. |
| + */ |
| + if (WARN_ON(adap->transmit_queue_sz)) |
| + adap->transmit_queue_sz = 0; |
| } |
| |
| /* |
| @@ -507,7 +516,8 @@ int cec_thread_func(void *_adap) |
| data = list_first_entry(&adap->transmit_queue, |
| struct cec_data, list); |
| list_del_init(&data->list); |
| - adap->transmit_queue_sz--; |
| + if (!WARN_ON(!data->adap->transmit_queue_sz)) |
| + adap->transmit_queue_sz--; |
| |
| /* Make this the current transmitting message */ |
| adap->transmitting = data; |
| -- |
| 2.7.4 |
| |