* [PATCH v3 1/2] mtd: mtd_intel_dg: add survivability partition
2026-09-30 14:14 [PATCH v3 0/2] drm/xe/nvm: add survivabilty partiton Alexander Usyskin
@ 2026-09-30 14:14 ` Alexander Usyskin
2026-09-30 14:14 ` [PATCH v3 2/2] drm/xe/nvm: define survivabilty partition Alexander Usyskin
1 sibling, 0 replies; 3+ messages in thread
From: Alexander Usyskin @ 2026-09-30 14:14 UTC (permalink / raw)
To: Miquel Raynal, Richard Weinberger, Vignesh Raghavendra,
Matthew Brost, Thomas Hellström, Rodrigo Vivi, David Airlie,
Simona Vetter
Cc: linux-mtd, linux-kernel, intel-xe, dri-devel, Menachem Adin,
Alexander Usyskin
Add option to expose additional fixed-sized partition starting
from the beginning of storage.
Xe driver can request this partition exposure if firmware or hardware
have detected failure that may involve corrupted partition table.
Fixed-sized partition allows full storage re-write in this situation.
Acked-by: Miquel Raynal <miquel.raynal@bootlin.com>
Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com>
---
drivers/mtd/devices/mtd_intel_dg.c | 65 ++++++++++++++++++++++++++++----------
include/linux/intel_dg_nvm_aux.h | 1 +
2 files changed, 50 insertions(+), 16 deletions(-)
diff --git a/drivers/mtd/devices/mtd_intel_dg.c b/drivers/mtd/devices/mtd_intel_dg.c
index a566e86eb5e3..976246e94e79 100644
--- a/drivers/mtd/devices/mtd_intel_dg.c
+++ b/drivers/mtd/devices/mtd_intel_dg.c
@@ -31,6 +31,7 @@ struct intel_dg_nvm {
void __iomem *base;
void __iomem *base2;
bool non_posted_erase;
+ bool survivability_enabled;
size_t size;
unsigned int nregions;
@@ -430,6 +431,15 @@ static int intel_dg_nvm_init(struct intel_dg_nvm *nvm, struct device *device,
/* clean error register, previous errors are ignored */
idg_nvm_error(nvm);
+ if (nvm->survivability_enabled) {
+ nvm->size = nvm->regions[0].offset + nvm->regions[0].size - 1;
+ dev_dbg(device, "Registered survivability region %s size=%lld\n",
+ nvm->regions[0].name,
+ nvm->regions[0].size);
+ n = 1;
+ goto out;
+ }
+
ret = idg_nvm_is_valid(nvm);
if (ret) {
dev_err(device, "The MEM is not valid %d\n", ret);
@@ -481,6 +491,7 @@ static int intel_dg_nvm_init(struct intel_dg_nvm *nvm, struct device *device,
n++;
}
+out:
nvm->non_posted_erase = non_posted_erase;
dev_dbg(device, "Registered %d regions\n", n);
@@ -753,15 +764,19 @@ static int intel_dg_mtd_probe(struct auxiliary_device *aux_dev,
device = &aux_dev->dev;
- /* count available regions */
- for (nregions = 0, i = 0; i < INTEL_DG_NVM_REGIONS; i++) {
- if (invm->regions[i].name)
- nregions++;
- }
+ if (invm->survivability_size) {
+ nregions = 1;
+ } else {
+ /* count available regions */
+ for (nregions = 0, i = 0; i < INTEL_DG_NVM_REGIONS; i++) {
+ if (invm->regions[i].name)
+ nregions++;
+ }
- if (!nregions) {
- dev_err(device, "no regions defined\n");
- return -ENODEV;
+ if (!nregions) {
+ dev_err(device, "no regions defined\n");
+ return -ENODEV;
+ }
}
nvm = kzalloc_flex(*nvm, regions, nregions);
@@ -771,21 +786,39 @@ static int intel_dg_mtd_probe(struct auxiliary_device *aux_dev,
kref_init(&nvm->refcnt);
mutex_init(&nvm->lock);
nvm->nregions = nregions;
+ nvm->survivability_enabled = !!invm->survivability_size;
- for (n = 0, i = 0; i < INTEL_DG_NVM_REGIONS; i++) {
- if (!invm->regions[i].name)
- continue;
-
+ if (invm->survivability_size) { /* survivability partition */
char *name = kasprintf(GFP_KERNEL, "%s.%s",
- dev_name(&aux_dev->dev), invm->regions[i].name);
+ dev_name(&aux_dev->dev), "DATA");
if (!name) {
ret = -ENOMEM;
goto err_norpm;
}
- nvm->regions[n].name = name;
- nvm->regions[n].id = i;
- n++;
+ nvm->regions[0].name = name;
+ nvm->regions[0].id = 0;
+ nvm->regions[0].offset = 0;
+ nvm->regions[0].size = invm->survivability_size;
+ nvm->regions[0].is_readable = true;
+ nvm->regions[0].is_writable = true;
+ n = 1;
+ } else {
+ for (n = 0, i = 0; i < INTEL_DG_NVM_REGIONS; i++) {
+ if (!invm->regions[i].name)
+ continue;
+
+ char *name = kasprintf(GFP_KERNEL, "%s.%s",
+ dev_name(&aux_dev->dev), invm->regions[i].name);
+ if (!name) {
+ ret = -ENOMEM;
+ goto err_norpm;
+ }
+
+ nvm->regions[n].name = name;
+ nvm->regions[n].id = i;
+ n++;
+ }
}
ret = devm_pm_runtime_enable(device);
diff --git a/include/linux/intel_dg_nvm_aux.h b/include/linux/intel_dg_nvm_aux.h
index 625d46a6b96e..84b5b6e0c4ea 100644
--- a/include/linux/intel_dg_nvm_aux.h
+++ b/include/linux/intel_dg_nvm_aux.h
@@ -21,6 +21,7 @@ struct intel_dg_nvm_dev {
struct auxiliary_device aux_dev;
bool writable_override;
bool non_posted_erase;
+ size_t survivability_size;
struct resource bar;
struct resource bar2;
const struct intel_dg_nvm_region *regions;
--
2.53.0
^ permalink raw reply [flat|nested] 3+ messages in thread* [PATCH v3 2/2] drm/xe/nvm: define survivabilty partition
2026-09-30 14:14 [PATCH v3 0/2] drm/xe/nvm: add survivabilty partiton Alexander Usyskin
2026-09-30 14:14 ` [PATCH v3 1/2] mtd: mtd_intel_dg: add survivability partition Alexander Usyskin
@ 2026-09-30 14:14 ` Alexander Usyskin
1 sibling, 0 replies; 3+ messages in thread
From: Alexander Usyskin @ 2026-09-30 14:14 UTC (permalink / raw)
To: Miquel Raynal, Richard Weinberger, Vignesh Raghavendra,
Matthew Brost, Thomas Hellström, Rodrigo Vivi, David Airlie,
Simona Vetter
Cc: linux-mtd, linux-kernel, intel-xe, dri-devel, Menachem Adin,
Alexander Usyskin
Define 8M survivability partition for CRI when
storage is open for write override.
Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com>
---
drivers/gpu/drm/xe/xe_nvm.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/xe/xe_nvm.c b/drivers/gpu/drm/xe/xe_nvm.c
index 51a1a431ad85..783c3103a8a4 100644
--- a/drivers/gpu/drm/xe/xe_nvm.c
+++ b/drivers/gpu/drm/xe/xe_nvm.c
@@ -56,10 +56,11 @@ static bool xe_nvm_non_posted_erase(struct xe_device *xe)
}
}
-static bool xe_nvm_writable_override(struct xe_device *xe)
+static bool xe_nvm_writable_override(struct xe_device *xe, size_t *survivability_size)
{
struct xe_mmio *mmio = xe_root_tile_mmio(xe);
bool writable_override;
+ size_t s_size = 0;
struct xe_reg reg;
u32 test_bit, test_val;
@@ -68,6 +69,7 @@ static bool xe_nvm_writable_override(struct xe_device *xe)
reg = PCODE_SCRATCH(0);
test_bit = FDO_MODE;
test_val = FDO_MODE;
+ s_size = SZ_8M;
break;
case XE_BATTLEMAGE:
reg = HECI_FWSTS2(DG2_GSC_HECI2_BASE);
@@ -91,12 +93,17 @@ static bool xe_nvm_writable_override(struct xe_device *xe)
break;
default:
drm_err(&xe->drm, "Unknown platform\n");
+ *survivability_size = 0;
return true;
}
writable_override = (xe_mmio_read32(mmio, reg) & test_bit) == test_val;
- if (writable_override)
+ if (writable_override) {
drm_info(&xe->drm, "NVM access overridden by jumper\n");
+ *survivability_size = s_size;
+ } else {
+ *survivability_size = 0;
+ }
return writable_override;
}
@@ -143,7 +150,7 @@ int xe_nvm_init(struct xe_device *xe)
if (!nvm)
return -ENOMEM;
- nvm->writable_override = xe_nvm_writable_override(xe);
+ nvm->writable_override = xe_nvm_writable_override(xe, &nvm->survivability_size);
nvm->non_posted_erase = xe_nvm_non_posted_erase(xe);
nvm->bar.parent = &pdev->resource[0];
nvm->bar.start = GEN12_GUNIT_NVM_BASE + pdev->resource[0].start;
--
2.53.0
^ permalink raw reply [flat|nested] 3+ messages in thread