Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright (c)  2019 Intel Corporation */
0003 
0004 #include "igc.h"
0005 #include "igc_tsn.h"
0006 
0007 static bool is_any_launchtime(struct igc_adapter *adapter)
0008 {
0009     int i;
0010 
0011     for (i = 0; i < adapter->num_tx_queues; i++) {
0012         struct igc_ring *ring = adapter->tx_ring[i];
0013 
0014         if (ring->launchtime_enable)
0015             return true;
0016     }
0017 
0018     return false;
0019 }
0020 
0021 static bool is_cbs_enabled(struct igc_adapter *adapter)
0022 {
0023     int i;
0024 
0025     for (i = 0; i < adapter->num_tx_queues; i++) {
0026         struct igc_ring *ring = adapter->tx_ring[i];
0027 
0028         if (ring->cbs_enable)
0029             return true;
0030     }
0031 
0032     return false;
0033 }
0034 
0035 static unsigned int igc_tsn_new_flags(struct igc_adapter *adapter)
0036 {
0037     unsigned int new_flags = adapter->flags & ~IGC_FLAG_TSN_ANY_ENABLED;
0038 
0039     if (adapter->base_time)
0040         new_flags |= IGC_FLAG_TSN_QBV_ENABLED;
0041 
0042     if (is_any_launchtime(adapter))
0043         new_flags |= IGC_FLAG_TSN_QBV_ENABLED;
0044 
0045     if (is_cbs_enabled(adapter))
0046         new_flags |= IGC_FLAG_TSN_QAV_ENABLED;
0047 
0048     return new_flags;
0049 }
0050 
0051 /* Returns the TSN specific registers to their default values after
0052  * the adapter is reset.
0053  */
0054 static int igc_tsn_disable_offload(struct igc_adapter *adapter)
0055 {
0056     struct igc_hw *hw = &adapter->hw;
0057     u32 tqavctrl;
0058     int i;
0059 
0060     wr32(IGC_TXPBS, I225_TXPBSIZE_DEFAULT);
0061     wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_DEFAULT);
0062 
0063     tqavctrl = rd32(IGC_TQAVCTRL);
0064     tqavctrl &= ~(IGC_TQAVCTRL_TRANSMIT_MODE_TSN |
0065               IGC_TQAVCTRL_ENHANCED_QAV);
0066     wr32(IGC_TQAVCTRL, tqavctrl);
0067 
0068     for (i = 0; i < adapter->num_tx_queues; i++) {
0069         wr32(IGC_TXQCTL(i), 0);
0070         wr32(IGC_STQT(i), 0);
0071         wr32(IGC_ENDQT(i), NSEC_PER_SEC);
0072     }
0073 
0074     wr32(IGC_QBVCYCLET_S, 0);
0075     wr32(IGC_QBVCYCLET, NSEC_PER_SEC);
0076 
0077     adapter->flags &= ~IGC_FLAG_TSN_QBV_ENABLED;
0078 
0079     return 0;
0080 }
0081 
0082 static int igc_tsn_enable_offload(struct igc_adapter *adapter)
0083 {
0084     struct igc_hw *hw = &adapter->hw;
0085     u32 tqavctrl, baset_l, baset_h;
0086     u32 sec, nsec, cycle;
0087     ktime_t base_time, systim;
0088     int i;
0089 
0090     cycle = adapter->cycle_time;
0091     base_time = adapter->base_time;
0092 
0093     wr32(IGC_TSAUXC, 0);
0094     wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_TSN);
0095     wr32(IGC_TXPBS, IGC_TXPBSIZE_TSN);
0096 
0097     tqavctrl = rd32(IGC_TQAVCTRL);
0098     tqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV;
0099     wr32(IGC_TQAVCTRL, tqavctrl);
0100 
0101     wr32(IGC_QBVCYCLET_S, cycle);
0102     wr32(IGC_QBVCYCLET, cycle);
0103 
0104     for (i = 0; i < adapter->num_tx_queues; i++) {
0105         struct igc_ring *ring = adapter->tx_ring[i];
0106         u32 txqctl = 0;
0107         u16 cbs_value;
0108         u32 tqavcc;
0109 
0110         wr32(IGC_STQT(i), ring->start_time);
0111         wr32(IGC_ENDQT(i), ring->end_time);
0112 
0113         if (adapter->base_time) {
0114             /* If we have a base_time we are in "taprio"
0115              * mode and we need to be strict about the
0116              * cycles: only transmit a packet if it can be
0117              * completed during that cycle.
0118              */
0119             txqctl |= IGC_TXQCTL_STRICT_CYCLE |
0120                 IGC_TXQCTL_STRICT_END;
0121         }
0122 
0123         if (ring->launchtime_enable)
0124             txqctl |= IGC_TXQCTL_QUEUE_MODE_LAUNCHT;
0125 
0126         /* Skip configuring CBS for Q2 and Q3 */
0127         if (i > 1)
0128             goto skip_cbs;
0129 
0130         if (ring->cbs_enable) {
0131             if (i == 0)
0132                 txqctl |= IGC_TXQCTL_QAV_SEL_CBS0;
0133             else
0134                 txqctl |= IGC_TXQCTL_QAV_SEL_CBS1;
0135 
0136             /* According to i225 datasheet section 7.5.2.7, we
0137              * should set the 'idleSlope' field from TQAVCC
0138              * register following the equation:
0139              *
0140              * value = link-speed   0x7736 * BW * 0.2
0141              *         ---------- *  -----------------         (E1)
0142              *          100Mbps            2.5
0143              *
0144              * Note that 'link-speed' is in Mbps.
0145              *
0146              * 'BW' is the percentage bandwidth out of full
0147              * link speed which can be found with the
0148              * following equation. Note that idleSlope here
0149              * is the parameter from this function
0150              * which is in kbps.
0151              *
0152              *     BW =     idleSlope
0153              *          -----------------                      (E2)
0154              *          link-speed * 1000
0155              *
0156              * That said, we can come up with a generic
0157              * equation to calculate the value we should set
0158              * it TQAVCC register by replacing 'BW' in E1 by E2.
0159              * The resulting equation is:
0160              *
0161              * value = link-speed * 0x7736 * idleSlope * 0.2
0162              *         -------------------------------------   (E3)
0163              *             100 * 2.5 * link-speed * 1000
0164              *
0165              * 'link-speed' is present in both sides of the
0166              * fraction so it is canceled out. The final
0167              * equation is the following:
0168              *
0169              *     value = idleSlope * 61036
0170              *             -----------------                   (E4)
0171              *                  2500000
0172              *
0173              * NOTE: For i225, given the above, we can see
0174              *       that idleslope is represented in
0175              *       40.959433 kbps units by the value at
0176              *       the TQAVCC register (2.5Gbps / 61036),
0177              *       which reduces the granularity for
0178              *       idleslope increments.
0179              *
0180              * In i225 controller, the sendSlope and loCredit
0181              * parameters from CBS are not configurable
0182              * by software so we don't do any
0183              * 'controller configuration' in respect to
0184              * these parameters.
0185              */
0186             cbs_value = DIV_ROUND_UP_ULL(ring->idleslope
0187                              * 61036ULL, 2500000);
0188 
0189             tqavcc = rd32(IGC_TQAVCC(i));
0190             tqavcc &= ~IGC_TQAVCC_IDLESLOPE_MASK;
0191             tqavcc |= cbs_value | IGC_TQAVCC_KEEP_CREDITS;
0192             wr32(IGC_TQAVCC(i), tqavcc);
0193 
0194             wr32(IGC_TQAVHC(i),
0195                  0x80000000 + ring->hicredit * 0x7735);
0196         } else {
0197             /* Disable any CBS for the queue */
0198             txqctl &= ~(IGC_TXQCTL_QAV_SEL_MASK);
0199 
0200             /* Set idleSlope to zero. */
0201             tqavcc = rd32(IGC_TQAVCC(i));
0202             tqavcc &= ~(IGC_TQAVCC_IDLESLOPE_MASK |
0203                     IGC_TQAVCC_KEEP_CREDITS);
0204             wr32(IGC_TQAVCC(i), tqavcc);
0205 
0206             /* Set hiCredit to zero. */
0207             wr32(IGC_TQAVHC(i), 0);
0208         }
0209 skip_cbs:
0210         wr32(IGC_TXQCTL(i), txqctl);
0211     }
0212 
0213     nsec = rd32(IGC_SYSTIML);
0214     sec = rd32(IGC_SYSTIMH);
0215 
0216     systim = ktime_set(sec, nsec);
0217 
0218     if (ktime_compare(systim, base_time) > 0) {
0219         s64 n;
0220 
0221         n = div64_s64(ktime_sub_ns(systim, base_time), cycle);
0222         base_time = ktime_add_ns(base_time, (n + 1) * cycle);
0223     }
0224 
0225     baset_h = div_s64_rem(base_time, NSEC_PER_SEC, &baset_l);
0226 
0227     wr32(IGC_BASET_H, baset_h);
0228     wr32(IGC_BASET_L, baset_l);
0229 
0230     return 0;
0231 }
0232 
0233 int igc_tsn_reset(struct igc_adapter *adapter)
0234 {
0235     unsigned int new_flags;
0236     int err = 0;
0237 
0238     new_flags = igc_tsn_new_flags(adapter);
0239 
0240     if (!(new_flags & IGC_FLAG_TSN_ANY_ENABLED))
0241         return igc_tsn_disable_offload(adapter);
0242 
0243     err = igc_tsn_enable_offload(adapter);
0244     if (err < 0)
0245         return err;
0246 
0247     adapter->flags = new_flags;
0248 
0249     return err;
0250 }
0251 
0252 int igc_tsn_offload_apply(struct igc_adapter *adapter)
0253 {
0254     int err;
0255 
0256     if (netif_running(adapter->netdev)) {
0257         schedule_work(&adapter->reset_task);
0258         return 0;
0259     }
0260 
0261     err = igc_tsn_enable_offload(adapter);
0262     if (err < 0)
0263         return err;
0264 
0265     adapter->flags = igc_tsn_new_flags(adapter);
0266     return 0;
0267 }