1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2019 Intel Corporation */
7 static bool is_any_launchtime(struct igc_adapter *adapter)
11 for (i = 0; i < adapter->num_tx_queues; i++) {
12 struct igc_ring *ring = adapter->tx_ring[i];
14 if (ring->launchtime_enable)
21 static bool is_cbs_enabled(struct igc_adapter *adapter)
25 for (i = 0; i < adapter->num_tx_queues; i++) {
26 struct igc_ring *ring = adapter->tx_ring[i];
35 static unsigned int igc_tsn_new_flags(struct igc_adapter *adapter)
37 unsigned int new_flags = adapter->flags & ~IGC_FLAG_TSN_ANY_ENABLED;
39 if (adapter->base_time)
40 new_flags |= IGC_FLAG_TSN_QBV_ENABLED;
42 if (is_any_launchtime(adapter))
43 new_flags |= IGC_FLAG_TSN_QBV_ENABLED;
45 if (is_cbs_enabled(adapter))
46 new_flags |= IGC_FLAG_TSN_QAV_ENABLED;
51 /* Returns the TSN specific registers to their default values after
52 * the adapter is reset.
54 static int igc_tsn_disable_offload(struct igc_adapter *adapter)
56 struct igc_hw *hw = &adapter->hw;
60 wr32(IGC_TXPBS, I225_TXPBSIZE_DEFAULT);
61 wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_DEFAULT);
63 tqavctrl = rd32(IGC_TQAVCTRL);
64 tqavctrl &= ~(IGC_TQAVCTRL_TRANSMIT_MODE_TSN |
65 IGC_TQAVCTRL_ENHANCED_QAV);
66 wr32(IGC_TQAVCTRL, tqavctrl);
68 for (i = 0; i < adapter->num_tx_queues; i++) {
69 wr32(IGC_TXQCTL(i), 0);
71 wr32(IGC_ENDQT(i), NSEC_PER_SEC);
74 wr32(IGC_QBVCYCLET_S, 0);
75 wr32(IGC_QBVCYCLET, NSEC_PER_SEC);
77 adapter->flags &= ~IGC_FLAG_TSN_QBV_ENABLED;
82 static int igc_tsn_enable_offload(struct igc_adapter *adapter)
84 struct igc_hw *hw = &adapter->hw;
85 u32 tqavctrl, baset_l, baset_h;
87 ktime_t base_time, systim;
90 cycle = adapter->cycle_time;
91 base_time = adapter->base_time;
94 wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_TSN);
95 wr32(IGC_TXPBS, IGC_TXPBSIZE_TSN);
97 tqavctrl = rd32(IGC_TQAVCTRL);
98 tqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV;
99 wr32(IGC_TQAVCTRL, tqavctrl);
101 wr32(IGC_QBVCYCLET_S, cycle);
102 wr32(IGC_QBVCYCLET, cycle);
104 for (i = 0; i < adapter->num_tx_queues; i++) {
105 struct igc_ring *ring = adapter->tx_ring[i];
110 wr32(IGC_STQT(i), ring->start_time);
111 wr32(IGC_ENDQT(i), ring->end_time);
113 if (adapter->base_time) {
114 /* If we have a base_time we are in "taprio"
115 * mode and we need to be strict about the
116 * cycles: only transmit a packet if it can be
117 * completed during that cycle.
119 txqctl |= IGC_TXQCTL_STRICT_CYCLE |
120 IGC_TXQCTL_STRICT_END;
123 if (ring->launchtime_enable)
124 txqctl |= IGC_TXQCTL_QUEUE_MODE_LAUNCHT;
126 /* Skip configuring CBS for Q2 and Q3 */
130 if (ring->cbs_enable) {
132 txqctl |= IGC_TXQCTL_QAV_SEL_CBS0;
134 txqctl |= IGC_TXQCTL_QAV_SEL_CBS1;
136 /* According to i225 datasheet section 7.5.2.7, we
137 * should set the 'idleSlope' field from TQAVCC
138 * register following the equation:
140 * value = link-speed 0x7736 * BW * 0.2
141 * ---------- * ----------------- (E1)
144 * Note that 'link-speed' is in Mbps.
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
153 * ----------------- (E2)
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:
161 * value = link-speed * 0x7736 * idleSlope * 0.2
162 * ------------------------------------- (E3)
163 * 100 * 2.5 * link-speed * 1000
165 * 'link-speed' is present in both sides of the
166 * fraction so it is canceled out. The final
167 * equation is the following:
169 * value = idleSlope * 61036
170 * ----------------- (E4)
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.
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
186 cbs_value = DIV_ROUND_UP_ULL(ring->idleslope
187 * 61036ULL, 2500000);
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);
195 0x80000000 + ring->hicredit * 0x7735);
197 /* Disable any CBS for the queue */
198 txqctl &= ~(IGC_TXQCTL_QAV_SEL_MASK);
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);
206 /* Set hiCredit to zero. */
207 wr32(IGC_TQAVHC(i), 0);
210 wr32(IGC_TXQCTL(i), txqctl);
213 nsec = rd32(IGC_SYSTIML);
214 sec = rd32(IGC_SYSTIMH);
216 systim = ktime_set(sec, nsec);
218 if (ktime_compare(systim, base_time) > 0) {
221 n = div64_s64(ktime_sub_ns(systim, base_time), cycle);
222 base_time = ktime_add_ns(base_time, (n + 1) * cycle);
225 baset_h = div_s64_rem(base_time, NSEC_PER_SEC, &baset_l);
227 wr32(IGC_BASET_H, baset_h);
228 wr32(IGC_BASET_L, baset_l);
233 int igc_tsn_reset(struct igc_adapter *adapter)
235 unsigned int new_flags;
238 new_flags = igc_tsn_new_flags(adapter);
240 if (!(new_flags & IGC_FLAG_TSN_ANY_ENABLED))
241 return igc_tsn_disable_offload(adapter);
243 err = igc_tsn_enable_offload(adapter);
247 adapter->flags = new_flags;
252 int igc_tsn_offload_apply(struct igc_adapter *adapter)
256 if (netif_running(adapter->netdev)) {
257 schedule_work(&adapter->reset_task);
261 err = igc_tsn_enable_offload(adapter);
265 adapter->flags = igc_tsn_new_flags(adapter);