# HG changeset patch # User ml29623 # Date 1175562926 25200 # Node ID e932b8e8ca41fad6b57da24b486fb23df88a61da # Parent 7c819a7ade911ac776ca55f0daba086583ae4d27 6494669 N2 NIU leaf driver: hot lock in nxge_start affecting specweb performance diff -r 7c819a7ade91 -r e932b8e8ca41 usr/src/uts/common/Makefile.files --- a/usr/src/uts/common/Makefile.files Mon Apr 02 17:39:35 2007 -0700 +++ b/usr/src/uts/common/Makefile.files Mon Apr 02 18:15:26 2007 -0700 @@ -1379,7 +1379,8 @@ nxge_hw.o nxge_fzc.o nxge_virtual.o \ nxge_send.o nxge_classify.o nxge_fflp.o \ nxge_fflp_hash.o nxge_ndd.o nxge_kstats.o \ - nxge_zcp.o nxge_fm.o nxge_espc.o + nxge_zcp.o nxge_fm.o nxge_espc.o \ + nxge_serialize.o NXGE_NPI_OBJS = \ npi.o npi_mac.o npi_ipp.o \ diff -r 7c819a7ade91 -r e932b8e8ca41 usr/src/uts/common/io/nxge/nxge_main.c --- a/usr/src/uts/common/io/nxge/nxge_main.c Mon Apr 02 17:39:35 2007 -0700 +++ b/usr/src/uts/common/io/nxge/nxge_main.c Mon Apr 02 18:15:26 2007 -0700 @@ -56,6 +56,7 @@ boolean_t nxge_jumbo_enable = B_FALSE; uint16_t nxge_rcr_timeout = NXGE_RDC_RCR_TIMEOUT; uint16_t nxge_rcr_threshold = NXGE_RDC_RCR_THRESHOLD; +nxge_tx_mode_t nxge_tx_scheme = NXGE_USE_SERIAL; /* * Debugging flags: @@ -2282,6 +2283,7 @@ size_t tx_buf_alloc_size; size_t tx_cntl_alloc_size; uint32_t *num_chunks; /* per dma */ + uint32_t bcopy_thresh; NXGE_DEBUG_MSG((nxgep, MEM_CTL, "==> nxge_alloc_tx_mem_pool")); @@ -2330,7 +2332,12 @@ * (For packet payload over this limit, packets will not be * copied.) */ - tx_buf_alloc_size = (nxge_bcopy_thresh * nxge_tx_ring_size); + if (nxgep->niu_type == N2_NIU) { + bcopy_thresh = TX_BCOPY_SIZE; + } else { + bcopy_thresh = nxge_bcopy_thresh; + } + tx_buf_alloc_size = (bcopy_thresh * nxge_tx_ring_size); /* * Addresses of transmit descriptor ring and the @@ -2378,7 +2385,7 @@ num_chunks[i] = 0; status = nxge_alloc_tx_buf_dma(nxgep, st_tdc, &dma_buf_p[i], tx_buf_alloc_size, - nxge_bcopy_thresh, &num_chunks[i]); + bcopy_thresh, &num_chunks[i]); if (status != NXGE_OK) { break; } diff -r 7c819a7ade91 -r e932b8e8ca41 usr/src/uts/common/io/nxge/nxge_send.c --- a/usr/src/uts/common/io/nxge/nxge_send.c Mon Apr 02 17:39:35 2007 -0700 +++ b/usr/src/uts/common/io/nxge/nxge_send.c Mon Apr 02 18:15:26 2007 -0700 @@ -38,6 +38,7 @@ extern uint32_t nxge_tx_use_bcopy; extern uint32_t nxge_tx_lb_policy; extern uint32_t nxge_no_tx_lb; +extern nxge_tx_mode_t nxge_tx_scheme; typedef struct _mac_tx_hint { uint16_t sap; @@ -223,7 +224,7 @@ * for header. No padding will be used. */ pkt_len = pack_len = boff = TX_PKT_HEADER_SIZE; - if (nxge_tx_use_bcopy) { + if (nxge_tx_use_bcopy && (nxgep->niu_type != N2_NIU)) { bcopy_thresh = (nxge_bcopy_thresh - TX_PKT_HEADER_SIZE); } else { bcopy_thresh = (TX_BCOPY_SIZE - TX_PKT_HEADER_SIZE); @@ -841,11 +842,21 @@ return (status); } +int +nxge_serial_tx(mblk_t *mp, void *arg) +{ + p_tx_ring_t tx_ring_p = (p_tx_ring_t)arg; + p_nxge_t nxgep = tx_ring_p->nxgep; + + return (nxge_start(nxgep, tx_ring_p, mp)); +} + boolean_t nxge_send(p_nxge_t nxgep, mblk_t *mp, p_mac_tx_hint_t hp) { p_tx_ring_t *tx_rings; uint8_t ring_index; + p_tx_ring_t tx_ring_p; NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_send")); @@ -858,10 +869,20 @@ NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_tx_msg: max_tdcs %d " "ring_index %d", nxgep->max_tdcs, ring_index)); - if (nxge_start(nxgep, tx_rings[ring_index], mp)) { - NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_send: failed " - "ring index %d", ring_index)); - return (B_FALSE); + switch (nxge_tx_scheme) { + case NXGE_USE_START: + if (nxge_start(nxgep, tx_rings[ring_index], mp)) { + NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_send: failed " + "ring index %d", ring_index)); + return (B_FALSE); + } + break; + + case NXGE_USE_SERIAL: + default: + tx_ring_p = tx_rings[ring_index]; + nxge_serialize_enter(tx_ring_p->serial, mp); + break; } NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_send: ring index %d", diff -r 7c819a7ade91 -r e932b8e8ca41 usr/src/uts/common/io/nxge/nxge_serialize.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/nxge/nxge_serialize.c Mon Apr 02 18:15:26 2007 -0700 @@ -0,0 +1,406 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" +#include +#include + +uint32_t nxge_maxhrs = MAXHRS; + +extern pri_t maxclsyspri; +extern proc_t p0; + +extern int servicing_interrupt(void); +extern void bzero(void *, size_t); + +#ifdef _KERNEL +static void nxge_onetrack(void *p); +#else +static void *nxge_onetrack(void *p); +#endif + +static int nxge_serial_put(nxge_serialize_t *, void *); +static int nxge_serial_getn(nxge_serialize_t *, mblk_t **, mblk_t **); +static void nxge_serial_ungetn(nxge_serialize_t *, mblk_t *, mblk_t *, int); +static int nxge_freelance(nxge_serialize_t *); +static caddr_t nxge_tx_s_begin(nxge_serialize_t *); +static void nxge_tx_s_end(nxge_serialize_t *); + +nxge_serialize_t * +nxge_serialize_create(int length, onetrack_t *proc, void *cookie) +{ + nxge_serialize_t *p; + + NXGE_DEBUG_MSG((NULL, TX_CTL, + "==> nxge_serialize_create:")); + + p = (nxge_serialize_t *)kmem_alloc(sizeof (nxge_serialize_t), KM_SLEEP); + mutex_init(&p->lock, NULL, MUTEX_DEFAULT, NULL); + mutex_init(&p->serial, NULL, MUTEX_DEFAULT, NULL); + mutex_init(&p->timelock, NULL, MUTEX_DEFAULT, NULL); + cv_init(&p->serial_cv, NULL, CV_DRIVER, NULL); + cv_init(&p->timecv, NULL, CV_DRIVER, NULL); + p->count = 0; + p->cookie = cookie; + p->serialop = proc; + p->owned = 0; + p->head = NULL; + p->tail = NULL; + p->totaltime = 0; + p->totalcount = 0; + /* + * An initial estimate of the avg time spent in the serializer function. + * Any non-zero value is fine. A large value will induce unnecessary + * delays. + */ + p->avg = 1; + p->length = length; + p->s_state = NXGE_TX_STHREAD_RUNNING; + + p->tx_sthread = thread_create(NULL, 0, + nxge_onetrack, p, 0, &p0, TS_RUN, maxclsyspri); + if (p->tx_sthread == NULL) { + cv_destroy(&p->serial_cv); + cv_destroy(&p->timecv); + mutex_destroy(&p->lock); + mutex_destroy(&p->serial); + mutex_destroy(&p->timelock); + kmem_free(p, sizeof (nxge_serialize_t)); + + NXGE_DEBUG_MSG((NULL, TX_CTL, + "<== nxge_serialize_create: (NULL)")); + + return (NULL); + } + + NXGE_DEBUG_MSG((NULL, TX_CTL, + "<== nxge_serialize_create: s %p thread %p", + p, p->tx_sthread)); + + return (p); +} + +void +nxge_serialize_destroy(nxge_serialize_t *p) +{ + int n, i; + mblk_t *mp, *nmp, *t; + + NXGE_DEBUG_MSG((NULL, TX_CTL, + "==> nxge_serialize_destroy: s %p", p)); + if (p == NULL) { + NXGE_DEBUG_MSG((NULL, TX_CTL, + "<== nxge_serialize_destroy:")); + return; + } + + mutex_enter(&p->serial); + p->s_state |= NXGE_TX_STHREAD_DESTROY; + cv_signal(&p->serial_cv); + cv_signal(&p->timecv); + while (p->s_state & NXGE_TX_STHREAD_DESTROY) { + cv_wait(&p->serial_cv, &p->serial); + NXGE_DEBUG_MSG((NULL, TX_CTL, + "==> nxge_serialize_destroy: s %p state %d", + p, p->s_state)); + if (p->s_state & NXGE_TX_STHREAD_EXIT) { + break; + } + } + + NXGE_DEBUG_MSG((NULL, TX_CTL, + "==> nxge_serialize_destroy: s %p state %d", + p, p->s_state)); + + n = nxge_serial_getn(p, &mp, &t); + for (i = 0; i < n; i++) { + NXGE_DEBUG_MSG((NULL, TX_CTL, + "==> nxge_serialize_destroy: s %p mp %p", p, mp)); + + nmp = mp->b_next; + mp->b_next = NULL; + freemsg(mp); + + mp = nmp; + } + + mutex_exit(&p->serial); + + cv_destroy(&p->serial_cv); + cv_destroy(&p->timecv); + mutex_destroy(&p->lock); + mutex_destroy(&p->serial); + mutex_destroy(&p->timelock); + kmem_free(p, sizeof (nxge_serialize_t)); + + NXGE_DEBUG_MSG((NULL, TX_CTL, + "<== nxge_serialize_destroy: s %p", p)); +} + +/* + * Return values: + * 0 means put succeeded + * 1 means we have exclusive access + */ +static int +nxge_serial_put(nxge_serialize_t *p, void *mp) +{ + mblk_t *t; + int r = 0; + int block = 0; + hrtime_t tns; + + NXGE_DEBUG_MSG((NULL, TX_CTL, + "==> nxge_serial_put: s %p mp %p", p, mp)); + + mutex_enter(&p->lock); + /* + * If the time required to drain all the queued up packets + * is greater than a tick, we need to block. + */ + if ((tns = (p->count++) * p->avg) > NXGE_TX_AVG_CNT) { + /* + * Sanity check that we will sleep only for less than ~a second + */ + if (tns > ONESEC) { + p->count--; + mutex_exit(&p->lock); + freemsg(mp); + return (0); + } + block = 1; + } + if (p->owned == 0) { + r = p->owned = 1; + block = 0; + } + if ((t = p->tail) != NULL) { + t->b_next = mp; + p->tail = mp; + } else { + p->head = p->tail = mp; + } + mutex_exit(&p->lock); + + /* + * Block for the number of ticks required to drain half + * the queued up packets - but only if we are not within + * an interrupt thread. + */ + if (block) { + if (!servicing_interrupt()) { + long wait = lbolt + drv_usectohz(tns/NXGE_TX_AVG_RES); + mutex_enter(&p->timelock); + (void) cv_timedwait(&p->timecv, &p->timelock, wait); + mutex_exit(&p->timelock); + } + } + + + return (r); +} + +static int +nxge_serial_getn(nxge_serialize_t *p, mblk_t **head, mblk_t **tail) +{ + int c; + + mutex_enter(&p->lock); + if ((c = p->count) != 0) { + *head = p->head; + *tail = p->tail; + p->head = p->tail = NULL; + p->count = 0; + } else { + p->owned = 0; + } + mutex_exit(&p->lock); + + return (c); +} + +static void +nxge_serial_ungetn(nxge_serialize_t *p, mblk_t *head, mblk_t *tail, int n) +{ + mutex_enter(&p->lock); + if (p->tail != NULL) { + tail->b_next = p->head; + p->head = head; + } else { + p->head = head; + p->tail = tail; + } + p->count += n; + mutex_exit(&p->lock); +} + +#ifdef _KERNEL +static void +#else +static void * +#endif +nxge_onetrack(void *s) +{ + int k, i; + mblk_t *mp, *ignore; + nxge_serialize_t *p = (nxge_serialize_t *)s; + + NXGE_DEBUG_MSG((NULL, TX_CTL, + "==> nxge_onetrack: s %p", s)); + (void) nxge_tx_s_begin(p); + mutex_enter(&p->serial); + while (p->s_state & NXGE_TX_STHREAD_RUNNING) { + CALLB_CPR_SAFE_BEGIN(&p->s_cprinfo); + if (p->s_state & NXGE_TX_STHREAD_DESTROY) { + break; + } + cv_wait(&p->serial_cv, &p->serial); + if (p->s_state & NXGE_TX_STHREAD_DESTROY) { + break; + } + CALLB_CPR_SAFE_END(&p->s_cprinfo, + &p->serial) + while (k = nxge_serial_getn(p, &mp, &ignore)) { + hrtime_t t0 = gethrtime(); + for (i = 0; i < k; i++) { + mblk_t *n = mp->b_next; + mp->b_next = NULL; + + NXGE_DEBUG_MSG((NULL, TX_CTL, + "==> nxge_onetrack: s %p mp %p", s, mp)); + + /* + * The queue is full, block and wait for half of + * it to drain. + */ + while (p->serialop(mp, p->cookie)) { + hrtime_t tns = p->avg * p->length; + long wait = lbolt + + drv_usectohz(tns / NXGE_TX_AVG_RES); + (void) cv_timedwait(&p->timecv, + &p->serial, wait); + } + mp = n; + } + + ASSERT(mp == NULL); + + /* + * Update the total time and count of the serializer + * function and * generate the avg time required to + * process a packet. + */ + p->totaltime += (gethrtime() - t0); + p->totalcount += k; + p->avg = p->totaltime/p->totalcount; + } + } + + mutex_exit(&p->serial); + + NXGE_DEBUG_MSG((NULL, TX_CTL, + "<== nxge_onetrack: s %p", s)); + nxge_tx_s_end(s); +} + + +/* + * Return values: + * 0 : don't need to signal worker + * 1 : worker needs to be signalled + */ +static int +nxge_freelance(nxge_serialize_t *s) +{ + int i, n, c = 0; + mblk_t *mp, *t; + + NXGE_DEBUG_MSG((NULL, TX_CTL, + "==> nxge_freelance: s %p", s)); + while (n = nxge_serial_getn(s, &mp, &t)) { + if ((n > nxge_maxhrs) || ((c += n) > nxge_maxhrs)) { + nxge_serial_ungetn(s, mp, t, n); + return (1); + } + for (i = 0; i < n; i++) { + mblk_t *next = mp->b_next; + mp->b_next = NULL; + if (s->serialop(mp, s->cookie)) { + mp->b_next = next; + nxge_serial_ungetn(s, mp, t, n - i); + return (1); + } + + NXGE_DEBUG_MSG((NULL, TX_CTL, + "==> nxge_freelance: s %p mp %p", s, mp)); + + mp = next; + } + } + NXGE_DEBUG_MSG((NULL, TX_CTL, + "<== nxge_freelance: s %p", s)); + + return (0); +} + +void +nxge_serialize_enter(nxge_serialize_t *s, mblk_t *mp) +{ + if (nxge_serial_put(s, mp)) { + if (nxge_freelance(s)) { + mutex_enter(&s->serial); + cv_signal(&s->serial_cv); + mutex_exit(&s->serial); + } + } +} + +static caddr_t +nxge_tx_s_begin(nxge_serialize_t *s) +{ + CALLB_CPR_INIT(&s->s_cprinfo, &s->serial, + callb_generic_cpr, "nxge_tx_serialize"); + return (s->cookie); +} + +static void +nxge_tx_s_end(nxge_serialize_t *s) +{ + callb_cpr_t cprinfo; + + NXGE_DEBUG_MSG((NULL, TX_CTL, + "==> nxge_tx_s_end: s %p", s)); + cprinfo = s->s_cprinfo; + mutex_enter(&s->serial); + s->s_state |= NXGE_TX_STHREAD_EXIT; + cv_signal(&s->serial_cv); + + CALLB_CPR_EXIT(&cprinfo); + + NXGE_DEBUG_MSG((NULL, TX_CTL, + "<== nxge_tx_s_end: s %p", s)); + + thread_exit(); +} diff -r 7c819a7ade91 -r e932b8e8ca41 usr/src/uts/common/io/nxge/nxge_txdma.c --- a/usr/src/uts/common/io/nxge/nxge_txdma.c Mon Apr 02 17:39:35 2007 -0700 +++ b/usr/src/uts/common/io/nxge/nxge_txdma.c Mon Apr 02 18:15:26 2007 -0700 @@ -51,6 +51,8 @@ extern ddi_dma_attr_t nxge_desc_dma_attr; extern ddi_dma_attr_t nxge_tx_dma_attr; +extern int nxge_serial_tx(mblk_t *mp, void *arg); + static nxge_status_t nxge_map_txdma(p_nxge_t); static void nxge_unmap_txdma(p_nxge_t); @@ -2251,6 +2253,10 @@ KMEM_ZALLOC(sizeof (tx_ring_t), KM_SLEEP); MUTEX_INIT(&tx_ring_p->lock, NULL, MUTEX_DRIVER, (void *)nxgep->interrupt_cookie); + + tx_ring_p->nxgep = nxgep; + tx_ring_p->serial = nxge_serialize_create(nmsgs, + nxge_serial_tx, tx_ring_p); /* * Allocate transmit message rings and handles for packets * not to be copied to premapped buffers. @@ -2334,6 +2340,11 @@ goto nxge_map_txdma_channel_buf_ring_exit; nxge_map_txdma_channel_buf_ring_fail1: + if (tx_ring_p->serial) { + nxge_serialize_destroy(tx_ring_p->serial); + tx_ring_p->serial = NULL; + } + index--; for (; index >= 0; index--) { if (tx_msg_ring[i].dma_handle != NULL) { @@ -2409,6 +2420,11 @@ } } + if (tx_ring_p->serial) { + nxge_serialize_destroy(tx_ring_p->serial); + tx_ring_p->serial = NULL; + } + MUTEX_DESTROY(&tx_ring_p->lock); KMEM_FREE(tx_msg_ring, sizeof (tx_msg_t) * tx_ring_p->tx_ring_size); KMEM_FREE(tx_ring_p, sizeof (tx_ring_t)); diff -r 7c819a7ade91 -r e932b8e8ca41 usr/src/uts/common/sys/nxge/nxge_serialize.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/sys/nxge/nxge_serialize.h Mon Apr 02 18:15:26 2007 -0700 @@ -0,0 +1,142 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SYS_NXGE_NXGE_SERIALIZE_H +#define _SYS_NXGE_NXGE_SERIALIZE_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +#define NXGE_TX_AVG_CNT 200000000 +#define NXGE_TX_AVG_RES 2000 /* sleep at least a tick */ +#define MAXHRS 3 /* # of packets to process */ +#define ONESEC 1000000000 /* one second */ + +#ifdef _KERNEL + +#include +#include +#include +#include +#include +#include + +/* + * Thread state flags + */ +#define NXGE_TX_STHREAD_RUNNING 0x0001 /* thread started */ +#define NXGE_TX_STHREAD_DESTROY 0x0002 /* thread is being destroyed */ +#define NXGE_TX_STHREAD_EXIT 0x0003 /* thread exits */ + +#else + +static int p0 = 0; +#define TS_RUN 0 +static int maxclsyspri = 99; + +#include +#include +#include +#include +#include +typedef void mblk_t; +typedef mutex_t kmutex_t; +typedef cond_t kcondvar_t; + +#define MUTEX_DEFAULT USYNC_THREAD + +#define mutex_init(a, b, c, d) mutex_init(a, b, c) +#define mutex_enter(a) mutex_lock(a) +#define mutex_tryenter(a) mutex_trylock(a) +#define mutex_exit(a) mutex_unlock(a) + +#define cv_init(c, n, t, m) cond_init(c, USYNC_THREAD, NULL) +#define cv_wait(c, m) cond_wait(c, m) +#define cv_signal(c) cond_signal(c) +#define cv_timedwait(c, m, t) cond_timedwait(c, m, &t) + +#define kmem_alloc(a, b) malloc(a) +#define kmem_free(a, b) free(a) + +#define cas32(a, b, c) atomic_cas_32(a, b, c) + +#define thread_create(a, b, c, d, e, f, g, h) \ + thr_create(a, b, c, d, THR_BOUND, NULL) + +#endif + + +typedef int (onetrack_t)(mblk_t *, void *); + +typedef struct { + kmutex_t lock; + int count; + mblk_t *head; + mblk_t *tail; + void *cookie; + onetrack_t *serialop; + int owned; + /* Counter tracks the total time spent in serializer function */ + hrtime_t totaltime; + /* + * Counter tracks the total number of time the serializer + * function was called. + */ + long totalcount; + /* + * Counter maintains the average time spent in the serializer function + * and is derived as (totaltime/totalcount). + */ + int avg; + /* + * The lenght of the queue to which the serializer function + * will append data. + */ + int length; + kcondvar_t serial_cv; + kcondvar_t timecv; + kmutex_t serial; + uint32_t s_state; + boolean_t s_need_signal; + callb_cpr_t s_cprinfo; + kthread_t *tx_sthread; + kmutex_t timelock; +} nxge_serialize_t; + +/* + * Prototypes definitions + */ +nxge_serialize_t *nxge_serialize_create(int, onetrack_t *, void *); +void nxge_serialize_destroy(nxge_serialize_t *); +void nxge_serialize_enter(nxge_serialize_t *, mblk_t *); + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_NXGE_NXGE_SERIALIZE_H */ diff -r 7c819a7ade91 -r e932b8e8ca41 usr/src/uts/common/sys/nxge/nxge_txdma.h --- a/usr/src/uts/common/sys/nxge/nxge_txdma.h Mon Apr 02 17:39:35 2007 -0700 +++ b/usr/src/uts/common/sys/nxge/nxge_txdma.h Mon Apr 02 18:15:26 2007 -0700 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -34,6 +34,7 @@ #include #include +#include #define TXDMA_PORT_BITMAP(nxgep) (nxgep->pt_config.tx_dma_map) @@ -67,6 +68,11 @@ #define TXDMA_DRR_WEIGHT_DEFAULT 0x001f +typedef enum { + NXGE_USE_SERIAL = 0, + NXGE_USE_START, +} nxge_tx_mode_t; + typedef struct _tx_msg_t { nxge_os_block_mv_t flags; /* DMA, BCOPY, DVMA (?) */ nxge_os_dma_common_t buf_dma; /* premapped buffer blocks */ @@ -163,7 +169,7 @@ boolean_t queueing; nxge_os_mutex_t sq_lock; - + nxge_serialize_t *serial; p_mblk_t head; p_mblk_t tail;