cxgb4: Add support to recognize 40G links
authorKumar Sanghvi <kumaras@chelsio.com>
Tue, 18 Feb 2014 12:26:08 +0000 (17:56 +0530)
committerDavid S. Miller <davem@davemloft.net>
Tue, 18 Feb 2014 21:23:00 +0000 (16:23 -0500)
Also, create a new Common Code interface to translate Firmware Port Technology
Type values (enum fw_port_type) to string descriptions.  This will allow us
to maintain the description translation table in one place rather than in
every driver.

Based on original work by Scott Bardone and Casey Leedom <leedom@chelsio.com>

Signed-off-by: Kumar Sanghvi <kumaras@chelsio.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h

index 1f4b9b30b9ed0bbaa969014e4bf6c1162d439d98..0c4edd1db76189a38fa3d4e1cf96fc99b8191aa6 100644 (file)
@@ -957,7 +957,7 @@ int t4_mc_read(struct adapter *adap, int idx, u32 addr, __be32 *data,
               u64 *parity);
 int t4_edc_read(struct adapter *adap, int idx, u32 addr, __be32 *data,
                u64 *parity);
-
+const char *t4_get_port_type_description(enum fw_port_type port_type);
 void t4_get_port_stats(struct adapter *adap, int idx, struct port_stats *p);
 void t4_read_mtu_tbl(struct adapter *adap, u16 *mtus, u8 *mtu_log);
 void t4_tp_wr_bits_indirect(struct adapter *adap, unsigned int addr,
index bd0321d8b6123c31d2b3a4624cc2d54eac1f9865..1da4adb013b34126724d6c7638bf4f6e64df8ba8 100644 (file)
@@ -432,6 +432,9 @@ static void link_report(struct net_device *dev)
                case SPEED_100:
                        s = "100Mbps";
                        break;
+               case 40000: /* Need a SPEED_40000 in ethtool.h */
+                       s = "40Gbps";
+                       break;
                }
 
                netdev_info(dev, "link up, %s, full-duplex, %s PAUSE\n", s,
@@ -2199,6 +2202,8 @@ static unsigned int from_fw_linkcaps(unsigned int type, unsigned int caps)
        else if (type == FW_PORT_TYPE_FIBER_XFI ||
                 type == FW_PORT_TYPE_FIBER_XAUI || type == FW_PORT_TYPE_SFP)
                v |= SUPPORTED_FIBRE;
+       else if (type == FW_PORT_TYPE_BP40_BA)
+               v |= SUPPORTED_40000baseSR4_Full;
 
        if (caps & FW_PORT_CAP_ANEG)
                v |= SUPPORTED_Autoneg;
@@ -2215,6 +2220,8 @@ static unsigned int to_fw_linkcaps(unsigned int caps)
                v |= FW_PORT_CAP_SPEED_1G;
        if (caps & ADVERTISED_10000baseT_Full)
                v |= FW_PORT_CAP_SPEED_10G;
+       if (caps & ADVERTISED_40000baseSR4_Full)
+               v |= FW_PORT_CAP_SPEED_40G;
        return v;
 }
 
@@ -2269,6 +2276,8 @@ static unsigned int speed_to_caps(int speed)
                return FW_PORT_CAP_SPEED_1G;
        if (speed == SPEED_10000)
                return FW_PORT_CAP_SPEED_10G;
+       if (speed == 40000) /* Need SPEED_40000 in ethtool.h */
+               return FW_PORT_CAP_SPEED_40G;
        return 0;
 }
 
@@ -2296,8 +2305,10 @@ static int set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
        if (cmd->autoneg == AUTONEG_DISABLE) {
                cap = speed_to_caps(speed);
 
-               if (!(lc->supported & cap) || (speed == SPEED_1000) ||
-                   (speed == SPEED_10000))
+               if (!(lc->supported & cap) ||
+                   (speed == SPEED_1000) ||
+                   (speed == SPEED_10000) ||
+                   (speed == 40000))
                        return -EINVAL;
                lc->requested_speed = cap;
                lc->advertising = 0;
@@ -5799,11 +5810,6 @@ static int init_rss(struct adapter *adap)
 
 static void print_port_info(const struct net_device *dev)
 {
-       static const char *base[] = {
-               "R XFI", "R XAUI", "T SGMII", "T XFI", "T XAUI", "KX4", "CX4",
-               "KX", "KR", "R SFP+", "KR/KX", "KR/KX/KX4"
-       };
-
        char buf[80];
        char *bufp = buf;
        const char *spd = "";
@@ -5821,9 +5827,11 @@ static void print_port_info(const struct net_device *dev)
                bufp += sprintf(bufp, "1000/");
        if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_10G)
                bufp += sprintf(bufp, "10G/");
+       if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_40G)
+               bufp += sprintf(bufp, "40G/");
        if (bufp != buf)
                --bufp;
-       sprintf(bufp, "BASE-%s", base[pi->port_type]);
+       sprintf(bufp, "BASE-%s", t4_get_port_type_description(pi->port_type));
 
        netdev_info(dev, "Chelsio %s rev %d %s %sNIC PCIe x%d%s%s\n",
                    adap->params.vpd.id,
index 2c109343d57083a651bcaf9ef08772dd8029ec1f..514c525e99cf02e0b9625fb0936b388767ab8a7b 100644 (file)
@@ -1155,7 +1155,8 @@ out:
 }
 
 #define ADVERT_MASK (FW_PORT_CAP_SPEED_100M | FW_PORT_CAP_SPEED_1G |\
-                    FW_PORT_CAP_SPEED_10G | FW_PORT_CAP_ANEG)
+                    FW_PORT_CAP_SPEED_10G | FW_PORT_CAP_SPEED_40G | \
+                    FW_PORT_CAP_ANEG)
 
 /**
  *     t4_link_start - apply link configuration to MAC/PHY
@@ -2246,6 +2247,36 @@ static unsigned int get_mps_bg_map(struct adapter *adap, int idx)
        return 1 << idx;
 }
 
+/**
+ *      t4_get_port_type_description - return Port Type string description
+ *      @port_type: firmware Port Type enumeration
+ */
+const char *t4_get_port_type_description(enum fw_port_type port_type)
+{
+       static const char *const port_type_description[] = {
+               "R XFI",
+               "R XAUI",
+               "T SGMII",
+               "T XFI",
+               "T XAUI",
+               "KX4",
+               "CX4",
+               "KX",
+               "KR",
+               "R SFP+",
+               "KR/KX",
+               "KR/KX/KX4",
+               "R QSFP_10G",
+               "",
+               "R QSFP",
+               "R BP40_BA",
+       };
+
+       if (port_type < ARRAY_SIZE(port_type_description))
+               return port_type_description[port_type];
+       return "UNKNOWN";
+}
+
 /**
  *     t4_get_port_stats - collect port statistics
  *     @adap: the adapter
@@ -3538,6 +3569,8 @@ int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl)
                        speed = SPEED_1000;
                else if (stat & FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_10G))
                        speed = SPEED_10000;
+               else if (stat & FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_40G))
+                       speed = 40000; /* Need SPEED_40000 in ethtool.h */
 
                if (link_ok != lc->link_ok || speed != lc->speed ||
                    fc != lc->fc) {                    /* something changed */
index 74fea74ce0aa25a676045868fa0b48c4a3800860..af6e12480e511a2e0ef47c06375b4b13c7123fb2 100644 (file)
@@ -1742,6 +1742,9 @@ enum fw_port_type {
        FW_PORT_TYPE_SFP,
        FW_PORT_TYPE_BP_AP,
        FW_PORT_TYPE_BP4_AP,
+       FW_PORT_TYPE_QSFP_10G,
+       FW_PORT_TYPE_QSFP,
+       FW_PORT_TYPE_BP40_BA,
 
        FW_PORT_TYPE_NONE = FW_PORT_CMD_PTYPE_MASK
 };