Skip to content

Commit

Permalink
Merge branch 'pci/yijing-ari' into next
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
Bjorn Helgaas committed Jan 27, 2013
2 parents 708b59b + fcbed0b commit 14b5cb3
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 136 deletions.
29 changes: 11 additions & 18 deletions drivers/pci/hotplug/cpci_hotplug_pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -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__);

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

Expand All @@ -305,22 +300,20 @@ 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) {
err("No device for slot %02x\n", slot->number);
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;
Expand Down
44 changes: 16 additions & 28 deletions drivers/pci/hotplug/pciehp_pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand All @@ -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);
Expand All @@ -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;
Expand All @@ -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;
Expand Down
63 changes: 29 additions & 34 deletions drivers/pci/hotplug/sgi_hotplug.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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 */
Expand Down
36 changes: 16 additions & 20 deletions drivers/pci/hotplug/shpchp_pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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);
Expand All @@ -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;
}
Expand Down
21 changes: 14 additions & 7 deletions drivers/pci/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -2042,20 +2042,20 @@ 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;

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;
Expand All @@ -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;
}
}

/**
Expand Down
2 changes: 1 addition & 1 deletion drivers/pci/pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading

0 comments on commit 14b5cb3

Please sign in to comment.