xref: /illumos-gate/usr/src/lib/sun_fc/common/TgtFCHBA.cc (revision b3385a702fe5f8caba5ad4c451836514efff0bfa)
1fcf3ce44SJohn Forte /*
2fcf3ce44SJohn Forte  * CDDL HEADER START
3fcf3ce44SJohn Forte  *
4fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7fcf3ce44SJohn Forte  *
8fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11fcf3ce44SJohn Forte  * and limitations under the License.
12fcf3ce44SJohn Forte  *
13fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18fcf3ce44SJohn Forte  *
19fcf3ce44SJohn Forte  * CDDL HEADER END
20fcf3ce44SJohn Forte  */
21fcf3ce44SJohn Forte /*
22a7949318SReed  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23fcf3ce44SJohn Forte  * Use is subject to license terms.
24fcf3ce44SJohn Forte  */
25fcf3ce44SJohn Forte 
26fcf3ce44SJohn Forte 
27fcf3ce44SJohn Forte #include <unistd.h>
28fcf3ce44SJohn Forte 
29fcf3ce44SJohn Forte #include <TgtFCHBA.h>
30fcf3ce44SJohn Forte #include <Exceptions.h>
31fcf3ce44SJohn Forte #include <Trace.h>
32fcf3ce44SJohn Forte #include <iostream>
33fcf3ce44SJohn Forte #include <iomanip>
34fcf3ce44SJohn Forte #include <cerrno>
35fcf3ce44SJohn Forte #include <cstring>
36fcf3ce44SJohn Forte #include <sys/types.h>
37fcf3ce44SJohn Forte #include <sys/stat.h>
38fcf3ce44SJohn Forte #include <fcntl.h>
39fcf3ce44SJohn Forte #include <unistd.h>
40fcf3ce44SJohn Forte #include <stropts.h>
41fcf3ce44SJohn Forte #include <sys/fctio.h>
42fcf3ce44SJohn Forte #include <sys/fibre-channel/impl/fc_error.h>
43fcf3ce44SJohn Forte #include <TgtFCHBAPort.h>
44fcf3ce44SJohn Forte #include <HBAList.h>
45fcf3ce44SJohn Forte #include <sun_fc.h>
46f3aaec0aSRichard Lowe #include <cstdlib>
47fcf3ce44SJohn Forte 
48fcf3ce44SJohn Forte using namespace std;
49fcf3ce44SJohn Forte const string TgtFCHBA::FCT_DRIVER_PATH = "/devices/pseudo/fct@0:admin";
50fcf3ce44SJohn Forte const string TgtFCHBA::FCT_ADAPTER_NAME_PREFIX = "/devices/pseudo/fct@0";
51fcf3ce44SJohn Forte const string TgtFCHBA::FCT_DRIVER_PKG	= "SUNWfct";
52fcf3ce44SJohn Forte const int TgtFCHBA::MAX_FCTIO_MSG_LEN = 256;
53fcf3ce44SJohn Forte 
TgtFCHBA(string path)54fcf3ce44SJohn Forte TgtFCHBA::TgtFCHBA(string path) : HBA()
55fcf3ce44SJohn Forte {
56fcf3ce44SJohn Forte     Trace log("TgtFCHBA::TgtFCHBA");
57fcf3ce44SJohn Forte     log.debug("Constructing new Target mode HBA (%s)", path.c_str());
58fcf3ce44SJohn Forte 
59fcf3ce44SJohn Forte     // Add a target FCHBA port. With fct driver architecuture, all target mode
60fcf3ce44SJohn Forte     // FCHBA will have a single port regardless of the multiport support on
61fcf3ce44SJohn Forte     // FCA layer.
62fcf3ce44SJohn Forte     addPort(new TgtFCHBAPort(path));
63fcf3ce44SJohn Forte     name = "INTERNAL-FAILURE"; // Just in case things go wrong
64fcf3ce44SJohn Forte     try {
65fcf3ce44SJohn Forte 	    HBA_ADAPTERATTRIBUTES attrs = getHBAAttributes();
66fcf3ce44SJohn Forte 	    name = attrs.Manufacturer;
67fcf3ce44SJohn Forte 	    name += "-";
68fcf3ce44SJohn Forte 	    name += attrs.Model;
69fcf3ce44SJohn Forte 	    name += "-Tgt";
70fcf3ce44SJohn Forte 
71fcf3ce44SJohn Forte     } catch (HBAException &e) {
72fcf3ce44SJohn Forte 	    log.debug(
73fcf3ce44SJohn Forte 		"Failed to get HBA attribute for %s", path.c_str());
74fcf3ce44SJohn Forte 	    throw e;
75fcf3ce44SJohn Forte     }
76fcf3ce44SJohn Forte }
77fcf3ce44SJohn Forte 
getName()78fcf3ce44SJohn Forte std::string TgtFCHBA::getName()
79fcf3ce44SJohn Forte {
80fcf3ce44SJohn Forte     Trace log("TgtFCHBA::getName");
81fcf3ce44SJohn Forte     return (name);
82fcf3ce44SJohn Forte }
83fcf3ce44SJohn Forte 
getHBAAttributes()84fcf3ce44SJohn Forte HBA_ADAPTERATTRIBUTES TgtFCHBA::getHBAAttributes()
85fcf3ce44SJohn Forte {
86fcf3ce44SJohn Forte     Trace log("TgtFCHBA::getHBAAttributes");
87fcf3ce44SJohn Forte     int fd;
88fcf3ce44SJohn Forte 
89fcf3ce44SJohn Forte     errno = 0;
90fcf3ce44SJohn Forte     HBAPort *port = getPortByIndex(0);
91fcf3ce44SJohn Forte 
92fcf3ce44SJohn Forte     HBA_ADAPTERATTRIBUTES attributes;
93fcf3ce44SJohn Forte     fctio_t			    fctio;
94fcf3ce44SJohn Forte     fc_tgt_hba_adapter_attributes_t	    attrs;
95fcf3ce44SJohn Forte     uint64_t	portwwn;
96fcf3ce44SJohn Forte 
97fcf3ce44SJohn Forte     if ((fd = open(FCT_DRIVER_PATH.c_str(), O_NDELAY | O_RDONLY)) == -1) {
98fcf3ce44SJohn Forte 	// Why did we fail?
99fcf3ce44SJohn Forte 	if (errno == EBUSY) {
100fcf3ce44SJohn Forte 	    throw BusyException();
101fcf3ce44SJohn Forte 	} else if (errno == EAGAIN) {
102fcf3ce44SJohn Forte 	    throw TryAgainException();
103fcf3ce44SJohn Forte 	} else if (errno == ENOTSUP) {
104fcf3ce44SJohn Forte 	    throw NotSupportedException();
105fcf3ce44SJohn Forte 	} else {
106fcf3ce44SJohn Forte 	    throw IOError(port);
107fcf3ce44SJohn Forte 	}
108fcf3ce44SJohn Forte     }
109fcf3ce44SJohn Forte 
110fcf3ce44SJohn Forte     try {
111fcf3ce44SJohn Forte 	    std::string path = port->getPath();
112fcf3ce44SJohn Forte 	    string::size_type offset = path.find_last_of(".");
113fcf3ce44SJohn Forte 	    if (offset >= 0) {
114fcf3ce44SJohn Forte 		string portwwnString = path.substr(offset+1);
115fcf3ce44SJohn Forte 		portwwn = strtoull(portwwnString.c_str(), NULL, 16);
116fcf3ce44SJohn Forte 	    }
117fcf3ce44SJohn Forte     } catch (...) {
118fcf3ce44SJohn Forte 	    throw BadArgumentException();
119fcf3ce44SJohn Forte     }
120fcf3ce44SJohn Forte 
121fcf3ce44SJohn Forte     uint64_t en_wwn = htonll(portwwn);
122fcf3ce44SJohn Forte 
123fcf3ce44SJohn Forte     memset(&fctio, 0, sizeof (fctio));
124fcf3ce44SJohn Forte     fctio.fctio_cmd = FCTIO_GET_ADAPTER_ATTRIBUTES;
125fcf3ce44SJohn Forte     fctio.fctio_olen = (uint32_t)(sizeof (attrs));
126fcf3ce44SJohn Forte     fctio.fctio_xfer = FCTIO_XFER_READ;
127fcf3ce44SJohn Forte     fctio.fctio_obuf = (uint64_t)(uintptr_t)&attrs;
128fcf3ce44SJohn Forte     fctio.fctio_ilen = 8;
129fcf3ce44SJohn Forte     fctio.fctio_ibuf = (uint64_t)(uintptr_t)&en_wwn;
130fcf3ce44SJohn Forte 
131fcf3ce44SJohn Forte     errno = 0;
132fcf3ce44SJohn Forte     if (ioctl(fd, FCTIO_CMD, &fctio) != 0) {
133fcf3ce44SJohn Forte 	close(fd);
134fcf3ce44SJohn Forte 	if (errno == EBUSY) {
135fcf3ce44SJohn Forte 	    throw BusyException();
136fcf3ce44SJohn Forte 	} else if (errno == EAGAIN) {
137fcf3ce44SJohn Forte 	    throw TryAgainException();
138fcf3ce44SJohn Forte 	} else if (errno == ENOTSUP) {
139fcf3ce44SJohn Forte 	    throw NotSupportedException();
140fcf3ce44SJohn Forte 	} else {
141fcf3ce44SJohn Forte 	    throw IOError("Unable to fetch adapter attributes");
142fcf3ce44SJohn Forte 	}
143fcf3ce44SJohn Forte     }
144fcf3ce44SJohn Forte     close(fd);
145fcf3ce44SJohn Forte 
146fcf3ce44SJohn Forte     /* Now copy over the payload */
147fcf3ce44SJohn Forte     attributes.NumberOfPorts = attrs.NumberOfPorts;
148fcf3ce44SJohn Forte     attributes.VendorSpecificID = attrs.VendorSpecificID;
149fcf3ce44SJohn Forte     memcpy(attributes.Manufacturer, attrs.Manufacturer, 64);
150fcf3ce44SJohn Forte     memcpy(attributes.SerialNumber, attrs.SerialNumber, 64);
151fcf3ce44SJohn Forte     memcpy(attributes.Model, attrs.Model, 256);
152fcf3ce44SJohn Forte     memcpy(attributes.ModelDescription, attrs.ModelDescription, 256);
153fcf3ce44SJohn Forte     memcpy(attributes.NodeSymbolicName, attrs.NodeSymbolicName, 256);
154fcf3ce44SJohn Forte     memcpy(attributes.HardwareVersion, attrs.HardwareVersion, 256);
155fcf3ce44SJohn Forte     memcpy(attributes.DriverVersion, attrs.DriverVersion, 256);
156fcf3ce44SJohn Forte     memcpy(attributes.OptionROMVersion, attrs.OptionROMVersion, 256);
157fcf3ce44SJohn Forte     memcpy(attributes.FirmwareVersion, attrs.FirmwareVersion, 256);
158fcf3ce44SJohn Forte     memcpy(attributes.DriverName, attrs.DriverName, 256);
159fcf3ce44SJohn Forte     memcpy(&attributes.NodeWWN, &attrs.NodeWWN, 8);
160fcf3ce44SJohn Forte 
161fcf3ce44SJohn Forte     return (attributes);
162fcf3ce44SJohn Forte }
163fcf3ce44SJohn Forte 
doForceLip()164a7949318SReed int TgtFCHBA::doForceLip()
165a7949318SReed {
166a7949318SReed     Trace	 log("TgtFCHBA::doForceLip");
167a7949318SReed     int		 fd;
168a7949318SReed     HBAPort	*port = getPortByIndex(0);
169a7949318SReed     fctio_t	 fctio;
170a7949318SReed     uint64_t	 portwwn;
171a7949318SReed 
172a7949318SReed     errno = 0;
173a7949318SReed     if ((fd = open(FCT_DRIVER_PATH.c_str(), O_NDELAY | O_RDONLY)) == -1) {
174a7949318SReed 	if (errno == EBUSY) {
175a7949318SReed 	    throw BusyException();
176a7949318SReed 	} else if (errno == EAGAIN) {
177a7949318SReed 	    throw TryAgainException();
178a7949318SReed 	} else if (errno == ENOTSUP) {
179a7949318SReed 	    throw NotSupportedException();
180a7949318SReed 	} else {
181a7949318SReed 	    throw IOError(port);
182a7949318SReed 	}
183a7949318SReed     }
184a7949318SReed 
185a7949318SReed     try {
186a7949318SReed 	    std::string path = port->getPath();
187a7949318SReed 	    string::size_type offset = path.find_last_of(".");
188a7949318SReed 	    if (offset >= 0) {
189a7949318SReed 		string portwwnString = path.substr(offset+1);
190a7949318SReed 		portwwn = strtoull(portwwnString.c_str(), NULL, 16);
191a7949318SReed 	    }
192a7949318SReed     } catch (...) {
193a7949318SReed 	    throw BadArgumentException();
194a7949318SReed     }
195a7949318SReed 
196a7949318SReed     uint64_t en_wwn = htonll(portwwn);
197a7949318SReed     memset(&fctio, 0, sizeof (fctio));
198a7949318SReed     fctio.fctio_cmd = FCTIO_FORCE_LIP;
199a7949318SReed     fctio.fctio_xfer = FCTIO_XFER_READ;
200a7949318SReed     fctio.fctio_ilen = 8;
201a7949318SReed     fctio.fctio_ibuf = (uint64_t)(uintptr_t)&en_wwn;
202a7949318SReed 
203a7949318SReed     errno = 0;
204a7949318SReed     if (ioctl(fd, FCTIO_CMD, &fctio) != 0) {
205a7949318SReed 	close(fd);
206a7949318SReed 	if (errno == EBUSY) {
207a7949318SReed 	    throw BusyException();
208a7949318SReed 	} else if (errno == EAGAIN) {
209a7949318SReed 	    throw TryAgainException();
210a7949318SReed 	} else if (errno == ENOTSUP) {
211a7949318SReed 	    throw NotSupportedException();
212a7949318SReed 	} else {
213a7949318SReed 	    throw IOError("Unable to reinitialize the link");
214a7949318SReed 	}
215a7949318SReed     } else {
216a7949318SReed 	close(fd);
217a7949318SReed 	return ((int)fctio.fctio_errno);
218a7949318SReed     }
219a7949318SReed }
220a7949318SReed 
loadAdapters(vector<HBA * > & list)221fcf3ce44SJohn Forte void TgtFCHBA::loadAdapters(vector<HBA*> &list)
222fcf3ce44SJohn Forte {
223fcf3ce44SJohn Forte     Trace log("TgtFCHBA::loadAdapters");
224fcf3ce44SJohn Forte     fctio_t			fctio;
225fcf3ce44SJohn Forte     fc_tgt_hba_list_t		*tgthbaList;
226fcf3ce44SJohn Forte     int			fd;
227fcf3ce44SJohn Forte     int			size = 64; // default first attempt
228fcf3ce44SJohn Forte     bool		retry = false;
229fcf3ce44SJohn Forte     struct stat		sb;
230fcf3ce44SJohn Forte     int bufSize;
231fcf3ce44SJohn Forte     char wwnStr[17];
232fcf3ce44SJohn Forte 
233fcf3ce44SJohn Forte     /* Before we do anything, let's see if FCT is on the system */
234fcf3ce44SJohn Forte     errno = 0;
235fcf3ce44SJohn Forte     if (stat(FCT_DRIVER_PATH.c_str(), &sb) != 0) {
236fcf3ce44SJohn Forte 	if (errno == ENOENT) {
237fcf3ce44SJohn Forte 	    log.genericIOError(
238fcf3ce44SJohn Forte 		"The %s driver is not present."
239fcf3ce44SJohn Forte                 " Please install the %s package.",
240fcf3ce44SJohn Forte 		FCT_DRIVER_PATH.c_str(), FCT_DRIVER_PKG.c_str());
241fcf3ce44SJohn Forte 	    throw NotSupportedException();
242fcf3ce44SJohn Forte 	} else {
243fcf3ce44SJohn Forte 	    log.genericIOError(
244fcf3ce44SJohn Forte 		"Can not stat the %s driver for reason \"%s\" "
245fcf3ce44SJohn Forte 		"Unable to get target mode FC adapters.",
246fcf3ce44SJohn Forte 		FCT_DRIVER_PATH.c_str(), strerror(errno));
247fcf3ce44SJohn Forte 	    throw IOError("Unable to stat FCSM driver");
248fcf3ce44SJohn Forte 	}
249fcf3ce44SJohn Forte     }
250fcf3ce44SJohn Forte 
251fcf3ce44SJohn Forte 
252fcf3ce44SJohn Forte     /* construct fcio struct */
253fcf3ce44SJohn Forte     memset(&fctio, 0, sizeof (fctio_t));
254fcf3ce44SJohn Forte     fctio.fctio_cmd	= FCTIO_ADAPTER_LIST;
255fcf3ce44SJohn Forte     fctio.fctio_xfer	= FCTIO_XFER_RW;
256fcf3ce44SJohn Forte 
257fcf3ce44SJohn Forte     /* open the fcsm node so we can send the ioctl to */
258fcf3ce44SJohn Forte     errno = 0;
259fcf3ce44SJohn Forte     if ((fd = open(FCT_DRIVER_PATH.c_str(), O_RDONLY)) < 0) {
260fcf3ce44SJohn Forte 	if (errno == EBUSY) {
261fcf3ce44SJohn Forte 	    throw BusyException();
262fcf3ce44SJohn Forte 	} else if (errno == EAGAIN) {
263fcf3ce44SJohn Forte 	    throw TryAgainException();
264fcf3ce44SJohn Forte 	} else if (errno == ENOTSUP) {
265fcf3ce44SJohn Forte 	    throw NotSupportedException();
266fcf3ce44SJohn Forte 	} else if (errno == ENOENT) {
267fcf3ce44SJohn Forte 	    throw UnavailableException();
268fcf3ce44SJohn Forte 	} else {
269fcf3ce44SJohn Forte 	    throw IOError("Unable to open FCT driver");
270fcf3ce44SJohn Forte 	}
271fcf3ce44SJohn Forte     }
272fcf3ce44SJohn Forte 
273fcf3ce44SJohn Forte     do {
274fcf3ce44SJohn Forte 	retry = false;
275fcf3ce44SJohn Forte 	errno = 0;
276fcf3ce44SJohn Forte 	bufSize = 8 * (size - 1) + (int) sizeof (fc_tgt_hba_list_t);
277fcf3ce44SJohn Forte 	tgthbaList = (fc_tgt_hba_list_t *)new uchar_t[bufSize];
278fcf3ce44SJohn Forte 	tgthbaList->numPorts = size;
279fcf3ce44SJohn Forte 	fctio.fctio_olen	= bufSize;
280fcf3ce44SJohn Forte 	fctio.fctio_obuf	= (uint64_t)(uintptr_t)tgthbaList;
281fcf3ce44SJohn Forte 	if (ioctl(fd, FCTIO_CMD, &fctio) != 0) {
282fcf3ce44SJohn Forte 	    /* Interpret the fcio error code */
283fcf3ce44SJohn Forte 	    char fcioErrorString[MAX_FCTIO_MSG_LEN] = "";
284fcf3ce44SJohn Forte 
285fcf3ce44SJohn Forte 	    log.genericIOError(
286fcf3ce44SJohn Forte 		"TGT_ADAPTER_LIST failed: "
287fcf3ce44SJohn Forte 		"Errno: \"%s\"",
288fcf3ce44SJohn Forte 		strerror(errno));
289*b3385a70SToomas Soome 	    delete[] (tgthbaList);
290fcf3ce44SJohn Forte 	    close(fd);
291fcf3ce44SJohn Forte 	    if (errno == EBUSY) {
292fcf3ce44SJohn Forte 		throw BusyException();
293fcf3ce44SJohn Forte 	    } else if (errno == EAGAIN) {
294fcf3ce44SJohn Forte 		throw TryAgainException();
295fcf3ce44SJohn Forte 	    } else if (errno == ENOTSUP) {
296fcf3ce44SJohn Forte 		throw NotSupportedException();
297fcf3ce44SJohn Forte 	    } else if (errno == ENOENT) {
298fcf3ce44SJohn Forte 		throw UnavailableException();
299fcf3ce44SJohn Forte 	    } else {
300fcf3ce44SJohn Forte 		throw IOError("Unable to build HBA list");
301fcf3ce44SJohn Forte 	    }
302fcf3ce44SJohn Forte 	}
303fcf3ce44SJohn Forte 	if (tgthbaList->numPorts > size) {
304fcf3ce44SJohn Forte 	    log.debug(
305fcf3ce44SJohn Forte 		"Buffer too small for number of target mode HBAs. Retrying.");
306fcf3ce44SJohn Forte 	    size = tgthbaList->numPorts;
307fcf3ce44SJohn Forte 	    retry = true;
308*b3385a70SToomas Soome 	    delete[] (tgthbaList);
309fcf3ce44SJohn Forte 	}
310fcf3ce44SJohn Forte     } while (retry);
311fcf3ce44SJohn Forte 
312fcf3ce44SJohn Forte     close(fd);
313fcf3ce44SJohn Forte     log.debug("Detected %d target mode adapters", tgthbaList->numPorts);
314fcf3ce44SJohn Forte     for (int i = 0; i < tgthbaList->numPorts; i++) {
315fcf3ce44SJohn Forte 	try {
316fcf3ce44SJohn Forte 	    std::string hbapath = FCT_ADAPTER_NAME_PREFIX.c_str();
317fcf3ce44SJohn Forte 	    hbapath += ".";
318fcf3ce44SJohn Forte 	    // move the row with two dimentional uint8 array for WWN
319fcf3ce44SJohn Forte 	    uint64_t tmp = ntohll(*((uint64_t *)&tgthbaList->port_wwn[i][0]));
320fcf3ce44SJohn Forte 	    sprintf(wwnStr, "%llx", tmp);
321fcf3ce44SJohn Forte 	    hbapath += wwnStr;
322fcf3ce44SJohn Forte 
323fcf3ce44SJohn Forte 	    HBA *hba = new TgtFCHBA(hbapath);
324fcf3ce44SJohn Forte 	    list.insert(list.begin(), hba);
325fcf3ce44SJohn Forte 	} catch (...) {
326fcf3ce44SJohn Forte 	    log.debug(
327fcf3ce44SJohn Forte 		"Ignoring partial failure while loading an HBA");
328fcf3ce44SJohn Forte 	}
329fcf3ce44SJohn Forte     }
330fcf3ce44SJohn Forte     if (tgthbaList->numPorts > HBAList::HBA_MAX_PER_LIST) {
331*b3385a70SToomas Soome 	delete[](tgthbaList);
332fcf3ce44SJohn Forte 	throw InternalError(
3330778188fSHengqing Hu 	    "Exceeds max number of adapters that VSL supports.");
334fcf3ce44SJohn Forte     }
335*b3385a70SToomas Soome     delete[] (tgthbaList);
336fcf3ce44SJohn Forte }
337