Message ID | 52b0b00dacbc4aad3169dd3667d79c85e334783b.1680657571.git.limings@nvidia.com (mailing list archive) |
---|---|
State | Accepted, archived |
Headers | show |
Series | [v1,1/1] mlxbf-bootctl: Add sysfs file for BlueField boot fifo | expand |
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@nvidia.com> > Reviewed-by: David Thompson <davthompson@nvidia.com> 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@nvidia.com>" > +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,
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@nvidia.com>" +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,