vsw_phys.c revision d62bc4badc1c1f1549c961cfb8b420e650e1272b
06db247c678f0e3956535e8a6dec31d6c2108827raghuram/*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * CDDL HEADER START
06db247c678f0e3956535e8a6dec31d6c2108827raghuram *
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * The contents of this file are subject to the terms of the
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Common Development and Distribution License (the "License").
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * You may not use this file except in compliance with the License.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram *
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * or http://www.opensolaris.org/os/licensing.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * See the License for the specific language governing permissions
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * and limitations under the License.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram *
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * When distributing Covered Code, include this CDDL HEADER in each
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * If applicable, add the following below this CDDL HEADER, with the
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * fields enclosed by brackets "[]" replaced with your own identifying
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * information: Portions Copyright [yyyy] [name of copyright owner]
06db247c678f0e3956535e8a6dec31d6c2108827raghuram *
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * CDDL HEADER END
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram/*
ee03c681cedb48165922333190cdd8b230ffa073wentaoy * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Use is subject to license terms.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#pragma ident "%Z%%M% %I% %E% SMI"
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#include <sys/types.h>
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#include <sys/errno.h>
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#include <sys/debug.h>
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#include <sys/time.h>
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#include <sys/sysmacros.h>
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#include <sys/systm.h>
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#include <sys/user.h>
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#include <sys/stropts.h>
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#include <sys/stream.h>
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#include <sys/strlog.h>
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#include <sys/strsubr.h>
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#include <sys/cmn_err.h>
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#include <sys/cpu.h>
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#include <sys/kmem.h>
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#include <sys/conf.h>
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#include <sys/ddi.h>
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#include <sys/sunddi.h>
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#include <sys/ksynch.h>
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#include <sys/stat.h>
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#include <sys/kstat.h>
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#include <sys/vtrace.h>
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#include <sys/strsun.h>
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#include <sys/dlpi.h>
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#include <sys/ethernet.h>
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#include <net/if.h>
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#include <sys/varargs.h>
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#include <sys/machsystm.h>
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#include <sys/modctl.h>
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#include <sys/modhash.h>
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#include <sys/mac.h>
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#include <sys/mac_ether.h>
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#include <sys/taskq.h>
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#include <sys/note.h>
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#include <sys/mach_descrip.h>
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#include <sys/mac.h>
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#include <sys/mdeg.h>
06db247c678f0e3956535e8a6dec31d6c2108827raghuram#include <sys/vsw.h>
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram/* MAC Ring table functions. */
06db247c678f0e3956535e8a6dec31d6c2108827raghuramstatic void vsw_mac_ring_tbl_init(vsw_t *vswp);
06db247c678f0e3956535e8a6dec31d6c2108827raghuramstatic void vsw_mac_ring_tbl_destroy(vsw_t *vswp);
06db247c678f0e3956535e8a6dec31d6c2108827raghuramstatic void vsw_queue_worker(vsw_mac_ring_t *rrp);
06db247c678f0e3956535e8a6dec31d6c2108827raghuramstatic void vsw_queue_stop(vsw_queue_t *vqp);
06db247c678f0e3956535e8a6dec31d6c2108827raghuramstatic vsw_queue_t *vsw_queue_create();
06db247c678f0e3956535e8a6dec31d6c2108827raghuramstatic void vsw_queue_destroy(vsw_queue_t *vqp);
06db247c678f0e3956535e8a6dec31d6c2108827raghuramstatic void vsw_rx_queue_cb(void *, mac_resource_handle_t, mblk_t *);
06db247c678f0e3956535e8a6dec31d6c2108827raghuramstatic void vsw_rx_cb(void *, mac_resource_handle_t, mblk_t *);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram/* MAC layer routines */
06db247c678f0e3956535e8a6dec31d6c2108827raghuramstatic mac_resource_handle_t vsw_mac_ring_add_cb(void *arg,
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mac_resource_t *mrp);
06db247c678f0e3956535e8a6dec31d6c2108827raghuramstatic int vsw_set_hw_addr(vsw_t *, mac_multi_addr_t *);
06db247c678f0e3956535e8a6dec31d6c2108827raghuramstatic int vsw_set_hw_promisc(vsw_t *, vsw_port_t *, int);
06db247c678f0e3956535e8a6dec31d6c2108827raghuramstatic int vsw_unset_hw_addr(vsw_t *, int);
06db247c678f0e3956535e8a6dec31d6c2108827raghuramstatic int vsw_unset_hw_promisc(vsw_t *, vsw_port_t *, int);
06db247c678f0e3956535e8a6dec31d6c2108827raghuramstatic int vsw_prog_if(vsw_t *);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram/* Support functions */
06db247c678f0e3956535e8a6dec31d6c2108827raghuramstatic int vsw_prog_ports(vsw_t *);
06db247c678f0e3956535e8a6dec31d6c2108827raghuramint vsw_set_hw(vsw_t *, vsw_port_t *, int);
06db247c678f0e3956535e8a6dec31d6c2108827raghuramint vsw_unset_hw(vsw_t *, vsw_port_t *, int);
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvoid vsw_reconfig_hw(vsw_t *);
06db247c678f0e3956535e8a6dec31d6c2108827raghuramint vsw_mac_attach(vsw_t *vswp);
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvoid vsw_mac_detach(vsw_t *vswp);
06db247c678f0e3956535e8a6dec31d6c2108827raghuramint vsw_mac_open(vsw_t *vswp);
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvoid vsw_mac_close(vsw_t *vswp);
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvoid vsw_unset_addrs(vsw_t *vswp);
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvoid vsw_set_addrs(vsw_t *vswp);
06db247c678f0e3956535e8a6dec31d6c2108827raghuramint vsw_get_hw_maddr(vsw_t *);
06db247c678f0e3956535e8a6dec31d6c2108827raghurammblk_t *vsw_tx_msg(vsw_t *, mblk_t *);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram/*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Tunables used in this file.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuramextern int vsw_mac_open_retries;
06db247c678f0e3956535e8a6dec31d6c2108827raghuramextern boolean_t vsw_multi_ring_enable;
06db247c678f0e3956535e8a6dec31d6c2108827raghuramextern int vsw_mac_rx_rings;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram/*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Check to see if the card supports the setting of multiple unicst
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * addresses.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram *
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Returns 0 if card supports the programming of multiple unicast addresses,
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * otherwise returns 1.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuramint
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvsw_get_hw_maddr(vsw_t *vswp)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram{
06db247c678f0e3956535e8a6dec31d6c2108827raghuram D1(vswp, "%s: enter", __func__);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT(MUTEX_HELD(&vswp->mac_lock));
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vswp->mh == NULL)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (1);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (!mac_capab_get(vswp->mh, MAC_CAPAB_MULTIADDRESS, &vswp->maddr)) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram cmn_err(CE_WARN, "!vsw%d: device (%s) does not support "
06db247c678f0e3956535e8a6dec31d6c2108827raghuram "setting multiple unicast addresses", vswp->instance,
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vswp->physname);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (1);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram D2(vswp, "%s: %d addrs : %d free", __func__,
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vswp->maddr.maddr_naddr, vswp->maddr.maddr_naddrfree);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram D1(vswp, "%s: exit", __func__);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (0);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram}
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram/*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Program unicast and multicast addresses of vsw interface and the ports
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * into the physical device.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvoid
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvsw_set_addrs(vsw_t *vswp)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram{
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vsw_port_list_t *plist = &vswp->plist;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vsw_port_t *port;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mcst_addr_t *mcap;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram int rv;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram READ_ENTER(&vswp->if_lockrw);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vswp->if_state & VSW_IF_UP) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /* program unicst addr of vsw interface in the physdev */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vswp->addr_set == VSW_ADDR_UNSET) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_enter(&vswp->hw_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram rv = vsw_set_hw(vswp, NULL, VSW_LOCALDEV);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_exit(&vswp->hw_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (rv != 0) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram cmn_err(CE_NOTE,
06db247c678f0e3956535e8a6dec31d6c2108827raghuram "!vsw%d: failed to program interface "
06db247c678f0e3956535e8a6dec31d6c2108827raghuram "unicast address\n", vswp->instance);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Notify the MAC layer of the changed address.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mac_unicst_update(vswp->if_mh,
06db247c678f0e3956535e8a6dec31d6c2108827raghuram (uint8_t *)&vswp->if_addr);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /* program mcast addrs of vsw interface in the physdev */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_enter(&vswp->mca_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_enter(&vswp->mac_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram for (mcap = vswp->mcap; mcap != NULL; mcap = mcap->nextp) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (mcap->mac_added)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram continue;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram rv = mac_multicst_add(vswp->mh, (uchar_t *)&mcap->mca);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (rv == 0) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mcap->mac_added = B_TRUE;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram } else {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram cmn_err(CE_WARN, "!vsw%d: unable to add "
06db247c678f0e3956535e8a6dec31d6c2108827raghuram "multicast address: %s\n", vswp->instance,
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ether_sprintf((void *)&mcap->mca));
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_exit(&vswp->mac_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_exit(&vswp->mca_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram RW_EXIT(&vswp->if_lockrw);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram WRITE_ENTER(&plist->lockrw);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /* program unicast address of ports in the physical device */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_enter(&vswp->hw_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram for (port = plist->head; port != NULL; port = port->p_next) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (port->addr_set != VSW_ADDR_UNSET) /* addr already set */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram continue;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vsw_set_hw(vswp, port, VSW_VNETPORT)) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram cmn_err(CE_NOTE,
06db247c678f0e3956535e8a6dec31d6c2108827raghuram "!vsw%d: port:%d failed to set unicast address\n",
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vswp->instance, port->p_instance);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_exit(&vswp->hw_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /* program multicast addresses of ports in the physdev */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram for (port = plist->head; port != NULL; port = port->p_next) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_enter(&port->mca_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_enter(&vswp->mac_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram for (mcap = port->mcap; mcap != NULL; mcap = mcap->nextp) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (mcap->mac_added)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram continue;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram rv = mac_multicst_add(vswp->mh, (uchar_t *)&mcap->mca);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (rv == 0) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mcap->mac_added = B_TRUE;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram } else {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram cmn_err(CE_WARN, "!vsw%d: unable to add "
06db247c678f0e3956535e8a6dec31d6c2108827raghuram "multicast address: %s\n", vswp->instance,
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ether_sprintf((void *)&mcap->mca));
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_exit(&vswp->mac_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_exit(&port->mca_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram RW_EXIT(&plist->lockrw);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram}
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram/*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Remove unicast and multicast addresses of vsw interface and the ports
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * from the physical device.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvoid
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvsw_unset_addrs(vsw_t *vswp)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram{
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vsw_port_list_t *plist = &vswp->plist;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vsw_port_t *port;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mcst_addr_t *mcap;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram READ_ENTER(&vswp->if_lockrw);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vswp->if_state & VSW_IF_UP) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Remove unicast addr of vsw interfce
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * from current physdev
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_enter(&vswp->hw_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram (void) vsw_unset_hw(vswp, NULL, VSW_LOCALDEV);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_exit(&vswp->hw_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Remove mcast addrs of vsw interface
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * from current physdev
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_enter(&vswp->mca_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_enter(&vswp->mac_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram for (mcap = vswp->mcap; mcap != NULL; mcap = mcap->nextp) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (!mcap->mac_added)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram continue;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram (void) mac_multicst_remove(vswp->mh,
06db247c678f0e3956535e8a6dec31d6c2108827raghuram (uchar_t *)&mcap->mca);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mcap->mac_added = B_FALSE;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_exit(&vswp->mac_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_exit(&vswp->mca_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram RW_EXIT(&vswp->if_lockrw);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram WRITE_ENTER(&plist->lockrw);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Remove unicast address of ports from the current physical device
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_enter(&vswp->hw_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram for (port = plist->head; port != NULL; port = port->p_next) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /* Remove address if was programmed into HW. */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (port->addr_set == VSW_ADDR_UNSET)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram continue;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram (void) vsw_unset_hw(vswp, port, VSW_VNETPORT);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_exit(&vswp->hw_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /* Remove multicast addresses of ports from the current physdev */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram for (port = plist->head; port != NULL; port = port->p_next) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_enter(&port->mca_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_enter(&vswp->mac_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram for (mcap = port->mcap; mcap != NULL; mcap = mcap->nextp) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (!mcap->mac_added)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram continue;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram (void) mac_multicst_remove(vswp->mh,
06db247c678f0e3956535e8a6dec31d6c2108827raghuram (uchar_t *)&mcap->mca);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mcap->mac_added = B_FALSE;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_exit(&vswp->mac_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_exit(&port->mca_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram RW_EXIT(&plist->lockrw);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram}
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram/*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Open the underlying physical device for access in layer2 mode.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Returns:
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * 0 on success
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * EAGAIN if mac_open() fails due to the device being not available yet.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * EIO on any other failures.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuramint
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvsw_mac_open(vsw_t *vswp)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram{
06db247c678f0e3956535e8a6dec31d6c2108827raghuram int rv;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT(MUTEX_HELD(&vswp->mac_lock));
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vswp->mh != NULL) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /* already open */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (0);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vswp->mac_open_retries++ >= vsw_mac_open_retries) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /* exceeded max retries */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (EIO);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if ((rv = mac_open_by_linkname(vswp->physname, &vswp->mh)) != 0) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * If mac_open() failed and the error indicates that either
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * the dlmgmtd door or the device is not available yet, we
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * return EAGAIN to indicate that mac_open() needs to be
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * retried. For example, this may happen during boot up, if
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * the required link aggregation groups(devices) have not
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * been created yet.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (rv == ENOENT || rv == EBADF) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (EAGAIN);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram } else {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram cmn_err(CE_WARN, "vsw%d: mac_open %s failed rv:%x",
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vswp->instance, vswp->physname, rv);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (EIO);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vswp->mac_open_retries = 0;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (0);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram}
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram/*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Close the underlying physical device.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvoid
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvsw_mac_close(vsw_t *vswp)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram{
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT(MUTEX_HELD(&vswp->mac_lock));
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vswp->mh != NULL) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mac_close(vswp->mh);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vswp->mh = NULL;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram}
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram/*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Link into the MAC layer to gain access to the services provided by
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * the underlying physical device driver (which should also have
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * registered with the MAC layer).
06db247c678f0e3956535e8a6dec31d6c2108827raghuram *
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Only when in layer 2 mode.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuramint
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvsw_mac_attach(vsw_t *vswp)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram{
06db247c678f0e3956535e8a6dec31d6c2108827raghuram D1(vswp, "%s: enter", __func__);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT(vswp->mrh == NULL);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT(vswp->mstarted == B_FALSE);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT(vswp->mresources == B_FALSE);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT(MUTEX_HELD(&vswp->mac_lock));
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT(vswp->mh != NULL);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram D2(vswp, "vsw_mac_attach: using device %s", vswp->physname);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vsw_multi_ring_enable) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Initialize the ring table.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vsw_mac_ring_tbl_init(vswp);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Register our rx callback function.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vswp->mrh = mac_rx_add(vswp->mh,
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vsw_rx_queue_cb, (void *)vswp);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT(vswp->mrh != NULL);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Register our mac resource callback.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mac_resource_set(vswp->mh, vsw_mac_ring_add_cb, (void *)vswp);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vswp->mresources = B_TRUE;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Get the ring resources available to us from
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * the mac below us.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mac_resources(vswp->mh);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram } else {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Just register our rx callback function
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vswp->mrh = mac_rx_add(vswp->mh, vsw_rx_cb, (void *)vswp);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT(vswp->mrh != NULL);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /* Get the MAC tx fn */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vswp->txinfo = mac_tx_get(vswp->mh);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /* start the interface */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (mac_start(vswp->mh) != 0) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram cmn_err(CE_WARN, "!vsw%d: Could not start mac interface",
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vswp->instance);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram goto mac_fail_exit;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vswp->mstarted = B_TRUE;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram D1(vswp, "%s: exit", __func__);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (0);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghurammac_fail_exit:
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vsw_mac_detach(vswp);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram D1(vswp, "%s: exit", __func__);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (1);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram}
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvoid
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvsw_mac_detach(vsw_t *vswp)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram{
06db247c678f0e3956535e8a6dec31d6c2108827raghuram D1(vswp, "vsw_mac_detach: enter");
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT(vswp != NULL);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT(MUTEX_HELD(&vswp->mac_lock));
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vsw_multi_ring_enable) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vsw_mac_ring_tbl_destroy(vswp);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vswp->mh != NULL) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vswp->mstarted)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mac_stop(vswp->mh);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vswp->mrh != NULL)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mac_rx_remove(vswp->mh, vswp->mrh, B_TRUE);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vswp->mresources)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mac_resource_set(vswp->mh, NULL, NULL);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vswp->mrh = NULL;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vswp->txinfo = NULL;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vswp->mstarted = B_FALSE;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram D1(vswp, "vsw_mac_detach: exit");
06db247c678f0e3956535e8a6dec31d6c2108827raghuram}
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram/*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Depending on the mode specified, the capabilites and capacity
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * of the underlying device setup the physical device.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram *
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * If in layer 3 mode, then do nothing.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram *
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * If in layer 2 programmed mode attempt to program the unicast address
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * associated with the port into the physical device. If this is not
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * possible due to resource exhaustion or simply because the device does
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * not support multiple unicast addresses then if required fallback onto
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * putting the card into promisc mode.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram *
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * If in promisc mode then simply set the card into promisc mode.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram *
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Returns 0 success, 1 on failure.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuramint
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvsw_set_hw(vsw_t *vswp, vsw_port_t *port, int type)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram{
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mac_multi_addr_t mac_addr;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram int err;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram D1(vswp, "%s: enter", __func__);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT(MUTEX_HELD(&vswp->hw_lock));
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT((type == VSW_LOCALDEV) || (type == VSW_VNETPORT));
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vswp->smode[vswp->smode_idx] == VSW_LAYER3)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (0);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vswp->smode[vswp->smode_idx] == VSW_LAYER2_PROMISC) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (vsw_set_hw_promisc(vswp, port, type));
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Attempt to program the unicast address into the HW.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mac_addr.mma_addrlen = ETHERADDRL;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (type == VSW_VNETPORT) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT(port != NULL);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ether_copy(&port->p_macaddr, &mac_addr.mma_addr);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram } else {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ether_copy(&vswp->if_addr, &mac_addr.mma_addr);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram err = vsw_set_hw_addr(vswp, &mac_addr);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (err == ENOSPC) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Mark that attempt should be made to re-config sometime
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * in future if a port is deleted.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vswp->recfg_reqd = B_TRUE;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Only 1 mode specified, nothing more to do.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vswp->smode_num == 1)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (err);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * If promiscuous was next mode specified try to
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * set the card into that mode.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if ((vswp->smode_idx <= (vswp->smode_num - 2)) &&
06db247c678f0e3956535e8a6dec31d6c2108827raghuram (vswp->smode[vswp->smode_idx + 1] ==
06db247c678f0e3956535e8a6dec31d6c2108827raghuram VSW_LAYER2_PROMISC)) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vswp->smode_idx += 1;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (vsw_set_hw_promisc(vswp, port, type));
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (err);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (err != 0)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (err);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (type == VSW_VNETPORT) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram port->addr_slot = mac_addr.mma_slot;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram port->addr_set = VSW_ADDR_HW;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram } else {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vswp->addr_slot = mac_addr.mma_slot;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vswp->addr_set = VSW_ADDR_HW;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram D2(vswp, "programmed addr %s into slot %d "
06db247c678f0e3956535e8a6dec31d6c2108827raghuram "of device %s", ether_sprintf((void *)mac_addr.mma_addr),
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mac_addr.mma_slot, vswp->physname);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram D1(vswp, "%s: exit", __func__);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (0);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram}
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram/*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * If in layer 3 mode do nothing.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram *
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * If in layer 2 switched mode remove the address from the physical
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * device.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram *
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * If in layer 2 promiscuous mode disable promisc mode.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram *
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Returns 0 on success.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuramint
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvsw_unset_hw(vsw_t *vswp, vsw_port_t *port, int type)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram{
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mac_addr_slot_t slot;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram int rv;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram D1(vswp, "%s: enter", __func__);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT(MUTEX_HELD(&vswp->hw_lock));
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vswp->smode[vswp->smode_idx] == VSW_LAYER3)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (0);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram switch (type) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram case VSW_VNETPORT:
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT(port != NULL);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (port->addr_set == VSW_ADDR_PROMISC) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (vsw_unset_hw_promisc(vswp, port, type));
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram } else if (port->addr_set == VSW_ADDR_HW) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram slot = port->addr_slot;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if ((rv = vsw_unset_hw_addr(vswp, slot)) == 0)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram port->addr_set = VSW_ADDR_UNSET;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram break;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram case VSW_LOCALDEV:
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vswp->addr_set == VSW_ADDR_PROMISC) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (vsw_unset_hw_promisc(vswp, NULL, type));
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram } else if (vswp->addr_set == VSW_ADDR_HW) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram slot = vswp->addr_slot;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if ((rv = vsw_unset_hw_addr(vswp, slot)) == 0)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vswp->addr_set = VSW_ADDR_UNSET;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram break;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram default:
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /* should never happen */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram DERR(vswp, "%s: unknown type %d", __func__, type);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT(0);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (1);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram D1(vswp, "%s: exit", __func__);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (rv);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram}
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram/*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Attempt to program a unicast address into HW.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram *
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Returns 0 on sucess, 1 on failure.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuramstatic int
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvsw_set_hw_addr(vsw_t *vswp, mac_multi_addr_t *mac)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram{
06db247c678f0e3956535e8a6dec31d6c2108827raghuram void *mah;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram int rv = EINVAL;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram D1(vswp, "%s: enter", __func__);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT(MUTEX_HELD(&vswp->hw_lock));
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vswp->maddr.maddr_handle == NULL)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (rv);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mah = vswp->maddr.maddr_handle;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram rv = vswp->maddr.maddr_add(mah, mac);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (rv == 0)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (rv);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Its okay for the add to fail because we have exhausted
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * all the resouces in the hardware device. Any other error
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * we want to flag.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (rv != ENOSPC) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram cmn_err(CE_WARN, "!vsw%d: error programming "
06db247c678f0e3956535e8a6dec31d6c2108827raghuram "address %s into HW err (%d)",
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vswp->instance, ether_sprintf((void *)mac->mma_addr), rv);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram D1(vswp, "%s: exit", __func__);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (rv);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram}
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram/*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Remove a unicast mac address which has previously been programmed
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * into HW.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram *
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Returns 0 on sucess, 1 on failure.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuramstatic int
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvsw_unset_hw_addr(vsw_t *vswp, int slot)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram{
06db247c678f0e3956535e8a6dec31d6c2108827raghuram void *mah;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram int rv;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram D1(vswp, "%s: enter", __func__);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT(MUTEX_HELD(&vswp->hw_lock));
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT(slot >= 0);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vswp->maddr.maddr_handle == NULL)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (1);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mah = vswp->maddr.maddr_handle;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram rv = vswp->maddr.maddr_remove(mah, slot);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (rv != 0) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram cmn_err(CE_WARN, "!vsw%d: unable to remove address "
06db247c678f0e3956535e8a6dec31d6c2108827raghuram "from slot %d in device %s (err %d)",
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vswp->instance, slot, vswp->physname, rv);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (1);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram D2(vswp, "removed addr from slot %d in device %s",
06db247c678f0e3956535e8a6dec31d6c2108827raghuram slot, vswp->physname);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram D1(vswp, "%s: exit", __func__);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (0);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram}
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram/*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Set network card into promisc mode.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram *
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Returns 0 on success, 1 on failure.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuramstatic int
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvsw_set_hw_promisc(vsw_t *vswp, vsw_port_t *port, int type)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram{
06db247c678f0e3956535e8a6dec31d6c2108827raghuram D1(vswp, "%s: enter", __func__);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT(MUTEX_HELD(&vswp->hw_lock));
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT((type == VSW_LOCALDEV) || (type == VSW_VNETPORT));
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_enter(&vswp->mac_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vswp->mh == NULL) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_exit(&vswp->mac_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (1);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vswp->promisc_cnt++ == 0) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (mac_promisc_set(vswp->mh, B_TRUE, MAC_DEVPROMISC) != 0) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vswp->promisc_cnt--;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_exit(&vswp->mac_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (1);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram cmn_err(CE_NOTE, "!vsw%d: switching device %s into "
06db247c678f0e3956535e8a6dec31d6c2108827raghuram "promiscuous mode", vswp->instance, vswp->physname);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_exit(&vswp->mac_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (type == VSW_VNETPORT) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT(port != NULL);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram port->addr_set = VSW_ADDR_PROMISC;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram } else {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vswp->addr_set = VSW_ADDR_PROMISC;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram D1(vswp, "%s: exit", __func__);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (0);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram}
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram/*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Turn off promiscuous mode on network card.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram *
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Returns 0 on success, 1 on failure.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuramstatic int
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvsw_unset_hw_promisc(vsw_t *vswp, vsw_port_t *port, int type)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram{
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vsw_port_list_t *plist = &vswp->plist;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram D2(vswp, "%s: enter", __func__);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT(MUTEX_HELD(&vswp->hw_lock));
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT((type == VSW_LOCALDEV) || (type == VSW_VNETPORT));
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_enter(&vswp->mac_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vswp->mh == NULL) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_exit(&vswp->mac_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (1);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (--vswp->promisc_cnt == 0) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (mac_promisc_set(vswp->mh, B_FALSE, MAC_DEVPROMISC) != 0) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vswp->promisc_cnt++;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_exit(&vswp->mac_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (1);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * We are exiting promisc mode either because we were
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * only in promisc mode because we had failed over from
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * switched mode due to HW resource issues, or the user
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * wanted the card in promisc mode for all the ports and
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * the last port is now being deleted. Tweak the message
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * accordingly.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (plist->num_ports != 0) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram cmn_err(CE_NOTE, "!vsw%d: switching device %s back to "
06db247c678f0e3956535e8a6dec31d6c2108827raghuram "programmed mode", vswp->instance, vswp->physname);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram } else {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram cmn_err(CE_NOTE, "!vsw%d: switching device %s out of "
06db247c678f0e3956535e8a6dec31d6c2108827raghuram "promiscuous mode", vswp->instance, vswp->physname);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_exit(&vswp->mac_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (type == VSW_VNETPORT) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT(port != NULL);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT(port->addr_set == VSW_ADDR_PROMISC);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram port->addr_set = VSW_ADDR_UNSET;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram } else {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT(vswp->addr_set == VSW_ADDR_PROMISC);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vswp->addr_set = VSW_ADDR_UNSET;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram D1(vswp, "%s: exit", __func__);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (0);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram}
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram/*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Determine whether or not we are operating in our prefered
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * mode and if not whether the physical resources now allow us
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * to operate in it.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram *
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * If a port is being removed should only be invoked after port has been
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * removed from the port list.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvoid
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvsw_reconfig_hw(vsw_t *vswp)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram{
06db247c678f0e3956535e8a6dec31d6c2108827raghuram int s_idx;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram D1(vswp, "%s: enter", __func__);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT(MUTEX_HELD(&vswp->hw_lock));
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vswp->maddr.maddr_handle == NULL) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * If we are in layer 2 (i.e. switched) or would like to be
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * in layer 2 then check if any ports or the vswitch itself
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * need to be programmed into the HW.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram *
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * This can happen in two cases - switched was specified as
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * the prefered mode of operation but we exhausted the HW
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * resources and so failed over to the next specifed mode,
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * or switched was the only mode specified so after HW
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * resources were exhausted there was nothing more we
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * could do.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vswp->smode_idx > 0)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram s_idx = vswp->smode_idx - 1;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram else
06db247c678f0e3956535e8a6dec31d6c2108827raghuram s_idx = vswp->smode_idx;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vswp->smode[s_idx] != VSW_LAYER2) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram D2(vswp, "%s: attempting reconfig..", __func__);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * First, attempt to set the vswitch mac address into HW,
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * if required.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vsw_prog_if(vswp)) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Next, attempt to set any ports which have not yet been
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * programmed into HW.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vsw_prog_ports(vswp)) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * By now we know that have programmed all desired ports etc
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * into HW, so safe to mark reconfiguration as complete.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vswp->recfg_reqd = B_FALSE;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vswp->smode_idx = s_idx;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram D1(vswp, "%s: exit", __func__);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram}
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram/*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Check to see if vsw itself is plumbed, and if so whether or not
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * its mac address should be written into HW.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram *
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Returns 0 if could set address, or didn't have to set it.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Returns 1 if failed to set address.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuramstatic int
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvsw_prog_if(vsw_t *vswp)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram{
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mac_multi_addr_t addr;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram D1(vswp, "%s: enter", __func__);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT(MUTEX_HELD(&vswp->hw_lock));
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram READ_ENTER(&vswp->if_lockrw);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if ((vswp->if_state & VSW_IF_UP) &&
06db247c678f0e3956535e8a6dec31d6c2108827raghuram (vswp->addr_set != VSW_ADDR_HW)) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram addr.mma_addrlen = ETHERADDRL;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ether_copy(&vswp->if_addr, &addr.mma_addr);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vsw_set_hw_addr(vswp, &addr) != 0) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram RW_EXIT(&vswp->if_lockrw);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (1);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vswp->addr_slot = addr.mma_slot;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * If previously when plumbed had had to place
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * interface into promisc mode, now reverse that.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram *
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Note that interface will only actually be set into
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * non-promisc mode when last port/interface has been
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * programmed into HW.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vswp->addr_set == VSW_ADDR_PROMISC)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram (void) vsw_unset_hw_promisc(vswp, NULL, VSW_LOCALDEV);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vswp->addr_set = VSW_ADDR_HW;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram RW_EXIT(&vswp->if_lockrw);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram D1(vswp, "%s: exit", __func__);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (0);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram}
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram/*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Scan the port list for any ports which have not yet been set
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * into HW. For those found attempt to program their mac addresses
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * into the physical device.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram *
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Returns 0 if able to program all required ports (can be 0) into HW.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Returns 1 if failed to set at least one mac address.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuramstatic int
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvsw_prog_ports(vsw_t *vswp)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram{
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mac_multi_addr_t addr;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vsw_port_list_t *plist = &vswp->plist;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vsw_port_t *tp;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram int rv = 0;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram D1(vswp, "%s: enter", __func__);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT(MUTEX_HELD(&vswp->hw_lock));
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram READ_ENTER(&plist->lockrw);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram for (tp = plist->head; tp != NULL; tp = tp->p_next) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (tp->addr_set != VSW_ADDR_HW) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram addr.mma_addrlen = ETHERADDRL;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ether_copy(&tp->p_macaddr, &addr.mma_addr);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vsw_set_hw_addr(vswp, &addr) != 0) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram rv = 1;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram break;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram tp->addr_slot = addr.mma_slot;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * If when this port had first attached we had
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * had to place the interface into promisc mode,
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * then now reverse that.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram *
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Note that the interface will not actually
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * change to non-promisc mode until all ports
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * have been programmed.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (tp->addr_set == VSW_ADDR_PROMISC)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram (void) vsw_unset_hw_promisc(vswp,
06db247c678f0e3956535e8a6dec31d6c2108827raghuram tp, VSW_VNETPORT);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram tp->addr_set = VSW_ADDR_HW;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram RW_EXIT(&plist->lockrw);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram D1(vswp, "%s: exit", __func__);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (rv);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram}
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuramstatic void
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvsw_mac_ring_tbl_entry_init(vsw_t *vswp, vsw_mac_ring_t *ringp)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram{
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ringp->ring_state = VSW_MAC_RING_FREE;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ringp->ring_arg = NULL;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ringp->ring_blank = NULL;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ringp->ring_vqp = NULL;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ringp->ring_vswp = vswp;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram}
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuramstatic void
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvsw_mac_ring_tbl_init(vsw_t *vswp)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram{
06db247c678f0e3956535e8a6dec31d6c2108827raghuram int i;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_init(&vswp->mac_ring_lock, NULL, MUTEX_DRIVER, NULL);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vswp->mac_ring_tbl_sz = vsw_mac_rx_rings;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vswp->mac_ring_tbl =
06db247c678f0e3956535e8a6dec31d6c2108827raghuram kmem_alloc(vsw_mac_rx_rings * sizeof (vsw_mac_ring_t), KM_SLEEP);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram for (i = 0; i < vswp->mac_ring_tbl_sz; i++)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vsw_mac_ring_tbl_entry_init(vswp, &vswp->mac_ring_tbl[i]);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram}
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuramstatic void
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvsw_mac_ring_tbl_destroy(vsw_t *vswp)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram{
06db247c678f0e3956535e8a6dec31d6c2108827raghuram int i;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vsw_mac_ring_t *ringp;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_enter(&vswp->mac_ring_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram for (i = 0; i < vswp->mac_ring_tbl_sz; i++) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ringp = &vswp->mac_ring_tbl[i];
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (ringp->ring_state != VSW_MAC_RING_FREE) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Destroy the queue.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vsw_queue_stop(ringp->ring_vqp);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vsw_queue_destroy(ringp->ring_vqp);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Re-initialize the structure.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vsw_mac_ring_tbl_entry_init(vswp, ringp);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_exit(&vswp->mac_ring_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_destroy(&vswp->mac_ring_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram kmem_free(vswp->mac_ring_tbl,
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vswp->mac_ring_tbl_sz * sizeof (vsw_mac_ring_t));
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vswp->mac_ring_tbl_sz = 0;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram}
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram/*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Handle resource add callbacks from the driver below.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuramstatic mac_resource_handle_t
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvsw_mac_ring_add_cb(void *arg, mac_resource_t *mrp)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram{
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vsw_t *vswp = (vsw_t *)arg;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mac_rx_fifo_t *mrfp = (mac_rx_fifo_t *)mrp;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vsw_mac_ring_t *ringp;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vsw_queue_t *vqp;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram int i;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT(vswp != NULL);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT(mrp != NULL);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT(vswp->mac_ring_tbl != NULL);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram D1(vswp, "%s: enter", __func__);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Check to make sure we have the correct resource type.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (mrp->mr_type != MAC_RX_FIFO)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (NULL);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Find a open entry in the ring table.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_enter(&vswp->mac_ring_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram for (i = 0; i < vswp->mac_ring_tbl_sz; i++) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ringp = &vswp->mac_ring_tbl[i];
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Check for an empty slot, if found, then setup queue
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * and thread.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (ringp->ring_state == VSW_MAC_RING_FREE) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Create the queue for this ring.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vqp = vsw_queue_create();
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Initialize the ring data structure.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ringp->ring_vqp = vqp;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ringp->ring_arg = mrfp->mrf_arg;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ringp->ring_blank = mrfp->mrf_blank;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ringp->ring_state = VSW_MAC_RING_INUSE;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Create the worker thread.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vqp->vq_worker = thread_create(NULL, 0,
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vsw_queue_worker, ringp, 0, &p0,
06db247c678f0e3956535e8a6dec31d6c2108827raghuram TS_RUN, minclsyspri);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vqp->vq_worker == NULL) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vsw_queue_destroy(vqp);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vsw_mac_ring_tbl_entry_init(vswp, ringp);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ringp = NULL;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (ringp != NULL) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Make sure thread get's running state for
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * this ring.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_enter(&vqp->vq_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram while ((vqp->vq_state != VSW_QUEUE_RUNNING) &&
06db247c678f0e3956535e8a6dec31d6c2108827raghuram (vqp->vq_state != VSW_QUEUE_DRAINED)) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram cv_wait(&vqp->vq_cv, &vqp->vq_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * If the thread is not running, cleanup.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vqp->vq_state == VSW_QUEUE_DRAINED) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vsw_queue_destroy(vqp);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vsw_mac_ring_tbl_entry_init(vswp,
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ringp);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ringp = NULL;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_exit(&vqp->vq_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_exit(&vswp->mac_ring_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram D1(vswp, "%s: exit", __func__);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return ((mac_resource_handle_t)ringp);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_exit(&vswp->mac_ring_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * No slots in the ring table available.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram D1(vswp, "%s: exit", __func__);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (NULL);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram}
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuramstatic void
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvsw_queue_stop(vsw_queue_t *vqp)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram{
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_enter(&vqp->vq_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vqp->vq_state == VSW_QUEUE_RUNNING) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vqp->vq_state = VSW_QUEUE_STOP;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram cv_signal(&vqp->vq_cv);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram while (vqp->vq_state != VSW_QUEUE_DRAINED)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram cv_wait(&vqp->vq_cv, &vqp->vq_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vqp->vq_state = VSW_QUEUE_STOPPED;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_exit(&vqp->vq_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram}
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuramstatic vsw_queue_t *
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvsw_queue_create()
06db247c678f0e3956535e8a6dec31d6c2108827raghuram{
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vsw_queue_t *vqp;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vqp = kmem_zalloc(sizeof (vsw_queue_t), KM_SLEEP);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_init(&vqp->vq_lock, NULL, MUTEX_DRIVER, NULL);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram cv_init(&vqp->vq_cv, NULL, CV_DRIVER, NULL);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vqp->vq_first = NULL;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vqp->vq_last = NULL;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vqp->vq_state = VSW_QUEUE_STOPPED;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (vqp);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram}
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuramstatic void
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvsw_queue_destroy(vsw_queue_t *vqp)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram{
06db247c678f0e3956535e8a6dec31d6c2108827raghuram cv_destroy(&vqp->vq_cv);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_destroy(&vqp->vq_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram kmem_free(vqp, sizeof (vsw_queue_t));
06db247c678f0e3956535e8a6dec31d6c2108827raghuram}
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuramstatic void
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvsw_queue_worker(vsw_mac_ring_t *rrp)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram{
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mblk_t *mp;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vsw_queue_t *vqp = rrp->ring_vqp;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vsw_t *vswp = rrp->ring_vswp;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_enter(&vqp->vq_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT(vqp->vq_state == VSW_QUEUE_STOPPED);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Set the state to running, since the thread is now active.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vqp->vq_state = VSW_QUEUE_RUNNING;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram cv_signal(&vqp->vq_cv);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram while (vqp->vq_state == VSW_QUEUE_RUNNING) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Wait for work to do or the state has changed
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * to not running.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram while ((vqp->vq_state == VSW_QUEUE_RUNNING) &&
06db247c678f0e3956535e8a6dec31d6c2108827raghuram (vqp->vq_first == NULL)) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram cv_wait(&vqp->vq_cv, &vqp->vq_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Process packets that we received from the interface.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vqp->vq_first != NULL) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mp = vqp->vq_first;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vqp->vq_first = NULL;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vqp->vq_last = NULL;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_exit(&vqp->vq_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /* switch the chain of packets received */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vswp->vsw_switch_frame(vswp, mp,
06db247c678f0e3956535e8a6dec31d6c2108827raghuram VSW_PHYSDEV, NULL, NULL);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_enter(&vqp->vq_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * We are drained and signal we are done.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vqp->vq_state = VSW_QUEUE_DRAINED;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram cv_signal(&vqp->vq_cv);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Exit lock and drain the remaining packets.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_exit(&vqp->vq_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Exit the thread
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram thread_exit();
06db247c678f0e3956535e8a6dec31d6c2108827raghuram}
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram/*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * static void
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * vsw_rx_queue_cb() - Receive callback routine when
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * vsw_multi_ring_enable is non-zero. Queue the packets
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * to a packet queue for a worker thread to process.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuramstatic void
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvsw_rx_queue_cb(void *arg, mac_resource_handle_t mrh, mblk_t *mp)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram{
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vsw_mac_ring_t *ringp = (vsw_mac_ring_t *)mrh;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vsw_t *vswp = (vsw_t *)arg;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vsw_queue_t *vqp;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mblk_t *bp, *last;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT(mrh != NULL);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT(vswp != NULL);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT(mp != NULL);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram D1(vswp, "%s: enter", __func__);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Find the last element in the mblk chain.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram bp = mp;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram do {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram last = bp;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram bp = bp->b_next;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram } while (bp != NULL);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /* Get the queue for the packets */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vqp = ringp->ring_vqp;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Grab the lock such we can queue the packets.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_enter(&vqp->vq_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vqp->vq_state != VSW_QUEUE_RUNNING) {
ee03c681cedb48165922333190cdd8b230ffa073wentaoy freemsgchain(mp);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_exit(&vqp->vq_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram goto vsw_rx_queue_cb_exit;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Add the mblk chain to the queue. If there
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * is some mblks in the queue, then add the new
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * chain to the end.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if (vqp->vq_first == NULL)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vqp->vq_first = mp;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram else
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vqp->vq_last->b_next = mp;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vqp->vq_last = last;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Signal the worker thread that there is work to
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * do.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram cv_signal(&vqp->vq_cv);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Let go of the lock and exit.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_exit(&vqp->vq_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvsw_rx_queue_cb_exit:
06db247c678f0e3956535e8a6dec31d6c2108827raghuram D1(vswp, "%s: exit", __func__);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram}
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram/*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * receive callback routine. Invoked by MAC layer when there
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * are pkts being passed up from physical device.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram *
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * PERF: It may be more efficient when the card is in promisc
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * mode to check the dest address of the pkts here (against
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * the FDB) rather than checking later. Needs to be investigated.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghuramstatic void
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvsw_rx_cb(void *arg, mac_resource_handle_t mrh, mblk_t *mp)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram{
06db247c678f0e3956535e8a6dec31d6c2108827raghuram _NOTE(ARGUNUSED(mrh))
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vsw_t *vswp = (vsw_t *)arg;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram ASSERT(vswp != NULL);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram D1(vswp, "vsw_rx_cb: enter");
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram /* switch the chain of packets received */
06db247c678f0e3956535e8a6dec31d6c2108827raghuram vswp->vsw_switch_frame(vswp, mp, VSW_PHYSDEV, NULL, NULL);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram D1(vswp, "vsw_rx_cb: exit");
06db247c678f0e3956535e8a6dec31d6c2108827raghuram}
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram/*
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Send a message out over the physical device via the MAC layer.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram *
06db247c678f0e3956535e8a6dec31d6c2108827raghuram * Returns any mblks that it was unable to transmit.
06db247c678f0e3956535e8a6dec31d6c2108827raghuram */
06db247c678f0e3956535e8a6dec31d6c2108827raghurammblk_t *
06db247c678f0e3956535e8a6dec31d6c2108827raghuramvsw_tx_msg(vsw_t *vswp, mblk_t *mp)
06db247c678f0e3956535e8a6dec31d6c2108827raghuram{
06db247c678f0e3956535e8a6dec31d6c2108827raghuram const mac_txinfo_t *mtp;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_enter(&vswp->mac_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram if ((vswp->mh == NULL) || (vswp->mstarted == B_FALSE)) {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram DERR(vswp, "vsw_tx_msg: dropping pkts: no tx routine avail");
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_exit(&vswp->mac_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (mp);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram } else {
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mtp = vswp->txinfo;
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mp = mtp->mt_fn(mtp->mt_arg, mp);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram }
06db247c678f0e3956535e8a6dec31d6c2108827raghuram mutex_exit(&vswp->mac_lock);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram
06db247c678f0e3956535e8a6dec31d6c2108827raghuram return (mp);
06db247c678f0e3956535e8a6dec31d6c2108827raghuram}