xref: /illumos-gate/usr/src/lib/mpapi/libmpscsi_vhci/common/mp_utils.c (revision c9eab9d4e096bb9b983e9b007577edfa73c32eff)
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 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
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
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 		default:
138 			log(LOG_INFO, "getStatus4ErrorCode()",
139 				" - received (unsupported) mp_errno=%d from"
140 				" driver call.", driverError);
141 			log(LOG_INFO, "getStatus4ErrorCode()",
142 				" - returning MP_STATUS_FAILED to caller.");
143 			mpStatus = MP_STATUS_FAILED;
144 	}
145 
146 	log(LOG_INFO, "getStatus4ErrorCode()", "- exit");
147 
148 	return (mpStatus);
149 }
150 
151 
152 
153 MP_OID_LIST
154 *createOidList(int size) {
155 
156 	MP_OID_LIST *pOidList = NULL;
157 
158 
159 	log(LOG_INFO, "createOidList()", "- enter");
160 
161 
162 	if (size < 1) {
163 
164 		log(LOG_INFO, "createOidList()",
165 			"requested size is less than 1");
166 		log(LOG_INFO, "createOidList()",
167 			" - error exit");
168 		return (NULL);
169 
170 	} else {
171 
172 		pOidList = (MP_OID_LIST*)calloc(1,
173 			sizeof (MP_OID_LIST) +
174 			((size - 1) *
175 		    sizeof (MP_OID)));
176 
177 		if (NULL == pOidList) {
178 			log(LOG_INFO, "createOidList()",
179 				"no memory for pOidList");
180 			log(LOG_INFO, "createOidList()",
181 				" - error exit");
182 			return (NULL);
183 		}
184 
185 		log(LOG_INFO,
186 		    "createOidList()",
187 			"- exit(%d)",
188 			size);
189 
190 		return (pOidList);
191 	}
192 }
193 
194 /* Calls the client callback function, if one is registered */
195 static void
196 notifyClient(sysevent_t *ev)
197 {
198 	nvlist_t *attr_list = NULL;
199 
200 	uint64_t *val = NULL;
201 	int32_t  *instance = NULL;
202 	int32_t  *major = NULL;
203 
204 	int valAllocated = 0;
205 
206 	uint_t nelem = 0;
207 
208 	int i = 0;
209 	int eventType = 0;
210 	int index = -1;
211 
212 	void *pCallerData = NULL;
213 
214 	char subClassName[256];
215 
216 	MP_BOOL becomingVisible = MP_FALSE;
217 
218 	MP_OID_LIST *oidList = NULL;
219 
220 
221 	log(LOG_INFO, "notifyClient()", "- enter");
222 
223 
224 	(void) strncpy(subClassName, sysevent_get_subclass_name(ev), 256);
225 
226 	if (strstr(subClassName, "change")) {
227 
228 		eventType = PROP_CHANGE;
229 
230 		log(LOG_INFO, "notifyClient()", "- got a change event");
231 		log(LOG_INFO, "notifyClient()", ": [%s]",
232 		    subClassName);
233 
234 		if (strncmp(subClassName, ESC_SUN_MP_LU_CHANGE, 255) == 0) {
235 
236 			index = MP_OBJECT_TYPE_MULTIPATH_LU;
237 
238 		} else if (strncmp(subClassName, ESC_SUN_MP_PATH_CHANGE, 255)
239 		    == 0) {
240 
241 			index = MP_OBJECT_TYPE_PATH_LU;
242 
243 		} else if (strncmp(subClassName, ESC_SUN_MP_INIT_PORT_CHANGE,
244 					255) == 0) {
245 
246 			index = MP_OBJECT_TYPE_INITIATOR_PORT;
247 
248 		} else if (strncmp(subClassName, ESC_SUN_MP_TPG_CHANGE, 255)
249 		    == 0) {
250 
251 			index = MP_OBJECT_TYPE_TARGET_PORT_GROUP;
252 
253 		} else if (strncmp(subClassName, ESC_SUN_MP_TARGET_PORT_CHANGE,
254 					255) == 0) {
255 
256 			index = MP_OBJECT_TYPE_TARGET_PORT;
257 
258 		} else if (strncmp(subClassName, ESC_SUN_MP_DEV_PROD_CHANGE,
259 					255) == 0) {
260 
261 			index = MP_OBJECT_TYPE_DEVICE_PRODUCT;
262 		}
263 
264 	} else if ((strstr(subClassName, "add")) ||
265 			(strstr(subClassName, "initiator_register"))) {
266 
267 		eventType = VISA_CHANGE;
268 		becomingVisible = MP_TRUE;
269 
270 		log(LOG_INFO, "notifyClient()", "- got a visibility"
271 		    " add event");
272 		log(LOG_INFO, "notifyClient()", ": [%s]",
273 		    subClassName);
274 
275 		if (strncmp(subClassName, ESC_DEVFS_DEVI_ADD, 255) == 0) {
276 
277 			index = MP_OBJECT_TYPE_MULTIPATH_LU;
278 
279 		} else if (strncmp(subClassName, ESC_SUN_MP_PATH_ADD, 255)
280 		    == 0) {
281 
282 			index = MP_OBJECT_TYPE_PATH_LU;
283 
284 		} else if (strncmp(subClassName, ESC_DDI_INITIATOR_REGISTER,
285 					244) == 0) {
286 
287 			index = MP_OBJECT_TYPE_INITIATOR_PORT;
288 
289 		} else if (strncmp(subClassName, ESC_SUN_MP_TPG_ADD,
290 					255) == 0) {
291 
292 			index = MP_OBJECT_TYPE_TARGET_PORT_GROUP;
293 
294 		} else if (strncmp(subClassName, ESC_SUN_MP_TARGET_PORT_ADD,
295 					255) == 0) {
296 
297 			index = MP_OBJECT_TYPE_TARGET_PORT;
298 
299 		} else if (strncmp(subClassName, ESC_SUN_MP_DEV_PROD_ADD, 255)
300 		    == 0) {
301 
302 			index = MP_OBJECT_TYPE_DEVICE_PRODUCT;
303 		}
304 
305 
306 	} else if ((strstr(subClassName, "remove")) ||
307 			(strstr(subClassName, "initiator_unregister"))) {
308 
309 		eventType = VISA_CHANGE;
310 		becomingVisible = MP_FALSE;
311 
312 		log(LOG_INFO, "notifyClient()", "- got a visibility"
313 		    " remove event");
314 		log(LOG_INFO, "notifyClient()", ": [%s]",
315 		    subClassName);
316 
317 		if (strncmp(subClassName, ESC_DEVFS_DEVI_REMOVE, 255) == 0) {
318 
319 			index = MP_OBJECT_TYPE_MULTIPATH_LU;
320 
321 		} else if (strncmp(subClassName, ESC_SUN_MP_PATH_REMOVE, 255)
322 		    == 0) {
323 
324 			index = MP_OBJECT_TYPE_PATH_LU;
325 
326 		} else if (strncmp(subClassName, ESC_DDI_INITIATOR_UNREGISTER,
327 					255) == 0) {
328 
329 			index = MP_OBJECT_TYPE_INITIATOR_PORT;
330 
331 		} else if (strncmp(subClassName, ESC_SUN_MP_TPG_REMOVE, 255)
332 		    == 0) {
333 
334 			index = MP_OBJECT_TYPE_TARGET_PORT_GROUP;
335 
336 		} else if (strncmp(subClassName, ESC_SUN_MP_TARGET_PORT_REMOVE,
337 					255) == 0) {
338 
339 			index = MP_OBJECT_TYPE_TARGET_PORT;
340 
341 		} else if (strncmp(subClassName, ESC_SUN_MP_DEV_PROD_REMOVE,
342 					255) == 0) {
343 
344 			index = MP_OBJECT_TYPE_DEVICE_PRODUCT;
345 		}
346 
347 
348 	} else {
349 		log(LOG_INFO, "notifyClient()", "- got an unsupported event");
350 		return;
351 	}
352 
353 	if (index < 0) {
354 
355 		log(LOG_INFO, "notifyClient()", "- index is less than zero");
356 		return;
357 	}
358 
359 	if (eventType == VISA_CHANGE) {
360 
361 		(void) pthread_mutex_lock(&g_visa_mutex);
362 
363 		if (NULL == g_Visibility_Callback_List[index].pClientFn) {
364 
365 			log(LOG_INFO, "notifyClient()",
366 			    "- no visibility change callback to notify");
367 
368 			(void) pthread_mutex_unlock(&g_visa_mutex);
369 
370 			return;
371 		}
372 
373 		(void) pthread_mutex_unlock(&g_visa_mutex);
374 	}
375 
376 	if (eventType == PROP_CHANGE) {
377 
378 		(void) pthread_mutex_lock(&g_prop_mutex);
379 
380 		if (NULL == g_Property_Callback_List[index].pClientFn) {
381 
382 			log(LOG_INFO, "notifyClient()",
383 			    "- no property change callback to notify");
384 
385 			    (void) pthread_mutex_unlock(&g_prop_mutex);
386 
387 			    return;
388 		    }
389 
390 		    (void) pthread_mutex_unlock(&g_prop_mutex);
391 	}
392 
393 	(void) sysevent_get_attr_list(ev, &attr_list);
394 	if (NULL != attr_list) {
395 
396 		if ((VISA_CHANGE == eventType) &&
397 		    (MP_OBJECT_TYPE_MULTIPATH_LU == index)) {
398 
399 			(void) nvlist_lookup_int32_array(attr_list,
400 			    DEVFS_INSTANCE, &instance, &nelem);
401 
402 			log(LOG_INFO, "notifyClient()",
403 			    "- event has [%d] elements",
404 			    nelem);
405 
406 			if (NULL != instance) {
407 
408 				val = (uint64_t *)malloc(sizeof (uint64_t));
409 
410 				valAllocated = 1;
411 
412 				*val = *instance;
413 				nelem = 1;
414 
415 			} else {
416 
417 				nelem = 0;
418 			}
419 
420 		} else if ((VISA_CHANGE == eventType) &&
421 			(MP_OBJECT_TYPE_INITIATOR_PORT == index)) {
422 
423 			(void) nvlist_lookup_int32_array(attr_list,
424 			    DDI_INSTANCE, &instance, &nelem);
425 
426 			log(LOG_INFO, "notifyClient()",
427 			    "- event (PHCI_INSTANCE) has [%d] elements",
428 			    nelem);
429 
430 			(void) nvlist_lookup_int32_array(attr_list,
431 			    DDI_DRIVER_MAJOR, &major, &nelem);
432 
433 			log(LOG_INFO, "notifyClient()",
434 			    "- event (PHCI_DRIVER_MAJOR) has [%d] elements",
435 			    nelem);
436 
437 			if ((NULL != instance) & (NULL != major)) {
438 
439 				val = (uint64_t *)malloc(sizeof (uint64_t));
440 
441 				valAllocated = 1;
442 
443 				*val = MP_STORE_INST_TO_ID(*instance, *val);
444 				*val = MP_STORE_MAJOR_TO_ID(*major, *val);
445 
446 				nelem = 1;
447 
448 			} else {
449 
450 				nelem = 0;
451 			}
452 
453 		} else {
454 
455 			(void) nvlist_lookup_uint64_array(attr_list, OIDLIST,
456 					    &val, &nelem);
457 
458 			log(LOG_INFO, "notifyClient()",
459 			    "- event has [%d] elements",
460 			    nelem);
461 		}
462 
463 		if (nelem > 0) {
464 
465 			for (i = 0; i < nelem; i++) {
466 
467 				log(LOG_INFO, "notifyClient()",
468 				    "- event [%d] = %llx",
469 				    i, val[i]);
470 			}
471 
472 			oidList = createOidList(nelem);
473 			if (NULL == oidList) {
474 
475 				log(LOG_INFO, "notifyClient()",
476 				    "- unable to create MP_OID_LIST");
477 
478 				log(LOG_INFO, "notifyClient()",
479 				    "- error exit");
480 
481 				nvlist_free(attr_list);
482 
483 				return;
484 			}
485 
486 			oidList->oidCount = nelem;
487 
488 			for (i = 0; i < nelem; i++) {
489 
490 				oidList->oids[i].objectType = index;
491 				oidList->oids[i].ownerId = g_pluginOwnerID;
492 				oidList->oids[i].objectSequenceNumber = val[i];
493 			}
494 
495 			if (valAllocated) {
496 
497 				free(val);
498 			}
499 
500 			for (i = 0; i < oidList->oidCount; i++) {
501 
502 				log(LOG_INFO, "notifyClient()",
503 					"oidList->oids[%d].objectType"
504 					"           = %d",
505 					i, oidList->oids[i].objectType);
506 				log(LOG_INFO, "notifyClient()",
507 					"oidList->oids[%d].ownerId"
508 					"              = %d",
509 					i, oidList->oids[i].ownerId);
510 				log(LOG_INFO, "notifyClient()",
511 					"oidList->oids[%d].objectSequenceNumber"
512 					" = %llx",
513 					i,
514 					oidList->oids[i].objectSequenceNumber);
515 			}
516 
517 			if (eventType == PROP_CHANGE) {
518 
519 				(void) pthread_mutex_lock(&g_prop_mutex);
520 
521 				pCallerData = g_Property_Callback_List[index].
522 					pCallerData;
523 
524 				(g_Property_Callback_List[index].pClientFn)
525 				(oidList, pCallerData);
526 
527 				(void) pthread_mutex_unlock(&g_prop_mutex);
528 
529 			} else if (eventType == VISA_CHANGE) {
530 
531 				(void) pthread_mutex_lock(&g_visa_mutex);
532 
533 				pCallerData = g_Visibility_Callback_List[index].
534 					pCallerData;
535 
536 				(g_Visibility_Callback_List[index].pClientFn)
537 				(becomingVisible, oidList, pCallerData);
538 
539 				(void) pthread_mutex_unlock(&g_visa_mutex);
540 
541 			}
542 		}
543 
544 		nvlist_free(attr_list);
545 	}
546 
547 
548 	log(LOG_INFO, "notifyClient()", "- exit");
549 }
550 
551 /* Event handler called by system */
552 static void
553 sysevent_handler(sysevent_t *ev)
554 {
555 	log(LOG_INFO, "sysevent_handler()", "- enter");
556 
557 	/* Is the event one of ours? */
558 	if ((strncmp(EC_SUN_MP, sysevent_get_class_name(ev), 9) != 0) &&
559 	    (strncmp(EC_DEVFS,  sysevent_get_class_name(ev), 8) != 0) &&
560 	    (strncmp(EC_DDI,    sysevent_get_class_name(ev), 6) != 0)) {
561 
562 		return;
563 	}
564 
565 	/* Notify client if it cares */
566 	notifyClient(ev);
567 
568 
569 	log(LOG_INFO, "sysevent_handler()", "- exit");
570 }
571 
572 /* Registers the plugin to the sysevent framework */
573 MP_STATUS init_sysevents() {
574 
575 	const char *subclass_list[] = {
576 
577 		ESC_SUN_MP_LU_CHANGE,
578 
579 		ESC_SUN_MP_PATH_CHANGE,
580 		ESC_SUN_MP_PATH_ADD,
581 		ESC_SUN_MP_PATH_REMOVE,
582 
583 		ESC_SUN_MP_INIT_PORT_CHANGE,
584 
585 		ESC_SUN_MP_TPG_CHANGE,
586 		ESC_SUN_MP_TPG_ADD,
587 		ESC_SUN_MP_TPG_REMOVE,
588 
589 		ESC_SUN_MP_TARGET_PORT_CHANGE,
590 		ESC_SUN_MP_TARGET_PORT_ADD,
591 		ESC_SUN_MP_TARGET_PORT_REMOVE,
592 
593 		ESC_SUN_MP_DEV_PROD_CHANGE,
594 		ESC_SUN_MP_DEV_PROD_ADD,
595 		ESC_SUN_MP_DEV_PROD_REMOVE
596 
597 	};
598 
599 	const char *lu_subclass_list[] = {
600 
601 		ESC_DEVFS_DEVI_ADD,
602 		ESC_DEVFS_DEVI_REMOVE
603 
604 	};
605 
606 	const char *init_port_subclass_list[] = {
607 
608 		ESC_DDI_INITIATOR_REGISTER,
609 		ESC_DDI_INITIATOR_UNREGISTER
610 	};
611 
612 
613 
614 	log(LOG_INFO, "init_sysevents()", "- enter");
615 
616 
617 	g_SysEventHandle = sysevent_bind_handle(sysevent_handler);
618 	if (g_SysEventHandle == NULL) {
619 
620 		log(LOG_INFO, "init_sysevents()",
621 		    "- sysevent_bind_handle() failed");
622 
623 		log(LOG_INFO, "init_sysevents()", "- error exit");
624 
625 		return (MP_STATUS_FAILED);
626 	}
627 
628 	if (sysevent_subscribe_event(g_SysEventHandle, EC_SUN_MP,
629 					subclass_list, 14) != 0) {
630 
631 
632 		log(LOG_INFO, "init_sysevents()",
633 		    "- sysevent_subscribe_event() failed for subclass_list");
634 
635 		log(LOG_INFO, "init_sysevents()", "- error exit");
636 
637 		sysevent_unbind_handle(g_SysEventHandle);
638 
639 		return (MP_STATUS_FAILED);
640 	}
641 
642 	if (sysevent_subscribe_event(g_SysEventHandle, EC_DEVFS,
643 					lu_subclass_list, 2) != 0) {
644 
645 
646 		log(LOG_INFO, "init_sysevents()",
647 		    "- sysevent_subscribe_event() failed for lu_subclass_list");
648 
649 		log(LOG_INFO, "init_sysevents()", "- error exit");
650 
651 		sysevent_unbind_handle(g_SysEventHandle);
652 
653 		return (MP_STATUS_FAILED);
654 	}
655 
656 	if (sysevent_subscribe_event(g_SysEventHandle, EC_DDI,
657 					init_port_subclass_list, 2) != 0) {
658 
659 
660 		log(LOG_INFO, "init_sysevents()",
661 		    "- sysevent_subscribe_event() failed "
662 		    "for init_port_subclass_list");
663 
664 		log(LOG_INFO, "init_sysevents()", "- error exit");
665 
666 		sysevent_unbind_handle(g_SysEventHandle);
667 
668 		return (MP_STATUS_FAILED);
669 	}
670 
671 
672 	log(LOG_INFO, "init_sysevents()", "- exit");
673 
674 	return (MP_STATUS_SUCCESS);
675 }
676