1 /*
2 * CDDL HEADER START
3 *
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 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2025 Hans Rosenfeld
24 */
25
26 #include "mp_utils.h"
27 #include <sys/sunddi.h>
28
29 #ifndef OIDLIST
30 #define OIDLIST "oid"
31 #endif
32
33
34 /* Remove these 5 when this source can compile with sunddi.h */
35 #ifndef EC_DDI
36 #define EC_DDI "EC_ddi"
37 #endif
38
39 #ifndef ESC_DDI_INITIATOR_REGISTER
40 #define ESC_DDI_INITIATOR_REGISTER "ESC_ddi_initiator_register"
41 #endif
42
43 #ifndef ESC_DDI_INITIATOR_UNREGISTER
44 #define ESC_DDI_INITIATOR_UNREGISTER "ESC_ddi_initiator_unregister"
45 #endif
46
47 #ifndef DDI_DRIVER_MAJOR
48 #define DDI_DRIVER_MAJOR "ddi.major"
49 #endif
50
51 #ifndef DDI_INSTANCE
52 #define DDI_INSTANCE "ddi.instance"
53 #endif
54
55
56 #define VISA_CHANGE 1
57 #define PROP_CHANGE 2
58
59
60
61 MP_STATUS
getStatus4ErrorCode(int driverError)62 getStatus4ErrorCode(int driverError)
63 {
64 MP_STATUS mpStatus = MP_STATUS_FAILED;
65
66 log(LOG_INFO, "getStatus4ErrorCode()", "- enter");
67
68 switch (driverError) {
69
70 case MP_DRVR_INVALID_ID:
71 log(LOG_INFO, "getStatus4ErrorCode()",
72 " received mp_errno=MP_DRVR_INVALID_ID"
73 " from driver call.");
74 log(LOG_INFO, "getStatus4ErrorCode()",
75 " returning MP_STATUS_OBJECT_NOT_FOUND"
76 " to caller.");
77 mpStatus = MP_STATUS_OBJECT_NOT_FOUND;
78 break;
79
80
81 case MP_DRVR_ID_OBSOLETE:
82 log(LOG_INFO, "getStatus4ErrorCode()",
83 " received mp_errno=MP_DRVR_ID_OBSOLETE"
84 " from driver call.");
85 log(LOG_INFO, "getStatus4ErrorCode()",
86 " returning MP_STATUS_OBJECT_NOT_FOUND"
87 " to caller.");
88 mpStatus = MP_STATUS_OBJECT_NOT_FOUND;
89 break;
90
91
92 case MP_DRVR_ACCESS_SYMMETRIC:
93 log(LOG_INFO, "getStatus4ErrorCode()",
94 " received mp_errno=MP_DRVR_ACCESS_SYMMETRIC"
95 " from driver call.");
96 log(LOG_INFO, "getStatus4ErrorCode()",
97 " returning MP_STATUS_INVALID_PARAMETER"
98 " to caller.");
99 mpStatus = MP_STATUS_INVALID_PARAMETER;
100 break;
101
102
103 case MP_DRVR_PATH_UNAVAILABLE:
104 log(LOG_INFO, "getStatus4ErrorCode()",
105 " received mp_errno=MP_DRVR_PATH_UNAVAILABLE"
106 " from driver call.");
107 log(LOG_INFO, "getStatus4ErrorCode()",
108 " returning MP_STATUS_PATH_NONOPERATIONAL"
109 " to caller.");
110 mpStatus = MP_STATUS_PATH_NONOPERATIONAL;
111 break;
112
113
114 case MP_DRVR_IDS_NOT_ASSOCIATED:
115 log(LOG_INFO, "getStatus4ErrorCode()",
116 " received mp_errno=MP_DRVR_IDS_NOT_ASSOCIATED"
117 " from driver call.");
118 log(LOG_INFO, "getStatus4ErrorCode()",
119 " returning MP_STATUS_INVALID_PARAMETER"
120 " to caller.");
121 mpStatus = MP_STATUS_INVALID_PARAMETER;
122 break;
123
124
125 case MP_DRVR_ILLEGAL_ACCESS_STATE_REQUEST:
126 log(LOG_INFO, "getStatus4ErrorCode()",
127 " received mp_errno="
128 "MP_DRVR_ILLEGAL_ACCESS_STATE_REQUEST"
129 " from driver call.");
130 log(LOG_INFO, "getStatus4ErrorCode()",
131 " returning MP_STATUS_INVALID_PARAMETER"
132 " to caller.");
133 mpStatus = MP_STATUS_ACCESS_STATE_INVALID;
134 break;
135
136
137 case MP_DRVR_ILLEGAL_LOAD_BALANCING_TYPE:
138 log(LOG_INFO, "getStatus4ErrorCode()",
139 " received mp_errno="
140 "MP_DRVR_ILLEGAL_LOAD_BALANCING_TYPE"
141 " from driver call.");
142 log(LOG_INFO, "getStatus4ErrorCode()",
143 " returning MP_STATUS_INVALID_PARAMETER"
144 " to caller.");
145 mpStatus = MP_STATUS_INVALID_PARAMETER;
146 break;
147
148 default:
149 log(LOG_INFO, "getStatus4ErrorCode()",
150 " - received (unsupported) mp_errno=%d from"
151 " driver call.", driverError);
152 log(LOG_INFO, "getStatus4ErrorCode()",
153 " - returning MP_STATUS_FAILED to caller.");
154 mpStatus = MP_STATUS_FAILED;
155 }
156
157 log(LOG_INFO, "getStatus4ErrorCode()", "- exit");
158
159 return (mpStatus);
160 }
161
162
163
164 MP_OID_LIST
createOidList(int size)165 *createOidList(int size) {
166
167 MP_OID_LIST *pOidList = NULL;
168
169
170 log(LOG_INFO, "createOidList()", "- enter");
171
172
173 if (size < 1) {
174
175 log(LOG_INFO, "createOidList()",
176 "requested size is less than 1");
177 log(LOG_INFO, "createOidList()",
178 " - error exit");
179 return (NULL);
180
181 } else {
182
183 pOidList = (MP_OID_LIST*)calloc(1,
184 sizeof (MP_OID_LIST) +
185 ((size - 1) *
186 sizeof (MP_OID)));
187
188 if (NULL == pOidList) {
189 log(LOG_INFO, "createOidList()",
190 "no memory for pOidList");
191 log(LOG_INFO, "createOidList()",
192 " - error exit");
193 return (NULL);
194 }
195
196 log(LOG_INFO,
197 "createOidList()",
198 "- exit(%d)",
199 size);
200
201 return (pOidList);
202 }
203 }
204
205 /* Calls the client callback function, if one is registered */
206 static void
notifyClient(sysevent_t * ev)207 notifyClient(sysevent_t *ev)
208 {
209 nvlist_t *attr_list = NULL;
210
211 uint64_t *val = NULL;
212 int32_t *instance = NULL;
213 int32_t *major = NULL;
214
215 int valAllocated = 0;
216
217 uint_t nelem = 0;
218
219 int i = 0;
220 int eventType = 0;
221 int index = -1;
222
223 void *pCallerData = NULL;
224
225 char subClassName[256];
226
227 MP_BOOL becomingVisible = MP_FALSE;
228
229 MP_OID_LIST *oidList = NULL;
230
231
232 log(LOG_INFO, "notifyClient()", "- enter");
233
234
235 (void) strncpy(subClassName, sysevent_get_subclass_name(ev), 256);
236
237 if (strstr(subClassName, "change")) {
238
239 eventType = PROP_CHANGE;
240
241 log(LOG_INFO, "notifyClient()", "- got a change event");
242 log(LOG_INFO, "notifyClient()", ": [%s]",
243 subClassName);
244
245 if (strncmp(subClassName, ESC_SUN_MP_PLUGIN_CHANGE, 255)
246 == 0) {
247
248 index = MP_OBJECT_TYPE_PLUGIN;
249
250 } else if (strncmp(subClassName, ESC_SUN_MP_LU_CHANGE, 255)
251 == 0) {
252
253 index = MP_OBJECT_TYPE_MULTIPATH_LU;
254
255 } else if (strncmp(subClassName, ESC_SUN_MP_PATH_CHANGE, 255)
256 == 0) {
257
258 index = MP_OBJECT_TYPE_PATH_LU;
259
260 } else if (strncmp(subClassName, ESC_SUN_MP_INIT_PORT_CHANGE,
261 255) == 0) {
262
263 index = MP_OBJECT_TYPE_INITIATOR_PORT;
264
265 } else if (strncmp(subClassName, ESC_SUN_MP_TPG_CHANGE, 255)
266 == 0) {
267
268 index = MP_OBJECT_TYPE_TARGET_PORT_GROUP;
269
270 } else if (strncmp(subClassName, ESC_SUN_MP_TARGET_PORT_CHANGE,
271 255) == 0) {
272
273 index = MP_OBJECT_TYPE_TARGET_PORT;
274
275 } else if (strncmp(subClassName, ESC_SUN_MP_DEV_PROD_CHANGE,
276 255) == 0) {
277
278 index = MP_OBJECT_TYPE_DEVICE_PRODUCT;
279 }
280
281 } else if ((strstr(subClassName, "add")) ||
282 (strstr(subClassName, "initiator_register"))) {
283
284 eventType = VISA_CHANGE;
285 becomingVisible = MP_TRUE;
286
287 log(LOG_INFO, "notifyClient()", "- got a visibility"
288 " add event");
289 log(LOG_INFO, "notifyClient()", ": [%s]",
290 subClassName);
291
292 if (strncmp(subClassName, ESC_SUN_MP_LU_ADD, 255) == 0) {
293
294 index = MP_OBJECT_TYPE_MULTIPATH_LU;
295
296 } else if (strncmp(subClassName, ESC_SUN_MP_PATH_ADD, 255)
297 == 0) {
298
299 index = MP_OBJECT_TYPE_PATH_LU;
300
301 } else if (strncmp(subClassName, ESC_DDI_INITIATOR_REGISTER,
302 244) == 0) {
303
304 index = MP_OBJECT_TYPE_INITIATOR_PORT;
305
306 } else if (strncmp(subClassName, ESC_SUN_MP_TPG_ADD,
307 255) == 0) {
308
309 index = MP_OBJECT_TYPE_TARGET_PORT_GROUP;
310
311 } else if (strncmp(subClassName, ESC_SUN_MP_TARGET_PORT_ADD,
312 255) == 0) {
313
314 index = MP_OBJECT_TYPE_TARGET_PORT;
315
316 } else if (strncmp(subClassName, ESC_SUN_MP_DEV_PROD_ADD, 255)
317 == 0) {
318
319 index = MP_OBJECT_TYPE_DEVICE_PRODUCT;
320 }
321
322
323 } else if ((strstr(subClassName, "remove")) ||
324 (strstr(subClassName, "initiator_unregister"))) {
325
326 eventType = VISA_CHANGE;
327 becomingVisible = MP_FALSE;
328
329 log(LOG_INFO, "notifyClient()", "- got a visibility"
330 " remove event");
331 log(LOG_INFO, "notifyClient()", ": [%s]",
332 subClassName);
333
334 if (strncmp(subClassName, ESC_SUN_MP_LU_REMOVE, 255) == 0) {
335
336 index = MP_OBJECT_TYPE_MULTIPATH_LU;
337
338 } else if (strncmp(subClassName, ESC_SUN_MP_PATH_REMOVE, 255)
339 == 0) {
340
341 index = MP_OBJECT_TYPE_PATH_LU;
342
343 } else if (strncmp(subClassName, ESC_DDI_INITIATOR_UNREGISTER,
344 255) == 0) {
345
346 index = MP_OBJECT_TYPE_INITIATOR_PORT;
347
348 } else if (strncmp(subClassName, ESC_SUN_MP_TPG_REMOVE, 255)
349 == 0) {
350
351 index = MP_OBJECT_TYPE_TARGET_PORT_GROUP;
352
353 } else if (strncmp(subClassName, ESC_SUN_MP_TARGET_PORT_REMOVE,
354 255) == 0) {
355
356 index = MP_OBJECT_TYPE_TARGET_PORT;
357
358 } else if (strncmp(subClassName, ESC_SUN_MP_DEV_PROD_REMOVE,
359 255) == 0) {
360
361 index = MP_OBJECT_TYPE_DEVICE_PRODUCT;
362 }
363
364
365 } else {
366 log(LOG_INFO, "notifyClient()", "- got an unsupported event");
367 return;
368 }
369
370 if (index < 0) {
371
372 log(LOG_INFO, "notifyClient()", "- index is less than zero");
373 return;
374 }
375
376 if (eventType == VISA_CHANGE) {
377
378 (void) pthread_mutex_lock(&g_visa_mutex);
379
380 if (NULL == g_Visibility_Callback_List[index].pClientFn) {
381
382 log(LOG_INFO, "notifyClient()",
383 "- no visibility change callback to notify");
384
385 (void) pthread_mutex_unlock(&g_visa_mutex);
386
387 return;
388 }
389
390 (void) pthread_mutex_unlock(&g_visa_mutex);
391 }
392
393 if (eventType == PROP_CHANGE) {
394
395 (void) pthread_mutex_lock(&g_prop_mutex);
396
397 if (NULL == g_Property_Callback_List[index].pClientFn) {
398
399 log(LOG_INFO, "notifyClient()",
400 "- no property change callback to notify");
401
402 (void) pthread_mutex_unlock(&g_prop_mutex);
403
404 return;
405 }
406
407 (void) pthread_mutex_unlock(&g_prop_mutex);
408 }
409
410 (void) sysevent_get_attr_list(ev, &attr_list);
411 if (NULL != attr_list) {
412
413 if ((VISA_CHANGE == eventType) &&
414 (MP_OBJECT_TYPE_PLUGIN == index)) {
415
416 val = (uint64_t *)malloc(sizeof (uint64_t));
417 valAllocated = 1;
418
419 /*
420 * We have no well-defined way to determine our OSN.
421 * Currently the common library uses 0 as OSN for every
422 * plugin, so just use 0. If the OSN assigned by the
423 * common library changed, this code would have to be
424 * updated.
425 */
426 *val = 0;
427 nelem = 1;
428
429 } else if ((VISA_CHANGE == eventType) &&
430 (MP_OBJECT_TYPE_INITIATOR_PORT == index)) {
431
432 (void) nvlist_lookup_int32_array(attr_list,
433 DDI_INSTANCE, &instance, &nelem);
434
435 log(LOG_INFO, "notifyClient()",
436 "- event (PHCI_INSTANCE) has [%d] elements",
437 nelem);
438
439 (void) nvlist_lookup_int32_array(attr_list,
440 DDI_DRIVER_MAJOR, &major, &nelem);
441
442 log(LOG_INFO, "notifyClient()",
443 "- event (PHCI_DRIVER_MAJOR) has [%d] elements",
444 nelem);
445
446 if ((NULL != instance) & (NULL != major)) {
447
448 val = (uint64_t *)malloc(sizeof (uint64_t));
449
450 valAllocated = 1;
451
452 *val = 0;
453 *val = MP_STORE_INST_TO_ID(*instance, *val);
454 *val = MP_STORE_MAJOR_TO_ID(*major, *val);
455
456 nelem = 1;
457
458 } else {
459
460 nelem = 0;
461 }
462
463 } else {
464
465 (void) nvlist_lookup_uint64_array(attr_list, OIDLIST,
466 &val, &nelem);
467
468 log(LOG_INFO, "notifyClient()",
469 "- event has [%d] elements",
470 nelem);
471 }
472
473 if (nelem > 0) {
474
475 for (i = 0; i < nelem; i++) {
476
477 log(LOG_INFO, "notifyClient()",
478 "- event [%d] = %llx",
479 i, val[i]);
480 }
481
482 oidList = createOidList(nelem);
483 if (NULL == oidList) {
484
485 log(LOG_INFO, "notifyClient()",
486 "- unable to create MP_OID_LIST");
487
488 log(LOG_INFO, "notifyClient()",
489 "- error exit");
490
491 nvlist_free(attr_list);
492
493 return;
494 }
495
496 oidList->oidCount = nelem;
497
498 for (i = 0; i < nelem; i++) {
499
500 oidList->oids[i].objectType = index;
501 oidList->oids[i].ownerId = g_pluginOwnerID;
502 oidList->oids[i].objectSequenceNumber = val[i];
503 }
504
505 if (valAllocated) {
506
507 free(val);
508 }
509
510 for (i = 0; i < oidList->oidCount; i++) {
511
512 log(LOG_INFO, "notifyClient()",
513 "oidList->oids[%d].objectType"
514 " = %d",
515 i, oidList->oids[i].objectType);
516 log(LOG_INFO, "notifyClient()",
517 "oidList->oids[%d].ownerId"
518 " = %d",
519 i, oidList->oids[i].ownerId);
520 log(LOG_INFO, "notifyClient()",
521 "oidList->oids[%d].objectSequenceNumber"
522 " = %llx",
523 i, oidList->oids[i].objectSequenceNumber);
524 }
525
526 if (eventType == PROP_CHANGE) {
527
528 (void) pthread_mutex_lock(&g_prop_mutex);
529
530 pCallerData = g_Property_Callback_List[index].
531 pCallerData;
532
533 (g_Property_Callback_List[index].pClientFn)
534 (oidList, pCallerData);
535
536 (void) pthread_mutex_unlock(&g_prop_mutex);
537
538 } else if (eventType == VISA_CHANGE) {
539
540 (void) pthread_mutex_lock(&g_visa_mutex);
541
542 pCallerData = g_Visibility_Callback_List[index].
543 pCallerData;
544
545 (g_Visibility_Callback_List[index].pClientFn)
546 (becomingVisible, oidList, pCallerData);
547
548 (void) pthread_mutex_unlock(&g_visa_mutex);
549
550 }
551 }
552
553 nvlist_free(attr_list);
554 }
555
556
557 log(LOG_INFO, "notifyClient()", "- exit");
558 }
559
560 /* Event handler called by system */
561 static void
sysevent_handler(sysevent_t * ev)562 sysevent_handler(sysevent_t *ev)
563 {
564 log(LOG_INFO, "sysevent_handler()", "- enter");
565
566 /* Is the event one of ours? */
567 if ((strncmp(EC_SUN_MP, sysevent_get_class_name(ev), 9) != 0) &&
568 (strncmp(EC_DDI, sysevent_get_class_name(ev), 6) != 0)) {
569
570 return;
571 }
572
573 /* Notify client if it cares */
574 notifyClient(ev);
575
576
577 log(LOG_INFO, "sysevent_handler()", "- exit");
578 }
579
580 /* Registers the plugin to the sysevent framework */
581 MP_STATUS
init_sysevents(void)582 init_sysevents(void)
583 {
584
585 const char *subclass_list[] = {
586
587 ESC_SUN_MP_PLUGIN_CHANGE,
588
589 ESC_SUN_MP_LU_CHANGE,
590 ESC_SUN_MP_LU_ADD,
591 ESC_SUN_MP_LU_REMOVE,
592
593 ESC_SUN_MP_PATH_CHANGE,
594 ESC_SUN_MP_PATH_ADD,
595 ESC_SUN_MP_PATH_REMOVE,
596
597 ESC_SUN_MP_INIT_PORT_CHANGE,
598
599 ESC_SUN_MP_TPG_CHANGE,
600 ESC_SUN_MP_TPG_ADD,
601 ESC_SUN_MP_TPG_REMOVE,
602
603 ESC_SUN_MP_TARGET_PORT_CHANGE,
604 ESC_SUN_MP_TARGET_PORT_ADD,
605 ESC_SUN_MP_TARGET_PORT_REMOVE,
606
607 ESC_SUN_MP_DEV_PROD_CHANGE,
608 ESC_SUN_MP_DEV_PROD_ADD,
609 ESC_SUN_MP_DEV_PROD_REMOVE
610
611 };
612
613 const char *init_port_subclass_list[] = {
614
615 ESC_DDI_INITIATOR_REGISTER,
616 ESC_DDI_INITIATOR_UNREGISTER
617 };
618
619
620
621 log(LOG_INFO, "init_sysevents()", "- enter");
622
623
624 g_SysEventHandle = sysevent_bind_handle(sysevent_handler);
625 if (g_SysEventHandle == NULL) {
626
627 log(LOG_INFO, "init_sysevents()",
628 "- sysevent_bind_handle() failed");
629
630 log(LOG_INFO, "init_sysevents()", "- error exit");
631
632 return (MP_STATUS_FAILED);
633 }
634
635 if (sysevent_subscribe_event(g_SysEventHandle, EC_SUN_MP,
636 subclass_list, sizeof (subclass_list) / sizeof (subclass_list[0]))
637 != 0) {
638
639
640 log(LOG_INFO, "init_sysevents()",
641 "- sysevent_subscribe_event() failed for subclass_list");
642
643 log(LOG_INFO, "init_sysevents()", "- error exit");
644
645 sysevent_unbind_handle(g_SysEventHandle);
646
647 return (MP_STATUS_FAILED);
648 }
649
650 if (sysevent_subscribe_event(g_SysEventHandle, EC_DDI,
651 init_port_subclass_list, sizeof (init_port_subclass_list) /
652 sizeof (init_port_subclass_list[0])) != 0) {
653
654
655 log(LOG_INFO, "init_sysevents()",
656 "- sysevent_subscribe_event() failed "
657 "for init_port_subclass_list");
658
659 log(LOG_INFO, "init_sysevents()", "- error exit");
660
661 sysevent_unbind_handle(g_SysEventHandle);
662
663 return (MP_STATUS_FAILED);
664 }
665
666
667 log(LOG_INFO, "init_sysevents()", "- exit");
668
669 return (MP_STATUS_SUCCESS);
670 }
671