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->qbv_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 bool tsn_mode_reconfig = false; 118 u32 tqavctrl, baset_l, baset_h; 119 u32 sec, nsec, cycle; 120 ktime_t base_time, systim; 121 int i; 122 123 wr32(IGC_TSAUXC, 0); 124 wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_TSN); 125 wr32(IGC_TXPBS, IGC_TXPBSIZE_TSN); 126 127 for (i = 0; i < adapter->num_tx_queues; i++) { 128 struct igc_ring *ring = adapter->tx_ring[i]; 129 u32 txqctl = 0; 130 u16 cbs_value; 131 u32 tqavcc; 132 133 wr32(IGC_STQT(i), ring->start_time); 134 wr32(IGC_ENDQT(i), ring->end_time); 135 136 txqctl |= IGC_TXQCTL_STRICT_CYCLE | 137 IGC_TXQCTL_STRICT_END; 138 139 if (ring->launchtime_enable) 140 txqctl |= IGC_TXQCTL_QUEUE_MODE_LAUNCHT; 141 142 /* Skip configuring CBS for Q2 and Q3 */ 143 if (i > 1) 144 goto skip_cbs; 145 146 if (ring->cbs_enable) { 147 if (i == 0) 148 txqctl |= IGC_TXQCTL_QAV_SEL_CBS0; 149 else 150 txqctl |= IGC_TXQCTL_QAV_SEL_CBS1; 151 152 /* According to i225 datasheet section 7.5.2.7, we 153 * should set the 'idleSlope' field from TQAVCC 154 * register following the equation: 155 * 156 * value = link-speed 0x7736 * BW * 0.2 157 * ---------- * ----------------- (E1) 158 * 100Mbps 2.5 159 * 160 * Note that 'link-speed' is in Mbps. 161 * 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 166 * which is in kbps. 167 * 168 * BW = idleSlope 169 * ----------------- (E2) 170 * link-speed * 1000 171 * 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: 176 * 177 * value = link-speed * 0x7736 * idleSlope * 0.2 178 * ------------------------------------- (E3) 179 * 100 * 2.5 * link-speed * 1000 180 * 181 * 'link-speed' is present in both sides of the 182 * fraction so it is canceled out. The final 183 * equation is the following: 184 * 185 * value = idleSlope * 61036 186 * ----------------- (E4) 187 * 2500000 188 * 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. 195 * 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 200 * these parameters. 201 */ 202 cbs_value = DIV_ROUND_UP_ULL(ring->idleslope 203 * 61036ULL, 2500000); 204 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); 209 210 wr32(IGC_TQAVHC(i), 211 0x80000000 + ring->hicredit * 0x7735); 212 } else { 213 /* Disable any CBS for the queue */ 214 txqctl &= ~(IGC_TXQCTL_QAV_SEL_MASK); 215 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); 221 222 /* Set hiCredit to zero. */ 223 wr32(IGC_TQAVHC(i), 0); 224 } 225 skip_cbs: 226 wr32(IGC_TXQCTL(i), txqctl); 227 } 228 229 tqavctrl = rd32(IGC_TQAVCTRL) & ~IGC_TQAVCTRL_FUTSCDDIS; 230 231 if (tqavctrl & IGC_TQAVCTRL_TRANSMIT_MODE_TSN) 232 tsn_mode_reconfig = true; 233 234 tqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV; 235 236 cycle = adapter->cycle_time; 237 base_time = adapter->base_time; 238 239 nsec = rd32(IGC_SYSTIML); 240 sec = rd32(IGC_SYSTIMH); 241 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); 245 246 base_time = ktime_add_ns(base_time, (n + 1) * cycle); 247 248 /* Increase the counter if scheduling into the past while 249 * Gate Control List (GCL) is running. 250 */ 251 if ((rd32(IGC_BASET_H) || rd32(IGC_BASET_L)) && 252 tsn_mode_reconfig) 253 adapter->qbv_config_change_errors++; 254 } else { 255 /* According to datasheet section 7.5.2.9.3.3, FutScdDis bit 256 * has to be configured before the cycle time and base time. 257 * Tx won't hang if there is a GCL is already running, 258 * so in this case we don't need to set FutScdDis. 259 */ 260 if (igc_is_device_id_i226(hw) && 261 !(rd32(IGC_BASET_H) || rd32(IGC_BASET_L))) 262 tqavctrl |= IGC_TQAVCTRL_FUTSCDDIS; 263 } 264 265 wr32(IGC_TQAVCTRL, tqavctrl); 266 267 wr32(IGC_QBVCYCLET_S, cycle); 268 wr32(IGC_QBVCYCLET, cycle); 269 270 baset_h = div_s64_rem(base_time, NSEC_PER_SEC, &baset_l); 271 wr32(IGC_BASET_H, baset_h); 272 273 /* In i226, Future base time is only supported when FutScdDis bit 274 * is enabled and only active for re-configuration. 275 * In this case, initialize the base time with zero to create 276 * "re-configuration" scenario then only set the desired base time. 277 */ 278 if (tqavctrl & IGC_TQAVCTRL_FUTSCDDIS) 279 wr32(IGC_BASET_L, 0); 280 wr32(IGC_BASET_L, baset_l); 281 282 return 0; 283 } 284 285 int igc_tsn_reset(struct igc_adapter *adapter) 286 { 287 unsigned int new_flags; 288 int err = 0; 289 290 new_flags = igc_tsn_new_flags(adapter); 291 292 if (!(new_flags & IGC_FLAG_TSN_ANY_ENABLED)) 293 return igc_tsn_disable_offload(adapter); 294 295 err = igc_tsn_enable_offload(adapter); 296 if (err < 0) 297 return err; 298 299 adapter->flags = new_flags; 300 301 return err; 302 } 303 304 int igc_tsn_offload_apply(struct igc_adapter *adapter) 305 { 306 struct igc_hw *hw = &adapter->hw; 307 308 if (netif_running(adapter->netdev) && igc_is_device_id_i225(hw)) { 309 schedule_work(&adapter->reset_task); 310 return 0; 311 } 312 313 igc_tsn_reset(adapter); 314 315 return 0; 316 } 317