From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail.linuxfoundation.org ([140.211.169.12]:34020 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754253AbdDLNeI (ORCPT ); Wed, 12 Apr 2017 09:34:08 -0400 Subject: Patch "i2c: bcm2835: Fix hang for writing messages larger than 16 bytes" has been added to the 4.9-stable tree To: noralf@tronnes.org, amit.pundir@linaro.org, eric@anholt.net, gregkh@linuxfoundation.org, kernel@martin.sperl.org, wsa@the-dreams.de Cc: , From: Date: Wed, 12 Apr 2017 15:33:58 +0200 Message-ID: <1492004038115113@kroah.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: stable-owner@vger.kernel.org List-ID: This is a note to let you know that I've just added the patch titled i2c: bcm2835: Fix hang for writing messages larger than 16 bytes to the 4.9-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: i2c-bcm2835-fix-hang-for-writing-messages-larger-than-16-bytes.patch and it can be found in the queue-4.9 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let know about it. >>From e2474541032db65d02bf88b6a8c2f954654b443f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Mon, 3 Oct 2016 22:06:08 +0200 Subject: i2c: bcm2835: Fix hang for writing messages larger than 16 bytes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Noralf Trønnes commit e2474541032db65d02bf88b6a8c2f954654b443f upstream. Writing messages larger than the FIFO size results in a hang, rendering the machine unusable. This is because the RXD status flag is set on the first interrupt which results in bcm2835_drain_rxfifo() stealing bytes from the buffer. The controller continues to trigger interrupts waiting for the missing bytes, but bcm2835_fill_txfifo() has none to give. In this situation wait_for_completion_timeout() apparently is unable to stop the madness. The BCM2835 ARM Peripherals datasheet has this to say about the flags: TXD: is set when the FIFO has space for at least one byte of data. RXD: is set when the FIFO contains at least one byte of data. TXW: is set during a write transfer and the FIFO is less than full. RXR: is set during a read transfer and the FIFO is or more full. Implementing the logic from the downstream i2c-bcm2708 driver solved the hang problem. Signed-off-by: Noralf Trønnes Reviewed-by: Eric Anholt Reviewed-by: Martin Sperl Signed-off-by: Wolfram Sang Signed-off-by: Amit Pundir Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/i2c-bcm2835.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) --- a/drivers/i2c/busses/i2c-bcm2835.c +++ b/drivers/i2c/busses/i2c-bcm2835.c @@ -64,6 +64,7 @@ struct bcm2835_i2c_dev { int irq; struct i2c_adapter adapter; struct completion completion; + struct i2c_msg *curr_msg; u32 msg_err; u8 *msg_buf; size_t msg_buf_remaining; @@ -126,14 +127,13 @@ static irqreturn_t bcm2835_i2c_isr(int t return IRQ_HANDLED; } - if (val & BCM2835_I2C_S_RXD) { - bcm2835_drain_rxfifo(i2c_dev); - if (!(val & BCM2835_I2C_S_DONE)) - return IRQ_HANDLED; - } - if (val & BCM2835_I2C_S_DONE) { - if (i2c_dev->msg_buf_remaining) + if (i2c_dev->curr_msg->flags & I2C_M_RD) { + bcm2835_drain_rxfifo(i2c_dev); + val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S); + } + + if ((val & BCM2835_I2C_S_RXD) || i2c_dev->msg_buf_remaining) i2c_dev->msg_err = BCM2835_I2C_S_LEN; else i2c_dev->msg_err = 0; @@ -141,11 +141,16 @@ static irqreturn_t bcm2835_i2c_isr(int t return IRQ_HANDLED; } - if (val & BCM2835_I2C_S_TXD) { + if (val & BCM2835_I2C_S_TXW) { bcm2835_fill_txfifo(i2c_dev); return IRQ_HANDLED; } + if (val & BCM2835_I2C_S_RXR) { + bcm2835_drain_rxfifo(i2c_dev); + return IRQ_HANDLED; + } + return IRQ_NONE; } @@ -155,6 +160,7 @@ static int bcm2835_i2c_xfer_msg(struct b u32 c; unsigned long time_left; + i2c_dev->curr_msg = msg; i2c_dev->msg_buf = msg->buf; i2c_dev->msg_buf_remaining = msg->len; reinit_completion(&i2c_dev->completion); Patches currently in stable-queue which might be from noralf@tronnes.org are queue-4.9/i2c-bcm2835-fix-hang-for-writing-messages-larger-than-16-bytes.patch