diff options
Diffstat (limited to 'drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c')
-rw-r--r-- | drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c | 182 |
1 files changed, 157 insertions, 25 deletions
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c index 60fcf82dd8cb..d59f5a9c7273 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c @@ -17,6 +17,7 @@ #include "otx2_common.h" #define DRV_NAME "octeontx2-nicpf" +#define DRV_VF_NAME "octeontx2-nicvf" struct otx2_stat { char name[ETH_GSTRING_LEN]; @@ -63,16 +64,6 @@ static const unsigned int otx2_n_dev_stats = ARRAY_SIZE(otx2_dev_stats); static const unsigned int otx2_n_drv_stats = ARRAY_SIZE(otx2_drv_stats); static const unsigned int otx2_n_queue_stats = ARRAY_SIZE(otx2_queue_stats); -static void otx2_dev_open(struct net_device *netdev) -{ - otx2_open(netdev); -} - -static void otx2_dev_stop(struct net_device *netdev) -{ - otx2_stop(netdev); -} - static void otx2_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *info) { @@ -232,7 +223,7 @@ static int otx2_set_channels(struct net_device *dev, return -EINVAL; if (if_up) - otx2_dev_stop(dev); + dev->netdev_ops->ndo_stop(dev); err = otx2_set_real_num_queues(dev, channel->tx_count, channel->rx_count); @@ -245,7 +236,7 @@ static int otx2_set_channels(struct net_device *dev, fail: if (if_up) - otx2_dev_open(dev); + dev->netdev_ops->ndo_open(dev); netdev_info(dev, "Setting num Tx rings to %d, Rx rings to %d success\n", pfvf->hw.tx_queues, pfvf->hw.rx_queues); @@ -253,6 +244,51 @@ fail: return err; } +static void otx2_get_pauseparam(struct net_device *netdev, + struct ethtool_pauseparam *pause) +{ + struct otx2_nic *pfvf = netdev_priv(netdev); + struct cgx_pause_frm_cfg *req, *rsp; + + if (is_otx2_lbkvf(pfvf->pdev)) + return; + + req = otx2_mbox_alloc_msg_cgx_cfg_pause_frm(&pfvf->mbox); + if (!req) + return; + + if (!otx2_sync_mbox_msg(&pfvf->mbox)) { + rsp = (struct cgx_pause_frm_cfg *) + otx2_mbox_get_rsp(&pfvf->mbox.mbox, 0, &req->hdr); + pause->rx_pause = rsp->rx_pause; + pause->tx_pause = rsp->tx_pause; + } +} + +static int otx2_set_pauseparam(struct net_device *netdev, + struct ethtool_pauseparam *pause) +{ + struct otx2_nic *pfvf = netdev_priv(netdev); + + if (pause->autoneg) + return -EOPNOTSUPP; + + if (is_otx2_lbkvf(pfvf->pdev)) + return -EOPNOTSUPP; + + if (pause->rx_pause) + pfvf->flags |= OTX2_FLAG_RX_PAUSE_ENABLED; + else + pfvf->flags &= ~OTX2_FLAG_RX_PAUSE_ENABLED; + + if (pause->tx_pause) + pfvf->flags |= OTX2_FLAG_TX_PAUSE_ENABLED; + else + pfvf->flags &= ~OTX2_FLAG_TX_PAUSE_ENABLED; + + return otx2_config_pause_frm(pfvf); +} + static void otx2_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) { @@ -297,14 +333,15 @@ static int otx2_set_ringparam(struct net_device *netdev, return 0; if (if_up) - otx2_dev_stop(netdev); + netdev->netdev_ops->ndo_stop(netdev); /* Assigned to the nearest possible exponent. */ qs->sqe_cnt = tx_count; qs->rqe_cnt = rx_count; if (if_up) - otx2_dev_open(netdev); + netdev->netdev_ops->ndo_open(netdev); + return 0; } @@ -329,17 +366,6 @@ static int otx2_set_coalesce(struct net_device *netdev, struct otx2_hw *hw = &pfvf->hw; int qidx; - if (ec->use_adaptive_rx_coalesce || ec->use_adaptive_tx_coalesce || - ec->rx_coalesce_usecs_irq || ec->rx_max_coalesced_frames_irq || - ec->tx_coalesce_usecs_irq || ec->tx_max_coalesced_frames_irq || - ec->stats_block_coalesce_usecs || ec->pkt_rate_low || - ec->rx_coalesce_usecs_low || ec->rx_max_coalesced_frames_low || - ec->tx_coalesce_usecs_low || ec->tx_max_coalesced_frames_low || - ec->pkt_rate_high || ec->rx_coalesce_usecs_high || - ec->rx_max_coalesced_frames_high || ec->tx_coalesce_usecs_high || - ec->tx_max_coalesced_frames_high || ec->rate_sample_interval) - return -EOPNOTSUPP; - if (!ec->rx_max_coalesced_frames || !ec->tx_max_coalesced_frames) return 0; @@ -631,10 +657,15 @@ static u32 otx2_get_link(struct net_device *netdev) { struct otx2_nic *pfvf = netdev_priv(netdev); + /* LBK link is internal and always UP */ + if (is_otx2_lbkvf(pfvf->pdev)) + return 1; return pfvf->linfo.link_up; } static const struct ethtool_ops otx2_ethtool_ops = { + .supported_coalesce_params = ETHTOOL_COALESCE_USECS | + ETHTOOL_COALESCE_MAX_FRAMES, .get_link = otx2_get_link, .get_drvinfo = otx2_get_drvinfo, .get_strings = otx2_get_strings, @@ -654,9 +685,110 @@ static const struct ethtool_ops otx2_ethtool_ops = { .set_rxfh = otx2_set_rxfh, .get_msglevel = otx2_get_msglevel, .set_msglevel = otx2_set_msglevel, + .get_pauseparam = otx2_get_pauseparam, + .set_pauseparam = otx2_set_pauseparam, }; void otx2_set_ethtool_ops(struct net_device *netdev) { netdev->ethtool_ops = &otx2_ethtool_ops; } + +/* VF's ethtool APIs */ +static void otx2vf_get_drvinfo(struct net_device *netdev, + struct ethtool_drvinfo *info) +{ + struct otx2_nic *vf = netdev_priv(netdev); + + strlcpy(info->driver, DRV_VF_NAME, sizeof(info->driver)); + strlcpy(info->bus_info, pci_name(vf->pdev), sizeof(info->bus_info)); +} + +static void otx2vf_get_strings(struct net_device *netdev, u32 sset, u8 *data) +{ + struct otx2_nic *vf = netdev_priv(netdev); + int stats; + + if (sset != ETH_SS_STATS) + return; + + for (stats = 0; stats < otx2_n_dev_stats; stats++) { + memcpy(data, otx2_dev_stats[stats].name, ETH_GSTRING_LEN); + data += ETH_GSTRING_LEN; + } + + for (stats = 0; stats < otx2_n_drv_stats; stats++) { + memcpy(data, otx2_drv_stats[stats].name, ETH_GSTRING_LEN); + data += ETH_GSTRING_LEN; + } + + otx2_get_qset_strings(vf, &data, 0); + + strcpy(data, "reset_count"); + data += ETH_GSTRING_LEN; +} + +static void otx2vf_get_ethtool_stats(struct net_device *netdev, + struct ethtool_stats *stats, u64 *data) +{ + struct otx2_nic *vf = netdev_priv(netdev); + int stat; + + otx2_get_dev_stats(vf); + for (stat = 0; stat < otx2_n_dev_stats; stat++) + *(data++) = ((u64 *)&vf->hw.dev_stats) + [otx2_dev_stats[stat].index]; + + for (stat = 0; stat < otx2_n_drv_stats; stat++) + *(data++) = atomic_read(&((atomic_t *)&vf->hw.drv_stats) + [otx2_drv_stats[stat].index]); + + otx2_get_qset_stats(vf, stats, &data); + *(data++) = vf->reset_count; +} + +static int otx2vf_get_sset_count(struct net_device *netdev, int sset) +{ + struct otx2_nic *vf = netdev_priv(netdev); + int qstats_count; + + if (sset != ETH_SS_STATS) + return -EINVAL; + + qstats_count = otx2_n_queue_stats * + (vf->hw.rx_queues + vf->hw.tx_queues); + + return otx2_n_dev_stats + otx2_n_drv_stats + qstats_count + 1; +} + +static const struct ethtool_ops otx2vf_ethtool_ops = { + .supported_coalesce_params = ETHTOOL_COALESCE_USECS | + ETHTOOL_COALESCE_MAX_FRAMES, + .get_link = otx2_get_link, + .get_drvinfo = otx2vf_get_drvinfo, + .get_strings = otx2vf_get_strings, + .get_ethtool_stats = otx2vf_get_ethtool_stats, + .get_sset_count = otx2vf_get_sset_count, + .set_channels = otx2_set_channels, + .get_channels = otx2_get_channels, + .get_rxnfc = otx2_get_rxnfc, + .set_rxnfc = otx2_set_rxnfc, + .get_rxfh_key_size = otx2_get_rxfh_key_size, + .get_rxfh_indir_size = otx2_get_rxfh_indir_size, + .get_rxfh = otx2_get_rxfh, + .set_rxfh = otx2_set_rxfh, + .get_ringparam = otx2_get_ringparam, + .set_ringparam = otx2_set_ringparam, + .get_coalesce = otx2_get_coalesce, + .set_coalesce = otx2_set_coalesce, + .get_msglevel = otx2_get_msglevel, + .set_msglevel = otx2_set_msglevel, + .get_pauseparam = otx2_get_pauseparam, + .set_pauseparam = otx2_set_pauseparam, +}; + +void otx2vf_set_ethtool_ops(struct net_device *netdev) +{ + netdev->ethtool_ops = &otx2vf_ethtool_ops; +} +EXPORT_SYMBOL(otx2vf_set_ethtool_ops); |