summaryrefslogtreecommitdiff
path: root/usr/src/lib/libcfgadm/common/config_admin.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libcfgadm/common/config_admin.c')
-rw-r--r--usr/src/lib/libcfgadm/common/config_admin.c698
1 files changed, 553 insertions, 145 deletions
diff --git a/usr/src/lib/libcfgadm/common/config_admin.c b/usr/src/lib/libcfgadm/common/config_admin.c
index dc4632e202..d642fa820b 100644
--- a/usr/src/lib/libcfgadm/common/config_admin.c
+++ b/usr/src/lib/libcfgadm/common/config_admin.c
@@ -22,12 +22,10 @@
/* Portions Copyright 2005 Cyril Plisko */
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
@@ -177,6 +175,7 @@ typedef struct list_stat {
stat_data_list_t *sdl; /* Linked list of stat structures */
array_list_t *al; /* Linked list of arrays of list structures */
vers_req_t use_vers; /* plugin versions to be stat'ed */
+ char *shp_errstr; /* only for shp plugin */
} list_stat_t;
/*
@@ -205,13 +204,24 @@ static void *config_calloc_check(size_t, size_t, char **);
static cfga_err_t resolve_lib_ref(plugin_lib_t *, lib_loc_t *);
static cfga_err_t config_get_lib(const char *, lib_loc_t *, char **);
static int check_ap(di_node_t, di_minor_t, void *);
+static int check_ap_hp(di_node_t, di_hp_t, void *);
+static int check_ap_impl(di_node_t, di_minor_t, di_hp_t, void *);
static int check_ap_phys(di_node_t, di_minor_t, void *);
+static int check_ap_phys_hp(di_node_t, di_hp_t, void *);
+static int check_ap_phys_impl(di_node_t, di_minor_t, di_hp_t, void *);
static cfga_err_t find_ap_common(lib_loc_t *libloc_p, const char *rootpath,
- int (*fcn)(di_node_t node, di_minor_t minor, void *arg), char **errstring);
+ int (*fcn)(di_node_t node, di_minor_t minor, void *arg),
+ int (*fcn_hp)(di_node_t node, di_hp_t hp, void *arg),
+ char **errstring);
static plugin_lib_t *lib_in_list(char *);
+static cfga_err_t find_lib(di_node_t, di_minor_t, lib_loc_t *);
+static cfga_err_t find_lib_hp(di_node_t, di_hp_t, lib_loc_t *);
+static cfga_err_t find_lib_impl(char *, lib_loc_t *);
static cfga_err_t load_lib(di_node_t, di_minor_t, lib_loc_t *);
+static cfga_err_t load_lib_hp(di_node_t, di_hp_t, lib_loc_t *);
+static cfga_err_t load_lib_impl(di_node_t, di_minor_t, di_hp_t, lib_loc_t *);
extern void bcopy(const void *, void *, size_t);
static void config_err(int, int, char **);
static void hold_lib(plugin_lib_t *);
@@ -222,6 +232,9 @@ static cfga_err_t parse_listopt(char *listopts, char **classpp,
static cfga_err_t list_common(list_stat_t *lstatp, const char *class);
static int do_list_common(di_node_t node, di_minor_t minor, void *arg);
+static int do_list_common_hp(di_node_t node, di_hp_t hp, void *arg);
+static int do_list_common_impl(di_node_t node, di_minor_t minor,
+ di_hp_t hp, void *arg);
static cfga_err_t stat_common(int num_ap_ids, char *const *ap_ids,
const char *class, list_stat_t *lstatp);
@@ -575,6 +588,7 @@ config_stat(
lstat.countp = &nstat;
lstat.opts = options;
lstat.errstr = errstring;
+ lstat.shp_errstr = NULL;
/*
* This is a V1 interface which can use only V1 plugins
*/
@@ -611,6 +625,7 @@ config_list(
lstat.countp = &nstat;
lstat.opts = options;
lstat.errstr = errstring;
+ lstat.shp_errstr = NULL;
/*
* This is a V1 interface which can use only V1 plugins
*/
@@ -683,6 +698,7 @@ config_list_ext(
lstat.countp = &nstat;
lstat.opts = options;
lstat.errstr = errstring;
+ lstat.shp_errstr = NULL;
lstat.flags = flags;
/*
* We support both V1 and V2 plugins through this entry
@@ -1127,6 +1143,35 @@ mklog_common(
}
/*
+ * mklog_common - make a logical name from the driver and instance
+ */
+/*ARGSUSED*/
+static cfga_err_t
+mklog_hp(
+ di_node_t node,
+ di_hp_t hp,
+ plugin_lib_t *libp,
+ lib_loc_t *liblocp)
+{
+ const size_t len = CFGA_LOG_EXT_LEN;
+ int inst;
+ char *drv, *hp_name;
+
+ drv = di_driver_name(node);
+ inst = di_instance(node);
+ hp_name = di_hp_name(hp);
+
+ errno = 0;
+ if (drv != NULL && inst != -1 && hp_name != NULL &&
+ snprintf(liblocp->ap_logical, len, "%s%d:%s", drv, inst,
+ hp_name) < len) { /* snprintf returns strlen */
+ return (CFGA_OK);
+ }
+
+ return (CFGA_LIB_ERROR);
+}
+
+/*
* resolve_lib_ref - relocate to use plugin lib
*/
static cfga_err_t
@@ -1352,6 +1397,9 @@ config_get_lib(
/*
* find and load the library
* The base component of the ap_id is used to locate the plug-in
+ *
+ * NOTE that PCIE/PCISHPC connectors also have minor nodes &
+ * dev links created for now.
*/
if ((type = find_arg_type(lib_loc_p->ap_base)) == PHYSICAL_AP) {
/*
@@ -1360,14 +1408,15 @@ config_get_lib(
* ap_id.
*/
ret = find_ap_common(lib_loc_p, lib_loc_p->ap_base,
- check_ap_phys, errstring);
+ check_ap_phys, check_ap_phys_hp, errstring);
} else if ((type == LOGICAL_DRV_AP) ||
(type == AP_TYPE && dyncomp == NULL)) {
/*
* logical ap_id or ap_type: Use "/" as root for tree walk
* Note: an aptype cannot have a dynamic component
*/
- ret = find_ap_common(lib_loc_p, "/", check_ap, errstring);
+ ret = find_ap_common(lib_loc_p, "/", check_ap,
+ check_ap_hp, errstring);
} else {
ret = CFGA_APID_NOEXIST;
}
@@ -1418,20 +1467,49 @@ out:
return (ret);
}
+/* load_lib - load library for non-SHP attachment point node */
+static cfga_err_t
+load_lib(
+ di_node_t node,
+ di_minor_t minor,
+ lib_loc_t *libloc_p)
+{
+ return (load_lib_impl(node, minor, NULL, libloc_p));
+}
+
+/* load_lib_hp - load library for SHP attachment point node */
+static cfga_err_t
+load_lib_hp(
+ di_node_t node,
+ di_hp_t hp,
+ lib_loc_t *libloc_p)
+{
+ return (load_lib_impl(node, NULL, hp, libloc_p));
+}
/*
- * load_lib - Given a library pathname, create a entry for it
- * in the library list, if one does not already exist, and read
+ * load_lib_impl - Given a library pathname, create a entry for it
+ * in the library list, * if one does not already exist, and read
* lock it to keep it there.
*/
static cfga_err_t
-load_lib(
+load_lib_impl(
di_node_t node,
di_minor_t minor,
+ di_hp_t hp,
lib_loc_t *libloc_p)
{
plugin_lib_t *libp, *list_libp;
char *devfs_path;
+ char *name;
+
+ if (minor != DI_MINOR_NIL && hp != DI_HP_NIL)
+ return (CFGA_LIB_ERROR);
+
+ if (minor != DI_MINOR_NIL)
+ name = di_minor_name(minor);
+ else
+ name = di_hp_name(hp);
/*
* lock the library list
@@ -1448,15 +1526,22 @@ load_lib(
/* fill in logical and physical name in libloc_p */
libloc_p->libp = libp = list_libp;
- if (libp->vers_ops->mklog(node, minor, libp, libloc_p)
- != CFGA_OK) {
- rele_lib(list_libp);
- return (CFGA_LIB_ERROR);
+ if (minor != DI_MINOR_NIL) {
+ if (libp->vers_ops->mklog(node, minor, libp, libloc_p)
+ != CFGA_OK) {
+ rele_lib(list_libp);
+ return (CFGA_LIB_ERROR);
+ }
+ } else {
+ if (mklog_hp(node, hp, libp, libloc_p) != CFGA_OK) {
+ rele_lib(list_libp);
+ return (CFGA_LIB_ERROR);
+ }
}
devfs_path = di_devfs_path(node);
(void) snprintf(libloc_p->ap_physical, MAXPATHLEN, "%s%s:%s",
- DEVICES_DIR, devfs_path, di_minor_name(minor));
+ DEVICES_DIR, devfs_path, name);
di_devfs_path_free(devfs_path);
return (CFGA_OK);
@@ -1482,12 +1567,23 @@ load_lib(
return (CFGA_NO_LIB);
}
- if (resolve_lib_ref(libp, libloc_p) != CFGA_OK ||
- libp->vers_ops->mklog(node, minor, libp, libloc_p) != CFGA_OK) {
- (void) mutex_unlock(&plugin_list_lock);
- (void) dlclose(libp->handle);
- free(libp);
- return (CFGA_NO_LIB);
+ if (minor != DI_MINOR_NIL) {
+ if (resolve_lib_ref(libp, libloc_p) != CFGA_OK ||
+ libp->vers_ops->mklog(node, minor, libp, libloc_p)
+ != CFGA_OK) {
+ (void) mutex_unlock(&plugin_list_lock);
+ (void) dlclose(libp->handle);
+ free(libp);
+ return (CFGA_NO_LIB);
+ }
+ } else {
+ if (resolve_lib_ref(libp, libloc_p) != CFGA_OK ||
+ mklog_hp(node, hp, libp, libloc_p) != CFGA_OK) {
+ (void) mutex_unlock(&plugin_list_lock);
+ (void) dlclose(libp->handle);
+ free(libp);
+ return (CFGA_NO_LIB);
+ }
}
/*
@@ -1511,7 +1607,7 @@ load_lib(
libloc_p->libp = libp;
devfs_path = di_devfs_path(node);
(void) snprintf(libloc_p->ap_physical, MAXPATHLEN, "%s%s:%s",
- DEVICES_DIR, devfs_path, di_minor_name(minor));
+ DEVICES_DIR, devfs_path, name);
di_devfs_path_free(devfs_path);
return (CFGA_OK);
@@ -1521,8 +1617,7 @@ load_lib(
#define NUM_LIB_NAMES 2
/*
- * find_lib - Given an attachment point node find it's library
- *
+ * find_lib - find library for non-SHP attachment point node
*/
static cfga_err_t
find_lib(
@@ -1530,34 +1625,13 @@ find_lib(
di_minor_t minor,
lib_loc_t *libloc_p)
{
- char lib[MAXPATHLEN];
char name[NUM_LIB_NAMES][MAXPATHLEN];
- struct stat lib_stat;
- void *dlhandle = NULL;
- static char plat_name[SYSINFO_LENGTH];
- static char machine_name[SYSINFO_LENGTH];
- static char arch_name[SYSINFO_LENGTH];
- int i = 0;
char *class = NULL, *drv = NULL;
+ int i;
/* Make sure pathname and class is null if we fail */
- *libloc_p->ap_class = *libloc_p->pathname = *lib = '\0';
-
- /*
- * Initialize machine name and arch name
- */
- if (strncmp("", machine_name, MAXPATHLEN) == 0) {
- if (sysinfo(SI_PLATFORM, plat_name, SYSINFO_LENGTH) == -1) {
- return (CFGA_ERROR);
- }
- if (sysinfo(SI_ARCHITECTURE, arch_name, SYSINFO_LENGTH) == -1) {
- return (CFGA_ERROR);
- }
- if (sysinfo(SI_MACHINE, machine_name, SYSINFO_LENGTH) == -1) {
- return (CFGA_ERROR);
- }
- }
+ *libloc_p->ap_class = *libloc_p->pathname = '\0';
/*
* Initialize possible library tags.
@@ -1584,72 +1658,174 @@ find_lib(
continue;
}
- /*
- * Try path based upon platform name
- */
- (void) snprintf(lib, sizeof (lib), "%s%s%s%s%s",
- LIB_PATH_BASE1, plat_name, LIB_PATH_MIDDLE,
- name[i], LIB_PATH_TAIL);
-
- if (stat(lib, &lib_stat) == 0) {
- /* file exists, is it a lib */
- dlhandle = dlopen(lib, RTLD_LAZY);
- if (dlhandle != NULL) {
- goto found;
- }
- }
+ if (find_lib_impl(name[i], libloc_p) == CFGA_OK)
+ goto found;
+ }
- /*
- * Try path based upon machine name
- */
- (void) snprintf(lib, sizeof (lib), "%s%s%s%s%s",
- LIB_PATH_BASE1, machine_name, LIB_PATH_MIDDLE,
- name[i], LIB_PATH_TAIL);
+ return (CFGA_NO_LIB);
+found:
- if (stat(lib, &lib_stat) == 0) {
- /* file exists, is it a lib */
- dlhandle = dlopen(lib, RTLD_LAZY);
- if (dlhandle != NULL) {
- goto found;
- }
- }
+ /* Record class name (if any) */
+ (void) snprintf(libloc_p->ap_class, sizeof (libloc_p->ap_class), "%s",
+ class);
+
+ return (CFGA_OK);
+}
+
+/*
+ * find_lib_hp - find library for SHP attachment point
+ */
+/*ARGSUSED*/
+static cfga_err_t
+find_lib_hp(
+ di_node_t node,
+ di_hp_t hp,
+ lib_loc_t *libloc_p)
+{
+ char name[MAXPATHLEN];
+ char *class = NULL;
- /*
- * Try path based upon arch name
- */
- (void) snprintf(lib, sizeof (lib), "%s%s%s%s%s",
- LIB_PATH_BASE1, arch_name, LIB_PATH_MIDDLE,
- name[i], LIB_PATH_TAIL);
-
- if (stat(lib, &lib_stat) == 0) {
- /* file exists, is it a lib */
- dlhandle = dlopen(lib, RTLD_LAZY);
- if (dlhandle != NULL) {
- goto found;
- }
+ /* Make sure pathname and class is null if we fail */
+ *libloc_p->ap_class = *libloc_p->pathname = '\0';
+
+ /*
+ * Initialize possible library tags.
+ *
+ * Only support PCI class for now, this will need to be
+ * changed as other plugins are migrated to SHP plugin.
+ */
+ class = "pci";
+#if 0
+ /*
+ * No type check for now as PCI is the only class SHP plugin
+ * supports. In the future we'll need to enable the type check
+ * and set class accordingly, when non PCI plugins are migrated
+ * to SHP. In that case we'll probably need to add an additional
+ * interface between libcfgadm and the plugins, and SHP plugin will
+ * implement this interface which will translate the bus specific
+ * strings to standard classes that libcfgadm can recognize, for
+ * all the buses it supports, e.g. for pci/pcie it will translate
+ * PCIE_NATIVE_HP_TYPE to string "pci". We'll also need to bump up
+ * SHP plugin version to 3 to use the new interface.
+ */
+ class = di_hp_type(hp);
+ if ((strcmp(class, PCIE_NATIVE_HP_TYPE) == 0) ||
+ (strcmp(class, PCIE_ACPI_HP_TYPE) == 0) ||
+ (strcmp(class, PCIE_PCI_HP_TYPE) == 0)) {
+ class = "pci";
+ } else {
+ goto fail;
+ }
+#endif
+ (void) snprintf(&name[0], sizeof (name), "%s", "shp");
+
+ if (find_lib_impl(name, libloc_p) == CFGA_OK)
+ goto found;
+fail:
+ return (CFGA_NO_LIB);
+
+found:
+
+ /* Record class name (if any) */
+ (void) snprintf(libloc_p->ap_class, sizeof (libloc_p->ap_class), "%s",
+ class);
+
+ return (CFGA_OK);
+}
+
+/*
+ * find_lib_impl - Given an attachment point node find it's library
+ */
+static cfga_err_t
+find_lib_impl(
+ char *name,
+ lib_loc_t *libloc_p)
+{
+ char lib[MAXPATHLEN];
+ struct stat lib_stat;
+ void *dlhandle = NULL;
+ static char plat_name[SYSINFO_LENGTH];
+ static char machine_name[SYSINFO_LENGTH];
+ static char arch_name[SYSINFO_LENGTH];
+
+ /*
+ * Initialize machine name and arch name
+ */
+ if (strncmp("", machine_name, MAXPATHLEN) == 0) {
+ if (sysinfo(SI_PLATFORM, plat_name, SYSINFO_LENGTH) == -1) {
+ return (CFGA_ERROR);
+ }
+ if (sysinfo(SI_ARCHITECTURE, arch_name, SYSINFO_LENGTH) == -1) {
+ return (CFGA_ERROR);
}
+ if (sysinfo(SI_MACHINE, machine_name, SYSINFO_LENGTH) == -1) {
+ return (CFGA_ERROR);
+ }
+ }
- /*
- * Try generic location
- */
- (void) snprintf(lib, sizeof (lib), "%s%s%s%s",
- LIB_PATH_BASE2, LIB_PATH_MIDDLE, name[i], LIB_PATH_TAIL);
+ /*
+ * Try path based upon platform name
+ */
+ (void) snprintf(lib, sizeof (lib), "%s%s%s%s%s",
+ LIB_PATH_BASE1, plat_name, LIB_PATH_MIDDLE,
+ name, LIB_PATH_TAIL);
+
+ if (stat(lib, &lib_stat) == 0) {
+ /* file exists, is it a lib */
+ dlhandle = dlopen(lib, RTLD_LAZY);
+ if (dlhandle != NULL) {
+ goto found;
+ }
+ }
+ /*
+ * Try path based upon machine name
+ */
+ (void) snprintf(lib, sizeof (lib), "%s%s%s%s%s",
+ LIB_PATH_BASE1, machine_name, LIB_PATH_MIDDLE,
+ name, LIB_PATH_TAIL);
- if (stat(lib, &lib_stat) == 0) {
- /* file exists, is it a lib */
- dlhandle = dlopen(lib, RTLD_LAZY);
- if (dlhandle != NULL) {
- goto found;
- }
+ if (stat(lib, &lib_stat) == 0) {
+ /* file exists, is it a lib */
+ dlhandle = dlopen(lib, RTLD_LAZY);
+ if (dlhandle != NULL) {
+ goto found;
+ }
+ }
+ /*
+ * Try path based upon arch name
+ */
+ (void) snprintf(lib, sizeof (lib), "%s%s%s%s%s",
+ LIB_PATH_BASE1, arch_name, LIB_PATH_MIDDLE,
+ name, LIB_PATH_TAIL);
+
+ if (stat(lib, &lib_stat) == 0) {
+ /* file exists, is it a lib */
+ dlhandle = dlopen(lib, RTLD_LAZY);
+ if (dlhandle != NULL) {
+ goto found;
}
+
}
+ /*
+ * Try generic location
+ */
+ (void) snprintf(lib, sizeof (lib), "%s%s%s%s",
+ LIB_PATH_BASE2, LIB_PATH_MIDDLE, name, LIB_PATH_TAIL);
+
+ if (stat(lib, &lib_stat) == 0) {
+ /* file exists, is it a lib */
+ dlhandle = dlopen(lib, RTLD_LAZY);
+ if (dlhandle != NULL) {
+ goto found;
+ }
+ }
return (CFGA_NO_LIB);
found:
@@ -1659,10 +1835,6 @@ found:
(void) dlclose(dlhandle);
- /* Record class name (if any) */
- (void) snprintf(libloc_p->ap_class, sizeof (libloc_p->ap_class), "%s",
- class);
-
return (CFGA_OK);
}
@@ -1746,6 +1918,7 @@ find_ap_common(
lib_loc_t *libloc_p,
const char *physpath,
int (*fcn)(di_node_t node, di_minor_t minor, void *arg),
+ int (*fcn_hp)(di_node_t node, di_hp_t hp, void *arg),
char **errstring)
{
di_node_t rnode, wnode;
@@ -1781,37 +1954,84 @@ find_ap_common(
/*
* begin walk of device tree
+ *
+ * Since we create minor nodes & dev links for both all PCI/PCIE
+ * connectors, but only create hp nodes for PCIE/PCISHPC connectors
+ * of the new framework, we should first match with hp nodes. If
+ * the ap_id refers to a PCIE/PCISHPC connector, we'll be able to
+ * find it here.
*/
- rnode = di_init("/", DINFOCACHE);
+ rnode = di_init("/", DINFOSUBTREE | DINFOHP);
if (rnode)
wnode = di_lookup_node(rnode, rpath);
else
wnode = DI_NODE_NIL;
- S_FREE(rpath);
if (wnode == DI_NODE_NIL) {
if (rnode == DI_NODE_NIL) {
+ S_FREE(rpath);
config_err(errno, DI_INIT_FAILED, errstring);
return (CFGA_LIB_ERROR);
} else {
/*
- * di_lookup_node() may fail because the ap_id
- * does not exist
+ * di_lookup_node() may fail, either because the
+ * ap_id does not exist, or because the ap_id refers
+ * to a legacy PCI slot, thus we'll not able to
+ * find node using DINFOHP, try to see if we can
+ * find one using DINFOCACHE.
*/
di_fini(rnode);
- return (CFGA_APID_NOEXIST);
+ goto find_minor;
}
}
libloc_p->libp = NULL;
libloc_p->status = CFGA_APID_NOEXIST;
- (void) di_walk_minor(wnode, "ddi_ctl:attachment_point",
- DI_CHECK_ALIAS|DI_CHECK_INTERNAL_PATH,
- libloc_p, fcn);
+ (void) di_walk_hp(wnode, NULL, DI_HP_CONNECTOR,
+ libloc_p, fcn_hp);
di_fini(rnode);
+ /*
+ * Failed to find a matching hp node, try minor node.
+ */
+ if (libloc_p->libp == NULL) {
+find_minor:
+ rnode = di_init("/", DINFOCACHE);
+ if (rnode)
+ wnode = di_lookup_node(rnode, rpath);
+ else
+ wnode = DI_NODE_NIL;
+
+ if (wnode == DI_NODE_NIL) {
+ if (rnode == DI_NODE_NIL) {
+ S_FREE(rpath);
+ config_err(errno, DI_INIT_FAILED, errstring);
+ return (CFGA_LIB_ERROR);
+ } else {
+ /*
+ * di_lookup_node() may fail, because the
+ * ap_id does not exist.
+ */
+ S_FREE(rpath);
+ di_fini(rnode);
+ return (CFGA_APID_NOEXIST);
+ }
+ }
+
+ libloc_p->libp = NULL;
+ libloc_p->status = CFGA_APID_NOEXIST;
+
+ (void) di_walk_minor(wnode, "ddi_ctl:attachment_point",
+ DI_CHECK_ALIAS|DI_CHECK_INTERNAL_PATH,
+ libloc_p, fcn);
+
+ di_fini(rnode);
+ }
+
+ S_FREE(rpath);
+
if (libloc_p->libp != NULL) {
update_cache(libloc_p);
return (CFGA_OK);
@@ -1821,18 +2041,42 @@ find_ap_common(
}
/*
- * check_ap - called for each attachment point found
+ * check_ap - called for each non-SHP attachment point found
+ */
+static int
+check_ap(
+ di_node_t node,
+ di_minor_t minor,
+ void *arg)
+{
+ return (check_ap_impl(node, minor, NULL, arg));
+}
+
+/*
+ * check_ap_hp - called for each SHP attachment point found
+ */
+static int
+check_ap_hp(
+ di_node_t node,
+ di_hp_t hp,
+ void *arg)
+{
+ return (check_ap_impl(node, NULL, hp, arg));
+}
+
+/*
+ * check_ap_impl - called for each attachment point found
*
* This is used in cases where a particular attachment point
* or type of attachment point is specified via a logical name or ap_type.
* Not used for physical names or in the list case with no
* ap's specified.
*/
-
static int
-check_ap(
+check_ap_impl(
di_node_t node,
di_minor_t minor,
+ di_hp_t hp,
void *arg)
{
char *cp = NULL;
@@ -1847,6 +2091,8 @@ check_ap(
int instance;
cfga_ap_types_t type;
+ if (minor != DI_MINOR_NIL && hp != DI_HP_NIL)
+ return (DI_WALK_CONTINUE);
libloc_p = (lib_loc_t *)arg;
@@ -1873,7 +2119,11 @@ check_ap(
return (DI_WALK_CONTINUE);
}
- node_minor = di_minor_name(minor);
+ if (minor != DI_MINOR_NIL)
+ node_minor = di_minor_name(minor);
+ else
+ node_minor = di_hp_name(hp);
+
drv_name = di_driver_name(node);
instance = di_instance(node);
@@ -1910,13 +2160,24 @@ check_ap(
/*
* save the correct type of error so user does not get confused
*/
- if (find_lib(node, minor, libloc_p) != CFGA_OK) {
- libloc_p->status = CFGA_NO_LIB;
- return (DI_WALK_CONTINUE);
- }
- if (load_lib(node, minor, libloc_p) != CFGA_OK) {
- libloc_p->status = CFGA_LIB_ERROR;
- return (DI_WALK_CONTINUE);
+ if (minor != DI_MINOR_NIL) {
+ if (find_lib(node, minor, libloc_p) != CFGA_OK) {
+ libloc_p->status = CFGA_NO_LIB;
+ return (DI_WALK_CONTINUE);
+ }
+ if (load_lib(node, minor, libloc_p) != CFGA_OK) {
+ libloc_p->status = CFGA_LIB_ERROR;
+ return (DI_WALK_CONTINUE);
+ }
+ } else {
+ if (find_lib_hp(node, hp, libloc_p) != CFGA_OK) {
+ libloc_p->status = CFGA_NO_LIB;
+ return (DI_WALK_CONTINUE);
+ }
+ if (load_lib_hp(node, hp, libloc_p) != CFGA_OK) {
+ libloc_p->status = CFGA_LIB_ERROR;
+ return (DI_WALK_CONTINUE);
+ }
}
libloc_p->status = CFGA_OK;
return (DI_WALK_TERMINATE);
@@ -1928,17 +2189,41 @@ check_ap(
/*
- * check_ap_phys - called for each attachment point found
+ * check_ap_phys - called for each non-SHP attachment point found
+ */
+static int
+check_ap_phys(
+ di_node_t node,
+ di_minor_t minor,
+ void *arg)
+{
+ return (check_ap_phys_impl(node, minor, DI_HP_NIL, arg));
+}
+
+/*
+ * check_ap_phys_hp - called for each SHP attachment point found
+ */
+static int
+check_ap_phys_hp(
+ di_node_t node,
+ di_hp_t hp,
+ void *arg)
+{
+ return (check_ap_phys_impl(node, DI_HP_NIL, hp, arg));
+}
+
+/*
+ * check_ap_phys_impl - called for each attachment point found
*
* This is used in cases where a particular attachment point
* is specified via a physical name. If the name matches then
* we try and find and load the library for it.
*/
-
static int
-check_ap_phys(
+check_ap_phys_impl(
di_node_t node,
di_minor_t minor,
+ di_hp_t hp,
void *arg)
{
lib_loc_t *libloc_p;
@@ -1946,9 +2231,15 @@ check_ap_phys(
char *devfs_path;
char *minor_name;
+ if (minor != DI_MINOR_NIL && hp != DI_HP_NIL)
+ return (DI_WALK_CONTINUE);
+
libloc_p = (lib_loc_t *)arg;
devfs_path = di_devfs_path(node);
- minor_name = di_minor_name(minor);
+ if (minor != DI_MINOR_NIL)
+ minor_name = di_minor_name(minor);
+ else
+ minor_name = di_hp_name(hp);
if (devfs_path == NULL || minor_name == NULL) {
libloc_p->status = CFGA_APID_NOEXIST;
@@ -1961,14 +2252,26 @@ check_ap_phys(
di_devfs_path_free(devfs_path);
if (strcmp(phys_name, libloc_p->ap_base) == 0) {
- if (find_lib(node, minor, libloc_p) != CFGA_OK) {
- libloc_p->status = CFGA_NO_LIB;
- return (DI_WALK_CONTINUE);
- }
- if (load_lib(node, minor, libloc_p) != CFGA_OK) {
- libloc_p->status = CFGA_LIB_ERROR;
- return (DI_WALK_CONTINUE);
+ if (minor != DI_MINOR_NIL) {
+ if (find_lib(node, minor, libloc_p) != CFGA_OK) {
+ libloc_p->status = CFGA_NO_LIB;
+ return (DI_WALK_CONTINUE);
+ }
+ if (load_lib(node, minor, libloc_p) != CFGA_OK) {
+ libloc_p->status = CFGA_LIB_ERROR;
+ return (DI_WALK_CONTINUE);
+ }
+ } else {
+ if (find_lib_hp(node, hp, libloc_p) != CFGA_OK) {
+ libloc_p->status = CFGA_NO_LIB;
+ return (DI_WALK_CONTINUE);
+ }
+ if (load_lib_hp(node, hp, libloc_p) != CFGA_OK) {
+ libloc_p->status = CFGA_LIB_ERROR;
+ return (DI_WALK_CONTINUE);
+ }
}
+
libloc_p->status = CFGA_OK;
return (DI_WALK_TERMINATE);
} else {
@@ -2167,15 +2470,6 @@ list_common(list_stat_t *lstatp, const char *class)
char nodetype[MAXPATHLEN];
const char *l_class, *l_sep;
-
- /*
- * begin walk of device tree
- */
- if ((rnode = di_init("/", DINFOCACHE)) == DI_NODE_NIL) {
- config_err(errno, DI_INIT_FAILED, lstatp->errstr);
- return (CFGA_LIB_ERROR);
- }
-
/*
* May walk a subset of all attachment points in the device tree if
* a class is specified
@@ -2190,10 +2484,38 @@ list_common(list_stat_t *lstatp, const char *class)
(void) snprintf(nodetype, sizeof (nodetype), "%s%s%s",
DDI_NT_ATTACHMENT_POINT, l_sep, l_class);
+ /*
+ * Walk all hp nodes
+ */
+ if ((rnode = di_init("/", DINFOSUBTREE | DINFOHP)) == DI_NODE_NIL) {
+ config_err(errno, DI_INIT_FAILED, lstatp->errstr);
+ return (CFGA_LIB_ERROR);
+ }
+ /* No need to filter on class for now */
+ (void) di_walk_hp(rnode, NULL, DI_HP_CONNECTOR,
+ lstatp, do_list_common_hp);
+
+ di_fini(rnode);
+
+ /*
+ * Walk all minor nodes
+ * but exclude PCIE/PCIESHPC connectors which have been walked above.
+ */
+ if ((rnode = di_init("/", DINFOCACHE)) == DI_NODE_NIL) {
+ config_err(errno, DI_INIT_FAILED, lstatp->errstr);
+ return (CFGA_LIB_ERROR);
+ }
(void) di_walk_minor(rnode, nodetype,
DI_CHECK_ALIAS|DI_CHECK_INTERNAL_PATH, lstatp, do_list_common);
+
di_fini(rnode);
+ if (lstatp->shp_errstr != NULL) {
+ *(lstatp->errstr) = strdup(lstatp->shp_errstr);
+ free(lstatp->shp_errstr);
+ lstatp->shp_errstr = NULL;
+ }
+
return (CFGA_OK);
}
@@ -2245,16 +2567,66 @@ config_err(int errnum, int err_type, char **errstring)
}
/*
- * do_list_common - Routine to list attachment point as part of
+ * do_list_common - list non-SHP attachment point
+ */
+static int
+do_list_common(
+ di_node_t node,
+ di_minor_t minor,
+ void *arg)
+{
+ di_node_t rnode;
+ di_hp_t hp;
+ char *minor_name;
+
+ minor_name = di_minor_name(minor);
+
+ /*
+ * since PCIE/PCIHSHPC connectors have both hp nodes and minor nodes
+ * created for now, we need to specifically exclude these connectors
+ * during walking minor nodes.
+ */
+ if ((rnode = di_init(di_devfs_path(node), DINFOSUBTREE | DINFOHP))
+ == DI_NODE_NIL) {
+ return (DI_WALK_CONTINUE);
+ }
+
+ for (hp = DI_HP_NIL; (hp = di_hp_next(rnode, hp)) != DI_HP_NIL; ) {
+ if (strcmp(di_hp_name(hp), minor_name) == 0) {
+ di_fini(rnode);
+ return (DI_WALK_CONTINUE);
+ }
+ }
+
+ di_fini(rnode);
+
+ return (do_list_common_impl(node, minor, NULL, arg));
+}
+
+/*
+ * do_list_common_hp - list SHP attachment point
+ */
+static int
+do_list_common_hp(
+ di_node_t node,
+ di_hp_t hp,
+ void *arg)
+{
+ return (do_list_common_impl(node, NULL, hp, arg));
+}
+
+/*
+ * do_list_common_impl - Routine to list attachment point as part of
* a config_list opertion. Used by both v1 and v2 interfaces.
* This is somewhat similar to config_get_lib() and its helper routines
* except that the ap_ids are always physical and don't have dynamic
* components.
*/
static int
-do_list_common(
+do_list_common_impl(
di_node_t node,
di_minor_t minor,
+ di_hp_t hp,
void *arg)
{
lib_loc_t lib_loc;
@@ -2262,6 +2634,8 @@ do_list_common(
list_stat_t *lstatp = NULL;
cfga_err_t ret = CFGA_ERROR;
+ if (minor != DI_MINOR_NIL && hp != DI_HP_NIL)
+ return (DI_WALK_CONTINUE);
lstatp = (list_stat_t *)arg;
@@ -2269,7 +2643,12 @@ do_list_common(
/*
* try and find a lib for this node
*/
- if (find_lib(node, minor, &lib_loc) != CFGA_OK) {
+ if (minor != DI_MINOR_NIL) {
+ ret = find_lib(node, minor, &lib_loc);
+ } else {
+ ret = find_lib_hp(node, hp, &lib_loc);
+ }
+ if (ret != CFGA_OK) {
return (DI_WALK_CONTINUE);
}
@@ -2280,7 +2659,11 @@ do_list_common(
lib_loc.vers_req.v_min = CFGA_HSL_V1;
lib_loc.vers_req.v_max = CFGA_HSL_VERS;
- ret = load_lib(node, minor, &lib_loc);
+ if (minor != DI_MINOR_NIL) {
+ ret = load_lib(node, minor, &lib_loc);
+ } else {
+ ret = load_lib_hp(node, hp, &lib_loc);
+ }
if (ret != CFGA_OK) {
return (DI_WALK_CONTINUE);
}
@@ -2294,7 +2677,32 @@ do_list_common(
* stop the walk if an error occurs in the plugin.
*/
if (compat_plugin(&lstatp->use_vers, libp->plugin_vers)) {
- (void) libp->vers_ops->stat_plugin(lstatp, &lib_loc, NULL);
+ if (minor != DI_MINOR_NIL) {
+ (void) libp->vers_ops->stat_plugin(lstatp,
+ &lib_loc, NULL);
+ } else {
+ /*
+ * If the underlying hotplug daemon is not enabled,
+ * the SHP attach points will not be shown, this
+ * could confuse the uesrs. We specifically pass the
+ * errstring to SHP plugin so that it can set the
+ * errstring accordingly in this case, giving users
+ * a hint.
+ */
+ ret = libp->vers_ops->stat_plugin(lstatp,
+ &lib_loc, lstatp->errstr);
+ if (ret == CFGA_NOTSUPP && *(lstatp->errstr) != NULL) {
+ if (lstatp->shp_errstr == NULL) {
+ lstatp->shp_errstr =
+ strdup(*(lstatp->errstr));
+ }
+ }
+
+ if (*(lstatp->errstr) != NULL) {
+ free(*(lstatp->errstr));
+ *(lstatp->errstr) = NULL;
+ }
+ }
}
rele_lib(libp);