Skip to content

Commit ac04840

Browse files
l1kdjbw
authored andcommitted
PCI/DOE: Create mailboxes on device enumeration
Currently a DOE instance cannot be shared by multiple drivers because each driver creates its own pci_doe_mb struct for a given DOE instance. For the same reason a DOE instance cannot be shared between the PCI core and a driver. Moreover, finding out which protocols a DOE instance supports requires creating a pci_doe_mb for it. If a device has multiple DOE instances, a driver looking for a specific protocol may need to create a pci_doe_mb for each of the device's DOE instances and then destroy those which do not support the desired protocol. That's obviously an inefficient way to do things. Overcome these issues by creating mailboxes in the PCI core on device enumeration. Provide a pci_find_doe_mailbox() API call to allow drivers to get a pci_doe_mb for a given (pci_dev, vendor, protocol) triple. This API is modeled after pci_find_capability() and can later be amended with a pci_find_next_doe_mailbox() call to iterate over all mailboxes of a given pci_dev which support a specific protocol. On removal, destroy the mailboxes in pci_destroy_dev(), after the driver is unbound. This allows drivers to use DOE in their ->remove() hook. On surprise removal, cancel ongoing DOE exchanges and prevent new ones from being scheduled. Thereby ensure that a hot-removed device doesn't needlessly wait for a running exchange to time out. Tested-by: Ira Weiny <ira.weiny@intel.com> Signed-off-by: Lukas Wunner <lukas@wunner.de> Reviewed-by: Ming Li <ming4.li@intel.com> Reviewed-by: Ira Weiny <ira.weiny@intel.com> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Acked-by: Bjorn Helgaas <bhelgaas@google.com> Link: https://lore.kernel.org/r/40a6f973f72ef283d79dd55e7e6fddc7481199af.1678543498.git.lukas@wunner.de Signed-off-by: Dan Williams <dan.j.williams@intel.com>
1 parent 022b66f commit ac04840

6 files changed

Lines changed: 91 additions & 0 deletions

File tree

drivers/pci/doe.c

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#include <linux/pci-doe.h>
2121
#include <linux/workqueue.h>
2222

23+
#include "pci.h"
24+
2325
#define PCI_DOE_PROTOCOL_DISCOVERY 0
2426

2527
/* Timeout of 1 second from 6.30.2 Operation, PCI Spec r6.0 */
@@ -658,3 +660,74 @@ int pci_doe(struct pci_doe_mb *doe_mb, u16 vendor, u8 type,
658660
return task.rv;
659661
}
660662
EXPORT_SYMBOL_GPL(pci_doe);
663+
664+
/**
665+
* pci_find_doe_mailbox() - Find Data Object Exchange mailbox
666+
*
667+
* @pdev: PCI device
668+
* @vendor: Vendor ID
669+
* @type: Data Object Type
670+
*
671+
* Find first DOE mailbox of a PCI device which supports the given protocol.
672+
*
673+
* RETURNS: Pointer to the DOE mailbox or NULL if none was found.
674+
*/
675+
struct pci_doe_mb *pci_find_doe_mailbox(struct pci_dev *pdev, u16 vendor,
676+
u8 type)
677+
{
678+
struct pci_doe_mb *doe_mb;
679+
unsigned long index;
680+
681+
xa_for_each(&pdev->doe_mbs, index, doe_mb)
682+
if (pci_doe_supports_prot(doe_mb, vendor, type))
683+
return doe_mb;
684+
685+
return NULL;
686+
}
687+
EXPORT_SYMBOL_GPL(pci_find_doe_mailbox);
688+
689+
void pci_doe_init(struct pci_dev *pdev)
690+
{
691+
struct pci_doe_mb *doe_mb;
692+
u16 offset = 0;
693+
int rc;
694+
695+
xa_init(&pdev->doe_mbs);
696+
697+
while ((offset = pci_find_next_ext_capability(pdev, offset,
698+
PCI_EXT_CAP_ID_DOE))) {
699+
doe_mb = pci_doe_create_mb(pdev, offset);
700+
if (IS_ERR(doe_mb)) {
701+
pci_err(pdev, "[%x] failed to create mailbox: %ld\n",
702+
offset, PTR_ERR(doe_mb));
703+
continue;
704+
}
705+
706+
rc = xa_insert(&pdev->doe_mbs, offset, doe_mb, GFP_KERNEL);
707+
if (rc) {
708+
pci_err(pdev, "[%x] failed to insert mailbox: %d\n",
709+
offset, rc);
710+
pci_doe_destroy_mb(doe_mb);
711+
}
712+
}
713+
}
714+
715+
void pci_doe_destroy(struct pci_dev *pdev)
716+
{
717+
struct pci_doe_mb *doe_mb;
718+
unsigned long index;
719+
720+
xa_for_each(&pdev->doe_mbs, index, doe_mb)
721+
pci_doe_destroy_mb(doe_mb);
722+
723+
xa_destroy(&pdev->doe_mbs);
724+
}
725+
726+
void pci_doe_disconnected(struct pci_dev *pdev)
727+
{
728+
struct pci_doe_mb *doe_mb;
729+
unsigned long index;
730+
731+
xa_for_each(&pdev->doe_mbs, index, doe_mb)
732+
pci_doe_cancel_tasks(doe_mb);
733+
}

drivers/pci/pci.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,16 @@ struct pci_sriov {
318318
bool drivers_autoprobe; /* Auto probing of VFs by driver */
319319
};
320320

321+
#ifdef CONFIG_PCI_DOE
322+
void pci_doe_init(struct pci_dev *pdev);
323+
void pci_doe_destroy(struct pci_dev *pdev);
324+
void pci_doe_disconnected(struct pci_dev *pdev);
325+
#else
326+
static inline void pci_doe_init(struct pci_dev *pdev) { }
327+
static inline void pci_doe_destroy(struct pci_dev *pdev) { }
328+
static inline void pci_doe_disconnected(struct pci_dev *pdev) { }
329+
#endif
330+
321331
/**
322332
* pci_dev_set_io_state - Set the new error state if possible.
323333
*
@@ -354,6 +364,7 @@ static inline bool pci_dev_set_io_state(struct pci_dev *dev,
354364
static inline int pci_dev_set_disconnected(struct pci_dev *dev, void *unused)
355365
{
356366
pci_dev_set_io_state(dev, pci_channel_io_perm_failure);
367+
pci_doe_disconnected(dev);
357368

358369
return 0;
359370
}

drivers/pci/probe.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2479,6 +2479,7 @@ static void pci_init_capabilities(struct pci_dev *dev)
24792479
pci_aer_init(dev); /* Advanced Error Reporting */
24802480
pci_dpc_init(dev); /* Downstream Port Containment */
24812481
pci_rcec_init(dev); /* Root Complex Event Collector */
2482+
pci_doe_init(dev); /* Data Object Exchange */
24822483

24832484
pcie_report_downtraining(dev);
24842485
pci_init_reset_methods(dev);

drivers/pci/remove.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ static void pci_destroy_dev(struct pci_dev *dev)
3939
list_del(&dev->bus_list);
4040
up_write(&pci_bus_sem);
4141

42+
pci_doe_destroy(dev);
4243
pcie_aspm_exit_link_state(dev);
4344
pci_bridge_d3_update(dev);
4445
pci_free_resources(dev);

include/linux/pci-doe.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ struct pci_doe_mb;
2929

3030
struct pci_doe_mb *pcim_doe_create_mb(struct pci_dev *pdev, u16 cap_offset);
3131
bool pci_doe_supports_prot(struct pci_doe_mb *doe_mb, u16 vid, u8 type);
32+
struct pci_doe_mb *pci_find_doe_mailbox(struct pci_dev *pdev, u16 vendor,
33+
u8 type);
3234

3335
int pci_doe(struct pci_doe_mb *doe_mb, u16 vendor, u8 type,
3436
const void *request, size_t request_sz,

include/linux/pci.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,9 @@ struct pci_dev {
511511
#endif
512512
#ifdef CONFIG_PCI_P2PDMA
513513
struct pci_p2pdma __rcu *p2pdma;
514+
#endif
515+
#ifdef CONFIG_PCI_DOE
516+
struct xarray doe_mbs; /* Data Object Exchange mailboxes */
514517
#endif
515518
u16 acs_cap; /* ACS Capability offset */
516519
phys_addr_t rom; /* Physical address if not from BAR */

0 commit comments

Comments
 (0)