On Wed, Aug 25, 2021 at 04:51:35PM +0300, Yishai Hadas wrote: > From: Max Gurtovoy <mgurtovoy@xxxxxxxxxx> > > Add 'override_only' field to struct pci_device_id to be used as part of > pci_match_device(). > > When set, it means that matching is true only when dev->driver_override > is this driver. Maybe: When set, a driver only matches the entry when dev->driver_override is set to that driver. > In addition, add a helper macro named 'PCI_DEVICE_DRIVER_OVERRIDE' to > enable setting some data on it. > > Next patch from this series will use the above functionality. > > Signed-off-by: Max Gurtovoy <mgurtovoy@xxxxxxxxxx> > Signed-off-by: Jason Gunthorpe <jgg@xxxxxxxxxx> > Signed-off-by: Yishai Hadas <yishaih@xxxxxxxxxx> Acked-by: Bjorn Helgaas <bhelgaas@xxxxxxxxxx> > --- > Documentation/PCI/pci.rst | 1 + > drivers/pci/pci-driver.c | 28 +++++++++++++++++++++------- > include/linux/mod_devicetable.h | 2 ++ > include/linux/pci.h | 15 +++++++++++++++ > 4 files changed, 39 insertions(+), 7 deletions(-) > > diff --git a/Documentation/PCI/pci.rst b/Documentation/PCI/pci.rst > index fa651e25d98c..87c6f4a6ca32 100644 > --- a/Documentation/PCI/pci.rst > +++ b/Documentation/PCI/pci.rst > @@ -103,6 +103,7 @@ need pass only as many optional fields as necessary: > - subvendor and subdevice fields default to PCI_ANY_ID (FFFFFFFF) > - class and classmask fields default to 0 > - driver_data defaults to 0UL. > + - override_only field defaults to 0. > > Note that driver_data must match the value used by any of the pci_device_id > entries defined in the driver. This makes the driver_data field mandatory > diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c > index 3a72352aa5cf..123c590ebe1d 100644 > --- a/drivers/pci/pci-driver.c > +++ b/drivers/pci/pci-driver.c > @@ -136,7 +136,7 @@ static const struct pci_device_id *pci_match_device(struct pci_driver *drv, > struct pci_dev *dev) > { > struct pci_dynid *dynid; > - const struct pci_device_id *found_id = NULL; > + const struct pci_device_id *found_id = NULL, *ids; > > /* When driver_override is set, only bind to the matching driver */ > if (dev->driver_override && strcmp(dev->driver_override, drv->name)) > @@ -152,14 +152,28 @@ static const struct pci_device_id *pci_match_device(struct pci_driver *drv, > } > spin_unlock(&drv->dynids.lock); > > - if (!found_id) > - found_id = pci_match_id(drv->id_table, dev); > + if (found_id) > + return found_id; > > - /* driver_override will always match, send a dummy id */ > - if (!found_id && dev->driver_override) > - found_id = &pci_device_id_any; > + for (ids = drv->id_table; (found_id = pci_match_id(ids, dev)); > + ids = found_id + 1) { > + /* > + * The match table is split based on driver_override. > + * In case override_only was set, enforce driver_override > + * matching. > + */ > + if (found_id->override_only) { > + if (dev->driver_override) > + return found_id; > + } else { > + return found_id; > + } > + } > > - return found_id; > + /* driver_override will always match, send a dummy id */ > + if (dev->driver_override) > + return &pci_device_id_any; > + return NULL; > } > > /** > diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h > index 8e291cfdaf06..2e3ba6d9ece0 100644 > --- a/include/linux/mod_devicetable.h > +++ b/include/linux/mod_devicetable.h > @@ -34,12 +34,14 @@ typedef unsigned long kernel_ulong_t; > * Best practice is to use driver_data as an index > * into a static list of equivalent device types, > * instead of using it as a pointer. > + * @override_only: Match only when dev->driver_override is this driver. > */ > struct pci_device_id { > __u32 vendor, device; /* Vendor and device ID or PCI_ANY_ID*/ > __u32 subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */ > __u32 class, class_mask; /* (class,subclass,prog-if) triplet */ > kernel_ulong_t driver_data; /* Data private to the driver */ > + __u32 override_only; > }; > > > diff --git a/include/linux/pci.h b/include/linux/pci.h > index 540b377ca8f6..0506b1a8c921 100644 > --- a/include/linux/pci.h > +++ b/include/linux/pci.h > @@ -901,6 +901,21 @@ struct pci_driver { > .vendor = (vend), .device = (dev), \ > .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID > > +/** > + * PCI_DEVICE_DRIVER_OVERRIDE - macro used to describe a PCI device with > + * override_only flags. > + * @vend: the 16 bit PCI Vendor ID > + * @dev: the 16 bit PCI Device ID > + * @driver_override: the 32 bit PCI Device override_only > + * > + * This macro is used to create a struct pci_device_id that matches only a > + * driver_override device. The subvendor and subdevice fields will be set to > + * PCI_ANY_ID. > + */ > +#define PCI_DEVICE_DRIVER_OVERRIDE(vend, dev, driver_override) \ > + .vendor = (vend), .device = (dev), .subvendor = PCI_ANY_ID, \ > + .subdevice = PCI_ANY_ID, .override_only = (driver_override) > + > /** > * PCI_DEVICE_SUB - macro used to describe a specific PCI device with subsystem > * @vend: the 16 bit PCI Vendor ID > -- > 2.18.1 >