11991Sheppo /* 21991Sheppo * CDDL HEADER START 31991Sheppo * 41991Sheppo * The contents of this file are subject to the terms of the 51991Sheppo * Common Development and Distribution License (the "License"). 61991Sheppo * You may not use this file except in compliance with the License. 71991Sheppo * 81991Sheppo * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 91991Sheppo * or http://www.opensolaris.org/os/licensing. 101991Sheppo * See the License for the specific language governing permissions 111991Sheppo * and limitations under the License. 121991Sheppo * 131991Sheppo * When distributing Covered Code, include this CDDL HEADER in each 141991Sheppo * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 151991Sheppo * If applicable, add the following below this CDDL HEADER, with the 161991Sheppo * fields enclosed by brackets "[]" replaced with your own identifying 171991Sheppo * information: Portions Copyright [yyyy] [name of copyright owner] 181991Sheppo * 191991Sheppo * CDDL HEADER END 201991Sheppo */ 211991Sheppo 221991Sheppo /* 23*11543SWentao.Yang@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 241991Sheppo * Use is subject to license terms. 251991Sheppo */ 261991Sheppo 271991Sheppo #include <sys/types.h> 281991Sheppo #include <sys/errno.h> 291991Sheppo #include <sys/param.h> 301991Sheppo #include <sys/stream.h> 311991Sheppo #include <sys/kmem.h> 321991Sheppo #include <sys/conf.h> 331991Sheppo #include <sys/devops.h> 341991Sheppo #include <sys/ksynch.h> 351991Sheppo #include <sys/stat.h> 361991Sheppo #include <sys/modctl.h> 376419Ssb155480 #include <sys/modhash.h> 381991Sheppo #include <sys/debug.h> 391991Sheppo #include <sys/ethernet.h> 401991Sheppo #include <sys/dlpi.h> 411991Sheppo #include <net/if.h> 428275SEric Cheng #include <sys/mac_provider.h> 4310309SSriharsha.Basavapatna@Sun.COM #include <sys/mac_client.h> 4410309SSriharsha.Basavapatna@Sun.COM #include <sys/mac_client_priv.h> 452311Sseb #include <sys/mac_ether.h> 461991Sheppo #include <sys/ddi.h> 471991Sheppo #include <sys/sunddi.h> 481991Sheppo #include <sys/strsun.h> 491991Sheppo #include <sys/note.h> 506419Ssb155480 #include <sys/atomic.h> 511991Sheppo #include <sys/vnet.h> 526419Ssb155480 #include <sys/vlan.h> 536495Sspeer #include <sys/vnet_mailbox.h> 546495Sspeer #include <sys/vnet_common.h> 556495Sspeer #include <sys/dds.h> 566495Sspeer #include <sys/strsubr.h> 576495Sspeer #include <sys/taskq.h> 581991Sheppo 591991Sheppo /* 601991Sheppo * Function prototypes. 611991Sheppo */ 621991Sheppo 631991Sheppo /* DDI entrypoints */ 641991Sheppo static int vnetdevinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); 651991Sheppo static int vnetattach(dev_info_t *, ddi_attach_cmd_t); 661991Sheppo static int vnetdetach(dev_info_t *, ddi_detach_cmd_t); 671991Sheppo 681991Sheppo /* MAC entrypoints */ 692311Sseb static int vnet_m_stat(void *, uint_t, uint64_t *); 701991Sheppo static int vnet_m_start(void *); 711991Sheppo static void vnet_m_stop(void *); 721991Sheppo static int vnet_m_promisc(void *, boolean_t); 731991Sheppo static int vnet_m_multicst(void *, boolean_t, const uint8_t *); 741991Sheppo static int vnet_m_unicst(void *, const uint8_t *); 751991Sheppo mblk_t *vnet_m_tx(void *, mblk_t *); 769336SSriharsha.Basavapatna@Sun.COM static void vnet_m_ioctl(void *arg, queue_t *q, mblk_t *mp); 779336SSriharsha.Basavapatna@Sun.COM #ifdef VNET_IOC_DEBUG 789336SSriharsha.Basavapatna@Sun.COM static void vnet_force_link_state(vnet_t *vnetp, queue_t *q, mblk_t *mp); 799336SSriharsha.Basavapatna@Sun.COM #endif 8010309SSriharsha.Basavapatna@Sun.COM static boolean_t vnet_m_capab(void *arg, mac_capab_t cap, void *cap_data); 8110309SSriharsha.Basavapatna@Sun.COM static void vnet_get_ring(void *arg, mac_ring_type_t rtype, const int g_index, 8210309SSriharsha.Basavapatna@Sun.COM const int r_index, mac_ring_info_t *infop, mac_ring_handle_t r_handle); 8310309SSriharsha.Basavapatna@Sun.COM static void vnet_get_group(void *arg, mac_ring_type_t type, const int index, 8410309SSriharsha.Basavapatna@Sun.COM mac_group_info_t *infop, mac_group_handle_t handle); 8510309SSriharsha.Basavapatna@Sun.COM static int vnet_rx_ring_start(mac_ring_driver_t rdriver, uint64_t mr_gen_num); 8610309SSriharsha.Basavapatna@Sun.COM static void vnet_rx_ring_stop(mac_ring_driver_t rdriver); 8710309SSriharsha.Basavapatna@Sun.COM static int vnet_tx_ring_start(mac_ring_driver_t rdriver, uint64_t mr_gen_num); 8810309SSriharsha.Basavapatna@Sun.COM static void vnet_tx_ring_stop(mac_ring_driver_t rdriver); 8910309SSriharsha.Basavapatna@Sun.COM static int vnet_ring_enable_intr(void *arg); 9010309SSriharsha.Basavapatna@Sun.COM static int vnet_ring_disable_intr(void *arg); 9110309SSriharsha.Basavapatna@Sun.COM static mblk_t *vnet_rx_poll(void *arg, int bytes_to_pickup); 9210309SSriharsha.Basavapatna@Sun.COM static int vnet_addmac(void *arg, const uint8_t *mac_addr); 9310309SSriharsha.Basavapatna@Sun.COM static int vnet_remmac(void *arg, const uint8_t *mac_addr); 941991Sheppo 951991Sheppo /* vnet internal functions */ 969217SWentao.Yang@Sun.COM static int vnet_unattach(vnet_t *vnetp); 9710309SSriharsha.Basavapatna@Sun.COM static void vnet_ring_grp_init(vnet_t *vnetp); 9810309SSriharsha.Basavapatna@Sun.COM static void vnet_ring_grp_uninit(vnet_t *vnetp); 991991Sheppo static int vnet_mac_register(vnet_t *); 1001991Sheppo static int vnet_read_mac_address(vnet_t *vnetp); 10110309SSriharsha.Basavapatna@Sun.COM static int vnet_bind_vgenring(vnet_res_t *vresp); 10210309SSriharsha.Basavapatna@Sun.COM static void vnet_unbind_vgenring(vnet_res_t *vresp); 10310309SSriharsha.Basavapatna@Sun.COM static int vnet_bind_hwrings(vnet_t *vnetp); 10410309SSriharsha.Basavapatna@Sun.COM static void vnet_unbind_hwrings(vnet_t *vnetp); 10510309SSriharsha.Basavapatna@Sun.COM static int vnet_bind_rings(vnet_res_t *vresp); 10610309SSriharsha.Basavapatna@Sun.COM static void vnet_unbind_rings(vnet_res_t *vresp); 10710309SSriharsha.Basavapatna@Sun.COM static int vnet_hio_stat(void *, uint_t, uint64_t *); 10810309SSriharsha.Basavapatna@Sun.COM static int vnet_hio_start(void *); 10910309SSriharsha.Basavapatna@Sun.COM static void vnet_hio_stop(void *); 11010309SSriharsha.Basavapatna@Sun.COM static void vnet_hio_notify_cb(void *arg, mac_notify_type_t type); 11110309SSriharsha.Basavapatna@Sun.COM mblk_t *vnet_hio_tx(void *, mblk_t *); 1121991Sheppo 1136419Ssb155480 /* Forwarding database (FDB) routines */ 1146419Ssb155480 static void vnet_fdb_create(vnet_t *vnetp); 1156419Ssb155480 static void vnet_fdb_destroy(vnet_t *vnetp); 1166495Sspeer static vnet_res_t *vnet_fdbe_find(vnet_t *vnetp, struct ether_addr *addrp); 1176419Ssb155480 static void vnet_fdbe_find_cb(mod_hash_key_t key, mod_hash_val_t val); 1186495Sspeer void vnet_fdbe_add(vnet_t *vnetp, vnet_res_t *vresp); 1196495Sspeer static void vnet_fdbe_del(vnet_t *vnetp, vnet_res_t *vresp); 1206495Sspeer 1217896SSriharsha.Basavapatna@Sun.COM static void vnet_rx_frames_untag(uint16_t pvid, mblk_t **mp); 1226495Sspeer static void vnet_rx(vio_net_handle_t vrh, mblk_t *mp); 1236495Sspeer static void vnet_tx_update(vio_net_handle_t vrh); 1246495Sspeer static void vnet_res_start_task(void *arg); 1256495Sspeer static void vnet_start_resources(vnet_t *vnetp); 1266495Sspeer static void vnet_stop_resources(vnet_t *vnetp); 1276495Sspeer static void vnet_dispatch_res_task(vnet_t *vnetp); 1286495Sspeer static void vnet_res_start_task(void *arg); 1296495Sspeer static void vnet_handle_res_err(vio_net_handle_t vrh, vio_net_err_val_t err); 13010309SSriharsha.Basavapatna@Sun.COM static void vnet_add_resource(vnet_t *vnetp, vnet_res_t *vresp); 13110309SSriharsha.Basavapatna@Sun.COM static vnet_res_t *vnet_rem_resource(vnet_t *vnetp, vnet_res_t *vresp); 1329336SSriharsha.Basavapatna@Sun.COM 1339336SSriharsha.Basavapatna@Sun.COM /* Exported to vnet_gen */ 1347529SSriharsha.Basavapatna@Sun.COM int vnet_mtu_update(vnet_t *vnetp, uint32_t mtu); 1359336SSriharsha.Basavapatna@Sun.COM void vnet_link_update(vnet_t *vnetp, link_state_t link_state); 1369647SWentao.Yang@Sun.COM void vnet_dds_cleanup_hio(vnet_t *vnetp); 1376419Ssb155480 1388160SWentao.Yang@Sun.COM static kstat_t *vnet_hio_setup_kstats(char *ks_mod, char *ks_name, 1398160SWentao.Yang@Sun.COM vnet_res_t *vresp); 1408160SWentao.Yang@Sun.COM static int vnet_hio_update_kstats(kstat_t *ksp, int rw); 1418160SWentao.Yang@Sun.COM static void vnet_hio_get_stats(vnet_res_t *vresp, vnet_hio_stats_t *statsp); 1428160SWentao.Yang@Sun.COM static void vnet_hio_destroy_kstats(kstat_t *ksp); 1438160SWentao.Yang@Sun.COM 1446495Sspeer /* Exported to to vnet_dds */ 1456495Sspeer int vnet_send_dds_msg(vnet_t *vnetp, void *dmsg); 14610309SSriharsha.Basavapatna@Sun.COM int vnet_hio_mac_init(vnet_t *vnetp, char *ifname); 14710309SSriharsha.Basavapatna@Sun.COM void vnet_hio_mac_cleanup(vnet_t *vnetp); 1481991Sheppo 1496495Sspeer /* Externs that are imported from vnet_gen */ 1506495Sspeer extern int vgen_init(void *vnetp, uint64_t regprop, dev_info_t *vnetdip, 1516495Sspeer const uint8_t *macaddr, void **vgenhdl); 15210309SSriharsha.Basavapatna@Sun.COM extern int vgen_init_mdeg(void *arg); 1539235SWentao.Yang@Sun.COM extern void vgen_uninit(void *arg); 1546495Sspeer extern int vgen_dds_tx(void *arg, void *dmsg); 1559217SWentao.Yang@Sun.COM extern void vgen_mod_init(void); 1569217SWentao.Yang@Sun.COM extern int vgen_mod_cleanup(void); 1579217SWentao.Yang@Sun.COM extern void vgen_mod_fini(void); 15810309SSriharsha.Basavapatna@Sun.COM extern int vgen_enable_intr(void *arg); 15910309SSriharsha.Basavapatna@Sun.COM extern int vgen_disable_intr(void *arg); 16010309SSriharsha.Basavapatna@Sun.COM extern mblk_t *vgen_poll(void *arg, int bytes_to_pickup); 1616495Sspeer 1626495Sspeer /* Externs that are imported from vnet_dds */ 1636495Sspeer extern void vdds_mod_init(void); 1646495Sspeer extern void vdds_mod_fini(void); 1656495Sspeer extern int vdds_init(vnet_t *vnetp); 1666495Sspeer extern void vdds_cleanup(vnet_t *vnetp); 1676495Sspeer extern void vdds_process_dds_msg(vnet_t *vnetp, vio_dds_msg_t *dmsg); 1687819SRaghuram.Kothakota@Sun.COM extern void vdds_cleanup_hybrid_res(void *arg); 1699647SWentao.Yang@Sun.COM extern void vdds_cleanup_hio(vnet_t *vnetp); 1701991Sheppo 17110309SSriharsha.Basavapatna@Sun.COM /* Externs imported from mac_impl */ 17210309SSriharsha.Basavapatna@Sun.COM extern mblk_t *mac_hwring_tx(mac_ring_handle_t, mblk_t *); 17310309SSriharsha.Basavapatna@Sun.COM 1748160SWentao.Yang@Sun.COM #define DRV_NAME "vnet" 1756419Ssb155480 #define VNET_FDBE_REFHOLD(p) \ 1766419Ssb155480 { \ 1776419Ssb155480 atomic_inc_32(&(p)->refcnt); \ 1786419Ssb155480 ASSERT((p)->refcnt != 0); \ 1796419Ssb155480 } 1806419Ssb155480 1816419Ssb155480 #define VNET_FDBE_REFRELE(p) \ 1826419Ssb155480 { \ 1836419Ssb155480 ASSERT((p)->refcnt != 0); \ 1846419Ssb155480 atomic_dec_32(&(p)->refcnt); \ 1856419Ssb155480 } 1866419Ssb155480 1879336SSriharsha.Basavapatna@Sun.COM #ifdef VNET_IOC_DEBUG 18810309SSriharsha.Basavapatna@Sun.COM #define VNET_M_CALLBACK_FLAGS (MC_IOCTL | MC_GETCAPAB) 1899336SSriharsha.Basavapatna@Sun.COM #else 19010309SSriharsha.Basavapatna@Sun.COM #define VNET_M_CALLBACK_FLAGS (MC_GETCAPAB) 1919336SSriharsha.Basavapatna@Sun.COM #endif 1929336SSriharsha.Basavapatna@Sun.COM 1932311Sseb static mac_callbacks_t vnet_m_callbacks = { 1949336SSriharsha.Basavapatna@Sun.COM VNET_M_CALLBACK_FLAGS, 1952311Sseb vnet_m_stat, 1962311Sseb vnet_m_start, 1972311Sseb vnet_m_stop, 1982311Sseb vnet_m_promisc, 1992311Sseb vnet_m_multicst, 20010309SSriharsha.Basavapatna@Sun.COM NULL, /* m_unicst entry must be NULL while rx rings are exposed */ 20110309SSriharsha.Basavapatna@Sun.COM NULL, /* m_tx entry must be NULL while tx rings are exposed */ 2029336SSriharsha.Basavapatna@Sun.COM vnet_m_ioctl, 20310309SSriharsha.Basavapatna@Sun.COM vnet_m_capab, 20410309SSriharsha.Basavapatna@Sun.COM NULL 20510309SSriharsha.Basavapatna@Sun.COM }; 20610309SSriharsha.Basavapatna@Sun.COM 20710309SSriharsha.Basavapatna@Sun.COM static mac_callbacks_t vnet_hio_res_callbacks = { 20810309SSriharsha.Basavapatna@Sun.COM 0, 20910309SSriharsha.Basavapatna@Sun.COM vnet_hio_stat, 21010309SSriharsha.Basavapatna@Sun.COM vnet_hio_start, 21110309SSriharsha.Basavapatna@Sun.COM vnet_hio_stop, 21210309SSriharsha.Basavapatna@Sun.COM NULL, 21310309SSriharsha.Basavapatna@Sun.COM NULL, 21410309SSriharsha.Basavapatna@Sun.COM NULL, 21510309SSriharsha.Basavapatna@Sun.COM vnet_hio_tx, 21610309SSriharsha.Basavapatna@Sun.COM NULL, 2172311Sseb NULL, 2182311Sseb NULL 2192311Sseb }; 2202311Sseb 2211991Sheppo /* 2221991Sheppo * Linked list of "vnet_t" structures - one per instance. 2231991Sheppo */ 2241991Sheppo static vnet_t *vnet_headp = NULL; 2251991Sheppo static krwlock_t vnet_rw; 2261991Sheppo 2271991Sheppo /* Tunables */ 2281991Sheppo uint32_t vnet_ntxds = VNET_NTXDS; /* power of 2 transmit descriptors */ 2291991Sheppo uint32_t vnet_ldcwd_interval = VNET_LDCWD_INTERVAL; /* watchdog freq in msec */ 2301991Sheppo uint32_t vnet_ldcwd_txtimeout = VNET_LDCWD_TXTIMEOUT; /* tx timeout in msec */ 2312410Slm66018 uint32_t vnet_ldc_mtu = VNET_LDC_MTU; /* ldc mtu */ 2326419Ssb155480 23310309SSriharsha.Basavapatna@Sun.COM /* Configure tx serialization in mac layer for the vnet device */ 23410309SSriharsha.Basavapatna@Sun.COM boolean_t vnet_mac_tx_serialize = B_TRUE; 23510309SSriharsha.Basavapatna@Sun.COM 2367529SSriharsha.Basavapatna@Sun.COM /* 2377529SSriharsha.Basavapatna@Sun.COM * Set this to non-zero to enable additional internal receive buffer pools 2387529SSriharsha.Basavapatna@Sun.COM * based on the MTU of the device for better performance at the cost of more 2397529SSriharsha.Basavapatna@Sun.COM * memory consumption. This is turned off by default, to use allocb(9F) for 2407529SSriharsha.Basavapatna@Sun.COM * receive buffer allocations of sizes > 2K. 2417529SSriharsha.Basavapatna@Sun.COM */ 2427529SSriharsha.Basavapatna@Sun.COM boolean_t vnet_jumbo_rxpools = B_FALSE; 2437529SSriharsha.Basavapatna@Sun.COM 2446419Ssb155480 /* # of chains in fdb hash table */ 2456419Ssb155480 uint32_t vnet_fdb_nchains = VNET_NFDB_HASH; 2466419Ssb155480 2476419Ssb155480 /* Internal tunables */ 2486419Ssb155480 uint32_t vnet_ethermtu = 1500; /* mtu of the device */ 2496419Ssb155480 2506419Ssb155480 /* 2516419Ssb155480 * Default vlan id. This is only used internally when the "default-vlan-id" 2526419Ssb155480 * property is not present in the MD device node. Therefore, this should not be 2536419Ssb155480 * used as a tunable; if this value is changed, the corresponding variable 2546419Ssb155480 * should be updated to the same value in vsw and also other vnets connected to 2556419Ssb155480 * the same vsw. 2566419Ssb155480 */ 2576419Ssb155480 uint16_t vnet_default_vlan_id = 1; 2586419Ssb155480 2596419Ssb155480 /* delay in usec to wait for all references on a fdb entry to be dropped */ 2606419Ssb155480 uint32_t vnet_fdbe_refcnt_delay = 10; 2611991Sheppo 2626495Sspeer static struct ether_addr etherbroadcastaddr = { 2636495Sspeer 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 2646495Sspeer }; 2656495Sspeer 26610309SSriharsha.Basavapatna@Sun.COM /* mac_open() retry delay in usec */ 26710309SSriharsha.Basavapatna@Sun.COM uint32_t vnet_mac_open_delay = 100; /* 0.1 ms */ 26810309SSriharsha.Basavapatna@Sun.COM 26910309SSriharsha.Basavapatna@Sun.COM /* max # of mac_open() retries */ 27010309SSriharsha.Basavapatna@Sun.COM uint32_t vnet_mac_open_retries = 100; 2716495Sspeer 2721991Sheppo /* 2731991Sheppo * Property names 2741991Sheppo */ 2751991Sheppo static char macaddr_propname[] = "local-mac-address"; 2761991Sheppo 2771991Sheppo /* 2781991Sheppo * This is the string displayed by modinfo(1m). 2791991Sheppo */ 2807529SSriharsha.Basavapatna@Sun.COM static char vnet_ident[] = "vnet driver"; 2811991Sheppo extern struct mod_ops mod_driverops; 2821991Sheppo static struct cb_ops cb_vnetops = { 2831991Sheppo nulldev, /* cb_open */ 2841991Sheppo nulldev, /* cb_close */ 2851991Sheppo nodev, /* cb_strategy */ 2861991Sheppo nodev, /* cb_print */ 2871991Sheppo nodev, /* cb_dump */ 2881991Sheppo nodev, /* cb_read */ 2891991Sheppo nodev, /* cb_write */ 2901991Sheppo nodev, /* cb_ioctl */ 2911991Sheppo nodev, /* cb_devmap */ 2921991Sheppo nodev, /* cb_mmap */ 2931991Sheppo nodev, /* cb_segmap */ 2941991Sheppo nochpoll, /* cb_chpoll */ 2951991Sheppo ddi_prop_op, /* cb_prop_op */ 2961991Sheppo NULL, /* cb_stream */ 2971991Sheppo (int)(D_MP) /* cb_flag */ 2981991Sheppo }; 2991991Sheppo 3001991Sheppo static struct dev_ops vnetops = { 3011991Sheppo DEVO_REV, /* devo_rev */ 3021991Sheppo 0, /* devo_refcnt */ 3031991Sheppo NULL, /* devo_getinfo */ 3041991Sheppo nulldev, /* devo_identify */ 3051991Sheppo nulldev, /* devo_probe */ 3061991Sheppo vnetattach, /* devo_attach */ 3071991Sheppo vnetdetach, /* devo_detach */ 3081991Sheppo nodev, /* devo_reset */ 3091991Sheppo &cb_vnetops, /* devo_cb_ops */ 3107656SSherry.Moore@Sun.COM (struct bus_ops *)NULL, /* devo_bus_ops */ 3117656SSherry.Moore@Sun.COM NULL, /* devo_power */ 3127656SSherry.Moore@Sun.COM ddi_quiesce_not_supported, /* devo_quiesce */ 3131991Sheppo }; 3141991Sheppo 3151991Sheppo static struct modldrv modldrv = { 3161991Sheppo &mod_driverops, /* Type of module. This one is a driver */ 3171991Sheppo vnet_ident, /* ID string */ 3181991Sheppo &vnetops /* driver specific ops */ 3191991Sheppo }; 3201991Sheppo 3211991Sheppo static struct modlinkage modlinkage = { 3221991Sheppo MODREV_1, (void *)&modldrv, NULL 3231991Sheppo }; 3241991Sheppo 3254647Sraghuram #ifdef DEBUG 3261991Sheppo 3271991Sheppo /* 3281991Sheppo * Print debug messages - set to 0xf to enable all msgs 3291991Sheppo */ 3304647Sraghuram int vnet_dbglevel = 0x8; 3311991Sheppo 3324647Sraghuram static void 3334647Sraghuram debug_printf(const char *fname, void *arg, const char *fmt, ...) 3341991Sheppo { 3351991Sheppo char buf[512]; 3361991Sheppo va_list ap; 3371991Sheppo vnet_t *vnetp = (vnet_t *)arg; 3384647Sraghuram char *bufp = buf; 3391991Sheppo 3404647Sraghuram if (vnetp == NULL) { 3414647Sraghuram (void) sprintf(bufp, "%s: ", fname); 3424647Sraghuram bufp += strlen(bufp); 3434647Sraghuram } else { 3444647Sraghuram (void) sprintf(bufp, "vnet%d:%s: ", vnetp->instance, fname); 3454647Sraghuram bufp += strlen(bufp); 3464647Sraghuram } 3474647Sraghuram va_start(ap, fmt); 3484647Sraghuram (void) vsprintf(bufp, fmt, ap); 3494647Sraghuram va_end(ap); 3504647Sraghuram cmn_err(CE_CONT, "%s\n", buf); 3514647Sraghuram } 3521991Sheppo 3531991Sheppo #endif 3541991Sheppo 3551991Sheppo /* _init(9E): initialize the loadable module */ 3561991Sheppo int 3571991Sheppo _init(void) 3581991Sheppo { 3591991Sheppo int status; 3601991Sheppo 3614647Sraghuram DBG1(NULL, "enter\n"); 3621991Sheppo 3631991Sheppo mac_init_ops(&vnetops, "vnet"); 3641991Sheppo status = mod_install(&modlinkage); 3651991Sheppo if (status != 0) { 3661991Sheppo mac_fini_ops(&vnetops); 3671991Sheppo } 3686495Sspeer vdds_mod_init(); 3699217SWentao.Yang@Sun.COM vgen_mod_init(); 3704647Sraghuram DBG1(NULL, "exit(%d)\n", status); 3711991Sheppo return (status); 3721991Sheppo } 3731991Sheppo 3741991Sheppo /* _fini(9E): prepare the module for unloading. */ 3751991Sheppo int 3761991Sheppo _fini(void) 3771991Sheppo { 3789217SWentao.Yang@Sun.COM int status; 3791991Sheppo 3804647Sraghuram DBG1(NULL, "enter\n"); 3811991Sheppo 3829217SWentao.Yang@Sun.COM status = vgen_mod_cleanup(); 3839217SWentao.Yang@Sun.COM if (status != 0) 3849217SWentao.Yang@Sun.COM return (status); 3859217SWentao.Yang@Sun.COM 3861991Sheppo status = mod_remove(&modlinkage); 3871991Sheppo if (status != 0) 3881991Sheppo return (status); 3891991Sheppo mac_fini_ops(&vnetops); 3909217SWentao.Yang@Sun.COM vgen_mod_fini(); 3916495Sspeer vdds_mod_fini(); 3921991Sheppo 3934647Sraghuram DBG1(NULL, "exit(%d)\n", status); 3941991Sheppo return (status); 3951991Sheppo } 3961991Sheppo 3971991Sheppo /* _info(9E): return information about the loadable module */ 3981991Sheppo int 3991991Sheppo _info(struct modinfo *modinfop) 4001991Sheppo { 4011991Sheppo return (mod_info(&modlinkage, modinfop)); 4021991Sheppo } 4031991Sheppo 4041991Sheppo /* 4051991Sheppo * attach(9E): attach a device to the system. 4061991Sheppo * called once for each instance of the device on the system. 4071991Sheppo */ 4081991Sheppo static int 4091991Sheppo vnetattach(dev_info_t *dip, ddi_attach_cmd_t cmd) 4101991Sheppo { 4119217SWentao.Yang@Sun.COM vnet_t *vnetp; 4129217SWentao.Yang@Sun.COM int status; 4139217SWentao.Yang@Sun.COM int instance; 4149217SWentao.Yang@Sun.COM uint64_t reg; 4159217SWentao.Yang@Sun.COM char qname[TASKQ_NAMELEN]; 4169217SWentao.Yang@Sun.COM vnet_attach_progress_t attach_progress; 4171991Sheppo 4189217SWentao.Yang@Sun.COM attach_progress = AST_init; 4191991Sheppo 4201991Sheppo switch (cmd) { 4211991Sheppo case DDI_ATTACH: 4221991Sheppo break; 4231991Sheppo case DDI_RESUME: 4241991Sheppo case DDI_PM_RESUME: 4251991Sheppo default: 4261991Sheppo goto vnet_attach_fail; 4271991Sheppo } 4281991Sheppo 4291991Sheppo instance = ddi_get_instance(dip); 4304647Sraghuram DBG1(NULL, "instance(%d) enter\n", instance); 4311991Sheppo 4321991Sheppo /* allocate vnet_t and mac_t structures */ 4331991Sheppo vnetp = kmem_zalloc(sizeof (vnet_t), KM_SLEEP); 4346495Sspeer vnetp->dip = dip; 4356495Sspeer vnetp->instance = instance; 4366495Sspeer rw_init(&vnetp->vrwlock, NULL, RW_DRIVER, NULL); 4376495Sspeer rw_init(&vnetp->vsw_fp_rw, NULL, RW_DRIVER, NULL); 4389217SWentao.Yang@Sun.COM attach_progress |= AST_vnet_alloc; 4391991Sheppo 44010309SSriharsha.Basavapatna@Sun.COM vnet_ring_grp_init(vnetp); 44110309SSriharsha.Basavapatna@Sun.COM attach_progress |= AST_ring_init; 44210309SSriharsha.Basavapatna@Sun.COM 4436495Sspeer status = vdds_init(vnetp); 4446495Sspeer if (status != 0) { 4456495Sspeer goto vnet_attach_fail; 4466495Sspeer } 4479217SWentao.Yang@Sun.COM attach_progress |= AST_vdds_init; 4486495Sspeer 4491991Sheppo /* setup links to vnet_t from both devinfo and mac_t */ 4501991Sheppo ddi_set_driver_private(dip, (caddr_t)vnetp); 4511991Sheppo 4521991Sheppo /* read the mac address */ 4531991Sheppo status = vnet_read_mac_address(vnetp); 4541991Sheppo if (status != DDI_SUCCESS) { 4551991Sheppo goto vnet_attach_fail; 4561991Sheppo } 4579217SWentao.Yang@Sun.COM attach_progress |= AST_read_macaddr; 4581991Sheppo 4596495Sspeer reg = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 4606495Sspeer DDI_PROP_DONTPASS, "reg", -1); 4616495Sspeer if (reg == -1) { 4626495Sspeer goto vnet_attach_fail; 4636495Sspeer } 4646495Sspeer vnetp->reg = reg; 4656495Sspeer 4666495Sspeer vnet_fdb_create(vnetp); 4679217SWentao.Yang@Sun.COM attach_progress |= AST_fdbh_alloc; 4686495Sspeer 4696495Sspeer (void) snprintf(qname, TASKQ_NAMELEN, "vnet_taskq%d", instance); 4706495Sspeer if ((vnetp->taskqp = ddi_taskq_create(dip, qname, 1, 4716495Sspeer TASKQ_DEFAULTPRI, 0)) == NULL) { 4726495Sspeer cmn_err(CE_WARN, "!vnet%d: Unable to create task queue", 4736495Sspeer instance); 4746495Sspeer goto vnet_attach_fail; 4756495Sspeer } 4769217SWentao.Yang@Sun.COM attach_progress |= AST_taskq_create; 4776495Sspeer 4786495Sspeer /* add to the list of vnet devices */ 4796495Sspeer WRITE_ENTER(&vnet_rw); 4806495Sspeer vnetp->nextp = vnet_headp; 4816495Sspeer vnet_headp = vnetp; 4826495Sspeer RW_EXIT(&vnet_rw); 4836495Sspeer 4849217SWentao.Yang@Sun.COM attach_progress |= AST_vnet_list; 4856495Sspeer 4861991Sheppo /* 48710309SSriharsha.Basavapatna@Sun.COM * Initialize the generic vnet plugin which provides communication via 48810309SSriharsha.Basavapatna@Sun.COM * sun4v LDC (logical domain channel) based resources. This involves 2 48910309SSriharsha.Basavapatna@Sun.COM * steps; first, vgen_init() is invoked to read the various properties 49010309SSriharsha.Basavapatna@Sun.COM * of the vnet device from its MD node (including its mtu which is 49110309SSriharsha.Basavapatna@Sun.COM * needed to mac_register()) and obtain a handle to the vgen layer. 49210309SSriharsha.Basavapatna@Sun.COM * After mac_register() is done and we have a mac handle, we then 49310309SSriharsha.Basavapatna@Sun.COM * invoke vgen_init_mdeg() which registers with the the MD event 49410309SSriharsha.Basavapatna@Sun.COM * generator (mdeg) framework to allow LDC resource notifications. 49510309SSriharsha.Basavapatna@Sun.COM * Note: this sequence also allows us to report the correct default # 49610309SSriharsha.Basavapatna@Sun.COM * of pseudo rings (2TX and 3RX) in vnet_m_capab() which gets invoked 49710309SSriharsha.Basavapatna@Sun.COM * in the context of mac_register(); and avoids conflicting with 49810309SSriharsha.Basavapatna@Sun.COM * dynamic pseudo rx rings which get added/removed as a result of mdeg 49910309SSriharsha.Basavapatna@Sun.COM * events in vgen. 5001991Sheppo */ 5016495Sspeer status = vgen_init(vnetp, reg, vnetp->dip, 5026495Sspeer (uint8_t *)vnetp->curr_macaddr, &vnetp->vgenhdl); 5031991Sheppo if (status != DDI_SUCCESS) { 5044647Sraghuram DERR(vnetp, "vgen_init() failed\n"); 5051991Sheppo goto vnet_attach_fail; 5061991Sheppo } 5079217SWentao.Yang@Sun.COM attach_progress |= AST_vgen_init; 5081991Sheppo 5091991Sheppo status = vnet_mac_register(vnetp); 5101991Sheppo if (status != DDI_SUCCESS) { 5111991Sheppo goto vnet_attach_fail; 5121991Sheppo } 5139336SSriharsha.Basavapatna@Sun.COM vnetp->link_state = LINK_STATE_UNKNOWN; 5149217SWentao.Yang@Sun.COM attach_progress |= AST_macreg; 5159217SWentao.Yang@Sun.COM 51610309SSriharsha.Basavapatna@Sun.COM status = vgen_init_mdeg(vnetp->vgenhdl); 51710309SSriharsha.Basavapatna@Sun.COM if (status != DDI_SUCCESS) { 51810309SSriharsha.Basavapatna@Sun.COM goto vnet_attach_fail; 51910309SSriharsha.Basavapatna@Sun.COM } 52010309SSriharsha.Basavapatna@Sun.COM attach_progress |= AST_init_mdeg; 52110309SSriharsha.Basavapatna@Sun.COM 5229217SWentao.Yang@Sun.COM vnetp->attach_progress = attach_progress; 5239217SWentao.Yang@Sun.COM 5244647Sraghuram DBG1(NULL, "instance(%d) exit\n", instance); 5251991Sheppo return (DDI_SUCCESS); 5261991Sheppo 5271991Sheppo vnet_attach_fail: 5289217SWentao.Yang@Sun.COM vnetp->attach_progress = attach_progress; 5299235SWentao.Yang@Sun.COM status = vnet_unattach(vnetp); 5309235SWentao.Yang@Sun.COM ASSERT(status == 0); 5311991Sheppo return (DDI_FAILURE); 5321991Sheppo } 5331991Sheppo 5341991Sheppo /* 5351991Sheppo * detach(9E): detach a device from the system. 5361991Sheppo */ 5371991Sheppo static int 5381991Sheppo vnetdetach(dev_info_t *dip, ddi_detach_cmd_t cmd) 5391991Sheppo { 5401991Sheppo vnet_t *vnetp; 5411991Sheppo int instance; 5421991Sheppo 5431991Sheppo instance = ddi_get_instance(dip); 5444647Sraghuram DBG1(NULL, "instance(%d) enter\n", instance); 5451991Sheppo 5461991Sheppo vnetp = ddi_get_driver_private(dip); 5471991Sheppo if (vnetp == NULL) { 5481991Sheppo goto vnet_detach_fail; 5491991Sheppo } 5501991Sheppo 5511991Sheppo switch (cmd) { 5521991Sheppo case DDI_DETACH: 5531991Sheppo break; 5541991Sheppo case DDI_SUSPEND: 5551991Sheppo case DDI_PM_SUSPEND: 5561991Sheppo default: 5571991Sheppo goto vnet_detach_fail; 5581991Sheppo } 5591991Sheppo 5609217SWentao.Yang@Sun.COM if (vnet_unattach(vnetp) != 0) { 5616495Sspeer goto vnet_detach_fail; 5622336Snarayan } 5632336Snarayan 5641991Sheppo return (DDI_SUCCESS); 5651991Sheppo 5661991Sheppo vnet_detach_fail: 5671991Sheppo return (DDI_FAILURE); 5681991Sheppo } 5691991Sheppo 5709217SWentao.Yang@Sun.COM /* 5719217SWentao.Yang@Sun.COM * Common routine to handle vnetattach() failure and vnetdetach(). Note that 5729217SWentao.Yang@Sun.COM * the only reason this function could fail is if mac_unregister() fails. 5739217SWentao.Yang@Sun.COM * Otherwise, this function must ensure that all resources are freed and return 5749217SWentao.Yang@Sun.COM * success. 5759217SWentao.Yang@Sun.COM */ 5769217SWentao.Yang@Sun.COM static int 5779217SWentao.Yang@Sun.COM vnet_unattach(vnet_t *vnetp) 5789217SWentao.Yang@Sun.COM { 5799217SWentao.Yang@Sun.COM vnet_attach_progress_t attach_progress; 5809217SWentao.Yang@Sun.COM 5819217SWentao.Yang@Sun.COM attach_progress = vnetp->attach_progress; 5829217SWentao.Yang@Sun.COM 5839217SWentao.Yang@Sun.COM /* 58410309SSriharsha.Basavapatna@Sun.COM * Disable the mac device in the gldv3 subsystem. This can fail, in 58510309SSriharsha.Basavapatna@Sun.COM * particular if there are still any open references to this mac 58610309SSriharsha.Basavapatna@Sun.COM * device; in which case we just return failure without continuing to 58710309SSriharsha.Basavapatna@Sun.COM * detach further. 58810309SSriharsha.Basavapatna@Sun.COM * If it succeeds, we then invoke vgen_uninit() which should unregister 58910309SSriharsha.Basavapatna@Sun.COM * any pseudo rings registered with the mac layer. Note we keep the 59010309SSriharsha.Basavapatna@Sun.COM * AST_macreg flag on, so we can unregister with the mac layer at 59110309SSriharsha.Basavapatna@Sun.COM * the end of this routine. 5929217SWentao.Yang@Sun.COM */ 5939217SWentao.Yang@Sun.COM if (attach_progress & AST_macreg) { 59410309SSriharsha.Basavapatna@Sun.COM if (mac_disable(vnetp->mh) != 0) { 5959217SWentao.Yang@Sun.COM return (1); 5969217SWentao.Yang@Sun.COM } 5979217SWentao.Yang@Sun.COM } 5989217SWentao.Yang@Sun.COM 5999217SWentao.Yang@Sun.COM /* 60010309SSriharsha.Basavapatna@Sun.COM * Now that we have disabled the device, we must finish all other steps 60110309SSriharsha.Basavapatna@Sun.COM * and successfully return from this function; otherwise we will end up 60210309SSriharsha.Basavapatna@Sun.COM * leaving the device in a broken/unusable state. 6039217SWentao.Yang@Sun.COM * 6049217SWentao.Yang@Sun.COM * First, release any hybrid resources assigned to this vnet device. 6059217SWentao.Yang@Sun.COM */ 6069217SWentao.Yang@Sun.COM if (attach_progress & AST_vdds_init) { 6079217SWentao.Yang@Sun.COM vdds_cleanup(vnetp); 6089217SWentao.Yang@Sun.COM attach_progress &= ~AST_vdds_init; 6099217SWentao.Yang@Sun.COM } 6109217SWentao.Yang@Sun.COM 6119217SWentao.Yang@Sun.COM /* 6129217SWentao.Yang@Sun.COM * Uninit vgen. This stops further mdeg callbacks to this vnet 6139217SWentao.Yang@Sun.COM * device and/or its ports; and detaches any existing ports. 6149217SWentao.Yang@Sun.COM */ 61510309SSriharsha.Basavapatna@Sun.COM if (attach_progress & (AST_vgen_init|AST_init_mdeg)) { 6169217SWentao.Yang@Sun.COM vgen_uninit(vnetp->vgenhdl); 6179217SWentao.Yang@Sun.COM attach_progress &= ~AST_vgen_init; 61810309SSriharsha.Basavapatna@Sun.COM attach_progress &= ~AST_init_mdeg; 6199217SWentao.Yang@Sun.COM } 6209217SWentao.Yang@Sun.COM 6219217SWentao.Yang@Sun.COM /* Destroy the taskq. */ 6229217SWentao.Yang@Sun.COM if (attach_progress & AST_taskq_create) { 6239217SWentao.Yang@Sun.COM ddi_taskq_destroy(vnetp->taskqp); 6249217SWentao.Yang@Sun.COM attach_progress &= ~AST_taskq_create; 6259217SWentao.Yang@Sun.COM } 6269217SWentao.Yang@Sun.COM 6279217SWentao.Yang@Sun.COM /* Destroy fdb. */ 6289217SWentao.Yang@Sun.COM if (attach_progress & AST_fdbh_alloc) { 6299217SWentao.Yang@Sun.COM vnet_fdb_destroy(vnetp); 6309217SWentao.Yang@Sun.COM attach_progress &= ~AST_fdbh_alloc; 6319217SWentao.Yang@Sun.COM } 6329217SWentao.Yang@Sun.COM 6339217SWentao.Yang@Sun.COM /* Remove from the device list */ 6349217SWentao.Yang@Sun.COM if (attach_progress & AST_vnet_list) { 6359217SWentao.Yang@Sun.COM vnet_t **vnetpp; 6369217SWentao.Yang@Sun.COM /* unlink from instance(vnet_t) list */ 6379217SWentao.Yang@Sun.COM WRITE_ENTER(&vnet_rw); 6389217SWentao.Yang@Sun.COM for (vnetpp = &vnet_headp; *vnetpp; 6399217SWentao.Yang@Sun.COM vnetpp = &(*vnetpp)->nextp) { 6409217SWentao.Yang@Sun.COM if (*vnetpp == vnetp) { 6419217SWentao.Yang@Sun.COM *vnetpp = vnetp->nextp; 6429217SWentao.Yang@Sun.COM break; 6439217SWentao.Yang@Sun.COM } 6449217SWentao.Yang@Sun.COM } 6459217SWentao.Yang@Sun.COM RW_EXIT(&vnet_rw); 6469217SWentao.Yang@Sun.COM attach_progress &= ~AST_vnet_list; 6479217SWentao.Yang@Sun.COM } 6489217SWentao.Yang@Sun.COM 64910309SSriharsha.Basavapatna@Sun.COM if (attach_progress & AST_ring_init) { 65010309SSriharsha.Basavapatna@Sun.COM vnet_ring_grp_uninit(vnetp); 65110309SSriharsha.Basavapatna@Sun.COM attach_progress &= ~AST_ring_init; 65210309SSriharsha.Basavapatna@Sun.COM } 65310309SSriharsha.Basavapatna@Sun.COM 65410309SSriharsha.Basavapatna@Sun.COM if (attach_progress & AST_macreg) { 65510309SSriharsha.Basavapatna@Sun.COM VERIFY(mac_unregister(vnetp->mh) == 0); 65610309SSriharsha.Basavapatna@Sun.COM vnetp->mh = NULL; 65710309SSriharsha.Basavapatna@Sun.COM attach_progress &= ~AST_macreg; 65810309SSriharsha.Basavapatna@Sun.COM } 65910309SSriharsha.Basavapatna@Sun.COM 6609217SWentao.Yang@Sun.COM if (attach_progress & AST_vnet_alloc) { 6619217SWentao.Yang@Sun.COM rw_destroy(&vnetp->vrwlock); 6629217SWentao.Yang@Sun.COM rw_destroy(&vnetp->vsw_fp_rw); 6639217SWentao.Yang@Sun.COM attach_progress &= ~AST_vnet_list; 6649217SWentao.Yang@Sun.COM KMEM_FREE(vnetp); 6659217SWentao.Yang@Sun.COM } 6669217SWentao.Yang@Sun.COM 6679217SWentao.Yang@Sun.COM return (0); 6689217SWentao.Yang@Sun.COM } 6699217SWentao.Yang@Sun.COM 6701991Sheppo /* enable the device for transmit/receive */ 6711991Sheppo static int 6721991Sheppo vnet_m_start(void *arg) 6731991Sheppo { 6741991Sheppo vnet_t *vnetp = arg; 6751991Sheppo 6764647Sraghuram DBG1(vnetp, "enter\n"); 6771991Sheppo 6786495Sspeer WRITE_ENTER(&vnetp->vrwlock); 6796495Sspeer vnetp->flags |= VNET_STARTED; 6806495Sspeer vnet_start_resources(vnetp); 6816495Sspeer RW_EXIT(&vnetp->vrwlock); 6821991Sheppo 6834647Sraghuram DBG1(vnetp, "exit\n"); 6841991Sheppo return (VNET_SUCCESS); 6851991Sheppo 6861991Sheppo } 6871991Sheppo 6881991Sheppo /* stop transmit/receive for the device */ 6891991Sheppo static void 6901991Sheppo vnet_m_stop(void *arg) 6911991Sheppo { 6921991Sheppo vnet_t *vnetp = arg; 6931991Sheppo 6944647Sraghuram DBG1(vnetp, "enter\n"); 6951991Sheppo 6966495Sspeer WRITE_ENTER(&vnetp->vrwlock); 6976495Sspeer if (vnetp->flags & VNET_STARTED) { 6989805SSriharsha.Basavapatna@Sun.COM /* 6999805SSriharsha.Basavapatna@Sun.COM * Set the flags appropriately; this should prevent starting of 7009805SSriharsha.Basavapatna@Sun.COM * any new resources that are added(see vnet_res_start_task()), 7019805SSriharsha.Basavapatna@Sun.COM * while we release the vrwlock in vnet_stop_resources() before 7029805SSriharsha.Basavapatna@Sun.COM * stopping each resource. 7039805SSriharsha.Basavapatna@Sun.COM */ 7049805SSriharsha.Basavapatna@Sun.COM vnetp->flags &= ~VNET_STARTED; 7059805SSriharsha.Basavapatna@Sun.COM vnetp->flags |= VNET_STOPPING; 7066495Sspeer vnet_stop_resources(vnetp); 7079805SSriharsha.Basavapatna@Sun.COM vnetp->flags &= ~VNET_STOPPING; 7081991Sheppo } 7096495Sspeer RW_EXIT(&vnetp->vrwlock); 7101991Sheppo 7114647Sraghuram DBG1(vnetp, "exit\n"); 7121991Sheppo } 7131991Sheppo 7141991Sheppo /* set the unicast mac address of the device */ 7151991Sheppo static int 7161991Sheppo vnet_m_unicst(void *arg, const uint8_t *macaddr) 7171991Sheppo { 7181991Sheppo _NOTE(ARGUNUSED(macaddr)) 7191991Sheppo 7201991Sheppo vnet_t *vnetp = arg; 7211991Sheppo 7224647Sraghuram DBG1(vnetp, "enter\n"); 7231991Sheppo /* 7242793Slm66018 * NOTE: setting mac address dynamically is not supported. 7251991Sheppo */ 7264647Sraghuram DBG1(vnetp, "exit\n"); 7271991Sheppo 7282109Slm66018 return (VNET_FAILURE); 7291991Sheppo } 7301991Sheppo 7311991Sheppo /* enable/disable a multicast address */ 7321991Sheppo static int 7331991Sheppo vnet_m_multicst(void *arg, boolean_t add, const uint8_t *mca) 7341991Sheppo { 7351991Sheppo _NOTE(ARGUNUSED(add, mca)) 7361991Sheppo 737*11543SWentao.Yang@Sun.COM vnet_t *vnetp = arg; 7386495Sspeer vnet_res_t *vresp; 7396495Sspeer mac_register_t *macp; 7402311Sseb mac_callbacks_t *cbp; 741*11543SWentao.Yang@Sun.COM int rv = VNET_SUCCESS; 7421991Sheppo 7434647Sraghuram DBG1(vnetp, "enter\n"); 7446495Sspeer 745*11543SWentao.Yang@Sun.COM READ_ENTER(&vnetp->vsw_fp_rw); 746*11543SWentao.Yang@Sun.COM if (vnetp->vsw_fp == NULL) { 747*11543SWentao.Yang@Sun.COM RW_EXIT(&vnetp->vsw_fp_rw); 748*11543SWentao.Yang@Sun.COM return (EAGAIN); 7491991Sheppo } 750*11543SWentao.Yang@Sun.COM VNET_FDBE_REFHOLD(vnetp->vsw_fp); 751*11543SWentao.Yang@Sun.COM RW_EXIT(&vnetp->vsw_fp_rw); 752*11543SWentao.Yang@Sun.COM 753*11543SWentao.Yang@Sun.COM vresp = vnetp->vsw_fp; 754*11543SWentao.Yang@Sun.COM macp = &vresp->macreg; 755*11543SWentao.Yang@Sun.COM cbp = macp->m_callbacks; 756*11543SWentao.Yang@Sun.COM rv = cbp->mc_multicst(macp->m_driver, add, mca); 757*11543SWentao.Yang@Sun.COM 758*11543SWentao.Yang@Sun.COM VNET_FDBE_REFRELE(vnetp->vsw_fp); 7596495Sspeer 7604647Sraghuram DBG1(vnetp, "exit(%d)\n", rv); 7611991Sheppo return (rv); 7621991Sheppo } 7631991Sheppo 7641991Sheppo /* set or clear promiscuous mode on the device */ 7651991Sheppo static int 7661991Sheppo vnet_m_promisc(void *arg, boolean_t on) 7671991Sheppo { 7681991Sheppo _NOTE(ARGUNUSED(on)) 7691991Sheppo 7701991Sheppo vnet_t *vnetp = arg; 7714647Sraghuram DBG1(vnetp, "enter\n"); 7721991Sheppo /* 7732793Slm66018 * NOTE: setting promiscuous mode is not supported, just return success. 7741991Sheppo */ 7754647Sraghuram DBG1(vnetp, "exit\n"); 7761991Sheppo return (VNET_SUCCESS); 7771991Sheppo } 7781991Sheppo 7791991Sheppo /* 7801991Sheppo * Transmit a chain of packets. This function provides switching functionality 7811991Sheppo * based on the destination mac address to reach other guests (within ldoms) or 7821991Sheppo * external hosts. 7831991Sheppo */ 7841991Sheppo mblk_t * 78510309SSriharsha.Basavapatna@Sun.COM vnet_tx_ring_send(void *arg, mblk_t *mp) 7861991Sheppo { 78710309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_tx_ring_t *tx_ringp; 7886419Ssb155480 vnet_t *vnetp; 7896495Sspeer vnet_res_t *vresp; 7906419Ssb155480 mblk_t *next; 7916495Sspeer mblk_t *resid_mp; 7926495Sspeer mac_register_t *macp; 7936495Sspeer struct ether_header *ehp; 7946495Sspeer boolean_t is_unicast; 7957896SSriharsha.Basavapatna@Sun.COM boolean_t is_pvid; /* non-default pvid ? */ 7967896SSriharsha.Basavapatna@Sun.COM boolean_t hres; /* Hybrid resource ? */ 79710309SSriharsha.Basavapatna@Sun.COM void *tx_arg; 79810309SSriharsha.Basavapatna@Sun.COM 79910309SSriharsha.Basavapatna@Sun.COM tx_ringp = (vnet_pseudo_tx_ring_t *)arg; 80010309SSriharsha.Basavapatna@Sun.COM vnetp = (vnet_t *)tx_ringp->vnetp; 8014647Sraghuram DBG1(vnetp, "enter\n"); 8021991Sheppo ASSERT(mp != NULL); 8031991Sheppo 8047896SSriharsha.Basavapatna@Sun.COM is_pvid = (vnetp->pvid != vnetp->default_vlan_id) ? B_TRUE : B_FALSE; 8057896SSriharsha.Basavapatna@Sun.COM 8061991Sheppo while (mp != NULL) { 8076419Ssb155480 8081991Sheppo next = mp->b_next; 8091991Sheppo mp->b_next = NULL; 8101991Sheppo 8116419Ssb155480 /* 8126419Ssb155480 * Find fdb entry for the destination 8136419Ssb155480 * and hold a reference to it. 8146419Ssb155480 */ 8151991Sheppo ehp = (struct ether_header *)mp->b_rptr; 8166495Sspeer vresp = vnet_fdbe_find(vnetp, &ehp->ether_dhost); 8176495Sspeer if (vresp != NULL) { 8181991Sheppo 8191991Sheppo /* 8206419Ssb155480 * Destination found in FDB. 8216419Ssb155480 * The destination is a vnet device within ldoms 8226419Ssb155480 * and directly reachable, invoke the tx function 8236419Ssb155480 * in the fdb entry. 8241991Sheppo */ 8256495Sspeer macp = &vresp->macreg; 8266495Sspeer resid_mp = macp->m_callbacks->mc_tx(macp->m_driver, mp); 8276419Ssb155480 8286419Ssb155480 /* tx done; now release ref on fdb entry */ 8296495Sspeer VNET_FDBE_REFRELE(vresp); 8306419Ssb155480 8311991Sheppo if (resid_mp != NULL) { 8321991Sheppo /* m_tx failed */ 8331991Sheppo mp->b_next = next; 8341991Sheppo break; 8351991Sheppo } 8361991Sheppo } else { 8376495Sspeer is_unicast = !(IS_BROADCAST(ehp) || 8386495Sspeer (IS_MULTICAST(ehp))); 8391991Sheppo /* 8406419Ssb155480 * Destination is not in FDB. 8416495Sspeer * If the destination is broadcast or multicast, 8426495Sspeer * then forward the packet to vswitch. 8436495Sspeer * If a Hybrid resource avilable, then send the 8446495Sspeer * unicast packet via hybrid resource, otherwise 8456495Sspeer * forward it to vswitch. 8461991Sheppo */ 8476419Ssb155480 READ_ENTER(&vnetp->vsw_fp_rw); 8486419Ssb155480 8496495Sspeer if ((is_unicast) && (vnetp->hio_fp != NULL)) { 8506495Sspeer vresp = vnetp->hio_fp; 8517896SSriharsha.Basavapatna@Sun.COM hres = B_TRUE; 8526495Sspeer } else { 8536495Sspeer vresp = vnetp->vsw_fp; 8547896SSriharsha.Basavapatna@Sun.COM hres = B_FALSE; 8556495Sspeer } 8566495Sspeer if (vresp == NULL) { 8576419Ssb155480 /* 8586419Ssb155480 * no fdb entry to vsw? drop the packet. 8596419Ssb155480 */ 8606419Ssb155480 RW_EXIT(&vnetp->vsw_fp_rw); 8611991Sheppo freemsg(mp); 8626419Ssb155480 mp = next; 8636419Ssb155480 continue; 8641991Sheppo } 8656419Ssb155480 8666419Ssb155480 /* ref hold the fdb entry to vsw */ 8676495Sspeer VNET_FDBE_REFHOLD(vresp); 8686419Ssb155480 8696419Ssb155480 RW_EXIT(&vnetp->vsw_fp_rw); 8706419Ssb155480 8717896SSriharsha.Basavapatna@Sun.COM /* 8727896SSriharsha.Basavapatna@Sun.COM * In the case of a hybrid resource we need to insert 8737896SSriharsha.Basavapatna@Sun.COM * the tag for the pvid case here; unlike packets that 8747896SSriharsha.Basavapatna@Sun.COM * are destined to a vnet/vsw in which case the vgen 8757896SSriharsha.Basavapatna@Sun.COM * layer does the tagging before sending it over ldc. 8767896SSriharsha.Basavapatna@Sun.COM */ 8777896SSriharsha.Basavapatna@Sun.COM if (hres == B_TRUE) { 8787896SSriharsha.Basavapatna@Sun.COM /* 8797896SSriharsha.Basavapatna@Sun.COM * Determine if the frame being transmitted 8807896SSriharsha.Basavapatna@Sun.COM * over the hybrid resource is untagged. If so, 8817896SSriharsha.Basavapatna@Sun.COM * insert the tag before transmitting. 8827896SSriharsha.Basavapatna@Sun.COM */ 8837896SSriharsha.Basavapatna@Sun.COM if (is_pvid == B_TRUE && 8847896SSriharsha.Basavapatna@Sun.COM ehp->ether_type != htons(ETHERTYPE_VLAN)) { 8857896SSriharsha.Basavapatna@Sun.COM 8867896SSriharsha.Basavapatna@Sun.COM mp = vnet_vlan_insert_tag(mp, 8877896SSriharsha.Basavapatna@Sun.COM vnetp->pvid); 8887896SSriharsha.Basavapatna@Sun.COM if (mp == NULL) { 8897896SSriharsha.Basavapatna@Sun.COM VNET_FDBE_REFRELE(vresp); 8907896SSriharsha.Basavapatna@Sun.COM mp = next; 8917896SSriharsha.Basavapatna@Sun.COM continue; 8927896SSriharsha.Basavapatna@Sun.COM } 8937896SSriharsha.Basavapatna@Sun.COM 8947896SSriharsha.Basavapatna@Sun.COM } 89510309SSriharsha.Basavapatna@Sun.COM 89610309SSriharsha.Basavapatna@Sun.COM macp = &vresp->macreg; 89710309SSriharsha.Basavapatna@Sun.COM tx_arg = tx_ringp; 89810309SSriharsha.Basavapatna@Sun.COM } else { 89910309SSriharsha.Basavapatna@Sun.COM macp = &vresp->macreg; 90010309SSriharsha.Basavapatna@Sun.COM tx_arg = macp->m_driver; 9017896SSriharsha.Basavapatna@Sun.COM } 90210309SSriharsha.Basavapatna@Sun.COM resid_mp = macp->m_callbacks->mc_tx(tx_arg, mp); 9036419Ssb155480 9046419Ssb155480 /* tx done; now release ref on fdb entry */ 9056495Sspeer VNET_FDBE_REFRELE(vresp); 9066419Ssb155480 9076419Ssb155480 if (resid_mp != NULL) { 9086419Ssb155480 /* m_tx failed */ 9096419Ssb155480 mp->b_next = next; 9106419Ssb155480 break; 9116419Ssb155480 } 9121991Sheppo } 9131991Sheppo 9141991Sheppo mp = next; 9151991Sheppo } 9161991Sheppo 9174647Sraghuram DBG1(vnetp, "exit\n"); 9181991Sheppo return (mp); 9191991Sheppo } 9201991Sheppo 9212311Sseb /* get statistics from the device */ 9222311Sseb int 9232311Sseb vnet_m_stat(void *arg, uint_t stat, uint64_t *val) 9241991Sheppo { 9251991Sheppo vnet_t *vnetp = arg; 9266495Sspeer vnet_res_t *vresp; 9276495Sspeer mac_register_t *macp; 9282311Sseb mac_callbacks_t *cbp; 9292311Sseb uint64_t val_total = 0; 9301991Sheppo 9314647Sraghuram DBG1(vnetp, "enter\n"); 9321991Sheppo 9331991Sheppo /* 9342311Sseb * get the specified statistic from each transport and return the 9352311Sseb * aggregate val. This obviously only works for counters. 9361991Sheppo */ 9372311Sseb if ((IS_MAC_STAT(stat) && !MAC_STAT_ISACOUNTER(stat)) || 9382311Sseb (IS_MACTYPE_STAT(stat) && !ETHER_STAT_ISACOUNTER(stat))) { 9392311Sseb return (ENOTSUP); 9402311Sseb } 9416495Sspeer 9426495Sspeer READ_ENTER(&vnetp->vrwlock); 9436495Sspeer for (vresp = vnetp->vres_list; vresp != NULL; vresp = vresp->nextp) { 9446495Sspeer macp = &vresp->macreg; 9456495Sspeer cbp = macp->m_callbacks; 9466495Sspeer if (cbp->mc_getstat(macp->m_driver, stat, val) == 0) 9472311Sseb val_total += *val; 9481991Sheppo } 9496495Sspeer RW_EXIT(&vnetp->vrwlock); 9501991Sheppo 9512311Sseb *val = val_total; 9522311Sseb 9534647Sraghuram DBG1(vnetp, "exit\n"); 9542311Sseb return (0); 9551991Sheppo } 9561991Sheppo 95710309SSriharsha.Basavapatna@Sun.COM static void 95810309SSriharsha.Basavapatna@Sun.COM vnet_ring_grp_init(vnet_t *vnetp) 95910309SSriharsha.Basavapatna@Sun.COM { 96010309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_group_t *rx_grp; 96110309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_ring_t *rx_ringp; 96210309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_tx_group_t *tx_grp; 96310309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_tx_ring_t *tx_ringp; 96410309SSriharsha.Basavapatna@Sun.COM int i; 96510309SSriharsha.Basavapatna@Sun.COM 96610309SSriharsha.Basavapatna@Sun.COM tx_grp = &vnetp->tx_grp[0]; 96710309SSriharsha.Basavapatna@Sun.COM tx_ringp = kmem_zalloc(sizeof (vnet_pseudo_tx_ring_t) * 96810309SSriharsha.Basavapatna@Sun.COM VNET_NUM_PSEUDO_TXRINGS, KM_SLEEP); 96910309SSriharsha.Basavapatna@Sun.COM for (i = 0; i < VNET_NUM_PSEUDO_TXRINGS; i++) { 97010309SSriharsha.Basavapatna@Sun.COM tx_ringp[i].state |= VNET_TXRING_SHARED; 97110309SSriharsha.Basavapatna@Sun.COM } 97210309SSriharsha.Basavapatna@Sun.COM tx_grp->rings = tx_ringp; 97310309SSriharsha.Basavapatna@Sun.COM tx_grp->ring_cnt = VNET_NUM_PSEUDO_TXRINGS; 97410309SSriharsha.Basavapatna@Sun.COM 97510309SSriharsha.Basavapatna@Sun.COM rx_grp = &vnetp->rx_grp[0]; 97610309SSriharsha.Basavapatna@Sun.COM rx_grp->max_ring_cnt = MAX_RINGS_PER_GROUP; 97710309SSriharsha.Basavapatna@Sun.COM rw_init(&rx_grp->lock, NULL, RW_DRIVER, NULL); 97810309SSriharsha.Basavapatna@Sun.COM rx_ringp = kmem_zalloc(sizeof (vnet_pseudo_rx_ring_t) * 97910309SSriharsha.Basavapatna@Sun.COM rx_grp->max_ring_cnt, KM_SLEEP); 98010309SSriharsha.Basavapatna@Sun.COM 98110309SSriharsha.Basavapatna@Sun.COM /* 98210309SSriharsha.Basavapatna@Sun.COM * Setup the first 3 Pseudo RX Rings that are reserved; 98310309SSriharsha.Basavapatna@Sun.COM * 1 for LDC resource to vswitch + 2 for RX rings of Hybrid resource. 98410309SSriharsha.Basavapatna@Sun.COM */ 98510309SSriharsha.Basavapatna@Sun.COM rx_ringp[0].state |= VNET_RXRING_INUSE|VNET_RXRING_LDC_SERVICE; 98610309SSriharsha.Basavapatna@Sun.COM rx_ringp[0].index = 0; 98710309SSriharsha.Basavapatna@Sun.COM rx_ringp[1].state |= VNET_RXRING_INUSE|VNET_RXRING_HYBRID; 98810309SSriharsha.Basavapatna@Sun.COM rx_ringp[1].index = 1; 98910309SSriharsha.Basavapatna@Sun.COM rx_ringp[2].state |= VNET_RXRING_INUSE|VNET_RXRING_HYBRID; 99010309SSriharsha.Basavapatna@Sun.COM rx_ringp[2].index = 2; 99110309SSriharsha.Basavapatna@Sun.COM 99210309SSriharsha.Basavapatna@Sun.COM rx_grp->ring_cnt = VNET_NUM_PSEUDO_RXRINGS_DEFAULT; 99310309SSriharsha.Basavapatna@Sun.COM rx_grp->rings = rx_ringp; 99410309SSriharsha.Basavapatna@Sun.COM 99510309SSriharsha.Basavapatna@Sun.COM for (i = VNET_NUM_PSEUDO_RXRINGS_DEFAULT; 99610309SSriharsha.Basavapatna@Sun.COM i < rx_grp->max_ring_cnt; i++) { 99710309SSriharsha.Basavapatna@Sun.COM rx_ringp = &rx_grp->rings[i]; 99810309SSriharsha.Basavapatna@Sun.COM rx_ringp->state = VNET_RXRING_FREE; 99910309SSriharsha.Basavapatna@Sun.COM rx_ringp->index = i; 100010309SSriharsha.Basavapatna@Sun.COM } 100110309SSriharsha.Basavapatna@Sun.COM } 100210309SSriharsha.Basavapatna@Sun.COM 100310309SSriharsha.Basavapatna@Sun.COM static void 100410309SSriharsha.Basavapatna@Sun.COM vnet_ring_grp_uninit(vnet_t *vnetp) 100510309SSriharsha.Basavapatna@Sun.COM { 100610309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_group_t *rx_grp; 100710309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_tx_group_t *tx_grp; 100810309SSriharsha.Basavapatna@Sun.COM 100910309SSriharsha.Basavapatna@Sun.COM tx_grp = &vnetp->tx_grp[0]; 101010309SSriharsha.Basavapatna@Sun.COM if (tx_grp->rings != NULL) { 101110309SSriharsha.Basavapatna@Sun.COM ASSERT(tx_grp->ring_cnt == VNET_NUM_PSEUDO_TXRINGS); 101210309SSriharsha.Basavapatna@Sun.COM kmem_free(tx_grp->rings, sizeof (vnet_pseudo_tx_ring_t) * 101310309SSriharsha.Basavapatna@Sun.COM tx_grp->ring_cnt); 101410309SSriharsha.Basavapatna@Sun.COM tx_grp->rings = NULL; 101510309SSriharsha.Basavapatna@Sun.COM } 101610309SSriharsha.Basavapatna@Sun.COM 101710309SSriharsha.Basavapatna@Sun.COM rx_grp = &vnetp->rx_grp[0]; 101810309SSriharsha.Basavapatna@Sun.COM if (rx_grp->rings != NULL) { 101910309SSriharsha.Basavapatna@Sun.COM ASSERT(rx_grp->max_ring_cnt == MAX_RINGS_PER_GROUP); 102010309SSriharsha.Basavapatna@Sun.COM ASSERT(rx_grp->ring_cnt == VNET_NUM_PSEUDO_RXRINGS_DEFAULT); 102110309SSriharsha.Basavapatna@Sun.COM kmem_free(rx_grp->rings, sizeof (vnet_pseudo_rx_ring_t) * 102210309SSriharsha.Basavapatna@Sun.COM rx_grp->max_ring_cnt); 102310309SSriharsha.Basavapatna@Sun.COM rx_grp->rings = NULL; 102410309SSriharsha.Basavapatna@Sun.COM } 102510309SSriharsha.Basavapatna@Sun.COM } 102610309SSriharsha.Basavapatna@Sun.COM 102710309SSriharsha.Basavapatna@Sun.COM static vnet_pseudo_rx_ring_t * 102810309SSriharsha.Basavapatna@Sun.COM vnet_alloc_pseudo_rx_ring(vnet_t *vnetp) 102910309SSriharsha.Basavapatna@Sun.COM { 103010309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_group_t *rx_grp; 103110309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_ring_t *rx_ringp; 103210309SSriharsha.Basavapatna@Sun.COM int index; 103310309SSriharsha.Basavapatna@Sun.COM 103410309SSriharsha.Basavapatna@Sun.COM rx_grp = &vnetp->rx_grp[0]; 103510309SSriharsha.Basavapatna@Sun.COM WRITE_ENTER(&rx_grp->lock); 103610309SSriharsha.Basavapatna@Sun.COM 103710309SSriharsha.Basavapatna@Sun.COM if (rx_grp->ring_cnt == rx_grp->max_ring_cnt) { 103810309SSriharsha.Basavapatna@Sun.COM /* no rings available */ 103910309SSriharsha.Basavapatna@Sun.COM RW_EXIT(&rx_grp->lock); 104010309SSriharsha.Basavapatna@Sun.COM return (NULL); 104110309SSriharsha.Basavapatna@Sun.COM } 104210309SSriharsha.Basavapatna@Sun.COM 104310309SSriharsha.Basavapatna@Sun.COM for (index = VNET_NUM_PSEUDO_RXRINGS_DEFAULT; 104410309SSriharsha.Basavapatna@Sun.COM index < rx_grp->max_ring_cnt; index++) { 104510309SSriharsha.Basavapatna@Sun.COM rx_ringp = &rx_grp->rings[index]; 104610309SSriharsha.Basavapatna@Sun.COM if (rx_ringp->state == VNET_RXRING_FREE) { 104710309SSriharsha.Basavapatna@Sun.COM rx_ringp->state |= VNET_RXRING_INUSE; 104810309SSriharsha.Basavapatna@Sun.COM rx_grp->ring_cnt++; 104910309SSriharsha.Basavapatna@Sun.COM break; 105010309SSriharsha.Basavapatna@Sun.COM } 105110309SSriharsha.Basavapatna@Sun.COM } 105210309SSriharsha.Basavapatna@Sun.COM 105310309SSriharsha.Basavapatna@Sun.COM RW_EXIT(&rx_grp->lock); 105410309SSriharsha.Basavapatna@Sun.COM return (rx_ringp); 105510309SSriharsha.Basavapatna@Sun.COM } 105610309SSriharsha.Basavapatna@Sun.COM 105710309SSriharsha.Basavapatna@Sun.COM static void 105810309SSriharsha.Basavapatna@Sun.COM vnet_free_pseudo_rx_ring(vnet_t *vnetp, vnet_pseudo_rx_ring_t *ringp) 105910309SSriharsha.Basavapatna@Sun.COM { 106010309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_group_t *rx_grp; 106110309SSriharsha.Basavapatna@Sun.COM 106210309SSriharsha.Basavapatna@Sun.COM ASSERT(ringp->index >= VNET_NUM_PSEUDO_RXRINGS_DEFAULT); 106310309SSriharsha.Basavapatna@Sun.COM rx_grp = &vnetp->rx_grp[0]; 106410309SSriharsha.Basavapatna@Sun.COM WRITE_ENTER(&rx_grp->lock); 106510309SSriharsha.Basavapatna@Sun.COM 106610309SSriharsha.Basavapatna@Sun.COM if (ringp->state != VNET_RXRING_FREE) { 106710309SSriharsha.Basavapatna@Sun.COM ringp->state = VNET_RXRING_FREE; 106810309SSriharsha.Basavapatna@Sun.COM ringp->handle = NULL; 106910309SSriharsha.Basavapatna@Sun.COM rx_grp->ring_cnt--; 107010309SSriharsha.Basavapatna@Sun.COM } 107110309SSriharsha.Basavapatna@Sun.COM 107210309SSriharsha.Basavapatna@Sun.COM RW_EXIT(&rx_grp->lock); 107310309SSriharsha.Basavapatna@Sun.COM } 107410309SSriharsha.Basavapatna@Sun.COM 10751991Sheppo /* wrapper function for mac_register() */ 10761991Sheppo static int 10771991Sheppo vnet_mac_register(vnet_t *vnetp) 10781991Sheppo { 10792311Sseb mac_register_t *macp; 10802311Sseb int err; 10811991Sheppo 10822311Sseb if ((macp = mac_alloc(MAC_VERSION)) == NULL) 10832311Sseb return (DDI_FAILURE); 10842311Sseb macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 10852311Sseb macp->m_driver = vnetp; 10861991Sheppo macp->m_dip = vnetp->dip; 10872311Sseb macp->m_src_addr = vnetp->curr_macaddr; 10882311Sseb macp->m_callbacks = &vnet_m_callbacks; 10892311Sseb macp->m_min_sdu = 0; 10907529SSriharsha.Basavapatna@Sun.COM macp->m_max_sdu = vnetp->mtu; 10916419Ssb155480 macp->m_margin = VLAN_TAGSZ; 10921991Sheppo 10931991Sheppo /* 109410309SSriharsha.Basavapatna@Sun.COM * MAC_VIRT_SERIALIZE flag is needed while hybridIO is enabled to 109510309SSriharsha.Basavapatna@Sun.COM * workaround tx lock contention issues in nxge. 109610309SSriharsha.Basavapatna@Sun.COM */ 109710309SSriharsha.Basavapatna@Sun.COM macp->m_v12n = MAC_VIRT_LEVEL1; 109810309SSriharsha.Basavapatna@Sun.COM if (vnet_mac_tx_serialize == B_TRUE) { 109910309SSriharsha.Basavapatna@Sun.COM macp->m_v12n |= MAC_VIRT_SERIALIZE; 110010309SSriharsha.Basavapatna@Sun.COM } 110110309SSriharsha.Basavapatna@Sun.COM 110210309SSriharsha.Basavapatna@Sun.COM /* 11031991Sheppo * Finally, we're ready to register ourselves with the MAC layer 11041991Sheppo * interface; if this succeeds, we're all ready to start() 11051991Sheppo */ 11062311Sseb err = mac_register(macp, &vnetp->mh); 11072311Sseb mac_free(macp); 11082311Sseb return (err == 0 ? DDI_SUCCESS : DDI_FAILURE); 11091991Sheppo } 11101991Sheppo 11111991Sheppo /* read the mac address of the device */ 11121991Sheppo static int 11131991Sheppo vnet_read_mac_address(vnet_t *vnetp) 11141991Sheppo { 11151991Sheppo uchar_t *macaddr; 11161991Sheppo uint32_t size; 11171991Sheppo int rv; 11181991Sheppo 11191991Sheppo rv = ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, vnetp->dip, 11204650Sraghuram DDI_PROP_DONTPASS, macaddr_propname, &macaddr, &size); 11211991Sheppo if ((rv != DDI_PROP_SUCCESS) || (size != ETHERADDRL)) { 11224647Sraghuram DWARN(vnetp, "prop_lookup failed(%s) err(%d)\n", 11234647Sraghuram macaddr_propname, rv); 11241991Sheppo return (DDI_FAILURE); 11251991Sheppo } 11261991Sheppo bcopy(macaddr, (caddr_t)vnetp->vendor_addr, ETHERADDRL); 11271991Sheppo bcopy(macaddr, (caddr_t)vnetp->curr_macaddr, ETHERADDRL); 11281991Sheppo ddi_prop_free(macaddr); 11291991Sheppo 11301991Sheppo return (DDI_SUCCESS); 11311991Sheppo } 11321991Sheppo 11336419Ssb155480 static void 11346419Ssb155480 vnet_fdb_create(vnet_t *vnetp) 11351991Sheppo { 11366419Ssb155480 char hashname[MAXNAMELEN]; 11371991Sheppo 11386419Ssb155480 (void) snprintf(hashname, MAXNAMELEN, "vnet%d-fdbhash", 11396419Ssb155480 vnetp->instance); 11406419Ssb155480 vnetp->fdb_nchains = vnet_fdb_nchains; 11416419Ssb155480 vnetp->fdb_hashp = mod_hash_create_ptrhash(hashname, vnetp->fdb_nchains, 11426419Ssb155480 mod_hash_null_valdtor, sizeof (void *)); 11436419Ssb155480 } 11441991Sheppo 11456419Ssb155480 static void 11466419Ssb155480 vnet_fdb_destroy(vnet_t *vnetp) 11476419Ssb155480 { 11486419Ssb155480 /* destroy fdb-hash-table */ 11496419Ssb155480 if (vnetp->fdb_hashp != NULL) { 11506419Ssb155480 mod_hash_destroy_hash(vnetp->fdb_hashp); 11516419Ssb155480 vnetp->fdb_hashp = NULL; 11526419Ssb155480 vnetp->fdb_nchains = 0; 11531991Sheppo } 11541991Sheppo } 11551991Sheppo 11566419Ssb155480 /* 11576419Ssb155480 * Add an entry into the fdb. 11586419Ssb155480 */ 11591991Sheppo void 11606495Sspeer vnet_fdbe_add(vnet_t *vnetp, vnet_res_t *vresp) 11611991Sheppo { 11626419Ssb155480 uint64_t addr = 0; 11636419Ssb155480 int rv; 11646419Ssb155480 11656495Sspeer KEY_HASH(addr, vresp->rem_macaddr); 11661991Sheppo 11676419Ssb155480 /* 11686495Sspeer * If the entry being added corresponds to LDC_SERVICE resource, 11696495Sspeer * that is, vswitch connection, it is added to the hash and also 11706495Sspeer * the entry is cached, an additional reference count reflects 11716495Sspeer * this. The HYBRID resource is not added to the hash, but only 11726495Sspeer * cached, as it is only used for sending out packets for unknown 11736495Sspeer * unicast destinations. 11746419Ssb155480 */ 11756495Sspeer (vresp->type == VIO_NET_RES_LDC_SERVICE) ? 11766495Sspeer (vresp->refcnt = 1) : (vresp->refcnt = 0); 11771991Sheppo 11786419Ssb155480 /* 11796419Ssb155480 * Note: duplicate keys will be rejected by mod_hash. 11806419Ssb155480 */ 11816495Sspeer if (vresp->type != VIO_NET_RES_HYBRID) { 11826495Sspeer rv = mod_hash_insert(vnetp->fdb_hashp, (mod_hash_key_t)addr, 11836495Sspeer (mod_hash_val_t)vresp); 11846495Sspeer if (rv != 0) { 11856495Sspeer DWARN(vnetp, "Duplicate macaddr key(%lx)\n", addr); 11866495Sspeer return; 11876495Sspeer } 11881991Sheppo } 11891991Sheppo 11906495Sspeer if (vresp->type == VIO_NET_RES_LDC_SERVICE) { 11916419Ssb155480 /* Cache the fdb entry to vsw-port */ 11926419Ssb155480 WRITE_ENTER(&vnetp->vsw_fp_rw); 11936419Ssb155480 if (vnetp->vsw_fp == NULL) 11946495Sspeer vnetp->vsw_fp = vresp; 11956495Sspeer RW_EXIT(&vnetp->vsw_fp_rw); 11966495Sspeer } else if (vresp->type == VIO_NET_RES_HYBRID) { 11976495Sspeer /* Cache the fdb entry to hybrid resource */ 11986495Sspeer WRITE_ENTER(&vnetp->vsw_fp_rw); 11996495Sspeer if (vnetp->hio_fp == NULL) 12006495Sspeer vnetp->hio_fp = vresp; 12016419Ssb155480 RW_EXIT(&vnetp->vsw_fp_rw); 12022793Slm66018 } 12031991Sheppo } 12041991Sheppo 12056419Ssb155480 /* 12066419Ssb155480 * Remove an entry from fdb. 12076419Ssb155480 */ 12086495Sspeer static void 12096495Sspeer vnet_fdbe_del(vnet_t *vnetp, vnet_res_t *vresp) 12105641Swentaoy { 12116419Ssb155480 uint64_t addr = 0; 12126419Ssb155480 int rv; 12136419Ssb155480 uint32_t refcnt; 12146495Sspeer vnet_res_t *tmp; 12155641Swentaoy 12166495Sspeer KEY_HASH(addr, vresp->rem_macaddr); 12175641Swentaoy 12186419Ssb155480 /* 12196419Ssb155480 * Remove the entry from fdb hash table. 12206419Ssb155480 * This prevents further references to this fdb entry. 12216419Ssb155480 */ 12226495Sspeer if (vresp->type != VIO_NET_RES_HYBRID) { 12236495Sspeer rv = mod_hash_remove(vnetp->fdb_hashp, (mod_hash_key_t)addr, 12246495Sspeer (mod_hash_val_t *)&tmp); 12256495Sspeer if (rv != 0) { 12266495Sspeer /* 12276495Sspeer * As the resources are added to the hash only 12286495Sspeer * after they are started, this can occur if 12296495Sspeer * a resource unregisters before it is ever started. 12306495Sspeer */ 12316495Sspeer return; 12326495Sspeer } 12336495Sspeer } 12345641Swentaoy 12356495Sspeer if (vresp->type == VIO_NET_RES_LDC_SERVICE) { 12366419Ssb155480 WRITE_ENTER(&vnetp->vsw_fp_rw); 12375641Swentaoy 12386495Sspeer ASSERT(tmp == vnetp->vsw_fp); 12396419Ssb155480 vnetp->vsw_fp = NULL; 12406419Ssb155480 12416419Ssb155480 RW_EXIT(&vnetp->vsw_fp_rw); 12426495Sspeer } else if (vresp->type == VIO_NET_RES_HYBRID) { 12436495Sspeer WRITE_ENTER(&vnetp->vsw_fp_rw); 12446495Sspeer 12456495Sspeer vnetp->hio_fp = NULL; 12466495Sspeer 12476495Sspeer RW_EXIT(&vnetp->vsw_fp_rw); 12485641Swentaoy } 12495641Swentaoy 12505641Swentaoy /* 12516419Ssb155480 * If there are threads already ref holding before the entry was 12526419Ssb155480 * removed from hash table, then wait for ref count to drop to zero. 12535641Swentaoy */ 12546495Sspeer (vresp->type == VIO_NET_RES_LDC_SERVICE) ? 12556495Sspeer (refcnt = 1) : (refcnt = 0); 12566495Sspeer while (vresp->refcnt > refcnt) { 12576419Ssb155480 delay(drv_usectohz(vnet_fdbe_refcnt_delay)); 12586419Ssb155480 } 12591991Sheppo } 12601991Sheppo 12616419Ssb155480 /* 12626419Ssb155480 * Search fdb for a given mac address. If an entry is found, hold 12636419Ssb155480 * a reference to it and return the entry; else returns NULL. 12646419Ssb155480 */ 12656495Sspeer static vnet_res_t * 12666419Ssb155480 vnet_fdbe_find(vnet_t *vnetp, struct ether_addr *addrp) 12671991Sheppo { 12686419Ssb155480 uint64_t key = 0; 12696495Sspeer vnet_res_t *vresp; 12706419Ssb155480 int rv; 12716419Ssb155480 12726495Sspeer KEY_HASH(key, addrp->ether_addr_octet); 12736419Ssb155480 12746419Ssb155480 rv = mod_hash_find_cb(vnetp->fdb_hashp, (mod_hash_key_t)key, 12756495Sspeer (mod_hash_val_t *)&vresp, vnet_fdbe_find_cb); 12761991Sheppo 12776419Ssb155480 if (rv != 0) 12786419Ssb155480 return (NULL); 12791991Sheppo 12806495Sspeer return (vresp); 12816419Ssb155480 } 12821991Sheppo 12836419Ssb155480 /* 12846419Ssb155480 * Callback function provided to mod_hash_find_cb(). After finding the fdb 12856419Ssb155480 * entry corresponding to the key (macaddr), this callback will be invoked by 12866419Ssb155480 * mod_hash_find_cb() to atomically increment the reference count on the fdb 12876419Ssb155480 * entry before returning the found entry. 12886419Ssb155480 */ 12896419Ssb155480 static void 12906419Ssb155480 vnet_fdbe_find_cb(mod_hash_key_t key, mod_hash_val_t val) 12916419Ssb155480 { 12926419Ssb155480 _NOTE(ARGUNUSED(key)) 12936495Sspeer VNET_FDBE_REFHOLD((vnet_res_t *)val); 12946495Sspeer } 12956495Sspeer 12967896SSriharsha.Basavapatna@Sun.COM /* 12977896SSriharsha.Basavapatna@Sun.COM * Frames received that are tagged with the pvid of the vnet device must be 12987896SSriharsha.Basavapatna@Sun.COM * untagged before sending up the stack. This function walks the chain of rx 12997896SSriharsha.Basavapatna@Sun.COM * frames, untags any such frames and returns the updated chain. 13007896SSriharsha.Basavapatna@Sun.COM * 13017896SSriharsha.Basavapatna@Sun.COM * Arguments: 13027896SSriharsha.Basavapatna@Sun.COM * pvid: pvid of the vnet device for which packets are being received 13037896SSriharsha.Basavapatna@Sun.COM * mp: head of pkt chain to be validated and untagged 13047896SSriharsha.Basavapatna@Sun.COM * 13057896SSriharsha.Basavapatna@Sun.COM * Returns: 13067896SSriharsha.Basavapatna@Sun.COM * mp: head of updated chain of packets 13077896SSriharsha.Basavapatna@Sun.COM */ 13087896SSriharsha.Basavapatna@Sun.COM static void 13097896SSriharsha.Basavapatna@Sun.COM vnet_rx_frames_untag(uint16_t pvid, mblk_t **mp) 13107896SSriharsha.Basavapatna@Sun.COM { 13117896SSriharsha.Basavapatna@Sun.COM struct ether_vlan_header *evhp; 13127896SSriharsha.Basavapatna@Sun.COM mblk_t *bp; 13137896SSriharsha.Basavapatna@Sun.COM mblk_t *bpt; 13147896SSriharsha.Basavapatna@Sun.COM mblk_t *bph; 13157896SSriharsha.Basavapatna@Sun.COM mblk_t *bpn; 13167896SSriharsha.Basavapatna@Sun.COM 13177896SSriharsha.Basavapatna@Sun.COM bpn = bph = bpt = NULL; 13187896SSriharsha.Basavapatna@Sun.COM 13197896SSriharsha.Basavapatna@Sun.COM for (bp = *mp; bp != NULL; bp = bpn) { 13207896SSriharsha.Basavapatna@Sun.COM 13217896SSriharsha.Basavapatna@Sun.COM bpn = bp->b_next; 13227896SSriharsha.Basavapatna@Sun.COM bp->b_next = bp->b_prev = NULL; 13237896SSriharsha.Basavapatna@Sun.COM 13247896SSriharsha.Basavapatna@Sun.COM evhp = (struct ether_vlan_header *)bp->b_rptr; 13257896SSriharsha.Basavapatna@Sun.COM 13267896SSriharsha.Basavapatna@Sun.COM if (ntohs(evhp->ether_tpid) == ETHERTYPE_VLAN && 13277896SSriharsha.Basavapatna@Sun.COM VLAN_ID(ntohs(evhp->ether_tci)) == pvid) { 13287896SSriharsha.Basavapatna@Sun.COM 13297896SSriharsha.Basavapatna@Sun.COM bp = vnet_vlan_remove_tag(bp); 13307896SSriharsha.Basavapatna@Sun.COM if (bp == NULL) { 13317896SSriharsha.Basavapatna@Sun.COM continue; 13327896SSriharsha.Basavapatna@Sun.COM } 13337896SSriharsha.Basavapatna@Sun.COM 13347896SSriharsha.Basavapatna@Sun.COM } 13357896SSriharsha.Basavapatna@Sun.COM 13367896SSriharsha.Basavapatna@Sun.COM /* build a chain of processed packets */ 13377896SSriharsha.Basavapatna@Sun.COM if (bph == NULL) { 13387896SSriharsha.Basavapatna@Sun.COM bph = bpt = bp; 13397896SSriharsha.Basavapatna@Sun.COM } else { 13407896SSriharsha.Basavapatna@Sun.COM bpt->b_next = bp; 13417896SSriharsha.Basavapatna@Sun.COM bpt = bp; 13427896SSriharsha.Basavapatna@Sun.COM } 13437896SSriharsha.Basavapatna@Sun.COM 13447896SSriharsha.Basavapatna@Sun.COM } 13457896SSriharsha.Basavapatna@Sun.COM 13467896SSriharsha.Basavapatna@Sun.COM *mp = bph; 13477896SSriharsha.Basavapatna@Sun.COM } 13487896SSriharsha.Basavapatna@Sun.COM 13496495Sspeer static void 13506495Sspeer vnet_rx(vio_net_handle_t vrh, mblk_t *mp) 13516495Sspeer { 135210309SSriharsha.Basavapatna@Sun.COM vnet_res_t *vresp = (vnet_res_t *)vrh; 135310309SSriharsha.Basavapatna@Sun.COM vnet_t *vnetp = vresp->vnetp; 135410309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_ring_t *ringp; 13557896SSriharsha.Basavapatna@Sun.COM 13567896SSriharsha.Basavapatna@Sun.COM if ((vnetp == NULL) || (vnetp->mh == 0)) { 13577896SSriharsha.Basavapatna@Sun.COM freemsgchain(mp); 13587896SSriharsha.Basavapatna@Sun.COM return; 13597896SSriharsha.Basavapatna@Sun.COM } 13606495Sspeer 136110309SSriharsha.Basavapatna@Sun.COM ringp = vresp->rx_ringp; 136210309SSriharsha.Basavapatna@Sun.COM mac_rx_ring(vnetp->mh, ringp->handle, mp, ringp->gen_num); 13631991Sheppo } 13642311Sseb 13652311Sseb void 13666495Sspeer vnet_tx_update(vio_net_handle_t vrh) 13676495Sspeer { 136810309SSriharsha.Basavapatna@Sun.COM vnet_res_t *vresp = (vnet_res_t *)vrh; 136910309SSriharsha.Basavapatna@Sun.COM vnet_t *vnetp = vresp->vnetp; 137010309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_tx_ring_t *tx_ringp; 137110309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_tx_group_t *tx_grp; 137210309SSriharsha.Basavapatna@Sun.COM int i; 137310309SSriharsha.Basavapatna@Sun.COM 137410309SSriharsha.Basavapatna@Sun.COM if (vnetp == NULL || vnetp->mh == NULL) { 137510309SSriharsha.Basavapatna@Sun.COM return; 137610309SSriharsha.Basavapatna@Sun.COM } 137710309SSriharsha.Basavapatna@Sun.COM 137810309SSriharsha.Basavapatna@Sun.COM /* 137910309SSriharsha.Basavapatna@Sun.COM * Currently, the tx hwring API (used to access rings that belong to 138010309SSriharsha.Basavapatna@Sun.COM * a Hybrid IO resource) does not provide us a per ring flow ctrl 138110309SSriharsha.Basavapatna@Sun.COM * update; also the pseudo rings are shared by the ports/ldcs in the 138210309SSriharsha.Basavapatna@Sun.COM * vgen layer. Thus we can't figure out which pseudo ring is being 138310309SSriharsha.Basavapatna@Sun.COM * re-enabled for transmits. To work around this, when we get a tx 138410309SSriharsha.Basavapatna@Sun.COM * restart notification from below, we simply propagate that to all 138510309SSriharsha.Basavapatna@Sun.COM * the tx pseudo rings registered with the mac layer above. 138610309SSriharsha.Basavapatna@Sun.COM * 138710309SSriharsha.Basavapatna@Sun.COM * There are a couple of side effects with this approach, but they are 138810309SSriharsha.Basavapatna@Sun.COM * not harmful, as outlined below: 138910309SSriharsha.Basavapatna@Sun.COM * 139010309SSriharsha.Basavapatna@Sun.COM * A) We might send an invalid ring_update() for a ring that is not 139110309SSriharsha.Basavapatna@Sun.COM * really flow controlled. This will not have any effect in the mac 139210309SSriharsha.Basavapatna@Sun.COM * layer and packets will continue to be transmitted on that ring. 139310309SSriharsha.Basavapatna@Sun.COM * 139410309SSriharsha.Basavapatna@Sun.COM * B) We might end up clearing the flow control in the mac layer for 139510309SSriharsha.Basavapatna@Sun.COM * a ring that is still flow controlled in the underlying resource. 139610309SSriharsha.Basavapatna@Sun.COM * This will result in the mac layer restarting transmit, only to be 139710309SSriharsha.Basavapatna@Sun.COM * flow controlled again on that ring. 139810309SSriharsha.Basavapatna@Sun.COM */ 139910309SSriharsha.Basavapatna@Sun.COM tx_grp = &vnetp->tx_grp[0]; 140010309SSriharsha.Basavapatna@Sun.COM for (i = 0; i < tx_grp->ring_cnt; i++) { 140110309SSriharsha.Basavapatna@Sun.COM tx_ringp = &tx_grp->rings[i]; 140210309SSriharsha.Basavapatna@Sun.COM mac_tx_ring_update(vnetp->mh, tx_ringp->handle); 14036495Sspeer } 14046495Sspeer } 14056495Sspeer 14066495Sspeer /* 14077529SSriharsha.Basavapatna@Sun.COM * Update the new mtu of vnet into the mac layer. First check if the device has 14087529SSriharsha.Basavapatna@Sun.COM * been plumbed and if so fail the mtu update. Returns 0 on success. 14097529SSriharsha.Basavapatna@Sun.COM */ 14107529SSriharsha.Basavapatna@Sun.COM int 14117529SSriharsha.Basavapatna@Sun.COM vnet_mtu_update(vnet_t *vnetp, uint32_t mtu) 14127529SSriharsha.Basavapatna@Sun.COM { 14137529SSriharsha.Basavapatna@Sun.COM int rv; 14147529SSriharsha.Basavapatna@Sun.COM 14157529SSriharsha.Basavapatna@Sun.COM if (vnetp == NULL || vnetp->mh == NULL) { 14167529SSriharsha.Basavapatna@Sun.COM return (EINVAL); 14177529SSriharsha.Basavapatna@Sun.COM } 14187529SSriharsha.Basavapatna@Sun.COM 14197529SSriharsha.Basavapatna@Sun.COM WRITE_ENTER(&vnetp->vrwlock); 14207529SSriharsha.Basavapatna@Sun.COM 14217529SSriharsha.Basavapatna@Sun.COM if (vnetp->flags & VNET_STARTED) { 14227529SSriharsha.Basavapatna@Sun.COM RW_EXIT(&vnetp->vrwlock); 14237529SSriharsha.Basavapatna@Sun.COM cmn_err(CE_NOTE, "!vnet%d: Unable to process mtu " 14247529SSriharsha.Basavapatna@Sun.COM "update as the device is plumbed\n", 14257529SSriharsha.Basavapatna@Sun.COM vnetp->instance); 14267529SSriharsha.Basavapatna@Sun.COM return (EBUSY); 14277529SSriharsha.Basavapatna@Sun.COM } 14287529SSriharsha.Basavapatna@Sun.COM 14297529SSriharsha.Basavapatna@Sun.COM /* update mtu in the mac layer */ 14307529SSriharsha.Basavapatna@Sun.COM rv = mac_maxsdu_update(vnetp->mh, mtu); 14317529SSriharsha.Basavapatna@Sun.COM if (rv != 0) { 14327529SSriharsha.Basavapatna@Sun.COM RW_EXIT(&vnetp->vrwlock); 14337529SSriharsha.Basavapatna@Sun.COM cmn_err(CE_NOTE, 14347529SSriharsha.Basavapatna@Sun.COM "!vnet%d: Unable to update mtu with mac layer\n", 14357529SSriharsha.Basavapatna@Sun.COM vnetp->instance); 14367529SSriharsha.Basavapatna@Sun.COM return (EIO); 14377529SSriharsha.Basavapatna@Sun.COM } 14387529SSriharsha.Basavapatna@Sun.COM 14397529SSriharsha.Basavapatna@Sun.COM vnetp->mtu = mtu; 14407529SSriharsha.Basavapatna@Sun.COM 14417529SSriharsha.Basavapatna@Sun.COM RW_EXIT(&vnetp->vrwlock); 14427529SSriharsha.Basavapatna@Sun.COM 14437529SSriharsha.Basavapatna@Sun.COM return (0); 14447529SSriharsha.Basavapatna@Sun.COM } 14457529SSriharsha.Basavapatna@Sun.COM 14467529SSriharsha.Basavapatna@Sun.COM /* 14479336SSriharsha.Basavapatna@Sun.COM * Update the link state of vnet to the mac layer. 14489336SSriharsha.Basavapatna@Sun.COM */ 14499336SSriharsha.Basavapatna@Sun.COM void 14509336SSriharsha.Basavapatna@Sun.COM vnet_link_update(vnet_t *vnetp, link_state_t link_state) 14519336SSriharsha.Basavapatna@Sun.COM { 14529336SSriharsha.Basavapatna@Sun.COM if (vnetp == NULL || vnetp->mh == NULL) { 14539336SSriharsha.Basavapatna@Sun.COM return; 14549336SSriharsha.Basavapatna@Sun.COM } 14559336SSriharsha.Basavapatna@Sun.COM 14569336SSriharsha.Basavapatna@Sun.COM WRITE_ENTER(&vnetp->vrwlock); 14579336SSriharsha.Basavapatna@Sun.COM if (vnetp->link_state == link_state) { 14589336SSriharsha.Basavapatna@Sun.COM RW_EXIT(&vnetp->vrwlock); 14599336SSriharsha.Basavapatna@Sun.COM return; 14609336SSriharsha.Basavapatna@Sun.COM } 14619336SSriharsha.Basavapatna@Sun.COM vnetp->link_state = link_state; 14629336SSriharsha.Basavapatna@Sun.COM RW_EXIT(&vnetp->vrwlock); 14639336SSriharsha.Basavapatna@Sun.COM 14649336SSriharsha.Basavapatna@Sun.COM mac_link_update(vnetp->mh, link_state); 14659336SSriharsha.Basavapatna@Sun.COM } 14669336SSriharsha.Basavapatna@Sun.COM 14679336SSriharsha.Basavapatna@Sun.COM /* 14686495Sspeer * vio_net_resource_reg -- An interface called to register a resource 14696495Sspeer * with vnet. 14706495Sspeer * macp -- a GLDv3 mac_register that has all the details of 14716495Sspeer * a resource and its callbacks etc. 14726495Sspeer * type -- resource type. 14736495Sspeer * local_macaddr -- resource's MAC address. This is used to 14746495Sspeer * associate a resource with a corresponding vnet. 14756495Sspeer * remote_macaddr -- remote side MAC address. This is ignored for 14766495Sspeer * the Hybrid resources. 14776495Sspeer * vhp -- A handle returned to the caller. 14786495Sspeer * vcb -- A set of callbacks provided to the callers. 14796495Sspeer */ 14806495Sspeer int vio_net_resource_reg(mac_register_t *macp, vio_net_res_type_t type, 14816495Sspeer ether_addr_t local_macaddr, ether_addr_t rem_macaddr, vio_net_handle_t *vhp, 14826495Sspeer vio_net_callbacks_t *vcb) 14836495Sspeer { 148410309SSriharsha.Basavapatna@Sun.COM vnet_t *vnetp; 148510309SSriharsha.Basavapatna@Sun.COM vnet_res_t *vresp; 14866495Sspeer 14876495Sspeer vresp = kmem_zalloc(sizeof (vnet_res_t), KM_SLEEP); 14886495Sspeer ether_copy(local_macaddr, vresp->local_macaddr); 14896495Sspeer ether_copy(rem_macaddr, vresp->rem_macaddr); 14906495Sspeer vresp->type = type; 14916495Sspeer bcopy(macp, &vresp->macreg, sizeof (mac_register_t)); 14926495Sspeer 14936495Sspeer DBG1(NULL, "Resource Registerig type=0%X\n", type); 14946495Sspeer 14956495Sspeer READ_ENTER(&vnet_rw); 14966495Sspeer vnetp = vnet_headp; 14976495Sspeer while (vnetp != NULL) { 14986495Sspeer if (VNET_MATCH_RES(vresp, vnetp)) { 14998332SWentao.Yang@Sun.COM vresp->vnetp = vnetp; 15008332SWentao.Yang@Sun.COM 15018332SWentao.Yang@Sun.COM /* Setup kstats for hio resource */ 15028332SWentao.Yang@Sun.COM if (vresp->type == VIO_NET_RES_HYBRID) { 15038332SWentao.Yang@Sun.COM vresp->ksp = vnet_hio_setup_kstats(DRV_NAME, 15048332SWentao.Yang@Sun.COM "hio", vresp); 15058332SWentao.Yang@Sun.COM if (vresp->ksp == NULL) { 15068332SWentao.Yang@Sun.COM cmn_err(CE_NOTE, "!vnet%d: Cannot " 15078332SWentao.Yang@Sun.COM "create kstats for hio resource", 15088332SWentao.Yang@Sun.COM vnetp->instance); 15098332SWentao.Yang@Sun.COM } 15108332SWentao.Yang@Sun.COM } 151110309SSriharsha.Basavapatna@Sun.COM vnet_add_resource(vnetp, vresp); 15126495Sspeer break; 15136495Sspeer } 15146495Sspeer vnetp = vnetp->nextp; 15156495Sspeer } 15166495Sspeer RW_EXIT(&vnet_rw); 15176495Sspeer if (vresp->vnetp == NULL) { 15186495Sspeer DWARN(NULL, "No vnet instance"); 15196495Sspeer kmem_free(vresp, sizeof (vnet_res_t)); 15206495Sspeer return (ENXIO); 15216495Sspeer } 15226495Sspeer 15236495Sspeer *vhp = vresp; 15246495Sspeer vcb->vio_net_rx_cb = vnet_rx; 15256495Sspeer vcb->vio_net_tx_update = vnet_tx_update; 15266495Sspeer vcb->vio_net_report_err = vnet_handle_res_err; 15276495Sspeer 152810309SSriharsha.Basavapatna@Sun.COM /* Bind the resource to pseudo ring(s) */ 152910309SSriharsha.Basavapatna@Sun.COM if (vnet_bind_rings(vresp) != 0) { 153010309SSriharsha.Basavapatna@Sun.COM (void) vnet_rem_resource(vnetp, vresp); 153110309SSriharsha.Basavapatna@Sun.COM vnet_hio_destroy_kstats(vresp->ksp); 153210309SSriharsha.Basavapatna@Sun.COM KMEM_FREE(vresp); 153310309SSriharsha.Basavapatna@Sun.COM return (1); 153410309SSriharsha.Basavapatna@Sun.COM } 153510309SSriharsha.Basavapatna@Sun.COM 15366495Sspeer /* Dispatch a task to start resources */ 15376495Sspeer vnet_dispatch_res_task(vnetp); 15386495Sspeer return (0); 15396495Sspeer } 15406495Sspeer 15416495Sspeer /* 15426495Sspeer * vio_net_resource_unreg -- An interface to unregister a resource. 15436495Sspeer */ 15446495Sspeer void 15456495Sspeer vio_net_resource_unreg(vio_net_handle_t vhp) 15466495Sspeer { 15479805SSriharsha.Basavapatna@Sun.COM vnet_res_t *vresp = (vnet_res_t *)vhp; 15489805SSriharsha.Basavapatna@Sun.COM vnet_t *vnetp = vresp->vnetp; 15496495Sspeer 15506495Sspeer DBG1(NULL, "Resource Registerig hdl=0x%p", vhp); 15516495Sspeer 15526495Sspeer ASSERT(vnetp != NULL); 15539805SSriharsha.Basavapatna@Sun.COM /* 15549805SSriharsha.Basavapatna@Sun.COM * Remove the resource from fdb; this ensures 15559805SSriharsha.Basavapatna@Sun.COM * there are no references to the resource. 15569805SSriharsha.Basavapatna@Sun.COM */ 15576495Sspeer vnet_fdbe_del(vnetp, vresp); 15586495Sspeer 155910309SSriharsha.Basavapatna@Sun.COM vnet_unbind_rings(vresp); 156010309SSriharsha.Basavapatna@Sun.COM 15619805SSriharsha.Basavapatna@Sun.COM /* Now remove the resource from the list */ 156210309SSriharsha.Basavapatna@Sun.COM (void) vnet_rem_resource(vnetp, vresp); 156310309SSriharsha.Basavapatna@Sun.COM 156410309SSriharsha.Basavapatna@Sun.COM vnet_hio_destroy_kstats(vresp->ksp); 156510309SSriharsha.Basavapatna@Sun.COM KMEM_FREE(vresp); 156610309SSriharsha.Basavapatna@Sun.COM } 156710309SSriharsha.Basavapatna@Sun.COM 156810309SSriharsha.Basavapatna@Sun.COM static void 156910309SSriharsha.Basavapatna@Sun.COM vnet_add_resource(vnet_t *vnetp, vnet_res_t *vresp) 157010309SSriharsha.Basavapatna@Sun.COM { 157110309SSriharsha.Basavapatna@Sun.COM WRITE_ENTER(&vnetp->vrwlock); 157210309SSriharsha.Basavapatna@Sun.COM vresp->nextp = vnetp->vres_list; 157310309SSriharsha.Basavapatna@Sun.COM vnetp->vres_list = vresp; 157410309SSriharsha.Basavapatna@Sun.COM RW_EXIT(&vnetp->vrwlock); 157510309SSriharsha.Basavapatna@Sun.COM } 157610309SSriharsha.Basavapatna@Sun.COM 157710309SSriharsha.Basavapatna@Sun.COM static vnet_res_t * 157810309SSriharsha.Basavapatna@Sun.COM vnet_rem_resource(vnet_t *vnetp, vnet_res_t *vresp) 157910309SSriharsha.Basavapatna@Sun.COM { 158010309SSriharsha.Basavapatna@Sun.COM vnet_res_t *vrp; 158110309SSriharsha.Basavapatna@Sun.COM 15826495Sspeer WRITE_ENTER(&vnetp->vrwlock); 15836495Sspeer if (vresp == vnetp->vres_list) { 15846495Sspeer vnetp->vres_list = vresp->nextp; 15856495Sspeer } else { 15866495Sspeer vrp = vnetp->vres_list; 15876495Sspeer while (vrp->nextp != NULL) { 15886495Sspeer if (vrp->nextp == vresp) { 15896495Sspeer vrp->nextp = vresp->nextp; 15906495Sspeer break; 15916495Sspeer } 15926495Sspeer vrp = vrp->nextp; 15936495Sspeer } 15946495Sspeer } 15956495Sspeer vresp->vnetp = NULL; 15966495Sspeer vresp->nextp = NULL; 159710309SSriharsha.Basavapatna@Sun.COM 15986495Sspeer RW_EXIT(&vnetp->vrwlock); 159910309SSriharsha.Basavapatna@Sun.COM 160010309SSriharsha.Basavapatna@Sun.COM return (vresp); 16016495Sspeer } 16026495Sspeer 16036495Sspeer /* 16046495Sspeer * vnet_dds_rx -- an interface called by vgen to DDS messages. 16056495Sspeer */ 16066495Sspeer void 16076495Sspeer vnet_dds_rx(void *arg, void *dmsg) 16082311Sseb { 16092311Sseb vnet_t *vnetp = arg; 16106495Sspeer vdds_process_dds_msg(vnetp, dmsg); 16112311Sseb } 16122311Sseb 16136495Sspeer /* 16146495Sspeer * vnet_send_dds_msg -- An interface provided to DDS to send 16156495Sspeer * DDS messages. This simply sends meessages via vgen. 16166495Sspeer */ 16176495Sspeer int 16186495Sspeer vnet_send_dds_msg(vnet_t *vnetp, void *dmsg) 16196495Sspeer { 16206495Sspeer int rv; 16216495Sspeer 16226495Sspeer if (vnetp->vgenhdl != NULL) { 16236495Sspeer rv = vgen_dds_tx(vnetp->vgenhdl, dmsg); 16246495Sspeer } 16256495Sspeer return (rv); 16266495Sspeer } 16276495Sspeer 16286495Sspeer /* 16299647SWentao.Yang@Sun.COM * vnet_cleanup_hio -- an interface called by vgen to cleanup hio resources. 16309647SWentao.Yang@Sun.COM */ 16319647SWentao.Yang@Sun.COM void 16329647SWentao.Yang@Sun.COM vnet_dds_cleanup_hio(vnet_t *vnetp) 16339647SWentao.Yang@Sun.COM { 16349647SWentao.Yang@Sun.COM vdds_cleanup_hio(vnetp); 16359647SWentao.Yang@Sun.COM } 16369647SWentao.Yang@Sun.COM 16379647SWentao.Yang@Sun.COM /* 16386495Sspeer * vnet_handle_res_err -- A callback function called by a resource 16396495Sspeer * to report an error. For example, vgen can call to report 16406495Sspeer * an LDC down/reset event. This will trigger cleanup of associated 16416495Sspeer * Hybrid resource. 16426495Sspeer */ 16436495Sspeer /* ARGSUSED */ 16446495Sspeer static void 16456495Sspeer vnet_handle_res_err(vio_net_handle_t vrh, vio_net_err_val_t err) 16466495Sspeer { 16476495Sspeer vnet_res_t *vresp = (vnet_res_t *)vrh; 16486495Sspeer vnet_t *vnetp = vresp->vnetp; 16496495Sspeer 16506495Sspeer if (vnetp == NULL) { 16516495Sspeer return; 16526495Sspeer } 16536495Sspeer if ((vresp->type != VIO_NET_RES_LDC_SERVICE) && 16546495Sspeer (vresp->type != VIO_NET_RES_HYBRID)) { 16556495Sspeer return; 16566495Sspeer } 16579647SWentao.Yang@Sun.COM 16589647SWentao.Yang@Sun.COM vdds_cleanup_hio(vnetp); 16596495Sspeer } 16606495Sspeer 16616495Sspeer /* 16626495Sspeer * vnet_dispatch_res_task -- A function to dispatch tasks start resources. 16636495Sspeer */ 16646495Sspeer static void 16656495Sspeer vnet_dispatch_res_task(vnet_t *vnetp) 16666495Sspeer { 16676495Sspeer int rv; 16686495Sspeer 16699677SZachary.Kissel@Sun.COM /* 16709677SZachary.Kissel@Sun.COM * Dispatch the task. It could be the case that vnetp->flags does 16719677SZachary.Kissel@Sun.COM * not have VNET_STARTED set. This is ok as vnet_rest_start_task() 16729805SSriharsha.Basavapatna@Sun.COM * can abort the task when the task is started. See related comments 16739805SSriharsha.Basavapatna@Sun.COM * in vnet_m_stop() and vnet_stop_resources(). 16749677SZachary.Kissel@Sun.COM */ 16759677SZachary.Kissel@Sun.COM rv = ddi_taskq_dispatch(vnetp->taskqp, vnet_res_start_task, 16769677SZachary.Kissel@Sun.COM vnetp, DDI_NOSLEEP); 16779677SZachary.Kissel@Sun.COM if (rv != DDI_SUCCESS) { 16789677SZachary.Kissel@Sun.COM cmn_err(CE_WARN, 16799677SZachary.Kissel@Sun.COM "vnet%d:Can't dispatch start resource task", 16809677SZachary.Kissel@Sun.COM vnetp->instance); 16816495Sspeer } 16826495Sspeer } 16836495Sspeer 16846495Sspeer /* 16856495Sspeer * vnet_res_start_task -- A taskq callback function that starts a resource. 16866495Sspeer */ 16876495Sspeer static void 16886495Sspeer vnet_res_start_task(void *arg) 16892311Sseb { 16902311Sseb vnet_t *vnetp = arg; 16916495Sspeer 16926495Sspeer WRITE_ENTER(&vnetp->vrwlock); 16936495Sspeer if (vnetp->flags & VNET_STARTED) { 16946495Sspeer vnet_start_resources(vnetp); 16956495Sspeer } 16966495Sspeer RW_EXIT(&vnetp->vrwlock); 16972311Sseb } 16986495Sspeer 16996495Sspeer /* 17006495Sspeer * vnet_start_resources -- starts all resources associated with 17016495Sspeer * a vnet. 17026495Sspeer */ 17036495Sspeer static void 17046495Sspeer vnet_start_resources(vnet_t *vnetp) 17056495Sspeer { 17066495Sspeer mac_register_t *macp; 17076495Sspeer mac_callbacks_t *cbp; 17086495Sspeer vnet_res_t *vresp; 17096495Sspeer int rv; 17106495Sspeer 17116495Sspeer DBG1(vnetp, "enter\n"); 17126495Sspeer 17139805SSriharsha.Basavapatna@Sun.COM ASSERT(RW_WRITE_HELD(&vnetp->vrwlock)); 17149805SSriharsha.Basavapatna@Sun.COM 17156495Sspeer for (vresp = vnetp->vres_list; vresp != NULL; vresp = vresp->nextp) { 17166495Sspeer /* skip if it is already started */ 17176495Sspeer if (vresp->flags & VNET_STARTED) { 17186495Sspeer continue; 17196495Sspeer } 17206495Sspeer macp = &vresp->macreg; 17216495Sspeer cbp = macp->m_callbacks; 17226495Sspeer rv = cbp->mc_start(macp->m_driver); 17236495Sspeer if (rv == 0) { 17246495Sspeer /* 17256495Sspeer * Successfully started the resource, so now 17266495Sspeer * add it to the fdb. 17276495Sspeer */ 17286495Sspeer vresp->flags |= VNET_STARTED; 17296495Sspeer vnet_fdbe_add(vnetp, vresp); 17306495Sspeer } 17316495Sspeer } 17326495Sspeer 17336495Sspeer DBG1(vnetp, "exit\n"); 17346495Sspeer 17356495Sspeer } 17366495Sspeer 17376495Sspeer /* 17386495Sspeer * vnet_stop_resources -- stop all resources associated with a vnet. 17396495Sspeer */ 17406495Sspeer static void 17416495Sspeer vnet_stop_resources(vnet_t *vnetp) 17426495Sspeer { 17436495Sspeer vnet_res_t *vresp; 17446495Sspeer mac_register_t *macp; 17456495Sspeer mac_callbacks_t *cbp; 17466495Sspeer 17476495Sspeer DBG1(vnetp, "enter\n"); 17486495Sspeer 17499805SSriharsha.Basavapatna@Sun.COM ASSERT(RW_WRITE_HELD(&vnetp->vrwlock)); 17509805SSriharsha.Basavapatna@Sun.COM 17516495Sspeer for (vresp = vnetp->vres_list; vresp != NULL; ) { 17526495Sspeer if (vresp->flags & VNET_STARTED) { 17539805SSriharsha.Basavapatna@Sun.COM /* 17549805SSriharsha.Basavapatna@Sun.COM * Release the lock while invoking mc_stop() of the 17559805SSriharsha.Basavapatna@Sun.COM * underlying resource. We hold a reference to this 17569805SSriharsha.Basavapatna@Sun.COM * resource to prevent being removed from the list in 17579805SSriharsha.Basavapatna@Sun.COM * vio_net_resource_unreg(). Note that new resources 17589805SSriharsha.Basavapatna@Sun.COM * can be added to the head of the list while the lock 17599805SSriharsha.Basavapatna@Sun.COM * is released, but they won't be started, as 17609805SSriharsha.Basavapatna@Sun.COM * VNET_STARTED flag has been cleared for the vnet 17619805SSriharsha.Basavapatna@Sun.COM * device in vnet_m_stop(). Also, while the lock is 17629805SSriharsha.Basavapatna@Sun.COM * released a resource could be removed from the list 17639805SSriharsha.Basavapatna@Sun.COM * in vio_net_resource_unreg(); but that is ok, as we 17649805SSriharsha.Basavapatna@Sun.COM * re-acquire the lock and only then access the forward 17659805SSriharsha.Basavapatna@Sun.COM * link (vresp->nextp) to continue with the next 17669805SSriharsha.Basavapatna@Sun.COM * resource. 17679805SSriharsha.Basavapatna@Sun.COM */ 17689805SSriharsha.Basavapatna@Sun.COM vresp->flags &= ~VNET_STARTED; 17699805SSriharsha.Basavapatna@Sun.COM vresp->flags |= VNET_STOPPING; 17706495Sspeer macp = &vresp->macreg; 17716495Sspeer cbp = macp->m_callbacks; 17729805SSriharsha.Basavapatna@Sun.COM VNET_FDBE_REFHOLD(vresp); 17739805SSriharsha.Basavapatna@Sun.COM RW_EXIT(&vnetp->vrwlock); 17749805SSriharsha.Basavapatna@Sun.COM 17756495Sspeer cbp->mc_stop(macp->m_driver); 17769805SSriharsha.Basavapatna@Sun.COM 17779805SSriharsha.Basavapatna@Sun.COM WRITE_ENTER(&vnetp->vrwlock); 17789805SSriharsha.Basavapatna@Sun.COM vresp->flags &= ~VNET_STOPPING; 17799805SSriharsha.Basavapatna@Sun.COM VNET_FDBE_REFRELE(vresp); 17806495Sspeer } 17819805SSriharsha.Basavapatna@Sun.COM vresp = vresp->nextp; 17826495Sspeer } 17836495Sspeer DBG1(vnetp, "exit\n"); 17846495Sspeer } 17858160SWentao.Yang@Sun.COM 17868160SWentao.Yang@Sun.COM /* 17878160SWentao.Yang@Sun.COM * Setup kstats for the HIO statistics. 17888160SWentao.Yang@Sun.COM * NOTE: the synchronization for the statistics is the 17898160SWentao.Yang@Sun.COM * responsibility of the caller. 17908160SWentao.Yang@Sun.COM */ 17918160SWentao.Yang@Sun.COM kstat_t * 17928160SWentao.Yang@Sun.COM vnet_hio_setup_kstats(char *ks_mod, char *ks_name, vnet_res_t *vresp) 17938160SWentao.Yang@Sun.COM { 17948160SWentao.Yang@Sun.COM kstat_t *ksp; 17958160SWentao.Yang@Sun.COM vnet_t *vnetp = vresp->vnetp; 17968160SWentao.Yang@Sun.COM vnet_hio_kstats_t *hiokp; 17978160SWentao.Yang@Sun.COM size_t size; 17988160SWentao.Yang@Sun.COM 17998160SWentao.Yang@Sun.COM ASSERT(vnetp != NULL); 18008160SWentao.Yang@Sun.COM size = sizeof (vnet_hio_kstats_t) / sizeof (kstat_named_t); 18018160SWentao.Yang@Sun.COM ksp = kstat_create(ks_mod, vnetp->instance, ks_name, "net", 18028160SWentao.Yang@Sun.COM KSTAT_TYPE_NAMED, size, 0); 18038160SWentao.Yang@Sun.COM if (ksp == NULL) { 18048160SWentao.Yang@Sun.COM return (NULL); 18058160SWentao.Yang@Sun.COM } 18068160SWentao.Yang@Sun.COM 18078160SWentao.Yang@Sun.COM hiokp = (vnet_hio_kstats_t *)ksp->ks_data; 18088160SWentao.Yang@Sun.COM kstat_named_init(&hiokp->ipackets, "ipackets", 18098160SWentao.Yang@Sun.COM KSTAT_DATA_ULONG); 18108160SWentao.Yang@Sun.COM kstat_named_init(&hiokp->ierrors, "ierrors", 18118160SWentao.Yang@Sun.COM KSTAT_DATA_ULONG); 18128160SWentao.Yang@Sun.COM kstat_named_init(&hiokp->opackets, "opackets", 18138160SWentao.Yang@Sun.COM KSTAT_DATA_ULONG); 18148160SWentao.Yang@Sun.COM kstat_named_init(&hiokp->oerrors, "oerrors", 18158160SWentao.Yang@Sun.COM KSTAT_DATA_ULONG); 18168160SWentao.Yang@Sun.COM 18178160SWentao.Yang@Sun.COM 18188160SWentao.Yang@Sun.COM /* MIB II kstat variables */ 18198160SWentao.Yang@Sun.COM kstat_named_init(&hiokp->rbytes, "rbytes", 18208160SWentao.Yang@Sun.COM KSTAT_DATA_ULONG); 18218160SWentao.Yang@Sun.COM kstat_named_init(&hiokp->obytes, "obytes", 18228160SWentao.Yang@Sun.COM KSTAT_DATA_ULONG); 18238160SWentao.Yang@Sun.COM kstat_named_init(&hiokp->multircv, "multircv", 18248160SWentao.Yang@Sun.COM KSTAT_DATA_ULONG); 18258160SWentao.Yang@Sun.COM kstat_named_init(&hiokp->multixmt, "multixmt", 18268160SWentao.Yang@Sun.COM KSTAT_DATA_ULONG); 18278160SWentao.Yang@Sun.COM kstat_named_init(&hiokp->brdcstrcv, "brdcstrcv", 18288160SWentao.Yang@Sun.COM KSTAT_DATA_ULONG); 18298160SWentao.Yang@Sun.COM kstat_named_init(&hiokp->brdcstxmt, "brdcstxmt", 18308160SWentao.Yang@Sun.COM KSTAT_DATA_ULONG); 18318160SWentao.Yang@Sun.COM kstat_named_init(&hiokp->norcvbuf, "norcvbuf", 18328160SWentao.Yang@Sun.COM KSTAT_DATA_ULONG); 18338160SWentao.Yang@Sun.COM kstat_named_init(&hiokp->noxmtbuf, "noxmtbuf", 18348160SWentao.Yang@Sun.COM KSTAT_DATA_ULONG); 18358160SWentao.Yang@Sun.COM 18368160SWentao.Yang@Sun.COM ksp->ks_update = vnet_hio_update_kstats; 18378160SWentao.Yang@Sun.COM ksp->ks_private = (void *)vresp; 18388160SWentao.Yang@Sun.COM kstat_install(ksp); 18398160SWentao.Yang@Sun.COM return (ksp); 18408160SWentao.Yang@Sun.COM } 18418160SWentao.Yang@Sun.COM 18428160SWentao.Yang@Sun.COM /* 18438160SWentao.Yang@Sun.COM * Destroy kstats. 18448160SWentao.Yang@Sun.COM */ 18458160SWentao.Yang@Sun.COM static void 18468160SWentao.Yang@Sun.COM vnet_hio_destroy_kstats(kstat_t *ksp) 18478160SWentao.Yang@Sun.COM { 18488160SWentao.Yang@Sun.COM if (ksp != NULL) 18498160SWentao.Yang@Sun.COM kstat_delete(ksp); 18508160SWentao.Yang@Sun.COM } 18518160SWentao.Yang@Sun.COM 18528160SWentao.Yang@Sun.COM /* 18538160SWentao.Yang@Sun.COM * Update the kstats. 18548160SWentao.Yang@Sun.COM */ 18558160SWentao.Yang@Sun.COM static int 18568160SWentao.Yang@Sun.COM vnet_hio_update_kstats(kstat_t *ksp, int rw) 18578160SWentao.Yang@Sun.COM { 18588160SWentao.Yang@Sun.COM vnet_t *vnetp; 18598160SWentao.Yang@Sun.COM vnet_res_t *vresp; 18608160SWentao.Yang@Sun.COM vnet_hio_stats_t statsp; 18618160SWentao.Yang@Sun.COM vnet_hio_kstats_t *hiokp; 18628160SWentao.Yang@Sun.COM 18638160SWentao.Yang@Sun.COM vresp = (vnet_res_t *)ksp->ks_private; 18648160SWentao.Yang@Sun.COM vnetp = vresp->vnetp; 18658160SWentao.Yang@Sun.COM 18668160SWentao.Yang@Sun.COM bzero(&statsp, sizeof (vnet_hio_stats_t)); 18678160SWentao.Yang@Sun.COM 18688160SWentao.Yang@Sun.COM READ_ENTER(&vnetp->vsw_fp_rw); 18698160SWentao.Yang@Sun.COM if (vnetp->hio_fp == NULL) { 18708160SWentao.Yang@Sun.COM /* not using hio resources, just return */ 18718160SWentao.Yang@Sun.COM RW_EXIT(&vnetp->vsw_fp_rw); 18728160SWentao.Yang@Sun.COM return (0); 18738160SWentao.Yang@Sun.COM } 18748160SWentao.Yang@Sun.COM VNET_FDBE_REFHOLD(vnetp->hio_fp); 18758160SWentao.Yang@Sun.COM RW_EXIT(&vnetp->vsw_fp_rw); 18768160SWentao.Yang@Sun.COM vnet_hio_get_stats(vnetp->hio_fp, &statsp); 18778160SWentao.Yang@Sun.COM VNET_FDBE_REFRELE(vnetp->hio_fp); 18788160SWentao.Yang@Sun.COM 18798160SWentao.Yang@Sun.COM hiokp = (vnet_hio_kstats_t *)ksp->ks_data; 18808160SWentao.Yang@Sun.COM 18818160SWentao.Yang@Sun.COM if (rw == KSTAT_READ) { 18828160SWentao.Yang@Sun.COM /* Link Input/Output stats */ 18838160SWentao.Yang@Sun.COM hiokp->ipackets.value.ul = (uint32_t)statsp.ipackets; 18848160SWentao.Yang@Sun.COM hiokp->ipackets64.value.ull = statsp.ipackets; 18858160SWentao.Yang@Sun.COM hiokp->ierrors.value.ul = statsp.ierrors; 18868160SWentao.Yang@Sun.COM hiokp->opackets.value.ul = (uint32_t)statsp.opackets; 18878160SWentao.Yang@Sun.COM hiokp->opackets64.value.ull = statsp.opackets; 18888160SWentao.Yang@Sun.COM hiokp->oerrors.value.ul = statsp.oerrors; 18898160SWentao.Yang@Sun.COM 18908160SWentao.Yang@Sun.COM /* MIB II kstat variables */ 18918160SWentao.Yang@Sun.COM hiokp->rbytes.value.ul = (uint32_t)statsp.rbytes; 18928160SWentao.Yang@Sun.COM hiokp->rbytes64.value.ull = statsp.rbytes; 18938160SWentao.Yang@Sun.COM hiokp->obytes.value.ul = (uint32_t)statsp.obytes; 18948160SWentao.Yang@Sun.COM hiokp->obytes64.value.ull = statsp.obytes; 18958160SWentao.Yang@Sun.COM hiokp->multircv.value.ul = statsp.multircv; 18968160SWentao.Yang@Sun.COM hiokp->multixmt.value.ul = statsp.multixmt; 18978160SWentao.Yang@Sun.COM hiokp->brdcstrcv.value.ul = statsp.brdcstrcv; 18988160SWentao.Yang@Sun.COM hiokp->brdcstxmt.value.ul = statsp.brdcstxmt; 18998160SWentao.Yang@Sun.COM hiokp->norcvbuf.value.ul = statsp.norcvbuf; 19008160SWentao.Yang@Sun.COM hiokp->noxmtbuf.value.ul = statsp.noxmtbuf; 19018160SWentao.Yang@Sun.COM } else { 19028160SWentao.Yang@Sun.COM return (EACCES); 19038160SWentao.Yang@Sun.COM } 19048160SWentao.Yang@Sun.COM 19058160SWentao.Yang@Sun.COM return (0); 19068160SWentao.Yang@Sun.COM } 19078160SWentao.Yang@Sun.COM 19088160SWentao.Yang@Sun.COM static void 19098160SWentao.Yang@Sun.COM vnet_hio_get_stats(vnet_res_t *vresp, vnet_hio_stats_t *statsp) 19108160SWentao.Yang@Sun.COM { 19118160SWentao.Yang@Sun.COM mac_register_t *macp; 19128160SWentao.Yang@Sun.COM mac_callbacks_t *cbp; 19138160SWentao.Yang@Sun.COM uint64_t val; 19148160SWentao.Yang@Sun.COM int stat; 19158160SWentao.Yang@Sun.COM 19168160SWentao.Yang@Sun.COM /* 19178160SWentao.Yang@Sun.COM * get the specified statistics from the underlying nxge. 19188160SWentao.Yang@Sun.COM */ 19198160SWentao.Yang@Sun.COM macp = &vresp->macreg; 19208160SWentao.Yang@Sun.COM cbp = macp->m_callbacks; 19218160SWentao.Yang@Sun.COM for (stat = MAC_STAT_MIN; stat < MAC_STAT_OVERFLOWS; stat++) { 19228160SWentao.Yang@Sun.COM if (cbp->mc_getstat(macp->m_driver, stat, &val) == 0) { 19238160SWentao.Yang@Sun.COM switch (stat) { 19248160SWentao.Yang@Sun.COM case MAC_STAT_IPACKETS: 19258160SWentao.Yang@Sun.COM statsp->ipackets = val; 19268160SWentao.Yang@Sun.COM break; 19278160SWentao.Yang@Sun.COM 19288160SWentao.Yang@Sun.COM case MAC_STAT_IERRORS: 19298160SWentao.Yang@Sun.COM statsp->ierrors = val; 19308160SWentao.Yang@Sun.COM break; 19318160SWentao.Yang@Sun.COM 19328160SWentao.Yang@Sun.COM case MAC_STAT_OPACKETS: 19338160SWentao.Yang@Sun.COM statsp->opackets = val; 19348160SWentao.Yang@Sun.COM break; 19358160SWentao.Yang@Sun.COM 19368160SWentao.Yang@Sun.COM case MAC_STAT_OERRORS: 19378160SWentao.Yang@Sun.COM statsp->oerrors = val; 19388160SWentao.Yang@Sun.COM break; 19398160SWentao.Yang@Sun.COM 19408160SWentao.Yang@Sun.COM case MAC_STAT_RBYTES: 19418160SWentao.Yang@Sun.COM statsp->rbytes = val; 19428160SWentao.Yang@Sun.COM break; 19438160SWentao.Yang@Sun.COM 19448160SWentao.Yang@Sun.COM case MAC_STAT_OBYTES: 19458160SWentao.Yang@Sun.COM statsp->obytes = val; 19468160SWentao.Yang@Sun.COM break; 19478160SWentao.Yang@Sun.COM 19488160SWentao.Yang@Sun.COM case MAC_STAT_MULTIRCV: 19498160SWentao.Yang@Sun.COM statsp->multircv = val; 19508160SWentao.Yang@Sun.COM break; 19518160SWentao.Yang@Sun.COM 19528160SWentao.Yang@Sun.COM case MAC_STAT_MULTIXMT: 19538160SWentao.Yang@Sun.COM statsp->multixmt = val; 19548160SWentao.Yang@Sun.COM break; 19558160SWentao.Yang@Sun.COM 19568160SWentao.Yang@Sun.COM case MAC_STAT_BRDCSTRCV: 19578160SWentao.Yang@Sun.COM statsp->brdcstrcv = val; 19588160SWentao.Yang@Sun.COM break; 19598160SWentao.Yang@Sun.COM 19608160SWentao.Yang@Sun.COM case MAC_STAT_BRDCSTXMT: 19618160SWentao.Yang@Sun.COM statsp->brdcstxmt = val; 19628160SWentao.Yang@Sun.COM break; 19638160SWentao.Yang@Sun.COM 19648160SWentao.Yang@Sun.COM case MAC_STAT_NOXMTBUF: 19658160SWentao.Yang@Sun.COM statsp->noxmtbuf = val; 19668160SWentao.Yang@Sun.COM break; 19678160SWentao.Yang@Sun.COM 19688160SWentao.Yang@Sun.COM case MAC_STAT_NORCVBUF: 19698160SWentao.Yang@Sun.COM statsp->norcvbuf = val; 19708160SWentao.Yang@Sun.COM break; 19718160SWentao.Yang@Sun.COM 19728160SWentao.Yang@Sun.COM default: 19738160SWentao.Yang@Sun.COM /* 19748160SWentao.Yang@Sun.COM * parameters not interested. 19758160SWentao.Yang@Sun.COM */ 19768160SWentao.Yang@Sun.COM break; 19778160SWentao.Yang@Sun.COM } 19788160SWentao.Yang@Sun.COM } 19798160SWentao.Yang@Sun.COM } 19808160SWentao.Yang@Sun.COM } 19819336SSriharsha.Basavapatna@Sun.COM 198210309SSriharsha.Basavapatna@Sun.COM static boolean_t 198310309SSriharsha.Basavapatna@Sun.COM vnet_m_capab(void *arg, mac_capab_t cap, void *cap_data) 198410309SSriharsha.Basavapatna@Sun.COM { 198510309SSriharsha.Basavapatna@Sun.COM vnet_t *vnetp = (vnet_t *)arg; 198610309SSriharsha.Basavapatna@Sun.COM 198710309SSriharsha.Basavapatna@Sun.COM if (vnetp == NULL) { 198810309SSriharsha.Basavapatna@Sun.COM return (0); 198910309SSriharsha.Basavapatna@Sun.COM } 199010309SSriharsha.Basavapatna@Sun.COM 199110309SSriharsha.Basavapatna@Sun.COM switch (cap) { 199210309SSriharsha.Basavapatna@Sun.COM 199310309SSriharsha.Basavapatna@Sun.COM case MAC_CAPAB_RINGS: { 199410309SSriharsha.Basavapatna@Sun.COM 199510309SSriharsha.Basavapatna@Sun.COM mac_capab_rings_t *cap_rings = cap_data; 199610309SSriharsha.Basavapatna@Sun.COM /* 199710309SSriharsha.Basavapatna@Sun.COM * Rings Capability Notes: 199810309SSriharsha.Basavapatna@Sun.COM * We advertise rings to make use of the rings framework in 199910309SSriharsha.Basavapatna@Sun.COM * gldv3 mac layer, to improve the performance. This is 200010309SSriharsha.Basavapatna@Sun.COM * specifically needed when a Hybrid resource (with multiple 200110309SSriharsha.Basavapatna@Sun.COM * tx/rx hardware rings) is assigned to a vnet device. We also 200210309SSriharsha.Basavapatna@Sun.COM * leverage this for the normal case when no Hybrid resource is 200310309SSriharsha.Basavapatna@Sun.COM * assigned. 200410309SSriharsha.Basavapatna@Sun.COM * 200510309SSriharsha.Basavapatna@Sun.COM * Ring Allocation: 200610309SSriharsha.Basavapatna@Sun.COM * - TX path: 200710309SSriharsha.Basavapatna@Sun.COM * We expose a pseudo ring group with 2 pseudo tx rings (as 200810309SSriharsha.Basavapatna@Sun.COM * currently HybridIO exports only 2 rings) In the normal case, 200910309SSriharsha.Basavapatna@Sun.COM * transmit traffic that comes down to the driver through the 201010309SSriharsha.Basavapatna@Sun.COM * mri_tx (vnet_tx_ring_send()) entry point goes through the 201110309SSriharsha.Basavapatna@Sun.COM * distributed switching algorithm in vnet and gets transmitted 201210309SSriharsha.Basavapatna@Sun.COM * over a port/LDC in the vgen layer to either the vswitch or a 201310309SSriharsha.Basavapatna@Sun.COM * peer vnet. If and when a Hybrid resource is assigned to the 201410309SSriharsha.Basavapatna@Sun.COM * vnet, we obtain the tx ring information of the Hybrid device 201510309SSriharsha.Basavapatna@Sun.COM * (nxge) and map the pseudo rings 1:1 to the 2 hw tx rings. 201610309SSriharsha.Basavapatna@Sun.COM * Traffic being sent over the Hybrid resource by the mac layer 201710309SSriharsha.Basavapatna@Sun.COM * gets spread across both hw rings, as they are mapped to the 201810309SSriharsha.Basavapatna@Sun.COM * 2 pseudo tx rings in vnet. 201910309SSriharsha.Basavapatna@Sun.COM * 202010309SSriharsha.Basavapatna@Sun.COM * - RX path: 202110309SSriharsha.Basavapatna@Sun.COM * We expose a pseudo ring group with 3 pseudo rx rings (static 202210309SSriharsha.Basavapatna@Sun.COM * rings) initially. The first (default) pseudo rx ring is 202310309SSriharsha.Basavapatna@Sun.COM * reserved for the resource that connects to the vswitch 202410309SSriharsha.Basavapatna@Sun.COM * service. The next 2 rings are reserved for a Hybrid resource 202510309SSriharsha.Basavapatna@Sun.COM * that may be assigned to the vnet device. If and when a 202610309SSriharsha.Basavapatna@Sun.COM * Hybrid resource is assigned to the vnet, we obtain the rx 202710309SSriharsha.Basavapatna@Sun.COM * ring information of the Hybrid device (nxge) and map these 202810309SSriharsha.Basavapatna@Sun.COM * pseudo rings 1:1 to the 2 hw rx rings. For each additional 202910309SSriharsha.Basavapatna@Sun.COM * resource that connects to a peer vnet, we dynamically 203010309SSriharsha.Basavapatna@Sun.COM * allocate a pseudo rx ring and map it to that resource, when 203110309SSriharsha.Basavapatna@Sun.COM * the resource gets added; and the pseudo rx ring is 203210309SSriharsha.Basavapatna@Sun.COM * dynamically registered with the upper mac layer. We do the 203310309SSriharsha.Basavapatna@Sun.COM * reverse and unregister the ring with the mac layer when 203410309SSriharsha.Basavapatna@Sun.COM * the resource gets removed. 203510309SSriharsha.Basavapatna@Sun.COM * 203610309SSriharsha.Basavapatna@Sun.COM * Synchronization notes: 203710309SSriharsha.Basavapatna@Sun.COM * We don't need any lock to protect members of ring structure, 203810309SSriharsha.Basavapatna@Sun.COM * specifically ringp->hw_rh, in either the TX or the RX ring, 203910309SSriharsha.Basavapatna@Sun.COM * as explained below. 204010309SSriharsha.Basavapatna@Sun.COM * - TX ring: 204110309SSriharsha.Basavapatna@Sun.COM * ring->hw_rh is initialized only when a Hybrid resource is 204210309SSriharsha.Basavapatna@Sun.COM * associated; and gets referenced only in vnet_hio_tx(). The 204310309SSriharsha.Basavapatna@Sun.COM * Hybrid resource itself is available in fdb only after tx 204410309SSriharsha.Basavapatna@Sun.COM * hwrings are found and mapped; i.e, in vio_net_resource_reg() 204510309SSriharsha.Basavapatna@Sun.COM * we call vnet_bind_rings() first and then call 204610309SSriharsha.Basavapatna@Sun.COM * vnet_start_resources() which adds an entry to fdb. For 204710309SSriharsha.Basavapatna@Sun.COM * traffic going over LDC resources, we don't reference 204810309SSriharsha.Basavapatna@Sun.COM * ring->hw_rh at all. 204910309SSriharsha.Basavapatna@Sun.COM * - RX ring: 205010309SSriharsha.Basavapatna@Sun.COM * For rings mapped to Hybrid resource ring->hw_rh is 205110309SSriharsha.Basavapatna@Sun.COM * initialized and only then do we add the rx callback for 205210309SSriharsha.Basavapatna@Sun.COM * the underlying Hybrid resource; we disable callbacks before 205310309SSriharsha.Basavapatna@Sun.COM * we unmap ring->hw_rh. For rings mapped to LDC resources, we 205410309SSriharsha.Basavapatna@Sun.COM * stop the rx callbacks (in vgen) before we remove ring->hw_rh 205510309SSriharsha.Basavapatna@Sun.COM * (vio_net_resource_unreg()). 205610309SSriharsha.Basavapatna@Sun.COM */ 205710309SSriharsha.Basavapatna@Sun.COM 205810309SSriharsha.Basavapatna@Sun.COM if (cap_rings->mr_type == MAC_RING_TYPE_RX) { 205910309SSriharsha.Basavapatna@Sun.COM cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC; 206010309SSriharsha.Basavapatna@Sun.COM 206110309SSriharsha.Basavapatna@Sun.COM /* 206210309SSriharsha.Basavapatna@Sun.COM * The ring_cnt for rx grp is initialized in 206310309SSriharsha.Basavapatna@Sun.COM * vnet_ring_grp_init(). Later, the ring_cnt gets 206410309SSriharsha.Basavapatna@Sun.COM * updated dynamically whenever LDC resources are added 206510309SSriharsha.Basavapatna@Sun.COM * or removed. 206610309SSriharsha.Basavapatna@Sun.COM */ 206710309SSriharsha.Basavapatna@Sun.COM cap_rings->mr_rnum = vnetp->rx_grp[0].ring_cnt; 206810309SSriharsha.Basavapatna@Sun.COM cap_rings->mr_rget = vnet_get_ring; 206910309SSriharsha.Basavapatna@Sun.COM 207010309SSriharsha.Basavapatna@Sun.COM cap_rings->mr_gnum = VNET_NUM_PSEUDO_GROUPS; 207110309SSriharsha.Basavapatna@Sun.COM cap_rings->mr_gget = vnet_get_group; 207210309SSriharsha.Basavapatna@Sun.COM cap_rings->mr_gaddring = NULL; 207310309SSriharsha.Basavapatna@Sun.COM cap_rings->mr_gremring = NULL; 207410309SSriharsha.Basavapatna@Sun.COM } else { 207510309SSriharsha.Basavapatna@Sun.COM cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC; 207610309SSriharsha.Basavapatna@Sun.COM 207710309SSriharsha.Basavapatna@Sun.COM /* 207810309SSriharsha.Basavapatna@Sun.COM * The ring_cnt for tx grp is initialized in 207910309SSriharsha.Basavapatna@Sun.COM * vnet_ring_grp_init() and remains constant, as we 208010309SSriharsha.Basavapatna@Sun.COM * do not support dymanic tx rings for now. 208110309SSriharsha.Basavapatna@Sun.COM */ 208210309SSriharsha.Basavapatna@Sun.COM cap_rings->mr_rnum = vnetp->tx_grp[0].ring_cnt; 208310309SSriharsha.Basavapatna@Sun.COM cap_rings->mr_rget = vnet_get_ring; 208410309SSriharsha.Basavapatna@Sun.COM 208510309SSriharsha.Basavapatna@Sun.COM /* 208610309SSriharsha.Basavapatna@Sun.COM * Transmit rings are not grouped; i.e, the number of 208710309SSriharsha.Basavapatna@Sun.COM * transmit ring groups advertised should be set to 0. 208810309SSriharsha.Basavapatna@Sun.COM */ 208910309SSriharsha.Basavapatna@Sun.COM cap_rings->mr_gnum = 0; 209010309SSriharsha.Basavapatna@Sun.COM 209110309SSriharsha.Basavapatna@Sun.COM cap_rings->mr_gget = vnet_get_group; 209210309SSriharsha.Basavapatna@Sun.COM cap_rings->mr_gaddring = NULL; 209310309SSriharsha.Basavapatna@Sun.COM cap_rings->mr_gremring = NULL; 209410309SSriharsha.Basavapatna@Sun.COM } 209510309SSriharsha.Basavapatna@Sun.COM return (B_TRUE); 209610309SSriharsha.Basavapatna@Sun.COM 209710309SSriharsha.Basavapatna@Sun.COM } 209810309SSriharsha.Basavapatna@Sun.COM 209910309SSriharsha.Basavapatna@Sun.COM default: 210010309SSriharsha.Basavapatna@Sun.COM break; 210110309SSriharsha.Basavapatna@Sun.COM 210210309SSriharsha.Basavapatna@Sun.COM } 210310309SSriharsha.Basavapatna@Sun.COM 210410309SSriharsha.Basavapatna@Sun.COM return (B_FALSE); 210510309SSriharsha.Basavapatna@Sun.COM } 210610309SSriharsha.Basavapatna@Sun.COM 210710309SSriharsha.Basavapatna@Sun.COM /* 210810309SSriharsha.Basavapatna@Sun.COM * Callback funtion for MAC layer to get ring information. 210910309SSriharsha.Basavapatna@Sun.COM */ 211010309SSriharsha.Basavapatna@Sun.COM static void 211110309SSriharsha.Basavapatna@Sun.COM vnet_get_ring(void *arg, mac_ring_type_t rtype, const int g_index, 211210309SSriharsha.Basavapatna@Sun.COM const int r_index, mac_ring_info_t *infop, mac_ring_handle_t r_handle) 211310309SSriharsha.Basavapatna@Sun.COM { 211410309SSriharsha.Basavapatna@Sun.COM vnet_t *vnetp = arg; 211510309SSriharsha.Basavapatna@Sun.COM 211610309SSriharsha.Basavapatna@Sun.COM switch (rtype) { 211710309SSriharsha.Basavapatna@Sun.COM 211810309SSriharsha.Basavapatna@Sun.COM case MAC_RING_TYPE_RX: { 211910309SSriharsha.Basavapatna@Sun.COM 212010309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_group_t *rx_grp; 212110309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_ring_t *rx_ringp; 212210309SSriharsha.Basavapatna@Sun.COM mac_intr_t *mintr; 212310309SSriharsha.Basavapatna@Sun.COM 212410309SSriharsha.Basavapatna@Sun.COM /* We advertised only one RX group */ 212510309SSriharsha.Basavapatna@Sun.COM ASSERT(g_index == 0); 212610309SSriharsha.Basavapatna@Sun.COM rx_grp = &vnetp->rx_grp[g_index]; 212710309SSriharsha.Basavapatna@Sun.COM 212810309SSriharsha.Basavapatna@Sun.COM /* Check the current # of rings in the rx group */ 212910309SSriharsha.Basavapatna@Sun.COM ASSERT((r_index >= 0) && (r_index < rx_grp->max_ring_cnt)); 213010309SSriharsha.Basavapatna@Sun.COM 213110309SSriharsha.Basavapatna@Sun.COM /* Get the ring based on the index */ 213210309SSriharsha.Basavapatna@Sun.COM rx_ringp = &rx_grp->rings[r_index]; 213310309SSriharsha.Basavapatna@Sun.COM 213410309SSriharsha.Basavapatna@Sun.COM rx_ringp->handle = r_handle; 213510309SSriharsha.Basavapatna@Sun.COM /* 213610309SSriharsha.Basavapatna@Sun.COM * Note: we don't need to save the incoming r_index in rx_ring, 213710309SSriharsha.Basavapatna@Sun.COM * as vnet_ring_grp_init() would have initialized the index for 213810309SSriharsha.Basavapatna@Sun.COM * each ring in the array. 213910309SSriharsha.Basavapatna@Sun.COM */ 214010309SSriharsha.Basavapatna@Sun.COM rx_ringp->grp = rx_grp; 214110309SSriharsha.Basavapatna@Sun.COM rx_ringp->vnetp = vnetp; 214210309SSriharsha.Basavapatna@Sun.COM 214310309SSriharsha.Basavapatna@Sun.COM mintr = &infop->mri_intr; 214410309SSriharsha.Basavapatna@Sun.COM mintr->mi_handle = (mac_intr_handle_t)rx_ringp; 214510309SSriharsha.Basavapatna@Sun.COM mintr->mi_enable = (mac_intr_enable_t)vnet_ring_enable_intr; 214610309SSriharsha.Basavapatna@Sun.COM mintr->mi_disable = (mac_intr_disable_t)vnet_ring_disable_intr; 214710309SSriharsha.Basavapatna@Sun.COM 214810309SSriharsha.Basavapatna@Sun.COM infop->mri_driver = (mac_ring_driver_t)rx_ringp; 214910309SSriharsha.Basavapatna@Sun.COM infop->mri_start = vnet_rx_ring_start; 215010309SSriharsha.Basavapatna@Sun.COM infop->mri_stop = vnet_rx_ring_stop; 215110309SSriharsha.Basavapatna@Sun.COM 215210309SSriharsha.Basavapatna@Sun.COM /* Set the poll function, as this is an rx ring */ 215310309SSriharsha.Basavapatna@Sun.COM infop->mri_poll = vnet_rx_poll; 215410309SSriharsha.Basavapatna@Sun.COM 215510309SSriharsha.Basavapatna@Sun.COM break; 215610309SSriharsha.Basavapatna@Sun.COM } 215710309SSriharsha.Basavapatna@Sun.COM 215810309SSriharsha.Basavapatna@Sun.COM case MAC_RING_TYPE_TX: { 215910309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_tx_group_t *tx_grp; 216010309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_tx_ring_t *tx_ringp; 216110309SSriharsha.Basavapatna@Sun.COM 216210309SSriharsha.Basavapatna@Sun.COM /* 216310309SSriharsha.Basavapatna@Sun.COM * No need to check grp index; mac layer passes -1 for it. 216410309SSriharsha.Basavapatna@Sun.COM */ 216510309SSriharsha.Basavapatna@Sun.COM tx_grp = &vnetp->tx_grp[0]; 216610309SSriharsha.Basavapatna@Sun.COM 216710309SSriharsha.Basavapatna@Sun.COM /* Check the # of rings in the tx group */ 216810309SSriharsha.Basavapatna@Sun.COM ASSERT((r_index >= 0) && (r_index < tx_grp->ring_cnt)); 216910309SSriharsha.Basavapatna@Sun.COM 217010309SSriharsha.Basavapatna@Sun.COM /* Get the ring based on the index */ 217110309SSriharsha.Basavapatna@Sun.COM tx_ringp = &tx_grp->rings[r_index]; 217210309SSriharsha.Basavapatna@Sun.COM 217310309SSriharsha.Basavapatna@Sun.COM tx_ringp->handle = r_handle; 217410309SSriharsha.Basavapatna@Sun.COM tx_ringp->index = r_index; 217510309SSriharsha.Basavapatna@Sun.COM tx_ringp->grp = tx_grp; 217610309SSriharsha.Basavapatna@Sun.COM tx_ringp->vnetp = vnetp; 217710309SSriharsha.Basavapatna@Sun.COM 217810309SSriharsha.Basavapatna@Sun.COM infop->mri_driver = (mac_ring_driver_t)tx_ringp; 217910309SSriharsha.Basavapatna@Sun.COM infop->mri_start = vnet_tx_ring_start; 218010309SSriharsha.Basavapatna@Sun.COM infop->mri_stop = vnet_tx_ring_stop; 218110309SSriharsha.Basavapatna@Sun.COM 218210309SSriharsha.Basavapatna@Sun.COM /* Set the transmit function, as this is a tx ring */ 218310309SSriharsha.Basavapatna@Sun.COM infop->mri_tx = vnet_tx_ring_send; 218410309SSriharsha.Basavapatna@Sun.COM 218510309SSriharsha.Basavapatna@Sun.COM break; 218610309SSriharsha.Basavapatna@Sun.COM } 218710309SSriharsha.Basavapatna@Sun.COM 218810309SSriharsha.Basavapatna@Sun.COM default: 218910309SSriharsha.Basavapatna@Sun.COM break; 219010309SSriharsha.Basavapatna@Sun.COM } 219110309SSriharsha.Basavapatna@Sun.COM } 219210309SSriharsha.Basavapatna@Sun.COM 219310309SSriharsha.Basavapatna@Sun.COM /* 219410309SSriharsha.Basavapatna@Sun.COM * Callback funtion for MAC layer to get group information. 219510309SSriharsha.Basavapatna@Sun.COM */ 219610309SSriharsha.Basavapatna@Sun.COM static void 219710309SSriharsha.Basavapatna@Sun.COM vnet_get_group(void *arg, mac_ring_type_t type, const int index, 219810309SSriharsha.Basavapatna@Sun.COM mac_group_info_t *infop, mac_group_handle_t handle) 219910309SSriharsha.Basavapatna@Sun.COM { 220010309SSriharsha.Basavapatna@Sun.COM vnet_t *vnetp = (vnet_t *)arg; 220110309SSriharsha.Basavapatna@Sun.COM 220210309SSriharsha.Basavapatna@Sun.COM switch (type) { 220310309SSriharsha.Basavapatna@Sun.COM 220410309SSriharsha.Basavapatna@Sun.COM case MAC_RING_TYPE_RX: 220510309SSriharsha.Basavapatna@Sun.COM { 220610309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_group_t *rx_grp; 220710309SSriharsha.Basavapatna@Sun.COM 220810309SSriharsha.Basavapatna@Sun.COM /* We advertised only one RX group */ 220910309SSriharsha.Basavapatna@Sun.COM ASSERT(index == 0); 221010309SSriharsha.Basavapatna@Sun.COM 221110309SSriharsha.Basavapatna@Sun.COM rx_grp = &vnetp->rx_grp[index]; 221210309SSriharsha.Basavapatna@Sun.COM rx_grp->handle = handle; 221310309SSriharsha.Basavapatna@Sun.COM rx_grp->index = index; 221410309SSriharsha.Basavapatna@Sun.COM rx_grp->vnetp = vnetp; 221510309SSriharsha.Basavapatna@Sun.COM 221610309SSriharsha.Basavapatna@Sun.COM infop->mgi_driver = (mac_group_driver_t)rx_grp; 221710309SSriharsha.Basavapatna@Sun.COM infop->mgi_start = NULL; 221810309SSriharsha.Basavapatna@Sun.COM infop->mgi_stop = NULL; 221910309SSriharsha.Basavapatna@Sun.COM infop->mgi_addmac = vnet_addmac; 222010309SSriharsha.Basavapatna@Sun.COM infop->mgi_remmac = vnet_remmac; 222110309SSriharsha.Basavapatna@Sun.COM infop->mgi_count = rx_grp->ring_cnt; 222210309SSriharsha.Basavapatna@Sun.COM 222310309SSriharsha.Basavapatna@Sun.COM break; 222410309SSriharsha.Basavapatna@Sun.COM } 222510309SSriharsha.Basavapatna@Sun.COM 222610309SSriharsha.Basavapatna@Sun.COM case MAC_RING_TYPE_TX: 222710309SSriharsha.Basavapatna@Sun.COM { 222810309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_tx_group_t *tx_grp; 222910309SSriharsha.Basavapatna@Sun.COM 223010309SSriharsha.Basavapatna@Sun.COM /* We advertised only one TX group */ 223110309SSriharsha.Basavapatna@Sun.COM ASSERT(index == 0); 223210309SSriharsha.Basavapatna@Sun.COM 223310309SSriharsha.Basavapatna@Sun.COM tx_grp = &vnetp->tx_grp[index]; 223410309SSriharsha.Basavapatna@Sun.COM tx_grp->handle = handle; 223510309SSriharsha.Basavapatna@Sun.COM tx_grp->index = index; 223610309SSriharsha.Basavapatna@Sun.COM tx_grp->vnetp = vnetp; 223710309SSriharsha.Basavapatna@Sun.COM 223810309SSriharsha.Basavapatna@Sun.COM infop->mgi_driver = (mac_group_driver_t)tx_grp; 223910309SSriharsha.Basavapatna@Sun.COM infop->mgi_start = NULL; 224010309SSriharsha.Basavapatna@Sun.COM infop->mgi_stop = NULL; 224110309SSriharsha.Basavapatna@Sun.COM infop->mgi_addmac = NULL; 224210309SSriharsha.Basavapatna@Sun.COM infop->mgi_remmac = NULL; 224310309SSriharsha.Basavapatna@Sun.COM infop->mgi_count = VNET_NUM_PSEUDO_TXRINGS; 224410309SSriharsha.Basavapatna@Sun.COM 224510309SSriharsha.Basavapatna@Sun.COM break; 224610309SSriharsha.Basavapatna@Sun.COM } 224710309SSriharsha.Basavapatna@Sun.COM 224810309SSriharsha.Basavapatna@Sun.COM default: 224910309SSriharsha.Basavapatna@Sun.COM break; 225010309SSriharsha.Basavapatna@Sun.COM 225110309SSriharsha.Basavapatna@Sun.COM } 225210309SSriharsha.Basavapatna@Sun.COM } 225310309SSriharsha.Basavapatna@Sun.COM 225410309SSriharsha.Basavapatna@Sun.COM static int 225510309SSriharsha.Basavapatna@Sun.COM vnet_rx_ring_start(mac_ring_driver_t arg, uint64_t mr_gen_num) 225610309SSriharsha.Basavapatna@Sun.COM { 225710309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_ring_t *rx_ringp = (vnet_pseudo_rx_ring_t *)arg; 225810309SSriharsha.Basavapatna@Sun.COM int err; 225910309SSriharsha.Basavapatna@Sun.COM 226010309SSriharsha.Basavapatna@Sun.COM /* 226110309SSriharsha.Basavapatna@Sun.COM * If this ring is mapped to a LDC resource, simply mark the state to 226210309SSriharsha.Basavapatna@Sun.COM * indicate the ring is started and return. 226310309SSriharsha.Basavapatna@Sun.COM */ 226410309SSriharsha.Basavapatna@Sun.COM if ((rx_ringp->state & 226510309SSriharsha.Basavapatna@Sun.COM (VNET_RXRING_LDC_SERVICE|VNET_RXRING_LDC_GUEST)) != 0) { 226610309SSriharsha.Basavapatna@Sun.COM rx_ringp->gen_num = mr_gen_num; 226710309SSriharsha.Basavapatna@Sun.COM rx_ringp->state |= VNET_RXRING_STARTED; 226810309SSriharsha.Basavapatna@Sun.COM return (0); 226910309SSriharsha.Basavapatna@Sun.COM } 227010309SSriharsha.Basavapatna@Sun.COM 227110309SSriharsha.Basavapatna@Sun.COM ASSERT((rx_ringp->state & VNET_RXRING_HYBRID) != 0); 227210309SSriharsha.Basavapatna@Sun.COM 227310309SSriharsha.Basavapatna@Sun.COM /* 227410309SSriharsha.Basavapatna@Sun.COM * This must be a ring reserved for a hwring. If the hwring is not 227510309SSriharsha.Basavapatna@Sun.COM * bound yet, simply mark the state to indicate the ring is started and 227610309SSriharsha.Basavapatna@Sun.COM * return. If and when a hybrid resource is activated for this vnet 227710309SSriharsha.Basavapatna@Sun.COM * device, we will bind the hwring and start it then. If a hwring is 227810309SSriharsha.Basavapatna@Sun.COM * already bound, start it now. 227910309SSriharsha.Basavapatna@Sun.COM */ 228010309SSriharsha.Basavapatna@Sun.COM if (rx_ringp->hw_rh == NULL) { 228110309SSriharsha.Basavapatna@Sun.COM rx_ringp->gen_num = mr_gen_num; 228210309SSriharsha.Basavapatna@Sun.COM rx_ringp->state |= VNET_RXRING_STARTED; 228310309SSriharsha.Basavapatna@Sun.COM return (0); 228410309SSriharsha.Basavapatna@Sun.COM } 228510309SSriharsha.Basavapatna@Sun.COM 228610309SSriharsha.Basavapatna@Sun.COM err = mac_hwring_start(rx_ringp->hw_rh); 228710309SSriharsha.Basavapatna@Sun.COM if (err == 0) { 228810309SSriharsha.Basavapatna@Sun.COM rx_ringp->gen_num = mr_gen_num; 228910309SSriharsha.Basavapatna@Sun.COM rx_ringp->state |= VNET_RXRING_STARTED; 229010309SSriharsha.Basavapatna@Sun.COM } else { 229110309SSriharsha.Basavapatna@Sun.COM err = ENXIO; 229210309SSriharsha.Basavapatna@Sun.COM } 229310309SSriharsha.Basavapatna@Sun.COM 229410309SSriharsha.Basavapatna@Sun.COM return (err); 229510309SSriharsha.Basavapatna@Sun.COM } 229610309SSriharsha.Basavapatna@Sun.COM 229710309SSriharsha.Basavapatna@Sun.COM static void 229810309SSriharsha.Basavapatna@Sun.COM vnet_rx_ring_stop(mac_ring_driver_t arg) 229910309SSriharsha.Basavapatna@Sun.COM { 230010309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_ring_t *rx_ringp = (vnet_pseudo_rx_ring_t *)arg; 230110309SSriharsha.Basavapatna@Sun.COM 230210309SSriharsha.Basavapatna@Sun.COM /* 230310309SSriharsha.Basavapatna@Sun.COM * If this ring is mapped to a LDC resource, simply mark the state to 230410309SSriharsha.Basavapatna@Sun.COM * indicate the ring is now stopped and return. 230510309SSriharsha.Basavapatna@Sun.COM */ 230610309SSriharsha.Basavapatna@Sun.COM if ((rx_ringp->state & 230710309SSriharsha.Basavapatna@Sun.COM (VNET_RXRING_LDC_SERVICE|VNET_RXRING_LDC_GUEST)) != 0) { 230810309SSriharsha.Basavapatna@Sun.COM rx_ringp->state &= ~VNET_RXRING_STARTED; 230910439SWentao.Yang@Sun.COM return; 231010309SSriharsha.Basavapatna@Sun.COM } 231110309SSriharsha.Basavapatna@Sun.COM 231210309SSriharsha.Basavapatna@Sun.COM ASSERT((rx_ringp->state & VNET_RXRING_HYBRID) != 0); 231310309SSriharsha.Basavapatna@Sun.COM 231410309SSriharsha.Basavapatna@Sun.COM /* 231510309SSriharsha.Basavapatna@Sun.COM * This must be a ring reserved for a hwring. If the hwring is not 231610309SSriharsha.Basavapatna@Sun.COM * bound yet, simply mark the state to indicate the ring is stopped and 231710309SSriharsha.Basavapatna@Sun.COM * return. If a hwring is already bound, stop it now. 231810309SSriharsha.Basavapatna@Sun.COM */ 231910309SSriharsha.Basavapatna@Sun.COM if (rx_ringp->hw_rh == NULL) { 232010309SSriharsha.Basavapatna@Sun.COM rx_ringp->state &= ~VNET_RXRING_STARTED; 232110309SSriharsha.Basavapatna@Sun.COM return; 232210309SSriharsha.Basavapatna@Sun.COM } 232310309SSriharsha.Basavapatna@Sun.COM 232410309SSriharsha.Basavapatna@Sun.COM mac_hwring_stop(rx_ringp->hw_rh); 232510309SSriharsha.Basavapatna@Sun.COM rx_ringp->state &= ~VNET_RXRING_STARTED; 232610309SSriharsha.Basavapatna@Sun.COM } 232710309SSriharsha.Basavapatna@Sun.COM 232810309SSriharsha.Basavapatna@Sun.COM /* ARGSUSED */ 232910309SSriharsha.Basavapatna@Sun.COM static int 233010309SSriharsha.Basavapatna@Sun.COM vnet_tx_ring_start(mac_ring_driver_t arg, uint64_t mr_gen_num) 233110309SSriharsha.Basavapatna@Sun.COM { 233210309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_tx_ring_t *tx_ringp = (vnet_pseudo_tx_ring_t *)arg; 233310309SSriharsha.Basavapatna@Sun.COM 233410309SSriharsha.Basavapatna@Sun.COM tx_ringp->state |= VNET_TXRING_STARTED; 233510309SSriharsha.Basavapatna@Sun.COM return (0); 233610309SSriharsha.Basavapatna@Sun.COM } 233710309SSriharsha.Basavapatna@Sun.COM 233810309SSriharsha.Basavapatna@Sun.COM static void 233910309SSriharsha.Basavapatna@Sun.COM vnet_tx_ring_stop(mac_ring_driver_t arg) 234010309SSriharsha.Basavapatna@Sun.COM { 234110309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_tx_ring_t *tx_ringp = (vnet_pseudo_tx_ring_t *)arg; 234210309SSriharsha.Basavapatna@Sun.COM 234310309SSriharsha.Basavapatna@Sun.COM tx_ringp->state &= ~VNET_TXRING_STARTED; 234410309SSriharsha.Basavapatna@Sun.COM } 234510309SSriharsha.Basavapatna@Sun.COM 234610309SSriharsha.Basavapatna@Sun.COM /* 234710309SSriharsha.Basavapatna@Sun.COM * Disable polling for a ring and enable its interrupt. 234810309SSriharsha.Basavapatna@Sun.COM */ 234910309SSriharsha.Basavapatna@Sun.COM static int 235010309SSriharsha.Basavapatna@Sun.COM vnet_ring_enable_intr(void *arg) 235110309SSriharsha.Basavapatna@Sun.COM { 235210309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_ring_t *rx_ringp = (vnet_pseudo_rx_ring_t *)arg; 235310309SSriharsha.Basavapatna@Sun.COM vnet_res_t *vresp; 235410309SSriharsha.Basavapatna@Sun.COM 235510309SSriharsha.Basavapatna@Sun.COM if (rx_ringp->hw_rh == NULL) { 235610309SSriharsha.Basavapatna@Sun.COM /* 235710309SSriharsha.Basavapatna@Sun.COM * Ring enable intr func is being invoked, but the ring is 235810309SSriharsha.Basavapatna@Sun.COM * not bound to any underlying resource ? This must be a ring 235910309SSriharsha.Basavapatna@Sun.COM * reserved for Hybrid resource and no such resource has been 236010309SSriharsha.Basavapatna@Sun.COM * assigned to this vnet device yet. We simply return success. 236110309SSriharsha.Basavapatna@Sun.COM */ 236210309SSriharsha.Basavapatna@Sun.COM ASSERT((rx_ringp->state & VNET_RXRING_HYBRID) != 0); 236310309SSriharsha.Basavapatna@Sun.COM return (0); 236410309SSriharsha.Basavapatna@Sun.COM } 236510309SSriharsha.Basavapatna@Sun.COM 236610309SSriharsha.Basavapatna@Sun.COM /* 236710309SSriharsha.Basavapatna@Sun.COM * The rx ring has been bound to either a LDC or a Hybrid resource. 236810309SSriharsha.Basavapatna@Sun.COM * Call the appropriate function to enable interrupts for the ring. 236910309SSriharsha.Basavapatna@Sun.COM */ 237010309SSriharsha.Basavapatna@Sun.COM if (rx_ringp->state & VNET_RXRING_HYBRID) { 237110309SSriharsha.Basavapatna@Sun.COM return (mac_hwring_enable_intr(rx_ringp->hw_rh)); 237210309SSriharsha.Basavapatna@Sun.COM } else { 237310309SSriharsha.Basavapatna@Sun.COM vresp = (vnet_res_t *)rx_ringp->hw_rh; 237410309SSriharsha.Basavapatna@Sun.COM return (vgen_enable_intr(vresp->macreg.m_driver)); 237510309SSriharsha.Basavapatna@Sun.COM } 237610309SSriharsha.Basavapatna@Sun.COM } 237710309SSriharsha.Basavapatna@Sun.COM 237810309SSriharsha.Basavapatna@Sun.COM /* 237910309SSriharsha.Basavapatna@Sun.COM * Enable polling for a ring and disable its interrupt. 238010309SSriharsha.Basavapatna@Sun.COM */ 238110309SSriharsha.Basavapatna@Sun.COM static int 238210309SSriharsha.Basavapatna@Sun.COM vnet_ring_disable_intr(void *arg) 238310309SSriharsha.Basavapatna@Sun.COM { 238410309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_ring_t *rx_ringp = (vnet_pseudo_rx_ring_t *)arg; 238510309SSriharsha.Basavapatna@Sun.COM vnet_res_t *vresp; 238610309SSriharsha.Basavapatna@Sun.COM 238710309SSriharsha.Basavapatna@Sun.COM if (rx_ringp->hw_rh == NULL) { 238810309SSriharsha.Basavapatna@Sun.COM /* 238910309SSriharsha.Basavapatna@Sun.COM * Ring disable intr func is being invoked, but the ring is 239010309SSriharsha.Basavapatna@Sun.COM * not bound to any underlying resource ? This must be a ring 239110309SSriharsha.Basavapatna@Sun.COM * reserved for Hybrid resource and no such resource has been 239210309SSriharsha.Basavapatna@Sun.COM * assigned to this vnet device yet. We simply return success. 239310309SSriharsha.Basavapatna@Sun.COM */ 239410309SSriharsha.Basavapatna@Sun.COM ASSERT((rx_ringp->state & VNET_RXRING_HYBRID) != 0); 239510309SSriharsha.Basavapatna@Sun.COM return (0); 239610309SSriharsha.Basavapatna@Sun.COM } 239710309SSriharsha.Basavapatna@Sun.COM 239810309SSriharsha.Basavapatna@Sun.COM /* 239910309SSriharsha.Basavapatna@Sun.COM * The rx ring has been bound to either a LDC or a Hybrid resource. 240010309SSriharsha.Basavapatna@Sun.COM * Call the appropriate function to disable interrupts for the ring. 240110309SSriharsha.Basavapatna@Sun.COM */ 240210309SSriharsha.Basavapatna@Sun.COM if (rx_ringp->state & VNET_RXRING_HYBRID) { 240310309SSriharsha.Basavapatna@Sun.COM return (mac_hwring_disable_intr(rx_ringp->hw_rh)); 240410309SSriharsha.Basavapatna@Sun.COM } else { 240510309SSriharsha.Basavapatna@Sun.COM vresp = (vnet_res_t *)rx_ringp->hw_rh; 240610309SSriharsha.Basavapatna@Sun.COM return (vgen_disable_intr(vresp->macreg.m_driver)); 240710309SSriharsha.Basavapatna@Sun.COM } 240810309SSriharsha.Basavapatna@Sun.COM } 240910309SSriharsha.Basavapatna@Sun.COM 241010309SSriharsha.Basavapatna@Sun.COM /* 241110309SSriharsha.Basavapatna@Sun.COM * Poll 'bytes_to_pickup' bytes of message from the rx ring. 241210309SSriharsha.Basavapatna@Sun.COM */ 241310309SSriharsha.Basavapatna@Sun.COM static mblk_t * 241410309SSriharsha.Basavapatna@Sun.COM vnet_rx_poll(void *arg, int bytes_to_pickup) 241510309SSriharsha.Basavapatna@Sun.COM { 241610309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_ring_t *rx_ringp = (vnet_pseudo_rx_ring_t *)arg; 241710309SSriharsha.Basavapatna@Sun.COM mblk_t *mp = NULL; 241810309SSriharsha.Basavapatna@Sun.COM vnet_res_t *vresp; 241910309SSriharsha.Basavapatna@Sun.COM vnet_t *vnetp = rx_ringp->vnetp; 242010309SSriharsha.Basavapatna@Sun.COM 242110309SSriharsha.Basavapatna@Sun.COM if (rx_ringp->hw_rh == NULL) { 242210309SSriharsha.Basavapatna@Sun.COM return (NULL); 242310309SSriharsha.Basavapatna@Sun.COM } 242410309SSriharsha.Basavapatna@Sun.COM 242510309SSriharsha.Basavapatna@Sun.COM if (rx_ringp->state & VNET_RXRING_HYBRID) { 242610309SSriharsha.Basavapatna@Sun.COM mp = mac_hwring_poll(rx_ringp->hw_rh, bytes_to_pickup); 242710309SSriharsha.Basavapatna@Sun.COM /* 242810309SSriharsha.Basavapatna@Sun.COM * Packets received over a hybrid resource need additional 242910309SSriharsha.Basavapatna@Sun.COM * processing to remove the tag, for the pvid case. The 243010309SSriharsha.Basavapatna@Sun.COM * underlying resource is not aware of the vnet's pvid and thus 243110309SSriharsha.Basavapatna@Sun.COM * packets are received with the vlan tag in the header; unlike 243210309SSriharsha.Basavapatna@Sun.COM * packets that are received over a ldc channel in which case 243310309SSriharsha.Basavapatna@Sun.COM * the peer vnet/vsw would have already removed the tag. 243410309SSriharsha.Basavapatna@Sun.COM */ 243510309SSriharsha.Basavapatna@Sun.COM if (vnetp->pvid != vnetp->default_vlan_id) { 243610309SSriharsha.Basavapatna@Sun.COM vnet_rx_frames_untag(vnetp->pvid, &mp); 243710309SSriharsha.Basavapatna@Sun.COM } 243810309SSriharsha.Basavapatna@Sun.COM } else { 243910309SSriharsha.Basavapatna@Sun.COM vresp = (vnet_res_t *)rx_ringp->hw_rh; 244010309SSriharsha.Basavapatna@Sun.COM mp = vgen_poll(vresp->macreg.m_driver, bytes_to_pickup); 244110309SSriharsha.Basavapatna@Sun.COM } 244210309SSriharsha.Basavapatna@Sun.COM return (mp); 244310309SSriharsha.Basavapatna@Sun.COM } 244410309SSriharsha.Basavapatna@Sun.COM 244510309SSriharsha.Basavapatna@Sun.COM /* ARGSUSED */ 244610309SSriharsha.Basavapatna@Sun.COM void 244710309SSriharsha.Basavapatna@Sun.COM vnet_hio_rx_cb(void *arg, mac_resource_handle_t mrh, mblk_t *mp, 244810309SSriharsha.Basavapatna@Sun.COM boolean_t loopback) 244910309SSriharsha.Basavapatna@Sun.COM { 245010309SSriharsha.Basavapatna@Sun.COM vnet_t *vnetp = (vnet_t *)arg; 245110309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_ring_t *ringp = (vnet_pseudo_rx_ring_t *)mrh; 245210309SSriharsha.Basavapatna@Sun.COM 245310309SSriharsha.Basavapatna@Sun.COM /* 245410309SSriharsha.Basavapatna@Sun.COM * Packets received over a hybrid resource need additional processing 245510309SSriharsha.Basavapatna@Sun.COM * to remove the tag, for the pvid case. The underlying resource is 245610309SSriharsha.Basavapatna@Sun.COM * not aware of the vnet's pvid and thus packets are received with the 245710309SSriharsha.Basavapatna@Sun.COM * vlan tag in the header; unlike packets that are received over a ldc 245810309SSriharsha.Basavapatna@Sun.COM * channel in which case the peer vnet/vsw would have already removed 245910309SSriharsha.Basavapatna@Sun.COM * the tag. 246010309SSriharsha.Basavapatna@Sun.COM */ 246110309SSriharsha.Basavapatna@Sun.COM if (vnetp->pvid != vnetp->default_vlan_id) { 246210309SSriharsha.Basavapatna@Sun.COM vnet_rx_frames_untag(vnetp->pvid, &mp); 246310309SSriharsha.Basavapatna@Sun.COM if (mp == NULL) { 246410309SSriharsha.Basavapatna@Sun.COM return; 246510309SSriharsha.Basavapatna@Sun.COM } 246610309SSriharsha.Basavapatna@Sun.COM } 246710309SSriharsha.Basavapatna@Sun.COM mac_rx_ring(vnetp->mh, ringp->handle, mp, ringp->gen_num); 246810309SSriharsha.Basavapatna@Sun.COM } 246910309SSriharsha.Basavapatna@Sun.COM 247010309SSriharsha.Basavapatna@Sun.COM static int 247110309SSriharsha.Basavapatna@Sun.COM vnet_addmac(void *arg, const uint8_t *mac_addr) 247210309SSriharsha.Basavapatna@Sun.COM { 247310309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_group_t *rx_grp = (vnet_pseudo_rx_group_t *)arg; 247410309SSriharsha.Basavapatna@Sun.COM vnet_t *vnetp; 247510309SSriharsha.Basavapatna@Sun.COM 247610309SSriharsha.Basavapatna@Sun.COM vnetp = rx_grp->vnetp; 247710309SSriharsha.Basavapatna@Sun.COM 247810309SSriharsha.Basavapatna@Sun.COM if (bcmp(mac_addr, vnetp->curr_macaddr, ETHERADDRL) == 0) { 247910309SSriharsha.Basavapatna@Sun.COM return (0); 248010309SSriharsha.Basavapatna@Sun.COM } 248110309SSriharsha.Basavapatna@Sun.COM 248210309SSriharsha.Basavapatna@Sun.COM cmn_err(CE_CONT, "!vnet%d: %s: Multiple macaddr unsupported\n", 248310309SSriharsha.Basavapatna@Sun.COM vnetp->instance, __func__); 248410309SSriharsha.Basavapatna@Sun.COM return (EINVAL); 248510309SSriharsha.Basavapatna@Sun.COM } 248610309SSriharsha.Basavapatna@Sun.COM 248710309SSriharsha.Basavapatna@Sun.COM static int 248810309SSriharsha.Basavapatna@Sun.COM vnet_remmac(void *arg, const uint8_t *mac_addr) 248910309SSriharsha.Basavapatna@Sun.COM { 249010309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_group_t *rx_grp = (vnet_pseudo_rx_group_t *)arg; 249110309SSriharsha.Basavapatna@Sun.COM vnet_t *vnetp; 249210309SSriharsha.Basavapatna@Sun.COM 249310309SSriharsha.Basavapatna@Sun.COM vnetp = rx_grp->vnetp; 249410309SSriharsha.Basavapatna@Sun.COM 249510309SSriharsha.Basavapatna@Sun.COM if (bcmp(mac_addr, vnetp->curr_macaddr, ETHERADDRL) == 0) { 249610309SSriharsha.Basavapatna@Sun.COM return (0); 249710309SSriharsha.Basavapatna@Sun.COM } 249810309SSriharsha.Basavapatna@Sun.COM 249910309SSriharsha.Basavapatna@Sun.COM cmn_err(CE_CONT, "!vnet%d: %s: Invalid macaddr: %s\n", 250010309SSriharsha.Basavapatna@Sun.COM vnetp->instance, __func__, ether_sprintf((void *)mac_addr)); 250110309SSriharsha.Basavapatna@Sun.COM return (EINVAL); 250210309SSriharsha.Basavapatna@Sun.COM } 250310309SSriharsha.Basavapatna@Sun.COM 250410309SSriharsha.Basavapatna@Sun.COM int 250510309SSriharsha.Basavapatna@Sun.COM vnet_hio_mac_init(vnet_t *vnetp, char *ifname) 250610309SSriharsha.Basavapatna@Sun.COM { 250710309SSriharsha.Basavapatna@Sun.COM mac_handle_t mh; 250810309SSriharsha.Basavapatna@Sun.COM mac_client_handle_t mch = NULL; 250910309SSriharsha.Basavapatna@Sun.COM mac_unicast_handle_t muh = NULL; 251010309SSriharsha.Basavapatna@Sun.COM mac_diag_t diag; 251110309SSriharsha.Basavapatna@Sun.COM mac_register_t *macp; 251210309SSriharsha.Basavapatna@Sun.COM char client_name[MAXNAMELEN]; 251310309SSriharsha.Basavapatna@Sun.COM int rv; 251410309SSriharsha.Basavapatna@Sun.COM uint16_t mac_flags = MAC_UNICAST_TAG_DISABLE | 251510309SSriharsha.Basavapatna@Sun.COM MAC_UNICAST_STRIP_DISABLE | MAC_UNICAST_PRIMARY; 251610309SSriharsha.Basavapatna@Sun.COM vio_net_callbacks_t vcb; 251710309SSriharsha.Basavapatna@Sun.COM ether_addr_t rem_addr = 251810309SSriharsha.Basavapatna@Sun.COM { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 251910309SSriharsha.Basavapatna@Sun.COM uint32_t retries = 0; 252010309SSriharsha.Basavapatna@Sun.COM 252110309SSriharsha.Basavapatna@Sun.COM if ((macp = mac_alloc(MAC_VERSION)) == NULL) { 252210309SSriharsha.Basavapatna@Sun.COM return (EAGAIN); 252310309SSriharsha.Basavapatna@Sun.COM } 252410309SSriharsha.Basavapatna@Sun.COM 252510309SSriharsha.Basavapatna@Sun.COM do { 252610309SSriharsha.Basavapatna@Sun.COM rv = mac_open_by_linkname(ifname, &mh); 252710309SSriharsha.Basavapatna@Sun.COM if (rv == 0) { 252810309SSriharsha.Basavapatna@Sun.COM break; 252910309SSriharsha.Basavapatna@Sun.COM } 253010309SSriharsha.Basavapatna@Sun.COM if (rv != ENOENT || (retries++ >= vnet_mac_open_retries)) { 253110309SSriharsha.Basavapatna@Sun.COM mac_free(macp); 253210309SSriharsha.Basavapatna@Sun.COM return (rv); 253310309SSriharsha.Basavapatna@Sun.COM } 253410309SSriharsha.Basavapatna@Sun.COM drv_usecwait(vnet_mac_open_delay); 253510309SSriharsha.Basavapatna@Sun.COM } while (rv == ENOENT); 253610309SSriharsha.Basavapatna@Sun.COM 253710309SSriharsha.Basavapatna@Sun.COM vnetp->hio_mh = mh; 253810309SSriharsha.Basavapatna@Sun.COM 253910309SSriharsha.Basavapatna@Sun.COM (void) snprintf(client_name, MAXNAMELEN, "vnet%d-%s", vnetp->instance, 254010309SSriharsha.Basavapatna@Sun.COM ifname); 254110309SSriharsha.Basavapatna@Sun.COM rv = mac_client_open(mh, &mch, client_name, MAC_OPEN_FLAGS_EXCLUSIVE); 254210309SSriharsha.Basavapatna@Sun.COM if (rv != 0) { 254310309SSriharsha.Basavapatna@Sun.COM goto fail; 254410309SSriharsha.Basavapatna@Sun.COM } 254510309SSriharsha.Basavapatna@Sun.COM vnetp->hio_mch = mch; 254610309SSriharsha.Basavapatna@Sun.COM 254710309SSriharsha.Basavapatna@Sun.COM rv = mac_unicast_add(mch, vnetp->curr_macaddr, mac_flags, &muh, 0, 254810309SSriharsha.Basavapatna@Sun.COM &diag); 254910309SSriharsha.Basavapatna@Sun.COM if (rv != 0) { 255010309SSriharsha.Basavapatna@Sun.COM goto fail; 255110309SSriharsha.Basavapatna@Sun.COM } 255210309SSriharsha.Basavapatna@Sun.COM vnetp->hio_muh = muh; 255310309SSriharsha.Basavapatna@Sun.COM 255410309SSriharsha.Basavapatna@Sun.COM macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 255510309SSriharsha.Basavapatna@Sun.COM macp->m_driver = vnetp; 255610309SSriharsha.Basavapatna@Sun.COM macp->m_dip = NULL; 255710309SSriharsha.Basavapatna@Sun.COM macp->m_src_addr = NULL; 255810309SSriharsha.Basavapatna@Sun.COM macp->m_callbacks = &vnet_hio_res_callbacks; 255910309SSriharsha.Basavapatna@Sun.COM macp->m_min_sdu = 0; 256010309SSriharsha.Basavapatna@Sun.COM macp->m_max_sdu = ETHERMTU; 256110309SSriharsha.Basavapatna@Sun.COM 256210309SSriharsha.Basavapatna@Sun.COM rv = vio_net_resource_reg(macp, VIO_NET_RES_HYBRID, 256310309SSriharsha.Basavapatna@Sun.COM vnetp->curr_macaddr, rem_addr, &vnetp->hio_vhp, &vcb); 256410309SSriharsha.Basavapatna@Sun.COM if (rv != 0) { 256510309SSriharsha.Basavapatna@Sun.COM goto fail; 256610309SSriharsha.Basavapatna@Sun.COM } 256710309SSriharsha.Basavapatna@Sun.COM mac_free(macp); 256810309SSriharsha.Basavapatna@Sun.COM 256910309SSriharsha.Basavapatna@Sun.COM /* add the recv callback */ 257010309SSriharsha.Basavapatna@Sun.COM mac_rx_set(vnetp->hio_mch, vnet_hio_rx_cb, vnetp); 257110309SSriharsha.Basavapatna@Sun.COM 257210309SSriharsha.Basavapatna@Sun.COM /* add the notify callback - only tx updates for now */ 257310309SSriharsha.Basavapatna@Sun.COM vnetp->hio_mnh = mac_notify_add(vnetp->hio_mh, vnet_hio_notify_cb, 257410309SSriharsha.Basavapatna@Sun.COM vnetp); 257510309SSriharsha.Basavapatna@Sun.COM 257610309SSriharsha.Basavapatna@Sun.COM return (0); 257710309SSriharsha.Basavapatna@Sun.COM 257810309SSriharsha.Basavapatna@Sun.COM fail: 257910309SSriharsha.Basavapatna@Sun.COM mac_free(macp); 258010309SSriharsha.Basavapatna@Sun.COM vnet_hio_mac_cleanup(vnetp); 258110309SSriharsha.Basavapatna@Sun.COM return (1); 258210309SSriharsha.Basavapatna@Sun.COM } 258310309SSriharsha.Basavapatna@Sun.COM 258410309SSriharsha.Basavapatna@Sun.COM void 258510309SSriharsha.Basavapatna@Sun.COM vnet_hio_mac_cleanup(vnet_t *vnetp) 258610309SSriharsha.Basavapatna@Sun.COM { 258710309SSriharsha.Basavapatna@Sun.COM if (vnetp->hio_mnh != NULL) { 258810309SSriharsha.Basavapatna@Sun.COM (void) mac_notify_remove(vnetp->hio_mnh, B_TRUE); 258910309SSriharsha.Basavapatna@Sun.COM vnetp->hio_mnh = NULL; 259010309SSriharsha.Basavapatna@Sun.COM } 259110309SSriharsha.Basavapatna@Sun.COM 259210309SSriharsha.Basavapatna@Sun.COM if (vnetp->hio_vhp != NULL) { 259310309SSriharsha.Basavapatna@Sun.COM vio_net_resource_unreg(vnetp->hio_vhp); 259410309SSriharsha.Basavapatna@Sun.COM vnetp->hio_vhp = NULL; 259510309SSriharsha.Basavapatna@Sun.COM } 259610309SSriharsha.Basavapatna@Sun.COM 259710309SSriharsha.Basavapatna@Sun.COM if (vnetp->hio_muh != NULL) { 259811311SSurya.Prakki@Sun.COM (void) mac_unicast_remove(vnetp->hio_mch, vnetp->hio_muh); 259910309SSriharsha.Basavapatna@Sun.COM vnetp->hio_muh = NULL; 260010309SSriharsha.Basavapatna@Sun.COM } 260110309SSriharsha.Basavapatna@Sun.COM 260210309SSriharsha.Basavapatna@Sun.COM if (vnetp->hio_mch != NULL) { 260310309SSriharsha.Basavapatna@Sun.COM mac_client_close(vnetp->hio_mch, 0); 260410309SSriharsha.Basavapatna@Sun.COM vnetp->hio_mch = NULL; 260510309SSriharsha.Basavapatna@Sun.COM } 260610309SSriharsha.Basavapatna@Sun.COM 260710309SSriharsha.Basavapatna@Sun.COM if (vnetp->hio_mh != NULL) { 260810309SSriharsha.Basavapatna@Sun.COM mac_close(vnetp->hio_mh); 260910309SSriharsha.Basavapatna@Sun.COM vnetp->hio_mh = NULL; 261010309SSriharsha.Basavapatna@Sun.COM } 261110309SSriharsha.Basavapatna@Sun.COM } 261210309SSriharsha.Basavapatna@Sun.COM 261310309SSriharsha.Basavapatna@Sun.COM /* Bind pseudo rings to hwrings */ 261410309SSriharsha.Basavapatna@Sun.COM static int 261510309SSriharsha.Basavapatna@Sun.COM vnet_bind_hwrings(vnet_t *vnetp) 261610309SSriharsha.Basavapatna@Sun.COM { 261710309SSriharsha.Basavapatna@Sun.COM mac_ring_handle_t hw_rh[VNET_NUM_HYBRID_RINGS]; 261810309SSriharsha.Basavapatna@Sun.COM mac_perim_handle_t mph1; 261910309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_group_t *rx_grp; 262010309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_ring_t *rx_ringp; 262110309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_tx_group_t *tx_grp; 262210309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_tx_ring_t *tx_ringp; 262310309SSriharsha.Basavapatna@Sun.COM int hw_ring_cnt; 262410309SSriharsha.Basavapatna@Sun.COM int i; 262510309SSriharsha.Basavapatna@Sun.COM int rv; 262610309SSriharsha.Basavapatna@Sun.COM 262710309SSriharsha.Basavapatna@Sun.COM mac_perim_enter_by_mh(vnetp->hio_mh, &mph1); 262810309SSriharsha.Basavapatna@Sun.COM 262910309SSriharsha.Basavapatna@Sun.COM /* Get the list of the underlying RX rings. */ 263010309SSriharsha.Basavapatna@Sun.COM hw_ring_cnt = mac_hwrings_get(vnetp->hio_mch, &vnetp->rx_hwgh, hw_rh, 263110309SSriharsha.Basavapatna@Sun.COM MAC_RING_TYPE_RX); 263210309SSriharsha.Basavapatna@Sun.COM 263310309SSriharsha.Basavapatna@Sun.COM /* We expect the the # of hw rx rings to match VNET_NUM_HYBRID_RINGS */ 263410309SSriharsha.Basavapatna@Sun.COM if (hw_ring_cnt != VNET_NUM_HYBRID_RINGS) { 263510309SSriharsha.Basavapatna@Sun.COM cmn_err(CE_WARN, 263610309SSriharsha.Basavapatna@Sun.COM "!vnet%d: vnet_bind_hwrings: bad rx hw_ring_cnt(%d)\n", 263710309SSriharsha.Basavapatna@Sun.COM vnetp->instance, hw_ring_cnt); 263810309SSriharsha.Basavapatna@Sun.COM goto fail; 263910309SSriharsha.Basavapatna@Sun.COM } 264010309SSriharsha.Basavapatna@Sun.COM 264110309SSriharsha.Basavapatna@Sun.COM if (vnetp->rx_hwgh != NULL) { 264210309SSriharsha.Basavapatna@Sun.COM /* 264310309SSriharsha.Basavapatna@Sun.COM * Quiesce the HW ring and the mac srs on the ring. Note 264410309SSriharsha.Basavapatna@Sun.COM * that the HW ring will be restarted when the pseudo ring 264510309SSriharsha.Basavapatna@Sun.COM * is started. At that time all the packets will be 264610309SSriharsha.Basavapatna@Sun.COM * directly passed up to the pseudo RX ring and handled 264710309SSriharsha.Basavapatna@Sun.COM * by mac srs created over the pseudo RX ring. 264810309SSriharsha.Basavapatna@Sun.COM */ 264910309SSriharsha.Basavapatna@Sun.COM mac_rx_client_quiesce(vnetp->hio_mch); 265010309SSriharsha.Basavapatna@Sun.COM mac_srs_perm_quiesce(vnetp->hio_mch, B_TRUE); 265110309SSriharsha.Basavapatna@Sun.COM } 265210309SSriharsha.Basavapatna@Sun.COM 265310309SSriharsha.Basavapatna@Sun.COM /* 265410309SSriharsha.Basavapatna@Sun.COM * Bind the pseudo rings to the hwrings and start the hwrings. 265510309SSriharsha.Basavapatna@Sun.COM * Note we don't need to register these with the upper mac, as we have 265610309SSriharsha.Basavapatna@Sun.COM * statically exported these pseudo rxrings which are reserved for 265710309SSriharsha.Basavapatna@Sun.COM * rxrings of Hybrid resource. 265810309SSriharsha.Basavapatna@Sun.COM */ 265910309SSriharsha.Basavapatna@Sun.COM rx_grp = &vnetp->rx_grp[0]; 266010309SSriharsha.Basavapatna@Sun.COM for (i = 0; i < VNET_NUM_HYBRID_RINGS; i++) { 266110309SSriharsha.Basavapatna@Sun.COM /* Pick the rxrings reserved for Hybrid resource */ 266210309SSriharsha.Basavapatna@Sun.COM rx_ringp = &rx_grp->rings[i + VNET_HYBRID_RXRING_INDEX]; 266310309SSriharsha.Basavapatna@Sun.COM 266410309SSriharsha.Basavapatna@Sun.COM /* Store the hw ring handle */ 266510309SSriharsha.Basavapatna@Sun.COM rx_ringp->hw_rh = hw_rh[i]; 266610309SSriharsha.Basavapatna@Sun.COM 266710309SSriharsha.Basavapatna@Sun.COM /* Bind the pseudo ring to the underlying hwring */ 266810309SSriharsha.Basavapatna@Sun.COM mac_hwring_setup(rx_ringp->hw_rh, 266910309SSriharsha.Basavapatna@Sun.COM (mac_resource_handle_t)rx_ringp); 267010309SSriharsha.Basavapatna@Sun.COM 267110309SSriharsha.Basavapatna@Sun.COM /* Start the hwring if needed */ 267210309SSriharsha.Basavapatna@Sun.COM if (rx_ringp->state & VNET_RXRING_STARTED) { 267310309SSriharsha.Basavapatna@Sun.COM rv = mac_hwring_start(rx_ringp->hw_rh); 267410309SSriharsha.Basavapatna@Sun.COM if (rv != 0) { 267510309SSriharsha.Basavapatna@Sun.COM mac_hwring_teardown(rx_ringp->hw_rh); 267610309SSriharsha.Basavapatna@Sun.COM rx_ringp->hw_rh = NULL; 267710309SSriharsha.Basavapatna@Sun.COM goto fail; 267810309SSriharsha.Basavapatna@Sun.COM } 267910309SSriharsha.Basavapatna@Sun.COM } 268010309SSriharsha.Basavapatna@Sun.COM } 268110309SSriharsha.Basavapatna@Sun.COM 268210309SSriharsha.Basavapatna@Sun.COM /* Get the list of the underlying TX rings. */ 268310309SSriharsha.Basavapatna@Sun.COM hw_ring_cnt = mac_hwrings_get(vnetp->hio_mch, &vnetp->tx_hwgh, hw_rh, 268410309SSriharsha.Basavapatna@Sun.COM MAC_RING_TYPE_TX); 268510309SSriharsha.Basavapatna@Sun.COM 268610309SSriharsha.Basavapatna@Sun.COM /* We expect the # of hw tx rings to match VNET_NUM_HYBRID_RINGS */ 268710309SSriharsha.Basavapatna@Sun.COM if (hw_ring_cnt != VNET_NUM_HYBRID_RINGS) { 268810309SSriharsha.Basavapatna@Sun.COM cmn_err(CE_WARN, 268910309SSriharsha.Basavapatna@Sun.COM "!vnet%d: vnet_bind_hwrings: bad tx hw_ring_cnt(%d)\n", 269010309SSriharsha.Basavapatna@Sun.COM vnetp->instance, hw_ring_cnt); 269110309SSriharsha.Basavapatna@Sun.COM goto fail; 269210309SSriharsha.Basavapatna@Sun.COM } 269310309SSriharsha.Basavapatna@Sun.COM 269410309SSriharsha.Basavapatna@Sun.COM /* 269510309SSriharsha.Basavapatna@Sun.COM * Now map the pseudo txrings to the hw txrings. Note we don't need 269610309SSriharsha.Basavapatna@Sun.COM * to register these with the upper mac, as we have statically exported 269710309SSriharsha.Basavapatna@Sun.COM * these rings. Note that these rings will continue to be used for LDC 269810309SSriharsha.Basavapatna@Sun.COM * resources to peer vnets and vswitch (shared ring). 269910309SSriharsha.Basavapatna@Sun.COM */ 270010309SSriharsha.Basavapatna@Sun.COM tx_grp = &vnetp->tx_grp[0]; 270110309SSriharsha.Basavapatna@Sun.COM for (i = 0; i < tx_grp->ring_cnt; i++) { 270210309SSriharsha.Basavapatna@Sun.COM tx_ringp = &tx_grp->rings[i]; 270310309SSriharsha.Basavapatna@Sun.COM tx_ringp->hw_rh = hw_rh[i]; 270410309SSriharsha.Basavapatna@Sun.COM tx_ringp->state |= VNET_TXRING_HYBRID; 270510309SSriharsha.Basavapatna@Sun.COM } 270610309SSriharsha.Basavapatna@Sun.COM 270710309SSriharsha.Basavapatna@Sun.COM mac_perim_exit(mph1); 270810309SSriharsha.Basavapatna@Sun.COM return (0); 270910309SSriharsha.Basavapatna@Sun.COM 271010309SSriharsha.Basavapatna@Sun.COM fail: 271110309SSriharsha.Basavapatna@Sun.COM mac_perim_exit(mph1); 271210309SSriharsha.Basavapatna@Sun.COM vnet_unbind_hwrings(vnetp); 271310309SSriharsha.Basavapatna@Sun.COM return (1); 271410309SSriharsha.Basavapatna@Sun.COM } 271510309SSriharsha.Basavapatna@Sun.COM 271610309SSriharsha.Basavapatna@Sun.COM /* Unbind pseudo rings from hwrings */ 271710309SSriharsha.Basavapatna@Sun.COM static void 271810309SSriharsha.Basavapatna@Sun.COM vnet_unbind_hwrings(vnet_t *vnetp) 271910309SSriharsha.Basavapatna@Sun.COM { 272010309SSriharsha.Basavapatna@Sun.COM mac_perim_handle_t mph1; 272110309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_ring_t *rx_ringp; 272210309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_group_t *rx_grp; 272310309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_tx_group_t *tx_grp; 272410309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_tx_ring_t *tx_ringp; 272510309SSriharsha.Basavapatna@Sun.COM int i; 272610309SSriharsha.Basavapatna@Sun.COM 272710309SSriharsha.Basavapatna@Sun.COM mac_perim_enter_by_mh(vnetp->hio_mh, &mph1); 272810309SSriharsha.Basavapatna@Sun.COM 272910309SSriharsha.Basavapatna@Sun.COM tx_grp = &vnetp->tx_grp[0]; 273010309SSriharsha.Basavapatna@Sun.COM for (i = 0; i < VNET_NUM_HYBRID_RINGS; i++) { 273110309SSriharsha.Basavapatna@Sun.COM tx_ringp = &tx_grp->rings[i]; 273210309SSriharsha.Basavapatna@Sun.COM if (tx_ringp->state & VNET_TXRING_HYBRID) { 273310309SSriharsha.Basavapatna@Sun.COM tx_ringp->state &= ~VNET_TXRING_HYBRID; 273410309SSriharsha.Basavapatna@Sun.COM tx_ringp->hw_rh = NULL; 273510309SSriharsha.Basavapatna@Sun.COM } 273610309SSriharsha.Basavapatna@Sun.COM } 273710309SSriharsha.Basavapatna@Sun.COM 273810309SSriharsha.Basavapatna@Sun.COM rx_grp = &vnetp->rx_grp[0]; 273910309SSriharsha.Basavapatna@Sun.COM for (i = 0; i < VNET_NUM_HYBRID_RINGS; i++) { 274010309SSriharsha.Basavapatna@Sun.COM rx_ringp = &rx_grp->rings[i + VNET_HYBRID_RXRING_INDEX]; 274110309SSriharsha.Basavapatna@Sun.COM if (rx_ringp->hw_rh != NULL) { 274210309SSriharsha.Basavapatna@Sun.COM /* Stop the hwring */ 274310309SSriharsha.Basavapatna@Sun.COM mac_hwring_stop(rx_ringp->hw_rh); 274410309SSriharsha.Basavapatna@Sun.COM 274510309SSriharsha.Basavapatna@Sun.COM /* Teardown the hwring */ 274610309SSriharsha.Basavapatna@Sun.COM mac_hwring_teardown(rx_ringp->hw_rh); 274710309SSriharsha.Basavapatna@Sun.COM rx_ringp->hw_rh = NULL; 274810309SSriharsha.Basavapatna@Sun.COM } 274910309SSriharsha.Basavapatna@Sun.COM } 275010309SSriharsha.Basavapatna@Sun.COM 275110309SSriharsha.Basavapatna@Sun.COM if (vnetp->rx_hwgh != NULL) { 275210309SSriharsha.Basavapatna@Sun.COM vnetp->rx_hwgh = NULL; 275310309SSriharsha.Basavapatna@Sun.COM /* 275410309SSriharsha.Basavapatna@Sun.COM * First clear the permanent-quiesced flag of the RX srs then 275510309SSriharsha.Basavapatna@Sun.COM * restart the HW ring and the mac srs on the ring. 275610309SSriharsha.Basavapatna@Sun.COM */ 275710309SSriharsha.Basavapatna@Sun.COM mac_srs_perm_quiesce(vnetp->hio_mch, B_FALSE); 275810309SSriharsha.Basavapatna@Sun.COM mac_rx_client_restart(vnetp->hio_mch); 275910309SSriharsha.Basavapatna@Sun.COM } 276010309SSriharsha.Basavapatna@Sun.COM 276110309SSriharsha.Basavapatna@Sun.COM mac_perim_exit(mph1); 276210309SSriharsha.Basavapatna@Sun.COM } 276310309SSriharsha.Basavapatna@Sun.COM 276410309SSriharsha.Basavapatna@Sun.COM /* Bind pseudo ring to a LDC resource */ 276510309SSriharsha.Basavapatna@Sun.COM static int 276610309SSriharsha.Basavapatna@Sun.COM vnet_bind_vgenring(vnet_res_t *vresp) 276710309SSriharsha.Basavapatna@Sun.COM { 276810309SSriharsha.Basavapatna@Sun.COM vnet_t *vnetp; 276910309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_group_t *rx_grp; 277010309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_ring_t *rx_ringp; 277110309SSriharsha.Basavapatna@Sun.COM mac_perim_handle_t mph1; 277210309SSriharsha.Basavapatna@Sun.COM int rv; 277310309SSriharsha.Basavapatna@Sun.COM int type; 277410309SSriharsha.Basavapatna@Sun.COM 277510309SSriharsha.Basavapatna@Sun.COM vnetp = vresp->vnetp; 277610309SSriharsha.Basavapatna@Sun.COM type = vresp->type; 277710309SSriharsha.Basavapatna@Sun.COM rx_grp = &vnetp->rx_grp[0]; 277810309SSriharsha.Basavapatna@Sun.COM 277910309SSriharsha.Basavapatna@Sun.COM if (type == VIO_NET_RES_LDC_SERVICE) { 278010309SSriharsha.Basavapatna@Sun.COM /* 278110309SSriharsha.Basavapatna@Sun.COM * Ring Index 0 is the default ring in the group and is 278210309SSriharsha.Basavapatna@Sun.COM * reserved for LDC_SERVICE in vnet_ring_grp_init(). This ring 278310309SSriharsha.Basavapatna@Sun.COM * is allocated statically and is reported to the mac layer 278410309SSriharsha.Basavapatna@Sun.COM * in vnet_m_capab(). So, all we need to do here, is save a 278510309SSriharsha.Basavapatna@Sun.COM * reference to the associated vresp. 278610309SSriharsha.Basavapatna@Sun.COM */ 278710309SSriharsha.Basavapatna@Sun.COM rx_ringp = &rx_grp->rings[0]; 278810309SSriharsha.Basavapatna@Sun.COM rx_ringp->hw_rh = (mac_ring_handle_t)vresp; 278910309SSriharsha.Basavapatna@Sun.COM vresp->rx_ringp = (void *)rx_ringp; 279010309SSriharsha.Basavapatna@Sun.COM return (0); 279110309SSriharsha.Basavapatna@Sun.COM } 279210309SSriharsha.Basavapatna@Sun.COM ASSERT(type == VIO_NET_RES_LDC_GUEST); 279310309SSriharsha.Basavapatna@Sun.COM 279410309SSriharsha.Basavapatna@Sun.COM mac_perim_enter_by_mh(vnetp->mh, &mph1); 279510309SSriharsha.Basavapatna@Sun.COM 279610309SSriharsha.Basavapatna@Sun.COM rx_ringp = vnet_alloc_pseudo_rx_ring(vnetp); 279710309SSriharsha.Basavapatna@Sun.COM if (rx_ringp == NULL) { 279810309SSriharsha.Basavapatna@Sun.COM cmn_err(CE_WARN, "!vnet%d: Failed to allocate pseudo rx ring", 279910309SSriharsha.Basavapatna@Sun.COM vnetp->instance); 280010309SSriharsha.Basavapatna@Sun.COM goto fail; 280110309SSriharsha.Basavapatna@Sun.COM } 280210309SSriharsha.Basavapatna@Sun.COM 280310309SSriharsha.Basavapatna@Sun.COM /* Store the LDC resource itself as the ring handle */ 280410309SSriharsha.Basavapatna@Sun.COM rx_ringp->hw_rh = (mac_ring_handle_t)vresp; 280510309SSriharsha.Basavapatna@Sun.COM 280610309SSriharsha.Basavapatna@Sun.COM /* 280710309SSriharsha.Basavapatna@Sun.COM * Save a reference to the ring in the resource for lookup during 280810309SSriharsha.Basavapatna@Sun.COM * unbind. Note this is only done for LDC resources. We don't need this 280910309SSriharsha.Basavapatna@Sun.COM * in the case of a Hybrid resource (see vnet_bind_hwrings()), as its 281010309SSriharsha.Basavapatna@Sun.COM * rx rings are mapped to reserved pseudo rx rings (index 1 and 2). 281110309SSriharsha.Basavapatna@Sun.COM */ 281210309SSriharsha.Basavapatna@Sun.COM vresp->rx_ringp = (void *)rx_ringp; 281310309SSriharsha.Basavapatna@Sun.COM rx_ringp->state |= VNET_RXRING_LDC_GUEST; 281410309SSriharsha.Basavapatna@Sun.COM 281510309SSriharsha.Basavapatna@Sun.COM /* Register the pseudo ring with upper-mac */ 281610309SSriharsha.Basavapatna@Sun.COM rv = mac_group_add_ring(rx_grp->handle, rx_ringp->index); 281710309SSriharsha.Basavapatna@Sun.COM if (rv != 0) { 281810309SSriharsha.Basavapatna@Sun.COM rx_ringp->state &= ~VNET_RXRING_LDC_GUEST; 281910309SSriharsha.Basavapatna@Sun.COM rx_ringp->hw_rh = NULL; 282010309SSriharsha.Basavapatna@Sun.COM vnet_free_pseudo_rx_ring(vnetp, rx_ringp); 282110309SSriharsha.Basavapatna@Sun.COM goto fail; 282210309SSriharsha.Basavapatna@Sun.COM } 282310309SSriharsha.Basavapatna@Sun.COM 282410309SSriharsha.Basavapatna@Sun.COM mac_perim_exit(mph1); 282510309SSriharsha.Basavapatna@Sun.COM return (0); 282610309SSriharsha.Basavapatna@Sun.COM fail: 282710309SSriharsha.Basavapatna@Sun.COM mac_perim_exit(mph1); 282810309SSriharsha.Basavapatna@Sun.COM return (1); 282910309SSriharsha.Basavapatna@Sun.COM } 283010309SSriharsha.Basavapatna@Sun.COM 283110309SSriharsha.Basavapatna@Sun.COM /* Unbind pseudo ring from a LDC resource */ 283210309SSriharsha.Basavapatna@Sun.COM static void 283310309SSriharsha.Basavapatna@Sun.COM vnet_unbind_vgenring(vnet_res_t *vresp) 283410309SSriharsha.Basavapatna@Sun.COM { 283510309SSriharsha.Basavapatna@Sun.COM vnet_t *vnetp; 283610309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_group_t *rx_grp; 283710309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_ring_t *rx_ringp; 283810309SSriharsha.Basavapatna@Sun.COM mac_perim_handle_t mph1; 283910309SSriharsha.Basavapatna@Sun.COM int type; 284010309SSriharsha.Basavapatna@Sun.COM 284110309SSriharsha.Basavapatna@Sun.COM vnetp = vresp->vnetp; 284210309SSriharsha.Basavapatna@Sun.COM type = vresp->type; 284310309SSriharsha.Basavapatna@Sun.COM rx_grp = &vnetp->rx_grp[0]; 284410309SSriharsha.Basavapatna@Sun.COM 284510309SSriharsha.Basavapatna@Sun.COM if (vresp->rx_ringp == NULL) { 284610309SSriharsha.Basavapatna@Sun.COM return; 284710309SSriharsha.Basavapatna@Sun.COM } 284810309SSriharsha.Basavapatna@Sun.COM 284910309SSriharsha.Basavapatna@Sun.COM if (type == VIO_NET_RES_LDC_SERVICE) { 285010309SSriharsha.Basavapatna@Sun.COM /* 285110309SSriharsha.Basavapatna@Sun.COM * Ring Index 0 is the default ring in the group and is 285210309SSriharsha.Basavapatna@Sun.COM * reserved for LDC_SERVICE in vnet_ring_grp_init(). This ring 285310309SSriharsha.Basavapatna@Sun.COM * is allocated statically and is reported to the mac layer 285410309SSriharsha.Basavapatna@Sun.COM * in vnet_m_capab(). So, all we need to do here, is remove its 285510309SSriharsha.Basavapatna@Sun.COM * reference to the associated vresp. 285610309SSriharsha.Basavapatna@Sun.COM */ 285710309SSriharsha.Basavapatna@Sun.COM rx_ringp = &rx_grp->rings[0]; 285810309SSriharsha.Basavapatna@Sun.COM rx_ringp->hw_rh = NULL; 285910309SSriharsha.Basavapatna@Sun.COM vresp->rx_ringp = NULL; 286010309SSriharsha.Basavapatna@Sun.COM return; 286110309SSriharsha.Basavapatna@Sun.COM } 286210309SSriharsha.Basavapatna@Sun.COM ASSERT(type == VIO_NET_RES_LDC_GUEST); 286310309SSriharsha.Basavapatna@Sun.COM 286410309SSriharsha.Basavapatna@Sun.COM mac_perim_enter_by_mh(vnetp->mh, &mph1); 286510309SSriharsha.Basavapatna@Sun.COM 286610309SSriharsha.Basavapatna@Sun.COM rx_ringp = (vnet_pseudo_rx_ring_t *)vresp->rx_ringp; 286710309SSriharsha.Basavapatna@Sun.COM vresp->rx_ringp = NULL; 286810309SSriharsha.Basavapatna@Sun.COM 286910309SSriharsha.Basavapatna@Sun.COM if (rx_ringp != NULL && (rx_ringp->state & VNET_RXRING_LDC_GUEST)) { 287010309SSriharsha.Basavapatna@Sun.COM /* Unregister the pseudo ring with upper-mac */ 287110309SSriharsha.Basavapatna@Sun.COM mac_group_rem_ring(rx_grp->handle, rx_ringp->handle); 287210309SSriharsha.Basavapatna@Sun.COM 287310309SSriharsha.Basavapatna@Sun.COM rx_ringp->hw_rh = NULL; 287410309SSriharsha.Basavapatna@Sun.COM rx_ringp->state &= ~VNET_RXRING_LDC_GUEST; 287510309SSriharsha.Basavapatna@Sun.COM 287610309SSriharsha.Basavapatna@Sun.COM /* Free the pseudo rx ring */ 287710309SSriharsha.Basavapatna@Sun.COM vnet_free_pseudo_rx_ring(vnetp, rx_ringp); 287810309SSriharsha.Basavapatna@Sun.COM } 287910309SSriharsha.Basavapatna@Sun.COM 288010309SSriharsha.Basavapatna@Sun.COM mac_perim_exit(mph1); 288110309SSriharsha.Basavapatna@Sun.COM } 288210309SSriharsha.Basavapatna@Sun.COM 288310309SSriharsha.Basavapatna@Sun.COM static void 288410309SSriharsha.Basavapatna@Sun.COM vnet_unbind_rings(vnet_res_t *vresp) 288510309SSriharsha.Basavapatna@Sun.COM { 288610309SSriharsha.Basavapatna@Sun.COM switch (vresp->type) { 288710309SSriharsha.Basavapatna@Sun.COM 288810309SSriharsha.Basavapatna@Sun.COM case VIO_NET_RES_LDC_SERVICE: 288910309SSriharsha.Basavapatna@Sun.COM case VIO_NET_RES_LDC_GUEST: 289010309SSriharsha.Basavapatna@Sun.COM vnet_unbind_vgenring(vresp); 289110309SSriharsha.Basavapatna@Sun.COM break; 289210309SSriharsha.Basavapatna@Sun.COM 289310309SSriharsha.Basavapatna@Sun.COM case VIO_NET_RES_HYBRID: 289410309SSriharsha.Basavapatna@Sun.COM vnet_unbind_hwrings(vresp->vnetp); 289510309SSriharsha.Basavapatna@Sun.COM break; 289610309SSriharsha.Basavapatna@Sun.COM 289710309SSriharsha.Basavapatna@Sun.COM default: 289810309SSriharsha.Basavapatna@Sun.COM break; 289910309SSriharsha.Basavapatna@Sun.COM 290010309SSriharsha.Basavapatna@Sun.COM } 290110309SSriharsha.Basavapatna@Sun.COM } 290210309SSriharsha.Basavapatna@Sun.COM 290310309SSriharsha.Basavapatna@Sun.COM static int 290410309SSriharsha.Basavapatna@Sun.COM vnet_bind_rings(vnet_res_t *vresp) 290510309SSriharsha.Basavapatna@Sun.COM { 290610309SSriharsha.Basavapatna@Sun.COM int rv; 290710309SSriharsha.Basavapatna@Sun.COM 290810309SSriharsha.Basavapatna@Sun.COM switch (vresp->type) { 290910309SSriharsha.Basavapatna@Sun.COM 291010309SSriharsha.Basavapatna@Sun.COM case VIO_NET_RES_LDC_SERVICE: 291110309SSriharsha.Basavapatna@Sun.COM case VIO_NET_RES_LDC_GUEST: 291210309SSriharsha.Basavapatna@Sun.COM rv = vnet_bind_vgenring(vresp); 291310309SSriharsha.Basavapatna@Sun.COM break; 291410309SSriharsha.Basavapatna@Sun.COM 291510309SSriharsha.Basavapatna@Sun.COM case VIO_NET_RES_HYBRID: 291610309SSriharsha.Basavapatna@Sun.COM rv = vnet_bind_hwrings(vresp->vnetp); 291710309SSriharsha.Basavapatna@Sun.COM break; 291810309SSriharsha.Basavapatna@Sun.COM 291910309SSriharsha.Basavapatna@Sun.COM default: 292010309SSriharsha.Basavapatna@Sun.COM rv = 1; 292110309SSriharsha.Basavapatna@Sun.COM break; 292210309SSriharsha.Basavapatna@Sun.COM 292310309SSriharsha.Basavapatna@Sun.COM } 292410309SSriharsha.Basavapatna@Sun.COM 292510309SSriharsha.Basavapatna@Sun.COM return (rv); 292610309SSriharsha.Basavapatna@Sun.COM } 292710309SSriharsha.Basavapatna@Sun.COM 292810309SSriharsha.Basavapatna@Sun.COM /* ARGSUSED */ 292910309SSriharsha.Basavapatna@Sun.COM int 293010309SSriharsha.Basavapatna@Sun.COM vnet_hio_stat(void *arg, uint_t stat, uint64_t *val) 293110309SSriharsha.Basavapatna@Sun.COM { 293210309SSriharsha.Basavapatna@Sun.COM vnet_t *vnetp = (vnet_t *)arg; 293310309SSriharsha.Basavapatna@Sun.COM 293410309SSriharsha.Basavapatna@Sun.COM *val = mac_stat_get(vnetp->hio_mh, stat); 293510309SSriharsha.Basavapatna@Sun.COM return (0); 293610309SSriharsha.Basavapatna@Sun.COM } 293710309SSriharsha.Basavapatna@Sun.COM 293810309SSriharsha.Basavapatna@Sun.COM /* 293910309SSriharsha.Basavapatna@Sun.COM * The start() and stop() routines for the Hybrid resource below, are just 294010309SSriharsha.Basavapatna@Sun.COM * dummy functions. This is provided to avoid resource type specific code in 294110309SSriharsha.Basavapatna@Sun.COM * vnet_start_resources() and vnet_stop_resources(). The starting and stopping 294210309SSriharsha.Basavapatna@Sun.COM * of the Hybrid resource happens in the context of the mac_client interfaces 294310309SSriharsha.Basavapatna@Sun.COM * that are invoked in vnet_hio_mac_init() and vnet_hio_mac_cleanup(). 294410309SSriharsha.Basavapatna@Sun.COM */ 294510309SSriharsha.Basavapatna@Sun.COM /* ARGSUSED */ 294610309SSriharsha.Basavapatna@Sun.COM static int 294710309SSriharsha.Basavapatna@Sun.COM vnet_hio_start(void *arg) 294810309SSriharsha.Basavapatna@Sun.COM { 294910309SSriharsha.Basavapatna@Sun.COM return (0); 295010309SSriharsha.Basavapatna@Sun.COM } 295110309SSriharsha.Basavapatna@Sun.COM 295210309SSriharsha.Basavapatna@Sun.COM /* ARGSUSED */ 295310309SSriharsha.Basavapatna@Sun.COM static void 295410309SSriharsha.Basavapatna@Sun.COM vnet_hio_stop(void *arg) 295510309SSriharsha.Basavapatna@Sun.COM { 295610309SSriharsha.Basavapatna@Sun.COM } 295710309SSriharsha.Basavapatna@Sun.COM 295810309SSriharsha.Basavapatna@Sun.COM mblk_t * 295910309SSriharsha.Basavapatna@Sun.COM vnet_hio_tx(void *arg, mblk_t *mp) 296010309SSriharsha.Basavapatna@Sun.COM { 296110309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_tx_ring_t *tx_ringp; 296210309SSriharsha.Basavapatna@Sun.COM mblk_t *nextp; 296310309SSriharsha.Basavapatna@Sun.COM mblk_t *ret_mp; 296410309SSriharsha.Basavapatna@Sun.COM 296510309SSriharsha.Basavapatna@Sun.COM tx_ringp = (vnet_pseudo_tx_ring_t *)arg; 296610309SSriharsha.Basavapatna@Sun.COM for (;;) { 296710309SSriharsha.Basavapatna@Sun.COM nextp = mp->b_next; 296810309SSriharsha.Basavapatna@Sun.COM mp->b_next = NULL; 296910309SSriharsha.Basavapatna@Sun.COM 297010309SSriharsha.Basavapatna@Sun.COM ret_mp = mac_hwring_tx(tx_ringp->hw_rh, mp); 297110309SSriharsha.Basavapatna@Sun.COM if (ret_mp != NULL) { 297210309SSriharsha.Basavapatna@Sun.COM ret_mp->b_next = nextp; 297310309SSriharsha.Basavapatna@Sun.COM mp = ret_mp; 297410309SSriharsha.Basavapatna@Sun.COM break; 297510309SSriharsha.Basavapatna@Sun.COM } 297610309SSriharsha.Basavapatna@Sun.COM 297710309SSriharsha.Basavapatna@Sun.COM if ((mp = nextp) == NULL) 297810309SSriharsha.Basavapatna@Sun.COM break; 297910309SSriharsha.Basavapatna@Sun.COM } 298010309SSriharsha.Basavapatna@Sun.COM return (mp); 298110309SSriharsha.Basavapatna@Sun.COM } 298210309SSriharsha.Basavapatna@Sun.COM 298310309SSriharsha.Basavapatna@Sun.COM static void 298410309SSriharsha.Basavapatna@Sun.COM vnet_hio_notify_cb(void *arg, mac_notify_type_t type) 298510309SSriharsha.Basavapatna@Sun.COM { 298610309SSriharsha.Basavapatna@Sun.COM vnet_t *vnetp = (vnet_t *)arg; 298710309SSriharsha.Basavapatna@Sun.COM mac_perim_handle_t mph; 298810309SSriharsha.Basavapatna@Sun.COM 298910309SSriharsha.Basavapatna@Sun.COM mac_perim_enter_by_mh(vnetp->hio_mh, &mph); 299010309SSriharsha.Basavapatna@Sun.COM switch (type) { 299110309SSriharsha.Basavapatna@Sun.COM case MAC_NOTE_TX: 299210309SSriharsha.Basavapatna@Sun.COM vnet_tx_update(vnetp->hio_vhp); 299310309SSriharsha.Basavapatna@Sun.COM break; 299410309SSriharsha.Basavapatna@Sun.COM 299510309SSriharsha.Basavapatna@Sun.COM default: 299610309SSriharsha.Basavapatna@Sun.COM break; 299710309SSriharsha.Basavapatna@Sun.COM } 299810309SSriharsha.Basavapatna@Sun.COM mac_perim_exit(mph); 299910309SSriharsha.Basavapatna@Sun.COM } 300010309SSriharsha.Basavapatna@Sun.COM 30019336SSriharsha.Basavapatna@Sun.COM #ifdef VNET_IOC_DEBUG 30029336SSriharsha.Basavapatna@Sun.COM 30039336SSriharsha.Basavapatna@Sun.COM /* 30049336SSriharsha.Basavapatna@Sun.COM * The ioctl entry point is used only for debugging for now. The ioctl commands 30059336SSriharsha.Basavapatna@Sun.COM * can be used to force the link state of the channel connected to vsw. 30069336SSriharsha.Basavapatna@Sun.COM */ 30079336SSriharsha.Basavapatna@Sun.COM static void 30089336SSriharsha.Basavapatna@Sun.COM vnet_m_ioctl(void *arg, queue_t *q, mblk_t *mp) 30099336SSriharsha.Basavapatna@Sun.COM { 30109336SSriharsha.Basavapatna@Sun.COM struct iocblk *iocp; 30119336SSriharsha.Basavapatna@Sun.COM vnet_t *vnetp; 30129336SSriharsha.Basavapatna@Sun.COM 30139336SSriharsha.Basavapatna@Sun.COM iocp = (struct iocblk *)(uintptr_t)mp->b_rptr; 30149336SSriharsha.Basavapatna@Sun.COM iocp->ioc_error = 0; 30159336SSriharsha.Basavapatna@Sun.COM vnetp = (vnet_t *)arg; 30169336SSriharsha.Basavapatna@Sun.COM 30179336SSriharsha.Basavapatna@Sun.COM if (vnetp == NULL) { 30189336SSriharsha.Basavapatna@Sun.COM miocnak(q, mp, 0, EINVAL); 30199336SSriharsha.Basavapatna@Sun.COM return; 30209336SSriharsha.Basavapatna@Sun.COM } 30219336SSriharsha.Basavapatna@Sun.COM 30229336SSriharsha.Basavapatna@Sun.COM switch (iocp->ioc_cmd) { 30239336SSriharsha.Basavapatna@Sun.COM 30249336SSriharsha.Basavapatna@Sun.COM case VNET_FORCE_LINK_DOWN: 30259336SSriharsha.Basavapatna@Sun.COM case VNET_FORCE_LINK_UP: 30269336SSriharsha.Basavapatna@Sun.COM vnet_force_link_state(vnetp, q, mp); 30279336SSriharsha.Basavapatna@Sun.COM break; 30289336SSriharsha.Basavapatna@Sun.COM 30299336SSriharsha.Basavapatna@Sun.COM default: 30309336SSriharsha.Basavapatna@Sun.COM iocp->ioc_error = EINVAL; 30319336SSriharsha.Basavapatna@Sun.COM miocnak(q, mp, 0, iocp->ioc_error); 30329336SSriharsha.Basavapatna@Sun.COM break; 30339336SSriharsha.Basavapatna@Sun.COM 30349336SSriharsha.Basavapatna@Sun.COM } 30359336SSriharsha.Basavapatna@Sun.COM } 30369336SSriharsha.Basavapatna@Sun.COM 30379336SSriharsha.Basavapatna@Sun.COM static void 30389336SSriharsha.Basavapatna@Sun.COM vnet_force_link_state(vnet_t *vnetp, queue_t *q, mblk_t *mp) 30399336SSriharsha.Basavapatna@Sun.COM { 30409336SSriharsha.Basavapatna@Sun.COM mac_register_t *macp; 30419336SSriharsha.Basavapatna@Sun.COM mac_callbacks_t *cbp; 30429336SSriharsha.Basavapatna@Sun.COM vnet_res_t *vresp; 30439336SSriharsha.Basavapatna@Sun.COM 30449336SSriharsha.Basavapatna@Sun.COM READ_ENTER(&vnetp->vsw_fp_rw); 30459336SSriharsha.Basavapatna@Sun.COM 30469336SSriharsha.Basavapatna@Sun.COM vresp = vnetp->vsw_fp; 30479336SSriharsha.Basavapatna@Sun.COM if (vresp == NULL) { 30489336SSriharsha.Basavapatna@Sun.COM RW_EXIT(&vnetp->vsw_fp_rw); 30499336SSriharsha.Basavapatna@Sun.COM return; 30509336SSriharsha.Basavapatna@Sun.COM } 30519336SSriharsha.Basavapatna@Sun.COM 30529336SSriharsha.Basavapatna@Sun.COM macp = &vresp->macreg; 30539336SSriharsha.Basavapatna@Sun.COM cbp = macp->m_callbacks; 30549336SSriharsha.Basavapatna@Sun.COM cbp->mc_ioctl(macp->m_driver, q, mp); 30559336SSriharsha.Basavapatna@Sun.COM 30569336SSriharsha.Basavapatna@Sun.COM RW_EXIT(&vnetp->vsw_fp_rw); 30579336SSriharsha.Basavapatna@Sun.COM } 30589336SSriharsha.Basavapatna@Sun.COM 30599336SSriharsha.Basavapatna@Sun.COM #else 30609336SSriharsha.Basavapatna@Sun.COM 30619336SSriharsha.Basavapatna@Sun.COM static void 30629336SSriharsha.Basavapatna@Sun.COM vnet_m_ioctl(void *arg, queue_t *q, mblk_t *mp) 30639336SSriharsha.Basavapatna@Sun.COM { 30649336SSriharsha.Basavapatna@Sun.COM vnet_t *vnetp; 30659336SSriharsha.Basavapatna@Sun.COM 30669336SSriharsha.Basavapatna@Sun.COM vnetp = (vnet_t *)arg; 30679336SSriharsha.Basavapatna@Sun.COM 30689336SSriharsha.Basavapatna@Sun.COM if (vnetp == NULL) { 30699336SSriharsha.Basavapatna@Sun.COM miocnak(q, mp, 0, EINVAL); 30709336SSriharsha.Basavapatna@Sun.COM return; 30719336SSriharsha.Basavapatna@Sun.COM } 30729336SSriharsha.Basavapatna@Sun.COM 30739336SSriharsha.Basavapatna@Sun.COM /* ioctl support only for debugging */ 30749336SSriharsha.Basavapatna@Sun.COM miocnak(q, mp, 0, ENOTSUP); 30759336SSriharsha.Basavapatna@Sun.COM } 30769336SSriharsha.Basavapatna@Sun.COM 30779336SSriharsha.Basavapatna@Sun.COM #endif 3078