diff options
| -rw-r--r-- | drivers/pci/quirks.c | 12 | ||||
| -rw-r--r-- | include/linux/pci.h | 63 | 
2 files changed, 59 insertions, 16 deletions
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index fb544d6d29f..2b4b1ea158c 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2961,17 +2961,19 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq);  static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,  			  struct pci_fixup *end)  { -	while (f < end) { -		if ((f->vendor == dev->vendor || f->vendor == (u16) PCI_ANY_ID) && -		    (f->device == dev->device || f->device == (u16) PCI_ANY_ID)) { +	for (; f < end; f++) +		if ((f->class == (u32) (dev->class >> f->class_shift) || +		     f->class == (u32) PCI_ANY_ID) && +		    (f->vendor == dev->vendor || +		     f->vendor == (u16) PCI_ANY_ID) && +		    (f->device == dev->device || +		     f->device == (u16) PCI_ANY_ID)) {  			dev_dbg(&dev->dev, "calling %pF\n", f->hook);  			if (initcall_debug)  				do_one_fixup_debug(f->hook, dev);  			else  				f->hook(dev);  		} -		f++; -	}  }  extern struct pci_fixup __start_pci_fixups_early[]; diff --git a/include/linux/pci.h b/include/linux/pci.h index be58a51706c..74a20bdc93f 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1382,7 +1382,10 @@ static inline void pci_resource_to_user(const struct pci_dev *dev, int bar,   */  struct pci_fixup { -	u16 vendor, device;	/* You can use PCI_ANY_ID here of course */ +	u16 vendor;		/* You can use PCI_ANY_ID here of course */ +	u16 device;		/* You can use PCI_ANY_ID here of course */ +	u32 class;		/* You can use PCI_ANY_ID here too */ +	unsigned int class_shift;	/* should be 0, 8, 16 */  	void (*hook)(struct pci_dev *dev);  }; @@ -1397,30 +1400,68 @@ enum pci_fixup_pass {  };  /* Anonymous variables would be nice... */ -#define DECLARE_PCI_FIXUP_SECTION(section, name, vendor, device, hook)	\ -	static const struct pci_fixup __pci_fixup_##name __used		\ -	__attribute__((__section__(#section))) = { vendor, device, hook }; +#define DECLARE_PCI_FIXUP_SECTION(section, name, vendor, device, class,	\ +				  class_shift, hook)			\ +	static const struct pci_fixup const __pci_fixup_##name __used	\ +	__attribute__((__section__(#section), aligned((sizeof(void *)))))    \ +		= { vendor, device, class, class_shift, hook }; + +#define DECLARE_PCI_FIXUP_CLASS_EARLY(vendor, device, class,		\ +					 class_shift, hook)		\ +	DECLARE_PCI_FIXUP_SECTION(.pci_fixup_early,			\ +		vendor##device##hook, vendor, device, class, class_shift, hook) +#define DECLARE_PCI_FIXUP_CLASS_HEADER(vendor, device, class,		\ +					 class_shift, hook)		\ +	DECLARE_PCI_FIXUP_SECTION(.pci_fixup_header,			\ +		vendor##device##hook, vendor, device, class, class_shift, hook) +#define DECLARE_PCI_FIXUP_CLASS_FINAL(vendor, device, class,		\ +					 class_shift, hook)		\ +	DECLARE_PCI_FIXUP_SECTION(.pci_fixup_final,			\ +		vendor##device##hook, vendor, device, class, class_shift, hook) +#define DECLARE_PCI_FIXUP_CLASS_ENABLE(vendor, device, class,		\ +					 class_shift, hook)		\ +	DECLARE_PCI_FIXUP_SECTION(.pci_fixup_enable,			\ +		vendor##device##hook, vendor, device, class, class_shift, hook) +#define DECLARE_PCI_FIXUP_CLASS_RESUME(vendor, device, class,		\ +					 class_shift, hook)		\ +	DECLARE_PCI_FIXUP_SECTION(.pci_fixup_resume,			\ +		resume##vendor##device##hook, vendor, device, class,	\ +		class_shift, hook) +#define DECLARE_PCI_FIXUP_CLASS_RESUME_EARLY(vendor, device, class,	\ +					 class_shift, hook)		\ +	DECLARE_PCI_FIXUP_SECTION(.pci_fixup_resume_early,		\ +		resume_early##vendor##device##hook, vendor, device,	\ +		class, class_shift, hook) +#define DECLARE_PCI_FIXUP_CLASS_SUSPEND(vendor, device, class,		\ +					 class_shift, hook)		\ +	DECLARE_PCI_FIXUP_SECTION(.pci_fixup_suspend,			\ +		suspend##vendor##device##hook, vendor, device, class,	\ +		class_shift, hook) +  #define DECLARE_PCI_FIXUP_EARLY(vendor, device, hook)			\  	DECLARE_PCI_FIXUP_SECTION(.pci_fixup_early,			\ -			vendor##device##hook, vendor, device, hook) +		vendor##device##hook, vendor, device, PCI_ANY_ID, 0, hook)  #define DECLARE_PCI_FIXUP_HEADER(vendor, device, hook)			\  	DECLARE_PCI_FIXUP_SECTION(.pci_fixup_header,			\ -			vendor##device##hook, vendor, device, hook) +		vendor##device##hook, vendor, device, PCI_ANY_ID, 0, hook)  #define DECLARE_PCI_FIXUP_FINAL(vendor, device, hook)			\  	DECLARE_PCI_FIXUP_SECTION(.pci_fixup_final,			\ -			vendor##device##hook, vendor, device, hook) +		vendor##device##hook, vendor, device, PCI_ANY_ID, 0, hook)  #define DECLARE_PCI_FIXUP_ENABLE(vendor, device, hook)			\  	DECLARE_PCI_FIXUP_SECTION(.pci_fixup_enable,			\ -			vendor##device##hook, vendor, device, hook) +		vendor##device##hook, vendor, device, PCI_ANY_ID, 0, hook)  #define DECLARE_PCI_FIXUP_RESUME(vendor, device, hook)			\  	DECLARE_PCI_FIXUP_SECTION(.pci_fixup_resume,			\ -			resume##vendor##device##hook, vendor, device, hook) +		resume##vendor##device##hook, vendor, device,		\ +		PCI_ANY_ID, 0, hook)  #define DECLARE_PCI_FIXUP_RESUME_EARLY(vendor, device, hook)		\  	DECLARE_PCI_FIXUP_SECTION(.pci_fixup_resume_early,		\ -			resume_early##vendor##device##hook, vendor, device, hook) +		resume_early##vendor##device##hook, vendor, device,	\ +		PCI_ANY_ID, 0, hook)  #define DECLARE_PCI_FIXUP_SUSPEND(vendor, device, hook)			\  	DECLARE_PCI_FIXUP_SECTION(.pci_fixup_suspend,			\ -			suspend##vendor##device##hook, vendor, device, hook) +		suspend##vendor##device##hook, vendor, device,		\ +		PCI_ANY_ID, 0, hook)  #ifdef CONFIG_PCI_QUIRKS  void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev);  |