Loading drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c +32 −3 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. * * RMNET configuration engine * Loading Loading @@ -216,6 +216,10 @@ static void rmnet_dellink(struct net_device *dev, struct list_head *head) synchronize_rcu(); kfree(ep); } if (!port->nr_rmnet_devs) qmi_rmnet_qmi_exit(port->qmi_info, port); rmnet_unregister_real_device(real_dev, port); unregister_netdevice_queue(dev, head); Loading @@ -236,6 +240,7 @@ static void rmnet_force_unassociate_device(struct net_device *dev) ASSERT_RTNL(); port = rmnet_get_port_rtnl(dev); qmi_rmnet_qmi_exit(port->qmi_info, port); rmnet_unregister_bridge(dev, port); Loading @@ -250,8 +255,6 @@ static void rmnet_force_unassociate_device(struct net_device *dev) unregister_netdevice_many(&list); qmi_rmnet_qmi_exit(port->qmi_info, port); rmnet_unregister_real_device(real_dev, port); } Loading Loading @@ -554,6 +557,7 @@ void rmnet_get_packets(void *port, u64 *rx, u64 *tx) *tx = 0; *rx = 0; rcu_read_lock(); hash_for_each(((struct rmnet_port *)port)->muxed_ep, bkt, ep, hlnode) { priv = netdev_priv(ep->egress_dev); for_each_possible_cpu(cpu) { Loading @@ -565,6 +569,7 @@ void rmnet_get_packets(void *port, u64 *rx, u64 *tx) } while (u64_stats_fetch_retry_irq(&ps->syncp, start)); } } rcu_read_unlock(); } EXPORT_SYMBOL(rmnet_get_packets); Loading Loading @@ -601,6 +606,30 @@ void rmnet_enable_all_flows(void *port) } EXPORT_SYMBOL(rmnet_enable_all_flows); bool rmnet_all_flows_enabled(void *port) { struct rmnet_endpoint *ep; unsigned long bkt; bool ret = true; if (unlikely(!port)) return true; rcu_read_lock(); hash_for_each_rcu(((struct rmnet_port *)port)->muxed_ep, bkt, ep, hlnode) { if (!qmi_rmnet_all_flows_enabled(ep->egress_dev)) { ret = false; goto out; } } out: rcu_read_unlock(); return ret; } EXPORT_SYMBOL(rmnet_all_flows_enabled); int rmnet_get_powersave_notif(void *port) { if (!port) Loading drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h +6 −2 Original line number Diff line number Diff line Loading @@ -28,8 +28,6 @@ struct rmnet_port_priv_stats { u64 dl_hdr_count; u64 dl_hdr_total_bytes; u64 dl_hdr_total_pkts; u64 dl_hdr_avg_bytes; u64 dl_hdr_avg_pkts; u64 dl_trl_last_seq; u64 dl_trl_count; }; Loading Loading @@ -58,6 +56,7 @@ struct rmnet_port { struct timespec agg_time; struct timespec agg_last; struct hrtimer hrtimer; struct work_struct agg_wq; void *qmi_info; Loading Loading @@ -130,6 +129,11 @@ struct rmnet_priv { void __rcu *qos_info; }; enum rmnet_dl_marker_prio { RMNET_PERF, RMNET_SHS, }; enum rmnet_trace_func { RMNET_MODULE, NW_STACK_MODULE, Loading drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c +59 −0 Original line number Diff line number Diff line Loading @@ -83,6 +83,11 @@ int (*rmnet_shs_skb_entry)(struct sk_buff *skb, struct rmnet_port *port) __rcu __read_mostly; EXPORT_SYMBOL(rmnet_shs_skb_entry); /* Shs hook handler for work queue*/ int (*rmnet_shs_skb_entry_wq)(struct sk_buff *skb, struct rmnet_port *port) __rcu __read_mostly; EXPORT_SYMBOL(rmnet_shs_skb_entry_wq); /* Generic handler */ void Loading Loading @@ -125,6 +130,59 @@ rmnet_deliver_skb(struct sk_buff *skb, struct rmnet_port *port) } EXPORT_SYMBOL(rmnet_deliver_skb); /* Important to note, port cannot be used here if it has gone stale */ void rmnet_deliver_skb_wq(struct sk_buff *skb, struct rmnet_port *port, enum rmnet_packet_context ctx) { int (*rmnet_shs_stamp)(struct sk_buff *skb, struct rmnet_port *port); struct rmnet_priv *priv = netdev_priv(skb->dev); trace_rmnet_low(RMNET_MODULE, RMNET_DLVR_SKB, 0xDEF, 0xDEF, 0xDEF, 0xDEF, (void *)skb, NULL); skb_reset_transport_header(skb); skb_reset_network_header(skb); rmnet_vnd_rx_fixup(skb->dev, skb->len); skb->pkt_type = PACKET_HOST; skb_set_mac_header(skb, 0); /* packets coming from work queue context due to packet flush timer * must go through the special workqueue path in SHS driver */ rmnet_shs_stamp = (!ctx) ? rcu_dereference(rmnet_shs_skb_entry) : rcu_dereference(rmnet_shs_skb_entry_wq); if (rmnet_shs_stamp) { rmnet_shs_stamp(skb, port); return; } if (ctx == RMNET_NET_RX_CTX) { if (port->data_format & RMNET_INGRESS_FORMAT_DL_MARKER) { if (!rmnet_check_skb_can_gro(skb) && port->dl_marker_flush >= 0) { struct napi_struct *napi = get_current_napi_context(); napi_gro_receive(napi, skb); port->dl_marker_flush++; } else { netif_receive_skb(skb); } } else { if (!rmnet_check_skb_can_gro(skb)) gro_cells_receive(&priv->gro_cells, skb); else netif_receive_skb(skb); } } else { if ((port->data_format & RMNET_INGRESS_FORMAT_DL_MARKER) && port->dl_marker_flush >= 0) port->dl_marker_flush++; gro_cells_receive(&priv->gro_cells, skb); } } EXPORT_SYMBOL(rmnet_deliver_skb_wq); /* Deliver a list of skbs after undoing coalescing */ static void rmnet_deliver_skb_list(struct sk_buff_head *head, struct rmnet_port *port) Loading Loading @@ -154,6 +212,7 @@ __rmnet_map_ingress_handler(struct sk_buff *skb, qmap = (struct rmnet_map_header *)rmnet_map_data_ptr(skb); if (qmap->cd_bit) { qmi_rmnet_set_dl_msg_active(port); if (port->data_format & RMNET_INGRESS_FORMAT_DL_MARKER) { if (!rmnet_map_flow_command(skb, port, false)) return; Loading drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.h +8 −1 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0 */ /* Copyright (c) 2013, 2016-2018 The Linux Foundation. All rights reserved. /* Copyright (c) 2013, 2016-2019 The Linux Foundation. All rights reserved. * * RMNET Data ingress/egress handler * Loading @@ -10,8 +10,15 @@ #include "rmnet_config.h" enum rmnet_packet_context { RMNET_NET_RX_CTX, RMNET_WQ_CTX, }; void rmnet_egress_handler(struct sk_buff *skb); void rmnet_deliver_skb(struct sk_buff *skb, struct rmnet_port *port); void rmnet_deliver_skb_wq(struct sk_buff *skb, struct rmnet_port *port, enum rmnet_packet_context ctx); void rmnet_set_skb_proto(struct sk_buff *skb); rx_handler_result_t _rmnet_map_ingress_handler(struct sk_buff *skb, struct rmnet_port *port); Loading drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h +1 −0 Original line number Diff line number Diff line Loading @@ -166,6 +166,7 @@ struct rmnet_map_dl_ind_trl { } __aligned(1); struct rmnet_map_dl_ind { u8 priority; void (*dl_hdr_handler)(struct rmnet_map_dl_ind_hdr *dlhdr); void (*dl_trl_handler)(struct rmnet_map_dl_ind_trl *dltrl); struct list_head list; Loading Loading
drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c +32 −3 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. * * RMNET configuration engine * Loading Loading @@ -216,6 +216,10 @@ static void rmnet_dellink(struct net_device *dev, struct list_head *head) synchronize_rcu(); kfree(ep); } if (!port->nr_rmnet_devs) qmi_rmnet_qmi_exit(port->qmi_info, port); rmnet_unregister_real_device(real_dev, port); unregister_netdevice_queue(dev, head); Loading @@ -236,6 +240,7 @@ static void rmnet_force_unassociate_device(struct net_device *dev) ASSERT_RTNL(); port = rmnet_get_port_rtnl(dev); qmi_rmnet_qmi_exit(port->qmi_info, port); rmnet_unregister_bridge(dev, port); Loading @@ -250,8 +255,6 @@ static void rmnet_force_unassociate_device(struct net_device *dev) unregister_netdevice_many(&list); qmi_rmnet_qmi_exit(port->qmi_info, port); rmnet_unregister_real_device(real_dev, port); } Loading Loading @@ -554,6 +557,7 @@ void rmnet_get_packets(void *port, u64 *rx, u64 *tx) *tx = 0; *rx = 0; rcu_read_lock(); hash_for_each(((struct rmnet_port *)port)->muxed_ep, bkt, ep, hlnode) { priv = netdev_priv(ep->egress_dev); for_each_possible_cpu(cpu) { Loading @@ -565,6 +569,7 @@ void rmnet_get_packets(void *port, u64 *rx, u64 *tx) } while (u64_stats_fetch_retry_irq(&ps->syncp, start)); } } rcu_read_unlock(); } EXPORT_SYMBOL(rmnet_get_packets); Loading Loading @@ -601,6 +606,30 @@ void rmnet_enable_all_flows(void *port) } EXPORT_SYMBOL(rmnet_enable_all_flows); bool rmnet_all_flows_enabled(void *port) { struct rmnet_endpoint *ep; unsigned long bkt; bool ret = true; if (unlikely(!port)) return true; rcu_read_lock(); hash_for_each_rcu(((struct rmnet_port *)port)->muxed_ep, bkt, ep, hlnode) { if (!qmi_rmnet_all_flows_enabled(ep->egress_dev)) { ret = false; goto out; } } out: rcu_read_unlock(); return ret; } EXPORT_SYMBOL(rmnet_all_flows_enabled); int rmnet_get_powersave_notif(void *port) { if (!port) Loading
drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h +6 −2 Original line number Diff line number Diff line Loading @@ -28,8 +28,6 @@ struct rmnet_port_priv_stats { u64 dl_hdr_count; u64 dl_hdr_total_bytes; u64 dl_hdr_total_pkts; u64 dl_hdr_avg_bytes; u64 dl_hdr_avg_pkts; u64 dl_trl_last_seq; u64 dl_trl_count; }; Loading Loading @@ -58,6 +56,7 @@ struct rmnet_port { struct timespec agg_time; struct timespec agg_last; struct hrtimer hrtimer; struct work_struct agg_wq; void *qmi_info; Loading Loading @@ -130,6 +129,11 @@ struct rmnet_priv { void __rcu *qos_info; }; enum rmnet_dl_marker_prio { RMNET_PERF, RMNET_SHS, }; enum rmnet_trace_func { RMNET_MODULE, NW_STACK_MODULE, Loading
drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c +59 −0 Original line number Diff line number Diff line Loading @@ -83,6 +83,11 @@ int (*rmnet_shs_skb_entry)(struct sk_buff *skb, struct rmnet_port *port) __rcu __read_mostly; EXPORT_SYMBOL(rmnet_shs_skb_entry); /* Shs hook handler for work queue*/ int (*rmnet_shs_skb_entry_wq)(struct sk_buff *skb, struct rmnet_port *port) __rcu __read_mostly; EXPORT_SYMBOL(rmnet_shs_skb_entry_wq); /* Generic handler */ void Loading Loading @@ -125,6 +130,59 @@ rmnet_deliver_skb(struct sk_buff *skb, struct rmnet_port *port) } EXPORT_SYMBOL(rmnet_deliver_skb); /* Important to note, port cannot be used here if it has gone stale */ void rmnet_deliver_skb_wq(struct sk_buff *skb, struct rmnet_port *port, enum rmnet_packet_context ctx) { int (*rmnet_shs_stamp)(struct sk_buff *skb, struct rmnet_port *port); struct rmnet_priv *priv = netdev_priv(skb->dev); trace_rmnet_low(RMNET_MODULE, RMNET_DLVR_SKB, 0xDEF, 0xDEF, 0xDEF, 0xDEF, (void *)skb, NULL); skb_reset_transport_header(skb); skb_reset_network_header(skb); rmnet_vnd_rx_fixup(skb->dev, skb->len); skb->pkt_type = PACKET_HOST; skb_set_mac_header(skb, 0); /* packets coming from work queue context due to packet flush timer * must go through the special workqueue path in SHS driver */ rmnet_shs_stamp = (!ctx) ? rcu_dereference(rmnet_shs_skb_entry) : rcu_dereference(rmnet_shs_skb_entry_wq); if (rmnet_shs_stamp) { rmnet_shs_stamp(skb, port); return; } if (ctx == RMNET_NET_RX_CTX) { if (port->data_format & RMNET_INGRESS_FORMAT_DL_MARKER) { if (!rmnet_check_skb_can_gro(skb) && port->dl_marker_flush >= 0) { struct napi_struct *napi = get_current_napi_context(); napi_gro_receive(napi, skb); port->dl_marker_flush++; } else { netif_receive_skb(skb); } } else { if (!rmnet_check_skb_can_gro(skb)) gro_cells_receive(&priv->gro_cells, skb); else netif_receive_skb(skb); } } else { if ((port->data_format & RMNET_INGRESS_FORMAT_DL_MARKER) && port->dl_marker_flush >= 0) port->dl_marker_flush++; gro_cells_receive(&priv->gro_cells, skb); } } EXPORT_SYMBOL(rmnet_deliver_skb_wq); /* Deliver a list of skbs after undoing coalescing */ static void rmnet_deliver_skb_list(struct sk_buff_head *head, struct rmnet_port *port) Loading Loading @@ -154,6 +212,7 @@ __rmnet_map_ingress_handler(struct sk_buff *skb, qmap = (struct rmnet_map_header *)rmnet_map_data_ptr(skb); if (qmap->cd_bit) { qmi_rmnet_set_dl_msg_active(port); if (port->data_format & RMNET_INGRESS_FORMAT_DL_MARKER) { if (!rmnet_map_flow_command(skb, port, false)) return; Loading
drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.h +8 −1 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0 */ /* Copyright (c) 2013, 2016-2018 The Linux Foundation. All rights reserved. /* Copyright (c) 2013, 2016-2019 The Linux Foundation. All rights reserved. * * RMNET Data ingress/egress handler * Loading @@ -10,8 +10,15 @@ #include "rmnet_config.h" enum rmnet_packet_context { RMNET_NET_RX_CTX, RMNET_WQ_CTX, }; void rmnet_egress_handler(struct sk_buff *skb); void rmnet_deliver_skb(struct sk_buff *skb, struct rmnet_port *port); void rmnet_deliver_skb_wq(struct sk_buff *skb, struct rmnet_port *port, enum rmnet_packet_context ctx); void rmnet_set_skb_proto(struct sk_buff *skb); rx_handler_result_t _rmnet_map_ingress_handler(struct sk_buff *skb, struct rmnet_port *port); Loading
drivers/net/ethernet/qualcomm/rmnet/rmnet_map.h +1 −0 Original line number Diff line number Diff line Loading @@ -166,6 +166,7 @@ struct rmnet_map_dl_ind_trl { } __aligned(1); struct rmnet_map_dl_ind { u8 priority; void (*dl_hdr_handler)(struct rmnet_map_dl_ind_hdr *dlhdr); void (*dl_trl_handler)(struct rmnet_map_dl_ind_trl *dltrl); struct list_head list; Loading