xref: /titanic_50/usr/src/lib/libfcoe/common/libfcoe.c (revision 2a8164df8a5f42c8a00f10c67d7bc84f80ae9c41)
1*2a8164dfSZhong Wang /*
2*2a8164dfSZhong Wang  * CDDL HEADER START
3*2a8164dfSZhong Wang  *
4*2a8164dfSZhong Wang  * The contents of this file are subject to the terms of the
5*2a8164dfSZhong Wang  * Common Development and Distribution License (the "License").
6*2a8164dfSZhong Wang  * You may not use this file except in compliance with the License.
7*2a8164dfSZhong Wang  *
8*2a8164dfSZhong Wang  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*2a8164dfSZhong Wang  * or http://www.opensolaris.org/os/licensing.
10*2a8164dfSZhong Wang  * See the License for the specific language governing permissions
11*2a8164dfSZhong Wang  * and limitations under the License.
12*2a8164dfSZhong Wang  *
13*2a8164dfSZhong Wang  * When distributing Covered Code, include this CDDL HEADER in each
14*2a8164dfSZhong Wang  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*2a8164dfSZhong Wang  * If applicable, add the following below this CDDL HEADER, with the
16*2a8164dfSZhong Wang  * fields enclosed by brackets "[]" replaced with your own identifying
17*2a8164dfSZhong Wang  * information: Portions Copyright [yyyy] [name of copyright owner]
18*2a8164dfSZhong Wang  *
19*2a8164dfSZhong Wang  * CDDL HEADER END
20*2a8164dfSZhong Wang  */
21*2a8164dfSZhong Wang /*
22*2a8164dfSZhong Wang  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23*2a8164dfSZhong Wang  * Use is subject to license terms.
24*2a8164dfSZhong Wang  */
25*2a8164dfSZhong Wang 
26*2a8164dfSZhong Wang #include <stdlib.h>
27*2a8164dfSZhong Wang #include <stdio.h>
28*2a8164dfSZhong Wang #include <wchar.h>
29*2a8164dfSZhong Wang #include <strings.h>
30*2a8164dfSZhong Wang #include <sys/types.h>
31*2a8164dfSZhong Wang #include <sys/stat.h>
32*2a8164dfSZhong Wang #include <fcntl.h>
33*2a8164dfSZhong Wang #include <unistd.h>
34*2a8164dfSZhong Wang #include <libintl.h>
35*2a8164dfSZhong Wang #include <errno.h>
36*2a8164dfSZhong Wang #include <string.h>
37*2a8164dfSZhong Wang #include <assert.h>
38*2a8164dfSZhong Wang #include <syslog.h>
39*2a8164dfSZhong Wang #include <libfcoe.h>
40*2a8164dfSZhong Wang #include <fcoeio.h>
41*2a8164dfSZhong Wang 
42*2a8164dfSZhong Wang #define	FCOE_DEV_PATH	 "/devices/fcoe:admin"
43*2a8164dfSZhong Wang 
44*2a8164dfSZhong Wang #define	OPEN_FCOE 0
45*2a8164dfSZhong Wang #define	OPEN_EXCL_FCOE O_EXCL
46*2a8164dfSZhong Wang 
47*2a8164dfSZhong Wang /*
48*2a8164dfSZhong Wang  * Open for fcoe module
49*2a8164dfSZhong Wang  *
50*2a8164dfSZhong Wang  * flag - open flag (OPEN_FCOE, OPEN_EXCL_FCOE)
51*2a8164dfSZhong Wang  * fd - pointer to integer. On success, contains the fcoe file descriptor
52*2a8164dfSZhong Wang  */
53*2a8164dfSZhong Wang static int
54*2a8164dfSZhong Wang openFcoe(int flag, int *fd)
55*2a8164dfSZhong Wang {
56*2a8164dfSZhong Wang 	int ret = FCOE_STATUS_ERROR;
57*2a8164dfSZhong Wang 
58*2a8164dfSZhong Wang 	if ((*fd = open(FCOE_DEV_PATH, O_NDELAY | O_RDONLY | flag)) != -1) {
59*2a8164dfSZhong Wang 		ret = FCOE_STATUS_OK;
60*2a8164dfSZhong Wang 	} else {
61*2a8164dfSZhong Wang 		if (errno == EPERM || errno == EACCES) {
62*2a8164dfSZhong Wang 			ret = FCOE_STATUS_ERROR_PERM;
63*2a8164dfSZhong Wang 		} else {
64*2a8164dfSZhong Wang 			ret = FCOE_STATUS_ERROR_OPEN_DEV;
65*2a8164dfSZhong Wang 		}
66*2a8164dfSZhong Wang 		syslog(LOG_DEBUG, "openFcoe:open failure:%s:errno(%d)",
67*2a8164dfSZhong Wang 		    FCOE_DEV_PATH, errno);
68*2a8164dfSZhong Wang 	}
69*2a8164dfSZhong Wang 
70*2a8164dfSZhong Wang 	return (ret);
71*2a8164dfSZhong Wang }
72*2a8164dfSZhong Wang 
73*2a8164dfSZhong Wang static int
74*2a8164dfSZhong Wang isWWNZero(FCOE_PORT_WWN portwwn)
75*2a8164dfSZhong Wang {
76*2a8164dfSZhong Wang 	int i;
77*2a8164dfSZhong Wang 	int size = sizeof (FCOE_PORT_WWN);
78*2a8164dfSZhong Wang 
79*2a8164dfSZhong Wang 	for (i = 0; i < size; i++) {
80*2a8164dfSZhong Wang 		if (portwwn.wwn[i] != 0) {
81*2a8164dfSZhong Wang 			return (0);
82*2a8164dfSZhong Wang 		}
83*2a8164dfSZhong Wang 	}
84*2a8164dfSZhong Wang 	return (1);
85*2a8164dfSZhong Wang }
86*2a8164dfSZhong Wang 
87*2a8164dfSZhong Wang FCOE_STATUS
88*2a8164dfSZhong Wang FCOE_CreatePort(
89*2a8164dfSZhong Wang 	const FCOE_UINT8		*macLinkName,
90*2a8164dfSZhong Wang 	FCOE_UINT8		portType,
91*2a8164dfSZhong Wang 	FCOE_PORT_WWN		pwwn,
92*2a8164dfSZhong Wang 	FCOE_PORT_WWN		nwwn,
93*2a8164dfSZhong Wang 	FCOE_UINT8		promiscuous)
94*2a8164dfSZhong Wang {
95*2a8164dfSZhong Wang 	FCOE_STATUS status = FCOE_STATUS_OK;
96*2a8164dfSZhong Wang 	int fcoe_fd;
97*2a8164dfSZhong Wang 	fcoeio_t	fcoeio;
98*2a8164dfSZhong Wang 	fcoeio_create_port_param_t	param;
99*2a8164dfSZhong Wang 
100*2a8164dfSZhong Wang 	bzero(&param, sizeof (fcoeio_create_port_param_t));
101*2a8164dfSZhong Wang 
102*2a8164dfSZhong Wang 	if (macLinkName == NULL) {
103*2a8164dfSZhong Wang 		return (FCOE_STATUS_ERROR_INVAL_ARG);
104*2a8164dfSZhong Wang 	}
105*2a8164dfSZhong Wang 
106*2a8164dfSZhong Wang 	if (portType != FCOE_PORTTYPE_INITIATOR &&
107*2a8164dfSZhong Wang 	    portType != FCOE_PORTTYPE_TARGET) {
108*2a8164dfSZhong Wang 		return (FCOE_STATUS_ERROR_INVAL_ARG);
109*2a8164dfSZhong Wang 	}
110*2a8164dfSZhong Wang 
111*2a8164dfSZhong Wang 	if (!isWWNZero(pwwn)) {
112*2a8164dfSZhong Wang 		param.fcp_pwwn_provided = 1;
113*2a8164dfSZhong Wang 		bcopy(pwwn.wwn, param.fcp_pwwn, 8);
114*2a8164dfSZhong Wang 	}
115*2a8164dfSZhong Wang 
116*2a8164dfSZhong Wang 	if (!isWWNZero(nwwn)) {
117*2a8164dfSZhong Wang 		param.fcp_nwwn_provided = 1;
118*2a8164dfSZhong Wang 		bcopy(nwwn.wwn, param.fcp_nwwn, 8);
119*2a8164dfSZhong Wang 	}
120*2a8164dfSZhong Wang 
121*2a8164dfSZhong Wang 	if (param.fcp_pwwn_provided == 1 &&
122*2a8164dfSZhong Wang 	    param.fcp_nwwn_provided == 1 &&
123*2a8164dfSZhong Wang 	    bcmp(&pwwn, &nwwn, 8) == 0) {
124*2a8164dfSZhong Wang 		return (FCOE_STATUS_ERROR_WWN_SAME);
125*2a8164dfSZhong Wang 	}
126*2a8164dfSZhong Wang 
127*2a8164dfSZhong Wang 	if (strlen((char *)macLinkName) > FCOE_MAX_MAC_NAME_LEN-1) {
128*2a8164dfSZhong Wang 		return (FCOE_STATUS_ERROR_MAC_LEN);
129*2a8164dfSZhong Wang 	}
130*2a8164dfSZhong Wang 
131*2a8164dfSZhong Wang 	param.fcp_force_promisc = promiscuous;
132*2a8164dfSZhong Wang 	(void) strcpy((char *)param.fcp_mac_name, (char *)macLinkName);
133*2a8164dfSZhong Wang 	param.fcp_port_type = (fcoe_cli_type_t)portType;
134*2a8164dfSZhong Wang 
135*2a8164dfSZhong Wang 	if ((status = openFcoe(OPEN_FCOE, &fcoe_fd)) != FCOE_STATUS_OK) {
136*2a8164dfSZhong Wang 		return (status);
137*2a8164dfSZhong Wang 	}
138*2a8164dfSZhong Wang 
139*2a8164dfSZhong Wang 	(void) memset(&fcoeio, 0, sizeof (fcoeio));
140*2a8164dfSZhong Wang 	fcoeio.fcoeio_cmd = FCOEIO_CREATE_FCOE_PORT;
141*2a8164dfSZhong Wang 
142*2a8164dfSZhong Wang 	fcoeio.fcoeio_ilen = sizeof (param);
143*2a8164dfSZhong Wang 	fcoeio.fcoeio_xfer = FCOEIO_XFER_WRITE;
144*2a8164dfSZhong Wang 	fcoeio.fcoeio_ibuf = (uintptr_t)&param;
145*2a8164dfSZhong Wang 
146*2a8164dfSZhong Wang 	if (ioctl(fcoe_fd, FCOEIO_CMD, &fcoeio) != 0) {
147*2a8164dfSZhong Wang 		switch (fcoeio.fcoeio_status) {
148*2a8164dfSZhong Wang 		case FCOEIOE_INVAL_ARG:
149*2a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_INVAL_ARG;
150*2a8164dfSZhong Wang 			break;
151*2a8164dfSZhong Wang 
152*2a8164dfSZhong Wang 		case FCOEIOE_BUSY:
153*2a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_BUSY;
154*2a8164dfSZhong Wang 			break;
155*2a8164dfSZhong Wang 
156*2a8164dfSZhong Wang 		case FCOEIOE_ALREADY:
157*2a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_ALREADY;
158*2a8164dfSZhong Wang 			break;
159*2a8164dfSZhong Wang 
160*2a8164dfSZhong Wang 		case FCOEIOE_PWWN_CONFLICTED:
161*2a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_PWWN_CONFLICTED;
162*2a8164dfSZhong Wang 			break;
163*2a8164dfSZhong Wang 
164*2a8164dfSZhong Wang 		case FCOEIOE_NWWN_CONFLICTED:
165*2a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_NWWN_CONFLICTED;
166*2a8164dfSZhong Wang 			break;
167*2a8164dfSZhong Wang 
168*2a8164dfSZhong Wang 		case FCOEIOE_CREATE_MAC:
169*2a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_CREATE_MAC;
170*2a8164dfSZhong Wang 			break;
171*2a8164dfSZhong Wang 
172*2a8164dfSZhong Wang 		case FCOEIOE_OPEN_MAC:
173*2a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_OPEN_MAC;
174*2a8164dfSZhong Wang 			break;
175*2a8164dfSZhong Wang 
176*2a8164dfSZhong Wang 		case FCOEIOE_CREATE_PORT:
177*2a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_CREATE_PORT;
178*2a8164dfSZhong Wang 			break;
179*2a8164dfSZhong Wang 
180*2a8164dfSZhong Wang 		case FCOEIOE_NEED_JUMBO_FRAME:
181*2a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_NEED_JUMBO_FRAME;
182*2a8164dfSZhong Wang 			break;
183*2a8164dfSZhong Wang 
184*2a8164dfSZhong Wang 		case FCOEIOE_VNIC_UNSUPPORT:
185*2a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_VNIC_UNSUPPORT;
186*2a8164dfSZhong Wang 			break;
187*2a8164dfSZhong Wang 
188*2a8164dfSZhong Wang 		default:
189*2a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR;
190*2a8164dfSZhong Wang 		}
191*2a8164dfSZhong Wang 	} else {
192*2a8164dfSZhong Wang 		status = FCOE_STATUS_OK;
193*2a8164dfSZhong Wang 	}
194*2a8164dfSZhong Wang 	(void) close(fcoe_fd);
195*2a8164dfSZhong Wang 	return (status);
196*2a8164dfSZhong Wang }
197*2a8164dfSZhong Wang 
198*2a8164dfSZhong Wang FCOE_STATUS
199*2a8164dfSZhong Wang FCOE_DeletePort(const FCOE_UINT8 *macLinkName)
200*2a8164dfSZhong Wang {
201*2a8164dfSZhong Wang 	FCOE_STATUS status = FCOE_STATUS_OK;
202*2a8164dfSZhong Wang 	int fcoe_fd;
203*2a8164dfSZhong Wang 	fcoeio_t	fcoeio;
204*2a8164dfSZhong Wang 
205*2a8164dfSZhong Wang 	if (macLinkName == NULL) {
206*2a8164dfSZhong Wang 		return (FCOE_STATUS_ERROR_INVAL_ARG);
207*2a8164dfSZhong Wang 	}
208*2a8164dfSZhong Wang 
209*2a8164dfSZhong Wang 	if (strlen((char *)macLinkName) > FCOE_MAX_MAC_NAME_LEN-1) {
210*2a8164dfSZhong Wang 		return (FCOE_STATUS_ERROR_MAC_LEN);
211*2a8164dfSZhong Wang 	}
212*2a8164dfSZhong Wang 
213*2a8164dfSZhong Wang 	if ((status = openFcoe(OPEN_FCOE, &fcoe_fd)) != FCOE_STATUS_OK) {
214*2a8164dfSZhong Wang 		return (status);
215*2a8164dfSZhong Wang 	}
216*2a8164dfSZhong Wang 
217*2a8164dfSZhong Wang 	(void) memset(&fcoeio, 0, sizeof (fcoeio));
218*2a8164dfSZhong Wang 	fcoeio.fcoeio_cmd = FCOEIO_DELETE_FCOE_PORT;
219*2a8164dfSZhong Wang 
220*2a8164dfSZhong Wang 	fcoeio.fcoeio_ilen = strlen((char *)macLinkName)+1;
221*2a8164dfSZhong Wang 	fcoeio.fcoeio_xfer = FCOEIO_XFER_WRITE;
222*2a8164dfSZhong Wang 	fcoeio.fcoeio_ibuf = (uintptr_t)macLinkName;
223*2a8164dfSZhong Wang 
224*2a8164dfSZhong Wang 	if (ioctl(fcoe_fd, FCOEIO_CMD, &fcoeio) != 0) {
225*2a8164dfSZhong Wang 		switch (fcoeio.fcoeio_status) {
226*2a8164dfSZhong Wang 		case FCOEIOE_INVAL_ARG:
227*2a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_INVAL_ARG;
228*2a8164dfSZhong Wang 			break;
229*2a8164dfSZhong Wang 
230*2a8164dfSZhong Wang 		case FCOEIOE_BUSY:
231*2a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_BUSY;
232*2a8164dfSZhong Wang 			break;
233*2a8164dfSZhong Wang 
234*2a8164dfSZhong Wang 		case FCOEIOE_ALREADY:
235*2a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_ALREADY;
236*2a8164dfSZhong Wang 			break;
237*2a8164dfSZhong Wang 
238*2a8164dfSZhong Wang 		case FCOEIOE_MAC_NOT_FOUND:
239*2a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_MAC_NOT_FOUND;
240*2a8164dfSZhong Wang 			break;
241*2a8164dfSZhong Wang 
242*2a8164dfSZhong Wang 		case FCOEIOE_OFFLINE_FAILURE:
243*2a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR_OFFLINE_DEV;
244*2a8164dfSZhong Wang 			break;
245*2a8164dfSZhong Wang 
246*2a8164dfSZhong Wang 		default:
247*2a8164dfSZhong Wang 			status = FCOE_STATUS_ERROR;
248*2a8164dfSZhong Wang 		}
249*2a8164dfSZhong Wang 	} else {
250*2a8164dfSZhong Wang 		status = FCOE_STATUS_OK;
251*2a8164dfSZhong Wang 	}
252*2a8164dfSZhong Wang 	(void) close(fcoe_fd);
253*2a8164dfSZhong Wang 	return (status);
254*2a8164dfSZhong Wang }
255*2a8164dfSZhong Wang 
256*2a8164dfSZhong Wang FCOE_STATUS
257*2a8164dfSZhong Wang FCOE_GetPortList(
258*2a8164dfSZhong Wang 	FCOE_UINT32		*port_num,
259*2a8164dfSZhong Wang 	FCOE_PORT_ATTRIBUTE	**portlist)
260*2a8164dfSZhong Wang {
261*2a8164dfSZhong Wang 	FCOE_STATUS	status = FCOE_STATUS_OK;
262*2a8164dfSZhong Wang 	int	fcoe_fd;
263*2a8164dfSZhong Wang 	fcoeio_t	fcoeio;
264*2a8164dfSZhong Wang 	fcoe_port_list_t		*inportlist = NULL;
265*2a8164dfSZhong Wang 	FCOE_PORT_ATTRIBUTE	*outportlist = NULL;
266*2a8164dfSZhong Wang 	int	i;
267*2a8164dfSZhong Wang 	int	size = 64; /* default first attempt */
268*2a8164dfSZhong Wang 	int	retry = 0;
269*2a8164dfSZhong Wang 	int	bufsize;
270*2a8164dfSZhong Wang 
271*2a8164dfSZhong Wang 	if (port_num == NULL || portlist == NULL) {
272*2a8164dfSZhong Wang 		return (FCOE_STATUS_ERROR_INVAL_ARG);
273*2a8164dfSZhong Wang 	}
274*2a8164dfSZhong Wang 	*port_num = 0;
275*2a8164dfSZhong Wang 
276*2a8164dfSZhong Wang 	if ((status = openFcoe(OPEN_FCOE, &fcoe_fd)) != FCOE_STATUS_OK) {
277*2a8164dfSZhong Wang 		return (status);
278*2a8164dfSZhong Wang 	}
279*2a8164dfSZhong Wang 
280*2a8164dfSZhong Wang 	/* Get fcoe port list */
281*2a8164dfSZhong Wang 	(void) memset(&fcoeio, 0, sizeof (fcoeio));
282*2a8164dfSZhong Wang 	retry = 0;
283*2a8164dfSZhong Wang 
284*2a8164dfSZhong Wang 	do {
285*2a8164dfSZhong Wang 		bufsize = sizeof (fcoe_port_instance_t) * (size - 1) +
286*2a8164dfSZhong Wang 		    sizeof (fcoe_port_list_t);
287*2a8164dfSZhong Wang 		inportlist = (fcoe_port_list_t *)malloc(bufsize);
288*2a8164dfSZhong Wang 		fcoeio.fcoeio_cmd = FCOEIO_GET_FCOE_PORT_LIST;
289*2a8164dfSZhong Wang 		fcoeio.fcoeio_olen = bufsize;
290*2a8164dfSZhong Wang 		fcoeio.fcoeio_xfer = FCOEIO_XFER_READ;
291*2a8164dfSZhong Wang 		fcoeio.fcoeio_obuf = (uintptr_t)inportlist;
292*2a8164dfSZhong Wang 
293*2a8164dfSZhong Wang 		if (ioctl(fcoe_fd, FCOEIO_CMD, &fcoeio) != 0) {
294*2a8164dfSZhong Wang 			if (fcoeio.fcoeio_status == FCOEIOE_MORE_DATA) {
295*2a8164dfSZhong Wang 				size = inportlist->numPorts;
296*2a8164dfSZhong Wang 			}
297*2a8164dfSZhong Wang 			free(inportlist);
298*2a8164dfSZhong Wang 			switch (fcoeio.fcoeio_status) {
299*2a8164dfSZhong Wang 			case FCOEIOE_INVAL_ARG:
300*2a8164dfSZhong Wang 				status = FCOE_STATUS_ERROR_INVAL_ARG;
301*2a8164dfSZhong Wang 				(void) close(fcoe_fd);
302*2a8164dfSZhong Wang 				return (status);
303*2a8164dfSZhong Wang 
304*2a8164dfSZhong Wang 			case FCOEIOE_BUSY:
305*2a8164dfSZhong Wang 				status = FCOE_STATUS_ERROR_BUSY;
306*2a8164dfSZhong Wang 				retry++;
307*2a8164dfSZhong Wang 				break;
308*2a8164dfSZhong Wang 
309*2a8164dfSZhong Wang 			case FCOEIOE_MORE_DATA:
310*2a8164dfSZhong Wang 				status = FCOE_STATUS_ERROR_MORE_DATA;
311*2a8164dfSZhong Wang 				retry++;
312*2a8164dfSZhong Wang 			default:
313*2a8164dfSZhong Wang 				status = FCOE_STATUS_ERROR;
314*2a8164dfSZhong Wang 			}
315*2a8164dfSZhong Wang 		} else {
316*2a8164dfSZhong Wang 			status = FCOE_STATUS_OK;
317*2a8164dfSZhong Wang 			break;
318*2a8164dfSZhong Wang 		}
319*2a8164dfSZhong Wang 	} while (retry <= 3 && status != FCOE_STATUS_OK);
320*2a8164dfSZhong Wang 
321*2a8164dfSZhong Wang 	if (status == FCOE_STATUS_OK) {
322*2a8164dfSZhong Wang 		outportlist = (PFCOE_PORT_ATTRIBUTE)
323*2a8164dfSZhong Wang 		    malloc(sizeof (FCOE_PORT_ATTRIBUTE) * inportlist->numPorts);
324*2a8164dfSZhong Wang 
325*2a8164dfSZhong Wang 		for (i = 0; i < inportlist->numPorts; i++) {
326*2a8164dfSZhong Wang 			fcoe_port_instance_t *pi = &inportlist->ports[i];
327*2a8164dfSZhong Wang 			FCOE_PORT_ATTRIBUTE *po = &outportlist[i];
328*2a8164dfSZhong Wang 			bcopy(pi->fpi_pwwn, &po->port_wwn, 8);
329*2a8164dfSZhong Wang 			bcopy(pi->fpi_mac_link_name, po->mac_link_name, 32);
330*2a8164dfSZhong Wang 			bcopy(pi->fpi_mac_factory_addr,
331*2a8164dfSZhong Wang 			    po->mac_factory_addr, 6);
332*2a8164dfSZhong Wang 			bcopy(pi->fpi_mac_current_addr,
333*2a8164dfSZhong Wang 			    po->mac_current_addr, 6);
334*2a8164dfSZhong Wang 			po->port_type = (FCOE_UINT8)pi->fpi_port_type;
335*2a8164dfSZhong Wang 			po->mtu_size = pi->fpi_mtu_size;
336*2a8164dfSZhong Wang 			po->mac_promisc = pi->fpi_mac_promisc;
337*2a8164dfSZhong Wang 		}
338*2a8164dfSZhong Wang 		*port_num = inportlist->numPorts;
339*2a8164dfSZhong Wang 		*portlist = outportlist;
340*2a8164dfSZhong Wang 		free(inportlist);
341*2a8164dfSZhong Wang 	} else {
342*2a8164dfSZhong Wang 		*port_num = 0;
343*2a8164dfSZhong Wang 		*portlist = NULL;
344*2a8164dfSZhong Wang 	}
345*2a8164dfSZhong Wang 	(void) close(fcoe_fd);
346*2a8164dfSZhong Wang 	return (status);
347*2a8164dfSZhong Wang }
348