From 901abf367d3eecd54f21829ced48c20f53c74c57 Mon Sep 17 00:00:00 2001 From: shaoyunl Date: Thu, 20 Jan 2022 10:39:41 -0500 Subject: drm/amdgpu: Disable FRU EEPROM access for SRIOV VF acces the EEPROM is blocked by security policy, we might need other way to get SKUs info for VF v2: squash in compilation fix from Luben Signed-off-by: shaoyunl Acked-by: Alex Deucher Reviewed-by: Kent Russell Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c index 2a786e788627..60e7e637eaa3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c @@ -40,6 +40,12 @@ static bool is_fru_eeprom_supported(struct amdgpu_device *adev) */ struct atom_context *atom_ctx = adev->mode_info.atom_context; + /* The i2c access is blocked on VF + * TODO: Need other way to get the info + */ + if (amdgpu_sriov_vf(adev)) + return false; + /* VBIOS is of the format ###-DXXXYY-##. For SKU identification, * we can use just the "DXXX" portion. If there were more models, we * could convert the 3 characters to a hex integer and use a switch -- cgit v1.2.3 From 2f60dd50769efcd6eedd0dc6b3f419cdd1f1f1fa Mon Sep 17 00:00:00 2001 From: Luben Tuikov Date: Wed, 19 Jan 2022 20:20:53 -0500 Subject: drm/amd: Expose the FRU SMU I2C bus Expose both SMU I2C buses. Some boards use the same bus for both the RAS and FRU EEPROMs and others use different buses. This enables the additional I2C bus and sets the right buses to use for RAS and FRU EEPROM access. Cc: Roy Sun Co-developed-by: Alex Deucher Signed-off-by: Luben Tuikov Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c | 6 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 14 ++-- drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c | 80 ++++++++++++++-------- drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.h | 6 +- drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 14 +++- .../drm/amd/pm/powerplay/smumgr/vega20_smumgr.c | 4 +- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 4 +- drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h | 4 +- drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 69 ++++++++++++++----- drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 68 +++++++++++++----- .../drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 71 ++++++++++++++----- drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c | 44 +++++++++--- drivers/gpu/drm/amd/pm/swsmu/smu_internal.h | 4 +- 13 files changed, 273 insertions(+), 115 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c index 60e7e637eaa3..40180648be38 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c @@ -75,7 +75,7 @@ static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr, { int ret, size; - ret = amdgpu_eeprom_read(&adev->pm.smu_i2c, addrptr, buff, 1); + ret = amdgpu_eeprom_read(adev->pm.fru_eeprom_i2c_bus, addrptr, buff, 1); if (ret < 1) { DRM_WARN("FRU: Failed to get size field"); return ret; @@ -86,7 +86,7 @@ static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr, */ size = buff[0] - I2C_PRODUCT_INFO_OFFSET; - ret = amdgpu_eeprom_read(&adev->pm.smu_i2c, addrptr + 1, buff, size); + ret = amdgpu_eeprom_read(adev->pm.fru_eeprom_i2c_bus, addrptr + 1, buff, size); if (ret < 1) { DRM_WARN("FRU: Failed to get data field"); return ret; @@ -109,7 +109,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev) offset = 0; /* If algo exists, it means that the i2c_adapter's initialized */ - if (!adev->pm.smu_i2c.algo) { + if (!adev->pm.fru_eeprom_i2c_bus || !adev->pm.fru_eeprom_i2c_bus->algo) { DRM_WARN("Cannot access FRU, EEPROM accessor not initialized"); return -ENODEV; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c index 05117eda105b..c09d047272b2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c @@ -194,7 +194,7 @@ static int __write_table_header(struct amdgpu_ras_eeprom_control *control) /* i2c may be unstable in gpu reset */ down_read(&adev->reset_sem); - res = amdgpu_eeprom_write(&adev->pm.smu_i2c, + res = amdgpu_eeprom_write(adev->pm.ras_eeprom_i2c_bus, control->i2c_address + control->ras_header_offset, buf, RAS_TABLE_HEADER_SIZE); @@ -389,7 +389,7 @@ static int __amdgpu_ras_eeprom_write(struct amdgpu_ras_eeprom_control *control, /* i2c may be unstable in gpu reset */ down_read(&adev->reset_sem); buf_size = num * RAS_TABLE_RECORD_SIZE; - res = amdgpu_eeprom_write(&adev->pm.smu_i2c, + res = amdgpu_eeprom_write(adev->pm.ras_eeprom_i2c_bus, control->i2c_address + RAS_INDEX_TO_OFFSET(control, fri), buf, buf_size); @@ -548,7 +548,7 @@ amdgpu_ras_eeprom_update_header(struct amdgpu_ras_eeprom_control *control) } down_read(&adev->reset_sem); - res = amdgpu_eeprom_read(&adev->pm.smu_i2c, + res = amdgpu_eeprom_read(adev->pm.ras_eeprom_i2c_bus, control->i2c_address + control->ras_record_offset, buf, buf_size); @@ -644,7 +644,7 @@ static int __amdgpu_ras_eeprom_read(struct amdgpu_ras_eeprom_control *control, /* i2c may be unstable in gpu reset */ down_read(&adev->reset_sem); buf_size = num * RAS_TABLE_RECORD_SIZE; - res = amdgpu_eeprom_read(&adev->pm.smu_i2c, + res = amdgpu_eeprom_read(adev->pm.ras_eeprom_i2c_bus, control->i2c_address + RAS_INDEX_TO_OFFSET(control, fri), buf, buf_size); @@ -1009,7 +1009,7 @@ static int __verify_ras_table_checksum(struct amdgpu_ras_eeprom_control *control return -ENOMEM; } - res = amdgpu_eeprom_read(&adev->pm.smu_i2c, + res = amdgpu_eeprom_read(adev->pm.ras_eeprom_i2c_bus, control->i2c_address + control->ras_header_offset, buf, buf_size); @@ -1045,7 +1045,7 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control, return 0; /* Verify i2c adapter is initialized */ - if (!adev->pm.smu_i2c.algo) + if (!adev->pm.ras_eeprom_i2c_bus || !adev->pm.ras_eeprom_i2c_bus->algo) return -ENOENT; if (!__get_eeprom_i2c_addr(adev, control)) @@ -1057,7 +1057,7 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control, mutex_init(&control->ras_tbl_mutex); /* Read the table header from EEPROM address */ - res = amdgpu_eeprom_read(&adev->pm.smu_i2c, + res = amdgpu_eeprom_read(adev->pm.ras_eeprom_i2c_bus, control->i2c_address + control->ras_header_offset, buf, RAS_TABLE_HEADER_SIZE); if (res < RAS_TABLE_HEADER_SIZE) { diff --git a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c index 73ffa8fde3df..87acb089cfcc 100644 --- a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c +++ b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c @@ -26,6 +26,7 @@ #include "smu_v11_0_i2c.h" #include "amdgpu.h" +#include "amdgpu_dpm.h" #include "soc15_common.h" #include #include @@ -43,11 +44,10 @@ #define I2C_X_RESTART BIT(31) -#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c)) - static void smu_v11_0_i2c_set_clock_gating(struct i2c_adapter *control, bool en) { - struct amdgpu_device *adev = to_amdgpu_device(control); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(control); + struct amdgpu_device *adev = smu_i2c->adev; uint32_t reg = RREG32_SOC15(SMUIO, 0, mmSMUIO_PWRMGT); reg = REG_SET_FIELD(reg, SMUIO_PWRMGT, i2c_clk_gate_en, en ? 1 : 0); @@ -75,7 +75,8 @@ static void smu_v11_0_i2c_set_clock_gating(struct i2c_adapter *control, bool en) static int smu_v11_0_i2c_enable(struct i2c_adapter *control, bool enable) { - struct amdgpu_device *adev = to_amdgpu_device(control); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(control); + struct amdgpu_device *adev = smu_i2c->adev; WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE, enable ? 1 : 0); @@ -100,7 +101,8 @@ static int smu_v11_0_i2c_enable(struct i2c_adapter *control, bool enable) static void smu_v11_0_i2c_clear_status(struct i2c_adapter *control) { - struct amdgpu_device *adev = to_amdgpu_device(control); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(control); + struct amdgpu_device *adev = smu_i2c->adev; /* do */ { RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_CLR_INTR); @@ -110,7 +112,8 @@ static void smu_v11_0_i2c_clear_status(struct i2c_adapter *control) static void smu_v11_0_i2c_configure(struct i2c_adapter *control) { - struct amdgpu_device *adev = to_amdgpu_device(control); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(control); + struct amdgpu_device *adev = smu_i2c->adev; uint32_t reg = 0; reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_SLAVE_DISABLE, 1); @@ -131,7 +134,8 @@ static void smu_v11_0_i2c_configure(struct i2c_adapter *control) static void smu_v11_0_i2c_set_clock(struct i2c_adapter *control) { - struct amdgpu_device *adev = to_amdgpu_device(control); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(control); + struct amdgpu_device *adev = smu_i2c->adev; /* * Standard mode speed, These values are taken from SMUIO MAS, @@ -154,7 +158,8 @@ static void smu_v11_0_i2c_set_clock(struct i2c_adapter *control) static void smu_v11_0_i2c_set_address(struct i2c_adapter *control, u16 address) { - struct amdgpu_device *adev = to_amdgpu_device(control); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(control); + struct amdgpu_device *adev = smu_i2c->adev; /* The IC_TAR::IC_TAR field is 10-bits wide. * It takes a 7-bit or 10-bit addresses as an address, @@ -165,7 +170,8 @@ static void smu_v11_0_i2c_set_address(struct i2c_adapter *control, u16 address) static uint32_t smu_v11_0_i2c_poll_tx_status(struct i2c_adapter *control) { - struct amdgpu_device *adev = to_amdgpu_device(control); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(control); + struct amdgpu_device *adev = smu_i2c->adev; uint32_t ret = I2C_OK; uint32_t reg, reg_c_tx_abrt_source; @@ -216,7 +222,8 @@ static uint32_t smu_v11_0_i2c_poll_tx_status(struct i2c_adapter *control) static uint32_t smu_v11_0_i2c_poll_rx_status(struct i2c_adapter *control) { - struct amdgpu_device *adev = to_amdgpu_device(control); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(control); + struct amdgpu_device *adev = smu_i2c->adev; uint32_t ret = I2C_OK; uint32_t reg_ic_status, reg_c_tx_abrt_source; @@ -262,7 +269,8 @@ static uint32_t smu_v11_0_i2c_transmit(struct i2c_adapter *control, u16 address, u8 *data, u32 numbytes, u32 i2c_flag) { - struct amdgpu_device *adev = to_amdgpu_device(control); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(control); + struct amdgpu_device *adev = smu_i2c->adev; u32 bytes_sent, reg, ret = I2C_OK; unsigned long timeout_counter; @@ -360,7 +368,8 @@ static uint32_t smu_v11_0_i2c_receive(struct i2c_adapter *control, u16 address, u8 *data, u32 numbytes, u32 i2c_flag) { - struct amdgpu_device *adev = to_amdgpu_device(control); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(control); + struct amdgpu_device *adev = smu_i2c->adev; uint32_t bytes_received, ret = I2C_OK; bytes_received = 0; @@ -431,7 +440,8 @@ static uint32_t smu_v11_0_i2c_receive(struct i2c_adapter *control, static void smu_v11_0_i2c_abort(struct i2c_adapter *control) { - struct amdgpu_device *adev = to_amdgpu_device(control); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(control); + struct amdgpu_device *adev = smu_i2c->adev; uint32_t reg = 0; /* Enable I2C engine; */ @@ -447,7 +457,8 @@ static void smu_v11_0_i2c_abort(struct i2c_adapter *control) static bool smu_v11_0_i2c_activity_done(struct i2c_adapter *control) { - struct amdgpu_device *adev = to_amdgpu_device(control); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(control); + struct amdgpu_device *adev = smu_i2c->adev; const uint32_t IDLE_TIMEOUT = 1024; uint32_t timeout_count = 0; @@ -508,7 +519,8 @@ static void smu_v11_0_i2c_init(struct i2c_adapter *control) static void smu_v11_0_i2c_fini(struct i2c_adapter *control) { - struct amdgpu_device *adev = to_amdgpu_device(control); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(control); + struct amdgpu_device *adev = smu_i2c->adev; u32 status, enable, en_stat; int res; @@ -543,7 +555,8 @@ static void smu_v11_0_i2c_fini(struct i2c_adapter *control) static bool smu_v11_0_i2c_bus_lock(struct i2c_adapter *control) { - struct amdgpu_device *adev = to_amdgpu_device(control); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(control); + struct amdgpu_device *adev = smu_i2c->adev; /* Send PPSMC_MSG_RequestI2CBus */ if (!amdgpu_dpm_smu_i2c_bus_access(adev, true)) @@ -554,7 +567,8 @@ static bool smu_v11_0_i2c_bus_lock(struct i2c_adapter *control) static bool smu_v11_0_i2c_bus_unlock(struct i2c_adapter *control) { - struct amdgpu_device *adev = to_amdgpu_device(control); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(control); + struct amdgpu_device *adev = smu_i2c->adev; /* Send PPSMC_MSG_ReleaseI2CBus */ if (!amdgpu_dpm_smu_i2c_bus_access(adev, false)) @@ -587,16 +601,17 @@ static uint32_t smu_v11_0_i2c_write_data(struct i2c_adapter *control, if (ret != I2C_OK) DRM_ERROR("WriteI2CData() - I2C error occurred :%x", ret); - + return ret; } static void lock_bus(struct i2c_adapter *i2c, unsigned int flags) { - struct amdgpu_device *adev = to_amdgpu_device(i2c); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(i2c); + struct amdgpu_device *adev = smu_i2c->adev; - mutex_lock(&adev->pm.smu_i2c_mutex); + mutex_lock(&smu_i2c->mutex); if (!smu_v11_0_i2c_bus_lock(i2c)) DRM_ERROR("Failed to lock the bus from SMU"); else @@ -611,13 +626,14 @@ static int trylock_bus(struct i2c_adapter *i2c, unsigned int flags) static void unlock_bus(struct i2c_adapter *i2c, unsigned int flags) { - struct amdgpu_device *adev = to_amdgpu_device(i2c); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(i2c); + struct amdgpu_device *adev = smu_i2c->adev; if (!smu_v11_0_i2c_bus_unlock(i2c)) DRM_ERROR("Failed to unlock the bus from SMU"); else adev->pm.bus_locked = false; - mutex_unlock(&adev->pm.smu_i2c_mutex); + mutex_unlock(&smu_i2c->mutex); } static const struct i2c_lock_operations smu_v11_0_i2c_i2c_lock_ops = { @@ -706,19 +722,26 @@ static const struct i2c_adapter_quirks smu_v11_0_i2c_control_quirks = { .flags = I2C_AQ_NO_ZERO_LEN, }; -int smu_v11_0_i2c_control_init(struct i2c_adapter *control) +int smu_v11_0_i2c_control_init(struct amdgpu_device *adev) { - struct amdgpu_device *adev = to_amdgpu_device(control); + struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[0]; + struct i2c_adapter *control = &smu_i2c->adapter; int res; - mutex_init(&adev->pm.smu_i2c_mutex); + smu_i2c->adev = adev; + smu_i2c->port = 0; + mutex_init(&smu_i2c->mutex); control->owner = THIS_MODULE; control->class = I2C_CLASS_HWMON; control->dev.parent = &adev->pdev->dev; control->algo = &smu_v11_0_i2c_algo; - snprintf(control->name, sizeof(control->name), "AMDGPU SMU"); + snprintf(control->name, sizeof(control->name), "AMDGPU SMU 0"); control->lock_ops = &smu_v11_0_i2c_i2c_lock_ops; control->quirks = &smu_v11_0_i2c_control_quirks; + i2c_set_adapdata(control, smu_i2c); + + adev->pm.ras_eeprom_i2c_bus = &adev->pm.smu_i2c[0].adapter; + adev->pm.fru_eeprom_i2c_bus = NULL; res = i2c_add_adapter(control); if (res) @@ -727,9 +750,12 @@ int smu_v11_0_i2c_control_init(struct i2c_adapter *control) return res; } -void smu_v11_0_i2c_control_fini(struct i2c_adapter *control) +void smu_v11_0_i2c_control_fini(struct amdgpu_device *adev) { + struct i2c_adapter *control = adev->pm.ras_eeprom_i2c_bus; + i2c_del_adapter(control); + adev->pm.ras_eeprom_i2c_bus = NULL; } /* diff --git a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.h b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.h index 44467c05f642..96ad14288a0c 100644 --- a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.h +++ b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.h @@ -26,9 +26,9 @@ #include -struct i2c_adapter; +struct amdgpu_device; -int smu_v11_0_i2c_control_init(struct i2c_adapter *control); -void smu_v11_0_i2c_control_fini(struct i2c_adapter *control); +int smu_v11_0_i2c_control_init(struct amdgpu_device *adev); +void smu_v11_0_i2c_control_fini(struct amdgpu_device *adev); #endif diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h index ba857ca75392..2766b88ecf96 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h @@ -284,6 +284,15 @@ enum ip_power_state { /* Used to mask smu debug modes */ #define SMU_DEBUG_HALT_ON_ERROR 0x1 +#define MAX_SMU_I2C_BUSES 2 + +struct amdgpu_smu_i2c_bus { + struct i2c_adapter adapter; + struct amdgpu_device *adev; + int port; + struct mutex mutex; +}; + struct amdgpu_pm { struct mutex mutex; u32 current_sclk; @@ -316,8 +325,9 @@ struct amdgpu_pm { uint32_t pp_feature; /* Used for I2C access to various EEPROMs on relevant ASICs */ - struct i2c_adapter smu_i2c; - struct mutex smu_i2c_mutex; + struct amdgpu_smu_i2c_bus smu_i2c[MAX_SMU_I2C_BUSES]; + struct i2c_adapter *ras_eeprom_i2c_bus; + struct i2c_adapter *fru_eeprom_i2c_bus; struct list_head pm_attr_list; atomic_t pwr_state[AMD_IP_BLOCK_TYPE_NUM]; diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega20_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega20_smumgr.c index 9ad26c285ecd..a5c95b180672 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega20_smumgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega20_smumgr.c @@ -520,7 +520,7 @@ static int vega20_smu_init(struct pp_hwmgr *hwmgr) priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].version = 0x01; priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].size = sizeof(DpmActivityMonitorCoeffInt_t); - ret = smu_v11_0_i2c_control_init(&adev->pm.smu_i2c); + ret = smu_v11_0_i2c_control_init(adev); if (ret) goto err4; @@ -558,7 +558,7 @@ static int vega20_smu_fini(struct pp_hwmgr *hwmgr) (struct vega20_smumgr *)(hwmgr->smu_backend); struct amdgpu_device *adev = hwmgr->adev; - smu_v11_0_i2c_control_fini(&adev->pm.smu_i2c); + smu_v11_0_i2c_control_fini(adev); if (priv) { amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PPTABLE].handle, diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 264eb09ccfd5..9861d70a5dad 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -886,7 +886,7 @@ static int smu_smc_table_sw_init(struct smu_context *smu) if (ret) return ret; - ret = smu_i2c_init(smu, &smu->adev->pm.smu_i2c); + ret = smu_i2c_init(smu); if (ret) return ret; @@ -897,7 +897,7 @@ static int smu_smc_table_sw_fini(struct smu_context *smu) { int ret; - smu_i2c_fini(smu, &smu->adev->pm.smu_i2c); + smu_i2c_fini(smu); smu_free_dummy_read_table(smu); diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h index 18f24db7d202..4c585241ef66 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h @@ -816,12 +816,12 @@ struct pptable_funcs { * other devices. The i2c's EEPROM also stores bad page tables on boards * with ECC. */ - int (*i2c_init)(struct smu_context *smu, struct i2c_adapter *control); + int (*i2c_init)(struct smu_context *smu); /** * @i2c_fini: Tear down i2c. */ - void (*i2c_fini)(struct smu_context *smu, struct i2c_adapter *control); + void (*i2c_fini)(struct smu_context *smu); /** * @get_unique_id: Get the GPU's unique id. Used for asset tracking. diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c index 2c78d04d5611..0cf385e8b4e9 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c @@ -25,6 +25,7 @@ #include #include "amdgpu.h" +#include "amdgpu_dpm.h" #include "amdgpu_smu.h" #include "atomfirmware.h" #include "amdgpu_atomfirmware.h" @@ -45,6 +46,7 @@ #include #include "amdgpu_ras.h" #include "smu_cmn.h" +#include "amdgpu_dpm.h" /* * DO NOT use these for err/warn/info/debug messages. @@ -56,8 +58,6 @@ #undef pr_info #undef pr_debug -#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c)) - #define ARCTURUS_FEA_MAP(smu_feature, arcturus_feature) \ [smu_feature] = {1, (arcturus_feature)} @@ -2062,7 +2062,8 @@ static int arcturus_dpm_set_vcn_enable(struct smu_context *smu, bool enable) static int arcturus_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msg, int num_msgs) { - struct amdgpu_device *adev = to_amdgpu_device(i2c_adap); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(i2c_adap); + struct amdgpu_device *adev = smu_i2c->adev; struct smu_context *smu = adev->powerplay.pp_handle; struct smu_table_context *smu_table = &smu->smu_table; struct smu_table *table = &smu_table->driver_table; @@ -2074,7 +2075,7 @@ static int arcturus_i2c_xfer(struct i2c_adapter *i2c_adap, if (!req) return -ENOMEM; - req->I2CcontrollerPort = 0; + req->I2CcontrollerPort = smu_i2c->port; req->I2CSpeed = I2C_SPEED_FAST_400K; req->SlaveAddress = msg[0].addr << 1; /* wants an 8-bit address */ dir = msg[0].flags & I2C_M_RD; @@ -2153,28 +2154,60 @@ static const struct i2c_adapter_quirks arcturus_i2c_control_quirks = { .max_comb_2nd_msg_len = MAX_SW_I2C_COMMANDS - 2, }; -static int arcturus_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control) +static int arcturus_i2c_control_init(struct smu_context *smu) { - struct amdgpu_device *adev = to_amdgpu_device(control); - int res; + struct amdgpu_device *adev = smu->adev; + int res, i; + + for (i = 0; i < MAX_SMU_I2C_BUSES; i++) { + struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i]; + struct i2c_adapter *control = &smu_i2c->adapter; + + smu_i2c->adev = adev; + smu_i2c->port = i; + mutex_init(&smu_i2c->mutex); + control->owner = THIS_MODULE; + control->class = I2C_CLASS_HWMON; + control->dev.parent = &adev->pdev->dev; + control->algo = &arcturus_i2c_algo; + control->quirks = &arcturus_i2c_control_quirks; + snprintf(control->name, sizeof(control->name), "AMDGPU SMU %d", i); + i2c_set_adapdata(control, smu_i2c); + + res = i2c_add_adapter(control); + if (res) { + DRM_ERROR("Failed to register hw i2c, err: %d\n", res); + goto Out_err; + } + } - control->owner = THIS_MODULE; - control->class = I2C_CLASS_HWMON; - control->dev.parent = &adev->pdev->dev; - control->algo = &arcturus_i2c_algo; - control->quirks = &arcturus_i2c_control_quirks; - snprintf(control->name, sizeof(control->name), "AMDGPU SMU"); + adev->pm.ras_eeprom_i2c_bus = &adev->pm.smu_i2c[0].adapter; + adev->pm.fru_eeprom_i2c_bus = &adev->pm.smu_i2c[1].adapter; - res = i2c_add_adapter(control); - if (res) - DRM_ERROR("Failed to register hw i2c, err: %d\n", res); + return 0; +Out_err: + for ( ; i >= 0; i--) { + struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i]; + struct i2c_adapter *control = &smu_i2c->adapter; + i2c_del_adapter(control); + } return res; } -static void arcturus_i2c_control_fini(struct smu_context *smu, struct i2c_adapter *control) +static void arcturus_i2c_control_fini(struct smu_context *smu) { - i2c_del_adapter(control); + struct amdgpu_device *adev = smu->adev; + int i; + + for (i = 0; i < MAX_SMU_I2C_BUSES; i++) { + struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i]; + struct i2c_adapter *control = &smu_i2c->adapter; + + i2c_del_adapter(control); + } + adev->pm.ras_eeprom_i2c_bus = NULL; + adev->pm.fru_eeprom_i2c_bus = NULL; } static void arcturus_get_unique_id(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index 84834c24a7e9..16a5d4d35981 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -27,6 +27,7 @@ #include #include #include "amdgpu.h" +#include "amdgpu_dpm.h" #include "amdgpu_smu.h" #include "atomfirmware.h" #include "amdgpu_atomfirmware.h" @@ -57,8 +58,6 @@ #undef pr_info #undef pr_debug -#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c)) - #define FEATURE_MASK(feature) (1ULL << feature) #define SMC_DPM_FEATURE ( \ FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT) | \ @@ -2746,7 +2745,8 @@ static ssize_t navi10_get_legacy_gpu_metrics(struct smu_context *smu, static int navi10_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msg, int num_msgs) { - struct amdgpu_device *adev = to_amdgpu_device(i2c_adap); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(i2c_adap); + struct amdgpu_device *adev = smu_i2c->adev; struct smu_context *smu = adev->powerplay.pp_handle; struct smu_table_context *smu_table = &smu->smu_table; struct smu_table *table = &smu_table->driver_table; @@ -2758,7 +2758,7 @@ static int navi10_i2c_xfer(struct i2c_adapter *i2c_adap, if (!req) return -ENOMEM; - req->I2CcontrollerPort = 0; + req->I2CcontrollerPort = smu_i2c->port; req->I2CSpeed = I2C_SPEED_FAST_400K; req->SlaveAddress = msg[0].addr << 1; /* wants an 8-bit address */ dir = msg[0].flags & I2C_M_RD; @@ -2836,28 +2836,60 @@ static const struct i2c_adapter_quirks navi10_i2c_control_quirks = { .max_comb_2nd_msg_len = MAX_SW_I2C_COMMANDS - 2, }; -static int navi10_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control) +static int navi10_i2c_control_init(struct smu_context *smu) { - struct amdgpu_device *adev = to_amdgpu_device(control); - int res; + struct amdgpu_device *adev = smu->adev; + int res, i; + + for (i = 0; i < MAX_SMU_I2C_BUSES; i++) { + struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i]; + struct i2c_adapter *control = &smu_i2c->adapter; + + smu_i2c->adev = adev; + smu_i2c->port = i; + mutex_init(&smu_i2c->mutex); + control->owner = THIS_MODULE; + control->class = I2C_CLASS_HWMON; + control->dev.parent = &adev->pdev->dev; + control->algo = &navi10_i2c_algo; + snprintf(control->name, sizeof(control->name), "AMDGPU SMU %d", i); + control->quirks = &navi10_i2c_control_quirks; + i2c_set_adapdata(control, smu_i2c); + + res = i2c_add_adapter(control); + if (res) { + DRM_ERROR("Failed to register hw i2c, err: %d\n", res); + goto Out_err; + } + } - control->owner = THIS_MODULE; - control->class = I2C_CLASS_HWMON; - control->dev.parent = &adev->pdev->dev; - control->algo = &navi10_i2c_algo; - snprintf(control->name, sizeof(control->name), "AMDGPU SMU"); - control->quirks = &navi10_i2c_control_quirks; + adev->pm.ras_eeprom_i2c_bus = &adev->pm.smu_i2c[0].adapter; + adev->pm.fru_eeprom_i2c_bus = &adev->pm.smu_i2c[1].adapter; - res = i2c_add_adapter(control); - if (res) - DRM_ERROR("Failed to register hw i2c, err: %d\n", res); + return 0; +Out_err: + for ( ; i >= 0; i--) { + struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i]; + struct i2c_adapter *control = &smu_i2c->adapter; + i2c_del_adapter(control); + } return res; } -static void navi10_i2c_control_fini(struct smu_context *smu, struct i2c_adapter *control) +static void navi10_i2c_control_fini(struct smu_context *smu) { - i2c_del_adapter(control); + struct amdgpu_device *adev = smu->adev; + int i; + + for (i = 0; i < MAX_SMU_I2C_BUSES; i++) { + struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i]; + struct i2c_adapter *control = &smu_i2c->adapter; + + i2c_del_adapter(control); + } + adev->pm.ras_eeprom_i2c_bus = NULL; + adev->pm.fru_eeprom_i2c_bus = NULL; } static ssize_t navi10_get_gpu_metrics(struct smu_context *smu, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index dcd35c68e59b..1c71ea97d06f 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -27,6 +27,7 @@ #include #include #include "amdgpu.h" +#include "amdgpu_dpm.h" #include "amdgpu_smu.h" #include "atomfirmware.h" #include "amdgpu_atomfirmware.h" @@ -59,8 +60,6 @@ #undef pr_info #undef pr_debug -#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c)) - #define FEATURE_MASK(feature) (1ULL << feature) #define SMC_DPM_FEATURE ( \ FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT) | \ @@ -3441,7 +3440,8 @@ static void sienna_cichlid_dump_pptable(struct smu_context *smu) static int sienna_cichlid_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msg, int num_msgs) { - struct amdgpu_device *adev = to_amdgpu_device(i2c_adap); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(i2c_adap); + struct amdgpu_device *adev = smu_i2c->adev; struct smu_context *smu = adev->powerplay.pp_handle; struct smu_table_context *smu_table = &smu->smu_table; struct smu_table *table = &smu_table->driver_table; @@ -3453,7 +3453,7 @@ static int sienna_cichlid_i2c_xfer(struct i2c_adapter *i2c_adap, if (!req) return -ENOMEM; - req->I2CcontrollerPort = 1; + req->I2CcontrollerPort = smu_i2c->port; req->I2CSpeed = I2C_SPEED_FAST_400K; req->SlaveAddress = msg[0].addr << 1; /* wants an 8-bit address */ dir = msg[0].flags & I2C_M_RD; @@ -3531,28 +3531,61 @@ static const struct i2c_adapter_quirks sienna_cichlid_i2c_control_quirks = { .max_comb_2nd_msg_len = MAX_SW_I2C_COMMANDS - 2, }; -static int sienna_cichlid_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control) +static int sienna_cichlid_i2c_control_init(struct smu_context *smu) { - struct amdgpu_device *adev = to_amdgpu_device(control); - int res; - - control->owner = THIS_MODULE; - control->class = I2C_CLASS_HWMON; - control->dev.parent = &adev->pdev->dev; - control->algo = &sienna_cichlid_i2c_algo; - snprintf(control->name, sizeof(control->name), "AMDGPU SMU"); - control->quirks = &sienna_cichlid_i2c_control_quirks; + struct amdgpu_device *adev = smu->adev; + int res, i; + + for (i = 0; i < MAX_SMU_I2C_BUSES; i++) { + struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i]; + struct i2c_adapter *control = &smu_i2c->adapter; + + smu_i2c->adev = adev; + smu_i2c->port = i; + mutex_init(&smu_i2c->mutex); + control->owner = THIS_MODULE; + control->class = I2C_CLASS_HWMON; + control->dev.parent = &adev->pdev->dev; + control->algo = &sienna_cichlid_i2c_algo; + snprintf(control->name, sizeof(control->name), "AMDGPU SMU %d", i); + control->quirks = &sienna_cichlid_i2c_control_quirks; + i2c_set_adapdata(control, smu_i2c); + + res = i2c_add_adapter(control); + if (res) { + DRM_ERROR("Failed to register hw i2c, err: %d\n", res); + goto Out_err; + } + } + /* assign the buses used for the FRU EEPROM and RAS EEPROM */ + /* XXX ideally this would be something in a vbios data table */ + adev->pm.ras_eeprom_i2c_bus = &adev->pm.smu_i2c[1].adapter; + adev->pm.fru_eeprom_i2c_bus = &adev->pm.smu_i2c[0].adapter; - res = i2c_add_adapter(control); - if (res) - DRM_ERROR("Failed to register hw i2c, err: %d\n", res); + return 0; +Out_err: + for ( ; i >= 0; i--) { + struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i]; + struct i2c_adapter *control = &smu_i2c->adapter; + i2c_del_adapter(control); + } return res; } -static void sienna_cichlid_i2c_control_fini(struct smu_context *smu, struct i2c_adapter *control) +static void sienna_cichlid_i2c_control_fini(struct smu_context *smu) { - i2c_del_adapter(control); + struct amdgpu_device *adev = smu->adev; + int i; + + for (i = 0; i < MAX_SMU_I2C_BUSES; i++) { + struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i]; + struct i2c_adapter *control = &smu_i2c->adapter; + + i2c_del_adapter(control); + } + adev->pm.ras_eeprom_i2c_bus = NULL; + adev->pm.fru_eeprom_i2c_bus = NULL; } static ssize_t sienna_cichlid_get_gpu_metrics(struct smu_context *smu, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c index 8c02adbf446a..450049bcedcb 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c @@ -25,6 +25,7 @@ #include #include "amdgpu.h" +#include "amdgpu_dpm.h" #include "amdgpu_smu.h" #include "atomfirmware.h" #include "amdgpu_atomfirmware.h" @@ -56,8 +57,6 @@ #undef pr_info #undef pr_debug -#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c)) - #define ALDEBARAN_FEA_MAP(smu_feature, aldebaran_feature) \ [smu_feature] = {1, (aldebaran_feature)} @@ -1465,7 +1464,8 @@ static bool aldebaran_is_dpm_running(struct smu_context *smu) static int aldebaran_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msg, int num_msgs) { - struct amdgpu_device *adev = to_amdgpu_device(i2c_adap); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(i2c_adap); + struct amdgpu_device *adev = smu_i2c->adev; struct smu_context *smu = adev->powerplay.pp_handle; struct smu_table_context *smu_table = &smu->smu_table; struct smu_table *table = &smu_table->driver_table; @@ -1477,7 +1477,7 @@ static int aldebaran_i2c_xfer(struct i2c_adapter *i2c_adap, if (!req) return -ENOMEM; - req->I2CcontrollerPort = 0; + req->I2CcontrollerPort = smu_i2c->port; req->I2CSpeed = I2C_SPEED_FAST_400K; req->SlaveAddress = msg[0].addr << 1; /* wants an 8-bit address */ dir = msg[0].flags & I2C_M_RD; @@ -1555,28 +1555,52 @@ static const struct i2c_adapter_quirks aldebaran_i2c_control_quirks = { .max_comb_2nd_msg_len = MAX_SW_I2C_COMMANDS - 2, }; -static int aldebaran_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control) +static int aldebaran_i2c_control_init(struct smu_context *smu) { - struct amdgpu_device *adev = to_amdgpu_device(control); + struct amdgpu_device *adev = smu->adev; + struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[0]; + struct i2c_adapter *control = &smu_i2c->adapter; int res; + smu_i2c->adev = adev; + smu_i2c->port = 0; + mutex_init(&smu_i2c->mutex); control->owner = THIS_MODULE; control->class = I2C_CLASS_SPD; control->dev.parent = &adev->pdev->dev; control->algo = &aldebaran_i2c_algo; - snprintf(control->name, sizeof(control->name), "AMDGPU SMU"); + snprintf(control->name, sizeof(control->name), "AMDGPU SMU 0"); control->quirks = &aldebaran_i2c_control_quirks; + i2c_set_adapdata(control, smu_i2c); res = i2c_add_adapter(control); - if (res) + if (res) { DRM_ERROR("Failed to register hw i2c, err: %d\n", res); + goto Out_err; + } + + adev->pm.ras_eeprom_i2c_bus = &adev->pm.smu_i2c[0].adapter; + + return 0; +Out_err: + i2c_del_adapter(control); return res; } -static void aldebaran_i2c_control_fini(struct smu_context *smu, struct i2c_adapter *control) +static void aldebaran_i2c_control_fini(struct smu_context *smu) { - i2c_del_adapter(control); + struct amdgpu_device *adev = smu->adev; + int i; + + for (i = 0; i < MAX_SMU_I2C_BUSES; i++) { + struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i]; + struct i2c_adapter *control = &smu_i2c->adapter; + + i2c_del_adapter(control); + } + adev->pm.ras_eeprom_i2c_bus = NULL; + adev->pm.fru_eeprom_i2c_bus = NULL; } static void aldebaran_get_unique_id(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h index 59f9cfff3d61..a290b5789195 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h @@ -78,8 +78,8 @@ #define smu_dump_pptable(smu) smu_ppt_funcs(dump_pptable, 0, smu) #define smu_update_pcie_parameters(smu, pcie_gen_cap, pcie_width_cap) smu_ppt_funcs(update_pcie_parameters, 0, smu, pcie_gen_cap, pcie_width_cap) #define smu_set_power_source(smu, power_src) smu_ppt_funcs(set_power_source, 0, smu, power_src) -#define smu_i2c_init(smu, control) smu_ppt_funcs(i2c_init, 0, smu, control) -#define smu_i2c_fini(smu, control) smu_ppt_funcs(i2c_fini, 0, smu, control) +#define smu_i2c_init(smu) smu_ppt_funcs(i2c_init, 0, smu) +#define smu_i2c_fini(smu) smu_ppt_funcs(i2c_fini, 0, smu) #define smu_get_unique_id(smu) smu_ppt_funcs(get_unique_id, 0, smu) #define smu_log_thermal_throttling(smu) smu_ppt_funcs(log_thermal_throttling_event, 0, smu) #define smu_get_asic_power_limits(smu, current, default, max) smu_ppt_funcs(get_power_limit, 0, smu, current, default, max) -- cgit v1.2.3 From 3ed893396b0132fa5a4d3fe3f9ba358678c6dba3 Mon Sep 17 00:00:00 2001 From: Luben Tuikov Date: Thu, 27 Jan 2022 13:49:30 -0500 Subject: drm/amd: Enable FRU EEPROM for Sienna Cichlid Enable the FRU EEPROM I2C bus for Sienna Cichlid server boards, for which it is enabled by checking the VBIOS version. Cc: Roy Sun Cc: Alex Deucher Signed-off-by: Luben Tuikov Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c index 40180648be38..ce5d5ee336a9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c @@ -46,7 +46,7 @@ static bool is_fru_eeprom_supported(struct amdgpu_device *adev) if (amdgpu_sriov_vf(adev)) return false; - /* VBIOS is of the format ###-DXXXYY-##. For SKU identification, + /* VBIOS is of the format ###-DXXXYYYY-##. For SKU identification, * we can use just the "DXXX" portion. If there were more models, we * could convert the 3 characters to a hex integer and use a switch * for ease/speed/readability. For now, 2 string comparisons are @@ -65,6 +65,12 @@ static bool is_fru_eeprom_supported(struct amdgpu_device *adev) case CHIP_ALDEBARAN: /* All Aldebaran SKUs have the FRU */ return true; + case CHIP_SIENNA_CICHLID: + if (strnstr(atom_ctx->vbios_version, "D603", + sizeof(atom_ctx->vbios_version))) + return true; + else + return false; default: return false; } -- cgit v1.2.3 From 3f1e2e9d9993a3b1e33661fee26566f091e01b2b Mon Sep 17 00:00:00 2001 From: Luben Tuikov Date: Thu, 3 Feb 2022 19:32:58 -0500 Subject: drm/amdgpu: Nerf "buff" to "buf" Buffer is abbreviated "buf" (buf-fer), not "buff" (buff-er). This is consistent with the rest of the kernel code. Cc: Kent Russell Cc: Alex Deucher Signed-off-by: Luben Tuikov Acked-by: Harish Kasiviswanathan Reviewed-by: Kent Russell Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c | 28 +++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c index ce5d5ee336a9..792337433a9e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c @@ -77,11 +77,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 *buf) { int ret, size; - ret = amdgpu_eeprom_read(adev->pm.fru_eeprom_i2c_bus, addrptr, buff, 1); + ret = amdgpu_eeprom_read(adev->pm.fru_eeprom_i2c_bus, addrptr, buf, 1); if (ret < 1) { DRM_WARN("FRU: Failed to get size field"); return ret; @@ -90,9 +90,9 @@ static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr, /* The size returned by the i2c requires subtraction of 0xC0 since the * size apparently always reports as 0xC0+actual size. */ - size = buff[0] - I2C_PRODUCT_INFO_OFFSET; + size = buf[0] - I2C_PRODUCT_INFO_OFFSET; - ret = amdgpu_eeprom_read(adev->pm.fru_eeprom_i2c_bus, addrptr + 1, buff, size); + ret = amdgpu_eeprom_read(adev->pm.fru_eeprom_i2c_bus, addrptr + 1, buf, size); if (ret < 1) { DRM_WARN("FRU: Failed to get data field"); return ret; @@ -103,7 +103,7 @@ 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[AMDGPU_PRODUCT_NAME_LEN+2]; + unsigned char buf[AMDGPU_PRODUCT_NAME_LEN+2]; u32 addrptr; int size, len; int offset = 2; @@ -133,7 +133,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev) * and the language field, so just start from 0xb, manufacturer size */ addrptr = FRU_EEPROM_MADDR + 0xb; - size = amdgpu_fru_read_eeprom(adev, addrptr, buff); + size = amdgpu_fru_read_eeprom(adev, addrptr, buf); if (size < 1) { DRM_ERROR("Failed to read FRU Manufacturer, ret:%d", size); return -EINVAL; @@ -143,7 +143,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev) * size field being 1 byte. This pattern continues below. */ addrptr += size + 1; - size = amdgpu_fru_read_eeprom(adev, addrptr, buff); + size = amdgpu_fru_read_eeprom(adev, addrptr, buf); if (size < 1) { DRM_ERROR("Failed to read FRU product name, ret:%d", size); return -EINVAL; @@ -155,12 +155,12 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev) AMDGPU_PRODUCT_NAME_LEN); len = AMDGPU_PRODUCT_NAME_LEN - 1; } - /* Start at 2 due to buff using fields 0 and 1 for the address */ - memcpy(adev->product_name, &buff[offset], len); + /* Start at 2 due to buf using fields 0 and 1 for the address */ + memcpy(adev->product_name, &buf[offset], len); adev->product_name[len] = '\0'; addrptr += size + 1; - size = amdgpu_fru_read_eeprom(adev, addrptr, buff); + size = amdgpu_fru_read_eeprom(adev, addrptr, buf); if (size < 1) { DRM_ERROR("Failed to read FRU product number, ret:%d", size); return -EINVAL; @@ -174,11 +174,11 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev) DRM_WARN("FRU Product Number is larger than 16 characters. This is likely a mistake"); len = sizeof(adev->product_number) - 1; } - memcpy(adev->product_number, &buff[offset], len); + memcpy(adev->product_number, &buf[offset], len); adev->product_number[len] = '\0'; addrptr += size + 1; - size = amdgpu_fru_read_eeprom(adev, addrptr, buff); + size = amdgpu_fru_read_eeprom(adev, addrptr, buf); if (size < 1) { DRM_ERROR("Failed to read FRU product version, ret:%d", size); @@ -186,7 +186,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev) } addrptr += size + 1; - size = amdgpu_fru_read_eeprom(adev, addrptr, buff); + size = amdgpu_fru_read_eeprom(adev, addrptr, buf); if (size < 1) { DRM_ERROR("Failed to read FRU serial number, ret:%d", size); @@ -201,7 +201,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev) DRM_WARN("FRU Serial Number is larger than 16 characters. This is likely a mistake"); len = sizeof(adev->serial) - 1; } - memcpy(adev->serial, &buff[offset], len); + memcpy(adev->serial, &buf[offset], len); adev->serial[len] = '\0'; return 0; -- cgit v1.2.3 From 3f3a24a0a3a58677d2b4f3c442d7a1be05afb123 Mon Sep 17 00:00:00 2001 From: Luben Tuikov Date: Thu, 3 Feb 2022 19:05:20 -0500 Subject: drm/amdgpu: Don't offset by 2 in FRU EEPROM Read buffers no longer expose the I2C address, and so we don't need to offset by two when we get the read data. Cc: Alex Deucher Cc: Kent Russell Cc: Andrey Grodzovsky Fixes: bd607166af7fe3 ("drm/amdgpu: Enable reading FRU chip via I2C v3") Signed-off-by: Luben Tuikov Acked-by: Harish Kasiviswanathan Reviewed-by: Kent Russell Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c index 792337433a9e..61c4e71e3998 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c @@ -103,17 +103,13 @@ 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 buf[AMDGPU_PRODUCT_NAME_LEN+2]; + unsigned char buf[AMDGPU_PRODUCT_NAME_LEN]; u32 addrptr; int size, len; - int offset = 2; if (!is_fru_eeprom_supported(adev)) return 0; - if (adev->asic_type == CHIP_ALDEBARAN) - offset = 0; - /* If algo exists, it means that the i2c_adapter's initialized */ if (!adev->pm.fru_eeprom_i2c_bus || !adev->pm.fru_eeprom_i2c_bus->algo) { DRM_WARN("Cannot access FRU, EEPROM accessor not initialized"); @@ -155,8 +151,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev) AMDGPU_PRODUCT_NAME_LEN); len = AMDGPU_PRODUCT_NAME_LEN - 1; } - /* Start at 2 due to buf using fields 0 and 1 for the address */ - memcpy(adev->product_name, &buf[offset], len); + memcpy(adev->product_name, buf, len); adev->product_name[len] = '\0'; addrptr += size + 1; @@ -174,7 +169,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev) DRM_WARN("FRU Product Number is larger than 16 characters. This is likely a mistake"); len = sizeof(adev->product_number) - 1; } - memcpy(adev->product_number, &buf[offset], len); + memcpy(adev->product_number, buf, len); adev->product_number[len] = '\0'; addrptr += size + 1; @@ -201,7 +196,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev) DRM_WARN("FRU Serial Number is larger than 16 characters. This is likely a mistake"); len = sizeof(adev->serial) - 1; } - memcpy(adev->serial, &buf[offset], len); + memcpy(adev->serial, buf, len); adev->serial[len] = '\0'; return 0; -- cgit v1.2.3 From 00b14ce075732edb2935d738de990e9aa96f1e08 Mon Sep 17 00:00:00 2001 From: Luben Tuikov Date: Thu, 3 Feb 2022 19:48:24 -0500 Subject: drm/amdgpu: Prevent random memory access in FRU code Prevent random memory access in the FRU EEPROM code by passing the size of the destination buffer to the reading routine, and reading no more than the size of the buffer. Cc: Kent Russell Cc: Alex Deucher Signed-off-by: Luben Tuikov Acked-by: Harish Kasiviswanathan Reviewed-by: Kent Russell Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c index 61c4e71e3998..ecada5eadfe3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c @@ -30,7 +30,6 @@ #include "amdgpu_eeprom.h" #define FRU_EEPROM_MADDR 0x60000 -#define I2C_PRODUCT_INFO_OFFSET 0xC0 static bool is_fru_eeprom_supported(struct amdgpu_device *adev) { @@ -77,9 +76,10 @@ 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 *buf) + unsigned char *buf, size_t buf_size) { - int ret, size; + int ret; + u8 size; ret = amdgpu_eeprom_read(adev->pm.fru_eeprom_i2c_bus, addrptr, buf, 1); if (ret < 1) { @@ -90,9 +90,11 @@ static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr, /* The size returned by the i2c requires subtraction of 0xC0 since the * size apparently always reports as 0xC0+actual size. */ - size = buf[0] - I2C_PRODUCT_INFO_OFFSET; + size = buf[0] & 0x3F; + size = min_t(size_t, size, buf_size); - ret = amdgpu_eeprom_read(adev->pm.fru_eeprom_i2c_bus, addrptr + 1, buf, size); + ret = amdgpu_eeprom_read(adev->pm.fru_eeprom_i2c_bus, addrptr + 1, + buf, size); if (ret < 1) { DRM_WARN("FRU: Failed to get data field"); return ret; @@ -129,7 +131,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev) * and the language field, so just start from 0xb, manufacturer size */ addrptr = FRU_EEPROM_MADDR + 0xb; - size = amdgpu_fru_read_eeprom(adev, addrptr, buf); + size = amdgpu_fru_read_eeprom(adev, addrptr, buf, sizeof(buf)); if (size < 1) { DRM_ERROR("Failed to read FRU Manufacturer, ret:%d", size); return -EINVAL; @@ -139,7 +141,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev) * size field being 1 byte. This pattern continues below. */ addrptr += size + 1; - size = amdgpu_fru_read_eeprom(adev, addrptr, buf); + size = amdgpu_fru_read_eeprom(adev, addrptr, buf, sizeof(buf)); if (size < 1) { DRM_ERROR("Failed to read FRU product name, ret:%d", size); return -EINVAL; @@ -155,7 +157,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev) adev->product_name[len] = '\0'; addrptr += size + 1; - size = amdgpu_fru_read_eeprom(adev, addrptr, buf); + size = amdgpu_fru_read_eeprom(adev, addrptr, buf, sizeof(buf)); if (size < 1) { DRM_ERROR("Failed to read FRU product number, ret:%d", size); return -EINVAL; @@ -173,7 +175,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev) adev->product_number[len] = '\0'; addrptr += size + 1; - size = amdgpu_fru_read_eeprom(adev, addrptr, buf); + size = amdgpu_fru_read_eeprom(adev, addrptr, buf, sizeof(buf)); if (size < 1) { DRM_ERROR("Failed to read FRU product version, ret:%d", size); @@ -181,7 +183,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev) } addrptr += size + 1; - size = amdgpu_fru_read_eeprom(adev, addrptr, buf); + size = amdgpu_fru_read_eeprom(adev, addrptr, buf, sizeof(buf)); if (size < 1) { DRM_ERROR("Failed to read FRU serial number, ret:%d", size); -- cgit v1.2.3