5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou/*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * CDDL HEADER START
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou *
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * The contents of this file are subject to the terms of the
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Common Development and Distribution License (the "License").
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * You may not use this file except in compliance with the License.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou *
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * or http://www.opensolaris.org/os/licensing.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * See the License for the specific language governing permissions
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * and limitations under the License.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou *
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * When distributing Covered Code, include this CDDL HEADER in each
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * If applicable, add the following below this CDDL HEADER, with the
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * fields enclosed by brackets "[]" replaced with your own identifying
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * information: Portions Copyright [yyyy] [name of copyright owner]
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou *
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * CDDL HEADER END
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou/*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Use is subject to license terms.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou/*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Softmac data-path switching:
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou *
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * - Fast-path model
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou *
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * When the softmac fast-path is used, a dedicated lower-stream
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * will be opened over the legacy device for each IP/ARP (upper-)stream
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * over the softMAC, and all DLPI messages (including control messages
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * and data messages) will be exchanged between the upper-stream and
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * the corresponding lower-stream directly. Therefore, the data
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * demultiplexing, filtering and classification processing will be done
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * by the lower-stream, and the GLDv3 DLS/MAC layer processing will be
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * no longer needed.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou *
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * - Slow-path model
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou *
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Some GLDv3 features requires the GLDv3 DLS/MAC layer processing to
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * not be bypassed to assure its function correctness. For example,
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * softmac fast-path must be disabled to support GLDv3 VNIC functionality.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * In this case, a shared lower-stream will be opened over the legacy
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * device, which is responsible for implementing the GLDv3 callbacks
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * and passing RAW data messages between the legacy devices and the GLDv3
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * framework.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou *
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * By default, the softmac fast-path mode will be used to assure the
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * performance; MAC clients will be able to request to disable the softmac
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * fast-path mode to support certain features, and if that succeeds,
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * the system will fallback to the slow-path softmac data-path model.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou *
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou *
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * The details of the softmac data fast-path model is stated as below
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou *
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * 1. When a stream is opened on a softMAC, the softmac module will takes
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * over the DLPI processing on this stream;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou *
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * 2. For IP/ARP streams over a softMAC, softmac data fast-path will be
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * used by default, unless fast-path is disabled by any MAC client
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * explicitly. The softmac module first identifies an IP/ARP stream
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * by seeing whether there is a SIOCSLIFNAME ioctl sent from upstream,
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * if there is one, this stream is either an IP or an ARP stream
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * and will use fast-path potentially;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou *
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * 3. When the softmac fast-path is used, an dedicated lower-stream will
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * be setup for each IP/ARP stream (1-1 mapping). From that point on,
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * all control and data messages will be exchanged between the IP/ARP
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * upper-stream and the legacy device through this dedicated
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * lower-stream. As a result, the DLS/MAC layer processing in GLDv3
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * will be skipped, and this greatly improves the performance;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou *
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * 4. When the softmac data fast-path is disabled by a MAC client (e.g.,
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * by a VNIC), all the IP/ARP upper streams will try to switch from
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * the fast-path to the slow-path. The dedicated lower-stream will be
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * destroyed, and all the control and data-messages will go through the
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * existing GLDv3 code path and (in the end) the shared lower-stream;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou *
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * 5. On the other hand, when the last MAC client cancels its fast-path
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * disable request, all the IP/ARP streams will try to switch back to
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * the fast-path mode;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou *
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Step 5 and 6 both rely on the data-path mode switching process
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * described below:
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou *
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * 1) To switch the softmac data-path mode (between fast-path and slow-path),
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * softmac will first send a DL_NOTE_REPLUMB DL_NOTIFY_IND message
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * upstream over each IP/ARP streams that needs data-path mode switching;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou *
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * 2) When IP receives this DL_NOTE_REPLUMB message, it will bring down
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * all the IP interfaces on the corresponding ill (IP Lower level
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * structure), and bring up those interfaces over again; this will in
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * turn cause the ARP to "replumb" the interface.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou *
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * During the replumb process, both IP and ARP will send downstream the
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * necessary DL_DISABMULTI_REQ and DL_UNBIND_REQ messages and cleanup
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * the old state of the underlying softMAC, following with the necessary
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * DL_BIND_REQ and DL_ENABMULTI_REQ messages to setup the new state.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Between the cleanup and re-setup process, IP/ARP will also send down
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * a DL_NOTE_REPLUMB_DONE DL_NOTIFY_CONF messages to the softMAC to
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * indicate the *switching point*;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou *
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * 3) When softmac receives the DL_NOTE_REPLUMB_DONE message, it either
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * creates or destroys the dedicated lower-stream (depending on which
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * data-path mode the softMAC switches to), and change the softmac
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * data-path mode. From then on, softmac will process all the succeeding
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * control messages (including the DL_BIND_REQ and DL_ENABMULTI_REQ
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * messages) and data messages based on new data-path mode.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou#include <sys/types.h>
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou#include <sys/disp.h>
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou#include <sys/callb.h>
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou#include <sys/sysmacros.h>
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou#include <sys/file.h>
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou#include <sys/vlan.h>
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou#include <sys/dld.h>
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou#include <sys/sockio.h>
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou#include <sys/softmac_impl.h>
82a2fc4751cef28c0bdc327d02012bf8796083b9James Carlson#include <net/if.h>
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhoustatic kmutex_t softmac_taskq_lock;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhoustatic kcondvar_t softmac_taskq_cv;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhoustatic list_t softmac_taskq_list; /* List of softmac_upper_t */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhouboolean_t softmac_taskq_quit;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhouboolean_t softmac_taskq_done;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhoustatic void softmac_taskq_dispatch();
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhoustatic int softmac_fastpath_setup(softmac_upper_t *);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhoustatic mac_tx_cookie_t softmac_fastpath_wput_data(softmac_upper_t *, mblk_t *,
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou uintptr_t, uint16_t);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhoustatic void softmac_datapath_switch_done(softmac_upper_t *);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhouvoid
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhousoftmac_fp_init()
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou{
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_init(&softmac_taskq_lock, NULL, MUTEX_DRIVER, NULL);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou cv_init(&softmac_taskq_cv, NULL, CV_DRIVER, NULL);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac_taskq_quit = B_FALSE;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac_taskq_done = B_FALSE;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou list_create(&softmac_taskq_list, sizeof (softmac_upper_t),
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou offsetof(softmac_upper_t, su_taskq_list_node));
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou (void) thread_create(NULL, 0, softmac_taskq_dispatch, NULL, 0,
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou &p0, TS_RUN, minclsyspri);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou}
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhouvoid
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhousoftmac_fp_fini()
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou{
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Request the softmac_taskq thread to quit and wait for it to be done.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_enter(&softmac_taskq_lock);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac_taskq_quit = B_TRUE;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou cv_signal(&softmac_taskq_cv);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou while (!softmac_taskq_done)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou cv_wait(&softmac_taskq_cv, &softmac_taskq_lock);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_exit(&softmac_taskq_lock);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou list_destroy(&softmac_taskq_list);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_destroy(&softmac_taskq_lock);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou cv_destroy(&softmac_taskq_cv);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou}
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhoustatic boolean_t
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhoucheck_ip_above(queue_t *q)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou{
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou queue_t *next_q;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou boolean_t ret = B_TRUE;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou claimstr(q);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou next_q = q->q_next;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (strcmp(next_q->q_qinfo->qi_minfo->mi_idname, "ip") != 0)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou ret = B_FALSE;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou releasestr(q);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return (ret);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou}
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou/* ARGSUSED */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhoustatic int
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhousoftmac_capab_perim(softmac_upper_t *sup, void *data, uint_t flags)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou{
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou switch (flags) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou case DLD_ENABLE:
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_enter(&sup->su_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou break;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou case DLD_DISABLE:
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_exit(&sup->su_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou break;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou case DLD_QUERY:
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return (MUTEX_HELD(&sup->su_mutex));
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return (0);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou}
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhoustatic mac_tx_notify_handle_t
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhousoftmac_client_tx_notify(softmac_upper_t *sup, mac_tx_notify_t func, void *arg)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou{
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou ASSERT(MUTEX_HELD(&sup->su_mutex));
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou if (func != NULL) {
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou sup->su_tx_notify_func = func;
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou sup->su_tx_notify_arg = arg;
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou } else {
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou /*
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou * Wait for all tx_notify_func call to be done.
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou */
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou while (sup->su_tx_inprocess != 0)
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou cv_wait(&sup->su_cv, &sup->su_mutex);
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou sup->su_tx_notify_func = NULL;
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou sup->su_tx_notify_arg = NULL;
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou }
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou return ((mac_tx_notify_handle_t)sup);
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou}
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhoustatic boolean_t
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhousoftmac_tx_is_flow_blocked(softmac_upper_t *sup, mac_tx_cookie_t cookie)
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou{
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou ASSERT(cookie == (mac_tx_cookie_t)sup);
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou return (sup->su_tx_busy);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou}
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhoustatic int
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhousoftmac_capab_direct(softmac_upper_t *sup, void *data, uint_t flags)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou{
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dld_capab_direct_t *direct = data;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac_lower_t *slp = sup->su_slp;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou ASSERT(MUTEX_HELD(&sup->su_mutex));
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou ASSERT(sup->su_mode == SOFTMAC_FASTPATH);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou switch (flags) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou case DLD_ENABLE:
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (sup->su_direct)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return (0);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou sup->su_direct_rxinfo.slr_rx = (softmac_rx_t)direct->di_rx_cf;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou sup->su_direct_rxinfo.slr_arg = direct->di_rx_ch;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou slp->sl_rxinfo = &sup->su_direct_rxinfo;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou direct->di_tx_df = (uintptr_t)softmac_fastpath_wput_data;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou direct->di_tx_dh = sup;
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou direct->di_tx_fctl_df = (uintptr_t)softmac_tx_is_flow_blocked;
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou direct->di_tx_fctl_dh = sup;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou direct->di_tx_cb_df = (uintptr_t)softmac_client_tx_notify;
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou direct->di_tx_cb_dh = sup;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou sup->su_direct = B_TRUE;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return (0);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou case DLD_DISABLE:
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (!sup->su_direct)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return (0);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou slp->sl_rxinfo = &sup->su_rxinfo;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou sup->su_direct = B_FALSE;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return (0);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return (ENOTSUP);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou}
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhoustatic int
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhousoftmac_dld_capab(softmac_upper_t *sup, uint_t type, void *data, uint_t flags)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou{
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou int err;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Don't enable direct callback capabilities unless the caller is
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * the IP client. When a module is inserted in a stream (_I_INSERT)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * the stack initiates capability disable, but due to races, the
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * module insertion may complete before the capability disable
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * completes. So we limit the check to DLD_ENABLE case.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if ((flags == DLD_ENABLE && type != DLD_CAPAB_PERIM) &&
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou !check_ip_above(sup->su_rq)) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return (ENOTSUP);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou switch (type) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou case DLD_CAPAB_DIRECT:
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou err = softmac_capab_direct(sup, data, flags);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou break;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou case DLD_CAPAB_PERIM:
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou err = softmac_capab_perim(sup, data, flags);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou break;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou default:
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou err = ENOTSUP;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou break;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return (err);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou}
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhoustatic void
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhousoftmac_capability_advertise(softmac_upper_t *sup, mblk_t *mp)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou{
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dl_capability_ack_t *dlap;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dl_capability_sub_t *dlsp;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou t_uscalar_t subsize;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou uint8_t *ptr;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou queue_t *q = sup->su_wq;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mblk_t *mp1;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac_t *softmac = sup->su_softmac;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou boolean_t dld_capable = B_FALSE;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou boolean_t hcksum_capable = B_FALSE;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou boolean_t zcopy_capable = B_FALSE;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou boolean_t mdt_capable = B_FALSE;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou ASSERT(sup->su_mode == SOFTMAC_FASTPATH);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Initially assume no capabilities.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou subsize = 0;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Direct capability negotiation interface between IP and softmac
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (check_ip_above(sup->su_rq)) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dld_capable = B_TRUE;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou subsize += sizeof (dl_capability_sub_t) +
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou sizeof (dl_capab_dld_t);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Check if checksum offload is supported on this MAC.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (softmac->smac_capab_flags & MAC_CAPAB_HCKSUM) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou hcksum_capable = B_TRUE;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou subsize += sizeof (dl_capability_sub_t) +
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou sizeof (dl_capab_hcksum_t);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Check if zerocopy is supported on this interface.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (!(softmac->smac_capab_flags & MAC_CAPAB_NO_ZCOPY)) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou zcopy_capable = B_TRUE;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou subsize += sizeof (dl_capability_sub_t) +
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou sizeof (dl_capab_zerocopy_t);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (softmac->smac_mdt) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mdt_capable = B_TRUE;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou subsize += sizeof (dl_capability_sub_t) +
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou sizeof (dl_capab_mdt_t);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * If there are no capabilities to advertise or if we
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * can't allocate a response, send a DL_ERROR_ACK.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if ((subsize == 0) || (mp1 = reallocb(mp,
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou sizeof (dl_capability_ack_t) + subsize, 0)) == NULL) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dlerrorack(q, mp, DL_CAPABILITY_REQ, DL_NOTSUPPORTED, 0);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mp = mp1;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou DB_TYPE(mp) = M_PROTO;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mp->b_wptr = mp->b_rptr + sizeof (dl_capability_ack_t) + subsize;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou bzero(mp->b_rptr, MBLKL(mp));
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dlap = (dl_capability_ack_t *)mp->b_rptr;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dlap->dl_primitive = DL_CAPABILITY_ACK;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dlap->dl_sub_offset = sizeof (dl_capability_ack_t);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dlap->dl_sub_length = subsize;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou ptr = (uint8_t *)&dlap[1];
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * IP polling interface.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (dld_capable) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dl_capab_dld_t dld;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dlsp = (dl_capability_sub_t *)ptr;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dlsp->dl_cap = DL_CAPAB_DLD;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dlsp->dl_length = sizeof (dl_capab_dld_t);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou ptr += sizeof (dl_capability_sub_t);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou bzero(&dld, sizeof (dl_capab_dld_t));
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dld.dld_version = DLD_CURRENT_VERSION;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dld.dld_capab = (uintptr_t)softmac_dld_capab;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dld.dld_capab_handle = (uintptr_t)sup;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dlcapabsetqid(&(dld.dld_mid), sup->su_rq);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou bcopy(&dld, ptr, sizeof (dl_capab_dld_t));
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou ptr += sizeof (dl_capab_dld_t);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * TCP/IP checksum offload.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (hcksum_capable) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dl_capab_hcksum_t hcksum;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dlsp = (dl_capability_sub_t *)ptr;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dlsp->dl_cap = DL_CAPAB_HCKSUM;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dlsp->dl_length = sizeof (dl_capab_hcksum_t);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou ptr += sizeof (dl_capability_sub_t);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou bzero(&hcksum, sizeof (dl_capab_hcksum_t));
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou hcksum.hcksum_version = HCKSUM_VERSION_1;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou hcksum.hcksum_txflags = softmac->smac_hcksum_txflags;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dlcapabsetqid(&(hcksum.hcksum_mid), sup->su_rq);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou bcopy(&hcksum, ptr, sizeof (dl_capab_hcksum_t));
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou ptr += sizeof (dl_capab_hcksum_t);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Zero copy
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (zcopy_capable) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dl_capab_zerocopy_t zcopy;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dlsp = (dl_capability_sub_t *)ptr;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dlsp->dl_cap = DL_CAPAB_ZEROCOPY;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dlsp->dl_length = sizeof (dl_capab_zerocopy_t);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou ptr += sizeof (dl_capability_sub_t);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou bzero(&zcopy, sizeof (dl_capab_zerocopy_t));
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou zcopy.zerocopy_version = ZEROCOPY_VERSION_1;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou zcopy.zerocopy_flags = DL_CAPAB_VMSAFE_MEM;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dlcapabsetqid(&(zcopy.zerocopy_mid), sup->su_rq);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou bcopy(&zcopy, ptr, sizeof (dl_capab_zerocopy_t));
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou ptr += sizeof (dl_capab_zerocopy_t);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * MDT
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (mdt_capable) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dl_capab_mdt_t mdt;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dlsp = (dl_capability_sub_t *)ptr;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dlsp->dl_cap = DL_CAPAB_MDT;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dlsp->dl_length = sizeof (dl_capab_mdt_t);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou ptr += sizeof (dl_capability_sub_t);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou bzero(&mdt, sizeof (dl_capab_mdt_t));
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mdt.mdt_version = MDT_VERSION_2;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mdt.mdt_flags = DL_CAPAB_MDT_ENABLE;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mdt.mdt_hdr_head = softmac->smac_mdt_capab.mdt_hdr_head;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mdt.mdt_hdr_tail = softmac->smac_mdt_capab.mdt_hdr_tail;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mdt.mdt_max_pld = softmac->smac_mdt_capab.mdt_max_pld;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mdt.mdt_span_limit = softmac->smac_mdt_capab.mdt_span_limit;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dlcapabsetqid(&(mdt.mdt_mid), sup->su_rq);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou bcopy(&mdt, ptr, sizeof (dl_capab_mdt_t));
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou ptr += sizeof (dl_capab_mdt_t);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou ASSERT(ptr == mp->b_rptr + sizeof (dl_capability_ack_t) + subsize);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou qreply(q, mp);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou}
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhoustatic void
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhousoftmac_capability_req(softmac_upper_t *sup, mblk_t *mp)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou{
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dl_capability_req_t *dlp = (dl_capability_req_t *)mp->b_rptr;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dl_capability_sub_t *sp;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou size_t size, len;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou offset_t off, end;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou t_uscalar_t dl_err;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou queue_t *q = sup->su_wq;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou ASSERT(sup->su_mode == SOFTMAC_FASTPATH);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (MBLKL(mp) < sizeof (dl_capability_req_t)) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dl_err = DL_BADPRIM;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou goto failed;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (!sup->su_bound) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dl_err = DL_OUTSTATE;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou goto failed;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * This request is overloaded. If there are no requested capabilities
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * then we just want to acknowledge with all the capabilities we
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * support. Otherwise we enable the set of capabilities requested.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (dlp->dl_sub_length == 0) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac_capability_advertise(sup, mp);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (!MBLKIN(mp, dlp->dl_sub_offset, dlp->dl_sub_length)) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dl_err = DL_BADPRIM;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou goto failed;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dlp->dl_primitive = DL_CAPABILITY_ACK;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou off = dlp->dl_sub_offset;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou len = dlp->dl_sub_length;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Walk the list of capabilities to be enabled.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou for (end = off + len; off < end; ) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou sp = (dl_capability_sub_t *)(mp->b_rptr + off);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou size = sizeof (dl_capability_sub_t) + sp->dl_length;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (off + size > end ||
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou !IS_P2ALIGNED(off, sizeof (uint32_t))) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dl_err = DL_BADPRIM;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou goto failed;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou switch (sp->dl_cap) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * TCP/IP checksum offload to hardware.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou case DL_CAPAB_HCKSUM: {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dl_capab_hcksum_t *hcksump;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dl_capab_hcksum_t hcksum;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou hcksump = (dl_capab_hcksum_t *)&sp[1];
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Copy for alignment.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou bcopy(hcksump, &hcksum, sizeof (dl_capab_hcksum_t));
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dlcapabsetqid(&(hcksum.hcksum_mid), sup->su_rq);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou bcopy(&hcksum, hcksump, sizeof (dl_capab_hcksum_t));
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou break;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou default:
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou break;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou off += size;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou qreply(q, mp);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhoufailed:
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dlerrorack(q, mp, DL_CAPABILITY_REQ, dl_err, 0);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou}
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhoustatic void
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhousoftmac_bind_req(softmac_upper_t *sup, mblk_t *mp)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou{
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac_lower_t *slp = sup->su_slp;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac_t *softmac = sup->su_softmac;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mblk_t *ackmp, *mp1;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou int err;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (MBLKL(mp) < DL_BIND_REQ_SIZE) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou freemsg(mp);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Allocate ackmp incase the underlying driver does not ack timely.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if ((mp1 = allocb(sizeof (dl_error_ack_t), BPRI_HI)) == NULL) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dlerrorack(sup->su_wq, mp, DL_BIND_REQ, DL_SYSERR, ENOMEM);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou err = softmac_output(slp, mp, DL_BIND_REQ, DL_BIND_ACK, &ackmp);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (ackmp != NULL) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou freemsg(mp1);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou } else {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * The driver does not ack timely.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou ASSERT(err == ENOMSG);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou ackmp = mp1;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (err != 0)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou goto failed;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Enable capabilities the underlying driver claims to support.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if ((err = softmac_capab_enable(slp)) != 0)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou goto failed;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Check whether this softmac is already marked as exclusively used,
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * e.g., an aggregation is created over it. Fail the BIND_REQ if so.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_enter(&softmac->smac_active_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (softmac->smac_active) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_exit(&softmac->smac_active_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou err = EBUSY;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou goto failed;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac->smac_nactive++;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou sup->su_active = B_TRUE;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_exit(&softmac->smac_active_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou sup->su_bound = B_TRUE;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou qreply(sup->su_wq, ackmp);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhoufailed:
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (err != 0) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dlerrorack(sup->su_wq, ackmp, DL_BIND_REQ, DL_SYSERR, err);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou}
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhoustatic void
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhousoftmac_unbind_req(softmac_upper_t *sup, mblk_t *mp)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou{
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac_lower_t *slp = sup->su_slp;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac_t *softmac = sup->su_softmac;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mblk_t *ackmp, *mp1;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou int err;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (MBLKL(mp) < DL_UNBIND_REQ_SIZE) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou freemsg(mp);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (!sup->su_bound) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dlerrorack(sup->su_wq, mp, DL_UNBIND_REQ, DL_OUTSTATE, 0);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Allocate ackmp incase the underlying driver does not ack timely.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if ((mp1 = allocb(sizeof (dl_error_ack_t), BPRI_HI)) == NULL) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dlerrorack(sup->su_wq, mp, DL_UNBIND_REQ, DL_SYSERR, ENOMEM);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou err = softmac_output(slp, mp, DL_UNBIND_REQ, DL_OK_ACK, &ackmp);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (ackmp != NULL) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou freemsg(mp1);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou } else {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * The driver does not ack timely.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou ASSERT(err == ENOMSG);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou ackmp = mp1;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (err != 0) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dlerrorack(sup->su_wq, ackmp, DL_UNBIND_REQ, DL_SYSERR, err);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou sup->su_bound = B_FALSE;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_enter(&softmac->smac_active_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (sup->su_active) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou ASSERT(!softmac->smac_active);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac->smac_nactive--;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou sup->su_active = B_FALSE;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_exit(&softmac->smac_active_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhoudone:
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou qreply(sup->su_wq, ackmp);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou}
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou/*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Process the non-data mblk.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhoustatic void
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhousoftmac_wput_single_nondata(softmac_upper_t *sup, mblk_t *mp)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou{
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac_t *softmac = sup->su_softmac;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac_lower_t *slp = sup->su_slp;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou unsigned char dbtype;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou t_uscalar_t prim;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dbtype = DB_TYPE(mp);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark sup->su_is_arp = 0;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou switch (dbtype) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark case M_CTL:
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark sup->su_is_arp = 1;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark /* FALLTHROUGH */
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark case M_IOCTL: {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou uint32_t expected_mode;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (((struct iocblk *)(mp->b_rptr))->ioc_cmd != SIOCSLIFNAME)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou break;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Nak the M_IOCTL based on the STREAMS specification.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (dbtype == M_IOCTL)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou miocnak(sup->su_wq, mp, 0, EINVAL);
f1956ffef55a0f859d3974677c90c728e3fc32f5Cathy Zhou else
f1956ffef55a0f859d3974677c90c728e3fc32f5Cathy Zhou freemsg(mp);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * This stream is either IP or ARP. See whether
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * we need to setup a dedicated-lower-stream for it.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_enter(&softmac->smac_fp_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou expected_mode = DATAPATH_MODE(softmac);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (expected_mode == SOFTMAC_SLOWPATH)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou sup->su_mode = SOFTMAC_SLOWPATH;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou list_insert_head(&softmac->smac_sup_list, sup);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_exit(&softmac->smac_fp_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Setup the fast-path dedicated lower stream if fast-path
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * is expected. Note that no lock is held here, and if
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * smac_expected_mode is changed from SOFTMAC_FASTPATH to
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * SOFTMAC_SLOWPATH, the DL_NOTE_REPLUMB message used for
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * data-path switching would already be queued and will
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * be processed by softmac_wput_single_nondata() later.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (expected_mode == SOFTMAC_FASTPATH)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou (void) softmac_fastpath_setup(sup);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou case M_PROTO:
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou case M_PCPROTO:
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (MBLKL(mp) < sizeof (t_uscalar_t)) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou freemsg(mp);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou prim = ((union DL_primitives *)mp->b_rptr)->dl_primitive;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou switch (prim) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou case DL_NOTIFY_IND:
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (MBLKL(mp) < sizeof (dl_notify_ind_t) ||
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou ((dl_notify_ind_t *)mp->b_rptr)->dl_notification !=
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou DL_NOTE_REPLUMB) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou freemsg(mp);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * This DL_NOTE_REPLUMB message is initiated
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * and queued by the softmac itself, when the
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * sup is trying to switching its datapath mode
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * between SOFTMAC_SLOWPATH and SOFTMAC_FASTPATH.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Send this message upstream.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou qreply(sup->su_wq, mp);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou case DL_NOTIFY_CONF:
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (MBLKL(mp) < sizeof (dl_notify_conf_t) ||
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou ((dl_notify_conf_t *)mp->b_rptr)->dl_notification !=
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou DL_NOTE_REPLUMB_DONE) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou freemsg(mp);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * This is an indication from IP/ARP that the
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * fastpath->slowpath switch is done.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou freemsg(mp);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac_datapath_switch_done(sup);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou break;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * No need to hold lock to check su_mode, since su_mode updating only
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * operation is is serialized by softmac_wput_nondata_task().
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (sup->su_mode != SOFTMAC_FASTPATH) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dld_wput(sup->su_wq, mp);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Fastpath non-data message processing. Most of non-data messages
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * can be directly passed down to the dedicated-lower-stream, aside
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * from the following M_PROTO/M_PCPROTO messages.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou switch (dbtype) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou case M_PROTO:
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou case M_PCPROTO:
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou switch (prim) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou case DL_BIND_REQ:
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac_bind_req(sup, mp);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou break;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou case DL_UNBIND_REQ:
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac_unbind_req(sup, mp);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou break;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou case DL_CAPABILITY_REQ:
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac_capability_req(sup, mp);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou break;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou default:
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou putnext(slp->sl_wq, mp);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou break;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou break;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou default:
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou putnext(slp->sl_wq, mp);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou break;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou}
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou/*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * The worker thread which processes non-data messages. Note we only process
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * one message at one time in order to be able to "flush" the queued message
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * and serialize the processing.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhoustatic void
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhousoftmac_wput_nondata_task(void *arg)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou{
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac_upper_t *sup = arg;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mblk_t *mp;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_enter(&sup->su_disp_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou while (sup->su_pending_head != NULL) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (sup->su_closing)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou break;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou SOFTMAC_DQ_PENDING(sup, &mp);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_exit(&sup->su_disp_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac_wput_single_nondata(sup, mp);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_enter(&sup->su_disp_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * If the stream is closing, flush all queued messages and inform
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * the stream to be closed.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou freemsgchain(sup->su_pending_head);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou sup->su_pending_head = sup->su_pending_tail = NULL;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou sup->su_dlpi_pending = B_FALSE;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou cv_signal(&sup->su_disp_cv);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_exit(&sup->su_disp_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou}
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou/*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Kernel thread to handle taskq dispatch failures in softmac_wput_nondata().
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * This thread is started when the softmac module is first loaded.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhoustatic void
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhousoftmac_taskq_dispatch(void)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou{
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou callb_cpr_t cprinfo;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac_upper_t *sup;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou CALLB_CPR_INIT(&cprinfo, &softmac_taskq_lock, callb_generic_cpr,
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou "softmac_taskq_dispatch");
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_enter(&softmac_taskq_lock);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou while (!softmac_taskq_quit) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou sup = list_head(&softmac_taskq_list);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou while (sup != NULL) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou list_remove(&softmac_taskq_list, sup);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou sup->su_taskq_scheduled = B_FALSE;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_exit(&softmac_taskq_lock);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou VERIFY(taskq_dispatch(system_taskq,
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac_wput_nondata_task, sup, TQ_SLEEP) != NULL);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_enter(&softmac_taskq_lock);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou sup = list_head(&softmac_taskq_list);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou CALLB_CPR_SAFE_BEGIN(&cprinfo);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou cv_wait(&softmac_taskq_cv, &softmac_taskq_lock);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou CALLB_CPR_SAFE_END(&cprinfo, &softmac_taskq_lock);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac_taskq_done = B_TRUE;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou cv_signal(&softmac_taskq_cv);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou CALLB_CPR_EXIT(&cprinfo);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou thread_exit();
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou}
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhouvoid
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhousoftmac_wput_nondata(softmac_upper_t *sup, mblk_t *mp)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou{
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * The processing of the message might block. Enqueue the
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * message for later processing.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_enter(&sup->su_disp_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (sup->su_closing) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_exit(&sup->su_disp_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou freemsg(mp);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou SOFTMAC_EQ_PENDING(sup, mp);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (sup->su_dlpi_pending) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_exit(&sup->su_disp_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou sup->su_dlpi_pending = B_TRUE;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_exit(&sup->su_disp_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (taskq_dispatch(system_taskq, softmac_wput_nondata_task,
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou sup, TQ_NOSLEEP) != NULL) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_enter(&softmac_taskq_lock);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (!sup->su_taskq_scheduled) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou list_insert_tail(&softmac_taskq_list, sup);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou cv_signal(&softmac_taskq_cv);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou sup->su_taskq_scheduled = B_TRUE;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_exit(&softmac_taskq_lock);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou}
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou/*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Setup the dedicated-lower-stream (fast-path) for the IP/ARP upperstream.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhoustatic int
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhousoftmac_fastpath_setup(softmac_upper_t *sup)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou{
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac_t *softmac = sup->su_softmac;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac_lower_t *slp;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou int err;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou err = softmac_lower_setup(softmac, sup, &slp);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_enter(&sup->su_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Wait for all data messages to be processed so that we can change
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * the su_mode.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou while (sup->su_tx_inprocess != 0)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou cv_wait(&sup->su_cv, &sup->su_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou ASSERT(sup->su_mode != SOFTMAC_FASTPATH);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou ASSERT(sup->su_slp == NULL);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (err != 0) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou sup->su_mode = SOFTMAC_SLOWPATH;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou } else {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou sup->su_slp = slp;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou sup->su_mode = SOFTMAC_FASTPATH;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_exit(&sup->su_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return (err);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou}
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou/*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Tear down the dedicated-lower-stream (fast-path) for the IP/ARP upperstream.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhoustatic void
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhousoftmac_fastpath_tear(softmac_upper_t *sup)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou{
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_enter(&sup->su_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Wait for all data messages in the dedicated-lower-stream
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * to be processed.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou while (sup->su_tx_inprocess != 0)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou cv_wait(&sup->su_cv, &sup->su_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou /*
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou * Note that this function is called either when the stream is closed,
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou * or the stream is unbound (fastpath-slowpath-switch). Therefore,
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou * No need to call the tx_notify callback.
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou */
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou sup->su_tx_notify_func = NULL;
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou sup->su_tx_notify_arg = NULL;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (sup->su_tx_busy) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou ASSERT(sup->su_tx_flow_mp == NULL);
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou VERIFY((sup->su_tx_flow_mp = getq(sup->su_wq)) != NULL);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou sup->su_tx_busy = B_FALSE;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou sup->su_mode = SOFTMAC_SLOWPATH;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Destroy the dedicated-lower-stream. Note that slp is destroyed
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * when lh is closed.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou (void) ldi_close(sup->su_slp->sl_lh, FREAD|FWRITE, kcred);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou sup->su_slp = NULL;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_exit(&sup->su_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou}
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhouvoid
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhousoftmac_wput_data(softmac_upper_t *sup, mblk_t *mp)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou{
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * No lock is required to access the su_mode field since the data
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * traffic is quiesce by IP when the data-path mode is in the
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * process of switching.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (sup->su_mode != SOFTMAC_FASTPATH)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dld_wput(sup->su_wq, mp);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou else
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou (void) softmac_fastpath_wput_data(sup, mp, NULL, 0);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou}
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou/*ARGSUSED*/
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhoustatic mac_tx_cookie_t
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhousoftmac_fastpath_wput_data(softmac_upper_t *sup, mblk_t *mp, uintptr_t f_hint,
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou uint16_t flag)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou{
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou queue_t *wq = sup->su_slp->sl_wq;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * This function is called from IP, only the MAC_DROP_ON_NO_DESC
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * flag can be specified.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou ASSERT((flag & ~MAC_DROP_ON_NO_DESC) == 0);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou ASSERT(mp->b_next == NULL);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Check wether the dedicated-lower-stream is able to handle more
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * messages, and enable the flow-control if it is not.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou *
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Note that in order not to introduce any packet reordering, we
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * always send the message down to the dedicated-lower-stream:
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou *
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * If the flow-control is already enabled, but we still get
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * the messages from the upper-stream, it means that the upper
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * stream does not respect STREAMS flow-control (e.g., TCP). Simply
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * pass the message down to the lower-stream in that case.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (SOFTMAC_CANPUTNEXT(wq)) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou putnext(wq, mp);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return (NULL);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (sup->su_tx_busy) {
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou if ((flag & MAC_DROP_ON_NO_DESC) != 0)
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou freemsg(mp);
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou else
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou putnext(wq, mp);
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou return ((mac_tx_cookie_t)sup);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_enter(&sup->su_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (!sup->su_tx_busy) {
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou /*
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou * If DLD_CAPAB_DIRECT is enabled, the notify callback will be
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou * called when the flow control can be disabled. Otherwise,
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou * put the tx_flow_mp into the wq to make use of the old
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou * streams flow control.
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou ASSERT(sup->su_tx_flow_mp != NULL);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou (void) putq(sup->su_wq, sup->su_tx_flow_mp);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou sup->su_tx_flow_mp = NULL;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou sup->su_tx_busy = B_TRUE;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou qenable(wq);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_exit(&sup->su_mutex);
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou if ((flag & MAC_DROP_ON_NO_DESC) != 0)
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou freemsg(mp);
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou else
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou putnext(wq, mp);
79eeb64527c881659e23b60088c32ae3736a7a2cCathy Zhou return ((mac_tx_cookie_t)sup);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou}
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhouboolean_t
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhousoftmac_active_set(void *arg)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou{
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac_t *softmac = arg;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_enter(&softmac->smac_active_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (softmac->smac_nactive != 0) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_exit(&softmac->smac_active_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return (B_FALSE);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac->smac_active = B_TRUE;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_exit(&softmac->smac_active_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return (B_TRUE);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou}
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhouvoid
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhousoftmac_active_clear(void *arg)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou{
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac_t *softmac = arg;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_enter(&softmac->smac_active_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou ASSERT(softmac->smac_active && (softmac->smac_nactive == 0));
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac->smac_active = B_FALSE;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_exit(&softmac->smac_active_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou}
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou/*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Disable/reenable fastpath on given softmac. This request could come from a
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * MAC client or directly from administrators.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhouint
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhousoftmac_datapath_switch(softmac_t *softmac, boolean_t disable, boolean_t admin)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou{
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac_upper_t *sup;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mblk_t *head = NULL, *tail = NULL, *mp;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou list_t reqlist;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac_switch_req_t *req;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou uint32_t current_mode, expected_mode;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou int err = 0;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_enter(&softmac->smac_fp_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou current_mode = DATAPATH_MODE(softmac);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (admin) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (softmac->smac_fastpath_admin_disabled == disable) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_exit(&softmac->smac_fp_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return (0);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac->smac_fastpath_admin_disabled = disable;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou } else if (disable) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac->smac_fp_disable_clients++;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou } else {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou ASSERT(softmac->smac_fp_disable_clients != 0);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac->smac_fp_disable_clients--;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou expected_mode = DATAPATH_MODE(softmac);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (current_mode == expected_mode) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_exit(&softmac->smac_fp_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return (0);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * The expected mode is different from whatever datapath mode
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * this softmac is expected from last request, enqueue the data-path
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * switch request.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou list_create(&reqlist, sizeof (softmac_switch_req_t),
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou offsetof(softmac_switch_req_t, ssq_req_list_node));
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Allocate all DL_NOTIFY_IND messages and request structures that
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * are required to switch each IP/ARP stream to the expected mode.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou for (sup = list_head(&softmac->smac_sup_list); sup != NULL;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou sup = list_next(&softmac->smac_sup_list, sup)) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dl_notify_ind_t *dlip;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou req = kmem_alloc(sizeof (softmac_switch_req_t), KM_NOSLEEP);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (req == NULL)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou break;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou req->ssq_expected_mode = expected_mode;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (sup->su_is_arp) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark list_insert_tail(&reqlist, req);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark continue;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Allocate the DL_NOTE_REPLUMB message.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if ((mp = allocb(sizeof (dl_notify_ind_t), BPRI_LO)) == NULL) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou kmem_free(req, sizeof (softmac_switch_req_t));
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou break;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou list_insert_tail(&reqlist, req);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mp->b_wptr = mp->b_rptr + sizeof (dl_notify_ind_t);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mp->b_datap->db_type = M_PROTO;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou bzero(mp->b_rptr, sizeof (dl_notify_ind_t));
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dlip = (dl_notify_ind_t *)mp->b_rptr;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dlip->dl_primitive = DL_NOTIFY_IND;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou dlip->dl_notification = DL_NOTE_REPLUMB;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (head == NULL) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou head = tail = mp;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou } else {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou tail->b_next = mp;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou tail = mp;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Note that it is fine if the expected data-path mode is fast-path
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * and some of streams fails to switch. Only return failure if we
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * are expected to switch to the slow-path.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (sup != NULL && expected_mode == SOFTMAC_SLOWPATH) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou err = ENOMEM;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou goto fail;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Start switching for each IP/ARP stream. The switching operation
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * will eventually succeed and there is no need to wait for it
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * to finish.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou for (sup = list_head(&softmac->smac_sup_list); sup != NULL;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou sup = list_next(&softmac->smac_sup_list, sup)) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark if (!sup->su_is_arp) {
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark mp = head->b_next;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark head->b_next = NULL;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark softmac_wput_nondata(sup, head);
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark head = mp;
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
bd670b35a010421b6e1a5536c34453a827007c81Erik Nordmark * Add the switch request to the requests list of the stream.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou req = list_head(&reqlist);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou ASSERT(req != NULL);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou list_remove(&reqlist, req);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou list_insert_tail(&sup->su_req_list, req);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_exit(&softmac->smac_fp_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou ASSERT(list_is_empty(&reqlist));
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou list_destroy(&reqlist);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return (0);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhoufail:
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (admin) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac->smac_fastpath_admin_disabled = !disable;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou } else if (disable) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac->smac_fp_disable_clients--;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou } else {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac->smac_fp_disable_clients++;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_exit(&softmac->smac_fp_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou while ((req = list_head(&reqlist)) != NULL) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou list_remove(&reqlist, req);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou kmem_free(req, sizeof (softmac_switch_req_t));
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou freemsgchain(head);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou list_destroy(&reqlist);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return (err);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou}
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhouint
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhousoftmac_fastpath_disable(void *arg)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou{
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return (softmac_datapath_switch((softmac_t *)arg, B_TRUE, B_FALSE));
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou}
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhouvoid
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhousoftmac_fastpath_enable(void *arg)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou{
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou VERIFY(softmac_datapath_switch((softmac_t *)arg, B_FALSE,
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou B_FALSE) == 0);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou}
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhouvoid
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhousoftmac_upperstream_close(softmac_upper_t *sup)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou{
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac_t *softmac = sup->su_softmac;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac_switch_req_t *req;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_enter(&softmac->smac_fp_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (sup->su_mode == SOFTMAC_FASTPATH)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac_fastpath_tear(sup);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (sup->su_mode != SOFTMAC_UNKNOWN) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou list_remove(&softmac->smac_sup_list, sup);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou sup->su_mode = SOFTMAC_UNKNOWN;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Cleanup all the switch requests queueed on this stream.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou while ((req = list_head(&sup->su_req_list)) != NULL) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou list_remove(&sup->su_req_list, req);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou kmem_free(req, sizeof (softmac_switch_req_t));
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_exit(&softmac->smac_fp_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou}
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou/*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * Handle the DL_NOTE_REPLUMB_DONE indication from IP/ARP. Change the upper
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * stream from the fastpath mode to the slowpath mode.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhoustatic void
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhousoftmac_datapath_switch_done(softmac_upper_t *sup)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou{
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac_t *softmac = sup->su_softmac;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac_switch_req_t *req;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou uint32_t expected_mode;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_enter(&softmac->smac_fp_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou req = list_head(&sup->su_req_list);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou list_remove(&sup->su_req_list, req);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou expected_mode = req->ssq_expected_mode;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou kmem_free(req, sizeof (softmac_switch_req_t));
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (expected_mode == sup->su_mode) {
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_exit(&softmac->smac_fp_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou return;
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou }
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou ASSERT(!sup->su_bound);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou mutex_exit(&softmac->smac_fp_mutex);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou /*
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * It is fine if the expected mode is fast-path and we fail
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou * to enable fastpath on this stream.
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou */
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou if (expected_mode == SOFTMAC_SLOWPATH)
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou softmac_fastpath_tear(sup);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou else
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou (void) softmac_fastpath_setup(sup);
5d460eafffba936e81c4dd5ebe0f59b238f09121Cathy Zhou}