aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3819-drm-amdgpu-Fix-EEPROM-checksum-calculation.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3819-drm-amdgpu-Fix-EEPROM-checksum-calculation.patch')
-rw-r--r--meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3819-drm-amdgpu-Fix-EEPROM-checksum-calculation.patch225
1 files changed, 225 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3819-drm-amdgpu-Fix-EEPROM-checksum-calculation.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3819-drm-amdgpu-Fix-EEPROM-checksum-calculation.patch
new file mode 100644
index 00000000..f3243917
--- /dev/null
+++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3819-drm-amdgpu-Fix-EEPROM-checksum-calculation.patch
@@ -0,0 +1,225 @@
+From b4798087078ac666f89859028629d3d06efd736b Mon Sep 17 00:00:00 2001
+From: Andrey Grodzovsky <andrey.grodzovsky@amd.com>
+Date: Thu, 12 Sep 2019 17:16:32 -0400
+Subject: [PATCH 3819/4256] drm/amdgpu:Fix EEPROM checksum calculation.
+
+Fix checksum calculation after manually resetting the table.
+Unify reset and empty EEPROM init flow.
+Protect the table reset with lock.
+
+Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@amd.com>
+Reviewed-by: Guchun Chen <guchun.chen@amd.com>
+---
+ .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 164 +++++++++---------
+ 1 file changed, 86 insertions(+), 78 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
+index 11a8445cf734..d0e020ef73e3 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
+@@ -100,22 +100,100 @@ static int __update_table_header(struct amdgpu_ras_eeprom_control *control,
+ return ret;
+ }
+
+-static uint32_t __calc_hdr_byte_sum(struct amdgpu_ras_eeprom_control *control);
++
++
++static uint32_t __calc_hdr_byte_sum(struct amdgpu_ras_eeprom_control *control)
++{
++ int i;
++ uint32_t tbl_sum = 0;
++
++ /* Header checksum, skip checksum field in the calculation */
++ for (i = 0; i < sizeof(control->tbl_hdr) - sizeof(control->tbl_hdr.checksum); i++)
++ tbl_sum += *(((unsigned char *)&control->tbl_hdr) + i);
++
++ return tbl_sum;
++}
++
++static uint32_t __calc_recs_byte_sum(struct eeprom_table_record *records,
++ int num)
++{
++ int i, j;
++ uint32_t tbl_sum = 0;
++
++ /* Records checksum */
++ for (i = 0; i < num; i++) {
++ struct eeprom_table_record *record = &records[i];
++
++ for (j = 0; j < sizeof(*record); j++) {
++ tbl_sum += *(((unsigned char *)record) + j);
++ }
++ }
++
++ return tbl_sum;
++}
++
++static inline uint32_t __calc_tbl_byte_sum(struct amdgpu_ras_eeprom_control *control,
++ struct eeprom_table_record *records, int 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,
++ struct eeprom_table_record *records, int num,
++ uint32_t old_hdr_byte_sum)
++{
++ /*
++ * 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 -= old_hdr_byte_sum;
++ control->tbl_byte_sum += __calc_tbl_byte_sum(control, records, num);
++
++ control->tbl_hdr.checksum = 256 - (control->tbl_byte_sum % 256);
++}
++
++/* table sum mod 256 + checksum must equals 256 */
++static bool __validate_tbl_checksum(struct amdgpu_ras_eeprom_control *control,
++ struct eeprom_table_record *records, int num)
++{
++ control->tbl_byte_sum = __calc_tbl_byte_sum(control, records, num);
++
++ if (control->tbl_hdr.checksum + (control->tbl_byte_sum % 256) != 256) {
++ DRM_WARN("Checksum mismatch, checksum: %u ", control->tbl_hdr.checksum);
++ return false;
++ }
++
++ return true;
++}
+
+ int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control)
+ {
+ unsigned char buff[EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE] = { 0 };
+- struct amdgpu_device *adev = to_amdgpu_device(control);
+ struct amdgpu_ras_eeprom_table_header *hdr = &control->tbl_hdr;
++ int ret = 0;
++
++ mutex_lock(&control->tbl_mutex);
+
+ hdr->header = EEPROM_TABLE_HDR_VAL;
+ hdr->version = EEPROM_TABLE_VER;
+ hdr->first_rec_offset = EEPROM_RECORD_START;
+ hdr->tbl_size = EEPROM_TABLE_HEADER_SIZE;
+
+- adev->psp.ras.ras->eeprom_control.tbl_byte_sum =
+- __calc_hdr_byte_sum(&adev->psp.ras.ras->eeprom_control);
+- return __update_table_header(control, buff);
++ control->tbl_byte_sum = 0;
++ __update_tbl_checksum(control, NULL, 0, 0);
++ control->next_addr = EEPROM_RECORD_START;
++
++ ret = __update_table_header(control, buff);
++
++ mutex_unlock(&control->tbl_mutex);
++
++ return ret;
++
+ }
+
+ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control)
+@@ -159,6 +237,9 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control)
+ if (hdr->header == EEPROM_TABLE_HDR_VAL) {
+ control->num_recs = (hdr->tbl_size - EEPROM_TABLE_HEADER_SIZE) /
+ EEPROM_TABLE_RECORD_SIZE;
++ control->tbl_byte_sum = __calc_hdr_byte_sum(control);
++ control->next_addr = EEPROM_RECORD_START;
++
+ DRM_DEBUG_DRIVER("Found existing EEPROM table with %d records",
+ control->num_recs);
+
+@@ -168,9 +249,6 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control)
+ ret = amdgpu_ras_eeprom_reset_table(control);
+ }
+
+- /* Start inserting records from here */
+- adev->psp.ras.ras->eeprom_control.next_addr = EEPROM_RECORD_START;
+-
+ return ret == 1 ? 0 : -EIO;
+ }
+
+@@ -275,76 +353,6 @@ static uint32_t __correct_eeprom_dest_address(uint32_t curr_address)
+ return curr_address;
+ }
+
+-
+-static uint32_t __calc_hdr_byte_sum(struct amdgpu_ras_eeprom_control *control)
+-{
+- int i;
+- uint32_t tbl_sum = 0;
+-
+- /* Header checksum, skip checksum field in the calculation */
+- for (i = 0; i < sizeof(control->tbl_hdr) - sizeof(control->tbl_hdr.checksum); i++)
+- tbl_sum += *(((unsigned char *)&control->tbl_hdr) + i);
+-
+- return tbl_sum;
+-}
+-
+-static uint32_t __calc_recs_byte_sum(struct eeprom_table_record *records,
+- int num)
+-{
+- int i, j;
+- uint32_t tbl_sum = 0;
+-
+- /* Records checksum */
+- for (i = 0; i < num; i++) {
+- struct eeprom_table_record *record = &records[i];
+-
+- for (j = 0; j < sizeof(*record); j++) {
+- tbl_sum += *(((unsigned char *)record) + j);
+- }
+- }
+-
+- return tbl_sum;
+-}
+-
+-static inline uint32_t __calc_tbl_byte_sum(struct amdgpu_ras_eeprom_control *control,
+- struct eeprom_table_record *records, int 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,
+- struct eeprom_table_record *records, int num,
+- uint32_t old_hdr_byte_sum)
+-{
+- /*
+- * 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 -= old_hdr_byte_sum;
+- control->tbl_byte_sum += __calc_tbl_byte_sum(control, records, num);
+-
+- control->tbl_hdr.checksum = 256 - (control->tbl_byte_sum % 256);
+-}
+-
+-/* table sum mod 256 + checksum must equals 256 */
+-static bool __validate_tbl_checksum(struct amdgpu_ras_eeprom_control *control,
+- struct eeprom_table_record *records, int num)
+-{
+- control->tbl_byte_sum = __calc_tbl_byte_sum(control, records, num);
+-
+- if (control->tbl_hdr.checksum + (control->tbl_byte_sum % 256) != 256) {
+- DRM_WARN("Checksum mismatch, checksum: %u ", control->tbl_hdr.checksum);
+- return false;
+- }
+-
+- return true;
+-}
+-
+ int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control,
+ struct eeprom_table_record *records,
+ bool write,
+--
+2.17.1
+