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