7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * CDDL HEADER START
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * The contents of this file are subject to the terms of the
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Common Development and Distribution License (the "License").
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * You may not use this file except in compliance with the License.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * or http://www.opensolaris.org/os/licensing.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * See the License for the specific language governing permissions
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * and limitations under the License.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * When distributing Covered Code, include this CDDL HEADER in each
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * If applicable, add the following below this CDDL HEADER, with the
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * fields enclosed by brackets "[]" replaced with your own identifying
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * information: Portions Copyright [yyyy] [name of copyright owner]
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * CDDL HEADER END
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*
186d582bd9dbcd38e0aeea49036d47d3426a3536Surya Prakki * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Use is subject to license terms.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
29493bd8e037cbaea9095b34172305abb589cb6bvn#include <strings.h>
29493bd8e037cbaea9095b34172305abb589cb6bvn#include <sys/fm/protocol.h>
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi#include <fm/topo_hc.h>
29493bd8e037cbaea9095b34172305abb589cb6bvn#include <fm/topo_mod.h>
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi#include <hb_sun4.h>
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi#include <hostbridge.h>
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi#include <pcibus.h>
29493bd8e037cbaea9095b34172305abb589cb6bvn#include <did.h>
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi#include <util.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
29493bd8e037cbaea9095b34172305abb589cb6bvn#include "hb_mdesc.h"
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
29493bd8e037cbaea9095b34172305abb589cb6bvnstatic const topo_pgroup_info_t io_pgroup =
29493bd8e037cbaea9095b34172305abb589cb6bvn { TOPO_PGROUP_IO, TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 };
29493bd8e037cbaea9095b34172305abb589cb6bvnstatic const topo_pgroup_info_t pci_pgroup =
29493bd8e037cbaea9095b34172305abb589cb6bvn { TOPO_PGROUP_PCI, TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 };
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
29493bd8e037cbaea9095b34172305abb589cb6bvn/*
29493bd8e037cbaea9095b34172305abb589cb6bvn * get_rcs()
29493bd8e037cbaea9095b34172305abb589cb6bvn * Description:
29493bd8e037cbaea9095b34172305abb589cb6bvn * Return a list of PX instances in the dev tree.
29493bd8e037cbaea9095b34172305abb589cb6bvn */
29493bd8e037cbaea9095b34172305abb589cb6bvnstatic busorrc_t *
29493bd8e037cbaea9095b34172305abb589cb6bvnget_rcs(topo_mod_t *mod)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi busorrc_t *rcs = NULL;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi di_node_t devtree;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi di_node_t pnode;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /* Scan for buses, top-level devinfo nodes with the right driver */
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi devtree = topo_mod_devinfo(mod);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (devtree == DI_NODE_NIL) {
29493bd8e037cbaea9095b34172305abb589cb6bvn topo_mod_dprintf(mod, "devinfo init failed.\n");
29493bd8e037cbaea9095b34172305abb589cb6bvn return (NULL);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi pnode = di_drv_first_node(PX, devtree);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi while (pnode != DI_NODE_NIL) {
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi if (busorrc_add(mod, &rcs, pnode) < 0) {
29493bd8e037cbaea9095b34172305abb589cb6bvn topo_mod_dprintf(mod, "busorrc_add() failed.\n");
29493bd8e037cbaea9095b34172305abb589cb6bvn busorrc_free(mod, rcs);
29493bd8e037cbaea9095b34172305abb589cb6bvn return (NULL);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi pnode = di_drv_next_node(pnode);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
29493bd8e037cbaea9095b34172305abb589cb6bvn return (rcs);
29493bd8e037cbaea9095b34172305abb589cb6bvn}
29493bd8e037cbaea9095b34172305abb589cb6bvn
29493bd8e037cbaea9095b34172305abb589cb6bvn/*
29493bd8e037cbaea9095b34172305abb589cb6bvn * find_dnode()
29493bd8e037cbaea9095b34172305abb589cb6bvn * Description:
29493bd8e037cbaea9095b34172305abb589cb6bvn * Find the dev pointer of a rc given its bus address, ba
29493bd8e037cbaea9095b34172305abb589cb6bvn */
29493bd8e037cbaea9095b34172305abb589cb6bvnstatic di_node_t
29493bd8e037cbaea9095b34172305abb589cb6bvnfind_dnode(busorrc_t *rcs, uint64_t ba)
29493bd8e037cbaea9095b34172305abb589cb6bvn{
29493bd8e037cbaea9095b34172305abb589cb6bvn busorrc_t *p;
29493bd8e037cbaea9095b34172305abb589cb6bvn for (p = rcs; p != NULL; p = p->br_nextbus) {
29493bd8e037cbaea9095b34172305abb589cb6bvn if (ba == p->br_ba_bc) {
29493bd8e037cbaea9095b34172305abb589cb6bvn return (p->br_din);
29493bd8e037cbaea9095b34172305abb589cb6bvn }
29493bd8e037cbaea9095b34172305abb589cb6bvn }
29493bd8e037cbaea9095b34172305abb589cb6bvn return (NULL);
29493bd8e037cbaea9095b34172305abb589cb6bvn}
29493bd8e037cbaea9095b34172305abb589cb6bvn
29493bd8e037cbaea9095b34172305abb589cb6bvn/*
29493bd8e037cbaea9095b34172305abb589cb6bvn * hb_tnode_create()
29493bd8e037cbaea9095b34172305abb589cb6bvn * Description:
29493bd8e037cbaea9095b34172305abb589cb6bvn * Create a topo node
29493bd8e037cbaea9095b34172305abb589cb6bvn */
29493bd8e037cbaea9095b34172305abb589cb6bvnstatic tnode_t *
29493bd8e037cbaea9095b34172305abb589cb6bvnhb_tnode_create(topo_mod_t *mod, tnode_t *parent, const char *name,
29493bd8e037cbaea9095b34172305abb589cb6bvn int inst, void *priv)
29493bd8e037cbaea9095b34172305abb589cb6bvn{
29493bd8e037cbaea9095b34172305abb589cb6bvn int err;
29493bd8e037cbaea9095b34172305abb589cb6bvn tnode_t *node;
29493bd8e037cbaea9095b34172305abb589cb6bvn nvlist_t *fmri;
29493bd8e037cbaea9095b34172305abb589cb6bvn nvlist_t *auth = topo_mod_auth(mod, parent);
29493bd8e037cbaea9095b34172305abb589cb6bvn
29493bd8e037cbaea9095b34172305abb589cb6bvn if (parent == NULL || inst < 0) {
29493bd8e037cbaea9095b34172305abb589cb6bvn return (NULL);
29493bd8e037cbaea9095b34172305abb589cb6bvn }
29493bd8e037cbaea9095b34172305abb589cb6bvn
29493bd8e037cbaea9095b34172305abb589cb6bvn /* Create FMRI */
29493bd8e037cbaea9095b34172305abb589cb6bvn if ((fmri = topo_mod_hcfmri(mod, parent, FM_HC_SCHEME_VERSION, name,
29493bd8e037cbaea9095b34172305abb589cb6bvn inst, NULL, auth, NULL, NULL, NULL)) == NULL) {
29493bd8e037cbaea9095b34172305abb589cb6bvn topo_mod_dprintf(mod, "create of tnode for %s failed: %s\n",
29493bd8e037cbaea9095b34172305abb589cb6bvn name, topo_strerror(topo_mod_errno(mod)));
29493bd8e037cbaea9095b34172305abb589cb6bvn nvlist_free(auth);
29493bd8e037cbaea9095b34172305abb589cb6bvn return (NULL);
29493bd8e037cbaea9095b34172305abb589cb6bvn }
29493bd8e037cbaea9095b34172305abb589cb6bvn nvlist_free(auth);
29493bd8e037cbaea9095b34172305abb589cb6bvn
29493bd8e037cbaea9095b34172305abb589cb6bvn /* Create and bind node */
29493bd8e037cbaea9095b34172305abb589cb6bvn node = topo_node_bind(mod, parent, name, inst, fmri);
29493bd8e037cbaea9095b34172305abb589cb6bvn if (node == NULL) {
29493bd8e037cbaea9095b34172305abb589cb6bvn nvlist_free(fmri);
29493bd8e037cbaea9095b34172305abb589cb6bvn topo_mod_dprintf(mod, "unable to bind a node(%s): %s\n",
29493bd8e037cbaea9095b34172305abb589cb6bvn name, topo_strerror(topo_mod_errno(mod)));
29493bd8e037cbaea9095b34172305abb589cb6bvn return (NULL); /* mod_errno already set */
29493bd8e037cbaea9095b34172305abb589cb6bvn }
29493bd8e037cbaea9095b34172305abb589cb6bvn
29493bd8e037cbaea9095b34172305abb589cb6bvn nvlist_free(fmri);
29493bd8e037cbaea9095b34172305abb589cb6bvn topo_node_setspecific(node, priv);
29493bd8e037cbaea9095b34172305abb589cb6bvn
29493bd8e037cbaea9095b34172305abb589cb6bvn /* Inherit the parent 's FRU and label */
29493bd8e037cbaea9095b34172305abb589cb6bvn (void) topo_node_fru_set(node, NULL, 0, &err);
29493bd8e037cbaea9095b34172305abb589cb6bvn (void) topo_node_label_set(node, NULL, &err);
29493bd8e037cbaea9095b34172305abb589cb6bvn
29493bd8e037cbaea9095b34172305abb589cb6bvn return (node);
29493bd8e037cbaea9095b34172305abb589cb6bvn}
29493bd8e037cbaea9095b34172305abb589cb6bvn
29493bd8e037cbaea9095b34172305abb589cb6bvn/*
29493bd8e037cbaea9095b34172305abb589cb6bvn * platform_pciexhostbridge_declare()
29493bd8e037cbaea9095b34172305abb589cb6bvn * Description:
29493bd8e037cbaea9095b34172305abb589cb6bvn * This is a sun4v specific function to create the hostbridge topo node.
29493bd8e037cbaea9095b34172305abb589cb6bvn */
29493bd8e037cbaea9095b34172305abb589cb6bvntnode_t *
29493bd8e037cbaea9095b34172305abb589cb6bvnplatform_pciexhostbridge_declare(topo_mod_t *mod, tnode_t *parent,
29493bd8e037cbaea9095b34172305abb589cb6bvn topo_instance_t inst)
29493bd8e037cbaea9095b34172305abb589cb6bvn{
29493bd8e037cbaea9095b34172305abb589cb6bvn tnode_t *hbn;
29493bd8e037cbaea9095b34172305abb589cb6bvn void *priv = NULL;
29493bd8e037cbaea9095b34172305abb589cb6bvn
29493bd8e037cbaea9095b34172305abb589cb6bvn topo_mod_dprintf(mod, "Create node %s=%d\n", HOSTBRIDGE, inst);
29493bd8e037cbaea9095b34172305abb589cb6bvn
29493bd8e037cbaea9095b34172305abb589cb6bvn hbn = hb_tnode_create(mod, parent, HOSTBRIDGE, inst, priv);
29493bd8e037cbaea9095b34172305abb589cb6bvn if (hbn == NULL) {
29493bd8e037cbaea9095b34172305abb589cb6bvn topo_mod_dprintf(mod, "Failed to create node %s=%d\n",
29493bd8e037cbaea9095b34172305abb589cb6bvn HOSTBRIDGE, inst);
29493bd8e037cbaea9095b34172305abb589cb6bvn return (NULL);
29493bd8e037cbaea9095b34172305abb589cb6bvn }
29493bd8e037cbaea9095b34172305abb589cb6bvn
29493bd8e037cbaea9095b34172305abb589cb6bvn /* Make room for children */
186d582bd9dbcd38e0aeea49036d47d3426a3536Surya Prakki (void) topo_node_range_create(mod, hbn, PCIEX_ROOT, 0, MAX_HB_BUSES);
29493bd8e037cbaea9095b34172305abb589cb6bvn
29493bd8e037cbaea9095b34172305abb589cb6bvn return (hbn);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
29493bd8e037cbaea9095b34172305abb589cb6bvn/*
29493bd8e037cbaea9095b34172305abb589cb6bvn * platform_pciexhostbridge_declare()
29493bd8e037cbaea9095b34172305abb589cb6bvn * Description:
29493bd8e037cbaea9095b34172305abb589cb6bvn * This is a sun4v specific function to create a root complex topo node,
29493bd8e037cbaea9095b34172305abb589cb6bvn * but do not enumerate its pci buses.
29493bd8e037cbaea9095b34172305abb589cb6bvn */
29493bd8e037cbaea9095b34172305abb589cb6bvnstatic tnode_t *
29493bd8e037cbaea9095b34172305abb589cb6bvnplatform_pciexrc_declare(topo_mod_t *mod, tnode_t *parent, int inst,
29493bd8e037cbaea9095b34172305abb589cb6bvn uint64_t ba)
29493bd8e037cbaea9095b34172305abb589cb6bvn{
29493bd8e037cbaea9095b34172305abb589cb6bvn int err;
29493bd8e037cbaea9095b34172305abb589cb6bvn tnode_t *rcn;
29493bd8e037cbaea9095b34172305abb589cb6bvn char dnpath[MAXPATHLEN];
29493bd8e037cbaea9095b34172305abb589cb6bvn nvlist_t *fmri;
29493bd8e037cbaea9095b34172305abb589cb6bvn
29493bd8e037cbaea9095b34172305abb589cb6bvn topo_mod_dprintf(mod, "Create node %s=%d\n", PCIEX_ROOT, inst);
29493bd8e037cbaea9095b34172305abb589cb6bvn
29493bd8e037cbaea9095b34172305abb589cb6bvn rcn = hb_tnode_create(mod, parent, PCIEX_ROOT, inst, NULL);
29493bd8e037cbaea9095b34172305abb589cb6bvn if (rcn == NULL) {
29493bd8e037cbaea9095b34172305abb589cb6bvn topo_mod_dprintf(mod, "Failed to create node %s=%d\n",
29493bd8e037cbaea9095b34172305abb589cb6bvn PCIEX_ROOT, inst);
29493bd8e037cbaea9095b34172305abb589cb6bvn return (NULL);
29493bd8e037cbaea9095b34172305abb589cb6bvn }
29493bd8e037cbaea9095b34172305abb589cb6bvn
29493bd8e037cbaea9095b34172305abb589cb6bvn /* Set ASRU to be the dev-scheme asru */
29493bd8e037cbaea9095b34172305abb589cb6bvn (void) snprintf(dnpath, sizeof (dnpath), "/pci@%llx", ba);
29493bd8e037cbaea9095b34172305abb589cb6bvn fmri = topo_mod_devfmri(mod, FM_DEV_SCHEME_VERSION, dnpath, NULL);
29493bd8e037cbaea9095b34172305abb589cb6bvn if (fmri == NULL) {
29493bd8e037cbaea9095b34172305abb589cb6bvn topo_mod_dprintf(mod, "dev:///%s fmri creation failed.\n",
29493bd8e037cbaea9095b34172305abb589cb6bvn dnpath);
29493bd8e037cbaea9095b34172305abb589cb6bvn return (NULL);
29493bd8e037cbaea9095b34172305abb589cb6bvn }
29493bd8e037cbaea9095b34172305abb589cb6bvn if (topo_node_asru_set(rcn, fmri, 0, &err) < 0) {
29493bd8e037cbaea9095b34172305abb589cb6bvn topo_mod_dprintf(mod, "topo_node_asru_set failed\n");
186d582bd9dbcd38e0aeea49036d47d3426a3536Surya Prakki (void) topo_mod_seterrno(mod, err);
29493bd8e037cbaea9095b34172305abb589cb6bvn nvlist_free(fmri);
29493bd8e037cbaea9095b34172305abb589cb6bvn return (NULL);
29493bd8e037cbaea9095b34172305abb589cb6bvn }
29493bd8e037cbaea9095b34172305abb589cb6bvn nvlist_free(fmri);
29493bd8e037cbaea9095b34172305abb589cb6bvn
29493bd8e037cbaea9095b34172305abb589cb6bvn /*
29493bd8e037cbaea9095b34172305abb589cb6bvn * Set properties of the root complex node pciexrc
29493bd8e037cbaea9095b34172305abb589cb6bvn */
29493bd8e037cbaea9095b34172305abb589cb6bvn
29493bd8e037cbaea9095b34172305abb589cb6bvn /* Add the io and pci property groups */
29493bd8e037cbaea9095b34172305abb589cb6bvn if (topo_pgroup_create(rcn, &io_pgroup, &err) < 0) {
29493bd8e037cbaea9095b34172305abb589cb6bvn topo_mod_dprintf(mod, "topo_pgroup_create(iogrp) failed\n");
186d582bd9dbcd38e0aeea49036d47d3426a3536Surya Prakki (void) topo_mod_seterrno(mod, err);
29493bd8e037cbaea9095b34172305abb589cb6bvn return (NULL);
29493bd8e037cbaea9095b34172305abb589cb6bvn }
29493bd8e037cbaea9095b34172305abb589cb6bvn if (topo_pgroup_create(rcn, &pci_pgroup, &err) < 0) {
29493bd8e037cbaea9095b34172305abb589cb6bvn topo_mod_dprintf(mod, "topo_pgroup_create(pcigrp) failed\n");
186d582bd9dbcd38e0aeea49036d47d3426a3536Surya Prakki (void) topo_mod_seterrno(mod, err);
29493bd8e037cbaea9095b34172305abb589cb6bvn return (NULL);
29493bd8e037cbaea9095b34172305abb589cb6bvn }
29493bd8e037cbaea9095b34172305abb589cb6bvn /* Add the devfs path property */
29493bd8e037cbaea9095b34172305abb589cb6bvn if (topo_prop_set_string(rcn, TOPO_PGROUP_IO, TOPO_IO_DEV,
29493bd8e037cbaea9095b34172305abb589cb6bvn TOPO_PROP_IMMUTABLE, dnpath, &err) != 0) {
29493bd8e037cbaea9095b34172305abb589cb6bvn topo_mod_dprintf(mod, "Failed to set %s property\n",
29493bd8e037cbaea9095b34172305abb589cb6bvn TOPO_IO_DEV);
186d582bd9dbcd38e0aeea49036d47d3426a3536Surya Prakki (void) topo_mod_seterrno(mod, err);
29493bd8e037cbaea9095b34172305abb589cb6bvn return (NULL);
29493bd8e037cbaea9095b34172305abb589cb6bvn }
29493bd8e037cbaea9095b34172305abb589cb6bvn
29493bd8e037cbaea9095b34172305abb589cb6bvn /* for sun4v, device type is always pciex */
29493bd8e037cbaea9095b34172305abb589cb6bvn if (topo_prop_set_string(rcn, TOPO_PGROUP_IO, TOPO_IO_DEVTYPE,
29493bd8e037cbaea9095b34172305abb589cb6bvn TOPO_PROP_IMMUTABLE, PCIEXTYPE, &err) != 0) {
29493bd8e037cbaea9095b34172305abb589cb6bvn topo_mod_dprintf(mod, "Failed to set %s property\n",
29493bd8e037cbaea9095b34172305abb589cb6bvn TOPO_IO_DEVTYPE);
29493bd8e037cbaea9095b34172305abb589cb6bvn }
29493bd8e037cbaea9095b34172305abb589cb6bvn
29493bd8e037cbaea9095b34172305abb589cb6bvn /* sun4v rc driver is always "px" */
29493bd8e037cbaea9095b34172305abb589cb6bvn if (topo_prop_set_string(rcn, TOPO_PGROUP_IO, TOPO_IO_DRIVER,
29493bd8e037cbaea9095b34172305abb589cb6bvn TOPO_PROP_IMMUTABLE, PX, &err) != 0) {
29493bd8e037cbaea9095b34172305abb589cb6bvn topo_mod_dprintf(mod, "Failed to set %s property\n",
29493bd8e037cbaea9095b34172305abb589cb6bvn TOPO_IO_DRIVER);
29493bd8e037cbaea9095b34172305abb589cb6bvn }
29493bd8e037cbaea9095b34172305abb589cb6bvn if ((fmri = topo_mod_modfmri(mod, FM_MOD_SCHEME_VERSION, PX)) == NULL ||
29493bd8e037cbaea9095b34172305abb589cb6bvn (topo_prop_set_fmri(rcn, TOPO_PGROUP_IO, TOPO_IO_MODULE,
29493bd8e037cbaea9095b34172305abb589cb6bvn TOPO_PROP_IMMUTABLE, fmri, &err) != 0)) {
29493bd8e037cbaea9095b34172305abb589cb6bvn topo_mod_dprintf(mod, "Failed to set %s property\n",
29493bd8e037cbaea9095b34172305abb589cb6bvn TOPO_IO_MODULE);
29493bd8e037cbaea9095b34172305abb589cb6bvn }
29493bd8e037cbaea9095b34172305abb589cb6bvn nvlist_free(fmri);
29493bd8e037cbaea9095b34172305abb589cb6bvn
29493bd8e037cbaea9095b34172305abb589cb6bvn /* This is a PCIEX Root Complex */
29493bd8e037cbaea9095b34172305abb589cb6bvn if (topo_prop_set_string(rcn, TOPO_PGROUP_PCI, TOPO_PCI_EXCAP,
29493bd8e037cbaea9095b34172305abb589cb6bvn TOPO_PROP_IMMUTABLE, PCIEX_ROOT, &err) != 0) {
29493bd8e037cbaea9095b34172305abb589cb6bvn topo_mod_dprintf(mod, "Failed to set %s property\n",
29493bd8e037cbaea9095b34172305abb589cb6bvn TOPO_PCI_EXCAP);
29493bd8e037cbaea9095b34172305abb589cb6bvn }
29493bd8e037cbaea9095b34172305abb589cb6bvn
29493bd8e037cbaea9095b34172305abb589cb6bvn /* Make room for children */
186d582bd9dbcd38e0aeea49036d47d3426a3536Surya Prakki (void) topo_node_range_create(mod, rcn, PCIEX_BUS, 0, MAX_HB_BUSES);
29493bd8e037cbaea9095b34172305abb589cb6bvn
29493bd8e037cbaea9095b34172305abb589cb6bvn return (rcn);
29493bd8e037cbaea9095b34172305abb589cb6bvn}
29493bd8e037cbaea9095b34172305abb589cb6bvn
29493bd8e037cbaea9095b34172305abb589cb6bvn/*
29493bd8e037cbaea9095b34172305abb589cb6bvn * platform_hb_enum()
29493bd8e037cbaea9095b34172305abb589cb6bvn * Description:
29493bd8e037cbaea9095b34172305abb589cb6bvn * This is an entry function to enumerate the sun4v hostbridges. First, it
29493bd8e037cbaea9095b34172305abb589cb6bvn * reads the hostbridges and their pciexrc root complexes from the PRI or
29493bd8e037cbaea9095b34172305abb589cb6bvn * MD.
29493bd8e037cbaea9095b34172305abb589cb6bvn * For the current sun4v platforms, it is assummed that there is only one
29493bd8e037cbaea9095b34172305abb589cb6bvn * hostbridge. All the pciex root complexes belong to this single hostbridge.
29493bd8e037cbaea9095b34172305abb589cb6bvn * Given the hostbridge/pciexrc information, this enumerator creates the
29493bd8e037cbaea9095b34172305abb589cb6bvn * the hostbridge topo node and pciexrc nodes. If the domain owns the
29493bd8e037cbaea9095b34172305abb589cb6bvn * the root complex, it uses the common hostbridge code to enumerate the
29493bd8e037cbaea9095b34172305abb589cb6bvn * pcibus. If not, it simply create the hostbridge/pciexrc nodes without the
29493bd8e037cbaea9095b34172305abb589cb6bvn * fabric.
29493bd8e037cbaea9095b34172305abb589cb6bvn */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*ARGSUSED*/
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindiint
0eb822a1c0c2bea495647510b75f77f0e57633ebcindiplatform_hb_enum(topo_mod_t *mod, tnode_t *parent, const char *name,
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi topo_instance_t imin, topo_instance_t imax)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
29493bd8e037cbaea9095b34172305abb589cb6bvn int i, j;
29493bd8e037cbaea9095b34172305abb589cb6bvn int err = 0;
29493bd8e037cbaea9095b34172305abb589cb6bvn md_hb_t *hbp;
29493bd8e037cbaea9095b34172305abb589cb6bvn md_rc_t *rcp;
29493bd8e037cbaea9095b34172305abb589cb6bvn md_info_t hbmd;
29493bd8e037cbaea9095b34172305abb589cb6bvn tnode_t **hbnode;
29493bd8e037cbaea9095b34172305abb589cb6bvn int nhbnode = 0;
29493bd8e037cbaea9095b34172305abb589cb6bvn tnode_t **rcnode;
29493bd8e037cbaea9095b34172305abb589cb6bvn int nrcs, nrcnode = 0;
29493bd8e037cbaea9095b34172305abb589cb6bvn busorrc_t *rcs;
29493bd8e037cbaea9095b34172305abb589cb6bvn
29493bd8e037cbaea9095b34172305abb589cb6bvn if (imin < 0 || imax < 0 || imin > imax) {
29493bd8e037cbaea9095b34172305abb589cb6bvn topo_mod_dprintf(mod, "Invalid hb range(%d,%d)\n", imin, imax);
29493bd8e037cbaea9095b34172305abb589cb6bvn return (-1);
29493bd8e037cbaea9095b34172305abb589cb6bvn }
29493bd8e037cbaea9095b34172305abb589cb6bvn
29493bd8e037cbaea9095b34172305abb589cb6bvn /* get the hostbrige and rootcomplex information in the PRI/MD */
29493bd8e037cbaea9095b34172305abb589cb6bvn (void) bzero((void *) &hbmd, sizeof (hbmd));
29493bd8e037cbaea9095b34172305abb589cb6bvn if (hb_mdesc_init(mod, &hbmd) != 0) {
29493bd8e037cbaea9095b34172305abb589cb6bvn topo_mod_dprintf(mod, "failed to get hb from the PRI/MD\n");
29493bd8e037cbaea9095b34172305abb589cb6bvn return (-1);
29493bd8e037cbaea9095b34172305abb589cb6bvn }
29493bd8e037cbaea9095b34172305abb589cb6bvn
29493bd8e037cbaea9095b34172305abb589cb6bvn /* count the number of hb and rc in the PRI/MD */
29493bd8e037cbaea9095b34172305abb589cb6bvn nrcs = 0;
29493bd8e037cbaea9095b34172305abb589cb6bvn for (i = 0, hbp = hbmd.hbs; i < hbmd.shbs; i++, hbp++) {
29493bd8e037cbaea9095b34172305abb589cb6bvn if (hbp->id < 0)
29493bd8e037cbaea9095b34172305abb589cb6bvn continue;
29493bd8e037cbaea9095b34172305abb589cb6bvn nrcs += hbp->srcs;
29493bd8e037cbaea9095b34172305abb589cb6bvn }
29493bd8e037cbaea9095b34172305abb589cb6bvn if (hbmd.shbs <= 0 || nrcs <= 0) {
29493bd8e037cbaea9095b34172305abb589cb6bvn topo_mod_dprintf(mod, "No hostbridge or pciex bus is found\n");
29493bd8e037cbaea9095b34172305abb589cb6bvn topo_node_range_destroy(parent, HOSTBRIDGE);
29493bd8e037cbaea9095b34172305abb589cb6bvn hb_mdesc_fini(mod, &hbmd);
29493bd8e037cbaea9095b34172305abb589cb6bvn return (0);
29493bd8e037cbaea9095b34172305abb589cb6bvn }
29493bd8e037cbaea9095b34172305abb589cb6bvn hbnode = topo_mod_zalloc(mod, hbmd.shbs * sizeof (tnode_t *));
29493bd8e037cbaea9095b34172305abb589cb6bvn rcnode = topo_mod_zalloc(mod, nrcs * sizeof (tnode_t *));
29493bd8e037cbaea9095b34172305abb589cb6bvn rcs = get_rcs(mod);
29493bd8e037cbaea9095b34172305abb589cb6bvn
29493bd8e037cbaea9095b34172305abb589cb6bvn /* process the hostbridge */
29493bd8e037cbaea9095b34172305abb589cb6bvn for (i = imin; (i <= imax) && (err == 0); i++) {
29493bd8e037cbaea9095b34172305abb589cb6bvn int brd = 0;
29493bd8e037cbaea9095b34172305abb589cb6bvn di_node_t dnode1, dnode2;
29493bd8e037cbaea9095b34172305abb589cb6bvn
29493bd8e037cbaea9095b34172305abb589cb6bvn if ((hbp = hb_find_hb(&hbmd, i)) == NULL) {
29493bd8e037cbaea9095b34172305abb589cb6bvn continue;
29493bd8e037cbaea9095b34172305abb589cb6bvn }
29493bd8e037cbaea9095b34172305abb589cb6bvn
29493bd8e037cbaea9095b34172305abb589cb6bvn dnode2 = NULL;
29493bd8e037cbaea9095b34172305abb589cb6bvn for (j = 0, rcp = hbp->rcs; j < hbp->srcs; j++, rcp++) {
29493bd8e037cbaea9095b34172305abb589cb6bvn if (rcp->id < 0)
29493bd8e037cbaea9095b34172305abb589cb6bvn continue;
29493bd8e037cbaea9095b34172305abb589cb6bvn dnode1 = find_dnode(rcs, rcp->cfg_handle);
29493bd8e037cbaea9095b34172305abb589cb6bvn if (dnode1 != NULL) {
29493bd8e037cbaea9095b34172305abb589cb6bvn dnode2 = dnode1;
29493bd8e037cbaea9095b34172305abb589cb6bvn if (did_create(mod, dnode1, brd, hbp->id,
29493bd8e037cbaea9095b34172305abb589cb6bvn rcp->id, rcp->id) == NULL) {
29493bd8e037cbaea9095b34172305abb589cb6bvn err = -1;
29493bd8e037cbaea9095b34172305abb589cb6bvn break;
29493bd8e037cbaea9095b34172305abb589cb6bvn }
29493bd8e037cbaea9095b34172305abb589cb6bvn }
29493bd8e037cbaea9095b34172305abb589cb6bvn }
29493bd8e037cbaea9095b34172305abb589cb6bvn
29493bd8e037cbaea9095b34172305abb589cb6bvn if (err != 0)
29493bd8e037cbaea9095b34172305abb589cb6bvn break;
29493bd8e037cbaea9095b34172305abb589cb6bvn
29493bd8e037cbaea9095b34172305abb589cb6bvn /*
29493bd8e037cbaea9095b34172305abb589cb6bvn * If this hb has a rc in the dev tree, use the common code to
29493bd8e037cbaea9095b34172305abb589cb6bvn * create a hostbridge node
29493bd8e037cbaea9095b34172305abb589cb6bvn */
29493bd8e037cbaea9095b34172305abb589cb6bvn if (dnode2 != NULL) {
29493bd8e037cbaea9095b34172305abb589cb6bvn hbnode[nhbnode] = pciexhostbridge_declare(mod, parent,
29493bd8e037cbaea9095b34172305abb589cb6bvn dnode2, hbp->id);
29493bd8e037cbaea9095b34172305abb589cb6bvn } else {
29493bd8e037cbaea9095b34172305abb589cb6bvn /* platformm specific */
29493bd8e037cbaea9095b34172305abb589cb6bvn hbnode[nhbnode] = platform_pciexhostbridge_declare(mod,
29493bd8e037cbaea9095b34172305abb589cb6bvn parent, hbp->id);
29493bd8e037cbaea9095b34172305abb589cb6bvn }
29493bd8e037cbaea9095b34172305abb589cb6bvn if (hbnode[nhbnode] == NULL) {
29493bd8e037cbaea9095b34172305abb589cb6bvn err = -1;
29493bd8e037cbaea9095b34172305abb589cb6bvn break;
29493bd8e037cbaea9095b34172305abb589cb6bvn }
29493bd8e037cbaea9095b34172305abb589cb6bvn
29493bd8e037cbaea9095b34172305abb589cb6bvn /*
29493bd8e037cbaea9095b34172305abb589cb6bvn * Create the pciexrc nodes under the hostbridge node
29493bd8e037cbaea9095b34172305abb589cb6bvn * If a rc exists in the dev tree, use the common code to
29493bd8e037cbaea9095b34172305abb589cb6bvn * create a pciexrc node and enumerate the fabric.
29493bd8e037cbaea9095b34172305abb589cb6bvn * Otherwise, only create the pciexrc node.
29493bd8e037cbaea9095b34172305abb589cb6bvn */
29493bd8e037cbaea9095b34172305abb589cb6bvn for (j = 0, rcp = hbp->rcs; j < hbp->nrcs; j++, rcp++) {
29493bd8e037cbaea9095b34172305abb589cb6bvn if (rcp->id < 0) {
29493bd8e037cbaea9095b34172305abb589cb6bvn topo_mod_dprintf(mod, "skip invalid rc[%d]\n",
29493bd8e037cbaea9095b34172305abb589cb6bvn j);
29493bd8e037cbaea9095b34172305abb589cb6bvn continue;
29493bd8e037cbaea9095b34172305abb589cb6bvn }
29493bd8e037cbaea9095b34172305abb589cb6bvn dnode1 = find_dnode(rcs, rcp->cfg_handle);
29493bd8e037cbaea9095b34172305abb589cb6bvn if (dnode1 != NULL) {
29493bd8e037cbaea9095b34172305abb589cb6bvn /* declare a pciexrc and enumerate its pcibus */
29493bd8e037cbaea9095b34172305abb589cb6bvn rcnode[nrcnode] = rc_process(mod,
29493bd8e037cbaea9095b34172305abb589cb6bvn hbnode[nhbnode], rcp->id, dnode1);
29493bd8e037cbaea9095b34172305abb589cb6bvn } else {
29493bd8e037cbaea9095b34172305abb589cb6bvn /* only declare the pciexrc */
29493bd8e037cbaea9095b34172305abb589cb6bvn rcnode[nrcnode] = platform_pciexrc_declare(mod,
29493bd8e037cbaea9095b34172305abb589cb6bvn hbnode[nhbnode], rcp->id, rcp->cfg_handle);
29493bd8e037cbaea9095b34172305abb589cb6bvn }
29493bd8e037cbaea9095b34172305abb589cb6bvn if (rcnode[nrcnode] == NULL) {
29493bd8e037cbaea9095b34172305abb589cb6bvn err = -1;
29493bd8e037cbaea9095b34172305abb589cb6bvn break;
29493bd8e037cbaea9095b34172305abb589cb6bvn }
29493bd8e037cbaea9095b34172305abb589cb6bvn nrcnode++;
29493bd8e037cbaea9095b34172305abb589cb6bvn }
29493bd8e037cbaea9095b34172305abb589cb6bvn
29493bd8e037cbaea9095b34172305abb589cb6bvn nhbnode++;
29493bd8e037cbaea9095b34172305abb589cb6bvn }
29493bd8e037cbaea9095b34172305abb589cb6bvn
29493bd8e037cbaea9095b34172305abb589cb6bvn /* failure: unbind all hb and rc tnodes */
29493bd8e037cbaea9095b34172305abb589cb6bvn if (err != 0) {
29493bd8e037cbaea9095b34172305abb589cb6bvn for (i = 0; i < nhbnode; i++)
29493bd8e037cbaea9095b34172305abb589cb6bvn topo_node_unbind(hbnode[i]);
29493bd8e037cbaea9095b34172305abb589cb6bvn for (i = 0; i < nrcnode; i++)
29493bd8e037cbaea9095b34172305abb589cb6bvn topo_node_unbind(rcnode[i]);
29493bd8e037cbaea9095b34172305abb589cb6bvn }
29493bd8e037cbaea9095b34172305abb589cb6bvn
29493bd8e037cbaea9095b34172305abb589cb6bvn topo_mod_free(mod, hbnode, hbmd.shbs * sizeof (tnode_t *));
29493bd8e037cbaea9095b34172305abb589cb6bvn topo_mod_free(mod, rcnode, nrcs * sizeof (tnode_t *));
29493bd8e037cbaea9095b34172305abb589cb6bvn hb_mdesc_fini(mod, &hbmd);
29493bd8e037cbaea9095b34172305abb589cb6bvn busorrc_free(mod, rcs);
29493bd8e037cbaea9095b34172305abb589cb6bvn
29493bd8e037cbaea9095b34172305abb589cb6bvn return (err);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*ARGSUSED*/
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindiint
0eb822a1c0c2bea495647510b75f77f0e57633ebcindiplatform_hb_label(topo_mod_t *mod, tnode_t *node, nvlist_t *in, nvlist_t **out)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
724365f7556fc4201fdb11766ebc6bd918523130sethg return (labelmethod_inherit(mod, node, in, out));
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}