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