[PATCH net-next v3 3/8] net: qualcomm: rmnet: Process MAPv5 frames as a list
flat view
COOLING5d
From: Subash Abhinov Kasiviswanathan <subash.a.kasiviswanathan@oss.qualcomm.com>
Date: 2026-10-09 08:44:23
Also in:
linux-doc, lkml
Subsystem:
networking drivers, qualcomm rmnet driver, the rest · Maintainers:
Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Subash Abhinov Kasiviswanathan, Sean Tranchetti, Linus Torvalds
Revision v3 of 3 in this series.
Revisions (3)
- v1 [diff vs current]
- v2 [diff vs current]
- v3 current
Add support for handling the MAP packets as a list in preparation for the subsequent patch in the series which adds support for handling the coalescing packets. This is needed as a single coalescing MAP packet could yield multiple IP packets. There is no functional change in the handling of the previously supported MAP packet formats. Co-developed-by: Sean Tranchetti <sean.tranchetti@oss.qualcomm.com> Signed-off-by: Sean Tranchetti <sean.tranchetti@oss.qualcomm.com> Signed-off-by: Subash Abhinov Kasiviswanathan <subash.a.kasiviswanathan@oss.qualcomm.com> --- v3: no change v2: https://lore.kernel.org/all/20261008005543.2630828-4-subash.a.kasiviswanathan@oss.qualcomm.com/ (local) v1: https://lore.kernel.org/all/20260930051345.857443-3-subash.a.kasiviswanathan@oss.qualcomm.com/ (local) .../ethernet/qualcomm/rmnet/rmnet_handlers.c | 22 +++++-- .../net/ethernet/qualcomm/rmnet/rmnet_map.h | 4 +- .../ethernet/qualcomm/rmnet/rmnet_map_data.c | 57 ++++++++++++------- 3 files changed, 58 insertions(+), 25 deletions(-)
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c
index aa5523f4618e..ab1dfbd833e3 100644
--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c@@ -50,6 +50,16 @@ rmnet_deliver_skb(struct sk_buff *skb) gro_cells_receive(&priv->gro_cells, skb); } +static void rmnet_deliver_skb_list(struct sk_buff_head *head) +{ + struct sk_buff *skb; + + while ((skb = __skb_dequeue(head))) { + rmnet_set_skb_proto(skb); + rmnet_deliver_skb(skb); + } +} + /* MAP handler */ static void
@@ -59,6 +69,7 @@ __rmnet_map_ingress_handler(struct sk_buff *skb, { struct rmnet_map_header *map_header = (void *)skb->data; struct rmnet_endpoint *ep; + struct sk_buff_head list; u16 len, pad; u8 mux_id;
@@ -83,12 +94,12 @@ __rmnet_map_ingress_handler(struct sk_buff *skb, skb->dev = ep->egress_dev; + __skb_queue_head_init(&list); + if ((data_format & RMNET_FLAGS_INGRESS_MAP_CKSUMV5) && (map_header->flags & MAP_NEXT_HEADER_FLAG)) { - if (rmnet_map_process_next_hdr_packet(skb, len)) + if (rmnet_map_process_next_hdr_packet(skb, &list, len)) goto free_skb; - skb_pull(skb, sizeof(*map_header)); - rmnet_set_skb_proto(skb); } else { /* Subtract MAP header */ skb_pull(skb, sizeof(*map_header));
@@ -96,10 +107,11 @@ __rmnet_map_ingress_handler(struct sk_buff *skb, if (data_format & RMNET_FLAGS_INGRESS_MAP_CKSUMV4 && !rmnet_map_checksum_downlink_packet(skb, len + pad)) skb->ip_summed = CHECKSUM_UNNECESSARY; + skb_trim(skb, len); + __skb_queue_tail(&list, skb); } - skb_trim(skb, len); - rmnet_deliver_skb(skb); + rmnet_deliver_skb_list(&list); return; free_skb:
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h
index 0977e495f591..ef738ce015d4 100644
--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h@@ -53,7 +53,9 @@ void rmnet_map_checksum_uplink_packet(struct sk_buff *skb, struct rmnet_port *port, struct net_device *orig_dev, int csum_type); -int rmnet_map_process_next_hdr_packet(struct sk_buff *skb, u16 len); +int rmnet_map_process_next_hdr_packet(struct sk_buff *skb, + struct sk_buff_head *list, + u16 len); unsigned int rmnet_map_tx_aggregate(struct sk_buff *skb, struct rmnet_port *port, struct net_device *orig_dev); void rmnet_map_tx_aggregate_init(struct rmnet_port *port);
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c
index 39d6d084e73f..577f2758e385 100644
--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c@@ -497,35 +497,54 @@ void rmnet_map_checksum_uplink_packet(struct sk_buff *skb, } } -/* Process a MAPv5 packet header */ +static struct rmnet_map_v5_csum_header * +rmnet_map_get_next_hdr(struct sk_buff *skb) +{ + return (struct rmnet_map_v5_csum_header *)(skb->data + + sizeof(struct rmnet_map_header)); +} + +static u8 rmnet_map_get_next_hdr_type(struct sk_buff *skb) +{ + struct rmnet_map_v5_csum_header *hdr = rmnet_map_get_next_hdr(skb); + + return u8_get_bits(hdr->header_info, MAPV5_HDRINFO_HDR_TYPE_FMASK); +} + +static bool rmnet_map_get_csum_valid(struct sk_buff *skb) +{ + struct rmnet_map_v5_csum_header *hdr = rmnet_map_get_next_hdr(skb); + + return !!(hdr->csum_info & MAPV5_CSUMINFO_VALID_FLAG); +} + int rmnet_map_process_next_hdr_packet(struct sk_buff *skb, + struct sk_buff_head *list, u16 len) { struct rmnet_priv *priv = netdev_priv(skb->dev); - struct rmnet_map_v5_csum_header *next_hdr; - u8 nexthdr_type; - next_hdr = (struct rmnet_map_v5_csum_header *)(skb->data + - sizeof(struct rmnet_map_header)); + switch (rmnet_map_get_next_hdr_type(skb)) { + case RMNET_MAP_HEADER_TYPE_CSUM_OFFLOAD: + if (unlikely(!(skb->dev->features & NETIF_F_RXCSUM))) { + priv->stats.csum_sw++; + } else if (rmnet_map_get_csum_valid(skb)) { + priv->stats.csum_ok++; + skb->ip_summed = CHECKSUM_UNNECESSARY; + } else { + priv->stats.csum_valid_unset++; + } - nexthdr_type = u8_get_bits(next_hdr->header_info, - MAPV5_HDRINFO_HDR_TYPE_FMASK); + skb_pull(skb, sizeof(struct rmnet_map_header) + + sizeof(struct rmnet_map_v5_csum_header)); + skb_trim(skb, len); + __skb_queue_tail(list, skb); + break; - if (nexthdr_type != RMNET_MAP_HEADER_TYPE_CSUM_OFFLOAD) + default: return -EINVAL; - - if (unlikely(!(skb->dev->features & NETIF_F_RXCSUM))) { - priv->stats.csum_sw++; - } else if (next_hdr->csum_info & MAPV5_CSUMINFO_VALID_FLAG) { - priv->stats.csum_ok++; - skb->ip_summed = CHECKSUM_UNNECESSARY; - } else { - priv->stats.csum_valid_unset++; } - /* Pull csum v5 header */ - skb_pull(skb, sizeof(*next_hdr)); - return 0; }
--
2.34.1