[PATCH 22/40] drm/amdgpu: RAS and FRU now use 19-bit I2C address

Alex Deucher alexdeucher at gmail.com
Thu Jun 10 20:59:22 UTC 2021


On Tue, Jun 8, 2021 at 5:40 PM Luben Tuikov <luben.tuikov at amd.com> wrote:
>
> Convert RAS and FRU code to use the 19-bit I2C
> memory address and remove all "slave_addr", as
> this is now absolved into the 19-bit address.
>
> Cc: Jean Delvare <jdelvare at suse.de>
> Cc: John Clements <john.clements at amd.com>
> Cc: Alexander Deucher <Alexander.Deucher at amd.com>
> Cc: Andrey Grodzovsky <Andrey.Grodzovsky at amd.com>
> Cc: Lijo Lazar <Lijo.Lazar at amd.com>
> Cc: Stanley Yang <Stanley.Yang at amd.com>
> Cc: Hawking Zhang <Hawking.Zhang at amd.com>
> Signed-off-by: Luben Tuikov <luben.tuikov at amd.com>

Acked-by: Alex Deucher <alexander.deucher at amd.com>

> ---
>  .../gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c    | 19 ++---
>  .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c    | 82 +++++++------------
>  .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h    |  2 +-
>  3 files changed, 39 insertions(+), 64 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
> index 2b854bc6ae34bb..69b9559f840ac3 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
> @@ -29,8 +29,8 @@
>  #include "amdgpu_fru_eeprom.h"
>  #include "amdgpu_eeprom.h"
>
> -#define I2C_PRODUCT_INFO_ADDR          0x56
> -#define I2C_PRODUCT_INFO_OFFSET                0xC0
> +#define FRU_EEPROM_MADDR        0x60000
> +#define I2C_PRODUCT_INFO_OFFSET 0xC0
>
>  static bool is_fru_eeprom_supported(struct amdgpu_device *adev)
>  {
> @@ -62,12 +62,11 @@ static bool is_fru_eeprom_supported(struct amdgpu_device *adev)
>  }
>
>  static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr,
> -                          unsigned char *buff)
> +                                 unsigned char *buff)
>  {
>         int ret, size;
>
> -       ret = amdgpu_eeprom_xfer(&adev->pm.smu_i2c, I2C_PRODUCT_INFO_ADDR,
> -                                addrptr, buff, 1, true);
> +       ret = amdgpu_eeprom_xfer(&adev->pm.smu_i2c, addrptr, buff, 1, true);
>         if (ret < 1) {
>                 DRM_WARN("FRU: Failed to get size field");
>                 return ret;
> @@ -78,8 +77,8 @@ static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr,
>          */
>         size = buff[0] - I2C_PRODUCT_INFO_OFFSET;
>
> -       ret = amdgpu_eeprom_xfer(&adev->pm.smu_i2c, I2C_PRODUCT_INFO_ADDR,
> -                                addrptr + 1, buff, size, true);
> +       ret = amdgpu_eeprom_xfer(&adev->pm.smu_i2c, addrptr + 1, buff, size,
> +                                true);
>         if (ret < 1) {
>                 DRM_WARN("FRU: Failed to get data field");
>                 return ret;
> @@ -91,8 +90,8 @@ static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr,
>  int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
>  {
>         unsigned char buff[34];
> -       int addrptr, size;
> -       int len;
> +       u32 addrptr;
> +       int size, len;
>
>         if (!is_fru_eeprom_supported(adev))
>                 return 0;
> @@ -115,7 +114,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
>          * Bytes 8-a are all 1-byte and refer to the size of the entire struct,
>          * and the language field, so just start from 0xb, manufacturer size
>          */
> -       addrptr = 0xb;
> +       addrptr = FRU_EEPROM_MADDR + 0xb;
>         size = amdgpu_fru_read_eeprom(adev, addrptr, buff);
>         if (size < 1) {
>                 DRM_ERROR("Failed to read FRU Manufacturer, ret:%d", size);
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
> index 2b981e96ce5b9e..f316fb11b16d9e 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
> @@ -28,11 +28,11 @@
>  #include "atom.h"
>  #include "amdgpu_eeprom.h"
>
> -#define EEPROM_I2C_TARGET_ADDR_VEGA20          0x50
> -#define EEPROM_I2C_TARGET_ADDR_ARCTURUS                0x54
> -#define EEPROM_I2C_TARGET_ADDR_ARCTURUS_D342   0x50
> -#define EEPROM_I2C_TARGET_ADDR_SIENNA_CICHLID   0x50
> -#define EEPROM_I2C_TARGET_ADDR_ALDEBARAN        0x50
> +#define EEPROM_I2C_MADDR_VEGA20         0x0
> +#define EEPROM_I2C_MADDR_ARCTURUS       0x40000
> +#define EEPROM_I2C_MADDR_ARCTURUS_D342  0x0
> +#define EEPROM_I2C_MADDR_SIENNA_CICHLID 0x0
> +#define EEPROM_I2C_MADDR_ALDEBARAN      0x0
>
>  /*
>   * The 2 macros bellow represent the actual size in bytes that
> @@ -58,7 +58,6 @@
>  #define EEPROM_HDR_START 0
>  #define EEPROM_RECORD_START (EEPROM_HDR_START + EEPROM_TABLE_HEADER_SIZE)
>  #define EEPROM_MAX_RECORD_NUM ((EEPROM_SIZE_BYTES - EEPROM_TABLE_HEADER_SIZE) / EEPROM_TABLE_RECORD_SIZE)
> -#define EEPROM_ADDR_MSB_MASK GENMASK(17, 8)
>
>  #define to_amdgpu_device(x) (container_of(x, struct amdgpu_ras, eeprom_control))->adev
>
> @@ -74,43 +73,43 @@ static bool __is_ras_eeprom_supported(struct amdgpu_device *adev)
>  }
>
>  static bool __get_eeprom_i2c_addr_arct(struct amdgpu_device *adev,
> -                                      uint16_t *i2c_addr)
> +                                      struct amdgpu_ras_eeprom_control *control)
>  {
>         struct atom_context *atom_ctx = adev->mode_info.atom_context;
>
> -       if (!i2c_addr || !atom_ctx)
> +       if (!control || !atom_ctx)
>                 return false;
>
>         if (strnstr(atom_ctx->vbios_version,
>                     "D342",
>                     sizeof(atom_ctx->vbios_version)))
> -               *i2c_addr = EEPROM_I2C_TARGET_ADDR_ARCTURUS_D342;
> +               control->i2c_address = EEPROM_I2C_MADDR_ARCTURUS_D342;
>         else
> -               *i2c_addr = EEPROM_I2C_TARGET_ADDR_ARCTURUS;
> +               control->i2c_address = EEPROM_I2C_MADDR_ARCTURUS;
>
>         return true;
>  }
>
>  static bool __get_eeprom_i2c_addr(struct amdgpu_device *adev,
> -                                 uint16_t *i2c_addr)
> +                                 struct amdgpu_ras_eeprom_control *control)
>  {
> -       if (!i2c_addr)
> +       if (!control)
>                 return false;
>
>         switch (adev->asic_type) {
>         case CHIP_VEGA20:
> -               *i2c_addr = EEPROM_I2C_TARGET_ADDR_VEGA20;
> +               control->i2c_address = EEPROM_I2C_MADDR_VEGA20;
>                 break;
>
>         case CHIP_ARCTURUS:
> -               return __get_eeprom_i2c_addr_arct(adev, i2c_addr);
> +               return __get_eeprom_i2c_addr_arct(adev, control);
>
>         case CHIP_SIENNA_CICHLID:
> -               *i2c_addr = EEPROM_I2C_TARGET_ADDR_SIENNA_CICHLID;
> +               control->i2c_address = EEPROM_I2C_MADDR_SIENNA_CICHLID;
>                 break;
>
>         case CHIP_ALDEBARAN:
> -               *i2c_addr = EEPROM_I2C_TARGET_ADDR_ALDEBARAN;
> +               control->i2c_address = EEPROM_I2C_MADDR_ALDEBARAN;
>                 break;
>
>         default:
> @@ -154,8 +153,9 @@ static int __update_table_header(struct amdgpu_ras_eeprom_control *control,
>
>         /* i2c may be unstable in gpu reset */
>         down_read(&adev->reset_sem);
> -       ret = amdgpu_eeprom_xfer(&adev->pm.smu_i2c, control->i2c_address,
> -                                EEPROM_HDR_START, buff, EEPROM_TABLE_HEADER_SIZE, false);
> +       ret = amdgpu_eeprom_xfer(&adev->pm.smu_i2c,
> +                                control->i2c_address + EEPROM_HDR_START,
> +                                buff, EEPROM_TABLE_HEADER_SIZE, false);
>         up_read(&adev->reset_sem);
>
>         if (ret < 1)
> @@ -277,7 +277,7 @@ int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control)
>  }
>
>  int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control,
> -                       bool *exceed_err_limit)
> +                          bool *exceed_err_limit)
>  {
>         int ret = 0;
>         struct amdgpu_device *adev = to_amdgpu_device(control);
> @@ -294,14 +294,15 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control,
>         if (!adev->pm.smu_i2c.algo)
>                 return -ENOENT;
>
> -       if (!__get_eeprom_i2c_addr(adev, &control->i2c_address))
> +       if (!__get_eeprom_i2c_addr(adev, control))
>                 return -EINVAL;
>
>         mutex_init(&control->tbl_mutex);
>
>         /* Read/Create table header from EEPROM address 0 */
> -       ret = amdgpu_eeprom_xfer(&adev->pm.smu_i2c, control->i2c_address,
> -                                EEPROM_HDR_START, buff, EEPROM_TABLE_HEADER_SIZE, true);
> +       ret = amdgpu_eeprom_xfer(&adev->pm.smu_i2c,
> +                                control->i2c_address + EEPROM_HDR_START,
> +                                buff, EEPROM_TABLE_HEADER_SIZE, true);
>         if (ret < 1) {
>                 DRM_ERROR("Failed to read EEPROM table header, ret:%d", ret);
>                 return ret;
> @@ -395,8 +396,6 @@ static void __decode_table_record_from_buff(struct amdgpu_ras_eeprom_control *co
>
>  /*
>   * When reaching end of EEPROM memory jump back to 0 record address
> - * When next record access will go beyond EEPROM page boundary modify bits A17/A8
> - * in I2C selector to go to next page
>   */
>  static uint32_t __correct_eeprom_dest_address(uint32_t curr_address)
>  {
> @@ -409,20 +408,6 @@ static uint32_t __correct_eeprom_dest_address(uint32_t curr_address)
>                 return EEPROM_RECORD_START;
>         }
>
> -       /*
> -        * To check if we overflow page boundary  compare next address with
> -        * current and see if bits 17/8 of the EEPROM address will change
> -        * If they do start from the next 256b page
> -        *
> -        * https://www.st.com/resource/en/datasheet/m24m02-dr.pdf sec. 5.1.2
> -        */
> -       if ((curr_address & EEPROM_ADDR_MSB_MASK) != (next_address & EEPROM_ADDR_MSB_MASK)) {
> -               DRM_DEBUG_DRIVER("Reached end of EEPROM memory page, jumping to next: %lx",
> -                               (next_address & EEPROM_ADDR_MSB_MASK));
> -
> -               return  (next_address & EEPROM_ADDR_MSB_MASK);
> -       }
> -
>         return curr_address;
>  }
>
> @@ -452,22 +437,20 @@ bool amdgpu_ras_eeprom_check_err_threshold(struct amdgpu_device *adev)
>  }
>
>  int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control,
> -                                           struct eeprom_table_record *records,
> -                                           bool write,
> -                                           int num)
> +                                    struct eeprom_table_record *records,
> +                                    bool write, int num)
>  {
>         int i, ret = 0;
>         unsigned char *buffs, *buff;
>         struct eeprom_table_record *record;
>         struct amdgpu_device *adev = to_amdgpu_device(control);
>         struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
> -       u16 slave_addr;
>
>         if (!__is_ras_eeprom_supported(adev))
>                 return 0;
>
>         buffs = kcalloc(num, EEPROM_ADDRESS_SIZE + EEPROM_TABLE_RECORD_SIZE,
> -                        GFP_KERNEL);
> +                       GFP_KERNEL);
>         if (!buffs)
>                 return -ENOMEM;
>
> @@ -507,22 +490,15 @@ int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control,
>
>                 control->next_addr = __correct_eeprom_dest_address(control->next_addr);
>
> -               /*
> -                * Update bits 16,17 of EEPROM address in I2C address by setting them
> -                * to bits 1,2 of Device address byte
> -                */
> -               slave_addr = control->i2c_address |
> -                       ((control->next_addr & EEPROM_ADDR_MSB_MASK) >> 15);
> -
>                 /* EEPROM table content is stored in LE format */
>                 if (write)
>                         __encode_table_record_to_buff(control, record, buff);
>
>                 /* i2c may be unstable in gpu reset */
>                 down_read(&adev->reset_sem);
> -               ret = amdgpu_eeprom_xfer(&adev->pm.smu_i2c, slave_addr,
> -                                        control->next_addr, buff,
> -                                        EEPROM_TABLE_RECORD_SIZE, write ? false : true);
> +               ret = amdgpu_eeprom_xfer(&adev->pm.smu_i2c,
> +                                        control->i2c_address + control->next_addr,
> +                                        buff, EEPROM_TABLE_RECORD_SIZE, !write);
>                 up_read(&adev->reset_sem);
>
>                 if (ret < 1) {
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h
> index 17872117097455..4c4c3d840a35c5 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h
> @@ -44,11 +44,11 @@ struct amdgpu_ras_eeprom_table_header {
>
>  struct amdgpu_ras_eeprom_control {
>         struct amdgpu_ras_eeprom_table_header tbl_hdr;
> +       u32 i2c_address; /* Base I2C 19-bit memory address */
>         uint32_t next_addr;
>         unsigned int num_recs;
>         struct mutex tbl_mutex;
>         uint32_t tbl_byte_sum;
> -       uint16_t i2c_address; // 8-bit represented address
>  };
>
>  /*
> --
> 2.32.0
>
> _______________________________________________
> amd-gfx mailing list
> amd-gfx at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx


More information about the amd-gfx mailing list