changeset 9820:8aaf03899a2b

6842466 nxge hang on Sun Storage 7310 during database write I/O
author Eric Cheng
date Mon, 08 Jun 2009 23:19:59 -0700
parents 82205569275c
children 548e87839fe9
files usr/src/uts/common/io/mac/mac_sched.c usr/src/uts/common/sys/mac_soft_ring.h
diffstat 2 files changed, 28 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/io/mac/mac_sched.c	Mon Jun 08 14:57:32 2009 -0700
+++ b/usr/src/uts/common/io/mac/mac_sched.c	Mon Jun 08 23:19:59 2009 -0700
@@ -1693,23 +1693,39 @@
 		mutex_enter(&mac_srs->srs_lock);
 	}
 
-	if (!(mac_srs->srs_state & (SRS_LATENCY_OPT|SRS_BLANK|SRS_PAUSE))) {
+	if (!(mac_srs->srs_state & (SRS_BLANK|SRS_PAUSE)) &&
+	    (mac_srs->srs_first != NULL)) {
 		/*
-		 * In case we are optimizing for throughput, we
-		 * should try and keep the worker thread running
-		 * as much as possible. Send the poll thread down
-		 * to check one more time if something else
-		 * arrived. In the meanwhile, if poll thread had
-		 * collected something due to earlier signal,
-		 * process it now.
+		 * More packets arrived while we were clearing the
+		 * SRS. This can be possible because of one of
+		 * three conditions below:
+		 * 1) The driver is using multiple worker threads
+		 *    to send the packets to us.
+		 * 2) The driver has a race in switching
+		 *    between interrupt and polling mode or
+		 * 3) Packets are arriving in this SRS via the
+		 *    S/W classification as well.
+		 *
+		 * We should switch to polling mode and see if we
+		 * need to send the poll thread down. Also, signal
+		 * the worker thread to process whats just arrived.
 		 */
+		MAC_SRS_POLLING_ON(mac_srs);
 		if (srs_rx->sr_poll_pkt_cnt <= srs_rx->sr_lowat) {
 			srs_rx->sr_drain_poll_sig++;
 			MAC_SRS_POLL_RING(mac_srs);
 		}
-		if (mac_srs->srs_first != NULL) {
+
+		/*
+		 * If we didn't signal the poll thread, we need
+		 * to deal with the pending packets ourselves.
+		 */
+		if (proc_type == SRS_WORKER) {
 			srs_rx->sr_drain_again++;
 			goto again;
+		} else {
+			srs_rx->sr_drain_worker_sig++;
+			cv_signal(&mac_srs->srs_async);
 		}
 	}
 
--- a/usr/src/uts/common/sys/mac_soft_ring.h	Mon Jun 08 14:57:32 2009 -0700
+++ b/usr/src/uts/common/sys/mac_soft_ring.h	Mon Jun 08 23:19:59 2009 -0700
@@ -231,8 +231,10 @@
 	uint32_t		sr_poll_goto_sleep;
 	/* Worker thread goes back to draining the queue */
 	uint32_t		sr_drain_again;
+	/* More Packets in queue so signal the poll thread to drain */
+	uint32_t		sr_drain_poll_sig;
 	/* More Packets in queue so signal the worker thread to drain */
-	uint32_t		sr_drain_poll_sig;
+	uint32_t		sr_drain_worker_sig;
 	/* Poll thread is already running so worker has nothing to do */
 	uint32_t		sr_drain_poll_running;
 	/* We have packets already queued so keep polling */