igc: offload queue max SDU from tc-taprio
authorTan Tee Min <tee.min.tan@linux.intel.com>
Thu, 16 Feb 2023 01:16:24 +0000 (09:16 +0800)
committerTony Nguyen <anthony.l.nguyen@intel.com>
Tue, 7 Mar 2023 21:45:56 +0000 (13:45 -0800)
Add support for configuring the max SDU for each Tx queue.
If not specified, keep the default.

Signed-off-by: Tan Tee Min <tee.min.tan@linux.intel.com>
Signed-off-by: Muhammad Husaini Zulkifli <muhammad.husaini.zulkifli@intel.com>
Tested-by: Naama Meir <naamax.meir@linux.intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
drivers/net/ethernet/intel/igc/igc.h
drivers/net/ethernet/intel/igc/igc_hw.h
drivers/net/ethernet/intel/igc/igc_main.c

index 79cc99a..c0c00b8 100644 (file)
@@ -99,6 +99,7 @@ struct igc_ring {
 
        u32 start_time;
        u32 end_time;
+       u32 max_sdu;
 
        /* CBS parameters */
        bool cbs_enable;                /* indicates if CBS is enabled */
index 88680e3..e1c572e 100644 (file)
@@ -273,6 +273,7 @@ struct igc_hw_stats {
        u64 o2bspc;
        u64 b2ospc;
        u64 b2ogprc;
+       u64 txdrop;
 };
 
 struct net_device *igc_get_hw_dev(struct igc_hw *hw);
index 4992cca..1e12450 100644 (file)
@@ -1501,6 +1501,7 @@ static int igc_tso(struct igc_ring *tx_ring,
 static netdev_tx_t igc_xmit_frame_ring(struct sk_buff *skb,
                                       struct igc_ring *tx_ring)
 {
+       struct igc_adapter *adapter = netdev_priv(tx_ring->netdev);
        bool first_flag = false, insert_empty = false;
        u16 count = TXD_USE_COUNT(skb_headlen(skb));
        __be16 protocol = vlan_get_protocol(skb);
@@ -1563,9 +1564,19 @@ done:
        first->bytecount = skb->len;
        first->gso_segs = 1;
 
-       if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
-               struct igc_adapter *adapter = netdev_priv(tx_ring->netdev);
+       if (tx_ring->max_sdu > 0) {
+               u32 max_sdu = 0;
+
+               max_sdu = tx_ring->max_sdu +
+                         (skb_vlan_tagged(first->skb) ? VLAN_HLEN : 0);
 
+               if (first->bytecount > max_sdu) {
+                       adapter->stats.txdrop++;
+                       goto out_drop;
+               }
+       }
+
+       if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
                /* FIXME: add support for retrieving timestamps from
                 * the other timer registers before skipping the
                 * timestamping request.
@@ -4920,7 +4931,8 @@ void igc_update_stats(struct igc_adapter *adapter)
        net_stats->tx_window_errors = adapter->stats.latecol;
        net_stats->tx_carrier_errors = adapter->stats.tncrs;
 
-       /* Tx Dropped needs to be maintained elsewhere */
+       /* Tx Dropped */
+       net_stats->tx_dropped = adapter->stats.txdrop;
 
        /* Management Stats */
        adapter->stats.mgptc += rd32(IGC_MGTPTC);
@@ -6056,6 +6068,7 @@ static int igc_tsn_clear_schedule(struct igc_adapter *adapter)
 
                ring->start_time = 0;
                ring->end_time = NSEC_PER_SEC;
+               ring->max_sdu = 0;
        }
 
        return 0;
@@ -6139,6 +6152,16 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
                }
        }
 
+       for (i = 0; i < adapter->num_tx_queues; i++) {
+               struct igc_ring *ring = adapter->tx_ring[i];
+               struct net_device *dev = adapter->netdev;
+
+               if (qopt->max_sdu[i])
+                       ring->max_sdu = qopt->max_sdu[i] + dev->hard_header_len;
+               else
+                       ring->max_sdu = 0;
+       }
+
        return 0;
 }
 
@@ -6237,8 +6260,10 @@ static int igc_tc_query_caps(struct igc_adapter *adapter,
 
                caps->broken_mqprio = true;
 
-               if (hw->mac.type == igc_i225)
+               if (hw->mac.type == igc_i225) {
+                       caps->supports_queue_max_sdu = true;
                        caps->gate_mask_per_txq = true;
+               }
 
                return 0;
        }