diff mbox

[U-Boot] mmc: dcache: Replace ext_csd buffer with cache aligned one

Message ID 1313137527-8744-1-git-send-email-l.majewski@samsung.com
State Superseded, archived
Delegated to: Andy Fleming
Headers show

Commit Message

Łukasz Majewski Aug. 12, 2011, 8:25 a.m. UTC
This commit replaces the ext_csd buffer allocated as an automatic
variable with one cache aligned. The ext_csd might be allocated with
alignment not equal to the L1 D cache alignment.

The memalign from common/dlmalloc.c is allowing for buffer allocation
with proper cache alignment.

The common/dlmalloc.c [c|m]alloc alignment is hardwired to 8 bytes,
so out of the box functions cannot be safely used with L1 D cache.

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
CC: Andy Fleming <afleming@gmail.com>
CC: Albert ARIBAUD <albert.u.boot@aribaud.net>
---
 drivers/mmc/mmc.c |   55 +++++++++++++++++++++++++++++++++-------------------
 1 files changed, 35 insertions(+), 20 deletions(-)

Comments

Albert ARIBAUD Aug. 12, 2011, 9:07 a.m. UTC | #1
Hi Lukasz,

On 12/08/2011 10:25, Lukasz Majewski wrote:

> +	char *ext_csd = memalign(get_dcache_line_size(), mmc->read_bl_len);

Since this is the first effort for aligning buffers on the caller side, 
I'd like to make sure the method can be, and is, standardized across all 
changes.

So before standardizing on memalign() for dynamically allocating aligned 
buffers, I want to to be sure that the use of this function is portable.

I know it is in GNU LIBC; I also know it is not (yet...) in U-Boot's own 
C library. What about the most common toolchains used on U-Boot?

Amicalement,
Łukasz Majewski Aug. 12, 2011, 9:35 a.m. UTC | #2
Hi Albert,

On Fri, 12 Aug 2011 11:07:57 +0200
Albert ARIBAUD <albert.u.boot@aribaud.net> wrote:

> I know it is in GNU LIBC; I also know it is not (yet...) in U-Boot's
> own C library. What about the most common toolchains used on U-Boot?

The memalign is already defined in the u-boot tree (common/dlmalloc.c).

The dlmalloc.o is also built during compilation and it is linked to the
final u-boot binary.

I'm using the CodeSourgery's ARM toolchain (gcc version 4.4.1 (Sourcery
G++ Lite 2009q3-68)). 
I can test it with (gcc version 4.3.2 (Sourcery G++ Lite 2008q3-72)) as
well.

Moreover I can try to install OSELAS.Toolchain (PTXdist ones) and test
this as well with those toolchains. There are several one available for
armv5/armv6/armv7.

Initially I was planning to use calloc/malloc from ./common/dlmalloc.c
but it is clearly stated, that it is using 8 bytes alignment (which is
hardwired in this implementation). 

I will keep you informed about the tests results.
Albert ARIBAUD Aug. 12, 2011, 9:50 a.m. UTC | #3
Hi Lukasz,

On 12/08/2011 11:35, Lukasz Majewski wrote:
> Hi Albert,
>
> On Fri, 12 Aug 2011 11:07:57 +0200
> Albert ARIBAUD<albert.u.boot@aribaud.net>  wrote:
>
>> I know it is in GNU LIBC; I also know it is not (yet...) in U-Boot's
>> own C library. What about the most common toolchains used on U-Boot?
>
> The memalign is already defined in the u-boot tree (common/dlmalloc.c).

Apologies: seems like I missed it.

> The dlmalloc.o is also built during compilation and it is linked to the
> final u-boot binary.
>
> I'm using the CodeSourgery's ARM toolchain (gcc version 4.4.1 (Sourcery
> G++ Lite 2009q3-68)).
> I can test it with (gcc version 4.3.2 (Sourcery G++ Lite 2008q3-72)) as
> well.
>
> Moreover I can try to install OSELAS.Toolchain (PTXdist ones) and test
> this as well with those toolchains. There are several one available for
> armv5/armv6/armv7.
>
> Initially I was planning to use calloc/malloc from ./common/dlmalloc.c
> but it is clearly stated, that it is using 8 bytes alignment (which is
> hardwired in this implementation).
>
> I will keep you informed about the tests results.

Thanks a lot! If no toolchain gives issues, then I guess the use of 
memalign() for dynamic buffers can be considered the way to go.

Amicalement,
Andy Fleming Aug. 17, 2011, 2:43 a.m. UTC | #4
On Fri, Aug 12, 2011 at 3:25 AM, Lukasz Majewski <l.majewski@samsung.com> wrote:
> This commit replaces the ext_csd buffer allocated as an automatic
> variable with one cache aligned. The ext_csd might be allocated with
> alignment not equal to the L1 D cache alignment.
>
> The memalign from common/dlmalloc.c is allowing for buffer allocation
> with proper cache alignment.
>
> The common/dlmalloc.c [c|m]alloc alignment is hardwired to 8 bytes,
> so out of the box functions cannot be safely used with L1 D cache.
>
> Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> CC: Andy Fleming <afleming@gmail.com>
> CC: Albert ARIBAUD <albert.u.boot@aribaud.net>
> ---
>  drivers/mmc/mmc.c |   55 +++++++++++++++++++++++++++++++++-------------------
>  1 files changed, 35 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
> index 7e703c0..422a0f9 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -660,7 +664,11 @@ int mmc_change_freq(struct mmc *mmc)
>        else
>                mmc->card_caps |= MMC_MODE_HS;
>
> -       return 0;
> + exit:
> +       err = 0;


Just initialize err to 0 at the beginning of the function, and relabel
"error" as "out"


> + error:
> +       free(ext_csd);
> +       return err;
>  }
>
>  int mmc_switch_part(int dev_num, unsigned int part_num)

> @@ -1122,6 +1134,9 @@ int mmc_startup(struct mmc *mmc)
>        init_part(&mmc->block_dev);
>
>        return 0;
> + error:
> +       free(ext_csd);

Need to remove that "return 0" so that ext_csd gets freed if things go
correctly, too. I would also relabel this one as "out", so as to not
confuse the casual reader.

Andy
diff mbox

Patch

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 7e703c0..422a0f9 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -29,6 +29,7 @@ 
 #include <mmc.h>
 #include <part.h>
 #include <malloc.h>
+#include <errno.h>
 #include <linux/list.h>
 #include <div64.h>
 
@@ -617,42 +618,45 @@  int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value)
 
 int mmc_change_freq(struct mmc *mmc)
 {
-	char ext_csd[512];
 	char cardtype;
 	int err;
+	char *ext_csd = memalign(get_dcache_line_size(), mmc->read_bl_len);
+
+	if (!ext_csd)
+		return -ENOMEM;
 
 	mmc->card_caps = 0;
 
 	if (mmc_host_is_spi(mmc))
-		return 0;
+		goto exit;
 
 	/* Only version 4 supports high-speed */
 	if (mmc->version < MMC_VERSION_4)
-		return 0;
+		goto exit;
 
 	mmc->card_caps |= MMC_MODE_4BIT;
 
 	err = mmc_send_ext_csd(mmc, ext_csd);
 
 	if (err)
-		return err;
+		goto error;
 
 	cardtype = ext_csd[196] & 0xf;
 
 	err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, 1);
 
 	if (err)
-		return err;
+		goto error;
 
 	/* Now check to see that it worked */
 	err = mmc_send_ext_csd(mmc, ext_csd);
 
 	if (err)
-		return err;
+		goto error;
 
 	/* No high-speed support */
 	if (!ext_csd[185])
-		return 0;
+		goto exit;
 
 	/* High Speed is set, there are two types: 52MHz and 26MHz */
 	if (cardtype & MMC_HS_52MHZ)
@@ -660,7 +664,11 @@  int mmc_change_freq(struct mmc *mmc)
 	else
 		mmc->card_caps |= MMC_MODE_HS;
 
-	return 0;
+ exit:
+	err = 0;
+ error:
+	free(ext_csd);
+	return err;
 }
 
 int mmc_switch_part(int dev_num, unsigned int part_num)
@@ -855,11 +863,15 @@  void mmc_set_bus_width(struct mmc *mmc, uint width)
 
 int mmc_startup(struct mmc *mmc)
 {
-	int err;
+	int err, i;
 	uint mult, freq;
 	u64 cmult, csize, capacity;
 	struct mmc_cmd cmd;
-	char ext_csd[512];
+	char *ext_csd = memalign(get_dcache_line_size(), mmc->read_bl_len);
+
+	if (!ext_csd)
+		return -ENOMEM;
+
 	int timeout = 1000;
 
 #ifdef CONFIG_MMC_SPI_CRC_ON
@@ -871,7 +883,7 @@  int mmc_startup(struct mmc *mmc)
 		err = mmc_send_cmd(mmc, &cmd, NULL);
 
 		if (err)
-			return err;
+			goto error;
 	}
 #endif
 
@@ -885,7 +897,7 @@  int mmc_startup(struct mmc *mmc)
 	err = mmc_send_cmd(mmc, &cmd, NULL);
 
 	if (err)
-		return err;
+		goto error;
 
 	memcpy(mmc->cid, cmd.response, 16);
 
@@ -903,7 +915,7 @@  int mmc_startup(struct mmc *mmc)
 		err = mmc_send_cmd(mmc, &cmd, NULL);
 
 		if (err)
-			return err;
+			goto error;
 
 		if (IS_SD(mmc))
 			mmc->rca = (cmd.response[0] >> 16) & 0xffff;
@@ -921,7 +933,7 @@  int mmc_startup(struct mmc *mmc)
 	mmc_send_status(mmc, timeout);
 
 	if (err)
-		return err;
+		goto error;
 
 	mmc->csd[0] = cmd.response[0];
 	mmc->csd[1] = cmd.response[1];
@@ -994,7 +1006,7 @@  int mmc_startup(struct mmc *mmc)
 		err = mmc_send_cmd(mmc, &cmd, NULL);
 
 		if (err)
-			return err;
+			goto error;
 	}
 
 	/*
@@ -1044,7 +1056,7 @@  int mmc_startup(struct mmc *mmc)
 		err = mmc_change_freq(mmc);
 
 	if (err)
-		return err;
+		goto error;
 
 	/* Restrict card's capabilities by what the host can do */
 	mmc->card_caps &= mmc->host_caps;
@@ -1058,7 +1070,7 @@  int mmc_startup(struct mmc *mmc)
 
 			err = mmc_send_cmd(mmc, &cmd, NULL);
 			if (err)
-				return err;
+				goto error;
 
 			cmd.cmdidx = SD_CMD_APP_SET_BUS_WIDTH;
 			cmd.resp_type = MMC_RSP_R1;
@@ -1066,7 +1078,7 @@  int mmc_startup(struct mmc *mmc)
 			cmd.flags = 0;
 			err = mmc_send_cmd(mmc, &cmd, NULL);
 			if (err)
-				return err;
+				goto error;
 
 			mmc_set_bus_width(mmc, 4);
 		}
@@ -1083,7 +1095,7 @@  int mmc_startup(struct mmc *mmc)
 					EXT_CSD_BUS_WIDTH_4);
 
 			if (err)
-				return err;
+				goto error;
 
 			mmc_set_bus_width(mmc, 4);
 		} else if (mmc->card_caps & MMC_MODE_8BIT) {
@@ -1093,7 +1105,7 @@  int mmc_startup(struct mmc *mmc)
 					EXT_CSD_BUS_WIDTH_8);
 
 			if (err)
-				return err;
+				goto error;
 
 			mmc_set_bus_width(mmc, 8);
 		}
@@ -1122,6 +1134,9 @@  int mmc_startup(struct mmc *mmc)
 	init_part(&mmc->block_dev);
 
 	return 0;
+ error:
+	free(ext_csd);
+	return err;
 }
 
 int mmc_send_if_cond(struct mmc *mmc)