4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25 /*
26 * This file contains SM-HBA support for MPT SAS driver
27 */
28
29 #if defined(lint) || defined(DEBUG)
30 #define MPTSAS_DEBUG
31 #endif
32
33 /*
34 * standard header files
35 */
36 #include <sys/note.h>
37 #include <sys/scsi/scsi.h>
38 #include <sys/pci.h>
39 #include <sys/scsi/generic/sas.h>
40 #include <sys/scsi/impl/scsi_sas.h>
41
42 #pragma pack(1)
43 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_type.h>
44 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2.h>
45 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_cnfg.h>
46 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_init.h>
47 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_ioc.h>
48 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_sas.h>
49 #pragma pack()
50
51 /*
52 * private header files.
53 */
54 #include <sys/scsi/adapters/mpt_sas/mptsas_var.h>
55 #include <sys/scsi/adapters/mpt_sas/mptsas_smhba.h>
56
57 /*
58 * SM - HBA statics
59 */
60 extern char *mptsas_driver_rev;
61
62 static void
63 mptsas_smhba_add_hba_prop(mptsas_t *mpt, data_type_t dt,
64 char *prop_name, void *prop_val);
65
66 void
67 mptsas_smhba_show_phy_info(mptsas_t *mpt);
68
69 static void
70 mptsas_smhba_add_hba_prop(mptsas_t *mpt, data_type_t dt,
71 char *prop_name, void *prop_val)
72 {
73 ASSERT(mpt != NULL);
74
75 switch (dt) {
76 case DATA_TYPE_INT32:
77 if (ddi_prop_update_int(DDI_DEV_T_NONE, mpt->m_dip,
78 prop_name, *(int *)prop_val)) {
79 mptsas_log(mpt, CE_WARN,
80 "%s: %s prop update failed", __func__, prop_name);
81 }
99 {
100 int i;
101
102 ASSERT(mpt != NULL);
103
104 for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
105 mptsas_log(mpt, CE_WARN,
106 "phy %d, Owner hdl:0x%x, attached hdl: 0x%x,"
107 "attached phy identifier %d,Program link rate 0x%x,"
108 "hw link rate 0x%x, negotiator link rate 0x%x, path %s",
109 i, mpt->m_phy_info[i].smhba_info.owner_devhdl,
110 mpt->m_phy_info[i].smhba_info.attached_devhdl,
111 mpt->m_phy_info[i].smhba_info.attached_phy_identify,
112 mpt->m_phy_info[i].smhba_info.programmed_link_rate,
113 mpt->m_phy_info[i].smhba_info.hw_link_rate,
114 mpt->m_phy_info[i].smhba_info.negotiated_link_rate,
115 mpt->m_phy_info[i].smhba_info.path);
116 }
117 }
118
119 void
120 mptsas_smhba_set_phy_props(mptsas_t *mpt, char *iport, dev_info_t *dip,
121 uint8_t phy_nums, uint16_t *attached_devhdl)
122 {
123 int i;
124 int j = 0;
125 int rval;
126 size_t packed_size;
127 char *packed_data = NULL;
128 char phymask[MPTSAS_MAX_PHYS];
129 nvlist_t **phy_props;
130 nvlist_t *nvl;
131 smhba_info_t *pSmhba = NULL;
132
133 if (phy_nums == 0) {
134 return;
135 }
136 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
137 mptsas_log(mpt, CE_WARN, "%s: nvlist_alloc() failed", __func__);
138 }
139
140 phy_props = kmem_zalloc(sizeof (nvlist_t *) * phy_nums,
141 KM_SLEEP);
142
143 for (i = 0; i < mpt->m_num_phys; i++) {
144
145 bzero(phymask, sizeof (phymask));
146 (void) sprintf(phymask, "%x", mpt->m_phy_info[i].phy_mask);
147 if (strcmp(phymask, iport) == 0) {
148 pSmhba = &mpt->m_phy_info[i].smhba_info;
149 (void) nvlist_alloc(&phy_props[j], NV_UNIQUE_NAME, 0);
150 (void) nvlist_add_uint8(phy_props[j], SAS_PHY_ID, i);
151 (void) nvlist_add_uint8(phy_props[j],
152 "phyState",
153 (pSmhba->negotiated_link_rate
154 & 0x0f));
155 (void) nvlist_add_int8(phy_props[j],
156 SAS_NEG_LINK_RATE,
157 (pSmhba->negotiated_link_rate
158 & 0x0f));
159 (void) nvlist_add_int8(phy_props[j],
160 SAS_PROG_MIN_LINK_RATE,
161 (pSmhba->programmed_link_rate
162 & 0x0f));
163 (void) nvlist_add_int8(phy_props[j],
164 SAS_HW_MIN_LINK_RATE,
165 (pSmhba->hw_link_rate
166 & 0x0f));
167 (void) nvlist_add_int8(phy_props[j],
168 SAS_PROG_MAX_LINK_RATE,
169 ((pSmhba->programmed_link_rate
170 & 0xf0) >> 4));
171 (void) nvlist_add_int8(phy_props[j],
172 SAS_HW_MAX_LINK_RATE,
173 ((pSmhba->hw_link_rate
174 & 0xf0) >> 4));
175
176 j++;
177
178 if (pSmhba->attached_devhdl &&
179 (attached_devhdl != NULL)) {
180 *attached_devhdl =
181 pSmhba->attached_devhdl;
182 }
183 }
184 }
185
186 rval = nvlist_add_nvlist_array(nvl, SAS_PHY_INFO_NVL, phy_props,
187 phy_nums);
188 if (rval) {
189 mptsas_log(mpt, CE_WARN,
190 " nv list array add failed, return value %d.",
191 rval);
192 goto exit;
193 }
194 (void) nvlist_size(nvl, &packed_size, NV_ENCODE_NATIVE);
195 packed_data = kmem_zalloc(packed_size, KM_SLEEP);
196 (void) nvlist_pack(nvl, &packed_data, &packed_size,
197 NV_ENCODE_NATIVE, 0);
198
199 (void) ddi_prop_update_byte_array(DDI_DEV_T_NONE, dip,
200 SAS_PHY_INFO, (uchar_t *)packed_data, packed_size);
201
202 exit:
203 for (i = 0; i < phy_nums && phy_props[i] != NULL; i++) {
204 nvlist_free(phy_props[i]);
205 }
206 nvlist_free(nvl);
207 kmem_free(phy_props, sizeof (nvlist_t *) * phy_nums);
208
209 if (packed_data != NULL) {
210 kmem_free(packed_data, packed_size);
211 }
212 }
213
214 /*
215 * Called with PHY lock held on phyp
216 */
217 void
218 mptsas_smhba_log_sysevent(mptsas_t *mpt, char *subclass, char *etype,
219 smhba_info_t *phyp)
220 {
221 nvlist_t *attr_list;
222 char *pname;
223 char sas_addr[MPTSAS_WWN_STRLEN];
224 uint8_t phynum = 0;
225 uint8_t lrate = 0;
226
227 if (mpt->m_dip == NULL)
228 return;
229 if (phyp == NULL)
230 return;
231
232 pname = kmem_zalloc(MAXPATHLEN, KM_NOSLEEP);
233 if (pname == NULL)
|
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
25 */
26 /*
27 * This file contains SM-HBA support for MPT SAS driver
28 */
29
30 #if defined(lint) || defined(DEBUG)
31 #define MPTSAS_DEBUG
32 #endif
33
34 /*
35 * standard header files
36 */
37 #include <sys/note.h>
38 #include <sys/scsi/scsi.h>
39 #include <sys/pci.h>
40 #include <sys/scsi/generic/sas.h>
41 #include <sys/scsi/impl/scsi_sas.h>
42
43 #pragma pack(1)
44 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_type.h>
45 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2.h>
46 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_cnfg.h>
47 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_init.h>
48 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_ioc.h>
49 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_sas.h>
50 #pragma pack()
51
52 /*
53 * private header files.
54 */
55 #include <sys/scsi/adapters/mpt_sas/mptsas_var.h>
56 #include <sys/scsi/adapters/mpt_sas/mptsas_smhba.h>
57
58 /*
59 * SM - HBA statics
60 */
61 extern char *mptsas_driver_rev;
62
63 static void mptsas_smhba_create_phy_props(nvlist_t **, smhba_info_t *, uint8_t,
64 uint16_t *);
65 static void mptsas_smhba_update_phy_props(mptsas_t *, dev_info_t *, nvlist_t **,
66 uint8_t);
67
68 static void
69 mptsas_smhba_add_hba_prop(mptsas_t *mpt, data_type_t dt,
70 char *prop_name, void *prop_val);
71
72 void
73 mptsas_smhba_show_phy_info(mptsas_t *mpt);
74
75 static void
76 mptsas_smhba_add_hba_prop(mptsas_t *mpt, data_type_t dt,
77 char *prop_name, void *prop_val)
78 {
79 ASSERT(mpt != NULL);
80
81 switch (dt) {
82 case DATA_TYPE_INT32:
83 if (ddi_prop_update_int(DDI_DEV_T_NONE, mpt->m_dip,
84 prop_name, *(int *)prop_val)) {
85 mptsas_log(mpt, CE_WARN,
86 "%s: %s prop update failed", __func__, prop_name);
87 }
105 {
106 int i;
107
108 ASSERT(mpt != NULL);
109
110 for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
111 mptsas_log(mpt, CE_WARN,
112 "phy %d, Owner hdl:0x%x, attached hdl: 0x%x,"
113 "attached phy identifier %d,Program link rate 0x%x,"
114 "hw link rate 0x%x, negotiator link rate 0x%x, path %s",
115 i, mpt->m_phy_info[i].smhba_info.owner_devhdl,
116 mpt->m_phy_info[i].smhba_info.attached_devhdl,
117 mpt->m_phy_info[i].smhba_info.attached_phy_identify,
118 mpt->m_phy_info[i].smhba_info.programmed_link_rate,
119 mpt->m_phy_info[i].smhba_info.hw_link_rate,
120 mpt->m_phy_info[i].smhba_info.negotiated_link_rate,
121 mpt->m_phy_info[i].smhba_info.path);
122 }
123 }
124
125 static void
126 mptsas_smhba_create_phy_props(nvlist_t **phy_props, smhba_info_t *pSmhba,
127 uint8_t phy_id, uint16_t *attached_devhdl)
128 {
129 (void) nvlist_alloc(phy_props, NV_UNIQUE_NAME, KM_SLEEP);
130 (void) nvlist_add_uint8(*phy_props, SAS_PHY_ID, phy_id);
131 (void) nvlist_add_uint8(*phy_props, "phyState",
132 (pSmhba->negotiated_link_rate & 0x0f));
133 (void) nvlist_add_int8(*phy_props, SAS_NEG_LINK_RATE,
134 (pSmhba->negotiated_link_rate & 0x0f));
135 (void) nvlist_add_int8(*phy_props, SAS_PROG_MIN_LINK_RATE,
136 (pSmhba->programmed_link_rate & 0x0f));
137 (void) nvlist_add_int8(*phy_props, SAS_HW_MIN_LINK_RATE,
138 (pSmhba->hw_link_rate & 0x0f));
139 (void) nvlist_add_int8(*phy_props, SAS_PROG_MAX_LINK_RATE,
140 ((pSmhba->programmed_link_rate & 0xf0) >> 4));
141 (void) nvlist_add_int8(*phy_props, SAS_HW_MAX_LINK_RATE,
142 ((pSmhba->hw_link_rate & 0xf0) >> 4));
143
144 if (pSmhba->attached_devhdl && (attached_devhdl != NULL))
145 *attached_devhdl = pSmhba->attached_devhdl;
146 }
147
148 static void
149 mptsas_smhba_update_phy_props(mptsas_t *mpt, dev_info_t *dip,
150 nvlist_t **phy_props, uint8_t phy_nums)
151 {
152 int rval;
153 size_t packed_size;
154 char *packed_data = NULL;
155 nvlist_t *nvl;
156
157 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP) != 0) {
158 mptsas_log(mpt, CE_WARN, "%s: nvlist_alloc() failed", __func__);
159 return;
160 }
161
162 rval = nvlist_add_nvlist_array(nvl, SAS_PHY_INFO_NVL, phy_props,
163 phy_nums);
164 if (rval) {
165 mptsas_log(mpt, CE_WARN,
166 " nv list array add failed, return value %d.", rval);
167 goto exit;
168 }
169 (void) nvlist_size(nvl, &packed_size, NV_ENCODE_NATIVE);
170 packed_data = kmem_zalloc(packed_size, KM_SLEEP);
171 (void) nvlist_pack(nvl, &packed_data, &packed_size,
172 NV_ENCODE_NATIVE, 0);
173
174 (void) ddi_prop_update_byte_array(DDI_DEV_T_NONE, dip,
175 SAS_PHY_INFO, (uchar_t *)packed_data, packed_size);
176
177 exit:
178 nvlist_free(nvl);
179
180 if (packed_data != NULL) {
181 kmem_free(packed_data, packed_size);
182 }
183 }
184
185 void
186 mptsas_smhba_set_one_phy_props(mptsas_t *mpt, dev_info_t *dip, uint8_t phy_id,
187 uint16_t *attached_devhdl)
188 {
189 nvlist_t *phy_props;
190
191 ASSERT(phy_id < mpt->m_num_phys);
192
193 mptsas_smhba_create_phy_props(&phy_props,
194 &mpt->m_phy_info[phy_id].smhba_info, phy_id, attached_devhdl);
195
196 mptsas_smhba_update_phy_props(mpt, dip, &phy_props, 1);
197
198 nvlist_free(phy_props);
199 }
200
201 void
202 mptsas_smhba_set_all_phy_props(mptsas_t *mpt, dev_info_t *dip, uint8_t phy_nums,
203 mptsas_phymask_t phy_mask, uint16_t *attached_devhdl)
204 {
205 int i, j;
206 nvlist_t **phy_props;
207
208 if (phy_nums == 0)
209 return;
210
211 phy_props = kmem_zalloc(sizeof (nvlist_t *) * phy_nums, KM_SLEEP);
212
213 for (i = 0, j = 0; i < mpt->m_num_phys && j < phy_nums; i++)
214 if (phy_mask == mpt->m_phy_info[i].phy_mask)
215 mptsas_smhba_create_phy_props(&phy_props[j++],
216 &mpt->m_phy_info[i].smhba_info, i, attached_devhdl);
217
218 mptsas_smhba_update_phy_props(mpt, dip, phy_props, j);
219
220 for (i = 0; i < j && phy_props[i] != NULL; i++)
221 nvlist_free(phy_props[i]);
222
223 kmem_free(phy_props, sizeof (nvlist_t *) * phy_nums);
224 }
225
226 /*
227 * Called with PHY lock held on phyp
228 */
229 void
230 mptsas_smhba_log_sysevent(mptsas_t *mpt, char *subclass, char *etype,
231 smhba_info_t *phyp)
232 {
233 nvlist_t *attr_list;
234 char *pname;
235 char sas_addr[MPTSAS_WWN_STRLEN];
236 uint8_t phynum = 0;
237 uint8_t lrate = 0;
238
239 if (mpt->m_dip == NULL)
240 return;
241 if (phyp == NULL)
242 return;
243
244 pname = kmem_zalloc(MAXPATHLEN, KM_NOSLEEP);
245 if (pname == NULL)
|