Merge branch 'LA.UM.9.1.R1.10.00.00.604.038' via branch 'qcom-msm-4.14' into android-msm-floral-4.14

Bug: 155859424
Change-Id: I0a01d96563211cfa85f3822527dbed8039f83de5
Signed-off-by: Wilson Sung <wilsonsung@google.com>
diff --git a/drivers/generic-sw-bridge/Makefile b/drivers/generic-sw-bridge/Makefile
deleted file mode 100644
index 5c63232..0000000
--- a/drivers/generic-sw-bridge/Makefile
+++ /dev/null
@@ -1,35 +0,0 @@
-#
-# Copyright (c) 2017, The Linux Foundation. All rights reserved.
-#
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 and
-# only version 2 as published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-
-#
-# Makefile for generic software bridge module.
-#
-KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build
-obj-m += gsb.o
-MY_CFLAGS += -g
-ccflags-y += ${MY_CFLAGS}
-CC += ${MY_CFLAGS}
-
-gsb-objs := \
-	generic_sw_bridge_main.o
-all:
-	$(MAKE) -C $(KERNEL_SRC) M=$(shell pwd) modules $(KBUILD_OPTIONS)
-
-debug:
-	$(MAKE) -C $(KERNEL_SRC) M=$(shell pwd) modules $(KBUILD_OPTIONS) EXTRA_CFLAGS="$(MY_CFLAGS)"
-
-modules_install:
-	$(MAKE) -C $(KERNEL_SRC) M=$(shell pwd) modules_install
-
-clean:
-	$(MAKE) -C $(KERNEL_SRC) M=$(PWD) clean
diff --git a/drivers/generic-sw-bridge/generic_sw_bridge.h b/drivers/generic-sw-bridge/generic_sw_bridge.h
deleted file mode 100644
index a26c9f5..0000000
--- a/drivers/generic-sw-bridge/generic_sw_bridge.h
+++ /dev/null
@@ -1,222 +0,0 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved. */
-/*
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef _GENERIC_SW_BRIDGE_H_
-#define _GENERIC_SW_BRIDGE_H_
-
-
-#include <linux/cdev.h>
-#include <linux/ipa_odu_bridge.h>
-
-
-
-
-#define MAX_SUPPORTED_IF_CONFIG 1
-#define DRV_VERSION "v1.0"
-/*
- * MAX buffer length for stats display.
- */
-#define MAX_BUFF_LEN 2000
-#define INACTIVITY_TIME 200
-
-#define PACKET_DUMP_BUFFER 200
-#define PACKET_MP_PRINT_LEN 100
-#define READ_STATS_OFFSET 5
-#define TAG_LENGTH 48
-#define MAX_PACKETS_TO_SEND 50
-
-#define GSB_ACCEPT 1
-#define GSB_DROP 2
-#define GSB_FORWARD 3
-
-#define GSB_FLOW_CNTRL_QUEUE_MULTIPLIER 4
-
-#define MAC_ADDR_ARRAY(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
-
-/**
- *  * struct gsb_ipa_stats - GSB - IPA_Bridge/IPA Stats
- *  */
-struct gsb_ipa_stats
-{
-	/* RX Side (UPLINK)*/
-	uint64_t total_recv_from_if;
-	uint64_t sent_to_ipa;
-	uint64_t exception_ipa_not_connected;
-	uint64_t exception_non_ip_packet;
-	uint64_t exception_fragmented;
-	uint64_t drop_flow_control_bottleneck;
-	uint64_t ipa_suspend_cnt;
-	uint64_t exp_ipa_suspended;
-	uint64_t exp_insufficient_hr;
-	uint64_t exception_packet_from_ipa;
-	uint64_t exp_packet_from_ipa_fail;
-	uint64_t drop_send_to_ipa_fail;
-	uint64_t exp_if_disconnected;
-	uint64_t exp_if_disconnected_fail;
-
-	/* TX Side(DOWNLINK)*/
-	uint64_t tx_send_to_if;
-	uint64_t tx_send_err;
-	uint64_t write_done_from_ipa;
-
-	/* Flow Control Stats */
-	uint64_t ipa_low_watermark_cnt;
-};
-
-enum if_device_type
-{
-	WLAN_TYPE = 1,
-	ETH_TYPE,
-};
-struct gsb_if_config
-{
-	char if_name[IFNAMSIZ];
-	u32 bw_reqd_in_mb;
-	u16 if_high_watermark;
-	u16 if_low_watermark;
-	enum if_device_type if_type;
-};
-
-/**
- * struct if_ipa_ctx - Interface IPA Context
- *  @stats: GSB - IPA brigde stats
- *  @ipa_rx_completion: Keeps track of pending IPA WRITE DONE Evts
- **/
-struct if_ipa_ctx
-{
-	struct gsb_ipa_stats stats;
-	uint64_t ipa_rx_completion;
-};
-
-
-/*
- *  struct gsb_if_info - Each if configured in
- *  GSB will have its own context
- **/
-struct gsb_if_info
-{
-	u32 handle;
-	struct dentry *dbg_dir_if;
-	struct net_device *pdev;
-	struct gsb_if_config  user_config;
-	char if_name[IFNAMSIZ];
-	bool net_dev_state;
-	struct hlist_node cache_ht_node;
-	bool is_connected_to_ipa_bridge;
-	bool is_wq_scheduled;
-	bool is_ipa_bridge_suspended;
-	bool is_debugfs_init;
-	bool is_ipa_bridge_initialized;
-
-	struct if_ipa_ctx *if_ipa;
-
-	u16 max_q_len_in_gsb;
-	u16 low_watermark;
-	u16 pendq_cnt;
-	u16 freeq_cnt;
-	u16 ipa_free_desc_cnt;
-	uint64_t wq_schedule_cnt;
-	uint64_t idle_cnt;
-	spinlock_t flow_ctrl_lock;
-	bool flow_ctrl_lock_acquired;
-
-	struct sk_buff_head pend_queue;
-
-	struct list_head pend_queue_head;
-	struct list_head free_queue_head;
-	struct work_struct ipa_send_task;
-	struct work_struct ipa_resume_task;
-
-};
-
-/*
- *  struct gsb_ctx - GSB global Context
- **/
-struct gsb_ctx
-{
-	struct dentry *dbg_dir_root;
-	spinlock_t gsb_lock;
-	bool gsb_lock_acquired;
-
-	/*
-	 * Callback notifiers.
-	 */
-	struct notifier_block gsb_dev_notifier;
-	struct notifier_block gsb_pm_notifier;
-
-	spinlock_t gsb_wake_lock;
-	bool gsb_wake_lock_acquired;
-	u16 wake_source_ref_count;
-	bool do_we_need_wake_source;
-	struct wakeup_source gsb_wake_src;
-	bool is_wake_src_acquired;
-
-	bool inactivity_timer_scheduled;
-
-	u32 mem_alloc_if_node;
-	u32 mem_alloc_read_stats_buffer;
-	u32 mem_alloc_if_ipa_context;
-	u32 mem_alloc_ioctl_buffer;
-	uint64_t mem_alloc_skb_free;
-
-	bool is_ipa_ready;
-	u32 gsb_state_mask;
-	u16 configured_if_count;
-	uint64_t inactivity_timer_cnt;
-	uint64_t inactivity_timer_cancelled_cnt;
-	struct hlist_head cache_htable_list[MAX_SUPPORTED_IF_CONFIG];
-};
-
-u8 NBITS(u32 n)
-{
-	u8 ret = 0;
-	while (n >>= 1) ret++;
-	return ret;
-}
-
-u32 StringtoAscii(char *str)
-{
-	int ret = -1;
-	int i = 0;
-	int len = strlen(str);
-	for (i = 0; i < len; i++)
-	{
-		ret = ret + str[i];
-	}
-
-	return ret;
-}
-
-
-
-// definitions required for IOCTL
-static unsigned int dev_num = 1;
-static struct cdev gsb_ioctl_cdev;
-static struct class *gsb_class;
-static dev_t device;
-#define GSB_IOC_MAGIC 0xED
-
-/*
- * Ioctls supported by bridge driver
- */
-#define GSB_IOC_ADD_IF_CONFIG _IOWR(GSB_IOC_MAGIC, \
-	0, \
-	struct gsb_if_config *)
-#define GSB_IOC_DEL_IF_CONFIG _IOWR(GSB_IOC_MAGIC, \
-	1, \
-	struct gsb_if_config *)
-
-
-
-
-#endif
diff --git a/drivers/generic-sw-bridge/generic_sw_bridge_main.c b/drivers/generic-sw-bridge/generic_sw_bridge_main.c
deleted file mode 100644
index de604fb..0000000
--- a/drivers/generic-sw-bridge/generic_sw_bridge_main.c
+++ /dev/null
@@ -1,2171 +0,0 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved. */
-/*
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/suspend.h>
-#include <linux/pm_wakeup.h>
-#include <linux/ioctl.h>
-#include <linux/wait.h>
-#include "generic_sw_bridge.h"
-#include "gsb_debugfs.h"
-#include <linux/hashtable.h>
-#include <linux/hash.h>
-#include <linux/timer.h>
-#include <linux/etherdevice.h>
-#include <linux/ip.h>
-#include <net/ip.h>
-#include <linux/proc_fs.h>
-
-static char gsb_drv_name[] = "gsb";
-static struct gsb_ctx *__gc = NULL;
-static DECLARE_WAIT_QUEUE_HEAD(wq);
-
-static struct proc_dir_entry* proc_file = NULL;
-static struct file_operations proc_file_ops;
-int gsb_enable_ipc_low;
-#define MAX_PROC_SIZE 10
-char tmp_buff[MAX_PROC_SIZE];
-
-static const char gsb_drv_description[] =
-	"The Linux Foundation"
-	"Generic Software Bridge Driver v0.1";
-
-static void gsb_ipa_send_routine(struct work_struct *work);
-static void gsb_ipa_resume_routine(struct work_struct *work);
-static void suspend_task(struct work_struct *work);
-struct gsb_if_info* get_node_info_from_ht(char *iface);
-static void schedule_inactivity_timer(const unsigned int time_in_ms);
-static int suspend_all_bridged_interfaces(void);
-static DECLARE_DELAYED_WORK(if_suspend_wq, suspend_task);
-static struct workqueue_struct *gsb_wq;
-extern int (*gsb_nw_stack_recv)(struct sk_buff *skb);
-
-
-
-static void release_wake_source(void)
-{
-	struct gsb_ctx *pgsb_ctx = __gc;
-	if (IS_ERR_OR_NULL(pgsb_ctx))
-	{
-		IPC_ERROR_LOW("NULL GSB Context passed\n");
-		return;
-	}
-	spin_lock_bh(&pgsb_ctx->gsb_wake_lock);
-	if (pgsb_ctx->wake_source_ref_count>0) pgsb_ctx->wake_source_ref_count--;
-	if (pgsb_ctx->do_we_need_wake_source && !pgsb_ctx->wake_source_ref_count)
-	{
-		IPC_TRACE_LOW("Scheduling Inactivity timer\n");
-		if (!pgsb_ctx->inactivity_timer_scheduled)
-		{
-			schedule_inactivity_timer(INACTIVITY_TIME);
-			pgsb_ctx->inactivity_timer_cnt++;
-		}
-	}
-	else
-	{
-		IPC_TRACE_LOW("Wake source count %d\n",
-				pgsb_ctx->wake_source_ref_count);
-	}
-
-	spin_unlock_bh(&pgsb_ctx->gsb_wake_lock);
-}
-
-static void acquire_wake_source(void)
-{
-	struct gsb_ctx *pgsb_ctx = __gc;
-	if (IS_ERR_OR_NULL(pgsb_ctx))
-	{
-		IPC_ERROR_LOW("NULL GSB Context passed\n");
-		return;
-	}
-
-	spin_lock_bh(&pgsb_ctx->gsb_wake_lock);
-	if (!pgsb_ctx->do_we_need_wake_source)
-	{
-		IPC_TRACE_LOW("Acquiring wake src\n");
-		pgsb_ctx->do_we_need_wake_source = true;
-		pgsb_ctx->wake_source_ref_count++;
-	}
-	else
-	{
-		pgsb_ctx->wake_source_ref_count++;
-		IPC_TRACE_LOW("Wake source count %d\n",
-				pgsb_ctx->wake_source_ref_count);
-	}
-	spin_unlock_bh(&pgsb_ctx->gsb_wake_lock);
-}
-
-static void acquire_caller(const char *func_name, u32 line_no)
-{
-	DEBUG_TRACE("%s[%u], calling acquire_wake_source \n", func_name, line_no);
-	acquire_wake_source();
-}
-
-static void release_caller(const char *func_name, u32 line_no)
-{
-	DEBUG_TRACE("%s[%u], calling release_wake_source\n", func_name, line_no);
-	release_wake_source();
-}
-
-#define acquire_wake_source() acquire_caller(__func__, __LINE__)
-#define release_wake_source() release_caller(__func__, __LINE__)
-
-static void suspend_task(struct work_struct *work)
-{
-	DEBUG_TRACE("suspending all interfaces\n");
-	if (suspend_all_bridged_interfaces() != 0)
-	{
-		DEBUG_ERROR("Could not suspend\n");
-	}
-}
-
-static struct timer_list INACTIVITY_TIMER;
-
-static void dump_packet_util(const struct sk_buff *skb)
-{
-	char buffer[PACKET_DUMP_BUFFER];
-	unsigned int len, printlen;
-	int i, buffloc = 0;
-	if (skb == NULL || skb->dev == NULL || skb->dev->name == NULL)
-	{
-		DEBUG_ERROR("Cannot dump this packet\n");
-		return;
-	}
-	DEBUG_TRACE("dumping packet.....\n");
-	DUMP_PACKET("[%s] - PKT skb->len=%d skb->head=%pK skb->data=%pK\n",
-			skb->dev->name, skb->len, (void *)skb->head, (void *)skb->data);
-	DUMP_PACKET("[%s] - PKT skb->tail=%pK skb->end=%pK\n",
-			skb->dev->name,  skb_tail_pointer(skb), skb_end_pointer(skb));
-	printlen = PACKET_MP_PRINT_LEN;
-	if (skb->len > 0) len = skb->len;
-	else len = ((unsigned int)(uintptr_t)skb->end) -
-			((unsigned int)(uintptr_t)skb->data);
-
-	DUMP_PACKET("[%s]- PKT len: %d, printing first %d bytes\n",
-			skb->dev->name, len, printlen);
-
-	memset(buffer, 0, sizeof(buffer));
-	for (i = 0; (i < printlen) && (i < len); i++)
-	{
-		if ((i % 16) == 0)
-		{
-			DUMP_PACKET("[%s]- PKT %s\n", skb->dev->name, buffer);
-			memset(buffer, 0, sizeof(buffer));
-			buffloc = 0;
-			buffloc += snprintf(&buffer[buffloc],
-						sizeof(buffer) - buffloc, "%04X:",
-						i);
-		}
-
-		buffloc += snprintf(&buffer[buffloc], sizeof(buffer) - buffloc,
-					" %02x", skb->data[i]);
-	}
-	DUMP_PACKET("[%s]- PKT%s\n", skb->dev->name, buffer);
-}
-
-static void schedule_inactivity_timer(const unsigned int time_in_ms)
-{
-	struct gsb_ctx *pgsb_ctx = __gc;
-	if (NULL == pgsb_ctx)
-	{
-		IPC_ERROR_LOW("Context is NULL\n");
-		return;
-	}
-
-	IPC_TRACE_LOW("fire in 200ms (%ld)\n", jiffies);
-	mod_timer(&INACTIVITY_TIMER, jiffies + msecs_to_jiffies(time_in_ms));
-	spin_lock_bh(&pgsb_ctx->gsb_lock);
-	pgsb_ctx->inactivity_timer_scheduled = true;
-	spin_unlock_bh(&pgsb_ctx->gsb_lock);
-}
-
-static int suspend_all_bridged_interfaces(void)
-{
-	struct gsb_if_info *curr;
-	struct hlist_node *tmp;
-	int bkt;
-	struct gsb_ctx *pgsb_ctx = __gc;
-	if (NULL == pgsb_ctx)
-	{
-		DEBUG_ERROR("Context is NULL\n");
-		return -EFAULT;
-	}
-
-	hash_for_each_safe(pgsb_ctx->cache_htable_list, bkt, tmp, curr, cache_ht_node)
-	{
-		spin_lock_bh(&pgsb_ctx->gsb_lock);
-		if (!curr->is_ipa_bridge_suspended)
-		{
-			spin_unlock_bh(&pgsb_ctx->gsb_lock);
-
-			if (ipa_bridge_suspend(curr->handle) != 0)
-			{
-				DEBUG_ERROR("failed to suspend if %s\n", curr->if_name);
-				return -EFAULT;
-			}
-			else
-			{
-				DEBUG_TRACE("if %s suspended\n", curr->if_name);
-				spin_lock_bh(&pgsb_ctx->gsb_lock);
-				curr->is_ipa_bridge_suspended = true;
-				curr->if_ipa->stats.ipa_suspend_cnt++;
-				spin_unlock_bh(&pgsb_ctx->gsb_lock);
-			}
-		}
-		else
-		{
-			spin_unlock_bh(&pgsb_ctx->gsb_lock);
-		}
-	}
-
-	// we are good as all if are suspended ...so relax if wake source was acquired
-	spin_lock_bh(&pgsb_ctx->gsb_wake_lock);
-	pgsb_ctx->do_we_need_wake_source = false;
-	if (pgsb_ctx->is_wake_src_acquired)
-	{
-		DEBUG_TRACE("relaxing wake src\n");
-		__pm_relax(&pgsb_ctx->gsb_wake_src);
-		pgsb_ctx->is_wake_src_acquired = false;
-	}
-	else
-	{
-		DEBUG_TRACE("no wake src acquired to relax\n");
-	}
-	spin_unlock_bh(&pgsb_ctx->gsb_wake_lock);
-	return 0;
-}
-
-
-static void inactivity_timer_cb(unsigned long data)
-{
-	struct gsb_ctx *pgsb_ctx = __gc;
-
-	if (IS_ERR_OR_NULL(pgsb_ctx))
-	{
-		DEBUG_ERROR("NULL GSB Context passed\n");
-		return;
-	}
-	DEBUG_TRACE("GSB Inactivity timer expired (%ld)\n", jiffies);
-	spin_lock_bh(&pgsb_ctx->gsb_lock);
-	if (pgsb_ctx->inactivity_timer_scheduled)
-	{
-		pgsb_ctx->inactivity_timer_scheduled = false;
-		spin_unlock_bh(&pgsb_ctx->gsb_lock);
-
-		DEBUG_TRACE("no data activity for 200 ms..suspending bridged interfaces\n");
-		schedule_delayed_work(&if_suspend_wq, 0);
-		return;
-	}
-	spin_unlock_bh(&pgsb_ctx->gsb_lock);
-}
-
-static bool is_ipv4_pkt(struct sk_buff *skb)
-{
-	return ((htons(ETH_P_IP) == skb->protocol));
-}
-
-static bool is_ipv6_pkt(struct sk_buff *skb)
-{
-	return ((htons(ETH_P_IPV6) == skb->protocol));
-}
-
-static bool is_non_ip_pkt(struct sk_buff *skb)
-{
-	return (!is_ipv4_pkt(skb) && !is_ipv6_pkt(skb));
-}
-
-static void remove_padding(struct sk_buff *skb, bool ipv4, bool ipv6)
-{
-	if (ipv4)
-	{
-		struct iphdr *ip_hdr = NULL;
-		ip_hdr = (struct iphdr *)(skb_mac_header(skb) + ETH_HLEN);
-		skb_trim(skb, ntohs(ip_hdr->tot_len) + ETH_HLEN);
-	}
-	else if (ipv6)
-	{
-		struct ipv6hdr *ip6_hdr = NULL;
-		ip6_hdr = (struct ipv6hdr *)(skb_mac_header(skb) + ETH_HLEN);
-		skb_trim(skb, ntohs(ip6_hdr->payload_len) + sizeof(struct ipv6hdr) + ETH_HLEN);
-	}
-}
-
-
-static void release_pending_packets_exp(struct gsb_if_info *if_info)
-{
-	struct sk_buff *skb;
-	struct if_ipa_ctx *pipa_ctx = if_info->if_ipa;
-	int retval = 0;
-
-
-	spin_lock_bh(&if_info->flow_ctrl_lock);
-	while (if_info->pend_queue.qlen)
-	{
-		skb = __skb_dequeue(&if_info->pend_queue);
-		if (IS_ERR_OR_NULL(skb))
-		{
-			DEBUG_ERROR("null skb\n");
-			BUG();
-			break;
-		}
-		//Send Packet to NW stack
-		retval = netif_rx_ni(skb);
-		if (retval != NET_RX_SUCCESS)
-		{
-			DEBUG_ERROR("ERROR sending to nw stack %d\n", retval);
-			dev_kfree_skb(skb);
-			pipa_ctx->stats.exp_if_disconnected_fail++;
-		}
-		else
-		{
-			pipa_ctx->stats.exp_if_disconnected++;
-		}
-	}
-	spin_unlock_bh(&if_info->flow_ctrl_lock);
-}
-
-
-static void flush_pending_packets(struct gsb_if_info *if_info)
-{
-	DEBUG_TRACE("Flush %d Pending UL Packets \n", if_info->pend_queue.qlen);
-	skb_queue_purge(&if_info->pend_queue);
-}
-
-
-static  bool is_ip_frag_pkt(struct sk_buff *skb)
-{
-	struct iphdr *ip_hdr = NULL;
-	ip_hdr = (struct iphdr *)(skb_mac_header(skb) + ETH_HLEN);
-
-	/* Return true if: 'More_Frag bit is set' OR
-		'Fragmentation Offset is set' */
-	if (ip_hdr->frag_off & htons(IP_MF | IP_OFFSET)) return true;
-	return false;
-}
-
-
-static  ssize_t gsb_read_stats(struct file *file,
-				char __user *user_buf, size_t count, loff_t *ppos)
-{
-	ssize_t ret_cnt = 0;
-	unsigned int len = 0, buf_len = 2000;
-	char *buf;
-	u16 pendq_cnt, ipa_free_desc_cnt;
-	u16 max_pkts_allowed, min_pkts_allowed;
-	uint64_t schedule_cnt = 0;
-	uint64_t idle_cnt = 0;
-	uint64_t pending_wde = 0;
-	u16 wake_ref_cnt;
-	uint64_t inactivity_sceduled = 0;
-	uint64_t inactivity_cancelled = 0;
-	bool is_suspended;
-	char file_name[PATH_MAX];
-	struct gsb_ctx *pgsb_ctx = __gc;
-	struct gsb_if_info *if_info = NULL;
-	char *raw_path = NULL;
-
-	if (IS_ERR_OR_NULL(pgsb_ctx))
-	{
-		DEBUG_ERROR("NULL GSB Context passed\n");
-		return ret_cnt;
-	}
-
-	raw_path = dentry_path_raw(file->f_path.dentry, file_name, PATH_MAX);
-	DEBUG_TRACE("rawpath  is %s\n", raw_path);
-	if (IS_ERR_OR_NULL(raw_path))
-	{
-		DEBUG_ERROR("NULL path found\n");
-		return ret_cnt;
-	}
-
-
-	spin_lock_bh(&pgsb_ctx->gsb_lock);
-	if_info = get_node_info_from_ht(raw_path + READ_STATS_OFFSET);
-	spin_unlock_bh(&pgsb_ctx->gsb_lock);
-
-
-	if (if_info == NULL)
-	{
-		DEBUG_ERROR("Could not find if node for stats\n");
-		return ret_cnt;
-	}
-
-	if (!if_info->is_debugfs_init)
-	{
-		DEBUG_ERROR("debugfs not initialized for %s\n", if_info->if_name);
-		return ret_cnt;
-	}
-
-	buf = kzalloc(MAX_BUFF_LEN, GFP_KERNEL);
-	if (!buf) return -ENOMEM;
-	pgsb_ctx->mem_alloc_read_stats_buffer++;
-
-	/* stats buffer*/
-	len += scnprintf(buf + len, buf_len - len, "\n \n");
-	len += scnprintf(buf + len, buf_len - len, "GSB stats for %s if\n",
-			if_info->if_name);
-	len += scnprintf(buf + len, buf_len - len, "%35s\n\n",
-			"==================================================");
-
-	len += scnprintf(buf + len, buf_len - len, "%35s %10llu\n",
-			"Total recv from if",
-			if_info->if_ipa->stats.total_recv_from_if);
-	len += scnprintf(buf + len, buf_len - len, "%35s %10llu\n",
-			"sent to ipa",
-			if_info->if_ipa->stats.sent_to_ipa);
-	len += scnprintf(buf + len, buf_len - len, "%35s %10llu\n",
-			"drop, sent to ipa fail",
-			if_info->if_ipa->stats.drop_send_to_ipa_fail);
-	len += scnprintf(buf + len, buf_len - len, "%35s %10llu\n",
-			"exp,ipa not connected",
-			if_info->if_ipa->stats.exception_ipa_not_connected);
-	len += scnprintf(buf + len, buf_len - len, "%35s %10llu\n",
-			"exp,if is suspended",
-			if_info->if_ipa->stats.exp_ipa_suspended);
-	len += scnprintf(buf + len, buf_len - len, "%35s %10llu\n",
-			"exp,insufficient hr",
-			 if_info->if_ipa->stats.exp_insufficient_hr);
-	len += scnprintf(buf + len, buf_len - len, "%35s %10llu\n",
-			"drop, congestion",
-			if_info->if_ipa->stats.drop_flow_control_bottleneck);
-	len += scnprintf(buf + len, buf_len - len, "%35s %10llu\n",
-			"exp, fragmented",
-			if_info->if_ipa->stats.exception_fragmented);
-	len += scnprintf(buf + len, buf_len - len, "%35s %10llu\n",
-			"exp, non ip packet",
-			if_info->if_ipa->stats.exception_non_ip_packet);
-	len += scnprintf(buf + len, buf_len - len, "%35s %10llu\n",
-			"IPA exp to stack fail",
-			if_info->if_ipa->stats.exp_packet_from_ipa_fail);
-	len += scnprintf(buf + len, buf_len - len, "%35s %10llu\n",
-			"exp, if down",
-			 if_info->if_ipa->stats.exp_if_disconnected);
-	len += scnprintf(buf + len, buf_len - len, "%35s %10llu\n",
-			"exp, if down fail",
-			 if_info->if_ipa->stats.exp_if_disconnected_fail);
-	len += scnprintf(buf + len, buf_len - len, "%35s %10llu\n",
-			"TX,sent to if",
-			if_info->if_ipa->stats.tx_send_to_if);
-	len += scnprintf(buf + len, buf_len - len, "%35s %10llu\n",
-			"TX,sent to if fail",
-			if_info->if_ipa->stats.tx_send_err);
-	len += scnprintf(buf + len, buf_len - len, "%35s %10llu\n",
-			"Writedone from IPA",
-			if_info->if_ipa->stats.write_done_from_ipa);
-	len += scnprintf(buf + len, buf_len - len, "%35s %10llu\n",
-			"IPA exp packet",
-			if_info->if_ipa->stats.exception_packet_from_ipa);
-	len += scnprintf(buf + len, buf_len - len, "%35s %10llu\n",
-			"flow control below low wm",
-			if_info->if_ipa->stats.ipa_low_watermark_cnt);
-
-
-
-	spin_lock_bh(&if_info->flow_ctrl_lock);
-	pendq_cnt = if_info->pend_queue.qlen;
-	ipa_free_desc_cnt = if_info->ipa_free_desc_cnt;
-	max_pkts_allowed = if_info->max_q_len_in_gsb;
-	min_pkts_allowed = if_info->low_watermark;
-	schedule_cnt = if_info->wq_schedule_cnt;
-	idle_cnt = if_info->idle_cnt;
-	pending_wde = if_info->if_ipa->ipa_rx_completion;
-	spin_unlock_bh(&if_info->flow_ctrl_lock);
-
-	len += scnprintf(buf + len, buf_len - len, "\n \n");
-
-	len += scnprintf(buf + len, buf_len - len, "%35s %10u\n",
-			"current Queue len: ", pendq_cnt);
-	len += scnprintf(buf + len, buf_len - len, "%35s %10llu\n",
-			"Pending wde: ", pending_wde);
-	len += scnprintf(buf + len, buf_len - len, "%35s %10u\n",
-			"Free ipa desc Count: ", ipa_free_desc_cnt);
-	len += scnprintf(buf + len, buf_len - len, "%35s %10u\n",
-			"max queue len: ", max_pkts_allowed);
-	len += scnprintf(buf + len, buf_len - len, "%35s %10u\n",
-			"Low Watermark: ", min_pkts_allowed);
-	len += scnprintf(buf + len, buf_len - len, "%35s %10llu\n",
-			"send schedule cnt: ", schedule_cnt);
-
-
-
-	spin_lock_bh(&pgsb_ctx->gsb_wake_lock);
-	is_suspended = if_info->is_ipa_bridge_suspended;
-	spin_unlock_bh(&pgsb_ctx->gsb_wake_lock);
-
-	len += scnprintf(buf + len, buf_len - len, "%35s %10u\n",
-			"is data src available?",
-			!is_suspended);
-	len += scnprintf(buf + len, buf_len - len, "\n \n");
-	len += scnprintf(buf + len, buf_len - len, "%35s %10u\n",
-			"is wake source acquired: ", pgsb_ctx->is_wake_src_acquired);
-
-	if (len > MAX_BUFF_LEN) len = MAX_BUFF_LEN;
-
-	ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
-	kfree(buf);
-	pgsb_ctx->mem_alloc_read_stats_buffer--;
-	return ret_cnt;
-}
-
-static const struct file_operations debug_fops = {
-	.read = gsb_read_stats,
-	.open = simple_open,
-	.owner = THIS_MODULE,
-	.llseek = default_llseek,
-};
-
-static int gsb_debugfs_init(struct gsb_ctx *gsb_cx)
-{
-	if (IS_ERR_OR_NULL(gsb_cx))
-	{
-		DEBUG_ERROR("NULL Context passed\n");
-		return -ENOMEM;
-	}
-
-	gsb_cx->dbg_dir_root = debugfs_create_dir(gsb_drv_name, NULL);
-	if (IS_ERR_OR_NULL(gsb_cx->dbg_dir_root))
-	{
-		DEBUG_ERROR("Failed to create debugfs dir\n");
-		return -ENOMEM;
-	}
-	return 0;
-}
-
-static int create_debugfs_dir_for_if(struct gsb_if_info *if_info)
-{
-	struct gsb_ctx *pgsb_ctx = __gc;
-
-	if (IS_ERR_OR_NULL(pgsb_ctx))
-	{
-		DEBUG_ERROR("NULL GSB Context passed\n");
-		return -EFAULT;
-	}
-
-	if (IS_ERR_OR_NULL(if_info))
-	{
-		DEBUG_ERROR("NULL if Context passed\n");
-		return -EFAULT;
-	}
-
-	if_info->dbg_dir_if = debugfs_create_file(if_info->if_name, S_IRUSR, pgsb_ctx->dbg_dir_root,
-						  pgsb_ctx, &debug_fops);
-	if (IS_ERR_OR_NULL(if_info->dbg_dir_if))
-	{
-		DEBUG_ERROR("Could not create debugfs dir for if %s\n",
-				if_info->if_name);
-		return -EFAULT;
-	}
-	if_info->is_debugfs_init = true;
-	return 0;
-}
-
-static void remove_debugfs_dir_for_if(struct dentry *entry)
-{
-	if (IS_ERR_OR_NULL(entry))
-	{
-		DEBUG_ERROR("NULL entry  passed\n");
-		return;
-	}
-
-	debugfs_remove(entry);
-}
-
-static void gsb_debugfs_exit(struct gsb_ctx *gsb_cx)
-{
-	if (IS_ERR_OR_NULL(gsb_cx))
-	{
-		DEBUG_ERROR("NULL Context passed\n");
-		return;
-	}
-
-	if (!gsb_cx->dbg_dir_root) return;
-
-	debugfs_remove_recursive(gsb_cx->dbg_dir_root);
-}
-
-
-static u32 get_ht_Key(char *str)
-{
-	u32 num = StringtoAscii(str);
-	u32 key  = hash_32(num, NBITS(MAX_SUPPORTED_IF_CONFIG));
-	return key;
-}
-
-struct gsb_if_info* get_node_info_from_ht(char *iface)
-{
-	struct gsb_ctx *pgsb_ctx = __gc;
-	struct gsb_if_info *curr = NULL;
-	u32 key;
-
-	if (NULL == pgsb_ctx)
-	{
-		IPC_ERROR_LOW("Context is NULL\n");
-		return NULL;
-	}
-	key = get_ht_Key(iface);
-	IPC_TRACE_LOW("key %d\n", key);
-	hash_for_each_possible(pgsb_ctx->cache_htable_list, curr, cache_ht_node, key)
-	{
-		IPC_TRACE_LOW("ht iface %s , passed iface %s\n", curr->user_config.if_name,
-				iface);
-		if (strncmp(curr->user_config.if_name,
-				iface,
-				IFNAMSIZ) == 0)
-		{
-			IPC_TRACE_LOW("config found\n");
-			return curr;
-		}
-	}
-
-	IPC_TRACE_LOW("config not found\n");
-	return curr;
-}
-
-
-static int remove_entry_from_ht(struct gsb_if_config *info)
-{
-	u32 key;
-	struct gsb_ctx *pgsb_ctx = __gc;
-	struct gsb_if_info *curr;
-
-	if (NULL == pgsb_ctx)
-	{
-		DEBUG_ERROR("Context is NULL\n");
-		return -EFAULT;
-	}
-	key = get_ht_Key(info->if_name);
-	hash_for_each_possible(pgsb_ctx->cache_htable_list, curr, cache_ht_node, key)
-	{
-		DEBUG_TRACE("ht iface %s , passed iface %s\n", curr->if_name,
-				info->if_name);
-		if (strncmp(curr->if_name,
-				info->if_name,
-				IFNAMSIZ) == 0)
-		{
-			hash_del(&curr->cache_ht_node);
-			return 0;
-		}
-	}
-	DEBUG_TRACE("config not found\n");
-	return -ENODEV;
-}
-
-static int cleanup_entries_from_ht(void)
-{
-	struct gsb_ctx *pgsb_ctx = __gc;
-	struct gsb_if_info *curr;
-	struct hlist_node *tmp;
-	int bkt;
-
-	if (NULL == pgsb_ctx)
-	{
-		DEBUG_ERROR("Context is NULL\n");
-		return -EFAULT;
-	}
-
-	hash_for_each_safe(pgsb_ctx->cache_htable_list, bkt, tmp, curr, cache_ht_node)
-	{
-		DEBUG_TRACE("removing iface %s\n", curr->if_name);
-		/* first disconnect this IF from IPA*/
-		if (curr->is_connected_to_ipa_bridge &&
-			ipa_bridge_disconnect(curr->handle) == 0)
-		{
-			spin_lock_bh(&pgsb_ctx->gsb_lock);
-			curr->is_connected_to_ipa_bridge = false;
-			curr->is_ipa_bridge_suspended = true;
-			curr->if_ipa->stats.ipa_suspend_cnt++;
-			spin_unlock_bh(&pgsb_ctx->gsb_lock);
-			flush_pending_packets(curr);
-			cancel_work_sync(&curr->ipa_resume_task);
-			cancel_work_sync(&curr->ipa_send_task);
-			release_wake_source();
-			DEBUG_INFO("IPA bridge dis connected for if %s",
-					curr->if_name);
-		}
-
-		/* delete IF from cache*/
-		spin_lock_bh(&pgsb_ctx->gsb_lock);
-		hash_del(&curr->cache_ht_node);
-		spin_unlock_bh(&pgsb_ctx->gsb_lock);
-
-		remove_debugfs_dir_for_if(curr->dbg_dir_if);
-
-		if (curr->is_ipa_bridge_initialized && ipa_bridge_cleanup(curr->handle) != 0)
-		{
-			DEBUG_ERROR("issue in cleaning up IPA bridge for if %s\n",
-					curr->if_name);
-		}
-
-		kfree(curr->if_ipa);
-		pgsb_ctx->mem_alloc_if_ipa_context--;
-		kfree(curr);
-
-		spin_lock_bh(&pgsb_ctx->gsb_lock);
-		pgsb_ctx->mem_alloc_if_node--;
-		pgsb_ctx->configured_if_count--;
-		spin_unlock_bh(&pgsb_ctx->gsb_lock);
-	}
-
-	DEBUG_TRACE("HT cleanup complete\n");
-	return 0;
-}
-
-
-static int add_entry_to_ht(struct gsb_if_info *info)
-{
-	u32 key;
-	struct gsb_ctx *pgsb_ctx = __gc;
-	struct gsb_if_info *curr;
-
-	if (NULL == pgsb_ctx)
-	{
-		DEBUG_ERROR("Context is NULL\n");
-		return -EFAULT;
-	}
-
-
-	INIT_HLIST_NODE(&info->cache_ht_node);
-	key = get_ht_Key(info->if_name);
-
-	DEBUG_TRACE("key %d\n", key);
-	hash_for_each_possible(pgsb_ctx->cache_htable_list, curr, cache_ht_node, key)
-	{
-		if (strncmp(curr->if_name,
-				info->if_name,
-				IFNAMSIZ) == 0)
-			{
-				DEBUG_ERROR("config already present\n");
-				return -EEXIST;
-			}
-	}
-	DEBUG_TRACE("config not found\n");
-	key = get_ht_Key(info->if_name);
-	DEBUG_TRACE("key %d\n", key);
-
-	info->is_connected_to_ipa_bridge = false;
-	info->is_ipa_bridge_initialized = false;
-	hash_add(pgsb_ctx->cache_htable_list, &info->cache_ht_node, key);
-	return 0;
-}
-
-static void display_cache(void)
-{
-	struct gsb_if_info *curr;
-	struct hlist_node *tmp;
-	int bkt;
-	struct gsb_ctx *pgsb_ctx = __gc;
-	if (NULL == pgsb_ctx)
-		{
-		DEBUG_ERROR("Context is NULL\n");
-		return;
-		}
-
-	hash_for_each_safe(pgsb_ctx->cache_htable_list, bkt, tmp, curr, cache_ht_node)
-	{
-		DEBUG_INFO("gsb iface %s,iface type %d,low wm %d,high wm %d,bw reqd %d\n\n",
-				curr->if_name,
-				curr->user_config.if_type,
-				curr->user_config.if_low_watermark,
-				curr->user_config.if_high_watermark,
-				curr->user_config.bw_reqd_in_mb);
-	}
-}
-
-static void gsb_recv_ipa_notification_cb(void *priv, enum ipa_dp_evt_type evt,
-					 unsigned long data)
-{
-	int retval = 0;
-	struct gsb_ctx *pgsb_ctx = __gc;
-	struct gsb_if_info *if_info = (struct gsb_if_info *)priv;
-	struct if_ipa_ctx *pipa_ctx = if_info->if_ipa;
-	struct sk_buff *skb = (struct sk_buff *)data;
-	u32 qlen = 0;
-
-	if (NULL == pgsb_ctx)
-	{
-		IPC_ERROR_LOW("Context is NULL\n");
-		dev_kfree_skb(skb);
-		return;
-	}
-
-	if (if_info == NULL)
-	{
-		IPC_ERROR_LOW("config not available \n");
-		dev_kfree_skb(skb);
-		return;
-	}
-
-	if (!if_info->is_connected_to_ipa_bridge)
-	{
-		IPC_ERROR_LOW("called before IPA_CONNECT was called with evt %d \n", evt);
-		dev_kfree_skb(skb);
-		return;
-	}
-
-	IPC_TRACE_LOW("EVT Rcvd %d for if %s \n", evt, if_info->if_name);
-	switch (evt)
-	{
-	case IPA_RECEIVE:
-
-		/* Deliver SKB to network adapter */
-		//IPA may have returned our skb back to us
-		//Lets make sure we tag it so we dont intercept it in stack
-
-		if (skb->cb[0] == '\0')
-		{
-			strlcpy(skb->cb, "isthisloop", ((sizeof(skb->cb)) / (sizeof(skb->cb[0]))));
-			IPC_TRACE_LOW("tagging skb with string %s, skbp= %pK\n", skb->cb, skb);
-		}
-		else
-		{
-			IPC_TRACE_LOW("skb is already tagged %s skbp= %pK\n", skb->cb, skb);
-		}
-
-
-		skb->dev = if_info->pdev;
-		skb->protocol = eth_type_trans(skb, skb->dev);
-
-		//to do need to optimize this
-		retval = netif_rx_ni(skb);
-		if (retval != NET_RX_SUCCESS)
-		{
-			IPC_ERROR_LOW("ERROR sending to nw stack %d\n", retval);
-			pipa_ctx->stats.exp_packet_from_ipa_fail++;
-		}
-		else
-		{
-			pipa_ctx->stats.exception_packet_from_ipa++;
-		}
-
-		break;
-
-	case IPA_WRITE_DONE:
-		/* SKB send to IPA, safe to free */
-		dev_kfree_skb(skb);
-
-		pgsb_ctx->mem_alloc_skb_free++;
-		pipa_ctx->stats.write_done_from_ipa++;
-
-
-		spin_lock_bh(&if_info->flow_ctrl_lock);
-		qlen = if_info->pend_queue.qlen;
-		if_info->ipa_free_desc_cnt++;
-		pipa_ctx->ipa_rx_completion--;
-		spin_unlock_bh(&if_info->flow_ctrl_lock);
-
-
-		if (!pipa_ctx->ipa_rx_completion && !qlen)
-		{
-			//seems like this interface is free of activity
-			IPC_TRACE_LOW("idle if %s\n", if_info->if_name);
-			if_info->idle_cnt++;
-			release_wake_source();
-		}
-		else
-		{
-			if (if_info->ipa_free_desc_cnt > if_info->low_watermark)
-			{
-				queue_work(gsb_wq, &if_info->ipa_send_task);
-			}
-			else
-			{
-				if_info->if_ipa->stats.ipa_low_watermark_cnt++;
-			}
-		}
-		break;
-
-	default:
-		IPC_ERROR_LOW("Invalid %d event from IPA\n", evt);
-		break;
-	}
-}
-
-//to do : we can be 100% sure that we will have wake src
-//while we are in this routine. resume will aqcuire or _bind_ will acquire
-
-/*
-Scenario 1: Inactivity timer was expired..if was suspended, resume call back will acquire wake source in that case ..no action reqd
-Scenario 2: Inactivity timer is been scheduled
-
-*/
-static void gsb_recv_dl_dp(void *priv, struct sk_buff *skb)
-{
-	struct gsb_ctx *pgsb_ctx = __gc;
-	bool is_inactivity_timer_cancelled = false;
-	struct gsb_if_info *if_info = (struct gsb_if_info *)priv;
-
-	if (NULL == if_info)
-	{
-		IPC_ERROR_LOW("if info is NULL, freed?\n");
-		dev_kfree_skb(skb);
-		BUG();
-		return;
-	}
-
-	if (!if_info->net_dev_state)
-	{
-		IPC_ERROR_LOW("%s interface does not exist\n",
-				if_info->user_config.if_name);
-		dev_kfree_skb(skb);
-		return;
-	}
-
-	if (NULL == pgsb_ctx)
-	{
-		IPC_ERROR_LOW("Context is NULL\n");
-		dev_kfree_skb(skb);
-		return;
-	}
-
-	if (skb == NULL)
-	{
-		IPC_ERROR_LOW("skb is NULL\n");
-		dev_kfree_skb(skb);
-		return;
-	}
-
-	if (skb->dev == NULL)
-	{
-		skb->dev = if_info->pdev;
-	}
-
-	// cancel inactivity timer ...if scheduled
-	if (pgsb_ctx->inactivity_timer_scheduled)
-	{
-		acquire_wake_source();
-		spin_lock_bh(&pgsb_ctx->gsb_lock);
-		pgsb_ctx->inactivity_timer_scheduled = false;
-		is_inactivity_timer_cancelled = true;
-		pgsb_ctx->inactivity_timer_cancelled_cnt++;
-		spin_unlock_bh(&pgsb_ctx->gsb_lock);
-	}
-
-
-	if (dev_queue_xmit(skb) != 0)
-	{
-		IPC_ERROR_LOW("could not forward the packet\n");
-		if_info->if_ipa->stats.tx_send_err++;
-		if (is_inactivity_timer_cancelled)
-		{
-			release_wake_source();
-		}
-		return;
-	}
-	else
-	{
-		IPC_TRACE_LOW("Downlink data was forwarded successfully\n");
-	}
-
-	if_info->if_ipa->stats.tx_send_to_if++;
-
-	if (is_inactivity_timer_cancelled)
-	{
-		release_wake_source();
-	}
-}
-
-
-static void gsb_wakeup_cb(void *ptr)
-{
-	struct gsb_if_info *if_info = (struct gsb_if_info *)ptr;
-	if (if_info == NULL)
-	{
-		DEBUG_ERROR("NULL node acquired\n");
-		BUG();
-		return;
-	}
-	queue_work(gsb_wq, &if_info->ipa_resume_task);
-}
-
-static int gsb_ipa_set_perf_level(struct gsb_if_info *if_info)
-{
-	int retval = 0;
-	retval = ipa_bridge_set_perf_profile(if_info->handle, if_info->user_config.bw_reqd_in_mb);
-	if (retval)
-	{
-		DEBUG_ERROR("could not set perf requirement with IPA %d\n", retval);
-		return retval;
-	}
-	return retval;
-}
-
-static int gsb_bind_if_to_ipa_bridge(struct gsb_if_info *if_info)
-{
-	struct ipa_bridge_init_params *params_ptr;
-	struct ipa_bridge_init_params params;
-	struct gsb_ctx *pgsb_ctx = __gc;
-	int retval = 0;
-
-
-	if (NULL == pgsb_ctx)
-	{
-		DEBUG_ERROR("Context is NULL\n");
-		return -EFAULT;
-	}
-
-	params_ptr = &params;
-	if (!params_ptr)
-	{
-		return -ENOMEM;
-	}
-
-	/* If IPA bridge is already initizliaed, clean up. */
-	if (if_info->is_ipa_bridge_initialized)
-	{
-		if (ipa_bridge_cleanup(if_info->handle) != 0)
-		{
-			DEBUG_ERROR("issue in cleaning up IPA bridge for if %s\n",
-					if_info->if_name);
-			return -EFAULT;
-		}
-		else
-		{
-			/* Reset the flag. */
-			if_info->is_ipa_bridge_initialized = false;
-		}
-	}
-
-	/* Initialize the IPA bridge driver */
-	params_ptr->info.netdev_name = if_info->user_config.if_name;
-	params_ptr->info.priv             = if_info;
-	params_ptr->info.tx_dp_notify     = gsb_recv_ipa_notification_cb;
-	params_ptr->info.send_dl_skb      = (void *)&gsb_recv_dl_dp;
-	params_ptr->info.ipa_desc_size    = (if_info->ipa_free_desc_cnt + 1) *
-		sizeof(struct sps_iovec);
-	//to do: fix mac address
-	switch (if_info->pdev->addr_assign_type)
-	{
-	case NET_ADDR_PERM:
-		memcpy(params_ptr->info.device_ethaddr, if_info->pdev->perm_addr, ETH_ALEN);
-		DEBUG_INFO("NET_ADDR_PERM assigned \n");
-		break;
-
-	case NET_ADDR_RANDOM:
-		DEBUG_TRACE("NET_ADDR_RANDOM assigned\n");
-		break;
-	case NET_ADDR_STOLEN:
-		DEBUG_TRACE("NET_ADDR_STOLEN  assigned\n");
-		break;
-	case NET_ADDR_SET:
-		memcpy(params_ptr->info.device_ethaddr, if_info->pdev->dev_addr, ETH_ALEN);
-		DEBUG_INFO("NET_ADDR_SET assigned\n");
-		break;
-
-	default:
-		DEBUG_TRACE("Invalid assign type\n");
-		return -EFAULT;
-		break;
-	}
-
-	params_ptr->wakeup_request = (void *)&gsb_wakeup_cb;
-
-	retval = ipa_bridge_init(params_ptr, &if_info->handle);
-	if (retval != 0)
-	{
-		DEBUG_ERROR("Couldnt initialize ipa bridge Driver\n");
-		return -EFAULT;
-	}
-
-	spin_lock_bh(&pgsb_ctx->gsb_lock);
-	if_info->is_ipa_bridge_initialized = true;
-	spin_unlock_bh(&pgsb_ctx->gsb_lock);
-
-	if (gsb_ipa_set_perf_level(if_info) != 0)
-	{
-		DEBUG_ERROR("Cannot set perf requirement for if %s\n",
-				if_info->if_name);
-		return -EFAULT;
-
-	}
-
-	spin_lock_init(&if_info->flow_ctrl_lock);
-	if_info->flow_ctrl_lock_acquired = false;
-
-	skb_queue_head_init(&if_info->pend_queue);
-
-	retval = ipa_bridge_connect(if_info->handle);
-	if (retval != 0)
-	{
-		DEBUG_ERROR("ipa bridge connect failed for if %s \n",
-				if_info->if_name);
-		return -EFAULT;
-	}
-
-	//protect these flags & ref counters
-	spin_lock_bh(&pgsb_ctx->gsb_lock);
-	if_info->is_connected_to_ipa_bridge = true;
-	if_info->is_ipa_bridge_suspended = false;
-	if_info->net_dev_state = true;
-	spin_unlock_bh(&pgsb_ctx->gsb_lock);
-
-	INIT_WORK(&if_info->ipa_send_task, gsb_ipa_send_routine);
-	INIT_WORK(&if_info->ipa_resume_task, gsb_ipa_resume_routine);
-
-	DEBUG_INFO("GSB<->IPA bind completed for if %s, MAC:  %X:%X:%X:%X:%X:%X \n",
-			if_info->if_name, MAC_ADDR_ARRAY(if_info->pdev->perm_addr));
-
-	/*Idea is if there is no activity for this if
-	after it was registered, then we should suspend.
-	following code will trigger ianctivity timer if this
-	is only interface and there is no activity*/
-	acquire_wake_source();
-	release_wake_source();
-	return retval;
-	}
-
-static long gsb_ioctl(struct file *filp,
-			unsigned int cmd,
-			unsigned long arg)
-{
-	int retval = 0;
-	u32 payload_size;
-	struct gsb_ctx *pgsb_ctx = NULL;
-	struct gsb_if_config *config = NULL;
-	struct gsb_if_info *info = NULL;
-	struct if_ipa_ctx *pif_ipa = NULL;
-
-
-	if (__gc != NULL)
-	{
-		pgsb_ctx = __gc;
-	}
-	else
-	{
-		DEBUG_ERROR("Null Context, cannot execute IOCTL\n");
-	}
-
-	switch (cmd)
-	{
-	case GSB_IOC_ADD_IF_CONFIG:
-		DEBUG_TRACE("device %s got GSB_IOC_ADD_IF_CONFIG\n",
-				gsb_drv_name);
-		payload_size = sizeof(struct gsb_if_config);
-		config = kzalloc(payload_size, GFP_KERNEL);
-		if (!config)
-		{
-			DEBUG_ERROR("issue allocating ioctl buffer\n");
-			return -ENOMEM;
-		}
-		pgsb_ctx->mem_alloc_ioctl_buffer++;
-
-		if (copy_from_user(config, (struct gsb_if_config *)arg, payload_size))
-		{
-			retval = -EFAULT;
-			break;
-		}
-
-		DEBUG_INFO("iface %s,iface type %d,low wm %d,high wm %d,bw reqd %d\n\n",
-				config->if_name, config->if_type, config->if_low_watermark,
-				config->if_high_watermark, config->bw_reqd_in_mb);
-		// add the config to GSB cache
-		if (pgsb_ctx->configured_if_count + 1 > MAX_SUPPORTED_IF_CONFIG)
-		{
-			DEBUG_ERROR("GSB cannot configure any more IF\n");
-			retval = -EPERM;
-			break;
-		}
-
-		info = kzalloc(sizeof(struct gsb_if_info), GFP_KERNEL);
-		if (!info)
-		{
-			retval = -ENOMEM;
-			break;
-		}
-		pgsb_ctx->mem_alloc_if_node++;
-
-
-		memcpy(&info->user_config, config, sizeof(struct gsb_if_config));
-		//init if related variables here
-		info->wq_schedule_cnt = 0;
-		info->idle_cnt = 0;
-		info->is_debugfs_init = false;
-		info->ipa_free_desc_cnt = info->user_config.if_high_watermark;
-		info->max_q_len_in_gsb = info->user_config.if_high_watermark *
-							GSB_FLOW_CNTRL_QUEUE_MULTIPLIER;
-		info->low_watermark = info->user_config.if_low_watermark;
-		info->is_ipa_bridge_suspended = true;
-
-		//ipa bridge takes address of if_name so there is a chance
-		// it can change the memory so make a local copy of the name
-		strlcpy(info->if_name, config->if_name, IFNAMSIZ);
-		/* Init IPA Context for the interface*/
-		pif_ipa = kzalloc(sizeof(struct if_ipa_ctx), GFP_KERNEL);
-		if (!pif_ipa)
-		{
-			DEBUG_ERROR("kzalloc err.\n");
-			kfree(info);
-			pgsb_ctx->mem_alloc_if_node--;
-			retval =  -ENOMEM;
-		}
-		else
-		{
-			info->if_ipa = pif_ipa;
-			memset(&info->if_ipa->stats, 0, sizeof(struct gsb_ipa_stats));
-			pgsb_ctx->mem_alloc_if_ipa_context++;
-		}
-		create_debugfs_dir_for_if(info);
-
-		spin_lock_bh(&pgsb_ctx->gsb_lock);
-		if (!add_entry_to_ht(info))
-		{
-			DEBUG_INFO("%s added successfully\n", config->if_name);
-			pgsb_ctx->configured_if_count++;
-		}
-		spin_unlock_bh(&pgsb_ctx->gsb_lock);
-
-		break;
-
-
-	case GSB_IOC_DEL_IF_CONFIG:
-		DEBUG_TRACE("device %s got GSB_IOC_DEL_IF_CONFIG\n",
-				gsb_drv_name);
-		payload_size = sizeof(struct gsb_if_config);
-		config = kzalloc(payload_size, GFP_KERNEL);
-		if (!config)
-		{
-			retval = -ENOMEM;
-			break;
-		}
-		pgsb_ctx->mem_alloc_ioctl_buffer++;
-
-		if (copy_from_user(config, (struct gsb_if_config *)arg, payload_size))
-		{
-			retval = -EFAULT;
-			break;
-		}
-
-		DEBUG_INFO("del iface %s\n\n", config->if_name);
-		if (pgsb_ctx->configured_if_count == 0)
-		{
-			DEBUG_TRACE("GSB cannot delete as there are no configured IF\n");
-			retval =  -EPERM;
-		}
-
-		spin_lock_bh(&pgsb_ctx->gsb_lock);
-		info = get_node_info_from_ht(config->if_name);
-		spin_unlock_bh(&pgsb_ctx->gsb_lock);
-
-		/* first disconnect this IF from IPA*/
-		if (info->is_connected_to_ipa_bridge &&
-			ipa_bridge_disconnect(info->handle) == 0)
-		{
-			spin_lock_bh(&pgsb_ctx->gsb_lock);
-			info->is_connected_to_ipa_bridge = false;
-			info->is_ipa_bridge_suspended = true;
-			info->if_ipa->stats.ipa_suspend_cnt++;
-			spin_unlock_bh(&pgsb_ctx->gsb_lock);
-			flush_pending_packets(info);
-			cancel_work_sync(&info->ipa_resume_task);
-			cancel_work_sync(&info->ipa_send_task);
-			release_wake_source();
-			DEBUG_INFO("IPA bridge dis connected for if %s",
-					info->if_name);
-		}
-
-		/* delete IF from cache*/
-		spin_lock_bh(&pgsb_ctx->gsb_lock);
-		if (!remove_entry_from_ht(config))
-		{
-			DEBUG_INFO("%s removed successfully\n", config->if_name);
-			pgsb_ctx->configured_if_count--;
-		}
-		else
-		{
-			DEBUG_TRACE("some failure..may be if not in cache\n");
-		}
-		spin_unlock_bh(&pgsb_ctx->gsb_lock);
-
-		if (info != NULL)
-		{
-			remove_debugfs_dir_for_if(info->dbg_dir_if);
-		}
-		else
-		{
-			DEBUG_ERROR("if node is NULL\n");
-			break;
-		}
-
-		if (ipa_bridge_cleanup(info->handle) != 0)
-		{
-			DEBUG_ERROR("issue in cleaning up IPA bridge for if %s\n",
-					info->if_name);
-		}
-
-		/* can free memory now*/
-		kfree(info);
-		pgsb_ctx->mem_alloc_if_node--;
-		kfree(info->if_ipa);
-		pgsb_ctx->mem_alloc_if_ipa_context--;
-		break;
-	default:
-		retval = -ENOTTY;
-	}
-	kfree(config);
-	pgsb_ctx->mem_alloc_ioctl_buffer--;
-	return retval;
-	}
-
-
-const struct file_operations gsb_ioctl_fops = {
-	.owner = THIS_MODULE,
-	.unlocked_ioctl = gsb_ioctl,
-	};
-
-
-static int gsb_ioctl_init(void)
-{
-	int ret;
-	struct device *dev;
-
-	ret = alloc_chrdev_region(&device, 0, dev_num, gsb_drv_name);
-	if (ret)
-	{
-		DEBUG_ERROR("device_alloc err\n");
-		goto dev_alloc_err;
-	}
-
-	gsb_class = class_create(THIS_MODULE, gsb_drv_name);
-	if (IS_ERR(gsb_class))
-	{
-		DEBUG_ERROR("class_create err\n");
-		goto class_err;
-	}
-
-	dev = device_create(gsb_class, NULL, device,
-			    __gc, gsb_drv_name);
-	if (IS_ERR(dev))
-	{
-		DEBUG_ERROR("device_create err\n");
-		goto device_err;
-	}
-
-	cdev_init(&gsb_ioctl_cdev, &gsb_ioctl_fops);
-	ret = cdev_add(&gsb_ioctl_cdev, device, dev_num);
-	if (ret)
-	{
-		DEBUG_ERROR("cdev_add err\n");
-		goto cdev_add_err;
-	}
-
-	DEBUG_TRACE("ioctl init OK!!\n");
-	return 0;
-
-
-cdev_add_err:
-	device_destroy(gsb_class, device);
-device_err:
-	class_destroy(gsb_class);
-class_err:
-	unregister_chrdev_region(device, dev_num);
-dev_alloc_err:
-	return -ENODEV;
-}
-
-static void gsb_ioctl_deinit(void)
-{
-	cdev_del(&gsb_ioctl_cdev);
-	device_destroy(gsb_class, device);
-	class_destroy(gsb_class);
-	unregister_chrdev_region(device, dev_num);
-}
-
-static void gsb_ipa_send_routine(struct work_struct *work)
-{
-	struct gsb_if_info *if_info = container_of(work,
-							struct gsb_if_info, ipa_send_task);
-	int ret = 0;
-	struct if_ipa_ctx *pipa_ctx = if_info->if_ipa;
-	struct gsb_ctx *pgsb_ctx = __gc;
-	struct sk_buff *skb;
-
-	if (NULL == pgsb_ctx)
-	{
-		DEBUG_ERROR("Context is NULL\n");
-		return;
-	}
-
-	if (IS_ERR_OR_NULL(if_info))
-	{
-		DEBUG_ERROR("if info is NULL\n");
-		return;
-	}
-
-	if (IS_ERR_OR_NULL(pipa_ctx))
-	{
-		DEBUG_ERROR("ipa stats structure is NULL\n");
-		return;
-	}
-
-	spin_lock_bh(&if_info->flow_ctrl_lock);
-
-
-	if (if_info->ipa_free_desc_cnt < if_info->low_watermark)
-	{
-		pipa_ctx->stats.ipa_low_watermark_cnt++;
-		spin_unlock_bh(&if_info->flow_ctrl_lock);
-		return;
-	}
-
-
-	while (if_info->pend_queue.qlen && if_info->ipa_free_desc_cnt)
-	{
-		skb = __skb_dequeue(&if_info->pend_queue);
-		if (IS_ERR_OR_NULL(skb))
-		{
-			DEBUG_ERROR("null skb\n");
-			break;
-		}
-		//Send Packet to IPA bridge Driver
-		ret = ipa_bridge_tx_dp(if_info->handle, skb, NULL);
-		if (ret)
-		{
-			DEBUG_ERROR("ret %d\n", ret);
-			dev_kfree_skb(skb);
-			pgsb_ctx->mem_alloc_skb_free++;
-			pipa_ctx->stats.drop_send_to_ipa_fail++;
-		}
-		else
-		{
-			if_info->wq_schedule_cnt++;
-			pipa_ctx->stats.sent_to_ipa++;
-			if_info->ipa_free_desc_cnt--;
-			pipa_ctx->ipa_rx_completion++;
-		}
-		/*Giving some time to IPA to send WD events back to GSB*/
-		spin_unlock_bh(&if_info->flow_ctrl_lock);
-		spin_lock_bh(&if_info->flow_ctrl_lock);
-	}
-	spin_unlock_bh(&if_info->flow_ctrl_lock);
-}
-
-static void gsb_ipa_resume_routine(struct work_struct *work)
-	{
-	struct gsb_ctx *pgsb_ctx = __gc;
-	struct gsb_if_info *if_info = NULL;
-
-	if (IS_ERR_OR_NULL(pgsb_ctx))
-	{
-		DEBUG_ERROR("NULL Context\n");
-		return;
-	}
-
-	if_info = container_of(work,struct gsb_if_info,
-				ipa_resume_task);
-
-	if (IS_ERR_OR_NULL(if_info))
-	{
-		DEBUG_ERROR("issue in getting correct node\n");
-		return;
-	}
-
-	spin_lock_bh(&pgsb_ctx->gsb_lock);
-	if (if_info->is_ipa_bridge_suspended)
-	{
-		spin_unlock_bh(&pgsb_ctx->gsb_lock);
-		if (ipa_bridge_resume(if_info->handle) != 0)
-		{
-			DEBUG_ERROR("issue in resuming IPA for if %s\n",
-					if_info->if_name);
-			return;
-		}
-		else
-		{
-			DEBUG_TRACE("if %s resumed\n", if_info->if_name);
-			spin_lock_bh(&pgsb_ctx->gsb_lock);
-			if_info->is_ipa_bridge_suspended = false;
-			//cancel  inactivity timer if scheduled
-			if (pgsb_ctx->inactivity_timer_scheduled)
-			{
-				pgsb_ctx->inactivity_timer_scheduled = false;
-				pgsb_ctx->inactivity_timer_cancelled_cnt++;
-			}
-			spin_unlock_bh(&pgsb_ctx->gsb_lock);
-			acquire_wake_source();
-			release_wake_source();
-			return;
-		}
-	}
-	spin_unlock_bh(&pgsb_ctx->gsb_lock);
-	}
-
-
-static int gsb_pm_handler(struct notifier_block *nb,
-			  unsigned long pm_evt, void *unused)
-{
-	struct gsb_ctx *pgsb_ctx = __gc;
-
-	if (IS_ERR_OR_NULL(pgsb_ctx))
-	{
-		DEBUG_ERROR("NULL Context\n");
-		return NOTIFY_DONE;
-	}
-
-	switch (pm_evt)
-	{
-	case PM_SUSPEND_PREPARE:
-	case PM_HIBERNATION_PREPARE:
-	case PM_RESTORE_PREPARE:
-		if (pgsb_ctx->do_we_need_wake_source && !pgsb_ctx->is_wake_src_acquired)
-		{
-			spin_lock_bh(&pgsb_ctx->gsb_wake_lock);
-			__pm_stay_awake(&pgsb_ctx->gsb_wake_src);
-			DEBUG_INFO("Wake src acquired..will not suspend! if cnt %d, ref cnt %d\n",
-					pgsb_ctx->configured_if_count,
-					pgsb_ctx->wake_source_ref_count);
-			pgsb_ctx->is_wake_src_acquired = true;
-			spin_unlock_bh(&pgsb_ctx->gsb_wake_lock);
-		}
-		else
-		{
-			DEBUG_INFO("GSB in idle mode .. suspending\n");
-		}
-		break;
-	case PM_POST_SUSPEND:
-	case PM_POST_HIBERNATION:
-	case PM_POST_RESTORE:
-		DEBUG_TRACE("Resuming\n");
-		spin_lock_bh(&pgsb_ctx->gsb_wake_lock);
-		if (pgsb_ctx->is_wake_src_acquired)
-		{
-			__pm_relax(&pgsb_ctx->gsb_wake_src);
-			pgsb_ctx->is_wake_src_acquired = false;
-		}
-		spin_unlock_bh(&pgsb_ctx->gsb_wake_lock);
-		break;
-	default:
-		break;
-	}
-	return NOTIFY_DONE;
-}
-
-
-static int gsb_device_event(struct notifier_block *this, unsigned long event, void *ptr)
-{
-	struct net_device *dev =  netdev_notifier_info_to_dev(ptr);
-	struct gsb_ctx *pgsb_ctx = __gc;
-	struct gsb_if_info *if_info = NULL;
-
-
-	if (IS_ERR_OR_NULL(pgsb_ctx))
-	{
-		DEBUG_ERROR("NULL Context\n");
-		return NOTIFY_DONE;
-	}
-	//obtain node if present in hash.
-	if (dev->name != NULL)
-	{
-		spin_lock_bh(&pgsb_ctx->gsb_lock);
-		if_info = get_node_info_from_ht(dev->name);
-		spin_unlock_bh(&pgsb_ctx->gsb_lock);
-
-		if (if_info == NULL)
-		{
-			DEBUG_TRACE("iface %s not registered with gsb\n", dev->name);
-			return NOTIFY_DONE;
-		}
-	}
-
-	DEBUG_INFO("event %d received for iface %s\n", event, dev->name);
-
-	switch (event)
-	{
-	case NETDEV_DOWN:
-		if (if_info->is_connected_to_ipa_bridge)
-		{
-			// lets send all pending packets to Network stack
-			release_pending_packets_exp(if_info);
-
-			// no need for inactivity timer as netdev going down
-			if (ipa_bridge_disconnect(if_info->handle) == 0)
-			{
-				spin_lock_bh(&pgsb_ctx->gsb_lock);
-				if_info->is_connected_to_ipa_bridge = false;
-				if_info->is_ipa_bridge_suspended = true;
-				if_info->if_ipa->stats.ipa_suspend_cnt++;
-				if_info->net_dev_state = false;
-				spin_unlock_bh(&pgsb_ctx->gsb_lock);
-				release_wake_source();
-				DEBUG_INFO("IPA bridge dis connected on NETDEV_DOWN for if %s\n",
-						if_info->if_name);
-			}
-			else
-			{
-				DEBUG_ERROR("ERROR in IPA_BRIDGE_DISCONNECT for if %s\n",
-						if_info->if_name);
-			}
-		}
-		DEBUG_TRACE("Net device %s went down\n", dev->name);
-		break;
-	case NETDEV_REGISTER:
-		DEBUG_TRACE("Net dev  %s is registered\n", dev->name);
-		break;
-	case NETDEV_PRE_UP:
-		DEBUG_TRACE("Net %s about to come UP\n", dev->name);
-
-		//IPA should be ready most of the time but we still have
-		//this code to be sure.
-		if (!pgsb_ctx->is_ipa_ready)
-		{
-			DEBUG_TRACE("waiting for IPA to be ready\n");
-			wait_event_interruptible(wq, (pgsb_ctx->is_ipa_ready != 0));
-			if (pgsb_ctx->is_ipa_ready)
-			{
-				DEBUG_TRACE("IPA is ready now\n");
-			}
-		}
-		//is this netdev in cache?
-		//if it is, is it already registered to IPA bridge?
-		//if not we need to bind it before it comes up.
-		//to do we should not be in atomic context to bind to IPA .IPA needs
-		//preemption to do what it need to do.
-		if (!in_atomic() && if_info != NULL)
-		{
-			if_info->pdev = dev;
-			if (gsb_bind_if_to_ipa_bridge(if_info) != 0)
-			{
-				DEBUG_ERROR("failed to bind if %s with IPA bridge\n",
-					if_info->if_name);
-			}
-		}
-		else
-		{
-			DEBUG_TRACE("IPA bridge already initialized for if %s\n",
-				if_info->if_name);
-		}
-		break;
-
-	case NETDEV_UP:
-		DEBUG_TRACE("Net dev  %s is up\n", dev->name);
-		if (!if_info->is_connected_to_ipa_bridge &&
-			if_info->is_ipa_bridge_initialized)
-		{
-			if (ipa_bridge_connect(if_info->handle) == 0)
-			{
-				spin_lock_bh(&pgsb_ctx->gsb_lock);
-				if_info->is_connected_to_ipa_bridge = true;
-				if_info->is_ipa_bridge_suspended = false;
-				if_info->net_dev_state = true;
-				spin_unlock_bh(&pgsb_ctx->gsb_lock);
-
-				acquire_wake_source();
-				DEBUG_INFO("IPA bridge connected on NETDEV_UP for if %s",
-						if_info->if_name);
-
-			}
-			else
-			{
-				DEBUG_ERROR("ERROR in IPA_BRIDGE_CONNECT for if %s",
-						if_info->if_name);
-			}
-		}
-
-		break;
-	case NETDEV_CHANGE:
-		DEBUG_TRACE("Net dev  %s changed\n", dev->name);
-		break;
-	case NETDEV_CHANGEADDR:
-		DEBUG_INFO("Net dev addr  %s changed\n", dev->name);
-		DEBUG_ERROR("This operation is not supported in GSB\n");
-		WARN_ON(1);
-		break;
-	case NETDEV_GOING_DOWN:
-		DEBUG_TRACE("Net device %s about to go down\n", dev->name);
-		break;
-	case NETDEV_CHANGENAME:
-		DEBUG_TRACE("Net device %s changed name\n", dev->name);
-		break;
-	}
-	return NOTIFY_DONE;
-}
-
-
-
-
-
-
-/*Do we need this for first version. From discussion, it is assumed that IPA
-  is ready but for ODU to bind with IF following steps need to be performed
-  Stop IF --> ipa_bridge_init --> Start IF
-  Above steps are done from connection manager. if IPA is not ready and IF comes up
-  then we will not be able to bind the IF from conn manager to IPA bridge*/
-static void gsb_ipa_ready_cb(void *context)
-{
-	struct gsb_ctx *pgsb_ctx = (struct gsb_ctx *)context;
-	DEBUG_TRACE("--- IPA is ready --- \n");
-	if (pgsb_ctx->is_ipa_ready)
-	{
-		DEBUG_TRACE("False event received\n");
-		return;
-	}
-
-	pgsb_ctx->is_ipa_ready = true;
-	wake_up_interruptible(&wq);
-}
-
-/*
-when packet received here...
-scenario 1. inactivity timer scheduled ( wake source avaialble  , if not suspended)
-scenario 2  ianctivity timer  expired (no wake source, if suspended)
-scenario 3. iactivity timer not scheduled...all good in this case( wake source available)
-*/
-
-static int gsb_intercept_packet_in_nw_stack(struct sk_buff *skb)
-{
-	struct gsb_ctx *pgsb_ctx = __gc;
-	struct gsb_if_info *if_info = NULL;
-	bool is_pkt_ipv4 = false;
-	bool is_pkt_ipv6 = false;
-	bool is_inactivity_timer_cancelled = false;
-	int ret = 0;
-	u32 pkts_to_send, qlen = 0;
-	unsigned char *ptr = NULL;
-	struct sk_buff *pend_skb;
-
-
-	if (NULL == pgsb_ctx)
-	{
-		IPC_ERROR_LOW("Context is NULL\n");
-		return -EFAULT;
-	}
-
-
-	spin_lock_bh(&pgsb_ctx->gsb_lock);
-	if (!IS_ERR_OR_NULL(skb))
-	{
-		if_info = get_node_info_from_ht(skb->dev->name);
-	}
-	else
-	{
-		IPC_ERROR_LOW("NULL skb passed\n");
-		BUG();
-	}
-	spin_unlock_bh(&pgsb_ctx->gsb_lock);
-
-	if (if_info == NULL)
-	{
-		IPC_TRACE_LOW("device %s not registered to GSB\n", skb->dev->name);
-		return 0;
-	}
-	else
-	{
-		IPC_TRACE_LOW("recvd packet from %s if\n", if_info->if_name);
-		if_info->if_ipa->stats.total_recv_from_if++;
-	}
-
-	if (strncmp(skb->cb, "isthisloop", TAG_LENGTH) == 0)
-	{
-		IPC_TRACE_LOW("tagged skb with string %s found, skbp= %pK\n", skb->cb, skb);
-		return 0;
-	}
-
-
-	is_pkt_ipv4 = is_ipv4_pkt(skb);
-	is_pkt_ipv6 = is_ipv6_pkt(skb);
-
-	/* if if not connected to IPA, ther eis nothing we could do here*/
-	if (unlikely(!if_info->is_connected_to_ipa_bridge))
-	{
-		IPC_TRACE_LOW("if %s not connected to IPA bridge yet\n",
-				if_info->if_name);
-		if_info->if_ipa->stats.exception_ipa_not_connected++;
-		return 0;
-	}
-	/* If Packet is an IP Packet and non-fragmented then Send it to
-		IPA Bridge Driver*/
-	if (is_non_ip_pkt(skb) ||
-		((is_pkt_ipv4) && is_ip_frag_pkt(skb)) ||
-		(!if_info->is_connected_to_ipa_bridge))
-	{
-		/* Send packet to network stack */
-		if (is_non_ip_pkt(skb))
-			{
-			if_info->if_ipa->stats.exception_non_ip_packet++;
-			}
-		else if (is_ip_frag_pkt(skb))
-			{
-			if_info->if_ipa->stats.exception_fragmented++;
-			}
-		return 0;
-	}
-
-
-	// check if if is suspended
-	spin_lock_bh(&pgsb_ctx->gsb_lock);
-	if (if_info->is_ipa_bridge_suspended)
-	{
-		//To do : need to see if we can do anything for
-		//if IPA bridge to resume here itself.
-		//at present let this packet go to nw stack
-		queue_work(gsb_wq, &if_info->ipa_resume_task);
-		IPC_TRACE_LOW("waiting for if %s to resume\n",
-				if_info->if_name);
-		if_info->if_ipa->stats.exp_ipa_suspended++;
-		spin_unlock_bh(&pgsb_ctx->gsb_lock);
-		return 0;
-	}
-	// cancel inactivity timer ...if scheduled
-	if (pgsb_ctx->inactivity_timer_scheduled)
-	{
-		pgsb_ctx->inactivity_timer_scheduled = false;
-		is_inactivity_timer_cancelled = true;
-		pgsb_ctx->inactivity_timer_cancelled_cnt++;
-	}
-	spin_unlock_bh(&pgsb_ctx->gsb_lock);
-
-
-	spin_lock_bh(&if_info->flow_ctrl_lock);
-	qlen = if_info->pend_queue.qlen;
-	if (!if_info->ipa_free_desc_cnt &&
-		(qlen > (if_info->max_q_len_in_gsb)))
-	{
-		dev_kfree_skb(skb);
-		pgsb_ctx->mem_alloc_skb_free++;
-		if_info->if_ipa->stats.drop_flow_control_bottleneck++;
-		/*claim packet by setting ret = non zero*/
-		ret = GSB_ACCEPT;
-		goto unlock_and_schedule;
-	}
-	//fix skb for IPA
-	if (skb_headroom(skb) > ETH_HLEN)
-	{
-		skb_reset_mac_header(skb);
-		ptr = (unsigned char *)skb->data;
-		ptr = ptr - ETH_HLEN;
-		skb->data = (unsigned char *)ptr;
-		skb->len += ETH_HLEN;
-	}
-	else
-	{
-		if_info->if_ipa->stats.exp_insufficient_hr++;
-		return 0;
-	}
-
-
-	/* Remove extra padding if the rcv_pkt_len == 64 */
-	//to do only do for eth, dont do it for wlan
-	if (skb->len == ETH_ZLEN && if_info->user_config.if_type == ETH_TYPE)
-	{
-		IPC_TRACE_LOW("remove_padding\n");
-		remove_padding(skb, is_pkt_ipv4, is_pkt_ipv6);
-	}
-
-	/* Packet ready for processing now */
-	__skb_queue_tail(&if_info->pend_queue, skb);
-	IPC_TRACE_LOW("Packet skbp= %pK enqueued,qlen %d,  free desc %d\n",
-			skb, if_info->pend_queue.qlen, if_info->ipa_free_desc_cnt);
-	/*claim packet by setting ret = non zero*/
-	ret = GSB_ACCEPT;
-
-	if (if_info->ipa_free_desc_cnt)
-	{
-		pkts_to_send = if_info->ipa_free_desc_cnt;
-		pkts_to_send = (pkts_to_send > MAX_PACKETS_TO_SEND) ?
-			MAX_PACKETS_TO_SEND : pkts_to_send;
-		while (if_info->pend_queue.qlen && pkts_to_send)
-		{
-			pend_skb = __skb_dequeue(&if_info->pend_queue);
-			if (unlikely(IS_ERR_OR_NULL(pend_skb)))
-			{
-				IPC_ERROR_LOW("null skb\n");
-				BUG();
-			}
-			/* Send Packet to IPA bridge Driver */
-			ret = ipa_bridge_tx_dp(if_info->handle, pend_skb, NULL);
-			if (ret)
-			{
-				IPC_ERROR_LOW("ret %d, free pkt %pK\n", ret, pend_skb);
-				dev_kfree_skb(pend_skb);
-				pgsb_ctx->mem_alloc_skb_free++;
-				if_info->if_ipa->stats.drop_send_to_ipa_fail++;
-				ret = GSB_DROP;
-				goto unlock_and_schedule;
-			}
-			else
-			{
-				if_info->ipa_free_desc_cnt--;
-				if_info->if_ipa->stats.sent_to_ipa++;
-				if_info->if_ipa->ipa_rx_completion++;
-				ret = GSB_FORWARD;
-			}
-			pkts_to_send--;
-		}
-	}
-
-unlock_and_schedule:
-	spin_unlock_bh(&if_info->flow_ctrl_lock);
-	if (ret == GSB_FORWARD && is_inactivity_timer_cancelled)
-	{
-		/*this wake source will be released after IPA WDE*/
-		acquire_wake_source();
-	}
-	return ret;
-}
-
-static ssize_t gsb_proc_read_cb(struct file *filp,char *buf,size_t count,loff_t *offp )
-{
-	if (*offp != 0)
-		return 0;
-
-	return snprintf(buf, PAGE_SIZE, "%d\n", gsb_enable_ipc_low);
-}
-
-static ssize_t gsb_proc_write_cb(struct file *file,const char *buf,size_t count,loff_t *data )
-
-{
-	int tmp = 0;
-
-	if(count > MAX_PROC_SIZE)
-		count = MAX_PROC_SIZE;
-	if(copy_from_user(tmp_buff, buf, count))
-		return -EFAULT;
-
-	if (sscanf(tmp_buff, "%du", &tmp) < 0)
-		pr_err("sscanf failed\n");
-	else {
-		if (tmp) {
-			if (!ipc_gsb_log_ctxt_low) {
-					ipc_gsb_log_ctxt_low = ipc_log_context_create(
-						IPCLOG_STATE_PAGES, "gsb_low", 0);
-			}
-			if (!ipc_gsb_log_ctxt_low) {
-				pr_err("failed to create ipc gsb low context\n");
-				return -EFAULT;
-			}
-		} else {
-			if (ipc_gsb_log_ctxt_low)
-				ipc_log_context_destroy(ipc_gsb_log_ctxt_low);
-				ipc_gsb_log_ctxt_low = NULL;
-		}
-	}
-	gsb_enable_ipc_low = tmp;
-	return count;
-}
-
-
-static int __init gsb_init_module(void)
-{
-	int retval = -1;
-	struct gsb_ctx *pgsb_ctx = NULL;
-	DEBUG_INFO("gsb enter %s\n", DRV_VERSION);
-
-
-	if (__gc)
-	{
-		DEBUG_ERROR("GSB context already initialized\n");
-		return -EEXIST;
-	}
-
-	ipc_gsb_log_ctxt = ipc_log_context_create(IPCLOG_STATE_PAGES,
-							"gsb", 0);
-	if (!ipc_gsb_log_ctxt)
-		pr_err("error creating logging context for GSB\n");
-	else
-		pr_info("IPC logging has been enabled for GSB\n");
-
-	//define proc file and operations
-	memset(&proc_file_ops, 0, sizeof(struct file_operations));
-	proc_file_ops.owner = THIS_MODULE;
-	proc_file_ops.read =  gsb_proc_read_cb;
-	proc_file_ops.write = gsb_proc_write_cb;
-	if((proc_file = proc_create("gsb_enable_ipc_low", 0, NULL,
-		&proc_file_ops)) == NULL) {
-		pr_err(" error creating proc entry!\n");
-		return -EINVAL;
-	}
-
-	pgsb_ctx = kzalloc(sizeof(struct gsb_ctx), GFP_KERNEL);
-	if (pgsb_ctx == NULL)
-	{
-		DEBUG_ERROR("Memory allocation failed\n");
-		return -ENOMEM;
-	}
-	else
-	{
-		__gc = pgsb_ctx;
-	}
-
-	gsb_wq  = create_singlethread_workqueue("gsb");
-	if (!gsb_wq)
-	{
-		DEBUG_ERROR("Unable to create gsb workqueue\n");
-		return -ENOMEM;
-	}
-
-	retval = gsb_debugfs_init(pgsb_ctx);
-	if (retval != 0)
-	{
-		DEBUG_ERROR("debugfs init failed\n");
-		goto debug_fs_init_failure;
-	}
-
-	spin_lock_init(&pgsb_ctx->gsb_lock);
-	pgsb_ctx->gsb_lock_acquired = false;
-
-
-	wakeup_source_init(&pgsb_ctx->gsb_wake_src, "gsb_wake_source");
-	pgsb_ctx->do_we_need_wake_source = false;
-	pgsb_ctx->is_wake_src_acquired = false;
-	pgsb_ctx->mem_alloc_if_ipa_context = 0;
-	pgsb_ctx->mem_alloc_if_node = 0;
-	pgsb_ctx->mem_alloc_ioctl_buffer = 0;
-	pgsb_ctx->mem_alloc_read_stats_buffer = 0;
-	pgsb_ctx->mem_alloc_skb_free = 0;
-
-
-
-	spin_lock_init(&pgsb_ctx->gsb_wake_lock);
-	pgsb_ctx->gsb_wake_lock_acquired = false;
-
-
-
-	pgsb_ctx->gsb_dev_notifier.notifier_call = gsb_device_event;
-	retval = register_netdevice_notifier(&pgsb_ctx->gsb_dev_notifier);
-	if (retval != 0)
-	{
-		DEBUG_ERROR("registering netdev notification failed\n");
-		goto failed_netdev_notification;
-	}
-
-	pgsb_ctx->gsb_pm_notifier.notifier_call = gsb_pm_handler;
-	retval = register_pm_notifier(&pgsb_ctx->gsb_pm_notifier);
-	if (retval != 0)
-	{
-		DEBUG_ERROR("registering system power notification failed\n");
-		goto failed_power_notification;
-	}
-
-	retval = gsb_ioctl_init();
-	if (retval != 0)
-	{
-		DEBUG_ERROR("Initializing IOCTL failed\n");
-		goto failed_ioctl_initialization;
-	}
-
-
-
-	//create hash table
-	hash_init(pgsb_ctx->cache_htable_list);
-	pgsb_ctx->gsb_state_mask = 0;
-	pgsb_ctx->is_ipa_ready = false;
-	pgsb_ctx->configured_if_count = 0;
-	pgsb_ctx->wake_source_ref_count = 0;
-	pgsb_ctx->inactivity_timer_cnt = 0;
-	pgsb_ctx->inactivity_timer_cancelled_cnt = 0;
-
-
-	retval = ipa_register_ipa_ready_cb(gsb_ipa_ready_cb, (void *)pgsb_ctx);
-	if (retval < 0)
-	{
-		if (retval == -EEXIST)
-		{
-			DEBUG_TRACE("-- IPA is Ready retval %d \n",
-					retval);
-			pgsb_ctx->is_ipa_ready = true;
-			//not an error so change return code.
-			retval = 0;
-		}
-		else
-		{
-			DEBUG_TRACE(" -- IPA is Not Ready retval %d \n",
-					retval);
-			//not an error so change return code.
-			retval = 0;
-		}
-	}
-
-	setup_timer(&INACTIVITY_TIMER, inactivity_timer_cb, 0);
-
-
-	/*
-	* Hook the receive path in the network stack.
-	*/
-	BUG_ON(gsb_nw_stack_recv != NULL);
-	RCU_INIT_POINTER(gsb_nw_stack_recv, gsb_intercept_packet_in_nw_stack);
-	DEBUG_INFO("%s\n", gsb_drv_description);
-
-	return retval;
-
-
-failed_ioctl_initialization:
-	unregister_pm_notifier(&pgsb_ctx->gsb_pm_notifier);
-failed_power_notification:
-	unregister_netdevice_notifier(&pgsb_ctx->gsb_dev_notifier);
-failed_netdev_notification:
-	gsb_debugfs_exit(pgsb_ctx);
-debug_fs_init_failure:
-	destroy_workqueue(gsb_wq);
-	kfree(pgsb_ctx);
-	DEBUG_ERROR("Failed to load %s\n", gsb_drv_name);
-	return retval;
-}
-
-static void __exit gsb_exit_module(void)
-{
-	int ret = 0;
-	struct gsb_ctx *pgsb_ctx = __gc;
-
-	if (NULL == pgsb_ctx)
-	{
-		DEBUG_ERROR("Context is NULL\n");
-		return -EFAULT;
-	}
-
-	unregister_netdevice_notifier(&pgsb_ctx->gsb_dev_notifier);
-	unregister_pm_notifier(&pgsb_ctx->gsb_pm_notifier);
-
-	/*lets delete the if  from cache so no more packets are
-		processed from stack*/
-	cancel_delayed_work_sync(&if_suspend_wq);
-	cleanup_entries_from_ht();
-	destroy_workqueue(gsb_wq);
-
-	/*
-	 * Unregister our receive callback so we dont intercept at all
-	 */
-	RCU_INIT_POINTER(gsb_nw_stack_recv, NULL);
-	/* delete inactivity timer*/
-
-	ret = del_timer(&INACTIVITY_TIMER);
-	if (ret) DEBUG_TRACE("timer still in use\n");
-
-
-	if (pgsb_ctx->is_wake_src_acquired)
-	{
-		__pm_relax(&pgsb_ctx->gsb_wake_src);
-	}
-	wakeup_source_trash(&pgsb_ctx->gsb_wake_src);
-
-	gsb_debugfs_exit(pgsb_ctx);
-	gsb_ioctl_deinit();
-
-	kfree(pgsb_ctx);
-
-	proc_remove(proc_file);
-
-	if (ipc_gsb_log_ctxt != NULL)
-		ipc_log_context_destroy(ipc_gsb_log_ctxt);
-
-	if (ipc_gsb_log_ctxt_low != NULL)
-		ipc_log_context_destroy(ipc_gsb_log_ctxt_low);
-
-	pr_info("exiting GSB %s\n", DRV_VERSION);
-}
-
-module_init(gsb_init_module);
-module_exit(gsb_exit_module);
-
-MODULE_AUTHOR("The Linux Foundation ");
-MODULE_DESCRIPTION("Generic Software Bridge");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/generic-sw-bridge/gsb_debugfs.h b/drivers/generic-sw-bridge/gsb_debugfs.h
deleted file mode 100644
index 9ad59d8..0000000
--- a/drivers/generic-sw-bridge/gsb_debugfs.h
+++ /dev/null
@@ -1,155 +0,0 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved. */
-/*
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef _GSB_DEBUGFS_H_
-#define _GSB_DEBUGFS_H_
-#include <linux/debugfs.h>
-#include <linux/fs.h>
-#include <linux/ipc_logging.h>
-
-#define IPCLOG_STATE_PAGES 2
-#define __FILENAME__ (strrchr(__FILE__, '/') ? \
-	strrchr(__FILE__, '/') + 1 : __FILE__)
-
-static void *ipc_gsb_log_ctxt;
-static void *ipc_gsb_log_ctxt_low;
-
-
-/*
- * Debug output verbosity level.
- */
-#define DEBUG_LEVEL 3
-
-#if (DEBUG_LEVEL < 1)
-#define DEBUG_ERROR(s, ...)
-#else
-#define DEBUG_ERROR(s, ...) \
-do { \
-	printk("%s[%u]:[GSB] ERROR: ", __func__,__LINE__); \
-	printk(s, ##__VA_ARGS__); \
-	if (ipc_gsb_log_ctxt) { \
-		ipc_log_string(ipc_gsb_log_ctxt, \
-		"%s: %s[%u]:[GSB] ERROR:" s, __FILENAME__ , \
-		__func__, __LINE__, ##__VA_ARGS__); \
-		} \
-} while (0)
-#endif
-
-#if (DEBUG_LEVEL < 2)
-#define DEBUG_WARN(s, ...)
-#else
-#define DEBUG_WARN(s, ...) \
-do { \
-	printk("%s[%u] GSB:", __func__,__LINE__); \
-	printk(s, ##__VA_ARGS__); \
-	if (ipc_gsb_log_ctxt) { \
-		ipc_log_string(ipc_gsb_log_ctxt, \
-		"%s: %s[%u]: GSB:" s, __FILENAME__ , \
-		__func__, __LINE__, ##__VA_ARGS__); \
-		} \
-} while (0)
-#endif
-
-#if (DEBUG_LEVEL < 3)
-#define DEBUG_INFO(s, ...)
-#else
-#define DEBUG_INFO(s, ...) \
-do { \
-	printk("%s[%u][GSB]:", __func__,__LINE__); \
-	printk(s, ##__VA_ARGS__); \
-	if (ipc_gsb_log_ctxt) { \
-		ipc_log_string(ipc_gsb_log_ctxt, \
-		"%s: %s[%u]: GSB:" s, __FILENAME__ , \
-		__func__, __LINE__, ##__VA_ARGS__); \
-		} \
-} while (0)
-#endif
-
-#if (DEBUG_LEVEL < 5)
-#define DEBUG_TRACE(s, ...)
-#else
-#define DEBUG_TRACE(s, ...) \
-do { \
-	printk("%s[%u]:", __func__,__LINE__); \
-	printk(s, ##__VA_ARGS__); \
-	if (ipc_gsb_log_ctxt) { \
-		ipc_log_string(ipc_gsb_log_ctxt, \
-		"%s: %s[%u]: TRACE:" s, __FILENAME__ , \
-		__func__, __LINE__, ##__VA_ARGS__); \
-		} \
-} while (0)
-#endif
-
-#if (DEBUG_LEVEL < 4)
-#define DUMP_PACKET(s, ...)
-#else
-#define DUMP_PACKET(s, ...) \
-do { \
-	printk(s, ##__VA_ARGS__); \
-	if (ipc_gsb_log_ctxt) { \
-		ipc_log_string(ipc_gsb_log_ctxt, \
-		"%s: %s[%u]: DUMP_PACKET:" s, __FILENAME__ , \
-		__func__, __LINE__, ##__VA_ARGS__); \
-		} \
-} while (0)
-
-#endif
-
-#define IPC_ERROR_LOW(s, ...) \
-do { \
-	if (ipc_gsb_log_ctxt_low) { \
-		ipc_log_string(ipc_gsb_log_ctxt_low, \
-		"%s: %s[%u]:[GSB] IPC ERROR LOW:" s, __FILENAME__ , \
-		__func__, __LINE__, ##__VA_ARGS__); \
-		} \
-} while (0)
-
-#define IPC_WARN_LOW(s, ...) \
-do { \
-	if (ipc_gsb_log_ctxt_low) { \
-		ipc_log_string(ipc_gsb_log_ctxt_low, \
-		"%s: %s[%u]:[GSB] IPC WARN LOW" s, __FILENAME__ , \
-		__func__, __LINE__, ##__VA_ARGS__); \
-	} \
-} while (0)
-
-#define IPC_INFO_LOW(s, ...) \
-do { \
-	if (ipc_gsb_log_ctxt_low) { \
-		ipc_log_string(ipc_gsb_log_ctxt_low, \
-		"%s: %s[%u]:[GSB] IPC INFO LOW" s, __FILENAME__ , \
-		__func__, __LINE__, ##__VA_ARGS__); \
-	} \
-} while (0)
-
-
-#define IPC_TRACE_LOW(s, ...) \
-do { \
-	if (ipc_gsb_log_ctxt_low) { \
-		ipc_log_string(ipc_gsb_log_ctxt_low, \
-		"%s: %s[%u]:[GSB] IPC TRACE LOW" s, __FILENAME__ , \
-		__func__, __LINE__, ##__VA_ARGS__); \
-	} \
-} while (0)
-
-#define IPC_DUMP_PACKET_LOW(s, ...) \
-do { \
-	if (ipc_gsb_log_ctxt_low) { \
-		ipc_log_string(ipc_gsb_log_ctxt_low, \
-		"%s: %s[%u]:[GSB] IPC DUMP_PACKET LOW" s, __FILENAME__ , \
-		__func__, __LINE__, ##__VA_ARGS__); \
-	} \
-} while (0)
-
-
-#endif
diff --git a/drivers/rmnet/perf/rmnet_perf_core.c b/drivers/rmnet/perf/rmnet_perf_core.c
index 4166c5d..4e8d4c6 100644
--- a/drivers/rmnet/perf/rmnet_perf_core.c
+++ b/drivers/rmnet/perf/rmnet_perf_core.c
@@ -498,6 +498,10 @@
 	struct rmnet_perf *perf = rmnet_perf_config_get_perf();
 	struct rmnet_perf_core_burst_marker_state *bm_state;
 
+	/* If handling deaggregation, we're already locked */
+	if (!rmnet_perf_core_is_deag_mode())
+		rmnet_perf_core_grab_lock();
+
 	bm_state = perf->core_meta->bm_state;
 	/* if we get two starts in a row, without an end, then we flush
 	 * and carry on
@@ -516,6 +520,9 @@
 	trace_rmnet_perf_low(RMNET_PERF_MODULE, RMNET_PERF_START_DL_MRK,
 			     bm_state->expect_packets, 0xDEF, 0xDEF, 0xDEF,
 			     NULL, NULL);
+
+	if (!rmnet_perf_core_is_deag_mode())
+		rmnet_perf_core_release_lock();
 }
 
 void rmnet_perf_core_handle_map_control_end_v2(struct rmnet_map_dl_ind_trl *dltrl,
@@ -529,6 +536,10 @@
 	struct rmnet_perf *perf = rmnet_perf_config_get_perf();
 	struct rmnet_perf_core_burst_marker_state *bm_state;
 
+	/* If handling deaggregation, we're already locked */
+	if (!rmnet_perf_core_is_deag_mode())
+		rmnet_perf_core_grab_lock();
+
 	bm_state = perf->core_meta->bm_state;
 	rmnet_perf_opt_flush_all_flow_nodes();
 	rmnet_perf_core_flush_reason_cnt[RMNET_PERF_CORE_DL_MARKER_FLUSHES]++;
@@ -537,6 +548,9 @@
 	bm_state->expect_packets = 0;
 	trace_rmnet_perf_low(RMNET_PERF_MODULE, RMNET_PERF_END_DL_MRK, 0xDEF,
 			     0xDEF, 0xDEF, 0xDEF, NULL, NULL);
+
+	if (!rmnet_perf_core_is_deag_mode())
+		rmnet_perf_core_release_lock();
 }
 
 int rmnet_perf_core_validate_pkt_csum(struct sk_buff *skb,
diff --git a/drivers/rmnet/perf/rmnet_perf_opt.h b/drivers/rmnet/perf/rmnet_perf_opt.h
index b98261d..17ee2c7 100644
--- a/drivers/rmnet/perf/rmnet_perf_opt.h
+++ b/drivers/rmnet/perf/rmnet_perf_opt.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -17,7 +17,7 @@
 #include "rmnet_perf_core.h"
 
 #define RMNET_PERF_FLOW_HASH_TABLE_BITS        4
-#define RMNET_PERF_NUM_FLOW_NODES              8
+#define RMNET_PERF_NUM_FLOW_NODES             50
 
 struct rmnet_perf_opt_pkt_node {
 	unsigned char *header_start;