1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2019 Intel Corporation */
8 static bool is_any_launchtime(struct igc_adapter *adapter)
12 for (i = 0; i < adapter->num_tx_queues; i++) {
13 struct igc_ring *ring = adapter->tx_ring[i];
15 if (ring->launchtime_enable)
22 static bool is_cbs_enabled(struct igc_adapter *adapter)
26 for (i = 0; i < adapter->num_tx_queues; i++) {
27 struct igc_ring *ring = adapter->tx_ring[i];
36 static unsigned int igc_tsn_new_flags(struct igc_adapter *adapter)
38 unsigned int new_flags = adapter->flags & ~IGC_FLAG_TSN_ANY_ENABLED;
40 if (adapter->qbv_enable)
41 new_flags |= IGC_FLAG_TSN_QBV_ENABLED;
43 if (is_any_launchtime(adapter))
44 new_flags |= IGC_FLAG_TSN_QBV_ENABLED;
46 if (is_cbs_enabled(adapter))
47 new_flags |= IGC_FLAG_TSN_QAV_ENABLED;
52 void igc_tsn_adjust_txtime_offset(struct igc_adapter *adapter)
54 struct igc_hw *hw = &adapter->hw;
57 if (!is_any_launchtime(adapter))
60 switch (adapter->link_speed) {
62 txoffset = IGC_TXOFFSET_SPEED_10;
65 txoffset = IGC_TXOFFSET_SPEED_100;
68 txoffset = IGC_TXOFFSET_SPEED_1000;
71 txoffset = IGC_TXOFFSET_SPEED_2500;
78 wr32(IGC_GTXOFFSET, txoffset);
81 /* Returns the TSN specific registers to their default values after
82 * the adapter is reset.
84 static int igc_tsn_disable_offload(struct igc_adapter *adapter)
86 struct igc_hw *hw = &adapter->hw;
90 wr32(IGC_GTXOFFSET, 0);
91 wr32(IGC_TXPBS, I225_TXPBSIZE_DEFAULT);
92 wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_DEFAULT);
94 tqavctrl = rd32(IGC_TQAVCTRL);
95 tqavctrl &= ~(IGC_TQAVCTRL_TRANSMIT_MODE_TSN |
96 IGC_TQAVCTRL_ENHANCED_QAV | IGC_TQAVCTRL_FUTSCDDIS);
98 wr32(IGC_TQAVCTRL, tqavctrl);
100 for (i = 0; i < adapter->num_tx_queues; i++) {
101 wr32(IGC_TXQCTL(i), 0);
102 wr32(IGC_STQT(i), 0);
103 wr32(IGC_ENDQT(i), NSEC_PER_SEC);
106 wr32(IGC_QBVCYCLET_S, 0);
107 wr32(IGC_QBVCYCLET, NSEC_PER_SEC);
109 adapter->flags &= ~IGC_FLAG_TSN_QBV_ENABLED;
114 static int igc_tsn_enable_offload(struct igc_adapter *adapter)
116 struct igc_hw *hw = &adapter->hw;
117 bool tsn_mode_reconfig = false;
118 u32 tqavctrl, baset_l, baset_h;
119 u32 sec, nsec, cycle;
120 ktime_t base_time, systim;
124 wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_TSN);
125 wr32(IGC_TXPBS, IGC_TXPBSIZE_TSN);
127 for (i = 0; i < adapter->num_tx_queues; i++) {
128 struct igc_ring *ring = adapter->tx_ring[i];
133 wr32(IGC_STQT(i), ring->start_time);
134 wr32(IGC_ENDQT(i), ring->end_time);
136 txqctl |= IGC_TXQCTL_STRICT_CYCLE |
137 IGC_TXQCTL_STRICT_END;
139 if (ring->launchtime_enable)
140 txqctl |= IGC_TXQCTL_QUEUE_MODE_LAUNCHT;
142 /* Skip configuring CBS for Q2 and Q3 */
146 if (ring->cbs_enable) {
148 txqctl |= IGC_TXQCTL_QAV_SEL_CBS0;
150 txqctl |= IGC_TXQCTL_QAV_SEL_CBS1;
152 /* According to i225 datasheet section 7.5.2.7, we
153 * should set the 'idleSlope' field from TQAVCC
154 * register following the equation:
156 * value = link-speed 0x7736 * BW * 0.2
157 * ---------- * ----------------- (E1)
160 * Note that 'link-speed' is in Mbps.
162 * 'BW' is the percentage bandwidth out of full
163 * link speed which can be found with the
164 * following equation. Note that idleSlope here
165 * is the parameter from this function
169 * ----------------- (E2)
172 * That said, we can come up with a generic
173 * equation to calculate the value we should set
174 * it TQAVCC register by replacing 'BW' in E1 by E2.
175 * The resulting equation is:
177 * value = link-speed * 0x7736 * idleSlope * 0.2
178 * ------------------------------------- (E3)
179 * 100 * 2.5 * link-speed * 1000
181 * 'link-speed' is present in both sides of the
182 * fraction so it is canceled out. The final
183 * equation is the following:
185 * value = idleSlope * 61036
186 * ----------------- (E4)
189 * NOTE: For i225, given the above, we can see
190 * that idleslope is represented in
191 * 40.959433 kbps units by the value at
192 * the TQAVCC register (2.5Gbps / 61036),
193 * which reduces the granularity for
194 * idleslope increments.
196 * In i225 controller, the sendSlope and loCredit
197 * parameters from CBS are not configurable
198 * by software so we don't do any
199 * 'controller configuration' in respect to
202 cbs_value = DIV_ROUND_UP_ULL(ring->idleslope
203 * 61036ULL, 2500000);
205 tqavcc = rd32(IGC_TQAVCC(i));
206 tqavcc &= ~IGC_TQAVCC_IDLESLOPE_MASK;
207 tqavcc |= cbs_value | IGC_TQAVCC_KEEP_CREDITS;
208 wr32(IGC_TQAVCC(i), tqavcc);
211 0x80000000 + ring->hicredit * 0x7735);
213 /* Disable any CBS for the queue */
214 txqctl &= ~(IGC_TXQCTL_QAV_SEL_MASK);
216 /* Set idleSlope to zero. */
217 tqavcc = rd32(IGC_TQAVCC(i));
218 tqavcc &= ~(IGC_TQAVCC_IDLESLOPE_MASK |
219 IGC_TQAVCC_KEEP_CREDITS);
220 wr32(IGC_TQAVCC(i), tqavcc);
222 /* Set hiCredit to zero. */
223 wr32(IGC_TQAVHC(i), 0);
226 wr32(IGC_TXQCTL(i), txqctl);
229 tqavctrl = rd32(IGC_TQAVCTRL) & ~IGC_TQAVCTRL_FUTSCDDIS;
231 if (tqavctrl & IGC_TQAVCTRL_TRANSMIT_MODE_TSN)
232 tsn_mode_reconfig = true;
234 tqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV;
236 cycle = adapter->cycle_time;
237 base_time = adapter->base_time;
239 nsec = rd32(IGC_SYSTIML);
240 sec = rd32(IGC_SYSTIMH);
242 systim = ktime_set(sec, nsec);
243 if (ktime_compare(systim, base_time) > 0) {
244 s64 n = div64_s64(ktime_sub_ns(systim, base_time), cycle);
246 base_time = ktime_add_ns(base_time, (n + 1) * cycle);
248 /* Increase the counter if scheduling into the past while
249 * Gate Control List (GCL) is running.
251 if ((rd32(IGC_BASET_H) || rd32(IGC_BASET_L)) &&
252 (adapter->tc_setup_type == TC_SETUP_QDISC_TAPRIO) &&
254 adapter->qbv_config_change_errors++;
256 /* According to datasheet section 7.5.2.9.3.3, FutScdDis bit
257 * has to be configured before the cycle time and base time.
258 * Tx won't hang if there is a GCL is already running,
259 * so in this case we don't need to set FutScdDis.
261 if (igc_is_device_id_i226(hw) &&
262 !(rd32(IGC_BASET_H) || rd32(IGC_BASET_L)))
263 tqavctrl |= IGC_TQAVCTRL_FUTSCDDIS;
266 wr32(IGC_TQAVCTRL, tqavctrl);
268 wr32(IGC_QBVCYCLET_S, cycle);
269 wr32(IGC_QBVCYCLET, cycle);
271 baset_h = div_s64_rem(base_time, NSEC_PER_SEC, &baset_l);
272 wr32(IGC_BASET_H, baset_h);
274 /* In i226, Future base time is only supported when FutScdDis bit
275 * is enabled and only active for re-configuration.
276 * In this case, initialize the base time with zero to create
277 * "re-configuration" scenario then only set the desired base time.
279 if (tqavctrl & IGC_TQAVCTRL_FUTSCDDIS)
280 wr32(IGC_BASET_L, 0);
281 wr32(IGC_BASET_L, baset_l);
286 int igc_tsn_reset(struct igc_adapter *adapter)
288 unsigned int new_flags;
291 new_flags = igc_tsn_new_flags(adapter);
293 if (!(new_flags & IGC_FLAG_TSN_ANY_ENABLED))
294 return igc_tsn_disable_offload(adapter);
296 err = igc_tsn_enable_offload(adapter);
300 adapter->flags = new_flags;
305 int igc_tsn_offload_apply(struct igc_adapter *adapter)
307 struct igc_hw *hw = &adapter->hw;
309 if (netif_running(adapter->netdev) && igc_is_device_id_i225(hw)) {
310 schedule_work(&adapter->reset_task);
314 igc_tsn_reset(adapter);