svn commit: r211848 - in stable/8/sys/dev/cxgb: . common

Navdeep Parhar np at FreeBSD.org
Thu Aug 26 19:55:03 UTC 2010


Author: np
Date: Thu Aug 26 19:55:03 2010
New Revision: 211848
URL: http://svn.freebsd.org/changeset/base/211848

Log:
  MFC r208887, r209115-209116, r209839-209841, r211345-211347
  
  r208887
  tunable to control mc5 partition
  
  r209115
  make format string a string literal.
  
  r209116
  Add knob to get packet timestamps from the hardware.
  
  r209839
  Fix bufsize calculation so that cxgbtool can display information for the
  last I/O queue too.
  
  r209840
  Eliminate ext_intr_task.  The "slow" interrupt handler is already
  running on the adapter's task queue.  Just do what the task does
  instead of enqueueing it.
  
  r209841
  Improved link detection.
  
  r211345
  wakeup is required if the adapter lock is released anywhere during
  init and not just for the may_sleep case.
  
  r211346
  Always reset the XGMAC's XAUI PCS on a link up.
  
  r211347
  Fix tx pause quanta and timer calculations.

Modified:
  stable/8/sys/dev/cxgb/common/cxgb_ael1002.c
  stable/8/sys/dev/cxgb/common/cxgb_common.h
  stable/8/sys/dev/cxgb/common/cxgb_t3_hw.c
  stable/8/sys/dev/cxgb/common/cxgb_xgmac.c
  stable/8/sys/dev/cxgb/cxgb_adapter.h
  stable/8/sys/dev/cxgb/cxgb_main.c
  stable/8/sys/dev/cxgb/cxgb_sge.c
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/dev/xen/xenpci/   (props changed)

Modified: stable/8/sys/dev/cxgb/common/cxgb_ael1002.c
==============================================================================
--- stable/8/sys/dev/cxgb/common/cxgb_ael1002.c	Thu Aug 26 16:01:29 2010	(r211847)
+++ stable/8/sys/dev/cxgb/common/cxgb_ael1002.c	Thu Aug 26 19:55:03 2010	(r211848)
@@ -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: stable/8/sys/dev/cxgb/common/cxgb_common.h
==============================================================================
--- stable/8/sys/dev/cxgb/common/cxgb_common.h	Thu Aug 26 16:01:29 2010	(r211847)
+++ stable/8/sys/dev/cxgb/common/cxgb_common.h	Thu Aug 26 19:55:03 2010	(r211848)
@@ -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 */
@@ -701,7 +700,6 @@ void t3_port_intr_enable(adapter_t *adap
 void t3_port_intr_disable(adapter_t *adapter, int idx);
 void t3_port_intr_clear(adapter_t *adapter, int idx);
 int t3_slow_intr_handler(adapter_t *adapter);
-int t3_phy_intr_handler(adapter_t *adapter);
 
 void t3_link_changed(adapter_t *adapter, int port_id);
 int t3_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc);
@@ -747,6 +745,7 @@ int t3_mc7_bd_read(struct mc7 *mc7, unsi
 
 int t3_mac_init(struct cmac *mac);
 void t3b_pcs_reset(struct cmac *mac);
+void t3c_pcs_force_los(struct cmac *mac);
 void t3_mac_disable_exact_filters(struct cmac *mac);
 void t3_mac_enable_exact_filters(struct cmac *mac);
 int t3_mac_enable(struct cmac *mac, int which);

Modified: stable/8/sys/dev/cxgb/common/cxgb_t3_hw.c
==============================================================================
--- stable/8/sys/dev/cxgb/common/cxgb_t3_hw.c	Thu Aug 26 16:01:29 2010	(r211847)
+++ stable/8/sys/dev/cxgb/common/cxgb_t3_hw.c	Thu Aug 26 19:55:03 2010	(r211848)
@@ -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
@@ -1555,6 +1558,13 @@ void t3_link_changed(adapter_t *adapter,
 				pi->link_fault = LF_YES;
 			}
 
+			if (uses_xaui(adapter)) {
+				if (adapter->params.rev >= T3_REV_C)
+					t3c_pcs_force_los(mac);
+				else
+					t3b_pcs_reset(mac);
+			}
+
 			/* Don't report link up */
 			link_ok = 0;
 		} else {
@@ -1581,12 +1591,20 @@ void t3_link_changed(adapter_t *adapter,
 		/* down -> up, or up -> up with changed settings */
 
 		if (adapter->params.rev > 0 && uses_xaui(adapter)) {
+
+			if (adapter->params.rev >= T3_REV_C)
+				t3c_pcs_force_los(mac);
+			else
+				t3b_pcs_reset(mac);
+
 			t3_write_reg(adapter, A_XGM_XAUI_ACT_CTRL + mac->offset,
 				     F_TXACTENABLE | F_RXEN);
 		}
 
+		/* disable TX FIFO drain */
 		t3_set_reg_field(adapter, A_XGM_TXFIFO_CFG + mac->offset,
 				 F_ENDROPPKT, 0);
+
 		t3_mac_enable(mac, MAC_DIRECTION_TX | MAC_DIRECTION_RX);
 		t3_set_reg_field(adapter, A_XGM_STAT_CTRL + mac->offset,
 				 F_CLRSTATS, 1);
@@ -1606,24 +1624,21 @@ void t3_link_changed(adapter_t *adapter,
 			t3_set_reg_field(adapter,
 					 A_XGM_INT_ENABLE + mac->offset,
 					 F_XGM_INT, 0);
-		}
 
-		if (!link_fault) {
-			if (is_10G(adapter))
-				pi->phy.ops->power_down(&pi->phy, 1);
 			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
-		 * high to help detect and indicate remote faults.
-		 */
-		t3_set_reg_field(adapter, A_XGM_TXFIFO_CFG + mac->offset, 0,
-				 F_ENDROPPKT);
-		t3_write_reg(adapter, A_XGM_RX_CTRL + mac->offset, 0);
-		t3_write_reg(adapter, A_XGM_TX_CTRL + mac->offset, F_TXEN);
-		t3_write_reg(adapter, A_XGM_RX_CTRL + mac->offset, F_RXEN);
+			/*
+			 * Make sure Tx FIFO continues to drain, even as rxen is
+			 * left high to help detect and indicate remote faults.
+			 */
+			t3_set_reg_field(adapter,
+			    A_XGM_TXFIFO_CFG + mac->offset, 0, F_ENDROPPKT);
+			t3_write_reg(adapter, A_XGM_RX_CTRL + mac->offset, 0);
+			t3_write_reg(adapter,
+			    A_XGM_TX_CTRL + mac->offset, F_TXEN);
+			t3_write_reg(adapter,
+			    A_XGM_RX_CTRL + mac->offset, F_RXEN);
+		}
 	}
 
 	t3_os_link_changed(adapter, port_id, link_ok, speed, duplex, fc,
@@ -2160,13 +2175,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);
@@ -2180,7 +2196,7 @@ static int mac_intr_handler(adapter_t *a
 /*
  * Interrupt handler for PHY events.
  */
-int t3_phy_intr_handler(adapter_t *adapter)
+static int phy_intr_handler(adapter_t *adapter)
 {
 	u32 i, cause = t3_read_reg(adapter, A_T3DBG_INT_CAUSE);
 
@@ -2194,7 +2210,7 @@ int t3_phy_intr_handler(adapter_t *adapt
 			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)
@@ -2262,7 +2278,7 @@ int t3_slow_intr_handler(adapter_t *adap
 	if (cause & F_XGMAC0_1)
 		mac_intr_handler(adapter, 1);
 	if (cause & F_T3DBG)
-		t3_os_ext_intr_handler(adapter);
+		phy_intr_handler(adapter);
 
 	/* Clear the interrupts just processed. */
 	t3_write_reg(adapter, A_PL_INT_CAUSE0, cause);

Modified: stable/8/sys/dev/cxgb/common/cxgb_xgmac.c
==============================================================================
--- stable/8/sys/dev/cxgb/common/cxgb_xgmac.c	Thu Aug 26 16:01:29 2010	(r211847)
+++ stable/8/sys/dev/cxgb/common/cxgb_xgmac.c	Thu Aug 26 19:55:03 2010	(r211848)
@@ -97,11 +97,40 @@ void t3b_pcs_reset(struct cmac *mac)
 {
 	t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset,
 			 F_PCS_RESET_, 0);
-	udelay(20);
+
+	/* No delay required */
+
 	t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset, 0,
 			 F_PCS_RESET_);
 }
 
+void t3c_pcs_force_los(struct cmac *mac)
+{
+	t3_set_reg_field(mac->adapter, A_XGM_SERDES_STAT0 + mac->offset,
+	    F_LOWSIGFORCEEN0 | F_LOWSIGFORCEVALUE0,
+	    F_LOWSIGFORCEEN0 | F_LOWSIGFORCEVALUE0);
+	t3_set_reg_field(mac->adapter, A_XGM_SERDES_STAT1 + mac->offset,
+	    F_LOWSIGFORCEEN1 | F_LOWSIGFORCEVALUE1,
+	    F_LOWSIGFORCEEN1 | F_LOWSIGFORCEVALUE1);
+	t3_set_reg_field(mac->adapter, A_XGM_SERDES_STAT2 + mac->offset,
+	    F_LOWSIGFORCEEN2 | F_LOWSIGFORCEVALUE2,
+	    F_LOWSIGFORCEEN2 | F_LOWSIGFORCEVALUE2);
+	t3_set_reg_field(mac->adapter, A_XGM_SERDES_STAT3 + mac->offset,
+	    F_LOWSIGFORCEEN3 | F_LOWSIGFORCEVALUE3,
+	    F_LOWSIGFORCEEN3 | F_LOWSIGFORCEVALUE3);
+
+	/* No delay required */
+
+	t3_set_reg_field(mac->adapter, A_XGM_SERDES_STAT0 + mac->offset,
+	    F_LOWSIGFORCEEN0, 0);
+	t3_set_reg_field(mac->adapter, A_XGM_SERDES_STAT1 + mac->offset,
+	    F_LOWSIGFORCEEN1, 0);
+	t3_set_reg_field(mac->adapter, A_XGM_SERDES_STAT2 + mac->offset,
+	    F_LOWSIGFORCEEN2, 0);
+	t3_set_reg_field(mac->adapter, A_XGM_SERDES_STAT3 + mac->offset,
+	    F_LOWSIGFORCEEN3, 0);
+}
+
 /**
  *	t3_mac_init - initialize a MAC
  *	@mac: the MAC to initialize
@@ -433,7 +462,7 @@ static int rx_fifo_hwm(int mtu)
  */
 int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu)
 {
-	int hwm, lwm, divisor;
+	int hwm, lwm;
 	int ipg;
 	unsigned int thres, v, reg;
 	adapter_t *adap = mac->adapter;
@@ -512,16 +541,6 @@ int t3_mac_set_mtu(struct cmac *mac, uns
 	t3_set_reg_field(adap, A_XGM_TXFIFO_CFG + mac->offset,
 			 V_TXFIFOTHRESH(M_TXFIFOTHRESH) | V_TXIPG(M_TXIPG),
 			 V_TXFIFOTHRESH(thres) | V_TXIPG(ipg));
-
-	/* Assuming a minimum drain rate of 2.5Gbps...
-	 */
-	if (adap->params.rev > 0) {
-		divisor = (adap->params.rev == T3_REV_C) ? 64 : 8;
-		t3_write_reg(adap, A_XGM_PAUSE_TIMER + mac->offset,
-			     (hwm - lwm) * 4 / divisor);
-	}
-	t3_write_reg(adap, A_XGM_TX_PAUSE_QUANTA + mac->offset,
-		     MAC_RXFIFO_SIZE * 4 * 8 / 512);
 	return 0;
 }
 
@@ -541,9 +560,17 @@ int t3_mac_set_speed_duplex_fc(struct cm
 	u32 val;
 	adapter_t *adap = mac->adapter;
 	unsigned int oft = mac->offset;
+	unsigned int pause_bits;
 
 	if (duplex >= 0 && duplex != DUPLEX_FULL)
 		return -EINVAL;
+
+	pause_bits = MAC_RXFIFO_SIZE * 4 * 8;
+	t3_write_reg(adap, A_XGM_TX_PAUSE_QUANTA + mac->offset,
+		     pause_bits / 512);
+	t3_write_reg(adap, A_XGM_PAUSE_TIMER + mac->offset,
+		     (pause_bits >> (adap->params.rev == T3_REV_C ? 10 : 7)));
+
 	if (mac->multiport) {
 		u32 rx_max_pkt_size =
 		    G_RXMAXPKTSIZE(t3_read_reg(adap,
@@ -552,9 +579,9 @@ int t3_mac_set_speed_duplex_fc(struct cm
 		val &= ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM);
 		val |= V_RXFIFOPAUSEHWM(rx_fifo_hwm(rx_max_pkt_size) / 8);
 		t3_write_reg(adap, A_XGM_RXFIFO_CFG + oft, val);
-
 		t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN,
 			  		F_TXPAUSEEN);
+
 		return t3_vsc7323_set_speed_fc(adap, speed, fc, mac->ext_port);
 	}
 	if (speed >= 0) {

Modified: stable/8/sys/dev/cxgb/cxgb_adapter.h
==============================================================================
--- stable/8/sys/dev/cxgb/cxgb_adapter.h	Thu Aug 26 16:01:29 2010	(r211847)
+++ stable/8/sys/dev/cxgb/cxgb_adapter.h	Thu Aug 26 19:55:03 2010	(r211848)
@@ -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;
 
@@ -350,7 +352,6 @@ struct adapter {
 	struct filter_info      *filters;
 	
 	/* Tasks */
-	struct task		ext_intr_task;
 	struct task		slow_intr_task;
 	struct task		tick_task;
 	struct taskqueue	*tq;
@@ -388,6 +389,8 @@ struct adapter {
 	char                    reglockbuf[ADAPTER_LOCK_NAME_LEN];
 	char                    mdiolockbuf[ADAPTER_LOCK_NAME_LEN];
 	char                    elmerlockbuf[ADAPTER_LOCK_NAME_LEN];
+
+	int			timestamp;
 };
 
 struct t3_rx_mode {
@@ -493,12 +496,12 @@ 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);
 void t3_sge_err_intr_handler(adapter_t *adapter);
 int t3_offload_tx(struct t3cdev *, struct mbuf *);
-void t3_os_ext_intr_handler(adapter_t *adapter);
 void t3_os_set_hw_addr(adapter_t *adapter, int port_idx, u8 hw_addr[]);
 int t3_mgmt_tx(adapter_t *adap, struct mbuf *m);
 
@@ -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: stable/8/sys/dev/cxgb/cxgb_main.c
==============================================================================
--- stable/8/sys/dev/cxgb/cxgb_main.c	Thu Aug 26 16:01:29 2010	(r211847)
+++ stable/8/sys/dev/cxgb/cxgb_main.c	Thu Aug 26 19:55:03 2010	(r211848)
@@ -95,9 +95,10 @@ static void cxgb_build_medialist(struct 
 static void cxgb_media_status(struct ifnet *, struct ifmediareq *);
 static int setup_sge_qsets(adapter_t *);
 static void cxgb_async_intr(void *);
-static void cxgb_ext_intr_handler(void *, int);
 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 *);
@@ -238,6 +239,10 @@ TUNABLE_INT("hw.cxgb.snd_queue_len", &cx
 SYSCTL_UINT(_hw_cxgb, OID_AUTO, snd_queue_len, CTLFLAG_RDTUN,
     &cxgb_snd_queue_len, 0, "send queue size ");
 
+static int nfilters = -1;
+TUNABLE_INT("hw.cxgb.nfilters", &nfilters);
+SYSCTL_INT(_hw_cxgb, OID_AUTO, nfilters, CTLFLAG_RDTUN,
+    &nfilters, 0, "max number of entries in the filter table");
 
 enum {
 	MAX_TXQ_ENTRIES      = 16384,
@@ -582,7 +587,6 @@ cxgb_controller_attach(device_t dev)
 
 	taskqueue_start_threads(&sc->tq, 1, PI_NET, "%s taskq",
 	    device_get_nameunit(dev));
-	TASK_INIT(&sc->ext_intr_task, 0, cxgb_ext_intr_handler, sc);
 	TASK_INIT(&sc->tick_task, 0, cxgb_tick_handler, sc);
 
 	
@@ -666,7 +670,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)
@@ -974,7 +978,7 @@ cxgb_makedev(struct port_info *pi)
 {
 	
 	pi->port_cdev = make_dev(&cxgb_cdevsw, pi->ifp->if_dunit,
-	    UID_ROOT, GID_WHEEL, 0600, if_name(pi->ifp));
+	    UID_ROOT, GID_WHEEL, 0600, "%s", if_name(pi->ifp));
 	
 	if (pi->port_cdev == NULL)
 		return (ENOMEM);
@@ -1003,6 +1007,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) {
@@ -1259,29 +1266,6 @@ void t3_os_phymod_changed(struct adapter
 	}
 }
 
-/*
- * Interrupt-context handler for external (PHY) interrupts.
- */
-void
-t3_os_ext_intr_handler(adapter_t *sc)
-{
-	if (cxgb_debug)
-		printf("t3_os_ext_intr_handler\n");
-	/*
-	 * Schedule a task to handle external interrupts as they may be slow
-	 * and we use a mutex to protect MDIO registers.  We disable PHY
-	 * interrupts in the meantime and let the task reenable them when
-	 * it's done.
-	 */
-	if (sc->slow_intr_mask) {
-		ADAPTER_LOCK(sc);
-		sc->slow_intr_mask &= ~F_T3DBG;
-		t3_write_reg(sc, A_PL_INT_ENABLE0, sc->slow_intr_mask);
-		taskqueue_enqueue(sc->tq, &sc->ext_intr_task);
-		ADAPTER_UNLOCK(sc);
-	}
-}
-
 void
 t3_os_set_hw_addr(adapter_t *adapter, int port_idx, u8 hw_addr[])
 {
@@ -1650,6 +1634,7 @@ static int
 cxgb_up(struct adapter *sc)
 {
 	int err = 0;
+	unsigned int mxf = t3_mc5_size(&sc->mc5) - MC5_MIN_TIDS;
 
 	KASSERT(sc->open_device_map == 0, ("%s: device(s) already open (%x)",
 					   __func__, sc->open_device_map));
@@ -1666,11 +1651,13 @@ cxgb_up(struct adapter *sc)
 			if ((err = update_tpsram(sc)))
 				goto out;
 
-		if (is_offload(sc)) {
+		if (is_offload(sc) && nfilters != 0) {
 			sc->params.mc5.nservers = 0;
-			sc->params.mc5.nroutes = 0;
-			sc->params.mc5.nfilters = t3_mc5_size(&sc->mc5) -
-			    MC5_MIN_TIDS;
+
+			if (nfilters < 0)
+				sc->params.mc5.nfilters = mxf;
+			else
+				sc->params.mc5.nfilters = min(nfilters, mxf);
 		}
 
 		err = t3_init_hw(sc, 0);
@@ -1791,11 +1778,12 @@ cxgb_init_locked(struct port_info *p)
 	struct adapter *sc = p->adapter;
 	struct ifnet *ifp = p->ifp;
 	struct cmac *mac = &p->mac;
-	int i, rc = 0, may_sleep = 0;
+	int i, rc = 0, may_sleep = 0, gave_up_lock = 0;
 
 	ADAPTER_LOCK_ASSERT_OWNED(sc);
 
 	while (!IS_DOOMED(p) && IS_BUSY(sc)) {
+		gave_up_lock = 1;
 		if (mtx_sleep(&sc->flags, &sc->lock, PCATCH, "cxgbinit", 0)) {
 			rc = EINTR;
 			goto done;
@@ -1815,6 +1803,7 @@ cxgb_init_locked(struct port_info *p)
 
 	if (may_sleep) {
 		SET_BUSY(sc);
+		gave_up_lock = 1;
 		ADAPTER_UNLOCK(sc);
 	}
 
@@ -1843,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];
@@ -1855,14 +1842,18 @@ 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) {
 		ADAPTER_LOCK(sc);
 		KASSERT(IS_BUSY(sc), ("%s: controller not busy.", __func__));
 		CLR_BUSY(sc);
-		wakeup_one(&sc->flags);
 	}
+	if (gave_up_lock)
+		wakeup_one(&sc->flags);
 	ADAPTER_UNLOCK(sc);
 	return (rc);
 }
@@ -1928,9 +1919,11 @@ cxgb_uninit_synchronized(struct port_inf
 	clrbit(&sc->open_device_map, pi->port_id);
 	t3_port_intr_disable(sc, pi->port_id);
 	taskqueue_drain(sc->tq, &sc->slow_intr_task);
-	taskqueue_drain(sc->tq, &sc->ext_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);
 
@@ -2286,61 +2279,47 @@ cxgb_async_intr(void *data)
 {
 	adapter_t *sc = data;
 
-	if (cxgb_debug)
-		device_printf(sc->dev, "cxgb_async_intr\n");
-	/*
-	 * May need to sleep - defer to taskqueue
-	 */
+	t3_write_reg(sc, A_PL_INT_ENABLE0, 0);
+	(void) t3_read_reg(sc, A_PL_INT_ENABLE0);
 	taskqueue_enqueue(sc->tq, &sc->slow_intr_task);
 }
 
 static void
-cxgb_ext_intr_handler(void *arg, int count)
+link_check_callout(void *arg)
 {
-	adapter_t *sc = (adapter_t *)arg;
-
-	if (cxgb_debug)
-		printf("cxgb_ext_intr_handler\n");
+	struct port_info *pi = arg;
+	struct adapter *sc = pi->adapter;
 
-	t3_phy_intr_handler(sc);
+	if (!isset(&sc->open_device_map, pi->port_id))
+		return;
 
-	/* Now reenable external interrupts */
-	ADAPTER_LOCK(sc);
-	if (sc->slow_intr_mask) {
-		sc->slow_intr_mask |= F_T3DBG;
-		t3_write_reg(sc, A_PL_INT_CAUSE0, F_T3DBG);
-		t3_write_reg(sc, A_PL_INT_ENABLE0, sc->slow_intr_mask);
-	}
-	ADAPTER_UNLOCK(sc);
+	taskqueue_enqueue(sc->tq, &pi->link_check_task);
 }
 
-static inline int
-link_poll_needed(struct port_info *p)
+static void
+check_link_status(void *arg, int pending)
 {
-	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;
+
+	t3_link_changed(sc, pi->port_id);
 
-	return (p->link_fault || !(phy->caps & SUPPORTED_LINK_IRQ));
+	if (pi->link_fault || !(pi->phy.caps & SUPPORTED_LINK_IRQ))
+		callout_reset(&pi->link_check_ch, hz, link_check_callout, pi);
 }
 
-static void
-check_link_status(adapter_t *sc)
+void
+t3_os_link_intr(struct port_info *pi)
 {
-	int i;
-
-	for (i = 0; i < (sc)->params.nports; ++i) {
-		struct port_info *p = &sc->port[i];
-
-		if (!isset(&sc->open_device_map, p->port_id))
-			continue;
-
-		if (link_poll_needed(p))
-			t3_link_changed(sc, i);
-	}
+	/*
+	 * 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
@@ -2392,7 +2371,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
@@ -2406,8 +2385,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);
 
@@ -3077,7 +3054,6 @@ cxgb_extension_ioctl(struct cdev *dev, u
 		if (!error) {
 			v = (uint32_t *)buf;
 
-			ioqs->bufsize -= 4 * sizeof(uint32_t);
 			ioqs->ioq_rx_enable = *v++;
 			ioqs->ioq_tx_enable = *v++;
 			ioqs->ioq_rx_status = *v++;

Modified: stable/8/sys/dev/cxgb/cxgb_sge.c
==============================================================================
--- stable/8/sys/dev/cxgb/cxgb_sge.c	Thu Aug 26 16:01:29 2010	(r211847)
+++ stable/8/sys/dev/cxgb/cxgb_sge.c	Thu Aug 26 19:55:03 2010	(r211848)
@@ -910,6 +910,8 @@ sge_slow_intr_handler(void *arg, int nco
 	adapter_t *sc = arg;
 
 	t3_slow_intr_handler(sc);
+	t3_write_reg(sc, A_PL_INT_ENABLE0, sc->slow_intr_mask);
+	(void) t3_read_reg(sc, A_PL_INT_ENABLE0);
 }
 
 /**
@@ -2961,6 +2963,7 @@ process_responses(adapter_t *adap, struc
 	struct lro_ctrl *lro_ctrl = &qs->lro.ctrl;
 	struct mbuf *offload_mbufs[RX_BUNDLE_SIZE];
 	int ngathered = 0;
+	struct t3_mbuf_hdr *mh = &rspq->rspq_mh;
 #ifdef DEBUG	
 	static int last_holdoff = 0;
 	if (cxgb_debug && rspq->holdoff_tmr != last_holdoff) {
@@ -2984,9 +2987,9 @@ process_responses(adapter_t *adap, struc
 			if (cxgb_debug)
 				printf("async notification\n");
 
-			if (rspq->rspq_mh.mh_head == NULL) {
-				rspq->rspq_mh.mh_head = m_gethdr(M_DONTWAIT, MT_DATA);
-				m = rspq->rspq_mh.mh_head;
+			if (mh->mh_head == NULL) {
+				mh->mh_head = m_gethdr(M_DONTWAIT, MT_DATA);
+				m = mh->mh_head;
 			} else {
 				m = m_gethdr(M_DONTWAIT, MT_DATA);
 			}
@@ -3005,27 +3008,28 @@ process_responses(adapter_t *adap, struc
 
 			DPRINTF("IMM DATA VALID opcode=0x%x rspq->cidx=%d\n",
 			    r->rss_hdr.opcode, rspq->cidx);
-			if (rspq->rspq_mh.mh_head == NULL)
-				rspq->rspq_mh.mh_head = m_gethdr(M_DONTWAIT, MT_DATA);
+			if (mh->mh_head == NULL)
+				mh->mh_head = m_gethdr(M_DONTWAIT, MT_DATA);
                         else 
 				m = m_gethdr(M_DONTWAIT, MT_DATA);
 
-			if (rspq->rspq_mh.mh_head == NULL &&  m == NULL) {	
+			if (mh->mh_head == NULL &&  m == NULL) {	
 		no_mem:
 				rspq->next_holdoff = NOMEM_INTR_DELAY;
 				budget_left--;
 				break;
 			}
-			get_imm_packet(adap, r, rspq->rspq_mh.mh_head);
+			get_imm_packet(adap, r, mh->mh_head);
 			eop = 1;
 			rspq->imm_data++;
 		} else if (r->len_cq) {
 			int drop_thresh = eth ? SGE_RX_DROP_THRES : 0;
 			
-			eop = get_packet(adap, drop_thresh, qs, &rspq->rspq_mh, r);
+			eop = get_packet(adap, drop_thresh, qs, mh, r);
 			if (eop) {
-				rspq->rspq_mh.mh_head->m_flags |= M_FLOWID;
-				rspq->rspq_mh.mh_head->m_pkthdr.flowid = rss_hash;
+				if (r->rss_hdr.hash_type && !adap->timestamp)
+					mh->mh_head->m_flags |= M_FLOWID;
+				mh->mh_head->m_pkthdr.flowid = rss_hash;
 			}
 			
 			ethpad = 2;
@@ -3050,20 +3054,20 @@ process_responses(adapter_t *adap, struc
 			rspq->credits = 0;
 		}
 		if (!eth && eop) {
-			rspq->rspq_mh.mh_head->m_pkthdr.csum_data = rss_csum;
+			mh->mh_head->m_pkthdr.csum_data = rss_csum;
 			/*
 			 * XXX size mismatch
 			 */
-			m_set_priority(rspq->rspq_mh.mh_head, rss_hash);
+			m_set_priority(mh->mh_head, rss_hash);
 
 			
 			ngathered = rx_offload(&adap->tdev, rspq,
-			    rspq->rspq_mh.mh_head, offload_mbufs, ngathered);
-			rspq->rspq_mh.mh_head = NULL;
+			    mh->mh_head, offload_mbufs, ngathered);
+			mh->mh_head = NULL;
 			DPRINTF("received offload packet\n");
 			
 		} else if (eth && eop) {
-			struct mbuf *m = rspq->rspq_mh.mh_head;
+			struct mbuf *m = mh->mh_head;
 
 			t3_rx_eth(adap, rspq, m, ethpad);
 
@@ -3092,7 +3096,7 @@ process_responses(adapter_t *adap, struc
 				struct ifnet *ifp = m->m_pkthdr.rcvif;
 				(*ifp->if_input)(ifp, m);
 			}
-			rspq->rspq_mh.mh_head = NULL;
+			mh->mh_head = NULL;
 
 		}
 		__refill_fl_lt(adap, &qs->fl[0], 32);
@@ -3166,8 +3170,11 @@ t3b_intr(void *data)
 	if (!map) 
 		return;
 
-	if (__predict_false(map & F_ERRINTR))
+	if (__predict_false(map & F_ERRINTR)) {
+		t3_write_reg(adap, A_PL_INT_ENABLE0, 0);
+		(void) t3_read_reg(adap, A_PL_INT_ENABLE0);
 		taskqueue_enqueue(adap->tq, &adap->slow_intr_task);
+	}
 
 	mtx_lock(&q0->lock);
 	for_each_port(adap, i)
@@ -3195,8 +3202,11 @@ t3_intr_msi(void *data)
 	    if (process_responses_gts(adap, &adap->sge.qs[i].rspq)) 
 		    new_packets = 1;
 	mtx_unlock(&q0->lock);
-	if (new_packets == 0)
+	if (new_packets == 0) {
+		t3_write_reg(adap, A_PL_INT_ENABLE0, 0);
+		(void) t3_read_reg(adap, A_PL_INT_ENABLE0);
 		taskqueue_enqueue(adap->tq, &adap->slow_intr_task);
+	}
 }
 
 void
@@ -3459,6 +3469,29 @@ t3_set_coalesce_usecs(SYSCTL_HANDLER_ARG
 	return (0);
 }
 
+static int
+t3_pkt_timestamp(SYSCTL_HANDLER_ARGS)
+{
+	adapter_t *sc = arg1;
+	int rc, timestamp;
+
+	if ((sc->flags & FULL_INIT_DONE) == 0)
+		return (ENXIO);
+
+	timestamp = sc->timestamp;
+	rc = sysctl_handle_int(oidp, &timestamp, arg2, req);
+
+	if (rc != 0)
+		return (rc);
+
+	if (timestamp != sc->timestamp) {
+		t3_set_reg_field(sc, A_TP_PC_CONFIG2, F_ENABLERXPKTTMSTPRSS,
+		    timestamp ? F_ENABLERXPKTTMSTPRSS : 0);
+		sc->timestamp = timestamp;
+	}
+
+	return (0);
+}
 
 void
 t3_add_attach_sysctls(adapter_t *sc)
@@ -3493,6 +3526,10 @@ t3_add_attach_sysctls(adapter_t *sc)
 	    "txq_overrun",
 	    CTLFLAG_RD, &txq_fills,
 	    0, "#times txq overrun");
+	SYSCTL_ADD_INT(ctx, children, OID_AUTO, 
+	    "core_clock",
+	    CTLFLAG_RD, &sc->params.vpd.cclk,
+	    0, "core clock frequency (in KHz)");
 }
 
 
@@ -3537,6 +3574,12 @@ t3_add_configured_sysctls(adapter_t *sc)
 	    0, t3_set_coalesce_usecs,
 	    "I", "interrupt coalescing timer (us)");
 
+	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, 
+	    "pkt_timestamp",
+	    CTLTYPE_INT | CTLFLAG_RW, sc,
+	    0, t3_pkt_timestamp,
+	    "I", "provide packet timestamp instead of connection hash");
+
 	for (i = 0; i < sc->params.nports; i++) {
 		struct port_info *pi = &sc->port[i];
 		struct sysctl_oid *poid;


More information about the svn-src-stable mailing list