aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux-4.19/linux-yocto-4.19.8/1052-drm-amdgpu-Add-sysfs-file-for-PCIe-usage-v5.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux-4.19/linux-yocto-4.19.8/1052-drm-amdgpu-Add-sysfs-file-for-PCIe-usage-v5.patch')
-rw-r--r--meta-amd-bsp/recipes-kernel/linux-4.19/linux-yocto-4.19.8/1052-drm-amdgpu-Add-sysfs-file-for-PCIe-usage-v5.patch406
1 files changed, 406 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux-4.19/linux-yocto-4.19.8/1052-drm-amdgpu-Add-sysfs-file-for-PCIe-usage-v5.patch b/meta-amd-bsp/recipes-kernel/linux-4.19/linux-yocto-4.19.8/1052-drm-amdgpu-Add-sysfs-file-for-PCIe-usage-v5.patch
new file mode 100644
index 00000000..dc7a4b6e
--- /dev/null
+++ b/meta-amd-bsp/recipes-kernel/linux-4.19/linux-yocto-4.19.8/1052-drm-amdgpu-Add-sysfs-file-for-PCIe-usage-v5.patch
@@ -0,0 +1,406 @@
+From 3a273b57c95ad3c1bec1eedbf58d61ae56fe803c Mon Sep 17 00:00:00 2001
+From: Kent Russell <kent.russell@amd.com>
+Date: Thu, 3 Jan 2019 08:12:39 -0500
+Subject: [PATCH 1052/2940] drm/amdgpu: Add sysfs file for PCIe usage v5
+
+Add a sysfs file that reports the number of bytes transmitted and
+received in the last second. This can be used to approximate the PCIe
+bandwidth usage over the last second.
+
+v2: Clarify use of mps as estimation of bandwidth
+v3: Don't make the file on APUs
+v4: Early exit for APUs in the read function, change output to
+ display "packets-received packets-sent mps"
+v5: fix missing header for si (Alex)
+
+Signed-off-by: Kent Russell <kent.russell@amd.com>
+Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com>
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu.h | 4 +++
+ drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 36 +++++++++++++++++++
+ drivers/gpu/drm/amd/amdgpu/cik.c | 47 ++++++++++++++++++++++++
+ drivers/gpu/drm/amd/amdgpu/si.c | 48 +++++++++++++++++++++++++
+ drivers/gpu/drm/amd/amdgpu/soc15.c | 50 ++++++++++++++++++++++++++
+ drivers/gpu/drm/amd/amdgpu/vi.c | 47 ++++++++++++++++++++++++
+ 6 files changed, 232 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+index 301fcca202a7..7f8cba98d154 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+@@ -548,6 +548,9 @@ struct amdgpu_asic_funcs {
+ bool (*need_full_reset)(struct amdgpu_device *adev);
+ /* initialize doorbell layout for specific asic*/
+ void (*init_doorbell_index)(struct amdgpu_device *adev);
++ /* PCIe bandwidth usage */
++ void (*get_pcie_usage)(struct amdgpu_device *adev, uint64_t *count0,
++ uint64_t *count1);
+ };
+
+ /*
+@@ -1079,6 +1082,7 @@ int emu_soc_asic_init(struct amdgpu_device *adev);
+ #define amdgpu_asic_invalidate_hdp(adev, r) (adev)->asic_funcs->invalidate_hdp((adev), (r))
+ #define amdgpu_asic_need_full_reset(adev) (adev)->asic_funcs->need_full_reset((adev))
+ #define amdgpu_asic_init_doorbell_index(adev) (adev)->asic_funcs->init_doorbell_index((adev))
++#define amdgpu_asic_get_pcie_usage(adev, cnt0, cnt1) ((adev)->asic_funcs->get_pcie_usage((adev), (cnt0), (cnt1)))
+
+ /* Common functions */
+ bool amdgpu_device_should_recover_gpu(struct amdgpu_device *adev);
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
+index 6896dec97fc7..b38c06f0196e 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
+@@ -990,6 +990,31 @@ static ssize_t amdgpu_get_busy_percent(struct device *dev,
+ return snprintf(buf, PAGE_SIZE, "%d\n", value);
+ }
+
++/**
++ * DOC: pcie_bw
++ *
++ * The amdgpu driver provides a sysfs API for estimating how much data
++ * has been received and sent by the GPU in the last second through PCIe.
++ * The file pcie_bw is used for this.
++ * The Perf counters count the number of received and sent messages and return
++ * those values, as well as the maximum payload size of a PCIe packet (mps).
++ * Note that it is not possible to easily and quickly obtain the size of each
++ * packet transmitted, so we output the max payload size (mps) to allow for
++ * quick estimation of the PCIe bandwidth usage
++ */
++static ssize_t amdgpu_get_pcie_bw(struct device *dev,
++ struct device_attribute *attr,
++ char *buf)
++{
++ struct drm_device *ddev = dev_get_drvdata(dev);
++ struct amdgpu_device *adev = ddev->dev_private;
++ uint64_t count0, count1;
++
++ amdgpu_asic_get_pcie_usage(adev, &count0, &count1);
++ return snprintf(buf, PAGE_SIZE, "%llu %llu %i\n",
++ count0, count1, pcie_get_mps(adev->pdev));
++}
++
+ static DEVICE_ATTR(power_dpm_state, S_IRUGO | S_IWUSR, amdgpu_get_dpm_state, amdgpu_set_dpm_state);
+ static DEVICE_ATTR(power_dpm_force_performance_level, S_IRUGO | S_IWUSR,
+ amdgpu_get_dpm_forced_performance_level,
+@@ -1025,6 +1050,7 @@ static DEVICE_ATTR(pp_od_clk_voltage, S_IRUGO | S_IWUSR,
+ amdgpu_set_pp_od_clk_voltage);
+ static DEVICE_ATTR(gpu_busy_percent, S_IRUGO,
+ amdgpu_get_busy_percent, NULL);
++static DEVICE_ATTR(pcie_bw, S_IRUGO, amdgpu_get_pcie_bw, NULL);
+
+ static ssize_t amdgpu_hwmon_show_temp(struct device *dev,
+ struct device_attribute *attr,
+@@ -2108,6 +2134,14 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
+ "gpu_busy_level\n");
+ return ret;
+ }
++ /* PCIe Perf counters won't work on APU nodes */
++ if (adev->flags & !AMD_IS_APU) {
++ ret = device_create_file(adev->dev, &dev_attr_pcie_bw);
++ if (ret) {
++ DRM_ERROR("failed to create device file pcie_bw\n");
++ return ret;
++ }
++ }
+ ret = amdgpu_debugfs_pm_init(adev);
+ if (ret) {
+ DRM_ERROR("Failed to register debugfs file for dpm!\n");
+@@ -2147,6 +2181,8 @@ void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev)
+ device_remove_file(adev->dev,
+ &dev_attr_pp_od_clk_voltage);
+ device_remove_file(adev->dev, &dev_attr_gpu_busy_percent);
++ if (adev->flags & !AMD_IS_APU)
++ device_remove_file(adev->dev, &dev_attr_pcie_bw);
+ }
+
+ void amdgpu_pm_compute_clocks(struct amdgpu_device *adev)
+diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c
+index 71c50d8900e3..6277de51483f 100644
+--- a/drivers/gpu/drm/amd/amdgpu/cik.c
++++ b/drivers/gpu/drm/amd/amdgpu/cik.c
+@@ -1741,6 +1741,52 @@ static bool cik_need_full_reset(struct amdgpu_device *adev)
+ return true;
+ }
+
++static void cik_get_pcie_usage(struct amdgpu_device *adev, uint64_t *count0,
++ uint64_t *count1)
++{
++ uint32_t perfctr = 0;
++ uint64_t cnt0_of, cnt1_of;
++ int tmp;
++
++ /* This reports 0 on APUs, so return to avoid writing/reading registers
++ * that may or may not be different from their GPU counterparts
++ */
++ if (adev->flags & AMD_IS_APU)
++ return;
++
++ /* Set the 2 events that we wish to watch, defined above */
++ /* Reg 40 is # received msgs, Reg 104 is # of posted requests sent */
++ perfctr = REG_SET_FIELD(perfctr, PCIE_PERF_CNTL_TXCLK, EVENT0_SEL, 40);
++ perfctr = REG_SET_FIELD(perfctr, PCIE_PERF_CNTL_TXCLK, EVENT1_SEL, 104);
++
++ /* Write to enable desired perf counters */
++ WREG32_PCIE(ixPCIE_PERF_CNTL_TXCLK, perfctr);
++ /* Zero out and enable the perf counters
++ * Write 0x5:
++ * Bit 0 = Start all counters(1)
++ * Bit 2 = Global counter reset enable(1)
++ */
++ WREG32_PCIE(ixPCIE_PERF_COUNT_CNTL, 0x00000005);
++
++ msleep(1000);
++
++ /* Load the shadow and disable the perf counters
++ * Write 0x2:
++ * Bit 0 = Stop counters(0)
++ * Bit 1 = Load the shadow counters(1)
++ */
++ WREG32_PCIE(ixPCIE_PERF_COUNT_CNTL, 0x00000002);
++
++ /* Read register values to get any >32bit overflow */
++ tmp = RREG32_PCIE(ixPCIE_PERF_CNTL_TXCLK);
++ cnt0_of = REG_GET_FIELD(tmp, PCIE_PERF_CNTL_TXCLK, COUNTER0_UPPER);
++ cnt1_of = REG_GET_FIELD(tmp, PCIE_PERF_CNTL_TXCLK, COUNTER1_UPPER);
++
++ /* Get the values and add the overflow */
++ *count0 = RREG32_PCIE(ixPCIE_PERF_COUNT0_TXCLK) | (cnt0_of << 32);
++ *count1 = RREG32_PCIE(ixPCIE_PERF_COUNT1_TXCLK) | (cnt1_of << 32);
++}
++
+ static const struct amdgpu_asic_funcs cik_asic_funcs =
+ {
+ .read_disabled_bios = &cik_read_disabled_bios,
+@@ -1756,6 +1802,7 @@ static const struct amdgpu_asic_funcs cik_asic_funcs =
+ .invalidate_hdp = &cik_invalidate_hdp,
+ .need_full_reset = &cik_need_full_reset,
+ .init_doorbell_index = &legacy_doorbell_index_init,
++ .get_pcie_usage = &cik_get_pcie_usage,
+ };
+
+ static int cik_common_early_init(void *handle)
+diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c
+index f8408f88cd37..7d2a48727e76 100644
+--- a/drivers/gpu/drm/amd/amdgpu/si.c
++++ b/drivers/gpu/drm/amd/amdgpu/si.c
+@@ -47,6 +47,7 @@
+ #include "dce/dce_6_0_d.h"
+ #include "uvd/uvd_4_0_d.h"
+ #include "bif/bif_3_0_d.h"
++#include "bif/bif_3_0_sh_mask.h"
+
+ static const u32 tahiti_golden_registers[] =
+ {
+@@ -1323,6 +1324,52 @@ static void si_set_pcie_lanes(struct amdgpu_device *adev, int lanes)
+ WREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl);
+ }
+
++static void si_get_pcie_usage(struct amdgpu_device *adev, uint64_t *count0,
++ uint64_t *count1)
++{
++ uint32_t perfctr = 0;
++ uint64_t cnt0_of, cnt1_of;
++ int tmp;
++
++ /* This reports 0 on APUs, so return to avoid writing/reading registers
++ * that may or may not be different from their GPU counterparts
++ */
++ if (adev->flags & AMD_IS_APU)
++ return;
++
++ /* Set the 2 events that we wish to watch, defined above */
++ /* Reg 40 is # received msgs, Reg 104 is # of posted requests sent */
++ perfctr = REG_SET_FIELD(perfctr, PCIE_PERF_CNTL_TXCLK, EVENT0_SEL, 40);
++ perfctr = REG_SET_FIELD(perfctr, PCIE_PERF_CNTL_TXCLK, EVENT1_SEL, 104);
++
++ /* Write to enable desired perf counters */
++ WREG32_PCIE(ixPCIE_PERF_CNTL_TXCLK, perfctr);
++ /* Zero out and enable the perf counters
++ * Write 0x5:
++ * Bit 0 = Start all counters(1)
++ * Bit 2 = Global counter reset enable(1)
++ */
++ WREG32_PCIE(ixPCIE_PERF_COUNT_CNTL, 0x00000005);
++
++ msleep(1000);
++
++ /* Load the shadow and disable the perf counters
++ * Write 0x2:
++ * Bit 0 = Stop counters(0)
++ * Bit 1 = Load the shadow counters(1)
++ */
++ WREG32_PCIE(ixPCIE_PERF_COUNT_CNTL, 0x00000002);
++
++ /* Read register values to get any >32bit overflow */
++ tmp = RREG32_PCIE(ixPCIE_PERF_CNTL_TXCLK);
++ cnt0_of = REG_GET_FIELD(tmp, PCIE_PERF_CNTL_TXCLK, COUNTER0_UPPER);
++ cnt1_of = REG_GET_FIELD(tmp, PCIE_PERF_CNTL_TXCLK, COUNTER1_UPPER);
++
++ /* Get the values and add the overflow */
++ *count0 = RREG32_PCIE(ixPCIE_PERF_COUNT0_TXCLK) | (cnt0_of << 32);
++ *count1 = RREG32_PCIE(ixPCIE_PERF_COUNT1_TXCLK) | (cnt1_of << 32);
++}
++
+ static const struct amdgpu_asic_funcs si_asic_funcs =
+ {
+ .read_disabled_bios = &si_read_disabled_bios,
+@@ -1339,6 +1386,7 @@ static const struct amdgpu_asic_funcs si_asic_funcs =
+ .flush_hdp = &si_flush_hdp,
+ .invalidate_hdp = &si_invalidate_hdp,
+ .need_full_reset = &si_need_full_reset,
++ .get_pcie_usage = &si_get_pcie_usage,
+ };
+
+ static uint32_t si_get_rev_id(struct amdgpu_device *adev)
+diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c
+index 864e7db0c4a1..1db5ed12d450 100644
+--- a/drivers/gpu/drm/amd/amdgpu/soc15.c
++++ b/drivers/gpu/drm/amd/amdgpu/soc15.c
+@@ -43,6 +43,9 @@
+ #include "hdp/hdp_4_0_sh_mask.h"
+ #include "smuio/smuio_9_0_offset.h"
+ #include "smuio/smuio_9_0_sh_mask.h"
++#include "nbio/nbio_7_0_default.h"
++#include "nbio/nbio_7_0_sh_mask.h"
++#include "nbio/nbio_7_0_smn.h"
+
+ #include "soc15.h"
+ #include "soc15_common.h"
+@@ -601,6 +604,51 @@ static bool soc15_need_full_reset(struct amdgpu_device *adev)
+ /* change this when we implement soft reset */
+ return true;
+ }
++static void soc15_get_pcie_usage(struct amdgpu_device *adev, uint64_t *count0,
++ uint64_t *count1)
++{
++ uint32_t perfctr = 0;
++ uint64_t cnt0_of, cnt1_of;
++ int tmp;
++
++ /* This reports 0 on APUs, so return to avoid writing/reading registers
++ * that may or may not be different from their GPU counterparts
++ */
++ if (adev->flags & AMD_IS_APU)
++ return;
++
++ /* Set the 2 events that we wish to watch, defined above */
++ /* Reg 40 is # received msgs, Reg 104 is # of posted requests sent */
++ perfctr = REG_SET_FIELD(perfctr, PCIE_PERF_CNTL_TXCLK, EVENT0_SEL, 40);
++ perfctr = REG_SET_FIELD(perfctr, PCIE_PERF_CNTL_TXCLK, EVENT1_SEL, 104);
++
++ /* Write to enable desired perf counters */
++ WREG32_PCIE(smnPCIE_PERF_CNTL_TXCLK, perfctr);
++ /* Zero out and enable the perf counters
++ * Write 0x5:
++ * Bit 0 = Start all counters(1)
++ * Bit 2 = Global counter reset enable(1)
++ */
++ WREG32_PCIE(smnPCIE_PERF_COUNT_CNTL, 0x00000005);
++
++ msleep(1000);
++
++ /* Load the shadow and disable the perf counters
++ * Write 0x2:
++ * Bit 0 = Stop counters(0)
++ * Bit 1 = Load the shadow counters(1)
++ */
++ WREG32_PCIE(smnPCIE_PERF_COUNT_CNTL, 0x00000002);
++
++ /* Read register values to get any >32bit overflow */
++ tmp = RREG32_PCIE(smnPCIE_PERF_CNTL_TXCLK);
++ cnt0_of = REG_GET_FIELD(tmp, PCIE_PERF_CNTL_TXCLK, COUNTER0_UPPER);
++ cnt1_of = REG_GET_FIELD(tmp, PCIE_PERF_CNTL_TXCLK, COUNTER1_UPPER);
++
++ /* Get the values and add the overflow */
++ *count0 = RREG32_PCIE(smnPCIE_PERF_COUNT0_TXCLK) | (cnt0_of << 32);
++ *count1 = RREG32_PCIE(smnPCIE_PERF_COUNT1_TXCLK) | (cnt1_of << 32);
++}
+
+ static const struct amdgpu_asic_funcs soc15_asic_funcs =
+ {
+@@ -617,6 +665,7 @@ static const struct amdgpu_asic_funcs soc15_asic_funcs =
+ .invalidate_hdp = &soc15_invalidate_hdp,
+ .need_full_reset = &soc15_need_full_reset,
+ .init_doorbell_index = &vega10_doorbell_index_init,
++ .get_pcie_usage = &soc15_get_pcie_usage,
+ };
+
+ static const struct amdgpu_asic_funcs vega20_asic_funcs =
+@@ -634,6 +683,7 @@ static const struct amdgpu_asic_funcs vega20_asic_funcs =
+ .invalidate_hdp = &soc15_invalidate_hdp,
+ .need_full_reset = &soc15_need_full_reset,
+ .init_doorbell_index = &vega20_doorbell_index_init,
++ .get_pcie_usage = &soc15_get_pcie_usage,
+ };
+
+ static int soc15_common_early_init(void *handle)
+diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c
+index 0fc89d788956..a542e20bf846 100644
+--- a/drivers/gpu/drm/amd/amdgpu/vi.c
++++ b/drivers/gpu/drm/amd/amdgpu/vi.c
+@@ -941,6 +941,52 @@ static bool vi_need_full_reset(struct amdgpu_device *adev)
+ }
+ }
+
++static void vi_get_pcie_usage(struct amdgpu_device *adev, uint64_t *count0,
++ uint64_t *count1)
++{
++ uint32_t perfctr = 0;
++ uint64_t cnt0_of, cnt1_of;
++ int tmp;
++
++ /* This reports 0 on APUs, so return to avoid writing/reading registers
++ * that may or may not be different from their GPU counterparts
++ */
++ if (adev->flags & AMD_IS_APU)
++ return;
++
++ /* Set the 2 events that we wish to watch, defined above */
++ /* Reg 40 is # received msgs, Reg 104 is # of posted requests sent */
++ perfctr = REG_SET_FIELD(perfctr, PCIE_PERF_CNTL_TXCLK, EVENT0_SEL, 40);
++ perfctr = REG_SET_FIELD(perfctr, PCIE_PERF_CNTL_TXCLK, EVENT1_SEL, 104);
++
++ /* Write to enable desired perf counters */
++ WREG32_PCIE(ixPCIE_PERF_CNTL_TXCLK, perfctr);
++ /* Zero out and enable the perf counters
++ * Write 0x5:
++ * Bit 0 = Start all counters(1)
++ * Bit 2 = Global counter reset enable(1)
++ */
++ WREG32_PCIE(ixPCIE_PERF_COUNT_CNTL, 0x00000005);
++
++ msleep(1000);
++
++ /* Load the shadow and disable the perf counters
++ * Write 0x2:
++ * Bit 0 = Stop counters(0)
++ * Bit 1 = Load the shadow counters(1)
++ */
++ WREG32_PCIE(ixPCIE_PERF_COUNT_CNTL, 0x00000002);
++
++ /* Read register values to get any >32bit overflow */
++ tmp = RREG32_PCIE(ixPCIE_PERF_CNTL_TXCLK);
++ cnt0_of = REG_GET_FIELD(tmp, PCIE_PERF_CNTL_TXCLK, COUNTER0_UPPER);
++ cnt1_of = REG_GET_FIELD(tmp, PCIE_PERF_CNTL_TXCLK, COUNTER1_UPPER);
++
++ /* Get the values and add the overflow */
++ *count0 = RREG32_PCIE(ixPCIE_PERF_COUNT0_TXCLK) | (cnt0_of << 32);
++ *count1 = RREG32_PCIE(ixPCIE_PERF_COUNT1_TXCLK) | (cnt1_of << 32);
++}
++
+ static const struct amdgpu_asic_funcs vi_asic_funcs =
+ {
+ .read_disabled_bios = &vi_read_disabled_bios,
+@@ -956,6 +1002,7 @@ static const struct amdgpu_asic_funcs vi_asic_funcs =
+ .invalidate_hdp = &vi_invalidate_hdp,
+ .need_full_reset = &vi_need_full_reset,
+ .init_doorbell_index = &legacy_doorbell_index_init,
++ .get_pcie_usage = &vi_get_pcie_usage,
+ };
+
+ #define CZ_REV_BRISTOL(rev) \
+--
+2.17.1
+