diff options
author | Rafał Miłecki <rafal@milecki.pl> | 2017-03-22 21:09:00 +0100 |
---|---|---|
committer | Rafał Miłecki <rafal@milecki.pl> | 2017-03-24 08:06:35 +0100 |
commit | fce21ae4ccfcee0c28fb18f5507e145fb0b02dec (patch) | |
tree | 6c29b7c1f65945991d0cae13af012e6c14adc713 /target/linux/brcm2708/patches-4.9/950-0106-i2c-bcm2835-Fix-hang-for-writing-messages-larger-tha.patch | |
parent | 46e390322a58bdc632ee43fdf9d14115dac26e7a (diff) | |
download | upstream-fce21ae4ccfcee0c28fb18f5507e145fb0b02dec.tar.gz upstream-fce21ae4ccfcee0c28fb18f5507e145fb0b02dec.tar.bz2 upstream-fce21ae4ccfcee0c28fb18f5507e145fb0b02dec.zip |
brcm2708: rename all patches from raspberrypi git tree to use 950 prefix
Right now all brcm2708 patches are extracted from the non-mainline
raspberrypi/linux git tree. Many of them are hacks and/or are unneeded
in LEDE. Raspberry Pi is getting better and better mainline support so
it would be nice to finally start maintaining patches in a cleaner way:
1) Backport patches accepted in upstream tree
2) Start using upstream drivers
3) Pick only these patches that are needed for more complete support
Handling above tasks requires grouping patches - ideally using the same
prefixes as generic ones. It means we should rename existing patches to
use some high prefix. This will allow e.g. use 0xx for backported code.
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Acked-by: Stijn Tintel <stijn@linux-ipv6.be>
Diffstat (limited to 'target/linux/brcm2708/patches-4.9/950-0106-i2c-bcm2835-Fix-hang-for-writing-messages-larger-tha.patch')
-rw-r--r-- | target/linux/brcm2708/patches-4.9/950-0106-i2c-bcm2835-Fix-hang-for-writing-messages-larger-tha.patch | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/target/linux/brcm2708/patches-4.9/950-0106-i2c-bcm2835-Fix-hang-for-writing-messages-larger-tha.patch b/target/linux/brcm2708/patches-4.9/950-0106-i2c-bcm2835-Fix-hang-for-writing-messages-larger-tha.patch new file mode 100644 index 0000000000..899c75e0db --- /dev/null +++ b/target/linux/brcm2708/patches-4.9/950-0106-i2c-bcm2835-Fix-hang-for-writing-messages-larger-tha.patch @@ -0,0 +1,90 @@ +From 89b466914a0d49f08d00be25556ba22497b9a284 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org> +Date: Sat, 17 Sep 2016 15:07:10 +0200 +Subject: [PATCH] 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 + +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 <noralf@tronnes.org> +Reviewed-by: Eric Anholt <eric@anholt.net> +Reviewed-by: Martin Sperl <kernel@martin.sperl.org> +--- + 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); |