vnet_gen.c revision 0dc2366f7b9f9f36e10909b1e95edbf2a261c2ac
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * CDDL HEADER START
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo *
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * The contents of this file are subject to the terms of the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Common Development and Distribution License (the "License").
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * You may not use this file except in compliance with the License.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo *
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * or http://www.opensolaris.org/os/licensing.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * See the License for the specific language governing permissions
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * and limitations under the License.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo *
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * When distributing Covered Code, include this CDDL HEADER in each
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If applicable, add the following below this CDDL HEADER, with the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * fields enclosed by brackets "[]" replaced with your own identifying
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * information: Portions Copyright [yyyy] [name of copyright owner]
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo *
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * CDDL HEADER END
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/*
0c4606f05172c66c6c65847c0f940871a0ea1c15WENTAO YANG * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Use is subject to license terms.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/types.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/errno.h>
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna#include <sys/sysmacros.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/param.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/stream.h>
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram#include <sys/strsubr.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/kmem.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/conf.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/devops.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/ksynch.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/stat.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/modctl.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/debug.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/ethernet.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/ddi.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/sunddi.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/strsun.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/note.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <sys/mac_provider.h>
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb#include <sys/mac_ether.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/ldc.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/mach_descrip.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/mdeg.h>
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram#include <net/if.h>
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram#include <sys/vnet.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/vio_mailbox.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/vio_common.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/vnet_common.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/vnet_mailbox.h>
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan#include <sys/vio_util.h>
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan#include <sys/vnet_gen.h>
f0ca1d9a12d54d304791bc74525e2010ca924726sb#include <sys/atomic.h>
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram#include <sys/callb.h>
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram#include <sys/sdt.h>
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram#include <sys/intr.h>
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram#include <sys/pattr.h>
c1c61f44e88f4c8c155272ee56d868043146096asb#include <sys/vlan.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Implementation of the mac functionality for vnet using the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * generic(default) transport layer of sun4v Logical Domain Channels(LDC).
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Function prototypes.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* vgen proxy entry points */
678453a8ed49104d8adad58f3ba591bdc39883e8speerint vgen_init(void *vnetp, uint64_t regprop, dev_info_t *vnetdip,
678453a8ed49104d8adad58f3ba591bdc39883e8speer const uint8_t *macaddr, void **vgenhdl);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatnaint vgen_init_mdeg(void *arg);
3ab636deaa8cd06b5153d9eb3eaf79808afb491cWENTAO YANGvoid vgen_uninit(void *arg);
678453a8ed49104d8adad58f3ba591bdc39883e8speerint vgen_dds_tx(void *arg, void *dmsg);
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANGvoid vgen_mod_init(void);
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANGint vgen_mod_cleanup(void);
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANGvoid vgen_mod_fini(void);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatnaint vgen_enable_intr(void *arg);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatnaint vgen_disable_intr(void *arg);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatnamblk_t *vgen_poll(void *arg, int bytes_to_pickup);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_start(void *arg);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void vgen_stop(void *arg);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic mblk_t *vgen_tx(void *arg, mblk_t *mp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_multicst(void *arg, boolean_t add,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo const uint8_t *mca);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_promisc(void *arg, boolean_t on);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_unicst(void *arg, const uint8_t *mca);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebstatic int vgen_stat(void *arg, uint_t stat, uint64_t *val);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnastatic void vgen_ioctl(void *arg, queue_t *q, mblk_t *mp);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna#ifdef VNET_IOC_DEBUG
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnastatic int vgen_force_link_state(vgen_port_t *portp, int link_state);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna#endif
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* vgen internal functions */
c1c61f44e88f4c8c155272ee56d868043146096asbstatic int vgen_read_mdprops(vgen_t *vgenp);
c1c61f44e88f4c8c155272ee56d868043146096asbstatic void vgen_update_md_prop(vgen_t *vgenp, md_t *mdp, mde_cookie_t mdex);
c1c61f44e88f4c8c155272ee56d868043146096asbstatic void vgen_read_pri_eth_types(vgen_t *vgenp, md_t *mdp,
c1c61f44e88f4c8c155272ee56d868043146096asb mde_cookie_t node);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatnastatic void vgen_mtu_read(vgen_t *vgenp, md_t *mdp, mde_cookie_t node,
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna uint32_t *mtu);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnastatic void vgen_linkprop_read(vgen_t *vgenp, md_t *mdp, mde_cookie_t node,
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna boolean_t *pls);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void vgen_detach_ports(vgen_t *vgenp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void vgen_port_detach(vgen_port_t *portp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void vgen_port_list_insert(vgen_port_t *portp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void vgen_port_list_remove(vgen_port_t *portp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic vgen_port_t *vgen_port_lookup(vgen_portlist_t *plistp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int port_num);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_mdeg_reg(vgen_t *vgenp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void vgen_mdeg_unreg(vgen_t *vgenp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_mdeg_cb(void *cb_argp, mdeg_result_t *resp);
c1c61f44e88f4c8c155272ee56d868043146096asbstatic int vgen_mdeg_port_cb(void *cb_argp, mdeg_result_t *resp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_add_port(vgen_t *vgenp, md_t *mdp, mde_cookie_t mdex);
c1c61f44e88f4c8c155272ee56d868043146096asbstatic int vgen_port_read_props(vgen_port_t *portp, vgen_t *vgenp, md_t *mdp,
c1c61f44e88f4c8c155272ee56d868043146096asb mde_cookie_t mdex);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_remove_port(vgen_t *vgenp, md_t *mdp, mde_cookie_t mdex);
c1c61f44e88f4c8c155272ee56d868043146096asbstatic int vgen_port_attach(vgen_port_t *portp);
c1c61f44e88f4c8c155272ee56d868043146096asbstatic void vgen_port_detach_mdeg(vgen_port_t *portp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_update_port(vgen_t *vgenp, md_t *curr_mdp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mde_cookie_t curr_mdex, md_t *prev_mdp, mde_cookie_t prev_mdex);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebstatic uint64_t vgen_port_stat(vgen_port_t *portp, uint_t stat);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnastatic void vgen_port_reset(vgen_port_t *portp);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnastatic void vgen_reset_vsw_port(vgen_t *vgenp);
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANGstatic void vgen_ldc_reset(vgen_ldc_t *ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_ldc_attach(vgen_port_t *portp, uint64_t ldc_id);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void vgen_ldc_detach(vgen_ldc_t *ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_alloc_tx_ring(vgen_ldc_t *ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void vgen_free_tx_ring(vgen_ldc_t *ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void vgen_init_ports(vgen_t *vgenp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void vgen_port_init(vgen_port_t *portp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void vgen_uninit_ports(vgen_t *vgenp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void vgen_port_uninit(vgen_port_t *portp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void vgen_init_ldcs(vgen_port_t *portp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void vgen_uninit_ldcs(vgen_port_t *portp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_ldc_init(vgen_ldc_t *ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void vgen_ldc_uninit(vgen_ldc_t *ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_init_tbufs(vgen_ldc_t *ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void vgen_uninit_tbufs(vgen_ldc_t *ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void vgen_clobber_tbufs(vgen_ldc_t *ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void vgen_clobber_rxds(vgen_ldc_t *ldcp);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebstatic uint64_t vgen_ldc_stat(vgen_ldc_t *ldcp, uint_t stat);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic uint_t vgen_ldc_cb(uint64_t event, caddr_t arg);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_portsend(vgen_port_t *portp, mblk_t *mp);
f0ca1d9a12d54d304791bc74525e2010ca924726sbstatic int vgen_ldcsend(void *arg, mblk_t *mp);
f0ca1d9a12d54d304791bc74525e2010ca924726sbstatic void vgen_ldcsend_pkt(void *arg, mblk_t *mp);
f0ca1d9a12d54d304791bc74525e2010ca924726sbstatic int vgen_ldcsend_dring(void *arg, mblk_t *mp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void vgen_reclaim(vgen_ldc_t *ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void vgen_reclaim_dring(vgen_ldc_t *ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_num_txpending(vgen_ldc_t *ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_tx_dring_full(vgen_ldc_t *ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_ldc_txtimeout(vgen_ldc_t *ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void vgen_ldc_watchdog(void *arg);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatnastatic mblk_t *vgen_ldc_poll(vgen_ldc_t *ldcp, int bytes_to_pickup);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* vgen handshake functions */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic vgen_ldc_t *vh_nextphase(vgen_ldc_t *ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_sendmsg(vgen_ldc_t *ldcp, caddr_t msg, size_t msglen,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo boolean_t caller_holds_lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_send_version_negotiate(vgen_ldc_t *ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_send_attr_info(vgen_ldc_t *ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_send_dring_reg(vgen_ldc_t *ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_send_rdx_info(vgen_ldc_t *ldcp);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayanstatic int vgen_send_dring_data(vgen_ldc_t *ldcp, uint32_t start, int32_t end);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_send_mcast_info(vgen_ldc_t *ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_handshake_phase2(vgen_ldc_t *ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void vgen_handshake_reset(vgen_ldc_t *ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void vgen_reset_hphase(vgen_ldc_t *ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void vgen_handshake(vgen_ldc_t *ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_handshake_done(vgen_ldc_t *ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void vgen_handshake_retry(vgen_ldc_t *ldcp);
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic int vgen_handle_version_negotiate(vgen_ldc_t *ldcp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vio_msg_tag_t *tagp);
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic int vgen_handle_attr_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic int vgen_handle_dring_reg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic int vgen_handle_rdx_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic int vgen_handle_mcast_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic int vgen_handle_ctrlmsg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
f0ca1d9a12d54d304791bc74525e2010ca924726sbstatic void vgen_handle_pkt_data_nop(void *arg1, void *arg2, uint32_t msglen);
f0ca1d9a12d54d304791bc74525e2010ca924726sbstatic void vgen_handle_pkt_data(void *arg1, void *arg2, uint32_t msglen);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramstatic int vgen_handle_dring_data(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramstatic int vgen_handle_dring_data_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramstatic int vgen_process_dring_data(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramstatic int vgen_handle_dring_data_ack(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramstatic int vgen_handle_dring_data_nack(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic int vgen_send_dring_ack(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp,
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan uint32_t start, int32_t end, uint8_t pstate);
f0ca1d9a12d54d304791bc74525e2010ca924726sbstatic int vgen_handle_datamsg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp,
f0ca1d9a12d54d304791bc74525e2010ca924726sb uint32_t msglen);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void vgen_handle_errmsg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
678453a8ed49104d8adad58f3ba591bdc39883e8speerstatic void vgen_handle_evt_up(vgen_ldc_t *ldcp);
678453a8ed49104d8adad58f3ba591bdc39883e8speerstatic void vgen_handle_evt_reset(vgen_ldc_t *ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_check_sid(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
f0ca1d9a12d54d304791bc74525e2010ca924726sbstatic int vgen_check_datamsg_seq(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic caddr_t vgen_print_ethaddr(uint8_t *a, char *ebuf);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void vgen_hwatchdog(void *arg);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void vgen_print_attr_info(vgen_ldc_t *ldcp, int endpoint);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void vgen_print_hparams(vgen_hparams_t *hp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void vgen_print_ldcinfo(vgen_ldc_t *ldcp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramstatic void vgen_stop_rcv_thread(vgen_ldc_t *ldcp);
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatnastatic void vgen_drain_rcv_thread(vgen_ldc_t *ldcp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramstatic void vgen_ldc_rcv_worker(void *arg);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramstatic void vgen_handle_evt_read(vgen_ldc_t *ldcp);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatnastatic void vgen_rx(vgen_ldc_t *ldcp, mblk_t *bp, mblk_t *bpt);
f0ca1d9a12d54d304791bc74525e2010ca924726sbstatic void vgen_set_vnet_proto_ops(vgen_ldc_t *ldcp);
f0ca1d9a12d54d304791bc74525e2010ca924726sbstatic void vgen_reset_vnet_proto_ops(vgen_ldc_t *ldcp);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnastatic void vgen_link_update(vgen_t *vgenp, link_state_t link_state);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
c1c61f44e88f4c8c155272ee56d868043146096asb/* VLAN routines */
c1c61f44e88f4c8c155272ee56d868043146096asbstatic void vgen_vlan_read_ids(void *arg, int type, md_t *mdp,
c1c61f44e88f4c8c155272ee56d868043146096asb mde_cookie_t node, uint16_t *pvidp, uint16_t **vidspp,
c1c61f44e88f4c8c155272ee56d868043146096asb uint16_t *nvidsp, uint16_t *default_idp);
c1c61f44e88f4c8c155272ee56d868043146096asbstatic void vgen_vlan_create_hash(vgen_port_t *portp);
c1c61f44e88f4c8c155272ee56d868043146096asbstatic void vgen_vlan_destroy_hash(vgen_port_t *portp);
c1c61f44e88f4c8c155272ee56d868043146096asbstatic void vgen_vlan_add_ids(vgen_port_t *portp);
c1c61f44e88f4c8c155272ee56d868043146096asbstatic void vgen_vlan_remove_ids(vgen_port_t *portp);
c1c61f44e88f4c8c155272ee56d868043146096asbstatic boolean_t vgen_vlan_lookup(mod_hash_t *vlan_hashp, uint16_t vid);
c1c61f44e88f4c8c155272ee56d868043146096asbstatic boolean_t vgen_frame_lookup_vid(vnet_t *vnetp, struct ether_header *ehp,
c1c61f44e88f4c8c155272ee56d868043146096asb uint16_t *vidp);
c1c61f44e88f4c8c155272ee56d868043146096asbstatic mblk_t *vgen_vlan_frame_fixtag(vgen_port_t *portp, mblk_t *mp,
c1c61f44e88f4c8c155272ee56d868043146096asb boolean_t is_tagged, uint16_t vid);
c1c61f44e88f4c8c155272ee56d868043146096asbstatic void vgen_vlan_unaware_port_reset(vgen_port_t *portp);
c1c61f44e88f4c8c155272ee56d868043146096asbstatic void vgen_reset_vlan_unaware_ports(vgen_t *vgenp);
678453a8ed49104d8adad58f3ba591bdc39883e8speerstatic int vgen_dds_rx(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer/* externs */
678453a8ed49104d8adad58f3ba591bdc39883e8speerextern void vnet_dds_rx(void *arg, void *dmsg);
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANGextern void vnet_dds_cleanup_hio(vnet_t *vnetp);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatnaextern int vnet_mtu_update(vnet_t *vnetp, uint32_t mtu);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnaextern void vnet_link_update(vnet_t *vnetp, link_state_t link_state);
c1c61f44e88f4c8c155272ee56d868043146096asb
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * The handshake process consists of 5 phases defined below, with VH_PHASE0
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * being the pre-handshake phase and VH_DONE is the phase to indicate
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * successful completion of all phases.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Each phase may have one to several handshake states which are required
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * to complete successfully to move to the next phase.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Refer to the functions vgen_handshake() and vgen_handshake_done() for
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * more details.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* handshake phases */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoenum { VH_PHASE0, VH_PHASE1, VH_PHASE2, VH_PHASE3, VH_DONE = 0x80 };
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* handshake states */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoenum {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo VER_INFO_SENT = 0x1,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo VER_ACK_RCVD = 0x2,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo VER_INFO_RCVD = 0x4,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo VER_ACK_SENT = 0x8,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo VER_NEGOTIATED = (VER_ACK_RCVD | VER_ACK_SENT),
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ATTR_INFO_SENT = 0x10,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ATTR_ACK_RCVD = 0x20,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ATTR_INFO_RCVD = 0x40,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ATTR_ACK_SENT = 0x80,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ATTR_INFO_EXCHANGED = (ATTR_ACK_RCVD | ATTR_ACK_SENT),
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DRING_INFO_SENT = 0x100,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DRING_ACK_RCVD = 0x200,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DRING_INFO_RCVD = 0x400,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DRING_ACK_SENT = 0x800,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DRING_INFO_EXCHANGED = (DRING_ACK_RCVD | DRING_ACK_SENT),
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo RDX_INFO_SENT = 0x1000,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo RDX_ACK_RCVD = 0x2000,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo RDX_INFO_RCVD = 0x4000,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo RDX_ACK_SENT = 0x8000,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo RDX_EXCHANGED = (RDX_ACK_RCVD | RDX_ACK_SENT)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo};
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
f0ca1d9a12d54d304791bc74525e2010ca924726sb#define VGEN_PRI_ETH_DEFINED(vgenp) ((vgenp)->pri_num_types != 0)
f0ca1d9a12d54d304791bc74525e2010ca924726sb
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#define LDC_LOCK(ldcp) \
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_enter(&((ldcp)->cblock));\
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_enter(&((ldcp)->rxlock));\
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_enter(&((ldcp)->wrlock));\
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_enter(&((ldcp)->txlock));\
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_enter(&((ldcp)->tclock));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#define LDC_UNLOCK(ldcp) \
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&((ldcp)->tclock));\
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&((ldcp)->txlock));\
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_exit(&((ldcp)->wrlock));\
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_exit(&((ldcp)->rxlock));\
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&((ldcp)->cblock));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
c1c61f44e88f4c8c155272ee56d868043146096asb#define VGEN_VER_EQ(ldcp, major, minor) \
c1c61f44e88f4c8c155272ee56d868043146096asb ((ldcp)->local_hparams.ver_major == (major) && \
c1c61f44e88f4c8c155272ee56d868043146096asb (ldcp)->local_hparams.ver_minor == (minor))
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb#define VGEN_VER_LT(ldcp, major, minor) \
c1c61f44e88f4c8c155272ee56d868043146096asb (((ldcp)->local_hparams.ver_major < (major)) || \
c1c61f44e88f4c8c155272ee56d868043146096asb ((ldcp)->local_hparams.ver_major == (major) && \
c1c61f44e88f4c8c155272ee56d868043146096asb (ldcp)->local_hparams.ver_minor < (minor)))
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb#define VGEN_VER_GTEQ(ldcp, major, minor) \
c1c61f44e88f4c8c155272ee56d868043146096asb (((ldcp)->local_hparams.ver_major > (major)) || \
c1c61f44e88f4c8c155272ee56d868043146096asb ((ldcp)->local_hparams.ver_major == (major) && \
c1c61f44e88f4c8c155272ee56d868043146096asb (ldcp)->local_hparams.ver_minor >= (minor)))
c1c61f44e88f4c8c155272ee56d868043146096asb
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic struct ether_addr etherbroadcastaddr = {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo};
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * MIB II broadcast/multicast packets
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#define IS_BROADCAST(ehp) \
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (ether_cmp(&ehp->ether_dhost, &etherbroadcastaddr) == 0)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#define IS_MULTICAST(ehp) \
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ((ehp->ether_dhost.ether_addr_octet[0] & 01) == 1)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Property names
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic char macaddr_propname[] = "mac-address";
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic char rmacaddr_propname[] = "remote-mac-address";
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic char channel_propname[] = "channel-endpoint";
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic char reg_propname[] = "reg";
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic char port_propname[] = "port";
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic char swport_propname[] = "switch-port";
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic char id_propname[] = "id";
f0ca1d9a12d54d304791bc74525e2010ca924726sbstatic char vdev_propname[] = "virtual-device";
f0ca1d9a12d54d304791bc74525e2010ca924726sbstatic char vnet_propname[] = "network";
f0ca1d9a12d54d304791bc74525e2010ca924726sbstatic char pri_types_propname[] = "priority-ether-types";
c1c61f44e88f4c8c155272ee56d868043146096asbstatic char vgen_pvid_propname[] = "port-vlan-id";
c1c61f44e88f4c8c155272ee56d868043146096asbstatic char vgen_vid_propname[] = "vlan-id";
c1c61f44e88f4c8c155272ee56d868043146096asbstatic char vgen_dvid_propname[] = "default-vlan-id";
c1c61f44e88f4c8c155272ee56d868043146096asbstatic char port_pvid_propname[] = "remote-port-vlan-id";
c1c61f44e88f4c8c155272ee56d868043146096asbstatic char port_vid_propname[] = "remote-vlan-id";
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatnastatic char vgen_mtu_propname[] = "mtu";
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnastatic char vgen_linkprop_propname[] = "linkprop";
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna/*
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * VIO Protocol Version Info:
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna *
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * The version specified below represents the version of protocol currently
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * supported in the driver. It means the driver can negotiate with peers with
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * versions <= this version. Here is a summary of the feature(s) that are
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * supported at each version of the protocol:
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna *
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * 1.0 Basic VIO protocol.
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * 1.1 vDisk protocol update (no virtual network update).
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * 1.2 Support for priority frames (priority-ether-types).
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * 1.3 VLAN and HybridIO support.
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * 1.4 Jumbo Frame support.
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * 1.5 Link State Notification support with optional support
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * for Physical Link information.
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnastatic vgen_ver_t vgen_versions[VGEN_NUM_VER] = { {1, 5} };
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* Tunables */
19b65a69adc64b3289ccb2fc32b805782e3f4540sbuint32_t vgen_hwd_interval = 5; /* handshake watchdog freq in sec */
445b4c2ed2d52ef648ae6b36e4f5e14ff3d234afsbuint32_t vgen_max_hretries = VNET_NUM_HANDSHAKES; /* # of handshake retries */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppouint32_t vgen_ldcwr_retries = 10; /* max # of ldc_write() retries */
8e6a2a040587479821d1e682a28bcef7e75f19a6lmuint32_t vgen_ldcup_retries = 5; /* max # of ldc_up() retries */
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatnauint32_t vgen_ldccl_retries = 5; /* max # of ldc_close() retries */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayanuint32_t vgen_recv_delay = 1; /* delay when rx descr not ready */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayanuint32_t vgen_recv_retries = 10; /* retry when rx descr not ready */
61a70d81555b002d961400e93b444d97fc467f13raghuramuint32_t vgen_tx_retries = 0x4; /* retry when tx descr not available */
61a70d81555b002d961400e93b444d97fc467f13raghuramuint32_t vgen_tx_delay = 0x30; /* delay when tx descr not available */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramint vgen_rcv_thread_enabled = 1; /* Enable Recieve thread */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANGstatic vio_mblk_pool_t *vgen_rx_poolp = NULL;
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANGstatic krwlock_t vgen_rw;
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram/*
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * max # of packets accumulated prior to sending them up. It is best
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * to keep this at 60% of the number of recieve buffers.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramuint32_t vgen_chain_len = (VGEN_NRBUFS * 0.6);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram/*
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * Internal tunables for receive buffer pools, that is, the size and number of
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * mblks for each pool. At least 3 sizes must be specified if these are used.
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * The sizes must be specified in increasing order. Non-zero value of the first
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * size will be used as a hint to use these values instead of the algorithm
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * that determines the sizes based on MTU.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatnauint32_t vgen_rbufsz1 = 0;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatnauint32_t vgen_rbufsz2 = 0;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatnauint32_t vgen_rbufsz3 = 0;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatnauint32_t vgen_rbufsz4 = 0;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramuint32_t vgen_nrbufs1 = VGEN_NRBUFS;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramuint32_t vgen_nrbufs2 = VGEN_NRBUFS;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramuint32_t vgen_nrbufs3 = VGEN_NRBUFS;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatnauint32_t vgen_nrbufs4 = VGEN_NRBUFS;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
f0ca1d9a12d54d304791bc74525e2010ca924726sb/*
f0ca1d9a12d54d304791bc74525e2010ca924726sb * In the absence of "priority-ether-types" property in MD, the following
f0ca1d9a12d54d304791bc74525e2010ca924726sb * internal tunable can be set to specify a single priority ethertype.
f0ca1d9a12d54d304791bc74525e2010ca924726sb */
f0ca1d9a12d54d304791bc74525e2010ca924726sbuint64_t vgen_pri_eth_type = 0;
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb/*
f0ca1d9a12d54d304791bc74525e2010ca924726sb * Number of transmit priority buffers that are preallocated per device.
f0ca1d9a12d54d304791bc74525e2010ca924726sb * This number is chosen to be a small value to throttle transmission
f0ca1d9a12d54d304791bc74525e2010ca924726sb * of priority packets. Note: Must be a power of 2 for vio_create_mblks().
f0ca1d9a12d54d304791bc74525e2010ca924726sb */
f0ca1d9a12d54d304791bc74525e2010ca924726sbuint32_t vgen_pri_tx_nmblks = 64;
f0ca1d9a12d54d304791bc74525e2010ca924726sb
c1c61f44e88f4c8c155272ee56d868043146096asbuint32_t vgen_vlan_nchains = 4; /* # of chains in vlan id hash table */
c1c61f44e88f4c8c155272ee56d868043146096asb
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#ifdef DEBUG
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* flags to simulate error conditions for debugging */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoint vgen_trigger_txtimeout = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoint vgen_trigger_rxlost = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#endif
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
c1c61f44e88f4c8c155272ee56d868043146096asb/*
c1c61f44e88f4c8c155272ee56d868043146096asb * Matching criteria passed to the MDEG to register interest
c1c61f44e88f4c8c155272ee56d868043146096asb * in changes to 'virtual-device' nodes (i.e. vnet nodes) identified
c1c61f44e88f4c8c155272ee56d868043146096asb * by their 'name' and 'cfg-handle' properties.
c1c61f44e88f4c8c155272ee56d868043146096asb */
c1c61f44e88f4c8c155272ee56d868043146096asbstatic md_prop_match_t vdev_prop_match[] = {
c1c61f44e88f4c8c155272ee56d868043146096asb { MDET_PROP_STR, "name" },
c1c61f44e88f4c8c155272ee56d868043146096asb { MDET_PROP_VAL, "cfg-handle" },
c1c61f44e88f4c8c155272ee56d868043146096asb { MDET_LIST_END, NULL }
c1c61f44e88f4c8c155272ee56d868043146096asb};
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asbstatic mdeg_node_match_t vdev_match = { "virtual-device",
c1c61f44e88f4c8c155272ee56d868043146096asb vdev_prop_match };
c1c61f44e88f4c8c155272ee56d868043146096asb
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* MD update matching structure */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic md_prop_match_t vport_prop_match[] = {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo { MDET_PROP_VAL, "id" },
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo { MDET_LIST_END, NULL }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo};
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic mdeg_node_match_t vport_match = { "virtual-device-port",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vport_prop_match };
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* template for matching a particular vnet instance */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic mdeg_prop_spec_t vgen_prop_template[] = {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo { MDET_PROP_STR, "name", "network" },
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo { MDET_PROP_VAL, "cfg-handle", NULL },
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo { MDET_LIST_END, NULL, NULL }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo};
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#define VGEN_SET_MDEG_PROP_INST(specp, val) (specp)[1].ps_val = (val)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
c1c61f44e88f4c8c155272ee56d868043146096asbstatic int vgen_mdeg_port_cb(void *cb_argp, mdeg_result_t *resp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna#ifdef VNET_IOC_DEBUG
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna#define VGEN_M_CALLBACK_FLAGS (MC_IOCTL)
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna#else
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna#define VGEN_M_CALLBACK_FLAGS (0)
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna#endif
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebstatic mac_callbacks_t vgen_m_callbacks = {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna VGEN_M_CALLBACK_FLAGS,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb vgen_stat,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb vgen_start,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb vgen_stop,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb vgen_promisc,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb vgen_multicst,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb vgen_unicst,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb vgen_tx,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer NULL,
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vgen_ioctl,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb NULL,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb NULL
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb};
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* externs */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramextern pri_t maxclsyspri;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramextern proc_t p0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoextern uint32_t vnet_ntxds;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoextern uint32_t vnet_ldcwd_interval;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoextern uint32_t vnet_ldcwd_txtimeout;
e1ebb9ec908bc2d0a8810f137ebd6566cc8a8061lmextern uint32_t vnet_ldc_mtu;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayanextern uint32_t vnet_nrbufs;
c1c61f44e88f4c8c155272ee56d868043146096asbextern uint32_t vnet_ethermtu;
c1c61f44e88f4c8c155272ee56d868043146096asbextern uint16_t vnet_default_vlan_id;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatnaextern boolean_t vnet_jumbo_rxpools;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram#ifdef DEBUG
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramextern int vnet_dbglevel;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramstatic void debug_printf(const char *fname, vgen_t *vgenp,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_ldc_t *ldcp, const char *fmt, ...);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram/* -1 for all LDCs info, or ldc_id for a specific LDC info */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramint vgendbg_ldcid = -1;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* simulate handshake error conditions for debug */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppouint32_t vgen_hdbg;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#define HDBG_VERSION 0x1
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#define HDBG_TIMEOUT 0x2
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#define HDBG_BAD_SID 0x4
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#define HDBG_OUT_STATE 0x8
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#endif
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * vgen_init() is called by an instance of vnet driver to initialize the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * corresponding generic proxy transport layer. The arguments passed by vnet
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * are - an opaque pointer to the vnet instance, pointers to dev_info_t and
678453a8ed49104d8adad58f3ba591bdc39883e8speer * the mac address of the vnet device, and a pointer to vgen_t is passed
678453a8ed49104d8adad58f3ba591bdc39883e8speer * back as a handle to vnet.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoint
678453a8ed49104d8adad58f3ba591bdc39883e8speervgen_init(void *vnetp, uint64_t regprop, dev_info_t *vnetdip,
678453a8ed49104d8adad58f3ba591bdc39883e8speer const uint8_t *macaddr, void **vgenhdl)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_t *vgenp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int instance;
f0ca1d9a12d54d304791bc74525e2010ca924726sb int rv;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb if ((vnetp == NULL) || (vnetdip == NULL))
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo instance = ddi_get_instance(vnetdip);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
06db247c678f0e3956535e8a6dec31d6c2108827raghuram DBG1(NULL, NULL, "vnet(%d): enter\n", instance);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp = kmem_zalloc(sizeof (vgen_t), KM_SLEEP);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp->vnetp = vnetp;
678453a8ed49104d8adad58f3ba591bdc39883e8speer vgenp->instance = instance;
678453a8ed49104d8adad58f3ba591bdc39883e8speer vgenp->regprop = regprop;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp->vnetdip = vnetdip;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bcopy(macaddr, &(vgenp->macaddr), ETHERADDRL);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vgenp->phys_link_state = LINK_STATE_UNKNOWN;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* allocate multicast table */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp->mctab = kmem_zalloc(VGEN_INIT_MCTAB_SIZE *
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo sizeof (struct ether_addr), KM_SLEEP);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp->mccount = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp->mcsize = VGEN_INIT_MCTAB_SIZE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_init(&vgenp->lock, NULL, MUTEX_DRIVER, NULL);
93b13a42237cddf986044511610fa8eddef1bd09wentaoy rw_init(&vgenp->vgenports.rwlock, NULL, RW_DRIVER, NULL);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
f0ca1d9a12d54d304791bc74525e2010ca924726sb rv = vgen_read_mdprops(vgenp);
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (rv != 0) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb goto vgen_init_fail;
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
678453a8ed49104d8adad58f3ba591bdc39883e8speer *vgenhdl = (void *)vgenp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
06db247c678f0e3956535e8a6dec31d6c2108827raghuram DBG1(NULL, NULL, "vnet(%d): exit\n", instance);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_SUCCESS);
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sbvgen_init_fail:
f0ca1d9a12d54d304791bc74525e2010ca924726sb rw_destroy(&vgenp->vgenports.rwlock);
f0ca1d9a12d54d304791bc74525e2010ca924726sb mutex_destroy(&vgenp->lock);
f0ca1d9a12d54d304791bc74525e2010ca924726sb kmem_free(vgenp->mctab, VGEN_INIT_MCTAB_SIZE *
f0ca1d9a12d54d304791bc74525e2010ca924726sb sizeof (struct ether_addr));
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (VGEN_PRI_ETH_DEFINED(vgenp)) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb kmem_free(vgenp->pri_types,
f0ca1d9a12d54d304791bc74525e2010ca924726sb sizeof (uint16_t) * vgenp->pri_num_types);
f0ca1d9a12d54d304791bc74525e2010ca924726sb (void) vio_destroy_mblks(vgenp->pri_tx_vmp);
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
f0ca1d9a12d54d304791bc74525e2010ca924726sb KMEM_FREE(vgenp);
f0ca1d9a12d54d304791bc74525e2010ca924726sb return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatnaint
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatnavgen_init_mdeg(void *arg)
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna{
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna vgen_t *vgenp = (vgen_t *)arg;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna /* register with MD event generator */
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna return (vgen_mdeg_reg(vgenp));
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna}
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Called by vnet to undo the initializations done by vgen_init().
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * The handle provided by generic transport during vgen_init() is the argument.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
3ab636deaa8cd06b5153d9eb3eaf79808afb491cWENTAO YANGvoid
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_uninit(void *arg)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
f0ca1d9a12d54d304791bc74525e2010ca924726sb vgen_t *vgenp = (vgen_t *)arg;
f0ca1d9a12d54d304791bc74525e2010ca924726sb vio_mblk_pool_t *rp;
f0ca1d9a12d54d304791bc74525e2010ca924726sb vio_mblk_pool_t *nrp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan if (vgenp == NULL) {
3ab636deaa8cd06b5153d9eb3eaf79808afb491cWENTAO YANG return;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, NULL, "enter\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* unregister with MD event generator */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_mdeg_unreg(vgenp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_enter(&vgenp->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* detach all ports from the device */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_detach_ports(vgenp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan /*
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * free any pending rx mblk pools,
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * that couldn't be freed previously during channel detach.
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan rp = vgenp->rmp;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan while (rp != NULL) {
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan nrp = vgenp->rmp = rp->nextp;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan if (vio_destroy_mblks(rp)) {
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG WRITE_ENTER(&vgen_rw);
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG rp->nextp = vgen_rx_poolp;
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG vgen_rx_poolp = rp;
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG RW_EXIT(&vgen_rw);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan rp = nrp;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* free multicast table */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kmem_free(vgenp->mctab, vgenp->mcsize * sizeof (struct ether_addr));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* free pri_types table */
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (VGEN_PRI_ETH_DEFINED(vgenp)) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb kmem_free(vgenp->pri_types,
f0ca1d9a12d54d304791bc74525e2010ca924726sb sizeof (uint16_t) * vgenp->pri_num_types);
f0ca1d9a12d54d304791bc74525e2010ca924726sb (void) vio_destroy_mblks(vgenp->pri_tx_vmp);
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
f0ca1d9a12d54d304791bc74525e2010ca924726sb
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&vgenp->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
93b13a42237cddf986044511610fa8eddef1bd09wentaoy rw_destroy(&vgenp->vgenports.rwlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_destroy(&vgenp->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, NULL, "exit\n");
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG KMEM_FREE(vgenp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG/*
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG * module specific initialization common to all instances of vnet/vgen.
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG */
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANGvoid
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANGvgen_mod_init(void)
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG{
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG rw_init(&vgen_rw, NULL, RW_DRIVER, NULL);
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG}
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG/*
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG * module specific cleanup common to all instances of vnet/vgen.
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG */
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANGint
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANGvgen_mod_cleanup(void)
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG{
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG vio_mblk_pool_t *poolp, *npoolp;
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG /*
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG * If any rx mblk pools are still in use, return
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG * error and stop the module from unloading.
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG */
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG WRITE_ENTER(&vgen_rw);
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG poolp = vgen_rx_poolp;
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG while (poolp != NULL) {
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG npoolp = vgen_rx_poolp = poolp->nextp;
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG if (vio_destroy_mblks(poolp) != 0) {
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG vgen_rx_poolp = poolp;
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG RW_EXIT(&vgen_rw);
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG return (EBUSY);
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG }
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG poolp = npoolp;
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG }
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG RW_EXIT(&vgen_rw);
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG return (0);
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG}
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG/*
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG * module specific uninitialization common to all instances of vnet/vgen.
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG */
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANGvoid
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANGvgen_mod_fini(void)
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG{
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG rw_destroy(&vgen_rw);
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG}
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* enable transmit/receive for the device */
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebint
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_start(void *arg)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
678453a8ed49104d8adad58f3ba591bdc39883e8speer vgen_port_t *portp = (vgen_port_t *)arg;
678453a8ed49104d8adad58f3ba591bdc39883e8speer vgen_t *vgenp = portp->vgenp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, NULL, "enter\n");
678453a8ed49104d8adad58f3ba591bdc39883e8speer mutex_enter(&portp->lock);
678453a8ed49104d8adad58f3ba591bdc39883e8speer vgen_port_init(portp);
678453a8ed49104d8adad58f3ba591bdc39883e8speer portp->flags |= VGEN_STARTED;
678453a8ed49104d8adad58f3ba591bdc39883e8speer mutex_exit(&portp->lock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, NULL, "exit\n");
678453a8ed49104d8adad58f3ba591bdc39883e8speer
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* stop transmit/receive */
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebvoid
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_stop(void *arg)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
678453a8ed49104d8adad58f3ba591bdc39883e8speer vgen_port_t *portp = (vgen_port_t *)arg;
678453a8ed49104d8adad58f3ba591bdc39883e8speer vgen_t *vgenp = portp->vgenp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, NULL, "enter\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
678453a8ed49104d8adad58f3ba591bdc39883e8speer mutex_enter(&portp->lock);
0c4606f05172c66c6c65847c0f940871a0ea1c15WENTAO YANG if (portp->flags & VGEN_STARTED) {
0c4606f05172c66c6c65847c0f940871a0ea1c15WENTAO YANG vgen_port_uninit(portp);
0c4606f05172c66c6c65847c0f940871a0ea1c15WENTAO YANG portp->flags &= ~(VGEN_STARTED);
0c4606f05172c66c6c65847c0f940871a0ea1c15WENTAO YANG }
678453a8ed49104d8adad58f3ba591bdc39883e8speer mutex_exit(&portp->lock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, NULL, "exit\n");
678453a8ed49104d8adad58f3ba591bdc39883e8speer
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* vgen transmit function */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic mblk_t *
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_tx(void *arg, mblk_t *mp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
61a70d81555b002d961400e93b444d97fc467f13raghuram int i;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_port_t *portp;
61a70d81555b002d961400e93b444d97fc467f13raghuram int status = VGEN_FAILURE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo portp = (vgen_port_t *)arg;
61a70d81555b002d961400e93b444d97fc467f13raghuram /*
61a70d81555b002d961400e93b444d97fc467f13raghuram * Retry so that we avoid reporting a failure
61a70d81555b002d961400e93b444d97fc467f13raghuram * to the upper layer. Returning a failure may cause the
61a70d81555b002d961400e93b444d97fc467f13raghuram * upper layer to go into single threaded mode there by
61a70d81555b002d961400e93b444d97fc467f13raghuram * causing performance degradation, especially for a large
61a70d81555b002d961400e93b444d97fc467f13raghuram * number of connections.
61a70d81555b002d961400e93b444d97fc467f13raghuram */
61a70d81555b002d961400e93b444d97fc467f13raghuram for (i = 0; i < vgen_tx_retries; ) {
61a70d81555b002d961400e93b444d97fc467f13raghuram status = vgen_portsend(portp, mp);
61a70d81555b002d961400e93b444d97fc467f13raghuram if (status == VGEN_SUCCESS) {
61a70d81555b002d961400e93b444d97fc467f13raghuram break;
61a70d81555b002d961400e93b444d97fc467f13raghuram }
61a70d81555b002d961400e93b444d97fc467f13raghuram if (++i < vgen_tx_retries)
61a70d81555b002d961400e93b444d97fc467f13raghuram delay(drv_usectohz(vgen_tx_delay));
61a70d81555b002d961400e93b444d97fc467f13raghuram }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (status != VGEN_SUCCESS) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* failure */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (mp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* success */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (NULL);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
c1c61f44e88f4c8c155272ee56d868043146096asb/*
c1c61f44e88f4c8c155272ee56d868043146096asb * This function provides any necessary tagging/untagging of the frames
c1c61f44e88f4c8c155272ee56d868043146096asb * that are being transmitted over the port. It first verifies the vlan
c1c61f44e88f4c8c155272ee56d868043146096asb * membership of the destination(port) and drops the packet if the
c1c61f44e88f4c8c155272ee56d868043146096asb * destination doesn't belong to the given vlan.
c1c61f44e88f4c8c155272ee56d868043146096asb *
c1c61f44e88f4c8c155272ee56d868043146096asb * Arguments:
c1c61f44e88f4c8c155272ee56d868043146096asb * portp: port over which the frames should be transmitted
c1c61f44e88f4c8c155272ee56d868043146096asb * mp: frame to be transmitted
c1c61f44e88f4c8c155272ee56d868043146096asb * is_tagged:
c1c61f44e88f4c8c155272ee56d868043146096asb * B_TRUE: indicates frame header contains the vlan tag already.
c1c61f44e88f4c8c155272ee56d868043146096asb * B_FALSE: indicates frame is untagged.
c1c61f44e88f4c8c155272ee56d868043146096asb * vid: vlan in which the frame should be transmitted.
c1c61f44e88f4c8c155272ee56d868043146096asb *
c1c61f44e88f4c8c155272ee56d868043146096asb * Returns:
c1c61f44e88f4c8c155272ee56d868043146096asb * Sucess: frame(mblk_t *) after doing the necessary tag/untag.
c1c61f44e88f4c8c155272ee56d868043146096asb * Failure: NULL
c1c61f44e88f4c8c155272ee56d868043146096asb */
c1c61f44e88f4c8c155272ee56d868043146096asbstatic mblk_t *
c1c61f44e88f4c8c155272ee56d868043146096asbvgen_vlan_frame_fixtag(vgen_port_t *portp, mblk_t *mp, boolean_t is_tagged,
c1c61f44e88f4c8c155272ee56d868043146096asb uint16_t vid)
c1c61f44e88f4c8c155272ee56d868043146096asb{
c1c61f44e88f4c8c155272ee56d868043146096asb vgen_t *vgenp;
c1c61f44e88f4c8c155272ee56d868043146096asb boolean_t dst_tagged;
c1c61f44e88f4c8c155272ee56d868043146096asb int rv;
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb vgenp = portp->vgenp;
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /*
c1c61f44e88f4c8c155272ee56d868043146096asb * If the packet is going to a vnet:
c1c61f44e88f4c8c155272ee56d868043146096asb * Check if the destination vnet is in the same vlan.
c1c61f44e88f4c8c155272ee56d868043146096asb * Check the frame header if tag or untag is needed.
c1c61f44e88f4c8c155272ee56d868043146096asb *
c1c61f44e88f4c8c155272ee56d868043146096asb * We do not check the above conditions if the packet is going to vsw:
c1c61f44e88f4c8c155272ee56d868043146096asb * vsw must be present implicitly in all the vlans that a vnet device
c1c61f44e88f4c8c155272ee56d868043146096asb * is configured into; even if vsw itself is not assigned to those
c1c61f44e88f4c8c155272ee56d868043146096asb * vlans as an interface. For instance, the packet might be destined
c1c61f44e88f4c8c155272ee56d868043146096asb * to another vnet(indirectly through vsw) or to an external host
c1c61f44e88f4c8c155272ee56d868043146096asb * which is in the same vlan as this vnet and vsw itself may not be
c1c61f44e88f4c8c155272ee56d868043146096asb * present in that vlan. Similarly packets going to vsw must be
c1c61f44e88f4c8c155272ee56d868043146096asb * always tagged(unless in the default-vlan) if not already tagged,
c1c61f44e88f4c8c155272ee56d868043146096asb * as we do not know the final destination. This is needed because
c1c61f44e88f4c8c155272ee56d868043146096asb * vsw must always invoke its switching function only after tagging
c1c61f44e88f4c8c155272ee56d868043146096asb * the packet; otherwise after switching function determines the
c1c61f44e88f4c8c155272ee56d868043146096asb * destination we cannot figure out if the destination belongs to the
c1c61f44e88f4c8c155272ee56d868043146096asb * the same vlan that the frame originated from and if it needs tag/
c1c61f44e88f4c8c155272ee56d868043146096asb * untag. Note that vsw will tag the packet itself when it receives
c1c61f44e88f4c8c155272ee56d868043146096asb * it over the channel from a client if needed. However, that is
c1c61f44e88f4c8c155272ee56d868043146096asb * needed only in the case of vlan unaware clients such as obp or
c1c61f44e88f4c8c155272ee56d868043146096asb * earlier versions of vnet.
c1c61f44e88f4c8c155272ee56d868043146096asb *
c1c61f44e88f4c8c155272ee56d868043146096asb */
c1c61f44e88f4c8c155272ee56d868043146096asb if (portp != vgenp->vsw_portp) {
c1c61f44e88f4c8c155272ee56d868043146096asb /*
c1c61f44e88f4c8c155272ee56d868043146096asb * Packet going to a vnet. Check if the destination vnet is in
c1c61f44e88f4c8c155272ee56d868043146096asb * the same vlan. Then check the frame header if tag/untag is
c1c61f44e88f4c8c155272ee56d868043146096asb * needed.
c1c61f44e88f4c8c155272ee56d868043146096asb */
c1c61f44e88f4c8c155272ee56d868043146096asb rv = vgen_vlan_lookup(portp->vlan_hashp, vid);
c1c61f44e88f4c8c155272ee56d868043146096asb if (rv == B_FALSE) {
c1c61f44e88f4c8c155272ee56d868043146096asb /* drop the packet */
c1c61f44e88f4c8c155272ee56d868043146096asb freemsg(mp);
c1c61f44e88f4c8c155272ee56d868043146096asb return (NULL);
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /* is the destination tagged or untagged in this vlan? */
c1c61f44e88f4c8c155272ee56d868043146096asb (vid == portp->pvid) ? (dst_tagged = B_FALSE) :
c1c61f44e88f4c8c155272ee56d868043146096asb (dst_tagged = B_TRUE);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb if (is_tagged == dst_tagged) {
c1c61f44e88f4c8c155272ee56d868043146096asb /* no tagging/untagging needed */
c1c61f44e88f4c8c155272ee56d868043146096asb return (mp);
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb if (is_tagged == B_TRUE) {
c1c61f44e88f4c8c155272ee56d868043146096asb /* frame is tagged; destination needs untagged */
c1c61f44e88f4c8c155272ee56d868043146096asb mp = vnet_vlan_remove_tag(mp);
c1c61f44e88f4c8c155272ee56d868043146096asb return (mp);
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /* (is_tagged == B_FALSE): fallthru to tag tx packet: */
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /*
c1c61f44e88f4c8c155272ee56d868043146096asb * Packet going to a vnet needs tagging.
c1c61f44e88f4c8c155272ee56d868043146096asb * OR
c1c61f44e88f4c8c155272ee56d868043146096asb * If the packet is going to vsw, then it must be tagged in all cases:
c1c61f44e88f4c8c155272ee56d868043146096asb * unknown unicast, broadcast/multicast or to vsw interface.
c1c61f44e88f4c8c155272ee56d868043146096asb */
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb if (is_tagged == B_FALSE) {
c1c61f44e88f4c8c155272ee56d868043146096asb mp = vnet_vlan_insert_tag(mp, vid);
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb return (mp);
c1c61f44e88f4c8c155272ee56d868043146096asb}
c1c61f44e88f4c8c155272ee56d868043146096asb
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* transmit packets over the given port */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_portsend(vgen_port_t *portp, mblk_t *mp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
c1c61f44e88f4c8c155272ee56d868043146096asb vgen_ldclist_t *ldclp;
c1c61f44e88f4c8c155272ee56d868043146096asb vgen_ldc_t *ldcp;
c1c61f44e88f4c8c155272ee56d868043146096asb int status;
c1c61f44e88f4c8c155272ee56d868043146096asb int rv = VGEN_SUCCESS;
678453a8ed49104d8adad58f3ba591bdc39883e8speer vgen_t *vgenp = portp->vgenp;
678453a8ed49104d8adad58f3ba591bdc39883e8speer vnet_t *vnetp = vgenp->vnetp;
c1c61f44e88f4c8c155272ee56d868043146096asb boolean_t is_tagged;
678453a8ed49104d8adad58f3ba591bdc39883e8speer boolean_t dec_refcnt = B_FALSE;
c1c61f44e88f4c8c155272ee56d868043146096asb uint16_t vlan_id;
c1c61f44e88f4c8c155272ee56d868043146096asb struct ether_header *ehp;
c1c61f44e88f4c8c155272ee56d868043146096asb
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (portp->use_vsw_port) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer (void) atomic_inc_32(&vgenp->vsw_port_refcnt);
678453a8ed49104d8adad58f3ba591bdc39883e8speer portp = portp->vgenp->vsw_portp;
678453a8ed49104d8adad58f3ba591bdc39883e8speer dec_refcnt = B_TRUE;
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (portp == NULL) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer return (VGEN_FAILURE);
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /*
c1c61f44e88f4c8c155272ee56d868043146096asb * Determine the vlan id that the frame belongs to.
c1c61f44e88f4c8c155272ee56d868043146096asb */
c1c61f44e88f4c8c155272ee56d868043146096asb ehp = (struct ether_header *)mp->b_rptr;
c1c61f44e88f4c8c155272ee56d868043146096asb is_tagged = vgen_frame_lookup_vid(vnetp, ehp, &vlan_id);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb if (vlan_id == vnetp->default_vlan_id) {
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /* Frames in default vlan must be untagged */
c1c61f44e88f4c8c155272ee56d868043146096asb ASSERT(is_tagged == B_FALSE);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /*
c1c61f44e88f4c8c155272ee56d868043146096asb * If the destination is a vnet-port verify it belongs to the
c1c61f44e88f4c8c155272ee56d868043146096asb * default vlan; otherwise drop the packet. We do not need
c1c61f44e88f4c8c155272ee56d868043146096asb * this check for vsw-port, as it should implicitly belong to
c1c61f44e88f4c8c155272ee56d868043146096asb * this vlan; see comments in vgen_vlan_frame_fixtag().
c1c61f44e88f4c8c155272ee56d868043146096asb */
c1c61f44e88f4c8c155272ee56d868043146096asb if (portp != vgenp->vsw_portp &&
c1c61f44e88f4c8c155272ee56d868043146096asb portp->pvid != vnetp->default_vlan_id) {
c1c61f44e88f4c8c155272ee56d868043146096asb freemsg(mp);
678453a8ed49104d8adad58f3ba591bdc39883e8speer goto portsend_ret;
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb } else { /* frame not in default-vlan */
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb mp = vgen_vlan_frame_fixtag(portp, mp, is_tagged, vlan_id);
c1c61f44e88f4c8c155272ee56d868043146096asb if (mp == NULL) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer goto portsend_ret;
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldclp = &portp->ldclist;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo READ_ENTER(&ldclp->rwlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * NOTE: for now, we will assume we have a single channel.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ldclp->headp == NULL) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo RW_EXIT(&ldclp->rwlock);
678453a8ed49104d8adad58f3ba591bdc39883e8speer rv = VGEN_FAILURE;
678453a8ed49104d8adad58f3ba591bdc39883e8speer goto portsend_ret;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp = ldclp->headp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
f0ca1d9a12d54d304791bc74525e2010ca924726sb status = ldcp->tx(ldcp, mp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
61a70d81555b002d961400e93b444d97fc467f13raghuram RW_EXIT(&ldclp->rwlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
61a70d81555b002d961400e93b444d97fc467f13raghuram if (status != VGEN_TX_SUCCESS) {
61a70d81555b002d961400e93b444d97fc467f13raghuram rv = VGEN_FAILURE;
61a70d81555b002d961400e93b444d97fc467f13raghuram }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speerportsend_ret:
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (dec_refcnt == B_TRUE) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer (void) atomic_dec_32(&vgenp->vsw_port_refcnt);
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
61a70d81555b002d961400e93b444d97fc467f13raghuram return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
f0ca1d9a12d54d304791bc74525e2010ca924726sb/*
f0ca1d9a12d54d304791bc74525e2010ca924726sb * Wrapper function to transmit normal and/or priority frames over the channel.
f0ca1d9a12d54d304791bc74525e2010ca924726sb */
f0ca1d9a12d54d304791bc74525e2010ca924726sbstatic int
f0ca1d9a12d54d304791bc74525e2010ca924726sbvgen_ldcsend(void *arg, mblk_t *mp)
f0ca1d9a12d54d304791bc74525e2010ca924726sb{
f0ca1d9a12d54d304791bc74525e2010ca924726sb vgen_ldc_t *ldcp = (vgen_ldc_t *)arg;
f0ca1d9a12d54d304791bc74525e2010ca924726sb int status;
f0ca1d9a12d54d304791bc74525e2010ca924726sb struct ether_header *ehp;
f0ca1d9a12d54d304791bc74525e2010ca924726sb vgen_t *vgenp = LDC_TO_VGEN(ldcp);
f0ca1d9a12d54d304791bc74525e2010ca924726sb uint32_t num_types;
f0ca1d9a12d54d304791bc74525e2010ca924726sb uint16_t *types;
f0ca1d9a12d54d304791bc74525e2010ca924726sb int i;
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb ASSERT(VGEN_PRI_ETH_DEFINED(vgenp));
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb num_types = vgenp->pri_num_types;
f0ca1d9a12d54d304791bc74525e2010ca924726sb types = vgenp->pri_types;
f0ca1d9a12d54d304791bc74525e2010ca924726sb ehp = (struct ether_header *)mp->b_rptr;
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb for (i = 0; i < num_types; i++) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (ehp->ether_type == types[i]) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* priority frame, use pri tx function */
f0ca1d9a12d54d304791bc74525e2010ca924726sb vgen_ldcsend_pkt(ldcp, mp);
f0ca1d9a12d54d304791bc74525e2010ca924726sb return (VGEN_SUCCESS);
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb status = vgen_ldcsend_dring(ldcp, mp);
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb return (status);
f0ca1d9a12d54d304791bc74525e2010ca924726sb}
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb/*
f0ca1d9a12d54d304791bc74525e2010ca924726sb * This functions handles ldc channel reset while in the context
f0ca1d9a12d54d304791bc74525e2010ca924726sb * of transmit routines: vgen_ldcsend_pkt() or vgen_ldcsend_dring().
f0ca1d9a12d54d304791bc74525e2010ca924726sb */
f0ca1d9a12d54d304791bc74525e2010ca924726sbstatic void
f0ca1d9a12d54d304791bc74525e2010ca924726sbvgen_ldcsend_process_reset(vgen_ldc_t *ldcp)
f0ca1d9a12d54d304791bc74525e2010ca924726sb{
f0ca1d9a12d54d304791bc74525e2010ca924726sb ldc_status_t istatus;
f0ca1d9a12d54d304791bc74525e2010ca924726sb vgen_t *vgenp = LDC_TO_VGEN(ldcp);
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (mutex_tryenter(&ldcp->cblock)) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (ldc_status(ldcp->ldc_handle, &istatus) != 0) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb DWARN(vgenp, ldcp, "ldc_status() error\n");
f0ca1d9a12d54d304791bc74525e2010ca924726sb } else {
f0ca1d9a12d54d304791bc74525e2010ca924726sb ldcp->ldc_status = istatus;
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (ldcp->ldc_status != LDC_UP) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer vgen_handle_evt_reset(ldcp);
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
f0ca1d9a12d54d304791bc74525e2010ca924726sb mutex_exit(&ldcp->cblock);
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
f0ca1d9a12d54d304791bc74525e2010ca924726sb}
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb/*
f0ca1d9a12d54d304791bc74525e2010ca924726sb * This function transmits the frame in the payload of a raw data
f0ca1d9a12d54d304791bc74525e2010ca924726sb * (VIO_PKT_DATA) message. Thus, it provides an Out-Of-Band path to
f0ca1d9a12d54d304791bc74525e2010ca924726sb * send special frames with high priorities, without going through
f0ca1d9a12d54d304791bc74525e2010ca924726sb * the normal data path which uses descriptor ring mechanism.
f0ca1d9a12d54d304791bc74525e2010ca924726sb */
f0ca1d9a12d54d304791bc74525e2010ca924726sbstatic void
f0ca1d9a12d54d304791bc74525e2010ca924726sbvgen_ldcsend_pkt(void *arg, mblk_t *mp)
f0ca1d9a12d54d304791bc74525e2010ca924726sb{
f0ca1d9a12d54d304791bc74525e2010ca924726sb vgen_ldc_t *ldcp = (vgen_ldc_t *)arg;
f0ca1d9a12d54d304791bc74525e2010ca924726sb vio_raw_data_msg_t *pkt;
f0ca1d9a12d54d304791bc74525e2010ca924726sb mblk_t *bp;
f0ca1d9a12d54d304791bc74525e2010ca924726sb mblk_t *nmp = NULL;
f0ca1d9a12d54d304791bc74525e2010ca924726sb caddr_t dst;
f0ca1d9a12d54d304791bc74525e2010ca924726sb uint32_t mblksz;
f0ca1d9a12d54d304791bc74525e2010ca924726sb uint32_t size;
f0ca1d9a12d54d304791bc74525e2010ca924726sb uint32_t nbytes;
f0ca1d9a12d54d304791bc74525e2010ca924726sb int rv;
f0ca1d9a12d54d304791bc74525e2010ca924726sb vgen_t *vgenp = LDC_TO_VGEN(ldcp);
f0ca1d9a12d54d304791bc74525e2010ca924726sb vgen_stats_t *statsp = &ldcp->stats;
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* drop the packet if ldc is not up or handshake is not done */
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (ldcp->ldc_status != LDC_UP) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb (void) atomic_inc_32(&statsp->tx_pri_fail);
f0ca1d9a12d54d304791bc74525e2010ca924726sb DWARN(vgenp, ldcp, "status(%d), dropping packet\n",
f0ca1d9a12d54d304791bc74525e2010ca924726sb ldcp->ldc_status);
f0ca1d9a12d54d304791bc74525e2010ca924726sb goto send_pkt_exit;
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (ldcp->hphase != VH_DONE) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb (void) atomic_inc_32(&statsp->tx_pri_fail);
f0ca1d9a12d54d304791bc74525e2010ca924726sb DWARN(vgenp, ldcp, "hphase(%x), dropping packet\n",
f0ca1d9a12d54d304791bc74525e2010ca924726sb ldcp->hphase);
f0ca1d9a12d54d304791bc74525e2010ca924726sb goto send_pkt_exit;
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb size = msgsize(mp);
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* frame size bigger than available payload len of raw data msg ? */
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (size > (size_t)(ldcp->msglen - VIO_PKT_DATA_HDRSIZE)) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb (void) atomic_inc_32(&statsp->tx_pri_fail);
f0ca1d9a12d54d304791bc74525e2010ca924726sb DWARN(vgenp, ldcp, "invalid size(%d)\n", size);
f0ca1d9a12d54d304791bc74525e2010ca924726sb goto send_pkt_exit;
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (size < ETHERMIN)
f0ca1d9a12d54d304791bc74525e2010ca924726sb size = ETHERMIN;
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* alloc space for a raw data message */
f0ca1d9a12d54d304791bc74525e2010ca924726sb nmp = vio_allocb(vgenp->pri_tx_vmp);
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (nmp == NULL) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb (void) atomic_inc_32(&statsp->tx_pri_fail);
f0ca1d9a12d54d304791bc74525e2010ca924726sb DWARN(vgenp, ldcp, "vio_allocb failed\n");
f0ca1d9a12d54d304791bc74525e2010ca924726sb goto send_pkt_exit;
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
f0ca1d9a12d54d304791bc74525e2010ca924726sb pkt = (vio_raw_data_msg_t *)nmp->b_rptr;
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* copy frame into the payload of raw data message */
f0ca1d9a12d54d304791bc74525e2010ca924726sb dst = (caddr_t)pkt->data;
f0ca1d9a12d54d304791bc74525e2010ca924726sb for (bp = mp; bp != NULL; bp = bp->b_cont) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb mblksz = MBLKL(bp);
f0ca1d9a12d54d304791bc74525e2010ca924726sb bcopy(bp->b_rptr, dst, mblksz);
f0ca1d9a12d54d304791bc74525e2010ca924726sb dst += mblksz;
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* setup the raw data msg */
f0ca1d9a12d54d304791bc74525e2010ca924726sb pkt->tag.vio_msgtype = VIO_TYPE_DATA;
f0ca1d9a12d54d304791bc74525e2010ca924726sb pkt->tag.vio_subtype = VIO_SUBTYPE_INFO;
f0ca1d9a12d54d304791bc74525e2010ca924726sb pkt->tag.vio_subtype_env = VIO_PKT_DATA;
f0ca1d9a12d54d304791bc74525e2010ca924726sb pkt->tag.vio_sid = ldcp->local_sid;
f0ca1d9a12d54d304791bc74525e2010ca924726sb nbytes = VIO_PKT_DATA_HDRSIZE + size;
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* send the msg over ldc */
f0ca1d9a12d54d304791bc74525e2010ca924726sb rv = vgen_sendmsg(ldcp, (caddr_t)pkt, nbytes, B_FALSE);
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (rv != VGEN_SUCCESS) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb (void) atomic_inc_32(&statsp->tx_pri_fail);
f0ca1d9a12d54d304791bc74525e2010ca924726sb DWARN(vgenp, ldcp, "Error sending priority frame\n");
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (rv == ECONNRESET) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb vgen_ldcsend_process_reset(ldcp);
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
f0ca1d9a12d54d304791bc74525e2010ca924726sb goto send_pkt_exit;
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* update stats */
f0ca1d9a12d54d304791bc74525e2010ca924726sb (void) atomic_inc_64(&statsp->tx_pri_packets);
f0ca1d9a12d54d304791bc74525e2010ca924726sb (void) atomic_add_64(&statsp->tx_pri_bytes, size);
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sbsend_pkt_exit:
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (nmp != NULL)
f0ca1d9a12d54d304791bc74525e2010ca924726sb freemsg(nmp);
f0ca1d9a12d54d304791bc74525e2010ca924726sb freemsg(mp);
f0ca1d9a12d54d304791bc74525e2010ca924726sb}
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb/*
f0ca1d9a12d54d304791bc74525e2010ca924726sb * This function transmits normal (non-priority) data frames over
f0ca1d9a12d54d304791bc74525e2010ca924726sb * the channel. It queues the frame into the transmit descriptor ring
f0ca1d9a12d54d304791bc74525e2010ca924726sb * and sends a VIO_DRING_DATA message if needed, to wake up the
f0ca1d9a12d54d304791bc74525e2010ca924726sb * peer to (re)start processing.
f0ca1d9a12d54d304791bc74525e2010ca924726sb */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
f0ca1d9a12d54d304791bc74525e2010ca924726sbvgen_ldcsend_dring(void *arg, mblk_t *mp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
f0ca1d9a12d54d304791bc74525e2010ca924726sb vgen_ldc_t *ldcp = (vgen_ldc_t *)arg;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_private_desc_t *tbufp;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_private_desc_t *rtbufp;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vnet_public_desc_t *rtxdp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_private_desc_t *ntbufp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vnet_public_desc_t *txdp;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vio_dring_entry_hdr_t *hdrp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_stats_t *statsp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo struct ether_header *ehp;
c1c61f44e88f4c8c155272ee56d868043146096asb boolean_t is_bcast = B_FALSE;
c1c61f44e88f4c8c155272ee56d868043146096asb boolean_t is_mcast = B_FALSE;
c1c61f44e88f4c8c155272ee56d868043146096asb size_t mblksz;
c1c61f44e88f4c8c155272ee56d868043146096asb caddr_t dst;
c1c61f44e88f4c8c155272ee56d868043146096asb mblk_t *bp;
c1c61f44e88f4c8c155272ee56d868043146096asb size_t size;
c1c61f44e88f4c8c155272ee56d868043146096asb int rv = 0;
c1c61f44e88f4c8c155272ee56d868043146096asb vgen_t *vgenp = LDC_TO_VGEN(ldcp);
c1c61f44e88f4c8c155272ee56d868043146096asb vgen_hparams_t *lp = &ldcp->local_hparams;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
06db247c678f0e3956535e8a6dec31d6c2108827raghuram statsp = &ldcp->stats;
8e6a2a040587479821d1e682a28bcef7e75f19a6lm size = msgsize(mp);
8e6a2a040587479821d1e682a28bcef7e75f19a6lm
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "enter\n");
8e6a2a040587479821d1e682a28bcef7e75f19a6lm
8e6a2a040587479821d1e682a28bcef7e75f19a6lm if (ldcp->ldc_status != LDC_UP) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "status(%d), dropping packet\n",
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ldcp->ldc_status);
8e6a2a040587479821d1e682a28bcef7e75f19a6lm /* retry ldc_up() if needed */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna#ifdef VNET_IOC_DEBUG
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (ldcp->flags & CHANNEL_STARTED && !ldcp->link_down_forced) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna#else
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (ldcp->flags & CHANNEL_STARTED) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna#endif
8e6a2a040587479821d1e682a28bcef7e75f19a6lm (void) ldc_up(ldcp->ldc_handle);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna }
f0ca1d9a12d54d304791bc74525e2010ca924726sb goto send_dring_exit;
8e6a2a040587479821d1e682a28bcef7e75f19a6lm }
8e6a2a040587479821d1e682a28bcef7e75f19a6lm
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* drop the packet if ldc is not up or handshake is not done */
8e6a2a040587479821d1e682a28bcef7e75f19a6lm if (ldcp->hphase != VH_DONE) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "hphase(%x), dropping packet\n",
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ldcp->hphase);
f0ca1d9a12d54d304791bc74525e2010ca924726sb goto send_dring_exit;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
c1c61f44e88f4c8c155272ee56d868043146096asb if (size > (size_t)lp->mtu) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "invalid size(%d)\n", size);
f0ca1d9a12d54d304791bc74525e2010ca924726sb goto send_dring_exit;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (size < ETHERMIN)
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram size = ETHERMIN;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ehp = (struct ether_header *)mp->b_rptr;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram is_bcast = IS_BROADCAST(ehp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram is_mcast = IS_MULTICAST(ehp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_enter(&ldcp->txlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * allocate a descriptor
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tbufp = ldcp->next_tbufp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ntbufp = NEXTTBUF(ldcp, tbufp);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan if (ntbufp == ldcp->cur_tbufp) { /* out of tbufs/txds */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_enter(&ldcp->tclock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* Try reclaiming now */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_reclaim_dring(ldcp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ldcp->reclaim_lbolt = ddi_get_lbolt();
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan if (ntbufp == ldcp->cur_tbufp) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* Now we are really out of tbuf/txds */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->need_resched = B_TRUE;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan mutex_exit(&ldcp->tclock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan statsp->tx_no_desc++;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan mutex_exit(&ldcp->txlock);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan return (VGEN_TX_NORESOURCES);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan mutex_exit(&ldcp->tclock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* update next available tbuf in the ring and update tx index */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ldcp->next_tbufp = ntbufp;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram INCR_TXI(ldcp->next_txi, ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* Mark the buffer busy before releasing the lock */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram tbufp->flags = VGEN_PRIV_DESC_BUSY;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_exit(&ldcp->txlock);
8e6a2a040587479821d1e682a28bcef7e75f19a6lm
8e6a2a040587479821d1e682a28bcef7e75f19a6lm /* copy data into pre-allocated transmit buffer */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan dst = tbufp->datap + VNET_IPALIGN;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan for (bp = mp; bp != NULL; bp = bp->b_cont) {
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan mblksz = MBLKL(bp);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan bcopy(bp->b_rptr, dst, mblksz);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan dst += mblksz;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
8e6a2a040587479821d1e682a28bcef7e75f19a6lm tbufp->datalen = size;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* initialize the corresponding public descriptor (txd) */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo txdp = tbufp->descp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo hdrp = &txdp->hdr;
8e6a2a040587479821d1e682a28bcef7e75f19a6lm txdp->nbytes = size;
8e6a2a040587479821d1e682a28bcef7e75f19a6lm txdp->ncookies = tbufp->ncookies;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bcopy((tbufp->memcookie), (txdp->memcookie),
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram tbufp->ncookies * sizeof (ldc_mem_cookie_t));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_enter(&ldcp->wrlock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /*
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * If the flags not set to BUSY, it implies that the clobber
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * was done while we were copying the data. In such case,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * discard the packet and return.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (tbufp->flags != VGEN_PRIV_DESC_BUSY) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram statsp->oerrors++;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_exit(&ldcp->wrlock);
f0ca1d9a12d54d304791bc74525e2010ca924726sb goto send_dring_exit;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram hdrp->dstate = VIO_DESC_READY;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* update stats */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo statsp->opackets++;
8e6a2a040587479821d1e682a28bcef7e75f19a6lm statsp->obytes += size;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (is_bcast)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo statsp->brdcstxmt++;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo else if (is_mcast)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo statsp->multixmt++;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* send dring datamsg to the peer */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (ldcp->resched_peer) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram rtbufp = &ldcp->tbufp[ldcp->resched_peer_txi];
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram rtxdp = rtbufp->descp;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (rtxdp->hdr.dstate == VIO_DESC_READY) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram rv = vgen_send_dring_data(ldcp,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram (uint32_t)ldcp->resched_peer_txi, -1);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (rv != 0) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* error: drop the packet */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "vgen_send_dring_data "
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram "failed: rv(%d) len(%d)\n",
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram ldcp->ldc_id, rv, size);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram statsp->oerrors++;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram } else {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ldcp->resched_peer = B_FALSE;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_exit(&ldcp->wrlock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
f0ca1d9a12d54d304791bc74525e2010ca924726sbsend_dring_exit:
3af08d828975d7e2581b6829e0eecff14d87a483lm if (rv == ECONNRESET) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb vgen_ldcsend_process_reset(ldcp);
3af08d828975d7e2581b6829e0eecff14d87a483lm }
8e6a2a040587479821d1e682a28bcef7e75f19a6lm freemsg(mp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "exit\n");
8e6a2a040587479821d1e682a28bcef7e75f19a6lm return (VGEN_TX_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
0c4606f05172c66c6c65847c0f940871a0ea1c15WENTAO YANG/*
0c4606f05172c66c6c65847c0f940871a0ea1c15WENTAO YANG * enable/disable a multicast address
0c4606f05172c66c6c65847c0f940871a0ea1c15WENTAO YANG * note that the cblock of the ldc channel connected to the vsw is used for
0c4606f05172c66c6c65847c0f940871a0ea1c15WENTAO YANG * synchronization of the mctab.
0c4606f05172c66c6c65847c0f940871a0ea1c15WENTAO YANG */
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebint
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_multicst(void *arg, boolean_t add, const uint8_t *mca)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_t *vgenp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vnet_mcast_msg_t mcastmsg;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vio_msg_tag_t *tagp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_port_t *portp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_ldc_t *ldcp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_ldclist_t *ldclp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo struct ether_addr *addrp;
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan int rv = DDI_FAILURE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint32_t i;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
678453a8ed49104d8adad58f3ba591bdc39883e8speer portp = (vgen_port_t *)arg;
678453a8ed49104d8adad58f3ba591bdc39883e8speer vgenp = portp->vgenp;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
0c4606f05172c66c6c65847c0f940871a0ea1c15WENTAO YANG if (portp->is_vsw_port != B_TRUE) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer return (DDI_SUCCESS);
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo addrp = (struct ether_addr *)mca;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp = &mcastmsg.tag;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bzero(&mcastmsg, sizeof (mcastmsg));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldclp = &portp->ldclist;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo READ_ENTER(&ldclp->rwlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp = ldclp->headp;
0c4606f05172c66c6c65847c0f940871a0ea1c15WENTAO YANG if (ldcp == NULL) {
0c4606f05172c66c6c65847c0f940871a0ea1c15WENTAO YANG RW_EXIT(&ldclp->rwlock);
0c4606f05172c66c6c65847c0f940871a0ea1c15WENTAO YANG return (DDI_FAILURE);
0c4606f05172c66c6c65847c0f940871a0ea1c15WENTAO YANG }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_enter(&ldcp->cblock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ldcp->hphase == VH_DONE) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If handshake is done, send a msg to vsw to add/remove
19b65a69adc64b3289ccb2fc32b805782e3f4540sb * the multicast address. Otherwise, we just update this
19b65a69adc64b3289ccb2fc32b805782e3f4540sb * mcast address in our table and the table will be sync'd
19b65a69adc64b3289ccb2fc32b805782e3f4540sb * with vsw when handshake completes.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_msgtype = VIO_TYPE_CTRL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_subtype = VIO_SUBTYPE_INFO;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_subtype_env = VNET_MCAST_INFO;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_sid = ldcp->local_sid;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bcopy(mca, &(mcastmsg.mca), ETHERADDRL);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mcastmsg.set = add;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mcastmsg.count = 1;
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan if (vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (mcastmsg),
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan B_FALSE) != VGEN_SUCCESS) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "vgen_sendmsg failed\n");
0c4606f05172c66c6c65847c0f940871a0ea1c15WENTAO YANG rv = DDI_FAILURE;
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan goto vgen_mcast_exit;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (add) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* expand multicast table if necessary */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vgenp->mccount >= vgenp->mcsize) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo struct ether_addr *newtab;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint32_t newsize;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo newsize = vgenp->mcsize * 2;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo newtab = kmem_zalloc(newsize *
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo sizeof (struct ether_addr), KM_NOSLEEP);
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan if (newtab == NULL)
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan goto vgen_mcast_exit;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bcopy(vgenp->mctab, newtab, vgenp->mcsize *
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo sizeof (struct ether_addr));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kmem_free(vgenp->mctab,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp->mcsize * sizeof (struct ether_addr));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp->mctab = newtab;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp->mcsize = newsize;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* add address to the table */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp->mctab[vgenp->mccount++] = *addrp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } else {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* delete address from the table */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (i = 0; i < vgenp->mccount; i++) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ether_cmp(addrp, &(vgenp->mctab[i])) == 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If there's more than one address in this
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * table, delete the unwanted one by moving
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * the last one in the list over top of it;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * otherwise, just remove it.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vgenp->mccount > 1) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp->mctab[i] =
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram vgenp->mctab[vgenp->mccount-1];
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp->mccount--;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan rv = DDI_SUCCESS;
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayanvgen_mcast_exit:
0c4606f05172c66c6c65847c0f940871a0ea1c15WENTAO YANG mutex_exit(&ldcp->cblock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo RW_EXIT(&ldclp->rwlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* set or clear promiscuous mode on the device */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_promisc(void *arg, boolean_t on)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo _NOTE(ARGUNUSED(arg, on))
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* set the unicast mac address of the device */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_unicst(void *arg, const uint8_t *mca)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo _NOTE(ARGUNUSED(arg, mca))
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* get device statistics */
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebint
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebvgen_stat(void *arg, uint_t stat, uint64_t *val)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
678453a8ed49104d8adad58f3ba591bdc39883e8speer vgen_port_t *portp = (vgen_port_t *)arg;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
678453a8ed49104d8adad58f3ba591bdc39883e8speer *val = vgen_port_stat(portp, stat);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb return (0);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* vgen internal functions */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* detach all ports from the device */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_detach_ports(vgen_t *vgenp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_port_t *portp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_portlist_t *plistp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo plistp = &(vgenp->vgenports);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo WRITE_ENTER(&plistp->rwlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo while ((portp = plistp->headp) != NULL) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_port_detach(portp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo RW_EXIT(&plistp->rwlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * detach the given port.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_port_detach(vgen_port_t *portp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_t *vgenp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_ldclist_t *ldclp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int port_num;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp = portp->vgenp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo port_num = portp->port_num;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, NULL, "port(%d):enter\n", port_num);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
678453a8ed49104d8adad58f3ba591bdc39883e8speer /*
678453a8ed49104d8adad58f3ba591bdc39883e8speer * If this port is connected to the vswitch, then
678453a8ed49104d8adad58f3ba591bdc39883e8speer * potentially there could be ports that may be using
678453a8ed49104d8adad58f3ba591bdc39883e8speer * this port to transmit packets. To address this do
678453a8ed49104d8adad58f3ba591bdc39883e8speer * the following:
678453a8ed49104d8adad58f3ba591bdc39883e8speer * - First set vgenp->vsw_portp to NULL, so that
678453a8ed49104d8adad58f3ba591bdc39883e8speer * its not used after that.
678453a8ed49104d8adad58f3ba591bdc39883e8speer * - Then wait for the refcnt to go down to 0.
678453a8ed49104d8adad58f3ba591bdc39883e8speer * - Now we can safely detach this port.
678453a8ed49104d8adad58f3ba591bdc39883e8speer */
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (vgenp->vsw_portp == portp) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer vgenp->vsw_portp = NULL;
678453a8ed49104d8adad58f3ba591bdc39883e8speer while (vgenp->vsw_port_refcnt > 0) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer delay(drv_usectohz(vgen_tx_delay));
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer (void) atomic_swap_32(&vgenp->vsw_port_refcnt, 0);
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (portp->vhp != NULL) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer vio_net_resource_unreg(portp->vhp);
678453a8ed49104d8adad58f3ba591bdc39883e8speer portp->vhp = NULL;
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
c1c61f44e88f4c8c155272ee56d868043146096asb vgen_vlan_destroy_hash(portp);
c1c61f44e88f4c8c155272ee56d868043146096asb
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* remove it from port list */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_port_list_remove(portp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* detach channels from this port */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldclp = &portp->ldclist;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo WRITE_ENTER(&ldclp->rwlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo while (ldclp->headp) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_ldc_detach(ldclp->headp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo RW_EXIT(&ldclp->rwlock);
93b13a42237cddf986044511610fa8eddef1bd09wentaoy rw_destroy(&ldclp->rwlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
c1c61f44e88f4c8c155272ee56d868043146096asb if (portp->num_ldcs != 0) {
c1c61f44e88f4c8c155272ee56d868043146096asb kmem_free(portp->ldc_ids, portp->num_ldcs * sizeof (uint64_t));
c1c61f44e88f4c8c155272ee56d868043146096asb portp->num_ldcs = 0;
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb
678453a8ed49104d8adad58f3ba591bdc39883e8speer mutex_destroy(&portp->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo KMEM_FREE(portp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, NULL, "port(%d):exit\n", port_num);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* add a port to port list */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_port_list_insert(vgen_port_t *portp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_portlist_t *plistp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_t *vgenp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp = portp->vgenp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo plistp = &(vgenp->vgenports);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (plistp->headp == NULL) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo plistp->headp = portp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } else {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo plistp->tailp->nextp = portp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo plistp->tailp = portp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo portp->nextp = NULL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* remove a port from port list */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_port_list_remove(vgen_port_t *portp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_port_t *prevp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_port_t *nextp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_portlist_t *plistp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_t *vgenp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp = portp->vgenp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo plistp = &(vgenp->vgenports);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (plistp->headp == NULL)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (portp == plistp->headp) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo plistp->headp = portp->nextp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (portp == plistp->tailp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo plistp->tailp = plistp->headp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } else {
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram for (prevp = plistp->headp;
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram ((nextp = prevp->nextp) != NULL) && (nextp != portp);
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram prevp = nextp)
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram ;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (nextp == portp) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo prevp->nextp = portp->nextp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (portp == plistp->tailp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo plistp->tailp = prevp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* lookup a port in the list based on port_num */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic vgen_port_t *
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_port_lookup(vgen_portlist_t *plistp, int port_num)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_port_t *portp = NULL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (portp = plistp->headp; portp != NULL; portp = portp->nextp) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (portp->port_num == port_num) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (portp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* enable ports for transmit/receive */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_init_ports(vgen_t *vgenp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_port_t *portp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_portlist_t *plistp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo plistp = &(vgenp->vgenports);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo READ_ENTER(&plistp->rwlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (portp = plistp->headp; portp != NULL; portp = portp->nextp) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_port_init(portp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo RW_EXIT(&plistp->rwlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_port_init(vgen_port_t *portp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
c1c61f44e88f4c8c155272ee56d868043146096asb /* Add the port to the specified vlans */
c1c61f44e88f4c8c155272ee56d868043146096asb vgen_vlan_add_ids(portp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* Bring up the channels of this port */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_init_ldcs(portp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* disable transmit/receive on ports */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_uninit_ports(vgen_t *vgenp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_port_t *portp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_portlist_t *plistp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo plistp = &(vgenp->vgenports);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo READ_ENTER(&plistp->rwlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (portp = plistp->headp; portp != NULL; portp = portp->nextp) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_port_uninit(portp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo RW_EXIT(&plistp->rwlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_port_uninit(vgen_port_t *portp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_uninit_ldcs(portp);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /* remove the port from vlans it has been assigned to */
c1c61f44e88f4c8c155272ee56d868043146096asb vgen_vlan_remove_ids(portp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
f0ca1d9a12d54d304791bc74525e2010ca924726sb/*
f0ca1d9a12d54d304791bc74525e2010ca924726sb * Scan the machine description for this instance of vnet
f0ca1d9a12d54d304791bc74525e2010ca924726sb * and read its properties. Called only from vgen_init().
f0ca1d9a12d54d304791bc74525e2010ca924726sb * Returns: 0 on success, 1 on failure.
f0ca1d9a12d54d304791bc74525e2010ca924726sb */
f0ca1d9a12d54d304791bc74525e2010ca924726sbstatic int
f0ca1d9a12d54d304791bc74525e2010ca924726sbvgen_read_mdprops(vgen_t *vgenp)
f0ca1d9a12d54d304791bc74525e2010ca924726sb{
c1c61f44e88f4c8c155272ee56d868043146096asb vnet_t *vnetp = vgenp->vnetp;
f0ca1d9a12d54d304791bc74525e2010ca924726sb md_t *mdp = NULL;
f0ca1d9a12d54d304791bc74525e2010ca924726sb mde_cookie_t rootnode;
f0ca1d9a12d54d304791bc74525e2010ca924726sb mde_cookie_t *listp = NULL;
f0ca1d9a12d54d304791bc74525e2010ca924726sb uint64_t cfgh;
f0ca1d9a12d54d304791bc74525e2010ca924726sb char *name;
f0ca1d9a12d54d304791bc74525e2010ca924726sb int rv = 1;
f0ca1d9a12d54d304791bc74525e2010ca924726sb int num_nodes = 0;
f0ca1d9a12d54d304791bc74525e2010ca924726sb int num_devs = 0;
f0ca1d9a12d54d304791bc74525e2010ca924726sb int listsz = 0;
f0ca1d9a12d54d304791bc74525e2010ca924726sb int i;
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb if ((mdp = md_get_handle()) == NULL) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb return (rv);
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb num_nodes = md_node_count(mdp);
f0ca1d9a12d54d304791bc74525e2010ca924726sb ASSERT(num_nodes > 0);
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb listsz = num_nodes * sizeof (mde_cookie_t);
f0ca1d9a12d54d304791bc74525e2010ca924726sb listp = (mde_cookie_t *)kmem_zalloc(listsz, KM_SLEEP);
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb rootnode = md_root_node(mdp);
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* search for all "virtual_device" nodes */
f0ca1d9a12d54d304791bc74525e2010ca924726sb num_devs = md_scan_dag(mdp, rootnode,
f0ca1d9a12d54d304791bc74525e2010ca924726sb md_find_name(mdp, vdev_propname),
f0ca1d9a12d54d304791bc74525e2010ca924726sb md_find_name(mdp, "fwd"), listp);
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (num_devs <= 0) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb goto vgen_readmd_exit;
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb /*
f0ca1d9a12d54d304791bc74525e2010ca924726sb * Now loop through the list of virtual-devices looking for
f0ca1d9a12d54d304791bc74525e2010ca924726sb * devices with name "network" and for each such device compare
f0ca1d9a12d54d304791bc74525e2010ca924726sb * its instance with what we have from the 'reg' property to
f0ca1d9a12d54d304791bc74525e2010ca924726sb * find the right node in MD and then read all its properties.
f0ca1d9a12d54d304791bc74525e2010ca924726sb */
f0ca1d9a12d54d304791bc74525e2010ca924726sb for (i = 0; i < num_devs; i++) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (md_get_prop_str(mdp, listp[i], "name", &name) != 0) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb goto vgen_readmd_exit;
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* is this a "network" device? */
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (strcmp(name, vnet_propname) != 0)
f0ca1d9a12d54d304791bc74525e2010ca924726sb continue;
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (md_get_prop_val(mdp, listp[i], "cfg-handle", &cfgh) != 0) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb goto vgen_readmd_exit;
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* is this the required instance of vnet? */
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (vgenp->regprop != cfgh)
f0ca1d9a12d54d304791bc74525e2010ca924726sb continue;
f0ca1d9a12d54d304791bc74525e2010ca924726sb
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna /*
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * Read the 'linkprop' property to know if this vnet
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * device should get physical link updates from vswitch.
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vgen_linkprop_read(vgenp, mdp, listp[i],
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna &vnetp->pls_update);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna /*
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * Read the mtu. Note that we set the mtu of vnet device within
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * this routine itself, after validating the range.
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna vgen_mtu_read(vgenp, mdp, listp[i], &vnetp->mtu);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna if (vnetp->mtu < ETHERMTU || vnetp->mtu > VNET_MAX_MTU) {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna vnetp->mtu = ETHERMTU;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna }
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna vgenp->max_frame_size = vnetp->mtu +
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna sizeof (struct ether_header) + VLAN_TAGSZ;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna /* read priority ether types */
f0ca1d9a12d54d304791bc74525e2010ca924726sb vgen_read_pri_eth_types(vgenp, mdp, listp[i]);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /* read vlan id properties of this vnet instance */
c1c61f44e88f4c8c155272ee56d868043146096asb vgen_vlan_read_ids(vgenp, VGEN_LOCAL, mdp, listp[i],
c1c61f44e88f4c8c155272ee56d868043146096asb &vnetp->pvid, &vnetp->vids, &vnetp->nvids,
c1c61f44e88f4c8c155272ee56d868043146096asb &vnetp->default_vlan_id);
c1c61f44e88f4c8c155272ee56d868043146096asb
f0ca1d9a12d54d304791bc74525e2010ca924726sb rv = 0;
f0ca1d9a12d54d304791bc74525e2010ca924726sb break;
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sbvgen_readmd_exit:
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb kmem_free(listp, listsz);
f0ca1d9a12d54d304791bc74525e2010ca924726sb (void) md_fini_handle(mdp);
f0ca1d9a12d54d304791bc74525e2010ca924726sb return (rv);
f0ca1d9a12d54d304791bc74525e2010ca924726sb}
f0ca1d9a12d54d304791bc74525e2010ca924726sb
c1c61f44e88f4c8c155272ee56d868043146096asb/*
c1c61f44e88f4c8c155272ee56d868043146096asb * Read vlan id properties of the given MD node.
c1c61f44e88f4c8c155272ee56d868043146096asb * Arguments:
c1c61f44e88f4c8c155272ee56d868043146096asb * arg: device argument(vnet device or a port)
c1c61f44e88f4c8c155272ee56d868043146096asb * type: type of arg; VGEN_LOCAL(vnet device) or VGEN_PEER(port)
c1c61f44e88f4c8c155272ee56d868043146096asb * mdp: machine description
c1c61f44e88f4c8c155272ee56d868043146096asb * node: md node cookie
c1c61f44e88f4c8c155272ee56d868043146096asb *
c1c61f44e88f4c8c155272ee56d868043146096asb * Returns:
c1c61f44e88f4c8c155272ee56d868043146096asb * pvidp: port-vlan-id of the node
c1c61f44e88f4c8c155272ee56d868043146096asb * vidspp: list of vlan-ids of the node
c1c61f44e88f4c8c155272ee56d868043146096asb * nvidsp: # of vlan-ids in the list
c1c61f44e88f4c8c155272ee56d868043146096asb * default_idp: default-vlan-id of the node(if node is vnet device)
c1c61f44e88f4c8c155272ee56d868043146096asb */
c1c61f44e88f4c8c155272ee56d868043146096asbstatic void
c1c61f44e88f4c8c155272ee56d868043146096asbvgen_vlan_read_ids(void *arg, int type, md_t *mdp, mde_cookie_t node,
c1c61f44e88f4c8c155272ee56d868043146096asb uint16_t *pvidp, uint16_t **vidspp, uint16_t *nvidsp,
c1c61f44e88f4c8c155272ee56d868043146096asb uint16_t *default_idp)
c1c61f44e88f4c8c155272ee56d868043146096asb{
c1c61f44e88f4c8c155272ee56d868043146096asb vgen_t *vgenp;
c1c61f44e88f4c8c155272ee56d868043146096asb vnet_t *vnetp;
c1c61f44e88f4c8c155272ee56d868043146096asb vgen_port_t *portp;
c1c61f44e88f4c8c155272ee56d868043146096asb char *pvid_propname;
c1c61f44e88f4c8c155272ee56d868043146096asb char *vid_propname;
c1c61f44e88f4c8c155272ee56d868043146096asb uint_t nvids;
c1c61f44e88f4c8c155272ee56d868043146096asb uint32_t vids_size;
c1c61f44e88f4c8c155272ee56d868043146096asb int rv;
c1c61f44e88f4c8c155272ee56d868043146096asb int i;
c1c61f44e88f4c8c155272ee56d868043146096asb uint64_t *data;
c1c61f44e88f4c8c155272ee56d868043146096asb uint64_t val;
c1c61f44e88f4c8c155272ee56d868043146096asb int size;
c1c61f44e88f4c8c155272ee56d868043146096asb int inst;
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb if (type == VGEN_LOCAL) {
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb vgenp = (vgen_t *)arg;
c1c61f44e88f4c8c155272ee56d868043146096asb vnetp = vgenp->vnetp;
c1c61f44e88f4c8c155272ee56d868043146096asb pvid_propname = vgen_pvid_propname;
c1c61f44e88f4c8c155272ee56d868043146096asb vid_propname = vgen_vid_propname;
c1c61f44e88f4c8c155272ee56d868043146096asb inst = vnetp->instance;
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb } else if (type == VGEN_PEER) {
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb portp = (vgen_port_t *)arg;
c1c61f44e88f4c8c155272ee56d868043146096asb vgenp = portp->vgenp;
c1c61f44e88f4c8c155272ee56d868043146096asb vnetp = vgenp->vnetp;
c1c61f44e88f4c8c155272ee56d868043146096asb pvid_propname = port_pvid_propname;
c1c61f44e88f4c8c155272ee56d868043146096asb vid_propname = port_vid_propname;
c1c61f44e88f4c8c155272ee56d868043146096asb inst = portp->port_num;
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb } else {
c1c61f44e88f4c8c155272ee56d868043146096asb return;
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb if (type == VGEN_LOCAL && default_idp != NULL) {
c1c61f44e88f4c8c155272ee56d868043146096asb rv = md_get_prop_val(mdp, node, vgen_dvid_propname, &val);
c1c61f44e88f4c8c155272ee56d868043146096asb if (rv != 0) {
c1c61f44e88f4c8c155272ee56d868043146096asb DWARN(vgenp, NULL, "prop(%s) not found",
c1c61f44e88f4c8c155272ee56d868043146096asb vgen_dvid_propname);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb *default_idp = vnet_default_vlan_id;
c1c61f44e88f4c8c155272ee56d868043146096asb } else {
c1c61f44e88f4c8c155272ee56d868043146096asb *default_idp = val & 0xFFF;
c1c61f44e88f4c8c155272ee56d868043146096asb DBG2(vgenp, NULL, "%s(%d): (%d)\n", vgen_dvid_propname,
c1c61f44e88f4c8c155272ee56d868043146096asb inst, *default_idp);
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb rv = md_get_prop_val(mdp, node, pvid_propname, &val);
c1c61f44e88f4c8c155272ee56d868043146096asb if (rv != 0) {
c1c61f44e88f4c8c155272ee56d868043146096asb DWARN(vgenp, NULL, "prop(%s) not found", pvid_propname);
c1c61f44e88f4c8c155272ee56d868043146096asb *pvidp = vnet_default_vlan_id;
c1c61f44e88f4c8c155272ee56d868043146096asb } else {
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb *pvidp = val & 0xFFF;
c1c61f44e88f4c8c155272ee56d868043146096asb DBG2(vgenp, NULL, "%s(%d): (%d)\n",
c1c61f44e88f4c8c155272ee56d868043146096asb pvid_propname, inst, *pvidp);
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb rv = md_get_prop_data(mdp, node, vid_propname, (uint8_t **)&data,
c1c61f44e88f4c8c155272ee56d868043146096asb &size);
c1c61f44e88f4c8c155272ee56d868043146096asb if (rv != 0) {
c1c61f44e88f4c8c155272ee56d868043146096asb DBG2(vgenp, NULL, "prop(%s) not found", vid_propname);
c1c61f44e88f4c8c155272ee56d868043146096asb size = 0;
c1c61f44e88f4c8c155272ee56d868043146096asb } else {
c1c61f44e88f4c8c155272ee56d868043146096asb size /= sizeof (uint64_t);
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb nvids = size;
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb if (nvids != 0) {
c1c61f44e88f4c8c155272ee56d868043146096asb DBG2(vgenp, NULL, "%s(%d): ", vid_propname, inst);
c1c61f44e88f4c8c155272ee56d868043146096asb vids_size = sizeof (uint16_t) * nvids;
c1c61f44e88f4c8c155272ee56d868043146096asb *vidspp = kmem_zalloc(vids_size, KM_SLEEP);
c1c61f44e88f4c8c155272ee56d868043146096asb for (i = 0; i < nvids; i++) {
c1c61f44e88f4c8c155272ee56d868043146096asb (*vidspp)[i] = data[i] & 0xFFFF;
c1c61f44e88f4c8c155272ee56d868043146096asb DBG2(vgenp, NULL, " %d ", (*vidspp)[i]);
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb DBG2(vgenp, NULL, "\n");
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb *nvidsp = nvids;
c1c61f44e88f4c8c155272ee56d868043146096asb}
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb/*
c1c61f44e88f4c8c155272ee56d868043146096asb * Create a vlan id hash table for the given port.
c1c61f44e88f4c8c155272ee56d868043146096asb */
c1c61f44e88f4c8c155272ee56d868043146096asbstatic void
c1c61f44e88f4c8c155272ee56d868043146096asbvgen_vlan_create_hash(vgen_port_t *portp)
c1c61f44e88f4c8c155272ee56d868043146096asb{
c1c61f44e88f4c8c155272ee56d868043146096asb char hashname[MAXNAMELEN];
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb (void) snprintf(hashname, MAXNAMELEN, "port%d-vlan-hash",
c1c61f44e88f4c8c155272ee56d868043146096asb portp->port_num);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb portp->vlan_nchains = vgen_vlan_nchains;
c1c61f44e88f4c8c155272ee56d868043146096asb portp->vlan_hashp = mod_hash_create_idhash(hashname,
c1c61f44e88f4c8c155272ee56d868043146096asb portp->vlan_nchains, mod_hash_null_valdtor);
c1c61f44e88f4c8c155272ee56d868043146096asb}
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb/*
c1c61f44e88f4c8c155272ee56d868043146096asb * Destroy the vlan id hash table in the given port.
c1c61f44e88f4c8c155272ee56d868043146096asb */
c1c61f44e88f4c8c155272ee56d868043146096asbstatic void
c1c61f44e88f4c8c155272ee56d868043146096asbvgen_vlan_destroy_hash(vgen_port_t *portp)
c1c61f44e88f4c8c155272ee56d868043146096asb{
c1c61f44e88f4c8c155272ee56d868043146096asb if (portp->vlan_hashp != NULL) {
c1c61f44e88f4c8c155272ee56d868043146096asb mod_hash_destroy_hash(portp->vlan_hashp);
c1c61f44e88f4c8c155272ee56d868043146096asb portp->vlan_hashp = NULL;
c1c61f44e88f4c8c155272ee56d868043146096asb portp->vlan_nchains = 0;
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb}
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb/*
c1c61f44e88f4c8c155272ee56d868043146096asb * Add a port to the vlans specified in its port properites.
c1c61f44e88f4c8c155272ee56d868043146096asb */
c1c61f44e88f4c8c155272ee56d868043146096asbstatic void
c1c61f44e88f4c8c155272ee56d868043146096asbvgen_vlan_add_ids(vgen_port_t *portp)
c1c61f44e88f4c8c155272ee56d868043146096asb{
c1c61f44e88f4c8c155272ee56d868043146096asb int rv;
c1c61f44e88f4c8c155272ee56d868043146096asb int i;
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb rv = mod_hash_insert(portp->vlan_hashp,
c1c61f44e88f4c8c155272ee56d868043146096asb (mod_hash_key_t)VLAN_ID_KEY(portp->pvid),
c1c61f44e88f4c8c155272ee56d868043146096asb (mod_hash_val_t)B_TRUE);
c1c61f44e88f4c8c155272ee56d868043146096asb ASSERT(rv == 0);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb for (i = 0; i < portp->nvids; i++) {
c1c61f44e88f4c8c155272ee56d868043146096asb rv = mod_hash_insert(portp->vlan_hashp,
c1c61f44e88f4c8c155272ee56d868043146096asb (mod_hash_key_t)VLAN_ID_KEY(portp->vids[i]),
c1c61f44e88f4c8c155272ee56d868043146096asb (mod_hash_val_t)B_TRUE);
c1c61f44e88f4c8c155272ee56d868043146096asb ASSERT(rv == 0);
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb}
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb/*
c1c61f44e88f4c8c155272ee56d868043146096asb * Remove a port from the vlans it has been assigned to.
c1c61f44e88f4c8c155272ee56d868043146096asb */
c1c61f44e88f4c8c155272ee56d868043146096asbstatic void
c1c61f44e88f4c8c155272ee56d868043146096asbvgen_vlan_remove_ids(vgen_port_t *portp)
c1c61f44e88f4c8c155272ee56d868043146096asb{
c1c61f44e88f4c8c155272ee56d868043146096asb int rv;
c1c61f44e88f4c8c155272ee56d868043146096asb int i;
c1c61f44e88f4c8c155272ee56d868043146096asb mod_hash_val_t vp;
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb rv = mod_hash_remove(portp->vlan_hashp,
c1c61f44e88f4c8c155272ee56d868043146096asb (mod_hash_key_t)VLAN_ID_KEY(portp->pvid),
c1c61f44e88f4c8c155272ee56d868043146096asb (mod_hash_val_t *)&vp);
c1c61f44e88f4c8c155272ee56d868043146096asb ASSERT(rv == 0);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb for (i = 0; i < portp->nvids; i++) {
c1c61f44e88f4c8c155272ee56d868043146096asb rv = mod_hash_remove(portp->vlan_hashp,
c1c61f44e88f4c8c155272ee56d868043146096asb (mod_hash_key_t)VLAN_ID_KEY(portp->vids[i]),
c1c61f44e88f4c8c155272ee56d868043146096asb (mod_hash_val_t *)&vp);
c1c61f44e88f4c8c155272ee56d868043146096asb ASSERT(rv == 0);
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb}
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb/*
c1c61f44e88f4c8c155272ee56d868043146096asb * Lookup the vlan id of the given tx frame. If it is a vlan-tagged frame,
c1c61f44e88f4c8c155272ee56d868043146096asb * then the vlan-id is available in the tag; otherwise, its vlan id is
c1c61f44e88f4c8c155272ee56d868043146096asb * implicitly obtained from the port-vlan-id of the vnet device.
c1c61f44e88f4c8c155272ee56d868043146096asb * The vlan id determined is returned in vidp.
c1c61f44e88f4c8c155272ee56d868043146096asb * Returns: B_TRUE if it is a tagged frame; B_FALSE if it is untagged.
c1c61f44e88f4c8c155272ee56d868043146096asb */
c1c61f44e88f4c8c155272ee56d868043146096asbstatic boolean_t
c1c61f44e88f4c8c155272ee56d868043146096asbvgen_frame_lookup_vid(vnet_t *vnetp, struct ether_header *ehp, uint16_t *vidp)
c1c61f44e88f4c8c155272ee56d868043146096asb{
c1c61f44e88f4c8c155272ee56d868043146096asb struct ether_vlan_header *evhp;
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /* If it's a tagged frame, get the vlan id from vlan header */
c1c61f44e88f4c8c155272ee56d868043146096asb if (ehp->ether_type == ETHERTYPE_VLAN) {
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb evhp = (struct ether_vlan_header *)ehp;
c1c61f44e88f4c8c155272ee56d868043146096asb *vidp = VLAN_ID(ntohs(evhp->ether_tci));
c1c61f44e88f4c8c155272ee56d868043146096asb return (B_TRUE);
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /* Untagged frame, vlan-id is the pvid of vnet device */
c1c61f44e88f4c8c155272ee56d868043146096asb *vidp = vnetp->pvid;
c1c61f44e88f4c8c155272ee56d868043146096asb return (B_FALSE);
c1c61f44e88f4c8c155272ee56d868043146096asb}
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb/*
c1c61f44e88f4c8c155272ee56d868043146096asb * Find the given vlan id in the hash table.
c1c61f44e88f4c8c155272ee56d868043146096asb * Return: B_TRUE if the id is found; B_FALSE if not found.
c1c61f44e88f4c8c155272ee56d868043146096asb */
c1c61f44e88f4c8c155272ee56d868043146096asbstatic boolean_t
c1c61f44e88f4c8c155272ee56d868043146096asbvgen_vlan_lookup(mod_hash_t *vlan_hashp, uint16_t vid)
c1c61f44e88f4c8c155272ee56d868043146096asb{
c1c61f44e88f4c8c155272ee56d868043146096asb int rv;
c1c61f44e88f4c8c155272ee56d868043146096asb mod_hash_val_t vp;
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb rv = mod_hash_find(vlan_hashp, VLAN_ID_KEY(vid), (mod_hash_val_t *)&vp);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb if (rv != 0)
c1c61f44e88f4c8c155272ee56d868043146096asb return (B_FALSE);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb return (B_TRUE);
c1c61f44e88f4c8c155272ee56d868043146096asb}
c1c61f44e88f4c8c155272ee56d868043146096asb
f0ca1d9a12d54d304791bc74525e2010ca924726sb/*
f0ca1d9a12d54d304791bc74525e2010ca924726sb * This function reads "priority-ether-types" property from md. This property
f0ca1d9a12d54d304791bc74525e2010ca924726sb * is used to enable support for priority frames. Applications which need
f0ca1d9a12d54d304791bc74525e2010ca924726sb * guaranteed and timely delivery of certain high priority frames to/from
f0ca1d9a12d54d304791bc74525e2010ca924726sb * a vnet or vsw within ldoms, should configure this property by providing
f0ca1d9a12d54d304791bc74525e2010ca924726sb * the ether type(s) for which the priority facility is needed.
f0ca1d9a12d54d304791bc74525e2010ca924726sb * Normal data frames are delivered over a ldc channel using the descriptor
f0ca1d9a12d54d304791bc74525e2010ca924726sb * ring mechanism which is constrained by factors such as descriptor ring size,
f0ca1d9a12d54d304791bc74525e2010ca924726sb * the rate at which the ring is processed at the peer ldc end point, etc.
f0ca1d9a12d54d304791bc74525e2010ca924726sb * The priority mechanism provides an Out-Of-Band path to send/receive frames
f0ca1d9a12d54d304791bc74525e2010ca924726sb * as raw pkt data (VIO_PKT_DATA) messages over the channel, avoiding the
f0ca1d9a12d54d304791bc74525e2010ca924726sb * descriptor ring path and enables a more reliable and timely delivery of
f0ca1d9a12d54d304791bc74525e2010ca924726sb * frames to the peer.
f0ca1d9a12d54d304791bc74525e2010ca924726sb */
f0ca1d9a12d54d304791bc74525e2010ca924726sbstatic void
f0ca1d9a12d54d304791bc74525e2010ca924726sbvgen_read_pri_eth_types(vgen_t *vgenp, md_t *mdp, mde_cookie_t node)
f0ca1d9a12d54d304791bc74525e2010ca924726sb{
f0ca1d9a12d54d304791bc74525e2010ca924726sb int rv;
f0ca1d9a12d54d304791bc74525e2010ca924726sb uint16_t *types;
f0ca1d9a12d54d304791bc74525e2010ca924726sb uint64_t *data;
f0ca1d9a12d54d304791bc74525e2010ca924726sb int size;
f0ca1d9a12d54d304791bc74525e2010ca924726sb int i;
f0ca1d9a12d54d304791bc74525e2010ca924726sb size_t mblk_sz;
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb rv = md_get_prop_data(mdp, node, pri_types_propname,
f0ca1d9a12d54d304791bc74525e2010ca924726sb (uint8_t **)&data, &size);
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (rv != 0) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb /*
f0ca1d9a12d54d304791bc74525e2010ca924726sb * Property may not exist if we are running pre-ldoms1.1 f/w.
f0ca1d9a12d54d304791bc74525e2010ca924726sb * Check if 'vgen_pri_eth_type' has been set in that case.
f0ca1d9a12d54d304791bc74525e2010ca924726sb */
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (vgen_pri_eth_type != 0) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb size = sizeof (vgen_pri_eth_type);
f0ca1d9a12d54d304791bc74525e2010ca924726sb data = &vgen_pri_eth_type;
f0ca1d9a12d54d304791bc74525e2010ca924726sb } else {
678453a8ed49104d8adad58f3ba591bdc39883e8speer DBG2(vgenp, NULL,
f0ca1d9a12d54d304791bc74525e2010ca924726sb "prop(%s) not found", pri_types_propname);
f0ca1d9a12d54d304791bc74525e2010ca924726sb size = 0;
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (size == 0) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb vgenp->pri_num_types = 0;
f0ca1d9a12d54d304791bc74525e2010ca924726sb return;
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb /*
f0ca1d9a12d54d304791bc74525e2010ca924726sb * we have some priority-ether-types defined;
f0ca1d9a12d54d304791bc74525e2010ca924726sb * allocate a table of these types and also
f0ca1d9a12d54d304791bc74525e2010ca924726sb * allocate a pool of mblks to transmit these
f0ca1d9a12d54d304791bc74525e2010ca924726sb * priority packets.
f0ca1d9a12d54d304791bc74525e2010ca924726sb */
f0ca1d9a12d54d304791bc74525e2010ca924726sb size /= sizeof (uint64_t);
f0ca1d9a12d54d304791bc74525e2010ca924726sb vgenp->pri_num_types = size;
f0ca1d9a12d54d304791bc74525e2010ca924726sb vgenp->pri_types = kmem_zalloc(size * sizeof (uint16_t), KM_SLEEP);
f0ca1d9a12d54d304791bc74525e2010ca924726sb for (i = 0, types = vgenp->pri_types; i < size; i++) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb types[i] = data[i] & 0xFFFF;
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
c1c61f44e88f4c8c155272ee56d868043146096asb mblk_sz = (VIO_PKT_DATA_HDRSIZE + vgenp->max_frame_size + 7) & ~7;
f0ca1d9a12d54d304791bc74525e2010ca924726sb (void) vio_create_mblks(vgen_pri_tx_nmblks, mblk_sz,
f0ca1d9a12d54d304791bc74525e2010ca924726sb &vgenp->pri_tx_vmp);
f0ca1d9a12d54d304791bc74525e2010ca924726sb}
f0ca1d9a12d54d304791bc74525e2010ca924726sb
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatnastatic void
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatnavgen_mtu_read(vgen_t *vgenp, md_t *mdp, mde_cookie_t node, uint32_t *mtu)
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna{
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna int rv;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna uint64_t val;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna char *mtu_propname;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna mtu_propname = vgen_mtu_propname;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna rv = md_get_prop_val(mdp, node, mtu_propname, &val);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna if (rv != 0) {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna DWARN(vgenp, NULL, "prop(%s) not found", mtu_propname);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna *mtu = vnet_ethermtu;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna } else {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna *mtu = val & 0xFFFF;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna DBG2(vgenp, NULL, "%s(%d): (%d)\n", mtu_propname,
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna vgenp->instance, *mtu);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna }
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna}
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnastatic void
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnavgen_linkprop_read(vgen_t *vgenp, md_t *mdp, mde_cookie_t node,
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna boolean_t *pls)
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna{
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna int rv;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna uint64_t val;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna char *linkpropname;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna linkpropname = vgen_linkprop_propname;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna rv = md_get_prop_val(mdp, node, linkpropname, &val);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (rv != 0) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna DWARN(vgenp, NULL, "prop(%s) not found", linkpropname);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna *pls = B_FALSE;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna } else {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna *pls = (val & 0x1) ? B_TRUE : B_FALSE;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna DBG2(vgenp, NULL, "%s(%d): (%d)\n", linkpropname,
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vgenp->instance, *pls);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna }
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna}
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* register with MD event generator */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_mdeg_reg(vgen_t *vgenp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mdeg_prop_spec_t *pspecp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mdeg_node_spec_t *parentp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint_t templatesz;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int rv;
c1c61f44e88f4c8c155272ee56d868043146096asb mdeg_handle_t dev_hdl = NULL;
c1c61f44e88f4c8c155272ee56d868043146096asb mdeg_handle_t port_hdl = NULL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo templatesz = sizeof (vgen_prop_template);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo pspecp = kmem_zalloc(templatesz, KM_NOSLEEP);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (pspecp == NULL) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo parentp = kmem_zalloc(sizeof (mdeg_node_spec_t), KM_NOSLEEP);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (parentp == NULL) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kmem_free(pspecp, templatesz);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bcopy(vgen_prop_template, pspecp, templatesz);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * NOTE: The instance here refers to the value of "reg" property and
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * not the dev_info instance (ddi_get_instance()) of vnet.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
c1c61f44e88f4c8c155272ee56d868043146096asb VGEN_SET_MDEG_PROP_INST(pspecp, vgenp->regprop);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo parentp->namep = "virtual-device";
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo parentp->specp = pspecp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* save parentp in vgen_t */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp->mdeg_parentp = parentp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
c1c61f44e88f4c8c155272ee56d868043146096asb /*
c1c61f44e88f4c8c155272ee56d868043146096asb * Register an interest in 'virtual-device' nodes with a
c1c61f44e88f4c8c155272ee56d868043146096asb * 'name' property of 'network'
c1c61f44e88f4c8c155272ee56d868043146096asb */
c1c61f44e88f4c8c155272ee56d868043146096asb rv = mdeg_register(parentp, &vdev_match, vgen_mdeg_cb, vgenp, &dev_hdl);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rv != MDEG_SUCCESS) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DERR(vgenp, NULL, "mdeg_register failed\n");
c1c61f44e88f4c8c155272ee56d868043146096asb goto mdeg_reg_fail;
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /* Register an interest in 'port' nodes */
c1c61f44e88f4c8c155272ee56d868043146096asb rv = mdeg_register(parentp, &vport_match, vgen_mdeg_port_cb, vgenp,
c1c61f44e88f4c8c155272ee56d868043146096asb &port_hdl);
c1c61f44e88f4c8c155272ee56d868043146096asb if (rv != MDEG_SUCCESS) {
c1c61f44e88f4c8c155272ee56d868043146096asb DERR(vgenp, NULL, "mdeg_register failed\n");
c1c61f44e88f4c8c155272ee56d868043146096asb goto mdeg_reg_fail;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* save mdeg handle in vgen_t */
c1c61f44e88f4c8c155272ee56d868043146096asb vgenp->mdeg_dev_hdl = dev_hdl;
c1c61f44e88f4c8c155272ee56d868043146096asb vgenp->mdeg_port_hdl = port_hdl;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_SUCCESS);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asbmdeg_reg_fail:
c1c61f44e88f4c8c155272ee56d868043146096asb if (dev_hdl != NULL) {
c1c61f44e88f4c8c155272ee56d868043146096asb (void) mdeg_unregister(dev_hdl);
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb KMEM_FREE(parentp);
c1c61f44e88f4c8c155272ee56d868043146096asb kmem_free(pspecp, templatesz);
c1c61f44e88f4c8c155272ee56d868043146096asb vgenp->mdeg_parentp = NULL;
c1c61f44e88f4c8c155272ee56d868043146096asb return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* unregister with MD event generator */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_mdeg_unreg(vgen_t *vgenp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna if (vgenp->mdeg_dev_hdl != NULL) {
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna (void) mdeg_unregister(vgenp->mdeg_dev_hdl);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna vgenp->mdeg_dev_hdl = NULL;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna }
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna if (vgenp->mdeg_port_hdl != NULL) {
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna (void) mdeg_unregister(vgenp->mdeg_port_hdl);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna vgenp->mdeg_port_hdl = NULL;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna }
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna if (vgenp->mdeg_parentp != NULL) {
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna kmem_free(vgenp->mdeg_parentp->specp,
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna sizeof (vgen_prop_template));
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna KMEM_FREE(vgenp->mdeg_parentp);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna vgenp->mdeg_parentp = NULL;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
c1c61f44e88f4c8c155272ee56d868043146096asb/* mdeg callback function for the port node */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
c1c61f44e88f4c8c155272ee56d868043146096asbvgen_mdeg_port_cb(void *cb_argp, mdeg_result_t *resp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int idx;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int vsw_idx = -1;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint64_t val;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_t *vgenp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((resp == NULL) || (cb_argp == NULL)) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (MDEG_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp = (vgen_t *)cb_argp;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, NULL, "enter\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_enter(&vgenp->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, NULL, "ports: removed(%x), "
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram "added(%x), updated(%x)\n", resp->removed.nelem,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram resp->added.nelem, resp->match_curr.nelem);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (idx = 0; idx < resp->removed.nelem; idx++) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void) vgen_remove_port(vgenp, resp->removed.mdp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo resp->removed.mdep[idx]);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vgenp->vsw_portp == NULL) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * find vsw_port and add it first, because other ports need
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * this when adding fdb entry (see vgen_port_init()).
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (idx = 0; idx < resp->added.nelem; idx++) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (!(md_get_prop_val(resp->added.mdp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo resp->added.mdep[idx], swport_propname, &val))) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (val == 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * This port is connected to the
c1c61f44e88f4c8c155272ee56d868043146096asb * vsw on service domain.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vsw_idx = idx;
ca7ee4f955b3b075d0cc91d95f3515ee04c16a79zk if (vgen_add_port(vgenp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo resp->added.mdp,
ca7ee4f955b3b075d0cc91d95f3515ee04c16a79zk resp->added.mdep[idx]) !=
ca7ee4f955b3b075d0cc91d95f3515ee04c16a79zk DDI_SUCCESS) {
ca7ee4f955b3b075d0cc91d95f3515ee04c16a79zk cmn_err(CE_NOTE, "vnet%d Could "
ca7ee4f955b3b075d0cc91d95f3515ee04c16a79zk "not initialize virtual "
ca7ee4f955b3b075d0cc91d95f3515ee04c16a79zk "switch port.",
678453a8ed49104d8adad58f3ba591bdc39883e8speer vgenp->instance);
ca7ee4f955b3b075d0cc91d95f3515ee04c16a79zk mutex_exit(&vgenp->lock);
ca7ee4f955b3b075d0cc91d95f3515ee04c16a79zk return (MDEG_FAILURE);
ca7ee4f955b3b075d0cc91d95f3515ee04c16a79zk }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
c198d18e90b390e955c8766a91af6e2db1fccd57zk if (vsw_idx == -1) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, NULL, "can't find vsw_port\n");
ca7ee4f955b3b075d0cc91d95f3515ee04c16a79zk mutex_exit(&vgenp->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (MDEG_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (idx = 0; idx < resp->added.nelem; idx++) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((vsw_idx != -1) && (vsw_idx == idx)) /* skip vsw_port */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo continue;
ca7ee4f955b3b075d0cc91d95f3515ee04c16a79zk
ca7ee4f955b3b075d0cc91d95f3515ee04c16a79zk /* If this port can't be added just skip it. */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void) vgen_add_port(vgenp, resp->added.mdp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo resp->added.mdep[idx]);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (idx = 0; idx < resp->match_curr.nelem; idx++) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void) vgen_update_port(vgenp, resp->match_curr.mdp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo resp->match_curr.mdep[idx],
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo resp->match_prev.mdp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo resp->match_prev.mdep[idx]);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&vgenp->lock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, NULL, "exit\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (MDEG_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
c1c61f44e88f4c8c155272ee56d868043146096asb/* mdeg callback function for the vnet node */
c1c61f44e88f4c8c155272ee56d868043146096asbstatic int
c1c61f44e88f4c8c155272ee56d868043146096asbvgen_mdeg_cb(void *cb_argp, mdeg_result_t *resp)
c1c61f44e88f4c8c155272ee56d868043146096asb{
c1c61f44e88f4c8c155272ee56d868043146096asb vgen_t *vgenp;
c1c61f44e88f4c8c155272ee56d868043146096asb vnet_t *vnetp;
c1c61f44e88f4c8c155272ee56d868043146096asb md_t *mdp;
c1c61f44e88f4c8c155272ee56d868043146096asb mde_cookie_t node;
c1c61f44e88f4c8c155272ee56d868043146096asb uint64_t inst;
c1c61f44e88f4c8c155272ee56d868043146096asb char *node_name = NULL;
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb if ((resp == NULL) || (cb_argp == NULL)) {
c1c61f44e88f4c8c155272ee56d868043146096asb return (MDEG_FAILURE);
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb vgenp = (vgen_t *)cb_argp;
c1c61f44e88f4c8c155272ee56d868043146096asb vnetp = vgenp->vnetp;
c1c61f44e88f4c8c155272ee56d868043146096asb
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG DBG1(vgenp, NULL, "added %d : removed %d : curr matched %d"
c1c61f44e88f4c8c155272ee56d868043146096asb " : prev matched %d", resp->added.nelem, resp->removed.nelem,
c1c61f44e88f4c8c155272ee56d868043146096asb resp->match_curr.nelem, resp->match_prev.nelem);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb mutex_enter(&vgenp->lock);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /*
c1c61f44e88f4c8c155272ee56d868043146096asb * We get an initial callback for this node as 'added' after
c1c61f44e88f4c8c155272ee56d868043146096asb * registering with mdeg. Note that we would have already gathered
c1c61f44e88f4c8c155272ee56d868043146096asb * information about this vnet node by walking MD earlier during attach
c1c61f44e88f4c8c155272ee56d868043146096asb * (in vgen_read_mdprops()). So, there is a window where the properties
c1c61f44e88f4c8c155272ee56d868043146096asb * of this node might have changed when we get this initial 'added'
c1c61f44e88f4c8c155272ee56d868043146096asb * callback. We handle this as if an update occured and invoke the same
c1c61f44e88f4c8c155272ee56d868043146096asb * function which handles updates to the properties of this vnet-node
c1c61f44e88f4c8c155272ee56d868043146096asb * if any. A non-zero 'match' value indicates that the MD has been
c1c61f44e88f4c8c155272ee56d868043146096asb * updated and that a 'network' node is present which may or may not
c1c61f44e88f4c8c155272ee56d868043146096asb * have been updated. It is up to the clients to examine their own
c1c61f44e88f4c8c155272ee56d868043146096asb * nodes and determine if they have changed.
c1c61f44e88f4c8c155272ee56d868043146096asb */
c1c61f44e88f4c8c155272ee56d868043146096asb if (resp->added.nelem != 0) {
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb if (resp->added.nelem != 1) {
c1c61f44e88f4c8c155272ee56d868043146096asb cmn_err(CE_NOTE, "!vnet%d: number of nodes added "
c1c61f44e88f4c8c155272ee56d868043146096asb "invalid: %d\n", vnetp->instance,
c1c61f44e88f4c8c155272ee56d868043146096asb resp->added.nelem);
c1c61f44e88f4c8c155272ee56d868043146096asb goto vgen_mdeg_cb_err;
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb mdp = resp->added.mdp;
c1c61f44e88f4c8c155272ee56d868043146096asb node = resp->added.mdep[0];
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb } else if (resp->match_curr.nelem != 0) {
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb if (resp->match_curr.nelem != 1) {
c1c61f44e88f4c8c155272ee56d868043146096asb cmn_err(CE_NOTE, "!vnet%d: number of nodes updated "
c1c61f44e88f4c8c155272ee56d868043146096asb "invalid: %d\n", vnetp->instance,
c1c61f44e88f4c8c155272ee56d868043146096asb resp->match_curr.nelem);
c1c61f44e88f4c8c155272ee56d868043146096asb goto vgen_mdeg_cb_err;
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb mdp = resp->match_curr.mdp;
c1c61f44e88f4c8c155272ee56d868043146096asb node = resp->match_curr.mdep[0];
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb } else {
c1c61f44e88f4c8c155272ee56d868043146096asb goto vgen_mdeg_cb_err;
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /* Validate name and instance */
c1c61f44e88f4c8c155272ee56d868043146096asb if (md_get_prop_str(mdp, node, "name", &node_name) != 0) {
c1c61f44e88f4c8c155272ee56d868043146096asb DERR(vgenp, NULL, "unable to get node name\n");
c1c61f44e88f4c8c155272ee56d868043146096asb goto vgen_mdeg_cb_err;
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /* is this a virtual-network device? */
c1c61f44e88f4c8c155272ee56d868043146096asb if (strcmp(node_name, vnet_propname) != 0) {
c1c61f44e88f4c8c155272ee56d868043146096asb DERR(vgenp, NULL, "%s: Invalid node name: %s\n", node_name);
c1c61f44e88f4c8c155272ee56d868043146096asb goto vgen_mdeg_cb_err;
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb if (md_get_prop_val(mdp, node, "cfg-handle", &inst)) {
c1c61f44e88f4c8c155272ee56d868043146096asb DERR(vgenp, NULL, "prop(cfg-handle) not found\n");
c1c61f44e88f4c8c155272ee56d868043146096asb goto vgen_mdeg_cb_err;
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb
678453a8ed49104d8adad58f3ba591bdc39883e8speer /* is this the right instance of vnet? */
c1c61f44e88f4c8c155272ee56d868043146096asb if (inst != vgenp->regprop) {
c1c61f44e88f4c8c155272ee56d868043146096asb DERR(vgenp, NULL, "Invalid cfg-handle: %lx\n", inst);
c1c61f44e88f4c8c155272ee56d868043146096asb goto vgen_mdeg_cb_err;
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb vgen_update_md_prop(vgenp, mdp, node);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb mutex_exit(&vgenp->lock);
c1c61f44e88f4c8c155272ee56d868043146096asb return (MDEG_SUCCESS);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asbvgen_mdeg_cb_err:
c1c61f44e88f4c8c155272ee56d868043146096asb mutex_exit(&vgenp->lock);
c1c61f44e88f4c8c155272ee56d868043146096asb return (MDEG_FAILURE);
c1c61f44e88f4c8c155272ee56d868043146096asb}
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb/*
c1c61f44e88f4c8c155272ee56d868043146096asb * Check to see if the relevant properties in the specified node have
c1c61f44e88f4c8c155272ee56d868043146096asb * changed, and if so take the appropriate action.
c1c61f44e88f4c8c155272ee56d868043146096asb */
c1c61f44e88f4c8c155272ee56d868043146096asbstatic void
c1c61f44e88f4c8c155272ee56d868043146096asbvgen_update_md_prop(vgen_t *vgenp, md_t *mdp, mde_cookie_t mdex)
c1c61f44e88f4c8c155272ee56d868043146096asb{
c1c61f44e88f4c8c155272ee56d868043146096asb uint16_t pvid;
c1c61f44e88f4c8c155272ee56d868043146096asb uint16_t *vids;
c1c61f44e88f4c8c155272ee56d868043146096asb uint16_t nvids;
c1c61f44e88f4c8c155272ee56d868043146096asb vnet_t *vnetp = vgenp->vnetp;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna uint32_t mtu;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna boolean_t pls_update;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna enum { MD_init = 0x1,
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna MD_vlans = 0x2,
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna MD_mtu = 0x4,
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna MD_pls = 0x8 } updated;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna int rv;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna updated = MD_init;
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /* Read the vlan ids */
c1c61f44e88f4c8c155272ee56d868043146096asb vgen_vlan_read_ids(vgenp, VGEN_LOCAL, mdp, mdex, &pvid, &vids,
c1c61f44e88f4c8c155272ee56d868043146096asb &nvids, NULL);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /* Determine if there are any vlan id updates */
c1c61f44e88f4c8c155272ee56d868043146096asb if ((pvid != vnetp->pvid) || /* pvid changed? */
c1c61f44e88f4c8c155272ee56d868043146096asb (nvids != vnetp->nvids) || /* # of vids changed? */
c1c61f44e88f4c8c155272ee56d868043146096asb ((nvids != 0) && (vnetp->nvids != 0) && /* vids changed? */
c1c61f44e88f4c8c155272ee56d868043146096asb bcmp(vids, vnetp->vids, sizeof (uint16_t) * nvids))) {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna updated |= MD_vlans;
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna /* Read mtu */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna vgen_mtu_read(vgenp, mdp, mdex, &mtu);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna if (mtu != vnetp->mtu) {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna if (mtu >= ETHERMTU && mtu <= VNET_MAX_MTU) {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna updated |= MD_mtu;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna } else {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna cmn_err(CE_NOTE, "!vnet%d: Unable to process mtu update"
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna " as the specified value:%d is invalid\n",
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna vnetp->instance, mtu);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna }
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna }
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna /*
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * Read the 'linkprop' property.
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vgen_linkprop_read(vgenp, mdp, mdex, &pls_update);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (pls_update != vnetp->pls_update) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna updated |= MD_pls;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna }
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna /* Now process the updated props */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna if (updated & MD_vlans) {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna /* save the new vlan ids */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna vnetp->pvid = pvid;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna if (vnetp->nvids != 0) {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna kmem_free(vnetp->vids,
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna sizeof (uint16_t) * vnetp->nvids);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna vnetp->nvids = 0;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna }
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna if (nvids != 0) {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna vnetp->nvids = nvids;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna vnetp->vids = vids;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna }
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna /* reset vlan-unaware peers (ver < 1.3) and restart handshake */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna vgen_reset_vlan_unaware_ports(vgenp);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna } else {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
c1c61f44e88f4c8c155272ee56d868043146096asb if (nvids != 0) {
c1c61f44e88f4c8c155272ee56d868043146096asb kmem_free(vids, sizeof (uint16_t) * nvids);
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna if (updated & MD_mtu) {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna DBG2(vgenp, NULL, "curr_mtu(%d) new_mtu(%d)\n",
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna vnetp->mtu, mtu);
c1c61f44e88f4c8c155272ee56d868043146096asb
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna rv = vnet_mtu_update(vnetp, mtu);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna if (rv == 0) {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna vgenp->max_frame_size = mtu +
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna sizeof (struct ether_header) + VLAN_TAGSZ;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna }
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna }
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (updated & MD_pls) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna /* enable/disable physical link state updates */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vnetp->pls_update = pls_update;
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG mutex_exit(&vgenp->lock);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna /* reset vsw-port to re-negotiate with the updated prop. */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vgen_reset_vsw_port(vgenp);
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG mutex_enter(&vgenp->lock);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna }
c1c61f44e88f4c8c155272ee56d868043146096asb}
c1c61f44e88f4c8c155272ee56d868043146096asb
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* add a new port to the device */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_add_port(vgen_t *vgenp, md_t *mdp, mde_cookie_t mdex)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
c1c61f44e88f4c8c155272ee56d868043146096asb vgen_port_t *portp;
c1c61f44e88f4c8c155272ee56d868043146096asb int rv;
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb portp = kmem_zalloc(sizeof (vgen_port_t), KM_SLEEP);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb rv = vgen_port_read_props(portp, vgenp, mdp, mdex);
c1c61f44e88f4c8c155272ee56d868043146096asb if (rv != DDI_SUCCESS) {
c1c61f44e88f4c8c155272ee56d868043146096asb KMEM_FREE(portp);
c1c61f44e88f4c8c155272ee56d868043146096asb return (DDI_FAILURE);
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb rv = vgen_port_attach(portp);
c1c61f44e88f4c8c155272ee56d868043146096asb if (rv != DDI_SUCCESS) {
c1c61f44e88f4c8c155272ee56d868043146096asb return (DDI_FAILURE);
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb return (DDI_SUCCESS);
c1c61f44e88f4c8c155272ee56d868043146096asb}
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb/* read properties of the port from its md node */
c1c61f44e88f4c8c155272ee56d868043146096asbstatic int
c1c61f44e88f4c8c155272ee56d868043146096asbvgen_port_read_props(vgen_port_t *portp, vgen_t *vgenp, md_t *mdp,
c1c61f44e88f4c8c155272ee56d868043146096asb mde_cookie_t mdex)
c1c61f44e88f4c8c155272ee56d868043146096asb{
c1c61f44e88f4c8c155272ee56d868043146096asb uint64_t port_num;
c1c61f44e88f4c8c155272ee56d868043146096asb uint64_t *ldc_ids;
c1c61f44e88f4c8c155272ee56d868043146096asb uint64_t macaddr;
c1c61f44e88f4c8c155272ee56d868043146096asb uint64_t val;
c1c61f44e88f4c8c155272ee56d868043146096asb int num_ldcs;
c1c61f44e88f4c8c155272ee56d868043146096asb int i;
c1c61f44e88f4c8c155272ee56d868043146096asb int addrsz;
c1c61f44e88f4c8c155272ee56d868043146096asb int num_nodes = 0;
c1c61f44e88f4c8c155272ee56d868043146096asb int listsz = 0;
c1c61f44e88f4c8c155272ee56d868043146096asb mde_cookie_t *listp = NULL;
c1c61f44e88f4c8c155272ee56d868043146096asb uint8_t *addrp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo struct ether_addr ea;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* read "id" property to get the port number */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (md_get_prop_val(mdp, mdex, id_propname, &port_num)) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, NULL, "prop(%s) not found\n", id_propname);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Find the channel endpoint node(s) under this port node.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((num_nodes = md_node_count(mdp)) <= 0) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, NULL, "invalid number of nodes found (%d)",
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram num_nodes);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* allocate space for node list */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo listsz = num_nodes * sizeof (mde_cookie_t);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo listp = kmem_zalloc(listsz, KM_NOSLEEP);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (listp == NULL)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo num_ldcs = md_scan_dag(mdp, mdex,
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram md_find_name(mdp, channel_propname),
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram md_find_name(mdp, "fwd"), listp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (num_ldcs <= 0) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, NULL, "can't find %s nodes", channel_propname);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kmem_free(listp, listsz);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG2(vgenp, NULL, "num_ldcs %d", num_ldcs);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldc_ids = kmem_zalloc(num_ldcs * sizeof (uint64_t), KM_NOSLEEP);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ldc_ids == NULL) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kmem_free(listp, listsz);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (i = 0; i < num_ldcs; i++) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* read channel ids */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (md_get_prop_val(mdp, listp[i], id_propname, &ldc_ids[i])) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, NULL, "prop(%s) not found\n",
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram id_propname);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kmem_free(listp, listsz);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kmem_free(ldc_ids, num_ldcs * sizeof (uint64_t));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG2(vgenp, NULL, "ldc_id 0x%llx", ldc_ids[i]);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kmem_free(listp, listsz);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (md_get_prop_data(mdp, mdex, rmacaddr_propname, &addrp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo &addrsz)) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, NULL, "prop(%s) not found\n", rmacaddr_propname);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kmem_free(ldc_ids, num_ldcs * sizeof (uint64_t));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (addrsz < ETHERADDRL) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, NULL, "invalid address size (%d)\n", addrsz);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kmem_free(ldc_ids, num_ldcs * sizeof (uint64_t));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo macaddr = *((uint64_t *)addrp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG2(vgenp, NULL, "remote mac address 0x%llx\n", macaddr);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (i = ETHERADDRL - 1; i >= 0; i--) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ea.ether_addr_octet[i] = macaddr & 0xFF;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo macaddr >>= 8;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (!(md_get_prop_val(mdp, mdex, swport_propname, &val))) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (val == 0) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna /* This port is connected to the vswitch */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna portp->is_vsw_port = B_TRUE;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna } else {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna portp->is_vsw_port = B_FALSE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /* now update all properties into the port */
c1c61f44e88f4c8c155272ee56d868043146096asb portp->vgenp = vgenp;
c1c61f44e88f4c8c155272ee56d868043146096asb portp->port_num = port_num;
c1c61f44e88f4c8c155272ee56d868043146096asb ether_copy(&ea, &portp->macaddr);
c1c61f44e88f4c8c155272ee56d868043146096asb portp->ldc_ids = kmem_zalloc(sizeof (uint64_t) * num_ldcs, KM_SLEEP);
c1c61f44e88f4c8c155272ee56d868043146096asb bcopy(ldc_ids, portp->ldc_ids, sizeof (uint64_t) * num_ldcs);
c1c61f44e88f4c8c155272ee56d868043146096asb portp->num_ldcs = num_ldcs;
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /* read vlan id properties of this port node */
c1c61f44e88f4c8c155272ee56d868043146096asb vgen_vlan_read_ids(portp, VGEN_PEER, mdp, mdex, &portp->pvid,
c1c61f44e88f4c8c155272ee56d868043146096asb &portp->vids, &portp->nvids, NULL);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kmem_free(ldc_ids, num_ldcs * sizeof (uint64_t));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
c1c61f44e88f4c8c155272ee56d868043146096asb return (DDI_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* remove a port from the device */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_remove_port(vgen_t *vgenp, md_t *mdp, mde_cookie_t mdex)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint64_t port_num;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_port_t *portp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_portlist_t *plistp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* read "id" property to get the port number */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (md_get_prop_val(mdp, mdex, id_propname, &port_num)) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, NULL, "prop(%s) not found\n", id_propname);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo plistp = &(vgenp->vgenports);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo WRITE_ENTER(&plistp->rwlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo portp = vgen_port_lookup(plistp, (int)port_num);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (portp == NULL) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, NULL, "can't find port(%lx)\n", port_num);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo RW_EXIT(&plistp->rwlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_port_detach_mdeg(portp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo RW_EXIT(&plistp->rwlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* attach a port to the device based on mdeg data */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
c1c61f44e88f4c8c155272ee56d868043146096asbvgen_port_attach(vgen_port_t *portp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int i;
c1c61f44e88f4c8c155272ee56d868043146096asb vgen_portlist_t *plistp;
c1c61f44e88f4c8c155272ee56d868043146096asb vgen_t *vgenp;
c1c61f44e88f4c8c155272ee56d868043146096asb uint64_t *ldcids;
c1c61f44e88f4c8c155272ee56d868043146096asb uint32_t num_ldcs;
678453a8ed49104d8adad58f3ba591bdc39883e8speer mac_register_t *macp;
678453a8ed49104d8adad58f3ba591bdc39883e8speer vio_net_res_type_t type;
678453a8ed49104d8adad58f3ba591bdc39883e8speer int rv;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
c1c61f44e88f4c8c155272ee56d868043146096asb ASSERT(portp != NULL);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb vgenp = portp->vgenp;
c1c61f44e88f4c8c155272ee56d868043146096asb ldcids = portp->ldc_ids;
c1c61f44e88f4c8c155272ee56d868043146096asb num_ldcs = portp->num_ldcs;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, NULL, "port_num(%d)\n", portp->port_num);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
678453a8ed49104d8adad58f3ba591bdc39883e8speer mutex_init(&portp->lock, NULL, MUTEX_DRIVER, NULL);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rw_init(&portp->ldclist.rwlock, NULL, RW_DRIVER, NULL);
c1c61f44e88f4c8c155272ee56d868043146096asb portp->ldclist.headp = NULL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
c1c61f44e88f4c8c155272ee56d868043146096asb for (i = 0; i < num_ldcs; i++) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG2(vgenp, NULL, "ldcid (%lx)\n", ldcids[i]);
ca7ee4f955b3b075d0cc91d95f3515ee04c16a79zk if (vgen_ldc_attach(portp, ldcids[i]) == DDI_FAILURE) {
ca7ee4f955b3b075d0cc91d95f3515ee04c16a79zk vgen_port_detach(portp);
ca7ee4f955b3b075d0cc91d95f3515ee04c16a79zk return (DDI_FAILURE);
ca7ee4f955b3b075d0cc91d95f3515ee04c16a79zk }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
c1c61f44e88f4c8c155272ee56d868043146096asb /* create vlan id hash table */
c1c61f44e88f4c8c155272ee56d868043146096asb vgen_vlan_create_hash(portp);
c1c61f44e88f4c8c155272ee56d868043146096asb
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (portp->is_vsw_port == B_TRUE) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer /* This port is connected to the switch port */
678453a8ed49104d8adad58f3ba591bdc39883e8speer (void) atomic_swap_32(&portp->use_vsw_port, B_FALSE);
678453a8ed49104d8adad58f3ba591bdc39883e8speer type = VIO_NET_RES_LDC_SERVICE;
678453a8ed49104d8adad58f3ba591bdc39883e8speer } else {
678453a8ed49104d8adad58f3ba591bdc39883e8speer (void) atomic_swap_32(&portp->use_vsw_port, B_TRUE);
678453a8ed49104d8adad58f3ba591bdc39883e8speer type = VIO_NET_RES_LDC_GUEST;
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
678453a8ed49104d8adad58f3ba591bdc39883e8speer if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer vgen_port_detach(portp);
678453a8ed49104d8adad58f3ba591bdc39883e8speer return (DDI_FAILURE);
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
678453a8ed49104d8adad58f3ba591bdc39883e8speer macp->m_driver = portp;
678453a8ed49104d8adad58f3ba591bdc39883e8speer macp->m_dip = vgenp->vnetdip;
678453a8ed49104d8adad58f3ba591bdc39883e8speer macp->m_src_addr = (uint8_t *)&(vgenp->macaddr);
678453a8ed49104d8adad58f3ba591bdc39883e8speer macp->m_callbacks = &vgen_m_callbacks;
678453a8ed49104d8adad58f3ba591bdc39883e8speer macp->m_min_sdu = 0;
678453a8ed49104d8adad58f3ba591bdc39883e8speer macp->m_max_sdu = ETHERMTU;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer mutex_enter(&portp->lock);
678453a8ed49104d8adad58f3ba591bdc39883e8speer rv = vio_net_resource_reg(macp, type, vgenp->macaddr,
678453a8ed49104d8adad58f3ba591bdc39883e8speer portp->macaddr, &portp->vhp, &portp->vcb);
678453a8ed49104d8adad58f3ba591bdc39883e8speer mutex_exit(&portp->lock);
678453a8ed49104d8adad58f3ba591bdc39883e8speer mac_free(macp);
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (rv == 0) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer /* link it into the list of ports */
678453a8ed49104d8adad58f3ba591bdc39883e8speer plistp = &(vgenp->vgenports);
678453a8ed49104d8adad58f3ba591bdc39883e8speer WRITE_ENTER(&plistp->rwlock);
678453a8ed49104d8adad58f3ba591bdc39883e8speer vgen_port_list_insert(portp);
678453a8ed49104d8adad58f3ba591bdc39883e8speer RW_EXIT(&plistp->rwlock);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (portp->is_vsw_port == B_TRUE) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna /* We now have the vswitch port attached */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vgenp->vsw_portp = portp;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna (void) atomic_swap_32(&vgenp->vsw_port_refcnt, 0);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna }
678453a8ed49104d8adad58f3ba591bdc39883e8speer } else {
678453a8ed49104d8adad58f3ba591bdc39883e8speer DERR(vgenp, NULL, "vio_net_resource_reg failed for portp=0x%p",
678453a8ed49104d8adad58f3ba591bdc39883e8speer portp);
678453a8ed49104d8adad58f3ba591bdc39883e8speer vgen_port_detach(portp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, NULL, "exit: port_num(%d)\n", portp->port_num);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* detach a port from the device based on mdeg data */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_port_detach_mdeg(vgen_port_t *portp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_t *vgenp = portp->vgenp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, NULL, "enter: port_num(%d)\n", portp->port_num);
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer mutex_enter(&portp->lock);
678453a8ed49104d8adad58f3ba591bdc39883e8speer
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* stop the port if needed */
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (portp->flags & VGEN_STARTED) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_port_uninit(portp);
0c4606f05172c66c6c65847c0f940871a0ea1c15WENTAO YANG portp->flags &= ~(VGEN_STARTED);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer mutex_exit(&portp->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_port_detach(portp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, NULL, "exit: port_num(%d)\n", portp->port_num);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_update_port(vgen_t *vgenp, md_t *curr_mdp, mde_cookie_t curr_mdex,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo md_t *prev_mdp, mde_cookie_t prev_mdex)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
c1c61f44e88f4c8c155272ee56d868043146096asb uint64_t cport_num;
c1c61f44e88f4c8c155272ee56d868043146096asb uint64_t pport_num;
c1c61f44e88f4c8c155272ee56d868043146096asb vgen_portlist_t *plistp;
c1c61f44e88f4c8c155272ee56d868043146096asb vgen_port_t *portp;
c1c61f44e88f4c8c155272ee56d868043146096asb boolean_t updated_vlans = B_FALSE;
c1c61f44e88f4c8c155272ee56d868043146096asb uint16_t pvid;
c1c61f44e88f4c8c155272ee56d868043146096asb uint16_t *vids;
c1c61f44e88f4c8c155272ee56d868043146096asb uint16_t nvids;
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /*
c1c61f44e88f4c8c155272ee56d868043146096asb * For now, we get port updates only if vlan ids changed.
c1c61f44e88f4c8c155272ee56d868043146096asb * We read the port num and do some sanity check.
c1c61f44e88f4c8c155272ee56d868043146096asb */
c1c61f44e88f4c8c155272ee56d868043146096asb if (md_get_prop_val(curr_mdp, curr_mdex, id_propname, &cport_num)) {
c1c61f44e88f4c8c155272ee56d868043146096asb DWARN(vgenp, NULL, "prop(%s) not found\n", id_propname);
c1c61f44e88f4c8c155272ee56d868043146096asb return (DDI_FAILURE);
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb if (md_get_prop_val(prev_mdp, prev_mdex, id_propname, &pport_num)) {
c1c61f44e88f4c8c155272ee56d868043146096asb DWARN(vgenp, NULL, "prop(%s) not found\n", id_propname);
c1c61f44e88f4c8c155272ee56d868043146096asb return (DDI_FAILURE);
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb if (cport_num != pport_num)
c1c61f44e88f4c8c155272ee56d868043146096asb return (DDI_FAILURE);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb plistp = &(vgenp->vgenports);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb READ_ENTER(&plistp->rwlock);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb portp = vgen_port_lookup(plistp, (int)cport_num);
c1c61f44e88f4c8c155272ee56d868043146096asb if (portp == NULL) {
c1c61f44e88f4c8c155272ee56d868043146096asb DWARN(vgenp, NULL, "can't find port(%lx)\n", cport_num);
c1c61f44e88f4c8c155272ee56d868043146096asb RW_EXIT(&plistp->rwlock);
c1c61f44e88f4c8c155272ee56d868043146096asb return (DDI_FAILURE);
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /* Read the vlan ids */
c1c61f44e88f4c8c155272ee56d868043146096asb vgen_vlan_read_ids(portp, VGEN_PEER, curr_mdp, curr_mdex, &pvid, &vids,
c1c61f44e88f4c8c155272ee56d868043146096asb &nvids, NULL);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /* Determine if there are any vlan id updates */
c1c61f44e88f4c8c155272ee56d868043146096asb if ((pvid != portp->pvid) || /* pvid changed? */
c1c61f44e88f4c8c155272ee56d868043146096asb (nvids != portp->nvids) || /* # of vids changed? */
c1c61f44e88f4c8c155272ee56d868043146096asb ((nvids != 0) && (portp->nvids != 0) && /* vids changed? */
c1c61f44e88f4c8c155272ee56d868043146096asb bcmp(vids, portp->vids, sizeof (uint16_t) * nvids))) {
c1c61f44e88f4c8c155272ee56d868043146096asb updated_vlans = B_TRUE;
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb if (updated_vlans == B_FALSE) {
c1c61f44e88f4c8c155272ee56d868043146096asb RW_EXIT(&plistp->rwlock);
c1c61f44e88f4c8c155272ee56d868043146096asb return (DDI_FAILURE);
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /* remove the port from vlans it has been assigned to */
c1c61f44e88f4c8c155272ee56d868043146096asb vgen_vlan_remove_ids(portp);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /* save the new vlan ids */
c1c61f44e88f4c8c155272ee56d868043146096asb portp->pvid = pvid;
c1c61f44e88f4c8c155272ee56d868043146096asb if (portp->nvids != 0) {
c1c61f44e88f4c8c155272ee56d868043146096asb kmem_free(portp->vids, sizeof (uint16_t) * portp->nvids);
c1c61f44e88f4c8c155272ee56d868043146096asb portp->nvids = 0;
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb if (nvids != 0) {
c1c61f44e88f4c8c155272ee56d868043146096asb portp->vids = kmem_zalloc(sizeof (uint16_t) * nvids, KM_SLEEP);
c1c61f44e88f4c8c155272ee56d868043146096asb bcopy(vids, portp->vids, sizeof (uint16_t) * nvids);
c1c61f44e88f4c8c155272ee56d868043146096asb portp->nvids = nvids;
c1c61f44e88f4c8c155272ee56d868043146096asb kmem_free(vids, sizeof (uint16_t) * nvids);
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /* add port to the new vlans */
c1c61f44e88f4c8c155272ee56d868043146096asb vgen_vlan_add_ids(portp);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /* reset the port if it is vlan unaware (ver < 1.3) */
c1c61f44e88f4c8c155272ee56d868043146096asb vgen_vlan_unaware_port_reset(portp);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb RW_EXIT(&plistp->rwlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic uint64_t
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebvgen_port_stat(vgen_port_t *portp, uint_t stat)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_ldclist_t *ldclp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_ldc_t *ldcp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint64_t val;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo val = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldclp = &portp->ldclist;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo READ_ENTER(&ldclp->rwlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (ldcp = ldclp->headp; ldcp != NULL; ldcp = ldcp->nextp) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo val += vgen_ldc_stat(ldcp, stat);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo RW_EXIT(&ldclp->rwlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (val);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna/* allocate receive resources */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatnastatic int
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatnavgen_init_multipools(vgen_ldc_t *ldcp)
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna{
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna size_t data_sz;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna vgen_t *vgenp = LDC_TO_VGEN(ldcp);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna int status;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna uint32_t sz1 = 0;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna uint32_t sz2 = 0;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna uint32_t sz3 = 0;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna uint32_t sz4 = 0;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna /*
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * We round up the mtu specified to be a multiple of 2K.
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * We then create rx pools based on the rounded up size.
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna data_sz = vgenp->max_frame_size + VNET_IPALIGN + VNET_LDCALIGN;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna data_sz = VNET_ROUNDUP_2K(data_sz);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna /*
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * If pool sizes are specified, use them. Note that the presence of
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * the first tunable will be used as a hint.
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna if (vgen_rbufsz1 != 0) {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna sz1 = vgen_rbufsz1;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna sz2 = vgen_rbufsz2;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna sz3 = vgen_rbufsz3;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna sz4 = vgen_rbufsz4;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna if (sz4 == 0) { /* need 3 pools */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna ldcp->max_rxpool_size = sz3;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna status = vio_init_multipools(&ldcp->vmp,
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna VGEN_NUM_VMPOOLS, sz1, sz2, sz3, vgen_nrbufs1,
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna vgen_nrbufs2, vgen_nrbufs3);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna } else {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna ldcp->max_rxpool_size = sz4;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna status = vio_init_multipools(&ldcp->vmp,
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna VGEN_NUM_VMPOOLS + 1, sz1, sz2, sz3, sz4,
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna vgen_nrbufs1, vgen_nrbufs2, vgen_nrbufs3,
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna vgen_nrbufs4);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna }
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna return (status);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna }
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna /*
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * Pool sizes are not specified. We select the pool sizes based on the
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * mtu if vnet_jumbo_rxpools is enabled.
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna if (vnet_jumbo_rxpools == B_FALSE || data_sz == VNET_2K) {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna /*
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * Receive buffer pool allocation based on mtu is disabled.
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * Use the default mechanism of standard size pool allocation.
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna sz1 = VGEN_DBLK_SZ_128;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna sz2 = VGEN_DBLK_SZ_256;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna sz3 = VGEN_DBLK_SZ_2048;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna ldcp->max_rxpool_size = sz3;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna status = vio_init_multipools(&ldcp->vmp, VGEN_NUM_VMPOOLS,
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna sz1, sz2, sz3,
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna vgen_nrbufs1, vgen_nrbufs2, vgen_nrbufs3);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna return (status);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna }
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna switch (data_sz) {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna case VNET_4K:
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna sz1 = VGEN_DBLK_SZ_128;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna sz2 = VGEN_DBLK_SZ_256;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna sz3 = VGEN_DBLK_SZ_2048;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna sz4 = sz3 << 1; /* 4K */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna ldcp->max_rxpool_size = sz4;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna status = vio_init_multipools(&ldcp->vmp, VGEN_NUM_VMPOOLS + 1,
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna sz1, sz2, sz3, sz4,
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna vgen_nrbufs1, vgen_nrbufs2, vgen_nrbufs3, vgen_nrbufs4);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna break;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna default: /* data_sz: 4K+ to 16K */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna sz1 = VGEN_DBLK_SZ_256;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna sz2 = VGEN_DBLK_SZ_2048;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna sz3 = data_sz >> 1; /* Jumbo-size/2 */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna sz4 = data_sz; /* Jumbo-size */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna ldcp->max_rxpool_size = sz4;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna status = vio_init_multipools(&ldcp->vmp, VGEN_NUM_VMPOOLS + 1,
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna sz1, sz2, sz3, sz4,
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna vgen_nrbufs1, vgen_nrbufs2, vgen_nrbufs3, vgen_nrbufs4);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna break;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna }
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna return (status);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna}
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* attach the channel corresponding to the given ldc_id to the port */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_ldc_attach(vgen_port_t *portp, uint64_t ldc_id)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_t *vgenp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_ldclist_t *ldclp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_ldc_t *ldcp, **prev_ldcp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldc_attr_t attr;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int status;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldc_status_t istatus;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram char kname[MAXNAMELEN];
06db247c678f0e3956535e8a6dec31d6c2108827raghuram int instance;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram enum {AST_init = 0x0, AST_ldc_alloc = 0x1,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram AST_mutex_init = 0x2, AST_ldc_init = 0x4,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram AST_ldc_reg_cb = 0x8, AST_alloc_tx_ring = 0x10,
f0ca1d9a12d54d304791bc74525e2010ca924726sb AST_create_rxmblks = 0x20,
f0ca1d9a12d54d304791bc74525e2010ca924726sb AST_create_rcv_thread = 0x40} attach_state;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo attach_state = AST_init;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp = portp->vgenp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldclp = &portp->ldclist;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp = kmem_zalloc(sizeof (vgen_ldc_t), KM_NOSLEEP);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ldcp == NULL) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo goto ldc_attach_failed;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id = ldc_id;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->portp = portp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo attach_state |= AST_ldc_alloc;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_init(&ldcp->txlock, NULL, MUTEX_DRIVER, NULL);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_init(&ldcp->cblock, NULL, MUTEX_DRIVER, NULL);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_init(&ldcp->tclock, NULL, MUTEX_DRIVER, NULL);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_init(&ldcp->wrlock, NULL, MUTEX_DRIVER, NULL);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_init(&ldcp->rxlock, NULL, MUTEX_DRIVER, NULL);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna mutex_init(&ldcp->pollq_lock, NULL, MUTEX_DRIVER, NULL);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo attach_state |= AST_mutex_init;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo attr.devclass = LDC_DEV_NT;
678453a8ed49104d8adad58f3ba591bdc39883e8speer attr.instance = vgenp->instance;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo attr.mode = LDC_MODE_UNRELIABLE;
e1ebb9ec908bc2d0a8810f137ebd6566cc8a8061lm attr.mtu = vnet_ldc_mtu;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo status = ldc_init(ldc_id, &attr, &ldcp->ldc_handle);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (status != 0) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "ldc_init failed,rv (%d)\n", status);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo goto ldc_attach_failed;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo attach_state |= AST_ldc_init;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (vgen_rcv_thread_enabled) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ldcp->rcv_thr_flags = 0;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_init(&ldcp->rcv_thr_lock, NULL, MUTEX_DRIVER, NULL);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram cv_init(&ldcp->rcv_thr_cv, NULL, CV_DRIVER, NULL);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ldcp->rcv_thread = thread_create(NULL, 2 * DEFAULTSTKSZ,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_ldc_rcv_worker, ldcp, 0, &p0, TS_RUN, maxclsyspri);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram attach_state |= AST_create_rcv_thread;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (ldcp->rcv_thread == NULL) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "Failed to create worker thread");
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram goto ldc_attach_failed;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo status = ldc_reg_callback(ldcp->ldc_handle, vgen_ldc_cb, (caddr_t)ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (status != 0) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "ldc_reg_callback failed, rv (%d)\n",
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram status);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo goto ldc_attach_failed;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
f0ca1d9a12d54d304791bc74525e2010ca924726sb /*
f0ca1d9a12d54d304791bc74525e2010ca924726sb * allocate a message for ldc_read()s, big enough to hold ctrl and
f0ca1d9a12d54d304791bc74525e2010ca924726sb * data msgs, including raw data msgs used to recv priority frames.
f0ca1d9a12d54d304791bc74525e2010ca924726sb */
c1c61f44e88f4c8c155272ee56d868043146096asb ldcp->msglen = VIO_PKT_DATA_HDRSIZE + vgenp->max_frame_size;
f0ca1d9a12d54d304791bc74525e2010ca924726sb ldcp->ldcmsg = kmem_alloc(ldcp->msglen, KM_SLEEP);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo attach_state |= AST_ldc_reg_cb;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void) ldc_status(ldcp->ldc_handle, &istatus);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ASSERT(istatus == LDC_INIT);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_status = istatus;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* allocate transmit resources */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo status = vgen_alloc_tx_ring(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (status != 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo goto ldc_attach_failed;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo attach_state |= AST_alloc_tx_ring;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan /* allocate receive resources */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna status = vgen_init_multipools(ldcp);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan if (status != 0) {
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG /*
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG * We do not return failure if receive mblk pools can't be
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG * allocated; instead allocb(9F) will be used to dynamically
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG * allocate buffers during receive.
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG */
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG DWARN(vgenp, ldcp,
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG "vnet%d: status(%d), failed to allocate rx mblk pools for "
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG "channel(0x%lx)\n",
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG vgenp->instance, status, ldcp->ldc_id);
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG } else {
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG attach_state |= AST_create_rxmblks;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* Setup kstats for the channel */
678453a8ed49104d8adad58f3ba591bdc39883e8speer instance = vgenp->instance;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram (void) sprintf(kname, "vnetldc0x%lx", ldcp->ldc_id);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ldcp->ksp = vgen_setup_kstats("vnet", instance, kname, &ldcp->stats);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (ldcp->ksp == NULL) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo goto ldc_attach_failed;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* initialize vgen_versions supported */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bcopy(vgen_versions, ldcp->vgen_versions, sizeof (ldcp->vgen_versions));
f0ca1d9a12d54d304791bc74525e2010ca924726sb vgen_reset_vnet_proto_ops(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* link it into the list of channels for this port */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo WRITE_ENTER(&ldclp->rwlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo prev_ldcp = (vgen_ldc_t **)(&ldclp->headp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->nextp = *prev_ldcp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo *prev_ldcp = ldcp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo RW_EXIT(&ldclp->rwlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna ldcp->link_state = LINK_STATE_UNKNOWN;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna#ifdef VNET_IOC_DEBUG
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna ldcp->link_down_forced = B_FALSE;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna#endif
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->flags |= CHANNEL_ATTACHED;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoldc_attach_failed:
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (attach_state & AST_ldc_reg_cb) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram (void) ldc_unreg_callback(ldcp->ldc_handle);
f0ca1d9a12d54d304791bc74525e2010ca924726sb kmem_free(ldcp->ldcmsg, ldcp->msglen);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (attach_state & AST_create_rcv_thread) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (ldcp->rcv_thread != NULL) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_stop_rcv_thread(ldcp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_destroy(&ldcp->rcv_thr_lock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram cv_destroy(&ldcp->rcv_thr_cv);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan if (attach_state & AST_create_rxmblks) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vio_mblk_pool_t *fvmp = NULL;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vio_destroy_multipools(&ldcp->vmp, &fvmp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ASSERT(fvmp == NULL);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (attach_state & AST_alloc_tx_ring) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_free_tx_ring(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (attach_state & AST_ldc_init) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void) ldc_fini(ldcp->ldc_handle);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (attach_state & AST_mutex_init) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_destroy(&ldcp->tclock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_destroy(&ldcp->txlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_destroy(&ldcp->cblock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_destroy(&ldcp->wrlock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_destroy(&ldcp->rxlock);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna mutex_destroy(&ldcp->pollq_lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (attach_state & AST_ldc_alloc) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo KMEM_FREE(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* detach a channel from the port */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_ldc_detach(vgen_ldc_t *ldcp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_port_t *portp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_t *vgenp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_ldc_t *pldcp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_ldc_t **prev_ldcp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_ldclist_t *ldclp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo portp = ldcp->portp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp = portp->vgenp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldclp = &portp->ldclist;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo prev_ldcp = (vgen_ldc_t **)&ldclp->headp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (; (pldcp = *prev_ldcp) != NULL; prev_ldcp = &pldcp->nextp) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (pldcp == ldcp) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (pldcp == NULL) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* invalid ldcp? */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ldcp->ldc_status != LDC_INIT) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "ldc_status is not INIT\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ldcp->flags & CHANNEL_ATTACHED) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->flags &= ~(CHANNEL_ATTACHED);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram (void) ldc_unreg_callback(ldcp->ldc_handle);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (ldcp->rcv_thread != NULL) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* First stop the receive thread */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_stop_rcv_thread(ldcp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_destroy(&ldcp->rcv_thr_lock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram cv_destroy(&ldcp->rcv_thr_cv);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
f0ca1d9a12d54d304791bc74525e2010ca924726sb kmem_free(ldcp->ldcmsg, ldcp->msglen);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vgen_destroy_kstats(ldcp->ksp);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ldcp->ksp = NULL;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /*
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * if we cannot reclaim all mblks, put this
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * on the list of pools(vgenp->rmp) to be reclaimed when the
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * device gets detached (see vgen_uninit()).
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vio_destroy_multipools(&ldcp->vmp, &vgenp->rmp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* free transmit resources */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_free_tx_ring(ldcp);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void) ldc_fini(ldcp->ldc_handle);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_destroy(&ldcp->tclock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_destroy(&ldcp->txlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_destroy(&ldcp->cblock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_destroy(&ldcp->wrlock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_destroy(&ldcp->rxlock);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna mutex_destroy(&ldcp->pollq_lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* unlink it from the list */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo *prev_ldcp = ldcp->nextp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo KMEM_FREE(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * This function allocates transmit resources for the channel.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * The resources consist of a transmit descriptor ring and an associated
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * transmit buffer ring.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_alloc_tx_ring(vgen_ldc_t *ldcp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo void *tbufp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldc_mem_info_t minfo;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint32_t txdsize;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint32_t tbufsize;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int status;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_t *vgenp = LDC_TO_VGEN(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->num_txds = vnet_ntxds;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo txdsize = sizeof (vnet_public_desc_t);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tbufsize = sizeof (vgen_private_desc_t);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* allocate transmit buffer ring */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tbufp = kmem_zalloc(ldcp->num_txds * tbufsize, KM_NOSLEEP);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (tbufp == NULL) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* create transmit descriptor ring */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo status = ldc_mem_dring_create(ldcp->num_txds, txdsize,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo &ldcp->tx_dhandle);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (status) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "ldc_mem_dring_create() failed\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kmem_free(tbufp, ldcp->num_txds * tbufsize);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* get the addr of descripror ring */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo status = ldc_mem_dring_info(ldcp->tx_dhandle, &minfo);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (status) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "ldc_mem_dring_info() failed\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kmem_free(tbufp, ldcp->num_txds * tbufsize);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void) ldc_mem_dring_destroy(ldcp->tx_dhandle);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->tbufp = NULL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->txdp = (vnet_public_desc_t *)(minfo.vaddr);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->tbufp = tbufp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->txdendp = &((ldcp->txdp)[ldcp->num_txds]);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->tbufendp = &((ldcp->tbufp)[ldcp->num_txds]);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* Free transmit resources for the channel */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_free_tx_ring(vgen_ldc_t *ldcp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int tbufsize = sizeof (vgen_private_desc_t);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* free transmit descriptor ring */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void) ldc_mem_dring_destroy(ldcp->tx_dhandle);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* free transmit buffer ring */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kmem_free(ldcp->tbufp, ldcp->num_txds * tbufsize);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->txdp = ldcp->txdendp = NULL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->tbufp = ldcp->tbufendp = NULL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* enable transmit/receive on the channels for the port */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_init_ldcs(vgen_port_t *portp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_ldclist_t *ldclp = &portp->ldclist;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_ldc_t *ldcp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo READ_ENTER(&ldclp->rwlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp = ldclp->headp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (; ldcp != NULL; ldcp = ldcp->nextp) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void) vgen_ldc_init(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo RW_EXIT(&ldclp->rwlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* stop transmit/receive on the channels for the port */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_uninit_ldcs(vgen_port_t *portp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_ldclist_t *ldclp = &portp->ldclist;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_ldc_t *ldcp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo READ_ENTER(&ldclp->rwlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp = ldclp->headp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (; ldcp != NULL; ldcp = ldcp->nextp) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_ldc_uninit(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo RW_EXIT(&ldclp->rwlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* enable transmit/receive on the channel */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_ldc_init(vgen_ldc_t *ldcp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_t *vgenp = LDC_TO_VGEN(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldc_status_t istatus;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int rv;
8e6a2a040587479821d1e682a28bcef7e75f19a6lm uint32_t retries = 0;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram enum { ST_init = 0x0, ST_ldc_open = 0x1,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ST_init_tbufs = 0x2, ST_cb_enable = 0x4} init_state;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo init_state = ST_init;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "enter\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo LDC_LOCK(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = ldc_open(ldcp->ldc_handle);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rv != 0) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "ldc_open failed: rv(%d)\n", rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo goto ldcinit_failed;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo init_state |= ST_ldc_open;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void) ldc_status(ldcp->ldc_handle, &istatus);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (istatus != LDC_OPEN && istatus != LDC_READY) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "status(%d) is not OPEN/READY\n", istatus);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo goto ldcinit_failed;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_status = istatus;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = vgen_init_tbufs(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rv != 0) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "vgen_init_tbufs() failed\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo goto ldcinit_failed;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo init_state |= ST_init_tbufs;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
7636cb21f250f0485ca6052ffadc80ace93e6358lm rv = ldc_set_cb_mode(ldcp->ldc_handle, LDC_CB_ENABLE);
7636cb21f250f0485ca6052ffadc80ace93e6358lm if (rv != 0) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "ldc_set_cb_mode failed: rv(%d)\n", rv);
7636cb21f250f0485ca6052ffadc80ace93e6358lm goto ldcinit_failed;
7636cb21f250f0485ca6052ffadc80ace93e6358lm }
7636cb21f250f0485ca6052ffadc80ace93e6358lm
7636cb21f250f0485ca6052ffadc80ace93e6358lm init_state |= ST_cb_enable;
7636cb21f250f0485ca6052ffadc80ace93e6358lm
8e6a2a040587479821d1e682a28bcef7e75f19a6lm do {
8e6a2a040587479821d1e682a28bcef7e75f19a6lm rv = ldc_up(ldcp->ldc_handle);
8e6a2a040587479821d1e682a28bcef7e75f19a6lm if ((rv != 0) && (rv == EWOULDBLOCK)) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG2(vgenp, ldcp, "ldc_up err rv(%d)\n", rv);
8e6a2a040587479821d1e682a28bcef7e75f19a6lm drv_usecwait(VGEN_LDC_UP_DELAY);
8e6a2a040587479821d1e682a28bcef7e75f19a6lm }
8e6a2a040587479821d1e682a28bcef7e75f19a6lm if (retries++ >= vgen_ldcup_retries)
8e6a2a040587479821d1e682a28bcef7e75f19a6lm break;
8e6a2a040587479821d1e682a28bcef7e75f19a6lm } while (rv == EWOULDBLOCK);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void) ldc_status(ldcp->ldc_handle, &istatus);
3af08d828975d7e2581b6829e0eecff14d87a483lm if (istatus == LDC_UP) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "status(%d) is UP\n", istatus);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
3af08d828975d7e2581b6829e0eecff14d87a483lm
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_status = istatus;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* initialize transmit watchdog timeout */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->wd_tid = timeout(vgen_ldc_watchdog, (caddr_t)ldcp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo drv_usectohz(vnet_ldcwd_interval * 1000));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
3af08d828975d7e2581b6829e0eecff14d87a483lm ldcp->hphase = -1;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->flags |= CHANNEL_STARTED;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
3af08d828975d7e2581b6829e0eecff14d87a483lm /* if channel is already UP - start handshake */
3af08d828975d7e2581b6829e0eecff14d87a483lm if (istatus == LDC_UP) {
3af08d828975d7e2581b6829e0eecff14d87a483lm vgen_t *vgenp = LDC_TO_VGEN(ldcp);
3af08d828975d7e2581b6829e0eecff14d87a483lm if (ldcp->portp != vgenp->vsw_portp) {
3af08d828975d7e2581b6829e0eecff14d87a483lm /*
678453a8ed49104d8adad58f3ba591bdc39883e8speer * As the channel is up, use this port from now on.
3af08d828975d7e2581b6829e0eecff14d87a483lm */
678453a8ed49104d8adad58f3ba591bdc39883e8speer (void) atomic_swap_32(
678453a8ed49104d8adad58f3ba591bdc39883e8speer &ldcp->portp->use_vsw_port, B_FALSE);
3af08d828975d7e2581b6829e0eecff14d87a483lm }
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm /* Initialize local session id */
3af08d828975d7e2581b6829e0eecff14d87a483lm ldcp->local_sid = ddi_get_lbolt();
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm /* clear peer session id */
3af08d828975d7e2581b6829e0eecff14d87a483lm ldcp->peer_sid = 0;
3af08d828975d7e2581b6829e0eecff14d87a483lm ldcp->hretries = 0;
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm /* Initiate Handshake process with peer ldc endpoint */
3af08d828975d7e2581b6829e0eecff14d87a483lm vgen_reset_hphase(ldcp);
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm mutex_exit(&ldcp->tclock);
3af08d828975d7e2581b6829e0eecff14d87a483lm mutex_exit(&ldcp->txlock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_exit(&ldcp->wrlock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_exit(&ldcp->rxlock);
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram vgen_handshake(vh_nextphase(ldcp));
3af08d828975d7e2581b6829e0eecff14d87a483lm mutex_exit(&ldcp->cblock);
3af08d828975d7e2581b6829e0eecff14d87a483lm } else {
3af08d828975d7e2581b6829e0eecff14d87a483lm LDC_UNLOCK(ldcp);
3af08d828975d7e2581b6829e0eecff14d87a483lm }
3af08d828975d7e2581b6829e0eecff14d87a483lm
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoldcinit_failed:
7636cb21f250f0485ca6052ffadc80ace93e6358lm if (init_state & ST_cb_enable) {
7636cb21f250f0485ca6052ffadc80ace93e6358lm (void) ldc_set_cb_mode(ldcp->ldc_handle, LDC_CB_DISABLE);
7636cb21f250f0485ca6052ffadc80ace93e6358lm }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (init_state & ST_init_tbufs) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_uninit_tbufs(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (init_state & ST_ldc_open) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void) ldc_close(ldcp->ldc_handle);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo LDC_UNLOCK(ldcp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "exit\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* stop transmit/receive on the channel */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_ldc_uninit(vgen_ldc_t *ldcp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_t *vgenp = LDC_TO_VGEN(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int rv;
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna uint_t retries = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "enter\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo LDC_LOCK(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((ldcp->flags & CHANNEL_STARTED) == 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo LDC_UNLOCK(ldcp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "CHANNEL_STARTED flag is not set\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* disable further callbacks */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = ldc_set_cb_mode(ldcp->ldc_handle, LDC_CB_DISABLE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rv != 0) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "ldc_set_cb_mode failed\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan /*
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan * clear handshake done bit and wait for pending tx and cb to finish.
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan * release locks before untimeout(9F) is invoked to cancel timeouts.
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->hphase &= ~(VH_DONE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo LDC_UNLOCK(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
5460ddbd465905aefef1e301733f035391f680e0Sriharsha Basavapatna if (vgenp->vsw_portp == ldcp->portp) {
5460ddbd465905aefef1e301733f035391f680e0Sriharsha Basavapatna vio_net_report_err_t rep_err =
5460ddbd465905aefef1e301733f035391f680e0Sriharsha Basavapatna ldcp->portp->vcb.vio_net_report_err;
5460ddbd465905aefef1e301733f035391f680e0Sriharsha Basavapatna rep_err(ldcp->portp->vhp, VIO_NET_RES_DOWN);
5460ddbd465905aefef1e301733f035391f680e0Sriharsha Basavapatna }
5460ddbd465905aefef1e301733f035391f680e0Sriharsha Basavapatna
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan /* cancel handshake watchdog timeout */
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan if (ldcp->htid) {
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan (void) untimeout(ldcp->htid);
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan ldcp->htid = 0;
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG if (ldcp->cancel_htid) {
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG (void) untimeout(ldcp->cancel_htid);
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG ldcp->cancel_htid = 0;
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG }
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan /* cancel transmit watchdog timeout */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ldcp->wd_tid) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void) untimeout(ldcp->wd_tid);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->wd_tid = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan drv_usecwait(1000);
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna if (ldcp->rcv_thread != NULL) {
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna /*
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna * Note that callbacks have been disabled already(above). The
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna * drain function takes care of the condition when an already
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna * executing callback signals the worker to start processing or
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna * the worker has already been signalled and is in the middle of
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna * processing.
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna */
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna vgen_drain_rcv_thread(ldcp);
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna }
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan /* acquire locks again; any pending transmits and callbacks are done */
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan LDC_LOCK(ldcp);
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan vgen_reset_hphase(ldcp);
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_uninit_tbufs(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna /* close the channel - retry on EAGAIN */
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna while ((rv = ldc_close(ldcp->ldc_handle)) == EAGAIN) {
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna if (++retries > vgen_ldccl_retries) {
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna break;
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna }
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna drv_usecwait(VGEN_LDC_CLOSE_DELAY);
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rv != 0) {
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna cmn_err(CE_NOTE,
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna "!vnet%d: Error(%d) closing the channel(0x%lx)\n",
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna vgenp->instance, rv, ldcp->ldc_id);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_status = LDC_INIT;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->flags &= ~(CHANNEL_STARTED);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo LDC_UNLOCK(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "exit\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* Initialize the transmit buffer ring for the channel */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_init_tbufs(vgen_ldc_t *ldcp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_private_desc_t *tbufp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vnet_public_desc_t *txdp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vio_dring_entry_hdr_t *hdrp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int i;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int rv;
8e6a2a040587479821d1e682a28bcef7e75f19a6lm caddr_t datap = NULL;
8e6a2a040587479821d1e682a28bcef7e75f19a6lm int ci;
8e6a2a040587479821d1e682a28bcef7e75f19a6lm uint32_t ncookies;
c1c61f44e88f4c8c155272ee56d868043146096asb size_t data_sz;
c1c61f44e88f4c8c155272ee56d868043146096asb vgen_t *vgenp;
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb vgenp = LDC_TO_VGEN(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bzero(ldcp->tbufp, sizeof (*tbufp) * (ldcp->num_txds));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bzero(ldcp->txdp, sizeof (*txdp) * (ldcp->num_txds));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna /*
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * In order to ensure that the number of ldc cookies per descriptor is
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * limited to be within the default MAX_COOKIES (2), we take the steps
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * outlined below:
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna *
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * Align the entire data buffer area to 8K and carve out per descriptor
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * data buffers starting from this 8K aligned base address.
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna *
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * We round up the mtu specified to be a multiple of 2K or 4K.
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * For sizes up to 12K we round up the size to the next 2K.
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * For sizes > 12K we round up to the next 4K (otherwise sizes such as
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * 14K could end up needing 3 cookies, with the buffer spread across
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * 3 8K pages: 8K+6K, 2K+8K+2K, 6K+8K, ...).
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna */
c1c61f44e88f4c8c155272ee56d868043146096asb data_sz = vgenp->max_frame_size + VNET_IPALIGN + VNET_LDCALIGN;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna if (data_sz <= VNET_12K) {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna data_sz = VNET_ROUNDUP_2K(data_sz);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna } else {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna data_sz = VNET_ROUNDUP_4K(data_sz);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna }
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna /* allocate extra 8K bytes for alignment */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna ldcp->tx_data_sz = (data_sz * ldcp->num_txds) + VNET_8K;
c1c61f44e88f4c8c155272ee56d868043146096asb datap = kmem_zalloc(ldcp->tx_data_sz, KM_SLEEP);
8e6a2a040587479821d1e682a28bcef7e75f19a6lm ldcp->tx_datap = datap;
8e6a2a040587479821d1e682a28bcef7e75f19a6lm
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna /* align the starting address of the data area to 8K */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna datap = (caddr_t)VNET_ROUNDUP_8K((uintptr_t)datap);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
8e6a2a040587479821d1e682a28bcef7e75f19a6lm * for each private descriptor, allocate a ldc mem_handle which is
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * required to map the data during transmit, set the flags
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * to free (available for use by transmit routine).
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (i = 0; i < ldcp->num_txds; i++) {
8e6a2a040587479821d1e682a28bcef7e75f19a6lm
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tbufp = &(ldcp->tbufp[i]);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = ldc_mem_alloc_handle(ldcp->ldc_handle,
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram &(tbufp->memhandle));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rv) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tbufp->memhandle = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo goto init_tbufs_failed;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
8e6a2a040587479821d1e682a28bcef7e75f19a6lm
8e6a2a040587479821d1e682a28bcef7e75f19a6lm /*
8e6a2a040587479821d1e682a28bcef7e75f19a6lm * bind ldc memhandle to the corresponding transmit buffer.
8e6a2a040587479821d1e682a28bcef7e75f19a6lm */
8e6a2a040587479821d1e682a28bcef7e75f19a6lm ci = ncookies = 0;
8e6a2a040587479821d1e682a28bcef7e75f19a6lm rv = ldc_mem_bind_handle(tbufp->memhandle,
c1c61f44e88f4c8c155272ee56d868043146096asb (caddr_t)datap, data_sz, LDC_SHADOW_MAP,
8e6a2a040587479821d1e682a28bcef7e75f19a6lm LDC_MEM_R, &(tbufp->memcookie[ci]), &ncookies);
8e6a2a040587479821d1e682a28bcef7e75f19a6lm if (rv != 0) {
8e6a2a040587479821d1e682a28bcef7e75f19a6lm goto init_tbufs_failed;
8e6a2a040587479821d1e682a28bcef7e75f19a6lm }
8e6a2a040587479821d1e682a28bcef7e75f19a6lm
8e6a2a040587479821d1e682a28bcef7e75f19a6lm /*
8e6a2a040587479821d1e682a28bcef7e75f19a6lm * successful in binding the handle to tx data buffer.
8e6a2a040587479821d1e682a28bcef7e75f19a6lm * set datap in the private descr to this buffer.
8e6a2a040587479821d1e682a28bcef7e75f19a6lm */
8e6a2a040587479821d1e682a28bcef7e75f19a6lm tbufp->datap = datap;
8e6a2a040587479821d1e682a28bcef7e75f19a6lm
8e6a2a040587479821d1e682a28bcef7e75f19a6lm if ((ncookies == 0) ||
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram (ncookies > MAX_COOKIES)) {
8e6a2a040587479821d1e682a28bcef7e75f19a6lm goto init_tbufs_failed;
8e6a2a040587479821d1e682a28bcef7e75f19a6lm }
8e6a2a040587479821d1e682a28bcef7e75f19a6lm
8e6a2a040587479821d1e682a28bcef7e75f19a6lm for (ci = 1; ci < ncookies; ci++) {
8e6a2a040587479821d1e682a28bcef7e75f19a6lm rv = ldc_mem_nextcookie(tbufp->memhandle,
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram &(tbufp->memcookie[ci]));
8e6a2a040587479821d1e682a28bcef7e75f19a6lm if (rv != 0) {
8e6a2a040587479821d1e682a28bcef7e75f19a6lm goto init_tbufs_failed;
8e6a2a040587479821d1e682a28bcef7e75f19a6lm }
8e6a2a040587479821d1e682a28bcef7e75f19a6lm }
8e6a2a040587479821d1e682a28bcef7e75f19a6lm
8e6a2a040587479821d1e682a28bcef7e75f19a6lm tbufp->ncookies = ncookies;
c1c61f44e88f4c8c155272ee56d868043146096asb datap += data_sz;
8e6a2a040587479821d1e682a28bcef7e75f19a6lm
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tbufp->flags = VGEN_PRIV_DESC_FREE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo txdp = &(ldcp->txdp[i]);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo hdrp = &txdp->hdr;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo hdrp->dstate = VIO_DESC_FREE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo hdrp->ack = B_FALSE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tbufp->descp = txdp;
8e6a2a040587479821d1e682a28bcef7e75f19a6lm
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* reset tbuf walking pointers */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->next_tbufp = ldcp->tbufp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->cur_tbufp = ldcp->tbufp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* initialize tx seqnum and index */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->next_txseq = VNET_ISS;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->next_txi = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan ldcp->resched_peer = B_TRUE;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ldcp->resched_peer_txi = 0;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoinit_tbufs_failed:;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_uninit_tbufs(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* Uninitialize transmit buffer ring for the channel */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_uninit_tbufs(vgen_ldc_t *ldcp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_private_desc_t *tbufp = ldcp->tbufp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int i;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* for each tbuf (priv_desc), free ldc mem_handle */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (i = 0; i < ldcp->num_txds; i++) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tbufp = &(ldcp->tbufp[i]);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
8e6a2a040587479821d1e682a28bcef7e75f19a6lm if (tbufp->datap) { /* if bound to a ldc memhandle */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void) ldc_mem_unbind_handle(tbufp->memhandle);
8e6a2a040587479821d1e682a28bcef7e75f19a6lm tbufp->datap = NULL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (tbufp->memhandle) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void) ldc_mem_free_handle(tbufp->memhandle);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tbufp->memhandle = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
8e6a2a040587479821d1e682a28bcef7e75f19a6lm if (ldcp->tx_datap) {
8e6a2a040587479821d1e682a28bcef7e75f19a6lm /* prealloc'd tx data buffer */
c1c61f44e88f4c8c155272ee56d868043146096asb kmem_free(ldcp->tx_datap, ldcp->tx_data_sz);
8e6a2a040587479821d1e682a28bcef7e75f19a6lm ldcp->tx_datap = NULL;
c1c61f44e88f4c8c155272ee56d868043146096asb ldcp->tx_data_sz = 0;
8e6a2a040587479821d1e682a28bcef7e75f19a6lm }
8e6a2a040587479821d1e682a28bcef7e75f19a6lm
7636cb21f250f0485ca6052ffadc80ace93e6358lm bzero(ldcp->tbufp, sizeof (vgen_private_desc_t) * (ldcp->num_txds));
7636cb21f250f0485ca6052ffadc80ace93e6358lm bzero(ldcp->txdp, sizeof (vnet_public_desc_t) * (ldcp->num_txds));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* clobber tx descriptor ring */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_clobber_tbufs(vgen_ldc_t *ldcp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vnet_public_desc_t *txdp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_private_desc_t *tbufp;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vio_dring_entry_hdr_t *hdrp;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_t *vgenp = LDC_TO_VGEN(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int i;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#ifdef DEBUG
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int ndone = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#endif
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (i = 0; i < ldcp->num_txds; i++) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tbufp = &(ldcp->tbufp[i]);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo txdp = tbufp->descp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo hdrp = &txdp->hdr;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (tbufp->flags & VGEN_PRIV_DESC_BUSY) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tbufp->flags = VGEN_PRIV_DESC_FREE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#ifdef DEBUG
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (hdrp->dstate == VIO_DESC_DONE)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ndone++;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#endif
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo hdrp->dstate = VIO_DESC_FREE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo hdrp->ack = B_FALSE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* reset tbuf walking pointers */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->next_tbufp = ldcp->tbufp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->cur_tbufp = ldcp->tbufp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* reset tx seqnum and index */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->next_txseq = VNET_ISS;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->next_txi = 0;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan ldcp->resched_peer = B_TRUE;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ldcp->resched_peer_txi = 0;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG2(vgenp, ldcp, "num descrs done (%d)\n", ndone);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* clobber receive descriptor ring */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_clobber_rxds(vgen_ldc_t *ldcp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->rx_dhandle = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bzero(&ldcp->rx_dcookie, sizeof (ldcp->rx_dcookie));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->rxdp = NULL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->next_rxi = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->num_rxds = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->next_rxseq = VNET_ISS;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* initialize receive descriptor ring */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_init_rxds(vgen_ldc_t *ldcp, uint32_t num_desc, uint32_t desc_size,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldc_mem_cookie_t *dcookie, uint32_t ncookies)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int rv;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldc_mem_info_t minfo;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = ldc_mem_dring_map(ldcp->ldc_handle, dcookie, ncookies, num_desc,
bbfa0259e68b6b625e9e085053d41d620f185eeeha desc_size, LDC_DIRECT_MAP, &(ldcp->rx_dhandle));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rv != 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * sucessfully mapped, now try to
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * get info about the mapped dring
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = ldc_mem_dring_info(ldcp->rx_dhandle, &minfo);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rv != 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void) ldc_mem_dring_unmap(ldcp->rx_dhandle);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * save ring address, number of descriptors.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->rxdp = (vnet_public_desc_t *)(minfo.vaddr);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bcopy(dcookie, &(ldcp->rx_dcookie), sizeof (*dcookie));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->num_rxdcookies = ncookies;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->num_rxds = num_desc;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->next_rxi = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->next_rxseq = VNET_ISS;
bbfa0259e68b6b625e9e085053d41d620f185eeeha ldcp->dring_mtype = minfo.mtype;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* get channel statistics */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic uint64_t
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebvgen_ldc_stat(vgen_ldc_t *ldcp, uint_t stat)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_stats_t *statsp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint64_t val;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo val = 0;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram statsp = &ldcp->stats;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo switch (stat) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case MAC_STAT_MULTIRCV:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo val = statsp->multircv;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case MAC_STAT_BRDCSTRCV:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo val = statsp->brdcstrcv;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case MAC_STAT_MULTIXMT:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo val = statsp->multixmt;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case MAC_STAT_BRDCSTXMT:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo val = statsp->brdcstxmt;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case MAC_STAT_NORCVBUF:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo val = statsp->norcvbuf;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case MAC_STAT_IERRORS:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo val = statsp->ierrors;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case MAC_STAT_NOXMTBUF:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo val = statsp->noxmtbuf;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case MAC_STAT_OERRORS:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo val = statsp->oerrors;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case MAC_STAT_COLLISIONS:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case MAC_STAT_RBYTES:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo val = statsp->rbytes;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case MAC_STAT_IPACKETS:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo val = statsp->ipackets;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case MAC_STAT_OBYTES:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo val = statsp->obytes;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case MAC_STAT_OPACKETS:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo val = statsp->opackets;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* stats not relevant to ldc, return 0 */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case MAC_STAT_IFSPEED:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_ALIGN_ERRORS:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_FCS_ERRORS:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_FIRST_COLLISIONS:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_MULTI_COLLISIONS:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_DEFER_XMTS:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_TX_LATE_COLLISIONS:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_EX_COLLISIONS:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_MACXMT_ERRORS:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_CARRIER_ERRORS:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_TOOLONG_ERRORS:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_XCVR_ADDR:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_XCVR_ID:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_XCVR_INUSE:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_CAP_1000FDX:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_CAP_1000HDX:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_CAP_100FDX:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_CAP_100HDX:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_CAP_10FDX:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_CAP_10HDX:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_CAP_ASMPAUSE:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_CAP_PAUSE:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_CAP_AUTONEG:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_ADV_CAP_1000FDX:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_ADV_CAP_1000HDX:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_ADV_CAP_100FDX:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_ADV_CAP_100HDX:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_ADV_CAP_10FDX:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_ADV_CAP_10HDX:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_ADV_CAP_ASMPAUSE:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_ADV_CAP_PAUSE:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_ADV_CAP_AUTONEG:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_LP_CAP_1000FDX:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_LP_CAP_1000HDX:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_LP_CAP_100FDX:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_LP_CAP_100HDX:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_LP_CAP_10FDX:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_LP_CAP_10HDX:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_LP_CAP_ASMPAUSE:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_LP_CAP_PAUSE:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_LP_CAP_AUTONEG:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_LINK_ASMPAUSE:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_LINK_PAUSE:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_LINK_AUTONEG:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_LINK_DUPLEX:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo default:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo val = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (val);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
3af08d828975d7e2581b6829e0eecff14d87a483lm/*
678453a8ed49104d8adad58f3ba591bdc39883e8speer * LDC channel is UP, start handshake process with peer.
3af08d828975d7e2581b6829e0eecff14d87a483lm */
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic void
678453a8ed49104d8adad58f3ba591bdc39883e8speervgen_handle_evt_up(vgen_ldc_t *ldcp)
3af08d828975d7e2581b6829e0eecff14d87a483lm{
3af08d828975d7e2581b6829e0eecff14d87a483lm vgen_t *vgenp = LDC_TO_VGEN(ldcp);
3af08d828975d7e2581b6829e0eecff14d87a483lm
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "enter\n");
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm ASSERT(MUTEX_HELD(&ldcp->cblock));
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm if (ldcp->portp != vgenp->vsw_portp) {
3af08d828975d7e2581b6829e0eecff14d87a483lm /*
678453a8ed49104d8adad58f3ba591bdc39883e8speer * As the channel is up, use this port from now on.
3af08d828975d7e2581b6829e0eecff14d87a483lm */
678453a8ed49104d8adad58f3ba591bdc39883e8speer (void) atomic_swap_32(&ldcp->portp->use_vsw_port, B_FALSE);
3af08d828975d7e2581b6829e0eecff14d87a483lm }
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm /* Initialize local session id */
3af08d828975d7e2581b6829e0eecff14d87a483lm ldcp->local_sid = ddi_get_lbolt();
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm /* clear peer session id */
3af08d828975d7e2581b6829e0eecff14d87a483lm ldcp->peer_sid = 0;
3af08d828975d7e2581b6829e0eecff14d87a483lm ldcp->hretries = 0;
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm if (ldcp->hphase != VH_PHASE0) {
3af08d828975d7e2581b6829e0eecff14d87a483lm vgen_handshake_reset(ldcp);
3af08d828975d7e2581b6829e0eecff14d87a483lm }
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm /* Initiate Handshake process with peer ldc endpoint */
3af08d828975d7e2581b6829e0eecff14d87a483lm vgen_handshake(vh_nextphase(ldcp));
3af08d828975d7e2581b6829e0eecff14d87a483lm
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "exit\n");
3af08d828975d7e2581b6829e0eecff14d87a483lm}
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm/*
3af08d828975d7e2581b6829e0eecff14d87a483lm * LDC channel is Reset, terminate connection with peer and try to
3af08d828975d7e2581b6829e0eecff14d87a483lm * bring the channel up again.
3af08d828975d7e2581b6829e0eecff14d87a483lm */
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic void
678453a8ed49104d8adad58f3ba591bdc39883e8speervgen_handle_evt_reset(vgen_ldc_t *ldcp)
3af08d828975d7e2581b6829e0eecff14d87a483lm{
3af08d828975d7e2581b6829e0eecff14d87a483lm ldc_status_t istatus;
3af08d828975d7e2581b6829e0eecff14d87a483lm vgen_t *vgenp = LDC_TO_VGEN(ldcp);
3af08d828975d7e2581b6829e0eecff14d87a483lm int rv;
3af08d828975d7e2581b6829e0eecff14d87a483lm
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "enter\n");
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm ASSERT(MUTEX_HELD(&ldcp->cblock));
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm if ((ldcp->portp != vgenp->vsw_portp) &&
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram (vgenp->vsw_portp != NULL)) {
3af08d828975d7e2581b6829e0eecff14d87a483lm /*
678453a8ed49104d8adad58f3ba591bdc39883e8speer * As the channel is down, use the switch port until
678453a8ed49104d8adad58f3ba591bdc39883e8speer * the channel becomes ready to be used.
3af08d828975d7e2581b6829e0eecff14d87a483lm */
678453a8ed49104d8adad58f3ba591bdc39883e8speer (void) atomic_swap_32(&ldcp->portp->use_vsw_port, B_TRUE);
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (vgenp->vsw_portp == ldcp->portp) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer vio_net_report_err_t rep_err =
678453a8ed49104d8adad58f3ba591bdc39883e8speer ldcp->portp->vcb.vio_net_report_err;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer /* Post a reset message */
678453a8ed49104d8adad58f3ba591bdc39883e8speer rep_err(ldcp->portp->vhp, VIO_NET_RES_DOWN);
3af08d828975d7e2581b6829e0eecff14d87a483lm }
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm if (ldcp->hphase != VH_PHASE0) {
3af08d828975d7e2581b6829e0eecff14d87a483lm vgen_handshake_reset(ldcp);
3af08d828975d7e2581b6829e0eecff14d87a483lm }
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm /* try to bring the channel up */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna#ifdef VNET_IOC_DEBUG
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (ldcp->link_down_forced == B_FALSE) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna rv = ldc_up(ldcp->ldc_handle);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (rv != 0) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna DWARN(vgenp, ldcp, "ldc_up err rv(%d)\n", rv);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna }
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna }
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna#else
3af08d828975d7e2581b6829e0eecff14d87a483lm rv = ldc_up(ldcp->ldc_handle);
3af08d828975d7e2581b6829e0eecff14d87a483lm if (rv != 0) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "ldc_up err rv(%d)\n", rv);
3af08d828975d7e2581b6829e0eecff14d87a483lm }
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna#endif
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm if (ldc_status(ldcp->ldc_handle, &istatus) != 0) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "ldc_status err\n");
3af08d828975d7e2581b6829e0eecff14d87a483lm } else {
3af08d828975d7e2581b6829e0eecff14d87a483lm ldcp->ldc_status = istatus;
3af08d828975d7e2581b6829e0eecff14d87a483lm }
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm /* if channel is already UP - restart handshake */
3af08d828975d7e2581b6829e0eecff14d87a483lm if (ldcp->ldc_status == LDC_UP) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer vgen_handle_evt_up(ldcp);
3af08d828975d7e2581b6829e0eecff14d87a483lm }
3af08d828975d7e2581b6829e0eecff14d87a483lm
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "exit\n");
3af08d828975d7e2581b6829e0eecff14d87a483lm}
3af08d828975d7e2581b6829e0eecff14d87a483lm
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* Interrupt handler for the channel */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic uint_t
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_ldc_cb(uint64_t event, caddr_t arg)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo _NOTE(ARGUNUSED(event))
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_ldc_t *ldcp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_t *vgenp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldc_status_t istatus;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_stats_t *statsp;
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG timeout_id_t cancel_htid = 0;
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG uint_t ret = LDC_SUCCESS;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp = (vgen_ldc_t *)arg;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp = LDC_TO_VGEN(ldcp);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram statsp = &ldcp->stats;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "enter\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_enter(&ldcp->cblock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo statsp->callbacks++;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((ldcp->ldc_status == LDC_INIT) || (ldcp->ldc_handle == NULL)) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "status(%d) is LDC_INIT\n",
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ldcp->ldc_status);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&ldcp->cblock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (LDC_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG /*
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG * cache cancel_htid before the events specific
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG * code may overwrite it. Do not clear ldcp->cancel_htid
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG * as it is also used to indicate the timer to quit immediately.
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG */
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG cancel_htid = ldcp->cancel_htid;
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG
3af08d828975d7e2581b6829e0eecff14d87a483lm /*
3af08d828975d7e2581b6829e0eecff14d87a483lm * NOTE: not using switch() as event could be triggered by
3af08d828975d7e2581b6829e0eecff14d87a483lm * a state change and a read request. Also the ordering of the
3af08d828975d7e2581b6829e0eecff14d87a483lm * check for the event types is deliberate.
3af08d828975d7e2581b6829e0eecff14d87a483lm */
3af08d828975d7e2581b6829e0eecff14d87a483lm if (event & LDC_EVT_UP) {
3af08d828975d7e2581b6829e0eecff14d87a483lm if (ldc_status(ldcp->ldc_handle, &istatus) != 0) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "ldc_status err\n");
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram /* status couldn't be determined */
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG ret = LDC_FAILURE;
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG goto ldc_cb_ret;
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram }
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram ldcp->ldc_status = istatus;
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram if (ldcp->ldc_status != LDC_UP) {
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram DWARN(vgenp, ldcp, "LDC_EVT_UP received "
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram " but ldc status is not UP(0x%x)\n",
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram ldcp->ldc_status);
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram /* spurious interrupt, return success */
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG goto ldc_cb_ret;
3af08d828975d7e2581b6829e0eecff14d87a483lm }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "event(%lx) UP, status(%d)\n",
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram event, ldcp->ldc_status);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
678453a8ed49104d8adad58f3ba591bdc39883e8speer vgen_handle_evt_up(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
3af08d828975d7e2581b6829e0eecff14d87a483lm ASSERT((event & (LDC_EVT_RESET | LDC_EVT_DOWN)) == 0);
3af08d828975d7e2581b6829e0eecff14d87a483lm }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram /* Handle RESET/DOWN before READ event */
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram if (event & (LDC_EVT_RESET | LDC_EVT_DOWN)) {
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram if (ldc_status(ldcp->ldc_handle, &istatus) != 0) {
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram DWARN(vgenp, ldcp, "ldc_status error\n");
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram /* status couldn't be determined */
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG ret = LDC_FAILURE;
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG goto ldc_cb_ret;
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram }
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram ldcp->ldc_status = istatus;
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram DWARN(vgenp, ldcp, "event(%lx) RESET/DOWN, status(%d)\n",
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram event, ldcp->ldc_status);
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram
678453a8ed49104d8adad58f3ba591bdc39883e8speer vgen_handle_evt_reset(ldcp);
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram /*
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram * As the channel is down/reset, ignore READ event
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram * but print a debug warning message.
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram */
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram if (event & LDC_EVT_READ) {
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram DWARN(vgenp, ldcp,
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram "LDC_EVT_READ set along with RESET/DOWN\n");
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram event &= ~LDC_EVT_READ;
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram }
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram }
7062b44a173ea4621ab043112cbf2d9977480fa9raghuram
3af08d828975d7e2581b6829e0eecff14d87a483lm if (event & LDC_EVT_READ) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG2(vgenp, ldcp, "event(%lx) READ, status(%d)\n",
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram event, ldcp->ldc_status);
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm ASSERT((event & (LDC_EVT_RESET | LDC_EVT_DOWN)) == 0);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (ldcp->rcv_thread != NULL) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /*
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * If the receive thread is enabled, then
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * wakeup the receive thread to process the
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * LDC messages.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_exit(&ldcp->cblock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_enter(&ldcp->rcv_thr_lock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (!(ldcp->rcv_thr_flags & VGEN_WTHR_DATARCVD)) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ldcp->rcv_thr_flags |= VGEN_WTHR_DATARCVD;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram cv_signal(&ldcp->rcv_thr_cv);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_exit(&ldcp->rcv_thr_lock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_enter(&ldcp->cblock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram } else {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_handle_evt_read(ldcp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
3af08d828975d7e2581b6829e0eecff14d87a483lm }
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANGldc_cb_ret:
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG /*
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG * Check to see if the status of cancel_htid has
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG * changed. If another timer needs to be cancelled,
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG * then let the next callback to clear it.
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG */
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG if (cancel_htid == 0) {
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG cancel_htid = ldcp->cancel_htid;
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG }
3af08d828975d7e2581b6829e0eecff14d87a483lm mutex_exit(&ldcp->cblock);
3af08d828975d7e2581b6829e0eecff14d87a483lm
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG if (cancel_htid) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /*
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * Cancel handshake timer.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * untimeout(9F) will not return until the pending callback is
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * cancelled or has run. No problems will result from calling
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * untimeout if the handler has already completed.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * If the timeout handler did run, then it would just
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * return as cancel_htid is set.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram */
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG DBG2(vgenp, ldcp, "cancel_htid =0x%X \n", cancel_htid);
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG (void) untimeout(cancel_htid);
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG mutex_enter(&ldcp->cblock);
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG /* clear it only if its the same as the one we cancelled */
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG if (ldcp->cancel_htid == cancel_htid) {
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG ldcp->cancel_htid = 0;
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG }
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG mutex_exit(&ldcp->cblock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "exit\n");
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG return (ret);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram}
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramstatic void
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramvgen_handle_evt_read(vgen_ldc_t *ldcp)
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram{
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram int rv;
f0ca1d9a12d54d304791bc74525e2010ca924726sb uint64_t *ldcmsg;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram size_t msglen;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_t *vgenp = LDC_TO_VGEN(ldcp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vio_msg_tag_t *tagp;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ldc_status_t istatus;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram boolean_t has_data;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "enter\n");
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
f0ca1d9a12d54d304791bc74525e2010ca924726sb ldcmsg = ldcp->ldcmsg;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /*
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * If the receive thread is enabled, then the cblock
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * need to be acquired here. If not, the vgen_ldc_cb()
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * calls this function with cblock held already.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (ldcp->rcv_thread != NULL) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_enter(&ldcp->cblock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram } else {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ASSERT(MUTEX_HELD(&ldcp->cblock));
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
3af08d828975d7e2581b6829e0eecff14d87a483lm
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramvgen_evt_read:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo do {
f0ca1d9a12d54d304791bc74525e2010ca924726sb msglen = ldcp->msglen;
f0ca1d9a12d54d304791bc74525e2010ca924726sb rv = ldc_read(ldcp->ldc_handle, (caddr_t)ldcmsg, &msglen);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rv != 0) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "err rv(%d) len(%d)\n",
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram rv, msglen);
3af08d828975d7e2581b6829e0eecff14d87a483lm if (rv == ECONNRESET)
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram goto vgen_evtread_error;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (msglen == 0) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG2(vgenp, ldcp, "ldc_read NODATA");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG2(vgenp, ldcp, "ldc_read msglen(%d)", msglen);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp = (vio_msg_tag_t *)ldcmsg;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ldcp->peer_sid) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * check sid only after we have received peer's sid
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * in the version negotiate msg.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#ifdef DEBUG
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vgen_hdbg & HDBG_BAD_SID) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* simulate bad sid condition */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_sid = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_hdbg &= ~(HDBG_BAD_SID);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#endif
3af08d828975d7e2581b6829e0eecff14d87a483lm rv = vgen_check_sid(ldcp, tagp);
3af08d828975d7e2581b6829e0eecff14d87a483lm if (rv != VGEN_SUCCESS) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If sid mismatch is detected,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * reset the channel.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram goto vgen_evtread_error;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo switch (tagp->vio_msgtype) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VIO_TYPE_CTRL:
3af08d828975d7e2581b6829e0eecff14d87a483lm rv = vgen_handle_ctrlmsg(ldcp, tagp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VIO_TYPE_DATA:
f0ca1d9a12d54d304791bc74525e2010ca924726sb rv = vgen_handle_datamsg(ldcp, tagp, msglen);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VIO_TYPE_ERR:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_handle_errmsg(ldcp, tagp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo default:
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "Unknown VIO_TYPE(%x)\n",
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram tagp->vio_msgtype);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /*
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * If an error is encountered, stop processing and
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * handle the error.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (rv != 0) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram goto vgen_evtread_error;
3af08d828975d7e2581b6829e0eecff14d87a483lm }
3af08d828975d7e2581b6829e0eecff14d87a483lm
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } while (msglen);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* check once more before exiting */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram rv = ldc_chkq(ldcp->ldc_handle, &has_data);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if ((rv == 0) && (has_data == B_TRUE)) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DTRACE_PROBE(vgen_chkq);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram goto vgen_evt_read;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
3af08d828975d7e2581b6829e0eecff14d87a483lm
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramvgen_evtread_error:
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (rv == ECONNRESET) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (ldc_status(ldcp->ldc_handle, &istatus) != 0) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "ldc_status err\n");
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram } else {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ldcp->ldc_status = istatus;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
678453a8ed49104d8adad58f3ba591bdc39883e8speer vgen_handle_evt_reset(ldcp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram } else if (rv) {
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG vgen_ldc_reset(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /*
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG * If the receive thread is enabled, then cancel the
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * handshake timeout here.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (ldcp->rcv_thread != NULL) {
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG timeout_id_t cancel_htid = ldcp->cancel_htid;
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_exit(&ldcp->cblock);
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG if (cancel_htid) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /*
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * Cancel handshake timer. untimeout(9F) will
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * not return until the pending callback is cancelled
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * or has run. No problems will result from calling
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * untimeout if the handler has already completed.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * If the timeout handler did run, then it would just
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * return as cancel_htid is set.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram */
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG DBG2(vgenp, ldcp, "cancel_htid =0x%X \n", cancel_htid);
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG (void) untimeout(cancel_htid);
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG /*
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG * clear it only if its the same as the one we
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG * cancelled
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG */
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG mutex_enter(&ldcp->cblock);
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG if (ldcp->cancel_htid == cancel_htid) {
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG ldcp->cancel_htid = 0;
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG }
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG mutex_exit(&ldcp->cblock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "exit\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* vgen handshake functions */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* change the hphase for the channel to the next phase */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic vgen_ldc_t *
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovh_nextphase(vgen_ldc_t *ldcp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ldcp->hphase == VH_PHASE3) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->hphase = VH_DONE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } else {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->hphase++;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * wrapper routine to send the given message over ldc using ldc_write().
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_sendmsg(vgen_ldc_t *ldcp, caddr_t msg, size_t msglen,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo boolean_t caller_holds_lock)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
f0ca1d9a12d54d304791bc74525e2010ca924726sb int rv;
f0ca1d9a12d54d304791bc74525e2010ca924726sb size_t len;
f0ca1d9a12d54d304791bc74525e2010ca924726sb uint32_t retries = 0;
f0ca1d9a12d54d304791bc74525e2010ca924726sb vgen_t *vgenp = LDC_TO_VGEN(ldcp);
f0ca1d9a12d54d304791bc74525e2010ca924726sb vio_msg_tag_t *tagp = (vio_msg_tag_t *)msg;
f0ca1d9a12d54d304791bc74525e2010ca924726sb vio_dring_msg_t *dmsg;
f0ca1d9a12d54d304791bc74525e2010ca924726sb vio_raw_data_msg_t *rmsg;
f0ca1d9a12d54d304791bc74525e2010ca924726sb boolean_t data_msg = B_FALSE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo len = msglen;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((len == 0) || (msg == NULL))
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (!caller_holds_lock) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_enter(&ldcp->wrlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (tagp->vio_subtype == VIO_SUBTYPE_INFO) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (tagp->vio_subtype_env == VIO_DRING_DATA) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb dmsg = (vio_dring_msg_t *)tagp;
f0ca1d9a12d54d304791bc74525e2010ca924726sb dmsg->seq_num = ldcp->next_txseq;
f0ca1d9a12d54d304791bc74525e2010ca924726sb data_msg = B_TRUE;
f0ca1d9a12d54d304791bc74525e2010ca924726sb } else if (tagp->vio_subtype_env == VIO_PKT_DATA) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb rmsg = (vio_raw_data_msg_t *)tagp;
f0ca1d9a12d54d304791bc74525e2010ca924726sb rmsg->seq_num = ldcp->next_txseq;
f0ca1d9a12d54d304791bc74525e2010ca924726sb data_msg = B_TRUE;
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
f0ca1d9a12d54d304791bc74525e2010ca924726sb
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo do {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo len = msglen;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = ldc_write(ldcp->ldc_handle, (caddr_t)msg, &len);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (retries++ >= vgen_ldcwr_retries)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } while (rv == EWOULDBLOCK);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (rv == 0 && data_msg == B_TRUE) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb ldcp->next_txseq++;
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
f0ca1d9a12d54d304791bc74525e2010ca924726sb
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (!caller_holds_lock) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_exit(&ldcp->wrlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
3af08d828975d7e2581b6829e0eecff14d87a483lm if (rv != 0) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "ldc_write failed: rv(%d)\n",
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram rv, msglen);
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
3af08d828975d7e2581b6829e0eecff14d87a483lm }
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm if (len != msglen) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "ldc_write failed: rv(%d) msglen (%d)\n",
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram rv, msglen);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
3af08d828975d7e2581b6829e0eecff14d87a483lm
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* send version negotiate message to the peer over ldc */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_send_version_negotiate(vgen_ldc_t *ldcp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_t *vgenp = LDC_TO_VGEN(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vio_ver_msg_t vermsg;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vio_msg_tag_t *tagp = &vermsg.tag;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int rv;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bzero(&vermsg, sizeof (vermsg));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_msgtype = VIO_TYPE_CTRL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_subtype = VIO_SUBTYPE_INFO;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_subtype_env = VIO_VER_INFO;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_sid = ldcp->local_sid;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* get version msg payload from ldcp->local */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vermsg.ver_major = ldcp->local_hparams.ver_major;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vermsg.ver_minor = ldcp->local_hparams.ver_minor;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vermsg.dev_class = ldcp->local_hparams.dev_class;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (vermsg), B_FALSE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rv != VGEN_SUCCESS) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "vgen_sendmsg failed\n");
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->hstate |= VER_INFO_SENT;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG2(vgenp, ldcp, "VER_INFO_SENT ver(%d,%d)\n",
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vermsg.ver_major, vermsg.ver_minor);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* send attr info message to the peer over ldc */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_send_attr_info(vgen_ldc_t *ldcp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_t *vgenp = LDC_TO_VGEN(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vnet_attr_msg_t attrmsg;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vio_msg_tag_t *tagp = &attrmsg.tag;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int rv;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bzero(&attrmsg, sizeof (attrmsg));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_msgtype = VIO_TYPE_CTRL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_subtype = VIO_SUBTYPE_INFO;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_subtype_env = VIO_ATTR_INFO;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_sid = ldcp->local_sid;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* get attr msg payload from ldcp->local */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo attrmsg.mtu = ldcp->local_hparams.mtu;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo attrmsg.addr = ldcp->local_hparams.addr;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo attrmsg.addr_type = ldcp->local_hparams.addr_type;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo attrmsg.xfer_mode = ldcp->local_hparams.xfer_mode;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo attrmsg.ack_freq = ldcp->local_hparams.ack_freq;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna attrmsg.physlink_update = ldcp->local_hparams.physlink_update;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (attrmsg), B_FALSE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rv != VGEN_SUCCESS) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "vgen_sendmsg failed\n");
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->hstate |= ATTR_INFO_SENT;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG2(vgenp, ldcp, "ATTR_INFO_SENT\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* send descriptor ring register message to the peer over ldc */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_send_dring_reg(vgen_ldc_t *ldcp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_t *vgenp = LDC_TO_VGEN(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vio_dring_reg_msg_t msg;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vio_msg_tag_t *tagp = &msg.tag;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int rv;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bzero(&msg, sizeof (msg));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_msgtype = VIO_TYPE_CTRL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_subtype = VIO_SUBTYPE_INFO;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_subtype_env = VIO_DRING_REG;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_sid = ldcp->local_sid;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* get dring info msg payload from ldcp->local */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bcopy(&(ldcp->local_hparams.dring_cookie), (msg.cookie),
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram sizeof (ldc_mem_cookie_t));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo msg.ncookies = ldcp->local_hparams.num_dcookies;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo msg.num_descriptors = ldcp->local_hparams.num_desc;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo msg.descriptor_size = ldcp->local_hparams.desc_size;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * dring_ident is set to 0. After mapping the dring, peer sets this
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * value and sends it in the ack, which is saved in
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * vgen_handle_dring_reg().
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo msg.dring_ident = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (msg), B_FALSE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rv != VGEN_SUCCESS) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "vgen_sendmsg failed\n");
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->hstate |= DRING_INFO_SENT;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG2(vgenp, ldcp, "DRING_INFO_SENT \n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_send_rdx_info(vgen_ldc_t *ldcp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_t *vgenp = LDC_TO_VGEN(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vio_rdx_msg_t rdxmsg;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vio_msg_tag_t *tagp = &rdxmsg.tag;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int rv;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bzero(&rdxmsg, sizeof (rdxmsg));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_msgtype = VIO_TYPE_CTRL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_subtype = VIO_SUBTYPE_INFO;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_subtype_env = VIO_RDX;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_sid = ldcp->local_sid;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (rdxmsg), B_FALSE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rv != VGEN_SUCCESS) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "vgen_sendmsg failed\n");
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->hstate |= RDX_INFO_SENT;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG2(vgenp, ldcp, "RDX_INFO_SENT\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* send descriptor ring data message to the peer over ldc */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayanvgen_send_dring_data(vgen_ldc_t *ldcp, uint32_t start, int32_t end)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_t *vgenp = LDC_TO_VGEN(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vio_dring_msg_t dringmsg, *msgp = &dringmsg;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vio_msg_tag_t *tagp = &msgp->tag;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vgen_stats_t *statsp = &ldcp->stats;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int rv;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bzero(msgp, sizeof (*msgp));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_msgtype = VIO_TYPE_DATA;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_subtype = VIO_SUBTYPE_INFO;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_subtype_env = VIO_DRING_DATA;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_sid = ldcp->local_sid;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo msgp->dring_ident = ldcp->local_hparams.dring_ident;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo msgp->start_idx = start;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo msgp->end_idx = end;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (dringmsg), B_TRUE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rv != VGEN_SUCCESS) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "vgen_sendmsg failed\n");
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
06db247c678f0e3956535e8a6dec31d6c2108827raghuram statsp->dring_data_msgs++;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG2(vgenp, ldcp, "DRING_DATA_SENT \n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* send multicast addr info message to vsw */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_send_mcast_info(vgen_ldc_t *ldcp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vnet_mcast_msg_t mcastmsg;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vnet_mcast_msg_t *msgp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vio_msg_tag_t *tagp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_t *vgenp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo struct ether_addr *mca;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int rv;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int i;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint32_t size;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint32_t mccount;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint32_t n;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo msgp = &mcastmsg;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp = &msgp->tag;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp = LDC_TO_VGEN(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mccount = vgenp->mccount;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo i = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo do {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_msgtype = VIO_TYPE_CTRL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_subtype = VIO_SUBTYPE_INFO;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_subtype_env = VNET_MCAST_INFO;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_sid = ldcp->local_sid;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo n = ((mccount >= VNET_NUM_MCAST) ? VNET_NUM_MCAST : mccount);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo size = n * sizeof (struct ether_addr);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mca = &(vgenp->mctab[i]);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bcopy(mca, (msgp->mca), size);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo msgp->set = B_TRUE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo msgp->count = n;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (*msgp),
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo B_FALSE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rv != VGEN_SUCCESS) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "vgen_sendmsg err(%d)\n", rv);
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mccount -= n;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo i += n;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } while (mccount);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* Initiate Phase 2 of handshake */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_handshake_phase2(vgen_ldc_t *ldcp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int rv;
3af08d828975d7e2581b6829e0eecff14d87a483lm uint32_t ncookies = 0;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_t *vgenp = LDC_TO_VGEN(ldcp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#ifdef DEBUG
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vgen_hdbg & HDBG_OUT_STATE) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* simulate out of state condition */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_hdbg &= ~(HDBG_OUT_STATE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = vgen_send_rdx_info(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vgen_hdbg & HDBG_TIMEOUT) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* simulate timeout condition */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_hdbg &= ~(HDBG_TIMEOUT);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#endif
3af08d828975d7e2581b6829e0eecff14d87a483lm rv = vgen_send_attr_info(ldcp);
3af08d828975d7e2581b6829e0eecff14d87a483lm if (rv != VGEN_SUCCESS) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm /* Bind descriptor ring to the channel */
3af08d828975d7e2581b6829e0eecff14d87a483lm if (ldcp->num_txdcookies == 0) {
3af08d828975d7e2581b6829e0eecff14d87a483lm rv = ldc_mem_dring_bind(ldcp->ldc_handle, ldcp->tx_dhandle,
bbfa0259e68b6b625e9e085053d41d620f185eeeha LDC_DIRECT_MAP | LDC_SHADOW_MAP, LDC_MEM_RW,
bbfa0259e68b6b625e9e085053d41d620f185eeeha &ldcp->tx_dcookie, &ncookies);
3af08d828975d7e2581b6829e0eecff14d87a483lm if (rv != 0) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "ldc_mem_dring_bind failed "
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram "rv(%x)\n", rv);
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
3af08d828975d7e2581b6829e0eecff14d87a483lm }
3af08d828975d7e2581b6829e0eecff14d87a483lm ASSERT(ncookies == 1);
3af08d828975d7e2581b6829e0eecff14d87a483lm ldcp->num_txdcookies = ncookies;
3af08d828975d7e2581b6829e0eecff14d87a483lm }
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm /* update local dring_info params */
3af08d828975d7e2581b6829e0eecff14d87a483lm bcopy(&(ldcp->tx_dcookie), &(ldcp->local_hparams.dring_cookie),
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram sizeof (ldc_mem_cookie_t));
3af08d828975d7e2581b6829e0eecff14d87a483lm ldcp->local_hparams.num_dcookies = ldcp->num_txdcookies;
3af08d828975d7e2581b6829e0eecff14d87a483lm ldcp->local_hparams.num_desc = ldcp->num_txds;
3af08d828975d7e2581b6829e0eecff14d87a483lm ldcp->local_hparams.desc_size = sizeof (vnet_public_desc_t);
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm rv = vgen_send_dring_reg(ldcp);
3af08d828975d7e2581b6829e0eecff14d87a483lm if (rv != VGEN_SUCCESS) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
f0ca1d9a12d54d304791bc74525e2010ca924726sb/*
f0ca1d9a12d54d304791bc74525e2010ca924726sb * Set vnet-protocol-version dependent functions based on version.
f0ca1d9a12d54d304791bc74525e2010ca924726sb */
f0ca1d9a12d54d304791bc74525e2010ca924726sbstatic void
f0ca1d9a12d54d304791bc74525e2010ca924726sbvgen_set_vnet_proto_ops(vgen_ldc_t *ldcp)
f0ca1d9a12d54d304791bc74525e2010ca924726sb{
f0ca1d9a12d54d304791bc74525e2010ca924726sb vgen_hparams_t *lp = &ldcp->local_hparams;
f0ca1d9a12d54d304791bc74525e2010ca924726sb vgen_t *vgenp = LDC_TO_VGEN(ldcp);
f0ca1d9a12d54d304791bc74525e2010ca924726sb
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (VGEN_VER_GTEQ(ldcp, 1, 5)) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vgen_port_t *portp = ldcp->portp;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vnet_t *vnetp = vgenp->vnetp;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna /*
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * If the version negotiated with vswitch is >= 1.5 (link
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * status update support), set the required bits in our
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * attributes if this vnet device has been configured to get
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * physical link state updates.
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (portp == vgenp->vsw_portp && vnetp->pls_update == B_TRUE) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna lp->physlink_update = PHYSLINK_UPDATE_STATE;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna } else {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna lp->physlink_update = PHYSLINK_UPDATE_NONE;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna }
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna }
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna if (VGEN_VER_GTEQ(ldcp, 1, 4)) {
c1c61f44e88f4c8c155272ee56d868043146096asb /*
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * If the version negotiated with peer is >= 1.4(Jumbo Frame
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * Support), set the mtu in our attributes to max_frame_size.
c1c61f44e88f4c8c155272ee56d868043146096asb */
c1c61f44e88f4c8c155272ee56d868043146096asb lp->mtu = vgenp->max_frame_size;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna } else if (VGEN_VER_EQ(ldcp, 1, 3)) {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna /*
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * If the version negotiated with peer is == 1.3 (Vlan Tag
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * Support) set the attr.mtu to ETHERMAX + VLAN_TAGSZ.
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna lp->mtu = ETHERMAX + VLAN_TAGSZ;
c1c61f44e88f4c8c155272ee56d868043146096asb } else {
c1c61f44e88f4c8c155272ee56d868043146096asb vgen_port_t *portp = ldcp->portp;
c1c61f44e88f4c8c155272ee56d868043146096asb vnet_t *vnetp = vgenp->vnetp;
c1c61f44e88f4c8c155272ee56d868043146096asb /*
c1c61f44e88f4c8c155272ee56d868043146096asb * Pre-1.3 peers expect max frame size of ETHERMAX.
c1c61f44e88f4c8c155272ee56d868043146096asb * We can negotiate that size with those peers provided the
c1c61f44e88f4c8c155272ee56d868043146096asb * following conditions are true:
c1c61f44e88f4c8c155272ee56d868043146096asb * - Only pvid is defined for our peer and there are no vids.
c1c61f44e88f4c8c155272ee56d868043146096asb * - pvids are equal.
c1c61f44e88f4c8c155272ee56d868043146096asb * If the above conditions are true, then we can send/recv only
c1c61f44e88f4c8c155272ee56d868043146096asb * untagged frames of max size ETHERMAX.
c1c61f44e88f4c8c155272ee56d868043146096asb */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna if (portp->nvids == 0 && portp->pvid == vnetp->pvid) {
c1c61f44e88f4c8c155272ee56d868043146096asb lp->mtu = ETHERMAX;
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb if (VGEN_VER_GTEQ(ldcp, 1, 2)) {
c1c61f44e88f4c8c155272ee56d868043146096asb /* Versions >= 1.2 */
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (VGEN_PRI_ETH_DEFINED(vgenp)) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb /*
f0ca1d9a12d54d304791bc74525e2010ca924726sb * enable priority routines and pkt mode only if
f0ca1d9a12d54d304791bc74525e2010ca924726sb * at least one pri-eth-type is specified in MD.
f0ca1d9a12d54d304791bc74525e2010ca924726sb */
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb ldcp->tx = vgen_ldcsend;
f0ca1d9a12d54d304791bc74525e2010ca924726sb ldcp->rx_pktdata = vgen_handle_pkt_data;
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* set xfer mode for vgen_send_attr_info() */
f0ca1d9a12d54d304791bc74525e2010ca924726sb lp->xfer_mode = VIO_PKT_MODE | VIO_DRING_MODE_V1_2;
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb } else {
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* no priority eth types defined in MD */
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb ldcp->tx = vgen_ldcsend_dring;
f0ca1d9a12d54d304791bc74525e2010ca924726sb ldcp->rx_pktdata = vgen_handle_pkt_data_nop;
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* set xfer mode for vgen_send_attr_info() */
f0ca1d9a12d54d304791bc74525e2010ca924726sb lp->xfer_mode = VIO_DRING_MODE_V1_2;
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
f0ca1d9a12d54d304791bc74525e2010ca924726sb } else {
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* Versions prior to 1.2 */
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb vgen_reset_vnet_proto_ops(ldcp);
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
f0ca1d9a12d54d304791bc74525e2010ca924726sb}
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb/*
f0ca1d9a12d54d304791bc74525e2010ca924726sb * Reset vnet-protocol-version dependent functions to pre-v1.2.
f0ca1d9a12d54d304791bc74525e2010ca924726sb */
f0ca1d9a12d54d304791bc74525e2010ca924726sbstatic void
f0ca1d9a12d54d304791bc74525e2010ca924726sbvgen_reset_vnet_proto_ops(vgen_ldc_t *ldcp)
f0ca1d9a12d54d304791bc74525e2010ca924726sb{
f0ca1d9a12d54d304791bc74525e2010ca924726sb vgen_hparams_t *lp = &ldcp->local_hparams;
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb ldcp->tx = vgen_ldcsend_dring;
f0ca1d9a12d54d304791bc74525e2010ca924726sb ldcp->rx_pktdata = vgen_handle_pkt_data_nop;
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* set xfer mode for vgen_send_attr_info() */
f0ca1d9a12d54d304791bc74525e2010ca924726sb lp->xfer_mode = VIO_DRING_MODE_V1_0;
f0ca1d9a12d54d304791bc74525e2010ca924726sb}
f0ca1d9a12d54d304791bc74525e2010ca924726sb
c1c61f44e88f4c8c155272ee56d868043146096asbstatic void
c1c61f44e88f4c8c155272ee56d868043146096asbvgen_vlan_unaware_port_reset(vgen_port_t *portp)
c1c61f44e88f4c8c155272ee56d868043146096asb{
c1c61f44e88f4c8c155272ee56d868043146096asb vgen_ldclist_t *ldclp;
c1c61f44e88f4c8c155272ee56d868043146096asb vgen_ldc_t *ldcp;
c1c61f44e88f4c8c155272ee56d868043146096asb vgen_t *vgenp = portp->vgenp;
c1c61f44e88f4c8c155272ee56d868043146096asb vnet_t *vnetp = vgenp->vnetp;
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb ldclp = &portp->ldclist;
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb READ_ENTER(&ldclp->rwlock);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /*
c1c61f44e88f4c8c155272ee56d868043146096asb * NOTE: for now, we will assume we have a single channel.
c1c61f44e88f4c8c155272ee56d868043146096asb */
c1c61f44e88f4c8c155272ee56d868043146096asb if (ldclp->headp == NULL) {
c1c61f44e88f4c8c155272ee56d868043146096asb RW_EXIT(&ldclp->rwlock);
c1c61f44e88f4c8c155272ee56d868043146096asb return;
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb ldcp = ldclp->headp;
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb mutex_enter(&ldcp->cblock);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb /*
c1c61f44e88f4c8c155272ee56d868043146096asb * If the peer is vlan_unaware(ver < 1.3), reset channel and terminate
c1c61f44e88f4c8c155272ee56d868043146096asb * the connection. See comments in vgen_set_vnet_proto_ops().
c1c61f44e88f4c8c155272ee56d868043146096asb */
c1c61f44e88f4c8c155272ee56d868043146096asb if (ldcp->hphase == VH_DONE && VGEN_VER_LT(ldcp, 1, 3) &&
c1c61f44e88f4c8c155272ee56d868043146096asb (portp->nvids != 0 || portp->pvid != vnetp->pvid)) {
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG vgen_ldc_reset(ldcp);
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb mutex_exit(&ldcp->cblock);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb RW_EXIT(&ldclp->rwlock);
c1c61f44e88f4c8c155272ee56d868043146096asb}
c1c61f44e88f4c8c155272ee56d868043146096asb
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnastatic void
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnavgen_port_reset(vgen_port_t *portp)
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna{
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vgen_ldclist_t *ldclp;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vgen_ldc_t *ldcp;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna ldclp = &portp->ldclist;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna READ_ENTER(&ldclp->rwlock);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna /*
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * NOTE: for now, we will assume we have a single channel.
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (ldclp->headp == NULL) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna RW_EXIT(&ldclp->rwlock);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna return;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna }
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna ldcp = ldclp->headp;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna mutex_enter(&ldcp->cblock);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG vgen_ldc_reset(ldcp);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna mutex_exit(&ldcp->cblock);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna RW_EXIT(&ldclp->rwlock);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna}
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
c1c61f44e88f4c8c155272ee56d868043146096asbstatic void
c1c61f44e88f4c8c155272ee56d868043146096asbvgen_reset_vlan_unaware_ports(vgen_t *vgenp)
c1c61f44e88f4c8c155272ee56d868043146096asb{
c1c61f44e88f4c8c155272ee56d868043146096asb vgen_port_t *portp;
c1c61f44e88f4c8c155272ee56d868043146096asb vgen_portlist_t *plistp;
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb plistp = &(vgenp->vgenports);
c1c61f44e88f4c8c155272ee56d868043146096asb READ_ENTER(&plistp->rwlock);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb for (portp = plistp->headp; portp != NULL; portp = portp->nextp) {
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb vgen_vlan_unaware_port_reset(portp);
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb }
c1c61f44e88f4c8c155272ee56d868043146096asb
c1c61f44e88f4c8c155272ee56d868043146096asb RW_EXIT(&plistp->rwlock);
c1c61f44e88f4c8c155272ee56d868043146096asb}
c1c61f44e88f4c8c155272ee56d868043146096asb
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnastatic void
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnavgen_reset_vsw_port(vgen_t *vgenp)
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna{
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vgen_port_t *portp;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if ((portp = vgenp->vsw_portp) != NULL) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vgen_port_reset(portp);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna }
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna}
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * This function resets the handshake phase to VH_PHASE0(pre-handshake phase).
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * This can happen after a channel comes up (status: LDC_UP) or
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * when handshake gets terminated due to various conditions.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_reset_hphase(vgen_ldc_t *ldcp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_t *vgenp = LDC_TO_VGEN(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldc_status_t istatus;
3af08d828975d7e2581b6829e0eecff14d87a483lm int rv;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "enter\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* reset hstate and hphase */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->hstate = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->hphase = VH_PHASE0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
f0ca1d9a12d54d304791bc74525e2010ca924726sb vgen_reset_vnet_proto_ops(ldcp);
f0ca1d9a12d54d304791bc74525e2010ca924726sb
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan /*
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan * Save the id of pending handshake timer in cancel_htid.
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan * This will be checked in vgen_ldc_cb() and the handshake timer will
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan * be cancelled after releasing cblock.
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ldcp->htid) {
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan ldcp->cancel_htid = ldcp->htid;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->htid = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ldcp->local_hparams.dring_ready) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->local_hparams.dring_ready = B_FALSE;
3af08d828975d7e2581b6829e0eecff14d87a483lm }
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm /* Unbind tx descriptor ring from the channel */
3af08d828975d7e2581b6829e0eecff14d87a483lm if (ldcp->num_txdcookies) {
3af08d828975d7e2581b6829e0eecff14d87a483lm rv = ldc_mem_dring_unbind(ldcp->tx_dhandle);
3af08d828975d7e2581b6829e0eecff14d87a483lm if (rv != 0) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "ldc_mem_dring_unbind failed\n");
3af08d828975d7e2581b6829e0eecff14d87a483lm }
3af08d828975d7e2581b6829e0eecff14d87a483lm ldcp->num_txdcookies = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ldcp->peer_hparams.dring_ready) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->peer_hparams.dring_ready = B_FALSE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* Unmap peer's dring */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void) ldc_mem_dring_unmap(ldcp->rx_dhandle);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_clobber_rxds(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_clobber_tbufs(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * clear local handshake params and initialize.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bzero(&(ldcp->local_hparams), sizeof (ldcp->local_hparams));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* set version to the highest version supported */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->local_hparams.ver_major =
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram ldcp->vgen_versions[0].ver_major;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->local_hparams.ver_minor =
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram ldcp->vgen_versions[0].ver_minor;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->local_hparams.dev_class = VDEV_NETWORK;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* set attr_info params */
c1c61f44e88f4c8c155272ee56d868043146096asb ldcp->local_hparams.mtu = vgenp->max_frame_size;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->local_hparams.addr =
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy vnet_macaddr_strtoul(vgenp->macaddr);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->local_hparams.addr_type = ADDR_TYPE_MAC;
f0ca1d9a12d54d304791bc74525e2010ca924726sb ldcp->local_hparams.xfer_mode = VIO_DRING_MODE_V1_0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->local_hparams.ack_freq = 0; /* don't need acks */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna ldcp->local_hparams.physlink_update = PHYSLINK_UPDATE_NONE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
3af08d828975d7e2581b6829e0eecff14d87a483lm * Note: dring is created, but not bound yet.
3af08d828975d7e2581b6829e0eecff14d87a483lm * local dring_info params will be updated when we bind the dring in
3af08d828975d7e2581b6829e0eecff14d87a483lm * vgen_handshake_phase2().
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * dring_ident is set to 0. After mapping the dring, peer sets this
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * value and sends it in the ack, which is saved in
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * vgen_handle_dring_reg().
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->local_hparams.dring_ident = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* clear peer_hparams */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bzero(&(ldcp->peer_hparams), sizeof (ldcp->peer_hparams));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* reset the channel if required */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna#ifdef VNET_IOC_DEBUG
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (ldcp->need_ldc_reset && !ldcp->link_down_forced) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna#else
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ldcp->need_ldc_reset) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna#endif
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "Doing Channel Reset...\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->need_ldc_reset = B_FALSE;
e1ebb9ec908bc2d0a8810f137ebd6566cc8a8061lm (void) ldc_down(ldcp->ldc_handle);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void) ldc_status(ldcp->ldc_handle, &istatus);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG2(vgenp, ldcp, "Reset Done,ldc_status(%x)\n", istatus);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_status = istatus;
3af08d828975d7e2581b6829e0eecff14d87a483lm
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* clear sids */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->local_sid = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->peer_sid = 0;
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm /* try to bring the channel up */
3af08d828975d7e2581b6829e0eecff14d87a483lm rv = ldc_up(ldcp->ldc_handle);
3af08d828975d7e2581b6829e0eecff14d87a483lm if (rv != 0) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "ldc_up err rv(%d)\n", rv);
3af08d828975d7e2581b6829e0eecff14d87a483lm }
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm if (ldc_status(ldcp->ldc_handle, &istatus) != 0) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "ldc_status err\n");
3af08d828975d7e2581b6829e0eecff14d87a483lm } else {
3af08d828975d7e2581b6829e0eecff14d87a483lm ldcp->ldc_status = istatus;
3af08d828975d7e2581b6829e0eecff14d87a483lm }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* wrapper function for vgen_reset_hphase */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_handshake_reset(vgen_ldc_t *ldcp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vgen_t *vgenp = LDC_TO_VGEN(ldcp);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ASSERT(MUTEX_HELD(&ldcp->cblock));
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_enter(&ldcp->rxlock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_enter(&ldcp->wrlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_enter(&ldcp->txlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_enter(&ldcp->tclock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_reset_hphase(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&ldcp->tclock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&ldcp->txlock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_exit(&ldcp->wrlock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_exit(&ldcp->rxlock);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna /*
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * As the connection is now reset, mark the channel
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * link_state as 'down' and notify the stack if needed.
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (ldcp->link_state != LINK_STATE_DOWN) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna ldcp->link_state = LINK_STATE_DOWN;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (ldcp->portp == vgenp->vsw_portp) { /* vswitch port ? */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna /*
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * As the channel link is down, mark physical link also
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * as down. After the channel comes back up and
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * handshake completes, we will get an update on the
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * physlink state from vswitch (if this device has been
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * configured to get phys link updates).
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vgenp->phys_link_state = LINK_STATE_DOWN;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna /* Now update the stack */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna mutex_exit(&ldcp->cblock);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vgen_link_update(vgenp, ldcp->link_state);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna mutex_enter(&ldcp->cblock);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna }
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Initiate handshake with the peer by sending various messages
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * based on the handshake-phase that the channel is currently in.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_handshake(vgen_ldc_t *ldcp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna uint32_t hphase = ldcp->hphase;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vgen_t *vgenp = LDC_TO_VGEN(ldcp);
3af08d828975d7e2581b6829e0eecff14d87a483lm ldc_status_t istatus;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna int rv = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo switch (hphase) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VH_PHASE1:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * start timer, for entire handshake process, turn this timer
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * off if all phases of handshake complete successfully and
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * hphase goes to VH_DONE(below) or
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * vgen_reset_hphase() gets called or
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * channel is reset due to errors or
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * vgen_ldc_uninit() is invoked(vgen_stop).
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
52bca946f2d16ccff45516dc42994f01d01ec89fWENTAO YANG ASSERT(ldcp->htid == 0);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->htid = timeout(vgen_hwatchdog, (caddr_t)ldcp,
19b65a69adc64b3289ccb2fc32b805782e3f4540sb drv_usectohz(vgen_hwd_interval * MICROSEC));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* Phase 1 involves negotiating the version */
3af08d828975d7e2581b6829e0eecff14d87a483lm rv = vgen_send_version_negotiate(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VH_PHASE2:
3af08d828975d7e2581b6829e0eecff14d87a483lm rv = vgen_handshake_phase2(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VH_PHASE3:
3af08d828975d7e2581b6829e0eecff14d87a483lm rv = vgen_send_rdx_info(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VH_DONE:
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan /*
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan * Save the id of pending handshake timer in cancel_htid.
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan * This will be checked in vgen_ldc_cb() and the handshake
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan * timer will be cancelled after releasing cblock.
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ldcp->htid) {
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan ldcp->cancel_htid = ldcp->htid;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->htid = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->hretries = 0;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "Handshake Done\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna /*
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * The channel is up and handshake is done successfully. Now we
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * can mark the channel link_state as 'up'. We also notify the
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * stack if the channel is connected to vswitch.
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna ldcp->link_state = LINK_STATE_UP;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
19b65a69adc64b3289ccb2fc32b805782e3f4540sb if (ldcp->portp == vgenp->vsw_portp) {
19b65a69adc64b3289ccb2fc32b805782e3f4540sb /*
19b65a69adc64b3289ccb2fc32b805782e3f4540sb * If this channel(port) is connected to vsw,
19b65a69adc64b3289ccb2fc32b805782e3f4540sb * need to sync multicast table with vsw.
19b65a69adc64b3289ccb2fc32b805782e3f4540sb */
3af08d828975d7e2581b6829e0eecff14d87a483lm rv = vgen_send_mcast_info(ldcp);
0c4606f05172c66c6c65847c0f940871a0ea1c15WENTAO YANG if (rv != VGEN_SUCCESS) {
0c4606f05172c66c6c65847c0f940871a0ea1c15WENTAO YANG break;
0c4606f05172c66c6c65847c0f940871a0ea1c15WENTAO YANG }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (vgenp->pls_negotiated == B_FALSE) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna /*
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * We haven't negotiated with vswitch to get
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * physical link state updates. We can update
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * update the stack at this point as the
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * channel to vswitch is up and the handshake
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * is done successfully.
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna *
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * If we have negotiated to get physical link
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * state updates, then we won't notify the
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * the stack here; we do that as soon as
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * vswitch sends us the initial phys link state
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * (see vgen_handle_physlink_info()).
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna */
0c4606f05172c66c6c65847c0f940871a0ea1c15WENTAO YANG mutex_exit(&ldcp->cblock);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vgen_link_update(vgenp, ldcp->link_state);
0c4606f05172c66c6c65847c0f940871a0ea1c15WENTAO YANG mutex_enter(&ldcp->cblock);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna }
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
3af08d828975d7e2581b6829e0eecff14d87a483lm }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
3af08d828975d7e2581b6829e0eecff14d87a483lm /*
3af08d828975d7e2581b6829e0eecff14d87a483lm * Check if mac layer should be notified to restart
3af08d828975d7e2581b6829e0eecff14d87a483lm * transmissions. This can happen if the channel got
3af08d828975d7e2581b6829e0eecff14d87a483lm * reset and vgen_clobber_tbufs() is called, while
3af08d828975d7e2581b6829e0eecff14d87a483lm * need_resched is set.
3af08d828975d7e2581b6829e0eecff14d87a483lm */
3af08d828975d7e2581b6829e0eecff14d87a483lm mutex_enter(&ldcp->tclock);
3af08d828975d7e2581b6829e0eecff14d87a483lm if (ldcp->need_resched) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer vio_net_tx_update_t vtx_update =
678453a8ed49104d8adad58f3ba591bdc39883e8speer ldcp->portp->vcb.vio_net_tx_update;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
3af08d828975d7e2581b6829e0eecff14d87a483lm ldcp->need_resched = B_FALSE;
678453a8ed49104d8adad58f3ba591bdc39883e8speer vtx_update(ldcp->portp->vhp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
3af08d828975d7e2581b6829e0eecff14d87a483lm mutex_exit(&ldcp->tclock);
3af08d828975d7e2581b6829e0eecff14d87a483lm
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo default:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm if (rv == ECONNRESET) {
3af08d828975d7e2581b6829e0eecff14d87a483lm if (ldc_status(ldcp->ldc_handle, &istatus) != 0) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "ldc_status err\n");
3af08d828975d7e2581b6829e0eecff14d87a483lm } else {
3af08d828975d7e2581b6829e0eecff14d87a483lm ldcp->ldc_status = istatus;
3af08d828975d7e2581b6829e0eecff14d87a483lm }
678453a8ed49104d8adad58f3ba591bdc39883e8speer vgen_handle_evt_reset(ldcp);
3af08d828975d7e2581b6829e0eecff14d87a483lm } else if (rv) {
3af08d828975d7e2581b6829e0eecff14d87a483lm vgen_handshake_reset(ldcp);
3af08d828975d7e2581b6829e0eecff14d87a483lm }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Check if the current handshake phase has completed successfully and
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * return the status.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_handshake_done(vgen_ldc_t *ldcp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_t *vgenp = LDC_TO_VGEN(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint32_t hphase = ldcp->hphase;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int status = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo switch (hphase) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VH_PHASE1:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Phase1 is done, if version negotiation
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * completed successfully.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo status = ((ldcp->hstate & VER_NEGOTIATED) ==
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram VER_NEGOTIATED);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VH_PHASE2:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Phase 2 is done, if attr info and dring info
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * have been exchanged successfully.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo status = (((ldcp->hstate & ATTR_INFO_EXCHANGED) ==
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram ATTR_INFO_EXCHANGED) &&
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram ((ldcp->hstate & DRING_INFO_EXCHANGED) ==
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram DRING_INFO_EXCHANGED));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VH_PHASE3:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* Phase 3 is done, if rdx msg has been exchanged */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo status = ((ldcp->hstate & RDX_EXCHANGED) ==
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram RDX_EXCHANGED);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo default:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (status == 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG2(vgenp, ldcp, "PHASE(%d)\n", hphase);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* retry handshake on failure */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_handshake_retry(vgen_ldc_t *ldcp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* reset handshake phase */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_handshake_reset(ldcp);
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan /* handshake retry is specified and the channel is UP */
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan if (vgen_max_hretries && (ldcp->ldc_status == LDC_UP)) {
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan if (ldcp->hretries++ < vgen_max_hretries) {
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan ldcp->local_sid = ddi_get_lbolt();
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_handshake(vh_nextphase(ldcp));
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna/*
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * Link State Update Notes:
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * The link state of the channel connected to vswitch is reported as the link
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * state of the vnet device, by default. If the channel is down or reset, then
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * the link state is marked 'down'. If the channel is 'up' *and* handshake
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * between the vnet and vswitch is successful, then the link state is marked
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * 'up'. If physical network link state is desired, then the vnet device must
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * be configured to get physical link updates and the 'linkprop' property
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * in the virtual-device MD node indicates this. As part of attribute exchange
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * the vnet device negotiates with the vswitch to obtain physical link state
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * updates. If it successfully negotiates, vswitch sends an initial physlink
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * msg once the handshake is done and further whenever the physical link state
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * changes. Currently we don't have mac layer interfaces to report two distinct
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * link states - virtual and physical. Thus, if the vnet has been configured to
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * get physical link updates, then the link status will be reported as 'up'
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * only when both the virtual and physical links are up.
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnastatic void
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnavgen_link_update(vgen_t *vgenp, link_state_t link_state)
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna{
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vnet_link_update(vgenp->vnetp, link_state);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna}
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Handle a version info msg from the peer or an ACK/NACK from the peer
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * to a version info msg that we sent.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_handle_version_negotiate(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_t *vgenp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vio_ver_msg_t *vermsg = (vio_ver_msg_t *)tagp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int ack = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int failed = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int idx;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_ver_t *versions = ldcp->vgen_versions;
3af08d828975d7e2581b6829e0eecff14d87a483lm int rv = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgenp = LDC_TO_VGEN(ldcp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "enter\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo switch (tagp->vio_subtype) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VIO_SUBTYPE_INFO:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* Cache sid of peer if this is the first time */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ldcp->peer_sid == 0) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG2(vgenp, ldcp, "Caching peer_sid(%x)\n",
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram tagp->vio_sid);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->peer_sid = tagp->vio_sid;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ldcp->hphase != VH_PHASE1) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * If we are not already in VH_PHASE1, reset to
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * pre-handshake state, and initiate handshake
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * to the peer too.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_handshake_reset(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_handshake(vh_nextphase(ldcp));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->hstate |= VER_INFO_RCVD;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* save peer's requested values */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->peer_hparams.ver_major = vermsg->ver_major;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->peer_hparams.ver_minor = vermsg->ver_minor;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->peer_hparams.dev_class = vermsg->dev_class;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((vermsg->dev_class != VDEV_NETWORK) &&
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (vermsg->dev_class != VDEV_NETWORK_SWITCH)) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* unsupported dev_class, send NACK */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "Version Negotiation Failed\n");
3af08d828975d7e2581b6829e0eecff14d87a483lm
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_subtype = VIO_SUBTYPE_NACK;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_sid = ldcp->local_sid;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* send reply msg back to peer */
3af08d828975d7e2581b6829e0eecff14d87a483lm rv = vgen_sendmsg(ldcp, (caddr_t)tagp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo sizeof (*vermsg), B_FALSE);
3af08d828975d7e2581b6829e0eecff14d87a483lm if (rv != VGEN_SUCCESS) {
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
3af08d828975d7e2581b6829e0eecff14d87a483lm }
3af08d828975d7e2581b6829e0eecff14d87a483lm return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG2(vgenp, ldcp, "VER_INFO_RCVD, ver(%d,%d)\n",
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vermsg->ver_major, vermsg->ver_minor);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo idx = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (;;) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vermsg->ver_major > versions[idx].ver_major) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* nack with next lower version */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_subtype = VIO_SUBTYPE_NACK;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vermsg->ver_major = versions[idx].ver_major;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vermsg->ver_minor = versions[idx].ver_minor;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vermsg->ver_major == versions[idx].ver_major) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* major version match - ACK version */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_subtype = VIO_SUBTYPE_ACK;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ack = 1;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * lower minor version to the one this endpt
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * supports, if necessary
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vermsg->ver_minor >
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo versions[idx].ver_minor) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vermsg->ver_minor =
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram versions[idx].ver_minor;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->peer_hparams.ver_minor =
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram versions[idx].ver_minor;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo idx++;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (idx == VGEN_NUM_VER) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* no version match - send NACK */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_subtype = VIO_SUBTYPE_NACK;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vermsg->ver_major = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vermsg->ver_minor = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo failed = 1;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_sid = ldcp->local_sid;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* send reply msg back to peer */
3af08d828975d7e2581b6829e0eecff14d87a483lm rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (*vermsg),
3af08d828975d7e2581b6829e0eecff14d87a483lm B_FALSE);
3af08d828975d7e2581b6829e0eecff14d87a483lm if (rv != VGEN_SUCCESS) {
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ack) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->hstate |= VER_ACK_SENT;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG2(vgenp, ldcp, "VER_ACK_SENT, ver(%d,%d) \n",
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vermsg->ver_major, vermsg->ver_minor);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (failed) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "Negotiation Failed\n");
3af08d828975d7e2581b6829e0eecff14d87a483lm return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vgen_handshake_done(ldcp) == VGEN_SUCCESS) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* VER_ACK_SENT and VER_ACK_RCVD */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* local and peer versions match? */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ASSERT((ldcp->local_hparams.ver_major ==
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram ldcp->peer_hparams.ver_major) &&
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram (ldcp->local_hparams.ver_minor ==
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram ldcp->peer_hparams.ver_minor));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
f0ca1d9a12d54d304791bc74525e2010ca924726sb vgen_set_vnet_proto_ops(ldcp);
f0ca1d9a12d54d304791bc74525e2010ca924726sb
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* move to the next phase */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_handshake(vh_nextphase(ldcp));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VIO_SUBTYPE_ACK:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ldcp->hphase != VH_PHASE1) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* This should not happen. */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "Invalid Phase(%u)\n", ldcp->hphase);
3af08d828975d7e2581b6829e0eecff14d87a483lm return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* SUCCESS - we have agreed on a version */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->local_hparams.ver_major = vermsg->ver_major;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->local_hparams.ver_minor = vermsg->ver_minor;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->hstate |= VER_ACK_RCVD;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG2(vgenp, ldcp, "VER_ACK_RCVD, ver(%d,%d) \n",
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vermsg->ver_major, vermsg->ver_minor);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vgen_handshake_done(ldcp) == VGEN_SUCCESS) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* VER_ACK_SENT and VER_ACK_RCVD */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* local and peer versions match? */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ASSERT((ldcp->local_hparams.ver_major ==
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram ldcp->peer_hparams.ver_major) &&
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram (ldcp->local_hparams.ver_minor ==
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram ldcp->peer_hparams.ver_minor));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
f0ca1d9a12d54d304791bc74525e2010ca924726sb vgen_set_vnet_proto_ops(ldcp);
f0ca1d9a12d54d304791bc74525e2010ca924726sb
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* move to the next phase */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_handshake(vh_nextphase(ldcp));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VIO_SUBTYPE_NACK:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ldcp->hphase != VH_PHASE1) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* This should not happen. */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "VER_NACK_RCVD Invalid "
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram "Phase(%u)\n", ldcp->hphase);
3af08d828975d7e2581b6829e0eecff14d87a483lm return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG2(vgenp, ldcp, "VER_NACK_RCVD next ver(%d,%d)\n",
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vermsg->ver_major, vermsg->ver_minor);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* check if version in NACK is zero */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vermsg->ver_major == 0 && vermsg->ver_minor == 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Version Negotiation has failed.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "Version Negotiation Failed\n");
3af08d828975d7e2581b6829e0eecff14d87a483lm return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo idx = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (;;) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vermsg->ver_major > versions[idx].ver_major) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* select next lower version */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->local_hparams.ver_major =
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram versions[idx].ver_major;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->local_hparams.ver_minor =
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram versions[idx].ver_minor;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vermsg->ver_major == versions[idx].ver_major) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* major version match */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->local_hparams.ver_major =
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram versions[idx].ver_major;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->local_hparams.ver_minor =
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram versions[idx].ver_minor;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo idx++;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (idx == VGEN_NUM_VER) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * no version match.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Version Negotiation has failed.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram "Version Negotiation Failed\n");
3af08d828975d7e2581b6829e0eecff14d87a483lm return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
3af08d828975d7e2581b6829e0eecff14d87a483lm rv = vgen_send_version_negotiate(ldcp);
3af08d828975d7e2581b6829e0eecff14d87a483lm if (rv != VGEN_SUCCESS) {
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
3af08d828975d7e2581b6829e0eecff14d87a483lm
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "exit\n");
3af08d828975d7e2581b6829e0eecff14d87a483lm return (VGEN_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* Check if the attributes are supported */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_check_attr_info(vgen_ldc_t *ldcp, vnet_attr_msg_t *msg)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
f0ca1d9a12d54d304791bc74525e2010ca924726sb vgen_hparams_t *lp = &ldcp->local_hparams;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna if ((msg->addr_type != ADDR_TYPE_MAC) ||
f0ca1d9a12d54d304791bc74525e2010ca924726sb (msg->ack_freq > 64) ||
f0ca1d9a12d54d304791bc74525e2010ca924726sb (msg->xfer_mode != lp->xfer_mode)) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna if (VGEN_VER_LT(ldcp, 1, 4)) {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna /* versions < 1.4, mtu must match */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna if (msg->mtu != lp->mtu) {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna return (VGEN_FAILURE);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna }
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna } else {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna /* Ver >= 1.4, validate mtu of the peer is at least ETHERMAX */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna if (msg->mtu < ETHERMAX) {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna return (VGEN_FAILURE);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna }
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna }
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Handle an attribute info msg from the peer or an ACK/NACK from the peer
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * to an attr info msg that we sent.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_handle_attr_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna vgen_t *vgenp = LDC_TO_VGEN(ldcp);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna vnet_attr_msg_t *msg = (vnet_attr_msg_t *)tagp;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna vgen_hparams_t *lp = &ldcp->local_hparams;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna vgen_hparams_t *rp = &ldcp->peer_hparams;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna int ack = 1;
3af08d828975d7e2581b6829e0eecff14d87a483lm int rv = 0;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna uint32_t mtu;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "enter\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ldcp->hphase != VH_PHASE2) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "Rcvd ATTR_INFO subtype(%d),"
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram " Invalid Phase(%u)\n",
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram tagp->vio_subtype, ldcp->hphase);
3af08d828975d7e2581b6829e0eecff14d87a483lm return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo switch (tagp->vio_subtype) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VIO_SUBTYPE_INFO:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG2(vgenp, ldcp, "ATTR_INFO_RCVD \n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->hstate |= ATTR_INFO_RCVD;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* save peer's values */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna rp->mtu = msg->mtu;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna rp->addr = msg->addr;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna rp->addr_type = msg->addr_type;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna rp->xfer_mode = msg->xfer_mode;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna rp->ack_freq = msg->ack_freq;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna rv = vgen_check_attr_info(ldcp, msg);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna if (rv == VGEN_FAILURE) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* unsupported attr, send NACK */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna ack = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } else {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna if (VGEN_VER_GTEQ(ldcp, 1, 4)) {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna /*
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * Versions >= 1.4:
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * The mtu is negotiated down to the
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * minimum of our mtu and peer's mtu.
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna mtu = MIN(msg->mtu, vgenp->max_frame_size);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna /*
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * If we have received an ack for the attr info
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * that we sent, then check if the mtu computed
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * above matches the mtu that the peer had ack'd
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * (saved in local hparams). If they don't
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * match, we fail the handshake.
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna if (ldcp->hstate & ATTR_ACK_RCVD) {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna if (mtu != lp->mtu) {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna /* send NACK */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna ack = 0;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna }
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna } else {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna /*
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * Save the mtu computed above in our
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * attr parameters, so it gets sent in
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * the attr info from us to the peer.
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna lp->mtu = mtu;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna }
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna /* save the MIN mtu in the msg to be replied */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna msg->mtu = mtu;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna }
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna }
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna if (ack) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_subtype = VIO_SUBTYPE_ACK;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna } else {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna tagp->vio_subtype = VIO_SUBTYPE_NACK;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_sid = ldcp->local_sid;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* send reply msg back to peer */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (*msg),
3af08d828975d7e2581b6829e0eecff14d87a483lm B_FALSE);
3af08d828975d7e2581b6829e0eecff14d87a483lm if (rv != VGEN_SUCCESS) {
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ack) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->hstate |= ATTR_ACK_SENT;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG2(vgenp, ldcp, "ATTR_ACK_SENT \n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } else {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* failed */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "ATTR_NACK_SENT \n");
3af08d828975d7e2581b6829e0eecff14d87a483lm return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vgen_handshake_done(ldcp) == VGEN_SUCCESS) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_handshake(vh_nextphase(ldcp));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VIO_SUBTYPE_ACK:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (VGEN_VER_GTEQ(ldcp, 1, 5) &&
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna ldcp->portp == vgenp->vsw_portp) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna /*
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * Versions >= 1.5:
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * If the vnet device has been configured to get
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * physical link state updates, check the corresponding
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * bits in the ack msg, if the peer is vswitch.
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (((lp->physlink_update &
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna PHYSLINK_UPDATE_STATE_MASK) ==
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna PHYSLINK_UPDATE_STATE) &&
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna ((msg->physlink_update &
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna PHYSLINK_UPDATE_STATE_MASK) ==
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna PHYSLINK_UPDATE_STATE_ACK)) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vgenp->pls_negotiated = B_TRUE;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna } else {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vgenp->pls_negotiated = B_FALSE;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna }
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna }
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna if (VGEN_VER_GTEQ(ldcp, 1, 4)) {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna /*
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * Versions >= 1.4:
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * The ack msg sent by the peer contains the minimum of
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * our mtu (that we had sent in our attr info) and the
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * peer's mtu.
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna *
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * If we have sent an ack for the attr info msg from
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * the peer, check if the mtu that was computed then
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * (saved in local hparams) matches the mtu that the
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * peer has ack'd. If they don't match, we fail the
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * handshake.
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna if (ldcp->hstate & ATTR_ACK_SENT) {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna if (lp->mtu != msg->mtu) {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna return (VGEN_FAILURE);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna }
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna } else {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna /*
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * If the mtu ack'd by the peer is > our mtu
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * fail handshake. Otherwise, save the mtu, so
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * we can validate it when we receive attr info
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * from our peer.
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna if (msg->mtu > lp->mtu) {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna return (VGEN_FAILURE);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna }
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna if (msg->mtu <= lp->mtu) {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna lp->mtu = msg->mtu;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna }
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna }
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna }
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->hstate |= ATTR_ACK_RCVD;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG2(vgenp, ldcp, "ATTR_ACK_RCVD \n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vgen_handshake_done(ldcp) == VGEN_SUCCESS) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_handshake(vh_nextphase(ldcp));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VIO_SUBTYPE_NACK:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG2(vgenp, ldcp, "ATTR_NACK_RCVD \n");
3af08d828975d7e2581b6829e0eecff14d87a483lm return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "exit\n");
3af08d828975d7e2581b6829e0eecff14d87a483lm return (VGEN_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* Check if the dring info msg is ok */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_check_dring_reg(vio_dring_reg_msg_t *msg)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* check if msg contents are ok */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((msg->num_descriptors < 128) || (msg->descriptor_size <
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo sizeof (vnet_public_desc_t))) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Handle a descriptor ring register msg from the peer or an ACK/NACK from
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * the peer to a dring register msg that we sent.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_handle_dring_reg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vio_dring_reg_msg_t *msg = (vio_dring_reg_msg_t *)tagp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldc_mem_cookie_t dcookie;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_t *vgenp = LDC_TO_VGEN(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int ack = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int rv = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "enter\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ldcp->hphase < VH_PHASE2) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* dring_info can be rcvd in any of the phases after Phase1 */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram "Rcvd DRING_INFO Subtype (%d), Invalid Phase(%u)\n",
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram tagp->vio_subtype, ldcp->hphase);
3af08d828975d7e2581b6829e0eecff14d87a483lm return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo switch (tagp->vio_subtype) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VIO_SUBTYPE_INFO:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG2(vgenp, ldcp, "DRING_INFO_RCVD \n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->hstate |= DRING_INFO_RCVD;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bcopy((msg->cookie), &dcookie, sizeof (dcookie));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ASSERT(msg->ncookies == 1);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vgen_check_dring_reg(msg) == VGEN_SUCCESS) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * verified dring info msg to be ok,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * now try to map the remote dring.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = vgen_init_rxds(ldcp, msg->num_descriptors,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo msg->descriptor_size, &dcookie,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo msg->ncookies);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rv == DDI_SUCCESS) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* now we can ack the peer */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ack = 1;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ack == 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* failed, send NACK */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_subtype = VIO_SUBTYPE_NACK;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } else {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (!(ldcp->peer_hparams.dring_ready)) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* save peer's dring_info values */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bcopy(&dcookie,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo &(ldcp->peer_hparams.dring_cookie),
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo sizeof (dcookie));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->peer_hparams.num_desc =
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram msg->num_descriptors;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->peer_hparams.desc_size =
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram msg->descriptor_size;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->peer_hparams.num_dcookies =
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram msg->ncookies;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* set dring_ident for the peer */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->peer_hparams.dring_ident =
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram (uint64_t)ldcp->rxdp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* return the dring_ident in ack msg */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo msg->dring_ident =
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram (uint64_t)ldcp->rxdp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->peer_hparams.dring_ready = B_TRUE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_subtype = VIO_SUBTYPE_ACK;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_sid = ldcp->local_sid;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* send reply msg back to peer */
3af08d828975d7e2581b6829e0eecff14d87a483lm rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (*msg),
3af08d828975d7e2581b6829e0eecff14d87a483lm B_FALSE);
3af08d828975d7e2581b6829e0eecff14d87a483lm if (rv != VGEN_SUCCESS) {
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ack) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->hstate |= DRING_ACK_SENT;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG2(vgenp, ldcp, "DRING_ACK_SENT");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } else {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "DRING_NACK_SENT");
3af08d828975d7e2581b6829e0eecff14d87a483lm return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vgen_handshake_done(ldcp) == VGEN_SUCCESS) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_handshake(vh_nextphase(ldcp));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VIO_SUBTYPE_ACK:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->hstate |= DRING_ACK_RCVD;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG2(vgenp, ldcp, "DRING_ACK_RCVD");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (!(ldcp->local_hparams.dring_ready)) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* local dring is now ready */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->local_hparams.dring_ready = B_TRUE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* save dring_ident acked by peer */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->local_hparams.dring_ident =
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram msg->dring_ident;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vgen_handshake_done(ldcp) == VGEN_SUCCESS) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_handshake(vh_nextphase(ldcp));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VIO_SUBTYPE_NACK:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG2(vgenp, ldcp, "DRING_NACK_RCVD");
3af08d828975d7e2581b6829e0eecff14d87a483lm return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "exit\n");
3af08d828975d7e2581b6829e0eecff14d87a483lm return (VGEN_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Handle a rdx info msg from the peer or an ACK/NACK
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * from the peer to a rdx info msg that we sent.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_handle_rdx_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
3af08d828975d7e2581b6829e0eecff14d87a483lm int rv = 0;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_t *vgenp = LDC_TO_VGEN(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "enter\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ldcp->hphase != VH_PHASE3) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram "Rcvd RDX_INFO Subtype (%d), Invalid Phase(%u)\n",
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram tagp->vio_subtype, ldcp->hphase);
3af08d828975d7e2581b6829e0eecff14d87a483lm return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo switch (tagp->vio_subtype) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VIO_SUBTYPE_INFO:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG2(vgenp, ldcp, "RDX_INFO_RCVD \n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->hstate |= RDX_INFO_RCVD;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_subtype = VIO_SUBTYPE_ACK;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_sid = ldcp->local_sid;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* send reply msg back to peer */
3af08d828975d7e2581b6829e0eecff14d87a483lm rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (vio_rdx_msg_t),
3af08d828975d7e2581b6829e0eecff14d87a483lm B_FALSE);
3af08d828975d7e2581b6829e0eecff14d87a483lm if (rv != VGEN_SUCCESS) {
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->hstate |= RDX_ACK_SENT;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG2(vgenp, ldcp, "RDX_ACK_SENT \n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vgen_handshake_done(ldcp) == VGEN_SUCCESS) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_handshake(vh_nextphase(ldcp));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VIO_SUBTYPE_ACK:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->hstate |= RDX_ACK_RCVD;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG2(vgenp, ldcp, "RDX_ACK_RCVD \n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vgen_handshake_done(ldcp) == VGEN_SUCCESS) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_handshake(vh_nextphase(ldcp));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VIO_SUBTYPE_NACK:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG2(vgenp, ldcp, "RDX_NACK_RCVD \n");
3af08d828975d7e2581b6829e0eecff14d87a483lm return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "exit\n");
3af08d828975d7e2581b6829e0eecff14d87a483lm return (VGEN_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* Handle ACK/NACK from vsw to a set multicast msg that we sent */
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_handle_mcast_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_t *vgenp = LDC_TO_VGEN(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vnet_mcast_msg_t *msgp = (vnet_mcast_msg_t *)tagp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo struct ether_addr *addrp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int count;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int i;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "enter\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo switch (tagp->vio_subtype) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VIO_SUBTYPE_INFO:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* vnet shouldn't recv set mcast msg, only vsw handles it */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "rcvd SET_MCAST_INFO \n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VIO_SUBTYPE_ACK:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* success adding/removing multicast addr */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "rcvd SET_MCAST_ACK \n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VIO_SUBTYPE_NACK:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "rcvd SET_MCAST_NACK \n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (!(msgp->set)) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* multicast remove request failed */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* multicast add request failed */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (count = 0; count < msgp->count; count++) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo addrp = &(msgp->mca[count]);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* delete address from the table */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (i = 0; i < vgenp->mccount; i++) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ether_cmp(addrp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo &(vgenp->mctab[i])) == 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vgenp->mccount > 1) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram int t = vgenp->mccount - 1;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp->mctab[i] =
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram vgenp->mctab[t];
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp->mccount--;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "exit\n");
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm return (VGEN_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna/*
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * Physical link information message from the peer. Only vswitch should send
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * us this message; if the vnet device has been configured to get physical link
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * state updates. Note that we must have already negotiated this with the
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * vswitch during attribute exchange phase of handshake.
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnastatic int
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnavgen_handle_physlink_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna{
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vgen_t *vgenp = LDC_TO_VGEN(ldcp);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vnet_physlink_msg_t *msgp = (vnet_physlink_msg_t *)tagp;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna link_state_t link_state;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna int rv;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (ldcp->portp != vgenp->vsw_portp) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna /*
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * drop the message and don't process; as we should
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * receive physlink_info message from only vswitch.
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna return (VGEN_SUCCESS);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna }
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (vgenp->pls_negotiated == B_FALSE) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna /*
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * drop the message and don't process; as we should receive
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * physlink_info message only if physlink update is enabled for
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * the device and negotiated with vswitch.
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna return (VGEN_SUCCESS);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna }
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna switch (tagp->vio_subtype) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna case VIO_SUBTYPE_INFO:
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if ((msgp->physlink_info & VNET_PHYSLINK_STATE_MASK) ==
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna VNET_PHYSLINK_STATE_UP) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna link_state = LINK_STATE_UP;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna } else {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna link_state = LINK_STATE_DOWN;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna }
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (vgenp->phys_link_state != link_state) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vgenp->phys_link_state = link_state;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna mutex_exit(&ldcp->cblock);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna /* Now update the stack */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vgen_link_update(vgenp, link_state);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna mutex_enter(&ldcp->cblock);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna }
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna tagp->vio_subtype = VIO_SUBTYPE_ACK;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna tagp->vio_sid = ldcp->local_sid;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna /* send reply msg back to peer */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna rv = vgen_sendmsg(ldcp, (caddr_t)tagp,
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna sizeof (vnet_physlink_msg_t), B_FALSE);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (rv != VGEN_SUCCESS) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna return (rv);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna }
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna break;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna case VIO_SUBTYPE_ACK:
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna /* vnet shouldn't recv physlink acks */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna DWARN(vgenp, ldcp, "rcvd PHYSLINK_ACK \n");
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna break;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna case VIO_SUBTYPE_NACK:
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna /* vnet shouldn't recv physlink nacks */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna DWARN(vgenp, ldcp, "rcvd PHYSLINK_NACK \n");
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna break;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna }
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna DBG1(vgenp, ldcp, "exit\n");
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna return (VGEN_SUCCESS);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna}
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* handler for control messages received from the peer ldc end-point */
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_handle_ctrlmsg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
3af08d828975d7e2581b6829e0eecff14d87a483lm int rv = 0;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_t *vgenp = LDC_TO_VGEN(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "enter\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo switch (tagp->vio_subtype_env) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VIO_VER_INFO:
3af08d828975d7e2581b6829e0eecff14d87a483lm rv = vgen_handle_version_negotiate(ldcp, tagp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VIO_ATTR_INFO:
3af08d828975d7e2581b6829e0eecff14d87a483lm rv = vgen_handle_attr_info(ldcp, tagp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VIO_DRING_REG:
3af08d828975d7e2581b6829e0eecff14d87a483lm rv = vgen_handle_dring_reg(ldcp, tagp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VIO_RDX:
3af08d828975d7e2581b6829e0eecff14d87a483lm rv = vgen_handle_rdx_info(ldcp, tagp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VNET_MCAST_INFO:
3af08d828975d7e2581b6829e0eecff14d87a483lm rv = vgen_handle_mcast_info(ldcp, tagp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
678453a8ed49104d8adad58f3ba591bdc39883e8speer case VIO_DDS_INFO:
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG /*
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG * If we are in the process of resetting the vswitch channel,
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG * drop the dds message. A new handshake will be initiated
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG * when the channel comes back up after the reset and dds
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG * negotiation can then continue.
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG */
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG if (ldcp->need_ldc_reset == B_TRUE) {
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG break;
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG }
678453a8ed49104d8adad58f3ba591bdc39883e8speer rv = vgen_dds_rx(ldcp, tagp);
678453a8ed49104d8adad58f3ba591bdc39883e8speer break;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna case VNET_PHYSLINK_INFO:
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna rv = vgen_handle_physlink_info(ldcp, tagp);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
3af08d828975d7e2581b6829e0eecff14d87a483lm
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "exit rv(%d)\n", rv);
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* handler for data messages received from the peer ldc end-point */
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic int
f0ca1d9a12d54d304791bc74525e2010ca924726sbvgen_handle_datamsg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp, uint32_t msglen)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
3af08d828975d7e2581b6829e0eecff14d87a483lm int rv = 0;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_t *vgenp = LDC_TO_VGEN(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "enter\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ldcp->hphase != VH_DONE)
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (tagp->vio_subtype == VIO_SUBTYPE_INFO) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb rv = vgen_check_datamsg_seq(ldcp, tagp);
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (rv != 0) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb return (rv);
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
f0ca1d9a12d54d304791bc74525e2010ca924726sb
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo switch (tagp->vio_subtype_env) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VIO_DRING_DATA:
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram rv = vgen_handle_dring_data(ldcp, tagp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb case VIO_PKT_DATA:
f0ca1d9a12d54d304791bc74525e2010ca924726sb ldcp->rx_pktdata((void *)ldcp, (void *)tagp, msglen);
f0ca1d9a12d54d304791bc74525e2010ca924726sb break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo default:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "exit rv(%d)\n", rv);
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
f0ca1d9a12d54d304791bc74525e2010ca924726sb/*
f0ca1d9a12d54d304791bc74525e2010ca924726sb * dummy pkt data handler function for vnet protocol version 1.0
f0ca1d9a12d54d304791bc74525e2010ca924726sb */
f0ca1d9a12d54d304791bc74525e2010ca924726sbstatic void
f0ca1d9a12d54d304791bc74525e2010ca924726sbvgen_handle_pkt_data_nop(void *arg1, void *arg2, uint32_t msglen)
f0ca1d9a12d54d304791bc74525e2010ca924726sb{
f0ca1d9a12d54d304791bc74525e2010ca924726sb _NOTE(ARGUNUSED(arg1, arg2, msglen))
f0ca1d9a12d54d304791bc74525e2010ca924726sb}
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb/*
f0ca1d9a12d54d304791bc74525e2010ca924726sb * This function handles raw pkt data messages received over the channel.
f0ca1d9a12d54d304791bc74525e2010ca924726sb * Currently, only priority-eth-type frames are received through this mechanism.
f0ca1d9a12d54d304791bc74525e2010ca924726sb * In this case, the frame(data) is present within the message itself which
f0ca1d9a12d54d304791bc74525e2010ca924726sb * is copied into an mblk before sending it up the stack.
f0ca1d9a12d54d304791bc74525e2010ca924726sb */
f0ca1d9a12d54d304791bc74525e2010ca924726sbstatic void
f0ca1d9a12d54d304791bc74525e2010ca924726sbvgen_handle_pkt_data(void *arg1, void *arg2, uint32_t msglen)
f0ca1d9a12d54d304791bc74525e2010ca924726sb{
f0ca1d9a12d54d304791bc74525e2010ca924726sb vgen_ldc_t *ldcp = (vgen_ldc_t *)arg1;
f0ca1d9a12d54d304791bc74525e2010ca924726sb vio_raw_data_msg_t *pkt = (vio_raw_data_msg_t *)arg2;
f0ca1d9a12d54d304791bc74525e2010ca924726sb uint32_t size;
f0ca1d9a12d54d304791bc74525e2010ca924726sb mblk_t *mp;
f0ca1d9a12d54d304791bc74525e2010ca924726sb vgen_t *vgenp = LDC_TO_VGEN(ldcp);
f0ca1d9a12d54d304791bc74525e2010ca924726sb vgen_stats_t *statsp = &ldcp->stats;
c1c61f44e88f4c8c155272ee56d868043146096asb vgen_hparams_t *lp = &ldcp->local_hparams;
678453a8ed49104d8adad58f3ba591bdc39883e8speer vio_net_rx_cb_t vrx_cb;
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb ASSERT(MUTEX_HELD(&ldcp->cblock));
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb mutex_exit(&ldcp->cblock);
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb size = msglen - VIO_PKT_DATA_HDRSIZE;
c1c61f44e88f4c8c155272ee56d868043146096asb if (size < ETHERMIN || size > lp->mtu) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb (void) atomic_inc_32(&statsp->rx_pri_fail);
f0ca1d9a12d54d304791bc74525e2010ca924726sb goto exit;
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb mp = vio_multipool_allocb(&ldcp->vmp, size);
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (mp == NULL) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb mp = allocb(size, BPRI_MED);
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (mp == NULL) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb (void) atomic_inc_32(&statsp->rx_pri_fail);
f0ca1d9a12d54d304791bc74525e2010ca924726sb DWARN(vgenp, ldcp, "allocb failure, "
f0ca1d9a12d54d304791bc74525e2010ca924726sb "unable to process priority frame\n");
f0ca1d9a12d54d304791bc74525e2010ca924726sb goto exit;
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* copy the frame from the payload of raw data msg into the mblk */
f0ca1d9a12d54d304791bc74525e2010ca924726sb bcopy(pkt->data, mp->b_rptr, size);
f0ca1d9a12d54d304791bc74525e2010ca924726sb mp->b_wptr = mp->b_rptr + size;
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* update stats */
f0ca1d9a12d54d304791bc74525e2010ca924726sb (void) atomic_inc_64(&statsp->rx_pri_packets);
f0ca1d9a12d54d304791bc74525e2010ca924726sb (void) atomic_add_64(&statsp->rx_pri_bytes, size);
f0ca1d9a12d54d304791bc74525e2010ca924726sb
678453a8ed49104d8adad58f3ba591bdc39883e8speer /* send up; call vrx_cb() as cblock is already released */
678453a8ed49104d8adad58f3ba591bdc39883e8speer vrx_cb = ldcp->portp->vcb.vio_net_rx_cb;
678453a8ed49104d8adad58f3ba591bdc39883e8speer vrx_cb(ldcp->portp->vhp, mp);
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sbexit:
f0ca1d9a12d54d304791bc74525e2010ca924726sb mutex_enter(&ldcp->cblock);
f0ca1d9a12d54d304791bc74525e2010ca924726sb}
f0ca1d9a12d54d304791bc74525e2010ca924726sb
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic int
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayanvgen_send_dring_ack(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp, uint32_t start,
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan int32_t end, uint8_t pstate)
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan{
3af08d828975d7e2581b6829e0eecff14d87a483lm int rv = 0;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_t *vgenp = LDC_TO_VGEN(ldcp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vio_dring_msg_t *msgp = (vio_dring_msg_t *)tagp;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan tagp->vio_subtype = VIO_SUBTYPE_ACK;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan tagp->vio_sid = ldcp->local_sid;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan msgp->start_idx = start;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan msgp->end_idx = end;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan msgp->dring_process_state = pstate;
3af08d828975d7e2581b6829e0eecff14d87a483lm rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (*msgp), B_FALSE);
3af08d828975d7e2581b6829e0eecff14d87a483lm if (rv != VGEN_SUCCESS) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "vgen_sendmsg failed\n");
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan }
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan}
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic int
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramvgen_handle_dring_data(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
3af08d828975d7e2581b6829e0eecff14d87a483lm int rv = 0;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_t *vgenp = LDC_TO_VGEN(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "enter\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo switch (tagp->vio_subtype) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VIO_SUBTYPE_INFO:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * To reduce the locking contention, release the
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * cblock here and re-acquire it once we are done
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * receiving packets.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_exit(&ldcp->cblock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_enter(&ldcp->rxlock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram rv = vgen_handle_dring_data_info(ldcp, tagp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_exit(&ldcp->rxlock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_enter(&ldcp->cblock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram case VIO_SUBTYPE_ACK:
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram rv = vgen_handle_dring_data_ack(ldcp, tagp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram break;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram case VIO_SUBTYPE_NACK:
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram rv = vgen_handle_dring_data_nack(ldcp, tagp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram break;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "exit rv(%d)\n", rv);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram return (rv);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram}
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramstatic int
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramvgen_handle_dring_data_info(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram{
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram uint32_t start;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram int32_t end;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram int rv = 0;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vio_dring_msg_t *dringmsg = (vio_dring_msg_t *)tagp;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_t *vgenp = LDC_TO_VGEN(ldcp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram#ifdef VGEN_HANDLE_LOST_PKTS
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vgen_stats_t *statsp = &ldcp->stats;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram uint32_t rxi;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram int n;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram#endif
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "enter\n");
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram start = dringmsg->start_idx;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram end = dringmsg->end_idx;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /*
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * received a data msg, which contains the start and end
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * indices of the descriptors within the rx ring holding data,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * the seq_num of data packet corresponding to the start index,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * and the dring_ident.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * We can now read the contents of each of these descriptors
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * and gather data from it.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "INFO: start(%d), end(%d)\n",
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram start, end);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* validate rx start and end indeces */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (!(CHECK_RXI(start, ldcp)) || ((end != -1) &&
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram !(CHECK_RXI(end, ldcp)))) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "Invalid Rx start(%d) or end(%d)\n",
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram start, end);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* drop the message if invalid index */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram return (rv);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* validate dring_ident */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (dringmsg->dring_ident != ldcp->peer_hparams.dring_ident) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "Invalid dring ident 0x%x\n",
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram dringmsg->dring_ident);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* invalid dring_ident, drop the msg */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram return (rv);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#ifdef DEBUG
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (vgen_trigger_rxlost) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* drop this msg to simulate lost pkts for debugging */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_trigger_rxlost = 0;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram return (rv);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#endif
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#ifdef VGEN_HANDLE_LOST_PKTS
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* receive start index doesn't match expected index */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (ldcp->next_rxi != start) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "next_rxi(%d) != start(%d)\n",
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ldcp->next_rxi, start);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* calculate the number of pkts lost */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (start >= ldcp->next_rxi) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram n = start - ldcp->next_rxi;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram } else {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram n = ldcp->num_rxds - (ldcp->next_rxi - start);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
f0ca1d9a12d54d304791bc74525e2010ca924726sb statsp->rx_lost_pkts += n;
f0ca1d9a12d54d304791bc74525e2010ca924726sb tagp->vio_subtype = VIO_SUBTYPE_NACK;
f0ca1d9a12d54d304791bc74525e2010ca924726sb tagp->vio_sid = ldcp->local_sid;
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* indicate the range of lost descriptors */
f0ca1d9a12d54d304791bc74525e2010ca924726sb dringmsg->start_idx = ldcp->next_rxi;
f0ca1d9a12d54d304791bc74525e2010ca924726sb rxi = start;
f0ca1d9a12d54d304791bc74525e2010ca924726sb DECR_RXI(rxi, ldcp);
f0ca1d9a12d54d304791bc74525e2010ca924726sb dringmsg->end_idx = rxi;
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* dring ident is left unchanged */
f0ca1d9a12d54d304791bc74525e2010ca924726sb rv = vgen_sendmsg(ldcp, (caddr_t)tagp,
f0ca1d9a12d54d304791bc74525e2010ca924726sb sizeof (*dringmsg), B_FALSE);
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (rv != VGEN_SUCCESS) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb DWARN(vgenp, ldcp,
f0ca1d9a12d54d304791bc74525e2010ca924726sb "vgen_sendmsg failed, stype:NACK\n");
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram return (rv);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /*
f0ca1d9a12d54d304791bc74525e2010ca924726sb * treat this range of descrs/pkts as dropped
f0ca1d9a12d54d304791bc74525e2010ca924726sb * and set the new expected value of next_rxi
f0ca1d9a12d54d304791bc74525e2010ca924726sb * and continue(below) to process from the new
f0ca1d9a12d54d304791bc74525e2010ca924726sb * start index.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram */
f0ca1d9a12d54d304791bc74525e2010ca924726sb ldcp->next_rxi = start;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#endif /* VGEN_HANDLE_LOST_PKTS */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* Now receive messages */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram rv = vgen_process_dring_data(ldcp, tagp);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "exit rv(%d)\n", rv);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram return (rv);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramstatic int
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramvgen_process_dring_data(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram{
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram boolean_t set_ack_start = B_FALSE;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram uint32_t start;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram uint32_t ack_end;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram uint32_t next_rxi;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram uint32_t rxi;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram int count = 0;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram int rv = 0;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram uint32_t retries = 0;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_stats_t *statsp;
bbfa0259e68b6b625e9e085053d41d620f185eeeha vnet_public_desc_t rxd;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vio_dring_entry_hdr_t *hdrp;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mblk_t *bp = NULL;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mblk_t *bpt = NULL;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram uint32_t ack_start;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram boolean_t rxd_err = B_FALSE;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mblk_t *mp = NULL;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram size_t nbytes;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram boolean_t ack_needed = B_FALSE;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram size_t nread;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram uint64_t off = 0;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram struct ether_header *ehp;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vio_dring_msg_t *dringmsg = (vio_dring_msg_t *)tagp;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_t *vgenp = LDC_TO_VGEN(ldcp);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna vgen_hparams_t *lp = &ldcp->local_hparams;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "enter\n");
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
06db247c678f0e3956535e8a6dec31d6c2108827raghuram statsp = &ldcp->stats;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram start = dringmsg->start_idx;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /*
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * start processing the descriptors from the specified
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * start index, up to the index a descriptor is not ready
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * to be processed or we process the entire descriptor ring
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * and wrap around upto the start index.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram */
3af08d828975d7e2581b6829e0eecff14d87a483lm
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* need to set the start index of descriptors to be ack'd */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram set_ack_start = B_TRUE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* index upto which we have ack'd */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ack_end = start;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DECR_RXI(ack_end, ldcp);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram next_rxi = rxi = start;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram do {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramvgen_recv_retry:
bbfa0259e68b6b625e9e085053d41d620f185eeeha rv = vnet_dring_entry_copy(&(ldcp->rxdp[rxi]), &rxd,
bbfa0259e68b6b625e9e085053d41d620f185eeeha ldcp->dring_mtype, ldcp->rx_dhandle, rxi, rxi);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (rv != 0) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "ldc_mem_dring_acquire() failed"
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram " rv(%d)\n", rv);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram statsp->ierrors++;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram return (rv);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
bbfa0259e68b6b625e9e085053d41d620f185eeeha hdrp = &rxd.hdr;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (hdrp->dstate != VIO_DESC_READY) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /*
f0ca1d9a12d54d304791bc74525e2010ca924726sb * Before waiting and retry here, send up
f0ca1d9a12d54d304791bc74525e2010ca924726sb * the packets that are received already
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (bp != NULL) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DTRACE_PROBE1(vgen_rcv_msgs, int, count);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna vgen_rx(ldcp, bp, bpt);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram count = 0;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram bp = bpt = NULL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /*
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * descriptor is not ready.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * retry descriptor acquire, stop processing
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * after max # retries.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (retries == vgen_recv_retries)
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram break;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram retries++;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram drv_usecwait(vgen_recv_delay);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram goto vgen_recv_retry;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram retries = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (set_ack_start) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /*
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * initialize the start index of the range
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * of descriptors to be ack'd.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ack_start = rxi;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram set_ack_start = B_FALSE;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
bbfa0259e68b6b625e9e085053d41d620f185eeeha if ((rxd.nbytes < ETHERMIN) ||
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna (rxd.nbytes > lp->mtu) ||
bbfa0259e68b6b625e9e085053d41d620f185eeeha (rxd.ncookies == 0) ||
bbfa0259e68b6b625e9e085053d41d620f185eeeha (rxd.ncookies > MAX_COOKIES)) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram rxd_err = B_TRUE;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram } else {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /*
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * Try to allocate an mblk from the free pool
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * of recv mblks for the channel.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * If this fails, use allocb().
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram */
bbfa0259e68b6b625e9e085053d41d620f185eeeha nbytes = (VNET_IPALIGN + rxd.nbytes + 7) & ~7;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna if (nbytes > ldcp->max_rxpool_size) {
bbfa0259e68b6b625e9e085053d41d620f185eeeha mp = allocb(VNET_IPALIGN + rxd.nbytes + 8,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram BPRI_MED);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna } else {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna mp = vio_multipool_allocb(&ldcp->vmp, nbytes);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna if (mp == NULL) {
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna statsp->rx_vio_allocb_fail++;
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna /*
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * Data buffer returned by allocb(9F)
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * is 8byte aligned. We allocate extra
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * 8 bytes to ensure size is multiple
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna * of 8 bytes for ldc_mem_copy().
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna */
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna mp = allocb(VNET_IPALIGN +
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna rxd.nbytes + 8, BPRI_MED);
7b1f684a14f99a2b9b1b2561f484ff648eff6d9bSriharsha Basavapatna }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if ((rxd_err) || (mp == NULL)) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /*
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * rxd_err or allocb() failure,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * drop this packet, get next.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (rxd_err) {
3af08d828975d7e2581b6829e0eecff14d87a483lm statsp->ierrors++;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram rxd_err = B_FALSE;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram } else {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram statsp->rx_allocb_fail++;
3af08d828975d7e2581b6829e0eecff14d87a483lm }
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm ack_needed = hdrp->ack;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* set descriptor done bit */
bbfa0259e68b6b625e9e085053d41d620f185eeeha rv = vnet_dring_entry_set_dstate(&(ldcp->rxdp[rxi]),
bbfa0259e68b6b625e9e085053d41d620f185eeeha ldcp->dring_mtype, ldcp->rx_dhandle, rxi, rxi,
bbfa0259e68b6b625e9e085053d41d620f185eeeha VIO_DESC_DONE);
3af08d828975d7e2581b6829e0eecff14d87a483lm if (rv != 0) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp,
bbfa0259e68b6b625e9e085053d41d620f185eeeha "vnet_dring_entry_set_dstate err rv(%d)\n",
bbfa0259e68b6b625e9e085053d41d620f185eeeha rv);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram return (rv);
3af08d828975d7e2581b6829e0eecff14d87a483lm }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
3af08d828975d7e2581b6829e0eecff14d87a483lm if (ack_needed) {
3af08d828975d7e2581b6829e0eecff14d87a483lm ack_needed = B_FALSE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * sender needs ack for this packet,
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * ack pkts upto this index.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan ack_end = rxi;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
3af08d828975d7e2581b6829e0eecff14d87a483lm rv = vgen_send_dring_ack(ldcp, tagp,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ack_start, ack_end,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram VIO_DP_ACTIVE);
3af08d828975d7e2581b6829e0eecff14d87a483lm if (rv != VGEN_SUCCESS) {
3af08d828975d7e2581b6829e0eecff14d87a483lm goto error_ret;
3af08d828975d7e2581b6829e0eecff14d87a483lm }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan /* need to set new ack start index */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan set_ack_start = B_TRUE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram goto vgen_next_rxi;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram nread = nbytes;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram rv = ldc_mem_copy(ldcp->ldc_handle,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram (caddr_t)mp->b_rptr, off, &nread,
bbfa0259e68b6b625e9e085053d41d620f185eeeha rxd.memcookie, rxd.ncookies, LDC_COPY_IN);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* if ldc_mem_copy() failed */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (rv) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "ldc_mem_copy err rv(%d)\n", rv);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram statsp->ierrors++;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram freemsg(mp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram goto error_ret;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ack_needed = hdrp->ack;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
bbfa0259e68b6b625e9e085053d41d620f185eeeha rv = vnet_dring_entry_set_dstate(&(ldcp->rxdp[rxi]),
bbfa0259e68b6b625e9e085053d41d620f185eeeha ldcp->dring_mtype, ldcp->rx_dhandle, rxi, rxi,
bbfa0259e68b6b625e9e085053d41d620f185eeeha VIO_DESC_DONE);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (rv != 0) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp,
bbfa0259e68b6b625e9e085053d41d620f185eeeha "vnet_dring_entry_set_dstate err rv(%d)\n", rv);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram goto error_ret;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mp->b_rptr += VNET_IPALIGN;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (ack_needed) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ack_needed = B_FALSE;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /*
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * sender needs ack for this packet,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * ack pkts upto this index.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan ack_end = rxi;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram rv = vgen_send_dring_ack(ldcp, tagp,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ack_start, ack_end, VIO_DP_ACTIVE);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (rv != VGEN_SUCCESS) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram goto error_ret;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* need to set new ack start index */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram set_ack_start = B_TRUE;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (nread != nbytes) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram "ldc_mem_copy nread(%lx), nbytes(%lx)\n",
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram nread, nbytes);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram statsp->ierrors++;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram freemsg(mp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram goto vgen_next_rxi;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* point to the actual end of data */
bbfa0259e68b6b625e9e085053d41d620f185eeeha mp->b_wptr = mp->b_rptr + rxd.nbytes;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* update stats */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram statsp->ipackets++;
bbfa0259e68b6b625e9e085053d41d620f185eeeha statsp->rbytes += rxd.nbytes;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ehp = (struct ether_header *)mp->b_rptr;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (IS_BROADCAST(ehp))
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram statsp->brdcstrcv++;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram else if (IS_MULTICAST(ehp))
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram statsp->multircv++;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* build a chain of received packets */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (bp == NULL) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* first pkt */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram bp = mp;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram bpt = bp;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram bpt->b_next = NULL;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram } else {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mp->b_next = NULL;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram bpt->b_next = mp;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram bpt = mp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (count++ > vgen_chain_len) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DTRACE_PROBE1(vgen_rcv_msgs, int, count);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna vgen_rx(ldcp, bp, bpt);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram count = 0;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram bp = bpt = NULL;
3af08d828975d7e2581b6829e0eecff14d87a483lm }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramvgen_next_rxi:
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* update end index of range of descrs to be ack'd */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ack_end = rxi;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* update the next index to be processed */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram INCR_RXI(next_rxi, ldcp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (next_rxi == start) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /*
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * processed the entire descriptor ring upto
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * the index at which we started.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram break;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram rxi = next_rxi;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram _NOTE(CONSTCOND)
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram } while (1);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /*
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * send an ack message to peer indicating that we have stopped
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * processing descriptors.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (set_ack_start) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * We have ack'd upto some index and we have not
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * processed any descriptors beyond that index.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * Use the last ack'd index as both the start and
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * end of range of descrs being ack'd.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * Note: This results in acking the last index twice
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * and should be harmless.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ack_start = ack_end;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram rv = vgen_send_dring_ack(ldcp, tagp, ack_start, ack_end,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram VIO_DP_STOPPED);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (rv != VGEN_SUCCESS) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram goto error_ret;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* save new recv index of next dring msg */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ldcp->next_rxi = next_rxi;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramerror_ret:
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* send up packets received so far */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (bp != NULL) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DTRACE_PROBE1(vgen_rcv_msgs, int, count);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna vgen_rx(ldcp, bp, bpt);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram bp = bpt = NULL;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "exit rv(%d)\n", rv);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram return (rv);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram}
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramstatic int
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramvgen_handle_dring_data_ack(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram{
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram int rv = 0;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram uint32_t start;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram int32_t end;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram uint32_t txi;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram boolean_t ready_txd = B_FALSE;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_stats_t *statsp;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_private_desc_t *tbufp;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vnet_public_desc_t *txdp;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vio_dring_entry_hdr_t *hdrp;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_t *vgenp = LDC_TO_VGEN(ldcp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vio_dring_msg_t *dringmsg = (vio_dring_msg_t *)tagp;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "enter\n");
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram start = dringmsg->start_idx;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram end = dringmsg->end_idx;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram statsp = &ldcp->stats;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /*
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * received an ack corresponding to a specific descriptor for
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * which we had set the ACK bit in the descriptor (during
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * transmit). This enables us to reclaim descriptors.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG2(vgenp, ldcp, "ACK: start(%d), end(%d)\n", start, end);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* validate start and end indeces in the tx ack msg */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (!(CHECK_TXI(start, ldcp)) || !(CHECK_TXI(end, ldcp))) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* drop the message if invalid index */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "Invalid Tx ack start(%d) or end(%d)\n",
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram start, end);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram return (rv);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* validate dring_ident */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (dringmsg->dring_ident != ldcp->local_hparams.dring_ident) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* invalid dring_ident, drop the msg */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "Invalid dring ident 0x%x\n",
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram dringmsg->dring_ident);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram return (rv);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram statsp->dring_data_acks++;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* reclaim descriptors that are done */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_reclaim(ldcp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (dringmsg->dring_process_state != VIO_DP_STOPPED) {
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan /*
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * receiver continued processing descriptors after
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * sending us the ack.
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram return (rv);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram statsp->dring_stopped_acks++;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* receiver stopped processing descriptors */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_enter(&ldcp->wrlock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_enter(&ldcp->tclock);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /*
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * determine if there are any pending tx descriptors
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * ready to be processed by the receiver(peer) and if so,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * send a message to the peer to restart receiving.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ready_txd = B_FALSE;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /*
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * using the end index of the descriptor range for which
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * we received the ack, check if the next descriptor is
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * ready.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram txi = end;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram INCR_TXI(txi, ldcp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram tbufp = &ldcp->tbufp[txi];
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram txdp = tbufp->descp;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram hdrp = &txdp->hdr;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (hdrp->dstate == VIO_DESC_READY) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ready_txd = B_TRUE;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram } else {
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan /*
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * descr next to the end of ack'd descr range is not
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * ready.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * starting from the current reclaim index, check
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * if any descriptor is ready.
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram txi = ldcp->cur_tbufp - ldcp->tbufp;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan tbufp = &ldcp->tbufp[txi];
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan txdp = tbufp->descp;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan hdrp = &txdp->hdr;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan if (hdrp->dstate == VIO_DESC_READY) {
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan ready_txd = B_TRUE;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (ready_txd) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /*
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * we have tx descriptor(s) ready to be
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * processed by the receiver.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * send a message to the peer with the start index
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * of ready descriptors.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram rv = vgen_send_dring_data(ldcp, txi, -1);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (rv != VGEN_SUCCESS) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ldcp->resched_peer = B_TRUE;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ldcp->resched_peer_txi = txi;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_exit(&ldcp->tclock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_exit(&ldcp->wrlock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram return (rv);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram } else {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /*
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * no ready tx descriptors. set the flag to send a
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * message to peer when tx descriptors are ready in
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * transmit routine.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ldcp->resched_peer = B_TRUE;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ldcp->resched_peer_txi = ldcp->cur_tbufp - ldcp->tbufp;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_exit(&ldcp->tclock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_exit(&ldcp->wrlock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "exit rv(%d)\n", rv);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram return (rv);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram}
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramstatic int
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramvgen_handle_dring_data_nack(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram{
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram int rv = 0;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram uint32_t start;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram int32_t end;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram uint32_t txi;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vnet_public_desc_t *txdp;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vio_dring_entry_hdr_t *hdrp;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_t *vgenp = LDC_TO_VGEN(ldcp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vio_dring_msg_t *dringmsg = (vio_dring_msg_t *)tagp;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "enter\n");
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram start = dringmsg->start_idx;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram end = dringmsg->end_idx;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /*
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * peer sent a NACK msg to indicate lost packets.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * The start and end correspond to the range of descriptors
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * for which the peer didn't receive a dring data msg and so
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * didn't receive the corresponding data.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "NACK: start(%d), end(%d)\n", start, end);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* validate start and end indeces in the tx nack msg */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (!(CHECK_TXI(start, ldcp)) || !(CHECK_TXI(end, ldcp))) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* drop the message if invalid index */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "Invalid Tx nack start(%d) or end(%d)\n",
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram start, end);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram return (rv);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* validate dring_ident */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (dringmsg->dring_ident != ldcp->local_hparams.dring_ident) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* invalid dring_ident, drop the msg */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "Invalid dring ident 0x%x\n",
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram dringmsg->dring_ident);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram return (rv);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_enter(&ldcp->txlock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_enter(&ldcp->tclock);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (ldcp->next_tbufp == ldcp->cur_tbufp) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* no busy descriptors, bogus nack ? */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan mutex_exit(&ldcp->tclock);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan mutex_exit(&ldcp->txlock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram return (rv);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /* we just mark the descrs as done so they can be reclaimed */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram for (txi = start; txi <= end; ) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram txdp = &(ldcp->txdp[txi]);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram hdrp = &txdp->hdr;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (hdrp->dstate == VIO_DESC_READY)
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram hdrp->dstate = VIO_DESC_DONE;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram INCR_TXI(txi, ldcp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_exit(&ldcp->tclock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_exit(&ldcp->txlock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "exit rv(%d)\n", rv);
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_reclaim(vgen_ldc_t *ldcp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan mutex_enter(&ldcp->tclock);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_reclaim_dring(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->reclaim_lbolt = ddi_get_lbolt();
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&ldcp->tclock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * transmit reclaim function. starting from the current reclaim index
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * look for descriptors marked DONE and reclaim the descriptor and the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * corresponding buffers (tbuf).
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_reclaim_dring(vgen_ldc_t *ldcp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
61a70d81555b002d961400e93b444d97fc467f13raghuram int count = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vnet_public_desc_t *txdp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_private_desc_t *tbufp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vio_dring_entry_hdr_t *hdrp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#ifdef DEBUG
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vgen_trigger_txtimeout)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#endif
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tbufp = ldcp->cur_tbufp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo txdp = tbufp->descp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo hdrp = &txdp->hdr;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo while ((hdrp->dstate == VIO_DESC_DONE) &&
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (tbufp != ldcp->next_tbufp)) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tbufp->flags = VGEN_PRIV_DESC_FREE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo hdrp->dstate = VIO_DESC_FREE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo hdrp->ack = B_FALSE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tbufp = NEXTTBUF(ldcp, tbufp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo txdp = tbufp->descp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo hdrp = &txdp->hdr;
61a70d81555b002d961400e93b444d97fc467f13raghuram count++;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->cur_tbufp = tbufp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Check if mac layer should be notified to restart transmissions
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
61a70d81555b002d961400e93b444d97fc467f13raghuram if ((ldcp->need_resched) && (count > 0)) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer vio_net_tx_update_t vtx_update =
678453a8ed49104d8adad58f3ba591bdc39883e8speer ldcp->portp->vcb.vio_net_tx_update;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->need_resched = B_FALSE;
678453a8ed49104d8adad58f3ba591bdc39883e8speer vtx_update(ldcp->portp->vhp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* return the number of pending transmits for the channel */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_num_txpending(vgen_ldc_t *ldcp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int n;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ldcp->next_tbufp >= ldcp->cur_tbufp) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo n = ldcp->next_tbufp - ldcp->cur_tbufp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } else {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* cur_tbufp > next_tbufp */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo n = ldcp->num_txds - (ldcp->cur_tbufp - ldcp->next_tbufp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (n);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* determine if the transmit descriptor ring is full */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_tx_dring_full(vgen_ldc_t *ldcp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_private_desc_t *tbufp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_private_desc_t *ntbufp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tbufp = ldcp->next_tbufp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ntbufp = NEXTTBUF(ldcp, tbufp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ntbufp == ldcp->cur_tbufp) { /* out of tbufs/txds */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* determine if timeout condition has occured */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_ldc_txtimeout(vgen_ldc_t *ldcp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (((ddi_get_lbolt() - ldcp->reclaim_lbolt) >
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram drv_usectohz(vnet_ldcwd_txtimeout * 1000)) &&
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram (vnet_ldcwd_txtimeout) &&
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram (vgen_tx_dring_full(ldcp) == VGEN_SUCCESS)) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } else {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* transmit watchdog timeout handler */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_ldc_watchdog(void *arg)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_ldc_t *ldcp;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan vgen_t *vgenp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int rv;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp = (vgen_ldc_t *)arg;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan vgenp = LDC_TO_VGEN(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = vgen_ldc_txtimeout(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rv == VGEN_SUCCESS) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "transmit timeout\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#ifdef DEBUG
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vgen_trigger_txtimeout) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* tx timeout triggered for debugging */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_trigger_txtimeout = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#endif
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_enter(&ldcp->cblock);
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG vgen_ldc_reset(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&ldcp->cblock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ldcp->need_resched) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer vio_net_tx_update_t vtx_update =
678453a8ed49104d8adad58f3ba591bdc39883e8speer ldcp->portp->vcb.vio_net_tx_update;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->need_resched = B_FALSE;
678453a8ed49104d8adad58f3ba591bdc39883e8speer vtx_update(ldcp->portp->vhp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->wd_tid = timeout(vgen_ldc_watchdog, (caddr_t)ldcp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo drv_usectohz(vnet_ldcwd_interval * 1000));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* handler for error messages received from the peer ldc end-point */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_handle_errmsg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo _NOTE(ARGUNUSED(ldcp, tagp))
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
f0ca1d9a12d54d304791bc74525e2010ca924726sbstatic int
f0ca1d9a12d54d304791bc74525e2010ca924726sbvgen_check_datamsg_seq(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
f0ca1d9a12d54d304791bc74525e2010ca924726sb{
f0ca1d9a12d54d304791bc74525e2010ca924726sb vio_raw_data_msg_t *rmsg;
f0ca1d9a12d54d304791bc74525e2010ca924726sb vio_dring_msg_t *dmsg;
f0ca1d9a12d54d304791bc74525e2010ca924726sb uint64_t seq_num;
f0ca1d9a12d54d304791bc74525e2010ca924726sb vgen_t *vgenp = LDC_TO_VGEN(ldcp);
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (tagp->vio_subtype_env == VIO_DRING_DATA) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb dmsg = (vio_dring_msg_t *)tagp;
f0ca1d9a12d54d304791bc74525e2010ca924726sb seq_num = dmsg->seq_num;
f0ca1d9a12d54d304791bc74525e2010ca924726sb } else if (tagp->vio_subtype_env == VIO_PKT_DATA) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb rmsg = (vio_raw_data_msg_t *)tagp;
f0ca1d9a12d54d304791bc74525e2010ca924726sb seq_num = rmsg->seq_num;
f0ca1d9a12d54d304791bc74525e2010ca924726sb } else {
f0ca1d9a12d54d304791bc74525e2010ca924726sb return (EINVAL);
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb if (seq_num != ldcp->next_rxseq) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb /* seqnums don't match */
f0ca1d9a12d54d304791bc74525e2010ca924726sb DWARN(vgenp, ldcp,
f0ca1d9a12d54d304791bc74525e2010ca924726sb "next_rxseq(0x%lx) != seq_num(0x%lx)\n",
f0ca1d9a12d54d304791bc74525e2010ca924726sb ldcp->next_rxseq, seq_num);
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb return (EINVAL);
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb }
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb ldcp->next_rxseq++;
f0ca1d9a12d54d304791bc74525e2010ca924726sb
f0ca1d9a12d54d304791bc74525e2010ca924726sb return (0);
f0ca1d9a12d54d304791bc74525e2010ca924726sb}
f0ca1d9a12d54d304791bc74525e2010ca924726sb
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* Check if the session id in the received message is valid */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_check_sid(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_t *vgenp = LDC_TO_VGEN(ldcp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (tagp->vio_sid != ldcp->peer_sid) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DWARN(vgenp, ldcp, "sid mismatch: expected(%x), rcvd(%x)\n",
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ldcp->peer_sid, tagp->vio_sid);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo else
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic caddr_t
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_print_ethaddr(uint8_t *a, char *ebuf)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void) sprintf(ebuf,
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram "%x:%x:%x:%x:%x:%x", a[0], a[1], a[2], a[3], a[4], a[5]);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (ebuf);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* Handshake watchdog timeout handler */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_hwatchdog(void *arg)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_ldc_t *ldcp = (vgen_ldc_t *)arg;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_t *vgenp = LDC_TO_VGEN(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG DWARN(vgenp, ldcp, "handshake timeout phase(%x) state(%x)\n",
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ldcp->hphase, ldcp->hstate);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_enter(&ldcp->cblock);
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan if (ldcp->cancel_htid) {
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan ldcp->cancel_htid = 0;
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan mutex_exit(&ldcp->cblock);
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan return;
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->htid = 0;
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG vgen_ldc_reset(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&ldcp->cblock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_print_hparams(vgen_hparams_t *hp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint8_t addr[6];
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo char ea[6];
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldc_mem_cookie_t *dc;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cmn_err(CE_CONT, "version_info:\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cmn_err(CE_CONT,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "\tver_major: %d, ver_minor: %d, dev_class: %d\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo hp->ver_major, hp->ver_minor, hp->dev_class);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
f2b610cf6e03184d9538e3aaec99bcaf65124714wentaoy vnet_macaddr_ultostr(hp->addr, addr);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cmn_err(CE_CONT, "attr_info:\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cmn_err(CE_CONT, "\tMTU: %lx, addr: %s\n", hp->mtu,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_print_ethaddr(addr, ea));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cmn_err(CE_CONT,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "\taddr_type: %x, xfer_mode: %x, ack_freq: %x\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo hp->addr_type, hp->xfer_mode, hp->ack_freq);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo dc = &hp->dring_cookie;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cmn_err(CE_CONT, "dring_info:\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cmn_err(CE_CONT,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "\tlength: %d, dsize: %d\n", hp->num_desc, hp->desc_size);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cmn_err(CE_CONT,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "\tldc_addr: 0x%lx, ldc_size: %ld\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo dc->addr, dc->size);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cmn_err(CE_CONT, "\tdring_ident: 0x%lx\n", hp->dring_ident);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_print_ldcinfo(vgen_ldc_t *ldcp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_hparams_t *hp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cmn_err(CE_CONT, "Channel Information:\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cmn_err(CE_CONT,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "\tldc_id: 0x%lx, ldc_status: 0x%x\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id, ldcp->ldc_status);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cmn_err(CE_CONT,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "\tlocal_sid: 0x%x, peer_sid: 0x%x\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->local_sid, ldcp->peer_sid);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cmn_err(CE_CONT,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "\thphase: 0x%x, hstate: 0x%x\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->hphase, ldcp->hstate);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cmn_err(CE_CONT, "Local handshake params:\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo hp = &ldcp->local_hparams;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_print_hparams(hp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo cmn_err(CE_CONT, "Peer handshake params:\n");
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo hp = &ldcp->peer_hparams;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_print_hparams(hp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram/*
f0ca1d9a12d54d304791bc74525e2010ca924726sb * Send received packets up the stack.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramstatic void
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatnavgen_rx(vgen_ldc_t *ldcp, mblk_t *bp, mblk_t *bpt)
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram{
678453a8ed49104d8adad58f3ba591bdc39883e8speer vio_net_rx_cb_t vrx_cb = ldcp->portp->vcb.vio_net_rx_cb;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna vgen_t *vgenp = LDC_TO_VGEN(ldcp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (ldcp->rcv_thread != NULL) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb ASSERT(MUTEX_HELD(&ldcp->rxlock));
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram } else {
f0ca1d9a12d54d304791bc74525e2010ca924726sb ASSERT(MUTEX_HELD(&ldcp->cblock));
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna }
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna mutex_enter(&ldcp->pollq_lock);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna if (ldcp->polling_on == B_TRUE) {
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna /*
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna * If we are in polling mode, simply queue
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna * the packets onto the poll queue and return.
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna */
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna if (ldcp->pollq_headp == NULL) {
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna ldcp->pollq_headp = bp;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna ldcp->pollq_tailp = bpt;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna } else {
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna ldcp->pollq_tailp->b_next = bp;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna ldcp->pollq_tailp = bpt;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna }
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna mutex_exit(&ldcp->pollq_lock);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna return;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna }
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna /*
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna * Prepend any pending mblks in the poll queue, now that we
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna * are in interrupt mode, before sending up the chain of pkts.
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna */
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna if (ldcp->pollq_headp != NULL) {
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna DBG2(vgenp, ldcp, "vgen_rx(%lx), pending pollq_headp\n",
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna (uintptr_t)ldcp);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna ldcp->pollq_tailp->b_next = bp;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna bp = ldcp->pollq_headp;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna ldcp->pollq_headp = ldcp->pollq_tailp = NULL;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna }
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna mutex_exit(&ldcp->pollq_lock);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna if (ldcp->rcv_thread != NULL) {
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna mutex_exit(&ldcp->rxlock);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna } else {
f0ca1d9a12d54d304791bc74525e2010ca924726sb mutex_exit(&ldcp->cblock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
f0ca1d9a12d54d304791bc74525e2010ca924726sb
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna /* Send up the packets */
678453a8ed49104d8adad58f3ba591bdc39883e8speer vrx_cb(ldcp->portp->vhp, bp);
f0ca1d9a12d54d304791bc74525e2010ca924726sb
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (ldcp->rcv_thread != NULL) {
f0ca1d9a12d54d304791bc74525e2010ca924726sb mutex_enter(&ldcp->rxlock);
f0ca1d9a12d54d304791bc74525e2010ca924726sb } else {
f0ca1d9a12d54d304791bc74525e2010ca924726sb mutex_enter(&ldcp->cblock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram}
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram/*
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * vgen_ldc_rcv_worker -- A per LDC worker thread to receive data.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * This thread is woken up by the LDC interrupt handler to process
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * LDC packets and receive data.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramstatic void
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramvgen_ldc_rcv_worker(void *arg)
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram{
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram callb_cpr_t cprinfo;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_ldc_t *ldcp = (vgen_ldc_t *)arg;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_t *vgenp = LDC_TO_VGEN(ldcp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "enter\n");
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram CALLB_CPR_INIT(&cprinfo, &ldcp->rcv_thr_lock, callb_generic_cpr,
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram "vnet_rcv_thread");
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_enter(&ldcp->rcv_thr_lock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram while (!(ldcp->rcv_thr_flags & VGEN_WTHR_STOP)) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram CALLB_CPR_SAFE_BEGIN(&cprinfo);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /*
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * Wait until the data is received or a stop
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * request is received.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram while (!(ldcp->rcv_thr_flags &
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram (VGEN_WTHR_DATARCVD | VGEN_WTHR_STOP))) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram cv_wait(&ldcp->rcv_thr_cv, &ldcp->rcv_thr_lock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram CALLB_CPR_SAFE_END(&cprinfo, &ldcp->rcv_thr_lock)
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /*
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * First process the stop request.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (ldcp->rcv_thr_flags & VGEN_WTHR_STOP) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG2(vgenp, ldcp, "stopped\n");
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram break;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ldcp->rcv_thr_flags &= ~VGEN_WTHR_DATARCVD;
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna ldcp->rcv_thr_flags |= VGEN_WTHR_PROCESSING;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_exit(&ldcp->rcv_thr_lock);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG2(vgenp, ldcp, "calling vgen_handle_evt_read\n");
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_handle_evt_read(ldcp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_enter(&ldcp->rcv_thr_lock);
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna ldcp->rcv_thr_flags &= ~VGEN_WTHR_PROCESSING;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /*
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * Update the run status and wakeup the thread that
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * has sent the stop request.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram */
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG ldcp->rcv_thr_flags &= ~VGEN_WTHR_STOP;
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG ldcp->rcv_thread = NULL;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram CALLB_CPR_EXIT(&cprinfo);
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram thread_exit();
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "exit\n");
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram}
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram/* vgen_stop_rcv_thread -- Co-ordinate with receive thread to stop it */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramstatic void
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramvgen_stop_rcv_thread(vgen_ldc_t *ldcp)
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram{
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG kt_did_t tid = 0;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_t *vgenp = LDC_TO_VGEN(ldcp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "enter\n");
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram /*
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * Send a stop request by setting the stop flag and
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * wait until the receive thread stops.
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_enter(&ldcp->rcv_thr_lock);
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG if (ldcp->rcv_thread != NULL) {
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG tid = ldcp->rcv_thread->t_did;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram ldcp->rcv_thr_flags |= VGEN_WTHR_STOP;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram cv_signal(&ldcp->rcv_thr_cv);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram mutex_exit(&ldcp->rcv_thr_lock);
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG if (tid != 0) {
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG thread_join(tid);
6f09f0fef8e4582cfa771d87fe2a1f777bfb5cf0WENTAO YANG }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram DBG1(vgenp, ldcp, "exit\n");
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram}
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna/*
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna * Wait for the channel rx-queue to be drained by allowing the receive
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna * worker thread to read all messages from the rx-queue of the channel.
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna * Assumption: further callbacks are disabled at this time.
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna */
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatnastatic void
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatnavgen_drain_rcv_thread(vgen_ldc_t *ldcp)
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna{
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna clock_t tm;
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna clock_t wt;
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna clock_t rv;
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna /*
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna * If there is data in ldc rx queue, wait until the rx
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna * worker thread runs and drains all msgs in the queue.
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna */
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna wt = drv_usectohz(MILLISEC);
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna mutex_enter(&ldcp->rcv_thr_lock);
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna tm = ddi_get_lbolt() + wt;
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna /*
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna * We need to check both bits - DATARCVD and PROCESSING, to be cleared.
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna * If DATARCVD is set, that means the callback has signalled the worker
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna * thread, but the worker hasn't started processing yet. If PROCESSING
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna * is set, that means the thread is awake and processing. Note that the
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna * DATARCVD state can only be seen once, as the assumption is that
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna * further callbacks have been disabled at this point.
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna */
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna while (ldcp->rcv_thr_flags &
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna (VGEN_WTHR_DATARCVD | VGEN_WTHR_PROCESSING)) {
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna rv = cv_timedwait(&ldcp->rcv_thr_cv, &ldcp->rcv_thr_lock, tm);
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna if (rv == -1) { /* timeout */
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna /*
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna * Note that the only way we return is due to a timeout;
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna * we set the new time to wait, before we go back and
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna * check the condition. The other(unlikely) possibility
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna * is a premature wakeup(see cv_timedwait(9F)) in which
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna * case we just continue to use the same time to wait.
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna */
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna tm = ddi_get_lbolt() + wt;
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna }
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna }
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna mutex_exit(&ldcp->rcv_thr_lock);
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna}
195ce4e5cab5a850f4079df860f51c5659a1298bSriharsha Basavapatna
678453a8ed49104d8adad58f3ba591bdc39883e8speer/*
678453a8ed49104d8adad58f3ba591bdc39883e8speer * vgen_dds_rx -- post DDS messages to vnet.
678453a8ed49104d8adad58f3ba591bdc39883e8speer */
678453a8ed49104d8adad58f3ba591bdc39883e8speerstatic int
678453a8ed49104d8adad58f3ba591bdc39883e8speervgen_dds_rx(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp)
678453a8ed49104d8adad58f3ba591bdc39883e8speer{
678453a8ed49104d8adad58f3ba591bdc39883e8speer vio_dds_msg_t *dmsg = (vio_dds_msg_t *)tagp;
678453a8ed49104d8adad58f3ba591bdc39883e8speer vgen_t *vgenp = LDC_TO_VGEN(ldcp);
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (dmsg->dds_class != DDS_VNET_NIU) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer DWARN(vgenp, ldcp, "Unknown DDS class, dropping");
678453a8ed49104d8adad58f3ba591bdc39883e8speer return (EBADMSG);
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer vnet_dds_rx(vgenp->vnetp, dmsg);
678453a8ed49104d8adad58f3ba591bdc39883e8speer return (0);
678453a8ed49104d8adad58f3ba591bdc39883e8speer}
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer/*
678453a8ed49104d8adad58f3ba591bdc39883e8speer * vgen_dds_tx -- an interface called by vnet to send DDS messages.
678453a8ed49104d8adad58f3ba591bdc39883e8speer */
678453a8ed49104d8adad58f3ba591bdc39883e8speerint
678453a8ed49104d8adad58f3ba591bdc39883e8speervgen_dds_tx(void *arg, void *msg)
678453a8ed49104d8adad58f3ba591bdc39883e8speer{
678453a8ed49104d8adad58f3ba591bdc39883e8speer vgen_t *vgenp = arg;
678453a8ed49104d8adad58f3ba591bdc39883e8speer vio_dds_msg_t *dmsg = msg;
678453a8ed49104d8adad58f3ba591bdc39883e8speer vgen_portlist_t *plistp = &vgenp->vgenports;
678453a8ed49104d8adad58f3ba591bdc39883e8speer vgen_ldc_t *ldcp;
678453a8ed49104d8adad58f3ba591bdc39883e8speer vgen_ldclist_t *ldclp;
678453a8ed49104d8adad58f3ba591bdc39883e8speer int rv = EIO;
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer READ_ENTER(&plistp->rwlock);
678453a8ed49104d8adad58f3ba591bdc39883e8speer ldclp = &(vgenp->vsw_portp->ldclist);
678453a8ed49104d8adad58f3ba591bdc39883e8speer READ_ENTER(&ldclp->rwlock);
678453a8ed49104d8adad58f3ba591bdc39883e8speer ldcp = ldclp->headp;
678453a8ed49104d8adad58f3ba591bdc39883e8speer if ((ldcp == NULL) || (ldcp->hphase != VH_DONE)) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer goto vgen_dsend_exit;
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer dmsg->tag.vio_sid = ldcp->local_sid;
678453a8ed49104d8adad58f3ba591bdc39883e8speer rv = vgen_sendmsg(ldcp, (caddr_t)dmsg, sizeof (vio_dds_msg_t), B_FALSE);
678453a8ed49104d8adad58f3ba591bdc39883e8speer if (rv != VGEN_SUCCESS) {
678453a8ed49104d8adad58f3ba591bdc39883e8speer rv = EIO;
678453a8ed49104d8adad58f3ba591bdc39883e8speer } else {
678453a8ed49104d8adad58f3ba591bdc39883e8speer rv = 0;
678453a8ed49104d8adad58f3ba591bdc39883e8speer }
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speervgen_dsend_exit:
678453a8ed49104d8adad58f3ba591bdc39883e8speer RW_EXIT(&ldclp->rwlock);
678453a8ed49104d8adad58f3ba591bdc39883e8speer RW_EXIT(&plistp->rwlock);
678453a8ed49104d8adad58f3ba591bdc39883e8speer return (rv);
678453a8ed49104d8adad58f3ba591bdc39883e8speer
678453a8ed49104d8adad58f3ba591bdc39883e8speer}
678453a8ed49104d8adad58f3ba591bdc39883e8speer
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANGstatic void
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANGvgen_ldc_reset(vgen_ldc_t *ldcp)
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG{
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG vnet_t *vnetp = LDC_TO_VNET(ldcp);
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG vgen_t *vgenp = LDC_TO_VGEN(ldcp);
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG ASSERT(MUTEX_HELD(&ldcp->cblock));
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG if (ldcp->need_ldc_reset == B_TRUE) {
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG /* another thread is already in the process of resetting */
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG return;
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG }
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG /* Set the flag to indicate reset is in progress */
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG ldcp->need_ldc_reset = B_TRUE;
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG if (ldcp->portp == vgenp->vsw_portp) {
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG mutex_exit(&ldcp->cblock);
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG /*
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG * Now cleanup any HIO resources; the above flag also tells
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG * the code that handles dds messages to drop any new msgs
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG * that arrive while we are cleaning up and resetting the
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG * channel.
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG */
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG vnet_dds_cleanup_hio(vnetp);
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG mutex_enter(&ldcp->cblock);
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG }
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG vgen_handshake_retry(ldcp);
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG}
6d6de4ee7da84f30d7d942184d5386d89b304030WENTAO YANG
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatnaint
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatnavgen_enable_intr(void *arg)
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna{
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna vgen_port_t *portp = (vgen_port_t *)arg;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna vgen_ldclist_t *ldclp;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna vgen_ldc_t *ldcp;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna ldclp = &portp->ldclist;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna READ_ENTER(&ldclp->rwlock);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna /*
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna * NOTE: for now, we will assume we have a single channel.
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna */
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna if (ldclp->headp == NULL) {
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna RW_EXIT(&ldclp->rwlock);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna return (1);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna }
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna ldcp = ldclp->headp;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna mutex_enter(&ldcp->pollq_lock);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna ldcp->polling_on = B_FALSE;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna mutex_exit(&ldcp->pollq_lock);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna RW_EXIT(&ldclp->rwlock);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna return (0);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna}
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatnaint
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatnavgen_disable_intr(void *arg)
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna{
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna vgen_port_t *portp = (vgen_port_t *)arg;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna vgen_ldclist_t *ldclp;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna vgen_ldc_t *ldcp;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna ldclp = &portp->ldclist;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna READ_ENTER(&ldclp->rwlock);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna /*
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna * NOTE: for now, we will assume we have a single channel.
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna */
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna if (ldclp->headp == NULL) {
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna RW_EXIT(&ldclp->rwlock);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna return (1);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna }
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna ldcp = ldclp->headp;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna mutex_enter(&ldcp->pollq_lock);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna ldcp->polling_on = B_TRUE;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna mutex_exit(&ldcp->pollq_lock);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna RW_EXIT(&ldclp->rwlock);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna return (0);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna}
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatnamblk_t *
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatnavgen_poll(void *arg, int bytes_to_pickup)
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna{
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna vgen_port_t *portp = (vgen_port_t *)arg;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna vgen_ldclist_t *ldclp;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna vgen_ldc_t *ldcp;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna mblk_t *mp = NULL;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna ldclp = &portp->ldclist;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna READ_ENTER(&ldclp->rwlock);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna /*
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna * NOTE: for now, we will assume we have a single channel.
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna */
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna if (ldclp->headp == NULL) {
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna RW_EXIT(&ldclp->rwlock);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna return (NULL);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna }
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna ldcp = ldclp->headp;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna mp = vgen_ldc_poll(ldcp, bytes_to_pickup);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna RW_EXIT(&ldclp->rwlock);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna return (mp);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna}
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatnastatic mblk_t *
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatnavgen_ldc_poll(vgen_ldc_t *ldcp, int bytes_to_pickup)
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna{
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna mblk_t *bp = NULL;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna mblk_t *bpt = NULL;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna mblk_t *mp = NULL;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna size_t mblk_sz = 0;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna size_t sz = 0;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna uint_t count = 0;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna mutex_enter(&ldcp->pollq_lock);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna bp = ldcp->pollq_headp;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna while (bp != NULL) {
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna /* get the size of this packet */
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna mblk_sz = msgdsize(bp);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna /* if adding this pkt, exceeds the size limit, we are done. */
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna if (sz + mblk_sz > bytes_to_pickup) {
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna break;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna }
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna /* we have room for this packet */
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna sz += mblk_sz;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna /* increment the # of packets being sent up */
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna count++;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna /* track the last processed pkt */
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna bpt = bp;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna /* get the next pkt */
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna bp = bp->b_next;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna }
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna if (count != 0) {
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna /*
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna * picked up some packets; save the head of pkts to be sent up.
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna */
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna mp = ldcp->pollq_headp;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna /* move the pollq_headp to skip over the pkts being sent up */
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna ldcp->pollq_headp = bp;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna /* picked up all pending pkts in the queue; reset tail also */
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna if (ldcp->pollq_headp == NULL) {
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna ldcp->pollq_tailp = NULL;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna }
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna /* terminate the tail of pkts to be sent up */
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna bpt->b_next = NULL;
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna }
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna mutex_exit(&ldcp->pollq_lock);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna DTRACE_PROBE1(vgen_poll_pkts, uint_t, count);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna return (mp);
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna}
63f531d1cf94e7ff3e74e15ca709808d96e239f3Sriharsha Basavapatna
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram#if DEBUG
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram/*
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram * Print debug messages - set to 0xf to enable all msgs
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram */
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramstatic void
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuramdebug_printf(const char *fname, vgen_t *vgenp,
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram vgen_ldc_t *ldcp, const char *fmt, ...)
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram{
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram char buf[256];
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram char *bufp = buf;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram va_list ap;
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if ((vgenp != NULL) && (vgenp->vnetp != NULL)) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram (void) sprintf(bufp, "vnet%d:",
b4d0458e18abef7b5e036915e96807c219ec1d58raghuram ((vnet_t *)(vgenp->vnetp))->instance);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram bufp += strlen(bufp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if (ldcp != NULL) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram (void) sprintf(bufp, "ldc(%ld):", ldcp->ldc_id);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram bufp += strlen(bufp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram (void) sprintf(bufp, "%s: ", fname);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram bufp += strlen(bufp);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram va_start(ap, fmt);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram (void) vsprintf(bufp, fmt, ap);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram va_end(ap);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram if ((ldcp == NULL) ||(vgendbg_ldcid == -1) ||
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram (vgendbg_ldcid == ldcp->ldc_id)) {
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram cmn_err(CE_CONT, "%s\n", buf);
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram }
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram}
844e62a3ec8c8ff5175bb35d1c38446e060730f6raghuram#endif
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna#ifdef VNET_IOC_DEBUG
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnastatic void
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnavgen_ioctl(void *arg, queue_t *q, mblk_t *mp)
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna{
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna struct iocblk *iocp;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vgen_port_t *portp;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna enum ioc_reply {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna IOC_INVAL = -1, /* bad, NAK with EINVAL */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna IOC_ACK /* OK, just send ACK */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna } status;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna int rv;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna iocp = (struct iocblk *)(uintptr_t)mp->b_rptr;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna iocp->ioc_error = 0;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna portp = (vgen_port_t *)arg;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (portp == NULL) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna status = IOC_INVAL;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna goto vgen_ioc_exit;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna }
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna mutex_enter(&portp->lock);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna switch (iocp->ioc_cmd) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna case VNET_FORCE_LINK_DOWN:
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna case VNET_FORCE_LINK_UP:
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna rv = vgen_force_link_state(portp, iocp->ioc_cmd);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna (rv == 0) ? (status = IOC_ACK) : (status = IOC_INVAL);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna break;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna default:
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna status = IOC_INVAL;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna break;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna }
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna mutex_exit(&portp->lock);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnavgen_ioc_exit:
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna switch (status) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna default:
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna case IOC_INVAL:
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna /* Error, reply with a NAK and EINVAL error */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna miocnak(q, mp, 0, EINVAL);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna break;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna case IOC_ACK:
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna /* OK, reply with an ACK */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna miocack(q, mp, 0, 0);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna break;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna }
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna}
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnastatic int
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnavgen_force_link_state(vgen_port_t *portp, int cmd)
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna{
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna ldc_status_t istatus;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vgen_ldclist_t *ldclp;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vgen_ldc_t *ldcp;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vgen_t *vgenp = portp->vgenp;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna int rv;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna ldclp = &portp->ldclist;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna READ_ENTER(&ldclp->rwlock);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna /*
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna * NOTE: for now, we will assume we have a single channel.
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (ldclp->headp == NULL) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna RW_EXIT(&ldclp->rwlock);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna return (1);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna }
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna ldcp = ldclp->headp;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna mutex_enter(&ldcp->cblock);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna switch (cmd) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna case VNET_FORCE_LINK_DOWN:
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna (void) ldc_down(ldcp->ldc_handle);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna ldcp->link_down_forced = B_TRUE;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna break;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna case VNET_FORCE_LINK_UP:
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna rv = ldc_up(ldcp->ldc_handle);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (rv != 0) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna DWARN(vgenp, ldcp, "ldc_up err rv(%d)\n", rv);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna }
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna ldcp->link_down_forced = B_FALSE;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (ldc_status(ldcp->ldc_handle, &istatus) != 0) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna DWARN(vgenp, ldcp, "ldc_status err\n");
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna } else {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna ldcp->ldc_status = istatus;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna }
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna /* if channel is already UP - restart handshake */
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (ldcp->ldc_status == LDC_UP) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vgen_handle_evt_up(ldcp);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna }
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna break;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna }
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna mutex_exit(&ldcp->cblock);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna RW_EXIT(&ldclp->rwlock);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna return (0);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna}
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna#else
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnastatic void
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatnavgen_ioctl(void *arg, queue_t *q, mblk_t *mp)
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna{
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna vgen_port_t *portp;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna portp = (vgen_port_t *)arg;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna if (portp == NULL) {
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna miocnak(q, mp, 0, EINVAL);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna return;
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna }
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna miocnak(q, mp, 0, ENOTSUP);
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna}
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna
1107ea9346159bcc8ea154084897667347c4e6d5Sriharsha Basavapatna#endif