mirror of
				https://github.com/torvalds/linux.git
				synced 2025-10-31 16:48:26 +02:00 
			
		
		
		
	staging: android: persistent_ram: refactor ecc support
Remove CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION and related #ifdefs. Also allow persistent ram zones without ecc enabled. For some use cases, like the data portion of the upcoming persistent_vars patches, or a persistent ftrace ringbuffer, ecc on every update is too expensive. CC: Greg KH <gregkh@linuxfoundation.org> CC: Android Kernel Team <kernel-team@android.com> Signed-off-by: Colin Cross <ccross@android.com> Signed-off-by: John Stultz <john.stultz@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
		
							parent
							
								
									c672528aec
								
							
						
					
					
						commit
						9cc05ad97c
					
				
					 4 changed files with 168 additions and 172 deletions
				
			
		|  | @ -27,6 +27,9 @@ config ANDROID_LOGGER | ||||||
| 
 | 
 | ||||||
| config ANDROID_PERSISTENT_RAM | config ANDROID_PERSISTENT_RAM | ||||||
| 	bool | 	bool | ||||||
|  | 	select REED_SOLOMON | ||||||
|  | 	select REED_SOLOMON_ENC8 | ||||||
|  | 	select REED_SOLOMON_DEC8 | ||||||
| 
 | 
 | ||||||
| config ANDROID_RAM_CONSOLE | config ANDROID_RAM_CONSOLE | ||||||
| 	bool "Android RAM buffer console" | 	bool "Android RAM buffer console" | ||||||
|  | @ -34,40 +37,6 @@ config ANDROID_RAM_CONSOLE | ||||||
| 	select ANDROID_PERSISTENT_RAM | 	select ANDROID_PERSISTENT_RAM | ||||||
| 	default n | 	default n | ||||||
| 
 | 
 | ||||||
| menuconfig ANDROID_RAM_CONSOLE_ERROR_CORRECTION |  | ||||||
| 	bool "Android RAM Console Enable error correction" |  | ||||||
| 	default n |  | ||||||
| 	depends on ANDROID_PERSISTENT_RAM |  | ||||||
| 	select REED_SOLOMON |  | ||||||
| 	select REED_SOLOMON_ENC8 |  | ||||||
| 	select REED_SOLOMON_DEC8 |  | ||||||
| 
 |  | ||||||
| if ANDROID_RAM_CONSOLE_ERROR_CORRECTION |  | ||||||
| 
 |  | ||||||
| config ANDROID_RAM_CONSOLE_ERROR_CORRECTION_DATA_SIZE |  | ||||||
| 	int "Android RAM Console Data data size" |  | ||||||
| 	default 128 |  | ||||||
| 	help |  | ||||||
| 	  Must be a power of 2. |  | ||||||
| 
 |  | ||||||
| config ANDROID_RAM_CONSOLE_ERROR_CORRECTION_ECC_SIZE |  | ||||||
| 	int "Android RAM Console ECC size" |  | ||||||
| 	default 16 |  | ||||||
| 
 |  | ||||||
| config ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE |  | ||||||
| 	int "Android RAM Console Symbol size" |  | ||||||
| 	default 8 |  | ||||||
| 
 |  | ||||||
| config ANDROID_RAM_CONSOLE_ERROR_CORRECTION_POLYNOMIAL |  | ||||||
| 	hex "Android RAM Console Polynomial" |  | ||||||
| 	default 0x19 if (ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE = 4) |  | ||||||
| 	default 0x29 if (ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE = 5) |  | ||||||
| 	default 0x61 if (ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE = 6) |  | ||||||
| 	default 0x89 if (ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE = 7) |  | ||||||
| 	default 0x11d if (ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE = 8) |  | ||||||
| 
 |  | ||||||
| endif # ANDROID_RAM_CONSOLE_ERROR_CORRECTION |  | ||||||
| 
 |  | ||||||
| config ANDROID_TIMED_OUTPUT | config ANDROID_TIMED_OUTPUT | ||||||
| 	bool "Timed output class driver" | 	bool "Timed output class driver" | ||||||
| 	default y | 	default y | ||||||
|  |  | ||||||
|  | @ -16,13 +16,10 @@ | ||||||
| #include <linux/kernel.h> | #include <linux/kernel.h> | ||||||
| #include <linux/init.h> | #include <linux/init.h> | ||||||
| #include <linux/io.h> | #include <linux/io.h> | ||||||
|  | #include <linux/rslib.h> | ||||||
| #include <linux/slab.h> | #include <linux/slab.h> | ||||||
| #include "persistent_ram.h" | #include "persistent_ram.h" | ||||||
| 
 | 
 | ||||||
| #ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION |  | ||||||
| #include <linux/rslib.h> |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| struct persistent_ram_buffer { | struct persistent_ram_buffer { | ||||||
| 	uint32_t    sig; | 	uint32_t    sig; | ||||||
| 	uint32_t    start; | 	uint32_t    start; | ||||||
|  | @ -34,21 +31,16 @@ struct persistent_ram_buffer { | ||||||
| 
 | 
 | ||||||
| static LIST_HEAD(zone_list); | static LIST_HEAD(zone_list); | ||||||
| 
 | 
 | ||||||
| #define ECC_BLOCK_SIZE CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_DATA_SIZE |  | ||||||
| #define ECC_SIZE CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_ECC_SIZE |  | ||||||
| #define ECC_SYMSIZE CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE |  | ||||||
| #define ECC_POLY CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_POLYNOMIAL |  | ||||||
| 
 |  | ||||||
| #ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION |  | ||||||
| static void persistent_ram_encode_rs8(struct persistent_ram_zone *prz, | static void persistent_ram_encode_rs8(struct persistent_ram_zone *prz, | ||||||
| 	uint8_t *data, size_t len, uint8_t *ecc) | 	uint8_t *data, size_t len, uint8_t *ecc) | ||||||
| { | { | ||||||
| 	int i; | 	int i; | ||||||
| 	uint16_t par[ECC_SIZE]; | 	uint16_t par[prz->ecc_size]; | ||||||
|  | 
 | ||||||
| 	/* Initialize the parity buffer */ | 	/* Initialize the parity buffer */ | ||||||
| 	memset(par, 0, sizeof(par)); | 	memset(par, 0, sizeof(par)); | ||||||
| 	encode_rs8(prz->rs_decoder, data, len, par, 0); | 	encode_rs8(prz->rs_decoder, data, len, par, 0); | ||||||
| 	for (i = 0; i < ECC_SIZE; i++) | 	for (i = 0; i < prz->ecc_size; i++) | ||||||
| 		ecc[i] = par[i]; | 		ecc[i] = par[i]; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -56,47 +48,157 @@ static int persistent_ram_decode_rs8(struct persistent_ram_zone *prz, | ||||||
| 	void *data, size_t len, uint8_t *ecc) | 	void *data, size_t len, uint8_t *ecc) | ||||||
| { | { | ||||||
| 	int i; | 	int i; | ||||||
| 	uint16_t par[ECC_SIZE]; | 	uint16_t par[prz->ecc_size]; | ||||||
| 	for (i = 0; i < ECC_SIZE; i++) | 
 | ||||||
|  | 	for (i = 0; i < prz->ecc_size; i++) | ||||||
| 		par[i] = ecc[i]; | 		par[i] = ecc[i]; | ||||||
| 	return decode_rs8(prz->rs_decoder, data, par, len, | 	return decode_rs8(prz->rs_decoder, data, par, len, | ||||||
| 				NULL, 0, NULL, 0, NULL); | 				NULL, 0, NULL, 0, NULL); | ||||||
| } | } | ||||||
| #endif | 
 | ||||||
|  | static void persistent_ram_update_ecc(struct persistent_ram_zone *prz, | ||||||
|  | 	unsigned int count) | ||||||
|  | { | ||||||
|  | 	struct persistent_ram_buffer *buffer = prz->buffer; | ||||||
|  | 	uint8_t *buffer_end = buffer->data + prz->buffer_size; | ||||||
|  | 	uint8_t *block; | ||||||
|  | 	uint8_t *par; | ||||||
|  | 	int ecc_block_size = prz->ecc_block_size; | ||||||
|  | 	int ecc_size = prz->ecc_size; | ||||||
|  | 	int size = prz->ecc_block_size; | ||||||
|  | 
 | ||||||
|  | 	if (!prz->ecc) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	block = buffer->data + (buffer->start & ~(ecc_block_size - 1)); | ||||||
|  | 	par = prz->par_buffer + | ||||||
|  | 	      (buffer->start / ecc_block_size) * prz->ecc_size; | ||||||
|  | 	do { | ||||||
|  | 		if (block + ecc_block_size > buffer_end) | ||||||
|  | 			size = buffer_end - block; | ||||||
|  | 		persistent_ram_encode_rs8(prz, block, size, par); | ||||||
|  | 		block += ecc_block_size; | ||||||
|  | 		par += ecc_size; | ||||||
|  | 	} while (block < buffer->data + buffer->start + count); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void persistent_ram_update_header_ecc(struct persistent_ram_zone *prz) | ||||||
|  | { | ||||||
|  | 	struct persistent_ram_buffer *buffer = prz->buffer; | ||||||
|  | 
 | ||||||
|  | 	if (!prz->ecc) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	persistent_ram_encode_rs8(prz, (uint8_t *)buffer, sizeof(*buffer), | ||||||
|  | 				  prz->par_header); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void persistent_ram_ecc_old(struct persistent_ram_zone *prz) | ||||||
|  | { | ||||||
|  | 	struct persistent_ram_buffer *buffer = prz->buffer; | ||||||
|  | 	uint8_t *block; | ||||||
|  | 	uint8_t *par; | ||||||
|  | 
 | ||||||
|  | 	if (!prz->ecc) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	block = buffer->data; | ||||||
|  | 	par = prz->par_buffer; | ||||||
|  | 	while (block < buffer->data + buffer->size) { | ||||||
|  | 		int numerr; | ||||||
|  | 		int size = prz->ecc_block_size; | ||||||
|  | 		if (block + size > buffer->data + prz->buffer_size) | ||||||
|  | 			size = buffer->data + prz->buffer_size - block; | ||||||
|  | 		numerr = persistent_ram_decode_rs8(prz, block, size, par); | ||||||
|  | 		if (numerr > 0) { | ||||||
|  | 			pr_devel("persistent_ram: error in block %p, %d\n", | ||||||
|  | 			       block, numerr); | ||||||
|  | 			prz->corrected_bytes += numerr; | ||||||
|  | 		} else if (numerr < 0) { | ||||||
|  | 			pr_devel("persistent_ram: uncorrectable error in block %p\n", | ||||||
|  | 				block); | ||||||
|  | 			prz->bad_blocks++; | ||||||
|  | 		} | ||||||
|  | 		block += prz->ecc_block_size; | ||||||
|  | 		par += prz->ecc_size; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int persistent_ram_init_ecc(struct persistent_ram_zone *prz, | ||||||
|  | 	size_t buffer_size) | ||||||
|  | { | ||||||
|  | 	int numerr; | ||||||
|  | 	struct persistent_ram_buffer *buffer = prz->buffer; | ||||||
|  | 	int ecc_blocks; | ||||||
|  | 
 | ||||||
|  | 	if (!prz->ecc) | ||||||
|  | 		return 0; | ||||||
|  | 
 | ||||||
|  | 	prz->ecc_block_size = 128; | ||||||
|  | 	prz->ecc_size = 16; | ||||||
|  | 	prz->ecc_symsize = 8; | ||||||
|  | 	prz->ecc_poly = 0x11d; | ||||||
|  | 
 | ||||||
|  | 	ecc_blocks = DIV_ROUND_UP(prz->buffer_size, prz->ecc_block_size); | ||||||
|  | 	prz->buffer_size -= (ecc_blocks + 1) * prz->ecc_size; | ||||||
|  | 
 | ||||||
|  | 	if (prz->buffer_size > buffer_size) { | ||||||
|  | 		pr_err("persistent_ram: invalid size %zu, non-ecc datasize %zu\n", | ||||||
|  | 		       buffer_size, prz->buffer_size); | ||||||
|  | 		return -EINVAL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	prz->par_buffer = buffer->data + prz->buffer_size; | ||||||
|  | 	prz->par_header = prz->par_buffer + ecc_blocks * prz->ecc_size; | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * first consecutive root is 0 | ||||||
|  | 	 * primitive element to generate roots = 1 | ||||||
|  | 	 */ | ||||||
|  | 	prz->rs_decoder = init_rs(prz->ecc_symsize, prz->ecc_poly, 0, 1, | ||||||
|  | 				  prz->ecc_size); | ||||||
|  | 	if (prz->rs_decoder == NULL) { | ||||||
|  | 		pr_info("persistent_ram: init_rs failed\n"); | ||||||
|  | 		return -EINVAL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	prz->corrected_bytes = 0; | ||||||
|  | 	prz->bad_blocks = 0; | ||||||
|  | 
 | ||||||
|  | 	numerr = persistent_ram_decode_rs8(prz, buffer, sizeof(*buffer), | ||||||
|  | 					   prz->par_header); | ||||||
|  | 	if (numerr > 0) { | ||||||
|  | 		pr_info("persistent_ram: error in header, %d\n", numerr); | ||||||
|  | 		prz->corrected_bytes += numerr; | ||||||
|  | 	} else if (numerr < 0) { | ||||||
|  | 		pr_info("persistent_ram: uncorrectable error in header\n"); | ||||||
|  | 		prz->bad_blocks++; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ssize_t persistent_ram_ecc_string(struct persistent_ram_zone *prz, | ||||||
|  | 	char *str, size_t len) | ||||||
|  | { | ||||||
|  | 	ssize_t ret; | ||||||
|  | 
 | ||||||
|  | 	if (prz->corrected_bytes || prz->bad_blocks) | ||||||
|  | 		ret = snprintf(str, len, "" | ||||||
|  | 			"\n%d Corrected bytes, %d unrecoverable blocks\n", | ||||||
|  | 			prz->corrected_bytes, prz->bad_blocks); | ||||||
|  | 	else | ||||||
|  | 		ret = snprintf(str, len, "\nNo errors detected\n"); | ||||||
|  | 
 | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| static void persistent_ram_update(struct persistent_ram_zone *prz, | static void persistent_ram_update(struct persistent_ram_zone *prz, | ||||||
| 	const void *s, unsigned int count) | 	const void *s, unsigned int count) | ||||||
| { | { | ||||||
| 	struct persistent_ram_buffer *buffer = prz->buffer; | 	struct persistent_ram_buffer *buffer = prz->buffer; | ||||||
| #ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION |  | ||||||
| 	uint8_t *buffer_end = buffer->data + prz->buffer_size; |  | ||||||
| 	uint8_t *block; |  | ||||||
| 	uint8_t *par; |  | ||||||
| 	int size = ECC_BLOCK_SIZE; |  | ||||||
| #endif |  | ||||||
| 	memcpy(buffer->data + buffer->start, s, count); | 	memcpy(buffer->data + buffer->start, s, count); | ||||||
| #ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION | 	persistent_ram_update_ecc(prz, count); | ||||||
| 	block = buffer->data + (buffer->start & ~(ECC_BLOCK_SIZE - 1)); |  | ||||||
| 	par = prz->par_buffer + |  | ||||||
| 	      (buffer->start / ECC_BLOCK_SIZE) * ECC_SIZE; |  | ||||||
| 	do { |  | ||||||
| 		if (block + ECC_BLOCK_SIZE > buffer_end) |  | ||||||
| 			size = buffer_end - block; |  | ||||||
| 		persistent_ram_encode_rs8(prz, block, size, par); |  | ||||||
| 		block += ECC_BLOCK_SIZE; |  | ||||||
| 		par += ECC_SIZE; |  | ||||||
| 	} while (block < buffer->data + buffer->start + count); |  | ||||||
| #endif |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void persistent_ram_update_header(struct persistent_ram_zone *prz) |  | ||||||
| { |  | ||||||
| #ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION |  | ||||||
| 	struct persistent_ram_buffer *buffer = prz->buffer; |  | ||||||
| 
 |  | ||||||
| 	persistent_ram_encode_rs8(prz, (uint8_t *)buffer, sizeof(*buffer), |  | ||||||
| 				  prz->par_header); |  | ||||||
| #endif |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void __init | static void __init | ||||||
|  | @ -105,35 +207,8 @@ persistent_ram_save_old(struct persistent_ram_zone *prz) | ||||||
| 	struct persistent_ram_buffer *buffer = prz->buffer; | 	struct persistent_ram_buffer *buffer = prz->buffer; | ||||||
| 	size_t old_log_size = buffer->size; | 	size_t old_log_size = buffer->size; | ||||||
| 	char *dest; | 	char *dest; | ||||||
| #ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION |  | ||||||
| 	uint8_t *block; |  | ||||||
| 	uint8_t *par; |  | ||||||
| 
 | 
 | ||||||
| 	block = buffer->data; | 	persistent_ram_ecc_old(prz); | ||||||
| 	par = prz->par_buffer; |  | ||||||
| 	while (block < buffer->data + buffer->size) { |  | ||||||
| 		int numerr; |  | ||||||
| 		int size = ECC_BLOCK_SIZE; |  | ||||||
| 		if (block + size > buffer->data + prz->buffer_size) |  | ||||||
| 			size = buffer->data + prz->buffer_size - block; |  | ||||||
| 		numerr = persistent_ram_decode_rs8(prz, block, size, par); |  | ||||||
| 		if (numerr > 0) { |  | ||||||
| #if 0 |  | ||||||
| 			pr_info("persistent_ram: error in block %p, %d\n", |  | ||||||
| 			       block, numerr); |  | ||||||
| #endif |  | ||||||
| 			prz->corrected_bytes += numerr; |  | ||||||
| 		} else if (numerr < 0) { |  | ||||||
| #if 0 |  | ||||||
| 			pr_info("persistent_ram: uncorrectable error in block %p\n", |  | ||||||
| 				block); |  | ||||||
| #endif |  | ||||||
| 			prz->bad_blocks++; |  | ||||||
| 		} |  | ||||||
| 		block += ECC_BLOCK_SIZE; |  | ||||||
| 		par += ECC_SIZE; |  | ||||||
| 	} |  | ||||||
| #endif |  | ||||||
| 
 | 
 | ||||||
| 	dest = kmalloc(old_log_size, GFP_KERNEL); | 	dest = kmalloc(old_log_size, GFP_KERNEL); | ||||||
| 	if (dest == NULL) { | 	if (dest == NULL) { | ||||||
|  | @ -173,30 +248,11 @@ int persistent_ram_write(struct persistent_ram_zone *prz, | ||||||
| 	buffer->start += c; | 	buffer->start += c; | ||||||
| 	if (buffer->size < prz->buffer_size) | 	if (buffer->size < prz->buffer_size) | ||||||
| 		buffer->size += c; | 		buffer->size += c; | ||||||
| 	persistent_ram_update_header(prz); | 	persistent_ram_update_header_ecc(prz); | ||||||
| 
 | 
 | ||||||
| 	return count; | 	return count; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ssize_t persistent_ram_ecc_string(struct persistent_ram_zone *prz, |  | ||||||
| 	char *str, size_t len) |  | ||||||
| { |  | ||||||
| #ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION |  | ||||||
| 	ssize_t ret; |  | ||||||
| 
 |  | ||||||
| 	if (prz->corrected_bytes || prz->bad_blocks) |  | ||||||
| 		ret = snprintf(str, len, "" |  | ||||||
| 			"\n%d Corrected bytes, %d unrecoverable blocks\n", |  | ||||||
| 			prz->corrected_bytes, prz->bad_blocks); |  | ||||||
| 	else |  | ||||||
| 		ret = snprintf(str, len, "\nNo errors detected\n"); |  | ||||||
| 
 |  | ||||||
| 	return ret; |  | ||||||
| #else |  | ||||||
| 	return 0; |  | ||||||
| #endif |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| size_t persistent_ram_old_size(struct persistent_ram_zone *prz) | size_t persistent_ram_old_size(struct persistent_ram_zone *prz) | ||||||
| { | { | ||||||
| 	return prz->old_log_size; | 	return prz->old_log_size; | ||||||
|  | @ -215,12 +271,10 @@ void persistent_ram_free_old(struct persistent_ram_zone *prz) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int __init __persistent_ram_init(struct persistent_ram_zone *prz, | static int __init __persistent_ram_init(struct persistent_ram_zone *prz, | ||||||
| 			       void __iomem *mem, size_t buffer_size) | 			       void __iomem *mem, size_t buffer_size, bool ecc) | ||||||
| { | { | ||||||
| 	struct persistent_ram_buffer *buffer = mem; | 	struct persistent_ram_buffer *buffer = mem; | ||||||
| #ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION | 	int ret; | ||||||
| 	int numerr; |  | ||||||
| #endif |  | ||||||
| 
 | 
 | ||||||
| 	INIT_LIST_HEAD(&prz->node); | 	INIT_LIST_HEAD(&prz->node); | ||||||
| 
 | 
 | ||||||
|  | @ -233,43 +287,10 @@ static int __init __persistent_ram_init(struct persistent_ram_zone *prz, | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| #ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION | 	prz->ecc = ecc; | ||||||
| 	prz->buffer_size -= (DIV_ROUND_UP(prz->buffer_size, | 	ret = persistent_ram_init_ecc(prz, buffer_size); | ||||||
| 						ECC_BLOCK_SIZE) + 1) * ECC_SIZE; | 	if (ret) | ||||||
| 
 | 		return ret; | ||||||
| 	if (prz->buffer_size > buffer_size) { |  | ||||||
| 		pr_err("persistent_ram: buffer %p, invalid size %zu, non-ecc datasize %zu\n", |  | ||||||
| 		       buffer, buffer_size, prz->buffer_size); |  | ||||||
| 		return -EINVAL; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	prz->par_buffer = buffer->data + prz->buffer_size; |  | ||||||
| 	prz->par_header = prz->par_buffer + |  | ||||||
| 		DIV_ROUND_UP(prz->buffer_size, ECC_BLOCK_SIZE) * ECC_SIZE; |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 	/* first consecutive root is 0
 |  | ||||||
| 	 * primitive element to generate roots = 1 |  | ||||||
| 	 */ |  | ||||||
| 	prz->rs_decoder = init_rs(ECC_SYMSIZE, ECC_POLY, 0, 1, ECC_SIZE); |  | ||||||
| 	if (prz->rs_decoder == NULL) { |  | ||||||
| 		pr_info("persistent_ram: init_rs failed\n"); |  | ||||||
| 		return -EINVAL; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	prz->corrected_bytes = 0; |  | ||||||
| 	prz->bad_blocks = 0; |  | ||||||
| 
 |  | ||||||
| 	numerr = persistent_ram_decode_rs8(prz, buffer, sizeof(*buffer), |  | ||||||
| 					   prz->par_header); |  | ||||||
| 	if (numerr > 0) { |  | ||||||
| 		pr_info("persistent_ram: error in header, %d\n", numerr); |  | ||||||
| 		prz->corrected_bytes += numerr; |  | ||||||
| 	} else if (numerr < 0) { |  | ||||||
| 		pr_info("persistent_ram: uncorrectable error in header\n"); |  | ||||||
| 		prz->bad_blocks++; |  | ||||||
| 	} |  | ||||||
| #endif |  | ||||||
| 
 | 
 | ||||||
| 	if (buffer->sig == PERSISTENT_RAM_SIG) { | 	if (buffer->sig == PERSISTENT_RAM_SIG) { | ||||||
| 		if (buffer->size > prz->buffer_size | 		if (buffer->size > prz->buffer_size | ||||||
|  | @ -296,7 +317,7 @@ static int __init __persistent_ram_init(struct persistent_ram_zone *prz, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int __init persistent_ram_init_ringbuffer(struct persistent_ram_zone *prz, | int __init persistent_ram_init_ringbuffer(struct persistent_ram_zone *prz, | ||||||
| 			       void __iomem *mem, size_t buffer_size) | 			       void __iomem *mem, size_t buffer_size, bool ecc) | ||||||
| { | { | ||||||
| 	return __persistent_ram_init(prz, mem, buffer_size); | 	return __persistent_ram_init(prz, mem, buffer_size, true); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,13 +24,19 @@ struct persistent_ram_zone { | ||||||
| 	struct list_head node; | 	struct list_head node; | ||||||
| 	struct persistent_ram_buffer *buffer; | 	struct persistent_ram_buffer *buffer; | ||||||
| 	size_t buffer_size; | 	size_t buffer_size; | ||||||
| #ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION | 
 | ||||||
|  | 	/* ECC correction */ | ||||||
|  | 	bool ecc; | ||||||
| 	char *par_buffer; | 	char *par_buffer; | ||||||
| 	char *par_header; | 	char *par_header; | ||||||
| 	struct rs_control *rs_decoder; | 	struct rs_control *rs_decoder; | ||||||
| 	int corrected_bytes; | 	int corrected_bytes; | ||||||
| 	int bad_blocks; | 	int bad_blocks; | ||||||
| #endif | 	int ecc_block_size; | ||||||
|  | 	int ecc_size; | ||||||
|  | 	int ecc_symsize; | ||||||
|  | 	int ecc_poly; | ||||||
|  | 
 | ||||||
| 	char *old_log; | 	char *old_log; | ||||||
| 	size_t old_log_size; | 	size_t old_log_size; | ||||||
| 	size_t old_log_footer_size; | 	size_t old_log_footer_size; | ||||||
|  | @ -38,7 +44,7 @@ struct persistent_ram_zone { | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| int persistent_ram_init_ringbuffer(struct persistent_ram_zone *prz, | int persistent_ram_init_ringbuffer(struct persistent_ram_zone *prz, | ||||||
| 	void __iomem *buffer, size_t buffer_size); | 	void __iomem *buffer, size_t buffer_size, bool ecc); | ||||||
| 
 | 
 | ||||||
| int persistent_ram_write(struct persistent_ram_zone *prz, const void *s, | int persistent_ram_write(struct persistent_ram_zone *prz, const void *s, | ||||||
| 	unsigned int count); | 	unsigned int count); | ||||||
|  |  | ||||||
|  | @ -76,7 +76,7 @@ static int ram_console_driver_probe(struct platform_device *pdev) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	ret = persistent_ram_init_ringbuffer(&ram_console_zone, buffer, | 	ret = persistent_ram_init_ringbuffer(&ram_console_zone, buffer, | ||||||
| 					     buffer_size); | 					     buffer_size, true); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		goto err; | 		goto err; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Colin Cross
						Colin Cross