cxgb4/cxgb4vf: fix flow control display for auto negotiation
authorRahul Lakkireddy <rahul.lakkireddy@chelsio.com>
Mon, 30 Dec 2019 12:44:08 +0000 (18:14 +0530)
committerDavid S. Miller <davem@davemloft.net>
Mon, 30 Dec 2019 22:40:42 +0000 (14:40 -0800)
As per 802.3-2005, Section Two, Annex 28B, Table 28B-2 [1], when
_only_ Rx pause is enabled, both symmetric and asymmetric pause
towards local device must be enabled. Also, firmware returns the local
device's flow control pause params as part of advertised capabilities
and negotiated params as part of current link attributes. So, fix up
ethtool's flow control pause params fetch logic to read from acaps,
instead of linkattr.

[1] https://standards.ieee.org/standard/802_3-2005.html

Fixes: c3168cabe1af ("cxgb4/cxgbvf: Handle 32-bit fw port capabilities")
Signed-off-by: Surendra Mobiya <surendra@chelsio.com>
Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h
drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c

index a70ac2097892d290f6ab183c9a076bdc8f4fc996..becee29f5df7a647981c142b5987c0d0fc652cd9 100644 (file)
@@ -504,6 +504,7 @@ struct link_config {
 
        enum cc_pause  requested_fc;     /* flow control user has requested */
        enum cc_pause  fc;               /* actual link flow control */
+       enum cc_pause  advertised_fc;    /* actual advertised flow control */
 
        enum cc_fec    requested_fec;    /* Forward Error Correction: */
        enum cc_fec    fec;              /* requested and actual in use */
index 20ab3b6285a2f750331aa14408dabf413c4c70bd..c837382ee522da107650f1c1f00c74741f7dda52 100644 (file)
@@ -807,8 +807,8 @@ static void get_pauseparam(struct net_device *dev,
        struct port_info *p = netdev_priv(dev);
 
        epause->autoneg = (p->link_cfg.requested_fc & PAUSE_AUTONEG) != 0;
-       epause->rx_pause = (p->link_cfg.fc & PAUSE_RX) != 0;
-       epause->tx_pause = (p->link_cfg.fc & PAUSE_TX) != 0;
+       epause->rx_pause = (p->link_cfg.advertised_fc & PAUSE_RX) != 0;
+       epause->tx_pause = (p->link_cfg.advertised_fc & PAUSE_TX) != 0;
 }
 
 static int set_pauseparam(struct net_device *dev,
index 19d18acfc9a6f3fc79050b5e32bfcf5cdb4621f9..844fdcf55118b232204ab87dac45b25dba5b6d18 100644 (file)
@@ -4089,7 +4089,8 @@ static inline fw_port_cap32_t cc_to_fwcap_pause(enum cc_pause cc_pause)
                if (cc_pause & PAUSE_TX)
                        fw_pause |= FW_PORT_CAP32_802_3_PAUSE;
                else
-                       fw_pause |= FW_PORT_CAP32_802_3_ASM_DIR;
+                       fw_pause |= FW_PORT_CAP32_802_3_ASM_DIR |
+                                   FW_PORT_CAP32_802_3_PAUSE;
        } else if (cc_pause & PAUSE_TX) {
                fw_pause |= FW_PORT_CAP32_802_3_ASM_DIR;
        }
@@ -8563,17 +8564,17 @@ static fw_port_cap32_t lstatus_to_fwcap(u32 lstatus)
 void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
 {
        const struct fw_port_cmd *cmd = (const void *)rpl;
-       int action = FW_PORT_CMD_ACTION_G(be32_to_cpu(cmd->action_to_len16));
-       struct adapter *adapter = pi->adapter;
+       fw_port_cap32_t pcaps, acaps, lpacaps, linkattr;
        struct link_config *lc = &pi->link_cfg;
-       int link_ok, linkdnrc;
-       enum fw_port_type port_type;
+       struct adapter *adapter = pi->adapter;
+       unsigned int speed, fc, fec, adv_fc;
        enum fw_port_module_type mod_type;
-       unsigned int speed, fc, fec;
-       fw_port_cap32_t pcaps, acaps, lpacaps, linkattr;
+       int action, link_ok, linkdnrc;
+       enum fw_port_type port_type;
 
        /* Extract the various fields from the Port Information message.
         */
+       action = FW_PORT_CMD_ACTION_G(be32_to_cpu(cmd->action_to_len16));
        switch (action) {
        case FW_PORT_ACTION_GET_PORT_INFO: {
                u32 lstatus = be32_to_cpu(cmd->u.info.lstatus_to_modtype);
@@ -8611,6 +8612,7 @@ void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
        }
 
        fec = fwcap_to_cc_fec(acaps);
+       adv_fc = fwcap_to_cc_pause(acaps);
        fc = fwcap_to_cc_pause(linkattr);
        speed = fwcap_to_speed(linkattr);
 
@@ -8667,7 +8669,9 @@ void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
        }
 
        if (link_ok != lc->link_ok || speed != lc->speed ||
-           fc != lc->fc || fec != lc->fec) {   /* something changed */
+           fc != lc->fc || adv_fc != lc->advertised_fc ||
+           fec != lc->fec) {
+               /* something changed */
                if (!link_ok && lc->link_ok) {
                        lc->link_down_rc = linkdnrc;
                        dev_warn_ratelimited(adapter->pdev_dev,
@@ -8677,6 +8681,7 @@ void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
                }
                lc->link_ok = link_ok;
                lc->speed = speed;
+               lc->advertised_fc = adv_fc;
                lc->fc = fc;
                lc->fec = fec;
 
index f6fc0875d5b0a285cf4dc5695debdf96b3cf2744..f4d41f968afa270df17efe4d4f502b79dab5c01e 100644 (file)
@@ -1690,8 +1690,8 @@ static void cxgb4vf_get_pauseparam(struct net_device *dev,
        struct port_info *pi = netdev_priv(dev);
 
        pauseparam->autoneg = (pi->link_cfg.requested_fc & PAUSE_AUTONEG) != 0;
-       pauseparam->rx_pause = (pi->link_cfg.fc & PAUSE_RX) != 0;
-       pauseparam->tx_pause = (pi->link_cfg.fc & PAUSE_TX) != 0;
+       pauseparam->rx_pause = (pi->link_cfg.advertised_fc & PAUSE_RX) != 0;
+       pauseparam->tx_pause = (pi->link_cfg.advertised_fc & PAUSE_TX) != 0;
 }
 
 /*
index ccca67cf4487d22d06f7c2b42dc6b16647cec8d0..57cfd10a99ecc8508735aa4d5accd96d75176ebb 100644 (file)
@@ -135,6 +135,7 @@ struct link_config {
 
        enum cc_pause   requested_fc;   /* flow control user has requested */
        enum cc_pause   fc;             /* actual link flow control */
+       enum cc_pause   advertised_fc;  /* actual advertised flow control */
 
        enum cc_fec     auto_fec;       /* Forward Error Correction: */
        enum cc_fec     requested_fec;  /*   "automatic" (IEEE 802.3), */
index 8a389d617a238048f268be38771e37c808dd84e7..9d49ff211cc1a50ed0d9404a05119fb70e63dd73 100644 (file)
@@ -1913,16 +1913,16 @@ static const char *t4vf_link_down_rc_str(unsigned char link_down_rc)
 static void t4vf_handle_get_port_info(struct port_info *pi,
                                      const struct fw_port_cmd *cmd)
 {
-       int action = FW_PORT_CMD_ACTION_G(be32_to_cpu(cmd->action_to_len16));
-       struct adapter *adapter = pi->adapter;
+       fw_port_cap32_t pcaps, acaps, lpacaps, linkattr;
        struct link_config *lc = &pi->link_cfg;
-       int link_ok, linkdnrc;
-       enum fw_port_type port_type;
+       struct adapter *adapter = pi->adapter;
+       unsigned int speed, fc, fec, adv_fc;
        enum fw_port_module_type mod_type;
-       unsigned int speed, fc, fec;
-       fw_port_cap32_t pcaps, acaps, lpacaps, linkattr;
+       int action, link_ok, linkdnrc;
+       enum fw_port_type port_type;
 
        /* Extract the various fields from the Port Information message. */
+       action = FW_PORT_CMD_ACTION_G(be32_to_cpu(cmd->action_to_len16));
        switch (action) {
        case FW_PORT_ACTION_GET_PORT_INFO: {
                u32 lstatus = be32_to_cpu(cmd->u.info.lstatus_to_modtype);
@@ -1982,6 +1982,7 @@ static void t4vf_handle_get_port_info(struct port_info *pi,
        }
 
        fec = fwcap_to_cc_fec(acaps);
+       adv_fc = fwcap_to_cc_pause(acaps);
        fc = fwcap_to_cc_pause(linkattr);
        speed = fwcap_to_speed(linkattr);
 
@@ -2012,7 +2013,9 @@ static void t4vf_handle_get_port_info(struct port_info *pi,
        }
 
        if (link_ok != lc->link_ok || speed != lc->speed ||
-           fc != lc->fc || fec != lc->fec) {   /* something changed */
+           fc != lc->fc || adv_fc != lc->advertised_fc ||
+           fec != lc->fec) {
+               /* something changed */
                if (!link_ok && lc->link_ok) {
                        lc->link_down_rc = linkdnrc;
                        dev_warn_ratelimited(adapter->pdev_dev,
@@ -2022,6 +2025,7 @@ static void t4vf_handle_get_port_info(struct port_info *pi,
                }
                lc->link_ok = link_ok;
                lc->speed = speed;
+               lc->advertised_fc = adv_fc;
                lc->fc = fc;
                lc->fec = fec;