xref: /illumos-gate/usr/src/uts/common/io/fcoe/fcoe_eth.c (revision 2a8164df)
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 <sys/stat.h>
27*2a8164dfSZhong Wang #include <sys/types.h>
28*2a8164dfSZhong Wang #include <netinet/in.h>
29*2a8164dfSZhong Wang #include <sys/inttypes.h>
30*2a8164dfSZhong Wang #include <sys/strsun.h>
31*2a8164dfSZhong Wang #include <sys/mac_client.h>
32*2a8164dfSZhong Wang 
33*2a8164dfSZhong Wang /*
34*2a8164dfSZhong Wang  * FCoE header files
35*2a8164dfSZhong Wang  */
36*2a8164dfSZhong Wang #include <sys/fcoe/fcoeio.h>
37*2a8164dfSZhong Wang #include <sys/fcoe/fcoe_common.h>
38*2a8164dfSZhong Wang 
39*2a8164dfSZhong Wang /*
40*2a8164dfSZhong Wang  * Driver's own header files
41*2a8164dfSZhong Wang  */
42*2a8164dfSZhong Wang #include <fcoe.h>
43*2a8164dfSZhong Wang #include <fcoe_eth.h>
44*2a8164dfSZhong Wang #include <fcoe_fc.h>
45*2a8164dfSZhong Wang 
46*2a8164dfSZhong Wang static void fcoe_rx(void *arg, mac_resource_handle_t mrh,
47*2a8164dfSZhong Wang     mblk_t *mp, boolean_t loopback);
48*2a8164dfSZhong Wang static void fcoe_mac_notify(void *arg, mac_notify_type_t type);
49*2a8164dfSZhong Wang 
50*2a8164dfSZhong Wang /*
51*2a8164dfSZhong Wang  * Global variable definitions
52*2a8164dfSZhong Wang  */
53*2a8164dfSZhong Wang 
54*2a8164dfSZhong Wang /*
55*2a8164dfSZhong Wang  * Internal tunable, used to enable p2p mode
56*2a8164dfSZhong Wang  */
57*2a8164dfSZhong Wang volatile uint32_t	fcoe_enable_p2pmode = 0;
58*2a8164dfSZhong Wang 
59*2a8164dfSZhong Wang int
60*2a8164dfSZhong Wang fcoe_open_mac(fcoe_mac_t *mac, int force_promisc, fcoeio_stat_t *err_detail)
61*2a8164dfSZhong Wang {
62*2a8164dfSZhong Wang 	int		ret;
63*2a8164dfSZhong Wang 	int		fcoe_ret;
64*2a8164dfSZhong Wang 	char		cli_name[MAXNAMELEN];
65*2a8164dfSZhong Wang 	mac_diag_t	diag;
66*2a8164dfSZhong Wang 	uint16_t	fm_open_flag = 0;
67*2a8164dfSZhong Wang 
68*2a8164dfSZhong Wang 	*err_detail = 0;
69*2a8164dfSZhong Wang 
70*2a8164dfSZhong Wang 	/*
71*2a8164dfSZhong Wang 	 * Open MAC interface
72*2a8164dfSZhong Wang 	 */
73*2a8164dfSZhong Wang 	ret = mac_open_by_linkname(mac->fm_link_name, &mac->fm_handle);
74*2a8164dfSZhong Wang 	if (ret != 0) {
75*2a8164dfSZhong Wang 		cmn_err(CE_WARN, "Open network interface %s failed",
76*2a8164dfSZhong Wang 		    mac->fm_link_name);
77*2a8164dfSZhong Wang 		FCOE_LOG("fcoe", "mac_open_by_linkname %s failed %x",
78*2a8164dfSZhong Wang 		    mac->fm_link_name, ret);
79*2a8164dfSZhong Wang 		return (FCOE_FAILURE);
80*2a8164dfSZhong Wang 	}
81*2a8164dfSZhong Wang 
82*2a8164dfSZhong Wang 	if (mac_is_vnic(mac->fm_handle)) {
83*2a8164dfSZhong Wang 		(void) mac_close(mac->fm_handle);
84*2a8164dfSZhong Wang 		*err_detail = FCOEIOE_VNIC_UNSUPPORT;
85*2a8164dfSZhong Wang 		return (FCOE_FAILURE);
86*2a8164dfSZhong Wang 	}
87*2a8164dfSZhong Wang 
88*2a8164dfSZhong Wang 	(void) sprintf(cli_name, "%s-%s", mac->fm_link_name, "fcoe");
89*2a8164dfSZhong Wang 
90*2a8164dfSZhong Wang 	ret = mac_client_open(mac->fm_handle,
91*2a8164dfSZhong Wang 	    &mac->fm_cli_handle, cli_name, fm_open_flag);
92*2a8164dfSZhong Wang 	if (ret != 0) {
93*2a8164dfSZhong Wang 		(void) fcoe_close_mac(mac);
94*2a8164dfSZhong Wang 		return (FCOE_FAILURE);
95*2a8164dfSZhong Wang 	}
96*2a8164dfSZhong Wang 	/*
97*2a8164dfSZhong Wang 	 * Cache the pointer of the immutable MAC inforamtion and
98*2a8164dfSZhong Wang 	 * the current and primary MAC address
99*2a8164dfSZhong Wang 	 */
100*2a8164dfSZhong Wang 	mac_unicast_primary_get(mac->fm_handle, mac->fm_primary_addr);
101*2a8164dfSZhong Wang 	bcopy(mac->fm_primary_addr, mac->fm_current_addr,
102*2a8164dfSZhong Wang 	    ETHERADDRL);
103*2a8164dfSZhong Wang 
104*2a8164dfSZhong Wang 	if (mac_unicast_add(mac->fm_cli_handle, NULL, MAC_UNICAST_PRIMARY,
105*2a8164dfSZhong Wang 	    &mac->fm_unicst_handle, 0, &diag)) {
106*2a8164dfSZhong Wang 		(void) fcoe_close_mac(mac);
107*2a8164dfSZhong Wang 		return (FCOE_FAILURE);
108*2a8164dfSZhong Wang 	}
109*2a8164dfSZhong Wang 
110*2a8164dfSZhong Wang 	if (force_promisc) {
111*2a8164dfSZhong Wang 		mac->fm_force_promisc = B_TRUE;
112*2a8164dfSZhong Wang 	}
113*2a8164dfSZhong Wang 
114*2a8164dfSZhong Wang 	/* Get mtu */
115*2a8164dfSZhong Wang 	mac_sdu_get(mac->fm_handle, NULL, &mac->fm_eport.eport_mtu);
116*2a8164dfSZhong Wang 	if (mac->fm_eport.eport_mtu < FCOE_MIN_MTU_SIZE) {
117*2a8164dfSZhong Wang 		if (!fcoe_enable_p2pmode || mac->fm_eport.eport_mtu < 1500) {
118*2a8164dfSZhong Wang 			/*
119*2a8164dfSZhong Wang 			 * Fail open if fail to get mtu, or we are not
120*2a8164dfSZhong Wang 			 * using p2p, or we are using p2p, but
121*2a8164dfSZhong Wang 			 * the mtu is too small
122*2a8164dfSZhong Wang 			 */
123*2a8164dfSZhong Wang 			(void) fcoe_close_mac(mac);
124*2a8164dfSZhong Wang 			*err_detail = FCOEIOE_NEED_JUMBO_FRAME;
125*2a8164dfSZhong Wang 			return (FCOE_FAILURE);
126*2a8164dfSZhong Wang 		}
127*2a8164dfSZhong Wang 	}
128*2a8164dfSZhong Wang 
129*2a8164dfSZhong Wang 	mac->fm_eport.eport_link_speed =
130*2a8164dfSZhong Wang 	    mac_client_stat_get(mac->fm_cli_handle, MAC_STAT_IFSPEED);
131*2a8164dfSZhong Wang 
132*2a8164dfSZhong Wang 	cv_init(&mac->fm_tx_cv, NULL, CV_DRIVER, NULL);
133*2a8164dfSZhong Wang 	mutex_init(&mac->fm_mutex, NULL, MUTEX_DRIVER, NULL);
134*2a8164dfSZhong Wang 	mac->fm_running = B_TRUE;
135*2a8164dfSZhong Wang 
136*2a8164dfSZhong Wang 	fcoe_ret = FCOE_SUCCESS;
137*2a8164dfSZhong Wang 	return (fcoe_ret);
138*2a8164dfSZhong Wang }
139*2a8164dfSZhong Wang 
140*2a8164dfSZhong Wang int
141*2a8164dfSZhong Wang fcoe_close_mac(fcoe_mac_t *mac)
142*2a8164dfSZhong Wang {
143*2a8164dfSZhong Wang 	int ret;
144*2a8164dfSZhong Wang 
145*2a8164dfSZhong Wang 	if (mac->fm_handle == NULL) {
146*2a8164dfSZhong Wang 		return (FCOE_SUCCESS);
147*2a8164dfSZhong Wang 	}
148*2a8164dfSZhong Wang 
149*2a8164dfSZhong Wang 	if (mac->fm_running) {
150*2a8164dfSZhong Wang 		cv_destroy(&mac->fm_tx_cv);
151*2a8164dfSZhong Wang 		mutex_destroy(&mac->fm_mutex);
152*2a8164dfSZhong Wang 		mac->fm_running = B_FALSE;
153*2a8164dfSZhong Wang 	}
154*2a8164dfSZhong Wang 
155*2a8164dfSZhong Wang 	if (mac->fm_promisc_handle != NULL) {
156*2a8164dfSZhong Wang 		mac_promisc_remove(mac->fm_promisc_handle);
157*2a8164dfSZhong Wang 		mac->fm_promisc_handle = NULL;
158*2a8164dfSZhong Wang 	} else {
159*2a8164dfSZhong Wang 		mac_rx_clear(mac->fm_cli_handle);
160*2a8164dfSZhong Wang 	}
161*2a8164dfSZhong Wang 
162*2a8164dfSZhong Wang 	if (mac->fm_notify_handle != NULL) {
163*2a8164dfSZhong Wang 		ret = mac_notify_remove(mac->fm_notify_handle, B_TRUE);
164*2a8164dfSZhong Wang 		ASSERT(ret == 0);
165*2a8164dfSZhong Wang 		mac->fm_notify_handle = NULL;
166*2a8164dfSZhong Wang 	}
167*2a8164dfSZhong Wang 
168*2a8164dfSZhong Wang 	if (mac->fm_unicst_handle != NULL) {
169*2a8164dfSZhong Wang 		(void) mac_unicast_remove(mac->fm_cli_handle,
170*2a8164dfSZhong Wang 		    mac->fm_unicst_handle);
171*2a8164dfSZhong Wang 		mac->fm_unicst_handle = NULL;
172*2a8164dfSZhong Wang 	}
173*2a8164dfSZhong Wang 
174*2a8164dfSZhong Wang 	mac_client_close(mac->fm_cli_handle, 0);
175*2a8164dfSZhong Wang 	mac->fm_cli_handle = NULL;
176*2a8164dfSZhong Wang 
177*2a8164dfSZhong Wang 	(void) mac_close(mac->fm_handle);
178*2a8164dfSZhong Wang 	mac->fm_handle = NULL;
179*2a8164dfSZhong Wang 
180*2a8164dfSZhong Wang 	return (FCOE_SUCCESS);
181*2a8164dfSZhong Wang }
182*2a8164dfSZhong Wang 
183*2a8164dfSZhong Wang int
184*2a8164dfSZhong Wang fcoe_enable_callback(fcoe_mac_t *mac)
185*2a8164dfSZhong Wang {
186*2a8164dfSZhong Wang 	int ret;
187*2a8164dfSZhong Wang 
188*2a8164dfSZhong Wang 	/*
189*2a8164dfSZhong Wang 	 * Set message callback
190*2a8164dfSZhong Wang 	 */
191*2a8164dfSZhong Wang 	if (mac->fm_force_promisc) {
192*2a8164dfSZhong Wang 		ret = mac_promisc_add(mac->fm_cli_handle,
193*2a8164dfSZhong Wang 		    MAC_CLIENT_PROMISC_FILTERED, fcoe_rx, mac,
194*2a8164dfSZhong Wang 		    &mac->fm_promisc_handle,
195*2a8164dfSZhong Wang 		    MAC_PROMISC_FLAGS_NO_TX_LOOP);
196*2a8164dfSZhong Wang 		if (ret != 0) {
197*2a8164dfSZhong Wang 			cmn_err(CE_WARN, "Enable promisc mode on %s failed",
198*2a8164dfSZhong Wang 			    mac->fm_link_name);
199*2a8164dfSZhong Wang 			FCOE_LOG("foce", "mac_promisc_add on %s failed %x",
200*2a8164dfSZhong Wang 			    mac->fm_link_name, ret);
201*2a8164dfSZhong Wang 			return (FCOE_FAILURE);
202*2a8164dfSZhong Wang 		}
203*2a8164dfSZhong Wang 	} else {
204*2a8164dfSZhong Wang 		mac_rx_set(mac->fm_cli_handle, fcoe_rx, mac);
205*2a8164dfSZhong Wang 	}
206*2a8164dfSZhong Wang 
207*2a8164dfSZhong Wang 	/* Get the link state, if it's up, we will need to notify client */
208*2a8164dfSZhong Wang 	mac->fm_link_state =
209*2a8164dfSZhong Wang 	    mac_stat_get(mac->fm_handle, MAC_STAT_LINK_UP)?
210*2a8164dfSZhong Wang 	    FCOE_MAC_LINK_STATE_UP:FCOE_MAC_LINK_STATE_DOWN;
211*2a8164dfSZhong Wang 
212*2a8164dfSZhong Wang 	/*
213*2a8164dfSZhong Wang 	 * Add a notify function so that we get updates from MAC
214*2a8164dfSZhong Wang 	 */
215*2a8164dfSZhong Wang 	mac->fm_notify_handle = mac_notify_add(mac->fm_handle,
216*2a8164dfSZhong Wang 	    fcoe_mac_notify, (void *)mac);
217*2a8164dfSZhong Wang 	return (FCOE_SUCCESS);
218*2a8164dfSZhong Wang }
219*2a8164dfSZhong Wang 
220*2a8164dfSZhong Wang int
221*2a8164dfSZhong Wang fcoe_disable_callback(fcoe_mac_t *mac)
222*2a8164dfSZhong Wang {
223*2a8164dfSZhong Wang 	int ret;
224*2a8164dfSZhong Wang 
225*2a8164dfSZhong Wang 	if (mac->fm_promisc_handle) {
226*2a8164dfSZhong Wang 		mac_promisc_remove(mac->fm_promisc_handle);
227*2a8164dfSZhong Wang 		mac->fm_promisc_handle = NULL;
228*2a8164dfSZhong Wang 	} else {
229*2a8164dfSZhong Wang 		mac_rx_clear(mac->fm_cli_handle);
230*2a8164dfSZhong Wang 	}
231*2a8164dfSZhong Wang 
232*2a8164dfSZhong Wang 	if (mac->fm_notify_handle) {
233*2a8164dfSZhong Wang 		ret = mac_notify_remove(mac->fm_notify_handle, B_TRUE);
234*2a8164dfSZhong Wang 		ASSERT(ret == 0);
235*2a8164dfSZhong Wang 		mac->fm_notify_handle = NULL;
236*2a8164dfSZhong Wang 	}
237*2a8164dfSZhong Wang 
238*2a8164dfSZhong Wang 	ret = fcoe_mac_set_address(&mac->fm_eport,
239*2a8164dfSZhong Wang 	    mac->fm_primary_addr, B_FALSE);
240*2a8164dfSZhong Wang 	FCOE_SET_DEFAULT_FPORT_ADDR(mac->fm_eport.eport_efh_dst);
241*2a8164dfSZhong Wang 	return (ret);
242*2a8164dfSZhong Wang }
243*2a8164dfSZhong Wang 
244*2a8164dfSZhong Wang /* ARGSUSED */
245*2a8164dfSZhong Wang static void
246*2a8164dfSZhong Wang fcoe_rx(void *arg, mac_resource_handle_t mrh, mblk_t *mp, boolean_t loopback)
247*2a8164dfSZhong Wang {
248*2a8164dfSZhong Wang 	fcoe_mac_t	*mac = (fcoe_mac_t *)arg;
249*2a8164dfSZhong Wang 	mblk_t		*next;
250*2a8164dfSZhong Wang 	fcoe_frame_t	*frm;
251*2a8164dfSZhong Wang 	uint32_t	raw_frame_size, frame_size;
252*2a8164dfSZhong Wang 	uint16_t	frm_type;
253*2a8164dfSZhong Wang 
254*2a8164dfSZhong Wang 	while (mp != NULL) {
255*2a8164dfSZhong Wang 		next = mp->b_next;
256*2a8164dfSZhong Wang 		mp->b_next = NULL;
257*2a8164dfSZhong Wang 		frm_type = ntohs(*(uint16_t *)((uintptr_t)mp->b_rptr + 12));
258*2a8164dfSZhong Wang 
259*2a8164dfSZhong Wang 		if (frm_type != ETHERTYPE_FCOE) {
260*2a8164dfSZhong Wang 			/*
261*2a8164dfSZhong Wang 			 * This mp is not allocated in FCoE, but we must free it
262*2a8164dfSZhong Wang 			 */
263*2a8164dfSZhong Wang 			freeb(mp);
264*2a8164dfSZhong Wang 			mp = next;
265*2a8164dfSZhong Wang 			continue;
266*2a8164dfSZhong Wang 		}
267*2a8164dfSZhong Wang 
268*2a8164dfSZhong Wang 		raw_frame_size = MBLKL(mp);
269*2a8164dfSZhong Wang 		frame_size = raw_frame_size - PADDING_SIZE;
270*2a8164dfSZhong Wang 		frm = fcoe_allocate_frame(&mac->fm_eport, frame_size, mp);
271*2a8164dfSZhong Wang 		if (frm != NULL) {
272*2a8164dfSZhong Wang 			fcoe_post_frame(frm);
273*2a8164dfSZhong Wang 		}
274*2a8164dfSZhong Wang 
275*2a8164dfSZhong Wang 		mp = next;
276*2a8164dfSZhong Wang 	}
277*2a8164dfSZhong Wang }
278*2a8164dfSZhong Wang 
279*2a8164dfSZhong Wang static void
280*2a8164dfSZhong Wang fcoe_mac_notify(void *arg, mac_notify_type_t type)
281*2a8164dfSZhong Wang {
282*2a8164dfSZhong Wang 	fcoe_mac_t *mac = (fcoe_mac_t *)arg;
283*2a8164dfSZhong Wang 
284*2a8164dfSZhong Wang 	/*
285*2a8164dfSZhong Wang 	 * We assume that the calls to this notification callback are serialized
286*2a8164dfSZhong Wang 	 * by MAC layer
287*2a8164dfSZhong Wang 	 */
288*2a8164dfSZhong Wang 
289*2a8164dfSZhong Wang 	switch (type) {
290*2a8164dfSZhong Wang 	case MAC_NOTE_LINK:
291*2a8164dfSZhong Wang 		/*
292*2a8164dfSZhong Wang 		 * This notification is sent every time the MAC driver
293*2a8164dfSZhong Wang 		 * updates the link state.
294*2a8164dfSZhong Wang 		 */
295*2a8164dfSZhong Wang 		if (mac_stat_get(mac->fm_handle, MAC_STAT_LINK_UP) != 0) {
296*2a8164dfSZhong Wang 			if (mac->fm_link_state == FCOE_MAC_LINK_STATE_UP) {
297*2a8164dfSZhong Wang 				break;
298*2a8164dfSZhong Wang 			}
299*2a8164dfSZhong Wang 			/* Get speed */
300*2a8164dfSZhong Wang 			mac->fm_eport.eport_link_speed =
301*2a8164dfSZhong Wang 			    mac_client_stat_get(mac->fm_cli_handle,
302*2a8164dfSZhong Wang 			    MAC_STAT_IFSPEED);
303*2a8164dfSZhong Wang 
304*2a8164dfSZhong Wang 			(void) fcoe_mac_set_address(&mac->fm_eport,
305*2a8164dfSZhong Wang 			    mac->fm_primary_addr, B_FALSE);
306*2a8164dfSZhong Wang 
307*2a8164dfSZhong Wang 			FCOE_SET_DEFAULT_FPORT_ADDR(
308*2a8164dfSZhong Wang 			    mac->fm_eport.eport_efh_dst);
309*2a8164dfSZhong Wang 
310*2a8164dfSZhong Wang 			mac->fm_link_state = FCOE_MAC_LINK_STATE_UP;
311*2a8164dfSZhong Wang 			FCOE_LOG(mac->fm_link_name,
312*2a8164dfSZhong Wang 			    "fcoe_mac_notify: arg/%p LINK up", arg, type);
313*2a8164dfSZhong Wang 			fcoe_mac_notify_link_up(mac);
314*2a8164dfSZhong Wang 		} else {
315*2a8164dfSZhong Wang 			if (mac->fm_link_state == FCOE_MAC_LINK_STATE_DOWN) {
316*2a8164dfSZhong Wang 				break;
317*2a8164dfSZhong Wang 			}
318*2a8164dfSZhong Wang 			mac->fm_link_state = FCOE_MAC_LINK_STATE_DOWN;
319*2a8164dfSZhong Wang 			FCOE_LOG(mac->fm_link_name,
320*2a8164dfSZhong Wang 			    "fcoe_mac_notify: arg/%p LINK down", arg, type);
321*2a8164dfSZhong Wang 			fcoe_mac_notify_link_down(mac);
322*2a8164dfSZhong Wang 		}
323*2a8164dfSZhong Wang 		break;
324*2a8164dfSZhong Wang 
325*2a8164dfSZhong Wang 	case MAC_NOTE_TX:
326*2a8164dfSZhong Wang 		/*
327*2a8164dfSZhong Wang 		 * MAC is not so busy now, then wake up fcoe_tx_frame to try
328*2a8164dfSZhong Wang 		 */
329*2a8164dfSZhong Wang 		mutex_enter(&mac->fm_mutex);
330*2a8164dfSZhong Wang 		cv_broadcast(&mac->fm_tx_cv);
331*2a8164dfSZhong Wang 		mutex_exit(&mac->fm_mutex);
332*2a8164dfSZhong Wang 
333*2a8164dfSZhong Wang 		FCOE_LOG("fcoe_mac_notify", "wake up");
334*2a8164dfSZhong Wang 		break;
335*2a8164dfSZhong Wang 
336*2a8164dfSZhong Wang 	default:
337*2a8164dfSZhong Wang 		FCOE_LOG("fcoe_mac_notify", "not supported arg/%p, type/%d",
338*2a8164dfSZhong Wang 		    arg, type);
339*2a8164dfSZhong Wang 		break;
340*2a8164dfSZhong Wang 	}
341*2a8164dfSZhong Wang }
342*2a8164dfSZhong Wang 
343*2a8164dfSZhong Wang int
344*2a8164dfSZhong Wang fcoe_mac_set_address(fcoe_port_t *eport, uint8_t *addr, boolean_t fc_assigned)
345*2a8164dfSZhong Wang {
346*2a8164dfSZhong Wang 	fcoe_mac_t	*mac = EPORT2MAC(eport);
347*2a8164dfSZhong Wang 	int		ret;
348*2a8164dfSZhong Wang 
349*2a8164dfSZhong Wang 	if (bcmp(addr, mac->fm_current_addr, 6) == 0) {
350*2a8164dfSZhong Wang 		return (FCOE_SUCCESS);
351*2a8164dfSZhong Wang 	}
352*2a8164dfSZhong Wang 
353*2a8164dfSZhong Wang 	mutex_enter(&mac->fm_mutex);
354*2a8164dfSZhong Wang 	if (mac->fm_promisc_handle == NULL) {
355*2a8164dfSZhong Wang 		ret = mac_unicast_primary_set(mac->fm_handle, addr);
356*2a8164dfSZhong Wang 		if (ret != 0) {
357*2a8164dfSZhong Wang 			mutex_exit(&mac->fm_mutex);
358*2a8164dfSZhong Wang 			cmn_err(CE_WARN, "Set primary unicast address on %s "
359*2a8164dfSZhong Wang 			    "failed", mac->fm_link_name);
360*2a8164dfSZhong Wang 			FCOE_LOG("fcoe", "mac_unicast_primary_set on %s "
361*2a8164dfSZhong Wang 			    "failed %x", mac->fm_link_name, ret);
362*2a8164dfSZhong Wang 			return (FCOE_FAILURE);
363*2a8164dfSZhong Wang 		}
364*2a8164dfSZhong Wang 	}
365*2a8164dfSZhong Wang 	if (fc_assigned) {
366*2a8164dfSZhong Wang 		bcopy(addr, mac->fm_current_addr, ETHERADDRL);
367*2a8164dfSZhong Wang 	} else {
368*2a8164dfSZhong Wang 		bcopy(mac->fm_primary_addr,
369*2a8164dfSZhong Wang 		    mac->fm_current_addr, ETHERADDRL);
370*2a8164dfSZhong Wang 	}
371*2a8164dfSZhong Wang 	mutex_exit(&mac->fm_mutex);
372*2a8164dfSZhong Wang 	return (FCOE_SUCCESS);
373*2a8164dfSZhong Wang }
374