}
}
+static u16 tg3_advert_flowctrl_1000T(u8 flow_ctrl)
+{
+ u16 miireg;
+
+ if ((flow_ctrl & TG3_FLOW_CTRL_TX) && (flow_ctrl & TG3_FLOW_CTRL_RX))
+ miireg = ADVERTISE_PAUSE_CAP;
+ else if (flow_ctrl & TG3_FLOW_CTRL_TX)
+ miireg = ADVERTISE_PAUSE_ASYM;
+ else if (flow_ctrl & TG3_FLOW_CTRL_RX)
+ miireg = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
+ else
+ miireg = 0;
+
+ return miireg;
+}
+
+static u16 tg3_advert_flowctrl_1000X(u8 flow_ctrl)
+{
+ u16 miireg;
+
+ if ((flow_ctrl & TG3_FLOW_CTRL_TX) && (flow_ctrl & TG3_FLOW_CTRL_RX))
+ miireg = ADVERTISE_1000XPAUSE;
+ else if (flow_ctrl & TG3_FLOW_CTRL_TX)
+ miireg = ADVERTISE_1000XPSE_ASYM;
+ else if (flow_ctrl & TG3_FLOW_CTRL_RX)
+ miireg = ADVERTISE_1000XPAUSE | ADVERTISE_1000XPSE_ASYM;
+ else
+ miireg = 0;
+
+ return miireg;
+}
+
static u8 tg3_resolve_flowctrl_1000T(u16 lcladv, u16 rmtadv)
{
u8 cap = 0;
~(ADVERTISED_1000baseT_Half |
ADVERTISED_1000baseT_Full);
- new_adv = (ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
+ new_adv = ADVERTISE_CSMA;
if (tp->link_config.advertising & ADVERTISED_10baseT_Half)
new_adv |= ADVERTISE_10HALF;
if (tp->link_config.advertising & ADVERTISED_10baseT_Full)
new_adv |= ADVERTISE_100HALF;
if (tp->link_config.advertising & ADVERTISED_100baseT_Full)
new_adv |= ADVERTISE_100FULL;
+
+ new_adv |= tg3_advert_flowctrl_1000T(tp->link_config.flowctrl);
+
tg3_writephy(tp, MII_ADVERTISE, new_adv);
if (tp->link_config.advertising &
tg3_writephy(tp, MII_TG3_CTRL, 0);
}
} else {
+ new_adv = tg3_advert_flowctrl_1000T(tp->link_config.flowctrl);
+ new_adv |= ADVERTISE_CSMA;
+
/* Asking for a specific link mode. */
if (tp->link_config.speed == SPEED_1000) {
- new_adv = ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP;
tg3_writephy(tp, MII_ADVERTISE, new_adv);
if (tp->link_config.duplex == DUPLEX_FULL)
tp->pci_chip_rev_id == CHIPREV_ID_5701_B0)
new_adv |= (MII_TG3_CTRL_AS_MASTER |
MII_TG3_CTRL_ENABLE_AS_MASTER);
- tg3_writephy(tp, MII_TG3_CTRL, new_adv);
} else {
- tg3_writephy(tp, MII_TG3_CTRL, 0);
-
- new_adv = ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP;
if (tp->link_config.speed == SPEED_100) {
if (tp->link_config.duplex == DUPLEX_FULL)
new_adv |= ADVERTISE_100FULL;
new_adv |= ADVERTISE_10HALF;
}
tg3_writephy(tp, MII_ADVERTISE, new_adv);
+
+ new_adv = 0;
}
+
+ tg3_writephy(tp, MII_TG3_CTRL, new_adv);
}
if (tp->link_config.autoneg == AUTONEG_DISABLE &&
if (tg3_readphy(tp, MII_ADVERTISE, &local_adv))
local_adv = 0;
- local_adv &= (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
if (tg3_readphy(tp, MII_LPA, &remote_adv))
remote_adv = 0;
- remote_adv &= (LPA_PAUSE_CAP | LPA_PAUSE_ASYM);
-
- /* If we are not advertising full pause capability,
- * something is wrong. Bring the link down and reconfigure.
+ /* If we are not advertising what has been requested,
+ * bring the link down and reconfigure.
*/
- if (local_adv != ADVERTISE_PAUSE_CAP) {
+ if (local_adv !=
+ tg3_advert_flowctrl_1000T(tp->link_config.flowctrl)) {
current_link_up = 0;
} else {
tg3_setup_flow_control(tp, local_adv, remote_adv);
ADVERTISE_1000XPSE_ASYM |
ADVERTISE_SLCT);
- /* Always advertise symmetric PAUSE just like copper */
- new_adv |= ADVERTISE_1000XPAUSE;
+ new_adv |= tg3_advert_flowctrl_1000X(tp->link_config.flowctrl);
if (tp->link_config.advertising & ADVERTISED_1000baseT_Half)
new_adv |= ADVERTISE_1000XHALF;