|
@@ -21,6 +21,13 @@
|
|
|
*/
|
|
|
|
|
|
#include "nan_main_i.h"
|
|
|
+#include "nan_ucfg_api.h"
|
|
|
+#include "wlan_nan_api.h"
|
|
|
+#include "target_if_nan.h"
|
|
|
+#include "scheduler_api.h"
|
|
|
+#include "wlan_serialization_api.h"
|
|
|
+#include "wlan_objmgr_cmn.h"
|
|
|
+#include "wlan_objmgr_global_obj.h"
|
|
|
#include "wlan_objmgr_psoc_obj.h"
|
|
|
#include "wlan_objmgr_pdev_obj.h"
|
|
|
#include "wlan_objmgr_vdev_obj.h"
|
|
@@ -55,4 +62,197 @@ struct nan_psoc_priv_obj *nan_get_psoc_priv_obj(
|
|
|
wlan_psoc_obj_unlock(psoc);
|
|
|
|
|
|
return obj;
|
|
|
-}
|
|
|
+}
|
|
|
+
|
|
|
+void nan_release_cmd(void *in_req, uint32_t req_type)
|
|
|
+{
|
|
|
+ struct wlan_objmgr_vdev *vdev = NULL;
|
|
|
+
|
|
|
+ if (!in_req)
|
|
|
+ return;
|
|
|
+
|
|
|
+ switch (req_type) {
|
|
|
+ case NDP_INITIATOR_REQ: {
|
|
|
+ struct nan_datapath_initiator_req *req = in_req;
|
|
|
+ vdev = req->vdev;
|
|
|
+ qdf_mem_free(req->pmk.pmk);
|
|
|
+ qdf_mem_free(req->ndp_info.ndp_app_info);
|
|
|
+ qdf_mem_free(req->ndp_config.ndp_cfg);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case NDP_RESPONDER_REQ: {
|
|
|
+ struct nan_datapath_responder_req *req = in_req;
|
|
|
+ vdev = req->vdev;
|
|
|
+ qdf_mem_free(req->pmk.pmk);
|
|
|
+ qdf_mem_free(req->ndp_info.ndp_app_info);
|
|
|
+ qdf_mem_free(req->ndp_config.ndp_cfg);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case NDP_END_REQ: {
|
|
|
+ struct nan_datapath_end_req *req = in_req;
|
|
|
+ vdev = req->vdev;
|
|
|
+ qdf_mem_free(req->ndp_ids);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ default:
|
|
|
+ nan_err("invalid req type: %d", req_type);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (vdev)
|
|
|
+ wlan_objmgr_vdev_release_ref(vdev, WLAN_NAN_ID);
|
|
|
+ else
|
|
|
+ nan_err("vdev is null");
|
|
|
+
|
|
|
+ qdf_mem_free(in_req);
|
|
|
+}
|
|
|
+
|
|
|
+static void nan_req_incomplete(void *req, uint32_t cmdtype)
|
|
|
+{
|
|
|
+ /* send msg to userspace if needed that cmd got incomplete */
|
|
|
+}
|
|
|
+
|
|
|
+static void nan_req_activated(void *in_req, uint32_t cmdtype)
|
|
|
+{
|
|
|
+ uint32_t req_type;
|
|
|
+ QDF_STATUS status;
|
|
|
+ struct wlan_objmgr_psoc *psoc;
|
|
|
+ struct wlan_objmgr_vdev *vdev;
|
|
|
+ struct wlan_lmac_if_nan_tx_ops *tx_ops;
|
|
|
+
|
|
|
+ switch (cmdtype) {
|
|
|
+ case WLAN_SER_CMD_NDP_INIT_REQ: {
|
|
|
+ struct nan_datapath_initiator_req *req = in_req;
|
|
|
+ vdev = req->vdev;
|
|
|
+ req_type = NDP_INITIATOR_REQ;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case WLAN_SER_CMD_NDP_RESP_REQ: {
|
|
|
+ struct nan_datapath_responder_req *req = in_req;
|
|
|
+ vdev = req->vdev;
|
|
|
+ req_type = NDP_RESPONDER_REQ;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case WLAN_SER_CMD_NDP_DATA_END_INIT_REQ: {
|
|
|
+ struct nan_datapath_end_req *req = in_req;
|
|
|
+ vdev = req->vdev;
|
|
|
+ req_type = NDP_END_REQ;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ default:
|
|
|
+ nan_alert("in correct cmdtype: %d", cmdtype);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!vdev) {
|
|
|
+ nan_alert("vdev is null");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ psoc = wlan_vdev_get_psoc(vdev);
|
|
|
+ if (!psoc) {
|
|
|
+ nan_alert("psoc is null");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ tx_ops = target_if_nan_get_tx_ops(psoc);
|
|
|
+ if (!tx_ops) {
|
|
|
+ nan_alert("tx_ops is null");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* send ndp_intiator_req/responder_req/end_req to FW */
|
|
|
+ tx_ops->nan_req_tx(in_req, req_type);
|
|
|
+}
|
|
|
+
|
|
|
+static QDF_STATUS nan_serialized_cb(void *cmd,
|
|
|
+ enum wlan_serialization_cb_reason reason)
|
|
|
+{
|
|
|
+ void *req;
|
|
|
+ struct wlan_serialization_command *ser_cmd = cmd;
|
|
|
+
|
|
|
+ if (!ser_cmd || !ser_cmd->umac_cmd) {
|
|
|
+ nan_alert("cmd or umac_cmd is null");
|
|
|
+ return QDF_STATUS_E_NULL_VALUE;
|
|
|
+ }
|
|
|
+ req = ser_cmd->umac_cmd;
|
|
|
+
|
|
|
+ switch (reason) {
|
|
|
+ case WLAN_SER_CB_ACTIVATE_CMD:
|
|
|
+ nan_req_activated(req, ser_cmd->cmd_type);
|
|
|
+ break;
|
|
|
+ case WLAN_SER_CB_CANCEL_CMD:
|
|
|
+ case WLAN_SER_CB_ACTIVE_CMD_TIMEOUT:
|
|
|
+ nan_req_incomplete(req, ser_cmd->cmd_type);
|
|
|
+ break;
|
|
|
+ case WLAN_SER_CB_RELEASE_MEM_CMD:
|
|
|
+ nan_release_cmd(req, ser_cmd->cmd_type);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ /* Do nothing but logging */
|
|
|
+ nan_alert("invalid serialized cb reason: %d", reason);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return QDF_STATUS_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+QDF_STATUS nan_scheduled_msg_handler(struct scheduler_msg *msg)
|
|
|
+{
|
|
|
+ QDF_STATUS ref_status;
|
|
|
+ enum wlan_serialization_status status = 0;
|
|
|
+ struct wlan_serialization_command cmd = {0};
|
|
|
+
|
|
|
+ if (!msg || !msg->bodyptr) {
|
|
|
+ nan_alert("msg or bodyptr is null");
|
|
|
+ return QDF_STATUS_E_NULL_VALUE;
|
|
|
+ }
|
|
|
+ switch (msg->type) {
|
|
|
+ case NDP_INITIATOR_REQ: {
|
|
|
+ struct nan_datapath_initiator_req *req = msg->bodyptr;
|
|
|
+ cmd.cmd_type = WLAN_SER_CMD_NDP_INIT_REQ;
|
|
|
+ cmd.vdev = req->vdev;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case NDP_RESPONDER_REQ: {
|
|
|
+ struct nan_datapath_responder_req *req = msg->bodyptr;
|
|
|
+ cmd.cmd_type = WLAN_SER_CMD_NDP_RESP_REQ;
|
|
|
+ cmd.vdev = req->vdev;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case NDP_END_REQ: {
|
|
|
+ struct nan_datapath_end_req *req = msg->bodyptr;
|
|
|
+ cmd.cmd_type = WLAN_SER_CMD_NDP_DATA_END_INIT_REQ;
|
|
|
+ cmd.vdev = req->vdev;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ default:
|
|
|
+ nan_err("wrong request type: %d", msg->type);
|
|
|
+ return QDF_STATUS_E_INVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* try get ref now, if failure, then vdev may have been deleted */
|
|
|
+ ref_status = wlan_objmgr_vdev_try_get_ref(cmd.vdev, WLAN_NAN_ID);
|
|
|
+ if (QDF_IS_STATUS_ERROR(ref_status)) {
|
|
|
+ nan_alert("couldn't get ref. vdev maybe deleted");
|
|
|
+ return QDF_STATUS_E_INVAL;
|
|
|
+ }
|
|
|
+ /* reference will be released when ser command finishes */
|
|
|
+
|
|
|
+ /* TBD - support more than one req of same type or avoid */
|
|
|
+ cmd.cmd_id = 0;
|
|
|
+ cmd.cmd_cb = nan_serialized_cb;
|
|
|
+ cmd.umac_cmd = msg->bodyptr;
|
|
|
+ cmd.source = WLAN_UMAC_COMP_NAN;
|
|
|
+ cmd.is_high_priority = false;
|
|
|
+ cmd.cmd_timeout_duration = 30000 /* 30 sec for now. TBD */;
|
|
|
+
|
|
|
+ status = wlan_serialization_request(&cmd);
|
|
|
+ /* following is TBD */
|
|
|
+ if (status != WLAN_SER_CMD_ACTIVE && status != WLAN_SER_CMD_PENDING) {
|
|
|
+ nan_err("unable to serialize command");
|
|
|
+ wlan_objmgr_vdev_release_ref(cmd.vdev, WLAN_NAN_ID);
|
|
|
+ return QDF_STATUS_E_INVAL;
|
|
|
+ }
|
|
|
+ return QDF_STATUS_SUCCESS;
|
|
|
+}
|