From f912da63c5a639a6ab5b46b89dd68e070c983a09 Mon Sep 17 00:00:00 2001 From: Skylar Chang Date: Fri, 5 Feb 2016 16:05:35 -0800 Subject: [PATCH] msm: ipa: support qmap control pkt using pkt_init Currently the qmap control pkts are sent back to AP from modem because of exception. The fix is to use pkt_init to skip filtering/natting on IPA-HW to reach modem instead. Also there is a requirement for AP-side to send back qmap flow control acks immediately after receiving the requets. The code change is to make 2st level high-watermark for those qmap control pkts to not be dropped. Also rmnet_ipa driver won't stop queue if the current pkt is qmap control pkt even when outstanding pkts above the first level of high-watermark. Change-Id: I3074e4a37d74c491593e109c1df0c99da85a5e57 Signed-off-by: Skylar Chang --- drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c | 70 ++++++++++++++------- drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c | 67 ++++++++++++++------ 2 files changed, 96 insertions(+), 41 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c index 05a6d5134379..dd5ca0a8463d 100644 --- a/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c +++ b/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c @@ -33,6 +33,7 @@ #include "ipa_qmi_service.h" #include #include +#include #include "ipa_trace.h" @@ -44,6 +45,7 @@ #define TAILROOM 0 /* for padding by mux layer */ #define MAX_NUM_OF_MUX_CHANNEL 10 /* max mux channels */ #define UL_FILTER_RULE_HANDLE_START 69 +#define DEFAULT_OUTSTANDING_HIGH_CTL 96 #define DEFAULT_OUTSTANDING_HIGH 64 #define DEFAULT_OUTSTANDING_LOW 32 @@ -110,6 +112,7 @@ struct wwan_private { struct net_device *net; struct net_device_stats stats; atomic_t outstanding_pkts; + int outstanding_high_ctl; int outstanding_high; int outstanding_low; uint32_t ch_id; @@ -1023,12 +1026,45 @@ static int ipa_wwan_change_mtu(struct net_device *dev, int new_mtu) static int ipa_wwan_xmit(struct sk_buff *skb, struct net_device *dev) { int ret = 0; + bool qmap_check; struct wwan_private *wwan_ptr = netdev_priv(dev); + struct ipa_tx_meta meta; - if (netif_queue_stopped(dev)) { - IPAWANERR("[%s]fatal: ipa_wwan_xmit stopped\n", dev->name); - return 0; + if (skb->protocol != htons(ETH_P_MAP)) { + IPAWANDBG + ("SW filtering out none QMAP packet received from %s", + current->comm); + return NETDEV_TX_OK; } + + qmap_check = RMNET_MAP_GET_CD_BIT(skb); + if (netif_queue_stopped(dev)) { + if (qmap_check && + atomic_read(&wwan_ptr->outstanding_pkts) < + wwan_ptr->outstanding_high_ctl) { + pr_err("[%s]Queue stop, send ctrl pkts\n", dev->name); + goto send; + } else { + pr_err("[%s]fatal: ipa_wwan_xmit stopped\n", dev->name); + return NETDEV_TX_BUSY; + } + } + + /* checking High WM hit */ + if (atomic_read(&wwan_ptr->outstanding_pkts) >= + wwan_ptr->outstanding_high) { + if (!qmap_check) { + IPAWANDBG("pending(%d)/(%d)- stop(%d), qmap_chk(%d)\n", + atomic_read(&wwan_ptr->outstanding_pkts), + wwan_ptr->outstanding_high, + netif_queue_stopped(dev), + qmap_check); + netif_stop_queue(dev); + return NETDEV_TX_BUSY; + } + } + +send: /* IPA_RM checking start */ ret = ipa2_rm_inactivity_timer_request_resource( IPA_RM_RESOURCE_WWAN_0_PROD); @@ -1042,24 +1078,16 @@ static int ipa_wwan_xmit(struct sk_buff *skb, struct net_device *dev) return -EFAULT; } /* IPA_RM checking end */ - if (skb->protocol != htons(ETH_P_MAP)) { - IPAWANDBG - ("SW filtering out none QMAP packet received from %s", - current->comm); - ret = NETDEV_TX_OK; - goto out; + + if (qmap_check) { + memset(&meta, 0, sizeof(meta)); + meta.pkt_init_dst_ep_valid = true; + meta.pkt_init_dst_ep_remote = true; + ret = ipa2_tx_dp(IPA_CLIENT_Q6_LAN_CONS, skb, &meta); + } else { + ret = ipa2_tx_dp(IPA_CLIENT_APPS_LAN_WAN_PROD, skb, NULL); } - /* checking High WM hit */ - if (atomic_read(&wwan_ptr->outstanding_pkts) >= - wwan_ptr->outstanding_high) { - IPAWANDBG("Outstanding high (%d)- stopping\n", - wwan_ptr->outstanding_high); - netif_stop_queue(dev); - ret = NETDEV_TX_BUSY; - goto out; - } - ret = ipa2_tx_dp(IPA_CLIENT_APPS_LAN_WAN_PROD, skb, NULL); if (ret) { ret = NETDEV_TX_BUSY; dev->stats.tx_dropped++; @@ -1070,7 +1098,6 @@ static int ipa_wwan_xmit(struct sk_buff *skb, struct net_device *dev) dev->stats.tx_packets++; dev->stats.tx_bytes += skb->len; ret = NETDEV_TX_OK; - out: ipa2_rm_inactivity_timer_release_resource( IPA_RM_RESOURCE_WWAN_0_PROD); @@ -1118,7 +1145,7 @@ static void apps_ipa_tx_complete_notify(void *priv, netif_queue_stopped(wwan_ptr->net) && atomic_read(&wwan_ptr->outstanding_pkts) < (wwan_ptr->outstanding_low)) { - IPAWANDBG("Outstanding low (%d) - waking up queue\n", + IPAWANDBG("Outstanding low (%d) - wake up queue\n", wwan_ptr->outstanding_low); netif_wake_queue(wwan_ptr->net); } @@ -1965,6 +1992,7 @@ static int ipa_wwan_probe(struct platform_device *pdev) memset(wwan_ptr, 0, sizeof(*wwan_ptr)); IPAWANDBG("wwan_ptr (private) = %p", wwan_ptr); wwan_ptr->net = dev; + wwan_ptr->outstanding_high_ctl = DEFAULT_OUTSTANDING_HIGH_CTL; wwan_ptr->outstanding_high = DEFAULT_OUTSTANDING_HIGH; wwan_ptr->outstanding_low = DEFAULT_OUTSTANDING_LOW; atomic_set(&wwan_ptr->outstanding_pkts, 0); diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c index 4c6961bcfcbc..03a4fcbbf7a5 100644 --- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c @@ -33,6 +33,7 @@ #include "ipa_qmi_service.h" #include #include +#include #include "ipa_trace.h" @@ -44,6 +45,7 @@ #define TAILROOM 0 /* for padding by mux layer */ #define MAX_NUM_OF_MUX_CHANNEL 10 /* max mux channels */ #define UL_FILTER_RULE_HANDLE_START 69 +#define DEFAULT_OUTSTANDING_HIGH_CTL 96 #define DEFAULT_OUTSTANDING_HIGH 64 #define DEFAULT_OUTSTANDING_LOW 32 @@ -99,6 +101,7 @@ struct ipa3_wwan_private { struct net_device *net; struct net_device_stats stats; atomic_t outstanding_pkts; + int outstanding_high_ctl; int outstanding_high; int outstanding_low; uint32_t ch_id; @@ -1043,12 +1046,45 @@ static int ipa3_wwan_change_mtu(struct net_device *dev, int new_mtu) static int ipa3_wwan_xmit(struct sk_buff *skb, struct net_device *dev) { int ret = 0; + bool qmap_check; struct ipa3_wwan_private *wwan_ptr = netdev_priv(dev); + struct ipa_tx_meta meta; - if (netif_queue_stopped(dev)) { - IPAWANERR("[%s]fatal: ipa3_wwan_xmit stopped\n", dev->name); - return 0; + if (skb->protocol != htons(ETH_P_MAP)) { + IPAWANDBG + ("SW filtering out none QMAP packet received from %s", + current->comm); + return NETDEV_TX_OK; } + + qmap_check = RMNET_MAP_GET_CD_BIT(skb); + if (netif_queue_stopped(dev)) { + if (qmap_check && + atomic_read(&wwan_ptr->outstanding_pkts) < + wwan_ptr->outstanding_high_ctl) { + pr_err("[%s]Queue stop, send ctrl pkts\n", dev->name); + goto send; + } else { + pr_err("[%s]fatal: ipa_wwan_xmit stopped\n", dev->name); + return NETDEV_TX_BUSY; + } + } + + /* checking High WM hit */ + if (atomic_read(&wwan_ptr->outstanding_pkts) >= + wwan_ptr->outstanding_high) { + if (!qmap_check) { + IPAWANDBG("pending(%d)/(%d)- stop(%d), qmap_chk(%d)\n", + atomic_read(&wwan_ptr->outstanding_pkts), + wwan_ptr->outstanding_high, + netif_queue_stopped(dev), + qmap_check); + netif_stop_queue(dev); + return NETDEV_TX_BUSY; + } + } + +send: /* IPA_RM checking start */ ret = ipa3_rm_inactivity_timer_request_resource( IPA_RM_RESOURCE_WWAN_0_PROD); @@ -1062,24 +1098,16 @@ static int ipa3_wwan_xmit(struct sk_buff *skb, struct net_device *dev) return -EFAULT; } /* IPA_RM checking end */ - if (skb->protocol != htons(ETH_P_MAP)) { - IPAWANDBG - ("SW filtering out none QMAP packet received from %s", - current->comm); - ret = NETDEV_TX_OK; - goto out; + + if (RMNET_MAP_GET_CD_BIT(skb)) { + memset(&meta, 0, sizeof(meta)); + meta.pkt_init_dst_ep_valid = true; + meta.pkt_init_dst_ep_remote = true; + ret = ipa3_tx_dp(IPA_CLIENT_Q6_LAN_CONS, skb, &meta); + } else { + ret = ipa3_tx_dp(IPA_CLIENT_APPS_LAN_WAN_PROD, skb, NULL); } - /* checking High WM hit */ - if (atomic_read(&wwan_ptr->outstanding_pkts) >= - wwan_ptr->outstanding_high) { - IPAWANDBG("Outstanding high (%d)- stopping\n", - wwan_ptr->outstanding_high); - netif_stop_queue(dev); - ret = NETDEV_TX_BUSY; - goto out; - } - ret = ipa3_tx_dp(IPA_CLIENT_APPS_LAN_WAN_PROD, skb, NULL); if (ret) { ret = NETDEV_TX_BUSY; dev->stats.tx_dropped++; @@ -1090,7 +1118,6 @@ static int ipa3_wwan_xmit(struct sk_buff *skb, struct net_device *dev) dev->stats.tx_packets++; dev->stats.tx_bytes += skb->len; ret = NETDEV_TX_OK; - out: ipa3_rm_inactivity_timer_release_resource( IPA_RM_RESOURCE_WWAN_0_PROD);