]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/net/qlcnic/qlcnic_ethtool.c
Merge branch 'master' into for-linus
[karo-tx-linux.git] / drivers / net / qlcnic / qlcnic_ethtool.c
index 6a760140f79295bcd39cc0a0778bcef3c564ab4d..25e93a53fca0954e41728e9c55e31305ee62cc53 100644 (file)
@@ -78,7 +78,25 @@ static const struct qlcnic_stats qlcnic_gstrings_stats[] = {
 
 };
 
+static const char qlcnic_device_gstrings_stats[][ETH_GSTRING_LEN] = {
+       "rx unicast frames",
+       "rx multicast frames",
+       "rx broadcast frames",
+       "rx dropped frames",
+       "rx errors",
+       "rx local frames",
+       "rx numbytes",
+       "tx unicast frames",
+       "tx multicast frames",
+       "tx broadcast frames",
+       "tx dropped frames",
+       "tx errors",
+       "tx local frames",
+       "tx numbytes",
+};
+
 #define QLCNIC_STATS_LEN       ARRAY_SIZE(qlcnic_gstrings_stats)
+#define QLCNIC_DEVICE_STATS_LEN        ARRAY_SIZE(qlcnic_device_gstrings_stats)
 
 static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = {
        "Register_Test_on_offline",
@@ -96,7 +114,7 @@ static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = {
 static const u32 diag_registers[] = {
        CRB_CMDPEG_STATE,
        CRB_RCVPEG_STATE,
-       CRB_XG_STATE_P3,
+       CRB_XG_STATE_P3P,
        CRB_FW_CAPABILITIES_1,
        ISR_INT_STATE_REG,
        QLCNIC_CRB_DRV_ACTIVE,
@@ -189,9 +207,9 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
                        goto skip;
                }
 
-               val = QLCRD32(adapter, P3_LINK_SPEED_REG(pcifn));
-               ecmd->speed = P3_LINK_SPEED_MHZ *
-                       P3_LINK_SPEED_VAL(pcifn, val);
+               val = QLCRD32(adapter, P3P_LINK_SPEED_REG(pcifn));
+               ecmd->speed = P3P_LINK_SPEED_MHZ *
+                       P3P_LINK_SPEED_VAL(pcifn, val);
                ecmd->duplex = DUPLEX_FULL;
                ecmd->autoneg = AUTONEG_DISABLE;
        } else
@@ -202,42 +220,42 @@ skip:
        ecmd->transceiver = XCVR_EXTERNAL;
 
        switch (adapter->ahw.board_type) {
-       case QLCNIC_BRDTYPE_P3_REF_QG:
-       case QLCNIC_BRDTYPE_P3_4_GB:
-       case QLCNIC_BRDTYPE_P3_4_GB_MM:
+       case QLCNIC_BRDTYPE_P3P_REF_QG:
+       case QLCNIC_BRDTYPE_P3P_4_GB:
+       case QLCNIC_BRDTYPE_P3P_4_GB_MM:
 
                ecmd->supported |= SUPPORTED_Autoneg;
                ecmd->advertising |= ADVERTISED_Autoneg;
-       case QLCNIC_BRDTYPE_P3_10G_CX4:
-       case QLCNIC_BRDTYPE_P3_10G_CX4_LP:
-       case QLCNIC_BRDTYPE_P3_10000_BASE_T:
+       case QLCNIC_BRDTYPE_P3P_10G_CX4:
+       case QLCNIC_BRDTYPE_P3P_10G_CX4_LP:
+       case QLCNIC_BRDTYPE_P3P_10000_BASE_T:
                ecmd->supported |= SUPPORTED_TP;
                ecmd->advertising |= ADVERTISED_TP;
                ecmd->port = PORT_TP;
                ecmd->autoneg =  adapter->link_autoneg;
                break;
-       case QLCNIC_BRDTYPE_P3_IMEZ:
-       case QLCNIC_BRDTYPE_P3_XG_LOM:
-       case QLCNIC_BRDTYPE_P3_HMEZ:
+       case QLCNIC_BRDTYPE_P3P_IMEZ:
+       case QLCNIC_BRDTYPE_P3P_XG_LOM:
+       case QLCNIC_BRDTYPE_P3P_HMEZ:
                ecmd->supported |= SUPPORTED_MII;
                ecmd->advertising |= ADVERTISED_MII;
                ecmd->port = PORT_MII;
                ecmd->autoneg = AUTONEG_DISABLE;
                break;
-       case QLCNIC_BRDTYPE_P3_10G_SFP_PLUS:
-       case QLCNIC_BRDTYPE_P3_10G_SFP_CT:
-       case QLCNIC_BRDTYPE_P3_10G_SFP_QT:
+       case QLCNIC_BRDTYPE_P3P_10G_SFP_PLUS:
+       case QLCNIC_BRDTYPE_P3P_10G_SFP_CT:
+       case QLCNIC_BRDTYPE_P3P_10G_SFP_QT:
                ecmd->advertising |= ADVERTISED_TP;
                ecmd->supported |= SUPPORTED_TP;
                check_sfp_module = netif_running(dev) &&
                        adapter->has_link_events;
-       case QLCNIC_BRDTYPE_P3_10G_XFP:
+       case QLCNIC_BRDTYPE_P3P_10G_XFP:
                ecmd->supported |= SUPPORTED_FIBRE;
                ecmd->advertising |= ADVERTISED_FIBRE;
                ecmd->port = PORT_FIBRE;
                ecmd->autoneg = AUTONEG_DISABLE;
                break;
-       case QLCNIC_BRDTYPE_P3_10G_TP:
+       case QLCNIC_BRDTYPE_P3P_10G_TP:
                if (adapter->ahw.port_type == QLCNIC_XGBE) {
                        ecmd->autoneg = AUTONEG_DISABLE;
                        ecmd->supported |= (SUPPORTED_FIBRE | SUPPORTED_TP);
@@ -381,9 +399,9 @@ static u32 qlcnic_test_link(struct net_device *dev)
        struct qlcnic_adapter *adapter = netdev_priv(dev);
        u32 val;
 
-       val = QLCRD32(adapter, CRB_XG_STATE_P3);
-       val = XG_LINK_STATE_P3(adapter->ahw.pci_func, val);
-       return (val == XG_LINK_UP_P3) ? 0 : 1;
+       val = QLCRD32(adapter, CRB_XG_STATE_P3P);
+       val = XG_LINK_STATE_P3P(adapter->ahw.pci_func, val);
+       return (val == XG_LINK_UP_P3P) ? 0 : 1;
 }
 
 static int
@@ -625,10 +643,13 @@ static int qlcnic_reg_test(struct net_device *dev)
 
 static int qlcnic_get_sset_count(struct net_device *dev, int sset)
 {
+       struct qlcnic_adapter *adapter = netdev_priv(dev);
        switch (sset) {
        case ETH_SS_TEST:
                return QLCNIC_TEST_LEN;
        case ETH_SS_STATS:
+               if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
+                       return QLCNIC_STATS_LEN + QLCNIC_DEVICE_STATS_LEN;
                return QLCNIC_STATS_LEN;
        default:
                return -EOPNOTSUPP;
@@ -706,6 +727,11 @@ static int qlcnic_loopback_test(struct net_device *netdev)
        if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
                return -EIO;
 
+       if (qlcnic_request_quiscent_mode(adapter)) {
+               clear_bit(__QLCNIC_RESETTING, &adapter->state);
+               return -EIO;
+       }
+
        ret = qlcnic_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST);
        if (ret)
                goto clear_it;
@@ -722,6 +748,7 @@ done:
        qlcnic_diag_free_res(netdev, max_sds_rings);
 
 clear_it:
+       qlcnic_clear_quiscent_mode(adapter);
        adapter->max_sds_rings = max_sds_rings;
        clear_bit(__QLCNIC_RESETTING, &adapter->state);
        return ret;
@@ -789,7 +816,8 @@ qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
 static void
 qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 * data)
 {
-       int index;
+       struct qlcnic_adapter *adapter = netdev_priv(dev);
+       int index, i;
 
        switch (stringset) {
        case ETH_SS_TEST:
@@ -802,16 +830,43 @@ qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 * data)
                               qlcnic_gstrings_stats[index].stat_string,
                               ETH_GSTRING_LEN);
                }
-               break;
+               if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
+                       return;
+               for (i = 0; i < QLCNIC_DEVICE_STATS_LEN; index++, i++) {
+                       memcpy(data + index * ETH_GSTRING_LEN,
+                              qlcnic_device_gstrings_stats[i],
+                              ETH_GSTRING_LEN);
+               }
        }
 }
 
+#define QLCNIC_FILL_ESWITCH_STATS(VAL1) \
+       (((VAL1) == QLCNIC_ESW_STATS_NOT_AVAIL) ? 0 : VAL1)
+
+static void
+qlcnic_fill_device_stats(int *index, u64 *data,
+               struct __qlcnic_esw_statistics *stats)
+{
+       int ind = *index;
+
+       data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->unicast_frames);
+       data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->multicast_frames);
+       data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->broadcast_frames);
+       data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->dropped_frames);
+       data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->errors);
+       data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->local_frames);
+       data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->numbytes);
+
+       *index = ind;
+}
+
 static void
 qlcnic_get_ethtool_stats(struct net_device *dev,
                             struct ethtool_stats *stats, u64 * data)
 {
        struct qlcnic_adapter *adapter = netdev_priv(dev);
-       int index;
+       struct qlcnic_esw_statistics port_stats;
+       int index, ret;
 
        for (index = 0; index < QLCNIC_STATS_LEN; index++) {
                char *p =
@@ -821,6 +876,24 @@ qlcnic_get_ethtool_stats(struct net_device *dev,
                    (qlcnic_gstrings_stats[index].sizeof_stat ==
                     sizeof(u64)) ? *(u64 *)p:(*(u32 *)p);
        }
+
+       if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
+               return;
+
+       memset(&port_stats, 0, sizeof(struct qlcnic_esw_statistics));
+       ret = qlcnic_get_port_stats(adapter, adapter->ahw.pci_func,
+                       QLCNIC_QUERY_RX_COUNTER, &port_stats.rx);
+       if (ret)
+               return;
+
+       qlcnic_fill_device_stats(&index, data, &port_stats.rx);
+
+       ret = qlcnic_get_port_stats(adapter, adapter->ahw.pci_func,
+                       QLCNIC_QUERY_TX_COUNTER, &port_stats.tx);
+       if (ret)
+               return;
+
+       qlcnic_fill_device_stats(&index, data, &port_stats.tx);
 }
 
 static int qlcnic_set_tx_csum(struct net_device *dev, u32 data)
@@ -859,7 +932,7 @@ static int qlcnic_set_rx_csum(struct net_device *dev, u32 data)
                return 0;
        }
 
-       if (adapter->flags & QLCNIC_LRO_ENABLED) {
+       if (dev->features & NETIF_F_LRO) {
                if (qlcnic_config_hw_lro(adapter, QLCNIC_LRO_DISABLED))
                        return -EIO;
 
@@ -1056,7 +1129,7 @@ static int qlcnic_set_flags(struct net_device *netdev, u32 data)
                return -EINVAL;
        }
 
-       if ((data & ETH_FLAG_LRO) && (adapter->flags & QLCNIC_LRO_ENABLED))
+       if ((data & ETH_FLAG_LRO) && (netdev->features & NETIF_F_LRO))
                return 0;
 
        if (data & ETH_FLAG_LRO) {