| From f3b7e6d977f13420a5e9b9cc968ee05043c83e7a Mon Sep 17 00:00:00 2001 |
| From: Hans Verkuil <hverkuil-cisco@xs4all.nl> |
| Date: Sat, 7 Dec 2019 23:43:23 +0100 |
| Subject: [PATCH] media: pulse8-cec: fix lost cec_transmit_attempt_done() call |
| |
| commit e5a52a1d15c79bb48a430fb263852263ec1d3f11 upstream. |
| |
| The periodic PING command could interfere with the result of |
| a CEC transmit, causing a lost cec_transmit_attempt_done() |
| call. |
| |
| Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> |
| Cc: <stable@vger.kernel.org> # for v4.10 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/usb/pulse8-cec/pulse8-cec.c b/drivers/media/usb/pulse8-cec/pulse8-cec.c |
| index ac88ade94cda..59609556d969 100644 |
| --- a/drivers/media/usb/pulse8-cec/pulse8-cec.c |
| +++ b/drivers/media/usb/pulse8-cec/pulse8-cec.c |
| @@ -116,6 +116,7 @@ struct pulse8 { |
| unsigned int vers; |
| struct completion cmd_done; |
| struct work_struct work; |
| + u8 work_result; |
| struct delayed_work ping_eeprom_work; |
| struct cec_msg rx_msg; |
| u8 data[DATA_SIZE]; |
| @@ -137,8 +138,10 @@ static void pulse8_irq_work_handler(struct work_struct *work) |
| { |
| struct pulse8 *pulse8 = |
| container_of(work, struct pulse8, work); |
| + u8 result = pulse8->work_result; |
| |
| - switch (pulse8->data[0] & 0x3f) { |
| + pulse8->work_result = 0; |
| + switch (result & 0x3f) { |
| case MSGCODE_FRAME_DATA: |
| cec_received_msg(pulse8->adap, &pulse8->rx_msg); |
| break; |
| @@ -172,12 +175,12 @@ static irqreturn_t pulse8_interrupt(struct serio *serio, unsigned char data, |
| pulse8->escape = false; |
| } else if (data == MSGEND) { |
| struct cec_msg *msg = &pulse8->rx_msg; |
| + u8 msgcode = pulse8->buf[0]; |
| |
| if (debug) |
| dev_info(pulse8->dev, "received: %*ph\n", |
| pulse8->idx, pulse8->buf); |
| - pulse8->data[0] = pulse8->buf[0]; |
| - switch (pulse8->buf[0] & 0x3f) { |
| + switch (msgcode & 0x3f) { |
| case MSGCODE_FRAME_START: |
| msg->len = 1; |
| msg->msg[0] = pulse8->buf[1]; |
| @@ -186,14 +189,20 @@ static irqreturn_t pulse8_interrupt(struct serio *serio, unsigned char data, |
| if (msg->len == CEC_MAX_MSG_SIZE) |
| break; |
| msg->msg[msg->len++] = pulse8->buf[1]; |
| - if (pulse8->buf[0] & MSGCODE_FRAME_EOM) |
| + if (msgcode & MSGCODE_FRAME_EOM) { |
| + WARN_ON(pulse8->work_result); |
| + pulse8->work_result = msgcode; |
| schedule_work(&pulse8->work); |
| + break; |
| + } |
| break; |
| case MSGCODE_TRANSMIT_SUCCEEDED: |
| case MSGCODE_TRANSMIT_FAILED_LINE: |
| case MSGCODE_TRANSMIT_FAILED_ACK: |
| case MSGCODE_TRANSMIT_FAILED_TIMEOUT_DATA: |
| case MSGCODE_TRANSMIT_FAILED_TIMEOUT_LINE: |
| + WARN_ON(pulse8->work_result); |
| + pulse8->work_result = msgcode; |
| schedule_work(&pulse8->work); |
| break; |
| case MSGCODE_HIGH_ERROR: |
| -- |
| 2.7.4 |
| |