Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 9 Jul 2010 00:38:00 +0000 (UTC)
From:      Navdeep Parhar <np@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r209841 - in head/sys/dev/cxgb: . common
Message-ID:  <201007090038.o690c0mI074691@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: np
Date: Fri Jul  9 00:38:00 2010
New Revision: 209841
URL: http://svn.freebsd.org/changeset/base/209841

Log:
  Improve cxgb(4)'s behaviour when faced with temporarily "bouncy" links:
  - Run the adapter's tick at 1Hz and remove link state checks from it.
    Instead, have each port check its link state.  Delay the check so that
    it takes place slightly after the driver is notified of a change in
    link state.  This is a cheap way to debounce these notifications if
    many are received in rapid succession.  POLL_LINK_1ST_TIME flag can
    also be eliminated as a side effect of these changes.
  - Do not reset the PHY when link goes down.
  - Clear port's link_fault flag if the PHY indicates link is down.
  - get_link_status_r should leave speed and duplex alone when link is down.
  
  MFC after:	1 month

Modified:
  head/sys/dev/cxgb/common/cxgb_ael1002.c
  head/sys/dev/cxgb/common/cxgb_common.h
  head/sys/dev/cxgb/common/cxgb_t3_hw.c
  head/sys/dev/cxgb/cxgb_adapter.h
  head/sys/dev/cxgb/cxgb_main.c

Modified: head/sys/dev/cxgb/common/cxgb_ael1002.c
==============================================================================
--- head/sys/dev/cxgb/common/cxgb_ael1002.c	Fri Jul  9 00:36:35 2010	(r209840)
+++ head/sys/dev/cxgb/common/cxgb_ael1002.c	Fri Jul  9 00:38:00 2010	(r209841)
@@ -297,6 +297,9 @@ static int get_link_status_r(struct cphy
 		if (err)
 			return err;
 		*link_ok = (stat0 & stat1 & (stat2 >> 12)) & 1;
+
+		if (*link_ok == 0)
+			return (0);
 	}
 	if (speed)
 		*speed = SPEED_10000;
@@ -1947,8 +1950,6 @@ static int ael2020_intr_enable(struct cp
 	if (err)
 		return err;
 
-	phy->caps |= POLL_LINK_1ST_TIME;
-
 	/* enable standard Link Alarm Status Interrupts */
 	err = t3_phy_lasi_intr_enable(phy);
 	if (err)

Modified: head/sys/dev/cxgb/common/cxgb_common.h
==============================================================================
--- head/sys/dev/cxgb/common/cxgb_common.h	Fri Jul  9 00:36:35 2010	(r209840)
+++ head/sys/dev/cxgb/common/cxgb_common.h	Fri Jul  9 00:38:00 2010	(r209841)
@@ -60,7 +60,6 @@ enum {
 	/* skip 25 */
 	SUPPORTED_MISC_IRQ = 1 << 26,
 	SUPPORTED_IRQ      = (SUPPORTED_LINK_IRQ | SUPPORTED_MISC_IRQ),
-	POLL_LINK_1ST_TIME = 1 << 27
 };
 
 enum {                            /* adapter interrupt-maintained statistics */

Modified: head/sys/dev/cxgb/common/cxgb_t3_hw.c
==============================================================================
--- head/sys/dev/cxgb/common/cxgb_t3_hw.c	Fri Jul  9 00:36:35 2010	(r209840)
+++ head/sys/dev/cxgb/common/cxgb_t3_hw.c	Fri Jul  9 00:38:00 2010	(r209841)
@@ -1530,6 +1530,9 @@ void t3_link_changed(adapter_t *adapter,
 
 	phy->ops->get_link_status(phy, &link_ok, &speed, &duplex, &fc);
 
+	if (link_ok == 0)
+		pi->link_fault = LF_NO;
+
 	if (lc->requested_fc & PAUSE_AUTONEG)
 		fc &= lc->requested_fc;
 	else
@@ -1608,12 +1611,8 @@ void t3_link_changed(adapter_t *adapter,
 					 F_XGM_INT, 0);
 		}
 
-		if (!link_fault) {
-			if (is_10G(adapter))
-				pi->phy.ops->power_down(&pi->phy, 1);
+		if (!link_fault)
 			t3_mac_disable(mac, MAC_DIRECTION_RX);
-			t3_link_start(phy, mac, lc);
-		}
 
 		/*
 		 * Make sure Tx FIFO continues to drain, even as rxen is left
@@ -2160,13 +2159,14 @@ static int mac_intr_handler(adapter_t *a
 		mac->stats.xaui_pcs_ctc_err++;
 	if (cause & F_XAUIPCSALIGNCHANGE)
 		mac->stats.xaui_pcs_align_change++;
-	if (cause & F_XGM_INT) {
-		t3_set_reg_field(adap,
-				 A_XGM_INT_ENABLE + mac->offset,
-				 F_XGM_INT, 0);
+	if (cause & F_XGM_INT &
+	    t3_read_reg(adap, A_XGM_INT_ENABLE + mac->offset)) {
+		t3_set_reg_field(adap, A_XGM_INT_ENABLE + mac->offset,
+		    F_XGM_INT, 0);
 
 		/* link fault suspected */
 		pi->link_fault = LF_MAYBE;
+		t3_os_link_intr(pi);
 	}
 
 	t3_write_reg(adap, A_XGM_INT_CAUSE + mac->offset, cause);
@@ -2194,7 +2194,7 @@ static int phy_intr_handler(adapter_t *a
 			int phy_cause = p->phy.ops->intr_handler(&p->phy);
 
 			if (phy_cause & cphy_cause_link_change)
-				t3_link_changed(adapter, i);
+				t3_os_link_intr(p);
 			if (phy_cause & cphy_cause_fifo_error)
 				p->phy.fifo_errors++;
 			if (phy_cause & cphy_cause_module_change)

Modified: head/sys/dev/cxgb/cxgb_adapter.h
==============================================================================
--- head/sys/dev/cxgb/cxgb_adapter.h	Fri Jul  9 00:36:35 2010	(r209840)
+++ head/sys/dev/cxgb/cxgb_adapter.h	Fri Jul  9 00:38:00 2010	(r209841)
@@ -106,6 +106,8 @@ struct port_info {
 	int		link_fault;
 
 	uint8_t		hw_addr[ETHER_ADDR_LEN];
+	struct callout	link_check_ch;
+	struct task	link_check_task;
 	struct task	timer_reclaim_task;
 	struct cdev     *port_cdev;
 
@@ -494,6 +496,7 @@ adap2pinfo(struct adapter *adap, int idx
 int t3_os_find_pci_capability(adapter_t *adapter, int cap);
 int t3_os_pci_save_state(struct adapter *adapter);
 int t3_os_pci_restore_state(struct adapter *adapter);
+void t3_os_link_intr(struct port_info *);
 void t3_os_link_changed(adapter_t *adapter, int port_id, int link_status,
 			int speed, int duplex, int fc, int mac_was_reset);
 void t3_os_phymod_changed(struct adapter *adap, int port_id);
@@ -527,10 +530,6 @@ int t3_get_desc(const struct sge_qset *q
     unsigned char *data);
 void t3_update_qset_coalesce(struct sge_qset *qs, const struct qset_params *p);
 
-#define CXGB_TICKS(a) ((a)->params.linkpoll_period ? \
-    (hz * (a)->params.linkpoll_period) / 10 : \
-    (a)->params.stats_update_period * hz)
-
 /*
  * XXX figure out how we can return this to being private to sge
  */

Modified: head/sys/dev/cxgb/cxgb_main.c
==============================================================================
--- head/sys/dev/cxgb/cxgb_main.c	Fri Jul  9 00:36:35 2010	(r209840)
+++ head/sys/dev/cxgb/cxgb_main.c	Fri Jul  9 00:38:00 2010	(r209841)
@@ -97,6 +97,8 @@ static int setup_sge_qsets(adapter_t *);
 static void cxgb_async_intr(void *);
 static void cxgb_tick_handler(void *, int);
 static void cxgb_tick(void *);
+static void link_check_callout(void *);
+static void check_link_status(void *, int);
 static void setup_rss(adapter_t *sc);
 static int alloc_filters(struct adapter *);
 static int setup_hw_filters(struct adapter *);
@@ -670,7 +672,7 @@ cxgb_controller_attach(device_t dev)
 		 sc->params.vpd.port_type[2], sc->params.vpd.port_type[3]);
 
 	device_printf(sc->dev, "Firmware Version %s\n", &sc->fw_version[0]);
-	callout_reset(&sc->cxgb_tick_ch, CXGB_TICKS(sc), cxgb_tick, sc);
+	callout_reset(&sc->cxgb_tick_ch, hz, cxgb_tick, sc);
 	t3_add_attach_sysctls(sc);
 out:
 	if (error)
@@ -1007,6 +1009,9 @@ cxgb_port_attach(device_t dev)
 	    device_get_unit(device_get_parent(dev)), p->port_id);
 	PORT_LOCK_INIT(p, p->lockbuf);
 
+	callout_init(&p->link_check_ch, CALLOUT_MPSAFE);
+	TASK_INIT(&p->link_check_task, 0, check_link_status, p);
+
 	/* Allocate an ifnet object and set it up */
 	ifp = p->ifp = if_alloc(IFT_ETHER);
 	if (ifp == NULL) {
@@ -1827,8 +1832,6 @@ cxgb_init_locked(struct port_info *p)
 	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
 	PORT_UNLOCK(p);
 
-	t3_link_changed(sc, p->port_id);
-
 	for (i = p->first_qset; i < p->first_qset + p->nqsets; i++) {
 		struct sge_qset *qs = &sc->sge.qs[i];
 		struct sge_txq *txq = &qs->txq[TXQ_ETH];
@@ -1839,6 +1842,9 @@ cxgb_init_locked(struct port_info *p)
 
 	/* all ok */
 	setbit(&sc->open_device_map, p->port_id);
+	callout_reset(&p->link_check_ch,
+	    p->phy.caps & SUPPORTED_LINK_IRQ ?  hz * 3 : hz / 4,
+	    link_check_callout, p);
 
 done:
 	if (may_sleep) {
@@ -1914,6 +1920,9 @@ cxgb_uninit_synchronized(struct port_inf
 	taskqueue_drain(sc->tq, &sc->slow_intr_task);
 	taskqueue_drain(sc->tq, &sc->tick_task);
 
+	callout_drain(&pi->link_check_ch);
+	taskqueue_drain(sc->tq, &pi->link_check_task);
+
 	PORT_LOCK(pi);
 	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
 
@@ -2274,33 +2283,42 @@ cxgb_async_intr(void *data)
 	taskqueue_enqueue(sc->tq, &sc->slow_intr_task);
 }
 
-static inline int
-link_poll_needed(struct port_info *p)
+static void
+link_check_callout(void *arg)
 {
-	struct cphy *phy = &p->phy;
+	struct port_info *pi = arg;
+	struct adapter *sc = pi->adapter;
 
-	if (phy->caps & POLL_LINK_1ST_TIME) {
-		p->phy.caps &= ~POLL_LINK_1ST_TIME;
-		return (1);
-	}
+	if (!isset(&sc->open_device_map, pi->port_id))
+		return;
 
-	return (p->link_fault || !(phy->caps & SUPPORTED_LINK_IRQ));
+	taskqueue_enqueue(sc->tq, &pi->link_check_task);
 }
 
 static void
-check_link_status(adapter_t *sc)
+check_link_status(void *arg, int pending)
 {
-	int i;
+	struct port_info *pi = arg;
+	struct adapter *sc = pi->adapter;
 
-	for (i = 0; i < (sc)->params.nports; ++i) {
-		struct port_info *p = &sc->port[i];
+	if (!isset(&sc->open_device_map, pi->port_id))
+		return;
 
-		if (!isset(&sc->open_device_map, p->port_id))
-			continue;
+	t3_link_changed(sc, pi->port_id);
 
-		if (link_poll_needed(p))
-			t3_link_changed(sc, i);
-	}
+	if (pi->link_fault || !(pi->phy.caps & SUPPORTED_LINK_IRQ))
+		callout_reset(&pi->link_check_ch, hz, link_check_callout, pi);
+}
+
+void
+t3_os_link_intr(struct port_info *pi)
+{
+	/*
+	 * Schedule a link check in the near future.  If the link is flapping
+	 * rapidly we'll keep resetting the callout and delaying the check until
+	 * things stabilize a bit.
+	 */
+	callout_reset(&pi->link_check_ch, hz / 4, link_check_callout, pi);
 }
 
 static void
@@ -2352,7 +2370,7 @@ cxgb_tick(void *arg)
 		return;
 
 	taskqueue_enqueue(sc->tq, &sc->tick_task);	
-	callout_reset(&sc->cxgb_tick_ch, CXGB_TICKS(sc), cxgb_tick, sc);
+	callout_reset(&sc->cxgb_tick_ch, hz, cxgb_tick, sc);
 }
 
 static void
@@ -2366,8 +2384,6 @@ cxgb_tick_handler(void *arg, int count)
 	if (sc->flags & CXGB_SHUTDOWN || !(sc->flags & FULL_INIT_DONE))
 		return;
 
-	check_link_status(sc);
-
 	if (p->rev == T3_REV_B2 && p->nports < 4 && sc->open_device_map) 
 		check_t3b2_mac(sc);
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201007090038.o690c0mI074691>