aboutsummaryrefslogtreecommitdiff
path: root/core/pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'core/pci.c')
-rw-r--r--core/pci.c179
1 files changed, 38 insertions, 141 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);
}