Merge branch 'android-msm-bluecross-4.9' into android-msm-pixel-4.9

Bug: 119540871
Bug: 125674783
Change-Id: Idd4721ba47c5071ae51ce255fdabbfbf27eab69a
Signed-off-by: Robin Peng <robinpeng@google.com>
diff --git a/qdf/inc/qdf_crypto.h b/qdf/inc/qdf_crypto.h
index 1cd3394..a640a4a 100644
--- a/qdf/inc/qdf_crypto.h
+++ b/qdf/inc/qdf_crypto.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -47,6 +47,11 @@
 #define FIXED_PARAM_OFFSET_ASSOC_REQ 4
 #define FIXED_PARAM_OFFSET_ASSOC_RSP 6
 
+#ifdef WLAN_FEATURE_GMAC
+#define AAD_LEN 20
+#define IEEE80211_MMIE_GMAC_MICLEN  16
+#endif
+
 /* Function declarations and documenation */
 
 /**
@@ -133,6 +138,23 @@
  */
 int qdf_aes_ctr(const uint8_t *key, unsigned int key_len, uint8_t *siv,
 		const uint8_t *src, size_t src_len, uint8_t *dest, bool enc);
+
+/**
+ * qdf_crypto_aes_gmac: This API calculates MIC for GMAC
+ * @key: key used for operation
+ * @key_length: key length
+ * @iv: Initialization vector
+ * @aad: Additional authentication data
+ * @data: Pointer to data
+ * @data_len: Length of data
+ * @mic: Pointer to MIC
+ *
+ * Return: 0 if success else Error number
+ */
+int qdf_crypto_aes_gmac(uint8_t *key, uint16_t key_length,
+			uint8_t *iv, uint8_t *aad, uint8_t *data,
+			uint16_t data_len, uint8_t *mic);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/qdf/inc/qdf_nbuf.h b/qdf/inc/qdf_nbuf.h
index 53f2eb7..e7f7578 100644
--- a/qdf/inc/qdf_nbuf.h
+++ b/qdf/inc/qdf_nbuf.h
@@ -2437,6 +2437,17 @@
 	__qdf_nbuf_reset_ctxt(nbuf);
 }
 
+static inline void
+qdf_nbuf_set_rx_info(__qdf_nbuf_t nbuf, void *info, uint32_t len)
+{
+	__qdf_nbuf_set_rx_info(nbuf, info, len);
+}
+
+static inline void *qdf_nbuf_get_rx_info(__qdf_nbuf_t nbuf)
+{
+	return __qdf_nbuf_get_rx_info(nbuf);
+}
+
 static inline void qdf_nbuf_init(qdf_nbuf_t buf)
 {
 	__qdf_nbuf_init(buf);
diff --git a/qdf/linux/src/i_qdf_nbuf.h b/qdf/linux/src/i_qdf_nbuf.h
index 6b96fdd..fe9602e 100644
--- a/qdf/linux/src/i_qdf_nbuf.h
+++ b/qdf/linux/src/i_qdf_nbuf.h
@@ -1522,6 +1522,42 @@
 	skb_reset_tail_pointer(nbuf);
 }
 
+/**
+ * __qdf_nbuf_set_rx_info() - set rx info
+ * @nbuf: sk buffer
+ * @info: rx info
+ * @len: length
+ *
+ * Return: none
+ */
+static inline void
+__qdf_nbuf_set_rx_info(__qdf_nbuf_t nbuf, void *info, uint32_t len)
+{
+	/* Customer may have skb->cb size increased, e.g. to 96 bytes,
+	 * then len's large enough to save the rs status info struct
+	 */
+	uint8_t offset = sizeof(struct qdf_nbuf_cb);
+	uint32_t max = sizeof(((struct sk_buff *)0)->cb)-offset;
+
+	len = (len > max ? max : len);
+
+	memcpy(((uint8_t *)(nbuf->cb) + offset), info, len);
+}
+
+/**
+ * __qdf_nbuf_get_rx_info() - get rx info
+ * @nbuf: sk buffer
+ *
+ * Return: rx_info
+ */
+static inline void *
+__qdf_nbuf_get_rx_info(__qdf_nbuf_t nbuf)
+{
+	uint8_t offset = sizeof(struct qdf_nbuf_cb);
+
+	return (void *)((uint8_t *)(nbuf->cb) + offset);
+}
+
 /*
  *  __qdf_nbuf_get_cb() - returns a pointer to skb->cb
  * @nbuf: sk buff
diff --git a/qdf/linux/src/i_qdf_timer.h b/qdf/linux/src/i_qdf_timer.h
index 8f3a20b..378b5b8 100644
--- a/qdf/linux/src/i_qdf_timer.h
+++ b/qdf/linux/src/i_qdf_timer.h
@@ -70,7 +70,7 @@
 	if (type == QDF_TIMER_TYPE_SW) {
 		if (object_is_on_stack(timer))
 			setup_deferrable_timer_on_stack(timer, func,
-							(unsigned long)arg);
+			    (unsigned long)arg);
 		else
 			setup_deferrable_timer(timer, func,
 					       (unsigned long)arg);
diff --git a/qdf/linux/src/qdf_crypto.c b/qdf/linux/src/qdf_crypto.c
index af6d456..80ccd96 100644
--- a/qdf/linux/src/qdf_crypto.c
+++ b/qdf/linux/src/qdf_crypto.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -28,6 +28,8 @@
 #include <crypto/hash.h>
 #include <crypto/aes.h>
 #include <crypto/skcipher.h>
+#include <crypto/aead.h>
+#include <linux/ieee80211.h>
 
 /* Function Definitions and Documentation */
 #define MAX_HMAC_ELEMENT_CNT 10
@@ -352,3 +354,85 @@
 	return -EINVAL;
 }
 #endif
+
+#if defined(WLAN_FEATURE_GMAC) && \
+		(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
+int qdf_crypto_aes_gmac(uint8_t *key, uint16_t key_length,
+			uint8_t *iv, uint8_t *aad, uint8_t *data,
+			uint16_t data_len, uint8_t *mic)
+{
+	struct crypto_aead *tfm;
+	int ret = 0;
+	struct scatterlist sg[4];
+	uint16_t req_size;
+	struct aead_request *req = NULL;
+	uint8_t *aad_ptr, *input;
+
+	tfm = crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC);
+	if (IS_ERR(tfm)) {
+		ret = PTR_ERR(tfm);
+		tfm = NULL;
+		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
+			  "%s: crypto_alloc_aead failed (%d)", __func__, ret);
+		goto err_tfm;
+	}
+
+	ret = crypto_aead_setkey(tfm, key, key_length);
+	if (ret) {
+		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
+			  "crypto_aead_setkey failed (%d)", ret);
+		goto err_tfm;
+	}
+
+	ret = crypto_aead_setauthsize(tfm, IEEE80211_MMIE_GMAC_MICLEN);
+	if (ret) {
+		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
+			  "crypto_aead_setauthsize failed (%d)", ret);
+		goto err_tfm;
+	}
+
+	/* Prepare aead request */
+	req_size = sizeof(*req) + crypto_aead_reqsize(tfm) +
+			IEEE80211_MMIE_GMAC_MICLEN + AAD_LEN;
+	req = qdf_mem_malloc(req_size);
+	if (!req) {
+		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
+			  "Memory allocation failed");
+		ret = -ENOMEM;
+		goto err_tfm;
+	}
+
+	input = (uint8_t *)req + sizeof(*req) + crypto_aead_reqsize(tfm);
+	aad_ptr = input + IEEE80211_MMIE_GMAC_MICLEN;
+	qdf_mem_copy(aad_ptr, aad, AAD_LEN);
+
+	/* Scatter list operations */
+	sg_init_table(sg, 4);
+	sg_set_buf(&sg[0], aad_ptr, AAD_LEN);
+	sg_set_buf(&sg[1], data, data_len);
+	sg_set_buf(&sg[2], input, IEEE80211_MMIE_GMAC_MICLEN);
+	sg_set_buf(&sg[3], mic, IEEE80211_MMIE_GMAC_MICLEN);
+
+	aead_request_set_tfm(req, tfm);
+	aead_request_set_crypt(req, sg, sg, 0, iv);
+	aead_request_set_ad(req,
+			    AAD_LEN + data_len + IEEE80211_MMIE_GMAC_MICLEN);
+	crypto_aead_encrypt(req);
+
+err_tfm:
+	if (tfm)
+		crypto_free_aead(tfm);
+
+	if (req)
+		qdf_mem_free(req);
+
+	return ret;
+}
+#else
+int qdf_crypto_aes_gmac(uint8_t *key, uint16_t key_length,
+			uint8_t *iv, uint8_t *aad, uint8_t *data,
+			uint16_t data_len, uint8_t *mic)
+{
+	return -EINVAL;
+}
+#endif
diff --git a/qdf/linux/src/qdf_nbuf.c b/qdf/linux/src/qdf_nbuf.c
index 025526f..3f1edf3 100644
--- a/qdf/linux/src/qdf_nbuf.c
+++ b/qdf/linux/src/qdf_nbuf.c
@@ -296,16 +296,13 @@
 		size += (align - 1);
 
 	if (in_interrupt() || irqs_disabled() || in_atomic()) {
-		flags = GFP_ATOMIC;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)
 		/*
 		 * Observed that kcompactd burns out CPU to make order-3 page.
 		 *__netdev_alloc_skb has 4k page fallback option just in case of
 		 * failing high order page allocation so we don't need to be
 		 * hard. Make kcompactd rest in piece.
 		 */
-		flags = flags & ~__GFP_KSWAPD_RECLAIM;
-#endif
+		flags = GFP_ATOMIC & ~__GFP_KSWAPD_RECLAIM;
 	}
 
 	skb = __netdev_alloc_skb(NULL, size, flags);
diff --git a/wmi/src/wmi_unified.c b/wmi/src/wmi_unified.c
index a255129..61ffee0 100644
--- a/wmi/src/wmi_unified.c
+++ b/wmi/src/wmi_unified.c
@@ -1388,7 +1388,6 @@
 		return QDF_STATUS_E_NOMEM;
 	}
 
-	qdf_mem_zero(qdf_nbuf_data(buf), sizeof(WMI_CMD_HDR));
 	WMI_SET_FIELD(qdf_nbuf_data(buf), WMI_CMD_HDR, COMMANDID, cmd_id);
 
 	qdf_atomic_inc(&wmi_handle->pending_cmds);