diff options
| author | Miquel Raynal <miquel.raynal@bootlin.com> | 2019-11-17 18:32:35 +0100 | 
|---|---|---|
| committer | Miquel Raynal <miquel.raynal@bootlin.com> | 2019-11-17 18:32:35 +0100 | 
| commit | ad39b5a1ed68032292794b41a5f9e41ea69f8052 (patch) | |
| tree | a7d47f8a7ba11be099c0ca08732334bbf1ba480d /drivers/mtd | |
| parent | 14f89e088155314d311e4d4dd9f2b4ccaeef92b2 (diff) | |
| parent | c15995695ea971253ea9507f6732c8cd35384e01 (diff) | |
| download | linux-ad39b5a1ed68032292794b41a5f9e41ea69f8052.tar.bz2 | |
Merge CFI/Hyperbus tag 'for-v5.5-rc1' into mtd/next
CFI core changes:
* Code cleanups related useless initializers and coding style issues
* Fix for a possible double free problem in cfi_cmdset_0002
* Improved error reporting and handling in cfi_cmdset_0002 core for HyperFlash
Diffstat (limited to 'drivers/mtd')
| -rw-r--r-- | drivers/mtd/chips/cfi_cmdset_0001.c | 10 | ||||
| -rw-r--r-- | drivers/mtd/chips/cfi_cmdset_0002.c | 79 | ||||
| -rw-r--r-- | drivers/mtd/chips/cfi_cmdset_0020.c | 8 | ||||
| -rw-r--r-- | drivers/mtd/chips/cfi_util.c | 2 | 
4 files changed, 55 insertions, 44 deletions
| diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 79a53cb8507b..00a79489067c 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c @@ -1353,7 +1353,7 @@ static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t a  {  	unsigned long cmd_addr;  	struct cfi_private *cfi = map->fldrv_priv; -	int ret = 0; +	int ret;  	adr += chip->start; @@ -1383,7 +1383,7 @@ static int cfi_intelext_point(struct mtd_info *mtd, loff_t from, size_t len,  	struct cfi_private *cfi = map->fldrv_priv;  	unsigned long ofs, last_end = 0;  	int chipnum; -	int ret = 0; +	int ret;  	if (!map->virt)  		return -EINVAL; @@ -1550,7 +1550,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,  {  	struct cfi_private *cfi = map->fldrv_priv;  	map_word status, write_cmd; -	int ret=0; +	int ret;  	adr += chip->start; @@ -1624,7 +1624,7 @@ static int cfi_intelext_write_words (struct mtd_info *mtd, loff_t to , size_t le  {  	struct map_info *map = mtd->priv;  	struct cfi_private *cfi = map->fldrv_priv; -	int ret = 0; +	int ret;  	int chipnum;  	unsigned long ofs; @@ -1871,7 +1871,7 @@ static int cfi_intelext_writev (struct mtd_info *mtd, const struct kvec *vecs,  	struct map_info *map = mtd->priv;  	struct cfi_private *cfi = map->fldrv_priv;  	int wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize; -	int ret = 0; +	int ret;  	int chipnum;  	unsigned long ofs, vec_seek, i;  	size_t len = 0; diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index cf8c8be40a9c..04b383bc3947 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -123,19 +123,23 @@ static int cfi_use_status_reg(struct cfi_private *cfi)  		(extp->SoftwareFeatures & poll_mask) == CFI_POLL_STATUS_REG;  } -static void cfi_check_err_status(struct map_info *map, struct flchip *chip, -				 unsigned long adr) +static int cfi_check_err_status(struct map_info *map, struct flchip *chip, +				unsigned long adr)  {  	struct cfi_private *cfi = map->fldrv_priv;  	map_word status;  	if (!cfi_use_status_reg(cfi)) -		return; +		return 0;  	cfi_send_gen_cmd(0x70, cfi->addr_unlock1, chip->start, map, cfi,  			 cfi->device_type, NULL);  	status = map_read(map, adr); +	/* The error bits are invalid while the chip's busy */ +	if (!map_word_bitsset(map, status, CMD(CFI_SR_DRB))) +		return 0; +  	if (map_word_bitsset(map, status, CMD(0x3a))) {  		unsigned long chipstatus = MERGESTATUS(status); @@ -151,7 +155,12 @@ static void cfi_check_err_status(struct map_info *map, struct flchip *chip,  		if (chipstatus & CFI_SR_SLSB)  			pr_err("%s sector write protected, status %lx\n",  			       map->name, chipstatus); + +		/* Erase/Program status bits are set on the operation failure */ +		if (chipstatus & (CFI_SR_ESB | CFI_SR_PSB)) +			return 1;  	} +	return 0;  }  /* #define DEBUG_CFI_FEATURES */ @@ -785,7 +794,6 @@ static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd)  	kfree(mtd->eraseregions);  	kfree(mtd);  	kfree(cfi->cmdset_priv); -	kfree(cfi->cfiq);  	return NULL;  } @@ -848,20 +856,16 @@ static int __xipram chip_good(struct map_info *map, struct flchip *chip,  	if (cfi_use_status_reg(cfi)) {  		map_word ready = CMD(CFI_SR_DRB); -		map_word err = CMD(CFI_SR_PSB | CFI_SR_ESB); +  		/*  		 * For chips that support status register, check device -		 * ready bit and Erase/Program status bit to know if -		 * operation succeeded. +		 * ready bit  		 */  		cfi_send_gen_cmd(0x70, cfi->addr_unlock1, chip->start, map, cfi,  				 cfi->device_type, NULL);  		curd = map_read(map, addr); -		if (map_word_andequal(map, curd, ready, ready)) -			return !map_word_bitsset(map, curd, err); - -		return 0; +		return map_word_andequal(map, curd, ready, ready);  	}  	oldd = map_read(map, addr); @@ -1699,8 +1703,11 @@ static int __xipram do_write_oneword_once(struct map_info *map,  			break;  		} -		if (chip_good(map, chip, adr, datum)) +		if (chip_good(map, chip, adr, datum)) { +			if (cfi_check_err_status(map, chip, adr)) +				ret = -EIO;  			break; +		}  		/* Latency issues. Drop the lock, wait a while and retry */  		UDELAY(map, chip, adr, 1); @@ -1713,7 +1720,7 @@ static int __xipram do_write_oneword_start(struct map_info *map,  					   struct flchip *chip,  					   unsigned long adr, int mode)  { -	int ret = 0; +	int ret;  	mutex_lock(&chip->mutex); @@ -1773,7 +1780,6 @@ static int __xipram do_write_oneword_retry(struct map_info *map,  	ret = do_write_oneword_once(map, chip, adr, datum, mode, cfi);  	if (ret) {  		/* reset on all failures. */ -		cfi_check_err_status(map, chip, adr);  		map_write(map, CMD(0xF0), chip->start);  		/* FIXME - should have reset delay before continuing */ @@ -1791,7 +1797,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,  				     unsigned long adr, map_word datum,  				     int mode)  { -	int ret = 0; +	int ret;  	adr += chip->start; @@ -1815,7 +1821,7 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len,  {  	struct map_info *map = mtd->priv;  	struct cfi_private *cfi = map->fldrv_priv; -	int ret = 0; +	int ret;  	int chipnum;  	unsigned long ofs, chipstart;  	DECLARE_WAITQUEUE(wait, current); @@ -1970,12 +1976,17 @@ static int __xipram do_write_buffer_wait(struct map_info *map,  		 */  		if (time_after(jiffies, timeo) &&  		    !chip_good(map, chip, adr, datum)) { +			pr_err("MTD %s(): software timeout, address:0x%.8lx.\n", +			       __func__, adr);  			ret = -EIO;  			break;  		} -		if (chip_good(map, chip, adr, datum)) +		if (chip_good(map, chip, adr, datum)) { +			if (cfi_check_err_status(map, chip, adr)) +				ret = -EIO;  			break; +		}  		/* Latency issues. Drop the lock, wait a while and retry */  		UDELAY(map, chip, adr, 1); @@ -2014,7 +2025,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,  				    int len)  {  	struct cfi_private *cfi = map->fldrv_priv; -	int ret = -EIO; +	int ret;  	unsigned long cmd_adr;  	int z, words;  	map_word datum; @@ -2071,12 +2082,8 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,  				chip->word_write_time);  	ret = do_write_buffer_wait(map, chip, adr, datum); -	if (ret) { -		cfi_check_err_status(map, chip, adr); +	if (ret)  		do_write_buffer_reset(map, chip, cfi); -		pr_err("MTD %s(): software timeout, address:0x%.8lx.\n", -		       __func__, adr); -	}  	xip_enable(map, chip, adr); @@ -2095,7 +2102,7 @@ static int cfi_amdstd_write_buffers(struct mtd_info *mtd, loff_t to, size_t len,  	struct map_info *map = mtd->priv;  	struct cfi_private *cfi = map->fldrv_priv;  	int wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize; -	int ret = 0; +	int ret;  	int chipnum;  	unsigned long ofs; @@ -2232,7 +2239,7 @@ static int do_panic_write_oneword(struct map_info *map, struct flchip *chip,  	struct cfi_private *cfi = map->fldrv_priv;  	int retry_cnt = 0;  	map_word oldd; -	int ret = 0; +	int ret;  	int i;  	adr += chip->start; @@ -2271,9 +2278,9 @@ retry:  		udelay(1);  	} -	if (!chip_good(map, chip, adr, datum)) { +	if (!chip_good(map, chip, adr, datum) || +	    cfi_check_err_status(map, chip, adr)) {  		/* reset on all failures. */ -		cfi_check_err_status(map, chip, adr);  		map_write(map, CMD(0xF0), chip->start);  		/* FIXME - should have reset delay before continuing */ @@ -2307,7 +2314,7 @@ static int cfi_amdstd_panic_write(struct mtd_info *mtd, loff_t to, size_t len,  	struct map_info *map = mtd->priv;  	struct cfi_private *cfi = map->fldrv_priv;  	unsigned long ofs, chipstart; -	int ret = 0; +	int ret;  	int chipnum;  	chipnum = to >> cfi->chipshift; @@ -2411,7 +2418,7 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip)  	unsigned long timeo = jiffies + HZ;  	unsigned long int adr;  	DECLARE_WAITQUEUE(wait, current); -	int ret = 0; +	int ret;  	int retry_cnt = 0;  	adr = cfi->addr_unlock1; @@ -2467,8 +2474,11 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip)  			chip->erase_suspended = 0;  		} -		if (chip_good(map, chip, adr, map_word_ff(map))) +		if (chip_good(map, chip, adr, map_word_ff(map))) { +			if (cfi_check_err_status(map, chip, adr)) +				ret = -EIO;  			break; +		}  		if (time_after(jiffies, timeo)) {  			printk(KERN_WARNING "MTD %s(): software timeout\n", @@ -2483,7 +2493,6 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip)  	/* Did we succeed? */  	if (ret) {  		/* reset on all failures. */ -		cfi_check_err_status(map, chip, adr);  		map_write(map, CMD(0xF0), chip->start);  		/* FIXME - should have reset delay before continuing */ @@ -2508,7 +2517,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,  	struct cfi_private *cfi = map->fldrv_priv;  	unsigned long timeo = jiffies + HZ;  	DECLARE_WAITQUEUE(wait, current); -	int ret = 0; +	int ret;  	int retry_cnt = 0;  	adr += chip->start; @@ -2564,8 +2573,11 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,  			chip->erase_suspended = 0;  		} -		if (chip_good(map, chip, adr, map_word_ff(map))) +		if (chip_good(map, chip, adr, map_word_ff(map))) { +			if (cfi_check_err_status(map, chip, adr)) +				ret = -EIO;  			break; +		}  		if (time_after(jiffies, timeo)) {  			printk(KERN_WARNING "MTD %s(): software timeout\n", @@ -2580,7 +2592,6 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,  	/* Did we succeed? */  	if (ret) {  		/* reset on all failures. */ -		cfi_check_err_status(map, chip, adr);  		map_write(map, CMD(0xF0), chip->start);  		/* FIXME - should have reset delay before continuing */ diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c index e752067526a5..54edae63b92d 100644 --- a/drivers/mtd/chips/cfi_cmdset_0020.c +++ b/drivers/mtd/chips/cfi_cmdset_0020.c @@ -611,7 +611,7 @@ static int cfi_staa_write_buffers (struct mtd_info *mtd, loff_t to,  	struct map_info *map = mtd->priv;  	struct cfi_private *cfi = map->fldrv_priv;  	int wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize; -	int ret = 0; +	int ret;  	int chipnum;  	unsigned long ofs; @@ -895,7 +895,7 @@ static int cfi_staa_erase_varsize(struct mtd_info *mtd,  {	struct map_info *map = mtd->priv;  	struct cfi_private *cfi = map->fldrv_priv;  	unsigned long adr, len; -	int chipnum, ret = 0; +	int chipnum, ret;  	int i, first;  	struct mtd_erase_region_info *regions = mtd->eraseregions; @@ -1132,7 +1132,7 @@ static int cfi_staa_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)  	struct map_info *map = mtd->priv;  	struct cfi_private *cfi = map->fldrv_priv;  	unsigned long adr; -	int chipnum, ret = 0; +	int chipnum, ret;  #ifdef DEBUG_LOCK_BITS  	int ofs_factor = cfi->interleave * cfi->device_type;  #endif @@ -1279,7 +1279,7 @@ static int cfi_staa_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)  	struct map_info *map = mtd->priv;  	struct cfi_private *cfi = map->fldrv_priv;  	unsigned long adr; -	int chipnum, ret = 0; +	int chipnum, ret;  #ifdef DEBUG_LOCK_BITS  	int ofs_factor = cfi->interleave * cfi->device_type;  #endif diff --git a/drivers/mtd/chips/cfi_util.c b/drivers/mtd/chips/cfi_util.c index e3b266ee06af..e2d4db05aeb3 100644 --- a/drivers/mtd/chips/cfi_util.c +++ b/drivers/mtd/chips/cfi_util.c @@ -26,7 +26,7 @@  void cfi_udelay(int us)  {  	if (us >= 1000) { -		msleep((us+999)/1000); +		msleep(DIV_ROUND_UP(us, 1000));  	} else {  		udelay(us);  		cond_resched(); |