1*9e86db79SHyon Kim /* 2*9e86db79SHyon Kim * CDDL HEADER START 3*9e86db79SHyon Kim * 4*9e86db79SHyon Kim * The contents of this file are subject to the terms of the 5*9e86db79SHyon Kim * Common Development and Distribution License (the "License"). 6*9e86db79SHyon Kim * You may not use this file except in compliance with the License. 7*9e86db79SHyon Kim * 8*9e86db79SHyon Kim * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*9e86db79SHyon Kim * or http://www.opensolaris.org/os/licensing. 10*9e86db79SHyon Kim * See the License for the specific language governing permissions 11*9e86db79SHyon Kim * and limitations under the License. 12*9e86db79SHyon Kim * 13*9e86db79SHyon Kim * When distributing Covered Code, include this CDDL HEADER in each 14*9e86db79SHyon Kim * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*9e86db79SHyon Kim * If applicable, add the following below this CDDL HEADER, with the 16*9e86db79SHyon Kim * fields enclosed by brackets "[]" replaced with your own identifying 17*9e86db79SHyon Kim * information: Portions Copyright [yyyy] [name of copyright owner] 18*9e86db79SHyon Kim * 19*9e86db79SHyon Kim * CDDL HEADER END 20*9e86db79SHyon Kim */ 21*9e86db79SHyon Kim /* 22*9e86db79SHyon Kim * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23*9e86db79SHyon Kim * Use is subject to license terms. 24*9e86db79SHyon Kim */ 25*9e86db79SHyon Kim 26*9e86db79SHyon Kim #include <sun_sas.h> 27*9e86db79SHyon Kim #include <libsysevent.h> 28*9e86db79SHyon Kim #include <sys/types.h> 29*9e86db79SHyon Kim #include <netinet/in.h> 30*9e86db79SHyon Kim #include <inttypes.h> 31*9e86db79SHyon Kim #include <ctype.h> 32*9e86db79SHyon Kim 33*9e86db79SHyon Kim 34*9e86db79SHyon Kim /* Remove these 5 when the header containing the event names aver available. */ 35*9e86db79SHyon Kim /* 36*9e86db79SHyon Kim * Event definitions 37*9e86db79SHyon Kim */ 38*9e86db79SHyon Kim /* Event Class */ 39*9e86db79SHyon Kim #define EC_HBA "EC_hba" 40*9e86db79SHyon Kim #define EC_DR "EC_dr" 41*9e86db79SHyon Kim /* Event Sub-Class */ 42*9e86db79SHyon Kim #define ESC_SAS_HBA_PORT_BROADCAST "ESC_sas_hba_port_broadcast" 43*9e86db79SHyon Kim #define ESC_SAS_PHY_EVENT "ESC_sas_phy_event" 44*9e86db79SHyon Kim #define ESC_DR_TARGET_STATE_CHANGE "ESC_dr_target_state_change" 45*9e86db79SHyon Kim 46*9e86db79SHyon Kim /* Broadcast Event Types */ 47*9e86db79SHyon Kim #define SAS_PORT_BROADCAST_CHANGE "port_broadcast_change" 48*9e86db79SHyon Kim #define SAS_PORT_BROADCAST_SES "port_broadcast_ses" 49*9e86db79SHyon Kim #define SAS_PORT_BROADCAST_D24_0 "port_broadcast_d24_0" 50*9e86db79SHyon Kim #define SAS_PORT_BROADCAST_D27_4 "port_broadcast_d27_4" 51*9e86db79SHyon Kim #define SAS_PORT_BROADCAST_D01_4 "port_broadcast_d01_4" 52*9e86db79SHyon Kim #define SAS_PORT_BROADCAST_D04_7 "port_broadcast_d04_7" 53*9e86db79SHyon Kim #define SAS_PORT_BROADCAST_D16_7 "port_broadcast_d16_7" 54*9e86db79SHyon Kim #define SAS_PORT_BROADCAST_D29_7 "port_broadcast_d29_7" 55*9e86db79SHyon Kim 56*9e86db79SHyon Kim /* Phy Event Types */ 57*9e86db79SHyon Kim #define SAS_PHY_ONLINE "port_online" 58*9e86db79SHyon Kim #define SAS_PHY_OFFLINE "port_offline" 59*9e86db79SHyon Kim #define SAS_PHY_REMOVE "port_remove" 60*9e86db79SHyon Kim 61*9e86db79SHyon Kim /* Event payload */ 62*9e86db79SHyon Kim #define SAS_DRV_INST "driver_instance" 63*9e86db79SHyon Kim #define SAS_PORT_ADDR "port_address" 64*9e86db79SHyon Kim #define SAS_DEVFS_PATH "devfs_path" 65*9e86db79SHyon Kim #define SAS_EVENT_TYPE "event_type" 66*9e86db79SHyon Kim 67*9e86db79SHyon Kim #define HBA_PORT_MATCH 1 68*9e86db79SHyon Kim #define TARGET_PORT_MATCH 2 69*9e86db79SHyon Kim #define PHY_MATCH 3 70*9e86db79SHyon Kim 71*9e86db79SHyon Kim #define REMOVED 1 72*9e86db79SHyon Kim #define ONLINE 2 73*9e86db79SHyon Kim #define OFFLINE 3 74*9e86db79SHyon Kim 75*9e86db79SHyon Kim sysevent_handle_t *gSysEventHandle = NULL; 76*9e86db79SHyon Kim 77*9e86db79SHyon Kim /* Calls the client callback function, if one is registered */ 78*9e86db79SHyon Kim static HBA_STATUS 79*9e86db79SHyon Kim updateMatchingPhy(HBA_WWN portAddr, uint8_t phyId, int update, uint8_t linkRate) 80*9e86db79SHyon Kim { 81*9e86db79SHyon Kim const char ROUTINE[] = "updateMatchingPhy"; 82*9e86db79SHyon Kim struct sun_sas_hba *hba_ptr; 83*9e86db79SHyon Kim struct sun_sas_port *hba_port_ptr; 84*9e86db79SHyon Kim struct phy_info *phy_ptr; 85*9e86db79SHyon Kim 86*9e86db79SHyon Kim log(LOG_DEBUG, ROUTINE, "- phy matching"); 87*9e86db79SHyon Kim /* grab write lock */ 88*9e86db79SHyon Kim lock(&all_hbas_lock); 89*9e86db79SHyon Kim /* loop through HBAs */ 90*9e86db79SHyon Kim for (hba_ptr = global_hba_head; hba_ptr != NULL; 91*9e86db79SHyon Kim hba_ptr = hba_ptr->next) { 92*9e86db79SHyon Kim /* loop through HBA ports */ 93*9e86db79SHyon Kim for (hba_port_ptr = hba_ptr->first_port; 94*9e86db79SHyon Kim hba_port_ptr != NULL; 95*9e86db79SHyon Kim hba_port_ptr = hba_port_ptr->next) { 96*9e86db79SHyon Kim if (wwnConversion(hba_port_ptr-> 97*9e86db79SHyon Kim port_attributes.PortSpecificAttribute. 98*9e86db79SHyon Kim SASPort->LocalSASAddress.wwn) == 99*9e86db79SHyon Kim wwnConversion(portAddr.wwn)) { 100*9e86db79SHyon Kim /* loop through phys */ 101*9e86db79SHyon Kim for (phy_ptr = hba_port_ptr->first_phy; 102*9e86db79SHyon Kim phy_ptr != NULL; phy_ptr = 103*9e86db79SHyon Kim phy_ptr->next) { 104*9e86db79SHyon Kim if (phy_ptr->phy.PhyIdentifier == 105*9e86db79SHyon Kim phyId) { 106*9e86db79SHyon Kim if (update == REMOVED) { 107*9e86db79SHyon Kim phy_ptr->invalid = 108*9e86db79SHyon Kim B_TRUE; 109*9e86db79SHyon Kim } else if (update == OFFLINE) { 110*9e86db79SHyon Kim phy_ptr->phy. 111*9e86db79SHyon Kim NegotiatedLinkRate 112*9e86db79SHyon Kim = 0; 113*9e86db79SHyon Kim } else { /* online */ 114*9e86db79SHyon Kim phy_ptr->phy. 115*9e86db79SHyon Kim NegotiatedLinkRate 116*9e86db79SHyon Kim = linkRate; 117*9e86db79SHyon Kim } 118*9e86db79SHyon Kim unlock(&all_hbas_lock); 119*9e86db79SHyon Kim return (HBA_STATUS_OK); 120*9e86db79SHyon Kim } 121*9e86db79SHyon Kim } /* for phys */ 122*9e86db79SHyon Kim } /* wwn mismatch. continue */ 123*9e86db79SHyon Kim } /* for HBA ports */ 124*9e86db79SHyon Kim } /* for HBAs */ 125*9e86db79SHyon Kim 126*9e86db79SHyon Kim unlock(&all_hbas_lock); 127*9e86db79SHyon Kim return (HBA_STATUS_ERROR); 128*9e86db79SHyon Kim } 129*9e86db79SHyon Kim 130*9e86db79SHyon Kim /* Event handler called by system */ 131*9e86db79SHyon Kim static void 132*9e86db79SHyon Kim syseventHandler(sysevent_t *ev) 133*9e86db79SHyon Kim { 134*9e86db79SHyon Kim 135*9e86db79SHyon Kim const char ROUTINE[] = "syseventHandler"; 136*9e86db79SHyon Kim nvlist_t *attrList = NULL; 137*9e86db79SHyon Kim char *eventStr, *portAddrStr, *charptr; 138*9e86db79SHyon Kim int update; 139*9e86db79SHyon Kim uint64_t addr; 140*9e86db79SHyon Kim uint8_t phyId, linkRate; 141*9e86db79SHyon Kim HBA_WWN portAddr; 142*9e86db79SHyon Kim 143*9e86db79SHyon Kim /* Is the event one of ours? */ 144*9e86db79SHyon Kim if (strncmp(EC_HBA, sysevent_get_class_name(ev), strlen(EC_HBA)) == 0) { 145*9e86db79SHyon Kim /* handle phy events */ 146*9e86db79SHyon Kim if (strncmp(ESC_SAS_PHY_EVENT, sysevent_get_subclass_name(ev), 147*9e86db79SHyon Kim strlen(ESC_SAS_PHY_EVENT)) == 0) { 148*9e86db79SHyon Kim if (sysevent_get_attr_list(ev, &attrList) != 0) { 149*9e86db79SHyon Kim log(LOG_DEBUG, ROUTINE, 150*9e86db79SHyon Kim "Failed to get event attributes on %s/%s", 151*9e86db79SHyon Kim EC_HBA, ESC_SAS_PHY_EVENT); 152*9e86db79SHyon Kim return; 153*9e86db79SHyon Kim } else { 154*9e86db79SHyon Kim if (nvlist_lookup_string(attrList, 155*9e86db79SHyon Kim "event_type", &eventStr) != 0) { 156*9e86db79SHyon Kim log(LOG_DEBUG, ROUTINE, 157*9e86db79SHyon Kim "Event type not found"); 158*9e86db79SHyon Kim return; 159*9e86db79SHyon Kim } else { 160*9e86db79SHyon Kim if (strncmp(eventStr, "phy_online", 161*9e86db79SHyon Kim sizeof (eventStr)) == 0) { 162*9e86db79SHyon Kim update = ONLINE; 163*9e86db79SHyon Kim if (nvlist_lookup_uint8( 164*9e86db79SHyon Kim attrList, "link_rate", 165*9e86db79SHyon Kim &linkRate) != 0) { 166*9e86db79SHyon Kim log(LOG_DEBUG, ROUTINE, 167*9e86db79SHyon Kim "Link Rate not \ 168*9e86db79SHyon Kim found"); 169*9e86db79SHyon Kim return; 170*9e86db79SHyon Kim } 171*9e86db79SHyon Kim } else if (strncmp(eventStr, 172*9e86db79SHyon Kim "phy_offline", 173*9e86db79SHyon Kim sizeof (eventStr)) == 0) { 174*9e86db79SHyon Kim update = OFFLINE; 175*9e86db79SHyon Kim } else if (strncmp(eventStr, 176*9e86db79SHyon Kim "phy_remove", 177*9e86db79SHyon Kim sizeof (eventStr)) == 0) { 178*9e86db79SHyon Kim update = REMOVED; 179*9e86db79SHyon Kim } else { 180*9e86db79SHyon Kim log(LOG_DEBUG, ROUTINE, 181*9e86db79SHyon Kim "Invalid event type"); 182*9e86db79SHyon Kim return; 183*9e86db79SHyon Kim } 184*9e86db79SHyon Kim } 185*9e86db79SHyon Kim if (nvlist_lookup_string(attrList, 186*9e86db79SHyon Kim "port_address", &portAddrStr) != 0) { 187*9e86db79SHyon Kim log(LOG_DEBUG, ROUTINE, 188*9e86db79SHyon Kim "Port SAS address not found"); 189*9e86db79SHyon Kim return; 190*9e86db79SHyon Kim } else { 191*9e86db79SHyon Kim for (charptr = portAddrStr; 192*9e86db79SHyon Kim charptr != NULL; charptr++) { 193*9e86db79SHyon Kim if (isxdigit(*charptr)) { 194*9e86db79SHyon Kim break; 195*9e86db79SHyon Kim } 196*9e86db79SHyon Kim } 197*9e86db79SHyon Kim addr = htonll(strtoll(charptr, 198*9e86db79SHyon Kim NULL, 16)); 199*9e86db79SHyon Kim (void) memcpy(portAddr.wwn, &addr, 8); 200*9e86db79SHyon Kim } 201*9e86db79SHyon Kim if (nvlist_lookup_uint8(attrList, 202*9e86db79SHyon Kim "PhyIdentifier", &phyId) != 0) { 203*9e86db79SHyon Kim log(LOG_DEBUG, ROUTINE, 204*9e86db79SHyon Kim "Port SAS address not found"); 205*9e86db79SHyon Kim return; 206*9e86db79SHyon Kim } 207*9e86db79SHyon Kim } 208*9e86db79SHyon Kim if (updateMatchingPhy(portAddr, phyId, update, 209*9e86db79SHyon Kim linkRate) != HBA_STATUS_OK) { 210*9e86db79SHyon Kim log(LOG_DEBUG, ROUTINE, 211*9e86db79SHyon Kim "updating phy for the events failed."); 212*9e86db79SHyon Kim } 213*9e86db79SHyon Kim } 214*9e86db79SHyon Kim } else if (strncmp(EC_DR, sysevent_get_class_name(ev), 2) == 0) { 215*9e86db79SHyon Kim /* handle DR events */ 216*9e86db79SHyon Kim log(LOG_DEBUG, ROUTINE, 217*9e86db79SHyon Kim "handle EC_dr events."); 218*9e86db79SHyon Kim } else { 219*9e86db79SHyon Kim log(LOG_DEBUG, ROUTINE, 220*9e86db79SHyon Kim "Found Unregistered event. - exit"); 221*9e86db79SHyon Kim return; 222*9e86db79SHyon Kim } 223*9e86db79SHyon Kim 224*9e86db79SHyon Kim log(LOG_DEBUG, ROUTINE, "- exit"); 225*9e86db79SHyon Kim } 226*9e86db79SHyon Kim 227*9e86db79SHyon Kim /* Registers events to the sysevent framework */ 228*9e86db79SHyon Kim HBA_STATUS 229*9e86db79SHyon Kim registerSysevent() { 230*9e86db79SHyon Kim 231*9e86db79SHyon Kim const char ROUTINE[] = "registerSysevent"; 232*9e86db79SHyon Kim const char *hba_subclass_list[] = { 233*9e86db79SHyon Kim ESC_SAS_PHY_EVENT 234*9e86db79SHyon Kim }; 235*9e86db79SHyon Kim const char *dr_subclass_list[] = { 236*9e86db79SHyon Kim ESC_DR_TARGET_STATE_CHANGE 237*9e86db79SHyon Kim }; 238*9e86db79SHyon Kim 239*9e86db79SHyon Kim gSysEventHandle = sysevent_bind_handle(syseventHandler); 240*9e86db79SHyon Kim if (gSysEventHandle == NULL) { 241*9e86db79SHyon Kim log(LOG_DEBUG, ROUTINE, 242*9e86db79SHyon Kim "- sysevent_bind_handle() failed"); 243*9e86db79SHyon Kim log(LOG_DEBUG, ROUTINE, "- error exit"); 244*9e86db79SHyon Kim return (HBA_STATUS_ERROR); 245*9e86db79SHyon Kim } 246*9e86db79SHyon Kim 247*9e86db79SHyon Kim if (sysevent_subscribe_event(gSysEventHandle, EC_HBA, 248*9e86db79SHyon Kim hba_subclass_list, 1) != 0) { 249*9e86db79SHyon Kim log(LOG_DEBUG, ROUTINE, 250*9e86db79SHyon Kim "- sysevent_subscribe_event() failed for EC_HBA subclass"); 251*9e86db79SHyon Kim log(LOG_DEBUG, ROUTINE, "- error exit"); 252*9e86db79SHyon Kim sysevent_unbind_handle(gSysEventHandle); 253*9e86db79SHyon Kim return (HBA_STATUS_ERROR); 254*9e86db79SHyon Kim } 255*9e86db79SHyon Kim 256*9e86db79SHyon Kim if (sysevent_subscribe_event(gSysEventHandle, EC_DR, 257*9e86db79SHyon Kim dr_subclass_list, 1) != 0) { 258*9e86db79SHyon Kim log(LOG_DEBUG, ROUTINE, 259*9e86db79SHyon Kim "- sysevent_subscribe_event() failed for DR subclass"); 260*9e86db79SHyon Kim log(LOG_DEBUG, ROUTINE, "- error exit"); 261*9e86db79SHyon Kim sysevent_unbind_handle(gSysEventHandle); 262*9e86db79SHyon Kim return (HBA_STATUS_ERROR); 263*9e86db79SHyon Kim } 264*9e86db79SHyon Kim 265*9e86db79SHyon Kim log(LOG_DEBUG, ROUTINE, "- exit"); 266*9e86db79SHyon Kim 267*9e86db79SHyon Kim return (HBA_STATUS_ERROR); 268*9e86db79SHyon Kim } 269