Mercurial > illumos > illumos-gate
changeset 9883:0ced6e024277
6839845 ixgbe TX causes huge out of order packets on RX side
author | Rajagopal Kunhappan <Rajagopal.Kunhappan@Sun.COM> |
---|---|
date | Tue, 16 Jun 2009 12:02:30 -0700 |
parents | a28e5f02b7fa |
children | 81f4d72ae348 |
files | usr/src/uts/common/inet/ip.h usr/src/uts/common/inet/squeue.c usr/src/uts/common/io/mac/mac_soft_ring.c usr/src/uts/common/sys/mac_soft_ring.h |
diffstat | 4 files changed, 37 insertions(+), 20 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/inet/ip.h Tue Jun 16 11:57:32 2009 -0700 +++ b/usr/src/uts/common/inet/ip.h Tue Jun 16 12:02:30 2009 -0700 @@ -3612,7 +3612,7 @@ * we need to duplicate the definitions here because we cannot * include mac/dls header files here. */ -typedef void (*ip_mac_intr_disable_t)(void *); +typedef boolean_t (*ip_mac_intr_disable_t)(void *); typedef void (*ip_mac_intr_enable_t)(void *); typedef ip_mac_tx_cookie_t (*ip_dld_tx_t)(void *, mblk_t *, uint64_t, uint16_t);
--- a/usr/src/uts/common/inet/squeue.c Tue Jun 16 11:57:32 2009 -0700 +++ b/usr/src/uts/common/inet/squeue.c Tue Jun 16 12:02:30 2009 -0700 @@ -163,14 +163,21 @@ \ } +/* + * Blank the receive ring (in this case it is the soft ring). When + * blanked, the soft ring will not send any more packets up. + * Blanking may not succeed when there is a CPU already in the soft + * ring sending packets up. In that case, SQS_POLLING will not be + * set. + */ #define SQS_POLLING_ON(sqp, sq_poll_capable, rx_ring) { \ ASSERT(MUTEX_HELD(&(sqp)->sq_lock)); \ if (sq_poll_capable) { \ ASSERT(rx_ring != NULL); \ ASSERT(sqp->sq_state & SQS_POLL_CAPAB); \ if (!(sqp->sq_state & SQS_POLLING)) { \ - sqp->sq_state |= SQS_POLLING; \ - rx_ring->rr_intr_disable(rx_ring->rr_intr_handle); \ + if (rx_ring->rr_intr_disable(rx_ring->rr_intr_handle)) \ + sqp->sq_state |= SQS_POLLING; \ } \ } \ } @@ -187,9 +194,10 @@ } \ } -#define SQS_POLL_RING(sqp, sq_poll_capable) { \ +/* Wakeup poll thread only if SQS_POLLING is set */ +#define SQS_POLL_RING(sqp) { \ ASSERT(MUTEX_HELD(&(sqp)->sq_lock)); \ - if (sq_poll_capable) { \ + if (sqp->sq_state & SQS_POLLING) { \ ASSERT(sqp->sq_state & SQS_POLL_CAPAB); \ if (!(sqp->sq_state & SQS_GET_PKTS)) { \ sqp->sq_state |= SQS_GET_PKTS; \ @@ -662,7 +670,6 @@ sqp->sq_state |= SQS_PROC | proc_type; - /* * We have backlog built up. Switch to polling mode if the * device underneath allows it. Need to do it so that @@ -740,9 +747,14 @@ * We turn off interrupts for all userland threads * doing drain but we do active polling only for * worker thread. + * + * Calling SQS_POLL_RING() even in the case of + * SQS_POLLING_ON() not succeeding is ok as + * SQS_POLL_RING() will not wake up poll thread + * if SQS_POLLING bit is not set. */ if (proc_type == SQS_WORKER) - SQS_POLL_RING(sqp, sq_poll_capable); + SQS_POLL_RING(sqp); goto again; } else { did_wakeup = B_TRUE; @@ -769,8 +781,7 @@ * thread down once more to see if something arrived. Otherwise, * turn the interrupts back on and we are done. */ - if ((proc_type == SQS_WORKER) && - (sqp->sq_state & SQS_POLL_CAPAB)) { + if ((proc_type == SQS_WORKER) && (sqp->sq_state & SQS_POLLING)) { /* * Do one last check to see if anything arrived * in the NIC. We leave the SQS_PROC set to ensure @@ -792,16 +803,17 @@ */ ASSERT(!(sqp->sq_state & (SQS_POLL_THR_QUIESCED | SQS_POLL_QUIESCE_DONE))); - SQS_POLL_RING(sqp, sq_poll_capable); + SQS_POLL_RING(sqp); sqp->sq_state &= ~proc_type; } else { /* - * The squeue is either not capable of polling or - * poll thread already finished processing and didn't - * find anything. Since there is nothing queued and - * we already turn polling on (for all threads doing - * drain), we should turn polling off and relinquish - * the PROC. + * The squeue is either not capable of polling or the + * attempt to blank (i.e., turn SQS_POLLING_ON()) was + * unsuccessful or poll thread already finished + * processing and didn't find anything. Since there + * is nothing queued and we already turn polling on + * (for all threads doing drain), we should turn + * polling off and relinquish the PROC. */ ASSERT(!(sqp->sq_state & (SQS_POLL_THR_QUIESCED | SQS_POLL_QUIESCE_DONE)));
--- a/usr/src/uts/common/io/mac/mac_soft_ring.c Tue Jun 16 11:57:32 2009 -0700 +++ b/usr/src/uts/common/io/mac/mac_soft_ring.c Tue Jun 16 12:02:30 2009 -0700 @@ -423,7 +423,7 @@ start: for (;;) { while (((ringp->s_ring_first == NULL || - (ringp->s_ring_state & S_RING_BLOCK)) && + (ringp->s_ring_state & (S_RING_BLOCK|S_RING_BLANK))) && !(ringp->s_ring_state & S_RING_PAUSE)) || (ringp->s_ring_state & S_RING_PROC)) { @@ -498,17 +498,22 @@ mutex_exit(&ringp->s_ring_lock); } -void +boolean_t mac_soft_ring_intr_disable(void *arg) { mac_soft_ring_t *ringp = (mac_soft_ring_t *)arg; + boolean_t sring_blanked = B_FALSE; /* * Stop worker thread from sending packets above. * Squeue will poll soft ring when it needs packets. */ mutex_enter(&ringp->s_ring_lock); - ringp->s_ring_state |= S_RING_BLANK; + if (!(ringp->s_ring_state & S_RING_PROC)) { + ringp->s_ring_state |= S_RING_BLANK; + sring_blanked = B_TRUE; + } mutex_exit(&ringp->s_ring_lock); + return (sring_blanked); } /*
--- a/usr/src/uts/common/sys/mac_soft_ring.h Tue Jun 16 11:57:32 2009 -0700 +++ b/usr/src/uts/common/sys/mac_soft_ring.h Tue Jun 16 12:02:30 2009 -0700 @@ -691,7 +691,7 @@ extern void mac_client_update_classifier(mac_client_impl_t *, boolean_t); extern void mac_soft_ring_intr_enable(void *); -extern void mac_soft_ring_intr_disable(void *); +extern boolean_t mac_soft_ring_intr_disable(void *); extern mac_soft_ring_t *mac_soft_ring_create(int, clock_t, void *, uint16_t, pri_t, mac_client_impl_t *, mac_soft_ring_set_t *, processorid_t, mac_direct_rx_t, void *, mac_resource_handle_t);