From 930869e013ede713fb970a9e36cf57efbf28fe92 Mon Sep 17 00:00:00 2001 From: Wu Gao Date: Mon, 6 Mar 2017 14:00:02 +0800 Subject: [PATCH] qcacmn: Private commands and wmi events for P2P Deliver private commands for P2P component. Registers and unregisters wmi events by target interface. Handles wmi events from target interface. Change-Id: Ic25f1c22ae1650f2b059b3fb428daa1b2e66b93c CRs-Fixed: 2015115 --- umac/p2p/core/src/wlan_p2p_main.c | 245 +++++++++++++++++--- umac/p2p/core/src/wlan_p2p_main.h | 35 +++ umac/p2p/dispatcher/inc/wlan_p2p_tgt_api.h | 44 ++++ umac/p2p/dispatcher/src/wlan_p2p_tgt_api.c | 148 ++++++++++++ umac/p2p/dispatcher/src/wlan_p2p_ucfg_api.c | 69 +++++- 5 files changed, 504 insertions(+), 37 deletions(-) diff --git a/umac/p2p/core/src/wlan_p2p_main.c b/umac/p2p/core/src/wlan_p2p_main.c index 9d62e5b6a0a5..faf753339940 100644 --- a/umac/p2p/core/src/wlan_p2p_main.c +++ b/umac/p2p/core/src/wlan_p2p_main.c @@ -100,13 +100,13 @@ static QDF_STATUS p2p_psoc_obj_create_notification( struct p2p_soc_priv_obj *p2p_soc_obj; QDF_STATUS status; - if (soc == NULL) { + if (!soc) { p2p_err("psoc context passed is NULL"); return QDF_STATUS_E_INVAL; } p2p_soc_obj = qdf_mem_malloc(sizeof(*p2p_soc_obj)); - if (p2p_soc_obj == NULL) { + if (!p2p_soc_obj) { p2p_err("Failed to allocate p2p soc private object"); return QDF_STATUS_E_NOMEM; } @@ -122,7 +122,7 @@ static QDF_STATUS p2p_psoc_obj_create_notification( return status; } - p2p_info("p2p soc object create successful, %p", p2p_soc_obj); + p2p_debug("p2p soc object create successful, %p", p2p_soc_obj); return QDF_STATUS_SUCCESS; } @@ -143,14 +143,14 @@ static QDF_STATUS p2p_psoc_obj_destroy_notification( struct p2p_soc_priv_obj *p2p_soc_obj; QDF_STATUS status; - if (soc == NULL) { + if (!soc) { p2p_err("psoc context passed is NULL"); return QDF_STATUS_E_INVAL; } p2p_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(soc, WLAN_UMAC_COMP_P2P); - if (p2p_soc_obj == NULL) { + if (!p2p_soc_obj) { p2p_err("p2p soc private object is NULL"); return QDF_STATUS_E_FAILURE; } @@ -164,7 +164,7 @@ static QDF_STATUS p2p_psoc_obj_destroy_notification( return status; } - p2p_info("destroy p2p soc object, %p", p2p_soc_obj); + p2p_debug("destroy p2p soc object, %p", p2p_soc_obj); qdf_mem_free(p2p_soc_obj); @@ -186,14 +186,25 @@ static QDF_STATUS p2p_vdev_obj_create_notification( { struct p2p_vdev_priv_obj *p2p_vdev_obj; QDF_STATUS status; + enum tQDF_ADAPTER_MODE mode; - if (vdev == NULL) { + if (!vdev) { p2p_err("vdev context passed is NULL"); return QDF_STATUS_E_INVAL; } - p2p_vdev_obj = qdf_mem_malloc(sizeof(*p2p_vdev_obj)); - if (p2p_vdev_obj == NULL) { + wlan_vdev_obj_lock(vdev); + mode = wlan_vdev_mlme_get_opmode(vdev); + wlan_vdev_obj_unlock(vdev); + p2p_debug("vdev mode:%d", mode); + if (mode != QDF_P2P_GO_MODE) { + p2p_debug("won't create p2p vdev private object if it is not GO"); + return QDF_STATUS_SUCCESS; + } + + p2p_vdev_obj = + qdf_mem_malloc(sizeof(*p2p_vdev_obj)); + if (!p2p_vdev_obj) { p2p_err("Failed to allocate p2p vdev object"); return QDF_STATUS_E_NOMEM; } @@ -210,7 +221,7 @@ static QDF_STATUS p2p_vdev_obj_create_notification( return status; } - p2p_info("p2p vdev object create successful, %p", p2p_vdev_obj); + p2p_debug("p2p vdev object create successful, %p", p2p_vdev_obj); return QDF_STATUS_SUCCESS; } @@ -230,17 +241,27 @@ static QDF_STATUS p2p_vdev_obj_destroy_notification( { struct p2p_vdev_priv_obj *p2p_vdev_obj; QDF_STATUS status; + enum tQDF_ADAPTER_MODE mode; - if (vdev == NULL) { + if (!vdev) { p2p_err("vdev context passed is NULL"); return QDF_STATUS_E_INVAL; } + wlan_vdev_obj_lock(vdev); + mode = wlan_vdev_mlme_get_opmode(vdev); + wlan_vdev_obj_unlock(vdev); + p2p_debug("vdev mode:%d", mode); + if (mode != QDF_P2P_GO_MODE) { + p2p_debug("no p2p vdev private object if it is not GO"); + return QDF_STATUS_SUCCESS; + } + p2p_vdev_obj = wlan_objmgr_vdev_get_comp_private_obj(vdev, WLAN_UMAC_COMP_P2P); - if (p2p_vdev_obj == NULL) { - p2p_err("p2p vdev object is NULL"); - return QDF_STATUS_E_FAILURE; + if (!p2p_vdev_obj) { + p2p_debug("p2p vdev object is NULL"); + return QDF_STATUS_SUCCESS; } p2p_vdev_obj->vdev = NULL; @@ -252,7 +273,7 @@ static QDF_STATUS p2p_vdev_obj_destroy_notification( return status; } - p2p_info("destroy p2p vdev object, p2p vdev obj:%p, noa info:%p", + p2p_debug("destroy p2p vdev object, p2p vdev obj:%p, noa info:%p", p2p_vdev_obj, p2p_vdev_obj->noa_info); if (p2p_vdev_obj->noa_info) @@ -263,6 +284,69 @@ static QDF_STATUS p2p_vdev_obj_destroy_notification( return QDF_STATUS_SUCCESS; } +/** + * p2p_send_noa_to_pe() - send noa information to pe + * @noa_info: vdev context + * + * This function sends noa information to pe since MCL layer need noa + * event. + * + * Return: QDF_STATUS_SUCCESS - in case of success + */ +static QDF_STATUS p2p_send_noa_to_pe(struct p2p_noa_info *noa_info) +{ + struct p2p_noa_attr *noa_attr; + struct scheduler_msg msg; + + if (!noa_info) { + p2p_err("noa info is null"); + return QDF_STATUS_E_INVAL; + } + + noa_attr = qdf_mem_malloc(sizeof(*noa_attr)); + if (!noa_attr) { + p2p_err("Failed to allocate memory for tSirP2PNoaAttr"); + return QDF_STATUS_E_NOMEM; + } + + noa_attr->index = noa_info->index; + noa_attr->opps_ps = noa_info->opps_ps; + noa_attr->ct_win = noa_info->ct_window; + if (!noa_info->num_desc) { + p2p_debug("Zero noa descriptors"); + } else { + p2p_debug("%d noa descriptors", noa_info->num_desc); + + noa_attr->noa1_count = + noa_info->noa_desc[0].type_count; + noa_attr->noa1_duration = + noa_info->noa_desc[0].duration; + noa_attr->noa1_interval = + noa_info->noa_desc[0].interval; + noa_attr->noa1_start_time = + noa_info->noa_desc[0].start_time; + if (noa_info->num_desc > 1) { + noa_attr->noa2_count = + noa_info->noa_desc[1].type_count; + noa_attr->noa2_duration = + noa_info->noa_desc[1].duration; + noa_attr->noa2_interval = + noa_info->noa_desc[1].interval; + noa_attr->noa2_start_time = + noa_info->noa_desc[1].start_time; + } + } + + p2p_debug("Sending P2P_NOA_ATTR_IND to pe"); + + msg.type = P2P_NOA_ATTR_IND; + msg.bodyval = 0; + msg.bodyptr = noa_attr; + scheduler_post_msg(QDF_MODULE_ID_PE, &msg); + + return QDF_STATUS_SUCCESS; +} + QDF_STATUS p2p_component_init(void) { QDF_STATUS status; @@ -373,14 +457,14 @@ QDF_STATUS p2p_psoc_object_open(struct wlan_objmgr_psoc *soc) { struct p2p_soc_priv_obj *p2p_soc_obj; - if (soc == NULL) { + if (!soc) { p2p_err("psoc context passed is NULL"); return QDF_STATUS_E_INVAL; } p2p_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(soc, WLAN_UMAC_COMP_P2P); - if (p2p_soc_obj == NULL) { + if (!p2p_soc_obj) { p2p_err("p2p soc priviate object is NULL"); return QDF_STATUS_E_FAILURE; } @@ -389,7 +473,6 @@ QDF_STATUS p2p_psoc_object_open(struct wlan_objmgr_psoc *soc) qdf_list_create(&p2p_soc_obj->tx_q_roc, MAX_QUEUE_LENGTH); qdf_list_create(&p2p_soc_obj->tx_q_ack, MAX_QUEUE_LENGTH); qdf_event_create(&p2p_soc_obj->cancel_roc_done); - /*TODO, register scan event, wmi lo and noa event */ p2p_debug("p2p psoc object open successful"); @@ -400,22 +483,22 @@ QDF_STATUS p2p_psoc_object_close(struct wlan_objmgr_psoc *soc) { struct p2p_soc_priv_obj *p2p_soc_obj; - if (soc == NULL) { + if (!soc) { p2p_err("psoc context passed is NULL"); return QDF_STATUS_E_INVAL; } p2p_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(soc, WLAN_UMAC_COMP_P2P); - if (p2p_soc_obj == NULL) { + if (!p2p_soc_obj) { p2p_err("p2p soc object is NULL"); return QDF_STATUS_E_FAILURE; } - qdf_list_destroy(&p2p_soc_obj->roc_q); - qdf_list_destroy(&p2p_soc_obj->tx_q_roc); + qdf_event_destroy(&p2p_soc_obj->cancel_roc_done); qdf_list_destroy(&p2p_soc_obj->tx_q_ack); - /*TODO, ucfg_scan_clear_requestor_id(soc, p2p_soc_obj->scan_req_id);*/ + qdf_list_destroy(&p2p_soc_obj->tx_q_roc); + qdf_list_destroy(&p2p_soc_obj->roc_q); p2p_debug("p2p psoc object close successful"); @@ -428,20 +511,20 @@ QDF_STATUS p2p_psoc_start(struct wlan_objmgr_psoc *soc, struct p2p_soc_priv_obj *p2p_soc_obj; struct p2p_start_param *start_param; - if (soc == NULL) { + if (!soc) { p2p_err("psoc context passed is NULL"); return QDF_STATUS_E_INVAL; } p2p_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(soc, WLAN_UMAC_COMP_P2P); - if (p2p_soc_obj == NULL) { + if (!p2p_soc_obj) { p2p_err("P2P soc object is NULL"); return QDF_STATUS_E_FAILURE; } start_param = qdf_mem_malloc(sizeof(*start_param)); - if (start_param == NULL) { + if (!start_param) { p2p_err("Failed to allocate start params"); return QDF_STATUS_E_NOMEM; } @@ -455,6 +538,10 @@ QDF_STATUS p2p_psoc_start(struct wlan_objmgr_psoc *soc, start_param->lo_event_cb_data = req->lo_event_cb_data; p2p_soc_obj->start_param = start_param; + /* register p2p lo stop and noa event */ + tgt_p2p_register_lo_ev_handler(soc); + tgt_p2p_register_noa_ev_handler(soc); + p2p_debug("p2p psoc start successful"); return QDF_STATUS_SUCCESS; @@ -465,25 +552,29 @@ QDF_STATUS p2p_psoc_stop(struct wlan_objmgr_psoc *soc) struct p2p_soc_priv_obj *p2p_soc_obj; struct p2p_start_param *start_param; - if (soc == NULL) { + if (!soc) { p2p_err("psoc context passed is NULL"); return QDF_STATUS_E_INVAL; } p2p_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(soc, WLAN_UMAC_COMP_P2P); - if (p2p_soc_obj == NULL) { + if (!p2p_soc_obj) { p2p_err("P2P soc object is NULL"); return QDF_STATUS_E_FAILURE; } start_param = p2p_soc_obj->start_param; p2p_soc_obj->start_param = NULL; - if (start_param == NULL) { + if (!start_param) { p2p_err("start parameters is NULL"); return QDF_STATUS_E_FAILURE; } + /* unregister p2p lo stop and noa event */ + tgt_p2p_unregister_lo_ev_handler(soc); + tgt_p2p_unregister_noa_ev_handler(soc); + start_param->rx_cb = NULL; start_param->rx_cb_data = NULL; start_param->event_cb = NULL; @@ -501,10 +592,10 @@ QDF_STATUS p2p_process_cmd(struct scheduler_msg *msg) { QDF_STATUS status; - p2p_info("msg type %d, %s", msg->type, + p2p_debug("msg type %d, %s", msg->type, p2p_get_cmd_type_str(msg->type)); - if (msg->bodyptr == NULL) { + if (!(msg->bodyptr)) { p2p_err("Invalid message body"); return QDF_STATUS_E_INVAL; } @@ -546,10 +637,10 @@ QDF_STATUS p2p_process_evt(struct scheduler_msg *msg) { QDF_STATUS status; - p2p_info("msg type %d, %s", msg->type, + p2p_debug("msg type %d, %s", msg->type, p2p_get_event_type_str(msg->type)); - if (msg->bodyptr == NULL) { + if (!(msg->bodyptr)) { p2p_err("Invalid message body"); return QDF_STATUS_E_INVAL; } @@ -591,10 +682,96 @@ QDF_STATUS p2p_process_evt(struct scheduler_msg *msg) QDF_STATUS p2p_process_lo_stop( struct p2p_lo_stop_event *lo_stop_event) { + struct p2p_lo_event *lo_evt; + struct p2p_soc_priv_obj *p2p_soc_obj; + struct p2p_start_param *start_param; + + if (!lo_stop_event) { + p2p_err("invalid lo stop event"); + return QDF_STATUS_E_INVAL; + } + lo_evt = lo_stop_event->lo_event; + p2p_soc_obj = lo_stop_event->p2p_soc_obj; + + p2p_debug("vdev_id %d, reason %d", + lo_evt->vdev_id, lo_evt->reason_code); + + if (!p2p_soc_obj || !(p2p_soc_obj->start_param)) { + p2p_err("Invalid p2p soc object or start parameters"); + return QDF_STATUS_E_INVAL; + } + start_param = p2p_soc_obj->start_param; + if (start_param->lo_event_cb) + start_param->lo_event_cb( + start_param->lo_event_cb_data, lo_evt); + else + p2p_err("Invalid p2p soc obj or hdd lo event callback"); + + qdf_mem_free(lo_evt); + return QDF_STATUS_SUCCESS; } QDF_STATUS p2p_process_noa(struct p2p_noa_event *noa_event) { - return QDF_STATUS_SUCCESS; + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct p2p_noa_info *noa_info; + struct p2p_vdev_priv_obj *p2p_vdev_obj; + struct p2p_soc_priv_obj *p2p_soc_obj; + struct wlan_objmgr_vdev *vdev; + struct wlan_objmgr_psoc *psoc; + enum tQDF_ADAPTER_MODE mode; + + if (!noa_event) { + p2p_err("invalid noa event"); + return QDF_STATUS_E_INVAL; + } + noa_info = noa_event->noa_info; + p2p_soc_obj = noa_event->p2p_soc_obj; + psoc = p2p_soc_obj->soc; + + p2p_debug("psoc:%p, index:%d, opps_ps:%d, ct_window:%d, num_desc:%d, vdev_id:%d", + psoc, noa_info->index, noa_info->opps_ps, + noa_info->ct_window, noa_info->num_desc, + noa_info->vdev_id); + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, + noa_info->vdev_id, WLAN_P2P_ID); + if (!vdev) { + p2p_err("vdev obj is NULL"); + qdf_mem_free(noa_event->noa_info); + return QDF_STATUS_E_INVAL; + } + + wlan_vdev_obj_lock(vdev); + mode = wlan_vdev_mlme_get_opmode(vdev); + wlan_vdev_obj_unlock(vdev); + p2p_debug("vdev mode:%d", mode); + if (mode != QDF_P2P_GO_MODE) { + p2p_err("invalid p2p vdev mode:%d", mode); + status = QDF_STATUS_E_INVAL; + goto fail; + } + + /* must send noa to pe since of limitation*/ + p2p_send_noa_to_pe(noa_info); + + p2p_vdev_obj = wlan_objmgr_vdev_get_comp_private_obj(vdev, + WLAN_UMAC_COMP_P2P); + if (!(p2p_vdev_obj->noa_info)) { + p2p_vdev_obj->noa_info = + qdf_mem_malloc(sizeof(struct p2p_noa_info)); + if (!(p2p_vdev_obj->noa_info)) { + p2p_err("Failed to allocate p2p noa info"); + status = QDF_STATUS_E_NOMEM; + goto fail; + } + } + qdf_mem_copy(p2p_vdev_obj->noa_info, noa_info, + sizeof(struct p2p_noa_info)); +fail: + qdf_mem_free(noa_event->noa_info); + wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID); + + return status; } diff --git a/umac/p2p/core/src/wlan_p2p_main.h b/umac/p2p/core/src/wlan_p2p_main.h index 6b6a35506d21..7b2e0056563b 100644 --- a/umac/p2p/core/src/wlan_p2p_main.h +++ b/umac/p2p/core/src/wlan_p2p_main.h @@ -28,6 +28,7 @@ #include #define MAX_QUEUE_LENGTH 20 +#define P2P_NOA_ATTR_IND 0x1090 #define P2P_MODULE_NAME "P2P" #define p2p_log(level, args...) \ @@ -154,6 +155,40 @@ struct p2p_vdev_priv_obj { struct p2p_noa_info *noa_info; }; +/** + * struct p2p_noa_attr - p2p noa attribute + * @rsvd1: reserved bits 1 + * @opps_ps: opps ps state of the AP + * @ct_win: ct window in TUs + * @index: identifies instance of NOA su element + * @rsvd2: reserved bits 2 + * @noa1_count: interval count of noa1 + * @noa1_duration: absent period duration of noa1 + * @noa1_interval: absent period interval of noa1 + * @noa1_start_time: 32 bit tsf time of noa1 + * @rsvd3: reserved bits 3 + * @noa2_count: interval count of noa2 + * @noa2_duration: absent period duration of noa2 + * @noa2_interval: absent period interval of noa2 + * @noa2_start_time: 32 bit tsf time of noa2 + */ +struct p2p_noa_attr { + uint32_t rsvd1:16; + uint32_t ct_win:7; + uint32_t opps_ps:1; + uint32_t index:8; + uint32_t rsvd2:24; + uint32_t noa1_count:8; + uint32_t noa1_duration; + uint32_t noa1_interval; + uint32_t noa1_start_time; + uint32_t rsvd3:24; + uint32_t noa2_count:8; + uint32_t noa2_duration; + uint32_t noa2_interval; + uint32_t noa2_start_time; +}; + /** * p2p_component_init() - P2P component initialization * diff --git a/umac/p2p/dispatcher/inc/wlan_p2p_tgt_api.h b/umac/p2p/dispatcher/inc/wlan_p2p_tgt_api.h index b5dc946ac92b..5644f263ca1f 100644 --- a/umac/p2p/dispatcher/inc/wlan_p2p_tgt_api.h +++ b/umac/p2p/dispatcher/inc/wlan_p2p_tgt_api.h @@ -33,6 +33,50 @@ struct p2p_lo_event; struct mgmt_rx_event_params; enum mgmt_frame_type; +/** + * tgt_p2p_register_lo_ev_handler() - register lo event + * @psoc: soc object + * + * p2p tgt api to register listen offload event handler. + * + * Return: QDF_STATUS_SUCCESS - in case of success + */ +QDF_STATUS tgt_p2p_register_lo_ev_handler( + struct wlan_objmgr_psoc *psoc); + +/** + * tgt_p2p_register_noa_ev_handler() - register noa event + * @psoc: soc object + * + * p2p tgt api to register noa event handler. + * + * Return: QDF_STATUS_SUCCESS - in case of success + */ +QDF_STATUS tgt_p2p_register_noa_ev_handler( + struct wlan_objmgr_psoc *psoc); + +/** + * tgt_p2p_unregister_lo_ev_handler() - unregister lo event + * @psoc: soc object + * + * p2p tgt api to unregister listen offload event handler. + * + * Return: QDF_STATUS_SUCCESS - in case of success + */ +QDF_STATUS tgt_p2p_unregister_lo_ev_handler( + struct wlan_objmgr_psoc *psoc); + +/** + * tgt_p2p_unregister_noa_ev_handler() - unregister noa event + * @psoc: soc object + * + * p2p tgt api to unregister noa event handler. + * + * Return: QDF_STATUS_SUCCESS - in case of success + */ +QDF_STATUS tgt_p2p_unregister_noa_ev_handler( + struct wlan_objmgr_psoc *psoc); + /** * tgt_p2p_scan_event_cb() - Callback for scan event * @vdev: vdev object diff --git a/umac/p2p/dispatcher/src/wlan_p2p_tgt_api.c b/umac/p2p/dispatcher/src/wlan_p2p_tgt_api.c index b87af0bed613..e2ca5192273b 100644 --- a/umac/p2p/dispatcher/src/wlan_p2p_tgt_api.c +++ b/umac/p2p/dispatcher/src/wlan_p2p_tgt_api.c @@ -27,6 +27,72 @@ #include "wlan_p2p_public_struct.h" #include "../../core/src/wlan_p2p_main.h" +static inline struct wlan_lmac_if_p2p_tx_ops * +wlan_psoc_get_p2p_tx_ops(struct wlan_objmgr_psoc *psoc) +{ + return &(psoc->soc_cb.tx_ops.p2p); +} + +QDF_STATUS tgt_p2p_register_lo_ev_handler( + struct wlan_objmgr_psoc *psoc) +{ + struct wlan_lmac_if_p2p_tx_ops *p2p_ops; + QDF_STATUS status = QDF_STATUS_E_FAILURE; + + p2p_ops = wlan_psoc_get_p2p_tx_ops(psoc); + if (p2p_ops && p2p_ops->reg_lo_ev_handler) { + status = p2p_ops->reg_lo_ev_handler(psoc, NULL); + p2p_debug("register lo event, status:%d", status); + } + + return status; +} + +QDF_STATUS tgt_p2p_register_noa_ev_handler( + struct wlan_objmgr_psoc *psoc) +{ + struct wlan_lmac_if_p2p_tx_ops *p2p_ops; + QDF_STATUS status = QDF_STATUS_E_FAILURE; + + p2p_ops = wlan_psoc_get_p2p_tx_ops(psoc); + if (p2p_ops && p2p_ops->reg_noa_ev_handler) { + status = p2p_ops->reg_noa_ev_handler(psoc, NULL); + p2p_debug("register noa event, status:%d", status); + } + + return status; +} + +QDF_STATUS tgt_p2p_unregister_lo_ev_handler( + struct wlan_objmgr_psoc *psoc) +{ + struct wlan_lmac_if_p2p_tx_ops *p2p_ops; + QDF_STATUS status = QDF_STATUS_E_FAILURE; + + p2p_ops = wlan_psoc_get_p2p_tx_ops(psoc); + if (p2p_ops && p2p_ops->unreg_lo_ev_handler) { + status = p2p_ops->unreg_lo_ev_handler(psoc, NULL); + p2p_debug("unregister lo event, status:%d", status); + } + + return status; +} + +QDF_STATUS tgt_p2p_unregister_noa_ev_handler( + struct wlan_objmgr_psoc *psoc) +{ + struct wlan_lmac_if_p2p_tx_ops *p2p_ops; + QDF_STATUS status = QDF_STATUS_E_FAILURE; + + p2p_ops = wlan_psoc_get_p2p_tx_ops(psoc); + if (p2p_ops && p2p_ops->unreg_noa_ev_handler) { + status = p2p_ops->unreg_noa_ev_handler(psoc, NULL); + p2p_debug("unregister noa event, status:%d", status); + } + + return status; +} + void tgt_p2p_scan_event_cb(struct wlan_objmgr_vdev *vdev, struct scan_event *event, void *arg) { @@ -55,11 +121,93 @@ QDF_STATUS tgt_p2p_mgmt_frame_rx_cb(struct wlan_objmgr_psoc *psoc, QDF_STATUS tgt_p2p_noa_event_cb(struct wlan_objmgr_psoc *psoc, struct p2p_noa_info *event_info) { + struct p2p_noa_event *noa_event; + struct scheduler_msg msg; + struct p2p_soc_priv_obj *p2p_soc_obj; + + p2p_debug("soc:%p, event_info:%p", psoc, event_info); + + if (!psoc) { + p2p_err("psoc context passed is NULL"); + if (event_info) + qdf_mem_free(event_info); + return QDF_STATUS_E_INVAL; + } + + p2p_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, + WLAN_UMAC_COMP_P2P); + if (!p2p_soc_obj) { + p2p_err("p2p soc object is NULL"); + if (event_info) + qdf_mem_free(event_info); + return QDF_STATUS_E_INVAL; + } + + if (!event_info) { + p2p_err("invalid noa event information"); + return QDF_STATUS_E_INVAL; + } + + noa_event = qdf_mem_malloc(sizeof(*noa_event)); + if (!noa_event) { + p2p_err("Failed to allocate p2p noa event"); + qdf_mem_free(event_info); + return QDF_STATUS_E_NOMEM; + } + + noa_event->p2p_soc_obj = p2p_soc_obj; + noa_event->noa_info = event_info; + msg.type = P2P_EVENT_NOA; + msg.bodyptr = noa_event; + msg.callback = p2p_process_evt; + scheduler_post_msg(QDF_MODULE_ID_TARGET_IF, &msg); + return QDF_STATUS_SUCCESS; } QDF_STATUS tgt_p2p_lo_event_cb(struct wlan_objmgr_psoc *psoc, struct p2p_lo_event *event_info) { + struct p2p_lo_stop_event *lo_stop_event; + struct scheduler_msg msg; + struct p2p_soc_priv_obj *p2p_soc_obj; + + p2p_debug("soc:%p, event_info:%p", psoc, event_info); + + if (!psoc) { + p2p_err("psoc context passed is NULL"); + if (event_info) + qdf_mem_free(event_info); + return QDF_STATUS_E_INVAL; + } + + p2p_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, + WLAN_UMAC_COMP_P2P); + if (!p2p_soc_obj) { + p2p_err("p2p soc object is NULL"); + if (event_info) + qdf_mem_free(event_info); + return QDF_STATUS_E_INVAL; + } + + if (!event_info) { + p2p_err("invalid lo stop event information"); + return QDF_STATUS_E_INVAL; + } + + lo_stop_event = qdf_mem_malloc(sizeof(*lo_stop_event)); + if (!lo_stop_event) { + p2p_err("Failed to allocate p2p lo stop event"); + qdf_mem_free(event_info); + return QDF_STATUS_E_NOMEM; + } + + lo_stop_event->p2p_soc_obj = p2p_soc_obj; + lo_stop_event->lo_event = event_info; + msg.type = P2P_EVENT_LO_STOPPED; + msg.bodyptr = lo_stop_event; + msg.callback = p2p_process_evt; + scheduler_post_msg(QDF_MODULE_ID_TARGET_IF, &msg); + return QDF_STATUS_SUCCESS; } diff --git a/umac/p2p/dispatcher/src/wlan_p2p_ucfg_api.c b/umac/p2p/dispatcher/src/wlan_p2p_ucfg_api.c index 86e98fcc5881..375c0a3f87ac 100644 --- a/umac/p2p/dispatcher/src/wlan_p2p_ucfg_api.c +++ b/umac/p2p/dispatcher/src/wlan_p2p_ucfg_api.c @@ -27,6 +27,12 @@ #include "wlan_p2p_public_struct.h" #include "../../core/src/wlan_p2p_main.h" +static inline struct wlan_lmac_if_p2p_tx_ops * +ucfg_p2p_psoc_get_tx_ops(struct wlan_objmgr_psoc *psoc) +{ + return &(psoc->soc_cb.tx_ops.p2p); +} + QDF_STATUS ucfg_p2p_init(void) { return p2p_component_init(); @@ -85,17 +91,74 @@ QDF_STATUS ucfg_p2p_mgmt_tx_cancel(struct wlan_objmgr_psoc *soc, QDF_STATUS ucfg_p2p_set_ps(struct wlan_objmgr_psoc *soc, struct p2p_ps_config *ps_config) { - return QDF_STATUS_SUCCESS; + struct wlan_lmac_if_p2p_tx_ops *p2p_ops; + QDF_STATUS status = QDF_STATUS_E_FAILURE; + + p2p_debug("soc:%p, vdev_id:%d, opp_ps:%d, ct_window:%d, count:%d, duration:%d, duration:%d, ps_selection:%d", + soc, ps_config->vdev_id, ps_config->opp_ps, + ps_config->ct_window, ps_config->count, + ps_config->duration, ps_config->single_noa_duration, + ps_config->ps_selection); + + if (!soc) { + p2p_err("psoc context passed is NULL"); + return QDF_STATUS_E_INVAL; + } + + p2p_ops = ucfg_p2p_psoc_get_tx_ops(soc); + if (p2p_ops->set_ps) { + status = p2p_ops->set_ps(soc, ps_config); + p2p_debug("p2p set ps, status:%d", status); + } + + return status; } QDF_STATUS ucfg_p2p_lo_start(struct wlan_objmgr_psoc *soc, struct p2p_lo_start *p2p_lo_start) { - return QDF_STATUS_SUCCESS; + struct wlan_lmac_if_p2p_tx_ops *p2p_ops; + QDF_STATUS status = QDF_STATUS_E_FAILURE; + + p2p_debug("soc:%p, vdev_id:%d, ctl_flags:%d, freq:%d, period:%d, interval:%d, count:%d, dev_types_len:%d, probe_resp_len:%d, device_types:%p, probe_resp_tmplt:%p", + soc, p2p_lo_start->vdev_id, p2p_lo_start->ctl_flags, + p2p_lo_start->freq, p2p_lo_start->period, + p2p_lo_start->interval, p2p_lo_start->count, + p2p_lo_start->dev_types_len, p2p_lo_start->probe_resp_len, + p2p_lo_start->device_types, p2p_lo_start->probe_resp_tmplt); + + if (!soc) { + p2p_err("psoc context passed is NULL"); + return QDF_STATUS_E_INVAL; + } + + p2p_ops = ucfg_p2p_psoc_get_tx_ops(soc); + if (p2p_ops->lo_start) { + status = p2p_ops->lo_start(soc, p2p_lo_start); + p2p_debug("p2p lo start, status:%d", status); + } + + return status; } QDF_STATUS ucfg_p2p_lo_stop(struct wlan_objmgr_psoc *soc, uint32_t vdev_id) { - return QDF_STATUS_SUCCESS; + struct wlan_lmac_if_p2p_tx_ops *p2p_ops; + QDF_STATUS status = QDF_STATUS_E_FAILURE; + + p2p_debug("soc:%p, vdev_id:%d", soc, vdev_id); + + if (!soc) { + p2p_err("psoc context passed is NULL"); + return QDF_STATUS_E_INVAL; + } + + p2p_ops = ucfg_p2p_psoc_get_tx_ops(soc); + if (p2p_ops->lo_stop) { + status = p2p_ops->lo_stop(soc, vdev_id); + p2p_debug("p2p lo stop, status:%d", status); + } + + return status; }