]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm/xe/xe_survivability: Add support for survivability mode v2
authorRiana Tauro <riana.tauro@intel.com>
Mon, 8 Dec 2025 08:45:42 +0000 (14:15 +0530)
committerRodrigo Vivi <rodrigo.vivi@intel.com>
Tue, 9 Dec 2025 22:19:43 +0000 (17:19 -0500)
v2 survivability breadcrumbs introduces a new mode called
SPI Flash Descriptor Override mode (FDO). This is enabled by
PCODE when MEI itself fails and firmware cannot be updated via
MEI using igsc. This mode provides the ability to update
the firmware directly via SPI driver.

Xe KMD initializes the nvm aux driver if FDO mode is enabled.

Userspace should check FDO mode entry in survivability info sysfs before
using the SPI driver to update firmware.

/sys/bus/pci/devices/<device>/survivability_info/fdo_mode

v2 also supports survivability mode for critical boot errors.

Signed-off-by: Riana Tauro <riana.tauro@intel.com>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Link: https://patch.msgid.link/20251208084539.3652902-6-riana.tauro@intel.com
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
drivers/gpu/drm/xe/xe_pcode_api.h
drivers/gpu/drm/xe/xe_survivability_mode.c
drivers/gpu/drm/xe/xe_survivability_mode_types.h

index 70dcd6625680c76a494879d162793d0c77f6387b..975892d6b23045ddb001b81777df1bbbdac4e966 100644 (file)
 
 #define PCODE_SCRATCH(x)               XE_REG(0x138320 + ((x) * 4))
 /* PCODE_SCRATCH0 */
+#define   BREADCRUMB_VERSION           REG_GENMASK(31, 29)
 #define   AUXINFO_REG_OFFSET           REG_GENMASK(17, 15)
 #define   OVERFLOW_REG_OFFSET          REG_GENMASK(14, 12)
 #define   HISTORY_TRACKING             REG_BIT(11)
 #define   OVERFLOW_SUPPORT             REG_BIT(10)
 #define   AUXINFO_SUPPORT              REG_BIT(9)
+#define   FDO_MODE                     REG_BIT(4)
 #define   BOOT_STATUS                  REG_GENMASK(3, 1)
 #define      CRITICAL_FAILURE          4
 #define      NON_CRITICAL_FAILURE      7
index b6ff5da86a4dff5982719320a8777a307904d25a..7520d7b7f9b8f9ae93c641e38d01be0a02451b19 100644 (file)
@@ -16,6 +16,7 @@
 #include "xe_heci_gsc.h"
 #include "xe_i2c.h"
 #include "xe_mmio.h"
+#include "xe_nvm.h"
 #include "xe_pcode_api.h"
 #include "xe_vsec.h"
 
  *
  * - ``aux_info<n>`` : Some failures have additional debug information
  *
+ * - ``fdo_mode`` : To allow recovery in scenarios where MEI itself fails, a new SPI Flash
+ *   Descriptor Override (FDO) mode is added in v2 survivability breadcrumbs. This mode is enabled
+ *   by PCODE and provides the ability to directly update the firmware via SPI Driver without
+ *   any dependency on MEI. Xe KMD initializes the nvm aux driver if FDO mode is enabled.
+ *
  * Runtime Survivability
  * =====================
  *
@@ -109,6 +115,8 @@ static const char * const reg_map[] = {
        [AUX_INFO4]               = "Auxiliary Info 4",
 };
 
+#define FDO_INFO       (MAX_SCRATCH_REG + 1)
+
 struct xe_survivability_attribute {
        struct device_attribute attr;
        u8 index;
@@ -142,6 +150,11 @@ static void populate_survivability_info(struct xe_device *xe)
        set_survivability_info(mmio, info, CAPABILITY_INFO);
        reg_value = info[CAPABILITY_INFO];
 
+       survivability->version = REG_FIELD_GET(BREADCRUMB_VERSION, reg_value);
+       /* FDO mode is exposed only from version 2 */
+       if (survivability->version >= 2)
+               survivability->fdo_mode = REG_FIELD_GET(FDO_MODE, reg_value);
+
        if (reg_value & HISTORY_TRACKING) {
                set_survivability_info(mmio, info, POSTCODE_TRACE);
 
@@ -203,6 +216,9 @@ static ssize_t survivability_info_show(struct device *dev,
        struct xe_survivability *survivability = &xe->survivability;
        u32 *info = survivability->info;
 
+       if (sa->index == FDO_INFO)
+               return sysfs_emit(buff, "%s\n", str_enabled_disabled(survivability->fdo_mode));
+
        return sysfs_emit(buff, "0x%x\n", info[sa->index]);
 }
 
@@ -220,13 +236,18 @@ SURVIVABILITY_ATTR_RO(aux_info1, AUX_INFO1);
 SURVIVABILITY_ATTR_RO(aux_info2, AUX_INFO2);
 SURVIVABILITY_ATTR_RO(aux_info3, AUX_INFO3);
 SURVIVABILITY_ATTR_RO(aux_info4, AUX_INFO4);
+SURVIVABILITY_ATTR_RO(fdo_mode, FDO_INFO);
 
 static void xe_survivability_mode_fini(void *arg)
 {
        struct xe_device *xe = arg;
+       struct xe_survivability *survivability = &xe->survivability;
        struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
        struct device *dev = &pdev->dev;
 
+       if (survivability->fdo_mode)
+               xe_nvm_fini(xe);
+
        device_remove_file(dev, &dev_attr_survivability_mode);
 }
 
@@ -237,7 +258,10 @@ static umode_t survivability_info_attrs_visible(struct kobject *kobj, struct att
        struct xe_survivability *survivability = &xe->survivability;
        u32 *info = survivability->info;
 
-       if (info[idx])
+       /* FDO mode is visible only when supported */
+       if (idx >= MAX_SCRATCH_REG && survivability->version >= 2)
+               return 0400;
+       else if (info[idx])
                return 0400;
 
        return 0;
@@ -253,6 +277,7 @@ static struct attribute *survivability_info_attrs[] = {
        &attr_aux_info2.attr.attr,
        &attr_aux_info3.attr.attr,
        &attr_aux_info4.attr.attr,
+       &attr_fdo_mode.attr.attr,
        NULL,
 };
 
@@ -302,12 +327,16 @@ static int enable_boot_survivability_mode(struct pci_dev *pdev)
        /* Make sure xe_heci_gsc_init() knows about survivability mode */
        survivability->mode = true;
 
-       ret = xe_heci_gsc_init(xe);
-       if (ret)
-               goto err;
+       xe_heci_gsc_init(xe);
 
        xe_vsec_init(xe);
 
+       if (survivability->fdo_mode) {
+               ret = xe_nvm_init(xe);
+               if (ret)
+                       goto err;
+       }
+
        ret = xe_i2c_probe(xe);
        if (ret)
                goto err;
@@ -317,6 +346,7 @@ static int enable_boot_survivability_mode(struct pci_dev *pdev)
        return 0;
 
 err:
+       dev_err(dev, "Failed to enable Survivability Mode\n");
        survivability->mode = false;
        return ret;
 }
@@ -423,8 +453,10 @@ int xe_survivability_mode_boot_enable(struct xe_device *xe)
 
        populate_survivability_info(xe);
 
-       /* Log breadcrumbs but do not enter survivability mode for Critical boot errors */
-       if (survivability->boot_status == CRITICAL_FAILURE) {
+       /*
+        * v2 supports survivability mode for critical errors
+        */
+       if (survivability->version < 2  && survivability->boot_status == CRITICAL_FAILURE) {
                log_survivability_info(pdev);
                return -ENXIO;
        }
index f31b3907d933102ebe24db0bd6abc8071f187e09..bd5dc1c955ffccd5382ba351ad9f6c1d725f635c 100644 (file)
@@ -44,6 +44,12 @@ struct xe_survivability {
 
        /** @type: survivability type */
        enum xe_survivability_type type;
+
+       /** @fdo_mode: indicates if FDO mode is enabled */
+       bool fdo_mode;
+
+       /** @version: breadcrumb version of survivability mode  */
+       u8 version;
 };
 
 #endif /* _XE_SURVIVABILITY_MODE_TYPES_H_ */