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 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 /* 27 * Copyright 2019 Joyent, Inc. 28 */ 29 30 #include <sun_sas.h> 31 32 /* 33 * Retrieves the attributes for a specific discovered port by WWN 34 */ 35 HBA_STATUS 36 Sun_sasGetPortAttributesByWWN(HBA_HANDLE handle, HBA_WWN portWWN, 37 HBA_WWN domainPortWWN, PSMHBA_PORTATTRIBUTES attributes) 38 { 39 const char ROUTINE[] = "Sun_sasGetPortAttributesByWWN"; 40 HBA_STATUS status; 41 struct sun_sas_hba *hba_ptr; 42 struct sun_sas_port *hba_port_ptr, *hba_disco_port; 43 int index, chkDomainPort = 0, domainFound = 0; 44 45 /* Validate the arguments */ 46 if (attributes == NULL) { 47 log(LOG_DEBUG, ROUTINE, "NULL port attributes"); 48 return (HBA_STATUS_ERROR_ARG); 49 } 50 51 if (wwnConversion(domainPortWWN.wwn) != 0) { 52 chkDomainPort = 1; 53 } 54 55 lock(&all_hbas_lock); 56 index = RetrieveIndex(handle); 57 lock(&open_handles_lock); 58 hba_ptr = RetrieveHandle(index); 59 if (hba_ptr == NULL) { 60 log(LOG_DEBUG, ROUTINE, "Invalid handle %08lx.", handle); 61 unlock(&open_handles_lock); 62 unlock(&all_hbas_lock); 63 return (HBA_STATUS_ERROR_INVALID_HANDLE); 64 } 65 66 /* Check for stale data */ 67 status = verifyAdapter(hba_ptr); 68 if (status != HBA_STATUS_OK) { 69 log(LOG_DEBUG, ROUTINE, "Verify adapter failed"); 70 unlock(&open_handles_lock); 71 unlock(&all_hbas_lock); 72 return (status); 73 } 74 75 if (hba_ptr->first_port == NULL) { 76 /* This is probably an internal failure of the library */ 77 if (hba_ptr->device_path[0] != '\0') { 78 log(LOG_DEBUG, ROUTINE, 79 "Internal failure: Adapter %s contains " 80 "no port data", hba_ptr->device_path); 81 } else { 82 log(LOG_DEBUG, ROUTINE, 83 "Internal failure: Adapter at index %d contains " 84 "no port data", hba_ptr->index); 85 } 86 unlock(&open_handles_lock); 87 unlock(&all_hbas_lock); 88 return (HBA_STATUS_ERROR); 89 } 90 91 /* Loop over all Adapter ports */ 92 for (hba_port_ptr = hba_ptr->first_port; 93 hba_port_ptr != NULL; 94 hba_port_ptr = hba_port_ptr->next) { 95 if (chkDomainPort) { 96 if (validateDomainAddress(hba_port_ptr, 97 domainPortWWN) != HBA_STATUS_OK) { 98 continue; 99 } else 100 domainFound = 1; 101 } 102 103 if (wwnConversion(hba_port_ptr->port_attributes. 104 PortSpecificAttribute.SASPort->LocalSASAddress.wwn) == 105 wwnConversion(portWWN.wwn)) { 106 /* 107 * We should indicate an error if we enter here 108 * without domainPortWWN set. 109 */ 110 if (chkDomainPort == 0) { 111 log(LOG_DEBUG, ROUTINE, 112 "Domain Port WWN should be set when " 113 "querying HBA port %016llx for " 114 "handle %08lx", 115 wwnConversion(portWWN.wwn), handle); 116 unlock(&open_handles_lock); 117 unlock(&all_hbas_lock); 118 return (HBA_STATUS_ERROR_ARG); 119 } 120 attributes->PortType = 121 hba_port_ptr->port_attributes.PortType; 122 attributes->PortState = 123 hba_port_ptr->port_attributes.PortState; 124 (void) strlcpy(attributes->OSDeviceName, 125 hba_port_ptr->port_attributes.OSDeviceName, 126 sizeof (attributes->OSDeviceName)); 127 (void) memcpy(attributes->PortSpecificAttribute.SASPort, 128 hba_port_ptr->port_attributes.PortSpecificAttribute. 129 SASPort, sizeof (struct SMHBA_SAS_Port)); 130 131 unlock(&open_handles_lock); 132 unlock(&all_hbas_lock); 133 return (HBA_STATUS_OK); 134 } 135 136 /* check to make sure there are devices attached to this port */ 137 if (hba_port_ptr->first_attached_port != NULL) { 138 139 /* Loop over all discovered ports */ 140 for (hba_disco_port = hba_port_ptr->first_attached_port; 141 hba_disco_port != NULL; 142 hba_disco_port = hba_disco_port->next) { 143 if (wwnConversion(hba_disco_port-> 144 port_attributes.PortSpecificAttribute. 145 SASPort->LocalSASAddress.wwn) == 146 wwnConversion(portWWN.wwn)) { 147 attributes->PortType = 148 hba_disco_port->port_attributes. 149 PortType; 150 attributes->PortState = 151 hba_disco_port->port_attributes. 152 PortState; 153 (void) strlcpy(attributes->OSDeviceName, 154 hba_disco_port->port_attributes. 155 OSDeviceName, 156 sizeof (attributes->OSDeviceName)); 157 (void) memcpy(attributes-> 158 PortSpecificAttribute.SASPort, 159 hba_disco_port->port_attributes. 160 PortSpecificAttribute.SASPort, 161 sizeof (struct SMHBA_SAS_Port)); 162 unlock(&open_handles_lock); 163 unlock(&all_hbas_lock); 164 return (HBA_STATUS_OK); 165 } 166 } 167 } 168 if (chkDomainPort) { 169 log(LOG_DEBUG, ROUTINE, 170 "Invalid Port WWN %016llx for handle %08lx", 171 wwnConversion(portWWN.wwn), handle); 172 unlock(&open_handles_lock); 173 unlock(&all_hbas_lock); 174 return (HBA_STATUS_ERROR_ILLEGAL_WWN); 175 } 176 } 177 if (chkDomainPort && domainFound == 0) { 178 log(LOG_DEBUG, ROUTINE, "No Matching domain port" 179 " (%16llx) for port (%16llx) for handle %08lx", 180 wwnConversion(domainPortWWN.wwn), 181 wwnConversion(portWWN.wwn), 182 handle); 183 } else { 184 /* We enter here only when chkDomainPort == 0 */ 185 log(LOG_DEBUG, ROUTINE, 186 "Invalid Port WWN %016llx for handle %08lx", 187 wwnConversion(portWWN.wwn), handle); 188 } 189 unlock(&open_handles_lock); 190 unlock(&all_hbas_lock); 191 return (HBA_STATUS_ERROR_ILLEGAL_WWN); 192 } 193