Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0b46e68f authored by Skylar Chang's avatar Skylar Chang
Browse files

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: default avatarSkylar Chang <chiaweic@codeaurora.org>
parent b65b7cae
Loading
Loading
Loading
Loading
+48 −20
Original line number Diff line number Diff line
@@ -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;
@@ -1018,12 +1021,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 (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)) {
		IPAWANERR("[%s]fatal: ipa_wwan_xmit stopped\n", dev->name);
	return 0;
		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);
@@ -1037,24 +1073,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;
	}

	/* 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;
	}
	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);
	}

	if (ret) {
		ret = NETDEV_TX_BUSY;
		dev->stats.tx_dropped++;
@@ -1065,7 +1093,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);
@@ -1113,7 +1140,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);
	}
@@ -1959,6 +1986,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);
+46 −19
Original line number Diff line number Diff line
@@ -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 (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)) {
		IPAWANERR("[%s]fatal: ipa3_wwan_xmit stopped\n", dev->name);
	return 0;
		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;
	}

	/* 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;
	}
	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);
	}

	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);