Print this page
OS-1996 mpt_sas: allow physical topology enumeration in libtopo
Reviewed by: Keith Wesolowski <keith.wesolowski@joyent.com>
@@ -19,10 +19,13 @@
* CDDL HEADER END
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
*/
+/*
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ */
#include <strings.h>
#include <devid.h>
#include <pthread.h>
#include <inttypes.h>
@@ -31,27 +34,53 @@
#include <fm/topo_mod.h>
#include <fm/topo_list.h>
#include <fm/libdiskstatus.h>
#include <sys/fm/protocol.h>
#include "disk.h"
+#include "disk_drivers.h"
static int disk_enum(topo_mod_t *, tnode_t *, const char *,
topo_instance_t, topo_instance_t, void *, void *);
static const topo_modops_t disk_ops =
{ disk_enum, NULL };
static const topo_modinfo_t disk_info =
{DISK, FM_FMRI_SCHEME_HC, DISK_VERSION, &disk_ops};
+static int
+disk_declare_driver(topo_mod_t *mod, tnode_t *baynode, topo_list_t *dlistp,
+ char *driver)
+{
+ int err;
+
+ if (strcmp("mpt_sas", driver) == 0) {
+ char *sas_address = NULL;
+ tnode_t *child = NULL;
+
+ if ((err = disk_mptsas_find_disk(mod, baynode,
+ &sas_address)) != 0)
+ return (err);
+
+ err = disk_declare_addr(mod, baynode, dlistp,
+ sas_address, &child);
+ topo_mod_strfree(mod, sas_address);
+
+ return (err);
+ }
+
+ topo_mod_dprintf(mod, "unknown disk driver '%s'\n", driver);
+ return (-1);
+}
+
/*ARGSUSED*/
static int
disk_enum(topo_mod_t *mod, tnode_t *baynode,
const char *name, topo_instance_t min, topo_instance_t max,
void *arg, void *notused)
{
- char *device;
+ char *device, *driver;
int err;
nvlist_t *fmri;
topo_list_t *dlistp = topo_mod_getspecific(mod);
if (strcmp(name, DISK) != 0) {
@@ -73,10 +102,26 @@
return (-1);
}
nvlist_free(fmri);
/*
+ * For internal storage, first check to see if we need to
+ * request more detail from an HBA driver.
+ */
+ if (topo_prop_get_string(baynode, TOPO_PGROUP_BINDING,
+ TOPO_BINDING_DRIVER, &driver, &err) == 0) {
+ err = disk_declare_driver(mod, baynode, dlistp, driver);
+
+ topo_mod_strfree(mod, driver);
+ return (err);
+ } else if (err != ETOPO_PROP_NOENT) {
+ topo_mod_dprintf(mod, "disk_enum: "
+ "binding error %s\n", topo_strerror(err));
+ return (-1);
+ }
+
+ /*
* For internal storage, get the path to the occupant from the
* binding group of the bay node
*/
if (topo_prop_get_string(baynode, TOPO_PGROUP_BINDING,
TOPO_BINDING_OCCUPANT, &device, &err) != 0) {