[Intel-wired-lan] [PATCH next-queue v2 3/3] igc: Add support for CBS offloading
Gunasekaran, Aravindhan
aravindhan.gunasekaran at intel.com
Mon Aug 9 06:37:55 UTC 2021
> -----Original Message-----
> From: Paul Menzel <pmenzel at molgen.mpg.de>
> Sent: Wednesday, August 4, 2021 8:11 PM
> To: Gunasekaran, Aravindhan <aravindhan.gunasekaran at intel.com>
> Cc: Chenniyappan, Velmurugan <velmurugan.chenniyappan at intel.com>;
> Chilakala, Mallikarjuna <mallikarjuna.chilakala at intel.com>; intel-wired-
> lan at osuosl.org
> Subject: Re: [Intel-wired-lan] [PATCH next-queue v2 3/3] igc: Add support for
> CBS offloading
>
> Dear Aravindhan,
>
>
> Am 04.08.21 um 16:19 schrieb aravindhan.gunasekaran at intel.com:
> > From: Aravindhan Gunasekaran <aravindhan.gunasekaran at intel.com>
> >
> > Implemented support for CBS Qdisc hardware offload mode in the driver.
> > There are two sets of CBS HW logic in i225 controller and this patch
> > supports enabling them in the top two priority TX queues.
> >
> > In-order for CBS algorithm to work as intended and provide BW
> > reservation CBS should be enabled in highest priority queue first.
> > If we enable CBS on any of low priority queues, the traffic in high
> > priority queue does not allow low priority queue to be selected for
> > transmission and bandwidth reservation is not guaranteed.
>
> Nit: Please re-flow for 75 characters per line.
>
> Please mention IEEE802.1Qav (CBS) in the commit message, the datasheet
> name and revision you used for the implementation (I see it in one of the
> comments), and maybe how to configure it.
>
> Should Linux log a message, if support is detected and used?
>
>
> Kind regards,
>
> Paul
This is my response.
>
>
> > Signed-off-by: Aravindhan Gunasekaran
> > <aravindhan.gunasekaran at intel.com>
> > ---
> > drivers/net/ethernet/intel/igc/igc.h | 11 ++-
> > drivers/net/ethernet/intel/igc/igc_defines.h | 8 +++
> > drivers/net/ethernet/intel/igc/igc_main.c | 71 ++++++++++++++++++
> > drivers/net/ethernet/intel/igc/igc_regs.h | 3 +
> > drivers/net/ethernet/intel/igc/igc_tsn.c | 103
> +++++++++++++++++++++++++++
> > 5 files changed, 195 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/net/ethernet/intel/igc/igc.h
> > b/drivers/net/ethernet/intel/igc/igc.h
> > index 58488ba..a125aaf 100644
> > --- a/drivers/net/ethernet/intel/igc/igc.h
> > +++ b/drivers/net/ethernet/intel/igc/igc.h
> > @@ -98,6 +98,13 @@ struct igc_ring {
> > u32 start_time;
> > u32 end_time;
> >
> > + /* CBS parameters */
> > + bool cbs_enable; /* indicates if CBS is enabled */
> > + s32 idleslope; /* idleSlope in kbps */
> > + s32 sendslope; /* sendSlope in kbps */
> > + s32 hicredit; /* hiCredit in bytes */
> > + s32 locredit; /* loCredit in bytes */
> > +
> > /* everything past this point are written often */
> > u16 next_to_clean;
> > u16 next_to_use;
> > @@ -289,8 +296,10 @@ extern char igc_driver_name[];
> > #define IGC_FLAG_VLAN_PROMISC BIT(15)
> > #define IGC_FLAG_RX_LEGACY BIT(16)
> > #define IGC_FLAG_TSN_QBV_ENABLED BIT(17)
> > +#define IGC_FLAG_TSN_QAV_ENABLED BIT(18)
> >
> > -#define IGC_FLAG_TSN_ANY_ENABLED
> IGC_FLAG_TSN_QBV_ENABLED
> > +#define IGC_FLAG_TSN_ANY_ENABLED \
> > + (IGC_FLAG_TSN_QBV_ENABLED | IGC_FLAG_TSN_QAV_ENABLED)
> >
> > #define IGC_FLAG_RSS_FIELD_IPV4_UDP BIT(6)
> > #define IGC_FLAG_RSS_FIELD_IPV6_UDP BIT(7)
> > diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h
> > b/drivers/net/ethernet/intel/igc/igc_defines.h
> > index 1361086..244edbc 100644
> > --- a/drivers/net/ethernet/intel/igc/igc_defines.h
> > +++ b/drivers/net/ethernet/intel/igc/igc_defines.h
> > @@ -518,6 +518,14 @@
> > #define IGC_TXQCTL_QUEUE_MODE_LAUNCHT 0x00000001
> > #define IGC_TXQCTL_STRICT_CYCLE 0x00000002
> > #define IGC_TXQCTL_STRICT_END 0x00000004
> > +#define IGC_TXQCTL_QAV_SEL_MASK 0x000000C0
> > +#define IGC_TXQCTL_QAV_SEL_CBS0 0x00000080
> > +#define IGC_TXQCTL_QAV_SEL_CBS1 0x000000C0
> > +
> > +#define IGC_TQAVCC_IDLESLOPE_MASK 0xFFFF
> > +#define IGC_TQAVCC_KEEP_CREDITS BIT(30)
> > +
> > +#define IGC_MAX_SR_QUEUES 2
> >
> > /* Receive Checksum Control */
> > #define IGC_RXCSUM_CRCOFL 0x00000800 /* CRC32 offload enable
> */
> > diff --git a/drivers/net/ethernet/intel/igc/igc_main.c
> > b/drivers/net/ethernet/intel/igc/igc_main.c
> > index 3eb4f9e..ea12633 100644
> > --- a/drivers/net/ethernet/intel/igc/igc_main.c
> > +++ b/drivers/net/ethernet/intel/igc/igc_main.c
> > @@ -5905,6 +5905,74 @@ static int igc_tsn_enable_qbv_scheduling(struct
> igc_adapter *adapter,
> > return igc_tsn_offload_apply(adapter);
> > }
> >
> > +static int igc_save_cbs_params(struct igc_adapter *adapter, int queue,
> > + bool enable, int idleslope, int sendslope,
> > + int hicredit, int locredit) {
> > + bool cbs_status[IGC_MAX_SR_QUEUES] = { false };
> > + struct net_device *netdev = adapter->netdev;
> > + struct igc_ring *ring;
> > + int i;
> > +
> > + /* i225 has two sets of credit-based shaper logic.
> > + * Supporting it only on the top two priority queues
> > + */
> > + if (queue < 0 || queue > 1)
> > + return -EINVAL;
> > +
> > + ring = adapter->tx_ring[queue];
> > +
> > + for (i = 0; i < IGC_MAX_SR_QUEUES; i++)
> > + if (adapter->tx_ring[i])
> > + cbs_status[i] = adapter->tx_ring[i]->cbs_enable;
> > +
> > + /* CBS should be enabled on the highest priority queue first inorder
> > + * for the CBS algorithm to operate as intended.
> > + */
> > + if (enable) {
> > + if (queue == 1 && !cbs_status[0]) {
> > + netdev_err(netdev,
> > + "Enabling CBS on queue1 before
> queue0\n");
> > + return -EINVAL;
> > + }
> > + } else {
> > + if (queue == 0 && cbs_status[1]) {
> > + netdev_err(netdev,
> > + "Disabling CBS on queue0 before
> queue1\n");
> > + return -EINVAL;
> > + }
> > + }
> > +
> > + ring->cbs_enable = enable;
> > + ring->idleslope = idleslope;
> > + ring->sendslope = sendslope;
> > + ring->hicredit = hicredit;
> > + ring->locredit = locredit;
> > +
> > + return 0;
> > +}
> > +
> > +static int igc_tsn_enable_cbs(struct igc_adapter *adapter,
> > + struct tc_cbs_qopt_offload *qopt) {
> > + struct igc_hw *hw = &adapter->hw;
> > + int err;
> > +
> > + if (hw->mac.type != igc_i225)
> > + return -EOPNOTSUPP;
> > +
> > + if (qopt->queue < 0 || qopt->queue > 1)
> > + return -EINVAL;
> > +
> > + err = igc_save_cbs_params(adapter, qopt->queue, qopt->enable,
> > + qopt->idleslope, qopt->sendslope,
> > + qopt->hicredit, qopt->locredit);
> > + if (err)
> > + return err;
> > +
> > + return igc_tsn_offload_apply(adapter); }
> > +
> > static int igc_setup_tc(struct net_device *dev, enum tc_setup_type type,
> > void *type_data)
> > {
> > @@ -5917,6 +5985,9 @@ static int igc_setup_tc(struct net_device *dev,
> enum tc_setup_type type,
> > case TC_SETUP_QDISC_ETF:
> > return igc_tsn_enable_launchtime(adapter, type_data);
> >
> > + case TC_SETUP_QDISC_CBS:
> > + return igc_tsn_enable_cbs(adapter, type_data);
> > +
> > default:
> > return -EOPNOTSUPP;
> > }
> > diff --git a/drivers/net/ethernet/intel/igc/igc_regs.h
> > b/drivers/net/ethernet/intel/igc/igc_regs.h
> > index 828c350..f90a644 100644
> > --- a/drivers/net/ethernet/intel/igc/igc_regs.h
> > +++ b/drivers/net/ethernet/intel/igc/igc_regs.h
> > @@ -236,6 +236,9 @@
> > #define IGC_ENDQT(_n) (0x3334 + 0x4 * (_n))
> > #define IGC_DTXMXPKTSZ 0x355C
> >
> > +#define IGC_TQAVCC(_n) (0x3004 + ((_n) * 0x40))
> > +#define IGC_TQAVHC(_n) (0x300C + ((_n) * 0x40))
> > +
> > /* System Time Registers */
> > #define IGC_SYSTIML 0x0B600 /* System time register Low - RO */
> > #define IGC_SYSTIMH 0x0B604 /* System time register High - RO */
> > diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.c
> > b/drivers/net/ethernet/intel/igc/igc_tsn.c
> > index 2935d57..0fce22d 100644
> > --- a/drivers/net/ethernet/intel/igc/igc_tsn.c
> > +++ b/drivers/net/ethernet/intel/igc/igc_tsn.c
> > @@ -18,6 +18,20 @@ static bool is_any_launchtime(struct igc_adapter
> *adapter)
> > return false;
> > }
> >
> > +static bool is_cbs_enabled(struct igc_adapter *adapter) {
> > + int i;
> > +
> > + for (i = 0; i < adapter->num_tx_queues; i++) {
> > + struct igc_ring *ring = adapter->tx_ring[i];
> > +
> > + if (ring->cbs_enable)
> > + return true;
> > + }
> > +
> > + return false;
> > +}
> > +
> > static unsigned int igc_tsn_new_flags(struct igc_adapter *adapter)
> > {
> > unsigned int new_flags = adapter->flags &
> > ~IGC_FLAG_TSN_ANY_ENABLED; @@ -28,6 +42,9 @@ static unsigned int
> igc_tsn_new_flags(struct igc_adapter *adapter)
> > if (is_any_launchtime(adapter))
> > new_flags |= IGC_FLAG_TSN_QBV_ENABLED;
> >
> > + if (is_cbs_enabled(adapter))
> > + new_flags |= IGC_FLAG_TSN_QAV_ENABLED;
> > +
> > return new_flags;
> > }
> >
> > @@ -87,6 +104,8 @@ static int igc_tsn_enable_offload(struct igc_adapter
> *adapter)
> > for (i = 0; i < adapter->num_tx_queues; i++) {
> > struct igc_ring *ring = adapter->tx_ring[i];
> > u32 txqctl = 0;
> > + u16 cbs_value;
> > + u32 tqavcc;
> >
> > wr32(IGC_STQT(i), ring->start_time);
> > wr32(IGC_ENDQT(i), ring->end_time); @@ -104,6 +123,90
> @@ static
> > int igc_tsn_enable_offload(struct igc_adapter *adapter)
> > if (ring->launchtime_enable)
> > txqctl |= IGC_TXQCTL_QUEUE_MODE_LAUNCHT;
> >
> > + /* Skip configuring CBS for Q2 and Q3 */
> > + if (i > 1)
> > + goto skip_cbs;
> > +
> > + if (ring->cbs_enable) {
> > + if (i == 0)
> > + txqctl |= IGC_TXQCTL_QAV_SEL_CBS0;
> > + else
> > + txqctl |= IGC_TXQCTL_QAV_SEL_CBS1;
> > +
> > + /* According to i225 datasheet section 7.5.2.7, we
> > + * should set the 'idleSlope' field from TQAVCC
> > + * register following the equation:
> > + *
> > + * value = link-speed 0x7736 * BW * 0.2
> > + * ---------- * ----------------- (E1)
> > + * 100Mbps 2.5
> > + *
> > + * Note that 'link-speed' is in Mbps.
> > + *
> > + * 'BW' is the percentage bandwidth out of full
> > + * link speed which can be found with the
> > + * following equation. Note that idleSlope here
> > + * is the parameter from this function
> > + * which is in kbps.
> > + *
> > + * BW = idleSlope
> > + * ----------------- (E2)
> > + * link-speed * 1000
> > + *
> > + * That said, we can come up with a generic
> > + * equation to calculate the value we should set
> > + * it TQAVCC register by replacing 'BW' in E1 by E2.
> > + * The resulting equation is:
> > + *
> > + * value = link-speed * 0x7736 * idleSlope * 0.2
> > + * ------------------------------------- (E3)
> > + * 100 * 2.5 * link-speed * 1000
> > + *
> > + * 'link-speed' is present in both sides of the
> > + * fraction so it is canceled out. The final
> > + * equation is the following:
> > + *
> > + * value = idleSlope * 61036
> > + * ----------------- (E4)
> > + * 2500000
> > + *
> > + * NOTE: For i225, given the above, we can see
> > + * that idleslope is represented in
> > + * 40.959433 kbps units by the value at
> > + * the TQAVCC register (2.5Gbps / 61036),
> > + * which reduces the granularity for
> > + * idleslope increments.
> > + *
> > + * In i225 controller, the sendSlope and loCredit
> > + * parameters from CBS are not configurable
> > + * by software so we don't do any
> > + * 'controller configuration' in respect to
> > + * these parameters.
> > + */
> > + cbs_value = DIV_ROUND_UP_ULL(ring->idleslope
> > + * 61036ULL, 2500000);
> > +
> > + tqavcc = rd32(IGC_TQAVCC(i));
> > + tqavcc &= ~IGC_TQAVCC_IDLESLOPE_MASK;
> > + tqavcc |= cbs_value | IGC_TQAVCC_KEEP_CREDITS;
> > + wr32(IGC_TQAVCC(i), tqavcc);
> > +
> > + wr32(IGC_TQAVHC(i),
> > + 0x80000000 + ring->hicredit * 0x7735);
> > + } else {
> > + /* Disable any CBS for the queue */
> > + txqctl &= ~(IGC_TXQCTL_QAV_SEL_MASK);
> > +
> > + /* Set idleSlope to zero. */
> > + tqavcc = rd32(IGC_TQAVCC(i));
> > + tqavcc &= ~(IGC_TQAVCC_IDLESLOPE_MASK |
> > + IGC_TQAVCC_KEEP_CREDITS);
> > + wr32(IGC_TQAVCC(i), tqavcc);
> > +
> > + /* Set hiCredit to zero. */
> > + wr32(IGC_TQAVHC(i), 0);
> > + }
> > +skip_cbs:
> > wr32(IGC_TXQCTL(i), txqctl);
> > }
> >
> >
More information about the Intel-wired-lan
mailing list