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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 27 #include <unistd.h> 28 29 #include <FCHBA.h> 30 #include <Exceptions.h> 31 #include <Trace.h> 32 #include <iostream> 33 #include <iomanip> 34 #include <cerrno> 35 #include <cstring> 36 #include <sys/types.h> 37 #include <sys/stat.h> 38 #include <fcntl.h> 39 #include <unistd.h> 40 #include <stropts.h> 41 #include <sys/fibre-channel/fcio.h> 42 #include <sys/fibre-channel/ulp/fcsm.h> 43 #include <FCHBAPort.h> 44 #include <HBAList.h> 45 46 using namespace std; 47 const string FCHBA::FCSM_DRIVER_PATH = "/devices/pseudo/fcsm@0:fcsm"; 48 const string FCHBA::FCSM_DRIVER_PKG = "SUNWfcsm"; 49 const int FCHBA::MAX_FCIO_MSG_LEN = 256; 50 51 FCHBA::FCHBA(string path) : HBA() { 52 Trace log("FCHBA::FCHBA"); 53 log.debug("Constructing new HBA (%s)", path.c_str()); 54 55 // Add first port 56 addPort(new FCHBAPort(path)); 57 58 name = "INTERNAL-FAILURE"; // Just in case things go wrong 59 try { 60 HBA_ADAPTERATTRIBUTES attrs = getHBAAttributes(); 61 name = attrs.Manufacturer; 62 name += "-"; 63 name += attrs.Model; 64 65 // Grab any other ports on this adapter 66 for (int i = 1; i < attrs.NumberOfPorts; i++) { 67 fcio_t fcio; 68 int fd; 69 char nextPath[MAXPATHLEN]; 70 71 log.debug("Fetching other port %d", i); 72 73 // construct fcio struct 74 memset(&fcio, 0, sizeof (fcio_t)); 75 memset(nextPath, 0, sizeof (nextPath)); 76 fcio.fcio_cmd = FCIO_GET_OTHER_ADAPTER_PORTS; 77 fcio.fcio_xfer = FCIO_XFER_RW; 78 79 fcio.fcio_olen = MAXPATHLEN; 80 fcio.fcio_obuf = (char *)nextPath; 81 fcio.fcio_ilen = sizeof (i); 82 fcio.fcio_ibuf = (char *)&i; 83 84 // open the fcsm node so we can send the ioctl to 85 errno = 0; 86 HBAPort *port = getPortByIndex(0); 87 if ((fd = open(port->getPath().c_str(), O_NDELAY | O_RDONLY)) == 88 -1) { 89 log.debug("Unable to open %d opened (%s)", i, 90 port->getPath().c_str()); 91 if (errno == EBUSY) { 92 throw BusyException(); 93 } else if (errno == EAGAIN) { 94 throw TryAgainException(); 95 } else if (errno == ENOTSUP) { 96 throw NotSupportedException(); 97 } else if (errno == ENOENT) { 98 throw UnavailableException(); 99 } else { 100 throw IOError("Unable to open FCSM driver"); 101 } 102 } 103 log.debug("Other port %d opened", i); 104 105 errno = 0; 106 if (ioctl(fd, FCIO_CMD, &fcio) != 0) { 107 // Interpret the fcio error code 108 char fcioErrorString[MAX_FCIO_MSG_LEN] = ""; 109 110 log.genericIOError( 111 "ADAPTER_LIST failed: " 112 "Errno: \"%s\"", 113 strerror(errno)); 114 close(fd); 115 if (errno == EBUSY) { 116 throw BusyException(); 117 } else if (errno == EAGAIN) { 118 throw TryAgainException(); 119 } else if (errno == ENOTSUP) { 120 throw NotSupportedException(); 121 } else if (errno == ENOENT) { 122 throw UnavailableException(); 123 } else { 124 throw IOError("Unable to build HBA list"); 125 } 126 } 127 close(fd); 128 log.debug("About to add port %d (%s)", i, nextPath); 129 addPort(new FCHBAPort(nextPath)); 130 } 131 } catch (HBAException &e) { 132 log.internalError( 133 "Unable to construct HBA."); 134 throw e; 135 } 136 } 137 138 std::string FCHBA::getName() { 139 Trace log("FCHBA::getName"); 140 return (name); 141 } 142 143 HBA_ADAPTERATTRIBUTES FCHBA::getHBAAttributes() { 144 Trace log("FCHBA::getHBAAttributes"); 145 int fd; 146 147 errno = 0; 148 HBAPort *port = getPortByIndex(0); 149 if ((fd = open(port->getPath().c_str(), O_NDELAY | O_RDONLY)) == -1) { 150 // Why did we fail? 151 if (errno == EBUSY) { 152 throw BusyException(); 153 } else if (errno == EAGAIN) { 154 throw TryAgainException(); 155 } else if (errno == ENOTSUP) { 156 throw NotSupportedException(); 157 } else { 158 throw IOError(port); 159 } 160 } 161 162 HBA_ADAPTERATTRIBUTES attributes; 163 fcio_t fcio; 164 fc_hba_adapter_attributes_t attrs; 165 166 memset(&fcio, 0, sizeof (fcio)); 167 168 fcio.fcio_cmd = FCIO_GET_ADAPTER_ATTRIBUTES; 169 fcio.fcio_olen = sizeof (attrs); 170 fcio.fcio_xfer = FCIO_XFER_READ; 171 fcio.fcio_obuf = (caddr_t)&attrs; 172 173 174 errno = 0; 175 if (ioctl(fd, FCIO_CMD, &fcio) != 0) { 176 close(fd); 177 if (errno == EBUSY) { 178 throw BusyException(); 179 } else if (errno == EAGAIN) { 180 throw TryAgainException(); 181 } else if (errno == ENOTSUP) { 182 throw NotSupportedException(); 183 } else { 184 throw IOError("Unable to fetch adapter attributes"); 185 } 186 } 187 close(fd); 188 189 /* Now copy over the payload */ 190 attributes.NumberOfPorts = attrs.NumberOfPorts; 191 attributes.VendorSpecificID = attrs.VendorSpecificID; 192 memcpy(attributes.Manufacturer, attrs.Manufacturer, 64); 193 memcpy(attributes.SerialNumber, attrs.SerialNumber, 64); 194 memcpy(attributes.Model, attrs.Model, 256); 195 memcpy(attributes.ModelDescription, attrs.ModelDescription, 256); 196 memcpy(attributes.NodeSymbolicName, attrs.NodeSymbolicName, 256); 197 memcpy(attributes.HardwareVersion, attrs.HardwareVersion, 256); 198 memcpy(attributes.DriverVersion, attrs.DriverVersion, 256); 199 memcpy(attributes.OptionROMVersion, attrs.OptionROMVersion, 256); 200 memcpy(attributes.FirmwareVersion, attrs.FirmwareVersion, 256); 201 memcpy(attributes.DriverName, attrs.DriverName, 256); 202 memcpy(&attributes.NodeWWN, &attrs.NodeWWN, 8); 203 204 return (attributes); 205 } 206 207 int FCHBA::doForceLip() { 208 Trace log("FCHBA::doForceLip"); 209 int fd; 210 fcio_t fcio; 211 uint64_t wwn = 0; 212 HBAPort *port = getPortByIndex(0); 213 214 errno = 0; 215 if ((fd = open(port->getPath().c_str(), O_RDONLY | O_EXCL)) == -1) { 216 if (errno == EBUSY) { 217 throw BusyException(); 218 } else if (errno == EAGAIN) { 219 throw TryAgainException(); 220 } else if (errno == ENOTSUP) { 221 throw NotSupportedException(); 222 } else { 223 throw IOError(port); 224 } 225 } 226 227 memset(&fcio, 0, sizeof (fcio)); 228 fcio.fcio_cmd = FCIO_RESET_LINK; 229 fcio.fcio_xfer = FCIO_XFER_WRITE; 230 fcio.fcio_ilen = sizeof (wwn); 231 fcio.fcio_ibuf = (caddr_t)&wwn; 232 233 errno = 0; 234 if (ioctl(fd, FCIO_CMD, &fcio) != 0) { 235 close(fd); 236 237 if (errno == EBUSY) { 238 throw BusyException(); 239 } else if (errno == EAGAIN) { 240 throw TryAgainException(); 241 } else if (errno == ENOTSUP) { 242 throw NotSupportedException(); 243 } else { 244 throw IOError("Unable to reinitialize the link"); 245 } 246 } else { 247 close(fd); 248 return (fcio.fcio_errno); 249 } 250 } 251 252 HBA_ADAPTERATTRIBUTES FCHBA::npivGetHBAAttributes() { 253 Trace log("FCHBA::npivGetHBAAttributes"); 254 int fd; 255 256 errno = 0; 257 HBAPort *port = getPortByIndex(0); 258 if ((fd = open(port->getPath().c_str(), O_NDELAY | O_RDONLY)) == -1) { 259 // Why did we fail? 260 if (errno == EBUSY) { 261 throw BusyException(); 262 } else if (errno == EAGAIN) { 263 throw TryAgainException(); 264 } else if (errno == ENOTSUP) { 265 throw NotSupportedException(); 266 } else { 267 throw IOError(port); 268 } 269 } 270 271 HBA_ADAPTERATTRIBUTES attributes; 272 fcio_t fcio; 273 fc_hba_adapter_attributes_t attrs; 274 275 memset(&fcio, 0, sizeof (fcio)); 276 fcio.fcio_cmd = FCIO_NPIV_GET_ADAPTER_ATTRIBUTES; 277 fcio.fcio_olen = sizeof (attrs); 278 fcio.fcio_xfer = FCIO_XFER_READ; 279 fcio.fcio_obuf = (caddr_t)&attrs; 280 errno = 0; 281 282 if (ioctl(fd, FCIO_CMD, &fcio) != 0) { 283 close(fd); 284 if (errno == EBUSY) { 285 throw BusyException(); 286 } else if (errno == EAGAIN) { 287 throw TryAgainException(); 288 } else if (errno == ENOTSUP) { 289 throw NotSupportedException(); 290 } else { 291 throw IOError("Unable to fetch adapter attributes"); 292 } 293 } 294 close(fd); 295 296 /* Now copy over the payload */ 297 attributes.NumberOfPorts = attrs.NumberOfPorts; 298 attributes.VendorSpecificID = attrs.VendorSpecificID; 299 memcpy(attributes.Manufacturer, attrs.Manufacturer, 64); 300 memcpy(attributes.SerialNumber, attrs.SerialNumber, 64); 301 memcpy(attributes.Model, attrs.Model, 256); 302 memcpy(attributes.ModelDescription, attrs.ModelDescription, 256); 303 memcpy(attributes.NodeSymbolicName, attrs.NodeSymbolicName, 256); 304 memcpy(attributes.HardwareVersion, attrs.HardwareVersion, 256); 305 memcpy(attributes.DriverVersion, attrs.DriverVersion, 256); 306 memcpy(attributes.OptionROMVersion, attrs.OptionROMVersion, 256); 307 memcpy(attributes.FirmwareVersion, attrs.FirmwareVersion, 256); 308 memcpy(attributes.DriverName, attrs.DriverName, 256); 309 memcpy(&attributes.NodeWWN, &attrs.NodeWWN, 8); 310 311 return (attributes); 312 } 313 314 void FCHBA::loadAdapters(vector<HBA*> &list) { 315 Trace log("FCHBA::loadAdapters"); 316 fcio_t fcio; 317 fc_hba_list_t *pathList; 318 int fd; 319 int size = 64; // default first attempt 320 bool retry = false; 321 struct stat sb; 322 int bufSize; 323 324 /* Before we do anything, let's see if FCSM is on the system */ 325 errno = 0; 326 if (stat(FCSM_DRIVER_PATH.c_str(), &sb) != 0) { 327 if (errno == ENOENT) { 328 log.genericIOError( 329 "The %s driver is not present. Unable to issue " 330 "CT commands. Please install the %s package.", 331 FCSM_DRIVER_PATH.c_str(), FCSM_DRIVER_PKG.c_str()); 332 throw NotSupportedException(); 333 } else { 334 log.genericIOError( 335 "Can not stat the %s driver for reason \"%s\" " 336 "Unable to issue CT commands.", 337 FCSM_DRIVER_PATH.c_str(), strerror(errno)); 338 throw IOError("Unable to stat FCSM driver"); 339 } 340 } 341 342 343 /* construct fcio struct */ 344 memset(&fcio, 0, sizeof (fcio_t)); 345 fcio.fcio_cmd = FCSMIO_ADAPTER_LIST; 346 fcio.fcio_xfer = FCIO_XFER_RW; 347 348 349 /* open the fcsm node so we can send the ioctl to */ 350 errno = 0; 351 if ((fd = open(FCSM_DRIVER_PATH.c_str(), O_RDONLY)) < 0) { 352 if (errno == EBUSY) { 353 throw BusyException(); 354 } else if (errno == EAGAIN) { 355 throw TryAgainException(); 356 } else if (errno == ENOTSUP) { 357 throw NotSupportedException(); 358 } else if (errno == ENOENT) { 359 throw UnavailableException(); 360 } else { 361 throw IOError("Unable to open FCSM driver"); 362 } 363 } 364 365 do { 366 retry = false; 367 errno = 0; 368 bufSize = MAXPATHLEN * size + (int) sizeof (fc_hba_list_t) - 1; 369 pathList = (fc_hba_list_t *)new uchar_t[bufSize]; 370 pathList->numAdapters = size; 371 fcio.fcio_olen = bufSize; 372 fcio.fcio_obuf = (char *)pathList; 373 if (ioctl(fd, FCSMIO_CMD, &fcio) != 0) { 374 /* Interpret the fcio error code */ 375 char fcioErrorString[MAX_FCIO_MSG_LEN] = ""; 376 377 log.genericIOError( 378 "ADAPTER_LIST failed: " 379 "Errno: \"%s\"", 380 strerror(errno)); 381 delete (pathList); 382 close(fd); 383 if (errno == EBUSY) { 384 throw BusyException(); 385 } else if (errno == EAGAIN) { 386 throw TryAgainException(); 387 } else if (errno == ENOTSUP) { 388 throw NotSupportedException(); 389 } else if (errno == ENOENT) { 390 throw UnavailableException(); 391 } else { 392 throw IOError("Unable to build HBA list"); 393 } 394 } 395 if (pathList->numAdapters > size) { 396 log.debug( 397 "Buffer too small for number of HBAs. Retrying."); 398 size = pathList->numAdapters; 399 retry = true; 400 delete (pathList); 401 } 402 } while (retry); 403 404 close(fd); 405 log.debug("Detected %d adapters", pathList->numAdapters); 406 for (int i = 0; i < pathList->numAdapters; i++) { 407 try { 408 HBA *hba = new FCHBA(pathList->hbaPaths[i]); 409 list.insert(list.begin(), hba); 410 } catch (...) { 411 log.debug( 412 "Ignoring partial failure while loading an HBA"); 413 } 414 } 415 if (pathList->numAdapters > HBAList::HBA_MAX_PER_LIST) { 416 delete(pathList); 417 throw InternalError( 418 "Exceeds max number of adatpers that VSL supports."); 419 } 420 delete (pathList); 421 } 422