All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v1 0/3] add Intel FPGA image loader support
@ 2022-07-05  8:00 Tianfei Zhang
  2022-07-05  8:00 ` [PATCH v1 1/3] mfd: intel-m10-bmc: add m10bmc_sys_update_bits API Tianfei Zhang
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Tianfei Zhang @ 2022-07-05  8:00 UTC (permalink / raw)
  To: mdf, yilun.xu, lee.jones, russell.h.weight
  Cc: hao.wu, trix, linux-fpga, Tianfei Zhang

This patchset adds FPGA image loader support on Intel PAC N3000 Card.
Image loader means that a reload mechanism of an FPGA, BMC, or
firmware image from FLASH or EEPROM after flash or program the images
without power cycle the server.

This patchset introduces 2 new sysfs files for query the available
images and trigger a image reload.

patch 1: add register access helper functions for M10BMC.
patch 2: add the available_images and image_load sysfs files.
Write a key word into image_load sysfs file to trigger a reload of an
FPGA, BMC, or firmware image from FLASH or EEPROM.
patch 3: add a trigger to update a new Retimer firmware.

Russ Weight (2):
  fpga: m10bmc-sec: add sysfs to load bmc images
  fpga: m10bmc-sec: add m10bmc_sec_retimer_load callback

Tianfei Zhang (1):
  mfd: intel-m10-bmc: add m10bmc_sys_update_bits API

 .../sysfs-driver-intel-m10-bmc-sec-update     |  21 ++
 drivers/fpga/intel-m10-bmc-sec-update.c       | 250 ++++++++++++++++++
 include/linux/mfd/intel-m10-bmc.h             |  49 ++++
 3 files changed, 320 insertions(+)

-- 
2.26.2


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v1 1/3] mfd: intel-m10-bmc: add m10bmc_sys_update_bits API
  2022-07-05  8:00 [PATCH v1 0/3] add Intel FPGA image loader support Tianfei Zhang
@ 2022-07-05  8:00 ` Tianfei Zhang
  2022-07-05  8:00 ` [PATCH v1 2/3] fpga: m10bmc-sec: add sysfs to load bmc images Tianfei Zhang
  2022-07-05  8:00 ` [PATCH v1 3/3] fpga: m10bmc-sec: add m10bmc_sec_retimer_load callback Tianfei Zhang
  2 siblings, 0 replies; 9+ messages in thread
From: Tianfei Zhang @ 2022-07-05  8:00 UTC (permalink / raw)
  To: mdf, yilun.xu, lee.jones, russell.h.weight
  Cc: hao.wu, trix, linux-fpga, Tianfei Zhang

Adds register access helper functions for M10BMC.
m10bmc_raw_update_bits() uses to update m10bmc register
bits per addr.
m10bmc_sys_update_bits() uses to update m10bmc system
register bits per offset.

Signed-off-by: Tianfei Zhang <tianfei.zhang@intel.com>
---
 include/linux/mfd/intel-m10-bmc.h | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/include/linux/mfd/intel-m10-bmc.h b/include/linux/mfd/intel-m10-bmc.h
index f0044b14136e..8e434886a5a1 100644
--- a/include/linux/mfd/intel-m10-bmc.h
+++ b/include/linux/mfd/intel-m10-bmc.h
@@ -133,6 +133,8 @@ struct intel_m10bmc {
  *
  * m10bmc_raw_read - read m10bmc register per addr
  * m10bmc_sys_read - read m10bmc system register per offset
+ * m10bmc_raw_update_bits - update m10bmc register bits per addr
+ * m10bmc_sys_update_bits - update m10bmc system register bits per offset
  */
 static inline int
 m10bmc_raw_read(struct intel_m10bmc *m10bmc, unsigned int addr,
@@ -148,6 +150,20 @@ m10bmc_raw_read(struct intel_m10bmc *m10bmc, unsigned int addr,
 	return ret;
 }
 
+static inline int
+m10bmc_raw_update_bits(struct intel_m10bmc *m10bmc, unsigned int addr,
+		       unsigned int msk, unsigned int val)
+{
+	int ret;
+
+	ret = regmap_update_bits(m10bmc->regmap, addr, msk, val);
+	if (ret)
+		dev_err(m10bmc->dev, "fail to update reg bits %x: %d\n",
+			addr, ret);
+
+	return ret;
+}
+
 /*
  * The base of the system registers could be configured by HW developers, and
  * in HW SPEC, the base is not added to the addresses of the system registers.
@@ -158,5 +174,7 @@ m10bmc_raw_read(struct intel_m10bmc *m10bmc, unsigned int addr,
  */
 #define m10bmc_sys_read(m10bmc, offset, val) \
 	m10bmc_raw_read(m10bmc, M10BMC_SYS_BASE + (offset), val)
+#define m10bmc_sys_update_bits(m10bmc, offset, msk, val) \
+	m10bmc_raw_update_bits(m10bmc, M10BMC_SYS_BASE + (offset), msk, val)
 
 #endif /* __MFD_INTEL_M10_BMC_H */
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v1 2/3] fpga: m10bmc-sec: add sysfs to load bmc images
  2022-07-05  8:00 [PATCH v1 0/3] add Intel FPGA image loader support Tianfei Zhang
  2022-07-05  8:00 ` [PATCH v1 1/3] mfd: intel-m10-bmc: add m10bmc_sys_update_bits API Tianfei Zhang
@ 2022-07-05  8:00 ` Tianfei Zhang
  2022-07-07  2:00   ` Xu Yilun
  2022-07-05  8:00 ` [PATCH v1 3/3] fpga: m10bmc-sec: add m10bmc_sec_retimer_load callback Tianfei Zhang
  2 siblings, 1 reply; 9+ messages in thread
From: Tianfei Zhang @ 2022-07-05  8:00 UTC (permalink / raw)
  To: mdf, yilun.xu, lee.jones, russell.h.weight
  Cc: hao.wu, trix, linux-fpga, Tianfei Zhang

From: Russ Weight <russell.h.weight@intel.com>

Add the available_images and image_load sysfs files. The available_images
file returns a space separated list of key words that may be written
into the image_load file. These keywords describe an FPGA, BMC, or
firmware image in FLASH or EEPROM storage that may be loaded.

The image_load sysfs file may be written with a key word to trigger a
reload of an FPGA, BMC, or firmware image from FLASH or EEPROM.

Signed-off-by: Russ Weight <russell.h.weight@intel.com>
Signed-off-by: Tianfei Zhang <tianfei.zhang@intel.com>
---
 .../sysfs-driver-intel-m10-bmc-sec-update     |  21 ++++
 drivers/fpga/intel-m10-bmc-sec-update.c       | 104 ++++++++++++++++++
 2 files changed, 125 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-sec-update b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-sec-update
index 0a41afe0ab4c..8ded1a59d4db 100644
--- a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-sec-update
+++ b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-sec-update
@@ -59,3 +59,24 @@ Contact:	Russ Weight <russell.h.weight@intel.com>
 Description:	Read only. Returns number of times the secure update
 		staging area has been flashed.
 		Format: "%u".
+
+What:		/sys/bus/platform/drivers/intel-m10bmc-sec-update/.../control/available_images
+Date:		July 2022
+KernelVersion:  5.20
+Contact:	Russ Weight <russell.h.weight@intel.com>
+Description:	Read-only. This file returns a space separated list of
+		key words that may be written into the image_load file
+		described below. These keywords decribe an FPGA, BMC,
+		or firmware image in FLASH or EEPROM storage that may
+		be loaded.
+
+What:		/sys/bus/platform/drivers/intel-m10bmc-sec-update/.../control/image_load
+Date:		July 2022
+KernelVersion:  5.20
+Contact:	Russ Weight <russell.h.weight@intel.com>
+Description:	Write-only. A key word may be written to this file to
+		trigger a reload of an FPGA, BMC, or firmware image from
+		FLASH or EEPROM. Refer to the available_images file for a
+		list of supported key words for the underlying device.
+		Writing an unsupported string to this file will result in
+		EINVAL being returned.
diff --git a/drivers/fpga/intel-m10-bmc-sec-update.c b/drivers/fpga/intel-m10-bmc-sec-update.c
index 72c677c910de..640690e6c131 100644
--- a/drivers/fpga/intel-m10-bmc-sec-update.c
+++ b/drivers/fpga/intel-m10-bmc-sec-update.c
@@ -14,6 +14,8 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 
+struct image_load;
+
 struct m10bmc_sec {
 	struct device *dev;
 	struct intel_m10bmc *m10bmc;
@@ -21,6 +23,12 @@ struct m10bmc_sec {
 	char *fw_name;
 	u32 fw_name_id;
 	bool cancel_request;
+	struct image_load *image_load;	/* terminated with { } member */
+};
+
+struct image_load {
+	const char *name;
+	int (*load_image)(struct m10bmc_sec *sec);
 };
 
 static DEFINE_XARRAY_ALLOC(fw_upload_xa);
@@ -137,6 +145,54 @@ DEVICE_ATTR_SEC_CSK_RO(pr, PR_PROG_ADDR + CSK_VEC_OFFSET);
 
 #define FLASH_COUNT_SIZE 4096	/* count stored as inverted bit vector */
 
+static ssize_t available_images_show(struct device *dev,
+				     struct device_attribute *attr, char *buf)
+{
+	struct m10bmc_sec *sec = dev_get_drvdata(dev);
+	const struct image_load *hndlr;
+	ssize_t count = 0;
+
+	for (hndlr = sec->image_load; hndlr->name; hndlr++) {
+		count += scnprintf(buf + count, PAGE_SIZE - count,
+				   "%s ", hndlr->name);
+	}
+
+	buf[count - 1] = '\n';
+
+	return count;
+}
+static DEVICE_ATTR_RO(available_images);
+
+static ssize_t image_load_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct m10bmc_sec *sec = dev_get_drvdata(dev);
+	const struct image_load *hndlr;
+	int ret = -EINVAL;
+
+	for (hndlr = sec->image_load; hndlr->name; hndlr++) {
+		if (sysfs_streq(buf, hndlr->name)) {
+			ret = hndlr->load_image(sec);
+			break;
+		}
+	}
+
+	return ret ? : count;
+}
+static DEVICE_ATTR_WO(image_load);
+
+static struct attribute *m10bmc_control_attrs[] = {
+	&dev_attr_available_images.attr,
+	&dev_attr_image_load.attr,
+	NULL,
+};
+
+static struct attribute_group m10bmc_control_attr_group = {
+	.name = "control",
+	.attrs = m10bmc_control_attrs,
+};
+
 static ssize_t flash_count_show(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
@@ -195,6 +251,7 @@ static struct attribute_group m10bmc_security_attr_group = {
 
 static const struct attribute_group *m10bmc_sec_attr_groups[] = {
 	&m10bmc_security_attr_group,
+	&m10bmc_control_attr_group,
 	NULL,
 };
 
@@ -208,6 +265,52 @@ static void log_error_regs(struct m10bmc_sec *sec, u32 doorbell)
 		dev_err(sec->dev, "RSU auth result: 0x%08x\n", auth_result);
 }
 
+static int m10bmc_sec_bmc_image_load(struct m10bmc_sec *sec,
+				     unsigned int val)
+{
+	u32 doorbell;
+	int ret;
+
+	if (val > 1) {
+		dev_err(sec->dev, "invalid reload val = %d\n", val);
+		return -EINVAL;
+	}
+
+	ret = m10bmc_sys_read(sec->m10bmc, M10BMC_DOORBELL, &doorbell);
+	if (ret)
+		return ret;
+
+	if (doorbell & DRBL_REBOOT_DISABLED)
+		return -EBUSY;
+
+	return m10bmc_sys_update_bits(sec->m10bmc, M10BMC_DOORBELL,
+				      DRBL_CONFIG_SEL | DRBL_REBOOT_REQ,
+				      FIELD_PREP(DRBL_CONFIG_SEL, val) |
+				      DRBL_REBOOT_REQ);
+}
+
+static int m10bmc_sec_bmc_image_load_0(struct m10bmc_sec *sec)
+{
+	return m10bmc_sec_bmc_image_load(sec, 0);
+}
+
+static int m10bmc_sec_bmc_image_load_1(struct m10bmc_sec *sec)
+{
+	return m10bmc_sec_bmc_image_load(sec, 1);
+}
+
+static struct image_load m10bmc_image_load_hndlrs[] = {
+	{
+		.name = "bmc_factory",
+		.load_image = m10bmc_sec_bmc_image_load_1,
+	},
+	{
+		.name = "bmc_user",
+		.load_image = m10bmc_sec_bmc_image_load_0,
+	},
+	{}
+};
+
 static enum fw_upload_err rsu_check_idle(struct m10bmc_sec *sec)
 {
 	u32 doorbell;
@@ -565,6 +668,7 @@ static int m10bmc_sec_probe(struct platform_device *pdev)
 	sec->dev = &pdev->dev;
 	sec->m10bmc = dev_get_drvdata(pdev->dev.parent);
 	dev_set_drvdata(&pdev->dev, sec);
+	sec->image_load = m10bmc_image_load_hndlrs;
 
 	ret = xa_alloc(&fw_upload_xa, &sec->fw_name_id, sec,
 		       xa_limit_32b, GFP_KERNEL);
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v1 3/3] fpga: m10bmc-sec: add m10bmc_sec_retimer_load callback
  2022-07-05  8:00 [PATCH v1 0/3] add Intel FPGA image loader support Tianfei Zhang
  2022-07-05  8:00 ` [PATCH v1 1/3] mfd: intel-m10-bmc: add m10bmc_sys_update_bits API Tianfei Zhang
  2022-07-05  8:00 ` [PATCH v1 2/3] fpga: m10bmc-sec: add sysfs to load bmc images Tianfei Zhang
@ 2022-07-05  8:00 ` Tianfei Zhang
  2022-07-07  2:05   ` Xu Yilun
  2 siblings, 1 reply; 9+ messages in thread
From: Tianfei Zhang @ 2022-07-05  8:00 UTC (permalink / raw)
  To: mdf, yilun.xu, lee.jones, russell.h.weight
  Cc: hao.wu, trix, linux-fpga, Tianfei Zhang

From: Russ Weight <russell.h.weight@intel.com>

Create m10bmc_sec_retimer_load() callback function
to provide a trigger to update a new retimer (Intel
C827 Ethernet transceiver) firmware on Intel PAC
N3000 Card.

Signed-off-by: Russ Weight <russell.h.weight@intel.com>
Signed-off-by: Tianfei Zhang <tianfei.zhang@intel.com>
---
 drivers/fpga/intel-m10-bmc-sec-update.c | 146 ++++++++++++++++++++++++
 include/linux/mfd/intel-m10-bmc.h       |  31 +++++
 2 files changed, 177 insertions(+)

diff --git a/drivers/fpga/intel-m10-bmc-sec-update.c b/drivers/fpga/intel-m10-bmc-sec-update.c
index 640690e6c131..707dfd8a1931 100644
--- a/drivers/fpga/intel-m10-bmc-sec-update.c
+++ b/drivers/fpga/intel-m10-bmc-sec-update.c
@@ -299,6 +299,148 @@ static int m10bmc_sec_bmc_image_load_1(struct m10bmc_sec *sec)
 	return m10bmc_sec_bmc_image_load(sec, 1);
 }
 
+static int trigger_retimer_eeprom_load(struct m10bmc_sec *sec)
+{
+	struct intel_m10bmc *m10bmc = sec->m10bmc;
+	unsigned int val;
+	int ret;
+
+	ret = m10bmc_sys_update_bits(m10bmc, M10BMC_DOORBELL,
+				     DRBL_PKVL_EEPROM_LOAD_SEC,
+				     DRBL_PKVL_EEPROM_LOAD_SEC);
+	if (ret)
+		return ret;
+
+	/*
+	 * If the current NIOS FW supports this retimer update feature, then
+	 * it will clear the same PKVL_EEPROM_LOAD bit in 2 seconds. Otherwise
+	 * the driver needs to clear the PKVL_EEPROM_LOAD bit manually and
+	 * return an error code.
+	 */
+	ret = regmap_read_poll_timeout(m10bmc->regmap,
+				       M10BMC_SYS_BASE + M10BMC_DOORBELL, val,
+				       (!(val & DRBL_PKVL_EEPROM_LOAD_SEC)),
+				       M10BMC_PKVL_LOAD_INTERVAL_US,
+				       M10BMC_PKVL_LOAD_TIMEOUT_US);
+	if (ret == -ETIMEDOUT) {
+		dev_err(sec->dev, "PKVL_EEPROM_LOAD clear timedout\n");
+		m10bmc_sys_update_bits(m10bmc, M10BMC_DOORBELL,
+				       DRBL_PKVL_EEPROM_LOAD_SEC, 0);
+		ret = -ENODEV;
+	} else if (ret) {
+		dev_err(sec->dev, "poll EEPROM_LOAD error %d\n", ret);
+	}
+
+	return ret;
+}
+
+static int poll_retimer_eeprom_load_done(struct m10bmc_sec *sec)
+{
+	struct intel_m10bmc *m10bmc = sec->m10bmc;
+	unsigned int doorbell;
+	int ret;
+
+	/*
+	 * RSU_STAT_PKVL_REJECT indicates that the current image is
+	 * already programmed. RSU_PROG_PKVL_PROM_DONE that the firmware
+	 * update process has finished, but does not necessarily indicate
+	 * a successful update.
+	 */
+	ret = regmap_read_poll_timeout(m10bmc->regmap,
+				       M10BMC_SYS_BASE + M10BMC_DOORBELL,
+				       doorbell,
+				       ((rsu_prog(doorbell) ==
+					 RSU_PROG_PKVL_PROM_DONE) ||
+					(rsu_stat(doorbell) ==
+					 RSU_STAT_PKVL_REJECT)),
+				       M10BMC_PKVL_PRELOAD_INTERVAL_US,
+				       M10BMC_PKVL_PRELOAD_TIMEOUT_US);
+	if (ret) {
+		if (ret == -ETIMEDOUT)
+			dev_err(sec->dev,
+				"Doorbell check timedout: 0x%08x\n", doorbell);
+		else
+			dev_err(sec->dev, "poll Doorbell error\n");
+		return ret;
+	}
+
+	if (rsu_stat(doorbell) == RSU_STAT_PKVL_REJECT) {
+		dev_err(sec->dev, "duplicate image rejected\n");
+		return -ECANCELED;
+	}
+
+	return 0;
+}
+
+static int poll_retimer_preload_done(struct m10bmc_sec *sec)
+{
+	struct intel_m10bmc *m10bmc = sec->m10bmc;
+	unsigned int val;
+	int ret;
+
+	/*
+	 * Wait for the updated firmware to be loaded by the PKVL device
+	 * and confirm that the updated firmware is operational
+	 */
+	ret = regmap_read_poll_timeout(m10bmc->regmap,
+				       M10BMC_SYS_BASE + M10BMC_PKVL_POLL_CTRL, val,
+				       ((val & M10BMC_PKVL_PRELOAD) == M10BMC_PKVL_PRELOAD),
+				       M10BMC_PKVL_PRELOAD_INTERVAL_US,
+				       M10BMC_PKVL_PRELOAD_TIMEOUT_US);
+	if (ret) {
+		dev_err(sec->dev, "poll M10BMC_PKVL_PRELOAD error %d\n", ret);
+		return ret;
+	}
+
+	if ((val & M10BMC_PKVL_UPG_STATUS_MASK) != M10BMC_PKVL_UPG_STATUS_GOOD) {
+		dev_err(sec->dev, "error detected during upgrade\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int retimer_check_idle(struct m10bmc_sec *sec)
+{
+	u32 doorbell;
+	int ret;
+
+	ret = m10bmc_sys_read(sec->m10bmc, M10BMC_DOORBELL, &doorbell);
+	if (ret)
+		return -EIO;
+
+	if (rsu_prog(doorbell) != RSU_PROG_IDLE &&
+	    rsu_prog(doorbell) != RSU_PROG_RSU_DONE &&
+	    rsu_prog(doorbell) != RSU_PROG_PKVL_PROM_DONE) {
+		log_error_regs(sec, doorbell);
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+static int m10bmc_sec_retimer_eeprom_load(struct m10bmc_sec *sec)
+{
+	int ret;
+
+	ret = retimer_check_idle(sec);
+	if (ret)
+		goto exit;
+
+	ret = trigger_retimer_eeprom_load(sec);
+	if (ret)
+		goto exit;
+
+	ret = poll_retimer_eeprom_load_done(sec);
+	if (ret)
+		goto exit;
+
+	ret = poll_retimer_preload_done(sec);
+
+exit:
+	return ret;
+}
+
 static struct image_load m10bmc_image_load_hndlrs[] = {
 	{
 		.name = "bmc_factory",
@@ -308,6 +450,10 @@ static struct image_load m10bmc_image_load_hndlrs[] = {
 		.name = "bmc_user",
 		.load_image = m10bmc_sec_bmc_image_load_0,
 	},
+	{
+		.name = "retimer_fw",
+		.load_image = m10bmc_sec_retimer_eeprom_load,
+	},
 	{}
 };
 
diff --git a/include/linux/mfd/intel-m10-bmc.h b/include/linux/mfd/intel-m10-bmc.h
index 8e434886a5a1..23025e4d2779 100644
--- a/include/linux/mfd/intel-m10-bmc.h
+++ b/include/linux/mfd/intel-m10-bmc.h
@@ -36,6 +36,37 @@
 #define M10BMC_VER_PCB_INFO_MSK		GENMASK(31, 24)
 #define M10BMC_VER_LEGACY_INVALID	0xffffffff
 
+/* Retimer related registers, in system register region */
+#define M10BMC_PKVL_POLL_CTRL		0x80
+#define M10BMC_PKVL_A_PRELOAD		BIT(16)
+#define M10BMC_PKVL_A_PRELOAD_TO	BIT(17)
+#define M10BMC_PKVL_A_DATA_TOO_BIG	BIT(18)
+#define M10BMC_PKVL_A_HDR_CKSUM	BIT(20)
+#define M10BMC_PKVL_B_PRELOAD		BIT(24)
+#define M10BMC_PKVL_B_PRELOAD_TO	BIT(25)
+#define M10BMC_PKVL_B_DATA_TOO_BIG	BIT(26)
+#define M10BMC_PKVL_B_HDR_CKSUM	BIT(28)
+
+#define M10BMC_PKVL_PRELOAD		(M10BMC_PKVL_A_PRELOAD | M10BMC_PKVL_B_PRELOAD)
+#define M10BMC_PKVL_PRELOAD_TIMEOUT	(M10BMC_PKVL_A_PRELOAD_TO | \
+					 M10BMC_PKVL_B_PRELOAD_TO)
+#define M10BMC_PKVL_DATA_TOO_BIG	(M10BMC_PKVL_A_DATA_TOO_BIG | \
+					 M10BMC_PKVL_B_DATA_TOO_BIG)
+#define M10BMC_PKVL_HDR_CHECKSUM	(M10BMC_PKVL_A_HDR_CKSUM | \
+					 M10BMC_PKVL_B_HDR_CKSUM)
+
+#define M10BMC_PKVL_UPG_STATUS_MASK	(M10BMC_PKVL_PRELOAD | M10BMC_PKVL_PRELOAD_TIMEOUT |\
+					 M10BMC_PKVL_DATA_TOO_BIG | M10BMC_PKVL_HDR_CHECKSUM)
+#define M10BMC_PKVL_UPG_STATUS_GOOD	(M10BMC_PKVL_PRELOAD | M10BMC_PKVL_HDR_CHECKSUM)
+
+/* interval 100ms and timeout 2s */
+#define M10BMC_PKVL_LOAD_INTERVAL_US	(100 * 1000)
+#define M10BMC_PKVL_LOAD_TIMEOUT_US	(2 * 1000 * 1000)
+
+/* interval 100ms and timeout 30s */
+#define M10BMC_PKVL_PRELOAD_INTERVAL_US	(100 * 1000)
+#define M10BMC_PKVL_PRELOAD_TIMEOUT_US	(30 * 1000 * 1000)
+
 /* Secure update doorbell register, in system register region */
 #define M10BMC_DOORBELL			0x400
 
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH v1 2/3] fpga: m10bmc-sec: add sysfs to load bmc images
  2022-07-05  8:00 ` [PATCH v1 2/3] fpga: m10bmc-sec: add sysfs to load bmc images Tianfei Zhang
@ 2022-07-07  2:00   ` Xu Yilun
  2022-07-11  6:24     ` Zhang, Tianfei
  0 siblings, 1 reply; 9+ messages in thread
From: Xu Yilun @ 2022-07-07  2:00 UTC (permalink / raw)
  To: Tianfei Zhang; +Cc: mdf, lee.jones, russell.h.weight, hao.wu, trix, linux-fpga

On Tue, Jul 05, 2022 at 04:00:57AM -0400, Tianfei Zhang wrote:
> From: Russ Weight <russell.h.weight@intel.com>
> 
> Add the available_images and image_load sysfs files. The available_images
> file returns a space separated list of key words that may be written
> into the image_load file. These keywords describe an FPGA, BMC, or
> firmware image in FLASH or EEPROM storage that may be loaded.
> 
> The image_load sysfs file may be written with a key word to trigger a
> reload of an FPGA, BMC, or firmware image from FLASH or EEPROM.
> 
> Signed-off-by: Russ Weight <russell.h.weight@intel.com>
> Signed-off-by: Tianfei Zhang <tianfei.zhang@intel.com>
> ---
>  .../sysfs-driver-intel-m10-bmc-sec-update     |  21 ++++
>  drivers/fpga/intel-m10-bmc-sec-update.c       | 104 ++++++++++++++++++
>  2 files changed, 125 insertions(+)
> 
> diff --git a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-sec-update b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-sec-update
> index 0a41afe0ab4c..8ded1a59d4db 100644
> --- a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-sec-update
> +++ b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-sec-update
> @@ -59,3 +59,24 @@ Contact:	Russ Weight <russell.h.weight@intel.com>
>  Description:	Read only. Returns number of times the secure update
>  		staging area has been flashed.
>  		Format: "%u".
> +
> +What:		/sys/bus/platform/drivers/intel-m10bmc-sec-update/.../control/available_images
> +Date:		July 2022
> +KernelVersion:  5.20
> +Contact:	Russ Weight <russell.h.weight@intel.com>
> +Description:	Read-only. This file returns a space separated list of
> +		key words that may be written into the image_load file
> +		described below. These keywords decribe an FPGA, BMC,
> +		or firmware image in FLASH or EEPROM storage that may
> +		be loaded.
> +
> +What:		/sys/bus/platform/drivers/intel-m10bmc-sec-update/.../control/image_load
> +Date:		July 2022
> +KernelVersion:  5.20
> +Contact:	Russ Weight <russell.h.weight@intel.com>
> +Description:	Write-only. A key word may be written to this file to
> +		trigger a reload of an FPGA, BMC, or firmware image from

A FPGA reprogramming could be handled by FPGA manager, so we may not
introduce a new API for the same purpose.

Thanks,
Yilun

> +		FLASH or EEPROM. Refer to the available_images file for a
> +		list of supported key words for the underlying device.
> +		Writing an unsupported string to this file will result in
> +		EINVAL being returned.
> diff --git a/drivers/fpga/intel-m10-bmc-sec-update.c b/drivers/fpga/intel-m10-bmc-sec-update.c
> index 72c677c910de..640690e6c131 100644
> --- a/drivers/fpga/intel-m10-bmc-sec-update.c
> +++ b/drivers/fpga/intel-m10-bmc-sec-update.c
> @@ -14,6 +14,8 @@
>  #include <linux/platform_device.h>
>  #include <linux/slab.h>
>  
> +struct image_load;
> +
>  struct m10bmc_sec {
>  	struct device *dev;
>  	struct intel_m10bmc *m10bmc;
> @@ -21,6 +23,12 @@ struct m10bmc_sec {
>  	char *fw_name;
>  	u32 fw_name_id;
>  	bool cancel_request;
> +	struct image_load *image_load;	/* terminated with { } member */
> +};
> +
> +struct image_load {
> +	const char *name;
> +	int (*load_image)(struct m10bmc_sec *sec);
>  };
>  
>  static DEFINE_XARRAY_ALLOC(fw_upload_xa);
> @@ -137,6 +145,54 @@ DEVICE_ATTR_SEC_CSK_RO(pr, PR_PROG_ADDR + CSK_VEC_OFFSET);
>  
>  #define FLASH_COUNT_SIZE 4096	/* count stored as inverted bit vector */
>  
> +static ssize_t available_images_show(struct device *dev,
> +				     struct device_attribute *attr, char *buf)
> +{
> +	struct m10bmc_sec *sec = dev_get_drvdata(dev);
> +	const struct image_load *hndlr;
> +	ssize_t count = 0;
> +
> +	for (hndlr = sec->image_load; hndlr->name; hndlr++) {
> +		count += scnprintf(buf + count, PAGE_SIZE - count,
> +				   "%s ", hndlr->name);
> +	}
> +
> +	buf[count - 1] = '\n';
> +
> +	return count;
> +}
> +static DEVICE_ATTR_RO(available_images);
> +
> +static ssize_t image_load_store(struct device *dev,
> +				struct device_attribute *attr,
> +				const char *buf, size_t count)
> +{
> +	struct m10bmc_sec *sec = dev_get_drvdata(dev);
> +	const struct image_load *hndlr;
> +	int ret = -EINVAL;
> +
> +	for (hndlr = sec->image_load; hndlr->name; hndlr++) {
> +		if (sysfs_streq(buf, hndlr->name)) {
> +			ret = hndlr->load_image(sec);
> +			break;
> +		}
> +	}
> +
> +	return ret ? : count;
> +}
> +static DEVICE_ATTR_WO(image_load);
> +
> +static struct attribute *m10bmc_control_attrs[] = {
> +	&dev_attr_available_images.attr,
> +	&dev_attr_image_load.attr,
> +	NULL,
> +};
> +
> +static struct attribute_group m10bmc_control_attr_group = {
> +	.name = "control",
> +	.attrs = m10bmc_control_attrs,
> +};
> +
>  static ssize_t flash_count_show(struct device *dev,
>  				struct device_attribute *attr, char *buf)
>  {
> @@ -195,6 +251,7 @@ static struct attribute_group m10bmc_security_attr_group = {
>  
>  static const struct attribute_group *m10bmc_sec_attr_groups[] = {
>  	&m10bmc_security_attr_group,
> +	&m10bmc_control_attr_group,
>  	NULL,
>  };
>  
> @@ -208,6 +265,52 @@ static void log_error_regs(struct m10bmc_sec *sec, u32 doorbell)
>  		dev_err(sec->dev, "RSU auth result: 0x%08x\n", auth_result);
>  }
>  
> +static int m10bmc_sec_bmc_image_load(struct m10bmc_sec *sec,
> +				     unsigned int val)
> +{
> +	u32 doorbell;
> +	int ret;
> +
> +	if (val > 1) {
> +		dev_err(sec->dev, "invalid reload val = %d\n", val);
> +		return -EINVAL;
> +	}
> +
> +	ret = m10bmc_sys_read(sec->m10bmc, M10BMC_DOORBELL, &doorbell);
> +	if (ret)
> +		return ret;
> +
> +	if (doorbell & DRBL_REBOOT_DISABLED)
> +		return -EBUSY;
> +
> +	return m10bmc_sys_update_bits(sec->m10bmc, M10BMC_DOORBELL,
> +				      DRBL_CONFIG_SEL | DRBL_REBOOT_REQ,
> +				      FIELD_PREP(DRBL_CONFIG_SEL, val) |
> +				      DRBL_REBOOT_REQ);
> +}
> +
> +static int m10bmc_sec_bmc_image_load_0(struct m10bmc_sec *sec)
> +{
> +	return m10bmc_sec_bmc_image_load(sec, 0);
> +}
> +
> +static int m10bmc_sec_bmc_image_load_1(struct m10bmc_sec *sec)
> +{
> +	return m10bmc_sec_bmc_image_load(sec, 1);
> +}
> +
> +static struct image_load m10bmc_image_load_hndlrs[] = {
> +	{
> +		.name = "bmc_factory",
> +		.load_image = m10bmc_sec_bmc_image_load_1,
> +	},
> +	{
> +		.name = "bmc_user",
> +		.load_image = m10bmc_sec_bmc_image_load_0,
> +	},
> +	{}
> +};
> +
>  static enum fw_upload_err rsu_check_idle(struct m10bmc_sec *sec)
>  {
>  	u32 doorbell;
> @@ -565,6 +668,7 @@ static int m10bmc_sec_probe(struct platform_device *pdev)
>  	sec->dev = &pdev->dev;
>  	sec->m10bmc = dev_get_drvdata(pdev->dev.parent);
>  	dev_set_drvdata(&pdev->dev, sec);
> +	sec->image_load = m10bmc_image_load_hndlrs;
>  
>  	ret = xa_alloc(&fw_upload_xa, &sec->fw_name_id, sec,
>  		       xa_limit_32b, GFP_KERNEL);
> -- 
> 2.26.2

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v1 3/3] fpga: m10bmc-sec: add m10bmc_sec_retimer_load callback
  2022-07-05  8:00 ` [PATCH v1 3/3] fpga: m10bmc-sec: add m10bmc_sec_retimer_load callback Tianfei Zhang
@ 2022-07-07  2:05   ` Xu Yilun
  2022-07-07  6:26     ` Zhang, Tianfei
  0 siblings, 1 reply; 9+ messages in thread
From: Xu Yilun @ 2022-07-07  2:05 UTC (permalink / raw)
  To: Tianfei Zhang; +Cc: mdf, lee.jones, russell.h.weight, hao.wu, trix, linux-fpga

On Tue, Jul 05, 2022 at 04:00:58AM -0400, Tianfei Zhang wrote:
> From: Russ Weight <russell.h.weight@intel.com>
> 
> Create m10bmc_sec_retimer_load() callback function
> to provide a trigger to update a new retimer (Intel
> C827 Ethernet transceiver) firmware on Intel PAC

A firmware loader framework is upstreamed recently, does that meet your
need?

Thanks,
Yilun

> N3000 Card.
> 
> Signed-off-by: Russ Weight <russell.h.weight@intel.com>
> Signed-off-by: Tianfei Zhang <tianfei.zhang@intel.com>
> ---
>  drivers/fpga/intel-m10-bmc-sec-update.c | 146 ++++++++++++++++++++++++
>  include/linux/mfd/intel-m10-bmc.h       |  31 +++++
>  2 files changed, 177 insertions(+)
> 
> diff --git a/drivers/fpga/intel-m10-bmc-sec-update.c b/drivers/fpga/intel-m10-bmc-sec-update.c
> index 640690e6c131..707dfd8a1931 100644
> --- a/drivers/fpga/intel-m10-bmc-sec-update.c
> +++ b/drivers/fpga/intel-m10-bmc-sec-update.c
> @@ -299,6 +299,148 @@ static int m10bmc_sec_bmc_image_load_1(struct m10bmc_sec *sec)
>  	return m10bmc_sec_bmc_image_load(sec, 1);
>  }
>  
> +static int trigger_retimer_eeprom_load(struct m10bmc_sec *sec)
> +{
> +	struct intel_m10bmc *m10bmc = sec->m10bmc;
> +	unsigned int val;
> +	int ret;
> +
> +	ret = m10bmc_sys_update_bits(m10bmc, M10BMC_DOORBELL,
> +				     DRBL_PKVL_EEPROM_LOAD_SEC,
> +				     DRBL_PKVL_EEPROM_LOAD_SEC);
> +	if (ret)
> +		return ret;
> +
> +	/*
> +	 * If the current NIOS FW supports this retimer update feature, then
> +	 * it will clear the same PKVL_EEPROM_LOAD bit in 2 seconds. Otherwise
> +	 * the driver needs to clear the PKVL_EEPROM_LOAD bit manually and
> +	 * return an error code.
> +	 */
> +	ret = regmap_read_poll_timeout(m10bmc->regmap,
> +				       M10BMC_SYS_BASE + M10BMC_DOORBELL, val,
> +				       (!(val & DRBL_PKVL_EEPROM_LOAD_SEC)),
> +				       M10BMC_PKVL_LOAD_INTERVAL_US,
> +				       M10BMC_PKVL_LOAD_TIMEOUT_US);
> +	if (ret == -ETIMEDOUT) {
> +		dev_err(sec->dev, "PKVL_EEPROM_LOAD clear timedout\n");
> +		m10bmc_sys_update_bits(m10bmc, M10BMC_DOORBELL,
> +				       DRBL_PKVL_EEPROM_LOAD_SEC, 0);
> +		ret = -ENODEV;
> +	} else if (ret) {
> +		dev_err(sec->dev, "poll EEPROM_LOAD error %d\n", ret);
> +	}
> +
> +	return ret;
> +}
> +
> +static int poll_retimer_eeprom_load_done(struct m10bmc_sec *sec)
> +{
> +	struct intel_m10bmc *m10bmc = sec->m10bmc;
> +	unsigned int doorbell;
> +	int ret;
> +
> +	/*
> +	 * RSU_STAT_PKVL_REJECT indicates that the current image is
> +	 * already programmed. RSU_PROG_PKVL_PROM_DONE that the firmware
> +	 * update process has finished, but does not necessarily indicate
> +	 * a successful update.
> +	 */
> +	ret = regmap_read_poll_timeout(m10bmc->regmap,
> +				       M10BMC_SYS_BASE + M10BMC_DOORBELL,
> +				       doorbell,
> +				       ((rsu_prog(doorbell) ==
> +					 RSU_PROG_PKVL_PROM_DONE) ||
> +					(rsu_stat(doorbell) ==
> +					 RSU_STAT_PKVL_REJECT)),
> +				       M10BMC_PKVL_PRELOAD_INTERVAL_US,
> +				       M10BMC_PKVL_PRELOAD_TIMEOUT_US);
> +	if (ret) {
> +		if (ret == -ETIMEDOUT)
> +			dev_err(sec->dev,
> +				"Doorbell check timedout: 0x%08x\n", doorbell);
> +		else
> +			dev_err(sec->dev, "poll Doorbell error\n");
> +		return ret;
> +	}
> +
> +	if (rsu_stat(doorbell) == RSU_STAT_PKVL_REJECT) {
> +		dev_err(sec->dev, "duplicate image rejected\n");
> +		return -ECANCELED;
> +	}
> +
> +	return 0;
> +}
> +
> +static int poll_retimer_preload_done(struct m10bmc_sec *sec)
> +{
> +	struct intel_m10bmc *m10bmc = sec->m10bmc;
> +	unsigned int val;
> +	int ret;
> +
> +	/*
> +	 * Wait for the updated firmware to be loaded by the PKVL device
> +	 * and confirm that the updated firmware is operational
> +	 */
> +	ret = regmap_read_poll_timeout(m10bmc->regmap,
> +				       M10BMC_SYS_BASE + M10BMC_PKVL_POLL_CTRL, val,
> +				       ((val & M10BMC_PKVL_PRELOAD) == M10BMC_PKVL_PRELOAD),
> +				       M10BMC_PKVL_PRELOAD_INTERVAL_US,
> +				       M10BMC_PKVL_PRELOAD_TIMEOUT_US);
> +	if (ret) {
> +		dev_err(sec->dev, "poll M10BMC_PKVL_PRELOAD error %d\n", ret);
> +		return ret;
> +	}
> +
> +	if ((val & M10BMC_PKVL_UPG_STATUS_MASK) != M10BMC_PKVL_UPG_STATUS_GOOD) {
> +		dev_err(sec->dev, "error detected during upgrade\n");
> +		return -EIO;
> +	}
> +
> +	return 0;
> +}
> +
> +static int retimer_check_idle(struct m10bmc_sec *sec)
> +{
> +	u32 doorbell;
> +	int ret;
> +
> +	ret = m10bmc_sys_read(sec->m10bmc, M10BMC_DOORBELL, &doorbell);
> +	if (ret)
> +		return -EIO;
> +
> +	if (rsu_prog(doorbell) != RSU_PROG_IDLE &&
> +	    rsu_prog(doorbell) != RSU_PROG_RSU_DONE &&
> +	    rsu_prog(doorbell) != RSU_PROG_PKVL_PROM_DONE) {
> +		log_error_regs(sec, doorbell);
> +		return -EBUSY;
> +	}
> +
> +	return 0;
> +}
> +
> +static int m10bmc_sec_retimer_eeprom_load(struct m10bmc_sec *sec)
> +{
> +	int ret;
> +
> +	ret = retimer_check_idle(sec);
> +	if (ret)
> +		goto exit;
> +
> +	ret = trigger_retimer_eeprom_load(sec);
> +	if (ret)
> +		goto exit;
> +
> +	ret = poll_retimer_eeprom_load_done(sec);
> +	if (ret)
> +		goto exit;
> +
> +	ret = poll_retimer_preload_done(sec);
> +
> +exit:
> +	return ret;
> +}
> +
>  static struct image_load m10bmc_image_load_hndlrs[] = {
>  	{
>  		.name = "bmc_factory",
> @@ -308,6 +450,10 @@ static struct image_load m10bmc_image_load_hndlrs[] = {
>  		.name = "bmc_user",
>  		.load_image = m10bmc_sec_bmc_image_load_0,
>  	},
> +	{
> +		.name = "retimer_fw",
> +		.load_image = m10bmc_sec_retimer_eeprom_load,
> +	},
>  	{}
>  };
>  
> diff --git a/include/linux/mfd/intel-m10-bmc.h b/include/linux/mfd/intel-m10-bmc.h
> index 8e434886a5a1..23025e4d2779 100644
> --- a/include/linux/mfd/intel-m10-bmc.h
> +++ b/include/linux/mfd/intel-m10-bmc.h
> @@ -36,6 +36,37 @@
>  #define M10BMC_VER_PCB_INFO_MSK		GENMASK(31, 24)
>  #define M10BMC_VER_LEGACY_INVALID	0xffffffff
>  
> +/* Retimer related registers, in system register region */
> +#define M10BMC_PKVL_POLL_CTRL		0x80
> +#define M10BMC_PKVL_A_PRELOAD		BIT(16)
> +#define M10BMC_PKVL_A_PRELOAD_TO	BIT(17)
> +#define M10BMC_PKVL_A_DATA_TOO_BIG	BIT(18)
> +#define M10BMC_PKVL_A_HDR_CKSUM	BIT(20)
> +#define M10BMC_PKVL_B_PRELOAD		BIT(24)
> +#define M10BMC_PKVL_B_PRELOAD_TO	BIT(25)
> +#define M10BMC_PKVL_B_DATA_TOO_BIG	BIT(26)
> +#define M10BMC_PKVL_B_HDR_CKSUM	BIT(28)
> +
> +#define M10BMC_PKVL_PRELOAD		(M10BMC_PKVL_A_PRELOAD | M10BMC_PKVL_B_PRELOAD)
> +#define M10BMC_PKVL_PRELOAD_TIMEOUT	(M10BMC_PKVL_A_PRELOAD_TO | \
> +					 M10BMC_PKVL_B_PRELOAD_TO)
> +#define M10BMC_PKVL_DATA_TOO_BIG	(M10BMC_PKVL_A_DATA_TOO_BIG | \
> +					 M10BMC_PKVL_B_DATA_TOO_BIG)
> +#define M10BMC_PKVL_HDR_CHECKSUM	(M10BMC_PKVL_A_HDR_CKSUM | \
> +					 M10BMC_PKVL_B_HDR_CKSUM)
> +
> +#define M10BMC_PKVL_UPG_STATUS_MASK	(M10BMC_PKVL_PRELOAD | M10BMC_PKVL_PRELOAD_TIMEOUT |\
> +					 M10BMC_PKVL_DATA_TOO_BIG | M10BMC_PKVL_HDR_CHECKSUM)
> +#define M10BMC_PKVL_UPG_STATUS_GOOD	(M10BMC_PKVL_PRELOAD | M10BMC_PKVL_HDR_CHECKSUM)
> +
> +/* interval 100ms and timeout 2s */
> +#define M10BMC_PKVL_LOAD_INTERVAL_US	(100 * 1000)
> +#define M10BMC_PKVL_LOAD_TIMEOUT_US	(2 * 1000 * 1000)
> +
> +/* interval 100ms and timeout 30s */
> +#define M10BMC_PKVL_PRELOAD_INTERVAL_US	(100 * 1000)
> +#define M10BMC_PKVL_PRELOAD_TIMEOUT_US	(30 * 1000 * 1000)
> +
>  /* Secure update doorbell register, in system register region */
>  #define M10BMC_DOORBELL			0x400
>  
> -- 
> 2.26.2

^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: [PATCH v1 3/3] fpga: m10bmc-sec: add m10bmc_sec_retimer_load callback
  2022-07-07  2:05   ` Xu Yilun
@ 2022-07-07  6:26     ` Zhang, Tianfei
  0 siblings, 0 replies; 9+ messages in thread
From: Zhang, Tianfei @ 2022-07-07  6:26 UTC (permalink / raw)
  To: Xu, Yilun; +Cc: mdf, lee.jones, Weight, Russell H, Wu, Hao, trix, linux-fpga



> -----Original Message-----
> From: Xu, Yilun <yilun.xu@intel.com>
> Sent: Thursday, July 7, 2022 10:06 AM
> To: Zhang, Tianfei <tianfei.zhang@intel.com>
> Cc: mdf@kernel.org; lee.jones@linaro.org; Weight, Russell H
> <russell.h.weight@intel.com>; Wu, Hao <hao.wu@intel.com>;
> trix@redhat.com; linux-fpga@vger.kernel.org
> Subject: Re: [PATCH v1 3/3] fpga: m10bmc-sec: add m10bmc_sec_retimer_load
> callback
> 
> On Tue, Jul 05, 2022 at 04:00:58AM -0400, Tianfei Zhang wrote:
> > From: Russ Weight <russell.h.weight@intel.com>
> >
> > Create m10bmc_sec_retimer_load() callback function to provide a
> > trigger to update a new retimer (Intel
> > C827 Ethernet transceiver) firmware on Intel PAC
> 
> A firmware loader framework is upstreamed recently, does that meet your
> need?

You mean that the firmware loader Russ has submitted? We have used this firmware loader framework to flash the M10 BMC image.
The retimer firmware was contained into M10 BMC image, this patch trigger the retimer firmware reload.

> 
> Thanks,
> Yilun
> 
> > N3000 Card.
> >
> > Signed-off-by: Russ Weight <russell.h.weight@intel.com>
> > Signed-off-by: Tianfei Zhang <tianfei.zhang@intel.com>
> > ---
> >  drivers/fpga/intel-m10-bmc-sec-update.c | 146 ++++++++++++++++++++++++
> >  include/linux/mfd/intel-m10-bmc.h       |  31 +++++
> >  2 files changed, 177 insertions(+)
> >
> > diff --git a/drivers/fpga/intel-m10-bmc-sec-update.c
> > b/drivers/fpga/intel-m10-bmc-sec-update.c
> > index 640690e6c131..707dfd8a1931 100644
> > --- a/drivers/fpga/intel-m10-bmc-sec-update.c
> > +++ b/drivers/fpga/intel-m10-bmc-sec-update.c
> > @@ -299,6 +299,148 @@ static int m10bmc_sec_bmc_image_load_1(struct
> m10bmc_sec *sec)
> >  	return m10bmc_sec_bmc_image_load(sec, 1);  }
> >
> > +static int trigger_retimer_eeprom_load(struct m10bmc_sec *sec) {
> > +	struct intel_m10bmc *m10bmc = sec->m10bmc;
> > +	unsigned int val;
> > +	int ret;
> > +
> > +	ret = m10bmc_sys_update_bits(m10bmc, M10BMC_DOORBELL,
> > +				     DRBL_PKVL_EEPROM_LOAD_SEC,
> > +				     DRBL_PKVL_EEPROM_LOAD_SEC);
> > +	if (ret)
> > +		return ret;
> > +
> > +	/*
> > +	 * If the current NIOS FW supports this retimer update feature, then
> > +	 * it will clear the same PKVL_EEPROM_LOAD bit in 2 seconds.
> Otherwise
> > +	 * the driver needs to clear the PKVL_EEPROM_LOAD bit manually and
> > +	 * return an error code.
> > +	 */
> > +	ret = regmap_read_poll_timeout(m10bmc->regmap,
> > +				       M10BMC_SYS_BASE +
> M10BMC_DOORBELL, val,
> > +				       (!(val & DRBL_PKVL_EEPROM_LOAD_SEC)),
> > +				       M10BMC_PKVL_LOAD_INTERVAL_US,
> > +				       M10BMC_PKVL_LOAD_TIMEOUT_US);
> > +	if (ret == -ETIMEDOUT) {
> > +		dev_err(sec->dev, "PKVL_EEPROM_LOAD clear timedout\n");
> > +		m10bmc_sys_update_bits(m10bmc, M10BMC_DOORBELL,
> > +				       DRBL_PKVL_EEPROM_LOAD_SEC, 0);
> > +		ret = -ENODEV;
> > +	} else if (ret) {
> > +		dev_err(sec->dev, "poll EEPROM_LOAD error %d\n", ret);
> > +	}
> > +
> > +	return ret;
> > +}
> > +
> > +static int poll_retimer_eeprom_load_done(struct m10bmc_sec *sec) {
> > +	struct intel_m10bmc *m10bmc = sec->m10bmc;
> > +	unsigned int doorbell;
> > +	int ret;
> > +
> > +	/*
> > +	 * RSU_STAT_PKVL_REJECT indicates that the current image is
> > +	 * already programmed. RSU_PROG_PKVL_PROM_DONE that the
> firmware
> > +	 * update process has finished, but does not necessarily indicate
> > +	 * a successful update.
> > +	 */
> > +	ret = regmap_read_poll_timeout(m10bmc->regmap,
> > +				       M10BMC_SYS_BASE +
> M10BMC_DOORBELL,
> > +				       doorbell,
> > +				       ((rsu_prog(doorbell) ==
> > +					 RSU_PROG_PKVL_PROM_DONE) ||
> > +					(rsu_stat(doorbell) ==
> > +					 RSU_STAT_PKVL_REJECT)),
> > +				       M10BMC_PKVL_PRELOAD_INTERVAL_US,
> > +				       M10BMC_PKVL_PRELOAD_TIMEOUT_US);
> > +	if (ret) {
> > +		if (ret == -ETIMEDOUT)
> > +			dev_err(sec->dev,
> > +				"Doorbell check timedout: 0x%08x\n",
> doorbell);
> > +		else
> > +			dev_err(sec->dev, "poll Doorbell error\n");
> > +		return ret;
> > +	}
> > +
> > +	if (rsu_stat(doorbell) == RSU_STAT_PKVL_REJECT) {
> > +		dev_err(sec->dev, "duplicate image rejected\n");
> > +		return -ECANCELED;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int poll_retimer_preload_done(struct m10bmc_sec *sec) {
> > +	struct intel_m10bmc *m10bmc = sec->m10bmc;
> > +	unsigned int val;
> > +	int ret;
> > +
> > +	/*
> > +	 * Wait for the updated firmware to be loaded by the PKVL device
> > +	 * and confirm that the updated firmware is operational
> > +	 */
> > +	ret = regmap_read_poll_timeout(m10bmc->regmap,
> > +				       M10BMC_SYS_BASE +
> M10BMC_PKVL_POLL_CTRL, val,
> > +				       ((val & M10BMC_PKVL_PRELOAD) ==
> M10BMC_PKVL_PRELOAD),
> > +				       M10BMC_PKVL_PRELOAD_INTERVAL_US,
> > +				       M10BMC_PKVL_PRELOAD_TIMEOUT_US);
> > +	if (ret) {
> > +		dev_err(sec->dev, "poll M10BMC_PKVL_PRELOAD error %d\n",
> ret);
> > +		return ret;
> > +	}
> > +
> > +	if ((val & M10BMC_PKVL_UPG_STATUS_MASK) !=
> M10BMC_PKVL_UPG_STATUS_GOOD) {
> > +		dev_err(sec->dev, "error detected during upgrade\n");
> > +		return -EIO;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int retimer_check_idle(struct m10bmc_sec *sec) {
> > +	u32 doorbell;
> > +	int ret;
> > +
> > +	ret = m10bmc_sys_read(sec->m10bmc, M10BMC_DOORBELL,
> &doorbell);
> > +	if (ret)
> > +		return -EIO;
> > +
> > +	if (rsu_prog(doorbell) != RSU_PROG_IDLE &&
> > +	    rsu_prog(doorbell) != RSU_PROG_RSU_DONE &&
> > +	    rsu_prog(doorbell) != RSU_PROG_PKVL_PROM_DONE) {
> > +		log_error_regs(sec, doorbell);
> > +		return -EBUSY;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int m10bmc_sec_retimer_eeprom_load(struct m10bmc_sec *sec) {
> > +	int ret;
> > +
> > +	ret = retimer_check_idle(sec);
> > +	if (ret)
> > +		goto exit;
> > +
> > +	ret = trigger_retimer_eeprom_load(sec);
> > +	if (ret)
> > +		goto exit;
> > +
> > +	ret = poll_retimer_eeprom_load_done(sec);
> > +	if (ret)
> > +		goto exit;
> > +
> > +	ret = poll_retimer_preload_done(sec);
> > +
> > +exit:
> > +	return ret;
> > +}
> > +
> >  static struct image_load m10bmc_image_load_hndlrs[] = {
> >  	{
> >  		.name = "bmc_factory",
> > @@ -308,6 +450,10 @@ static struct image_load
> m10bmc_image_load_hndlrs[] = {
> >  		.name = "bmc_user",
> >  		.load_image = m10bmc_sec_bmc_image_load_0,
> >  	},
> > +	{
> > +		.name = "retimer_fw",
> > +		.load_image = m10bmc_sec_retimer_eeprom_load,
> > +	},
> >  	{}
> >  };
> >
> > diff --git a/include/linux/mfd/intel-m10-bmc.h
> > b/include/linux/mfd/intel-m10-bmc.h
> > index 8e434886a5a1..23025e4d2779 100644
> > --- a/include/linux/mfd/intel-m10-bmc.h
> > +++ b/include/linux/mfd/intel-m10-bmc.h
> > @@ -36,6 +36,37 @@
> >  #define M10BMC_VER_PCB_INFO_MSK		GENMASK(31, 24)
> >  #define M10BMC_VER_LEGACY_INVALID	0xffffffff
> >
> > +/* Retimer related registers, in system register region */
> > +#define M10BMC_PKVL_POLL_CTRL		0x80
> > +#define M10BMC_PKVL_A_PRELOAD		BIT(16)
> > +#define M10BMC_PKVL_A_PRELOAD_TO	BIT(17)
> > +#define M10BMC_PKVL_A_DATA_TOO_BIG	BIT(18)
> > +#define M10BMC_PKVL_A_HDR_CKSUM	BIT(20)
> > +#define M10BMC_PKVL_B_PRELOAD		BIT(24)
> > +#define M10BMC_PKVL_B_PRELOAD_TO	BIT(25)
> > +#define M10BMC_PKVL_B_DATA_TOO_BIG	BIT(26)
> > +#define M10BMC_PKVL_B_HDR_CKSUM	BIT(28)
> > +
> > +#define M10BMC_PKVL_PRELOAD		(M10BMC_PKVL_A_PRELOAD |
> M10BMC_PKVL_B_PRELOAD)
> > +#define M10BMC_PKVL_PRELOAD_TIMEOUT
> 	(M10BMC_PKVL_A_PRELOAD_TO | \
> > +					 M10BMC_PKVL_B_PRELOAD_TO)
> > +#define M10BMC_PKVL_DATA_TOO_BIG
> 	(M10BMC_PKVL_A_DATA_TOO_BIG | \
> > +					 M10BMC_PKVL_B_DATA_TOO_BIG)
> > +#define M10BMC_PKVL_HDR_CHECKSUM
> 	(M10BMC_PKVL_A_HDR_CKSUM | \
> > +					 M10BMC_PKVL_B_HDR_CKSUM)
> > +
> > +#define M10BMC_PKVL_UPG_STATUS_MASK	(M10BMC_PKVL_PRELOAD |
> M10BMC_PKVL_PRELOAD_TIMEOUT |\
> > +					 M10BMC_PKVL_DATA_TOO_BIG |
> M10BMC_PKVL_HDR_CHECKSUM)
> > +#define M10BMC_PKVL_UPG_STATUS_GOOD	(M10BMC_PKVL_PRELOAD |
> M10BMC_PKVL_HDR_CHECKSUM)
> > +
> > +/* interval 100ms and timeout 2s */
> > +#define M10BMC_PKVL_LOAD_INTERVAL_US	(100 * 1000)
> > +#define M10BMC_PKVL_LOAD_TIMEOUT_US	(2 * 1000 * 1000)
> > +
> > +/* interval 100ms and timeout 30s */
> > +#define M10BMC_PKVL_PRELOAD_INTERVAL_US	(100 * 1000)
> > +#define M10BMC_PKVL_PRELOAD_TIMEOUT_US	(30 * 1000 * 1000)
> > +
> >  /* Secure update doorbell register, in system register region */
> >  #define M10BMC_DOORBELL			0x400
> >
> > --
> > 2.26.2

^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: [PATCH v1 2/3] fpga: m10bmc-sec: add sysfs to load bmc images
  2022-07-07  2:00   ` Xu Yilun
@ 2022-07-11  6:24     ` Zhang, Tianfei
  2022-07-11  6:58       ` Xu Yilun
  0 siblings, 1 reply; 9+ messages in thread
From: Zhang, Tianfei @ 2022-07-11  6:24 UTC (permalink / raw)
  To: Xu, Yilun; +Cc: mdf, lee.jones, Weight, Russell H, Wu, Hao, trix, linux-fpga



> -----Original Message-----
> From: Xu, Yilun <yilun.xu@intel.com>
> Sent: Thursday, July 7, 2022 10:00 AM
> To: Zhang, Tianfei <tianfei.zhang@intel.com>
> Cc: mdf@kernel.org; lee.jones@linaro.org; Weight, Russell H
> <russell.h.weight@intel.com>; Wu, Hao <hao.wu@intel.com>;
> trix@redhat.com; linux-fpga@vger.kernel.org
> Subject: Re: [PATCH v1 2/3] fpga: m10bmc-sec: add sysfs to load bmc images
> 
> On Tue, Jul 05, 2022 at 04:00:57AM -0400, Tianfei Zhang wrote:
> > From: Russ Weight <russell.h.weight@intel.com>
> >
> > Add the available_images and image_load sysfs files. The
> > available_images file returns a space separated list of key words that
> > may be written into the image_load file. These keywords describe an
> > FPGA, BMC, or firmware image in FLASH or EEPROM storage that may be
> loaded.
> >
> > The image_load sysfs file may be written with a key word to trigger a
> > reload of an FPGA, BMC, or firmware image from FLASH or EEPROM.
> >
> > Signed-off-by: Russ Weight <russell.h.weight@intel.com>
> > Signed-off-by: Tianfei Zhang <tianfei.zhang@intel.com>
> > ---
> >  .../sysfs-driver-intel-m10-bmc-sec-update     |  21 ++++
> >  drivers/fpga/intel-m10-bmc-sec-update.c       | 104 ++++++++++++++++++
> >  2 files changed, 125 insertions(+)
> >
> > diff --git
> > a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-sec-update
> > b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-sec-update
> > index 0a41afe0ab4c..8ded1a59d4db 100644
> > --- a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-sec-update
> > +++ b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-sec-update
> > @@ -59,3 +59,24 @@ Contact:	Russ Weight
> <russell.h.weight@intel.com>
> >  Description:	Read only. Returns number of times the secure update
> >  		staging area has been flashed.
> >  		Format: "%u".
> > +
> > +What:		/sys/bus/platform/drivers/intel-m10bmc-sec-
> update/.../control/available_images
> > +Date:		July 2022
> > +KernelVersion:  5.20
> > +Contact:	Russ Weight <russell.h.weight@intel.com>
> > +Description:	Read-only. This file returns a space separated list of
> > +		key words that may be written into the image_load file
> > +		described below. These keywords decribe an FPGA, BMC,
> > +		or firmware image in FLASH or EEPROM storage that may
> > +		be loaded.
> > +
> > +What:		/sys/bus/platform/drivers/intel-m10bmc-sec-
> update/.../control/image_load
> > +Date:		July 2022
> > +KernelVersion:  5.20
> > +Contact:	Russ Weight <russell.h.weight@intel.com>
> > +Description:	Write-only. A key word may be written to this file to
> > +		trigger a reload of an FPGA, BMC, or firmware image from
> 
> A FPGA reprogramming could be handled by FPGA manager, so we may not
> introduce a new API for the same purpose.

The FPGA reprogramming is in the MAX10 BMC Secure Update drive, which instantiates the new Firmware
Upload functionality, like update the image into flash. Those functionalities have implemented by Russ's patchset.
https://lore.kernel.org/linux-fpga/20220606160038.846236-1-russell.h.weight@intel.com/

This patch doesn't related to the FPGA reprogramming, it just do the FPGA/BMC image reload,
and trigger the FPGA/BMC to reload a new image from different flash page. For example, on N3000 card, the 
FPGA image has 2 pages, page 0 for factory image, page 1 for user image. This patch was easy to select and 
trigger the FPGA to reload the image via sysfs file, like factory or user image.

I will change the title of patch change in next version patch:
fpga: m10bmc-sec: add sysfs files to reload fpga/bmc images

> 
> Thanks,
> Yilun
> 
> > +		FLASH or EEPROM. Refer to the available_images file for a
> > +		list of supported key words for the underlying device.
> > +		Writing an unsupported string to this file will result in
> > +		EINVAL being returned.
> > diff --git a/drivers/fpga/intel-m10-bmc-sec-update.c
> > b/drivers/fpga/intel-m10-bmc-sec-update.c
> > index 72c677c910de..640690e6c131 100644
> > --- a/drivers/fpga/intel-m10-bmc-sec-update.c
> > +++ b/drivers/fpga/intel-m10-bmc-sec-update.c
> > @@ -14,6 +14,8 @@
> >  #include <linux/platform_device.h>
> >  #include <linux/slab.h>
> >
> > +struct image_load;
> > +
> >  struct m10bmc_sec {
> >  	struct device *dev;
> >  	struct intel_m10bmc *m10bmc;
> > @@ -21,6 +23,12 @@ struct m10bmc_sec {
> >  	char *fw_name;
> >  	u32 fw_name_id;
> >  	bool cancel_request;
> > +	struct image_load *image_load;	/* terminated with { } member */
> > +};
> > +
> > +struct image_load {
> > +	const char *name;
> > +	int (*load_image)(struct m10bmc_sec *sec);
> >  };
> >
> >  static DEFINE_XARRAY_ALLOC(fw_upload_xa);
> > @@ -137,6 +145,54 @@ DEVICE_ATTR_SEC_CSK_RO(pr, PR_PROG_ADDR +
> > CSK_VEC_OFFSET);
> >
> >  #define FLASH_COUNT_SIZE 4096	/* count stored as inverted bit vector
> */
> >
> > +static ssize_t available_images_show(struct device *dev,
> > +				     struct device_attribute *attr, char *buf) {
> > +	struct m10bmc_sec *sec = dev_get_drvdata(dev);
> > +	const struct image_load *hndlr;
> > +	ssize_t count = 0;
> > +
> > +	for (hndlr = sec->image_load; hndlr->name; hndlr++) {
> > +		count += scnprintf(buf + count, PAGE_SIZE - count,
> > +				   "%s ", hndlr->name);
> > +	}
> > +
> > +	buf[count - 1] = '\n';
> > +
> > +	return count;
> > +}
> > +static DEVICE_ATTR_RO(available_images);
> > +
> > +static ssize_t image_load_store(struct device *dev,
> > +				struct device_attribute *attr,
> > +				const char *buf, size_t count)
> > +{
> > +	struct m10bmc_sec *sec = dev_get_drvdata(dev);
> > +	const struct image_load *hndlr;
> > +	int ret = -EINVAL;
> > +
> > +	for (hndlr = sec->image_load; hndlr->name; hndlr++) {
> > +		if (sysfs_streq(buf, hndlr->name)) {
> > +			ret = hndlr->load_image(sec);
> > +			break;
> > +		}
> > +	}
> > +
> > +	return ret ? : count;
> > +}
> > +static DEVICE_ATTR_WO(image_load);
> > +
> > +static struct attribute *m10bmc_control_attrs[] = {
> > +	&dev_attr_available_images.attr,
> > +	&dev_attr_image_load.attr,
> > +	NULL,
> > +};
> > +
> > +static struct attribute_group m10bmc_control_attr_group = {
> > +	.name = "control",
> > +	.attrs = m10bmc_control_attrs,
> > +};
> > +
> >  static ssize_t flash_count_show(struct device *dev,
> >  				struct device_attribute *attr, char *buf)  { @@
> -195,6 +251,7 @@
> > static struct attribute_group m10bmc_security_attr_group = {
> >
> >  static const struct attribute_group *m10bmc_sec_attr_groups[] = {
> >  	&m10bmc_security_attr_group,
> > +	&m10bmc_control_attr_group,
> >  	NULL,
> >  };
> >
> > @@ -208,6 +265,52 @@ static void log_error_regs(struct m10bmc_sec *sec,
> u32 doorbell)
> >  		dev_err(sec->dev, "RSU auth result: 0x%08x\n", auth_result);  }
> >
> > +static int m10bmc_sec_bmc_image_load(struct m10bmc_sec *sec,
> > +				     unsigned int val)
> > +{
> > +	u32 doorbell;
> > +	int ret;
> > +
> > +	if (val > 1) {
> > +		dev_err(sec->dev, "invalid reload val = %d\n", val);
> > +		return -EINVAL;
> > +	}
> > +
> > +	ret = m10bmc_sys_read(sec->m10bmc, M10BMC_DOORBELL,
> &doorbell);
> > +	if (ret)
> > +		return ret;
> > +
> > +	if (doorbell & DRBL_REBOOT_DISABLED)
> > +		return -EBUSY;
> > +
> > +	return m10bmc_sys_update_bits(sec->m10bmc, M10BMC_DOORBELL,
> > +				      DRBL_CONFIG_SEL | DRBL_REBOOT_REQ,
> > +				      FIELD_PREP(DRBL_CONFIG_SEL, val) |
> > +				      DRBL_REBOOT_REQ);
> > +}
> > +
> > +static int m10bmc_sec_bmc_image_load_0(struct m10bmc_sec *sec) {
> > +	return m10bmc_sec_bmc_image_load(sec, 0); }
> > +
> > +static int m10bmc_sec_bmc_image_load_1(struct m10bmc_sec *sec) {
> > +	return m10bmc_sec_bmc_image_load(sec, 1); }
> > +
> > +static struct image_load m10bmc_image_load_hndlrs[] = {
> > +	{
> > +		.name = "bmc_factory",
> > +		.load_image = m10bmc_sec_bmc_image_load_1,
> > +	},
> > +	{
> > +		.name = "bmc_user",
> > +		.load_image = m10bmc_sec_bmc_image_load_0,
> > +	},
> > +	{}
> > +};
> > +
> >  static enum fw_upload_err rsu_check_idle(struct m10bmc_sec *sec)  {
> >  	u32 doorbell;
> > @@ -565,6 +668,7 @@ static int m10bmc_sec_probe(struct platform_device
> *pdev)
> >  	sec->dev = &pdev->dev;
> >  	sec->m10bmc = dev_get_drvdata(pdev->dev.parent);
> >  	dev_set_drvdata(&pdev->dev, sec);
> > +	sec->image_load = m10bmc_image_load_hndlrs;
> >
> >  	ret = xa_alloc(&fw_upload_xa, &sec->fw_name_id, sec,
> >  		       xa_limit_32b, GFP_KERNEL);
> > --
> > 2.26.2

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v1 2/3] fpga: m10bmc-sec: add sysfs to load bmc images
  2022-07-11  6:24     ` Zhang, Tianfei
@ 2022-07-11  6:58       ` Xu Yilun
  0 siblings, 0 replies; 9+ messages in thread
From: Xu Yilun @ 2022-07-11  6:58 UTC (permalink / raw)
  To: Zhang, Tianfei
  Cc: mdf, lee.jones, Weight, Russell H, Wu, Hao, trix, linux-fpga

On Mon, Jul 11, 2022 at 02:24:01PM +0800, Zhang, Tianfei wrote:
> 
> 
> > -----Original Message-----
> > From: Xu, Yilun <yilun.xu@intel.com>
> > Sent: Thursday, July 7, 2022 10:00 AM
> > To: Zhang, Tianfei <tianfei.zhang@intel.com>
> > Cc: mdf@kernel.org; lee.jones@linaro.org; Weight, Russell H
> > <russell.h.weight@intel.com>; Wu, Hao <hao.wu@intel.com>;
> > trix@redhat.com; linux-fpga@vger.kernel.org
> > Subject: Re: [PATCH v1 2/3] fpga: m10bmc-sec: add sysfs to load bmc images
> >
> > On Tue, Jul 05, 2022 at 04:00:57AM -0400, Tianfei Zhang wrote:
> > > From: Russ Weight <russell.h.weight@intel.com>
> > >
> > > Add the available_images and image_load sysfs files. The
> > > available_images file returns a space separated list of key words that
> > > may be written into the image_load file. These keywords describe an
> > > FPGA, BMC, or firmware image in FLASH or EEPROM storage that may be
> > loaded.
> > >
> > > The image_load sysfs file may be written with a key word to trigger a
> > > reload of an FPGA, BMC, or firmware image from FLASH or EEPROM.
> > >
> > > Signed-off-by: Russ Weight <russell.h.weight@intel.com>
> > > Signed-off-by: Tianfei Zhang <tianfei.zhang@intel.com>
> > > ---
> > >  .../sysfs-driver-intel-m10-bmc-sec-update     |  21 ++++
> > >  drivers/fpga/intel-m10-bmc-sec-update.c       | 104 ++++++++++++++++++
> > >  2 files changed, 125 insertions(+)
> > >
> > > diff --git
> > > a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-sec-update
> > > b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-sec-update
> > > index 0a41afe0ab4c..8ded1a59d4db 100644
> > > --- a/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-sec-update
> > > +++ b/Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-sec-update
> > > @@ -59,3 +59,24 @@ Contact: Russ Weight
> > <russell.h.weight@intel.com>
> > >  Description:       Read only. Returns number of times the secure update
> > >             staging area has been flashed.
> > >             Format: "%u".
> > > +
> > > +What:              /sys/bus/platform/drivers/intel-m10bmc-sec-
> > update/.../control/available_images
> > > +Date:              July 2022
> > > +KernelVersion:  5.20
> > > +Contact:   Russ Weight <russell.h.weight@intel.com>
> > > +Description:       Read-only. This file returns a space separated list of
> > > +           key words that may be written into the image_load file
> > > +           described below. These keywords decribe an FPGA, BMC,
> > > +           or firmware image in FLASH or EEPROM storage that may
> > > +           be loaded.
> > > +
> > > +What:              /sys/bus/platform/drivers/intel-m10bmc-sec-
> > update/.../control/image_load
> > > +Date:              July 2022
> > > +KernelVersion:  5.20
> > > +Contact:   Russ Weight <russell.h.weight@intel.com>
> > > +Description:       Write-only. A key word may be written to this file to
> > > +           trigger a reload of an FPGA, BMC, or firmware image from
> >
> > A FPGA reprogramming could be handled by FPGA manager, so we may not
> > introduce a new API for the same purpose.
> 
> The FPGA reprogramming is in the MAX10 BMC Secure Update drive, which instantiates the new Firmware
> Upload functionality, like update the image into flash. Those functionalities have implemented by Russ's patchset.

As you can see, the firmware updating writes image to the backup flash,
not the FPGA region. It is not the FPGA reprograming. That's why we
introduced a separate interface for it.

> https://lore.kernel.org/linux-fpga/20220606160038.846236-1-russell.h.weight@intel.com/
> 
> This patch doesn't related to the FPGA reprogramming, it just do the FPGA/BMC image reload,

But this image reload interface does the FPGA reprogramming, as it
affects the real FPGA region, as well as the devices in the FPGA region.

Thanks,
Yilun

> and trigger the FPGA/BMC to reload a new image from different flash page. For example, on N3000 card, the
> FPGA image has 2 pages, page 0 for factory image, page 1 for user image. This patch was easy to select and
> trigger the FPGA to reload the image via sysfs file, like factory or user image.
> 
> I will change the title of patch change in next version patch:
> fpga: m10bmc-sec: add sysfs files to reload fpga/bmc images
> 
> >
> > Thanks,
> > Yilun
> >
> > > +           FLASH or EEPROM. Refer to the available_images file for a
> > > +           list of supported key words for the underlying device.
> > > +           Writing an unsupported string to this file will result in
> > > +           EINVAL being returned.
> > > diff --git a/drivers/fpga/intel-m10-bmc-sec-update.c
> > > b/drivers/fpga/intel-m10-bmc-sec-update.c
> > > index 72c677c910de..640690e6c131 100644
> > > --- a/drivers/fpga/intel-m10-bmc-sec-update.c
> > > +++ b/drivers/fpga/intel-m10-bmc-sec-update.c
> > > @@ -14,6 +14,8 @@
> > >  #include <linux/platform_device.h>
> > >  #include <linux/slab.h>
> > >
> > > +struct image_load;
> > > +
> > >  struct m10bmc_sec {
> > >     struct device *dev;
> > >     struct intel_m10bmc *m10bmc;
> > > @@ -21,6 +23,12 @@ struct m10bmc_sec {
> > >     char *fw_name;
> > >     u32 fw_name_id;
> > >     bool cancel_request;
> > > +   struct image_load *image_load;  /* terminated with { } member */
> > > +};
> > > +
> > > +struct image_load {
> > > +   const char *name;
> > > +   int (*load_image)(struct m10bmc_sec *sec);
> > >  };
> > >
> > >  static DEFINE_XARRAY_ALLOC(fw_upload_xa);
> > > @@ -137,6 +145,54 @@ DEVICE_ATTR_SEC_CSK_RO(pr, PR_PROG_ADDR +
> > > CSK_VEC_OFFSET);
> > >
> > >  #define FLASH_COUNT_SIZE 4096      /* count stored as inverted bit vector
> > */
> > >
> > > +static ssize_t available_images_show(struct device *dev,
> > > +                                struct device_attribute *attr, char *buf) {
> > > +   struct m10bmc_sec *sec = dev_get_drvdata(dev);
> > > +   const struct image_load *hndlr;
> > > +   ssize_t count = 0;
> > > +
> > > +   for (hndlr = sec->image_load; hndlr->name; hndlr++) {
> > > +           count += scnprintf(buf + count, PAGE_SIZE - count,
> > > +                              "%s ", hndlr->name);
> > > +   }
> > > +
> > > +   buf[count - 1] = '\n';
> > > +
> > > +   return count;
> > > +}
> > > +static DEVICE_ATTR_RO(available_images);
> > > +
> > > +static ssize_t image_load_store(struct device *dev,
> > > +                           struct device_attribute *attr,
> > > +                           const char *buf, size_t count)
> > > +{
> > > +   struct m10bmc_sec *sec = dev_get_drvdata(dev);
> > > +   const struct image_load *hndlr;
> > > +   int ret = -EINVAL;
> > > +
> > > +   for (hndlr = sec->image_load; hndlr->name; hndlr++) {
> > > +           if (sysfs_streq(buf, hndlr->name)) {
> > > +                   ret = hndlr->load_image(sec);
> > > +                   break;
> > > +           }
> > > +   }
> > > +
> > > +   return ret ? : count;
> > > +}
> > > +static DEVICE_ATTR_WO(image_load);
> > > +
> > > +static struct attribute *m10bmc_control_attrs[] = {
> > > +   &dev_attr_available_images.attr,
> > > +   &dev_attr_image_load.attr,
> > > +   NULL,
> > > +};
> > > +
> > > +static struct attribute_group m10bmc_control_attr_group = {
> > > +   .name = "control",
> > > +   .attrs = m10bmc_control_attrs,
> > > +};
> > > +
> > >  static ssize_t flash_count_show(struct device *dev,
> > >                             struct device_attribute *attr, char *buf)  { @@
> > -195,6 +251,7 @@
> > > static struct attribute_group m10bmc_security_attr_group = {
> > >
> > >  static const struct attribute_group *m10bmc_sec_attr_groups[] = {
> > >     &m10bmc_security_attr_group,
> > > +   &m10bmc_control_attr_group,
> > >     NULL,
> > >  };
> > >
> > > @@ -208,6 +265,52 @@ static void log_error_regs(struct m10bmc_sec *sec,
> > u32 doorbell)
> > >             dev_err(sec->dev, "RSU auth result: 0x%08x\n", auth_result);  }
> > >
> > > +static int m10bmc_sec_bmc_image_load(struct m10bmc_sec *sec,
> > > +                                unsigned int val)
> > > +{
> > > +   u32 doorbell;
> > > +   int ret;
> > > +
> > > +   if (val > 1) {
> > > +           dev_err(sec->dev, "invalid reload val = %d\n", val);
> > > +           return -EINVAL;
> > > +   }
> > > +
> > > +   ret = m10bmc_sys_read(sec->m10bmc, M10BMC_DOORBELL,
> > &doorbell);
> > > +   if (ret)
> > > +           return ret;
> > > +
> > > +   if (doorbell & DRBL_REBOOT_DISABLED)
> > > +           return -EBUSY;
> > > +
> > > +   return m10bmc_sys_update_bits(sec->m10bmc, M10BMC_DOORBELL,
> > > +                                 DRBL_CONFIG_SEL | DRBL_REBOOT_REQ,
> > > +                                 FIELD_PREP(DRBL_CONFIG_SEL, val) |
> > > +                                 DRBL_REBOOT_REQ);
> > > +}
> > > +
> > > +static int m10bmc_sec_bmc_image_load_0(struct m10bmc_sec *sec) {
> > > +   return m10bmc_sec_bmc_image_load(sec, 0); }
> > > +
> > > +static int m10bmc_sec_bmc_image_load_1(struct m10bmc_sec *sec) {
> > > +   return m10bmc_sec_bmc_image_load(sec, 1); }
> > > +
> > > +static struct image_load m10bmc_image_load_hndlrs[] = {
> > > +   {
> > > +           .name = "bmc_factory",
> > > +           .load_image = m10bmc_sec_bmc_image_load_1,
> > > +   },
> > > +   {
> > > +           .name = "bmc_user",
> > > +           .load_image = m10bmc_sec_bmc_image_load_0,
> > > +   },
> > > +   {}
> > > +};
> > > +
> > >  static enum fw_upload_err rsu_check_idle(struct m10bmc_sec *sec)  {
> > >     u32 doorbell;
> > > @@ -565,6 +668,7 @@ static int m10bmc_sec_probe(struct platform_device
> > *pdev)
> > >     sec->dev = &pdev->dev;
> > >     sec->m10bmc = dev_get_drvdata(pdev->dev.parent);
> > >     dev_set_drvdata(&pdev->dev, sec);
> > > +   sec->image_load = m10bmc_image_load_hndlrs;
> > >
> > >     ret = xa_alloc(&fw_upload_xa, &sec->fw_name_id, sec,
> > >                    xa_limit_32b, GFP_KERNEL);
> > > --
> > > 2.26.2

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2022-07-11  7:08 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-07-05  8:00 [PATCH v1 0/3] add Intel FPGA image loader support Tianfei Zhang
2022-07-05  8:00 ` [PATCH v1 1/3] mfd: intel-m10-bmc: add m10bmc_sys_update_bits API Tianfei Zhang
2022-07-05  8:00 ` [PATCH v1 2/3] fpga: m10bmc-sec: add sysfs to load bmc images Tianfei Zhang
2022-07-07  2:00   ` Xu Yilun
2022-07-11  6:24     ` Zhang, Tianfei
2022-07-11  6:58       ` Xu Yilun
2022-07-05  8:00 ` [PATCH v1 3/3] fpga: m10bmc-sec: add m10bmc_sec_retimer_load callback Tianfei Zhang
2022-07-07  2:05   ` Xu Yilun
2022-07-07  6:26     ` Zhang, Tianfei

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.