diff --git a/Documentation/gpu/drm-ras.rst b/Documentation/gpu/drm-ras.rst index 70b246a78fc8..4636e68f5678 100644 --- a/Documentation/gpu/drm-ras.rst +++ b/Documentation/gpu/drm-ras.rst @@ -52,6 +52,8 @@ User space tools can: as a parameter. * Query specific error counter values with the ``get-error-counter`` command, using both ``node-id`` and ``error-id`` as parameters. +* Clear specific error counters with the ``clear-error-counter`` command, using both + ``node-id`` and ``error-id`` as parameters. YAML-based Interface -------------------- @@ -101,3 +103,9 @@ Example: Query an error counter for a given node sudo ynl --family drm_ras --do get-error-counter --json '{"node-id":0, "error-id":1}' {'error-id': 1, 'error-name': 'error_name1', 'error-value': 0} +Example: Clear an error counter for a given node + +.. code-block:: bash + + sudo ynl --family drm_ras --do clear-error-counter --json '{"node-id":0, "error-id":1}' + None diff --git a/Documentation/gpu/xe/index.rst b/Documentation/gpu/xe/index.rst index bc432c95d1a3..874ffcb6da3a 100644 --- a/Documentation/gpu/xe/index.rst +++ b/Documentation/gpu/xe/index.rst @@ -29,3 +29,4 @@ DG2, etc is provided to prototype the driver. xe_device xe-drm-usage-stats.rst xe_configfs + xe_gt_stats diff --git a/Documentation/gpu/xe/xe_gt_stats.rst b/Documentation/gpu/xe/xe_gt_stats.rst new file mode 100644 index 000000000000..5ff806abaddb --- /dev/null +++ b/Documentation/gpu/xe/xe_gt_stats.rst @@ -0,0 +1,11 @@ +.. SPDX-License-Identifier: (GPL-2.0+ OR MIT) + +================ +Xe GT Statistics +================ + +.. kernel-doc:: drivers/gpu/drm/xe/xe_gt_stats.c + :doc: Xe GT Statistics + +.. kernel-doc:: drivers/gpu/drm/xe/xe_gt_stats_types.h + :internal: diff --git a/Documentation/netlink/specs/drm_ras.yaml b/Documentation/netlink/specs/drm_ras.yaml index 79af25dac3c5..e113056f8c01 100644 --- a/Documentation/netlink/specs/drm_ras.yaml +++ b/Documentation/netlink/specs/drm_ras.yaml @@ -99,7 +99,7 @@ operations: flags: [admin-perm] do: request: - attributes: + attributes: &id-attrs - node-id - error-id reply: @@ -113,3 +113,14 @@ operations: - node-id reply: attributes: *errorinfo + - + name: clear-error-counter + doc: >- + Clear error counter for a given node. + The request includes the error-id and node-id of the + counter to be cleared. + attribute-set: error-counter-attrs + flags: [admin-perm] + do: + request: + attributes: *id-attrs diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c index 4b928fda5b12..7993e85c0566 100644 --- a/drivers/gpu/drm/drm_gpusvm.c +++ b/drivers/gpu/drm/drm_gpusvm.c @@ -1065,6 +1065,11 @@ drm_gpusvm_range_find_or_insert(struct drm_gpusvm *gpusvm, goto err_notifier_remove; } + if (vas->vm_flags & (VM_IO | VM_PFNMAP)) { + err = -EIO; + goto err_notifier_remove; + } + range = drm_gpusvm_range_find(notifier, fault_addr, fault_addr + 1); if (range) goto out_mmunlock; diff --git a/drivers/gpu/drm/drm_ras.c b/drivers/gpu/drm/drm_ras.c index b2fa5ab86d87..d6eab29a1394 100644 --- a/drivers/gpu/drm/drm_ras.c +++ b/drivers/gpu/drm/drm_ras.c @@ -26,7 +26,7 @@ * efficient lookup by ID. Nodes can be registered or unregistered * dynamically at runtime. * - * A Generic Netlink family `drm_ras` exposes two main operations to + * A Generic Netlink family `drm_ras` exposes the below operations to * userspace: * * 1. LIST_NODES: Dump all currently registered RAS nodes. @@ -37,6 +37,10 @@ * Returns all counters of a node if only Node ID is provided or specific * error counters. * + * 3. CLEAR_ERROR_COUNTER: Clear error counter of a given node. + * Userspace must provide Node ID, Error ID. + * Clears specific error counter of a node if supported. + * * Node registration: * * - drm_ras_node_register(): Registers a new node and assigns @@ -66,6 +70,8 @@ * operation, fetching all counters from a specific node. * - drm_ras_nl_get_error_counter_doit(): Implements the GET_ERROR_COUNTER doit * operation, fetching a counter value from a specific node. + * - drm_ras_nl_clear_error_counter_doit(): Implements the CLEAR_ERROR_COUNTER doit + * operation, clearing a counter value from a specific node. */ static DEFINE_XARRAY_ALLOC(drm_ras_xa); @@ -314,6 +320,41 @@ int drm_ras_nl_get_error_counter_doit(struct sk_buff *skb, return doit_reply_value(info, node_id, error_id); } +/** + * drm_ras_nl_clear_error_counter_doit() - Clear an error counter of a node + * @skb: Netlink message buffer + * @info: Generic Netlink info containing attributes of the request + * + * Extracts the node ID and error ID from the netlink attributes and + * clears the current value. + * + * Return: 0 on success, or negative errno on failure. + */ +int drm_ras_nl_clear_error_counter_doit(struct sk_buff *skb, + struct genl_info *info) +{ + struct drm_ras_node *node; + u32 node_id, error_id; + + if (!info->attrs || + GENL_REQ_ATTR_CHECK(info, DRM_RAS_A_ERROR_COUNTER_ATTRS_NODE_ID) || + GENL_REQ_ATTR_CHECK(info, DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_ID)) + return -EINVAL; + + node_id = nla_get_u32(info->attrs[DRM_RAS_A_ERROR_COUNTER_ATTRS_NODE_ID]); + error_id = nla_get_u32(info->attrs[DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_ID]); + + node = xa_load(&drm_ras_xa, node_id); + if (!node || !node->clear_error_counter) + return -ENOENT; + + if (error_id < node->error_counter_range.first || + error_id > node->error_counter_range.last) + return -EINVAL; + + return node->clear_error_counter(node, error_id); +} + /** * drm_ras_node_register() - Register a new RAS node * @node: Node structure to register diff --git a/drivers/gpu/drm/drm_ras_nl.c b/drivers/gpu/drm/drm_ras_nl.c index 16803d0c4a44..dea1c1b2494e 100644 --- a/drivers/gpu/drm/drm_ras_nl.c +++ b/drivers/gpu/drm/drm_ras_nl.c @@ -22,6 +22,12 @@ static const struct nla_policy drm_ras_get_error_counter_dump_nl_policy[DRM_RAS_ [DRM_RAS_A_ERROR_COUNTER_ATTRS_NODE_ID] = { .type = NLA_U32, }, }; +/* DRM_RAS_CMD_CLEAR_ERROR_COUNTER - do */ +static const struct nla_policy drm_ras_clear_error_counter_nl_policy[DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_ID + 1] = { + [DRM_RAS_A_ERROR_COUNTER_ATTRS_NODE_ID] = { .type = NLA_U32, }, + [DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_ID] = { .type = NLA_U32, }, +}; + /* Ops table for drm_ras */ static const struct genl_split_ops drm_ras_nl_ops[] = { { @@ -43,6 +49,13 @@ static const struct genl_split_ops drm_ras_nl_ops[] = { .maxattr = DRM_RAS_A_ERROR_COUNTER_ATTRS_NODE_ID, .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DUMP, }, + { + .cmd = DRM_RAS_CMD_CLEAR_ERROR_COUNTER, + .doit = drm_ras_nl_clear_error_counter_doit, + .policy = drm_ras_clear_error_counter_nl_policy, + .maxattr = DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_ID, + .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, + }, }; struct genl_family drm_ras_nl_family __ro_after_init = { diff --git a/drivers/gpu/drm/drm_ras_nl.h b/drivers/gpu/drm/drm_ras_nl.h index 06ccd9342773..a398643572a5 100644 --- a/drivers/gpu/drm/drm_ras_nl.h +++ b/drivers/gpu/drm/drm_ras_nl.h @@ -18,6 +18,8 @@ int drm_ras_nl_get_error_counter_doit(struct sk_buff *skb, struct genl_info *info); int drm_ras_nl_get_error_counter_dumpit(struct sk_buff *skb, struct netlink_callback *cb); +int drm_ras_nl_clear_error_counter_doit(struct sk_buff *skb, + struct genl_info *info); extern struct genl_family drm_ras_nl_family; diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index a47736613f6e..e3b044ee3e16 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "hsw_ips.h" #include "intel_atomic.h" @@ -46,7 +47,6 @@ #include "intel_pci_config.h" #include "intel_plane.h" #include "intel_psr.h" -#include "intel_step.h" #include "intel_vdsc.h" #include "skl_watermark.h" #include "skl_watermark_regs.h" diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index ebefa889bc8c..178074316a2c 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "icl_dsi.h" #include "intel_alpm.h" @@ -81,7 +82,6 @@ #include "intel_psr.h" #include "intel_quirks.h" #include "intel_snps_phy.h" -#include "intel_step.h" #include "intel_tc.h" #include "intel_vdsc.h" #include "intel_vdsc_regs.h" diff --git a/drivers/gpu/drm/i915/display/intel_display_device.c b/drivers/gpu/drm/i915/display/intel_display_device.c index be55ef8ea617..7260990038dd 100644 --- a/drivers/gpu/drm/i915/display/intel_display_device.c +++ b/drivers/gpu/drm/i915/display/intel_display_device.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "intel_cx0_phy_regs.h" #include "intel_de.h" @@ -21,7 +22,6 @@ #include "intel_display_types.h" #include "intel_display_wa.h" #include "intel_fbc.h" -#include "intel_step.h" __diag_push(); __diag_ignore_all("-Woverride-init", "Allow field initialization overrides for display info"); diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index ec96b141c74c..1a2de99ad78f 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -8,6 +8,7 @@ #include #include +#include #include "intel_backlight_regs.h" #include "intel_cdclk.h" @@ -30,7 +31,6 @@ #include "intel_pmdemand.h" #include "intel_pps_regs.h" #include "intel_snps_phy.h" -#include "intel_step.h" #include "skl_watermark.h" #include "skl_watermark_regs.h" #include "vlv_sideband.h" diff --git a/drivers/gpu/drm/i915/display/intel_display_wa.c b/drivers/gpu/drm/i915/display/intel_display_wa.c index 081a4092cd13..7d3d63a59882 100644 --- a/drivers/gpu/drm/i915/display/intel_display_wa.c +++ b/drivers/gpu/drm/i915/display/intel_display_wa.c @@ -4,12 +4,12 @@ */ #include +#include #include "intel_de.h" #include "intel_display_core.h" #include "intel_display_regs.h" #include "intel_display_wa.h" -#include "intel_step.h" static void gen11_display_wa_apply(struct intel_display *display) { diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index f9c8a7d79ab6..249dfd84b51a 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "intel_atomic.h" #include "intel_audio.h" @@ -56,7 +57,6 @@ #include "intel_link_bw.h" #include "intel_pfit.h" #include "intel_psr.h" -#include "intel_step.h" #include "intel_vdsc.h" #include "intel_vrr.h" #include "skl_scaler.h" diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 5f92391e4bdd..a9d88cecb338 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -25,6 +25,7 @@ #include #include +#include #include "bxt_dpio_phy_regs.h" #include "intel_cx0_phy.h" @@ -41,7 +42,6 @@ #include "intel_lt_phy.h" #include "intel_mg_phy_regs.h" #include "intel_pch_refclk.h" -#include "intel_step.h" #include "intel_tc.h" /** diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index ea0ce00c8474..55cb3ceb3523 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -44,6 +44,7 @@ #include #include #include +#include #include "i9xx_plane_regs.h" #include "intel_de.h" @@ -58,7 +59,6 @@ #include "intel_fbc_regs.h" #include "intel_frontbuffer.h" #include "intel_parent.h" -#include "intel_step.h" #define for_each_fbc_id(__display, __fbc_id) \ for ((__fbc_id) = INTEL_FBC_A; (__fbc_id) < I915_MAX_FBCS; (__fbc_id)++) \ diff --git a/drivers/gpu/drm/i915/display/intel_flipq.c b/drivers/gpu/drm/i915/display/intel_flipq.c index 253dc2e96d2d..333d28faf4ca 100644 --- a/drivers/gpu/drm/i915/display/intel_flipq.c +++ b/drivers/gpu/drm/i915/display/intel_flipq.c @@ -6,6 +6,7 @@ #include #include +#include #include "intel_crtc.h" #include "intel_de.h" @@ -17,7 +18,6 @@ #include "intel_dmc_regs.h" #include "intel_dsb.h" #include "intel_flipq.h" -#include "intel_step.h" #include "intel_vblank.h" #include "intel_vrr.h" diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 892eab4b6f92..9b4ff3b80b05 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "intel_connector.h" #include "intel_de.h" @@ -33,7 +34,6 @@ #include "intel_hdcp_regs.h" #include "intel_hdcp_shim.h" #include "intel_parent.h" -#include "intel_step.h" #define USE_HDCP_GSC(__display) (DISPLAY_VER(__display) >= 14) diff --git a/drivers/gpu/drm/i915/display/intel_pmdemand.c b/drivers/gpu/drm/i915/display/intel_pmdemand.c index 244806a26da3..7819b724795b 100644 --- a/drivers/gpu/drm/i915/display/intel_pmdemand.c +++ b/drivers/gpu/drm/i915/display/intel_pmdemand.c @@ -6,6 +6,7 @@ #include #include +#include #include "intel_atomic.h" #include "intel_bw.h" @@ -17,7 +18,6 @@ #include "intel_display_utils.h" #include "intel_display_wa.h" #include "intel_pmdemand.h" -#include "intel_step.h" #include "skl_watermark.h" struct pmdemand_params { diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index ab22a62fa55b..3b6e885de1c9 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "intel_alpm.h" #include "intel_atomic.h" @@ -51,7 +52,6 @@ #include "intel_psr_regs.h" #include "intel_quirks.h" #include "intel_snps_phy.h" -#include "intel_step.h" #include "intel_vblank.h" #include "intel_vdsc.h" #include "intel_vrr.h" diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 11ba42c67e3e..7a9d494334b5 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "intel_bo.h" #include "intel_color.h" @@ -25,7 +26,6 @@ #include "intel_plane.h" #include "intel_psr.h" #include "intel_psr_regs.h" -#include "intel_step.h" #include "skl_scaler.h" #include "skl_universal_plane.h" #include "skl_universal_plane_regs.h" diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index 03242e8b3d87..bd1697733335 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -113,6 +113,7 @@ xe-y += xe_bb.o \ xe_pxp_submit.o \ xe_query.o \ xe_range_fence.o \ + xe_ras.o \ xe_reg_sr.o \ xe_reg_whitelist.o \ xe_ring_ops.o \ @@ -124,6 +125,9 @@ xe-y += xe_bb.o \ xe_step.o \ xe_survivability_mode.o \ xe_sync.o \ + xe_sysctrl.o \ + xe_sysctrl_event.o \ + xe_sysctrl_mailbox.o \ xe_tile.o \ xe_tile_sysfs.o \ xe_tlb_inval.o \ diff --git a/drivers/gpu/drm/xe/abi/guc_klvs_abi.h b/drivers/gpu/drm/xe/abi/guc_klvs_abi.h index e33bd622ab44..644f5a4226d7 100644 --- a/drivers/gpu/drm/xe/abi/guc_klvs_abi.h +++ b/drivers/gpu/drm/xe/abi/guc_klvs_abi.h @@ -192,6 +192,13 @@ enum { * `GuC KLV`_ keys available for use with PF2GUC_UPDATE_VGT_POLICY. * * _`GUC_KLV_VGT_POLICY_SCHED_IF_IDLE` : 0x8001 + * [From 70.12.0] + * This config allows to update scheduling priority of PF and all VFs at once. + * Setting this policy to 0 updates all VFs scheduling priorities to LOW, and + * setting this policy to 1 updates all VFs scheduling priorities to NORMAL. + * Those changes will take effect on the next VF-Switch event. + * + * [Before 70.12.0] * This config sets whether strict scheduling is enabled whereby any VF * that doesn’t have work to submit is still allocated a fixed execution * time-slice to ensure active VFs execution is always consistent even @@ -496,6 +503,7 @@ enum xe_guc_klv_ids { GUC_WA_KLV_WAKE_POWER_DOMAINS_FOR_OUTBOUND_MMIO = 0x900a, GUC_WA_KLV_RESET_BB_STACK_PTR_ON_VF_SWITCH = 0x900b, GUC_WA_KLV_RESTORE_UNSAVED_MEDIA_CONTROL_REG = 0x900c, + GUC_WA_KLV_CLR_CS_INDIRECT_RING_STATE_IF_IDLE_AT_CTX_REG = 0x900e, }; #endif diff --git a/drivers/gpu/drm/xe/abi/xe_sysctrl_abi.h b/drivers/gpu/drm/xe/abi/xe_sysctrl_abi.h new file mode 100644 index 000000000000..4cbde267ac44 --- /dev/null +++ b/drivers/gpu/drm/xe/abi/xe_sysctrl_abi.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2026 Intel Corporation + */ + +#ifndef _XE_SYSCTRL_ABI_H_ +#define _XE_SYSCTRL_ABI_H_ + +#include + +/** + * DOC: System Controller ABI + * + * This header defines the Application Binary Interface (ABI) used by + * drm/xe to communicate with System Controller firmware on Intel Xe3p + * discrete GPU platforms. + * + * System Controller (sysctrl) is a firmware-managed entity on Intel + * dGPUs responsible for certain low-level platform management + * functions. + * + * Communication protocol: + * + * Communication uses a mailbox interface with messages composed of: + * + * - Application message header (struct xe_sysctrl_app_msg_hdr) + * containing group_id, command, and version + * - Variable-length, command-specific payload + * + * Message header format: + * + * The 32-bit application message header is packed as: + * + * - Bits [7:0] : Group ID identifying command group + * - Bits [15:8] : Command identifier within group + * - Bits [23:16] : Command version for interface compatibility + * - Bits [31:24] : Reserved, must be zero + * + * This header defines firmware ABI message formats and constants shared + * between driver and System Controller firmware. + */ + +/** + * struct xe_sysctrl_app_msg_hdr - Application layer message header + * @data: 32-bit header data + * + * Header structure for application-level messages. + */ +struct xe_sysctrl_app_msg_hdr { + u32 data; +} __packed; + +#define SYSCTRL_HDR_GROUP_ID_MASK GENMASK(7, 0) +#define SYSCTRL_HDR_COMMAND_MASK GENMASK(14, 8) +#define SYSCTRL_HDR_COMMAND_MAX 0x7f +#define SYSCTRL_HDR_IS_RESPONSE BIT(15) +#define SYSCTRL_HDR_RESERVED_MASK GENMASK(23, 16) +#define SYSCTRL_HDR_RESULT_MASK GENMASK(31, 24) + +#define APP_HDR_GROUP_ID_MASK GENMASK(7, 0) +#define APP_HDR_COMMAND_MASK GENMASK(15, 8) +#define APP_HDR_VERSION_MASK GENMASK(23, 16) +#define APP_HDR_RESERVED_MASK GENMASK(31, 24) + +#endif diff --git a/drivers/gpu/drm/xe/compat-i915-headers/intel_step.h b/drivers/gpu/drm/xe/compat-i915-headers/intel_step.h deleted file mode 100644 index 0eabe2866f5f..000000000000 --- a/drivers/gpu/drm/xe/compat-i915-headers/intel_step.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright © 2023 Intel Corporation - */ - -#ifndef __INTEL_STEP_H__ -#define __INTEL_STEP_H__ - -#include "xe_step_types.h" - -#define intel_step xe_step - -#endif /* __INTEL_STEP_H__ */ diff --git a/drivers/gpu/drm/xe/display/xe_fb_pin.c b/drivers/gpu/drm/xe/display/xe_fb_pin.c index e45a1e7a4670..d670a3cf1b84 100644 --- a/drivers/gpu/drm/xe/display/xe_fb_pin.c +++ b/drivers/gpu/drm/xe/display/xe_fb_pin.c @@ -14,6 +14,7 @@ #include "xe_device.h" #include "xe_display_vma.h" #include "xe_ggtt.h" +#include "xe_pat.h" #include "xe_pm.h" #include "xe_vram_types.h" @@ -24,7 +25,7 @@ write_dpt_rotated(struct xe_bo *bo, struct iosys_map *map, u32 *dpt_ofs, u32 bo_ struct xe_device *xe = xe_bo_device(bo); struct xe_ggtt *ggtt = xe_device_get_root_tile(xe)->mem.ggtt; u32 column, row; - u64 pte = xe_ggtt_encode_pte_flags(ggtt, bo, xe->pat.idx[XE_CACHE_NONE]); + u64 pte = xe_ggtt_encode_pte_flags(ggtt, bo, xe_cache_pat_idx(xe, XE_CACHE_NONE)); /* TODO: Maybe rewrite so we can traverse the bo addresses sequentially, * by writing dpt/ggtt in a different order? @@ -64,7 +65,7 @@ write_dpt_remapped_linear(struct xe_bo *bo, struct iosys_map *map, struct xe_device *xe = xe_bo_device(bo); struct xe_ggtt *ggtt = xe_device_get_root_tile(xe)->mem.ggtt; const u64 pte = xe_ggtt_encode_pte_flags(ggtt, bo, - xe->pat.idx[XE_CACHE_NONE]); + xe_cache_pat_idx(xe, XE_CACHE_NONE)); unsigned int offset = plane->offset * XE_PAGE_SIZE; unsigned int size = plane->size; @@ -87,7 +88,7 @@ write_dpt_remapped_tiled(struct xe_bo *bo, struct iosys_map *map, struct xe_device *xe = xe_bo_device(bo); struct xe_ggtt *ggtt = xe_device_get_root_tile(xe)->mem.ggtt; const u64 pte = xe_ggtt_encode_pte_flags(ggtt, bo, - xe->pat.idx[XE_CACHE_NONE]); + xe_cache_pat_idx(xe, XE_CACHE_NONE)); unsigned int offset, column, row; for (row = 0; row < plane->height; row++) { @@ -190,7 +191,7 @@ static int __xe_pin_fb_vma_dpt(const struct intel_framebuffer *fb, return PTR_ERR(dpt); if (view->type == I915_GTT_VIEW_NORMAL) { - u64 pte = xe_ggtt_encode_pte_flags(ggtt, bo, xe->pat.idx[XE_CACHE_NONE]); + u64 pte = xe_ggtt_encode_pte_flags(ggtt, bo, xe_cache_pat_idx(xe, XE_CACHE_NONE)); u32 x; for (x = 0; x < size / XE_PAGE_SIZE; x++) { @@ -306,7 +307,7 @@ static int __xe_pin_fb_vma_ggtt(const struct intel_framebuffer *fb, /* display uses tiles instead of bytes here, so convert it back.. */ size = intel_rotation_info_size(&view->rotated) * XE_PAGE_SIZE; - pte = xe_ggtt_encode_pte_flags(ggtt, bo, xe->pat.idx[XE_CACHE_NONE]); + pte = xe_ggtt_encode_pte_flags(ggtt, bo, xe_cache_pat_idx(xe, XE_CACHE_NONE)); vma->node = xe_ggtt_insert_node_transform(ggtt, bo, pte, ALIGN(size, align), align, view->type == I915_GTT_VIEW_NORMAL ? diff --git a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c index 29c72aa4b0d2..33494b86205d 100644 --- a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c +++ b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c @@ -37,9 +37,17 @@ static bool intel_hdcp_gsc_check_status(struct drm_device *drm) struct xe_device *xe = to_xe_device(drm); struct xe_tile *tile = xe_device_get_root_tile(xe); struct xe_gt *gt = tile->media_gt; - struct xe_gsc *gsc = >->uc.gsc; + struct xe_gsc *gsc; - if (!gsc || !xe_uc_fw_is_available(&gsc->fw)) { + if (!gt) { + drm_dbg_kms(&xe->drm, + "not checking GSC status for HDCP2.x: media GT not present or disabled\n"); + return false; + } + + gsc = >->uc.gsc; + + if (!xe_uc_fw_is_available(&gsc->fw)) { drm_dbg_kms(&xe->drm, "GSC Components not ready for HDCP2.x\n"); return false; diff --git a/drivers/gpu/drm/xe/regs/xe_engine_regs.h b/drivers/gpu/drm/xe/regs/xe_engine_regs.h index 1b4a7e9a703d..c4c879a9e555 100644 --- a/drivers/gpu/drm/xe/regs/xe_engine_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_engine_regs.h @@ -165,9 +165,9 @@ #define CTX_CTRL_INHIBIT_SYN_CTX_SWITCH REG_BIT(3) #define CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT REG_BIT(0) -#define RING_MODE(base) XE_REG((base) + 0x29c) -#define GFX_DISABLE_LEGACY_MODE REG_BIT(3) +#define GFX_MODE(base) XE_REG((base) + 0x29c, XE_REG_OPTION_MASKED) #define GFX_MSIX_INTERRUPT_ENABLE REG_BIT(13) +#define GFX_DISABLE_LEGACY_MODE REG_BIT(3) #define RING_CSMQDEBUG(base) XE_REG((base) + 0x2b0) @@ -176,7 +176,6 @@ #define RING_TIMESTAMP_UDW(base) XE_REG((base) + 0x358 + 4) #define RING_VALID_MASK 0x00000001 #define RING_VALID 0x00000001 -#define STOP_RING REG_BIT(8) #define RING_CTX_TIMESTAMP(base) XE_REG((base) + 0x3a8) #define RING_CTX_TIMESTAMP_UDW(base) XE_REG((base) + 0x3ac) diff --git a/drivers/gpu/drm/xe/regs/xe_gt_regs.h b/drivers/gpu/drm/xe/regs/xe_gt_regs.h index 9c88ca3ce768..16c87ce3f614 100644 --- a/drivers/gpu/drm/xe/regs/xe_gt_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_gt_regs.h @@ -528,6 +528,7 @@ #define ROW_CHICKEN3 XE_REG_MCR(0xe49c, XE_REG_OPTION_MASKED) #define XE2_EUPEND_CHK_FLUSH_DIS REG_BIT(14) +#define DIS_EU_GRF_POISON_TO_LSC REG_BIT(13) #define DIS_FIX_EOT1_FLUSH REG_BIT(9) #define TDL_TSL_CHICKEN XE_REG_MCR(0xe4c4, XE_REG_OPTION_MASKED) @@ -535,6 +536,9 @@ #define SLM_WMTP_RESTORE REG_BIT(11) #define RES_CHK_SPR_DIS REG_BIT(6) +#define TDL_TSL_CHICKEN2 XE_REG_MCR(0xe4cc, XE_REG_OPTION_MASKED) +#define TILEY_LOCALID REG_BIT(2) + #define ROW_CHICKEN XE_REG_MCR(0xe4f0, XE_REG_OPTION_MASKED) #define UGM_BACKUP_MODE REG_BIT(13) #define MDQ_ARBITRATION_MODE REG_BIT(12) @@ -560,6 +564,7 @@ #define DIS_ATOMIC_CHAINING_TYPED_WRITES REG_BIT(3) #define TDL_CHICKEN XE_REG_MCR(0xe5f4, XE_REG_OPTION_MASKED) +#define BIT_APQ_OPT_DIS REG_BIT(14) #define QID_WAIT_FOR_THREAD_NOT_RUN_DISABLE REG_BIT(12) #define EUSTALL_PERF_SAMPLING_DISABLE REG_BIT(5) diff --git a/drivers/gpu/drm/xe/regs/xe_irq_regs.h b/drivers/gpu/drm/xe/regs/xe_irq_regs.h index 9d74f454d3ff..1d6b976c4de0 100644 --- a/drivers/gpu/drm/xe/regs/xe_irq_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_irq_regs.h @@ -22,6 +22,7 @@ #define DISPLAY_IRQ REG_BIT(16) #define SOC_H2DMEMINT_IRQ REG_BIT(13) #define I2C_IRQ REG_BIT(12) +#define SYSCTRL_IRQ REG_BIT(11) #define GT_DW_IRQ(x) REG_BIT(x) /* diff --git a/drivers/gpu/drm/xe/regs/xe_pcode_regs.h b/drivers/gpu/drm/xe/regs/xe_pcode_regs.h index 4b3c46eb858f..c63b409d7a82 100644 --- a/drivers/gpu/drm/xe/regs/xe_pcode_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_pcode_regs.h @@ -27,4 +27,7 @@ #define TEMP_SIGN_MASK REG_BIT(31) #define BMG_PACKAGE_TEMPERATURE XE_REG(0x138434) +#define CRI_PACKAGE_ENERGY_STATUS XE_REG(0x138120) +#define CRI_PLATFORM_ENERGY_STATUS XE_REG(0x138458) + #endif /* _XE_PCODE_REGS_H_ */ diff --git a/drivers/gpu/drm/xe/regs/xe_sysctrl_regs.h b/drivers/gpu/drm/xe/regs/xe_sysctrl_regs.h new file mode 100644 index 000000000000..59f3f3ec59a6 --- /dev/null +++ b/drivers/gpu/drm/xe/regs/xe_sysctrl_regs.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2026 Intel Corporation + */ + +#ifndef _XE_SYSCTRL_REGS_H_ +#define _XE_SYSCTRL_REGS_H_ + +#include "xe_regs.h" + +#define SYSCTRL_BASE_OFFSET 0xdb000 +#define SYSCTRL_BASE (SOC_BASE + SYSCTRL_BASE_OFFSET) +#define SYSCTRL_MAILBOX_INDEX 0x03 +#define SYSCTRL_BAR_LENGTH 0x1000 + +#define SYSCTRL_MB_CTRL XE_REG(0x10) +#define SYSCTRL_MB_CTRL_RUN_BUSY REG_BIT(31) +#define SYSCTRL_MB_CTRL_IRQ REG_BIT(30) +#define SYSCTRL_MB_CTRL_RUN_BUSY_OUT REG_BIT(29) +#define SYSCTRL_MB_CTRL_PARAM3_MASK REG_GENMASK(28, 24) +#define SYSCTRL_MB_CTRL_PARAM2_MASK REG_GENMASK(23, 16) +#define SYSCTRL_MB_CTRL_PARAM1_MASK REG_GENMASK(15, 8) +#define SYSCTRL_MB_CTRL_COMMAND_MASK REG_GENMASK(7, 0) +#define SYSCTRL_MB_CTRL_CMD REG_FIELD_PREP(SYSCTRL_MB_CTRL_COMMAND_MASK, 5) + +#define SYSCTRL_MB_DATA0 XE_REG(0x14) +#define SYSCTRL_MB_DATA1 XE_REG(0x18) +#define SYSCTRL_MB_DATA2 XE_REG(0x1c) +#define SYSCTRL_MB_DATA3 XE_REG(0x20) + +#define SYSCTRL_FRAME_PHASE REG_BIT(24) +#define SYSCTRL_FRAME_CURRENT_MASK REG_GENMASK(21, 16) +#define SYSCTRL_FRAME_TOTAL_MASK REG_GENMASK(13, 8) +#define SYSCTRL_FRAME_COMMAND_MASK REG_GENMASK(7, 0) + +#endif diff --git a/drivers/gpu/drm/xe/tests/xe_gt_sriov_pf_config_kunit.c b/drivers/gpu/drm/xe/tests/xe_gt_sriov_pf_config_kunit.c index efa8963ec248..e6eaa94d4d30 100644 --- a/drivers/gpu/drm/xe/tests/xe_gt_sriov_pf_config_kunit.c +++ b/drivers/gpu/drm/xe/tests/xe_gt_sriov_pf_config_kunit.c @@ -13,11 +13,28 @@ #define TEST_MAX_VFS 63 #define TEST_VRAM 0x7a800000ull /* random size that works on 32-bit */ +static bool xe_device_is_admin_only_stub_enable(const struct xe_device *xe) +{ + return true; +} + +static bool xe_device_is_admin_only_stub_disable(const struct xe_device *xe) +{ + return false; +} + static void pf_set_admin_mode(struct xe_device *xe, bool enable) { - /* should match logic of xe_sriov_pf_admin_only() */ - xe->sriov.pf.admin_only = enable; + typeof(xe_device_is_admin_only) *stub = enable ? + xe_device_is_admin_only_stub_enable : + xe_device_is_admin_only_stub_disable; + + kunit_activate_static_stub(kunit_get_current_test(), + xe_device_is_admin_only, + *stub); + KUNIT_EXPECT_EQ(kunit_get_current_test(), enable, xe_sriov_pf_admin_only(xe)); + KUNIT_EXPECT_EQ(kunit_get_current_test(), enable, xe_device_is_admin_only(xe)); } static void pf_set_usable_vram(struct xe_device *xe, u64 usable) diff --git a/drivers/gpu/drm/xe/tests/xe_migrate.c b/drivers/gpu/drm/xe/tests/xe_migrate.c index 34e2f0f4631f..50a97705e0ac 100644 --- a/drivers/gpu/drm/xe/tests/xe_migrate.c +++ b/drivers/gpu/drm/xe/tests/xe_migrate.c @@ -9,6 +9,7 @@ #include "tests/xe_kunit_helpers.h" #include "tests/xe_pci_test.h" +#include "xe_pat.h" #include "xe_pci.h" #include "xe_pm.h" @@ -246,7 +247,7 @@ static void xe_migrate_sanity_test(struct xe_migrate *m, struct kunit *test, /* First part of the test, are we updating our pagetable bo with a new entry? */ xe_map_wr(xe, &bo->vmap, XE_PAGE_SIZE * (NUM_KERNEL_PDE - 1), u64, 0xdeaddeadbeefbeef); - expected = m->q->vm->pt_ops->pte_encode_bo(pt, 0, xe->pat.idx[XE_CACHE_WB], 0); + expected = m->q->vm->pt_ops->pte_encode_bo(pt, 0, xe_cache_pat_idx(xe, XE_CACHE_WB), 0); if (m->q->vm->flags & XE_VM_FLAG_64K) expected |= XE_PTE_PS64; if (xe_bo_is_vram(pt)) diff --git a/drivers/gpu/drm/xe/tests/xe_pci.c b/drivers/gpu/drm/xe/tests/xe_pci.c index f3179b31f13e..860409c579f8 100644 --- a/drivers/gpu/drm/xe/tests/xe_pci.c +++ b/drivers/gpu/drm/xe/tests/xe_pci.c @@ -131,12 +131,12 @@ static const char *subplatform_prefix(enum xe_subplatform s) return s == XE_SUBPLATFORM_NONE ? "" : " "; } -static const char *step_prefix(enum xe_step step) +static const char *step_prefix(enum intel_step step) { return step == STEP_NONE ? "" : " "; } -static const char *step_name(enum xe_step step) +static const char *step_name(enum intel_step step) { return step == STEP_NONE ? "" : xe_step_name(step); } diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c index 4075edf97421..5ce60d161e09 100644 --- a/drivers/gpu/drm/xe/xe_bo.c +++ b/drivers/gpu/drm/xe/xe_bo.c @@ -173,19 +173,6 @@ mem_type_to_migrate(struct xe_device *xe, u32 mem_type) return tile->migrate; } -static struct xe_vram_region *res_to_mem_region(struct ttm_resource *res) -{ - struct xe_device *xe = ttm_to_xe_device(res->bo->bdev); - struct ttm_resource_manager *mgr; - struct xe_ttm_vram_mgr *vram_mgr; - - xe_assert(xe, resource_is_vram(res)); - mgr = ttm_manager_type(&xe->ttm, res->mem_type); - vram_mgr = to_xe_ttm_vram_mgr(mgr); - - return container_of(vram_mgr, struct xe_vram_region, ttm); -} - static void try_add_system(struct xe_device *xe, struct xe_bo *bo, u32 bo_flags, u32 *c) { @@ -635,7 +622,7 @@ static int xe_ttm_io_mem_reserve(struct ttm_device *bdev, return 0; case XE_PL_VRAM0: case XE_PL_VRAM1: { - struct xe_vram_region *vram = res_to_mem_region(mem); + struct xe_vram_region *vram = xe_map_resource_to_region(mem); if (!xe_ttm_resource_visible(mem)) return -EINVAL; @@ -1642,7 +1629,7 @@ static unsigned long xe_ttm_io_mem_pfn(struct ttm_buffer_object *ttm_bo, if (ttm_bo->resource->mem_type == XE_PL_STOLEN) return xe_ttm_stolen_io_offset(bo, page_offset << PAGE_SHIFT) >> PAGE_SHIFT; - vram = res_to_mem_region(ttm_bo->resource); + vram = xe_map_resource_to_region(ttm_bo->resource); xe_res_first(ttm_bo->resource, (u64)page_offset << PAGE_SHIFT, 0, &cursor); return (vram->io_start + cursor.start) >> PAGE_SHIFT; } @@ -1782,7 +1769,7 @@ static int xe_ttm_access_memory(struct ttm_buffer_object *ttm_bo, goto out; } - vram = res_to_mem_region(ttm_bo->resource); + vram = xe_map_resource_to_region(ttm_bo->resource); xe_res_first(ttm_bo->resource, offset & PAGE_MASK, xe_bo_size(bo) - (offset & PAGE_MASK), &cursor); @@ -2927,7 +2914,7 @@ uint64_t vram_region_gpu_offset(struct ttm_resource *res) case XE_PL_SYSTEM: return 0; default: - return res_to_mem_region(res)->dpa_base; + return xe_map_resource_to_region(res)->dpa_base; } return 0; } diff --git a/drivers/gpu/drm/xe/xe_bo_types.h b/drivers/gpu/drm/xe/xe_bo_types.h index 9d19940b8fc0..9c199badd9b2 100644 --- a/drivers/gpu/drm/xe/xe_bo_types.h +++ b/drivers/gpu/drm/xe/xe_bo_types.h @@ -67,7 +67,7 @@ struct xe_bo { /** @attr: User controlled attributes for bo */ struct { /** - * @atomic_access: type of atomic access bo needs + * @attr.atomic_access: type of atomic access bo needs * protected by bo dma-resv lock */ u32 atomic_access; diff --git a/drivers/gpu/drm/xe/xe_debugfs.c b/drivers/gpu/drm/xe/xe_debugfs.c index ad2d8f179eb6..22b471303984 100644 --- a/drivers/gpu/drm/xe/xe_debugfs.c +++ b/drivers/gpu/drm/xe/xe_debugfs.c @@ -15,9 +15,11 @@ #include "xe_bo.h" #include "xe_device.h" #include "xe_force_wake.h" +#include "xe_gt.h" #include "xe_gt_debugfs.h" #include "xe_gt_printk.h" #include "xe_guc_ads.h" +#include "xe_hw_engine.h" #include "xe_mmio.h" #include "xe_pm.h" #include "xe_psmi.h" @@ -61,6 +63,37 @@ static struct xe_device *node_to_xe(struct drm_info_node *node) return to_xe_device(node->minor->dev); } +static void print_engine_class_mask(struct drm_printer *p, u16 mask) +{ + if (!mask) { + drm_printf(p, " none\n"); + return; + } + + for (enum xe_engine_class ec = 0; ec < XE_ENGINE_CLASS_MAX; ec++) { + if (mask & BIT(ec)) + drm_printf(p, " %s", xe_hw_engine_class_to_str(ec)); + } + drm_printf(p, "\n"); +} + +static void print_engine_mask(struct drm_printer *p, struct xe_gt *gt, u64 mask) +{ + struct xe_hw_engine *hwe; + enum xe_hw_engine_id id; + + if (!mask) { + drm_printf(p, " none\n"); + return; + } + + for_each_hw_engine(hwe, gt, id) { + if (mask & BIT_ULL(id)) + drm_printf(p, " %s", hwe->name); + } + drm_printf(p, "\n"); +} + static int info(struct seq_file *m, void *data) { struct xe_device *xe = node_to_xe(m->private); @@ -88,13 +121,15 @@ static int info(struct seq_file *m, void *data) drm_printf(&p, "has_flat_ccs %s\n", str_yes_no(xe->info.has_flat_ccs)); drm_printf(&p, "has_usm %s\n", str_yes_no(xe->info.has_usm)); drm_printf(&p, "skip_guc_pc %s\n", str_yes_no(xe->info.skip_guc_pc)); + drm_printf(&p, "multi_lrc_engine_classes"); + print_engine_class_mask(&p, xe->info.multi_lrc_mask); for_each_gt(gt, xe, id) { drm_printf(&p, "gt%d force wake %d\n", id, xe_force_wake_ref(gt_to_fw(gt), XE_FW_GT)); - drm_printf(&p, "gt%d engine_mask 0x%llx\n", id, - gt->info.engine_mask); - drm_printf(&p, "gt%d multi_queue_engine_class_mask 0x%x\n", id, - gt->info.multi_queue_engine_class_mask); + drm_printf(&p, "gt%d engines", id); + print_engine_mask(&p, gt, gt->info.engine_mask); + drm_printf(&p, "gt%d multi_queue_engine_classes", id); + print_engine_class_mask(&p, gt->info.multi_queue_engine_class_mask); } return 0; diff --git a/drivers/gpu/drm/xe/xe_dep_scheduler.h b/drivers/gpu/drm/xe/xe_dep_scheduler.h index 853961eec64b..f314fb5d80f5 100644 --- a/drivers/gpu/drm/xe/xe_dep_scheduler.h +++ b/drivers/gpu/drm/xe/xe_dep_scheduler.h @@ -3,6 +3,9 @@ * Copyright © 2025 Intel Corporation */ +#ifndef _XE_DEP_SCHEDULER_H_ +#define _XE_DEP_SCHEDULER_H_ + #include struct drm_sched_entity; @@ -19,3 +22,5 @@ void xe_dep_scheduler_fini(struct xe_dep_scheduler *dep_scheduler); struct drm_sched_entity * xe_dep_scheduler_entity(struct xe_dep_scheduler *dep_scheduler); + +#endif diff --git a/drivers/gpu/drm/xe/xe_devcoredump.c b/drivers/gpu/drm/xe/xe_devcoredump.c index 558a1a9841a0..5f2b90b18f97 100644 --- a/drivers/gpu/drm/xe/xe_devcoredump.c +++ b/drivers/gpu/drm/xe/xe_devcoredump.c @@ -8,7 +8,7 @@ #include #include -#include +#include #include @@ -101,7 +101,7 @@ static ssize_t __xe_devcoredump_read(char *buffer, ssize_t count, drm_puts(&p, "**** Xe Device Coredump ****\n"); drm_printf(&p, "Reason: %s\n", ss->reason); - drm_puts(&p, "kernel: " UTS_RELEASE "\n"); + drm_printf(&p, "kernel: %s\n", init_utsname()->release); drm_puts(&p, "module: " KBUILD_MODNAME "\n"); ts = ktime_to_timespec64(ss->snapshot_time); @@ -149,7 +149,8 @@ static void xe_devcoredump_snapshot_free(struct xe_devcoredump_snapshot *ss) xe_guc_ct_snapshot_free(ss->guc.ct); ss->guc.ct = NULL; - xe_guc_capture_put_matched_nodes(&ss->gt->uc.guc); + if (!IS_ERR_OR_NULL(ss->gt)) + xe_guc_capture_put_matched_nodes(&ss->gt->uc.guc); ss->matched_node = NULL; xe_guc_exec_queue_snapshot_free(ss->ge); @@ -254,7 +255,8 @@ static void xe_devcoredump_free(void *data) if (!data || !coredump_to_xe(coredump)) return; - cancel_work_sync(&coredump->snapshot.work); + if (coredump->captured) + cancel_work_sync(&coredump->snapshot.work); mutex_lock(&coredump->lock); diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index ffea4a453c01..4b45b617a039 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include "display/xe_display.h" @@ -25,6 +26,7 @@ #include "regs/xe_regs.h" #include "xe_bo.h" #include "xe_bo_evict.h" +#include "xe_configfs.h" #include "xe_debugfs.h" #include "xe_defaults.h" #include "xe_devcoredump.h" @@ -65,6 +67,7 @@ #include "xe_survivability_mode.h" #include "xe_sriov.h" #include "xe_svm.h" +#include "xe_sysctrl.h" #include "xe_tile.h" #include "xe_ttm_stolen_mgr.h" #include "xe_ttm_sys_mgr.h" @@ -389,7 +392,7 @@ bool xe_is_xe_file(const struct file *file) return file->f_op == &xe_driver_fops; } -static struct drm_driver driver = { +static struct drm_driver regular_driver = { .driver_features = DRIVER_GEM | DRIVER_RENDER | DRIVER_SYNCOBJ | @@ -414,6 +417,40 @@ static struct drm_driver driver = { .patchlevel = DRIVER_PATCHLEVEL, }; +#ifdef CONFIG_PCI_IOV +static const struct drm_ioctl_desc xe_ioctls_admin_only[] = { + DRM_IOCTL_DEF_DRV(XE_DEVICE_QUERY, xe_query_ioctl, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(XE_OBSERVATION, xe_observation_ioctl, DRM_RENDER_ALLOW), +}; + +static struct drm_driver admin_only_driver = { + .driver_features = + DRIVER_GEM | DRIVER_RENDER | DRIVER_GEM_GPUVA, + .open = xe_file_open, + .postclose = xe_file_close, + .ioctls = xe_ioctls_admin_only, + .num_ioctls = ARRAY_SIZE(xe_ioctls_admin_only), + .fops = &xe_driver_fops, + .name = DRIVER_NAME, + .desc = DRIVER_DESC, + .major = DRIVER_MAJOR, + .minor = DRIVER_MINOR, + .patchlevel = DRIVER_PATCHLEVEL, +}; + +/** + * xe_device_is_admin_only() - Check whether device is admin only or not. + * @xe: the &xe_device to check + * + * Return: true if the device is admin only, false otherwise. + */ +bool xe_device_is_admin_only(const struct xe_device *xe) +{ + KUNIT_STATIC_STUB_REDIRECT(xe_device_is_admin_only, xe); + return xe->drm.driver == &admin_only_driver; +} +#endif + static void xe_device_destroy(struct drm_device *dev, void *dummy) { struct xe_device *xe = to_xe_device(dev); @@ -438,16 +475,26 @@ static void xe_device_destroy(struct drm_device *dev, void *dummy) struct xe_device *xe_device_create(struct pci_dev *pdev, const struct pci_device_id *ent) { + struct drm_driver *driver = ®ular_driver; struct xe_device *xe; int err; - xe_display_driver_set_hooks(&driver); +#ifdef CONFIG_PCI_IOV + /* + * Since XE device is not initialized yet, read from configfs + * directly to decide whether we are in admin-only PF mode or not. + */ + if (xe_configfs_admin_only_pf(pdev)) + driver = &admin_only_driver; +#endif - err = aperture_remove_conflicting_pci_devices(pdev, driver.name); + xe_display_driver_set_hooks(driver); + + err = aperture_remove_conflicting_pci_devices(pdev, driver->name); if (err) return ERR_PTR(err); - xe = devm_drm_dev_alloc(&pdev->dev, &driver, struct xe_device, drm); + xe = devm_drm_dev_alloc(&pdev->dev, driver, struct xe_device, drm); if (IS_ERR(xe)) return xe; @@ -707,6 +754,11 @@ int xe_device_probe_early(struct xe_device *xe) xe_sriov_probe_early(xe); + if (xe_device_is_admin_only(xe) && !IS_SRIOV_PF(xe)) { + xe_err(xe, "Can't run Admin-only mode without SR-IOV PF mode!\n"); + return -ENODEV; + } + if (IS_SRIOV_VF(xe)) vf_update_device_info(xe); @@ -992,6 +1044,10 @@ int xe_device_probe(struct xe_device *xe) if (err) goto err_unregister_display; + err = xe_sysctrl_init(xe); + if (err) + goto err_unregister_display; + err = xe_device_sysfs_init(xe); if (err) goto err_unregister_display; diff --git a/drivers/gpu/drm/xe/xe_device.h b/drivers/gpu/drm/xe/xe_device.h index e4b9de8d8e95..355d69dc8f54 100644 --- a/drivers/gpu/drm/xe/xe_device.h +++ b/drivers/gpu/drm/xe/xe_device.h @@ -146,37 +146,37 @@ static inline struct xe_force_wake *gt_to_fw(struct xe_gt *gt) void xe_device_assert_mem_access(struct xe_device *xe); -static inline bool xe_device_has_flat_ccs(struct xe_device *xe) +static inline bool xe_device_has_flat_ccs(const struct xe_device *xe) { return xe->info.has_flat_ccs; } -static inline bool xe_device_has_sriov(struct xe_device *xe) +static inline bool xe_device_has_sriov(const struct xe_device *xe) { return xe->info.has_sriov; } -static inline bool xe_device_has_msix(struct xe_device *xe) +static inline bool xe_device_has_msix(const struct xe_device *xe) { return xe->irq.msix.nvec > 0; } -static inline bool xe_device_has_memirq(struct xe_device *xe) +static inline bool xe_device_has_memirq(const struct xe_device *xe) { return GRAPHICS_VERx100(xe) >= 1250; } -static inline bool xe_device_uses_memirq(struct xe_device *xe) +static inline bool xe_device_uses_memirq(const struct xe_device *xe) { return xe_device_has_memirq(xe) && (IS_SRIOV_VF(xe) || xe_device_has_msix(xe)); } -static inline bool xe_device_has_lmtt(struct xe_device *xe) +static inline bool xe_device_has_lmtt(const struct xe_device *xe) { return IS_DGFX(xe); } -static inline bool xe_device_has_mert(struct xe_device *xe) +static inline bool xe_device_has_mert(const struct xe_device *xe) { return xe->info.has_mert; } @@ -211,6 +211,15 @@ bool xe_is_xe_file(const struct file *file); struct xe_vm *xe_device_asid_to_vm(struct xe_device *xe, u32 asid); +#ifdef CONFIG_PCI_IOV +bool xe_device_is_admin_only(const struct xe_device *xe); +#else +static inline bool xe_device_is_admin_only(const struct xe_device *xe) +{ + return false; +} +#endif + /* * Occasionally it is seen that the G2H worker starts running after a delay of more than * a second even after being queued and activated by the Linux workqueue subsystem. This diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h index 615218d775b1..89437de3001a 100644 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@ -27,6 +27,7 @@ #include "xe_sriov_vf_ccs_types.h" #include "xe_step_types.h" #include "xe_survivability_mode_types.h" +#include "xe_sysctrl_types.h" #include "xe_tile_types.h" #include "xe_validation.h" @@ -196,6 +197,8 @@ struct xe_device { u8 has_soc_remapper_telem:1; /** @info.has_sriov: Supports SR-IOV */ u8 has_sriov:1; + /** @info.has_sysctrl: Supports System Controller */ + u8 has_sysctrl:1; /** @info.has_usm: Device has unified shared memory support */ u8 has_usm:1; /** @info.has_64bit_timestamp: Device supports 64-bit timestamps */ @@ -215,8 +218,6 @@ struct xe_device { u8 probe_display:1; /** @info.skip_guc_pc: Skip GuC based PM feature init */ u8 skip_guc_pc:1; - /** @info.skip_mtcfg: skip Multi-Tile configuration from MTCFG register */ - u8 skip_mtcfg:1; /** @info.skip_pcode: skip access to PCODE uC */ u8 skip_pcode:1; /** @info.needs_shared_vf_gt_wq: needs shared GT WQ on VF */ @@ -273,7 +274,7 @@ struct xe_device { struct xe_vram_region *vram; /** @mem.sys_mgr: system TTM manager */ struct ttm_resource_manager sys_mgr; - /** @mem.sys_mgr: system memory shrinker. */ + /** @mem.shrinker: system memory shrinker. */ struct xe_shrinker *shrinker; } mem; @@ -295,7 +296,7 @@ struct xe_device { /** @usm: unified memory state */ struct { - /** @usm.asid: convert a ASID to VM */ + /** @usm.asid_to_vm: convert an ASID to VM */ struct xarray asid_to_vm; /** @usm.next_asid: next ASID, used to cyclical alloc asids */ u32 next_asid; @@ -312,7 +313,7 @@ struct xe_device { /** @usm.pf_queue: Page fault queues */ struct xe_pagefault_queue pf_queue[XE_PAGEFAULT_QUEUE_COUNT]; #if IS_ENABLED(CONFIG_DRM_XE_PAGEMAP) - /** @usm.pagemap_shrinker: Shrinker for unused pagemaps */ + /** @usm.dpagemap_shrinker: Shrinker for unused pagemaps */ struct drm_pagemap_shrinker *dpagemap_shrinker; #endif } usm; @@ -334,7 +335,7 @@ struct xe_device { struct list_head kernel_bo_present; /** @pinned.late.evicted: pinned BO that have been evicted */ struct list_head evicted; - /** @pinned.external: pinned external and dma-buf. */ + /** @pinned.late.external: pinned external and dma-buf. */ struct list_head external; } late; } pinned; @@ -369,7 +370,7 @@ struct xe_device { struct { /** * @mem_access.vram_userfault.lock: Protects access to - * @vram_usefault.list Using mutex instead of spinlock + * @mem_access.vram_userfault.list Using mutex instead of spinlock * as lock is applied to entire list operation which * may sleep */ @@ -400,7 +401,7 @@ struct xe_device { const struct xe_pat_table_entry *pat_primary_pta; /** @pat.pat_media_pta: media GT PAT entry for page table accesses */ const struct xe_pat_table_entry *pat_media_pta; - u32 idx[__XE_CACHE_LEVEL_COUNT]; + u16 idx[__XE_CACHE_LEVEL_COUNT]; } pat; /** @d3cold: Encapsulate d3cold related stuff */ @@ -508,6 +509,9 @@ struct xe_device { /** @i2c: I2C host controller */ struct xe_i2c *i2c; + /** @sc: System Controller */ + struct xe_sysctrl sc; + /** @atomic_svm_timeslice_ms: Atomic SVM fault timeslice MS */ u32 atomic_svm_timeslice_ms; @@ -578,7 +582,7 @@ struct xe_file { /** @vm: VM state for file */ struct { - /** @vm.xe: xarray to store VMs */ + /** @vm.xa: xarray to store VMs */ struct xarray xa; /** * @vm.lock: Protects VM lookup + reference and removal from diff --git a/drivers/gpu/drm/xe/xe_device_wa_oob.rules b/drivers/gpu/drm/xe/xe_device_wa_oob.rules index d129cddb6ead..92371c490529 100644 --- a/drivers/gpu/drm/xe/xe_device_wa_oob.rules +++ b/drivers/gpu/drm/xe/xe_device_wa_oob.rules @@ -4,3 +4,4 @@ 22019338487_display PLATFORM(LUNARLAKE) 14022085890 SUBPLATFORM(BATTLEMAGE, G21) 14026539277 PLATFORM(NOVALAKE_P), PLATFORM_STEP(A0, B0) +14026633728 PLATFORM(CRESCENTISLAND) diff --git a/drivers/gpu/drm/xe/xe_drm_ras.c b/drivers/gpu/drm/xe/xe_drm_ras.c index e07dc23a155e..c21c8b428de6 100644 --- a/drivers/gpu/drm/xe/xe_drm_ras.c +++ b/drivers/gpu/drm/xe/xe_drm_ras.c @@ -27,6 +27,16 @@ static int hw_query_error_counter(struct xe_drm_ras_counter *info, return 0; } +static int hw_clear_error_counter(struct xe_drm_ras_counter *info, u32 error_id) +{ + if (!info || !info[error_id].name) + return -ENOENT; + + atomic_set(&info[error_id].counter, 0); + + return 0; +} + static int query_uncorrectable_error_counter(struct drm_ras_node *ep, u32 error_id, const char **name, u32 *val) { @@ -37,6 +47,15 @@ static int query_uncorrectable_error_counter(struct drm_ras_node *ep, u32 error_ return hw_query_error_counter(info, error_id, name, val); } +static int clear_uncorrectable_error_counter(struct drm_ras_node *node, u32 error_id) +{ + struct xe_device *xe = node->priv; + struct xe_drm_ras *ras = &xe->ras; + struct xe_drm_ras_counter *info = ras->info[DRM_XE_RAS_ERR_SEV_UNCORRECTABLE]; + + return hw_clear_error_counter(info, error_id); +} + static int query_correctable_error_counter(struct drm_ras_node *ep, u32 error_id, const char **name, u32 *val) { @@ -47,6 +66,15 @@ static int query_correctable_error_counter(struct drm_ras_node *ep, u32 error_id return hw_query_error_counter(info, error_id, name, val); } +static int clear_correctable_error_counter(struct drm_ras_node *node, u32 error_id) +{ + struct xe_device *xe = node->priv; + struct xe_drm_ras *ras = &xe->ras; + struct xe_drm_ras_counter *info = ras->info[DRM_XE_RAS_ERR_SEV_CORRECTABLE]; + + return hw_clear_error_counter(info, error_id); +} + static struct xe_drm_ras_counter *allocate_and_copy_counters(struct xe_device *xe) { struct xe_drm_ras_counter *counter; @@ -92,10 +120,13 @@ static int assign_node_params(struct xe_device *xe, struct drm_ras_node *node, if (IS_ERR(ras->info[severity])) return PTR_ERR(ras->info[severity]); - if (severity == DRM_XE_RAS_ERR_SEV_CORRECTABLE) + if (severity == DRM_XE_RAS_ERR_SEV_CORRECTABLE) { node->query_error_counter = query_correctable_error_counter; - else + node->clear_error_counter = clear_correctable_error_counter; + } else { node->query_error_counter = query_uncorrectable_error_counter; + node->clear_error_counter = clear_uncorrectable_error_counter; + } return 0; } diff --git a/drivers/gpu/drm/xe/xe_drm_ras.h b/drivers/gpu/drm/xe/xe_drm_ras.h index 5cc8f0124411..365c70e93e82 100644 --- a/drivers/gpu/drm/xe/xe_drm_ras.h +++ b/drivers/gpu/drm/xe/xe_drm_ras.h @@ -2,8 +2,8 @@ /* * Copyright © 2026 Intel Corporation */ -#ifndef XE_DRM_RAS_H_ -#define XE_DRM_RAS_H_ +#ifndef _XE_DRM_RAS_H_ +#define _XE_DRM_RAS_H_ struct xe_device; diff --git a/drivers/gpu/drm/xe/xe_eu_stall.h b/drivers/gpu/drm/xe/xe_eu_stall.h index d1c76e503799..842bef9f6872 100644 --- a/drivers/gpu/drm/xe/xe_eu_stall.h +++ b/drivers/gpu/drm/xe/xe_eu_stall.h @@ -3,8 +3,8 @@ * Copyright © 2025 Intel Corporation */ -#ifndef __XE_EU_STALL_H__ -#define __XE_EU_STALL_H__ +#ifndef _XE_EU_STALL_H_ +#define _XE_EU_STALL_H_ #include "xe_gt_types.h" #include "xe_sriov.h" diff --git a/drivers/gpu/drm/xe/xe_exec_queue_types.h b/drivers/gpu/drm/xe/xe_exec_queue_types.h index 8ce78e0b1d50..2f5ccf294675 100644 --- a/drivers/gpu/drm/xe/xe_exec_queue_types.h +++ b/drivers/gpu/drm/xe/xe_exec_queue_types.h @@ -214,7 +214,7 @@ struct xe_exec_queue { */ struct xe_dep_scheduler *dep_scheduler; /** - * @last_fence: last fence for tlb invalidation, protected by + * @tlb_inval.last_fence: last fence for tlb invalidation, protected by * vm->lock in write mode */ struct dma_fence *last_fence; diff --git a/drivers/gpu/drm/xe/xe_execlist.c b/drivers/gpu/drm/xe/xe_execlist.c index 755a2bff5d7b..0fe4fb226ef4 100644 --- a/drivers/gpu/drm/xe/xe_execlist.c +++ b/drivers/gpu/drm/xe/xe_execlist.c @@ -47,7 +47,6 @@ static void __start_lrc(struct xe_hw_engine *hwe, struct xe_lrc *lrc, struct xe_mmio *mmio = >->mmio; struct xe_device *xe = gt_to_xe(gt); u64 lrc_desc; - u32 ring_mode = REG_MASKED_FIELD_ENABLE(GFX_DISABLE_LEGACY_MODE); lrc_desc = xe_lrc_descriptor(lrc); @@ -59,10 +58,6 @@ static void __start_lrc(struct xe_hw_engine *hwe, struct xe_lrc *lrc, lrc_desc |= FIELD_PREP(SW_CTX_ID, ctx_id); } - if (hwe->class == XE_ENGINE_CLASS_COMPUTE) - xe_mmio_write32(mmio, RCU_MODE, - REG_MASKED_FIELD_ENABLE(RCU_MODE_CCS_ENABLE)); - xe_lrc_write_ctx_reg(lrc, CTX_RING_TAIL, lrc->ring.tail); lrc->ring.old_tail = lrc->ring.tail; @@ -82,10 +77,6 @@ static void __start_lrc(struct xe_hw_engine *hwe, struct xe_lrc *lrc, xe_bo_ggtt_addr(hwe->hwsp)); xe_mmio_read32(mmio, RING_HWS_PGA(hwe->mmio_base)); - if (xe_device_has_msix(gt_to_xe(hwe->gt))) - ring_mode |= REG_MASKED_FIELD_ENABLE(GFX_MSIX_INTERRUPT_ENABLE); - xe_mmio_write32(mmio, RING_MODE(hwe->mmio_base), ring_mode); - xe_mmio_write32(mmio, RING_EXECLIST_SQ_CONTENTS_LO(hwe->mmio_base), lower_32_bits(lrc_desc)); xe_mmio_write32(mmio, RING_EXECLIST_SQ_CONTENTS_HI(hwe->mmio_base), diff --git a/drivers/gpu/drm/xe/xe_ggtt.c b/drivers/gpu/drm/xe/xe_ggtt.c index a848d1a41b9b..a351c578b170 100644 --- a/drivers/gpu/drm/xe/xe_ggtt.c +++ b/drivers/gpu/drm/xe/xe_ggtt.c @@ -24,6 +24,7 @@ #include "xe_gt_types.h" #include "xe_map.h" #include "xe_mmio.h" +#include "xe_pat.h" #include "xe_pm.h" #include "xe_res_cursor.h" #include "xe_sriov.h" @@ -115,7 +116,6 @@ struct xe_ggtt { /** @size: Total usable size of this GGTT */ u64 size; -#define XE_GGTT_FLAGS_64K BIT(0) /** * @flags: Flags for this GGTT * Acceptable flags: @@ -259,7 +259,7 @@ static u64 xe_ggtt_get_pte(struct xe_ggtt *ggtt, u64 addr) static void xe_ggtt_clear(struct xe_ggtt *ggtt, u64 start, u64 size) { - u16 pat_index = tile_to_xe(ggtt->tile)->pat.idx[XE_CACHE_WB]; + u16 pat_index = xe_cache_pat_idx(tile_to_xe(ggtt->tile), XE_CACHE_WB); u64 end = start + size - 1; u64 scratch_pte; @@ -724,7 +724,7 @@ static void xe_ggtt_map_bo(struct xe_ggtt *ggtt, struct xe_ggtt_node *node, void xe_ggtt_map_bo_unlocked(struct xe_ggtt *ggtt, struct xe_bo *bo) { u16 cache_mode = bo->flags & XE_BO_FLAG_NEEDS_UC ? XE_CACHE_NONE : XE_CACHE_WB; - u16 pat_index = tile_to_xe(ggtt->tile)->pat.idx[cache_mode]; + u16 pat_index = xe_cache_pat_idx(tile_to_xe(ggtt->tile), cache_mode); u64 pte; mutex_lock(&ggtt->lock); @@ -841,7 +841,7 @@ static int __xe_ggtt_insert_bo_at(struct xe_ggtt *ggtt, struct xe_bo *bo, bo->ggtt_node[tile_id] = NULL; } else { u16 cache_mode = bo->flags & XE_BO_FLAG_NEEDS_UC ? XE_CACHE_NONE : XE_CACHE_WB; - u16 pat_index = tile_to_xe(ggtt->tile)->pat.idx[cache_mode]; + u16 pat_index = xe_cache_pat_idx(tile_to_xe(ggtt->tile), cache_mode); u64 pte = ggtt->pt_ops->pte_encode_flags(bo, pat_index); xe_ggtt_map_bo(ggtt, bo->ggtt_node[tile_id], bo, pte); diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c index 8a31c963c372..cdc678d1ae1f 100644 --- a/drivers/gpu/drm/xe/xe_gt.c +++ b/drivers/gpu/drm/xe/xe_gt.c @@ -993,7 +993,6 @@ void xe_gt_reset_async(struct xe_gt *gt) void xe_gt_suspend_prepare(struct xe_gt *gt) { - CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FORCEWAKE_ALL); xe_uc_suspend_prepare(>->uc); } diff --git a/drivers/gpu/drm/xe/xe_gt_mcr.c b/drivers/gpu/drm/xe/xe_gt_mcr.c index 7c6f039c880d..df281688c617 100644 --- a/drivers/gpu/drm/xe/xe_gt_mcr.c +++ b/drivers/gpu/drm/xe/xe_gt_mcr.c @@ -216,9 +216,7 @@ static const struct xe_mmio_range xe2lpg_sqidi_psmi_steering_table[] = { static const struct xe_mmio_range xe2lpg_instance0_steering_table[] = { { 0x004000, 0x004AFF }, /* GAM, rsvd, GAMWKR */ { 0x008700, 0x00887F }, /* SQIDI, MEMPIPE */ - { 0x00B000, 0x00B3FF }, /* NODE, L3BANK */ { 0x00C800, 0x00CFFF }, /* GAM */ - { 0x00D880, 0x00D8FF }, /* NODE */ { 0x00DD00, 0x00DDFF }, /* MEMPIPE */ { 0x00E900, 0x00E97F }, /* MEMPIPE */ { 0x00F000, 0x00FFFF }, /* GAM, GAMWKR */ @@ -267,7 +265,7 @@ static const struct xe_mmio_range xe3p_xpc_gam_grp1_steering_table[] = { {}, }; -static const struct xe_mmio_range xe3p_xpc_node_steering_table[] = { +static const struct xe_mmio_range xe2_node_steering_table[] = { { 0x00B000, 0x00B0FF }, { 0x00D880, 0x00D8FF }, {}, @@ -298,7 +296,7 @@ static void init_steering_l3bank(struct xe_gt *gt) struct xe_device *xe = gt_to_xe(gt); struct xe_mmio *mmio = >->mmio; - if (GRAPHICS_VER(xe) >= 35) { + if (GRAPHICS_VER(xe) >= 20) { unsigned int first_bank = xe_l3_bank_mask_ffs(gt->fuse_topo.l3_bank_mask); const int banks_per_node = 4; unsigned int node = first_bank / banks_per_node; @@ -430,19 +428,6 @@ void xe_gt_mcr_get_dss_steering(const struct xe_gt *gt, unsigned int dss, u16 *g *instance = dss % gt->steering_dss_per_grp; } -/** - * xe_gt_mcr_steering_info_to_dss_id - Get DSS ID from group/instance steering - * @gt: GT structure - * @group: steering group ID - * @instance: steering instance ID - * - * Return: the converted DSS id. - */ -u32 xe_gt_mcr_steering_info_to_dss_id(struct xe_gt *gt, u16 group, u16 instance) -{ - return group * dss_per_group(gt) + instance; -} - static void init_steering_dss(struct xe_gt *gt) { gt->steering_dss_per_grp = dss_per_group(gt); @@ -536,7 +521,7 @@ void xe_gt_mcr_init_early(struct xe_gt *gt) gt->steering[GAM1].ranges = xe3p_xpc_gam_grp1_steering_table; gt->steering[INSTANCE0].ranges = xe3p_xpc_instance0_steering_table; gt->steering[L3BANK].ranges = xelpg_l3bank_steering_table; - gt->steering[NODE].ranges = xe3p_xpc_node_steering_table; + gt->steering[NODE].ranges = xe2_node_steering_table; } else if (GRAPHICS_VERx100(xe) >= 3510) { gt->steering[DSS].ranges = xe2lpg_dss_steering_table; gt->steering[INSTANCE0].ranges = xe3p_lpg_instance0_steering_table; @@ -544,6 +529,8 @@ void xe_gt_mcr_init_early(struct xe_gt *gt) gt->steering[DSS].ranges = xe2lpg_dss_steering_table; gt->steering[SQIDI_PSMI].ranges = xe2lpg_sqidi_psmi_steering_table; gt->steering[INSTANCE0].ranges = xe2lpg_instance0_steering_table; + gt->steering[L3BANK].ranges = xelpg_l3bank_steering_table; + gt->steering[NODE].ranges = xe2_node_steering_table; } else if (GRAPHICS_VERx100(xe) >= 1270) { gt->steering[INSTANCE0].ranges = xelpg_instance0_steering_table; gt->steering[L3BANK].ranges = xelpg_l3bank_steering_table; diff --git a/drivers/gpu/drm/xe/xe_gt_mcr.h b/drivers/gpu/drm/xe/xe_gt_mcr.h index 283a1c9770e2..2be9419b8acc 100644 --- a/drivers/gpu/drm/xe/xe_gt_mcr.h +++ b/drivers/gpu/drm/xe/xe_gt_mcr.h @@ -33,7 +33,6 @@ bool xe_gt_mcr_get_nonterminated_steering(struct xe_gt *gt, void xe_gt_mcr_steering_dump(struct xe_gt *gt, struct drm_printer *p); void xe_gt_mcr_get_dss_steering(const struct xe_gt *gt, unsigned int dss, u16 *group, u16 *instance); -u32 xe_gt_mcr_steering_info_to_dss_id(struct xe_gt *gt, u16 group, u16 instance); /* * Loop over each DSS and determine the group and instance IDs that diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf.c index fb5c9101e275..7868056841b3 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf.c @@ -219,6 +219,7 @@ static void pf_restart(struct xe_gt *gt) xe_gt_assert(gt, !xe_pm_runtime_suspended(xe)); + xe_gt_sriov_pf_policy_restart(gt); xe_gt_sriov_pf_config_restart(gt); xe_gt_sriov_pf_control_restart(gt); diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c index 2f376b5fb088..2c9b85b84b1b 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c @@ -285,6 +285,13 @@ static u32 encode_config_ggtt(u32 *cfg, const struct xe_gt_sriov_config *config, return encode_ggtt(cfg, xe_ggtt_node_addr(node), xe_ggtt_node_size(node), details); } +static bool custom_sched_priority(struct xe_gt *gt, u32 priority) +{ + return xe_gt_sriov_pf_policy_get_sched_if_idle_locked(gt) ? + priority != GUC_SCHED_PRIORITY_NORMAL : + priority != GUC_SCHED_PRIORITY_LOW; +} + static u32 encode_config_sched(struct xe_gt *gt, u32 *cfg, u32 n, const struct xe_gt_sriov_config *config) { @@ -313,6 +320,11 @@ static u32 encode_config_sched(struct xe_gt *gt, u32 *cfg, u32 n, cfg[n++] = config->preempt_timeout[0]; } + if (custom_sched_priority(gt, config->sched_priority)) { + cfg[n++] = PREP_GUC_KLV_TAG(VF_CFG_SCHED_PRIORITY); + cfg[n++] = config->sched_priority; + } + return n; } @@ -1922,29 +1934,45 @@ static u64 pf_profile_fair_lmem(struct xe_gt *gt, unsigned int num_vfs) return ALIGN_DOWN(fair, alignment); } -static void __pf_show_provisioning_lmem(struct xe_gt *gt, unsigned int first_vf, - unsigned int num_vfs, bool provisioned) +static void __pf_show_provisioned(struct xe_gt *gt, unsigned int first_vf, + unsigned int num_vfs, bool provisioned, + u32 (*get32)(struct xe_gt *, unsigned int), + u64 (*get64)(struct xe_gt *, unsigned int), + const char *what) { unsigned int allvfs = 1 + xe_gt_sriov_pf_get_totalvfs(gt); /* PF plus VFs */ unsigned long *bitmap __free(bitmap) = bitmap_zalloc(allvfs, GFP_KERNEL); unsigned int weight; unsigned int n; + bool pf; + + xe_gt_assert(gt, get32 || get64); if (!bitmap) return; for (n = first_vf; n < first_vf + num_vfs; n++) { - if (!!pf_get_vf_config_lmem(gt, VFID(n)) == provisioned) + if ((get32 && (!!get32(gt, VFID(n)) == provisioned)) || + (get64 && (!!get64(gt, VFID(n)) == provisioned))) bitmap_set(bitmap, n, 1); } + pf = test_and_clear_bit(0, bitmap); weight = bitmap_weight(bitmap, allvfs); - if (!weight) + if (!pf && !weight) return; - xe_gt_sriov_info(gt, "VF%s%*pbl %s provisioned with VRAM\n", - weight > 1 ? "s " : "", allvfs, bitmap, - provisioned ? "already" : "not"); + xe_gt_sriov_info(gt, "%s%s%s%s%*pbl %s provisioned with %s\n", + pf ? "PF" : "", pf && weight ? " and " : "", + weight ? "VF" : "", weight > 1 ? "s " : "", + allvfs, bitmap, provisioned ? "already" : "not", what); +} + +static void __pf_show_provisioning_lmem(struct xe_gt *gt, unsigned int first_vf, + unsigned int num_vfs, bool provisioned) +{ + __pf_show_provisioned(gt, first_vf, num_vfs, provisioned, + NULL, pf_get_vf_config_lmem, "VRAM"); } static void pf_show_all_provisioned_lmem(struct xe_gt *gt) @@ -2078,6 +2106,17 @@ static u32 pf_get_exec_quantum(struct xe_gt *gt, unsigned int vfid) return config->exec_quantum[0]; } +static bool pf_non_default_exec_quantum(struct xe_gt *gt, unsigned int vfid) +{ + struct xe_gt_sriov_config *config = pf_pick_vf_config(gt, vfid); + int i; + + for (i = 0; i < ARRAY_SIZE(config->exec_quantum); i++) + if (config->exec_quantum[i]) + return true; + return false; +} + /** * xe_gt_sriov_pf_config_set_exec_quantum_locked() - Configure PF/VF execution quantum. * @gt: the &xe_gt @@ -2154,6 +2193,25 @@ u32 xe_gt_sriov_pf_config_get_exec_quantum(struct xe_gt *gt, unsigned int vfid) return pf_get_exec_quantum(gt, vfid); } +static int pf_bulk_set_exec_quantum(struct xe_gt *gt, u32 exec_quantum, + unsigned int first_vf, unsigned int num_vfs) +{ + unsigned int n; + int err = 0; + + lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); + + for (n = first_vf; n < first_vf + num_vfs; n++) { + err = pf_provision_exec_quantum(gt, VFID(n), exec_quantum); + if (err) + break; + } + + return pf_config_bulk_set_u32_done(gt, first_vf, num_vfs, exec_quantum, + pf_get_exec_quantum, "execution quantum", + exec_quantum_unit, n, err); +} + /** * xe_gt_sriov_pf_config_bulk_set_exec_quantum_locked() - Configure EQ for PF and VFs. * @gt: the &xe_gt to configure @@ -2166,20 +2224,8 @@ u32 xe_gt_sriov_pf_config_get_exec_quantum(struct xe_gt *gt, unsigned int vfid) int xe_gt_sriov_pf_config_bulk_set_exec_quantum_locked(struct xe_gt *gt, u32 exec_quantum) { unsigned int totalvfs = xe_gt_sriov_pf_get_totalvfs(gt); - unsigned int n; - int err = 0; - lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); - - for (n = 0; n <= totalvfs; n++) { - err = pf_provision_exec_quantum(gt, VFID(n), exec_quantum); - if (err) - break; - } - - return pf_config_bulk_set_u32_done(gt, 0, 1 + totalvfs, exec_quantum, - pf_get_exec_quantum, "execution quantum", - exec_quantum_unit, n, err); + return pf_bulk_set_exec_quantum(gt, exec_quantum, PFID, 1 + totalvfs); } static int pf_provision_groups_exec_quantums(struct xe_gt *gt, unsigned int vfid, @@ -2293,6 +2339,17 @@ static u32 pf_get_preempt_timeout(struct xe_gt *gt, unsigned int vfid) return config->preempt_timeout[0]; } +static bool pf_non_default_preempt_timeout(struct xe_gt *gt, unsigned int vfid) +{ + struct xe_gt_sriov_config *config = pf_pick_vf_config(gt, vfid); + int i; + + for (i = 0; i < ARRAY_SIZE(config->preempt_timeout); i++) + if (config->preempt_timeout[i]) + return true; + return false; +} + /** * xe_gt_sriov_pf_config_set_preempt_timeout_locked() - Configure PF/VF preemption timeout. * @gt: the &xe_gt @@ -2368,6 +2425,25 @@ u32 xe_gt_sriov_pf_config_get_preempt_timeout(struct xe_gt *gt, unsigned int vfi return pf_get_preempt_timeout(gt, vfid); } +static int pf_bulk_set_preempt_timeout(struct xe_gt *gt, u32 preempt_timeout, + unsigned int first_vf, unsigned int num_vfs) +{ + unsigned int n; + int err = 0; + + lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); + + for (n = first_vf; n < first_vf + num_vfs; n++) { + err = pf_provision_preempt_timeout(gt, VFID(n), preempt_timeout); + if (err) + break; + } + + return pf_config_bulk_set_u32_done(gt, first_vf, num_vfs, preempt_timeout, + pf_get_preempt_timeout, "preemption timeout", + preempt_timeout_unit, n, err); +} + /** * xe_gt_sriov_pf_config_bulk_set_preempt_timeout_locked() - Configure PT for PF and VFs. * @gt: the &xe_gt to configure @@ -2380,20 +2456,8 @@ u32 xe_gt_sriov_pf_config_get_preempt_timeout(struct xe_gt *gt, unsigned int vfi int xe_gt_sriov_pf_config_bulk_set_preempt_timeout_locked(struct xe_gt *gt, u32 preempt_timeout) { unsigned int totalvfs = xe_gt_sriov_pf_get_totalvfs(gt); - unsigned int n; - int err = 0; - lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); - - for (n = 0; n <= totalvfs; n++) { - err = pf_provision_preempt_timeout(gt, VFID(n), preempt_timeout); - if (err) - break; - } - - return pf_config_bulk_set_u32_done(gt, 0, 1 + totalvfs, preempt_timeout, - pf_get_preempt_timeout, "preemption timeout", - preempt_timeout_unit, n, err); + return pf_bulk_set_preempt_timeout(gt, preempt_timeout, PFID, 1 + totalvfs); } static int pf_provision_groups_preempt_timeouts(struct xe_gt *gt, unsigned int vfid, @@ -2500,7 +2564,7 @@ static int pf_provision_sched_priority(struct xe_gt *gt, unsigned int vfid, u32 return 0; } -static int pf_get_sched_priority(struct xe_gt *gt, unsigned int vfid) +static u32 pf_get_sched_priority(struct xe_gt *gt, unsigned int vfid) { struct xe_gt_sriov_config *config = pf_pick_vf_config(gt, vfid); @@ -2550,6 +2614,35 @@ u32 xe_gt_sriov_pf_config_get_sched_priority(struct xe_gt *gt, unsigned int vfid return priority; } +/** + * xe_gt_sriov_pf_config_force_sched_priority_locked() - Force update scheduling priority. + * @gt: the &xe_gt + * @priority: new scheduling priority to set + * + * This function allows to update cached values of the scheduling priorities of all + * VFs (and PF) as result of applying the `GUC_KLV_VGT_POLICY_SCHED_IF_IDLE`_ policy. + * + * This function can only be called on PF. + */ +void xe_gt_sriov_pf_config_force_sched_priority_locked(struct xe_gt *gt, u32 priority) +{ + unsigned int total_vfs = xe_gt_sriov_pf_get_totalvfs(gt); + struct xe_gt_sriov_config *config; + unsigned int n; + + xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); + lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); + + for (n = 0; n <= total_vfs; n++) { + config = pf_pick_vf_config(gt, VFID(n)); + config->sched_priority = priority; + } + + pf_config_bulk_set_u32_done(gt, PFID, 1 + total_vfs, priority, + pf_get_sched_priority, "scheduling priority", + sched_priority_unit, n, 0); +} + static void pf_reset_config_sched(struct xe_gt *gt, struct xe_gt_sriov_config *config) { int i; @@ -2562,6 +2655,104 @@ static void pf_reset_config_sched(struct xe_gt *gt, struct xe_gt_sriov_config *c } } +static bool pf_non_default_sched(struct xe_gt *gt, unsigned int vfid) +{ + return pf_non_default_exec_quantum(gt, vfid) || + pf_non_default_preempt_timeout(gt, vfid) || + custom_sched_priority(gt, pf_get_sched_priority(gt, vfid)); +} + +static void __pf_show_provisioned_sched(struct xe_gt *gt, unsigned int first_vf, + unsigned int num_vfs, bool provisioned) +{ + __pf_show_provisioned(gt, first_vf, num_vfs, provisioned, + pf_get_exec_quantum, NULL, "EQ"); + __pf_show_provisioned(gt, first_vf, num_vfs, provisioned, + pf_get_preempt_timeout, NULL, "PT"); + + /* we only care about non-default priorities */ + if (provisioned) + __pf_show_provisioned(gt, first_vf, num_vfs, true, + pf_get_sched_priority, NULL, "PRIORITY"); +} + +static void pf_show_all_provisioned_sched(struct xe_gt *gt) +{ + __pf_show_provisioned_sched(gt, PFID, 1 + xe_gt_sriov_pf_get_totalvfs(gt), true); +} + +static void pf_show_unprovisioned_sched(struct xe_gt *gt, unsigned int num_vfs) +{ + __pf_show_provisioned_sched(gt, PFID, 1 + num_vfs, false); +} + +static bool pf_needs_provision_sched(struct xe_gt *gt, unsigned int num_vfs) +{ + unsigned int vfid; + + for (vfid = PFID; vfid <= PFID + num_vfs; vfid++) { + if (pf_non_default_sched(gt, vfid)) { + pf_show_all_provisioned_sched(gt); + pf_show_unprovisioned_sched(gt, num_vfs); + return false; + } + } + + if (xe_gt_sriov_pf_policy_get_sched_if_idle_locked(gt)) { + pf_show_all_provisioned_sched(gt); + pf_show_unprovisioned_sched(gt, num_vfs); + return false; + } + + pf_show_all_provisioned_sched(gt); + return true; +} + +/* With 16ms EQ/PT GuC should be able to handle up to 63 VFs within 2s */ +#define XE_FAIR_EXEC_QUANTUM_MS 16 +#define XE_FAIR_PREEMPT_TIMEOUT_US 16000 +#define XE_FAIR_SCHED_PRIORITY GUC_SCHED_PRIORITY_LOW +#define XE_ADMIN_PF_SCHED_PRIORITY GUC_SCHED_PRIORITY_HIGH + +/** + * xe_gt_sriov_pf_config_set_fair_sched() - Provision PF and VFs with fair scheduling. + * @gt: the &xe_gt + * @num_vfs: number of VFs to provision (can't be 0) + * + * This function can only be called on PF. + * + * Return: 0 on success or a negative error code on failure. + */ +int xe_gt_sriov_pf_config_set_fair_sched(struct xe_gt *gt, unsigned int num_vfs) +{ + int result = 0; + int err; + + xe_gt_assert(gt, num_vfs); + xe_gt_assert(gt, XE_FAIR_EXEC_QUANTUM_MS); + xe_gt_assert(gt, XE_FAIR_PREEMPT_TIMEOUT_US); + + guard(mutex)(xe_gt_sriov_pf_master_mutex(gt)); + + if (!pf_needs_provision_sched(gt, num_vfs)) + return 0; + + err = pf_bulk_set_exec_quantum(gt, XE_FAIR_EXEC_QUANTUM_MS, PFID, 1 + num_vfs); + result = result ?: err; + err = pf_bulk_set_preempt_timeout(gt, XE_FAIR_PREEMPT_TIMEOUT_US, PFID, 1 + num_vfs); + result = result ?: err; + + xe_gt_assert(gt, XE_FAIR_SCHED_PRIORITY == GUC_SCHED_PRIORITY_LOW); + xe_gt_assert(gt, !xe_gt_sriov_pf_policy_get_sched_if_idle_locked(gt)); + + if (xe_sriov_pf_admin_only(gt_to_xe(gt))) { + err = pf_provision_sched_priority(gt, PFID, XE_ADMIN_PF_SCHED_PRIORITY); + result = result ?: err; + } + + return result; +} + static int pf_provision_threshold(struct xe_gt *gt, unsigned int vfid, enum xe_guc_klv_threshold_index index, u32 value) { @@ -2838,6 +3029,9 @@ static int pf_validate_vf_config(struct xe_gt *gt, unsigned int vfid) valid_all = valid_all && valid_lmem; } + /* also check optional EQ/PT/PRIO */ + valid_any = valid_any || pf_non_default_sched(gt, vfid); + return valid_all ? 0 : valid_any ? -ENOKEY : -ENODATA; } diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.h b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.h index 4a004ecd6140..2ec62c12ad5c 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.h +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.h @@ -71,12 +71,14 @@ int xe_gt_sriov_pf_config_set_groups_preempt_timeouts(struct xe_gt *gt, unsigned u32 xe_gt_sriov_pf_config_get_sched_priority(struct xe_gt *gt, unsigned int vfid); int xe_gt_sriov_pf_config_set_sched_priority(struct xe_gt *gt, unsigned int vfid, u32 priority); +void xe_gt_sriov_pf_config_force_sched_priority_locked(struct xe_gt *gt, u32 priority); u32 xe_gt_sriov_pf_config_get_threshold(struct xe_gt *gt, unsigned int vfid, enum xe_guc_klv_threshold_index index); int xe_gt_sriov_pf_config_set_threshold(struct xe_gt *gt, unsigned int vfid, enum xe_guc_klv_threshold_index index, u32 value); +int xe_gt_sriov_pf_config_set_fair_sched(struct xe_gt *gt, unsigned int num_vfs); int xe_gt_sriov_pf_config_set_fair(struct xe_gt *gt, unsigned int vfid, unsigned int num_vfs); int xe_gt_sriov_pf_config_sanitize(struct xe_gt *gt, unsigned int vfid, long timeout); int xe_gt_sriov_pf_config_release(struct xe_gt *gt, unsigned int vfid, bool force); diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c index 848e24926ecd..e8458d63742d 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c @@ -8,6 +8,7 @@ #include "abi/guc_actions_sriov_abi.h" #include "xe_gt.h" +#include "xe_gt_sriov_pf_config.h" #include "xe_gt_sriov_pf_helpers.h" #include "xe_gt_sriov_pf_policy.h" #include "xe_gt_sriov_printk.h" @@ -16,7 +17,6 @@ #include "xe_guc_ct.h" #include "xe_guc_klv_helpers.h" #include "xe_guc_submit.h" -#include "xe_pm.h" /* * Return: number of KLVs that were successfully parsed and saved, @@ -67,6 +67,15 @@ static int pf_push_policy_buf_klvs(struct xe_gt *gt, u32 num_klvs, return err; } + if (IS_ENABLED(CONFIG_DRM_XE_DEBUG_SRIOV)) { + struct drm_printer p = xe_gt_dbg_printer(gt); + void *klvs = xe_guc_buf_cpu_ptr(buf); + + xe_gt_sriov_dbg(gt, "pushed policy update with %u KLV%s:\n", + num_klvs, str_plural(num_klvs)); + xe_guc_klv_print(klvs, num_dwords, &p); + } + return 0; } @@ -153,33 +162,14 @@ static int pf_update_policy_u32(struct xe_gt *gt, u16 key, u32 *policy, u32 valu return 0; } -static void pf_bulk_reset_sched_priority(struct xe_gt *gt, u32 priority) -{ - unsigned int total_vfs = 1 + xe_gt_sriov_pf_get_totalvfs(gt); - unsigned int n; - - xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); - lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); - - for (n = 0; n < total_vfs; n++) - gt->sriov.pf.vfs[n].config.sched_priority = priority; -} - static int pf_provision_sched_if_idle(struct xe_gt *gt, bool enable) { - int err; - xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); - err = pf_update_policy_bool(gt, GUC_KLV_VGT_POLICY_SCHED_IF_IDLE_KEY, - >->sriov.pf.policy.guc.sched_if_idle, - enable); - - if (!err) - pf_bulk_reset_sched_priority(gt, enable ? GUC_SCHED_PRIORITY_NORMAL : - GUC_SCHED_PRIORITY_LOW); - return err; + return pf_update_policy_bool(gt, GUC_KLV_VGT_POLICY_SCHED_IF_IDLE_KEY, + >->sriov.pf.policy.guc.sched_if_idle, + enable); } static int pf_reprovision_sched_if_idle(struct xe_gt *gt) @@ -187,6 +177,9 @@ static int pf_reprovision_sched_if_idle(struct xe_gt *gt) xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); + if (!gt->sriov.pf.policy.guc.sched_if_idle) + return 0; + return pf_provision_sched_if_idle(gt, gt->sriov.pf.policy.guc.sched_if_idle); } @@ -199,7 +192,39 @@ static void pf_sanitize_sched_if_idle(struct xe_gt *gt) } /** - * xe_gt_sriov_pf_policy_set_sched_if_idle - Control the 'sched_if_idle' policy. + * xe_gt_sriov_pf_policy_set_sched_if_idle_locked() - Control the 'sched_if_idle' policy. + * @gt: the &xe_gt where to apply the policy + * @enable: the value of the 'sched_if_idle' policy + * + * This function can only be called on PF. + * + * Return: 0 on success or a negative error code on failure. + */ +int xe_gt_sriov_pf_policy_set_sched_if_idle_locked(struct xe_gt *gt, bool enable) +{ + u32 priority; + int err; + + lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); + + err = pf_provision_sched_if_idle(gt, enable); + if (err) + return err; + + /* + * As of GuC 70.12 a change of this policy impacts individual configs + * of all VFs. See `GUC_KLV_VGT_POLICY_SCHED_IF_IDLE`_ for details. + */ + xe_gt_assert(gt, GUC_FIRMWARE_VER_AT_LEAST(>->uc.guc, 70, 12)); + + priority = enable ? GUC_SCHED_PRIORITY_NORMAL : GUC_SCHED_PRIORITY_LOW; + xe_gt_sriov_pf_config_force_sched_priority_locked(gt, priority); + + return 0; +} + +/** + * xe_gt_sriov_pf_policy_set_sched_if_idle() - Control the 'sched_if_idle' policy. * @gt: the &xe_gt where to apply the policy * @enable: the value of the 'sched_if_idle' policy * @@ -209,13 +234,26 @@ static void pf_sanitize_sched_if_idle(struct xe_gt *gt) */ int xe_gt_sriov_pf_policy_set_sched_if_idle(struct xe_gt *gt, bool enable) { - int err; + xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); + guard(mutex)(xe_gt_sriov_pf_master_mutex(gt)); - mutex_lock(xe_gt_sriov_pf_master_mutex(gt)); - err = pf_provision_sched_if_idle(gt, enable); - mutex_unlock(xe_gt_sriov_pf_master_mutex(gt)); + return xe_gt_sriov_pf_policy_set_sched_if_idle_locked(gt, enable); +} - return err; +/** + * xe_gt_sriov_pf_policy_get_sched_if_idle_locked() - Retrieve value of 'sched_if_idle' policy. + * @gt: the &xe_gt where to read the policy from + * + * This function can only be called on PF. + * + * Return: last value of 'sched_if_idle' policy applied. + */ +bool xe_gt_sriov_pf_policy_get_sched_if_idle_locked(struct xe_gt *gt) +{ + xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); + lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); + + return gt->sriov.pf.policy.guc.sched_if_idle; } /** @@ -228,15 +266,10 @@ int xe_gt_sriov_pf_policy_set_sched_if_idle(struct xe_gt *gt, bool enable) */ bool xe_gt_sriov_pf_policy_get_sched_if_idle(struct xe_gt *gt) { - bool enable; - xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); + guard(mutex)(xe_gt_sriov_pf_master_mutex(gt)); - mutex_lock(xe_gt_sriov_pf_master_mutex(gt)); - enable = gt->sriov.pf.policy.guc.sched_if_idle; - mutex_unlock(xe_gt_sriov_pf_master_mutex(gt)); - - return enable; + return xe_gt_sriov_pf_policy_get_sched_if_idle_locked(gt); } static int pf_provision_reset_engine(struct xe_gt *gt, bool enable) @@ -253,6 +286,9 @@ static int pf_reprovision_reset_engine(struct xe_gt *gt) xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); + if (!gt->sriov.pf.policy.guc.reset_engine) + return 0; + return pf_provision_reset_engine(gt, gt->sriov.pf.policy.guc.reset_engine); } @@ -319,6 +355,9 @@ static int pf_reprovision_sample_period(struct xe_gt *gt) xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); + if (!gt->sriov.pf.policy.guc.sample_period) + return 0; + return pf_provision_sample_period(gt, gt->sriov.pf.policy.guc.sample_period); } @@ -689,30 +728,23 @@ void xe_gt_sriov_pf_policy_sanitize(struct xe_gt *gt) } /** - * xe_gt_sriov_pf_policy_reprovision - Reprovision (and optionally reset) policy settings. + * xe_gt_sriov_pf_policy_restart() - Reprovision policy settings. * @gt: the &xe_gt - * @reset: if true will reprovision using default values instead of latest * * This function can only be called on PF. * * Return: 0 on success or a negative error code on failure. */ -int xe_gt_sriov_pf_policy_reprovision(struct xe_gt *gt, bool reset) +int xe_gt_sriov_pf_policy_restart(struct xe_gt *gt) { int err = 0; - xe_pm_runtime_get_noresume(gt_to_xe(gt)); + guard(mutex)(xe_gt_sriov_pf_master_mutex(gt)); - mutex_lock(xe_gt_sriov_pf_master_mutex(gt)); - if (reset) - pf_sanitize_guc_policies(gt); err |= pf_reprovision_sched_if_idle(gt); err |= pf_reprovision_reset_engine(gt); err |= pf_reprovision_sample_period(gt); err |= pf_reprovision_sched_groups(gt); - mutex_unlock(xe_gt_sriov_pf_master_mutex(gt)); - - xe_pm_runtime_put(gt_to_xe(gt)); return err ? -ENXIO : 0; } diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.h b/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.h index bd73aa58f9ca..d667d66897b1 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.h +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.h @@ -14,7 +14,9 @@ struct drm_printer; struct xe_gt; int xe_gt_sriov_pf_policy_set_sched_if_idle(struct xe_gt *gt, bool enable); +int xe_gt_sriov_pf_policy_set_sched_if_idle_locked(struct xe_gt *gt, bool enable); bool xe_gt_sriov_pf_policy_get_sched_if_idle(struct xe_gt *gt); +bool xe_gt_sriov_pf_policy_get_sched_if_idle_locked(struct xe_gt *gt); int xe_gt_sriov_pf_policy_set_reset_engine(struct xe_gt *gt, bool enable); bool xe_gt_sriov_pf_policy_get_reset_engine(struct xe_gt *gt); int xe_gt_sriov_pf_policy_set_sample_period(struct xe_gt *gt, u32 value); @@ -29,7 +31,7 @@ bool xe_gt_sriov_pf_policy_sched_groups_enabled(struct xe_gt *gt); void xe_gt_sriov_pf_policy_init(struct xe_gt *gt); void xe_gt_sriov_pf_policy_sanitize(struct xe_gt *gt); -int xe_gt_sriov_pf_policy_reprovision(struct xe_gt *gt, bool reset); +int xe_gt_sriov_pf_policy_restart(struct xe_gt *gt); int xe_gt_sriov_pf_policy_print(struct xe_gt *gt, struct drm_printer *p); #endif diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_types.h b/drivers/gpu/drm/xe/xe_gt_sriov_pf_types.h index 667b8310478d..6296483c44ec 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_types.h +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_types.h @@ -49,7 +49,6 @@ struct xe_gt_sriov_pf_workers { * @service: service data. * @control: control data. * @policy: policy data. - * @migration: migration data. * @spare: PF-only provisioning configuration. * @vfs: metadata for all VFs. */ diff --git a/drivers/gpu/drm/xe/xe_gt_stats.c b/drivers/gpu/drm/xe/xe_gt_stats.c index 59b3b23a54c8..789397514f3e 100644 --- a/drivers/gpu/drm/xe/xe_gt_stats.c +++ b/drivers/gpu/drm/xe/xe_gt_stats.c @@ -9,6 +9,47 @@ #include "xe_device.h" #include "xe_gt_stats.h" +/** + * DOC: Xe GT Statistics + * + * Overview + * ======== + * + * The Xe driver exposes per-GT statistics through the debugfs filesystem at:: + * + * /sys/kernel/debug/dri//gt/stats + * + * This interface requires the kernel to be built with ``CONFIG_DEBUG_FS=y``. + * + * Reading statistics + * ================== + * + * Reading the file prints all available statistics, one per line, in + * ``name: value`` format:: + * + * $ cat /sys/kernel/debug/dri/0/gt0/stats + * svm_pagefault_count: 0 + * tlb_inval_count: 1234 + * ... + * + * All values are 64-bit unsigned integers aggregated across all CPUs. + * Counters accumulate since the driver was loaded or since the last explicit + * reset. Timing counters use microseconds as their unit; data volume counters + * use KiB. + * + * Resetting statistics + * ==================== + * + * Writing a boolean true value to the file resets all counters to zero:: + * + * echo 1 > /sys/kernel/debug/dri/0/gt0/stats + * + * Any value accepted by ``kstrtobool()`` (e.g. ``1``, ``y``, ``yes``, + * ``on``) triggers the reset. Resetting while the GPU is active may yield + * unpredictable intermediate values; it is recommended to reset only when + * the GPU is idle. + */ + static void xe_gt_stats_fini(struct drm_device *drm, void *arg) { struct xe_gt *gt = arg; diff --git a/drivers/gpu/drm/xe/xe_gt_stats_types.h b/drivers/gpu/drm/xe/xe_gt_stats_types.h index 081c787ddcb6..425491bed6c4 100644 --- a/drivers/gpu/drm/xe/xe_gt_stats_types.h +++ b/drivers/gpu/drm/xe/xe_gt_stats_types.h @@ -8,6 +8,124 @@ #include +/** + * enum xe_gt_stats_id - GT statistics identifiers + * @XE_GT_STATS_ID_SVM_PAGEFAULT_COUNT: Total SVM page faults handled. + * @XE_GT_STATS_ID_TLB_INVAL: Total GPU Translation Lookaside Buffer (TLB) + * invalidations issued. + * @XE_GT_STATS_ID_SVM_TLB_INVAL_COUNT: TLB invalidations issued during SVM + * page-fault handling. + * @XE_GT_STATS_ID_SVM_TLB_INVAL_US: Cumulative time (µs) waiting for TLB + * invalidations during SVM page-fault handling. + * + * @XE_GT_STATS_ID_VMA_PAGEFAULT_COUNT: Buffer-object (non-SVM) page faults + * handled. + * @XE_GT_STATS_ID_VMA_PAGEFAULT_KB: Size (KiB) of VMAs involved in + * buffer-object page fault handling. + * @XE_GT_STATS_ID_INVALID_PREFETCH_PAGEFAULT_COUNT: GPU prefetch faults for + * addresses with no valid backing. + * + * @XE_GT_STATS_ID_SVM_4K_PAGEFAULT_COUNT: SVM page faults resolved by + * mapping 4K pages. + * @XE_GT_STATS_ID_SVM_64K_PAGEFAULT_COUNT: SVM page faults resolved by + * mapping 64K pages. + * @XE_GT_STATS_ID_SVM_2M_PAGEFAULT_COUNT: SVM page faults resolved by + * mapping 2M pages. + * @XE_GT_STATS_ID_SVM_4K_VALID_PAGEFAULT_COUNT: Valid SVM page faults + * at 4K page size, where the GPU mapping was already valid — resolved without + * creating new mappings. + * @XE_GT_STATS_ID_SVM_64K_VALID_PAGEFAULT_COUNT: Valid SVM page faults at 64K + * page size. + * @XE_GT_STATS_ID_SVM_2M_VALID_PAGEFAULT_COUNT: Valid SVM page faults at 2M + * page size. + * @XE_GT_STATS_ID_SVM_4K_PAGEFAULT_US: Cumulative time (µs) handling 4K SVM + * page faults. + * @XE_GT_STATS_ID_SVM_64K_PAGEFAULT_US: Cumulative time (µs) handling 64K + * SVM page faults. + * @XE_GT_STATS_ID_SVM_2M_PAGEFAULT_US: Cumulative time (µs) handling 2M SVM + * page faults. + * + * @XE_GT_STATS_ID_SVM_4K_MIGRATE_COUNT: 4K pages moved from CPU to device + * memory. + * @XE_GT_STATS_ID_SVM_64K_MIGRATE_COUNT: 64K pages moved from CPU to device + * memory. + * @XE_GT_STATS_ID_SVM_2M_MIGRATE_COUNT: 2M pages moved from CPU to device + * memory. + * @XE_GT_STATS_ID_SVM_4K_MIGRATE_US: Cumulative time (µs) moving 4K pages + * from CPU to device memory. + * @XE_GT_STATS_ID_SVM_64K_MIGRATE_US: Cumulative time (µs) moving 64K pages + * from CPU to device memory. + * @XE_GT_STATS_ID_SVM_2M_MIGRATE_US: Cumulative time (µs) moving 2M pages + * from CPU to device memory. + * + * @XE_GT_STATS_ID_SVM_DEVICE_COPY_US: Cumulative time (µs) for memory copies to + * device, across all page sizes. + * @XE_GT_STATS_ID_SVM_4K_DEVICE_COPY_US: Cumulative time (µs) for memory copies + * of 4K pages to device. + * @XE_GT_STATS_ID_SVM_64K_DEVICE_COPY_US: Cumulative time (µs) for memory + * copies of 64K pages to device. + * @XE_GT_STATS_ID_SVM_2M_DEVICE_COPY_US: Cumulative time (µs) for memory copies + * of 2M pages to device. + * @XE_GT_STATS_ID_SVM_CPU_COPY_US: Cumulative time (µs) for memory copies to + * CPU, across all page sizes. + * @XE_GT_STATS_ID_SVM_4K_CPU_COPY_US: Cumulative time (µs) for memory copies of + * 4K pages to CPU. + * @XE_GT_STATS_ID_SVM_64K_CPU_COPY_US: Cumulative time (µs) for memory copies + * of 64K pages to CPU. + * @XE_GT_STATS_ID_SVM_2M_CPU_COPY_US: Cumulative time (µs) for memory copies of + * 2M pages to CPU. + * @XE_GT_STATS_ID_SVM_DEVICE_COPY_KB: Data (KiB) copied to device across all + * page sizes. + * @XE_GT_STATS_ID_SVM_4K_DEVICE_COPY_KB: Data (KiB) copied to device for 4K + * pages. + * @XE_GT_STATS_ID_SVM_64K_DEVICE_COPY_KB: Data (KiB) copied to device for + * 64K pages. + * @XE_GT_STATS_ID_SVM_2M_DEVICE_COPY_KB: Data (KiB) copied to device for 2M + * pages. + * @XE_GT_STATS_ID_SVM_CPU_COPY_KB: Data (KiB) copied to CPU across all page + * sizes. + * @XE_GT_STATS_ID_SVM_4K_CPU_COPY_KB: Data (KiB) copied to CPU for 4K pages. + * @XE_GT_STATS_ID_SVM_64K_CPU_COPY_KB: Data (KiB) copied to CPU for 64K pages. + * @XE_GT_STATS_ID_SVM_2M_CPU_COPY_KB: Data (KiB) copied to CPU for 2M pages. + * + * @XE_GT_STATS_ID_SVM_4K_GET_PAGES_US: Cumulative time (µs) getting CPU + * memory pages for GPU access at 4K page size. + * @XE_GT_STATS_ID_SVM_64K_GET_PAGES_US: Cumulative time (µs) getting CPU + * memory pages for GPU access at 64K page size. + * @XE_GT_STATS_ID_SVM_2M_GET_PAGES_US: Cumulative time (µs) getting CPU + * memory pages for GPU access at 2M page size. + * @XE_GT_STATS_ID_SVM_4K_BIND_US: Cumulative time (µs) binding 4K pages + * into the GPU page table. + * @XE_GT_STATS_ID_SVM_64K_BIND_US: Cumulative time (µs) binding 64K pages + * into the GPU page table. + * @XE_GT_STATS_ID_SVM_2M_BIND_US: Cumulative time (µs) binding 2M pages + * into the GPU page table. + * + * @XE_GT_STATS_ID_HW_ENGINE_GROUP_SUSPEND_LR_QUEUE_COUNT: Times the + * scheduler preempted a long-running (LR) GPU exec queue. + * @XE_GT_STATS_ID_HW_ENGINE_GROUP_SKIP_LR_QUEUE_COUNT: Times the scheduler + * skipped suspend because the system was idle. + * @XE_GT_STATS_ID_HW_ENGINE_GROUP_WAIT_DMA_QUEUE_COUNT: Times the driver + * stalled waiting for prior GPU work to complete before scheduling more. + * @XE_GT_STATS_ID_HW_ENGINE_GROUP_SUSPEND_LR_QUEUE_US: Cumulative time + * (µs) spent preempting long-running (LR) GPU exec queues. + * @XE_GT_STATS_ID_HW_ENGINE_GROUP_WAIT_DMA_QUEUE_US: Cumulative time (µs) + * stalled waiting for prior GPU work to complete. + * + * @XE_GT_STATS_ID_PRL_4K_ENTRY_COUNT: 4K-page entries from the page reclaim + * list that were processed. + * @XE_GT_STATS_ID_PRL_64K_ENTRY_COUNT: 64K-page entries from the page reclaim + * list that were processed. + * @XE_GT_STATS_ID_PRL_2M_ENTRY_COUNT: 2M-page entries from the page reclaim + * list that were processed. + * @XE_GT_STATS_ID_PRL_ISSUED_COUNT: Times a page reclamation was issued. + * @XE_GT_STATS_ID_PRL_ABORTED_COUNT: Times the page reclaim process was + * aborted. + * + * @__XE_GT_STATS_NUM_IDS: Number of valid IDs; not a real counter. + * + * See Documentation/gpu/xe/xe_gt_stats.rst. + */ enum xe_gt_stats_id { XE_GT_STATS_ID_SVM_PAGEFAULT_COUNT, XE_GT_STATS_ID_TLB_INVAL, diff --git a/drivers/gpu/drm/xe/xe_gt_types.h b/drivers/gpu/drm/xe/xe_gt_types.h index 8b55cf25a75f..7351aadd238e 100644 --- a/drivers/gpu/drm/xe/xe_gt_types.h +++ b/drivers/gpu/drm/xe/xe_gt_types.h @@ -136,7 +136,7 @@ struct xe_gt { /** @info.gmdid: raw GMD_ID value from hardware */ u32 gmdid; /** - * @multi_queue_engine_class_mask: Bitmask of engine classes with + * @info.multi_queue_engine_class_mask: Bitmask of engine classes with * multi queue support enabled. */ u16 multi_queue_engine_class_mask; @@ -355,7 +355,7 @@ struct xe_gt { /** @user_engines: engines present in GT and available to userspace */ struct { /** - * @user_engines.mask: like @info->engine_mask, but take in + * @user_engines.mask: like @info.engine_mask, but take in * consideration only engines available to userspace */ u64 mask; diff --git a/drivers/gpu/drm/xe/xe_guc.c b/drivers/gpu/drm/xe/xe_guc.c index ccebb437e37f..e468b638271b 100644 --- a/drivers/gpu/drm/xe/xe_guc.c +++ b/drivers/gpu/drm/xe/xe_guc.c @@ -780,6 +780,14 @@ int xe_guc_init(struct xe_guc *guc) if (GUC_SUBMIT_VER(guc) < MAKE_GUC_VER(1, 14, 0)) xe->info.has_page_reclaim_hw_assist = false; + /* Disable indirect_ring_state if missing GuC 70.53+ WA 14025515070. */ + if (gt->info.has_indirect_ring_state && + XE_GT_WA(gt, 14025515070) && + GUC_SUBMIT_VER(guc) < MAKE_GUC_VER(1, 26, 0)) { + gt->info.has_indirect_ring_state = 0; + xe_gt_notice(gt, "indirect ring state requires WA in GuC submit ver 1.26+\n"); + } + if (IS_SRIOV_VF(xe)) { ret = devm_add_action_or_reset(xe->drm.dev, vf_guc_fini_hw, guc); if (ret) @@ -1693,13 +1701,8 @@ void xe_guc_reset_wait(struct xe_guc *guc) void xe_guc_stop_prepare(struct xe_guc *guc) { - if (!IS_SRIOV_VF(guc_to_xe(guc))) { - int err; - - err = xe_guc_pc_stop(&guc->pc); - xe_gt_WARN(guc_to_gt(guc), err, "Failed to stop GuC PC: %pe\n", - ERR_PTR(err)); - } + if (!IS_SRIOV_VF(guc_to_xe(guc))) + xe_guc_pc_stop(&guc->pc); } void xe_guc_stop(struct xe_guc *guc) diff --git a/drivers/gpu/drm/xe/xe_guc_ads.c b/drivers/gpu/drm/xe/xe_guc_ads.c index 81b5f01b1f65..ce651da6f318 100644 --- a/drivers/gpu/drm/xe/xe_guc_ads.c +++ b/drivers/gpu/drm/xe/xe_guc_ads.c @@ -360,6 +360,9 @@ static void guc_waklv_init(struct xe_guc_ads *ads) if (XE_GT_WA(gt, 14020001231)) guc_waklv_enable(ads, NULL, 0, &offset, &remain, GUC_WORKAROUND_KLV_DISABLE_PSMI_INTERRUPTS_AT_C6_ENTRY_RESTORE_AT_EXIT); + if (XE_GT_WA(gt, 14025515070) && GUC_FIRMWARE_VER_AT_LEAST(>->uc.guc, 70, 53)) + guc_waklv_enable(ads, NULL, 0, &offset, &remain, + GUC_WA_KLV_CLR_CS_INDIRECT_RING_STATE_IF_IDLE_AT_CTX_REG); size = guc_ads_waklv_size(ads) - remain; if (!size) @@ -742,10 +745,8 @@ static unsigned int guc_mmio_regset_write(struct xe_guc_ads *ads, struct xe_reg reg; bool skip; } *e, extra_regs[] = { - { .reg = RING_MODE(hwe->mmio_base), }, { .reg = RING_HWS_PGA(hwe->mmio_base), }, { .reg = RING_IMR(hwe->mmio_base), }, - { .reg = RCU_MODE, .skip = hwe != hwe_rcs_reset_domain }, { .reg = CCS_MODE, .skip = hwe != hwe_rcs_reset_domain || !xe_gt_ccs_mode_enabled(hwe->gt) }, }; diff --git a/drivers/gpu/drm/xe/xe_guc_capture.c b/drivers/gpu/drm/xe/xe_guc_capture.c index 2f5816c78fba..bc49e40165a3 100644 --- a/drivers/gpu/drm/xe/xe_guc_capture.c +++ b/drivers/gpu/drm/xe/xe_guc_capture.c @@ -111,7 +111,7 @@ struct __guc_capture_parsed_output { { RING_TAIL(0), REG_32BIT, 0, 0, 0, "RING_TAIL"}, \ { RING_CTL(0), REG_32BIT, 0, 0, 0, "RING_CTL"}, \ { RING_MI_MODE(0), REG_32BIT, 0, 0, 0, "RING_MI_MODE"}, \ - { RING_MODE(0), REG_32BIT, 0, 0, 0, "RING_MODE"}, \ + { GFX_MODE(0), REG_32BIT, 0, 0, 0, "GFX_MODE"}, \ { RING_ESR(0), REG_32BIT, 0, 0, 0, "RING_ESR"}, \ { RING_EMR(0), REG_32BIT, 0, 0, 0, "RING_EMR"}, \ { RING_EIR(0), REG_32BIT, 0, 0, 0, "RING_EIR"}, \ diff --git a/drivers/gpu/drm/xe/xe_guc_capture.h b/drivers/gpu/drm/xe/xe_guc_capture.h index 34d6fdc64f56..dca97d52b192 100644 --- a/drivers/gpu/drm/xe/xe_guc_capture.h +++ b/drivers/gpu/drm/xe/xe_guc_capture.h @@ -3,8 +3,8 @@ * Copyright © 2021-2024 Intel Corporation */ -#ifndef _XE_GUC_CAPTURE_H -#define _XE_GUC_CAPTURE_H +#ifndef _XE_GUC_CAPTURE_H_ +#define _XE_GUC_CAPTURE_H_ #include #include "abi/guc_capture_abi.h" diff --git a/drivers/gpu/drm/xe/xe_guc_capture_types.h b/drivers/gpu/drm/xe/xe_guc_capture_types.h index 6cb439115597..058a3f2eadce 100644 --- a/drivers/gpu/drm/xe/xe_guc_capture_types.h +++ b/drivers/gpu/drm/xe/xe_guc_capture_types.h @@ -3,8 +3,8 @@ * Copyright © 2021-2024 Intel Corporation */ -#ifndef _XE_GUC_CAPTURE_TYPES_H -#define _XE_GUC_CAPTURE_TYPES_H +#ifndef _XE_GUC_CAPTURE_TYPES_H_ +#define _XE_GUC_CAPTURE_TYPES_H_ #include #include "regs/xe_reg_defs.h" @@ -32,7 +32,7 @@ struct __guc_mmio_reg_descr { /** * @data_type: data type of the register * Could be 32 bit, low or hi dword of a 64 bit, see enum - * register_data_type + * capture_register_data_type */ enum capture_register_data_type data_type; /** @flags: Flags for the register */ diff --git a/drivers/gpu/drm/xe/xe_guc_ct.c b/drivers/gpu/drm/xe/xe_guc_ct.c index a11cff7a20be..21e0dad9a481 100644 --- a/drivers/gpu/drm/xe/xe_guc_ct.c +++ b/drivers/gpu/drm/xe/xe_guc_ct.c @@ -186,13 +186,16 @@ static void fast_req_track(struct xe_guc_ct *ct, u16 fence, u16 action) { } struct g2h_fence { u32 *response_buffer; u32 seqno; + /* fields below this point are setup based on the response */ u32 response_data; u16 response_len; u16 error; u16 hint; u16 reason; + u32 counter; bool cancel; bool retry; + bool wait; bool fail; bool done; }; @@ -204,6 +207,11 @@ static void g2h_fence_init(struct g2h_fence *g2h_fence, u32 *response_buffer) g2h_fence->seqno = ~0x0; } +static void g2h_fence_reinit(struct g2h_fence *g2h_fence) +{ + memset_after(g2h_fence, 0, seqno); +} + static void g2h_fence_cancel(struct g2h_fence *g2h_fence) { g2h_fence->cancel = true; @@ -1331,6 +1339,7 @@ static int guc_ct_send_recv(struct xe_guc_ct *ct, const u32 *action, u32 len, /* READ_ONCEs pairs with WRITE_ONCEs in parse_g2h_response * and g2h_fence_cancel. */ +wait_again: ret = wait_event_timeout(ct->g2h_fence_wq, READ_ONCE(g2h_fence.done), HZ); if (!ret) { LNL_FLUSH_WORK(&ct->g2h_worker); @@ -1356,6 +1365,14 @@ static int guc_ct_send_recv(struct xe_guc_ct *ct, const u32 *action, u32 len, return -ETIME; } + if (g2h_fence.wait) { + xe_gt_dbg(gt, "H2G action %#x busy: counter %u\n", + action[0], g2h_fence.counter); + /* we can't leave any response data if we want to wait again */ + g2h_fence_reinit(&g2h_fence); + mutex_unlock(&ct->lock); + goto wait_again; + } if (g2h_fence.retry) { xe_gt_dbg(gt, "H2G action %#x retrying: reason %#x\n", action[0], g2h_fence.reason); @@ -1508,7 +1525,12 @@ static int parse_g2h_response(struct xe_guc_ct *ct, u32 *msg, u32 len) return -EPROTO; } - g2h_fence = xa_erase(&ct->fence_lookup, fence); + /* don't erase as we still expect a final response with the same fence */ + if (type == GUC_HXG_TYPE_NO_RESPONSE_BUSY) + g2h_fence = xa_load(&ct->fence_lookup, fence); + else + g2h_fence = xa_erase(&ct->fence_lookup, fence); + if (unlikely(!g2h_fence)) { /* Don't tear down channel, as send could've timed out */ /* CT_DEAD(ct, NULL, PARSE_G2H_UNKNOWN); */ @@ -1519,6 +1541,12 @@ static int parse_g2h_response(struct xe_guc_ct *ct, u32 *msg, u32 len) xe_gt_assert(gt, fence == g2h_fence->seqno); + /* + * reinit as we might have already process this g2h_fence before + * if we received a NO_RESPONSE_BUSY reply + */ + g2h_fence_reinit(g2h_fence); + if (type == GUC_HXG_TYPE_RESPONSE_FAILURE) { g2h_fence->fail = true; g2h_fence->error = FIELD_GET(GUC_HXG_FAILURE_MSG_0_ERROR, hxg[0]); @@ -1526,6 +1554,9 @@ static int parse_g2h_response(struct xe_guc_ct *ct, u32 *msg, u32 len) } else if (type == GUC_HXG_TYPE_NO_RESPONSE_RETRY) { g2h_fence->retry = true; g2h_fence->reason = FIELD_GET(GUC_HXG_RETRY_MSG_0_REASON, hxg[0]); + } else if (type == GUC_HXG_TYPE_NO_RESPONSE_BUSY) { + g2h_fence->wait = true; + g2h_fence->counter = FIELD_GET(GUC_HXG_BUSY_MSG_0_COUNTER, hxg[0]); } else if (g2h_fence->response_buffer) { g2h_fence->response_len = hxg_len; memcpy(g2h_fence->response_buffer, hxg, hxg_len * sizeof(u32)); @@ -1533,7 +1564,9 @@ static int parse_g2h_response(struct xe_guc_ct *ct, u32 *msg, u32 len) g2h_fence->response_data = FIELD_GET(GUC_HXG_RESPONSE_MSG_0_DATA0, hxg[0]); } - g2h_release_space(ct, GUC_CTB_HXG_MSG_MAX_LEN); + /* don't release any space if it was an intermediate message */ + if (!g2h_fence->wait) + g2h_release_space(ct, GUC_CTB_HXG_MSG_MAX_LEN); /* WRITE_ONCE pairs with READ_ONCEs in guc_ct_send_recv. */ WRITE_ONCE(g2h_fence->done, true); @@ -1570,6 +1603,7 @@ static int parse_g2h_msg(struct xe_guc_ct *ct, u32 *msg, u32 len) case GUC_HXG_TYPE_RESPONSE_SUCCESS: case GUC_HXG_TYPE_RESPONSE_FAILURE: case GUC_HXG_TYPE_NO_RESPONSE_RETRY: + case GUC_HXG_TYPE_NO_RESPONSE_BUSY: ret = parse_g2h_response(ct, msg, len); break; default: diff --git a/drivers/gpu/drm/xe/xe_guc_ct_types.h b/drivers/gpu/drm/xe/xe_guc_ct_types.h index 5da1ce5dc372..f88e588af0d3 100644 --- a/drivers/gpu/drm/xe/xe_guc_ct_types.h +++ b/drivers/gpu/drm/xe/xe_guc_ct_types.h @@ -102,9 +102,9 @@ struct xe_dead_ct { bool reported; /** @worker: worker thread to get out of interrupt context before dumping */ struct work_struct worker; - /** snapshot_ct: copy of CT state and CTB content at point of error */ + /** @snapshot_ct: copy of CT state and CTB content at point of error */ struct xe_guc_ct_snapshot *snapshot_ct; - /** snapshot_log: copy of GuC log at point of error */ + /** @snapshot_log: copy of GuC log at point of error */ struct xe_guc_log_snapshot *snapshot_log; }; @@ -134,9 +134,9 @@ struct xe_guc_ct { spinlock_t fast_lock; /** @ctbs: buffers for sending and receiving commands */ struct { - /** @ctbs.send: Host to GuC (H2G, send) channel */ + /** @ctbs.h2g: Host to GuC (H2G, send) channel */ struct guc_ctb h2g; - /** @ctbs.recv: GuC to Host (G2H, receive) channel */ + /** @ctbs.g2h: GuC to Host (G2H, receive) channel */ struct guc_ctb g2h; } ctbs; /** @g2h_outstanding: number of outstanding G2H */ diff --git a/drivers/gpu/drm/xe/xe_guc_fwif.h b/drivers/gpu/drm/xe/xe_guc_fwif.h index b73fae063fac..3fbda4798cff 100644 --- a/drivers/gpu/drm/xe/xe_guc_fwif.h +++ b/drivers/gpu/drm/xe/xe_guc_fwif.h @@ -3,8 +3,8 @@ * Copyright © 2022 Intel Corporation */ -#ifndef _XE_GUC_FWIF_H -#define _XE_GUC_FWIF_H +#ifndef _XE_GUC_FWIF_H_ +#define _XE_GUC_FWIF_H_ #include diff --git a/drivers/gpu/drm/xe/xe_guc_pc.c b/drivers/gpu/drm/xe/xe_guc_pc.c index bb8c4e793492..59f2fa79ad42 100644 --- a/drivers/gpu/drm/xe/xe_guc_pc.c +++ b/drivers/gpu/drm/xe/xe_guc_pc.c @@ -890,9 +890,26 @@ void xe_guc_pc_init_early(struct xe_guc_pc *pc) pc_init_fused_rp_values(pc); } +static bool pc_needs_min_freq_change(struct xe_guc_pc *pc) +{ + struct xe_device *xe = pc_to_xe(pc); + struct xe_gt *gt = pc_to_gt(pc); + + if (XE_DEVICE_WA(xe, 14022085890)) + return true; + + if (xe_gt_is_media_type(gt)) + return false; + + if (xe->info.platform == XE_BATTLEMAGE || + xe->info.platform == XE_CRESCENTISLAND) + return true; + + return false; +} + static int pc_adjust_freq_bounds(struct xe_guc_pc *pc) { - struct xe_tile *tile = gt_to_tile(pc_to_gt(pc)); int ret; lockdep_assert_held(&pc->freq_lock); @@ -919,7 +936,18 @@ static int pc_adjust_freq_bounds(struct xe_guc_pc *pc) if (pc_get_min_freq(pc) > pc->rp0_freq) ret = pc_set_min_freq(pc, pc->rp0_freq); - if (XE_DEVICE_WA(tile_to_xe(tile), 14022085890)) + /* + * Setting GT RP min frequency to 1.2GHz by default for + * GT0(Graphics) Tile of BMG and CRI. + * + * While BMG G21 WA will apply min frequency for + * both GT0(Graphics) and GT1(Media) Tile. + * + * This is an active frequency, so if the device is idle + * we aren't expecting high power output across board + * + */ + if (pc_needs_min_freq_change(pc)) ret = pc_set_min_freq(pc, max(BMG_MIN_FREQ, pc_get_min_freq(pc))); out: @@ -1288,18 +1316,16 @@ int xe_guc_pc_start(struct xe_guc_pc *pc) * xe_guc_pc_stop - Stop GuC's Power Conservation component * @pc: Xe_GuC_PC instance */ -int xe_guc_pc_stop(struct xe_guc_pc *pc) +void xe_guc_pc_stop(struct xe_guc_pc *pc) { struct xe_device *xe = pc_to_xe(pc); if (xe->info.skip_guc_pc) - return 0; + return; mutex_lock(&pc->freq_lock); pc->freq_ready = false; mutex_unlock(&pc->freq_lock); - - return 0; } /** @@ -1314,10 +1340,10 @@ static void xe_guc_pc_fini_hw(void *arg) if (xe_device_wedged(xe)) return; - CLASS(xe_force_wake, fw_ref)(gt_to_fw(pc_to_gt(pc)), XE_FW_GT); - XE_WARN_ON(xe_guc_pc_stop(pc)); + xe_guc_pc_stop(pc); /* Bind requested freq to mert_freq_cap before unload */ + CLASS(xe_force_wake, fw_ref)(gt_to_fw(pc_to_gt(pc)), XE_FW_GT); pc_set_cur_freq(pc, min(pc_max_freq_cap(pc), xe_guc_pc_get_rpe_freq(pc))); } diff --git a/drivers/gpu/drm/xe/xe_guc_pc.h b/drivers/gpu/drm/xe/xe_guc_pc.h index 0678a4e787b3..1025a2b15f5f 100644 --- a/drivers/gpu/drm/xe/xe_guc_pc.h +++ b/drivers/gpu/drm/xe/xe_guc_pc.h @@ -13,7 +13,7 @@ struct drm_printer; int xe_guc_pc_init(struct xe_guc_pc *pc); int xe_guc_pc_start(struct xe_guc_pc *pc); -int xe_guc_pc_stop(struct xe_guc_pc *pc); +void xe_guc_pc_stop(struct xe_guc_pc *pc); void xe_guc_pc_print(struct xe_guc_pc *pc, struct drm_printer *p); int xe_guc_pc_action_set_param(struct xe_guc_pc *pc, u8 id, u32 value); int xe_guc_pc_action_unset_param(struct xe_guc_pc *pc, u8 id); diff --git a/drivers/gpu/drm/xe/xe_guc_relay_types.h b/drivers/gpu/drm/xe/xe_guc_relay_types.h index 20eee10856b2..b99a6686416b 100644 --- a/drivers/gpu/drm/xe/xe_guc_relay_types.h +++ b/drivers/gpu/drm/xe/xe_guc_relay_types.h @@ -15,7 +15,7 @@ * struct xe_guc_relay - Data used by the VF-PF Relay Communication over GuC. */ struct xe_guc_relay { - /**@lock: protects all internal data. */ + /** @lock: protects all internal data. */ spinlock_t lock; /** @worker: dispatches incoming action messages. */ diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c index 10556156eaad..b1222b42174c 100644 --- a/drivers/gpu/drm/xe/xe_guc_submit.c +++ b/drivers/gpu/drm/xe/xe_guc_submit.c @@ -2968,9 +2968,10 @@ int xe_guc_exec_queue_reset_handler(struct xe_guc *guc, u32 *msg, u32 len) if (unlikely(!q)) return -EPROTO; - xe_gt_info(gt, "Engine reset: engine_class=%s, logical_mask: 0x%x, guc_id=%d, state=0x%0x", - xe_hw_engine_class_to_str(q->class), q->logical_mask, guc_id, - atomic_read(&q->guc->state)); + if (!exec_queue_killed(q)) + xe_gt_info(gt, "Engine reset: engine_class=%s, logical_mask: 0x%x, guc_id=%d, state=0x%0x", + xe_hw_engine_class_to_str(q->class), q->logical_mask, guc_id, + atomic_read(&q->guc->state)); trace_xe_exec_queue_reset(q); diff --git a/drivers/gpu/drm/xe/xe_guc_submit_types.h b/drivers/gpu/drm/xe/xe_guc_submit_types.h index 5ccc5f959bb3..7824f61b1290 100644 --- a/drivers/gpu/drm/xe/xe_guc_submit_types.h +++ b/drivers/gpu/drm/xe/xe_guc_submit_types.h @@ -138,7 +138,7 @@ struct xe_guc_submit_exec_queue_snapshot { u32 primary; /** @multi_queue.pos: Position of the exec queue within the multi queue group */ u8 pos; - /** @valid: The exec queue is part of a multi queue group */ + /** @multi_queue.valid: The exec queue is part of a multi queue group */ bool valid; } multi_queue; }; diff --git a/drivers/gpu/drm/xe/xe_hw_engine.c b/drivers/gpu/drm/xe/xe_hw_engine.c index 6dd05fac6595..0f0e08bcc182 100644 --- a/drivers/gpu/drm/xe/xe_hw_engine.c +++ b/drivers/gpu/drm/xe/xe_hw_engine.c @@ -67,7 +67,7 @@ static const struct engine_info engine_infos[] = { .class = XE_ENGINE_CLASS_COPY, .instance = 0, .irq_offset = ilog2(INTR_BCS(0)), - .domain = XE_FW_RENDER, + .domain = XE_FW_GT, .mmio_base = BLT_RING_BASE, }, [XE_HW_ENGINE_BCS1] = { @@ -75,7 +75,7 @@ static const struct engine_info engine_infos[] = { .class = XE_ENGINE_CLASS_COPY, .instance = 1, .irq_offset = ilog2(INTR_BCS(1)), - .domain = XE_FW_RENDER, + .domain = XE_FW_GT, .mmio_base = XEHPC_BCS1_RING_BASE, }, [XE_HW_ENGINE_BCS2] = { @@ -83,7 +83,7 @@ static const struct engine_info engine_infos[] = { .class = XE_ENGINE_CLASS_COPY, .instance = 2, .irq_offset = ilog2(INTR_BCS(2)), - .domain = XE_FW_RENDER, + .domain = XE_FW_GT, .mmio_base = XEHPC_BCS2_RING_BASE, }, [XE_HW_ENGINE_BCS3] = { @@ -91,7 +91,7 @@ static const struct engine_info engine_infos[] = { .class = XE_ENGINE_CLASS_COPY, .instance = 3, .irq_offset = ilog2(INTR_BCS(3)), - .domain = XE_FW_RENDER, + .domain = XE_FW_GT, .mmio_base = XEHPC_BCS3_RING_BASE, }, [XE_HW_ENGINE_BCS4] = { @@ -99,7 +99,7 @@ static const struct engine_info engine_infos[] = { .class = XE_ENGINE_CLASS_COPY, .instance = 4, .irq_offset = ilog2(INTR_BCS(4)), - .domain = XE_FW_RENDER, + .domain = XE_FW_GT, .mmio_base = XEHPC_BCS4_RING_BASE, }, [XE_HW_ENGINE_BCS5] = { @@ -107,7 +107,7 @@ static const struct engine_info engine_infos[] = { .class = XE_ENGINE_CLASS_COPY, .instance = 5, .irq_offset = ilog2(INTR_BCS(5)), - .domain = XE_FW_RENDER, + .domain = XE_FW_GT, .mmio_base = XEHPC_BCS5_RING_BASE, }, [XE_HW_ENGINE_BCS6] = { @@ -115,7 +115,7 @@ static const struct engine_info engine_infos[] = { .class = XE_ENGINE_CLASS_COPY, .instance = 6, .irq_offset = ilog2(INTR_BCS(6)), - .domain = XE_FW_RENDER, + .domain = XE_FW_GT, .mmio_base = XEHPC_BCS6_RING_BASE, }, [XE_HW_ENGINE_BCS7] = { @@ -123,7 +123,7 @@ static const struct engine_info engine_infos[] = { .class = XE_ENGINE_CLASS_COPY, .irq_offset = ilog2(INTR_BCS(7)), .instance = 7, - .domain = XE_FW_RENDER, + .domain = XE_FW_GT, .mmio_base = XEHPC_BCS7_RING_BASE, }, [XE_HW_ENGINE_BCS8] = { @@ -131,7 +131,7 @@ static const struct engine_info engine_infos[] = { .class = XE_ENGINE_CLASS_COPY, .instance = 8, .irq_offset = ilog2(INTR_BCS8), - .domain = XE_FW_RENDER, + .domain = XE_FW_GT, .mmio_base = XEHPC_BCS8_RING_BASE, }, @@ -282,27 +282,6 @@ static void hw_engine_fini(void *arg) hwe->gt = NULL; } -/** - * xe_hw_engine_mmio_write32() - Write engine register - * @hwe: engine - * @reg: register to write into - * @val: desired 32-bit value to write - * - * This function will write val into an engine specific register. - * Forcewake must be held by the caller. - * - */ -void xe_hw_engine_mmio_write32(struct xe_hw_engine *hwe, - struct xe_reg reg, u32 val) -{ - xe_gt_assert(hwe->gt, !(reg.addr & hwe->mmio_base)); - xe_force_wake_assert_held(gt_to_fw(hwe->gt), hwe->domain); - - reg.addr += hwe->mmio_base; - - xe_mmio_write32(&hwe->gt->mmio, reg, val); -} - /** * xe_hw_engine_mmio_read32() - Read engine register * @hwe: engine @@ -325,24 +304,8 @@ u32 xe_hw_engine_mmio_read32(struct xe_hw_engine *hwe, struct xe_reg reg) void xe_hw_engine_enable_ring(struct xe_hw_engine *hwe) { - u32 ccs_mask = - xe_hw_engine_mask_per_class(hwe->gt, XE_ENGINE_CLASS_COMPUTE); - u32 ring_mode = REG_MASKED_FIELD_ENABLE(GFX_DISABLE_LEGACY_MODE); - - if (hwe->class == XE_ENGINE_CLASS_COMPUTE && ccs_mask) - xe_mmio_write32(&hwe->gt->mmio, RCU_MODE, - REG_MASKED_FIELD_ENABLE(RCU_MODE_CCS_ENABLE)); - - xe_hw_engine_mmio_write32(hwe, RING_HWSTAM(0), ~0x0); - xe_hw_engine_mmio_write32(hwe, RING_HWS_PGA(0), - xe_bo_ggtt_addr(hwe->hwsp)); - - if (xe_device_has_msix(gt_to_xe(hwe->gt))) - ring_mode |= REG_MASKED_FIELD_ENABLE(GFX_MSIX_INTERRUPT_ENABLE); - xe_hw_engine_mmio_write32(hwe, RING_MODE(0), ring_mode); - xe_hw_engine_mmio_write32(hwe, RING_MI_MODE(0), - REG_MASKED_FIELD_DISABLE(STOP_RING)); - xe_hw_engine_mmio_read32(hwe, RING_MI_MODE(0)); + xe_mmio_write32(&hwe->gt->mmio, RING_HWS_PGA(hwe->mmio_base), + xe_bo_ggtt_addr(hwe->hwsp)); } static bool xe_hw_engine_match_fixed_cslice_mode(const struct xe_device *xe, @@ -390,7 +353,7 @@ xe_hw_engine_setup_default_lrc_state(struct xe_hw_engine *hwe) * BLIT_CCTL registers are needed to be programmed to un-cached. */ { XE_RTP_NAME("BLIT_CCTL_default_MOCS"), - XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1200, XE_RTP_END_VERSION_UNDEFINED), + XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1200, 1274), ENGINE_CLASS(COPY)), XE_RTP_ACTIONS(FIELD_SET(BLIT_CCTL(0), BLIT_CCTL_DST_MOCS_MASK | @@ -436,13 +399,23 @@ hw_engine_setup_default_state(struct xe_hw_engine *hwe) struct xe_rtp_process_ctx ctx = XE_RTP_PROCESS_CTX_INITIALIZER(hwe); const struct xe_rtp_entry_sr engine_entries[] = { { XE_RTP_NAME("RING_CMD_CCTL_default_MOCS"), - XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1200, XE_RTP_END_VERSION_UNDEFINED)), + XE_RTP_RULES(FUNC(xe_rtp_match_always)), XE_RTP_ACTIONS(FIELD_SET(RING_CMD_CCTL(0), CMD_CCTL_WRITE_OVERRIDE_MASK | CMD_CCTL_READ_OVERRIDE_MASK, ring_cmd_cctl_val, XE_RTP_ACTION_FLAG(ENGINE_BASE))) }, + { XE_RTP_NAME("Disable HW status page updates for interrupts"), + XE_RTP_RULES(FUNC(xe_rtp_match_always)), + XE_RTP_ACTIONS(SET(RING_HWSTAM(0), ~0x0, + XE_RTP_ACTION_FLAG(ENGINE_BASE))) + }, + { XE_RTP_NAME("Disable engine 'legacy' mode"), + XE_RTP_RULES(FUNC(xe_rtp_match_always)), + XE_RTP_ACTIONS(SET(GFX_MODE(0), GFX_DISABLE_LEGACY_MODE, + XE_RTP_ACTION_FLAG(ENGINE_BASE))) + }, /* * To allow the GSC engine to go idle on MTL we need to enable * idle messaging and set the hysteresis value (we use 0xA=5us @@ -465,12 +438,22 @@ hw_engine_setup_default_state(struct xe_hw_engine *hwe) XE_RTP_ACTIONS(SET(CSFE_CHICKEN1(0), CS_PRIORITY_MEM_READ, XE_RTP_ACTION_FLAG(ENGINE_BASE))) }, + { XE_RTP_NAME("Enable CCS Engine(s)"), + XE_RTP_RULES(GRAPHICS_VERSION_RANGE(1255, XE_RTP_END_VERSION_UNDEFINED), + FUNC(xe_rtp_match_first_render_or_compute)), + XE_RTP_ACTIONS(SET(RCU_MODE, RCU_MODE_CCS_ENABLE)) + }, /* Use Fixed slice CCS mode */ { XE_RTP_NAME("RCU_MODE_FIXED_SLICE_CCS_MODE"), XE_RTP_RULES(FUNC(xe_hw_engine_match_fixed_cslice_mode)), XE_RTP_ACTIONS(FIELD_SET(RCU_MODE, RCU_MODE_FIXED_SLICE_CCS_MODE, RCU_MODE_FIXED_SLICE_CCS_MODE)) }, + { XE_RTP_NAME("Enable MSI-X interrupt support"), + XE_RTP_RULES(FUNC(xe_rtp_match_has_msix)), + XE_RTP_ACTIONS(SET(GFX_MODE(0), GFX_MSIX_INTERRUPT_ENABLE, + XE_RTP_ACTION_FLAG(ENGINE_BASE))) + }, }; xe_rtp_process_to_sr(&ctx, engine_entries, ARRAY_SIZE(engine_entries), @@ -1026,6 +1009,9 @@ bool xe_hw_engine_is_reserved(struct xe_hw_engine *hwe) struct xe_gt *gt = hwe->gt; struct xe_device *xe = gt_to_xe(gt); + if (xe_device_is_admin_only(xe)) + return true; + if (hwe->class == XE_ENGINE_CLASS_OTHER) return true; diff --git a/drivers/gpu/drm/xe/xe_hw_engine.h b/drivers/gpu/drm/xe/xe_hw_engine.h index 6b5f9fa2a594..ee9218773b51 100644 --- a/drivers/gpu/drm/xe/xe_hw_engine.h +++ b/drivers/gpu/drm/xe/xe_hw_engine.h @@ -76,7 +76,6 @@ const char *xe_hw_engine_class_to_str(enum xe_engine_class class); u64 xe_hw_engine_read_timestamp(struct xe_hw_engine *hwe); enum xe_force_wake_domains xe_hw_engine_to_fw_domain(struct xe_hw_engine *hwe); -void xe_hw_engine_mmio_write32(struct xe_hw_engine *hwe, struct xe_reg reg, u32 val); u32 xe_hw_engine_mmio_read32(struct xe_hw_engine *hwe, struct xe_reg reg); #endif diff --git a/drivers/gpu/drm/xe/xe_hw_engine_types.h b/drivers/gpu/drm/xe/xe_hw_engine_types.h index e4191a7a2c31..0f87128c6529 100644 --- a/drivers/gpu/drm/xe/xe_hw_engine_types.h +++ b/drivers/gpu/drm/xe/xe_hw_engine_types.h @@ -79,7 +79,7 @@ struct xe_hw_engine_class_intf { * @defaults: default scheduling properties */ struct { - /** @sched_props.set_job_timeout: Set job timeout in ms for engine */ + /** @sched_props.job_timeout_ms: Set job timeout in ms for engine */ u32 job_timeout_ms; /** @sched_props.job_timeout_min: Min job timeout in ms for engine */ u32 job_timeout_min; diff --git a/drivers/gpu/drm/xe/xe_hw_error.h b/drivers/gpu/drm/xe/xe_hw_error.h index d86e28c5180c..5e3a11424108 100644 --- a/drivers/gpu/drm/xe/xe_hw_error.h +++ b/drivers/gpu/drm/xe/xe_hw_error.h @@ -2,8 +2,8 @@ /* * Copyright © 2025 Intel Corporation */ -#ifndef XE_HW_ERROR_H_ -#define XE_HW_ERROR_H_ +#ifndef _XE_HW_ERROR_H_ +#define _XE_HW_ERROR_H_ #include diff --git a/drivers/gpu/drm/xe/xe_hwmon.c b/drivers/gpu/drm/xe/xe_hwmon.c index 92e423a339f1..de3f2aeffc3f 100644 --- a/drivers/gpu/drm/xe/xe_hwmon.c +++ b/drivers/gpu/drm/xe/xe_hwmon.c @@ -180,6 +180,18 @@ struct xe_hwmon { struct xe_hwmon_thermal_info temp; }; +static inline int prepare_power_limit_param2(const struct xe_hwmon *hwmon) +{ + if (hwmon->boot_power_limit_read) { + if (hwmon->xe->info.platform >= XE_CRESCENTISLAND) + return READ_PL_ACCEPTED; + else + return READ_PL_FROM_PCODE; + } else { + return READ_PL_FROM_FW; + } +} + static int xe_hwmon_pcode_read_power_limit(const struct xe_hwmon *hwmon, u32 attr, int channel, u32 *uval) { @@ -191,9 +203,7 @@ static int xe_hwmon_pcode_read_power_limit(const struct xe_hwmon *hwmon, u32 att (channel == CHANNEL_CARD) ? READ_PSYSGPU_POWER_LIMIT : READ_PACKAGE_POWER_LIMIT, - hwmon->boot_power_limit_read ? - READ_PL_FROM_PCODE : READ_PL_FROM_FW), - &val0, &val1); + prepare_power_limit_param2(hwmon)), &val0, &val1); if (ret) { drm_dbg(&hwmon->xe->drm, "read failed ch %d val0 0x%08x, val1 0x%08x, ret %d\n", @@ -226,10 +236,7 @@ static int xe_hwmon_pcode_rmw_power_limit(const struct xe_hwmon *hwmon, u32 attr (channel == CHANNEL_CARD) ? READ_PSYSGPU_POWER_LIMIT : READ_PACKAGE_POWER_LIMIT, - hwmon->boot_power_limit_read ? - READ_PL_FROM_PCODE : READ_PL_FROM_FW), - &val0, &val1); - + prepare_power_limit_param2(hwmon)), &val0, &val1); if (ret) drm_dbg(&hwmon->xe->drm, "read failed ch %d val0 0x%08x, val1 0x%08x, ret %d\n", channel, val0, val1, ret); @@ -296,7 +303,12 @@ static struct xe_reg xe_hwmon_get_reg(struct xe_hwmon *hwmon, enum xe_hwmon_reg return GT_PERF_STATUS; break; case REG_PKG_ENERGY_STATUS: - if (xe->info.platform == XE_PVC && channel == CHANNEL_PKG) { + if (xe->info.platform == XE_CRESCENTISLAND) { + if (channel == CHANNEL_CARD) + return CRI_PLATFORM_ENERGY_STATUS; + else if (channel == CHANNEL_PKG) + return CRI_PACKAGE_ENERGY_STATUS; + } else if (xe->info.platform == XE_PVC && channel == CHANNEL_PKG) { return PVC_GT0_PLATFORM_ENERGY_STATUS; } else if ((xe->info.platform == XE_DG2) && (channel == CHANNEL_PKG)) { return PCU_CR_PACKAGE_ENERGY_STATUS; diff --git a/drivers/gpu/drm/xe/xe_irq.c b/drivers/gpu/drm/xe/xe_irq.c index 7560a45f7f64..9e49e2241da4 100644 --- a/drivers/gpu/drm/xe/xe_irq.c +++ b/drivers/gpu/drm/xe/xe_irq.c @@ -24,6 +24,7 @@ #include "xe_mmio.h" #include "xe_pxp.h" #include "xe_sriov.h" +#include "xe_sysctrl.h" #include "xe_tile.h" /* @@ -525,6 +526,7 @@ static irqreturn_t dg1_irq_handler(int irq, void *arg) xe_heci_csc_irq_handler(xe, master_ctl); xe_display_irq_handler(xe, master_ctl); xe_i2c_irq_handler(xe, master_ctl); + xe_sysctrl_irq_handler(xe, master_ctl); xe_mert_irq_handler(xe, master_ctl); gu_misc_iir = gu_misc_irq_ack(xe, master_ctl); } diff --git a/drivers/gpu/drm/xe/xe_lrc.c b/drivers/gpu/drm/xe/xe_lrc.c index c725cde4508d..9db914584347 100644 --- a/drivers/gpu/drm/xe/xe_lrc.c +++ b/drivers/gpu/drm/xe/xe_lrc.c @@ -682,25 +682,6 @@ static void set_memory_based_intr(u32 *regs, struct xe_hw_engine *hwe) } } -static int lrc_ring_mi_mode(struct xe_hw_engine *hwe) -{ - struct xe_device *xe = gt_to_xe(hwe->gt); - - if (GRAPHICS_VERx100(xe) >= 1250) - return 0x70; - else - return 0x60; -} - -static void reset_stop_ring(u32 *regs, struct xe_hw_engine *hwe) -{ - int x; - - x = lrc_ring_mi_mode(hwe); - regs[x + 1] &= ~STOP_RING; - regs[x + 1] |= STOP_RING << 16; -} - static inline bool xe_lrc_has_indirect_ring_state(struct xe_lrc *lrc) { return lrc->flags & XE_LRC_FLAG_INDIRECT_RING_STATE; @@ -980,7 +961,6 @@ static void *empty_lrc_data(struct xe_hw_engine *hwe) set_offsets(regs, reg_offsets(gt_to_xe(gt), hwe->class), hwe); set_context_control(regs, hwe); set_memory_based_intr(regs, hwe); - reset_stop_ring(regs, hwe); if (xe_gt_has_indirect_ring_state(gt)) { regs = data + xe_gt_lrc_size(gt, hwe->class) - LRC_INDIRECT_RING_STATE_SIZE; diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c index 5fdc89ed5256..a87fbc1e9fb1 100644 --- a/drivers/gpu/drm/xe/xe_migrate.c +++ b/drivers/gpu/drm/xe/xe_migrate.c @@ -31,6 +31,7 @@ #include "xe_map.h" #include "xe_mem_pool.h" #include "xe_mocs.h" +#include "xe_pat.h" #include "xe_printk.h" #include "xe_pt.h" #include "xe_res_cursor.h" @@ -217,7 +218,7 @@ static void xe_migrate_prepare_vm(struct xe_tile *tile, struct xe_migrate *m, struct xe_vm *vm, u32 *ofs) { struct xe_device *xe = tile_to_xe(tile); - u16 pat_index = xe->pat.idx[XE_CACHE_WB]; + u16 pat_index = xe_cache_pat_idx(xe, XE_CACHE_WB); u8 id = tile->id; u32 num_entries = NUM_PT_SLOTS, num_level = vm->pt_root[id]->level; #define VRAM_IDENTITY_MAP_COUNT 2 @@ -337,7 +338,7 @@ static void xe_migrate_prepare_vm(struct xe_tile *tile, struct xe_migrate *m, * if flat ccs is enabled. */ if (GRAPHICS_VER(xe) >= 20 && xe_device_has_flat_ccs(xe)) { - u16 comp_pat_index = xe->pat.idx[XE_CACHE_NONE_COMPRESSION]; + u16 comp_pat_index = xe_cache_pat_idx(xe, XE_CACHE_NONE_COMPRESSION); u64 vram_offset = IDENTITY_OFFSET + DIV_ROUND_UP_ULL(actual_phy_size, SZ_1G); u64 pt31_ofs = xe_bo_size(bo) - XE_PAGE_SIZE; @@ -637,10 +638,10 @@ static void emit_pte(struct xe_migrate *m, /* Indirect access needs compression enabled uncached PAT index */ if (GRAPHICS_VERx100(xe) >= 2000) - pat_index = is_comp_pte ? xe->pat.idx[XE_CACHE_NONE_COMPRESSION] : - xe->pat.idx[XE_CACHE_WB]; + pat_index = is_comp_pte ? xe_cache_pat_idx(xe, XE_CACHE_NONE_COMPRESSION) : + xe_cache_pat_idx(xe, XE_CACHE_WB); else - pat_index = xe->pat.idx[XE_CACHE_WB]; + pat_index = xe_cache_pat_idx(xe, XE_CACHE_WB); ptes = DIV_ROUND_UP(size, XE_PAGE_SIZE); @@ -1876,7 +1877,7 @@ __xe_migrate_update_pgtables(struct xe_migrate *m, /* For sysmem PTE's, need to map them in our hole.. */ if (!IS_DGFX(xe)) { - u16 pat_index = xe->pat.idx[XE_CACHE_WB]; + u16 pat_index = xe_cache_pat_idx(xe, XE_CACHE_WB); u32 ptes, ofs; ppgtt_ofs = NUM_KERNEL_PDE - 1; @@ -2098,7 +2099,7 @@ static void build_pt_update_batch_sram(struct xe_migrate *m, struct drm_pagemap_addr *sram_addr, u32 size, int level) { - u16 pat_index = tile_to_xe(m->tile)->pat.idx[XE_CACHE_WB]; + u16 pat_index = xe_cache_pat_idx(tile_to_xe(m->tile), XE_CACHE_WB); u64 gpu_page_size = 0x1ull << xe_pt_shift(level); u32 ptes; int i = 0; diff --git a/drivers/gpu/drm/xe/xe_migrate.h b/drivers/gpu/drm/xe/xe_migrate.h index 169279d9d8c2..965c45889c72 100644 --- a/drivers/gpu/drm/xe/xe_migrate.h +++ b/drivers/gpu/drm/xe/xe_migrate.h @@ -3,8 +3,8 @@ * Copyright © 2020 Intel Corporation */ -#ifndef _XE_MIGRATE_ -#define _XE_MIGRATE_ +#ifndef _XE_MIGRATE_H_ +#define _XE_MIGRATE_H_ #include diff --git a/drivers/gpu/drm/xe/xe_nvm.h b/drivers/gpu/drm/xe/xe_nvm.h index fd3467ad35a4..b14722103f81 100644 --- a/drivers/gpu/drm/xe/xe_nvm.h +++ b/drivers/gpu/drm/xe/xe_nvm.h @@ -3,8 +3,8 @@ * Copyright(c) 2019-2025 Intel Corporation. All rights reserved. */ -#ifndef __XE_NVM_H__ -#define __XE_NVM_H__ +#ifndef _XE_NVM_H_ +#define _XE_NVM_H_ struct xe_device; diff --git a/drivers/gpu/drm/xe/xe_oa.c b/drivers/gpu/drm/xe/xe_oa.c index 6337e671c97a..5de5bf19240a 100644 --- a/drivers/gpu/drm/xe/xe_oa.c +++ b/drivers/gpu/drm/xe/xe_oa.c @@ -9,11 +9,13 @@ #include #include +#include #include #include #include #include +#include #include "abi/guc_actions_slpc_abi.h" #include "instructions/xe_mi_commands.h" @@ -213,32 +215,45 @@ static u32 xe_oa_hw_tail_read(struct xe_oa_stream *stream) #define oa_report_header_64bit(__s) \ ((__s)->oa_buffer.format->header == HDR_64_BIT) -static u64 oa_report_id(struct xe_oa_stream *stream, void *report) +static u64 oa_report_id(struct xe_oa_stream *stream, u32 report_offset) { - return oa_report_header_64bit(stream) ? *(u64 *)report : *(u32 *)report; -} + struct iosys_map *map = &stream->oa_buffer.bo->vmap; -static void oa_report_id_clear(struct xe_oa_stream *stream, u32 *report) -{ - if (oa_report_header_64bit(stream)) - *(u64 *)report = 0; - else - *report = 0; -} - -static u64 oa_timestamp(struct xe_oa_stream *stream, void *report) -{ return oa_report_header_64bit(stream) ? - *((u64 *)report + 1) : - *((u32 *)report + 1); + xe_map_rd(stream->oa->xe, map, report_offset, u64) : + xe_map_rd(stream->oa->xe, map, report_offset, u32); } -static void oa_timestamp_clear(struct xe_oa_stream *stream, u32 *report) +static void oa_report_id_clear(struct xe_oa_stream *stream, u32 report_offset) { - if (oa_report_header_64bit(stream)) - *(u64 *)&report[2] = 0; - else - report[1] = 0; + struct iosys_map *map = &stream->oa_buffer.bo->vmap; + + oa_report_header_64bit(stream) ? + xe_map_wr(stream->oa->xe, map, report_offset, u64, 0) : + xe_map_wr(stream->oa->xe, map, report_offset, u32, 0); +} + +static u64 oa_timestamp(struct xe_oa_stream *stream, u32 report_offset) +{ + struct iosys_map *map = &stream->oa_buffer.bo->vmap; + + return oa_report_header_64bit(stream) ? + xe_map_rd(stream->oa->xe, map, report_offset + 8, u64) : + xe_map_rd(stream->oa->xe, map, report_offset + 4, u32); +} + +static void oa_timestamp_clear(struct xe_oa_stream *stream, u32 report_offset) +{ + struct iosys_map *map = &stream->oa_buffer.bo->vmap; + + oa_report_header_64bit(stream) ? + xe_map_wr(stream->oa->xe, map, report_offset + 8, u64, 0) : + xe_map_wr(stream->oa->xe, map, report_offset + 4, u32, 0); +} + +static bool mert_wa_14026633728(struct xe_oa_stream *s) +{ + return s->oa_unit->type == DRM_XE_OA_UNIT_TYPE_MERT && XE_DEVICE_WA(s->oa->xe, 14026633728); } static bool xe_oa_buffer_check_unlocked(struct xe_oa_stream *stream) @@ -275,9 +290,7 @@ static bool xe_oa_buffer_check_unlocked(struct xe_oa_stream *stream) * they were written. If not : (╯°□°)╯︵ ┻━┻ */ while (xe_oa_circ_diff(stream, tail, stream->oa_buffer.tail) >= report_size) { - void *report = stream->oa_buffer.vaddr + tail; - - if (oa_report_id(stream, report) || oa_timestamp(stream, report)) + if (oa_report_id(stream, tail) || oa_timestamp(stream, tail)) break; tail = xe_oa_circ_diff(stream, tail, report_size); @@ -311,30 +324,37 @@ static enum hrtimer_restart xe_oa_poll_check_timer_cb(struct hrtimer *hrtimer) return HRTIMER_RESTART; } +static unsigned long +xe_oa_copy_to_user(struct xe_oa_stream *stream, void __user *dst, u32 report_offset, u32 len) +{ + xe_assert(stream->oa->xe, len <= stream->oa_buffer.format->size); + + xe_map_memcpy_from(stream->oa->xe, stream->oa_buffer.bounce, + &stream->oa_buffer.bo->vmap, report_offset, len); + return copy_to_user(dst, stream->oa_buffer.bounce, len); +} + static int xe_oa_append_report(struct xe_oa_stream *stream, char __user *buf, - size_t count, size_t *offset, const u8 *report) + size_t count, size_t *offset, u32 report_offset) { int report_size = stream->oa_buffer.format->size; int report_size_partial; - u8 *oa_buf_end; if ((count - *offset) < report_size) return -ENOSPC; buf += *offset; - oa_buf_end = stream->oa_buffer.vaddr + stream->oa_buffer.circ_size; - report_size_partial = oa_buf_end - report; + report_size_partial = stream->oa_buffer.circ_size - report_offset; if (report_size_partial < report_size) { - if (copy_to_user(buf, report, report_size_partial)) + if (xe_oa_copy_to_user(stream, buf, report_offset, report_size_partial)) return -EFAULT; buf += report_size_partial; - if (copy_to_user(buf, stream->oa_buffer.vaddr, - report_size - report_size_partial)) + if (xe_oa_copy_to_user(stream, buf, 0, report_size - report_size_partial)) return -EFAULT; - } else if (copy_to_user(buf, report, report_size)) { + } else if (xe_oa_copy_to_user(stream, buf, report_offset, report_size)) { return -EFAULT; } @@ -347,7 +367,6 @@ static int xe_oa_append_reports(struct xe_oa_stream *stream, char __user *buf, size_t count, size_t *offset) { int report_size = stream->oa_buffer.format->size; - u8 *oa_buf_base = stream->oa_buffer.vaddr; u32 gtt_offset = xe_bo_ggtt_addr(stream->oa_buffer.bo); size_t start_offset = *offset; unsigned long flags; @@ -364,26 +383,24 @@ static int xe_oa_append_reports(struct xe_oa_stream *stream, char __user *buf, for (; xe_oa_circ_diff(stream, tail, head); head = xe_oa_circ_incr(stream, head, report_size)) { - u8 *report = oa_buf_base + head; - - ret = xe_oa_append_report(stream, buf, count, offset, report); + ret = xe_oa_append_report(stream, buf, count, offset, head); if (ret) break; if (!(stream->oa_buffer.circ_size % report_size)) { /* Clear out report id and timestamp to detect unlanded reports */ - oa_report_id_clear(stream, (void *)report); - oa_timestamp_clear(stream, (void *)report); + oa_report_id_clear(stream, head); + oa_timestamp_clear(stream, head); } else { - u8 *oa_buf_end = stream->oa_buffer.vaddr + stream->oa_buffer.circ_size; - u32 part = oa_buf_end - report; + struct iosys_map *map = &stream->oa_buffer.bo->vmap; + u32 part = stream->oa_buffer.circ_size - head; /* Zero out the entire report */ if (report_size <= part) { - memset(report, 0, report_size); + xe_map_memset(stream->oa->xe, map, head, 0, report_size); } else { - memset(report, 0, part); - memset(oa_buf_base, 0, report_size - part); + xe_map_memset(stream->oa->xe, map, head, 0, part); + xe_map_memset(stream->oa->xe, map, 0, 0, report_size - part); } } } @@ -436,7 +453,8 @@ static void xe_oa_init_oa_buffer(struct xe_oa_stream *stream) spin_unlock_irqrestore(&stream->oa_buffer.ptr_lock, flags); /* Zero out the OA buffer since we rely on zero report id and timestamp fields */ - memset(stream->oa_buffer.vaddr, 0, xe_bo_size(stream->oa_buffer.bo)); + xe_map_memset(stream->oa->xe, &stream->oa_buffer.bo->vmap, 0, 0, + xe_bo_size(stream->oa_buffer.bo)); } static u32 __format_to_oactrl(const struct xe_oa_format *format, int counter_sel_mask) @@ -699,6 +717,7 @@ static int num_lri_dwords(int num_regs) static void xe_oa_free_oa_buffer(struct xe_oa_stream *stream) { xe_bo_unpin_map_no_vm(stream->oa_buffer.bo); + kfree(stream->oa_buffer.bounce); } static void xe_oa_free_configs(struct xe_oa_stream *stream) @@ -880,18 +899,25 @@ static void xe_oa_stream_destroy(struct xe_oa_stream *stream) static int xe_oa_alloc_oa_buffer(struct xe_oa_stream *stream, size_t size) { + u32 vram = mert_wa_14026633728(stream) ? + XE_BO_FLAG_VRAM_IF_DGFX(xe_device_get_root_tile(stream->oa->xe)) : + XE_BO_FLAG_SYSTEM; struct xe_bo *bo; bo = xe_bo_create_pin_map_novm(stream->oa->xe, stream->gt->tile, size, ttm_bo_type_kernel, - XE_BO_FLAG_SYSTEM | XE_BO_FLAG_GGTT, false); + vram | XE_BO_FLAG_GGTT, false); if (IS_ERR(bo)) return PTR_ERR(bo); stream->oa_buffer.bo = bo; - /* mmap implementation requires OA buffer to be in system memory */ - xe_assert(stream->oa->xe, bo->vmap.is_iomem == 0); - stream->oa_buffer.vaddr = bo->vmap.vaddr; + + stream->oa_buffer.bounce = kmalloc(stream->oa_buffer.format->size, GFP_KERNEL); + if (!stream->oa_buffer.bounce) { + xe_bo_unpin_map_no_vm(stream->oa_buffer.bo); + return -ENOMEM; + } + return 0; } @@ -1673,8 +1699,6 @@ static int xe_oa_mmap(struct file *file, struct vm_area_struct *vma) { struct xe_oa_stream *stream = file->private_data; struct xe_bo *bo = stream->oa_buffer.bo; - unsigned long start = vma->vm_start; - int i, ret; if (xe_observation_paranoid && !perfmon_capable()) { drm_dbg(&stream->oa->xe->drm, "Insufficient privilege to map OA buffer\n"); @@ -1682,7 +1706,7 @@ static int xe_oa_mmap(struct file *file, struct vm_area_struct *vma) } /* Can mmap the entire OA buffer or nothing (no partial OA buffer mmaps) */ - if (vma->vm_end - vma->vm_start != xe_bo_size(stream->oa_buffer.bo)) { + if (vma->vm_end - vma->vm_start != xe_bo_size(bo)) { drm_dbg(&stream->oa->xe->drm, "Wrong mmap size, must be OA buffer size\n"); return -EINVAL; } @@ -1698,17 +1722,7 @@ static int xe_oa_mmap(struct file *file, struct vm_area_struct *vma) vm_flags_mod(vma, VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP | VM_DONTCOPY, VM_MAYWRITE | VM_MAYEXEC); - xe_assert(stream->oa->xe, bo->ttm.ttm->num_pages == vma_pages(vma)); - for (i = 0; i < bo->ttm.ttm->num_pages; i++) { - ret = remap_pfn_range(vma, start, page_to_pfn(bo->ttm.ttm->pages[i]), - PAGE_SIZE, vma->vm_page_prot); - if (ret) - break; - - start += PAGE_SIZE; - } - - return ret; + return drm_gem_mmap_obj(&bo->ttm.base, xe_bo_size(bo), vma); } static const struct file_operations xe_oa_fops = { diff --git a/drivers/gpu/drm/xe/xe_oa_types.h b/drivers/gpu/drm/xe/xe_oa_types.h index b03ffd513483..3d9ec8490899 100644 --- a/drivers/gpu/drm/xe/xe_oa_types.h +++ b/drivers/gpu/drm/xe/xe_oa_types.h @@ -67,7 +67,7 @@ struct xe_oa_format { u32 counter_select; /** @size: record size as written by HW (multiple of 64 byte cachelines) */ int size; - /** @type: of enum @drm_xe_oa_format_type */ + /** @type: of enum drm_xe_oa_format_type */ int type; /** @header: 32 or 64 bit report headers */ enum xe_oa_report_header header; @@ -154,16 +154,18 @@ struct xe_oa { u16 oa_unit_ids; }; -/** @xe_oa_buffer: State of the stream OA buffer */ +/** + * struct xe_oa_buffer - State of the stream OA buffer + */ struct xe_oa_buffer { /** @format: data format */ const struct xe_oa_format *format; - /** @format: xe_bo backing the OA buffer */ + /** @bo: xe_bo backing the OA buffer */ struct xe_bo *bo; - /** @vaddr: mapped vaddr of the OA buffer */ - u8 *vaddr; + /** @bounce: bounce buffer used with xe_map layer */ + void *bounce; /** @ptr_lock: Lock protecting reads/writes to head/tail pointers */ spinlock_t ptr_lock; diff --git a/drivers/gpu/drm/xe/xe_pagefault_types.h b/drivers/gpu/drm/xe/xe_pagefault_types.h index b3289219b1be..c4ee625b93dd 100644 --- a/drivers/gpu/drm/xe/xe_pagefault_types.h +++ b/drivers/gpu/drm/xe/xe_pagefault_types.h @@ -86,7 +86,7 @@ struct xe_pagefault { u8 engine_class; /** @consumer.engine_instance: engine instance */ u8 engine_instance; - /** consumer.reserved: reserved bits for future expansion */ + /** @consumer.reserved: reserved bits for future expansion */ u64 reserved; } consumer; /** @@ -112,7 +112,7 @@ struct xe_pagefault { }; /** - * struct xe_pagefault_queue: Xe pagefault queue (consumer) + * struct xe_pagefault_queue - Xe pagefault queue (consumer) * * Used to capture all device page faults for deferred processing. Size this * queue to absorb the device’s worst-case number of outstanding faults. diff --git a/drivers/gpu/drm/xe/xe_pat.c b/drivers/gpu/drm/xe/xe_pat.c index 356f53bdb83c..fad5b5a5ed4a 100644 --- a/drivers/gpu/drm/xe/xe_pat.c +++ b/drivers/gpu/drm/xe/xe_pat.c @@ -531,6 +531,14 @@ static int xe2_dump(struct xe_gt *gt, struct drm_printer *p) drm_printf(p, "Page Table Access:\n"); xe->pat.ops->entry_dump(p, "PTA_MODE", pat, false); + if (xe_gt_is_media_type(gt)) + pat = xe_mmio_read32(>->mmio, XE_REG(_PAT_ATS)); + else + pat = xe_gt_mcr_unicast_read_any(gt, XE_REG_MCR(_PAT_ATS)); + + drm_printf(p, "PCIe ATS/PASID:\n"); + xe->pat.ops->entry_dump(p, "PAT_ATS ", pat, false); + return 0; } @@ -551,6 +559,7 @@ static const struct xe_pat_ops xe3p_xpc_pat_ops = { void xe_pat_init_early(struct xe_device *xe) { xe->pat.idx[XE_CACHE_WB_COMPRESSION] = XE_PAT_INVALID_IDX; + xe->pat.idx[XE_CACHE_NONE_COMPRESSION] = XE_PAT_INVALID_IDX; if (GRAPHICS_VERx100(xe) == 3511) { xe->pat.ops = &xe3p_xpc_pat_ops; xe->pat.table = xe3p_xpc_pat_table; diff --git a/drivers/gpu/drm/xe/xe_pat.h b/drivers/gpu/drm/xe/xe_pat.h index a1e287c08f57..7060f66e1d63 100644 --- a/drivers/gpu/drm/xe/xe_pat.h +++ b/drivers/gpu/drm/xe/xe_pat.h @@ -82,4 +82,12 @@ bool xe_pat_index_get_comp_en(struct xe_device *xe, u16 pat_index); */ u16 xe_pat_index_get_l3_policy(struct xe_device *xe, u16 pat_index); +#define xe_cache_pat_idx(xe, cache_mode) ({ \ + const struct xe_device *__xedev = (xe); \ + enum xe_cache_level __mode = (cache_mode); \ + xe_assert(__xedev, __mode < __XE_CACHE_LEVEL_COUNT); \ + xe_assert(__xedev, __xedev->pat.idx[__mode] != XE_PAT_INVALID_IDX); \ + __xedev->pat.idx[__mode]; \ +}) + #endif diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c index 9f98d0334164..41435f84aeb2 100644 --- a/drivers/gpu/drm/xe/xe_pci.c +++ b/drivers/gpu/drm/xe/xe_pci.c @@ -466,6 +466,7 @@ static const struct xe_device_desc cri_desc = { .has_soc_remapper_sysctrl = true, .has_soc_remapper_telem = true, .has_sriov = true, + .has_sysctrl = true, .max_gt_per_tile = 2, MULTI_LRC_MASK, .require_force_probe = true, @@ -764,8 +765,8 @@ static int xe_info_init_early(struct xe_device *xe, xe->info.has_soc_remapper_telem = desc->has_soc_remapper_telem; xe->info.has_sriov = xe_configfs_primary_gt_allowed(to_pci_dev(xe->drm.dev)) && desc->has_sriov; + xe->info.has_sysctrl = desc->has_sysctrl; xe->info.skip_guc_pc = desc->skip_guc_pc; - xe->info.skip_mtcfg = desc->skip_mtcfg; xe->info.skip_pcode = desc->skip_pcode; xe->info.needs_scratch = desc->needs_scratch; xe->info.needs_shared_vf_gt_wq = desc->needs_shared_vf_gt_wq; @@ -807,9 +808,6 @@ static void xe_info_probe_tile_count(struct xe_device *xe) if (xe->info.tile_count == 1) return; - if (xe->info.skip_mtcfg) - return; - mmio = xe_root_tile_mmio(xe); /* @@ -960,6 +958,12 @@ static int xe_info_init(struct xe_device *xe, xe->info.has_64bit_timestamp = graphics_desc->has_64bit_timestamp; xe->info.has_mem_copy_instr = GRAPHICS_VER(xe) >= 20; + if (IS_SRIOV_VF(xe)) { + xe->info.has_sysctrl = 0; + xe->info.has_soc_remapper_sysctrl = 0; + xe->info.has_soc_remapper_telem = 0; + } + xe_info_probe_tile_count(xe); for_each_remote_tile(tile, xe, id) { diff --git a/drivers/gpu/drm/xe/xe_pci_sriov.c b/drivers/gpu/drm/xe/xe_pci_sriov.c index 3fd22034f03e..35e6b53e18ce 100644 --- a/drivers/gpu/drm/xe/xe_pci_sriov.c +++ b/drivers/gpu/drm/xe/xe_pci_sriov.c @@ -191,6 +191,8 @@ static int pf_disable_vfs(struct xe_device *xe) pci_disable_sriov(pdev); + xe_sriov_pf_reprovision_default(xe); + pf_reset_vfs(xe, num_vfs); xe_sriov_pf_unprovision_vfs(xe, num_vfs); diff --git a/drivers/gpu/drm/xe/xe_pci_types.h b/drivers/gpu/drm/xe/xe_pci_types.h index 8eee4fb1c57c..5b85e2c24b7b 100644 --- a/drivers/gpu/drm/xe/xe_pci_types.h +++ b/drivers/gpu/drm/xe/xe_pci_types.h @@ -57,9 +57,9 @@ struct xe_device_desc { u8 has_soc_remapper_sysctrl:1; u8 has_soc_remapper_telem:1; u8 has_sriov:1; + u8 has_sysctrl:1; u8 needs_scratch:1; u8 skip_guc_pc:1; - u8 skip_mtcfg:1; u8 skip_pcode:1; u8 needs_shared_vf_gt_wq:1; }; diff --git a/drivers/gpu/drm/xe/xe_pcode_api.h b/drivers/gpu/drm/xe/xe_pcode_api.h index 85cc7478b787..94575c476e3d 100644 --- a/drivers/gpu/drm/xe/xe_pcode_api.h +++ b/drivers/gpu/drm/xe/xe_pcode_api.h @@ -3,6 +3,9 @@ * Copyright © 2022 Intel Corporation */ +#ifndef _XE_PCODE_API_H_ +#define _XE_PCODE_API_H_ + /* Internal to xe_pcode */ #include "regs/xe_reg_defs.h" @@ -47,8 +50,9 @@ #define WRITE_PSYSGPU_POWER_LIMIT 0x7 #define READ_PACKAGE_POWER_LIMIT 0x8 #define WRITE_PACKAGE_POWER_LIMIT 0x9 -#define READ_PL_FROM_FW 0x1 #define READ_PL_FROM_PCODE 0x0 +#define READ_PL_FROM_FW 0x1 +#define READ_PL_ACCEPTED 0x2 #define PCODE_THERMAL_INFO 0x25 #define READ_THERMAL_LIMITS 0x0 @@ -101,3 +105,5 @@ #define BMG_PCIE_CAP XE_REG(0x138340) #define LINK_DOWNGRADE REG_GENMASK(1, 0) #define DOWNGRADE_CAPABLE 2 + +#endif diff --git a/drivers/gpu/drm/xe/xe_pm.c b/drivers/gpu/drm/xe/xe_pm.c index 01185f10a883..d4672eb07476 100644 --- a/drivers/gpu/drm/xe/xe_pm.c +++ b/drivers/gpu/drm/xe/xe_pm.c @@ -26,6 +26,7 @@ #include "xe_pcode.h" #include "xe_pxp.h" #include "xe_sriov_vf_ccs.h" +#include "xe_sysctrl.h" #include "xe_trace.h" #include "xe_vm.h" #include "xe_wa.h" @@ -259,6 +260,8 @@ int xe_pm_resume(struct xe_device *xe) xe_i2c_pm_resume(xe, true); + xe_sysctrl_pm_resume(xe); + xe_irq_resume(xe); for_each_gt(gt, xe, id) { @@ -670,6 +673,9 @@ int xe_pm_runtime_resume(struct xe_device *xe) xe_i2c_pm_resume(xe, xe->d3cold.allowed); + if (xe->d3cold.allowed) + xe_sysctrl_pm_resume(xe); + xe_irq_resume(xe); for_each_gt(gt, xe, id) { diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c index 8e5f4f0dea3f..2669ff5ee747 100644 --- a/drivers/gpu/drm/xe/xe_pt.c +++ b/drivers/gpu/drm/xe/xe_pt.c @@ -14,6 +14,7 @@ #include "xe_gt_stats.h" #include "xe_migrate.h" #include "xe_page_reclaim.h" +#include "xe_pat.h" #include "xe_pt_types.h" #include "xe_pt_walk.h" #include "xe_res_cursor.h" @@ -62,7 +63,7 @@ static u64 __xe_pt_empty_pte(struct xe_tile *tile, struct xe_vm *vm, unsigned int level) { struct xe_device *xe = tile_to_xe(tile); - u16 pat_index = xe->pat.idx[XE_CACHE_WB]; + u16 pat_index = xe_cache_pat_idx(xe, XE_CACHE_WB); u8 id = tile->id; if (!xe_vm_has_scratch(vm)) diff --git a/drivers/gpu/drm/xe/xe_pt_types.h b/drivers/gpu/drm/xe/xe_pt_types.h index 84b51d3762a4..a7d1bb708b69 100644 --- a/drivers/gpu/drm/xe/xe_pt_types.h +++ b/drivers/gpu/drm/xe/xe_pt_types.h @@ -34,7 +34,7 @@ struct xe_pt { bool rebind; bool is_compact; #if IS_ENABLED(CONFIG_DRM_XE_DEBUG_VM) - /** addr: Virtual address start address of the PT. */ + /** @addr: Virtual address start address of the PT. */ u64 addr; #endif }; diff --git a/drivers/gpu/drm/xe/xe_pt_walk.h b/drivers/gpu/drm/xe/xe_pt_walk.h index 5c02c244f7de..e91995fa703b 100644 --- a/drivers/gpu/drm/xe/xe_pt_walk.h +++ b/drivers/gpu/drm/xe/xe_pt_walk.h @@ -2,8 +2,8 @@ /* * Copyright © 2022 Intel Corporation */ -#ifndef __XE_PT_WALK__ -#define __XE_PT_WALK__ +#ifndef _XE_PT_WALK_H_ +#define _XE_PT_WALK_H_ #include #include @@ -34,7 +34,7 @@ struct xe_pt_walk { * changed during the walk. */ const u64 *shifts; - /** @max_level: Highest populated level in @sizes */ + /** @max_level: Highest populated level in @shifts */ unsigned int max_level; /** * @shared_pt_mode: Whether to skip all entries that are private @@ -49,7 +49,7 @@ struct xe_pt_walk { /** * typedef xe_pt_entry_fn - gpu page-table-walk callback-function - * @parent: The parent page.table. + * @parent: The parent page table. * @offset: The offset (number of entries) into the page table. * @level: The level of @parent. * @addr: The virtual address. @@ -111,14 +111,14 @@ static inline bool xe_pt_covers(u64 addr, u64 end, unsigned int level, } /** - * xe_pt_num_entries: Number of page-table entries of a given range at this + * xe_pt_num_entries - Number of page-table entries of a given range at this * level * @addr: Start address. * @end: End address. * @level: Page table level. * @walk: Walk info. * - * Return: The number of page table entries at this level between @start and + * Return: The number of page table entries at this level between @addr and * @end. */ static inline pgoff_t @@ -132,7 +132,7 @@ xe_pt_num_entries(u64 addr, u64 end, unsigned int level, } /** - * xe_pt_offset: Offset of the page-table entry for a given address. + * xe_pt_offset - Offset of the page-table entry for a given address. * @addr: The address. * @level: Page table level. * @walk: Walk info. diff --git a/drivers/gpu/drm/xe/xe_pxp.c b/drivers/gpu/drm/xe/xe_pxp.c index 7244090b0782..968b7e70b3f9 100644 --- a/drivers/gpu/drm/xe/xe_pxp.c +++ b/drivers/gpu/drm/xe/xe_pxp.c @@ -13,10 +13,12 @@ #include "xe_device_types.h" #include "xe_exec_queue.h" #include "xe_force_wake.h" +#include "xe_guc_exec_queue_types.h" #include "xe_guc_submit.h" #include "xe_gsc_proxy.h" #include "xe_gt_types.h" #include "xe_huc.h" +#include "xe_hw_engine.h" #include "xe_mmio.h" #include "xe_pm.h" #include "xe_pxp_submit.h" @@ -740,6 +742,10 @@ static void pxp_invalidate_queues(struct xe_pxp *pxp) spin_unlock_irq(&pxp->queues.lock); list_for_each_entry_safe(q, tmp, &to_clean, pxp.link) { + drm_dbg(&pxp->xe->drm, + "Killing queue due to PXP termination: eclass=%s, guc_id=%d\n", + xe_hw_engine_class_to_str(q->class), q->guc->id); + xe_exec_queue_kill(q); /* diff --git a/drivers/gpu/drm/xe/xe_pxp.h b/drivers/gpu/drm/xe/xe_pxp.h index 71a23280b900..4fb6e0afffd2 100644 --- a/drivers/gpu/drm/xe/xe_pxp.h +++ b/drivers/gpu/drm/xe/xe_pxp.h @@ -3,8 +3,8 @@ * Copyright(c) 2024, Intel Corporation. All rights reserved. */ -#ifndef __XE_PXP_H__ -#define __XE_PXP_H__ +#ifndef _XE_PXP_H_ +#define _XE_PXP_H_ #include @@ -32,4 +32,4 @@ int xe_pxp_key_assign(struct xe_pxp *pxp, struct xe_bo *bo); int xe_pxp_bo_key_check(struct xe_pxp *pxp, struct xe_bo *bo); int xe_pxp_obj_key_check(struct drm_gem_object *obj); -#endif /* __XE_PXP_H__ */ +#endif /* _XE_PXP_H_ */ diff --git a/drivers/gpu/drm/xe/xe_pxp_debugfs.h b/drivers/gpu/drm/xe/xe_pxp_debugfs.h index 988466aad50b..2997de0c90b2 100644 --- a/drivers/gpu/drm/xe/xe_pxp_debugfs.h +++ b/drivers/gpu/drm/xe/xe_pxp_debugfs.h @@ -3,11 +3,11 @@ * Copyright © 2024 Intel Corporation */ -#ifndef __XE_PXP_DEBUGFS_H__ -#define __XE_PXP_DEBUGFS_H__ +#ifndef _XE_PXP_DEBUGFS_H_ +#define _XE_PXP_DEBUGFS_H_ struct xe_pxp; void xe_pxp_debugfs_register(struct xe_pxp *pxp); -#endif /* __XE_PXP_DEBUGFS_H__ */ +#endif /* _XE_PXP_DEBUGFS_H_ */ diff --git a/drivers/gpu/drm/xe/xe_pxp_submit.h b/drivers/gpu/drm/xe/xe_pxp_submit.h index c9efda02f4b0..dbbbe6b92bb2 100644 --- a/drivers/gpu/drm/xe/xe_pxp_submit.h +++ b/drivers/gpu/drm/xe/xe_pxp_submit.h @@ -3,8 +3,8 @@ * Copyright(c) 2024, Intel Corporation. All rights reserved. */ -#ifndef __XE_PXP_SUBMIT_H__ -#define __XE_PXP_SUBMIT_H__ +#ifndef _XE_PXP_SUBMIT_H_ +#define _XE_PXP_SUBMIT_H_ #include @@ -19,4 +19,4 @@ int xe_pxp_submit_session_termination(struct xe_pxp *pxp, u32 id); int xe_pxp_submit_session_invalidation(struct xe_pxp_gsc_client_resources *gsc_res, u32 id); -#endif /* __XE_PXP_SUBMIT_H__ */ +#endif /* _XE_PXP_SUBMIT_H_ */ diff --git a/drivers/gpu/drm/xe/xe_pxp_types.h b/drivers/gpu/drm/xe/xe_pxp_types.h index 53e9d48d10fb..ec86306e16f4 100644 --- a/drivers/gpu/drm/xe/xe_pxp_types.h +++ b/drivers/gpu/drm/xe/xe_pxp_types.h @@ -3,8 +3,8 @@ * Copyright(c) 2024, Intel Corporation. All rights reserved. */ -#ifndef __XE_PXP_TYPES_H__ -#define __XE_PXP_TYPES_H__ +#ifndef _XE_PXP_TYPES_H_ +#define _XE_PXP_TYPES_H_ #include #include @@ -132,4 +132,4 @@ struct xe_pxp { u32 last_suspend_key_instance; }; -#endif /* __XE_PXP_TYPES_H__ */ +#endif /* _XE_PXP_TYPES_H_ */ diff --git a/drivers/gpu/drm/xe/xe_query.c b/drivers/gpu/drm/xe/xe_query.c index d84d6a422c45..8c7d54498f38 100644 --- a/drivers/gpu/drm/xe/xe_query.c +++ b/drivers/gpu/drm/xe/xe_query.c @@ -231,6 +231,9 @@ static size_t calc_mem_regions_size(struct xe_device *xe) u32 num_managers = 1; int i; + if (xe_device_is_admin_only(xe)) + return sizeof(struct drm_xe_query_mem_regions); + for (i = XE_PL_VRAM0; i <= XE_PL_VRAM1; ++i) if (ttm_manager_type(&xe->ttm, i)) num_managers++; @@ -259,6 +262,9 @@ static int query_mem_regions(struct xe_device *xe, if (XE_IOCTL_DBG(xe, !mem_regions)) return -ENOMEM; + if (xe_device_is_admin_only(xe)) + goto user_copy; + man = ttm_manager_type(&xe->ttm, XE_PL_TT); mem_regions->mem_regions[0].mem_class = DRM_XE_MEM_REGION_CLASS_SYSMEM; /* @@ -297,6 +303,7 @@ static int query_mem_regions(struct xe_device *xe, } } +user_copy: if (!copy_to_user(query_ptr, mem_regions, size)) ret = 0; else diff --git a/drivers/gpu/drm/xe/xe_ras.c b/drivers/gpu/drm/xe/xe_ras.c new file mode 100644 index 000000000000..4cb16b419b0c --- /dev/null +++ b/drivers/gpu/drm/xe/xe_ras.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2026 Intel Corporation + */ + +#include "xe_device.h" +#include "xe_printk.h" +#include "xe_ras.h" +#include "xe_ras_types.h" +#include "xe_sysctrl.h" +#include "xe_sysctrl_event_types.h" + +/* Severity of detected errors */ +enum xe_ras_severity { + XE_RAS_SEV_NOT_SUPPORTED = 0, + XE_RAS_SEV_CORRECTABLE, + XE_RAS_SEV_UNCORRECTABLE, + XE_RAS_SEV_INFORMATIONAL, + XE_RAS_SEV_MAX +}; + +/* Major IP blocks/components where errors can originate */ +enum xe_ras_component { + XE_RAS_COMP_NOT_SUPPORTED = 0, + XE_RAS_COMP_DEVICE_MEMORY, + XE_RAS_COMP_CORE_COMPUTE, + XE_RAS_COMP_RESERVED, + XE_RAS_COMP_PCIE, + XE_RAS_COMP_FABRIC, + XE_RAS_COMP_SOC_INTERNAL, + XE_RAS_COMP_MAX +}; + +static const char *const xe_ras_severities[] = { + [XE_RAS_SEV_NOT_SUPPORTED] = "Not Supported", + [XE_RAS_SEV_CORRECTABLE] = "Correctable Error", + [XE_RAS_SEV_UNCORRECTABLE] = "Uncorrectable Error", + [XE_RAS_SEV_INFORMATIONAL] = "Informational Error", +}; +static_assert(ARRAY_SIZE(xe_ras_severities) == XE_RAS_SEV_MAX); + +static const char *const xe_ras_components[] = { + [XE_RAS_COMP_NOT_SUPPORTED] = "Not Supported", + [XE_RAS_COMP_DEVICE_MEMORY] = "Device Memory", + [XE_RAS_COMP_CORE_COMPUTE] = "Core Compute", + [XE_RAS_COMP_RESERVED] = "Reserved", + [XE_RAS_COMP_PCIE] = "PCIe", + [XE_RAS_COMP_FABRIC] = "Fabric", + [XE_RAS_COMP_SOC_INTERNAL] = "SoC Internal", +}; +static_assert(ARRAY_SIZE(xe_ras_components) == XE_RAS_COMP_MAX); + +static inline const char *sev_to_str(u8 severity) +{ + if (severity >= XE_RAS_SEV_MAX) + severity = XE_RAS_SEV_NOT_SUPPORTED; + + return xe_ras_severities[severity]; +} + +static inline const char *comp_to_str(u8 component) +{ + if (component >= XE_RAS_COMP_MAX) + component = XE_RAS_COMP_NOT_SUPPORTED; + + return xe_ras_components[component]; +} + +void xe_ras_counter_threshold_crossed(struct xe_device *xe, + struct xe_sysctrl_event_response *response) +{ + struct xe_ras_threshold_crossed *pending = (void *)&response->data; + struct xe_ras_error_class *errors = pending->counters; + u32 id, ncounters = pending->ncounters; + + BUILD_BUG_ON(sizeof(response->data) < sizeof(*pending)); + xe_device_assert_mem_access(xe); + + if (!ncounters || ncounters > XE_RAS_NUM_COUNTERS) + xe_err(xe, "sysctrl: unexpected counter threshold crossed %u\n", ncounters); + else + xe_warn(xe, "[RAS]: counter threshold crossed, %u new errors\n", ncounters); + + for (id = 0; id < ncounters && id < XE_RAS_NUM_COUNTERS; id++) { + u8 severity, component; + + severity = errors[id].common.severity; + component = errors[id].common.component; + + xe_warn(xe, "[RAS]: %s %s detected\n", + comp_to_str(component), sev_to_str(severity)); + } +} diff --git a/drivers/gpu/drm/xe/xe_ras.h b/drivers/gpu/drm/xe/xe_ras.h new file mode 100644 index 000000000000..ea90593b62dc --- /dev/null +++ b/drivers/gpu/drm/xe/xe_ras.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2026 Intel Corporation + */ + +#ifndef _XE_RAS_H_ +#define _XE_RAS_H_ + +struct xe_device; +struct xe_sysctrl_event_response; + +void xe_ras_counter_threshold_crossed(struct xe_device *xe, + struct xe_sysctrl_event_response *response); + +#endif diff --git a/drivers/gpu/drm/xe/xe_ras_types.h b/drivers/gpu/drm/xe/xe_ras_types.h new file mode 100644 index 000000000000..4e63c67f806a --- /dev/null +++ b/drivers/gpu/drm/xe/xe_ras_types.h @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2026 Intel Corporation + */ + +#ifndef _XE_RAS_TYPES_H_ +#define _XE_RAS_TYPES_H_ + +#include + +#define XE_RAS_NUM_COUNTERS 16 + +/** + * struct xe_ras_error_common - Error fields that are common across all products + */ +struct xe_ras_error_common { + /** @severity: Error severity */ + u8 severity; + /** @component: IP block where error originated */ + u8 component; +} __packed; + +/** + * struct xe_ras_error_unit - Error unit information + */ +struct xe_ras_error_unit { + /** @tile: Tile identifier */ + u8 tile; + /** @instance: Instance identifier specific to IP */ + u32 instance; +} __packed; + +/** + * struct xe_ras_error_cause - Error cause information + */ +struct xe_ras_error_cause { + /** @cause: Cause/checker */ + u32 cause; + /** @reserved: For future use */ + u8 reserved; +} __packed; + +/** + * struct xe_ras_error_product - Error fields that are specific to the product + */ +struct xe_ras_error_product { + /** @unit: Unit within IP block */ + struct xe_ras_error_unit unit; + /** @cause: Cause/checker */ + struct xe_ras_error_cause cause; +} __packed; + +/** + * struct xe_ras_error_class - Combines common and product-specific parts + */ +struct xe_ras_error_class { + /** @common: Common error type and component */ + struct xe_ras_error_common common; + /** @product: Product-specific unit and cause */ + struct xe_ras_error_product product; +} __packed; + +/** + * struct xe_ras_threshold_crossed - Data for threshold crossed event + */ +struct xe_ras_threshold_crossed { + /** @ncounters: Number of error counters that crossed thresholds */ + u32 ncounters; + /** @counters: Array of error counters that crossed threshold */ + struct xe_ras_error_class counters[XE_RAS_NUM_COUNTERS]; +} __packed; + +#endif diff --git a/drivers/gpu/drm/xe/xe_reg_sr.h b/drivers/gpu/drm/xe/xe_reg_sr.h index 1ec6e8ecf278..d26cf4713383 100644 --- a/drivers/gpu/drm/xe/xe_reg_sr.h +++ b/drivers/gpu/drm/xe/xe_reg_sr.h @@ -3,8 +3,8 @@ * Copyright © 2022 Intel Corporation */ -#ifndef _XE_REG_SR_ -#define _XE_REG_SR_ +#ifndef _XE_REG_SR_H_ +#define _XE_REG_SR_H_ /* * Reg save/restore bookkeeping diff --git a/drivers/gpu/drm/xe/xe_reg_sr_types.h b/drivers/gpu/drm/xe/xe_reg_sr_types.h index ebe11f237fa2..0a6695db2967 100644 --- a/drivers/gpu/drm/xe/xe_reg_sr_types.h +++ b/drivers/gpu/drm/xe/xe_reg_sr_types.h @@ -3,8 +3,8 @@ * Copyright © 2022 Intel Corporation */ -#ifndef _XE_REG_SR_TYPES_ -#define _XE_REG_SR_TYPES_ +#ifndef _XE_REG_SR_TYPES_H_ +#define _XE_REG_SR_TYPES_H_ #include #include diff --git a/drivers/gpu/drm/xe/xe_reg_whitelist.h b/drivers/gpu/drm/xe/xe_reg_whitelist.h index 69b121d377da..3b64b42fe96e 100644 --- a/drivers/gpu/drm/xe/xe_reg_whitelist.h +++ b/drivers/gpu/drm/xe/xe_reg_whitelist.h @@ -3,8 +3,8 @@ * Copyright © 2023 Intel Corporation */ -#ifndef _XE_REG_WHITELIST_ -#define _XE_REG_WHITELIST_ +#ifndef _XE_REG_WHITELIST_H_ +#define _XE_REG_WHITELIST_H_ #include diff --git a/drivers/gpu/drm/xe/xe_rtp.c b/drivers/gpu/drm/xe/xe_rtp.c index 991f218f1cc3..1a4dcbbbc176 100644 --- a/drivers/gpu/drm/xe/xe_rtp.c +++ b/drivers/gpu/drm/xe/xe_rtp.c @@ -10,6 +10,7 @@ #include #include "xe_configfs.h" +#include "xe_device.h" #include "xe_gt.h" #include "xe_gt_topology.h" #include "xe_reg_sr.h" @@ -352,6 +353,13 @@ void xe_rtp_process(struct xe_rtp_process_ctx *ctx, } EXPORT_SYMBOL_IF_KUNIT(xe_rtp_process); +bool xe_rtp_match_always(const struct xe_device *xe, + const struct xe_gt *gt, + const struct xe_hw_engine *hwe) +{ + return true; +} + bool xe_rtp_match_even_instance(const struct xe_device *xe, const struct xe_gt *gt, const struct xe_hw_engine *hwe) @@ -397,3 +405,10 @@ bool xe_rtp_match_has_flat_ccs(const struct xe_device *xe, { return xe->info.has_flat_ccs; } + +bool xe_rtp_match_has_msix(const struct xe_device *xe, + const struct xe_gt *gt, + const struct xe_hw_engine *hwe) +{ + return xe_device_has_msix(xe); +} diff --git a/drivers/gpu/drm/xe/xe_rtp.h b/drivers/gpu/drm/xe/xe_rtp.h index 7d6daa7eb1e4..562082b18d7b 100644 --- a/drivers/gpu/drm/xe/xe_rtp.h +++ b/drivers/gpu/drm/xe/xe_rtp.h @@ -3,8 +3,8 @@ * Copyright © 2022 Intel Corporation */ -#ifndef _XE_RTP_ -#define _XE_RTP_ +#ifndef _XE_RTP_H_ +#define _XE_RTP_H_ #include #include @@ -459,6 +459,18 @@ void xe_rtp_process(struct xe_rtp_process_ctx *ctx, /* Match functions to be used with XE_RTP_MATCH_FUNC */ +/** + * xe_rtp_match_always - Match RTP entry unconditionally + * @xe: Device structure + * @gt: GT structure + * @hwe: Engine instance + * + * Returns: true, regardless of inputs + */ +bool xe_rtp_match_always(const struct xe_device *xe, + const struct xe_gt *gt, + const struct xe_hw_engine *hwe); + /** * xe_rtp_match_even_instance - Match if engine instance is even * @xe: Device structure @@ -524,4 +536,16 @@ bool xe_rtp_match_has_flat_ccs(const struct xe_device *xe, const struct xe_gt *gt, const struct xe_hw_engine *hwe); +/** + * xe_rtp_match_has_msix - Match when platform has MSI-X + * @xe: Device structure + * @gt: GT structure + * @hwe: Engine instance + * + * Returns: true if platform has MSI-X interrupt support + */ +bool xe_rtp_match_has_msix(const struct xe_device *xe, + const struct xe_gt *gt, + const struct xe_hw_engine *hwe); + #endif diff --git a/drivers/gpu/drm/xe/xe_rtp_helpers.h b/drivers/gpu/drm/xe/xe_rtp_helpers.h index a33b0ae98bbc..ffa8b2f8828d 100644 --- a/drivers/gpu/drm/xe/xe_rtp_helpers.h +++ b/drivers/gpu/drm/xe/xe_rtp_helpers.h @@ -3,8 +3,8 @@ * Copyright © 2023 Intel Corporation */ -#ifndef _XE_RTP_HELPERS_ -#define _XE_RTP_HELPERS_ +#ifndef _XE_RTP_HELPERS_H_ +#define _XE_RTP_HELPERS_H_ #ifndef _XE_RTP_INCLUDE_PRIVATE_HELPERS #error "This header is supposed to be included by xe_rtp.h only" @@ -66,6 +66,8 @@ #define XE_RTP_PASTE_10(prefix_, sep_, args_) _XE_RTP_CONCAT(prefix_, FIRST_ARG args_) __XE_RTP_PASTE_SEP_ ## sep_ XE_RTP_PASTE_9(prefix_, sep_, _XE_TUPLE_TAIL args_) #define XE_RTP_PASTE_11(prefix_, sep_, args_) _XE_RTP_CONCAT(prefix_, FIRST_ARG args_) __XE_RTP_PASTE_SEP_ ## sep_ XE_RTP_PASTE_10(prefix_, sep_, _XE_TUPLE_TAIL args_) #define XE_RTP_PASTE_12(prefix_, sep_, args_) _XE_RTP_CONCAT(prefix_, FIRST_ARG args_) __XE_RTP_PASTE_SEP_ ## sep_ XE_RTP_PASTE_11(prefix_, sep_, _XE_TUPLE_TAIL args_) +#define XE_RTP_PASTE_13(prefix_, sep_, args_) _XE_RTP_CONCAT(prefix_, FIRST_ARG args_) __XE_RTP_PASTE_SEP_ ## sep_ XE_RTP_PASTE_12(prefix_, sep_, _XE_TUPLE_TAIL args_) +#define XE_RTP_PASTE_14(prefix_, sep_, args_) _XE_RTP_CONCAT(prefix_, FIRST_ARG args_) __XE_RTP_PASTE_SEP_ ## sep_ XE_RTP_PASTE_13(prefix_, sep_, _XE_TUPLE_TAIL args_) /* * XE_RTP_DROP_CAST - Drop cast to convert a compound statement to a initializer diff --git a/drivers/gpu/drm/xe/xe_rtp_types.h b/drivers/gpu/drm/xe/xe_rtp_types.h index 166251615be1..0265c16d2762 100644 --- a/drivers/gpu/drm/xe/xe_rtp_types.h +++ b/drivers/gpu/drm/xe/xe_rtp_types.h @@ -3,8 +3,8 @@ * Copyright © 2022 Intel Corporation */ -#ifndef _XE_RTP_TYPES_ -#define _XE_RTP_TYPES_ +#ifndef _XE_RTP_TYPES_H_ +#define _XE_RTP_TYPES_H_ #include diff --git a/drivers/gpu/drm/xe/xe_sriov_pf.c b/drivers/gpu/drm/xe/xe_sriov_pf.c index 47a6e0fd66e0..33bd754d138f 100644 --- a/drivers/gpu/drm/xe/xe_sriov_pf.c +++ b/drivers/gpu/drm/xe/xe_sriov_pf.c @@ -20,11 +20,6 @@ #include "xe_sriov_pf_sysfs.h" #include "xe_sriov_printk.h" -static bool wanted_admin_only(struct xe_device *xe) -{ - return xe_configfs_admin_only_pf(to_pci_dev(xe->drm.dev)); -} - static unsigned int wanted_max_vfs(struct xe_device *xe) { return xe_configfs_get_max_vfs(to_pci_dev(xe->drm.dev)); @@ -79,7 +74,6 @@ bool xe_sriov_pf_readiness(struct xe_device *xe) pf_reduce_totalvfs(xe, newlimit); - xe->sriov.pf.admin_only = wanted_admin_only(xe); xe->sriov.pf.device_total_vfs = totalvfs; xe->sriov.pf.driver_max_vfs = newlimit; diff --git a/drivers/gpu/drm/xe/xe_sriov_pf_helpers.h b/drivers/gpu/drm/xe/xe_sriov_pf_helpers.h index 0fcc6cec4afc..19f6f8331c8d 100644 --- a/drivers/gpu/drm/xe/xe_sriov_pf_helpers.h +++ b/drivers/gpu/drm/xe/xe_sriov_pf_helpers.h @@ -7,6 +7,7 @@ #define _XE_SRIOV_PF_HELPERS_H_ #include "xe_assert.h" +#include "xe_device.h" #include "xe_device_types.h" #include "xe_sriov.h" #include "xe_sriov_types.h" @@ -57,7 +58,7 @@ static inline unsigned int xe_sriov_pf_num_vfs(const struct xe_device *xe) static inline bool xe_sriov_pf_admin_only(const struct xe_device *xe) { xe_assert(xe, IS_SRIOV_PF(xe)); - return xe->sriov.pf.admin_only; + return xe_device_is_admin_only(xe); } static inline struct mutex *xe_sriov_pf_master_mutex(struct xe_device *xe) diff --git a/drivers/gpu/drm/xe/xe_sriov_pf_provision.c b/drivers/gpu/drm/xe/xe_sriov_pf_provision.c index abe3677d33ed..0ec7ea83f12a 100644 --- a/drivers/gpu/drm/xe/xe_sriov_pf_provision.c +++ b/drivers/gpu/drm/xe/xe_sriov_pf_provision.c @@ -41,6 +41,8 @@ static int pf_provision_vfs(struct xe_device *xe, unsigned int num_vfs) int err; for_each_gt(gt, xe, id) { + err = xe_gt_sriov_pf_config_set_fair_sched(gt, num_vfs); + result = result ?: err; err = xe_gt_sriov_pf_config_set_fair(gt, VFID(1), num_vfs); result = result ?: err; } @@ -103,6 +105,45 @@ int xe_sriov_pf_unprovision_vfs(struct xe_device *xe, unsigned int num_vfs) return 0; } +static int pf_reprovision_default(struct xe_device *xe) +{ + struct xe_gt *gt; + unsigned int id; + int result = 0; + int err; + + guard(mutex)(xe_sriov_pf_master_mutex(xe)); + + for_each_gt(gt, xe, id) { + err = xe_gt_sriov_pf_policy_set_sched_if_idle_locked(gt, false); + result = result ?: err; + err = xe_gt_sriov_pf_config_set_exec_quantum_locked(gt, PFID, 0); + result = result ?: err; + err = xe_gt_sriov_pf_config_set_preempt_timeout_locked(gt, PFID, 0); + result = result ?: err; + } + + return result; +} + +/** + * xe_sriov_pf_reprovision_default() - Reprovision default PF in auto-mode. + * @xe: the PF &xe_device + * + * This function can only be called on PF. + * + * Return: 0 on success or a negative error code on failure. + */ +int xe_sriov_pf_reprovision_default(struct xe_device *xe) +{ + xe_assert(xe, IS_SRIOV_PF(xe)); + + if (!pf_auto_provisioning_mode(xe)) + return 0; + + return pf_reprovision_default(xe); +} + /** * xe_sriov_pf_provision_set_mode() - Change VFs provision mode. * @xe: the PF &xe_device diff --git a/drivers/gpu/drm/xe/xe_sriov_pf_provision.h b/drivers/gpu/drm/xe/xe_sriov_pf_provision.h index f26f49539697..b15e4d7ad940 100644 --- a/drivers/gpu/drm/xe/xe_sriov_pf_provision.h +++ b/drivers/gpu/drm/xe/xe_sriov_pf_provision.h @@ -30,6 +30,7 @@ int xe_sriov_pf_provision_query_vf_vram(struct xe_device *xe, unsigned int vfid, int xe_sriov_pf_provision_vfs(struct xe_device *xe, unsigned int num_vfs); int xe_sriov_pf_unprovision_vfs(struct xe_device *xe, unsigned int num_vfs); +int xe_sriov_pf_reprovision_default(struct xe_device *xe); int xe_sriov_pf_provision_set_mode(struct xe_device *xe, enum xe_sriov_provisioning_mode mode); diff --git a/drivers/gpu/drm/xe/xe_sriov_pf_types.h b/drivers/gpu/drm/xe/xe_sriov_pf_types.h index 080cf10512f4..b0253e1ae5da 100644 --- a/drivers/gpu/drm/xe/xe_sriov_pf_types.h +++ b/drivers/gpu/drm/xe/xe_sriov_pf_types.h @@ -36,9 +36,6 @@ struct xe_sriov_metadata { * @XE_SRIOV_MODE_PF mode. */ struct xe_device_pf { - /** @admin_only: PF functionality focused on VFs management only. */ - bool admin_only; - /** @device_total_vfs: Maximum number of VFs supported by the device. */ u16 device_total_vfs; diff --git a/drivers/gpu/drm/xe/xe_step.c b/drivers/gpu/drm/xe/xe_step.c index d0f888c31831..fb9c31613ca7 100644 --- a/drivers/gpu/drm/xe/xe_step.c +++ b/drivers/gpu/drm/xe/xe_step.c @@ -278,7 +278,7 @@ void xe_step_gmdid_get(struct xe_device *xe, case STEP_##name: \ return #name; -const char *xe_step_name(enum xe_step step) +const char *xe_step_name(enum intel_step step) { switch (step) { STEP_NAME_LIST(STEP_NAME_CASE); diff --git a/drivers/gpu/drm/xe/xe_step.h b/drivers/gpu/drm/xe/xe_step.h index 41f1c95c46e5..ea36b22cc297 100644 --- a/drivers/gpu/drm/xe/xe_step.h +++ b/drivers/gpu/drm/xe/xe_step.h @@ -18,8 +18,8 @@ void xe_step_pre_gmdid_get(struct xe_device *xe); void xe_step_gmdid_get(struct xe_device *xe, u32 graphics_gmdid_revid, u32 media_gmdid_revid); -static inline u32 xe_step_to_gmdid(enum xe_step step) { return step - STEP_A0; } +static inline u32 xe_step_to_gmdid(enum intel_step step) { return step - STEP_A0; } -const char *xe_step_name(enum xe_step step); +const char *xe_step_name(enum intel_step step); #endif diff --git a/drivers/gpu/drm/xe/xe_step_types.h b/drivers/gpu/drm/xe/xe_step_types.h index 43ca73850739..f60572b93523 100644 --- a/drivers/gpu/drm/xe/xe_step_types.h +++ b/drivers/gpu/drm/xe/xe_step_types.h @@ -8,6 +8,8 @@ #include +#include + struct xe_step_info { u8 platform; u8 graphics; @@ -15,63 +17,4 @@ struct xe_step_info { u8 basedie; }; -#define STEP_ENUM_VAL(name) STEP_##name, - -/* - * Always define four minor steppings 0-3 for each stepping to match GMD ID - * spacing of values. See xe_step_gmdid_get(). - */ -#define STEP_NAME_LIST(func) \ - func(A0) \ - func(A1) \ - func(A2) \ - func(A3) \ - func(B0) \ - func(B1) \ - func(B2) \ - func(B3) \ - func(C0) \ - func(C1) \ - func(C2) \ - func(C3) \ - func(D0) \ - func(D1) \ - func(D2) \ - func(D3) \ - func(E0) \ - func(E1) \ - func(E2) \ - func(E3) \ - func(F0) \ - func(F1) \ - func(F2) \ - func(F3) \ - func(G0) \ - func(G1) \ - func(G2) \ - func(G3) \ - func(H0) \ - func(H1) \ - func(H2) \ - func(H3) \ - func(I0) \ - func(I1) \ - func(I2) \ - func(I3) \ - func(J0) \ - func(J1) \ - func(J2) \ - func(J3) - -/* - * Symbolic steppings that do not match the hardware. These are valid both as gt - * and display steppings as symbolic names. - */ -enum xe_step { - STEP_NONE = 0, - STEP_NAME_LIST(STEP_ENUM_VAL) - STEP_FUTURE, - STEP_FOREVER, -}; - #endif diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c index 5933b2b6392b..ba67355f64cb 100644 --- a/drivers/gpu/drm/xe/xe_svm.c +++ b/drivers/gpu/drm/xe/xe_svm.c @@ -786,12 +786,12 @@ static int xe_svm_populate_devmem_pfn(struct drm_pagemap_devmem *devmem_allocati struct xe_bo *bo = to_xe_bo(devmem_allocation); struct ttm_resource *res = bo->ttm.resource; struct list_head *blocks = &to_xe_ttm_vram_mgr_resource(res)->blocks; + struct xe_vram_region *vr = xe_map_resource_to_region(res); + struct gpu_buddy *buddy = vram_to_buddy(vr); struct gpu_buddy_block *block; int j = 0; list_for_each_entry(block, blocks, link) { - struct xe_vram_region *vr = block->private; - struct gpu_buddy *buddy = vram_to_buddy(vr); u64 block_pfn = block_offset_to_pfn(devmem_allocation->dpagemap, gpu_buddy_block_offset(block)); int i; @@ -1061,9 +1061,7 @@ static int xe_drm_pagemap_populate_mm(struct drm_pagemap *dpagemap, struct dma_fence *pre_migrate_fence = NULL; struct xe_device *xe = vr->xe; struct device *dev = xe->drm.dev; - struct gpu_buddy_block *block; struct xe_validation_ctx vctx; - struct list_head *blocks; struct drm_exec exec; struct xe_bo *bo; int err = 0, idx; @@ -1100,10 +1098,6 @@ static int xe_drm_pagemap_populate_mm(struct drm_pagemap *dpagemap, &dpagemap_devmem_ops, dpagemap, end - start, pre_migrate_fence); - blocks = &to_xe_ttm_vram_mgr_resource(bo->ttm.resource)->blocks; - list_for_each_entry(block, blocks, link) - block->private = vr; - xe_bo_get(bo); /* Ensure the device has a pm ref while there are device pages active. */ diff --git a/drivers/gpu/drm/xe/xe_sysctrl.c b/drivers/gpu/drm/xe/xe_sysctrl.c new file mode 100644 index 000000000000..1db20be8158b --- /dev/null +++ b/drivers/gpu/drm/xe/xe_sysctrl.c @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2026 Intel Corporation + */ + +#include +#include + +#include + +#include "regs/xe_irq_regs.h" +#include "regs/xe_sysctrl_regs.h" +#include "xe_device.h" +#include "xe_mmio.h" +#include "xe_pm.h" +#include "xe_soc_remapper.h" +#include "xe_sysctrl.h" +#include "xe_sysctrl_mailbox.h" +#include "xe_sysctrl_types.h" + +/** + * DOC: System Controller (sysctrl) + * + * System Controller (sysctrl) is a firmware-managed entity on Intel dGPUs + * responsible for selected low-level platform management functions. + * Communication between driver and System Controller is performed + * via a mailbox interface, enabling command and response exchange. + * + * This module provides initialization and support code for interacting + * with System Controller through the mailbox interface. + */ +static void sysctrl_fini(void *arg) +{ + struct xe_device *xe = arg; + struct xe_sysctrl *sc = &xe->sc; + + disable_work_sync(&sc->work); + xe->soc_remapper.set_sysctrl_region(xe, 0); +} + +static void xe_sysctrl_work(struct work_struct *work) +{ + struct xe_sysctrl *sc = container_of(work, struct xe_sysctrl, work); + struct xe_device *xe = sc_to_xe(sc); + + guard(xe_pm_runtime)(xe); + xe_sysctrl_event(sc); +} + +/** + * xe_sysctrl_init() - Initialize System Controller subsystem + * @xe: xe device instance + * + * Entry point for System Controller initialization, called from xe_device_probe. + * This function checks platform support and initializes the system controller. + * + * Return: 0 on success, error code on failure + */ +int xe_sysctrl_init(struct xe_device *xe) +{ + struct xe_tile *tile = xe_device_get_root_tile(xe); + struct xe_sysctrl *sc = &xe->sc; + int ret; + + if (!xe->info.has_soc_remapper_sysctrl) + return 0; + + if (!xe->info.has_sysctrl) + return 0; + + sc->mmio = devm_kzalloc(xe->drm.dev, sizeof(*sc->mmio), GFP_KERNEL); + if (!sc->mmio) + return -ENOMEM; + + xe_mmio_init(sc->mmio, tile, tile->mmio.regs, tile->mmio.regs_size); + sc->mmio->adj_offset = SYSCTRL_BASE; + sc->mmio->adj_limit = U32_MAX; + + ret = devm_mutex_init(xe->drm.dev, &sc->cmd_lock); + if (ret) + return ret; + + ret = devm_mutex_init(xe->drm.dev, &sc->event_lock); + if (ret) + return ret; + + xe->soc_remapper.set_sysctrl_region(xe, SYSCTRL_MAILBOX_INDEX); + xe_sysctrl_mailbox_init(sc); + INIT_WORK(&sc->work, xe_sysctrl_work); + + return devm_add_action_or_reset(xe->drm.dev, sysctrl_fini, xe); +} + +/** + * xe_sysctrl_irq_handler() - Handler for System Controller interrupts + * @xe: xe device instance + * @master_ctl: interrupt register + * + * Handle interrupts generated by System Controller. + */ +void xe_sysctrl_irq_handler(struct xe_device *xe, u32 master_ctl) +{ + struct xe_sysctrl *sc = &xe->sc; + + if (!xe->info.has_sysctrl || !sc->work.func) + return; + + if (master_ctl & SYSCTRL_IRQ) + schedule_work(&sc->work); +} + +/** + * xe_sysctrl_pm_resume() - System Controller resume handler + * @xe: xe device instance + * + * Invoked during system resume (S3/S4 to S0) and runtime resume from D3cold. + * Restores SoC remapper configuration and reinitializes mailbox interface. + */ +void xe_sysctrl_pm_resume(struct xe_device *xe) +{ + struct xe_sysctrl *sc = &xe->sc; + + if (!xe->info.has_soc_remapper_sysctrl) + return; + + if (!xe->info.has_sysctrl) + return; + + xe->soc_remapper.set_sysctrl_region(xe, SYSCTRL_MAILBOX_INDEX); + + xe_sysctrl_mailbox_init(sc); +} diff --git a/drivers/gpu/drm/xe/xe_sysctrl.h b/drivers/gpu/drm/xe/xe_sysctrl.h new file mode 100644 index 000000000000..090dffb6d55f --- /dev/null +++ b/drivers/gpu/drm/xe/xe_sysctrl.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2026 Intel Corporation + */ + +#ifndef _XE_SYSCTRL_H_ +#define _XE_SYSCTRL_H_ + +#include + +#include "xe_device_types.h" +#include "xe_sysctrl_types.h" + +static inline struct xe_device *sc_to_xe(struct xe_sysctrl *sc) +{ + return container_of(sc, struct xe_device, sc); +} + +void xe_sysctrl_event(struct xe_sysctrl *sc); +int xe_sysctrl_init(struct xe_device *xe); +void xe_sysctrl_irq_handler(struct xe_device *xe, u32 master_ctl); +void xe_sysctrl_pm_resume(struct xe_device *xe); + +#endif diff --git a/drivers/gpu/drm/xe/xe_sysctrl_event.c b/drivers/gpu/drm/xe/xe_sysctrl_event.c new file mode 100644 index 000000000000..b4d17329af6c --- /dev/null +++ b/drivers/gpu/drm/xe/xe_sysctrl_event.c @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2026 Intel Corporation + */ + +#include "xe_device.h" +#include "xe_irq.h" +#include "xe_printk.h" +#include "xe_ras.h" +#include "xe_sysctrl.h" +#include "xe_sysctrl_event_types.h" +#include "xe_sysctrl_mailbox.h" +#include "xe_sysctrl_mailbox_types.h" + +static void get_pending_event(struct xe_sysctrl *sc, struct xe_sysctrl_mailbox_command *command) +{ + struct xe_sysctrl_event_response *response = command->data_out; + struct xe_device *xe = sc_to_xe(sc); + u32 count = XE_SYSCTRL_EVENT_FLOOD; + size_t len; + int ret; + + do { + memset(response, 0, sizeof(*response)); + + ret = xe_sysctrl_send_command(sc, command, &len); + if (ret) { + xe_err(xe, "sysctrl: failed to get pending event %d\n", ret); + return; + } + + if (len != sizeof(*response)) { + xe_err(xe, "sysctrl: unexpected event response length %zu (expected %zu)\n", + len, sizeof(*response)); + return; + } + + if (response->event == XE_SYSCTRL_EVENT_THRESHOLD_CROSSED) + xe_ras_counter_threshold_crossed(xe, response); + else + xe_warn(xe, "sysctrl: unexpected event %#x\n", response->event); + + if (!--count) { + xe_err(xe, "sysctrl: event flooding\n"); + return; + } + + xe_dbg(xe, "sysctrl: %u events pending\n", response->count); + } while (response->count); +} + +static void event_request_prepare(struct xe_device *xe, struct xe_sysctrl_app_msg_hdr *header, + struct xe_sysctrl_event_request *request) +{ + struct pci_dev *pdev = to_pci_dev(xe->drm.dev); + + header->data = REG_FIELD_PREP(APP_HDR_GROUP_ID_MASK, XE_SYSCTRL_GROUP_GFSP) | + REG_FIELD_PREP(APP_HDR_COMMAND_MASK, XE_SYSCTRL_CMD_GET_PENDING_EVENT); + + request->vector = xe_device_has_msix(xe) ? XE_IRQ_DEFAULT_MSIX : 0; + request->fn = PCI_FUNC(pdev->devfn); +} + +/** + * xe_sysctrl_event() - Handler for System Controller events + * @sc: System Controller instance + * + * Handle events generated by System Controller. + */ +void xe_sysctrl_event(struct xe_sysctrl *sc) +{ + struct xe_sysctrl_mailbox_command command = {}; + struct xe_sysctrl_event_response response = {}; + struct xe_sysctrl_event_request request = {}; + struct xe_sysctrl_app_msg_hdr header = {}; + + xe_device_assert_mem_access(sc_to_xe(sc)); + event_request_prepare(sc_to_xe(sc), &header, &request); + + command.header = header; + command.data_in = &request; + command.data_in_len = sizeof(request); + command.data_out = &response; + command.data_out_len = sizeof(response); + + guard(mutex)(&sc->event_lock); + get_pending_event(sc, &command); +} diff --git a/drivers/gpu/drm/xe/xe_sysctrl_event_types.h b/drivers/gpu/drm/xe/xe_sysctrl_event_types.h new file mode 100644 index 000000000000..c16c66b9fa7f --- /dev/null +++ b/drivers/gpu/drm/xe/xe_sysctrl_event_types.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2026 Intel Corporation + */ + +#ifndef _XE_SYSCTRL_EVENT_TYPES_H_ +#define _XE_SYSCTRL_EVENT_TYPES_H_ + +#include + +#define XE_SYSCTRL_EVENT_DATA_LEN 59 + +/* Modify as needed */ +#define XE_SYSCTRL_EVENT_FLOOD 16 + +/** + * enum xe_sysctrl_event - Events reported by System Controller + * + * @XE_SYSCTRL_EVENT_THRESHOLD_CROSSED: Error counter threshold crossed + */ +enum xe_sysctrl_event { + XE_SYSCTRL_EVENT_THRESHOLD_CROSSED = 0x01, +}; + +/** + * struct xe_sysctrl_event_request - Request structure for pending event + */ +struct xe_sysctrl_event_request { + /** @vector: MSI-X vector that was triggered */ + u32 vector; + /** @fn: Function index (0-7) of PCIe device */ + u32 fn:8; + /** @reserved: Reserved for future use */ + u32 reserved:24; + /** @reserved1: Reserved for future use */ + u32 reserved1[2]; +} __packed; + +/** + * struct xe_sysctrl_event_response - Response structure for pending event + */ +struct xe_sysctrl_event_response { + /** @count: Pending event count after this response */ + u32 count; + /** @event: Pending event type */ + u32 event; + /** @timestamp: Timestamp of most recent event */ + u64 timestamp; + /** @extended: Event has extended payload */ + u32 extended:1; + /** @reserved: Reserved for future use */ + u32 reserved:31; + /** @data: Generic event data */ + u32 data[XE_SYSCTRL_EVENT_DATA_LEN]; +} __packed; + +#endif /* _XE_SYSCTRL_EVENT_TYPES_H_ */ diff --git a/drivers/gpu/drm/xe/xe_sysctrl_mailbox.c b/drivers/gpu/drm/xe/xe_sysctrl_mailbox.c new file mode 100644 index 000000000000..3caa9f15875f --- /dev/null +++ b/drivers/gpu/drm/xe/xe_sysctrl_mailbox.c @@ -0,0 +1,371 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2026 Intel Corporation + */ + +#include +#include +#include +#include +#include + +#include "regs/xe_sysctrl_regs.h" +#include "xe_device.h" +#include "xe_mmio.h" +#include "xe_pm.h" +#include "xe_printk.h" +#include "xe_sysctrl.h" +#include "xe_sysctrl_mailbox.h" +#include "xe_sysctrl_mailbox_types.h" + +struct xe_sysctrl_mailbox_msg_hdr { + __le32 data; +} __packed; + +#define XE_SYSCTRL_HDR_GROUP_ID(hdr) \ + FIELD_GET(SYSCTRL_HDR_GROUP_ID_MASK, le32_to_cpu((hdr)->data)) + +#define XE_SYSCTRL_HDR_COMMAND(hdr) \ + FIELD_GET(SYSCTRL_HDR_COMMAND_MASK, le32_to_cpu((hdr)->data)) + +#define XE_SYSCTRL_HDR_IS_RESPONSE(hdr) \ + FIELD_GET(SYSCTRL_HDR_IS_RESPONSE, le32_to_cpu((hdr)->data)) + +#define XE_SYSCTRL_HDR_RESULT(hdr) \ + FIELD_GET(SYSCTRL_HDR_RESULT_MASK, le32_to_cpu((hdr)->data)) + +static bool sysctrl_wait_bit_clear(struct xe_sysctrl *sc, u32 bit_mask, + unsigned int timeout_ms) +{ + int ret; + + ret = xe_mmio_wait32_not(sc->mmio, SYSCTRL_MB_CTRL, bit_mask, bit_mask, + timeout_ms * 1000, NULL, false); + + return ret == 0; +} + +static bool sysctrl_wait_bit_set(struct xe_sysctrl *sc, u32 bit_mask, + unsigned int timeout_ms) +{ + int ret; + + ret = xe_mmio_wait32(sc->mmio, SYSCTRL_MB_CTRL, bit_mask, bit_mask, + timeout_ms * 1000, NULL, false); + + return ret == 0; +} + +static int sysctrl_write_frame(struct xe_sysctrl *sc, const void *frame, + size_t len) +{ + static const struct xe_reg regs[] = { + SYSCTRL_MB_DATA0, SYSCTRL_MB_DATA1, SYSCTRL_MB_DATA2, SYSCTRL_MB_DATA3 + }; + struct xe_device *xe = sc_to_xe(sc); + u32 val[XE_SYSCTRL_MB_FRAME_SIZE / sizeof(u32)] = {0}; + u32 dw = DIV_ROUND_UP(len, sizeof(u32)); + u32 i; + + xe_assert(xe, len > 0 && len <= XE_SYSCTRL_MB_FRAME_SIZE); + + memcpy(val, frame, len); + + for (i = 0; i < dw; i++) + xe_mmio_write32(sc->mmio, regs[i], val[i]); + + return 0; +} + +static int sysctrl_read_frame(struct xe_sysctrl *sc, void *frame, + size_t len) +{ + static const struct xe_reg regs[] = { + SYSCTRL_MB_DATA0, SYSCTRL_MB_DATA1, SYSCTRL_MB_DATA2, SYSCTRL_MB_DATA3 + }; + struct xe_device *xe = sc_to_xe(sc); + u32 val[XE_SYSCTRL_MB_FRAME_SIZE / sizeof(u32)] = {0}; + u32 dw = DIV_ROUND_UP(len, sizeof(u32)); + u32 i; + + xe_assert(xe, len > 0 && len <= XE_SYSCTRL_MB_FRAME_SIZE); + + for (i = 0; i < dw; i++) + val[i] = xe_mmio_read32(sc->mmio, regs[i]); + + memcpy(frame, val, len); + + return 0; +} + +static void sysctrl_clear_response(struct xe_sysctrl *sc) +{ + xe_mmio_rmw32(sc->mmio, SYSCTRL_MB_CTRL, SYSCTRL_MB_CTRL_RUN_BUSY_OUT, 0); +} + +static int sysctrl_prepare_command(struct xe_device *xe, + u8 group_id, u8 command, + const void *data_in, size_t data_in_len, + u8 **mbox_cmd, size_t *cmd_size) +{ + struct xe_sysctrl_mailbox_msg_hdr *hdr; + size_t size; + u8 *buffer; + + xe_assert(xe, command <= SYSCTRL_HDR_COMMAND_MAX); + + if (data_in_len > XE_SYSCTRL_MB_MAX_MESSAGE_SIZE - sizeof(*hdr)) { + xe_err(xe, "sysctrl: Input data too large: %zu bytes\n", data_in_len); + return -EINVAL; + } + + size = sizeof(*hdr) + data_in_len; + + buffer = kmalloc(size, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + hdr = (struct xe_sysctrl_mailbox_msg_hdr *)buffer; + hdr->data = cpu_to_le32(FIELD_PREP(SYSCTRL_HDR_GROUP_ID_MASK, group_id) | + FIELD_PREP(SYSCTRL_HDR_COMMAND_MASK, command)); + + if (data_in && data_in_len) + memcpy(buffer + sizeof(*hdr), data_in, data_in_len); + + *mbox_cmd = buffer; + *cmd_size = size; + + return 0; +} + +static int sysctrl_send_frames(struct xe_sysctrl *sc, + const u8 *mbox_cmd, + size_t cmd_size, unsigned int timeout_ms) +{ + struct xe_device *xe = sc_to_xe(sc); + u32 ctrl_reg, total_frames, frame; + size_t bytes_sent, frame_size; + + total_frames = DIV_ROUND_UP(cmd_size, XE_SYSCTRL_MB_FRAME_SIZE); + + if (!sysctrl_wait_bit_clear(sc, SYSCTRL_MB_CTRL_RUN_BUSY, timeout_ms)) { + xe_err(xe, "sysctrl: Mailbox busy\n"); + return -EBUSY; + } + + sc->phase_bit ^= 1; + bytes_sent = 0; + + for (frame = 0; frame < total_frames; frame++) { + frame_size = min_t(size_t, cmd_size - bytes_sent, XE_SYSCTRL_MB_FRAME_SIZE); + + if (sysctrl_write_frame(sc, mbox_cmd + bytes_sent, frame_size)) { + xe_err(xe, "sysctrl: Failed to write frame %u\n", frame); + sc->phase_bit = 0; + return -EIO; + } + + ctrl_reg = SYSCTRL_MB_CTRL_RUN_BUSY | + REG_FIELD_PREP(SYSCTRL_FRAME_CURRENT_MASK, frame) | + REG_FIELD_PREP(SYSCTRL_FRAME_TOTAL_MASK, total_frames - 1) | + SYSCTRL_MB_CTRL_CMD | + (sc->phase_bit ? SYSCTRL_FRAME_PHASE : 0); + + xe_mmio_write32(sc->mmio, SYSCTRL_MB_CTRL, ctrl_reg); + + if (!sysctrl_wait_bit_clear(sc, SYSCTRL_MB_CTRL_RUN_BUSY, timeout_ms)) { + xe_err(xe, "sysctrl: Frame %u acknowledgment timeout\n", frame); + sc->phase_bit = 0; + return -ETIMEDOUT; + } + + bytes_sent += frame_size; + } + + return 0; +} + +static int sysctrl_process_frame(struct xe_sysctrl *sc, void *out, + size_t frame_size, unsigned int timeout_ms, + bool *done) +{ + u32 curr_frame, total_frames, ctrl_reg; + struct xe_device *xe = sc_to_xe(sc); + int ret; + + if (!sysctrl_wait_bit_set(sc, SYSCTRL_MB_CTRL_RUN_BUSY_OUT, timeout_ms)) { + xe_err(xe, "sysctrl: Response frame timeout\n"); + return -ETIMEDOUT; + } + + ctrl_reg = xe_mmio_read32(sc->mmio, SYSCTRL_MB_CTRL); + total_frames = FIELD_GET(SYSCTRL_FRAME_TOTAL_MASK, ctrl_reg); + curr_frame = FIELD_GET(SYSCTRL_FRAME_CURRENT_MASK, ctrl_reg); + + ret = sysctrl_read_frame(sc, out, frame_size); + if (ret) + return ret; + + sysctrl_clear_response(sc); + + if (curr_frame == total_frames) + *done = true; + + return 0; +} + +static int sysctrl_receive_frames(struct xe_sysctrl *sc, + const struct xe_sysctrl_mailbox_msg_hdr *req, + void *data_out, size_t data_out_len, + size_t *rdata_len, unsigned int timeout_ms) +{ + struct xe_sysctrl_mailbox_msg_hdr *hdr; + struct xe_device *xe = sc_to_xe(sc); + size_t remain = sizeof(*hdr) + data_out_len; + u8 *buffer __free(kfree) = kzalloc(remain, GFP_KERNEL); + size_t frame_size; + bool done = false; + int ret = 0; + u8 *out; + + if (!buffer) + return -ENOMEM; + + out = buffer; + while (!done && remain) { + frame_size = min_t(size_t, remain, XE_SYSCTRL_MB_FRAME_SIZE); + + ret = sysctrl_process_frame(sc, out, frame_size, timeout_ms, + &done); + if (ret) + return ret; + + remain -= frame_size; + out += frame_size; + } + + hdr = (struct xe_sysctrl_mailbox_msg_hdr *)buffer; + + if (!XE_SYSCTRL_HDR_IS_RESPONSE(hdr) || + XE_SYSCTRL_HDR_GROUP_ID(hdr) != XE_SYSCTRL_HDR_GROUP_ID(req) || + XE_SYSCTRL_HDR_COMMAND(hdr) != XE_SYSCTRL_HDR_COMMAND(req)) { + xe_err(xe, "sysctrl: Response header mismatch\n"); + return -EPROTO; + } + + if (XE_SYSCTRL_HDR_RESULT(hdr) != 0) { + xe_err(xe, "sysctrl: Firmware error: 0x%02lx\n", + XE_SYSCTRL_HDR_RESULT(hdr)); + return -EIO; + } + + memcpy(data_out, hdr + 1, data_out_len); + *rdata_len = out - buffer - sizeof(*hdr); + + return 0; +} + +static int sysctrl_send_command(struct xe_sysctrl *sc, + const u8 *mbox_cmd, size_t cmd_size, + void *data_out, size_t data_out_len, + size_t *rdata_len, unsigned int timeout_ms) +{ + const struct xe_sysctrl_mailbox_msg_hdr *hdr; + size_t received; + int ret; + + ret = sysctrl_send_frames(sc, mbox_cmd, cmd_size, timeout_ms); + if (ret) + return ret; + + if (!data_out || !rdata_len) + return 0; + + hdr = (const struct xe_sysctrl_mailbox_msg_hdr *)mbox_cmd; + + ret = sysctrl_receive_frames(sc, hdr, data_out, data_out_len, + &received, timeout_ms); + if (ret) + return ret; + + *rdata_len = received; + + return 0; +} + +/** + * xe_sysctrl_mailbox_init - Initialize System Controller mailbox interface + * @sc: System controller structure + * + * Initialize system controller mailbox interface for communication. + */ +void xe_sysctrl_mailbox_init(struct xe_sysctrl *sc) +{ + u32 ctrl_reg; + + ctrl_reg = xe_mmio_read32(sc->mmio, SYSCTRL_MB_CTRL); + sc->phase_bit = (ctrl_reg & SYSCTRL_FRAME_PHASE) ? 1 : 0; +} + +/** + * xe_sysctrl_send_command() - Send mailbox command to System Controller + * @sc: System Controller instance + * @cmd: Command descriptor containing request header and payload buffers + * @rdata_len: Pointer to store actual response data length + * + * Sends a mailbox command to System Controller firmware using + * System Controller mailbox and waits for a response. + * + * Request payload is provided via @cmd->data_in and @cmd->data_in_len. + * If a response is expected, @cmd->data_out must point to a buffer of + * size @cmd->data_out_len supplied by caller. + * + * On success, @rdata_len is updated with number of valid response bytes + * returned by firmware, bounded by @cmd->data_out_len. + * + * Return: 0 on success, or negative errno on failure. + */ +int xe_sysctrl_send_command(struct xe_sysctrl *sc, + struct xe_sysctrl_mailbox_command *cmd, + size_t *rdata_len) +{ + struct xe_device *xe = sc_to_xe(sc); + u8 group_id, command_code; + u8 *mbox_cmd = NULL; + size_t cmd_size = 0; + int ret; + + guard(xe_pm_runtime_noresume)(xe); + + if (!xe->info.has_sysctrl) + return -ENODEV; + + xe_assert(xe, cmd->data_in || cmd->data_out); + xe_assert(xe, !cmd->data_in || cmd->data_in_len); + xe_assert(xe, !cmd->data_out || cmd->data_out_len); + + group_id = XE_SYSCTRL_APP_HDR_GROUP_ID(&cmd->header); + command_code = XE_SYSCTRL_APP_HDR_COMMAND(&cmd->header); + + might_sleep(); + + ret = sysctrl_prepare_command(xe, group_id, command_code, + cmd->data_in, cmd->data_in_len, + &mbox_cmd, &cmd_size); + if (ret) { + xe_err(xe, "sysctrl: Failed to prepare command: %pe\n", ERR_PTR(ret)); + return ret; + } + + guard(mutex)(&sc->cmd_lock); + + ret = sysctrl_send_command(sc, mbox_cmd, cmd_size, + cmd->data_out, cmd->data_out_len, rdata_len, + XE_SYSCTRL_MB_DEFAULT_TIMEOUT_MS); + if (ret) + xe_err(xe, "sysctrl: Mailbox command failed: %pe\n", ERR_PTR(ret)); + + kfree(mbox_cmd); + + return ret; +} diff --git a/drivers/gpu/drm/xe/xe_sysctrl_mailbox.h b/drivers/gpu/drm/xe/xe_sysctrl_mailbox.h new file mode 100644 index 000000000000..f67e9234de48 --- /dev/null +++ b/drivers/gpu/drm/xe/xe_sysctrl_mailbox.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2026 Intel Corporation + */ + +#ifndef _XE_SYSCTRL_MAILBOX_H_ +#define _XE_SYSCTRL_MAILBOX_H_ + +#include +#include + +#include "abi/xe_sysctrl_abi.h" + +struct xe_sysctrl; +struct xe_sysctrl_mailbox_command; + +#define XE_SYSCTRL_APP_HDR_GROUP_ID(hdr) \ + FIELD_GET(APP_HDR_GROUP_ID_MASK, (hdr)->data) + +#define XE_SYSCTRL_APP_HDR_COMMAND(hdr) \ + FIELD_GET(APP_HDR_COMMAND_MASK, (hdr)->data) + +#define XE_SYSCTRL_APP_HDR_VERSION(hdr) \ + FIELD_GET(APP_HDR_VERSION_MASK, (hdr)->data) + +void xe_sysctrl_mailbox_init(struct xe_sysctrl *sc); +int xe_sysctrl_send_command(struct xe_sysctrl *sc, + struct xe_sysctrl_mailbox_command *cmd, + size_t *rdata_len); + +#endif diff --git a/drivers/gpu/drm/xe/xe_sysctrl_mailbox_types.h b/drivers/gpu/drm/xe/xe_sysctrl_mailbox_types.h new file mode 100644 index 000000000000..84d7c647e743 --- /dev/null +++ b/drivers/gpu/drm/xe/xe_sysctrl_mailbox_types.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2026 Intel Corporation + */ + +#ifndef _XE_SYSCTRL_MAILBOX_TYPES_H_ +#define _XE_SYSCTRL_MAILBOX_TYPES_H_ + +#include + +#include "abi/xe_sysctrl_abi.h" + +/** + * enum xe_sysctrl_group - System Controller command groups + * + * @XE_SYSCTRL_GROUP_GFSP: GFSP group + */ +enum xe_sysctrl_group { + XE_SYSCTRL_GROUP_GFSP = 0x01, +}; + +/** + * enum xe_sysctrl_gfsp_cmd - Commands supported by GFSP group + * + * @XE_SYSCTRL_CMD_GET_PENDING_EVENT: Retrieve pending event + */ +enum xe_sysctrl_gfsp_cmd { + XE_SYSCTRL_CMD_GET_PENDING_EVENT = 0x07, +}; + +/** + * struct xe_sysctrl_mailbox_command - System Controller mailbox command + */ +struct xe_sysctrl_mailbox_command { + /** @header: Application message header containing command information */ + struct xe_sysctrl_app_msg_hdr header; + + /** @data_in: Pointer to input payload data (can be NULL if no input data) */ + void *data_in; + + /** @data_in_len: Size of input payload in bytes (0 if no input data) */ + size_t data_in_len; + + /** @data_out: Pointer to output buffer for response data (can be NULL if no response) */ + void *data_out; + + /** @data_out_len: Size of output buffer in bytes (0 if no response expected) */ + size_t data_out_len; +}; + +#define XE_SYSCTRL_MB_FRAME_SIZE 16 +#define XE_SYSCTRL_MB_MAX_FRAMES 64 +#define XE_SYSCTRL_MB_MAX_MESSAGE_SIZE \ + (XE_SYSCTRL_MB_FRAME_SIZE * XE_SYSCTRL_MB_MAX_FRAMES) + +#define XE_SYSCTRL_MB_DEFAULT_TIMEOUT_MS 500 + +#endif diff --git a/drivers/gpu/drm/xe/xe_sysctrl_types.h b/drivers/gpu/drm/xe/xe_sysctrl_types.h new file mode 100644 index 000000000000..66ba24f43017 --- /dev/null +++ b/drivers/gpu/drm/xe/xe_sysctrl_types.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2026 Intel Corporation + */ + +#ifndef _XE_SYSCTRL_TYPES_H_ +#define _XE_SYSCTRL_TYPES_H_ + +#include +#include +#include + +struct xe_mmio; + +/** + * struct xe_sysctrl - System Controller driver context + * + * This structure maintains the runtime state for System Controller + * communication. All fields are initialized during xe_sysctrl_init() + * and protected appropriately for concurrent access. + */ +struct xe_sysctrl { + /** @mmio: MMIO region for system control registers */ + struct xe_mmio *mmio; + + /** @cmd_lock: Mutex protecting mailbox command operations */ + struct mutex cmd_lock; + + /** @phase_bit: Message boundary phase toggle bit (0 or 1) */ + bool phase_bit; + + /** @work: Pending events worker */ + struct work_struct work; + + /** @event_lock: Mutex protecting pending events */ + struct mutex event_lock; +}; + +#endif diff --git a/drivers/gpu/drm/xe/xe_tlb_inval.c b/drivers/gpu/drm/xe/xe_tlb_inval.c index 10dcd4abb00f..bbd21d393062 100644 --- a/drivers/gpu/drm/xe/xe_tlb_inval.c +++ b/drivers/gpu/drm/xe/xe_tlb_inval.c @@ -529,7 +529,7 @@ int xe_tlb_inval_range_tilemask_submit(struct xe_device *xe, u32 asid, struct xe_tile *tile; u32 fence_id = 0; u8 id; - int err; + int err = 0; batch->num_fences = 0; if (!tile_mask) diff --git a/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c b/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c index 5fd0d5506a7e..6ba47996bc7c 100644 --- a/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c +++ b/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c @@ -292,8 +292,6 @@ static void xe_ttm_vram_mgr_fini(struct drm_device *dev, void *arg) ttm_resource_manager_cleanup(&mgr->manager); ttm_set_driver_manager(&xe->ttm, mgr->mem_type, NULL); - - mutex_destroy(&mgr->lock); } int __xe_ttm_vram_mgr_init(struct xe_device *xe, struct xe_ttm_vram_mgr *mgr, @@ -312,7 +310,9 @@ int __xe_ttm_vram_mgr_init(struct xe_device *xe, struct xe_ttm_vram_mgr *mgr, man->func = &xe_ttm_vram_mgr_func; mgr->mem_type = mem_type; - mutex_init(&mgr->lock); + err = drmm_mutex_init(&xe->drm, &mgr->lock); + if (err) + return err; mgr->default_page_size = default_page_size; mgr->visible_size = io_size; mgr->visible_avail = io_size; diff --git a/drivers/gpu/drm/xe/xe_tuning.c b/drivers/gpu/drm/xe/xe_tuning.c index 0b78ec2bc6a4..ce39b77a084a 100644 --- a/drivers/gpu/drm/xe/xe_tuning.c +++ b/drivers/gpu/drm/xe/xe_tuning.c @@ -43,7 +43,7 @@ static const struct xe_rtp_entry_sr gt_tunings[] = { REG_FIELD_PREP(L3_PWM_TIMER_INIT_VAL_MASK, 0x7f))) }, { XE_RTP_NAME("Tuning: Compression Overfetch"), - XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, XE_RTP_END_VERSION_UNDEFINED), + XE_RTP_RULES(GRAPHICS_VERSION_RANGE(2001, 3499), FUNC(xe_rtp_match_has_flat_ccs)), XE_RTP_ACTIONS(CLR(CCCHKNREG1, ENCOMPPERFFIX), SET(CCCHKNREG1, L3CMPCTRL)) @@ -124,6 +124,11 @@ static const struct xe_rtp_entry_sr engine_tunings[] = { GHWSP_CSB_REPORT_DIS, XE_RTP_ACTION_FLAG(ENGINE_BASE))) }, + { XE_RTP_NAME("Tuning: TileY 2x2 Walk"), + XE_RTP_RULES(GRAPHICS_VERSION_RANGE(3510, XE_RTP_END_VERSION_UNDEFINED), + FUNC(xe_rtp_match_first_render_or_compute)), + XE_RTP_ACTIONS(SET(TDL_TSL_CHICKEN2, TILEY_LOCALID)) + }, }; static const struct xe_rtp_entry_sr lrc_tunings[] = { diff --git a/drivers/gpu/drm/xe/xe_tuning.h b/drivers/gpu/drm/xe/xe_tuning.h index c1cc5927fda7..d18e187debf6 100644 --- a/drivers/gpu/drm/xe/xe_tuning.h +++ b/drivers/gpu/drm/xe/xe_tuning.h @@ -3,8 +3,8 @@ * Copyright © 2022 Intel Corporation */ -#ifndef _XE_TUNING_ -#define _XE_TUNING_ +#ifndef _XE_TUNING_H_ +#define _XE_TUNING_H_ struct drm_printer; struct xe_gt; diff --git a/drivers/gpu/drm/xe/xe_uc_fw.c b/drivers/gpu/drm/xe/xe_uc_fw.c index 9cebb2490245..df2aa196f6f9 100644 --- a/drivers/gpu/drm/xe/xe_uc_fw.c +++ b/drivers/gpu/drm/xe/xe_uc_fw.c @@ -214,6 +214,17 @@ static struct xe_device *uc_fw_to_xe(struct xe_uc_fw *uc_fw) return gt_to_xe(uc_fw_to_gt(uc_fw)); } +#if IS_ENABLED(CONFIG_DRM_XE_DEBUG_GUC) +void xe_uc_fw_change_status(struct xe_uc_fw *uc_fw, enum xe_uc_fw_status status) +{ + xe_gt_dbg(uc_fw_to_gt(uc_fw), "%s %s->%s\n", + xe_uc_fw_type_repr(uc_fw->type), + xe_uc_fw_status_repr(uc_fw->status), + xe_uc_fw_status_repr(status)); + uc_fw->__status = status; +} +#endif + static void uc_fw_auto_select(struct xe_device *xe, struct xe_uc_fw *uc_fw) { diff --git a/drivers/gpu/drm/xe/xe_uc_fw.h b/drivers/gpu/drm/xe/xe_uc_fw.h index 6195e353f269..bb281b72a677 100644 --- a/drivers/gpu/drm/xe/xe_uc_fw.h +++ b/drivers/gpu/drm/xe/xe_uc_fw.h @@ -25,11 +25,15 @@ static inline u32 xe_uc_fw_rsa_offset(struct xe_uc_fw *uc_fw) return sizeof(struct uc_css_header) + uc_fw->ucode_size + uc_fw->css_offset; } +#if IS_ENABLED(CONFIG_DRM_XE_DEBUG_GUC) +void xe_uc_fw_change_status(struct xe_uc_fw *uc_fw, enum xe_uc_fw_status status); +#else static inline void xe_uc_fw_change_status(struct xe_uc_fw *uc_fw, enum xe_uc_fw_status status) { uc_fw->__status = status; } +#endif static inline const char *xe_uc_fw_status_repr(enum xe_uc_fw_status status) diff --git a/drivers/gpu/drm/xe/xe_uc_fw_abi.h b/drivers/gpu/drm/xe/xe_uc_fw_abi.h index 3c9a63d13032..74b888904fdc 100644 --- a/drivers/gpu/drm/xe/xe_uc_fw_abi.h +++ b/drivers/gpu/drm/xe/xe_uc_fw_abi.h @@ -3,8 +3,8 @@ * Copyright © 2022 Intel Corporation */ -#ifndef _XE_UC_FW_ABI_H -#define _XE_UC_FW_ABI_H +#ifndef _XE_UC_FW_ABI_H_ +#define _XE_UC_FW_ABI_H_ #include #include diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index a717a2b8dea3..c3836f6eab35 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -634,9 +634,9 @@ void xe_vm_add_fault_entry_pf(struct xe_vm *vm, struct xe_pagefault *pf) e->address_precision = SZ_4K; e->access_type = pf->consumer.access_type; e->fault_type = FIELD_GET(XE_PAGEFAULT_TYPE_MASK, - pf->consumer.fault_type_level), + pf->consumer.fault_type_level); e->fault_level = FIELD_GET(XE_PAGEFAULT_LEVEL_MASK, - pf->consumer.fault_type_level), + pf->consumer.fault_type_level); list_add_tail(&e->list, &vm->faults.list); vm->faults.len++; @@ -1399,9 +1399,9 @@ static u16 pde_pat_index(struct xe_bo *bo) * something which is always safe). */ if (!xe_bo_is_vram(bo) && bo->ttm.ttm->caching == ttm_cached) - pat_index = xe->pat.idx[XE_CACHE_WB]; + pat_index = xe_cache_pat_idx(xe, XE_CACHE_WB); else - pat_index = xe->pat.idx[XE_CACHE_NONE]; + pat_index = xe_cache_pat_idx(xe, XE_CACHE_NONE); xe_assert(xe, pat_index <= 3); @@ -4206,7 +4206,7 @@ struct dma_fence *xe_vm_bind_kernel_bo(struct xe_vm *vm, struct xe_bo *bo, ops = vm_bind_ioctl_ops_create(vm, &vops, bo, 0, addr, xe_bo_size(bo), DRM_XE_VM_BIND_OP_MAP, 0, 0, - vm->xe->pat.idx[cache_lvl]); + xe_cache_pat_idx(vm->xe, cache_lvl)); if (IS_ERR(ops)) { err = PTR_ERR(ops); goto release_vm_lock; @@ -4409,7 +4409,7 @@ struct xe_vm_snapshot { #define XE_VM_SNAP_FLAG_IS_NULL BIT(2) unsigned long flags; int uapi_mem_region; - int pat_index; + u16 pat_index; int cpu_caching; struct xe_bo *bo; void *data; diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h index a94827d7fbec..635ed29b9a69 100644 --- a/drivers/gpu/drm/xe/xe_vm_types.h +++ b/drivers/gpu/drm/xe/xe_vm_types.h @@ -412,10 +412,11 @@ struct xe_vm { struct xe_vma_op_map { /** @vma: VMA to map */ struct xe_vma *vma; + /** @vma_flags: VMA flags for this operation */ unsigned int vma_flags; /** @immediate: Immediate bind */ bool immediate; - /** @read_only: Read only */ + /** @invalidate_on_bind: Invalidate on bind */ bool invalidate_on_bind; /** @request_decompress: schedule decompression for GPU map */ bool request_decompress; diff --git a/drivers/gpu/drm/xe/xe_vram.c b/drivers/gpu/drm/xe/xe_vram.c index 0538dcb8b18c..23eb7edbdd57 100644 --- a/drivers/gpu/drm/xe/xe_vram.c +++ b/drivers/gpu/drm/xe/xe_vram.c @@ -13,6 +13,7 @@ #include "regs/xe_gt_regs.h" #include "regs/xe_regs.h" #include "xe_assert.h" +#include "xe_bo.h" #include "xe_device.h" #include "xe_force_wake.h" #include "xe_gt_mcr.h" @@ -249,6 +250,27 @@ static int vram_region_init(struct xe_device *xe, struct xe_vram_region *vram, return 0; } +/** + * xe_map_resource_to_region - Map ttm resource to vram memory region + * @res: The ttm resource + * + * Get vram memory region using vram memory manager managing this resource + * + * Returns: pointer to xe_vram_region + */ +struct xe_vram_region *xe_map_resource_to_region(struct ttm_resource *res) +{ + struct xe_device *xe = ttm_to_xe_device(res->bo->bdev); + struct ttm_resource_manager *mgr; + struct xe_ttm_vram_mgr *vram_mgr; + + xe_assert(xe, mem_type_is_vram(res->mem_type)); + mgr = ttm_manager_type(&xe->ttm, res->mem_type); + vram_mgr = to_xe_ttm_vram_mgr(mgr); + + return container_of(vram_mgr, struct xe_vram_region, ttm); +} + /** * xe_vram_probe() - Probe VRAM configuration * @xe: the &xe_device diff --git a/drivers/gpu/drm/xe/xe_vram.h b/drivers/gpu/drm/xe/xe_vram.h index 72860f714fc6..dd1c8bf17922 100644 --- a/drivers/gpu/drm/xe/xe_vram.h +++ b/drivers/gpu/drm/xe/xe_vram.h @@ -10,7 +10,9 @@ struct xe_device; struct xe_vram_region; +struct ttm_resource; +struct xe_vram_region *xe_map_resource_to_region(struct ttm_resource *res); int xe_vram_probe(struct xe_device *xe); struct xe_vram_region *xe_vram_region_alloc(struct xe_device *xe, u8 id, u32 placement); diff --git a/drivers/gpu/drm/xe/xe_wa.c b/drivers/gpu/drm/xe/xe_wa.c index 4b1cbced06be..49f5e3e4c7cc 100644 --- a/drivers/gpu/drm/xe/xe_wa.c +++ b/drivers/gpu/drm/xe/xe_wa.c @@ -601,6 +601,19 @@ static const struct xe_rtp_entry_sr engine_was[] = { FUNC(xe_rtp_match_first_render_or_compute)), XE_RTP_ACTIONS(SET(ROW_CHICKEN5, CPSS_AWARE_DIS)) }, + + /* Xe3p_XPC */ + + { XE_RTP_NAME("14026999295"), + XE_RTP_RULES(GRAPHICS_VERSION(3511), + FUNC(xe_rtp_match_first_render_or_compute)), + XE_RTP_ACTIONS(SET(ROW_CHICKEN3, DIS_EU_GRF_POISON_TO_LSC)) + }, + { XE_RTP_NAME("18044193044"), + XE_RTP_RULES(GRAPHICS_VERSION(3510), GRAPHICS_STEP(A0, B0), + FUNC(xe_rtp_match_first_render_or_compute)), + XE_RTP_ACTIONS(SET(TDL_CHICKEN, BIT_APQ_OPT_DIS)) + }, }; static const struct xe_rtp_entry_sr lrc_was[] = { diff --git a/drivers/gpu/drm/xe/xe_wa.h b/drivers/gpu/drm/xe/xe_wa.h index 8fd6a5af0910..a5f7d33c1b32 100644 --- a/drivers/gpu/drm/xe/xe_wa.h +++ b/drivers/gpu/drm/xe/xe_wa.h @@ -3,8 +3,8 @@ * Copyright © 2022 Intel Corporation */ -#ifndef _XE_WA_ -#define _XE_WA_ +#ifndef _XE_WA_H_ +#define _XE_WA_H_ #include "xe_assert.h" diff --git a/drivers/gpu/drm/xe/xe_wa_oob.rules b/drivers/gpu/drm/xe/xe_wa_oob.rules index 80b54b195f20..f8a185103b80 100644 --- a/drivers/gpu/drm/xe/xe_wa_oob.rules +++ b/drivers/gpu/drm/xe/xe_wa_oob.rules @@ -51,6 +51,13 @@ MEDIA_VERSION_RANGE(2000, 3002), FUNC(xe_rtp_match_psmi_enabled) 16023683509 MEDIA_VERSION(2000), FUNC(xe_rtp_match_psmi_enabled) MEDIA_VERSION(3000), MEDIA_STEP(A0, B0), FUNC(xe_rtp_match_psmi_enabled) +14025515070 GRAPHICS_VERSION(2004) + MEDIA_VERSION_RANGE(1301, 3000) + MEDIA_VERSION(3002) + GRAPHICS_VERSION_RANGE(3000, 3001) + GRAPHICS_VERSION_RANGE(3003, 3005) + MEDIA_VERSION(3500) + GRAPHICS_VERSION(3510), GRAPHICS_STEP(A0, B0) 15015404425_disable PLATFORM(PANTHERLAKE), MEDIA_STEP(B0, FOREVER) 16026007364 MEDIA_VERSION(3000) diff --git a/include/drm/drm_ras.h b/include/drm/drm_ras.h index 5d50209e51db..f2a787bc4f64 100644 --- a/include/drm/drm_ras.h +++ b/include/drm/drm_ras.h @@ -58,6 +58,17 @@ struct drm_ras_node { int (*query_error_counter)(struct drm_ras_node *node, u32 error_id, const char **name, u32 *val); + /** + * @clear_error_counter: + * + * This callback is used by drm_ras to clear a specific error counter. + * Driver should implement this callback to support clearing error counters + * of a node. + * + * Returns: 0 on success, negative error code on failure. + */ + int (*clear_error_counter)(struct drm_ras_node *node, u32 error_id); + /** @priv: Driver private data */ void *priv; }; diff --git a/include/uapi/drm/drm_ras.h b/include/uapi/drm/drm_ras.h index 5f40fa5b869d..218a3ee86805 100644 --- a/include/uapi/drm/drm_ras.h +++ b/include/uapi/drm/drm_ras.h @@ -41,6 +41,7 @@ enum { enum { DRM_RAS_CMD_LIST_NODES = 1, DRM_RAS_CMD_GET_ERROR_COUNTER, + DRM_RAS_CMD_CLEAR_ERROR_COUNTER, __DRM_RAS_CMD_MAX, DRM_RAS_CMD_MAX = (__DRM_RAS_CMD_MAX - 1) diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h index ae2fda23ce7c..48e9f1fdb78d 100644 --- a/include/uapi/drm/xe_drm.h +++ b/include/uapi/drm/xe_drm.h @@ -83,6 +83,7 @@ extern "C" { * - &DRM_IOCTL_XE_OBSERVATION * - &DRM_IOCTL_XE_MADVISE * - &DRM_IOCTL_XE_VM_QUERY_MEM_RANGE_ATTRS + * - &DRM_IOCTL_XE_EXEC_QUEUE_SET_PROPERTY * - &DRM_IOCTL_XE_VM_GET_PROPERTY */ @@ -167,7 +168,7 @@ extern "C" { * Typically the struct drm_xe_user_extension would be embedded in some uAPI * struct, and in this case we would feed it the head of the chain(i.e ext1), * which would then apply all of the above extensions. -*/ + */ /** * struct drm_xe_user_extension - Base class for defining a chain of extensions @@ -229,9 +230,9 @@ struct drm_xe_ext_set_property { /** * struct drm_xe_engine_class_instance - instance of an engine class * - * It is returned as part of the @drm_xe_engine, but it also is used as - * the input of engine selection for both @drm_xe_exec_queue_create and - * @drm_xe_query_engine_cycles + * It is returned as part of the &struct drm_xe_engine, but it also is used as + * the input of engine selection for both &struct drm_xe_exec_queue_create and + * &struct drm_xe_query_engine_cycles * * The @engine_class can be: * - %DRM_XE_ENGINE_CLASS_RENDER @@ -264,7 +265,7 @@ struct drm_xe_engine_class_instance { * struct drm_xe_engine - describe hardware engine */ struct drm_xe_engine { - /** @instance: The @drm_xe_engine_class_instance */ + /** @instance: The &struct drm_xe_engine_class_instance */ struct drm_xe_engine_class_instance instance; /** @reserved: Reserved */ @@ -274,9 +275,9 @@ struct drm_xe_engine { /** * struct drm_xe_query_engines - describe engines * - * If a query is made with a struct @drm_xe_device_query where .query + * If a query is made with a &struct drm_xe_device_query where .query * is equal to %DRM_XE_DEVICE_QUERY_ENGINES, then the reply uses an array of - * struct @drm_xe_query_engines in .data. + * &struct drm_xe_query_engines in .data. */ struct drm_xe_query_engines { /** @num_engines: number of engines returned in @engines */ @@ -349,7 +350,7 @@ struct drm_xe_mem_region { * is smaller than @total_size then this is referred to as a * small BAR system. * - * On systems without small BAR (full BAR), the probed_size will + * On systems without small BAR (full BAR), the @cpu_visible_size will * always equal the @total_size, since all of it will be CPU * accessible. * @@ -410,7 +411,7 @@ struct drm_xe_query_mem_regions { * device supports the userspace hint %DRM_XE_GEM_CREATE_FLAG_NO_COMPRESSION. * This is exposed only on Xe2+. * - %DRM_XE_QUERY_CONFIG_FLAG_HAS_DISABLE_STATE_CACHE_PERF_FIX - Flag is set - * if a queue can be creaed with + * if a queue can be created with * %DRM_XE_EXEC_QUEUE_SET_DISABLE_STATE_CACHE_PERF_FIX * - %DRM_XE_QUERY_CONFIG_MIN_ALIGNMENT - Minimal memory alignment * required by this device, typically SZ_4K or SZ_64K @@ -705,7 +706,10 @@ struct drm_xe_query_pxp_status { * attributes. * - %DRM_XE_DEVICE_QUERY_GT_TOPOLOGY * - %DRM_XE_DEVICE_QUERY_ENGINE_CYCLES + * - %DRM_XE_DEVICE_QUERY_UC_FW_VERSION + * - %DRM_XE_DEVICE_QUERY_OA_UNITS * - %DRM_XE_DEVICE_QUERY_PXP_STATUS + * - %DRM_XE_DEVICE_QUERY_EU_STALL * * If size is set to 0, the driver fills it with the required size for * the requested type of data to query. If size is equal to the required @@ -825,7 +829,7 @@ struct drm_xe_device_query { * * This ioctl supports setting the following properties via the * %DRM_XE_GEM_CREATE_EXTENSION_SET_PROPERTY extension, which uses the - * generic @drm_xe_ext_set_property struct: + * generic &struct drm_xe_ext_set_property: * * - %DRM_XE_GEM_CREATE_SET_PROPERTY_PXP_TYPE - set the type of PXP session * this object will be used with. Valid values are listed in enum @@ -862,8 +866,7 @@ struct drm_xe_gem_create { #define DRM_XE_GEM_CREATE_FLAG_NEEDS_VISIBLE_VRAM (1 << 2) #define DRM_XE_GEM_CREATE_FLAG_NO_COMPRESSION (1 << 3) /** - * @flags: Flags, currently a mask of memory instances of where BO can - * be placed + * @flags: Flags for the GEM object, see DRM_XE_GEM_CREATE_FLAG_* */ __u32 flags; @@ -888,7 +891,7 @@ struct drm_xe_gem_create { #define DRM_XE_GEM_CPU_CACHING_WC 2 /** * @cpu_caching: The CPU caching mode to select for this object. If - * mmaping the object the mode selected here will also be used. The + * mmapping the object the mode selected here will also be used. The * exception is when mapping system memory (including data evicted * to system) on discrete GPUs. The caching mode selected will * then be overridden to DRM_XE_GEM_CPU_CACHING_WB, and coherency @@ -931,7 +934,7 @@ struct drm_xe_gem_create { * * err = ioctl(fd, DRM_IOCTL_XE_GEM_MMAP_OFFSET, &mmo); * map = mmap(NULL, size, PROT_WRITE, MAP_SHARED, fd, mmo.offset); - * map[i] = 0xdeadbeaf; // issue barrier + * map[i] = 0xdeadbeef; // issue barrier */ struct drm_xe_gem_mmap_offset { /** @extensions: Pointer to the first extension struct, if any */ @@ -958,8 +961,8 @@ struct drm_xe_gem_mmap_offset { * - %DRM_XE_VM_CREATE_FLAG_SCRATCH_PAGE - Map the whole virtual address * space of the VM to scratch page. A vm_bind would overwrite the scratch * page mapping. This flag is mutually exclusive with the - * %DRM_XE_VM_CREATE_FLAG_FAULT_MODE flag, with an exception of on x2 and - * xe3 platform. + * %DRM_XE_VM_CREATE_FLAG_FAULT_MODE flag, with an exception on Xe2 and + * Xe3 platforms. * - %DRM_XE_VM_CREATE_FLAG_LR_MODE - An LR, or Long Running VM accepts * exec submissions to its exec_queues that don't have an upper time * limit on the job execution time. But exec submissions to these @@ -1045,7 +1048,7 @@ struct drm_xe_vm_destroy { * set, no mappings are created rather the range is reserved for CPU address * mirroring which will be populated on GPU page faults or prefetches. Only * valid on VMs with DRM_XE_VM_CREATE_FLAG_FAULT_MODE set. The CPU address - * mirror flag are only valid for DRM_XE_VM_BIND_OP_MAP operations, the BO + * mirror flag is only valid for DRM_XE_VM_BIND_OP_MAP operations, the BO * handle MBZ, and the BO offset MBZ. * - %DRM_XE_VM_BIND_FLAG_MADVISE_AUTORESET - Can be used in combination with * %DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR to reset madvises when the underlying @@ -1061,6 +1064,7 @@ struct drm_xe_vm_destroy { * not invoke autoreset. Neither will stack variables going out of scope. * Therefore it's recommended to always explicitly reset the madvises when * freeing the memory backing a region used in a &DRM_IOCTL_XE_MADVISE call. + * * - %DRM_XE_VM_BIND_FLAG_DECOMPRESS - Request on-device decompression for a MAP. * When set on a MAP bind operation, request the driver schedule an on-device * in-place decompression (via the migrate/resolve path) for the GPU mapping @@ -1109,7 +1113,7 @@ struct drm_xe_vm_bind_op { * ppGTT WT -> COH_NONE * ppGTT WB -> COH_AT_LEAST_1WAY * - * In practice UC/WC/WT should only ever used for scanout surfaces on + * In practice UC/WC/WT should only ever be used for scanout surfaces on * such platforms (or perhaps in general for dma-buf if shared with * another device) since it is only the display engine that is actually * incoherent. Everything else should typically use WB given that we @@ -1199,10 +1203,10 @@ struct drm_xe_vm_bind_op { /** * struct drm_xe_vm_bind - Input of &DRM_IOCTL_XE_VM_BIND * - * Below is an example of a minimal use of @drm_xe_vm_bind to + * Below is an example of a minimal use of &struct drm_xe_vm_bind to * asynchronously bind the buffer `data` at address `BIND_ADDRESS` to * illustrate `userptr`. It can be synchronized by using the example - * provided for @drm_xe_sync. + * provided for &struct drm_xe_sync. * * .. code-block:: C * @@ -1355,7 +1359,7 @@ struct drm_xe_vm_get_property { * * This ioctl supports setting the following properties via the * %DRM_XE_EXEC_QUEUE_EXTENSION_SET_PROPERTY extension, which uses the - * generic @drm_xe_ext_set_property struct: + * generic &struct drm_xe_ext_set_property: * * - %DRM_XE_EXEC_QUEUE_SET_PROPERTY_PRIORITY - set the queue priority. * CAP_SYS_NICE is required to set a value above normal. @@ -1366,7 +1370,7 @@ struct drm_xe_vm_get_property { * drm_xe_pxp_session_type. %DRM_XE_PXP_TYPE_NONE is the default behavior, so * there is no need to explicitly set that. When a queue of type * %DRM_XE_PXP_TYPE_HWDRM is created, the PXP default HWDRM session - * (%XE_PXP_HWDRM_DEFAULT_SESSION) will be started, if isn't already running. + * (%DRM_XE_PXP_HWDRM_DEFAULT_SESSION) will be started, if it isn't already running. * The user is expected to query the PXP status via the query ioctl (see * %DRM_XE_DEVICE_QUERY_PXP_STATUS) and to wait for PXP to be ready before * attempting to create a queue with this property. When a queue is created @@ -1390,9 +1394,9 @@ struct drm_xe_vm_get_property { * enable render color cache keying on BTP+BTI instead of just BTI * (only valid for render queues). * - * The example below shows how to use @drm_xe_exec_queue_create to create + * The example below shows how to use &struct drm_xe_exec_queue_create to create * a simple exec_queue (no parallel submission) of class - * &DRM_XE_ENGINE_CLASS_RENDER. + * %DRM_XE_ENGINE_CLASS_RENDER. * * .. code-block:: C * @@ -1402,23 +1406,25 @@ struct drm_xe_vm_get_property { * struct drm_xe_exec_queue_create exec_queue_create = { * .extensions = 0, * .vm_id = vm, - * .num_bb_per_exec = 1, - * .num_eng_per_bb = 1, + * .width = 1, + * .num_placements = 1, * .instances = to_user_pointer(&instance), * }; * ioctl(fd, DRM_IOCTL_XE_EXEC_QUEUE_CREATE, &exec_queue_create); * - * Allow users to provide a hint to kernel for cases demanding low latency - * profile. Please note it will have impact on power consumption. User can - * indicate low latency hint with flag while creating exec queue as - * mentioned below, + * Allow users to provide a hint to kernel for cases demanding low latency + * profile. Please note it will have impact on power consumption. User can + * indicate low latency hint with flag while creating exec queue as + * mentioned below: + * + * .. code-block:: C * * struct drm_xe_exec_queue_create exec_queue_create = { * .flags = DRM_XE_EXEC_QUEUE_LOW_LATENCY_HINT, * .extensions = 0, * .vm_id = vm, - * .num_bb_per_exec = 1, - * .num_eng_per_bb = 1, + * .width = 1, + * .num_placements = 1, * .instances = to_user_pointer(&instance), * }; * ioctl(fd, DRM_IOCTL_XE_EXEC_QUEUE_CREATE, &exec_queue_create); @@ -1515,7 +1521,7 @@ struct drm_xe_exec_queue_get_property { * and the @flags can be: * - %DRM_XE_SYNC_FLAG_SIGNAL * - * A minimal use of @drm_xe_sync looks like this: + * A minimal use of &struct drm_xe_sync looks like this: * * .. code-block:: C * @@ -1546,7 +1552,7 @@ struct drm_xe_sync { #define DRM_XE_SYNC_TYPE_SYNCOBJ 0x0 #define DRM_XE_SYNC_TYPE_TIMELINE_SYNCOBJ 0x1 #define DRM_XE_SYNC_TYPE_USER_FENCE 0x2 - /** @type: Type of the this sync object */ + /** @type: Type of this sync object */ __u32 type; #define DRM_XE_SYNC_FLAG_SIGNAL (1 << 0) @@ -1559,9 +1565,9 @@ struct drm_xe_sync { /** * @addr: Address of user fence. When sync is passed in via exec - * IOCTL this is a GPU address in the VM. When sync passed in via + * IOCTL this is a GPU address in the VM. When sync is passed in via * VM bind IOCTL this is a user pointer. In either case, it is - * the users responsibility that this address is present and + * the user's responsibility that this address is present and * mapped when the user fence is signalled. Must be qword * aligned. */ @@ -1581,10 +1587,10 @@ struct drm_xe_sync { /** * struct drm_xe_exec - Input of &DRM_IOCTL_XE_EXEC * - * This is an example to use @drm_xe_exec for execution of the object - * at BIND_ADDRESS (see example in @drm_xe_vm_bind) by an exec_queue - * (see example in @drm_xe_exec_queue_create). It can be synchronized - * by using the example provided for @drm_xe_sync. + * This is an example to use &struct drm_xe_exec for execution of the object + * at BIND_ADDRESS (see example in &struct drm_xe_vm_bind) by an exec_queue + * (see example in &struct drm_xe_exec_queue_create). It can be synchronized + * by using the example provided for &struct drm_xe_sync. * * .. code-block:: C * @@ -1651,7 +1657,6 @@ struct drm_xe_exec { * * and the @flags can be: * - %DRM_XE_UFENCE_WAIT_FLAG_ABSTIME - * - %DRM_XE_UFENCE_WAIT_FLAG_SOFT_OP * * The @mask values can be for example: * - 0xffu for u8 @@ -1664,7 +1669,7 @@ struct drm_xe_wait_user_fence { __u64 extensions; /** - * @addr: user pointer address to wait on, must qword aligned + * @addr: user pointer address to wait on, must be qword aligned */ __u64 addr; @@ -1695,9 +1700,9 @@ struct drm_xe_wait_user_fence { * Without DRM_XE_UFENCE_WAIT_FLAG_ABSTIME flag set (relative timeout) * it contains timeout expressed in nanoseconds to wait (fence will * expire at now() + timeout). - * When DRM_XE_UFENCE_WAIT_FLAG_ABSTIME flat is set (absolute timeout) wait - * will end at timeout (uses system MONOTONIC_CLOCK). - * Passing negative timeout leads to neverending wait. + * When DRM_XE_UFENCE_WAIT_FLAG_ABSTIME flag is set (absolute timeout) wait + * will end at timeout (uses system CLOCK_MONOTONIC). + * Passing negative timeout leads to never ending wait. * * On relative timeout this value is updated with timeout left * (for restarting the call in case of signal delivery). @@ -1741,7 +1746,7 @@ enum drm_xe_observation_op { }; /** - * struct drm_xe_observation_param - Input of &DRM_XE_OBSERVATION + * struct drm_xe_observation_param - Input of &DRM_IOCTL_XE_OBSERVATION * * The observation layer enables multiplexing observation streams of * multiple types. The actual params for a particular stream operation are @@ -1751,25 +1756,25 @@ enum drm_xe_observation_op { struct drm_xe_observation_param { /** @extensions: Pointer to the first extension struct, if any */ __u64 extensions; - /** @observation_type: observation stream type, of enum @drm_xe_observation_type */ + /** @observation_type: observation stream type, of &enum drm_xe_observation_type */ __u64 observation_type; - /** @observation_op: observation stream op, of enum @drm_xe_observation_op */ + /** @observation_op: observation stream op, of &enum drm_xe_observation_op */ __u64 observation_op; /** @param: Pointer to actual stream params */ __u64 param; }; /** - * enum drm_xe_observation_ioctls - Observation stream fd ioctl's + * enum drm_xe_observation_ioctls - Observation stream fd ioctls * * Information exchanged between userspace and kernel for observation fd - * ioctl's is stream type specific + * ioctls is stream type specific */ enum drm_xe_observation_ioctls { /** @DRM_XE_OBSERVATION_IOCTL_ENABLE: Enable data capture for an observation stream */ DRM_XE_OBSERVATION_IOCTL_ENABLE = _IO('i', 0x0), - /** @DRM_XE_OBSERVATION_IOCTL_DISABLE: Disable data capture for a observation stream */ + /** @DRM_XE_OBSERVATION_IOCTL_DISABLE: Disable data capture for an observation stream */ DRM_XE_OBSERVATION_IOCTL_DISABLE = _IO('i', 0x1), /** @DRM_XE_OBSERVATION_IOCTL_CONFIG: Change observation stream configuration */ @@ -1812,7 +1817,7 @@ struct drm_xe_oa_unit { /** @oa_unit_id: OA unit ID */ __u32 oa_unit_id; - /** @oa_unit_type: OA unit type of @drm_xe_oa_unit_type */ + /** @oa_unit_type: OA unit type of &enum drm_xe_oa_unit_type */ __u32 oa_unit_type; /** @capabilities: OA capabilities bit-mask */ @@ -1875,7 +1880,7 @@ struct drm_xe_query_oa_units { /** @pad: MBZ */ __u32 pad; /** - * @oa_units: struct @drm_xe_oa_unit array returned for this device. + * @oa_units: &struct drm_xe_oa_unit array returned for this device. * Written below as a u64 array to avoid problems with nested flexible * arrays with some compilers */ @@ -1902,24 +1907,24 @@ enum drm_xe_oa_format_type { }; /** - * enum drm_xe_oa_property_id - OA stream property id's + * enum drm_xe_oa_property_id - OA stream property IDs * - * Stream params are specified as a chain of @drm_xe_ext_set_property - * struct's, with @property values from enum @drm_xe_oa_property_id and - * @drm_xe_user_extension base.name set to @DRM_XE_OA_EXTENSION_SET_PROPERTY. - * @param field in struct @drm_xe_observation_param points to the first - * @drm_xe_ext_set_property struct. + * Stream params are specified as a chain of &struct drm_xe_ext_set_property + * structs, with property values from &enum drm_xe_oa_property_id and + * &struct drm_xe_user_extension base.name set to %DRM_XE_OA_EXTENSION_SET_PROPERTY. + * The param field in &struct drm_xe_observation_param points to the first + * &struct drm_xe_ext_set_property struct. * * Exactly the same mechanism is also used for stream reconfiguration using the - * @DRM_XE_OBSERVATION_IOCTL_CONFIG observation stream fd ioctl, though only a + * %DRM_XE_OBSERVATION_IOCTL_CONFIG observation stream fd ioctl, though only a * subset of properties below can be specified for stream reconfiguration. */ enum drm_xe_oa_property_id { #define DRM_XE_OA_EXTENSION_SET_PROPERTY 0 /** * @DRM_XE_OA_PROPERTY_OA_UNIT_ID: ID of the OA unit on which to open - * the OA stream, see @oa_unit_id in 'struct - * drm_xe_query_oa_units'. Defaults to 0 if not provided. + * the OA stream, see oa_unit_id in &struct drm_xe_oa_unit. + * Defaults to 0 if not provided. */ DRM_XE_OA_PROPERTY_OA_UNIT_ID = 1, @@ -1932,7 +1937,7 @@ enum drm_xe_oa_property_id { /** * @DRM_XE_OA_PROPERTY_OA_METRIC_SET: OA metrics defining contents of OA - * reports, previously added via @DRM_XE_OBSERVATION_OP_ADD_CONFIG. + * reports, previously added via %DRM_XE_OBSERVATION_OP_ADD_CONFIG. */ DRM_XE_OA_PROPERTY_OA_METRIC_SET, @@ -1940,7 +1945,7 @@ enum drm_xe_oa_property_id { DRM_XE_OA_PROPERTY_OA_FORMAT, /* * OA_FORMAT's are specified the same way as in PRM/Bspec 52198/60942, - * in terms of the following quantities: a. enum @drm_xe_oa_format_type + * in terms of the following quantities: a. &enum drm_xe_oa_format_type * b. Counter select c. Counter size and d. BC report. Also refer to the * oa_formats array in drivers/gpu/drm/xe/xe_oa.c. */ @@ -1957,19 +1962,19 @@ enum drm_xe_oa_property_id { /** * @DRM_XE_OA_PROPERTY_OA_DISABLED: A value of 1 will open the OA - * stream in a DISABLED state (see @DRM_XE_OBSERVATION_IOCTL_ENABLE). + * stream in a DISABLED state (see %DRM_XE_OBSERVATION_IOCTL_ENABLE). */ DRM_XE_OA_PROPERTY_OA_DISABLED, /** * @DRM_XE_OA_PROPERTY_EXEC_QUEUE_ID: Open the stream for a specific - * @exec_queue_id. OA queries can be executed on this exec queue. + * exec_queue_id. OA queries can be executed on this exec queue. */ DRM_XE_OA_PROPERTY_EXEC_QUEUE_ID, /** * @DRM_XE_OA_PROPERTY_OA_ENGINE_INSTANCE: Optional engine instance to - * pass along with @DRM_XE_OA_PROPERTY_EXEC_QUEUE_ID or will default to 0. + * pass along with %DRM_XE_OA_PROPERTY_EXEC_QUEUE_ID or will default to 0. */ DRM_XE_OA_PROPERTY_OA_ENGINE_INSTANCE, @@ -1981,16 +1986,16 @@ enum drm_xe_oa_property_id { /** * @DRM_XE_OA_PROPERTY_NUM_SYNCS: Number of syncs in the sync array - * specified in @DRM_XE_OA_PROPERTY_SYNCS + * specified in %DRM_XE_OA_PROPERTY_SYNCS */ DRM_XE_OA_PROPERTY_NUM_SYNCS, /** - * @DRM_XE_OA_PROPERTY_SYNCS: Pointer to struct @drm_xe_sync array - * with array size specified via @DRM_XE_OA_PROPERTY_NUM_SYNCS. OA + * @DRM_XE_OA_PROPERTY_SYNCS: Pointer to &struct drm_xe_sync array + * with array size specified via %DRM_XE_OA_PROPERTY_NUM_SYNCS. OA * configuration will wait till input fences signal. Output fences * will signal after the new OA configuration takes effect. For - * @DRM_XE_SYNC_TYPE_USER_FENCE, @addr is a user pointer, similar + * %DRM_XE_SYNC_TYPE_USER_FENCE, addr is a user pointer, similar * to the VM bind case. */ DRM_XE_OA_PROPERTY_SYNCS, @@ -2013,15 +2018,15 @@ enum drm_xe_oa_property_id { /** * struct drm_xe_oa_config - OA metric configuration * - * Multiple OA configs can be added using @DRM_XE_OBSERVATION_OP_ADD_CONFIG. A + * Multiple OA configs can be added using %DRM_XE_OBSERVATION_OP_ADD_CONFIG. A * particular config can be specified when opening an OA stream using - * @DRM_XE_OA_PROPERTY_OA_METRIC_SET property. + * %DRM_XE_OA_PROPERTY_OA_METRIC_SET property. */ struct drm_xe_oa_config { /** @extensions: Pointer to the first extension struct, if any */ __u64 extensions; - /** @uuid: String formatted like "%\08x-%\04x-%\04x-%\04x-%\012x" */ + /** @uuid: String formatted like "%08x-%04x-%04x-%04x-%012x" */ char uuid[36]; /** @n_regs: Number of regs in @regs_ptr */ @@ -2036,7 +2041,7 @@ struct drm_xe_oa_config { /** * struct drm_xe_oa_stream_status - OA stream status returned from - * @DRM_XE_OBSERVATION_IOCTL_STATUS observation stream fd ioctl. Userspace can + * %DRM_XE_OBSERVATION_IOCTL_STATUS observation stream fd ioctl. Userspace can * call the ioctl to query stream status in response to EIO errno from * observation fd read(). */ @@ -2057,7 +2062,7 @@ struct drm_xe_oa_stream_status { /** * struct drm_xe_oa_stream_info - OA stream info returned from - * @DRM_XE_OBSERVATION_IOCTL_INFO observation stream fd ioctl + * %DRM_XE_OBSERVATION_IOCTL_INFO observation stream fd ioctl */ struct drm_xe_oa_stream_info { /** @extensions: Pointer to the first extension struct, if any */ @@ -2094,27 +2099,27 @@ enum drm_xe_pxp_session_type { * enum drm_xe_eu_stall_property_id - EU stall sampling input property ids. * * These properties are passed to the driver at open as a chain of - * @drm_xe_ext_set_property structures with @property set to these - * properties' enums and @value set to the corresponding values of these - * properties. @drm_xe_user_extension base.name should be set to - * @DRM_XE_EU_STALL_EXTENSION_SET_PROPERTY. + * &struct drm_xe_ext_set_property structures with property set to these + * properties' enums and value set to the corresponding values of these + * properties. &struct drm_xe_user_extension base.name should be set to + * %DRM_XE_EU_STALL_EXTENSION_SET_PROPERTY. * * With the file descriptor obtained from open, user space must enable - * the EU stall stream fd with @DRM_XE_OBSERVATION_IOCTL_ENABLE before + * the EU stall stream fd with %DRM_XE_OBSERVATION_IOCTL_ENABLE before * calling read(). EIO errno from read() indicates HW dropped data * due to full buffer. */ enum drm_xe_eu_stall_property_id { #define DRM_XE_EU_STALL_EXTENSION_SET_PROPERTY 0 /** - * @DRM_XE_EU_STALL_PROP_GT_ID: @gt_id of the GT on which + * @DRM_XE_EU_STALL_PROP_GT_ID: gt_id of the GT on which * EU stall data will be captured. */ DRM_XE_EU_STALL_PROP_GT_ID = 1, /** * @DRM_XE_EU_STALL_PROP_SAMPLE_RATE: Sampling rate in - * GPU cycles from @sampling_rates in struct @drm_xe_query_eu_stall + * GPU cycles from sampling_rates in &struct drm_xe_query_eu_stall */ DRM_XE_EU_STALL_PROP_SAMPLE_RATE, @@ -2129,9 +2134,9 @@ enum drm_xe_eu_stall_property_id { /** * struct drm_xe_query_eu_stall - Information about EU stall sampling. * - * If a query is made with a struct @drm_xe_device_query where .query - * is equal to @DRM_XE_DEVICE_QUERY_EU_STALL, then the reply uses - * struct @drm_xe_query_eu_stall in .data. + * If a query is made with a &struct drm_xe_device_query where .query + * is equal to %DRM_XE_DEVICE_QUERY_EU_STALL, then the reply uses + * &struct drm_xe_query_eu_stall in .data. */ struct drm_xe_query_eu_stall { /** @extensions: Pointer to the first extension struct, if any */ @@ -2183,7 +2188,7 @@ struct drm_xe_query_eu_stall { * .start = 0x100000, * .range = 0x2000, * .type = DRM_XE_MEM_RANGE_ATTR_ATOMIC, - * .atomic_val = DRM_XE_ATOMIC_DEVICE, + * .atomic.val = DRM_XE_ATOMIC_DEVICE, * }; * * ioctl(fd, DRM_IOCTL_XE_MADVISE, &madvise); @@ -2242,7 +2247,7 @@ struct drm_xe_madvise { /** * @preferred_mem_loc.region_instance : Region instance. - * MBZ if @devmem_fd <= &DRM_XE_PREFERRED_LOC_DEFAULT_DEVICE. + * MBZ if @devmem_fd <= %DRM_XE_PREFERRED_LOC_DEFAULT_DEVICE. * Otherwise should point to the desired device * VRAM instance of the device indicated by * @preferred_mem_loc.devmem_fd. @@ -2369,24 +2374,19 @@ struct drm_xe_madvise { }; /** - * struct drm_xe_mem_range_attr - Output of &DRM_IOCTL_XE_VM_QUERY_MEM_RANGES_ATTRS + * struct drm_xe_mem_range_attr - Output of &DRM_IOCTL_XE_VM_QUERY_MEM_RANGE_ATTRS * * This structure is provided by userspace and filled by KMD in response to the - * DRM_IOCTL_XE_VM_QUERY_MEM_RANGES_ATTRS ioctl. It describes memory attributes of - * a memory ranges within a user specified address range in a VM. + * DRM_IOCTL_XE_VM_QUERY_MEM_RANGE_ATTRS ioctl. It describes memory attributes of + * memory ranges within a user specified address range in a VM. * * The structure includes information such as atomic access policy, * page attribute table (PAT) index, and preferred memory location. * Userspace allocates an array of these structures and passes a pointer to the - * ioctl to retrieve attributes for each memory ranges - * - * @extensions: Pointer to the first extension struct, if any - * @start: Start address of the memory range - * @end: End address of the virtual memory range - * + * ioctl to retrieve attributes for each memory range. */ struct drm_xe_mem_range_attr { - /** @extensions: Pointer to the first extension struct, if any */ + /** @extensions: Pointer to the first extension struct, if any */ __u64 extensions; /** @start: start of the memory range */ @@ -2413,7 +2413,7 @@ struct drm_xe_mem_range_attr { __u32 reserved; } atomic; - /** @pat_index: Page attribute table index */ + /** @pat_index: Page attribute table index */ struct { /** @pat_index.val: PAT index */ __u32 val; @@ -2427,7 +2427,7 @@ struct drm_xe_mem_range_attr { }; /** - * struct drm_xe_vm_query_mem_range_attr - Input of &DRM_IOCTL_XE_VM_QUERY_MEM_ATTRIBUTES + * struct drm_xe_vm_query_mem_range_attr - Input of &DRM_IOCTL_XE_VM_QUERY_MEM_RANGE_ATTRS * * This structure is used to query memory attributes of memory regions * within a user specified address range in a VM. It provides detailed @@ -2435,15 +2435,15 @@ struct drm_xe_mem_range_attr { * page attribute table (PAT) index, and preferred memory location. * * Userspace first calls the ioctl with @num_mem_ranges = 0, - * @sizeof_mem_ranges_attr = 0 and @vector_of_vma_mem_attr = NULL to retrieve + * @sizeof_mem_range_attr = 0 and @vector_of_mem_attr = NULL to retrieve * the number of memory regions and size of each memory range attribute. * Then, it allocates a buffer of that size and calls the ioctl again to fill * the buffer with memory range attributes. * * If second call fails with -ENOSPC, it means memory ranges changed between * first call and now, retry IOCTL again with @num_mem_ranges = 0, - * @sizeof_mem_ranges_attr = 0 and @vector_of_vma_mem_attr = NULL followed by - * Second ioctl call. + * @sizeof_mem_range_attr = 0 and @vector_of_mem_attr = NULL followed by + * second ioctl call. * * Example: *