da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * CDDL HEADER START
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * The contents of this file are subject to the terms of the
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Common Development and Distribution License (the "License").
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * You may not use this file except in compliance with the License.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * or http://www.opensolaris.org/os/licensing.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * See the License for the specific language governing permissions
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * and limitations under the License.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * When distributing Covered Code, include this CDDL HEADER in each
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * If applicable, add the following below this CDDL HEADER, with the
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * fields enclosed by brackets "[]" replaced with your own identifying
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * information: Portions Copyright [yyyy] [name of copyright owner]
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * CDDL HEADER END
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/*
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Use is subject to license terms.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * General Soft rings - Simulating Rx rings in S/W.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Soft ring is a data abstraction containing a queue and a worker
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * thread and represents a hardware Rx ring in software. Each soft
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * ring set can have a collection of soft rings for separating
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * L3/L4 specific traffic (IPv4 from IPv6 or TCP from UDP) or for
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * allowing a higher degree of parallelism by sending traffic to
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * one of the soft rings for a SRS (using a hash on src IP or port).
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Each soft ring worker thread can be bound to a different CPU
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * allowing the processing for each soft ring to happen in parallel
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * and independent from each other.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Protocol soft rings:
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Each SRS has at an minimum 3 softrings. One each for IPv4 TCP,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * IPv4 UDP and rest (OTH - for IPv6 and everything else). The
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * SRS does dynamic polling and enforces link level bandwidth but
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * it does so for all traffic (IPv4 and IPv6 and all protocols) on
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * that link. However, each protocol layer wants a different
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * behaviour. For instance IPv4 TCP has per CPU squeues which
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * enforce their own polling and flow control so IPv4 TCP traffic
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * needs to go to a separate soft ring which can be polled by the
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * TCP squeue. It also allows TCP squeue to push back flow control
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * all the way to NIC hardware (if it puts its corresponding soft
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * ring in the poll mode and soft ring queue builds up, the
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * shared srs_poll_pkt_cnt goes up and SRS automatically stops
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * more packets from entering the system).
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Similarly, the UDP benefits from a DLS bypass and packet chaining
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * so sending it to a separate soft ring is desired. All the rest of
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * the traffic (including IPv6 is sent to OTH softring). The IPv6
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * traffic current goes through OTH softring and via DLS because
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * it need more processing to be done. Irrespective of the sap
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * (IPv4 or IPv6) or the transport, the dynamic polling, B/W enforcement,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * cpu assignment, fanout, etc apply to all traffic since they
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * are implement by the SRS which is agnostic to sap or transport.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Fanout soft rings:
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * On a multithreaded system, we can assign more CPU and multi thread
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * the stack by creating a soft ring per CPU and spreading traffic
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * based on a hash computed on src IP etc. Since we still need to
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * keep the protocol separation, we create a set of 3 soft ring per
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * CPU (specified by cpu list or degree of fanout).
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * NOTE: See the block level comment on top of mac_sched.c
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <sys/types.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <sys/callb.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <sys/sdt.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <sys/strsubr.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <sys/strsun.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <sys/vlan.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <inet/ipsec_impl.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <inet/ip_impl.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <inet/sadb.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <inet/ipsecesp.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <inet/ipsecah.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <sys/mac_impl.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <sys/mac_client_impl.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <sys/mac_soft_ring.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <sys/mac_flow_impl.h>
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer#include <sys/mac_stat.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic void mac_rx_soft_ring_drain(mac_soft_ring_t *);
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic void mac_soft_ring_fire(void *);
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic void mac_soft_ring_worker(mac_soft_ring_t *);
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic void mac_tx_soft_ring_drain(mac_soft_ring_t *);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chenguint32_t mac_tx_soft_ring_max_q_cnt = 100000;
da14cebe459d3275048785f25bd869cb09b5307fEric Chenguint32_t mac_tx_soft_ring_hiwat = 1000;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengextern kmem_cache_t *mac_soft_ring_cache;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#define ADD_SOFTRING_TO_SET(mac_srs, softring) { \
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (mac_srs->srs_soft_ring_head == NULL) { \
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mac_srs->srs_soft_ring_head = softring; \
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mac_srs->srs_soft_ring_tail = softring; \
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng } else { \
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* ADD to the list */ \
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng softring->s_ring_prev = \
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mac_srs->srs_soft_ring_tail; \
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mac_srs->srs_soft_ring_tail->s_ring_next = softring; \
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mac_srs->srs_soft_ring_tail = softring; \
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng } \
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mac_srs->srs_soft_ring_count++; \
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * mac_soft_ring_worker_wakeup
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Wake up the soft ring worker thread to process the queue as long
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * as no one else is processing it and upper layer (client) is still
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * ready to receive packets.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvoid
da14cebe459d3275048785f25bd869cb09b5307fEric Chengmac_soft_ring_worker_wakeup(mac_soft_ring_t *ringp)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ASSERT(MUTEX_HELD(&ringp->s_ring_lock));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (!(ringp->s_ring_state & S_RING_PROC) &&
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng !(ringp->s_ring_state & S_RING_BLANK) &&
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (ringp->s_ring_tid == NULL)) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (ringp->s_ring_wait != 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_tid =
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng timeout(mac_soft_ring_fire, ringp,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_wait);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng } else {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* Schedule the worker thread. */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng cv_signal(&ringp->s_ring_async);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * mac_soft_ring_create
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Create a soft ring, do the necessary setup and bind the worker
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * thread to the assigned CPU.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Chengmac_soft_ring_t *
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyermac_soft_ring_create(int id, clock_t wait, uint16_t type,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng pri_t pri, mac_client_impl_t *mcip, mac_soft_ring_set_t *mac_srs,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng processorid_t cpuid, mac_direct_rx_t rx_func, void *x_arg1,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mac_resource_handle_t x_arg2)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mac_soft_ring_t *ringp;
08ac1c49adeb1b81324fa4e70a922581ad7ec309Nicolas Droux char name[S_RING_NAMELEN];
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bzero(name, 64);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp = kmem_cache_alloc(mac_soft_ring_cache, KM_SLEEP);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (type & ST_RING_TCP) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) snprintf(name, sizeof (name),
08ac1c49adeb1b81324fa4e70a922581ad7ec309Nicolas Droux "mac_tcp_soft_ring_%d_%p", id, (void *)mac_srs);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng } else if (type & ST_RING_UDP) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) snprintf(name, sizeof (name),
08ac1c49adeb1b81324fa4e70a922581ad7ec309Nicolas Droux "mac_udp_soft_ring_%d_%p", id, (void *)mac_srs);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer } else if (type & ST_RING_OTH) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) snprintf(name, sizeof (name),
08ac1c49adeb1b81324fa4e70a922581ad7ec309Nicolas Droux "mac_oth_soft_ring_%d_%p", id, (void *)mac_srs);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer } else {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer ASSERT(type & ST_RING_TX);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer (void) snprintf(name, sizeof (name),
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer "mac_tx_soft_ring_%d_%p", id, (void *)mac_srs);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bzero(ringp, sizeof (mac_soft_ring_t));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) strncpy(ringp->s_ring_name, name, S_RING_NAMELEN + 1);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_name[S_RING_NAMELEN] = '\0';
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_init(&ringp->s_ring_lock, NULL, MUTEX_DEFAULT, NULL);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_notify_cb_info.mcbi_lockp = &ringp->s_ring_lock;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_type = type;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_wait = MSEC_TO_TICK(wait);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_mcip = mcip;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_set = mac_srs;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Protect against access from DR callbacks (mac_walk_srs_bind/unbind)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * which can't grab the mac perimeter
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_enter(&mac_srs->srs_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ADD_SOFTRING_TO_SET(mac_srs, ringp);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_exit(&mac_srs->srs_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * set the bind CPU to -1 to indicate
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * no thread affinity set
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_cpuid = ringp->s_ring_cpuid_save = -1;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_worker = thread_create(NULL, 0,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mac_soft_ring_worker, ringp, 0, &p0, TS_RUN, pri);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (type & ST_RING_TX) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_drain_func = mac_tx_soft_ring_drain;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_tx_arg1 = x_arg1;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_tx_arg2 = x_arg2;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_tx_max_q_cnt = mac_tx_soft_ring_max_q_cnt;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_tx_hiwat =
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (mac_tx_soft_ring_hiwat > mac_tx_soft_ring_max_q_cnt) ?
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mac_tx_soft_ring_max_q_cnt : mac_tx_soft_ring_hiwat;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (mcip->mci_state_flags & MCIS_IS_AGGR) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_srs_tx_t *tx = &mac_srs->srs_tx;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer ASSERT(tx->st_soft_rings[
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer ((mac_ring_t *)x_arg2)->mr_index] == NULL);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer tx->st_soft_rings[((mac_ring_t *)x_arg2)->mr_index] =
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer ringp;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng } else {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_drain_func = mac_rx_soft_ring_drain;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_rx_func = rx_func;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_rx_arg1 = x_arg1;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_rx_arg2 = x_arg2;
ae6aa22afeb444ae208c287e7227a4a7c877f17aVenugopal Iyer if (mac_srs->srs_state & SRS_SOFTRING_QUEUE)
ae6aa22afeb444ae208c287e7227a4a7c877f17aVenugopal Iyer ringp->s_ring_type |= ST_RING_WORKER_ONLY;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (cpuid != -1)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) mac_soft_ring_bind(ringp, cpuid);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_soft_ring_stat_create(ringp);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (ringp);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * mac_soft_ring_free
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Free the soft ring once we are done with it.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvoid
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyermac_soft_ring_free(mac_soft_ring_t *softring)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ASSERT((softring->s_ring_state &
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (S_RING_CONDEMNED | S_RING_CONDEMNED_DONE | S_RING_PROC)) ==
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (S_RING_CONDEMNED | S_RING_CONDEMNED_DONE));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mac_pkt_drop(NULL, NULL, softring->s_ring_first, B_FALSE);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer softring->s_ring_tx_arg2 = NULL;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_soft_ring_stat_delete(softring);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mac_callback_free(softring->s_ring_notify_cb_list);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng kmem_cache_free(mac_soft_ring_cache, softring);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengint mac_soft_ring_thread_bind = 1;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * mac_soft_ring_bind
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Bind a soft ring worker thread to supplied CPU.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Chengcpu_t *
da14cebe459d3275048785f25bd869cb09b5307fEric Chengmac_soft_ring_bind(mac_soft_ring_t *ringp, processorid_t cpuid)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng cpu_t *cp;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng boolean_t clear = B_FALSE;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ASSERT(MUTEX_HELD(&cpu_lock));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (mac_soft_ring_thread_bind == 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng DTRACE_PROBE1(mac__soft__ring__no__cpu__bound,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mac_soft_ring_t *, ringp);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (NULL);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng cp = cpu_get(cpuid);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (cp == NULL || !cpu_is_online(cp))
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (NULL);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_enter(&ringp->s_ring_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_state |= S_RING_BOUND;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (ringp->s_ring_cpuid != -1)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng clear = B_TRUE;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_cpuid = cpuid;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_exit(&ringp->s_ring_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (clear)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng thread_affinity_clear(ringp->s_ring_worker);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng DTRACE_PROBE2(mac__soft__ring__cpu__bound, mac_soft_ring_t *,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp, processorid_t, cpuid);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng thread_affinity_set(ringp->s_ring_worker, cpuid);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (cp);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * mac_soft_ring_unbind
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Un Bind a soft ring worker thread.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvoid
da14cebe459d3275048785f25bd869cb09b5307fEric Chengmac_soft_ring_unbind(mac_soft_ring_t *ringp)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ASSERT(MUTEX_HELD(&cpu_lock));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_enter(&ringp->s_ring_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (!(ringp->s_ring_state & S_RING_BOUND)) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ASSERT(ringp->s_ring_cpuid == -1);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_exit(&ringp->s_ring_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_cpuid = -1;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_state &= ~S_RING_BOUND;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng thread_affinity_clear(ringp->s_ring_worker);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_exit(&ringp->s_ring_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * PRIVATE FUNCTIONS
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic void
da14cebe459d3275048785f25bd869cb09b5307fEric Chengmac_soft_ring_fire(void *arg)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mac_soft_ring_t *ringp = arg;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_enter(&ringp->s_ring_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (ringp->s_ring_tid == 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_exit(&ringp->s_ring_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_tid = 0;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (!(ringp->s_ring_state & S_RING_PROC)) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng cv_signal(&ringp->s_ring_async);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_exit(&ringp->s_ring_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * mac_rx_soft_ring_drain
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Called when worker thread model (ST_RING_WORKER_ONLY) of processing
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * incoming packets is used. s_ring_first contain the queued packets.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * s_ring_rx_func contains the upper level (client) routine where the
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * packets are destined and s_ring_rx_arg1/s_ring_rx_arg2 are the
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * cookie meant for the client.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/* ARGSUSED */
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic void
da14cebe459d3275048785f25bd869cb09b5307fEric Chengmac_rx_soft_ring_drain(mac_soft_ring_t *ringp)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mblk_t *mp;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng void *arg1;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mac_resource_handle_t arg2;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng timeout_id_t tid;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mac_direct_rx_t proc;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng size_t sz;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng int cnt;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mac_soft_ring_set_t *mac_srs = ringp->s_ring_set;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_run = curthread;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ASSERT(mutex_owned(&ringp->s_ring_lock));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ASSERT(!(ringp->s_ring_state & S_RING_PROC));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if ((tid = ringp->s_ring_tid) != 0)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_tid = 0;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_state |= S_RING_PROC;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng proc = ringp->s_ring_rx_func;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng arg1 = ringp->s_ring_rx_arg1;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng arg2 = ringp->s_ring_rx_arg2;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng while ((ringp->s_ring_first != NULL) &&
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng !(ringp->s_ring_state & S_RING_PAUSE)) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mp = ringp->s_ring_first;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_first = NULL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_last = NULL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng cnt = ringp->s_ring_count;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_count = 0;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng sz = ringp->s_ring_size;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_size = 0;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_exit(&ringp->s_ring_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (tid != 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) untimeout(tid);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng tid = 0;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (*proc)(arg1, arg2, mp, NULL);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * If we have a soft ring set which is doing
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * bandwidth control, we need to decrement its
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * srs_size so it can have a accurate idea of
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * what is the real data queued between SRS and
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * its soft rings. We decrement the size for a
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * packet only when it gets processed by both
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * SRS and the soft ring.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_enter(&mac_srs->srs_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng MAC_UPDATE_SRS_COUNT_LOCKED(mac_srs, cnt);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng MAC_UPDATE_SRS_SIZE_LOCKED(mac_srs, sz);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_exit(&mac_srs->srs_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_enter(&ringp->s_ring_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_state &= ~S_RING_PROC;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (ringp->s_ring_state & S_RING_CLIENT_WAIT)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng cv_signal(&ringp->s_ring_client_cv);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_run = NULL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * mac_soft_ring_worker
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * The soft ring worker routine to process any queued packets. In
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * normal case, the worker thread is bound to a CPU. It the soft
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * ring is dealing with TCP packets, then the worker thread will
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * be bound to the same CPU as the TCP squeue.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic void
da14cebe459d3275048785f25bd869cb09b5307fEric Chengmac_soft_ring_worker(mac_soft_ring_t *ringp)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng kmutex_t *lock = &ringp->s_ring_lock;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng kcondvar_t *async = &ringp->s_ring_async;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mac_soft_ring_set_t *srs = ringp->s_ring_set;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng callb_cpr_t cprinfo;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng CALLB_CPR_INIT(&cprinfo, lock, callb_generic_cpr, "mac_soft_ring");
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_enter(lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstart:
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng for (;;) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng while (((ringp->s_ring_first == NULL ||
efe28d82661ce6701204798fb838fd29c6348931Rajagopal Kunhappan (ringp->s_ring_state & (S_RING_BLOCK|S_RING_BLANK))) &&
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng !(ringp->s_ring_state & S_RING_PAUSE)) ||
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (ringp->s_ring_state & S_RING_PROC)) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng CALLB_CPR_SAFE_BEGIN(&cprinfo);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng cv_wait(async, lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng CALLB_CPR_SAFE_END(&cprinfo, lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Either we have work to do, or we have been asked to
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * shutdown temporarily or permanently
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (ringp->s_ring_state & S_RING_PAUSE)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng goto done;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_drain_func(ringp);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Chengdone:
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_exit(lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_enter(&srs->srs_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_enter(lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_state |= S_RING_QUIESCE_DONE;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (!(ringp->s_ring_state & S_RING_CONDEMNED)) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng srs->srs_soft_ring_quiesced_count++;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng cv_broadcast(&srs->srs_async);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_exit(&srs->srs_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng while (!(ringp->s_ring_state &
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (S_RING_RESTART | S_RING_CONDEMNED)))
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng cv_wait(&ringp->s_ring_async, &ringp->s_ring_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_exit(lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_enter(&srs->srs_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_enter(lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng srs->srs_soft_ring_quiesced_count--;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (ringp->s_ring_state & S_RING_RESTART) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ASSERT(!(ringp->s_ring_state & S_RING_CONDEMNED));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_state &= ~(S_RING_RESTART |
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng S_RING_QUIESCE | S_RING_QUIESCE_DONE);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng cv_broadcast(&srs->srs_async);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_exit(&srs->srs_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng goto start;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ASSERT(ringp->s_ring_state & S_RING_CONDEMNED);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_state |= S_RING_CONDEMNED_DONE;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng CALLB_CPR_EXIT(&cprinfo);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng srs->srs_soft_ring_condemned_count++;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng cv_broadcast(&srs->srs_async);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_exit(&srs->srs_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng thread_exit();
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * mac_soft_ring_intr_enable and mac_soft_ring_intr_disable
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * these functions are called to toggle the sending of packets to the
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * client. They are called by the client. the client gets the name
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * of these routine and corresponding cookie (pointing to softring)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * during capability negotiation at setup time.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Enabling is allow the processing thread to send packets to the
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * client while disabling does the opposite.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvoid
da14cebe459d3275048785f25bd869cb09b5307fEric Chengmac_soft_ring_intr_enable(void *arg)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mac_soft_ring_t *ringp = (mac_soft_ring_t *)arg;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_enter(&ringp->s_ring_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_state &= ~S_RING_BLANK;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (ringp->s_ring_first != NULL)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mac_soft_ring_worker_wakeup(ringp);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_exit(&ringp->s_ring_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
efe28d82661ce6701204798fb838fd29c6348931Rajagopal Kunhappanboolean_t
da14cebe459d3275048785f25bd869cb09b5307fEric Chengmac_soft_ring_intr_disable(void *arg)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mac_soft_ring_t *ringp = (mac_soft_ring_t *)arg;
efe28d82661ce6701204798fb838fd29c6348931Rajagopal Kunhappan boolean_t sring_blanked = B_FALSE;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Stop worker thread from sending packets above.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Squeue will poll soft ring when it needs packets.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_enter(&ringp->s_ring_lock);
efe28d82661ce6701204798fb838fd29c6348931Rajagopal Kunhappan if (!(ringp->s_ring_state & S_RING_PROC)) {
efe28d82661ce6701204798fb838fd29c6348931Rajagopal Kunhappan ringp->s_ring_state |= S_RING_BLANK;
efe28d82661ce6701204798fb838fd29c6348931Rajagopal Kunhappan sring_blanked = B_TRUE;
efe28d82661ce6701204798fb838fd29c6348931Rajagopal Kunhappan }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_exit(&ringp->s_ring_lock);
efe28d82661ce6701204798fb838fd29c6348931Rajagopal Kunhappan return (sring_blanked);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * mac_soft_ring_poll
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * This routine is called by the client to poll for packets from
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * the soft ring. The function name and cookie corresponding to
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * the soft ring is exchanged during capability negotiation during
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * setup.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Chengmblk_t *
da14cebe459d3275048785f25bd869cb09b5307fEric Chengmac_soft_ring_poll(mac_soft_ring_t *ringp, int bytes_to_pickup)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mblk_t *head, *tail;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mblk_t *mp;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng size_t sz = 0;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng int cnt = 0;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mac_soft_ring_set_t *mac_srs = ringp->s_ring_set;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ASSERT(mac_srs != NULL);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_enter(&ringp->s_ring_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng head = tail = mp = ringp->s_ring_first;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (head == NULL) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_exit(&ringp->s_ring_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (NULL);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (ringp->s_ring_size <= bytes_to_pickup) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng head = ringp->s_ring_first;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_first = NULL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_last = NULL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng cnt = ringp->s_ring_count;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_count = 0;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng sz = ringp->s_ring_size;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_size = 0;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng } else {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng while (mp && sz <= bytes_to_pickup) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng sz += msgdsize(mp);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng cnt++;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng tail = mp;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mp = mp->b_next;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_count -= cnt;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_size -= sz;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng tail->b_next = NULL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (mp == NULL) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_first = NULL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_last = NULL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ASSERT(ringp->s_ring_count == 0);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng } else {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_first = mp;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_exit(&ringp->s_ring_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Update the shared count and size counters so
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * that SRS has a accurate idea of queued packets.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_enter(&mac_srs->srs_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng MAC_UPDATE_SRS_COUNT_LOCKED(mac_srs, cnt);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng MAC_UPDATE_SRS_SIZE_LOCKED(mac_srs, sz);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_exit(&mac_srs->srs_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (head);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * mac_soft_ring_dls_bypass
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Enable direct client (IP) callback function from the softrings.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Callers need to make sure they don't need any DLS layer processing
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvoid
da14cebe459d3275048785f25bd869cb09b5307fEric Chengmac_soft_ring_dls_bypass(void *arg, mac_direct_rx_t rx_func, void *rx_arg1)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mac_soft_ring_t *softring = arg;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mac_soft_ring_set_t *srs;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ASSERT(rx_func != NULL);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_enter(&softring->s_ring_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng softring->s_ring_rx_func = rx_func;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng softring->s_ring_rx_arg1 = rx_arg1;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_exit(&softring->s_ring_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng srs = softring->s_ring_set;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_enter(&srs->srs_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng srs->srs_type |= SRST_DLS_BYPASS;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_exit(&srs->srs_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * mac_soft_ring_signal
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Typically used to set the soft ring state to QUIESCE, CONDEMNED, or
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * RESTART.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * In the Rx side, the quiescing is done bottom up. After the Rx upcalls
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * from the driver are done, then the Rx SRS is quiesced and only then can
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * we signal the soft rings. Thus this function can't be called arbitrarily
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * without satisfying the prerequisites. On the Tx side, the threads from
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * top need to quiesced, then the Tx SRS and only then can we signal the
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Tx soft rings.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvoid
da14cebe459d3275048785f25bd869cb09b5307fEric Chengmac_soft_ring_signal(mac_soft_ring_t *softring, uint_t sr_flag)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_enter(&softring->s_ring_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng softring->s_ring_state |= sr_flag;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng cv_signal(&softring->s_ring_async);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_exit(&softring->s_ring_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * mac_tx_soft_ring_drain
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * The transmit side drain routine in case the soft ring was being
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * used to transmit packets.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic void
da14cebe459d3275048785f25bd869cb09b5307fEric Chengmac_tx_soft_ring_drain(mac_soft_ring_t *ringp)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mblk_t *mp;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng void *arg1;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng void *arg2;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mblk_t *tail;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng uint_t saved_pkt_count, saved_size;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mac_tx_stats_t stats;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mac_soft_ring_set_t *mac_srs = ringp->s_ring_set;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng saved_pkt_count = saved_size = 0;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_run = curthread;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ASSERT(mutex_owned(&ringp->s_ring_lock));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ASSERT(!(ringp->s_ring_state & S_RING_PROC));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_state |= S_RING_PROC;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng arg1 = ringp->s_ring_tx_arg1;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng arg2 = ringp->s_ring_tx_arg2;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng while (ringp->s_ring_first != NULL) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mp = ringp->s_ring_first;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng tail = ringp->s_ring_last;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng saved_pkt_count = ringp->s_ring_count;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng saved_size = ringp->s_ring_size;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_first = NULL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_last = NULL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_count = 0;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_size = 0;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_exit(&ringp->s_ring_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mp = mac_tx_send(arg1, arg2, mp, &stats);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_enter(&ringp->s_ring_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (mp != NULL) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* Device out of tx desc, set block */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng tail->b_next = ringp->s_ring_first;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_first = mp;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_count +=
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer (saved_pkt_count - stats.mts_opackets);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer ringp->s_ring_size += (saved_size - stats.mts_obytes);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (ringp->s_ring_last == NULL)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_last = tail;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (ringp->s_ring_tx_woken_up) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_tx_woken_up = B_FALSE;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng } else {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_state |= S_RING_BLOCK;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer ringp->s_st_stat.mts_blockcnt++;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_state &= ~S_RING_PROC;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_run = NULL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng } else {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_tx_woken_up = B_FALSE;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer SRS_TX_STATS_UPDATE(mac_srs, &stats);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer SOFTRING_TX_STATS_UPDATE(ringp, &stats);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (ringp->s_ring_count == 0 && ringp->s_ring_state &
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (S_RING_TX_HIWAT | S_RING_WAKEUP_CLIENT | S_RING_ENQUEUED)) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mac_client_impl_t *mcip = ringp->s_ring_mcip;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng boolean_t wakeup_required = B_FALSE;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (ringp->s_ring_state &
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (S_RING_TX_HIWAT|S_RING_WAKEUP_CLIENT)) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng wakeup_required = B_TRUE;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_state &=
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ~(S_RING_TX_HIWAT | S_RING_WAKEUP_CLIENT | S_RING_ENQUEUED);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_exit(&ringp->s_ring_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (wakeup_required) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_tx_invoke_callbacks(mcip, (mac_tx_cookie_t)ringp);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * If the client is not the primary MAC client, then we
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * need to send the notification to the clients upper
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * MAC, i.e. mci_upper_mip.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mac_tx_notify(mcip->mci_upper_mip != NULL ?
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mcip->mci_upper_mip : mcip->mci_mip);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_enter(&ringp->s_ring_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_state &= ~S_RING_PROC;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ringp->s_ring_run = NULL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}