Re: [PATCH v1 1/1] mlxbf-bootctl: Add sysfs file for BlueField boot fifo

From: Hans de Goede
Date: Mon Apr 17 2023 - 04:18:32 EST


Hi,

On 4/11/23 17:39, Liming Sun wrote:
> This commit adds sysfs file for BlueField boot fifo. The boot
> fifo is usually used to push boot stream via USB or PCIe. Once
> OS is up, it can be reused by applications to read data or
> configuration from external host.
>
> Signed-off-by: Liming Sun <limings@xxxxxxxxxx>
> Reviewed-by: David Thompson <davthompson@xxxxxxxxxx>

Thank you for your patch, I've applied this patch to my review-hans
branch:
https://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git/log/?h=review-hans

Note it will show up in my review-hans branch once I've pushed my
local branch there, which might take a while.

Once I've run some tests on this branch the patches there will be
added to the platform-drivers-x86/for-next branch and eventually
will be included in the pdx86 pull-request to Linus for the next
merge-window.

Regards,

Hans



> ---
> .../testing/sysfs-platform-mellanox-bootctl | 7 ++
> drivers/platform/mellanox/mlxbf-bootctl.c | 68 +++++++++++++++++++
> 2 files changed, 75 insertions(+)
>
> diff --git a/Documentation/ABI/testing/sysfs-platform-mellanox-bootctl b/Documentation/ABI/testing/sysfs-platform-mellanox-bootctl
> index e79ca22e2f45..9b99a81babb1 100644
> --- a/Documentation/ABI/testing/sysfs-platform-mellanox-bootctl
> +++ b/Documentation/ABI/testing/sysfs-platform-mellanox-bootctl
> @@ -68,3 +68,10 @@ Description:
> Wasted burnt and invalid
> Invalid not burnt but marked as valid (error state).
> ======= ===============================================
> +
> +What: /sys/bus/platform/devices/MLNXBF04:00/bootfifo
> +Date: Apr 2023
> +KernelVersion: 6.4
> +Contact: "Liming Sun <limings@xxxxxxxxxx>"
> +Description:
> + The file used to access the BlueField boot fifo.
> diff --git a/drivers/platform/mellanox/mlxbf-bootctl.c b/drivers/platform/mellanox/mlxbf-bootctl.c
> index 1c7a288b59a5..d4463bb632e1 100644
> --- a/drivers/platform/mellanox/mlxbf-bootctl.c
> +++ b/drivers/platform/mellanox/mlxbf-bootctl.c
> @@ -10,6 +10,7 @@
>
> #include <linux/acpi.h>
> #include <linux/arm-smccc.h>
> +#include <linux/delay.h>
> #include <linux/module.h>
> #include <linux/platform_device.h>
>
> @@ -44,6 +45,10 @@ static const char * const mlxbf_bootctl_lifecycle_states[] = {
> [3] = "RMA",
> };
>
> +/* Mapped pointer for RSH_BOOT_FIFO_DATA and RSH_BOOT_FIFO_COUNT register. */
> +static void __iomem *mlxbf_rsh_boot_data;
> +static void __iomem *mlxbf_rsh_boot_cnt;
> +
> /* ARM SMC call which is atomic and no need for lock. */
> static int mlxbf_bootctl_smc(unsigned int smc_op, int smc_arg)
> {
> @@ -268,6 +273,45 @@ static const struct acpi_device_id mlxbf_bootctl_acpi_ids[] = {
>
> MODULE_DEVICE_TABLE(acpi, mlxbf_bootctl_acpi_ids);
>
> +static ssize_t mlxbf_bootctl_bootfifo_read(struct file *filp,
> + struct kobject *kobj,
> + struct bin_attribute *bin_attr,
> + char *buf, loff_t pos,
> + size_t count)
> +{
> + unsigned long timeout = msecs_to_jiffies(500);
> + unsigned long expire = jiffies + timeout;
> + u64 data, cnt = 0;
> + char *p = buf;
> +
> + while (count >= sizeof(data)) {
> + /* Give up reading if no more data within 500ms. */
> + if (!cnt) {
> + cnt = readq(mlxbf_rsh_boot_cnt);
> + if (!cnt) {
> + if (time_after(jiffies, expire))
> + break;
> + usleep_range(10, 50);
> + continue;
> + }
> + }
> +
> + data = readq(mlxbf_rsh_boot_data);
> + memcpy(p, &data, sizeof(data));
> + count -= sizeof(data);
> + p += sizeof(data);
> + cnt--;
> + expire = jiffies + timeout;
> + }
> +
> + return p - buf;
> +}
> +
> +static struct bin_attribute mlxbf_bootctl_bootfifo_sysfs_attr = {
> + .attr = { .name = "bootfifo", .mode = 0400 },
> + .read = mlxbf_bootctl_bootfifo_read,
> +};
> +
> static bool mlxbf_bootctl_guid_match(const guid_t *guid,
> const struct arm_smccc_res *res)
> {
> @@ -285,6 +329,16 @@ static int mlxbf_bootctl_probe(struct platform_device *pdev)
> guid_t guid;
> int ret;
>
> + /* Get the resource of the bootfifo data register. */
> + mlxbf_rsh_boot_data = devm_platform_ioremap_resource(pdev, 0);
> + if (IS_ERR(mlxbf_rsh_boot_data))
> + return PTR_ERR(mlxbf_rsh_boot_data);
> +
> + /* Get the resource of the bootfifo counter register. */
> + mlxbf_rsh_boot_cnt = devm_platform_ioremap_resource(pdev, 1);
> + if (IS_ERR(mlxbf_rsh_boot_cnt))
> + return PTR_ERR(mlxbf_rsh_boot_cnt);
> +
> /* Ensure we have the UUID we expect for this service. */
> arm_smccc_smc(MLXBF_BOOTCTL_SIP_SVC_UID, 0, 0, 0, 0, 0, 0, 0, &res);
> guid_parse(mlxbf_bootctl_svc_uuid_str, &guid);
> @@ -302,11 +356,25 @@ static int mlxbf_bootctl_probe(struct platform_device *pdev)
> if (ret < 0)
> dev_warn(&pdev->dev, "Unable to reset the EMMC boot mode\n");
>
> + ret = sysfs_create_bin_file(&pdev->dev.kobj,
> + &mlxbf_bootctl_bootfifo_sysfs_attr);
> + if (ret)
> + pr_err("Unable to create bootfifo sysfs file, error %d\n", ret);
> +
> + return ret;
> +}
> +
> +static int mlxbf_bootctl_remove(struct platform_device *pdev)
> +{
> + sysfs_remove_bin_file(&pdev->dev.kobj,
> + &mlxbf_bootctl_bootfifo_sysfs_attr);
> +
> return 0;
> }
>
> static struct platform_driver mlxbf_bootctl_driver = {
> .probe = mlxbf_bootctl_probe,
> + .remove = mlxbf_bootctl_remove,
> .driver = {
> .name = "mlxbf-bootctl",
> .dev_groups = mlxbf_bootctl_groups,