diff --git a/os_if/linux/nan/inc/os_if_nan.h b/os_if/linux/nan/inc/os_if_nan.h index 3843abacfa52..4e263d5ef6a4 100644 --- a/os_if/linux/nan/inc/os_if_nan.h +++ b/os_if/linux/nan/inc/os_if_nan.h @@ -23,6 +23,11 @@ #ifndef _OS_IF_NAN_H_ #define _OS_IF_NAN_H_ +#include "qdf_types.h" + +struct wlan_objmgr_psoc; +struct wlan_objmgr_vdev; + #ifdef WLAN_FEATURE_NAN_CONVERGENCE #define NDP_QOS_INFO_LEN 255 @@ -114,4 +119,28 @@ enum qca_wlan_vendor_attr_ndp_sub_cmd_value { #endif /* WLAN_FEATURE_NAN_CONVERGENCE */ +/** + * os_if_nan_process_ndp_cmd: os_if api to handle nan request message + * @psoc: pointer to psoc object + * @data: request data. contains vendor cmd tlvs + * @data_len: length of data + * + * Return: status of operation + */ +int os_if_nan_process_ndp_cmd(struct wlan_objmgr_psoc *psoc, + const void *data, int data_len); + +/** + * os_if_nan_event_handler: os_if handler api for nan response messages + * @psoc: pointer to psoc object + * @vdev: pointer to vdev object + * @type: message type + * @msg: msg buffer + * + * Return: None + */ +void os_if_nan_event_handler(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_vdev *vdev, + uint32_t type, void *msg); + #endif diff --git a/os_if/linux/nan/src/os_if_nan.c b/os_if/linux/nan/src/os_if_nan.c index 3ee4c4706966..5d260ecc32a9 100644 --- a/os_if/linux/nan/src/os_if_nan.c +++ b/os_if/linux/nan/src/os_if_nan.c @@ -20,3 +20,99 @@ * DOC: defines nan component os interface APIs */ +#include "qdf_types.h" +#include "qdf_trace.h" +#include "os_if_nan.h" +#include "wlan_nlink_srv.h" +#include "nan_public_structs.h" +#include "wlan_cfg80211.h" + +/* NLA policy */ +static const struct nla_policy +vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_NDP_PARAMS_MAX + 1] = { + [QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID] = { .type = NLA_U16 }, + [QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR] = { .type = NLA_STRING, + .len = IFNAMSIZ }, + [QCA_WLAN_VENDOR_ATTR_NDP_SERVICE_INSTANCE_ID] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_NDP_PEER_DISCOVERY_MAC_ADDR] = { + .type = NLA_BINARY, + .len = QDF_MAC_ADDR_SIZE }, + [QCA_WLAN_VENDOR_ATTR_NDP_CONFIG_SECURITY] = { .type = NLA_U16 }, + [QCA_WLAN_VENDOR_ATTR_NDP_CONFIG_QOS] = { .type = NLA_BINARY, + .len = NDP_QOS_INFO_LEN }, + [QCA_WLAN_VENDOR_ATTR_NDP_APP_INFO] = { .type = NLA_BINARY, + .len = NDP_APP_INFO_LEN }, + [QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_NDP_RESPONSE_CODE] = { .type = NLA_U16 }, + [QCA_WLAN_VENDOR_ATTR_NDP_NDI_MAC_ADDR] = { .type = NLA_BINARY, + .len = QDF_MAC_ADDR_SIZE }, + [QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID_ARRAY] = { .type = NLA_BINARY, + .len = NDP_NUM_INSTANCE_ID }, + [QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_CONFIG] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_NDP_NCS_SK_TYPE] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_NDP_PMK] = { .type = NLA_BINARY, + .len = NDP_PMK_LEN }, + [QCA_WLAN_VENDOR_ATTR_NDP_SCID] = { .type = NLA_BINARY, + .len = NDP_SCID_BUF_LEN }, + [QCA_WLAN_VENDOR_ATTR_NDP_DRV_RESPONSE_STATUS_TYPE] = { .type = + NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_VALUE] = { .type = NLA_U32 }, +}; + +int os_if_nan_process_ndp_cmd(void *ctx, struct wlan_objmgr_psoc *psoc, + const void *data, int data_len) +{ + uint32_t ndp_cmd_type; + uint16_t transaction_id; + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_NDP_PARAMS_MAX + 1]; + char *iface_name; + + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_NDP_PARAMS_MAX, + data, data_len, vendor_attr_policy)) { + cfg80211_err("Invalid NDP vendor command attributes"); + return -EINVAL; + } + + /* Parse and fetch NDP Command Type*/ + if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD]) { + cfg80211_err("NAN datapath cmd type failed"); + return -EINVAL; + } + ndp_cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD]); + + if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID]) { + cfg80211_err("attr transaction id failed"); + return -EINVAL; + } + transaction_id = nla_get_u16( + tb[QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID]); + + if (tb[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR]) { + iface_name = nla_data(tb[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR]); + cfg80211_err("Transaction Id: %d NDPCmd: %d iface_name: %s", + transaction_id, ndp_cmd_type, iface_name); + } else { + cfg80211_err("Transaction Id: %d NDPCmd: %d iface_name: unspecified", + transaction_id, ndp_cmd_type); + } + + switch (ndp_cmd_type) { + default: + cfg80211_err("Unrecognized NDP vendor cmd %d", ndp_cmd_type); + return -EINVAL; + } + + return -EINVAL; +} + +void os_if_nan_event_handler(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_vdev *vdev, + uint32_t type, void *msg) +{ + switch (type) { + default: + break; + } +} diff --git a/umac/nan/core/src/nan_main.c b/umac/nan/core/src/nan_main.c index 8506ce52ea9a..7c5e2d560573 100644 --- a/umac/nan/core/src/nan_main.c +++ b/umac/nan/core/src/nan_main.c @@ -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; -} \ No newline at end of file +} + +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; +} diff --git a/umac/nan/core/src/nan_main_i.h b/umac/nan/core/src/nan_main_i.h index cf2929252479..c66594ceac6e 100644 --- a/umac/nan/core/src/nan_main_i.h +++ b/umac/nan/core/src/nan_main_i.h @@ -104,4 +104,22 @@ struct nan_vdev_priv_obj *nan_get_vdev_priv_obj(struct wlan_objmgr_vdev *vdev); */ struct nan_psoc_priv_obj *nan_get_psoc_priv_obj(struct wlan_objmgr_psoc *psoc); +/** + * nan_release_cmd: frees resources for NAN command. + * @in_req: pointer to msg buffer to be freed + * @req_type: type of request + * + * Return: None + */ +void nan_release_cmd(void *in_req, uint32_t req_type); + +/** + * nan_scheduled_msg_handler: callback pointer to be called when scheduler + * starts executing enqueued NAN command. + * @msg: pointer to msg + * + * Return: status of operation + */ +QDF_STATUS nan_scheduled_msg_handler(struct scheduler_msg *msg); + #endif diff --git a/umac/nan/dispatcher/inc/nan_ucfg_api.h b/umac/nan/dispatcher/inc/nan_ucfg_api.h index 35bc40ffa647..d099b9ea6d59 100644 --- a/umac/nan/dispatcher/inc/nan_ucfg_api.h +++ b/umac/nan/dispatcher/inc/nan_ucfg_api.h @@ -170,4 +170,15 @@ uint32_t ucfg_nan_get_ndi_delete_rsp_status(struct wlan_objmgr_vdev *vdev); QDF_STATUS ucfg_nan_get_callbacks(struct wlan_objmgr_psoc *psoc, struct nan_callbacks *cb_obj); +/** + * ucfg_nan_req_processor: ucfg API to be called from HDD/OS_IF to + * process nan datapath initiator request from userspace + * @in_req: NDP request + * @psoc: pointer to psoc object + * @req_type: type of request + * + * Return: status of operation + */ +QDF_STATUS ucfg_nan_req_processor(void *in_req, uint32_t req_type); + #endif /* _NAN_UCFG_API_H_ */ diff --git a/umac/nan/dispatcher/src/nan_ucfg_api.c b/umac/nan/dispatcher/src/nan_ucfg_api.c index 3ae24b858f2a..b432346ab72a 100644 --- a/umac/nan/dispatcher/src/nan_ucfg_api.c +++ b/umac/nan/dispatcher/src/nan_ucfg_api.c @@ -23,6 +23,7 @@ #include "nan_ucfg_api.h" #include "nan_public_structs.h" #include "../../core/src/nan_main_i.h" +#include "scheduler_api.h" inline QDF_STATUS ucfg_nan_set_ndi_state(struct wlan_objmgr_vdev *vdev, uint32_t state) @@ -294,3 +295,25 @@ inline QDF_STATUS ucfg_nan_get_callbacks(struct wlan_objmgr_psoc *psoc, return QDF_STATUS_SUCCESS; } + +QDF_STATUS ucfg_nan_req_processor(void *in_req, uint32_t req_type) +{ + QDF_STATUS status; + struct scheduler_msg msg = {0}; + + if (!in_req) { + nan_alert("req is null"); + return QDF_STATUS_E_NULL_VALUE; + } + + msg.type = req_type; + msg.bodyptr = in_req; + msg.callback = nan_scheduled_msg_handler; + status = scheduler_post_msg(QDF_MODULE_ID_OS_IF, &msg); + if (QDF_IS_STATUS_ERROR(status)) { + nan_err("faild to post msg to NAN component, status: %d", + status); + } + + return status; +}