diff --git a/qdf/inc/qdf_status.h b/qdf/inc/qdf_status.h index 0a58c4eb48..a8e00e79fb 100644 --- a/qdf/inc/qdf_status.h +++ b/qdf/inc/qdf_status.h @@ -79,6 +79,9 @@ * @QDF_STATUS_CMD_NOT_QUEUED: command not queued * @QDF_STATUS_FW_MSG_TIMEDOUT: target message timeout * @QDF_STATUS_E_USB_ERROR: USB transaction error + * @QDF_STATUS_MAXCOMP_FAIL: Component id is more than MAX UMAC components + * @QDF_STATUS_COMP_DISABLED: UMAC Component is disabled + * @QDF_STATUS_COMP_ASYNC: UMAC component runs in asynchronous communication * @QDF_STATUS_MAX: not a realy value just a place holder for max */ typedef enum { @@ -125,6 +128,9 @@ typedef enum { QDF_STATUS_CMD_NOT_QUEUED, QDF_STATUS_FW_MSG_TIMEDOUT, QDF_STATUS_E_USB_ERROR, + QDF_STATUS_MAXCOMP_FAIL, + QDF_STATUS_COMP_DISABLED, + QDF_STATUS_COMP_ASYNC, QDF_STATUS_MAX } QDF_STATUS; diff --git a/qdf/inc/qdf_types.h b/qdf/inc/qdf_types.h index a1351a5460..8cf56ea7a0 100644 --- a/qdf/inc/qdf_types.h +++ b/qdf/inc/qdf_types.h @@ -296,6 +296,9 @@ typedef enum { * @QDF_EPPING_MODE: EPPING device mode * @QDF_QVIT_MODE: QVIT device mode * @QDF_NDI_MODE: NAN datapath mode + * @QDF_WDS_MODE: WDS mode + * @QDF_BTAMP_MODE: BTAMP mode + * @QDF_AHDEMO_MODE: AHDEMO mode * @QDF_MAX_NO_OF_MODE: Max place holder * * These are generic IDs that identify the various roles @@ -314,6 +317,9 @@ enum tQDF_ADAPTER_MODE { QDF_EPPING_MODE, QDF_QVIT_MODE, QDF_NDI_MODE, + QDF_WDS_MODE, + QDF_BTAMP_MODE, + QDF_AHDEMO_MODE, QDF_MAX_NO_OF_MODE }; diff --git a/umac/cmn_services/obj_mgr/inc/wlan_objmgr_cmn.h b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_cmn.h new file mode 100644 index 0000000000..9b8f6c477b --- /dev/null +++ b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_cmn.h @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + /** + * DOC: This file provides the common defintions for object manager + */ + +#ifndef _WLAN_OBJMGR_CMN_H_ +#define _WLAN_OBJMGR_CMN_H_ + +#include "qdf_lock.h" +#include "qdf_list.h" +#include "qdf_status.h" + +/* No. of PSOCs can be supported */ +#define WLAN_OBJMGR_MAX_DEVICES 2 +/* Max no of UMAC components */ +#define WLAN_UMAC_MAX_COMPONENTS 25 +/* Max no. of radios, a pSoc/Device can support */ +#define WLAN_UMAC_MAX_PDEVS 3 +/* Max no. of VDEV per PSOC */ +#define WLAN_UMAC_PSOC_MAX_VDEVS 51 +/* Max no. of VDEVs, a PDEV can support */ +#define WLAN_UMAC_PDEV_MAX_VDEVS 17 +/* Max no. of Peers, a device can support */ +#define WLAN_UMAC_PSOC_MAX_PEERS 1024 + + +/* Max length of a SSID */ +#define WLAN_SSID_MAX_LEN 32 + +/* Max no. of Stations can be associated to VDEV*/ +#define WLAN_UMAC_MAX_AP_PEERS WLAN_UMAC_PSOC_MAX_PEERS +/* Max no. of peers for STA vap */ +#define WLAN_UMAC_MAX_STA_PEERS 2 + +/* 802.11 cap info */ +#define WLAN_CAPINFO_ESS 0x0001 +#define WLAN_CAPINFO_IBSS 0x0002 +#define WLAN_CAPINFO_CF_POLLABLE 0x0004 +#define WLAN_CAPINFO_CF_POLLREQ 0x0008 +#define WLAN_CAPINFO_PRIVACY 0x0010 +#define WLAN_CAPINFO_SHORT_PREAMBLE 0x0020 +#define WLAN_CAPINFO_PBCC 0x0040 +#define WLAN_CAPINFO_CHNL_AGILITY 0x0080 +#define WLAN_CAPINFO_SPECTRUM_MGMT 0x0100 +#define WLAN_CAPINFO_QOS 0x0200 +#define WLAN_CAPINFO_SHORT_SLOTTIME 0x0400 +#define WLAN_CAPINFO_APSD 0x0800 +#define WLAN_CAPINFO_RADIOMEAS 0x1000 +#define WLAN_CAPINFO_DSSSOFDM 0x2000 + +/** + * enum wlan_umac_comp_id - UMAC component id + * @WLAN_UMAC_COMP_MLME: MLME + * @WLAN_UMAC_COMP_SCANMGR: SCAN MGR + * @WLAN_UMAC_COMP_SCANCACHE: SCAN CACHE + * @WLAN_UMAC_COMP_MGMT_TXRX: MGMT Tx/Rx + * + * This id is static. + * On Adding new component, new id has to be assigned + */ +enum wlan_umac_comp_id { + WLAN_UMAC_COMP_MLME = 0, + WLAN_UMAC_COMP_SCANMGR = 1, + WLAN_UMAC_COMP_SCANCACHE = 2, + WLAN_UMAC_COMP_MGMT_TXRX = 3, +}; + +/** + * enum WLAN_OBJ_STATE - State of Object + * @WLAN_OBJ_STATE_CREATED: All component objects are created + * @WLAN_OBJ_STATE_DELETED: All component objects are deleted + * @WLAN_OBJ_STATE_PARTIALLY_CREATED: Few/All component objects creation is + * in progress + * @WLAN_OBJ_STATE_PARTIALLY_DELETED: Few/All component objects yet to be + * deleted + * @WLAN_OBJ_STATE_COMP_DEL_PROGRESS: If a component is disabled run time, + * and this state is used to represent the + * deletion in progress after that + * component object is deleted, object + * state would be moved to CREATED state + * @WLAN_OBJ_STATE_CREATION_FAILED: any component object is failed to be + * created + * @WLAN_OBJ_STATE_DELETION_FAILED: any component object is failed to be + * deleted + */ +typedef enum { + WLAN_OBJ_STATE_CREATED = 0, + WLAN_OBJ_STATE_DELETED = 1, + WLAN_OBJ_STATE_PARTIALLY_CREATED = 2, + WLAN_OBJ_STATE_PARTIALLY_DELETED = 3, + WLAN_OBJ_STATE_COMP_DEL_PROGRESS = 4, + WLAN_OBJ_STATE_CREATION_FAILED = 5, + WLAN_OBJ_STATE_DELETION_FAILED = 6, +} WLAN_OBJ_STATE; + +/* Object type is assigned with value */ +enum wlan_objmgr_obj_type { + WLAN_PSOC_OP = 0, + WLAN_PDEV_OP = 1, + WLAN_VDEV_OP = 2, + WLAN_PEER_OP = 3, +}; + +/** + * enum WLAN_DEV_TYPE - for DA or OL architecture types + * @WLAN_DEV_DA: Direct attach + * @WLAN_DEV_OL: Partial offload + * @WLAN_DEV_INVALID: Invalid dev type + */ +typedef enum { + WLAN_DEV_DA = 0, + WLAN_DEV_OL = 1, + WLAN_DEV_INVALID = 3, +} WLAN_DEV_TYPE; + +/** + * enum wlan_phymode - phy mode + * @WLAN_PHYMODE_AUTO: autoselect + * @WLAN_PHYMODE_11A: 5GHz, OFDM + * @WLAN_PHYMODE_11B: 2GHz, CCK + * @WLAN_PHYMODE_11G: 2GHz, OFDM + * @WLAN_PHYMODE_11NA_HT20: 5Ghz, HT20 + * @WLAN_PHYMODE_11NG_HT20: 2Ghz, HT20 + * @WLAN_PHYMODE_11NA_HT40PLUS: 5Ghz, HT40 (ext ch +1) + * @WLAN_PHYMODE_11NA_HT40MINUS: 5Ghz, HT40 (ext ch -1) + * @WLAN_PHYMODE_11NG_HT40PLUS: 2Ghz, HT40 (ext ch +1) + * @WLAN_PHYMODE_11NG_HT40MINUS: 2Ghz, HT40 (ext ch -1) + * @WLAN_PHYMODE_11NG_HT40: 2Ghz, Auto HT40 + * @WLAN_PHYMODE_11NA_HT40: 5Ghz, Auto HT40 + * @WLAN_PHYMODE_11AC_VHT20: 5Ghz, VHT20 + * @WLAN_PHYMODE_11AC_VHT40PLUS: 5Ghz, VHT40 (Ext ch +1) + * @WLAN_PHYMODE_11AC_VHT40MINUS:5Ghz VHT40 (Ext ch -1) + * @WLAN_PHYMODE_11AC_VHT40: 5Ghz, VHT40 + * @WLAN_PHYMODE_11AC_VHT80: 5Ghz, VHT80 + * @WLAN_PHYMODE_11AC_VHT160: 5Ghz, VHT160 + * @WLAN_PHYMODE_11AC_VHT80_80: 5Ghz, VHT80_80 + */ +enum wlan_phymode { + WLAN_PHYMODE_AUTO = 0, + WLAN_PHYMODE_11A = 1, + WLAN_PHYMODE_11B = 2, + WLAN_PHYMODE_11G = 3, + WLAN_PHYMODE_11NA_HT20 = 4, + WLAN_PHYMODE_11NG_HT20 = 5, + WLAN_PHYMODE_11NA_HT40PLUS = 6, + WLAN_PHYMODE_11NA_HT40MINUS = 7, + WLAN_PHYMODE_11NG_HT40PLUS = 8, + WLAN_PHYMODE_11NG_HT40MINUS = 9, + WLAN_PHYMODE_11NG_HT40 = 10, + WLAN_PHYMODE_11NA_HT40 = 11, + WLAN_PHYMODE_11AC_VHT20 = 12, + WLAN_PHYMODE_11AC_VHT40PLUS = 13, + WLAN_PHYMODE_11AC_VHT40MINUS = 14, + WLAN_PHYMODE_11AC_VHT40 = 15, + WLAN_PHYMODE_11AC_VHT80 = 16, + WLAN_PHYMODE_11AC_VHT160 = 17, + WLAN_PHYMODE_11AC_VHT80_80 = 18, +}; + +#define WLAN_PHYMODE_MAX (WLAN_PHYMODE_11AC_VHT80_80 + 1) + +/** + * enum wlan_peer_type - peer type + * @WLAN_PEER_SELF: for AP mode, SELF PEER or AP PEER are same + * @WLAN_PEER_AP: BSS peer for STA mode, Self peer for AP mode + * @WLAN_PEER_STA: Self Peer for STA mode, STA peer for AP mode + * @WLAN_PEER_TDLS: TDLS Peer + * @WLAN_PEER_NAWDS: NAWDS Peer + * @WLAN_PEER_STA_TEMP: STA Peer Temp (its host only node) + */ +enum wlan_peer_type { + WLAN_PEER_SELF = 1, + WLAN_PEER_AP = 2, + WLAN_PEER_STA = 3, + WLAN_PEER_TDLS = 4, + WLAN_PEER_NAWDS = 5, + WLAN_PEER_STA_TEMP = 6, +}; + +/* MAC address length */ +#define WLAN_MACADDR_LEN 6 +/* Util API to copy the MAC address */ +#define WLAN_ADDR_COPY(dst, src) qdf_mem_copy(dst, src, WLAN_MACADDR_LEN) +/* Util API to compare the MAC address */ +#define WLAN_ADDR_EQ(a1, a2) qdf_mem_cmp(a1, a2, WLAN_MACADDR_LEN) + +/* size of Hash */ +#define WLAN_PEER_HASHSIZE 64 +/* simple hash is enough for variation of macaddr */ +#define WLAN_PEER_HASH(addr) \ +(((const uint8_t *)(addr))[WLAN_MACADDR_LEN - 1] % WLAN_PEER_HASHSIZE) + +/* Allowed time to wait for Object creation */ +#define WLAN_VDEV_CREATE_TIMEOUT_CNT 300 + /* 25 msec */ +#define WLAN_VDEV_CREATE_TIMEOUT ((CONVERT_SEC_TO_SYSTEM_TIME(1)/40) + 1) + +#define WLAN_PDEV_CREATE_TIMEOUT_CNT 300 + /* 25 msec */ +#define WLAN_PDEV_CREATE_TIMEOUT ((CONVERT_SEC_TO_SYSTEM_TIME(1)/40) + 1) + +#define WLAN_PSOC_CREATE_TIMEOUT_CNT 300 +/* 25 msec */ +#define WLAN_PSOC_CREATE_TIMEOUT ((CONVERT_SEC_TO_SYSTEM_TIME(1)/40) + 1) + +/** + * struct wlan_peer_list { + * @peer_hash[]: peer sub lists + * @peer_list_lock: List lock, this has to be acquired on + * accessing/updating the list + * + * Peer list, it maintains sublists based on the MAC address as hash + * Note: For DA WDS similar peer list has to be maintained + * This peer list will not have WDS nodes + */ +struct wlan_peer_list { + qdf_list_t peer_hash[WLAN_PEER_HASHSIZE]; + qdf_spinlock_t peer_list_lock; +}; + +struct wlan_objmgr_psoc; +struct wlan_objmgr_pdev; +struct wlan_objmgr_vdev; +struct wlan_objmgr_peer; + +/* Create handler would return the following status + QDF_STATUS_SUCCESS-- + For synchronous handler:- this is returned on successful + component object creation + + QDF_STATUS_COMP_DISABLED-- + For synchronous handler:- this is returned on if component + doesn't want to allocate + + QDF_STATUS_COMP_ASYNC-- + For asynchronous handler:- this is returned on if component + needs a context break + + QDF_STATUS_E_NOMEM-- + For synchronous handler:- this is returned on if component + can't allocate + QDF_STATUS_E_FAILURE-- + For synchronous handler:- If it is failed, + For asynchronous handler:- If it is failed to post message + (means, not required)/feature is not supported +*/ +typedef QDF_STATUS (*wlan_objmgr_psoc_create_handler)( + struct wlan_objmgr_psoc *psoc, void *arg); +typedef QDF_STATUS (*wlan_objmgr_psoc_delete_handler)( + struct wlan_objmgr_psoc *psoc, void *arg); +typedef void (*wlan_objmgr_psoc_status_handler)(struct wlan_objmgr_psoc *psoc, + void *arg, QDF_STATUS status); + +typedef QDF_STATUS (*wlan_objmgr_pdev_create_handler)( + struct wlan_objmgr_pdev *pdev, void *arg); +typedef QDF_STATUS (*wlan_objmgr_pdev_delete_handler)( + struct wlan_objmgr_pdev *pdev, void *arg); +typedef void (*wlan_objmgr_pdev_status_handler)( + struct wlan_objmgr_pdev *pdev, void *arg, + QDF_STATUS status); + +typedef QDF_STATUS (*wlan_objmgr_vdev_create_handler)( + struct wlan_objmgr_vdev *vdev, void *arg); +typedef QDF_STATUS (*wlan_objmgr_vdev_delete_handler)( + struct wlan_objmgr_vdev *vdev, void *arg); +typedef void (*wlan_objmgr_vdev_status_handler)( + struct wlan_objmgr_vdev *vdev, void *arg, + QDF_STATUS status); + +typedef QDF_STATUS (*wlan_objmgr_peer_create_handler)( + struct wlan_objmgr_peer *peer, void *arg); +typedef QDF_STATUS (*wlan_objmgr_peer_delete_handler)( + struct wlan_objmgr_peer *peer, void *arg); +typedef void (*wlan_objmgr_peer_status_handler)( + struct wlan_objmgr_peer *peer, void *arg, + QDF_STATUS status); + +#endif /* _WLAN_OBJMGR_CMN_H_*/ diff --git a/umac/cmn_services/obj_mgr/inc/wlan_objmgr_global_obj.h b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_global_obj.h new file mode 100644 index 0000000000..92f16039d2 --- /dev/null +++ b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_global_obj.h @@ -0,0 +1,483 @@ +/* + * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + /** + * DOC: Public APIs to perform operations on Global objects + */ +#ifndef _WLAN_OBJMGR_GLOBAL_OBJ_H_ +#define _WLAN_OBJMGR_GLOBAL_OBJ_H_ + +/** + * wlan_objmgr_global_obj_create() - Creates global object + * + * Creates global object, intializes with default values + * + * Return: SUCCESS on successful creation, + * FAILURE on Mem alloc failure or allocated already + * + */ +QDF_STATUS wlan_objmgr_global_obj_create(void); + +/** + * wlan_objmgr_global_obj_delete() - Deletes global object + * + * Deletes global object + * + * Return: SUCCESS on successful deletion, + * FAILURE on object is not found + * + */ +QDF_STATUS wlan_objmgr_global_obj_delete(void); + +/** + * wlan_objmgr_global_obj_can_deleted() - Checks whether global object + * can be deleted + * + * Checks the psoc table of global object, if psoc table is empty + * returns the SUCCESS + * + * Return: SUCCESS on can be deleted, + * FAILURE on can't be deleted + * + */ +QDF_STATUS wlan_objmgr_global_obj_can_deleted(void); + +/** + * wlan_objmgr_register_psoc_create_handler() - register psoc create handler + * @id: component id + * @handler: function pointer of the component + * @args: args, if component wants certain args to be passed on PSOC creation + * + * API, allows other UMAC components to register handler + * The registered handler would be invoked on PSOC creation + * + * Return: SUCCESS, + * Failure (if registration fails, each failure has different error + * code) + */ +QDF_STATUS wlan_objmgr_register_psoc_create_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_psoc_create_handler handler, + void *args); + +/** + * wlan_objmgr_unregister_psoc_create_handler() - unregister psoc create handler + * @id: component id + * @handler: function pointer of the component + * @args: args, if component wants certain args to be passed on PSOC creation + * + * API, allows other UMAC components to unregister handler + * + * Return: SUCCESS, + * Failure (if handler is not present, each failure has different error + * code) + */ +QDF_STATUS wlan_objmgr_unregister_psoc_create_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_psoc_create_handler handler, + void *args); + +/** + * wlan_objmgr_register_psoc_delete_handler() - register delete handler + * @id: component id + * @handler: function pointer of the component + * @args: args, if component wants certain args to be passed on PSOC deletion + * + * API, allows other UMAC components to register handler + * The registered handler would be invoked on PSOC deletion + * + * Return: SUCCESS, + * Failure (if registration fails, each failure has different error + * code) + */ +QDF_STATUS wlan_objmgr_register_psoc_delete_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_psoc_delete_handler handler, + void *args); + +/** + * wlan_objmgr_unregister_psoc_delete_handler() - unregister delete handler + * @id: component id + * @handler: function pointer of the component + * @args: args, if component wants certain args to be passed on PSOC deletion + * + * API, allows other UMAC components to unregister handler + * + * Return: SUCCESS, + * Failure (if handler is not present, each failure has different error + * code) + */ +QDF_STATUS wlan_objmgr_unregister_psoc_delete_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_psoc_delete_handler handler, + void *args); + +/** + * wlan_objmgr_register_psoc_status_handler() - register status handler + * @id: component id + * @handler: function pointer of the component + * @args: args, if component wants certain args to be passed on PSOC status + * change + * + * API, allows other UMAC components to register handler + * The registered handler would be invoked on PSOC object status change + * + * Return: SUCCESS, + * Failure (if registration fails, each failure has different error + * code) + */ +QDF_STATUS wlan_objmgr_register_psoc_status_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_psoc_status_handler handler, + void *args); + +/** + * wlan_objmgr_unregister_psoc_status_handler() - unregister status handler + * @id: component id + * @handler: function pointer of the component + * @args: args, if component wants certain args to be passed on PSOC status + * + * API, allows other UMAC components to unregister handler + * + * Return: SUCCESS, + * Failure (if handler is not present, each failure has different error + * code) + */ +QDF_STATUS wlan_objmgr_unregister_psoc_status_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_psoc_status_handler handler, + void *args); + +/** + * wlan_objmgr_register_pdev_create_handler() - register pdev create handler + * @id: component id + * @handler: function pointer of the component + * @args: args, if component wants certain args to be passed on PDEV creation + * + * API, allows other UMAC components to register handler + * The registered handler would be invoked on PDEV creation + * + * Return: SUCCESS, + * Failure (if registration fails, each failure has different error + * code) + */ +QDF_STATUS wlan_objmgr_register_pdev_create_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_pdev_create_handler handler, + void *args); + +/** + * wlan_objmgr_unregister_pdev_create_handler() - unregister pdev create handler + * @id: component id + * @handler: function pointer of the component + * @args: args, if component wants certain args to be passed on PDEV creation + * + * API, allows other UMAC components to unregister handler + * + * Return: SUCCESS, + * Failure (if handler is not present, each failure has different error + * code) + */ +QDF_STATUS wlan_objmgr_unregister_pdev_create_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_pdev_create_handler handler, + void *args); + +/** + * wlan_objmgr_register_pdev_delete_handler() - register pdev delete handler + * @id: component id + * @handler: function pointer of the component + * @args: args, if component wants certain args to be passed on PDEV deletion + * + * API, allows other UMAC components to register handler + * The registered handler would be invoked on PDEV deletion + * + * Return: SUCCESS, + * Failure (if registration fails, each failure has different error + * code) + */ +QDF_STATUS wlan_objmgr_register_pdev_delete_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_pdev_delete_handler handler, + void *args); + +/** + * wlan_objmgr_unregister_pdev_delete_handler() - unregister pdev delete handler + * @id: component id + * @handler: function pointer of the component + * @args: args, if component wants certain args to be passed on PDEV deletion + * + * API, allows other UMAC components to unregister handler + * + * Return: SUCCESS, + * Failure (if handler is not present, each failure has different error + * code) + */ +QDF_STATUS wlan_objmgr_unregister_pdev_delete_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_pdev_delete_handler handler, + void *args); + +/** + * wlan_objmgr_register_pdev_status_handler() - register pdev status handler + * @id: component id + * @handler: function pointer of the component + * @args: args, if component wants certain args to be passed on PDEV status + * change + * + * API, allows other UMAC components to register handler + * The registered handler would be invoked on PDEV object status change + * + * Return: SUCCESS, + * Failure (if registration fails, each failure has different error + * code) + */ +QDF_STATUS wlan_objmgr_register_pdev_status_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_pdev_status_handler handler, + void *args); + +/** + * wlan_objmgr_unregister_pdev_status_handler() - unregister pdev status handler + * @id: component id + * @handler: function pointer of the component + * @args: args, if component wants certain args to be passed on PDEV status + * + * API, allows other UMAC components to unregister handler + * + * Return: SUCCESS, + * Failure (if handler is not present, each failure has different error + * code) + */ +QDF_STATUS wlan_objmgr_unregister_pdev_status_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_pdev_status_handler handler, + void *args); + +/** + * wlan_objmgr_register_vdev_create_handler() - register vdev create handler + * @id: component id + * @handler: function pointer of the component + * @args: args, if component wants certain args to be passed on VDEV creation + * + * API, allows other UMAC components to register handler + * The registered handler would be invoked on VDEV creation + * + * Return: SUCCESS, + * Failure (if registration fails, each failure has different error + * code) + */ +QDF_STATUS wlan_objmgr_register_vdev_create_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_vdev_create_handler handler, + void *args); + +/** + * wlan_objmgr_unregister_vdev_create_handler() - unregister vdev create handler + * @id: component id + * @handler: function pointer of the component + * @args: args, if component wants certain args to be passed on VDEV creation + * + * API, allows other UMAC components to unregister handler + * + * Return: SUCCESS, + * Failure (if handler is not present, each failure has different error + * code) + */ +QDF_STATUS wlan_objmgr_unregister_vdev_create_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_vdev_create_handler handler, + void *args); + +/** + * wlan_objmgr_register_vdev_delete_handler() - register vdev delete handler + * @id: component id + * @handler: function pointer of the component + * @args: args, if component wants certain args to be passed on VDEV deletion + * + * API, allows other UMAC components to register handler + * The registered handler would be invoked on VDEV deletion + * + * Return: SUCCESS, + * Failure (if registration fails, each failure has different error + * code) + */ +QDF_STATUS wlan_objmgr_register_vdev_delete_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_vdev_delete_handler handler, + void *args); + +/** + * wlan_objmgr_unregister_vdev_delete_handler() - unregister vdev delete handler + * @id: component id + * @handler: function pointer of the component + * @args: args, if component wants certain args to be passed on VDEV deletion + * + * API, allows other UMAC components to unregister handler + * + * Return: SUCCESS, + * Failure (if handler is not present, each failure has different error + * code) + */ +QDF_STATUS wlan_objmgr_unregister_vdev_delete_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_vdev_delete_handler handler, + void *args); + +/** + * wlan_objmgr_register_vdev_status_handler() - register vdev status handler + * @id: component id + * @handler: function pointer of the component + * @args: args, if component wants certain args to be passed on VDEV status + * change + * + * API, allows other UMAC components to register handler + * The registered handler would be invoked on VDEV object status change + * + * Return: SUCCESS, + * Failure (if registration fails, each failure has different error + * code) + */ +QDF_STATUS wlan_objmgr_register_vdev_status_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_vdev_status_handler handler, + void *args); + +/** + * wlan_objmgr_unregister_vdev_status_handler() - unregister vdev status handler + * @id: component id + * @handler: function pointer of the component + * @args: args, if component wants certain args to be passed on VDEV status + * + * API, allows other UMAC components to unregister handler + * + * Return: SUCCESS, + * Failure (if handler is not present, each failure has different error + * code) + */ +QDF_STATUS wlan_objmgr_unregister_vdev_status_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_vdev_status_handler handler, + void *args); + +/** + * wlan_objmgr_register_peer_create_handler() - register peer create handler + * @id: component id + * @handler: function pointer of the component + * @args: args, if component wants certain args to be passed on PEER creation + * + * API, allows other UMAC components to register handler + * The registered handler would be invoked on PEER creation + * + * Return: SUCCESS, + * Failure (if registration fails, each failure has different error + * code) + */ +QDF_STATUS wlan_objmgr_register_peer_create_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_peer_create_handler handler, + void *args); + +/** + * wlan_objmgr_unregister_peer_create_handler() - unregister peer create handler + * @id: component id + * @handler: function pointer of the component + * @args: args, if component wants certain args to be passed on PEER creation + * + * API, allows other UMAC components to unregister handler + * + * Return: SUCCESS, + * Failure (if handler is not present, each failure has different error + * code) + */ +QDF_STATUS wlan_objmgr_unregister_peer_create_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_peer_create_handler handler, + void *args); + +/** + * wlan_objmgr_register_peer_delete_handler() - register peer delete handler + * @id: component id + * @handler: function pointer of the component + * @args: args, if component wants certain args to be passed on PEER deletion + * + * API, allows other UMAC components to register handler + * The registered handler would be invoked on PEER deletion + * + * Return: SUCCESS, + * Failure (if registration fails, each failure has different error + * code) + */ +QDF_STATUS wlan_objmgr_register_peer_delete_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_peer_delete_handler handler, + void *args); + +/** + * wlan_objmgr_unregister_peer_delete_handler() - unregister peer delete handler + * @id: component id + * @handler: function pointer of the component + * @args: args, if component wants certain args to be passed on PEER deletion + * + * API, allows other UMAC components to unregister handler + * + * Return: SUCCESS, + * Failure (if handler is not present, each failure has different error + * code) + */ +QDF_STATUS wlan_objmgr_unregister_peer_delete_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_peer_delete_handler handler, + void *args); + +/** + * wlan_objmgr_register_peer_status_handler() - register peer status handler + * @id: component id + * @handler: function pointer of the component + * @args: args, if component wants certain args to be passed on PEER status + * change + * + * API, allows other UMAC components to register handler + * The registered handler would be invoked on PEER object status change + * + * Return: SUCCESS, + * Failure (if registration fails, each failure has different error + * code) + */ +QDF_STATUS wlan_objmgr_register_peer_status_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_peer_status_handler handler, + void *args); + +/** + * wlan_objmgr_unregister_peer_status_handler() - unregister peer status handler + * @id: component id + * @handler: function pointer of the component + * @args: args, if component wants certain args to be passed on PEER status + * + * API, allows other UMAC components to unregister handler + * + * Return: SUCCESS, + * Failure (if handler is not present, each failure has different error + * code) + */ +QDF_STATUS wlan_objmgr_unregister_peer_status_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_peer_status_handler handler, + void *args); + +#endif /* _WLAN_OBJMGR_GLOBAL_OBJ_H_*/ diff --git a/umac/cmn_services/obj_mgr/inc/wlan_objmgr_pdev_obj.h b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_pdev_obj.h new file mode 100644 index 0000000000..cb82364f34 --- /dev/null +++ b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_pdev_obj.h @@ -0,0 +1,527 @@ +/* + * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + /** + * DOC: Define the pdev data structure of UMAC + * Public APIs to perform operations on Global objects + */ +#ifndef _WLAN_OBJMGR_PDEV_OBJ_H_ +#define _WLAN_OBJMGR_PDEV_OBJ_H_ +#include + +/* STATUS: scanning */ +#define WLAN_PDEV_F_SCAN 0x00000001 +/* STATUS: use short slot time*/ +#define WLAN_PDEV_F_SHSLOT 0x00000002 + /* STATUS: channel switch event pending after DFS RADAR */ +#define WLAN_PDEV_F_DFS_CHANSWITCH_PENDING 0x00000004 + /* TX Power: fixed rate */ +#define WLAN_PDEV_F_TXPOW_FIXED 0x00000008 + /* STATUS: use short preamble */ +#define WLAN_PDEV_F_SHPREAMBLE 0x00000010 + /* CONF: do alignment pad */ +#define WLAN_PDEV_F_DATAPAD 0x00000020 + /* STATUS: protection enabled */ +#define WLAN_PDEV_F_USEPROT 0x00000040 + /* STATUS: use barker preamble*/ +#define WLAN_PDEV_F_USEBARKER 0x00000080 + /* CONF: DISABLE 2040 coexistance */ +#define WLAN_PDEV_F_COEXT_DISABLE 0x00000100 + /* STATE: scan pending */ +#define WLAN_PDEV_F_SCAN_PENDING 0x00000200 + /* CONF: send regclassids in country ie */ +#define WLAN_PDEV_F_REGCLASS 0x00000400 + /* CONF: block the use of DFS channels */ +#define WLAN_PDEV_F_BLKDFSCHAN 0x00000800 + /* STATUS: 11D in used */ +#define WLAN_PDEV_F_DOT11D 0x00001000 + /* STATUS: 11D channel-switch detected */ +#define WLAN_PDEV_F_RADAR 0x00002000 + /* CONF: A-MPDU supported */ +#define WLAN_PDEV_F_AMPDU 0x00004000 + /* CONF: A-MSDU supported */ +#define WLAN_PDEV_F_AMSDU 0x00008000 + /* CONF: HT traffic protected */ +#define WLAN_PDEV_F_HTPROT 0x00010000 + /* CONF: Reset once */ +#define WLAN_PDEV_F_RESET 0x00020000 + /* CONF: ignore 11d beacon */ +#define WLAN_PDEV_F_IGNORE_11D_BEACON 0x00040000 + /* HT CAP IE present */ +#define WLAN_PDEV_F_HTVIE 0x00080000 + /* radio in middle of CSA */ +#define WLAN_PDEV_F_CSA_WAIT 0x00100000 + /* wnm support flag */ +#define WLAN_PDEV_F_WNM 0x00200000 +#define WLAN_PDEV_F_2G_CSA 0x00400000 + /* enhanced independent repeater */ +#define WLAN_PDEV_F_ENH_REP_IND 0x00800000 + /* Disable Tx AMSDU for station vap */ +#define WLAN_PDEV_F_STA_AMPDU_DIS 0x01000000 +/* do not send probe request in passive channel */ +#define WLAN_PDEV_F_STRICT_PSCAN_EN 0x02000000 + /* dupie (ANA,pre ANA ) */ +/*#define WLAN_PDEV_F_DUPIE 0x00200000*/ + +/* PDEV op flags */ + /* Enable htrate for wep and tkip */ +#define WLAN_PDEV_OP_WEP_TKIP_HTRATE 0x00000001 + /* non HT AP found flag */ +#define WLAN_PDEV_OP_NON_HT_AP 0x00000002 + /* block the use of DFS channels flag */ +#define WLAN_PDEV_OP_BLK_DFS_CHAN 0x00000004 + /* 11.h flag */ +#define WLAN_PDEV_OP_DOTH 0x00000008 + /* Off-channel support enabled */ +#define WLAN_PDEV_OP_OFFCHAN 0x00000010 +#define WLAN_PDEV_OP_HT20ADHOC 0x00000020 +#define WLAN_PDEV_OP_HT40ADHOC 0x00000040 +#define WLAN_PDEV_OP_HTADHOC_AGGR 0x00000080 + /* disallow CC change when assoc completes */ +#define WLAN_PDEV_OP_DISALLOW_AUTO_CC 0x00000100 + /* Is P2P Enabled? */ +#define WLAN_PDEV_OP_P2P 0x00000200 + /* disallowed */ +#define WLAN_PDEV_OP_IGNORE_DYNHALT 0x00000400 + /* overwrite probe response IE with beacon IE */ +#define WLAN_PDEV_OP_OVERRIDE_PROBERESP 0x00000800 +#define WLAN_PDEV_OP_DROPSTA_QUERY 0x00001000 +#define WLAN_PDEV_OP_BLK_REPORT_FLOOD 0x00002000 + /* Offchan scan */ +#define WLAN_PDEV_OP_OFFCHAN_SCAN 0x00004000 + /*Consider OBSS non-erp to change to long slot*/ +#define WLAN_PDEV_OP_OBSS_LONGSLOT 0x00008000 + /* enable/disable min rssi cli block */ +#define WLAN_PDEV_OP_MIN_RSSI_ENABLE 0x00010000 + +/** + * struct wlan_objmgr_pdev_nif - pdev object nif structure + * @pdev_fw_caps: radio specific FW capabilities + * @pdev_feature_caps: radio specific feature capabilities + * @pdev_ospriv: OS specific pointer + * @notified_ap_vdev: ap vdev + */ +struct wlan_objmgr_pdev_nif { + uint32_t pdev_fw_caps; + uint32_t pdev_feature_caps; + void *pdev_ospriv; + uint8_t notified_ap_vdev; +}; + +/** + * struct wlan_objmgr_pdev_mlme - pdev object mlme structure + * @pdev_op_flags: PDEV operation flags, can be used to know the + * operation status (deletion progress, etc) + */ +struct wlan_objmgr_pdev_mlme { + uint32_t pdev_op_flags; +}; + +/** + * struct wlan_objmgr_pdev_objmgr - pdev object object manager structure + * @wlan_pdev_id: PDEV id + * @wlan_vdev_list: List maintains the VDEVs created on this PDEV + * @wlan_vdev_count: VDEVs count + * @max_vdev_count: Max no. of VDEVs supported by this PDEV + * @wlan_psoc: back pointer to PSOC, its attached to + */ +struct wlan_objmgr_pdev_objmgr { + uint8_t wlan_pdev_id; + qdf_list_t wlan_vdev_list; + uint8_t wlan_vdev_count; + uint8_t max_vdev_count; + struct wlan_objmgr_psoc *wlan_psoc; +}; + +/** + * struct wlan_objmgr_pdev - PDEV common object + * @current_chan_list: Active/current Channel list of the radio + * @pdev_nif: pdev nif structure + * @pdev_objmgr: pdev object manager structure + * @pdev_mlme: pdev MLME structure + * @pdev_comp_obj[]: component objects array + * @obj_status[]: object status of each component object + * @obj_state: object state + * @pdev_lock: lock to protect object +*/ +struct wlan_objmgr_pdev { + struct wlan_chan_list *current_chan_list; + struct wlan_objmgr_pdev_nif pdev_nif; + struct wlan_objmgr_pdev_objmgr pdev_objmgr; + struct wlan_objmgr_pdev_mlme pdev_mlme; + void *pdev_comp_obj[WLAN_UMAC_MAX_COMPONENTS]; + QDF_STATUS obj_status[WLAN_UMAC_MAX_COMPONENTS]; + WLAN_OBJ_STATE obj_state; + qdf_spinlock_t pdev_lock; +}; + + +/** + ** APIs to Create/Delete Global object APIs + */ +/** + * wlan_objmgr_pdev_obj_create() - pdev create + * @psoc: PSOC object + * @scn: os private object + * + * Creates PDEV object, intializes with default values + * Invokes the registered notifiers to create component object + * + * Return: Handle to struct wlan_objmgr_psoc on successful creation, + * NULL on Failure (on Mem alloc failure and Component objects + * Failure) + */ +struct wlan_objmgr_pdev *wlan_objmgr_pdev_obj_create( + struct wlan_objmgr_psoc *psoc, void *scn); + +/** + * wlan_objmgr_pdev_obj_delete() - pdev delete + * @psoc: PDEV object + * + * Deletes PDEV object, + * Invokes the registered notifiers to delete component objects + * + * Return: SUCCESS/FAILURE + */ +QDF_STATUS wlan_objmgr_pdev_obj_delete(struct wlan_objmgr_pdev *pdev); + +/** + ** APIs to attach/detach component objects + */ +/** + * wlan_objmgr_pdev_component_obj_attach() - pdev comp object attach + * @psoc: PDEV object + * @id: Component id + * @comp_objptr: component's private object pointer + * @status: Component's private object creation status + * + * API to be used for attaching component object with PDEV common object + * + * Return: SUCCESS on successful storing of component's object in common object + * On FAILURE (appropriate failure codes are returned) + */ +QDF_STATUS wlan_objmgr_pdev_component_obj_attach( + struct wlan_objmgr_pdev *pdev, + enum wlan_umac_comp_id id, + void *comp_objptr, + QDF_STATUS status); + +/** + * wlan_objmgr_pdev_component_obj_detach() - pdev comp object detach + * @psoc: PDEV object + * @id: Component id + * @comp_objptr: component's private object pointer + * + * API to be used for detaching component object with PDEV common object + * + * Return: SUCCESS on successful removal of component's object from common + * object + * On FAILURE (appropriate failure codes are returned) + */ +QDF_STATUS wlan_objmgr_pdev_component_obj_detach( + struct wlan_objmgr_pdev *pdev, + enum wlan_umac_comp_id id, + void *comp_objptr); + +/** + ** APIs to operations on pdev objects + */ + +/** + * wlan_objmgr_pdev_iterate_obj_list() - operate on all objects of pdev + * @pdev: PDEV object + * @obj_type: VDEV_OP/PEER_OP + * @handler: the handler will be called for each object of requested type + * the handler should be implemented to perform required operation + * @arg: agruments passed by caller + * @lock_free_op: This gives provision to run this API with out lock protected + * It would be useful, for operations like Obj Delete, where + * lock should not be taken by caller. + * + * API to be used for performing the operations on all VDEV/PEER objects + * of pdev + * + * Return: SUCCESS/FAILURE + */ + +typedef void (*wlan_objmgr_pdev_op_handler)(struct wlan_objmgr_pdev *pdev, + void *object, + void *arg); + +QDF_STATUS wlan_objmgr_pdev_iterate_obj_list( + struct wlan_objmgr_pdev *pdev, + enum wlan_objmgr_obj_type obj_type, + wlan_objmgr_pdev_op_handler handler, + void *arg, uint8_t lock_free_op); + +/** + * wlan_objmgr_trigger_pdev_comp_object_creation() - create comp object of pdev + * @pdev: PDEV object + * @id: Component id + * + * API to create component object in run time, this would be used for features + * which gets enabled in run time + * + * Return: SUCCESS on successful creation + * On FAILURE (appropriate failure codes are returned) + */ +QDF_STATUS wlan_objmgr_trigger_pdev_comp_object_creation( + struct wlan_objmgr_pdev *pdev, + enum wlan_umac_comp_id id); + +/** + * wlan_objmgr_trigger_pdev_comp_object_deletion() - delete comp object of pdev + * @pdev: PDEV object + * @id: Component id + * + * API to delete component object in run time, this would be used for features + * which gets disabled in run time + * + * Return: SUCCESS on successful deletion + * On FAILURE (appropriate failure codes are returned) + */ +QDF_STATUS wlan_objmgr_trigger_pdev_comp_object_deletion( + struct wlan_objmgr_pdev *pdev, + enum wlan_umac_comp_id id); + +/** + * wlan_objmgr_find_vdev_by_id_from_pdev() - find vdev using id from pdev + * @pdev: PDEV object + * @vdev_id: vdev id + * + * API to find vdev object pointer by vdev id from pdev's vdev list + * + * Return: vdev pointer + * NULL on FAILURE + */ +struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_id_from_pdev( + struct wlan_objmgr_pdev *pdev, uint8_t vdev_id); + +/** + * wlan_objmgr_find_vdev_by_macaddr_from_pdev() - find vdev using macaddr + * @pdev: PDEV object + * @macaddr: MAC address + * + * API to find vdev object pointer by vdev mac addr from pdev's vdev list + * + * Return: vdev pointer + * NULL on FAILURE + */ +struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_macaddr_from_pdev( + struct wlan_objmgr_pdev *pdev, uint8_t *macaddr); + +/** + * wlan_pdev_obj_lock() - Acquire PDEV spinlock + * @pdev: PDEV object + * + * API to acquire PDEV lock + * + * Return: void + */ +static inline void wlan_pdev_obj_lock(struct wlan_objmgr_pdev *pdev) +{ + qdf_spin_lock_bh(&pdev->pdev_lock); +} + +/** + * wlan_pdev_obj_unlock() - Release PDEV spinlock + * @pdev: PDEV object + * + * API to Release PDEV lock + * + * Return: void + */ +static inline void wlan_pdev_obj_unlock(struct wlan_objmgr_pdev *pdev) +{ + qdf_spin_unlock_bh(&pdev->pdev_lock); +} + +/** + * wlan_pdev_get_psoc() - get psoc + * @pdev: PDEV object + * + * API to get the psoc object from PDEV + * + * Caller need to acquire lock with wlan_pdev_obj_lock() + * + * Return: + * @psoc: PSOC object + */ +static inline struct wlan_objmgr_psoc *wlan_pdev_get_psoc( + struct wlan_objmgr_pdev *pdev) +{ + return pdev->pdev_objmgr.wlan_psoc; +} + +/** + * wlan_pdev_set_psoc() - set psoc + * @pdev: PDEV object + * @psoc: PSOC object + * + * API to set the psoc object from PDEV + * + * Caller need to acquire lock with wlan_pdev_obj_lock() + * + * Return: void + */ +static inline void wlan_pdev_set_psoc(struct wlan_objmgr_pdev *pdev, + struct wlan_objmgr_psoc *psoc) +{ + pdev->pdev_objmgr.wlan_psoc = psoc; +} + +/** + * wlan_pdev_nif_fw_cap_set() - set fw caps + * @pdev: PDEV object + * @cap: capability flag to be set + * + * API to set fw caps in pdev + * + * Caller need to acquire lock with wlan_pdev_obj_lock() + * + * Return: void + */ +static inline void wlan_pdev_nif_fw_cap_set(struct wlan_objmgr_pdev *pdev, + uint32_t cap) +{ + pdev->pdev_nif.pdev_fw_caps |= cap; +} + +/** + * wlan_pdev_nif_fw_cap_clear() - clear fw cap + * @pdev: PDEV object + * @cap: capability flag to be cleared + * + * API to clear fw caps in pdev + * + * Caller need to acquire lock with wlan_pdev_obj_lock() + * + * Return: void + */ +static inline void wlan_pdev_nif_fw_cap_clear(struct wlan_objmgr_pdev *pdev, + uint32_t cap) +{ + pdev->pdev_nif.pdev_fw_caps &= ~cap; +} + +/** + * wlan_pdev_nif_fw_cap_get() - get fw caps + * @pdev: PDEV object + * @cap: capability flag to be checked + * + * API to know, whether particular fw caps flag is set in pdev + * + * Caller need to acquire lock with wlan_pdev_obj_lock() + * + * Return: 1 (for set) or 0 (for not set) + */ +static inline uint8_t wlan_pdev_nif_fw_cap_get(struct wlan_objmgr_pdev *pdev, + uint32_t cap) +{ + return (pdev->pdev_nif.pdev_fw_caps & cap) ? 1 : 0; +} + +/** + * wlan_pdev_nif_feat_cap_set() - set feature caps + * @pdev: PDEV object + * @cap: capability flag to be set + * + * API to set feat caps in pdev + * + * Caller need to acquire lock with wlan_pdev_obj_lock() + * + * Return: void + */ +static inline void wlan_pdev_nif_feat_cap_set(struct wlan_objmgr_pdev *pdev, + uint32_t cap) +{ + pdev->pdev_nif.pdev_feature_caps |= cap; +} + +/** + * wlan_pdev_nif_feat_cap_clear() - clear feature caps + * @pdev: PDEV object + * @cap: capability flag to be cleared + * + * API to clear feat caps in pdev + * + * Caller need to acquire lock with wlan_pdev_obj_lock() + * + * Return: void + */ +static inline void wlan_pdev_nif_feat_cap_clear(struct wlan_objmgr_pdev *pdev, + uint32_t cap) +{ + pdev->pdev_nif.pdev_feature_caps &= ~cap; +} + +/** + * wlan_pdev_nif_feat_cap_get() - get feature caps + * @pdev: PDEV object + * @cap: capability flag to be checked + * + * API to know, whether particular feat caps flag is set in pdev + * + * Caller need to acquire lock with wlan_pdev_obj_lock() + * + * Return: 1 (for set) or 0 (for not set) + */ +static inline uint8_t wlan_pdev_nif_feat_cap_get(struct wlan_objmgr_pdev *pdev, + uint32_t cap) +{ + return (pdev->pdev_nif.pdev_feature_caps & cap) ? 1 : 0; +} + +/** + * wlan_pdev_get_hw_macaddr() - get hw macaddr + * @pdev: PDEV object + * + * API to get HW MAC address form PDEV + * + * Caller need to acquire lock with wlan_pdev_obj_lock() + * + * Return: @macaddr -MAC address + */ +static inline uint8_t *wlan_pdev_get_hw_macaddr(struct wlan_objmgr_pdev *pdev) +{ + struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); + + return wlan_psoc_get_hw_macaddr(psoc); +} + +/** + * wlan_pdev_set_hw_macaddr() - set hw macaddr + * @pdev: PDEV object + * @macaddr: MAC address + * + * API to set HW MAC address form PDEV + * + * Caller need to acquire lock with wlan_pdev_obj_lock() + * + * Return: void + */ +static inline void wlan_pdev_set_hw_macaddr(struct wlan_objmgr_pdev *pdev, + uint8_t *macaddr) +{ + struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev); + + if (psoc != NULL) + wlan_psoc_set_hw_macaddr(psoc, macaddr); +} + + +#endif /* _WLAN_OBJMGR_PDEV_H_*/ diff --git a/umac/cmn_services/obj_mgr/inc/wlan_objmgr_peer_obj.h b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_peer_obj.h new file mode 100644 index 0000000000..e66a2b57f5 --- /dev/null +++ b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_peer_obj.h @@ -0,0 +1,648 @@ +/* + * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + /** + * DOC: Define the peer data structure of UMAC + * Public APIs to perform operations on Global objects + */ +#ifndef _WLAN_OBJMGR_PEER_OBJ_H_ +#define _WLAN_OBJMGR_PEER_OBJ_H_ +#include +#include + +/* peer flags */ +/* authorized for data */ +#define WLAN_PEER_F_AUTH 0x00000001 +/* QoS enabled */ +#define WLAN_PEER_F_QOS 0x00000002 +/* ERP enabled */ +#define WLAN_PEER_F_ERP 0x00000004 +/* HT enabled */ +#define WLAN_PEER_F_HT 0x00000008 +/* NB: tWLANhave the same value as IEEE80211_FC1_PWR_MGT */ +/* power save mode enabled */ +#define WLAN_PEER_F_PWR_MGT 0x00000010 +/* keytsc for node has already been updated */ +#define WLAN_PEER_F_TSC_SET 0x00000020 +/* U-APSD power save enabled */ +#define WLAN_PEER_F_UAPSD 0x00000040 +/* U-APSD triggerable state */ +#define WLAN_PEER_F_UAPSD_TRIG 0x00000080 +/* U-APSD SP in progress */ +#define WLAN_PEER_F_UAPSD_SP 0x00000100 +/* Atheros Owl or follow-on device */ +#define WLAN_PEER_F_ATH 0x00000200 +/* Owl WDS workaround needed*/ +#define WLAN_PEER_F_OWL_WDSWAR 0x00000400 +/* WDS link */ +#define WLAN_PEER_F_WDS 0x00000800 +/* No AMPDU support */ +#define WLAN_PEER_F_NOAMPDU 0x00001000 +/* Atheros proprietary wep/tkip aggregation support */ +#define WLAN_PEER_F_WEPTKIPAGGR 0x00002000 +#define WLAN_PEER_F_WEPTKIP 0x00004000 +/* temp node (not in the node table) */ +#define WLAN_PEER_F_TEMP 0x00008000 +/* 2.4ng VHT interop AMSDU disabled */ +#define WLAN_PEER_F_11NG_VHT_INTEROP_AMSDU_DISABLE 0x00010000 +/* HT40 Intolerant */ +#define WLAN_PEER_F_40_INTOLERANT 0x00020000 +/* node is paused*/ +#define WLAN_PEER_F_PAUSED 0x00040000 +#define WLAN_PEER_F_EXTRADELIMWAR 0x00080000 +/* HT20 requesting node */ +#define WLAN_PEER_F_REQ_HT20 0x00100000 +/* all the tid queues in ath layer are paused*/ +#define WLAN_PEER_F_ATH_PAUSED 0x00200000 +/*Require credit update*/ +#define WLAN_PEER_F_UAPSD_CREDIT_UPDATE 0x00400000 +/*Require send deauth when h/w queue no data*/ +#define WLAN_PEER_F_KICK_OUT_DEAUTH 0x00800000 +/* RRM enabled node */ +#define WLAN_PEER_F_RRM 0x01000000 +/* Wakeup node */ +#define WLAN_PEER_F_WAKEUP 0x02000000 +/* VHT enabled node */ +#define WLAN_PEER_F_VHT 0x04000000 +/* deauth/Disassoc wait for node cleanup till frame goes on + air and tx feedback received */ +#define WLAN_PEER_F_DELAYED_CLEANUP 0x08000000 +/* Extended stats enabled node */ +#define WLAN_PEER_F_EXT_STATS 0x10000000 +/* Prevent _ieee80211_node_leave() from reentry */ +#define WLAN_PEER_F_LEAVE_ONGOING 0x20000000 +/* band steering is enabled for this node */ +#define WLAN_PEER_F_BSTEERING_CAPABLE 0x40000000 +/* node is a local mesh peer */ +#define WLAN_PEER_F_LOCAL_MESH_PEER 0x80000000 + +/** + * enum wlan_peer_state - peer state + * @WLAN_INIT_STATE: Default state + * @WLAN_JOIN_STATE: Station mode, STA is waiting for Join + * @WLAN_AUTH_STATE: AUTH in progress + * @WLAN_ASSOC_STATE: ASSOC in progress + * @WLAN_WAITKEY_STATE: 4-way KEY handshake is in progress + * @WLAN_CONNECTED_STATE: Connected state + * @WLAN_PREAUTH_STATE: Station mode: Preauth + * @WLAN_DISCONNECT_STATE: Disconnect is in progress + */ +enum wlan_peer_state { + WLAN_INIT_STATE = 1, + WLAN_JOIN_STATE = 2, + WLAN_AUTH_STATE = 3, + WLAN_ASSOC_STATE = 4, + WLAN_WAITKEY_STATE = 5, + WLAN_CONNECTED_STATE = 6, + WLAN_PREAUTH_STATE = 7, + WLAN_DISCONNECT_STATE = 8, +}; + +/** + * struct wlan_objmgr_peer_mlme - mlme common data of peer + * @peer_capinfo: protocol cap info + * @peer_flags: PEER OP flags + * @peer_type: Type of PEER, (STA/AP/etc.) + * @phymode: phy mode of station + * @rssi: Last received RSSI value + * @max_rate: Max Rate supported + * @state: State of the peer + */ +struct wlan_objmgr_peer_mlme { + uint32_t peer_capinfo; + uint32_t peer_flags; + enum wlan_peer_type peer_type; + enum wlan_phymode phymode; + int8_t rssi; + uint32_t max_rate; + enum wlan_peer_state state; +}; + +/** + * struct wlan_objmgr_peer_objmgr - object manager data of peer + * @vdev: VDEV pointer to which it is associated + * @ref_cnt: Ref count + */ +struct wlan_objmgr_peer_objmgr { + struct wlan_objmgr_vdev *vdev; + qdf_atomic_t ref_cnt; +}; + +/** + * struct wlan_peer_activity -- peer inactivity info + * + */ +struct wlan_peer_activity { /*TODO */ + +}; + +/** + * struct wlan_objmgr_peer - PEER common object + * @psoc_peer: peer list node for psoc's qdf list + * @vdev_peer: peer list node for vdev's qdf list + * @macaddr[]: Peer MAC address + * @peer_mlme: Peer MLME common structure + * @peer_activity: peer activity + * @peer_objmgr: Peer Object manager common structure + * @peer_comp_obj[]: Component object pointers + * @obj_status[]: status of each component object + * @obj_state: Status of Peer object + * @peer_lock: Lock for access/update peer contents + */ +struct wlan_objmgr_peer { + qdf_list_node_t psoc_peer; + qdf_list_node_t vdev_peer; + uint8_t macaddr[WLAN_MACADDR_LEN]; + struct wlan_objmgr_peer_mlme peer_mlme; + struct wlan_peer_activity peer_activity; + struct wlan_objmgr_peer_objmgr peer_objmgr; + void *peer_comp_obj[WLAN_UMAC_MAX_COMPONENTS]; + QDF_STATUS obj_status[WLAN_UMAC_MAX_COMPONENTS]; + WLAN_OBJ_STATE obj_state; + qdf_spinlock_t peer_lock; +}; + +/** + ** APIs to Create/Delete Global object APIs + */ +/** + * wlan_objmgr_peer_obj_create() - peer object create + * @vdev: VDEV object on which this peer gets created + * @peer_type: peer type (AP/STA) + * @macaddr: MAC address + * + * Creates Peer object, intializes with default values + * Attaches to psoc and vdev objects + * Invokes the registered notifiers to create component object + * + * Return: Handle to struct wlan_objmgr_peer on successful creation, + * NULL on Failure (on Mem alloc failure and Component objects + * Failure) + */ +struct wlan_objmgr_peer *wlan_objmgr_peer_obj_create( + struct wlan_objmgr_vdev *vdev, + enum wlan_peer_type type, + uint8_t macaddr[]); + +/** + * wlan_objmgr_peer_obj_delete() - peer object delete + * @peer: PEER object + * + * Deletes PEER object, removes it from PSOC's, VDEV's peer list + * Invokes the registered notifiers to delete component objects + * + * Return: SUCCESS/FAILURE + */ +QDF_STATUS wlan_objmgr_peer_obj_delete(struct wlan_objmgr_peer *peer); + +/** + ** APIs to attach/detach component objects + */ +/** + * wlan_objmgr_peer_component_obj_attach() - attach comp object to peer + * @peer: PEER object + * @id: Component id + * @comp_objptr: component's private object pointer + * @status: Component's private object creation status + * + * API to be used for attaching component object with PEER common object + * + * Return: SUCCESS on successful storing of component's object in common object + * On FAILURE (appropriate failure codes are returned) + */ +QDF_STATUS wlan_objmgr_peer_component_obj_attach( + struct wlan_objmgr_peer *peer, + enum wlan_umac_comp_id id, + void *comp_objptr, + QDF_STATUS status); + +/** + * wlan_objmgr_peer_component_obj_detach() - detach comp object from peer + * @peer: PEER object + * @id: Component id + * @comp_objptr: component's private object pointer + * + * API to be used for detaching component object with PEER common object + * + * Return: SUCCESS on successful removal of component's object from common + * object + * On FAILURE (appropriate failure codes are returned) + */ +QDF_STATUS wlan_objmgr_peer_component_obj_detach( + struct wlan_objmgr_peer *peer, + enum wlan_umac_comp_id id, + void *comp_objptr); + +/** + ** APIs to operations on peer objects + */ + +/** + * wlan_objmgr_trigger_peer_comp_object_creation() - create peer comp object + * @peer: PEER object + * @id: Component id + * + * API to create component object in run time, this would be used for features + * which gets enabled in run time + * + * Return: SUCCESS on successful creation + * On FAILURE (appropriate failure codes are returned) + */ +QDF_STATUS wlan_objmgr_trigger_peer_comp_object_creation( + struct wlan_objmgr_peer *peer, + enum wlan_umac_comp_id id); + +/** + * wlan_objmgr_trigger_peer_comp_object_deletion() - delete peer comp object + * @peer: PEER object + * @id: Component id + * + * API to delete component object in run time, this would be used for features + * which gets disabled in run time + * + * Return: SUCCESS on successful deletion + * On FAILURE (appropriate failure codes are returned) + */ +QDF_STATUS wlan_objmgr_trigger_peer_comp_object_deletion( + struct wlan_objmgr_peer *peer, + enum wlan_umac_comp_id id); + +/** + * wlan_peer_obj_lock() - Acquire PEER spinlock + * @psoc: PEER object + * + * API to acquire PEER spin lock + * + * Return: void + */ +static inline void wlan_peer_obj_lock(struct wlan_objmgr_peer *peer) +{ + qdf_spin_lock_bh(&peer->peer_lock); +} + +/** + * wlan_peer_obj_unlock() - Release PEER spinlock + * @peer: PEER object + * + * API to Release PEER spin lock + * + * Return: void + */ +static inline void wlan_peer_obj_unlock(struct wlan_objmgr_peer *peer) +{ + qdf_spin_unlock_bh(&peer->peer_lock); +} +/** + * wlan_objmgr_peer_ref_peer() - increment ref count + * @peer: PEER object + * + * API to increment ref count of peer + * + * Return: void + */ +static inline void wlan_objmgr_peer_ref_peer(struct wlan_objmgr_peer *peer) +{ + if (peer == NULL) { + qdf_print("%s: peer obj is NULL\n", __func__); + return; + } + /* Increment ref count */ + qdf_atomic_inc(&peer->peer_objmgr.ref_cnt); + return; +} + +/** + * wlan_objmgr_peer_unref_peer() - decrement ref count + * @peer: PEER object + * + * API to decrement ref count of peer, if ref count is 1, it initiates the + * peer deletion + * + * Return: void + */ +static inline void wlan_objmgr_peer_unref_peer(struct wlan_objmgr_peer *peer) +{ + if (peer == NULL) { + qdf_print("%s: peer obj is NULL\n", __func__); + return; + } + /* Decrement ref count, free peer, if count becomes 0 */ + if (qdf_atomic_dec_and_test(&peer->peer_objmgr.ref_cnt)) + wlan_objmgr_peer_obj_delete(peer); + return; +} + +/** + * wlan_psoc_peer_list_peek_head() - get head of psoc peer list + * @peer_list: qdf_list_t + * + * API to get the head peer of given peer (of psoc's peer list) + * + * Caller need to acquire lock with wlan_peer_obj_lock() + * + * Return: + * @peer: head peer + */ +static inline struct wlan_objmgr_peer *wlan_psoc_peer_list_peek_head( + qdf_list_t *peer_list) +{ + struct wlan_objmgr_peer *peer; + qdf_list_node_t *psoc_node = NULL; + + if (qdf_list_peek_front(peer_list, &psoc_node) != QDF_STATUS_SUCCESS) + return NULL; + + peer = qdf_container_of(psoc_node, struct wlan_objmgr_peer, psoc_peer); + return peer; +} + +/** + * wlan_vdev_peer_list_peek_head() - get head of vdev peer list + * @peer_list: qdf_list_t + * + * API to get the head peer of given peer (of vdev's peer list) + * + * Caller need to acquire lock with wlan_peer_obj_lock() + * + * Return: + * @peer: head peer + */ +static inline struct wlan_objmgr_peer *wlan_vdev_peer_list_peek_head( + qdf_list_t *peer_list) +{ + struct wlan_objmgr_peer *peer; + qdf_list_node_t *vdev_node = NULL; + + if (qdf_list_peek_front(peer_list, &vdev_node) != QDF_STATUS_SUCCESS) + return NULL; + + peer = qdf_container_of(vdev_node, struct wlan_objmgr_peer, vdev_peer); + return peer; +} + +/** + * wlan_peer_get_next_peer_of_vdev() - get next peer of vdev list + * @peer: PEER object + * + * API to get the next peer of given peer (of vdev's peer list) + * + * Caller need to acquire lock with wlan_peer_obj_lock() + * + * Return: + * @next_peer: PEER object + */ +static inline struct wlan_objmgr_peer *wlan_peer_get_next_peer_of_vdev( + qdf_list_t *peer_list, struct wlan_objmgr_peer *peer) +{ + struct wlan_objmgr_peer *peer_next; + qdf_list_node_t *node; + qdf_list_node_t *next_node = NULL; + + if (peer == NULL) + return NULL; + + node = &peer->vdev_peer; + if (qdf_list_peek_next(peer_list, node, &next_node) != + QDF_STATUS_SUCCESS) + return NULL; + + peer_next = qdf_container_of(next_node, struct wlan_objmgr_peer, + vdev_peer); + return peer_next; +} + +/** + * wlan_peer_set_next_peer_of_vdev() - add peer to vdev peer list + * @peer: PEER object + * @new_peer: PEER object + * + * API to set as the next peer to given peer (of vdev's peer list) + * + * Caller need to acquire lock with wlan_peer_obj_lock() + * + * Return: void + */ +static inline void wlan_peer_set_next_peer_of_vdev(qdf_list_t *peer_list, + struct wlan_objmgr_peer *new_peer) +{ + /* set next peer with new peer */ + qdf_list_insert_back(peer_list, &new_peer->vdev_peer); + return; +} + +/** + * wlan_peer_get_next_peer_of_psoc() - get next peer to psoc peer list + * @peer: PEER object + * + * API to get the next peer of given peer (of psoc's peer list) + * + * Caller need to acquire lock with wlan_peer_obj_lock() + * + * Return: + * @next_peer: PEER object + */ +static inline struct wlan_objmgr_peer *wlan_peer_get_next_peer_of_psoc( + qdf_list_t *peer_list, struct wlan_objmgr_peer *peer) +{ + struct wlan_objmgr_peer *peer_next; + qdf_list_node_t *node = NULL; + qdf_list_node_t *next_node = NULL; + + if (peer == NULL) + return NULL; + + node = &peer->psoc_peer; + if (qdf_list_peek_next(peer_list, node, &next_node) != + QDF_STATUS_SUCCESS) + return NULL; + + peer_next = qdf_container_of(next_node, struct wlan_objmgr_peer, + psoc_peer); + return peer_next; +} + +/** + * wlan_peer_set_next_peer_of_psoc() - add peer to psoc peer list + * @peer: PEER object + * @new_peer: PEER object + * + * API to set as the next peer to given peer (of psoc's peer list) + * + * Caller need to acquire lock with wlan_peer_obj_lock() + * + * Return: void + */ +static inline void wlan_peer_set_next_peer_of_psoc(qdf_list_t *peer_list, + struct wlan_objmgr_peer *new_peer) +{ + /* set next peer with new peer */ + qdf_list_insert_back(peer_list, &new_peer->psoc_peer); + return; +} + +/** + * wlan_peer_set_peer_type() - set peer type + * @peer: PEER object + * @peer_type: type of PEER + * + * API to set peer type + * + * Caller need to acquire lock with wlan_peer_obj_lock() + * + * Return: void + */ +static inline void wlan_peer_set_peer_type(struct wlan_objmgr_peer *peer, + enum wlan_peer_type type) +{ + peer->peer_mlme.peer_type = type; +} + +/** + * wlan_peer_get_peer_type() - get peer type + * @peer: PEER object + * + * API to get peer type + * + * Caller need to acquire lock with wlan_peer_obj_lock() + * + * Return: + * @peer_type: type of PEER + */ +static inline enum wlan_peer_type wlan_peer_get_peer_type( + struct wlan_objmgr_peer *peer) +{ + return peer->peer_mlme.peer_type; +} + +/** + * wlan_peer_set_macaddr() - set mac addr + * @peer: PEER object + * @macaddr: MAC address + * + * API to set peer mac address + * + * Caller need to acquire lock with wlan_peer_obj_lock() + * + * Return: void + */ +static inline void wlan_peer_set_macaddr(struct wlan_objmgr_peer *peer, + uint8_t *macaddr) +{ + WLAN_ADDR_COPY(peer->macaddr, macaddr); +} + +/** + * wlan_peer_get_macaddr() - get mac addr + * @peer: PEER object + * + * API to get peer mac address + * + * Caller need to acquire lock with wlan_peer_obj_lock() + * + * Return: + * @macaddr: MAC address + */ +static inline uint8_t *wlan_peer_get_macaddr(struct wlan_objmgr_peer *peer) +{ + return peer->macaddr; +} + +/** + * wlan_peer_get_vdev() - get vdev + * @peer: PEER object + * + * API to get peer's vdev + * + * Caller need to acquire lock with wlan_peer_obj_lock() + * + * Return: + * @vdev: VDEV object + */ +static inline struct wlan_objmgr_vdev *wlan_peer_get_vdev( + struct wlan_objmgr_peer *peer) +{ + return peer->peer_objmgr.vdev; +} + +/** + * wlan_peer_set_vdev() - set vdev + * @peer: PEER object + * @vdev: VDEV object + * + * API to set peer's vdev + * + * Caller need to acquire lock with wlan_peer_obj_lock() + * + * Return: void + */ +static inline void wlan_peer_set_vdev(struct wlan_objmgr_peer *peer, + struct wlan_objmgr_vdev *vdev) +{ + peer->peer_objmgr.vdev = vdev; +} + +/** + * wlan_peer_mlme_flag_set() - mlme flag set + * @peer: PEER object + * @flag: flag to be set + * + * API to set flag in peer + * + * Caller need to acquire lock with wlan_peer_obj_lock() + * + * Return: void + */ +static inline void wlan_peer_mlme_flag_set(struct wlan_objmgr_peer *peer, + uint32_t flag) +{ + peer->peer_mlme.peer_flags |= flag; +} + +/** + * wlan_peer_mlme_flag_clear() - mlme flag clear + * @peer: PEER object + * @flag: flag to be cleared + * + * API to clear flag in peer + * + * Caller need to acquire lock with wlan_peer_obj_lock() + * + * Return: void + */ +static inline void wlan_peer_mlme_flag_clear(struct wlan_objmgr_peer *peer, + uint32_t flag) +{ + peer->peer_mlme.peer_flags &= ~flag; +} + +/** + * wlan_peer_mlme_flag_get() - mlme flag get + * @peer: PEER object + * @flag: flag to be checked + * + * API to know, whether particular flag is set in peer + * + * Caller need to acquire lock with wlan_peer_obj_lock() + * + * Return: 1 (for set) or 0 (for not set) + */ +static inline uint8_t wlan_peer_mlme_flag_get(struct wlan_objmgr_peer *peer, + uint32_t flag) +{ + return (peer->peer_mlme.peer_flags & flag) ? 1 : 0; +} +#endif /* _WLAN_OBJMGR_PEER_OBJ_H_*/ diff --git a/umac/cmn_services/obj_mgr/inc/wlan_objmgr_psoc_obj.h b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_psoc_obj.h new file mode 100644 index 0000000000..24dc4d7457 --- /dev/null +++ b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_psoc_obj.h @@ -0,0 +1,742 @@ +/* + * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + /** + * DOC: Define the pSoc data structure of UMAC + * Public APIs to perform operations on Global objects + */ +#ifndef _WLAN_OBJMGR_PSOC_OBJ_H_ +#define _WLAN_OBJMGR_PSOC_OBJ_H_ + +#include "wlan_objmgr_cmn.h" + +#define REG_DMN_CH144 0x0001 +#define REG_DMN_ENTREPRISE 0x0002 + + +/* fw_caps */ + /* CAPABILITY: WEP available */ +#define WLAN_SOC_C_WEP 0x00000001 + /* CAPABILITY: TKIP available */ +#define WLAN_SOC_C_TKIP 0x00000002 + /* CAPABILITY: AES OCB avail */ +#define WLAN_SOC_C_AES 0x00000004 + /* CAPABILITY: AES CCM avail */ +#define WLAN_SOC_C_AES_CCM 0x00000008 + /* CAPABILITY: 11n HT available */ +#define WLAN_SOC_C_HT 0x00000010 + /* CAPABILITY: CKIP available */ +#define WLAN_SOC_C_CKIP 0x00000020 + /* CAPABILITY: ATH FF avail */ +#define WLAN_SOC_C_FF 0x00000040 + /* CAPABILITY: ATH Turbo avail*/ +#define WLAN_SOC_C_TURBOP 0x00000080 + /* CAPABILITY: IBSS available */ +#define WLAN_SOC_C_IBSS 0x00000100 + /* CAPABILITY: Power mgmt */ +#define WLAN_SOC_C_PMGT 0x00000200 + /* CAPABILITY: HOSTAP avail */ +#define WLAN_SOC_C_HOSTAP 0x00000400 + /* CAPABILITY: Old Adhoc Demo */ +#define WLAN_SOC_C_AHDEMO 0x00000800 + /* CAPABILITY: tx power mgmt */ +#define WLAN_SOC_C_TXPMGT 0x00001000 + /* CAPABILITY: short slottime */ +#define WLAN_SOC_C_SHSLOT 0x00002000 + /* CAPABILITY: short preamble */ +#define WLAN_SOC_C_SHPREAMBLE 0x00004000 + /* CAPABILITY: monitor mode */ +#define WLAN_SOC_C_MONITOR 0x00008000 + /* CAPABILITY: TKIP MIC avail */ +#define WLAN_SOC_C_TKIPMIC 0x00010000 + /* CAPABILITY: ATH WAPI avail */ +#define WLAN_SOC_C_WAPI 0x00020000 + /* CONF: WDS auto Detect/DELBA */ +#define WLAN_SOC_C_WDS_AUTODETECT 0x00040000 + /* CAPABILITY: WPA1 avail */ +#define WLAN_SOC_C_WPA1 0x00080000 + /* CAPABILITY: WPA2 avail */ +#define WLAN_SOC_C_WPA2 0x00100000 + /* CAPABILITY: WPA1+WPA2 avail*/ +#define WLAN_SOC_C_WPA 0x00180000 + /* CAPABILITY: frame bursting */ +#define WLAN_SOC_C_BURST 0x00200000 + /* CAPABILITY: WME avail */ +#define WLAN_SOC_C_WME 0x00400000 + /* CAPABILITY: 4-addr support */ +#define WLAN_SOC_C_WDS 0x00800000 + /* CAPABILITY: TKIP MIC for QoS frame */ +#define WLAN_SOC_C_WME_TKIPMIC 0x01000000 + /* CAPABILITY: bg scanning */ +#define WLAN_SOC_C_BGSCAN 0x02000000 + /* CAPABILITY: UAPSD */ +#define WLAN_SOC_C_UAPSD 0x04000000 + /* CAPABILITY: enabled 11.h */ +#define WLAN_SOC_C_DOTH 0x08000000 + +/* XXX protection/barker? */ + /* CAPABILITY: crypto alg's */ +#define WLAN_SOC_C_CRYPTO 0x0000002f + +/* fw_caps_ext */ + /* CAPABILITY: fast channel change */ +#define WLAN_SOC_CEXT_FASTCC 0x00000001 + /* CAPABILITY: P2P */ +#define WLAN_SOC_CEXT_P2P 0x00000002 + /* CAPABILITY: Multi-Channel Operations */ +#define WLAN_SOC_CEXT_MULTICHAN 0x00000004 + /* CAPABILITY: the device supports perf and power offload */ +#define WLAN_SOC_CEXT_PERF_PWR_OFLD 0x00000008 + /* CAPABILITY: the device supports 11ac */ +#define WLAN_SOC_CEXT_11AC 0x00000010 + /* CAPABILITY: the device support acs channel hopping */ +#define WLAN_SOC_CEXT_ACS_CHAN_HOP 0x00000020 + /* CAPABILITY: the device support STA DFS */ +#define WLAN_SOC_CEXT_STADFS 0x00000040 + +/* feature_flags */ + /* CONF: ATH FF enabled */ +#define WLAN_SOC_F_FF 0x00000001 + /* CONF: ATH Turbo enabled*/ +#define WLAN_SOC_F_TURBOP 0x00000002 + /* STATUS: promiscuous mode */ +#define WLAN_SOC_F_PROMISC 0x00000004 + /* STATUS: all multicast mode */ +#define WLAN_SOC_F_ALLMULTI 0x00000008 +/* NB: this is intentionally setup to be IEEE80211_CAPINFO_PRIVACY */ + /* STATUS: start IBSS */ +#define WLAN_SOC_F_SIBSS 0x00000010 +/* NB: this is intentionally setup to be IEEE80211_CAPINFO_SHORT_SLOTTIME */ + /* CONF: Power mgmt enable */ +#define WLAN_SOC_F_PMGTON 0x00000020 + /* CONF: IBSS creation enable */ +#define WLAN_SOC_F_IBSSON 0x00000040 + /* force chanswitch */ +#define WLAN_SOC_F_CHANSWITCH 0x00000080 + +/* ic_flags_ext and/or iv_flags_ext */ + /* CONF: enable country IE */ +#define WLAN_SOC_F_COUNTRYIE 0x00000100 + /* STATE: enable full bgscan completion */ +#define WLAN_SOC_F_BGSCAN 0x00000200 + /* CONF: enable U-APSD */ +#define WLAN_SOC_F_UAPSD 0x00000400 + /* STATUS: sleeping */ +#define WLAN_SOC_F_SLEEP 0x00000800 + /* Enable marking of dfs interfernce */ +#define WLAN_SOC_F_MARKDFS 0x00001000 + /* enable or disable s/w ccmp encrypt decrypt support */ +#define WLAN_SOC_F_CCMPSW_ENCDEC 0x00002000 + /* STATE: hibernating */ +#define WLAN_SOC_F_HIBERNATION 0x00004000 + /* CONF: desired country has been set */ +#define WLAN_SOC_F_DESCOUNTRY 0x00008000 + /* CONF: enable power capability or contraint IE */ +#define WLAN_SOC_F_PWRCNSTRIE 0x00010000 + /* STATUS: 11D in used */ +#define WLAN_SOC_F_DOT11D 0x00020000 + +/** + * struct wlan_objmgr_psoc_regulatory - Regulatory sub structure of PSOC + * @country_code: Country code + * @reg_dmn: Regulatory Domain + * @reg_flags: Regulatory flags + */ +struct wlan_objmgr_psoc_regulatory { + uint16_t country_code; + uint16_t reg_dmn; + uint16_t reg_flags; +}; + +/** + * struct wlan_objmgr_psoc_nif - HDD/OSIF specific sub structure of PSOC + * @phy_version: phy version, read in device probe + * @phy_type: OL/DA type + * @soc_fw_caps: FW capabilities + * @soc_fw_ext_caps: FW ext capabilities + * @soc_feature_caps:Feature capabilities + * @soc_hw_macaddr[]:HW MAC address + */ +struct wlan_objmgr_psoc_nif { + uint32_t phy_version; + WLAN_DEV_TYPE phy_type; + uint32_t soc_fw_caps; + uint32_t soc_fw_ext_caps; + uint32_t soc_feature_caps; + uint8_t soc_hw_macaddr[WLAN_MACADDR_LEN]; +}; + +/** + * struct wlan_objmgr_psoc_objmgr - psoc object manager sub structure + * @wlan_pdev_count: PDEV count + * @wlan_pdev_list[]: PDEV list + * @wlan_pdev_id_map: PDEV id map, to allocate free ids + * @wlan_vdev_count: VDEV count + * @max_vdev_count: Max no. of VDEVs supported by this PSOC + * @wlan_vdev_list[]: VDEV list + * @wlan_vdev_id_map[]: VDEV id map, to allocate free ids + * @wlan_peer_count: PEER count + * @peer_list: Peer list + */ +struct wlan_objmgr_psoc_objmgr { + uint8_t wlan_pdev_count; + struct wlan_objmgr_pdev *wlan_pdev_list[WLAN_UMAC_MAX_PDEVS]; + uint8_t wlan_pdev_id_map; + uint8_t wlan_vdev_count; + uint8_t max_vdev_count; + struct wlan_objmgr_vdev *wlan_vdev_list[WLAN_UMAC_PSOC_MAX_VDEVS]; + uint32_t wlan_vdev_id_map[2]; + uint16_t wlan_peer_count; + struct wlan_peer_list peer_list; +}; + +/** + * struct wlan_soc_southbound_cb - structure for south bound callbacks + * + */ +struct wlan_soc_southbound_cb { +}; + +/** + * struct wlan_concurrency_info - structure for concurrency info + * + */ +struct wlan_concurrency_info { +}; + +/** + * struct wlan_soc_timer - structure for soc timer + * + */ +struct wlan_soc_timer { +}; + +/** + * struct wlan_objmgr_psoc - PSOC common object + * @soc_reg: regulatory sub structure + * @soc_nif: nif sub strucutre + * @soc_objmgr: object manager sub structure + * @soc_cb: south bound callbacks + * @soc_timer: soc timer for inactivity + * @soc_concurrency: concurrency info + * @wlan_active_vdevs[]: List of active VDEVs + * @soc_comp_obj[]: component object pointers + * @obj_status[]: component object status + * @obj_state: object state + * @psoc_lock: psoc lock + */ +struct wlan_objmgr_psoc { + struct wlan_objmgr_psoc_regulatory soc_reg; + struct wlan_objmgr_psoc_nif soc_nif; + struct wlan_objmgr_psoc_objmgr soc_objmgr; + struct wlan_soc_southbound_cb soc_cb; + struct wlan_soc_timer soc_timer; + struct wlan_concurrency_info soc_concurrency; /*TODO */ + uint8_t wlan_active_vdevs[WLAN_UMAC_PSOC_MAX_VDEVS]; + void *soc_comp_obj[WLAN_UMAC_MAX_COMPONENTS]; + QDF_STATUS obj_status[WLAN_UMAC_MAX_COMPONENTS]; + WLAN_OBJ_STATE obj_state; + qdf_spinlock_t psoc_lock; +}; + +/** + ** APIs to Create/Delete Global object APIs + */ +/** + * wlan_objmgr_psoc_obj_create() - psoc object create + * @phy_version: device id (from probe) + * @dev_type: Offload/DA + * + * Creates PSOC object, intializes with default values + * Invokes the registered notifiers to create component object + * + * Return: Handle to struct wlan_objmgr_psoc on successful creation, + * NULL on Failure (on Mem alloc failure and Component objects + * Failure) + */ +struct wlan_objmgr_psoc *wlan_objmgr_psoc_obj_create(uint32_t phy_version, + WLAN_DEV_TYPE dev_type); + +/** + * wlan_objmgr_psoc_obj_delete() - psoc object delete + * @psoc: PSOC object + * + * Deletes PSOC object, + * Invokes the registered notifiers to delete component objects + * + * Return: SUCCESS/FAILURE + */ +QDF_STATUS wlan_objmgr_psoc_obj_delete(struct wlan_objmgr_psoc *psoc); + +/** + ** APIs to attach/detach component objects + */ + +/** + * wlan_objmgr_psoc_component_obj_attach() - psoc comp object attach + * @psoc: PSOC object + * @id: Component id + * @comp_objptr: component's private object pointer + * @status: Component's private object creation status + * + * API to be used for attaching component object with PSOC common object + * + * Return: SUCCESS on successful storing of component's object in common object + * On FAILURE (appropriate failure codes are returned) + */ +QDF_STATUS wlan_objmgr_psoc_component_obj_attach( + struct wlan_objmgr_psoc *psoc, + enum wlan_umac_comp_id id, + void *comp_objptr, + QDF_STATUS status); + +/** + * wlan_objmgr_psoc_component_obj_detach() - psoc comp object detach + * @psoc: PSOC object + * @id: Component id + * @comp_objptr: component's private object pointer + * + * API to be used for detaching component object with PSOC common object + * + * Return: SUCCESS on successful removal of component's object from common + * object + * On FAILURE (appropriate failure codes are returned) + */ +QDF_STATUS wlan_objmgr_psoc_component_obj_detach( + struct wlan_objmgr_psoc *psoc, + enum wlan_umac_comp_id id, + void *comp_objptr); + +/** + ** APIs to operations on psoc objects + */ +/** + * wlan_objmgr_iterate_obj_list() - iterate through all psoc objects + * @psoc: PSOC object + * @obj_type: PDEV_OP/VDEV_OP/PEER_OP + * @handler: the handler will be called for each object of requested type + * the handler should be implemented to perform required operation + * @arg: agruments passed by caller + * @lock_free_op: This gives provision to run this API with out lock protected + * It would be useful, for operations like Obj Delete, where + * lock should not be taken by caller. + * + * API to be used for performing the operations on all PDEV/VDEV/PEER objects + * of psoc + * + * Return: SUCCESS/FAILURE + */ +typedef void (*wlan_objmgr_op_handler)(struct wlan_objmgr_psoc *psoc, + void *object, + void *arg); +/* handler should not take obj lock */ +QDF_STATUS wlan_objmgr_iterate_obj_list( + struct wlan_objmgr_psoc *psoc, + enum wlan_objmgr_obj_type obj_type, + wlan_objmgr_op_handler handler, + void *arg, uint8_t lock_free_op); + +/** + * wlan_objmgr_free_all_objects_per_psoc() - free all psoc objects + * @psoc: PSOC object + * + * API to be used free all the objects(pdev/vdev/peer) of psoc + * + * Return: SUCCESS/FAILURE + */ +QDF_STATUS wlan_objmgr_free_all_objects_per_psoc( + struct wlan_objmgr_psoc *psoc); + +/** + * wlan_objmgr_trigger_psoc_comp_object_creation() - create psoc comp object + * @psoc: PSOC object + * @id: Component id + * + * API to create component object in run time, this would be used for features + * which gets enabled in run time + * + * Return: SUCCESS on successful creation + * On FAILURE (appropriate failure codes are returned) + */ +QDF_STATUS wlan_objmgr_trigger_psoc_comp_object_creation( + struct wlan_objmgr_psoc *psoc, + enum wlan_umac_comp_id id); + +/** + * wlan_objmgr_trigger_psoc_comp_object_deletion() - delete psoc comp object + * @psoc: PSOC object + * @id: Component id + * + * API to delete component object in run time, this would be used for features + * which gets disabled in run time + * + * Return: SUCCESS on successful deletion + * On FAILURE (appropriate failure codes are returned) + */ +QDF_STATUS wlan_objmgr_trigger_psoc_comp_object_deletion( + struct wlan_objmgr_psoc *psoc, + enum wlan_umac_comp_id id); + +/** + * wlan_objmgr_find_peer() - find peer from psoc's peer list + * @psoc: PSOC object + * @macaddr: MAC address + * + * API to find peer object pointer by MAC addr + * + * Return: peer pointer + * NULL on FAILURE + */ +struct wlan_objmgr_peer *wlan_objmgr_find_peer( + struct wlan_objmgr_psoc *psoc, uint8_t *macaddr); + +/** + * wlan_objmgr_find_pdev_by_id() - retrieve pdev by id + * @psoc: PSOC object + * @id: pdev id + * + * API to find pdev object pointer by pdev id + * + * Return: pdev pointer + * NULL on FAILURE + */ +struct wlan_objmgr_pdev *wlan_objmgr_find_pdev_by_id( + struct wlan_objmgr_psoc *psoc, uint8_t id); + +/** + * wlan_objmgr_find_pdev_by_macaddr() - retrieve pdev by macaddr + * @psoc: PSOC object + * @macaddr: MAC address + * + * API to find pdev object pointer by pdev macaddr + * + * Return: pdev pointer + * NULL on FAILURE + */ +struct wlan_objmgr_pdev *wlan_objmgr_find_pdev_by_macaddr( + struct wlan_objmgr_psoc *psoc, uint8_t *macaddr); + +/** + * wlan_objmgr_find_vdev_by_id_from_psoc() - retrieve vdev by id + * @psoc: PSOC object + * @id: vdev id + * + * API to find vdev object pointer by vdev id from psoc + * + * Return: vdev pointer + * NULL on FAILURE + */ +struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_id_from_psoc( + struct wlan_objmgr_psoc *psoc, uint8_t vdev_id); + +/** + * wlan_objmgr_find_vdev_by_macaddr_from_psoc() - retrieve vdev by macaddr + * @psoc: PSOC object + * @macaddr: macaddr + * + * API to find vdev object pointer by vdev macaddr from psoc + * + * Return: vdev pointer + * NULL on FAILURE + */ +struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_macaddr_from_psoc( + struct wlan_objmgr_psoc *psoc, uint8_t *macaddr); + +/** + * wlan_psoc_obj_lock() - Acquire PSOC spinlock + * @psoc: PSOC object + * + * API to acquire PSOC lock + * + * Return: void + */ +static inline void wlan_psoc_obj_lock(struct wlan_objmgr_psoc *psoc) +{ + qdf_spin_lock_bh(&psoc->psoc_lock); +} + +/** + * wlan_psoc_obj_unlock() - Release PSOC spinlock + * @psoc: PSOC object + * + * API to Release PSOC lock + * + * Return: void + */ +static inline void wlan_psoc_obj_unlock(struct wlan_objmgr_psoc *psoc) +{ + qdf_spin_unlock_bh(&psoc->psoc_lock); +} + +/** + * wlan_psoc_set_nif_phy_version() - set nif phy version + * @psoc: PSOC object + * @phy_ver: phy version + * + * API to set nif phy version in psoc + * + * Caller need to acquire lock with wlan_psoc_obj_lock() + * + * Return: void + */ +static inline void wlan_psoc_set_nif_phy_version(struct wlan_objmgr_psoc *psoc, + uint32_t phy_ver) +{ + psoc->soc_nif.phy_version = phy_ver; +} + +/** + * wlan_psoc_get_nif_phy_version() - get nif phy version + * @psoc: PSOC object + * + * API to set nif phy version in psoc + * + * Caller need to acquire lock with wlan_psoc_obj_lock() + * + * Return: @phy_ver: phy version + */ +static inline uint32_t wlan_psoc_get_nif_phy_version( + struct wlan_objmgr_psoc *psoc) +{ + if (psoc == NULL) + return (uint32_t)-1; + return psoc->soc_nif.phy_version; +} + +/** + * wlan_psoc_set_dev_type() - set dev type + * @psoc: PSOC object + * @phy_type: phy type (OL/DA) + * + * API to set dev type in psoc + * + * Caller need to acquire lock with wlan_psoc_obj_lock() + * + * Return: void + */ +static inline void wlan_psoc_set_dev_type(struct wlan_objmgr_psoc *psoc, + WLAN_DEV_TYPE phy_type) +{ + psoc->soc_nif.phy_type = phy_type; +} + +/** + * wlan_objmgr_psoc_get_dev_type - get dev type + * @psoc: PSOC object + * + * API to get dev type in psoc + * + * Caller need to acquire lock with wlan_psoc_obj_lock() + * + * Return: phy type (OL/DA) + */ +static inline WLAN_DEV_TYPE wlan_objmgr_psoc_get_dev_type( + struct wlan_objmgr_psoc *psoc) +{ + if (psoc == NULL) + return (uint32_t)-1; + return psoc->soc_nif.phy_type; +} + +/** + * wlan_psoc_nif_fw_cap_set() - set fw caps + * @psoc: PSOC object + * @cap: capability flag to be set + * + * API to set fw caps in psoc + * + * Caller need to acquire lock with wlan_psoc_obj_lock() + * + * Return: void + */ +static inline void wlan_psoc_nif_fw_cap_set(struct wlan_objmgr_psoc *psoc, + uint32_t cap) +{ + psoc->soc_nif.soc_fw_caps |= cap; +} + +/** + * wlan_psoc_nif_fw_cap_clear() - clear fw caps + * @psoc: PSOC object + * @cap: capability flag to be cleared + * + * API to clear fw caps in psoc + * + * Caller need to acquire lock with wlan_psoc_obj_lock() + * + * Return: void + */ +static inline void wlan_psoc_nif_fw_cap_clear(struct wlan_objmgr_psoc *psoc, + uint32_t cap) +{ + psoc->soc_nif.soc_fw_caps &= ~cap; +} + +/** + * wlan_psoc_nif_fw_cap_get() - get fw caps + * @psoc: PSOC object + * @cap: capability flag to be checked + * + * API to know, whether particular fw caps flag is set in psoc + * + * Caller need to acquire lock with wlan_psoc_obj_lock() + * + * Return: 1 (for set) or 0 (for not set) + */ +static inline uint8_t wlan_psoc_nif_fw_cap_get(struct wlan_objmgr_psoc *psoc, + uint32_t cap) +{ + return (psoc->soc_nif.soc_fw_caps & cap) ? 1 : 0; +} + +/** + * wlan_psoc_nif_fw_ext_cap_set() - set fw ext caps + * @psoc: PSOC object + * @ext_cap: capability flag to be set + * + * API to set fw ext caps in psoc + * + * Caller need to acquire lock with wlan_psoc_obj_lock() + * + * Return: void + */ +static inline void wlan_psoc_nif_fw_ext_cap_set(struct wlan_objmgr_psoc *psoc, + uint32_t ext_cap) +{ + psoc->soc_nif.soc_fw_ext_caps |= ext_cap; +} + +/** + * wlan_psoc_nif_fw_ext_cap_clear() - clear fw ext caps + * @psoc: PSOC object + * @ext_cap: capability flag to be cleared + * + * API to clear fw ext caps in psoc + * + * Caller need to acquire lock with wlan_psoc_obj_lock() + * + * Return: void + */ +static inline void wlan_psoc_nif_fw_ext_cap_clear(struct wlan_objmgr_psoc *psoc, + uint32_t ext_cap) +{ + psoc->soc_nif.soc_fw_ext_caps &= ~ext_cap; +} + +/** + * wlan_psoc_nif_fw_ext_cap_get() - get fw caps + * @psoc: PSOC object + * @ext_cap: capability flag to be checked + * + * API to know, whether particular fw caps flag is set in psoc + * + * Caller need to acquire lock with wlan_psoc_obj_lock() + * + * Return: 1 (for set) or 0 (for not set) + */ +static inline uint8_t wlan_psoc_nif_fw_ext_cap_get( + struct wlan_objmgr_psoc *psoc, uint32_t ext_cap) +{ + return (psoc->soc_nif.soc_fw_ext_caps & ext_cap) ? 1 : 0; +} + +/** + * wlan_psoc_nif_feat_cap_set() - set feature caps + * @psoc: PSOC object + * @cap: feature flag to be set + * + * API to set feature caps in psoc + * + * Caller need to acquire lock with wlan_psoc_obj_lock() + * + * Return: void + */ +static inline void wlan_psoc_nif_feat_cap_set(struct wlan_objmgr_psoc *psoc, + uint32_t feat_cap) +{ + psoc->soc_nif.soc_feature_caps |= feat_cap; +} + +/** + * wlan_psoc_nif_feat_cap_clear() - clear feature caps + * @psoc: PSOC object + * @cap: feature flag to be cleared + * + * API to clear feature caps in psoc + * + * Caller need to acquire lock with wlan_psoc_obj_lock() + * + * Return: void + */ +static inline void wlan_psoc_nif_feat_cap_clear(struct wlan_objmgr_psoc *psoc, + uint32_t feat_cap) +{ + psoc->soc_nif.soc_feature_caps &= ~feat_cap; +} + +/** + * wlan_psoc_nif_feat_cap_get() - get feature caps + * @psoc: PSOC object + * @cap: feature flag to be checked + * + * API to know, whether particular feature cap flag is set in psoc + * + * Caller need to acquire lock with wlan_psoc_obj_lock() + * + * Return: 1 (for set) or 0 (for not set) + */ +static inline uint8_t wlan_psoc_nif_feat_cap_get(struct wlan_objmgr_psoc *psoc, + uint32_t feat_cap) +{ + return (psoc->soc_nif.soc_feature_caps & feat_cap) ? 1 : 0; +} + +/** + * wlan_psoc_set_hw_macaddr() - set hw mac addr + * @psoc: PSOC object + * @macaddr: hw macaddr + * + * API to set hw macaddr of psoc + * + * Caller need to acquire lock with wlan_psoc_obj_lock() + * + * Return: void + */ +static inline void wlan_psoc_set_hw_macaddr(struct wlan_objmgr_psoc *psoc, + uint8_t *macaddr) +{ + if (psoc != NULL) + WLAN_ADDR_COPY(psoc->soc_nif.soc_hw_macaddr, macaddr); +} + +/** + * wlan_psoc_get_hw_macaddr() - get hw macaddr + * @psoc: PSOC object + * + * API to set hw macaddr of psoc + * + * Caller need to acquire lock with wlan_psoc_obj_lock() + * + * Return: hw macaddr + */ +static inline uint8_t *wlan_psoc_get_hw_macaddr(struct wlan_objmgr_psoc *psoc) +{ + if (psoc == NULL) + return NULL; + return psoc->soc_nif.soc_hw_macaddr; +} +#endif /* _WLAN_OBJMGR_PSOC_OBJ_H_*/ diff --git a/umac/cmn_services/obj_mgr/inc/wlan_objmgr_vdev_obj.h b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_vdev_obj.h new file mode 100644 index 0000000000..bc5df7cf8e --- /dev/null +++ b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_vdev_obj.h @@ -0,0 +1,1289 @@ +/* + * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + /** + * DOC: Define the vdev data structure of UMAC + */ +#ifndef _WLAN_OBJMGR_VDEV_OBJ_H_ +#define _WLAN_OBJMGR_VDEV_OBJ_H_ + /* CONF: privacy enabled */ +#define WLAN_VDEV_F_PRIVACY 0x00000001 + /* CONF: 11g w/o 11b sta's */ +#define WLAN_VDEV_F_PUREG 0x00000002 + /* CONF: des_bssid is set */ +#define WLAN_VDEV_F_DESBSSID 0x00000004 + /* CONF: bg scan enabled */ +#define WLAN_VDEV_F_BGSCAN 0x00000008 + /* CONF: sw tx retry enabled */ +#define WLAN_VDEV_F_SWRETRY 0x00000010 + /* STATUS: update beacon tim */ +#define WLAN_VDEV_F_TIMUPDATE 0x00000020 + /* CONF: WPA enabled */ +#define WLAN_VDEV_F_WPA1 0x00000040 + /* CONF: WPA2 enabled */ +#define WLAN_VDEV_F_WPA2 0x00000080 + /* CONF: WPA/WPA2 enabled */ +#define WLAN_VDEV_F_WPA 0x000000c0 + /* CONF: drop unencrypted */ +#define WLAN_VDEV_F_DROPUNENC 0x00000100 + /* CONF: TKIP countermeasures */ +#define WLAN_VDEV_F_COUNTERM 0x00000200 + /* CONF: hide SSID in beacon */ /*TODO PDEV/PSOC */ +#define WLAN_VDEV_F_HIDESSID 0x00000400 + /* CONF: disable internal bridge */ /*TODO PDEV/PSOC */ +#define WLAN_VDEV_F_NOBRIDGE 0x00000800 + /* STATUS: update beacon wme */ +#define WLAN_VDEV_F_WMEUPDATE 0x00001000 + /* CONF: 4 addr allowed */ +#define WLAN_VDEV_F_WDS 0x00002000 + /* CONF: enable U-APSD */ +#define WLAN_VDEV_F_UAPSD 0x00004000 + /* STATUS: sleeping */ +#define WLAN_VDEV_F_SLEEP 0x00008000 + /* drop uapsd EOSP frames for test */ +#define WLAN_VDEV_F_EOSPDROP 0x00010000 + /* drop uapsd EOSP frames for test */ +#define WLAN_VDEV_F_AMPDU 0x00020000 + /* STATE: beacon APP IE updated */ +#define WLAN_VDEV_F_APPIE_UPDATE 0x00040000 + /* CONF: WDS auto Detect/DELBA */ +#define WLAN_VDEV_F_WDS_AUTODETECT 0x00080000 + /* 11b only without 11g stations */ +#define WLAN_VDEV_F_PUREB 0x00100000 + /* disable HT rates */ +#define WLAN_VDEV_F_HTRATES 0x00200000 + /* Extender AP */ +#define WLAN_VDEV_F_AP 0x00400000 + /* CONF: deliver rx frames with 802.11 header */ +#define WLAN_VDEV_F_DELIVER_80211 0x00800000 + /* CONF: os sends down tx frames with 802.11 header */ +#define WLAN_VDEV_F_SEND_80211 0x01000000 + /* CONF: statically configured WDS */ +#define WLAN_VDEV_F_WDS_STATIC 0x02000000 + /* CONF: pure 11n mode */ +#define WLAN_VDEV_F_PURE11N 0x04000000 + /* CONF: pure 11ac mode */ +#define WLAN_VDEV_F_PURE11AC 0x08000000 + /* Basic Rates Update */ +#define WLAN_VDEV_F_BR_UPDATE 0x10000000 + /* CONF: restrict bw ont top of per 11ac/n */ +#define WLAN_VDEV_F_STRICT_BW 0x20000000 + /* Wi-Fi SON mode (with APS) */ +#define WLAN_VDEV_F_SON 0x40000000 + /* Wi-Fi SON mode (with APS) */ +#define WLAN_VDEV_F_MBO 0x80000000 + +/* Feature extension flags */ + /* CONF: MSFT safe mode */ +#define WLAN_VDEV_FEXT_SAFEMODE 0x00000001 + /* if the vap can sleep*/ +#define WLAN_VDEV_FEXT_CANSLEEP 0x00000002 + /* use sw bmiss timer */ +#define WLAN_VDEV_FEXT_SWBMISS 0x00000004 + /* enable beacon copy */ +#define WLAN_VDEV_FEXT_COPY_BEACON 0x00000008 +#define WLAN_VDEV_FEXT_WAPI 0x00000010 + /* 802.11h enabled */ +#define WLAN_VDEV_FEXT_DOTH 0x00000020 + /* if the vap has wds independance set */ +#define WLAN_VDEV_FEXT_VAPIND 0x00000040 + /* QBSS load IE enabled */ +#define WLAN_VDEV_FEXT_BSSLOAD 0x00000080 + /* Short Guard Interval Enable:1 Disable:0 */ +#define WLAN_VDEV_FEXT_SGI 0x00000100 + /* Short Guard Interval Enable:1 Disable:0 for VHT fixed rates */ +#define WLAN_VDEV_FEXT_DATASGI 0x00000200 + /* LDPC Enable Rx:1 TX: 2 ; Disable:0 */ +#define WLAN_VDEV_FEXT_LDPC_TX 0x00000400 +#define WLAN_VDEV_FEXT_LDPC_RX 0x00000800 +#define WLAN_VDEV_FEXT_LDPC 0x00000c00 + /* wme enabled */ +#define WLAN_VDEV_FEXT_WME 0x00001000 + /* WNM Capabilities */ +#define WLAN_VDEV_FEXT_WNM 0x00002000 + /* RRM Capabilities */ +#define WLAN_VDEV_FEXT_RRM 0x00004000 + /* WNM Proxy ARP Capabilities */ +#define WLAN_VDEV_FEXT_PROXYARP 0x00008000 + /* 256 QAM support in 2.4GHz mode Enable:1 Disable:0 */ +#define WLAN_VDEV_FEXT_256QAM 0x00010000 + /* 2.4NG 256 QAM Interop mode Enable:1 Disable:0 */ +#define WLAN_VDEV_FEXT_256QAM_INTEROP 0x00020000 + /* static mimo ps enabled */ +#define WLAN_VDEV_FEXT_STATIC_MIMOPS 0x00040000 + /* dynamic mimo ps enabled */ +#define WLAN_VDEV_FEXT_DYN_MIMOPS 0x00080000 + /* Country IE enabled */ +#define WLAN_VDEV_FEXT_CNTRY_IE 0x00100000 + /*does not want to trigger multi channel operation + instead follow master vaps channel (for AP/GO Vaps) */ +#define WLAN_VDEV_FEXT_NO_MULCHAN 0x00200000 + /*non-beaconing AP VAP*/ +#define WLAN_VDEV_FEXT_NON_BEACON 0x00400000 + +/* VDEV OP flags */ + /* if the vap deleted by user */ +#define WLAN_VDEV_OP_DELETE_PROGRESS 0x00000001 + /* set to enable sta-fws fweature */ +#define WLAN_VDEV_OP_STAFWD 0x00000002 + /* Off-channel support enabled */ +#define WLAN_VDEV_OP_OFFCHAN 0x00000004 + /* if the vap has erp update set */ +#define WLAN_VDEV_OP_ERPUPDATE 0x00000008 + /* this vap needs scheduler for off channel operation */ +#define WLAN_VDEV_OP_NEEDS_SCHED 0x00000010 + /*STA in forced sleep set PS bit for all outgoing frames */ +#define WLAN_VDEV_OP_FORCED_SLEEP 0x00000020 + /* update bssload IE in beacon */ +#define WLAN_VDEV_OP_BSSLOAD_UPDATE 0x00000040 + /* Hotspot 2.0 DGAF Disable bit */ +#define WLAN_VDEV_OP_DGAF_DISABLE 0x00000080 + /* STA SmartNet enabled */ +#define WLAN_VDEV_OP_SMARTNET_EN 0x00000100 + /* SoftAP to reject resuming in DFS channels */ +#define WLAN_VDEV_OP_REJ_DFS_CHAN 0x00000200 + /* Trigger mlme response */ +#define WLAN_VDEV_OP_TRIGGER_MLME_RESP 0x00000400 + /* test flag for MFP */ +#define WLAN_VDEV_OP_MFP_TEST 0x00000800 + /* flag to indicate using default ratemask */ +#define WLAN_VDEV_OP_DEF_RATEMASK 0x00001000 +/*For wakeup AP VAP when wds-sta connect to the AP only use when + export (UMAC_REPEATER_DELAYED_BRINGUP || DBDC_REPEATER_SUPPORT)=1*/ +#define WLAN_VDEV_OP_KEYFLAG 0x00002000 + /* if performe the iwlist scanning */ +#define WLAN_VDEV_OP_LIST_SCANNING 0x00004000 + /*Set when VAP down*/ +#define WLAN_VDEV_OP_IS_DOWN 0x00008000 + /* if vap may require acs when another vap is brought down */ +#define WLAN_VDEV_OP_NEEDS_UP_ACS 0x00010000 + /* Block data traffic tx for this vap */ +#define WLAN_VDEV_OP_BLOCK_TX_TRAFFIC 0x00020000 + /* for mbo functionality */ +#define WLAN_VDEV_OP_MBO 0x00040000 + + /* CAPABILITY: IBSS available */ +#define WLAN_VDEV_C_IBSS 0x00000001 +/* CAPABILITY: HOSTAP avail */ +#define WLAN_VDEV_C_HOSTAP 0x00000002 + /* CAPABILITY: Old Adhoc Demo */ +#define WLAN_VDEV_C_AHDEMO 0x00000004 + /* CAPABILITY: sw tx retry */ +#define WLAN_VDEV_C_SWRETRY 0x00000008 + /* CAPABILITY: monitor mode */ +#define WLAN_VDEV_C_MONITOR 0x00000010 + /* CAPABILITY: TKIP MIC avail */ +#define WLAN_VDEV_C_TKIPMIC 0x00000020 + /* CAPABILITY: 4-addr support */ +#define WLAN_VDEV_C_WDS 0x00000040 + /* CAPABILITY: TKIP MIC for QoS frame */ +#define WLAN_VDEV_C_WME_TKIPMIC 0x00000080 + /* CAPABILITY: bg scanning */ +#define WLAN_VDEV_C_BGSCAN 0x00000100 + +/** + * enum wlan_vdev_state - VDEV state + * @WLAN_VDEV_S_INIT: Default state, IDLE state + * @WLAN_VDEV_S_SCAN: SCAN state + * @WLAN_VDEV_S_JOIN: Join state + * @WLAN_VDEV_S_DFS_WAIT:CAC period + * @WLAN_VDEV_S_RUN: RUN state + * @WLAN_VDEV_S_STOP: STOP state + * @WLAN_VDEV_S_RESET: RESET state, STOP+INIT+JOIN + * @WLAN_VDEV_S_MAX: MAX state + */ +enum wlan_vdev_state { + WLAN_VDEV_S_INIT = 0, + WLAN_VDEV_S_SCAN = 1, + WLAN_VDEV_S_JOIN = 2, + WLAN_VDEV_S_DFS_WAIT = 3, + WLAN_VDEV_S_RUN = 4, + WLAN_VDEV_S_STOP = 5, + WLAN_VDEV_S_RESET = 6, + WLAN_VDEV_S_MAX, +}; + +/** + * struct wlan_vdev_create_params - Create params, HDD/OSIF passes this + * structure While creating VDEV + * @opmode: Opmode of VDEV + * @macaddr[]: MAC address + * @flags: create flags + * @osifp: OS structure + * @mataddr[]: MAT address + */ +struct wlan_vdev_create_params { + enum tQDF_ADAPTER_MODE opmode; + uint8_t macaddr[WLAN_MACADDR_LEN]; + uint32_t flags; + void *osifp; + uint8_t mataddr[WLAN_MACADDR_LEN]; +}; + +/** + * struct wlan_channel - channel structure + */ +struct wlan_channel { + +}; + +/** + * struct wlan_objmgr_vdev_mlme - VDEV MLME specific sub structure + * @vdev_opmode: Opmode of VDEV + * @ssid[]: SSID + * @ssid_len: SSID length + * @bss_chan: BSS channel + * @des_chan: Desired channel, for STA Desired may not be used + * @nss: Num. Spatial streams + * @chainmask: Chainmask + * @macaddr[]: VDEV self MAC address + * @vdev_caps: VDEV capabilities + * @vdev_feat_caps: VDEV feature caps + * @vdev_feat_ext_caps: VDEV Extended feature caps + * @max_rate: MAX rate + * @tx_mgmt_rate: TX Mgmt. Rate + * @tx_power: Tx power + * @mlme_state: VDEV state + * @vdev_op_flags: Operation flags + * @mataddr[]: MAT address + */ +struct wlan_objmgr_vdev_mlme { + enum tQDF_ADAPTER_MODE vdev_opmode; + char ssid[WLAN_SSID_MAX_LEN+1]; + uint8_t ssid_len; + struct wlan_channel *bss_chan; /* Define wlan_channel */ + struct wlan_channel *des_chan; /*TODO ??? */ + uint8_t nss; + uint8_t chainmask; + uint8_t macaddr[WLAN_MACADDR_LEN]; + uint32_t vdev_caps; + uint32_t vdev_feat_caps; + uint32_t vdev_feat_ext_caps; + uint32_t max_rate; + uint32_t tx_mgmt_rate; + uint8_t tx_power; + enum wlan_vdev_state mlme_state; + uint32_t vdev_op_flags; + uint8_t mataddr[WLAN_MACADDR_LEN]; +}; + +/** + * struct wlan_objmgr_vdev_nif - VDEV HDD specific sub structure + * @osdev: OS specific pointer + */ +struct wlan_objmgr_vdev_nif { + void *osdev; +}; + +/** + * struct wlan_objmgr_vdev_objmgr - vdev object manager sub structure + * @vdev_id: VDEV id + * @self_peer: Self PEER + * @bss_peer: BSS PEER + * @wlan_peer_list: PEER list + * @wlan_pdev: PDEV pointer + * @wlan_peer_count: Peer count + * @max_peer_count: Max Peer count + * @c_flags: creation specific flags + */ +struct wlan_objmgr_vdev_objmgr { + uint8_t vdev_id; + struct wlan_objmgr_peer *self_peer; + struct wlan_objmgr_peer *bss_peer; + qdf_list_t wlan_peer_list; + struct wlan_objmgr_pdev *wlan_pdev; + uint16_t wlan_peer_count; + uint16_t max_peer_count; + uint32_t c_flags; +}; + +/** + * struct wlan_objmgr_vdev - VDEV common object + * @vdev_node: qdf list of pdev's vdev list + * @vdev_mlme: VDEV MLME substructure + * @vdev_objmgr: VDEV Object Mgr substructure + * @vdev_nif: VDEV HDD substructure + * @vdev_comp_obj[]:Component objects list + * @obj_status[]: Component object status + * @obj_state: VDEV object state + * @vdev_lock: VDEV lock + */ +struct wlan_objmgr_vdev { + qdf_list_node_t vdev_node; + struct wlan_objmgr_vdev_mlme vdev_mlme; + struct wlan_objmgr_vdev_objmgr vdev_objmgr; + struct wlan_objmgr_vdev_nif vdev_nif; + void *vdev_comp_obj[WLAN_UMAC_MAX_COMPONENTS]; + QDF_STATUS obj_status[WLAN_UMAC_MAX_COMPONENTS]; + WLAN_OBJ_STATE obj_state; + qdf_spinlock_t vdev_lock; +}; + +/** + ** APIs to Create/Delete Global object APIs + */ +/** + * wlan_objmgr_vdev_obj_create() - vdev object create + * @pdev: PDEV object on which this vdev gets created + * @params: VDEV create params from HDD + * + * Creates vdev object, intializes with default values + * Attaches to psoc and pdev objects + * Invokes the registered notifiers to create component object + * + * Return: Handle to struct wlan_objmgr_vdev on successful creation, + * NULL on Failure (on Mem alloc failure and Component objects + * Failure) + */ +struct wlan_objmgr_vdev *wlan_objmgr_vdev_obj_create( + struct wlan_objmgr_pdev *pdev, + struct wlan_vdev_create_params *params); + +/** + * wlan_objmgr_vdev_obj_delete() - vdev object delete + * @vdev: vdev object + * + * Deletes VDEV object, removes it from PSOC's, PDEV's VDEV list + * Invokes the registered notifiers to delete component objects + * + * Return: SUCCESS/FAILURE + */ +QDF_STATUS wlan_objmgr_vdev_obj_delete(struct wlan_objmgr_vdev *vdev); + +/** + ** APIs to attach/detach component objects + */ +/** + * wlan_objmgr_vdev_component_obj_attach() - vdev comp object attach + * @vdev: VDEV object + * @id: Component id + * @comp_objptr: component's private object pointer + * @status: Component's private object creation status + * + * API to be used for attaching component object with VDEV common object + * + * Return: SUCCESS on successful storing of component's object in common object + * On FAILURE (appropriate failure codes are returned) + */ +QDF_STATUS wlan_objmgr_vdev_component_obj_attach( + struct wlan_objmgr_vdev *vdev, + enum wlan_umac_comp_id id, + void *comp_objptr, + QDF_STATUS status); + +/** + * wlan_objmgr_vdev_component_obj_detach() - vdev comp object detach + * @vdev: VDEV object + * @id: Component id + * @comp_objptr: component's private object pointer + * + * API to be used for detaching component object with VDEV common object + * + * Return: SUCCESS on successful removal of component's object from common + * object + * On FAILURE (appropriate failure codes are returned) + */ +QDF_STATUS wlan_objmgr_vdev_component_obj_detach( + struct wlan_objmgr_vdev *vdev, + enum wlan_umac_comp_id id, + void *comp_objptr); +/* + ** APIs to operations on vdev objects +*/ + +/** + * wlan_objmgr_iterate_peerobj_list() - iterate vdev's peer list + * @vdev: vdev object + * @handler: the handler will be called for each object of requested type + * the handler should be implemented to perform required operation + * @arg: agruments passed by caller + * + * API to be used for performing the operations on all PEER objects + * of vdev + * + * Return: SUCCESS/FAILURE + */ +typedef void (*wlan_objmgr_vdev_op_handler)(struct wlan_objmgr_vdev *vdev, + void *object, + void *arg); + +QDF_STATUS wlan_objmgr_iterate_peerobj_list( + struct wlan_objmgr_vdev *vdev, + wlan_objmgr_vdev_op_handler handler, + void *arg); + +/** + * wlan_objmgr_trigger_vdev_comp_object_creation() - vdev comp object creation + * @vdev: VDEV object + * @id: Component id + * + * API to create component object in run time, this would be used for features + * which gets enabled in run time + * + * Return: SUCCESS on successful creation + * On FAILURE (appropriate failure codes are returned) + */ +QDF_STATUS wlan_objmgr_trigger_vdev_comp_object_creation( + struct wlan_objmgr_vdev *vdev, + enum wlan_umac_comp_id id); + +/** + * wlan_objmgr_trigger_vdev_comp_object_deletion() - vdev comp object deletion + * @vdev: VDEV object + * @id: Component id + * + * API to delete component object in run time, this would be used for features + * which gets disabled in run time + * + * Return: SUCCESS on successful deletion + * On FAILURE (appropriate failure codes are returned) + */ +QDF_STATUS wlan_objmgr_trigger_vdev_comp_object_deletion( + struct wlan_objmgr_vdev *vdev, + enum wlan_umac_comp_id id); + +/* Util APIs */ + +/** + * wlan_vdev_get_pdev() - get pdev + * @vdev: VDEV object + * + * API to get pdev object pointer from vdev + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: pdev object pointer + */ +static inline struct wlan_objmgr_pdev *wlan_vdev_get_pdev( + struct wlan_objmgr_vdev *vdev) +{ + return vdev->vdev_objmgr.wlan_pdev; +} + +/** + * wlan_pdev_vdev_list_peek_head() - get first vdev from pdev list + * @peer_list: qdf_list_t + * + * API to get the head vdev of given peer (of pdev's vdev list) + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: + * @peer: head peer + */ +static inline struct wlan_objmgr_vdev *wlan_pdev_vdev_list_peek_head( + qdf_list_t *vdev_list) +{ + struct wlan_objmgr_vdev *vdev; + qdf_list_node_t *vdev_node = NULL; + + if (qdf_list_peek_front(vdev_list, &vdev_node) != QDF_STATUS_SUCCESS) + return NULL; + + vdev = qdf_container_of(vdev_node, struct wlan_objmgr_vdev, vdev_node); + return vdev; +} + +/** + * wlan_vdev_get_next_vdev_of_pdev() - get next vdev + * @vdev: VDEV object + * + * API to get next vdev object pointer of vdev + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: + * @vdev_next: VDEV object + */ +static inline struct wlan_objmgr_vdev *wlan_vdev_get_next_vdev_of_pdev( + qdf_list_t *vdev_list, + struct wlan_objmgr_vdev *vdev) +{ + struct wlan_objmgr_vdev *vdev_next; + qdf_list_node_t *node = &vdev->vdev_node; + qdf_list_node_t *next_node = NULL; + + if (node == NULL) + return NULL; + + if (qdf_list_peek_next(vdev_list, node, &next_node) != + QDF_STATUS_SUCCESS) + return NULL; + + vdev_next = qdf_container_of(next_node, struct wlan_objmgr_vdev, + vdev_node); + return vdev_next; +} + +/** + * wlan_vdev_set_pdev() - set pdev + * @vdev: VDEV object + * @pdev: PDEV object + * + * API to get pdev object pointer from vdev + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: void + */ +static inline void wlan_vdev_set_pdev(struct wlan_objmgr_vdev *vdev, + struct wlan_objmgr_pdev *pdev) +{ + vdev->vdev_objmgr.wlan_pdev = pdev; +} + +/** + * wlan_vdev_get_psoc() - get psoc + * @vdev: VDEV object + * + * API to get pdev object pointer from vdev + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: psoc object pointer + */ +static inline struct wlan_objmgr_psoc *wlan_vdev_get_psoc( + struct wlan_objmgr_vdev *vdev) +{ + struct wlan_objmgr_pdev *pdev; + + pdev = wlan_vdev_get_pdev(vdev); + if (pdev == NULL) + return NULL; + + return wlan_pdev_get_psoc(pdev); +} + +/** + * wlan_vdev_mlme_set_opmode() - set vdev opmode + * @vdev: VDEV object + * @mode: VDEV op mode + * + * API to set opmode in vdev object + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: void + */ +static inline void wlan_vdev_mlme_set_opmode(struct wlan_objmgr_vdev *vdev, + enum tQDF_ADAPTER_MODE mode) +{ + vdev->vdev_mlme.vdev_opmode = mode; +} + +/** + * wlan_vdev_mlme_get_opmode() - get vdev opmode + * @vdev: VDEV object + * + * API to set opmode of vdev object + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: + * @mode: VDEV op mode + */ +static inline enum tQDF_ADAPTER_MODE wlan_vdev_mlme_get_opmode( + struct wlan_objmgr_vdev *vdev) +{ + return vdev->vdev_mlme.vdev_opmode; +} + +/** + * wlan_vdev_mlme_set_macaddr() - set vdev macaddr + * @vdev: VDEV object + * @macaddr: MAC address + * + * API to set macaddr in vdev object + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: void + */ +static inline void wlan_vdev_mlme_set_macaddr(struct wlan_objmgr_vdev *vdev, + uint8_t *macaddr) +{ + WLAN_ADDR_COPY(vdev->vdev_mlme.macaddr, macaddr); +} + +/** + * wlan_vdev_mlme_get_macaddr() - get vdev macaddr + * @vdev: VDEV object + * + * API to get MAC address from vdev object + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: + * @macaddr: MAC address + */ +static inline uint8_t *wlan_vdev_mlme_get_macaddr(struct wlan_objmgr_vdev *vdev) +{ + return vdev->vdev_mlme.macaddr; +} + +/** + * wlan_vdev_mlme_set_mataddr() - set vdev mataddr + * @vdev: VDEV object + * @mataddr: MAT address + * + * API to set mataddr in vdev object + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: void + */ +static inline void wlan_vdev_mlme_set_mataddr(struct wlan_objmgr_vdev *vdev, + uint8_t *mataddr) +{ + WLAN_ADDR_COPY(vdev->vdev_mlme.mataddr, mataddr); +} + +/** + * wlan_vdev_mlme_get_mataddr() - get mataddr + * @vdev: VDEV object + * + * API to get MAT address from vdev object + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: + * @mataddr: MAT address + */ +static inline uint8_t *wlan_vdev_mlme_get_mataddr(struct wlan_objmgr_vdev *vdev) +{ + return vdev->vdev_mlme.mataddr; +} + +/** + * wlan_vdev_get_id() - get vdev id + * @vdev: VDEV object + * + * API to get vdev id + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: + * @id: vdev id + */ +static inline uint8_t wlan_vdev_get_id(struct wlan_objmgr_vdev *vdev) +{ + return vdev->vdev_objmgr.vdev_id; +} + +/** + * wlan_vdev_get_hw_macaddr() - get hw macaddr + * @vdev: VDEV object + * + * API to retrieve the HW MAC address from PDEV + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: + * @macaddr: HW MAC address + */ +static inline uint8_t *wlan_vdev_get_hw_macaddr(struct wlan_objmgr_vdev *vdev) +{ + struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev); + + if (pdev != NULL) { + return wlan_pdev_get_hw_macaddr(pdev); + } else { + qdf_print("%s:pdev is NULL\n", __func__); + return NULL; + } +} + +/** + * wlan_vdev_mlme_set_ssid() - set ssid + * @vdev: VDEV object + * @ssid: SSID (input) + * @ssid_len: Length of SSID + * + * API to set the SSID of VDEV + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: SUCCESS, if update is done + * FAILURE, if ssid length is > max ssid len + */ +static inline QDF_STATUS wlan_vdev_mlme_set_ssid( + struct wlan_objmgr_vdev *vdev, + const uint8_t *ssid, uint8_t ssid_len) +{ + if (ssid_len < WLAN_SSID_MAX_LEN) { + qdf_mem_copy(vdev->vdev_mlme.ssid, ssid, ssid_len); + vdev->vdev_mlme.ssid_len = ssid_len; + } else { + vdev->vdev_mlme.ssid_len = 0; + return QDF_STATUS_E_FAILURE; + } + return QDF_STATUS_SUCCESS; +} + +/** + * wlan_vdev_mlme_get_ssid() - get ssid + * @vdev: VDEV object + * @ssid: SSID + * @ssid_len: Length of SSID + * + * API to get the SSID of VDEV, it updates the SSID and its length + * in @ssid, @ssid_len respectively + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: SUCCESS, if update is done + * FAILURE, if ssid length is > max ssid len + */ +static inline QDF_STATUS wlan_vdev_mlme_get_ssid( + struct wlan_objmgr_vdev *vdev, + uint8_t *ssid, uint8_t *ssid_len) +{ + if (vdev->vdev_mlme.ssid_len > 0) { + *ssid_len = vdev->vdev_mlme.ssid_len; + qdf_mem_copy(ssid, vdev->vdev_mlme.ssid, *ssid_len); + } else { + *ssid_len = 0; + return QDF_STATUS_E_FAILURE; + } + return QDF_STATUS_SUCCESS; +} + +/** + * wlan_vdev_obj_lock() - Acquire VDEV spinlock + * @vdev: VDEV object + * + * API to acquire VDEV lock + * + * Return: void + */ +static inline void wlan_vdev_obj_lock(struct wlan_objmgr_vdev *vdev) +{ + qdf_spin_lock_bh(&vdev->vdev_lock); +} + +/** + * wlan_vdev_obj_unlock() - Release VDEV spinlock + * @vdev: VDEV object + * + * API to Release VDEV lock + * + * Return: void + */ +static inline void wlan_vdev_obj_unlock(struct wlan_objmgr_vdev *vdev) +{ + qdf_spin_unlock_bh(&vdev->vdev_lock); +} + +/** + * wlan_vdev_mlme_set_bss_chan() - set bss chan + * @vdev: VDEV object + * @bss_chan: Channel + * + * API to set the BSS channel + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: void + */ +static inline void wlan_vdev_mlme_set_bss_chan(struct wlan_objmgr_vdev *vdev, + struct wlan_channel *bss_chan) +{ + vdev->vdev_mlme.bss_chan = bss_chan; +} + +/** + * wlan_vdev_mlme_get_bss_chan() - get bss chan + * @vdev: VDEV object + * + * API to get the BSS channel + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: + * @bss_chan: Channel + */ +static inline struct wlan_channel *wlan_vdev_mlme_get_bss_chan( + struct wlan_objmgr_vdev *vdev) +{ + return vdev->vdev_mlme.bss_chan; +} + +/** + * wlan_vdev_mlme_set_des_chan() - set desired chan + * @vdev: VDEV object + * @des_chan: Channel configured by user + * + * API to set the desired channel + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: void + */ +static inline void wlan_vdev_mlme_set_des_chan(struct wlan_objmgr_vdev *vdev, + struct wlan_channel *des_chan) +{ + vdev->vdev_mlme.des_chan = des_chan; +} + +/** + * wlan_vdev_mlme_get_des_chan() - get desired chan + * @vdev: VDEV object + * + * API to get the desired channel + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: + * @des_chan: Channel configured by user + */ +static inline struct wlan_channel *wlan_vdev_mlme_get_des_chan( + struct wlan_objmgr_vdev *vdev) +{ + return vdev->vdev_mlme.des_chan; +} + +/** + * wlan_vdev_mlme_set_nss() - set NSS + * @vdev: VDEV object + * @nss: nss configured by user + * + * API to set the Number of Spatial streams + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: void + */ +static inline void wlan_vdev_mlme_set_nss(struct wlan_objmgr_vdev *vdev, + uint8_t nss) +{ + vdev->vdev_mlme.nss = nss; +} + +/** + * wlan_vdev_mlme_get_nss() - get NSS + * @vdev: VDEV object + * + * API to get the Number of Spatial Streams + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: + * @nss: nss value + */ +static inline uint8_t wlan_vdev_mlme_get_nss( + struct wlan_objmgr_vdev *vdev) +{ + return vdev->vdev_mlme.nss; +} + +/** + * wlan_vdev_mlme_set_chainmask() - set chainmask + * @vdev: VDEV object + * @chainmask : chainmask either configured by user or max supported + * + * API to set the chainmask + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: void + */ +static inline void wlan_vdev_mlme_set_chainmask(struct wlan_objmgr_vdev *vdev, + uint8_t chainmask) +{ + vdev->vdev_mlme.chainmask = chainmask; +} + +/** + * wlan_vdev_mlme_get_chainmask() - get chainmask + * @vdev: VDEV object + * + * API to get the chainmask + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: + * @chainmask : chainmask either configured by user or max supported + */ +static inline uint8_t wlan_vdev_mlme_get_chainmask( + struct wlan_objmgr_vdev *vdev) +{ + return vdev->vdev_mlme.chainmask; +} + +/** + * wlan_vdev_mlme_set_txpower() - set tx power + * @vdev: VDEV object + * @txpow: tx power either configured by used or max allowed + * + * API to set the tx power + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: void + */ +static inline void wlan_vdev_mlme_set_txpower(struct wlan_objmgr_vdev *vdev, + uint8_t txpow) +{ + vdev->vdev_mlme.tx_power = txpow; +} + +/** + * wlan_vdev_mlme_get_txpower() - get tx power + * @vdev: VDEV object + * + * API to get the tx power + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: + * @txpow: tx power either configured by used or max allowed + */ +static inline uint8_t wlan_vdev_mlme_get_txpower( + struct wlan_objmgr_vdev *vdev) +{ + return vdev->vdev_mlme.tx_power; +} + +/** + * wlan_vdev_mlme_set_maxrate() - set max rate + * @vdev: VDEV object + * @maxrate: configured by used or based on configured mode + * + * API to set the max rate the vdev supports + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: void + */ +static inline void wlan_vdev_mlme_set_maxrate(struct wlan_objmgr_vdev *vdev, + uint32_t maxrate) +{ + vdev->vdev_mlme.max_rate = maxrate; +} + +/** + * wlan_vdev_mlme_get_maxrate() - get max rate + * @vdev: VDEV object + * + * API to get the max rate the vdev supports + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: + * @maxrate: configured by used or based on configured mode + */ +static inline uint32_t wlan_vdev_mlme_get_maxrate( + struct wlan_objmgr_vdev *vdev) +{ + return vdev->vdev_mlme.max_rate; +} + +/** + * wlan_vdev_mlme_set_txmgmtrate() - set txmgmtrate + * @vdev: VDEV object + * @txmgmtrate: Tx Mgmt rate + * + * API to set Mgmt Tx rate + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: void + */ +static inline void wlan_vdev_mlme_set_txmgmtrate(struct wlan_objmgr_vdev *vdev, + uint32_t txmgmtrate) +{ + vdev->vdev_mlme.tx_mgmt_rate = txmgmtrate; +} + +/** + * wlan_vdev_mlme_get_txmgmtrate() - get txmgmtrate + * @vdev: VDEV object + * + * API to get Mgmt Tx rate + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: + * @txmgmtrate: Tx Mgmt rate + */ +static inline uint32_t wlan_vdev_mlme_get_txmgmtrate( + struct wlan_objmgr_vdev *vdev) +{ + return vdev->vdev_mlme.tx_mgmt_rate; +} + +/** + * wlan_vdev_mlme_feat_cap_set() - set feature caps + * @vdev: VDEV object + * @cap: capabilities to be set + * + * API to set MLME feature capabilities + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: void + */ +static inline void wlan_vdev_mlme_feat_cap_set(struct wlan_objmgr_vdev *vdev, + uint32_t cap) +{ + vdev->vdev_mlme.vdev_feat_caps |= cap; +} + +/** + * wlan_vdev_mlme_feat_cap_clear() - clear feature caps + * @vdev: VDEV object + * @cap: capabilities to be cleared + * + * API to clear MLME feature capabilities + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: void + */ +static inline void wlan_vdev_mlme_feat_cap_clear(struct wlan_objmgr_vdev *vdev, + uint32_t cap) +{ + vdev->vdev_mlme.vdev_feat_caps &= ~cap; +} + +/** + * wlan_vdev_mlme_feat_cap_get() - get feature caps + * @vdev: VDEV object + * @cap: capabilities to be checked + * + * API to know MLME feature capability is set or not + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: 1 -- if capabilities set + * 0 -- if capabilities clear + */ +static inline uint8_t wlan_vdev_mlme_feat_cap_get(struct wlan_objmgr_vdev *vdev, + uint32_t cap) +{ + return (vdev->vdev_mlme.vdev_feat_caps & cap) ? 1 : 0; +} + +/** + * wlan_vdev_mlme_feat_ext_cap_set() - set ext feature caps + * @vdev: VDEV object + * @cap: capabilities to be set + * + * API to set the MLME extensive feature capabilities + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: void + */ +static inline void wlan_vdev_mlme_feat_ext_cap_set( + struct wlan_objmgr_vdev *vdev, + uint32_t cap) +{ + vdev->vdev_mlme.vdev_feat_ext_caps |= cap; +} + +/** + * wlan_vdev_mlme_feat_ext_cap_clear() - clear ext feature caps + * @vdev: VDEV object + * @cap: capabilities to be cleared + * + * API to clear the MLME extensive feature capabilities + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: void + */ +static inline void wlan_vdev_mlme_feat_ext_cap_clear( + struct wlan_objmgr_vdev *vdev, + uint32_t cap) +{ + vdev->vdev_mlme.vdev_feat_ext_caps &= ~cap; +} + +/** + * wlan_vdev_mlme_feat_ext_cap_get() - get feature ext caps + * @vdev: VDEV object + * @cap: capabilities to be checked + * + * API to know MLME ext feature capability is set or not + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: 1 -- if capabilities set + * 0 -- if capabilities clear + */ +static inline uint8_t wlan_vdev_mlme_feat_ext_cap_get( + struct wlan_objmgr_vdev *vdev, + uint32_t cap) +{ + return (vdev->vdev_mlme.vdev_feat_ext_caps & cap) ? 1 : 0; +} + +/** + * wlan_vdev_mlme_cap_set() - mlme caps set + * @vdev: VDEV object + * @cap: capabilities to be set + * + * API to set the MLME capabilities + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: void + */ +static inline void wlan_vdev_mlme_cap_set(struct wlan_objmgr_vdev *vdev, + uint32_t cap) +{ + vdev->vdev_mlme.vdev_caps |= cap; +} + +/** + * wlan_vdev_mlme_cap_clear() - mlme caps clear + * @vdev: VDEV object + * @cap: capabilities to be cleared + * + * API to clear the MLME capabilities + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: void + */ +static inline void wlan_vdev_mlme_cap_clear(struct wlan_objmgr_vdev *vdev, + uint32_t cap) +{ + vdev->vdev_mlme.vdev_caps &= ~cap; +} + +/** + * wlan_vdev_mlme_cap_get() - get mlme caps + * @vdev: VDEV object + * @cap: capabilities to be checked + * + * API to know MLME capability is set or not + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: 1 -- if capabilities set + * 0 -- if capabilities clear + */ +static inline uint8_t wlan_vdev_mlme_cap_get(struct wlan_objmgr_vdev *vdev, + uint32_t cap) +{ + return (vdev->vdev_mlme.vdev_caps & cap) ? 1 : 0; +} + +/** + * wlan_vdev_mlme_get_state() - get mlme state + * @vdev: VDEV object + * + * API to get MLME state + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: state of MLME + */ +static inline enum wlan_vdev_state wlan_vdev_mlme_get_state( + struct wlan_objmgr_vdev *vdev) +{ + return vdev->vdev_mlme.mlme_state; +} + +/** + * wlan_vdev_mlme_set_state() - set mlme state + * @vdev: VDEV object + * @state: MLME state + * + * API to set MLME state + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: void + */ +static inline void wlan_vdev_mlme_set_state(struct wlan_objmgr_vdev *vdev, + enum wlan_vdev_state state) +{ + if (state < WLAN_VDEV_S_MAX) + vdev->vdev_mlme.mlme_state = state; +} + +/** + * wlan_vdev_set_selfpeer() - set self peer + * @vdev: VDEV object + * @peer: peer pointer + * + * API to set the self peer of VDEV + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: void + */ +static inline void wlan_vdev_set_selfpeer(struct wlan_objmgr_vdev *vdev, + struct wlan_objmgr_peer *peer) +{ + vdev->vdev_objmgr.self_peer = peer; +} + +/** + * wlan_vdev_get_selfpeer() - get self peer + * @vdev: VDEV object + * + * API to get the self peer of VDEV + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: + * @peer: peer pointer + */ +static inline struct wlan_objmgr_peer *wlan_vdev_get_selfpeer( + struct wlan_objmgr_vdev *vdev) +{ + return vdev->vdev_objmgr.self_peer; +} + +/** + * wlan_vdev_set_bsspeer() - set bss peer + * @vdev: VDEV object + * @peer: BSS peer pointer + * + * API to set the BSS peer of VDEV + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: void + */ +static inline void wlan_vdev_set_bsspeer(struct wlan_objmgr_vdev *vdev, + struct wlan_objmgr_peer *peer) +{ + vdev->vdev_objmgr.bss_peer = peer; +} + +/** + * wlan_vdev_get_bsspeer() - get bss peer + * @vdev: VDEV object + * + * API to get the BSS peer of VDEV + * + * Caller need to acquire lock with wlan_vdev_obj_lock() + * + * Return: + * @peer: BSS peer pointer + */ +static inline struct wlan_objmgr_peer *wlan_vdev_get_bsspeer( + struct wlan_objmgr_vdev *vdev) +{ + return vdev->vdev_objmgr.bss_peer; +} +#endif /* _WLAN_OBJMGR_VDEV_OBJ_H_*/ diff --git a/umac/cmn_services/obj_mgr/src/wlan_objmgr_global_obj.c b/umac/cmn_services/obj_mgr/src/wlan_objmgr_global_obj.c new file mode 100644 index 0000000000..fde317a224 --- /dev/null +++ b/umac/cmn_services/obj_mgr/src/wlan_objmgr_global_obj.c @@ -0,0 +1,774 @@ +/* + * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + /** + * DOC: Public APIs to perform operations on Global objects + */ + +#include +#include +#include "qdf_mem.h" + +/* Global object, it is declared globally */ +struct wlan_objmgr_global *g_umac_glb_obj; +/* Component Name table */ +const char *wlan_umac_component_name[] = { + "MLME", + "SCAN_MGR", + "SCAN_CACHE", + "MGMT_TXRX", + "", +}; +/* +** APIs to Create/Delete Global object APIs +*/ +QDF_STATUS wlan_objmgr_global_obj_create(void) +{ + struct wlan_objmgr_global *umac_global_obj; + + /* If it is already created, ignore */ + if (g_umac_glb_obj != NULL) { + qdf_print("%s: Global object is already created\n", __func__); + return QDF_STATUS_E_FAILURE; + } + /* Allocation of memory for Global object */ + umac_global_obj = (struct wlan_objmgr_global *)qdf_mem_malloc( + sizeof(*umac_global_obj)); + if (umac_global_obj == NULL) { + qdf_print("%s: Global object alloc failed due to malloc\n", + __func__); + return QDF_STATUS_E_NOMEM; + } + /* Store Global object pointer in Global variable */ + g_umac_glb_obj = umac_global_obj; + /* Initialize spinlock */ + qdf_spinlock_create(&g_umac_glb_obj->global_lock); + + return QDF_STATUS_SUCCESS; +} +EXPORT_SYMBOL(wlan_objmgr_global_obj_create); + +QDF_STATUS wlan_objmgr_global_obj_delete(void) +{ + /* If it is already deleted */ + if (g_umac_glb_obj == NULL) { + qdf_print("%s: Global object is not allocated\n", __func__); + return QDF_STATUS_E_FAILURE; + } + /* TODO: Do we need to check, if any object + * is not freed before this is called ?? + * ideally, init/deinit module should take care of freeing */ + /* Initialize spinlock */ + qdf_spinlock_destroy(&g_umac_glb_obj->global_lock); + /* Free Global object memory */ + qdf_mem_free(g_umac_glb_obj); + /* Reset Global variable to NULL */ + g_umac_glb_obj = NULL; + return QDF_STATUS_SUCCESS; +} +EXPORT_SYMBOL(wlan_objmgr_global_obj_delete); + +/** + ** APIs to register/unregister handlers + */ +QDF_STATUS wlan_objmgr_register_psoc_create_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_psoc_create_handler handler, + void *arg) +{ + /* If id is not within valid range, return */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) { + qdf_print("%s: component %d is out of range\n", __func__, id); + return QDF_STATUS_MAXCOMP_FAIL; + } + + qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); + /* If there is a valid entry, return failure */ + if (g_umac_glb_obj->psoc_create_handler[id] != NULL) { + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + qdf_print("%s:callback for comp %d is already registered\n", + __func__, id); + return QDF_STATUS_E_FAILURE; + } + /* Store handler and args in Global object table */ + g_umac_glb_obj->psoc_create_handler[id] = handler; + g_umac_glb_obj->psoc_create_handler_arg[id] = arg; + + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_objmgr_unregister_psoc_create_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_psoc_create_handler handler, + void *arg) +{ + /* If id is not within valid range, return */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) { + qdf_print("%s: component %d is out of range\n", __func__, id); + return QDF_STATUS_MAXCOMP_FAIL; + } + qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); + /* If there is an invalid entry, return failure */ + if (g_umac_glb_obj->psoc_create_handler[id] != handler) { + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + qdf_print("%s:callback for comp %d is not registered\n", + __func__, id); + return QDF_STATUS_E_FAILURE; + } + /* Reset handlers, and args to NULL */ + g_umac_glb_obj->psoc_create_handler[id] = NULL; + g_umac_glb_obj->psoc_create_handler_arg[id] = NULL; + + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_objmgr_register_psoc_delete_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_psoc_delete_handler handler, + void *arg) +{ + /* If id is not within valid range, return */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) { + qdf_print("%s: component %d is out of range\n", __func__, id); + return QDF_STATUS_MAXCOMP_FAIL; + } + qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); + /* If there is a valid entry, return failure */ + if (g_umac_glb_obj->psoc_delete_handler[id] != NULL) { + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + qdf_print("%s:callback for comp %d is already registered\n", + __func__, id); + return QDF_STATUS_E_FAILURE; + } + /* Store handler and args in Global object table */ + g_umac_glb_obj->psoc_delete_handler[id] = handler; + g_umac_glb_obj->psoc_delete_handler_arg[id] = arg; + + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_objmgr_unregister_psoc_delete_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_psoc_delete_handler handler, + void *arg) +{ + /* If id is not within valid range, return */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) { + qdf_print("%s: component %d is out of range\n", __func__, id); + return QDF_STATUS_MAXCOMP_FAIL; + } + qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); + /* If there is an invalid entry, return failure */ + if (g_umac_glb_obj->psoc_delete_handler[id] != handler) { + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + qdf_print("%s:callback for comp %d is not registered\n", + __func__, id); + return QDF_STATUS_E_FAILURE; + } + /* Reset handlers, and args to NULL */ + g_umac_glb_obj->psoc_delete_handler[id] = NULL; + g_umac_glb_obj->psoc_delete_handler_arg[id] = NULL; + + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_objmgr_register_psoc_status_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_psoc_status_handler handler, + void *arg) +{ + /* If id is not within valid range, return */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) { + qdf_print("%s: component %d is out of range\n", __func__, id); + return QDF_STATUS_MAXCOMP_FAIL; + } + qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); + /* If there is a valid entry, return failure */ + if (g_umac_glb_obj->psoc_status_handler[id] != NULL) { + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + qdf_print("%s:callback for comp %d is already registered\n", + __func__, id); + return QDF_STATUS_E_FAILURE; + } + /* Store handler and args in Global object table */ + g_umac_glb_obj->psoc_status_handler[id] = handler; + g_umac_glb_obj->psoc_status_handler_arg[id] = arg; + + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_objmgr_unregister_psoc_status_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_psoc_status_handler handler, + void *arg) +{ + /* If id is not within valid range, return */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) { + qdf_print("%s: component %d is out of range\n", __func__, id); + return QDF_STATUS_MAXCOMP_FAIL; + } + qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); + /* If there is an invalid entry, return failure */ + if (g_umac_glb_obj->psoc_status_handler[id] != handler) { + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + qdf_print("%s:callback for comp %d is not registered\n", + __func__, id); + return QDF_STATUS_E_FAILURE; + } + /* Reset handlers, and args to NULL */ + g_umac_glb_obj->psoc_status_handler[id] = NULL; + g_umac_glb_obj->psoc_status_handler_arg[id] = NULL; + + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + return QDF_STATUS_SUCCESS; +} + + +QDF_STATUS wlan_objmgr_register_pdev_create_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_pdev_create_handler handler, + void *arg) +{ + /* If id is not within valid range, return */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) { + qdf_print("%s: component %d is out of range\n", __func__, id); + return QDF_STATUS_MAXCOMP_FAIL; + } + qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); + /* If there is a valid entry, return failure */ + if (g_umac_glb_obj->pdev_create_handler[id] != NULL) { + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + qdf_print("%s:callback for comp %d is already registered\n", + __func__, id); + return QDF_STATUS_E_FAILURE; + } + /* Store handler and args in Global object table */ + g_umac_glb_obj->pdev_create_handler[id] = handler; + g_umac_glb_obj->pdev_create_handler_arg[id] = arg; + + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_objmgr_unregister_pdev_create_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_pdev_create_handler handler, + void *arg) +{ + /* If id is not within valid range, return */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) { + qdf_print("%s: component %d is out of range\n", __func__, id); + return QDF_STATUS_MAXCOMP_FAIL; + } + qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); + /* If there is an invalid entry, return failure */ + if (g_umac_glb_obj->pdev_create_handler[id] != handler) { + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + qdf_print("%s:callback for comp %d is not registered\n", + __func__, id); + return QDF_STATUS_E_FAILURE; + } + /* Reset handlers, and args to NULL */ + g_umac_glb_obj->pdev_create_handler[id] = NULL; + g_umac_glb_obj->pdev_create_handler_arg[id] = NULL; + + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_objmgr_register_pdev_delete_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_pdev_delete_handler handler, + void *arg) +{ + /* If id is not within valid range, return */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) { + qdf_print("%s: component %d is out of range\n", __func__, id); + return QDF_STATUS_MAXCOMP_FAIL; + } + qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); + /* If there is a valid entry, return failure */ + if (g_umac_glb_obj->pdev_delete_handler[id] != NULL) { + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + qdf_print("%s:callback for comp %d is already registered\n", + __func__, id); + return QDF_STATUS_E_FAILURE; + } + /* Store handler and args in Global object table */ + g_umac_glb_obj->pdev_delete_handler[id] = handler; + g_umac_glb_obj->pdev_delete_handler_arg[id] = arg; + + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_objmgr_unregister_pdev_delete_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_pdev_delete_handler handler, + void *arg) +{ + /* If id is not within valid range, return */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) { + qdf_print("%s: component %d is out of range\n", __func__, id); + return QDF_STATUS_MAXCOMP_FAIL; + } + qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); + /* If there is an invalid entry, return failure */ + if (g_umac_glb_obj->pdev_delete_handler[id] != handler) { + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + qdf_print("%s:callback for component %d is not registered\n", + __func__, id); + return QDF_STATUS_E_FAILURE; + } + /* Reset handlers, and args to NULL */ + g_umac_glb_obj->pdev_delete_handler[id] = NULL; + g_umac_glb_obj->pdev_delete_handler_arg[id] = NULL; + + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_objmgr_register_pdev_status_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_pdev_status_handler handler, + void *arg) +{ + /* If id is not within valid range, return */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) { + qdf_print("%s: component %d is out of range\n", __func__, id); + return QDF_STATUS_MAXCOMP_FAIL; + } + qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); + /* If there is a valid entry, return failure */ + if (g_umac_glb_obj->pdev_status_handler[id] != NULL) { + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + qdf_print("%s:callback for comp %d is already registered\n", + __func__, id); + return QDF_STATUS_E_FAILURE; + } + /* Store handler and args in Global object table */ + g_umac_glb_obj->pdev_status_handler[id] = handler; + g_umac_glb_obj->pdev_status_handler_arg[id] = arg; + + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_objmgr_unregister_pdev_status_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_pdev_status_handler handler, + void *arg) +{ + /* If id is not within valid range, return */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) { + qdf_print("%s: component %d is out of range\n", __func__, id); + return QDF_STATUS_MAXCOMP_FAIL; + } + qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); + /* If there is an invalid entry, return failure */ + if (g_umac_glb_obj->pdev_status_handler[id] != handler) { + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + qdf_print("%s:callback for component %d is not registered\n", + __func__, id); + return QDF_STATUS_E_FAILURE; + } + /* Reset handlers, and args to NULL */ + g_umac_glb_obj->pdev_status_handler[id] = NULL; + g_umac_glb_obj->pdev_status_handler_arg[id] = NULL; + + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + return QDF_STATUS_SUCCESS; +} + + +QDF_STATUS wlan_objmgr_register_vdev_create_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_vdev_create_handler handler, + void *arg) +{ + /* If id is not within valid range, return */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) { + qdf_print("%s: component %d is out of range\n", __func__, id); + return QDF_STATUS_MAXCOMP_FAIL; + } + qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); + /* If there is a valid entry, return failure */ + if (g_umac_glb_obj->vdev_create_handler[id] != NULL) { + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + qdf_print("%s:callback for comp %d is already registered\n", + __func__, id); + return QDF_STATUS_E_FAILURE; + } + /* Store handler and args in Global object table */ + g_umac_glb_obj->vdev_create_handler[id] = handler; + g_umac_glb_obj->vdev_create_handler_arg[id] = arg; + + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_objmgr_unregister_vdev_create_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_vdev_create_handler handler, + void *arg) +{ + /* If id is not within valid range, return */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) { + qdf_print("%s: component %d is out of range\n", __func__, id); + return QDF_STATUS_MAXCOMP_FAIL; + } + qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); + /* If there is an invalid entry, return failure */ + if (g_umac_glb_obj->vdev_create_handler[id] != handler) { + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + qdf_print("%s:callback for comp %d is not registered\n", + __func__, id); + return QDF_STATUS_E_FAILURE; + } + /* Reset handlers, and args to NULL */ + g_umac_glb_obj->vdev_create_handler[id] = NULL; + g_umac_glb_obj->vdev_create_handler_arg[id] = NULL; + + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_objmgr_register_vdev_delete_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_vdev_delete_handler handler, + void *arg) +{ + /* If id is not within valid range, return */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) { + qdf_print("%s: component %d is out of range\n", __func__, id); + return QDF_STATUS_MAXCOMP_FAIL; + } + qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); + /* If there is a valid entry, return failure */ + if (g_umac_glb_obj->vdev_delete_handler[id] != NULL) { + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + qdf_print("%s:callback for comp %d is already registered\n", + __func__, id); + return QDF_STATUS_E_FAILURE; + } + /* Store handler and args in Global object table */ + g_umac_glb_obj->vdev_delete_handler[id] = handler; + g_umac_glb_obj->vdev_delete_handler_arg[id] = arg; + + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_objmgr_unregister_vdev_delete_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_vdev_delete_handler handler, + void *arg) +{ + /* If id is not within valid range, return */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) { + qdf_print("%s: component %d is out of range\n", __func__, id); + return QDF_STATUS_MAXCOMP_FAIL; + } + qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); + /* If there is an invalid entry, return failure */ + if (g_umac_glb_obj->vdev_delete_handler[id] != handler) { + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + qdf_print("%s:callback for comp %d is not registered\n", + __func__, id); + return QDF_STATUS_E_FAILURE; + } + /* Reset handlers, and args to NULL */ + g_umac_glb_obj->vdev_delete_handler[id] = NULL; + g_umac_glb_obj->vdev_delete_handler_arg[id] = NULL; + + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_objmgr_register_vdev_status_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_vdev_status_handler handler, + void *arg) +{ + /* If id is not within valid range, return */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) { + qdf_print("%s: component %d is out of range\n", __func__, id); + return QDF_STATUS_MAXCOMP_FAIL; + } + qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); + /* If there is a valid entry, return failure */ + if (g_umac_glb_obj->vdev_status_handler[id] != NULL) { + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + qdf_print("%s:callback for comp %d is already registered\n", + __func__, id); + return QDF_STATUS_E_FAILURE; + } + /* Store handler and args in Global object table */ + g_umac_glb_obj->vdev_status_handler[id] = handler; + g_umac_glb_obj->vdev_status_handler_arg[id] = arg; + + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_objmgr_unregister_vdev_status_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_vdev_status_handler handler, + void *arg) +{ + /* If id is not within valid range, return */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) { + qdf_print("%s: component %d is out of range\n", __func__, id); + return QDF_STATUS_MAXCOMP_FAIL; + } + qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); + /* If there is an invalid entry, return failure */ + if (g_umac_glb_obj->vdev_status_handler[id] != handler) { + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + qdf_print("%s:callback for component %d is not registered\n", + __func__, id); + return QDF_STATUS_E_FAILURE; + } + /* Reset handlers, and args to NULL */ + g_umac_glb_obj->vdev_status_handler[id] = NULL; + g_umac_glb_obj->vdev_status_handler_arg[id] = NULL; + + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + return QDF_STATUS_SUCCESS; +} + + +QDF_STATUS wlan_objmgr_register_peer_create_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_peer_create_handler handler, + void *arg) +{ + /* If id is not within valid range, return */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) { + qdf_print("%s: component %d is out of range\n", __func__, id); + return QDF_STATUS_MAXCOMP_FAIL; + } + qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); + /* If there is a valid entry, return failure */ + if (g_umac_glb_obj->peer_create_handler[id] != NULL) { + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + qdf_print("%s:callback for comp %d is already registered\n", + __func__, id); + return QDF_STATUS_E_FAILURE; + } + /* Store handler and args in Global object table */ + g_umac_glb_obj->peer_create_handler[id] = handler; + g_umac_glb_obj->peer_create_handler_arg[id] = arg; + + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + return QDF_STATUS_SUCCESS; +} + + +QDF_STATUS wlan_objmgr_unregister_peer_create_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_peer_create_handler handler, + void *arg) +{ + /* If id is not within valid range, return */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) { + qdf_print("%s: component %d is out of range\n", __func__, id); + return QDF_STATUS_MAXCOMP_FAIL; + } + qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); + /* If there is an invalid entry, return failure */ + if (g_umac_glb_obj->peer_create_handler[id] != handler) { + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + qdf_print("%s:callback for comp %d is not registered\n", + __func__, id); + return QDF_STATUS_E_FAILURE; + } + /* Reset handlers, and args to NULL */ + g_umac_glb_obj->peer_create_handler[id] = NULL; + g_umac_glb_obj->peer_create_handler_arg[id] = NULL; + + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_objmgr_register_peer_delete_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_peer_delete_handler handler, + void *arg) +{ + /* If id is not within valid range, return */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) { + qdf_print("%s: component %d is out of range\n", __func__, id); + return QDF_STATUS_MAXCOMP_FAIL; + } + qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); + /* If there is a valid entry, return failure */ + if (g_umac_glb_obj->peer_delete_handler[id] != NULL) { + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + qdf_print("%s:callback for comp %d is already registered\n", + __func__, id); + return QDF_STATUS_E_FAILURE; + } + /* Store handler and args in Global object table */ + g_umac_glb_obj->peer_delete_handler[id] = handler; + g_umac_glb_obj->peer_delete_handler_arg[id] = arg; + + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_objmgr_unregister_peer_delete_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_peer_delete_handler handler, + void *arg) +{ + /* If id is not within valid range, return */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) { + qdf_print("%s: component %d is out of range\n", __func__, id); + return QDF_STATUS_MAXCOMP_FAIL; + } + qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); + /* If there is an invalid entry, return failure */ + if (g_umac_glb_obj->peer_delete_handler[id] != handler) { + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + qdf_print("%s:callback for comp %d is not registered\n", + __func__, id); + return QDF_STATUS_E_FAILURE; + } + /* Reset handlers, and args to NULL */ + g_umac_glb_obj->peer_delete_handler[id] = NULL; + g_umac_glb_obj->peer_delete_handler_arg[id] = NULL; + + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_objmgr_register_peer_status_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_peer_status_handler handler, + void *arg) +{ + /* If id is not within valid range, return */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) { + qdf_print("%s: component %d is out of range\n", __func__, id); + return QDF_STATUS_MAXCOMP_FAIL; + } + qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); + /* If there is a valid entry, return failure */ + if (g_umac_glb_obj->peer_status_handler[id] != NULL) { + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + qdf_print("%s:callback for comp %d is already registered\n", + __func__, id); + return QDF_STATUS_E_FAILURE; + } + /* Store handler and args in Global object table */ + g_umac_glb_obj->peer_status_handler[id] = handler; + g_umac_glb_obj->peer_status_handler_arg[id] = arg; + + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_objmgr_unregister_peer_status_handler( + enum wlan_umac_comp_id id, + wlan_objmgr_peer_status_handler handler, + void *arg) +{ + /* If id is not within valid range, return */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) { + qdf_print("%s: component %d is out of range\n", __func__, id); + return QDF_STATUS_MAXCOMP_FAIL; + } + qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); + /* If there is an invalid entry, return failure */ + if (g_umac_glb_obj->peer_status_handler[id] != handler) { + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + qdf_print("%s:callback for comp %d is not registered\n", + __func__, id); + return QDF_STATUS_E_FAILURE; + } + /* Reset handlers, and args to NULL */ + g_umac_glb_obj->peer_status_handler[id] = NULL; + g_umac_glb_obj->peer_status_handler_arg[id] = NULL; + + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + return QDF_STATUS_SUCCESS; +} + + +QDF_STATUS wlan_objmgr_psoc_object_attach(struct wlan_objmgr_psoc *psoc) +{ + uint8_t index = 0; + QDF_STATUS status = QDF_STATUS_E_FAILURE; + + qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); + /* Find free slot in PSOC table, store the PSOC */ + while (index < WLAN_OBJMGR_MAX_DEVICES) { + if (g_umac_glb_obj->psoc[index] == NULL) { + /* Found free slot, store psoc */ + g_umac_glb_obj->psoc[index] = psoc; + status = QDF_STATUS_SUCCESS; + break; + } + index++; + } + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + return status; +} + +QDF_STATUS wlan_objmgr_psoc_object_detach(struct wlan_objmgr_psoc *psoc) +{ + uint8_t index = 0; + QDF_STATUS status = QDF_STATUS_E_FAILURE; + + qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); + while (index < WLAN_OBJMGR_MAX_DEVICES) { + if (g_umac_glb_obj->psoc[index] == psoc) { + /* found psoc, store NULL */ + g_umac_glb_obj->psoc[index] = NULL; + status = QDF_STATUS_SUCCESS; + break; + } + index++; + } + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + return status; +} + +QDF_STATUS wlan_objmgr_global_obj_can_deleted(void) +{ + uint8_t index = 0; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + qdf_spin_lock_bh(&g_umac_glb_obj->global_lock); + /* Check whether all PSOCs are freed */ + while (index < WLAN_OBJMGR_MAX_DEVICES) { + if (g_umac_glb_obj->psoc[index] != NULL) { + status = QDF_STATUS_E_FAILURE; + break; + } + index++; + } + qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock); + return status; +} +EXPORT_SYMBOL(wlan_objmgr_global_obj_can_deleted); diff --git a/umac/cmn_services/obj_mgr/src/wlan_objmgr_global_obj_i.h b/umac/cmn_services/obj_mgr/src/wlan_objmgr_global_obj_i.h new file mode 100644 index 0000000000..7206e4e665 --- /dev/null +++ b/umac/cmn_services/obj_mgr/src/wlan_objmgr_global_obj_i.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + /** + * DOC: Define the global data structure of UMAC + */ +#ifndef _WLAN_OBJMGR_GLOBAL_OBJ_I_H_ +#define _WLAN_OBJMGR_GLOBAL_OBJ_I_H_ + +#include "wlan_objmgr_cmn.h" +/** + * struct wlan_objmgr_global - Global object definition + * @psoc[]: Array of PSOCs to maintain PSOC's list, + * its optional + * @psoc_create_handler[]: PSOC create handler array + * @psoc_create_handler_arg[]: PSOC create handler args array + * @psoc_delete_handler[]: PSOC delete handler array + * @psoc_delete_handler_arg[]: PSOC delete handler args array + * @psoc_status_handler[]: PSOC status handler array + * @psoc_status_handler_arg[]: PSOC status handler args array + * @pdev_create_handler[]: PDEV create handler array + * @pdev_create_handler_arg[]: PDEV create handler args array + * @pdev_delete_handler[]: PDEV delete handler array + * @pdev_delete_handler_arg[]: PDEV delete handler args array + * @pdev_status_handler[]: PDEV status handler array + * @pdev_status_handler_arg[]: PDEV status handler args array + * @vdev_create_handler[]: VDEV create handler array + * @vdev_create_handler_arg[]: VDEV create handler args array + * @vdev_delete_handler[]: VDEV delete handler array + * @vdev_delete_handler_arg[]: VDEV delete handler args array + * @vdev_status_handler[]: VDEV status handler array + * @vdev_status_handler_arg[]: VDEV status handler args array + * @peer_create_handler[]: PEER create handler array + * @peer_create_handler_arg[]: PEER create handler args array + * @peer_delete_handler[]: PEER delete handler array + * @peer_delete_handler_arg[]: PEER delete handler args array + * @peer_status_handler[]: PEER status handler array + * @peer_status_handler_arg[]: PEER status handler args array + * @global_lock: Global lock + */ +struct wlan_objmgr_global { + struct wlan_objmgr_psoc *psoc[WLAN_OBJMGR_MAX_DEVICES]; + wlan_objmgr_psoc_create_handler + psoc_create_handler[WLAN_UMAC_MAX_COMPONENTS]; + void *psoc_create_handler_arg[WLAN_UMAC_MAX_COMPONENTS]; + wlan_objmgr_psoc_delete_handler + psoc_delete_handler[WLAN_UMAC_MAX_COMPONENTS]; + void *psoc_delete_handler_arg[WLAN_UMAC_MAX_COMPONENTS]; + wlan_objmgr_psoc_status_handler + psoc_status_handler[WLAN_UMAC_MAX_COMPONENTS]; + void *psoc_status_handler_arg[WLAN_UMAC_MAX_COMPONENTS]; + wlan_objmgr_pdev_create_handler + pdev_create_handler[WLAN_UMAC_MAX_COMPONENTS]; + void *pdev_create_handler_arg[WLAN_UMAC_MAX_COMPONENTS]; + wlan_objmgr_pdev_delete_handler + pdev_delete_handler[WLAN_UMAC_MAX_COMPONENTS]; + void *pdev_delete_handler_arg[WLAN_UMAC_MAX_COMPONENTS]; + wlan_objmgr_pdev_status_handler + pdev_status_handler[WLAN_UMAC_MAX_COMPONENTS]; + void *pdev_status_handler_arg[WLAN_UMAC_MAX_COMPONENTS]; + wlan_objmgr_vdev_create_handler + vdev_create_handler[WLAN_UMAC_MAX_COMPONENTS]; + void *vdev_create_handler_arg[WLAN_UMAC_MAX_COMPONENTS]; + wlan_objmgr_vdev_delete_handler + vdev_delete_handler[WLAN_UMAC_MAX_COMPONENTS]; + void *vdev_delete_handler_arg[WLAN_UMAC_MAX_COMPONENTS]; + wlan_objmgr_vdev_status_handler + vdev_status_handler[WLAN_UMAC_MAX_COMPONENTS]; + void *vdev_status_handler_arg[WLAN_UMAC_MAX_COMPONENTS]; + wlan_objmgr_peer_create_handler + peer_create_handler[WLAN_UMAC_MAX_COMPONENTS]; + void *peer_create_handler_arg[WLAN_UMAC_MAX_COMPONENTS]; + wlan_objmgr_peer_delete_handler + peer_delete_handler[WLAN_UMAC_MAX_COMPONENTS]; + void *peer_delete_handler_arg[WLAN_UMAC_MAX_COMPONENTS]; + wlan_objmgr_peer_status_handler + peer_status_handler[WLAN_UMAC_MAX_COMPONENTS]; + void *peer_status_handler_arg[WLAN_UMAC_MAX_COMPONENTS]; + qdf_spinlock_t global_lock; +}; + +#define MAX_SLEEP_ITERATION 5 + +extern struct wlan_objmgr_global *g_umac_glb_obj; + +#endif /* _WLAN_OBJMGR_GLOBAL_OBJ_I_H_ */ diff --git a/umac/cmn_services/obj_mgr/src/wlan_objmgr_pdev_obj.c b/umac/cmn_services/obj_mgr/src/wlan_objmgr_pdev_obj.c new file mode 100644 index 0000000000..1f2fdf968d --- /dev/null +++ b/umac/cmn_services/obj_mgr/src/wlan_objmgr_pdev_obj.c @@ -0,0 +1,628 @@ +/* + * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + /** + * DOC: Public APIs to perform operations on Global objects + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/** + ** APIs to Create/Delete Global object APIs + */ +static QDF_STATUS wlan_objmgr_pdev_object_status( + struct wlan_objmgr_pdev *pdev) +{ + uint8_t id; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + wlan_pdev_obj_lock(pdev); + /* Iterate through all components to derive the object status */ + for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { + /* If component disabled, Ignore */ + if (pdev->obj_status[id] == QDF_STATUS_COMP_DISABLED) { + continue; + /* If component operates in Async, status is Partially created, + break */ + } else if (pdev->obj_status[id] == QDF_STATUS_COMP_ASYNC) { + if (pdev->pdev_comp_obj[id] == NULL) { + status = QDF_STATUS_COMP_ASYNC; + break; + } + /* If component failed to allocate its object, treat it as + failure, complete object need to be cleaned up */ + } else if ((pdev->obj_status[id] == QDF_STATUS_E_NOMEM) || + (pdev->obj_status[id] == QDF_STATUS_E_FAILURE)) { + status = QDF_STATUS_E_FAILURE; + break; + } + } + wlan_pdev_obj_unlock(pdev); + return status; +} + +struct wlan_objmgr_pdev *wlan_objmgr_pdev_obj_create( + struct wlan_objmgr_psoc *psoc, void *osdev_priv) +{ + struct wlan_objmgr_pdev *pdev; + uint8_t id; + wlan_objmgr_pdev_create_handler handler; + wlan_objmgr_pdev_status_handler s_handler; + void *arg; + QDF_STATUS obj_status; + + if (psoc == NULL) { + qdf_print("%s:psoc is NULL\n", __func__); + return NULL; + } + /* Allocate PDEV object's memory */ + pdev = qdf_mem_malloc(sizeof(*pdev)); + if (pdev == NULL) { + qdf_print("%s:pdev alloc failed\n", __func__); + return NULL; + } + /* Attach PDEV with PSOC */ + if (wlan_objmgr_psoc_pdev_attach(psoc, pdev) + != QDF_STATUS_SUCCESS) { + qdf_print("%s:pdev psoc attach failed\n", __func__); + qdf_mem_free(pdev); + return NULL; + } + /* Save PSOC object pointer in PDEV */ + wlan_pdev_set_psoc(pdev, psoc); + /* Initialize PDEV spinlock */ + qdf_spinlock_create(&pdev->pdev_lock); + /* Initialize PDEV's VDEV list, assign default values */ + qdf_list_create(&pdev->pdev_objmgr.wlan_vdev_list, + WLAN_UMAC_PDEV_MAX_VDEVS); + pdev->pdev_objmgr.wlan_vdev_count = 0; + pdev->pdev_objmgr.max_vdev_count = WLAN_UMAC_PDEV_MAX_VDEVS; + /* Save HDD/OSIF pointer */ + pdev->pdev_nif.pdev_ospriv = osdev_priv; + + /* Invoke registered create handlers */ + for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { + handler = g_umac_glb_obj->pdev_create_handler[id]; + arg = g_umac_glb_obj->pdev_create_handler_arg[id]; + if (handler != NULL) + pdev->obj_status[id] = handler(pdev, arg); + else + pdev->obj_status[id] = QDF_STATUS_COMP_DISABLED; + } + /* Derive object status */ + obj_status = wlan_objmgr_pdev_object_status(pdev); + + if (obj_status == QDF_STATUS_SUCCESS) { + /* Object status is SUCCESS, Object is created */ + pdev->obj_state = WLAN_OBJ_STATE_CREATED; + /* Invoke component registered status handlers */ + for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { + s_handler = g_umac_glb_obj->pdev_status_handler[id]; + arg = g_umac_glb_obj->pdev_status_handler_arg[id]; + if (s_handler != NULL) { + s_handler(pdev, arg, + QDF_STATUS_SUCCESS); + } + } + /* Few components operates in Asynchrous communction, Object state + partially created */ + } else if (obj_status == QDF_STATUS_COMP_ASYNC) { + pdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED; + /* Component object failed to be created, clean up the object */ + } else if (obj_status == QDF_STATUS_E_FAILURE) { + /* Clean up the psoc */ + qdf_print("%s: PDEV component objects allocation failed\n", + __func__); + wlan_objmgr_pdev_obj_delete(pdev); + return NULL; + } + return pdev; +} +EXPORT_SYMBOL(wlan_objmgr_pdev_obj_create); + +QDF_STATUS wlan_objmgr_pdev_obj_delete(struct wlan_objmgr_pdev *pdev) +{ + uint8_t id; + wlan_objmgr_pdev_delete_handler handler; + QDF_STATUS obj_status; + void *arg; + + if (pdev == NULL) { + qdf_print("%s:pdev is NULL\n", __func__); + return QDF_STATUS_E_FAILURE; + } + + /* Invoke registered delete handlers */ + for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { + handler = g_umac_glb_obj->pdev_delete_handler[id]; + arg = g_umac_glb_obj->pdev_delete_handler_arg[id]; + if (handler != NULL) + pdev->obj_status[id] = handler(pdev, arg); + else + pdev->obj_status[id] = QDF_STATUS_COMP_DISABLED; + } + /* Derive object status */ + obj_status = wlan_objmgr_pdev_object_status(pdev); + + if (obj_status == QDF_STATUS_E_FAILURE) { + qdf_print("%s: PDEV component objects delete failed\n", + __func__); + /* Ideally should not happen */ + /* This leads to memleak ??? how to handle */ + QDF_BUG(0); + return QDF_STATUS_E_FAILURE; + } + /* Deletion is in progress */ + if (obj_status == QDF_STATUS_COMP_ASYNC) { + pdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_DELETED; + return QDF_STATUS_COMP_ASYNC; + } else { + /* Detach PDEV from PSOC PDEV's list */ + if (wlan_objmgr_psoc_pdev_detach(pdev->pdev_objmgr.wlan_psoc, + pdev) == + QDF_STATUS_E_FAILURE) { + qdf_print("%s: PSOC PDEV detach failed\n", + __func__); + return QDF_STATUS_E_FAILURE; + } + /* de-init lock */ + qdf_spinlock_destroy(&pdev->pdev_lock); + /* Free the memory */ + qdf_mem_free(pdev); + } + return QDF_STATUS_SUCCESS; +} +EXPORT_SYMBOL(wlan_objmgr_pdev_obj_delete); + +/** + ** APIs to attach/detach component objects + */ +QDF_STATUS wlan_objmgr_pdev_component_obj_attach( + struct wlan_objmgr_pdev *pdev, + enum wlan_umac_comp_id id, + void *comp_objptr, + QDF_STATUS status) +{ + uint8_t i; + wlan_objmgr_pdev_status_handler s_hlr; + void *a; + QDF_STATUS obj_status; + + /* component id is invalid */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) { + qdf_print("%s: component-id %d is not supported\n", + __func__, id); + return QDF_STATUS_MAXCOMP_FAIL; + } + wlan_pdev_obj_lock(pdev); + /* If there is a valid entry, return failure */ + if (pdev->pdev_comp_obj[id] != NULL) { + qdf_print("%s: component-%d already have valid pointer\n", + __func__, id); + wlan_pdev_obj_unlock(pdev); + return QDF_STATUS_E_FAILURE; + } + /* Save component's pointer and status */ + pdev->pdev_comp_obj[id] = comp_objptr; + pdev->obj_status[id] = status; + wlan_pdev_obj_unlock(pdev); + + if (pdev->obj_state != WLAN_OBJ_STATE_PARTIALLY_CREATED) + return QDF_STATUS_SUCCESS; + /* If PDEV object status is partially created means, this API is + invoked with differnt context, this block should be executed for async + components only */ + /* Derive status */ + obj_status = wlan_objmgr_pdev_object_status(pdev); + /* STATUS_SUCCESS means, object is CREATED */ + if (obj_status == QDF_STATUS_SUCCESS) + pdev->obj_state = WLAN_OBJ_STATE_CREATED; + /* update state as CREATION failed, caller has to delete the + PDEV object */ + else if (obj_status == QDF_STATUS_E_FAILURE) + pdev->obj_state = WLAN_OBJ_STATE_CREATION_FAILED; + /* Notify components about the CREATION success/failure */ + if ((obj_status == QDF_STATUS_SUCCESS) || + (obj_status == QDF_STATUS_E_FAILURE)) { + /* nofity object status */ + for (i = 0; i < WLAN_UMAC_MAX_COMPONENTS; i++) { + s_hlr = g_umac_glb_obj->pdev_status_handler[i]; + a = g_umac_glb_obj->pdev_status_handler_arg[i]; + if (s_hlr != NULL) + s_hlr(pdev, a, obj_status); + } + } + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_objmgr_pdev_component_obj_detach( + struct wlan_objmgr_pdev *pdev, + enum wlan_umac_comp_id id, + void *comp_objptr) +{ + QDF_STATUS obj_status; + + /* component id is invalid */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) + return QDF_STATUS_MAXCOMP_FAIL; + + wlan_pdev_obj_lock(pdev); + /* If there is a invalid entry, return failure */ + if (pdev->pdev_comp_obj[id] != comp_objptr) { + pdev->obj_status[id] = QDF_STATUS_E_FAILURE; + wlan_pdev_obj_unlock(pdev); + return QDF_STATUS_E_FAILURE; + } + /* Reset pointers to NULL, update the status*/ + pdev->pdev_comp_obj[id] = NULL; + pdev->obj_status[id] = QDF_STATUS_SUCCESS; + wlan_pdev_obj_unlock(pdev); + + /* If PDEV object status is partially deleted means, this API is + invoked with differnt context, this block should be executed for async + components only */ + if ((pdev->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) || + (pdev->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)) { + /* Derive object status */ + obj_status = wlan_objmgr_pdev_object_status(pdev); + if (obj_status == QDF_STATUS_SUCCESS) { + /*Update the status as Deleted, if full object + deletion is in progress */ + if (pdev->obj_state == + WLAN_OBJ_STATE_PARTIALLY_DELETED) + pdev->obj_state = WLAN_OBJ_STATE_DELETED; + /* Move to creation state, since this component + deletion alone requested */ + if (pdev->obj_state == + WLAN_OBJ_STATE_COMP_DEL_PROGRESS) + pdev->obj_state = WLAN_OBJ_STATE_CREATED; + /* Object status is failure */ + } else if (obj_status == QDF_STATUS_E_FAILURE) { + /*Update the status as Deletion failed, if full object + deletion is in progress */ + if (pdev->obj_state == + WLAN_OBJ_STATE_PARTIALLY_DELETED) + pdev->obj_state = + WLAN_OBJ_STATE_DELETION_FAILED; + /* Move to creation state, since this component + deletion alone requested (do not block other + components)*/ + if (pdev->obj_state == + WLAN_OBJ_STATE_COMP_DEL_PROGRESS) + pdev->obj_state = WLAN_OBJ_STATE_CREATED; + } + + /* Delete pdev object */ + if ((obj_status == QDF_STATUS_SUCCESS) && + (pdev->obj_state == WLAN_OBJ_STATE_DELETED)) { + /* Detach pdev object from psoc */ + if (wlan_objmgr_psoc_pdev_detach( + pdev->pdev_objmgr.wlan_psoc, pdev) == + QDF_STATUS_E_FAILURE) + return QDF_STATUS_E_FAILURE; + /* Destroy spinlock */ + qdf_spinlock_destroy(&pdev->pdev_lock); + /* Free PDEV memory */ + qdf_mem_free(pdev); + } + } + return QDF_STATUS_SUCCESS; +} + +/** + ** APIs to operations on pdev objects + */ +static void wlan_objmgr_pdev_vdev_iterate_peers(struct wlan_objmgr_pdev *pdev, + struct wlan_objmgr_vdev *vdev, + wlan_objmgr_pdev_op_handler handler, + void *arg, uint8_t lock_free_op) +{ + qdf_list_t *peer_list = NULL; + struct wlan_objmgr_peer *peer = NULL; + struct wlan_objmgr_peer *peer_next = NULL; + + /* Iterating through vdev's peer list, so lock is + needed */ + if (!lock_free_op) + wlan_vdev_obj_lock(vdev); + /* Get peer list of the vdev */ + peer_list = &vdev->vdev_objmgr.wlan_peer_list; + if (peer_list != NULL) { + peer = wlan_vdev_peer_list_peek_head(peer_list); + while (peer != NULL) { + /* Increment ref count, to hold the + peer pointer */ + wlan_objmgr_peer_ref_peer(peer); + /* Get next peer pointer */ + peer_next = wlan_peer_get_next_peer_of_vdev(peer_list, + peer); + /* Invoke the handler */ + handler(pdev, (void *)peer, arg); + /* Decrement ref count, this can lead + to peer deletion also */ + wlan_objmgr_peer_unref_peer(peer); + peer = peer_next; + } + } + if (!lock_free_op) + wlan_vdev_obj_unlock(vdev); +} + +QDF_STATUS wlan_objmgr_pdev_iterate_obj_list( + struct wlan_objmgr_pdev *pdev, + enum wlan_objmgr_obj_type obj_type, + wlan_objmgr_pdev_op_handler handler, + void *arg, uint8_t lock_free_op) +{ + struct wlan_objmgr_pdev_objmgr *objmgr = &pdev->pdev_objmgr; + qdf_list_t *vdev_list = NULL; + struct wlan_objmgr_vdev *vdev = NULL; + struct wlan_objmgr_vdev *vdev_next = NULL; + + /* If caller requests for lock free opeation, do not acquire + handler will handle the synchronization*/ + if (!lock_free_op) + wlan_pdev_obj_lock(pdev); + /* VDEV list */ + vdev_list = &objmgr->wlan_vdev_list; + switch (obj_type) { + case WLAN_VDEV_OP: + /* Iterate through all VDEV object, and invoke handler for each + VDEV object */ + vdev = wlan_pdev_vdev_list_peek_head(vdev_list); + while (vdev != NULL) { + /* TODO increment ref count */ + /* Get next vdev (handler can be invoked for + vdev deletion also */ + vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list, + vdev); + handler(pdev, (void *)vdev, arg); + vdev = vdev_next; + /* TODO decrement ref count */ + } + break; + case WLAN_PEER_OP: + vdev = wlan_pdev_vdev_list_peek_head(vdev_list); + while (vdev != NULL) { + /* TODO increment ref count */ + wlan_objmgr_pdev_vdev_iterate_peers(pdev, vdev, handler, + arg, lock_free_op); + /* Get Next VDEV */ + vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list, + vdev); + /* TODO decrement ref count */ + } + break; + default: + break; + } + if (!lock_free_op) + wlan_pdev_obj_unlock(pdev); + + return QDF_STATUS_SUCCESS; +} +EXPORT_SYMBOL(wlan_objmgr_pdev_iterate_obj_list); + +QDF_STATUS wlan_objmgr_trigger_pdev_comp_object_creation( + struct wlan_objmgr_pdev *pdev, + enum wlan_umac_comp_id id) +{ + wlan_objmgr_pdev_create_handler handler; + void *arg; + QDF_STATUS obj_status = QDF_STATUS_SUCCESS; + + /* Component id is invalid */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) + return QDF_STATUS_MAXCOMP_FAIL; + + wlan_pdev_obj_lock(pdev); + /* If component object is already created, delete old + component object, then invoke creation */ + if (pdev->pdev_comp_obj[id] != NULL) { + wlan_pdev_obj_unlock(pdev); + return QDF_STATUS_E_FAILURE; + } + wlan_pdev_obj_unlock(pdev); + + /* Invoke registered create handlers */ + handler = g_umac_glb_obj->pdev_create_handler[id]; + arg = g_umac_glb_obj->pdev_create_handler_arg[id]; + if (handler != NULL) + pdev->obj_status[id] = handler(pdev, arg); + else + return QDF_STATUS_E_FAILURE; + /* If object status is created, then only handle this object status */ + if (pdev->obj_state == WLAN_OBJ_STATE_CREATED) { + /* Derive object status */ + obj_status = wlan_objmgr_pdev_object_status(pdev); + /* Move PDEV object state to Partially created state */ + if (obj_status == QDF_STATUS_COMP_ASYNC) { + /*TODO atomic */ + pdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED; + } + } + return obj_status; +} + +QDF_STATUS wlan_objmgr_trigger_pdev_comp_object_deletion( + struct wlan_objmgr_pdev *pdev, + enum wlan_umac_comp_id id) +{ + wlan_objmgr_pdev_delete_handler handler; + void *arg; + QDF_STATUS obj_status = QDF_STATUS_SUCCESS; + + /* component id is invalid */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) + return QDF_STATUS_MAXCOMP_FAIL; + + wlan_pdev_obj_lock(pdev); + /* Component object was never created, invalid operation */ + if (pdev->pdev_comp_obj[id] == NULL) { + wlan_pdev_obj_unlock(pdev); + return QDF_STATUS_E_FAILURE; + } + wlan_pdev_obj_unlock(pdev); + + /* Invoke registered create handlers */ + handler = g_umac_glb_obj->pdev_delete_handler[id]; + arg = g_umac_glb_obj->pdev_delete_handler_arg[id]; + if (handler != NULL) + pdev->obj_status[id] = handler(pdev, arg); + else + return QDF_STATUS_E_FAILURE; + + /* If object status is created, then only handle this object status */ + if (pdev->obj_state == WLAN_OBJ_STATE_CREATED) { + obj_status = wlan_objmgr_pdev_object_status(pdev); + /* move object state to DEL progress */ + if (obj_status == QDF_STATUS_COMP_ASYNC) + pdev->obj_state = WLAN_OBJ_STATE_COMP_DEL_PROGRESS; + } + return obj_status; +} + +static void wlan_obj_pdev_vdevlist_add_tail(qdf_list_t *obj_list, + struct wlan_objmgr_vdev *obj) +{ + qdf_list_insert_back(obj_list, &obj->vdev_node); +} + +static QDF_STATUS wlan_obj_pdev_vdevlist_remove_vdev( + qdf_list_t *obj_list, + struct wlan_objmgr_vdev *vdev) +{ + qdf_list_node_t *vdev_node = NULL; + + if (vdev == NULL) + return QDF_STATUS_E_FAILURE; + /* get vdev list node element */ + vdev_node = &vdev->vdev_node; + /* list is empty, return failure */ + if (qdf_list_remove_node(obj_list, vdev_node) != QDF_STATUS_SUCCESS) + return QDF_STATUS_E_FAILURE; + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_objmgr_pdev_vdev_attach(struct wlan_objmgr_pdev *pdev, + struct wlan_objmgr_vdev *vdev) +{ + struct wlan_objmgr_pdev_objmgr *objmgr = &pdev->pdev_objmgr; + + wlan_pdev_obj_lock(pdev); + /* If Max vdev count exceeds, return failure */ + if (objmgr->wlan_vdev_count > objmgr->max_vdev_count) { + wlan_pdev_obj_unlock(pdev); + return QDF_STATUS_E_FAILURE; + } + /* Add vdev to pdev's vdev list */ + wlan_obj_pdev_vdevlist_add_tail(&objmgr->wlan_vdev_list, vdev); + /* Increment vdev count of pdev */ + objmgr->wlan_vdev_count++; + wlan_pdev_obj_unlock(pdev); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_objmgr_pdev_vdev_detach(struct wlan_objmgr_pdev *pdev, + struct wlan_objmgr_vdev *vdev) +{ + struct wlan_objmgr_pdev_objmgr *objmgr = &pdev->pdev_objmgr; + + wlan_pdev_obj_lock(pdev); + /* if vdev count is 0, return failure */ + if (objmgr->wlan_vdev_count == 0) { + wlan_pdev_obj_unlock(pdev); + return QDF_STATUS_E_FAILURE; + } + /* remove vdev from pdev's vdev list */ + wlan_obj_pdev_vdevlist_remove_vdev(&objmgr->wlan_vdev_list, vdev); + /* decrement vdev count */ + objmgr->wlan_vdev_count--; + + wlan_pdev_obj_unlock(pdev); + return QDF_STATUS_SUCCESS; +} + +struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_id_from_pdev( + struct wlan_objmgr_pdev *pdev, uint8_t vdev_id) +{ + struct wlan_objmgr_vdev *vdev; + struct wlan_objmgr_vdev *vdev_next; + struct wlan_objmgr_pdev_objmgr *objmgr; + qdf_list_t *vdev_list; + + wlan_pdev_obj_lock(pdev); + + objmgr = &pdev->pdev_objmgr; + vdev_list = &objmgr->wlan_vdev_list; + /* Get first vdev */ + vdev = wlan_pdev_vdev_list_peek_head(vdev_list); + /* Iterate through pdev's vdev list, till vdev id matches with + entry of vdev list */ + while (vdev != NULL) { + if (wlan_vdev_get_id(vdev) == vdev_id) { + wlan_pdev_obj_unlock(pdev); + return vdev; + } + /* get next vdev */ + vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list, vdev); + vdev = vdev_next; + } + wlan_pdev_obj_unlock(pdev); + return NULL; +} +EXPORT_SYMBOL(wlan_objmgr_find_vdev_by_id_from_pdev); + +struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_macaddr_from_pdev( + struct wlan_objmgr_pdev *pdev, uint8_t *macaddr) +{ + struct wlan_objmgr_vdev *vdev; + struct wlan_objmgr_vdev *vdev_next; + struct wlan_objmgr_pdev_objmgr *objmgr; + qdf_list_t *vdev_list; + + wlan_pdev_obj_lock(pdev); + objmgr = &pdev->pdev_objmgr; + vdev_list = &objmgr->wlan_vdev_list; + /* Get first vdev */ + vdev = wlan_pdev_vdev_list_peek_head(vdev_list); + /* Iterate through pdev's vdev list, till vdev macaddr matches with + entry of vdev list */ + while (vdev != NULL) { + if (WLAN_ADDR_EQ(wlan_vdev_mlme_get_macaddr(vdev), macaddr) + == QDF_STATUS_SUCCESS) { + wlan_pdev_obj_unlock(pdev); + return vdev; + } + /* get next vdev */ + vdev_next = wlan_vdev_get_next_vdev_of_pdev(vdev_list, vdev); + vdev = vdev_next; + } + wlan_pdev_obj_unlock(pdev); + return NULL; +} diff --git a/umac/cmn_services/obj_mgr/src/wlan_objmgr_pdev_obj_i.h b/umac/cmn_services/obj_mgr/src/wlan_objmgr_pdev_obj_i.h new file mode 100644 index 0000000000..8c0bc8e096 --- /dev/null +++ b/umac/cmn_services/obj_mgr/src/wlan_objmgr_pdev_obj_i.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + /** + * DOC: Public APIs to perform operations on PDEV object + */ +#ifndef _WLAN_OBJMGR_PDEV_OBJ_I_H_ +#define _WLAN_OBJMGR_PDEV_OBJ_I_H_ + +/** + * wlan_objmgr_pdev_vdev_attach() - attach vdev to pdev + * @pdev: PDEV object + * @vdev: VDEV object + * + * API to be used for adding the VDEV object in PDEV's VDEV object list + * + * Return: SUCCESS on successful storing of VDEV object + * FAILURE + */ +QDF_STATUS wlan_objmgr_pdev_vdev_attach(struct wlan_objmgr_pdev *pdev, + struct wlan_objmgr_vdev *vdev); + +/** + * wlan_objmgr_pdev_vdev_detach() - detach vdev from pdev + * @pdev: PDEV object + * @vdev: VDEV object + * + * API to be used for removing the VDEV object from PDEV's VDEV object list + * + * Return: SUCCESS on successful removal of VDEV object + * FAILURE + */ +QDF_STATUS wlan_objmgr_pdev_vdev_detach(struct wlan_objmgr_pdev *pdev, + struct wlan_objmgr_vdev *vdev); + +#endif /* _WLAN_OBJMGR_PDEV_OBJ_I_H_*/ diff --git a/umac/cmn_services/obj_mgr/src/wlan_objmgr_peer_obj.c b/umac/cmn_services/obj_mgr/src/wlan_objmgr_peer_obj.c new file mode 100644 index 0000000000..588b9db916 --- /dev/null +++ b/umac/cmn_services/obj_mgr/src/wlan_objmgr_peer_obj.c @@ -0,0 +1,463 @@ +/* + * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + /** + * DOC: Public APIs to perform operations on Peer object + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/** + ** APIs to Create/Delete Peer object APIs + */ +static QDF_STATUS wlan_objmgr_peer_object_status( + struct wlan_objmgr_peer *peer) +{ + uint8_t id; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + wlan_peer_obj_lock(peer); + /* Iterate through all components to derive the object status */ + for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { + /* If component disabled, Ignore */ + if (peer->obj_status[id] == QDF_STATUS_COMP_DISABLED) + continue; + /* If component operates in Async, status is Partially created, + break */ + else if (peer->obj_status[id] == QDF_STATUS_COMP_ASYNC) { + if (peer->peer_comp_obj[id] == NULL) { + status = QDF_STATUS_COMP_ASYNC; + break; + } + /* If component failed to allocate its object, treat it as + failure, complete object need to be cleaned up */ + } else if ((peer->obj_status[id] == QDF_STATUS_E_NOMEM) || + (peer->obj_status[id] == QDF_STATUS_E_FAILURE)) { + status = QDF_STATUS_E_FAILURE; + break; + } + } + wlan_peer_obj_unlock(peer); + return status; +} + +struct wlan_objmgr_peer *wlan_objmgr_peer_obj_create( + struct wlan_objmgr_vdev *vdev, + enum wlan_peer_type type, + uint8_t *macaddr) +{ + struct wlan_objmgr_peer *peer; + struct wlan_objmgr_psoc *psoc; + wlan_objmgr_peer_create_handler handler; + wlan_objmgr_peer_status_handler stat_handler; + void *arg; + QDF_STATUS obj_status; + uint8_t id; + + if (vdev == NULL) { + qdf_print("%s: VDEV is NULL\n", __func__); + return NULL; + } + /* Get psoc, if psoc is NULL, return */ + psoc = wlan_vdev_get_psoc(vdev); + if (psoc == NULL) { + qdf_print("%s: PSOC is NULL\n", __func__); + return NULL; + } + /* Allocate memory for peer object */ + peer = qdf_mem_malloc(sizeof(*peer)); + if (peer == NULL) { + qdf_print("%s: Peer allocation failure\n", __func__); + return NULL; + } + /* set vdev to peer */ + wlan_peer_set_vdev(peer, vdev); + /* set peer type */ + wlan_peer_set_peer_type(peer, type); + /* set mac address of peer */ + wlan_peer_set_macaddr(peer, macaddr); + /* Attach peer to psoc, psoc maintains the node table for the device */ + if (wlan_objmgr_psoc_peer_attach(psoc, peer) != + QDF_STATUS_SUCCESS) { + qdf_print("%s: Peer PSOC attach failure\n", __func__); + qdf_mem_free(peer); + return NULL; + } + /* Attach peer to vdev peer table */ + if (wlan_objmgr_vdev_peer_attach(vdev, peer) != + QDF_STATUS_SUCCESS) { + qdf_print("%s: Peer VDEV attach failure\n", __func__); + /* if attach fails, detach from psoc table before free */ + wlan_objmgr_psoc_peer_detach(psoc, peer); + qdf_mem_free(peer); + return NULL; + } + /* init spinlock */ + qdf_spinlock_create(&peer->peer_lock); + /* Increment ref count for BSS peer, so that BSS peer deletes last*/ + if ((type == WLAN_PEER_STA) || (type == WLAN_PEER_STA_TEMP)) + wlan_objmgr_peer_ref_peer(wlan_vdev_get_bsspeer(vdev)); + /* TODO init other parameters */ + /* Invoke registered create handlers */ + for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { + handler = g_umac_glb_obj->peer_create_handler[id]; + arg = g_umac_glb_obj->peer_create_handler_arg[id]; + if (handler != NULL) + peer->obj_status[id] = handler(peer, arg); + else + peer->obj_status[id] = QDF_STATUS_COMP_DISABLED; + } + /* derive the object status */ + obj_status = wlan_objmgr_peer_object_status(peer); + /* If SUCCESS, Object is created */ + if (obj_status == QDF_STATUS_SUCCESS) { + peer->obj_state = WLAN_OBJ_STATE_CREATED; + for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { + stat_handler = g_umac_glb_obj->peer_status_handler[id]; + arg = g_umac_glb_obj->peer_status_handler_arg[id]; + if (stat_handler != NULL) + stat_handler(peer, arg, + QDF_STATUS_SUCCESS); + } + } else if (obj_status == QDF_STATUS_COMP_ASYNC) { + /* If any component operates in different context, update it + as partially created */ + peer->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED; + } else if (obj_status == QDF_STATUS_E_FAILURE) { + /* Clean up the peer */ + qdf_print("%s: Peer component object alloc failure\n", + __func__); + wlan_objmgr_peer_obj_delete(peer); + return NULL; + } + return peer; +} + +QDF_STATUS wlan_objmgr_peer_obj_delete(struct wlan_objmgr_peer *peer) +{ + uint8_t id; + wlan_objmgr_peer_delete_handler handler; + QDF_STATUS obj_status; + void *arg; + struct wlan_objmgr_psoc *psoc; + struct wlan_objmgr_vdev *vdev; + + if (peer == NULL) { + qdf_print("%s: PEER is NULL\n", __func__); + return QDF_STATUS_E_FAILURE; + } + /* get VDEV from peer, if it is NULL, return */ + vdev = wlan_peer_get_vdev(peer); + if (vdev == NULL) { + qdf_print("%s: VDEV is NULL\n", __func__); + return QDF_STATUS_E_FAILURE; + } + /* get PSOC from VDEV, if it is NULL, return */ + psoc = wlan_vdev_get_psoc(vdev); + if (psoc == NULL) { + qdf_print("%s: PSOC is NULL\n", __func__); + return QDF_STATUS_E_FAILURE; + } + /* Decrement ref count for BSS peer, so that BSS peer deletes last*/ + if ((wlan_peer_get_peer_type(peer) == WLAN_PEER_STA) || + (wlan_peer_get_peer_type(peer) == WLAN_PEER_STA_TEMP)) + wlan_objmgr_peer_unref_peer(wlan_vdev_get_bsspeer(vdev)); + + /* Invoke registered delete handlers */ + for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { + handler = g_umac_glb_obj->peer_delete_handler[id]; + arg = g_umac_glb_obj->peer_delete_handler_arg[id]; + if (handler != NULL) + peer->obj_status[id] = handler(peer, arg); + else + peer->obj_status[id] = QDF_STATUS_COMP_DISABLED; + } + /* Derive the object status */ + obj_status = wlan_objmgr_peer_object_status(peer); + if (obj_status == QDF_STATUS_E_FAILURE) { + /* If it status is failure, memory will not be freed */ + QDF_BUG(0); + return QDF_STATUS_E_FAILURE; + } + /* few components deletion is in progress */ + if (obj_status == QDF_STATUS_COMP_ASYNC) { + peer->obj_state = WLAN_OBJ_STATE_PARTIALLY_DELETED; + return QDF_STATUS_COMP_ASYNC; + } else { + /* Detach peer from VDEV's peer list */ + if (wlan_objmgr_vdev_peer_detach(vdev, peer) + == QDF_STATUS_E_FAILURE) { + qdf_print("%s: Peer VDEV detach failure\n", __func__); + return QDF_STATUS_E_FAILURE; + } + /* Detach peer from PSOC's peer list */ + if (wlan_objmgr_psoc_peer_detach(psoc, peer) + == QDF_STATUS_E_FAILURE) { + qdf_print("%s: Peer PSOC detach failure\n", __func__); + return QDF_STATUS_E_FAILURE; + } + /* destroy spinlock */ + qdf_spinlock_destroy(&peer->peer_lock); + /* Free memory */ + qdf_mem_free(peer); + } + return QDF_STATUS_SUCCESS; +} + +/** + ** APIs to attach/detach component objects + */ +QDF_STATUS wlan_objmgr_peer_component_obj_attach( + struct wlan_objmgr_peer *peer, + enum wlan_umac_comp_id id, + void *comp_objptr, + QDF_STATUS status) +{ + wlan_objmgr_peer_status_handler s_hler; + void *arg; + uint8_t i; + QDF_STATUS obj_status; + + /* component id is invalid */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) + return QDF_STATUS_MAXCOMP_FAIL; + + wlan_peer_obj_lock(peer); + /* If there is a valid entry, return failure, + valid object needs to be freed first */ + if (peer->peer_comp_obj[id] != NULL) { + wlan_peer_obj_unlock(peer); + return QDF_STATUS_E_FAILURE; + } + /* Assign component object pointer(can be NULL also), status */ + peer->peer_comp_obj[id] = comp_objptr; + peer->obj_status[id] = status; + wlan_peer_obj_unlock(peer); + + if (peer->obj_state != WLAN_OBJ_STATE_PARTIALLY_CREATED) + return QDF_STATUS_SUCCESS; + + /* If PEER object status is partially created means, this API is + invoked with differnt context. this block should be executed for async + components only */ + /* Derive status */ + obj_status = wlan_objmgr_peer_object_status(peer); + /* STATUS_SUCCESS means, object is CREATED */ + if (obj_status == QDF_STATUS_SUCCESS) + peer->obj_state = WLAN_OBJ_STATE_CREATED; + /* update state as CREATION failed, caller has to delete the + PEER object */ + else if (obj_status == QDF_STATUS_E_FAILURE) + peer->obj_state = WLAN_OBJ_STATE_CREATION_FAILED; + /* Notify components about the CREATION success/failure */ + if ((obj_status == QDF_STATUS_SUCCESS) || + (obj_status == QDF_STATUS_E_FAILURE)) { + /* nofity object status */ + for (i = 0; i < WLAN_UMAC_MAX_COMPONENTS; i++) { + s_hler = g_umac_glb_obj->peer_status_handler[i]; + arg = g_umac_glb_obj->peer_status_handler_arg[i]; + if (s_hler != NULL) + s_hler(peer, arg, obj_status); + } + } + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_objmgr_peer_component_obj_detach( + struct wlan_objmgr_peer *peer, + enum wlan_umac_comp_id id, + void *comp_objptr) +{ + QDF_STATUS obj_status; + struct wlan_objmgr_psoc *psoc; + struct wlan_objmgr_vdev *vdev; + + /* component id is invalid */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) + return QDF_STATUS_MAXCOMP_FAIL; + + /* get VDEV from peer, if it is NULL, return */ + vdev = wlan_peer_get_vdev(peer); + if (vdev == NULL) { + qdf_print("%s: VDEV is NULL\n", __func__); + return QDF_STATUS_E_FAILURE; + } + + /* get PSOC from VDEV, if it is NULL, return */ + psoc = wlan_vdev_get_psoc(vdev); + if (psoc == NULL) { + qdf_print("%s: PSOC is NULL\n", __func__); + return QDF_STATUS_E_FAILURE; + } + + wlan_peer_obj_lock(peer); + /* If there is a invalid entry, return failure */ + if (peer->peer_comp_obj[id] != comp_objptr) { + peer->obj_status[id] = QDF_STATUS_E_FAILURE; + wlan_peer_obj_unlock(peer); + return QDF_STATUS_E_FAILURE; + } + /* Reset the pointer to NULL */ + peer->peer_comp_obj[id] = NULL; + peer->obj_status[id] = QDF_STATUS_SUCCESS; + wlan_peer_obj_unlock(peer); + + /* If PEER object status is partially deleted means, this API is + invoked with differnt context, this block should be executed for async + components only */ + if ((peer->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) || + (peer->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)) { + /* Derive object status */ + obj_status = wlan_objmgr_peer_object_status(peer); + if (obj_status == QDF_STATUS_SUCCESS) { + /*Update the status as Deleted, if full object + deletion is in progress */ + if (peer->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) + peer->obj_state = WLAN_OBJ_STATE_DELETED; + /* Move to creation state, since this component + deletion alone requested */ + if (peer->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS) + peer->obj_state = WLAN_OBJ_STATE_CREATED; + /* Object status is failure */ + } else if (obj_status == QDF_STATUS_E_FAILURE) { + /*Update the status as Deletion failed, if full object + deletion is in progress */ + if (peer->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) + peer->obj_state = + WLAN_OBJ_STATE_DELETION_FAILED; + /* Move to creation state, since this component + deletion alone requested (do not block other + components) */ + if (peer->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS) + peer->obj_state = WLAN_OBJ_STATE_CREATED; + } + + /* Delete peer object */ + if ((obj_status == QDF_STATUS_SUCCESS) && + (peer->obj_state == WLAN_OBJ_STATE_DELETED)) { + /* delete peer from vdev's peer list */ + if (wlan_objmgr_vdev_peer_detach(vdev, peer) == + QDF_STATUS_E_FAILURE) + return QDF_STATUS_E_FAILURE; + + /* delete peer from psoc's peer list */ + if (wlan_objmgr_psoc_peer_detach(psoc, peer) == + QDF_STATUS_E_FAILURE) + return QDF_STATUS_E_FAILURE; + /* Destroy spinlock */ + qdf_spinlock_destroy(&peer->peer_lock); + /* free memory */ + qdf_mem_free(peer); + return QDF_STATUS_SUCCESS; + } + } + return QDF_STATUS_SUCCESS; +} + + +QDF_STATUS wlan_objmgr_trigger_peer_comp_object_creation( + struct wlan_objmgr_peer *peer, + enum wlan_umac_comp_id id) +{ + wlan_objmgr_peer_create_handler handler; + void *arg; + QDF_STATUS obj_status = QDF_STATUS_SUCCESS; + + /* Component id is invalid */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) + return QDF_STATUS_MAXCOMP_FAIL; + + wlan_peer_obj_lock(peer); + /* If component object is already created, delete old + component object, then invoke creation */ + if (peer->peer_comp_obj[id] != NULL) { + wlan_peer_obj_unlock(peer); + return QDF_STATUS_E_FAILURE; + } + wlan_peer_obj_unlock(peer); + + /* Invoke registered create handlers */ + handler = g_umac_glb_obj->peer_create_handler[id]; + arg = g_umac_glb_obj->peer_create_handler_arg[id]; + if (handler != NULL) + peer->obj_status[id] = handler(peer, arg); + else + return QDF_STATUS_E_FAILURE; + + /* If object status is created, then only handle this object status */ + if (peer->obj_state == WLAN_OBJ_STATE_CREATED) { + /* Derive object status */ + obj_status = wlan_objmgr_peer_object_status(peer); + /* Move PDEV object state to Partially created state */ + if (obj_status == QDF_STATUS_COMP_ASYNC) { + /*TODO atomic */ + peer->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED; + } + } + + return obj_status; +} + + +QDF_STATUS wlan_objmgr_trigger_peer_comp_object_deletion( + struct wlan_objmgr_peer *peer, + enum wlan_umac_comp_id id) +{ + wlan_objmgr_peer_delete_handler handler; + void *arg; + QDF_STATUS obj_status = QDF_STATUS_SUCCESS; + + /* component id is invalid */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) + return QDF_STATUS_MAXCOMP_FAIL; + + wlan_peer_obj_lock(peer); + /* Component object was never created, invalid operation */ + if (peer->peer_comp_obj[id] == NULL) { + wlan_peer_obj_unlock(peer); + return QDF_STATUS_E_FAILURE; + } + + wlan_peer_obj_unlock(peer); + + /* Invoke registered delete handlers */ + handler = g_umac_glb_obj->peer_delete_handler[id]; + arg = g_umac_glb_obj->peer_delete_handler_arg[id]; + if (handler != NULL) + peer->obj_status[id] = handler(peer, arg); + else + return QDF_STATUS_E_FAILURE; + + /* If object status is created, then only handle this object status */ + if (peer->obj_state == WLAN_OBJ_STATE_CREATED) { + obj_status = wlan_objmgr_peer_object_status(peer); + /* move object state to DEL progress */ + if (obj_status == QDF_STATUS_COMP_ASYNC) + peer->obj_state = WLAN_OBJ_STATE_COMP_DEL_PROGRESS; + } + return obj_status; +} diff --git a/umac/cmn_services/obj_mgr/src/wlan_objmgr_psoc_obj.c b/umac/cmn_services/obj_mgr/src/wlan_objmgr_psoc_obj.c new file mode 100644 index 0000000000..5a6a39dc77 --- /dev/null +++ b/umac/cmn_services/obj_mgr/src/wlan_objmgr_psoc_obj.c @@ -0,0 +1,880 @@ +/* + * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + /** + * DOC: Public APIs to perform operations on Global objects + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + ** APIs to Create/Delete Global object APIs + */ +static QDF_STATUS wlan_objmgr_psoc_object_status( + struct wlan_objmgr_psoc *psoc) +{ + uint8_t id; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + wlan_psoc_obj_lock(psoc); + /* Iterate through all components to derive the object status */ + for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { + /* If component disabled, Ignore */ + if (psoc->obj_status[id] == QDF_STATUS_COMP_DISABLED) + continue; + /* If component operates in Async, status is Partially created, + break */ + else if (psoc->obj_status[id] == QDF_STATUS_COMP_ASYNC) { + if (psoc->soc_comp_obj[id] == NULL) { + status = QDF_STATUS_COMP_ASYNC; + break; + } + /* + * If component failed to allocate its object, treat it as + * failure, complete object need to be cleaned up + */ + } else if ((psoc->obj_status[id] == QDF_STATUS_E_NOMEM) || + (psoc->obj_status[id] == QDF_STATUS_E_FAILURE)) { + status = QDF_STATUS_E_FAILURE; + break; + } + } + wlan_psoc_obj_unlock(psoc); + return status; +} + +static void wlan_objmgr_psoc_peer_list_init(struct wlan_peer_list *peer_list) +{ + uint8_t i; + + qdf_spinlock_create(&peer_list->peer_list_lock); + for (i = 0; i < WLAN_PEER_HASHSIZE; i++) + qdf_list_create(&peer_list->peer_hash[i], + WLAN_UMAC_PSOC_MAX_PEERS); +} + +static void wlan_objmgr_psoc_peer_list_deinit(struct wlan_peer_list *peer_list) +{ + uint8_t i; + + /* deinit the lock */ + qdf_spinlock_destroy(&peer_list->peer_list_lock); + for (i = 0; i < WLAN_PEER_HASHSIZE; i++) + qdf_list_destroy(&peer_list->peer_hash[i]); +} +/* + * wlan_objmgr_psco_create_handler would return following status values + */ +struct wlan_objmgr_psoc *wlan_objmgr_psoc_obj_create(uint32_t phy_version, + WLAN_DEV_TYPE dev_type) +{ + uint8_t id; + struct wlan_objmgr_psoc *psoc = NULL; + wlan_objmgr_psoc_create_handler handler; + wlan_objmgr_psoc_status_handler stat_handler; + struct wlan_objmgr_psoc_objmgr *objmgr; + QDF_STATUS obj_status; + void *arg; + + /* Allocate PSOC object's memory */ + psoc = qdf_mem_malloc(sizeof(*psoc)); + if (psoc == NULL) { + qdf_print("%s: PSOC allocation failed\n", __func__); + return NULL; + } + /* Init spinlock */ + qdf_spinlock_create(&psoc->psoc_lock); + /* Initialize with default values */ + objmgr = &psoc->soc_objmgr; + objmgr->wlan_pdev_count = 0; + objmgr->wlan_vdev_count = 0; + objmgr->max_vdev_count = WLAN_UMAC_PSOC_MAX_VDEVS; + objmgr->wlan_peer_count = 0; + /* set phy version, dev_type in psoc */ + wlan_psoc_set_nif_phy_version(psoc, phy_version); + wlan_psoc_set_dev_type(psoc, dev_type); + /* Initialize peer list */ + wlan_objmgr_psoc_peer_list_init(&objmgr->peer_list); + /* Invoke registered create handlers */ + for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { + handler = g_umac_glb_obj->psoc_create_handler[id]; + arg = g_umac_glb_obj->psoc_create_handler_arg[id]; + if (handler != NULL) + psoc->obj_status[id] = handler(psoc, arg); + else + psoc->obj_status[id] = QDF_STATUS_COMP_DISABLED; + } + /* Derive object status */ + obj_status = wlan_objmgr_psoc_object_status(psoc); + + if (obj_status == QDF_STATUS_SUCCESS) { + /* Object status is SUCCESS, Object is created */ + psoc->obj_state = WLAN_OBJ_STATE_CREATED; + for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { + stat_handler = g_umac_glb_obj->psoc_status_handler[id]; + arg = g_umac_glb_obj->psoc_status_handler_arg[id]; + if (stat_handler != NULL) + stat_handler(psoc, arg, + QDF_STATUS_SUCCESS); + } + /* + * Few components operates in Asynchrous communction, Object state + * partially created + */ + } else if (obj_status == QDF_STATUS_COMP_ASYNC) { + psoc->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED; + /* Component object failed to be created, clean up the object */ + } else if (obj_status == QDF_STATUS_E_FAILURE) { + qdf_print("%s: PSOC component objects allocation failed\n", + __func__); + /* Clean up the psoc */ + wlan_objmgr_psoc_obj_delete(psoc); + return NULL; + } + + if (wlan_objmgr_psoc_object_attach(psoc) != + QDF_STATUS_SUCCESS) { + qdf_print("%s: PSOC object attach failed\n", __func__); + wlan_objmgr_psoc_obj_delete(psoc); + return NULL; + } + return psoc; +} +EXPORT_SYMBOL(wlan_objmgr_psoc_obj_create); + +QDF_STATUS wlan_objmgr_psoc_obj_delete(struct wlan_objmgr_psoc *psoc) +{ + uint8_t id; + wlan_objmgr_psoc_delete_handler handler; + QDF_STATUS obj_status; + void *arg; + + /* if PSOC is NULL, return */ + if (psoc == NULL) { + qdf_print("%s:psoc is NULL\n", __func__); + return QDF_STATUS_E_FAILURE; + } + + /* Invoke registered create handlers */ + for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { + handler = g_umac_glb_obj->psoc_delete_handler[id]; + arg = g_umac_glb_obj->psoc_delete_handler_arg[id]; + if (handler != NULL) + psoc->obj_status[id] = handler(psoc, arg); + else + psoc->obj_status[id] = QDF_STATUS_COMP_DISABLED; + } + /* Derive object status */ + obj_status = wlan_objmgr_psoc_object_status(psoc); + + if (obj_status == QDF_STATUS_E_FAILURE) { + qdf_print("%s: PSOC component object free failed\n", __func__); + /* Ideally should not happen */ + /*This leads to memleak ??? how to handle */ + QDF_BUG(0); + return QDF_STATUS_E_FAILURE; + } + /* Deletion is in progress */ + if (obj_status == QDF_STATUS_COMP_ASYNC) { + psoc->obj_state = WLAN_OBJ_STATE_PARTIALLY_DELETED; + return QDF_STATUS_COMP_ASYNC; + } else { + /* Detach PSOC from global object's psoc list */ + if (wlan_objmgr_psoc_object_detach(psoc) == + QDF_STATUS_E_FAILURE) { + qdf_print("%s: PSOC object detach failed\n", __func__); + return QDF_STATUS_E_FAILURE; + } + wlan_objmgr_psoc_peer_list_deinit(&psoc->soc_objmgr.peer_list); + /* Destroy spinlock */ + qdf_spinlock_destroy(&psoc->psoc_lock); + /* Free the memory */ + qdf_mem_free(psoc); + } + return QDF_STATUS_SUCCESS; +} +EXPORT_SYMBOL(wlan_objmgr_psoc_obj_delete); + +/** + ** APIs to attach/detach component objects + */ +QDF_STATUS wlan_objmgr_psoc_component_obj_attach( + struct wlan_objmgr_psoc *psoc, + enum wlan_umac_comp_id id, + void *comp_objptr, + QDF_STATUS status) +{ + wlan_objmgr_psoc_status_handler stat_handler; + void *arg = NULL; + QDF_STATUS obj_status; + uint8_t i; + + /* component id is invalid */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) + return QDF_STATUS_MAXCOMP_FAIL; + + wlan_psoc_obj_lock(psoc); + /* If there is a valid entry, return failure */ + if (psoc->soc_comp_obj[id] != NULL) { + wlan_psoc_obj_unlock(psoc); + return QDF_STATUS_E_FAILURE; + } + /* Save component's pointer and status */ + psoc->soc_comp_obj[id] = comp_objptr; + psoc->obj_status[id] = status; + wlan_psoc_obj_unlock(psoc); + + if (psoc->obj_state != WLAN_OBJ_STATE_PARTIALLY_CREATED) + return QDF_STATUS_SUCCESS; + /* If PSOC object status is partially created means, this API is + * invoked with differnt context, this block should be executed for + * async components only + */ + /* Derive status */ + obj_status = wlan_objmgr_psoc_object_status(psoc); + /* STATUS_SUCCESS means, object is CREATED */ + if (obj_status == QDF_STATUS_SUCCESS) + psoc->obj_state = WLAN_OBJ_STATE_CREATED; + /* update state as CREATION failed, caller has to delete the + * PSOC object + */ + else if (obj_status == QDF_STATUS_E_FAILURE) + psoc->obj_state = WLAN_OBJ_STATE_CREATION_FAILED; + + /* Notify components about the CREATION success/failure */ + if ((obj_status == QDF_STATUS_SUCCESS) || + (obj_status == QDF_STATUS_E_FAILURE)) { + /* nofity object status */ + for (i = 0; i < WLAN_UMAC_MAX_COMPONENTS; i++) { + stat_handler = g_umac_glb_obj->psoc_status_handler[i]; + arg = g_umac_glb_obj->psoc_status_handler_arg[i]; + if (stat_handler != NULL) + stat_handler(psoc, arg, obj_status); + } + } + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_objmgr_psoc_component_obj_detach( + struct wlan_objmgr_psoc *psoc, + enum wlan_umac_comp_id id, + void *comp_objptr) +{ + QDF_STATUS obj_status; + + /* component id is invalid */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) + return QDF_STATUS_MAXCOMP_FAIL; + + wlan_psoc_obj_lock(psoc); + /* If there is a valid entry, return failure */ + if (psoc->soc_comp_obj[id] != comp_objptr) { + psoc->obj_status[id] = QDF_STATUS_E_FAILURE; + wlan_psoc_obj_unlock(psoc); + return QDF_STATUS_E_FAILURE; + } + /* Reset pointers to NULL, update the status*/ + psoc->soc_comp_obj[id] = NULL; + psoc->obj_status[id] = QDF_STATUS_SUCCESS; + wlan_psoc_obj_unlock(psoc); + + /* If PSOC object status is partially created means, this API is + * invoked with differnt context, this block should be executed for + * async components only + */ + if ((psoc->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) || + (psoc->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)) { + /* Derive object status */ + obj_status = wlan_objmgr_psoc_object_status(psoc); + if (obj_status == QDF_STATUS_SUCCESS) { + /* Update the status as Deleted, if full object + * deletion is in progress + */ + if (psoc->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) + psoc->obj_state = WLAN_OBJ_STATE_DELETED; + + /* Move to creation state, since this component + * deletion alone requested + */ + if (psoc->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS) + psoc->obj_state = WLAN_OBJ_STATE_CREATED; + /* Object status is failure */ + } else if (obj_status == QDF_STATUS_E_FAILURE) { + /* Update the status as Deletion failed, if full object + * deletion is in progress + */ + if (psoc->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) + psoc->obj_state = + WLAN_OBJ_STATE_DELETION_FAILED; + + /* Move to creation state, since this component + * deletion alone requested (do not block other + * components) + */ + if (psoc->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS) + psoc->obj_state = WLAN_OBJ_STATE_CREATED; + } + + /* Delete psoc object */ + if ((obj_status == QDF_STATUS_SUCCESS) && + (psoc->obj_state == WLAN_OBJ_STATE_DELETED)) { + /* Detach PSOC from global object's psoc list */ + if (wlan_objmgr_psoc_object_detach(psoc) == + QDF_STATUS_E_FAILURE) + return QDF_STATUS_E_FAILURE; + + wlan_objmgr_psoc_peer_list_deinit( + &psoc->soc_objmgr.peer_list); + /* Destroy spinlock */ + qdf_spinlock_destroy(&psoc->psoc_lock); + /* Free memory */ + qdf_mem_free(psoc); + } + } + return QDF_STATUS_SUCCESS; +} + +/** + ** APIs to operations on psoc objects + */ + +QDF_STATUS wlan_objmgr_iterate_obj_list( + struct wlan_objmgr_psoc *psoc, + enum wlan_objmgr_obj_type obj_type, + wlan_objmgr_op_handler handler, + void *arg, uint8_t lock_free_op) +{ + uint16_t obj_id; + uint8_t i; + struct wlan_objmgr_psoc_objmgr *objmgr = &psoc->soc_objmgr; + struct wlan_peer_list *peer_list; + qdf_list_t *obj_list; + struct wlan_objmgr_peer *peer; + struct wlan_objmgr_peer *peer_next; + + /* If caller requests for lock free opeation, do not acquire, + * handler will handle the synchronization + */ + if (!lock_free_op) + wlan_psoc_obj_lock(psoc); + + switch (obj_type) { + case WLAN_PDEV_OP: + /* Iterate through PDEV list, invoke handler for each pdev */ + for (obj_id = 0; obj_id < WLAN_UMAC_MAX_PDEVS; obj_id++) { + if (objmgr->wlan_pdev_list[obj_id] != NULL) { + /* TODO increment ref count */ + handler(psoc, + (void *)objmgr->wlan_pdev_list[obj_id], + arg); + /* TODO decrement ref count */ + } + } + break; + case WLAN_VDEV_OP: + /* Iterate through VDEV list, invoke handler for each vdev */ + for (obj_id = 0; obj_id < WLAN_UMAC_PSOC_MAX_VDEVS; obj_id++) { + if (objmgr->wlan_vdev_list[obj_id] != NULL) { + /* TODO increment ref count */ + handler(psoc, + (void *)objmgr->wlan_vdev_list[obj_id], + arg); + /* TODO decrement ref count */ + } + } + break; + case WLAN_PEER_OP: + /* Iterate through PEER list, invoke handler for each peer */ + peer_list = &objmgr->peer_list; + if (!lock_free_op) + qdf_spin_lock_bh(&peer_list->peer_list_lock); + /* Since peer list has sublist, iterate through sublists */ + for (i = 0; i < WLAN_PEER_HASHSIZE; i++) { + obj_list = &peer_list->peer_hash[i]; + peer = wlan_psoc_peer_list_peek_head(obj_list); + while (peer) { + /* Increment ref count, to hold the + peer pointer */ + wlan_objmgr_peer_ref_peer(peer); + handler(psoc, (void *)peer, arg); + /* Get next peer */ + peer_next = wlan_peer_get_next_peer_of_psoc( + obj_list, peer); + /* Decrement ref count, this can lead + to peer deletion also */ + wlan_objmgr_peer_unref_peer(peer); + peer = peer_next; + } + } + if (!lock_free_op) + qdf_spin_unlock_bh(&peer_list->peer_list_lock); + break; + default: + break; + } + if (!lock_free_op) + wlan_psoc_obj_unlock(psoc); + return QDF_STATUS_SUCCESS; +} + +void wlan_objmgr_psoc_peer_delete(struct wlan_objmgr_psoc *psoc, void *obj, + void *args) +{ + struct wlan_objmgr_peer *peer = (struct wlan_objmgr_peer *)obj; + + wlan_objmgr_peer_obj_delete(peer); +} + +void wlan_objmgr_psoc_vdev_delete(struct wlan_objmgr_psoc *psoc, void *obj, + void *args) +{ + struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)obj; + + wlan_objmgr_vdev_obj_delete(vdev); +} + +void wlan_objmgr_psoc_pdev_delete(struct wlan_objmgr_psoc *psoc, void *obj, + void *args) +{ + struct wlan_objmgr_pdev *pdev = (struct wlan_objmgr_pdev *)obj; + + wlan_objmgr_pdev_obj_delete(pdev); +} + +QDF_STATUS wlan_objmgr_free_all_objects_per_psoc( + struct wlan_objmgr_psoc *psoc) +{ + /* Free all peers */ + wlan_objmgr_iterate_obj_list(psoc, WLAN_PEER_OP, + wlan_objmgr_psoc_peer_delete, NULL, 1); + /* Free all vdevs */ + wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP, + wlan_objmgr_psoc_vdev_delete, NULL, 1); + /* Free all PDEVs */ + wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP, + wlan_objmgr_psoc_pdev_delete, NULL, 1); + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_objmgr_trigger_psoc_comp_object_creation( + struct wlan_objmgr_psoc *psoc, + enum wlan_umac_comp_id id) +{ + wlan_objmgr_psoc_create_handler handler; + void *arg; + QDF_STATUS obj_status = QDF_STATUS_SUCCESS; + + /* Component id is invalid */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) + return QDF_STATUS_MAXCOMP_FAIL; + + wlan_psoc_obj_lock(psoc); + /* If component object is already created, delete old + * component object, then invoke creation + */ + if (psoc->soc_comp_obj[id] != NULL) { + wlan_psoc_obj_unlock(psoc); + return QDF_STATUS_E_FAILURE; + } + wlan_psoc_obj_unlock(psoc); + /* Invoke registered create handlers */ + handler = g_umac_glb_obj->psoc_create_handler[id]; + arg = g_umac_glb_obj->psoc_create_handler_arg[id]; + if (handler != NULL) + psoc->obj_status[id] = handler(psoc, arg); + else + return QDF_STATUS_E_FAILURE; + + /* If object status is created, then only handle this object status */ + if (psoc->obj_state == WLAN_OBJ_STATE_CREATED) { + /* Derive object status */ + obj_status = wlan_objmgr_psoc_object_status(psoc); + /* Move PSOC object state to Partially created state */ + if (obj_status == QDF_STATUS_COMP_ASYNC) { + /*TODO atomic */ + psoc->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED; + } + } + return obj_status; +} + +QDF_STATUS wlan_objmgr_trigger_psoc_comp_object_deletion( + struct wlan_objmgr_psoc *psoc, + enum wlan_umac_comp_id id) +{ + wlan_objmgr_psoc_delete_handler handler; + void *arg; + QDF_STATUS obj_status = QDF_STATUS_SUCCESS; + + /* component id is invalid */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) + return QDF_STATUS_MAXCOMP_FAIL; + + wlan_psoc_obj_lock(psoc); + /* Component object was never created, invalid operation */ + if (psoc->soc_comp_obj[id] == NULL) { + wlan_psoc_obj_unlock(psoc); + return QDF_STATUS_E_FAILURE; + } + wlan_psoc_obj_unlock(psoc); + /* Invoke registered create handlers */ + handler = g_umac_glb_obj->psoc_delete_handler[id]; + arg = g_umac_glb_obj->psoc_delete_handler_arg[id]; + if (handler != NULL) + psoc->obj_status[id] = handler(psoc, arg); + else + return QDF_STATUS_E_FAILURE; + + /* If object status is created, then only handle this object status */ + if (psoc->obj_state == WLAN_OBJ_STATE_CREATED) { + obj_status = wlan_objmgr_psoc_object_status(psoc); + /* move object state to DEL progress */ + if (obj_status == QDF_STATUS_COMP_ASYNC) + psoc->obj_state = WLAN_OBJ_STATE_COMP_DEL_PROGRESS; + } + return obj_status; +} + +/* Util APIs */ + +QDF_STATUS wlan_objmgr_psoc_pdev_attach(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev) +{ + struct wlan_objmgr_psoc_objmgr *objmgr = &psoc->soc_objmgr; + uint8_t id = 0; + QDF_STATUS status; + + wlan_psoc_obj_lock(psoc); + /* + * Derive pdev id from pdev map + * First free pdev id is assigned + */ + while ((id < WLAN_UMAC_MAX_PDEVS) && + (objmgr->wlan_pdev_id_map & (1<wlan_pdev_id_map |= (1<wlan_pdev_list[id] = pdev; + /* Increment pdev count */ + objmgr->wlan_pdev_count++; + /* save pdev id */ + pdev->pdev_objmgr.wlan_pdev_id = id; + status = QDF_STATUS_SUCCESS; + } + wlan_psoc_obj_unlock(psoc); + return status; +} + +QDF_STATUS wlan_objmgr_psoc_pdev_detach(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev) +{ + struct wlan_objmgr_psoc_objmgr *objmgr = &psoc->soc_objmgr; + uint8_t id; + + id = pdev->pdev_objmgr.wlan_pdev_id; + /* If id is invalid, return */ + if (id >= WLAN_UMAC_MAX_PDEVS) + return QDF_STATUS_E_FAILURE; + + wlan_psoc_obj_lock(psoc); + /* Free pdev id slot */ + objmgr->wlan_pdev_id_map &= ~(1<wlan_pdev_list[id] = NULL; + objmgr->wlan_pdev_count--; + pdev->pdev_objmgr.wlan_pdev_id = 0xff; + wlan_psoc_obj_unlock(psoc); + + return QDF_STATUS_E_FAILURE; +} + +struct wlan_objmgr_pdev *wlan_objmgr_find_pdev_by_id( + struct wlan_objmgr_psoc *psoc, uint8_t id) +{ + struct wlan_objmgr_psoc_objmgr *objmgr = &psoc->soc_objmgr; + struct wlan_objmgr_pdev *pdev = NULL; + + wlan_psoc_obj_lock(psoc); + /* get pdev from pdev list */ + pdev = objmgr->wlan_pdev_list[id]; + wlan_psoc_obj_unlock(psoc); + return pdev; +} + +QDF_STATUS wlan_objmgr_psoc_vdev_attach(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_vdev *vdev) +{ + struct wlan_objmgr_psoc_objmgr *objmgr = &psoc->soc_objmgr; + uint8_t id = 0; + uint8_t map_index = 0; + uint8_t map_entry_size = 32; + uint8_t adjust_ix = 0; + QDF_STATUS status; + + wlan_psoc_obj_lock(psoc); + /* Find first free vdev id */ + while ((id < objmgr->max_vdev_count) && + (objmgr->wlan_vdev_id_map[map_index] & (1<<(id - adjust_ix)))) { + id++; + /* + * The map is two DWORDS(32 bits), so, map_index + * adjust_ix derived based on the id value + */ + if (id == ((map_index+1)*map_entry_size)) { + adjust_ix = map_index*map_entry_size; + map_index++; + } + } + /* If no free slot, return failure */ + if (id == objmgr->max_vdev_count) { + status = QDF_STATUS_E_FAILURE; + } else { + /* set free vdev id index */ + objmgr->wlan_vdev_id_map[map_index] |= (1<<(id-adjust_ix)); + /* store vdev pointer in vdev list */ + objmgr->wlan_vdev_list[id] = vdev; + /* increment vdev counter */ + objmgr->wlan_vdev_count++; + /* save vdev id */ + vdev->vdev_objmgr.vdev_id = id; + status = QDF_STATUS_SUCCESS; + } + wlan_psoc_obj_unlock(psoc); + return status; +} + +QDF_STATUS wlan_objmgr_psoc_vdev_detach(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_vdev *vdev) +{ + struct wlan_objmgr_psoc_objmgr *objmgr = &psoc->soc_objmgr; + uint8_t id = 0; + uint8_t map_index = 0; + uint8_t map_entry_size = 32; + uint8_t adjust_ix = 0; + + id = vdev->vdev_objmgr.vdev_id; + /* Invalid vdev id */ + if (id >= WLAN_UMAC_PSOC_MAX_VDEVS) + return QDF_STATUS_E_FAILURE; + /* + * Derive map_index and adjust_ix to find actual DWORD + * the id map is present + */ + while ((id - adjust_ix) >= map_entry_size) { + map_index++; + adjust_ix = map_index * map_entry_size; + } + wlan_psoc_obj_lock(psoc); + /* unset bit, to free the slot */ + objmgr->wlan_vdev_id_map[map_index] &= ~(1<<(id-adjust_ix)); + /* reset VDEV pointer to NULL in VDEV list array */ + objmgr->wlan_vdev_list[id] = NULL; + /* decrement vdev count */ + objmgr->wlan_vdev_count--; + vdev->vdev_objmgr.vdev_id = 0xff; + wlan_psoc_obj_unlock(psoc); + return QDF_STATUS_SUCCESS; +} + + +struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_id_from_psoc( + struct wlan_objmgr_psoc *psoc, uint8_t vdev_id) +{ + struct wlan_objmgr_vdev *vdev; + + /* if PSOC is NULL, return */ + if (psoc == NULL) + return NULL; + /* vdev id is invalid */ + if (vdev_id >= WLAN_UMAC_PSOC_MAX_VDEVS) + return NULL; + + wlan_psoc_obj_lock(psoc); + /* retrieve vdev pointer from vdev list */ + vdev = psoc->soc_objmgr.wlan_vdev_list[vdev_id]; + wlan_psoc_obj_unlock(psoc); + return vdev; +} + +struct wlan_objmgr_vdev *wlan_objmgr_find_vdev_by_macaddr_from_psoc( + struct wlan_objmgr_psoc *psoc, uint8_t *macaddr) +{ + struct wlan_objmgr_vdev *vdev; + uint8_t id; + + /* if PSOC is NULL, return */ + if (psoc == NULL) + return NULL; + + wlan_psoc_obj_lock(psoc); + /* Iterate through PSOC's vdev list */ + for (id = 0; id < WLAN_UMAC_PSOC_MAX_VDEVS; id++) { + vdev = psoc->soc_objmgr.wlan_vdev_list[id]; + if (vdev == NULL) + continue; + /* MAC address matches, break */ + if (WLAN_ADDR_EQ(wlan_vdev_mlme_get_macaddr(vdev), macaddr) + == QDF_STATUS_SUCCESS) { + wlan_psoc_obj_unlock(psoc); + return vdev; + } + } + wlan_psoc_obj_unlock(psoc); + return NULL; +} + +static void wlan_obj_psoc_peerlist_add_tail(qdf_list_t *obj_list, + struct wlan_objmgr_peer *obj) +{ + qdf_list_insert_back(obj_list, &obj->psoc_peer); +} + +static QDF_STATUS wlan_obj_psoc_peerlist_remove_peer( + qdf_list_t *obj_list, + struct wlan_objmgr_peer *peer) +{ + qdf_list_node_t *psoc_node = NULL; + + if (peer == NULL) + return QDF_STATUS_E_FAILURE; + /* get vdev list node element */ + psoc_node = &peer->psoc_peer; + /* list is empty, return failure */ + if (qdf_list_remove_node(obj_list, psoc_node) != QDF_STATUS_SUCCESS) + return QDF_STATUS_E_FAILURE; + + return QDF_STATUS_SUCCESS; +} + +struct wlan_objmgr_peer *wlan_obj_psoc_peerlist_get_peer( + qdf_list_t *obj_list, + uint8_t *macaddr) +{ + struct wlan_objmgr_peer *peer; + struct wlan_objmgr_peer *peer_temp; + + /* Iterate through hash list to get the peer */ + peer = wlan_psoc_peer_list_peek_head(obj_list); + while (peer != NULL) { + /* For peer, macaddr is key */ + if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), macaddr) + == QDF_STATUS_SUCCESS) { + /* Increment ref count for access */ + wlan_objmgr_peer_ref_peer(peer); + return peer; + } + /* Move to next peer */ + peer_temp = peer; + peer = wlan_peer_get_next_peer_of_psoc(obj_list, peer_temp); + } + /* Not found, return NULL */ + return NULL; +} + +QDF_STATUS wlan_objmgr_psoc_peer_attach(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_peer *peer) +{ + struct wlan_objmgr_psoc_objmgr *objmgr = &psoc->soc_objmgr; + uint8_t hash_index; + + wlan_psoc_obj_lock(psoc); + /* Max peer limit is reached, return failure */ + if (objmgr->wlan_peer_count > WLAN_UMAC_PSOC_MAX_PEERS) { + wlan_psoc_obj_unlock(psoc); + return QDF_STATUS_E_FAILURE; + } + /* Derive hash index from mac address */ + hash_index = WLAN_PEER_HASH(peer->macaddr); + /* add peer to hash peer list */ + wlan_obj_psoc_peerlist_add_tail( + &objmgr->peer_list.peer_hash[hash_index], + peer); + /* Increment peer count */ + objmgr->wlan_peer_count++; + + wlan_psoc_obj_unlock(psoc); + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_objmgr_psoc_peer_detach(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_peer *peer) +{ + struct wlan_objmgr_psoc_objmgr *objmgr = &psoc->soc_objmgr; + uint8_t hash_index; + + wlan_psoc_obj_lock(psoc); + /* if list is empty, return */ + if (objmgr->wlan_peer_count == 0) { + wlan_psoc_obj_unlock(psoc); + return QDF_STATUS_E_FAILURE; + } + /* Get hash index, to locate the actual peer list */ + hash_index = WLAN_PEER_HASH(peer->macaddr); + /* removes the peer from peer_list */ + if (wlan_obj_psoc_peerlist_remove_peer( + &objmgr->peer_list.peer_hash[hash_index], + peer) == + QDF_STATUS_E_FAILURE) { + wlan_psoc_obj_unlock(psoc); + qdf_print("%s: Failed to detach peer\n", __func__); + return QDF_STATUS_E_FAILURE; + } + /* Decrement peer count */ + objmgr->wlan_peer_count--; + + wlan_psoc_obj_unlock(psoc); + return QDF_STATUS_SUCCESS; +} + +struct wlan_objmgr_peer *wlan_objmgr_find_peer( + struct wlan_objmgr_psoc *psoc, uint8_t *macaddr) +{ + struct wlan_objmgr_psoc_objmgr *objmgr = &psoc->soc_objmgr; + uint8_t hash_index; + struct wlan_objmgr_peer *peer = NULL; + struct wlan_peer_list *peer_list; + + wlan_psoc_obj_lock(psoc); + /* List is empty, return NULL */ + if (objmgr->wlan_peer_count == 0) { + wlan_psoc_obj_unlock(psoc); + return NULL; + } + /* reduce the search window, with hash key */ + hash_index = WLAN_PEER_HASH(macaddr); + peer_list = &objmgr->peer_list; + qdf_spin_lock_bh(&peer_list->peer_list_lock); + /* Iterate through peer list, get peer */ + peer = wlan_obj_psoc_peerlist_get_peer( + &peer_list->peer_hash[hash_index], macaddr); + qdf_spin_unlock_bh(&peer_list->peer_list_lock); + wlan_psoc_obj_unlock(psoc); + return peer; +} diff --git a/umac/cmn_services/obj_mgr/src/wlan_objmgr_psoc_obj_i.h b/umac/cmn_services/obj_mgr/src/wlan_objmgr_psoc_obj_i.h new file mode 100644 index 0000000000..f36487d615 --- /dev/null +++ b/umac/cmn_services/obj_mgr/src/wlan_objmgr_psoc_obj_i.h @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + /** + * DOC: Public APIs to perform operations on Global objects + */ +#ifndef _WLAN_OBJMGR_PSOC_OBJ_I_H_ +#define _WLAN_OBJMGR_PSOC_OBJ_I_H_ + +/** + * wlan_objmgr_psoc_pdev_attach() - store pdev in psoc's pdev list + * @psoc - PSOC object + * @pdev - PDEV object + * + * Attaches PDEV to PSOC, allocates PDEV id + * + * Return: SUCCESS + * Failure (Max PDEVs are exceeded) + */ +QDF_STATUS wlan_objmgr_psoc_pdev_attach(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev); + +/** + * wlan_objmgr_psoc_pdev_detach() - remove pdev from psoc's pdev list + * @psoc - PSOC object + * @pdev - PDEV object + * + * detaches PDEV to PSOC, frees PDEV id + * + * Return: SUCCESS + * Failure (No PDEVs are present) + */ +QDF_STATUS wlan_objmgr_psoc_pdev_detach(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev); + +/** + * wlan_objmgr_psoc_vdev_attach() - store vdev in psoc's vdev list + * @psoc - PSOC object + * @vdev - VDEV object + * + * Attaches VDEV to PSOC, allocates VDEV id + * + * Return: SUCCESS + * Failure (Max VDEVs are exceeded) + */ +QDF_STATUS wlan_objmgr_psoc_vdev_attach(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_vdev *vdev); + +/** + * wlan_objmgr_psoc_vdev_detach() - remove vdev from psoc's vdev list + * @psoc - PSOC object + * @vdev - VDEV object + * + * detaches VDEV to PSOC, frees VDEV id + * + * Return: SUCCESS + * Failure (No VDEVs are present) + */ +QDF_STATUS wlan_objmgr_psoc_vdev_detach(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_vdev *vdev); + +/** + * wlan_objmgr_psoc_peer_attach() - store peer in psoc's peer table + * @psoc - PSOC object + * @peer - PEER object + * + * Attaches PEER to PSOC, derives the HASH, add peer to its peer list + * + * Return: SUCCESS + * Failure (Max PEERs are exceeded) + */ +QDF_STATUS wlan_objmgr_psoc_peer_attach(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_peer *peer); + +/** + * wlan_objmgr_psoc_peer_detach() - remove peer from psoc's peer table + * @psoc - PSOC object + * @peer - PEER object + * + * detaches PEER to PSOC, removes the peer from the peer list + * + * Return: SUCCESS + * Failure (PEER is not present) + */ +QDF_STATUS wlan_objmgr_psoc_peer_detach(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_peer *peer); + +/** + * wlan_objmgr_psoc_object_attach() - attach psoc to global object + * @psoc - PSOC object + * + * attaches PSOC to global psoc list + * + * Return: SUCCESS + * Failure (Max supported PSOCs exceeded) + */ +QDF_STATUS wlan_objmgr_psoc_object_attach( + struct wlan_objmgr_psoc *psoc); + +/** + * wlan_objmgr_psoc_object_detach() - detach psoc from global object + * @psoc - PSOC object + * + * detaches PSOC from global psoc list + * + * Return: SUCCESS + * Failure (if list is empty and PSOC is not present) + */ +QDF_STATUS wlan_objmgr_psoc_object_detach( + struct wlan_objmgr_psoc *psoc); + +#endif /* _WLAN_OBJMGR_PSOC_OBJ_I_H_ */ diff --git a/umac/cmn_services/obj_mgr/src/wlan_objmgr_vdev_obj.c b/umac/cmn_services/obj_mgr/src/wlan_objmgr_vdev_obj.c new file mode 100644 index 0000000000..1386fc197d --- /dev/null +++ b/umac/cmn_services/obj_mgr/src/wlan_objmgr_vdev_obj.c @@ -0,0 +1,593 @@ +/* + * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + /** + * DOC: Public APIs to perform operations on Global objects + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + ** APIs to Create/Delete Global object APIs + */ + +static QDF_STATUS wlan_objmgr_vdev_object_status( + struct wlan_objmgr_vdev *vdev) +{ + uint8_t id; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + wlan_vdev_obj_lock(vdev); + + /* Iterate through all components to derive the object status */ + for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { + /* If component disabled, Ignore */ + if (vdev->obj_status[id] == QDF_STATUS_COMP_DISABLED) { + continue; + /* + * If component operates in Async, status is Partially created, + * break + */ + } else if (vdev->obj_status[id] == QDF_STATUS_COMP_ASYNC) { + if (vdev->vdev_comp_obj[id] == NULL) { + status = QDF_STATUS_COMP_ASYNC; + break; + } + /* + * If component failed to allocate its object, treat it as + * failure, complete object need to be cleaned up + */ + } else if ((vdev->obj_status[id] == QDF_STATUS_E_NOMEM) || + (vdev->obj_status[id] == QDF_STATUS_E_FAILURE)) { + status = QDF_STATUS_E_FAILURE; + break; + } + } + wlan_vdev_obj_unlock(vdev); + return status; +} + +struct wlan_objmgr_vdev *wlan_objmgr_vdev_obj_create( + struct wlan_objmgr_pdev *pdev, + struct wlan_vdev_create_params *params) +{ + struct wlan_objmgr_vdev *vdev; + struct wlan_objmgr_psoc *psoc; + uint8_t id; + wlan_objmgr_vdev_create_handler handler; + wlan_objmgr_vdev_status_handler stat_handler; + void *arg; + QDF_STATUS obj_status; + + if (pdev == NULL) { + qdf_print("%s: pdev is NULL\n", __func__); + return NULL; + } + psoc = wlan_pdev_get_psoc(pdev); + /* PSOC is NULL */ + if (psoc == NULL) { + qdf_print("%s: psoc is NULL\n", __func__); + return NULL; + } + /* Allocate vdev object memory */ + vdev = qdf_mem_malloc(sizeof(*vdev)); + if (vdev == NULL) { + qdf_print("%s: Memory allocation failure\n", __func__); + return NULL; + } + /* Attach VDEV to PSOC VDEV's list */ + if (wlan_objmgr_psoc_vdev_attach(psoc, vdev) != + QDF_STATUS_SUCCESS) { + qdf_mem_free(vdev); + qdf_print("%s: psoc vdev attach failed\n", __func__); + return NULL; + } + /* Store pdev in vdev */ + wlan_vdev_set_pdev(vdev, pdev); + /* Attach vdev to PDEV */ + if (wlan_objmgr_pdev_vdev_attach(pdev, vdev) != + QDF_STATUS_SUCCESS) { + qdf_print("%s: pdev vdev attach failed\n", __func__); + wlan_objmgr_psoc_vdev_detach(psoc, vdev); + qdf_mem_free(vdev); + return NULL; + } + /* Initialize spinlock */ + qdf_spinlock_create(&vdev->vdev_lock); + /* set opmode */ + wlan_vdev_mlme_set_opmode(vdev, params->opmode); + /* set MAC address */ + wlan_vdev_mlme_set_macaddr(vdev, params->macaddr); + /* set MAT address */ + wlan_vdev_mlme_set_mataddr(vdev, params->mataddr); + /* Set create flags */ + vdev->vdev_objmgr.c_flags = params->flags; + /* store os-specific pointer */ + vdev->vdev_nif.osdev = params->osifp; + /* peer count to 0 */ + vdev->vdev_objmgr.wlan_peer_count = 0; + /* Initialize max peer count based on opmode type */ + if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) + vdev->vdev_objmgr.max_peer_count = WLAN_UMAC_MAX_STA_PEERS; + else + vdev->vdev_objmgr.max_peer_count = WLAN_UMAC_MAX_AP_PEERS; + + /* Initialize peer list */ + qdf_list_create(&vdev->vdev_objmgr.wlan_peer_list, + vdev->vdev_objmgr.max_peer_count); + /* TODO init other parameters */ + + /* Invoke registered create handlers */ + for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { + handler = g_umac_glb_obj->vdev_create_handler[id]; + arg = g_umac_glb_obj->vdev_create_handler_arg[id]; + if (handler != NULL) + vdev->obj_status[id] = handler(vdev, arg); + else + vdev->obj_status[id] = QDF_STATUS_COMP_DISABLED; + } + + /* Derive object status */ + obj_status = wlan_objmgr_vdev_object_status(vdev); + + if (obj_status == QDF_STATUS_SUCCESS) { + /* Object status is SUCCESS, Object is created */ + vdev->obj_state = WLAN_OBJ_STATE_CREATED; + /* Invoke component registered status handlers */ + for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { + stat_handler = g_umac_glb_obj->vdev_status_handler[id]; + arg = g_umac_glb_obj->vdev_status_handler_arg[id]; + if (stat_handler != NULL) { + stat_handler(vdev, arg, + QDF_STATUS_SUCCESS); + } + } + /* + * Few components operates in Asynchrous communction, Object state + * partially created + */ + } else if (obj_status == QDF_STATUS_COMP_ASYNC) { + vdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED; + /* Component object failed to be created, clean up the object */ + } else if (obj_status == QDF_STATUS_E_FAILURE) { + /* Clean up the psoc */ + wlan_objmgr_vdev_obj_delete(vdev); + qdf_print("%s:VDEV component objects creation failed\n", + __func__); + return NULL; + } + return vdev; +} + +QDF_STATUS wlan_objmgr_vdev_obj_delete(struct wlan_objmgr_vdev *vdev) +{ + uint8_t id; + wlan_objmgr_vdev_delete_handler handler; + QDF_STATUS obj_status; + void *arg; + struct wlan_objmgr_pdev *pdev; + + if (vdev == NULL) { + qdf_print("%s:vdev is NULL\n", __func__); + return QDF_STATUS_E_FAILURE; + } + /* if PDEV is NULL, return */ + pdev = wlan_vdev_get_pdev(vdev); + if (pdev == NULL) { + qdf_print("%s:pdev is NULL\n", __func__); + return QDF_STATUS_E_FAILURE; + } + + /* Invoke registered create handlers */ + for (id = 0; id < WLAN_UMAC_MAX_COMPONENTS; id++) { + handler = g_umac_glb_obj->vdev_delete_handler[id]; + arg = g_umac_glb_obj->vdev_delete_handler_arg[id]; + if (handler != NULL) + vdev->obj_status[id] = handler(vdev, arg); + else + vdev->obj_status[id] = QDF_STATUS_COMP_DISABLED; + } + /* Derive object status */ + obj_status = wlan_objmgr_vdev_object_status(vdev); + + if (obj_status == QDF_STATUS_E_FAILURE) { + qdf_print("%s: VDEV object deletion failed\n", __func__); + /* Ideally should not happen */ + /* This leads to memleak ??? how to handle */ + QDF_BUG(0); + return QDF_STATUS_E_FAILURE; + } + + /* Deletion is in progress */ + if (obj_status == QDF_STATUS_COMP_ASYNC) { + vdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_DELETED; + return QDF_STATUS_COMP_ASYNC; + } else { + /* Detach VDEV from PDEV VDEV's list */ + if (wlan_objmgr_pdev_vdev_detach(pdev, vdev) == + QDF_STATUS_E_FAILURE) + return QDF_STATUS_E_FAILURE; + + /* Detach VDEV from PSOC VDEV's list */ + if (wlan_objmgr_psoc_vdev_detach( + pdev->pdev_objmgr.wlan_psoc, vdev) == + QDF_STATUS_E_FAILURE) + return QDF_STATUS_E_FAILURE; + + /* de-init lock */ + qdf_spinlock_destroy(&vdev->vdev_lock); + /* Free the memory */ + qdf_mem_free(vdev); + } + return QDF_STATUS_SUCCESS; +} + +/** + ** APIs to attach/detach component objects + */ +QDF_STATUS wlan_objmgr_vdev_component_obj_attach( + struct wlan_objmgr_vdev *vdev, + enum wlan_umac_comp_id id, + void *comp_objptr, + QDF_STATUS status) +{ + wlan_objmgr_vdev_status_handler stat_handler; + void *arg; + uint8_t i; + QDF_STATUS obj_status; + + /* component id is invalid */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) + return QDF_STATUS_MAXCOMP_FAIL; + + wlan_vdev_obj_lock(vdev); + /* If there is a valid entry, return failure */ + if (vdev->vdev_comp_obj[id] != NULL) { + wlan_vdev_obj_unlock(vdev); + return QDF_STATUS_E_FAILURE; + } + /* Save component's pointer and status */ + vdev->vdev_comp_obj[id] = comp_objptr; + vdev->obj_status[id] = status; + wlan_vdev_obj_unlock(vdev); + + if (vdev->obj_state != WLAN_OBJ_STATE_PARTIALLY_CREATED) + return QDF_STATUS_SUCCESS; + /* + * If VDEV object status is partially created means, this API is + * invoked with differnt context, this block should be executed for + * async components only + */ + /* Derive status */ + obj_status = wlan_objmgr_vdev_object_status(vdev); + /* STATUS_SUCCESS means, object is CREATED */ + if (obj_status == QDF_STATUS_SUCCESS) + vdev->obj_state = WLAN_OBJ_STATE_CREATED; + /* + * update state as CREATION failed, caller has to delete the + * VDEV object + */ + else if (obj_status == QDF_STATUS_E_FAILURE) + vdev->obj_state = WLAN_OBJ_STATE_CREATION_FAILED; + /* Notify components about the CREATION success/failure */ + if ((obj_status == QDF_STATUS_SUCCESS) || + (obj_status == QDF_STATUS_E_FAILURE)) { + for (i = 0; i < WLAN_UMAC_MAX_COMPONENTS; i++) { + stat_handler = g_umac_glb_obj->vdev_status_handler[i]; + arg = g_umac_glb_obj->vdev_status_handler_arg[i]; + if (stat_handler != NULL) + stat_handler(vdev, arg, obj_status); + } + } + return QDF_STATUS_SUCCESS; +} +EXPORT_SYMBOL(wlan_objmgr_vdev_component_obj_attach); + +QDF_STATUS wlan_objmgr_vdev_component_obj_detach( + struct wlan_objmgr_vdev *vdev, + enum wlan_umac_comp_id id, + void *comp_objptr) +{ + QDF_STATUS obj_status; + + /* component id is invalid */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) + return QDF_STATUS_MAXCOMP_FAIL; + wlan_vdev_obj_lock(vdev); + /* If there is a valid entry, return failure */ + if (vdev->vdev_comp_obj[id] != comp_objptr) { + vdev->obj_status[id] = QDF_STATUS_E_FAILURE; + wlan_vdev_obj_unlock(vdev); + return QDF_STATUS_E_FAILURE; + } + /* Reset pointers to NULL, update the status*/ + vdev->vdev_comp_obj[id] = NULL; + vdev->obj_status[id] = QDF_STATUS_SUCCESS; + wlan_vdev_obj_unlock(vdev); + + /** + *If VDEV object status is partially deleted means, this API is + * invoked with differnt context, this block should be executed for + * async components only + */ + if ((vdev->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) || + (vdev->obj_state == WLAN_OBJ_STATE_COMP_DEL_PROGRESS)) { + /* Derive object status */ + obj_status = wlan_objmgr_vdev_object_status(vdev); + if (obj_status == QDF_STATUS_SUCCESS) { + /* + * Update the status as Deleted, if full object + * deletion is in progress + */ + if (vdev->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) + vdev->obj_state = WLAN_OBJ_STATE_DELETED; + /* + * Move to creation state, since this component + * deletion alone requested + */ + else if (vdev->obj_state == + WLAN_OBJ_STATE_COMP_DEL_PROGRESS) + vdev->obj_state = WLAN_OBJ_STATE_CREATED; + /* Object status is failure */ + } else if (obj_status == QDF_STATUS_E_FAILURE) { + /* + * Update the status as Deletion failed, if full object + * deletion is in progress + */ + if (vdev->obj_state == WLAN_OBJ_STATE_PARTIALLY_DELETED) + vdev->obj_state = + WLAN_OBJ_STATE_DELETION_FAILED; + /* Move to creation state, since this component + deletion alone requested (do not block other + components) */ + else if (vdev->obj_state == + WLAN_OBJ_STATE_COMP_DEL_PROGRESS) + vdev->obj_state = WLAN_OBJ_STATE_CREATED; + } + /* Delete vdev object */ + if ((obj_status == QDF_STATUS_SUCCESS) && + (vdev->obj_state == WLAN_OBJ_STATE_DELETED)) { + /* Detach vdev object from psoc */ + if (wlan_objmgr_pdev_vdev_detach( + wlan_vdev_get_pdev(vdev), vdev) + == QDF_STATUS_E_FAILURE) + return QDF_STATUS_E_FAILURE; + /* Detach vdev object from psoc */ + if (wlan_objmgr_psoc_vdev_detach( + wlan_vdev_get_psoc(vdev), vdev) == + QDF_STATUS_E_FAILURE) + return QDF_STATUS_E_FAILURE; + + /* Destroy spinlock */ + qdf_spinlock_destroy(&vdev->vdev_lock); + /* Free VDEV memory */ + qdf_mem_free(vdev); + } + } + return QDF_STATUS_SUCCESS; +} + +/** + ** APIs to operations on vdev objects + */ +QDF_STATUS wlan_objmgr_iterate_peerobj_list( + struct wlan_objmgr_vdev *vdev, + wlan_objmgr_vdev_op_handler handler, + void *arg) +{ + qdf_list_t *peer_list = NULL; + struct wlan_objmgr_peer *peer = NULL; + struct wlan_objmgr_peer *prev_peer = NULL; + + if (vdev == NULL) { + qdf_print("%s: VDEV NULL\n", __func__); + return QDF_STATUS_E_FAILURE; + } + /* TODO increment ref count */ + wlan_vdev_obj_lock(vdev); + peer_list = &vdev->vdev_objmgr.wlan_peer_list; + if (peer_list != NULL) { + /* Iterate through VDEV's peer list */ + peer = wlan_vdev_peer_list_peek_head(peer_list); + while (peer != NULL) { + wlan_objmgr_peer_ref_peer(peer); + /* Invoke handler for operation */ + handler(vdev, (void *)peer, arg); + prev_peer = peer; + peer = wlan_peer_get_next_peer_of_vdev(peer_list, + prev_peer); + wlan_objmgr_peer_unref_peer(prev_peer); + } + } + wlan_vdev_obj_unlock(vdev); + /* TODO decrement ref count */ + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_objmgr_trigger_vdev_comp_object_creation( + struct wlan_objmgr_vdev *vdev, + enum wlan_umac_comp_id id) +{ + wlan_objmgr_vdev_create_handler handler; + void *arg; + QDF_STATUS obj_status = QDF_STATUS_SUCCESS; + + /* Component id is invalid */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) + return QDF_STATUS_MAXCOMP_FAIL; + + wlan_vdev_obj_lock(vdev); + /* + * If component object is already created, delete old + * component object, then invoke creation + */ + if (vdev->vdev_comp_obj[id] != NULL) { + wlan_vdev_obj_unlock(vdev); + return QDF_STATUS_E_FAILURE; + } + wlan_vdev_obj_unlock(vdev); + + /* Invoke registered create handlers */ + handler = g_umac_glb_obj->vdev_create_handler[id]; + arg = g_umac_glb_obj->vdev_create_handler_arg[id]; + if (handler != NULL) + vdev->obj_status[id] = handler(vdev, arg); + else + return QDF_STATUS_E_FAILURE; + + /* If object status is created, then only handle this object status */ + if (vdev->obj_state == WLAN_OBJ_STATE_CREATED) { + /* Derive object status */ + obj_status = wlan_objmgr_vdev_object_status(vdev); + /* Move PDEV object state to Partially created state */ + if (obj_status == QDF_STATUS_COMP_ASYNC) { + /*TODO atomic */ + vdev->obj_state = WLAN_OBJ_STATE_PARTIALLY_CREATED; + } + } + return obj_status; +} + +QDF_STATUS wlan_objmgr_trigger_vdev_comp_object_deletion( + struct wlan_objmgr_vdev *vdev, + enum wlan_umac_comp_id id) +{ + wlan_objmgr_vdev_delete_handler handler; + void *arg; + QDF_STATUS obj_status = QDF_STATUS_SUCCESS; + + /* component id is invalid */ + if (id >= WLAN_UMAC_MAX_COMPONENTS) + return QDF_STATUS_MAXCOMP_FAIL; + + wlan_vdev_obj_lock(vdev); + /* Component object was never created, invalid operation */ + if (vdev->vdev_comp_obj[id] == NULL) { + wlan_vdev_obj_unlock(vdev); + return QDF_STATUS_E_FAILURE; + } + wlan_vdev_obj_unlock(vdev); + + /* Invoke registered create handlers */ + handler = g_umac_glb_obj->vdev_delete_handler[id]; + arg = g_umac_glb_obj->vdev_delete_handler_arg[id]; + if (handler != NULL) + vdev->obj_status[id] = handler(vdev, arg); + else + return QDF_STATUS_E_FAILURE; + + /* If object status is created, then only handle this object status */ + if (vdev->obj_state == WLAN_OBJ_STATE_CREATED) { + obj_status = wlan_objmgr_vdev_object_status(vdev); + /* move object state to DEL progress */ + if (obj_status == QDF_STATUS_COMP_ASYNC) + vdev->obj_state = WLAN_OBJ_STATE_COMP_DEL_PROGRESS; + } + return obj_status; +} + + + +static void wlan_obj_vdev_peerlist_add_tail(qdf_list_t *obj_list, + struct wlan_objmgr_peer *obj) +{ + qdf_list_insert_back(obj_list, &obj->vdev_peer); +} + +static QDF_STATUS wlan_obj_vdev_peerlist_remove_peer(qdf_list_t *obj_list, + struct wlan_objmgr_peer *peer) +{ + qdf_list_node_t *vdev_node = NULL; + + if (peer == NULL) + return QDF_STATUS_E_FAILURE; + /* get vdev list node element */ + vdev_node = &peer->vdev_peer; + /* list is empty, return failure */ + if (qdf_list_remove_node(obj_list, vdev_node) != QDF_STATUS_SUCCESS) + return QDF_STATUS_E_FAILURE; + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_objmgr_vdev_peer_attach(struct wlan_objmgr_vdev *vdev, + struct wlan_objmgr_peer *peer) +{ + struct wlan_objmgr_vdev_objmgr *objmgr = &vdev->vdev_objmgr; + + wlan_vdev_obj_lock(vdev); + /* If Max peer count exceeds, return failure */ + if (objmgr->wlan_peer_count > objmgr->max_peer_count) { + wlan_vdev_obj_unlock(vdev); + return QDF_STATUS_E_FAILURE; + } + /* Add peer to vdev's peer list */ + wlan_obj_vdev_peerlist_add_tail(&objmgr->wlan_peer_list, peer); + objmgr->wlan_peer_count++; + + if (wlan_peer_get_peer_type(peer) == WLAN_PEER_AP) { + if (WLAN_ADDR_EQ(wlan_peer_get_macaddr(peer), + wlan_vdev_mlme_get_macaddr(vdev)) == + QDF_STATUS_SUCCESS) { + /* + * if peer mac address and vdev mac address match, set + * this peer as self peer + */ + wlan_vdev_set_selfpeer(vdev, peer); + /* For AP mode, self peer and BSS peer are same */ + if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) + wlan_vdev_set_bsspeer(vdev, peer); + } + /* set BSS peer for sta */ + if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) + wlan_vdev_set_bsspeer(vdev, peer); + } + wlan_vdev_obj_unlock(vdev); + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_objmgr_vdev_peer_detach(struct wlan_objmgr_vdev *vdev, + struct wlan_objmgr_peer *peer) +{ + struct wlan_objmgr_vdev_objmgr *objmgr = &vdev->vdev_objmgr; + + wlan_vdev_obj_lock(vdev); + /* if peer count is 0, return failure */ + if (objmgr->wlan_peer_count == 0) { + wlan_vdev_obj_unlock(vdev); + return QDF_STATUS_E_FAILURE; + } + /* remove peer from vdev's peer list */ + if (wlan_obj_vdev_peerlist_remove_peer(&objmgr->wlan_peer_list, peer) + == QDF_STATUS_E_FAILURE) { + wlan_vdev_obj_unlock(vdev); + return QDF_STATUS_E_FAILURE; + } + /* decrement peer count */ + objmgr->wlan_peer_count--; + wlan_vdev_obj_unlock(vdev); + return QDF_STATUS_SUCCESS; +} + diff --git a/umac/cmn_services/obj_mgr/src/wlan_objmgr_vdev_obj_i.h b/umac/cmn_services/obj_mgr/src/wlan_objmgr_vdev_obj_i.h new file mode 100644 index 0000000000..039e4de104 --- /dev/null +++ b/umac/cmn_services/obj_mgr/src/wlan_objmgr_vdev_obj_i.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + /** + * DOC: Public APIs to perform operations on VDEV objects + */ +#ifndef _WLAN_OBJMGR_VDEV_OBJ_I_H_ +#define _WLAN_OBJMGR_VDEV_OBJ_I_H_ + +/** + * wlan_objmgr_vdev_peer_attach() - attach peer to vdev peer list + * @vdev: VDEV object + * @peer: PEER object + * + * Attaches PEER to VDEV, stores it in VDEV's peer list + * + * Return: SUCCESS + * Failure (Max PEERs are exceeded) + */ +QDF_STATUS wlan_objmgr_vdev_peer_attach(struct wlan_objmgr_vdev *vdev, + struct wlan_objmgr_peer *peer); + +/** + * wlan_objmgr_vdev_peer_detach() - detach peer from vdev peer list + * @vdev: VDEV object + * @peer: PEER object + * + * detaches PEER from VDEV's peer list + * + * Return: SUCCESS + * Failure (No PEERs are present) + */ +QDF_STATUS wlan_objmgr_vdev_peer_detach(struct wlan_objmgr_vdev *vdev, + struct wlan_objmgr_peer *peer); + +#endif /* _WLAN_OBJMGR_VDEV_OBJ_I_H_*/