Mercurial > illumos > illumos-gate
changeset 10615:4bb212e117c7
6786791 nge needs to have a new tx stall detection mechanism
6871807 nge driver should enable TFINT for tx_recylce
author | Winson Wang - Sun Microsystems - Beijing China <Zhen.W@Sun.COM> |
---|---|
date | Wed, 23 Sep 2009 09:09:49 +0800 |
parents | 4f397871da47 |
children | 3be00c4a6835 |
files | usr/src/uts/common/io/nge/nge.h usr/src/uts/common/io/nge/nge_chip.c usr/src/uts/common/io/nge/nge_main.c usr/src/uts/common/io/nge/nge_tx.c |
diffstat | 4 files changed, 75 insertions(+), 65 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/io/nge/nge.h Tue Sep 22 17:11:54 2009 -0700 +++ b/usr/src/uts/common/io/nge/nge.h Wed Sep 23 09:09:49 2009 +0800 @@ -147,8 +147,7 @@ #define VTAG_SIZE 4 #endif -#define NGE_HALFTICK 268435456LL /* 2**28 ns! */ -#define NGE_CYCLIC_PERIOD (4*NGE_HALFTICK) /* ~0.5s */ +#define NGE_CYCLIC_PERIOD (1000000000) #define NGE_DEFAULT_MTU 1500 #define NGE_DEFAULT_SDU 1518 @@ -191,9 +190,12 @@ #define NGE_MAX_DMA_HDR (4*1024) /* Used by interrupt moderation */ +#define NGE_TFINT_DEFAULT 32 +#define NGE_POLL_TUNE 80000 +#define NGE_POLL_ENTER 10000 +#define NGE_POLL_MAX 1280000 #define NGE_POLL_QUIET_TIME 100 #define NGE_POLL_BUSY_TIME 2 -#define NGE_TX_N_INTR 128 /* * NGE-specific ioctls ... @@ -655,7 +657,7 @@ uint32_t (*rxd_check)(const void *, size_t *); void (*txd_fill)(void *, const ddi_dma_cookie_t *, size_t, - uint32_t, boolean_t); + uint32_t, boolean_t, boolean_t); uint32_t (*txd_check)(const void *); }; @@ -755,7 +757,8 @@ uint32_t recv_count; uint32_t quiet_time; uint32_t busy_time; - uint32_t stint_count; + uint64_t tpkts_last; + uint32_t tfint_threshold; uint32_t sw_intr_intv; nge_mac_addr_t cur_uni_addr; uint32_t rx_datahwm; @@ -829,7 +832,6 @@ int param_poll_busy_time; int param_rx_intr_hwater; int param_rx_intr_lwater; - int param_tx_n_intr; } nge_t; extern const nge_ksindex_t nge_statistics[]; @@ -1044,7 +1046,7 @@ extern uint32_t nge_sum_rxd_check(const void *, size_t *); extern void nge_sum_txd_fill(void *, const ddi_dma_cookie_t *, - size_t, uint32_t, boolean_t); + size_t, uint32_t, boolean_t, boolean_t); extern uint32_t nge_sum_txd_check(const void *); /* @@ -1055,7 +1057,7 @@ extern uint32_t nge_hot_rxd_check(const void *, size_t *); extern void nge_hot_txd_fill(void *, const ddi_dma_cookie_t *, - size_t, uint32_t, boolean_t); + size_t, uint32_t, boolean_t, boolean_t); extern uint32_t nge_hot_txd_check(const void *); #ifdef __cplusplus
--- a/usr/src/uts/common/io/nge/nge_chip.c Tue Sep 22 17:11:54 2009 -0700 +++ b/usr/src/uts/common/io/nge/nge_chip.c Wed Sep 23 09:09:49 2009 +0800 @@ -25,7 +25,8 @@ */ #include "nge.h" -static uint32_t nge_watchdog_count = 1 << 29; +static uint32_t nge_watchdog_count = 1 << 5; +static uint32_t nge_watchdog_check = 1 << 3; extern boolean_t nge_enable_msi; static void nge_sync_mac_modes(nge_t *); @@ -1302,12 +1303,12 @@ intr_mask.mask_bits.reint = NGE_SET; intr_mask.mask_bits.rcint = NGE_SET; intr_mask.mask_bits.miss = NGE_SET; - intr_mask.mask_bits.teint = NGE_CLEAR; - intr_mask.mask_bits.tcint = NGE_SET; + intr_mask.mask_bits.teint = NGE_SET; + intr_mask.mask_bits.tcint = NGE_CLEAR; intr_mask.mask_bits.stint = NGE_CLEAR; intr_mask.mask_bits.mint = NGE_CLEAR; intr_mask.mask_bits.rfint = NGE_CLEAR; - intr_mask.mask_bits.tfint = NGE_CLEAR; + intr_mask.mask_bits.tfint = NGE_SET; intr_mask.mask_bits.feint = NGE_SET; intr_mask.mask_bits.resv10 = NGE_CLEAR; intr_mask.mask_bits.resv11 = NGE_CLEAR; @@ -1635,6 +1636,8 @@ nge_factotum_stall_check(nge_t *ngep) { uint32_t dogval; + send_ring_t *srp; + srp = ngep->send; /* * Specific check for Tx stall ... * @@ -1649,23 +1652,21 @@ * All of which should ensure that we don't get into a state * where packets are left pending indefinitely! */ + if (ngep->watchdog == 0 && + srp->tx_free < srp->desc.nslots) + ngep->watchdog = 1; dogval = nge_atomic_shl32(&ngep->watchdog, 1); - if (dogval < nge_watchdog_count) { - ngep->stall_cknum = 0; - } else { - ngep->stall_cknum++; - } - if (ngep->stall_cknum < 16) { + if (dogval >= nge_watchdog_check) + nge_tx_recycle(ngep, B_FALSE); + if (dogval < nge_watchdog_count) return (B_FALSE); - } else { - ngep->stall_cknum = 0; + else { ngep->statistics.sw_statistics.tx_stall++; return (B_TRUE); } } - /* * The factotum is woken up when there's something to do that we'd rather * not do from inside a hardware interrupt handler or high-level cyclic. @@ -1748,12 +1749,8 @@ if (pintr_src->int_bits.miss) ngep->statistics.sw_statistics.rx_nobuffer++; - btx = (pintr_src->int_bits.teint | pintr_src->int_bits.tcint) + btx = (pintr_src->int_bits.teint | pintr_src->int_bits.tfint) != 0 ? B_TRUE : B_FALSE; - if (pintr_src->int_bits.stint && ngep->poll) - ngep->stint_count ++; - if (ngep->poll && (ngep->stint_count % ngep->param_tx_n_intr == 0)) - btx = B_TRUE; if (btx) nge_tx_recycle(ngep, B_TRUE); if (brx) @@ -1768,8 +1765,6 @@ ngep->param_poll_quiet_time) { ngep->poll = B_FALSE; ngep->quiet_time = 0; - ngep->stint_count = 0; - nge_tx_recycle(ngep, B_TRUE); } } else ngep->quiet_time = 0; @@ -1837,9 +1832,6 @@ intr_mask.mask_val = nge_reg_get32(ngep, NGE_INTR_MASK); intr_mask.mask_bits.stint = NGE_SET; intr_mask.mask_bits.rcint = NGE_CLEAR; - intr_mask.mask_bits.reint = NGE_CLEAR; - intr_mask.mask_bits.tcint = NGE_CLEAR; - intr_mask.mask_bits.teint = NGE_CLEAR; nge_reg_put32(ngep, NGE_INTR_MASK, intr_mask.mask_val); ngep->ch_intr_mode = B_TRUE; } else if ((ngep->ch_intr_mode) && (!ngep->poll)) {
--- a/usr/src/uts/common/io/nge/nge_main.c Tue Sep 22 17:11:54 2009 -0700 +++ b/usr/src/uts/common/io/nge/nge_main.c Wed Sep 23 09:09:49 2009 +0800 @@ -211,7 +211,6 @@ {"_poll_busy_time", MAC_PROP_PERM_RW}, {"_rx_intr_hwater", MAC_PROP_PERM_RW}, {"_rx_intr_lwater", MAC_PROP_PERM_RW}, - {"_tx_n_intr", MAC_PROP_PERM_RW} }; #define NGE_MAX_PRIV_PROPS \ @@ -2044,21 +2043,6 @@ } return (err); } - if (strcmp(pr_name, "_tx_n_intr") == 0) { - if (pr_val == NULL) { - err = EINVAL; - return (err); - } - (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); - if (result < 1 || result > 10000) { - err = EINVAL; - } else { - ngep->param_tx_n_intr = (uint32_t)result; - goto reprogram; - } - return (err); - } - err = ENOTSUP; return (err); @@ -2118,12 +2102,6 @@ err = 0; goto done; } - if (strcmp(pr_name, "_tx_n_intr") == 0) { - value = (is_default ? NGE_TX_N_INTR : - ngep->param_tx_n_intr); - err = 0; - goto done; - } done: if (err == 0) { @@ -2190,6 +2168,19 @@ mutex_exit(ngep->softlock); } +void +nge_interrupt_optimize(nge_t *ngep) +{ + uint32_t tx_pkts; + tx_pkts = ngep->statistics.sw_statistics.xmit_count - ngep->tpkts_last; + ngep->tpkts_last = ngep->statistics.sw_statistics.xmit_count; + if ((tx_pkts > NGE_POLL_TUNE) && + (tx_pkts <= NGE_POLL_MAX)) + ngep->tfint_threshold = (tx_pkts / NGE_POLL_ENTER); + else + ngep->tfint_threshold = NGE_TFINT_DEFAULT; +} + /* * High-level cyclic handler * @@ -2209,6 +2200,7 @@ return; case NGE_CHIP_RUNNING: + nge_interrupt_optimize(ngep); break; case NGE_CHIP_FAULT: @@ -2461,6 +2453,9 @@ */ ngep->param_poll_quiet_time = NGE_POLL_QUIET_TIME; ngep->param_poll_busy_time = NGE_POLL_BUSY_TIME; + ngep->tfint_threshold = NGE_TFINT_DEFAULT; + ngep->poll = B_FALSE; + ngep->ch_intr_mode = B_FALSE; /* * param_rx_intr_hwater/param_rx_intr_lwater: ackets received @@ -2470,11 +2465,6 @@ ngep->param_rx_intr_hwater = 1; ngep->param_rx_intr_lwater = 8; - /* - * param_tx_n_intr: Per N tx packets to do tx recycle in poll mode. - * Bounds: min 1, max 10000. - */ - ngep->param_tx_n_intr = NGE_TX_N_INTR; infop = (chip_info_t *)&ngep->chipinfo; nge_chip_cfg_init(ngep, infop, B_FALSE);
--- a/usr/src/uts/common/io/nge/nge_tx.c Tue Sep 22 17:11:54 2009 -0700 +++ b/usr/src/uts/common/io/nge/nge_tx.c Wed Sep 23 09:09:49 2009 +0800 @@ -80,6 +80,12 @@ NGE_TXSWD_RECYCLE(ssbdp); } + if (ngep->nge_mac_state == NGE_MAC_STARTED && + ngep->resched_needed == 1) { + ngep->resched_needed = 0; + mac_tx_update(ngep->mh); + } + } static size_t @@ -178,8 +184,13 @@ used = nslots - free - used; ASSERT(slot == NEXT_INDEX(next, free, nslots)); + if (used == 0) { + ngep->watchdog = 0; + mutex_exit(srp->tc_lock); + return; + } - if (used > srp->tx_hwmark) + if (used > srp->tx_hwmark && ngep->resched_needed == 0) used = srp->tx_hwmark; nge_tx_desc_sync(ngep, slot, used, DDI_DMA_SYNC_FORKERNEL); @@ -224,6 +235,11 @@ * we're not about to free more places than were claimed! */ + if (free == 0) { + mutex_exit(srp->tc_lock); + return; + } + mutex_enter(srp->tx_lock); srp->tx_free += free; @@ -317,7 +333,8 @@ * counter may not get reset on a partial reclaim; but the * large trigger threshold makes false positives unlikely */ - ngep->watchdog ++; + if (ngep->watchdog == 0) + ngep->watchdog = 1; mode_cntl.mode_val = nge_reg_get32(ngep, NGE_MODE_CNTL); mode_cntl.mode_bits.txdm = NGE_SET; @@ -343,6 +360,7 @@ mblk_t *bp; void *hw_sbd_p; sw_tx_sbd_t *ssbdp; + boolean_t tfint; hcksum_retrieve(mp, NULL, NULL, NULL, NULL, NULL, NULL, &flags); @@ -361,6 +379,7 @@ * This is the point of no return! */ + tfint = ((start_index % ngep->tfint_threshold) == 0); bp = mp; totlen = 0; ssbdp = &srp->sw_sbds[start_index]; @@ -384,7 +403,7 @@ hw_sbd_p = DMA_VPTR(ssbdp->desc); ngep->desc_attr.txd_fill(hw_sbd_p, &ssbdp->pbuf.cookie, totlen, - flags, B_TRUE); + flags, B_TRUE, tfint); nge_tx_desc_sync(ngep, start_index, bds, DDI_DMA_SYNC_FORDEV); ssbdp->flags = CONTROLER_OWN; @@ -427,6 +446,7 @@ nge_dmah_node_t *dmer; nge_dmah_list_t dmah_list; ddi_dma_cookie_t cookie[NGE_MAX_COOKIES * NGE_MAP_FRAGS]; + boolean_t tfint; srp = ngep->send; nslots = srp->desc.nslots; @@ -522,16 +542,18 @@ for (i = slot - 1, j = end_index; start_index - j != 0; j = PREV(j, nslots), --i) { + tfint = ((j % ngep->tfint_threshold) == 0); hw_sbd_p = DMA_VPTR(srp->sw_sbds[j].desc); ngep->desc_attr.txd_fill(hw_sbd_p, cookie + i, - cookie[i].dmac_size, 0, end); + cookie[i].dmac_size, 0, end, tfint); end = B_FALSE; } hw_sbd_p = DMA_VPTR(srp->sw_sbds[j].desc); + tfint = ((j % ngep->tfint_threshold) == 0); ngep->desc_attr.txd_fill(hw_sbd_p, cookie + i, cookie[i].dmac_size, - flags, end); + flags, end, tfint); nge_tx_desc_sync(ngep, start_index, slot, DDI_DMA_SYNC_FORDEV); @@ -710,7 +732,7 @@ void nge_hot_txd_fill(void *hwdesc, const ddi_dma_cookie_t *cookie, - size_t length, uint32_t sum_flag, boolean_t end) + size_t length, uint32_t sum_flag, boolean_t end, boolean_t tfint) { hot_tx_bd * hw_sbd_p = hwdesc; @@ -736,6 +758,8 @@ /* * indicating the end of BDs */ + if (tfint) + hw_sbd_p->control_status.control_sum_bits.inten = NGE_SET; if (end) hw_sbd_p->control_status.control_sum_bits.end = NGE_SET; @@ -747,7 +771,7 @@ void nge_sum_txd_fill(void *hwdesc, const ddi_dma_cookie_t *cookie, - size_t length, uint32_t sum_flag, boolean_t end) + size_t length, uint32_t sum_flag, boolean_t end, boolean_t tfint) { sum_tx_bd * hw_sbd_p = hwdesc; @@ -772,6 +796,8 @@ /* * indicating the end of BDs */ + if (tfint) + hw_sbd_p->control_status.control_sum_bits.inten = NGE_SET; if (end) hw_sbd_p->control_status.control_sum_bits.end = NGE_SET;