changeset 9738:70ba742e2254

6831148 System panics while running UDP stress test with cassini driver
author Cathy Zhou <Cathy.Zhou@Sun.COM>
date Wed, 27 May 2009 11:56:36 -0700
parents f100be4364e0
children 6d565cf1d9cc
files usr/src/uts/common/inet/ip/ip_if.c usr/src/uts/common/io/softmac/softmac_dev.c usr/src/uts/common/io/softmac/softmac_fp.c usr/src/uts/common/sys/softmac_impl.h
diffstat 4 files changed, 78 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/inet/ip/ip_if.c	Wed May 27 12:45:22 2009 -0400
+++ b/usr/src/uts/common/inet/ip/ip_if.c	Wed May 27 11:56:36 2009 -0700
@@ -3054,6 +3054,9 @@
 		idd->idd_tx_cb_dh = direct.di_tx_cb_dh;
 		idd->idd_tx_fctl_df = (ip_dld_fctl_t)direct.di_tx_fctl_df;
 		idd->idd_tx_fctl_dh = direct.di_tx_fctl_dh;
+		ASSERT(idd->idd_tx_cb_df != NULL);
+		ASSERT(idd->idd_tx_fctl_df != NULL);
+		ASSERT(idd->idd_tx_df != NULL);
 		/*
 		 * One time registration of flow enable callback function
 		 */
--- a/usr/src/uts/common/io/softmac/softmac_dev.c	Wed May 27 12:45:22 2009 -0400
+++ b/usr/src/uts/common/io/softmac/softmac_dev.c	Wed May 27 11:56:36 2009 -0700
@@ -180,6 +180,8 @@
 	ASSERT(!sup->su_tx_busy);
 	ASSERT(!sup->su_bound);
 	ASSERT(!sup->su_taskq_scheduled);
+	ASSERT(sup->su_tx_notify_func == NULL);
+	ASSERT(sup->su_tx_notify_arg == NULL);
 	ASSERT(list_is_empty(&sup->su_req_list));
 
 	list_destroy(&sup->su_req_list);
@@ -656,10 +658,22 @@
 	} else if (sup->su_tx_busy && SOFTMAC_CANPUTNEXT(sup->su_slp->sl_wq)) {
 		/*
 		 * The flow-conctol of the dedicated-lower-stream is
-		 * relieved, relieve the flow-control of the
-		 * upper-stream too.
+		 * relieved. If DLD_CAPAB_DIRECT is enabled, call tx_notify
+		 * callback to relieve the flow-control of the specific client,
+		 * otherwise relieve the flow-control of all the upper-stream
+		 * using the traditional STREAM mechanism.
 		 */
-		sup->su_tx_flow_mp = getq(wq);
+		if (sup->su_tx_notify_func != NULL) {
+			sup->su_tx_inprocess++;
+			mutex_exit(&sup->su_mutex);
+			sup->su_tx_notify_func(sup->su_tx_notify_arg,
+			    (mac_tx_cookie_t)sup);
+			mutex_enter(&sup->su_mutex);
+			if (--sup->su_tx_inprocess == 0)
+				cv_signal(&sup->su_cv);
+		}
+		ASSERT(sup->su_tx_flow_mp == NULL);
+		VERIFY((sup->su_tx_flow_mp = getq(wq)) != NULL);
 		sup->su_tx_busy = B_FALSE;
 	}
 	mutex_exit(&sup->su_mutex);
--- a/usr/src/uts/common/io/softmac/softmac_fp.c	Wed May 27 12:45:22 2009 -0400
+++ b/usr/src/uts/common/io/softmac/softmac_fp.c	Wed May 27 11:56:36 2009 -0700
@@ -196,11 +196,32 @@
 	return (0);
 }
 
-/* ARGSUSED */
 static mac_tx_notify_handle_t
-softmac_client_tx_notify(void *txcb, mac_tx_notify_t func, void *arg)
+softmac_client_tx_notify(softmac_upper_t *sup, mac_tx_notify_t func, void *arg)
 {
-	return (NULL);
+	ASSERT(MUTEX_HELD(&sup->su_mutex));
+
+	if (func != NULL) {
+		sup->su_tx_notify_func = func;
+		sup->su_tx_notify_arg = arg;
+	} else {
+		/*
+		 * Wait for all tx_notify_func call to be done.
+		 */
+		while (sup->su_tx_inprocess != 0)
+			cv_wait(&sup->su_cv, &sup->su_mutex);
+
+		sup->su_tx_notify_func = NULL;
+		sup->su_tx_notify_arg = NULL;
+	}
+	return ((mac_tx_notify_handle_t)sup);
+}
+
+static boolean_t
+softmac_tx_is_flow_blocked(softmac_upper_t *sup, mac_tx_cookie_t cookie)
+{
+	ASSERT(cookie == (mac_tx_cookie_t)sup);
+	return (sup->su_tx_busy);
 }
 
 static int
@@ -223,15 +244,10 @@
 		slp->sl_rxinfo = &sup->su_direct_rxinfo;
 		direct->di_tx_df = (uintptr_t)softmac_fastpath_wput_data;
 		direct->di_tx_dh = sup;
-
-		/*
-		 * We relying on the STREAM flow-control to backenable
-		 * the IP stream. Therefore, no notify callback needs to
-		 * be registered. But IP requires this to be a valid function
-		 * pointer.
-		 */
+		direct->di_tx_fctl_df = (uintptr_t)softmac_tx_is_flow_blocked;
+		direct->di_tx_fctl_dh = sup;
 		direct->di_tx_cb_df = (uintptr_t)softmac_client_tx_notify;
-		direct->di_tx_cb_dh = NULL;
+		direct->di_tx_cb_dh = sup;
 		sup->su_direct = B_TRUE;
 		return (0);
 
@@ -933,9 +949,16 @@
 	while (sup->su_tx_inprocess != 0)
 		cv_wait(&sup->su_cv, &sup->su_mutex);
 
+	/*
+	 * Note that this function is called either when the stream is closed,
+	 * or the stream is unbound (fastpath-slowpath-switch). Therefore,
+	 * No need to call the tx_notify callback.
+	 */
+	sup->su_tx_notify_func = NULL;
+	sup->su_tx_notify_arg = NULL;
 	if (sup->su_tx_busy) {
 		ASSERT(sup->su_tx_flow_mp == NULL);
-		sup->su_tx_flow_mp = getq(sup->su_wq);
+		VERIFY((sup->su_tx_flow_mp = getq(sup->su_wq)) != NULL);
 		sup->su_tx_busy = B_FALSE;
 	}
 
@@ -995,18 +1018,22 @@
 		return (NULL);
 	}
 
-	if ((flag & MAC_DROP_ON_NO_DESC) != 0) {
-		freemsg(mp);
-		return ((mac_tx_cookie_t)wq);
-	}
-
 	if (sup->su_tx_busy) {
-		putnext(wq, mp);
-		return ((mac_tx_cookie_t)wq);
+		if ((flag & MAC_DROP_ON_NO_DESC) != 0)
+			freemsg(mp);
+		else
+			putnext(wq, mp);
+		return ((mac_tx_cookie_t)sup);
 	}
 
 	mutex_enter(&sup->su_mutex);
 	if (!sup->su_tx_busy) {
+		/*
+		 * If DLD_CAPAB_DIRECT is enabled, the notify callback will be
+		 * called when the flow control can be disabled. Otherwise,
+		 * put the tx_flow_mp into the wq to make use of the old
+		 * streams flow control.
+		 */
 		ASSERT(sup->su_tx_flow_mp != NULL);
 		(void) putq(sup->su_wq, sup->su_tx_flow_mp);
 		sup->su_tx_flow_mp = NULL;
@@ -1014,8 +1041,12 @@
 		qenable(wq);
 	}
 	mutex_exit(&sup->su_mutex);
-	putnext(wq, mp);
-	return ((mac_tx_cookie_t)wq);
+
+	if ((flag & MAC_DROP_ON_NO_DESC) != 0)
+		freemsg(mp);
+	else
+		putnext(wq, mp);
+	return ((mac_tx_cookie_t)sup);
 }
 
 boolean_t
--- a/usr/src/uts/common/sys/softmac_impl.h	Wed May 27 12:45:22 2009 -0400
+++ b/usr/src/uts/common/sys/softmac_impl.h	Wed May 27 11:56:36 2009 -0700
@@ -323,6 +323,12 @@
 	 * Whether this stream is already scheduled in softmac_taskq_list.
 	 */
 	boolean_t		su_taskq_scheduled;	/* softmac_taskq_lock */
+
+	/*
+	 * The DLD_CAPAB_DIRECT related notify callback.
+	 */
+	mac_tx_notify_t		su_tx_notify_func;	/* su_mutex */
+	void			*su_tx_notify_arg;	/* su_mutex */
 } softmac_upper_t;
 
 #define	SOFTMAC_EQ_PENDING(sup, mp) {					\