From b9443f401bb20ae6414e3e68bca0413bad28b689 Mon Sep 17 00:00:00 2001 From: Feng Tang Date: Thu, 23 Aug 2012 15:45:03 +0800 Subject: PCI: Use pci_device_id on stack for pci_get_subsys/class() to avoid kmalloc This fixes a kernel warning https://lkml.org/lkml/2012/7/31/682 pci_get_subsys() may get called in late system reboot stage, using a sleepable kmalloc() sounds fragile and will cause a kernel warning with my recent commmit 55c844a "x86/reboot: Fix a warning message triggered by stop_other_cpus()" which disable local interrupt in late system shutdown/reboot phase. Using a local parameter instead will fix it and make it eligible for calling from atomic context. Do the same change for the pci_get_class() as suggested by Bjorn Helgaas. Initializing the on-stack struct pci_device_id suggested by Fengguang Wu and Jiri Slaby. Section 6.7.8 of the C99 standard guarantees that when we initialize some of the struct members, the rest of the struct is implicitly initialized the same as objects with static storage duration, i.e., to zero in this case. [bhelgaas: changelog, incorporate Fengguang/Jiri initialization fix] Bisected-by: Fengguang Wu Signed-off-by: Feng Tang Signed-off-by: Jiri Slaby Signed-off-by: Bjorn Helgaas Reviewed-by: Fengguang Wu --- drivers/pci/search.c | 44 +++++++++++++++++--------------------------- 1 file changed, 17 insertions(+), 27 deletions(-) (limited to 'drivers/pci/search.c') diff --git a/drivers/pci/search.c b/drivers/pci/search.c index 993d4a0a2469..9148b6e8056b 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -245,8 +245,12 @@ struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device, unsigned int ss_vendor, unsigned int ss_device, struct pci_dev *from) { - struct pci_dev *pdev; - struct pci_device_id *id; + struct pci_device_id id = { + .vendor = vendor, + .device = device, + .subvendor = ss_vendor, + .subdevice = ss_device, + }; /* * pci_find_subsys() can be called on the ide_setup() path, @@ -257,18 +261,7 @@ struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device, if (unlikely(no_pci_devices())) return NULL; - id = kzalloc(sizeof(*id), GFP_KERNEL); - if (!id) - return NULL; - id->vendor = vendor; - id->device = device; - id->subvendor = ss_vendor; - id->subdevice = ss_device; - - pdev = pci_get_dev_by_id(id, from); - kfree(id); - - return pdev; + return pci_get_dev_by_id(&id, from); } /** @@ -307,19 +300,16 @@ pci_get_device(unsigned int vendor, unsigned int device, struct pci_dev *from) */ struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from) { - struct pci_dev *dev; - struct pci_device_id *id; - - id = kzalloc(sizeof(*id), GFP_KERNEL); - if (!id) - return NULL; - id->vendor = id->device = id->subvendor = id->subdevice = PCI_ANY_ID; - id->class_mask = PCI_ANY_ID; - id->class = class; - - dev = pci_get_dev_by_id(id, from); - kfree(id); - return dev; + struct pci_device_id id = { + .vendor = PCI_ANY_ID, + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .class_mask = PCI_ANY_ID, + .class = class, + }; + + return pci_get_dev_by_id(&id, from); } /** -- cgit v1.2.3 From e9bf1040f649d89db3c2e060d1b0b56665a4fb93 Mon Sep 17 00:00:00 2001 From: Feng Tang Date: Thu, 23 Aug 2012 15:45:47 +0800 Subject: PCI: Remove the obsolete no_pci_devices() check In function pci_get_subsys() there is a check: /* * pci_find_subsys() can be called on the ide_setup() path, * super-early in boot. But the down_read() will enable local * interrupts, which can cause some machines to crash. So here we * detect and flag that situation and bail out early. */ if (unlikely(no_pci_devices())) return NULL; But there is no ide_setup() now, and no down_read() either, which makes the check obsolete. So remove it. Signed-off-by: Feng Tang Signed-off-by: Bjorn Helgaas Cc: Andrew Morton Cc: Greg Kroah-Hartman --- drivers/pci/search.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'drivers/pci/search.c') diff --git a/drivers/pci/search.c b/drivers/pci/search.c index 9148b6e8056b..d84a2f8cc12a 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -252,15 +252,6 @@ struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device, .subdevice = ss_device, }; - /* - * pci_find_subsys() can be called on the ide_setup() path, - * super-early in boot. But the down_read() will enable local - * interrupts, which can cause some machines to crash. So here we - * detect and flag that situation and bail out early. - */ - if (unlikely(no_pci_devices())) - return NULL; - return pci_get_dev_by_id(&id, from); } -- cgit v1.2.3