@@ -711,7 +711,6 @@ static void igc_configure_tx_ring(struct igc_adapter *adapter,
711711 /* disable the queue */
712712 wr32 (IGC_TXDCTL (reg_idx ), 0 );
713713 wrfl ();
714- mdelay (10 );
715714
716715 wr32 (IGC_TDLEN (reg_idx ),
717716 ring -> count * sizeof (union igc_adv_tx_desc ));
@@ -1573,16 +1572,12 @@ static netdev_tx_t igc_xmit_frame_ring(struct sk_buff *skb,
15731572 first -> bytecount = skb -> len ;
15741573 first -> gso_segs = 1 ;
15751574
1576- if (tx_ring -> max_sdu > 0 ) {
1577- u32 max_sdu = 0 ;
1578-
1579- max_sdu = tx_ring -> max_sdu +
1580- (skb_vlan_tagged (first -> skb ) ? VLAN_HLEN : 0 );
1575+ if (adapter -> qbv_transition || tx_ring -> oper_gate_closed )
1576+ goto out_drop ;
15811577
1582- if (first -> bytecount > max_sdu ) {
1583- adapter -> stats .txdrop ++ ;
1584- goto out_drop ;
1585- }
1578+ if (tx_ring -> max_sdu > 0 && first -> bytecount > tx_ring -> max_sdu ) {
1579+ adapter -> stats .txdrop ++ ;
1580+ goto out_drop ;
15861581 }
15871582
15881583 if (unlikely (test_bit (IGC_RING_FLAG_TX_HWTSTAMP , & tx_ring -> flags ) &&
@@ -3012,8 +3007,8 @@ static bool igc_clean_tx_irq(struct igc_q_vector *q_vector, int napi_budget)
30123007 time_after (jiffies , tx_buffer -> time_stamp +
30133008 (adapter -> tx_timeout_factor * HZ )) &&
30143009 !(rd32 (IGC_STATUS ) & IGC_STATUS_TXOFF ) &&
3015- (rd32 (IGC_TDH (tx_ring -> reg_idx )) !=
3016- readl ( tx_ring -> tail )) ) {
3010+ (rd32 (IGC_TDH (tx_ring -> reg_idx )) != readl ( tx_ring -> tail )) &&
3011+ ! tx_ring -> oper_gate_closed ) {
30173012 /* detected Tx unit hang */
30183013 netdev_err (tx_ring -> netdev ,
30193014 "Detected Tx Unit Hang\n"
@@ -6103,13 +6098,17 @@ static int igc_tsn_clear_schedule(struct igc_adapter *adapter)
61036098 adapter -> base_time = 0 ;
61046099 adapter -> cycle_time = NSEC_PER_SEC ;
61056100 adapter -> qbv_config_change_errors = 0 ;
6101+ adapter -> qbv_transition = false;
6102+ adapter -> qbv_count = 0 ;
61066103
61076104 for (i = 0 ; i < adapter -> num_tx_queues ; i ++ ) {
61086105 struct igc_ring * ring = adapter -> tx_ring [i ];
61096106
61106107 ring -> start_time = 0 ;
61116108 ring -> end_time = NSEC_PER_SEC ;
61126109 ring -> max_sdu = 0 ;
6110+ ring -> oper_gate_closed = false;
6111+ ring -> admin_gate_closed = false;
61136112 }
61146113
61156114 return 0 ;
@@ -6121,6 +6120,7 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
61216120 bool queue_configured [IGC_MAX_TX_QUEUES ] = { };
61226121 struct igc_hw * hw = & adapter -> hw ;
61236122 u32 start_time = 0 , end_time = 0 ;
6123+ struct timespec64 now ;
61246124 size_t n ;
61256125 int i ;
61266126
@@ -6150,6 +6150,8 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
61506150 adapter -> cycle_time = qopt -> cycle_time ;
61516151 adapter -> base_time = qopt -> base_time ;
61526152
6153+ igc_ptp_read (adapter , & now );
6154+
61536155 for (n = 0 ; n < qopt -> num_entries ; n ++ ) {
61546156 struct tc_taprio_sched_entry * e = & qopt -> entries [n ];
61556157
@@ -6184,7 +6186,10 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
61846186 ring -> start_time = start_time ;
61856187 ring -> end_time = end_time ;
61866188
6187- queue_configured [i ] = true;
6189+ if (ring -> start_time >= adapter -> cycle_time )
6190+ queue_configured [i ] = false;
6191+ else
6192+ queue_configured [i ] = true;
61886193 }
61896194
61906195 start_time += e -> interval ;
@@ -6194,8 +6199,20 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
61946199 * If not, set the start and end time to be end time.
61956200 */
61966201 for (i = 0 ; i < adapter -> num_tx_queues ; i ++ ) {
6202+ struct igc_ring * ring = adapter -> tx_ring [i ];
6203+
6204+ if (!is_base_time_past (qopt -> base_time , & now )) {
6205+ ring -> admin_gate_closed = false;
6206+ } else {
6207+ ring -> oper_gate_closed = false;
6208+ ring -> admin_gate_closed = false;
6209+ }
6210+
61976211 if (!queue_configured [i ]) {
6198- struct igc_ring * ring = adapter -> tx_ring [i ];
6212+ if (!is_base_time_past (qopt -> base_time , & now ))
6213+ ring -> admin_gate_closed = true;
6214+ else
6215+ ring -> oper_gate_closed = true;
61996216
62006217 ring -> start_time = end_time ;
62016218 ring -> end_time = end_time ;
@@ -6207,7 +6224,7 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
62076224 struct net_device * dev = adapter -> netdev ;
62086225
62096226 if (qopt -> max_sdu [i ])
6210- ring -> max_sdu = qopt -> max_sdu [i ] + dev -> hard_header_len ;
6227+ ring -> max_sdu = qopt -> max_sdu [i ] + dev -> hard_header_len - ETH_TLEN ;
62116228 else
62126229 ring -> max_sdu = 0 ;
62136230 }
@@ -6327,6 +6344,8 @@ static int igc_setup_tc(struct net_device *dev, enum tc_setup_type type,
63276344{
63286345 struct igc_adapter * adapter = netdev_priv (dev );
63296346
6347+ adapter -> tc_setup_type = type ;
6348+
63306349 switch (type ) {
63316350 case TC_QUERY_CAPS :
63326351 return igc_tc_query_caps (adapter , type_data );
@@ -6574,6 +6593,27 @@ static const struct xdp_metadata_ops igc_xdp_metadata_ops = {
65746593 .xmo_rx_timestamp = igc_xdp_rx_timestamp ,
65756594};
65766595
6596+ static enum hrtimer_restart igc_qbv_scheduling_timer (struct hrtimer * timer )
6597+ {
6598+ struct igc_adapter * adapter = container_of (timer , struct igc_adapter ,
6599+ hrtimer );
6600+ unsigned int i ;
6601+
6602+ adapter -> qbv_transition = true;
6603+ for (i = 0 ; i < adapter -> num_tx_queues ; i ++ ) {
6604+ struct igc_ring * tx_ring = adapter -> tx_ring [i ];
6605+
6606+ if (tx_ring -> admin_gate_closed ) {
6607+ tx_ring -> admin_gate_closed = false;
6608+ tx_ring -> oper_gate_closed = true;
6609+ } else {
6610+ tx_ring -> oper_gate_closed = false;
6611+ }
6612+ }
6613+ adapter -> qbv_transition = false;
6614+ return HRTIMER_NORESTART ;
6615+ }
6616+
65776617/**
65786618 * igc_probe - Device Initialization Routine
65796619 * @pdev: PCI device information struct
@@ -6752,6 +6792,9 @@ static int igc_probe(struct pci_dev *pdev,
67526792 INIT_WORK (& adapter -> reset_task , igc_reset_task );
67536793 INIT_WORK (& adapter -> watchdog_task , igc_watchdog_task );
67546794
6795+ hrtimer_init (& adapter -> hrtimer , CLOCK_MONOTONIC , HRTIMER_MODE_REL );
6796+ adapter -> hrtimer .function = & igc_qbv_scheduling_timer ;
6797+
67556798 /* Initialize link properties that are user-changeable */
67566799 adapter -> fc_autoneg = true;
67576800 hw -> mac .autoneg = true;
@@ -6855,6 +6898,7 @@ static void igc_remove(struct pci_dev *pdev)
68556898
68566899 cancel_work_sync (& adapter -> reset_task );
68576900 cancel_work_sync (& adapter -> watchdog_task );
6901+ hrtimer_cancel (& adapter -> hrtimer );
68586902
68596903 /* Release control of h/w to f/w. If f/w is AMT enabled, this
68606904 * would have already happened in close and is redundant.
0 commit comments