vnet_gen.c revision bd8f0338e0109a8df4e34499bdf42e592c77eeda
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/*
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Use is subject to license terms.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#pragma ident "%Z%%M% %I% %E% SMI"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/types.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/errno.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/param.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/stream.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>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/mac.h>
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb#include <sys/mac_ether.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/ldc.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/mach_descrip.h>
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#include <sys/mdeg.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>
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 */
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebint vgen_init(void *vnetp, dev_info_t *vnetdip, const uint8_t *macaddr,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb mac_register_t **vgenmacp);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayanint vgen_uninit(void *arg);
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);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void vgen_ioctl(void *arg, queue_t *wq, mblk_t *mp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* externs - functions provided by vnet to add/remove/modify entries in fdb */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovoid vnet_add_fdb(void *arg, uint8_t *macaddr, mac_tx_t m_tx, void *txarg);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovoid vnet_del_fdb(void *arg, uint8_t *macaddr);
3af08d828975d7e2581b6829e0eecff14d87a483lmvoid vnet_modify_fdb(void *arg, uint8_t *macaddr, mac_tx_t m_tx,
3af08d828975d7e2581b6829e0eecff14d87a483lm void *txarg, boolean_t upgrade);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovoid vnet_add_def_rte(void *arg, mac_tx_t m_tx, void *txarg);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovoid vnet_del_def_rte(void *arg);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebvoid vnet_rx(void *arg, mac_resource_handle_t mrh, mblk_t *mp);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebvoid vnet_tx_update(void *arg);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* vgen internal functions */
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);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_add_port(vgen_t *vgenp, md_t *mdp, mde_cookie_t mdex);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_remove_port(vgen_t *vgenp, md_t *mdp, mde_cookie_t mdex);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_port_attach_mdeg(vgen_t *vgenp, int port_num, uint64_t *ldcids,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int num_ids, struct ether_addr *macaddr, boolean_t vsw_port);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic 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);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
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);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_ldcsend(vgen_ldc_t *ldcp, 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);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_setup_kstats(vgen_ldc_t *ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void vgen_destroy_kstats(vgen_ldc_t *ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_kstat_update(kstat_t *ksp, int rw);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* vgen handshake functions */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic vgen_ldc_t *vh_nextphase(vgen_ldc_t *ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_supported_version(vgen_ldc_t *ldcp, uint16_t ver_major,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint16_t ver_minor);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_next_version(vgen_ldc_t *ldcp, vgen_ver_t *verp);
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);
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic int vgen_handle_dring_data(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mblk_t **headp, mblk_t **tailp);
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);
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic int vgen_handle_datamsg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mblk_t **headp, mblk_t **tailp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void vgen_handle_errmsg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic void vgen_handle_evt_up(vgen_ldc_t *ldcp, boolean_t flag);
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic void vgen_handle_evt_reset(vgen_ldc_t *ldcp, boolean_t flag);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_check_sid(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic uint64_t vgen_macaddr_strtoul(const uint8_t *macaddr);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_macaddr_ultostr(uint64_t value, uint8_t *macaddr);
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);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
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
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#define LDC_LOCK(ldcp) \
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_enter(&((ldcp)->cblock));\
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));\
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&((ldcp)->cblock));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
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";
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* versions supported - in decreasing order */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic vgen_ver_t vgen_versions[VGEN_NUM_VER] = { {1, 0} };
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* Tunables */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppouint32_t vgen_hwd_interval = 1000; /* handshake watchdog freq in msec */
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 */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayanuint32_t vgen_recv_delay = 1; /* delay when rx descr not ready */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayanuint32_t vgen_recv_retries = 10; /* retry when rx descr not ready */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#ifdef DEBUG
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* flags to simulate error conditions for debugging */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoint vgen_trigger_txtimeout = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoint vgen_trigger_rxlost = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#endif
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
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
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int vgen_mdeg_cb(void *cb_argp, mdeg_result_t *resp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebstatic mac_callbacks_t vgen_m_callbacks = {
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb 0,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb vgen_stat,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb vgen_start,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb vgen_stop,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb vgen_promisc,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb vgen_multicst,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb vgen_unicst,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb vgen_tx,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb NULL,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb NULL,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb NULL
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb};
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* externs */
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;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoextern int _vnet_dbglevel;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoextern void _vnetdebug_printf(void *vnetp, const char *fmt, ...);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#ifdef DEBUG
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/*
3af08d828975d7e2581b6829e0eecff14d87a483lm * NOTE: definitions below need to be in sync with those in vnet.c
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * debug levels:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * DBG_LEVEL1: Function entry/exit tracing
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * DBG_LEVEL2: Info messages
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * DBG_LEVEL3: Warning messages
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * DBG_LEVEL4: Error messages
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoenum { DBG_LEVEL1 = 0x01, DBG_LEVEL2 = 0x02, DBG_LEVEL3 = 0x04,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG_LEVEL4 = 0x08 };
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#define DBG1(_s) do { \
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((_vnet_dbglevel & DBG_LEVEL1) != 0) { \
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo _vnetdebug_printf _s; \
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } \
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo _NOTE(CONSTCOND) } while (0)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#define DBG2(_s) do { \
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((_vnet_dbglevel & DBG_LEVEL2) != 0) { \
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo _vnetdebug_printf _s; \
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } \
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo _NOTE(CONSTCOND) } while (0)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#define DWARN(_s) do { \
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((_vnet_dbglevel & DBG_LEVEL3) != 0) { \
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo _vnetdebug_printf _s; \
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } \
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo _NOTE(CONSTCOND) } while (0)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#define DERR(_s) do { \
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((_vnet_dbglevel & DBG_LEVEL4) != 0) { \
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo _vnetdebug_printf _s; \
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } \
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo _NOTE(CONSTCOND) } while (0)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#else
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#define DBG1(_s) if (0) _vnetdebug_printf _s
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#define DBG2(_s) if (0) _vnetdebug_printf _s
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#define DWARN(_s) if (0) _vnetdebug_printf _s
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#define DERR(_s) if (0) _vnetdebug_printf _s
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#endif
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#ifdef DEBUG
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
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
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
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb * the mac address of the vnet device, and a pointer to mac_register_t of
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb * the generic transport is returned in the last argument.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoint
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebvgen_init(void *vnetp, dev_info_t *vnetdip, const uint8_t *macaddr,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb mac_register_t **vgenmacp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_t *vgenp;
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb mac_register_t *macp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int instance;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb if ((vnetp == NULL) || (vnetdip == NULL))
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo instance = ddi_get_instance(vnetdip);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vnetp, "vgen_init: enter vnet_instance(%d)\n", instance));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp = kmem_zalloc(sizeof (vgen_t), KM_SLEEP);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp->vnetp = vnetp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp->vnetdip = vnetdip;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bcopy(macaddr, &(vgenp->macaddr), ETHERADDRL);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb KMEM_FREE(vgenp);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb return (DDI_FAILURE);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb }
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb macp->m_driver = vgenp;
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb macp->m_dip = vnetdip;
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb macp->m_src_addr = (uint8_t *)&(vgenp->macaddr);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb macp->m_callbacks = &vgen_m_callbacks;
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb macp->m_min_sdu = 0;
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb macp->m_max_sdu = ETHERMTU;
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb vgenp->macp = macp;
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb
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);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* register with MD event generator */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vgen_mdeg_reg(vgenp) != DDI_SUCCESS) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_destroy(&vgenp->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kmem_free(vgenp->mctab, VGEN_INIT_MCTAB_SIZE *
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo sizeof (struct ether_addr));
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb mac_free(vgenp->macp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo KMEM_FREE(vgenp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb /* register macp of this vgen_t with vnet */
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb *vgenmacp = vgenp->macp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vnetp, "vgen_init: exit vnet_instance(%d)\n", instance));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
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 */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayanint
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_uninit(void *arg)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_t *vgenp = (vgen_t *)arg;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo void *vnetp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int instance;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan vio_mblk_pool_t *rp, *nrp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan if (vgenp == NULL) {
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan return (DDI_FAILURE);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo instance = ddi_get_instance(vgenp->vnetdip);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vnetp = vgenp->vnetp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vnetp, "vgen_uninit: enter vnet_instance(%d)\n", instance));
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)) {
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan vgenp->rmp = rp;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan mutex_exit(&vgenp->lock);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan return (DDI_FAILURE);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan rp = nrp;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* free multicast table */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kmem_free(vgenp->mctab, vgenp->mcsize * sizeof (struct ether_addr));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb mac_free(vgenp->macp);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&vgenp->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_destroy(&vgenp->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo KMEM_FREE(vgenp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vnetp, "vgen_uninit: exit vnet_instance(%d)\n", instance));
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan return (DDI_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* enable transmit/receive for the device */
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebint
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_start(void *arg)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_t *vgenp = (vgen_t *)arg;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vgenp->vnetp, "vgen_start: enter\n"));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_enter(&vgenp->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_init_ports(vgenp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp->flags |= VGEN_STARTED;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&vgenp->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vgenp->vnetp, "vgen_start: exit\n"));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* stop transmit/receive */
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebvoid
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_stop(void *arg)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_t *vgenp = (vgen_t *)arg;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vgenp->vnetp, "vgen_stop: enter\n"));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_enter(&vgenp->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_uninit_ports(vgenp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp->flags &= ~(VGEN_STARTED);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&vgenp->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vgenp->vnetp, "vgen_stop: exit\n"));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* vgen transmit function */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic mblk_t *
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_tx(void *arg, mblk_t *mp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_port_t *portp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int status;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo portp = (vgen_port_t *)arg;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo status = vgen_portsend(portp, mp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (status != VGEN_SUCCESS) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* failure */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (mp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* success */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (NULL);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* transmit packets over the given port */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_portsend(vgen_port_t *portp, mblk_t *mp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_ldclist_t *ldclp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_ldc_t *ldcp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int status;
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);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp = ldclp->headp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ldcp->need_resched) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* out of tx resources, see vgen_ldcsend() for details. */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_enter(&ldcp->txlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->statsp->tx_no_desc++;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&ldcp->txlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo RW_EXIT(&ldclp->rwlock);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo status = vgen_ldcsend(ldcp, mp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo RW_EXIT(&ldclp->rwlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (status != VGEN_TX_SUCCESS)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* channel transmit function */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_ldcsend(vgen_ldc_t *ldcp, mblk_t *mp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo void *vnetp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo size_t size;
3af08d828975d7e2581b6829e0eecff14d87a483lm int rv = 0;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan uint64_t tbuf_ix;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_private_desc_t *tbufp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_private_desc_t *ntbufp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vnet_public_desc_t *txdp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vio_dring_entry_hdr_t *hdrp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_stats_t *statsp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo struct ether_header *ehp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo boolean_t is_bcast = B_FALSE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo boolean_t is_mcast = B_FALSE;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan size_t mblksz;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan caddr_t dst;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan mblk_t *bp;
3af08d828975d7e2581b6829e0eecff14d87a483lm ldc_status_t istatus;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vnetp = LDC_TO_VNET(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo statsp = ldcp->statsp;
8e6a2a040587479821d1e682a28bcef7e75f19a6lm size = msgsize(mp);
8e6a2a040587479821d1e682a28bcef7e75f19a6lm
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vnetp, "vgen_ldcsend: enter ldcid(%lx)\n", ldcp->ldc_id));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
8e6a2a040587479821d1e682a28bcef7e75f19a6lm mutex_enter(&ldcp->txlock);
8e6a2a040587479821d1e682a28bcef7e75f19a6lm
8e6a2a040587479821d1e682a28bcef7e75f19a6lm /* drop the packet if ldc is not up or handshake is not done */
8e6a2a040587479821d1e682a28bcef7e75f19a6lm if (ldcp->ldc_status != LDC_UP) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_ldcsend: id(%lx) status(%d), dropping packet\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id, ldcp->ldc_status));
8e6a2a040587479821d1e682a28bcef7e75f19a6lm /* retry ldc_up() if needed */
8e6a2a040587479821d1e682a28bcef7e75f19a6lm if (ldcp->flags & CHANNEL_STARTED)
8e6a2a040587479821d1e682a28bcef7e75f19a6lm (void) ldc_up(ldcp->ldc_handle);
8e6a2a040587479821d1e682a28bcef7e75f19a6lm goto vgen_tx_exit;
8e6a2a040587479821d1e682a28bcef7e75f19a6lm }
8e6a2a040587479821d1e682a28bcef7e75f19a6lm
8e6a2a040587479821d1e682a28bcef7e75f19a6lm if (ldcp->hphase != VH_DONE) {
8e6a2a040587479821d1e682a28bcef7e75f19a6lm DWARN((vnetp,
8e6a2a040587479821d1e682a28bcef7e75f19a6lm "vgen_ldcsend: id(%lx) hphase(%x), dropping packet\n",
8e6a2a040587479821d1e682a28bcef7e75f19a6lm ldcp->ldc_id, ldcp->hphase));
8e6a2a040587479821d1e682a28bcef7e75f19a6lm goto vgen_tx_exit;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (size > (size_t)ETHERMAX) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp, "vgen_ldcsend: id(%lx) invalid size(%d)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id, size));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo goto vgen_tx_exit;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
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);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan if (ntbufp == ldcp->cur_tbufp) {
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 }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
8e6a2a040587479821d1e682a28bcef7e75f19a6lm if (size < ETHERMIN)
8e6a2a040587479821d1e682a28bcef7e75f19a6lm size = ETHERMIN;
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
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan tbuf_ix = tbufp - ldcp->tbufp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
8e6a2a040587479821d1e682a28bcef7e75f19a6lm ehp = (struct ether_header *)tbufp->datap;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo is_bcast = IS_BROADCAST(ehp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo is_mcast = IS_MULTICAST(ehp);
8e6a2a040587479821d1e682a28bcef7e75f19a6lm
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tbufp->flags = VGEN_PRIV_DESC_BUSY;
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),
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan tbufp->ncookies * sizeof (ldc_mem_cookie_t));
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan hdrp->dstate = VIO_DESC_READY;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* send dring datamsg to the peer */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan if (ldcp->resched_peer) {
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan rv = vgen_send_dring_data(ldcp, (uint32_t)tbuf_ix, -1);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan if (rv != 0) {
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan /* vgen_send_dring_data() error: drop the packet */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan DWARN((vnetp,
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan "vgen_ldcsend: vgen_send_dring_data(): failed: "
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan "id(%lx) rv(%d) len (%d)\n",
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan ldcp->ldc_id, rv, size));
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan tbufp->flags = VGEN_PRIV_DESC_FREE; /* free tbuf */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan hdrp->dstate = VIO_DESC_FREE; /* free txd */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan hdrp->ack = B_FALSE;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan statsp->oerrors++;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan goto vgen_tx_exit;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan ldcp->resched_peer = B_FALSE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* update next available tbuf in the ring */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->next_tbufp = ntbufp;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan /* update tx index */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo INCR_TXI(ldcp->next_txi, ldcp);
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
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_tx_exit:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&ldcp->txlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
3af08d828975d7e2581b6829e0eecff14d87a483lm if (rv == ECONNRESET) {
3af08d828975d7e2581b6829e0eecff14d87a483lm /*
3af08d828975d7e2581b6829e0eecff14d87a483lm * Check if either callback thread or another tx thread is
3af08d828975d7e2581b6829e0eecff14d87a483lm * already running. Calling mutex_enter() will result in a
3af08d828975d7e2581b6829e0eecff14d87a483lm * deadlock if the other thread already holds cblock and is
3af08d828975d7e2581b6829e0eecff14d87a483lm * blocked in vnet_modify_fdb() (which is called from
3af08d828975d7e2581b6829e0eecff14d87a483lm * vgen_handle_evt_reset()) waiting for write access on rwlock,
3af08d828975d7e2581b6829e0eecff14d87a483lm * as this transmit thread already holds that lock as a reader
3af08d828975d7e2581b6829e0eecff14d87a483lm * in vnet_m_tx(). See comments in vnet_modify_fdb() in vnet.c.
3af08d828975d7e2581b6829e0eecff14d87a483lm */
3af08d828975d7e2581b6829e0eecff14d87a483lm if (mutex_tryenter(&ldcp->cblock)) {
3af08d828975d7e2581b6829e0eecff14d87a483lm if (ldc_status(ldcp->ldc_handle, &istatus) != 0) {
3af08d828975d7e2581b6829e0eecff14d87a483lm DWARN((vnetp,
3af08d828975d7e2581b6829e0eecff14d87a483lm "vgen_ldcsend: ldc_status err id(%lx)\n"));
3af08d828975d7e2581b6829e0eecff14d87a483lm } else {
3af08d828975d7e2581b6829e0eecff14d87a483lm ldcp->ldc_status = istatus;
3af08d828975d7e2581b6829e0eecff14d87a483lm }
3af08d828975d7e2581b6829e0eecff14d87a483lm if (ldcp->ldc_status != LDC_UP) {
3af08d828975d7e2581b6829e0eecff14d87a483lm /*
3af08d828975d7e2581b6829e0eecff14d87a483lm * Second arg is TRUE, as we know that
3af08d828975d7e2581b6829e0eecff14d87a483lm * the caller of this function - vnet_m_tx(),
3af08d828975d7e2581b6829e0eecff14d87a483lm * already holds fdb-rwlock as a reader.
3af08d828975d7e2581b6829e0eecff14d87a483lm */
3af08d828975d7e2581b6829e0eecff14d87a483lm vgen_handle_evt_reset(ldcp, B_TRUE);
3af08d828975d7e2581b6829e0eecff14d87a483lm }
3af08d828975d7e2581b6829e0eecff14d87a483lm mutex_exit(&ldcp->cblock);
3af08d828975d7e2581b6829e0eecff14d87a483lm }
3af08d828975d7e2581b6829e0eecff14d87a483lm }
3af08d828975d7e2581b6829e0eecff14d87a483lm
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vnetp, "vgen_ldcsend: exit: ldcid (%lx)\n", ldcp->ldc_id));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
8e6a2a040587479821d1e682a28bcef7e75f19a6lm freemsg(mp);
8e6a2a040587479821d1e682a28bcef7e75f19a6lm return (VGEN_TX_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* enable/disable a multicast address */
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_portlist_t *plistp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_ldc_t *ldcp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_ldclist_t *ldclp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo void *vnetp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo struct ether_addr *addrp;
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan int rv = DDI_FAILURE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint32_t i;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp = (vgen_t *)arg;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vnetp = vgenp->vnetp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo addrp = (struct ether_addr *)mca;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp = &mcastmsg.tag;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bzero(&mcastmsg, sizeof (mcastmsg));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_enter(&vgenp->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo plistp = &(vgenp->vgenports);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo READ_ENTER(&plistp->rwlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo portp = vgenp->vsw_portp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (portp == NULL) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo RW_EXIT(&plistp->rwlock);
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan mutex_exit(&vgenp->lock);
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldclp = &portp->ldclist;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo READ_ENTER(&ldclp->rwlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp = ldclp->headp;
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan if (ldcp == NULL)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo goto vgen_mcast_exit;
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
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * the multicast address.
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) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp, "vgen_mutlicst: vgen_sendmsg failed"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "id (%lx)\n", ldcp->ldc_id));
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan mutex_exit(&ldcp->cblock);
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan goto vgen_mcast_exit;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } else {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* set the flag to send a msg to vsw after handshake is done */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->need_mcast_sync = B_TRUE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&ldcp->cblock);
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] =
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp->mctab[vgenp->mccount-1];
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp->mccount--;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan rv = DDI_SUCCESS;
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayanvgen_mcast_exit:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo RW_EXIT(&ldclp->rwlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo RW_EXIT(&plistp->rwlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&vgenp->lock);
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{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_t *vgenp = (vgen_t *)arg;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_port_t *portp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_portlist_t *plistp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb *val = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo plistp = &(vgenp->vgenports);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo READ_ENTER(&plistp->rwlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (portp = plistp->headp; portp != NULL; portp = portp->nextp) {
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb *val += vgen_port_stat(portp, stat);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo RW_EXIT(&plistp->rwlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb return (0);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_ioctl(void *arg, queue_t *wq, mblk_t *mp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo _NOTE(ARGUNUSED(arg, wq, mp))
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
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo while ((portp = plistp->headp) != NULL) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_port_detach(portp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
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
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vgenp->vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_port_detach: enter: port_num(%d)\n", port_num));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
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);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vgenp->vsw_portp == portp) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp->vsw_portp = NULL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo KMEM_FREE(portp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vgenp->vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_port_detach: exit: port_num(%d)\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 {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (prevp = plistp->headp; ((nextp = prevp->nextp) != NULL) &&
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (nextp != portp); prevp = nextp);
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{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_t *vgenp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp = portp->vgenp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Create fdb entry in vnet, corresponding to the mac
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * address of this port. Note that the port specified
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * is vsw-port. This is done so that vsw-port acts
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * as the route to reach this macaddr, until the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * channel for this port comes up (LDC_UP) and
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * handshake is done successfully.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * eg, if the peer is OBP-vnet, it may not bring the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * channel up for this port and may communicate via
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * vsw to reach this port.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Later, when Solaris-vnet comes up at the other end
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * of the channel for this port and brings up the channel,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * it is an indication that peer vnet is capable of
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * distributed switching, so the direct route through this
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * port is specified in fdb, using vnet_modify_fdb(macaddr);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vnet_add_fdb(vgenp->vnetp, (uint8_t *)&portp->macaddr,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_tx, vgenp->vsw_portp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (portp == vgenp->vsw_portp) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * create the default route entry in vnet's fdb.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * This is the entry used by vnet to reach
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * unknown destinations, which basically goes
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * through vsw on domain0 and out through the
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * physical device bound to vsw.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vnet_add_def_rte(vgenp->vnetp, vgen_tx, portp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
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_t *vgenp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp = portp->vgenp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_uninit_ldcs(portp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* delete the entry in vnet's fdb for this port */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vnet_del_fdb(vgenp->vnetp, (uint8_t *)&portp->macaddr);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (portp == vgenp->vsw_portp) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * if this is vsw-port, then delete the default
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * route entry in vnet's fdb.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vnet_del_def_rte(vgenp->vnetp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
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;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mdeg_handle_t hdl;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int i;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo void *vnetp = vgenp->vnetp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo i = ddi_prop_get_int(DDI_DEV_T_ANY, vgenp->vnetdip,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DDI_PROP_DONTPASS, reg_propname, -1);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (i == -1) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
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 */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo VGEN_SET_MDEG_PROP_INST(pspecp, i);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo parentp->namep = "virtual-device";
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo parentp->specp = pspecp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* save parentp in vgen_t */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp->mdeg_parentp = parentp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = mdeg_register(parentp, &vport_match, vgen_mdeg_cb, vgenp, &hdl);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rv != MDEG_SUCCESS) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DERR((vnetp, "vgen_mdeg_reg: mdeg_register failed\n"));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo KMEM_FREE(parentp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kmem_free(pspecp, templatesz);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp->mdeg_parentp = NULL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* save mdeg handle in vgen_t */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp->mdeg_hdl = hdl;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* unregister with MD event generator */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_mdeg_unreg(vgen_t *vgenp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void) mdeg_unregister(vgenp->mdeg_hdl);
445b4c2ed2d52ef648ae6b36e4f5e14ff3d234afsb kmem_free(vgenp->mdeg_parentp->specp, sizeof (vgen_prop_template));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo KMEM_FREE(vgenp->mdeg_parentp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp->mdeg_parentp = NULL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp->mdeg_hdl = NULL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* callback function registered with MD event generator */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_mdeg_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;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vgenp->vnetp, "vgen_mdeg_cb: enter\n"));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_enter(&vgenp->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vgenp->vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_mdeg_cb: ports: removed(%x), added(%x), updated(%x)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo resp->removed.nelem, 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
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * vsw on dom0.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vsw_idx = idx;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void) vgen_add_port(vgenp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo resp->added.mdp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo resp->added.mdep[idx]);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vsw_idx == -1) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vgenp->vnetp, "vgen_mdeg_cb: "
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "can't find vsw_port\n"));
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;
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);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vgenp->vnetp, "vgen_mdeg_cb: exit\n"));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (MDEG_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* add a new port to the device */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_add_port(vgen_t *vgenp, md_t *mdp, mde_cookie_t mdex)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint64_t port_num;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint64_t *ldc_ids;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint64_t macaddr;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint64_t val;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int num_ldcs;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int vsw_port = B_FALSE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int i;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int addrsz;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int num_nodes = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int listsz = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mde_cookie_t *listp = NULL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo 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)) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vgenp->vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_add_port: 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) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vgenp->vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_add_port: invalid number of nodes found (%d)",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo 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,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo md_find_name(mdp, channel_propname),
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo md_find_name(mdp, "fwd"), listp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (num_ldcs <= 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vgenp->vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_add_port: can't find %s nodes", channel_propname));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kmem_free(listp, listsz);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG2((vgenp->vnetp, "vgen_add_port: 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])) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vgenp->vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_add_port: prop(%s) not found\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo id_propname));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kmem_free(listp, listsz);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kmem_free(ldc_ids, num_ldcs * sizeof (uint64_t));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG2((vgenp->vnetp, "vgen_add_port: ldc_id 0x%llx",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldc_ids[i]));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kmem_free(listp, listsz);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (md_get_prop_data(mdp, mdex, rmacaddr_propname, &addrp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo &addrsz)) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vgenp->vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_add_port: 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) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vgenp->vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_add_port: 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
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG2((vgenp->vnetp, "vgen_add_port: remote mac address 0x%llx\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo macaddr));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (i = ETHERADDRL - 1; i >= 0; i--) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ea.ether_addr_octet[i] = macaddr & 0xFF;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo macaddr >>= 8;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vgenp->vsw_portp == NULL) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (!(md_get_prop_val(mdp, mdex, swport_propname, &val))) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (val == 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* This port is connected to the vsw on dom0 */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vsw_port = B_TRUE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void) vgen_port_attach_mdeg(vgenp, (int)port_num, ldc_ids, num_ldcs,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo &ea, vsw_port);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kmem_free(ldc_ids, num_ldcs * sizeof (uint64_t));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo 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)) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vgenp->vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_remove_port: 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) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vgenp->vnetp, "vgen_remove_port: can't find port(%lx)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo 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
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_port_attach_mdeg(vgen_t *vgenp, int port_num, uint64_t *ldcids,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int num_ids, struct ether_addr *macaddr, boolean_t vsw_port)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_port_t *portp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_portlist_t *plistp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int i;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo portp = kmem_zalloc(sizeof (vgen_port_t), KM_NOSLEEP);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (portp == NULL) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo portp->vgenp = vgenp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo portp->port_num = port_num;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vgenp->vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_port_attach_mdeg: port_num(%d)\n", portp->port_num));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo portp->ldclist.num_ldcs = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo portp->ldclist.headp = NULL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rw_init(&portp->ldclist.rwlock, NULL, RW_DRIVER, NULL);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ether_copy(macaddr, &portp->macaddr);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (i = 0; i < num_ids; i++) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG2((vgenp->vnetp, "vgen_port_attach_mdeg: ldcid (%lx)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcids[i]));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void) vgen_ldc_attach(portp, ldcids[i]);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* link it into the list of ports */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo plistp = &(vgenp->vgenports);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo WRITE_ENTER(&plistp->rwlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_port_list_insert(portp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo RW_EXIT(&plistp->rwlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* This port is connected to the vsw on domain0 */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vsw_port)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp->vsw_portp = portp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vgenp->flags & VGEN_STARTED) { /* interface is configured */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_port_init(portp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vgenp->vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_port_attach_mdeg: 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
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vgenp->vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_port_detach_mdeg: enter: port_num(%d)\n", portp->port_num));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* stop the port if needed */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vgenp->flags & VGEN_STARTED) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_port_uninit(portp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_port_detach(portp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vgenp->vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_port_detach_mdeg: 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{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo _NOTE(ARGUNUSED(vgenp, curr_mdp, curr_mdex, prev_mdp, prev_mdex))
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
3af08d828975d7e2581b6829e0eecff14d87a483lm /* NOTE: TBD */
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
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;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo enum {AST_init = 0x0, AST_ldc_alloc = 0x1,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo AST_mutex_init = 0x2, AST_ldc_init = 0x4,
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan AST_ldc_reg_cb = 0x8, AST_alloc_tx_ring = 0x10,
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan AST_create_rxmblks = 0x20}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo 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);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo attach_state |= AST_mutex_init;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo attr.devclass = LDC_DEV_NT;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo attr.instance = ddi_get_instance(vgenp->vnetdip);
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) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vgenp->vnetp, "ldc_init failed, id (%lx) rv (%d)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldc_id, status));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo goto ldc_attach_failed;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo attach_state |= AST_ldc_init;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo status = ldc_reg_callback(ldcp->ldc_handle, vgen_ldc_cb, (caddr_t)ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (status != 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vgenp->vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "ldc_reg_callback failed, id (%lx) rv (%d)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldc_id, status));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo goto ldc_attach_failed;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
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 */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan ldcp->num_rbufs = vnet_nrbufs;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan ldcp->rmp = NULL;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan status = vio_create_mblks(ldcp->num_rbufs, VGEN_DBLK_SZ,
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan &(ldcp->rmp));
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan if (status != 0) {
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan goto ldc_attach_failed;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan attach_state |= AST_create_rxmblks;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* Setup kstats for the channel */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo status = vgen_setup_kstats(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (status != VGEN_SUCCESS) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo goto ldc_attach_failed;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* initialize vgen_versions supported */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bcopy(vgen_versions, ldcp->vgen_versions, sizeof (ldcp->vgen_versions));
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 ldclp->num_ldcs++;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo RW_EXIT(&ldclp->rwlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->flags |= CHANNEL_ATTACHED;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppoldc_attach_failed:
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan if (attach_state & AST_create_rxmblks) {
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan (void) vio_destroy_mblks(ldcp->rmp);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (attach_state & AST_alloc_tx_ring) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_free_tx_ring(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (attach_state & AST_ldc_reg_cb) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void) ldc_unreg_callback(ldcp->ldc_handle);
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);
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) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vgenp->vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_ldc_detach: ldc_status is not INIT id(%lx)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ldcp->flags & CHANNEL_ATTACHED) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->flags &= ~(CHANNEL_ATTACHED);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_destroy_kstats(ldcp);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan /* free receive resources */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan if (vio_destroy_mblks(ldcp->rmp)) {
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan /*
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * if we cannot reclaim all mblks, put this
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * on the list of pools to be reclaimed when the
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * device gets detached (see vgen_uninit()).
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan ldcp->rmp->nextp = vgenp->rmp;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan vgenp->rmp = ldcp->rmp;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* free transmit resources */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_free_tx_ring(ldcp);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void) ldc_unreg_callback(ldcp->ldc_handle);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void) ldc_fini(ldcp->ldc_handle);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_destroy(&ldcp->tclock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_destroy(&ldcp->txlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_destroy(&ldcp->cblock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* unlink it from the list */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo *prev_ldcp = ldcp->nextp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldclp->num_ldcs--;
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;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo void *vnetp = LDC_TO_VNET(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) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp, "vgen_alloc_tx_ring: ldc_mem_dring_create() "
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "failed, id(%lx)\n", ldcp->ldc_id));
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) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp, "vgen_alloc_tx_ring: ldc_mem_dring_info() "
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "failed, id(%lx)\n", ldcp->ldc_id));
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{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo void *vnetp = LDC_TO_VNET(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldc_status_t istatus;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int rv;
3af08d828975d7e2581b6829e0eecff14d87a483lm enum { ST_init = 0x0, ST_ldc_open = 0x1,
3af08d828975d7e2581b6829e0eecff14d87a483lm ST_init_tbufs = 0x2, ST_cb_enable = 0x4
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo init_state;
8e6a2a040587479821d1e682a28bcef7e75f19a6lm uint32_t retries = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo init_state = ST_init;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo LDC_LOCK(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = ldc_open(ldcp->ldc_handle);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rv != 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_ldcinit: ldc_open failed: id<%lx> rv(%d)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id, 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) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_ldcinit: id (%lx) status(%d) is not OPEN/READY\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id, istatus));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo goto ldcinit_failed;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_status = istatus;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = vgen_init_tbufs(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rv != 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_ldcinit: vgen_init_tbufs() failed: id(%lx)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id));
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) {
3af08d828975d7e2581b6829e0eecff14d87a483lm DWARN((vnetp, "vgen_ldc_init: ldc_set_cb_mode failed: id(%lx) "
3af08d828975d7e2581b6829e0eecff14d87a483lm "rv(%d)\n", ldcp->ldc_id, 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)) {
8e6a2a040587479821d1e682a28bcef7e75f19a6lm DBG2((vnetp,
8e6a2a040587479821d1e682a28bcef7e75f19a6lm "vgen_ldcinit: ldc_up err id(%lx) rv(%d)\n",
8e6a2a040587479821d1e682a28bcef7e75f19a6lm ldcp->ldc_id, 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) {
3af08d828975d7e2581b6829e0eecff14d87a483lm DWARN((vnetp, "vgen_ldc_init: id(%lx) status(%d) is UP\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id, 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 /*
3af08d828975d7e2581b6829e0eecff14d87a483lm * modify fdb entry to use this port as the
3af08d828975d7e2581b6829e0eecff14d87a483lm * channel is up, instead of going through the
3af08d828975d7e2581b6829e0eecff14d87a483lm * vsw-port (see comments in vgen_port_init())
3af08d828975d7e2581b6829e0eecff14d87a483lm */
3af08d828975d7e2581b6829e0eecff14d87a483lm vnet_modify_fdb(vnetp,
3af08d828975d7e2581b6829e0eecff14d87a483lm (uint8_t *)&ldcp->portp->macaddr,
3af08d828975d7e2581b6829e0eecff14d87a483lm vgen_tx, ldcp->portp, 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);
3af08d828975d7e2581b6829e0eecff14d87a483lm 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);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (DDI_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* stop transmit/receive on the channel */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_ldc_uninit(vgen_ldc_t *ldcp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo void *vnetp = LDC_TO_VNET(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int rv;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vnetp, "vgen_ldc_uninit: enter: id(%lx)\n", ldcp->ldc_id));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo LDC_LOCK(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((ldcp->flags & CHANNEL_STARTED) == 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo LDC_UNLOCK(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp, "vgen_ldc_uninit: id(%lx) CHANNEL_STARTED"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo " flag is not set\n", ldcp->ldc_id));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* disable further callbacks */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = ldc_set_cb_mode(ldcp->ldc_handle, LDC_CB_DISABLE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rv != 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp, "vgen_ldc_uninit: id (%lx) "
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "ldc_set_cb_mode failed\n", ldcp->ldc_id));
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
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan /* cancel handshake watchdog timeout */
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan if (ldcp->htid) {
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan (void) untimeout(ldcp->htid);
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan ldcp->htid = 0;
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
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
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
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = ldc_close(ldcp->ldc_handle);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rv != 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp, "vgen_ldcuninit: ldc_close err id(%lx)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_status = LDC_INIT;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->flags &= ~(CHANNEL_STARTED);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo LDC_UNLOCK(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vnetp, "vgen_ldc_uninit: exit: id(%lx)\n", ldcp->ldc_id));
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;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bzero(ldcp->tbufp, sizeof (*tbufp) * (ldcp->num_txds));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bzero(ldcp->txdp, sizeof (*txdp) * (ldcp->num_txds));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan datap = kmem_zalloc(ldcp->num_txds * VGEN_DBLK_SZ, KM_SLEEP);
8e6a2a040587479821d1e682a28bcef7e75f19a6lm ldcp->tx_datap = datap;
8e6a2a040587479821d1e682a28bcef7e75f19a6lm
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,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo &(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,
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan (caddr_t)datap, VGEN_DBLK_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) ||
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan (ncookies > MAX_COOKIES)) {
8e6a2a040587479821d1e682a28bcef7e75f19a6lm goto init_tbufs_failed;
8e6a2a040587479821d1e682a28bcef7e75f19a6lm }
8e6a2a040587479821d1e682a28bcef7e75f19a6lm
8e6a2a040587479821d1e682a28bcef7e75f19a6lm for (ci = 1; ci < ncookies; ci++) {
8e6a2a040587479821d1e682a28bcef7e75f19a6lm rv = ldc_mem_nextcookie(tbufp->memhandle,
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan &(tbufp->memcookie[ci]));
8e6a2a040587479821d1e682a28bcef7e75f19a6lm if (rv != 0) {
8e6a2a040587479821d1e682a28bcef7e75f19a6lm goto init_tbufs_failed;
8e6a2a040587479821d1e682a28bcef7e75f19a6lm }
8e6a2a040587479821d1e682a28bcef7e75f19a6lm }
8e6a2a040587479821d1e682a28bcef7e75f19a6lm
8e6a2a040587479821d1e682a28bcef7e75f19a6lm tbufp->ncookies = ncookies;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan datap += VGEN_DBLK_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;
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 */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan kmem_free(ldcp->tx_datap, ldcp->num_txds * VGEN_DBLK_SZ);
8e6a2a040587479821d1e682a28bcef7e75f19a6lm ldcp->tx_datap = NULL;
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;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vio_dring_entry_hdr_t *hdrp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo void *vnetp = LDC_TO_VNET(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;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#ifdef DEBUG
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG2((vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_clobber_tbufs: id(0x%lx) num descrs done (%d)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id, ndone));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#endif
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,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo desc_size, LDC_SHADOW_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;
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;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo statsp = ldcp->statsp;
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/*
3af08d828975d7e2581b6829e0eecff14d87a483lm * LDC channel is UP, start handshake process with peer.
3af08d828975d7e2581b6829e0eecff14d87a483lm * Flag tells vnet_modify_fdb() about the context: set to B_TRUE if this
3af08d828975d7e2581b6829e0eecff14d87a483lm * function is being called from transmit routine, otherwise B_FALSE.
3af08d828975d7e2581b6829e0eecff14d87a483lm */
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic void
3af08d828975d7e2581b6829e0eecff14d87a483lmvgen_handle_evt_up(vgen_ldc_t *ldcp, boolean_t flag)
3af08d828975d7e2581b6829e0eecff14d87a483lm{
3af08d828975d7e2581b6829e0eecff14d87a483lm vgen_t *vgenp = LDC_TO_VGEN(ldcp);
3af08d828975d7e2581b6829e0eecff14d87a483lm void *vnetp = LDC_TO_VNET(ldcp);
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm DBG1((vnetp, "vgen_handle_evt_up: enter: id(%lx)\n", ldcp->ldc_id));
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm ASSERT(MUTEX_HELD(&ldcp->cblock));
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm if (ldcp->portp != vgenp->vsw_portp) {
3af08d828975d7e2581b6829e0eecff14d87a483lm /*
3af08d828975d7e2581b6829e0eecff14d87a483lm * modify fdb entry to use this port as the
3af08d828975d7e2581b6829e0eecff14d87a483lm * channel is up, instead of going through the
3af08d828975d7e2581b6829e0eecff14d87a483lm * vsw-port (see comments in vgen_port_init())
3af08d828975d7e2581b6829e0eecff14d87a483lm */
3af08d828975d7e2581b6829e0eecff14d87a483lm vnet_modify_fdb(vnetp, (uint8_t *)&ldcp->portp->macaddr,
3af08d828975d7e2581b6829e0eecff14d87a483lm vgen_tx, ldcp->portp, flag);
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
3af08d828975d7e2581b6829e0eecff14d87a483lm DBG1((vnetp, "vgen_handle_evt_up: exit: id(%lx)\n", ldcp->ldc_id));
3af08d828975d7e2581b6829e0eecff14d87a483lm}
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm/*
3af08d828975d7e2581b6829e0eecff14d87a483lm * LDC channel is Reset, terminate connection with peer and try to
3af08d828975d7e2581b6829e0eecff14d87a483lm * bring the channel up again.
3af08d828975d7e2581b6829e0eecff14d87a483lm * Flag tells vnet_modify_fdb() about the context: set to B_TRUE if this
3af08d828975d7e2581b6829e0eecff14d87a483lm * function is being called from transmit routine, otherwise B_FALSE.
3af08d828975d7e2581b6829e0eecff14d87a483lm */
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic void
3af08d828975d7e2581b6829e0eecff14d87a483lmvgen_handle_evt_reset(vgen_ldc_t *ldcp, boolean_t flag)
3af08d828975d7e2581b6829e0eecff14d87a483lm{
3af08d828975d7e2581b6829e0eecff14d87a483lm ldc_status_t istatus;
3af08d828975d7e2581b6829e0eecff14d87a483lm vgen_t *vgenp = LDC_TO_VGEN(ldcp);
3af08d828975d7e2581b6829e0eecff14d87a483lm void *vnetp = LDC_TO_VNET(ldcp);
3af08d828975d7e2581b6829e0eecff14d87a483lm int rv;
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm DBG1((vnetp, "vgen_handle_evt_reset: enter: id(%lx)\n", ldcp->ldc_id));
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm ASSERT(MUTEX_HELD(&ldcp->cblock));
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm if ((ldcp->portp != vgenp->vsw_portp) &&
3af08d828975d7e2581b6829e0eecff14d87a483lm (vgenp->vsw_portp != NULL)) {
3af08d828975d7e2581b6829e0eecff14d87a483lm /*
3af08d828975d7e2581b6829e0eecff14d87a483lm * modify fdb entry to use vsw-port as the
3af08d828975d7e2581b6829e0eecff14d87a483lm * channel is reset and we don't have a direct
3af08d828975d7e2581b6829e0eecff14d87a483lm * link to the destination (see comments
3af08d828975d7e2581b6829e0eecff14d87a483lm * in vgen_port_init()).
3af08d828975d7e2581b6829e0eecff14d87a483lm */
3af08d828975d7e2581b6829e0eecff14d87a483lm vnet_modify_fdb(vnetp, (uint8_t *)&ldcp->portp->macaddr,
3af08d828975d7e2581b6829e0eecff14d87a483lm vgen_tx, vgenp->vsw_portp, flag);
3af08d828975d7e2581b6829e0eecff14d87a483lm }
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm if (ldcp->hphase != VH_PHASE0) {
3af08d828975d7e2581b6829e0eecff14d87a483lm vgen_handshake_reset(ldcp);
3af08d828975d7e2581b6829e0eecff14d87a483lm }
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm /* try to bring the channel up */
3af08d828975d7e2581b6829e0eecff14d87a483lm rv = ldc_up(ldcp->ldc_handle);
3af08d828975d7e2581b6829e0eecff14d87a483lm if (rv != 0) {
3af08d828975d7e2581b6829e0eecff14d87a483lm DWARN((vnetp,
3af08d828975d7e2581b6829e0eecff14d87a483lm "vgen_handle_evt_reset: ldc_up err id(%lx) rv(%d)\n",
3af08d828975d7e2581b6829e0eecff14d87a483lm ldcp->ldc_id, rv));
3af08d828975d7e2581b6829e0eecff14d87a483lm }
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm if (ldc_status(ldcp->ldc_handle, &istatus) != 0) {
3af08d828975d7e2581b6829e0eecff14d87a483lm DWARN((vnetp,
3af08d828975d7e2581b6829e0eecff14d87a483lm "vgen_handle_evt_reset: ldc_status err id(%lx)\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) {
3af08d828975d7e2581b6829e0eecff14d87a483lm vgen_handle_evt_up(ldcp, flag);
3af08d828975d7e2581b6829e0eecff14d87a483lm }
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm DBG1((vnetp, "vgen_handle_evt_reset: exit: id(%lx)\n", ldcp->ldc_id));
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 void *vnetp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_t *vgenp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo size_t msglen;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldc_status_t istatus;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint64_t ldcmsg[7];
3af08d828975d7e2581b6829e0eecff14d87a483lm int rv = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vio_msg_tag_t *tagp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mblk_t *mp = NULL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mblk_t *bp = NULL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mblk_t *bpt = NULL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mblk_t *headp = NULL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mblk_t *tailp = NULL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_stats_t *statsp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp = (vgen_ldc_t *)arg;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp = LDC_TO_VGEN(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vnetp = LDC_TO_VNET(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo statsp = ldcp->statsp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vnetp, "vgen_ldc_cb enter: ldcid (%lx)\n", ldcp->ldc_id));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_enter(&ldcp->cblock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo statsp->callbacks++;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((ldcp->ldc_status == LDC_INIT) || (ldcp->ldc_handle == NULL)) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp, "vgen_ldc_cb: id(%lx), status(%d) is LDC_INIT\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id, ldcp->ldc_status));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&ldcp->cblock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (LDC_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
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) {
3af08d828975d7e2581b6829e0eecff14d87a483lm DWARN((vnetp,
3af08d828975d7e2581b6829e0eecff14d87a483lm "vgen_ldc_cb: ldc_status err id(%lx)\n"));
3af08d828975d7e2581b6829e0eecff14d87a483lm } else {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_status = istatus;
3af08d828975d7e2581b6829e0eecff14d87a483lm }
3af08d828975d7e2581b6829e0eecff14d87a483lm ASSERT(ldcp->ldc_status == LDC_UP);
3af08d828975d7e2581b6829e0eecff14d87a483lm DWARN((vnetp,
3af08d828975d7e2581b6829e0eecff14d87a483lm "vgen_ldc_cb: id(%lx) event(%lx) UP, status(%d)\n",
3af08d828975d7e2581b6829e0eecff14d87a483lm ldcp->ldc_id, event, ldcp->ldc_status));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
3af08d828975d7e2581b6829e0eecff14d87a483lm vgen_handle_evt_up(ldcp, B_FALSE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
3af08d828975d7e2581b6829e0eecff14d87a483lm ASSERT((event & (LDC_EVT_RESET | LDC_EVT_DOWN)) == 0);
3af08d828975d7e2581b6829e0eecff14d87a483lm }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
3af08d828975d7e2581b6829e0eecff14d87a483lm if (event & LDC_EVT_READ) {
3af08d828975d7e2581b6829e0eecff14d87a483lm DBG2((vnetp,
3af08d828975d7e2581b6829e0eecff14d87a483lm "vgen_ldc_cb: id(%lx) event(%lx) READ, status(%d)\n",
3af08d828975d7e2581b6829e0eecff14d87a483lm ldcp->ldc_id, event, ldcp->ldc_status));
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm ASSERT((event & (LDC_EVT_RESET | LDC_EVT_DOWN)) == 0);
3af08d828975d7e2581b6829e0eecff14d87a483lm goto vgen_ldccb_rcv;
3af08d828975d7e2581b6829e0eecff14d87a483lm }
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm if (event & (LDC_EVT_RESET | LDC_EVT_DOWN)) {
3af08d828975d7e2581b6829e0eecff14d87a483lm if (ldc_status(ldcp->ldc_handle, &istatus) != 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp,
3af08d828975d7e2581b6829e0eecff14d87a483lm "vgen_ldc_cb: ldc_status err id(%lx)\n"));
3af08d828975d7e2581b6829e0eecff14d87a483lm } else {
3af08d828975d7e2581b6829e0eecff14d87a483lm ldcp->ldc_status = istatus;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
3af08d828975d7e2581b6829e0eecff14d87a483lm DWARN((vnetp,
3af08d828975d7e2581b6829e0eecff14d87a483lm "vgen_ldc_cb: id(%lx) event(%lx) RESET/DOWN, status(%d)\n",
3af08d828975d7e2581b6829e0eecff14d87a483lm ldcp->ldc_id, event, ldcp->ldc_status));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
3af08d828975d7e2581b6829e0eecff14d87a483lm vgen_handle_evt_reset(ldcp, B_FALSE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
3af08d828975d7e2581b6829e0eecff14d87a483lm mutex_exit(&ldcp->cblock);
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan goto vgen_ldccb_exit;
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lmvgen_ldccb_rcv:
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm /* if event is LDC_EVT_READ, receive all packets */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo do {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo msglen = sizeof (ldcmsg);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = ldc_read(ldcp->ldc_handle, (caddr_t)&ldcmsg, &msglen);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rv != 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_ldc_cb:ldc_read err id(%lx) rv(%d) "
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "len(%d)\n", ldcp->ldc_id, rv, msglen));
3af08d828975d7e2581b6829e0eecff14d87a483lm if (rv == ECONNRESET)
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan goto vgen_ldccb_error;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (msglen == 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG2((vnetp, "vgen_ldc_cb: ldc_read id(%lx) NODATA",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG2((vnetp, "vgen_ldc_cb: ldc_read id(%lx): msglen(%d)",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id, 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 */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->need_ldc_reset = B_TRUE;
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan goto vgen_ldccb_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:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo headp = tailp = NULL;
3af08d828975d7e2581b6829e0eecff14d87a483lm rv = vgen_handle_datamsg(ldcp, tagp, &headp, &tailp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* build a chain of received packets */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (headp != NULL) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (bp == NULL) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bp = headp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bpt = tailp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } else {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bpt->b_next = headp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bpt = tailp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VIO_TYPE_ERR:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_handle_errmsg(ldcp, tagp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo default:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_ldc_cb: Unknown VIO_TYPE(%x)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_msgtype));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayanvgen_ldccb_error:
3af08d828975d7e2581b6829e0eecff14d87a483lm if (rv == ECONNRESET) {
3af08d828975d7e2581b6829e0eecff14d87a483lm if (ldc_status(ldcp->ldc_handle, &istatus) != 0) {
3af08d828975d7e2581b6829e0eecff14d87a483lm DWARN((vnetp,
3af08d828975d7e2581b6829e0eecff14d87a483lm "vgen_ldc_cb: ldc_status err id(%lx)\n"));
3af08d828975d7e2581b6829e0eecff14d87a483lm } else {
3af08d828975d7e2581b6829e0eecff14d87a483lm ldcp->ldc_status = istatus;
3af08d828975d7e2581b6829e0eecff14d87a483lm }
3af08d828975d7e2581b6829e0eecff14d87a483lm vgen_handle_evt_reset(ldcp, B_FALSE);
3af08d828975d7e2581b6829e0eecff14d87a483lm break;
3af08d828975d7e2581b6829e0eecff14d87a483lm } else if (rv) {
3af08d828975d7e2581b6829e0eecff14d87a483lm vgen_handshake_retry(ldcp);
3af08d828975d7e2581b6829e0eecff14d87a483lm break;
3af08d828975d7e2581b6829e0eecff14d87a483lm }
3af08d828975d7e2581b6829e0eecff14d87a483lm
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } while (msglen);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&ldcp->cblock);
3af08d828975d7e2581b6829e0eecff14d87a483lm
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* send up the received packets to MAC layer */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo while (bp != NULL) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mp = bp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bp = bp->b_next;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mp->b_next = mp->b_prev = NULL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG2((vnetp, "vgen_ldc_cb: id(%lx) rx pkt len (%lx)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id, MBLKL(mp)));
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb vnet_rx(vgenp->vnetp, NULL, mp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayanvgen_ldccb_exit:
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan if (ldcp->cancel_htid) {
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan /*
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan * Cancel handshake timer.
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan * untimeout(9F) will not return until the pending callback is
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan * cancelled or has run. No problems will result from calling
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan * untimeout if the handler has already completed.
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan * If the timeout handler did run, then it would just
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan * return as cancel_htid is set.
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan */
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan (void) untimeout(ldcp->cancel_htid);
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan ldcp->cancel_htid = 0;
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vnetp, "vgen_ldc_cb exit: ldcid (%lx)\n", ldcp->ldc_id));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (LDC_SUCCESS);
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 * Check whether the given version is supported or not and
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * return VGEN_SUCCESS if supported.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_supported_version(vgen_ldc_t *ldcp, uint16_t ver_major,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppouint16_t ver_minor)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_ver_t *versions = ldcp->vgen_versions;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int i = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo while (i < VGEN_NUM_VER) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((versions[i].ver_major == 0) &&
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (versions[i].ver_minor == 0)) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((versions[i].ver_major == ver_major) &&
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (versions[i].ver_minor == ver_minor)) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo i++;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Given a version, return VGEN_SUCCESS if a lower version is supported.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_next_version(vgen_ldc_t *ldcp, vgen_ver_t *verp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_ver_t *versions = ldcp->vgen_versions;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int i = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo while (i < VGEN_NUM_VER) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((versions[i].ver_major == 0) &&
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (versions[i].ver_minor == 0)) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * if we support a lower minor version within the same major
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * version, or if we support a lower major version,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * update the verp parameter with this lower version and
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * return success.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (((versions[i].ver_major == verp->ver_major) &&
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (versions[i].ver_minor < verp->ver_minor)) ||
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (versions[i].ver_major < verp->ver_major)) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo verp->ver_major = versions[i].ver_major;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo verp->ver_minor = versions[i].ver_minor;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo i++;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_FAILURE);
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{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int rv;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo size_t len;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo void *vnetp = LDC_TO_VNET(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint32_t retries = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo len = msglen;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((len == 0) || (msg == NULL))
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (!caller_holds_lock) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_enter(&ldcp->txlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
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
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (!caller_holds_lock) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&ldcp->txlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
3af08d828975d7e2581b6829e0eecff14d87a483lm if (rv != 0) {
3af08d828975d7e2581b6829e0eecff14d87a483lm DWARN((vnetp,
3af08d828975d7e2581b6829e0eecff14d87a483lm "vgen_sendmsg: ldc_write failed: id(%lx) rv(%d)\n",
3af08d828975d7e2581b6829e0eecff14d87a483lm ldcp->ldc_id, rv, msglen));
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
3af08d828975d7e2581b6829e0eecff14d87a483lm }
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm if (len != msglen) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_sendmsg: ldc_write failed: id(%lx) rv(%d)"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo " msglen (%d)\n", ldcp->ldc_id, 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{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vio_ver_msg_t vermsg;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vio_msg_tag_t *tagp = &vermsg.tag;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo void *vnetp = LDC_TO_VNET(ldcp);
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) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp, "vgen_send_version_negotiate: vgen_sendmsg failed"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "id (%lx)\n", ldcp->ldc_id));
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->hstate |= VER_INFO_SENT;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG2((vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_send_version_negotiate: VER_INFO_SENT id (%lx) ver(%d,%d)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id, 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{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vnet_attr_msg_t attrmsg;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vio_msg_tag_t *tagp = &attrmsg.tag;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo void *vnetp = LDC_TO_VNET(ldcp);
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;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = vgen_sendmsg(ldcp, (caddr_t)tagp, sizeof (attrmsg), B_FALSE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rv != VGEN_SUCCESS) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp, "vgen_send_attr_info: vgen_sendmsg failed"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "id (%lx)\n", ldcp->ldc_id));
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->hstate |= ATTR_INFO_SENT;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG2((vnetp, "vgen_send_attr_info: ATTR_INFO_SENT id (%lx)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id));
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{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vio_dring_reg_msg_t msg;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vio_msg_tag_t *tagp = &msg.tag;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo void *vnetp = LDC_TO_VNET(ldcp);
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),
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo 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) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp, "vgen_send_dring_reg: vgen_sendmsg failed"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "id (%lx)\n", ldcp->ldc_id));
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->hstate |= DRING_INFO_SENT;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG2((vnetp, "vgen_send_dring_reg: DRING_INFO_SENT id (%lx)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_send_rdx_info(vgen_ldc_t *ldcp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vio_rdx_msg_t rdxmsg;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vio_msg_tag_t *tagp = &rdxmsg.tag;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo void *vnetp = LDC_TO_VNET(ldcp);
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) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp, "vgen_send_rdx_info: vgen_sendmsg failed"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "id (%lx)\n", ldcp->ldc_id));
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->hstate |= RDX_INFO_SENT;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG2((vnetp, "vgen_send_rdx_info: RDX_INFO_SENT id (%lx)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id));
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{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vio_dring_msg_t dringmsg, *msgp = &dringmsg;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vio_msg_tag_t *tagp = &msgp->tag;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo void *vnetp = LDC_TO_VNET(ldcp);
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
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan msgp->seq_num = ldcp->next_txseq;
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) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp, "vgen_send_dring_data: vgen_sendmsg failed"
3af08d828975d7e2581b6829e0eecff14d87a483lm " id (%lx)\n", ldcp->ldc_id));
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan ldcp->next_txseq++;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan ldcp->statsp->dring_data_msgs++;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG2((vnetp, "vgen_send_dring_data: DRING_DATA_SENT id (%lx)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id));
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 void *vnetp;
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 vnetp = LDC_TO_VNET(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) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp, "vgen_send_mcast_info: vgen_sendmsg err"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "id (%lx)\n", ldcp->ldc_id));
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;
3af08d828975d7e2581b6829e0eecff14d87a483lm void *vnetp = LDC_TO_VNET(ldcp);
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,
3af08d828975d7e2581b6829e0eecff14d87a483lm LDC_SHADOW_MAP, LDC_MEM_RW, &ldcp->tx_dcookie, &ncookies);
3af08d828975d7e2581b6829e0eecff14d87a483lm if (rv != 0) {
3af08d828975d7e2581b6829e0eecff14d87a483lm DWARN((vnetp, "vgen_handshake_phase2: id (%lx) "
3af08d828975d7e2581b6829e0eecff14d87a483lm "ldc_mem_dring_bind failed rv(%x)\n",
3af08d828975d7e2581b6829e0eecff14d87a483lm ldcp->ldc_id, 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),
3af08d828975d7e2581b6829e0eecff14d87a483lm 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
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{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_t *vgenp = LDC_TO_VGEN(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo void *vnetp = LDC_TO_VNET(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldc_status_t istatus;
3af08d828975d7e2581b6829e0eecff14d87a483lm int rv;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG2((vnetp, "vgen_reset_hphase: id(0x%lx)\n", ldcp->ldc_id));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* reset hstate and hphase */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->hstate = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->hphase = VH_PHASE0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
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) {
3af08d828975d7e2581b6829e0eecff14d87a483lm DWARN((vnetp,
3af08d828975d7e2581b6829e0eecff14d87a483lm "vgen_reset_hphase: ldc_mem_dring_unbind "
3af08d828975d7e2581b6829e0eecff14d87a483lm "failed id(%lx)\n", ldcp->ldc_id));
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 =
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->vgen_versions[0].ver_major;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->local_hparams.ver_minor =
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->vgen_versions[0].ver_minor;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->local_hparams.dev_class = VDEV_NETWORK;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* set attr_info params */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->local_hparams.mtu = ETHERMAX;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->local_hparams.addr =
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_macaddr_strtoul(vgenp->macaddr);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->local_hparams.addr_type = ADDR_TYPE_MAC;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->local_hparams.xfer_mode = VIO_DRING_MODE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->local_hparams.ack_freq = 0; /* don't need acks */
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 */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ldcp->need_ldc_reset) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_reset_hphase: id (%lx), Doing Channel Reset...\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->need_ldc_reset = B_FALSE;
e1ebb9ec908bc2d0a8810f137ebd6566cc8a8061lm (void) ldc_down(ldcp->ldc_handle);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void) ldc_status(ldcp->ldc_handle, &istatus);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG2((vnetp,
3af08d828975d7e2581b6829e0eecff14d87a483lm "vgen_reset_hphase: id (%lx), Reset Done,ldc_status(%x)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id, 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) {
3af08d828975d7e2581b6829e0eecff14d87a483lm DWARN((vnetp,
3af08d828975d7e2581b6829e0eecff14d87a483lm "vgen_reset_hphase: ldc_up err id(%lx) rv(%d)\n",
3af08d828975d7e2581b6829e0eecff14d87a483lm ldcp->ldc_id, rv));
3af08d828975d7e2581b6829e0eecff14d87a483lm }
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm if (ldc_status(ldcp->ldc_handle, &istatus) != 0) {
3af08d828975d7e2581b6829e0eecff14d87a483lm DWARN((vnetp,
3af08d828975d7e2581b6829e0eecff14d87a483lm "vgen_reset_hphase: ldc_status err id(%lx)\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{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ASSERT(MUTEX_HELD(&ldcp->cblock));
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);
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{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint32_t hphase = ldcp->hphase;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo void *vnetp = LDC_TO_VNET(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_t *vgenp = LDC_TO_VGEN(ldcp);
3af08d828975d7e2581b6829e0eecff14d87a483lm ldc_status_t istatus;
3af08d828975d7e2581b6829e0eecff14d87a483lm 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 */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->htid = timeout(vgen_hwatchdog, (caddr_t)ldcp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo drv_usectohz(vgen_hwd_interval * 1000));
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;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#if 0
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_print_ldcinfo(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#endif
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vnetp, "vgen_handshake: id(0x%lx) Handshake Done\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ldcp->need_mcast_sync) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* need to sync multicast table with vsw */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->need_mcast_sync = B_FALSE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&ldcp->cblock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_enter(&vgenp->lock);
3af08d828975d7e2581b6829e0eecff14d87a483lm rv = vgen_send_mcast_info(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&vgenp->lock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_enter(&ldcp->cblock);
3af08d828975d7e2581b6829e0eecff14d87a483lm if (rv != VGEN_SUCCESS)
3af08d828975d7e2581b6829e0eecff14d87a483lm break;
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) {
3af08d828975d7e2581b6829e0eecff14d87a483lm ldcp->need_resched = B_FALSE;
3af08d828975d7e2581b6829e0eecff14d87a483lm vnet_tx_update(vgenp->vnetp);
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) {
3af08d828975d7e2581b6829e0eecff14d87a483lm DWARN((vnetp,
3af08d828975d7e2581b6829e0eecff14d87a483lm "vgen_handshake: ldc_status err id(%lx)\n"));
3af08d828975d7e2581b6829e0eecff14d87a483lm } else {
3af08d828975d7e2581b6829e0eecff14d87a483lm ldcp->ldc_status = istatus;
3af08d828975d7e2581b6829e0eecff14d87a483lm }
3af08d828975d7e2581b6829e0eecff14d87a483lm vgen_handle_evt_reset(ldcp, B_FALSE);
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{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint32_t hphase = ldcp->hphase;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int status = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo void *vnetp = LDC_TO_VNET(ldcp);
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) ==
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo 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) ==
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ATTR_INFO_EXCHANGED) &&
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ((ldcp->hstate & DRING_INFO_EXCHANGED) ==
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo 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) ==
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo RDX_EXCHANGED);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo default:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (status == 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG2((vnetp, "VNET_HANDSHAKE_DONE: 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
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{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vio_ver_msg_t *vermsg = (vio_ver_msg_t *)tagp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int ack = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int failed = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo void *vnetp = LDC_TO_VNET(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int idx;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_ver_t *versions = ldcp->vgen_versions;
3af08d828975d7e2581b6829e0eecff14d87a483lm int rv = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vnetp, "vgen_handle_version_negotiate: 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) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG2((vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_handle_version_negotiate: id (%lx) Caching"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo " peer_sid(%x)\n", ldcp->ldc_id, 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
3af08d828975d7e2581b6829e0eecff14d87a483lm DWARN((vnetp,
3af08d828975d7e2581b6829e0eecff14d87a483lm "vgen_handle_version_negotiate: Version"
3af08d828975d7e2581b6829e0eecff14d87a483lm " Negotiation Failed id (%lx)\n", ldcp->ldc_id));
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
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG2((vnetp, "vgen_handle_version_negotiate: VER_INFO_RCVD,"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo " id (%lx), ver(%d,%d)\n", ldcp->ldc_id,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo 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 =
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo versions[idx].ver_minor;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->peer_hparams.ver_minor =
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo 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;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG2((vnetp, "vgen_handle_version_negotiate:"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo " VER_ACK_SENT, id (%lx) ver(%d,%d) \n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id, vermsg->ver_major,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vermsg->ver_minor));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (failed) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp, "vgen_handle_version_negotiate:"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo " Version Negotiation Failed id (%lx)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id));
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 ==
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->peer_hparams.ver_major) &&
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (ldcp->local_hparams.ver_minor ==
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->peer_hparams.ver_minor));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
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. */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_handle_version_negotiate:"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo " VER_ACK_RCVD id (%lx) Invalid Phase(%u)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id, 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
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG2((vnetp, "vgen_handle_version_negotiate:"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo " VER_ACK_RCVD, id (%lx) ver(%d,%d) \n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id, 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 ==
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->peer_hparams.ver_major) &&
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (ldcp->local_hparams.ver_minor ==
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->peer_hparams.ver_minor));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
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. */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_handle_version_negotiate:"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo " VER_NACK_RCVD id (%lx) Invalid Phase(%u)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id, ldcp->hphase));
3af08d828975d7e2581b6829e0eecff14d87a483lm return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG2((vnetp, "vgen_handle_version_negotiate:"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo " VER_NACK_RCVD id(%lx) next ver(%d,%d)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id, 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 */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp, "vgen_handle_version_negotiate:"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo " Version Negotiation Failed id (%lx)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id));
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 =
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo versions[idx].ver_major;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->local_hparams.ver_minor =
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo 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 =
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo versions[idx].ver_major;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->local_hparams.ver_minor =
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo 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 */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp, "vgen_handle_version_negotiate:"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo " Version Negotiation Failed id (%lx)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id));
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
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vnetp, "vgen_handle_version_negotiate: 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{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo _NOTE(ARGUNUSED(ldcp))
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#if 0
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint64_t port_macaddr;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo port_macaddr = vgen_macaddr_strtoul((uint8_t *)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo &(ldcp->portp->macaddr));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#endif
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * currently, we support these attr values:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * mtu of ethernet, addr_type of mac, xfer_mode of
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * ldc shared memory, ack_freq of 0 (data is acked if
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * the ack bit is set in the descriptor) and the address should
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * match the address in the port node.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((msg->mtu != ETHERMAX) ||
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (msg->addr_type != ADDR_TYPE_MAC) ||
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (msg->xfer_mode != VIO_DRING_MODE) ||
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (msg->ack_freq > 64)) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#if 0
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (msg->addr != port_macaddr))
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppocmn_err(CE_CONT, "vgen_check_attr_info: msg->addr(%lx), port_macaddr(%lx)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo msg->addr, port_macaddr);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#endif
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
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{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vnet_attr_msg_t *attrmsg = (vnet_attr_msg_t *)tagp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo void *vnetp = LDC_TO_VNET(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int ack = 0;
3af08d828975d7e2581b6829e0eecff14d87a483lm int rv = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vnetp, "vgen_handle_attr_info: enter\n"));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ldcp->hphase != VH_PHASE2) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_handle_attr_info: Rcvd ATTR_INFO id(%lx)"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo " subtype (%d), Invalid Phase(%u)\n", ldcp->ldc_id,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_subtype, ldcp->hphase));
3af08d828975d7e2581b6829e0eecff14d87a483lm return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo switch (tagp->vio_subtype) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VIO_SUBTYPE_INFO:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG2((vnetp, "vgen_handle_attr_info: ATTR_INFO_RCVD id(%lx)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->hstate |= ATTR_INFO_RCVD;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* save peer's values */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->peer_hparams.mtu = attrmsg->mtu;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->peer_hparams.addr = attrmsg->addr;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->peer_hparams.addr_type = attrmsg->addr_type;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->peer_hparams.xfer_mode = attrmsg->xfer_mode;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->peer_hparams.ack_freq = attrmsg->ack_freq;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vgen_check_attr_info(ldcp, attrmsg) == VGEN_FAILURE) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* unsupported attr, send NACK */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_subtype = VIO_SUBTYPE_NACK;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } else {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ack = 1;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_subtype = VIO_SUBTYPE_ACK;
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 (*attrmsg),
3af08d828975d7e2581b6829e0eecff14d87a483lm B_FALSE);
3af08d828975d7e2581b6829e0eecff14d87a483lm if (rv != VGEN_SUCCESS) {
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ack) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->hstate |= ATTR_ACK_SENT;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG2((vnetp, "vgen_handle_attr_info:"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo " ATTR_ACK_SENT id(%lx)\n", ldcp->ldc_id));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } else {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* failed */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp, "vgen_handle_attr_info:"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo " ATTR_NACK_SENT id(%lx)\n", ldcp->ldc_id));
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 |= ATTR_ACK_RCVD;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG2((vnetp, "vgen_handle_attr_info: ATTR_ACK_RCVD id(%lx)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id));
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
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG2((vnetp, "vgen_handle_attr_info: ATTR_NACK_RCVD id(%lx)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id));
3af08d828975d7e2581b6829e0eecff14d87a483lm return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vnetp, "vgen_handle_attr_info: 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 void *vnetp = LDC_TO_VNET(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldc_mem_cookie_t dcookie;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int ack = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int rv = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vnetp, "vgen_handle_dring_reg: enter\n"));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ldcp->hphase < VH_PHASE2) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* dring_info can be rcvd in any of the phases after Phase1 */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_handle_dring_reg: Rcvd DRING_INFO, id (%lx)"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo " Subtype (%d), Invalid Phase(%u)\n", ldcp->ldc_id,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_subtype, ldcp->hphase));
3af08d828975d7e2581b6829e0eecff14d87a483lm return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo switch (tagp->vio_subtype) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VIO_SUBTYPE_INFO:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG2((vnetp, "vgen_handle_dring_reg: DRING_INFO_RCVD id(%lx)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id));
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 =
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo msg->num_descriptors;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->peer_hparams.desc_size =
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo msg->descriptor_size;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->peer_hparams.num_dcookies =
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo msg->ncookies;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* set dring_ident for the peer */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->peer_hparams.dring_ident =
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (uint64_t)ldcp->rxdp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* return the dring_ident in ack msg */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo msg->dring_ident =
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (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;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG2((vnetp, "vgen_handle_dring_reg: DRING_ACK_SENT"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo " id (%lx)\n", ldcp->ldc_id));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } else {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp, "vgen_handle_dring_reg: DRING_NACK_SENT"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo " id (%lx)\n", ldcp->ldc_id));
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
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG2((vnetp, "vgen_handle_dring_reg: DRING_ACK_RCVD"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo " id (%lx)\n", ldcp->ldc_id));
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 =
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo 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
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG2((vnetp, "vgen_handle_dring_reg: DRING_NACK_RCVD"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo " id (%lx)\n", ldcp->ldc_id));
3af08d828975d7e2581b6829e0eecff14d87a483lm return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vnetp, "vgen_handle_dring_reg: 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{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo void *vnetp = LDC_TO_VNET(ldcp);
3af08d828975d7e2581b6829e0eecff14d87a483lm int rv = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vnetp, "vgen_handle_rdx_info: enter\n"));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ldcp->hphase != VH_PHASE3) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_handle_rdx_info: Rcvd RDX_INFO, id (%lx)"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo " Subtype (%d), Invalid Phase(%u)\n", ldcp->ldc_id,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_subtype, ldcp->hphase));
3af08d828975d7e2581b6829e0eecff14d87a483lm return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo switch (tagp->vio_subtype) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VIO_SUBTYPE_INFO:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG2((vnetp, "vgen_handle_rdx_info: RDX_INFO_RCVD id (%lx)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id));
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;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG2((vnetp, "vgen_handle_rdx_info: RDX_ACK_SENT id (%lx)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id));
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
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG2((vnetp, "vgen_handle_rdx_info: RDX_ACK_RCVD id (%lx)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id));
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
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG2((vnetp, "vgen_handle_rdx_info: RDX_NACK_RCVD id (%lx)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id));
3af08d828975d7e2581b6829e0eecff14d87a483lm return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vnetp, "vgen_handle_rdx_info: 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 void *vnetp = LDC_TO_VNET(ldcp);
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
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vnetp, "vgen_handle_mcast_info: 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 */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_handle_mcast_info: rcvd SET_MCAST_INFO id (%lx)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VIO_SUBTYPE_ACK:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* success adding/removing multicast addr */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG2((vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_handle_mcast_info: rcvd SET_MCAST_ACK id (%lx)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VIO_SUBTYPE_NACK:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_handle_mcast_info: rcvd SET_MCAST_NACK id (%lx)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id));
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) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp->mctab[i] =
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp->mctab[vgenp->mccount-1];
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp->mccount--;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vnetp, "vgen_handle_mcast_info: exit\n"));
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm return (VGEN_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
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{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo void *vnetp = LDC_TO_VNET(ldcp);
3af08d828975d7e2581b6829e0eecff14d87a483lm int rv = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vnetp, "vgen_handle_ctrlmsg: 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
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
3af08d828975d7e2581b6829e0eecff14d87a483lm
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vnetp, "vgen_handle_ctrlmsg: exit\n"));
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* handler for data messages received from the peer ldc end-point */
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_handle_datamsg(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mblk_t **headp, mblk_t **tailp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo void *vnetp = LDC_TO_VNET(ldcp);
3af08d828975d7e2581b6829e0eecff14d87a483lm int rv = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vnetp, "vgen_handle_datamsg: enter\n"));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ldcp->hphase != VH_DONE)
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo switch (tagp->vio_subtype_env) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VIO_DRING_DATA:
3af08d828975d7e2581b6829e0eecff14d87a483lm rv = vgen_handle_dring_data(ldcp, tagp, headp, tailp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo default:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vnetp, "vgen_handle_datamsg: exit\n"));
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
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{
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan vio_dring_msg_t *msgp = (vio_dring_msg_t *)tagp;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan void *vnetp = LDC_TO_VNET(ldcp);
3af08d828975d7e2581b6829e0eecff14d87a483lm int rv = 0;
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) {
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan DWARN((vnetp, "vgen_send_dring_ack: id(%lx) vgen_sendmsg "
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan "failed\n", (ldcp)->ldc_id));
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan }
3af08d828975d7e2581b6829e0eecff14d87a483lm return (rv);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan}
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
3af08d828975d7e2581b6829e0eecff14d87a483lmstatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_handle_dring_data(vgen_ldc_t *ldcp, vio_msg_tag_t *tagp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mblk_t **headp, mblk_t **tailp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vio_dring_msg_t *dringmsg;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vnet_public_desc_t *rxdp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vnet_public_desc_t *txdp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vio_dring_entry_hdr_t *hdrp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_stats_t *statsp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo struct ether_header *ehp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mblk_t *mp = NULL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mblk_t *bp = NULL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mblk_t *bpt = NULL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo size_t nbytes;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo size_t nread;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint64_t off = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint32_t start;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan int32_t end;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint32_t datalen;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint32_t ncookies;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan uint32_t ack_start;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan uint32_t ack_end;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint32_t rxi;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint32_t txi;
3af08d828975d7e2581b6829e0eecff14d87a483lm int rv = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo boolean_t rxd_err = B_FALSE;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan boolean_t set_ack_start = B_FALSE;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan vgen_private_desc_t *tbufp;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan uint32_t next_rxi;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan boolean_t ready_txd = B_FALSE;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan uint32_t retries = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#ifdef VGEN_HANDLE_LOST_PKTS
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int n;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#endif
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#ifdef VGEN_REXMIT
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint64_t seqnum;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#endif
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo void *vnetp = LDC_TO_VNET(ldcp);
3af08d828975d7e2581b6829e0eecff14d87a483lm boolean_t ack_needed = B_FALSE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo dringmsg = (vio_dring_msg_t *)tagp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo start = dringmsg->start_idx;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo end = dringmsg->end_idx;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo statsp = ldcp->statsp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vnetp, "vgen_handle_dring_data: enter\n"));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo switch (tagp->vio_subtype) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VIO_SUBTYPE_INFO:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * received a data msg, which contains the start and end
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * indeces of the descriptors within the rx ring holding data,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * the seq_num of data packet corresponding to the start index,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * and the dring_ident.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * We can now read the contents of each of these descriptors
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * and gather data from it.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG2((vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_handle_dring_data: INFO: start(%d), end(%d)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo start, end));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* validate rx start and end indeces */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan if (!(CHECK_RXI(start, ldcp)) || ((end != -1) &&
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan !(CHECK_RXI(end, ldcp)))) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* drop the message if invalid index */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* validate dring_ident */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (dringmsg->dring_ident != ldcp->peer_hparams.dring_ident) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* invalid dring_ident, drop the msg */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#ifdef DEBUG
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (vgen_trigger_rxlost) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* drop this msg to simulate lost pkts for debugging */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_trigger_rxlost = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#endif
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#ifdef VGEN_HANDLE_LOST_PKTS
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* receive start index doesn't match expected index */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ldcp->next_rxi != start) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp, "vgen_handle_dring_data: id(%lx) "
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "next_rxi(%d) != start(%d)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id, ldcp->next_rxi, start));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* calculate the number of pkts lost */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (start >= ldcp->next_rxi) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo n = start - ldcp->next_rxi;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } else {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo n = ldcp->num_rxds - (ldcp->next_rxi - start);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * sequence number of dring data message
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * is less than the next sequence number that
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * is expected:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo *
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * drop the message and the corresponding packets.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ldcp->next_rxseq > dringmsg->seq_num) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp, "vgen_handle_dring_data: id(%lx) "
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "dropping pkts, expected rxseq(0x%lx) "
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "> recvd(0x%lx)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id, ldcp->next_rxseq,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo dringmsg->seq_num));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * duplicate/multiple retransmissions from
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * sender?? drop this msg.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * sequence number of dring data message
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * is greater than the next expected sequence number
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo *
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * send a NACK back to the peer to indicate lost
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * packets.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (dringmsg->seq_num > ldcp->next_rxseq) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo statsp->rx_lost_pkts += n;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_subtype = VIO_SUBTYPE_NACK;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tagp->vio_sid = ldcp->local_sid;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* indicate the range of lost descriptors */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo dringmsg->start_idx = ldcp->next_rxi;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rxi = start;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DECR_RXI(rxi, ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo dringmsg->end_idx = rxi;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* dring ident is left unchanged */
3af08d828975d7e2581b6829e0eecff14d87a483lm rv = vgen_sendmsg(ldcp, (caddr_t)tagp,
3af08d828975d7e2581b6829e0eecff14d87a483lm sizeof (*dringmsg), B_FALSE);
3af08d828975d7e2581b6829e0eecff14d87a483lm if (rv != VGEN_SUCCESS) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_handle_dring_data: id(%lx) "
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_sendmsg failed, "
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "stype: NACK\n", ldcp->ldc_id));
3af08d828975d7e2581b6829e0eecff14d87a483lm goto error_ret;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#ifdef VGEN_REXMIT
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * stop further processing until peer
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * retransmits with the right index.
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * update next_rxseq expected.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan ldcp->next_rxseq += 1;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#else /* VGEN_REXMIT */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * treat this range of descrs/pkts as dropped
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * and set the new expected values for next_rxi
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * and next_rxseq. continue(below) to process
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * from the new start index.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->next_rxi = start;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan ldcp->next_rxseq += 1;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#endif /* VGEN_REXMIT */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } else if (dringmsg->seq_num == ldcp->next_rxseq) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * expected and received seqnums match, but
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * the descriptor indeces don't?
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo *
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * restart handshake with peer.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_handle_dring_data: id(%lx) "
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "next_rxseq(0x%lx) == seq_num(0x%lx)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id, ldcp->next_rxseq,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo dringmsg->seq_num));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } else {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* expected and start dring indeces match */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (dringmsg->seq_num != ldcp->next_rxseq) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* seqnums don't match */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_handle_dring_data: id(%lx) "
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "next_rxseq(0x%lx) != seq_num(0x%lx)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id, ldcp->next_rxseq,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo dringmsg->seq_num));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#endif /* VGEN_HANDLE_LOST_PKTS */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * start processing the descriptors from the specified
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * start index, up to the index a descriptor is not ready
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * to be processed or we process the entire descriptor ring
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * and wrap around upto the start index.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan /* need to set the start index of descriptors to be ack'd */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan set_ack_start = B_TRUE;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan /* index upto which we have ack'd */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan ack_end = start;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan DECR_RXI(ack_end, ldcp);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan next_rxi = rxi = start;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo do {
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
3af08d828975d7e2581b6829e0eecff14d87a483lmvgen_recv_retry: rv = ldc_mem_dring_acquire(ldcp->rx_dhandle, rxi, rxi);
3af08d828975d7e2581b6829e0eecff14d87a483lm if (rv != 0) {
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan DWARN((vnetp, "vgen_handle_dring_data: "
3af08d828975d7e2581b6829e0eecff14d87a483lm "ldc_mem_dring_acquire() failed"
3af08d828975d7e2581b6829e0eecff14d87a483lm " id(%lx) rv(%d)\n", ldcp->ldc_id, rv));
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan statsp->ierrors++;
3af08d828975d7e2581b6829e0eecff14d87a483lm goto error_ret;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rxdp = &(ldcp->rxdp[rxi]);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo hdrp = &rxdp->hdr;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan if (hdrp->dstate != VIO_DESC_READY) {
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan /*
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * descriptor is not ready.
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * retry descriptor acquire, stop processing
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * after max # retries.
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan if (retries == vgen_recv_retries)
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan break;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan retries++;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan drv_usecwait(vgen_recv_delay);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan goto vgen_recv_retry;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan retries = 0;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan if (set_ack_start) {
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan /*
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * initialize the start index of the range
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * of descriptors to be ack'd.
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan ack_start = rxi;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan set_ack_start = B_FALSE;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo datalen = rxdp->nbytes;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ncookies = rxdp->ncookies;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((datalen < ETHERMIN) ||
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (ncookies == 0) ||
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan (ncookies > MAX_COOKIES)) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rxd_err = B_TRUE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } else {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * Try to allocate an mblk from the free pool
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * of recv mblks for the channel.
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * If this fails, use allocb().
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan mp = vio_allocb(ldcp->rmp);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan if (!mp) {
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan /*
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * The data buffer returned by
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * allocb(9F) is 8byte aligned. We
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * allocate extra 8 bytes to ensure
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * size is multiple of 8 bytes for
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * ldc_mem_copy().
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan statsp->rx_vio_allocb_fail++;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan mp = allocb(VNET_IPALIGN + datalen + 8,
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan BPRI_MED);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan nbytes = (VNET_IPALIGN + datalen + 7) & ~7;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if ((rxd_err) || (mp == NULL)) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * rxd_err or allocb() failure,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * drop this packet, get next.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rxd_err) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo statsp->ierrors++;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rxd_err = B_FALSE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } else {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo statsp->rx_allocb_fail++;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
3af08d828975d7e2581b6829e0eecff14d87a483lm ack_needed = hdrp->ack;
3af08d828975d7e2581b6829e0eecff14d87a483lm
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* set descriptor done bit */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo hdrp->dstate = VIO_DESC_DONE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
3af08d828975d7e2581b6829e0eecff14d87a483lm rv = ldc_mem_dring_release(ldcp->rx_dhandle,
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan rxi, rxi);
3af08d828975d7e2581b6829e0eecff14d87a483lm if (rv != 0) {
3af08d828975d7e2581b6829e0eecff14d87a483lm DWARN((vnetp, "vgen_handle_dring_data: "
3af08d828975d7e2581b6829e0eecff14d87a483lm "ldc_mem_dring_release err id(%lx)"
3af08d828975d7e2581b6829e0eecff14d87a483lm " rv(%d)\n", ldcp->ldc_id, rv));
3af08d828975d7e2581b6829e0eecff14d87a483lm goto error_ret;
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,
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan ack_start, ack_end,
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan 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 }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo goto vgen_next_rxi;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo nread = nbytes;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = ldc_mem_copy(ldcp->ldc_handle,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (caddr_t)mp->b_rptr, off, &nread,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rxdp->memcookie, ncookies, LDC_COPY_IN);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
3af08d828975d7e2581b6829e0eecff14d87a483lm /* if ldc_mem_copy() failed */
3af08d828975d7e2581b6829e0eecff14d87a483lm if (rv) {
3af08d828975d7e2581b6829e0eecff14d87a483lm DWARN((vnetp,
3af08d828975d7e2581b6829e0eecff14d87a483lm "vgen_handle_dring_data: ldc_mem_copy err "
3af08d828975d7e2581b6829e0eecff14d87a483lm " id(%lx) rv(%d)\n", ldcp->ldc_id, rv));
3af08d828975d7e2581b6829e0eecff14d87a483lm statsp->ierrors++;
3af08d828975d7e2581b6829e0eecff14d87a483lm freemsg(mp);
3af08d828975d7e2581b6829e0eecff14d87a483lm goto error_ret;
3af08d828975d7e2581b6829e0eecff14d87a483lm }
3af08d828975d7e2581b6829e0eecff14d87a483lm
3af08d828975d7e2581b6829e0eecff14d87a483lm ack_needed = hdrp->ack;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo hdrp->dstate = VIO_DESC_DONE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
3af08d828975d7e2581b6829e0eecff14d87a483lm rv = ldc_mem_dring_release(ldcp->rx_dhandle, rxi, rxi);
3af08d828975d7e2581b6829e0eecff14d87a483lm if (rv != 0) {
3af08d828975d7e2581b6829e0eecff14d87a483lm DWARN((vnetp, "vgen_handle_dring_data: "
3af08d828975d7e2581b6829e0eecff14d87a483lm "ldc_mem_dring_release err id(%lx)"
3af08d828975d7e2581b6829e0eecff14d87a483lm " rv(%d)\n", ldcp->ldc_id, rv));
3af08d828975d7e2581b6829e0eecff14d87a483lm goto error_ret;
3af08d828975d7e2581b6829e0eecff14d87a483lm }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan mp->b_rptr += VNET_IPALIGN;
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,
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan ack_start, ack_end, 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 }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (nread != nbytes) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_handle_dring_data: id(%lx) "
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "ldc_mem_copy nread(%lx), nbytes(%lx)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id, nread, nbytes));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo statsp->ierrors++;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo freemsg(mp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo goto vgen_next_rxi;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* point to the actual end of data */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mp->b_wptr = mp->b_rptr + datalen;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* update stats */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo statsp->ipackets++;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo statsp->rbytes += datalen;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ehp = (struct ether_header *)mp->b_rptr;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (IS_BROADCAST(ehp))
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo statsp->brdcstrcv++;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo else if (IS_MULTICAST(ehp))
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo statsp->multircv++;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* build a chain of received packets */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (bp == NULL) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* first pkt */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bp = mp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bpt = bp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bpt->b_next = NULL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } else {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mp->b_next = NULL;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bpt->b_next = mp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo bpt = mp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayanvgen_next_rxi:
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan /* update end index of range of descrs to be ack'd */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan ack_end = rxi;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan /* update the next index to be processed */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan INCR_RXI(next_rxi, ldcp);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan if (next_rxi == start) {
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan /*
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * processed the entire descriptor ring upto
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * the index at which we started.
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan rxi = next_rxi;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo _NOTE(CONSTCOND)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } while (1);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan /*
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * send an ack message to peer indicating that we have stopped
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * processing descriptors.
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan if (set_ack_start) {
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan /*
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * We have ack'd upto some index and we have not
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * processed any descriptors beyond that index.
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * Use the last ack'd index as both the start and
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * end of range of descrs being ack'd.
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * Note: This results in acking the last index twice
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * and should be harmless.
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan ack_start = ack_end;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
3af08d828975d7e2581b6829e0eecff14d87a483lm rv = vgen_send_dring_ack(ldcp, tagp, ack_start, ack_end,
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan VIO_DP_STOPPED);
3af08d828975d7e2581b6829e0eecff14d87a483lm if (rv != VGEN_SUCCESS) {
3af08d828975d7e2581b6829e0eecff14d87a483lm goto error_ret;
3af08d828975d7e2581b6829e0eecff14d87a483lm }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan /* save new recv index and expected seqnum of next dring msg */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan ldcp->next_rxi = next_rxi;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan ldcp->next_rxseq += 1;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VIO_SUBTYPE_ACK:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * received an ack corresponding to a specific descriptor for
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * which we had set the ACK bit in the descriptor (during
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * transmit). This enables us to reclaim descriptors.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG2((vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_handle_dring_data: ACK: start(%d), end(%d)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo start, end));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* validate start and end indeces in the tx ack msg */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (!(CHECK_TXI(start, ldcp)) || !(CHECK_TXI(end, ldcp))) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* drop the message if invalid index */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* validate dring_ident */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (dringmsg->dring_ident != ldcp->local_hparams.dring_ident) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* invalid dring_ident, drop the msg */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo statsp->dring_data_acks++;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan /* reclaim descriptors that are done */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_reclaim(ldcp);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan if (dringmsg->dring_process_state != VIO_DP_STOPPED) {
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan /*
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * receiver continued processing descriptors after
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * sending us the ack.
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan break;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan statsp->dring_stopped_acks++;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan /* receiver stopped processing descriptors */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan mutex_enter(&ldcp->txlock);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan mutex_enter(&ldcp->tclock);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan /*
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * determine if there are any pending tx descriptors
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * ready to be processed by the receiver(peer) and if so,
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * send a message to the peer to restart receiving.
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan ready_txd = B_FALSE;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan /*
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * using the end index of the descriptor range for which
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * we received the ack, check if the next descriptor is
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * ready.
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan txi = end;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan INCR_TXI(txi, ldcp);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan tbufp = &ldcp->tbufp[txi];
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan txdp = tbufp->descp;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan hdrp = &txdp->hdr;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan if (hdrp->dstate == VIO_DESC_READY) {
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan ready_txd = B_TRUE;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan } else {
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan /*
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * descr next to the end of ack'd descr range is not
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * ready.
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * starting from the current reclaim index, check
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * if any descriptor is ready.
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan txi = ldcp->cur_tbufp - ldcp->tbufp;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan tbufp = &ldcp->tbufp[txi];
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan while (tbufp != ldcp->next_tbufp) {
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan txdp = tbufp->descp;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan hdrp = &txdp->hdr;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan if (hdrp->dstate == VIO_DESC_READY) {
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan break;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan INCR_TXI(txi, ldcp);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan tbufp = &ldcp->tbufp[txi];
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan if (tbufp != ldcp->next_tbufp)
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan ready_txd = B_TRUE;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan if (ready_txd) {
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan /*
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * we have tx descriptor(s) ready to be
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * processed by the receiver.
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * send a message to the peer with the start index
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * of ready descriptors.
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan rv = vgen_send_dring_data(ldcp, txi, -1);
3af08d828975d7e2581b6829e0eecff14d87a483lm if (rv != VGEN_SUCCESS) {
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan ldcp->resched_peer = B_TRUE;
3af08d828975d7e2581b6829e0eecff14d87a483lm mutex_exit(&ldcp->tclock);
3af08d828975d7e2581b6829e0eecff14d87a483lm mutex_exit(&ldcp->txlock);
3af08d828975d7e2581b6829e0eecff14d87a483lm goto error_ret;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan } else {
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan /*
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * no ready tx descriptors. set the flag to send a
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * message to peer when tx descriptors are ready in
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan * transmit routine.
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan */
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan ldcp->resched_peer = B_TRUE;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan }
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan mutex_exit(&ldcp->tclock);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan mutex_exit(&ldcp->txlock);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo case VIO_SUBTYPE_NACK:
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * peer sent a NACK msg to indicate lost packets.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * The start and end correspond to the range of descriptors
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * for which the peer didn't receive a dring data msg and so
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * didn't receive the corresponding data.
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_handle_dring_data: NACK: start(%d), end(%d)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo start, end));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* validate start and end indeces in the tx nack msg */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (!(CHECK_TXI(start, ldcp)) || !(CHECK_TXI(end, ldcp))) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* drop the message if invalid index */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* validate dring_ident */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (dringmsg->dring_ident != ldcp->local_hparams.dring_ident) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* invalid dring_ident, drop the msg */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_enter(&ldcp->txlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_enter(&ldcp->tclock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ldcp->next_tbufp == ldcp->cur_tbufp) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* no busy descriptors, bogus nack ? */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&ldcp->tclock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&ldcp->txlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#ifdef VGEN_REXMIT
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* send a new dring data msg including the lost descrs */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo end = ldcp->next_tbufp - ldcp->tbufp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DECR_TXI(end, ldcp);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan rv = vgen_send_dring_data(ldcp, start, end);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rv != 0) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * vgen_send_dring_data() error: drop all packets
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * in this descr range
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_handle_dring_data: "
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_send_dring_data failed :"
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "id(%lx) rv(%d)\n", ldcp->ldc_id, rv));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (txi = start; txi <= end; ) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tbufp = &(ldcp->tbufp[txi]);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo txdp = tbufp->descp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo hdrp = &txdp->hdr;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo tbufp->flags = VGEN_PRIV_DESC_FREE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo hdrp->dstate = VIO_DESC_FREE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo hdrp->ack = B_FALSE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo statsp->oerrors++;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* update next pointer */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->next_tbufp = &(ldcp->tbufp[start]);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->next_txi = start;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG2((vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_handle_dring_data: rexmit: start(%d) end(%d)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo start, end));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#else /* VGEN_REXMIT */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* we just mark the descrs as done so they can be reclaimed */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (txi = start; txi <= end; ) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo txdp = &(ldcp->txdp[txi]);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo hdrp = &txdp->hdr;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (hdrp->dstate == VIO_DESC_READY)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo hdrp->dstate = VIO_DESC_DONE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo INCR_TXI(txi, ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo#endif /* VGEN_REXMIT */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&ldcp->tclock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&ldcp->txlock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo break;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
3af08d828975d7e2581b6829e0eecff14d87a483lmerror_ret:
3af08d828975d7e2581b6829e0eecff14d87a483lm
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DBG1((vnetp, "vgen_handle_dring_data: exit\n"));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo *headp = bp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo *tailp = bpt;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan
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{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vnet_public_desc_t *txdp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_private_desc_t *tbufp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vio_dring_entry_hdr_t *hdrp;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan vgen_t *vgenp = LDC_TO_VGEN(ldcp);
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;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->cur_tbufp = tbufp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * Check if mac layer should be notified to restart transmissions
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ldcp->need_resched) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->need_resched = B_FALSE;
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb vnet_tx_update(vgenp->vnetp);
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) >
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo drv_usectohz(vnet_ldcwd_txtimeout * 1000)) &&
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (vnet_ldcwd_txtimeout) &&
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (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 void *vnetp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int rv;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp = (vgen_ldc_t *)arg;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan vgenp = LDC_TO_VGEN(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vnetp = LDC_TO_VNET(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo rv = vgen_ldc_txtimeout(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rv == VGEN_SUCCESS) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_ldc_watchdog: transmit timeout ldcid(%lx)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id));
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);
3af08d828975d7e2581b6829e0eecff14d87a483lm ldcp->need_ldc_reset = B_TRUE;
bd8f0338e0109a8df4e34499bdf42e592c77eedanarayan vgen_handshake_retry(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo mutex_exit(&ldcp->cblock);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ldcp->need_resched) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->need_resched = B_FALSE;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan vnet_tx_update(vgenp->vnetp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->wd_tid = timeout(vgen_ldc_watchdog, (caddr_t)ldcp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo drv_usectohz(vnet_ldcwd_interval * 1000));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_setup_kstats(vgen_ldc_t *ldcp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_t *vgenp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo struct kstat *ksp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_stats_t *statsp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_kstats_t *ldckp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int instance;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo size_t size;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo char name[MAXNAMELEN];
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgenp = LDC_TO_VGEN(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo instance = ddi_get_instance(vgenp->vnetdip);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void) sprintf(name, "vnetldc0x%lx", ldcp->ldc_id);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo statsp = kmem_zalloc(sizeof (vgen_stats_t), KM_SLEEP);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (statsp == NULL) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo size = sizeof (vgen_kstats_t) / sizeof (kstat_named_t);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ksp = kstat_create("vnet", instance, name, "net", KSTAT_TYPE_NAMED,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo size, 0);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ksp == NULL) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo KMEM_FREE(statsp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldckp = (vgen_kstats_t *)ksp->ks_data;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kstat_named_init(&ldckp->ipackets, "ipackets",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo KSTAT_DATA_ULONG);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kstat_named_init(&ldckp->ipackets64, "ipackets64",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo KSTAT_DATA_ULONGLONG);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kstat_named_init(&ldckp->ierrors, "ierrors",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo KSTAT_DATA_ULONG);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kstat_named_init(&ldckp->opackets, "opackets",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo KSTAT_DATA_ULONG);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kstat_named_init(&ldckp->opackets64, "opackets64",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo KSTAT_DATA_ULONGLONG);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kstat_named_init(&ldckp->oerrors, "oerrors",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo KSTAT_DATA_ULONG);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* MIB II kstat variables */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kstat_named_init(&ldckp->rbytes, "rbytes",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo KSTAT_DATA_ULONG);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kstat_named_init(&ldckp->rbytes64, "rbytes64",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo KSTAT_DATA_ULONGLONG);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kstat_named_init(&ldckp->obytes, "obytes",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo KSTAT_DATA_ULONG);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kstat_named_init(&ldckp->obytes64, "obytes64",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo KSTAT_DATA_ULONGLONG);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kstat_named_init(&ldckp->multircv, "multircv",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo KSTAT_DATA_ULONG);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kstat_named_init(&ldckp->multixmt, "multixmt",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo KSTAT_DATA_ULONG);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kstat_named_init(&ldckp->brdcstrcv, "brdcstrcv",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo KSTAT_DATA_ULONG);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kstat_named_init(&ldckp->brdcstxmt, "brdcstxmt",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo KSTAT_DATA_ULONG);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kstat_named_init(&ldckp->norcvbuf, "norcvbuf",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo KSTAT_DATA_ULONG);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kstat_named_init(&ldckp->noxmtbuf, "noxmtbuf",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo KSTAT_DATA_ULONG);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* Tx stats */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kstat_named_init(&ldckp->tx_no_desc, "tx_no_desc",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo KSTAT_DATA_ULONG);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* Rx stats */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kstat_named_init(&ldckp->rx_allocb_fail, "rx_allocb_fail",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo KSTAT_DATA_ULONG);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan kstat_named_init(&ldckp->rx_vio_allocb_fail, "rx_vio_allocb_fail",
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan KSTAT_DATA_ULONG);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kstat_named_init(&ldckp->rx_lost_pkts, "rx_lost_pkts",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo KSTAT_DATA_ULONG);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /* Interrupt stats */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kstat_named_init(&ldckp->callbacks, "callbacks",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo KSTAT_DATA_ULONG);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kstat_named_init(&ldckp->dring_data_acks, "dring_data_acks",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo KSTAT_DATA_ULONG);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan kstat_named_init(&ldckp->dring_stopped_acks, "dring_stopped_acks",
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan KSTAT_DATA_ULONG);
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan kstat_named_init(&ldckp->dring_data_msgs, "dring_data_msgs",
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan KSTAT_DATA_ULONG);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ksp->ks_update = vgen_kstat_update;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ksp->ks_private = (void *)ldcp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kstat_install(ksp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ksp = ksp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->statsp = statsp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic void
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_destroy_kstats(vgen_ldc_t *ldcp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (ldcp->ksp)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo kstat_delete(ldcp->ksp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo KMEM_FREE(ldcp->statsp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_kstat_update(kstat_t *ksp, int rw)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_ldc_t *ldcp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_stats_t *statsp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_kstats_t *ldckp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp = (vgen_ldc_t *)ksp->ks_private;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo statsp = ldcp->statsp;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldckp = (vgen_kstats_t *)ksp->ks_data;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (rw == KSTAT_READ) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldckp->ipackets.value.ul = (uint32_t)statsp->ipackets;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldckp->ipackets64.value.ull = statsp->ipackets;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldckp->ierrors.value.ul = statsp->ierrors;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldckp->opackets.value.ul = (uint32_t)statsp->opackets;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldckp->opackets64.value.ull = statsp->opackets;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldckp->oerrors.value.ul = statsp->oerrors;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * MIB II kstat variables
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldckp->rbytes.value.ul = (uint32_t)statsp->rbytes;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldckp->rbytes64.value.ull = statsp->rbytes;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldckp->obytes.value.ul = (uint32_t)statsp->obytes;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldckp->obytes64.value.ull = statsp->obytes;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldckp->multircv.value.ul = statsp->multircv;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldckp->multixmt.value.ul = statsp->multixmt;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldckp->brdcstrcv.value.ul = statsp->brdcstrcv;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldckp->brdcstxmt.value.ul = statsp->brdcstxmt;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldckp->norcvbuf.value.ul = statsp->norcvbuf;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldckp->noxmtbuf.value.ul = statsp->noxmtbuf;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldckp->tx_no_desc.value.ul = statsp->tx_no_desc;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldckp->rx_allocb_fail.value.ul = statsp->rx_allocb_fail;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan ldckp->rx_vio_allocb_fail.value.ul = statsp->rx_vio_allocb_fail;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldckp->rx_lost_pkts.value.ul = statsp->rx_lost_pkts;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldckp->callbacks.value.ul = statsp->callbacks;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldckp->dring_data_acks.value.ul = statsp->dring_data_acks;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan ldckp->dring_stopped_acks.value.ul = statsp->dring_stopped_acks;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan ldckp->dring_data_msgs.value.ul = statsp->dring_data_msgs;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo } else {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo statsp->ipackets = ldckp->ipackets64.value.ull;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo statsp->ierrors = ldckp->ierrors.value.ul;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo statsp->opackets = ldckp->opackets64.value.ull;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo statsp->oerrors = ldckp->oerrors.value.ul;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo /*
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo * MIB II kstat variables
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo statsp->rbytes = ldckp->rbytes64.value.ull;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo statsp->obytes = ldckp->obytes64.value.ull;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo statsp->multircv = ldckp->multircv.value.ul;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo statsp->multixmt = ldckp->multixmt.value.ul;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo statsp->brdcstrcv = ldckp->brdcstrcv.value.ul;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo statsp->brdcstxmt = ldckp->brdcstxmt.value.ul;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo statsp->norcvbuf = ldckp->norcvbuf.value.ul;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo statsp->noxmtbuf = ldckp->noxmtbuf.value.ul;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo statsp->tx_no_desc = ldckp->tx_no_desc.value.ul;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo statsp->rx_allocb_fail = ldckp->rx_allocb_fail.value.ul;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan statsp->rx_vio_allocb_fail = ldckp->rx_vio_allocb_fail.value.ul;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo statsp->rx_lost_pkts = ldckp->rx_lost_pkts.value.ul;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo statsp->callbacks = ldckp->callbacks.value.ul;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo statsp->dring_data_acks = ldckp->dring_data_acks.value.ul;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan statsp->dring_stopped_acks = ldckp->dring_stopped_acks.value.ul;
d10e4ef2fabf16c3237c6d6592496df3eac6a1efnarayan statsp->dring_data_msgs = ldckp->dring_data_msgs.value.ul;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_SUCCESS);
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
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{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo if (tagp->vio_sid != ldcp->peer_sid) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo void *vnetp = LDC_TO_VNET(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "sid mismatch: expected(%x), rcvd(%x)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->peer_sid, tagp->vio_sid));
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_FAILURE);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo else
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* convert mac address from string to uint64_t */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic uint64_t
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_macaddr_strtoul(const uint8_t *macaddr)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint64_t val = 0;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int i;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (i = 0; i < ETHERADDRL; i++) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo val <<= 8;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo val |= macaddr[i];
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (val);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo/* convert mac address from uint64_t to string */
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic int
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_macaddr_ultostr(uint64_t val, uint8_t *macaddr)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo int i;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo uint64_t value;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo value = val;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo for (i = ETHERADDRL - 1; i >= 0; i--) {
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo macaddr[i] = value & 0xFF;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo value >>= 8;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo }
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo return (VGEN_SUCCESS);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo}
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppostatic caddr_t
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppovgen_print_ethaddr(uint8_t *a, char *ebuf)
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo{
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void) sprintf(ebuf,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "%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;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo void *vnetp = LDC_TO_VNET(ldcp);
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo DWARN((vnetp,
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo "vgen_hwatchdog: handshake timeout ldc(%lx) phase(%x) state(%x)\n",
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo ldcp->ldc_id, 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;
a8ea4ede2107d9ad3895b91946b9f33a83c5f7eenarayan ldcp->need_ldc_reset = B_TRUE;
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo vgen_handshake_retry(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
1ae0874509b6811fdde1dfd46f0d93fd09867a3fheppo (void) vgen_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}