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) {