MMC: PL180: Fix infinite loop with VExpress extended fifo implementation
PATCH 1/1 MMC: PL180: Fix infinite loop with VExpress extended fifo implementation
From: Jon Medhurst <[email protected]>
The new IO FPGA implementation for Versatile Express contains an MMCI (PL180) cell with the FIFO extended to 128 words. This causes the read_bytes() function to go into an infinite loop; as it will wait for for the half-full signal (SDI_STA_RXFIFOBR) if there are more than 8 words remaining (SDI_FIFO_BURST_SIZE), but it won't receive this signal once there are fewer than 64 words left to transfer.
One possible fix is to add some build time configuration to change SDI_FIFO_BURST_SIZE for the new implementation. However, the problematic code only seems to exist as a small performance optimisation, so the solution implemented by this patch is to simply remove it. The error checking following the loop is also removed as this will be handled by code further down the function.
---
If it is desirable to keep the burst read optimisation, then an alternative solution would be to keep the loop and add an if clause to do a single read if the fifo doesn't have enough for a burst.
--- drivers/mmc/arm_pl180_mmci.c | 26 -------------------------- 1 files changed, 0 insertions(+), 26 deletions(-)
drivers/mmc/arm_pl180_mmci.c +0 -26
@@ -111,7 +111,6 @@ static int do_command(struct mmc *dev, struct mmc_cmd *cmd)static int read_bytes (struct mmc *dev,u32 *dest,u32 blkcount,u32 blksize) {u32 *tempbuff = dest; -int i;u64 xfercount = blkcount * blksize;struct mmc_host *host = dev->priv;u32 status, status_err;
@@ -121,31 +120,6 @@ static int read_bytes(struct mmc *dev, u32 *dest, u32 blkcount, u32 blksize) status =readl (&host->base->status); status_err = status & (SDI_STA_DCRCFAIL |SDI_STA_DTIMEOUT |SDI_STA_RXOVERR ); -while (!status_err && - (xfercount >=SDI_FIFO_BURST_SIZE *sizeof (u32))) { -if (status &SDI_STA_RXFIFOBR ) { -for (i =0 ; i <SDI_FIFO_BURST_SIZE ; i++) - *(tempbuff + i) =readl (&host->base->fifo); - tempbuff +=SDI_FIFO_BURST_SIZE ; - xfercount -=SDI_FIFO_BURST_SIZE *sizeof (u32); - } - status =readl (&host->base->status); - status_err = status & - (SDI_STA_DCRCFAIL |SDI_STA_DTIMEOUT |SDI_STA_RXOVERR ); - } - -if (status &SDI_STA_DTIMEOUT ) { -printf ("Read data timed out, xfercount: %llu, status: 0x%08X\n" , - xfercount, status); -return -ETIMEDOUT ; - }else if (status &SDI_STA_DCRCFAIL ) { -printf ("Read data blk CRC error: 0x%x\n" , status); -return -EILSEQ ; - }else if (status &SDI_STA_RXOVERR ) { -printf ("Read data RX overflow error\n" ); -return -EIO ; - } -while ((!status_err) && (xfercount >=sizeof (u32))) {if (status &SDI_STA_RXDAVL ) { *(tempbuff) =readl (&host->base->fifo);
Signature · 1 line
1.7.4.1
PATCH 1/1 MMC: PL180: Fix infinite loop with VExpress extended fifo implementation
Hi Tixy,
Quoted 2 lines
One possible fix is to add some build time configuration to change
SDI_FIFO_BURST_SIZEfor the new implementation.
You can also detect the configuration in runtime, basing on PeriphID:
http://infocenter.arm.com/help/topic/com.arm.doc.ddi0172a/i1024149.html
Configuration == 0 (ID == 0x00041180) -> FIFO length = 16 * 4 Configuration == 1 (ID == 0x01041180) -> FIFO length = 128 * 4
Cheers!
PAwe?
PATCH 1/1 MMC: PL180: Fix infinite loop with VExpress extended fifo implementation
Quoted 11 lines · Pawel Moll
Hi Tixy,
Quoted 2 lines
One possible fix is to add some build time configuration to change
SDI_FIFO_BURST_SIZEfor the new implementation.You can also detect the configuration in runtime, basing on PeriphID:
http://infocenter.arm.com/help/topic/com.arm.doc.ddi0172a/i1024149.html
Configuration == 0 (ID ==
0x00041180) -> FIFO length = 16 * 4 Configuration == 1 (ID ==0x01041180) -> FIFO length = 128 * 4
That's useful to know. The PL180 code is also used for U8500, I don't know if that implements the peripheral ID register; though I guess any probing could be limited to vexpress anyway.
However, I think that if smaller and simpler code will work on all hardware then that is preferable.
Signature · 1 line
Tixy
PATCH 1/1 MMC: PL180: Fix infinite loop with VExpress extended fifo implementation
Quoted 3 lines
That's useful to know. The PL180 code is also used for U8500, I don't know if that implements the peripheral ID register; though I guess any probing could be limited to vexpress anyway.
STE have the same "problems" with FIFO size, see drivers/mmc/host/mmci.c in kernel sources:
static struct variant_data variant_arm = {
.fifosize = 16 * 4,
.fifohalfsize = 8 * 4,
.datalength_bits = 16, };
static struct variant_data variant_arm_extended_fifo = {
.fifosize = 128 * 4,
.fifohalfsize = 64 * 4,
.datalength_bits = 16,};
static struct variant_data variant_u300 = {
.fifosize = 16 * 4,
.fifohalfsize = 8 * 4,
.clkreg_enable = MCI_ST_U300_HWFCEN,
.datalength_bits = 16,
.sdio = true,};
static struct variant_data variant_ux500 = {
.fifosize = 30 * 4,
.fifohalfsize = 8 * 4,
.clkreg = MCI_CLK_ENABLE,
.clkreg_enable = MCI_ST_UX500_HWFCEN,
.datalength_bits = 24,
.sdio = true,
.st_clkdiv = true,};
static struct variant_data variant_ux500v2 = {
.fifosize = 30 * 4,
.fifohalfsize = 8 * 4,
.clkreg = MCI_CLK_ENABLE,
.clkreg_enable = MCI_ST_UX500_HWFCEN,
.datalength_bits = 24,
.sdio = true,
.st_clkdiv = true,
.blksz_datactrl16 = true,};
Cheers!
Pawe?
PATCH 1/1 MMC: PL180: Fix infinite loop with VExpress extended fifo implementation
Quoted 6 lines · Pawel Moll
Quoted 3 lines
That's useful to know. The PL180 code is also used for U8500, I don't know if that implements the peripheral ID register; though I guess any probing could be limited to vexpress anyway.
STE have the same "problems" with FIFO size, see
drivers/mmc/host/mmci.cin kernel sources:
Yes, and my proposed fix for U-Boot will work with them all because it removes a dependency on the fifo size.
Signature · 1 line
Tixy
PATCH 1/1 MMC: PL180: Fix infinite loop with VExpress extended fifo implementation
In reply to Jon Medhurst (Tixy)Quoted 16 lines · Jon Medhurst (Tixy)
From: Jon Medhurst <[email protected]>
The new IO FPGA implementation for Versatile Express contains an MMCI (PL180) cell with the FIFO extended to 128 words. This causes the
read_bytes()function to go into an infinite loop; as it will wait for for the half-full signal (SDI_STA_RXFIFOBR) if there are more than 8 words remaining (SDI_FIFO_BURST_SIZE), but it won't receive this signal once there are fewer than 64 words left to transfer.One possible fix is to add some build time configuration to change
SDI_FIFO_BURST_SIZEfor the new implementation. However, the problematic code only seems to exist as a small performance optimisation, so the solution implemented by this patch is to simply remove it. The error checking following the loop is also removed as this will be handled by code further down the function.
Quoted 2 lines
Cc Andy Fleming <[email protected]>Signed-off-by Jon Medhurst <[email protected]>
Quoted 54 lines
---
If it is desirable to keep the burst read optimisation, then an alternative solution would be to keep the loop and add an if clause to do a single read if the fifo doesn't have enough for a burst.
--- drivers/mmc/arm_pl180_mmci.c | 26 -------------------------- 1 files changed, 0 insertions(+), 26 deletions(-)drivers/mmc/arm_pl180_mmci.c +0
-26@@ -111,7 +111,6 @@ static int do_command(struct mmc *dev, struct mmc_cmd *cmd)static int read_bytes (struct mmc *dev,u32 *dest,u32 blkcount,u32 blksize) {u32 *tempbuff = dest; -int i;u64 xfercount = blkcount * blksize;struct mmc_host *host = dev->priv;u32 status, status_err;@@ -121,31 +120,6 @@ static int read_bytes(struct mmc *dev, u32 *dest, u32 blkcount, u32 blksize) status =readl (&host->base->status); status_err = status & (SDI_STA_DCRCFAIL |SDI_STA_DTIMEOUT |SDI_STA_RXOVERR ); -while (!status_err && - (xfercount >=SDI_FIFO_BURST_SIZE *sizeof (u32))) { -if (status &SDI_STA_RXFIFOBR ) { -for (i =0 ; i <SDI_FIFO_BURST_SIZE ; i++) - *(tempbuff + i) =readl (&host->base->fifo); - tempbuff +=SDI_FIFO_BURST_SIZE ; - xfercount -=SDI_FIFO_BURST_SIZE *sizeof (u32); - } - status =readl (&host->base->status); - status_err = status & - (SDI_STA_DCRCFAIL |SDI_STA_DTIMEOUT |SDI_STA_RXOVERR ); - } - -if (status &SDI_STA_DTIMEOUT ) { -printf ("Read data timed out, xfercount: %llu, status: 0x%08X\n" , - xfercount, status); -return -ETIMEDOUT ; - }else if (status &SDI_STA_DCRCFAIL ) { -printf ("Read data blk CRC error: 0x%x\n" , status); -return -EILSEQ ; - }else if (status &SDI_STA_RXOVERR ) { -printf ("Read data RX overflow error\n" ); -return -EIO ; - } -while ((!status_err) && (xfercount >=sizeof (u32))) {if (status &SDI_STA_RXDAVL ) { *(tempbuff) =readl (&host->base->fifo);
Signature · 5 lines
Linaro.org ? Open source software for ARM SoCs Follow Linaro: http://www.facebook.com/pages/Linaro/155974581091106 http://twitter.com/#!/linaroorg http://www.linaro.org/linaro-blog/
PATCH 1/1 MMC: PL180: Fix infinite loop with VExpress extended fifo implementation
In reply to Jon Medhurst (Tixy)Quoted 10 lines · Jon Medhurst (Tixy)
Cc Andy Fleming <[email protected]>Signed-off-by Jon Medhurst <[email protected]>?drivers/mmc/arm_pl180_mmci.c | ? 26 -------------------------- ?1 files changed, 0 insertions(+), 26 deletions(-)
drivers/mmc/arm_pl180_mmci.c +0
-0
drivers/mmc/arm_pl180_mmci.c static int do_command(struct mmc *dev, struct mmc_cmd *cmd) · line 116
Quoted 7 lines
drivers/mmc/arm_pl180_mmci.c +0
-1@@ -111,7 +111,6 @@ static int do_command(struct mmc *dev, struct mmc_cmd *cmd) ?static int read_bytes(struct mmc *dev, u32 *dest, u32 blkcount, u32 blksize) ?{ ? ? ? ?u32 *tempbuff = dest; - ? ? ? int i; ? ? ? ?u64 xfercount = blkcount * blksize; ? ? ? ?struct mmc_host *host = dev->priv; ? ? ? ?u32 status, status_err;
Please fix your patch-sending software. This patch has converted all of the tabs to spaces, and won't apply.
Andy
PATCH v2 1/1 MMC: PL180: Fix infinite loop with VExpress extended fifo implementation
The new IO FPGA implementation for Versatile Express contains an MMCI (PL180) cell with the FIFO extended to 128 words. This causes the read_bytes() function to go into an infinite loop; as it will wait for for the half-full signal (SDI_STA_RXFIFOBR) if there are more than 8 words remaining (SDI_FIFO_BURST_SIZE), but it won't receive this signal once there are fewer than 64 words left to transfer.
One possible fix is to add some build time configuration to change SDI_FIFO_BURST_SIZE for the new implementation. However, the problematic code only seems to exist as a small performance optimisation, so the solution implemented by this patch is to simply remove it. The error checking following the loop is also removed as this will be handled by code further down the function.
---
Changes for version 2
- Fix broken whitespace in patch
--- drivers/mmc/arm_pl180_mmci.c | 26 -------------------------- 1 files changed, 0 insertions(+), 26 deletions(-)
drivers/mmc/arm_pl180_mmci.c +0 -26
@@ -111,7 +111,6 @@ static int do_command(struct mmc *dev, struct mmc_cmd *cmd)static int read_bytes (struct mmc *dev,u32 *dest,u32 blkcount,u32 blksize) {u32 *tempbuff = dest; -int i;u64 xfercount = blkcount * blksize;struct mmc_host *host = dev->priv;u32 status, status_err;
@@ -121,31 +120,6 @@ static int read_bytes(struct mmc *dev, u32 *dest, u32 blkcount, u32 blksize) status =readl (&host->base->status); status_err = status & (SDI_STA_DCRCFAIL |SDI_STA_DTIMEOUT |SDI_STA_RXOVERR ); -while (!status_err && - (xfercount >=SDI_FIFO_BURST_SIZE *sizeof (u32))) { -if (status &SDI_STA_RXFIFOBR ) { -for (i =0 ; i <SDI_FIFO_BURST_SIZE ; i++) - *(tempbuff + i) =readl (&host->base->fifo); - tempbuff +=SDI_FIFO_BURST_SIZE ; - xfercount -=SDI_FIFO_BURST_SIZE *sizeof (u32); - } - status =readl (&host->base->status); - status_err = status & - (SDI_STA_DCRCFAIL |SDI_STA_DTIMEOUT |SDI_STA_RXOVERR ); - } - -if (status &SDI_STA_DTIMEOUT ) { -printf ("Read data timed out, xfercount: %llu, status: 0x%08X\n" , - xfercount, status); -return -ETIMEDOUT ; - }else if (status &SDI_STA_DCRCFAIL ) { -printf ("Read data blk CRC error: 0x%x\n" , status); -return -EILSEQ ; - }else if (status &SDI_STA_RXOVERR ) { -printf ("Read data RX overflow error\n" ); -return -EIO ; - } -while ((!status_err) && (xfercount >=sizeof (u32))) {if (status &SDI_STA_RXDAVL ) { *(tempbuff) =readl (&host->base->fifo);
Signature · 1 line
1.7.4.1
Andy Fleming
AppliedPATCH v2 1/1 MMC: PL180: Fix infinite loop with VExpress extended fifo implementation
Quoted 14 lines · Jon Medhurst (Tixy)
The new IO FPGA implementation for Versatile Express contains an MMCI (PL180) cell with the FIFO extended to 128 words. This causes the
read_bytes()function to go into an infinite loop; as it will wait for for the half-full signal (SDI_STA_RXFIFOBR) if there are more than 8 words remaining (SDI_FIFO_BURST_SIZE), but it won't receive this signal once there are fewer than 64 words left to transfer.One possible fix is to add some build time configuration to change
SDI_FIFO_BURST_SIZEfor the new implementation. However, the problematic code only seems to exist as a small performance optimisation, so the solution implemented by this patch is to simply remove it. The error checking following the loop is also removed as this will be handled by code further down the function.
Quoted 2 lines
Cc Andy Fleming <[email protected]>Signed-off-by Jon Medhurst <[email protected]>
Applied, thx