Re: [PATCH v4] Bluetooth: btintel_pcie: Add vendor_rst PCI sysfs for PLDR
Luiz Augusto von Dentz <[email protected]>
| Newsgroups | org.kernel.vger.linux-bluetooth |
|---|---|
| Message-ID | <CABBYNZJ6NM55ykYVrMxx-HLZOPC53bZrBzXWhjQnZ7gKSEwNWw@mail.gmail.com> |
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. > +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