From patchwork Fri Jul 6 08:44:04 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Loic Pallardy X-Patchwork-Id: 1164311 Return-Path: X-Original-To: patchwork-linux-mmc@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork2.kernel.org (Postfix) with ESMTP id 11BF3DFF34 for ; Fri, 6 Jul 2012 09:42:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752213Ab2GFJmQ (ORCPT ); Fri, 6 Jul 2012 05:42:16 -0400 Received: from eu1sys200aog114.obsmtp.com ([207.126.144.137]:35713 "EHLO eu1sys200aog114.obsmtp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753337Ab2GFJmP (ORCPT ); Fri, 6 Jul 2012 05:42:15 -0400 Received: from beta.dmz-ap.st.com ([138.198.100.35]) (using TLSv1) by eu1sys200aob114.postini.com ([207.126.147.11]) with SMTP ID DSNKT/ay9BNeid2m2zvnEl3JX2+gzj60b0LM@postini.com; Fri, 06 Jul 2012 09:42:14 UTC Received: from zeta.dmz-ap.st.com (ns6.st.com [138.198.234.13]) by beta.dmz-ap.st.com (STMicroelectronics) with ESMTP id 6B343BF; Fri, 6 Jul 2012 08:36:57 +0000 (GMT) Received: from relay1.stm.gmessaging.net (unknown [10.230.100.17]) by zeta.dmz-ap.st.com (STMicroelectronics) with ESMTP id 94ADCE37; Fri, 6 Jul 2012 08:45:14 +0000 (GMT) Received: from exdcvycastm022.EQ1STM.local (alteon-source-exch [10.230.100.61]) (using TLSv1 with cipher RC4-MD5 (128/128 bits)) (Client CN "exdcvycastm022", Issuer "exdcvycastm022" (not verified)) by relay1.stm.gmessaging.net (Postfix) with ESMTPS id AD5AE24C3EC; Fri, 6 Jul 2012 10:44:58 +0200 (CEST) Received: from lmenx30v.lme.st.com (10.230.100.153) by smtp.stericsson.com (10.230.100.30) with Microsoft SMTP Server (TLS) id 8.3.83.0; Fri, 6 Jul 2012 10:45:03 +0200 From: Loic Pallardy To: , Chris Ball Cc: Linus Walleij , STEricsson_nomadik_linux , Ulf Hansson , Loic Pallardy , Alex Macro Subject: [PATCH v1 5/5] mmc: card: Add RPMB support in IOCTL interface Date: Fri, 6 Jul 2012 10:44:04 +0200 Message-ID: <1341564244-6178-6-git-send-email-loic.pallardy@stericsson.com> X-Mailer: git-send-email 1.7.11.1 In-Reply-To: <1341564244-6178-1-git-send-email-loic.pallardy@stericsson.com> References: <1341564244-6178-1-git-send-email-loic.pallardy@stericsson.com> MIME-Version: 1.0 Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org RPMB partition is accessing though /dev/block/mmcXrpmb device User callers can read and write entire data frame(s) as defined by JEDEC Standard JESD84-A441, using standard IOCTL interface. Signed-off-by: Alex Macro Signed-off-by: Loic Pallardy Acked-by: Linus Walleij Acked-by: Johan Rudholm Reviewed-by: Namjae Jeon --- drivers/mmc/card/block.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 1b202fe..a9956cf 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -126,6 +126,10 @@ enum mmc_blk_status { module_param(perdev_minors, int, 0444); MODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device"); +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); + static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk) { struct mmc_blk_data *md; @@ -357,6 +361,38 @@ out: return ERR_PTR(err); } +static int ioctl_rpmb_card_status_poll(struct mmc_card *card, u32 *status, + u32 retries_max) +{ + int err; + u32 retry_count = 0; + + if (!status || !retries_max) + return -EINVAL; + + do { + err = get_card_status(card, status, 5); + if (err) + break; + + if (!R1_STATUS(*status) && + (R1_CURRENT_STATE(*status) != R1_STATE_PRG)) + break; /* RPMB programming operation complete */ + + /* + * Rechedule to give the MMC device a chance to continue + * processing the previous command without being polled too + * frequently. + */ + usleep_range(1000, 5000); + } while (++retry_count < retries_max); + + if (retry_count == retries_max) + err = -EPERM; + + return err; +} + static int mmc_blk_ioctl_cmd(struct block_device *bdev, struct mmc_ioc_cmd __user *ic_ptr) { @@ -368,6 +404,8 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev, struct mmc_request mrq = {NULL}; struct scatterlist sg; int err; + int is_rpmb = false; + u32 status = 0; /* * The caller must have CAP_SYS_RAWIO, and must be calling this on the @@ -387,6 +425,9 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev, goto cmd_err; } + if (md->area_type & MMC_BLK_DATA_AREA_RPMB) + is_rpmb = true; + card = md->queue.card; if (IS_ERR(card)) { err = PTR_ERR(card); @@ -437,12 +478,23 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev, mmc_claim_host(card->host); + err = mmc_blk_part_switch(card, md); + if (err) + goto cmd_rel_host; + if (idata->ic.is_acmd) { err = mmc_app_cmd(card->host, card); if (err) goto cmd_rel_host; } + if (is_rpmb) { + err = mmc_set_blockcount(card, data.blocks, + idata->ic.write_flag & (1 << 31)); + if (err) + goto cmd_rel_host; + } + mmc_wait_for_req(card->host, &mrq); if (cmd.error) { @@ -478,6 +530,18 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev, } } + if (is_rpmb) { + /* + * Ensure RPMB command has completed by polling CMD13 + * "Send Status". + */ + err = ioctl_rpmb_card_status_poll(card, &status, 5); + if (err) + dev_err(mmc_dev(card->host), + "%s: Card Status=0x%08X, error %d\n", + __func__, status, err); + } + cmd_rel_host: mmc_release_host(card->host);