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