Thread (7 messages) flat view 7 messages, 3 authors, 2021-02-03

Re: [PATCH net-next v2 1/2] net: mhi-net: Add de-aggeration support

From: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
Date: 2021-02-03 14:07:57

[...]
quoted
quoted
 static void mhi_net_dl_callback(struct mhi_device *mhi_dev,
                                struct mhi_result *mhi_res)
 {
@@ -142,19 +175,42 @@ static void mhi_net_dl_callback(struct mhi_device *mhi_dev,
        free_desc_count = mhi_get_free_desc_count(mhi_dev, DMA_FROM_DEVICE);

        if (unlikely(mhi_res->transaction_status)) {
-               dev_kfree_skb_any(skb);
-
-               /* MHI layer stopping/resetting the DL channel */
-               if (mhi_res->transaction_status == -ENOTCONN)
+               switch (mhi_res->transaction_status) {
+               case -EOVERFLOW:
+                       /* Packet can not fit in one MHI buffer and has been
+                        * split over multiple MHI transfers, do re-aggregation.
+                        * That usually means the device side MTU is larger than
+                        * the host side MTU/MRU. Since this is not optimal,
+                        * print a warning (once).
+                        */
+                       netdev_warn_once(mhi_netdev->ndev,
+                                        "Fragmented packets received, fix MTU?\n");
+                       skb_put(skb, mhi_res->bytes_xferd);
+                       mhi_net_skb_agg(mhi_netdev, skb);
+                       break;
+               case -ENOTCONN:
+                       /* MHI layer stopping/resetting the DL channel */
+                       dev_kfree_skb_any(skb);
                        return;
-
-               u64_stats_update_begin(&mhi_netdev->stats.rx_syncp);
-               u64_stats_inc(&mhi_netdev->stats.rx_errors);
-               u64_stats_update_end(&mhi_netdev->stats.rx_syncp);
+               default:
+                       /* Unknown error, simply drop */
+                       dev_kfree_skb_any(skb);
+                       u64_stats_update_begin(&mhi_netdev->stats.rx_syncp);
+                       u64_stats_inc(&mhi_netdev->stats.rx_errors);
+                       u64_stats_update_end(&mhi_netdev->stats.rx_syncp);
+               }
        } else {
+               skb_put(skb, mhi_res->bytes_xferd);
+
+               if (mhi_netdev->skbagg_head) {
+                       /* Aggregate the final fragment */
+                       skb = mhi_net_skb_agg(mhi_netdev, skb);
+                       mhi_netdev->skbagg_head = NULL;
+               }
+
                u64_stats_update_begin(&mhi_netdev->stats.rx_syncp);
                u64_stats_inc(&mhi_netdev->stats.rx_packets);
-               u64_stats_add(&mhi_netdev->stats.rx_bytes, mhi_res->bytes_xferd);
+               u64_stats_add(&mhi_netdev->stats.rx_bytes, skb->len);
might this change stats? it will if skb->len != 0 before skb_put. Even
if so, perhaps it doesn't matter.
Don't get that point, skb is the received MHI buffer, we simply set
its size because MHI core don't (skb->len is always 0 before put).
Then if it is part of a fragmented transfer we just do the extra
'skb = skb_agg+ skb', so skb->len should always be right here,
whether it's a standalone/linear packet or a multi-frag packet.
Great. I did not know that skb->len is 0 before put for this codepath.
It isn't for other protocols, and then any protocol headers would have
been counted.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help