summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWinson Wang - Sun Microsystems - Beijing China <Zhen.W@Sun.COM>2009-09-23 09:09:49 +0800
committerWinson Wang - Sun Microsystems - Beijing China <Zhen.W@Sun.COM>2009-09-23 09:09:49 +0800
commit51fc88a818087605a0e5f11eddb8b66576f72c23 (patch)
tree53e0f601111a0bd63bf191dcf1245dd89bcd48fc
parent22fe2c8844be88ebae6478ca1b0b92c8ec2aef54 (diff)
downloadillumos-joyent-51fc88a818087605a0e5f11eddb8b66576f72c23.tar.gz
6786791 nge needs to have a new tx stall detection mechanism
6871807 nge driver should enable TFINT for tx_recylce
-rw-r--r--usr/src/uts/common/io/nge/nge.h18
-rw-r--r--usr/src/uts/common/io/nge/nge_chip.c38
-rw-r--r--usr/src/uts/common/io/nge/nge_main.c44
-rw-r--r--usr/src/uts/common/io/nge/nge_tx.c40
4 files changed, 75 insertions, 65 deletions
diff --git a/usr/src/uts/common/io/nge/nge.h b/usr/src/uts/common/io/nge/nge.h
index 972ca5001c..ca83273109 100644
--- a/usr/src/uts/common/io/nge/nge.h
+++ b/usr/src/uts/common/io/nge/nge.h
@@ -147,8 +147,7 @@ extern int secpolicy_net_config(const cred_t *, boolean_t);
#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 @@ extern int secpolicy_net_config(const cred_t *, boolean_t);
#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 @@ struct nge_desc_attr {
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 @@ typedef struct nge {
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 @@ typedef struct nge {
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 void nge_sum_rxd_fill(void *, const ddi_dma_cookie_t *, size_t);
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 void nge_hot_rxd_fill(void *, const ddi_dma_cookie_t *, size_t);
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
diff --git a/usr/src/uts/common/io/nge/nge_chip.c b/usr/src/uts/common/io/nge/nge_chip.c
index 5efae34727..04a5858840 100644
--- a/usr/src/uts/common/io/nge/nge_chip.c
+++ b/usr/src/uts/common/io/nge/nge_chip.c
@@ -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 @@ nge_chip_start(nge_t *ngep)
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 @@ static boolean_t
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 @@ nge_factotum_stall_check(nge_t *ngep)
* 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 @@ nge_intr_handle(nge_t *ngep, nge_intr_src *pintr_src)
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 @@ nge_intr_handle(nge_t *ngep, nge_intr_src *pintr_src)
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 @@ nge_chip_intr(caddr_t arg1, caddr_t arg2)
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)) {
diff --git a/usr/src/uts/common/io/nge/nge_main.c b/usr/src/uts/common/io/nge/nge_main.c
index e0f06f10e6..583e9bd61e 100644
--- a/usr/src/uts/common/io/nge/nge_main.c
+++ b/usr/src/uts/common/io/nge/nge_main.c
@@ -211,7 +211,6 @@ mac_priv_prop_t nge_priv_props[] = {
{"_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 @@ nge_set_priv_prop(nge_t *ngep, const char *pr_name, uint_t pr_valsize,
}
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 @@ nge_get_priv_prop(nge_t *ngep, const char *pr_name, uint_t pr_flags,
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 @@ nge_wake_factotum(nge_t *ngep)
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 @@ nge_chip_cyclic(void *arg)
return;
case NGE_CHIP_RUNNING:
+ nge_interrupt_optimize(ngep);
break;
case NGE_CHIP_FAULT:
@@ -2461,6 +2453,9 @@ nge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
*/
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 @@ nge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
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);
diff --git a/usr/src/uts/common/io/nge/nge_tx.c b/usr/src/uts/common/io/nge/nge_tx.c
index 5f1ff307d9..c16368bd5f 100644
--- a/usr/src/uts/common/io/nge/nge_tx.c
+++ b/usr/src/uts/common/io/nge/nge_tx.c
@@ -80,6 +80,12 @@ nge_tx_recycle_all(nge_t *ngep)
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 @@ nge_tx_recycle(nge_t *ngep, boolean_t is_intr)
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 @@ nge_tx_recycle(nge_t *ngep, boolean_t is_intr)
* 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 @@ nge_tx_start(nge_t *ngep, uint32_t slotnum)
* 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 @@ nge_send_copy(nge_t *ngep, mblk_t *mp, send_ring_t *srp)
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 @@ nge_send_copy(nge_t *ngep, mblk_t *mp, send_ring_t *srp)
* 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 @@ nge_send_copy(nge_t *ngep, mblk_t *mp, send_ring_t *srp)
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_send_mapped(nge_t *ngep, mblk_t *mp, size_t fragno)
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 @@ nge_send_mapped(nge_t *ngep, mblk_t *mp, size_t fragno)
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 @@ nge_sum_txd_check(const void *hwd)
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 @@ nge_hot_txd_fill(void *hwdesc, const ddi_dma_cookie_t *cookie,
/*
* 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 @@ nge_hot_txd_fill(void *hwdesc, const ddi_dma_cookie_t *cookie,
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 @@ nge_sum_txd_fill(void *hwdesc, const ddi_dma_cookie_t *cookie,
/*
* 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;