Skip to content

Commit 1ab011b

Browse files
agunasekanguy11
authored andcommitted
igc: Add support for CBS offloading
Implement support for Credit-based shaper(CBS) Qdisc hardware offload mode in the driver. There are two sets of IEEE802.1Qav (CBS) HW logic in i225 controller and this patch supports enabling them in the top two priority TX queues. Driver implemented as recommended by Foxville External Architecture Specification v0.993. Idleslope and Hi-credit are the CBS tunable parameters for i225 NIC, programmed in TQAVCC and TQAVHC registers respectively. In-order for IEEE802.1Qav (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. Signed-off-by: Aravindhan Gunasekaran <[email protected]> Signed-off-by: Mallikarjuna Chilakala <[email protected]> Tested-by: Dvora Fuxbrumer <[email protected]> Signed-off-by: Tony Nguyen <[email protected]>
1 parent 61572d5 commit 1ab011b

File tree

5 files changed

+195
-1
lines changed

5 files changed

+195
-1
lines changed

drivers/net/ethernet/intel/igc/igc.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,13 @@ struct igc_ring {
9898
u32 start_time;
9999
u32 end_time;
100100

101+
/* CBS parameters */
102+
bool cbs_enable; /* indicates if CBS is enabled */
103+
s32 idleslope; /* idleSlope in kbps */
104+
s32 sendslope; /* sendSlope in kbps */
105+
s32 hicredit; /* hiCredit in bytes */
106+
s32 locredit; /* loCredit in bytes */
107+
101108
/* everything past this point are written often */
102109
u16 next_to_clean;
103110
u16 next_to_use;
@@ -290,8 +297,10 @@ extern char igc_driver_name[];
290297
#define IGC_FLAG_VLAN_PROMISC BIT(15)
291298
#define IGC_FLAG_RX_LEGACY BIT(16)
292299
#define IGC_FLAG_TSN_QBV_ENABLED BIT(17)
300+
#define IGC_FLAG_TSN_QAV_ENABLED BIT(18)
293301

294-
#define IGC_FLAG_TSN_ANY_ENABLED IGC_FLAG_TSN_QBV_ENABLED
302+
#define IGC_FLAG_TSN_ANY_ENABLED \
303+
(IGC_FLAG_TSN_QBV_ENABLED | IGC_FLAG_TSN_QAV_ENABLED)
295304

296305
#define IGC_FLAG_RSS_FIELD_IPV4_UDP BIT(6)
297306
#define IGC_FLAG_RSS_FIELD_IPV6_UDP BIT(7)

drivers/net/ethernet/intel/igc/igc_defines.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,14 @@
518518
#define IGC_TXQCTL_QUEUE_MODE_LAUNCHT 0x00000001
519519
#define IGC_TXQCTL_STRICT_CYCLE 0x00000002
520520
#define IGC_TXQCTL_STRICT_END 0x00000004
521+
#define IGC_TXQCTL_QAV_SEL_MASK 0x000000C0
522+
#define IGC_TXQCTL_QAV_SEL_CBS0 0x00000080
523+
#define IGC_TXQCTL_QAV_SEL_CBS1 0x000000C0
524+
525+
#define IGC_TQAVCC_IDLESLOPE_MASK 0xFFFF
526+
#define IGC_TQAVCC_KEEP_CREDITS BIT(30)
527+
528+
#define IGC_MAX_SR_QUEUES 2
521529

522530
/* Receive Checksum Control */
523531
#define IGC_RXCSUM_CRCOFL 0x00000800 /* CRC32 offload enable */

drivers/net/ethernet/intel/igc/igc_main.c

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5904,6 +5904,74 @@ static int igc_tsn_enable_qbv_scheduling(struct igc_adapter *adapter,
59045904
return igc_tsn_offload_apply(adapter);
59055905
}
59065906

5907+
static int igc_save_cbs_params(struct igc_adapter *adapter, int queue,
5908+
bool enable, int idleslope, int sendslope,
5909+
int hicredit, int locredit)
5910+
{
5911+
bool cbs_status[IGC_MAX_SR_QUEUES] = { false };
5912+
struct net_device *netdev = adapter->netdev;
5913+
struct igc_ring *ring;
5914+
int i;
5915+
5916+
/* i225 has two sets of credit-based shaper logic.
5917+
* Supporting it only on the top two priority queues
5918+
*/
5919+
if (queue < 0 || queue > 1)
5920+
return -EINVAL;
5921+
5922+
ring = adapter->tx_ring[queue];
5923+
5924+
for (i = 0; i < IGC_MAX_SR_QUEUES; i++)
5925+
if (adapter->tx_ring[i])
5926+
cbs_status[i] = adapter->tx_ring[i]->cbs_enable;
5927+
5928+
/* CBS should be enabled on the highest priority queue first in order
5929+
* for the CBS algorithm to operate as intended.
5930+
*/
5931+
if (enable) {
5932+
if (queue == 1 && !cbs_status[0]) {
5933+
netdev_err(netdev,
5934+
"Enabling CBS on queue1 before queue0\n");
5935+
return -EINVAL;
5936+
}
5937+
} else {
5938+
if (queue == 0 && cbs_status[1]) {
5939+
netdev_err(netdev,
5940+
"Disabling CBS on queue0 before queue1\n");
5941+
return -EINVAL;
5942+
}
5943+
}
5944+
5945+
ring->cbs_enable = enable;
5946+
ring->idleslope = idleslope;
5947+
ring->sendslope = sendslope;
5948+
ring->hicredit = hicredit;
5949+
ring->locredit = locredit;
5950+
5951+
return 0;
5952+
}
5953+
5954+
static int igc_tsn_enable_cbs(struct igc_adapter *adapter,
5955+
struct tc_cbs_qopt_offload *qopt)
5956+
{
5957+
struct igc_hw *hw = &adapter->hw;
5958+
int err;
5959+
5960+
if (hw->mac.type != igc_i225)
5961+
return -EOPNOTSUPP;
5962+
5963+
if (qopt->queue < 0 || qopt->queue > 1)
5964+
return -EINVAL;
5965+
5966+
err = igc_save_cbs_params(adapter, qopt->queue, qopt->enable,
5967+
qopt->idleslope, qopt->sendslope,
5968+
qopt->hicredit, qopt->locredit);
5969+
if (err)
5970+
return err;
5971+
5972+
return igc_tsn_offload_apply(adapter);
5973+
}
5974+
59075975
static int igc_setup_tc(struct net_device *dev, enum tc_setup_type type,
59085976
void *type_data)
59095977
{
@@ -5916,6 +5984,9 @@ static int igc_setup_tc(struct net_device *dev, enum tc_setup_type type,
59165984
case TC_SETUP_QDISC_ETF:
59175985
return igc_tsn_enable_launchtime(adapter, type_data);
59185986

5987+
case TC_SETUP_QDISC_CBS:
5988+
return igc_tsn_enable_cbs(adapter, type_data);
5989+
59195990
default:
59205991
return -EOPNOTSUPP;
59215992
}

drivers/net/ethernet/intel/igc/igc_regs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,9 @@
236236
#define IGC_ENDQT(_n) (0x3334 + 0x4 * (_n))
237237
#define IGC_DTXMXPKTSZ 0x355C
238238

239+
#define IGC_TQAVCC(_n) (0x3004 + ((_n) * 0x40))
240+
#define IGC_TQAVHC(_n) (0x300C + ((_n) * 0x40))
241+
239242
/* System Time Registers */
240243
#define IGC_SYSTIML 0x0B600 /* System time register Low - RO */
241244
#define IGC_SYSTIMH 0x0B604 /* System time register High - RO */

drivers/net/ethernet/intel/igc/igc_tsn.c

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,20 @@ static bool is_any_launchtime(struct igc_adapter *adapter)
1818
return false;
1919
}
2020

21+
static bool is_cbs_enabled(struct igc_adapter *adapter)
22+
{
23+
int i;
24+
25+
for (i = 0; i < adapter->num_tx_queues; i++) {
26+
struct igc_ring *ring = adapter->tx_ring[i];
27+
28+
if (ring->cbs_enable)
29+
return true;
30+
}
31+
32+
return false;
33+
}
34+
2135
static unsigned int igc_tsn_new_flags(struct igc_adapter *adapter)
2236
{
2337
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)
2842
if (is_any_launchtime(adapter))
2943
new_flags |= IGC_FLAG_TSN_QBV_ENABLED;
3044

45+
if (is_cbs_enabled(adapter))
46+
new_flags |= IGC_FLAG_TSN_QAV_ENABLED;
47+
3148
return new_flags;
3249
}
3350

@@ -87,6 +104,8 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
87104
for (i = 0; i < adapter->num_tx_queues; i++) {
88105
struct igc_ring *ring = adapter->tx_ring[i];
89106
u32 txqctl = 0;
107+
u16 cbs_value;
108+
u32 tqavcc;
90109

91110
wr32(IGC_STQT(i), ring->start_time);
92111
wr32(IGC_ENDQT(i), ring->end_time);
@@ -104,6 +123,90 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
104123
if (ring->launchtime_enable)
105124
txqctl |= IGC_TXQCTL_QUEUE_MODE_LAUNCHT;
106125

126+
/* Skip configuring CBS for Q2 and Q3 */
127+
if (i > 1)
128+
goto skip_cbs;
129+
130+
if (ring->cbs_enable) {
131+
if (i == 0)
132+
txqctl |= IGC_TXQCTL_QAV_SEL_CBS0;
133+
else
134+
txqctl |= IGC_TXQCTL_QAV_SEL_CBS1;
135+
136+
/* According to i225 datasheet section 7.5.2.7, we
137+
* should set the 'idleSlope' field from TQAVCC
138+
* register following the equation:
139+
*
140+
* value = link-speed 0x7736 * BW * 0.2
141+
* ---------- * ----------------- (E1)
142+
* 100Mbps 2.5
143+
*
144+
* Note that 'link-speed' is in Mbps.
145+
*
146+
* 'BW' is the percentage bandwidth out of full
147+
* link speed which can be found with the
148+
* following equation. Note that idleSlope here
149+
* is the parameter from this function
150+
* which is in kbps.
151+
*
152+
* BW = idleSlope
153+
* ----------------- (E2)
154+
* link-speed * 1000
155+
*
156+
* That said, we can come up with a generic
157+
* equation to calculate the value we should set
158+
* it TQAVCC register by replacing 'BW' in E1 by E2.
159+
* The resulting equation is:
160+
*
161+
* value = link-speed * 0x7736 * idleSlope * 0.2
162+
* ------------------------------------- (E3)
163+
* 100 * 2.5 * link-speed * 1000
164+
*
165+
* 'link-speed' is present in both sides of the
166+
* fraction so it is canceled out. The final
167+
* equation is the following:
168+
*
169+
* value = idleSlope * 61036
170+
* ----------------- (E4)
171+
* 2500000
172+
*
173+
* NOTE: For i225, given the above, we can see
174+
* that idleslope is represented in
175+
* 40.959433 kbps units by the value at
176+
* the TQAVCC register (2.5Gbps / 61036),
177+
* which reduces the granularity for
178+
* idleslope increments.
179+
*
180+
* In i225 controller, the sendSlope and loCredit
181+
* parameters from CBS are not configurable
182+
* by software so we don't do any
183+
* 'controller configuration' in respect to
184+
* these parameters.
185+
*/
186+
cbs_value = DIV_ROUND_UP_ULL(ring->idleslope
187+
* 61036ULL, 2500000);
188+
189+
tqavcc = rd32(IGC_TQAVCC(i));
190+
tqavcc &= ~IGC_TQAVCC_IDLESLOPE_MASK;
191+
tqavcc |= cbs_value | IGC_TQAVCC_KEEP_CREDITS;
192+
wr32(IGC_TQAVCC(i), tqavcc);
193+
194+
wr32(IGC_TQAVHC(i),
195+
0x80000000 + ring->hicredit * 0x7735);
196+
} else {
197+
/* Disable any CBS for the queue */
198+
txqctl &= ~(IGC_TXQCTL_QAV_SEL_MASK);
199+
200+
/* Set idleSlope to zero. */
201+
tqavcc = rd32(IGC_TQAVCC(i));
202+
tqavcc &= ~(IGC_TQAVCC_IDLESLOPE_MASK |
203+
IGC_TQAVCC_KEEP_CREDITS);
204+
wr32(IGC_TQAVCC(i), tqavcc);
205+
206+
/* Set hiCredit to zero. */
207+
wr32(IGC_TQAVHC(i), 0);
208+
}
209+
skip_cbs:
107210
wr32(IGC_TXQCTL(i), txqctl);
108211
}
109212

0 commit comments

Comments
 (0)