mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	mmc: core: Disable card detect during shutdown
It's seems prone to problems by allowing card detect and its corresponding mmc_rescan() work to run, during platform shutdown. For example, we may end up turning off the power while initializing a card, which potentially could damage it. To avoid this scenario, let's add ->shutdown_pre() callback for the mmc host class device and then turn of the card detect from there. Reported-by: Al Cooper <alcooperx@gmail.com> Suggested-by: Adrian Hunter <adrian.hunter@intel.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20211203141555.105351-1-ulf.hansson@linaro.org
This commit is contained in:
		
							parent
							
								
									4fc7261dba
								
							
						
					
					
						commit
						66c915d09b
					
				
					 3 changed files with 16 additions and 1 deletions
				
			
		| 
						 | 
				
			
			@ -2264,7 +2264,7 @@ void mmc_start_host(struct mmc_host *host)
 | 
			
		|||
	_mmc_detect_change(host, 0, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mmc_stop_host(struct mmc_host *host)
 | 
			
		||||
void __mmc_stop_host(struct mmc_host *host)
 | 
			
		||||
{
 | 
			
		||||
	if (host->slot.cd_irq >= 0) {
 | 
			
		||||
		mmc_gpio_set_cd_wake(host, false);
 | 
			
		||||
| 
						 | 
				
			
			@ -2273,6 +2273,11 @@ void mmc_stop_host(struct mmc_host *host)
 | 
			
		|||
 | 
			
		||||
	host->rescan_disable = 1;
 | 
			
		||||
	cancel_delayed_work_sync(&host->detect);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mmc_stop_host(struct mmc_host *host)
 | 
			
		||||
{
 | 
			
		||||
	__mmc_stop_host(host);
 | 
			
		||||
 | 
			
		||||
	/* clear pm flags now and let card drivers set them as needed */
 | 
			
		||||
	host->pm_flags = 0;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -70,6 +70,7 @@ static inline void mmc_delay(unsigned int ms)
 | 
			
		|||
 | 
			
		||||
void mmc_rescan(struct work_struct *work);
 | 
			
		||||
void mmc_start_host(struct mmc_host *host);
 | 
			
		||||
void __mmc_stop_host(struct mmc_host *host);
 | 
			
		||||
void mmc_stop_host(struct mmc_host *host);
 | 
			
		||||
 | 
			
		||||
void _mmc_detect_change(struct mmc_host *host, unsigned long delay,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -80,9 +80,18 @@ static void mmc_host_classdev_release(struct device *dev)
 | 
			
		|||
	kfree(host);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int mmc_host_classdev_shutdown(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	struct mmc_host *host = cls_dev_to_mmc_host(dev);
 | 
			
		||||
 | 
			
		||||
	__mmc_stop_host(host);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct class mmc_host_class = {
 | 
			
		||||
	.name		= "mmc_host",
 | 
			
		||||
	.dev_release	= mmc_host_classdev_release,
 | 
			
		||||
	.shutdown_pre	= mmc_host_classdev_shutdown,
 | 
			
		||||
	.pm		= MMC_HOST_CLASS_DEV_PM_OPS,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue