11ae08745Sheppo /*
21ae08745Sheppo * CDDL HEADER START
31ae08745Sheppo *
41ae08745Sheppo * The contents of this file are subject to the terms of the
51ae08745Sheppo * Common Development and Distribution License (the "License").
61ae08745Sheppo * You may not use this file except in compliance with the License.
71ae08745Sheppo *
81ae08745Sheppo * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91ae08745Sheppo * or http://www.opensolaris.org/os/licensing.
101ae08745Sheppo * See the License for the specific language governing permissions
111ae08745Sheppo * and limitations under the License.
121ae08745Sheppo *
131ae08745Sheppo * When distributing Covered Code, include this CDDL HEADER in each
141ae08745Sheppo * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151ae08745Sheppo * If applicable, add the following below this CDDL HEADER, with the
161ae08745Sheppo * fields enclosed by brackets "[]" replaced with your own identifying
171ae08745Sheppo * information: Portions Copyright [yyyy] [name of copyright owner]
181ae08745Sheppo *
191ae08745Sheppo * CDDL HEADER END
201ae08745Sheppo */
211ae08745Sheppo
221ae08745Sheppo /*
230c4606f0SWENTAO YANG * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
241ae08745Sheppo * Use is subject to license terms.
251ae08745Sheppo */
261ae08745Sheppo
271ae08745Sheppo #include <sys/types.h>
281ae08745Sheppo #include <sys/errno.h>
291ae08745Sheppo #include <sys/param.h>
300dc2366fSVenugopal Iyer #include <sys/callb.h>
311ae08745Sheppo #include <sys/stream.h>
321ae08745Sheppo #include <sys/kmem.h>
331ae08745Sheppo #include <sys/conf.h>
341ae08745Sheppo #include <sys/devops.h>
351ae08745Sheppo #include <sys/ksynch.h>
361ae08745Sheppo #include <sys/stat.h>
371ae08745Sheppo #include <sys/modctl.h>
38c1c61f44Ssb155480 #include <sys/modhash.h>
391ae08745Sheppo #include <sys/debug.h>
401ae08745Sheppo #include <sys/ethernet.h>
411ae08745Sheppo #include <sys/dlpi.h>
421ae08745Sheppo #include <net/if.h>
43da14cebeSEric Cheng #include <sys/mac_provider.h>
4463f531d1SSriharsha Basavapatna #include <sys/mac_client.h>
4563f531d1SSriharsha Basavapatna #include <sys/mac_client_priv.h>
46ba2e4443Sseb #include <sys/mac_ether.h>
471ae08745Sheppo #include <sys/ddi.h>
481ae08745Sheppo #include <sys/sunddi.h>
491ae08745Sheppo #include <sys/strsun.h>
501ae08745Sheppo #include <sys/note.h>
51c1c61f44Ssb155480 #include <sys/atomic.h>
521ae08745Sheppo #include <sys/vnet.h>
53c1c61f44Ssb155480 #include <sys/vlan.h>
54678453a8Sspeer #include <sys/vnet_mailbox.h>
55678453a8Sspeer #include <sys/vnet_common.h>
56678453a8Sspeer #include <sys/dds.h>
57678453a8Sspeer #include <sys/strsubr.h>
58678453a8Sspeer #include <sys/taskq.h>
591ae08745Sheppo
601ae08745Sheppo /*
611ae08745Sheppo * Function prototypes.
621ae08745Sheppo */
631ae08745Sheppo
641ae08745Sheppo /* DDI entrypoints */
651ae08745Sheppo static int vnetdevinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
661ae08745Sheppo static int vnetattach(dev_info_t *, ddi_attach_cmd_t);
671ae08745Sheppo static int vnetdetach(dev_info_t *, ddi_detach_cmd_t);
681ae08745Sheppo
691ae08745Sheppo /* MAC entrypoints */
70ba2e4443Sseb static int vnet_m_stat(void *, uint_t, uint64_t *);
711ae08745Sheppo static int vnet_m_start(void *);
721ae08745Sheppo static void vnet_m_stop(void *);
731ae08745Sheppo static int vnet_m_promisc(void *, boolean_t);
741ae08745Sheppo static int vnet_m_multicst(void *, boolean_t, const uint8_t *);
751ae08745Sheppo static int vnet_m_unicst(void *, const uint8_t *);
761ae08745Sheppo mblk_t *vnet_m_tx(void *, mblk_t *);
771107ea93SSriharsha Basavapatna static void vnet_m_ioctl(void *arg, queue_t *q, mblk_t *mp);
781107ea93SSriharsha Basavapatna #ifdef VNET_IOC_DEBUG
791107ea93SSriharsha Basavapatna static void vnet_force_link_state(vnet_t *vnetp, queue_t *q, mblk_t *mp);
801107ea93SSriharsha Basavapatna #endif
8163f531d1SSriharsha Basavapatna static boolean_t vnet_m_capab(void *arg, mac_capab_t cap, void *cap_data);
8263f531d1SSriharsha Basavapatna static void vnet_get_ring(void *arg, mac_ring_type_t rtype, const int g_index,
8363f531d1SSriharsha Basavapatna const int r_index, mac_ring_info_t *infop, mac_ring_handle_t r_handle);
8463f531d1SSriharsha Basavapatna static void vnet_get_group(void *arg, mac_ring_type_t type, const int index,
8563f531d1SSriharsha Basavapatna mac_group_info_t *infop, mac_group_handle_t handle);
8663f531d1SSriharsha Basavapatna static int vnet_rx_ring_start(mac_ring_driver_t rdriver, uint64_t mr_gen_num);
8763f531d1SSriharsha Basavapatna static void vnet_rx_ring_stop(mac_ring_driver_t rdriver);
880dc2366fSVenugopal Iyer static int vnet_rx_ring_stat(mac_ring_driver_t rdriver, uint_t stat,
890dc2366fSVenugopal Iyer uint64_t *val);
9063f531d1SSriharsha Basavapatna static int vnet_tx_ring_start(mac_ring_driver_t rdriver, uint64_t mr_gen_num);
9163f531d1SSriharsha Basavapatna static void vnet_tx_ring_stop(mac_ring_driver_t rdriver);
920dc2366fSVenugopal Iyer static int vnet_tx_ring_stat(mac_ring_driver_t rdriver, uint_t stat,
930dc2366fSVenugopal Iyer uint64_t *val);
9463f531d1SSriharsha Basavapatna static int vnet_ring_enable_intr(void *arg);
9563f531d1SSriharsha Basavapatna static int vnet_ring_disable_intr(void *arg);
9663f531d1SSriharsha Basavapatna static mblk_t *vnet_rx_poll(void *arg, int bytes_to_pickup);
9763f531d1SSriharsha Basavapatna static int vnet_addmac(void *arg, const uint8_t *mac_addr);
9863f531d1SSriharsha Basavapatna static int vnet_remmac(void *arg, const uint8_t *mac_addr);
991ae08745Sheppo
1001ae08745Sheppo /* vnet internal functions */
1016f09f0feSWENTAO YANG static int vnet_unattach(vnet_t *vnetp);
10263f531d1SSriharsha Basavapatna static void vnet_ring_grp_init(vnet_t *vnetp);
10363f531d1SSriharsha Basavapatna static void vnet_ring_grp_uninit(vnet_t *vnetp);
1041ae08745Sheppo static int vnet_mac_register(vnet_t *);
1051ae08745Sheppo static int vnet_read_mac_address(vnet_t *vnetp);
10663f531d1SSriharsha Basavapatna static int vnet_bind_vgenring(vnet_res_t *vresp);
10763f531d1SSriharsha Basavapatna static void vnet_unbind_vgenring(vnet_res_t *vresp);
10863f531d1SSriharsha Basavapatna static int vnet_bind_hwrings(vnet_t *vnetp);
10963f531d1SSriharsha Basavapatna static void vnet_unbind_hwrings(vnet_t *vnetp);
11063f531d1SSriharsha Basavapatna static int vnet_bind_rings(vnet_res_t *vresp);
11163f531d1SSriharsha Basavapatna static void vnet_unbind_rings(vnet_res_t *vresp);
11263f531d1SSriharsha Basavapatna static int vnet_hio_stat(void *, uint_t, uint64_t *);
11363f531d1SSriharsha Basavapatna static int vnet_hio_start(void *);
11463f531d1SSriharsha Basavapatna static void vnet_hio_stop(void *);
11563f531d1SSriharsha Basavapatna mblk_t *vnet_hio_tx(void *, mblk_t *);
1161ae08745Sheppo
117c1c61f44Ssb155480 /* Forwarding database (FDB) routines */
118c1c61f44Ssb155480 static void vnet_fdb_create(vnet_t *vnetp);
119c1c61f44Ssb155480 static void vnet_fdb_destroy(vnet_t *vnetp);
120678453a8Sspeer static vnet_res_t *vnet_fdbe_find(vnet_t *vnetp, struct ether_addr *addrp);
121c1c61f44Ssb155480 static void vnet_fdbe_find_cb(mod_hash_key_t key, mod_hash_val_t val);
122678453a8Sspeer void vnet_fdbe_add(vnet_t *vnetp, vnet_res_t *vresp);
123678453a8Sspeer static void vnet_fdbe_del(vnet_t *vnetp, vnet_res_t *vresp);
124c1c61f44Ssb155480
1258c242ab0SSriharsha Basavapatna static void vnet_rx_frames_untag(uint16_t pvid, mblk_t **mp);
126678453a8Sspeer static void vnet_rx(vio_net_handle_t vrh, mblk_t *mp);
127678453a8Sspeer static void vnet_tx_update(vio_net_handle_t vrh);
128678453a8Sspeer static void vnet_res_start_task(void *arg);
129678453a8Sspeer static void vnet_start_resources(vnet_t *vnetp);
130678453a8Sspeer static void vnet_stop_resources(vnet_t *vnetp);
131678453a8Sspeer static void vnet_dispatch_res_task(vnet_t *vnetp);
132678453a8Sspeer static void vnet_res_start_task(void *arg);
133678453a8Sspeer static void vnet_handle_res_err(vio_net_handle_t vrh, vio_net_err_val_t err);
13463f531d1SSriharsha Basavapatna static void vnet_add_resource(vnet_t *vnetp, vnet_res_t *vresp);
13563f531d1SSriharsha Basavapatna static vnet_res_t *vnet_rem_resource(vnet_t *vnetp, vnet_res_t *vresp);
1360dc2366fSVenugopal Iyer static void vnet_tx_notify_thread(void *);
1371107ea93SSriharsha Basavapatna
1381107ea93SSriharsha Basavapatna /* Exported to vnet_gen */
1397b1f684aSSriharsha Basavapatna int vnet_mtu_update(vnet_t *vnetp, uint32_t mtu);
1401107ea93SSriharsha Basavapatna void vnet_link_update(vnet_t *vnetp, link_state_t link_state);
1416d6de4eeSWENTAO YANG void vnet_dds_cleanup_hio(vnet_t *vnetp);
142678453a8Sspeer
1436ab6cb20SWENTAO YANG static kstat_t *vnet_hio_setup_kstats(char *ks_mod, char *ks_name,
1446ab6cb20SWENTAO YANG vnet_res_t *vresp);
1456ab6cb20SWENTAO YANG static int vnet_hio_update_kstats(kstat_t *ksp, int rw);
1466ab6cb20SWENTAO YANG static void vnet_hio_get_stats(vnet_res_t *vresp, vnet_hio_stats_t *statsp);
1476ab6cb20SWENTAO YANG static void vnet_hio_destroy_kstats(kstat_t *ksp);
1486ab6cb20SWENTAO YANG
149678453a8Sspeer /* Exported to to vnet_dds */
150678453a8Sspeer int vnet_send_dds_msg(vnet_t *vnetp, void *dmsg);
15163f531d1SSriharsha Basavapatna int vnet_hio_mac_init(vnet_t *vnetp, char *ifname);
15263f531d1SSriharsha Basavapatna void vnet_hio_mac_cleanup(vnet_t *vnetp);
153678453a8Sspeer
154678453a8Sspeer /* Externs that are imported from vnet_gen */
155678453a8Sspeer extern int vgen_init(void *vnetp, uint64_t regprop, dev_info_t *vnetdip,
156678453a8Sspeer const uint8_t *macaddr, void **vgenhdl);
15763f531d1SSriharsha Basavapatna extern int vgen_init_mdeg(void *arg);
1583ab636deSWENTAO YANG extern void vgen_uninit(void *arg);
159678453a8Sspeer extern int vgen_dds_tx(void *arg, void *dmsg);
16063f531d1SSriharsha Basavapatna extern int vgen_enable_intr(void *arg);
16163f531d1SSriharsha Basavapatna extern int vgen_disable_intr(void *arg);
162*7bd3a2e2SSriharsha Basavapatna extern mblk_t *vgen_rx_poll(void *arg, int bytes_to_pickup);
163678453a8Sspeer
164678453a8Sspeer /* Externs that are imported from vnet_dds */
165678453a8Sspeer extern void vdds_mod_init(void);
166678453a8Sspeer extern void vdds_mod_fini(void);
167678453a8Sspeer extern int vdds_init(vnet_t *vnetp);
168678453a8Sspeer extern void vdds_cleanup(vnet_t *vnetp);
169678453a8Sspeer extern void vdds_process_dds_msg(vnet_t *vnetp, vio_dds_msg_t *dmsg);
170d0288fccSRaghuram Kothakota extern void vdds_cleanup_hybrid_res(void *arg);
1716d6de4eeSWENTAO YANG extern void vdds_cleanup_hio(vnet_t *vnetp);
1721ae08745Sheppo
1730dc2366fSVenugopal Iyer extern pri_t minclsyspri;
17463f531d1SSriharsha Basavapatna
1756ab6cb20SWENTAO YANG #define DRV_NAME "vnet"
176c1c61f44Ssb155480 #define VNET_FDBE_REFHOLD(p) \
177c1c61f44Ssb155480 { \
178c1c61f44Ssb155480 atomic_inc_32(&(p)->refcnt); \
179c1c61f44Ssb155480 ASSERT((p)->refcnt != 0); \
180c1c61f44Ssb155480 }
181c1c61f44Ssb155480
182c1c61f44Ssb155480 #define VNET_FDBE_REFRELE(p) \
183c1c61f44Ssb155480 { \
184c1c61f44Ssb155480 ASSERT((p)->refcnt != 0); \
185c1c61f44Ssb155480 atomic_dec_32(&(p)->refcnt); \
186c1c61f44Ssb155480 }
187c1c61f44Ssb155480
1881107ea93SSriharsha Basavapatna #ifdef VNET_IOC_DEBUG
18963f531d1SSriharsha Basavapatna #define VNET_M_CALLBACK_FLAGS (MC_IOCTL | MC_GETCAPAB)
1901107ea93SSriharsha Basavapatna #else
19163f531d1SSriharsha Basavapatna #define VNET_M_CALLBACK_FLAGS (MC_GETCAPAB)
1921107ea93SSriharsha Basavapatna #endif
1931107ea93SSriharsha Basavapatna
194ba2e4443Sseb static mac_callbacks_t vnet_m_callbacks = {
1951107ea93SSriharsha Basavapatna VNET_M_CALLBACK_FLAGS,
196ba2e4443Sseb vnet_m_stat,
197ba2e4443Sseb vnet_m_start,
198ba2e4443Sseb vnet_m_stop,
199ba2e4443Sseb vnet_m_promisc,
200ba2e4443Sseb vnet_m_multicst,
20163f531d1SSriharsha Basavapatna NULL, /* m_unicst entry must be NULL while rx rings are exposed */
20263f531d1SSriharsha Basavapatna NULL, /* m_tx entry must be NULL while tx rings are exposed */
2030dc2366fSVenugopal Iyer NULL,
2041107ea93SSriharsha Basavapatna vnet_m_ioctl,
20563f531d1SSriharsha Basavapatna vnet_m_capab,
20663f531d1SSriharsha Basavapatna NULL
20763f531d1SSriharsha Basavapatna };
20863f531d1SSriharsha Basavapatna
20963f531d1SSriharsha Basavapatna static mac_callbacks_t vnet_hio_res_callbacks = {
21063f531d1SSriharsha Basavapatna 0,
21163f531d1SSriharsha Basavapatna vnet_hio_stat,
21263f531d1SSriharsha Basavapatna vnet_hio_start,
21363f531d1SSriharsha Basavapatna vnet_hio_stop,
21463f531d1SSriharsha Basavapatna NULL,
21563f531d1SSriharsha Basavapatna NULL,
21663f531d1SSriharsha Basavapatna NULL,
21763f531d1SSriharsha Basavapatna vnet_hio_tx,
21863f531d1SSriharsha Basavapatna NULL,
219ba2e4443Sseb NULL,
220ba2e4443Sseb NULL
221ba2e4443Sseb };
222ba2e4443Sseb
2231ae08745Sheppo /*
2241ae08745Sheppo * Linked list of "vnet_t" structures - one per instance.
2251ae08745Sheppo */
2261ae08745Sheppo static vnet_t *vnet_headp = NULL;
2271ae08745Sheppo static krwlock_t vnet_rw;
2281ae08745Sheppo
2291ae08745Sheppo /* Tunables */
230*7bd3a2e2SSriharsha Basavapatna uint32_t vnet_num_descriptors = VNET_NUM_DESCRIPTORS;
231c1c61f44Ssb155480
232*7bd3a2e2SSriharsha Basavapatna /*
233*7bd3a2e2SSriharsha Basavapatna * Configure tx serialization in mac layer for the vnet device. This tunable
234*7bd3a2e2SSriharsha Basavapatna * should be enabled to improve performance only if HybridIO is configured for
235*7bd3a2e2SSriharsha Basavapatna * the vnet device.
236*7bd3a2e2SSriharsha Basavapatna */
237*7bd3a2e2SSriharsha Basavapatna boolean_t vnet_mac_tx_serialize = B_FALSE;
238*7bd3a2e2SSriharsha Basavapatna
2390dc2366fSVenugopal Iyer /* Configure enqueing at Rx soft rings in mac layer for the vnet device */
2400dc2366fSVenugopal Iyer boolean_t vnet_mac_rx_queuing = B_TRUE;
24163f531d1SSriharsha Basavapatna
2427b1f684aSSriharsha Basavapatna /*
2437b1f684aSSriharsha Basavapatna * Set this to non-zero to enable additional internal receive buffer pools
2447b1f684aSSriharsha Basavapatna * based on the MTU of the device for better performance at the cost of more
2457b1f684aSSriharsha Basavapatna * memory consumption. This is turned off by default, to use allocb(9F) for
2467b1f684aSSriharsha Basavapatna * receive buffer allocations of sizes > 2K.
2477b1f684aSSriharsha Basavapatna */
2487b1f684aSSriharsha Basavapatna boolean_t vnet_jumbo_rxpools = B_FALSE;
2497b1f684aSSriharsha Basavapatna
250c1c61f44Ssb155480 /* # of chains in fdb hash table */
251c1c61f44Ssb155480 uint32_t vnet_fdb_nchains = VNET_NFDB_HASH;
252c1c61f44Ssb155480
253c1c61f44Ssb155480 /* Internal tunables */
254c1c61f44Ssb155480 uint32_t vnet_ethermtu = 1500; /* mtu of the device */
255c1c61f44Ssb155480
256c1c61f44Ssb155480 /*
257c1c61f44Ssb155480 * Default vlan id. This is only used internally when the "default-vlan-id"
258c1c61f44Ssb155480 * property is not present in the MD device node. Therefore, this should not be
259c1c61f44Ssb155480 * used as a tunable; if this value is changed, the corresponding variable
260c1c61f44Ssb155480 * should be updated to the same value in vsw and also other vnets connected to
261c1c61f44Ssb155480 * the same vsw.
262c1c61f44Ssb155480 */
263c1c61f44Ssb155480 uint16_t vnet_default_vlan_id = 1;
264c1c61f44Ssb155480
265c1c61f44Ssb155480 /* delay in usec to wait for all references on a fdb entry to be dropped */
266c1c61f44Ssb155480 uint32_t vnet_fdbe_refcnt_delay = 10;
2671ae08745Sheppo
268678453a8Sspeer static struct ether_addr etherbroadcastaddr = {
269678453a8Sspeer 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
270678453a8Sspeer };
271678453a8Sspeer
27263f531d1SSriharsha Basavapatna /* mac_open() retry delay in usec */
27363f531d1SSriharsha Basavapatna uint32_t vnet_mac_open_delay = 100; /* 0.1 ms */
27463f531d1SSriharsha Basavapatna
27563f531d1SSriharsha Basavapatna /* max # of mac_open() retries */
27663f531d1SSriharsha Basavapatna uint32_t vnet_mac_open_retries = 100;
277678453a8Sspeer
2781ae08745Sheppo /*
2791ae08745Sheppo * Property names
2801ae08745Sheppo */
2811ae08745Sheppo static char macaddr_propname[] = "local-mac-address";
2821ae08745Sheppo
2831ae08745Sheppo /*
2841ae08745Sheppo * This is the string displayed by modinfo(1m).
2851ae08745Sheppo */
2867b1f684aSSriharsha Basavapatna static char vnet_ident[] = "vnet driver";
2871ae08745Sheppo extern struct mod_ops mod_driverops;
2881ae08745Sheppo static struct cb_ops cb_vnetops = {
2891ae08745Sheppo nulldev, /* cb_open */
2901ae08745Sheppo nulldev, /* cb_close */
2911ae08745Sheppo nodev, /* cb_strategy */
2921ae08745Sheppo nodev, /* cb_print */
2931ae08745Sheppo nodev, /* cb_dump */
2941ae08745Sheppo nodev, /* cb_read */
2951ae08745Sheppo nodev, /* cb_write */
2961ae08745Sheppo nodev, /* cb_ioctl */
2971ae08745Sheppo nodev, /* cb_devmap */
2981ae08745Sheppo nodev, /* cb_mmap */
2991ae08745Sheppo nodev, /* cb_segmap */
3001ae08745Sheppo nochpoll, /* cb_chpoll */
3011ae08745Sheppo ddi_prop_op, /* cb_prop_op */
3021ae08745Sheppo NULL, /* cb_stream */
3031ae08745Sheppo (int)(D_MP) /* cb_flag */
3041ae08745Sheppo };
3051ae08745Sheppo
3061ae08745Sheppo static struct dev_ops vnetops = {
3071ae08745Sheppo DEVO_REV, /* devo_rev */
3081ae08745Sheppo 0, /* devo_refcnt */
3091ae08745Sheppo NULL, /* devo_getinfo */
3101ae08745Sheppo nulldev, /* devo_identify */
3111ae08745Sheppo nulldev, /* devo_probe */
3121ae08745Sheppo vnetattach, /* devo_attach */
3131ae08745Sheppo vnetdetach, /* devo_detach */
3141ae08745Sheppo nodev, /* devo_reset */
3151ae08745Sheppo &cb_vnetops, /* devo_cb_ops */
31619397407SSherry Moore (struct bus_ops *)NULL, /* devo_bus_ops */
31719397407SSherry Moore NULL, /* devo_power */
31819397407SSherry Moore ddi_quiesce_not_supported, /* devo_quiesce */
3191ae08745Sheppo };
3201ae08745Sheppo
3211ae08745Sheppo static struct modldrv modldrv = {
3221ae08745Sheppo &mod_driverops, /* Type of module. This one is a driver */
3231ae08745Sheppo vnet_ident, /* ID string */
3241ae08745Sheppo &vnetops /* driver specific ops */
3251ae08745Sheppo };
3261ae08745Sheppo
3271ae08745Sheppo static struct modlinkage modlinkage = {
3281ae08745Sheppo MODREV_1, (void *)&modldrv, NULL
3291ae08745Sheppo };
3301ae08745Sheppo
331844e62a3Sraghuram #ifdef DEBUG
3321ae08745Sheppo
333*7bd3a2e2SSriharsha Basavapatna #define DEBUG_PRINTF debug_printf
334*7bd3a2e2SSriharsha Basavapatna
3351ae08745Sheppo /*
3361ae08745Sheppo * Print debug messages - set to 0xf to enable all msgs
3371ae08745Sheppo */
338844e62a3Sraghuram int vnet_dbglevel = 0x8;
3391ae08745Sheppo
340844e62a3Sraghuram static void
debug_printf(const char * fname,void * arg,const char * fmt,...)341844e62a3Sraghuram debug_printf(const char *fname, void *arg, const char *fmt, ...)
3421ae08745Sheppo {
3431ae08745Sheppo char buf[512];
3441ae08745Sheppo va_list ap;
3451ae08745Sheppo vnet_t *vnetp = (vnet_t *)arg;
346844e62a3Sraghuram char *bufp = buf;
3471ae08745Sheppo
348844e62a3Sraghuram if (vnetp == NULL) {
349844e62a3Sraghuram (void) sprintf(bufp, "%s: ", fname);
350844e62a3Sraghuram bufp += strlen(bufp);
351844e62a3Sraghuram } else {
352844e62a3Sraghuram (void) sprintf(bufp, "vnet%d:%s: ", vnetp->instance, fname);
353844e62a3Sraghuram bufp += strlen(bufp);
3541ae08745Sheppo }
355844e62a3Sraghuram va_start(ap, fmt);
356844e62a3Sraghuram (void) vsprintf(bufp, fmt, ap);
357844e62a3Sraghuram va_end(ap);
358844e62a3Sraghuram cmn_err(CE_CONT, "%s\n", buf);
359844e62a3Sraghuram }
3601ae08745Sheppo
3611ae08745Sheppo #endif
3621ae08745Sheppo
3631ae08745Sheppo /* _init(9E): initialize the loadable module */
3641ae08745Sheppo int
_init(void)3651ae08745Sheppo _init(void)
3661ae08745Sheppo {
3671ae08745Sheppo int status;
3681ae08745Sheppo
369844e62a3Sraghuram DBG1(NULL, "enter\n");
3701ae08745Sheppo
3711ae08745Sheppo mac_init_ops(&vnetops, "vnet");
3721ae08745Sheppo status = mod_install(&modlinkage);
3731ae08745Sheppo if (status != 0) {
3741ae08745Sheppo mac_fini_ops(&vnetops);
3751ae08745Sheppo }
376678453a8Sspeer vdds_mod_init();
377844e62a3Sraghuram DBG1(NULL, "exit(%d)\n", status);
3781ae08745Sheppo return (status);
3791ae08745Sheppo }
3801ae08745Sheppo
3811ae08745Sheppo /* _fini(9E): prepare the module for unloading. */
3821ae08745Sheppo int
_fini(void)3831ae08745Sheppo _fini(void)
3841ae08745Sheppo {
3851ae08745Sheppo int status;
3861ae08745Sheppo
387844e62a3Sraghuram DBG1(NULL, "enter\n");
3881ae08745Sheppo
3891ae08745Sheppo status = mod_remove(&modlinkage);
3901ae08745Sheppo if (status != 0)
3911ae08745Sheppo return (status);
3921ae08745Sheppo mac_fini_ops(&vnetops);
393678453a8Sspeer vdds_mod_fini();
3941ae08745Sheppo
395844e62a3Sraghuram DBG1(NULL, "exit(%d)\n", status);
3961ae08745Sheppo return (status);
3971ae08745Sheppo }
3981ae08745Sheppo
3991ae08745Sheppo /* _info(9E): return information about the loadable module */
4001ae08745Sheppo int
_info(struct modinfo * modinfop)4011ae08745Sheppo _info(struct modinfo *modinfop)
4021ae08745Sheppo {
4031ae08745Sheppo return (mod_info(&modlinkage, modinfop));
4041ae08745Sheppo }
4051ae08745Sheppo
4061ae08745Sheppo /*
4071ae08745Sheppo * attach(9E): attach a device to the system.
4081ae08745Sheppo * called once for each instance of the device on the system.
4091ae08745Sheppo */
4101ae08745Sheppo static int
vnetattach(dev_info_t * dip,ddi_attach_cmd_t cmd)4111ae08745Sheppo vnetattach(dev_info_t *dip, ddi_attach_cmd_t cmd)
4121ae08745Sheppo {
4131ae08745Sheppo vnet_t *vnetp;
4141ae08745Sheppo int status;
415678453a8Sspeer int instance;
416678453a8Sspeer uint64_t reg;
417678453a8Sspeer char qname[TASKQ_NAMELEN];
4186f09f0feSWENTAO YANG vnet_attach_progress_t attach_progress;
4191ae08745Sheppo
4206f09f0feSWENTAO YANG attach_progress = AST_init;
4211ae08745Sheppo
4221ae08745Sheppo switch (cmd) {
4231ae08745Sheppo case DDI_ATTACH:
4241ae08745Sheppo break;
4251ae08745Sheppo case DDI_RESUME:
4261ae08745Sheppo case DDI_PM_RESUME:
4271ae08745Sheppo default:
4281ae08745Sheppo goto vnet_attach_fail;
4291ae08745Sheppo }
4301ae08745Sheppo
4311ae08745Sheppo instance = ddi_get_instance(dip);
432844e62a3Sraghuram DBG1(NULL, "instance(%d) enter\n", instance);
4331ae08745Sheppo
4341ae08745Sheppo /* allocate vnet_t and mac_t structures */
4351ae08745Sheppo vnetp = kmem_zalloc(sizeof (vnet_t), KM_SLEEP);
436678453a8Sspeer vnetp->dip = dip;
437678453a8Sspeer vnetp->instance = instance;
438678453a8Sspeer rw_init(&vnetp->vrwlock, NULL, RW_DRIVER, NULL);
439678453a8Sspeer rw_init(&vnetp->vsw_fp_rw, NULL, RW_DRIVER, NULL);
4406f09f0feSWENTAO YANG attach_progress |= AST_vnet_alloc;
4411ae08745Sheppo
44263f531d1SSriharsha Basavapatna vnet_ring_grp_init(vnetp);
44363f531d1SSriharsha Basavapatna attach_progress |= AST_ring_init;
44463f531d1SSriharsha Basavapatna
445678453a8Sspeer status = vdds_init(vnetp);
446678453a8Sspeer if (status != 0) {
447678453a8Sspeer goto vnet_attach_fail;
448678453a8Sspeer }
4496f09f0feSWENTAO YANG attach_progress |= AST_vdds_init;
450678453a8Sspeer
4511ae08745Sheppo /* setup links to vnet_t from both devinfo and mac_t */
4521ae08745Sheppo ddi_set_driver_private(dip, (caddr_t)vnetp);
4531ae08745Sheppo
4541ae08745Sheppo /* read the mac address */
4551ae08745Sheppo status = vnet_read_mac_address(vnetp);
4561ae08745Sheppo if (status != DDI_SUCCESS) {
4571ae08745Sheppo goto vnet_attach_fail;
4581ae08745Sheppo }
4596f09f0feSWENTAO YANG attach_progress |= AST_read_macaddr;
4601ae08745Sheppo
461678453a8Sspeer reg = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
462678453a8Sspeer DDI_PROP_DONTPASS, "reg", -1);
463678453a8Sspeer if (reg == -1) {
4641ae08745Sheppo goto vnet_attach_fail;
4651ae08745Sheppo }
466678453a8Sspeer vnetp->reg = reg;
4671ae08745Sheppo
468c1c61f44Ssb155480 vnet_fdb_create(vnetp);
4696f09f0feSWENTAO YANG attach_progress |= AST_fdbh_alloc;
4701ae08745Sheppo
471*7bd3a2e2SSriharsha Basavapatna (void) snprintf(qname, TASKQ_NAMELEN, "vres_taskq%d", instance);
472678453a8Sspeer if ((vnetp->taskqp = ddi_taskq_create(dip, qname, 1,
473678453a8Sspeer TASKQ_DEFAULTPRI, 0)) == NULL) {
474678453a8Sspeer cmn_err(CE_WARN, "!vnet%d: Unable to create task queue",
475678453a8Sspeer instance);
4761ae08745Sheppo goto vnet_attach_fail;
4771ae08745Sheppo }
4786f09f0feSWENTAO YANG attach_progress |= AST_taskq_create;
4791ae08745Sheppo
4801ae08745Sheppo /* add to the list of vnet devices */
4811ae08745Sheppo WRITE_ENTER(&vnet_rw);
4821ae08745Sheppo vnetp->nextp = vnet_headp;
4831ae08745Sheppo vnet_headp = vnetp;
4841ae08745Sheppo RW_EXIT(&vnet_rw);
4851ae08745Sheppo
4866f09f0feSWENTAO YANG attach_progress |= AST_vnet_list;
487678453a8Sspeer
488678453a8Sspeer /*
48963f531d1SSriharsha Basavapatna * Initialize the generic vnet plugin which provides communication via
49063f531d1SSriharsha Basavapatna * sun4v LDC (logical domain channel) based resources. This involves 2
49163f531d1SSriharsha Basavapatna * steps; first, vgen_init() is invoked to read the various properties
49263f531d1SSriharsha Basavapatna * of the vnet device from its MD node (including its mtu which is
49363f531d1SSriharsha Basavapatna * needed to mac_register()) and obtain a handle to the vgen layer.
49463f531d1SSriharsha Basavapatna * After mac_register() is done and we have a mac handle, we then
49563f531d1SSriharsha Basavapatna * invoke vgen_init_mdeg() which registers with the the MD event
49663f531d1SSriharsha Basavapatna * generator (mdeg) framework to allow LDC resource notifications.
49763f531d1SSriharsha Basavapatna * Note: this sequence also allows us to report the correct default #
49863f531d1SSriharsha Basavapatna * of pseudo rings (2TX and 3RX) in vnet_m_capab() which gets invoked
49963f531d1SSriharsha Basavapatna * in the context of mac_register(); and avoids conflicting with
50063f531d1SSriharsha Basavapatna * dynamic pseudo rx rings which get added/removed as a result of mdeg
50163f531d1SSriharsha Basavapatna * events in vgen.
502678453a8Sspeer */
503678453a8Sspeer status = vgen_init(vnetp, reg, vnetp->dip,
504678453a8Sspeer (uint8_t *)vnetp->curr_macaddr, &vnetp->vgenhdl);
505678453a8Sspeer if (status != DDI_SUCCESS) {
506678453a8Sspeer DERR(vnetp, "vgen_init() failed\n");
507678453a8Sspeer goto vnet_attach_fail;
508678453a8Sspeer }
5096f09f0feSWENTAO YANG attach_progress |= AST_vgen_init;
510678453a8Sspeer
511678453a8Sspeer status = vnet_mac_register(vnetp);
512678453a8Sspeer if (status != DDI_SUCCESS) {
513678453a8Sspeer goto vnet_attach_fail;
514678453a8Sspeer }
5151107ea93SSriharsha Basavapatna vnetp->link_state = LINK_STATE_UNKNOWN;
5166f09f0feSWENTAO YANG attach_progress |= AST_macreg;
5176f09f0feSWENTAO YANG
51863f531d1SSriharsha Basavapatna status = vgen_init_mdeg(vnetp->vgenhdl);
51963f531d1SSriharsha Basavapatna if (status != DDI_SUCCESS) {
52063f531d1SSriharsha Basavapatna goto vnet_attach_fail;
52163f531d1SSriharsha Basavapatna }
52263f531d1SSriharsha Basavapatna attach_progress |= AST_init_mdeg;
52363f531d1SSriharsha Basavapatna
5246f09f0feSWENTAO YANG vnetp->attach_progress = attach_progress;
5256f09f0feSWENTAO YANG
526844e62a3Sraghuram DBG1(NULL, "instance(%d) exit\n", instance);
5271ae08745Sheppo return (DDI_SUCCESS);
5281ae08745Sheppo
5291ae08745Sheppo vnet_attach_fail:
5306f09f0feSWENTAO YANG vnetp->attach_progress = attach_progress;
5313ab636deSWENTAO YANG status = vnet_unattach(vnetp);
5323ab636deSWENTAO YANG ASSERT(status == 0);
5331ae08745Sheppo return (DDI_FAILURE);
5341ae08745Sheppo }
5351ae08745Sheppo
5361ae08745Sheppo /*
5371ae08745Sheppo * detach(9E): detach a device from the system.
5381ae08745Sheppo */
5391ae08745Sheppo static int
vnetdetach(dev_info_t * dip,ddi_detach_cmd_t cmd)5401ae08745Sheppo vnetdetach(dev_info_t *dip, ddi_detach_cmd_t cmd)
5411ae08745Sheppo {
5421ae08745Sheppo vnet_t *vnetp;
5431ae08745Sheppo int instance;
5441ae08745Sheppo
5451ae08745Sheppo instance = ddi_get_instance(dip);
546844e62a3Sraghuram DBG1(NULL, "instance(%d) enter\n", instance);
5471ae08745Sheppo
5481ae08745Sheppo vnetp = ddi_get_driver_private(dip);
5491ae08745Sheppo if (vnetp == NULL) {
5501ae08745Sheppo goto vnet_detach_fail;
5511ae08745Sheppo }
5521ae08745Sheppo
5531ae08745Sheppo switch (cmd) {
5541ae08745Sheppo case DDI_DETACH:
5551ae08745Sheppo break;
5561ae08745Sheppo case DDI_SUSPEND:
5571ae08745Sheppo case DDI_PM_SUSPEND:
5581ae08745Sheppo default:
5591ae08745Sheppo goto vnet_detach_fail;
5601ae08745Sheppo }
5611ae08745Sheppo
5626f09f0feSWENTAO YANG if (vnet_unattach(vnetp) != 0) {
563d10e4ef2Snarayan goto vnet_detach_fail;
564d10e4ef2Snarayan }
565d10e4ef2Snarayan
5666f09f0feSWENTAO YANG return (DDI_SUCCESS);
5671ae08745Sheppo
5686f09f0feSWENTAO YANG vnet_detach_fail:
5696f09f0feSWENTAO YANG return (DDI_FAILURE);
5706f09f0feSWENTAO YANG }
5716f09f0feSWENTAO YANG
5726f09f0feSWENTAO YANG /*
5736f09f0feSWENTAO YANG * Common routine to handle vnetattach() failure and vnetdetach(). Note that
5746f09f0feSWENTAO YANG * the only reason this function could fail is if mac_unregister() fails.
5756f09f0feSWENTAO YANG * Otherwise, this function must ensure that all resources are freed and return
5766f09f0feSWENTAO YANG * success.
5776f09f0feSWENTAO YANG */
5786f09f0feSWENTAO YANG static int
vnet_unattach(vnet_t * vnetp)5796f09f0feSWENTAO YANG vnet_unattach(vnet_t *vnetp)
5806f09f0feSWENTAO YANG {
5816f09f0feSWENTAO YANG vnet_attach_progress_t attach_progress;
5826f09f0feSWENTAO YANG
5836f09f0feSWENTAO YANG attach_progress = vnetp->attach_progress;
5846f09f0feSWENTAO YANG
5856f09f0feSWENTAO YANG /*
58663f531d1SSriharsha Basavapatna * Disable the mac device in the gldv3 subsystem. This can fail, in
58763f531d1SSriharsha Basavapatna * particular if there are still any open references to this mac
58863f531d1SSriharsha Basavapatna * device; in which case we just return failure without continuing to
58963f531d1SSriharsha Basavapatna * detach further.
59063f531d1SSriharsha Basavapatna * If it succeeds, we then invoke vgen_uninit() which should unregister
59163f531d1SSriharsha Basavapatna * any pseudo rings registered with the mac layer. Note we keep the
59263f531d1SSriharsha Basavapatna * AST_macreg flag on, so we can unregister with the mac layer at
59363f531d1SSriharsha Basavapatna * the end of this routine.
5946f09f0feSWENTAO YANG */
5956f09f0feSWENTAO YANG if (attach_progress & AST_macreg) {
59663f531d1SSriharsha Basavapatna if (mac_disable(vnetp->mh) != 0) {
5976f09f0feSWENTAO YANG return (1);
5986f09f0feSWENTAO YANG }
5996f09f0feSWENTAO YANG }
6006f09f0feSWENTAO YANG
6016f09f0feSWENTAO YANG /*
60263f531d1SSriharsha Basavapatna * Now that we have disabled the device, we must finish all other steps
60363f531d1SSriharsha Basavapatna * and successfully return from this function; otherwise we will end up
60463f531d1SSriharsha Basavapatna * leaving the device in a broken/unusable state.
6056f09f0feSWENTAO YANG *
6066f09f0feSWENTAO YANG * First, release any hybrid resources assigned to this vnet device.
6076f09f0feSWENTAO YANG */
6086f09f0feSWENTAO YANG if (attach_progress & AST_vdds_init) {
6096f09f0feSWENTAO YANG vdds_cleanup(vnetp);
6106f09f0feSWENTAO YANG attach_progress &= ~AST_vdds_init;
6116f09f0feSWENTAO YANG }
6126f09f0feSWENTAO YANG
6136f09f0feSWENTAO YANG /*
6146f09f0feSWENTAO YANG * Uninit vgen. This stops further mdeg callbacks to this vnet
6156f09f0feSWENTAO YANG * device and/or its ports; and detaches any existing ports.
6166f09f0feSWENTAO YANG */
61763f531d1SSriharsha Basavapatna if (attach_progress & (AST_vgen_init|AST_init_mdeg)) {
6186f09f0feSWENTAO YANG vgen_uninit(vnetp->vgenhdl);
6196f09f0feSWENTAO YANG attach_progress &= ~AST_vgen_init;
62063f531d1SSriharsha Basavapatna attach_progress &= ~AST_init_mdeg;
6216f09f0feSWENTAO YANG }
6226f09f0feSWENTAO YANG
6236f09f0feSWENTAO YANG /* Destroy the taskq. */
6246f09f0feSWENTAO YANG if (attach_progress & AST_taskq_create) {
6256f09f0feSWENTAO YANG ddi_taskq_destroy(vnetp->taskqp);
6266f09f0feSWENTAO YANG attach_progress &= ~AST_taskq_create;
6276f09f0feSWENTAO YANG }
6286f09f0feSWENTAO YANG
6296f09f0feSWENTAO YANG /* Destroy fdb. */
6306f09f0feSWENTAO YANG if (attach_progress & AST_fdbh_alloc) {
6316f09f0feSWENTAO YANG vnet_fdb_destroy(vnetp);
6326f09f0feSWENTAO YANG attach_progress &= ~AST_fdbh_alloc;
6336f09f0feSWENTAO YANG }
6346f09f0feSWENTAO YANG
6356f09f0feSWENTAO YANG /* Remove from the device list */
6366f09f0feSWENTAO YANG if (attach_progress & AST_vnet_list) {
6376f09f0feSWENTAO YANG vnet_t **vnetpp;
6381ae08745Sheppo /* unlink from instance(vnet_t) list */
6391ae08745Sheppo WRITE_ENTER(&vnet_rw);
6406f09f0feSWENTAO YANG for (vnetpp = &vnet_headp; *vnetpp;
6416f09f0feSWENTAO YANG vnetpp = &(*vnetpp)->nextp) {
6421ae08745Sheppo if (*vnetpp == vnetp) {
6431ae08745Sheppo *vnetpp = vnetp->nextp;
6441ae08745Sheppo break;
6451ae08745Sheppo }
6461ae08745Sheppo }
6471ae08745Sheppo RW_EXIT(&vnet_rw);
6486f09f0feSWENTAO YANG attach_progress &= ~AST_vnet_list;
6496f09f0feSWENTAO YANG }
6501ae08745Sheppo
65163f531d1SSriharsha Basavapatna if (attach_progress & AST_ring_init) {
65263f531d1SSriharsha Basavapatna vnet_ring_grp_uninit(vnetp);
65363f531d1SSriharsha Basavapatna attach_progress &= ~AST_ring_init;
65463f531d1SSriharsha Basavapatna }
65563f531d1SSriharsha Basavapatna
65663f531d1SSriharsha Basavapatna if (attach_progress & AST_macreg) {
65763f531d1SSriharsha Basavapatna VERIFY(mac_unregister(vnetp->mh) == 0);
65863f531d1SSriharsha Basavapatna vnetp->mh = NULL;
65963f531d1SSriharsha Basavapatna attach_progress &= ~AST_macreg;
66063f531d1SSriharsha Basavapatna }
66163f531d1SSriharsha Basavapatna
6626f09f0feSWENTAO YANG if (attach_progress & AST_vnet_alloc) {
663678453a8Sspeer rw_destroy(&vnetp->vrwlock);
664678453a8Sspeer rw_destroy(&vnetp->vsw_fp_rw);
6656f09f0feSWENTAO YANG attach_progress &= ~AST_vnet_list;
6661ae08745Sheppo KMEM_FREE(vnetp);
6676f09f0feSWENTAO YANG }
6681ae08745Sheppo
6696f09f0feSWENTAO YANG return (0);
6701ae08745Sheppo }
6711ae08745Sheppo
6721ae08745Sheppo /* enable the device for transmit/receive */
6731ae08745Sheppo static int
vnet_m_start(void * arg)6741ae08745Sheppo vnet_m_start(void *arg)
6751ae08745Sheppo {
6761ae08745Sheppo vnet_t *vnetp = arg;
6771ae08745Sheppo
678844e62a3Sraghuram DBG1(vnetp, "enter\n");
6791ae08745Sheppo
680678453a8Sspeer WRITE_ENTER(&vnetp->vrwlock);
681678453a8Sspeer vnetp->flags |= VNET_STARTED;
682678453a8Sspeer vnet_start_resources(vnetp);
683678453a8Sspeer RW_EXIT(&vnetp->vrwlock);
6841ae08745Sheppo
685844e62a3Sraghuram DBG1(vnetp, "exit\n");
6861ae08745Sheppo return (VNET_SUCCESS);
6871ae08745Sheppo
6881ae08745Sheppo }
6891ae08745Sheppo
6901ae08745Sheppo /* stop transmit/receive for the device */
6911ae08745Sheppo static void
vnet_m_stop(void * arg)6921ae08745Sheppo vnet_m_stop(void *arg)
6931ae08745Sheppo {
6941ae08745Sheppo vnet_t *vnetp = arg;
6951ae08745Sheppo
696844e62a3Sraghuram DBG1(vnetp, "enter\n");
6971ae08745Sheppo
698678453a8Sspeer WRITE_ENTER(&vnetp->vrwlock);
699678453a8Sspeer if (vnetp->flags & VNET_STARTED) {
7005460ddbdSSriharsha Basavapatna /*
7015460ddbdSSriharsha Basavapatna * Set the flags appropriately; this should prevent starting of
7025460ddbdSSriharsha Basavapatna * any new resources that are added(see vnet_res_start_task()),
7035460ddbdSSriharsha Basavapatna * while we release the vrwlock in vnet_stop_resources() before
7045460ddbdSSriharsha Basavapatna * stopping each resource.
7055460ddbdSSriharsha Basavapatna */
706678453a8Sspeer vnetp->flags &= ~VNET_STARTED;
7075460ddbdSSriharsha Basavapatna vnetp->flags |= VNET_STOPPING;
7085460ddbdSSriharsha Basavapatna vnet_stop_resources(vnetp);
7095460ddbdSSriharsha Basavapatna vnetp->flags &= ~VNET_STOPPING;
7101ae08745Sheppo }
711678453a8Sspeer RW_EXIT(&vnetp->vrwlock);
7121ae08745Sheppo
713844e62a3Sraghuram DBG1(vnetp, "exit\n");
7141ae08745Sheppo }
7151ae08745Sheppo
7161ae08745Sheppo /* set the unicast mac address of the device */
7171ae08745Sheppo static int
vnet_m_unicst(void * arg,const uint8_t * macaddr)7181ae08745Sheppo vnet_m_unicst(void *arg, const uint8_t *macaddr)
7191ae08745Sheppo {
7201ae08745Sheppo _NOTE(ARGUNUSED(macaddr))
7211ae08745Sheppo
7221ae08745Sheppo vnet_t *vnetp = arg;
7231ae08745Sheppo
724844e62a3Sraghuram DBG1(vnetp, "enter\n");
7251ae08745Sheppo /*
7263af08d82Slm66018 * NOTE: setting mac address dynamically is not supported.
7271ae08745Sheppo */
728844e62a3Sraghuram DBG1(vnetp, "exit\n");
7291ae08745Sheppo
7308e6a2a04Slm66018 return (VNET_FAILURE);
7311ae08745Sheppo }
7321ae08745Sheppo
7331ae08745Sheppo /* enable/disable a multicast address */
7341ae08745Sheppo static int
vnet_m_multicst(void * arg,boolean_t add,const uint8_t * mca)7351ae08745Sheppo vnet_m_multicst(void *arg, boolean_t add, const uint8_t *mca)
7361ae08745Sheppo {
7371ae08745Sheppo _NOTE(ARGUNUSED(add, mca))
7381ae08745Sheppo
7391ae08745Sheppo vnet_t *vnetp = arg;
740678453a8Sspeer vnet_res_t *vresp;
741678453a8Sspeer mac_register_t *macp;
742ba2e4443Sseb mac_callbacks_t *cbp;
7431ae08745Sheppo int rv = VNET_SUCCESS;
7441ae08745Sheppo
745844e62a3Sraghuram DBG1(vnetp, "enter\n");
746678453a8Sspeer
7470c4606f0SWENTAO YANG READ_ENTER(&vnetp->vsw_fp_rw);
7480c4606f0SWENTAO YANG if (vnetp->vsw_fp == NULL) {
7490c4606f0SWENTAO YANG RW_EXIT(&vnetp->vsw_fp_rw);
7500c4606f0SWENTAO YANG return (EAGAIN);
7510c4606f0SWENTAO YANG }
7520c4606f0SWENTAO YANG VNET_FDBE_REFHOLD(vnetp->vsw_fp);
7530c4606f0SWENTAO YANG RW_EXIT(&vnetp->vsw_fp_rw);
7540c4606f0SWENTAO YANG
7550c4606f0SWENTAO YANG vresp = vnetp->vsw_fp;
756678453a8Sspeer macp = &vresp->macreg;
757678453a8Sspeer cbp = macp->m_callbacks;
758678453a8Sspeer rv = cbp->mc_multicst(macp->m_driver, add, mca);
7590c4606f0SWENTAO YANG
7600c4606f0SWENTAO YANG VNET_FDBE_REFRELE(vnetp->vsw_fp);
761678453a8Sspeer
762844e62a3Sraghuram DBG1(vnetp, "exit(%d)\n", rv);
7631ae08745Sheppo return (rv);
7641ae08745Sheppo }
7651ae08745Sheppo
7661ae08745Sheppo /* set or clear promiscuous mode on the device */
7671ae08745Sheppo static int
vnet_m_promisc(void * arg,boolean_t on)7681ae08745Sheppo vnet_m_promisc(void *arg, boolean_t on)
7691ae08745Sheppo {
7701ae08745Sheppo _NOTE(ARGUNUSED(on))
7711ae08745Sheppo
7721ae08745Sheppo vnet_t *vnetp = arg;
773844e62a3Sraghuram DBG1(vnetp, "enter\n");
7741ae08745Sheppo /*
7753af08d82Slm66018 * NOTE: setting promiscuous mode is not supported, just return success.
7761ae08745Sheppo */
777844e62a3Sraghuram DBG1(vnetp, "exit\n");
7781ae08745Sheppo return (VNET_SUCCESS);
7791ae08745Sheppo }
7801ae08745Sheppo
7811ae08745Sheppo /*
7821ae08745Sheppo * Transmit a chain of packets. This function provides switching functionality
7831ae08745Sheppo * based on the destination mac address to reach other guests (within ldoms) or
7841ae08745Sheppo * external hosts.
7851ae08745Sheppo */
7861ae08745Sheppo mblk_t *
vnet_tx_ring_send(void * arg,mblk_t * mp)78763f531d1SSriharsha Basavapatna vnet_tx_ring_send(void *arg, mblk_t *mp)
7881ae08745Sheppo {
78963f531d1SSriharsha Basavapatna vnet_pseudo_tx_ring_t *tx_ringp;
7900dc2366fSVenugopal Iyer vnet_tx_ring_stats_t *statsp;
7911ae08745Sheppo vnet_t *vnetp;
792678453a8Sspeer vnet_res_t *vresp;
7931ae08745Sheppo mblk_t *next;
7941ae08745Sheppo mblk_t *resid_mp;
795678453a8Sspeer mac_register_t *macp;
796c1c61f44Ssb155480 struct ether_header *ehp;
797678453a8Sspeer boolean_t is_unicast;
7988c242ab0SSriharsha Basavapatna boolean_t is_pvid; /* non-default pvid ? */
7998c242ab0SSriharsha Basavapatna boolean_t hres; /* Hybrid resource ? */
80063f531d1SSriharsha Basavapatna void *tx_arg;
8010dc2366fSVenugopal Iyer size_t size;
8021ae08745Sheppo
80363f531d1SSriharsha Basavapatna tx_ringp = (vnet_pseudo_tx_ring_t *)arg;
8040dc2366fSVenugopal Iyer statsp = &tx_ringp->tx_ring_stats;
80563f531d1SSriharsha Basavapatna vnetp = (vnet_t *)tx_ringp->vnetp;
806844e62a3Sraghuram DBG1(vnetp, "enter\n");
8071ae08745Sheppo ASSERT(mp != NULL);
8081ae08745Sheppo
8098c242ab0SSriharsha Basavapatna is_pvid = (vnetp->pvid != vnetp->default_vlan_id) ? B_TRUE : B_FALSE;
8108c242ab0SSriharsha Basavapatna
8111ae08745Sheppo while (mp != NULL) {
812c1c61f44Ssb155480
8131ae08745Sheppo next = mp->b_next;
8141ae08745Sheppo mp->b_next = NULL;
8151ae08745Sheppo
8160dc2366fSVenugopal Iyer /* update stats */
8170dc2366fSVenugopal Iyer size = msgsize(mp);
8180dc2366fSVenugopal Iyer
8191ae08745Sheppo /*
820c1c61f44Ssb155480 * Find fdb entry for the destination
821c1c61f44Ssb155480 * and hold a reference to it.
8221ae08745Sheppo */
823c1c61f44Ssb155480 ehp = (struct ether_header *)mp->b_rptr;
824678453a8Sspeer vresp = vnet_fdbe_find(vnetp, &ehp->ether_dhost);
825678453a8Sspeer if (vresp != NULL) {
826c1c61f44Ssb155480
827c1c61f44Ssb155480 /*
828c1c61f44Ssb155480 * Destination found in FDB.
829c1c61f44Ssb155480 * The destination is a vnet device within ldoms
830c1c61f44Ssb155480 * and directly reachable, invoke the tx function
831c1c61f44Ssb155480 * in the fdb entry.
832c1c61f44Ssb155480 */
833678453a8Sspeer macp = &vresp->macreg;
834678453a8Sspeer resid_mp = macp->m_callbacks->mc_tx(macp->m_driver, mp);
835c1c61f44Ssb155480
836c1c61f44Ssb155480 /* tx done; now release ref on fdb entry */
837678453a8Sspeer VNET_FDBE_REFRELE(vresp);
838c1c61f44Ssb155480
8391ae08745Sheppo if (resid_mp != NULL) {
8401ae08745Sheppo /* m_tx failed */
8411ae08745Sheppo mp->b_next = next;
8421ae08745Sheppo break;
8431ae08745Sheppo }
8441ae08745Sheppo } else {
845678453a8Sspeer is_unicast = !(IS_BROADCAST(ehp) ||
846678453a8Sspeer (IS_MULTICAST(ehp)));
8471ae08745Sheppo /*
848c1c61f44Ssb155480 * Destination is not in FDB.
849678453a8Sspeer * If the destination is broadcast or multicast,
850678453a8Sspeer * then forward the packet to vswitch.
851678453a8Sspeer * If a Hybrid resource avilable, then send the
852678453a8Sspeer * unicast packet via hybrid resource, otherwise
853678453a8Sspeer * forward it to vswitch.
8541ae08745Sheppo */
855c1c61f44Ssb155480 READ_ENTER(&vnetp->vsw_fp_rw);
856c1c61f44Ssb155480
857678453a8Sspeer if ((is_unicast) && (vnetp->hio_fp != NULL)) {
858678453a8Sspeer vresp = vnetp->hio_fp;
8598c242ab0SSriharsha Basavapatna hres = B_TRUE;
860678453a8Sspeer } else {
861678453a8Sspeer vresp = vnetp->vsw_fp;
8628c242ab0SSriharsha Basavapatna hres = B_FALSE;
863678453a8Sspeer }
864678453a8Sspeer if (vresp == NULL) {
865c1c61f44Ssb155480 /*
866c1c61f44Ssb155480 * no fdb entry to vsw? drop the packet.
867c1c61f44Ssb155480 */
868c1c61f44Ssb155480 RW_EXIT(&vnetp->vsw_fp_rw);
869c1c61f44Ssb155480 freemsg(mp);
870c1c61f44Ssb155480 mp = next;
871c1c61f44Ssb155480 continue;
872c1c61f44Ssb155480 }
873c1c61f44Ssb155480
874c1c61f44Ssb155480 /* ref hold the fdb entry to vsw */
875678453a8Sspeer VNET_FDBE_REFHOLD(vresp);
876c1c61f44Ssb155480
877c1c61f44Ssb155480 RW_EXIT(&vnetp->vsw_fp_rw);
878c1c61f44Ssb155480
8798c242ab0SSriharsha Basavapatna /*
8808c242ab0SSriharsha Basavapatna * In the case of a hybrid resource we need to insert
8818c242ab0SSriharsha Basavapatna * the tag for the pvid case here; unlike packets that
8828c242ab0SSriharsha Basavapatna * are destined to a vnet/vsw in which case the vgen
8838c242ab0SSriharsha Basavapatna * layer does the tagging before sending it over ldc.
8848c242ab0SSriharsha Basavapatna */
8858c242ab0SSriharsha Basavapatna if (hres == B_TRUE) {
8868c242ab0SSriharsha Basavapatna /*
8878c242ab0SSriharsha Basavapatna * Determine if the frame being transmitted
8888c242ab0SSriharsha Basavapatna * over the hybrid resource is untagged. If so,
8898c242ab0SSriharsha Basavapatna * insert the tag before transmitting.
8908c242ab0SSriharsha Basavapatna */
8918c242ab0SSriharsha Basavapatna if (is_pvid == B_TRUE &&
8928c242ab0SSriharsha Basavapatna ehp->ether_type != htons(ETHERTYPE_VLAN)) {
8938c242ab0SSriharsha Basavapatna
8948c242ab0SSriharsha Basavapatna mp = vnet_vlan_insert_tag(mp,
8958c242ab0SSriharsha Basavapatna vnetp->pvid);
8968c242ab0SSriharsha Basavapatna if (mp == NULL) {
8978c242ab0SSriharsha Basavapatna VNET_FDBE_REFRELE(vresp);
8988c242ab0SSriharsha Basavapatna mp = next;
8998c242ab0SSriharsha Basavapatna continue;
9008c242ab0SSriharsha Basavapatna }
9018c242ab0SSriharsha Basavapatna
9028c242ab0SSriharsha Basavapatna }
9038c242ab0SSriharsha Basavapatna
904678453a8Sspeer macp = &vresp->macreg;
90563f531d1SSriharsha Basavapatna tx_arg = tx_ringp;
90663f531d1SSriharsha Basavapatna } else {
90763f531d1SSriharsha Basavapatna macp = &vresp->macreg;
90863f531d1SSriharsha Basavapatna tx_arg = macp->m_driver;
90963f531d1SSriharsha Basavapatna }
91063f531d1SSriharsha Basavapatna resid_mp = macp->m_callbacks->mc_tx(tx_arg, mp);
911c1c61f44Ssb155480
912c1c61f44Ssb155480 /* tx done; now release ref on fdb entry */
913678453a8Sspeer VNET_FDBE_REFRELE(vresp);
914c1c61f44Ssb155480
9151ae08745Sheppo if (resid_mp != NULL) {
9161ae08745Sheppo /* m_tx failed */
9171ae08745Sheppo mp->b_next = next;
9181ae08745Sheppo break;
9191ae08745Sheppo }
9201ae08745Sheppo }
9211ae08745Sheppo
9220dc2366fSVenugopal Iyer statsp->obytes += size;
9230dc2366fSVenugopal Iyer statsp->opackets++;
9241ae08745Sheppo mp = next;
9251ae08745Sheppo }
9261ae08745Sheppo
927844e62a3Sraghuram DBG1(vnetp, "exit\n");
9281ae08745Sheppo return (mp);
9291ae08745Sheppo }
9301ae08745Sheppo
9311ae08745Sheppo /* get statistics from the device */
932ba2e4443Sseb int
vnet_m_stat(void * arg,uint_t stat,uint64_t * val)933ba2e4443Sseb vnet_m_stat(void *arg, uint_t stat, uint64_t *val)
9341ae08745Sheppo {
9351ae08745Sheppo vnet_t *vnetp = arg;
936678453a8Sspeer vnet_res_t *vresp;
937678453a8Sspeer mac_register_t *macp;
938ba2e4443Sseb mac_callbacks_t *cbp;
939ba2e4443Sseb uint64_t val_total = 0;
9401ae08745Sheppo
941844e62a3Sraghuram DBG1(vnetp, "enter\n");
9421ae08745Sheppo
9431ae08745Sheppo /*
944ba2e4443Sseb * get the specified statistic from each transport and return the
945ba2e4443Sseb * aggregate val. This obviously only works for counters.
9461ae08745Sheppo */
947ba2e4443Sseb if ((IS_MAC_STAT(stat) && !MAC_STAT_ISACOUNTER(stat)) ||
948ba2e4443Sseb (IS_MACTYPE_STAT(stat) && !ETHER_STAT_ISACOUNTER(stat))) {
949ba2e4443Sseb return (ENOTSUP);
950ba2e4443Sseb }
951678453a8Sspeer
952678453a8Sspeer READ_ENTER(&vnetp->vrwlock);
953678453a8Sspeer for (vresp = vnetp->vres_list; vresp != NULL; vresp = vresp->nextp) {
954678453a8Sspeer macp = &vresp->macreg;
955678453a8Sspeer cbp = macp->m_callbacks;
956678453a8Sspeer if (cbp->mc_getstat(macp->m_driver, stat, val) == 0)
957ba2e4443Sseb val_total += *val;
9581ae08745Sheppo }
959678453a8Sspeer RW_EXIT(&vnetp->vrwlock);
9601ae08745Sheppo
961ba2e4443Sseb *val = val_total;
962ba2e4443Sseb
963844e62a3Sraghuram DBG1(vnetp, "exit\n");
964ba2e4443Sseb return (0);
9651ae08745Sheppo }
9661ae08745Sheppo
96763f531d1SSriharsha Basavapatna static void
vnet_ring_grp_init(vnet_t * vnetp)96863f531d1SSriharsha Basavapatna vnet_ring_grp_init(vnet_t *vnetp)
96963f531d1SSriharsha Basavapatna {
97063f531d1SSriharsha Basavapatna vnet_pseudo_rx_group_t *rx_grp;
97163f531d1SSriharsha Basavapatna vnet_pseudo_rx_ring_t *rx_ringp;
97263f531d1SSriharsha Basavapatna vnet_pseudo_tx_group_t *tx_grp;
97363f531d1SSriharsha Basavapatna vnet_pseudo_tx_ring_t *tx_ringp;
97463f531d1SSriharsha Basavapatna int i;
97563f531d1SSriharsha Basavapatna
97663f531d1SSriharsha Basavapatna tx_grp = &vnetp->tx_grp[0];
97763f531d1SSriharsha Basavapatna tx_ringp = kmem_zalloc(sizeof (vnet_pseudo_tx_ring_t) *
97863f531d1SSriharsha Basavapatna VNET_NUM_PSEUDO_TXRINGS, KM_SLEEP);
97963f531d1SSriharsha Basavapatna for (i = 0; i < VNET_NUM_PSEUDO_TXRINGS; i++) {
98063f531d1SSriharsha Basavapatna tx_ringp[i].state |= VNET_TXRING_SHARED;
98163f531d1SSriharsha Basavapatna }
98263f531d1SSriharsha Basavapatna tx_grp->rings = tx_ringp;
98363f531d1SSriharsha Basavapatna tx_grp->ring_cnt = VNET_NUM_PSEUDO_TXRINGS;
9840dc2366fSVenugopal Iyer mutex_init(&tx_grp->flowctl_lock, NULL, MUTEX_DRIVER, NULL);
9850dc2366fSVenugopal Iyer cv_init(&tx_grp->flowctl_cv, NULL, CV_DRIVER, NULL);
9860dc2366fSVenugopal Iyer tx_grp->flowctl_thread = thread_create(NULL, 0,
9870dc2366fSVenugopal Iyer vnet_tx_notify_thread, tx_grp, 0, &p0, TS_RUN, minclsyspri);
98863f531d1SSriharsha Basavapatna
98963f531d1SSriharsha Basavapatna rx_grp = &vnetp->rx_grp[0];
99063f531d1SSriharsha Basavapatna rx_grp->max_ring_cnt = MAX_RINGS_PER_GROUP;
99163f531d1SSriharsha Basavapatna rw_init(&rx_grp->lock, NULL, RW_DRIVER, NULL);
99263f531d1SSriharsha Basavapatna rx_ringp = kmem_zalloc(sizeof (vnet_pseudo_rx_ring_t) *
99363f531d1SSriharsha Basavapatna rx_grp->max_ring_cnt, KM_SLEEP);
99463f531d1SSriharsha Basavapatna
99563f531d1SSriharsha Basavapatna /*
99663f531d1SSriharsha Basavapatna * Setup the first 3 Pseudo RX Rings that are reserved;
99763f531d1SSriharsha Basavapatna * 1 for LDC resource to vswitch + 2 for RX rings of Hybrid resource.
99863f531d1SSriharsha Basavapatna */
99963f531d1SSriharsha Basavapatna rx_ringp[0].state |= VNET_RXRING_INUSE|VNET_RXRING_LDC_SERVICE;
100063f531d1SSriharsha Basavapatna rx_ringp[0].index = 0;
100163f531d1SSriharsha Basavapatna rx_ringp[1].state |= VNET_RXRING_INUSE|VNET_RXRING_HYBRID;
100263f531d1SSriharsha Basavapatna rx_ringp[1].index = 1;
100363f531d1SSriharsha Basavapatna rx_ringp[2].state |= VNET_RXRING_INUSE|VNET_RXRING_HYBRID;
100463f531d1SSriharsha Basavapatna rx_ringp[2].index = 2;
100563f531d1SSriharsha Basavapatna
100663f531d1SSriharsha Basavapatna rx_grp->ring_cnt = VNET_NUM_PSEUDO_RXRINGS_DEFAULT;
100763f531d1SSriharsha Basavapatna rx_grp->rings = rx_ringp;
100863f531d1SSriharsha Basavapatna
100963f531d1SSriharsha Basavapatna for (i = VNET_NUM_PSEUDO_RXRINGS_DEFAULT;
101063f531d1SSriharsha Basavapatna i < rx_grp->max_ring_cnt; i++) {
101163f531d1SSriharsha Basavapatna rx_ringp = &rx_grp->rings[i];
101263f531d1SSriharsha Basavapatna rx_ringp->state = VNET_RXRING_FREE;
101363f531d1SSriharsha Basavapatna rx_ringp->index = i;
101463f531d1SSriharsha Basavapatna }
101563f531d1SSriharsha Basavapatna }
101663f531d1SSriharsha Basavapatna
101763f531d1SSriharsha Basavapatna static void
vnet_ring_grp_uninit(vnet_t * vnetp)101863f531d1SSriharsha Basavapatna vnet_ring_grp_uninit(vnet_t *vnetp)
101963f531d1SSriharsha Basavapatna {
102063f531d1SSriharsha Basavapatna vnet_pseudo_rx_group_t *rx_grp;
102163f531d1SSriharsha Basavapatna vnet_pseudo_tx_group_t *tx_grp;
10220dc2366fSVenugopal Iyer kt_did_t tid = 0;
102363f531d1SSriharsha Basavapatna
102463f531d1SSriharsha Basavapatna tx_grp = &vnetp->tx_grp[0];
10250dc2366fSVenugopal Iyer
10260dc2366fSVenugopal Iyer /* Inform tx_notify_thread to exit */
10270dc2366fSVenugopal Iyer mutex_enter(&tx_grp->flowctl_lock);
10280dc2366fSVenugopal Iyer if (tx_grp->flowctl_thread != NULL) {
10290dc2366fSVenugopal Iyer tid = tx_grp->flowctl_thread->t_did;
10300dc2366fSVenugopal Iyer tx_grp->flowctl_done = B_TRUE;
10310dc2366fSVenugopal Iyer cv_signal(&tx_grp->flowctl_cv);
10320dc2366fSVenugopal Iyer }
10330dc2366fSVenugopal Iyer mutex_exit(&tx_grp->flowctl_lock);
10340dc2366fSVenugopal Iyer if (tid != 0)
10350dc2366fSVenugopal Iyer thread_join(tid);
10360dc2366fSVenugopal Iyer
103763f531d1SSriharsha Basavapatna if (tx_grp->rings != NULL) {
103863f531d1SSriharsha Basavapatna ASSERT(tx_grp->ring_cnt == VNET_NUM_PSEUDO_TXRINGS);
103963f531d1SSriharsha Basavapatna kmem_free(tx_grp->rings, sizeof (vnet_pseudo_tx_ring_t) *
104063f531d1SSriharsha Basavapatna tx_grp->ring_cnt);
104163f531d1SSriharsha Basavapatna tx_grp->rings = NULL;
104263f531d1SSriharsha Basavapatna }
104363f531d1SSriharsha Basavapatna
104463f531d1SSriharsha Basavapatna rx_grp = &vnetp->rx_grp[0];
104563f531d1SSriharsha Basavapatna if (rx_grp->rings != NULL) {
104663f531d1SSriharsha Basavapatna ASSERT(rx_grp->max_ring_cnt == MAX_RINGS_PER_GROUP);
104763f531d1SSriharsha Basavapatna ASSERT(rx_grp->ring_cnt == VNET_NUM_PSEUDO_RXRINGS_DEFAULT);
104863f531d1SSriharsha Basavapatna kmem_free(rx_grp->rings, sizeof (vnet_pseudo_rx_ring_t) *
104963f531d1SSriharsha Basavapatna rx_grp->max_ring_cnt);
105063f531d1SSriharsha Basavapatna rx_grp->rings = NULL;
105163f531d1SSriharsha Basavapatna }
105263f531d1SSriharsha Basavapatna }
105363f531d1SSriharsha Basavapatna
105463f531d1SSriharsha Basavapatna static vnet_pseudo_rx_ring_t *
vnet_alloc_pseudo_rx_ring(vnet_t * vnetp)105563f531d1SSriharsha Basavapatna vnet_alloc_pseudo_rx_ring(vnet_t *vnetp)
105663f531d1SSriharsha Basavapatna {
105763f531d1SSriharsha Basavapatna vnet_pseudo_rx_group_t *rx_grp;
105863f531d1SSriharsha Basavapatna vnet_pseudo_rx_ring_t *rx_ringp;
105963f531d1SSriharsha Basavapatna int index;
106063f531d1SSriharsha Basavapatna
106163f531d1SSriharsha Basavapatna rx_grp = &vnetp->rx_grp[0];
106263f531d1SSriharsha Basavapatna WRITE_ENTER(&rx_grp->lock);
106363f531d1SSriharsha Basavapatna
106463f531d1SSriharsha Basavapatna if (rx_grp->ring_cnt == rx_grp->max_ring_cnt) {
106563f531d1SSriharsha Basavapatna /* no rings available */
106663f531d1SSriharsha Basavapatna RW_EXIT(&rx_grp->lock);
106763f531d1SSriharsha Basavapatna return (NULL);
106863f531d1SSriharsha Basavapatna }
106963f531d1SSriharsha Basavapatna
107063f531d1SSriharsha Basavapatna for (index = VNET_NUM_PSEUDO_RXRINGS_DEFAULT;
107163f531d1SSriharsha Basavapatna index < rx_grp->max_ring_cnt; index++) {
107263f531d1SSriharsha Basavapatna rx_ringp = &rx_grp->rings[index];
107363f531d1SSriharsha Basavapatna if (rx_ringp->state == VNET_RXRING_FREE) {
107463f531d1SSriharsha Basavapatna rx_ringp->state |= VNET_RXRING_INUSE;
107563f531d1SSriharsha Basavapatna rx_grp->ring_cnt++;
107663f531d1SSriharsha Basavapatna break;
107763f531d1SSriharsha Basavapatna }
107863f531d1SSriharsha Basavapatna }
107963f531d1SSriharsha Basavapatna
108063f531d1SSriharsha Basavapatna RW_EXIT(&rx_grp->lock);
108163f531d1SSriharsha Basavapatna return (rx_ringp);
108263f531d1SSriharsha Basavapatna }
108363f531d1SSriharsha Basavapatna
108463f531d1SSriharsha Basavapatna static void
vnet_free_pseudo_rx_ring(vnet_t * vnetp,vnet_pseudo_rx_ring_t * ringp)108563f531d1SSriharsha Basavapatna vnet_free_pseudo_rx_ring(vnet_t *vnetp, vnet_pseudo_rx_ring_t *ringp)
108663f531d1SSriharsha Basavapatna {
108763f531d1SSriharsha Basavapatna vnet_pseudo_rx_group_t *rx_grp;
108863f531d1SSriharsha Basavapatna
108963f531d1SSriharsha Basavapatna ASSERT(ringp->index >= VNET_NUM_PSEUDO_RXRINGS_DEFAULT);
109063f531d1SSriharsha Basavapatna rx_grp = &vnetp->rx_grp[0];
109163f531d1SSriharsha Basavapatna WRITE_ENTER(&rx_grp->lock);
109263f531d1SSriharsha Basavapatna
109363f531d1SSriharsha Basavapatna if (ringp->state != VNET_RXRING_FREE) {
109463f531d1SSriharsha Basavapatna ringp->state = VNET_RXRING_FREE;
109563f531d1SSriharsha Basavapatna ringp->handle = NULL;
109663f531d1SSriharsha Basavapatna rx_grp->ring_cnt--;
109763f531d1SSriharsha Basavapatna }
109863f531d1SSriharsha Basavapatna
109963f531d1SSriharsha Basavapatna RW_EXIT(&rx_grp->lock);
110063f531d1SSriharsha Basavapatna }
110163f531d1SSriharsha Basavapatna
11021ae08745Sheppo /* wrapper function for mac_register() */
11031ae08745Sheppo static int
vnet_mac_register(vnet_t * vnetp)11041ae08745Sheppo vnet_mac_register(vnet_t *vnetp)
11051ae08745Sheppo {
1106ba2e4443Sseb mac_register_t *macp;
1107ba2e4443Sseb int err;
11081ae08745Sheppo
1109ba2e4443Sseb if ((macp = mac_alloc(MAC_VERSION)) == NULL)
1110ba2e4443Sseb return (DDI_FAILURE);
1111ba2e4443Sseb macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
1112ba2e4443Sseb macp->m_driver = vnetp;
11131ae08745Sheppo macp->m_dip = vnetp->dip;
1114ba2e4443Sseb macp->m_src_addr = vnetp->curr_macaddr;
1115ba2e4443Sseb macp->m_callbacks = &vnet_m_callbacks;
1116ba2e4443Sseb macp->m_min_sdu = 0;
11177b1f684aSSriharsha Basavapatna macp->m_max_sdu = vnetp->mtu;
1118c1c61f44Ssb155480 macp->m_margin = VLAN_TAGSZ;
11191ae08745Sheppo
112063f531d1SSriharsha Basavapatna macp->m_v12n = MAC_VIRT_LEVEL1;
112163f531d1SSriharsha Basavapatna
112263f531d1SSriharsha Basavapatna /*
11231ae08745Sheppo * Finally, we're ready to register ourselves with the MAC layer
11241ae08745Sheppo * interface; if this succeeds, we're all ready to start()
11251ae08745Sheppo */
1126ba2e4443Sseb err = mac_register(macp, &vnetp->mh);
1127ba2e4443Sseb mac_free(macp);
1128ba2e4443Sseb return (err == 0 ? DDI_SUCCESS : DDI_FAILURE);
11291ae08745Sheppo }
11301ae08745Sheppo
11311ae08745Sheppo /* read the mac address of the device */
11321ae08745Sheppo static int
vnet_read_mac_address(vnet_t * vnetp)11331ae08745Sheppo vnet_read_mac_address(vnet_t *vnetp)
11341ae08745Sheppo {
11351ae08745Sheppo uchar_t *macaddr;
11361ae08745Sheppo uint32_t size;
11371ae08745Sheppo int rv;
11381ae08745Sheppo
11391ae08745Sheppo rv = ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, vnetp->dip,
11401ae08745Sheppo DDI_PROP_DONTPASS, macaddr_propname, &macaddr, &size);
11411ae08745Sheppo if ((rv != DDI_PROP_SUCCESS) || (size != ETHERADDRL)) {
1142844e62a3Sraghuram DWARN(vnetp, "prop_lookup failed(%s) err(%d)\n",
1143844e62a3Sraghuram macaddr_propname, rv);
11441ae08745Sheppo return (DDI_FAILURE);
11451ae08745Sheppo }
11461ae08745Sheppo bcopy(macaddr, (caddr_t)vnetp->vendor_addr, ETHERADDRL);
11471ae08745Sheppo bcopy(macaddr, (caddr_t)vnetp->curr_macaddr, ETHERADDRL);
11481ae08745Sheppo ddi_prop_free(macaddr);
11491ae08745Sheppo
11501ae08745Sheppo return (DDI_SUCCESS);
11511ae08745Sheppo }
11521ae08745Sheppo
115393b13a42Swentaoy static void
vnet_fdb_create(vnet_t * vnetp)1154c1c61f44Ssb155480 vnet_fdb_create(vnet_t *vnetp)
115593b13a42Swentaoy {
1156c1c61f44Ssb155480 char hashname[MAXNAMELEN];
115793b13a42Swentaoy
1158c1c61f44Ssb155480 (void) snprintf(hashname, MAXNAMELEN, "vnet%d-fdbhash",
1159c1c61f44Ssb155480 vnetp->instance);
1160c1c61f44Ssb155480 vnetp->fdb_nchains = vnet_fdb_nchains;
1161c1c61f44Ssb155480 vnetp->fdb_hashp = mod_hash_create_ptrhash(hashname, vnetp->fdb_nchains,
1162c1c61f44Ssb155480 mod_hash_null_valdtor, sizeof (void *));
116393b13a42Swentaoy }
116493b13a42Swentaoy
116593b13a42Swentaoy static void
vnet_fdb_destroy(vnet_t * vnetp)1166c1c61f44Ssb155480 vnet_fdb_destroy(vnet_t *vnetp)
116793b13a42Swentaoy {
1168c1c61f44Ssb155480 /* destroy fdb-hash-table */
1169c1c61f44Ssb155480 if (vnetp->fdb_hashp != NULL) {
1170c1c61f44Ssb155480 mod_hash_destroy_hash(vnetp->fdb_hashp);
1171c1c61f44Ssb155480 vnetp->fdb_hashp = NULL;
1172c1c61f44Ssb155480 vnetp->fdb_nchains = 0;
1173c1c61f44Ssb155480 }
117493b13a42Swentaoy }
117593b13a42Swentaoy
117693b13a42Swentaoy /*
1177c1c61f44Ssb155480 * Add an entry into the fdb.
117893b13a42Swentaoy */
11791ae08745Sheppo void
vnet_fdbe_add(vnet_t * vnetp,vnet_res_t * vresp)1180678453a8Sspeer vnet_fdbe_add(vnet_t *vnetp, vnet_res_t *vresp)
11811ae08745Sheppo {
1182c1c61f44Ssb155480 uint64_t addr = 0;
1183c1c61f44Ssb155480 int rv;
1184c1c61f44Ssb155480
1185678453a8Sspeer KEY_HASH(addr, vresp->rem_macaddr);
11861ae08745Sheppo
11871ae08745Sheppo /*
1188678453a8Sspeer * If the entry being added corresponds to LDC_SERVICE resource,
1189678453a8Sspeer * that is, vswitch connection, it is added to the hash and also
1190678453a8Sspeer * the entry is cached, an additional reference count reflects
1191678453a8Sspeer * this. The HYBRID resource is not added to the hash, but only
1192678453a8Sspeer * cached, as it is only used for sending out packets for unknown
1193678453a8Sspeer * unicast destinations.
11941ae08745Sheppo */
1195678453a8Sspeer (vresp->type == VIO_NET_RES_LDC_SERVICE) ?
1196678453a8Sspeer (vresp->refcnt = 1) : (vresp->refcnt = 0);
11971ae08745Sheppo
1198c1c61f44Ssb155480 /*
1199c1c61f44Ssb155480 * Note: duplicate keys will be rejected by mod_hash.
1200c1c61f44Ssb155480 */
1201678453a8Sspeer if (vresp->type != VIO_NET_RES_HYBRID) {
1202c1c61f44Ssb155480 rv = mod_hash_insert(vnetp->fdb_hashp, (mod_hash_key_t)addr,
1203678453a8Sspeer (mod_hash_val_t)vresp);
1204c1c61f44Ssb155480 if (rv != 0) {
1205c1c61f44Ssb155480 DWARN(vnetp, "Duplicate macaddr key(%lx)\n", addr);
12061ae08745Sheppo return;
12071ae08745Sheppo }
1208678453a8Sspeer }
12091ae08745Sheppo
1210678453a8Sspeer if (vresp->type == VIO_NET_RES_LDC_SERVICE) {
1211c1c61f44Ssb155480 /* Cache the fdb entry to vsw-port */
1212c1c61f44Ssb155480 WRITE_ENTER(&vnetp->vsw_fp_rw);
1213c1c61f44Ssb155480 if (vnetp->vsw_fp == NULL)
1214678453a8Sspeer vnetp->vsw_fp = vresp;
1215678453a8Sspeer RW_EXIT(&vnetp->vsw_fp_rw);
1216678453a8Sspeer } else if (vresp->type == VIO_NET_RES_HYBRID) {
1217678453a8Sspeer /* Cache the fdb entry to hybrid resource */
1218678453a8Sspeer WRITE_ENTER(&vnetp->vsw_fp_rw);
1219678453a8Sspeer if (vnetp->hio_fp == NULL)
1220678453a8Sspeer vnetp->hio_fp = vresp;
1221c1c61f44Ssb155480 RW_EXIT(&vnetp->vsw_fp_rw);
1222c1c61f44Ssb155480 }
12231ae08745Sheppo }
12241ae08745Sheppo
1225c1c61f44Ssb155480 /*
1226c1c61f44Ssb155480 * Remove an entry from fdb.
1227c1c61f44Ssb155480 */
1228678453a8Sspeer static void
vnet_fdbe_del(vnet_t * vnetp,vnet_res_t * vresp)1229678453a8Sspeer vnet_fdbe_del(vnet_t *vnetp, vnet_res_t *vresp)
12301ae08745Sheppo {
1231c1c61f44Ssb155480 uint64_t addr = 0;
1232c1c61f44Ssb155480 int rv;
1233c1c61f44Ssb155480 uint32_t refcnt;
1234678453a8Sspeer vnet_res_t *tmp;
1235c1c61f44Ssb155480
1236678453a8Sspeer KEY_HASH(addr, vresp->rem_macaddr);
12371ae08745Sheppo
12381ae08745Sheppo /*
1239c1c61f44Ssb155480 * Remove the entry from fdb hash table.
1240c1c61f44Ssb155480 * This prevents further references to this fdb entry.
12411ae08745Sheppo */
1242678453a8Sspeer if (vresp->type != VIO_NET_RES_HYBRID) {
1243c1c61f44Ssb155480 rv = mod_hash_remove(vnetp->fdb_hashp, (mod_hash_key_t)addr,
1244678453a8Sspeer (mod_hash_val_t *)&tmp);
1245678453a8Sspeer if (rv != 0) {
1246678453a8Sspeer /*
1247678453a8Sspeer * As the resources are added to the hash only
1248678453a8Sspeer * after they are started, this can occur if
1249678453a8Sspeer * a resource unregisters before it is ever started.
1250678453a8Sspeer */
1251678453a8Sspeer return;
1252678453a8Sspeer }
1253678453a8Sspeer }
12541ae08745Sheppo
1255678453a8Sspeer if (vresp->type == VIO_NET_RES_LDC_SERVICE) {
1256c1c61f44Ssb155480 WRITE_ENTER(&vnetp->vsw_fp_rw);
12571ae08745Sheppo
1258678453a8Sspeer ASSERT(tmp == vnetp->vsw_fp);
1259c1c61f44Ssb155480 vnetp->vsw_fp = NULL;
1260c1c61f44Ssb155480
1261c1c61f44Ssb155480 RW_EXIT(&vnetp->vsw_fp_rw);
1262678453a8Sspeer } else if (vresp->type == VIO_NET_RES_HYBRID) {
1263678453a8Sspeer WRITE_ENTER(&vnetp->vsw_fp_rw);
1264678453a8Sspeer
1265678453a8Sspeer vnetp->hio_fp = NULL;
1266678453a8Sspeer
1267678453a8Sspeer RW_EXIT(&vnetp->vsw_fp_rw);
12681ae08745Sheppo }
12691ae08745Sheppo
1270c1c61f44Ssb155480 /*
1271c1c61f44Ssb155480 * If there are threads already ref holding before the entry was
1272c1c61f44Ssb155480 * removed from hash table, then wait for ref count to drop to zero.
1273c1c61f44Ssb155480 */
1274678453a8Sspeer (vresp->type == VIO_NET_RES_LDC_SERVICE) ?
1275678453a8Sspeer (refcnt = 1) : (refcnt = 0);
1276678453a8Sspeer while (vresp->refcnt > refcnt) {
1277c1c61f44Ssb155480 delay(drv_usectohz(vnet_fdbe_refcnt_delay));
1278c1c61f44Ssb155480 }
1279c1c61f44Ssb155480 }
1280c1c61f44Ssb155480
1281c1c61f44Ssb155480 /*
1282c1c61f44Ssb155480 * Search fdb for a given mac address. If an entry is found, hold
1283c1c61f44Ssb155480 * a reference to it and return the entry; else returns NULL.
1284c1c61f44Ssb155480 */
1285678453a8Sspeer static vnet_res_t *
vnet_fdbe_find(vnet_t * vnetp,struct ether_addr * addrp)1286c1c61f44Ssb155480 vnet_fdbe_find(vnet_t *vnetp, struct ether_addr *addrp)
1287c1c61f44Ssb155480 {
1288c1c61f44Ssb155480 uint64_t key = 0;
1289678453a8Sspeer vnet_res_t *vresp;
1290c1c61f44Ssb155480 int rv;
1291c1c61f44Ssb155480
1292678453a8Sspeer KEY_HASH(key, addrp->ether_addr_octet);
1293c1c61f44Ssb155480
1294c1c61f44Ssb155480 rv = mod_hash_find_cb(vnetp->fdb_hashp, (mod_hash_key_t)key,
1295678453a8Sspeer (mod_hash_val_t *)&vresp, vnet_fdbe_find_cb);
1296c1c61f44Ssb155480
1297c1c61f44Ssb155480 if (rv != 0)
1298c1c61f44Ssb155480 return (NULL);
1299c1c61f44Ssb155480
1300678453a8Sspeer return (vresp);
1301c1c61f44Ssb155480 }
1302c1c61f44Ssb155480
1303c1c61f44Ssb155480 /*
1304c1c61f44Ssb155480 * Callback function provided to mod_hash_find_cb(). After finding the fdb
1305c1c61f44Ssb155480 * entry corresponding to the key (macaddr), this callback will be invoked by
1306c1c61f44Ssb155480 * mod_hash_find_cb() to atomically increment the reference count on the fdb
1307c1c61f44Ssb155480 * entry before returning the found entry.
1308c1c61f44Ssb155480 */
1309c1c61f44Ssb155480 static void
vnet_fdbe_find_cb(mod_hash_key_t key,mod_hash_val_t val)1310c1c61f44Ssb155480 vnet_fdbe_find_cb(mod_hash_key_t key, mod_hash_val_t val)
1311c1c61f44Ssb155480 {
1312c1c61f44Ssb155480 _NOTE(ARGUNUSED(key))
1313678453a8Sspeer VNET_FDBE_REFHOLD((vnet_res_t *)val);
1314678453a8Sspeer }
1315678453a8Sspeer
13168c242ab0SSriharsha Basavapatna /*
13178c242ab0SSriharsha Basavapatna * Frames received that are tagged with the pvid of the vnet device must be
13188c242ab0SSriharsha Basavapatna * untagged before sending up the stack. This function walks the chain of rx
13198c242ab0SSriharsha Basavapatna * frames, untags any such frames and returns the updated chain.
13208c242ab0SSriharsha Basavapatna *
13218c242ab0SSriharsha Basavapatna * Arguments:
13228c242ab0SSriharsha Basavapatna * pvid: pvid of the vnet device for which packets are being received
13238c242ab0SSriharsha Basavapatna * mp: head of pkt chain to be validated and untagged
13248c242ab0SSriharsha Basavapatna *
13258c242ab0SSriharsha Basavapatna * Returns:
13268c242ab0SSriharsha Basavapatna * mp: head of updated chain of packets
13278c242ab0SSriharsha Basavapatna */
13288c242ab0SSriharsha Basavapatna static void
vnet_rx_frames_untag(uint16_t pvid,mblk_t ** mp)13298c242ab0SSriharsha Basavapatna vnet_rx_frames_untag(uint16_t pvid, mblk_t **mp)
13308c242ab0SSriharsha Basavapatna {
13318c242ab0SSriharsha Basavapatna struct ether_vlan_header *evhp;
13328c242ab0SSriharsha Basavapatna mblk_t *bp;
13338c242ab0SSriharsha Basavapatna mblk_t *bpt;
13348c242ab0SSriharsha Basavapatna mblk_t *bph;
13358c242ab0SSriharsha Basavapatna mblk_t *bpn;
13368c242ab0SSriharsha Basavapatna
13378c242ab0SSriharsha Basavapatna bpn = bph = bpt = NULL;
13388c242ab0SSriharsha Basavapatna
13398c242ab0SSriharsha Basavapatna for (bp = *mp; bp != NULL; bp = bpn) {
13408c242ab0SSriharsha Basavapatna
13418c242ab0SSriharsha Basavapatna bpn = bp->b_next;
13428c242ab0SSriharsha Basavapatna bp->b_next = bp->b_prev = NULL;
13438c242ab0SSriharsha Basavapatna
13448c242ab0SSriharsha Basavapatna evhp = (struct ether_vlan_header *)bp->b_rptr;
13458c242ab0SSriharsha Basavapatna
13468c242ab0SSriharsha Basavapatna if (ntohs(evhp->ether_tpid) == ETHERTYPE_VLAN &&
13478c242ab0SSriharsha Basavapatna VLAN_ID(ntohs(evhp->ether_tci)) == pvid) {
13488c242ab0SSriharsha Basavapatna
13498c242ab0SSriharsha Basavapatna bp = vnet_vlan_remove_tag(bp);
13508c242ab0SSriharsha Basavapatna if (bp == NULL) {
13518c242ab0SSriharsha Basavapatna continue;
13528c242ab0SSriharsha Basavapatna }
13538c242ab0SSriharsha Basavapatna
13548c242ab0SSriharsha Basavapatna }
13558c242ab0SSriharsha Basavapatna
13568c242ab0SSriharsha Basavapatna /* build a chain of processed packets */
13578c242ab0SSriharsha Basavapatna if (bph == NULL) {
13588c242ab0SSriharsha Basavapatna bph = bpt = bp;
13598c242ab0SSriharsha Basavapatna } else {
13608c242ab0SSriharsha Basavapatna bpt->b_next = bp;
13618c242ab0SSriharsha Basavapatna bpt = bp;
13628c242ab0SSriharsha Basavapatna }
13638c242ab0SSriharsha Basavapatna
13648c242ab0SSriharsha Basavapatna }
13658c242ab0SSriharsha Basavapatna
13668c242ab0SSriharsha Basavapatna *mp = bph;
13678c242ab0SSriharsha Basavapatna }
13688c242ab0SSriharsha Basavapatna
1369678453a8Sspeer static void
vnet_rx(vio_net_handle_t vrh,mblk_t * mp)1370678453a8Sspeer vnet_rx(vio_net_handle_t vrh, mblk_t *mp)
1371678453a8Sspeer {
1372678453a8Sspeer vnet_res_t *vresp = (vnet_res_t *)vrh;
1373678453a8Sspeer vnet_t *vnetp = vresp->vnetp;
137463f531d1SSriharsha Basavapatna vnet_pseudo_rx_ring_t *ringp;
1375678453a8Sspeer
13768c242ab0SSriharsha Basavapatna if ((vnetp == NULL) || (vnetp->mh == 0)) {
1377678453a8Sspeer freemsgchain(mp);
13788c242ab0SSriharsha Basavapatna return;
1379678453a8Sspeer }
13808c242ab0SSriharsha Basavapatna
138163f531d1SSriharsha Basavapatna ringp = vresp->rx_ringp;
138263f531d1SSriharsha Basavapatna mac_rx_ring(vnetp->mh, ringp->handle, mp, ringp->gen_num);
13831ae08745Sheppo }
1384ba2e4443Sseb
1385ba2e4443Sseb void
vnet_tx_update(vio_net_handle_t vrh)1386678453a8Sspeer vnet_tx_update(vio_net_handle_t vrh)
1387ba2e4443Sseb {
1388678453a8Sspeer vnet_res_t *vresp = (vnet_res_t *)vrh;
1389678453a8Sspeer vnet_t *vnetp = vresp->vnetp;
139063f531d1SSriharsha Basavapatna vnet_pseudo_tx_ring_t *tx_ringp;
139163f531d1SSriharsha Basavapatna vnet_pseudo_tx_group_t *tx_grp;
139263f531d1SSriharsha Basavapatna int i;
1393ba2e4443Sseb
139463f531d1SSriharsha Basavapatna if (vnetp == NULL || vnetp->mh == NULL) {
139563f531d1SSriharsha Basavapatna return;
139663f531d1SSriharsha Basavapatna }
139763f531d1SSriharsha Basavapatna
139863f531d1SSriharsha Basavapatna /*
139963f531d1SSriharsha Basavapatna * Currently, the tx hwring API (used to access rings that belong to
140063f531d1SSriharsha Basavapatna * a Hybrid IO resource) does not provide us a per ring flow ctrl
140163f531d1SSriharsha Basavapatna * update; also the pseudo rings are shared by the ports/ldcs in the
140263f531d1SSriharsha Basavapatna * vgen layer. Thus we can't figure out which pseudo ring is being
140363f531d1SSriharsha Basavapatna * re-enabled for transmits. To work around this, when we get a tx
140463f531d1SSriharsha Basavapatna * restart notification from below, we simply propagate that to all
140563f531d1SSriharsha Basavapatna * the tx pseudo rings registered with the mac layer above.
140663f531d1SSriharsha Basavapatna *
140763f531d1SSriharsha Basavapatna * There are a couple of side effects with this approach, but they are
140863f531d1SSriharsha Basavapatna * not harmful, as outlined below:
140963f531d1SSriharsha Basavapatna *
141063f531d1SSriharsha Basavapatna * A) We might send an invalid ring_update() for a ring that is not
141163f531d1SSriharsha Basavapatna * really flow controlled. This will not have any effect in the mac
141263f531d1SSriharsha Basavapatna * layer and packets will continue to be transmitted on that ring.
141363f531d1SSriharsha Basavapatna *
141463f531d1SSriharsha Basavapatna * B) We might end up clearing the flow control in the mac layer for
141563f531d1SSriharsha Basavapatna * a ring that is still flow controlled in the underlying resource.
141663f531d1SSriharsha Basavapatna * This will result in the mac layer restarting transmit, only to be
141763f531d1SSriharsha Basavapatna * flow controlled again on that ring.
141863f531d1SSriharsha Basavapatna */
141963f531d1SSriharsha Basavapatna tx_grp = &vnetp->tx_grp[0];
142063f531d1SSriharsha Basavapatna for (i = 0; i < tx_grp->ring_cnt; i++) {
142163f531d1SSriharsha Basavapatna tx_ringp = &tx_grp->rings[i];
142263f531d1SSriharsha Basavapatna mac_tx_ring_update(vnetp->mh, tx_ringp->handle);
1423ba2e4443Sseb }
1424678453a8Sspeer }
1425678453a8Sspeer
1426678453a8Sspeer /*
14270dc2366fSVenugopal Iyer * vnet_tx_notify_thread:
14280dc2366fSVenugopal Iyer *
14290dc2366fSVenugopal Iyer * vnet_tx_ring_update() callback function wakes up this thread when
14300dc2366fSVenugopal Iyer * it gets called. This thread will call mac_tx_ring_update() to
14310dc2366fSVenugopal Iyer * notify upper mac of flow control getting relieved. Note that
14320dc2366fSVenugopal Iyer * vnet_tx_ring_update() cannot call mac_tx_ring_update() directly
14330dc2366fSVenugopal Iyer * because vnet_tx_ring_update() is called from lower mac with
14340dc2366fSVenugopal Iyer * mi_rw_lock held and mac_tx_ring_update() would also try to grab
14350dc2366fSVenugopal Iyer * the same lock.
14360dc2366fSVenugopal Iyer */
14370dc2366fSVenugopal Iyer static void
vnet_tx_notify_thread(void * arg)14380dc2366fSVenugopal Iyer vnet_tx_notify_thread(void *arg)
14390dc2366fSVenugopal Iyer {
14400dc2366fSVenugopal Iyer callb_cpr_t cprinfo;
14410dc2366fSVenugopal Iyer vnet_pseudo_tx_group_t *tx_grp = (vnet_pseudo_tx_group_t *)arg;
14420dc2366fSVenugopal Iyer vnet_pseudo_tx_ring_t *tx_ringp;
14430dc2366fSVenugopal Iyer vnet_t *vnetp;
14440dc2366fSVenugopal Iyer int i;
14450dc2366fSVenugopal Iyer
14460dc2366fSVenugopal Iyer CALLB_CPR_INIT(&cprinfo, &tx_grp->flowctl_lock, callb_generic_cpr,
14470dc2366fSVenugopal Iyer "vnet_tx_notify_thread");
14480dc2366fSVenugopal Iyer
14490dc2366fSVenugopal Iyer mutex_enter(&tx_grp->flowctl_lock);
14500dc2366fSVenugopal Iyer while (!tx_grp->flowctl_done) {
14510dc2366fSVenugopal Iyer CALLB_CPR_SAFE_BEGIN(&cprinfo);
14520dc2366fSVenugopal Iyer cv_wait(&tx_grp->flowctl_cv, &tx_grp->flowctl_lock);
14530dc2366fSVenugopal Iyer CALLB_CPR_SAFE_END(&cprinfo, &tx_grp->flowctl_lock);
14540dc2366fSVenugopal Iyer
14550dc2366fSVenugopal Iyer for (i = 0; i < tx_grp->ring_cnt; i++) {
14560dc2366fSVenugopal Iyer tx_ringp = &tx_grp->rings[i];
14570dc2366fSVenugopal Iyer if (tx_ringp->woken_up) {
14580dc2366fSVenugopal Iyer tx_ringp->woken_up = B_FALSE;
14590dc2366fSVenugopal Iyer vnetp = tx_ringp->vnetp;
14600dc2366fSVenugopal Iyer mac_tx_ring_update(vnetp->mh, tx_ringp->handle);
14610dc2366fSVenugopal Iyer }
14620dc2366fSVenugopal Iyer }
14630dc2366fSVenugopal Iyer }
14640dc2366fSVenugopal Iyer /*
14650dc2366fSVenugopal Iyer * The tx_grp is being destroyed, exit the thread.
14660dc2366fSVenugopal Iyer */
14670dc2366fSVenugopal Iyer tx_grp->flowctl_thread = NULL;
14680dc2366fSVenugopal Iyer CALLB_CPR_EXIT(&cprinfo);
14690dc2366fSVenugopal Iyer thread_exit();
14700dc2366fSVenugopal Iyer }
14710dc2366fSVenugopal Iyer
14720dc2366fSVenugopal Iyer void
vnet_tx_ring_update(void * arg1,uintptr_t arg2)14730dc2366fSVenugopal Iyer vnet_tx_ring_update(void *arg1, uintptr_t arg2)
14740dc2366fSVenugopal Iyer {
14750dc2366fSVenugopal Iyer vnet_t *vnetp = (vnet_t *)arg1;
14760dc2366fSVenugopal Iyer vnet_pseudo_tx_group_t *tx_grp;
14770dc2366fSVenugopal Iyer vnet_pseudo_tx_ring_t *tx_ringp;
14780dc2366fSVenugopal Iyer int i;
14790dc2366fSVenugopal Iyer
14800dc2366fSVenugopal Iyer tx_grp = &vnetp->tx_grp[0];
14810dc2366fSVenugopal Iyer for (i = 0; i < tx_grp->ring_cnt; i++) {
14820dc2366fSVenugopal Iyer tx_ringp = &tx_grp->rings[i];
14830dc2366fSVenugopal Iyer if (tx_ringp->hw_rh == (mac_ring_handle_t)arg2) {
14840dc2366fSVenugopal Iyer mutex_enter(&tx_grp->flowctl_lock);
14850dc2366fSVenugopal Iyer tx_ringp->woken_up = B_TRUE;
14860dc2366fSVenugopal Iyer cv_signal(&tx_grp->flowctl_cv);
14870dc2366fSVenugopal Iyer mutex_exit(&tx_grp->flowctl_lock);
14880dc2366fSVenugopal Iyer break;
14890dc2366fSVenugopal Iyer }
14900dc2366fSVenugopal Iyer }
14910dc2366fSVenugopal Iyer }
14920dc2366fSVenugopal Iyer
14930dc2366fSVenugopal Iyer /*
14947b1f684aSSriharsha Basavapatna * Update the new mtu of vnet into the mac layer. First check if the device has
14957b1f684aSSriharsha Basavapatna * been plumbed and if so fail the mtu update. Returns 0 on success.
14967b1f684aSSriharsha Basavapatna */
14977b1f684aSSriharsha Basavapatna int
vnet_mtu_update(vnet_t * vnetp,uint32_t mtu)14987b1f684aSSriharsha Basavapatna vnet_mtu_update(vnet_t *vnetp, uint32_t mtu)
14997b1f684aSSriharsha Basavapatna {
15007b1f684aSSriharsha Basavapatna int rv;
15017b1f684aSSriharsha Basavapatna
15027b1f684aSSriharsha Basavapatna if (vnetp == NULL || vnetp->mh == NULL) {
15037b1f684aSSriharsha Basavapatna return (EINVAL);
15047b1f684aSSriharsha Basavapatna }
15057b1f684aSSriharsha Basavapatna
15067b1f684aSSriharsha Basavapatna WRITE_ENTER(&vnetp->vrwlock);
15077b1f684aSSriharsha Basavapatna
15087b1f684aSSriharsha Basavapatna if (vnetp->flags & VNET_STARTED) {
15097b1f684aSSriharsha Basavapatna RW_EXIT(&vnetp->vrwlock);
15107b1f684aSSriharsha Basavapatna cmn_err(CE_NOTE, "!vnet%d: Unable to process mtu "
15117b1f684aSSriharsha Basavapatna "update as the device is plumbed\n",
15127b1f684aSSriharsha Basavapatna vnetp->instance);
15137b1f684aSSriharsha Basavapatna return (EBUSY);
15147b1f684aSSriharsha Basavapatna }
15157b1f684aSSriharsha Basavapatna
15167b1f684aSSriharsha Basavapatna /* update mtu in the mac layer */
15177b1f684aSSriharsha Basavapatna rv = mac_maxsdu_update(vnetp->mh, mtu);
15187b1f684aSSriharsha Basavapatna if (rv != 0) {
15197b1f684aSSriharsha Basavapatna RW_EXIT(&vnetp->vrwlock);
15207b1f684aSSriharsha Basavapatna cmn_err(CE_NOTE,
15217b1f684aSSriharsha Basavapatna "!vnet%d: Unable to update mtu with mac layer\n",
15227b1f684aSSriharsha Basavapatna vnetp->instance);
15237b1f684aSSriharsha Basavapatna return (EIO);
15247b1f684aSSriharsha Basavapatna }
15257b1f684aSSriharsha Basavapatna
15267b1f684aSSriharsha Basavapatna vnetp->mtu = mtu;
15277b1f684aSSriharsha Basavapatna
15287b1f684aSSriharsha Basavapatna RW_EXIT(&vnetp->vrwlock);
15297b1f684aSSriharsha Basavapatna
15307b1f684aSSriharsha Basavapatna return (0);
15317b1f684aSSriharsha Basavapatna }
15327b1f684aSSriharsha Basavapatna
15337b1f684aSSriharsha Basavapatna /*
15341107ea93SSriharsha Basavapatna * Update the link state of vnet to the mac layer.
15351107ea93SSriharsha Basavapatna */
15361107ea93SSriharsha Basavapatna void
vnet_link_update(vnet_t * vnetp,link_state_t link_state)15371107ea93SSriharsha Basavapatna vnet_link_update(vnet_t *vnetp, link_state_t link_state)
15381107ea93SSriharsha Basavapatna {
15391107ea93SSriharsha Basavapatna if (vnetp == NULL || vnetp->mh == NULL) {
15401107ea93SSriharsha Basavapatna return;
15411107ea93SSriharsha Basavapatna }
15421107ea93SSriharsha Basavapatna
15431107ea93SSriharsha Basavapatna WRITE_ENTER(&vnetp->vrwlock);
15441107ea93SSriharsha Basavapatna if (vnetp->link_state == link_state) {
15451107ea93SSriharsha Basavapatna RW_EXIT(&vnetp->vrwlock);
15461107ea93SSriharsha Basavapatna return;
15471107ea93SSriharsha Basavapatna }
15481107ea93SSriharsha Basavapatna vnetp->link_state = link_state;
15491107ea93SSriharsha Basavapatna RW_EXIT(&vnetp->vrwlock);
15501107ea93SSriharsha Basavapatna
15511107ea93SSriharsha Basavapatna mac_link_update(vnetp->mh, link_state);
15521107ea93SSriharsha Basavapatna }
15531107ea93SSriharsha Basavapatna
15541107ea93SSriharsha Basavapatna /*
1555678453a8Sspeer * vio_net_resource_reg -- An interface called to register a resource
1556678453a8Sspeer * with vnet.
1557678453a8Sspeer * macp -- a GLDv3 mac_register that has all the details of
1558678453a8Sspeer * a resource and its callbacks etc.
1559678453a8Sspeer * type -- resource type.
1560678453a8Sspeer * local_macaddr -- resource's MAC address. This is used to
1561678453a8Sspeer * associate a resource with a corresponding vnet.
1562678453a8Sspeer * remote_macaddr -- remote side MAC address. This is ignored for
1563678453a8Sspeer * the Hybrid resources.
1564678453a8Sspeer * vhp -- A handle returned to the caller.
1565678453a8Sspeer * vcb -- A set of callbacks provided to the callers.
1566678453a8Sspeer */
vio_net_resource_reg(mac_register_t * macp,vio_net_res_type_t type,ether_addr_t local_macaddr,ether_addr_t rem_macaddr,vio_net_handle_t * vhp,vio_net_callbacks_t * vcb)1567678453a8Sspeer int vio_net_resource_reg(mac_register_t *macp, vio_net_res_type_t type,
1568678453a8Sspeer ether_addr_t local_macaddr, ether_addr_t rem_macaddr, vio_net_handle_t *vhp,
1569678453a8Sspeer vio_net_callbacks_t *vcb)
1570678453a8Sspeer {
1571678453a8Sspeer vnet_t *vnetp;
1572678453a8Sspeer vnet_res_t *vresp;
1573678453a8Sspeer
1574678453a8Sspeer vresp = kmem_zalloc(sizeof (vnet_res_t), KM_SLEEP);
1575678453a8Sspeer ether_copy(local_macaddr, vresp->local_macaddr);
1576678453a8Sspeer ether_copy(rem_macaddr, vresp->rem_macaddr);
1577678453a8Sspeer vresp->type = type;
1578678453a8Sspeer bcopy(macp, &vresp->macreg, sizeof (mac_register_t));
1579678453a8Sspeer
1580678453a8Sspeer DBG1(NULL, "Resource Registerig type=0%X\n", type);
1581678453a8Sspeer
1582678453a8Sspeer READ_ENTER(&vnet_rw);
1583678453a8Sspeer vnetp = vnet_headp;
1584678453a8Sspeer while (vnetp != NULL) {
1585678453a8Sspeer if (VNET_MATCH_RES(vresp, vnetp)) {
1586678453a8Sspeer vresp->vnetp = vnetp;
15876b8fc343SWENTAO YANG
15886b8fc343SWENTAO YANG /* Setup kstats for hio resource */
15896b8fc343SWENTAO YANG if (vresp->type == VIO_NET_RES_HYBRID) {
15906b8fc343SWENTAO YANG vresp->ksp = vnet_hio_setup_kstats(DRV_NAME,
15916b8fc343SWENTAO YANG "hio", vresp);
15926b8fc343SWENTAO YANG if (vresp->ksp == NULL) {
15936b8fc343SWENTAO YANG cmn_err(CE_NOTE, "!vnet%d: Cannot "
15946b8fc343SWENTAO YANG "create kstats for hio resource",
15956b8fc343SWENTAO YANG vnetp->instance);
15966b8fc343SWENTAO YANG }
15976b8fc343SWENTAO YANG }
159863f531d1SSriharsha Basavapatna vnet_add_resource(vnetp, vresp);
1599678453a8Sspeer break;
1600678453a8Sspeer }
1601678453a8Sspeer vnetp = vnetp->nextp;
1602678453a8Sspeer }
1603678453a8Sspeer RW_EXIT(&vnet_rw);
1604678453a8Sspeer if (vresp->vnetp == NULL) {
1605678453a8Sspeer DWARN(NULL, "No vnet instance");
1606678453a8Sspeer kmem_free(vresp, sizeof (vnet_res_t));
1607678453a8Sspeer return (ENXIO);
1608678453a8Sspeer }
1609678453a8Sspeer
1610678453a8Sspeer *vhp = vresp;
1611678453a8Sspeer vcb->vio_net_rx_cb = vnet_rx;
1612678453a8Sspeer vcb->vio_net_tx_update = vnet_tx_update;
1613678453a8Sspeer vcb->vio_net_report_err = vnet_handle_res_err;
1614678453a8Sspeer
161563f531d1SSriharsha Basavapatna /* Bind the resource to pseudo ring(s) */
161663f531d1SSriharsha Basavapatna if (vnet_bind_rings(vresp) != 0) {
161763f531d1SSriharsha Basavapatna (void) vnet_rem_resource(vnetp, vresp);
161863f531d1SSriharsha Basavapatna vnet_hio_destroy_kstats(vresp->ksp);
161963f531d1SSriharsha Basavapatna KMEM_FREE(vresp);
162063f531d1SSriharsha Basavapatna return (1);
162163f531d1SSriharsha Basavapatna }
162263f531d1SSriharsha Basavapatna
1623678453a8Sspeer /* Dispatch a task to start resources */
1624678453a8Sspeer vnet_dispatch_res_task(vnetp);
1625678453a8Sspeer return (0);
1626678453a8Sspeer }
1627678453a8Sspeer
1628678453a8Sspeer /*
1629678453a8Sspeer * vio_net_resource_unreg -- An interface to unregister a resource.
1630678453a8Sspeer */
1631678453a8Sspeer void
vio_net_resource_unreg(vio_net_handle_t vhp)1632678453a8Sspeer vio_net_resource_unreg(vio_net_handle_t vhp)
1633678453a8Sspeer {
1634678453a8Sspeer vnet_res_t *vresp = (vnet_res_t *)vhp;
1635678453a8Sspeer vnet_t *vnetp = vresp->vnetp;
1636678453a8Sspeer
1637678453a8Sspeer DBG1(NULL, "Resource Registerig hdl=0x%p", vhp);
1638678453a8Sspeer
1639678453a8Sspeer ASSERT(vnetp != NULL);
16405460ddbdSSriharsha Basavapatna /*
16415460ddbdSSriharsha Basavapatna * Remove the resource from fdb; this ensures
16425460ddbdSSriharsha Basavapatna * there are no references to the resource.
16435460ddbdSSriharsha Basavapatna */
1644678453a8Sspeer vnet_fdbe_del(vnetp, vresp);
1645678453a8Sspeer
164663f531d1SSriharsha Basavapatna vnet_unbind_rings(vresp);
164763f531d1SSriharsha Basavapatna
16485460ddbdSSriharsha Basavapatna /* Now remove the resource from the list */
164963f531d1SSriharsha Basavapatna (void) vnet_rem_resource(vnetp, vresp);
165063f531d1SSriharsha Basavapatna
165163f531d1SSriharsha Basavapatna vnet_hio_destroy_kstats(vresp->ksp);
165263f531d1SSriharsha Basavapatna KMEM_FREE(vresp);
165363f531d1SSriharsha Basavapatna }
165463f531d1SSriharsha Basavapatna
165563f531d1SSriharsha Basavapatna static void
vnet_add_resource(vnet_t * vnetp,vnet_res_t * vresp)165663f531d1SSriharsha Basavapatna vnet_add_resource(vnet_t *vnetp, vnet_res_t *vresp)
165763f531d1SSriharsha Basavapatna {
165863f531d1SSriharsha Basavapatna WRITE_ENTER(&vnetp->vrwlock);
165963f531d1SSriharsha Basavapatna vresp->nextp = vnetp->vres_list;
166063f531d1SSriharsha Basavapatna vnetp->vres_list = vresp;
166163f531d1SSriharsha Basavapatna RW_EXIT(&vnetp->vrwlock);
166263f531d1SSriharsha Basavapatna }
166363f531d1SSriharsha Basavapatna
166463f531d1SSriharsha Basavapatna static vnet_res_t *
vnet_rem_resource(vnet_t * vnetp,vnet_res_t * vresp)166563f531d1SSriharsha Basavapatna vnet_rem_resource(vnet_t *vnetp, vnet_res_t *vresp)
166663f531d1SSriharsha Basavapatna {
166763f531d1SSriharsha Basavapatna vnet_res_t *vrp;
166863f531d1SSriharsha Basavapatna
1669678453a8Sspeer WRITE_ENTER(&vnetp->vrwlock);
1670678453a8Sspeer if (vresp == vnetp->vres_list) {
1671678453a8Sspeer vnetp->vres_list = vresp->nextp;
1672678453a8Sspeer } else {
1673678453a8Sspeer vrp = vnetp->vres_list;
1674678453a8Sspeer while (vrp->nextp != NULL) {
1675678453a8Sspeer if (vrp->nextp == vresp) {
1676678453a8Sspeer vrp->nextp = vresp->nextp;
1677678453a8Sspeer break;
1678678453a8Sspeer }
1679678453a8Sspeer vrp = vrp->nextp;
1680678453a8Sspeer }
1681678453a8Sspeer }
1682678453a8Sspeer vresp->vnetp = NULL;
1683678453a8Sspeer vresp->nextp = NULL;
168463f531d1SSriharsha Basavapatna
1685678453a8Sspeer RW_EXIT(&vnetp->vrwlock);
168663f531d1SSriharsha Basavapatna
168763f531d1SSriharsha Basavapatna return (vresp);
1688678453a8Sspeer }
1689678453a8Sspeer
1690678453a8Sspeer /*
1691678453a8Sspeer * vnet_dds_rx -- an interface called by vgen to DDS messages.
1692678453a8Sspeer */
1693678453a8Sspeer void
vnet_dds_rx(void * arg,void * dmsg)1694678453a8Sspeer vnet_dds_rx(void *arg, void *dmsg)
1695678453a8Sspeer {
1696678453a8Sspeer vnet_t *vnetp = arg;
1697678453a8Sspeer vdds_process_dds_msg(vnetp, dmsg);
1698678453a8Sspeer }
1699678453a8Sspeer
1700678453a8Sspeer /*
1701678453a8Sspeer * vnet_send_dds_msg -- An interface provided to DDS to send
1702678453a8Sspeer * DDS messages. This simply sends meessages via vgen.
1703678453a8Sspeer */
1704678453a8Sspeer int
vnet_send_dds_msg(vnet_t * vnetp,void * dmsg)1705678453a8Sspeer vnet_send_dds_msg(vnet_t *vnetp, void *dmsg)
1706678453a8Sspeer {
1707678453a8Sspeer int rv;
1708678453a8Sspeer
1709678453a8Sspeer if (vnetp->vgenhdl != NULL) {
1710678453a8Sspeer rv = vgen_dds_tx(vnetp->vgenhdl, dmsg);
1711678453a8Sspeer }
1712678453a8Sspeer return (rv);
1713678453a8Sspeer }
1714678453a8Sspeer
1715678453a8Sspeer /*
17166d6de4eeSWENTAO YANG * vnet_cleanup_hio -- an interface called by vgen to cleanup hio resources.
17176d6de4eeSWENTAO YANG */
17186d6de4eeSWENTAO YANG void
vnet_dds_cleanup_hio(vnet_t * vnetp)17196d6de4eeSWENTAO YANG vnet_dds_cleanup_hio(vnet_t *vnetp)
17206d6de4eeSWENTAO YANG {
17216d6de4eeSWENTAO YANG vdds_cleanup_hio(vnetp);
17226d6de4eeSWENTAO YANG }
17236d6de4eeSWENTAO YANG
17246d6de4eeSWENTAO YANG /*
1725678453a8Sspeer * vnet_handle_res_err -- A callback function called by a resource
1726678453a8Sspeer * to report an error. For example, vgen can call to report
1727678453a8Sspeer * an LDC down/reset event. This will trigger cleanup of associated
1728678453a8Sspeer * Hybrid resource.
1729678453a8Sspeer */
1730678453a8Sspeer /* ARGSUSED */
1731678453a8Sspeer static void
vnet_handle_res_err(vio_net_handle_t vrh,vio_net_err_val_t err)1732678453a8Sspeer vnet_handle_res_err(vio_net_handle_t vrh, vio_net_err_val_t err)
1733678453a8Sspeer {
1734678453a8Sspeer vnet_res_t *vresp = (vnet_res_t *)vrh;
1735678453a8Sspeer vnet_t *vnetp = vresp->vnetp;
1736678453a8Sspeer
1737678453a8Sspeer if (vnetp == NULL) {
1738678453a8Sspeer return;
1739678453a8Sspeer }
1740678453a8Sspeer if ((vresp->type != VIO_NET_RES_LDC_SERVICE) &&
1741678453a8Sspeer (vresp->type != VIO_NET_RES_HYBRID)) {
1742678453a8Sspeer return;
1743678453a8Sspeer }
17446d6de4eeSWENTAO YANG
17456d6de4eeSWENTAO YANG vdds_cleanup_hio(vnetp);
1746678453a8Sspeer }
1747678453a8Sspeer
1748678453a8Sspeer /*
1749678453a8Sspeer * vnet_dispatch_res_task -- A function to dispatch tasks start resources.
1750678453a8Sspeer */
1751678453a8Sspeer static void
vnet_dispatch_res_task(vnet_t * vnetp)1752678453a8Sspeer vnet_dispatch_res_task(vnet_t *vnetp)
1753678453a8Sspeer {
1754678453a8Sspeer int rv;
1755678453a8Sspeer
17568b923298SZach Kissel /*
17578b923298SZach Kissel * Dispatch the task. It could be the case that vnetp->flags does
17588b923298SZach Kissel * not have VNET_STARTED set. This is ok as vnet_rest_start_task()
17595460ddbdSSriharsha Basavapatna * can abort the task when the task is started. See related comments
17605460ddbdSSriharsha Basavapatna * in vnet_m_stop() and vnet_stop_resources().
17618b923298SZach Kissel */
1762678453a8Sspeer rv = ddi_taskq_dispatch(vnetp->taskqp, vnet_res_start_task,
1763678453a8Sspeer vnetp, DDI_NOSLEEP);
1764678453a8Sspeer if (rv != DDI_SUCCESS) {
1765678453a8Sspeer cmn_err(CE_WARN,
1766678453a8Sspeer "vnet%d:Can't dispatch start resource task",
1767678453a8Sspeer vnetp->instance);
1768678453a8Sspeer }
1769678453a8Sspeer }
1770678453a8Sspeer
1771678453a8Sspeer /*
1772678453a8Sspeer * vnet_res_start_task -- A taskq callback function that starts a resource.
1773678453a8Sspeer */
1774678453a8Sspeer static void
vnet_res_start_task(void * arg)1775678453a8Sspeer vnet_res_start_task(void *arg)
1776678453a8Sspeer {
1777678453a8Sspeer vnet_t *vnetp = arg;
1778678453a8Sspeer
1779678453a8Sspeer WRITE_ENTER(&vnetp->vrwlock);
1780678453a8Sspeer if (vnetp->flags & VNET_STARTED) {
1781678453a8Sspeer vnet_start_resources(vnetp);
1782678453a8Sspeer }
1783678453a8Sspeer RW_EXIT(&vnetp->vrwlock);
1784678453a8Sspeer }
1785678453a8Sspeer
1786678453a8Sspeer /*
1787678453a8Sspeer * vnet_start_resources -- starts all resources associated with
1788678453a8Sspeer * a vnet.
1789678453a8Sspeer */
1790678453a8Sspeer static void
vnet_start_resources(vnet_t * vnetp)1791678453a8Sspeer vnet_start_resources(vnet_t *vnetp)
1792678453a8Sspeer {
1793678453a8Sspeer mac_register_t *macp;
1794678453a8Sspeer mac_callbacks_t *cbp;
1795678453a8Sspeer vnet_res_t *vresp;
1796678453a8Sspeer int rv;
1797678453a8Sspeer
1798678453a8Sspeer DBG1(vnetp, "enter\n");
1799678453a8Sspeer
18005460ddbdSSriharsha Basavapatna ASSERT(RW_WRITE_HELD(&vnetp->vrwlock));
18015460ddbdSSriharsha Basavapatna
1802678453a8Sspeer for (vresp = vnetp->vres_list; vresp != NULL; vresp = vresp->nextp) {
1803678453a8Sspeer /* skip if it is already started */
1804678453a8Sspeer if (vresp->flags & VNET_STARTED) {
1805678453a8Sspeer continue;
1806678453a8Sspeer }
1807678453a8Sspeer macp = &vresp->macreg;
1808678453a8Sspeer cbp = macp->m_callbacks;
1809678453a8Sspeer rv = cbp->mc_start(macp->m_driver);
1810678453a8Sspeer if (rv == 0) {
1811678453a8Sspeer /*
1812678453a8Sspeer * Successfully started the resource, so now
1813678453a8Sspeer * add it to the fdb.
1814678453a8Sspeer */
1815678453a8Sspeer vresp->flags |= VNET_STARTED;
1816678453a8Sspeer vnet_fdbe_add(vnetp, vresp);
1817678453a8Sspeer }
1818678453a8Sspeer }
1819678453a8Sspeer
1820678453a8Sspeer DBG1(vnetp, "exit\n");
1821678453a8Sspeer
1822678453a8Sspeer }
1823678453a8Sspeer
1824678453a8Sspeer /*
1825678453a8Sspeer * vnet_stop_resources -- stop all resources associated with a vnet.
1826678453a8Sspeer */
1827678453a8Sspeer static void
vnet_stop_resources(vnet_t * vnetp)1828678453a8Sspeer vnet_stop_resources(vnet_t *vnetp)
1829678453a8Sspeer {
1830678453a8Sspeer vnet_res_t *vresp;
1831678453a8Sspeer mac_register_t *macp;
1832678453a8Sspeer mac_callbacks_t *cbp;
1833678453a8Sspeer
1834678453a8Sspeer DBG1(vnetp, "enter\n");
1835678453a8Sspeer
18365460ddbdSSriharsha Basavapatna ASSERT(RW_WRITE_HELD(&vnetp->vrwlock));
18375460ddbdSSriharsha Basavapatna
1838678453a8Sspeer for (vresp = vnetp->vres_list; vresp != NULL; ) {
1839678453a8Sspeer if (vresp->flags & VNET_STARTED) {
18405460ddbdSSriharsha Basavapatna /*
18415460ddbdSSriharsha Basavapatna * Release the lock while invoking mc_stop() of the
18425460ddbdSSriharsha Basavapatna * underlying resource. We hold a reference to this
18435460ddbdSSriharsha Basavapatna * resource to prevent being removed from the list in
18445460ddbdSSriharsha Basavapatna * vio_net_resource_unreg(). Note that new resources
18455460ddbdSSriharsha Basavapatna * can be added to the head of the list while the lock
18465460ddbdSSriharsha Basavapatna * is released, but they won't be started, as
18475460ddbdSSriharsha Basavapatna * VNET_STARTED flag has been cleared for the vnet
18485460ddbdSSriharsha Basavapatna * device in vnet_m_stop(). Also, while the lock is
18495460ddbdSSriharsha Basavapatna * released a resource could be removed from the list
18505460ddbdSSriharsha Basavapatna * in vio_net_resource_unreg(); but that is ok, as we
18515460ddbdSSriharsha Basavapatna * re-acquire the lock and only then access the forward
18525460ddbdSSriharsha Basavapatna * link (vresp->nextp) to continue with the next
18535460ddbdSSriharsha Basavapatna * resource.
18545460ddbdSSriharsha Basavapatna */
18555460ddbdSSriharsha Basavapatna vresp->flags &= ~VNET_STARTED;
18565460ddbdSSriharsha Basavapatna vresp->flags |= VNET_STOPPING;
1857678453a8Sspeer macp = &vresp->macreg;
1858678453a8Sspeer cbp = macp->m_callbacks;
18595460ddbdSSriharsha Basavapatna VNET_FDBE_REFHOLD(vresp);
18605460ddbdSSriharsha Basavapatna RW_EXIT(&vnetp->vrwlock);
18615460ddbdSSriharsha Basavapatna
1862678453a8Sspeer cbp->mc_stop(macp->m_driver);
18635460ddbdSSriharsha Basavapatna
18645460ddbdSSriharsha Basavapatna WRITE_ENTER(&vnetp->vrwlock);
18655460ddbdSSriharsha Basavapatna vresp->flags &= ~VNET_STOPPING;
18665460ddbdSSriharsha Basavapatna VNET_FDBE_REFRELE(vresp);
1867678453a8Sspeer }
18685460ddbdSSriharsha Basavapatna vresp = vresp->nextp;
1869678453a8Sspeer }
1870678453a8Sspeer DBG1(vnetp, "exit\n");
1871678453a8Sspeer }
18726ab6cb20SWENTAO YANG
18736ab6cb20SWENTAO YANG /*
18746ab6cb20SWENTAO YANG * Setup kstats for the HIO statistics.
18756ab6cb20SWENTAO YANG * NOTE: the synchronization for the statistics is the
18766ab6cb20SWENTAO YANG * responsibility of the caller.
18776ab6cb20SWENTAO YANG */
18786ab6cb20SWENTAO YANG kstat_t *
vnet_hio_setup_kstats(char * ks_mod,char * ks_name,vnet_res_t * vresp)18796ab6cb20SWENTAO YANG vnet_hio_setup_kstats(char *ks_mod, char *ks_name, vnet_res_t *vresp)
18806ab6cb20SWENTAO YANG {
18816ab6cb20SWENTAO YANG kstat_t *ksp;
18826ab6cb20SWENTAO YANG vnet_t *vnetp = vresp->vnetp;
18836ab6cb20SWENTAO YANG vnet_hio_kstats_t *hiokp;
18846ab6cb20SWENTAO YANG size_t size;
18856ab6cb20SWENTAO YANG
18866ab6cb20SWENTAO YANG ASSERT(vnetp != NULL);
18876ab6cb20SWENTAO YANG size = sizeof (vnet_hio_kstats_t) / sizeof (kstat_named_t);
18886ab6cb20SWENTAO YANG ksp = kstat_create(ks_mod, vnetp->instance, ks_name, "net",
18896ab6cb20SWENTAO YANG KSTAT_TYPE_NAMED, size, 0);
18906ab6cb20SWENTAO YANG if (ksp == NULL) {
18916ab6cb20SWENTAO YANG return (NULL);
18926ab6cb20SWENTAO YANG }
18936ab6cb20SWENTAO YANG
18946ab6cb20SWENTAO YANG hiokp = (vnet_hio_kstats_t *)ksp->ks_data;
18956ab6cb20SWENTAO YANG kstat_named_init(&hiokp->ipackets, "ipackets",
18966ab6cb20SWENTAO YANG KSTAT_DATA_ULONG);
18976ab6cb20SWENTAO YANG kstat_named_init(&hiokp->ierrors, "ierrors",
18986ab6cb20SWENTAO YANG KSTAT_DATA_ULONG);
18996ab6cb20SWENTAO YANG kstat_named_init(&hiokp->opackets, "opackets",
19006ab6cb20SWENTAO YANG KSTAT_DATA_ULONG);
19016ab6cb20SWENTAO YANG kstat_named_init(&hiokp->oerrors, "oerrors",
19026ab6cb20SWENTAO YANG KSTAT_DATA_ULONG);
19036ab6cb20SWENTAO YANG
19046ab6cb20SWENTAO YANG
19056ab6cb20SWENTAO YANG /* MIB II kstat variables */
19066ab6cb20SWENTAO YANG kstat_named_init(&hiokp->rbytes, "rbytes",
19076ab6cb20SWENTAO YANG KSTAT_DATA_ULONG);
19086ab6cb20SWENTAO YANG kstat_named_init(&hiokp->obytes, "obytes",
19096ab6cb20SWENTAO YANG KSTAT_DATA_ULONG);
19106ab6cb20SWENTAO YANG kstat_named_init(&hiokp->multircv, "multircv",
19116ab6cb20SWENTAO YANG KSTAT_DATA_ULONG);
19126ab6cb20SWENTAO YANG kstat_named_init(&hiokp->multixmt, "multixmt",
19136ab6cb20SWENTAO YANG KSTAT_DATA_ULONG);
19146ab6cb20SWENTAO YANG kstat_named_init(&hiokp->brdcstrcv, "brdcstrcv",
19156ab6cb20SWENTAO YANG KSTAT_DATA_ULONG);
19166ab6cb20SWENTAO YANG kstat_named_init(&hiokp->brdcstxmt, "brdcstxmt",
19176ab6cb20SWENTAO YANG KSTAT_DATA_ULONG);
19186ab6cb20SWENTAO YANG kstat_named_init(&hiokp->norcvbuf, "norcvbuf",
19196ab6cb20SWENTAO YANG KSTAT_DATA_ULONG);
19206ab6cb20SWENTAO YANG kstat_named_init(&hiokp->noxmtbuf, "noxmtbuf",
19216ab6cb20SWENTAO YANG KSTAT_DATA_ULONG);
19226ab6cb20SWENTAO YANG
19236ab6cb20SWENTAO YANG ksp->ks_update = vnet_hio_update_kstats;
19246ab6cb20SWENTAO YANG ksp->ks_private = (void *)vresp;
19256ab6cb20SWENTAO YANG kstat_install(ksp);
19266ab6cb20SWENTAO YANG return (ksp);
19276ab6cb20SWENTAO YANG }
19286ab6cb20SWENTAO YANG
19296ab6cb20SWENTAO YANG /*
19306ab6cb20SWENTAO YANG * Destroy kstats.
19316ab6cb20SWENTAO YANG */
19326ab6cb20SWENTAO YANG static void
vnet_hio_destroy_kstats(kstat_t * ksp)19336ab6cb20SWENTAO YANG vnet_hio_destroy_kstats(kstat_t *ksp)
19346ab6cb20SWENTAO YANG {
19356ab6cb20SWENTAO YANG if (ksp != NULL)
19366ab6cb20SWENTAO YANG kstat_delete(ksp);
19376ab6cb20SWENTAO YANG }
19386ab6cb20SWENTAO YANG
19396ab6cb20SWENTAO YANG /*
19406ab6cb20SWENTAO YANG * Update the kstats.
19416ab6cb20SWENTAO YANG */
19426ab6cb20SWENTAO YANG static int
vnet_hio_update_kstats(kstat_t * ksp,int rw)19436ab6cb20SWENTAO YANG vnet_hio_update_kstats(kstat_t *ksp, int rw)
19446ab6cb20SWENTAO YANG {
19456ab6cb20SWENTAO YANG vnet_t *vnetp;
19466ab6cb20SWENTAO YANG vnet_res_t *vresp;
19476ab6cb20SWENTAO YANG vnet_hio_stats_t statsp;
19486ab6cb20SWENTAO YANG vnet_hio_kstats_t *hiokp;
19496ab6cb20SWENTAO YANG
19506ab6cb20SWENTAO YANG vresp = (vnet_res_t *)ksp->ks_private;
19516ab6cb20SWENTAO YANG vnetp = vresp->vnetp;
19526ab6cb20SWENTAO YANG
19536ab6cb20SWENTAO YANG bzero(&statsp, sizeof (vnet_hio_stats_t));
19546ab6cb20SWENTAO YANG
19556ab6cb20SWENTAO YANG READ_ENTER(&vnetp->vsw_fp_rw);
19566ab6cb20SWENTAO YANG if (vnetp->hio_fp == NULL) {
19576ab6cb20SWENTAO YANG /* not using hio resources, just return */
19586ab6cb20SWENTAO YANG RW_EXIT(&vnetp->vsw_fp_rw);
19596ab6cb20SWENTAO YANG return (0);
19606ab6cb20SWENTAO YANG }
19616ab6cb20SWENTAO YANG VNET_FDBE_REFHOLD(vnetp->hio_fp);
19626ab6cb20SWENTAO YANG RW_EXIT(&vnetp->vsw_fp_rw);
19636ab6cb20SWENTAO YANG vnet_hio_get_stats(vnetp->hio_fp, &statsp);
19646ab6cb20SWENTAO YANG VNET_FDBE_REFRELE(vnetp->hio_fp);
19656ab6cb20SWENTAO YANG
19666ab6cb20SWENTAO YANG hiokp = (vnet_hio_kstats_t *)ksp->ks_data;
19676ab6cb20SWENTAO YANG
19686ab6cb20SWENTAO YANG if (rw == KSTAT_READ) {
19696ab6cb20SWENTAO YANG /* Link Input/Output stats */
19706ab6cb20SWENTAO YANG hiokp->ipackets.value.ul = (uint32_t)statsp.ipackets;
19716ab6cb20SWENTAO YANG hiokp->ipackets64.value.ull = statsp.ipackets;
19726ab6cb20SWENTAO YANG hiokp->ierrors.value.ul = statsp.ierrors;
19736ab6cb20SWENTAO YANG hiokp->opackets.value.ul = (uint32_t)statsp.opackets;
19746ab6cb20SWENTAO YANG hiokp->opackets64.value.ull = statsp.opackets;
19756ab6cb20SWENTAO YANG hiokp->oerrors.value.ul = statsp.oerrors;
19766ab6cb20SWENTAO YANG
19776ab6cb20SWENTAO YANG /* MIB II kstat variables */
19786ab6cb20SWENTAO YANG hiokp->rbytes.value.ul = (uint32_t)statsp.rbytes;
19796ab6cb20SWENTAO YANG hiokp->rbytes64.value.ull = statsp.rbytes;
19806ab6cb20SWENTAO YANG hiokp->obytes.value.ul = (uint32_t)statsp.obytes;
19816ab6cb20SWENTAO YANG hiokp->obytes64.value.ull = statsp.obytes;
19826ab6cb20SWENTAO YANG hiokp->multircv.value.ul = statsp.multircv;
19836ab6cb20SWENTAO YANG hiokp->multixmt.value.ul = statsp.multixmt;
19846ab6cb20SWENTAO YANG hiokp->brdcstrcv.value.ul = statsp.brdcstrcv;
19856ab6cb20SWENTAO YANG hiokp->brdcstxmt.value.ul = statsp.brdcstxmt;
19866ab6cb20SWENTAO YANG hiokp->norcvbuf.value.ul = statsp.norcvbuf;
19876ab6cb20SWENTAO YANG hiokp->noxmtbuf.value.ul = statsp.noxmtbuf;
19886ab6cb20SWENTAO YANG } else {
19896ab6cb20SWENTAO YANG return (EACCES);
19906ab6cb20SWENTAO YANG }
19916ab6cb20SWENTAO YANG
19926ab6cb20SWENTAO YANG return (0);
19936ab6cb20SWENTAO YANG }
19946ab6cb20SWENTAO YANG
19956ab6cb20SWENTAO YANG static void
vnet_hio_get_stats(vnet_res_t * vresp,vnet_hio_stats_t * statsp)19966ab6cb20SWENTAO YANG vnet_hio_get_stats(vnet_res_t *vresp, vnet_hio_stats_t *statsp)
19976ab6cb20SWENTAO YANG {
19986ab6cb20SWENTAO YANG mac_register_t *macp;
19996ab6cb20SWENTAO YANG mac_callbacks_t *cbp;
20006ab6cb20SWENTAO YANG uint64_t val;
20016ab6cb20SWENTAO YANG int stat;
20026ab6cb20SWENTAO YANG
20036ab6cb20SWENTAO YANG /*
20046ab6cb20SWENTAO YANG * get the specified statistics from the underlying nxge.
20056ab6cb20SWENTAO YANG */
20066ab6cb20SWENTAO YANG macp = &vresp->macreg;
20076ab6cb20SWENTAO YANG cbp = macp->m_callbacks;
20086ab6cb20SWENTAO YANG for (stat = MAC_STAT_MIN; stat < MAC_STAT_OVERFLOWS; stat++) {
20096ab6cb20SWENTAO YANG if (cbp->mc_getstat(macp->m_driver, stat, &val) == 0) {
20106ab6cb20SWENTAO YANG switch (stat) {
20116ab6cb20SWENTAO YANG case MAC_STAT_IPACKETS:
20126ab6cb20SWENTAO YANG statsp->ipackets = val;
20136ab6cb20SWENTAO YANG break;
20146ab6cb20SWENTAO YANG
20156ab6cb20SWENTAO YANG case MAC_STAT_IERRORS:
20166ab6cb20SWENTAO YANG statsp->ierrors = val;
20176ab6cb20SWENTAO YANG break;
20186ab6cb20SWENTAO YANG
20196ab6cb20SWENTAO YANG case MAC_STAT_OPACKETS:
20206ab6cb20SWENTAO YANG statsp->opackets = val;
20216ab6cb20SWENTAO YANG break;
20226ab6cb20SWENTAO YANG
20236ab6cb20SWENTAO YANG case MAC_STAT_OERRORS:
20246ab6cb20SWENTAO YANG statsp->oerrors = val;
20256ab6cb20SWENTAO YANG break;
20266ab6cb20SWENTAO YANG
20276ab6cb20SWENTAO YANG case MAC_STAT_RBYTES:
20286ab6cb20SWENTAO YANG statsp->rbytes = val;
20296ab6cb20SWENTAO YANG break;
20306ab6cb20SWENTAO YANG
20316ab6cb20SWENTAO YANG case MAC_STAT_OBYTES:
20326ab6cb20SWENTAO YANG statsp->obytes = val;
20336ab6cb20SWENTAO YANG break;
20346ab6cb20SWENTAO YANG
20356ab6cb20SWENTAO YANG case MAC_STAT_MULTIRCV:
20366ab6cb20SWENTAO YANG statsp->multircv = val;
20376ab6cb20SWENTAO YANG break;
20386ab6cb20SWENTAO YANG
20396ab6cb20SWENTAO YANG case MAC_STAT_MULTIXMT:
20406ab6cb20SWENTAO YANG statsp->multixmt = val;
20416ab6cb20SWENTAO YANG break;
20426ab6cb20SWENTAO YANG
20436ab6cb20SWENTAO YANG case MAC_STAT_BRDCSTRCV:
20446ab6cb20SWENTAO YANG statsp->brdcstrcv = val;
20456ab6cb20SWENTAO YANG break;
20466ab6cb20SWENTAO YANG
20476ab6cb20SWENTAO YANG case MAC_STAT_BRDCSTXMT:
20486ab6cb20SWENTAO YANG statsp->brdcstxmt = val;
20496ab6cb20SWENTAO YANG break;
20506ab6cb20SWENTAO YANG
20516ab6cb20SWENTAO YANG case MAC_STAT_NOXMTBUF:
20526ab6cb20SWENTAO YANG statsp->noxmtbuf = val;
20536ab6cb20SWENTAO YANG break;
20546ab6cb20SWENTAO YANG
20556ab6cb20SWENTAO YANG case MAC_STAT_NORCVBUF:
20566ab6cb20SWENTAO YANG statsp->norcvbuf = val;
20576ab6cb20SWENTAO YANG break;
20586ab6cb20SWENTAO YANG
20596ab6cb20SWENTAO YANG default:
20606ab6cb20SWENTAO YANG /*
20616ab6cb20SWENTAO YANG * parameters not interested.
20626ab6cb20SWENTAO YANG */
20636ab6cb20SWENTAO YANG break;
20646ab6cb20SWENTAO YANG }
20656ab6cb20SWENTAO YANG }
20666ab6cb20SWENTAO YANG }
20676ab6cb20SWENTAO YANG }
20681107ea93SSriharsha Basavapatna
206963f531d1SSriharsha Basavapatna static boolean_t
vnet_m_capab(void * arg,mac_capab_t cap,void * cap_data)207063f531d1SSriharsha Basavapatna vnet_m_capab(void *arg, mac_capab_t cap, void *cap_data)
207163f531d1SSriharsha Basavapatna {
207263f531d1SSriharsha Basavapatna vnet_t *vnetp = (vnet_t *)arg;
207363f531d1SSriharsha Basavapatna
207463f531d1SSriharsha Basavapatna if (vnetp == NULL) {
207563f531d1SSriharsha Basavapatna return (0);
207663f531d1SSriharsha Basavapatna }
207763f531d1SSriharsha Basavapatna
207863f531d1SSriharsha Basavapatna switch (cap) {
207963f531d1SSriharsha Basavapatna
208063f531d1SSriharsha Basavapatna case MAC_CAPAB_RINGS: {
208163f531d1SSriharsha Basavapatna
208263f531d1SSriharsha Basavapatna mac_capab_rings_t *cap_rings = cap_data;
208363f531d1SSriharsha Basavapatna /*
208463f531d1SSriharsha Basavapatna * Rings Capability Notes:
208563f531d1SSriharsha Basavapatna * We advertise rings to make use of the rings framework in
208663f531d1SSriharsha Basavapatna * gldv3 mac layer, to improve the performance. This is
208763f531d1SSriharsha Basavapatna * specifically needed when a Hybrid resource (with multiple
208863f531d1SSriharsha Basavapatna * tx/rx hardware rings) is assigned to a vnet device. We also
208963f531d1SSriharsha Basavapatna * leverage this for the normal case when no Hybrid resource is
209063f531d1SSriharsha Basavapatna * assigned.
209163f531d1SSriharsha Basavapatna *
209263f531d1SSriharsha Basavapatna * Ring Allocation:
209363f531d1SSriharsha Basavapatna * - TX path:
209463f531d1SSriharsha Basavapatna * We expose a pseudo ring group with 2 pseudo tx rings (as
209563f531d1SSriharsha Basavapatna * currently HybridIO exports only 2 rings) In the normal case,
209663f531d1SSriharsha Basavapatna * transmit traffic that comes down to the driver through the
209763f531d1SSriharsha Basavapatna * mri_tx (vnet_tx_ring_send()) entry point goes through the
209863f531d1SSriharsha Basavapatna * distributed switching algorithm in vnet and gets transmitted
209963f531d1SSriharsha Basavapatna * over a port/LDC in the vgen layer to either the vswitch or a
210063f531d1SSriharsha Basavapatna * peer vnet. If and when a Hybrid resource is assigned to the
210163f531d1SSriharsha Basavapatna * vnet, we obtain the tx ring information of the Hybrid device
210263f531d1SSriharsha Basavapatna * (nxge) and map the pseudo rings 1:1 to the 2 hw tx rings.
210363f531d1SSriharsha Basavapatna * Traffic being sent over the Hybrid resource by the mac layer
210463f531d1SSriharsha Basavapatna * gets spread across both hw rings, as they are mapped to the
210563f531d1SSriharsha Basavapatna * 2 pseudo tx rings in vnet.
210663f531d1SSriharsha Basavapatna *
210763f531d1SSriharsha Basavapatna * - RX path:
210863f531d1SSriharsha Basavapatna * We expose a pseudo ring group with 3 pseudo rx rings (static
210963f531d1SSriharsha Basavapatna * rings) initially. The first (default) pseudo rx ring is
211063f531d1SSriharsha Basavapatna * reserved for the resource that connects to the vswitch
211163f531d1SSriharsha Basavapatna * service. The next 2 rings are reserved for a Hybrid resource
211263f531d1SSriharsha Basavapatna * that may be assigned to the vnet device. If and when a
211363f531d1SSriharsha Basavapatna * Hybrid resource is assigned to the vnet, we obtain the rx
211463f531d1SSriharsha Basavapatna * ring information of the Hybrid device (nxge) and map these
211563f531d1SSriharsha Basavapatna * pseudo rings 1:1 to the 2 hw rx rings. For each additional
211663f531d1SSriharsha Basavapatna * resource that connects to a peer vnet, we dynamically
211763f531d1SSriharsha Basavapatna * allocate a pseudo rx ring and map it to that resource, when
211863f531d1SSriharsha Basavapatna * the resource gets added; and the pseudo rx ring is
211963f531d1SSriharsha Basavapatna * dynamically registered with the upper mac layer. We do the
212063f531d1SSriharsha Basavapatna * reverse and unregister the ring with the mac layer when
212163f531d1SSriharsha Basavapatna * the resource gets removed.
212263f531d1SSriharsha Basavapatna *
212363f531d1SSriharsha Basavapatna * Synchronization notes:
212463f531d1SSriharsha Basavapatna * We don't need any lock to protect members of ring structure,
212563f531d1SSriharsha Basavapatna * specifically ringp->hw_rh, in either the TX or the RX ring,
212663f531d1SSriharsha Basavapatna * as explained below.
212763f531d1SSriharsha Basavapatna * - TX ring:
212863f531d1SSriharsha Basavapatna * ring->hw_rh is initialized only when a Hybrid resource is
212963f531d1SSriharsha Basavapatna * associated; and gets referenced only in vnet_hio_tx(). The
213063f531d1SSriharsha Basavapatna * Hybrid resource itself is available in fdb only after tx
213163f531d1SSriharsha Basavapatna * hwrings are found and mapped; i.e, in vio_net_resource_reg()
213263f531d1SSriharsha Basavapatna * we call vnet_bind_rings() first and then call
213363f531d1SSriharsha Basavapatna * vnet_start_resources() which adds an entry to fdb. For
213463f531d1SSriharsha Basavapatna * traffic going over LDC resources, we don't reference
213563f531d1SSriharsha Basavapatna * ring->hw_rh at all.
213663f531d1SSriharsha Basavapatna * - RX ring:
213763f531d1SSriharsha Basavapatna * For rings mapped to Hybrid resource ring->hw_rh is
213863f531d1SSriharsha Basavapatna * initialized and only then do we add the rx callback for
213963f531d1SSriharsha Basavapatna * the underlying Hybrid resource; we disable callbacks before
214063f531d1SSriharsha Basavapatna * we unmap ring->hw_rh. For rings mapped to LDC resources, we
214163f531d1SSriharsha Basavapatna * stop the rx callbacks (in vgen) before we remove ring->hw_rh
214263f531d1SSriharsha Basavapatna * (vio_net_resource_unreg()).
21430dc2366fSVenugopal Iyer * Also, we access ring->hw_rh in vnet_rx_ring_stat().
21440dc2366fSVenugopal Iyer * Note that for rings mapped to Hybrid resource, though the
21450dc2366fSVenugopal Iyer * rings are statically registered with the mac layer, its
21460dc2366fSVenugopal Iyer * hardware ring mapping (ringp->hw_rh) can be torn down in
21470dc2366fSVenugopal Iyer * vnet_unbind_hwrings() while the kstat operation is in
21480dc2366fSVenugopal Iyer * progress. To protect against this, we hold a reference to
21490dc2366fSVenugopal Iyer * the resource in FDB; this ensures that the thread in
21500dc2366fSVenugopal Iyer * vio_net_resource_unreg() waits for the reference to be
21510dc2366fSVenugopal Iyer * dropped before unbinding the ring.
21520dc2366fSVenugopal Iyer *
21530dc2366fSVenugopal Iyer * We don't need to do this for rings mapped to LDC resources.
21540dc2366fSVenugopal Iyer * These rings are registered/unregistered dynamically with
21550dc2366fSVenugopal Iyer * the mac layer and so any attempt to unregister the ring
21560dc2366fSVenugopal Iyer * while kstat operation is in progress will block in
21570dc2366fSVenugopal Iyer * mac_group_rem_ring(). Thus implicitly protects the
21580dc2366fSVenugopal Iyer * resource (ringp->hw_rh) from disappearing.
215963f531d1SSriharsha Basavapatna */
216063f531d1SSriharsha Basavapatna
216163f531d1SSriharsha Basavapatna if (cap_rings->mr_type == MAC_RING_TYPE_RX) {
216263f531d1SSriharsha Basavapatna cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
216363f531d1SSriharsha Basavapatna
216463f531d1SSriharsha Basavapatna /*
216563f531d1SSriharsha Basavapatna * The ring_cnt for rx grp is initialized in
216663f531d1SSriharsha Basavapatna * vnet_ring_grp_init(). Later, the ring_cnt gets
216763f531d1SSriharsha Basavapatna * updated dynamically whenever LDC resources are added
216863f531d1SSriharsha Basavapatna * or removed.
216963f531d1SSriharsha Basavapatna */
217063f531d1SSriharsha Basavapatna cap_rings->mr_rnum = vnetp->rx_grp[0].ring_cnt;
217163f531d1SSriharsha Basavapatna cap_rings->mr_rget = vnet_get_ring;
217263f531d1SSriharsha Basavapatna
217363f531d1SSriharsha Basavapatna cap_rings->mr_gnum = VNET_NUM_PSEUDO_GROUPS;
217463f531d1SSriharsha Basavapatna cap_rings->mr_gget = vnet_get_group;
217563f531d1SSriharsha Basavapatna cap_rings->mr_gaddring = NULL;
217663f531d1SSriharsha Basavapatna cap_rings->mr_gremring = NULL;
217763f531d1SSriharsha Basavapatna } else {
217863f531d1SSriharsha Basavapatna cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
217963f531d1SSriharsha Basavapatna
218063f531d1SSriharsha Basavapatna /*
218163f531d1SSriharsha Basavapatna * The ring_cnt for tx grp is initialized in
218263f531d1SSriharsha Basavapatna * vnet_ring_grp_init() and remains constant, as we
218363f531d1SSriharsha Basavapatna * do not support dymanic tx rings for now.
218463f531d1SSriharsha Basavapatna */
218563f531d1SSriharsha Basavapatna cap_rings->mr_rnum = vnetp->tx_grp[0].ring_cnt;
218663f531d1SSriharsha Basavapatna cap_rings->mr_rget = vnet_get_ring;
218763f531d1SSriharsha Basavapatna
218863f531d1SSriharsha Basavapatna /*
218963f531d1SSriharsha Basavapatna * Transmit rings are not grouped; i.e, the number of
219063f531d1SSriharsha Basavapatna * transmit ring groups advertised should be set to 0.
219163f531d1SSriharsha Basavapatna */
219263f531d1SSriharsha Basavapatna cap_rings->mr_gnum = 0;
219363f531d1SSriharsha Basavapatna
219463f531d1SSriharsha Basavapatna cap_rings->mr_gget = vnet_get_group;
219563f531d1SSriharsha Basavapatna cap_rings->mr_gaddring = NULL;
219663f531d1SSriharsha Basavapatna cap_rings->mr_gremring = NULL;
219763f531d1SSriharsha Basavapatna }
219863f531d1SSriharsha Basavapatna return (B_TRUE);
219963f531d1SSriharsha Basavapatna
220063f531d1SSriharsha Basavapatna }
220163f531d1SSriharsha Basavapatna
220263f531d1SSriharsha Basavapatna default:
220363f531d1SSriharsha Basavapatna break;
220463f531d1SSriharsha Basavapatna
220563f531d1SSriharsha Basavapatna }
220663f531d1SSriharsha Basavapatna
220763f531d1SSriharsha Basavapatna return (B_FALSE);
220863f531d1SSriharsha Basavapatna }
220963f531d1SSriharsha Basavapatna
221063f531d1SSriharsha Basavapatna /*
221163f531d1SSriharsha Basavapatna * Callback funtion for MAC layer to get ring information.
221263f531d1SSriharsha Basavapatna */
221363f531d1SSriharsha Basavapatna static void
vnet_get_ring(void * arg,mac_ring_type_t rtype,const int g_index,const int r_index,mac_ring_info_t * infop,mac_ring_handle_t r_handle)221463f531d1SSriharsha Basavapatna vnet_get_ring(void *arg, mac_ring_type_t rtype, const int g_index,
221563f531d1SSriharsha Basavapatna const int r_index, mac_ring_info_t *infop, mac_ring_handle_t r_handle)
221663f531d1SSriharsha Basavapatna {
221763f531d1SSriharsha Basavapatna vnet_t *vnetp = arg;
221863f531d1SSriharsha Basavapatna
221963f531d1SSriharsha Basavapatna switch (rtype) {
222063f531d1SSriharsha Basavapatna
222163f531d1SSriharsha Basavapatna case MAC_RING_TYPE_RX: {
222263f531d1SSriharsha Basavapatna
222363f531d1SSriharsha Basavapatna vnet_pseudo_rx_group_t *rx_grp;
222463f531d1SSriharsha Basavapatna vnet_pseudo_rx_ring_t *rx_ringp;
222563f531d1SSriharsha Basavapatna mac_intr_t *mintr;
222663f531d1SSriharsha Basavapatna
222763f531d1SSriharsha Basavapatna /* We advertised only one RX group */
222863f531d1SSriharsha Basavapatna ASSERT(g_index == 0);
222963f531d1SSriharsha Basavapatna rx_grp = &vnetp->rx_grp[g_index];
223063f531d1SSriharsha Basavapatna
223163f531d1SSriharsha Basavapatna /* Check the current # of rings in the rx group */
223263f531d1SSriharsha Basavapatna ASSERT((r_index >= 0) && (r_index < rx_grp->max_ring_cnt));
223363f531d1SSriharsha Basavapatna
223463f531d1SSriharsha Basavapatna /* Get the ring based on the index */
223563f531d1SSriharsha Basavapatna rx_ringp = &rx_grp->rings[r_index];
223663f531d1SSriharsha Basavapatna
223763f531d1SSriharsha Basavapatna rx_ringp->handle = r_handle;
223863f531d1SSriharsha Basavapatna /*
223963f531d1SSriharsha Basavapatna * Note: we don't need to save the incoming r_index in rx_ring,
224063f531d1SSriharsha Basavapatna * as vnet_ring_grp_init() would have initialized the index for
224163f531d1SSriharsha Basavapatna * each ring in the array.
224263f531d1SSriharsha Basavapatna */
224363f531d1SSriharsha Basavapatna rx_ringp->grp = rx_grp;
224463f531d1SSriharsha Basavapatna rx_ringp->vnetp = vnetp;
224563f531d1SSriharsha Basavapatna
224663f531d1SSriharsha Basavapatna mintr = &infop->mri_intr;
224763f531d1SSriharsha Basavapatna mintr->mi_handle = (mac_intr_handle_t)rx_ringp;
224863f531d1SSriharsha Basavapatna mintr->mi_enable = (mac_intr_enable_t)vnet_ring_enable_intr;
224963f531d1SSriharsha Basavapatna mintr->mi_disable = (mac_intr_disable_t)vnet_ring_disable_intr;
225063f531d1SSriharsha Basavapatna
225163f531d1SSriharsha Basavapatna infop->mri_driver = (mac_ring_driver_t)rx_ringp;
225263f531d1SSriharsha Basavapatna infop->mri_start = vnet_rx_ring_start;
225363f531d1SSriharsha Basavapatna infop->mri_stop = vnet_rx_ring_stop;
22540dc2366fSVenugopal Iyer infop->mri_stat = vnet_rx_ring_stat;
225563f531d1SSriharsha Basavapatna
225663f531d1SSriharsha Basavapatna /* Set the poll function, as this is an rx ring */
225763f531d1SSriharsha Basavapatna infop->mri_poll = vnet_rx_poll;
22580dc2366fSVenugopal Iyer /*
22590dc2366fSVenugopal Iyer * MAC_RING_RX_ENQUEUE bit needed to be set for nxge
22600dc2366fSVenugopal Iyer * which was not sending packet chains in interrupt
22610dc2366fSVenugopal Iyer * context. For such drivers, packets are queued in
22620dc2366fSVenugopal Iyer * Rx soft rings so that we get a chance to switch
22630dc2366fSVenugopal Iyer * into a polling mode under backlog. This bug (not
22640dc2366fSVenugopal Iyer * sending packet chains) has now been fixed. Once
22650dc2366fSVenugopal Iyer * the performance impact is measured, this change
22660dc2366fSVenugopal Iyer * will be removed.
22670dc2366fSVenugopal Iyer */
22680dc2366fSVenugopal Iyer infop->mri_flags = (vnet_mac_rx_queuing ?
22690dc2366fSVenugopal Iyer MAC_RING_RX_ENQUEUE : 0);
227063f531d1SSriharsha Basavapatna break;
227163f531d1SSriharsha Basavapatna }
227263f531d1SSriharsha Basavapatna
227363f531d1SSriharsha Basavapatna case MAC_RING_TYPE_TX: {
227463f531d1SSriharsha Basavapatna vnet_pseudo_tx_group_t *tx_grp;
227563f531d1SSriharsha Basavapatna vnet_pseudo_tx_ring_t *tx_ringp;
227663f531d1SSriharsha Basavapatna
227763f531d1SSriharsha Basavapatna /*
227863f531d1SSriharsha Basavapatna * No need to check grp index; mac layer passes -1 for it.
227963f531d1SSriharsha Basavapatna */
228063f531d1SSriharsha Basavapatna tx_grp = &vnetp->tx_grp[0];
228163f531d1SSriharsha Basavapatna
228263f531d1SSriharsha Basavapatna /* Check the # of rings in the tx group */
228363f531d1SSriharsha Basavapatna ASSERT((r_index >= 0) && (r_index < tx_grp->ring_cnt));
228463f531d1SSriharsha Basavapatna
228563f531d1SSriharsha Basavapatna /* Get the ring based on the index */
228663f531d1SSriharsha Basavapatna tx_ringp = &tx_grp->rings[r_index];
228763f531d1SSriharsha Basavapatna
228863f531d1SSriharsha Basavapatna tx_ringp->handle = r_handle;
228963f531d1SSriharsha Basavapatna tx_ringp->index = r_index;
229063f531d1SSriharsha Basavapatna tx_ringp->grp = tx_grp;
229163f531d1SSriharsha Basavapatna tx_ringp->vnetp = vnetp;
229263f531d1SSriharsha Basavapatna
229363f531d1SSriharsha Basavapatna infop->mri_driver = (mac_ring_driver_t)tx_ringp;
229463f531d1SSriharsha Basavapatna infop->mri_start = vnet_tx_ring_start;
229563f531d1SSriharsha Basavapatna infop->mri_stop = vnet_tx_ring_stop;
22960dc2366fSVenugopal Iyer infop->mri_stat = vnet_tx_ring_stat;
229763f531d1SSriharsha Basavapatna
229863f531d1SSriharsha Basavapatna /* Set the transmit function, as this is a tx ring */
229963f531d1SSriharsha Basavapatna infop->mri_tx = vnet_tx_ring_send;
23000dc2366fSVenugopal Iyer /*
23010dc2366fSVenugopal Iyer * MAC_RING_TX_SERIALIZE bit needs to be set while
23020dc2366fSVenugopal Iyer * hybridIO is enabled to workaround tx lock
23030dc2366fSVenugopal Iyer * contention issues in nxge.
23040dc2366fSVenugopal Iyer */
23050dc2366fSVenugopal Iyer infop->mri_flags = (vnet_mac_tx_serialize ?
23060dc2366fSVenugopal Iyer MAC_RING_TX_SERIALIZE : 0);
230763f531d1SSriharsha Basavapatna break;
230863f531d1SSriharsha Basavapatna }
230963f531d1SSriharsha Basavapatna
231063f531d1SSriharsha Basavapatna default:
231163f531d1SSriharsha Basavapatna break;
231263f531d1SSriharsha Basavapatna }
231363f531d1SSriharsha Basavapatna }
231463f531d1SSriharsha Basavapatna
231563f531d1SSriharsha Basavapatna /*
231663f531d1SSriharsha Basavapatna * Callback funtion for MAC layer to get group information.
231763f531d1SSriharsha Basavapatna */
231863f531d1SSriharsha Basavapatna static void
vnet_get_group(void * arg,mac_ring_type_t type,const int index,mac_group_info_t * infop,mac_group_handle_t handle)231963f531d1SSriharsha Basavapatna vnet_get_group(void *arg, mac_ring_type_t type, const int index,
232063f531d1SSriharsha Basavapatna mac_group_info_t *infop, mac_group_handle_t handle)
232163f531d1SSriharsha Basavapatna {
232263f531d1SSriharsha Basavapatna vnet_t *vnetp = (vnet_t *)arg;
232363f531d1SSriharsha Basavapatna
232463f531d1SSriharsha Basavapatna switch (type) {
232563f531d1SSriharsha Basavapatna
232663f531d1SSriharsha Basavapatna case MAC_RING_TYPE_RX:
232763f531d1SSriharsha Basavapatna {
232863f531d1SSriharsha Basavapatna vnet_pseudo_rx_group_t *rx_grp;
232963f531d1SSriharsha Basavapatna
233063f531d1SSriharsha Basavapatna /* We advertised only one RX group */
233163f531d1SSriharsha Basavapatna ASSERT(index == 0);
233263f531d1SSriharsha Basavapatna
233363f531d1SSriharsha Basavapatna rx_grp = &vnetp->rx_grp[index];
233463f531d1SSriharsha Basavapatna rx_grp->handle = handle;
233563f531d1SSriharsha Basavapatna rx_grp->index = index;
233663f531d1SSriharsha Basavapatna rx_grp->vnetp = vnetp;
233763f531d1SSriharsha Basavapatna
233863f531d1SSriharsha Basavapatna infop->mgi_driver = (mac_group_driver_t)rx_grp;
233963f531d1SSriharsha Basavapatna infop->mgi_start = NULL;
234063f531d1SSriharsha Basavapatna infop->mgi_stop = NULL;
234163f531d1SSriharsha Basavapatna infop->mgi_addmac = vnet_addmac;
234263f531d1SSriharsha Basavapatna infop->mgi_remmac = vnet_remmac;
234363f531d1SSriharsha Basavapatna infop->mgi_count = rx_grp->ring_cnt;
234463f531d1SSriharsha Basavapatna
234563f531d1SSriharsha Basavapatna break;
234663f531d1SSriharsha Basavapatna }
234763f531d1SSriharsha Basavapatna
234863f531d1SSriharsha Basavapatna case MAC_RING_TYPE_TX:
234963f531d1SSriharsha Basavapatna {
235063f531d1SSriharsha Basavapatna vnet_pseudo_tx_group_t *tx_grp;
235163f531d1SSriharsha Basavapatna
235263f531d1SSriharsha Basavapatna /* We advertised only one TX group */
235363f531d1SSriharsha Basavapatna ASSERT(index == 0);
235463f531d1SSriharsha Basavapatna
235563f531d1SSriharsha Basavapatna tx_grp = &vnetp->tx_grp[index];
235663f531d1SSriharsha Basavapatna tx_grp->handle = handle;
235763f531d1SSriharsha Basavapatna tx_grp->index = index;
235863f531d1SSriharsha Basavapatna tx_grp->vnetp = vnetp;
235963f531d1SSriharsha Basavapatna
236063f531d1SSriharsha Basavapatna infop->mgi_driver = (mac_group_driver_t)tx_grp;
236163f531d1SSriharsha Basavapatna infop->mgi_start = NULL;
236263f531d1SSriharsha Basavapatna infop->mgi_stop = NULL;
236363f531d1SSriharsha Basavapatna infop->mgi_addmac = NULL;
236463f531d1SSriharsha Basavapatna infop->mgi_remmac = NULL;
236563f531d1SSriharsha Basavapatna infop->mgi_count = VNET_NUM_PSEUDO_TXRINGS;
236663f531d1SSriharsha Basavapatna
236763f531d1SSriharsha Basavapatna break;
236863f531d1SSriharsha Basavapatna }
236963f531d1SSriharsha Basavapatna
237063f531d1SSriharsha Basavapatna default:
237163f531d1SSriharsha Basavapatna break;
237263f531d1SSriharsha Basavapatna
237363f531d1SSriharsha Basavapatna }
237463f531d1SSriharsha Basavapatna }
237563f531d1SSriharsha Basavapatna
237663f531d1SSriharsha Basavapatna static int
vnet_rx_ring_start(mac_ring_driver_t arg,uint64_t mr_gen_num)237763f531d1SSriharsha Basavapatna vnet_rx_ring_start(mac_ring_driver_t arg, uint64_t mr_gen_num)
237863f531d1SSriharsha Basavapatna {
237963f531d1SSriharsha Basavapatna vnet_pseudo_rx_ring_t *rx_ringp = (vnet_pseudo_rx_ring_t *)arg;
238063f531d1SSriharsha Basavapatna int err;
238163f531d1SSriharsha Basavapatna
238263f531d1SSriharsha Basavapatna /*
238363f531d1SSriharsha Basavapatna * If this ring is mapped to a LDC resource, simply mark the state to
238463f531d1SSriharsha Basavapatna * indicate the ring is started and return.
238563f531d1SSriharsha Basavapatna */
238663f531d1SSriharsha Basavapatna if ((rx_ringp->state &
238763f531d1SSriharsha Basavapatna (VNET_RXRING_LDC_SERVICE|VNET_RXRING_LDC_GUEST)) != 0) {
238863f531d1SSriharsha Basavapatna rx_ringp->gen_num = mr_gen_num;
238963f531d1SSriharsha Basavapatna rx_ringp->state |= VNET_RXRING_STARTED;
239063f531d1SSriharsha Basavapatna return (0);
239163f531d1SSriharsha Basavapatna }
239263f531d1SSriharsha Basavapatna
239363f531d1SSriharsha Basavapatna ASSERT((rx_ringp->state & VNET_RXRING_HYBRID) != 0);
239463f531d1SSriharsha Basavapatna
239563f531d1SSriharsha Basavapatna /*
239663f531d1SSriharsha Basavapatna * This must be a ring reserved for a hwring. If the hwring is not
239763f531d1SSriharsha Basavapatna * bound yet, simply mark the state to indicate the ring is started and
239863f531d1SSriharsha Basavapatna * return. If and when a hybrid resource is activated for this vnet
239963f531d1SSriharsha Basavapatna * device, we will bind the hwring and start it then. If a hwring is
240063f531d1SSriharsha Basavapatna * already bound, start it now.
240163f531d1SSriharsha Basavapatna */
240263f531d1SSriharsha Basavapatna if (rx_ringp->hw_rh == NULL) {
240363f531d1SSriharsha Basavapatna rx_ringp->gen_num = mr_gen_num;
240463f531d1SSriharsha Basavapatna rx_ringp->state |= VNET_RXRING_STARTED;
240563f531d1SSriharsha Basavapatna return (0);
240663f531d1SSriharsha Basavapatna }
240763f531d1SSriharsha Basavapatna
240863f531d1SSriharsha Basavapatna err = mac_hwring_start(rx_ringp->hw_rh);
240963f531d1SSriharsha Basavapatna if (err == 0) {
241063f531d1SSriharsha Basavapatna rx_ringp->gen_num = mr_gen_num;
241163f531d1SSriharsha Basavapatna rx_ringp->state |= VNET_RXRING_STARTED;
241263f531d1SSriharsha Basavapatna } else {
241363f531d1SSriharsha Basavapatna err = ENXIO;
241463f531d1SSriharsha Basavapatna }
241563f531d1SSriharsha Basavapatna
241663f531d1SSriharsha Basavapatna return (err);
241763f531d1SSriharsha Basavapatna }
241863f531d1SSriharsha Basavapatna
241963f531d1SSriharsha Basavapatna static void
vnet_rx_ring_stop(mac_ring_driver_t arg)242063f531d1SSriharsha Basavapatna vnet_rx_ring_stop(mac_ring_driver_t arg)
242163f531d1SSriharsha Basavapatna {
242263f531d1SSriharsha Basavapatna vnet_pseudo_rx_ring_t *rx_ringp = (vnet_pseudo_rx_ring_t *)arg;
242363f531d1SSriharsha Basavapatna
242463f531d1SSriharsha Basavapatna /*
242563f531d1SSriharsha Basavapatna * If this ring is mapped to a LDC resource, simply mark the state to
242663f531d1SSriharsha Basavapatna * indicate the ring is now stopped and return.
242763f531d1SSriharsha Basavapatna */
242863f531d1SSriharsha Basavapatna if ((rx_ringp->state &
242963f531d1SSriharsha Basavapatna (VNET_RXRING_LDC_SERVICE|VNET_RXRING_LDC_GUEST)) != 0) {
243063f531d1SSriharsha Basavapatna rx_ringp->state &= ~VNET_RXRING_STARTED;
2431e8c4ecbbSWENTAO YANG return;
243263f531d1SSriharsha Basavapatna }
243363f531d1SSriharsha Basavapatna
243463f531d1SSriharsha Basavapatna ASSERT((rx_ringp->state & VNET_RXRING_HYBRID) != 0);
243563f531d1SSriharsha Basavapatna
243663f531d1SSriharsha Basavapatna /*
243763f531d1SSriharsha Basavapatna * This must be a ring reserved for a hwring. If the hwring is not
243863f531d1SSriharsha Basavapatna * bound yet, simply mark the state to indicate the ring is stopped and
243963f531d1SSriharsha Basavapatna * return. If a hwring is already bound, stop it now.
244063f531d1SSriharsha Basavapatna */
244163f531d1SSriharsha Basavapatna if (rx_ringp->hw_rh == NULL) {
244263f531d1SSriharsha Basavapatna rx_ringp->state &= ~VNET_RXRING_STARTED;
244363f531d1SSriharsha Basavapatna return;
244463f531d1SSriharsha Basavapatna }
244563f531d1SSriharsha Basavapatna
244663f531d1SSriharsha Basavapatna mac_hwring_stop(rx_ringp->hw_rh);
244763f531d1SSriharsha Basavapatna rx_ringp->state &= ~VNET_RXRING_STARTED;
244863f531d1SSriharsha Basavapatna }
244963f531d1SSriharsha Basavapatna
24500dc2366fSVenugopal Iyer static int
vnet_rx_ring_stat(mac_ring_driver_t rdriver,uint_t stat,uint64_t * val)24510dc2366fSVenugopal Iyer vnet_rx_ring_stat(mac_ring_driver_t rdriver, uint_t stat, uint64_t *val)
24520dc2366fSVenugopal Iyer {
24530dc2366fSVenugopal Iyer vnet_pseudo_rx_ring_t *rx_ringp = (vnet_pseudo_rx_ring_t *)rdriver;
24540dc2366fSVenugopal Iyer vnet_t *vnetp = (vnet_t *)rx_ringp->vnetp;
24550dc2366fSVenugopal Iyer vnet_res_t *vresp;
24560dc2366fSVenugopal Iyer mac_register_t *macp;
24570dc2366fSVenugopal Iyer mac_callbacks_t *cbp;
24580dc2366fSVenugopal Iyer
24590dc2366fSVenugopal Iyer /*
24600dc2366fSVenugopal Iyer * Refer to vnet_m_capab() function for detailed comments on ring
24610dc2366fSVenugopal Iyer * synchronization.
24620dc2366fSVenugopal Iyer */
24630dc2366fSVenugopal Iyer if ((rx_ringp->state & VNET_RXRING_HYBRID) != 0) {
24640dc2366fSVenugopal Iyer READ_ENTER(&vnetp->vsw_fp_rw);
24650dc2366fSVenugopal Iyer if (vnetp->hio_fp == NULL) {
24660dc2366fSVenugopal Iyer RW_EXIT(&vnetp->vsw_fp_rw);
24670dc2366fSVenugopal Iyer return (0);
24680dc2366fSVenugopal Iyer }
24690dc2366fSVenugopal Iyer
24700dc2366fSVenugopal Iyer VNET_FDBE_REFHOLD(vnetp->hio_fp);
24710dc2366fSVenugopal Iyer RW_EXIT(&vnetp->vsw_fp_rw);
24729f26b864SVenugopal Iyer (void) mac_hwring_getstat(rx_ringp->hw_rh, stat, val);
24730dc2366fSVenugopal Iyer VNET_FDBE_REFRELE(vnetp->hio_fp);
24740dc2366fSVenugopal Iyer return (0);
24750dc2366fSVenugopal Iyer }
24760dc2366fSVenugopal Iyer
24770dc2366fSVenugopal Iyer ASSERT((rx_ringp->state &
24780dc2366fSVenugopal Iyer (VNET_RXRING_LDC_SERVICE|VNET_RXRING_LDC_GUEST)) != 0);
24790dc2366fSVenugopal Iyer vresp = (vnet_res_t *)rx_ringp->hw_rh;
24800dc2366fSVenugopal Iyer macp = &vresp->macreg;
24810dc2366fSVenugopal Iyer cbp = macp->m_callbacks;
24820dc2366fSVenugopal Iyer
24830dc2366fSVenugopal Iyer cbp->mc_getstat(macp->m_driver, stat, val);
24840dc2366fSVenugopal Iyer
24850dc2366fSVenugopal Iyer return (0);
24860dc2366fSVenugopal Iyer }
24870dc2366fSVenugopal Iyer
248863f531d1SSriharsha Basavapatna /* ARGSUSED */
248963f531d1SSriharsha Basavapatna static int
vnet_tx_ring_start(mac_ring_driver_t arg,uint64_t mr_gen_num)249063f531d1SSriharsha Basavapatna vnet_tx_ring_start(mac_ring_driver_t arg, uint64_t mr_gen_num)
249163f531d1SSriharsha Basavapatna {
249263f531d1SSriharsha Basavapatna vnet_pseudo_tx_ring_t *tx_ringp = (vnet_pseudo_tx_ring_t *)arg;
249363f531d1SSriharsha Basavapatna
249463f531d1SSriharsha Basavapatna tx_ringp->state |= VNET_TXRING_STARTED;
249563f531d1SSriharsha Basavapatna return (0);
249663f531d1SSriharsha Basavapatna }
249763f531d1SSriharsha Basavapatna
249863f531d1SSriharsha Basavapatna static void
vnet_tx_ring_stop(mac_ring_driver_t arg)249963f531d1SSriharsha Basavapatna vnet_tx_ring_stop(mac_ring_driver_t arg)
250063f531d1SSriharsha Basavapatna {
250163f531d1SSriharsha Basavapatna vnet_pseudo_tx_ring_t *tx_ringp = (vnet_pseudo_tx_ring_t *)arg;
250263f531d1SSriharsha Basavapatna
250363f531d1SSriharsha Basavapatna tx_ringp->state &= ~VNET_TXRING_STARTED;
250463f531d1SSriharsha Basavapatna }
250563f531d1SSriharsha Basavapatna
25060dc2366fSVenugopal Iyer static int
vnet_tx_ring_stat(mac_ring_driver_t rdriver,uint_t stat,uint64_t * val)25070dc2366fSVenugopal Iyer vnet_tx_ring_stat(mac_ring_driver_t rdriver, uint_t stat, uint64_t *val)
25080dc2366fSVenugopal Iyer {
25090dc2366fSVenugopal Iyer vnet_pseudo_tx_ring_t *tx_ringp = (vnet_pseudo_tx_ring_t *)rdriver;
25100dc2366fSVenugopal Iyer vnet_tx_ring_stats_t *statsp;
25110dc2366fSVenugopal Iyer
25120dc2366fSVenugopal Iyer statsp = &tx_ringp->tx_ring_stats;
25130dc2366fSVenugopal Iyer
25140dc2366fSVenugopal Iyer switch (stat) {
25150dc2366fSVenugopal Iyer case MAC_STAT_OPACKETS:
25160dc2366fSVenugopal Iyer *val = statsp->opackets;
25170dc2366fSVenugopal Iyer break;
25180dc2366fSVenugopal Iyer
25190dc2366fSVenugopal Iyer case MAC_STAT_OBYTES:
25200dc2366fSVenugopal Iyer *val = statsp->obytes;
25210dc2366fSVenugopal Iyer break;
25220dc2366fSVenugopal Iyer
25230dc2366fSVenugopal Iyer default:
25240dc2366fSVenugopal Iyer *val = 0;
25250dc2366fSVenugopal Iyer return (ENOTSUP);
25260dc2366fSVenugopal Iyer }
25270dc2366fSVenugopal Iyer
25280dc2366fSVenugopal Iyer return (0);
25290dc2366fSVenugopal Iyer }
25300dc2366fSVenugopal Iyer
253163f531d1SSriharsha Basavapatna /*
253263f531d1SSriharsha Basavapatna * Disable polling for a ring and enable its interrupt.
253363f531d1SSriharsha Basavapatna */
253463f531d1SSriharsha Basavapatna static int
vnet_ring_enable_intr(void * arg)253563f531d1SSriharsha Basavapatna vnet_ring_enable_intr(void *arg)
253663f531d1SSriharsha Basavapatna {
253763f531d1SSriharsha Basavapatna vnet_pseudo_rx_ring_t *rx_ringp = (vnet_pseudo_rx_ring_t *)arg;
253863f531d1SSriharsha Basavapatna vnet_res_t *vresp;
253963f531d1SSriharsha Basavapatna
254063f531d1SSriharsha Basavapatna if (rx_ringp->hw_rh == NULL) {
254163f531d1SSriharsha Basavapatna /*
254263f531d1SSriharsha Basavapatna * Ring enable intr func is being invoked, but the ring is
254363f531d1SSriharsha Basavapatna * not bound to any underlying resource ? This must be a ring
254463f531d1SSriharsha Basavapatna * reserved for Hybrid resource and no such resource has been
254563f531d1SSriharsha Basavapatna * assigned to this vnet device yet. We simply return success.
254663f531d1SSriharsha Basavapatna */
254763f531d1SSriharsha Basavapatna ASSERT((rx_ringp->state & VNET_RXRING_HYBRID) != 0);
254863f531d1SSriharsha Basavapatna return (0);
254963f531d1SSriharsha Basavapatna }
255063f531d1SSriharsha Basavapatna
255163f531d1SSriharsha Basavapatna /*
255263f531d1SSriharsha Basavapatna * The rx ring has been bound to either a LDC or a Hybrid resource.
255363f531d1SSriharsha Basavapatna * Call the appropriate function to enable interrupts for the ring.
255463f531d1SSriharsha Basavapatna */
255563f531d1SSriharsha Basavapatna if (rx_ringp->state & VNET_RXRING_HYBRID) {
255663f531d1SSriharsha Basavapatna return (mac_hwring_enable_intr(rx_ringp->hw_rh));
255763f531d1SSriharsha Basavapatna } else {
255863f531d1SSriharsha Basavapatna vresp = (vnet_res_t *)rx_ringp->hw_rh;
255963f531d1SSriharsha Basavapatna return (vgen_enable_intr(vresp->macreg.m_driver));
256063f531d1SSriharsha Basavapatna }
256163f531d1SSriharsha Basavapatna }
256263f531d1SSriharsha Basavapatna
256363f531d1SSriharsha Basavapatna /*
256463f531d1SSriharsha Basavapatna * Enable polling for a ring and disable its interrupt.
256563f531d1SSriharsha Basavapatna */
256663f531d1SSriharsha Basavapatna static int
vnet_ring_disable_intr(void * arg)256763f531d1SSriharsha Basavapatna vnet_ring_disable_intr(void *arg)
256863f531d1SSriharsha Basavapatna {
256963f531d1SSriharsha Basavapatna vnet_pseudo_rx_ring_t *rx_ringp = (vnet_pseudo_rx_ring_t *)arg;
257063f531d1SSriharsha Basavapatna vnet_res_t *vresp;
257163f531d1SSriharsha Basavapatna
257263f531d1SSriharsha Basavapatna if (rx_ringp->hw_rh == NULL) {
257363f531d1SSriharsha Basavapatna /*
257463f531d1SSriharsha Basavapatna * Ring disable intr func is being invoked, but the ring is
257563f531d1SSriharsha Basavapatna * not bound to any underlying resource ? This must be a ring
257663f531d1SSriharsha Basavapatna * reserved for Hybrid resource and no such resource has been
257763f531d1SSriharsha Basavapatna * assigned to this vnet device yet. We simply return success.
257863f531d1SSriharsha Basavapatna */
257963f531d1SSriharsha Basavapatna ASSERT((rx_ringp->state & VNET_RXRING_HYBRID) != 0);
258063f531d1SSriharsha Basavapatna return (0);
258163f531d1SSriharsha Basavapatna }
258263f531d1SSriharsha Basavapatna
258363f531d1SSriharsha Basavapatna /*
258463f531d1SSriharsha Basavapatna * The rx ring has been bound to either a LDC or a Hybrid resource.
258563f531d1SSriharsha Basavapatna * Call the appropriate function to disable interrupts for the ring.
258663f531d1SSriharsha Basavapatna */
258763f531d1SSriharsha Basavapatna if (rx_ringp->state & VNET_RXRING_HYBRID) {
258863f531d1SSriharsha Basavapatna return (mac_hwring_disable_intr(rx_ringp->hw_rh));
258963f531d1SSriharsha Basavapatna } else {
259063f531d1SSriharsha Basavapatna vresp = (vnet_res_t *)rx_ringp->hw_rh;
259163f531d1SSriharsha Basavapatna return (vgen_disable_intr(vresp->macreg.m_driver));
259263f531d1SSriharsha Basavapatna }
259363f531d1SSriharsha Basavapatna }
259463f531d1SSriharsha Basavapatna
259563f531d1SSriharsha Basavapatna /*
259663f531d1SSriharsha Basavapatna * Poll 'bytes_to_pickup' bytes of message from the rx ring.
259763f531d1SSriharsha Basavapatna */
259863f531d1SSriharsha Basavapatna static mblk_t *
vnet_rx_poll(void * arg,int bytes_to_pickup)259963f531d1SSriharsha Basavapatna vnet_rx_poll(void *arg, int bytes_to_pickup)
260063f531d1SSriharsha Basavapatna {
260163f531d1SSriharsha Basavapatna vnet_pseudo_rx_ring_t *rx_ringp = (vnet_pseudo_rx_ring_t *)arg;
260263f531d1SSriharsha Basavapatna mblk_t *mp = NULL;
260363f531d1SSriharsha Basavapatna vnet_res_t *vresp;
260463f531d1SSriharsha Basavapatna vnet_t *vnetp = rx_ringp->vnetp;
260563f531d1SSriharsha Basavapatna
260663f531d1SSriharsha Basavapatna if (rx_ringp->hw_rh == NULL) {
260763f531d1SSriharsha Basavapatna return (NULL);
260863f531d1SSriharsha Basavapatna }
260963f531d1SSriharsha Basavapatna
261063f531d1SSriharsha Basavapatna if (rx_ringp->state & VNET_RXRING_HYBRID) {
261163f531d1SSriharsha Basavapatna mp = mac_hwring_poll(rx_ringp->hw_rh, bytes_to_pickup);
261263f531d1SSriharsha Basavapatna /*
261363f531d1SSriharsha Basavapatna * Packets received over a hybrid resource need additional
261463f531d1SSriharsha Basavapatna * processing to remove the tag, for the pvid case. The
261563f531d1SSriharsha Basavapatna * underlying resource is not aware of the vnet's pvid and thus
261663f531d1SSriharsha Basavapatna * packets are received with the vlan tag in the header; unlike
261763f531d1SSriharsha Basavapatna * packets that are received over a ldc channel in which case
261863f531d1SSriharsha Basavapatna * the peer vnet/vsw would have already removed the tag.
261963f531d1SSriharsha Basavapatna */
262063f531d1SSriharsha Basavapatna if (vnetp->pvid != vnetp->default_vlan_id) {
262163f531d1SSriharsha Basavapatna vnet_rx_frames_untag(vnetp->pvid, &mp);
262263f531d1SSriharsha Basavapatna }
262363f531d1SSriharsha Basavapatna } else {
262463f531d1SSriharsha Basavapatna vresp = (vnet_res_t *)rx_ringp->hw_rh;
2625*7bd3a2e2SSriharsha Basavapatna mp = vgen_rx_poll(vresp->macreg.m_driver, bytes_to_pickup);
262663f531d1SSriharsha Basavapatna }
262763f531d1SSriharsha Basavapatna return (mp);
262863f531d1SSriharsha Basavapatna }
262963f531d1SSriharsha Basavapatna
263063f531d1SSriharsha Basavapatna /* ARGSUSED */
263163f531d1SSriharsha Basavapatna void
vnet_hio_rx_cb(void * arg,mac_resource_handle_t mrh,mblk_t * mp,boolean_t loopback)263263f531d1SSriharsha Basavapatna vnet_hio_rx_cb(void *arg, mac_resource_handle_t mrh, mblk_t *mp,
263363f531d1SSriharsha Basavapatna boolean_t loopback)
263463f531d1SSriharsha Basavapatna {
263563f531d1SSriharsha Basavapatna vnet_t *vnetp = (vnet_t *)arg;
263663f531d1SSriharsha Basavapatna vnet_pseudo_rx_ring_t *ringp = (vnet_pseudo_rx_ring_t *)mrh;
263763f531d1SSriharsha Basavapatna
263863f531d1SSriharsha Basavapatna /*
263963f531d1SSriharsha Basavapatna * Packets received over a hybrid resource need additional processing
264063f531d1SSriharsha Basavapatna * to remove the tag, for the pvid case. The underlying resource is
264163f531d1SSriharsha Basavapatna * not aware of the vnet's pvid and thus packets are received with the
264263f531d1SSriharsha Basavapatna * vlan tag in the header; unlike packets that are received over a ldc
264363f531d1SSriharsha Basavapatna * channel in which case the peer vnet/vsw would have already removed
264463f531d1SSriharsha Basavapatna * the tag.
264563f531d1SSriharsha Basavapatna */
264663f531d1SSriharsha Basavapatna if (vnetp->pvid != vnetp->default_vlan_id) {
264763f531d1SSriharsha Basavapatna vnet_rx_frames_untag(vnetp->pvid, &mp);
264863f531d1SSriharsha Basavapatna if (mp == NULL) {
264963f531d1SSriharsha Basavapatna return;
265063f531d1SSriharsha Basavapatna }
265163f531d1SSriharsha Basavapatna }
265263f531d1SSriharsha Basavapatna mac_rx_ring(vnetp->mh, ringp->handle, mp, ringp->gen_num);
265363f531d1SSriharsha Basavapatna }
265463f531d1SSriharsha Basavapatna
265563f531d1SSriharsha Basavapatna static int
vnet_addmac(void * arg,const uint8_t * mac_addr)265663f531d1SSriharsha Basavapatna vnet_addmac(void *arg, const uint8_t *mac_addr)
265763f531d1SSriharsha Basavapatna {
265863f531d1SSriharsha Basavapatna vnet_pseudo_rx_group_t *rx_grp = (vnet_pseudo_rx_group_t *)arg;
265963f531d1SSriharsha Basavapatna vnet_t *vnetp;
266063f531d1SSriharsha Basavapatna
266163f531d1SSriharsha Basavapatna vnetp = rx_grp->vnetp;
266263f531d1SSriharsha Basavapatna
266363f531d1SSriharsha Basavapatna if (bcmp(mac_addr, vnetp->curr_macaddr, ETHERADDRL) == 0) {
266463f531d1SSriharsha Basavapatna return (0);
266563f531d1SSriharsha Basavapatna }
266663f531d1SSriharsha Basavapatna
266763f531d1SSriharsha Basavapatna cmn_err(CE_CONT, "!vnet%d: %s: Multiple macaddr unsupported\n",
266863f531d1SSriharsha Basavapatna vnetp->instance, __func__);
266963f531d1SSriharsha Basavapatna return (EINVAL);
267063f531d1SSriharsha Basavapatna }
267163f531d1SSriharsha Basavapatna
267263f531d1SSriharsha Basavapatna static int
vnet_remmac(void * arg,const uint8_t * mac_addr)267363f531d1SSriharsha Basavapatna vnet_remmac(void *arg, const uint8_t *mac_addr)
267463f531d1SSriharsha Basavapatna {
267563f531d1SSriharsha Basavapatna vnet_pseudo_rx_group_t *rx_grp = (vnet_pseudo_rx_group_t *)arg;
267663f531d1SSriharsha Basavapatna vnet_t *vnetp;
267763f531d1SSriharsha Basavapatna
267863f531d1SSriharsha Basavapatna vnetp = rx_grp->vnetp;
267963f531d1SSriharsha Basavapatna
268063f531d1SSriharsha Basavapatna if (bcmp(mac_addr, vnetp->curr_macaddr, ETHERADDRL) == 0) {
268163f531d1SSriharsha Basavapatna return (0);
268263f531d1SSriharsha Basavapatna }
268363f531d1SSriharsha Basavapatna
268463f531d1SSriharsha Basavapatna cmn_err(CE_CONT, "!vnet%d: %s: Invalid macaddr: %s\n",
268563f531d1SSriharsha Basavapatna vnetp->instance, __func__, ether_sprintf((void *)mac_addr));
268663f531d1SSriharsha Basavapatna return (EINVAL);
268763f531d1SSriharsha Basavapatna }
268863f531d1SSriharsha Basavapatna
268963f531d1SSriharsha Basavapatna int
vnet_hio_mac_init(vnet_t * vnetp,char * ifname)269063f531d1SSriharsha Basavapatna vnet_hio_mac_init(vnet_t *vnetp, char *ifname)
269163f531d1SSriharsha Basavapatna {
269263f531d1SSriharsha Basavapatna mac_handle_t mh;
269363f531d1SSriharsha Basavapatna mac_client_handle_t mch = NULL;
269463f531d1SSriharsha Basavapatna mac_unicast_handle_t muh = NULL;
269563f531d1SSriharsha Basavapatna mac_diag_t diag;
269663f531d1SSriharsha Basavapatna mac_register_t *macp;
269763f531d1SSriharsha Basavapatna char client_name[MAXNAMELEN];
269863f531d1SSriharsha Basavapatna int rv;
269963f531d1SSriharsha Basavapatna uint16_t mac_flags = MAC_UNICAST_TAG_DISABLE |
270063f531d1SSriharsha Basavapatna MAC_UNICAST_STRIP_DISABLE | MAC_UNICAST_PRIMARY;
270163f531d1SSriharsha Basavapatna vio_net_callbacks_t vcb;
270263f531d1SSriharsha Basavapatna ether_addr_t rem_addr =
270363f531d1SSriharsha Basavapatna { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
270463f531d1SSriharsha Basavapatna uint32_t retries = 0;
270563f531d1SSriharsha Basavapatna
270663f531d1SSriharsha Basavapatna if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
270763f531d1SSriharsha Basavapatna return (EAGAIN);
270863f531d1SSriharsha Basavapatna }
270963f531d1SSriharsha Basavapatna
271063f531d1SSriharsha Basavapatna do {
271163f531d1SSriharsha Basavapatna rv = mac_open_by_linkname(ifname, &mh);
271263f531d1SSriharsha Basavapatna if (rv == 0) {
271363f531d1SSriharsha Basavapatna break;
271463f531d1SSriharsha Basavapatna }
271563f531d1SSriharsha Basavapatna if (rv != ENOENT || (retries++ >= vnet_mac_open_retries)) {
271663f531d1SSriharsha Basavapatna mac_free(macp);
271763f531d1SSriharsha Basavapatna return (rv);
271863f531d1SSriharsha Basavapatna }
271963f531d1SSriharsha Basavapatna drv_usecwait(vnet_mac_open_delay);
272063f531d1SSriharsha Basavapatna } while (rv == ENOENT);
272163f531d1SSriharsha Basavapatna
272263f531d1SSriharsha Basavapatna vnetp->hio_mh = mh;
272363f531d1SSriharsha Basavapatna
272463f531d1SSriharsha Basavapatna (void) snprintf(client_name, MAXNAMELEN, "vnet%d-%s", vnetp->instance,
272563f531d1SSriharsha Basavapatna ifname);
272663f531d1SSriharsha Basavapatna rv = mac_client_open(mh, &mch, client_name, MAC_OPEN_FLAGS_EXCLUSIVE);
272763f531d1SSriharsha Basavapatna if (rv != 0) {
272863f531d1SSriharsha Basavapatna goto fail;
272963f531d1SSriharsha Basavapatna }
273063f531d1SSriharsha Basavapatna vnetp->hio_mch = mch;
273163f531d1SSriharsha Basavapatna
273263f531d1SSriharsha Basavapatna rv = mac_unicast_add(mch, vnetp->curr_macaddr, mac_flags, &muh, 0,
273363f531d1SSriharsha Basavapatna &diag);
273463f531d1SSriharsha Basavapatna if (rv != 0) {
273563f531d1SSriharsha Basavapatna goto fail;
273663f531d1SSriharsha Basavapatna }
273763f531d1SSriharsha Basavapatna vnetp->hio_muh = muh;
273863f531d1SSriharsha Basavapatna
273963f531d1SSriharsha Basavapatna macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
274063f531d1SSriharsha Basavapatna macp->m_driver = vnetp;
274163f531d1SSriharsha Basavapatna macp->m_dip = NULL;
274263f531d1SSriharsha Basavapatna macp->m_src_addr = NULL;
274363f531d1SSriharsha Basavapatna macp->m_callbacks = &vnet_hio_res_callbacks;
274463f531d1SSriharsha Basavapatna macp->m_min_sdu = 0;
274563f531d1SSriharsha Basavapatna macp->m_max_sdu = ETHERMTU;
274663f531d1SSriharsha Basavapatna
274763f531d1SSriharsha Basavapatna rv = vio_net_resource_reg(macp, VIO_NET_RES_HYBRID,
274863f531d1SSriharsha Basavapatna vnetp->curr_macaddr, rem_addr, &vnetp->hio_vhp, &vcb);
274963f531d1SSriharsha Basavapatna if (rv != 0) {
275063f531d1SSriharsha Basavapatna goto fail;
275163f531d1SSriharsha Basavapatna }
275263f531d1SSriharsha Basavapatna mac_free(macp);
275363f531d1SSriharsha Basavapatna
275463f531d1SSriharsha Basavapatna /* add the recv callback */
275563f531d1SSriharsha Basavapatna mac_rx_set(vnetp->hio_mch, vnet_hio_rx_cb, vnetp);
275663f531d1SSriharsha Basavapatna
275763f531d1SSriharsha Basavapatna return (0);
275863f531d1SSriharsha Basavapatna
275963f531d1SSriharsha Basavapatna fail:
276063f531d1SSriharsha Basavapatna mac_free(macp);
276163f531d1SSriharsha Basavapatna vnet_hio_mac_cleanup(vnetp);
276263f531d1SSriharsha Basavapatna return (1);
276363f531d1SSriharsha Basavapatna }
276463f531d1SSriharsha Basavapatna
276563f531d1SSriharsha Basavapatna void
vnet_hio_mac_cleanup(vnet_t * vnetp)276663f531d1SSriharsha Basavapatna vnet_hio_mac_cleanup(vnet_t *vnetp)
276763f531d1SSriharsha Basavapatna {
276863f531d1SSriharsha Basavapatna if (vnetp->hio_vhp != NULL) {
276963f531d1SSriharsha Basavapatna vio_net_resource_unreg(vnetp->hio_vhp);
277063f531d1SSriharsha Basavapatna vnetp->hio_vhp = NULL;
277163f531d1SSriharsha Basavapatna }
277263f531d1SSriharsha Basavapatna
277363f531d1SSriharsha Basavapatna if (vnetp->hio_muh != NULL) {
277407d06da5SSurya Prakki (void) mac_unicast_remove(vnetp->hio_mch, vnetp->hio_muh);
277563f531d1SSriharsha Basavapatna vnetp->hio_muh = NULL;
277663f531d1SSriharsha Basavapatna }
277763f531d1SSriharsha Basavapatna
277863f531d1SSriharsha Basavapatna if (vnetp->hio_mch != NULL) {
277963f531d1SSriharsha Basavapatna mac_client_close(vnetp->hio_mch, 0);
278063f531d1SSriharsha Basavapatna vnetp->hio_mch = NULL;
278163f531d1SSriharsha Basavapatna }
278263f531d1SSriharsha Basavapatna
278363f531d1SSriharsha Basavapatna if (vnetp->hio_mh != NULL) {
278463f531d1SSriharsha Basavapatna mac_close(vnetp->hio_mh);
278563f531d1SSriharsha Basavapatna vnetp->hio_mh = NULL;
278663f531d1SSriharsha Basavapatna }
278763f531d1SSriharsha Basavapatna }
278863f531d1SSriharsha Basavapatna
278963f531d1SSriharsha Basavapatna /* Bind pseudo rings to hwrings */
279063f531d1SSriharsha Basavapatna static int
vnet_bind_hwrings(vnet_t * vnetp)279163f531d1SSriharsha Basavapatna vnet_bind_hwrings(vnet_t *vnetp)
279263f531d1SSriharsha Basavapatna {
279363f531d1SSriharsha Basavapatna mac_ring_handle_t hw_rh[VNET_NUM_HYBRID_RINGS];
279463f531d1SSriharsha Basavapatna mac_perim_handle_t mph1;
279563f531d1SSriharsha Basavapatna vnet_pseudo_rx_group_t *rx_grp;
279663f531d1SSriharsha Basavapatna vnet_pseudo_rx_ring_t *rx_ringp;
279763f531d1SSriharsha Basavapatna vnet_pseudo_tx_group_t *tx_grp;
279863f531d1SSriharsha Basavapatna vnet_pseudo_tx_ring_t *tx_ringp;
279963f531d1SSriharsha Basavapatna int hw_ring_cnt;
280063f531d1SSriharsha Basavapatna int i;
280163f531d1SSriharsha Basavapatna int rv;
280263f531d1SSriharsha Basavapatna
280363f531d1SSriharsha Basavapatna mac_perim_enter_by_mh(vnetp->hio_mh, &mph1);
280463f531d1SSriharsha Basavapatna
280563f531d1SSriharsha Basavapatna /* Get the list of the underlying RX rings. */
280663f531d1SSriharsha Basavapatna hw_ring_cnt = mac_hwrings_get(vnetp->hio_mch, &vnetp->rx_hwgh, hw_rh,
280763f531d1SSriharsha Basavapatna MAC_RING_TYPE_RX);
280863f531d1SSriharsha Basavapatna
280963f531d1SSriharsha Basavapatna /* We expect the the # of hw rx rings to match VNET_NUM_HYBRID_RINGS */
281063f531d1SSriharsha Basavapatna if (hw_ring_cnt != VNET_NUM_HYBRID_RINGS) {
281163f531d1SSriharsha Basavapatna cmn_err(CE_WARN,
281263f531d1SSriharsha Basavapatna "!vnet%d: vnet_bind_hwrings: bad rx hw_ring_cnt(%d)\n",
281363f531d1SSriharsha Basavapatna vnetp->instance, hw_ring_cnt);
281463f531d1SSriharsha Basavapatna goto fail;
281563f531d1SSriharsha Basavapatna }
281663f531d1SSriharsha Basavapatna
281763f531d1SSriharsha Basavapatna if (vnetp->rx_hwgh != NULL) {
281863f531d1SSriharsha Basavapatna /*
281963f531d1SSriharsha Basavapatna * Quiesce the HW ring and the mac srs on the ring. Note
282063f531d1SSriharsha Basavapatna * that the HW ring will be restarted when the pseudo ring
282163f531d1SSriharsha Basavapatna * is started. At that time all the packets will be
282263f531d1SSriharsha Basavapatna * directly passed up to the pseudo RX ring and handled
282363f531d1SSriharsha Basavapatna * by mac srs created over the pseudo RX ring.
282463f531d1SSriharsha Basavapatna */
282563f531d1SSriharsha Basavapatna mac_rx_client_quiesce(vnetp->hio_mch);
282663f531d1SSriharsha Basavapatna mac_srs_perm_quiesce(vnetp->hio_mch, B_TRUE);
282763f531d1SSriharsha Basavapatna }
282863f531d1SSriharsha Basavapatna
282963f531d1SSriharsha Basavapatna /*
283063f531d1SSriharsha Basavapatna * Bind the pseudo rings to the hwrings and start the hwrings.
283163f531d1SSriharsha Basavapatna * Note we don't need to register these with the upper mac, as we have
283263f531d1SSriharsha Basavapatna * statically exported these pseudo rxrings which are reserved for
283363f531d1SSriharsha Basavapatna * rxrings of Hybrid resource.
283463f531d1SSriharsha Basavapatna */
283563f531d1SSriharsha Basavapatna rx_grp = &vnetp->rx_grp[0];
283663f531d1SSriharsha Basavapatna for (i = 0; i < VNET_NUM_HYBRID_RINGS; i++) {
283763f531d1SSriharsha Basavapatna /* Pick the rxrings reserved for Hybrid resource */
283863f531d1SSriharsha Basavapatna rx_ringp = &rx_grp->rings[i + VNET_HYBRID_RXRING_INDEX];
283963f531d1SSriharsha Basavapatna
284063f531d1SSriharsha Basavapatna /* Store the hw ring handle */
284163f531d1SSriharsha Basavapatna rx_ringp->hw_rh = hw_rh[i];
284263f531d1SSriharsha Basavapatna
284363f531d1SSriharsha Basavapatna /* Bind the pseudo ring to the underlying hwring */
284463f531d1SSriharsha Basavapatna mac_hwring_setup(rx_ringp->hw_rh,
28450dc2366fSVenugopal Iyer (mac_resource_handle_t)rx_ringp, NULL);
284663f531d1SSriharsha Basavapatna
284763f531d1SSriharsha Basavapatna /* Start the hwring if needed */
284863f531d1SSriharsha Basavapatna if (rx_ringp->state & VNET_RXRING_STARTED) {
284963f531d1SSriharsha Basavapatna rv = mac_hwring_start(rx_ringp->hw_rh);
285063f531d1SSriharsha Basavapatna if (rv != 0) {
285163f531d1SSriharsha Basavapatna mac_hwring_teardown(rx_ringp->hw_rh);
285263f531d1SSriharsha Basavapatna rx_ringp->hw_rh = NULL;
285363f531d1SSriharsha Basavapatna goto fail;
285463f531d1SSriharsha Basavapatna }
285563f531d1SSriharsha Basavapatna }
285663f531d1SSriharsha Basavapatna }
285763f531d1SSriharsha Basavapatna
285863f531d1SSriharsha Basavapatna /* Get the list of the underlying TX rings. */
285963f531d1SSriharsha Basavapatna hw_ring_cnt = mac_hwrings_get(vnetp->hio_mch, &vnetp->tx_hwgh, hw_rh,
286063f531d1SSriharsha Basavapatna MAC_RING_TYPE_TX);
286163f531d1SSriharsha Basavapatna
286263f531d1SSriharsha Basavapatna /* We expect the # of hw tx rings to match VNET_NUM_HYBRID_RINGS */
286363f531d1SSriharsha Basavapatna if (hw_ring_cnt != VNET_NUM_HYBRID_RINGS) {
286463f531d1SSriharsha Basavapatna cmn_err(CE_WARN,
286563f531d1SSriharsha Basavapatna "!vnet%d: vnet_bind_hwrings: bad tx hw_ring_cnt(%d)\n",
286663f531d1SSriharsha Basavapatna vnetp->instance, hw_ring_cnt);
286763f531d1SSriharsha Basavapatna goto fail;
286863f531d1SSriharsha Basavapatna }
286963f531d1SSriharsha Basavapatna
287063f531d1SSriharsha Basavapatna /*
287163f531d1SSriharsha Basavapatna * Now map the pseudo txrings to the hw txrings. Note we don't need
287263f531d1SSriharsha Basavapatna * to register these with the upper mac, as we have statically exported
287363f531d1SSriharsha Basavapatna * these rings. Note that these rings will continue to be used for LDC
287463f531d1SSriharsha Basavapatna * resources to peer vnets and vswitch (shared ring).
287563f531d1SSriharsha Basavapatna */
287663f531d1SSriharsha Basavapatna tx_grp = &vnetp->tx_grp[0];
287763f531d1SSriharsha Basavapatna for (i = 0; i < tx_grp->ring_cnt; i++) {
287863f531d1SSriharsha Basavapatna tx_ringp = &tx_grp->rings[i];
287963f531d1SSriharsha Basavapatna tx_ringp->hw_rh = hw_rh[i];
288063f531d1SSriharsha Basavapatna tx_ringp->state |= VNET_TXRING_HYBRID;
288163f531d1SSriharsha Basavapatna }
28820dc2366fSVenugopal Iyer tx_grp->tx_notify_handle =
28830dc2366fSVenugopal Iyer mac_client_tx_notify(vnetp->hio_mch, vnet_tx_ring_update, vnetp);
288463f531d1SSriharsha Basavapatna
288563f531d1SSriharsha Basavapatna mac_perim_exit(mph1);
288663f531d1SSriharsha Basavapatna return (0);
288763f531d1SSriharsha Basavapatna
288863f531d1SSriharsha Basavapatna fail:
288963f531d1SSriharsha Basavapatna mac_perim_exit(mph1);
289063f531d1SSriharsha Basavapatna vnet_unbind_hwrings(vnetp);
289163f531d1SSriharsha Basavapatna return (1);
289263f531d1SSriharsha Basavapatna }
289363f531d1SSriharsha Basavapatna
289463f531d1SSriharsha Basavapatna /* Unbind pseudo rings from hwrings */
289563f531d1SSriharsha Basavapatna static void
vnet_unbind_hwrings(vnet_t * vnetp)289663f531d1SSriharsha Basavapatna vnet_unbind_hwrings(vnet_t *vnetp)
289763f531d1SSriharsha Basavapatna {
289863f531d1SSriharsha Basavapatna mac_perim_handle_t mph1;
289963f531d1SSriharsha Basavapatna vnet_pseudo_rx_ring_t *rx_ringp;
290063f531d1SSriharsha Basavapatna vnet_pseudo_rx_group_t *rx_grp;
290163f531d1SSriharsha Basavapatna vnet_pseudo_tx_group_t *tx_grp;
290263f531d1SSriharsha Basavapatna vnet_pseudo_tx_ring_t *tx_ringp;
290363f531d1SSriharsha Basavapatna int i;
290463f531d1SSriharsha Basavapatna
290563f531d1SSriharsha Basavapatna mac_perim_enter_by_mh(vnetp->hio_mh, &mph1);
290663f531d1SSriharsha Basavapatna
290763f531d1SSriharsha Basavapatna tx_grp = &vnetp->tx_grp[0];
290863f531d1SSriharsha Basavapatna for (i = 0; i < VNET_NUM_HYBRID_RINGS; i++) {
290963f531d1SSriharsha Basavapatna tx_ringp = &tx_grp->rings[i];
291063f531d1SSriharsha Basavapatna if (tx_ringp->state & VNET_TXRING_HYBRID) {
291163f531d1SSriharsha Basavapatna tx_ringp->state &= ~VNET_TXRING_HYBRID;
291263f531d1SSriharsha Basavapatna tx_ringp->hw_rh = NULL;
291363f531d1SSriharsha Basavapatna }
291463f531d1SSriharsha Basavapatna }
29150dc2366fSVenugopal Iyer (void) mac_client_tx_notify(vnetp->hio_mch, NULL,
29160dc2366fSVenugopal Iyer tx_grp->tx_notify_handle);
291763f531d1SSriharsha Basavapatna
291863f531d1SSriharsha Basavapatna rx_grp = &vnetp->rx_grp[0];
291963f531d1SSriharsha Basavapatna for (i = 0; i < VNET_NUM_HYBRID_RINGS; i++) {
292063f531d1SSriharsha Basavapatna rx_ringp = &rx_grp->rings[i + VNET_HYBRID_RXRING_INDEX];
292163f531d1SSriharsha Basavapatna if (rx_ringp->hw_rh != NULL) {
292263f531d1SSriharsha Basavapatna /* Stop the hwring */
292363f531d1SSriharsha Basavapatna mac_hwring_stop(rx_ringp->hw_rh);
292463f531d1SSriharsha Basavapatna
292563f531d1SSriharsha Basavapatna /* Teardown the hwring */
292663f531d1SSriharsha Basavapatna mac_hwring_teardown(rx_ringp->hw_rh);
292763f531d1SSriharsha Basavapatna rx_ringp->hw_rh = NULL;
292863f531d1SSriharsha Basavapatna }
292963f531d1SSriharsha Basavapatna }
293063f531d1SSriharsha Basavapatna
293163f531d1SSriharsha Basavapatna if (vnetp->rx_hwgh != NULL) {
293263f531d1SSriharsha Basavapatna vnetp->rx_hwgh = NULL;
293363f531d1SSriharsha Basavapatna /*
293463f531d1SSriharsha Basavapatna * First clear the permanent-quiesced flag of the RX srs then
293563f531d1SSriharsha Basavapatna * restart the HW ring and the mac srs on the ring.
293663f531d1SSriharsha Basavapatna */
293763f531d1SSriharsha Basavapatna mac_srs_perm_quiesce(vnetp->hio_mch, B_FALSE);
293863f531d1SSriharsha Basavapatna mac_rx_client_restart(vnetp->hio_mch);
293963f531d1SSriharsha Basavapatna }
294063f531d1SSriharsha Basavapatna
294163f531d1SSriharsha Basavapatna mac_perim_exit(mph1);
294263f531d1SSriharsha Basavapatna }
294363f531d1SSriharsha Basavapatna
294463f531d1SSriharsha Basavapatna /* Bind pseudo ring to a LDC resource */
294563f531d1SSriharsha Basavapatna static int
vnet_bind_vgenring(vnet_res_t * vresp)294663f531d1SSriharsha Basavapatna vnet_bind_vgenring(vnet_res_t *vresp)
294763f531d1SSriharsha Basavapatna {
294863f531d1SSriharsha Basavapatna vnet_t *vnetp;
294963f531d1SSriharsha Basavapatna vnet_pseudo_rx_group_t *rx_grp;
295063f531d1SSriharsha Basavapatna vnet_pseudo_rx_ring_t *rx_ringp;
295163f531d1SSriharsha Basavapatna mac_perim_handle_t mph1;
295263f531d1SSriharsha Basavapatna int rv;
295363f531d1SSriharsha Basavapatna int type;
295463f531d1SSriharsha Basavapatna
295563f531d1SSriharsha Basavapatna vnetp = vresp->vnetp;
295663f531d1SSriharsha Basavapatna type = vresp->type;
295763f531d1SSriharsha Basavapatna rx_grp = &vnetp->rx_grp[0];
295863f531d1SSriharsha Basavapatna
295963f531d1SSriharsha Basavapatna if (type == VIO_NET_RES_LDC_SERVICE) {
296063f531d1SSriharsha Basavapatna /*
296163f531d1SSriharsha Basavapatna * Ring Index 0 is the default ring in the group and is
296263f531d1SSriharsha Basavapatna * reserved for LDC_SERVICE in vnet_ring_grp_init(). This ring
296363f531d1SSriharsha Basavapatna * is allocated statically and is reported to the mac layer
296463f531d1SSriharsha Basavapatna * in vnet_m_capab(). So, all we need to do here, is save a
296563f531d1SSriharsha Basavapatna * reference to the associated vresp.
296663f531d1SSriharsha Basavapatna */
296763f531d1SSriharsha Basavapatna rx_ringp = &rx_grp->rings[0];
296863f531d1SSriharsha Basavapatna rx_ringp->hw_rh = (mac_ring_handle_t)vresp;
296963f531d1SSriharsha Basavapatna vresp->rx_ringp = (void *)rx_ringp;
297063f531d1SSriharsha Basavapatna return (0);
297163f531d1SSriharsha Basavapatna }
297263f531d1SSriharsha Basavapatna ASSERT(type == VIO_NET_RES_LDC_GUEST);
297363f531d1SSriharsha Basavapatna
297463f531d1SSriharsha Basavapatna mac_perim_enter_by_mh(vnetp->mh, &mph1);
297563f531d1SSriharsha Basavapatna
297663f531d1SSriharsha Basavapatna rx_ringp = vnet_alloc_pseudo_rx_ring(vnetp);
297763f531d1SSriharsha Basavapatna if (rx_ringp == NULL) {
297863f531d1SSriharsha Basavapatna cmn_err(CE_WARN, "!vnet%d: Failed to allocate pseudo rx ring",
297963f531d1SSriharsha Basavapatna vnetp->instance);
298063f531d1SSriharsha Basavapatna goto fail;
298163f531d1SSriharsha Basavapatna }
298263f531d1SSriharsha Basavapatna
298363f531d1SSriharsha Basavapatna /* Store the LDC resource itself as the ring handle */
298463f531d1SSriharsha Basavapatna rx_ringp->hw_rh = (mac_ring_handle_t)vresp;
298563f531d1SSriharsha Basavapatna
298663f531d1SSriharsha Basavapatna /*
298763f531d1SSriharsha Basavapatna * Save a reference to the ring in the resource for lookup during
298863f531d1SSriharsha Basavapatna * unbind. Note this is only done for LDC resources. We don't need this
298963f531d1SSriharsha Basavapatna * in the case of a Hybrid resource (see vnet_bind_hwrings()), as its
299063f531d1SSriharsha Basavapatna * rx rings are mapped to reserved pseudo rx rings (index 1 and 2).
299163f531d1SSriharsha Basavapatna */
299263f531d1SSriharsha Basavapatna vresp->rx_ringp = (void *)rx_ringp;
299363f531d1SSriharsha Basavapatna rx_ringp->state |= VNET_RXRING_LDC_GUEST;
299463f531d1SSriharsha Basavapatna
299563f531d1SSriharsha Basavapatna /* Register the pseudo ring with upper-mac */
299663f531d1SSriharsha Basavapatna rv = mac_group_add_ring(rx_grp->handle, rx_ringp->index);
299763f531d1SSriharsha Basavapatna if (rv != 0) {
299863f531d1SSriharsha Basavapatna rx_ringp->state &= ~VNET_RXRING_LDC_GUEST;
299963f531d1SSriharsha Basavapatna rx_ringp->hw_rh = NULL;
300063f531d1SSriharsha Basavapatna vnet_free_pseudo_rx_ring(vnetp, rx_ringp);
300163f531d1SSriharsha Basavapatna goto fail;
300263f531d1SSriharsha Basavapatna }
300363f531d1SSriharsha Basavapatna
300463f531d1SSriharsha Basavapatna mac_perim_exit(mph1);
300563f531d1SSriharsha Basavapatna return (0);
300663f531d1SSriharsha Basavapatna fail:
300763f531d1SSriharsha Basavapatna mac_perim_exit(mph1);
300863f531d1SSriharsha Basavapatna return (1);
300963f531d1SSriharsha Basavapatna }
301063f531d1SSriharsha Basavapatna
301163f531d1SSriharsha Basavapatna /* Unbind pseudo ring from a LDC resource */
301263f531d1SSriharsha Basavapatna static void
vnet_unbind_vgenring(vnet_res_t * vresp)301363f531d1SSriharsha Basavapatna vnet_unbind_vgenring(vnet_res_t *vresp)
301463f531d1SSriharsha Basavapatna {
301563f531d1SSriharsha Basavapatna vnet_t *vnetp;
301663f531d1SSriharsha Basavapatna vnet_pseudo_rx_group_t *rx_grp;
301763f531d1SSriharsha Basavapatna vnet_pseudo_rx_ring_t *rx_ringp;
301863f531d1SSriharsha Basavapatna mac_perim_handle_t mph1;
301963f531d1SSriharsha Basavapatna int type;
302063f531d1SSriharsha Basavapatna
302163f531d1SSriharsha Basavapatna vnetp = vresp->vnetp;
302263f531d1SSriharsha Basavapatna type = vresp->type;
302363f531d1SSriharsha Basavapatna rx_grp = &vnetp->rx_grp[0];
302463f531d1SSriharsha Basavapatna
302563f531d1SSriharsha Basavapatna if (vresp->rx_ringp == NULL) {
302663f531d1SSriharsha Basavapatna return;
302763f531d1SSriharsha Basavapatna }
302863f531d1SSriharsha Basavapatna
302963f531d1SSriharsha Basavapatna if (type == VIO_NET_RES_LDC_SERVICE) {
303063f531d1SSriharsha Basavapatna /*
303163f531d1SSriharsha Basavapatna * Ring Index 0 is the default ring in the group and is
303263f531d1SSriharsha Basavapatna * reserved for LDC_SERVICE in vnet_ring_grp_init(). This ring
303363f531d1SSriharsha Basavapatna * is allocated statically and is reported to the mac layer
303463f531d1SSriharsha Basavapatna * in vnet_m_capab(). So, all we need to do here, is remove its
303563f531d1SSriharsha Basavapatna * reference to the associated vresp.
303663f531d1SSriharsha Basavapatna */
303763f531d1SSriharsha Basavapatna rx_ringp = &rx_grp->rings[0];
303863f531d1SSriharsha Basavapatna rx_ringp->hw_rh = NULL;
303963f531d1SSriharsha Basavapatna vresp->rx_ringp = NULL;
304063f531d1SSriharsha Basavapatna return;
304163f531d1SSriharsha Basavapatna }
304263f531d1SSriharsha Basavapatna ASSERT(type == VIO_NET_RES_LDC_GUEST);
304363f531d1SSriharsha Basavapatna
304463f531d1SSriharsha Basavapatna mac_perim_enter_by_mh(vnetp->mh, &mph1);
304563f531d1SSriharsha Basavapatna
304663f531d1SSriharsha Basavapatna rx_ringp = (vnet_pseudo_rx_ring_t *)vresp->rx_ringp;
304763f531d1SSriharsha Basavapatna vresp->rx_ringp = NULL;
304863f531d1SSriharsha Basavapatna
304963f531d1SSriharsha Basavapatna if (rx_ringp != NULL && (rx_ringp->state & VNET_RXRING_LDC_GUEST)) {
305063f531d1SSriharsha Basavapatna /* Unregister the pseudo ring with upper-mac */
305163f531d1SSriharsha Basavapatna mac_group_rem_ring(rx_grp->handle, rx_ringp->handle);
305263f531d1SSriharsha Basavapatna
305363f531d1SSriharsha Basavapatna rx_ringp->hw_rh = NULL;
305463f531d1SSriharsha Basavapatna rx_ringp->state &= ~VNET_RXRING_LDC_GUEST;
305563f531d1SSriharsha Basavapatna
305663f531d1SSriharsha Basavapatna /* Free the pseudo rx ring */
305763f531d1SSriharsha Basavapatna vnet_free_pseudo_rx_ring(vnetp, rx_ringp);
305863f531d1SSriharsha Basavapatna }
305963f531d1SSriharsha Basavapatna
306063f531d1SSriharsha Basavapatna mac_perim_exit(mph1);
306163f531d1SSriharsha Basavapatna }
306263f531d1SSriharsha Basavapatna
306363f531d1SSriharsha Basavapatna static void
vnet_unbind_rings(vnet_res_t * vresp)306463f531d1SSriharsha Basavapatna vnet_unbind_rings(vnet_res_t *vresp)
306563f531d1SSriharsha Basavapatna {
306663f531d1SSriharsha Basavapatna switch (vresp->type) {
306763f531d1SSriharsha Basavapatna
306863f531d1SSriharsha Basavapatna case VIO_NET_RES_LDC_SERVICE:
306963f531d1SSriharsha Basavapatna case VIO_NET_RES_LDC_GUEST:
307063f531d1SSriharsha Basavapatna vnet_unbind_vgenring(vresp);
307163f531d1SSriharsha Basavapatna break;
307263f531d1SSriharsha Basavapatna
307363f531d1SSriharsha Basavapatna case VIO_NET_RES_HYBRID:
307463f531d1SSriharsha Basavapatna vnet_unbind_hwrings(vresp->vnetp);
307563f531d1SSriharsha Basavapatna break;
307663f531d1SSriharsha Basavapatna
307763f531d1SSriharsha Basavapatna default:
307863f531d1SSriharsha Basavapatna break;
307963f531d1SSriharsha Basavapatna
308063f531d1SSriharsha Basavapatna }
308163f531d1SSriharsha Basavapatna }
308263f531d1SSriharsha Basavapatna
308363f531d1SSriharsha Basavapatna static int
vnet_bind_rings(vnet_res_t * vresp)308463f531d1SSriharsha Basavapatna vnet_bind_rings(vnet_res_t *vresp)
308563f531d1SSriharsha Basavapatna {
308663f531d1SSriharsha Basavapatna int rv;
308763f531d1SSriharsha Basavapatna
308863f531d1SSriharsha Basavapatna switch (vresp->type) {
308963f531d1SSriharsha Basavapatna
309063f531d1SSriharsha Basavapatna case VIO_NET_RES_LDC_SERVICE:
309163f531d1SSriharsha Basavapatna case VIO_NET_RES_LDC_GUEST:
309263f531d1SSriharsha Basavapatna rv = vnet_bind_vgenring(vresp);
309363f531d1SSriharsha Basavapatna break;
309463f531d1SSriharsha Basavapatna
309563f531d1SSriharsha Basavapatna case VIO_NET_RES_HYBRID:
309663f531d1SSriharsha Basavapatna rv = vnet_bind_hwrings(vresp->vnetp);
309763f531d1SSriharsha Basavapatna break;
309863f531d1SSriharsha Basavapatna
309963f531d1SSriharsha Basavapatna default:
310063f531d1SSriharsha Basavapatna rv = 1;
310163f531d1SSriharsha Basavapatna break;
310263f531d1SSriharsha Basavapatna
310363f531d1SSriharsha Basavapatna }
310463f531d1SSriharsha Basavapatna
310563f531d1SSriharsha Basavapatna return (rv);
310663f531d1SSriharsha Basavapatna }
310763f531d1SSriharsha Basavapatna
310863f531d1SSriharsha Basavapatna /* ARGSUSED */
310963f531d1SSriharsha Basavapatna int
vnet_hio_stat(void * arg,uint_t stat,uint64_t * val)311063f531d1SSriharsha Basavapatna vnet_hio_stat(void *arg, uint_t stat, uint64_t *val)
311163f531d1SSriharsha Basavapatna {
311263f531d1SSriharsha Basavapatna vnet_t *vnetp = (vnet_t *)arg;
311363f531d1SSriharsha Basavapatna
311463f531d1SSriharsha Basavapatna *val = mac_stat_get(vnetp->hio_mh, stat);
311563f531d1SSriharsha Basavapatna return (0);
311663f531d1SSriharsha Basavapatna }
311763f531d1SSriharsha Basavapatna
311863f531d1SSriharsha Basavapatna /*
311963f531d1SSriharsha Basavapatna * The start() and stop() routines for the Hybrid resource below, are just
312063f531d1SSriharsha Basavapatna * dummy functions. This is provided to avoid resource type specific code in
312163f531d1SSriharsha Basavapatna * vnet_start_resources() and vnet_stop_resources(). The starting and stopping
312263f531d1SSriharsha Basavapatna * of the Hybrid resource happens in the context of the mac_client interfaces
312363f531d1SSriharsha Basavapatna * that are invoked in vnet_hio_mac_init() and vnet_hio_mac_cleanup().
312463f531d1SSriharsha Basavapatna */
312563f531d1SSriharsha Basavapatna /* ARGSUSED */
312663f531d1SSriharsha Basavapatna static int
vnet_hio_start(void * arg)312763f531d1SSriharsha Basavapatna vnet_hio_start(void *arg)
312863f531d1SSriharsha Basavapatna {
312963f531d1SSriharsha Basavapatna return (0);
313063f531d1SSriharsha Basavapatna }
313163f531d1SSriharsha Basavapatna
313263f531d1SSriharsha Basavapatna /* ARGSUSED */
313363f531d1SSriharsha Basavapatna static void
vnet_hio_stop(void * arg)313463f531d1SSriharsha Basavapatna vnet_hio_stop(void *arg)
313563f531d1SSriharsha Basavapatna {
313663f531d1SSriharsha Basavapatna }
313763f531d1SSriharsha Basavapatna
313863f531d1SSriharsha Basavapatna mblk_t *
vnet_hio_tx(void * arg,mblk_t * mp)313963f531d1SSriharsha Basavapatna vnet_hio_tx(void *arg, mblk_t *mp)
314063f531d1SSriharsha Basavapatna {
314163f531d1SSriharsha Basavapatna vnet_pseudo_tx_ring_t *tx_ringp;
314263f531d1SSriharsha Basavapatna mblk_t *nextp;
314363f531d1SSriharsha Basavapatna mblk_t *ret_mp;
314463f531d1SSriharsha Basavapatna
314563f531d1SSriharsha Basavapatna tx_ringp = (vnet_pseudo_tx_ring_t *)arg;
314663f531d1SSriharsha Basavapatna for (;;) {
314763f531d1SSriharsha Basavapatna nextp = mp->b_next;
314863f531d1SSriharsha Basavapatna mp->b_next = NULL;
314963f531d1SSriharsha Basavapatna
315063f531d1SSriharsha Basavapatna ret_mp = mac_hwring_tx(tx_ringp->hw_rh, mp);
315163f531d1SSriharsha Basavapatna if (ret_mp != NULL) {
315263f531d1SSriharsha Basavapatna ret_mp->b_next = nextp;
315363f531d1SSriharsha Basavapatna mp = ret_mp;
315463f531d1SSriharsha Basavapatna break;
315563f531d1SSriharsha Basavapatna }
315663f531d1SSriharsha Basavapatna
315763f531d1SSriharsha Basavapatna if ((mp = nextp) == NULL)
315863f531d1SSriharsha Basavapatna break;
315963f531d1SSriharsha Basavapatna }
316063f531d1SSriharsha Basavapatna return (mp);
316163f531d1SSriharsha Basavapatna }
316263f531d1SSriharsha Basavapatna
31631107ea93SSriharsha Basavapatna #ifdef VNET_IOC_DEBUG
31641107ea93SSriharsha Basavapatna
31651107ea93SSriharsha Basavapatna /*
31661107ea93SSriharsha Basavapatna * The ioctl entry point is used only for debugging for now. The ioctl commands
31671107ea93SSriharsha Basavapatna * can be used to force the link state of the channel connected to vsw.
31681107ea93SSriharsha Basavapatna */
31691107ea93SSriharsha Basavapatna static void
vnet_m_ioctl(void * arg,queue_t * q,mblk_t * mp)31701107ea93SSriharsha Basavapatna vnet_m_ioctl(void *arg, queue_t *q, mblk_t *mp)
31711107ea93SSriharsha Basavapatna {
31721107ea93SSriharsha Basavapatna struct iocblk *iocp;
31731107ea93SSriharsha Basavapatna vnet_t *vnetp;
31741107ea93SSriharsha Basavapatna
31751107ea93SSriharsha Basavapatna iocp = (struct iocblk *)(uintptr_t)mp->b_rptr;
31761107ea93SSriharsha Basavapatna iocp->ioc_error = 0;
31771107ea93SSriharsha Basavapatna vnetp = (vnet_t *)arg;
31781107ea93SSriharsha Basavapatna
31791107ea93SSriharsha Basavapatna if (vnetp == NULL) {
31801107ea93SSriharsha Basavapatna miocnak(q, mp, 0, EINVAL);
31811107ea93SSriharsha Basavapatna return;
31821107ea93SSriharsha Basavapatna }
31831107ea93SSriharsha Basavapatna
31841107ea93SSriharsha Basavapatna switch (iocp->ioc_cmd) {
31851107ea93SSriharsha Basavapatna
31861107ea93SSriharsha Basavapatna case VNET_FORCE_LINK_DOWN:
31871107ea93SSriharsha Basavapatna case VNET_FORCE_LINK_UP:
31881107ea93SSriharsha Basavapatna vnet_force_link_state(vnetp, q, mp);
31891107ea93SSriharsha Basavapatna break;
31901107ea93SSriharsha Basavapatna
31911107ea93SSriharsha Basavapatna default:
31921107ea93SSriharsha Basavapatna iocp->ioc_error = EINVAL;
31931107ea93SSriharsha Basavapatna miocnak(q, mp, 0, iocp->ioc_error);
31941107ea93SSriharsha Basavapatna break;
31951107ea93SSriharsha Basavapatna
31961107ea93SSriharsha Basavapatna }
31971107ea93SSriharsha Basavapatna }
31981107ea93SSriharsha Basavapatna
31991107ea93SSriharsha Basavapatna static void
vnet_force_link_state(vnet_t * vnetp,queue_t * q,mblk_t * mp)32001107ea93SSriharsha Basavapatna vnet_force_link_state(vnet_t *vnetp, queue_t *q, mblk_t *mp)
32011107ea93SSriharsha Basavapatna {
32021107ea93SSriharsha Basavapatna mac_register_t *macp;
32031107ea93SSriharsha Basavapatna mac_callbacks_t *cbp;
32041107ea93SSriharsha Basavapatna vnet_res_t *vresp;
32051107ea93SSriharsha Basavapatna
32061107ea93SSriharsha Basavapatna READ_ENTER(&vnetp->vsw_fp_rw);
32071107ea93SSriharsha Basavapatna
32081107ea93SSriharsha Basavapatna vresp = vnetp->vsw_fp;
32091107ea93SSriharsha Basavapatna if (vresp == NULL) {
32101107ea93SSriharsha Basavapatna RW_EXIT(&vnetp->vsw_fp_rw);
32111107ea93SSriharsha Basavapatna return;
32121107ea93SSriharsha Basavapatna }
32131107ea93SSriharsha Basavapatna
32141107ea93SSriharsha Basavapatna macp = &vresp->macreg;
32151107ea93SSriharsha Basavapatna cbp = macp->m_callbacks;
32161107ea93SSriharsha Basavapatna cbp->mc_ioctl(macp->m_driver, q, mp);
32171107ea93SSriharsha Basavapatna
32181107ea93SSriharsha Basavapatna RW_EXIT(&vnetp->vsw_fp_rw);
32191107ea93SSriharsha Basavapatna }
32201107ea93SSriharsha Basavapatna
32211107ea93SSriharsha Basavapatna #else
32221107ea93SSriharsha Basavapatna
32231107ea93SSriharsha Basavapatna static void
vnet_m_ioctl(void * arg,queue_t * q,mblk_t * mp)32241107ea93SSriharsha Basavapatna vnet_m_ioctl(void *arg, queue_t *q, mblk_t *mp)
32251107ea93SSriharsha Basavapatna {
32261107ea93SSriharsha Basavapatna vnet_t *vnetp;
32271107ea93SSriharsha Basavapatna
32281107ea93SSriharsha Basavapatna vnetp = (vnet_t *)arg;
32291107ea93SSriharsha Basavapatna
32301107ea93SSriharsha Basavapatna if (vnetp == NULL) {
32311107ea93SSriharsha Basavapatna miocnak(q, mp, 0, EINVAL);
32321107ea93SSriharsha Basavapatna return;
32331107ea93SSriharsha Basavapatna }
32341107ea93SSriharsha Basavapatna
32351107ea93SSriharsha Basavapatna /* ioctl support only for debugging */
32361107ea93SSriharsha Basavapatna miocnak(q, mp, 0, ENOTSUP);
32371107ea93SSriharsha Basavapatna }
32381107ea93SSriharsha Basavapatna
32391107ea93SSriharsha Basavapatna #endif
3240