fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro/*
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * CDDL HEADER START
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro *
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * The contents of this file are subject to the terms of the
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * Common Development and Distribution License (the "License").
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * You may not use this file except in compliance with the License.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro *
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * or http://www.opensolaris.org/os/licensing.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * See the License for the specific language governing permissions
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * and limitations under the License.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro *
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * When distributing Covered Code, include this CDDL HEADER in each
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * If applicable, add the following below this CDDL HEADER, with the
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * fields enclosed by brackets "[]" replaced with your own identifying
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * information: Portions Copyright [yyyy] [name of copyright owner]
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro *
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * CDDL HEADER END
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro/*
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * Use is subject to license terms.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro#include <sys/types.h>
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro#include <sys/ddi.h>
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro#include <sys/dditypes.h>
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro#include <sys/ddifm.h>
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro#include <sys/sunndi.h>
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro#include <sys/devops.h>
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro#include <sys/pcie.h>
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro#include <sys/pci_cap.h>
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro#include <sys/pcie_impl.h>
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro#include <sys/pathname.h>
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro/*
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * The below 2 global variables are for PCIe IOV Error Handling. They must only
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * be accessed during error handling under the protection of a error mutex.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorostatic pcie_domains_t *pcie_faulty_domains = NULL;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorostatic boolean_t pcie_faulty_all = B_FALSE;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorostatic void pcie_domain_list_destroy(pcie_domains_t *domain_ids);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorostatic void pcie_bdf_list_add(pcie_req_id_t bdf,
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_req_id_list_t **rlist_p);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorostatic void pcie_bdf_list_remove(pcie_req_id_t bdf,
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_req_id_list_t **rlist_p);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorostatic void pcie_cache_domain_info(pcie_bus_t *bus_p);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorostatic void pcie_uncache_domain_info(pcie_bus_t *bus_p);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorostatic void pcie_faulty_list_clear();
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorostatic void pcie_faulty_list_update(pcie_domains_t *pd,
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_domains_t **headp);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorodev_info_t *
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloropcie_find_dip_by_bdf(dev_info_t *rootp, pcie_req_id_t bdf)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro{
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro dev_info_t *dip;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_bus_t *bus_p;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro int bus_num;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro dip = ddi_get_child(rootp);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro while (dip) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro bus_p = PCIE_DIP2BUS(dip);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (bus_p && (bus_p->bus_bdf == bdf))
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (dip);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (bus_p) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro bus_num = (bdf >> 8) & 0xff;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if ((bus_num >= bus_p->bus_bus_range.lo &&
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro bus_num <= bus_p->bus_bus_range.hi) ||
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro bus_p->bus_bus_range.hi == 0)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (pcie_find_dip_by_bdf(dip, bdf));
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro dip = ddi_get_next_sibling(dip);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (NULL);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro}
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro/*
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * Add a device bdf to the bdf list.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorostatic void
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloropcie_bdf_list_add(pcie_req_id_t bdf, pcie_req_id_list_t **rlist_p)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro{
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_req_id_list_t *rl = PCIE_ZALLOC(pcie_req_id_list_t);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro rl->bdf = bdf;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro rl->next = *rlist_p;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro *rlist_p = rl;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro}
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro/*
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * Remove a bdf from the bdf list.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorostatic void
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloropcie_bdf_list_remove(pcie_req_id_t bdf, pcie_req_id_list_t **rlist_p)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro{
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_req_id_list_t *rl_pre, *rl_next;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro rl_pre = *rlist_p;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (rl_pre->bdf == bdf) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro *rlist_p = rl_pre->next;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro kmem_free(rl_pre, sizeof (pcie_req_id_list_t));
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro while (rl_pre->next) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro rl_next = rl_pre->next;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (rl_next->bdf == bdf) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro rl_pre->next = rl_next->next;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro kmem_free(rl_next, sizeof (pcie_req_id_list_t));
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro break;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro } else
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro rl_pre = rl_next;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro}
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro/*
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * Cache IOV domain info in all it's parent's pcie_domain_t
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro *
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * The leaf devices's domain info must be set before calling this function.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorovoid
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloropcie_cache_domain_info(pcie_bus_t *bus_p)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro{
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro boolean_t assigned = PCIE_IS_ASSIGNED(bus_p);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro boolean_t fma_dom = PCIE_ASSIGNED_TO_FMA_DOM(bus_p);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro uint_t domain_id = PCIE_DOMAIN_ID_GET(bus_p);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_req_id_t bdf = bus_p->bus_bdf;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro dev_info_t *pdip;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_bus_t *pbus_p;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_domain_t *pdom_p;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro ASSERT(!PCIE_IS_BDG(bus_p));
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro for (pdip = ddi_get_parent(PCIE_BUS2DIP(bus_p)); PCIE_DIP2BUS(pdip);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pdip = ddi_get_parent(pdip)) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pbus_p = PCIE_DIP2BUS(pdip);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pdom_p = PCIE_BUS2DOM(pbus_p);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (assigned) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (domain_id)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro PCIE_DOMAIN_LIST_ADD(pbus_p, domain_id);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (fma_dom)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pdom_p->fmadom_count++;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro else {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro PCIE_BDF_LIST_ADD(pbus_p, bdf);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pdom_p->nfmadom_count++;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro } else
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pdom_p->rootdom_count++;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro}
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro/*
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * Clear the leaf device's domain info and uncache IOV domain info in all it's
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * parent's pcie_domain_t
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro *
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * The leaf devices's domain info is also cleared by calling this function.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorovoid
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloropcie_uncache_domain_info(pcie_bus_t *bus_p)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro{
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro boolean_t assigned = PCIE_IS_ASSIGNED(bus_p);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro boolean_t fma_dom = PCIE_ASSIGNED_TO_FMA_DOM(bus_p);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro uint_t domain_id = PCIE_DOMAIN_ID_GET(bus_p);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_domain_t *dom_p = PCIE_BUS2DOM(bus_p), *pdom_p;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_bus_t *pbus_p;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro dev_info_t *pdip;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro ASSERT(!PCIE_IS_BDG(bus_p));
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro ASSERT((dom_p->fmadom_count + dom_p->nfmadom_count +
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro dom_p->rootdom_count) == 1);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro /* Clear the domain information */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (domain_id) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro PCIE_DOMAIN_ID_SET(bus_p, NULL);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro PCIE_DOMAIN_ID_DECR_REF_COUNT(bus_p);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro dom_p->fmadom_count = 0;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro dom_p->nfmadom_count = 0;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro dom_p->rootdom_count = 0;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro for (pdip = ddi_get_parent(PCIE_BUS2DIP(bus_p)); PCIE_DIP2BUS(pdip);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pdip = ddi_get_parent(pdip)) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pbus_p = PCIE_DIP2BUS(pdip);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pdom_p = PCIE_BUS2DOM(pbus_p);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (assigned) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (domain_id)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro PCIE_DOMAIN_LIST_REMOVE(pbus_p, domain_id);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (fma_dom)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pdom_p->fmadom_count--;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro else {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pdom_p->nfmadom_count--;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro PCIE_BDF_LIST_REMOVE(pbus_p, bus_p->bus_bdf);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro } else
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pdom_p->rootdom_count--;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro}
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro/*
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * Initialize private data structure for IOV environments.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * o Allocate memory for iov data
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * o Cache Domain ids.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorovoid
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloropcie_init_dom(dev_info_t *dip)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro{
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_domain_t *dom_p = PCIE_ZALLOC(pcie_domain_t);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_bus_t *bus_p = PCIE_DIP2BUS(dip);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro PCIE_BUS2DOM(bus_p) = dom_p;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro /* Only leaf devices are assignable to IO Domains */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (PCIE_IS_BDG(bus_p))
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro /*
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * At the time of init_dom in the root domain a device may or may not
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * have been assigned to an IO Domain.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro *
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * LDOMS: the property "ddi-assigned" will be set for devices that is
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * assignable to an IO domain and unusable in the root domain. If the
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * property exist assume it has been assigned to a non-fma domain until
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * otherwise notified. The domain id is unknown on LDOMS.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro *
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * Xen: the "ddi-assigned" property won't be set until Xen store calls
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * pcie_loan_device is called. In this function this will always look
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * like the device is assigned to the root domain. Domain ID caching
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * will occur in pcie_loan_device function.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro "ddi-assigned", -1) != -1) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro dom_p->nfmadom_count = 1;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro /* Prevent "assigned" device from detaching */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro ndi_hold_devi(dip);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro } else
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro dom_p->rootdom_count = 1;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "ddi-assigned");
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_cache_domain_info(bus_p);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro}
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorovoid
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloropcie_fini_dom(dev_info_t *dip)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro{
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_domain_t *dom_p = PCIE_DIP2DOM(dip);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_bus_t *bus_p = PCIE_DIP2BUS(dip);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (PCIE_IS_BDG(bus_p))
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_domain_list_destroy(PCIE_DOMAIN_LIST_GET(bus_p));
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro else
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_uncache_domain_info(bus_p);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro kmem_free(dom_p, sizeof (pcie_domain_t));
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro}
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro/*
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * PCIe Severity:
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro *
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * PF_ERR_NO_ERROR : no IOV Action
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * PF_ERR_CE : no IOV Action
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * PF_ERR_NO_PANIC : contains error telemetry, log domain info
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * PF_ERR_MATCHED_DEVICE: contains error telemetry, log domain info
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * PF_ERR_MATCHED_RC : Error already taken care of, no further IOV Action
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * PF_ERR_MATCHED_PARENT: Error already taken care of, no further IOV Action
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * PF_ERR_PANIC : contains error telemetry, log domain info
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro *
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * For NO_PANIC, MATCHED_DEVICE and PANIC, IOV wants to look at the affected
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * devices and find the domains involved.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro *
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * If root domain does not own an affected device, IOV EH should change
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * PF_ERR_PANIC to PF_ERR_MATCH_DOM.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloroint
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloropciev_eh(pf_data_t *pfd_p, pf_impl_t *impl)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro{
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro int severity = pfd_p->pe_severity_flags;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro int iov_severity = severity;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_bus_t *a_bus_p; /* Affected device's pcie_bus_t */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pf_data_t *root_pfd_p = impl->pf_dq_head_p;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_bus_t *root_bus_p;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro /*
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * check if all devices under the root device are unassigned.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * this function should quickly return in non-IOV environment.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro ASSERT(root_pfd_p != NULL);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro root_bus_p = PCIE_PFD2BUS(root_pfd_p);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (PCIE_BDG_IS_UNASSIGNED(root_bus_p))
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (severity);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (severity & PF_ERR_PANIC_DEADLOCK) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_faulty_all = B_TRUE;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro } else if (severity & (PF_ERR_NO_PANIC | PF_ERR_MATCHED_DEVICE |
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro PF_ERR_PANIC | PF_ERR_PANIC_BAD_RESPONSE)) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro uint16_t affected_flag, dev_affected_flags;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro uint_t is_panic = 0, is_aff_dev_found = 0;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro dev_affected_flags = PFD_AFFECTED_DEV(pfd_p)->pe_affected_flags;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro /* adjust affected flags to leverage cached domain ids */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (dev_affected_flags & PF_AFFECTED_CHILDREN) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro dev_affected_flags |= PF_AFFECTED_SELF;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro dev_affected_flags &= ~PF_AFFECTED_CHILDREN;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro for (affected_flag = 1;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro affected_flag <= PF_MAX_AFFECTED_FLAG;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro affected_flag <<= 1) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro a_bus_p = pciev_get_affected_dev(impl, pfd_p,
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro affected_flag, dev_affected_flags);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (a_bus_p == NULL)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro continue;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro is_aff_dev_found++;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro PFD_AFFECTED_DEV(pfd_p)->pe_affected_bdf =
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro a_bus_p->bus_bdf;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro /*
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * If a leaf device is assigned to the root domain or if
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * a bridge has children assigned to a root domain
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * panic.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro *
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * If a leaf device or a child of a bridge is assigned
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * to NFMA domain mark it for panic. If assigned to FMA
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * domain save the domain id.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (!PCIE_IS_BDG(a_bus_p) &&
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro !PCIE_IS_ASSIGNED(a_bus_p)) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (severity & PF_ERR_FATAL_FLAGS)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro is_panic++;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro continue;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (PCIE_BDG_HAS_CHILDREN_ROOT_DOM(a_bus_p)) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (severity & PF_ERR_FATAL_FLAGS)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro is_panic++;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if ((PCIE_ASSIGNED_TO_NFMA_DOM(a_bus_p) ||
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro PCIE_BDG_HAS_CHILDREN_NFMA_DOM(a_bus_p)) &&
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro (severity & PF_ERR_FATAL_FLAGS)) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro PCIE_BUS2DOM(a_bus_p)->nfma_panic = B_TRUE;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro iov_severity |= PF_ERR_MATCH_DOM;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (PCIE_ASSIGNED_TO_FMA_DOM(a_bus_p)) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_save_domain_id(
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro &PCIE_BUS2DOM(a_bus_p)->domain.id);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro iov_severity |= PF_ERR_MATCH_DOM;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (PCIE_BDG_HAS_CHILDREN_FMA_DOM(a_bus_p)) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_save_domain_id(
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro PCIE_DOMAIN_LIST_GET(a_bus_p));
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro iov_severity |= PF_ERR_MATCH_DOM;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro /*
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * Overwrite the severity only if affected device can be
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * identified and root domain does not need to panic.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if ((!is_panic) && is_aff_dev_found) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro iov_severity &= ~PF_ERR_FATAL_FLAGS;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (iov_severity);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro}
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro/* ARGSUSED */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorovoid
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloropciev_eh_exit(pf_data_t *root_pfd_p, uint_t intr_type)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro{
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_bus_t *root_bus_p;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro /*
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * check if all devices under the root device are unassigned.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * this function should quickly return in non-IOV environment.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro root_bus_p = PCIE_PFD2BUS(root_pfd_p);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (PCIE_BDG_IS_UNASSIGNED(root_bus_p))
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_faulty_list_clear();
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro}
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloropcie_bus_t *
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloropciev_get_affected_dev(pf_impl_t *impl, pf_data_t *pfd_p,
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro uint16_t affected_flag, uint16_t dev_affected_flags)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro{
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_bus_t *bus_p = PCIE_PFD2BUS(pfd_p);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro uint16_t flag = affected_flag & dev_affected_flags;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_bus_t *temp_bus_p;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_req_id_t a_bdf;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro uint64_t a_addr;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro uint16_t cmd;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (!flag)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (NULL);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro switch (flag) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro case PF_AFFECTED_ROOT:
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (PCIE_DIP2BUS(bus_p->bus_rp_dip));
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro case PF_AFFECTED_SELF:
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (bus_p);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro case PF_AFFECTED_PARENT:
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (PCIE_DIP2BUS(ddi_get_parent(PCIE_BUS2DIP(bus_p))));
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro case PF_AFFECTED_BDF: /* may only be used for RC */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro a_bdf = PFD_AFFECTED_DEV(pfd_p)->pe_affected_bdf;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (!PCIE_CHECK_VALID_BDF(a_bdf))
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (NULL);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro temp_bus_p = pf_find_busp_by_bdf(impl, a_bdf);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (temp_bus_p);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro case PF_AFFECTED_AER:
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (pf_tlp_decode(bus_p, PCIE_ADV_REG(pfd_p)) == DDI_SUCCESS) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro temp_bus_p = pf_find_busp_by_aer(impl, pfd_p);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (temp_bus_p);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro break;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro case PF_AFFECTED_SAER:
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (pf_pci_decode(pfd_p, &cmd) == DDI_SUCCESS) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro temp_bus_p = pf_find_busp_by_saer(impl, pfd_p);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (temp_bus_p);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro break;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro case PF_AFFECTED_ADDR: /* ROOT only */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro a_addr = PCIE_ROOT_FAULT(pfd_p)->scan_addr;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro temp_bus_p = pf_find_busp_by_addr(impl, a_addr);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (temp_bus_p);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (NULL);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro}
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro/* type used for pcie_domain_list_find() function */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorotypedef enum {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro PCIE_DOM_LIST_TYPE_CACHE = 1,
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro PCIE_DOM_LIST_TYPE_FAULT = 2
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro} pcie_dom_list_type_t;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro/*
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * Check if a domain id is already in the linked list
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorostatic pcie_domains_t *
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloropcie_domain_list_find(uint_t domain_id, pcie_domains_t *pd_list_p,
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_dom_list_type_t type)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro{
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro while (pd_list_p) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (pd_list_p->domain_id == domain_id)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (pd_list_p);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (type == PCIE_DOM_LIST_TYPE_CACHE) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pd_list_p = pd_list_p->cached_next;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro } else if (type == PCIE_DOM_LIST_TYPE_FAULT) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pd_list_p = pd_list_p->faulty_next;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro } else {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (NULL);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (NULL);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro}
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro/*
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * Return true if a leaf device is assigned to a domain or a bridge device
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * has children assigned to the domain
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloroboolean_t
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloropcie_in_domain(pcie_bus_t *bus_p, uint_t domain_id)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro{
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (PCIE_IS_BDG(bus_p)) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_domains_t *pd;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pd = pcie_domain_list_find(domain_id,
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro PCIE_DOMAIN_LIST_GET(bus_p), PCIE_DOM_LIST_TYPE_CACHE);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (pd && pd->cached_count)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (B_TRUE);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (B_FALSE);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro } else {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return (PCIE_DOMAIN_ID_GET(bus_p) == domain_id);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro}
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro/*
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * Add a domain id to a cached domain id list.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * If the domain already exists in the list, increment the reference count.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorovoid
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloropcie_domain_list_add(uint_t domain_id, pcie_domains_t **pd_list_p)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro{
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_domains_t *pd;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pd = pcie_domain_list_find(domain_id, *pd_list_p,
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro PCIE_DOM_LIST_TYPE_CACHE);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (pd == NULL) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pd = PCIE_ZALLOC(pcie_domains_t);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pd->domain_id = domain_id;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pd->cached_count = 1;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pd->cached_next = *pd_list_p;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro *pd_list_p = pd;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro } else
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pd->cached_count++;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro}
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro/*
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * Remove a domain id from a cached domain id list.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro * Decrement the reference count.
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorovoid
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloropcie_domain_list_remove(uint_t domain_id, pcie_domains_t *pd_list_p)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro{
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_domains_t *pd;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pd = pcie_domain_list_find(domain_id, pd_list_p,
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro PCIE_DOM_LIST_TYPE_CACHE);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (pd) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro ASSERT((pd->cached_count)--);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro}
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro/* destroy cached domain id list */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorostatic void
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloropcie_domain_list_destroy(pcie_domains_t *domain_ids)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro{
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_domains_t *p = domain_ids;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_domains_t *next;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro while (p) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro next = p->cached_next;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro kmem_free(p, sizeof (pcie_domains_t));
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro p = next;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro}
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorostatic void
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloropcie_faulty_list_update(pcie_domains_t *pd,
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_domains_t **headp)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro{
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (pd == NULL)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (*headp == NULL) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro *headp = pd;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pd->faulty_prev = NULL;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pd->faulty_next = NULL;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pd->faulty_count = 1;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro } else {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pd->faulty_next = *headp;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro (*headp)->faulty_prev = pd;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pd->faulty_prev = NULL;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pd->faulty_count = 1;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro *headp = pd;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro}
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorostatic void
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloropcie_faulty_list_clear()
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro{
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_domains_t *pd = pcie_faulty_domains;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_domains_t *next;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro /* unlink all domain structures from the faulty list */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro while (pd) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro next = pd->faulty_next;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pd->faulty_prev = NULL;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pd->faulty_next = NULL;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pd->faulty_count = 0;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pd = next;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_faulty_domains = NULL;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_faulty_all = B_FALSE;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro}
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Belorovoid
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloropcie_save_domain_id(pcie_domains_t *domain_ids)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro{
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_domains_t *old_list_p, *new_list_p, *pd;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (pcie_faulty_all)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (domain_ids == NULL)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro return;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro old_list_p = pcie_faulty_domains;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro for (new_list_p = domain_ids; new_list_p;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro new_list_p = new_list_p->cached_next) {
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (!new_list_p->cached_count)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro continue;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro /* search domain id in the faulty domain list */
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pd = pcie_domain_list_find(new_list_p->domain_id,
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro old_list_p, PCIE_DOM_LIST_TYPE_FAULT);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro if (pd)
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pd->faulty_count++;
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro else
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro pcie_faulty_list_update(new_list_p,
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro &pcie_faulty_domains);
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro }
fc256490629fe68815f7e0f23cf9b3545720cfacJason Beloro}