forked from mirrors/linux
		
	mmc: core: new discard feature support at eMMC v4.5
MMC v4.5 supports the DISCARD feature (CMD38). It's different from trim and there's no check bit. Currently it's only supported at v4.5. Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Jaehoon Chung <jh80.chung@samsung.com> Signed-off-by: Chris Ball <cjb@laptop.org>
This commit is contained in:
		
							parent
							
								
									d9ddd62943
								
							
						
					
					
						commit
						b3bf915308
					
				
					 5 changed files with 26 additions and 1 deletions
				
			
		|  | @ -756,7 +756,9 @@ static int mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req) | ||||||
| 	from = blk_rq_pos(req); | 	from = blk_rq_pos(req); | ||||||
| 	nr = blk_rq_sectors(req); | 	nr = blk_rq_sectors(req); | ||||||
| 
 | 
 | ||||||
| 	if (mmc_can_trim(card)) | 	if (mmc_can_discard(card)) | ||||||
|  | 		arg = MMC_DISCARD_ARG; | ||||||
|  | 	else if (mmc_can_trim(card)) | ||||||
| 		arg = MMC_TRIM_ARG; | 		arg = MMC_TRIM_ARG; | ||||||
| 	else | 	else | ||||||
| 		arg = MMC_ERASE_ARG; | 		arg = MMC_ERASE_ARG; | ||||||
|  |  | ||||||
|  | @ -1709,10 +1709,24 @@ int mmc_can_trim(struct mmc_card *card) | ||||||
| { | { | ||||||
| 	if (card->ext_csd.sec_feature_support & EXT_CSD_SEC_GB_CL_EN) | 	if (card->ext_csd.sec_feature_support & EXT_CSD_SEC_GB_CL_EN) | ||||||
| 		return 1; | 		return 1; | ||||||
|  | 	if (mmc_can_discard(card)) | ||||||
|  | 		return 1; | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| EXPORT_SYMBOL(mmc_can_trim); | EXPORT_SYMBOL(mmc_can_trim); | ||||||
| 
 | 
 | ||||||
|  | int mmc_can_discard(struct mmc_card *card) | ||||||
|  | { | ||||||
|  | 	/*
 | ||||||
|  | 	 * As there's no way to detect the discard support bit at v4.5 | ||||||
|  | 	 * use the s/w feature support filed. | ||||||
|  | 	 */ | ||||||
|  | 	if (card->ext_csd.feature_support & MMC_DISCARD_FEATURE) | ||||||
|  | 		return 1; | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | EXPORT_SYMBOL(mmc_can_discard); | ||||||
|  | 
 | ||||||
| int mmc_can_sanitize(struct mmc_card *card) | int mmc_can_sanitize(struct mmc_card *card) | ||||||
| { | { | ||||||
| 	if (card->ext_csd.sec_feature_support & EXT_CSD_SEC_SANITIZE) | 	if (card->ext_csd.sec_feature_support & EXT_CSD_SEC_SANITIZE) | ||||||
|  |  | ||||||
|  | @ -452,6 +452,10 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) | ||||||
| 		card->ext_csd.rst_n_function = ext_csd[EXT_CSD_RST_N_FUNCTION]; | 		card->ext_csd.rst_n_function = ext_csd[EXT_CSD_RST_N_FUNCTION]; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/* eMMC v4.5 or later */ | ||||||
|  | 	if (card->ext_csd.rev >= 6) | ||||||
|  | 		card->ext_csd.feature_support |= MMC_DISCARD_FEATURE; | ||||||
|  | 
 | ||||||
| 	card->ext_csd.raw_erased_mem_count = ext_csd[EXT_CSD_ERASED_MEM_CONT]; | 	card->ext_csd.raw_erased_mem_count = ext_csd[EXT_CSD_ERASED_MEM_CONT]; | ||||||
| 	if (ext_csd[EXT_CSD_ERASED_MEM_CONT]) | 	if (ext_csd[EXT_CSD_ERASED_MEM_CONT]) | ||||||
| 		card->erased_byte = 0xFF; | 		card->erased_byte = 0xFF; | ||||||
|  |  | ||||||
|  | @ -80,6 +80,9 @@ struct mmc_ext_csd { | ||||||
| 	u8			raw_sec_feature_support;/* 231 */ | 	u8			raw_sec_feature_support;/* 231 */ | ||||||
| 	u8			raw_trim_mult;		/* 232 */ | 	u8			raw_trim_mult;		/* 232 */ | ||||||
| 	u8			raw_sectors[4];		/* 212 - 4 bytes */ | 	u8			raw_sectors[4];		/* 212 - 4 bytes */ | ||||||
|  | 
 | ||||||
|  | 	unsigned int            feature_support; | ||||||
|  | #define MMC_DISCARD_FEATURE	BIT(0)                  /* CMD38 feature */ | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct sd_scr { | struct sd_scr { | ||||||
|  |  | ||||||
|  | @ -146,6 +146,7 @@ extern int mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int); | ||||||
| #define MMC_ERASE_ARG		0x00000000 | #define MMC_ERASE_ARG		0x00000000 | ||||||
| #define MMC_SECURE_ERASE_ARG	0x80000000 | #define MMC_SECURE_ERASE_ARG	0x80000000 | ||||||
| #define MMC_TRIM_ARG		0x00000001 | #define MMC_TRIM_ARG		0x00000001 | ||||||
|  | #define MMC_DISCARD_ARG		0x00000003 | ||||||
| #define MMC_SECURE_TRIM1_ARG	0x80000001 | #define MMC_SECURE_TRIM1_ARG	0x80000001 | ||||||
| #define MMC_SECURE_TRIM2_ARG	0x80008000 | #define MMC_SECURE_TRIM2_ARG	0x80008000 | ||||||
| 
 | 
 | ||||||
|  | @ -156,6 +157,7 @@ extern int mmc_erase(struct mmc_card *card, unsigned int from, unsigned int nr, | ||||||
| 		     unsigned int arg); | 		     unsigned int arg); | ||||||
| extern int mmc_can_erase(struct mmc_card *card); | extern int mmc_can_erase(struct mmc_card *card); | ||||||
| extern int mmc_can_trim(struct mmc_card *card); | extern int mmc_can_trim(struct mmc_card *card); | ||||||
|  | extern int mmc_can_discard(struct mmc_card *card); | ||||||
| extern int mmc_can_sanitize(struct mmc_card *card); | extern int mmc_can_sanitize(struct mmc_card *card); | ||||||
| extern int mmc_can_secure_erase_trim(struct mmc_card *card); | extern int mmc_can_secure_erase_trim(struct mmc_card *card); | ||||||
| extern int mmc_erase_group_aligned(struct mmc_card *card, unsigned int from, | extern int mmc_erase_group_aligned(struct mmc_card *card, unsigned int from, | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Kyungmin Park
						Kyungmin Park