Re: [PATCH v4 8/9] bus: mhi: Expose DDR training data via controller sysfs
From: Manivannan Sadhasivam
Date: Mon Apr 13 2026 - 07:59:10 EST
On Thu, Mar 19, 2026 at 12:01:48PM +0530, Kishore Batta wrote:
> DDR training data captured during Sahara command mode needs to be
> accessible to userspace so it can be persisted and reused on subsequent
> boots. Currently, the training data is stored internally in the driver
> but has no external visibility once the sahara channel is torn down.
>
Maybe share some steps on how the userspace is expected to use this calibration
data.
> Expose the captured DDR training data via a read-only binary sysfs
> attribute on the MHI controller device. The sysfs file is created under
> the controller node, allowing userspace to read the training data even
> after the sahara channel device has been removed.
>
So once the calibration data is read, how it can be used further?
> The sysfs attribute reads directly from controller-scoped storage and
> relies on device managed resources for cleanup when the controller
> device is destroyed. No explicit sysfs removal is required, avoiding
> lifetime dependencies on the Sahara channel device.
>
Missing ABI documentation.
- Mani
> Signed-off-by: Kishore Batta <kishore.batta@xxxxxxxxxxxxxxxx>
> ---
> drivers/bus/mhi/sahara/sahara.c | 69 +++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 69 insertions(+)
>
> diff --git a/drivers/bus/mhi/sahara/sahara.c b/drivers/bus/mhi/sahara/sahara.c
> index c88f1220199ac4373d3552167870c19a0d5f23b9..b7208738df10fc3c3895acd46873412818dc1730 100644
> --- a/drivers/bus/mhi/sahara/sahara.c
> +++ b/drivers/bus/mhi/sahara/sahara.c
> @@ -415,6 +415,73 @@ static struct sahara_ctrl_trng_data *sahara_ctrl_trng_get(struct device *dev)
> return ct;
> }
>
> +static ssize_t ddr_training_data_read(struct file *filp, struct kobject *kobj,
> + const struct bin_attribute *attr, char *buf,
> + loff_t offset, size_t count)
> +{
> + struct device *dev = kobj_to_dev(kobj);
> + struct sahara_ctrl_trng_data *ct;
> + size_t available;
> +
> + ct = sahara_ctrl_trng_get(dev);
> + if (!ct)
> + return -ENODEV;
> +
> + mutex_lock(&ct->lock);
> +
> + /* No data yet or offset past end */
> + if (!ct->data || offset >= ct->size) {
> + mutex_unlock(&ct->lock);
> + return 0;
> + }
> +
> + available = ct->size - offset;
> + count = min(count, available);
> + memcpy(buf, (u8 *)ct->data + offset, count);
> +
> + mutex_unlock(&ct->lock);
> +
> + return count;
> +}
> +
> +static const struct bin_attribute ddr_training_data_attr = {
> + .attr = {
> + .name = "ddr_training_data",
> + .mode = 0444,
> + },
> + .read = ddr_training_data_read,
> +};
> +
> +static void sahara_sysfs_devres_release(struct device *dev, void *res)
> +{
> + device_remove_bin_file(dev, &ddr_training_data_attr);
> +}
> +
> +static void sahara_sysfs_create(struct mhi_device *mhi_dev)
> +{
> + struct device *dev = &mhi_dev->mhi_cntrl->mhi_dev->dev;
> + void *cookie;
> + int ret;
> +
> + if (devres_find(dev, sahara_sysfs_devres_release, NULL, NULL))
> + return;
> +
> + ret = device_create_bin_file(dev, &ddr_training_data_attr);
> + if (ret) {
> + dev_warn(&mhi_dev->dev,
> + "Failed to create DDR training sysfs node (%d)\n", ret);
> + return;
> + }
> +
> + cookie = devres_alloc(sahara_sysfs_devres_release, 1, GFP_KERNEL);
> + if (!cookie) {
> + device_remove_bin_file(dev, &ddr_training_data_attr);
> + return;
> + }
> +
> + devres_add(dev, cookie);
> +}
> +
> static int sahara_find_image(struct sahara_context *context, u32 image_id)
> {
> char *fw_path;
> @@ -1272,6 +1339,8 @@ static int sahara_mhi_probe(struct mhi_device *mhi_dev, const struct mhi_device_
> return ret;
> }
>
> + sahara_sysfs_create(mhi_dev);
> +
> return 0;
> }
>
>
> --
> 2.34.1
>
--
மணிவண்ணன் சதாசிவம்