RE: [PATCH v4] Bluetooth: btintel_pcie: Add vendor_rst PCI sysfs for PLDR
"Devegowda, Chandrashekar" <[email protected]>
| Newsgroups | org.kernel.vger.linux-bluetooth |
|---|---|
| Message-ID | <IA3PR11MB90160EE8F2DFC564ACE29AA1FCC02@IA3PR11MB9016.namprd11.prod.outlook.com> |
Hi Luiz
Thanks for the comments.
> -----Original Message-----
> From: Luiz Augusto von Dentz <[email protected]>
> Sent: Wednesday, July 22, 2026 9:13 PM
> To: Devegowda, Chandrashekar <[email protected]>
> Cc: [email protected]; [email protected]; Srivatsa,
> Ravishankar <[email protected]>; Tumkur Narayan, Chethan
> <[email protected]>; K, Kiran <[email protected]>
> Subject: Re: [PATCH v4] Bluetooth: btintel_pcie: Add vendor_rst PCI sysfs for
> PLDR
>
> Hi Chandru,
>
> On Tue, Jul 21, 2026 at 9:22 PM Chandrashekar Devegowda
> <[email protected]> wrote:
> >
> > Add a read-write sysfs entry at /sys/bus/pci/devices/<BDF>/vendor_rst
> > to allow userspace to trigger PLDR (Product Level Device Reset).
> > Reading the attribute displays supported reset types. Writing integer
> > 0 triggers PLDR. Any other input is rejected with -EINVAL and a
> > warning log.
> >
> > Signed-off-by: Chandrashekar Devegowda
> > <[email protected]>
> > ---
> > Changes in v4:
> > - Rebased on latest bluetooth-next (6f55ad8fb0ac) to fix
> > CI apply failure
> >
> > Changes in v3:
> > - Dropped reset_type parameter approach from hdev->reset()
> > - Directly call btintel_pcie_request_reset() instead of manual
> > flag manipulation and schedule_work()
> > - Accept only integer 0 for PLDR trigger
> > - Handle schedule_work() failure: release pci_dev_get refcount
> > and clear RECOVERY_IN_PROGRESS flag
> > - Fix remove ordering: device_remove_file before disable_work_sync
> >
> > Changes in v2:
> > - Added reset_type parameter to hdev->reset() callback (1/2)
> > - vendor_rst sysfs used reset_type to select PLDR (2/2)
> >
> > Changes in v1:
> > - Initial vendor_rst PCI sysfs implementation
> > drivers/bluetooth/btintel_pcie.c | 42
> +++++++++++++++++++++++++++++++-
> > 1 file changed, 41 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/bluetooth/btintel_pcie.c
> > b/drivers/bluetooth/btintel_pcie.c
> > index 2e28847263ab..a412ca7ff3ad 100644
> > --- a/drivers/bluetooth/btintel_pcie.c
> > +++ b/drivers/bluetooth/btintel_pcie.c
> > @@ -2781,7 +2781,10 @@ static void btintel_pcie_request_reset(struct
> btintel_pcie_data *data,
> > data->reset_type = type;
> >
> > pci_dev_get(data->pdev);
> > - schedule_work(&data->reset_work);
> > + if (!schedule_work(&data->reset_work)) {
> > + pci_dev_put(data->pdev);
> > + clear_bit(BTINTEL_PCIE_RECOVERY_IN_PROGRESS, &data->flags);
> > + }
> > }
> >
> > static void btintel_pcie_hci_reset(struct hci_dev *hdev) @@ -2791,6
> > +2794,36 @@ static void btintel_pcie_hci_reset(struct hci_dev *hdev)
> > btintel_pcie_request_reset(data, BTINTEL_PCIE_IOSF_PRR_FLR);
> > }
> >
> > +static ssize_t vendor_rst_store(struct device *dev,
> > + struct device_attribute *attr,
> > + const char *buf, size_t count) {
> > + unsigned int val;
> > + struct pci_dev *pdev = to_pci_dev(dev);
> > + struct btintel_pcie_data *data = pci_get_drvdata(pdev);
> > +
> > + if (!data || !data->hdev)
> > + return -ENODEV;
> > +
> > + if (kstrtouint(buf, 10, &val) || val != 0) {
> > + bt_dev_warn(data->hdev, "PLDR rejected: invalid input");
> > + return -EINVAL;
> > + }
> > +
> > + bt_dev_info(data->hdev, "PLDR triggered via sysfs");
> > + btintel_pcie_request_reset(data, BTINTEL_PCIE_IOSF_PRR_PLDR);
> > +
> > + return count;
> > +}
> > +
> > +static ssize_t vendor_rst_show(struct device *dev,
> > + struct device_attribute *attr, char
> > +*buf) {
> > + return sysfs_emit(buf, "0 - PLDR\n"); }
>
> Ok, so I assume this will be btintel_pcie only right? Not Bluetooth-wide? In
> that case you can call it pldr directly since it no longer need to generic and only
> applies to btintel_pcie driver.
>
This is only for btintel_pcie driver currently keeping it as integer so that it can be scaled further for top-silent reset.
> > +static DEVICE_ATTR_RW(vendor_rst);
> > +
> > static void btintel_pcie_hw_error(struct hci_dev *hdev, u8 code) {
> > struct btintel_pcie_dev_recovery *rec; @@ -3010,6 +3043,11 @@
> > static int btintel_pcie_probe(struct pci_dev *pdev,
> > if (err)
> > goto exit_error;
> >
> > + err = device_create_file(&pdev->dev, &dev_attr_vendor_rst);
> > + if (err)
> > + bt_dev_warn(data->hdev, "Failed to create vendor_rst sysfs (%d)",
> > + err);
> > +
> > bt_dev_dbg(data->hdev, "cnvi: 0x%8.8x cnvr: 0x%8.8x", data->cnvi,
> > data->cnvr);
> > return 0;
> > @@ -3046,6 +3084,8 @@ static void btintel_pcie_remove(struct pci_dev
> *pdev)
> > disable_work_sync(&data->hwexp_work);
> > disable_work_sync(&data->fwtrigger_work);
> >
> > + device_remove_file(&pdev->dev, &dev_attr_vendor_rst);
> > +
> > /* Cancel pending reset work. Skip only when remove() is called from
> > * within the reset work itself (PLDR device_reprobe path) to avoid
> > * deadlock. current_work() returns the work_struct of the
> > caller if
> > --
> > 2.43.0
> >
>
>
> --
> Luiz Augusto von Dentz