Commit 32bd3eb5 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-intel-gt-next-2024-09-06' of...

Merge tag 'drm-intel-gt-next-2024-09-06' of https://gitlab.freedesktop.org/drm/i915/kernel into drm-next

Driver Changes:

- Expose fan speed via hwmon (Raag)
- Correction to Wa_14019159160 on ARL (John H)
- Whitelist COMMON_SLICE_CHICKEN1 for UMD access on DG2/MTL/ARL (Dnyaneshwar)
- Do not attempt to load the GSC multiple times to avoid hanging GSC HW (Daniele)

- Populate /sys/class/drm/cardX/engines/ even if one engine fails (Andi)
- Use kmemdup_array instead of kmemdup for multiple allocation (Yu)
- Remove extra unlikely() (Hongbo)
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
From: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/Ztrfr_Wuurfa-3Rv@jlahtine-mobl.ger.corp.intel.com
parents 2ef8d63d 596a7f10
...@@ -75,3 +75,11 @@ Description: RO. Energy input of device or gt in microjoules. ...@@ -75,3 +75,11 @@ Description: RO. Energy input of device or gt in microjoules.
for the gt. for the gt.
Only supported for particular Intel i915 graphics platforms. Only supported for particular Intel i915 graphics platforms.
What: /sys/bus/pci/drivers/i915/.../hwmon/hwmon<i>/fan1_input
Date: November 2024
KernelVersion: 6.12
Contact: intel-gfx@lists.freedesktop.org
Description: RO. Fan speed of device in RPM.
Only supported for particular Intel i915 graphics platforms.
...@@ -825,7 +825,7 @@ static int eb_select_context(struct i915_execbuffer *eb) ...@@ -825,7 +825,7 @@ static int eb_select_context(struct i915_execbuffer *eb)
struct i915_gem_context *ctx; struct i915_gem_context *ctx;
ctx = i915_gem_context_lookup(eb->file->driver_priv, eb->args->rsvd1); ctx = i915_gem_context_lookup(eb->file->driver_priv, eb->args->rsvd1);
if (unlikely(IS_ERR(ctx))) if (IS_ERR(ctx))
return PTR_ERR(ctx); return PTR_ERR(ctx);
eb->gem_context = ctx; eb->gem_context = ctx;
......
...@@ -1553,6 +1553,8 @@ ...@@ -1553,6 +1553,8 @@
#define VLV_RENDER_C0_COUNT _MMIO(0x138118) #define VLV_RENDER_C0_COUNT _MMIO(0x138118)
#define VLV_MEDIA_C0_COUNT _MMIO(0x13811c) #define VLV_MEDIA_C0_COUNT _MMIO(0x13811c)
#define PCU_PWM_FAN_SPEED _MMIO(0x138140)
#define GEN12_RPSTAT1 _MMIO(0x1381b4) #define GEN12_RPSTAT1 _MMIO(0x1381b4)
#define GEN12_VOLTAGE_MASK REG_GENMASK(10, 0) #define GEN12_VOLTAGE_MASK REG_GENMASK(10, 0)
#define GEN12_CAGF_MASK REG_GENMASK(19, 11) #define GEN12_CAGF_MASK REG_GENMASK(19, 11)
......
...@@ -111,9 +111,8 @@ static void wa_init_finish(struct i915_wa_list *wal) ...@@ -111,9 +111,8 @@ static void wa_init_finish(struct i915_wa_list *wal)
{ {
/* Trim unused entries. */ /* Trim unused entries. */
if (!IS_ALIGNED(wal->count, WA_LIST_CHUNK)) { if (!IS_ALIGNED(wal->count, WA_LIST_CHUNK)) {
struct i915_wa *list = kmemdup(wal->list, struct i915_wa *list = kmemdup_array(wal->list, wal->count,
wal->count * sizeof(*list), sizeof(*list), GFP_KERNEL);
GFP_KERNEL);
if (list) { if (list) {
kfree(wal->list); kfree(wal->list);
...@@ -2072,7 +2071,7 @@ static void dg2_whitelist_build(struct intel_engine_cs *engine) ...@@ -2072,7 +2071,7 @@ static void dg2_whitelist_build(struct intel_engine_cs *engine)
case RENDER_CLASS: case RENDER_CLASS:
/* Required by recommended tuning setting (not a workaround) */ /* Required by recommended tuning setting (not a workaround) */
whitelist_mcr_reg(w, XEHP_COMMON_SLICE_CHICKEN3); whitelist_mcr_reg(w, XEHP_COMMON_SLICE_CHICKEN3);
whitelist_reg(w, GEN7_COMMON_SLICE_CHICKEN1);
break; break;
default: default:
break; break;
...@@ -2087,7 +2086,7 @@ static void xelpg_whitelist_build(struct intel_engine_cs *engine) ...@@ -2087,7 +2086,7 @@ static void xelpg_whitelist_build(struct intel_engine_cs *engine)
case RENDER_CLASS: case RENDER_CLASS:
/* Required by recommended tuning setting (not a workaround) */ /* Required by recommended tuning setting (not a workaround) */
whitelist_mcr_reg(w, XEHP_COMMON_SLICE_CHICKEN3); whitelist_mcr_reg(w, XEHP_COMMON_SLICE_CHICKEN3);
whitelist_reg(w, GEN7_COMMON_SLICE_CHICKEN1);
break; break;
default: default:
break; break;
......
...@@ -530,9 +530,8 @@ void intel_engines_add_sysfs(struct drm_i915_private *i915) ...@@ -530,9 +530,8 @@ void intel_engines_add_sysfs(struct drm_i915_private *i915)
err_object: err_object:
kobject_put(kobj); kobject_put(kobj);
err_engine: err_engine:
dev_err(kdev, "Failed to add sysfs engine '%s'\n", dev_warn(kdev, "Failed to add sysfs engine '%s'\n",
engine->name); engine->name);
break;
} }
} }
} }
...@@ -302,7 +302,7 @@ void intel_gsc_uc_load_start(struct intel_gsc_uc *gsc) ...@@ -302,7 +302,7 @@ void intel_gsc_uc_load_start(struct intel_gsc_uc *gsc)
{ {
struct intel_gt *gt = gsc_uc_to_gt(gsc); struct intel_gt *gt = gsc_uc_to_gt(gsc);
if (!intel_uc_fw_is_loadable(&gsc->fw)) if (!intel_uc_fw_is_loadable(&gsc->fw) || intel_uc_fw_is_in_error(&gsc->fw))
return; return;
if (intel_gsc_uc_fw_init_done(gsc)) if (intel_gsc_uc_fw_init_done(gsc))
......
...@@ -4507,7 +4507,7 @@ static void guc_default_vfuncs(struct intel_engine_cs *engine) ...@@ -4507,7 +4507,7 @@ static void guc_default_vfuncs(struct intel_engine_cs *engine)
/* Wa_16019325821 */ /* Wa_16019325821 */
/* Wa_14019159160 */ /* Wa_14019159160 */
if ((engine->class == COMPUTE_CLASS || engine->class == RENDER_CLASS) && if ((engine->class == COMPUTE_CLASS || engine->class == RENDER_CLASS) &&
IS_GFX_GT_IP_RANGE(engine->gt, IP_VER(12, 70), IP_VER(12, 71))) IS_GFX_GT_IP_RANGE(engine->gt, IP_VER(12, 70), IP_VER(12, 74)))
engine->flags |= I915_ENGINE_USES_WA_HOLD_SWITCHOUT; engine->flags |= I915_ENGINE_USES_WA_HOLD_SWITCHOUT;
/* /*
......
...@@ -258,6 +258,11 @@ static inline bool intel_uc_fw_is_running(struct intel_uc_fw *uc_fw) ...@@ -258,6 +258,11 @@ static inline bool intel_uc_fw_is_running(struct intel_uc_fw *uc_fw)
return __intel_uc_fw_status(uc_fw) == INTEL_UC_FIRMWARE_RUNNING; return __intel_uc_fw_status(uc_fw) == INTEL_UC_FIRMWARE_RUNNING;
} }
static inline bool intel_uc_fw_is_in_error(struct intel_uc_fw *uc_fw)
{
return intel_uc_fw_status_to_error(__intel_uc_fw_status(uc_fw)) != 0;
}
static inline bool intel_uc_fw_is_overridden(const struct intel_uc_fw *uc_fw) static inline bool intel_uc_fw_is_overridden(const struct intel_uc_fw *uc_fw)
{ {
return uc_fw->user_overridden; return uc_fw->user_overridden;
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <linux/hwmon.h> #include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h> #include <linux/hwmon-sysfs.h>
#include <linux/jiffies.h>
#include <linux/types.h> #include <linux/types.h>
#include "i915_drv.h" #include "i915_drv.h"
...@@ -36,6 +37,7 @@ struct hwm_reg { ...@@ -36,6 +37,7 @@ struct hwm_reg {
i915_reg_t pkg_rapl_limit; i915_reg_t pkg_rapl_limit;
i915_reg_t energy_status_all; i915_reg_t energy_status_all;
i915_reg_t energy_status_tile; i915_reg_t energy_status_tile;
i915_reg_t fan_speed;
}; };
struct hwm_energy_info { struct hwm_energy_info {
...@@ -43,11 +45,17 @@ struct hwm_energy_info { ...@@ -43,11 +45,17 @@ struct hwm_energy_info {
long accum_energy; /* Accumulated energy for energy1_input */ long accum_energy; /* Accumulated energy for energy1_input */
}; };
struct hwm_fan_info {
u32 reg_val_prev;
u64 time_prev;
};
struct hwm_drvdata { struct hwm_drvdata {
struct i915_hwmon *hwmon; struct i915_hwmon *hwmon;
struct intel_uncore *uncore; struct intel_uncore *uncore;
struct device *hwmon_dev; struct device *hwmon_dev;
struct hwm_energy_info ei; /* Energy info for energy1_input */ struct hwm_energy_info ei; /* Energy info for energy1_input */
struct hwm_fan_info fi; /* Fan info for fan1_input */
char name[12]; char name[12];
int gt_n; int gt_n;
bool reset_in_progress; bool reset_in_progress;
...@@ -276,6 +284,7 @@ static const struct hwmon_channel_info * const hwm_info[] = { ...@@ -276,6 +284,7 @@ static const struct hwmon_channel_info * const hwm_info[] = {
HWMON_CHANNEL_INFO(power, HWMON_P_MAX | HWMON_P_RATED_MAX | HWMON_P_CRIT), HWMON_CHANNEL_INFO(power, HWMON_P_MAX | HWMON_P_RATED_MAX | HWMON_P_CRIT),
HWMON_CHANNEL_INFO(energy, HWMON_E_INPUT), HWMON_CHANNEL_INFO(energy, HWMON_E_INPUT),
HWMON_CHANNEL_INFO(curr, HWMON_C_CRIT), HWMON_CHANNEL_INFO(curr, HWMON_C_CRIT),
HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT),
NULL NULL
}; };
...@@ -613,6 +622,69 @@ hwm_curr_write(struct hwm_drvdata *ddat, u32 attr, long val) ...@@ -613,6 +622,69 @@ hwm_curr_write(struct hwm_drvdata *ddat, u32 attr, long val)
} }
} }
static umode_t
hwm_fan_is_visible(const struct hwm_drvdata *ddat, u32 attr)
{
struct i915_hwmon *hwmon = ddat->hwmon;
if (attr == hwmon_fan_input && i915_mmio_reg_valid(hwmon->rg.fan_speed))
return 0444;
return 0;
}
static int
hwm_fan_input_read(struct hwm_drvdata *ddat, long *val)
{
struct i915_hwmon *hwmon = ddat->hwmon;
struct hwm_fan_info *fi = &ddat->fi;
u64 rotations, time_now, time;
intel_wakeref_t wakeref;
u32 reg_val;
int ret = 0;
wakeref = intel_runtime_pm_get(ddat->uncore->rpm);
mutex_lock(&hwmon->hwmon_lock);
reg_val = intel_uncore_read(ddat->uncore, hwmon->rg.fan_speed);
time_now = get_jiffies_64();
/*
* HW register value is accumulated count of pulses from
* PWM fan with the scale of 2 pulses per rotation.
*/
rotations = (reg_val - fi->reg_val_prev) / 2;
time = jiffies_delta_to_msecs(time_now - fi->time_prev);
if (unlikely(!time)) {
ret = -EAGAIN;
goto exit;
}
/*
* Calculate fan speed in RPM by time averaging two subsequent
* readings in minutes.
* RPM = number of rotations * msecs per minute / time in msecs
*/
*val = DIV_ROUND_UP_ULL(rotations * (MSEC_PER_SEC * 60), time);
fi->reg_val_prev = reg_val;
fi->time_prev = time_now;
exit:
mutex_unlock(&hwmon->hwmon_lock);
intel_runtime_pm_put(ddat->uncore->rpm, wakeref);
return ret;
}
static int
hwm_fan_read(struct hwm_drvdata *ddat, u32 attr, long *val)
{
if (attr == hwmon_fan_input)
return hwm_fan_input_read(ddat, val);
return -EOPNOTSUPP;
}
static umode_t static umode_t
hwm_is_visible(const void *drvdata, enum hwmon_sensor_types type, hwm_is_visible(const void *drvdata, enum hwmon_sensor_types type,
u32 attr, int channel) u32 attr, int channel)
...@@ -628,6 +700,8 @@ hwm_is_visible(const void *drvdata, enum hwmon_sensor_types type, ...@@ -628,6 +700,8 @@ hwm_is_visible(const void *drvdata, enum hwmon_sensor_types type,
return hwm_energy_is_visible(ddat, attr); return hwm_energy_is_visible(ddat, attr);
case hwmon_curr: case hwmon_curr:
return hwm_curr_is_visible(ddat, attr); return hwm_curr_is_visible(ddat, attr);
case hwmon_fan:
return hwm_fan_is_visible(ddat, attr);
default: default:
return 0; return 0;
} }
...@@ -648,6 +722,8 @@ hwm_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, ...@@ -648,6 +722,8 @@ hwm_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
return hwm_energy_read(ddat, attr, val); return hwm_energy_read(ddat, attr, val);
case hwmon_curr: case hwmon_curr:
return hwm_curr_read(ddat, attr, val); return hwm_curr_read(ddat, attr, val);
case hwmon_fan:
return hwm_fan_read(ddat, attr, val);
default: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
...@@ -739,12 +815,14 @@ hwm_get_preregistration_info(struct drm_i915_private *i915) ...@@ -739,12 +815,14 @@ hwm_get_preregistration_info(struct drm_i915_private *i915)
hwmon->rg.pkg_rapl_limit = PCU_PACKAGE_RAPL_LIMIT; hwmon->rg.pkg_rapl_limit = PCU_PACKAGE_RAPL_LIMIT;
hwmon->rg.energy_status_all = PCU_PACKAGE_ENERGY_STATUS; hwmon->rg.energy_status_all = PCU_PACKAGE_ENERGY_STATUS;
hwmon->rg.energy_status_tile = INVALID_MMIO_REG; hwmon->rg.energy_status_tile = INVALID_MMIO_REG;
hwmon->rg.fan_speed = PCU_PWM_FAN_SPEED;
} else { } else {
hwmon->rg.pkg_power_sku_unit = INVALID_MMIO_REG; hwmon->rg.pkg_power_sku_unit = INVALID_MMIO_REG;
hwmon->rg.pkg_power_sku = INVALID_MMIO_REG; hwmon->rg.pkg_power_sku = INVALID_MMIO_REG;
hwmon->rg.pkg_rapl_limit = INVALID_MMIO_REG; hwmon->rg.pkg_rapl_limit = INVALID_MMIO_REG;
hwmon->rg.energy_status_all = INVALID_MMIO_REG; hwmon->rg.energy_status_all = INVALID_MMIO_REG;
hwmon->rg.energy_status_tile = INVALID_MMIO_REG; hwmon->rg.energy_status_tile = INVALID_MMIO_REG;
hwmon->rg.fan_speed = INVALID_MMIO_REG;
} }
with_intel_runtime_pm(uncore->rpm, wakeref) { with_intel_runtime_pm(uncore->rpm, wakeref) {
...@@ -755,6 +833,16 @@ hwm_get_preregistration_info(struct drm_i915_private *i915) ...@@ -755,6 +833,16 @@ hwm_get_preregistration_info(struct drm_i915_private *i915)
if (i915_mmio_reg_valid(hwmon->rg.pkg_power_sku_unit)) if (i915_mmio_reg_valid(hwmon->rg.pkg_power_sku_unit))
val_sku_unit = intel_uncore_read(uncore, val_sku_unit = intel_uncore_read(uncore,
hwmon->rg.pkg_power_sku_unit); hwmon->rg.pkg_power_sku_unit);
/*
* Store the initial fan register value, so that we can use it for
* initial fan speed calculation.
*/
if (i915_mmio_reg_valid(hwmon->rg.fan_speed)) {
ddat->fi.reg_val_prev = intel_uncore_read(uncore,
hwmon->rg.fan_speed);
ddat->fi.time_prev = get_jiffies_64();
}
} }
hwmon->scl_shift_power = REG_FIELD_GET(PKG_PWR_UNIT, val_sku_unit); hwmon->scl_shift_power = REG_FIELD_GET(PKG_PWR_UNIT, val_sku_unit);
......
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