msm: rmnet_bam: kickoff UL wakeup when necessary
Kickoff uplink wakeup on the transport when necessary so that necessary
scheduling does not occur in atomic context.
Change-Id: Iae702d0b318c8edc8ee0b45e372cc2db85370a97
Signed-off-by: Jeffrey Hugo <jhugo@codeaurora.org>
diff --git a/drivers/net/msm_rmnet_bam.c b/drivers/net/msm_rmnet_bam.c
index 5397cbf..8a3e427 100644
--- a/drivers/net/msm_rmnet_bam.c
+++ b/drivers/net/msm_rmnet_bam.c
@@ -81,8 +81,11 @@
struct tasklet_struct tsklt;
u32 operation_mode; /* IOCTL specified mode (protocol, QoS header) */
uint8_t device_up;
+ uint8_t waiting_for_ul;
};
+static uint8_t ul_is_connected;
+
#ifdef CONFIG_MSM_RMNET_DEBUG
static unsigned long timeout_us;
@@ -337,6 +340,8 @@
static void bam_notify(void *dev, int event, unsigned long data)
{
+ struct rmnet_private *p = netdev_priv(dev);
+
switch (event) {
case BAM_DMUX_RECEIVE:
bam_recv_notify(dev, (struct sk_buff *)(data));
@@ -344,6 +349,16 @@
case BAM_DMUX_WRITE_DONE:
bam_write_done(dev, (struct sk_buff *)(data));
break;
+ case BAM_DMUX_UL_CONNECTED:
+ ul_is_connected = 1;
+ if (p->waiting_for_ul) {
+ netif_wake_queue(dev);
+ p->waiting_for_ul = 0;
+ }
+ break;
+ case BAM_DMUX_UL_DISCONNECTED:
+ ul_is_connected = 0;
+ break;
}
}
@@ -419,6 +434,8 @@
static int rmnet_xmit(struct sk_buff *skb, struct net_device *dev)
{
+ struct rmnet_private *p = netdev_priv(dev);
+
if (netif_queue_stopped(dev)) {
pr_err("[%s]fatal: rmnet_xmit called when "
"netif_queue is stopped", dev->name);
@@ -426,6 +443,11 @@
}
netif_stop_queue(dev);
+ if (!ul_is_connected) {
+ p->waiting_for_ul = 1;
+ msm_bam_dmux_kickoff_ul_wakeup();
+ return NETDEV_TX_BUSY;
+ }
_rmnet_xmit(skb, dev);
return 0;
@@ -626,6 +648,7 @@
/* Initial config uses Ethernet */
p->operation_mode = RMNET_MODE_LLP_ETH;
p->ch_id = n;
+ p->waiting_for_ul = 0;
spin_lock_init(&p->lock);
#ifdef CONFIG_MSM_RMNET_DEBUG
p->timeout_us = timeout_us;