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 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 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 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 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 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