1*da14cebeSEric Cheng /* 2*da14cebeSEric Cheng * CDDL HEADER START 3*da14cebeSEric Cheng * 4*da14cebeSEric Cheng * The contents of this file are subject to the terms of the 5*da14cebeSEric Cheng * Common Development and Distribution License (the "License"). 6*da14cebeSEric Cheng * You may not use this file except in compliance with the License. 7*da14cebeSEric Cheng * 8*da14cebeSEric Cheng * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*da14cebeSEric Cheng * or http://www.opensolaris.org/os/licensing. 10*da14cebeSEric Cheng * See the License for the specific language governing permissions 11*da14cebeSEric Cheng * and limitations under the License. 12*da14cebeSEric Cheng * 13*da14cebeSEric Cheng * When distributing Covered Code, include this CDDL HEADER in each 14*da14cebeSEric Cheng * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*da14cebeSEric Cheng * If applicable, add the following below this CDDL HEADER, with the 16*da14cebeSEric Cheng * fields enclosed by brackets "[]" replaced with your own identifying 17*da14cebeSEric Cheng * information: Portions Copyright [yyyy] [name of copyright owner] 18*da14cebeSEric Cheng * 19*da14cebeSEric Cheng * CDDL HEADER END 20*da14cebeSEric Cheng */ 21*da14cebeSEric Cheng 22*da14cebeSEric Cheng /* 23*da14cebeSEric Cheng * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24*da14cebeSEric Cheng * Use is subject to license terms. 25*da14cebeSEric Cheng */ 26*da14cebeSEric Cheng 27*da14cebeSEric Cheng #ifndef _SYS_MAC_SOFT_RING_H 28*da14cebeSEric Cheng #define _SYS_MAC_SOFT_RING_H 29*da14cebeSEric Cheng 30*da14cebeSEric Cheng #ifdef __cplusplus 31*da14cebeSEric Cheng extern "C" { 32*da14cebeSEric Cheng #endif 33*da14cebeSEric Cheng 34*da14cebeSEric Cheng #include <sys/types.h> 35*da14cebeSEric Cheng #include <sys/cpuvar.h> 36*da14cebeSEric Cheng #include <sys/processor.h> 37*da14cebeSEric Cheng #include <sys/stream.h> 38*da14cebeSEric Cheng #include <sys/squeue.h> 39*da14cebeSEric Cheng #include <sys/dlpi.h> 40*da14cebeSEric Cheng #include <sys/mac_impl.h> 41*da14cebeSEric Cheng 42*da14cebeSEric Cheng #define S_RING_NAMELEN 64 43*da14cebeSEric Cheng 44*da14cebeSEric Cheng #define MAX_SR_FANOUT 32 45*da14cebeSEric Cheng 46*da14cebeSEric Cheng extern boolean_t mac_soft_ring_enable; 47*da14cebeSEric Cheng extern boolean_t mac_latency_optimize; 48*da14cebeSEric Cheng 49*da14cebeSEric Cheng typedef struct mac_soft_ring_s mac_soft_ring_t; 50*da14cebeSEric Cheng typedef struct mac_soft_ring_set_s mac_soft_ring_set_t; 51*da14cebeSEric Cheng 52*da14cebeSEric Cheng typedef void (*mac_soft_ring_drain_func_t)(mac_soft_ring_t *); 53*da14cebeSEric Cheng typedef mac_tx_cookie_t (*mac_tx_func_t)(mac_soft_ring_set_t *, mblk_t *, 54*da14cebeSEric Cheng uintptr_t, uint16_t, mblk_t **); 55*da14cebeSEric Cheng 56*da14cebeSEric Cheng 57*da14cebeSEric Cheng /* Tx notify callback */ 58*da14cebeSEric Cheng typedef struct mac_tx_notify_cb_s { 59*da14cebeSEric Cheng mac_cb_t mtnf_link; /* Linked list of callbacks */ 60*da14cebeSEric Cheng mac_tx_notify_t mtnf_fn; /* The callback function */ 61*da14cebeSEric Cheng void *mtnf_arg; /* Callback function argument */ 62*da14cebeSEric Cheng } mac_tx_notify_cb_t; 63*da14cebeSEric Cheng 64*da14cebeSEric Cheng struct mac_soft_ring_s { 65*da14cebeSEric Cheng /* Keep the most used members 64bytes cache aligned */ 66*da14cebeSEric Cheng kmutex_t s_ring_lock; /* lock before using any member */ 67*da14cebeSEric Cheng uint16_t s_ring_type; /* processing model of the sq */ 68*da14cebeSEric Cheng uint16_t s_ring_state; /* state flags and message count */ 69*da14cebeSEric Cheng int s_ring_count; /* # of mblocks in mac_soft_ring */ 70*da14cebeSEric Cheng size_t s_ring_size; /* Size of data queued */ 71*da14cebeSEric Cheng mblk_t *s_ring_first; /* first mblk chain or NULL */ 72*da14cebeSEric Cheng mblk_t *s_ring_last; /* last mblk chain or NULL */ 73*da14cebeSEric Cheng 74*da14cebeSEric Cheng mac_direct_rx_t s_ring_rx_func; 75*da14cebeSEric Cheng void *s_ring_rx_arg1; 76*da14cebeSEric Cheng mac_resource_handle_t s_ring_rx_arg2; 77*da14cebeSEric Cheng 78*da14cebeSEric Cheng /* 79*da14cebeSEric Cheng * Threshold after which packets get dropped. 80*da14cebeSEric Cheng * Is always greater than s_ring_tx_hiwat 81*da14cebeSEric Cheng */ 82*da14cebeSEric Cheng int s_ring_tx_max_q_cnt; 83*da14cebeSEric Cheng /* # of mblocks after which to apply flow control */ 84*da14cebeSEric Cheng int s_ring_tx_hiwat; 85*da14cebeSEric Cheng /* # of mblocks after which to relieve flow control */ 86*da14cebeSEric Cheng int s_ring_tx_lowat; 87*da14cebeSEric Cheng boolean_t s_ring_tx_woken_up; 88*da14cebeSEric Cheng uint32_t s_ring_blocked_cnt; /* times blocked for Tx descs */ 89*da14cebeSEric Cheng uint32_t s_ring_unblocked_cnt; /* unblock calls from driver */ 90*da14cebeSEric Cheng uint32_t s_ring_hiwat_cnt; /* times blocked for Tx descs */ 91*da14cebeSEric Cheng 92*da14cebeSEric Cheng void *s_ring_tx_arg1; 93*da14cebeSEric Cheng void *s_ring_tx_arg2; 94*da14cebeSEric Cheng 95*da14cebeSEric Cheng /* Tx notify callback */ 96*da14cebeSEric Cheng mac_cb_info_t s_ring_notify_cb_info; /* cb list info */ 97*da14cebeSEric Cheng mac_cb_t *s_ring_notify_cb_list; /* The cb list */ 98*da14cebeSEric Cheng 99*da14cebeSEric Cheng clock_t s_ring_awaken; /* time async thread was awakened */ 100*da14cebeSEric Cheng 101*da14cebeSEric Cheng kthread_t *s_ring_run; /* Current thread processing sq */ 102*da14cebeSEric Cheng processorid_t s_ring_cpuid; /* processor to bind to */ 103*da14cebeSEric Cheng processorid_t s_ring_cpuid_save; /* saved cpuid during offline */ 104*da14cebeSEric Cheng kcondvar_t s_ring_async; /* async thread blocks on */ 105*da14cebeSEric Cheng clock_t s_ring_wait; /* lbolts to wait after a fill() */ 106*da14cebeSEric Cheng timeout_id_t s_ring_tid; /* timer id of pending timeout() */ 107*da14cebeSEric Cheng kthread_t *s_ring_worker; /* kernel thread id */ 108*da14cebeSEric Cheng char s_ring_name[S_RING_NAMELEN + 1]; 109*da14cebeSEric Cheng uint32_t s_ring_total_inpkt; 110*da14cebeSEric Cheng uint32_t s_ring_drops; 111*da14cebeSEric Cheng struct mac_client_impl_s *s_ring_mcip; 112*da14cebeSEric Cheng void *s_ring_flent; 113*da14cebeSEric Cheng kstat_t *s_ring_ksp; 114*da14cebeSEric Cheng 115*da14cebeSEric Cheng /* Teardown, poll disable control ops */ 116*da14cebeSEric Cheng kcondvar_t s_ring_client_cv; /* Client wait for control op */ 117*da14cebeSEric Cheng 118*da14cebeSEric Cheng mac_soft_ring_set_t *s_ring_set; /* The SRS this ring belongs to */ 119*da14cebeSEric Cheng mac_soft_ring_t *s_ring_next; 120*da14cebeSEric Cheng mac_soft_ring_t *s_ring_prev; 121*da14cebeSEric Cheng mac_soft_ring_drain_func_t s_ring_drain_func; 122*da14cebeSEric Cheng }; 123*da14cebeSEric Cheng 124*da14cebeSEric Cheng typedef void (*mac_srs_drain_proc_t)(mac_soft_ring_set_t *, uint_t); 125*da14cebeSEric Cheng 126*da14cebeSEric Cheng /* Transmit side Soft Ring Set */ 127*da14cebeSEric Cheng typedef struct mac_srs_tx_s { 128*da14cebeSEric Cheng /* Members for Tx size processing */ 129*da14cebeSEric Cheng uint32_t st_mode; 130*da14cebeSEric Cheng mac_tx_func_t st_func; 131*da14cebeSEric Cheng void *st_arg1; 132*da14cebeSEric Cheng void *st_arg2; 133*da14cebeSEric Cheng mac_group_t *st_group; /* TX group for share */ 134*da14cebeSEric Cheng boolean_t st_woken_up; 135*da14cebeSEric Cheng 136*da14cebeSEric Cheng /* 137*da14cebeSEric Cheng * st_max_q_cnt is the queue depth threshold to limit 138*da14cebeSEric Cheng * outstanding packets on the Tx SRS. Once the limit 139*da14cebeSEric Cheng * is reached, Tx SRS will drop packets until the 140*da14cebeSEric Cheng * limit goes below the threshold. 141*da14cebeSEric Cheng */ 142*da14cebeSEric Cheng uint32_t st_max_q_cnt; /* max. outstanding packets */ 143*da14cebeSEric Cheng /* 144*da14cebeSEric Cheng * st_hiwat is used Tx serializer and bandwidth mode. 145*da14cebeSEric Cheng * This is the queue depth threshold upto which 146*da14cebeSEric Cheng * packets will get buffered with no flow-control 147*da14cebeSEric Cheng * back pressure applied to the caller. Once this 148*da14cebeSEric Cheng * threshold is reached, back pressure will be 149*da14cebeSEric Cheng * applied to the caller of mac_tx() (mac_tx() starts 150*da14cebeSEric Cheng * returning a cookie to indicate a blocked SRS). 151*da14cebeSEric Cheng * st_hiwat should always be lesser than or equal to 152*da14cebeSEric Cheng * st_max_q_cnt. 153*da14cebeSEric Cheng */ 154*da14cebeSEric Cheng uint32_t st_hiwat; /* mblk cnt to apply flow control */ 155*da14cebeSEric Cheng uint32_t st_lowat; /* mblk cnt to relieve flow control */ 156*da14cebeSEric Cheng uint32_t st_drop_count; 157*da14cebeSEric Cheng /* 158*da14cebeSEric Cheng * Number of times the srs gets blocked due to lack of Tx 159*da14cebeSEric Cheng * desc is noted down. Corresponding wakeup from driver 160*da14cebeSEric Cheng * to unblock is also noted down. They should match in a 161*da14cebeSEric Cheng * correctly working setup. If there is less unblocks 162*da14cebeSEric Cheng * than blocks, then Tx side waits forever for a wakeup 163*da14cebeSEric Cheng * from below. The following protected by srs_lock. 164*da14cebeSEric Cheng */ 165*da14cebeSEric Cheng uint32_t st_blocked_cnt; /* times blocked for Tx descs */ 166*da14cebeSEric Cheng uint32_t st_unblocked_cnt; /* unblock calls from driver */ 167*da14cebeSEric Cheng uint32_t st_hiwat_cnt; /* times blocked for Tx descs */ 168*da14cebeSEric Cheng } mac_srs_tx_t; 169*da14cebeSEric Cheng 170*da14cebeSEric Cheng /* Receive side Soft Ring Set */ 171*da14cebeSEric Cheng typedef struct mac_srs_rx_s { 172*da14cebeSEric Cheng /* 173*da14cebeSEric Cheng * Upcall Function for fanout, Rx processing etc. Perhaps 174*da14cebeSEric Cheng * the same 3 members below can be used for Tx 175*da14cebeSEric Cheng * processing, but looking around, mac_rx_func_t has 176*da14cebeSEric Cheng * proliferated too much into various files at different 177*da14cebeSEric Cheng * places. I am leaving the consolidation battle for 178*da14cebeSEric Cheng * another day. 179*da14cebeSEric Cheng */ 180*da14cebeSEric Cheng mac_direct_rx_t sr_func; /* srs_lock */ 181*da14cebeSEric Cheng void *sr_arg1; /* srs_lock */ 182*da14cebeSEric Cheng mac_resource_handle_t sr_arg2; /* srs_lock */ 183*da14cebeSEric Cheng mac_rx_func_t sr_lower_proc; /* Atomically changed */ 184*da14cebeSEric Cheng boolean_t sr_enqueue_always; /* enqueue at soft ring */ 185*da14cebeSEric Cheng uint32_t sr_poll_pkt_cnt; 186*da14cebeSEric Cheng uint32_t sr_poll_thres; 187*da14cebeSEric Cheng 188*da14cebeSEric Cheng /* mblk cnt to apply flow control */ 189*da14cebeSEric Cheng uint32_t sr_hiwat; 190*da14cebeSEric Cheng /* mblk cnt to relieve flow control */ 191*da14cebeSEric Cheng uint32_t sr_lowat; 192*da14cebeSEric Cheng uint32_t sr_poll_count; 193*da14cebeSEric Cheng uint32_t sr_intr_count; 194*da14cebeSEric Cheng uint32_t sr_drop_count; 195*da14cebeSEric Cheng 196*da14cebeSEric Cheng /* Times polling was enabled */ 197*da14cebeSEric Cheng uint32_t sr_poll_on; 198*da14cebeSEric Cheng /* Times polling was enabled by worker thread */ 199*da14cebeSEric Cheng uint32_t sr_worker_poll_on; 200*da14cebeSEric Cheng /* Times polling was disabled */ 201*da14cebeSEric Cheng uint32_t sr_poll_off; 202*da14cebeSEric Cheng /* Poll thread signalled count */ 203*da14cebeSEric Cheng uint32_t sr_poll_thr_sig; 204*da14cebeSEric Cheng /* Poll thread busy */ 205*da14cebeSEric Cheng uint32_t sr_poll_thr_busy; 206*da14cebeSEric Cheng /* SRS drains, stays in poll mode but doesn't poll */ 207*da14cebeSEric Cheng uint32_t sr_poll_drain_no_poll; 208*da14cebeSEric Cheng /* 209*da14cebeSEric Cheng * SRS has nothing to do and no packets in H/W but 210*da14cebeSEric Cheng * there is a backlog in softrings. SRS stays in 211*da14cebeSEric Cheng * poll mode but doesn't do polling. 212*da14cebeSEric Cheng */ 213*da14cebeSEric Cheng uint32_t sr_poll_no_poll; 214*da14cebeSEric Cheng /* Active polling restarted */ 215*da14cebeSEric Cheng uint32_t sr_below_hiwat; 216*da14cebeSEric Cheng /* Found packets in last poll so try and poll again */ 217*da14cebeSEric Cheng uint32_t sr_poll_again; 218*da14cebeSEric Cheng /* 219*da14cebeSEric Cheng * Packets in queue but poll thread not allowed to process so 220*da14cebeSEric Cheng * signal the worker thread. 221*da14cebeSEric Cheng */ 222*da14cebeSEric Cheng uint32_t sr_poll_sig_worker; 223*da14cebeSEric Cheng /* 224*da14cebeSEric Cheng * Poll thread has nothing to do and H/W has nothing so 225*da14cebeSEric Cheng * reenable the interrupts. 226*da14cebeSEric Cheng */ 227*da14cebeSEric Cheng uint32_t sr_poll_intr_enable; 228*da14cebeSEric Cheng /* 229*da14cebeSEric Cheng * Poll thread has nothing to do and worker thread was already 230*da14cebeSEric Cheng * running so it can decide to reenable interrupt or poll again. 231*da14cebeSEric Cheng */ 232*da14cebeSEric Cheng uint32_t sr_poll_goto_sleep; 233*da14cebeSEric Cheng /* Worker thread goes back to draining the queue */ 234*da14cebeSEric Cheng uint32_t sr_drain_again; 235*da14cebeSEric Cheng /* More Packets in queue so signal the worker thread to drain */ 236*da14cebeSEric Cheng uint32_t sr_drain_worker_sig; 237*da14cebeSEric Cheng /* Poll thread is already running so worker has nothing to do */ 238*da14cebeSEric Cheng uint32_t sr_drain_poll_running; 239*da14cebeSEric Cheng /* We have packets already queued so keep polling */ 240*da14cebeSEric Cheng uint32_t sr_drain_keep_polling; 241*da14cebeSEric Cheng /* Drain is done and interrupts are reenabled */ 242*da14cebeSEric Cheng uint32_t sr_drain_finish_intr; 243*da14cebeSEric Cheng /* Polling thread needs to schedule worker wakeup */ 244*da14cebeSEric Cheng uint32_t sr_poll_worker_wakeup; 245*da14cebeSEric Cheng 246*da14cebeSEric Cheng /* Chains less than 10 pkts */ 247*da14cebeSEric Cheng uint32_t sr_chain_cnt_undr10; 248*da14cebeSEric Cheng /* Chains between 10 & 50 pkts */ 249*da14cebeSEric Cheng uint32_t sr_chain_cnt_10to50; 250*da14cebeSEric Cheng /* Chains over 50 pkts */ 251*da14cebeSEric Cheng uint32_t sr_chain_cnt_over50; 252*da14cebeSEric Cheng } mac_srs_rx_t; 253*da14cebeSEric Cheng 254*da14cebeSEric Cheng /* 255*da14cebeSEric Cheng * mac_soft_ring_set_s: 256*da14cebeSEric Cheng * This is used both for Tx and Rx side. The srs_type identifies Rx or 257*da14cebeSEric Cheng * Tx type. 258*da14cebeSEric Cheng * 259*da14cebeSEric Cheng * Note that the structure is carefully crafted, with Rx elements coming 260*da14cebeSEric Cheng * first followed by Tx specific members. Future additions to this 261*da14cebeSEric Cheng * structure should follow the same guidelines. 262*da14cebeSEric Cheng * 263*da14cebeSEric Cheng * Rx-side notes: 264*da14cebeSEric Cheng * mac_rx_classify_flow_add() always creates a mac_soft_ring_set_t and fn_flow 265*da14cebeSEric Cheng * points to info from it (func = srs_lower_proc, arg = soft_ring_set). On 266*da14cebeSEric Cheng * interrupt path, srs_lower_proc does B/W adjustment and switch to polling mode 267*da14cebeSEric Cheng * (if poll capable) and feeds the packets to soft_ring_list via choosen 268*da14cebeSEric Cheng * fanout type (specified by srs_type). In poll mode, the poll thread which is 269*da14cebeSEric Cheng * also a pointer can pick up the packets and feed them to various 270*da14cebeSEric Cheng * soft_ring_list. 271*da14cebeSEric Cheng * 272*da14cebeSEric Cheng * The srs_type can either be protocol based or fanout based where fanout itelf 273*da14cebeSEric Cheng * can be various types 274*da14cebeSEric Cheng * 275*da14cebeSEric Cheng * The polling works by turning off interrupts as soon as a packets 276*da14cebeSEric Cheng * are queued on the soft ring set. Once the backlog is clear and poll 277*da14cebeSEric Cheng * thread return empty handed i.e. Rx ring doesn't have anything, the 278*da14cebeSEric Cheng * interrupt is turned back on. For this purpose we keep a separate 279*da14cebeSEric Cheng * srs_poll_pkt_cnt counter which tracks the packets queued between SRS 280*da14cebeSEric Cheng * and the soft rings as well. The counter is incremented when packets 281*da14cebeSEric Cheng * are queued and decremented when SRS processes them (in case it has 282*da14cebeSEric Cheng * no soft rings) or the soft ring process them. Its important that 283*da14cebeSEric Cheng * in case SRS has softrings, the decrement doesn't happen till the 284*da14cebeSEric Cheng * packet is processed by the soft rings since it takes very little time 285*da14cebeSEric Cheng * for SRS to queue packet from SRS to soft rings and it will keep 286*da14cebeSEric Cheng * bringing more packets in the system faster than soft rings can 287*da14cebeSEric Cheng * process them. 288*da14cebeSEric Cheng * 289*da14cebeSEric Cheng * Tx side notes: 290*da14cebeSEric Cheng * The srs structure acts as a serializer with a worker thread. The 291*da14cebeSEric Cheng * default behavior of srs though is to act as a pass-thru. The queues 292*da14cebeSEric Cheng * (srs_first, srs_last, srs_count) get used when Tx ring runs out of Tx 293*da14cebeSEric Cheng * descriptors or to enforce bandwidth limits. 294*da14cebeSEric Cheng * 295*da14cebeSEric Cheng * When multiple Tx rings are present, the SRS state will be set to 296*da14cebeSEric Cheng * SRS_FANOUT_OTH. Outgoing packets coming into mac_tx_srs_process() 297*da14cebeSEric Cheng * function will be fanned out to one of the Tx side soft rings based on 298*da14cebeSEric Cheng * a hint passed in mac_tx_srs_process(). Each soft ring, in turn, will 299*da14cebeSEric Cheng * be associated with a distinct h/w Tx ring. 300*da14cebeSEric Cheng */ 301*da14cebeSEric Cheng 302*da14cebeSEric Cheng struct mac_soft_ring_set_s { 303*da14cebeSEric Cheng /* 304*da14cebeSEric Cheng * Common elements, common to both Rx and Tx SRS type. 305*da14cebeSEric Cheng * The following block of fields are protected by srs_lock 306*da14cebeSEric Cheng */ 307*da14cebeSEric Cheng kmutex_t srs_lock; 308*da14cebeSEric Cheng uint32_t srs_type; 309*da14cebeSEric Cheng uint32_t srs_state; /* state flags */ 310*da14cebeSEric Cheng uint32_t srs_count; 311*da14cebeSEric Cheng mblk_t *srs_first; /* first mblk chain or NULL */ 312*da14cebeSEric Cheng mblk_t *srs_last; /* last mblk chain or NULL */ 313*da14cebeSEric Cheng kcondvar_t srs_async; /* cv for worker thread */ 314*da14cebeSEric Cheng kcondvar_t srs_cv; /* cv for poll thread */ 315*da14cebeSEric Cheng kcondvar_t srs_quiesce_done_cv; /* cv for removal */ 316*da14cebeSEric Cheng timeout_id_t srs_tid; /* timeout id for pending timeout */ 317*da14cebeSEric Cheng 318*da14cebeSEric Cheng /* 319*da14cebeSEric Cheng * List of soft rings & processing function. 320*da14cebeSEric Cheng * The following block is protected by Rx quiescence. 321*da14cebeSEric Cheng * i.e. they can be changed only after quiescing the SRS 322*da14cebeSEric Cheng * Protected by srs_lock. 323*da14cebeSEric Cheng */ 324*da14cebeSEric Cheng mac_soft_ring_t *srs_soft_ring_head; 325*da14cebeSEric Cheng mac_soft_ring_t *srs_soft_ring_tail; 326*da14cebeSEric Cheng int srs_soft_ring_count; 327*da14cebeSEric Cheng int srs_soft_ring_quiesced_count; 328*da14cebeSEric Cheng int srs_soft_ring_condemned_count; 329*da14cebeSEric Cheng mac_soft_ring_t **srs_tcp_soft_rings; 330*da14cebeSEric Cheng int srs_tcp_ring_count; 331*da14cebeSEric Cheng mac_soft_ring_t **srs_udp_soft_rings; 332*da14cebeSEric Cheng int srs_udp_ring_count; 333*da14cebeSEric Cheng /* 334*da14cebeSEric Cheng * srs_oth_soft_rings is also used by tx_srs in 335*da14cebeSEric Cheng * when operating in multi tx ring mode. 336*da14cebeSEric Cheng */ 337*da14cebeSEric Cheng mac_soft_ring_t **srs_oth_soft_rings; 338*da14cebeSEric Cheng int srs_oth_ring_count; 339*da14cebeSEric Cheng 340*da14cebeSEric Cheng /* 341*da14cebeSEric Cheng * Bandwidth control related members. 342*da14cebeSEric Cheng * They are common to both Rx- and Tx-side. 343*da14cebeSEric Cheng * Following protected by srs_lock 344*da14cebeSEric Cheng */ 345*da14cebeSEric Cheng mac_bw_ctl_t *srs_bw; 346*da14cebeSEric Cheng size_t srs_size; /* Size of packets queued in bytes */ 347*da14cebeSEric Cheng pri_t srs_pri; 348*da14cebeSEric Cheng 349*da14cebeSEric Cheng mac_soft_ring_set_t *srs_next; /* mac_srs_g_lock */ 350*da14cebeSEric Cheng mac_soft_ring_set_t *srs_prev; /* mac_srs_g_lock */ 351*da14cebeSEric Cheng 352*da14cebeSEric Cheng /* Attribute specific drain func (BW ctl vs non-BW ctl) */ 353*da14cebeSEric Cheng mac_srs_drain_proc_t srs_drain_func; /* Write once (WO) */ 354*da14cebeSEric Cheng 355*da14cebeSEric Cheng /* 356*da14cebeSEric Cheng * If the associated ring is exclusively used by a mac client, e.g., 357*da14cebeSEric Cheng * an aggregation, this fields is used to keep a reference to the 358*da14cebeSEric Cheng * MAC client's pseudo ring. 359*da14cebeSEric Cheng */ 360*da14cebeSEric Cheng mac_resource_handle_t srs_mrh; 361*da14cebeSEric Cheng /* 362*da14cebeSEric Cheng * The following blocks are write once (WO) and valid for the life 363*da14cebeSEric Cheng * of the SRS 364*da14cebeSEric Cheng */ 365*da14cebeSEric Cheng struct mac_client_impl_s *srs_mcip; /* back ptr to mac client */ 366*da14cebeSEric Cheng void *srs_flent; /* back ptr to flent */ 367*da14cebeSEric Cheng mac_ring_t *srs_ring; /* Ring Descriptor */ 368*da14cebeSEric Cheng 369*da14cebeSEric Cheng /* Teardown, disable control ops */ 370*da14cebeSEric Cheng kcondvar_t srs_client_cv; /* Client wait for the control op */ 371*da14cebeSEric Cheng 372*da14cebeSEric Cheng kthread_t *srs_worker; /* WO, worker thread */ 373*da14cebeSEric Cheng kthread_t *srs_poll_thr; /* WO, poll thread */ 374*da14cebeSEric Cheng 375*da14cebeSEric Cheng uint_t srs_ind; /* Round Robin indx for picking up SR */ 376*da14cebeSEric Cheng processorid_t srs_worker_cpuid; /* processor to bind to */ 377*da14cebeSEric Cheng processorid_t srs_worker_cpuid_save; /* saved cpuid during offline */ 378*da14cebeSEric Cheng processorid_t srs_poll_cpuid; /* processor to bind to */ 379*da14cebeSEric Cheng processorid_t srs_poll_cpuid_save; /* saved cpuid during offline */ 380*da14cebeSEric Cheng uint_t srs_fanout_state; 381*da14cebeSEric Cheng mac_cpus_t srs_cpu; 382*da14cebeSEric Cheng 383*da14cebeSEric Cheng mac_srs_rx_t srs_rx; 384*da14cebeSEric Cheng mac_srs_tx_t srs_tx; 385*da14cebeSEric Cheng }; 386*da14cebeSEric Cheng 387*da14cebeSEric Cheng /* 388*da14cebeSEric Cheng * type flags - combination allowed to process and drain the queue 389*da14cebeSEric Cheng */ 390*da14cebeSEric Cheng #define ST_RING_WORKER_ONLY 0x0001 /* Worker thread only */ 391*da14cebeSEric Cheng #define ST_RING_ANY 0x0002 /* Any thread can process the queue */ 392*da14cebeSEric Cheng #define ST_RING_TCP 0x0004 393*da14cebeSEric Cheng #define ST_RING_UDP 0x0008 394*da14cebeSEric Cheng #define ST_RING_OTH 0x0010 395*da14cebeSEric Cheng 396*da14cebeSEric Cheng #define ST_RING_BW_CTL 0x0020 397*da14cebeSEric Cheng #define ST_RING_TX 0x0040 398*da14cebeSEric Cheng 399*da14cebeSEric Cheng /* 400*da14cebeSEric Cheng * State flags. 401*da14cebeSEric Cheng */ 402*da14cebeSEric Cheng #define S_RING_PROC 0x0001 /* being processed */ 403*da14cebeSEric Cheng #define S_RING_BOUND 0x0002 /* Worker thread is bound to a cpu */ 404*da14cebeSEric Cheng #define S_RING_BLOCK 0x0004 /* No Tx descs */ 405*da14cebeSEric Cheng #define S_RING_TX_HIWAT 0x0008 /* Tx high watermark reached */ 406*da14cebeSEric Cheng 407*da14cebeSEric Cheng #define S_RING_WAKEUP_CLIENT 0x0010 /* flow ctrl, client wakeup needed */ 408*da14cebeSEric Cheng #define S_RING_BLANK 0x0020 /* Has been put into polling mode */ 409*da14cebeSEric Cheng #define S_RING_CLIENT_WAIT 0x0040 /* Client waiting for control op */ 410*da14cebeSEric Cheng 411*da14cebeSEric Cheng #define S_RING_CONDEMNED 0x0100 /* Being torn down */ 412*da14cebeSEric Cheng #define S_RING_CONDEMNED_DONE 0x0200 /* Being torn down */ 413*da14cebeSEric Cheng #define S_RING_QUIESCE 0x0400 /* No traffic flow, transient flag */ 414*da14cebeSEric Cheng #define S_RING_QUIESCE_DONE 0x0800 /* No traffic flow, transient flag */ 415*da14cebeSEric Cheng 416*da14cebeSEric Cheng #define S_RING_RESTART 0x1000 /* Go back to normal traffic flow */ 417*da14cebeSEric Cheng #define S_RING_ENQUEUED 0x2000 /* Pkts enqueued in Tx soft ring */ 418*da14cebeSEric Cheng 419*da14cebeSEric Cheng /* 420*da14cebeSEric Cheng * arguments for processors to bind to 421*da14cebeSEric Cheng */ 422*da14cebeSEric Cheng #define S_RING_BIND_NONE -1 423*da14cebeSEric Cheng 424*da14cebeSEric Cheng /* 425*da14cebeSEric Cheng * defines for srs_type - identifies a link or a sub-flow 426*da14cebeSEric Cheng * and other static characteristics of a SRS like a tx 427*da14cebeSEric Cheng * srs, tcp only srs, etc. 428*da14cebeSEric Cheng */ 429*da14cebeSEric Cheng #define SRST_LINK 0x00000001 430*da14cebeSEric Cheng #define SRST_FLOW 0x00000002 431*da14cebeSEric Cheng #define SRST_NO_SOFT_RINGS 0x00000004 432*da14cebeSEric Cheng #define SRST_TCP_ONLY 0x00000008 433*da14cebeSEric Cheng 434*da14cebeSEric Cheng #define SRST_FANOUT_PROTO 0x00000010 435*da14cebeSEric Cheng #define SRST_FANOUT_SRC_IP 0x00000020 436*da14cebeSEric Cheng #define SRST_FANOUT_OTH 0x00000040 437*da14cebeSEric Cheng #define SRST_DEFAULT_GRP 0x00000080 438*da14cebeSEric Cheng 439*da14cebeSEric Cheng #define SRST_TX 0x00000100 440*da14cebeSEric Cheng #define SRST_BW_CONTROL 0x00000200 441*da14cebeSEric Cheng #define SRST_DIRECT_POLL 0x00000400 442*da14cebeSEric Cheng 443*da14cebeSEric Cheng #define SRST_DLS_BYPASS 0x00001000 444*da14cebeSEric Cheng #define SRST_CLIENT_POLL_ENABLED 0x00002000 445*da14cebeSEric Cheng 446*da14cebeSEric Cheng /* 447*da14cebeSEric Cheng * soft ring set flags. These bits are dynamic in nature and get 448*da14cebeSEric Cheng * applied to srs_state. They reflect the state of SRS at any 449*da14cebeSEric Cheng * point of time 450*da14cebeSEric Cheng */ 451*da14cebeSEric Cheng #define SRS_BLANK 0x00000001 452*da14cebeSEric Cheng #define SRS_WORKER_BOUND 0x00000002 453*da14cebeSEric Cheng #define SRS_POLL_BOUND 0x00000004 454*da14cebeSEric Cheng #define SRS_POLLING_CAPAB 0x00000008 455*da14cebeSEric Cheng 456*da14cebeSEric Cheng #define SRS_PROC 0x00000010 457*da14cebeSEric Cheng #define SRS_GET_PKTS 0x00000020 458*da14cebeSEric Cheng #define SRS_POLLING 0x00000040 459*da14cebeSEric Cheng #define SRS_BW_ENFORCED 0x00000080 460*da14cebeSEric Cheng 461*da14cebeSEric Cheng #define SRS_WORKER 0x00000100 462*da14cebeSEric Cheng #define SRS_ENQUEUED 0x00000200 463*da14cebeSEric Cheng #define SRS_ANY_PROCESS 0x00000400 464*da14cebeSEric Cheng #define SRS_PROC_FAST 0x00000800 465*da14cebeSEric Cheng 466*da14cebeSEric Cheng #define SRS_POLL_PROC 0x00001000 467*da14cebeSEric Cheng #define SRS_TX_BLOCKED 0x00002000 /* out of Tx descs */ 468*da14cebeSEric Cheng #define SRS_TX_HIWAT 0x00004000 /* Tx count exceeds hiwat */ 469*da14cebeSEric Cheng #define SRS_TX_WAKEUP_CLIENT 0x00008000 /* Flow-ctl: wakeup client */ 470*da14cebeSEric Cheng 471*da14cebeSEric Cheng #define SRS_CLIENT_PROC 0x00010000 472*da14cebeSEric Cheng #define SRS_CLIENT_WAIT 0x00020000 473*da14cebeSEric Cheng #define SRS_QUIESCE 0x00040000 474*da14cebeSEric Cheng #define SRS_QUIESCE_DONE 0x00080000 475*da14cebeSEric Cheng 476*da14cebeSEric Cheng #define SRS_CONDEMNED 0x00100000 477*da14cebeSEric Cheng #define SRS_CONDEMNED_DONE 0x00200000 478*da14cebeSEric Cheng #define SRS_POLL_THR_QUIESCED 0x00400000 479*da14cebeSEric Cheng #define SRS_RESTART 0x00800000 480*da14cebeSEric Cheng 481*da14cebeSEric Cheng #define SRS_RESTART_DONE 0x01000000 482*da14cebeSEric Cheng #define SRS_POLL_THR_RESTART 0x02000000 483*da14cebeSEric Cheng #define SRS_IN_GLIST 0x04000000 484*da14cebeSEric Cheng #define SRS_POLL_THR_EXITED 0x08000000 485*da14cebeSEric Cheng 486*da14cebeSEric Cheng #define SRS_QUIESCE_PERM 0x10000000 487*da14cebeSEric Cheng #define SRS_LATENCY_OPT 0x20000000 488*da14cebeSEric Cheng 489*da14cebeSEric Cheng #define SRS_QUIESCED(srs) (srs->srs_state & SRS_QUIESCE_DONE) 490*da14cebeSEric Cheng 491*da14cebeSEric Cheng /* 492*da14cebeSEric Cheng * If the SRS_QUIESCE_PERM flag is set, the SRS worker thread will not be 493*da14cebeSEric Cheng * able to be restarted. 494*da14cebeSEric Cheng */ 495*da14cebeSEric Cheng #define SRS_QUIESCED_PERMANENT(srs) (srs->srs_state & SRS_QUIESCE_PERM) 496*da14cebeSEric Cheng 497*da14cebeSEric Cheng /* 498*da14cebeSEric Cheng * soft ring set (SRS) Tx modes 499*da14cebeSEric Cheng */ 500*da14cebeSEric Cheng typedef enum { 501*da14cebeSEric Cheng SRS_TX_DEFAULT = 0, 502*da14cebeSEric Cheng SRS_TX_SERIALIZE, 503*da14cebeSEric Cheng SRS_TX_FANOUT, 504*da14cebeSEric Cheng SRS_TX_BW, 505*da14cebeSEric Cheng SRS_TX_BW_FANOUT 506*da14cebeSEric Cheng } mac_tx_srs_mode_t; 507*da14cebeSEric Cheng 508*da14cebeSEric Cheng /* 509*da14cebeSEric Cheng * SRS fanout states 510*da14cebeSEric Cheng */ 511*da14cebeSEric Cheng typedef enum { 512*da14cebeSEric Cheng SRS_FANOUT_UNINIT = 0, 513*da14cebeSEric Cheng SRS_FANOUT_INIT, 514*da14cebeSEric Cheng SRS_FANOUT_REINIT 515*da14cebeSEric Cheng } mac_srs_fanout_state_t; 516*da14cebeSEric Cheng 517*da14cebeSEric Cheng /* 518*da14cebeSEric Cheng * Structure for dls statistics 519*da14cebeSEric Cheng */ 520*da14cebeSEric Cheng struct dls_kstats { 521*da14cebeSEric Cheng kstat_named_t dlss_soft_ring_pkt_drop; 522*da14cebeSEric Cheng }; 523*da14cebeSEric Cheng 524*da14cebeSEric Cheng extern struct dls_kstats dls_kstat; 525*da14cebeSEric Cheng 526*da14cebeSEric Cheng #define DLS_BUMP_STAT(x, y) (dls_kstat.x.value.ui32 += y) 527*da14cebeSEric Cheng 528*da14cebeSEric Cheng /* Turn dynamic polling off */ 529*da14cebeSEric Cheng #define MAC_SRS_POLLING_OFF(mac_srs) { \ 530*da14cebeSEric Cheng ASSERT(MUTEX_HELD(&(mac_srs)->srs_lock)); \ 531*da14cebeSEric Cheng if (((mac_srs)->srs_state & (SRS_POLLING_CAPAB|SRS_POLLING)) == \ 532*da14cebeSEric Cheng (SRS_POLLING_CAPAB|SRS_POLLING)) { \ 533*da14cebeSEric Cheng (mac_srs)->srs_state &= ~SRS_POLLING; \ 534*da14cebeSEric Cheng (void) mac_hwring_enable_intr((mac_ring_handle_t) \ 535*da14cebeSEric Cheng (mac_srs)->srs_ring); \ 536*da14cebeSEric Cheng (mac_srs)->srs_rx.sr_poll_off++; \ 537*da14cebeSEric Cheng } \ 538*da14cebeSEric Cheng } 539*da14cebeSEric Cheng 540*da14cebeSEric Cheng #define MAC_COUNT_CHAIN(mac_srs, head, tail, cnt, sz) { \ 541*da14cebeSEric Cheng mblk_t *tmp; \ 542*da14cebeSEric Cheng boolean_t bw_ctl = B_FALSE; \ 543*da14cebeSEric Cheng \ 544*da14cebeSEric Cheng ASSERT((head) != NULL); \ 545*da14cebeSEric Cheng cnt = 0; \ 546*da14cebeSEric Cheng sz = 0; \ 547*da14cebeSEric Cheng if ((mac_srs)->srs_type & SRST_BW_CONTROL) \ 548*da14cebeSEric Cheng bw_ctl = B_TRUE; \ 549*da14cebeSEric Cheng tmp = tail = (head); \ 550*da14cebeSEric Cheng if ((head)->b_next == NULL) { \ 551*da14cebeSEric Cheng cnt = 1; \ 552*da14cebeSEric Cheng if (bw_ctl) \ 553*da14cebeSEric Cheng sz += msgdsize(head); \ 554*da14cebeSEric Cheng } else { \ 555*da14cebeSEric Cheng while (tmp != NULL) { \ 556*da14cebeSEric Cheng tail = tmp; \ 557*da14cebeSEric Cheng cnt++; \ 558*da14cebeSEric Cheng if (bw_ctl) \ 559*da14cebeSEric Cheng sz += msgdsize(tmp); \ 560*da14cebeSEric Cheng tmp = tmp->b_next; \ 561*da14cebeSEric Cheng } \ 562*da14cebeSEric Cheng } \ 563*da14cebeSEric Cheng } 564*da14cebeSEric Cheng 565*da14cebeSEric Cheng /* 566*da14cebeSEric Cheng * Decrement the cumulative packet count in SRS and its 567*da14cebeSEric Cheng * soft rings. If the srs_poll_pkt_cnt goes below lowat, then check 568*da14cebeSEric Cheng * if if the interface was left in a polling mode and no one 569*da14cebeSEric Cheng * is really processing the queue (to get the interface out 570*da14cebeSEric Cheng * of poll mode). If no one is processing the queue, then 571*da14cebeSEric Cheng * acquire the PROC and signal the poll thread to check the 572*da14cebeSEric Cheng * interface for packets and get the interface back to interrupt 573*da14cebeSEric Cheng * mode if nothing is found. 574*da14cebeSEric Cheng */ 575*da14cebeSEric Cheng #define MAC_UPDATE_SRS_COUNT_LOCKED(mac_srs, cnt) { \ 576*da14cebeSEric Cheng mac_srs_rx_t *srs_rx = &(mac_srs)->srs_rx; \ 577*da14cebeSEric Cheng ASSERT(MUTEX_HELD(&(mac_srs)->srs_lock)); \ 578*da14cebeSEric Cheng \ 579*da14cebeSEric Cheng srs_rx->sr_poll_pkt_cnt -= cnt; \ 580*da14cebeSEric Cheng if ((srs_rx->sr_poll_pkt_cnt <= srs_rx->sr_poll_thres) && \ 581*da14cebeSEric Cheng (((mac_srs)->srs_state & \ 582*da14cebeSEric Cheng (SRS_POLLING|SRS_PROC|SRS_GET_PKTS)) == SRS_POLLING)) \ 583*da14cebeSEric Cheng { \ 584*da14cebeSEric Cheng (mac_srs)->srs_state |= (SRS_PROC|SRS_GET_PKTS); \ 585*da14cebeSEric Cheng cv_signal(&(mac_srs)->srs_cv); \ 586*da14cebeSEric Cheng srs_rx->sr_below_hiwat++; \ 587*da14cebeSEric Cheng } \ 588*da14cebeSEric Cheng } 589*da14cebeSEric Cheng 590*da14cebeSEric Cheng /* 591*da14cebeSEric Cheng * The following two macros are used to update the inbound packet and byte. 592*da14cebeSEric Cheng * count. The packet and byte count reflect the packets and bytes that are 593*da14cebeSEric Cheng * taken out of the SRS's queue, i.e. indicating they are being delivered. 594*da14cebeSEric Cheng * The srs_count and srs_size are updated in different locations as the 595*da14cebeSEric Cheng * srs_size is also used to take into account any bandwidth limits. The 596*da14cebeSEric Cheng * srs_size is updated only when a soft ring, if any, sends a packet up, 597*da14cebeSEric Cheng * as opposed to updating it when the SRS sends a packet to the SR, i.e. 598*da14cebeSEric Cheng * the srs_size reflects the packets in the SRS and SRs. These 599*da14cebeSEric Cheng * macros decrement the srs_size and srs_count and also increment the 600*da14cebeSEric Cheng * ipackets and ibytes stats resp. 601*da14cebeSEric Cheng * 602*da14cebeSEric Cheng * xxx-venu These are done under srs_lock, for now we still update 603*da14cebeSEric Cheng * mci_stat_ibytes/mci_stat_ipackets atomically, need to check if 604*da14cebeSEric Cheng * just updating them would be accurate enough. 605*da14cebeSEric Cheng * 606*da14cebeSEric Cheng * If we are updating these for a sub-flow SRS, then we need to also 607*da14cebeSEric Cheng * updated it's MAC client bandwidth info, if the MAC client is also 608*da14cebeSEric Cheng * bandwidth regulated. 609*da14cebeSEric Cheng */ 610*da14cebeSEric Cheng #define MAC_UPDATE_SRS_SIZE_LOCKED(srs, sz) { \ 611*da14cebeSEric Cheng if ((srs)->srs_type & SRST_BW_CONTROL) { \ 612*da14cebeSEric Cheng mutex_enter(&(srs)->srs_bw->mac_bw_lock); \ 613*da14cebeSEric Cheng (srs)->srs_bw->mac_bw_sz -= (sz); \ 614*da14cebeSEric Cheng (srs)->srs_bw->mac_bw_used += (sz); \ 615*da14cebeSEric Cheng mutex_exit(&(srs)->srs_bw->mac_bw_lock); \ 616*da14cebeSEric Cheng } \ 617*da14cebeSEric Cheng } 618*da14cebeSEric Cheng 619*da14cebeSEric Cheng #define MAC_TX_UPDATE_BW_INFO(srs, sz) { \ 620*da14cebeSEric Cheng (srs)->srs_bw->mac_bw_sz -= (sz); \ 621*da14cebeSEric Cheng (srs)->srs_bw->mac_bw_used += (sz); \ 622*da14cebeSEric Cheng } 623*da14cebeSEric Cheng 624*da14cebeSEric Cheng #define TX_MULTI_RING_MODE(mac_srs) \ 625*da14cebeSEric Cheng ((mac_srs)->srs_tx.st_mode == SRS_TX_FANOUT || \ 626*da14cebeSEric Cheng (mac_srs)->srs_tx.st_mode == SRS_TX_BW_FANOUT) 627*da14cebeSEric Cheng 628*da14cebeSEric Cheng /* Soft ring flags for teardown */ 629*da14cebeSEric Cheng #define SRS_POLL_THR_OWNER (SRS_PROC | SRS_POLLING | SRS_GET_PKTS) 630*da14cebeSEric Cheng #define SRS_PAUSE (SRS_CONDEMNED | SRS_QUIESCE) 631*da14cebeSEric Cheng #define S_RING_PAUSE (S_RING_CONDEMNED | S_RING_QUIESCE) 632*da14cebeSEric Cheng 633*da14cebeSEric Cheng /* Soft rings */ 634*da14cebeSEric Cheng extern void mac_soft_ring_init(void); 635*da14cebeSEric Cheng extern void mac_soft_ring_finish(void); 636*da14cebeSEric Cheng extern void mac_fanout_setup(mac_client_impl_t *, flow_entry_t *, 637*da14cebeSEric Cheng mac_resource_props_t *, mac_direct_rx_t, void *, mac_resource_handle_t); 638*da14cebeSEric Cheng 639*da14cebeSEric Cheng extern void mac_soft_ring_worker_wakeup(mac_soft_ring_t *); 640*da14cebeSEric Cheng extern void mac_soft_ring_blank(void *, time_t, uint_t, int); 641*da14cebeSEric Cheng extern mblk_t *mac_soft_ring_poll(mac_soft_ring_t *, int); 642*da14cebeSEric Cheng extern void mac_soft_ring_destroy(mac_soft_ring_t *); 643*da14cebeSEric Cheng extern void mac_soft_ring_dls_bypass(void *, mac_direct_rx_t, void *); 644*da14cebeSEric Cheng 645*da14cebeSEric Cheng /* Rx SRS */ 646*da14cebeSEric Cheng extern mac_soft_ring_set_t *mac_srs_create(struct mac_client_impl_s *, 647*da14cebeSEric Cheng flow_entry_t *, uint32_t, mac_direct_rx_t, void *, mac_resource_handle_t, 648*da14cebeSEric Cheng mac_ring_t *); 649*da14cebeSEric Cheng extern void mac_srs_free(mac_soft_ring_set_t *); 650*da14cebeSEric Cheng extern void mac_srs_signal(mac_soft_ring_set_t *, uint_t); 651*da14cebeSEric Cheng extern cpu_t *mac_srs_bind(mac_soft_ring_set_t *, processorid_t); 652*da14cebeSEric Cheng 653*da14cebeSEric Cheng extern void mac_srs_change_upcall(void *, mac_direct_rx_t, void *); 654*da14cebeSEric Cheng extern void mac_srs_quiesce_initiate(mac_soft_ring_set_t *); 655*da14cebeSEric Cheng extern void mac_srs_client_poll_enable(struct mac_client_impl_s *, 656*da14cebeSEric Cheng mac_soft_ring_set_t *); 657*da14cebeSEric Cheng extern void mac_srs_client_poll_disable(struct mac_client_impl_s *, 658*da14cebeSEric Cheng mac_soft_ring_set_t *); 659*da14cebeSEric Cheng extern void mac_srs_client_poll_quiesce(struct mac_client_impl_s *, 660*da14cebeSEric Cheng mac_soft_ring_set_t *); 661*da14cebeSEric Cheng extern void mac_srs_client_poll_restart(struct mac_client_impl_s *, 662*da14cebeSEric Cheng mac_soft_ring_set_t *); 663*da14cebeSEric Cheng extern void mac_rx_srs_quiesce(mac_soft_ring_set_t *, uint_t); 664*da14cebeSEric Cheng extern void mac_rx_srs_restart(mac_soft_ring_set_t *); 665*da14cebeSEric Cheng extern void mac_rx_srs_subflow_process(void *, mac_resource_handle_t, mblk_t *, 666*da14cebeSEric Cheng boolean_t); 667*da14cebeSEric Cheng extern void mac_tx_srs_quiesce(mac_soft_ring_set_t *, uint_t); 668*da14cebeSEric Cheng 669*da14cebeSEric Cheng /* Tx SRS, Tx softring */ 670*da14cebeSEric Cheng extern void mac_tx_srs_wakeup(mac_soft_ring_set_t *, mac_ring_handle_t); 671*da14cebeSEric Cheng extern void mac_tx_srs_setup(struct mac_client_impl_s *, 672*da14cebeSEric Cheng flow_entry_t *, uint32_t); 673*da14cebeSEric Cheng extern mac_tx_func_t mac_tx_get_func(uint32_t); 674*da14cebeSEric Cheng extern mblk_t *mac_tx_send(mac_client_handle_t, mac_ring_handle_t, mblk_t *, 675*da14cebeSEric Cheng mac_tx_stats_t *); 676*da14cebeSEric Cheng extern boolean_t mac_tx_srs_ring_present(mac_soft_ring_set_t *, mac_ring_t *); 677*da14cebeSEric Cheng extern void mac_tx_srs_add_ring(mac_soft_ring_set_t *, mac_ring_t *); 678*da14cebeSEric Cheng extern void mac_tx_srs_del_ring(mac_soft_ring_set_t *, mac_ring_t *); 679*da14cebeSEric Cheng extern mac_tx_cookie_t mac_tx_srs_no_desc(mac_soft_ring_set_t *, mblk_t *, 680*da14cebeSEric Cheng uint16_t, mblk_t **); 681*da14cebeSEric Cheng 682*da14cebeSEric Cheng /* Subflow specific stuff */ 683*da14cebeSEric Cheng extern int mac_srs_flow_create(struct mac_client_impl_s *, flow_entry_t *, 684*da14cebeSEric Cheng mac_resource_props_t *, int, int, mac_direct_rx_t); 685*da14cebeSEric Cheng extern void mac_srs_update_bwlimit(flow_entry_t *, mac_resource_props_t *); 686*da14cebeSEric Cheng extern void mac_srs_adjust_subflow_bwlimit(struct mac_client_impl_s *); 687*da14cebeSEric Cheng extern void mac_srs_update_drv(struct mac_client_impl_s *); 688*da14cebeSEric Cheng extern void mac_update_srs_priority(mac_soft_ring_set_t *, pri_t); 689*da14cebeSEric Cheng extern void mac_client_update_classifier(mac_client_impl_t *, boolean_t); 690*da14cebeSEric Cheng 691*da14cebeSEric Cheng extern void mac_soft_ring_intr_enable(void *); 692*da14cebeSEric Cheng extern void mac_soft_ring_intr_disable(void *); 693*da14cebeSEric Cheng extern mac_soft_ring_t *mac_soft_ring_create(int, clock_t, void *, uint16_t, 694*da14cebeSEric Cheng pri_t, mac_client_impl_t *, mac_soft_ring_set_t *, 695*da14cebeSEric Cheng processorid_t, mac_direct_rx_t, void *, mac_resource_handle_t); 696*da14cebeSEric Cheng extern cpu_t *mac_soft_ring_bind(mac_soft_ring_t *, processorid_t); 697*da14cebeSEric Cheng extern void mac_soft_ring_unbind(mac_soft_ring_t *); 698*da14cebeSEric Cheng extern void mac_soft_ring_free(mac_soft_ring_t *, boolean_t); 699*da14cebeSEric Cheng extern void mac_soft_ring_signal(mac_soft_ring_t *, uint_t); 700*da14cebeSEric Cheng extern void mac_rx_soft_ring_process(mac_client_impl_t *, mac_soft_ring_t *, 701*da14cebeSEric Cheng mblk_t *, mblk_t *, int, size_t); 702*da14cebeSEric Cheng extern mac_tx_cookie_t mac_tx_soft_ring_process(mac_soft_ring_t *, 703*da14cebeSEric Cheng mblk_t *, uint16_t, mblk_t **); 704*da14cebeSEric Cheng extern void mac_srs_worker_quiesce(mac_soft_ring_set_t *); 705*da14cebeSEric Cheng extern void mac_srs_worker_restart(mac_soft_ring_set_t *); 706*da14cebeSEric Cheng extern void mac_rx_attach_flow_srs(mac_impl_t *, flow_entry_t *, 707*da14cebeSEric Cheng mac_soft_ring_set_t *, mac_ring_t *, mac_classify_type_t); 708*da14cebeSEric Cheng 709*da14cebeSEric Cheng extern void mac_rx_srs_drain_bw(mac_soft_ring_set_t *, uint_t); 710*da14cebeSEric Cheng extern void mac_rx_srs_drain(mac_soft_ring_set_t *, uint_t); 711*da14cebeSEric Cheng extern void mac_rx_srs_process(void *, mac_resource_handle_t, mblk_t *, 712*da14cebeSEric Cheng boolean_t); 713*da14cebeSEric Cheng extern void mac_srs_worker(mac_soft_ring_set_t *); 714*da14cebeSEric Cheng extern void mac_rx_srs_poll_ring(mac_soft_ring_set_t *); 715*da14cebeSEric Cheng extern void mac_tx_srs_drain(mac_soft_ring_set_t *, uint_t); 716*da14cebeSEric Cheng 717*da14cebeSEric Cheng extern void mac_tx_srs_restart(mac_soft_ring_set_t *); 718*da14cebeSEric Cheng extern void mac_rx_srs_remove(mac_soft_ring_set_t *); 719*da14cebeSEric Cheng 720*da14cebeSEric Cheng #ifdef __cplusplus 721*da14cebeSEric Cheng } 722*da14cebeSEric Cheng #endif 723*da14cebeSEric Cheng 724*da14cebeSEric Cheng #endif /* _SYS_MAC_SOFT_RING_H */ 725