From e830e98bcf702ac8cf05123082dd6f1ec1a222a2 Mon Sep 17 00:00:00 2001 From: Naveen Rawat Date: Sun, 2 Apr 2017 19:39:25 -0700 Subject: [PATCH] qcacmn: Add implementation for NDI Create/Delete Implement NDI create and NDI delete commands. Change-Id: Icd4c745f4d25c0f10f12271fd4fcd7720ad85860 CRs-Fixed: 2014795 --- os_if/linux/nan/inc/os_if_nan.h | 102 +++++- os_if/linux/nan/src/os_if_nan.c | 413 ++++++++++++++++++++++++- umac/nan/core/inc/nan_public_structs.h | 8 + umac/nan/core/src/nan_api.c | 45 ++- umac/nan/core/src/nan_main_i.h | 2 + umac/nan/dispatcher/inc/nan_ucfg_api.h | 43 ++- umac/nan/dispatcher/src/nan_ucfg_api.c | 57 +++- 7 files changed, 655 insertions(+), 15 deletions(-) diff --git a/os_if/linux/nan/inc/os_if_nan.h b/os_if/linux/nan/inc/os_if_nan.h index 4e263d5ef6a4..9b8fc9f3db37 100644 --- a/os_if/linux/nan/inc/os_if_nan.h +++ b/os_if/linux/nan/inc/os_if_nan.h @@ -24,6 +24,8 @@ #define _OS_IF_NAN_H_ #include "qdf_types.h" +#include "nan_public_structs.h" +#include "nan_ucfg_api.h" struct wlan_objmgr_psoc; struct wlan_objmgr_vdev; @@ -117,8 +119,6 @@ enum qca_wlan_vendor_attr_ndp_sub_cmd_value { QCA_WLAN_VENDOR_ATTR_NDP_END_IND = 11 }; -#endif /* WLAN_FEATURE_NAN_CONVERGENCE */ - /** * os_if_nan_process_ndp_cmd: os_if api to handle nan request message * @psoc: pointer to psoc object @@ -143,4 +143,102 @@ void os_if_nan_event_handler(struct wlan_objmgr_psoc *psoc, struct wlan_objmgr_vdev *vdev, uint32_t type, void *msg); +/** + * os_if_nan_register_hdd_callbacks: os_if api to register hdd callbacks + * @psoc: pointer to psoc object + * @cb_obj: struct pointer containing callbacks + * + * Return: status of operation + */ +int os_if_nan_register_hdd_callbacks(struct wlan_objmgr_psoc *psoc, + struct nan_callbacks *cb_obj); + +/** + * os_if_nan_post_ndi_create_rsp: os_if api to pos ndi create rsp to umac nan + * component + * @psoc: pointer to psoc object + * @vdev_id: vdev id of ndi + * @success: if create was success or failure + * + * Return: None + */ +void os_if_nan_post_ndi_create_rsp(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, bool success); + +/** + * os_if_nan_post_ndi_delete_rsp: os_if api to pos ndi delete rsp to umac nan + * component + * @psoc: pointer to psoc object + * @vdev_id: vdev id of ndi + * @success: if delete was success or failure + * + * Return: None + */ +void os_if_nan_post_ndi_delete_rsp(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, bool success); + +/** + * os_if_nan_ndi_session_end: os_if api to process ndi session end + * component + * @vdev: pointer to vdev deleted + * + * Return: None + */ +void os_if_nan_ndi_session_end(struct wlan_objmgr_vdev *vdev); + +/** + * os_if_nan_set_ndi_state: os_if api set NDI state + * @vdev: pointer to vdev deleted + * @state: value to set + * + * Return: status of operation + */ +static inline QDF_STATUS os_if_nan_set_ndi_state(struct wlan_objmgr_vdev *vdev, + uint32_t state) +{ + return ucfg_nan_set_ndi_state(vdev, state); +} + +/** + * os_if_nan_set_ndp_create_transaction_id: set ndp create transaction id + * @vdev: pointer to vdev object + * @val: value to set + * + * Return: status of operation + */ +static inline QDF_STATUS os_if_nan_set_ndp_create_transaction_id( + struct wlan_objmgr_vdev *vdev, + uint16_t val) +{ + return ucfg_nan_set_ndp_create_transaction_id(vdev, val); +} + +/** + * os_if_nan_set_ndp_delete_transaction_id: set ndp delete transaction id + * @vdev: pointer to vdev object + * @val: value to set + * + * Return: status of operation + */ +static inline QDF_STATUS os_if_nan_set_ndp_delete_transaction_id( + struct wlan_objmgr_vdev *vdev, + uint16_t val) +{ + return ucfg_nan_set_ndp_delete_transaction_id(vdev, val); +} + +#else + +static inline void os_if_nan_post_ndi_create_rsp(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, bool success) +{ +} + +static inline void os_if_nan_post_ndi_delete_rsp(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, bool success) +{ +} + +#endif /* WLAN_FEATURE_NAN_CONVERGENCE */ + #endif diff --git a/os_if/linux/nan/src/os_if_nan.c b/os_if/linux/nan/src/os_if_nan.c index 5d260ecc32a9..311a26085d73 100644 --- a/os_if/linux/nan/src/os_if_nan.c +++ b/os_if/linux/nan/src/os_if_nan.c @@ -23,9 +23,14 @@ #include "qdf_types.h" #include "qdf_trace.h" #include "os_if_nan.h" -#include "wlan_nlink_srv.h" +#include "wlan_nan_api.h" #include "nan_public_structs.h" +#include "wlan_osif_priv.h" +#include #include "wlan_cfg80211.h" +#include "wlan_objmgr_psoc_obj.h" +#include "wlan_objmgr_pdev_obj.h" +#include "wlan_objmgr_vdev_obj.h" /* NLA policy */ static const struct nla_policy @@ -61,7 +66,109 @@ vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_NDP_PARAMS_MAX + 1] = { [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, +static int os_if_nan_process_ndi_create(struct wlan_objmgr_psoc *psoc, + struct nlattr **tb) +{ + char *iface_name; + QDF_STATUS status; + uint16_t transaction_id; + struct wlan_objmgr_vdev *nan_vdev; + struct nan_callbacks cb_obj; + + cfg80211_debug("enter"); + if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR]) { + cfg80211_err("Interface name string is unavailable"); + return -EINVAL; + } + iface_name = nla_data(tb[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR]); + + if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID]) { + cfg80211_err("transaction id is unavailable"); + return -EINVAL; + } + transaction_id = + nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID]); + + status = ucfg_nan_get_callbacks(psoc, &cb_obj); + if (QDF_IS_STATUS_ERROR(status)) { + cfg80211_err("Couldn't get ballback object"); + return -EINVAL; + } + + nan_vdev = cb_obj.ndi_open(iface_name); + + if (!nan_vdev) { + cfg80211_err("ndi_open failed"); + return -EINVAL; + } + + /* + * Create transaction id is required to be saved since the firmware + * does not honor the transaction id for create request + */ + ucfg_nan_set_ndp_create_transaction_id(nan_vdev, transaction_id); + ucfg_nan_set_ndi_state(nan_vdev, NAN_DATA_NDI_CREATING_STATE); + + return cb_obj.ndi_start(wlan_vdev_get_id(nan_vdev)); +} + +static int os_if_nan_process_ndi_delete(struct wlan_objmgr_psoc *psoc, + struct nlattr **tb) +{ + uint8_t vdev_id; + char *iface_name; + QDF_STATUS status; + uint32_t num_peers; + uint16_t transaction_id; + struct nan_callbacks cb_obj; + struct wlan_objmgr_vdev *nan_vdev = NULL; + + if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR]) { + cfg80211_err("Interface name string is unavailable"); + return -EINVAL; + } + + iface_name = nla_data(tb[QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR]); + + if (!tb[QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID]) { + cfg80211_err("Transaction id is unavailable"); + return -EINVAL; + } + + nan_vdev = ucfg_nan_get_ndi_vdev(psoc, WLAN_NAN_ID); + if (!nan_vdev) { + cfg80211_err("Nan datapath interface is not present"); + return -EINVAL; + } + + transaction_id = + nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID]); + vdev_id = wlan_vdev_get_id(nan_vdev); + num_peers = ucfg_nan_get_active_peers(nan_vdev); + /* + * wlan_objmgr_get_vdev_by_opmode_from_psoc API will have incremented + * ref count - decrement here since vdev returned by that api is not + * used any more + */ + wlan_objmgr_vdev_release_ref(nan_vdev, WLAN_NAN_ID); + + /* check if there are active peers on the adapter */ + if (num_peers) { + cfg80211_err("NDP peers active: %d, cannot delete NDI", + num_peers); + return -EINVAL; + } + + status = ucfg_nan_get_callbacks(psoc, &cb_obj); + if (QDF_IS_STATUS_ERROR(status)) { + cfg80211_err("Couldn't get ballback object"); + return -EINVAL; + } + + return cb_obj.ndi_delete(vdev_id, iface_name, transaction_id); +} + +int os_if_nan_process_ndp_cmd(struct wlan_objmgr_psoc *psoc, const void *data, int data_len) { uint32_t ndp_cmd_type; @@ -98,7 +205,12 @@ int os_if_nan_process_ndp_cmd(void *ctx, struct wlan_objmgr_psoc *psoc, transaction_id, ndp_cmd_type); } + cfg80211_debug("Received NDP cmd: %d", ndp_cmd_type); switch (ndp_cmd_type) { + case QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_CREATE: + return os_if_nan_process_ndi_create(psoc, tb); + case QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_DELETE: + return os_if_nan_process_ndi_delete(psoc, tb); default: cfg80211_err("Unrecognized NDP vendor cmd %d", ndp_cmd_type); return -EINVAL; @@ -107,12 +219,309 @@ int os_if_nan_process_ndp_cmd(void *ctx, struct wlan_objmgr_psoc *psoc, return -EINVAL; } +/** + * os_if_ndp_iface_create_rsp_handler() - NDP iface create response handler + * @adapter: pointer to adapter context + * @rsp_params: response parameters + * + * The function is expected to send a response back to the user space + * even if the creation of BSS has failed + * + * Following vendor event is sent to cfg80211: + * QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD = + * QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_CREATE (4 bytes) + * QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID (2 bytes) + * QCA_WLAN_VENDOR_ATTR_NDP_DRV_RESPONSE_STATUS_TYPE (4 bytes) + * QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_VALUE + * + * Return: none + */ +static void os_if_ndp_iface_create_rsp_handler(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_vdev *vdev, + void *rsp_params) +{ + QDF_STATUS status; + bool create_fail = false; + struct nan_callbacks cb_obj; + struct sk_buff *vendor_event; + uint8_t create_transaction_id; + struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev); + struct pdev_osif_priv *os_priv = wlan_pdev_get_ospriv(pdev); + uint32_t create_status = NAN_DATAPATH_RSP_STATUS_ERROR; + uint32_t create_reason = NAN_DATAPATH_NAN_DATA_IFACE_CREATE_FAILED; + struct nan_datapath_inf_create_rsp *ndi_rsp = + (struct nan_datapath_inf_create_rsp *)rsp_params; + uint32_t data_len = (3 * sizeof(uint32_t)) + sizeof(uint16_t) + + NLMSG_HDRLEN + (4 * NLA_HDRLEN); + + status = ucfg_nan_get_callbacks(psoc, &cb_obj); + if (QDF_IS_STATUS_ERROR(status)) { + cfg80211_err("Couldn't get ballback object"); + return; + } + + if (ndi_rsp) { + create_status = ndi_rsp->status; + create_reason = ndi_rsp->reason; + } else { + cfg80211_err("Invalid ndi create response"); + create_fail = true; + } + + create_transaction_id = ucfg_nan_get_ndp_create_transaction_id(vdev); + + /* notify response to the upper layer */ + vendor_event = cfg80211_vendor_event_alloc(os_priv->wiphy, + NULL, + data_len, + QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX, + GFP_KERNEL); + if (!vendor_event) { + cfg80211_err("cfg80211_vendor_event_alloc failed"); + create_fail = true; + goto close_ndi; + } + + /* Sub vendor command */ + if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD, + QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_CREATE)) { + cfg80211_err("QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD put fail"); + goto nla_put_failure; + } + + /* Transaction id */ + if (nla_put_u16(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID, + create_transaction_id)) { + cfg80211_err("VENDOR_ATTR_NDP_TRANSACTION_ID put fail"); + goto nla_put_failure; + } + + /* Status code */ + if (nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_NDP_DRV_RESPONSE_STATUS_TYPE, + create_status)) { + cfg80211_err("VENDOR_ATTR_NDP_DRV_RETURN_TYPE put fail"); + goto nla_put_failure; + } + + /* Status return value */ + if (nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_VALUE, + create_reason)) { + cfg80211_err("VENDOR_ATTR_NDP_DRV_RETURN_VALUE put fail"); + goto nla_put_failure; + } + + cfg80211_debug("sub command: %d, value: %d", + QCA_NL80211_VENDOR_SUBCMD_NDP, + QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_CREATE); + cfg80211_debug("create transaction id: %d, value: %d", + QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID, create_transaction_id); + cfg80211_debug("status code: %d, value: %d", + QCA_WLAN_VENDOR_ATTR_NDP_DRV_RESPONSE_STATUS_TYPE, + create_status); + cfg80211_debug("Return value: %d, value: %d", + QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_VALUE, create_reason); + + cfg80211_vendor_event(vendor_event, GFP_KERNEL); + + if (!create_fail) { + /* update txrx queues and register self sta */ + cb_obj.drv_ndi_create_rsp_handler(wlan_vdev_get_id(vdev), + ndi_rsp); + } else { + cfg80211_err("NDI interface creation failed with reason %d", + ndi_rsp->reason); + goto close_ndi; + } + + return; + +nla_put_failure: + kfree_skb(vendor_event); +close_ndi: + cb_obj.ndi_close(wlan_vdev_get_id(vdev)); + return; +} + +/** + * os_if_ndp_iface_delete_rsp_handler() - NDP iface delete response handler + * @adapter: pointer to adapter context + * @rsp_params: response parameters + * + * Return: none + */ +static void os_if_ndp_iface_delete_rsp_handler(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_vdev *vdev, + void *rsp_params) +{ + QDF_STATUS status; + uint8_t vdev_id = wlan_vdev_get_id(vdev); + struct nan_datapath_inf_delete_rsp *ndi_rsp = rsp_params; + struct nan_callbacks cb_obj; + + if (!ndi_rsp) { + cfg80211_err("Invalid ndi delete response"); + return; + } + + status = ucfg_nan_get_callbacks(psoc, &cb_obj); + if (QDF_IS_STATUS_ERROR(status)) { + cfg80211_err("Couldn't get ballback object"); + return; + } + + if (ndi_rsp->status == NAN_DATAPATH_RSP_STATUS_SUCCESS) + cfg80211_debug("NDI BSS successfully stopped"); + else + cfg80211_debug("NDI BSS stop failed with reason %d", + ndi_rsp->reason); + + ucfg_nan_set_ndi_delete_rsp_reason(vdev, ndi_rsp->reason); + ucfg_nan_set_ndi_delete_rsp_status(vdev, ndi_rsp->status); + cb_obj.drv_ndi_delete_rsp_handler(vdev_id); +} + void os_if_nan_event_handler(struct wlan_objmgr_psoc *psoc, struct wlan_objmgr_vdev *vdev, uint32_t type, void *msg) { switch (type) { + case NAN_DATAPATH_INF_CREATE_RSP: + os_if_ndp_iface_create_rsp_handler(psoc, vdev, msg); + break; + case NAN_DATAPATH_INF_DELETE_RSP: + os_if_ndp_iface_delete_rsp_handler(psoc, vdev, msg); + break; default: break; } } + +int os_if_nan_register_hdd_callbacks(struct wlan_objmgr_psoc *psoc, + struct nan_callbacks *cb_obj) +{ + return ucfg_nan_register_hdd_callbacks(psoc, cb_obj, + os_if_nan_event_handler); +} + +void os_if_nan_post_ndi_create_rsp(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, bool success) +{ + struct nan_datapath_inf_create_rsp rsp = {0}; + struct wlan_objmgr_vdev *vdev = wlan_objmgr_get_vdev_by_id_from_psoc( + psoc, vdev_id, WLAN_NAN_ID); + + if (success) { + rsp.status = NAN_DATAPATH_RSP_STATUS_SUCCESS; + rsp.reason = 0; + os_if_nan_event_handler(psoc, vdev, + NAN_DATAPATH_INF_CREATE_RSP, &rsp); + } else { + rsp.status = NAN_DATAPATH_RSP_STATUS_ERROR; + rsp.reason = NAN_DATAPATH_NAN_DATA_IFACE_CREATE_FAILED; + os_if_nan_event_handler(psoc, vdev, + NAN_DATAPATH_INF_CREATE_RSP, &rsp); + } + wlan_objmgr_vdev_release_ref(vdev, WLAN_NAN_ID); +} + +void os_if_nan_post_ndi_delete_rsp(struct wlan_objmgr_psoc *psoc, + uint8_t vdev_id, bool success) +{ + struct nan_datapath_inf_delete_rsp rsp = {0}; + struct wlan_objmgr_vdev *vdev = wlan_objmgr_get_vdev_by_id_from_psoc( + psoc, vdev_id, WLAN_NAN_ID); + if (success) { + rsp.status = NAN_DATAPATH_RSP_STATUS_SUCCESS; + rsp.reason = 0; + os_if_nan_event_handler(psoc, vdev, + NAN_DATAPATH_INF_DELETE_RSP, &rsp); + } else { + rsp.status = NAN_DATAPATH_RSP_STATUS_ERROR; + rsp.reason = NAN_DATAPATH_NAN_DATA_IFACE_DELETE_FAILED; + os_if_nan_event_handler(psoc, vdev, + NAN_DATAPATH_INF_DELETE_RSP, &rsp); + } + wlan_objmgr_vdev_release_ref(vdev, WLAN_NAN_ID); +} + +void os_if_nan_ndi_session_end(struct wlan_objmgr_vdev *vdev) +{ + struct sk_buff *vendor_event; + struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev); + struct pdev_osif_priv *os_priv = wlan_pdev_get_ospriv(pdev); + uint32_t data_len = sizeof(uint32_t) * (3 + sizeof(uint16_t)) + + (NLA_HDRLEN * 4) + NLMSG_HDRLEN; + + /* + * The virtual adapters are stopped and closed even during + * driver unload or stop, the service layer is not required + * to be informed in that case (response is not expected) + */ + if (NAN_DATA_NDI_DELETING_STATE != ucfg_nan_get_ndi_state(vdev)) { + cfg80211_err("NDI interface deleted"); + return; + } + + /* notify response to the upper layer */ + vendor_event = cfg80211_vendor_event_alloc(os_priv->wiphy, NULL, + data_len, QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX, + GFP_KERNEL); + + if (!vendor_event) { + cfg80211_err("cfg80211_vendor_event_alloc failed"); + return; + } + + /* Sub vendor command goes first */ + if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD, + QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_DELETE)) { + cfg80211_err("VENDOR_ATTR_NDP_SUBCMD put fail"); + goto failure; + } + + /* Transaction id */ + if (nla_put_u16(vendor_event, QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID, + ucfg_nan_get_ndp_delete_transaction_id(vdev))) { + cfg80211_err("VENDOR_ATTR_NDP_TRANSACTION_ID put fail"); + goto failure; + } + + /* Status code */ + if (nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_NDP_DRV_RESPONSE_STATUS_TYPE, + ucfg_nan_get_ndi_delete_rsp_status(vdev))) { + cfg80211_err("VENDOR_ATTR_NDP_DRV_RETURN_TYPE put fail"); + goto failure; + } + + /* Status return value */ + if (nla_put_u32(vendor_event, + QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_VALUE, + ucfg_nan_get_ndi_delete_rsp_reason(vdev))) { + cfg80211_err("VENDOR_ATTR_NDP_DRV_RETURN_VALUE put fail"); + goto failure; + } + + cfg80211_debug("sub command: %d, value: %d", + QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD, + QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_DELETE); + cfg80211_debug("delete transaction id: %d, value: %d", + QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID, + ucfg_nan_get_ndp_delete_transaction_id(vdev)); + cfg80211_debug("status code: %d, value: %d", + QCA_WLAN_VENDOR_ATTR_NDP_DRV_RESPONSE_STATUS_TYPE, + ucfg_nan_get_ndi_delete_rsp_status(vdev)); + cfg80211_debug("Return value: %d, value: %d", + QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_VALUE, + ucfg_nan_get_ndi_delete_rsp_reason(vdev)); + + ucfg_nan_set_ndp_delete_transaction_id(vdev, 0); + ucfg_nan_set_ndi_state(vdev, NAN_DATA_NDI_DELETED_STATE); + cfg80211_vendor_event(vendor_event, GFP_KERNEL); + + return; +failure: + kfree_skb(vendor_event); +} diff --git a/umac/nan/core/inc/nan_public_structs.h b/umac/nan/core/inc/nan_public_structs.h index 188dc82c724b..54f1ca6e36dc 100644 --- a/umac/nan/core/inc/nan_public_structs.h +++ b/umac/nan/core/inc/nan_public_structs.h @@ -484,6 +484,14 @@ struct nan_callbacks { void (*os_if_event_handler)(struct wlan_objmgr_psoc *psoc, struct wlan_objmgr_vdev *vdev, uint32_t type, void *msg); + + struct wlan_objmgr_vdev* (*ndi_open)(char *iface_name); + int (*ndi_start)(uint8_t); + void (*ndi_close)(uint8_t); + int (*ndi_delete)(uint8_t, char *iface_name, uint16_t transaction_id); + void (*drv_ndi_create_rsp_handler)(uint8_t, + struct nan_datapath_inf_create_rsp *); + void (*drv_ndi_delete_rsp_handler)(uint8_t); }; #endif diff --git a/umac/nan/core/src/nan_api.c b/umac/nan/core/src/nan_api.c index 8cca4e9445a7..23b0bae32189 100644 --- a/umac/nan/core/src/nan_api.c +++ b/umac/nan/core/src/nan_api.c @@ -40,8 +40,7 @@ static QDF_STATUS nan_psoc_obj_created_notification( nan_obj = qdf_mem_malloc(sizeof(*nan_obj)); if (!nan_obj) { nan_alert("malloc failed for nan prv obj"); - status = QDF_STATUS_E_NOMEM; - goto nan_psoc_notif_failed; + return QDF_STATUS_E_NOMEM; } qdf_spinlock_create(&nan_obj->lock); @@ -89,8 +88,10 @@ static QDF_STATUS nan_psoc_obj_destroyed_notification( static QDF_STATUS nan_vdev_obj_created_notification( struct wlan_objmgr_vdev *vdev, void *arg_list) { - QDF_STATUS status = QDF_STATUS_SUCCESS; + struct wlan_objmgr_psoc *psoc; struct nan_vdev_priv_obj *nan_obj; + struct nan_psoc_priv_obj *nan_psoc_obj; + QDF_STATUS status = QDF_STATUS_SUCCESS; if (wlan_vdev_mlme_get_opmode(vdev) != QDF_NDI_MODE) { nan_debug("not a ndi vdev. do nothing"); @@ -98,13 +99,26 @@ static QDF_STATUS nan_vdev_obj_created_notification( } nan_debug("nan_vdev_create_notif called"); - nan_obj = qdf_mem_malloc(sizeof(*nan_obj)); - if (!nan_obj) { - nan_alert("malloc failed for nan prv obj"); - status = QDF_STATUS_E_NOMEM; - goto nan_vdev_notif_failed; + + psoc = wlan_vdev_get_psoc(vdev); + if (!psoc) { + nan_err("psoc is null"); + return QDF_STATUS_E_NULL_VALUE; } + nan_psoc_obj = nan_get_psoc_priv_obj(psoc); + if (!nan_psoc_obj) { + nan_err("nan_psoc_obj is null"); + return QDF_STATUS_E_NULL_VALUE; + } + + nan_obj = qdf_mem_malloc(sizeof(*nan_obj)); + if (!nan_obj) { + nan_err("malloc failed for nan prv obj"); + return QDF_STATUS_E_NOMEM; + } + + nan_psoc_obj->vdev = vdev; qdf_spinlock_create(&nan_obj->lock); status = wlan_objmgr_vdev_component_obj_attach(vdev, WLAN_UMAC_COMP_NAN, (void *)nan_obj, @@ -126,8 +140,10 @@ nan_vdev_notif_failed: static QDF_STATUS nan_vdev_obj_destroyed_notification( struct wlan_objmgr_vdev *vdev, void *arg_list) { - QDF_STATUS status = QDF_STATUS_SUCCESS; + struct wlan_objmgr_psoc *psoc; struct nan_vdev_priv_obj *nan_obj; + struct nan_psoc_priv_obj *nan_psoc_obj; + QDF_STATUS status = QDF_STATUS_SUCCESS; if (wlan_vdev_mlme_get_opmode(vdev) != QDF_NDI_MODE) { nan_debug("not a ndi vdev. do nothing"); @@ -135,6 +151,17 @@ static QDF_STATUS nan_vdev_obj_destroyed_notification( } nan_debug("nan_vdev_delete_notif called"); + psoc = wlan_vdev_get_psoc(vdev); + if (psoc) { + nan_psoc_obj = nan_get_psoc_priv_obj(psoc); + if (nan_psoc_obj) + nan_psoc_obj->vdev = NULL; + else + nan_err("nan_psoc_obj is null"); + } else { + nan_err("psoc is null"); + } + nan_obj = nan_get_vdev_priv_obj(vdev); if (!nan_obj) { nan_err("nan_obj is NULL"); diff --git a/umac/nan/core/src/nan_main_i.h b/umac/nan/core/src/nan_main_i.h index c66594ceac6e..b95c87b5ad06 100644 --- a/umac/nan/core/src/nan_main_i.h +++ b/umac/nan/core/src/nan_main_i.h @@ -59,10 +59,12 @@ struct scheduler_msg; * struct nan_psoc_priv_obj - nan private psoc obj * @lock: lock to be acquired before reading or writing to object * @cb_obj: struct contaning callback pointers + * @vdev: ndi vdev */ struct nan_psoc_priv_obj { qdf_spinlock_t lock; struct nan_callbacks cb_obj; + struct wlan_objmgr_vdev *vdev; }; /** diff --git a/umac/nan/dispatcher/inc/nan_ucfg_api.h b/umac/nan/dispatcher/inc/nan_ucfg_api.h index d099b9ea6d59..bec291036a0e 100644 --- a/umac/nan/dispatcher/inc/nan_ucfg_api.h +++ b/umac/nan/dispatcher/inc/nan_ucfg_api.h @@ -25,10 +25,13 @@ #include "qdf_types.h" #include "qdf_status.h" +#include "wlan_objmgr_cmn.h" struct nan_callbacks; struct wlan_objmgr_vdev; struct wlan_objmgr_psoc; +struct wlan_objmgr_vdev; +struct nan_callbacks; /** * ucfg_nan_set_ndi_state: set ndi state @@ -170,15 +173,53 @@ 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_get_ndi_vdev: ucfg API get ndi vdev from psoc + * @psoc: psoc obj pointer + * @dbg_id: component id that will be owner of reference + * + * Return: vdev object pointer on success, null otherwise + */ +struct wlan_objmgr_vdev *ucfg_nan_get_ndi_vdev(struct wlan_objmgr_psoc *psoc, + wlan_objmgr_ref_dbgid dbg_id); + /** * ucfg_nan_req_processor: ucfg API to be called from HDD/OS_IF to * process nan datapath initiator request from userspace + * @vdev: nan vdev pointer * @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); +QDF_STATUS ucfg_nan_req_processor(struct wlan_objmgr_vdev *vdev, + void *in_req, uint32_t req_type); + +/** + * ucfg_nan_register_hdd_callbacks: ucfg API to set hdd callbacks + * @psoc: pointer to psoc object + * @cb_obj: structs containing callbacks + * @os_if_event_handler: os if event handler callback + * + * Return: status of operation + */ +int ucfg_nan_register_hdd_callbacks(struct wlan_objmgr_psoc *psoc, + struct nan_callbacks *cb_obj, + void (os_if_event_handler)( + struct wlan_objmgr_psoc *, + struct wlan_objmgr_vdev *, + uint32_t, void *)); + +/** + * ucfg_nan_get_callbacks: ucfg API to return callbacks + * @psoc: pointer to psoc object + * @cb_obj: callback struct to populate + * + * Return: callback struct on sucess, NULL otherwise + */ +QDF_STATUS ucfg_nan_get_callbacks(struct wlan_objmgr_psoc *psoc, + struct nan_callbacks *cb_obj); #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 b432346ab72a..023d36b4a2eb 100644 --- a/umac/nan/dispatcher/src/nan_ucfg_api.c +++ b/umac/nan/dispatcher/src/nan_ucfg_api.c @@ -24,6 +24,12 @@ #include "nan_public_structs.h" #include "../../core/src/nan_main_i.h" #include "scheduler_api.h" +#include "wlan_objmgr_psoc_obj.h" +#include "wlan_objmgr_pdev_obj.h" +#include "wlan_objmgr_vdev_obj.h" + +struct wlan_objmgr_psoc; +struct wlan_objmgr_vdev; inline QDF_STATUS ucfg_nan_set_ndi_state(struct wlan_objmgr_vdev *vdev, uint32_t state) @@ -296,7 +302,28 @@ 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) +struct wlan_objmgr_vdev *ucfg_nan_get_ndi_vdev(struct wlan_objmgr_psoc *psoc, + wlan_objmgr_ref_dbgid dbg_id) +{ + QDF_STATUS status; + struct nan_psoc_priv_obj *psoc_obj = nan_get_psoc_priv_obj(psoc); + + if (!psoc_obj) { + nan_err("nan psoc priv object is NULL"); + return NULL; + } + + status = wlan_objmgr_vdev_try_get_ref(psoc_obj->vdev, dbg_id); + if (QDF_IS_STATUS_ERROR(status)) { + nan_err("could not get vdev ref. vdev may have been deleted"); + return NULL; + } + + return psoc_obj->vdev; +} + +QDF_STATUS ucfg_nan_req_processor(struct wlan_objmgr_vdev *vdev, + void *in_req, uint32_t req_type) { QDF_STATUS status; struct scheduler_msg msg = {0}; @@ -317,3 +344,31 @@ QDF_STATUS ucfg_nan_req_processor(void *in_req, uint32_t req_type) return status; } + +int ucfg_nan_register_hdd_callbacks(struct wlan_objmgr_psoc *psoc, + struct nan_callbacks *cb_obj, + void (os_if_event_handler)( + struct wlan_objmgr_psoc *, + struct wlan_objmgr_vdev *, + uint32_t, void *)) +{ + struct nan_psoc_priv_obj *psoc_obj = nan_get_psoc_priv_obj(psoc); + + if (!psoc_obj) { + nan_err("nan psoc priv object is NULL"); + return -EINVAL; + } + + psoc_obj->cb_obj.os_if_event_handler = os_if_event_handler; + + psoc_obj->cb_obj.ndi_open = cb_obj->ndi_open; + psoc_obj->cb_obj.ndi_start = cb_obj->ndi_start; + psoc_obj->cb_obj.ndi_delete = cb_obj->ndi_delete; + psoc_obj->cb_obj.ndi_close = cb_obj->ndi_close; + psoc_obj->cb_obj.drv_ndi_create_rsp_handler = + cb_obj->drv_ndi_create_rsp_handler; + psoc_obj->cb_obj.drv_ndi_delete_rsp_handler = + cb_obj->drv_ndi_delete_rsp_handler; + + return 0; +}