Skip to content

Commit

Permalink
PCI: Use pci_device_id on stack for pci_get_subsys/class() to avoid k…
Browse files Browse the repository at this point in the history
…malloc

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 <fengguang.wu@intel.com>
Signed-off-by: Feng Tang <feng.tang@intel.com>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Fengguang Wu <fengguang.wu@intel.com>
  • Loading branch information
Feng Tang authored and Bjorn Helgaas committed Aug 24, 2012
1 parent 0d7614f commit b9443f4
Showing 1 changed file with 17 additions and 27 deletions.
44 changes: 17 additions & 27 deletions drivers/pci/search.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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);
}

/**
Expand Down Expand Up @@ -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);
}

/**
Expand Down

0 comments on commit b9443f4

Please sign in to comment.