Commit 803c6ebd authored by Luben Tuikov's avatar Luben Tuikov Committed by Alex Deucher

drm/amdgpu: Simplify RAS EEPROM checksum calculations

Rename update_table_header() to
write_table_header() as this function is actually
writing it to EEPROM.

Use kernel types; use u8 to carry around the
checksum, in order to take advantage of arithmetic
modulo 8-bits (256).

Tidy up to 80 columns.

When updating the checksum, just recalculate the
whole thing.

Cc: Alexander Deucher <Alexander.Deucher@amd.com>
Cc: Andrey Grodzovsky <Andrey.Grodzovsky@amd.com>
Signed-off-by: default avatarLuben Tuikov <luben.tuikov@amd.com>
Acked-by: default avatarAlexander Deucher <Alexander.Deucher@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent dce4400e
...@@ -141,7 +141,7 @@ static void __decode_table_header_from_buff(struct amdgpu_ras_eeprom_table_heade ...@@ -141,7 +141,7 @@ static void __decode_table_header_from_buff(struct amdgpu_ras_eeprom_table_heade
hdr->checksum = le32_to_cpu(pp[4]); hdr->checksum = le32_to_cpu(pp[4]);
} }
static int __update_table_header(struct amdgpu_ras_eeprom_control *control, static int __write_table_header(struct amdgpu_ras_eeprom_control *control,
unsigned char *buff) unsigned char *buff)
{ {
int ret = 0; int ret = 0;
...@@ -162,69 +162,74 @@ static int __update_table_header(struct amdgpu_ras_eeprom_control *control, ...@@ -162,69 +162,74 @@ static int __update_table_header(struct amdgpu_ras_eeprom_control *control,
return ret; return ret;
} }
static uint32_t __calc_hdr_byte_sum(struct amdgpu_ras_eeprom_control *control) static u8 __calc_hdr_byte_sum(const struct amdgpu_ras_eeprom_control *control)
{ {
int i; int i;
uint32_t tbl_sum = 0; u8 hdr_sum = 0;
u8 *p;
size_t sz;
/* Header checksum, skip checksum field in the calculation */ /* Header checksum, skip checksum field in the calculation */
for (i = 0; i < sizeof(control->tbl_hdr) - sizeof(control->tbl_hdr.checksum); i++) sz = sizeof(control->tbl_hdr) - sizeof(control->tbl_hdr.checksum);
tbl_sum += *(((unsigned char *)&control->tbl_hdr) + i); p = (u8 *) &control->tbl_hdr;
for (i = 0; i < sz; i++, p++)
hdr_sum += *p;
return tbl_sum; return hdr_sum;
} }
static uint32_t __calc_recs_byte_sum(struct eeprom_table_record *records, static u8 __calc_recs_byte_sum(const struct eeprom_table_record *record,
int num) const int num)
{ {
int i, j; int i, j;
uint32_t tbl_sum = 0; u8 tbl_sum = 0;
if (!record)
return 0;
/* Records checksum */ /* Records checksum */
for (i = 0; i < num; i++) { for (i = 0; i < num; i++) {
struct eeprom_table_record *record = &records[i]; u8 *p = (u8 *) &record[i];
for (j = 0; j < sizeof(*record); j++) { for (j = 0; j < sizeof(*record); j++, p++)
tbl_sum += *(((unsigned char *)record) + j); tbl_sum += *p;
}
} }
return tbl_sum; return tbl_sum;
} }
static inline uint32_t __calc_tbl_byte_sum(struct amdgpu_ras_eeprom_control *control, static inline u8
__calc_tbl_byte_sum(struct amdgpu_ras_eeprom_control *control,
struct eeprom_table_record *records, int num) struct eeprom_table_record *records, int num)
{ {
return __calc_hdr_byte_sum(control) + __calc_recs_byte_sum(records, num); return __calc_hdr_byte_sum(control) +
__calc_recs_byte_sum(records, num);
} }
/* Checksum = 256 -((sum of all table entries) mod 256) */
static void __update_tbl_checksum(struct amdgpu_ras_eeprom_control *control, static void __update_tbl_checksum(struct amdgpu_ras_eeprom_control *control,
struct eeprom_table_record *records, int num, struct eeprom_table_record *records, int num)
uint32_t old_hdr_byte_sum)
{ {
/* u8 v;
* This will update the table sum with new records.
*
* TODO: What happens when the EEPROM table is to be wrapped around
* and old records from start will get overridden.
*/
/* need to recalculate updated header byte sum */ control->tbl_byte_sum = __calc_tbl_byte_sum(control, records, num);
control->tbl_byte_sum -= old_hdr_byte_sum; /* Avoid 32-bit sign extension. */
control->tbl_byte_sum += __calc_tbl_byte_sum(control, records, num); v = -control->tbl_byte_sum;
control->tbl_hdr.checksum = v;
control->tbl_hdr.checksum = 256 - (control->tbl_byte_sum % 256);
} }
/* table sum mod 256 + checksum must equals 256 */ static bool __verify_tbl_checksum(struct amdgpu_ras_eeprom_control *control,
static bool __validate_tbl_checksum(struct amdgpu_ras_eeprom_control *control, struct eeprom_table_record *records,
struct eeprom_table_record *records, int num) int num)
{ {
u8 result;
control->tbl_byte_sum = __calc_tbl_byte_sum(control, records, num); control->tbl_byte_sum = __calc_tbl_byte_sum(control, records, num);
if (control->tbl_hdr.checksum + (control->tbl_byte_sum % 256) != 256) { result = (u8)control->tbl_hdr.checksum + control->tbl_byte_sum;
DRM_WARN("Checksum mismatch, checksum: %u ", control->tbl_hdr.checksum); if (result) {
DRM_WARN("RAS table checksum mismatch: stored:0x%02X wants:0x%02hhX",
control->tbl_hdr.checksum,
-control->tbl_byte_sum);
return false; return false;
} }
...@@ -243,7 +248,7 @@ static int amdgpu_ras_eeprom_correct_header_tag( ...@@ -243,7 +248,7 @@ static int amdgpu_ras_eeprom_correct_header_tag(
mutex_lock(&control->tbl_mutex); mutex_lock(&control->tbl_mutex);
hdr->header = header; hdr->header = header;
ret = __update_table_header(control, buff); ret = __write_table_header(control, buff);
mutex_unlock(&control->tbl_mutex); mutex_unlock(&control->tbl_mutex);
return ret; return ret;
...@@ -262,11 +267,9 @@ int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control) ...@@ -262,11 +267,9 @@ int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control)
hdr->first_rec_offset = RAS_RECORD_START; hdr->first_rec_offset = RAS_RECORD_START;
hdr->tbl_size = RAS_TABLE_HEADER_SIZE; hdr->tbl_size = RAS_TABLE_HEADER_SIZE;
control->tbl_byte_sum = 0; __update_tbl_checksum(control, NULL, 0);
__update_tbl_checksum(control, NULL, 0, 0);
control->next_addr = RAS_RECORD_START; control->next_addr = RAS_RECORD_START;
ret = __write_table_header(control, buff);
ret = __update_table_header(control, buff);
mutex_unlock(&control->tbl_mutex); mutex_unlock(&control->tbl_mutex);
...@@ -521,8 +524,6 @@ static int amdgpu_ras_eeprom_xfer(struct amdgpu_ras_eeprom_control *control, ...@@ -521,8 +524,6 @@ static int amdgpu_ras_eeprom_xfer(struct amdgpu_ras_eeprom_control *control,
} }
if (write) { if (write) {
uint32_t old_hdr_byte_sum = __calc_hdr_byte_sum(control);
/* /*
* Update table header with size and CRC and account for table * Update table header with size and CRC and account for table
* wrap around where the assumption is that we treat it as empty * wrap around where the assumption is that we treat it as empty
...@@ -537,10 +538,9 @@ static int amdgpu_ras_eeprom_xfer(struct amdgpu_ras_eeprom_control *control, ...@@ -537,10 +538,9 @@ static int amdgpu_ras_eeprom_xfer(struct amdgpu_ras_eeprom_control *control,
control->tbl_hdr.tbl_size = RAS_TABLE_HEADER_SIZE + control->tbl_hdr.tbl_size = RAS_TABLE_HEADER_SIZE +
control->num_recs * RAS_TABLE_RECORD_SIZE; control->num_recs * RAS_TABLE_RECORD_SIZE;
__update_tbl_checksum(control, records, num, old_hdr_byte_sum); __update_tbl_checksum(control, records, num);
__write_table_header(control, buffs);
__update_table_header(control, buffs); } else if (!__verify_tbl_checksum(control, records, num)) {
} else if (!__validate_tbl_checksum(control, records, num)) {
DRM_WARN("EEPROM Table checksum mismatch!"); DRM_WARN("EEPROM Table checksum mismatch!");
/* TODO Uncomment when EEPROM read/write is relliable */ /* TODO Uncomment when EEPROM read/write is relliable */
/* ret = -EIO; */ /* ret = -EIO; */
......
...@@ -48,7 +48,7 @@ struct amdgpu_ras_eeprom_control { ...@@ -48,7 +48,7 @@ struct amdgpu_ras_eeprom_control {
uint32_t next_addr; uint32_t next_addr;
unsigned int num_recs; unsigned int num_recs;
struct mutex tbl_mutex; struct mutex tbl_mutex;
uint32_t tbl_byte_sum; u8 tbl_byte_sum;
}; };
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment