55 TOPO_STABILITY_INTERNAL, mptsas_led_mode },
56 { NULL }
57 };
58
59 /*ARGSUSED*/
60 int
61 _topo_init(topo_mod_t *mod, topo_version_t version)
62 {
63 if (getenv("TOPOFACMPTSASDEBUG") != NULL)
64 topo_mod_setdebug(mod);
65
66 return (topo_mod_register(mod, &mptsas_info, TOPO_VERSION));
67 }
68
69 void
70 _topo_fini(topo_mod_t *mod)
71 {
72 topo_mod_unregister(mod);
73 }
74
75 static int
76 do_led_control(topo_mod_t *mod, char *devctl, uint16_t enclosure,
77 uint16_t slot, uint8_t led, uint32_t *ledmode, boolean_t set)
78 {
79 int fd;
80 mptsas_led_control_t lc;
81
82 bzero(&lc, sizeof (lc));
83
84 lc.Command = set ? MPTSAS_LEDCTL_FLAG_SET : MPTSAS_LEDCTL_FLAG_GET;
85 lc.Enclosure = enclosure;
86 lc.Slot = slot;
87 lc.Led = led;
88 lc.LedStatus = *ledmode;
89
90 if ((fd = open(devctl, (set ? O_RDWR : O_RDONLY))) == -1) {
91 topo_mod_dprintf(mod, "devctl open failed: %s",
92 strerror(errno));
93 return (-1);
94 }
95
96 if (ioctl(fd, MPTIOCTL_LED_CONTROL, &lc) == -1) {
97 if (errno == ENOENT) {
98 /*
99 * If there is not presently a target attached for
100 * a particular enclosure/slot pair then the driver
101 * does not track LED status for this bay. Assume
102 * all LEDs are off.
103 */
104 lc.LedStatus = 0;
105 } else {
106 topo_mod_dprintf(mod, "led control ioctl failed: %s",
107 strerror(errno));
108 (void) close(fd);
109 return (-1);
110 }
111 }
112
113 *ledmode = lc.LedStatus ? TOPO_LED_STATE_ON : TOPO_LED_STATE_OFF;
114
115 (void) close(fd);
116 return (0);
117 }
118
119 static int
120 mptsas_led_mode(topo_mod_t *mod, tnode_t *node, topo_version_t vers,
121 nvlist_t *in, nvlist_t **nvout)
122 {
123 int err, ret = 0;
124 tnode_t *pnode = topo_node_parent(node);
125 uint32_t type, ledmode = 0;
126 nvlist_t *pargs, *nvl;
127 char *driver = NULL, *devctl = NULL;
128 uint32_t enclosure, slot;
129 uint8_t mptsas_led;
130 boolean_t set;
131
132 if (vers > TOPO_METH_MPTSAS_LED_MODE_VERSION)
133 return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW));
134
135 if (topo_prop_get_string(pnode, TOPO_PGROUP_BINDING,
136 TOPO_BINDING_DRIVER, &driver, &err) != 0 ||
137 strcmp("mpt_sas", driver) != 0) {
138 topo_mod_dprintf(mod, "%s: Facility driver was not mpt_sas",
139 __func__);
140 ret = topo_mod_seterrno(mod, EMOD_NVL_INVAL);
141 goto out;
142 }
143 if (topo_prop_get_uint32(node, TOPO_PGROUP_FACILITY, TOPO_FACILITY_TYPE,
144 &type, &err) != 0) {
145 topo_mod_dprintf(mod, "%s: Failed to lookup %s property "
146 "(%s)", __func__, TOPO_FACILITY_TYPE, topo_strerror(err));
147 return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
148 }
149 switch (type) {
150 case (TOPO_LED_TYPE_SERVICE):
180 */
181 set = B_TRUE;
182 if ((ret = nvlist_lookup_uint32(pargs, TOPO_PROP_VAL_VAL,
183 &ledmode)) != 0) {
184 topo_mod_dprintf(mod, "%s: Failed to lookup %s nvpair "
185 "(%s)\n", __func__, TOPO_PROP_VAL_VAL,
186 strerror(ret));
187 ret = topo_mod_seterrno(mod, EMOD_NVL_INVAL);
188 goto out;
189 }
190 topo_mod_dprintf(mod, "%s: Setting LED mode to %s\n", __func__,
191 ledmode ? "ON" : "OFF");
192 } else {
193 /*
194 * Get the LED mode
195 */
196 set = B_FALSE;
197 topo_mod_dprintf(mod, "%s: Getting LED mode\n", __func__);
198 }
199
200 if (do_led_control(mod, devctl, enclosure, slot, mptsas_led, &ledmode,
201 set) != 0) {
202 topo_mod_dprintf(mod, "%s: do_led_control failed", __func__);
203 ret = topo_mod_seterrno(mod, EMOD_UNKNOWN);
204 goto out;
205 }
206
207 if (topo_mod_nvalloc(mod, &nvl, NV_UNIQUE_NAME) != 0 ||
208 nvlist_add_string(nvl, TOPO_PROP_VAL_NAME, TOPO_LED_MODE) != 0 ||
209 nvlist_add_uint32(nvl, TOPO_PROP_VAL_TYPE, TOPO_TYPE_UINT32) != 0 ||
210 nvlist_add_uint32(nvl, TOPO_PROP_VAL_VAL, ledmode) != 0) {
211 topo_mod_dprintf(mod, "%s: Failed to allocate 'out' nvlist\n",
212 __func__);
213 nvlist_free(nvl);
214 ret = topo_mod_seterrno(mod, EMOD_NOMEM);
215 goto out;
216 }
217 *nvout = nvl;
218
219 out:
220 if (driver != NULL)
221 topo_mod_strfree(mod, driver);
|
55 TOPO_STABILITY_INTERNAL, mptsas_led_mode },
56 { NULL }
57 };
58
59 /*ARGSUSED*/
60 int
61 _topo_init(topo_mod_t *mod, topo_version_t version)
62 {
63 if (getenv("TOPOFACMPTSASDEBUG") != NULL)
64 topo_mod_setdebug(mod);
65
66 return (topo_mod_register(mod, &mptsas_info, TOPO_VERSION));
67 }
68
69 void
70 _topo_fini(topo_mod_t *mod)
71 {
72 topo_mod_unregister(mod);
73 }
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 */
84 static int
85 do_led_control(topo_mod_t *mod, char *devctl, uint16_t enclosure,
86 uint16_t slot, uint8_t led, uint32_t *ledmode, boolean_t set)
87 {
88 int fd;
89 mptsas_led_control_t lc;
90
91 bzero(&lc, sizeof (lc));
92
93 lc.Command = set ? MPTSAS_LEDCTL_FLAG_SET : MPTSAS_LEDCTL_FLAG_GET;
94 lc.Enclosure = enclosure;
95 lc.Slot = slot;
96 lc.Led = led;
97 lc.LedStatus = *ledmode;
98
99 if ((fd = open(devctl, (set ? O_RDWR : O_RDONLY))) == -1) {
100 int rc = (errno == ENOENT ? -2 : -1);
101 topo_mod_dprintf(mod, "devctl open failed: %s",
102 strerror(errno));
103 return (rc);
104 }
105
106 if (ioctl(fd, MPTIOCTL_LED_CONTROL, &lc) == -1) {
107 if (errno == ENOENT) {
108 /*
109 * If there is not presently a target attached for
110 * a particular enclosure/slot pair then the driver
111 * does not track LED status for this bay. Assume
112 * all LEDs are off.
113 */
114 lc.LedStatus = 0;
115 } else {
116 topo_mod_dprintf(mod, "led control ioctl failed: %s",
117 strerror(errno));
118 (void) close(fd);
119 return (-1);
120 }
121 }
122
123 *ledmode = lc.LedStatus ? TOPO_LED_STATE_ON : TOPO_LED_STATE_OFF;
124
125 (void) close(fd);
126 return (0);
127 }
128
129 static int
130 mptsas_led_mode(topo_mod_t *mod, tnode_t *node, topo_version_t vers,
131 nvlist_t *in, nvlist_t **nvout)
132 {
133 int err, ret = 0;
134 tnode_t *pnode = topo_node_parent(node);
135 uint32_t type, ledmode = 0;
136 nvlist_t *pargs, *nvl;
137 char *driver = NULL, *devctl = NULL;
138 uint32_t enclosure, slot;
139 uint8_t mptsas_led;
140 boolean_t set;
141 char *elem, *lastp;
142
143 if (vers > TOPO_METH_MPTSAS_LED_MODE_VERSION)
144 return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW));
145
146 if (topo_prop_get_string(pnode, TOPO_PGROUP_BINDING,
147 TOPO_BINDING_DRIVER, &driver, &err) != 0 ||
148 strcmp("mpt_sas", driver) != 0) {
149 topo_mod_dprintf(mod, "%s: Facility driver was not mpt_sas",
150 __func__);
151 ret = topo_mod_seterrno(mod, EMOD_NVL_INVAL);
152 goto out;
153 }
154 if (topo_prop_get_uint32(node, TOPO_PGROUP_FACILITY, TOPO_FACILITY_TYPE,
155 &type, &err) != 0) {
156 topo_mod_dprintf(mod, "%s: Failed to lookup %s property "
157 "(%s)", __func__, TOPO_FACILITY_TYPE, topo_strerror(err));
158 return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
159 }
160 switch (type) {
161 case (TOPO_LED_TYPE_SERVICE):
191 */
192 set = B_TRUE;
193 if ((ret = nvlist_lookup_uint32(pargs, TOPO_PROP_VAL_VAL,
194 &ledmode)) != 0) {
195 topo_mod_dprintf(mod, "%s: Failed to lookup %s nvpair "
196 "(%s)\n", __func__, TOPO_PROP_VAL_VAL,
197 strerror(ret));
198 ret = topo_mod_seterrno(mod, EMOD_NVL_INVAL);
199 goto out;
200 }
201 topo_mod_dprintf(mod, "%s: Setting LED mode to %s\n", __func__,
202 ledmode ? "ON" : "OFF");
203 } else {
204 /*
205 * Get the LED mode
206 */
207 set = B_FALSE;
208 topo_mod_dprintf(mod, "%s: Getting LED mode\n", __func__);
209 }
210
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) {
244 topo_mod_dprintf(mod, "%s: do_led_control failed", __func__);
245 ret = topo_mod_seterrno(mod, EMOD_UNKNOWN);
246 goto out;
247 }
248
249 if (topo_mod_nvalloc(mod, &nvl, NV_UNIQUE_NAME) != 0 ||
250 nvlist_add_string(nvl, TOPO_PROP_VAL_NAME, TOPO_LED_MODE) != 0 ||
251 nvlist_add_uint32(nvl, TOPO_PROP_VAL_TYPE, TOPO_TYPE_UINT32) != 0 ||
252 nvlist_add_uint32(nvl, TOPO_PROP_VAL_VAL, ledmode) != 0) {
253 topo_mod_dprintf(mod, "%s: Failed to allocate 'out' nvlist\n",
254 __func__);
255 nvlist_free(nvl);
256 ret = topo_mod_seterrno(mod, EMOD_NOMEM);
257 goto out;
258 }
259 *nvout = nvl;
260
261 out:
262 if (driver != NULL)
263 topo_mod_strfree(mod, driver);
|