2429 lines · 60.7 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-only/* *  linux/drivers/mmc/core/core.c * *  Copyright (C) 2003-2004 Russell King, All Rights Reserved. *  SD support Copyright (C) 2004 Ian Molton, All Rights Reserved. *  Copyright (C) 2005-2008 Pierre Ossman, All Rights Reserved. *  MMCv4 support Copyright (C) 2006 Philip Langdale, All Rights Reserved. */#include <linux/module.h>#include <linux/init.h>#include <linux/interrupt.h>#include <linux/completion.h>#include <linux/device.h>#include <linux/delay.h>#include <linux/pagemap.h>#include <linux/err.h>#include <linux/leds.h>#include <linux/scatterlist.h>#include <linux/log2.h>#include <linux/pm_runtime.h>#include <linux/suspend.h>#include <linux/fault-inject.h>#include <linux/random.h>#include <linux/slab.h>#include <linux/of.h> #include <linux/mmc/card.h>#include <linux/mmc/host.h>#include <linux/mmc/mmc.h>#include <linux/mmc/sd.h>#include <linux/mmc/slot-gpio.h> #define CREATE_TRACE_POINTS#include <trace/events/mmc.h> #include "core.h"#include "card.h"#include "crypto.h"#include "bus.h"#include "host.h"#include "sdio_bus.h"#include "pwrseq.h" #include "mmc_ops.h"#include "sd_ops.h"#include "sdio_ops.h" /* The max erase timeout, used when host->max_busy_timeout isn't specified */#define MMC_ERASE_TIMEOUT_MS	(60 * 1000) /* 60 s */#define SD_DISCARD_TIMEOUT_MS	(250) static const unsigned freqs[] = { 400000, 300000, 200000, 100000 }; /* * Enabling software CRCs on the data blocks can be a significant (30%) * performance cost, and for other reasons may not always be desired. * So we allow it to be disabled. */bool use_spi_crc = 1;module_param(use_spi_crc, bool, 0); static int mmc_schedule_delayed_work(struct delayed_work *work,				     unsigned long delay){	/*	 * We use the system_freezable_wq, because of two reasons.	 * First, it allows several works (not the same work item) to be	 * executed simultaneously. Second, the queue becomes frozen when	 * userspace becomes frozen during system PM.	 */	return queue_delayed_work(system_freezable_wq, work, delay);} #ifdef CONFIG_FAIL_MMC_REQUEST /* * Internal function. Inject random data errors. * If mmc_data is NULL no errors are injected. */static void mmc_should_fail_request(struct mmc_host *host,				    struct mmc_request *mrq){	struct mmc_command *cmd = mrq->cmd;	struct mmc_data *data = mrq->data;	static const int data_errors[] = {		-ETIMEDOUT,		-EILSEQ,		-EIO,	}; 	if (!data)		return; 	if ((cmd && cmd->error) || data->error ||	    !should_fail(&host->fail_mmc_request, data->blksz * data->blocks))		return; 	data->error = data_errors[get_random_u32_below(ARRAY_SIZE(data_errors))];	data->bytes_xfered = get_random_u32_below(data->bytes_xfered >> SECTOR_SHIFT)						  << SECTOR_SHIFT;} #else /* CONFIG_FAIL_MMC_REQUEST */ static inline void mmc_should_fail_request(struct mmc_host *host,					   struct mmc_request *mrq){} #endif /* CONFIG_FAIL_MMC_REQUEST */ static inline void mmc_complete_cmd(struct mmc_request *mrq){	if (mrq->cap_cmd_during_tfr && !completion_done(&mrq->cmd_completion))		complete_all(&mrq->cmd_completion);} void mmc_command_done(struct mmc_host *host, struct mmc_request *mrq){	if (!mrq->cap_cmd_during_tfr)		return; 	mmc_complete_cmd(mrq); 	pr_debug("%s: cmd done, tfr ongoing (CMD%u)\n",		 mmc_hostname(host), mrq->cmd->opcode);}EXPORT_SYMBOL(mmc_command_done); /** *	mmc_request_done - finish processing an MMC request *	@host: MMC host which completed request *	@mrq: MMC request which request * *	MMC drivers should call this function when they have completed *	their processing of a request. */void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq){	struct mmc_command *cmd = mrq->cmd;	int err = cmd->error; 	/* Flag re-tuning needed on CRC errors */	if (!mmc_op_tuning(cmd->opcode) &&	    !host->retune_crc_disable &&	    (err == -EILSEQ || (mrq->sbc && mrq->sbc->error == -EILSEQ) ||	    (mrq->data && mrq->data->error == -EILSEQ) ||	    (mrq->stop && mrq->stop->error == -EILSEQ)))		mmc_retune_needed(host); 	if (err && cmd->retries && mmc_host_is_spi(host)) {		if (cmd->resp[0] & R1_SPI_ILLEGAL_COMMAND)			cmd->retries = 0;	} 	if (host->ongoing_mrq == mrq)		host->ongoing_mrq = NULL; 	mmc_complete_cmd(mrq); 	trace_mmc_request_done(host, mrq); 	/*	 * We list various conditions for the command to be considered	 * properly done:	 *	 * - There was no error, OK fine then	 * - We are not doing some kind of retry	 * - The card was removed (...so just complete everything no matter	 *   if there are errors or retries)	 */	if (!err || !cmd->retries || mmc_card_removed(host->card)) {		mmc_should_fail_request(host, mrq); 		if (!host->ongoing_mrq)			led_trigger_event(host->led, LED_OFF); 		if (mrq->sbc) {			pr_debug("%s: req done <CMD%u>: %d: %08x %08x %08x %08x\n",				mmc_hostname(host), mrq->sbc->opcode,				mrq->sbc->error,				mrq->sbc->resp[0], mrq->sbc->resp[1],				mrq->sbc->resp[2], mrq->sbc->resp[3]);		} 		pr_debug("%s: req done (CMD%u): %d: %08x %08x %08x %08x\n",			mmc_hostname(host), cmd->opcode, err,			cmd->resp[0], cmd->resp[1],			cmd->resp[2], cmd->resp[3]); 		if (mrq->data) {			pr_debug("%s:     %d bytes transferred: %d\n",				mmc_hostname(host),				mrq->data->bytes_xfered, mrq->data->error);		} 		if (mrq->stop) {			pr_debug("%s:     (CMD%u): %d: %08x %08x %08x %08x\n",				mmc_hostname(host), mrq->stop->opcode,				mrq->stop->error,				mrq->stop->resp[0], mrq->stop->resp[1],				mrq->stop->resp[2], mrq->stop->resp[3]);		}	}	/*	 * Request starter must handle retries - see	 * mmc_wait_for_req_done().	 */	if (mrq->done)		mrq->done(mrq);} EXPORT_SYMBOL(mmc_request_done); static void __mmc_start_request(struct mmc_host *host, struct mmc_request *mrq){	int err; 	/* Assumes host controller has been runtime resumed by mmc_claim_host */	err = mmc_retune(host);	if (err) {		mrq->cmd->error = err;		mmc_request_done(host, mrq);		return;	} 	/*	 * For sdio rw commands we must wait for card busy otherwise some	 * sdio devices won't work properly.	 * And bypass I/O abort, reset and bus suspend operations.	 */	if (sdio_is_io_busy(mrq->cmd->opcode, mrq->cmd->arg) &&	    host->ops->card_busy) {		int tries = 500; /* Wait aprox 500ms at maximum */ 		while (host->ops->card_busy(host) && --tries)			mmc_delay(1); 		if (tries == 0) {			mrq->cmd->error = -EBUSY;			mmc_request_done(host, mrq);			return;		}	} 	if (mrq->cap_cmd_during_tfr) {		host->ongoing_mrq = mrq;		/*		 * Retry path could come through here without having waiting on		 * cmd_completion, so ensure it is reinitialised.		 */		reinit_completion(&mrq->cmd_completion);	} 	trace_mmc_request_start(host, mrq); 	if (host->cqe_on)		host->cqe_ops->cqe_off(host); 	host->ops->request(host, mrq);} static void mmc_mrq_pr_debug(struct mmc_host *host, struct mmc_request *mrq,			     bool cqe){	if (mrq->sbc) {		pr_debug("<%s: starting CMD%u arg %08x flags %08x>\n",			 mmc_hostname(host), mrq->sbc->opcode,			 mrq->sbc->arg, mrq->sbc->flags);	} 	if (mrq->cmd) {		pr_debug("%s: starting %sCMD%u arg %08x flags %08x\n",			 mmc_hostname(host), cqe ? "CQE direct " : "",			 mrq->cmd->opcode, mrq->cmd->arg, mrq->cmd->flags);	} else if (cqe) {		pr_debug("%s: starting CQE transfer for tag %d blkaddr %u\n",			 mmc_hostname(host), mrq->tag, mrq->data->blk_addr);	} 	if (mrq->data) {		pr_debug("%s:     blksz %d blocks %d flags %08x "			"tsac %d ms nsac %d\n",			mmc_hostname(host), mrq->data->blksz,			mrq->data->blocks, mrq->data->flags,			mrq->data->timeout_ns / 1000000,			mrq->data->timeout_clks);	} 	if (mrq->stop) {		pr_debug("%s:     CMD%u arg %08x flags %08x\n",			 mmc_hostname(host), mrq->stop->opcode,			 mrq->stop->arg, mrq->stop->flags);	}} static int mmc_mrq_prep(struct mmc_host *host, struct mmc_request *mrq){	unsigned int i, sz = 0;	struct scatterlist *sg; 	if (mrq->cmd) {		mrq->cmd->error = 0;		mrq->cmd->mrq = mrq;		mrq->cmd->data = mrq->data;	}	if (mrq->sbc) {		mrq->sbc->error = 0;		mrq->sbc->mrq = mrq;	}	if (mrq->data) {		if (mrq->data->blksz > host->max_blk_size ||		    mrq->data->blocks > host->max_blk_count ||		    mrq->data->blocks * mrq->data->blksz > host->max_req_size)			return -EINVAL; 		for_each_sg(mrq->data->sg, sg, mrq->data->sg_len, i)			sz += sg->length;		if (sz != mrq->data->blocks * mrq->data->blksz)			return -EINVAL; 		mrq->data->error = 0;		mrq->data->mrq = mrq;		if (mrq->stop) {			mrq->data->stop = mrq->stop;			mrq->stop->error = 0;			mrq->stop->mrq = mrq;		}	} 	return 0;} int mmc_start_request(struct mmc_host *host, struct mmc_request *mrq){	int err; 	if (mrq->cmd->has_ext_addr)		mmc_send_ext_addr(host, mrq->cmd->ext_addr); 	init_completion(&mrq->cmd_completion); 	mmc_retune_hold(host); 	if (mmc_card_removed(host->card))		return -ENOMEDIUM; 	mmc_mrq_pr_debug(host, mrq, false); 	WARN_ON(!host->claimed); 	err = mmc_mrq_prep(host, mrq);	if (err)		return err; 	if (host->uhs2_sd_tran)		mmc_uhs2_prepare_cmd(host, mrq); 	led_trigger_event(host->led, LED_FULL);	__mmc_start_request(host, mrq); 	return 0;}EXPORT_SYMBOL(mmc_start_request); static void mmc_wait_done(struct mmc_request *mrq){	complete(&mrq->completion);} static inline void mmc_wait_ongoing_tfr_cmd(struct mmc_host *host){	struct mmc_request *ongoing_mrq = READ_ONCE(host->ongoing_mrq); 	/*	 * If there is an ongoing transfer, wait for the command line to become	 * available.	 */	if (ongoing_mrq && !completion_done(&ongoing_mrq->cmd_completion))		wait_for_completion(&ongoing_mrq->cmd_completion);} static int __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq){	int err; 	mmc_wait_ongoing_tfr_cmd(host); 	init_completion(&mrq->completion);	mrq->done = mmc_wait_done; 	err = mmc_start_request(host, mrq);	if (err) {		mrq->cmd->error = err;		mmc_complete_cmd(mrq);		complete(&mrq->completion);	} 	return err;} void mmc_wait_for_req_done(struct mmc_host *host, struct mmc_request *mrq){	struct mmc_command *cmd; 	while (1) {		wait_for_completion(&mrq->completion); 		cmd = mrq->cmd; 		if (!cmd->error || !cmd->retries ||		    mmc_card_removed(host->card))			break; 		mmc_retune_recheck(host); 		pr_debug("%s: req failed (CMD%u): %d, retrying...\n",			 mmc_hostname(host), cmd->opcode, cmd->error);		cmd->retries--;		cmd->error = 0;		__mmc_start_request(host, mrq);	} 	mmc_retune_release(host);}EXPORT_SYMBOL(mmc_wait_for_req_done); /* * mmc_cqe_start_req - Start a CQE request. * @host: MMC host to start the request * @mrq: request to start * * Start the request, re-tuning if needed and it is possible. Returns an error * code if the request fails to start or -EBUSY if CQE is busy. */int mmc_cqe_start_req(struct mmc_host *host, struct mmc_request *mrq){	int err; 	/*	 * CQE cannot process re-tuning commands. Caller must hold retuning	 * while CQE is in use.  Re-tuning can happen here only when CQE has no	 * active requests i.e. this is the first.  Note, re-tuning will call	 * ->cqe_off().	 */	err = mmc_retune(host);	if (err)		goto out_err; 	mrq->host = host; 	mmc_mrq_pr_debug(host, mrq, true); 	err = mmc_mrq_prep(host, mrq);	if (err)		goto out_err; 	if (host->uhs2_sd_tran)		mmc_uhs2_prepare_cmd(host, mrq); 	err = host->cqe_ops->cqe_request(host, mrq);	if (err)		goto out_err; 	trace_mmc_request_start(host, mrq); 	return 0; out_err:	if (mrq->cmd) {		pr_debug("%s: failed to start CQE direct CMD%u, error %d\n",			 mmc_hostname(host), mrq->cmd->opcode, err);	} else {		pr_debug("%s: failed to start CQE transfer for tag %d, error %d\n",			 mmc_hostname(host), mrq->tag, err);	}	return err;}EXPORT_SYMBOL(mmc_cqe_start_req); /** *	mmc_cqe_request_done - CQE has finished processing an MMC request *	@host: MMC host which completed request *	@mrq: MMC request which completed * *	CQE drivers should call this function when they have completed *	their processing of a request. */void mmc_cqe_request_done(struct mmc_host *host, struct mmc_request *mrq){	mmc_should_fail_request(host, mrq); 	/* Flag re-tuning needed on CRC errors */	if ((mrq->cmd && mrq->cmd->error == -EILSEQ) ||	    (mrq->data && mrq->data->error == -EILSEQ))		mmc_retune_needed(host); 	trace_mmc_request_done(host, mrq); 

Lines 1–500 of 2429.