Linux MultiMedia Card development
 help / color / mirror / Atom feed
From: Adrian Hunter <adrian.hunter@intel.com>
To: Avri Altman <avri.altman@wdc.com>,
	Ulf Hansson <ulf.hansson@linaro.org>,
	linux-mmc@vger.kernel.org
Cc: Daniil Lunev <dlunev@google.com>,
	Asutosh Das <quic_asutoshd@quicinc.com>
Subject: Re: [PATCH] mmc: core: Use mrq.sbc in close-ended ffu
Date: Mon, 6 Nov 2023 16:53:26 +0200	[thread overview]
Message-ID: <557eb489-3e1d-4cbd-b62d-d3046870a4cc@intel.com> (raw)
In-Reply-To: <20231030090906.1897035-1-avri.altman@wdc.com>

On 30/10/23 11:09, Avri Altman wrote:
> Field Firmware Update (ffu) may use close-ended or open ended sequence.
> Each such sequence is comprised of a write commands enclosed between 2
> switch commands - to and from ffu mode. So for the close-ended case, it
> will be: cmd6->cmd23-cmd25-cmd6.
> 
> Some host controllers however, get confused when multi-block rw is sent
> without sbc, and may generate auto-cmd12 which breaks the ffu sequence.
> I encountered  this issue while testing fwupd (github.com/fwupd/fwupd)
> on HP Chromebook x2, a qualcomm based QC-7c, code name - strongbad.
> 
> Instead of a quirk, or hooking the request function of the msm ops,
> it would be better to fix the ioctl handling and make it use mrq.sbc
> instead of issuing SET_BLOCK_COUNT separately.
> 
> Signed-off-by: Avri Altman <avri.altman@wdc.com>
> ---
>  drivers/mmc/core/block.c | 41 ++++++++++++++++++++++++++++++++++++++--
>  include/linux/mmc/mmc.h  |  1 +
>  2 files changed, 40 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
> index 3a8f27c3e310..6d94617ef206 100644
> --- a/drivers/mmc/core/block.c
> +++ b/drivers/mmc/core/block.c
> @@ -400,6 +400,10 @@ struct mmc_blk_ioc_data {
>  	struct mmc_ioc_cmd ic;
>  	unsigned char *buf;
>  	u64 buf_bytes;
> +	unsigned int flags;
> +#define MMC_BLK_IOC_DROP	BIT(0)	/* drop this mrq */
> +#define MMC_BLK_IOC_SBC	BIT(1)	/* use mrq.sbc */
> +
>  	struct mmc_rpmb_data *rpmb;
>  };
>  
> @@ -479,6 +483,9 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
>  	if (!card || !md || !idata)
>  		return -EINVAL;
>  
> +	if (idata->flags & MMC_BLK_IOC_DROP)
> +		return 0;
> +
>  	/*
>  	 * The RPMB accesses comes in from the character device, so we
>  	 * need to target these explicitly. Else we just target the
> @@ -532,14 +539,19 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
>  			return err;
>  	}
>  
> -	if (idata->rpmb) {
> +	if (idata->rpmb || (idata->flags & MMC_BLK_IOC_SBC)) {
> +		u32 sbc_arg = data.blocks;
> +
>  		sbc.opcode = MMC_SET_BLOCK_COUNT;
>  		/*
>  		 * We don't do any blockcount validation because the max size
>  		 * may be increased by a future standard. We just copy the
>  		 * 'Reliable Write' bit here.
>  		 */
> -		sbc.arg = data.blocks | (idata->ic.write_flag & BIT(31));
> +		if (idata->rpmb)
> +			sbc_arg |= (idata->ic.write_flag & BIT(31));

What about supporting more generic use-cases with other information
in the arg of CMD23 idata, such as reliable write etc?  Perhaps
link the other idata and populate sbc opcode and arg from that.

> +
> +		sbc.arg = sbc_arg;
>  		sbc.flags = MMC_RSP_R1 | MMC_CMD_AC;
>  		mrq.sbc = &sbc;

Also could copy the sbc response back to the "CMD23" idata
after mmc_wait_for_req().

>  	}
> @@ -1032,6 +1044,28 @@ static inline void mmc_blk_reset_success(struct mmc_blk_data *md, int type)
>  	md->reset_done &= ~type;
>  }
>  
> +/* close-ended ffu */
> +static void mmc_blk_check_ce_ffu(struct mmc_queue_req *mq_rq)
> +{
> +	struct mmc_blk_ioc_data **idata = mq_rq->drv_op_data;
> +
> +	if (mq_rq->ioc_count != 4)
> +		return;
> +
> +	if (idata[0]->ic.opcode != MMC_SWITCH)
> +		return;
> +
> +	if (MMC_EXTRACT_INDEX_FROM_ARG(idata[0]->ic.arg) !=
> +			EXT_CSD_MODE_CONFIG)
> +		return;
> +
> +	if (idata[1]->ic.opcode == MMC_SET_BLOCK_COUNT &&
> +	    idata[2]->ic.opcode == MMC_WRITE_MULTIPLE_BLOCK) {
> +		idata[1]->flags |= MMC_BLK_IOC_DROP;
> +		idata[2]->flags |= MMC_BLK_IOC_SBC;
> +	}

Could this be more generic e.g. simply

	for (i = 1; i < mq_rq->ioc_count; i++)
		if (idata[i - 1]->ic.opcode == MMC_SET_BLOCK_COUNT &&
		    mmc_op_multi(idata[i + 1]->ic.opcode)) {
			idata[i - 1]->flags |= MMC_BLK_IOC_DROP;
			idata[i]->flags |= MMC_BLK_IOC_SBC;
		}

with no need to check for 4 cmds, MMC_SWITCH or EXT_CSD_MODE_CONFIG

> +}
> +
>  /*
>   * The non-block commands come back from the block layer after it queued it and
>   * processed it with all other requests and then they get issued in this
> @@ -1059,6 +1093,9 @@ static void mmc_blk_issue_drv_op(struct mmc_queue *mq, struct request *req)
>  			if (ret)
>  				break;
>  		}
> +
> +		mmc_blk_check_ce_ffu(mq_rq);
> +
>  		fallthrough;
>  	case MMC_DRV_OP_IOCTL_RPMB:
>  		idata = mq_rq->drv_op_data;
> diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
> index 6f7993803ee7..d4d10cabaa57 100644
> --- a/include/linux/mmc/mmc.h
> +++ b/include/linux/mmc/mmc.h
> @@ -254,6 +254,7 @@ static inline bool mmc_ready_for_data(u32 status)
>   */
>  
>  #define EXT_CSD_CMDQ_MODE_EN		15	/* R/W */
> +#define EXT_CSD_MODE_CONFIG		30	/* R/W */
>  #define EXT_CSD_FLUSH_CACHE		32      /* W */
>  #define EXT_CSD_CACHE_CTRL		33      /* R/W */
>  #define EXT_CSD_POWER_OFF_NOTIFICATION	34	/* R/W */


  reply	other threads:[~2023-11-06 14:53 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-10-30  9:09 [PATCH] mmc: core: Use mrq.sbc in close-ended ffu Avri Altman
2023-11-06 14:53 ` Adrian Hunter [this message]
2023-11-06 19:06   ` Avri Altman
2023-11-14 11:21     ` Avri Altman
2023-11-14 16:27       ` Ulf Hansson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=557eb489-3e1d-4cbd-b62d-d3046870a4cc@intel.com \
    --to=adrian.hunter@intel.com \
    --cc=avri.altman@wdc.com \
    --cc=dlunev@google.com \
    --cc=linux-mmc@vger.kernel.org \
    --cc=quic_asutoshd@quicinc.com \
    --cc=ulf.hansson@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox