diff options
Diffstat (limited to 'drivers/mmc/core/block.c')
| -rw-r--r-- | drivers/mmc/core/block.c | 76 | 
1 files changed, 47 insertions, 29 deletions
| diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index d666e24fbe0e..689eb9afeeed 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -539,7 +539,7 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,  	if ((MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_SANITIZE_START) &&  	    (cmd.opcode == MMC_SWITCH)) -		return mmc_sanitize(card); +		return mmc_sanitize(card, idata->ic.cmd_timeout_ms);  	mmc_wait_for_req(card->host, &mrq); @@ -573,6 +573,18 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,  	}  	/* +	 * Make sure to update CACHE_CTRL in case it was changed. The cache +	 * will get turned back on if the card is re-initialized, e.g. +	 * suspend/resume or hw reset in recovery. +	 */ +	if ((MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_CACHE_CTRL) && +	    (cmd.opcode == MMC_SWITCH)) { +		u8 value = MMC_EXTRACT_VALUE_FROM_ARG(cmd.arg) & 1; + +		card->ext_csd.cache_ctrl = value; +	} + +	/*  	 * According to the SD specs, some commands require a delay after  	 * issuing the command.  	 */ @@ -947,7 +959,7 @@ static int mmc_blk_reset(struct mmc_blk_data *md, struct mmc_host *host,  	md->reset_done |= type;  	err = mmc_hw_reset(host);  	/* Ensure we switch back to the correct partition */ -	if (err != -EOPNOTSUPP) { +	if (err) {  		struct mmc_blk_data *main_md =  			dev_get_drvdata(&host->card->dev);  		int part_err; @@ -1933,8 +1945,9 @@ static void mmc_blk_hsq_req_done(struct mmc_request *mrq)  void mmc_blk_mq_complete(struct request *req)  {  	struct mmc_queue *mq = req->q->queuedata; +	struct mmc_host *host = mq->card->host; -	if (mq->use_cqe) +	if (host->cqe_enabled)  		mmc_blk_cqe_complete_rq(mq, req);  	else if (likely(!blk_should_fake_timeout(req->q)))  		mmc_blk_mq_complete_rq(mq, req); @@ -2179,7 +2192,7 @@ out_post_req:  static int mmc_blk_wait_for_idle(struct mmc_queue *mq, struct mmc_host *host)  { -	if (mq->use_cqe) +	if (host->cqe_enabled)  		return host->cqe_ops->cqe_wait_for_idle(host);  	return mmc_blk_rw_wait(mq, NULL); @@ -2224,11 +2237,15 @@ enum mmc_issued mmc_blk_mq_issue_rq(struct mmc_queue *mq, struct request *req)  	case MMC_ISSUE_ASYNC:  		switch (req_op(req)) {  		case REQ_OP_FLUSH: +			if (!mmc_cache_enabled(host)) { +				blk_mq_end_request(req, BLK_STS_OK); +				return MMC_REQ_FINISHED; +			}  			ret = mmc_blk_cqe_issue_flush(mq, req);  			break;  		case REQ_OP_READ:  		case REQ_OP_WRITE: -			if (mq->use_cqe) +			if (host->cqe_enabled)  				ret = mmc_blk_cqe_issue_rw_rq(mq, req);  			else  				ret = mmc_blk_mq_issue_rw_rq(mq, req); @@ -2261,6 +2278,7 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,  {  	struct mmc_blk_data *md;  	int devidx, ret; +	char cap_str[10];  	devidx = ida_simple_get(&mmc_blk_ida, 0, max_devices, GFP_KERNEL);  	if (devidx < 0) { @@ -2365,6 +2383,12 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,  		blk_queue_write_cache(md->queue.queue, true, true);  	} +	string_get_size((u64)size, 512, STRING_UNITS_2, +			cap_str, sizeof(cap_str)); +	pr_info("%s: %s %s %s %s\n", +		md->disk->disk_name, mmc_card_id(card), mmc_card_name(card), +		cap_str, md->read_only ? "(ro)" : ""); +  	return md;   err_putdisk: @@ -2407,7 +2431,6 @@ static int mmc_blk_alloc_part(struct mmc_card *card,  			      const char *subname,  			      int area_type)  { -	char cap_str[10];  	struct mmc_blk_data *part_md;  	part_md = mmc_blk_alloc_req(card, disk_to_dev(md->disk), size, default_ro, @@ -2417,11 +2440,6 @@ static int mmc_blk_alloc_part(struct mmc_card *card,  	part_md->part_type = part_type;  	list_add(&part_md->part, &md->part); -	string_get_size((u64)get_capacity(part_md->disk), 512, STRING_UNITS_2, -			cap_str, sizeof(cap_str)); -	pr_info("%s: %s %s partition %u %s\n", -	       part_md->disk->disk_name, mmc_card_id(card), -	       mmc_card_name(card), part_md->part_type, cap_str);  	return 0;  } @@ -2558,9 +2576,8 @@ static int mmc_blk_alloc_rpmb_part(struct mmc_card *card,  	string_get_size((u64)size, 512, STRING_UNITS_2,  			cap_str, sizeof(cap_str)); -	pr_info("%s: %s %s partition %u %s, chardev (%d:%d)\n", -		rpmb_name, mmc_card_id(card), -		mmc_card_name(card), EXT_CSD_PART_CONFIG_ACC_RPMB, cap_str, +	pr_info("%s: %s %s %s, chardev (%d:%d)\n", +		rpmb_name, mmc_card_id(card), mmc_card_name(card), cap_str,  		MAJOR(mmc_rpmb_devt), rpmb->id);  	return 0; @@ -2876,7 +2893,7 @@ static void mmc_blk_remove_debugfs(struct mmc_card *card,  static int mmc_blk_probe(struct mmc_card *card)  {  	struct mmc_blk_data *md, *part_md; -	char cap_str[10]; +	int ret = 0;  	/*  	 * Check that the card supports the command class(es) we need. @@ -2888,31 +2905,30 @@ static int mmc_blk_probe(struct mmc_card *card)  	card->complete_wq = alloc_workqueue("mmc_complete",  					WQ_MEM_RECLAIM | WQ_HIGHPRI, 0); -	if (unlikely(!card->complete_wq)) { +	if (!card->complete_wq) {  		pr_err("Failed to create mmc completion workqueue");  		return -ENOMEM;  	}  	md = mmc_blk_alloc(card); -	if (IS_ERR(md)) -		return PTR_ERR(md); - -	string_get_size((u64)get_capacity(md->disk), 512, STRING_UNITS_2, -			cap_str, sizeof(cap_str)); -	pr_info("%s: %s %s %s %s\n", -		md->disk->disk_name, mmc_card_id(card), mmc_card_name(card), -		cap_str, md->read_only ? "(ro)" : ""); +	if (IS_ERR(md)) { +		ret = PTR_ERR(md); +		goto out_free; +	} -	if (mmc_blk_alloc_parts(card, md)) +	ret = mmc_blk_alloc_parts(card, md); +	if (ret)  		goto out;  	dev_set_drvdata(&card->dev, md); -	if (mmc_add_disk(md)) +	ret = mmc_add_disk(md); +	if (ret)  		goto out;  	list_for_each_entry(part_md, &md->part, part) { -		if (mmc_add_disk(part_md)) +		ret = mmc_add_disk(part_md); +		if (ret)  			goto out;  	} @@ -2933,10 +2949,12 @@ static int mmc_blk_probe(struct mmc_card *card)  	return 0; - out: +out:  	mmc_blk_remove_parts(card, md);  	mmc_blk_remove_req(md); -	return 0; +out_free: +	destroy_workqueue(card->complete_wq); +	return ret;  }  static void mmc_blk_remove(struct mmc_card *card) | 
