xref: /onnv-gate/usr/src/uts/common/io/fcoe/fcoe_eth.c (revision 10264:1196af6129ec)
19087SZhong.Wang@Sun.COM /*
29087SZhong.Wang@Sun.COM  * CDDL HEADER START
39087SZhong.Wang@Sun.COM  *
49087SZhong.Wang@Sun.COM  * The contents of this file are subject to the terms of the
59087SZhong.Wang@Sun.COM  * Common Development and Distribution License (the "License").
69087SZhong.Wang@Sun.COM  * You may not use this file except in compliance with the License.
79087SZhong.Wang@Sun.COM  *
89087SZhong.Wang@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99087SZhong.Wang@Sun.COM  * or http://www.opensolaris.org/os/licensing.
109087SZhong.Wang@Sun.COM  * See the License for the specific language governing permissions
119087SZhong.Wang@Sun.COM  * and limitations under the License.
129087SZhong.Wang@Sun.COM  *
139087SZhong.Wang@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
149087SZhong.Wang@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
159087SZhong.Wang@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
169087SZhong.Wang@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
179087SZhong.Wang@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
189087SZhong.Wang@Sun.COM  *
199087SZhong.Wang@Sun.COM  * CDDL HEADER END
209087SZhong.Wang@Sun.COM  */
219087SZhong.Wang@Sun.COM /*
229087SZhong.Wang@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
239087SZhong.Wang@Sun.COM  * Use is subject to license terms.
249087SZhong.Wang@Sun.COM  */
259087SZhong.Wang@Sun.COM 
269087SZhong.Wang@Sun.COM #include <sys/stat.h>
279087SZhong.Wang@Sun.COM #include <sys/types.h>
289087SZhong.Wang@Sun.COM #include <netinet/in.h>
299087SZhong.Wang@Sun.COM #include <sys/inttypes.h>
309087SZhong.Wang@Sun.COM #include <sys/strsun.h>
319087SZhong.Wang@Sun.COM #include <sys/mac_client.h>
329087SZhong.Wang@Sun.COM 
339087SZhong.Wang@Sun.COM /*
349087SZhong.Wang@Sun.COM  * FCoE header files
359087SZhong.Wang@Sun.COM  */
369087SZhong.Wang@Sun.COM #include <sys/fcoe/fcoeio.h>
379087SZhong.Wang@Sun.COM #include <sys/fcoe/fcoe_common.h>
389087SZhong.Wang@Sun.COM 
399087SZhong.Wang@Sun.COM /*
409087SZhong.Wang@Sun.COM  * Driver's own header files
419087SZhong.Wang@Sun.COM  */
429087SZhong.Wang@Sun.COM #include <fcoe.h>
439087SZhong.Wang@Sun.COM #include <fcoe_eth.h>
449087SZhong.Wang@Sun.COM #include <fcoe_fc.h>
459087SZhong.Wang@Sun.COM 
469087SZhong.Wang@Sun.COM static void fcoe_rx(void *arg, mac_resource_handle_t mrh,
479087SZhong.Wang@Sun.COM     mblk_t *mp, boolean_t loopback);
489087SZhong.Wang@Sun.COM static void fcoe_mac_notify(void *arg, mac_notify_type_t type);
499087SZhong.Wang@Sun.COM 
509087SZhong.Wang@Sun.COM /*
519087SZhong.Wang@Sun.COM  * Global variable definitions
529087SZhong.Wang@Sun.COM  */
539087SZhong.Wang@Sun.COM 
549087SZhong.Wang@Sun.COM /*
559087SZhong.Wang@Sun.COM  * Internal tunable, used to enable p2p mode
569087SZhong.Wang@Sun.COM  */
579087SZhong.Wang@Sun.COM volatile uint32_t	fcoe_enable_p2pmode = 0;
589087SZhong.Wang@Sun.COM 
599087SZhong.Wang@Sun.COM int
fcoe_open_mac(fcoe_mac_t * mac,int force_promisc,fcoeio_stat_t * err_detail)609087SZhong.Wang@Sun.COM fcoe_open_mac(fcoe_mac_t *mac, int force_promisc, fcoeio_stat_t *err_detail)
619087SZhong.Wang@Sun.COM {
629087SZhong.Wang@Sun.COM 	int		ret;
639087SZhong.Wang@Sun.COM 	int		fcoe_ret;
649087SZhong.Wang@Sun.COM 	char		cli_name[MAXNAMELEN];
659087SZhong.Wang@Sun.COM 	mac_diag_t	diag;
669087SZhong.Wang@Sun.COM 	uint16_t	fm_open_flag = 0;
679087SZhong.Wang@Sun.COM 
689087SZhong.Wang@Sun.COM 	*err_detail = 0;
699087SZhong.Wang@Sun.COM 
709087SZhong.Wang@Sun.COM 	/*
719087SZhong.Wang@Sun.COM 	 * Open MAC interface
729087SZhong.Wang@Sun.COM 	 */
739307Skelly.hu@Sun.COM 	ret = mac_open_by_linkid(mac->fm_linkid, &mac->fm_handle);
749087SZhong.Wang@Sun.COM 	if (ret != 0) {
759307Skelly.hu@Sun.COM 		FCOE_LOG("fcoe", "mac_open_by_linkname %d failed %x",
769307Skelly.hu@Sun.COM 		    mac->fm_linkid, ret);
779087SZhong.Wang@Sun.COM 		return (FCOE_FAILURE);
789087SZhong.Wang@Sun.COM 	}
799087SZhong.Wang@Sun.COM 
809307Skelly.hu@Sun.COM 	(void) sprintf(cli_name, "%s-%d", "fcoe", mac->fm_linkid);
819087SZhong.Wang@Sun.COM 
829087SZhong.Wang@Sun.COM 	ret = mac_client_open(mac->fm_handle,
839087SZhong.Wang@Sun.COM 	    &mac->fm_cli_handle, cli_name, fm_open_flag);
849087SZhong.Wang@Sun.COM 	if (ret != 0) {
859087SZhong.Wang@Sun.COM 		(void) fcoe_close_mac(mac);
869087SZhong.Wang@Sun.COM 		return (FCOE_FAILURE);
879087SZhong.Wang@Sun.COM 	}
889087SZhong.Wang@Sun.COM 	/*
899087SZhong.Wang@Sun.COM 	 * Cache the pointer of the immutable MAC inforamtion and
909087SZhong.Wang@Sun.COM 	 * the current and primary MAC address
919087SZhong.Wang@Sun.COM 	 */
929087SZhong.Wang@Sun.COM 	mac_unicast_primary_get(mac->fm_handle, mac->fm_primary_addr);
939087SZhong.Wang@Sun.COM 	bcopy(mac->fm_primary_addr, mac->fm_current_addr,
949087SZhong.Wang@Sun.COM 	    ETHERADDRL);
959087SZhong.Wang@Sun.COM 
969087SZhong.Wang@Sun.COM 	if (mac_unicast_add(mac->fm_cli_handle, NULL, MAC_UNICAST_PRIMARY,
979087SZhong.Wang@Sun.COM 	    &mac->fm_unicst_handle, 0, &diag)) {
989087SZhong.Wang@Sun.COM 		(void) fcoe_close_mac(mac);
999087SZhong.Wang@Sun.COM 		return (FCOE_FAILURE);
1009087SZhong.Wang@Sun.COM 	}
1019087SZhong.Wang@Sun.COM 
1029087SZhong.Wang@Sun.COM 	if (force_promisc) {
1039087SZhong.Wang@Sun.COM 		mac->fm_force_promisc = B_TRUE;
1049087SZhong.Wang@Sun.COM 	}
1059087SZhong.Wang@Sun.COM 
1069087SZhong.Wang@Sun.COM 	/* Get mtu */
1079087SZhong.Wang@Sun.COM 	mac_sdu_get(mac->fm_handle, NULL, &mac->fm_eport.eport_mtu);
1089087SZhong.Wang@Sun.COM 	if (mac->fm_eport.eport_mtu < FCOE_MIN_MTU_SIZE) {
1099087SZhong.Wang@Sun.COM 		if (!fcoe_enable_p2pmode || mac->fm_eport.eport_mtu < 1500) {
1109087SZhong.Wang@Sun.COM 			/*
1119087SZhong.Wang@Sun.COM 			 * Fail open if fail to get mtu, or we are not
1129087SZhong.Wang@Sun.COM 			 * using p2p, or we are using p2p, but
1139087SZhong.Wang@Sun.COM 			 * the mtu is too small
1149087SZhong.Wang@Sun.COM 			 */
1159087SZhong.Wang@Sun.COM 			(void) fcoe_close_mac(mac);
1169087SZhong.Wang@Sun.COM 			*err_detail = FCOEIOE_NEED_JUMBO_FRAME;
1179087SZhong.Wang@Sun.COM 			return (FCOE_FAILURE);
1189087SZhong.Wang@Sun.COM 		}
1199087SZhong.Wang@Sun.COM 	}
1209087SZhong.Wang@Sun.COM 
1219087SZhong.Wang@Sun.COM 	mac->fm_eport.eport_link_speed =
1229087SZhong.Wang@Sun.COM 	    mac_client_stat_get(mac->fm_cli_handle, MAC_STAT_IFSPEED);
1239087SZhong.Wang@Sun.COM 
1249087SZhong.Wang@Sun.COM 	cv_init(&mac->fm_tx_cv, NULL, CV_DRIVER, NULL);
1259087SZhong.Wang@Sun.COM 	mutex_init(&mac->fm_mutex, NULL, MUTEX_DRIVER, NULL);
1269087SZhong.Wang@Sun.COM 	mac->fm_running = B_TRUE;
1279087SZhong.Wang@Sun.COM 
1289087SZhong.Wang@Sun.COM 	fcoe_ret = FCOE_SUCCESS;
1299087SZhong.Wang@Sun.COM 	return (fcoe_ret);
1309087SZhong.Wang@Sun.COM }
1319087SZhong.Wang@Sun.COM 
1329087SZhong.Wang@Sun.COM int
fcoe_close_mac(fcoe_mac_t * mac)1339087SZhong.Wang@Sun.COM fcoe_close_mac(fcoe_mac_t *mac)
1349087SZhong.Wang@Sun.COM {
1359087SZhong.Wang@Sun.COM 	int ret;
1369087SZhong.Wang@Sun.COM 
1379087SZhong.Wang@Sun.COM 	if (mac->fm_handle == NULL) {
1389087SZhong.Wang@Sun.COM 		return (FCOE_SUCCESS);
1399087SZhong.Wang@Sun.COM 	}
1409087SZhong.Wang@Sun.COM 
1419087SZhong.Wang@Sun.COM 	if (mac->fm_running) {
1429087SZhong.Wang@Sun.COM 		cv_destroy(&mac->fm_tx_cv);
1439087SZhong.Wang@Sun.COM 		mutex_destroy(&mac->fm_mutex);
1449087SZhong.Wang@Sun.COM 		mac->fm_running = B_FALSE;
1459087SZhong.Wang@Sun.COM 	}
1469087SZhong.Wang@Sun.COM 
1479087SZhong.Wang@Sun.COM 	if (mac->fm_promisc_handle != NULL) {
1489087SZhong.Wang@Sun.COM 		mac_promisc_remove(mac->fm_promisc_handle);
1499087SZhong.Wang@Sun.COM 		mac->fm_promisc_handle = NULL;
1509087SZhong.Wang@Sun.COM 	} else {
1519087SZhong.Wang@Sun.COM 		mac_rx_clear(mac->fm_cli_handle);
1529087SZhong.Wang@Sun.COM 	}
1539087SZhong.Wang@Sun.COM 
1549087SZhong.Wang@Sun.COM 	if (mac->fm_notify_handle != NULL) {
1559087SZhong.Wang@Sun.COM 		ret = mac_notify_remove(mac->fm_notify_handle, B_TRUE);
1569087SZhong.Wang@Sun.COM 		ASSERT(ret == 0);
1579087SZhong.Wang@Sun.COM 		mac->fm_notify_handle = NULL;
1589087SZhong.Wang@Sun.COM 	}
1599087SZhong.Wang@Sun.COM 
1609087SZhong.Wang@Sun.COM 	if (mac->fm_unicst_handle != NULL) {
1619087SZhong.Wang@Sun.COM 		(void) mac_unicast_remove(mac->fm_cli_handle,
1629087SZhong.Wang@Sun.COM 		    mac->fm_unicst_handle);
1639087SZhong.Wang@Sun.COM 		mac->fm_unicst_handle = NULL;
1649087SZhong.Wang@Sun.COM 	}
1659087SZhong.Wang@Sun.COM 
1669087SZhong.Wang@Sun.COM 	mac_client_close(mac->fm_cli_handle, 0);
1679087SZhong.Wang@Sun.COM 	mac->fm_cli_handle = NULL;
1689087SZhong.Wang@Sun.COM 
1699087SZhong.Wang@Sun.COM 	(void) mac_close(mac->fm_handle);
1709087SZhong.Wang@Sun.COM 	mac->fm_handle = NULL;
1719087SZhong.Wang@Sun.COM 
1729087SZhong.Wang@Sun.COM 	return (FCOE_SUCCESS);
1739087SZhong.Wang@Sun.COM }
1749087SZhong.Wang@Sun.COM 
1759087SZhong.Wang@Sun.COM int
fcoe_enable_callback(fcoe_mac_t * mac)1769087SZhong.Wang@Sun.COM fcoe_enable_callback(fcoe_mac_t *mac)
1779087SZhong.Wang@Sun.COM {
1789087SZhong.Wang@Sun.COM 	int ret;
1799087SZhong.Wang@Sun.COM 
1809087SZhong.Wang@Sun.COM 	/*
1819087SZhong.Wang@Sun.COM 	 * Set message callback
1829087SZhong.Wang@Sun.COM 	 */
1839087SZhong.Wang@Sun.COM 	if (mac->fm_force_promisc) {
1849087SZhong.Wang@Sun.COM 		ret = mac_promisc_add(mac->fm_cli_handle,
1859087SZhong.Wang@Sun.COM 		    MAC_CLIENT_PROMISC_FILTERED, fcoe_rx, mac,
1869087SZhong.Wang@Sun.COM 		    &mac->fm_promisc_handle,
1879087SZhong.Wang@Sun.COM 		    MAC_PROMISC_FLAGS_NO_TX_LOOP);
1889087SZhong.Wang@Sun.COM 		if (ret != 0) {
1899307Skelly.hu@Sun.COM 			FCOE_LOG("foce", "mac_promisc_add on %d failed %x",
1909307Skelly.hu@Sun.COM 			    mac->fm_linkid, ret);
1919087SZhong.Wang@Sun.COM 			return (FCOE_FAILURE);
1929087SZhong.Wang@Sun.COM 		}
1939087SZhong.Wang@Sun.COM 	} else {
1949087SZhong.Wang@Sun.COM 		mac_rx_set(mac->fm_cli_handle, fcoe_rx, mac);
1959087SZhong.Wang@Sun.COM 	}
1969087SZhong.Wang@Sun.COM 
1979087SZhong.Wang@Sun.COM 	/* Get the link state, if it's up, we will need to notify client */
1989087SZhong.Wang@Sun.COM 	mac->fm_link_state =
1999087SZhong.Wang@Sun.COM 	    mac_stat_get(mac->fm_handle, MAC_STAT_LINK_UP)?
2009087SZhong.Wang@Sun.COM 	    FCOE_MAC_LINK_STATE_UP:FCOE_MAC_LINK_STATE_DOWN;
2019087SZhong.Wang@Sun.COM 
202*10264SZhong.Wang@Sun.COM 	mac->fm_eport.eport_link_speed =
203*10264SZhong.Wang@Sun.COM 	    mac_client_stat_get(mac->fm_cli_handle, MAC_STAT_IFSPEED);
204*10264SZhong.Wang@Sun.COM 
2059087SZhong.Wang@Sun.COM 	/*
2069087SZhong.Wang@Sun.COM 	 * Add a notify function so that we get updates from MAC
2079087SZhong.Wang@Sun.COM 	 */
2089087SZhong.Wang@Sun.COM 	mac->fm_notify_handle = mac_notify_add(mac->fm_handle,
2099087SZhong.Wang@Sun.COM 	    fcoe_mac_notify, (void *)mac);
2109087SZhong.Wang@Sun.COM 	return (FCOE_SUCCESS);
2119087SZhong.Wang@Sun.COM }
2129087SZhong.Wang@Sun.COM 
2139087SZhong.Wang@Sun.COM int
fcoe_disable_callback(fcoe_mac_t * mac)2149087SZhong.Wang@Sun.COM fcoe_disable_callback(fcoe_mac_t *mac)
2159087SZhong.Wang@Sun.COM {
2169087SZhong.Wang@Sun.COM 	int ret;
2179087SZhong.Wang@Sun.COM 
2189087SZhong.Wang@Sun.COM 	if (mac->fm_promisc_handle) {
2199087SZhong.Wang@Sun.COM 		mac_promisc_remove(mac->fm_promisc_handle);
2209087SZhong.Wang@Sun.COM 		mac->fm_promisc_handle = NULL;
2219087SZhong.Wang@Sun.COM 	} else {
2229087SZhong.Wang@Sun.COM 		mac_rx_clear(mac->fm_cli_handle);
2239087SZhong.Wang@Sun.COM 	}
2249087SZhong.Wang@Sun.COM 
2259087SZhong.Wang@Sun.COM 	if (mac->fm_notify_handle) {
2269087SZhong.Wang@Sun.COM 		ret = mac_notify_remove(mac->fm_notify_handle, B_TRUE);
2279087SZhong.Wang@Sun.COM 		ASSERT(ret == 0);
2289087SZhong.Wang@Sun.COM 		mac->fm_notify_handle = NULL;
2299087SZhong.Wang@Sun.COM 	}
2309087SZhong.Wang@Sun.COM 
2319087SZhong.Wang@Sun.COM 	ret = fcoe_mac_set_address(&mac->fm_eport,
2329087SZhong.Wang@Sun.COM 	    mac->fm_primary_addr, B_FALSE);
2339087SZhong.Wang@Sun.COM 	FCOE_SET_DEFAULT_FPORT_ADDR(mac->fm_eport.eport_efh_dst);
2349087SZhong.Wang@Sun.COM 	return (ret);
2359087SZhong.Wang@Sun.COM }
2369087SZhong.Wang@Sun.COM 
2379087SZhong.Wang@Sun.COM /* ARGSUSED */
2389087SZhong.Wang@Sun.COM static void
fcoe_rx(void * arg,mac_resource_handle_t mrh,mblk_t * mp,boolean_t loopback)2399087SZhong.Wang@Sun.COM fcoe_rx(void *arg, mac_resource_handle_t mrh, mblk_t *mp, boolean_t loopback)
2409087SZhong.Wang@Sun.COM {
2419087SZhong.Wang@Sun.COM 	fcoe_mac_t	*mac = (fcoe_mac_t *)arg;
2429087SZhong.Wang@Sun.COM 	mblk_t		*next;
2439087SZhong.Wang@Sun.COM 	fcoe_frame_t	*frm;
2449087SZhong.Wang@Sun.COM 	uint32_t	raw_frame_size, frame_size;
2459087SZhong.Wang@Sun.COM 	uint16_t	frm_type;
2469087SZhong.Wang@Sun.COM 
2479087SZhong.Wang@Sun.COM 	while (mp != NULL) {
2489087SZhong.Wang@Sun.COM 		next = mp->b_next;
2499087SZhong.Wang@Sun.COM 		mp->b_next = NULL;
2509087SZhong.Wang@Sun.COM 		frm_type = ntohs(*(uint16_t *)((uintptr_t)mp->b_rptr + 12));
2519087SZhong.Wang@Sun.COM 
2529087SZhong.Wang@Sun.COM 		if (frm_type != ETHERTYPE_FCOE) {
2539087SZhong.Wang@Sun.COM 			/*
2549087SZhong.Wang@Sun.COM 			 * This mp is not allocated in FCoE, but we must free it
2559087SZhong.Wang@Sun.COM 			 */
2569087SZhong.Wang@Sun.COM 			freeb(mp);
2579087SZhong.Wang@Sun.COM 			mp = next;
2589087SZhong.Wang@Sun.COM 			continue;
2599087SZhong.Wang@Sun.COM 		}
2609087SZhong.Wang@Sun.COM 
2619087SZhong.Wang@Sun.COM 		raw_frame_size = MBLKL(mp);
2629087SZhong.Wang@Sun.COM 		frame_size = raw_frame_size - PADDING_SIZE;
2639087SZhong.Wang@Sun.COM 		frm = fcoe_allocate_frame(&mac->fm_eport, frame_size, mp);
2649087SZhong.Wang@Sun.COM 		if (frm != NULL) {
265*10264SZhong.Wang@Sun.COM 			frm->frm_clock = CURRENT_CLOCK;
2669087SZhong.Wang@Sun.COM 			fcoe_post_frame(frm);
2679087SZhong.Wang@Sun.COM 		}
2689087SZhong.Wang@Sun.COM 
2699087SZhong.Wang@Sun.COM 		mp = next;
2709087SZhong.Wang@Sun.COM 	}
2719087SZhong.Wang@Sun.COM }
2729087SZhong.Wang@Sun.COM 
2739087SZhong.Wang@Sun.COM static void
fcoe_mac_notify(void * arg,mac_notify_type_t type)2749087SZhong.Wang@Sun.COM fcoe_mac_notify(void *arg, mac_notify_type_t type)
2759087SZhong.Wang@Sun.COM {
2769087SZhong.Wang@Sun.COM 	fcoe_mac_t *mac = (fcoe_mac_t *)arg;
2779087SZhong.Wang@Sun.COM 
2789087SZhong.Wang@Sun.COM 	/*
2799087SZhong.Wang@Sun.COM 	 * We assume that the calls to this notification callback are serialized
2809087SZhong.Wang@Sun.COM 	 * by MAC layer
2819087SZhong.Wang@Sun.COM 	 */
2829087SZhong.Wang@Sun.COM 
2839087SZhong.Wang@Sun.COM 	switch (type) {
2849087SZhong.Wang@Sun.COM 	case MAC_NOTE_LINK:
2859087SZhong.Wang@Sun.COM 		/*
2869087SZhong.Wang@Sun.COM 		 * This notification is sent every time the MAC driver
2879087SZhong.Wang@Sun.COM 		 * updates the link state.
2889087SZhong.Wang@Sun.COM 		 */
2899087SZhong.Wang@Sun.COM 		if (mac_stat_get(mac->fm_handle, MAC_STAT_LINK_UP) != 0) {
2909087SZhong.Wang@Sun.COM 			if (mac->fm_link_state == FCOE_MAC_LINK_STATE_UP) {
2919087SZhong.Wang@Sun.COM 				break;
2929087SZhong.Wang@Sun.COM 			}
2939087SZhong.Wang@Sun.COM 			/* Get speed */
2949087SZhong.Wang@Sun.COM 			mac->fm_eport.eport_link_speed =
2959087SZhong.Wang@Sun.COM 			    mac_client_stat_get(mac->fm_cli_handle,
2969087SZhong.Wang@Sun.COM 			    MAC_STAT_IFSPEED);
2979087SZhong.Wang@Sun.COM 			(void) fcoe_mac_set_address(&mac->fm_eport,
2989087SZhong.Wang@Sun.COM 			    mac->fm_primary_addr, B_FALSE);
2999087SZhong.Wang@Sun.COM 
3009087SZhong.Wang@Sun.COM 			FCOE_SET_DEFAULT_FPORT_ADDR(
3019087SZhong.Wang@Sun.COM 			    mac->fm_eport.eport_efh_dst);
3029087SZhong.Wang@Sun.COM 
3039087SZhong.Wang@Sun.COM 			mac->fm_link_state = FCOE_MAC_LINK_STATE_UP;
3049307Skelly.hu@Sun.COM 			FCOE_LOG(NULL,
3059307Skelly.hu@Sun.COM 			    "fcoe_mac_notify: link/%d arg/%p LINK up",
3069307Skelly.hu@Sun.COM 			    mac->fm_linkid, arg, type);
3079087SZhong.Wang@Sun.COM 			fcoe_mac_notify_link_up(mac);
3089087SZhong.Wang@Sun.COM 		} else {
3099087SZhong.Wang@Sun.COM 			if (mac->fm_link_state == FCOE_MAC_LINK_STATE_DOWN) {
3109087SZhong.Wang@Sun.COM 				break;
3119087SZhong.Wang@Sun.COM 			}
3129087SZhong.Wang@Sun.COM 			mac->fm_link_state = FCOE_MAC_LINK_STATE_DOWN;
3139307Skelly.hu@Sun.COM 			FCOE_LOG(NULL,
3149307Skelly.hu@Sun.COM 			    "fcoe_mac_notify: link/%d arg/%p LINK down",
3159307Skelly.hu@Sun.COM 			    mac->fm_linkid, arg, type);
3169087SZhong.Wang@Sun.COM 			fcoe_mac_notify_link_down(mac);
3179087SZhong.Wang@Sun.COM 		}
3189087SZhong.Wang@Sun.COM 		break;
3199087SZhong.Wang@Sun.COM 
3209087SZhong.Wang@Sun.COM 	case MAC_NOTE_TX:
3219087SZhong.Wang@Sun.COM 		/*
3229087SZhong.Wang@Sun.COM 		 * MAC is not so busy now, then wake up fcoe_tx_frame to try
3239087SZhong.Wang@Sun.COM 		 */
3249087SZhong.Wang@Sun.COM 		mutex_enter(&mac->fm_mutex);
3259087SZhong.Wang@Sun.COM 		cv_broadcast(&mac->fm_tx_cv);
3269087SZhong.Wang@Sun.COM 		mutex_exit(&mac->fm_mutex);
3279087SZhong.Wang@Sun.COM 
3289087SZhong.Wang@Sun.COM 		FCOE_LOG("fcoe_mac_notify", "wake up");
3299087SZhong.Wang@Sun.COM 		break;
3309087SZhong.Wang@Sun.COM 
3319087SZhong.Wang@Sun.COM 	default:
3329087SZhong.Wang@Sun.COM 		FCOE_LOG("fcoe_mac_notify", "not supported arg/%p, type/%d",
3339087SZhong.Wang@Sun.COM 		    arg, type);
3349087SZhong.Wang@Sun.COM 		break;
3359087SZhong.Wang@Sun.COM 	}
3369087SZhong.Wang@Sun.COM }
3379087SZhong.Wang@Sun.COM 
3389087SZhong.Wang@Sun.COM int
fcoe_mac_set_address(fcoe_port_t * eport,uint8_t * addr,boolean_t fc_assigned)3399087SZhong.Wang@Sun.COM fcoe_mac_set_address(fcoe_port_t *eport, uint8_t *addr, boolean_t fc_assigned)
3409087SZhong.Wang@Sun.COM {
3419087SZhong.Wang@Sun.COM 	fcoe_mac_t	*mac = EPORT2MAC(eport);
3429087SZhong.Wang@Sun.COM 	int		ret;
3439087SZhong.Wang@Sun.COM 
3449087SZhong.Wang@Sun.COM 	if (bcmp(addr, mac->fm_current_addr, 6) == 0) {
3459087SZhong.Wang@Sun.COM 		return (FCOE_SUCCESS);
3469087SZhong.Wang@Sun.COM 	}
3479087SZhong.Wang@Sun.COM 
3489087SZhong.Wang@Sun.COM 	mutex_enter(&mac->fm_mutex);
3499087SZhong.Wang@Sun.COM 	if (mac->fm_promisc_handle == NULL) {
3509087SZhong.Wang@Sun.COM 		ret = mac_unicast_primary_set(mac->fm_handle, addr);
3519087SZhong.Wang@Sun.COM 		if (ret != 0) {
3529087SZhong.Wang@Sun.COM 			mutex_exit(&mac->fm_mutex);
3539307Skelly.hu@Sun.COM 			FCOE_LOG("fcoe", "mac_unicast_primary_set on %d "
3549307Skelly.hu@Sun.COM 			    "failed %x", mac->fm_linkid, ret);
3559087SZhong.Wang@Sun.COM 			return (FCOE_FAILURE);
3569087SZhong.Wang@Sun.COM 		}
3579087SZhong.Wang@Sun.COM 	}
3589087SZhong.Wang@Sun.COM 	if (fc_assigned) {
3599087SZhong.Wang@Sun.COM 		bcopy(addr, mac->fm_current_addr, ETHERADDRL);
3609087SZhong.Wang@Sun.COM 	} else {
3619087SZhong.Wang@Sun.COM 		bcopy(mac->fm_primary_addr,
3629087SZhong.Wang@Sun.COM 		    mac->fm_current_addr, ETHERADDRL);
3639087SZhong.Wang@Sun.COM 	}
3649087SZhong.Wang@Sun.COM 	mutex_exit(&mac->fm_mutex);
3659087SZhong.Wang@Sun.COM 	return (FCOE_SUCCESS);
3669087SZhong.Wang@Sun.COM }
367