Skip to contentSkip to conversation

mmc: Update "mmc->part_num" when performing a partition switch

PATCH New Fabio Estevam 3 participants 11 messages Jun 4, 2013 MMC, SD and SDIO

lore
Share & tools
lore
#0 lore raw

PATCH v2 1/1 mmc: Update "mmc->part_num" when performing a partition switch

When running the "save" command several times on a mx6qsabresd we see:

U-Boot > save
Saving Environment to MMC...
Writing to MMC(1)... done
U-Boot > save
Saving Environment to MMC...
MMC partition switch failed
U-Boot > save
Saving Environment to MMC...
Writing to MMC(1)... done
U-Boot > save
Saving Environment to MMC...
MMC partition switch failed
U-Boot > save
Saving Environment to MMC...
Writing to MMC(1)... done
U-Boot > save
Saving Environment to MMC...
MMC partition switch failed

Fix this by updating mmc->part_num inside mmc_switch_part() after a succesful mmc partition switch.

After this fix, we no longer see the error after the "save" command on a mx6qsabresd. Also tested on a mx53loco.

---
Changes since v1:
- Do the change inside the mmc core

 drivers/mmc/mmc.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)
drivers/mmc/mmc.c +7 -1
index 2590f1b..7f568ed 100644
@@ -680,14 +680,20 @@ static int mmc_change_freq(struct mmc *mmc)
 
 int mmc_switch_part(int dev_num, unsigned int part_num)
 {
+	int ret;
 	struct mmc *mmc = find_mmc_device(dev_num);
 
 	if (!mmc)
 		return -1;
 
-	return mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF,
+	ret = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF,
 			  (mmc->part_config & ~PART_ACCESS_MASK)
 			  | (part_num & PART_ACCESS_MASK));
+
+	if (!ret)
+		mmc->part_num = part_num;
+
+	return ret;
 }
 
 int mmc_getcd(struct mmc *mmc)
Signature · 1 line
1.8.1.2
#1 lore raw

PATCH v2 1/1 mmc: Update "mmc->part_num" when performing a partition switch

Quoted 21 lines · Fabio Estevam

When running the "save" command several times on a mx6qsabresd we see:

U-Boot > save
Saving Environment to MMC...
Writing to MMC(1)... done
U-Boot > save
Saving Environment to MMC...
MMC partition switch failed
U-Boot > save
Saving Environment to MMC...
Writing to MMC(1)... done
U-Boot > save
Saving Environment to MMC...
MMC partition switch failed
U-Boot > save
Saving Environment to MMC...
Writing to MMC(1)... done
U-Boot > save
Saving Environment to MMC...
MMC partition switch failed

Quoted 2 lines

Fix this by updating mmc->part_num inside mmc_switch_part() after a succesful mmc partition switch.

This surely has exactly the same issue as the previous version, where the update of part_num was done inside common/env_mmc.c?

#2 lore raw

PATCH v2 1/1 mmc: Update "mmc->part_num" when performing a partition switch

Quoted 2 lines · Stephen Warren

This surely has exactly the same issue as the previous version, where the update of part_num was done inside common/env_mmc.c?

My understading is that the mmc core should update mmc->part_num and I don't see such update, or am I missing something?

Thanks,

Fabio Estevam

#3 lore raw

PATCH v2 1/1 mmc: Update "mmc->part_num" when performing a partition switch

Quoted 7 lines · Fabio Estevam
Quoted 2 lines · Stephen Warren

This surely has exactly the same issue as the previous version, where the update of part_num was done inside common/env_mmc.c?

My understading is that the mmc core should update mmc->part_num and I don't see such update, or am I missing something?

That seems like a reasonable way for the code to work. However, you'd need to modify common/env_mmc.c:init_mmc_for_env() so that it saves off mmc->part_num before switching MMC partitions, so that fini_mmc_for_env() knows which partition to switch back to. Right now, it relies on the fact that mmc_switch_part() does not update mmc->part_num, and hence uses that value to save the previously selected partition ID.

Also, if you make this change, I think you can update common/cmd_mmc.c:do_mmcops(), since it will no longer need to update mmc->part_num after a successful switch.

#4 lore raw

PATCH v2 1/1 mmc: Update "mmc->part_num" when performing a partition switch

Hi Stephen,

Quoted 11 lines · Stephen Warren

That seems like a reasonable way for the code to work. However, you'd need to modify common/env_mmc.c:init_mmc_for_env() so that it saves off mmc->part_num before switching MMC partitions, so that fini_mmc_for_env() knows which partition to switch back to. Right now, it relies on the fact that mmc_switch_part() does not update mmc->part_num, and hence uses that value to save the previously selected partition ID.

Also, if you make this change, I think you can update common/cmd_mmc.c:do_mmcops(), since it will no longer need to update mmc->part_num after a successful switch.

I understood your second suggestion and did the changes below, but I am not sure on the first one regarding the change you proposed inside init_mmc_for_env().

Here is what I did so far:

common/cmd_mmc.c +0 -0
index 7d82469..20a2792 100644
@@ -243,8 +243,6 @@ static int do_mmcops(cmd_tbl_t *cmdtp, int flag,

int argc, char * const argv[])

if (part != mmc->part_num) {
ret = mmc_switch_part(dev, part);
- if (!ret)
- mmc->part_num = part;

printf("switch to partions #%d, %s\n",
part, (!ret) ? "OK" : "ERROR");

drivers/mmc/mmc.c +7 -1
index 0a2f535..e8d2ea6 100644
@@ -702,14 +702,20 @@ static int mmc_change_freq(struct mmc *mmc)
 
 int mmc_switch_part(int dev_num, unsigned int part_num)
 {
+	int ret;
 	struct mmc *mmc = find_mmc_device(dev_num);
 
 	if (!mmc)
 		return -1;
 
-	return mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF,
+	ret = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF,
 			  (mmc->part_config & ~PART_ACCESS_MASK)
 			  | (part_num & PART_ACCESS_MASK));
+
+	if (!ret)
+		mmc->part_num = part_num;
+
+	return ret;
 }
 
 int mmc_getcd(struct mmc *mmc)
Signature · 4 lines
1.8.1.2

Could you please explain the change you proposed for saving
mmc->part_num inside init_mmc_for_env() ?
#5 lore raw

PATCH v2 1/1 mmc: Update "mmc->part_num" when performing a partition switch

Quoted 12 lines · Fabio Estevam

Hi Stephen,

Quoted 8 lines · Stephen Warren

That seems like a reasonable way for the code to work. However, you'd need to modify common/env_mmc.c:init_mmc_for_env() so that it saves off mmc->part_num before switching MMC partitions, so that fini_mmc_for_env() knows which partition to switch back to. Right now, it relies on the fact that mmc_switch_part() does not update mmc->part_num, and hence uses that value to save the previously selected partition ID.

Quoted 7 lines
Quoted 3 lines

Also, if you make this change, I think you can update common/cmd_mmc.c:do_mmcops(), since it will no longer need to update mmc->part_num after a successful switch.

I understood your second suggestion and did the changes below, but I am not sure on the first one regarding the change you proposed inside init_mmc_for_env().

In env_mmc.c, you'll want something like:

+#ifdef CONFIG_SYS_MMC_ENV_PART
+static char orig_part_num;
+#ifdef CONFIG_SYS_MMC_ENV_PART

static int init_mmc_for_env(struct mmc *mmc)
...
#ifdef CONFIG_SYS_MMC_ENV_PART
+ orig_part_num = mmc->part_num;
if (CONFIG_SYS_MMC_ENV_PART != mmc->part_num) {
if (mmc_switch_part(CONFIG_SYS_MMC_ENV_DEV,
CONFIG_SYS_MMC_ENV_PART)) {
puts("MMC partition switch failed\n"); return -1;
}
}
#endif
...
static void fini_mmc_for_env(struct mmc *mmc)
{
#ifdef CONFIG_SYS_MMC_ENV_PART
- if (CONFIG_SYS_MMC_ENV_PART != mmc->part_num)
+ if (mmc->part_num != orig_part_num)
mmc_switch_part(CONFIG_SYS_MMC_ENV_DEV,
- mmc->part_num);
+ orig_part_num);
#endif
}

#6 lore raw

PATCH v2 1/1 mmc: Update "mmc->part_num" when performing a partition switch

Quoted 1 line · Stephen Warren

In env_mmc.c, you'll want something like:

Thanks for the patch, but when I add these changes on top of my patch it results in the original error:

U-Boot > save
Saving Environment to MMC...
Writing to MMC(1)... done
U-Boot > save
Saving Environment to MMC...
MMC partition switch failed
U-Boot >

#7 lore raw

PATCH v2 1/1 mmc: Update "mmc->part_num" when performing a partition switch

Quoted 6 lines · Fabio Estevam
Quoted 1 line · Stephen Warren

In env_mmc.c, you'll want something like:

Thanks for the patch, but when I add these changes on top of my patch it results in the original error:

Of course; with that patch applied, there is no effective difference in the code - you've just cleaned it up to have the MMC core manage mmc->part_num, rather than requiring all callers to update it themselves.

Quoted 7 lines

U-Boot > save
Saving Environment to MMC...
Writing to MMC(1)... done
U-Boot > save
Saving Environment to MMC...
MMC partition switch failed
U-Boot >

I have no idea why that happens. You'll simply have to debug the code. Do you have CONFIG_SYS_MMC_ENV_PART set? I wasn't aware anyone else used it, besides Tegra.

#8 lore raw

PATCH v2 1/1 mmc: Update "mmc->part_num" when performing a partition switch

Quoted 2 lines · Stephen Warren

Do you have CONFIG_SYS_MMC_ENV_PART set? I wasn't aware anyone else used it, besides Tegra.

Yes, this is the issue. CONFIG_SYS_MMC_ENV_PART is used incorrectly on this board.

Will update its config file.

#9 lore raw

PATCH v2 1/1 mmc: Update "mmc->part_num" when performing a partition switch

In reply to Stephen Warren

Review

Quoted 8 lines · Stephen Warren

static void fini_mmc_for_env(struct mmc *mmc)
{
#ifdef CONFIG_SYS_MMC_ENV_PART

(quoted diff) +2 -2
-       if (CONFIG_SYS_MMC_ENV_PART != mmc->part_num)
+       if (mmc->part_num != orig_part_num)
                mmc_switch_part(CONFIG_SYS_MMC_ENV_DEV,
-                               mmc->part_num);
+                               orig_part_num);

If I keep the original 'mmc->part_num' here, then it works.

#10 lore raw

PATCH v2 1/1 mmc: Update "mmc->part_num" when performing a partition switch

Quoted 11 lines · Fabio Estevam

Review

Quoted 8 lines · Stephen Warren

static void fini_mmc_for_env(struct mmc *mmc)
{
#ifdef CONFIG_SYS_MMC_ENV_PART

(quoted diff) +2 -2
-       if (CONFIG_SYS_MMC_ENV_PART != mmc->part_num)
+       if (mmc->part_num != orig_part_num)
                mmc_switch_part(CONFIG_SYS_MMC_ENV_DEV,
-                               mmc->part_num);
+                               orig_part_num);
Quoted 1 line

If I keep the original 'mmc->part_num' here, then it works.

It doesn't "work", it just hides the problem. By passing mmc->part_num here, you're passing the partition that's already/currently selected rather than restoring the original value. Selecting it again is a no-op; IIRC the MMC core explicitly checks for this condition and immediately returns without touching the HW.