[PATCH v4 05/12] PCI: endpoint: pci-epf-vntb: Guard configfs writes after EPC attach
From: Koichiro Den
Date: Tue May 12 2026 - 22:55:17 EST
db_count controls how many doorbell slots are allocated and exposed. It is
also used by the doorbell mask helpers. After an EPC has been attached,
changing it from configfs can leave runtime paths using a different count
than the one used to set up the doorbell resources.
Reject db_count writes after EPC attach, and reject values outside
MIN_DB_COUNT..MAX_DB_COUNT before attach. Now that MIN_DB_COUNT documents
the usable doorbell floor, use it in the store path too.
While at it, apply the same after-attach guard to the other vNTB configfs
knobs. BAR choices, spad_count, memory-window counts and sizes, and the
virtual PCI IDs are also consumed during bind, so changing them later at
runtime is meaningless and unsafe.
Return -EOPNOTSUPP for after-attach writes. The value itself may be valid,
but changing it in that state is not supported.
Signed-off-by: Koichiro Den <den@xxxxxxxxxxxxx>
---
Changes since v3:
- New patch.
drivers/pci/endpoint/functions/pci-epf-vntb.c | 41 ++++++++++++++++++-
1 file changed, 40 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/endpoint/functions/pci-epf-vntb.c b/drivers/pci/endpoint/functions/pci-epf-vntb.c
index 818ae5999976..524355a8b4be 100644
--- a/drivers/pci/endpoint/functions/pci-epf-vntb.c
+++ b/drivers/pci/endpoint/functions/pci-epf-vntb.c
@@ -1020,6 +1020,11 @@ static void epf_ntb_epc_cleanup(struct epf_ntb *ntb)
epf_ntb_config_sspad_bar_clear(ntb);
}
+static bool epf_ntb_epc_attached(struct epf_ntb *ntb)
+{
+ return ntb->epf->epc || ntb->epf->sec_epc;
+}
+
#define EPF_NTB_R(_name) \
static ssize_t epf_ntb_##_name##_show(struct config_item *item, \
char *page) \
@@ -1039,6 +1044,9 @@ static ssize_t epf_ntb_##_name##_store(struct config_item *item, \
u32 val; \
int ret; \
\
+ if (epf_ntb_epc_attached(ntb)) \
+ return -EOPNOTSUPP; \
+ \
ret = kstrtou32(page, 0, &val); \
if (ret) \
return ret; \
@@ -1081,6 +1089,9 @@ static ssize_t epf_ntb_##_name##_store(struct config_item *item, \
u64 val; \
int ret; \
\
+ if (epf_ntb_epc_attached(ntb)) \
+ return -EOPNOTSUPP; \
+ \
ret = kstrtou64(page, 0, &val); \
if (ret) \
return ret; \
@@ -1119,6 +1130,9 @@ static ssize_t epf_ntb_##_name##_store(struct config_item *item, \
int val; \
int ret; \
\
+ if (epf_ntb_epc_attached(ntb)) \
+ return -EOPNOTSUPP; \
+ \
ret = kstrtoint(page, 0, &val); \
if (ret) \
return ret; \
@@ -1139,6 +1153,9 @@ static ssize_t epf_ntb_num_mws_store(struct config_item *item,
u32 val;
int ret;
+ if (epf_ntb_epc_attached(ntb))
+ return -EOPNOTSUPP;
+
ret = kstrtou32(page, 0, &val);
if (ret)
return ret;
@@ -1151,10 +1168,32 @@ static ssize_t epf_ntb_num_mws_store(struct config_item *item,
return len;
}
+static ssize_t epf_ntb_db_count_store(struct config_item *item,
+ const char *page, size_t len)
+{
+ struct config_group *group = to_config_group(item);
+ struct epf_ntb *ntb = to_epf_ntb(group);
+ u32 val;
+ int ret;
+
+ if (epf_ntb_epc_attached(ntb))
+ return -EOPNOTSUPP;
+
+ ret = kstrtou32(page, 0, &val);
+ if (ret)
+ return ret;
+
+ if (val < MIN_DB_COUNT || val > MAX_DB_COUNT)
+ return -EINVAL;
+
+ WRITE_ONCE(ntb->db_count, val);
+
+ return len;
+}
+
EPF_NTB_R(spad_count)
EPF_NTB_W(spad_count)
EPF_NTB_R(db_count)
-EPF_NTB_W(db_count)
EPF_NTB_R(num_mws)
EPF_NTB_R(vbus_number)
EPF_NTB_W(vbus_number)
--
2.51.0