On Wed, Jul 01, 2026 at 04:07:41PM +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.
> 
> Expose the captured DDR training data via a read-only binary sysfs
> attribute on the MHI controller device:
> 
> /sys/bus/mhi/devices/<mhi_cntrl>/ddr_training_data
> 
> The sysfs read callback serves data directly from controller scoped storage
> and protects access with the controller training data lock. The attribute
> lifetime is tied to the controller device via devres, allowing the data to
> remain readable after Sahara channel teardown and ensuring automatic
> cleanup when controller device is removed.
> 
> Userspace flow:
> 1. For each controller device, userspace reads the ddr_training_data sysfs
>    attribute.
> 2. If the read returns non-zero data, userspace persists it using a
>    serial specific filename (for example, mdmddr_0x<serial_no>.mbn).
> 3. On subsequent boots, the Sahara driver attempts to load this serial
>    specific DDR training image before falling back to the default
>    training image, restoring DDR calibration data and avoiding retraining.
> 
> Add ABI documentation for the DDR training data sysfs attribute exposed by
> Sahara MHI driver.
> 
> Signed-off-by: Kishore Batta <[email protected]>
> ---
>  .../ABI/testing/sysfs-bus-mhi-ddr_training_data    | 19 +++++++
>  drivers/bus/mhi/host/clients/sahara/sahara.c       | 62 
> ++++++++++++++++++++++
>  2 files changed, 81 insertions(+)
> 
> diff --git a/Documentation/ABI/testing/sysfs-bus-mhi-ddr_training_data 
> b/Documentation/ABI/testing/sysfs-bus-mhi-ddr_training_data
> new file mode 100644
> index 
> 0000000000000000000000000000000000000000..810b487b5a5fdba133d81255f9879844e3938a10
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-bus-mhi-ddr_training_data
> @@ -0,0 +1,19 @@
> +What:                   /sys/bus/mhi/devices/<mhi-cntrl>/ddr_training_data
> +
> +Date:                   March 2026
> +
> +Contact:                Kishore Batta <[email protected]>
> +
> +Description:            Contains the DDR training data for the Qualcomm 
> device
> +                        connected. MHI driver populates different controller
> +                        nodes for each device. The DDR training data is 
> exposed
> +                        to userspace to read and save the training data file 
> to
> +                        the filesystem. In the subsequent boot up of the 
> device,
> +                        the training data is restored from host to device
> +                        optimizing the boot up time of the device.
> +
> +Usage:                  Example for reading DDR training data:
> +                        cat /sys/bus/mhi/devices/mhi0/ddr_training_data
> +
> +Permissions:            The file permissions are set to 0444 allowing read
> +                        access.
> diff --git a/drivers/bus/mhi/host/clients/sahara/sahara.c 
> b/drivers/bus/mhi/host/clients/sahara/sahara.c
> index 
> 07bc743aa061dd2fa85638067d494562152474e3..72ac751c302a98448b5756c9feb438647bd0ce4b
>  100644
> --- a/drivers/bus/mhi/host/clients/sahara/sahara.c
> +++ b/drivers/bus/mhi/host/clients/sahara/sahara.c
> @@ -273,6 +273,66 @@ static struct sahara_cntrl_training_data 
> *sahara_cntrl_training_get(struct devic
>       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_cntrl_training_data *ct;
> +     size_t available;
> +
> +     ct = sahara_cntrl_training_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 BIN_ATTR_RO(ddr_training_data, 0);
> +
> +static void sahara_sysfs_devres_release(struct device *dev, void *res)
> +{
> +     device_remove_bin_file(dev, &bin_attr_ddr_training_data);
> +}
> +
> +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;
> +

I think I asked this question before, but didn't follow up. This attribute
should be tied to the SAHARA channel, not the controller. There is no reason for
it to be available when the channel is gone.

- Mani

-- 
மணிவண்ணன் சதாசிவம்

Reply via email to