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