[DTV00922135] p2p: multiple p2p ie support in probe resp

[Description]
Add multiple p2p ie support

Symptom:
When MT7668 act as GO, after 5th GC connected, 6th p2p devices can not
find MT7668

Root cause:
When upper layer call mgmt tx to request driver send probe response,
if it includes multiple p2p ie, driver only store the last one.
It is because that p2p ie is stored in wsc ie struct and which
 is only one array for it.
Trace wpas_supplicant, when total p2p ie is over 251
(fragment length, 0xff - 4 byte OUI)
wpa_supplicant will divide it to multiple p2p ie

Modification:
1. refine vendor specific ie definition, 300 should be enough
2. refine structure for storing probe response p2p ie, assume max 4
   multiple ie will append
3. add p2p ie operation functions

Change-Id: I67e1192764f2423da0c02aec892083beab70ad70
CR-Id: DTV00922135
Signed-off-by: guo-jie.wang <guo-jie.wang@mediatek.com>
Feature: p2p
Reviewed-on: http://gerrit.mediatek.inc:8080/1301185
CheckPatch: Check Patch <srv_checkpatch@mediatek.com>
Reviewed-by: George Kuo <george.kuo@mediatek.com>
Reviewed-by: Deren Wu <deren.wu@mediatek.com>
Build: srv_neptune_adm <srv_neptune_adm@mediatek.com>
Test: srv_neptune_adm <srv_neptune_adm@mediatek.com>
diff --git a/mgmt/p2p_func.c b/mgmt/p2p_func.c
index ab4fc43..ef0d9b1 100644
--- a/mgmt/p2p_func.c
+++ b/mgmt/p2p_func.c
@@ -3250,12 +3250,18 @@
 	BOOLEAN fgIsWFDIE = FALSE;
 	P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL;
 	UINT_16 u2EstimateSize = 0, u2EstimatedExtraIELen = 0;
-	UINT_32 u4IeArraySize = 0, u4Idx = 0;
+	UINT_32 u4IeArraySize = 0, u4Idx = 0, i = 0;
+	P_GLUE_INFO_T prGlueInfo = NULL;
 
 	do {
 		ASSERT_BREAK((prAdapter != NULL) && (prMgmtTxMsdu != NULL));
 
 		prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx);
+		prGlueInfo = prAdapter->prGlueInfo;
+		if (!prGlueInfo) {
+			DBGLOG(P2P, ERROR, "NULL prGlueInfo\n");
+			break;
+		}
 
 		/* 3 Make sure this is probe response frame. */
 		prProbeRspFrame = (P_WLAN_PROBE_RSP_FRAME_T) ((ULONG) prMgmtTxMsdu->prPacket + MAC_TX_RESERVED_FIELD);
@@ -3272,7 +3278,8 @@
 		/* Reset in each time ?? */
 		prAdapter->prGlueInfo->prP2PInfo[prP2pBssInfo->u4PrivateData]->u2WFDIELen = 0;
 #endif
-
+		kalP2PResetP2P_IE(prGlueInfo,
+			(UINT_8) prP2pBssInfo->u4PrivateData);
 		IE_FOR_EACH(pucIEBuf, u2IELength, u2Offset) {
 			switch (IE_ID(pucIEBuf)) {
 			case ELEM_ID_SSID:
@@ -3326,8 +3333,11 @@
 			(UINT_8) prP2pBssInfo->u4PrivateData);
 
 		if (fgIsP2PIE) {
-			u2EstimatedExtraIELen += kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 1,
-				(UINT_8) prP2pBssInfo->u4PrivateData);
+			for (i = 0; i < MAX_MULTI_P2P_IE_COUNT; i++) {
+				u2EstimatedExtraIELen +=
+					kalP2PCalP2P_IELen(prGlueInfo, i,
+					(UINT_8) prP2pBssInfo->u4PrivateData);
+			}
 			u2EstimatedExtraIELen += p2pFuncCalculateP2P_IE_NoA(prAdapter, ucBssIdx, NULL);
 		}
 #if CFG_SUPPORT_WFD
@@ -3390,16 +3400,17 @@
 		}
 
 		if (fgIsP2PIE) {
-			kalP2PGenWSC_IE(prAdapter->prGlueInfo,
-					1,
-					(PUINT_8) ((ULONG) prRetMsduInfo->prPacket +
-						   (ULONG) prRetMsduInfo->u2FrameLength),
-						   (UINT_8) prP2pBssInfo->u4PrivateData);
+			for (i = 0; i < MAX_MULTI_P2P_IE_COUNT; i++) {
+				kalP2PGenP2P_IE(prGlueInfo, i,
+				(PUINT_8) ((ULONG) prRetMsduInfo->prPacket +
+					(ULONG) prRetMsduInfo->u2FrameLength),
+					(UINT_8) prP2pBssInfo->u4PrivateData);
+				prRetMsduInfo->u2FrameLength +=
+					kalP2PCalP2P_IELen(prGlueInfo, i,
+					(UINT_8) prP2pBssInfo->u4PrivateData);
+			}
 
-			prRetMsduInfo->u2FrameLength += (UINT_16) kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 1,
-				(UINT_8) prP2pBssInfo->u4PrivateData);
 			p2pFuncGenerateP2P_IE_NoA(prAdapter, prRetMsduInfo);
-
 		}
 #if CFG_SUPPORT_WFD
 
@@ -3479,10 +3490,8 @@
 
 		} else if (p2pFuncParseCheckForP2PInfoElem(prAdapter, pucIEBuf, &ucOuiType)) {
 			if (ucOuiType == VENDOR_OUI_TYPE_P2P) {
-				/* 2 Note(frog): I use WSC IE buffer for Probe Request
-				 * to store the P2P IE for Probe Response.
-				 */
-				kalP2PUpdateWSC_IE(prAdapter->prGlueInfo, 1, pucIEBuf, IE_SIZE(pucIEBuf),
+				kalP2PUpdateP2P_IE(prAdapter->prGlueInfo,
+					pucIEBuf, IE_SIZE(pucIEBuf),
 					(UINT_8) ((P_BSS_INFO_T)*prP2pBssInfo)->u4PrivateData);
 				*fgIsP2PIE = TRUE;
 			}
diff --git a/os/linux/gl_p2p_kal.c b/os/linux/gl_p2p_kal.c
index f1b32e4..457b109 100644
--- a/os/linux/gl_p2p_kal.c
+++ b/os/linux/gl_p2p_kal.c
@@ -548,9 +548,9 @@
 		if ((prGlueInfo == NULL) || (ucType >= 4) || ((u2BufferLength > 0) && (pucBuffer == NULL)))
 			break;
 
-		if (u2BufferLength > 400) {
-			DBGLOG(P2P, ERROR,
-			       "Buffer length is not enough, GLUE only 400 bytes but %d received\n", u2BufferLength);
+		if (u2BufferLength > VENDOR_SPECIFIC_IE_LENGTH) {
+			DBGLOG(P2P, ERROR, "Allow %d bytes but %d received\n",
+				VENDOR_SPECIFIC_IE_LENGTH, u2BufferLength);
 			ASSERT(FALSE);
 			break;
 		}
@@ -565,6 +565,98 @@
 
 }				/* kalP2PUpdateWSC_IE */
 
+UINT_16 kalP2PCalP2P_IELen(IN P_GLUE_INFO_T prGlueInfo,
+	IN UINT_32 u4IEIdx, IN UINT_8 ucRoleIdx)
+{
+	if (u4IEIdx >= MAX_MULTI_P2P_IE_COUNT)
+		return 0;
+
+	return prGlueInfo->prP2PInfo[ucRoleIdx]->u2P2PIELen[u4IEIdx];
+}
+
+/* kalP2PGenP2P_IE
+ * append p2p ie to output frame
+ */
+VOID kalP2PGenP2P_IE(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4IEIdx,
+	IN PUINT_8 pucBuffer, IN UINT_8 ucRoleIdx)
+{
+	P_GL_P2P_INFO_T prGlP2pInfo = (P_GL_P2P_INFO_T) NULL;
+
+	if (!pucBuffer)
+		return;
+
+	if (u4IEIdx >= MAX_MULTI_P2P_IE_COUNT)
+		return;
+
+	prGlP2pInfo = prGlueInfo->prP2PInfo[ucRoleIdx];
+
+	if (prGlP2pInfo->u2P2PIELen[u4IEIdx] > 0)
+		kalMemCopy(pucBuffer, prGlP2pInfo->aucP2PIE[u4IEIdx],
+			prGlP2pInfo->u2P2PIELen[u4IEIdx]);
+}
+
+VOID kalP2PResetP2P_IE(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucRoleIdx)
+{
+	P_GL_P2P_INFO_T prGlP2pInfo = (P_GL_P2P_INFO_T) NULL;
+	UINT_32 u4IEIdx = MAX_MULTI_P2P_IE_COUNT;
+
+	prGlP2pInfo = prGlueInfo->prP2PInfo[ucRoleIdx];
+
+	while (u4IEIdx-- > 0)
+		prGlP2pInfo->u2P2PIELen[u4IEIdx] = 0;
+}
+
+/* kalP2PUpdateP2P_IE
+ * copy multiple p2p ie to local buffer
+ */
+VOID kalP2PUpdateP2P_IE(IN P_GLUE_INFO_T prGlueInfo,
+	IN PUINT_8 pucBuffer, IN UINT_16 u2BufferLength, IN UINT_8 ucRoleIdx)
+{
+	P_GL_P2P_INFO_T prGlP2pInfo = (P_GL_P2P_INFO_T) NULL;
+	UINT_32 u4IEIdx;
+
+	if (!prGlueInfo) {
+		DBGLOG(P2P, ERROR, "NULL prGlueInfo!\n");
+		return;
+	}
+
+	if (!pucBuffer) {
+		DBGLOG(P2P, ERROR, "NULL pucBuffer!\n");
+		return;
+	}
+
+	if (u2BufferLength == 0) {
+		DBGLOG(P2P, WARN, "0 IE length, skip update\n");
+		return;
+	}
+
+	if (u2BufferLength > VENDOR_SPECIFIC_IE_LENGTH) {
+		DBGLOG(P2P, ERROR, "Allow %d bytes but %d received\n",
+			VENDOR_SPECIFIC_IE_LENGTH, u2BufferLength);
+		return;
+	}
+
+	DBGLOG(P2P, TRACE, "ucRoleIdx=%d, u2BufferLength=%d\n",
+		ucRoleIdx, u2BufferLength);
+
+	prGlP2pInfo = prGlueInfo->prP2PInfo[ucRoleIdx];
+
+	for (u4IEIdx = 0; u4IEIdx < MAX_MULTI_P2P_IE_COUNT; u4IEIdx++) {
+		if (prGlP2pInfo->u2P2PIELen[u4IEIdx] == 0) {
+			DBGLOG(P2P, INFO,
+				"ucRoleIdx=%d, u4IEIdx=%d, u2BufferLength=%d\n",
+				ucRoleIdx, u4IEIdx, u2BufferLength);
+			kalMemCopy(prGlP2pInfo->aucP2PIE[u4IEIdx],
+				pucBuffer, u2BufferLength);
+			prGlP2pInfo->u2P2PIELen[u4IEIdx] = u2BufferLength;
+			break;
+		}
+	}
+
+	if (u4IEIdx == MAX_MULTI_P2P_IE_COUNT)
+		DBGLOG(P2P, WARN, "No available aucP2PIE\n");
+}
+
 #if 0
 /*----------------------------------------------------------------------------*/
 /*!
diff --git a/os/linux/include/gl_p2p_kal.h b/os/linux/include/gl_p2p_kal.h
index 5b90a56..339d4d1 100644
--- a/os/linux/include/gl_p2p_kal.h
+++ b/os/linux/include/gl_p2p_kal.h
@@ -177,6 +177,15 @@
 VOID kalP2PUpdateWSC_IE(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucType, IN PUINT_8 pucBuffer,
 	IN UINT_16 u2BufferLength, IN UINT_8 ucRoleIdx);
 
+UINT_16 kalP2PCalP2P_IELen(IN P_GLUE_INFO_T prGlueInfo,
+	IN UINT_32 u4IEIdx, IN UINT_8 ucRoleIdx);
+VOID kalP2PGenP2P_IE(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4IEIdx,
+	IN PUINT_8 pucBuffer, IN UINT_8 ucRoleIdx);
+VOID kalP2PResetP2P_IE(IN P_GLUE_INFO_T prGlueInfo,
+	IN UINT_8 ucRoleIdx);
+VOID kalP2PUpdateP2P_IE(IN P_GLUE_INFO_T prGlueInfo,
+	IN PUINT_8 pucBuffer, IN UINT_16 u2BufferLength, IN UINT_8 ucRoleIdx);
+
 BOOLEAN kalP2PIndicateFound(IN P_GLUE_INFO_T prGlueInfo);
 
 VOID kalP2PIndicateConnReq(IN P_GLUE_INFO_T prGlueInfo, IN PUINT_8 pucDevName, IN INT_32 u4NameLength,
diff --git a/os/linux/include/gl_p2p_os.h b/os/linux/include/gl_p2p_os.h
index 0862987..2d01699 100644
--- a/os/linux/include/gl_p2p_os.h
+++ b/os/linux/include/gl_p2p_os.h
@@ -66,6 +66,8 @@
 #ifndef _GL_P2P_OS_H
 #define _GL_P2P_OS_H
 
+#define VENDOR_SPECIFIC_IE_LENGTH 300 /* 1(IE) + 1(length) + 0xff(max length) */
+#define MAX_MULTI_P2P_IE_COUNT 4
 /*******************************************************************************
 *                         C O M P I L E R   F L A G S
 ********************************************************************************
@@ -172,11 +174,15 @@
 	UINT_32 u4CipherPairwise;
 	/*UINT_8 ucWSCRunning;*//* TH3 multiple P2P */
 
-	UINT_8 aucWSCIE[4][400];	/* 0 for beacon, 1 for probe req, 2 for probe response, 3 for assoc response */
+	/* 0: beacon, 1: probe req, 2: probe response, 3: assoc response */
+	UINT_8 aucWSCIE[4][VENDOR_SPECIFIC_IE_LENGTH];
 	UINT_16 u2WSCIELen[4];
 
+	UINT_8 aucP2PIE[MAX_MULTI_P2P_IE_COUNT][VENDOR_SPECIFIC_IE_LENGTH];
+	UINT_16 u2P2PIELen[MAX_MULTI_P2P_IE_COUNT];
+
 #if CFG_SUPPORT_WFD
-	UINT_8 aucWFDIE[400];	/* 0 for beacon, 1 for probe req, 2 for probe response */
+	UINT_8 aucWFDIE[VENDOR_SPECIFIC_IE_LENGTH];
 	UINT_16 u2WFDIELen;
 	/* UINT_8                      aucVenderIE[1024]; *//* Save the other IE for prove resp */
 /* UINT_16                     u2VenderIELen; */