drm/xe/nvm: add support for non-posted erase
Erase command is slow on discrete graphics storage and may overshot PCI completion timeout. BMG introduces the ability to have non-posted erase. Add driver support for non-posted erase with polling for erase completion. Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Acked-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: Reuven Abliyev <reuven.abliyev@intel.com> Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com> Link: https://lore.kernel.org/r/20250617145159.3803852-9-alexander.usyskin@intel.com Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
This commit is contained in:
committed by
Rodrigo Vivi
parent
87e1ebbafb
commit
a1c940cbf5
@@ -14,7 +14,15 @@
|
||||
#include "xe_sriov.h"
|
||||
|
||||
#define GEN12_GUNIT_NVM_BASE 0x00102040
|
||||
#define GEN12_DEBUG_NVM_BASE 0x00101018
|
||||
|
||||
#define GEN12_CNTL_PROTECTED_NVM_REG 0x0010100C
|
||||
|
||||
#define GEN12_GUNIT_NVM_SIZE 0x80
|
||||
#define GEN12_DEBUG_NVM_SIZE 0x4
|
||||
|
||||
#define NVM_NON_POSTED_ERASE_CHICKEN_BIT BIT(13)
|
||||
|
||||
#define HECI_FW_STATUS_2_NVM_ACCESS_MODE BIT(3)
|
||||
|
||||
static const struct intel_dg_nvm_region regions[INTEL_DG_NVM_REGIONS] = {
|
||||
@@ -29,6 +37,16 @@ static void xe_nvm_release_dev(struct device *dev)
|
||||
{
|
||||
}
|
||||
|
||||
static bool xe_nvm_non_posted_erase(struct xe_device *xe)
|
||||
{
|
||||
struct xe_gt *gt = xe_root_mmio_gt(xe);
|
||||
|
||||
if (xe->info.platform != XE_BATTLEMAGE)
|
||||
return false;
|
||||
return !(xe_mmio_read32(>->mmio, XE_REG(GEN12_CNTL_PROTECTED_NVM_REG)) &
|
||||
NVM_NON_POSTED_ERASE_CHICKEN_BIT);
|
||||
}
|
||||
|
||||
static bool xe_nvm_writable_override(struct xe_device *xe)
|
||||
{
|
||||
struct xe_gt *gt = xe_root_mmio_gt(xe);
|
||||
@@ -86,6 +104,7 @@ int xe_nvm_init(struct xe_device *xe)
|
||||
nvm = xe->nvm;
|
||||
|
||||
nvm->writable_override = xe_nvm_writable_override(xe);
|
||||
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;
|
||||
nvm->bar.end = nvm->bar.start + GEN12_GUNIT_NVM_SIZE - 1;
|
||||
@@ -93,6 +112,12 @@ int xe_nvm_init(struct xe_device *xe)
|
||||
nvm->bar.desc = IORES_DESC_NONE;
|
||||
nvm->regions = regions;
|
||||
|
||||
nvm->bar2.parent = &pdev->resource[0];
|
||||
nvm->bar2.start = GEN12_DEBUG_NVM_BASE + pdev->resource[0].start;
|
||||
nvm->bar2.end = nvm->bar2.start + GEN12_DEBUG_NVM_SIZE - 1;
|
||||
nvm->bar2.flags = IORESOURCE_MEM;
|
||||
nvm->bar2.desc = IORES_DESC_NONE;
|
||||
|
||||
aux_dev = &nvm->aux_dev;
|
||||
|
||||
aux_dev->name = "nvm";
|
||||
|
||||
@@ -25,6 +25,9 @@ struct intel_dg_nvm {
|
||||
struct mtd_info mtd;
|
||||
struct mutex lock; /* region access lock */
|
||||
void __iomem *base;
|
||||
void __iomem *base2;
|
||||
bool non_posted_erase;
|
||||
|
||||
size_t size;
|
||||
unsigned int nregions;
|
||||
struct {
|
||||
@@ -41,6 +44,7 @@ struct intel_dg_nvm {
|
||||
#define NVM_VALSIG_REG 0x00000010
|
||||
#define NVM_ADDRESS_REG 0x00000040
|
||||
#define NVM_REGION_ID_REG 0x00000044
|
||||
#define NVM_DEBUG_REG 0x00000000
|
||||
/*
|
||||
* [15:0]-Erase size = 0x0010 4K 0x0080 32K 0x0100 64K
|
||||
* [23:16]-Reserved
|
||||
@@ -72,6 +76,9 @@ struct intel_dg_nvm {
|
||||
#define NVM_FREG_ADDR_SHIFT 12
|
||||
#define NVM_FREG_MIN_REGION_SIZE 0xFFF
|
||||
|
||||
#define NVM_NON_POSTED_ERASE_DONE BIT(23)
|
||||
#define NVM_NON_POSTED_ERASE_DONE_ITER 3000
|
||||
|
||||
static inline void idg_nvm_set_region_id(struct intel_dg_nvm *nvm, u8 region)
|
||||
{
|
||||
iowrite32((u32)region, nvm->base + NVM_REGION_ID_REG);
|
||||
@@ -373,13 +380,32 @@ static ssize_t idg_read(struct intel_dg_nvm *nvm, u8 region,
|
||||
static ssize_t
|
||||
idg_erase(struct intel_dg_nvm *nvm, u8 region, loff_t from, u64 len, u64 *fail_addr)
|
||||
{
|
||||
void __iomem *base2 = nvm->base2;
|
||||
void __iomem *base = nvm->base;
|
||||
const u32 block = 0x10;
|
||||
u32 iter = 0;
|
||||
u32 reg;
|
||||
u64 i;
|
||||
|
||||
for (i = 0; i < len; i += SZ_4K) {
|
||||
iowrite32(from + i, base + NVM_ADDRESS_REG);
|
||||
iowrite32(region << 24 | block, base + NVM_ERASE_REG);
|
||||
if (nvm->non_posted_erase) {
|
||||
/* Wait for Erase Done */
|
||||
reg = ioread32(base2 + NVM_DEBUG_REG);
|
||||
while (!(reg & NVM_NON_POSTED_ERASE_DONE) &&
|
||||
++iter < NVM_NON_POSTED_ERASE_DONE_ITER) {
|
||||
msleep(10);
|
||||
reg = ioread32(base2 + NVM_DEBUG_REG);
|
||||
}
|
||||
if (reg & NVM_NON_POSTED_ERASE_DONE) {
|
||||
/* Clear Erase Done */
|
||||
iowrite32(reg, base2 + NVM_DEBUG_REG);
|
||||
} else {
|
||||
*fail_addr = from + i;
|
||||
return -ETIME;
|
||||
}
|
||||
}
|
||||
/* Since the writes are via sgunit
|
||||
* we cannot do back to back erases.
|
||||
*/
|
||||
@@ -388,7 +414,8 @@ idg_erase(struct intel_dg_nvm *nvm, u8 region, loff_t from, u64 len, u64 *fail_a
|
||||
return len;
|
||||
}
|
||||
|
||||
static int intel_dg_nvm_init(struct intel_dg_nvm *nvm, struct device *device)
|
||||
static int intel_dg_nvm_init(struct intel_dg_nvm *nvm, struct device *device,
|
||||
bool non_posted_erase)
|
||||
{
|
||||
u32 access_map = 0;
|
||||
unsigned int i, n;
|
||||
@@ -448,7 +475,10 @@ static int intel_dg_nvm_init(struct intel_dg_nvm *nvm, struct device *device)
|
||||
n++;
|
||||
}
|
||||
|
||||
nvm->non_posted_erase = non_posted_erase;
|
||||
|
||||
dev_dbg(device, "Registered %d regions\n", n);
|
||||
dev_dbg(device, "Non posted erase %d\n", nvm->non_posted_erase);
|
||||
|
||||
/* Need to add 1 to the amount of memory
|
||||
* so it is reported as an even block
|
||||
@@ -729,7 +759,15 @@ static int intel_dg_mtd_probe(struct auxiliary_device *aux_dev,
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = intel_dg_nvm_init(nvm, device);
|
||||
if (invm->non_posted_erase) {
|
||||
nvm->base2 = devm_ioremap_resource(device, &invm->bar2);
|
||||
if (IS_ERR(nvm->base2)) {
|
||||
ret = PTR_ERR(nvm->base2);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
ret = intel_dg_nvm_init(nvm, device, invm->non_posted_erase);
|
||||
if (ret < 0) {
|
||||
dev_err(device, "cannot initialize nvm %d\n", ret);
|
||||
goto err;
|
||||
|
||||
@@ -20,7 +20,9 @@ struct intel_dg_nvm_region {
|
||||
struct intel_dg_nvm_dev {
|
||||
struct auxiliary_device aux_dev;
|
||||
bool writable_override;
|
||||
bool non_posted_erase;
|
||||
struct resource bar;
|
||||
struct resource bar2;
|
||||
const struct intel_dg_nvm_region *regions;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user