cxgb4: avoid disabling FEC by default
authorGanesh Goudar <ganeshgr@chelsio.com>
Sat, 6 May 2017 08:55:06 +0000 (14:25 +0530)
committerDavid S. Miller <davem@davemloft.net>
Mon, 8 May 2017 19:00:57 +0000 (15:00 -0400)
Recent Chelsio firmware started using few port capablity bits to
manage FEC and as driver was not aware of FEC changes those bits
were zeroed, consequently disabling FEC.

Avoid zeroing those bits and default to whatever the firmware
tells us the Link is currently advertising.

Signed-off-by: Ganesh Goudar <ganeshgr@chelsio.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h

index 163543b1ea0bf1bec215f0613a6bce2a729fa337..862e0083420b6fdaa886eda3f5c6a8cc441d65e9 100644 (file)
@@ -108,6 +108,12 @@ enum {
        PAUSE_AUTONEG = 1 << 2
 };
 
+enum {
+       FEC_AUTO      = 1 << 0,  /* IEEE 802.3 "automatic" */
+       FEC_RS        = 1 << 1,  /* Reed-Solomon */
+       FEC_BASER_RS  = 1 << 2   /* BaseR/Reed-Solomon */
+};
+
 struct port_stats {
        u64 tx_octets;            /* total # of octets in good frames */
        u64 tx_frames;            /* all good frames */
@@ -432,6 +438,9 @@ struct link_config {
        unsigned int   speed;            /* actual link speed */
        unsigned char  requested_fc;     /* flow control user has requested */
        unsigned char  fc;               /* actual link flow control */
+       unsigned char  auto_fec;         /* Forward Error Correction: */
+       unsigned char  requested_fec;    /* "automatic" (IEEE 802.3), */
+       unsigned char  fec;              /* requested, and actual in use */
        unsigned char  autoneg;          /* autonegotiating? */
        unsigned char  link_ok;          /* link up? */
        unsigned char  link_down_rc;     /* link down reason */
index 0de8eb72325c53ae50cd3ec535915486a9fb5064..aded42b96f6d966ba7e814c0a89c738968a655b6 100644 (file)
@@ -3707,7 +3707,8 @@ int t4_link_l1cfg(struct adapter *adap, unsigned int mbox, unsigned int port,
                  struct link_config *lc)
 {
        struct fw_port_cmd c;
-       unsigned int fc = 0, mdi = FW_PORT_CAP_MDI_V(FW_PORT_CAP_MDI_AUTO);
+       unsigned int mdi = FW_PORT_CAP_MDI_V(FW_PORT_CAP_MDI_AUTO);
+       unsigned int fc = 0, fec = 0, fw_fec = 0;
 
        lc->link_ok = 0;
        if (lc->requested_fc & PAUSE_RX)
@@ -3715,6 +3716,13 @@ int t4_link_l1cfg(struct adapter *adap, unsigned int mbox, unsigned int port,
        if (lc->requested_fc & PAUSE_TX)
                fc |= FW_PORT_CAP_FC_TX;
 
+       fec = lc->requested_fec & FEC_AUTO ? lc->auto_fec : lc->requested_fec;
+
+       if (fec & FEC_RS)
+               fw_fec |= FW_PORT_CAP_FEC_RS;
+       if (fec & FEC_BASER_RS)
+               fw_fec |= FW_PORT_CAP_FEC_BASER_RS;
+
        memset(&c, 0, sizeof(c));
        c.op_to_portid = cpu_to_be32(FW_CMD_OP_V(FW_PORT_CMD) |
                                     FW_CMD_REQUEST_F | FW_CMD_EXEC_F |
@@ -3725,13 +3733,15 @@ int t4_link_l1cfg(struct adapter *adap, unsigned int mbox, unsigned int port,
 
        if (!(lc->supported & FW_PORT_CAP_ANEG)) {
                c.u.l1cfg.rcap = cpu_to_be32((lc->supported & ADVERT_MASK) |
-                                            fc);
+                                            fc | fw_fec);
                lc->fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
        } else if (lc->autoneg == AUTONEG_DISABLE) {
-               c.u.l1cfg.rcap = cpu_to_be32(lc->requested_speed | fc | mdi);
+               c.u.l1cfg.rcap = cpu_to_be32(lc->requested_speed | fc |
+                                            fw_fec | mdi);
                lc->fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
        } else
-               c.u.l1cfg.rcap = cpu_to_be32(lc->advertising | fc | mdi);
+               c.u.l1cfg.rcap = cpu_to_be32(lc->advertising | fc |
+                                            fw_fec | mdi);
 
        return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
 }
@@ -7407,13 +7417,26 @@ static void get_pci_mode(struct adapter *adapter, struct pci_params *p)
  *     Initializes the SW state maintained for each link, including the link's
  *     capabilities and default speed/flow-control/autonegotiation settings.
  */
-static void init_link_config(struct link_config *lc, unsigned int caps)
+static void init_link_config(struct link_config *lc, unsigned int pcaps,
+                            unsigned int acaps)
 {
-       lc->supported = caps;
+       lc->supported = pcaps;
        lc->lp_advertising = 0;
        lc->requested_speed = 0;
        lc->speed = 0;
        lc->requested_fc = lc->fc = PAUSE_RX | PAUSE_TX;
+       lc->auto_fec = 0;
+
+       /* For Forward Error Control, we default to whatever the Firmware
+        * tells us the Link is currently advertising.
+        */
+       if (acaps & FW_PORT_CAP_FEC_RS)
+               lc->auto_fec |= FEC_RS;
+       if (acaps & FW_PORT_CAP_FEC_BASER_RS)
+               lc->auto_fec |= FEC_BASER_RS;
+       lc->requested_fec = FEC_AUTO;
+       lc->fec = lc->auto_fec;
+
        if (lc->supported & FW_PORT_CAP_ANEG) {
                lc->advertising = lc->supported & ADVERT_MASK;
                lc->autoneg = AUTONEG_ENABLE;
@@ -7991,7 +8014,8 @@ int t4_init_portinfo(struct port_info *pi, int mbox,
        pi->port_type = FW_PORT_CMD_PTYPE_G(ret);
        pi->mod_type = FW_PORT_MOD_TYPE_NA;
 
-       init_link_config(&pi->link_cfg, be16_to_cpu(c.u.info.pcap));
+       init_link_config(&pi->link_cfg, be16_to_cpu(c.u.info.pcap),
+                        be16_to_cpu(c.u.info.acap));
        return 0;
 }
 
index 8f8c079d0d2b89be66fc49005bc1d50bf32265c7..251a35e9795c56e943fce354f26b45bcddae8d1c 100644 (file)
@@ -2263,9 +2263,9 @@ enum fw_port_cap {
        FW_PORT_CAP_ANEG                = 0x0100,
        FW_PORT_CAP_MDIX                = 0x0200,
        FW_PORT_CAP_MDIAUTO             = 0x0400,
-       FW_PORT_CAP_FEC                 = 0x0800,
-       FW_PORT_CAP_TECHKR              = 0x1000,
-       FW_PORT_CAP_TECHKX4             = 0x2000,
+       FW_PORT_CAP_FEC_RS              = 0x0800,
+       FW_PORT_CAP_FEC_BASER_RS        = 0x1000,
+       FW_PORT_CAP_FEC_RESERVED        = 0x2000,
        FW_PORT_CAP_802_3_PAUSE         = 0x4000,
        FW_PORT_CAP_802_3_ASM_DIR       = 0x8000,
 };