Re: [PATCH v5 7/7] bus: mhi: Expose DDR training data via controller sysfs
Kishore Batta <[email protected]> Wed, 1 Jul 2026 16:06:26 +0530
| Newsgroups | dev.linux.lists.mhi,org.freedesktop.lists.dri-devel,org.kernel.vger.linux-arm-msm,org.kernel.vger.linux-doc,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
On 5/12/2026 7:49 PM, Manivannan Sadhasivam wrote: > On Thu, Apr 16, 2026 at 07:39: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. >> >> 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 | 69 ++++++++++++++++++++++ >> 2 files changed, 88 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..fef5dc1d8884133397d204f23361584fd1d9b075 100644 >> --- a/drivers/bus/mhi/host/clients/sahara/sahara.c >> +++ b/drivers/bus/mhi/host/clients/sahara/sahara.c >> @@ -273,6 +273,73 @@ 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 const struct bin_attribute ddr_training_data_attr = { >> + .attr = { >> + .name = "ddr_training_data", >> + .mode = 0444, >> + }, >> + .read = ddr_training_data_read, >> +}; > You can simplify the attribute creation with BIN_ATTR_RO(). ACK. Will use BIN_ATTR_RO() in v6 patch series. > >> + >> +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; > So you are expecting this helper to be called mutiple times without teardown? > > - Mani Yes. This helper can be invoked multiple times for the same controller device without a full teardown. In this case, Sahara probe can be re-entered across events like subsystem restart/warm resets, while underlying controller device(mhi_cntrl->mhi_dev->dev) persists and is not re-created. Since this sysfs node is associated with the controller device (not a single probe instance), it should only be created once per controller lifetime. The devres_find() check is used to make the helper idempotent and avoid duplicate sysfs creation when probe path is re-entered. The sysfs lifetime is intentionally tied to the controller device, so it is only removed when the device itself is released.