diff options
Diffstat (limited to 'core/pci.c')
-rw-r--r-- | core/pci.c | 179 |
1 files changed, 38 insertions, 141 deletions
@@ -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); } |