mmc: core: Detect card removal on I/O error
To prevent I/O as soon as possible at card removal, a new detect work is re-scheduled without a delay to let a rescan remove the card device as soon as possible. Additionally, MMC_CAP2_DETECT_ON_ERR can now be used to handle "slowly" removed cards that a scheduled detect work did not detect as removed. To prevent further I/O requests for these lingering removed cards, check if card has been removed and then schedule a detect work to properly remove it. Signed-off-by: Ulf Hansson <ulf.hansson@stericsson.com> Reviewed-by: Namjae Jeon <linkinjeon@gmail.com> Acked-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Chris Ball <cjb@laptop.org>
This commit is contained in:
		
							parent
							
								
									885c3e800c
								
							
						
					
					
						commit
						f0cc9cf993
					
				| @ -2121,18 +2121,36 @@ int _mmc_detect_card_removed(struct mmc_host *host) | ||||
| int mmc_detect_card_removed(struct mmc_host *host) | ||||
| { | ||||
| 	struct mmc_card *card = host->card; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	WARN_ON(!host->claimed); | ||||
| 
 | ||||
| 	if (!card) | ||||
| 		return 1; | ||||
| 
 | ||||
| 	ret = mmc_card_removed(card); | ||||
| 	/*
 | ||||
| 	 * The card will be considered unchanged unless we have been asked to | ||||
| 	 * detect a change or host requires polling to provide card detection. | ||||
| 	 */ | ||||
| 	if (card && !host->detect_change && !(host->caps & MMC_CAP_NEEDS_POLL)) | ||||
| 		return mmc_card_removed(card); | ||||
| 	if (!host->detect_change && !(host->caps & MMC_CAP_NEEDS_POLL) && | ||||
| 	    !(host->caps2 & MMC_CAP2_DETECT_ON_ERR)) | ||||
| 		return ret; | ||||
| 
 | ||||
| 	host->detect_change = 0; | ||||
| 	if (!ret) { | ||||
| 		ret = _mmc_detect_card_removed(host); | ||||
| 		if (ret && (host->caps2 & MMC_CAP2_DETECT_ON_ERR)) { | ||||
| 			/*
 | ||||
| 			 * Schedule a detect work as soon as possible to let a | ||||
| 			 * rescan handle the card removal. | ||||
| 			 */ | ||||
| 			cancel_delayed_work(&host->detect); | ||||
| 			mmc_detect_change(host, 0); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return _mmc_detect_card_removed(host); | ||||
| 	return ret; | ||||
| } | ||||
| EXPORT_SYMBOL(mmc_detect_card_removed); | ||||
| 
 | ||||
|  | ||||
| @ -258,6 +258,7 @@ struct mmc_host { | ||||
| #define MMC_CAP2_HS200		(MMC_CAP2_HS200_1_8V_SDR | \ | ||||
| 				 MMC_CAP2_HS200_1_2V_SDR) | ||||
| #define MMC_CAP2_BROKEN_VOLTAGE	(1 << 7)	/* Use the broken voltage */ | ||||
| #define MMC_CAP2_DETECT_ON_ERR	(1 << 8)	/* On I/O err check card removal */ | ||||
| 
 | ||||
| 	mmc_pm_flag_t		pm_caps;	/* supported pm features */ | ||||
| 	unsigned int        power_notify_type; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user