diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index b740489b6a5c5ac2d8bb9bc5c6aad57bf965284a..ae5f08ea27d1ad7442025419bd44222356669259 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -2362,6 +2362,14 @@ static void bnxt_free_stats(struct bnxt *bp) u32 size, i; struct pci_dev *pdev = bp->pdev; + if (bp->hw_rx_port_stats) { + dma_free_coherent(&pdev->dev, bp->hw_port_stats_size, + bp->hw_rx_port_stats, + bp->hw_rx_port_stats_map); + bp->hw_rx_port_stats = NULL; + bp->flags &= ~BNXT_FLAG_PORT_STATS; + } + if (!bp->bnapi) return; @@ -2398,6 +2406,24 @@ static int bnxt_alloc_stats(struct bnxt *bp) cpr->hw_stats_ctx_id = INVALID_STATS_CTX_ID; } + + if (BNXT_PF(bp)) { + bp->hw_port_stats_size = sizeof(struct rx_port_stats) + + sizeof(struct tx_port_stats) + 1024; + + bp->hw_rx_port_stats = + dma_alloc_coherent(&pdev->dev, bp->hw_port_stats_size, + &bp->hw_rx_port_stats_map, + GFP_KERNEL); + if (!bp->hw_rx_port_stats) + return -ENOMEM; + + bp->hw_tx_port_stats = (void *)(bp->hw_rx_port_stats + 1) + + 512; + bp->hw_tx_port_stats_map = bp->hw_rx_port_stats_map + + sizeof(struct rx_port_stats) + 512; + bp->flags |= BNXT_FLAG_PORT_STATS; + } return 0; } @@ -3834,6 +3860,23 @@ static int bnxt_hwrm_ver_get(struct bnxt *bp) return rc; } +static int bnxt_hwrm_port_qstats(struct bnxt *bp) +{ + int rc; + struct bnxt_pf_info *pf = &bp->pf; + struct hwrm_port_qstats_input req = {0}; + + if (!(bp->flags & BNXT_FLAG_PORT_STATS)) + return 0; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_PORT_QSTATS, -1, -1); + req.port_id = cpu_to_le16(pf->port_id); + req.tx_stat_host_addr = cpu_to_le64(bp->hw_tx_port_stats_map); + req.rx_stat_host_addr = cpu_to_le64(bp->hw_rx_port_stats_map); + rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); + return rc; +} + static void bnxt_hwrm_free_tunnel_ports(struct bnxt *bp) { if (bp->vxlan_port_cnt) { @@ -5232,6 +5275,10 @@ static void bnxt_timer(unsigned long data) if (atomic_read(&bp->intr_sem) != 0) goto bnxt_restart_timer; + if (bp->link_info.link_up && (bp->flags & BNXT_FLAG_PORT_STATS)) { + set_bit(BNXT_PERIODIC_STATS_SP_EVENT, &bp->sp_event); + schedule_work(&bp->sp_task); + } bnxt_restart_timer: mod_timer(&bp->timer, jiffies + bp->current_interval); } @@ -5283,6 +5330,9 @@ static void bnxt_sp_task(struct work_struct *work) rtnl_unlock(); } + if (test_and_clear_bit(BNXT_PERIODIC_STATS_SP_EVENT, &bp->sp_event)) + bnxt_hwrm_port_qstats(bp); + smp_mb__before_atomic(); clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state); } diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index c4424b60d859144f39704c7e827ecf4ac8cd6e2d..ec04c47172b7f33e338a000d07140892f6c72cb5 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -873,6 +873,7 @@ struct bnxt { #define BNXT_FLAG_MSIX_CAP 0x80 #define BNXT_FLAG_RFS 0x100 #define BNXT_FLAG_SHARED_RINGS 0x200 + #define BNXT_FLAG_PORT_STATS 0x400 #define BNXT_FLAG_ALL_CONFIG_FEATS (BNXT_FLAG_TPA | \ BNXT_FLAG_RFS | \ @@ -925,7 +926,7 @@ struct bnxt { struct bnxt_queue_info q_info[BNXT_MAX_QUEUE]; unsigned int current_interval; -#define BNXT_TIMER_INTERVAL (HZ / 2) +#define BNXT_TIMER_INTERVAL HZ struct timer_list timer; @@ -945,6 +946,13 @@ struct bnxt { void *hwrm_dbg_resp_addr; dma_addr_t hwrm_dbg_resp_dma_addr; #define HWRM_DBG_REG_BUF_SIZE 128 + + struct rx_port_stats *hw_rx_port_stats; + struct tx_port_stats *hw_tx_port_stats; + dma_addr_t hw_rx_port_stats_map; + dma_addr_t hw_tx_port_stats_map; + int hw_port_stats_size; + int hwrm_cmd_timeout; struct mutex hwrm_cmd_lock; /* serialize hwrm messages */ struct hwrm_ver_get_output ver_resp; @@ -980,6 +988,7 @@ struct bnxt { #define BNXT_RESET_TASK_SP_EVENT 6 #define BNXT_RST_RING_SP_EVENT 7 #define BNXT_HWRM_PF_UNLOAD_SP_EVENT 8 +#define BNXT_PERIODIC_STATS_SP_EVENT 9 struct bnxt_pf_info pf; #ifdef CONFIG_BNXT_SRIOV