kernel: make bcm47xxpart work with TRX flashed at bad block(s)
Signed-off-by: Rafał Miłecki <zajec5@gmail.com> SVN-Revision: 48061
This commit is contained in:
		| @@ -22,7 +22,7 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com> | ||||
|   | ||||
|  #include <uapi/linux/magic.h> | ||||
|   | ||||
| @@ -131,6 +132,17 @@ static int bcm47xxpart_parse(struct mtd_ | ||||
| @@ -159,6 +160,17 @@ static int bcm47xxpart_parse(struct mtd_ | ||||
|  			break; | ||||
|  		} | ||||
|   | ||||
|   | ||||
| @@ -12,7 +12,7 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com> | ||||
|  | ||||
| --- a/drivers/mtd/bcm47xxpart.c | ||||
| +++ b/drivers/mtd/bcm47xxpart.c | ||||
| @@ -66,19 +66,22 @@ static void bcm47xxpart_add_part(struct | ||||
| @@ -94,19 +94,22 @@ static size_t bcm47xxpart_real_offset(st | ||||
|  static const char *bcm47xxpart_trx_data_part_name(struct mtd_info *master, | ||||
|  						  size_t offset) | ||||
|  { | ||||
|   | ||||
| @@ -22,7 +22,7 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com> | ||||
|   | ||||
|  #include <uapi/linux/magic.h> | ||||
|   | ||||
| @@ -131,6 +132,17 @@ static int bcm47xxpart_parse(struct mtd_ | ||||
| @@ -159,6 +160,17 @@ static int bcm47xxpart_parse(struct mtd_ | ||||
|  			break; | ||||
|  		} | ||||
|   | ||||
|   | ||||
| @@ -0,0 +1,100 @@ | ||||
| From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> | ||||
| Date: Sat, 2 Jan 2016 01:04:52 +0100 | ||||
| Subject: [PATCH] mtd: bcm47xxpart: check for bad blocks when calculating | ||||
|  offsets | ||||
| MIME-Version: 1.0 | ||||
| Content-Type: text/plain; charset=UTF-8 | ||||
| Content-Transfer-Encoding: 8bit | ||||
|  | ||||
| Signed-off-by: Rafał Miłecki <zajec5@gmail.com> | ||||
| --- | ||||
|  drivers/mtd/bcm47xxpart.c | 50 +++++++++++++++++++++++++++++++++++++---------- | ||||
|  1 file changed, 40 insertions(+), 10 deletions(-) | ||||
|  | ||||
| --- a/drivers/mtd/bcm47xxpart.c | ||||
| +++ b/drivers/mtd/bcm47xxpart.c | ||||
| @@ -61,6 +61,34 @@ static void bcm47xxpart_add_part(struct mtd_partition *part, const char *name, | ||||
|  	part->mask_flags = mask_flags; | ||||
|  } | ||||
|   | ||||
| +/* | ||||
| + * Calculate real end offset (address) for a given amount of data. It checks | ||||
| + * all blocks skipping bad ones. | ||||
| + */ | ||||
| +static size_t bcm47xxpart_real_offset(struct mtd_info *master, size_t offset, | ||||
| +				      size_t bytes) | ||||
| +{ | ||||
| +	size_t real_offset = offset; | ||||
| + | ||||
| +	if (mtd_block_isbad(master, real_offset)) | ||||
| +		pr_warn("Base offset shouldn't be at bad block"); | ||||
| + | ||||
| +	while (bytes >= master->erasesize) { | ||||
| +		bytes -= master->erasesize; | ||||
| +		real_offset += master->erasesize; | ||||
| +		while (mtd_block_isbad(master, real_offset)) { | ||||
| +			real_offset += master->erasesize; | ||||
| + | ||||
| +			if (real_offset >= master->size) | ||||
| +				return real_offset - master->erasesize; | ||||
| +		} | ||||
| +	} | ||||
| + | ||||
| +	real_offset += bytes; | ||||
| + | ||||
| +	return real_offset; | ||||
| +} | ||||
| + | ||||
|  static const char *bcm47xxpart_trx_data_part_name(struct mtd_info *master, | ||||
|  						  size_t offset) | ||||
|  { | ||||
| @@ -182,6 +210,8 @@ static int bcm47xxpart_parse(struct mtd_info *master, | ||||
|   | ||||
|  		/* TRX */ | ||||
|  		if (buf[0x000 / 4] == TRX_MAGIC) { | ||||
| +			uint32_t tmp; | ||||
| + | ||||
|  			if (BCM47XXPART_MAX_PARTS - curr_part < 4) { | ||||
|  				pr_warn("Not enough partitions left to register trx, scanning stopped!\n"); | ||||
|  				break; | ||||
| @@ -196,18 +226,18 @@ static int bcm47xxpart_parse(struct mtd_info *master, | ||||
|  			i = 0; | ||||
|  			/* We have LZMA loader if offset[2] points to sth */ | ||||
|  			if (trx->offset[2]) { | ||||
| +				tmp = bcm47xxpart_real_offset(master, offset, | ||||
| +							      trx->offset[i]); | ||||
|  				bcm47xxpart_add_part(&parts[curr_part++], | ||||
| -						     "loader", | ||||
| -						     offset + trx->offset[i], | ||||
| -						     0); | ||||
| +						     "loader", tmp, 0); | ||||
|  				i++; | ||||
|  			} | ||||
|   | ||||
|  			if (trx->offset[i]) { | ||||
| +				tmp = bcm47xxpart_real_offset(master, offset, | ||||
| +							      trx->offset[i]); | ||||
|  				bcm47xxpart_add_part(&parts[curr_part++], | ||||
| -						     "linux", | ||||
| -						     offset + trx->offset[i], | ||||
| -						     0); | ||||
| +						     "linux", tmp, 0); | ||||
|  				i++; | ||||
|  			} | ||||
|   | ||||
| @@ -219,11 +249,11 @@ static int bcm47xxpart_parse(struct mtd_info *master, | ||||
|  			if (trx->offset[i]) { | ||||
|  				const char *name; | ||||
|   | ||||
| -				name = bcm47xxpart_trx_data_part_name(master, offset + trx->offset[i]); | ||||
| +				tmp = bcm47xxpart_real_offset(master, offset, | ||||
| +							      trx->offset[i]); | ||||
| +				name = bcm47xxpart_trx_data_part_name(master, tmp); | ||||
|  				bcm47xxpart_add_part(&parts[curr_part++], | ||||
| -						     name, | ||||
| -						     offset + trx->offset[i], | ||||
| -						     0); | ||||
| +						     name, tmp, 0); | ||||
|  				i++; | ||||
|  			} | ||||
|   | ||||
| @@ -24,7 +24,7 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com> | ||||
|  #define ML_MAGIC1			0x39685a42 | ||||
|  #define ML_MAGIC2			0x26594131 | ||||
|  #define TRX_MAGIC			0x30524448 | ||||
| @@ -179,6 +180,15 @@ static int bcm47xxpart_parse(struct mtd_ | ||||
| @@ -207,6 +208,15 @@ static int bcm47xxpart_parse(struct mtd_ | ||||
|  					     MTD_WRITEABLE); | ||||
|  			continue; | ||||
|  		} | ||||
|   | ||||
| @@ -0,0 +1,100 @@ | ||||
| From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> | ||||
| Date: Sat, 2 Jan 2016 01:04:52 +0100 | ||||
| Subject: [PATCH] mtd: bcm47xxpart: check for bad blocks when calculating | ||||
|  offsets | ||||
| MIME-Version: 1.0 | ||||
| Content-Type: text/plain; charset=UTF-8 | ||||
| Content-Transfer-Encoding: 8bit | ||||
|  | ||||
| Signed-off-by: Rafał Miłecki <zajec5@gmail.com> | ||||
| --- | ||||
|  drivers/mtd/bcm47xxpart.c | 50 +++++++++++++++++++++++++++++++++++++---------- | ||||
|  1 file changed, 40 insertions(+), 10 deletions(-) | ||||
|  | ||||
| --- a/drivers/mtd/bcm47xxpart.c | ||||
| +++ b/drivers/mtd/bcm47xxpart.c | ||||
| @@ -61,6 +61,34 @@ static void bcm47xxpart_add_part(struct mtd_partition *part, const char *name, | ||||
|  	part->mask_flags = mask_flags; | ||||
|  } | ||||
|   | ||||
| +/* | ||||
| + * Calculate real end offset (address) for a given amount of data. It checks | ||||
| + * all blocks skipping bad ones. | ||||
| + */ | ||||
| +static size_t bcm47xxpart_real_offset(struct mtd_info *master, size_t offset, | ||||
| +				      size_t bytes) | ||||
| +{ | ||||
| +	size_t real_offset = offset; | ||||
| + | ||||
| +	if (mtd_block_isbad(master, real_offset)) | ||||
| +		pr_warn("Base offset shouldn't be at bad block"); | ||||
| + | ||||
| +	while (bytes >= master->erasesize) { | ||||
| +		bytes -= master->erasesize; | ||||
| +		real_offset += master->erasesize; | ||||
| +		while (mtd_block_isbad(master, real_offset)) { | ||||
| +			real_offset += master->erasesize; | ||||
| + | ||||
| +			if (real_offset >= master->size) | ||||
| +				return real_offset - master->erasesize; | ||||
| +		} | ||||
| +	} | ||||
| + | ||||
| +	real_offset += bytes; | ||||
| + | ||||
| +	return real_offset; | ||||
| +} | ||||
| + | ||||
|  static const char *bcm47xxpart_trx_data_part_name(struct mtd_info *master, | ||||
|  						  size_t offset) | ||||
|  { | ||||
| @@ -182,6 +210,8 @@ static int bcm47xxpart_parse(struct mtd_info *master, | ||||
|   | ||||
|  		/* TRX */ | ||||
|  		if (buf[0x000 / 4] == TRX_MAGIC) { | ||||
| +			uint32_t tmp; | ||||
| + | ||||
|  			if (BCM47XXPART_MAX_PARTS - curr_part < 4) { | ||||
|  				pr_warn("Not enough partitions left to register trx, scanning stopped!\n"); | ||||
|  				break; | ||||
| @@ -196,18 +226,18 @@ static int bcm47xxpart_parse(struct mtd_info *master, | ||||
|  			i = 0; | ||||
|  			/* We have LZMA loader if offset[2] points to sth */ | ||||
|  			if (trx->offset[2]) { | ||||
| +				tmp = bcm47xxpart_real_offset(master, offset, | ||||
| +							      trx->offset[i]); | ||||
|  				bcm47xxpart_add_part(&parts[curr_part++], | ||||
| -						     "loader", | ||||
| -						     offset + trx->offset[i], | ||||
| -						     0); | ||||
| +						     "loader", tmp, 0); | ||||
|  				i++; | ||||
|  			} | ||||
|   | ||||
|  			if (trx->offset[i]) { | ||||
| +				tmp = bcm47xxpart_real_offset(master, offset, | ||||
| +							      trx->offset[i]); | ||||
|  				bcm47xxpart_add_part(&parts[curr_part++], | ||||
| -						     "linux", | ||||
| -						     offset + trx->offset[i], | ||||
| -						     0); | ||||
| +						     "linux", tmp, 0); | ||||
|  				i++; | ||||
|  			} | ||||
|   | ||||
| @@ -219,11 +249,11 @@ static int bcm47xxpart_parse(struct mtd_info *master, | ||||
|  			if (trx->offset[i]) { | ||||
|  				const char *name; | ||||
|   | ||||
| -				name = bcm47xxpart_trx_data_part_name(master, offset + trx->offset[i]); | ||||
| +				tmp = bcm47xxpart_real_offset(master, offset, | ||||
| +							      trx->offset[i]); | ||||
| +				name = bcm47xxpart_trx_data_part_name(master, tmp); | ||||
|  				bcm47xxpart_add_part(&parts[curr_part++], | ||||
| -						     name, | ||||
| -						     offset + trx->offset[i], | ||||
| -						     0); | ||||
| +						     name, tmp, 0); | ||||
|  				i++; | ||||
|  			} | ||||
|   | ||||
| @@ -24,7 +24,7 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com> | ||||
|  #define ML_MAGIC1			0x39685a42 | ||||
|  #define ML_MAGIC2			0x26594131 | ||||
|  #define TRX_MAGIC			0x30524448 | ||||
| @@ -179,6 +180,15 @@ static int bcm47xxpart_parse(struct mtd_ | ||||
| @@ -207,6 +208,15 @@ static int bcm47xxpart_parse(struct mtd_ | ||||
|  					     MTD_WRITEABLE); | ||||
|  			continue; | ||||
|  		} | ||||
|   | ||||
| @@ -0,0 +1,100 @@ | ||||
| From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> | ||||
| Date: Sat, 2 Jan 2016 01:04:52 +0100 | ||||
| Subject: [PATCH] mtd: bcm47xxpart: check for bad blocks when calculating | ||||
|  offsets | ||||
| MIME-Version: 1.0 | ||||
| Content-Type: text/plain; charset=UTF-8 | ||||
| Content-Transfer-Encoding: 8bit | ||||
|  | ||||
| Signed-off-by: Rafał Miłecki <zajec5@gmail.com> | ||||
| --- | ||||
|  drivers/mtd/bcm47xxpart.c | 50 +++++++++++++++++++++++++++++++++++++---------- | ||||
|  1 file changed, 40 insertions(+), 10 deletions(-) | ||||
|  | ||||
| --- a/drivers/mtd/bcm47xxpart.c | ||||
| +++ b/drivers/mtd/bcm47xxpart.c | ||||
| @@ -61,6 +61,34 @@ static void bcm47xxpart_add_part(struct mtd_partition *part, const char *name, | ||||
|  	part->mask_flags = mask_flags; | ||||
|  } | ||||
|   | ||||
| +/* | ||||
| + * Calculate real end offset (address) for a given amount of data. It checks | ||||
| + * all blocks skipping bad ones. | ||||
| + */ | ||||
| +static size_t bcm47xxpart_real_offset(struct mtd_info *master, size_t offset, | ||||
| +				      size_t bytes) | ||||
| +{ | ||||
| +	size_t real_offset = offset; | ||||
| + | ||||
| +	if (mtd_block_isbad(master, real_offset)) | ||||
| +		pr_warn("Base offset shouldn't be at bad block"); | ||||
| + | ||||
| +	while (bytes >= master->erasesize) { | ||||
| +		bytes -= master->erasesize; | ||||
| +		real_offset += master->erasesize; | ||||
| +		while (mtd_block_isbad(master, real_offset)) { | ||||
| +			real_offset += master->erasesize; | ||||
| + | ||||
| +			if (real_offset >= master->size) | ||||
| +				return real_offset - master->erasesize; | ||||
| +		} | ||||
| +	} | ||||
| + | ||||
| +	real_offset += bytes; | ||||
| + | ||||
| +	return real_offset; | ||||
| +} | ||||
| + | ||||
|  static const char *bcm47xxpart_trx_data_part_name(struct mtd_info *master, | ||||
|  						  size_t offset) | ||||
|  { | ||||
| @@ -182,6 +210,8 @@ static int bcm47xxpart_parse(struct mtd_info *master, | ||||
|   | ||||
|  		/* TRX */ | ||||
|  		if (buf[0x000 / 4] == TRX_MAGIC) { | ||||
| +			uint32_t tmp; | ||||
| + | ||||
|  			if (BCM47XXPART_MAX_PARTS - curr_part < 4) { | ||||
|  				pr_warn("Not enough partitions left to register trx, scanning stopped!\n"); | ||||
|  				break; | ||||
| @@ -196,18 +226,18 @@ static int bcm47xxpart_parse(struct mtd_info *master, | ||||
|  			i = 0; | ||||
|  			/* We have LZMA loader if offset[2] points to sth */ | ||||
|  			if (trx->offset[2]) { | ||||
| +				tmp = bcm47xxpart_real_offset(master, offset, | ||||
| +							      trx->offset[i]); | ||||
|  				bcm47xxpart_add_part(&parts[curr_part++], | ||||
| -						     "loader", | ||||
| -						     offset + trx->offset[i], | ||||
| -						     0); | ||||
| +						     "loader", tmp, 0); | ||||
|  				i++; | ||||
|  			} | ||||
|   | ||||
|  			if (trx->offset[i]) { | ||||
| +				tmp = bcm47xxpart_real_offset(master, offset, | ||||
| +							      trx->offset[i]); | ||||
|  				bcm47xxpart_add_part(&parts[curr_part++], | ||||
| -						     "linux", | ||||
| -						     offset + trx->offset[i], | ||||
| -						     0); | ||||
| +						     "linux", tmp, 0); | ||||
|  				i++; | ||||
|  			} | ||||
|   | ||||
| @@ -219,11 +249,11 @@ static int bcm47xxpart_parse(struct mtd_info *master, | ||||
|  			if (trx->offset[i]) { | ||||
|  				const char *name; | ||||
|   | ||||
| -				name = bcm47xxpart_trx_data_part_name(master, offset + trx->offset[i]); | ||||
| +				tmp = bcm47xxpart_real_offset(master, offset, | ||||
| +							      trx->offset[i]); | ||||
| +				name = bcm47xxpart_trx_data_part_name(master, tmp); | ||||
|  				bcm47xxpart_add_part(&parts[curr_part++], | ||||
| -						     name, | ||||
| -						     offset + trx->offset[i], | ||||
| -						     0); | ||||
| +						     name, tmp, 0); | ||||
|  				i++; | ||||
|  			} | ||||
|   | ||||
| @@ -24,7 +24,7 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com> | ||||
|  #define ML_MAGIC1			0x39685a42 | ||||
|  #define ML_MAGIC2			0x26594131 | ||||
|  #define TRX_MAGIC			0x30524448 | ||||
| @@ -179,6 +180,15 @@ static int bcm47xxpart_parse(struct mtd_ | ||||
| @@ -207,6 +208,15 @@ static int bcm47xxpart_parse(struct mtd_ | ||||
|  					     MTD_WRITEABLE); | ||||
|  			continue; | ||||
|  		} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Rafał Miłecki
					Rafał Miłecki