Browse Source

qcacld-3.0: Send WOW timer pattern to firmware

Send WOW timer pattern to firmware when suspend is requested and
INSTALL_KEY is not sent to firmware yet. This will allow firmware
to wake host in case Eapol frames are not received and do a graceful
disconnect.

Change-Id: Ibbcc0af85ee9ddcd7f6559c83c67274508193004
CRs-Fixed: 2127634
Naveen Rawat 7 years ago
parent
commit
d773414489

+ 2 - 1
components/target_if/pmo/src/target_if_pmo_suspend_resume.c

@@ -22,7 +22,7 @@
  * send suspend / resume related cmd and process event.
  */
 
-
+#include "wma.h"
 #include "target_if.h"
 #include "target_if_pmo.h"
 #include "wmi_unified_api.h"
@@ -142,6 +142,7 @@ QDF_STATUS target_if_pmo_psoc_send_wow_enable_req(
 		struct wlan_objmgr_psoc *psoc,
 		struct pmo_wow_cmd_params *param)
 {
+	wma_check_and_set_wake_timer(SIR_INSTALL_KEY_TIMEOUT_MS);
 	return wmi_unified_wow_enable_send(GET_WMI_HDL_FROM_PSOC(psoc),
 			(struct wow_cmd_params *)param,
 			TGT_WILDCARD_PDEV_ID);

+ 14 - 0
core/mac/src/include/sir_params.h

@@ -45,6 +45,20 @@
 #define WAKELOCK_DURATION_RECOMMENDED	1000
 #define WAKELOCK_DURATION_MAX		3000
 
+
+#define SYSTEM_TIME_MSEC_TO_USEC      1000
+#define SYSTEM_TIME_SEC_TO_MSEC       1000
+#define SYSTEM_TIME_NSEC_TO_USEC      1000
+
+/*
+ * Following time is used to program WOW_TIMER_PATTERN to FW so that FW will
+ * wake host up to do graceful disconnect in case PEER remains un-authorized
+ * for this long.
+ */
+#define SIR_INSTALL_KEY_TIMEOUT_SEC      70
+#define SIR_INSTALL_KEY_TIMEOUT_MS       \
+			(SIR_INSTALL_KEY_TIMEOUT_SEC * SYSTEM_TIME_SEC_TO_MSEC)
+
 /* defines for WPS config states */
 #define       SAP_WPS_DISABLED             0
 #define       SAP_WPS_ENABLED_UNCONFIGURED 1

+ 3 - 2
core/sme/src/csr/csr_api_roam.c

@@ -65,8 +65,9 @@
 
 #define CSR_NUM_IBSS_START_CHAN_50      5
 #define CSR_NUM_IBSS_START_CHANNELS_24      3
-/* 75 seconds, for WPA, WPA2, CCKM */
-#define CSR_WAIT_FOR_KEY_TIMEOUT_PERIOD     (75 * QDF_MC_TIMER_TO_SEC_UNIT)
+/* 70 seconds, for WPA, WPA2, CCKM */
+#define CSR_WAIT_FOR_KEY_TIMEOUT_PERIOD     \
+	(SIR_INSTALL_KEY_TIMEOUT_SEC * QDF_MC_TIMER_TO_SEC_UNIT)
 /* 120 seconds, for WPS */
 #define CSR_WAIT_FOR_WPS_KEY_TIMEOUT_PERIOD (120 * QDF_MC_TIMER_TO_SEC_UNIT)
 

+ 0 - 3
core/sme/src/csr/csr_inside_api.h

@@ -62,9 +62,6 @@
 #define CSR_MAX_2_4_GHZ_SUPPORTED_CHANNELS 14
 
 #define CSR_MAX_BSS_SUPPORT            512
-#define SYSTEM_TIME_MSEC_TO_USEC      1000
-#define SYSTEM_TIME_SEC_TO_MSEC       1000
-#define SYSTEM_TIME_NSEC_TO_USEC      1000
 
 /* This number minus 1 means the number of times a channel is scanned before
  * a BSS is remvoed from

+ 10 - 0
core/wma/inc/wma.h

@@ -1145,6 +1145,7 @@ struct wma_txrx_node {
 	qdf_wake_lock_t vdev_stop_wakelock;
 	qdf_wake_lock_t vdev_set_key_wakelock;
 	struct roam_synch_frame_ind roam_synch_frame_ind;
+	bool is_waiting_for_key;
 };
 
 #if defined(QCA_WIFI_FTM)
@@ -2659,4 +2660,13 @@ QDF_STATUS wma_get_chain_rssi(tp_wma_handle wma_handle,
 QDF_STATUS wma_config_bmiss_bcnt_params(uint32_t vdev_id, uint32_t first_cnt,
 		uint32_t final_cnt);
 
+/**
+ * wma_check_and_set_wake_timer(): checks all interfaces and if any interface
+ * has install_key pending, sets timer pattern in fw to wake up host after
+ * specified time has elapsed.
+ * @time: time after which host wants to be awaken.
+ *
+ * Return: None
+ */
+void wma_check_and_set_wake_timer(uint32_t time);
 #endif

+ 2 - 0
core/wma/src/wma_dev_if.c

@@ -3896,6 +3896,8 @@ static void wma_add_bss_sta_mode(tp_wma_handle wma, tpAddBssParams add_bss)
 				pps_val, status);
 		wma_send_peer_assoc(wma, add_bss->nwType,
 					    &add_bss->staContext);
+		/* we just had peer assoc, so install key will be done later */
+		iface->is_waiting_for_key = true;
 		peer_assoc_sent = true;
 
 		if (add_bss->rmfEnabled)

+ 74 - 0
core/wma/src/wma_features.c

@@ -1185,6 +1185,69 @@ QDF_STATUS wma_unified_fw_profiling_cmd(wmi_unified_t wmi_handle,
 	return QDF_STATUS_SUCCESS;
 }
 
+/**
+ * wma_wow_set_wake_time() - set timer pattern tlv, so that firmware will wake
+ * up host after specified time is elapsed
+ * @wma_handle: wma handle
+ * @vdev_id: vdev id
+ * @cookie: value to identify reason why host set up wake call.
+ * @time: time in ms
+ *
+ * Return: QDF status
+ */
+static QDF_STATUS wma_wow_set_wake_time(WMA_HANDLE wma_handle, uint8_t vdev_id,
+					uint32_t cookie, uint32_t time)
+{
+	int ret;
+	tp_wma_handle wma = (tp_wma_handle)wma_handle;
+
+	WMA_LOGD(FL("send timer patter with time: %d and vdev = %d to fw"),
+		    time, vdev_id);
+	ret = wmi_unified_wow_timer_pattern_cmd(wma->wmi_handle, vdev_id,
+						cookie, time);
+	if (ret) {
+		WMA_LOGE(FL("Failed to send timer patter to fw"));
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * wma_check_and_set_wake_timer(): checks all interfaces and if any interface
+ * has install_key pending, sets timer pattern in fw to wake up host after
+ * specified time has elapsed.
+ * @wma: wma handle
+ * @time: time after which host wants to be awaken.
+ *
+ * Return: None
+ */
+void wma_check_and_set_wake_timer(uint32_t time)
+{
+	int i;
+	struct wma_txrx_node *iface;
+	t_wma_handle *wma = cds_get_context(QDF_MODULE_ID_WMA);
+
+	if (!WMI_SERVICE_EXT_IS_ENABLED(wma->wmi_service_bitmap,
+		wma->wmi_service_ext_bitmap,
+		WMI_SERVICE_WOW_WAKEUP_BY_TIMER_PATTERN)) {
+		WMA_LOGD("TIME_PATTERN is not enabled");
+		return;
+	}
+
+	for (i = 0; i < wma->max_bssid; i++) {
+		iface = &wma->interfaces[i];
+		if (iface->is_vdev_valid && iface->is_waiting_for_key) {
+			/*
+			 * right now cookie is dont care, since FW disregards
+			 * that.
+			 */
+			wma_wow_set_wake_time((WMA_HANDLE)wma, i, 0, time);
+			break;
+		}
+	}
+}
+
 /**
  * wmi_unified_nat_keepalive_enable() - enable NAT keepalive filter
  * @wma: wma handle
@@ -2721,6 +2784,17 @@ static int wma_wake_event_piggybacked(
 		errno = wma_tdls_event_handler(wma, pb_event, pb_event_len);
 		break;
 #endif
+
+	case WOW_REASON_TIMER_INTR_RECV:
+		/*
+		 * Right now firmware is not returning any cookie host has
+		 * programmed. So do not check for cookie.
+		 */
+		WMA_LOGE("WOW_REASON_TIMER_INTR_RECV received, indicating key exchange did not finish. Initiate disconnect");
+		errno = wma_peer_sta_kickout_event_handler(wma, pb_event,
+							   pb_event_len);
+		break;
+
 	default:
 		WMA_LOGE("Wake reason %s(%u) is not a piggybacked event",
 			 wma_wow_wake_reason_str(wake_reason), wake_reason);

+ 2 - 0
core/wma/src/wma_main.c

@@ -2400,6 +2400,7 @@ void wma_vdev_init(struct wma_txrx_node *vdev)
 	qdf_wake_lock_create(&vdev->vdev_start_wakelock, "vdev_start");
 	qdf_wake_lock_create(&vdev->vdev_stop_wakelock, "vdev_stop");
 	qdf_wake_lock_create(&vdev->vdev_set_key_wakelock, "vdev_set_key");
+	vdev->is_waiting_for_key = false;
 }
 
 void wma_vdev_deinit(struct wma_txrx_node *vdev)
@@ -2407,6 +2408,7 @@ void wma_vdev_deinit(struct wma_txrx_node *vdev)
 	qdf_wake_lock_destroy(&vdev->vdev_start_wakelock);
 	qdf_wake_lock_destroy(&vdev->vdev_stop_wakelock);
 	qdf_wake_lock_destroy(&vdev->vdev_set_key_wakelock);
+	vdev->is_waiting_for_key = false;
 }
 
 /**

+ 4 - 0
core/wma/src/wma_mgmt.c

@@ -1805,6 +1805,10 @@ static QDF_STATUS wma_setup_install_key_cmd(tp_wma_handle wma_handle,
 		WMA_LOGD("Release set key wake lock");
 		wma_release_wakelock(&iface->vdev_set_key_wakelock);
 	}
+
+	/* install key was requested */
+	iface->is_waiting_for_key = false;
+
 end:
 	qdf_mem_free(params.key_rsc_counter);
 	return status;