Print this page
Reduce lint
OS-3878 The pseudo nexus should be FMA capable
OS-3881 pseudonex_detach does not properly check the detach command
Reviewed by: Joshua M. Clulow <josh@sysmgr.org>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
        
@@ -81,17 +81,21 @@
 static int pseudonex_attach(dev_info_t *, ddi_attach_cmd_t);
 static int pseudonex_detach(dev_info_t *, ddi_detach_cmd_t);
 static int pseudonex_open(dev_t *, int, int, cred_t *);
 static int pseudonex_close(dev_t, int, int, cred_t *);
 static int pseudonex_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
+static int pseudonex_fm_init(dev_info_t *, dev_info_t *, int,
+    ddi_iblock_cookie_t *);
 static int pseudonex_ctl(dev_info_t *, dev_info_t *, ddi_ctl_enum_t, void *,
     void *);
 
 static void *pseudonex_state;
 
 typedef struct pseudonex_state {
         dev_info_t *pnx_devi;
+        int pnx_fmcap;
+        ddi_iblock_cookie_t pnx_fm_ibc;
 } pseudonex_state_t;
 
 static struct bus_ops pseudonex_bus_ops = {
         BUSO_REV,
         nullbusmap,             /* bus_map */
@@ -114,11 +118,11 @@
         0,                      /* bus_remove_eventcall */
         0,                      /* bus_post_event */
         NULL,                   /* bus_intr_ctl */
         NULL,                   /* bus_config */
         NULL,                   /* bus_unconfig */
-        NULL,                   /* bus_fm_init */
+        pseudonex_fm_init,      /* bus_fm_init */
         NULL,                   /* bus_fm_fini */
         NULL,                   /* bus_fm_access_enter */
         NULL,                   /* bus_fm_access_exit */
         NULL,                   /* bus_power */
         pseudonex_intr_op       /* bus_intr_op */
@@ -226,10 +230,13 @@
         if (ddi_soft_state_zalloc(pseudonex_state, instance) != DDI_SUCCESS)
                 return (DDI_FAILURE);
         pnx_state = ddi_get_soft_state(pseudonex_state, instance);
         pnx_state->pnx_devi = devi;
 
+        pnx_state->pnx_fmcap = DDI_FM_EREPORT_CAPABLE;
+        ddi_fm_init(devi, &pnx_state->pnx_fmcap, &pnx_state->pnx_fm_ibc);
+
         if (ddi_create_minor_node(devi, "devctl", S_IFCHR, instance,
             DDI_NT_NEXUS, 0) != DDI_SUCCESS) {
                 ddi_remove_minor_node(devi, NULL);
                 ddi_soft_state_free(pseudonex_state, instance);
                 return (DDI_FAILURE);
@@ -245,10 +252,14 @@
         int instance = ddi_get_instance(devi);
 
         if (cmd == DDI_SUSPEND)
                 return (DDI_SUCCESS);
 
+        if (cmd != DDI_DETACH)
+                return (DDI_FAILURE);
+
+        ddi_fm_fini(devi);
         ddi_remove_minor_node(devi, NULL);
         ddi_soft_state_free(pseudonex_state, instance);
         return (DDI_SUCCESS);
 }
 
@@ -372,10 +383,24 @@
         }
         UNLOCK_DEV_OPS(dmp);
         return (-1);
 }
 
+/* ARGSUSED */
+static int
+pseudonex_fm_init(dev_info_t *dip, dev_info_t *tdip, int cap,
+    ddi_iblock_cookie_t *ibc)
+{
+        pseudonex_state_t *pnx_state;
+
+        pnx_state = ddi_get_soft_state(pseudonex_state, ddi_get_instance(dip));
+        ASSERT(pnx_state != NULL);
+        ASSERT(ibc != NULL);
+        *ibc = pnx_state->pnx_fm_ibc;
+        return (pnx_state->pnx_fmcap & cap);
+}
+
 static int
 pseudonex_ctl(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t ctlop,
     void *arg, void *result)
 {
         switch (ctlop) {