mirror of
https://github.com/torvalds/linux.git
synced 2026-05-28 17:13:52 +02:00
Merge branch 'pci/hotplug'
- Remove unused cpcihp struct cpci_hp_controller_ops.hardware_test (Guilherme Giacomo Simoes) - Remove unused cpqphp struct ctrl_dbg.ctrl (Christophe JAILLET) - Clean up cpqphp PCIBIOS_* return value confusion (Ilpo Järvinen) - Use pci_bus_read_dev_vendor_id() instead of hand-coded presence detection in cpqphp (Ilpo Järvinen) - Simplify cpqphp enumeration, which is already simple-minded and doesn't handle devices below hot-added bridges (Ilpo Järvinen) - Retain a reference to the pci_bus for the lifetime of a pci_slot to avoid a use-after-free when the thunderbolt driver resets USB4 host routers on boot, causing hotplug remove/add of downstream docks or other devices (Lukas Wunner) * pci/hotplug: PCI: Fix use-after-free of slot->bus on hot remove PCI: cpqphp: Simplify PCI_ScanBusForNonBridge() PCI: cpqphp: Use define to read class/revision dword PCI: cpqphp: Use pci_bus_read_dev_vendor_id() to detect presence PCI: cpqphp: Fix PCIBIOS_* return value confusion PCI: cpqphp: Remove unused struct ctrl_dbg.ctrl PCI: cpcihp: Remove unused struct cpci_hp_controller_ops.hardware_test
This commit is contained in:
commit
dcd12456b3
|
|
@ -44,7 +44,6 @@ struct cpci_hp_controller_ops {
|
|||
int (*enable_irq)(void);
|
||||
int (*disable_irq)(void);
|
||||
int (*check_irq)(void *dev_id);
|
||||
int (*hardware_test)(struct slot *slot, u32 value);
|
||||
u8 (*get_power)(struct slot *slot);
|
||||
int (*set_power)(struct slot *slot, int value);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,8 +12,11 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "cpqphp: " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
|
@ -132,18 +135,6 @@ int cpqhp_unconfigure_device(struct pci_func *func)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int PCI_RefinedAccessConfig(struct pci_bus *bus, unsigned int devfn, u8 offset, u32 *value)
|
||||
{
|
||||
u32 vendID = 0;
|
||||
|
||||
if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &vendID) == -1)
|
||||
return -1;
|
||||
if (PCI_POSSIBLE_ERROR(vendID))
|
||||
return -1;
|
||||
return pci_bus_read_config_dword(bus, devfn, offset, value);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* cpqhp_set_irq
|
||||
*
|
||||
|
|
@ -202,13 +193,16 @@ static int PCI_ScanBusForNonBridge(struct controller *ctrl, u8 bus_num, u8 *dev_
|
|||
{
|
||||
u16 tdevice;
|
||||
u32 work;
|
||||
u8 tbus;
|
||||
int ret = -1;
|
||||
|
||||
ctrl->pci_bus->number = bus_num;
|
||||
|
||||
for (tdevice = 0; tdevice < 0xFF; tdevice++) {
|
||||
/* Scan for access first */
|
||||
if (PCI_RefinedAccessConfig(ctrl->pci_bus, tdevice, 0x08, &work) == -1)
|
||||
if (!pci_bus_read_dev_vendor_id(ctrl->pci_bus, tdevice, &work, 0))
|
||||
continue;
|
||||
ret = pci_bus_read_config_dword(ctrl->pci_bus, tdevice, PCI_CLASS_REVISION, &work);
|
||||
if (ret)
|
||||
continue;
|
||||
dbg("Looking for nonbridge bus_num %d dev_num %d\n", bus_num, tdevice);
|
||||
/* Yep we got one. Not a bridge ? */
|
||||
|
|
@ -216,23 +210,20 @@ static int PCI_ScanBusForNonBridge(struct controller *ctrl, u8 bus_num, u8 *dev_
|
|||
*dev_num = tdevice;
|
||||
dbg("found it !\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
for (tdevice = 0; tdevice < 0xFF; tdevice++) {
|
||||
/* Scan for access first */
|
||||
if (PCI_RefinedAccessConfig(ctrl->pci_bus, tdevice, 0x08, &work) == -1)
|
||||
continue;
|
||||
dbg("Looking for bridge bus_num %d dev_num %d\n", bus_num, tdevice);
|
||||
/* Yep we got one. bridge ? */
|
||||
if ((work >> 8) == PCI_TO_PCI_BRIDGE_CLASS) {
|
||||
pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(tdevice, 0), PCI_SECONDARY_BUS, &tbus);
|
||||
/* XXX: no recursion, wtf? */
|
||||
dbg("Recurse on bus_num %d tdevice %d\n", tbus, tdevice);
|
||||
return 0;
|
||||
} else {
|
||||
/*
|
||||
* XXX: Code whose debug printout indicated
|
||||
* recursion to buses underneath bridges might be
|
||||
* necessary was removed because it never did
|
||||
* any recursion.
|
||||
*/
|
||||
ret = 0;
|
||||
pr_warn("missing feature: bridge scan recursion not implemented\n");
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -123,7 +123,6 @@ static int spew_debug_info(struct controller *ctrl, char *data, int size)
|
|||
struct ctrl_dbg {
|
||||
int size;
|
||||
char *data;
|
||||
struct controller *ctrl;
|
||||
};
|
||||
|
||||
#define MAX_OUTPUT (4*PAGE_SIZE)
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ static void pci_slot_release(struct kobject *kobj)
|
|||
up_read(&pci_bus_sem);
|
||||
|
||||
list_del(&slot->list);
|
||||
pci_bus_put(slot->bus);
|
||||
|
||||
kfree(slot);
|
||||
}
|
||||
|
|
@ -261,7 +262,7 @@ struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr,
|
|||
goto err;
|
||||
}
|
||||
|
||||
slot->bus = parent;
|
||||
slot->bus = pci_bus_get(parent);
|
||||
slot->number = slot_nr;
|
||||
|
||||
slot->kobj.kset = pci_slots_kset;
|
||||
|
|
@ -269,6 +270,7 @@ struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr,
|
|||
slot_name = make_slot_name(name);
|
||||
if (!slot_name) {
|
||||
err = -ENOMEM;
|
||||
pci_bus_put(slot->bus);
|
||||
kfree(slot);
|
||||
goto err;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user