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 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 txqctl |= IGC_TXQCTL_STRICT_CYCLE | 136 IGC_TXQCTL_STRICT_END; 137 138 if (ring->launchtime_enable) 139 txqctl |= IGC_TXQCTL_QUEUE_MODE_LAUNCHT; 140 141 /* Skip configuring CBS for Q2 and Q3 */ 142 if (i > 1) 143 goto skip_cbs; 144 145 if (ring->cbs_enable) { 146 if (i == 0) 147 txqctl |= IGC_TXQCTL_QAV_SEL_CBS0; 148 else 149 txqctl |= IGC_TXQCTL_QAV_SEL_CBS1; 150 151 /* According to i225 datasheet section 7.5.2.7, we 152 * should set the 'idleSlope' field from TQAVCC 153 * register following the equation: 154 * 155 * value = link-speed 0x7736 * BW * 0.2 156 * ---------- * ----------------- (E1) 157 * 100Mbps 2.5 158 * 159 * Note that 'link-speed' is in Mbps. 160 * 161 * 'BW' is the percentage bandwidth out of full 162 * link speed which can be found with the 163 * following equation. Note that idleSlope here 164 * is the parameter from this function 165 * which is in kbps. 166 * 167 * BW = idleSlope 168 * ----------------- (E2) 169 * link-speed * 1000 170 * 171 * That said, we can come up with a generic 172 * equation to calculate the value we should set 173 * it TQAVCC register by replacing 'BW' in E1 by E2. 174 * The resulting equation is: 175 * 176 * value = link-speed * 0x7736 * idleSlope * 0.2 177 * ------------------------------------- (E3) 178 * 100 * 2.5 * link-speed * 1000 179 * 180 * 'link-speed' is present in both sides of the 181 * fraction so it is canceled out. The final 182 * equation is the following: 183 * 184 * value = idleSlope * 61036 185 * ----------------- (E4) 186 * 2500000 187 * 188 * NOTE: For i225, given the above, we can see 189 * that idleslope is represented in 190 * 40.959433 kbps units by the value at 191 * the TQAVCC register (2.5Gbps / 61036), 192 * which reduces the granularity for 193 * idleslope increments. 194 * 195 * In i225 controller, the sendSlope and loCredit 196 * parameters from CBS are not configurable 197 * by software so we don't do any 198 * 'controller configuration' in respect to 199 * these parameters. 200 */ 201 cbs_value = DIV_ROUND_UP_ULL(ring->idleslope 202 * 61036ULL, 2500000); 203 204 tqavcc = rd32(IGC_TQAVCC(i)); 205 tqavcc &= ~IGC_TQAVCC_IDLESLOPE_MASK; 206 tqavcc |= cbs_value | IGC_TQAVCC_KEEP_CREDITS; 207 wr32(IGC_TQAVCC(i), tqavcc); 208 209 wr32(IGC_TQAVHC(i), 210 0x80000000 + ring->hicredit * 0x7735); 211 } else { 212 /* Disable any CBS for the queue */ 213 txqctl &= ~(IGC_TXQCTL_QAV_SEL_MASK); 214 215 /* Set idleSlope to zero. */ 216 tqavcc = rd32(IGC_TQAVCC(i)); 217 tqavcc &= ~(IGC_TQAVCC_IDLESLOPE_MASK | 218 IGC_TQAVCC_KEEP_CREDITS); 219 wr32(IGC_TQAVCC(i), tqavcc); 220 221 /* Set hiCredit to zero. */ 222 wr32(IGC_TQAVHC(i), 0); 223 } 224 skip_cbs: 225 wr32(IGC_TXQCTL(i), txqctl); 226 } 227 228 tqavctrl = rd32(IGC_TQAVCTRL) & ~IGC_TQAVCTRL_FUTSCDDIS; 229 tqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV; 230 231 cycle = adapter->cycle_time; 232 base_time = adapter->base_time; 233 234 nsec = rd32(IGC_SYSTIML); 235 sec = rd32(IGC_SYSTIMH); 236 237 systim = ktime_set(sec, nsec); 238 if (ktime_compare(systim, base_time) > 0) { 239 s64 n = div64_s64(ktime_sub_ns(systim, base_time), cycle); 240 241 base_time = ktime_add_ns(base_time, (n + 1) * cycle); 242 } else { 243 /* According to datasheet section 7.5.2.9.3.3, FutScdDis bit 244 * has to be configured before the cycle time and base time. 245 * Tx won't hang if there is a GCL is already running, 246 * so in this case we don't need to set FutScdDis. 247 */ 248 if (igc_is_device_id_i226(hw) && 249 !(rd32(IGC_BASET_H) || rd32(IGC_BASET_L))) 250 tqavctrl |= IGC_TQAVCTRL_FUTSCDDIS; 251 } 252 253 wr32(IGC_TQAVCTRL, tqavctrl); 254 255 wr32(IGC_QBVCYCLET_S, cycle); 256 wr32(IGC_QBVCYCLET, cycle); 257 258 baset_h = div_s64_rem(base_time, NSEC_PER_SEC, &baset_l); 259 wr32(IGC_BASET_H, baset_h); 260 261 /* In i226, Future base time is only supported when FutScdDis bit 262 * is enabled and only active for re-configuration. 263 * In this case, initialize the base time with zero to create 264 * "re-configuration" scenario then only set the desired base time. 265 */ 266 if (tqavctrl & IGC_TQAVCTRL_FUTSCDDIS) 267 wr32(IGC_BASET_L, 0); 268 wr32(IGC_BASET_L, baset_l); 269 270 return 0; 271 } 272 273 int igc_tsn_reset(struct igc_adapter *adapter) 274 { 275 unsigned int new_flags; 276 int err = 0; 277 278 new_flags = igc_tsn_new_flags(adapter); 279 280 if (!(new_flags & IGC_FLAG_TSN_ANY_ENABLED)) 281 return igc_tsn_disable_offload(adapter); 282 283 err = igc_tsn_enable_offload(adapter); 284 if (err < 0) 285 return err; 286 287 adapter->flags = new_flags; 288 289 return err; 290 } 291 292 int igc_tsn_offload_apply(struct igc_adapter *adapter) 293 { 294 struct igc_hw *hw = &adapter->hw; 295 296 if (netif_running(adapter->netdev) && igc_is_device_id_i225(hw)) { 297 schedule_work(&adapter->reset_task); 298 return 0; 299 } 300 301 igc_tsn_reset(adapter); 302 303 return 0; 304 } 305