Print this page
4233 mptsas topo change buffer overflow

@@ -19,10 +19,11 @@
  * CDDL HEADER END
  */
 
 /*
  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
  */
 /*
  * This file contains SM-HBA support for MPT SAS driver
  */
 

@@ -57,10 +58,15 @@
 /*
  * SM - HBA statics
  */
 extern char *mptsas_driver_rev;
 
+static void mptsas_smhba_create_phy_props(nvlist_t **, smhba_info_t *, uint8_t,
+    uint16_t *);
+static void mptsas_smhba_update_phy_props(mptsas_t *, dev_info_t *, nvlist_t **,
+    uint8_t);
+
 static void
 mptsas_smhba_add_hba_prop(mptsas_t *mpt, data_type_t dt,
     char *prop_name, void *prop_val);
 
 void

@@ -114,83 +120,52 @@
                     mpt->m_phy_info[i].smhba_info.negotiated_link_rate,
                     mpt->m_phy_info[i].smhba_info.path);
         }
 }
 
-void
-mptsas_smhba_set_phy_props(mptsas_t *mpt, char *iport, dev_info_t *dip,
-    uint8_t phy_nums, uint16_t *attached_devhdl)
+static void
+mptsas_smhba_create_phy_props(nvlist_t **phy_props, smhba_info_t *pSmhba,
+    uint8_t phy_id, uint16_t *attached_devhdl)
 {
-        int             i;
-        int             j = 0;
+        (void) nvlist_alloc(phy_props, NV_UNIQUE_NAME, KM_SLEEP);
+        (void) nvlist_add_uint8(*phy_props, SAS_PHY_ID, phy_id);
+        (void) nvlist_add_uint8(*phy_props, "phyState",
+            (pSmhba->negotiated_link_rate & 0x0f));
+        (void) nvlist_add_int8(*phy_props, SAS_NEG_LINK_RATE,
+            (pSmhba->negotiated_link_rate & 0x0f));
+        (void) nvlist_add_int8(*phy_props, SAS_PROG_MIN_LINK_RATE,
+            (pSmhba->programmed_link_rate & 0x0f));
+        (void) nvlist_add_int8(*phy_props, SAS_HW_MIN_LINK_RATE,
+            (pSmhba->hw_link_rate & 0x0f));
+        (void) nvlist_add_int8(*phy_props, SAS_PROG_MAX_LINK_RATE,
+            ((pSmhba->programmed_link_rate & 0xf0) >> 4));
+        (void) nvlist_add_int8(*phy_props, SAS_HW_MAX_LINK_RATE,
+            ((pSmhba->hw_link_rate & 0xf0) >> 4));
+
+        if (pSmhba->attached_devhdl && (attached_devhdl != NULL))
+                *attached_devhdl = pSmhba->attached_devhdl;
+}
+
+static void
+mptsas_smhba_update_phy_props(mptsas_t *mpt, dev_info_t *dip,
+    nvlist_t **phy_props, uint8_t phy_nums)
+{
         int             rval;
         size_t          packed_size;
         char            *packed_data = NULL;
-        char            phymask[MPTSAS_MAX_PHYS];
-        nvlist_t        **phy_props;
         nvlist_t        *nvl;
-        smhba_info_t    *pSmhba = NULL;
 
-        if (phy_nums == 0) {
+        if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP) != 0) {
+                mptsas_log(mpt, CE_WARN, "%s: nvlist_alloc() failed", __func__);
                 return;
         }
-        if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
-                mptsas_log(mpt, CE_WARN, "%s: nvlist_alloc() failed", __func__);
-        }
 
-        phy_props = kmem_zalloc(sizeof (nvlist_t *) * phy_nums,
-            KM_SLEEP);
-
-        for (i = 0; i < mpt->m_num_phys; i++) {
-
-                bzero(phymask, sizeof (phymask));
-                (void) sprintf(phymask, "%x", mpt->m_phy_info[i].phy_mask);
-                if (strcmp(phymask, iport) == 0) {
-                        pSmhba = &mpt->m_phy_info[i].smhba_info;
-                        (void) nvlist_alloc(&phy_props[j], NV_UNIQUE_NAME, 0);
-                        (void) nvlist_add_uint8(phy_props[j], SAS_PHY_ID, i);
-                        (void) nvlist_add_uint8(phy_props[j],
-                            "phyState",
-                            (pSmhba->negotiated_link_rate
-                            & 0x0f));
-                        (void) nvlist_add_int8(phy_props[j],
-                            SAS_NEG_LINK_RATE,
-                            (pSmhba->negotiated_link_rate
-                            & 0x0f));
-                        (void) nvlist_add_int8(phy_props[j],
-                            SAS_PROG_MIN_LINK_RATE,
-                            (pSmhba->programmed_link_rate
-                            & 0x0f));
-                        (void) nvlist_add_int8(phy_props[j],
-                            SAS_HW_MIN_LINK_RATE,
-                            (pSmhba->hw_link_rate
-                            & 0x0f));
-                        (void) nvlist_add_int8(phy_props[j],
-                            SAS_PROG_MAX_LINK_RATE,
-                            ((pSmhba->programmed_link_rate
-                            & 0xf0) >> 4));
-                        (void) nvlist_add_int8(phy_props[j],
-                            SAS_HW_MAX_LINK_RATE,
-                            ((pSmhba->hw_link_rate
-                            & 0xf0) >> 4));
-
-                        j++;
-
-                        if (pSmhba->attached_devhdl &&
-                            (attached_devhdl != NULL)) {
-                                *attached_devhdl =
-                                    pSmhba->attached_devhdl;
-                        }
-                }
-        }
-
         rval = nvlist_add_nvlist_array(nvl, SAS_PHY_INFO_NVL, phy_props,
             phy_nums);
         if (rval) {
                 mptsas_log(mpt, CE_WARN,
-                    " nv list array add failed, return value %d.",
-                    rval);
+                    " nv list array add failed, return value %d.", rval);
                 goto exit;
         }
         (void) nvlist_size(nvl, &packed_size, NV_ENCODE_NATIVE);
         packed_data = kmem_zalloc(packed_size, KM_SLEEP);
         (void) nvlist_pack(nvl, &packed_data, &packed_size,

@@ -198,21 +173,58 @@
 
         (void) ddi_prop_update_byte_array(DDI_DEV_T_NONE, dip,
             SAS_PHY_INFO, (uchar_t *)packed_data, packed_size);
 
 exit:
-        for (i = 0; i < phy_nums && phy_props[i] != NULL; i++) {
-                nvlist_free(phy_props[i]);
-        }
         nvlist_free(nvl);
-        kmem_free(phy_props, sizeof (nvlist_t *) * phy_nums);
 
         if (packed_data != NULL) {
                 kmem_free(packed_data, packed_size);
         }
 }
 
+void
+mptsas_smhba_set_one_phy_props(mptsas_t *mpt, dev_info_t *dip, uint8_t phy_id,
+    uint16_t *attached_devhdl)
+{
+        nvlist_t        *phy_props;
+
+        ASSERT(phy_id < mpt->m_num_phys);
+
+        mptsas_smhba_create_phy_props(&phy_props,
+            &mpt->m_phy_info[phy_id].smhba_info, phy_id, attached_devhdl);
+
+        mptsas_smhba_update_phy_props(mpt, dip, &phy_props, 1);
+
+        nvlist_free(phy_props);
+}
+
+void
+mptsas_smhba_set_all_phy_props(mptsas_t *mpt, dev_info_t *dip, uint8_t phy_nums,
+    mptsas_phymask_t phy_mask, uint16_t *attached_devhdl)
+{
+        int             i, j;
+        nvlist_t        **phy_props;
+
+        if (phy_nums == 0)
+                return;
+
+        phy_props = kmem_zalloc(sizeof (nvlist_t *) * phy_nums, KM_SLEEP);
+
+        for (i = 0, j = 0; i < mpt->m_num_phys && j < phy_nums; i++)
+                if (phy_mask == mpt->m_phy_info[i].phy_mask)
+                        mptsas_smhba_create_phy_props(&phy_props[j++],
+                            &mpt->m_phy_info[i].smhba_info, i, attached_devhdl);
+
+        mptsas_smhba_update_phy_props(mpt, dip, phy_props, j);
+
+        for (i = 0; i < j && phy_props[i] != NULL; i++)
+                nvlist_free(phy_props[i]);
+
+        kmem_free(phy_props, sizeof (nvlist_t *) * phy_nums);
+}
+
 /*
  * Called with PHY lock held on phyp
  */
 void
 mptsas_smhba_log_sysevent(mptsas_t *mpt, char *subclass, char *etype,