mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-30 05:15:03 +00:00
Merge branch 'pci/yijing-ari' into next
* pci/yijing-ari: PCI: shpchp: Iterate over all devices in slot, not functions 0-7 PCI: sgihp: Iterate over all devices in slot, not functions 0-7 PCI: cpcihp: Iterate over all devices in slot, not functions 0-7 PCI: pciehp: Iterate over all devices in slot, not functions 0-7 PCI: Consolidate "next-function" functions PCI: Rename pci_enable_ari() to pci_configure_ari() PCI: Enable ARI if dev and upstream bridge support it; disable otherwise
This commit is contained in:
commit
14b5cb37cc
@ -252,8 +252,8 @@ int cpci_led_off(struct slot* slot)
|
||||
|
||||
int __ref cpci_configure_slot(struct slot *slot)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
struct pci_bus *parent;
|
||||
int fn;
|
||||
|
||||
dbg("%s - enter", __func__);
|
||||
|
||||
@ -282,18 +282,13 @@ int __ref cpci_configure_slot(struct slot *slot)
|
||||
}
|
||||
parent = slot->dev->bus;
|
||||
|
||||
for (fn = 0; fn < 8; fn++) {
|
||||
struct pci_dev *dev;
|
||||
|
||||
dev = pci_get_slot(parent,
|
||||
PCI_DEVFN(PCI_SLOT(slot->devfn), fn));
|
||||
if (!dev)
|
||||
list_for_each_entry(dev, &parent->devices, bus_list)
|
||||
if (PCI_SLOT(dev->devfn) != PCI_SLOT(slot->devfn))
|
||||
continue;
|
||||
if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
|
||||
(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS))
|
||||
pci_hp_add_bridge(dev);
|
||||
pci_dev_put(dev);
|
||||
}
|
||||
|
||||
|
||||
pci_assign_unassigned_bridge_resources(parent->self);
|
||||
|
||||
@ -305,8 +300,7 @@ int __ref cpci_configure_slot(struct slot *slot)
|
||||
|
||||
int cpci_unconfigure_slot(struct slot* slot)
|
||||
{
|
||||
int i;
|
||||
struct pci_dev *dev;
|
||||
struct pci_dev *dev, *temp;
|
||||
|
||||
dbg("%s - enter", __func__);
|
||||
if (!slot->dev) {
|
||||
@ -314,13 +308,12 @@ int cpci_unconfigure_slot(struct slot* slot)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
dev = pci_get_slot(slot->bus,
|
||||
PCI_DEVFN(PCI_SLOT(slot->devfn), i));
|
||||
if (dev) {
|
||||
pci_stop_and_remove_bus_device(dev);
|
||||
pci_dev_put(dev);
|
||||
}
|
||||
list_for_each_entry_safe(dev, temp, &slot->bus->devices, bus_list) {
|
||||
if (PCI_SLOT(dev->devfn) != PCI_SLOT(slot->devfn))
|
||||
continue;
|
||||
pci_dev_get(dev);
|
||||
pci_stop_and_remove_bus_device(dev);
|
||||
pci_dev_put(dev);
|
||||
}
|
||||
pci_dev_put(slot->dev);
|
||||
slot->dev = NULL;
|
||||
|
@ -39,7 +39,7 @@ int pciehp_configure_device(struct slot *p_slot)
|
||||
struct pci_dev *dev;
|
||||
struct pci_dev *bridge = p_slot->ctrl->pcie->port;
|
||||
struct pci_bus *parent = bridge->subordinate;
|
||||
int num, fn;
|
||||
int num;
|
||||
struct controller *ctrl = p_slot->ctrl;
|
||||
|
||||
dev = pci_get_slot(parent, PCI_DEVFN(0, 0));
|
||||
@ -57,28 +57,18 @@ int pciehp_configure_device(struct slot *p_slot)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
for (fn = 0; fn < 8; fn++) {
|
||||
dev = pci_get_slot(parent, PCI_DEVFN(0, fn));
|
||||
if (!dev)
|
||||
continue;
|
||||
list_for_each_entry(dev, &parent->devices, bus_list)
|
||||
if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
|
||||
(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS))
|
||||
pci_hp_add_bridge(dev);
|
||||
pci_dev_put(dev);
|
||||
}
|
||||
|
||||
pci_assign_unassigned_bridge_resources(bridge);
|
||||
|
||||
for (fn = 0; fn < 8; fn++) {
|
||||
dev = pci_get_slot(parent, PCI_DEVFN(0, fn));
|
||||
if (!dev)
|
||||
list_for_each_entry(dev, &parent->devices, bus_list) {
|
||||
if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
|
||||
continue;
|
||||
if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
|
||||
pci_dev_put(dev);
|
||||
continue;
|
||||
}
|
||||
|
||||
pci_configure_slot(dev);
|
||||
pci_dev_put(dev);
|
||||
}
|
||||
|
||||
pci_bus_add_devices(parent);
|
||||
@ -89,9 +79,9 @@ int pciehp_configure_device(struct slot *p_slot)
|
||||
int pciehp_unconfigure_device(struct slot *p_slot)
|
||||
{
|
||||
int ret, rc = 0;
|
||||
int j;
|
||||
u8 bctl = 0;
|
||||
u8 presence = 0;
|
||||
struct pci_dev *dev, *temp;
|
||||
struct pci_bus *parent = p_slot->ctrl->pcie->port->subordinate;
|
||||
u16 command;
|
||||
struct controller *ctrl = p_slot->ctrl;
|
||||
@ -102,33 +92,31 @@ int pciehp_unconfigure_device(struct slot *p_slot)
|
||||
if (ret)
|
||||
presence = 0;
|
||||
|
||||
for (j = 0; j < 8; j++) {
|
||||
struct pci_dev *temp = pci_get_slot(parent, PCI_DEVFN(0, j));
|
||||
if (!temp)
|
||||
continue;
|
||||
if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE && presence) {
|
||||
pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl);
|
||||
list_for_each_entry_safe(dev, temp, &parent->devices, bus_list) {
|
||||
pci_dev_get(dev);
|
||||
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE && presence) {
|
||||
pci_read_config_byte(dev, PCI_BRIDGE_CONTROL, &bctl);
|
||||
if (bctl & PCI_BRIDGE_CTL_VGA) {
|
||||
ctrl_err(ctrl,
|
||||
"Cannot remove display device %s\n",
|
||||
pci_name(temp));
|
||||
pci_dev_put(temp);
|
||||
pci_name(dev));
|
||||
pci_dev_put(dev);
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
pci_stop_and_remove_bus_device(temp);
|
||||
pci_stop_and_remove_bus_device(dev);
|
||||
/*
|
||||
* Ensure that no new Requests will be generated from
|
||||
* the device.
|
||||
*/
|
||||
if (presence) {
|
||||
pci_read_config_word(temp, PCI_COMMAND, &command);
|
||||
pci_read_config_word(dev, PCI_COMMAND, &command);
|
||||
command &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_SERR);
|
||||
command |= PCI_COMMAND_INTX_DISABLE;
|
||||
pci_write_config_word(temp, PCI_COMMAND, command);
|
||||
pci_write_config_word(dev, PCI_COMMAND, command);
|
||||
}
|
||||
pci_dev_put(temp);
|
||||
pci_dev_put(dev);
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
@ -334,7 +334,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
|
||||
struct slot *slot = bss_hotplug_slot->private;
|
||||
struct pci_bus *new_bus = NULL;
|
||||
struct pci_dev *dev;
|
||||
int func, num_funcs;
|
||||
int num_funcs;
|
||||
int new_ppb = 0;
|
||||
int rc;
|
||||
char *ssdt = NULL;
|
||||
@ -381,29 +381,26 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
|
||||
* to the Linux PCI interface and tell the drivers
|
||||
* about them.
|
||||
*/
|
||||
for (func = 0; func < num_funcs; func++) {
|
||||
dev = pci_get_slot(slot->pci_bus,
|
||||
PCI_DEVFN(slot->device_num + 1,
|
||||
PCI_FUNC(func)));
|
||||
if (dev) {
|
||||
/* Need to do slot fixup on PPB before fixup of children
|
||||
* (PPB's pcidev_info needs to be in pcidev_info list
|
||||
* before child's SN_PCIDEV_INFO() call to setup
|
||||
* pdi_host_pcidev_info).
|
||||
*/
|
||||
pcibios_fixup_device_resources(dev);
|
||||
if (SN_ACPI_BASE_SUPPORT())
|
||||
sn_acpi_slot_fixup(dev);
|
||||
else
|
||||
sn_io_slot_fixup(dev);
|
||||
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
|
||||
pci_hp_add_bridge(dev);
|
||||
if (dev->subordinate) {
|
||||
new_bus = dev->subordinate;
|
||||
new_ppb = 1;
|
||||
}
|
||||
list_for_each_entry(dev, &slot->pci_bus->devices, bus_list) {
|
||||
if (PCI_SLOT(dev->devfn) != slot->device_num + 1)
|
||||
continue;
|
||||
|
||||
/* Need to do slot fixup on PPB before fixup of children
|
||||
* (PPB's pcidev_info needs to be in pcidev_info list
|
||||
* before child's SN_PCIDEV_INFO() call to setup
|
||||
* pdi_host_pcidev_info).
|
||||
*/
|
||||
pcibios_fixup_device_resources(dev);
|
||||
if (SN_ACPI_BASE_SUPPORT())
|
||||
sn_acpi_slot_fixup(dev);
|
||||
else
|
||||
sn_io_slot_fixup(dev);
|
||||
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
|
||||
pci_hp_add_bridge(dev);
|
||||
if (dev->subordinate) {
|
||||
new_bus = dev->subordinate;
|
||||
new_ppb = 1;
|
||||
}
|
||||
pci_dev_put(dev);
|
||||
}
|
||||
}
|
||||
|
||||
@ -481,8 +478,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
|
||||
static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
|
||||
{
|
||||
struct slot *slot = bss_hotplug_slot->private;
|
||||
struct pci_dev *dev;
|
||||
int func;
|
||||
struct pci_dev *dev, *temp;
|
||||
int rc;
|
||||
acpi_owner_id ssdt_id = 0;
|
||||
|
||||
@ -542,15 +538,14 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
|
||||
}
|
||||
|
||||
/* Free the SN resources assigned to the Linux device.*/
|
||||
for (func = 0; func < 8; func++) {
|
||||
dev = pci_get_slot(slot->pci_bus,
|
||||
PCI_DEVFN(slot->device_num + 1,
|
||||
PCI_FUNC(func)));
|
||||
if (dev) {
|
||||
sn_bus_free_data(dev);
|
||||
pci_stop_and_remove_bus_device(dev);
|
||||
pci_dev_put(dev);
|
||||
}
|
||||
list_for_each_entry_safe(dev, temp, &slot->pci_bus->devices, bus_list) {
|
||||
if (PCI_SLOT(dev->devfn) != slot->device_num + 1)
|
||||
continue;
|
||||
|
||||
pci_dev_get(dev);
|
||||
sn_bus_free_data(dev);
|
||||
pci_stop_and_remove_bus_device(dev);
|
||||
pci_dev_put(dev);
|
||||
}
|
||||
|
||||
/* Remove the SSDT for the slot from the ACPI namespace */
|
||||
|
@ -40,7 +40,7 @@ int __ref shpchp_configure_device(struct slot *p_slot)
|
||||
struct controller *ctrl = p_slot->ctrl;
|
||||
struct pci_dev *bridge = ctrl->pci_dev;
|
||||
struct pci_bus *parent = bridge->subordinate;
|
||||
int num, fn;
|
||||
int num;
|
||||
|
||||
dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0));
|
||||
if (dev) {
|
||||
@ -57,24 +57,20 @@ int __ref shpchp_configure_device(struct slot *p_slot)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
for (fn = 0; fn < 8; fn++) {
|
||||
dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, fn));
|
||||
if (!dev)
|
||||
list_for_each_entry(dev, &parent->devices, bus_list) {
|
||||
if (PCI_SLOT(dev->devfn) != p_slot->device)
|
||||
continue;
|
||||
if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
|
||||
(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS))
|
||||
pci_hp_add_bridge(dev);
|
||||
pci_dev_put(dev);
|
||||
}
|
||||
|
||||
pci_assign_unassigned_bridge_resources(bridge);
|
||||
|
||||
for (fn = 0; fn < 8; fn++) {
|
||||
dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, fn));
|
||||
if (!dev)
|
||||
list_for_each_entry(dev, &parent->devices, bus_list) {
|
||||
if (PCI_SLOT(dev->devfn) != p_slot->device)
|
||||
continue;
|
||||
pci_configure_slot(dev);
|
||||
pci_dev_put(dev);
|
||||
}
|
||||
|
||||
pci_bus_add_devices(parent);
|
||||
@ -85,32 +81,32 @@ int __ref shpchp_configure_device(struct slot *p_slot)
|
||||
int shpchp_unconfigure_device(struct slot *p_slot)
|
||||
{
|
||||
int rc = 0;
|
||||
int j;
|
||||
u8 bctl = 0;
|
||||
struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
|
||||
struct pci_dev *dev, *temp;
|
||||
struct controller *ctrl = p_slot->ctrl;
|
||||
|
||||
ctrl_dbg(ctrl, "%s: domain:bus:dev = %04x:%02x:%02x\n",
|
||||
__func__, pci_domain_nr(parent), p_slot->bus, p_slot->device);
|
||||
|
||||
for (j = 0; j < 8 ; j++) {
|
||||
struct pci_dev *temp = pci_get_slot(parent,
|
||||
(p_slot->device << 3) | j);
|
||||
if (!temp)
|
||||
list_for_each_entry_safe(dev, temp, &parent->devices, bus_list) {
|
||||
if (PCI_SLOT(dev->devfn) != p_slot->device)
|
||||
continue;
|
||||
if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
|
||||
pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl);
|
||||
|
||||
pci_dev_get(dev);
|
||||
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
|
||||
pci_read_config_byte(dev, PCI_BRIDGE_CONTROL, &bctl);
|
||||
if (bctl & PCI_BRIDGE_CTL_VGA) {
|
||||
ctrl_err(ctrl,
|
||||
"Cannot remove display device %s\n",
|
||||
pci_name(temp));
|
||||
pci_dev_put(temp);
|
||||
pci_name(dev));
|
||||
pci_dev_put(dev);
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
pci_stop_and_remove_bus_device(temp);
|
||||
pci_dev_put(temp);
|
||||
pci_stop_and_remove_bus_device(dev);
|
||||
pci_dev_put(dev);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
@ -2042,10 +2042,13 @@ void pci_free_cap_save_buffers(struct pci_dev *dev)
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_enable_ari - enable ARI forwarding if hardware support it
|
||||
* pci_configure_ari - enable or disable ARI forwarding
|
||||
* @dev: the PCI device
|
||||
*
|
||||
* If @dev and its upstream bridge both support ARI, enable ARI in the
|
||||
* bridge. Otherwise, disable ARI in the bridge.
|
||||
*/
|
||||
void pci_enable_ari(struct pci_dev *dev)
|
||||
void pci_configure_ari(struct pci_dev *dev)
|
||||
{
|
||||
u32 cap;
|
||||
struct pci_dev *bridge;
|
||||
@ -2053,9 +2056,6 @@ void pci_enable_ari(struct pci_dev *dev)
|
||||
if (pcie_ari_disabled || !pci_is_pcie(dev) || dev->devfn)
|
||||
return;
|
||||
|
||||
if (!pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI))
|
||||
return;
|
||||
|
||||
bridge = dev->bus->self;
|
||||
if (!bridge)
|
||||
return;
|
||||
@ -2064,8 +2064,15 @@ void pci_enable_ari(struct pci_dev *dev)
|
||||
if (!(cap & PCI_EXP_DEVCAP2_ARI))
|
||||
return;
|
||||
|
||||
pcie_capability_set_word(bridge, PCI_EXP_DEVCTL2, PCI_EXP_DEVCTL2_ARI);
|
||||
bridge->ari_enabled = 1;
|
||||
if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI)) {
|
||||
pcie_capability_set_word(bridge, PCI_EXP_DEVCTL2,
|
||||
PCI_EXP_DEVCTL2_ARI);
|
||||
bridge->ari_enabled = 1;
|
||||
} else {
|
||||
pcie_capability_clear_word(bridge, PCI_EXP_DEVCTL2,
|
||||
PCI_EXP_DEVCTL2_ARI);
|
||||
bridge->ari_enabled = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -204,7 +204,7 @@ extern int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
|
||||
extern int pci_resource_bar(struct pci_dev *dev, int resno,
|
||||
enum pci_bar_type *type);
|
||||
extern int pci_bus_add_child(struct pci_bus *bus);
|
||||
extern void pci_enable_ari(struct pci_dev *dev);
|
||||
extern void pci_configure_ari(struct pci_dev *dev);
|
||||
/**
|
||||
* pci_ari_enabled - query ARI forwarding status
|
||||
* @bus: the PCI bus
|
||||
|
@ -1285,7 +1285,7 @@ static void pci_init_capabilities(struct pci_dev *dev)
|
||||
pci_vpd_pci22_init(dev);
|
||||
|
||||
/* Alternative Routing-ID Forwarding */
|
||||
pci_enable_ari(dev);
|
||||
pci_configure_ari(dev);
|
||||
|
||||
/* Single Root I/O Virtualization */
|
||||
pci_iov_init(dev);
|
||||
@ -1348,31 +1348,31 @@ struct pci_dev *__ref pci_scan_single_device(struct pci_bus *bus, int devfn)
|
||||
}
|
||||
EXPORT_SYMBOL(pci_scan_single_device);
|
||||
|
||||
static unsigned next_ari_fn(struct pci_dev *dev, unsigned fn)
|
||||
static unsigned next_fn(struct pci_bus *bus, struct pci_dev *dev, unsigned fn)
|
||||
{
|
||||
u16 cap;
|
||||
unsigned pos, next_fn;
|
||||
int pos;
|
||||
u16 cap = 0;
|
||||
unsigned next_fn;
|
||||
|
||||
if (!dev)
|
||||
return 0;
|
||||
if (pci_ari_enabled(bus)) {
|
||||
if (!dev)
|
||||
return 0;
|
||||
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI);
|
||||
if (!pos)
|
||||
return 0;
|
||||
|
||||
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI);
|
||||
if (!pos)
|
||||
return 0;
|
||||
pci_read_config_word(dev, pos + 4, &cap);
|
||||
next_fn = cap >> 8;
|
||||
if (next_fn <= fn)
|
||||
return 0;
|
||||
return next_fn;
|
||||
}
|
||||
pci_read_config_word(dev, pos + PCI_ARI_CAP, &cap);
|
||||
next_fn = PCI_ARI_CAP_NFN(cap);
|
||||
if (next_fn <= fn)
|
||||
return 0; /* protect against malformed list */
|
||||
|
||||
static unsigned next_trad_fn(struct pci_dev *dev, unsigned fn)
|
||||
{
|
||||
return (fn + 1) % 8;
|
||||
}
|
||||
return next_fn;
|
||||
}
|
||||
|
||||
/* dev may be NULL for non-contiguous multifunction devices */
|
||||
if (!dev || dev->multifunction)
|
||||
return (fn + 1) % 8;
|
||||
|
||||
static unsigned no_next_fn(struct pci_dev *dev, unsigned fn)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1405,7 +1405,6 @@ int pci_scan_slot(struct pci_bus *bus, int devfn)
|
||||
{
|
||||
unsigned fn, nr = 0;
|
||||
struct pci_dev *dev;
|
||||
unsigned (*next_fn)(struct pci_dev *, unsigned) = no_next_fn;
|
||||
|
||||
if (only_one_child(bus) && (devfn > 0))
|
||||
return 0; /* Already scanned the entire slot */
|
||||
@ -1416,12 +1415,7 @@ int pci_scan_slot(struct pci_bus *bus, int devfn)
|
||||
if (!dev->is_added)
|
||||
nr++;
|
||||
|
||||
if (pci_ari_enabled(bus))
|
||||
next_fn = next_ari_fn;
|
||||
else if (dev->multifunction)
|
||||
next_fn = next_trad_fn;
|
||||
|
||||
for (fn = next_fn(dev, 0); fn > 0; fn = next_fn(dev, fn)) {
|
||||
for (fn = next_fn(bus, dev, 0); fn > 0; fn = next_fn(bus, dev, fn)) {
|
||||
dev = pci_scan_single_device(bus, devfn + fn);
|
||||
if (dev) {
|
||||
if (!dev->is_added)
|
||||
|
Loading…
Reference in New Issue
Block a user