* [RFC PATCH] mmc: core: Update ext_csd if touched by ioctl
@ 2013-09-11 5:26 Dirk Behme
0 siblings, 0 replies; only message in thread
From: Dirk Behme @ 2013-09-11 5:26 UTC (permalink / raw)
To: linux-mmc; +Cc: Chris Ball, Dirk Behme
In case an ioctl changes an EXT_CSD register, update the internal ext_csd
data structure, too. Else the driver's internal ext_csd data structure and
the EXT_CSD register content doesn't match any more. In this case additional
ioctls changing the ext_csd would revert the initial one due to the old data
in the driver's internal ext_csd data.
E.g. using the mmc utils utility to enable the bootpart
mmc bootpart enable 1 0 /dev/mmcblk1
correctly writes to the EXT_CSD structure of the device, but
doesn't update
card->ext_csd.part_config
Issuing additional MMC_SWITCH commands afterwards use the then (wrong)
card->ext_csd.part_config. Resulting in an undo of the initial mmc bootpart
enable.
Fix this by updating the ext_csd in case of an EXT_CSD update ioctl.
Signed-off-by: Dirk Behme <dirk.behme@gmail.com>
---
Notes:
This fixes the issue discussed in
http://marc.info/?l=linux-mmc&m=137820629730918
This patch is marked as RFC due to two reasons:
* exporting mmc_update_ext_csd() in core/mmc.c and calling it directly from
card/block.c
* It seems it's not allowed to call mmc_part_add() in mmc_read_ext_csd()
several times. So this is disabled by passing an 'update' variable to
mmc_read_ext_csd() disabling the mmc_part_add() in case we just want to
update the ext_csd variables.
How can this be done better/cleaner?
drivers/mmc/card/block.c | 14 ++++++++++++++
drivers/mmc/core/mmc.c | 26 ++++++++++++++++++++++----
2 files changed, 36 insertions(+), 4 deletions(-)
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 1a3163f..0a4bd62 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -132,6 +132,8 @@ enum {
module_param(perdev_minors, int, 0444);
MODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device");
+int mmc_update_ext_csd(struct mmc_card *card);
+
static inline int mmc_blk_part_switch(struct mmc_card *card,
struct mmc_blk_data *md);
static int get_card_status(struct mmc_card *card, u32 *status, int retries);
@@ -600,6 +602,18 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
__func__, status, err);
}
+ if ((cmd.opcode == MMC_SWITCH) && ((cmd.arg >> 24) & 0x3)) {
+ /*
+ * In case the IOCTL has modified the EXT_CSD,
+ * update it, i.e. re-read the EXT_CSD.
+ */
+ err = mmc_update_ext_csd(card);
+ if (err)
+ dev_err(mmc_dev(card->host),
+ "%s: EXT_CSD update failed, error %d\n",
+ __func__, err);
+ }
+
cmd_rel_host:
mmc_put_card(card);
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 6d02012..5db9d8c 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -269,7 +269,7 @@ static void mmc_select_card_type(struct mmc_card *card)
/*
* Decode extended CSD.
*/
-static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
+static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd, int update)
{
int err = 0, idx;
unsigned int part_size;
@@ -348,7 +348,8 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
* There are two boot regions of equal size, defined in
* multiples of 128K.
*/
- if (ext_csd[EXT_CSD_BOOT_MULT] && mmc_boot_partition_access(card->host)) {
+ if (ext_csd[EXT_CSD_BOOT_MULT] && mmc_boot_partition_access(card->host) &&
+ !update) {
for (idx = 0; idx < MMC_NUM_BOOT_PARTITION; idx++) {
part_size = ext_csd[EXT_CSD_BOOT_MULT] << 17;
mmc_part_add(card, part_size,
@@ -519,7 +520,8 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
* RPMB regions are defined in multiples of 128K.
*/
card->ext_csd.raw_rpmb_size_mult = ext_csd[EXT_CSD_RPMB_MULT];
- if (ext_csd[EXT_CSD_RPMB_MULT] && mmc_host_cmd23(card->host)) {
+ if (ext_csd[EXT_CSD_RPMB_MULT] && mmc_host_cmd23(card->host) &&
+ !update) {
mmc_part_add(card, ext_csd[EXT_CSD_RPMB_MULT] << 17,
EXT_CSD_PART_CONFIG_ACC_RPMB,
"rpmb", 0, false,
@@ -983,7 +985,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
err = mmc_get_ext_csd(card, &ext_csd);
if (err)
goto free_card;
- err = mmc_read_ext_csd(card, ext_csd);
+ err = mmc_read_ext_csd(card, ext_csd, 0);
if (err)
goto free_card;
@@ -1634,6 +1636,22 @@ static void mmc_attach_bus_ops(struct mmc_host *host)
mmc_attach_bus(host, bus_ops);
}
+int mmc_update_ext_csd(struct mmc_card *card)
+{
+ u8 *new_ext_csd;
+ int err;
+
+ err = mmc_get_ext_csd(card, &new_ext_csd);
+ if (err || new_ext_csd == NULL)
+ goto out;
+
+ err = mmc_read_ext_csd(card, new_ext_csd, 1);
+
+out:
+ mmc_free_ext_csd(new_ext_csd);
+ return err;
+}
+
/*
* Starting point for MMC card init.
*/
--
1.7.10.4
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2013-09-11 5:26 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-09-11 5:26 [RFC PATCH] mmc: core: Update ext_csd if touched by ioctl Dirk Behme
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.