]> err.no Git - linux-2.6/commitdiff
[TG3]: Add 1000T & 1000X flowctrl resolvers
authorMatt Carlson <mcarlson@broadcom.com>
Fri, 21 Dec 2007 04:06:19 +0000 (20:06 -0800)
committerDavid S. Miller <davem@davemloft.net>
Mon, 28 Jan 2008 22:59:30 +0000 (14:59 -0800)
This patch adds two new utility functions to resolve flow control.  One
function resolves flow control based on 1000-BaseT register definitions.
The other resolves flow control based on 1000-Base X register
definitions.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/tg3.c

index ad0289ab26c9ba4c6fefd3378a15ce0aed4c44df..b571b20ce6eca907434c48aeaf56e9351bbc31a7 100644 (file)
@@ -1612,6 +1612,50 @@ static void tg3_link_report(struct tg3 *tp)
        }
 }
 
+static u8 tg3_resolve_flowctrl_1000T(u16 lcladv, u16 rmtadv)
+{
+       u8 cap = 0;
+
+       if (lcladv & ADVERTISE_PAUSE_CAP) {
+               if (lcladv & ADVERTISE_PAUSE_ASYM) {
+                       if (rmtadv & LPA_PAUSE_CAP)
+                               cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX;
+                       else if (rmtadv & LPA_PAUSE_ASYM)
+                               cap = TG3_FLOW_CTRL_RX;
+               } else {
+                       if (rmtadv & LPA_PAUSE_CAP)
+                               cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX;
+               }
+       } else if (lcladv & ADVERTISE_PAUSE_ASYM) {
+               if ((rmtadv & LPA_PAUSE_CAP) && (rmtadv & LPA_PAUSE_ASYM))
+                       cap = TG3_FLOW_CTRL_TX;
+       }
+
+       return cap;
+}
+
+static u8 tg3_resolve_flowctrl_1000X(u16 lcladv, u16 rmtadv)
+{
+       u8 cap = 0;
+
+       if (lcladv & ADVERTISE_1000XPAUSE) {
+               if (lcladv & ADVERTISE_1000XPSE_ASYM) {
+                       if (rmtadv & LPA_1000XPAUSE)
+                               cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX;
+                       else if (rmtadv & LPA_1000XPAUSE_ASYM)
+                               cap = TG3_FLOW_CTRL_RX;
+               } else {
+                       if (rmtadv & LPA_1000XPAUSE)
+                               cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX;
+               }
+       } else if (lcladv & ADVERTISE_1000XPSE_ASYM) {
+               if ((rmtadv & LPA_1000XPAUSE) && (rmtadv & LPA_1000XPAUSE_ASYM))
+                       cap = TG3_FLOW_CTRL_TX;
+       }
+
+       return cap;
+}
+
 static void tg3_setup_flow_control(struct tg3 *tp, u32 local_adv, u32 remote_adv)
 {
        u8 new_tg3_flags = 0;
@@ -1619,42 +1663,12 @@ static void tg3_setup_flow_control(struct tg3 *tp, u32 local_adv, u32 remote_adv
        u32 old_tx_mode = tp->tx_mode;
 
        if (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) {
-
-               /* Convert 1000BaseX flow control bits to 1000BaseT
-                * bits before resolving flow control.
-                */
-               if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) {
-                       local_adv &= ~(ADVERTISE_PAUSE_CAP |
-                                      ADVERTISE_PAUSE_ASYM);
-                       remote_adv &= ~(LPA_PAUSE_CAP | LPA_PAUSE_ASYM);
-
-                       if (local_adv & ADVERTISE_1000XPAUSE)
-                               local_adv |= ADVERTISE_PAUSE_CAP;
-                       if (local_adv & ADVERTISE_1000XPSE_ASYM)
-                               local_adv |= ADVERTISE_PAUSE_ASYM;
-                       if (remote_adv & LPA_1000XPAUSE)
-                               remote_adv |= LPA_PAUSE_CAP;
-                       if (remote_adv & LPA_1000XPAUSE_ASYM)
-                               remote_adv |= LPA_PAUSE_ASYM;
-               }
-
-               if (local_adv & ADVERTISE_PAUSE_CAP) {
-                       if (local_adv & ADVERTISE_PAUSE_ASYM) {
-                               if (remote_adv & LPA_PAUSE_CAP)
-                                       new_tg3_flags = TG3_FLOW_CTRL_RX |
-                                                       TG3_FLOW_CTRL_TX;
-                               else if (remote_adv & LPA_PAUSE_ASYM)
-                                       new_tg3_flags = TG3_FLOW_CTRL_RX;
-                       } else {
-                               if (remote_adv & LPA_PAUSE_CAP)
-                                       new_tg3_flags = TG3_FLOW_CTRL_RX |
-                                                       TG3_FLOW_CTRL_TX;
-                       }
-               } else if (local_adv & ADVERTISE_PAUSE_ASYM) {
-                       if ((remote_adv & LPA_PAUSE_CAP) &&
-                           (remote_adv & LPA_PAUSE_ASYM))
-                               new_tg3_flags = TG3_FLOW_CTRL_TX;
-               }
+               if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES)
+                       new_tg3_flags = tg3_resolve_flowctrl_1000X(local_adv,
+                                                                  remote_adv);
+               else
+                       new_tg3_flags = tg3_resolve_flowctrl_1000T(local_adv,
+                                                                  remote_adv);
        } else {
                new_tg3_flags = tp->link_config.flowctrl;
        }