1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2019 Intel Corporation */ 3 4 #include "igc.h" 5 #include "igc_hw.h" 6 #include "igc_tsn.h" 7 8 static bool is_any_launchtime(struct igc_adapter *adapter) 9 { 10 int i; 11 12 for (i = 0; i < adapter->num_tx_queues; i++) { 13 struct igc_ring *ring = adapter->tx_ring[i]; 14 15 if (ring->launchtime_enable) 16 return true; 17 } 18 19 return false; 20 } 21 22 static bool is_cbs_enabled(struct igc_adapter *adapter) 23 { 24 int i; 25 26 for (i = 0; i < adapter->num_tx_queues; i++) { 27 struct igc_ring *ring = adapter->tx_ring[i]; 28 29 if (ring->cbs_enable) 30 return true; 31 } 32 33 return false; 34 } 35 36 static unsigned int igc_tsn_new_flags(struct igc_adapter *adapter) 37 { 38 unsigned int new_flags = adapter->flags & ~IGC_FLAG_TSN_ANY_ENABLED; 39 40 if (adapter->taprio_offload_enable) 41 new_flags |= IGC_FLAG_TSN_QBV_ENABLED; 42 43 if (is_any_launchtime(adapter)) 44 new_flags |= IGC_FLAG_TSN_QBV_ENABLED; 45 46 if (is_cbs_enabled(adapter)) 47 new_flags |= IGC_FLAG_TSN_QAV_ENABLED; 48 49 return new_flags; 50 } 51 52 void igc_tsn_adjust_txtime_offset(struct igc_adapter *adapter) 53 { 54 struct igc_hw *hw = &adapter->hw; 55 u16 txoffset; 56 57 if (!is_any_launchtime(adapter)) 58 return; 59 60 switch (adapter->link_speed) { 61 case SPEED_10: 62 txoffset = IGC_TXOFFSET_SPEED_10; 63 break; 64 case SPEED_100: 65 txoffset = IGC_TXOFFSET_SPEED_100; 66 break; 67 case SPEED_1000: 68 txoffset = IGC_TXOFFSET_SPEED_1000; 69 break; 70 case SPEED_2500: 71 txoffset = IGC_TXOFFSET_SPEED_2500; 72 break; 73 default: 74 txoffset = 0; 75 break; 76 } 77 78 wr32(IGC_GTXOFFSET, txoffset); 79 } 80 81 /* Returns the TSN specific registers to their default values after 82 * the adapter is reset. 83 */ 84 static int igc_tsn_disable_offload(struct igc_adapter *adapter) 85 { 86 struct igc_hw *hw = &adapter->hw; 87 u32 tqavctrl; 88 int i; 89 90 wr32(IGC_GTXOFFSET, 0); 91 wr32(IGC_TXPBS, I225_TXPBSIZE_DEFAULT); 92 wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_DEFAULT); 93 94 tqavctrl = rd32(IGC_TQAVCTRL); 95 tqavctrl &= ~(IGC_TQAVCTRL_TRANSMIT_MODE_TSN | 96 IGC_TQAVCTRL_ENHANCED_QAV | IGC_TQAVCTRL_FUTSCDDIS); 97 98 wr32(IGC_TQAVCTRL, tqavctrl); 99 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); 104 } 105 106 wr32(IGC_QBVCYCLET_S, 0); 107 wr32(IGC_QBVCYCLET, NSEC_PER_SEC); 108 109 adapter->flags &= ~IGC_FLAG_TSN_QBV_ENABLED; 110 111 return 0; 112 } 113 114 static int igc_tsn_enable_offload(struct igc_adapter *adapter) 115 { 116 struct igc_hw *hw = &adapter->hw; 117 u32 tqavctrl, baset_l, baset_h; 118 u32 sec, nsec, cycle; 119 ktime_t base_time, systim; 120 int i; 121 122 wr32(IGC_TSAUXC, 0); 123 wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_TSN); 124 wr32(IGC_TXPBS, IGC_TXPBSIZE_TSN); 125 126 for (i = 0; i < adapter->num_tx_queues; i++) { 127 struct igc_ring *ring = adapter->tx_ring[i]; 128 u32 txqctl = 0; 129 u16 cbs_value; 130 u32 tqavcc; 131 132 wr32(IGC_STQT(i), ring->start_time); 133 wr32(IGC_ENDQT(i), ring->end_time); 134 135 if (adapter->taprio_offload_enable) { 136 /* If taprio_offload_enable is set we are in "taprio" 137 * mode and we need to be strict about the 138 * cycles: only transmit a packet if it can be 139 * completed during that cycle. 140 * 141 * If taprio_offload_enable is NOT true when 142 * enabling TSN offload, the cycle should have 143 * no external effects, but is only used internally 144 * to adapt the base time register after a second 145 * has passed. 146 * 147 * Enabling strict mode in this case would 148 * unnecessarily prevent the transmission of 149 * certain packets (i.e. at the boundary of a 150 * second) and thus interfere with the launchtime 151 * feature that promises transmission at a 152 * certain point in time. 153 */ 154 txqctl |= IGC_TXQCTL_STRICT_CYCLE | 155 IGC_TXQCTL_STRICT_END; 156 } 157 158 if (ring->launchtime_enable) 159 txqctl |= IGC_TXQCTL_QUEUE_MODE_LAUNCHT; 160 161 /* Skip configuring CBS for Q2 and Q3 */ 162 if (i > 1) 163 goto skip_cbs; 164 165 if (ring->cbs_enable) { 166 if (i == 0) 167 txqctl |= IGC_TXQCTL_QAV_SEL_CBS0; 168 else 169 txqctl |= IGC_TXQCTL_QAV_SEL_CBS1; 170 171 /* According to i225 datasheet section 7.5.2.7, we 172 * should set the 'idleSlope' field from TQAVCC 173 * register following the equation: 174 * 175 * value = link-speed 0x7736 * BW * 0.2 176 * ---------- * ----------------- (E1) 177 * 100Mbps 2.5 178 * 179 * Note that 'link-speed' is in Mbps. 180 * 181 * 'BW' is the percentage bandwidth out of full 182 * link speed which can be found with the 183 * following equation. Note that idleSlope here 184 * is the parameter from this function 185 * which is in kbps. 186 * 187 * BW = idleSlope 188 * ----------------- (E2) 189 * link-speed * 1000 190 * 191 * That said, we can come up with a generic 192 * equation to calculate the value we should set 193 * it TQAVCC register by replacing 'BW' in E1 by E2. 194 * The resulting equation is: 195 * 196 * value = link-speed * 0x7736 * idleSlope * 0.2 197 * ------------------------------------- (E3) 198 * 100 * 2.5 * link-speed * 1000 199 * 200 * 'link-speed' is present in both sides of the 201 * fraction so it is canceled out. The final 202 * equation is the following: 203 * 204 * value = idleSlope * 61036 205 * ----------------- (E4) 206 * 2500000 207 * 208 * NOTE: For i225, given the above, we can see 209 * that idleslope is represented in 210 * 40.959433 kbps units by the value at 211 * the TQAVCC register (2.5Gbps / 61036), 212 * which reduces the granularity for 213 * idleslope increments. 214 * 215 * In i225 controller, the sendSlope and loCredit 216 * parameters from CBS are not configurable 217 * by software so we don't do any 218 * 'controller configuration' in respect to 219 * these parameters. 220 */ 221 cbs_value = DIV_ROUND_UP_ULL(ring->idleslope 222 * 61036ULL, 2500000); 223 224 tqavcc = rd32(IGC_TQAVCC(i)); 225 tqavcc &= ~IGC_TQAVCC_IDLESLOPE_MASK; 226 tqavcc |= cbs_value | IGC_TQAVCC_KEEP_CREDITS; 227 wr32(IGC_TQAVCC(i), tqavcc); 228 229 wr32(IGC_TQAVHC(i), 230 0x80000000 + ring->hicredit * 0x7736); 231 } else { 232 /* Disable any CBS for the queue */ 233 txqctl &= ~(IGC_TXQCTL_QAV_SEL_MASK); 234 235 /* Set idleSlope to zero. */ 236 tqavcc = rd32(IGC_TQAVCC(i)); 237 tqavcc &= ~(IGC_TQAVCC_IDLESLOPE_MASK | 238 IGC_TQAVCC_KEEP_CREDITS); 239 wr32(IGC_TQAVCC(i), tqavcc); 240 241 /* Set hiCredit to zero. */ 242 wr32(IGC_TQAVHC(i), 0); 243 } 244 skip_cbs: 245 wr32(IGC_TXQCTL(i), txqctl); 246 } 247 248 tqavctrl = rd32(IGC_TQAVCTRL) & ~IGC_TQAVCTRL_FUTSCDDIS; 249 250 tqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV; 251 252 adapter->qbv_count++; 253 254 cycle = adapter->cycle_time; 255 base_time = adapter->base_time; 256 257 nsec = rd32(IGC_SYSTIML); 258 sec = rd32(IGC_SYSTIMH); 259 260 systim = ktime_set(sec, nsec); 261 if (ktime_compare(systim, base_time) > 0) { 262 s64 n = div64_s64(ktime_sub_ns(systim, base_time), cycle); 263 264 base_time = ktime_add_ns(base_time, (n + 1) * cycle); 265 266 /* Increase the counter if scheduling into the past while 267 * Gate Control List (GCL) is running. 268 */ 269 if ((rd32(IGC_BASET_H) || rd32(IGC_BASET_L)) && 270 (adapter->tc_setup_type == TC_SETUP_QDISC_TAPRIO) && 271 (adapter->qbv_count > 1)) 272 adapter->qbv_config_change_errors++; 273 } else { 274 if (igc_is_device_id_i226(hw)) { 275 ktime_t adjust_time, expires_time; 276 277 /* According to datasheet section 7.5.2.9.3.3, FutScdDis bit 278 * has to be configured before the cycle time and base time. 279 * Tx won't hang if a GCL is already running, 280 * so in this case we don't need to set FutScdDis. 281 */ 282 if (!(rd32(IGC_BASET_H) || rd32(IGC_BASET_L))) 283 tqavctrl |= IGC_TQAVCTRL_FUTSCDDIS; 284 285 nsec = rd32(IGC_SYSTIML); 286 sec = rd32(IGC_SYSTIMH); 287 systim = ktime_set(sec, nsec); 288 289 adjust_time = adapter->base_time; 290 expires_time = ktime_sub_ns(adjust_time, systim); 291 hrtimer_start(&adapter->hrtimer, expires_time, HRTIMER_MODE_REL); 292 } 293 } 294 295 wr32(IGC_TQAVCTRL, tqavctrl); 296 297 wr32(IGC_QBVCYCLET_S, cycle); 298 wr32(IGC_QBVCYCLET, cycle); 299 300 baset_h = div_s64_rem(base_time, NSEC_PER_SEC, &baset_l); 301 wr32(IGC_BASET_H, baset_h); 302 303 /* In i226, Future base time is only supported when FutScdDis bit 304 * is enabled and only active for re-configuration. 305 * In this case, initialize the base time with zero to create 306 * "re-configuration" scenario then only set the desired base time. 307 */ 308 if (tqavctrl & IGC_TQAVCTRL_FUTSCDDIS) 309 wr32(IGC_BASET_L, 0); 310 wr32(IGC_BASET_L, baset_l); 311 312 return 0; 313 } 314 315 int igc_tsn_reset(struct igc_adapter *adapter) 316 { 317 unsigned int new_flags; 318 int err = 0; 319 320 new_flags = igc_tsn_new_flags(adapter); 321 322 if (!(new_flags & IGC_FLAG_TSN_ANY_ENABLED)) 323 return igc_tsn_disable_offload(adapter); 324 325 err = igc_tsn_enable_offload(adapter); 326 if (err < 0) 327 return err; 328 329 adapter->flags = new_flags; 330 331 return err; 332 } 333 334 int igc_tsn_offload_apply(struct igc_adapter *adapter) 335 { 336 struct igc_hw *hw = &adapter->hw; 337 338 /* Per I225/6 HW Design Section 7.5.2.1, transmit mode 339 * cannot be changed dynamically. Require reset the adapter. 340 */ 341 if (netif_running(adapter->netdev) && 342 (igc_is_device_id_i225(hw) || !adapter->qbv_count)) { 343 schedule_work(&adapter->reset_task); 344 return 0; 345 } 346 347 igc_tsn_reset(adapter); 348 349 return 0; 350 } 351