Print this page
OS-2444 richmond hardware maps need to support ivy bridge
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/fm/topo/modules/common/fac_prov_mptsas/fac_prov_mptsas.c
+++ new/usr/src/lib/fm/topo/modules/common/fac_prov_mptsas/fac_prov_mptsas.c
1 1 /*
2 2 * This file and its contents are supplied under the terms of the
3 3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 4 * You may only use this file in accordance with the terms of version
5 5 * 1.0 of the CDDL.
6 6 *
7 7 * A full copy of the text of the CDDL should have accompanied this
8 8 * source. A copy of the CDDL is also available via the Internet at
9 9 * http://www.illumos.org/license/CDDL.
10 10 */
11 11
12 12 /*
13 13 * Copyright (c) 2013, Joyent, Inc. All rights reserved.
14 14 */
15 15
16 16 #include <unistd.h>
17 17 #include <stdio.h>
18 18 #include <stdlib.h>
19 19 #include <fcntl.h>
20 20 #include <string.h>
21 21 #include <strings.h>
22 22 #include <limits.h>
23 23 #include <alloca.h>
24 24 #include <errno.h>
25 25 #include <libnvpair.h>
26 26 #include <sys/types.h>
27 27 #include <sys/stat.h>
28 28 #include <sys/param.h>
29 29 #include <sys/fm/protocol.h>
30 30 #include <fm/libtopo.h>
31 31 #include <fm/topo_mod.h>
32 32
33 33 #include "sys/scsi/adapters/mpt_sas/mptsas_ioctl.h"
34 34
35 35 #define TOPO_METH_MPTSAS_LED_MODE_VERSION 0
36 36
37 37 static int fac_prov_mptsas_enum(topo_mod_t *, tnode_t *, const char *,
38 38 topo_instance_t, topo_instance_t, void *, void *);
39 39
40 40 /*
41 41 * mpt_sas facility provider methods
42 42 */
43 43 static int mptsas_led_mode(topo_mod_t *, tnode_t *, topo_version_t,
44 44 nvlist_t *, nvlist_t **);
45 45
46 46 const topo_modops_t mptsas_ops = { fac_prov_mptsas_enum, NULL };
47 47
48 48 const topo_modinfo_t mptsas_info =
49 49 { "mpt_sas facility provider", FM_FMRI_SCHEME_HC, TOPO_VERSION,
50 50 &mptsas_ops };
51 51
52 52 static const topo_method_t mptsas_fac_methods[] = {
53 53 { "mptsas_led_mode", TOPO_PROP_METH_DESC,
54 54 TOPO_METH_MPTSAS_LED_MODE_VERSION,
55 55 TOPO_STABILITY_INTERNAL, mptsas_led_mode },
56 56 { NULL }
57 57 };
58 58
59 59 /*ARGSUSED*/
60 60 int
61 61 _topo_init(topo_mod_t *mod, topo_version_t version)
62 62 {
63 63 if (getenv("TOPOFACMPTSASDEBUG") != NULL)
64 64 topo_mod_setdebug(mod);
↓ open down ↓ |
64 lines elided |
↑ open up ↑ |
65 65
66 66 return (topo_mod_register(mod, &mptsas_info, TOPO_VERSION));
67 67 }
68 68
69 69 void
70 70 _topo_fini(topo_mod_t *mod)
71 71 {
72 72 topo_mod_unregister(mod);
73 73 }
74 74
75 +/*
76 + * Get or set LED state for a particular target attached to an mpt_sas
77 + * instance at (Enclosure Number, Slot Number).
78 + *
79 + * Returns:
80 + * -2 /devices node (*devctl) does not exist
81 + * -1 All other failures
82 + * 0 Success
83 + */
75 84 static int
76 85 do_led_control(topo_mod_t *mod, char *devctl, uint16_t enclosure,
77 86 uint16_t slot, uint8_t led, uint32_t *ledmode, boolean_t set)
78 87 {
79 88 int fd;
80 89 mptsas_led_control_t lc;
81 90
82 91 bzero(&lc, sizeof (lc));
83 92
84 93 lc.Command = set ? MPTSAS_LEDCTL_FLAG_SET : MPTSAS_LEDCTL_FLAG_GET;
85 94 lc.Enclosure = enclosure;
86 95 lc.Slot = slot;
87 96 lc.Led = led;
88 97 lc.LedStatus = *ledmode;
89 98
90 99 if ((fd = open(devctl, (set ? O_RDWR : O_RDONLY))) == -1) {
100 + int rc = (errno == ENOENT ? -2 : -1);
91 101 topo_mod_dprintf(mod, "devctl open failed: %s",
92 102 strerror(errno));
93 - return (-1);
103 + return (rc);
94 104 }
95 105
96 106 if (ioctl(fd, MPTIOCTL_LED_CONTROL, &lc) == -1) {
97 107 if (errno == ENOENT) {
98 108 /*
99 109 * If there is not presently a target attached for
100 110 * a particular enclosure/slot pair then the driver
101 111 * does not track LED status for this bay. Assume
102 112 * all LEDs are off.
103 113 */
104 114 lc.LedStatus = 0;
105 115 } else {
106 116 topo_mod_dprintf(mod, "led control ioctl failed: %s",
107 117 strerror(errno));
108 118 (void) close(fd);
109 119 return (-1);
110 120 }
111 121 }
112 122
113 123 *ledmode = lc.LedStatus ? TOPO_LED_STATE_ON : TOPO_LED_STATE_OFF;
114 124
115 125 (void) close(fd);
116 126 return (0);
117 127 }
118 128
119 129 static int
120 130 mptsas_led_mode(topo_mod_t *mod, tnode_t *node, topo_version_t vers,
↓ open down ↓ |
17 lines elided |
↑ open up ↑ |
121 131 nvlist_t *in, nvlist_t **nvout)
122 132 {
123 133 int err, ret = 0;
124 134 tnode_t *pnode = topo_node_parent(node);
125 135 uint32_t type, ledmode = 0;
126 136 nvlist_t *pargs, *nvl;
127 137 char *driver = NULL, *devctl = NULL;
128 138 uint32_t enclosure, slot;
129 139 uint8_t mptsas_led;
130 140 boolean_t set;
141 + char *elem, *lastp;
131 142
132 143 if (vers > TOPO_METH_MPTSAS_LED_MODE_VERSION)
133 144 return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW));
134 145
135 146 if (topo_prop_get_string(pnode, TOPO_PGROUP_BINDING,
136 147 TOPO_BINDING_DRIVER, &driver, &err) != 0 ||
137 148 strcmp("mpt_sas", driver) != 0) {
138 149 topo_mod_dprintf(mod, "%s: Facility driver was not mpt_sas",
139 150 __func__);
140 151 ret = topo_mod_seterrno(mod, EMOD_NVL_INVAL);
141 152 goto out;
142 153 }
143 154 if (topo_prop_get_uint32(node, TOPO_PGROUP_FACILITY, TOPO_FACILITY_TYPE,
144 155 &type, &err) != 0) {
145 156 topo_mod_dprintf(mod, "%s: Failed to lookup %s property "
146 157 "(%s)", __func__, TOPO_FACILITY_TYPE, topo_strerror(err));
147 158 return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
148 159 }
149 160 switch (type) {
150 161 case (TOPO_LED_TYPE_SERVICE):
151 162 mptsas_led = MPTSAS_LEDCTL_LED_FAIL;
152 163 break;
153 164 case (TOPO_LED_TYPE_LOCATE):
154 165 mptsas_led = MPTSAS_LEDCTL_LED_IDENT;
155 166 break;
156 167 case (TOPO_LED_TYPE_OK2RM):
157 168 mptsas_led = MPTSAS_LEDCTL_LED_OK2RM;
158 169 break;
159 170 default:
160 171 topo_mod_dprintf(mod, "%s: Invalid LED type: 0x%x\n", __func__,
161 172 type);
162 173 return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
163 174 }
164 175 if (topo_prop_get_string(pnode, TOPO_PGROUP_BINDING,
165 176 TOPO_BINDING_DEVCTL, &devctl, &err) != 0 ||
166 177 topo_prop_get_uint32(pnode, TOPO_PGROUP_BINDING,
167 178 TOPO_BINDING_ENCLOSURE, &enclosure, &err) != 0 ||
168 179 topo_prop_get_uint32(pnode, TOPO_PGROUP_BINDING,
169 180 TOPO_BINDING_SLOT, &slot, &err) != 0) {
170 181 topo_mod_dprintf(mod, "%s: Facility was missing mpt_sas binding"
171 182 " properties\n", __func__);
172 183 ret = topo_mod_seterrno(mod, EMOD_NVL_INVAL);
173 184 goto out;
174 185 }
175 186
176 187 if ((nvlist_lookup_nvlist(in, TOPO_PROP_PARGS, &pargs) == 0) &&
177 188 nvlist_exists(pargs, TOPO_PROP_VAL_VAL)) {
178 189 /*
179 190 * Set the LED mode
180 191 */
181 192 set = B_TRUE;
182 193 if ((ret = nvlist_lookup_uint32(pargs, TOPO_PROP_VAL_VAL,
183 194 &ledmode)) != 0) {
184 195 topo_mod_dprintf(mod, "%s: Failed to lookup %s nvpair "
185 196 "(%s)\n", __func__, TOPO_PROP_VAL_VAL,
186 197 strerror(ret));
187 198 ret = topo_mod_seterrno(mod, EMOD_NVL_INVAL);
188 199 goto out;
189 200 }
↓ open down ↓ |
49 lines elided |
↑ open up ↑ |
190 201 topo_mod_dprintf(mod, "%s: Setting LED mode to %s\n", __func__,
191 202 ledmode ? "ON" : "OFF");
192 203 } else {
193 204 /*
194 205 * Get the LED mode
195 206 */
196 207 set = B_FALSE;
197 208 topo_mod_dprintf(mod, "%s: Getting LED mode\n", __func__);
198 209 }
199 210
200 - if (do_led_control(mod, devctl, enclosure, slot, mptsas_led, &ledmode,
201 - set) != 0) {
211 + /*
212 + * devctl is a (potentially) pipe-separated list of different device
213 + * paths to try.
214 + */
215 + if ((elem = topo_mod_strsplit(mod, devctl, "|", &lastp)) == NULL) {
216 + topo_mod_dprintf(mod, "%s: could not parse devctl list",
217 + __func__);
218 + ret = topo_mod_seterrno(mod, EMOD_UNKNOWN);
219 + goto out;
220 + }
221 + do {
222 + topo_mod_dprintf(mod, "%s: trying mpt_sas instance at %s\n",
223 + __func__, elem);
224 +
225 + ret = do_led_control(mod, elem, enclosure, slot,
226 + mptsas_led, &ledmode, set);
227 +
228 + topo_mod_strfree(mod, elem);
229 +
230 + /*
231 + * Only try further devctl paths from the list if this one
232 + * was not found:
233 + */
234 + if (ret != -2) {
235 + break;
236 + } else {
237 + topo_mod_dprintf(mod, "%s: instance not found\n",
238 + __func__);
239 + }
240 +
241 + } while ((elem = topo_mod_strsplit(mod, NULL, "|", &lastp)) != NULL);
242 +
243 + if (ret != 0) {
202 244 topo_mod_dprintf(mod, "%s: do_led_control failed", __func__);
203 245 ret = topo_mod_seterrno(mod, EMOD_UNKNOWN);
204 246 goto out;
205 247 }
206 248
207 249 if (topo_mod_nvalloc(mod, &nvl, NV_UNIQUE_NAME) != 0 ||
208 250 nvlist_add_string(nvl, TOPO_PROP_VAL_NAME, TOPO_LED_MODE) != 0 ||
209 251 nvlist_add_uint32(nvl, TOPO_PROP_VAL_TYPE, TOPO_TYPE_UINT32) != 0 ||
210 252 nvlist_add_uint32(nvl, TOPO_PROP_VAL_VAL, ledmode) != 0) {
211 253 topo_mod_dprintf(mod, "%s: Failed to allocate 'out' nvlist\n",
212 254 __func__);
213 255 nvlist_free(nvl);
214 256 ret = topo_mod_seterrno(mod, EMOD_NOMEM);
215 257 goto out;
216 258 }
217 259 *nvout = nvl;
218 260
219 261 out:
220 262 if (driver != NULL)
221 263 topo_mod_strfree(mod, driver);
222 264 if (devctl != NULL)
223 265 topo_mod_strfree(mod, devctl);
224 266 return (ret);
225 267 }
226 268
227 269 /*ARGSUSED*/
228 270 static int
229 271 fac_prov_mptsas_enum(topo_mod_t *mod, tnode_t *rnode, const char *name,
230 272 topo_instance_t min, topo_instance_t max, void *arg, void *unused)
231 273 {
232 274 if (topo_node_flags(rnode) == TOPO_NODE_FACILITY) {
233 275 if (topo_method_register(mod, rnode, mptsas_fac_methods) != 0) {
234 276 topo_mod_dprintf(mod, "%s: topo_method_register() "
235 277 "failed: %s", __func__, topo_mod_errmsg(mod));
236 278 return (-1);
237 279 }
238 280 return (0);
239 281 }
240 282
241 283 topo_mod_dprintf(mod, "%s: unexpected node flags %x", __func__,
242 284 topo_node_flags(rnode));
243 285 return (-1);
244 286 }
↓ open down ↓ |
33 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX