qcacld: IPA uC: Intra-BSS offload - forward non-IP exception packets to Tx

When enabled intra-BSS forwarding offload, non-IP exception packets should
be forwarded to Tx from the WLAN IPA exception callback function.

Change-Id: Ia6385f806527779e74e887d58eb1e349a6677d54
CRs-fixed: 770042
diff --git a/CORE/HDD/src/wlan_hdd_ipa.c b/CORE/HDD/src/wlan_hdd_ipa.c
index 897c12b..640c368 100644
--- a/CORE/HDD/src/wlan_hdd_ipa.c
+++ b/CORE/HDD/src/wlan_hdd_ipa.c
@@ -302,6 +302,8 @@
 	uint64_t num_freeq_empty;
 	uint64_t num_pri_freeq_empty;
 	uint64_t num_rx_excep;
+	uint64_t num_tx_bcmc;
+	uint64_t num_tx_bcmc_err;
 };
 
 #ifdef IPA_UC_OFFLOAD
@@ -1047,12 +1049,16 @@
 			"IND RING SIZE: %d\n"
 			"IND RING DBELL : 0x%x\n"
 			"PROC DONE IND ADDR : 0x%x\n"
-			"NUM EXCP PKT : %llu",
+			"NUM EXCP PKT : %llu\n"
+			"NUM TX BCMC : %llu\n"
+			"NUM TX BCMC ERR : %llu",
 			hdd_ctx->rx_rdy_ring_base_paddr,
 			hdd_ctx->rx_rdy_ring_size,
 			hdd_ctx->rx_ready_doorbell_paddr,
 			hdd_ctx->rx_proc_done_idx_paddr,
-			hdd_ipa->stats.num_rx_excep);
+			hdd_ipa->stats.num_rx_excep,
+			hdd_ipa->stats.num_tx_bcmc,
+			hdd_ipa->stats.num_tx_bcmc_err);
 		VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
 			"==== IPA_UC WLAN_HOST CONTROL ====\n"
 			"SAP NUM STAs: %d\n"
@@ -2163,8 +2169,14 @@
 	struct ipa_tx_data_desc *done_desc_head, *done_desc, *tmp;
 	adf_nbuf_t skb;
 	uint8_t iface_id;
+	struct hdd_ipa_iface_context *iface_context;
 #ifdef IPA_UC_OFFLOAD
 	uint8_t session_id;
+#ifdef INTRA_BSS_FWD_OFFLOAD
+	struct ethhdr *eth;
+	adf_nbuf_t copy;
+	int ret;
+#endif
 #endif
 	adf_nbuf_t buf;
 
@@ -2197,7 +2209,8 @@
 			return;
 		}
 
-		adapter = hdd_ipa->iface_context[iface_id].adapter;
+		iface_context = &hdd_ipa->iface_context[iface_id];
+		adapter = iface_context->adapter;
 
 		HDD_IPA_DBG_DUMP(VOS_TRACE_LEVEL_DEBUG,
 			"w2i -- skb", skb->data, 8);
@@ -2211,7 +2224,35 @@
 			skb_pull(skb, HDD_IPA_WLAN_CLD_HDR_LEN);
 		}
 
-		hdd_ipa->iface_context[iface_id].stats.num_rx_ipa_excep++;
+		iface_context->stats.num_rx_ipa_excep++;
+
+#if defined(IPA_UC_OFFLOAD) && defined(INTRA_BSS_FWD_OFFLOAD)
+		eth = (struct ethhdr *)skb->data;
+
+		/*
+		 * When INTRA_BSS_FWD_OFFLOAD is enabled, FW will send all Rx
+		 * packets to IPA uC, which need to be forwarded to other
+		 * interface.
+		 * And, since only IP packets are forwarded through IPA Ethernet
+		 * Bridging, non-IP exception packets should be forwarded to Tx
+		 * here.
+		 */
+		if (eth->h_proto != be16_to_cpu(ETH_P_IP)) {
+			copy = adf_nbuf_copy(skb);
+			if (copy) {
+				ret = hdd_softap_hard_start_xmit(
+					(struct sk_buff *)copy, adapter->dev);
+				if (ret) {
+					HDD_IPA_LOG(VOS_TRACE_LEVEL_DEBUG,
+						"Forward packet tx fail");
+					hdd_ipa->stats.num_tx_bcmc_err++;
+				} else {
+					hdd_ipa->stats.num_tx_bcmc++;
+				}
+			}
+		}
+#endif
+
 		hdd_ipa_send_skb_to_network(skb, adapter);
 		break;
 	case IPA_WRITE_DONE:
diff --git a/Kbuild b/Kbuild
index c9b55cd..d343bde 100755
--- a/Kbuild
+++ b/Kbuild
@@ -1203,6 +1203,7 @@
 CDEFINES += -DIPA_UC_OFFLOAD
 ifeq ($(CONFIG_ARCH_MDM9640), y)
 CDEFINES += -DIPA_UC_STA_OFFLOAD
+CDEFINES += -DINTRA_BSS_FWD_OFFLOAD
 else
 CDEFINES += -DQCA_CONFIG_SMP
 endif