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 <chiaweic@codeaurora.org>
This commit is contained in:
parent
c28a277ec8
commit
f912da63c5
2 changed files with 96 additions and 41 deletions
|
@ -33,6 +33,7 @@
|
|||
#include "ipa_qmi_service.h"
|
||||
#include <linux/rmnet_ipa_fd_ioctl.h>
|
||||
#include <linux/ipa.h>
|
||||
#include <uapi/linux/net_map.h>
|
||||
|
||||
#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);
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "ipa_qmi_service.h"
|
||||
#include <linux/rmnet_ipa_fd_ioctl.h>
|
||||
#include <linux/ipa.h>
|
||||
#include <uapi/linux/net_map.h>
|
||||
|
||||
#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);
|
||||
|
|
Loading…
Add table
Reference in a new issue