Message ID | 20220418110205.282193-1-sumang@marvell.com (mailing list archive) |
---|---|
State | Changes Requested |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | [V2] octeontx2-pf: Add support for adaptive interrupt coalescing | expand |
Context | Check | Description |
---|---|---|
netdev/tree_selection | success | Not a local patch |
On Mon, 2022-04-18 at 16:32 +0530, Suman Ghosh wrote: > Added support for adaptive IRQ coalescing. It uses net_dim > algorithm to find the suitable delay/IRQ count based on the > current packet rate. > > Signed-off-by: Suman Ghosh <sumang@marvell.com> > Reviewed-by: Sunil Kovvuri Goutham <sgoutham@marvell.com> > --- > Changes since V1 > - No change, resubmitting because V1 did not get picked up in patchworks > for some reason. > > .../net/ethernet/marvell/octeontx2/Kconfig | 1 + > .../marvell/octeontx2/nic/otx2_common.c | 5 --- > .../marvell/octeontx2/nic/otx2_common.h | 10 +++++ > .../marvell/octeontx2/nic/otx2_ethtool.c | 43 ++++++++++++++++--- > .../ethernet/marvell/octeontx2/nic/otx2_pf.c | 22 ++++++++++ > .../marvell/octeontx2/nic/otx2_txrx.c | 28 ++++++++++++ > .../marvell/octeontx2/nic/otx2_txrx.h | 1 + > 7 files changed, 99 insertions(+), 11 deletions(-) > > diff --git a/drivers/net/ethernet/marvell/octeontx2/Kconfig b/drivers/net/ethernet/marvell/octeontx2/Kconfig > index 8560f7e463d3..a544733152d8 100644 > --- a/drivers/net/ethernet/marvell/octeontx2/Kconfig > +++ b/drivers/net/ethernet/marvell/octeontx2/Kconfig > @@ -30,6 +30,7 @@ config OCTEONTX2_PF > tristate "Marvell OcteonTX2 NIC Physical Function driver" > select OCTEONTX2_MBOX > select NET_DEVLINK > + select DIMLIB > depends on PCI > help > This driver supports Marvell's OcteonTX2 Resource Virtualization > diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c > index 033fd79d35b0..c28850d815c2 100644 > --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c > +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c > @@ -103,11 +103,6 @@ void otx2_get_dev_stats(struct otx2_nic *pfvf) > { > struct otx2_dev_stats *dev_stats = &pfvf->hw.dev_stats; > > -#define OTX2_GET_RX_STATS(reg) \ > - otx2_read64(pfvf, NIX_LF_RX_STATX(reg)) > -#define OTX2_GET_TX_STATS(reg) \ > - otx2_read64(pfvf, NIX_LF_TX_STATX(reg)) > - > dev_stats->rx_bytes = OTX2_GET_RX_STATS(RX_OCTS); > dev_stats->rx_drops = OTX2_GET_RX_STATS(RX_DROP); > dev_stats->rx_bcast_frames = OTX2_GET_RX_STATS(RX_BCAST); > diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h > index d9f4b085b2a4..6abf5c28921f 100644 > --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h > +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h > @@ -16,6 +16,7 @@ > #include <net/pkt_cls.h> > #include <net/devlink.h> > #include <linux/time64.h> > +#include <linux/dim.h> > > #include <mbox.h> > #include <npc.h> > @@ -54,6 +55,11 @@ enum arua_mapped_qtypes { > /* Send skid of 2000 packets required for CQ size of 4K CQEs. */ > #define SEND_CQ_SKID 2000 > > +#define OTX2_GET_RX_STATS(reg) \ > + otx2_read64(pfvf, NIX_LF_RX_STATX(reg)) > +#define OTX2_GET_TX_STATS(reg) \ > + otx2_read64(pfvf, NIX_LF_TX_STATX(reg)) > + > struct otx2_lmt_info { > u64 lmt_addr; > u16 lmt_id; > @@ -363,6 +369,7 @@ struct otx2_nic { > #define OTX2_FLAG_TC_MATCHALL_INGRESS_ENABLED BIT_ULL(13) > #define OTX2_FLAG_DMACFLTR_SUPPORT BIT_ULL(14) > #define OTX2_FLAG_PTP_ONESTEP_SYNC BIT_ULL(15) > +#define OTX2_FLAG_ADPTV_INT_COAL_ENABLED BIT_ULL(16) > u64 flags; > u64 *cq_op_addr; > > @@ -442,6 +449,9 @@ struct otx2_nic { > #endif > /* qos */ > struct otx2_qos qos; > + > + /* napi event count. It is needed for adaptive irq coalescing */ > + u32 napi_events; > }; > > static inline bool is_otx2_lbkvf(struct pci_dev *pdev) > diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c > index 72d0b02da3cc..8ed282991f05 100644 > --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c > +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c > @@ -477,6 +477,14 @@ static int otx2_get_coalesce(struct net_device *netdev, > cmd->rx_max_coalesced_frames = hw->cq_ecount_wait; > cmd->tx_coalesce_usecs = hw->cq_time_wait; > cmd->tx_max_coalesced_frames = hw->cq_ecount_wait; > + if ((pfvf->flags & OTX2_FLAG_ADPTV_INT_COAL_ENABLED) == > + OTX2_FLAG_ADPTV_INT_COAL_ENABLED) { > + cmd->use_adaptive_rx_coalesce = 1; > + cmd->use_adaptive_tx_coalesce = 1; > + } else { > + cmd->use_adaptive_rx_coalesce = 0; > + cmd->use_adaptive_tx_coalesce = 0; > + } > > return 0; > } > @@ -486,10 +494,10 @@ static int otx2_set_coalesce(struct net_device *netdev, > { > struct otx2_nic *pfvf = netdev_priv(netdev); > struct otx2_hw *hw = &pfvf->hw; > + u8 priv_coalesce_status; > int qidx; > > - if (ec->use_adaptive_rx_coalesce || ec->use_adaptive_tx_coalesce || > - ec->rx_coalesce_usecs_irq || ec->rx_max_coalesced_frames_irq || > + if (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 || > @@ -502,6 +510,18 @@ static int otx2_set_coalesce(struct net_device *netdev, > if (!ec->rx_max_coalesced_frames || !ec->tx_max_coalesced_frames) > return 0; > > + /* Check and update coalesce status */ > + if ((pfvf->flags & OTX2_FLAG_ADPTV_INT_COAL_ENABLED) == > + OTX2_FLAG_ADPTV_INT_COAL_ENABLED) { > + priv_coalesce_status = 1; > + if (!ec->use_adaptive_rx_coalesce || !ec->use_adaptive_tx_coalesce) > + pfvf->flags &= ~OTX2_FLAG_ADPTV_INT_COAL_ENABLED; > + } else { > + priv_coalesce_status = 0; > + if (ec->use_adaptive_rx_coalesce || ec->use_adaptive_tx_coalesce) > + pfvf->flags |= OTX2_FLAG_ADPTV_INT_COAL_ENABLED; > + } > + > /* 'cq_time_wait' is 8bit and is in multiple of 100ns, > * so clamp the user given value to the range of 1 to 25usec. > */ > @@ -521,13 +541,13 @@ static int otx2_set_coalesce(struct net_device *netdev, > hw->cq_time_wait = min_t(u8, ec->rx_coalesce_usecs, > ec->tx_coalesce_usecs); > > - /* Max ecount_wait supported is 16bit, > - * so clamp the user given value to the range of 1 to 64k. > + /* Max packet budget per napi is 64, > + * so clamp the user given value to the range of 1 to 64. > */ > ec->rx_max_coalesced_frames = clamp_t(u32, ec->rx_max_coalesced_frames, > - 1, U16_MAX); > + 1, NAPI_POLL_WEIGHT); > ec->tx_max_coalesced_frames = clamp_t(u32, ec->tx_max_coalesced_frames, > - 1, U16_MAX); > + 1, NAPI_POLL_WEIGHT); > > /* Rx and Tx are mapped to same CQ, check which one > * is changed, if both then choose the min. > @@ -540,6 +560,17 @@ static int otx2_set_coalesce(struct net_device *netdev, > hw->cq_ecount_wait = min_t(u16, ec->rx_max_coalesced_frames, > ec->tx_max_coalesced_frames); > > + /* Reset 'cq_time_wait' and 'cq_ecount_wait' to > + * default values if coalesce status changed from > + * 'on' to 'off'. > + */ > + if (priv_coalesce_status && > + ((pfvf->flags & OTX2_FLAG_ADPTV_INT_COAL_ENABLED) != > + OTX2_FLAG_ADPTV_INT_COAL_ENABLED)) { > + hw->cq_time_wait = CQ_TIMER_THRESH_DEFAULT; > + hw->cq_ecount_wait = CQ_CQE_THRESH_DEFAULT; > + } > + > if (netif_running(netdev)) { > for (qidx = 0; qidx < pfvf->hw.cint_cnt; qidx++) > otx2_config_irq_coalescing(pfvf, qidx); > diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c > index f18c9a9a50d0..94aaafbeb365 100644 > --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c > +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c > @@ -1279,6 +1279,7 @@ static irqreturn_t otx2_cq_intr_handler(int irq, void *cq_irq) > otx2_write64(pf, NIX_LF_CINTX_ENA_W1C(qidx), BIT_ULL(0)); > > /* Schedule NAPI */ > + pf->napi_events++; > napi_schedule_irqoff(&cq_poll->napi); > > return IRQ_HANDLED; > @@ -1292,6 +1293,7 @@ static void otx2_disable_napi(struct otx2_nic *pf) > > for (qidx = 0; qidx < pf->hw.cint_cnt; qidx++) { > cq_poll = &qset->napi[qidx]; > + cancel_work_sync(&cq_poll->dim.work); > napi_disable(&cq_poll->napi); > netif_napi_del(&cq_poll->napi); > } > @@ -1538,6 +1540,24 @@ static void otx2_free_hw_resources(struct otx2_nic *pf) > mutex_unlock(&mbox->lock); > } > > +static void otx2_dim_work(struct work_struct *w) > +{ > + struct dim_cq_moder cur_moder; > + struct otx2_cq_poll *cq_poll; > + struct otx2_nic *pfvf; > + struct dim *dim; > + > + dim = container_of(w, struct dim, work); > + cur_moder = net_dim_get_rx_moderation(dim->mode, dim->profile_ix); > + cq_poll = container_of(dim, struct otx2_cq_poll, dim); > + pfvf = (struct otx2_nic *)cq_poll->dev; > + pfvf->hw.cq_time_wait = (cur_moder.usec > CQ_TIMER_THRESH_MAX) ? > + CQ_TIMER_THRESH_MAX : cur_moder.usec; > + pfvf->hw.cq_ecount_wait = (cur_moder.pkts > NAPI_POLL_WEIGHT) ? > + NAPI_POLL_WEIGHT : cur_moder.pkts; > + dim->state = DIM_START_MEASURE; > +} > + > int otx2_open(struct net_device *netdev) > { > struct otx2_nic *pf = netdev_priv(netdev); > @@ -1611,6 +1631,8 @@ int otx2_open(struct net_device *netdev) > CINT_INVALID_CQ; > > cq_poll->dev = (void *)pf; > + cq_poll->dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_CQE; > + INIT_WORK(&cq_poll->dim.work, otx2_dim_work); > netif_napi_add(netdev, &cq_poll->napi, > otx2_napi_handler, NAPI_POLL_WEIGHT); > napi_enable(&cq_poll->napi); > diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c > index 459b94b99ddb..927dd12b4f4e 100644 > --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c > +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c > @@ -512,6 +512,22 @@ static int otx2_tx_napi_handler(struct otx2_nic *pfvf, > return 0; > } > > +static void otx2_adjust_adaptive_coalese(struct otx2_nic *pfvf, struct otx2_cq_poll *cq_poll) > +{ > + struct dim_sample dim_sample; > + u64 rx_frames, rx_bytes; > + > + rx_frames = OTX2_GET_RX_STATS(RX_BCAST) + OTX2_GET_RX_STATS(RX_MCAST) + > + OTX2_GET_RX_STATS(RX_UCAST); > + rx_bytes = OTX2_GET_RX_STATS(RX_OCTS); > + dim_update_sample(pfvf->napi_events, > + rx_frames, > + rx_bytes, > + &dim_sample); > + > + net_dim(&cq_poll->dim, dim_sample); > +} > + > int otx2_napi_handler(struct napi_struct *napi, int budget) > { > struct otx2_cq_queue *rx_cq = NULL; > @@ -549,6 +565,18 @@ int otx2_napi_handler(struct napi_struct *napi, int budget) > if (pfvf->flags & OTX2_FLAG_INTF_DOWN) > return workdone; > > + /* Check for adaptive interrupt coalesce */ > + if (workdone != 0 && > + ((pfvf->flags & OTX2_FLAG_ADPTV_INT_COAL_ENABLED) == > + OTX2_FLAG_ADPTV_INT_COAL_ENABLED)) { > + /* Adjust irq coalese using net_dim */ > + otx2_adjust_adaptive_coalese(pfvf, cq_poll); > + > + /* Update irq coalescing */ > + for (i = 0; i < pfvf->hw.cint_cnt; i++) > + otx2_config_irq_coalescing(pfvf, i); > + } > + Why are you updating the IRQ coalescing parameters for every sample? You probably should to that in void otx2_dim_work(), when dim tells it's the right time to update them. Thanks, Paolo
Hi Paolo, >-----Original Message----- >From: Paolo Abeni <pabeni@redhat.com> >Sent: Thursday, April 21, 2022 6:57 PM >To: Suman Ghosh <sumang@marvell.com>; davem@davemloft.net; kuba@kernel.org; >Sunil Kovvuri Goutham <sgoutham@marvell.com>; netdev@vger.kernel.org >Subject: Re: [PATCH V2] octeontx2-pf: Add support for adaptive >interrupt coalescing > >On Mon, 2022-04-18 at 16:32 +0530, Suman Ghosh wrote: >> Added support for adaptive IRQ coalescing. It uses net_dim algorithm >> to find the suitable delay/IRQ count based on the current packet rate. >> >> Signed-off-by: Suman Ghosh <sumang@marvell.com> >> Reviewed-by: Sunil Kovvuri Goutham <sgoutham@marvell.com> >> --- >> Changes since V1 >> - No change, resubmitting because V1 did not get picked up in patchworks >> for some reason. >> >> .../net/ethernet/marvell/octeontx2/Kconfig | 1 + >> .../marvell/octeontx2/nic/otx2_common.c | 5 --- >> .../marvell/octeontx2/nic/otx2_common.h | 10 +++++ >> .../marvell/octeontx2/nic/otx2_ethtool.c | 43 ++++++++++++++++--- >> .../ethernet/marvell/octeontx2/nic/otx2_pf.c | 22 ++++++++++ >> .../marvell/octeontx2/nic/otx2_txrx.c | 28 ++++++++++++ >> .../marvell/octeontx2/nic/otx2_txrx.h | 1 + >> 7 files changed, 99 insertions(+), 11 deletions(-) >> >> diff --git a/drivers/net/ethernet/marvell/octeontx2/Kconfig >> b/drivers/net/ethernet/marvell/octeontx2/Kconfig >> index 8560f7e463d3..a544733152d8 100644 >> --- a/drivers/net/ethernet/marvell/octeontx2/Kconfig >> +++ b/drivers/net/ethernet/marvell/octeontx2/Kconfig >> @@ -30,6 +30,7 @@ config OCTEONTX2_PF >> tristate "Marvell OcteonTX2 NIC Physical Function driver" >> select OCTEONTX2_MBOX >> select NET_DEVLINK >> + select DIMLIB >> depends on PCI >> help >> This driver supports Marvell's OcteonTX2 Resource Virtualization >> diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c >> b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c >> index 033fd79d35b0..c28850d815c2 100644 >> --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c >> +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c >> @@ -103,11 +103,6 @@ void otx2_get_dev_stats(struct otx2_nic *pfvf) { >> struct otx2_dev_stats *dev_stats = &pfvf->hw.dev_stats; >> >> -#define OTX2_GET_RX_STATS(reg) \ >> - otx2_read64(pfvf, NIX_LF_RX_STATX(reg)) >> -#define OTX2_GET_TX_STATS(reg) \ >> - otx2_read64(pfvf, NIX_LF_TX_STATX(reg)) >> - >> dev_stats->rx_bytes = OTX2_GET_RX_STATS(RX_OCTS); >> dev_stats->rx_drops = OTX2_GET_RX_STATS(RX_DROP); >> dev_stats->rx_bcast_frames = OTX2_GET_RX_STATS(RX_BCAST); diff --git >> a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h >> b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h >> index d9f4b085b2a4..6abf5c28921f 100644 >> --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h >> +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h >> @@ -16,6 +16,7 @@ >> #include <net/pkt_cls.h> >> #include <net/devlink.h> >> #include <linux/time64.h> >> +#include <linux/dim.h> >> >> #include <mbox.h> >> #include <npc.h> >> @@ -54,6 +55,11 @@ enum arua_mapped_qtypes { >> /* Send skid of 2000 packets required for CQ size of 4K CQEs. */ >> #define SEND_CQ_SKID 2000 >> >> +#define OTX2_GET_RX_STATS(reg) \ >> + otx2_read64(pfvf, NIX_LF_RX_STATX(reg)) #define >> +OTX2_GET_TX_STATS(reg) \ >> + otx2_read64(pfvf, NIX_LF_TX_STATX(reg)) >> + >> struct otx2_lmt_info { >> u64 lmt_addr; >> u16 lmt_id; >> @@ -363,6 +369,7 @@ struct otx2_nic { >> #define OTX2_FLAG_TC_MATCHALL_INGRESS_ENABLED BIT_ULL(13) >> #define OTX2_FLAG_DMACFLTR_SUPPORT BIT_ULL(14) >> #define OTX2_FLAG_PTP_ONESTEP_SYNC BIT_ULL(15) >> +#define OTX2_FLAG_ADPTV_INT_COAL_ENABLED BIT_ULL(16) >> u64 flags; >> u64 *cq_op_addr; >> >> @@ -442,6 +449,9 @@ struct otx2_nic { >> #endif >> /* qos */ >> struct otx2_qos qos; >> + >> + /* napi event count. It is needed for adaptive irq coalescing */ >> + u32 napi_events; >> }; >> >> static inline bool is_otx2_lbkvf(struct pci_dev *pdev) diff --git >> a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c >> b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c >> index 72d0b02da3cc..8ed282991f05 100644 >> --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c >> +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c >> @@ -477,6 +477,14 @@ static int otx2_get_coalesce(struct net_device >*netdev, >> cmd->rx_max_coalesced_frames = hw->cq_ecount_wait; >> cmd->tx_coalesce_usecs = hw->cq_time_wait; >> cmd->tx_max_coalesced_frames = hw->cq_ecount_wait; >> + if ((pfvf->flags & OTX2_FLAG_ADPTV_INT_COAL_ENABLED) == >> + OTX2_FLAG_ADPTV_INT_COAL_ENABLED) { >> + cmd->use_adaptive_rx_coalesce = 1; >> + cmd->use_adaptive_tx_coalesce = 1; >> + } else { >> + cmd->use_adaptive_rx_coalesce = 0; >> + cmd->use_adaptive_tx_coalesce = 0; >> + } >> >> return 0; >> } >> @@ -486,10 +494,10 @@ static int otx2_set_coalesce(struct net_device >> *netdev, { >> struct otx2_nic *pfvf = netdev_priv(netdev); >> struct otx2_hw *hw = &pfvf->hw; >> + u8 priv_coalesce_status; >> int qidx; >> >> - if (ec->use_adaptive_rx_coalesce || ec->use_adaptive_tx_coalesce || >> - ec->rx_coalesce_usecs_irq || ec->rx_max_coalesced_frames_irq || >> + if (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 || >> @@ -502,6 +510,18 @@ static int otx2_set_coalesce(struct net_device >*netdev, >> if (!ec->rx_max_coalesced_frames || !ec->tx_max_coalesced_frames) >> return 0; >> >> + /* Check and update coalesce status */ >> + if ((pfvf->flags & OTX2_FLAG_ADPTV_INT_COAL_ENABLED) == >> + OTX2_FLAG_ADPTV_INT_COAL_ENABLED) { >> + priv_coalesce_status = 1; >> + if (!ec->use_adaptive_rx_coalesce || !ec- >>use_adaptive_tx_coalesce) >> + pfvf->flags &= ~OTX2_FLAG_ADPTV_INT_COAL_ENABLED; >> + } else { >> + priv_coalesce_status = 0; >> + if (ec->use_adaptive_rx_coalesce || ec->use_adaptive_tx_coalesce) >> + pfvf->flags |= OTX2_FLAG_ADPTV_INT_COAL_ENABLED; >> + } >> + >> /* 'cq_time_wait' is 8bit and is in multiple of 100ns, >> * so clamp the user given value to the range of 1 to 25usec. >> */ >> @@ -521,13 +541,13 @@ static int otx2_set_coalesce(struct net_device >*netdev, >> hw->cq_time_wait = min_t(u8, ec->rx_coalesce_usecs, >> ec->tx_coalesce_usecs); >> >> - /* Max ecount_wait supported is 16bit, >> - * so clamp the user given value to the range of 1 to 64k. >> + /* Max packet budget per napi is 64, >> + * so clamp the user given value to the range of 1 to 64. >> */ >> ec->rx_max_coalesced_frames = clamp_t(u32, ec- >>rx_max_coalesced_frames, >> - 1, U16_MAX); >> + 1, NAPI_POLL_WEIGHT); >> ec->tx_max_coalesced_frames = clamp_t(u32, ec- >>tx_max_coalesced_frames, >> - 1, U16_MAX); >> + 1, NAPI_POLL_WEIGHT); >> >> /* Rx and Tx are mapped to same CQ, check which one >> * is changed, if both then choose the min. >> @@ -540,6 +560,17 @@ static int otx2_set_coalesce(struct net_device >*netdev, >> hw->cq_ecount_wait = min_t(u16, ec->rx_max_coalesced_frames, >> ec->tx_max_coalesced_frames); >> >> + /* Reset 'cq_time_wait' and 'cq_ecount_wait' to >> + * default values if coalesce status changed from >> + * 'on' to 'off'. >> + */ >> + if (priv_coalesce_status && >> + ((pfvf->flags & OTX2_FLAG_ADPTV_INT_COAL_ENABLED) != >> + OTX2_FLAG_ADPTV_INT_COAL_ENABLED)) { >> + hw->cq_time_wait = CQ_TIMER_THRESH_DEFAULT; >> + hw->cq_ecount_wait = CQ_CQE_THRESH_DEFAULT; >> + } >> + >> if (netif_running(netdev)) { >> for (qidx = 0; qidx < pfvf->hw.cint_cnt; qidx++) >> otx2_config_irq_coalescing(pfvf, qidx); diff --git >> a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c >> b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c >> index f18c9a9a50d0..94aaafbeb365 100644 >> --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c >> +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c >> @@ -1279,6 +1279,7 @@ static irqreturn_t otx2_cq_intr_handler(int irq, >void *cq_irq) >> otx2_write64(pf, NIX_LF_CINTX_ENA_W1C(qidx), BIT_ULL(0)); >> >> /* Schedule NAPI */ >> + pf->napi_events++; >> napi_schedule_irqoff(&cq_poll->napi); >> >> return IRQ_HANDLED; >> @@ -1292,6 +1293,7 @@ static void otx2_disable_napi(struct otx2_nic >> *pf) >> >> for (qidx = 0; qidx < pf->hw.cint_cnt; qidx++) { >> cq_poll = &qset->napi[qidx]; >> + cancel_work_sync(&cq_poll->dim.work); >> napi_disable(&cq_poll->napi); >> netif_napi_del(&cq_poll->napi); >> } >> @@ -1538,6 +1540,24 @@ static void otx2_free_hw_resources(struct otx2_nic >*pf) >> mutex_unlock(&mbox->lock); >> } >> >> +static void otx2_dim_work(struct work_struct *w) { >> + struct dim_cq_moder cur_moder; >> + struct otx2_cq_poll *cq_poll; >> + struct otx2_nic *pfvf; >> + struct dim *dim; >> + >> + dim = container_of(w, struct dim, work); >> + cur_moder = net_dim_get_rx_moderation(dim->mode, dim->profile_ix); >> + cq_poll = container_of(dim, struct otx2_cq_poll, dim); >> + pfvf = (struct otx2_nic *)cq_poll->dev; >> + pfvf->hw.cq_time_wait = (cur_moder.usec > CQ_TIMER_THRESH_MAX) ? >> + CQ_TIMER_THRESH_MAX : cur_moder.usec; >> + pfvf->hw.cq_ecount_wait = (cur_moder.pkts > NAPI_POLL_WEIGHT) ? >> + NAPI_POLL_WEIGHT : cur_moder.pkts; >> + dim->state = DIM_START_MEASURE; >> +} >> + >> int otx2_open(struct net_device *netdev) { >> struct otx2_nic *pf = netdev_priv(netdev); @@ -1611,6 +1631,8 @@ int >> otx2_open(struct net_device *netdev) >> CINT_INVALID_CQ; >> >> cq_poll->dev = (void *)pf; >> + cq_poll->dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_CQE; >> + INIT_WORK(&cq_poll->dim.work, otx2_dim_work); >> netif_napi_add(netdev, &cq_poll->napi, >> otx2_napi_handler, NAPI_POLL_WEIGHT); >> napi_enable(&cq_poll->napi); >> diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c >> b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c >> index 459b94b99ddb..927dd12b4f4e 100644 >> --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c >> +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c >> @@ -512,6 +512,22 @@ static int otx2_tx_napi_handler(struct otx2_nic >*pfvf, >> return 0; >> } >> >> +static void otx2_adjust_adaptive_coalese(struct otx2_nic *pfvf, >> +struct otx2_cq_poll *cq_poll) { >> + struct dim_sample dim_sample; >> + u64 rx_frames, rx_bytes; >> + >> + rx_frames = OTX2_GET_RX_STATS(RX_BCAST) + OTX2_GET_RX_STATS(RX_MCAST) >+ >> + OTX2_GET_RX_STATS(RX_UCAST); >> + rx_bytes = OTX2_GET_RX_STATS(RX_OCTS); >> + dim_update_sample(pfvf->napi_events, >> + rx_frames, >> + rx_bytes, >> + &dim_sample); >> + >> + net_dim(&cq_poll->dim, dim_sample); >> +} >> + >> int otx2_napi_handler(struct napi_struct *napi, int budget) { >> struct otx2_cq_queue *rx_cq = NULL; >> @@ -549,6 +565,18 @@ int otx2_napi_handler(struct napi_struct *napi, int >budget) >> if (pfvf->flags & OTX2_FLAG_INTF_DOWN) >> return workdone; >> >> + /* Check for adaptive interrupt coalesce */ >> + if (workdone != 0 && >> + ((pfvf->flags & OTX2_FLAG_ADPTV_INT_COAL_ENABLED) == >> + OTX2_FLAG_ADPTV_INT_COAL_ENABLED)) { >> + /* Adjust irq coalese using net_dim */ >> + otx2_adjust_adaptive_coalese(pfvf, cq_poll); >> + >> + /* Update irq coalescing */ >> + for (i = 0; i < pfvf->hw.cint_cnt; i++) >> + otx2_config_irq_coalescing(pfvf, i); >> + } >> + > >Why are you updating the IRQ coalescing parameters for every sample? >You probably should to that in void otx2_dim_work(), when dim tells it's >the right time to update them. Otx2_dim_work() is called from dim context. All the existing users of net_dim is not doing register read/writes from dim context(example: drivers/net/ethernet/amazon/ena/ena_netdev.c). I guess this is to ensure individual user's register read/write should not impact the performance of the dim algorithm. Regards, Suman >Thanks, > >Paolo
diff --git a/drivers/net/ethernet/marvell/octeontx2/Kconfig b/drivers/net/ethernet/marvell/octeontx2/Kconfig index 8560f7e463d3..a544733152d8 100644 --- a/drivers/net/ethernet/marvell/octeontx2/Kconfig +++ b/drivers/net/ethernet/marvell/octeontx2/Kconfig @@ -30,6 +30,7 @@ config OCTEONTX2_PF tristate "Marvell OcteonTX2 NIC Physical Function driver" select OCTEONTX2_MBOX select NET_DEVLINK + select DIMLIB depends on PCI help This driver supports Marvell's OcteonTX2 Resource Virtualization diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c index 033fd79d35b0..c28850d815c2 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c @@ -103,11 +103,6 @@ void otx2_get_dev_stats(struct otx2_nic *pfvf) { struct otx2_dev_stats *dev_stats = &pfvf->hw.dev_stats; -#define OTX2_GET_RX_STATS(reg) \ - otx2_read64(pfvf, NIX_LF_RX_STATX(reg)) -#define OTX2_GET_TX_STATS(reg) \ - otx2_read64(pfvf, NIX_LF_TX_STATX(reg)) - dev_stats->rx_bytes = OTX2_GET_RX_STATS(RX_OCTS); dev_stats->rx_drops = OTX2_GET_RX_STATS(RX_DROP); dev_stats->rx_bcast_frames = OTX2_GET_RX_STATS(RX_BCAST); diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h index d9f4b085b2a4..6abf5c28921f 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h @@ -16,6 +16,7 @@ #include <net/pkt_cls.h> #include <net/devlink.h> #include <linux/time64.h> +#include <linux/dim.h> #include <mbox.h> #include <npc.h> @@ -54,6 +55,11 @@ enum arua_mapped_qtypes { /* Send skid of 2000 packets required for CQ size of 4K CQEs. */ #define SEND_CQ_SKID 2000 +#define OTX2_GET_RX_STATS(reg) \ + otx2_read64(pfvf, NIX_LF_RX_STATX(reg)) +#define OTX2_GET_TX_STATS(reg) \ + otx2_read64(pfvf, NIX_LF_TX_STATX(reg)) + struct otx2_lmt_info { u64 lmt_addr; u16 lmt_id; @@ -363,6 +369,7 @@ struct otx2_nic { #define OTX2_FLAG_TC_MATCHALL_INGRESS_ENABLED BIT_ULL(13) #define OTX2_FLAG_DMACFLTR_SUPPORT BIT_ULL(14) #define OTX2_FLAG_PTP_ONESTEP_SYNC BIT_ULL(15) +#define OTX2_FLAG_ADPTV_INT_COAL_ENABLED BIT_ULL(16) u64 flags; u64 *cq_op_addr; @@ -442,6 +449,9 @@ struct otx2_nic { #endif /* qos */ struct otx2_qos qos; + + /* napi event count. It is needed for adaptive irq coalescing */ + u32 napi_events; }; static inline bool is_otx2_lbkvf(struct pci_dev *pdev) diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c index 72d0b02da3cc..8ed282991f05 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c @@ -477,6 +477,14 @@ static int otx2_get_coalesce(struct net_device *netdev, cmd->rx_max_coalesced_frames = hw->cq_ecount_wait; cmd->tx_coalesce_usecs = hw->cq_time_wait; cmd->tx_max_coalesced_frames = hw->cq_ecount_wait; + if ((pfvf->flags & OTX2_FLAG_ADPTV_INT_COAL_ENABLED) == + OTX2_FLAG_ADPTV_INT_COAL_ENABLED) { + cmd->use_adaptive_rx_coalesce = 1; + cmd->use_adaptive_tx_coalesce = 1; + } else { + cmd->use_adaptive_rx_coalesce = 0; + cmd->use_adaptive_tx_coalesce = 0; + } return 0; } @@ -486,10 +494,10 @@ static int otx2_set_coalesce(struct net_device *netdev, { struct otx2_nic *pfvf = netdev_priv(netdev); struct otx2_hw *hw = &pfvf->hw; + u8 priv_coalesce_status; int qidx; - if (ec->use_adaptive_rx_coalesce || ec->use_adaptive_tx_coalesce || - ec->rx_coalesce_usecs_irq || ec->rx_max_coalesced_frames_irq || + if (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 || @@ -502,6 +510,18 @@ static int otx2_set_coalesce(struct net_device *netdev, if (!ec->rx_max_coalesced_frames || !ec->tx_max_coalesced_frames) return 0; + /* Check and update coalesce status */ + if ((pfvf->flags & OTX2_FLAG_ADPTV_INT_COAL_ENABLED) == + OTX2_FLAG_ADPTV_INT_COAL_ENABLED) { + priv_coalesce_status = 1; + if (!ec->use_adaptive_rx_coalesce || !ec->use_adaptive_tx_coalesce) + pfvf->flags &= ~OTX2_FLAG_ADPTV_INT_COAL_ENABLED; + } else { + priv_coalesce_status = 0; + if (ec->use_adaptive_rx_coalesce || ec->use_adaptive_tx_coalesce) + pfvf->flags |= OTX2_FLAG_ADPTV_INT_COAL_ENABLED; + } + /* 'cq_time_wait' is 8bit and is in multiple of 100ns, * so clamp the user given value to the range of 1 to 25usec. */ @@ -521,13 +541,13 @@ static int otx2_set_coalesce(struct net_device *netdev, hw->cq_time_wait = min_t(u8, ec->rx_coalesce_usecs, ec->tx_coalesce_usecs); - /* Max ecount_wait supported is 16bit, - * so clamp the user given value to the range of 1 to 64k. + /* Max packet budget per napi is 64, + * so clamp the user given value to the range of 1 to 64. */ ec->rx_max_coalesced_frames = clamp_t(u32, ec->rx_max_coalesced_frames, - 1, U16_MAX); + 1, NAPI_POLL_WEIGHT); ec->tx_max_coalesced_frames = clamp_t(u32, ec->tx_max_coalesced_frames, - 1, U16_MAX); + 1, NAPI_POLL_WEIGHT); /* Rx and Tx are mapped to same CQ, check which one * is changed, if both then choose the min. @@ -540,6 +560,17 @@ static int otx2_set_coalesce(struct net_device *netdev, hw->cq_ecount_wait = min_t(u16, ec->rx_max_coalesced_frames, ec->tx_max_coalesced_frames); + /* Reset 'cq_time_wait' and 'cq_ecount_wait' to + * default values if coalesce status changed from + * 'on' to 'off'. + */ + if (priv_coalesce_status && + ((pfvf->flags & OTX2_FLAG_ADPTV_INT_COAL_ENABLED) != + OTX2_FLAG_ADPTV_INT_COAL_ENABLED)) { + hw->cq_time_wait = CQ_TIMER_THRESH_DEFAULT; + hw->cq_ecount_wait = CQ_CQE_THRESH_DEFAULT; + } + if (netif_running(netdev)) { for (qidx = 0; qidx < pfvf->hw.cint_cnt; qidx++) otx2_config_irq_coalescing(pfvf, qidx); diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c index f18c9a9a50d0..94aaafbeb365 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c @@ -1279,6 +1279,7 @@ static irqreturn_t otx2_cq_intr_handler(int irq, void *cq_irq) otx2_write64(pf, NIX_LF_CINTX_ENA_W1C(qidx), BIT_ULL(0)); /* Schedule NAPI */ + pf->napi_events++; napi_schedule_irqoff(&cq_poll->napi); return IRQ_HANDLED; @@ -1292,6 +1293,7 @@ static void otx2_disable_napi(struct otx2_nic *pf) for (qidx = 0; qidx < pf->hw.cint_cnt; qidx++) { cq_poll = &qset->napi[qidx]; + cancel_work_sync(&cq_poll->dim.work); napi_disable(&cq_poll->napi); netif_napi_del(&cq_poll->napi); } @@ -1538,6 +1540,24 @@ static void otx2_free_hw_resources(struct otx2_nic *pf) mutex_unlock(&mbox->lock); } +static void otx2_dim_work(struct work_struct *w) +{ + struct dim_cq_moder cur_moder; + struct otx2_cq_poll *cq_poll; + struct otx2_nic *pfvf; + struct dim *dim; + + dim = container_of(w, struct dim, work); + cur_moder = net_dim_get_rx_moderation(dim->mode, dim->profile_ix); + cq_poll = container_of(dim, struct otx2_cq_poll, dim); + pfvf = (struct otx2_nic *)cq_poll->dev; + pfvf->hw.cq_time_wait = (cur_moder.usec > CQ_TIMER_THRESH_MAX) ? + CQ_TIMER_THRESH_MAX : cur_moder.usec; + pfvf->hw.cq_ecount_wait = (cur_moder.pkts > NAPI_POLL_WEIGHT) ? + NAPI_POLL_WEIGHT : cur_moder.pkts; + dim->state = DIM_START_MEASURE; +} + int otx2_open(struct net_device *netdev) { struct otx2_nic *pf = netdev_priv(netdev); @@ -1611,6 +1631,8 @@ int otx2_open(struct net_device *netdev) CINT_INVALID_CQ; cq_poll->dev = (void *)pf; + cq_poll->dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_CQE; + INIT_WORK(&cq_poll->dim.work, otx2_dim_work); netif_napi_add(netdev, &cq_poll->napi, otx2_napi_handler, NAPI_POLL_WEIGHT); napi_enable(&cq_poll->napi); diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c index 459b94b99ddb..927dd12b4f4e 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c @@ -512,6 +512,22 @@ static int otx2_tx_napi_handler(struct otx2_nic *pfvf, return 0; } +static void otx2_adjust_adaptive_coalese(struct otx2_nic *pfvf, struct otx2_cq_poll *cq_poll) +{ + struct dim_sample dim_sample; + u64 rx_frames, rx_bytes; + + rx_frames = OTX2_GET_RX_STATS(RX_BCAST) + OTX2_GET_RX_STATS(RX_MCAST) + + OTX2_GET_RX_STATS(RX_UCAST); + rx_bytes = OTX2_GET_RX_STATS(RX_OCTS); + dim_update_sample(pfvf->napi_events, + rx_frames, + rx_bytes, + &dim_sample); + + net_dim(&cq_poll->dim, dim_sample); +} + int otx2_napi_handler(struct napi_struct *napi, int budget) { struct otx2_cq_queue *rx_cq = NULL; @@ -549,6 +565,18 @@ int otx2_napi_handler(struct napi_struct *napi, int budget) if (pfvf->flags & OTX2_FLAG_INTF_DOWN) return workdone; + /* Check for adaptive interrupt coalesce */ + if (workdone != 0 && + ((pfvf->flags & OTX2_FLAG_ADPTV_INT_COAL_ENABLED) == + OTX2_FLAG_ADPTV_INT_COAL_ENABLED)) { + /* Adjust irq coalese using net_dim */ + otx2_adjust_adaptive_coalese(pfvf, cq_poll); + + /* Update irq coalescing */ + for (i = 0; i < pfvf->hw.cint_cnt; i++) + otx2_config_irq_coalescing(pfvf, i); + } + /* Re-enable interrupts */ otx2_write64(pfvf, NIX_LF_CINTX_ENA_W1S(cq_poll->cint_idx), BIT_ULL(0)); diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h index a2ac2b3bdbf5..ed41a68d3ec6 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h @@ -107,6 +107,7 @@ struct otx2_cq_poll { #define CINT_INVALID_CQ 255 u8 cint_idx; u8 cq_ids[CQS_PER_CINT]; + struct dim dim; struct napi_struct napi; };