summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornp <np@FreeBSD.org>2010-08-15 20:45:16 +0000
committernp <np@FreeBSD.org>2010-08-15 20:45:16 +0000
commit82b574175c110ed0f47a86a38ffa0e36c7cabe54 (patch)
tree161fcb594d45acf98541923a316dc316c2e40f3b
parent18dccf2b7363f7ef638fc90ad747e3201f200ae9 (diff)
downloadFreeBSD-src-82b574175c110ed0f47a86a38ffa0e36c7cabe54.zip
FreeBSD-src-82b574175c110ed0f47a86a38ffa0e36c7cabe54.tar.gz
Always reset the XGMAC's XAUI PCS on a link up.
MFC after: 3 days
-rw-r--r--sys/dev/cxgb/common/cxgb_common.h1
-rw-r--r--sys/dev/cxgb/common/cxgb_t3_hw.c38
-rw-r--r--sys/dev/cxgb/common/cxgb_xgmac.c31
3 files changed, 58 insertions, 12 deletions
diff --git a/sys/dev/cxgb/common/cxgb_common.h b/sys/dev/cxgb/common/cxgb_common.h
index 1501e16..3760bd6 100644
--- a/sys/dev/cxgb/common/cxgb_common.h
+++ b/sys/dev/cxgb/common/cxgb_common.h
@@ -745,6 +745,7 @@ int t3_mc7_bd_read(struct mc7 *mc7, unsigned int start, unsigned int n,
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);
diff --git a/sys/dev/cxgb/common/cxgb_t3_hw.c b/sys/dev/cxgb/common/cxgb_t3_hw.c
index ce27407..610a481 100644
--- a/sys/dev/cxgb/common/cxgb_t3_hw.c
+++ b/sys/dev/cxgb/common/cxgb_t3_hw.c
@@ -1558,6 +1558,13 @@ void t3_link_changed(adapter_t *adapter, int port_id)
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 {
@@ -1584,12 +1591,20 @@ void t3_link_changed(adapter_t *adapter, int port_id)
/* 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);
@@ -1609,20 +1624,21 @@ void t3_link_changed(adapter_t *adapter, int port_id)
t3_set_reg_field(adapter,
A_XGM_INT_ENABLE + mac->offset,
F_XGM_INT, 0);
- }
- if (!link_fault)
t3_mac_disable(mac, MAC_DIRECTION_RX);
- /*
- * 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,
diff --git a/sys/dev/cxgb/common/cxgb_xgmac.c b/sys/dev/cxgb/common/cxgb_xgmac.c
index 853da35..3ee2bf0 100644
--- a/sys/dev/cxgb/common/cxgb_xgmac.c
+++ b/sys/dev/cxgb/common/cxgb_xgmac.c
@@ -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
OpenPOWER on IntegriCloud