Commit dcd12456 authored by Bjorn Helgaas's avatar Bjorn Helgaas
Browse files

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
parents 77ac2e28 c7acef99
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -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);
};
+19 −28
Original line number Diff line number Diff line
@@ -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;
}


+0 −1
Original line number Diff line number Diff line
@@ -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)
+3 −1
Original line number Diff line number Diff line
@@ -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;
	}