Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 336288
b: refs/heads/master
c: 8d1e977
h: refs/heads/master
v: v3
  • Loading branch information
Loic Pallardy authored and Chris Ball committed Dec 6, 2012
1 parent 87a5e5c commit 65828d5
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 67c79db8d9c0e5d2e2075c9108f42566ce0f8a6f
refs/heads/master: 8d1e977da82ebd1defd44d085edc2c0140aecc2a
64 changes: 64 additions & 0 deletions trunk/drivers/mmc/card/block.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,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;
Expand Down Expand Up @@ -358,6 +362,38 @@ static struct mmc_blk_ioc_data *mmc_blk_ioctl_copy_from_user(
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)
{
Expand All @@ -369,6 +405,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
Expand All @@ -388,6 +426,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);
Expand Down Expand Up @@ -438,12 +479,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) {
Expand Down Expand Up @@ -479,6 +531,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);

Expand Down

0 comments on commit 65828d5

Please sign in to comment.