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 /*
279087SZhong.Wang@Sun.COM * The following notice accompanied the original version of this file:
289087SZhong.Wang@Sun.COM *
299087SZhong.Wang@Sun.COM * BSD LICENSE
309087SZhong.Wang@Sun.COM *
319087SZhong.Wang@Sun.COM * Copyright(c) 2007 Intel Corporation. All rights reserved.
329087SZhong.Wang@Sun.COM * All rights reserved.
339087SZhong.Wang@Sun.COM *
349087SZhong.Wang@Sun.COM * Redistribution and use in source and binary forms, with or without
359087SZhong.Wang@Sun.COM * modification, are permitted provided that the following conditions
369087SZhong.Wang@Sun.COM * are met:
379087SZhong.Wang@Sun.COM *
389087SZhong.Wang@Sun.COM * * Redistributions of source code must retain the above copyright
399087SZhong.Wang@Sun.COM * notice, this list of conditions and the following disclaimer.
409087SZhong.Wang@Sun.COM * * Redistributions in binary form must reproduce the above copyright
419087SZhong.Wang@Sun.COM * notice, this list of conditions and the following disclaimer in
429087SZhong.Wang@Sun.COM * the documentation and/or other materials provided with the
439087SZhong.Wang@Sun.COM * distribution.
449087SZhong.Wang@Sun.COM * * Neither the name of Intel Corporation nor the names of its
459087SZhong.Wang@Sun.COM * contributors may be used to endorse or promote products derived
469087SZhong.Wang@Sun.COM * from this software without specific prior written permission.
479087SZhong.Wang@Sun.COM *
489087SZhong.Wang@Sun.COM * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
499087SZhong.Wang@Sun.COM * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
509087SZhong.Wang@Sun.COM * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
519087SZhong.Wang@Sun.COM * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
529087SZhong.Wang@Sun.COM * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
539087SZhong.Wang@Sun.COM * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
549087SZhong.Wang@Sun.COM * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
559087SZhong.Wang@Sun.COM * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
569087SZhong.Wang@Sun.COM * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
579087SZhong.Wang@Sun.COM * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
589087SZhong.Wang@Sun.COM * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
599087SZhong.Wang@Sun.COM */
609087SZhong.Wang@Sun.COM
619087SZhong.Wang@Sun.COM /*
629087SZhong.Wang@Sun.COM * Common FCoE interface interacts with MAC and FCoE clients, managing
639087SZhong.Wang@Sun.COM * FCoE ports, doing MAC address discovery/managment, and FC frame
649087SZhong.Wang@Sun.COM * encapsulation/decapsulation
659087SZhong.Wang@Sun.COM */
669087SZhong.Wang@Sun.COM
679087SZhong.Wang@Sun.COM #include <sys/stat.h>
689087SZhong.Wang@Sun.COM #include <sys/conf.h>
699087SZhong.Wang@Sun.COM #include <sys/file.h>
709087SZhong.Wang@Sun.COM #include <sys/cred.h>
719087SZhong.Wang@Sun.COM
729087SZhong.Wang@Sun.COM #include <sys/ddi.h>
739087SZhong.Wang@Sun.COM #include <sys/sunddi.h>
749087SZhong.Wang@Sun.COM #include <sys/sunndi.h>
759087SZhong.Wang@Sun.COM #include <sys/byteorder.h>
769087SZhong.Wang@Sun.COM #include <sys/atomic.h>
779087SZhong.Wang@Sun.COM #include <sys/sysmacros.h>
789087SZhong.Wang@Sun.COM #include <sys/cmn_err.h>
799087SZhong.Wang@Sun.COM #include <sys/crc32.h>
809087SZhong.Wang@Sun.COM #include <sys/strsubr.h>
819087SZhong.Wang@Sun.COM
829087SZhong.Wang@Sun.COM #include <sys/mac_client.h>
839087SZhong.Wang@Sun.COM
849087SZhong.Wang@Sun.COM /*
859087SZhong.Wang@Sun.COM * FCoE header files
869087SZhong.Wang@Sun.COM */
879087SZhong.Wang@Sun.COM #include <sys/fcoe/fcoeio.h>
889087SZhong.Wang@Sun.COM #include <sys/fcoe/fcoe_common.h>
899087SZhong.Wang@Sun.COM
909087SZhong.Wang@Sun.COM /*
919087SZhong.Wang@Sun.COM * Driver's own header files
929087SZhong.Wang@Sun.COM */
939087SZhong.Wang@Sun.COM #include <fcoe.h>
949087SZhong.Wang@Sun.COM #include <fcoe_fc.h>
959087SZhong.Wang@Sun.COM #include <fcoe_eth.h>
969087SZhong.Wang@Sun.COM
979087SZhong.Wang@Sun.COM /*
989087SZhong.Wang@Sun.COM * Function forward declaration
999087SZhong.Wang@Sun.COM */
1009087SZhong.Wang@Sun.COM static int fcoe_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
1019087SZhong.Wang@Sun.COM static int fcoe_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
1029087SZhong.Wang@Sun.COM static int fcoe_bus_ctl(dev_info_t *fca_dip, dev_info_t *rip,
1039087SZhong.Wang@Sun.COM ddi_ctl_enum_t op, void *arg, void *result);
1049087SZhong.Wang@Sun.COM static int fcoe_open(dev_t *devp, int flag, int otype, cred_t *credp);
1059087SZhong.Wang@Sun.COM static int fcoe_close(dev_t dev, int flag, int otype, cred_t *credp);
1069087SZhong.Wang@Sun.COM static int fcoe_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
1079087SZhong.Wang@Sun.COM cred_t *credp, int *rval);
1089087SZhong.Wang@Sun.COM static int fcoe_copyin_iocdata(intptr_t data, int mode, fcoeio_t **fcoeio,
1099087SZhong.Wang@Sun.COM void **ibuf, void **abuf, void **obuf);
1109087SZhong.Wang@Sun.COM static int fcoe_copyout_iocdata(intptr_t data, int mode, fcoeio_t *fcoeio,
1119087SZhong.Wang@Sun.COM void *obuf);
1129087SZhong.Wang@Sun.COM static int fcoe_iocmd(fcoe_soft_state_t *ss, intptr_t data, int mode);
1139087SZhong.Wang@Sun.COM static int fcoe_attach_init(fcoe_soft_state_t *this_ss);
1149087SZhong.Wang@Sun.COM static int fcoe_detach_uninit(fcoe_soft_state_t *this_ss);
1159087SZhong.Wang@Sun.COM static int fcoe_initchild(dev_info_t *fcoe_dip, dev_info_t *client_dip);
1169087SZhong.Wang@Sun.COM static int fcoe_uninitchild(dev_info_t *fcoe_dip, dev_info_t *client_dip);
1179087SZhong.Wang@Sun.COM static void fcoe_init_wwn_from_mac(uint8_t *wwn, uint8_t *mac,
1189087SZhong.Wang@Sun.COM int is_pwwn, uint8_t idx);
1199307Skelly.hu@Sun.COM static fcoe_mac_t *fcoe_create_mac_by_id(datalink_id_t linkid);
1209087SZhong.Wang@Sun.COM static int fcoe_cmp_wwn(fcoe_mac_t *checkedmac);
1219087SZhong.Wang@Sun.COM static void fcoe_watchdog(void *arg);
1229087SZhong.Wang@Sun.COM static void fcoe_worker_init();
1239087SZhong.Wang@Sun.COM static int fcoe_worker_fini();
1249087SZhong.Wang@Sun.COM static void fcoe_worker_frame();
1259087SZhong.Wang@Sun.COM static int fcoe_get_port_list(fcoe_port_instance_t *ports, int count);
126*11231SKevin.Yu@Sun.COM static boolean_t fcoe_mac_existed(fcoe_mac_t *pmac);
1279087SZhong.Wang@Sun.COM
1289087SZhong.Wang@Sun.COM /*
1299087SZhong.Wang@Sun.COM * Driver identificaton stuff
1309087SZhong.Wang@Sun.COM */
1319087SZhong.Wang@Sun.COM static struct cb_ops fcoe_cb_ops = {
1329087SZhong.Wang@Sun.COM fcoe_open,
1339087SZhong.Wang@Sun.COM fcoe_close,
1349087SZhong.Wang@Sun.COM nodev,
1359087SZhong.Wang@Sun.COM nodev,
1369087SZhong.Wang@Sun.COM nodev,
1379087SZhong.Wang@Sun.COM nodev,
1389087SZhong.Wang@Sun.COM nodev,
1399087SZhong.Wang@Sun.COM fcoe_ioctl,
1409087SZhong.Wang@Sun.COM nodev,
1419087SZhong.Wang@Sun.COM nodev,
1429087SZhong.Wang@Sun.COM nodev,
1439087SZhong.Wang@Sun.COM nochpoll,
1449087SZhong.Wang@Sun.COM ddi_prop_op,
1459087SZhong.Wang@Sun.COM 0,
1469087SZhong.Wang@Sun.COM D_MP | D_NEW | D_HOTPLUG,
1479087SZhong.Wang@Sun.COM CB_REV,
1489087SZhong.Wang@Sun.COM nodev,
1499087SZhong.Wang@Sun.COM nodev
1509087SZhong.Wang@Sun.COM };
1519087SZhong.Wang@Sun.COM
1529087SZhong.Wang@Sun.COM static struct bus_ops fcoe_busops = {
1539087SZhong.Wang@Sun.COM BUSO_REV,
1549087SZhong.Wang@Sun.COM nullbusmap, /* bus_map */
1559087SZhong.Wang@Sun.COM NULL, /* bus_get_intrspec */
1569087SZhong.Wang@Sun.COM NULL, /* bus_add_intrspec */
1579087SZhong.Wang@Sun.COM NULL, /* bus_remove_intrspec */
1589087SZhong.Wang@Sun.COM i_ddi_map_fault, /* bus_map_fault */
1599087SZhong.Wang@Sun.COM ddi_dma_map, /* bus_dma_map */
1609087SZhong.Wang@Sun.COM ddi_dma_allochdl, /* bus_dma_allochdl */
1619087SZhong.Wang@Sun.COM ddi_dma_freehdl, /* bus_dma_freehdl */
1629087SZhong.Wang@Sun.COM ddi_dma_bindhdl, /* bus_dma_bindhdl */
1639087SZhong.Wang@Sun.COM ddi_dma_unbindhdl, /* bus_unbindhdl */
1649087SZhong.Wang@Sun.COM ddi_dma_flush, /* bus_dma_flush */
1659087SZhong.Wang@Sun.COM ddi_dma_win, /* bus_dma_win */
1669087SZhong.Wang@Sun.COM ddi_dma_mctl, /* bus_dma_ctl */
1679087SZhong.Wang@Sun.COM fcoe_bus_ctl, /* bus_ctl */
1689087SZhong.Wang@Sun.COM ddi_bus_prop_op, /* bus_prop_op */
1699087SZhong.Wang@Sun.COM NULL, /* bus_get_eventcookie */
1709087SZhong.Wang@Sun.COM NULL, /* bus_add_eventcall */
1719087SZhong.Wang@Sun.COM NULL, /* bus_remove_event */
1729087SZhong.Wang@Sun.COM NULL, /* bus_post_event */
1739087SZhong.Wang@Sun.COM NULL, /* bus_intr_ctl */
1749087SZhong.Wang@Sun.COM NULL, /* bus_config */
1759087SZhong.Wang@Sun.COM NULL, /* bus_unconfig */
1769087SZhong.Wang@Sun.COM NULL, /* bus_fm_init */
1779087SZhong.Wang@Sun.COM NULL, /* bus_fm_fini */
1789087SZhong.Wang@Sun.COM NULL, /* bus_fm_access_enter */
1799087SZhong.Wang@Sun.COM NULL, /* bus_fm_access_exit */
1809087SZhong.Wang@Sun.COM NULL, /* bus_power */
1819087SZhong.Wang@Sun.COM NULL
1829087SZhong.Wang@Sun.COM };
1839087SZhong.Wang@Sun.COM
1849087SZhong.Wang@Sun.COM static struct dev_ops fcoe_ops = {
1859087SZhong.Wang@Sun.COM DEVO_REV,
1869087SZhong.Wang@Sun.COM 0,
1879087SZhong.Wang@Sun.COM nodev,
1889087SZhong.Wang@Sun.COM nulldev,
1899087SZhong.Wang@Sun.COM nulldev,
1909087SZhong.Wang@Sun.COM fcoe_attach,
1919087SZhong.Wang@Sun.COM fcoe_detach,
1929087SZhong.Wang@Sun.COM nodev,
1939087SZhong.Wang@Sun.COM &fcoe_cb_ops,
1949087SZhong.Wang@Sun.COM &fcoe_busops,
1959328SZhong.Wang@Sun.COM ddi_power,
1969328SZhong.Wang@Sun.COM ddi_quiesce_not_needed
1979087SZhong.Wang@Sun.COM };
1989087SZhong.Wang@Sun.COM
199*11231SKevin.Yu@Sun.COM #define FCOE_VERSION "20091123-1.02"
2009087SZhong.Wang@Sun.COM #define FCOE_NAME "FCoE Transport v" FCOE_VERSION
2019087SZhong.Wang@Sun.COM #define TASKQ_NAME_LEN 32
2029087SZhong.Wang@Sun.COM
2039087SZhong.Wang@Sun.COM static struct modldrv modldrv = {
2049087SZhong.Wang@Sun.COM &mod_driverops,
2059087SZhong.Wang@Sun.COM FCOE_NAME,
2069087SZhong.Wang@Sun.COM &fcoe_ops,
2079087SZhong.Wang@Sun.COM };
2089087SZhong.Wang@Sun.COM
2099087SZhong.Wang@Sun.COM static struct modlinkage modlinkage = {
2109087SZhong.Wang@Sun.COM MODREV_1, &modldrv, NULL
2119087SZhong.Wang@Sun.COM };
2129087SZhong.Wang@Sun.COM
2139087SZhong.Wang@Sun.COM /*
2149087SZhong.Wang@Sun.COM * TRACE for all FCoE related modules
2159087SZhong.Wang@Sun.COM */
2169087SZhong.Wang@Sun.COM static kmutex_t fcoe_trace_buf_lock;
2179087SZhong.Wang@Sun.COM static int fcoe_trace_buf_curndx = 0;
2189087SZhong.Wang@Sun.COM static int fcoe_trace_on = 1;
2199087SZhong.Wang@Sun.COM static caddr_t fcoe_trace_buf = NULL;
2209087SZhong.Wang@Sun.COM static clock_t fcoe_trace_start = 0;
2219087SZhong.Wang@Sun.COM static caddr_t ftb = NULL;
2229087SZhong.Wang@Sun.COM static int fcoe_trace_buf_size = (1 * 1024 * 1024);
2239087SZhong.Wang@Sun.COM
2249087SZhong.Wang@Sun.COM /*
2259087SZhong.Wang@Sun.COM * Driver's global variables
2269087SZhong.Wang@Sun.COM */
22710264SZhong.Wang@Sun.COM const fcoe_ver_e fcoe_ver_now = FCOE_VER_NOW;
2289087SZhong.Wang@Sun.COM static void *fcoe_state = NULL;
2299087SZhong.Wang@Sun.COM fcoe_soft_state_t *fcoe_global_ss = NULL;
2309087SZhong.Wang@Sun.COM int fcoe_use_ext_log = 1;
2319087SZhong.Wang@Sun.COM
2329087SZhong.Wang@Sun.COM static ddi_taskq_t *fcoe_worker_taskq;
2339087SZhong.Wang@Sun.COM static fcoe_worker_t *fcoe_workers;
2349087SZhong.Wang@Sun.COM static uint32_t fcoe_nworkers_running;
2359087SZhong.Wang@Sun.COM
2369087SZhong.Wang@Sun.COM const char *fcoe_workers_num = "workers-number";
2379087SZhong.Wang@Sun.COM volatile int fcoe_nworkers;
2389087SZhong.Wang@Sun.COM
2399087SZhong.Wang@Sun.COM /*
2409087SZhong.Wang@Sun.COM * Common loadable module entry points _init, _fini, _info
2419087SZhong.Wang@Sun.COM */
2429087SZhong.Wang@Sun.COM
2439087SZhong.Wang@Sun.COM int
_init(void)2449087SZhong.Wang@Sun.COM _init(void)
2459087SZhong.Wang@Sun.COM {
2469087SZhong.Wang@Sun.COM int ret;
2479087SZhong.Wang@Sun.COM
2489087SZhong.Wang@Sun.COM ret = ddi_soft_state_init(&fcoe_state, sizeof (fcoe_soft_state_t), 0);
2499087SZhong.Wang@Sun.COM if (ret == 0) {
2509087SZhong.Wang@Sun.COM ret = mod_install(&modlinkage);
2519087SZhong.Wang@Sun.COM if (ret != 0) {
2529087SZhong.Wang@Sun.COM ddi_soft_state_fini(&fcoe_state);
2539087SZhong.Wang@Sun.COM } else {
2549087SZhong.Wang@Sun.COM fcoe_trace_start = ddi_get_lbolt();
2559087SZhong.Wang@Sun.COM ftb = kmem_zalloc(fcoe_trace_buf_size,
2569087SZhong.Wang@Sun.COM KM_SLEEP);
2579087SZhong.Wang@Sun.COM fcoe_trace_buf = ftb;
2589087SZhong.Wang@Sun.COM mutex_init(&fcoe_trace_buf_lock, NULL, MUTEX_DRIVER, 0);
2599087SZhong.Wang@Sun.COM }
2609087SZhong.Wang@Sun.COM }
2619087SZhong.Wang@Sun.COM
2629087SZhong.Wang@Sun.COM FCOE_LOG("fcoe", "exit _init with %x", ret);
2639087SZhong.Wang@Sun.COM
2649087SZhong.Wang@Sun.COM return (ret);
2659087SZhong.Wang@Sun.COM }
2669087SZhong.Wang@Sun.COM
2679087SZhong.Wang@Sun.COM int
_fini(void)2689087SZhong.Wang@Sun.COM _fini(void)
2699087SZhong.Wang@Sun.COM {
2709087SZhong.Wang@Sun.COM int ret;
2719087SZhong.Wang@Sun.COM
2729087SZhong.Wang@Sun.COM ret = mod_remove(&modlinkage);
2739087SZhong.Wang@Sun.COM if (ret == 0) {
2749087SZhong.Wang@Sun.COM ddi_soft_state_fini(&fcoe_state);
2759087SZhong.Wang@Sun.COM }
2769087SZhong.Wang@Sun.COM
2779087SZhong.Wang@Sun.COM FCOE_LOG("fcoe", "exit _fini with %x", ret);
2789087SZhong.Wang@Sun.COM if (ret == 0) {
2799087SZhong.Wang@Sun.COM kmem_free(fcoe_trace_buf, fcoe_trace_buf_size);
2809087SZhong.Wang@Sun.COM mutex_destroy(&fcoe_trace_buf_lock);
2819087SZhong.Wang@Sun.COM }
2829087SZhong.Wang@Sun.COM
2839087SZhong.Wang@Sun.COM return (ret);
2849087SZhong.Wang@Sun.COM }
2859087SZhong.Wang@Sun.COM
2869087SZhong.Wang@Sun.COM int
_info(struct modinfo * modinfop)2879087SZhong.Wang@Sun.COM _info(struct modinfo *modinfop)
2889087SZhong.Wang@Sun.COM {
2899087SZhong.Wang@Sun.COM return (mod_info(&modlinkage, modinfop));
2909087SZhong.Wang@Sun.COM }
2919087SZhong.Wang@Sun.COM
2929087SZhong.Wang@Sun.COM /*
2939087SZhong.Wang@Sun.COM * Autoconfiguration entry points: attach, detach, getinfo
2949087SZhong.Wang@Sun.COM */
2959087SZhong.Wang@Sun.COM
2969087SZhong.Wang@Sun.COM static int
fcoe_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)2979087SZhong.Wang@Sun.COM fcoe_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
2989087SZhong.Wang@Sun.COM {
2999087SZhong.Wang@Sun.COM int ret = DDI_FAILURE;
3009087SZhong.Wang@Sun.COM int fcoe_ret;
3019087SZhong.Wang@Sun.COM int instance;
3029087SZhong.Wang@Sun.COM fcoe_soft_state_t *ss;
3039087SZhong.Wang@Sun.COM
3049087SZhong.Wang@Sun.COM instance = ddi_get_instance(dip);
3059087SZhong.Wang@Sun.COM switch (cmd) {
3069087SZhong.Wang@Sun.COM case DDI_ATTACH:
3079087SZhong.Wang@Sun.COM ret = ddi_soft_state_zalloc(fcoe_state, instance);
3089087SZhong.Wang@Sun.COM if (ret == DDI_FAILURE) {
3099087SZhong.Wang@Sun.COM FCOE_LOG(0, "soft_state_zalloc-%x/%x", ret, instance);
3109087SZhong.Wang@Sun.COM return (ret);
3119087SZhong.Wang@Sun.COM }
3129087SZhong.Wang@Sun.COM
3139087SZhong.Wang@Sun.COM ss = ddi_get_soft_state(fcoe_state, instance);
3149087SZhong.Wang@Sun.COM ss->ss_dip = dip;
3159087SZhong.Wang@Sun.COM
3169087SZhong.Wang@Sun.COM ASSERT(fcoe_global_ss == NULL);
3179087SZhong.Wang@Sun.COM fcoe_global_ss = ss;
3189087SZhong.Wang@Sun.COM fcoe_ret = fcoe_attach_init(ss);
3199087SZhong.Wang@Sun.COM if (fcoe_ret == FCOE_SUCCESS) {
3209087SZhong.Wang@Sun.COM ret = DDI_SUCCESS;
3219087SZhong.Wang@Sun.COM }
3229087SZhong.Wang@Sun.COM
3239087SZhong.Wang@Sun.COM FCOE_LOG("fcoe", "fcoe_attach_init end with-%x", fcoe_ret);
3249087SZhong.Wang@Sun.COM break;
3259087SZhong.Wang@Sun.COM
3269087SZhong.Wang@Sun.COM case DDI_RESUME:
3279087SZhong.Wang@Sun.COM ret = DDI_SUCCESS;
3289087SZhong.Wang@Sun.COM break;
3299087SZhong.Wang@Sun.COM
3309087SZhong.Wang@Sun.COM default:
3319087SZhong.Wang@Sun.COM FCOE_LOG("fcoe", "unsupported attach cmd-%x", cmd);
3329087SZhong.Wang@Sun.COM break;
3339087SZhong.Wang@Sun.COM }
3349087SZhong.Wang@Sun.COM
3359087SZhong.Wang@Sun.COM return (ret);
3369087SZhong.Wang@Sun.COM }
3379087SZhong.Wang@Sun.COM
3389087SZhong.Wang@Sun.COM static int
fcoe_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)3399087SZhong.Wang@Sun.COM fcoe_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
3409087SZhong.Wang@Sun.COM {
3419087SZhong.Wang@Sun.COM int ret = DDI_FAILURE;
3429087SZhong.Wang@Sun.COM int fcoe_ret;
3439087SZhong.Wang@Sun.COM int instance;
3449087SZhong.Wang@Sun.COM fcoe_soft_state_t *ss;
3459087SZhong.Wang@Sun.COM
3469087SZhong.Wang@Sun.COM instance = ddi_get_instance(dip);
3479087SZhong.Wang@Sun.COM ss = ddi_get_soft_state(fcoe_state, instance);
3489087SZhong.Wang@Sun.COM if (ss == NULL) {
3499087SZhong.Wang@Sun.COM return (ret);
3509087SZhong.Wang@Sun.COM }
3519087SZhong.Wang@Sun.COM
3529087SZhong.Wang@Sun.COM ASSERT(fcoe_global_ss != NULL);
3539087SZhong.Wang@Sun.COM ASSERT(dip == fcoe_global_ss->ss_dip);
3549087SZhong.Wang@Sun.COM switch (cmd) {
3559087SZhong.Wang@Sun.COM case DDI_DETACH:
3569087SZhong.Wang@Sun.COM fcoe_ret = fcoe_detach_uninit(ss);
3579087SZhong.Wang@Sun.COM if (fcoe_ret == FCOE_SUCCESS) {
3589087SZhong.Wang@Sun.COM ret = DDI_SUCCESS;
3599087SZhong.Wang@Sun.COM fcoe_global_ss = NULL;
3609087SZhong.Wang@Sun.COM }
3619087SZhong.Wang@Sun.COM
3629087SZhong.Wang@Sun.COM break;
3639087SZhong.Wang@Sun.COM
3649087SZhong.Wang@Sun.COM case DDI_SUSPEND:
3659087SZhong.Wang@Sun.COM ret = DDI_SUCCESS;
3669087SZhong.Wang@Sun.COM break;
3679087SZhong.Wang@Sun.COM
3689087SZhong.Wang@Sun.COM default:
3699087SZhong.Wang@Sun.COM FCOE_LOG(0, "unsupported detach cmd-%x", cmd);
3709087SZhong.Wang@Sun.COM break;
3719087SZhong.Wang@Sun.COM }
3729087SZhong.Wang@Sun.COM
3739087SZhong.Wang@Sun.COM return (ret);
3749087SZhong.Wang@Sun.COM }
3759087SZhong.Wang@Sun.COM
3769087SZhong.Wang@Sun.COM /*
3779087SZhong.Wang@Sun.COM * FCA driver's intercepted bus control operations.
3789087SZhong.Wang@Sun.COM */
3799087SZhong.Wang@Sun.COM static int
fcoe_bus_ctl(dev_info_t * fcoe_dip,dev_info_t * rip,ddi_ctl_enum_t op,void * clientarg,void * result)3809087SZhong.Wang@Sun.COM fcoe_bus_ctl(dev_info_t *fcoe_dip, dev_info_t *rip,
3819087SZhong.Wang@Sun.COM ddi_ctl_enum_t op, void *clientarg, void *result)
3829087SZhong.Wang@Sun.COM {
3839087SZhong.Wang@Sun.COM int ret;
3849087SZhong.Wang@Sun.COM switch (op) {
3859087SZhong.Wang@Sun.COM case DDI_CTLOPS_REPORTDEV:
3869087SZhong.Wang@Sun.COM case DDI_CTLOPS_IOMIN:
3879087SZhong.Wang@Sun.COM ret = DDI_SUCCESS;
3889087SZhong.Wang@Sun.COM break;
3899087SZhong.Wang@Sun.COM
3909087SZhong.Wang@Sun.COM case DDI_CTLOPS_INITCHILD:
3919087SZhong.Wang@Sun.COM ret = fcoe_initchild(fcoe_dip, (dev_info_t *)clientarg);
3929087SZhong.Wang@Sun.COM break;
3939087SZhong.Wang@Sun.COM
3949087SZhong.Wang@Sun.COM case DDI_CTLOPS_UNINITCHILD:
3959087SZhong.Wang@Sun.COM ret = fcoe_uninitchild(fcoe_dip, (dev_info_t *)clientarg);
3969087SZhong.Wang@Sun.COM break;
3979087SZhong.Wang@Sun.COM
3989087SZhong.Wang@Sun.COM default:
3999087SZhong.Wang@Sun.COM ret = ddi_ctlops(fcoe_dip, rip, op, clientarg, result);
4009087SZhong.Wang@Sun.COM break;
4019087SZhong.Wang@Sun.COM }
4029087SZhong.Wang@Sun.COM
4039087SZhong.Wang@Sun.COM return (ret);
4049087SZhong.Wang@Sun.COM }
4059087SZhong.Wang@Sun.COM
4069087SZhong.Wang@Sun.COM /*
4079087SZhong.Wang@Sun.COM * We need specify the dev address for client driver's instance, or we
4089087SZhong.Wang@Sun.COM * can't online client driver's instance.
4099087SZhong.Wang@Sun.COM */
4109087SZhong.Wang@Sun.COM /* ARGSUSED */
4119087SZhong.Wang@Sun.COM static int
fcoe_initchild(dev_info_t * fcoe_dip,dev_info_t * client_dip)4129087SZhong.Wang@Sun.COM fcoe_initchild(dev_info_t *fcoe_dip, dev_info_t *client_dip)
4139087SZhong.Wang@Sun.COM {
41410264SZhong.Wang@Sun.COM char client_addr[FCOE_STR_LEN];
41510264SZhong.Wang@Sun.COM int rval;
4169087SZhong.Wang@Sun.COM
41710264SZhong.Wang@Sun.COM rval = ddi_prop_get_int(DDI_DEV_T_ANY, client_dip,
41810264SZhong.Wang@Sun.COM DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "mac_id", -1);
41910264SZhong.Wang@Sun.COM if (rval == -1) {
42010264SZhong.Wang@Sun.COM FCOE_LOG(__FUNCTION__, "no mac_id property: %p", client_dip);
42110264SZhong.Wang@Sun.COM return (DDI_FAILURE);
4229087SZhong.Wang@Sun.COM }
4239087SZhong.Wang@Sun.COM
42410264SZhong.Wang@Sun.COM bzero(client_addr, FCOE_STR_LEN);
42510264SZhong.Wang@Sun.COM (void) sprintf((char *)client_addr, "%x,0", rval);
42610264SZhong.Wang@Sun.COM ddi_set_name_addr(client_dip, client_addr);
4279087SZhong.Wang@Sun.COM return (DDI_SUCCESS);
4289087SZhong.Wang@Sun.COM }
4299087SZhong.Wang@Sun.COM
4309087SZhong.Wang@Sun.COM /* ARGSUSED */
4319087SZhong.Wang@Sun.COM static int
fcoe_uninitchild(dev_info_t * fcoe_dip,dev_info_t * client_dip)4329087SZhong.Wang@Sun.COM fcoe_uninitchild(dev_info_t *fcoe_dip, dev_info_t *client_dip)
4339087SZhong.Wang@Sun.COM {
4349087SZhong.Wang@Sun.COM ddi_set_name_addr(client_dip, NULL);
4359087SZhong.Wang@Sun.COM return (DDI_SUCCESS);
4369087SZhong.Wang@Sun.COM }
4379087SZhong.Wang@Sun.COM
4389087SZhong.Wang@Sun.COM /*
4399087SZhong.Wang@Sun.COM * Device access entry points
4409087SZhong.Wang@Sun.COM */
4419087SZhong.Wang@Sun.COM static int
fcoe_open(dev_t * devp,int flag,int otype,cred_t * credp)4429087SZhong.Wang@Sun.COM fcoe_open(dev_t *devp, int flag, int otype, cred_t *credp)
4439087SZhong.Wang@Sun.COM {
4449087SZhong.Wang@Sun.COM int instance;
4459087SZhong.Wang@Sun.COM fcoe_soft_state_t *ss;
4469087SZhong.Wang@Sun.COM
4479087SZhong.Wang@Sun.COM if (otype != OTYP_CHR) {
4489087SZhong.Wang@Sun.COM return (EINVAL);
4499087SZhong.Wang@Sun.COM }
4509087SZhong.Wang@Sun.COM
4519087SZhong.Wang@Sun.COM /*
4529087SZhong.Wang@Sun.COM * Since this is for debugging only, only allow root to issue ioctl now
4539087SZhong.Wang@Sun.COM */
4549087SZhong.Wang@Sun.COM if (drv_priv(credp) != 0) {
4559087SZhong.Wang@Sun.COM return (EPERM);
4569087SZhong.Wang@Sun.COM }
4579087SZhong.Wang@Sun.COM
4589087SZhong.Wang@Sun.COM instance = (int)getminor(*devp);
4599087SZhong.Wang@Sun.COM ss = ddi_get_soft_state(fcoe_state, instance);
4609087SZhong.Wang@Sun.COM if (ss == NULL) {
4619087SZhong.Wang@Sun.COM return (ENXIO);
4629087SZhong.Wang@Sun.COM }
4639087SZhong.Wang@Sun.COM
4649087SZhong.Wang@Sun.COM mutex_enter(&ss->ss_ioctl_mutex);
4659087SZhong.Wang@Sun.COM if (ss->ss_ioctl_flags & FCOE_IOCTL_FLAG_EXCL) {
4669087SZhong.Wang@Sun.COM /*
4679087SZhong.Wang@Sun.COM * It is already open for exclusive access.
4689087SZhong.Wang@Sun.COM * So shut the door on this caller.
4699087SZhong.Wang@Sun.COM */
4709087SZhong.Wang@Sun.COM mutex_exit(&ss->ss_ioctl_mutex);
4719087SZhong.Wang@Sun.COM return (EBUSY);
4729087SZhong.Wang@Sun.COM }
4739087SZhong.Wang@Sun.COM
4749087SZhong.Wang@Sun.COM if (flag & FEXCL) {
4759087SZhong.Wang@Sun.COM if (ss->ss_ioctl_flags & FCOE_IOCTL_FLAG_OPEN) {
4769087SZhong.Wang@Sun.COM /*
4779087SZhong.Wang@Sun.COM * Exclusive operation not possible
4789087SZhong.Wang@Sun.COM * as it is already opened
4799087SZhong.Wang@Sun.COM */
4809087SZhong.Wang@Sun.COM mutex_exit(&ss->ss_ioctl_mutex);
4819087SZhong.Wang@Sun.COM return (EBUSY);
4829087SZhong.Wang@Sun.COM }
4839087SZhong.Wang@Sun.COM ss->ss_ioctl_flags |= FCOE_IOCTL_FLAG_EXCL;
4849087SZhong.Wang@Sun.COM }
4859087SZhong.Wang@Sun.COM
4869087SZhong.Wang@Sun.COM ss->ss_ioctl_flags |= FCOE_IOCTL_FLAG_OPEN;
4879087SZhong.Wang@Sun.COM mutex_exit(&ss->ss_ioctl_mutex);
4889087SZhong.Wang@Sun.COM
4899087SZhong.Wang@Sun.COM return (0);
4909087SZhong.Wang@Sun.COM }
4919087SZhong.Wang@Sun.COM
4929087SZhong.Wang@Sun.COM /* ARGSUSED */
4939087SZhong.Wang@Sun.COM static int
fcoe_close(dev_t dev,int flag,int otype,cred_t * credp)4949087SZhong.Wang@Sun.COM fcoe_close(dev_t dev, int flag, int otype, cred_t *credp)
4959087SZhong.Wang@Sun.COM {
4969087SZhong.Wang@Sun.COM int instance;
4979087SZhong.Wang@Sun.COM fcoe_soft_state_t *ss;
4989087SZhong.Wang@Sun.COM
4999087SZhong.Wang@Sun.COM if (otype != OTYP_CHR) {
5009087SZhong.Wang@Sun.COM return (EINVAL);
5019087SZhong.Wang@Sun.COM }
5029087SZhong.Wang@Sun.COM
5039087SZhong.Wang@Sun.COM instance = (int)getminor(dev);
5049087SZhong.Wang@Sun.COM ss = ddi_get_soft_state(fcoe_state, instance);
5059087SZhong.Wang@Sun.COM if (ss == NULL) {
5069087SZhong.Wang@Sun.COM return (ENXIO);
5079087SZhong.Wang@Sun.COM }
5089087SZhong.Wang@Sun.COM
5099087SZhong.Wang@Sun.COM mutex_enter(&ss->ss_ioctl_mutex);
5109087SZhong.Wang@Sun.COM if ((ss->ss_ioctl_flags & FCOE_IOCTL_FLAG_OPEN) == 0) {
5119087SZhong.Wang@Sun.COM mutex_exit(&ss->ss_ioctl_mutex);
5129087SZhong.Wang@Sun.COM return (ENODEV);
5139087SZhong.Wang@Sun.COM }
5149087SZhong.Wang@Sun.COM
5159087SZhong.Wang@Sun.COM ss->ss_ioctl_flags &= ~FCOE_IOCTL_FLAG_MASK;
5169087SZhong.Wang@Sun.COM mutex_exit(&ss->ss_ioctl_mutex);
5179087SZhong.Wang@Sun.COM
5189087SZhong.Wang@Sun.COM return (0);
5199087SZhong.Wang@Sun.COM }
5209087SZhong.Wang@Sun.COM
5219087SZhong.Wang@Sun.COM /* ARGSUSED */
5229087SZhong.Wang@Sun.COM static int
fcoe_ioctl(dev_t dev,int cmd,intptr_t data,int mode,cred_t * credp,int * rval)5239087SZhong.Wang@Sun.COM fcoe_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
5249087SZhong.Wang@Sun.COM cred_t *credp, int *rval)
5259087SZhong.Wang@Sun.COM {
5269087SZhong.Wang@Sun.COM fcoe_soft_state_t *ss;
5279087SZhong.Wang@Sun.COM int ret = 0;
5289087SZhong.Wang@Sun.COM
5299087SZhong.Wang@Sun.COM if (drv_priv(credp) != 0) {
5309087SZhong.Wang@Sun.COM return (EPERM);
5319087SZhong.Wang@Sun.COM }
5329087SZhong.Wang@Sun.COM
5339087SZhong.Wang@Sun.COM ss = ddi_get_soft_state(fcoe_state, (int32_t)getminor(dev));
5349087SZhong.Wang@Sun.COM if (ss == NULL) {
5359087SZhong.Wang@Sun.COM return (ENXIO);
5369087SZhong.Wang@Sun.COM }
5379087SZhong.Wang@Sun.COM
5389087SZhong.Wang@Sun.COM mutex_enter(&ss->ss_ioctl_mutex);
5399087SZhong.Wang@Sun.COM if ((ss->ss_ioctl_flags & FCOE_IOCTL_FLAG_OPEN) == 0) {
5409087SZhong.Wang@Sun.COM mutex_exit(&ss->ss_ioctl_mutex);
5419087SZhong.Wang@Sun.COM return (ENXIO);
5429087SZhong.Wang@Sun.COM }
5439087SZhong.Wang@Sun.COM mutex_exit(&ss->ss_ioctl_mutex);
5449087SZhong.Wang@Sun.COM
5459087SZhong.Wang@Sun.COM switch (cmd) {
5469087SZhong.Wang@Sun.COM case FCOEIO_CMD:
5479087SZhong.Wang@Sun.COM ret = fcoe_iocmd(ss, data, mode);
5489087SZhong.Wang@Sun.COM break;
5499087SZhong.Wang@Sun.COM default:
5509087SZhong.Wang@Sun.COM FCOE_LOG(0, "fcoe_ioctl: ioctl-0x%02X", cmd);
5519087SZhong.Wang@Sun.COM ret = ENOTTY;
5529087SZhong.Wang@Sun.COM break;
5539087SZhong.Wang@Sun.COM }
5549087SZhong.Wang@Sun.COM
5559087SZhong.Wang@Sun.COM return (ret);
5569087SZhong.Wang@Sun.COM }
5579087SZhong.Wang@Sun.COM
5589087SZhong.Wang@Sun.COM static int
fcoe_copyin_iocdata(intptr_t data,int mode,fcoeio_t ** fcoeio,void ** ibuf,void ** abuf,void ** obuf)5599087SZhong.Wang@Sun.COM fcoe_copyin_iocdata(intptr_t data, int mode, fcoeio_t **fcoeio,
5609087SZhong.Wang@Sun.COM void **ibuf, void **abuf, void **obuf)
5619087SZhong.Wang@Sun.COM {
5629087SZhong.Wang@Sun.COM int ret = 0;
5639087SZhong.Wang@Sun.COM
5649087SZhong.Wang@Sun.COM *ibuf = NULL;
5659087SZhong.Wang@Sun.COM *abuf = NULL;
5669087SZhong.Wang@Sun.COM *obuf = NULL;
5679087SZhong.Wang@Sun.COM *fcoeio = kmem_zalloc(sizeof (fcoeio_t), KM_SLEEP);
5689087SZhong.Wang@Sun.COM if (ddi_copyin((void *)data, *fcoeio, sizeof (fcoeio_t), mode) != 0) {
5699087SZhong.Wang@Sun.COM ret = EFAULT;
5709087SZhong.Wang@Sun.COM goto copyin_iocdata_fail;
5719087SZhong.Wang@Sun.COM }
5729087SZhong.Wang@Sun.COM
5739087SZhong.Wang@Sun.COM if ((*fcoeio)->fcoeio_ilen > FCOEIO_MAX_BUF_LEN ||
5749087SZhong.Wang@Sun.COM (*fcoeio)->fcoeio_alen > FCOEIO_MAX_BUF_LEN ||
5759087SZhong.Wang@Sun.COM (*fcoeio)->fcoeio_olen > FCOEIO_MAX_BUF_LEN) {
5769087SZhong.Wang@Sun.COM ret = EFAULT;
5779087SZhong.Wang@Sun.COM goto copyin_iocdata_fail;
5789087SZhong.Wang@Sun.COM }
5799087SZhong.Wang@Sun.COM
5809087SZhong.Wang@Sun.COM if ((*fcoeio)->fcoeio_ilen) {
5819087SZhong.Wang@Sun.COM *ibuf = kmem_zalloc((*fcoeio)->fcoeio_ilen, KM_SLEEP);
5829087SZhong.Wang@Sun.COM if (ddi_copyin((void *)(unsigned long)(*fcoeio)->fcoeio_ibuf,
5839087SZhong.Wang@Sun.COM *ibuf, (*fcoeio)->fcoeio_ilen, mode) != 0) {
5849087SZhong.Wang@Sun.COM ret = EFAULT;
5859087SZhong.Wang@Sun.COM goto copyin_iocdata_fail;
5869087SZhong.Wang@Sun.COM }
5879087SZhong.Wang@Sun.COM }
5889087SZhong.Wang@Sun.COM
5899087SZhong.Wang@Sun.COM if ((*fcoeio)->fcoeio_alen) {
5909087SZhong.Wang@Sun.COM *abuf = kmem_zalloc((*fcoeio)->fcoeio_alen, KM_SLEEP);
5919087SZhong.Wang@Sun.COM if (ddi_copyin((void *)(unsigned long)(*fcoeio)->fcoeio_abuf,
5929087SZhong.Wang@Sun.COM *abuf, (*fcoeio)->fcoeio_alen, mode) != 0) {
5939087SZhong.Wang@Sun.COM ret = EFAULT;
5949087SZhong.Wang@Sun.COM goto copyin_iocdata_fail;
5959087SZhong.Wang@Sun.COM }
5969087SZhong.Wang@Sun.COM }
5979087SZhong.Wang@Sun.COM
5989087SZhong.Wang@Sun.COM if ((*fcoeio)->fcoeio_olen) {
5999087SZhong.Wang@Sun.COM *obuf = kmem_zalloc((*fcoeio)->fcoeio_olen, KM_SLEEP);
6009087SZhong.Wang@Sun.COM }
6019087SZhong.Wang@Sun.COM return (ret);
6029087SZhong.Wang@Sun.COM
6039087SZhong.Wang@Sun.COM copyin_iocdata_fail:
6049087SZhong.Wang@Sun.COM if (*abuf) {
6059087SZhong.Wang@Sun.COM kmem_free(*abuf, (*fcoeio)->fcoeio_alen);
6069087SZhong.Wang@Sun.COM *abuf = NULL;
6079087SZhong.Wang@Sun.COM }
6089087SZhong.Wang@Sun.COM
6099087SZhong.Wang@Sun.COM if (*ibuf) {
6109087SZhong.Wang@Sun.COM kmem_free(*ibuf, (*fcoeio)->fcoeio_ilen);
6119087SZhong.Wang@Sun.COM *ibuf = NULL;
6129087SZhong.Wang@Sun.COM }
6139087SZhong.Wang@Sun.COM
6149087SZhong.Wang@Sun.COM kmem_free(*fcoeio, sizeof (fcoeio_t));
6159087SZhong.Wang@Sun.COM return (ret);
6169087SZhong.Wang@Sun.COM }
6179087SZhong.Wang@Sun.COM
6189087SZhong.Wang@Sun.COM static int
fcoe_copyout_iocdata(intptr_t data,int mode,fcoeio_t * fcoeio,void * obuf)6199087SZhong.Wang@Sun.COM fcoe_copyout_iocdata(intptr_t data, int mode, fcoeio_t *fcoeio, void *obuf)
6209087SZhong.Wang@Sun.COM {
6219087SZhong.Wang@Sun.COM if (fcoeio->fcoeio_olen) {
6229087SZhong.Wang@Sun.COM if (ddi_copyout(obuf,
6239087SZhong.Wang@Sun.COM (void *)(unsigned long)fcoeio->fcoeio_obuf,
6249087SZhong.Wang@Sun.COM fcoeio->fcoeio_olen, mode) != 0) {
6259087SZhong.Wang@Sun.COM return (EFAULT);
6269087SZhong.Wang@Sun.COM }
6279087SZhong.Wang@Sun.COM }
6289087SZhong.Wang@Sun.COM
6299087SZhong.Wang@Sun.COM if (ddi_copyout(fcoeio, (void *)data, sizeof (fcoeio_t), mode) != 0) {
6309087SZhong.Wang@Sun.COM return (EFAULT);
6319087SZhong.Wang@Sun.COM }
6329087SZhong.Wang@Sun.COM return (0);
6339087SZhong.Wang@Sun.COM }
6349087SZhong.Wang@Sun.COM
6359087SZhong.Wang@Sun.COM static int
fcoe_iocmd(fcoe_soft_state_t * ss,intptr_t data,int mode)6369087SZhong.Wang@Sun.COM fcoe_iocmd(fcoe_soft_state_t *ss, intptr_t data, int mode)
6379087SZhong.Wang@Sun.COM {
6389087SZhong.Wang@Sun.COM int ret;
6399087SZhong.Wang@Sun.COM fcoe_mac_t *fcoe_mac;
6409087SZhong.Wang@Sun.COM void *ibuf = NULL;
6419087SZhong.Wang@Sun.COM void *obuf = NULL;
6429087SZhong.Wang@Sun.COM void *abuf = NULL;
6439087SZhong.Wang@Sun.COM fcoeio_t *fcoeio;
6449087SZhong.Wang@Sun.COM
6459087SZhong.Wang@Sun.COM ret = fcoe_copyin_iocdata(data, mode, &fcoeio, &ibuf, &abuf, &obuf);
6469087SZhong.Wang@Sun.COM if (ret != 0) {
6479087SZhong.Wang@Sun.COM goto fcoeiocmd_release_buf;
6489087SZhong.Wang@Sun.COM }
6499087SZhong.Wang@Sun.COM
6509087SZhong.Wang@Sun.COM /*
6519087SZhong.Wang@Sun.COM * If an exclusive open was demanded during open, ensure that
6529087SZhong.Wang@Sun.COM * only one thread can execute an ioctl at a time
6539087SZhong.Wang@Sun.COM */
6549087SZhong.Wang@Sun.COM mutex_enter(&ss->ss_ioctl_mutex);
6559087SZhong.Wang@Sun.COM if (ss->ss_ioctl_flags & FCOE_IOCTL_FLAG_EXCL) {
6569087SZhong.Wang@Sun.COM if (ss->ss_ioctl_flags & FCOE_IOCTL_FLAG_EXCL_BUSY) {
6579087SZhong.Wang@Sun.COM mutex_exit(&ss->ss_ioctl_mutex);
6589087SZhong.Wang@Sun.COM fcoeio->fcoeio_status = FCOEIOE_BUSY;
6599087SZhong.Wang@Sun.COM ret = EBUSY;
6609087SZhong.Wang@Sun.COM goto fcoeiocmd_release_buf;
6619087SZhong.Wang@Sun.COM }
6629087SZhong.Wang@Sun.COM ss->ss_ioctl_flags |= FCOE_IOCTL_FLAG_EXCL_BUSY;
6639087SZhong.Wang@Sun.COM }
6649087SZhong.Wang@Sun.COM mutex_exit(&ss->ss_ioctl_mutex);
6659087SZhong.Wang@Sun.COM
6669087SZhong.Wang@Sun.COM fcoeio->fcoeio_status = 0;
6679087SZhong.Wang@Sun.COM
6689087SZhong.Wang@Sun.COM switch (fcoeio->fcoeio_cmd) {
6699087SZhong.Wang@Sun.COM case FCOEIO_CREATE_FCOE_PORT: {
6709087SZhong.Wang@Sun.COM fcoeio_create_port_param_t *param =
6719087SZhong.Wang@Sun.COM (fcoeio_create_port_param_t *)ibuf;
6729087SZhong.Wang@Sun.COM int cmpwwn = 0;
6739087SZhong.Wang@Sun.COM fcoe_port_t *eport;
6749087SZhong.Wang@Sun.COM
6759087SZhong.Wang@Sun.COM if (fcoeio->fcoeio_ilen !=
6769087SZhong.Wang@Sun.COM sizeof (fcoeio_create_port_param_t) ||
6779087SZhong.Wang@Sun.COM fcoeio->fcoeio_xfer != FCOEIO_XFER_WRITE) {
6789087SZhong.Wang@Sun.COM fcoeio->fcoeio_status = FCOEIOE_INVAL_ARG;
6799087SZhong.Wang@Sun.COM ret = EINVAL;
6809087SZhong.Wang@Sun.COM break;
6819087SZhong.Wang@Sun.COM }
6829087SZhong.Wang@Sun.COM
6839087SZhong.Wang@Sun.COM mutex_enter(&ss->ss_ioctl_mutex);
6849307Skelly.hu@Sun.COM fcoe_mac = fcoe_create_mac_by_id(param->fcp_mac_linkid);
6859087SZhong.Wang@Sun.COM if (fcoe_mac == NULL) {
6869087SZhong.Wang@Sun.COM mutex_exit(&ss->ss_ioctl_mutex);
6879087SZhong.Wang@Sun.COM fcoeio->fcoeio_status = FCOEIOE_CREATE_MAC;
6889087SZhong.Wang@Sun.COM ret = EIO;
6899087SZhong.Wang@Sun.COM break;
6909087SZhong.Wang@Sun.COM }
6919087SZhong.Wang@Sun.COM
6929087SZhong.Wang@Sun.COM if (fcoe_mac->fm_flags & FCOE_MAC_FLAG_ENABLED) {
6939087SZhong.Wang@Sun.COM mutex_exit(&ss->ss_ioctl_mutex);
6949087SZhong.Wang@Sun.COM fcoeio->fcoeio_status = FCOEIOE_ALREADY;
6959087SZhong.Wang@Sun.COM ret = EALREADY;
6969087SZhong.Wang@Sun.COM break;
6979087SZhong.Wang@Sun.COM } else {
6989087SZhong.Wang@Sun.COM ret = fcoe_open_mac(fcoe_mac, param->fcp_force_promisc,
6999087SZhong.Wang@Sun.COM &fcoeio->fcoeio_status);
7009087SZhong.Wang@Sun.COM if (ret != 0) {
7019087SZhong.Wang@Sun.COM fcoe_destroy_mac(fcoe_mac);
7029087SZhong.Wang@Sun.COM mutex_exit(&ss->ss_ioctl_mutex);
7039087SZhong.Wang@Sun.COM if (fcoeio->fcoeio_status == 0) {
7049087SZhong.Wang@Sun.COM fcoeio->fcoeio_status =
7059087SZhong.Wang@Sun.COM FCOEIOE_OPEN_MAC;
7069087SZhong.Wang@Sun.COM }
7079087SZhong.Wang@Sun.COM ret = EIO;
7089087SZhong.Wang@Sun.COM break;
7099087SZhong.Wang@Sun.COM } else {
7109087SZhong.Wang@Sun.COM fcoe_mac->fm_flags |= FCOE_MAC_FLAG_ENABLED;
7119087SZhong.Wang@Sun.COM }
7129087SZhong.Wang@Sun.COM }
7139087SZhong.Wang@Sun.COM
7149087SZhong.Wang@Sun.COM /*
7159087SZhong.Wang@Sun.COM * Provide PWWN and NWWN based on mac address
7169087SZhong.Wang@Sun.COM */
7179087SZhong.Wang@Sun.COM eport = &fcoe_mac->fm_eport;
7189087SZhong.Wang@Sun.COM if (!param->fcp_pwwn_provided) {
7199087SZhong.Wang@Sun.COM fcoe_init_wwn_from_mac(eport->eport_portwwn,
7209087SZhong.Wang@Sun.COM fcoe_mac->fm_current_addr, 1, 0);
7219087SZhong.Wang@Sun.COM } else {
7229087SZhong.Wang@Sun.COM (void) memcpy(eport->eport_portwwn, param->fcp_pwwn, 8);
7239087SZhong.Wang@Sun.COM }
7249087SZhong.Wang@Sun.COM
7259087SZhong.Wang@Sun.COM if (!param->fcp_nwwn_provided) {
7269087SZhong.Wang@Sun.COM fcoe_init_wwn_from_mac(eport->eport_nodewwn,
7279087SZhong.Wang@Sun.COM fcoe_mac->fm_current_addr, 0, 0);
7289087SZhong.Wang@Sun.COM } else {
7299087SZhong.Wang@Sun.COM (void) memcpy(eport->eport_nodewwn, param->fcp_nwwn, 8);
7309087SZhong.Wang@Sun.COM }
7319087SZhong.Wang@Sun.COM
7329087SZhong.Wang@Sun.COM cmpwwn = fcoe_cmp_wwn(fcoe_mac);
7339087SZhong.Wang@Sun.COM
7349087SZhong.Wang@Sun.COM if (cmpwwn != 0) {
7359087SZhong.Wang@Sun.COM if (cmpwwn == 1) {
7369087SZhong.Wang@Sun.COM fcoeio->fcoeio_status = FCOEIOE_PWWN_CONFLICTED;
7379087SZhong.Wang@Sun.COM } else if (cmpwwn == -1) {
7389087SZhong.Wang@Sun.COM fcoeio->fcoeio_status = FCOEIOE_NWWN_CONFLICTED;
7399087SZhong.Wang@Sun.COM }
7409087SZhong.Wang@Sun.COM (void) fcoe_close_mac(fcoe_mac);
7419087SZhong.Wang@Sun.COM fcoe_destroy_mac(fcoe_mac);
7429087SZhong.Wang@Sun.COM mutex_exit(&ss->ss_ioctl_mutex);
7439087SZhong.Wang@Sun.COM ret = ENOTUNIQ;
7449087SZhong.Wang@Sun.COM break;
7459087SZhong.Wang@Sun.COM }
7469087SZhong.Wang@Sun.COM
7479087SZhong.Wang@Sun.COM if (ret == 0) {
7489087SZhong.Wang@Sun.COM ret = fcoe_create_port(ss->ss_dip,
7499087SZhong.Wang@Sun.COM fcoe_mac,
7509087SZhong.Wang@Sun.COM (param->fcp_port_type == FCOE_CLIENT_TARGET));
7519087SZhong.Wang@Sun.COM if (ret != 0) {
752*11231SKevin.Yu@Sun.COM if (fcoe_mac_existed(fcoe_mac) == B_TRUE) {
753*11231SKevin.Yu@Sun.COM (void) fcoe_close_mac(fcoe_mac);
754*11231SKevin.Yu@Sun.COM fcoe_destroy_mac(fcoe_mac);
755*11231SKevin.Yu@Sun.COM }
7569087SZhong.Wang@Sun.COM fcoeio->fcoeio_status = FCOEIOE_CREATE_PORT;
7579087SZhong.Wang@Sun.COM ret = EIO;
7589087SZhong.Wang@Sun.COM }
7599087SZhong.Wang@Sun.COM }
7609087SZhong.Wang@Sun.COM mutex_exit(&ss->ss_ioctl_mutex);
7619087SZhong.Wang@Sun.COM
7629087SZhong.Wang@Sun.COM break;
7639087SZhong.Wang@Sun.COM }
7649087SZhong.Wang@Sun.COM
7659087SZhong.Wang@Sun.COM case FCOEIO_DELETE_FCOE_PORT: {
7669307Skelly.hu@Sun.COM fcoeio_delete_port_param_t *del_port_param =
7679307Skelly.hu@Sun.COM (fcoeio_delete_port_param_t *)ibuf;
7689895SKevin.Yu@Sun.COM uint64_t *is_target = (uint64_t *)obuf;
7699087SZhong.Wang@Sun.COM
7709307Skelly.hu@Sun.COM if (fcoeio->fcoeio_ilen < sizeof (fcoeio_delete_port_param_t) ||
7719895SKevin.Yu@Sun.COM fcoeio->fcoeio_olen != sizeof (uint64_t) ||
7729895SKevin.Yu@Sun.COM fcoeio->fcoeio_xfer != FCOEIO_XFER_RW) {
7739087SZhong.Wang@Sun.COM fcoeio->fcoeio_status = FCOEIOE_INVAL_ARG;
7749087SZhong.Wang@Sun.COM ret = EINVAL;
7759087SZhong.Wang@Sun.COM break;
7769087SZhong.Wang@Sun.COM }
7779087SZhong.Wang@Sun.COM
7789087SZhong.Wang@Sun.COM mutex_enter(&ss->ss_ioctl_mutex);
7799307Skelly.hu@Sun.COM ret = fcoe_delete_port(ss->ss_dip, fcoeio,
7809895SKevin.Yu@Sun.COM del_port_param->fdp_mac_linkid, is_target);
7819087SZhong.Wang@Sun.COM mutex_exit(&ss->ss_ioctl_mutex);
78210264SZhong.Wang@Sun.COM FCOE_LOG("fcoe", "fcoe_delete_port %x return: %d",
78310264SZhong.Wang@Sun.COM del_port_param->fdp_mac_linkid, ret);
7849087SZhong.Wang@Sun.COM break;
7859087SZhong.Wang@Sun.COM }
7869087SZhong.Wang@Sun.COM
7879087SZhong.Wang@Sun.COM case FCOEIO_GET_FCOE_PORT_LIST: {
7889087SZhong.Wang@Sun.COM fcoe_port_list_t *list = (fcoe_port_list_t *)obuf;
7899087SZhong.Wang@Sun.COM int count;
7909087SZhong.Wang@Sun.COM
7919087SZhong.Wang@Sun.COM if (fcoeio->fcoeio_xfer != FCOEIO_XFER_READ ||
7929087SZhong.Wang@Sun.COM fcoeio->fcoeio_olen < sizeof (fcoe_port_list_t)) {
7939087SZhong.Wang@Sun.COM fcoeio->fcoeio_status = FCOEIOE_INVAL_ARG;
7949087SZhong.Wang@Sun.COM ret = EINVAL;
7959087SZhong.Wang@Sun.COM break;
7969087SZhong.Wang@Sun.COM }
7979087SZhong.Wang@Sun.COM mutex_enter(&ss->ss_ioctl_mutex);
7989087SZhong.Wang@Sun.COM
7999087SZhong.Wang@Sun.COM list->numPorts = 1 + (fcoeio->fcoeio_olen -
8009087SZhong.Wang@Sun.COM sizeof (fcoe_port_list_t))/sizeof (fcoe_port_instance_t);
8019087SZhong.Wang@Sun.COM
8029087SZhong.Wang@Sun.COM count = fcoe_get_port_list(list->ports, list->numPorts);
8039087SZhong.Wang@Sun.COM
8049087SZhong.Wang@Sun.COM if (count > list->numPorts) {
8059087SZhong.Wang@Sun.COM fcoeio->fcoeio_status = FCOEIOE_MORE_DATA;
8069087SZhong.Wang@Sun.COM ret = ENOSPC;
8079087SZhong.Wang@Sun.COM }
8089087SZhong.Wang@Sun.COM list->numPorts = count;
8099087SZhong.Wang@Sun.COM mutex_exit(&ss->ss_ioctl_mutex);
8109087SZhong.Wang@Sun.COM
8119087SZhong.Wang@Sun.COM break;
8129087SZhong.Wang@Sun.COM
8139087SZhong.Wang@Sun.COM }
8149087SZhong.Wang@Sun.COM
8159087SZhong.Wang@Sun.COM default:
8169087SZhong.Wang@Sun.COM return (ENOTTY);
8179087SZhong.Wang@Sun.COM }
8189087SZhong.Wang@Sun.COM
81910264SZhong.Wang@Sun.COM FCOE_LOG("fcoe", "fcoe_ioctl %x returned %d, fcoeio_status = %d",
82010264SZhong.Wang@Sun.COM fcoeio->fcoeio_cmd, ret, fcoeio->fcoeio_status);
8219087SZhong.Wang@Sun.COM
8229087SZhong.Wang@Sun.COM fcoeiocmd_release_buf:
8239087SZhong.Wang@Sun.COM if (ret == 0) {
8249087SZhong.Wang@Sun.COM ret = fcoe_copyout_iocdata(data, mode, fcoeio, obuf);
8259087SZhong.Wang@Sun.COM } else if (fcoeio->fcoeio_status) {
8269087SZhong.Wang@Sun.COM (void) fcoe_copyout_iocdata(data, mode, fcoeio, obuf);
8279087SZhong.Wang@Sun.COM }
8289087SZhong.Wang@Sun.COM
8299087SZhong.Wang@Sun.COM if (obuf != NULL) {
8309087SZhong.Wang@Sun.COM kmem_free(obuf, fcoeio->fcoeio_olen);
8319087SZhong.Wang@Sun.COM obuf = NULL;
8329087SZhong.Wang@Sun.COM }
8339087SZhong.Wang@Sun.COM if (abuf != NULL) {
8349087SZhong.Wang@Sun.COM kmem_free(abuf, fcoeio->fcoeio_alen);
8359087SZhong.Wang@Sun.COM abuf = NULL;
8369087SZhong.Wang@Sun.COM }
8379087SZhong.Wang@Sun.COM
8389087SZhong.Wang@Sun.COM if (ibuf != NULL) {
8399087SZhong.Wang@Sun.COM kmem_free(ibuf, fcoeio->fcoeio_ilen);
8409087SZhong.Wang@Sun.COM ibuf = NULL;
8419087SZhong.Wang@Sun.COM }
8429087SZhong.Wang@Sun.COM kmem_free(fcoeio, sizeof (fcoeio_t));
8439087SZhong.Wang@Sun.COM
8449087SZhong.Wang@Sun.COM return (ret);
8459087SZhong.Wang@Sun.COM }
8469087SZhong.Wang@Sun.COM
8479087SZhong.Wang@Sun.COM /*
8489087SZhong.Wang@Sun.COM * Finish final initialization
8499087SZhong.Wang@Sun.COM */
8509087SZhong.Wang@Sun.COM static int
fcoe_attach_init(fcoe_soft_state_t * ss)8519087SZhong.Wang@Sun.COM fcoe_attach_init(fcoe_soft_state_t *ss)
8529087SZhong.Wang@Sun.COM {
8539087SZhong.Wang@Sun.COM char taskq_name[TASKQ_NAME_LEN];
8549087SZhong.Wang@Sun.COM
8559087SZhong.Wang@Sun.COM if (ddi_create_minor_node(ss->ss_dip, "admin", S_IFCHR,
8569087SZhong.Wang@Sun.COM ddi_get_instance(ss->ss_dip), DDI_PSEUDO, 0) != DDI_SUCCESS) {
8579087SZhong.Wang@Sun.COM FCOE_LOG("FCOE", "ddi_create_minor_node failed");
8589087SZhong.Wang@Sun.COM return (FCOE_FAILURE);
8599087SZhong.Wang@Sun.COM }
8609087SZhong.Wang@Sun.COM
8619087SZhong.Wang@Sun.COM /*
8629087SZhong.Wang@Sun.COM * watchdog responsible for release frame and dispatch events
8639087SZhong.Wang@Sun.COM */
8649087SZhong.Wang@Sun.COM (void) snprintf(taskq_name, sizeof (taskq_name), "fcoe_mac");
8659087SZhong.Wang@Sun.COM taskq_name[TASKQ_NAME_LEN - 1] = 0;
8669087SZhong.Wang@Sun.COM if ((ss->ss_watchdog_taskq = ddi_taskq_create(NULL,
8679087SZhong.Wang@Sun.COM taskq_name, 2, TASKQ_DEFAULTPRI, 0)) == NULL) {
8689087SZhong.Wang@Sun.COM return (FCOE_FAILURE);
8699087SZhong.Wang@Sun.COM }
8709087SZhong.Wang@Sun.COM
8719087SZhong.Wang@Sun.COM ss->ss_ioctl_flags = 0;
8729087SZhong.Wang@Sun.COM mutex_init(&ss->ss_ioctl_mutex, NULL, MUTEX_DRIVER, NULL);
8739087SZhong.Wang@Sun.COM list_create(&ss->ss_mac_list, sizeof (fcoe_mac_t),
8749087SZhong.Wang@Sun.COM offsetof(fcoe_mac_t, fm_ss_node));
8759087SZhong.Wang@Sun.COM list_create(&ss->ss_pfrm_list, sizeof (fcoe_i_frame_t),
8769087SZhong.Wang@Sun.COM offsetof(fcoe_i_frame_t, fmi_pending_node));
8779087SZhong.Wang@Sun.COM
8789087SZhong.Wang@Sun.COM mutex_init(&ss->ss_watch_mutex, 0, MUTEX_DRIVER, 0);
8799087SZhong.Wang@Sun.COM cv_init(&ss->ss_watch_cv, NULL, CV_DRIVER, NULL);
8809087SZhong.Wang@Sun.COM ss->ss_flags &= ~SS_FLAG_TERMINATE_WATCHDOG;
8819087SZhong.Wang@Sun.COM (void) ddi_taskq_dispatch(ss->ss_watchdog_taskq,
8829087SZhong.Wang@Sun.COM fcoe_watchdog, ss, DDI_SLEEP);
8839087SZhong.Wang@Sun.COM while ((ss->ss_flags & SS_FLAG_WATCHDOG_RUNNING) == 0) {
8849087SZhong.Wang@Sun.COM delay(10);
8859087SZhong.Wang@Sun.COM }
8869087SZhong.Wang@Sun.COM fcoe_nworkers = ddi_prop_get_int(DDI_DEV_T_ANY, ss->ss_dip,
8879087SZhong.Wang@Sun.COM DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, (char *)fcoe_workers_num, 4);
8889087SZhong.Wang@Sun.COM if (fcoe_nworkers < 1) {
8899087SZhong.Wang@Sun.COM fcoe_nworkers = 4;
8909087SZhong.Wang@Sun.COM }
8919087SZhong.Wang@Sun.COM fcoe_worker_init();
8929087SZhong.Wang@Sun.COM
8939087SZhong.Wang@Sun.COM ddi_report_dev(ss->ss_dip);
8949087SZhong.Wang@Sun.COM return (FCOE_SUCCESS);
8959087SZhong.Wang@Sun.COM }
8969087SZhong.Wang@Sun.COM
8979087SZhong.Wang@Sun.COM /*
8989087SZhong.Wang@Sun.COM * Finish final uninitialization
8999087SZhong.Wang@Sun.COM */
9009087SZhong.Wang@Sun.COM static int
fcoe_detach_uninit(fcoe_soft_state_t * ss)9019087SZhong.Wang@Sun.COM fcoe_detach_uninit(fcoe_soft_state_t *ss)
9029087SZhong.Wang@Sun.COM {
9039087SZhong.Wang@Sun.COM int ret;
9049087SZhong.Wang@Sun.COM if (!list_is_empty(&ss->ss_mac_list)) {
9059087SZhong.Wang@Sun.COM FCOE_LOG("fcoe", "ss_mac_list is not empty when detach");
9069087SZhong.Wang@Sun.COM return (FCOE_FAILURE);
9079087SZhong.Wang@Sun.COM }
9089087SZhong.Wang@Sun.COM
9099087SZhong.Wang@Sun.COM if ((ret = fcoe_worker_fini()) != FCOE_SUCCESS) {
9109087SZhong.Wang@Sun.COM return (ret);
9119087SZhong.Wang@Sun.COM }
9129087SZhong.Wang@Sun.COM
9139087SZhong.Wang@Sun.COM /*
9149087SZhong.Wang@Sun.COM * Stop watchdog
9159087SZhong.Wang@Sun.COM */
9169087SZhong.Wang@Sun.COM if (ss->ss_flags & SS_FLAG_WATCHDOG_RUNNING) {
9179087SZhong.Wang@Sun.COM mutex_enter(&ss->ss_watch_mutex);
9189087SZhong.Wang@Sun.COM ss->ss_flags |= SS_FLAG_TERMINATE_WATCHDOG;
9199087SZhong.Wang@Sun.COM cv_broadcast(&ss->ss_watch_cv);
9209087SZhong.Wang@Sun.COM mutex_exit(&ss->ss_watch_mutex);
9219087SZhong.Wang@Sun.COM while (ss->ss_flags & SS_FLAG_WATCHDOG_RUNNING) {
9229087SZhong.Wang@Sun.COM delay(10);
9239087SZhong.Wang@Sun.COM }
9249087SZhong.Wang@Sun.COM }
9259087SZhong.Wang@Sun.COM
9269087SZhong.Wang@Sun.COM ddi_taskq_destroy(ss->ss_watchdog_taskq);
9279087SZhong.Wang@Sun.COM mutex_destroy(&ss->ss_watch_mutex);
9289087SZhong.Wang@Sun.COM cv_destroy(&ss->ss_watch_cv);
9299087SZhong.Wang@Sun.COM
9309087SZhong.Wang@Sun.COM ddi_remove_minor_node(ss->ss_dip, NULL);
9319087SZhong.Wang@Sun.COM mutex_destroy(&ss->ss_ioctl_mutex);
9329087SZhong.Wang@Sun.COM list_destroy(&ss->ss_mac_list);
9339087SZhong.Wang@Sun.COM
9349087SZhong.Wang@Sun.COM return (FCOE_SUCCESS);
9359087SZhong.Wang@Sun.COM }
9369087SZhong.Wang@Sun.COM
9379087SZhong.Wang@Sun.COM /*
9389087SZhong.Wang@Sun.COM * Return mac instance if it exist, or else return NULL.
9399087SZhong.Wang@Sun.COM */
9409087SZhong.Wang@Sun.COM fcoe_mac_t *
fcoe_lookup_mac_by_id(datalink_id_t linkid)9419307Skelly.hu@Sun.COM fcoe_lookup_mac_by_id(datalink_id_t linkid)
9429087SZhong.Wang@Sun.COM {
9439087SZhong.Wang@Sun.COM fcoe_mac_t *mac = NULL;
9449087SZhong.Wang@Sun.COM
9459307Skelly.hu@Sun.COM ASSERT(MUTEX_HELD(&fcoe_global_ss->ss_ioctl_mutex));
9469087SZhong.Wang@Sun.COM for (mac = list_head(&fcoe_global_ss->ss_mac_list); mac;
9479087SZhong.Wang@Sun.COM mac = list_next(&fcoe_global_ss->ss_mac_list, mac)) {
9489307Skelly.hu@Sun.COM if (linkid != mac->fm_linkid) {
9499087SZhong.Wang@Sun.COM continue;
9509087SZhong.Wang@Sun.COM }
9519087SZhong.Wang@Sun.COM return (mac);
9529087SZhong.Wang@Sun.COM }
9539087SZhong.Wang@Sun.COM return (NULL);
9549087SZhong.Wang@Sun.COM }
9559087SZhong.Wang@Sun.COM
9569087SZhong.Wang@Sun.COM /*
957*11231SKevin.Yu@Sun.COM * Return B_TRUE if mac exists, or else return B_FALSE
958*11231SKevin.Yu@Sun.COM */
959*11231SKevin.Yu@Sun.COM static boolean_t
fcoe_mac_existed(fcoe_mac_t * pmac)960*11231SKevin.Yu@Sun.COM fcoe_mac_existed(fcoe_mac_t *pmac)
961*11231SKevin.Yu@Sun.COM {
962*11231SKevin.Yu@Sun.COM fcoe_mac_t *mac = NULL;
963*11231SKevin.Yu@Sun.COM
964*11231SKevin.Yu@Sun.COM ASSERT(MUTEX_HELD(&fcoe_global_ss->ss_ioctl_mutex));
965*11231SKevin.Yu@Sun.COM for (mac = list_head(&fcoe_global_ss->ss_mac_list); mac;
966*11231SKevin.Yu@Sun.COM mac = list_next(&fcoe_global_ss->ss_mac_list, mac)) {
967*11231SKevin.Yu@Sun.COM if (mac == pmac) {
968*11231SKevin.Yu@Sun.COM return (B_TRUE);
969*11231SKevin.Yu@Sun.COM }
970*11231SKevin.Yu@Sun.COM }
971*11231SKevin.Yu@Sun.COM return (B_FALSE);
972*11231SKevin.Yu@Sun.COM }
973*11231SKevin.Yu@Sun.COM
974*11231SKevin.Yu@Sun.COM /*
9759087SZhong.Wang@Sun.COM * port wwn will start with 20:..., node wwn will start with 10:...
9769087SZhong.Wang@Sun.COM */
9779087SZhong.Wang@Sun.COM static void
fcoe_init_wwn_from_mac(uint8_t * wwn,uint8_t * mac,int is_pwwn,uint8_t idx)9789087SZhong.Wang@Sun.COM fcoe_init_wwn_from_mac(uint8_t *wwn, uint8_t *mac, int is_pwwn, uint8_t idx)
9799087SZhong.Wang@Sun.COM {
9809087SZhong.Wang@Sun.COM ASSERT(wwn != NULL);
9819087SZhong.Wang@Sun.COM ASSERT(mac != NULL);
9829087SZhong.Wang@Sun.COM wwn[0] = (is_pwwn + 1) << 4;
9839087SZhong.Wang@Sun.COM wwn[1] = idx;
9849087SZhong.Wang@Sun.COM bcopy(mac, wwn + 2, ETHERADDRL);
9859087SZhong.Wang@Sun.COM }
9869087SZhong.Wang@Sun.COM
9879087SZhong.Wang@Sun.COM /*
9889087SZhong.Wang@Sun.COM * Return fcoe_mac if it exists, otherwise create a new one
9899087SZhong.Wang@Sun.COM */
9909087SZhong.Wang@Sun.COM static fcoe_mac_t *
fcoe_create_mac_by_id(datalink_id_t linkid)9919307Skelly.hu@Sun.COM fcoe_create_mac_by_id(datalink_id_t linkid)
9929087SZhong.Wang@Sun.COM {
9939087SZhong.Wang@Sun.COM fcoe_mac_t *mac = NULL;
9949307Skelly.hu@Sun.COM ASSERT(MUTEX_HELD(&fcoe_global_ss->ss_ioctl_mutex));
9959087SZhong.Wang@Sun.COM
9969307Skelly.hu@Sun.COM mac = fcoe_lookup_mac_by_id(linkid);
9979087SZhong.Wang@Sun.COM if (mac != NULL) {
9989307Skelly.hu@Sun.COM FCOE_LOG("fcoe", "fcoe_create_mac_by_id found one mac %d",
9999307Skelly.hu@Sun.COM linkid);
10009087SZhong.Wang@Sun.COM return (mac);
10019087SZhong.Wang@Sun.COM }
10029087SZhong.Wang@Sun.COM
10039087SZhong.Wang@Sun.COM mac = kmem_zalloc(sizeof (fcoe_mac_t), KM_SLEEP);
10049307Skelly.hu@Sun.COM mac->fm_linkid = linkid;
10059087SZhong.Wang@Sun.COM mac->fm_flags = 0;
10069087SZhong.Wang@Sun.COM mac->fm_ss = fcoe_global_ss;
10079087SZhong.Wang@Sun.COM list_insert_tail(&mac->fm_ss->ss_mac_list, mac);
10089307Skelly.hu@Sun.COM FCOE_LOG("fcoe", "fcoe_create_mac_by_id created one mac %d", linkid);
10099087SZhong.Wang@Sun.COM return (mac);
10109087SZhong.Wang@Sun.COM }
10119087SZhong.Wang@Sun.COM
10129087SZhong.Wang@Sun.COM void
fcoe_destroy_mac(fcoe_mac_t * mac)10139087SZhong.Wang@Sun.COM fcoe_destroy_mac(fcoe_mac_t *mac)
10149087SZhong.Wang@Sun.COM {
10159087SZhong.Wang@Sun.COM ASSERT(mac != NULL);
10169087SZhong.Wang@Sun.COM list_remove(&mac->fm_ss->ss_mac_list, mac);
10179087SZhong.Wang@Sun.COM kmem_free(mac, sizeof (fcoe_mac_t));
10189087SZhong.Wang@Sun.COM }
10199087SZhong.Wang@Sun.COM
10209087SZhong.Wang@Sun.COM /*
10219087SZhong.Wang@Sun.COM * raw frame layout:
10229087SZhong.Wang@Sun.COM * ethernet header + vlan header (optional) + FCoE header +
10239087SZhong.Wang@Sun.COM * FC frame + FCoE tailer
10249087SZhong.Wang@Sun.COM */
10259087SZhong.Wang@Sun.COM /* ARGSUSED */
10269087SZhong.Wang@Sun.COM mblk_t *
fcoe_get_mblk(fcoe_mac_t * mac,uint32_t raw_frame_size)10279087SZhong.Wang@Sun.COM fcoe_get_mblk(fcoe_mac_t *mac, uint32_t raw_frame_size)
10289087SZhong.Wang@Sun.COM {
10299087SZhong.Wang@Sun.COM mblk_t *mp;
10309087SZhong.Wang@Sun.COM int err;
10319087SZhong.Wang@Sun.COM
10329087SZhong.Wang@Sun.COM /*
10339087SZhong.Wang@Sun.COM * FCFH_SIZE + PADDING_SIZE
10349087SZhong.Wang@Sun.COM */
10359087SZhong.Wang@Sun.COM ASSERT(raw_frame_size >= 60);
10369087SZhong.Wang@Sun.COM while ((mp = allocb((size_t)raw_frame_size, 0)) == NULL) {
10379087SZhong.Wang@Sun.COM if ((err = strwaitbuf((size_t)raw_frame_size, BPRI_LO)) != 0) {
10389087SZhong.Wang@Sun.COM FCOE_LOG("fcoe_get_mblk", "strwaitbuf return %d", err);
10399087SZhong.Wang@Sun.COM return (NULL);
10409087SZhong.Wang@Sun.COM }
10419087SZhong.Wang@Sun.COM }
10429087SZhong.Wang@Sun.COM mp->b_wptr = mp->b_rptr + raw_frame_size;
10439087SZhong.Wang@Sun.COM
10449087SZhong.Wang@Sun.COM /*
10459087SZhong.Wang@Sun.COM * We should always zero FC frame header
10469087SZhong.Wang@Sun.COM */
10479087SZhong.Wang@Sun.COM bzero(mp->b_rptr + PADDING_HEADER_SIZE,
10489087SZhong.Wang@Sun.COM sizeof (fcoe_fc_frame_header_t));
10499087SZhong.Wang@Sun.COM return (mp);
10509087SZhong.Wang@Sun.COM }
10519087SZhong.Wang@Sun.COM
10529087SZhong.Wang@Sun.COM static void
fcoe_watchdog(void * arg)10539087SZhong.Wang@Sun.COM fcoe_watchdog(void *arg)
10549087SZhong.Wang@Sun.COM {
10559087SZhong.Wang@Sun.COM fcoe_soft_state_t *ss = (fcoe_soft_state_t *)arg;
10569087SZhong.Wang@Sun.COM fcoe_i_frame_t *fmi;
10579087SZhong.Wang@Sun.COM fcoe_mac_t *mac = NULL;
10589087SZhong.Wang@Sun.COM
10599087SZhong.Wang@Sun.COM FCOE_LOG("fcoe", "fcoe_soft_state is %p", ss);
10609087SZhong.Wang@Sun.COM
10619087SZhong.Wang@Sun.COM mutex_enter(&ss->ss_watch_mutex);
10629087SZhong.Wang@Sun.COM ss->ss_flags |= SS_FLAG_WATCHDOG_RUNNING;
10639087SZhong.Wang@Sun.COM while ((ss->ss_flags & SS_FLAG_TERMINATE_WATCHDOG) == 0) {
10649087SZhong.Wang@Sun.COM while (fmi = (fcoe_i_frame_t *)list_head(&ss->ss_pfrm_list)) {
10659087SZhong.Wang@Sun.COM list_remove(&ss->ss_pfrm_list, fmi);
10669087SZhong.Wang@Sun.COM mutex_exit(&ss->ss_watch_mutex);
10679087SZhong.Wang@Sun.COM
10689087SZhong.Wang@Sun.COM mac = EPORT2MAC(fmi->fmi_frame->frm_eport);
10699087SZhong.Wang@Sun.COM mac->fm_client.ect_release_sol_frame(fmi->fmi_frame);
10709087SZhong.Wang@Sun.COM
10719087SZhong.Wang@Sun.COM mutex_enter(&ss->ss_watch_mutex);
10729087SZhong.Wang@Sun.COM mac->fm_frm_cnt--;
10739087SZhong.Wang@Sun.COM }
10749087SZhong.Wang@Sun.COM
10759087SZhong.Wang@Sun.COM ss->ss_flags |= SS_FLAG_DOG_WAITING;
10769087SZhong.Wang@Sun.COM (void) cv_wait(&ss->ss_watch_cv, &ss->ss_watch_mutex);
10779087SZhong.Wang@Sun.COM ss->ss_flags &= ~SS_FLAG_DOG_WAITING;
10789087SZhong.Wang@Sun.COM }
10799087SZhong.Wang@Sun.COM
10809087SZhong.Wang@Sun.COM ss->ss_flags &= ~SS_FLAG_WATCHDOG_RUNNING;
10819087SZhong.Wang@Sun.COM mutex_exit(&ss->ss_watch_mutex);
10829087SZhong.Wang@Sun.COM }
10839087SZhong.Wang@Sun.COM
10849087SZhong.Wang@Sun.COM static void
fcoe_worker_init()10859087SZhong.Wang@Sun.COM fcoe_worker_init()
10869087SZhong.Wang@Sun.COM {
10879087SZhong.Wang@Sun.COM uint32_t i;
10889087SZhong.Wang@Sun.COM
10899087SZhong.Wang@Sun.COM fcoe_nworkers_running = 0;
10909087SZhong.Wang@Sun.COM fcoe_worker_taskq = ddi_taskq_create(0, "FCOE_WORKER_TASKQ",
10919087SZhong.Wang@Sun.COM fcoe_nworkers, TASKQ_DEFAULTPRI, 0);
10929087SZhong.Wang@Sun.COM fcoe_workers = (fcoe_worker_t *)kmem_zalloc(sizeof (fcoe_worker_t) *
10939087SZhong.Wang@Sun.COM fcoe_nworkers, KM_SLEEP);
10949087SZhong.Wang@Sun.COM for (i = 0; i < fcoe_nworkers; i++) {
10959087SZhong.Wang@Sun.COM fcoe_worker_t *w = &fcoe_workers[i];
10969087SZhong.Wang@Sun.COM mutex_init(&w->worker_lock, NULL, MUTEX_DRIVER, NULL);
10979087SZhong.Wang@Sun.COM cv_init(&w->worker_cv, NULL, CV_DRIVER, NULL);
10989087SZhong.Wang@Sun.COM w->worker_flags &= ~FCOE_WORKER_TERMINATE;
10999087SZhong.Wang@Sun.COM list_create(&w->worker_frm_list, sizeof (fcoe_i_frame_t),
11009087SZhong.Wang@Sun.COM offsetof(fcoe_i_frame_t, fmi_pending_node));
11019087SZhong.Wang@Sun.COM (void) ddi_taskq_dispatch(fcoe_worker_taskq, fcoe_worker_frame,
11029087SZhong.Wang@Sun.COM w, DDI_SLEEP);
11039087SZhong.Wang@Sun.COM }
11049087SZhong.Wang@Sun.COM while (fcoe_nworkers_running != fcoe_nworkers) {
11059087SZhong.Wang@Sun.COM delay(10);
11069087SZhong.Wang@Sun.COM }
11079087SZhong.Wang@Sun.COM }
11089087SZhong.Wang@Sun.COM
11099087SZhong.Wang@Sun.COM static int
fcoe_worker_fini()11109087SZhong.Wang@Sun.COM fcoe_worker_fini()
11119087SZhong.Wang@Sun.COM {
11129087SZhong.Wang@Sun.COM uint32_t i;
11139087SZhong.Wang@Sun.COM
11149087SZhong.Wang@Sun.COM for (i = 0; i < fcoe_nworkers; i++) {
11159087SZhong.Wang@Sun.COM fcoe_worker_t *w = &fcoe_workers[i];
11169087SZhong.Wang@Sun.COM mutex_enter(&w->worker_lock);
11179087SZhong.Wang@Sun.COM if (w->worker_flags & FCOE_WORKER_STARTED) {
11189087SZhong.Wang@Sun.COM w->worker_flags |= FCOE_WORKER_TERMINATE;
11199087SZhong.Wang@Sun.COM cv_signal(&w->worker_cv);
11209087SZhong.Wang@Sun.COM }
11219087SZhong.Wang@Sun.COM mutex_exit(&w->worker_lock);
11229087SZhong.Wang@Sun.COM }
11239087SZhong.Wang@Sun.COM
11249087SZhong.Wang@Sun.COM while (fcoe_nworkers_running != 0) {
11259087SZhong.Wang@Sun.COM delay(drv_usectohz(10000));
11269087SZhong.Wang@Sun.COM }
11279087SZhong.Wang@Sun.COM
11289087SZhong.Wang@Sun.COM ddi_taskq_destroy(fcoe_worker_taskq);
11299087SZhong.Wang@Sun.COM kmem_free(fcoe_workers, sizeof (fcoe_worker_t) * fcoe_nworkers);
11309087SZhong.Wang@Sun.COM fcoe_workers = NULL;
11319087SZhong.Wang@Sun.COM return (FCOE_SUCCESS);
11329087SZhong.Wang@Sun.COM }
11339087SZhong.Wang@Sun.COM
11349087SZhong.Wang@Sun.COM static int
fcoe_crc_verify(fcoe_frame_t * frm)11359087SZhong.Wang@Sun.COM fcoe_crc_verify(fcoe_frame_t *frm)
11369087SZhong.Wang@Sun.COM {
11379087SZhong.Wang@Sun.COM uint32_t crc;
11389087SZhong.Wang@Sun.COM uint8_t *crc_array = FRM2FMI(frm)->fmi_fft->fft_crc;
11399087SZhong.Wang@Sun.COM uint32_t crc_from_frame = ~(crc_array[0] | (crc_array[1] << 8) |
11409087SZhong.Wang@Sun.COM (crc_array[2] << 16) | (crc_array[3] << 24));
11419087SZhong.Wang@Sun.COM CRC32(crc, frm->frm_fc_frame, frm->frm_fc_frame_size, -1U, crc32_table);
11429087SZhong.Wang@Sun.COM return (crc == crc_from_frame ? FCOE_SUCCESS : FCOE_FAILURE);
11439087SZhong.Wang@Sun.COM }
11449087SZhong.Wang@Sun.COM
11459087SZhong.Wang@Sun.COM static void
fcoe_worker_frame(void * arg)11469087SZhong.Wang@Sun.COM fcoe_worker_frame(void *arg)
11479087SZhong.Wang@Sun.COM {
11489087SZhong.Wang@Sun.COM fcoe_worker_t *w = (fcoe_worker_t *)arg;
11499087SZhong.Wang@Sun.COM fcoe_i_frame_t *fmi;
11509087SZhong.Wang@Sun.COM int ret;
11519087SZhong.Wang@Sun.COM
11529087SZhong.Wang@Sun.COM atomic_add_32(&fcoe_nworkers_running, 1);
11539087SZhong.Wang@Sun.COM mutex_enter(&w->worker_lock);
11549087SZhong.Wang@Sun.COM w->worker_flags |= FCOE_WORKER_STARTED | FCOE_WORKER_ACTIVE;
11559087SZhong.Wang@Sun.COM while ((w->worker_flags & FCOE_WORKER_TERMINATE) == 0) {
11569087SZhong.Wang@Sun.COM /*
11579087SZhong.Wang@Sun.COM * loop through the frames
11589087SZhong.Wang@Sun.COM */
11599087SZhong.Wang@Sun.COM while (fmi = list_head(&w->worker_frm_list)) {
11609087SZhong.Wang@Sun.COM list_remove(&w->worker_frm_list, fmi);
11619087SZhong.Wang@Sun.COM mutex_exit(&w->worker_lock);
11629087SZhong.Wang@Sun.COM /*
11639087SZhong.Wang@Sun.COM * do the checksum
11649087SZhong.Wang@Sun.COM */
11659087SZhong.Wang@Sun.COM ret = fcoe_crc_verify(fmi->fmi_frame);
11669087SZhong.Wang@Sun.COM if (ret == FCOE_SUCCESS) {
11679087SZhong.Wang@Sun.COM fmi->fmi_mac->fm_client.ect_rx_frame(
11689087SZhong.Wang@Sun.COM fmi->fmi_frame);
11699087SZhong.Wang@Sun.COM } else {
11709087SZhong.Wang@Sun.COM fcoe_release_frame(fmi->fmi_frame);
11719087SZhong.Wang@Sun.COM }
11729087SZhong.Wang@Sun.COM mutex_enter(&w->worker_lock);
11739087SZhong.Wang@Sun.COM w->worker_ntasks--;
11749087SZhong.Wang@Sun.COM }
11759087SZhong.Wang@Sun.COM w->worker_flags &= ~FCOE_WORKER_ACTIVE;
11769087SZhong.Wang@Sun.COM cv_wait(&w->worker_cv, &w->worker_lock);
11779087SZhong.Wang@Sun.COM w->worker_flags |= FCOE_WORKER_ACTIVE;
11789087SZhong.Wang@Sun.COM }
11799087SZhong.Wang@Sun.COM w->worker_flags &= ~(FCOE_WORKER_STARTED | FCOE_WORKER_ACTIVE);
11809087SZhong.Wang@Sun.COM mutex_exit(&w->worker_lock);
11819087SZhong.Wang@Sun.COM atomic_add_32(&fcoe_nworkers_running, -1);
11829087SZhong.Wang@Sun.COM list_destroy(&w->worker_frm_list);
11839087SZhong.Wang@Sun.COM }
11849087SZhong.Wang@Sun.COM
11859087SZhong.Wang@Sun.COM void
fcoe_post_frame(fcoe_frame_t * frm)11869087SZhong.Wang@Sun.COM fcoe_post_frame(fcoe_frame_t *frm)
11879087SZhong.Wang@Sun.COM {
11889087SZhong.Wang@Sun.COM fcoe_worker_t *w;
11899087SZhong.Wang@Sun.COM uint16_t oxid = FRM_OXID(frm);
11909087SZhong.Wang@Sun.COM
11919087SZhong.Wang@Sun.COM w = &fcoe_workers[oxid % fcoe_nworkers_running];
11929087SZhong.Wang@Sun.COM mutex_enter(&w->worker_lock);
11939087SZhong.Wang@Sun.COM list_insert_tail(&w->worker_frm_list, frm->frm_fcoe_private);
11949087SZhong.Wang@Sun.COM w->worker_ntasks++;
11959087SZhong.Wang@Sun.COM if ((w->worker_flags & FCOE_WORKER_ACTIVE) == 0) {
11969087SZhong.Wang@Sun.COM cv_signal(&w->worker_cv);
11979087SZhong.Wang@Sun.COM }
11989087SZhong.Wang@Sun.COM mutex_exit(&w->worker_lock);
11999087SZhong.Wang@Sun.COM }
12009087SZhong.Wang@Sun.COM
12019087SZhong.Wang@Sun.COM /*
12029087SZhong.Wang@Sun.COM * The max length of every LOG is 158
12039087SZhong.Wang@Sun.COM */
12049087SZhong.Wang@Sun.COM void
fcoe_trace(caddr_t ident,const char * fmt,...)12059087SZhong.Wang@Sun.COM fcoe_trace(caddr_t ident, const char *fmt, ...)
12069087SZhong.Wang@Sun.COM {
12079087SZhong.Wang@Sun.COM va_list args;
12089087SZhong.Wang@Sun.COM char tbuf[160];
12099087SZhong.Wang@Sun.COM int len;
12109087SZhong.Wang@Sun.COM clock_t curclock;
12119087SZhong.Wang@Sun.COM clock_t usec;
12129087SZhong.Wang@Sun.COM
12139087SZhong.Wang@Sun.COM if (fcoe_trace_on == 0) {
12149087SZhong.Wang@Sun.COM return;
12159087SZhong.Wang@Sun.COM }
12169087SZhong.Wang@Sun.COM
12179087SZhong.Wang@Sun.COM curclock = ddi_get_lbolt();
12189087SZhong.Wang@Sun.COM usec = (curclock - fcoe_trace_start) * usec_per_tick;
12199087SZhong.Wang@Sun.COM len = snprintf(tbuf, 158, "%lu.%03lus 0t%lu %s ", (usec /
12209087SZhong.Wang@Sun.COM (1000 * 1000)), ((usec % (1000 * 1000)) / 1000),
12219087SZhong.Wang@Sun.COM curclock, (ident ? ident : "unknown"));
12229087SZhong.Wang@Sun.COM va_start(args, fmt);
12239087SZhong.Wang@Sun.COM len += vsnprintf(tbuf + len, 158 - len, fmt, args);
12249087SZhong.Wang@Sun.COM va_end(args);
12259087SZhong.Wang@Sun.COM
12269087SZhong.Wang@Sun.COM if (len > 158) {
12279087SZhong.Wang@Sun.COM len = 158;
12289087SZhong.Wang@Sun.COM }
12299087SZhong.Wang@Sun.COM tbuf[len++] = '\n';
12309087SZhong.Wang@Sun.COM tbuf[len] = 0;
12319087SZhong.Wang@Sun.COM
12329087SZhong.Wang@Sun.COM mutex_enter(&fcoe_trace_buf_lock);
12339087SZhong.Wang@Sun.COM bcopy(tbuf, &fcoe_trace_buf[fcoe_trace_buf_curndx], len+1);
12349087SZhong.Wang@Sun.COM fcoe_trace_buf_curndx += len;
12359087SZhong.Wang@Sun.COM if (fcoe_trace_buf_curndx > (fcoe_trace_buf_size - 320)) {
12369087SZhong.Wang@Sun.COM fcoe_trace_buf_curndx = 0;
12379087SZhong.Wang@Sun.COM }
12389087SZhong.Wang@Sun.COM mutex_exit(&fcoe_trace_buf_lock);
12399087SZhong.Wang@Sun.COM }
12409087SZhong.Wang@Sun.COM
12419087SZhong.Wang@Sun.COM /*
12429087SZhong.Wang@Sun.COM * Check whether the pwwn or nwwn already exist or not
12439087SZhong.Wang@Sun.COM * Return value:
12449087SZhong.Wang@Sun.COM * 1: PWWN conflicted
12459087SZhong.Wang@Sun.COM * -1: NWWN conflicted
12469087SZhong.Wang@Sun.COM * 0: No conflict
12479087SZhong.Wang@Sun.COM */
12489087SZhong.Wang@Sun.COM static int
fcoe_cmp_wwn(fcoe_mac_t * checkedmac)12499087SZhong.Wang@Sun.COM fcoe_cmp_wwn(fcoe_mac_t *checkedmac)
12509087SZhong.Wang@Sun.COM {
12519087SZhong.Wang@Sun.COM fcoe_mac_t *mac;
12529087SZhong.Wang@Sun.COM uint8_t *nwwn, *pwwn, *cnwwn, *cpwwn;
12539087SZhong.Wang@Sun.COM
12549087SZhong.Wang@Sun.COM cnwwn = checkedmac->fm_eport.eport_nodewwn;
12559087SZhong.Wang@Sun.COM cpwwn = checkedmac->fm_eport.eport_portwwn;
12569307Skelly.hu@Sun.COM ASSERT(MUTEX_HELD(&fcoe_global_ss->ss_ioctl_mutex));
12579087SZhong.Wang@Sun.COM
12589087SZhong.Wang@Sun.COM for (mac = list_head(&fcoe_global_ss->ss_mac_list); mac;
12599087SZhong.Wang@Sun.COM mac = list_next(&fcoe_global_ss->ss_mac_list, mac)) {
12609087SZhong.Wang@Sun.COM if (mac == checkedmac) {
12619087SZhong.Wang@Sun.COM continue;
12629087SZhong.Wang@Sun.COM }
12639087SZhong.Wang@Sun.COM nwwn = mac->fm_eport.eport_nodewwn;
12649087SZhong.Wang@Sun.COM pwwn = mac->fm_eport.eport_portwwn;
12659087SZhong.Wang@Sun.COM
12669087SZhong.Wang@Sun.COM if (memcmp(nwwn, cnwwn, 8) == 0) {
12679087SZhong.Wang@Sun.COM return (-1);
12689087SZhong.Wang@Sun.COM }
12699087SZhong.Wang@Sun.COM
12709087SZhong.Wang@Sun.COM if (memcmp(pwwn, cpwwn, 8) == 0) {
12719087SZhong.Wang@Sun.COM return (1);
12729087SZhong.Wang@Sun.COM }
12739087SZhong.Wang@Sun.COM }
12749087SZhong.Wang@Sun.COM return (0);
12759087SZhong.Wang@Sun.COM }
12769087SZhong.Wang@Sun.COM
12779087SZhong.Wang@Sun.COM static int
fcoe_get_port_list(fcoe_port_instance_t * ports,int count)12789087SZhong.Wang@Sun.COM fcoe_get_port_list(fcoe_port_instance_t *ports, int count)
12799087SZhong.Wang@Sun.COM {
12809087SZhong.Wang@Sun.COM fcoe_mac_t *mac = NULL;
12819087SZhong.Wang@Sun.COM int i = 0;
12829087SZhong.Wang@Sun.COM
12839087SZhong.Wang@Sun.COM ASSERT(ports != NULL);
12849307Skelly.hu@Sun.COM ASSERT(MUTEX_HELD(&fcoe_global_ss->ss_ioctl_mutex));
12859087SZhong.Wang@Sun.COM
12869087SZhong.Wang@Sun.COM for (mac = list_head(&fcoe_global_ss->ss_mac_list); mac;
12879087SZhong.Wang@Sun.COM mac = list_next(&fcoe_global_ss->ss_mac_list, mac)) {
12889087SZhong.Wang@Sun.COM if (i < count) {
12899087SZhong.Wang@Sun.COM bcopy(mac->fm_eport.eport_portwwn,
12909087SZhong.Wang@Sun.COM ports[i].fpi_pwwn, 8);
12919307Skelly.hu@Sun.COM ports[i].fpi_mac_linkid = mac->fm_linkid;
12929087SZhong.Wang@Sun.COM bcopy(mac->fm_current_addr,
12939087SZhong.Wang@Sun.COM ports[i].fpi_mac_current_addr, ETHERADDRL);
12949087SZhong.Wang@Sun.COM bcopy(mac->fm_primary_addr,
12959087SZhong.Wang@Sun.COM ports[i].fpi_mac_factory_addr, ETHERADDRL);
12969087SZhong.Wang@Sun.COM ports[i].fpi_port_type =
12979087SZhong.Wang@Sun.COM EPORT_CLT_TYPE(&mac->fm_eport);
12989087SZhong.Wang@Sun.COM ports[i].fpi_mtu_size =
12999087SZhong.Wang@Sun.COM mac->fm_eport.eport_mtu;
13009087SZhong.Wang@Sun.COM ports[i].fpi_mac_promisc =
13019087SZhong.Wang@Sun.COM mac->fm_promisc_handle != NULL ? 1 : 0;
13029087SZhong.Wang@Sun.COM }
13039087SZhong.Wang@Sun.COM i++;
13049087SZhong.Wang@Sun.COM }
13059087SZhong.Wang@Sun.COM return (i);
13069087SZhong.Wang@Sun.COM }
1307