aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGavin Shan <gwshan@linux.vnet.ibm.com>2016-06-10 15:03:49 +1000
committerStewart Smith <stewart@linux.vnet.ibm.com>2016-06-14 16:00:17 +1000
commitb0cb209e3893d1db7f10662c0803997d928942e5 (patch)
treef18761bfb32f55cf756cc960e01b50fbfb47765e
parentaa928bfbd89192ea13809c6cd8f0402fd981a976 (diff)
downloadskiboot-b0cb209e3893d1db7f10662c0803997d928942e5.zip
skiboot-b0cb209e3893d1db7f10662c0803997d928942e5.tar.gz
skiboot-b0cb209e3893d1db7f10662c0803997d928942e5.tar.bz2
core/pci: Use PCI slot in enumeration
During PCI enumeration, the root complex's link and fundamental reset are carried out by PHB's callbacks which are replaced by the corresponding PCI slot's callbacks. Also, the hotplug related device node properties are populated based on the PCI slot info that is included in PCI slot now. This uses PCI slot in enumeration: * Use PCI slot's callbacks for fundamental reset and link status retrieval in PCI enumeration. * Simplify the code by removing traditional PCI/PCI-x related logic as we don't have PCI/PCI-X root complex. * Replace pci_add_slot_properties() with pci_slot_add_properties() to populate PCI slot properties in device-tree. * PHB is always not hotpluggable. No hotpluggable properties in its device node are needed. * Remove "struct pci_slot_info" definition as its info is included in "struct pci_slot". Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com> Reviewed-by: Russell Currey <ruscur@russell.cc> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
-rw-r--r--core/pci.c179
-rw-r--r--include/pci.h17
2 files changed, 38 insertions, 158 deletions
diff --git a/core/pci.c b/core/pci.c
index 9f5c1f3..bf07ff9 100644
--- a/core/pci.c
+++ b/core/pci.c
@@ -721,110 +721,57 @@ void pci_device_init(struct phb *phb, struct pci_device *pd)
pci_disable_completion_timeout(phb, pd);
}
-/*
- * The power state would be checked. If the power has
- * been on, we will issue fundamental reset. Otherwise,
- * we will power it on before issuing fundamental reset.
- */
-static int64_t pci_phb_reset(struct phb *phb)
+static void pci_reset_phb(void *data)
{
- const char *desc;
+ struct phb *phb = data;
+ struct pci_slot *slot = phb->slot;
int64_t rc;
- rc = phb->ops->power_state(phb);
- if (rc < 0) {
- PCIERR(phb, 0, "Failed to get power state, rc=%lld\n", rc);
- return rc;
- }
-
- if (rc == OPAL_SHPC_POWER_ON) {
- desc = "fundamental reset";
- rc = phb->ops->fundamental_reset(phb);
- } else {
- desc = "power on";
- rc = phb->ops->slot_power_on(phb);
- }
-
- if (rc < 0) {
- /* Don't warn if it's just an empty slot */
- if (rc != OPAL_CLOSED)
- goto warn_err;
- return rc;
+ if (!slot || !slot->ops.freset) {
+ PCINOTICE(phb, 0, "Cannot issue fundamental reset\n");
+ return;
}
- /* Wait the internal state machine */
+ pci_slot_add_flags(slot, PCI_SLOT_FLAG_BOOTUP);
+ rc = slot->ops.freset(slot);
while (rc > 0) {
time_wait(rc);
- rc = phb->ops->poll(phb);
+ rc = slot->ops.poll(slot);
}
-
- warn_err:
+ pci_slot_remove_flags(slot, PCI_SLOT_FLAG_BOOTUP);
if (rc < 0)
- PCIERR(phb, 0, "Failed to %s, rc=%lld\n", desc, rc);
-
- return rc;
-}
-
-static void pci_reset_phb(void *data)
-{
- struct phb *phb = data;
- int64_t rc;
-
- PCIDBG(phb, 0, "Init slot...\n");
-
- /*
- * For PCI/PCI-X, we get the slot info and we also
- * check if the PHB has anything connected to it
- */
- if (phb->phb_type < phb_type_pcie_v1) {
- if (platform.pci_get_slot_info)
- platform.pci_get_slot_info(phb, NULL);
- rc = phb->ops->presence_detect(phb);
- if (rc != OPAL_SHPC_DEV_PRESENT) {
- PCIDBG(phb, 0, "Slot empty\n");
- return;
- }
- }
-
- /*
- * Power on the PHB, the PHB should be reset in
- * fundamental way while powering on. The reset
- * state machine is going to wait for the link
- */
- pci_phb_reset(phb);
+ PCIERR(phb, 0, "Error %lld fundamental resetting\n", rc);
}
static void pci_scan_phb(void *data)
{
struct phb *phb = data;
+ struct pci_slot *slot = phb->slot;
+ uint8_t link;
uint32_t mps = 0xffffffff;
- bool has_link = false;
int64_t rc;
- rc = phb->ops->link_state(phb);
- if (rc < 0) {
- PCIERR(phb, 0, "Failed to query link state, rc=%lld\n", rc);
- return;
+ if (!slot || !slot->ops.get_link_state) {
+ PCIERR(phb, 0, "Cannot query link status\n");
+ link = 0;
+ } else {
+ rc = slot->ops.get_link_state(slot, &link);
+ if (rc != OPAL_SUCCESS) {
+ PCIERR(phb, 0, "Error %lld querying link status\n",
+ rc);
+ link = 0;
+ }
}
- /*
- * We will probe the root port. If the PHB has trained
- * link, we will probe the downstream port as well.
- */
- if (rc != OPAL_SHPC_LINK_DOWN)
- has_link = true;
-
- if (has_link && phb->phb_type >= phb_type_pcie_v1)
- PCIDBG(phb, 0, "Link up at x%lld width\n", rc);
- else if (has_link)
- PCIDBG(phb, 0, "Link up\n");
- else
+ if (!link)
PCIDBG(phb, 0, "Link down\n");
+ else
+ PCIDBG(phb, 0, "Link up at x%d width\n", link);
/* Scan root port and downstream ports if applicable */
PCIDBG(phb, 0, "Scanning (upstream%s)...\n",
- has_link ? "+downsteam" : " only");
- pci_scan_bus(phb, 0, 0xff, &phb->devices, NULL, has_link);
+ link ? "+downsteam" : " only");
+ pci_scan_bus(phb, 0, 0xff, &phb->devices, NULL, link);
/* Configure MPS (Max Payload Size) for PCIe domain */
pci_walk_dev(phb, NULL, pci_get_mps, &mps);
@@ -1193,52 +1140,6 @@ void pci_std_swizzle_irq_map(struct dt_node *np,
free(map);
}
-static void pci_add_slot_properties(struct phb *phb, struct pci_slot_info *info,
- struct dt_node *np)
-{
- char loc_code[LOC_CODE_SIZE];
- size_t base_loc_code_len = 0, slot_label_len = 0;
-
- loc_code[0] = '\0';
-
- if (phb->base_loc_code) {
- base_loc_code_len = strlen(phb->base_loc_code);
- strcpy(loc_code, phb->base_loc_code);
- }
- slot_label_len = strlen(info->label);
- if (slot_label_len) {
- if ((base_loc_code_len + slot_label_len + 1) < LOC_CODE_SIZE) {
- if (base_loc_code_len)
- strcat(loc_code, "-");
- strcat(loc_code, info->label);
- dt_add_property(np, "ibm,slot-location-code",
- loc_code, strlen(loc_code) + 1);
- } else {
- PCIERR(phb, 0, "Loc Code too long - %zu + %zu + 1\n",
- base_loc_code_len, slot_label_len);
- }
- }
-
- /* Add other slot information */
- dt_add_property_cells(np, "ibm,slot-pluggable", info->pluggable);
- dt_add_property_cells(np, "ibm,slot-power-ctl", info->power_ctl);
- if (info->wired_lanes >= 0)
- dt_add_property_cells(np, "ibm,slot-wired-lanes", info->wired_lanes);
- /*dt_add_property(np, "ibm,slot-bus-clock", &pd->slot_info->bus_clock, sizeof(uint8_t));*/
- if (info->connector_type >= 0)
- dt_add_property_cells(np, "ibm,slot-connector-type", info->connector_type);
- if (info->card_desc >= 0)
- dt_add_property_cells(np, "ibm,slot-card-desc", info->card_desc);
- if (info->card_mech >= 0)
- dt_add_property_cells(np, "ibm,slot-card-mech", info->card_mech);
- if (info->pwr_led_ctl >= 0)
- dt_add_property_cells(np, "ibm,slot-pwr-led-ctl", info->pwr_led_ctl);
- if (info->attn_led_ctl >= 0)
- dt_add_property_cells(np, "ibm,slot-attn-led-ctl", info->attn_led_ctl);
- if (strlen(info->label) > 0)
- dt_add_property_string(np, "ibm,slot-label", info->label);
-}
-
static void pci_add_loc_code(struct dt_node *np, struct pci_device *pd)
{
struct dt_node *p = np->parent;
@@ -1249,14 +1150,13 @@ static void pci_add_loc_code(struct dt_node *np, struct pci_device *pd)
uint8_t pos, len;
/* If there is a label assigned to the function, use it on openpower machines */
- if (pd->slot_info && strlen(pd->slot_info->label) && !fsp_present()) {
- blcode = pd->slot_info->label;
- } else {
- /* Look for a parent with a slot-location-code */
- while (p && !blcode) {
- blcode = dt_prop_get_def(p, "ibm,slot-location-code", NULL);
- p = p->parent;
- }
+ if (pd->slot)
+ blcode = dt_prop_get_def(np, "ibm,slot-label", NULL);
+
+ /* Look for a parent with a slot-location-code */
+ while (!blcode && p) {
+ blcode = dt_prop_get_def(p, "ibm,slot-location-code", NULL);
+ p = p->parent;
}
if (!blcode)
return;
@@ -1422,8 +1322,8 @@ static void pci_add_one_device_node(struct phb *phb,
*/
/* Add slot properties if needed and iff this is a bridge */
- if (pd->slot_info && pd->is_bridge)
- pci_add_slot_properties(phb, pd->slot_info, np);
+ if (pd->slot)
+ pci_slot_add_dt_properties(pd->slot, np);
/* Make up location code */
pci_add_loc_code(np, pd);
@@ -1480,10 +1380,6 @@ void pci_add_device_nodes(struct phb *phb,
{
struct pci_device *pd;
- /* If the PHB has its own slot info, add them */
- if (phb->slot_info)
- pci_add_slot_properties(phb, phb->slot_info, NULL);
-
/* Add all child devices */
list_for_each(list, pd, link) {
pci_add_one_device_node(phb, pd, parent_node,
@@ -1574,6 +1470,7 @@ void pci_init_slots(void)
for (i = 0; i < ARRAY_SIZE(phbs); i++) {
if (!phbs[i])
continue;
+
pci_add_device_nodes(phbs[i], &phbs[i]->devices,
phbs[i]->dt_node, &phbs[i]->lstate, 0);
}
diff --git a/include/pci.h b/include/pci.h
index 486b712..ce46889 100644
--- a/include/pci.h
+++ b/include/pci.h
@@ -22,21 +22,6 @@
#include <lock.h>
#include <ccan/list/list.h>
-/* PCI Slot Entry Information */
-struct pci_slot_info {
- char label[16];
- bool pluggable;
- bool power_ctl;
- int wired_lanes;
- int bus_clock;
- int connector_type;
- int card_desc;
- int card_mech;
- int pwr_led_ctl;
- int attn_led_ctl;
- int slot_index;
-};
-
struct pci_device;
struct pci_cfg_reg_filter;
@@ -98,7 +83,6 @@ struct pci_device {
struct dt_node *dn;
struct pci_slot *slot;
- struct pci_slot_info *slot_info;
struct pci_device *parent;
struct list_head children;
struct list_node link;
@@ -410,7 +394,6 @@ struct phb {
/* PCI-X only slot info, for PCI-E this is in the RC bridge */
struct pci_slot *slot;
- struct pci_slot_info *slot_info;
/* Base location code used to generate the children one */
const char *base_loc_code;