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 /* 239217SWentao.Yang@Sun.COM * Copyright 2009 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 7371991Sheppo vnet_t *vnetp = arg; 7386495Sspeer vnet_res_t *vresp; 7396495Sspeer mac_register_t *macp; 7402311Sseb mac_callbacks_t *cbp; 7411991Sheppo int rv = VNET_SUCCESS; 7421991Sheppo 7434647Sraghuram DBG1(vnetp, "enter\n"); 7446495Sspeer 7456495Sspeer READ_ENTER(&vnetp->vrwlock); 7466495Sspeer for (vresp = vnetp->vres_list; vresp != NULL; vresp = vresp->nextp) { 7476495Sspeer if (vresp->type == VIO_NET_RES_LDC_SERVICE) { 7486495Sspeer macp = &vresp->macreg; 7496495Sspeer cbp = macp->m_callbacks; 7506495Sspeer rv = cbp->mc_multicst(macp->m_driver, add, mca); 7511991Sheppo } 7521991Sheppo } 7536495Sspeer RW_EXIT(&vnetp->vrwlock); 7546495Sspeer 7554647Sraghuram DBG1(vnetp, "exit(%d)\n", rv); 7561991Sheppo return (rv); 7571991Sheppo } 7581991Sheppo 7591991Sheppo /* set or clear promiscuous mode on the device */ 7601991Sheppo static int 7611991Sheppo vnet_m_promisc(void *arg, boolean_t on) 7621991Sheppo { 7631991Sheppo _NOTE(ARGUNUSED(on)) 7641991Sheppo 7651991Sheppo vnet_t *vnetp = arg; 7664647Sraghuram DBG1(vnetp, "enter\n"); 7671991Sheppo /* 7682793Slm66018 * NOTE: setting promiscuous mode is not supported, just return success. 7691991Sheppo */ 7704647Sraghuram DBG1(vnetp, "exit\n"); 7711991Sheppo return (VNET_SUCCESS); 7721991Sheppo } 7731991Sheppo 7741991Sheppo /* 7751991Sheppo * Transmit a chain of packets. This function provides switching functionality 7761991Sheppo * based on the destination mac address to reach other guests (within ldoms) or 7771991Sheppo * external hosts. 7781991Sheppo */ 7791991Sheppo mblk_t * 78010309SSriharsha.Basavapatna@Sun.COM vnet_tx_ring_send(void *arg, mblk_t *mp) 7811991Sheppo { 78210309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_tx_ring_t *tx_ringp; 7836419Ssb155480 vnet_t *vnetp; 7846495Sspeer vnet_res_t *vresp; 7856419Ssb155480 mblk_t *next; 7866495Sspeer mblk_t *resid_mp; 7876495Sspeer mac_register_t *macp; 7886495Sspeer struct ether_header *ehp; 7896495Sspeer boolean_t is_unicast; 7907896SSriharsha.Basavapatna@Sun.COM boolean_t is_pvid; /* non-default pvid ? */ 7917896SSriharsha.Basavapatna@Sun.COM boolean_t hres; /* Hybrid resource ? */ 79210309SSriharsha.Basavapatna@Sun.COM void *tx_arg; 79310309SSriharsha.Basavapatna@Sun.COM 79410309SSriharsha.Basavapatna@Sun.COM tx_ringp = (vnet_pseudo_tx_ring_t *)arg; 79510309SSriharsha.Basavapatna@Sun.COM vnetp = (vnet_t *)tx_ringp->vnetp; 7964647Sraghuram DBG1(vnetp, "enter\n"); 7971991Sheppo ASSERT(mp != NULL); 7981991Sheppo 7997896SSriharsha.Basavapatna@Sun.COM is_pvid = (vnetp->pvid != vnetp->default_vlan_id) ? B_TRUE : B_FALSE; 8007896SSriharsha.Basavapatna@Sun.COM 8011991Sheppo while (mp != NULL) { 8026419Ssb155480 8031991Sheppo next = mp->b_next; 8041991Sheppo mp->b_next = NULL; 8051991Sheppo 8066419Ssb155480 /* 8076419Ssb155480 * Find fdb entry for the destination 8086419Ssb155480 * and hold a reference to it. 8096419Ssb155480 */ 8101991Sheppo ehp = (struct ether_header *)mp->b_rptr; 8116495Sspeer vresp = vnet_fdbe_find(vnetp, &ehp->ether_dhost); 8126495Sspeer if (vresp != NULL) { 8131991Sheppo 8141991Sheppo /* 8156419Ssb155480 * Destination found in FDB. 8166419Ssb155480 * The destination is a vnet device within ldoms 8176419Ssb155480 * and directly reachable, invoke the tx function 8186419Ssb155480 * in the fdb entry. 8191991Sheppo */ 8206495Sspeer macp = &vresp->macreg; 8216495Sspeer resid_mp = macp->m_callbacks->mc_tx(macp->m_driver, mp); 8226419Ssb155480 8236419Ssb155480 /* tx done; now release ref on fdb entry */ 8246495Sspeer VNET_FDBE_REFRELE(vresp); 8256419Ssb155480 8261991Sheppo if (resid_mp != NULL) { 8271991Sheppo /* m_tx failed */ 8281991Sheppo mp->b_next = next; 8291991Sheppo break; 8301991Sheppo } 8311991Sheppo } else { 8326495Sspeer is_unicast = !(IS_BROADCAST(ehp) || 8336495Sspeer (IS_MULTICAST(ehp))); 8341991Sheppo /* 8356419Ssb155480 * Destination is not in FDB. 8366495Sspeer * If the destination is broadcast or multicast, 8376495Sspeer * then forward the packet to vswitch. 8386495Sspeer * If a Hybrid resource avilable, then send the 8396495Sspeer * unicast packet via hybrid resource, otherwise 8406495Sspeer * forward it to vswitch. 8411991Sheppo */ 8426419Ssb155480 READ_ENTER(&vnetp->vsw_fp_rw); 8436419Ssb155480 8446495Sspeer if ((is_unicast) && (vnetp->hio_fp != NULL)) { 8456495Sspeer vresp = vnetp->hio_fp; 8467896SSriharsha.Basavapatna@Sun.COM hres = B_TRUE; 8476495Sspeer } else { 8486495Sspeer vresp = vnetp->vsw_fp; 8497896SSriharsha.Basavapatna@Sun.COM hres = B_FALSE; 8506495Sspeer } 8516495Sspeer if (vresp == NULL) { 8526419Ssb155480 /* 8536419Ssb155480 * no fdb entry to vsw? drop the packet. 8546419Ssb155480 */ 8556419Ssb155480 RW_EXIT(&vnetp->vsw_fp_rw); 8561991Sheppo freemsg(mp); 8576419Ssb155480 mp = next; 8586419Ssb155480 continue; 8591991Sheppo } 8606419Ssb155480 8616419Ssb155480 /* ref hold the fdb entry to vsw */ 8626495Sspeer VNET_FDBE_REFHOLD(vresp); 8636419Ssb155480 8646419Ssb155480 RW_EXIT(&vnetp->vsw_fp_rw); 8656419Ssb155480 8667896SSriharsha.Basavapatna@Sun.COM /* 8677896SSriharsha.Basavapatna@Sun.COM * In the case of a hybrid resource we need to insert 8687896SSriharsha.Basavapatna@Sun.COM * the tag for the pvid case here; unlike packets that 8697896SSriharsha.Basavapatna@Sun.COM * are destined to a vnet/vsw in which case the vgen 8707896SSriharsha.Basavapatna@Sun.COM * layer does the tagging before sending it over ldc. 8717896SSriharsha.Basavapatna@Sun.COM */ 8727896SSriharsha.Basavapatna@Sun.COM if (hres == B_TRUE) { 8737896SSriharsha.Basavapatna@Sun.COM /* 8747896SSriharsha.Basavapatna@Sun.COM * Determine if the frame being transmitted 8757896SSriharsha.Basavapatna@Sun.COM * over the hybrid resource is untagged. If so, 8767896SSriharsha.Basavapatna@Sun.COM * insert the tag before transmitting. 8777896SSriharsha.Basavapatna@Sun.COM */ 8787896SSriharsha.Basavapatna@Sun.COM if (is_pvid == B_TRUE && 8797896SSriharsha.Basavapatna@Sun.COM ehp->ether_type != htons(ETHERTYPE_VLAN)) { 8807896SSriharsha.Basavapatna@Sun.COM 8817896SSriharsha.Basavapatna@Sun.COM mp = vnet_vlan_insert_tag(mp, 8827896SSriharsha.Basavapatna@Sun.COM vnetp->pvid); 8837896SSriharsha.Basavapatna@Sun.COM if (mp == NULL) { 8847896SSriharsha.Basavapatna@Sun.COM VNET_FDBE_REFRELE(vresp); 8857896SSriharsha.Basavapatna@Sun.COM mp = next; 8867896SSriharsha.Basavapatna@Sun.COM continue; 8877896SSriharsha.Basavapatna@Sun.COM } 8887896SSriharsha.Basavapatna@Sun.COM 8897896SSriharsha.Basavapatna@Sun.COM } 89010309SSriharsha.Basavapatna@Sun.COM 89110309SSriharsha.Basavapatna@Sun.COM macp = &vresp->macreg; 89210309SSriharsha.Basavapatna@Sun.COM tx_arg = tx_ringp; 89310309SSriharsha.Basavapatna@Sun.COM } else { 89410309SSriharsha.Basavapatna@Sun.COM macp = &vresp->macreg; 89510309SSriharsha.Basavapatna@Sun.COM tx_arg = macp->m_driver; 8967896SSriharsha.Basavapatna@Sun.COM } 89710309SSriharsha.Basavapatna@Sun.COM resid_mp = macp->m_callbacks->mc_tx(tx_arg, mp); 8986419Ssb155480 8996419Ssb155480 /* tx done; now release ref on fdb entry */ 9006495Sspeer VNET_FDBE_REFRELE(vresp); 9016419Ssb155480 9026419Ssb155480 if (resid_mp != NULL) { 9036419Ssb155480 /* m_tx failed */ 9046419Ssb155480 mp->b_next = next; 9056419Ssb155480 break; 9066419Ssb155480 } 9071991Sheppo } 9081991Sheppo 9091991Sheppo mp = next; 9101991Sheppo } 9111991Sheppo 9124647Sraghuram DBG1(vnetp, "exit\n"); 9131991Sheppo return (mp); 9141991Sheppo } 9151991Sheppo 9162311Sseb /* get statistics from the device */ 9172311Sseb int 9182311Sseb vnet_m_stat(void *arg, uint_t stat, uint64_t *val) 9191991Sheppo { 9201991Sheppo vnet_t *vnetp = arg; 9216495Sspeer vnet_res_t *vresp; 9226495Sspeer mac_register_t *macp; 9232311Sseb mac_callbacks_t *cbp; 9242311Sseb uint64_t val_total = 0; 9251991Sheppo 9264647Sraghuram DBG1(vnetp, "enter\n"); 9271991Sheppo 9281991Sheppo /* 9292311Sseb * get the specified statistic from each transport and return the 9302311Sseb * aggregate val. This obviously only works for counters. 9311991Sheppo */ 9322311Sseb if ((IS_MAC_STAT(stat) && !MAC_STAT_ISACOUNTER(stat)) || 9332311Sseb (IS_MACTYPE_STAT(stat) && !ETHER_STAT_ISACOUNTER(stat))) { 9342311Sseb return (ENOTSUP); 9352311Sseb } 9366495Sspeer 9376495Sspeer READ_ENTER(&vnetp->vrwlock); 9386495Sspeer for (vresp = vnetp->vres_list; vresp != NULL; vresp = vresp->nextp) { 9396495Sspeer macp = &vresp->macreg; 9406495Sspeer cbp = macp->m_callbacks; 9416495Sspeer if (cbp->mc_getstat(macp->m_driver, stat, val) == 0) 9422311Sseb val_total += *val; 9431991Sheppo } 9446495Sspeer RW_EXIT(&vnetp->vrwlock); 9451991Sheppo 9462311Sseb *val = val_total; 9472311Sseb 9484647Sraghuram DBG1(vnetp, "exit\n"); 9492311Sseb return (0); 9501991Sheppo } 9511991Sheppo 95210309SSriharsha.Basavapatna@Sun.COM static void 95310309SSriharsha.Basavapatna@Sun.COM vnet_ring_grp_init(vnet_t *vnetp) 95410309SSriharsha.Basavapatna@Sun.COM { 95510309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_group_t *rx_grp; 95610309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_ring_t *rx_ringp; 95710309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_tx_group_t *tx_grp; 95810309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_tx_ring_t *tx_ringp; 95910309SSriharsha.Basavapatna@Sun.COM int i; 96010309SSriharsha.Basavapatna@Sun.COM 96110309SSriharsha.Basavapatna@Sun.COM tx_grp = &vnetp->tx_grp[0]; 96210309SSriharsha.Basavapatna@Sun.COM tx_ringp = kmem_zalloc(sizeof (vnet_pseudo_tx_ring_t) * 96310309SSriharsha.Basavapatna@Sun.COM VNET_NUM_PSEUDO_TXRINGS, KM_SLEEP); 96410309SSriharsha.Basavapatna@Sun.COM for (i = 0; i < VNET_NUM_PSEUDO_TXRINGS; i++) { 96510309SSriharsha.Basavapatna@Sun.COM tx_ringp[i].state |= VNET_TXRING_SHARED; 96610309SSriharsha.Basavapatna@Sun.COM } 96710309SSriharsha.Basavapatna@Sun.COM tx_grp->rings = tx_ringp; 96810309SSriharsha.Basavapatna@Sun.COM tx_grp->ring_cnt = VNET_NUM_PSEUDO_TXRINGS; 96910309SSriharsha.Basavapatna@Sun.COM 97010309SSriharsha.Basavapatna@Sun.COM rx_grp = &vnetp->rx_grp[0]; 97110309SSriharsha.Basavapatna@Sun.COM rx_grp->max_ring_cnt = MAX_RINGS_PER_GROUP; 97210309SSriharsha.Basavapatna@Sun.COM rw_init(&rx_grp->lock, NULL, RW_DRIVER, NULL); 97310309SSriharsha.Basavapatna@Sun.COM rx_ringp = kmem_zalloc(sizeof (vnet_pseudo_rx_ring_t) * 97410309SSriharsha.Basavapatna@Sun.COM rx_grp->max_ring_cnt, KM_SLEEP); 97510309SSriharsha.Basavapatna@Sun.COM 97610309SSriharsha.Basavapatna@Sun.COM /* 97710309SSriharsha.Basavapatna@Sun.COM * Setup the first 3 Pseudo RX Rings that are reserved; 97810309SSriharsha.Basavapatna@Sun.COM * 1 for LDC resource to vswitch + 2 for RX rings of Hybrid resource. 97910309SSriharsha.Basavapatna@Sun.COM */ 98010309SSriharsha.Basavapatna@Sun.COM rx_ringp[0].state |= VNET_RXRING_INUSE|VNET_RXRING_LDC_SERVICE; 98110309SSriharsha.Basavapatna@Sun.COM rx_ringp[0].index = 0; 98210309SSriharsha.Basavapatna@Sun.COM rx_ringp[1].state |= VNET_RXRING_INUSE|VNET_RXRING_HYBRID; 98310309SSriharsha.Basavapatna@Sun.COM rx_ringp[1].index = 1; 98410309SSriharsha.Basavapatna@Sun.COM rx_ringp[2].state |= VNET_RXRING_INUSE|VNET_RXRING_HYBRID; 98510309SSriharsha.Basavapatna@Sun.COM rx_ringp[2].index = 2; 98610309SSriharsha.Basavapatna@Sun.COM 98710309SSriharsha.Basavapatna@Sun.COM rx_grp->ring_cnt = VNET_NUM_PSEUDO_RXRINGS_DEFAULT; 98810309SSriharsha.Basavapatna@Sun.COM rx_grp->rings = rx_ringp; 98910309SSriharsha.Basavapatna@Sun.COM 99010309SSriharsha.Basavapatna@Sun.COM for (i = VNET_NUM_PSEUDO_RXRINGS_DEFAULT; 99110309SSriharsha.Basavapatna@Sun.COM i < rx_grp->max_ring_cnt; i++) { 99210309SSriharsha.Basavapatna@Sun.COM rx_ringp = &rx_grp->rings[i]; 99310309SSriharsha.Basavapatna@Sun.COM rx_ringp->state = VNET_RXRING_FREE; 99410309SSriharsha.Basavapatna@Sun.COM rx_ringp->index = i; 99510309SSriharsha.Basavapatna@Sun.COM } 99610309SSriharsha.Basavapatna@Sun.COM } 99710309SSriharsha.Basavapatna@Sun.COM 99810309SSriharsha.Basavapatna@Sun.COM static void 99910309SSriharsha.Basavapatna@Sun.COM vnet_ring_grp_uninit(vnet_t *vnetp) 100010309SSriharsha.Basavapatna@Sun.COM { 100110309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_group_t *rx_grp; 100210309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_tx_group_t *tx_grp; 100310309SSriharsha.Basavapatna@Sun.COM 100410309SSriharsha.Basavapatna@Sun.COM tx_grp = &vnetp->tx_grp[0]; 100510309SSriharsha.Basavapatna@Sun.COM if (tx_grp->rings != NULL) { 100610309SSriharsha.Basavapatna@Sun.COM ASSERT(tx_grp->ring_cnt == VNET_NUM_PSEUDO_TXRINGS); 100710309SSriharsha.Basavapatna@Sun.COM kmem_free(tx_grp->rings, sizeof (vnet_pseudo_tx_ring_t) * 100810309SSriharsha.Basavapatna@Sun.COM tx_grp->ring_cnt); 100910309SSriharsha.Basavapatna@Sun.COM tx_grp->rings = NULL; 101010309SSriharsha.Basavapatna@Sun.COM } 101110309SSriharsha.Basavapatna@Sun.COM 101210309SSriharsha.Basavapatna@Sun.COM rx_grp = &vnetp->rx_grp[0]; 101310309SSriharsha.Basavapatna@Sun.COM if (rx_grp->rings != NULL) { 101410309SSriharsha.Basavapatna@Sun.COM ASSERT(rx_grp->max_ring_cnt == MAX_RINGS_PER_GROUP); 101510309SSriharsha.Basavapatna@Sun.COM ASSERT(rx_grp->ring_cnt == VNET_NUM_PSEUDO_RXRINGS_DEFAULT); 101610309SSriharsha.Basavapatna@Sun.COM kmem_free(rx_grp->rings, sizeof (vnet_pseudo_rx_ring_t) * 101710309SSriharsha.Basavapatna@Sun.COM rx_grp->max_ring_cnt); 101810309SSriharsha.Basavapatna@Sun.COM rx_grp->rings = NULL; 101910309SSriharsha.Basavapatna@Sun.COM } 102010309SSriharsha.Basavapatna@Sun.COM } 102110309SSriharsha.Basavapatna@Sun.COM 102210309SSriharsha.Basavapatna@Sun.COM static vnet_pseudo_rx_ring_t * 102310309SSriharsha.Basavapatna@Sun.COM vnet_alloc_pseudo_rx_ring(vnet_t *vnetp) 102410309SSriharsha.Basavapatna@Sun.COM { 102510309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_group_t *rx_grp; 102610309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_ring_t *rx_ringp; 102710309SSriharsha.Basavapatna@Sun.COM int index; 102810309SSriharsha.Basavapatna@Sun.COM 102910309SSriharsha.Basavapatna@Sun.COM rx_grp = &vnetp->rx_grp[0]; 103010309SSriharsha.Basavapatna@Sun.COM WRITE_ENTER(&rx_grp->lock); 103110309SSriharsha.Basavapatna@Sun.COM 103210309SSriharsha.Basavapatna@Sun.COM if (rx_grp->ring_cnt == rx_grp->max_ring_cnt) { 103310309SSriharsha.Basavapatna@Sun.COM /* no rings available */ 103410309SSriharsha.Basavapatna@Sun.COM RW_EXIT(&rx_grp->lock); 103510309SSriharsha.Basavapatna@Sun.COM return (NULL); 103610309SSriharsha.Basavapatna@Sun.COM } 103710309SSriharsha.Basavapatna@Sun.COM 103810309SSriharsha.Basavapatna@Sun.COM for (index = VNET_NUM_PSEUDO_RXRINGS_DEFAULT; 103910309SSriharsha.Basavapatna@Sun.COM index < rx_grp->max_ring_cnt; index++) { 104010309SSriharsha.Basavapatna@Sun.COM rx_ringp = &rx_grp->rings[index]; 104110309SSriharsha.Basavapatna@Sun.COM if (rx_ringp->state == VNET_RXRING_FREE) { 104210309SSriharsha.Basavapatna@Sun.COM rx_ringp->state |= VNET_RXRING_INUSE; 104310309SSriharsha.Basavapatna@Sun.COM rx_grp->ring_cnt++; 104410309SSriharsha.Basavapatna@Sun.COM break; 104510309SSriharsha.Basavapatna@Sun.COM } 104610309SSriharsha.Basavapatna@Sun.COM } 104710309SSriharsha.Basavapatna@Sun.COM 104810309SSriharsha.Basavapatna@Sun.COM RW_EXIT(&rx_grp->lock); 104910309SSriharsha.Basavapatna@Sun.COM return (rx_ringp); 105010309SSriharsha.Basavapatna@Sun.COM } 105110309SSriharsha.Basavapatna@Sun.COM 105210309SSriharsha.Basavapatna@Sun.COM static void 105310309SSriharsha.Basavapatna@Sun.COM vnet_free_pseudo_rx_ring(vnet_t *vnetp, vnet_pseudo_rx_ring_t *ringp) 105410309SSriharsha.Basavapatna@Sun.COM { 105510309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_group_t *rx_grp; 105610309SSriharsha.Basavapatna@Sun.COM 105710309SSriharsha.Basavapatna@Sun.COM ASSERT(ringp->index >= VNET_NUM_PSEUDO_RXRINGS_DEFAULT); 105810309SSriharsha.Basavapatna@Sun.COM rx_grp = &vnetp->rx_grp[0]; 105910309SSriharsha.Basavapatna@Sun.COM WRITE_ENTER(&rx_grp->lock); 106010309SSriharsha.Basavapatna@Sun.COM 106110309SSriharsha.Basavapatna@Sun.COM if (ringp->state != VNET_RXRING_FREE) { 106210309SSriharsha.Basavapatna@Sun.COM ringp->state = VNET_RXRING_FREE; 106310309SSriharsha.Basavapatna@Sun.COM ringp->handle = NULL; 106410309SSriharsha.Basavapatna@Sun.COM rx_grp->ring_cnt--; 106510309SSriharsha.Basavapatna@Sun.COM } 106610309SSriharsha.Basavapatna@Sun.COM 106710309SSriharsha.Basavapatna@Sun.COM RW_EXIT(&rx_grp->lock); 106810309SSriharsha.Basavapatna@Sun.COM } 106910309SSriharsha.Basavapatna@Sun.COM 10701991Sheppo /* wrapper function for mac_register() */ 10711991Sheppo static int 10721991Sheppo vnet_mac_register(vnet_t *vnetp) 10731991Sheppo { 10742311Sseb mac_register_t *macp; 10752311Sseb int err; 10761991Sheppo 10772311Sseb if ((macp = mac_alloc(MAC_VERSION)) == NULL) 10782311Sseb return (DDI_FAILURE); 10792311Sseb macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 10802311Sseb macp->m_driver = vnetp; 10811991Sheppo macp->m_dip = vnetp->dip; 10822311Sseb macp->m_src_addr = vnetp->curr_macaddr; 10832311Sseb macp->m_callbacks = &vnet_m_callbacks; 10842311Sseb macp->m_min_sdu = 0; 10857529SSriharsha.Basavapatna@Sun.COM macp->m_max_sdu = vnetp->mtu; 10866419Ssb155480 macp->m_margin = VLAN_TAGSZ; 10871991Sheppo 10881991Sheppo /* 108910309SSriharsha.Basavapatna@Sun.COM * MAC_VIRT_SERIALIZE flag is needed while hybridIO is enabled to 109010309SSriharsha.Basavapatna@Sun.COM * workaround tx lock contention issues in nxge. 109110309SSriharsha.Basavapatna@Sun.COM */ 109210309SSriharsha.Basavapatna@Sun.COM macp->m_v12n = MAC_VIRT_LEVEL1; 109310309SSriharsha.Basavapatna@Sun.COM if (vnet_mac_tx_serialize == B_TRUE) { 109410309SSriharsha.Basavapatna@Sun.COM macp->m_v12n |= MAC_VIRT_SERIALIZE; 109510309SSriharsha.Basavapatna@Sun.COM } 109610309SSriharsha.Basavapatna@Sun.COM 109710309SSriharsha.Basavapatna@Sun.COM /* 10981991Sheppo * Finally, we're ready to register ourselves with the MAC layer 10991991Sheppo * interface; if this succeeds, we're all ready to start() 11001991Sheppo */ 11012311Sseb err = mac_register(macp, &vnetp->mh); 11022311Sseb mac_free(macp); 11032311Sseb return (err == 0 ? DDI_SUCCESS : DDI_FAILURE); 11041991Sheppo } 11051991Sheppo 11061991Sheppo /* read the mac address of the device */ 11071991Sheppo static int 11081991Sheppo vnet_read_mac_address(vnet_t *vnetp) 11091991Sheppo { 11101991Sheppo uchar_t *macaddr; 11111991Sheppo uint32_t size; 11121991Sheppo int rv; 11131991Sheppo 11141991Sheppo rv = ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, vnetp->dip, 11154650Sraghuram DDI_PROP_DONTPASS, macaddr_propname, &macaddr, &size); 11161991Sheppo if ((rv != DDI_PROP_SUCCESS) || (size != ETHERADDRL)) { 11174647Sraghuram DWARN(vnetp, "prop_lookup failed(%s) err(%d)\n", 11184647Sraghuram macaddr_propname, rv); 11191991Sheppo return (DDI_FAILURE); 11201991Sheppo } 11211991Sheppo bcopy(macaddr, (caddr_t)vnetp->vendor_addr, ETHERADDRL); 11221991Sheppo bcopy(macaddr, (caddr_t)vnetp->curr_macaddr, ETHERADDRL); 11231991Sheppo ddi_prop_free(macaddr); 11241991Sheppo 11251991Sheppo return (DDI_SUCCESS); 11261991Sheppo } 11271991Sheppo 11286419Ssb155480 static void 11296419Ssb155480 vnet_fdb_create(vnet_t *vnetp) 11301991Sheppo { 11316419Ssb155480 char hashname[MAXNAMELEN]; 11321991Sheppo 11336419Ssb155480 (void) snprintf(hashname, MAXNAMELEN, "vnet%d-fdbhash", 11346419Ssb155480 vnetp->instance); 11356419Ssb155480 vnetp->fdb_nchains = vnet_fdb_nchains; 11366419Ssb155480 vnetp->fdb_hashp = mod_hash_create_ptrhash(hashname, vnetp->fdb_nchains, 11376419Ssb155480 mod_hash_null_valdtor, sizeof (void *)); 11386419Ssb155480 } 11391991Sheppo 11406419Ssb155480 static void 11416419Ssb155480 vnet_fdb_destroy(vnet_t *vnetp) 11426419Ssb155480 { 11436419Ssb155480 /* destroy fdb-hash-table */ 11446419Ssb155480 if (vnetp->fdb_hashp != NULL) { 11456419Ssb155480 mod_hash_destroy_hash(vnetp->fdb_hashp); 11466419Ssb155480 vnetp->fdb_hashp = NULL; 11476419Ssb155480 vnetp->fdb_nchains = 0; 11481991Sheppo } 11491991Sheppo } 11501991Sheppo 11516419Ssb155480 /* 11526419Ssb155480 * Add an entry into the fdb. 11536419Ssb155480 */ 11541991Sheppo void 11556495Sspeer vnet_fdbe_add(vnet_t *vnetp, vnet_res_t *vresp) 11561991Sheppo { 11576419Ssb155480 uint64_t addr = 0; 11586419Ssb155480 int rv; 11596419Ssb155480 11606495Sspeer KEY_HASH(addr, vresp->rem_macaddr); 11611991Sheppo 11626419Ssb155480 /* 11636495Sspeer * If the entry being added corresponds to LDC_SERVICE resource, 11646495Sspeer * that is, vswitch connection, it is added to the hash and also 11656495Sspeer * the entry is cached, an additional reference count reflects 11666495Sspeer * this. The HYBRID resource is not added to the hash, but only 11676495Sspeer * cached, as it is only used for sending out packets for unknown 11686495Sspeer * unicast destinations. 11696419Ssb155480 */ 11706495Sspeer (vresp->type == VIO_NET_RES_LDC_SERVICE) ? 11716495Sspeer (vresp->refcnt = 1) : (vresp->refcnt = 0); 11721991Sheppo 11736419Ssb155480 /* 11746419Ssb155480 * Note: duplicate keys will be rejected by mod_hash. 11756419Ssb155480 */ 11766495Sspeer if (vresp->type != VIO_NET_RES_HYBRID) { 11776495Sspeer rv = mod_hash_insert(vnetp->fdb_hashp, (mod_hash_key_t)addr, 11786495Sspeer (mod_hash_val_t)vresp); 11796495Sspeer if (rv != 0) { 11806495Sspeer DWARN(vnetp, "Duplicate macaddr key(%lx)\n", addr); 11816495Sspeer return; 11826495Sspeer } 11831991Sheppo } 11841991Sheppo 11856495Sspeer if (vresp->type == VIO_NET_RES_LDC_SERVICE) { 11866419Ssb155480 /* Cache the fdb entry to vsw-port */ 11876419Ssb155480 WRITE_ENTER(&vnetp->vsw_fp_rw); 11886419Ssb155480 if (vnetp->vsw_fp == NULL) 11896495Sspeer vnetp->vsw_fp = vresp; 11906495Sspeer RW_EXIT(&vnetp->vsw_fp_rw); 11916495Sspeer } else if (vresp->type == VIO_NET_RES_HYBRID) { 11926495Sspeer /* Cache the fdb entry to hybrid resource */ 11936495Sspeer WRITE_ENTER(&vnetp->vsw_fp_rw); 11946495Sspeer if (vnetp->hio_fp == NULL) 11956495Sspeer vnetp->hio_fp = vresp; 11966419Ssb155480 RW_EXIT(&vnetp->vsw_fp_rw); 11972793Slm66018 } 11981991Sheppo } 11991991Sheppo 12006419Ssb155480 /* 12016419Ssb155480 * Remove an entry from fdb. 12026419Ssb155480 */ 12036495Sspeer static void 12046495Sspeer vnet_fdbe_del(vnet_t *vnetp, vnet_res_t *vresp) 12055641Swentaoy { 12066419Ssb155480 uint64_t addr = 0; 12076419Ssb155480 int rv; 12086419Ssb155480 uint32_t refcnt; 12096495Sspeer vnet_res_t *tmp; 12105641Swentaoy 12116495Sspeer KEY_HASH(addr, vresp->rem_macaddr); 12125641Swentaoy 12136419Ssb155480 /* 12146419Ssb155480 * Remove the entry from fdb hash table. 12156419Ssb155480 * This prevents further references to this fdb entry. 12166419Ssb155480 */ 12176495Sspeer if (vresp->type != VIO_NET_RES_HYBRID) { 12186495Sspeer rv = mod_hash_remove(vnetp->fdb_hashp, (mod_hash_key_t)addr, 12196495Sspeer (mod_hash_val_t *)&tmp); 12206495Sspeer if (rv != 0) { 12216495Sspeer /* 12226495Sspeer * As the resources are added to the hash only 12236495Sspeer * after they are started, this can occur if 12246495Sspeer * a resource unregisters before it is ever started. 12256495Sspeer */ 12266495Sspeer return; 12276495Sspeer } 12286495Sspeer } 12295641Swentaoy 12306495Sspeer if (vresp->type == VIO_NET_RES_LDC_SERVICE) { 12316419Ssb155480 WRITE_ENTER(&vnetp->vsw_fp_rw); 12325641Swentaoy 12336495Sspeer ASSERT(tmp == vnetp->vsw_fp); 12346419Ssb155480 vnetp->vsw_fp = NULL; 12356419Ssb155480 12366419Ssb155480 RW_EXIT(&vnetp->vsw_fp_rw); 12376495Sspeer } else if (vresp->type == VIO_NET_RES_HYBRID) { 12386495Sspeer WRITE_ENTER(&vnetp->vsw_fp_rw); 12396495Sspeer 12406495Sspeer vnetp->hio_fp = NULL; 12416495Sspeer 12426495Sspeer RW_EXIT(&vnetp->vsw_fp_rw); 12435641Swentaoy } 12445641Swentaoy 12455641Swentaoy /* 12466419Ssb155480 * If there are threads already ref holding before the entry was 12476419Ssb155480 * removed from hash table, then wait for ref count to drop to zero. 12485641Swentaoy */ 12496495Sspeer (vresp->type == VIO_NET_RES_LDC_SERVICE) ? 12506495Sspeer (refcnt = 1) : (refcnt = 0); 12516495Sspeer while (vresp->refcnt > refcnt) { 12526419Ssb155480 delay(drv_usectohz(vnet_fdbe_refcnt_delay)); 12536419Ssb155480 } 12541991Sheppo } 12551991Sheppo 12566419Ssb155480 /* 12576419Ssb155480 * Search fdb for a given mac address. If an entry is found, hold 12586419Ssb155480 * a reference to it and return the entry; else returns NULL. 12596419Ssb155480 */ 12606495Sspeer static vnet_res_t * 12616419Ssb155480 vnet_fdbe_find(vnet_t *vnetp, struct ether_addr *addrp) 12621991Sheppo { 12636419Ssb155480 uint64_t key = 0; 12646495Sspeer vnet_res_t *vresp; 12656419Ssb155480 int rv; 12666419Ssb155480 12676495Sspeer KEY_HASH(key, addrp->ether_addr_octet); 12686419Ssb155480 12696419Ssb155480 rv = mod_hash_find_cb(vnetp->fdb_hashp, (mod_hash_key_t)key, 12706495Sspeer (mod_hash_val_t *)&vresp, vnet_fdbe_find_cb); 12711991Sheppo 12726419Ssb155480 if (rv != 0) 12736419Ssb155480 return (NULL); 12741991Sheppo 12756495Sspeer return (vresp); 12766419Ssb155480 } 12771991Sheppo 12786419Ssb155480 /* 12796419Ssb155480 * Callback function provided to mod_hash_find_cb(). After finding the fdb 12806419Ssb155480 * entry corresponding to the key (macaddr), this callback will be invoked by 12816419Ssb155480 * mod_hash_find_cb() to atomically increment the reference count on the fdb 12826419Ssb155480 * entry before returning the found entry. 12836419Ssb155480 */ 12846419Ssb155480 static void 12856419Ssb155480 vnet_fdbe_find_cb(mod_hash_key_t key, mod_hash_val_t val) 12866419Ssb155480 { 12876419Ssb155480 _NOTE(ARGUNUSED(key)) 12886495Sspeer VNET_FDBE_REFHOLD((vnet_res_t *)val); 12896495Sspeer } 12906495Sspeer 12917896SSriharsha.Basavapatna@Sun.COM /* 12927896SSriharsha.Basavapatna@Sun.COM * Frames received that are tagged with the pvid of the vnet device must be 12937896SSriharsha.Basavapatna@Sun.COM * untagged before sending up the stack. This function walks the chain of rx 12947896SSriharsha.Basavapatna@Sun.COM * frames, untags any such frames and returns the updated chain. 12957896SSriharsha.Basavapatna@Sun.COM * 12967896SSriharsha.Basavapatna@Sun.COM * Arguments: 12977896SSriharsha.Basavapatna@Sun.COM * pvid: pvid of the vnet device for which packets are being received 12987896SSriharsha.Basavapatna@Sun.COM * mp: head of pkt chain to be validated and untagged 12997896SSriharsha.Basavapatna@Sun.COM * 13007896SSriharsha.Basavapatna@Sun.COM * Returns: 13017896SSriharsha.Basavapatna@Sun.COM * mp: head of updated chain of packets 13027896SSriharsha.Basavapatna@Sun.COM */ 13037896SSriharsha.Basavapatna@Sun.COM static void 13047896SSriharsha.Basavapatna@Sun.COM vnet_rx_frames_untag(uint16_t pvid, mblk_t **mp) 13057896SSriharsha.Basavapatna@Sun.COM { 13067896SSriharsha.Basavapatna@Sun.COM struct ether_vlan_header *evhp; 13077896SSriharsha.Basavapatna@Sun.COM mblk_t *bp; 13087896SSriharsha.Basavapatna@Sun.COM mblk_t *bpt; 13097896SSriharsha.Basavapatna@Sun.COM mblk_t *bph; 13107896SSriharsha.Basavapatna@Sun.COM mblk_t *bpn; 13117896SSriharsha.Basavapatna@Sun.COM 13127896SSriharsha.Basavapatna@Sun.COM bpn = bph = bpt = NULL; 13137896SSriharsha.Basavapatna@Sun.COM 13147896SSriharsha.Basavapatna@Sun.COM for (bp = *mp; bp != NULL; bp = bpn) { 13157896SSriharsha.Basavapatna@Sun.COM 13167896SSriharsha.Basavapatna@Sun.COM bpn = bp->b_next; 13177896SSriharsha.Basavapatna@Sun.COM bp->b_next = bp->b_prev = NULL; 13187896SSriharsha.Basavapatna@Sun.COM 13197896SSriharsha.Basavapatna@Sun.COM evhp = (struct ether_vlan_header *)bp->b_rptr; 13207896SSriharsha.Basavapatna@Sun.COM 13217896SSriharsha.Basavapatna@Sun.COM if (ntohs(evhp->ether_tpid) == ETHERTYPE_VLAN && 13227896SSriharsha.Basavapatna@Sun.COM VLAN_ID(ntohs(evhp->ether_tci)) == pvid) { 13237896SSriharsha.Basavapatna@Sun.COM 13247896SSriharsha.Basavapatna@Sun.COM bp = vnet_vlan_remove_tag(bp); 13257896SSriharsha.Basavapatna@Sun.COM if (bp == NULL) { 13267896SSriharsha.Basavapatna@Sun.COM continue; 13277896SSriharsha.Basavapatna@Sun.COM } 13287896SSriharsha.Basavapatna@Sun.COM 13297896SSriharsha.Basavapatna@Sun.COM } 13307896SSriharsha.Basavapatna@Sun.COM 13317896SSriharsha.Basavapatna@Sun.COM /* build a chain of processed packets */ 13327896SSriharsha.Basavapatna@Sun.COM if (bph == NULL) { 13337896SSriharsha.Basavapatna@Sun.COM bph = bpt = bp; 13347896SSriharsha.Basavapatna@Sun.COM } else { 13357896SSriharsha.Basavapatna@Sun.COM bpt->b_next = bp; 13367896SSriharsha.Basavapatna@Sun.COM bpt = bp; 13377896SSriharsha.Basavapatna@Sun.COM } 13387896SSriharsha.Basavapatna@Sun.COM 13397896SSriharsha.Basavapatna@Sun.COM } 13407896SSriharsha.Basavapatna@Sun.COM 13417896SSriharsha.Basavapatna@Sun.COM *mp = bph; 13427896SSriharsha.Basavapatna@Sun.COM } 13437896SSriharsha.Basavapatna@Sun.COM 13446495Sspeer static void 13456495Sspeer vnet_rx(vio_net_handle_t vrh, mblk_t *mp) 13466495Sspeer { 134710309SSriharsha.Basavapatna@Sun.COM vnet_res_t *vresp = (vnet_res_t *)vrh; 134810309SSriharsha.Basavapatna@Sun.COM vnet_t *vnetp = vresp->vnetp; 134910309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_ring_t *ringp; 13507896SSriharsha.Basavapatna@Sun.COM 13517896SSriharsha.Basavapatna@Sun.COM if ((vnetp == NULL) || (vnetp->mh == 0)) { 13527896SSriharsha.Basavapatna@Sun.COM freemsgchain(mp); 13537896SSriharsha.Basavapatna@Sun.COM return; 13547896SSriharsha.Basavapatna@Sun.COM } 13556495Sspeer 135610309SSriharsha.Basavapatna@Sun.COM ringp = vresp->rx_ringp; 135710309SSriharsha.Basavapatna@Sun.COM mac_rx_ring(vnetp->mh, ringp->handle, mp, ringp->gen_num); 13581991Sheppo } 13592311Sseb 13602311Sseb void 13616495Sspeer vnet_tx_update(vio_net_handle_t vrh) 13626495Sspeer { 136310309SSriharsha.Basavapatna@Sun.COM vnet_res_t *vresp = (vnet_res_t *)vrh; 136410309SSriharsha.Basavapatna@Sun.COM vnet_t *vnetp = vresp->vnetp; 136510309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_tx_ring_t *tx_ringp; 136610309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_tx_group_t *tx_grp; 136710309SSriharsha.Basavapatna@Sun.COM int i; 136810309SSriharsha.Basavapatna@Sun.COM 136910309SSriharsha.Basavapatna@Sun.COM if (vnetp == NULL || vnetp->mh == NULL) { 137010309SSriharsha.Basavapatna@Sun.COM return; 137110309SSriharsha.Basavapatna@Sun.COM } 137210309SSriharsha.Basavapatna@Sun.COM 137310309SSriharsha.Basavapatna@Sun.COM /* 137410309SSriharsha.Basavapatna@Sun.COM * Currently, the tx hwring API (used to access rings that belong to 137510309SSriharsha.Basavapatna@Sun.COM * a Hybrid IO resource) does not provide us a per ring flow ctrl 137610309SSriharsha.Basavapatna@Sun.COM * update; also the pseudo rings are shared by the ports/ldcs in the 137710309SSriharsha.Basavapatna@Sun.COM * vgen layer. Thus we can't figure out which pseudo ring is being 137810309SSriharsha.Basavapatna@Sun.COM * re-enabled for transmits. To work around this, when we get a tx 137910309SSriharsha.Basavapatna@Sun.COM * restart notification from below, we simply propagate that to all 138010309SSriharsha.Basavapatna@Sun.COM * the tx pseudo rings registered with the mac layer above. 138110309SSriharsha.Basavapatna@Sun.COM * 138210309SSriharsha.Basavapatna@Sun.COM * There are a couple of side effects with this approach, but they are 138310309SSriharsha.Basavapatna@Sun.COM * not harmful, as outlined below: 138410309SSriharsha.Basavapatna@Sun.COM * 138510309SSriharsha.Basavapatna@Sun.COM * A) We might send an invalid ring_update() for a ring that is not 138610309SSriharsha.Basavapatna@Sun.COM * really flow controlled. This will not have any effect in the mac 138710309SSriharsha.Basavapatna@Sun.COM * layer and packets will continue to be transmitted on that ring. 138810309SSriharsha.Basavapatna@Sun.COM * 138910309SSriharsha.Basavapatna@Sun.COM * B) We might end up clearing the flow control in the mac layer for 139010309SSriharsha.Basavapatna@Sun.COM * a ring that is still flow controlled in the underlying resource. 139110309SSriharsha.Basavapatna@Sun.COM * This will result in the mac layer restarting transmit, only to be 139210309SSriharsha.Basavapatna@Sun.COM * flow controlled again on that ring. 139310309SSriharsha.Basavapatna@Sun.COM */ 139410309SSriharsha.Basavapatna@Sun.COM tx_grp = &vnetp->tx_grp[0]; 139510309SSriharsha.Basavapatna@Sun.COM for (i = 0; i < tx_grp->ring_cnt; i++) { 139610309SSriharsha.Basavapatna@Sun.COM tx_ringp = &tx_grp->rings[i]; 139710309SSriharsha.Basavapatna@Sun.COM mac_tx_ring_update(vnetp->mh, tx_ringp->handle); 13986495Sspeer } 13996495Sspeer } 14006495Sspeer 14016495Sspeer /* 14027529SSriharsha.Basavapatna@Sun.COM * Update the new mtu of vnet into the mac layer. First check if the device has 14037529SSriharsha.Basavapatna@Sun.COM * been plumbed and if so fail the mtu update. Returns 0 on success. 14047529SSriharsha.Basavapatna@Sun.COM */ 14057529SSriharsha.Basavapatna@Sun.COM int 14067529SSriharsha.Basavapatna@Sun.COM vnet_mtu_update(vnet_t *vnetp, uint32_t mtu) 14077529SSriharsha.Basavapatna@Sun.COM { 14087529SSriharsha.Basavapatna@Sun.COM int rv; 14097529SSriharsha.Basavapatna@Sun.COM 14107529SSriharsha.Basavapatna@Sun.COM if (vnetp == NULL || vnetp->mh == NULL) { 14117529SSriharsha.Basavapatna@Sun.COM return (EINVAL); 14127529SSriharsha.Basavapatna@Sun.COM } 14137529SSriharsha.Basavapatna@Sun.COM 14147529SSriharsha.Basavapatna@Sun.COM WRITE_ENTER(&vnetp->vrwlock); 14157529SSriharsha.Basavapatna@Sun.COM 14167529SSriharsha.Basavapatna@Sun.COM if (vnetp->flags & VNET_STARTED) { 14177529SSriharsha.Basavapatna@Sun.COM RW_EXIT(&vnetp->vrwlock); 14187529SSriharsha.Basavapatna@Sun.COM cmn_err(CE_NOTE, "!vnet%d: Unable to process mtu " 14197529SSriharsha.Basavapatna@Sun.COM "update as the device is plumbed\n", 14207529SSriharsha.Basavapatna@Sun.COM vnetp->instance); 14217529SSriharsha.Basavapatna@Sun.COM return (EBUSY); 14227529SSriharsha.Basavapatna@Sun.COM } 14237529SSriharsha.Basavapatna@Sun.COM 14247529SSriharsha.Basavapatna@Sun.COM /* update mtu in the mac layer */ 14257529SSriharsha.Basavapatna@Sun.COM rv = mac_maxsdu_update(vnetp->mh, mtu); 14267529SSriharsha.Basavapatna@Sun.COM if (rv != 0) { 14277529SSriharsha.Basavapatna@Sun.COM RW_EXIT(&vnetp->vrwlock); 14287529SSriharsha.Basavapatna@Sun.COM cmn_err(CE_NOTE, 14297529SSriharsha.Basavapatna@Sun.COM "!vnet%d: Unable to update mtu with mac layer\n", 14307529SSriharsha.Basavapatna@Sun.COM vnetp->instance); 14317529SSriharsha.Basavapatna@Sun.COM return (EIO); 14327529SSriharsha.Basavapatna@Sun.COM } 14337529SSriharsha.Basavapatna@Sun.COM 14347529SSriharsha.Basavapatna@Sun.COM vnetp->mtu = mtu; 14357529SSriharsha.Basavapatna@Sun.COM 14367529SSriharsha.Basavapatna@Sun.COM RW_EXIT(&vnetp->vrwlock); 14377529SSriharsha.Basavapatna@Sun.COM 14387529SSriharsha.Basavapatna@Sun.COM return (0); 14397529SSriharsha.Basavapatna@Sun.COM } 14407529SSriharsha.Basavapatna@Sun.COM 14417529SSriharsha.Basavapatna@Sun.COM /* 14429336SSriharsha.Basavapatna@Sun.COM * Update the link state of vnet to the mac layer. 14439336SSriharsha.Basavapatna@Sun.COM */ 14449336SSriharsha.Basavapatna@Sun.COM void 14459336SSriharsha.Basavapatna@Sun.COM vnet_link_update(vnet_t *vnetp, link_state_t link_state) 14469336SSriharsha.Basavapatna@Sun.COM { 14479336SSriharsha.Basavapatna@Sun.COM if (vnetp == NULL || vnetp->mh == NULL) { 14489336SSriharsha.Basavapatna@Sun.COM return; 14499336SSriharsha.Basavapatna@Sun.COM } 14509336SSriharsha.Basavapatna@Sun.COM 14519336SSriharsha.Basavapatna@Sun.COM WRITE_ENTER(&vnetp->vrwlock); 14529336SSriharsha.Basavapatna@Sun.COM if (vnetp->link_state == link_state) { 14539336SSriharsha.Basavapatna@Sun.COM RW_EXIT(&vnetp->vrwlock); 14549336SSriharsha.Basavapatna@Sun.COM return; 14559336SSriharsha.Basavapatna@Sun.COM } 14569336SSriharsha.Basavapatna@Sun.COM vnetp->link_state = link_state; 14579336SSriharsha.Basavapatna@Sun.COM RW_EXIT(&vnetp->vrwlock); 14589336SSriharsha.Basavapatna@Sun.COM 14599336SSriharsha.Basavapatna@Sun.COM mac_link_update(vnetp->mh, link_state); 14609336SSriharsha.Basavapatna@Sun.COM } 14619336SSriharsha.Basavapatna@Sun.COM 14629336SSriharsha.Basavapatna@Sun.COM /* 14636495Sspeer * vio_net_resource_reg -- An interface called to register a resource 14646495Sspeer * with vnet. 14656495Sspeer * macp -- a GLDv3 mac_register that has all the details of 14666495Sspeer * a resource and its callbacks etc. 14676495Sspeer * type -- resource type. 14686495Sspeer * local_macaddr -- resource's MAC address. This is used to 14696495Sspeer * associate a resource with a corresponding vnet. 14706495Sspeer * remote_macaddr -- remote side MAC address. This is ignored for 14716495Sspeer * the Hybrid resources. 14726495Sspeer * vhp -- A handle returned to the caller. 14736495Sspeer * vcb -- A set of callbacks provided to the callers. 14746495Sspeer */ 14756495Sspeer int vio_net_resource_reg(mac_register_t *macp, vio_net_res_type_t type, 14766495Sspeer ether_addr_t local_macaddr, ether_addr_t rem_macaddr, vio_net_handle_t *vhp, 14776495Sspeer vio_net_callbacks_t *vcb) 14786495Sspeer { 147910309SSriharsha.Basavapatna@Sun.COM vnet_t *vnetp; 148010309SSriharsha.Basavapatna@Sun.COM vnet_res_t *vresp; 14816495Sspeer 14826495Sspeer vresp = kmem_zalloc(sizeof (vnet_res_t), KM_SLEEP); 14836495Sspeer ether_copy(local_macaddr, vresp->local_macaddr); 14846495Sspeer ether_copy(rem_macaddr, vresp->rem_macaddr); 14856495Sspeer vresp->type = type; 14866495Sspeer bcopy(macp, &vresp->macreg, sizeof (mac_register_t)); 14876495Sspeer 14886495Sspeer DBG1(NULL, "Resource Registerig type=0%X\n", type); 14896495Sspeer 14906495Sspeer READ_ENTER(&vnet_rw); 14916495Sspeer vnetp = vnet_headp; 14926495Sspeer while (vnetp != NULL) { 14936495Sspeer if (VNET_MATCH_RES(vresp, vnetp)) { 14948332SWentao.Yang@Sun.COM vresp->vnetp = vnetp; 14958332SWentao.Yang@Sun.COM 14968332SWentao.Yang@Sun.COM /* Setup kstats for hio resource */ 14978332SWentao.Yang@Sun.COM if (vresp->type == VIO_NET_RES_HYBRID) { 14988332SWentao.Yang@Sun.COM vresp->ksp = vnet_hio_setup_kstats(DRV_NAME, 14998332SWentao.Yang@Sun.COM "hio", vresp); 15008332SWentao.Yang@Sun.COM if (vresp->ksp == NULL) { 15018332SWentao.Yang@Sun.COM cmn_err(CE_NOTE, "!vnet%d: Cannot " 15028332SWentao.Yang@Sun.COM "create kstats for hio resource", 15038332SWentao.Yang@Sun.COM vnetp->instance); 15048332SWentao.Yang@Sun.COM } 15058332SWentao.Yang@Sun.COM } 150610309SSriharsha.Basavapatna@Sun.COM vnet_add_resource(vnetp, vresp); 15076495Sspeer break; 15086495Sspeer } 15096495Sspeer vnetp = vnetp->nextp; 15106495Sspeer } 15116495Sspeer RW_EXIT(&vnet_rw); 15126495Sspeer if (vresp->vnetp == NULL) { 15136495Sspeer DWARN(NULL, "No vnet instance"); 15146495Sspeer kmem_free(vresp, sizeof (vnet_res_t)); 15156495Sspeer return (ENXIO); 15166495Sspeer } 15176495Sspeer 15186495Sspeer *vhp = vresp; 15196495Sspeer vcb->vio_net_rx_cb = vnet_rx; 15206495Sspeer vcb->vio_net_tx_update = vnet_tx_update; 15216495Sspeer vcb->vio_net_report_err = vnet_handle_res_err; 15226495Sspeer 152310309SSriharsha.Basavapatna@Sun.COM /* Bind the resource to pseudo ring(s) */ 152410309SSriharsha.Basavapatna@Sun.COM if (vnet_bind_rings(vresp) != 0) { 152510309SSriharsha.Basavapatna@Sun.COM (void) vnet_rem_resource(vnetp, vresp); 152610309SSriharsha.Basavapatna@Sun.COM vnet_hio_destroy_kstats(vresp->ksp); 152710309SSriharsha.Basavapatna@Sun.COM KMEM_FREE(vresp); 152810309SSriharsha.Basavapatna@Sun.COM return (1); 152910309SSriharsha.Basavapatna@Sun.COM } 153010309SSriharsha.Basavapatna@Sun.COM 15316495Sspeer /* Dispatch a task to start resources */ 15326495Sspeer vnet_dispatch_res_task(vnetp); 15336495Sspeer return (0); 15346495Sspeer } 15356495Sspeer 15366495Sspeer /* 15376495Sspeer * vio_net_resource_unreg -- An interface to unregister a resource. 15386495Sspeer */ 15396495Sspeer void 15406495Sspeer vio_net_resource_unreg(vio_net_handle_t vhp) 15416495Sspeer { 15429805SSriharsha.Basavapatna@Sun.COM vnet_res_t *vresp = (vnet_res_t *)vhp; 15439805SSriharsha.Basavapatna@Sun.COM vnet_t *vnetp = vresp->vnetp; 15446495Sspeer 15456495Sspeer DBG1(NULL, "Resource Registerig hdl=0x%p", vhp); 15466495Sspeer 15476495Sspeer ASSERT(vnetp != NULL); 15489805SSriharsha.Basavapatna@Sun.COM /* 15499805SSriharsha.Basavapatna@Sun.COM * Remove the resource from fdb; this ensures 15509805SSriharsha.Basavapatna@Sun.COM * there are no references to the resource. 15519805SSriharsha.Basavapatna@Sun.COM */ 15526495Sspeer vnet_fdbe_del(vnetp, vresp); 15536495Sspeer 155410309SSriharsha.Basavapatna@Sun.COM vnet_unbind_rings(vresp); 155510309SSriharsha.Basavapatna@Sun.COM 15569805SSriharsha.Basavapatna@Sun.COM /* Now remove the resource from the list */ 155710309SSriharsha.Basavapatna@Sun.COM (void) vnet_rem_resource(vnetp, vresp); 155810309SSriharsha.Basavapatna@Sun.COM 155910309SSriharsha.Basavapatna@Sun.COM vnet_hio_destroy_kstats(vresp->ksp); 156010309SSriharsha.Basavapatna@Sun.COM KMEM_FREE(vresp); 156110309SSriharsha.Basavapatna@Sun.COM } 156210309SSriharsha.Basavapatna@Sun.COM 156310309SSriharsha.Basavapatna@Sun.COM static void 156410309SSriharsha.Basavapatna@Sun.COM vnet_add_resource(vnet_t *vnetp, vnet_res_t *vresp) 156510309SSriharsha.Basavapatna@Sun.COM { 156610309SSriharsha.Basavapatna@Sun.COM WRITE_ENTER(&vnetp->vrwlock); 156710309SSriharsha.Basavapatna@Sun.COM vresp->nextp = vnetp->vres_list; 156810309SSriharsha.Basavapatna@Sun.COM vnetp->vres_list = vresp; 156910309SSriharsha.Basavapatna@Sun.COM RW_EXIT(&vnetp->vrwlock); 157010309SSriharsha.Basavapatna@Sun.COM } 157110309SSriharsha.Basavapatna@Sun.COM 157210309SSriharsha.Basavapatna@Sun.COM static vnet_res_t * 157310309SSriharsha.Basavapatna@Sun.COM vnet_rem_resource(vnet_t *vnetp, vnet_res_t *vresp) 157410309SSriharsha.Basavapatna@Sun.COM { 157510309SSriharsha.Basavapatna@Sun.COM vnet_res_t *vrp; 157610309SSriharsha.Basavapatna@Sun.COM 15776495Sspeer WRITE_ENTER(&vnetp->vrwlock); 15786495Sspeer if (vresp == vnetp->vres_list) { 15796495Sspeer vnetp->vres_list = vresp->nextp; 15806495Sspeer } else { 15816495Sspeer vrp = vnetp->vres_list; 15826495Sspeer while (vrp->nextp != NULL) { 15836495Sspeer if (vrp->nextp == vresp) { 15846495Sspeer vrp->nextp = vresp->nextp; 15856495Sspeer break; 15866495Sspeer } 15876495Sspeer vrp = vrp->nextp; 15886495Sspeer } 15896495Sspeer } 15906495Sspeer vresp->vnetp = NULL; 15916495Sspeer vresp->nextp = NULL; 159210309SSriharsha.Basavapatna@Sun.COM 15936495Sspeer RW_EXIT(&vnetp->vrwlock); 159410309SSriharsha.Basavapatna@Sun.COM 159510309SSriharsha.Basavapatna@Sun.COM return (vresp); 15966495Sspeer } 15976495Sspeer 15986495Sspeer /* 15996495Sspeer * vnet_dds_rx -- an interface called by vgen to DDS messages. 16006495Sspeer */ 16016495Sspeer void 16026495Sspeer vnet_dds_rx(void *arg, void *dmsg) 16032311Sseb { 16042311Sseb vnet_t *vnetp = arg; 16056495Sspeer vdds_process_dds_msg(vnetp, dmsg); 16062311Sseb } 16072311Sseb 16086495Sspeer /* 16096495Sspeer * vnet_send_dds_msg -- An interface provided to DDS to send 16106495Sspeer * DDS messages. This simply sends meessages via vgen. 16116495Sspeer */ 16126495Sspeer int 16136495Sspeer vnet_send_dds_msg(vnet_t *vnetp, void *dmsg) 16146495Sspeer { 16156495Sspeer int rv; 16166495Sspeer 16176495Sspeer if (vnetp->vgenhdl != NULL) { 16186495Sspeer rv = vgen_dds_tx(vnetp->vgenhdl, dmsg); 16196495Sspeer } 16206495Sspeer return (rv); 16216495Sspeer } 16226495Sspeer 16236495Sspeer /* 16249647SWentao.Yang@Sun.COM * vnet_cleanup_hio -- an interface called by vgen to cleanup hio resources. 16259647SWentao.Yang@Sun.COM */ 16269647SWentao.Yang@Sun.COM void 16279647SWentao.Yang@Sun.COM vnet_dds_cleanup_hio(vnet_t *vnetp) 16289647SWentao.Yang@Sun.COM { 16299647SWentao.Yang@Sun.COM vdds_cleanup_hio(vnetp); 16309647SWentao.Yang@Sun.COM } 16319647SWentao.Yang@Sun.COM 16329647SWentao.Yang@Sun.COM /* 16336495Sspeer * vnet_handle_res_err -- A callback function called by a resource 16346495Sspeer * to report an error. For example, vgen can call to report 16356495Sspeer * an LDC down/reset event. This will trigger cleanup of associated 16366495Sspeer * Hybrid resource. 16376495Sspeer */ 16386495Sspeer /* ARGSUSED */ 16396495Sspeer static void 16406495Sspeer vnet_handle_res_err(vio_net_handle_t vrh, vio_net_err_val_t err) 16416495Sspeer { 16426495Sspeer vnet_res_t *vresp = (vnet_res_t *)vrh; 16436495Sspeer vnet_t *vnetp = vresp->vnetp; 16446495Sspeer 16456495Sspeer if (vnetp == NULL) { 16466495Sspeer return; 16476495Sspeer } 16486495Sspeer if ((vresp->type != VIO_NET_RES_LDC_SERVICE) && 16496495Sspeer (vresp->type != VIO_NET_RES_HYBRID)) { 16506495Sspeer return; 16516495Sspeer } 16529647SWentao.Yang@Sun.COM 16539647SWentao.Yang@Sun.COM vdds_cleanup_hio(vnetp); 16546495Sspeer } 16556495Sspeer 16566495Sspeer /* 16576495Sspeer * vnet_dispatch_res_task -- A function to dispatch tasks start resources. 16586495Sspeer */ 16596495Sspeer static void 16606495Sspeer vnet_dispatch_res_task(vnet_t *vnetp) 16616495Sspeer { 16626495Sspeer int rv; 16636495Sspeer 16649677SZachary.Kissel@Sun.COM /* 16659677SZachary.Kissel@Sun.COM * Dispatch the task. It could be the case that vnetp->flags does 16669677SZachary.Kissel@Sun.COM * not have VNET_STARTED set. This is ok as vnet_rest_start_task() 16679805SSriharsha.Basavapatna@Sun.COM * can abort the task when the task is started. See related comments 16689805SSriharsha.Basavapatna@Sun.COM * in vnet_m_stop() and vnet_stop_resources(). 16699677SZachary.Kissel@Sun.COM */ 16709677SZachary.Kissel@Sun.COM rv = ddi_taskq_dispatch(vnetp->taskqp, vnet_res_start_task, 16719677SZachary.Kissel@Sun.COM vnetp, DDI_NOSLEEP); 16729677SZachary.Kissel@Sun.COM if (rv != DDI_SUCCESS) { 16739677SZachary.Kissel@Sun.COM cmn_err(CE_WARN, 16749677SZachary.Kissel@Sun.COM "vnet%d:Can't dispatch start resource task", 16759677SZachary.Kissel@Sun.COM vnetp->instance); 16766495Sspeer } 16776495Sspeer } 16786495Sspeer 16796495Sspeer /* 16806495Sspeer * vnet_res_start_task -- A taskq callback function that starts a resource. 16816495Sspeer */ 16826495Sspeer static void 16836495Sspeer vnet_res_start_task(void *arg) 16842311Sseb { 16852311Sseb vnet_t *vnetp = arg; 16866495Sspeer 16876495Sspeer WRITE_ENTER(&vnetp->vrwlock); 16886495Sspeer if (vnetp->flags & VNET_STARTED) { 16896495Sspeer vnet_start_resources(vnetp); 16906495Sspeer } 16916495Sspeer RW_EXIT(&vnetp->vrwlock); 16922311Sseb } 16936495Sspeer 16946495Sspeer /* 16956495Sspeer * vnet_start_resources -- starts all resources associated with 16966495Sspeer * a vnet. 16976495Sspeer */ 16986495Sspeer static void 16996495Sspeer vnet_start_resources(vnet_t *vnetp) 17006495Sspeer { 17016495Sspeer mac_register_t *macp; 17026495Sspeer mac_callbacks_t *cbp; 17036495Sspeer vnet_res_t *vresp; 17046495Sspeer int rv; 17056495Sspeer 17066495Sspeer DBG1(vnetp, "enter\n"); 17076495Sspeer 17089805SSriharsha.Basavapatna@Sun.COM ASSERT(RW_WRITE_HELD(&vnetp->vrwlock)); 17099805SSriharsha.Basavapatna@Sun.COM 17106495Sspeer for (vresp = vnetp->vres_list; vresp != NULL; vresp = vresp->nextp) { 17116495Sspeer /* skip if it is already started */ 17126495Sspeer if (vresp->flags & VNET_STARTED) { 17136495Sspeer continue; 17146495Sspeer } 17156495Sspeer macp = &vresp->macreg; 17166495Sspeer cbp = macp->m_callbacks; 17176495Sspeer rv = cbp->mc_start(macp->m_driver); 17186495Sspeer if (rv == 0) { 17196495Sspeer /* 17206495Sspeer * Successfully started the resource, so now 17216495Sspeer * add it to the fdb. 17226495Sspeer */ 17236495Sspeer vresp->flags |= VNET_STARTED; 17246495Sspeer vnet_fdbe_add(vnetp, vresp); 17256495Sspeer } 17266495Sspeer } 17276495Sspeer 17286495Sspeer DBG1(vnetp, "exit\n"); 17296495Sspeer 17306495Sspeer } 17316495Sspeer 17326495Sspeer /* 17336495Sspeer * vnet_stop_resources -- stop all resources associated with a vnet. 17346495Sspeer */ 17356495Sspeer static void 17366495Sspeer vnet_stop_resources(vnet_t *vnetp) 17376495Sspeer { 17386495Sspeer vnet_res_t *vresp; 17396495Sspeer mac_register_t *macp; 17406495Sspeer mac_callbacks_t *cbp; 17416495Sspeer 17426495Sspeer DBG1(vnetp, "enter\n"); 17436495Sspeer 17449805SSriharsha.Basavapatna@Sun.COM ASSERT(RW_WRITE_HELD(&vnetp->vrwlock)); 17459805SSriharsha.Basavapatna@Sun.COM 17466495Sspeer for (vresp = vnetp->vres_list; vresp != NULL; ) { 17476495Sspeer if (vresp->flags & VNET_STARTED) { 17489805SSriharsha.Basavapatna@Sun.COM /* 17499805SSriharsha.Basavapatna@Sun.COM * Release the lock while invoking mc_stop() of the 17509805SSriharsha.Basavapatna@Sun.COM * underlying resource. We hold a reference to this 17519805SSriharsha.Basavapatna@Sun.COM * resource to prevent being removed from the list in 17529805SSriharsha.Basavapatna@Sun.COM * vio_net_resource_unreg(). Note that new resources 17539805SSriharsha.Basavapatna@Sun.COM * can be added to the head of the list while the lock 17549805SSriharsha.Basavapatna@Sun.COM * is released, but they won't be started, as 17559805SSriharsha.Basavapatna@Sun.COM * VNET_STARTED flag has been cleared for the vnet 17569805SSriharsha.Basavapatna@Sun.COM * device in vnet_m_stop(). Also, while the lock is 17579805SSriharsha.Basavapatna@Sun.COM * released a resource could be removed from the list 17589805SSriharsha.Basavapatna@Sun.COM * in vio_net_resource_unreg(); but that is ok, as we 17599805SSriharsha.Basavapatna@Sun.COM * re-acquire the lock and only then access the forward 17609805SSriharsha.Basavapatna@Sun.COM * link (vresp->nextp) to continue with the next 17619805SSriharsha.Basavapatna@Sun.COM * resource. 17629805SSriharsha.Basavapatna@Sun.COM */ 17639805SSriharsha.Basavapatna@Sun.COM vresp->flags &= ~VNET_STARTED; 17649805SSriharsha.Basavapatna@Sun.COM vresp->flags |= VNET_STOPPING; 17656495Sspeer macp = &vresp->macreg; 17666495Sspeer cbp = macp->m_callbacks; 17679805SSriharsha.Basavapatna@Sun.COM VNET_FDBE_REFHOLD(vresp); 17689805SSriharsha.Basavapatna@Sun.COM RW_EXIT(&vnetp->vrwlock); 17699805SSriharsha.Basavapatna@Sun.COM 17706495Sspeer cbp->mc_stop(macp->m_driver); 17719805SSriharsha.Basavapatna@Sun.COM 17729805SSriharsha.Basavapatna@Sun.COM WRITE_ENTER(&vnetp->vrwlock); 17739805SSriharsha.Basavapatna@Sun.COM vresp->flags &= ~VNET_STOPPING; 17749805SSriharsha.Basavapatna@Sun.COM VNET_FDBE_REFRELE(vresp); 17756495Sspeer } 17769805SSriharsha.Basavapatna@Sun.COM vresp = vresp->nextp; 17776495Sspeer } 17786495Sspeer DBG1(vnetp, "exit\n"); 17796495Sspeer } 17808160SWentao.Yang@Sun.COM 17818160SWentao.Yang@Sun.COM /* 17828160SWentao.Yang@Sun.COM * Setup kstats for the HIO statistics. 17838160SWentao.Yang@Sun.COM * NOTE: the synchronization for the statistics is the 17848160SWentao.Yang@Sun.COM * responsibility of the caller. 17858160SWentao.Yang@Sun.COM */ 17868160SWentao.Yang@Sun.COM kstat_t * 17878160SWentao.Yang@Sun.COM vnet_hio_setup_kstats(char *ks_mod, char *ks_name, vnet_res_t *vresp) 17888160SWentao.Yang@Sun.COM { 17898160SWentao.Yang@Sun.COM kstat_t *ksp; 17908160SWentao.Yang@Sun.COM vnet_t *vnetp = vresp->vnetp; 17918160SWentao.Yang@Sun.COM vnet_hio_kstats_t *hiokp; 17928160SWentao.Yang@Sun.COM size_t size; 17938160SWentao.Yang@Sun.COM 17948160SWentao.Yang@Sun.COM ASSERT(vnetp != NULL); 17958160SWentao.Yang@Sun.COM size = sizeof (vnet_hio_kstats_t) / sizeof (kstat_named_t); 17968160SWentao.Yang@Sun.COM ksp = kstat_create(ks_mod, vnetp->instance, ks_name, "net", 17978160SWentao.Yang@Sun.COM KSTAT_TYPE_NAMED, size, 0); 17988160SWentao.Yang@Sun.COM if (ksp == NULL) { 17998160SWentao.Yang@Sun.COM return (NULL); 18008160SWentao.Yang@Sun.COM } 18018160SWentao.Yang@Sun.COM 18028160SWentao.Yang@Sun.COM hiokp = (vnet_hio_kstats_t *)ksp->ks_data; 18038160SWentao.Yang@Sun.COM kstat_named_init(&hiokp->ipackets, "ipackets", 18048160SWentao.Yang@Sun.COM KSTAT_DATA_ULONG); 18058160SWentao.Yang@Sun.COM kstat_named_init(&hiokp->ierrors, "ierrors", 18068160SWentao.Yang@Sun.COM KSTAT_DATA_ULONG); 18078160SWentao.Yang@Sun.COM kstat_named_init(&hiokp->opackets, "opackets", 18088160SWentao.Yang@Sun.COM KSTAT_DATA_ULONG); 18098160SWentao.Yang@Sun.COM kstat_named_init(&hiokp->oerrors, "oerrors", 18108160SWentao.Yang@Sun.COM KSTAT_DATA_ULONG); 18118160SWentao.Yang@Sun.COM 18128160SWentao.Yang@Sun.COM 18138160SWentao.Yang@Sun.COM /* MIB II kstat variables */ 18148160SWentao.Yang@Sun.COM kstat_named_init(&hiokp->rbytes, "rbytes", 18158160SWentao.Yang@Sun.COM KSTAT_DATA_ULONG); 18168160SWentao.Yang@Sun.COM kstat_named_init(&hiokp->obytes, "obytes", 18178160SWentao.Yang@Sun.COM KSTAT_DATA_ULONG); 18188160SWentao.Yang@Sun.COM kstat_named_init(&hiokp->multircv, "multircv", 18198160SWentao.Yang@Sun.COM KSTAT_DATA_ULONG); 18208160SWentao.Yang@Sun.COM kstat_named_init(&hiokp->multixmt, "multixmt", 18218160SWentao.Yang@Sun.COM KSTAT_DATA_ULONG); 18228160SWentao.Yang@Sun.COM kstat_named_init(&hiokp->brdcstrcv, "brdcstrcv", 18238160SWentao.Yang@Sun.COM KSTAT_DATA_ULONG); 18248160SWentao.Yang@Sun.COM kstat_named_init(&hiokp->brdcstxmt, "brdcstxmt", 18258160SWentao.Yang@Sun.COM KSTAT_DATA_ULONG); 18268160SWentao.Yang@Sun.COM kstat_named_init(&hiokp->norcvbuf, "norcvbuf", 18278160SWentao.Yang@Sun.COM KSTAT_DATA_ULONG); 18288160SWentao.Yang@Sun.COM kstat_named_init(&hiokp->noxmtbuf, "noxmtbuf", 18298160SWentao.Yang@Sun.COM KSTAT_DATA_ULONG); 18308160SWentao.Yang@Sun.COM 18318160SWentao.Yang@Sun.COM ksp->ks_update = vnet_hio_update_kstats; 18328160SWentao.Yang@Sun.COM ksp->ks_private = (void *)vresp; 18338160SWentao.Yang@Sun.COM kstat_install(ksp); 18348160SWentao.Yang@Sun.COM return (ksp); 18358160SWentao.Yang@Sun.COM } 18368160SWentao.Yang@Sun.COM 18378160SWentao.Yang@Sun.COM /* 18388160SWentao.Yang@Sun.COM * Destroy kstats. 18398160SWentao.Yang@Sun.COM */ 18408160SWentao.Yang@Sun.COM static void 18418160SWentao.Yang@Sun.COM vnet_hio_destroy_kstats(kstat_t *ksp) 18428160SWentao.Yang@Sun.COM { 18438160SWentao.Yang@Sun.COM if (ksp != NULL) 18448160SWentao.Yang@Sun.COM kstat_delete(ksp); 18458160SWentao.Yang@Sun.COM } 18468160SWentao.Yang@Sun.COM 18478160SWentao.Yang@Sun.COM /* 18488160SWentao.Yang@Sun.COM * Update the kstats. 18498160SWentao.Yang@Sun.COM */ 18508160SWentao.Yang@Sun.COM static int 18518160SWentao.Yang@Sun.COM vnet_hio_update_kstats(kstat_t *ksp, int rw) 18528160SWentao.Yang@Sun.COM { 18538160SWentao.Yang@Sun.COM vnet_t *vnetp; 18548160SWentao.Yang@Sun.COM vnet_res_t *vresp; 18558160SWentao.Yang@Sun.COM vnet_hio_stats_t statsp; 18568160SWentao.Yang@Sun.COM vnet_hio_kstats_t *hiokp; 18578160SWentao.Yang@Sun.COM 18588160SWentao.Yang@Sun.COM vresp = (vnet_res_t *)ksp->ks_private; 18598160SWentao.Yang@Sun.COM vnetp = vresp->vnetp; 18608160SWentao.Yang@Sun.COM 18618160SWentao.Yang@Sun.COM bzero(&statsp, sizeof (vnet_hio_stats_t)); 18628160SWentao.Yang@Sun.COM 18638160SWentao.Yang@Sun.COM READ_ENTER(&vnetp->vsw_fp_rw); 18648160SWentao.Yang@Sun.COM if (vnetp->hio_fp == NULL) { 18658160SWentao.Yang@Sun.COM /* not using hio resources, just return */ 18668160SWentao.Yang@Sun.COM RW_EXIT(&vnetp->vsw_fp_rw); 18678160SWentao.Yang@Sun.COM return (0); 18688160SWentao.Yang@Sun.COM } 18698160SWentao.Yang@Sun.COM VNET_FDBE_REFHOLD(vnetp->hio_fp); 18708160SWentao.Yang@Sun.COM RW_EXIT(&vnetp->vsw_fp_rw); 18718160SWentao.Yang@Sun.COM vnet_hio_get_stats(vnetp->hio_fp, &statsp); 18728160SWentao.Yang@Sun.COM VNET_FDBE_REFRELE(vnetp->hio_fp); 18738160SWentao.Yang@Sun.COM 18748160SWentao.Yang@Sun.COM hiokp = (vnet_hio_kstats_t *)ksp->ks_data; 18758160SWentao.Yang@Sun.COM 18768160SWentao.Yang@Sun.COM if (rw == KSTAT_READ) { 18778160SWentao.Yang@Sun.COM /* Link Input/Output stats */ 18788160SWentao.Yang@Sun.COM hiokp->ipackets.value.ul = (uint32_t)statsp.ipackets; 18798160SWentao.Yang@Sun.COM hiokp->ipackets64.value.ull = statsp.ipackets; 18808160SWentao.Yang@Sun.COM hiokp->ierrors.value.ul = statsp.ierrors; 18818160SWentao.Yang@Sun.COM hiokp->opackets.value.ul = (uint32_t)statsp.opackets; 18828160SWentao.Yang@Sun.COM hiokp->opackets64.value.ull = statsp.opackets; 18838160SWentao.Yang@Sun.COM hiokp->oerrors.value.ul = statsp.oerrors; 18848160SWentao.Yang@Sun.COM 18858160SWentao.Yang@Sun.COM /* MIB II kstat variables */ 18868160SWentao.Yang@Sun.COM hiokp->rbytes.value.ul = (uint32_t)statsp.rbytes; 18878160SWentao.Yang@Sun.COM hiokp->rbytes64.value.ull = statsp.rbytes; 18888160SWentao.Yang@Sun.COM hiokp->obytes.value.ul = (uint32_t)statsp.obytes; 18898160SWentao.Yang@Sun.COM hiokp->obytes64.value.ull = statsp.obytes; 18908160SWentao.Yang@Sun.COM hiokp->multircv.value.ul = statsp.multircv; 18918160SWentao.Yang@Sun.COM hiokp->multixmt.value.ul = statsp.multixmt; 18928160SWentao.Yang@Sun.COM hiokp->brdcstrcv.value.ul = statsp.brdcstrcv; 18938160SWentao.Yang@Sun.COM hiokp->brdcstxmt.value.ul = statsp.brdcstxmt; 18948160SWentao.Yang@Sun.COM hiokp->norcvbuf.value.ul = statsp.norcvbuf; 18958160SWentao.Yang@Sun.COM hiokp->noxmtbuf.value.ul = statsp.noxmtbuf; 18968160SWentao.Yang@Sun.COM } else { 18978160SWentao.Yang@Sun.COM return (EACCES); 18988160SWentao.Yang@Sun.COM } 18998160SWentao.Yang@Sun.COM 19008160SWentao.Yang@Sun.COM return (0); 19018160SWentao.Yang@Sun.COM } 19028160SWentao.Yang@Sun.COM 19038160SWentao.Yang@Sun.COM static void 19048160SWentao.Yang@Sun.COM vnet_hio_get_stats(vnet_res_t *vresp, vnet_hio_stats_t *statsp) 19058160SWentao.Yang@Sun.COM { 19068160SWentao.Yang@Sun.COM mac_register_t *macp; 19078160SWentao.Yang@Sun.COM mac_callbacks_t *cbp; 19088160SWentao.Yang@Sun.COM uint64_t val; 19098160SWentao.Yang@Sun.COM int stat; 19108160SWentao.Yang@Sun.COM 19118160SWentao.Yang@Sun.COM /* 19128160SWentao.Yang@Sun.COM * get the specified statistics from the underlying nxge. 19138160SWentao.Yang@Sun.COM */ 19148160SWentao.Yang@Sun.COM macp = &vresp->macreg; 19158160SWentao.Yang@Sun.COM cbp = macp->m_callbacks; 19168160SWentao.Yang@Sun.COM for (stat = MAC_STAT_MIN; stat < MAC_STAT_OVERFLOWS; stat++) { 19178160SWentao.Yang@Sun.COM if (cbp->mc_getstat(macp->m_driver, stat, &val) == 0) { 19188160SWentao.Yang@Sun.COM switch (stat) { 19198160SWentao.Yang@Sun.COM case MAC_STAT_IPACKETS: 19208160SWentao.Yang@Sun.COM statsp->ipackets = val; 19218160SWentao.Yang@Sun.COM break; 19228160SWentao.Yang@Sun.COM 19238160SWentao.Yang@Sun.COM case MAC_STAT_IERRORS: 19248160SWentao.Yang@Sun.COM statsp->ierrors = val; 19258160SWentao.Yang@Sun.COM break; 19268160SWentao.Yang@Sun.COM 19278160SWentao.Yang@Sun.COM case MAC_STAT_OPACKETS: 19288160SWentao.Yang@Sun.COM statsp->opackets = val; 19298160SWentao.Yang@Sun.COM break; 19308160SWentao.Yang@Sun.COM 19318160SWentao.Yang@Sun.COM case MAC_STAT_OERRORS: 19328160SWentao.Yang@Sun.COM statsp->oerrors = val; 19338160SWentao.Yang@Sun.COM break; 19348160SWentao.Yang@Sun.COM 19358160SWentao.Yang@Sun.COM case MAC_STAT_RBYTES: 19368160SWentao.Yang@Sun.COM statsp->rbytes = val; 19378160SWentao.Yang@Sun.COM break; 19388160SWentao.Yang@Sun.COM 19398160SWentao.Yang@Sun.COM case MAC_STAT_OBYTES: 19408160SWentao.Yang@Sun.COM statsp->obytes = val; 19418160SWentao.Yang@Sun.COM break; 19428160SWentao.Yang@Sun.COM 19438160SWentao.Yang@Sun.COM case MAC_STAT_MULTIRCV: 19448160SWentao.Yang@Sun.COM statsp->multircv = val; 19458160SWentao.Yang@Sun.COM break; 19468160SWentao.Yang@Sun.COM 19478160SWentao.Yang@Sun.COM case MAC_STAT_MULTIXMT: 19488160SWentao.Yang@Sun.COM statsp->multixmt = val; 19498160SWentao.Yang@Sun.COM break; 19508160SWentao.Yang@Sun.COM 19518160SWentao.Yang@Sun.COM case MAC_STAT_BRDCSTRCV: 19528160SWentao.Yang@Sun.COM statsp->brdcstrcv = val; 19538160SWentao.Yang@Sun.COM break; 19548160SWentao.Yang@Sun.COM 19558160SWentao.Yang@Sun.COM case MAC_STAT_BRDCSTXMT: 19568160SWentao.Yang@Sun.COM statsp->brdcstxmt = val; 19578160SWentao.Yang@Sun.COM break; 19588160SWentao.Yang@Sun.COM 19598160SWentao.Yang@Sun.COM case MAC_STAT_NOXMTBUF: 19608160SWentao.Yang@Sun.COM statsp->noxmtbuf = val; 19618160SWentao.Yang@Sun.COM break; 19628160SWentao.Yang@Sun.COM 19638160SWentao.Yang@Sun.COM case MAC_STAT_NORCVBUF: 19648160SWentao.Yang@Sun.COM statsp->norcvbuf = val; 19658160SWentao.Yang@Sun.COM break; 19668160SWentao.Yang@Sun.COM 19678160SWentao.Yang@Sun.COM default: 19688160SWentao.Yang@Sun.COM /* 19698160SWentao.Yang@Sun.COM * parameters not interested. 19708160SWentao.Yang@Sun.COM */ 19718160SWentao.Yang@Sun.COM break; 19728160SWentao.Yang@Sun.COM } 19738160SWentao.Yang@Sun.COM } 19748160SWentao.Yang@Sun.COM } 19758160SWentao.Yang@Sun.COM } 19769336SSriharsha.Basavapatna@Sun.COM 197710309SSriharsha.Basavapatna@Sun.COM static boolean_t 197810309SSriharsha.Basavapatna@Sun.COM vnet_m_capab(void *arg, mac_capab_t cap, void *cap_data) 197910309SSriharsha.Basavapatna@Sun.COM { 198010309SSriharsha.Basavapatna@Sun.COM vnet_t *vnetp = (vnet_t *)arg; 198110309SSriharsha.Basavapatna@Sun.COM 198210309SSriharsha.Basavapatna@Sun.COM if (vnetp == NULL) { 198310309SSriharsha.Basavapatna@Sun.COM return (0); 198410309SSriharsha.Basavapatna@Sun.COM } 198510309SSriharsha.Basavapatna@Sun.COM 198610309SSriharsha.Basavapatna@Sun.COM switch (cap) { 198710309SSriharsha.Basavapatna@Sun.COM 198810309SSriharsha.Basavapatna@Sun.COM case MAC_CAPAB_RINGS: { 198910309SSriharsha.Basavapatna@Sun.COM 199010309SSriharsha.Basavapatna@Sun.COM mac_capab_rings_t *cap_rings = cap_data; 199110309SSriharsha.Basavapatna@Sun.COM /* 199210309SSriharsha.Basavapatna@Sun.COM * Rings Capability Notes: 199310309SSriharsha.Basavapatna@Sun.COM * We advertise rings to make use of the rings framework in 199410309SSriharsha.Basavapatna@Sun.COM * gldv3 mac layer, to improve the performance. This is 199510309SSriharsha.Basavapatna@Sun.COM * specifically needed when a Hybrid resource (with multiple 199610309SSriharsha.Basavapatna@Sun.COM * tx/rx hardware rings) is assigned to a vnet device. We also 199710309SSriharsha.Basavapatna@Sun.COM * leverage this for the normal case when no Hybrid resource is 199810309SSriharsha.Basavapatna@Sun.COM * assigned. 199910309SSriharsha.Basavapatna@Sun.COM * 200010309SSriharsha.Basavapatna@Sun.COM * Ring Allocation: 200110309SSriharsha.Basavapatna@Sun.COM * - TX path: 200210309SSriharsha.Basavapatna@Sun.COM * We expose a pseudo ring group with 2 pseudo tx rings (as 200310309SSriharsha.Basavapatna@Sun.COM * currently HybridIO exports only 2 rings) In the normal case, 200410309SSriharsha.Basavapatna@Sun.COM * transmit traffic that comes down to the driver through the 200510309SSriharsha.Basavapatna@Sun.COM * mri_tx (vnet_tx_ring_send()) entry point goes through the 200610309SSriharsha.Basavapatna@Sun.COM * distributed switching algorithm in vnet and gets transmitted 200710309SSriharsha.Basavapatna@Sun.COM * over a port/LDC in the vgen layer to either the vswitch or a 200810309SSriharsha.Basavapatna@Sun.COM * peer vnet. If and when a Hybrid resource is assigned to the 200910309SSriharsha.Basavapatna@Sun.COM * vnet, we obtain the tx ring information of the Hybrid device 201010309SSriharsha.Basavapatna@Sun.COM * (nxge) and map the pseudo rings 1:1 to the 2 hw tx rings. 201110309SSriharsha.Basavapatna@Sun.COM * Traffic being sent over the Hybrid resource by the mac layer 201210309SSriharsha.Basavapatna@Sun.COM * gets spread across both hw rings, as they are mapped to the 201310309SSriharsha.Basavapatna@Sun.COM * 2 pseudo tx rings in vnet. 201410309SSriharsha.Basavapatna@Sun.COM * 201510309SSriharsha.Basavapatna@Sun.COM * - RX path: 201610309SSriharsha.Basavapatna@Sun.COM * We expose a pseudo ring group with 3 pseudo rx rings (static 201710309SSriharsha.Basavapatna@Sun.COM * rings) initially. The first (default) pseudo rx ring is 201810309SSriharsha.Basavapatna@Sun.COM * reserved for the resource that connects to the vswitch 201910309SSriharsha.Basavapatna@Sun.COM * service. The next 2 rings are reserved for a Hybrid resource 202010309SSriharsha.Basavapatna@Sun.COM * that may be assigned to the vnet device. If and when a 202110309SSriharsha.Basavapatna@Sun.COM * Hybrid resource is assigned to the vnet, we obtain the rx 202210309SSriharsha.Basavapatna@Sun.COM * ring information of the Hybrid device (nxge) and map these 202310309SSriharsha.Basavapatna@Sun.COM * pseudo rings 1:1 to the 2 hw rx rings. For each additional 202410309SSriharsha.Basavapatna@Sun.COM * resource that connects to a peer vnet, we dynamically 202510309SSriharsha.Basavapatna@Sun.COM * allocate a pseudo rx ring and map it to that resource, when 202610309SSriharsha.Basavapatna@Sun.COM * the resource gets added; and the pseudo rx ring is 202710309SSriharsha.Basavapatna@Sun.COM * dynamically registered with the upper mac layer. We do the 202810309SSriharsha.Basavapatna@Sun.COM * reverse and unregister the ring with the mac layer when 202910309SSriharsha.Basavapatna@Sun.COM * the resource gets removed. 203010309SSriharsha.Basavapatna@Sun.COM * 203110309SSriharsha.Basavapatna@Sun.COM * Synchronization notes: 203210309SSriharsha.Basavapatna@Sun.COM * We don't need any lock to protect members of ring structure, 203310309SSriharsha.Basavapatna@Sun.COM * specifically ringp->hw_rh, in either the TX or the RX ring, 203410309SSriharsha.Basavapatna@Sun.COM * as explained below. 203510309SSriharsha.Basavapatna@Sun.COM * - TX ring: 203610309SSriharsha.Basavapatna@Sun.COM * ring->hw_rh is initialized only when a Hybrid resource is 203710309SSriharsha.Basavapatna@Sun.COM * associated; and gets referenced only in vnet_hio_tx(). The 203810309SSriharsha.Basavapatna@Sun.COM * Hybrid resource itself is available in fdb only after tx 203910309SSriharsha.Basavapatna@Sun.COM * hwrings are found and mapped; i.e, in vio_net_resource_reg() 204010309SSriharsha.Basavapatna@Sun.COM * we call vnet_bind_rings() first and then call 204110309SSriharsha.Basavapatna@Sun.COM * vnet_start_resources() which adds an entry to fdb. For 204210309SSriharsha.Basavapatna@Sun.COM * traffic going over LDC resources, we don't reference 204310309SSriharsha.Basavapatna@Sun.COM * ring->hw_rh at all. 204410309SSriharsha.Basavapatna@Sun.COM * - RX ring: 204510309SSriharsha.Basavapatna@Sun.COM * For rings mapped to Hybrid resource ring->hw_rh is 204610309SSriharsha.Basavapatna@Sun.COM * initialized and only then do we add the rx callback for 204710309SSriharsha.Basavapatna@Sun.COM * the underlying Hybrid resource; we disable callbacks before 204810309SSriharsha.Basavapatna@Sun.COM * we unmap ring->hw_rh. For rings mapped to LDC resources, we 204910309SSriharsha.Basavapatna@Sun.COM * stop the rx callbacks (in vgen) before we remove ring->hw_rh 205010309SSriharsha.Basavapatna@Sun.COM * (vio_net_resource_unreg()). 205110309SSriharsha.Basavapatna@Sun.COM */ 205210309SSriharsha.Basavapatna@Sun.COM 205310309SSriharsha.Basavapatna@Sun.COM if (cap_rings->mr_type == MAC_RING_TYPE_RX) { 205410309SSriharsha.Basavapatna@Sun.COM cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC; 205510309SSriharsha.Basavapatna@Sun.COM 205610309SSriharsha.Basavapatna@Sun.COM /* 205710309SSriharsha.Basavapatna@Sun.COM * The ring_cnt for rx grp is initialized in 205810309SSriharsha.Basavapatna@Sun.COM * vnet_ring_grp_init(). Later, the ring_cnt gets 205910309SSriharsha.Basavapatna@Sun.COM * updated dynamically whenever LDC resources are added 206010309SSriharsha.Basavapatna@Sun.COM * or removed. 206110309SSriharsha.Basavapatna@Sun.COM */ 206210309SSriharsha.Basavapatna@Sun.COM cap_rings->mr_rnum = vnetp->rx_grp[0].ring_cnt; 206310309SSriharsha.Basavapatna@Sun.COM cap_rings->mr_rget = vnet_get_ring; 206410309SSriharsha.Basavapatna@Sun.COM 206510309SSriharsha.Basavapatna@Sun.COM cap_rings->mr_gnum = VNET_NUM_PSEUDO_GROUPS; 206610309SSriharsha.Basavapatna@Sun.COM cap_rings->mr_gget = vnet_get_group; 206710309SSriharsha.Basavapatna@Sun.COM cap_rings->mr_gaddring = NULL; 206810309SSriharsha.Basavapatna@Sun.COM cap_rings->mr_gremring = NULL; 206910309SSriharsha.Basavapatna@Sun.COM } else { 207010309SSriharsha.Basavapatna@Sun.COM cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC; 207110309SSriharsha.Basavapatna@Sun.COM 207210309SSriharsha.Basavapatna@Sun.COM /* 207310309SSriharsha.Basavapatna@Sun.COM * The ring_cnt for tx grp is initialized in 207410309SSriharsha.Basavapatna@Sun.COM * vnet_ring_grp_init() and remains constant, as we 207510309SSriharsha.Basavapatna@Sun.COM * do not support dymanic tx rings for now. 207610309SSriharsha.Basavapatna@Sun.COM */ 207710309SSriharsha.Basavapatna@Sun.COM cap_rings->mr_rnum = vnetp->tx_grp[0].ring_cnt; 207810309SSriharsha.Basavapatna@Sun.COM cap_rings->mr_rget = vnet_get_ring; 207910309SSriharsha.Basavapatna@Sun.COM 208010309SSriharsha.Basavapatna@Sun.COM /* 208110309SSriharsha.Basavapatna@Sun.COM * Transmit rings are not grouped; i.e, the number of 208210309SSriharsha.Basavapatna@Sun.COM * transmit ring groups advertised should be set to 0. 208310309SSriharsha.Basavapatna@Sun.COM */ 208410309SSriharsha.Basavapatna@Sun.COM cap_rings->mr_gnum = 0; 208510309SSriharsha.Basavapatna@Sun.COM 208610309SSriharsha.Basavapatna@Sun.COM cap_rings->mr_gget = vnet_get_group; 208710309SSriharsha.Basavapatna@Sun.COM cap_rings->mr_gaddring = NULL; 208810309SSriharsha.Basavapatna@Sun.COM cap_rings->mr_gremring = NULL; 208910309SSriharsha.Basavapatna@Sun.COM } 209010309SSriharsha.Basavapatna@Sun.COM return (B_TRUE); 209110309SSriharsha.Basavapatna@Sun.COM 209210309SSriharsha.Basavapatna@Sun.COM } 209310309SSriharsha.Basavapatna@Sun.COM 209410309SSriharsha.Basavapatna@Sun.COM default: 209510309SSriharsha.Basavapatna@Sun.COM break; 209610309SSriharsha.Basavapatna@Sun.COM 209710309SSriharsha.Basavapatna@Sun.COM } 209810309SSriharsha.Basavapatna@Sun.COM 209910309SSriharsha.Basavapatna@Sun.COM return (B_FALSE); 210010309SSriharsha.Basavapatna@Sun.COM } 210110309SSriharsha.Basavapatna@Sun.COM 210210309SSriharsha.Basavapatna@Sun.COM /* 210310309SSriharsha.Basavapatna@Sun.COM * Callback funtion for MAC layer to get ring information. 210410309SSriharsha.Basavapatna@Sun.COM */ 210510309SSriharsha.Basavapatna@Sun.COM static void 210610309SSriharsha.Basavapatna@Sun.COM vnet_get_ring(void *arg, mac_ring_type_t rtype, const int g_index, 210710309SSriharsha.Basavapatna@Sun.COM const int r_index, mac_ring_info_t *infop, mac_ring_handle_t r_handle) 210810309SSriharsha.Basavapatna@Sun.COM { 210910309SSriharsha.Basavapatna@Sun.COM vnet_t *vnetp = arg; 211010309SSriharsha.Basavapatna@Sun.COM 211110309SSriharsha.Basavapatna@Sun.COM switch (rtype) { 211210309SSriharsha.Basavapatna@Sun.COM 211310309SSriharsha.Basavapatna@Sun.COM case MAC_RING_TYPE_RX: { 211410309SSriharsha.Basavapatna@Sun.COM 211510309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_group_t *rx_grp; 211610309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_ring_t *rx_ringp; 211710309SSriharsha.Basavapatna@Sun.COM mac_intr_t *mintr; 211810309SSriharsha.Basavapatna@Sun.COM 211910309SSriharsha.Basavapatna@Sun.COM /* We advertised only one RX group */ 212010309SSriharsha.Basavapatna@Sun.COM ASSERT(g_index == 0); 212110309SSriharsha.Basavapatna@Sun.COM rx_grp = &vnetp->rx_grp[g_index]; 212210309SSriharsha.Basavapatna@Sun.COM 212310309SSriharsha.Basavapatna@Sun.COM /* Check the current # of rings in the rx group */ 212410309SSriharsha.Basavapatna@Sun.COM ASSERT((r_index >= 0) && (r_index < rx_grp->max_ring_cnt)); 212510309SSriharsha.Basavapatna@Sun.COM 212610309SSriharsha.Basavapatna@Sun.COM /* Get the ring based on the index */ 212710309SSriharsha.Basavapatna@Sun.COM rx_ringp = &rx_grp->rings[r_index]; 212810309SSriharsha.Basavapatna@Sun.COM 212910309SSriharsha.Basavapatna@Sun.COM rx_ringp->handle = r_handle; 213010309SSriharsha.Basavapatna@Sun.COM /* 213110309SSriharsha.Basavapatna@Sun.COM * Note: we don't need to save the incoming r_index in rx_ring, 213210309SSriharsha.Basavapatna@Sun.COM * as vnet_ring_grp_init() would have initialized the index for 213310309SSriharsha.Basavapatna@Sun.COM * each ring in the array. 213410309SSriharsha.Basavapatna@Sun.COM */ 213510309SSriharsha.Basavapatna@Sun.COM rx_ringp->grp = rx_grp; 213610309SSriharsha.Basavapatna@Sun.COM rx_ringp->vnetp = vnetp; 213710309SSriharsha.Basavapatna@Sun.COM 213810309SSriharsha.Basavapatna@Sun.COM mintr = &infop->mri_intr; 213910309SSriharsha.Basavapatna@Sun.COM mintr->mi_handle = (mac_intr_handle_t)rx_ringp; 214010309SSriharsha.Basavapatna@Sun.COM mintr->mi_enable = (mac_intr_enable_t)vnet_ring_enable_intr; 214110309SSriharsha.Basavapatna@Sun.COM mintr->mi_disable = (mac_intr_disable_t)vnet_ring_disable_intr; 214210309SSriharsha.Basavapatna@Sun.COM 214310309SSriharsha.Basavapatna@Sun.COM infop->mri_driver = (mac_ring_driver_t)rx_ringp; 214410309SSriharsha.Basavapatna@Sun.COM infop->mri_start = vnet_rx_ring_start; 214510309SSriharsha.Basavapatna@Sun.COM infop->mri_stop = vnet_rx_ring_stop; 214610309SSriharsha.Basavapatna@Sun.COM 214710309SSriharsha.Basavapatna@Sun.COM /* Set the poll function, as this is an rx ring */ 214810309SSriharsha.Basavapatna@Sun.COM infop->mri_poll = vnet_rx_poll; 214910309SSriharsha.Basavapatna@Sun.COM 215010309SSriharsha.Basavapatna@Sun.COM break; 215110309SSriharsha.Basavapatna@Sun.COM } 215210309SSriharsha.Basavapatna@Sun.COM 215310309SSriharsha.Basavapatna@Sun.COM case MAC_RING_TYPE_TX: { 215410309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_tx_group_t *tx_grp; 215510309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_tx_ring_t *tx_ringp; 215610309SSriharsha.Basavapatna@Sun.COM 215710309SSriharsha.Basavapatna@Sun.COM /* 215810309SSriharsha.Basavapatna@Sun.COM * No need to check grp index; mac layer passes -1 for it. 215910309SSriharsha.Basavapatna@Sun.COM */ 216010309SSriharsha.Basavapatna@Sun.COM tx_grp = &vnetp->tx_grp[0]; 216110309SSriharsha.Basavapatna@Sun.COM 216210309SSriharsha.Basavapatna@Sun.COM /* Check the # of rings in the tx group */ 216310309SSriharsha.Basavapatna@Sun.COM ASSERT((r_index >= 0) && (r_index < tx_grp->ring_cnt)); 216410309SSriharsha.Basavapatna@Sun.COM 216510309SSriharsha.Basavapatna@Sun.COM /* Get the ring based on the index */ 216610309SSriharsha.Basavapatna@Sun.COM tx_ringp = &tx_grp->rings[r_index]; 216710309SSriharsha.Basavapatna@Sun.COM 216810309SSriharsha.Basavapatna@Sun.COM tx_ringp->handle = r_handle; 216910309SSriharsha.Basavapatna@Sun.COM tx_ringp->index = r_index; 217010309SSriharsha.Basavapatna@Sun.COM tx_ringp->grp = tx_grp; 217110309SSriharsha.Basavapatna@Sun.COM tx_ringp->vnetp = vnetp; 217210309SSriharsha.Basavapatna@Sun.COM 217310309SSriharsha.Basavapatna@Sun.COM infop->mri_driver = (mac_ring_driver_t)tx_ringp; 217410309SSriharsha.Basavapatna@Sun.COM infop->mri_start = vnet_tx_ring_start; 217510309SSriharsha.Basavapatna@Sun.COM infop->mri_stop = vnet_tx_ring_stop; 217610309SSriharsha.Basavapatna@Sun.COM 217710309SSriharsha.Basavapatna@Sun.COM /* Set the transmit function, as this is a tx ring */ 217810309SSriharsha.Basavapatna@Sun.COM infop->mri_tx = vnet_tx_ring_send; 217910309SSriharsha.Basavapatna@Sun.COM 218010309SSriharsha.Basavapatna@Sun.COM break; 218110309SSriharsha.Basavapatna@Sun.COM } 218210309SSriharsha.Basavapatna@Sun.COM 218310309SSriharsha.Basavapatna@Sun.COM default: 218410309SSriharsha.Basavapatna@Sun.COM break; 218510309SSriharsha.Basavapatna@Sun.COM } 218610309SSriharsha.Basavapatna@Sun.COM } 218710309SSriharsha.Basavapatna@Sun.COM 218810309SSriharsha.Basavapatna@Sun.COM /* 218910309SSriharsha.Basavapatna@Sun.COM * Callback funtion for MAC layer to get group information. 219010309SSriharsha.Basavapatna@Sun.COM */ 219110309SSriharsha.Basavapatna@Sun.COM static void 219210309SSriharsha.Basavapatna@Sun.COM vnet_get_group(void *arg, mac_ring_type_t type, const int index, 219310309SSriharsha.Basavapatna@Sun.COM mac_group_info_t *infop, mac_group_handle_t handle) 219410309SSriharsha.Basavapatna@Sun.COM { 219510309SSriharsha.Basavapatna@Sun.COM vnet_t *vnetp = (vnet_t *)arg; 219610309SSriharsha.Basavapatna@Sun.COM 219710309SSriharsha.Basavapatna@Sun.COM switch (type) { 219810309SSriharsha.Basavapatna@Sun.COM 219910309SSriharsha.Basavapatna@Sun.COM case MAC_RING_TYPE_RX: 220010309SSriharsha.Basavapatna@Sun.COM { 220110309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_group_t *rx_grp; 220210309SSriharsha.Basavapatna@Sun.COM 220310309SSriharsha.Basavapatna@Sun.COM /* We advertised only one RX group */ 220410309SSriharsha.Basavapatna@Sun.COM ASSERT(index == 0); 220510309SSriharsha.Basavapatna@Sun.COM 220610309SSriharsha.Basavapatna@Sun.COM rx_grp = &vnetp->rx_grp[index]; 220710309SSriharsha.Basavapatna@Sun.COM rx_grp->handle = handle; 220810309SSriharsha.Basavapatna@Sun.COM rx_grp->index = index; 220910309SSriharsha.Basavapatna@Sun.COM rx_grp->vnetp = vnetp; 221010309SSriharsha.Basavapatna@Sun.COM 221110309SSriharsha.Basavapatna@Sun.COM infop->mgi_driver = (mac_group_driver_t)rx_grp; 221210309SSriharsha.Basavapatna@Sun.COM infop->mgi_start = NULL; 221310309SSriharsha.Basavapatna@Sun.COM infop->mgi_stop = NULL; 221410309SSriharsha.Basavapatna@Sun.COM infop->mgi_addmac = vnet_addmac; 221510309SSriharsha.Basavapatna@Sun.COM infop->mgi_remmac = vnet_remmac; 221610309SSriharsha.Basavapatna@Sun.COM infop->mgi_count = rx_grp->ring_cnt; 221710309SSriharsha.Basavapatna@Sun.COM 221810309SSriharsha.Basavapatna@Sun.COM break; 221910309SSriharsha.Basavapatna@Sun.COM } 222010309SSriharsha.Basavapatna@Sun.COM 222110309SSriharsha.Basavapatna@Sun.COM case MAC_RING_TYPE_TX: 222210309SSriharsha.Basavapatna@Sun.COM { 222310309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_tx_group_t *tx_grp; 222410309SSriharsha.Basavapatna@Sun.COM 222510309SSriharsha.Basavapatna@Sun.COM /* We advertised only one TX group */ 222610309SSriharsha.Basavapatna@Sun.COM ASSERT(index == 0); 222710309SSriharsha.Basavapatna@Sun.COM 222810309SSriharsha.Basavapatna@Sun.COM tx_grp = &vnetp->tx_grp[index]; 222910309SSriharsha.Basavapatna@Sun.COM tx_grp->handle = handle; 223010309SSriharsha.Basavapatna@Sun.COM tx_grp->index = index; 223110309SSriharsha.Basavapatna@Sun.COM tx_grp->vnetp = vnetp; 223210309SSriharsha.Basavapatna@Sun.COM 223310309SSriharsha.Basavapatna@Sun.COM infop->mgi_driver = (mac_group_driver_t)tx_grp; 223410309SSriharsha.Basavapatna@Sun.COM infop->mgi_start = NULL; 223510309SSriharsha.Basavapatna@Sun.COM infop->mgi_stop = NULL; 223610309SSriharsha.Basavapatna@Sun.COM infop->mgi_addmac = NULL; 223710309SSriharsha.Basavapatna@Sun.COM infop->mgi_remmac = NULL; 223810309SSriharsha.Basavapatna@Sun.COM infop->mgi_count = VNET_NUM_PSEUDO_TXRINGS; 223910309SSriharsha.Basavapatna@Sun.COM 224010309SSriharsha.Basavapatna@Sun.COM break; 224110309SSriharsha.Basavapatna@Sun.COM } 224210309SSriharsha.Basavapatna@Sun.COM 224310309SSriharsha.Basavapatna@Sun.COM default: 224410309SSriharsha.Basavapatna@Sun.COM break; 224510309SSriharsha.Basavapatna@Sun.COM 224610309SSriharsha.Basavapatna@Sun.COM } 224710309SSriharsha.Basavapatna@Sun.COM } 224810309SSriharsha.Basavapatna@Sun.COM 224910309SSriharsha.Basavapatna@Sun.COM static int 225010309SSriharsha.Basavapatna@Sun.COM vnet_rx_ring_start(mac_ring_driver_t arg, uint64_t mr_gen_num) 225110309SSriharsha.Basavapatna@Sun.COM { 225210309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_ring_t *rx_ringp = (vnet_pseudo_rx_ring_t *)arg; 225310309SSriharsha.Basavapatna@Sun.COM int err; 225410309SSriharsha.Basavapatna@Sun.COM 225510309SSriharsha.Basavapatna@Sun.COM /* 225610309SSriharsha.Basavapatna@Sun.COM * If this ring is mapped to a LDC resource, simply mark the state to 225710309SSriharsha.Basavapatna@Sun.COM * indicate the ring is started and return. 225810309SSriharsha.Basavapatna@Sun.COM */ 225910309SSriharsha.Basavapatna@Sun.COM if ((rx_ringp->state & 226010309SSriharsha.Basavapatna@Sun.COM (VNET_RXRING_LDC_SERVICE|VNET_RXRING_LDC_GUEST)) != 0) { 226110309SSriharsha.Basavapatna@Sun.COM rx_ringp->gen_num = mr_gen_num; 226210309SSriharsha.Basavapatna@Sun.COM rx_ringp->state |= VNET_RXRING_STARTED; 226310309SSriharsha.Basavapatna@Sun.COM return (0); 226410309SSriharsha.Basavapatna@Sun.COM } 226510309SSriharsha.Basavapatna@Sun.COM 226610309SSriharsha.Basavapatna@Sun.COM ASSERT((rx_ringp->state & VNET_RXRING_HYBRID) != 0); 226710309SSriharsha.Basavapatna@Sun.COM 226810309SSriharsha.Basavapatna@Sun.COM /* 226910309SSriharsha.Basavapatna@Sun.COM * This must be a ring reserved for a hwring. If the hwring is not 227010309SSriharsha.Basavapatna@Sun.COM * bound yet, simply mark the state to indicate the ring is started and 227110309SSriharsha.Basavapatna@Sun.COM * return. If and when a hybrid resource is activated for this vnet 227210309SSriharsha.Basavapatna@Sun.COM * device, we will bind the hwring and start it then. If a hwring is 227310309SSriharsha.Basavapatna@Sun.COM * already bound, start it now. 227410309SSriharsha.Basavapatna@Sun.COM */ 227510309SSriharsha.Basavapatna@Sun.COM if (rx_ringp->hw_rh == NULL) { 227610309SSriharsha.Basavapatna@Sun.COM rx_ringp->gen_num = mr_gen_num; 227710309SSriharsha.Basavapatna@Sun.COM rx_ringp->state |= VNET_RXRING_STARTED; 227810309SSriharsha.Basavapatna@Sun.COM return (0); 227910309SSriharsha.Basavapatna@Sun.COM } 228010309SSriharsha.Basavapatna@Sun.COM 228110309SSriharsha.Basavapatna@Sun.COM err = mac_hwring_start(rx_ringp->hw_rh); 228210309SSriharsha.Basavapatna@Sun.COM if (err == 0) { 228310309SSriharsha.Basavapatna@Sun.COM rx_ringp->gen_num = mr_gen_num; 228410309SSriharsha.Basavapatna@Sun.COM rx_ringp->state |= VNET_RXRING_STARTED; 228510309SSriharsha.Basavapatna@Sun.COM } else { 228610309SSriharsha.Basavapatna@Sun.COM err = ENXIO; 228710309SSriharsha.Basavapatna@Sun.COM } 228810309SSriharsha.Basavapatna@Sun.COM 228910309SSriharsha.Basavapatna@Sun.COM return (err); 229010309SSriharsha.Basavapatna@Sun.COM } 229110309SSriharsha.Basavapatna@Sun.COM 229210309SSriharsha.Basavapatna@Sun.COM static void 229310309SSriharsha.Basavapatna@Sun.COM vnet_rx_ring_stop(mac_ring_driver_t arg) 229410309SSriharsha.Basavapatna@Sun.COM { 229510309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_ring_t *rx_ringp = (vnet_pseudo_rx_ring_t *)arg; 229610309SSriharsha.Basavapatna@Sun.COM 229710309SSriharsha.Basavapatna@Sun.COM /* 229810309SSriharsha.Basavapatna@Sun.COM * If this ring is mapped to a LDC resource, simply mark the state to 229910309SSriharsha.Basavapatna@Sun.COM * indicate the ring is now stopped and return. 230010309SSriharsha.Basavapatna@Sun.COM */ 230110309SSriharsha.Basavapatna@Sun.COM if ((rx_ringp->state & 230210309SSriharsha.Basavapatna@Sun.COM (VNET_RXRING_LDC_SERVICE|VNET_RXRING_LDC_GUEST)) != 0) { 230310309SSriharsha.Basavapatna@Sun.COM rx_ringp->state &= ~VNET_RXRING_STARTED; 230410439SWentao.Yang@Sun.COM return; 230510309SSriharsha.Basavapatna@Sun.COM } 230610309SSriharsha.Basavapatna@Sun.COM 230710309SSriharsha.Basavapatna@Sun.COM ASSERT((rx_ringp->state & VNET_RXRING_HYBRID) != 0); 230810309SSriharsha.Basavapatna@Sun.COM 230910309SSriharsha.Basavapatna@Sun.COM /* 231010309SSriharsha.Basavapatna@Sun.COM * This must be a ring reserved for a hwring. If the hwring is not 231110309SSriharsha.Basavapatna@Sun.COM * bound yet, simply mark the state to indicate the ring is stopped and 231210309SSriharsha.Basavapatna@Sun.COM * return. If a hwring is already bound, stop it now. 231310309SSriharsha.Basavapatna@Sun.COM */ 231410309SSriharsha.Basavapatna@Sun.COM if (rx_ringp->hw_rh == NULL) { 231510309SSriharsha.Basavapatna@Sun.COM rx_ringp->state &= ~VNET_RXRING_STARTED; 231610309SSriharsha.Basavapatna@Sun.COM return; 231710309SSriharsha.Basavapatna@Sun.COM } 231810309SSriharsha.Basavapatna@Sun.COM 231910309SSriharsha.Basavapatna@Sun.COM mac_hwring_stop(rx_ringp->hw_rh); 232010309SSriharsha.Basavapatna@Sun.COM rx_ringp->state &= ~VNET_RXRING_STARTED; 232110309SSriharsha.Basavapatna@Sun.COM } 232210309SSriharsha.Basavapatna@Sun.COM 232310309SSriharsha.Basavapatna@Sun.COM /* ARGSUSED */ 232410309SSriharsha.Basavapatna@Sun.COM static int 232510309SSriharsha.Basavapatna@Sun.COM vnet_tx_ring_start(mac_ring_driver_t arg, uint64_t mr_gen_num) 232610309SSriharsha.Basavapatna@Sun.COM { 232710309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_tx_ring_t *tx_ringp = (vnet_pseudo_tx_ring_t *)arg; 232810309SSriharsha.Basavapatna@Sun.COM 232910309SSriharsha.Basavapatna@Sun.COM tx_ringp->state |= VNET_TXRING_STARTED; 233010309SSriharsha.Basavapatna@Sun.COM return (0); 233110309SSriharsha.Basavapatna@Sun.COM } 233210309SSriharsha.Basavapatna@Sun.COM 233310309SSriharsha.Basavapatna@Sun.COM static void 233410309SSriharsha.Basavapatna@Sun.COM vnet_tx_ring_stop(mac_ring_driver_t arg) 233510309SSriharsha.Basavapatna@Sun.COM { 233610309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_tx_ring_t *tx_ringp = (vnet_pseudo_tx_ring_t *)arg; 233710309SSriharsha.Basavapatna@Sun.COM 233810309SSriharsha.Basavapatna@Sun.COM tx_ringp->state &= ~VNET_TXRING_STARTED; 233910309SSriharsha.Basavapatna@Sun.COM } 234010309SSriharsha.Basavapatna@Sun.COM 234110309SSriharsha.Basavapatna@Sun.COM /* 234210309SSriharsha.Basavapatna@Sun.COM * Disable polling for a ring and enable its interrupt. 234310309SSriharsha.Basavapatna@Sun.COM */ 234410309SSriharsha.Basavapatna@Sun.COM static int 234510309SSriharsha.Basavapatna@Sun.COM vnet_ring_enable_intr(void *arg) 234610309SSriharsha.Basavapatna@Sun.COM { 234710309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_ring_t *rx_ringp = (vnet_pseudo_rx_ring_t *)arg; 234810309SSriharsha.Basavapatna@Sun.COM vnet_res_t *vresp; 234910309SSriharsha.Basavapatna@Sun.COM 235010309SSriharsha.Basavapatna@Sun.COM if (rx_ringp->hw_rh == NULL) { 235110309SSriharsha.Basavapatna@Sun.COM /* 235210309SSriharsha.Basavapatna@Sun.COM * Ring enable intr func is being invoked, but the ring is 235310309SSriharsha.Basavapatna@Sun.COM * not bound to any underlying resource ? This must be a ring 235410309SSriharsha.Basavapatna@Sun.COM * reserved for Hybrid resource and no such resource has been 235510309SSriharsha.Basavapatna@Sun.COM * assigned to this vnet device yet. We simply return success. 235610309SSriharsha.Basavapatna@Sun.COM */ 235710309SSriharsha.Basavapatna@Sun.COM ASSERT((rx_ringp->state & VNET_RXRING_HYBRID) != 0); 235810309SSriharsha.Basavapatna@Sun.COM return (0); 235910309SSriharsha.Basavapatna@Sun.COM } 236010309SSriharsha.Basavapatna@Sun.COM 236110309SSriharsha.Basavapatna@Sun.COM /* 236210309SSriharsha.Basavapatna@Sun.COM * The rx ring has been bound to either a LDC or a Hybrid resource. 236310309SSriharsha.Basavapatna@Sun.COM * Call the appropriate function to enable interrupts for the ring. 236410309SSriharsha.Basavapatna@Sun.COM */ 236510309SSriharsha.Basavapatna@Sun.COM if (rx_ringp->state & VNET_RXRING_HYBRID) { 236610309SSriharsha.Basavapatna@Sun.COM return (mac_hwring_enable_intr(rx_ringp->hw_rh)); 236710309SSriharsha.Basavapatna@Sun.COM } else { 236810309SSriharsha.Basavapatna@Sun.COM vresp = (vnet_res_t *)rx_ringp->hw_rh; 236910309SSriharsha.Basavapatna@Sun.COM return (vgen_enable_intr(vresp->macreg.m_driver)); 237010309SSriharsha.Basavapatna@Sun.COM } 237110309SSriharsha.Basavapatna@Sun.COM } 237210309SSriharsha.Basavapatna@Sun.COM 237310309SSriharsha.Basavapatna@Sun.COM /* 237410309SSriharsha.Basavapatna@Sun.COM * Enable polling for a ring and disable its interrupt. 237510309SSriharsha.Basavapatna@Sun.COM */ 237610309SSriharsha.Basavapatna@Sun.COM static int 237710309SSriharsha.Basavapatna@Sun.COM vnet_ring_disable_intr(void *arg) 237810309SSriharsha.Basavapatna@Sun.COM { 237910309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_ring_t *rx_ringp = (vnet_pseudo_rx_ring_t *)arg; 238010309SSriharsha.Basavapatna@Sun.COM vnet_res_t *vresp; 238110309SSriharsha.Basavapatna@Sun.COM 238210309SSriharsha.Basavapatna@Sun.COM if (rx_ringp->hw_rh == NULL) { 238310309SSriharsha.Basavapatna@Sun.COM /* 238410309SSriharsha.Basavapatna@Sun.COM * Ring disable intr func is being invoked, but the ring is 238510309SSriharsha.Basavapatna@Sun.COM * not bound to any underlying resource ? This must be a ring 238610309SSriharsha.Basavapatna@Sun.COM * reserved for Hybrid resource and no such resource has been 238710309SSriharsha.Basavapatna@Sun.COM * assigned to this vnet device yet. We simply return success. 238810309SSriharsha.Basavapatna@Sun.COM */ 238910309SSriharsha.Basavapatna@Sun.COM ASSERT((rx_ringp->state & VNET_RXRING_HYBRID) != 0); 239010309SSriharsha.Basavapatna@Sun.COM return (0); 239110309SSriharsha.Basavapatna@Sun.COM } 239210309SSriharsha.Basavapatna@Sun.COM 239310309SSriharsha.Basavapatna@Sun.COM /* 239410309SSriharsha.Basavapatna@Sun.COM * The rx ring has been bound to either a LDC or a Hybrid resource. 239510309SSriharsha.Basavapatna@Sun.COM * Call the appropriate function to disable interrupts for the ring. 239610309SSriharsha.Basavapatna@Sun.COM */ 239710309SSriharsha.Basavapatna@Sun.COM if (rx_ringp->state & VNET_RXRING_HYBRID) { 239810309SSriharsha.Basavapatna@Sun.COM return (mac_hwring_disable_intr(rx_ringp->hw_rh)); 239910309SSriharsha.Basavapatna@Sun.COM } else { 240010309SSriharsha.Basavapatna@Sun.COM vresp = (vnet_res_t *)rx_ringp->hw_rh; 240110309SSriharsha.Basavapatna@Sun.COM return (vgen_disable_intr(vresp->macreg.m_driver)); 240210309SSriharsha.Basavapatna@Sun.COM } 240310309SSriharsha.Basavapatna@Sun.COM } 240410309SSriharsha.Basavapatna@Sun.COM 240510309SSriharsha.Basavapatna@Sun.COM /* 240610309SSriharsha.Basavapatna@Sun.COM * Poll 'bytes_to_pickup' bytes of message from the rx ring. 240710309SSriharsha.Basavapatna@Sun.COM */ 240810309SSriharsha.Basavapatna@Sun.COM static mblk_t * 240910309SSriharsha.Basavapatna@Sun.COM vnet_rx_poll(void *arg, int bytes_to_pickup) 241010309SSriharsha.Basavapatna@Sun.COM { 241110309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_ring_t *rx_ringp = (vnet_pseudo_rx_ring_t *)arg; 241210309SSriharsha.Basavapatna@Sun.COM mblk_t *mp = NULL; 241310309SSriharsha.Basavapatna@Sun.COM vnet_res_t *vresp; 241410309SSriharsha.Basavapatna@Sun.COM vnet_t *vnetp = rx_ringp->vnetp; 241510309SSriharsha.Basavapatna@Sun.COM 241610309SSriharsha.Basavapatna@Sun.COM if (rx_ringp->hw_rh == NULL) { 241710309SSriharsha.Basavapatna@Sun.COM return (NULL); 241810309SSriharsha.Basavapatna@Sun.COM } 241910309SSriharsha.Basavapatna@Sun.COM 242010309SSriharsha.Basavapatna@Sun.COM if (rx_ringp->state & VNET_RXRING_HYBRID) { 242110309SSriharsha.Basavapatna@Sun.COM mp = mac_hwring_poll(rx_ringp->hw_rh, bytes_to_pickup); 242210309SSriharsha.Basavapatna@Sun.COM /* 242310309SSriharsha.Basavapatna@Sun.COM * Packets received over a hybrid resource need additional 242410309SSriharsha.Basavapatna@Sun.COM * processing to remove the tag, for the pvid case. The 242510309SSriharsha.Basavapatna@Sun.COM * underlying resource is not aware of the vnet's pvid and thus 242610309SSriharsha.Basavapatna@Sun.COM * packets are received with the vlan tag in the header; unlike 242710309SSriharsha.Basavapatna@Sun.COM * packets that are received over a ldc channel in which case 242810309SSriharsha.Basavapatna@Sun.COM * the peer vnet/vsw would have already removed the tag. 242910309SSriharsha.Basavapatna@Sun.COM */ 243010309SSriharsha.Basavapatna@Sun.COM if (vnetp->pvid != vnetp->default_vlan_id) { 243110309SSriharsha.Basavapatna@Sun.COM vnet_rx_frames_untag(vnetp->pvid, &mp); 243210309SSriharsha.Basavapatna@Sun.COM } 243310309SSriharsha.Basavapatna@Sun.COM } else { 243410309SSriharsha.Basavapatna@Sun.COM vresp = (vnet_res_t *)rx_ringp->hw_rh; 243510309SSriharsha.Basavapatna@Sun.COM mp = vgen_poll(vresp->macreg.m_driver, bytes_to_pickup); 243610309SSriharsha.Basavapatna@Sun.COM } 243710309SSriharsha.Basavapatna@Sun.COM return (mp); 243810309SSriharsha.Basavapatna@Sun.COM } 243910309SSriharsha.Basavapatna@Sun.COM 244010309SSriharsha.Basavapatna@Sun.COM /* ARGSUSED */ 244110309SSriharsha.Basavapatna@Sun.COM void 244210309SSriharsha.Basavapatna@Sun.COM vnet_hio_rx_cb(void *arg, mac_resource_handle_t mrh, mblk_t *mp, 244310309SSriharsha.Basavapatna@Sun.COM boolean_t loopback) 244410309SSriharsha.Basavapatna@Sun.COM { 244510309SSriharsha.Basavapatna@Sun.COM vnet_t *vnetp = (vnet_t *)arg; 244610309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_ring_t *ringp = (vnet_pseudo_rx_ring_t *)mrh; 244710309SSriharsha.Basavapatna@Sun.COM 244810309SSriharsha.Basavapatna@Sun.COM /* 244910309SSriharsha.Basavapatna@Sun.COM * Packets received over a hybrid resource need additional processing 245010309SSriharsha.Basavapatna@Sun.COM * to remove the tag, for the pvid case. The underlying resource is 245110309SSriharsha.Basavapatna@Sun.COM * not aware of the vnet's pvid and thus packets are received with the 245210309SSriharsha.Basavapatna@Sun.COM * vlan tag in the header; unlike packets that are received over a ldc 245310309SSriharsha.Basavapatna@Sun.COM * channel in which case the peer vnet/vsw would have already removed 245410309SSriharsha.Basavapatna@Sun.COM * the tag. 245510309SSriharsha.Basavapatna@Sun.COM */ 245610309SSriharsha.Basavapatna@Sun.COM if (vnetp->pvid != vnetp->default_vlan_id) { 245710309SSriharsha.Basavapatna@Sun.COM vnet_rx_frames_untag(vnetp->pvid, &mp); 245810309SSriharsha.Basavapatna@Sun.COM if (mp == NULL) { 245910309SSriharsha.Basavapatna@Sun.COM return; 246010309SSriharsha.Basavapatna@Sun.COM } 246110309SSriharsha.Basavapatna@Sun.COM } 246210309SSriharsha.Basavapatna@Sun.COM mac_rx_ring(vnetp->mh, ringp->handle, mp, ringp->gen_num); 246310309SSriharsha.Basavapatna@Sun.COM } 246410309SSriharsha.Basavapatna@Sun.COM 246510309SSriharsha.Basavapatna@Sun.COM static int 246610309SSriharsha.Basavapatna@Sun.COM vnet_addmac(void *arg, const uint8_t *mac_addr) 246710309SSriharsha.Basavapatna@Sun.COM { 246810309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_group_t *rx_grp = (vnet_pseudo_rx_group_t *)arg; 246910309SSriharsha.Basavapatna@Sun.COM vnet_t *vnetp; 247010309SSriharsha.Basavapatna@Sun.COM 247110309SSriharsha.Basavapatna@Sun.COM vnetp = rx_grp->vnetp; 247210309SSriharsha.Basavapatna@Sun.COM 247310309SSriharsha.Basavapatna@Sun.COM if (bcmp(mac_addr, vnetp->curr_macaddr, ETHERADDRL) == 0) { 247410309SSriharsha.Basavapatna@Sun.COM return (0); 247510309SSriharsha.Basavapatna@Sun.COM } 247610309SSriharsha.Basavapatna@Sun.COM 247710309SSriharsha.Basavapatna@Sun.COM cmn_err(CE_CONT, "!vnet%d: %s: Multiple macaddr unsupported\n", 247810309SSriharsha.Basavapatna@Sun.COM vnetp->instance, __func__); 247910309SSriharsha.Basavapatna@Sun.COM return (EINVAL); 248010309SSriharsha.Basavapatna@Sun.COM } 248110309SSriharsha.Basavapatna@Sun.COM 248210309SSriharsha.Basavapatna@Sun.COM static int 248310309SSriharsha.Basavapatna@Sun.COM vnet_remmac(void *arg, const uint8_t *mac_addr) 248410309SSriharsha.Basavapatna@Sun.COM { 248510309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_group_t *rx_grp = (vnet_pseudo_rx_group_t *)arg; 248610309SSriharsha.Basavapatna@Sun.COM vnet_t *vnetp; 248710309SSriharsha.Basavapatna@Sun.COM 248810309SSriharsha.Basavapatna@Sun.COM vnetp = rx_grp->vnetp; 248910309SSriharsha.Basavapatna@Sun.COM 249010309SSriharsha.Basavapatna@Sun.COM if (bcmp(mac_addr, vnetp->curr_macaddr, ETHERADDRL) == 0) { 249110309SSriharsha.Basavapatna@Sun.COM return (0); 249210309SSriharsha.Basavapatna@Sun.COM } 249310309SSriharsha.Basavapatna@Sun.COM 249410309SSriharsha.Basavapatna@Sun.COM cmn_err(CE_CONT, "!vnet%d: %s: Invalid macaddr: %s\n", 249510309SSriharsha.Basavapatna@Sun.COM vnetp->instance, __func__, ether_sprintf((void *)mac_addr)); 249610309SSriharsha.Basavapatna@Sun.COM return (EINVAL); 249710309SSriharsha.Basavapatna@Sun.COM } 249810309SSriharsha.Basavapatna@Sun.COM 249910309SSriharsha.Basavapatna@Sun.COM int 250010309SSriharsha.Basavapatna@Sun.COM vnet_hio_mac_init(vnet_t *vnetp, char *ifname) 250110309SSriharsha.Basavapatna@Sun.COM { 250210309SSriharsha.Basavapatna@Sun.COM mac_handle_t mh; 250310309SSriharsha.Basavapatna@Sun.COM mac_client_handle_t mch = NULL; 250410309SSriharsha.Basavapatna@Sun.COM mac_unicast_handle_t muh = NULL; 250510309SSriharsha.Basavapatna@Sun.COM mac_diag_t diag; 250610309SSriharsha.Basavapatna@Sun.COM mac_register_t *macp; 250710309SSriharsha.Basavapatna@Sun.COM char client_name[MAXNAMELEN]; 250810309SSriharsha.Basavapatna@Sun.COM int rv; 250910309SSriharsha.Basavapatna@Sun.COM uint16_t mac_flags = MAC_UNICAST_TAG_DISABLE | 251010309SSriharsha.Basavapatna@Sun.COM MAC_UNICAST_STRIP_DISABLE | MAC_UNICAST_PRIMARY; 251110309SSriharsha.Basavapatna@Sun.COM vio_net_callbacks_t vcb; 251210309SSriharsha.Basavapatna@Sun.COM ether_addr_t rem_addr = 251310309SSriharsha.Basavapatna@Sun.COM { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 251410309SSriharsha.Basavapatna@Sun.COM uint32_t retries = 0; 251510309SSriharsha.Basavapatna@Sun.COM 251610309SSriharsha.Basavapatna@Sun.COM if ((macp = mac_alloc(MAC_VERSION)) == NULL) { 251710309SSriharsha.Basavapatna@Sun.COM return (EAGAIN); 251810309SSriharsha.Basavapatna@Sun.COM } 251910309SSriharsha.Basavapatna@Sun.COM 252010309SSriharsha.Basavapatna@Sun.COM do { 252110309SSriharsha.Basavapatna@Sun.COM rv = mac_open_by_linkname(ifname, &mh); 252210309SSriharsha.Basavapatna@Sun.COM if (rv == 0) { 252310309SSriharsha.Basavapatna@Sun.COM break; 252410309SSriharsha.Basavapatna@Sun.COM } 252510309SSriharsha.Basavapatna@Sun.COM if (rv != ENOENT || (retries++ >= vnet_mac_open_retries)) { 252610309SSriharsha.Basavapatna@Sun.COM mac_free(macp); 252710309SSriharsha.Basavapatna@Sun.COM return (rv); 252810309SSriharsha.Basavapatna@Sun.COM } 252910309SSriharsha.Basavapatna@Sun.COM drv_usecwait(vnet_mac_open_delay); 253010309SSriharsha.Basavapatna@Sun.COM } while (rv == ENOENT); 253110309SSriharsha.Basavapatna@Sun.COM 253210309SSriharsha.Basavapatna@Sun.COM vnetp->hio_mh = mh; 253310309SSriharsha.Basavapatna@Sun.COM 253410309SSriharsha.Basavapatna@Sun.COM (void) snprintf(client_name, MAXNAMELEN, "vnet%d-%s", vnetp->instance, 253510309SSriharsha.Basavapatna@Sun.COM ifname); 253610309SSriharsha.Basavapatna@Sun.COM rv = mac_client_open(mh, &mch, client_name, MAC_OPEN_FLAGS_EXCLUSIVE); 253710309SSriharsha.Basavapatna@Sun.COM if (rv != 0) { 253810309SSriharsha.Basavapatna@Sun.COM goto fail; 253910309SSriharsha.Basavapatna@Sun.COM } 254010309SSriharsha.Basavapatna@Sun.COM vnetp->hio_mch = mch; 254110309SSriharsha.Basavapatna@Sun.COM 254210309SSriharsha.Basavapatna@Sun.COM rv = mac_unicast_add(mch, vnetp->curr_macaddr, mac_flags, &muh, 0, 254310309SSriharsha.Basavapatna@Sun.COM &diag); 254410309SSriharsha.Basavapatna@Sun.COM if (rv != 0) { 254510309SSriharsha.Basavapatna@Sun.COM goto fail; 254610309SSriharsha.Basavapatna@Sun.COM } 254710309SSriharsha.Basavapatna@Sun.COM vnetp->hio_muh = muh; 254810309SSriharsha.Basavapatna@Sun.COM 254910309SSriharsha.Basavapatna@Sun.COM macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 255010309SSriharsha.Basavapatna@Sun.COM macp->m_driver = vnetp; 255110309SSriharsha.Basavapatna@Sun.COM macp->m_dip = NULL; 255210309SSriharsha.Basavapatna@Sun.COM macp->m_src_addr = NULL; 255310309SSriharsha.Basavapatna@Sun.COM macp->m_callbacks = &vnet_hio_res_callbacks; 255410309SSriharsha.Basavapatna@Sun.COM macp->m_min_sdu = 0; 255510309SSriharsha.Basavapatna@Sun.COM macp->m_max_sdu = ETHERMTU; 255610309SSriharsha.Basavapatna@Sun.COM 255710309SSriharsha.Basavapatna@Sun.COM rv = vio_net_resource_reg(macp, VIO_NET_RES_HYBRID, 255810309SSriharsha.Basavapatna@Sun.COM vnetp->curr_macaddr, rem_addr, &vnetp->hio_vhp, &vcb); 255910309SSriharsha.Basavapatna@Sun.COM if (rv != 0) { 256010309SSriharsha.Basavapatna@Sun.COM goto fail; 256110309SSriharsha.Basavapatna@Sun.COM } 256210309SSriharsha.Basavapatna@Sun.COM mac_free(macp); 256310309SSriharsha.Basavapatna@Sun.COM 256410309SSriharsha.Basavapatna@Sun.COM /* add the recv callback */ 256510309SSriharsha.Basavapatna@Sun.COM mac_rx_set(vnetp->hio_mch, vnet_hio_rx_cb, vnetp); 256610309SSriharsha.Basavapatna@Sun.COM 256710309SSriharsha.Basavapatna@Sun.COM /* add the notify callback - only tx updates for now */ 256810309SSriharsha.Basavapatna@Sun.COM vnetp->hio_mnh = mac_notify_add(vnetp->hio_mh, vnet_hio_notify_cb, 256910309SSriharsha.Basavapatna@Sun.COM vnetp); 257010309SSriharsha.Basavapatna@Sun.COM 257110309SSriharsha.Basavapatna@Sun.COM return (0); 257210309SSriharsha.Basavapatna@Sun.COM 257310309SSriharsha.Basavapatna@Sun.COM fail: 257410309SSriharsha.Basavapatna@Sun.COM mac_free(macp); 257510309SSriharsha.Basavapatna@Sun.COM vnet_hio_mac_cleanup(vnetp); 257610309SSriharsha.Basavapatna@Sun.COM return (1); 257710309SSriharsha.Basavapatna@Sun.COM } 257810309SSriharsha.Basavapatna@Sun.COM 257910309SSriharsha.Basavapatna@Sun.COM void 258010309SSriharsha.Basavapatna@Sun.COM vnet_hio_mac_cleanup(vnet_t *vnetp) 258110309SSriharsha.Basavapatna@Sun.COM { 258210309SSriharsha.Basavapatna@Sun.COM if (vnetp->hio_mnh != NULL) { 258310309SSriharsha.Basavapatna@Sun.COM (void) mac_notify_remove(vnetp->hio_mnh, B_TRUE); 258410309SSriharsha.Basavapatna@Sun.COM vnetp->hio_mnh = NULL; 258510309SSriharsha.Basavapatna@Sun.COM } 258610309SSriharsha.Basavapatna@Sun.COM 258710309SSriharsha.Basavapatna@Sun.COM if (vnetp->hio_vhp != NULL) { 258810309SSriharsha.Basavapatna@Sun.COM vio_net_resource_unreg(vnetp->hio_vhp); 258910309SSriharsha.Basavapatna@Sun.COM vnetp->hio_vhp = NULL; 259010309SSriharsha.Basavapatna@Sun.COM } 259110309SSriharsha.Basavapatna@Sun.COM 259210309SSriharsha.Basavapatna@Sun.COM if (vnetp->hio_muh != NULL) { 2593*11311SSurya.Prakki@Sun.COM (void) mac_unicast_remove(vnetp->hio_mch, vnetp->hio_muh); 259410309SSriharsha.Basavapatna@Sun.COM vnetp->hio_muh = NULL; 259510309SSriharsha.Basavapatna@Sun.COM } 259610309SSriharsha.Basavapatna@Sun.COM 259710309SSriharsha.Basavapatna@Sun.COM if (vnetp->hio_mch != NULL) { 259810309SSriharsha.Basavapatna@Sun.COM mac_client_close(vnetp->hio_mch, 0); 259910309SSriharsha.Basavapatna@Sun.COM vnetp->hio_mch = NULL; 260010309SSriharsha.Basavapatna@Sun.COM } 260110309SSriharsha.Basavapatna@Sun.COM 260210309SSriharsha.Basavapatna@Sun.COM if (vnetp->hio_mh != NULL) { 260310309SSriharsha.Basavapatna@Sun.COM mac_close(vnetp->hio_mh); 260410309SSriharsha.Basavapatna@Sun.COM vnetp->hio_mh = NULL; 260510309SSriharsha.Basavapatna@Sun.COM } 260610309SSriharsha.Basavapatna@Sun.COM } 260710309SSriharsha.Basavapatna@Sun.COM 260810309SSriharsha.Basavapatna@Sun.COM /* Bind pseudo rings to hwrings */ 260910309SSriharsha.Basavapatna@Sun.COM static int 261010309SSriharsha.Basavapatna@Sun.COM vnet_bind_hwrings(vnet_t *vnetp) 261110309SSriharsha.Basavapatna@Sun.COM { 261210309SSriharsha.Basavapatna@Sun.COM mac_ring_handle_t hw_rh[VNET_NUM_HYBRID_RINGS]; 261310309SSriharsha.Basavapatna@Sun.COM mac_perim_handle_t mph1; 261410309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_group_t *rx_grp; 261510309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_ring_t *rx_ringp; 261610309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_tx_group_t *tx_grp; 261710309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_tx_ring_t *tx_ringp; 261810309SSriharsha.Basavapatna@Sun.COM int hw_ring_cnt; 261910309SSriharsha.Basavapatna@Sun.COM int i; 262010309SSriharsha.Basavapatna@Sun.COM int rv; 262110309SSriharsha.Basavapatna@Sun.COM 262210309SSriharsha.Basavapatna@Sun.COM mac_perim_enter_by_mh(vnetp->hio_mh, &mph1); 262310309SSriharsha.Basavapatna@Sun.COM 262410309SSriharsha.Basavapatna@Sun.COM /* Get the list of the underlying RX rings. */ 262510309SSriharsha.Basavapatna@Sun.COM hw_ring_cnt = mac_hwrings_get(vnetp->hio_mch, &vnetp->rx_hwgh, hw_rh, 262610309SSriharsha.Basavapatna@Sun.COM MAC_RING_TYPE_RX); 262710309SSriharsha.Basavapatna@Sun.COM 262810309SSriharsha.Basavapatna@Sun.COM /* We expect the the # of hw rx rings to match VNET_NUM_HYBRID_RINGS */ 262910309SSriharsha.Basavapatna@Sun.COM if (hw_ring_cnt != VNET_NUM_HYBRID_RINGS) { 263010309SSriharsha.Basavapatna@Sun.COM cmn_err(CE_WARN, 263110309SSriharsha.Basavapatna@Sun.COM "!vnet%d: vnet_bind_hwrings: bad rx hw_ring_cnt(%d)\n", 263210309SSriharsha.Basavapatna@Sun.COM vnetp->instance, hw_ring_cnt); 263310309SSriharsha.Basavapatna@Sun.COM goto fail; 263410309SSriharsha.Basavapatna@Sun.COM } 263510309SSriharsha.Basavapatna@Sun.COM 263610309SSriharsha.Basavapatna@Sun.COM if (vnetp->rx_hwgh != NULL) { 263710309SSriharsha.Basavapatna@Sun.COM /* 263810309SSriharsha.Basavapatna@Sun.COM * Quiesce the HW ring and the mac srs on the ring. Note 263910309SSriharsha.Basavapatna@Sun.COM * that the HW ring will be restarted when the pseudo ring 264010309SSriharsha.Basavapatna@Sun.COM * is started. At that time all the packets will be 264110309SSriharsha.Basavapatna@Sun.COM * directly passed up to the pseudo RX ring and handled 264210309SSriharsha.Basavapatna@Sun.COM * by mac srs created over the pseudo RX ring. 264310309SSriharsha.Basavapatna@Sun.COM */ 264410309SSriharsha.Basavapatna@Sun.COM mac_rx_client_quiesce(vnetp->hio_mch); 264510309SSriharsha.Basavapatna@Sun.COM mac_srs_perm_quiesce(vnetp->hio_mch, B_TRUE); 264610309SSriharsha.Basavapatna@Sun.COM } 264710309SSriharsha.Basavapatna@Sun.COM 264810309SSriharsha.Basavapatna@Sun.COM /* 264910309SSriharsha.Basavapatna@Sun.COM * Bind the pseudo rings to the hwrings and start the hwrings. 265010309SSriharsha.Basavapatna@Sun.COM * Note we don't need to register these with the upper mac, as we have 265110309SSriharsha.Basavapatna@Sun.COM * statically exported these pseudo rxrings which are reserved for 265210309SSriharsha.Basavapatna@Sun.COM * rxrings of Hybrid resource. 265310309SSriharsha.Basavapatna@Sun.COM */ 265410309SSriharsha.Basavapatna@Sun.COM rx_grp = &vnetp->rx_grp[0]; 265510309SSriharsha.Basavapatna@Sun.COM for (i = 0; i < VNET_NUM_HYBRID_RINGS; i++) { 265610309SSriharsha.Basavapatna@Sun.COM /* Pick the rxrings reserved for Hybrid resource */ 265710309SSriharsha.Basavapatna@Sun.COM rx_ringp = &rx_grp->rings[i + VNET_HYBRID_RXRING_INDEX]; 265810309SSriharsha.Basavapatna@Sun.COM 265910309SSriharsha.Basavapatna@Sun.COM /* Store the hw ring handle */ 266010309SSriharsha.Basavapatna@Sun.COM rx_ringp->hw_rh = hw_rh[i]; 266110309SSriharsha.Basavapatna@Sun.COM 266210309SSriharsha.Basavapatna@Sun.COM /* Bind the pseudo ring to the underlying hwring */ 266310309SSriharsha.Basavapatna@Sun.COM mac_hwring_setup(rx_ringp->hw_rh, 266410309SSriharsha.Basavapatna@Sun.COM (mac_resource_handle_t)rx_ringp); 266510309SSriharsha.Basavapatna@Sun.COM 266610309SSriharsha.Basavapatna@Sun.COM /* Start the hwring if needed */ 266710309SSriharsha.Basavapatna@Sun.COM if (rx_ringp->state & VNET_RXRING_STARTED) { 266810309SSriharsha.Basavapatna@Sun.COM rv = mac_hwring_start(rx_ringp->hw_rh); 266910309SSriharsha.Basavapatna@Sun.COM if (rv != 0) { 267010309SSriharsha.Basavapatna@Sun.COM mac_hwring_teardown(rx_ringp->hw_rh); 267110309SSriharsha.Basavapatna@Sun.COM rx_ringp->hw_rh = NULL; 267210309SSriharsha.Basavapatna@Sun.COM goto fail; 267310309SSriharsha.Basavapatna@Sun.COM } 267410309SSriharsha.Basavapatna@Sun.COM } 267510309SSriharsha.Basavapatna@Sun.COM } 267610309SSriharsha.Basavapatna@Sun.COM 267710309SSriharsha.Basavapatna@Sun.COM /* Get the list of the underlying TX rings. */ 267810309SSriharsha.Basavapatna@Sun.COM hw_ring_cnt = mac_hwrings_get(vnetp->hio_mch, &vnetp->tx_hwgh, hw_rh, 267910309SSriharsha.Basavapatna@Sun.COM MAC_RING_TYPE_TX); 268010309SSriharsha.Basavapatna@Sun.COM 268110309SSriharsha.Basavapatna@Sun.COM /* We expect the # of hw tx rings to match VNET_NUM_HYBRID_RINGS */ 268210309SSriharsha.Basavapatna@Sun.COM if (hw_ring_cnt != VNET_NUM_HYBRID_RINGS) { 268310309SSriharsha.Basavapatna@Sun.COM cmn_err(CE_WARN, 268410309SSriharsha.Basavapatna@Sun.COM "!vnet%d: vnet_bind_hwrings: bad tx hw_ring_cnt(%d)\n", 268510309SSriharsha.Basavapatna@Sun.COM vnetp->instance, hw_ring_cnt); 268610309SSriharsha.Basavapatna@Sun.COM goto fail; 268710309SSriharsha.Basavapatna@Sun.COM } 268810309SSriharsha.Basavapatna@Sun.COM 268910309SSriharsha.Basavapatna@Sun.COM /* 269010309SSriharsha.Basavapatna@Sun.COM * Now map the pseudo txrings to the hw txrings. Note we don't need 269110309SSriharsha.Basavapatna@Sun.COM * to register these with the upper mac, as we have statically exported 269210309SSriharsha.Basavapatna@Sun.COM * these rings. Note that these rings will continue to be used for LDC 269310309SSriharsha.Basavapatna@Sun.COM * resources to peer vnets and vswitch (shared ring). 269410309SSriharsha.Basavapatna@Sun.COM */ 269510309SSriharsha.Basavapatna@Sun.COM tx_grp = &vnetp->tx_grp[0]; 269610309SSriharsha.Basavapatna@Sun.COM for (i = 0; i < tx_grp->ring_cnt; i++) { 269710309SSriharsha.Basavapatna@Sun.COM tx_ringp = &tx_grp->rings[i]; 269810309SSriharsha.Basavapatna@Sun.COM tx_ringp->hw_rh = hw_rh[i]; 269910309SSriharsha.Basavapatna@Sun.COM tx_ringp->state |= VNET_TXRING_HYBRID; 270010309SSriharsha.Basavapatna@Sun.COM } 270110309SSriharsha.Basavapatna@Sun.COM 270210309SSriharsha.Basavapatna@Sun.COM mac_perim_exit(mph1); 270310309SSriharsha.Basavapatna@Sun.COM return (0); 270410309SSriharsha.Basavapatna@Sun.COM 270510309SSriharsha.Basavapatna@Sun.COM fail: 270610309SSriharsha.Basavapatna@Sun.COM mac_perim_exit(mph1); 270710309SSriharsha.Basavapatna@Sun.COM vnet_unbind_hwrings(vnetp); 270810309SSriharsha.Basavapatna@Sun.COM return (1); 270910309SSriharsha.Basavapatna@Sun.COM } 271010309SSriharsha.Basavapatna@Sun.COM 271110309SSriharsha.Basavapatna@Sun.COM /* Unbind pseudo rings from hwrings */ 271210309SSriharsha.Basavapatna@Sun.COM static void 271310309SSriharsha.Basavapatna@Sun.COM vnet_unbind_hwrings(vnet_t *vnetp) 271410309SSriharsha.Basavapatna@Sun.COM { 271510309SSriharsha.Basavapatna@Sun.COM mac_perim_handle_t mph1; 271610309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_ring_t *rx_ringp; 271710309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_group_t *rx_grp; 271810309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_tx_group_t *tx_grp; 271910309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_tx_ring_t *tx_ringp; 272010309SSriharsha.Basavapatna@Sun.COM int i; 272110309SSriharsha.Basavapatna@Sun.COM 272210309SSriharsha.Basavapatna@Sun.COM mac_perim_enter_by_mh(vnetp->hio_mh, &mph1); 272310309SSriharsha.Basavapatna@Sun.COM 272410309SSriharsha.Basavapatna@Sun.COM tx_grp = &vnetp->tx_grp[0]; 272510309SSriharsha.Basavapatna@Sun.COM for (i = 0; i < VNET_NUM_HYBRID_RINGS; i++) { 272610309SSriharsha.Basavapatna@Sun.COM tx_ringp = &tx_grp->rings[i]; 272710309SSriharsha.Basavapatna@Sun.COM if (tx_ringp->state & VNET_TXRING_HYBRID) { 272810309SSriharsha.Basavapatna@Sun.COM tx_ringp->state &= ~VNET_TXRING_HYBRID; 272910309SSriharsha.Basavapatna@Sun.COM tx_ringp->hw_rh = NULL; 273010309SSriharsha.Basavapatna@Sun.COM } 273110309SSriharsha.Basavapatna@Sun.COM } 273210309SSriharsha.Basavapatna@Sun.COM 273310309SSriharsha.Basavapatna@Sun.COM rx_grp = &vnetp->rx_grp[0]; 273410309SSriharsha.Basavapatna@Sun.COM for (i = 0; i < VNET_NUM_HYBRID_RINGS; i++) { 273510309SSriharsha.Basavapatna@Sun.COM rx_ringp = &rx_grp->rings[i + VNET_HYBRID_RXRING_INDEX]; 273610309SSriharsha.Basavapatna@Sun.COM if (rx_ringp->hw_rh != NULL) { 273710309SSriharsha.Basavapatna@Sun.COM /* Stop the hwring */ 273810309SSriharsha.Basavapatna@Sun.COM mac_hwring_stop(rx_ringp->hw_rh); 273910309SSriharsha.Basavapatna@Sun.COM 274010309SSriharsha.Basavapatna@Sun.COM /* Teardown the hwring */ 274110309SSriharsha.Basavapatna@Sun.COM mac_hwring_teardown(rx_ringp->hw_rh); 274210309SSriharsha.Basavapatna@Sun.COM rx_ringp->hw_rh = NULL; 274310309SSriharsha.Basavapatna@Sun.COM } 274410309SSriharsha.Basavapatna@Sun.COM } 274510309SSriharsha.Basavapatna@Sun.COM 274610309SSriharsha.Basavapatna@Sun.COM if (vnetp->rx_hwgh != NULL) { 274710309SSriharsha.Basavapatna@Sun.COM vnetp->rx_hwgh = NULL; 274810309SSriharsha.Basavapatna@Sun.COM /* 274910309SSriharsha.Basavapatna@Sun.COM * First clear the permanent-quiesced flag of the RX srs then 275010309SSriharsha.Basavapatna@Sun.COM * restart the HW ring and the mac srs on the ring. 275110309SSriharsha.Basavapatna@Sun.COM */ 275210309SSriharsha.Basavapatna@Sun.COM mac_srs_perm_quiesce(vnetp->hio_mch, B_FALSE); 275310309SSriharsha.Basavapatna@Sun.COM mac_rx_client_restart(vnetp->hio_mch); 275410309SSriharsha.Basavapatna@Sun.COM } 275510309SSriharsha.Basavapatna@Sun.COM 275610309SSriharsha.Basavapatna@Sun.COM mac_perim_exit(mph1); 275710309SSriharsha.Basavapatna@Sun.COM } 275810309SSriharsha.Basavapatna@Sun.COM 275910309SSriharsha.Basavapatna@Sun.COM /* Bind pseudo ring to a LDC resource */ 276010309SSriharsha.Basavapatna@Sun.COM static int 276110309SSriharsha.Basavapatna@Sun.COM vnet_bind_vgenring(vnet_res_t *vresp) 276210309SSriharsha.Basavapatna@Sun.COM { 276310309SSriharsha.Basavapatna@Sun.COM vnet_t *vnetp; 276410309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_group_t *rx_grp; 276510309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_ring_t *rx_ringp; 276610309SSriharsha.Basavapatna@Sun.COM mac_perim_handle_t mph1; 276710309SSriharsha.Basavapatna@Sun.COM int rv; 276810309SSriharsha.Basavapatna@Sun.COM int type; 276910309SSriharsha.Basavapatna@Sun.COM 277010309SSriharsha.Basavapatna@Sun.COM vnetp = vresp->vnetp; 277110309SSriharsha.Basavapatna@Sun.COM type = vresp->type; 277210309SSriharsha.Basavapatna@Sun.COM rx_grp = &vnetp->rx_grp[0]; 277310309SSriharsha.Basavapatna@Sun.COM 277410309SSriharsha.Basavapatna@Sun.COM if (type == VIO_NET_RES_LDC_SERVICE) { 277510309SSriharsha.Basavapatna@Sun.COM /* 277610309SSriharsha.Basavapatna@Sun.COM * Ring Index 0 is the default ring in the group and is 277710309SSriharsha.Basavapatna@Sun.COM * reserved for LDC_SERVICE in vnet_ring_grp_init(). This ring 277810309SSriharsha.Basavapatna@Sun.COM * is allocated statically and is reported to the mac layer 277910309SSriharsha.Basavapatna@Sun.COM * in vnet_m_capab(). So, all we need to do here, is save a 278010309SSriharsha.Basavapatna@Sun.COM * reference to the associated vresp. 278110309SSriharsha.Basavapatna@Sun.COM */ 278210309SSriharsha.Basavapatna@Sun.COM rx_ringp = &rx_grp->rings[0]; 278310309SSriharsha.Basavapatna@Sun.COM rx_ringp->hw_rh = (mac_ring_handle_t)vresp; 278410309SSriharsha.Basavapatna@Sun.COM vresp->rx_ringp = (void *)rx_ringp; 278510309SSriharsha.Basavapatna@Sun.COM return (0); 278610309SSriharsha.Basavapatna@Sun.COM } 278710309SSriharsha.Basavapatna@Sun.COM ASSERT(type == VIO_NET_RES_LDC_GUEST); 278810309SSriharsha.Basavapatna@Sun.COM 278910309SSriharsha.Basavapatna@Sun.COM mac_perim_enter_by_mh(vnetp->mh, &mph1); 279010309SSriharsha.Basavapatna@Sun.COM 279110309SSriharsha.Basavapatna@Sun.COM rx_ringp = vnet_alloc_pseudo_rx_ring(vnetp); 279210309SSriharsha.Basavapatna@Sun.COM if (rx_ringp == NULL) { 279310309SSriharsha.Basavapatna@Sun.COM cmn_err(CE_WARN, "!vnet%d: Failed to allocate pseudo rx ring", 279410309SSriharsha.Basavapatna@Sun.COM vnetp->instance); 279510309SSriharsha.Basavapatna@Sun.COM goto fail; 279610309SSriharsha.Basavapatna@Sun.COM } 279710309SSriharsha.Basavapatna@Sun.COM 279810309SSriharsha.Basavapatna@Sun.COM /* Store the LDC resource itself as the ring handle */ 279910309SSriharsha.Basavapatna@Sun.COM rx_ringp->hw_rh = (mac_ring_handle_t)vresp; 280010309SSriharsha.Basavapatna@Sun.COM 280110309SSriharsha.Basavapatna@Sun.COM /* 280210309SSriharsha.Basavapatna@Sun.COM * Save a reference to the ring in the resource for lookup during 280310309SSriharsha.Basavapatna@Sun.COM * unbind. Note this is only done for LDC resources. We don't need this 280410309SSriharsha.Basavapatna@Sun.COM * in the case of a Hybrid resource (see vnet_bind_hwrings()), as its 280510309SSriharsha.Basavapatna@Sun.COM * rx rings are mapped to reserved pseudo rx rings (index 1 and 2). 280610309SSriharsha.Basavapatna@Sun.COM */ 280710309SSriharsha.Basavapatna@Sun.COM vresp->rx_ringp = (void *)rx_ringp; 280810309SSriharsha.Basavapatna@Sun.COM rx_ringp->state |= VNET_RXRING_LDC_GUEST; 280910309SSriharsha.Basavapatna@Sun.COM 281010309SSriharsha.Basavapatna@Sun.COM /* Register the pseudo ring with upper-mac */ 281110309SSriharsha.Basavapatna@Sun.COM rv = mac_group_add_ring(rx_grp->handle, rx_ringp->index); 281210309SSriharsha.Basavapatna@Sun.COM if (rv != 0) { 281310309SSriharsha.Basavapatna@Sun.COM rx_ringp->state &= ~VNET_RXRING_LDC_GUEST; 281410309SSriharsha.Basavapatna@Sun.COM rx_ringp->hw_rh = NULL; 281510309SSriharsha.Basavapatna@Sun.COM vnet_free_pseudo_rx_ring(vnetp, rx_ringp); 281610309SSriharsha.Basavapatna@Sun.COM goto fail; 281710309SSriharsha.Basavapatna@Sun.COM } 281810309SSriharsha.Basavapatna@Sun.COM 281910309SSriharsha.Basavapatna@Sun.COM mac_perim_exit(mph1); 282010309SSriharsha.Basavapatna@Sun.COM return (0); 282110309SSriharsha.Basavapatna@Sun.COM fail: 282210309SSriharsha.Basavapatna@Sun.COM mac_perim_exit(mph1); 282310309SSriharsha.Basavapatna@Sun.COM return (1); 282410309SSriharsha.Basavapatna@Sun.COM } 282510309SSriharsha.Basavapatna@Sun.COM 282610309SSriharsha.Basavapatna@Sun.COM /* Unbind pseudo ring from a LDC resource */ 282710309SSriharsha.Basavapatna@Sun.COM static void 282810309SSriharsha.Basavapatna@Sun.COM vnet_unbind_vgenring(vnet_res_t *vresp) 282910309SSriharsha.Basavapatna@Sun.COM { 283010309SSriharsha.Basavapatna@Sun.COM vnet_t *vnetp; 283110309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_group_t *rx_grp; 283210309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_rx_ring_t *rx_ringp; 283310309SSriharsha.Basavapatna@Sun.COM mac_perim_handle_t mph1; 283410309SSriharsha.Basavapatna@Sun.COM int type; 283510309SSriharsha.Basavapatna@Sun.COM 283610309SSriharsha.Basavapatna@Sun.COM vnetp = vresp->vnetp; 283710309SSriharsha.Basavapatna@Sun.COM type = vresp->type; 283810309SSriharsha.Basavapatna@Sun.COM rx_grp = &vnetp->rx_grp[0]; 283910309SSriharsha.Basavapatna@Sun.COM 284010309SSriharsha.Basavapatna@Sun.COM if (vresp->rx_ringp == NULL) { 284110309SSriharsha.Basavapatna@Sun.COM return; 284210309SSriharsha.Basavapatna@Sun.COM } 284310309SSriharsha.Basavapatna@Sun.COM 284410309SSriharsha.Basavapatna@Sun.COM if (type == VIO_NET_RES_LDC_SERVICE) { 284510309SSriharsha.Basavapatna@Sun.COM /* 284610309SSriharsha.Basavapatna@Sun.COM * Ring Index 0 is the default ring in the group and is 284710309SSriharsha.Basavapatna@Sun.COM * reserved for LDC_SERVICE in vnet_ring_grp_init(). This ring 284810309SSriharsha.Basavapatna@Sun.COM * is allocated statically and is reported to the mac layer 284910309SSriharsha.Basavapatna@Sun.COM * in vnet_m_capab(). So, all we need to do here, is remove its 285010309SSriharsha.Basavapatna@Sun.COM * reference to the associated vresp. 285110309SSriharsha.Basavapatna@Sun.COM */ 285210309SSriharsha.Basavapatna@Sun.COM rx_ringp = &rx_grp->rings[0]; 285310309SSriharsha.Basavapatna@Sun.COM rx_ringp->hw_rh = NULL; 285410309SSriharsha.Basavapatna@Sun.COM vresp->rx_ringp = NULL; 285510309SSriharsha.Basavapatna@Sun.COM return; 285610309SSriharsha.Basavapatna@Sun.COM } 285710309SSriharsha.Basavapatna@Sun.COM ASSERT(type == VIO_NET_RES_LDC_GUEST); 285810309SSriharsha.Basavapatna@Sun.COM 285910309SSriharsha.Basavapatna@Sun.COM mac_perim_enter_by_mh(vnetp->mh, &mph1); 286010309SSriharsha.Basavapatna@Sun.COM 286110309SSriharsha.Basavapatna@Sun.COM rx_ringp = (vnet_pseudo_rx_ring_t *)vresp->rx_ringp; 286210309SSriharsha.Basavapatna@Sun.COM vresp->rx_ringp = NULL; 286310309SSriharsha.Basavapatna@Sun.COM 286410309SSriharsha.Basavapatna@Sun.COM if (rx_ringp != NULL && (rx_ringp->state & VNET_RXRING_LDC_GUEST)) { 286510309SSriharsha.Basavapatna@Sun.COM /* Unregister the pseudo ring with upper-mac */ 286610309SSriharsha.Basavapatna@Sun.COM mac_group_rem_ring(rx_grp->handle, rx_ringp->handle); 286710309SSriharsha.Basavapatna@Sun.COM 286810309SSriharsha.Basavapatna@Sun.COM rx_ringp->hw_rh = NULL; 286910309SSriharsha.Basavapatna@Sun.COM rx_ringp->state &= ~VNET_RXRING_LDC_GUEST; 287010309SSriharsha.Basavapatna@Sun.COM 287110309SSriharsha.Basavapatna@Sun.COM /* Free the pseudo rx ring */ 287210309SSriharsha.Basavapatna@Sun.COM vnet_free_pseudo_rx_ring(vnetp, rx_ringp); 287310309SSriharsha.Basavapatna@Sun.COM } 287410309SSriharsha.Basavapatna@Sun.COM 287510309SSriharsha.Basavapatna@Sun.COM mac_perim_exit(mph1); 287610309SSriharsha.Basavapatna@Sun.COM } 287710309SSriharsha.Basavapatna@Sun.COM 287810309SSriharsha.Basavapatna@Sun.COM static void 287910309SSriharsha.Basavapatna@Sun.COM vnet_unbind_rings(vnet_res_t *vresp) 288010309SSriharsha.Basavapatna@Sun.COM { 288110309SSriharsha.Basavapatna@Sun.COM switch (vresp->type) { 288210309SSriharsha.Basavapatna@Sun.COM 288310309SSriharsha.Basavapatna@Sun.COM case VIO_NET_RES_LDC_SERVICE: 288410309SSriharsha.Basavapatna@Sun.COM case VIO_NET_RES_LDC_GUEST: 288510309SSriharsha.Basavapatna@Sun.COM vnet_unbind_vgenring(vresp); 288610309SSriharsha.Basavapatna@Sun.COM break; 288710309SSriharsha.Basavapatna@Sun.COM 288810309SSriharsha.Basavapatna@Sun.COM case VIO_NET_RES_HYBRID: 288910309SSriharsha.Basavapatna@Sun.COM vnet_unbind_hwrings(vresp->vnetp); 289010309SSriharsha.Basavapatna@Sun.COM break; 289110309SSriharsha.Basavapatna@Sun.COM 289210309SSriharsha.Basavapatna@Sun.COM default: 289310309SSriharsha.Basavapatna@Sun.COM break; 289410309SSriharsha.Basavapatna@Sun.COM 289510309SSriharsha.Basavapatna@Sun.COM } 289610309SSriharsha.Basavapatna@Sun.COM } 289710309SSriharsha.Basavapatna@Sun.COM 289810309SSriharsha.Basavapatna@Sun.COM static int 289910309SSriharsha.Basavapatna@Sun.COM vnet_bind_rings(vnet_res_t *vresp) 290010309SSriharsha.Basavapatna@Sun.COM { 290110309SSriharsha.Basavapatna@Sun.COM int rv; 290210309SSriharsha.Basavapatna@Sun.COM 290310309SSriharsha.Basavapatna@Sun.COM switch (vresp->type) { 290410309SSriharsha.Basavapatna@Sun.COM 290510309SSriharsha.Basavapatna@Sun.COM case VIO_NET_RES_LDC_SERVICE: 290610309SSriharsha.Basavapatna@Sun.COM case VIO_NET_RES_LDC_GUEST: 290710309SSriharsha.Basavapatna@Sun.COM rv = vnet_bind_vgenring(vresp); 290810309SSriharsha.Basavapatna@Sun.COM break; 290910309SSriharsha.Basavapatna@Sun.COM 291010309SSriharsha.Basavapatna@Sun.COM case VIO_NET_RES_HYBRID: 291110309SSriharsha.Basavapatna@Sun.COM rv = vnet_bind_hwrings(vresp->vnetp); 291210309SSriharsha.Basavapatna@Sun.COM break; 291310309SSriharsha.Basavapatna@Sun.COM 291410309SSriharsha.Basavapatna@Sun.COM default: 291510309SSriharsha.Basavapatna@Sun.COM rv = 1; 291610309SSriharsha.Basavapatna@Sun.COM break; 291710309SSriharsha.Basavapatna@Sun.COM 291810309SSriharsha.Basavapatna@Sun.COM } 291910309SSriharsha.Basavapatna@Sun.COM 292010309SSriharsha.Basavapatna@Sun.COM return (rv); 292110309SSriharsha.Basavapatna@Sun.COM } 292210309SSriharsha.Basavapatna@Sun.COM 292310309SSriharsha.Basavapatna@Sun.COM /* ARGSUSED */ 292410309SSriharsha.Basavapatna@Sun.COM int 292510309SSriharsha.Basavapatna@Sun.COM vnet_hio_stat(void *arg, uint_t stat, uint64_t *val) 292610309SSriharsha.Basavapatna@Sun.COM { 292710309SSriharsha.Basavapatna@Sun.COM vnet_t *vnetp = (vnet_t *)arg; 292810309SSriharsha.Basavapatna@Sun.COM 292910309SSriharsha.Basavapatna@Sun.COM *val = mac_stat_get(vnetp->hio_mh, stat); 293010309SSriharsha.Basavapatna@Sun.COM return (0); 293110309SSriharsha.Basavapatna@Sun.COM } 293210309SSriharsha.Basavapatna@Sun.COM 293310309SSriharsha.Basavapatna@Sun.COM /* 293410309SSriharsha.Basavapatna@Sun.COM * The start() and stop() routines for the Hybrid resource below, are just 293510309SSriharsha.Basavapatna@Sun.COM * dummy functions. This is provided to avoid resource type specific code in 293610309SSriharsha.Basavapatna@Sun.COM * vnet_start_resources() and vnet_stop_resources(). The starting and stopping 293710309SSriharsha.Basavapatna@Sun.COM * of the Hybrid resource happens in the context of the mac_client interfaces 293810309SSriharsha.Basavapatna@Sun.COM * that are invoked in vnet_hio_mac_init() and vnet_hio_mac_cleanup(). 293910309SSriharsha.Basavapatna@Sun.COM */ 294010309SSriharsha.Basavapatna@Sun.COM /* ARGSUSED */ 294110309SSriharsha.Basavapatna@Sun.COM static int 294210309SSriharsha.Basavapatna@Sun.COM vnet_hio_start(void *arg) 294310309SSriharsha.Basavapatna@Sun.COM { 294410309SSriharsha.Basavapatna@Sun.COM return (0); 294510309SSriharsha.Basavapatna@Sun.COM } 294610309SSriharsha.Basavapatna@Sun.COM 294710309SSriharsha.Basavapatna@Sun.COM /* ARGSUSED */ 294810309SSriharsha.Basavapatna@Sun.COM static void 294910309SSriharsha.Basavapatna@Sun.COM vnet_hio_stop(void *arg) 295010309SSriharsha.Basavapatna@Sun.COM { 295110309SSriharsha.Basavapatna@Sun.COM } 295210309SSriharsha.Basavapatna@Sun.COM 295310309SSriharsha.Basavapatna@Sun.COM mblk_t * 295410309SSriharsha.Basavapatna@Sun.COM vnet_hio_tx(void *arg, mblk_t *mp) 295510309SSriharsha.Basavapatna@Sun.COM { 295610309SSriharsha.Basavapatna@Sun.COM vnet_pseudo_tx_ring_t *tx_ringp; 295710309SSriharsha.Basavapatna@Sun.COM mblk_t *nextp; 295810309SSriharsha.Basavapatna@Sun.COM mblk_t *ret_mp; 295910309SSriharsha.Basavapatna@Sun.COM 296010309SSriharsha.Basavapatna@Sun.COM tx_ringp = (vnet_pseudo_tx_ring_t *)arg; 296110309SSriharsha.Basavapatna@Sun.COM for (;;) { 296210309SSriharsha.Basavapatna@Sun.COM nextp = mp->b_next; 296310309SSriharsha.Basavapatna@Sun.COM mp->b_next = NULL; 296410309SSriharsha.Basavapatna@Sun.COM 296510309SSriharsha.Basavapatna@Sun.COM ret_mp = mac_hwring_tx(tx_ringp->hw_rh, mp); 296610309SSriharsha.Basavapatna@Sun.COM if (ret_mp != NULL) { 296710309SSriharsha.Basavapatna@Sun.COM ret_mp->b_next = nextp; 296810309SSriharsha.Basavapatna@Sun.COM mp = ret_mp; 296910309SSriharsha.Basavapatna@Sun.COM break; 297010309SSriharsha.Basavapatna@Sun.COM } 297110309SSriharsha.Basavapatna@Sun.COM 297210309SSriharsha.Basavapatna@Sun.COM if ((mp = nextp) == NULL) 297310309SSriharsha.Basavapatna@Sun.COM break; 297410309SSriharsha.Basavapatna@Sun.COM } 297510309SSriharsha.Basavapatna@Sun.COM return (mp); 297610309SSriharsha.Basavapatna@Sun.COM } 297710309SSriharsha.Basavapatna@Sun.COM 297810309SSriharsha.Basavapatna@Sun.COM static void 297910309SSriharsha.Basavapatna@Sun.COM vnet_hio_notify_cb(void *arg, mac_notify_type_t type) 298010309SSriharsha.Basavapatna@Sun.COM { 298110309SSriharsha.Basavapatna@Sun.COM vnet_t *vnetp = (vnet_t *)arg; 298210309SSriharsha.Basavapatna@Sun.COM mac_perim_handle_t mph; 298310309SSriharsha.Basavapatna@Sun.COM 298410309SSriharsha.Basavapatna@Sun.COM mac_perim_enter_by_mh(vnetp->hio_mh, &mph); 298510309SSriharsha.Basavapatna@Sun.COM switch (type) { 298610309SSriharsha.Basavapatna@Sun.COM case MAC_NOTE_TX: 298710309SSriharsha.Basavapatna@Sun.COM vnet_tx_update(vnetp->hio_vhp); 298810309SSriharsha.Basavapatna@Sun.COM break; 298910309SSriharsha.Basavapatna@Sun.COM 299010309SSriharsha.Basavapatna@Sun.COM default: 299110309SSriharsha.Basavapatna@Sun.COM break; 299210309SSriharsha.Basavapatna@Sun.COM } 299310309SSriharsha.Basavapatna@Sun.COM mac_perim_exit(mph); 299410309SSriharsha.Basavapatna@Sun.COM } 299510309SSriharsha.Basavapatna@Sun.COM 29969336SSriharsha.Basavapatna@Sun.COM #ifdef VNET_IOC_DEBUG 29979336SSriharsha.Basavapatna@Sun.COM 29989336SSriharsha.Basavapatna@Sun.COM /* 29999336SSriharsha.Basavapatna@Sun.COM * The ioctl entry point is used only for debugging for now. The ioctl commands 30009336SSriharsha.Basavapatna@Sun.COM * can be used to force the link state of the channel connected to vsw. 30019336SSriharsha.Basavapatna@Sun.COM */ 30029336SSriharsha.Basavapatna@Sun.COM static void 30039336SSriharsha.Basavapatna@Sun.COM vnet_m_ioctl(void *arg, queue_t *q, mblk_t *mp) 30049336SSriharsha.Basavapatna@Sun.COM { 30059336SSriharsha.Basavapatna@Sun.COM struct iocblk *iocp; 30069336SSriharsha.Basavapatna@Sun.COM vnet_t *vnetp; 30079336SSriharsha.Basavapatna@Sun.COM 30089336SSriharsha.Basavapatna@Sun.COM iocp = (struct iocblk *)(uintptr_t)mp->b_rptr; 30099336SSriharsha.Basavapatna@Sun.COM iocp->ioc_error = 0; 30109336SSriharsha.Basavapatna@Sun.COM vnetp = (vnet_t *)arg; 30119336SSriharsha.Basavapatna@Sun.COM 30129336SSriharsha.Basavapatna@Sun.COM if (vnetp == NULL) { 30139336SSriharsha.Basavapatna@Sun.COM miocnak(q, mp, 0, EINVAL); 30149336SSriharsha.Basavapatna@Sun.COM return; 30159336SSriharsha.Basavapatna@Sun.COM } 30169336SSriharsha.Basavapatna@Sun.COM 30179336SSriharsha.Basavapatna@Sun.COM switch (iocp->ioc_cmd) { 30189336SSriharsha.Basavapatna@Sun.COM 30199336SSriharsha.Basavapatna@Sun.COM case VNET_FORCE_LINK_DOWN: 30209336SSriharsha.Basavapatna@Sun.COM case VNET_FORCE_LINK_UP: 30219336SSriharsha.Basavapatna@Sun.COM vnet_force_link_state(vnetp, q, mp); 30229336SSriharsha.Basavapatna@Sun.COM break; 30239336SSriharsha.Basavapatna@Sun.COM 30249336SSriharsha.Basavapatna@Sun.COM default: 30259336SSriharsha.Basavapatna@Sun.COM iocp->ioc_error = EINVAL; 30269336SSriharsha.Basavapatna@Sun.COM miocnak(q, mp, 0, iocp->ioc_error); 30279336SSriharsha.Basavapatna@Sun.COM break; 30289336SSriharsha.Basavapatna@Sun.COM 30299336SSriharsha.Basavapatna@Sun.COM } 30309336SSriharsha.Basavapatna@Sun.COM } 30319336SSriharsha.Basavapatna@Sun.COM 30329336SSriharsha.Basavapatna@Sun.COM static void 30339336SSriharsha.Basavapatna@Sun.COM vnet_force_link_state(vnet_t *vnetp, queue_t *q, mblk_t *mp) 30349336SSriharsha.Basavapatna@Sun.COM { 30359336SSriharsha.Basavapatna@Sun.COM mac_register_t *macp; 30369336SSriharsha.Basavapatna@Sun.COM mac_callbacks_t *cbp; 30379336SSriharsha.Basavapatna@Sun.COM vnet_res_t *vresp; 30389336SSriharsha.Basavapatna@Sun.COM 30399336SSriharsha.Basavapatna@Sun.COM READ_ENTER(&vnetp->vsw_fp_rw); 30409336SSriharsha.Basavapatna@Sun.COM 30419336SSriharsha.Basavapatna@Sun.COM vresp = vnetp->vsw_fp; 30429336SSriharsha.Basavapatna@Sun.COM if (vresp == NULL) { 30439336SSriharsha.Basavapatna@Sun.COM RW_EXIT(&vnetp->vsw_fp_rw); 30449336SSriharsha.Basavapatna@Sun.COM return; 30459336SSriharsha.Basavapatna@Sun.COM } 30469336SSriharsha.Basavapatna@Sun.COM 30479336SSriharsha.Basavapatna@Sun.COM macp = &vresp->macreg; 30489336SSriharsha.Basavapatna@Sun.COM cbp = macp->m_callbacks; 30499336SSriharsha.Basavapatna@Sun.COM cbp->mc_ioctl(macp->m_driver, q, mp); 30509336SSriharsha.Basavapatna@Sun.COM 30519336SSriharsha.Basavapatna@Sun.COM RW_EXIT(&vnetp->vsw_fp_rw); 30529336SSriharsha.Basavapatna@Sun.COM } 30539336SSriharsha.Basavapatna@Sun.COM 30549336SSriharsha.Basavapatna@Sun.COM #else 30559336SSriharsha.Basavapatna@Sun.COM 30569336SSriharsha.Basavapatna@Sun.COM static void 30579336SSriharsha.Basavapatna@Sun.COM vnet_m_ioctl(void *arg, queue_t *q, mblk_t *mp) 30589336SSriharsha.Basavapatna@Sun.COM { 30599336SSriharsha.Basavapatna@Sun.COM vnet_t *vnetp; 30609336SSriharsha.Basavapatna@Sun.COM 30619336SSriharsha.Basavapatna@Sun.COM vnetp = (vnet_t *)arg; 30629336SSriharsha.Basavapatna@Sun.COM 30639336SSriharsha.Basavapatna@Sun.COM if (vnetp == NULL) { 30649336SSriharsha.Basavapatna@Sun.COM miocnak(q, mp, 0, EINVAL); 30659336SSriharsha.Basavapatna@Sun.COM return; 30669336SSriharsha.Basavapatna@Sun.COM } 30679336SSriharsha.Basavapatna@Sun.COM 30689336SSriharsha.Basavapatna@Sun.COM /* ioctl support only for debugging */ 30699336SSriharsha.Basavapatna@Sun.COM miocnak(q, mp, 0, ENOTSUP); 30709336SSriharsha.Basavapatna@Sun.COM } 30719336SSriharsha.Basavapatna@Sun.COM 30729336SSriharsha.Basavapatna@Sun.COM #endif 3073