diff options
Diffstat (limited to 'drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c')
-rw-r--r-- | drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 190 |
1 files changed, 123 insertions, 67 deletions
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c index b4aa56dc4f9f..64da654f1038 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c @@ -142,7 +142,7 @@ static const char * const bnxt_ring_rx_stats_str[] = { "rx_mcast_packets", "rx_bcast_packets", "rx_discards", - "rx_drops", + "rx_errors", "rx_ucast_bytes", "rx_mcast_bytes", "rx_bcast_bytes", @@ -152,8 +152,8 @@ static const char * const bnxt_ring_tx_stats_str[] = { "tx_ucast_packets", "tx_mcast_packets", "tx_bcast_packets", + "tx_errors", "tx_discards", - "tx_drops", "tx_ucast_bytes", "tx_mcast_bytes", "tx_bcast_bytes", @@ -293,9 +293,6 @@ static const char * const bnxt_cmn_sw_stats_str[] = { BNXT_TX_STATS_PRI_ENTRY(counter, 6), \ BNXT_TX_STATS_PRI_ENTRY(counter, 7) -#define BNXT_PCIE_STATS_ENTRY(counter) \ - { BNXT_PCIE_STATS_OFFSET(counter), __stringify(counter) } - enum { RX_TOTAL_DISCARDS, TX_TOTAL_DISCARDS, @@ -454,24 +451,6 @@ static const struct { BNXT_TX_STATS_PRI_ENTRIES(tx_packets), }; -static const struct { - long offset; - char string[ETH_GSTRING_LEN]; -} bnxt_pcie_stats_arr[] = { - BNXT_PCIE_STATS_ENTRY(pcie_pl_signal_integrity), - BNXT_PCIE_STATS_ENTRY(pcie_dl_signal_integrity), - BNXT_PCIE_STATS_ENTRY(pcie_tl_signal_integrity), - BNXT_PCIE_STATS_ENTRY(pcie_link_integrity), - BNXT_PCIE_STATS_ENTRY(pcie_tx_traffic_rate), - BNXT_PCIE_STATS_ENTRY(pcie_rx_traffic_rate), - BNXT_PCIE_STATS_ENTRY(pcie_tx_dllp_statistics), - BNXT_PCIE_STATS_ENTRY(pcie_rx_dllp_statistics), - BNXT_PCIE_STATS_ENTRY(pcie_equalization_time), - BNXT_PCIE_STATS_ENTRY(pcie_ltssm_histogram[0]), - BNXT_PCIE_STATS_ENTRY(pcie_ltssm_histogram[2]), - BNXT_PCIE_STATS_ENTRY(pcie_recovery_histogram), -}; - #define BNXT_NUM_SW_FUNC_STATS ARRAY_SIZE(bnxt_sw_func_stats) #define BNXT_NUM_PORT_STATS ARRAY_SIZE(bnxt_port_stats_arr) #define BNXT_NUM_STATS_PRI \ @@ -479,7 +458,6 @@ static const struct { ARRAY_SIZE(bnxt_rx_pkts_pri_arr) + \ ARRAY_SIZE(bnxt_tx_bytes_pri_arr) + \ ARRAY_SIZE(bnxt_tx_pkts_pri_arr)) -#define BNXT_NUM_PCIE_STATS ARRAY_SIZE(bnxt_pcie_stats_arr) static int bnxt_get_num_tpa_ring_stats(struct bnxt *bp) { @@ -526,9 +504,6 @@ static int bnxt_get_num_stats(struct bnxt *bp) num_stats += BNXT_NUM_STATS_PRI; } - if (bp->flags & BNXT_FLAG_PCIE_STATS) - num_stats += BNXT_NUM_PCIE_STATS; - return num_stats; } @@ -584,19 +559,19 @@ static void bnxt_get_ethtool_stats(struct net_device *dev, for (i = 0; i < bp->cp_nr_rings; i++) { struct bnxt_napi *bnapi = bp->bnapi[i]; struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring; - __le64 *hw_stats = (__le64 *)cpr->hw_stats; + u64 *sw_stats = cpr->stats.sw_stats; u64 *sw; int k; if (is_rx_ring(bp, i)) { for (k = 0; k < NUM_RING_RX_HW_STATS; j++, k++) - buf[j] = le64_to_cpu(hw_stats[k]); + buf[j] = sw_stats[k]; } if (is_tx_ring(bp, i)) { k = NUM_RING_RX_HW_STATS; for (; k < NUM_RING_RX_HW_STATS + NUM_RING_TX_HW_STATS; j++, k++) - buf[j] = le64_to_cpu(hw_stats[k]); + buf[j] = sw_stats[k]; } if (!tpa_stats || !is_rx_ring(bp, i)) goto skip_tpa_ring_stats; @@ -604,7 +579,7 @@ static void bnxt_get_ethtool_stats(struct net_device *dev, k = NUM_RING_RX_HW_STATS + NUM_RING_TX_HW_STATS; for (; k < NUM_RING_RX_HW_STATS + NUM_RING_TX_HW_STATS + tpa_stats; j++, k++) - buf[j] = le64_to_cpu(hw_stats[k]); + buf[j] = sw_stats[k]; skip_tpa_ring_stats: sw = (u64 *)&cpr->sw_stats.rx; @@ -618,9 +593,9 @@ skip_tpa_ring_stats: buf[j] = sw[k]; bnxt_sw_func_stats[RX_TOTAL_DISCARDS].counter += - le64_to_cpu(cpr->hw_stats->rx_discard_pkts); + BNXT_GET_RING_STATS64(sw_stats, rx_discard_pkts); bnxt_sw_func_stats[TX_TOTAL_DISCARDS].counter += - le64_to_cpu(cpr->hw_stats->tx_discard_pkts); + BNXT_GET_RING_STATS64(sw_stats, tx_discard_pkts); } for (i = 0; i < BNXT_NUM_SW_FUNC_STATS; i++, j++) @@ -628,60 +603,50 @@ skip_tpa_ring_stats: skip_ring_stats: if (bp->flags & BNXT_FLAG_PORT_STATS) { - __le64 *port_stats = (__le64 *)bp->hw_rx_port_stats; + u64 *port_stats = bp->port_stats.sw_stats; - for (i = 0; i < BNXT_NUM_PORT_STATS; i++, j++) { - buf[j] = le64_to_cpu(*(port_stats + - bnxt_port_stats_arr[i].offset)); - } + for (i = 0; i < BNXT_NUM_PORT_STATS; i++, j++) + buf[j] = *(port_stats + bnxt_port_stats_arr[i].offset); } if (bp->flags & BNXT_FLAG_PORT_STATS_EXT) { - __le64 *rx_port_stats_ext = (__le64 *)bp->hw_rx_port_stats_ext; - __le64 *tx_port_stats_ext = (__le64 *)bp->hw_tx_port_stats_ext; + u64 *rx_port_stats_ext = bp->rx_port_stats_ext.sw_stats; + u64 *tx_port_stats_ext = bp->tx_port_stats_ext.sw_stats; for (i = 0; i < bp->fw_rx_stats_ext_size; i++, j++) { - buf[j] = le64_to_cpu(*(rx_port_stats_ext + - bnxt_port_stats_ext_arr[i].offset)); + buf[j] = *(rx_port_stats_ext + + bnxt_port_stats_ext_arr[i].offset); } for (i = 0; i < bp->fw_tx_stats_ext_size; i++, j++) { - buf[j] = le64_to_cpu(*(tx_port_stats_ext + - bnxt_tx_port_stats_ext_arr[i].offset)); + buf[j] = *(tx_port_stats_ext + + bnxt_tx_port_stats_ext_arr[i].offset); } if (bp->pri2cos_valid) { for (i = 0; i < 8; i++, j++) { long n = bnxt_rx_bytes_pri_arr[i].base_off + bp->pri2cos_idx[i]; - buf[j] = le64_to_cpu(*(rx_port_stats_ext + n)); + buf[j] = *(rx_port_stats_ext + n); } for (i = 0; i < 8; i++, j++) { long n = bnxt_rx_pkts_pri_arr[i].base_off + bp->pri2cos_idx[i]; - buf[j] = le64_to_cpu(*(rx_port_stats_ext + n)); + buf[j] = *(rx_port_stats_ext + n); } for (i = 0; i < 8; i++, j++) { long n = bnxt_tx_bytes_pri_arr[i].base_off + bp->pri2cos_idx[i]; - buf[j] = le64_to_cpu(*(tx_port_stats_ext + n)); + buf[j] = *(tx_port_stats_ext + n); } for (i = 0; i < 8; i++, j++) { long n = bnxt_tx_pkts_pri_arr[i].base_off + bp->pri2cos_idx[i]; - buf[j] = le64_to_cpu(*(tx_port_stats_ext + n)); + buf[j] = *(tx_port_stats_ext + n); } } } - if (bp->flags & BNXT_FLAG_PCIE_STATS) { - __le64 *pcie_stats = (__le64 *)bp->hw_pcie_stats; - - for (i = 0; i < BNXT_NUM_PCIE_STATS; i++, j++) { - buf[j] = le64_to_cpu(*(pcie_stats + - bnxt_pcie_stats_arr[i].offset)); - } - } } static void bnxt_get_strings(struct net_device *dev, u32 stringset, u8 *buf) @@ -782,12 +747,6 @@ skip_tpa_stats: } } } - if (bp->flags & BNXT_FLAG_PCIE_STATS) { - for (i = 0; i < BNXT_NUM_PCIE_STATS; i++) { - strcpy(buf, bnxt_pcie_stats_arr[i].string); - buf += ETH_GSTRING_LEN; - } - } break; case ETH_SS_TEST: if (bp->num_tests) @@ -926,6 +885,13 @@ static int bnxt_set_channels(struct net_device *dev, return rc; } + if (bnxt_get_nr_rss_ctxs(bp, req_rx_rings) != + bnxt_get_nr_rss_ctxs(bp, bp->rx_nr_rings) && + (dev->priv_flags & IFF_RXFH_CONFIGURED)) { + netdev_warn(dev, "RSS table size change required, RSS table entries must be default to proceed\n"); + return -EINVAL; + } + if (netif_running(dev)) { if (BNXT_PF(bp)) { /* TODO CHIMP_FW: Send message to all VF's @@ -1273,8 +1239,12 @@ static int bnxt_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) return rc; } -static u32 bnxt_get_rxfh_indir_size(struct net_device *dev) +u32 bnxt_get_rxfh_indir_size(struct net_device *dev) { + struct bnxt *bp = netdev_priv(dev); + + if (bp->flags & BNXT_FLAG_CHIP_P5) + return ALIGN(bp->rx_nr_rings, BNXT_RSS_TABLE_ENTRIES_P5); return HW_HASH_INDEX_SIZE; } @@ -1288,7 +1258,7 @@ static int bnxt_get_rxfh(struct net_device *dev, u32 *indir, u8 *key, { struct bnxt *bp = netdev_priv(dev); struct bnxt_vnic_info *vnic; - int i = 0; + u32 i, tbl_size; if (hfunc) *hfunc = ETH_RSS_HASH_TOP; @@ -1297,9 +1267,10 @@ static int bnxt_get_rxfh(struct net_device *dev, u32 *indir, u8 *key, return 0; vnic = &bp->vnic_info[0]; - if (indir && vnic->rss_table) { - for (i = 0; i < HW_HASH_INDEX_SIZE; i++) - indir[i] = le16_to_cpu(vnic->rss_table[i]); + if (indir && bp->rss_indir_tbl) { + tbl_size = bnxt_get_rxfh_indir_size(dev); + for (i = 0; i < tbl_size; i++) + indir[i] = bp->rss_indir_tbl[i]; } if (key && vnic->rss_hash_key) @@ -1308,6 +1279,35 @@ static int bnxt_get_rxfh(struct net_device *dev, u32 *indir, u8 *key, return 0; } +static int bnxt_set_rxfh(struct net_device *dev, const u32 *indir, + const u8 *key, const u8 hfunc) +{ + struct bnxt *bp = netdev_priv(dev); + int rc = 0; + + if (hfunc && hfunc != ETH_RSS_HASH_TOP) + return -EOPNOTSUPP; + + if (key) + return -EOPNOTSUPP; + + if (indir) { + u32 i, pad, tbl_size = bnxt_get_rxfh_indir_size(dev); + + for (i = 0; i < tbl_size; i++) + bp->rss_indir_tbl[i] = indir[i]; + pad = bp->rss_indir_tbl_entries - tbl_size; + if (pad) + memset(&bp->rss_indir_tbl[i], 0, pad * sizeof(u16)); + } + + if (netif_running(bp->dev)) { + bnxt_close_nic(bp, false, false); + rc = bnxt_open_nic(bp, false, false); + } + return rc; +} + static void bnxt_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { @@ -1324,6 +1324,59 @@ static void bnxt_get_drvinfo(struct net_device *dev, info->regdump_len = 0; } +static int bnxt_get_regs_len(struct net_device *dev) +{ + struct bnxt *bp = netdev_priv(dev); + int reg_len; + + reg_len = BNXT_PXP_REG_LEN; + + if (bp->fw_cap & BNXT_FW_CAP_PCIE_STATS_SUPPORTED) + reg_len += sizeof(struct pcie_ctx_hw_stats); + + return reg_len; +} + +static void bnxt_get_regs(struct net_device *dev, struct ethtool_regs *regs, + void *_p) +{ + struct pcie_ctx_hw_stats *hw_pcie_stats; + struct hwrm_pcie_qstats_input req = {0}; + struct bnxt *bp = netdev_priv(dev); + dma_addr_t hw_pcie_stats_addr; + int rc; + + regs->version = 0; + bnxt_dbg_hwrm_rd_reg(bp, 0, BNXT_PXP_REG_LEN / 4, _p); + + if (!(bp->fw_cap & BNXT_FW_CAP_PCIE_STATS_SUPPORTED)) + return; + + hw_pcie_stats = dma_alloc_coherent(&bp->pdev->dev, + sizeof(*hw_pcie_stats), + &hw_pcie_stats_addr, GFP_KERNEL); + if (!hw_pcie_stats) + return; + + regs->version = 1; + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_PCIE_QSTATS, -1, -1); + req.pcie_stat_size = cpu_to_le16(sizeof(*hw_pcie_stats)); + req.pcie_stat_host_addr = cpu_to_le64(hw_pcie_stats_addr); + mutex_lock(&bp->hwrm_cmd_lock); + rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); + if (!rc) { + __le64 *src = (__le64 *)hw_pcie_stats; + u64 *dst = (u64 *)(_p + BNXT_PXP_REG_LEN); + int i; + + for (i = 0; i < sizeof(*hw_pcie_stats) / sizeof(__le64); i++) + dst[i] = le64_to_cpu(src[i]); + } + mutex_unlock(&bp->hwrm_cmd_lock); + dma_free_coherent(&bp->pdev->dev, sizeof(*hw_pcie_stats), hw_pcie_stats, + hw_pcie_stats_addr); +} + static void bnxt_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct bnxt *bp = netdev_priv(dev); @@ -3599,6 +3652,8 @@ const struct ethtool_ops bnxt_ethtool_ops = { .get_pauseparam = bnxt_get_pauseparam, .set_pauseparam = bnxt_set_pauseparam, .get_drvinfo = bnxt_get_drvinfo, + .get_regs_len = bnxt_get_regs_len, + .get_regs = bnxt_get_regs, .get_wol = bnxt_get_wol, .set_wol = bnxt_set_wol, .get_coalesce = bnxt_get_coalesce, @@ -3617,6 +3672,7 @@ const struct ethtool_ops bnxt_ethtool_ops = { .get_rxfh_indir_size = bnxt_get_rxfh_indir_size, .get_rxfh_key_size = bnxt_get_rxfh_key_size, .get_rxfh = bnxt_get_rxfh, + .set_rxfh = bnxt_set_rxfh, .flash_device = bnxt_flash_device, .get_eeprom_len = bnxt_get_eeprom_len, .get_eeprom = bnxt_get_eeprom, |