This patch is support the sysfs for operation mode. There are two operation modes(open-ended/pre-defined). Now, operation mode is selected only one at the compile time. But using this patch, we can change the operation mode with node at runtime. * pre-defined mode echo 1 > /sys/class/mmc_host/mmc0/pre_defined_op * open-ended mode echo 0 > /sys/class/mmc_host/mmc0/pre_defined_op Signed-off-by: Jaehoon Chung <jh80.chung@xxxxxxxxxxx> Signed-off-by: Kyungmin Park <kyungmin.park@xxxxxxxxxxx> --- Changelog v2: - Add the check point in mmc_cmd23_store() (If host controller didn't support CMD23, need not to change the ops-mode.) drivers/mmc/card/block.c | 14 +++++++------- drivers/mmc/core/host.c | 41 +++++++++++++++++++++++++++++++++++++++++ include/linux/mmc/host.h | 5 ++++- 3 files changed, 52 insertions(+), 8 deletions(-) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 176b78e..3a190a2 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -1390,6 +1390,13 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) struct mmc_blk_data *md = mq->data; struct mmc_card *card = md->queue.card; + if (mmc_host_cmd23(card->host)) { + if (mmc_card_mmc(card) || + (mmc_card_sd(card) && + card->scr.cmds & SD_SCR_CMD23_SUPPORT)) + md->flags |= MMC_BLK_CMD23; + } + if (req && !mq->mqrq_prev->req) /* claim host only for the first request */ mmc_claim_host(card->host); @@ -1520,13 +1527,6 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card, blk_queue_logical_block_size(md->queue.queue, 512); set_capacity(md->disk, size); - if (mmc_host_cmd23(card->host)) { - if (mmc_card_mmc(card) || - (mmc_card_sd(card) && - card->scr.cmds & SD_SCR_CMD23_SUPPORT)) - md->flags |= MMC_BLK_CMD23; - } - if (mmc_card_mmc(card) && md->flags & MMC_BLK_CMD23 && ((card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN) || diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 30055f2..2660a0c 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -293,6 +293,43 @@ static inline void mmc_host_clk_sysfs_init(struct mmc_host *host) #endif +static ssize_t mmc_cmd23_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct mmc_host *host = cls_dev_to_mmc_host(dev); + return snprintf(buf, PAGE_SIZE, "%d\n", host->pre_defined_op); +} + +static ssize_t mmc_cmd23_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct mmc_host *host = cls_dev_to_mmc_host(dev); + unsigned long flags, value; + + if (!(host->caps & MMC_CAP_CMD23)) + return -EINVAL; + + if (kstrtoul(buf, 0, &value)) + return -EINVAL; + + spin_lock_irqsave(&host->lock, flags); + host->pre_defined_op = value; + spin_unlock_irqrestore(&host->lock, flags); + return count; +} + +static inline void mmc_host_cmd23_sysfs_init(struct mmc_host *host) +{ + host->pre_defined_attr.show = mmc_cmd23_show; + host->pre_defined_attr.store = mmc_cmd23_store; + sysfs_attr_init(&host->pre_defined_attr.attr); + host->pre_defined_attr.attr.name = "pre_defined_op"; + host->pre_defined_attr.attr.mode = S_IRUGO | S_IWUSR; + if (device_create_file(&host->class_dev, &host->pre_defined_attr)) + pr_err("%s: Failed to create pre_defined_op sysfs entry\n", + mmc_hostname(host)); +} + /** * mmc_alloc_host - initialise the per-host structure. * @extra: sizeof private data structure @@ -381,6 +418,10 @@ int mmc_add_host(struct mmc_host *host) #endif mmc_host_clk_sysfs_init(host); + if (host->caps & MMC_CAP_CMD23) + host->pre_defined_op = 1; + mmc_host_cmd23_sysfs_init(host); + mmc_start_host(host); register_pm_notifier(&host->pm_notify); diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index dd13e05..44fbf6c 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -258,6 +258,9 @@ struct mmc_host { #define MMC_CAP2_HS200 (MMC_CAP2_HS200_1_8V_SDR | \ MMC_CAP2_HS200_1_2V_SDR) + struct device_attribute pre_defined_attr; + bool pre_defined_op; /* CMD23 should be use or not */ + mmc_pm_flag_t pm_caps; /* supported pm features */ unsigned int power_notify_type; #define MMC_HOST_PW_NOTIFY_NONE 0 @@ -436,7 +439,7 @@ static inline int mmc_card_wake_sdio_irq(struct mmc_host *host) static inline int mmc_host_cmd23(struct mmc_host *host) { - return host->caps & MMC_CAP_CMD23; + return host->pre_defined_op; } static inline int mmc_boot_partition_access(struct mmc_host *host) -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html