Browse Source

qcacld-3.0: Handle FW rejuvenate scenario

Upon driver reinitialize after a FW rejuvenate,
data packets are not going through IPA path.

Check for FW rejuvenate scenario during driver
recovery and send appropriate message to IPA
driver.

Change-Id: I8c1d7ba78227684cd5653a5927aa4d4c2ce5d354
Crs-Fixed: 2287293
jitiphil 6 years ago
parent
commit
0e3b592aed

+ 9 - 0
components/ipa/core/inc/wlan_ipa_core.h

@@ -650,5 +650,14 @@ void wlan_ipa_cleanup_dev_iface(struct wlan_ipa_priv *ipa_ctx,
  * Return: None
  */
 void wlan_ipa_uc_ssr_cleanup(struct wlan_ipa_priv *ipa_ctx);
+
+/**
+ * wlan_ipa_fw_rejuvenate_send_msg() - send fw rejuvenate message to IPA driver
+ * @ipa_ctx: IPA context
+ *
+ * Return: void
+ */
+void wlan_ipa_fw_rejuvenate_send_msg(struct wlan_ipa_priv *ipa_ctx);
+
 #endif /* IPA_OFFLOAD */
 #endif /* _WLAN_IPA_CORE_H_ */

+ 9 - 0
components/ipa/core/inc/wlan_ipa_main.h

@@ -413,5 +413,14 @@ void ipa_cleanup_dev_iface(struct wlan_objmgr_pdev *pdev,
  * Return: None
  */
 void ipa_uc_ssr_cleanup(struct wlan_objmgr_pdev *pdev);
+
+/**
+ * ipa_fw_rejuvenate_send_msg() - send fw rejuvenate message to IPA driver
+ * @pdev: pdev obj
+ *
+ * Return: None
+ */
+void ipa_fw_rejuvenate_send_msg(struct wlan_objmgr_pdev *pdev);
+
 #endif /* IPA_OFFLOAD */
 #endif /* end  of _WLAN_IPA_MAIN_H_ */

+ 26 - 0
components/ipa/core/src/wlan_ipa_core.c

@@ -3004,3 +3004,29 @@ void wlan_ipa_uc_ssr_cleanup(struct wlan_ipa_priv *ipa_ctx)
 		}
 	}
 }
+
+void wlan_ipa_fw_rejuvenate_send_msg(struct wlan_ipa_priv *ipa_ctx)
+{
+	qdf_ipa_msg_meta_t meta;
+	qdf_ipa_wlan_msg_t *msg;
+	int ret;
+
+	meta.msg_len = sizeof(*msg);
+	msg = qdf_mem_malloc(meta.msg_len);
+	if (!msg) {
+		ipa_debug("msg allocation failed");
+		return;
+	}
+
+	QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_FWR_SSR_BEFORE_SHUTDOWN);
+	ipa_debug("ipa_send_msg(Evt:%d)",
+		  meta.msg_type);
+	ret = qdf_ipa_send_msg(&meta, msg, wlan_ipa_msg_free_fn);
+
+	if (ret) {
+		ipa_err("ipa_send_msg(Evt:%d)-fail=%d",
+			meta.msg_type, ret);
+		qdf_mem_free(msg);
+	}
+	ipa_ctx->stats.num_send_msg++;
+}

+ 13 - 0
components/ipa/core/src/wlan_ipa_main.c

@@ -589,3 +589,16 @@ void ipa_uc_ssr_cleanup(struct wlan_objmgr_pdev *pdev)
 
 	return wlan_ipa_uc_ssr_cleanup(ipa_obj);
 }
+
+void ipa_fw_rejuvenate_send_msg(struct wlan_objmgr_pdev *pdev)
+{
+	struct wlan_ipa_priv *ipa_obj;
+
+	ipa_obj = ipa_pdev_get_priv_obj(pdev);
+	if (!ipa_obj) {
+		ipa_err("IPA object is NULL");
+		return;
+	}
+
+	return wlan_ipa_fw_rejuvenate_send_msg(ipa_obj);
+}

+ 14 - 0
components/ipa/dispatcher/inc/wlan_ipa_ucfg_api.h

@@ -323,6 +323,15 @@ void ucfg_ipa_cleanup_dev_iface(struct wlan_objmgr_pdev *pdev,
  * Return: None
  */
 void ucfg_ipa_uc_ssr_cleanup(struct wlan_objmgr_pdev *pdev);
+
+/**
+ * ucfg_ipa_fw_rejuvenate_send_msg() - Send msg to IPA driver in FW rejuvenate
+ * @pdev: pdev obj
+ *
+ * Return: None
+ */
+void ucfg_ipa_fw_rejuvenate_send_msg(struct wlan_objmgr_pdev *pdev);
+
 #else
 
 static inline bool ucfg_ipa_is_present(void)
@@ -503,5 +512,10 @@ static inline
 void ucfg_ipa_uc_ssr_cleanup(struct wlan_objmgr_pdev *pdev)
 {
 }
+
+static inline
+void ucfg_ipa_fw_rejuvenate_send_msg(struct wlan_objmgr_pdev *pdev)
+{
+}
 #endif /* IPA_OFFLOAD */
 #endif /* _WLAN_IPA_UCFG_API_H_ */

+ 5 - 0
components/ipa/dispatcher/src/wlan_ipa_ucfg_api.c

@@ -191,3 +191,8 @@ void ucfg_ipa_uc_ssr_cleanup(struct wlan_objmgr_pdev *pdev)
 {
 	return ipa_uc_ssr_cleanup(pdev);
 }
+
+void ucfg_ipa_fw_rejuvenate_send_msg(struct wlan_objmgr_pdev *pdev)
+{
+	return ipa_fw_rejuvenate_send_msg(pdev);
+}

+ 3 - 0
core/hdd/src/wlan_hdd_driver_ops.c

@@ -1552,6 +1552,9 @@ static void wlan_hdd_handle_the_pld_uevent(struct pld_uevent_data *uevent)
 		qdf_complete_wait_events();
 		cds_set_target_ready(false);
 		wlan_cfg80211_cleanup_scan_queue(hdd_ctx->pdev, NULL);
+		if (pld_is_fw_rejuvenate(hdd_ctx->parent_dev) &&
+		    ucfg_ipa_is_enabled())
+			ucfg_ipa_fw_rejuvenate_send_msg(hdd_ctx->pdev);
 		break;
 	default:
 		break;

+ 11 - 0
core/pld/inc/pld_common.h

@@ -546,6 +546,17 @@ int pld_is_fw_down(struct device *dev);
 int pld_force_assert_target(struct device *dev);
 bool pld_is_fw_dump_skipped(struct device *dev);
 
+/**
+ * pld_is_fw_rejuvenate() - Check WLAN fw is rejuvenating
+ *
+ * Help the driver decide whether FW down is due to
+ * SSR or FW rejuvenate.
+ *
+ * Return: 1 FW is rejuvenating
+ *         0 FW is not rejuvenating
+ */
+int pld_is_fw_rejuvenate(struct device *dev);
+
 #if defined(CONFIG_WCNSS_MEM_PRE_ALLOC) && defined(FEATURE_SKB_PRE_ALLOC)
 
 /**

+ 15 - 0
core/pld/src/pld_common.c

@@ -1555,3 +1555,18 @@ bool pld_is_fw_dump_skipped(struct device *dev)
 	}
 	return ret;
 }
+
+int pld_is_fw_rejuvenate(struct device *dev)
+{
+	int ret = 0;
+	enum pld_bus_type type = pld_get_bus_type(dev);
+
+	switch (type) {
+	case PLD_BUS_TYPE_SNOC:
+		ret = pld_snoc_is_fw_rejuvenate();
+		break;
+	default:
+		break;
+	}
+	return ret;
+}

+ 12 - 0
core/pld/src/pld_snoc.h

@@ -126,6 +126,12 @@ static inline int pld_snoc_force_assert_target(struct device *dev)
 {
 	return 0;
 }
+
+static inline int pld_snoc_is_fw_rejuvenate(void)
+{
+	return 0;
+}
+
 #else
 int pld_snoc_register_driver(void);
 void pld_snoc_unregister_driver(void);
@@ -293,5 +299,11 @@ static inline int pld_snoc_force_assert_target(struct device *dev)
 {
 	return icnss_trigger_recovery(dev);
 }
+
+static inline int pld_snoc_is_fw_rejuvenate(void)
+{
+	return icnss_is_rejuvenate();
+}
+
 #endif
 #endif