mirror of
https://git.codelinaro.org/clo/qsdk/oss/boot/u-boot-2016.git
synced 2025-12-10 07:44:53 +01:00
ipq: Added nand bad block skipping to dump_to_flash feature
This change will skip the bad blocks offsets, if any while writing into the nand flash duirng crash when dump_to_flash enabled. This change also verifies whether the dump data is not overwritten into the next partition. Signed-off-by: Karthick Shanmugham <kartshan@codeaurora.org> Change-Id: I0eec4c772a5f5efb3c17bfd1fd3d3d9a5ff85d1d
This commit is contained in:
parent
c1ece2b859
commit
434cc613fc
3 changed files with 153 additions and 23 deletions
|
|
@ -585,6 +585,52 @@ unsigned int get_partition_table_offset(void)
|
|||
return primary_mibib;
|
||||
}
|
||||
|
||||
/*
|
||||
* smem_getpart_from_offset - retreive partition start and size for given offset
|
||||
* belongs to.
|
||||
* @part_name: offset for which part start and size needed
|
||||
* @start: location where the start offset is to be stored
|
||||
* @size: location where the size is to be stored
|
||||
*
|
||||
* Returns 0 at success or -ENOENT otherwise.
|
||||
*/
|
||||
int smem_getpart_from_offset(uint32_t offset, uint32_t *start, uint32_t *size)
|
||||
{
|
||||
unsigned i;
|
||||
qca_smem_flash_info_t *sfi = &qca_smem_flash_info;
|
||||
struct smem_ptn *p;
|
||||
uint32_t bsize;
|
||||
|
||||
for (i = 0; i < smem_ptable.len; i++) {
|
||||
p = &smem_ptable.parts[i];
|
||||
*start = p->start;
|
||||
bsize = get_part_block_size(p, sfi);
|
||||
|
||||
if (p->size == (~0u)) {
|
||||
/*
|
||||
* Partition size is 'till end of device', calculate
|
||||
* appropriately
|
||||
*/
|
||||
#ifdef CONFIG_CMD_NAND
|
||||
*size = (nand_info[get_device_id_by_part(p)].size /
|
||||
bsize) - p->start;
|
||||
#else
|
||||
*size = 0;
|
||||
bsize = bsize;
|
||||
#endif
|
||||
} else {
|
||||
*size = p->size;
|
||||
}
|
||||
*start = *start * bsize;
|
||||
*size = *size * bsize;
|
||||
if (*start <= offset && *start + *size > offset) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
|
||||
}
|
||||
/*
|
||||
* smem_getpart - retreive partition start and size
|
||||
* @part_name: partition name
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ int smem_get_boot_flash(uint32_t *flash_type,
|
|||
uint32_t *flash_block_size,
|
||||
uint32_t *flash_density);
|
||||
int smem_getpart(char *name, uint32_t *start, uint32_t *size);
|
||||
int smem_getpart_from_offset(uint32_t offset, uint32_t *start, uint32_t *size);
|
||||
int getpart_offset_size(char *part_name, uint32_t *offset, uint32_t *size);
|
||||
unsigned int smem_get_board_machtype(void);
|
||||
uint32_t get_nand_block_size(uint8_t dev_id);
|
||||
|
|
|
|||
|
|
@ -97,6 +97,8 @@ struct crashdump_flash_nand_cxt {
|
|||
int cur_page_data_len;
|
||||
int write_size;
|
||||
unsigned char temp_data[MAX_NAND_PAGE_SIZE];
|
||||
uint32_t part_start;
|
||||
uint32_t part_size;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_QCA_SPI
|
||||
|
|
@ -748,6 +750,93 @@ reset:
|
|||
reset_board();
|
||||
}
|
||||
#ifdef CONFIG_MTD_DEVICE
|
||||
|
||||
/*
|
||||
* NAND flash check and write. Before writing into the nand flash
|
||||
* this function checks if the block is non-bad, and skips if bad. While
|
||||
* skipping, there is also possiblity of crossing the partition and corrupting
|
||||
* next partition with crashdump data. So this function also checks whether
|
||||
* offset is within the partition, where the configured offset belongs.
|
||||
*
|
||||
* Returns 0 on succes and 1 otherwise
|
||||
*/
|
||||
static int check_and_write_crashdump_nand_flash(
|
||||
struct crashdump_flash_nand_cxt *nand_cnxt,
|
||||
nand_info_t *nand, unsigned char *data,
|
||||
unsigned int req_size)
|
||||
{
|
||||
nand_erase_options_t nand_erase_options;
|
||||
uint32_t part_start = nand_cnxt->part_start;
|
||||
uint32_t part_end = nand_cnxt->part_start + nand_cnxt->part_size;
|
||||
unsigned int remaining_len = req_size;
|
||||
unsigned int data_offset = 0;
|
||||
loff_t skipoff, skipoff_cmp, *offset;
|
||||
int ret = 0;
|
||||
static int first_erase = 1;
|
||||
|
||||
offset = &nand_cnxt->cur_crashdump_offset;
|
||||
|
||||
memset(&nand_erase_options, 0, sizeof(nand_erase_options));
|
||||
nand_erase_options.length = nand->erasesize;
|
||||
|
||||
while (remaining_len)
|
||||
{
|
||||
|
||||
skipoff = *offset - (*offset & (nand->erasesize - 1));
|
||||
skipoff_cmp = skipoff;
|
||||
|
||||
for (; skipoff < part_end; skipoff += nand->erasesize) {
|
||||
if (nand_block_isbad(nand, skipoff)) {
|
||||
printf("Skipping bad block at 0x%llx\n", skipoff);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (skipoff_cmp != skipoff)
|
||||
*offset = skipoff;
|
||||
|
||||
if(part_start > *offset || ((*offset + remaining_len) >= part_end)) {
|
||||
printf("Failure: Attempt to write in next partition\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if((*offset & (nand->erasesize - 1)) == 0 || first_erase){
|
||||
nand_erase_options.offset = *offset;
|
||||
|
||||
ret = nand_erase_opts(&nand_info[0],
|
||||
&nand_erase_options);
|
||||
if (ret)
|
||||
return ret;
|
||||
first_erase = 0;
|
||||
}
|
||||
|
||||
if( remaining_len > nand->erasesize) {
|
||||
|
||||
ret = nand_write(nand, *offset, &nand->erasesize,
|
||||
data + data_offset);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
remaining_len -= nand->erasesize;
|
||||
*offset += nand->erasesize;
|
||||
data_offset += nand->erasesize;
|
||||
}
|
||||
else {
|
||||
|
||||
ret = nand_write(nand, *offset, &remaining_len,
|
||||
data + data_offset);
|
||||
|
||||
*offset += remaining_len;
|
||||
remaining_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Init function for NAND flash writing. It intializes its own context
|
||||
* and erases the required sectors
|
||||
|
|
@ -755,10 +844,14 @@ reset:
|
|||
int init_crashdump_nand_flash_write(void *cnxt, loff_t offset,
|
||||
unsigned int total_size)
|
||||
{
|
||||
nand_erase_options_t nand_erase_options;
|
||||
struct crashdump_flash_nand_cxt *nand_cnxt = cnxt;
|
||||
int ret;
|
||||
|
||||
ret = smem_getpart_from_offset(offset, &nand_cnxt->part_start,
|
||||
&nand_cnxt->part_size);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
nand_cnxt->start_crashdump_offset = offset;
|
||||
nand_cnxt->cur_crashdump_offset = offset;
|
||||
nand_cnxt->cur_page_data_len = 0;
|
||||
|
|
@ -769,16 +862,6 @@ int init_crashdump_nand_flash_write(void *cnxt, loff_t offset,
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(&nand_erase_options, 0, sizeof(nand_erase_options));
|
||||
|
||||
nand_erase_options.length = total_size;
|
||||
nand_erase_options.offset = offset;
|
||||
|
||||
ret = nand_erase_opts(&nand_info[0],
|
||||
&nand_erase_options);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -803,9 +886,11 @@ int deinit_crashdump_nand_flash_write(void *cnxt)
|
|||
0xFF, remaining_bytes);
|
||||
|
||||
cur_nand_write_len = nand_cnxt->write_size;
|
||||
ret_val = nand_write(&nand_info[0],
|
||||
nand_cnxt->cur_crashdump_offset,
|
||||
&cur_nand_write_len, nand_cnxt->temp_data);
|
||||
|
||||
ret_val = check_and_write_crashdump_nand_flash(nand_cnxt,
|
||||
&nand_info[0], nand_cnxt->temp_data,
|
||||
cur_nand_write_len);
|
||||
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
|
|
@ -853,15 +938,14 @@ int crashdump_nand_flash_write_data(void *cnxt,
|
|||
memcpy(nand_cnxt->temp_data + nand_cnxt->cur_page_data_len, data,
|
||||
remaining_len_cur_page);
|
||||
|
||||
ret_val = nand_write(&nand_info[0], nand_cnxt->cur_crashdump_offset,
|
||||
&cur_nand_write_len,
|
||||
nand_cnxt->temp_data);
|
||||
ret_val = check_and_write_crashdump_nand_flash(nand_cnxt,
|
||||
&nand_info[0], nand_cnxt->temp_data,
|
||||
cur_nand_write_len);
|
||||
|
||||
if (ret_val)
|
||||
return ret_val;
|
||||
|
||||
cur_data_pos += remaining_len_cur_page;
|
||||
nand_cnxt->cur_crashdump_offset += cur_nand_write_len;
|
||||
|
||||
/*
|
||||
* Calculate the write length in multiple of page length and do the nand
|
||||
|
|
@ -871,17 +955,16 @@ int crashdump_nand_flash_write_data(void *cnxt,
|
|||
nand_cnxt->write_size) * nand_cnxt->write_size;
|
||||
|
||||
if (cur_nand_write_len > 0) {
|
||||
ret_val = nand_write(&nand_info[0],
|
||||
nand_cnxt->cur_crashdump_offset,
|
||||
&cur_nand_write_len,
|
||||
cur_data_pos);
|
||||
ret_val = check_and_write_crashdump_nand_flash(nand_cnxt,
|
||||
&nand_info[0], cur_data_pos,
|
||||
cur_nand_write_len);
|
||||
|
||||
if (ret_val)
|
||||
return ret_val;
|
||||
|
||||
}
|
||||
|
||||
cur_data_pos += cur_nand_write_len;
|
||||
nand_cnxt->cur_crashdump_offset += cur_nand_write_len;
|
||||
|
||||
/* Store the remaining data in temp data */
|
||||
remaining_bytes = data + size - cur_data_pos;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue