blob: bddd397f0a6919fd1b7007324bd4e661486cc576 [file] [log] [blame]
/*
* Copyright (c) 2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
*
* 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.
*/
/*
* This file was originally distributed by Qualcomm Atheros, Inc.
* under proprietary terms before Copyright ownership was assigned
* to the Linux Foundation.
*/
/**
* DOC: HDD object manager API source file to create/destroy PSOC,
* PDEV, VDEV and PEER objects.
*/
#include <wlan_hdd_object_manager.h>
int hdd_create_and_store_psoc(hdd_context_t *hdd_ctx, uint8_t psoc_id)
{
struct wlan_objmgr_psoc *psoc;
psoc = wlan_objmgr_psoc_obj_create(psoc_id, WLAN_DEV_OL);
if (!psoc)
return -ENOMEM;
hdd_ctx->hdd_psoc = psoc;
return 0;
}
int hdd_release_and_destroy_psoc(hdd_context_t *hdd_ctx)
{
struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
hdd_ctx->hdd_psoc = NULL;
if (!psoc)
return -EINVAL;
return qdf_status_to_os_return(wlan_objmgr_psoc_obj_delete(psoc));
}
int hdd_create_and_store_pdev(hdd_context_t *hdd_ctx)
{
struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
struct wlan_objmgr_pdev *pdev;
if (!psoc) {
hdd_err("Psoc NULL");
return -EINVAL;
}
pdev = wlan_objmgr_pdev_obj_create(psoc, NULL);
if (!pdev) {
hdd_err("pdev obj create failed");
return -ENOMEM;
}
hdd_ctx->hdd_pdev = pdev;
return 0;
}
int hdd_release_and_destroy_pdev(hdd_context_t *hdd_ctx)
{
struct wlan_objmgr_pdev *pdev = hdd_ctx->hdd_pdev;
hdd_ctx->hdd_pdev = NULL;
if (!pdev)
return -EINVAL;
return qdf_status_to_os_return(wlan_objmgr_pdev_obj_delete(pdev));
}
int hdd_create_and_store_vdev(struct wlan_objmgr_pdev *pdev,
hdd_adapter_t *adapter)
{
struct wlan_objmgr_vdev *vdev;
struct wlan_objmgr_peer *peer;
struct wlan_vdev_create_params vdev_params;
vdev_params.opmode = adapter->device_mode;
qdf_mem_copy(vdev_params.macaddr, adapter->macAddressCurrent.bytes,
QDF_NET_MAC_ADDR_MAX_LEN);
if (!pdev) {
hdd_err("pdev NULL");
return -EINVAL;
}
vdev = wlan_objmgr_vdev_obj_create(pdev, &vdev_params);
if (!vdev) {
hdd_err("vdev obj create fails");
return -ENOMEM;
}
if (adapter->sessionId != wlan_vdev_get_id(vdev)) {
hdd_err("session id and vdev id mismatch");
wlan_objmgr_vdev_obj_delete(vdev);
QDF_ASSERT(0);
return -EINVAL;
}
peer = wlan_objmgr_peer_obj_create(vdev, WLAN_PEER_SELF,
vdev_params.macaddr);
if (!peer) {
hdd_err("obj manager self peer create fails for adapter %d",
adapter->device_mode);
wlan_objmgr_vdev_obj_delete(vdev);
return -ENOMEM;
}
adapter->hdd_vdev = vdev;
wlan_objmgr_peer_ref_peer(peer);
return 0;
}
int hdd_release_and_destroy_vdev(hdd_adapter_t *adapter)
{
struct wlan_objmgr_vdev *vdev = adapter->hdd_vdev;
adapter->hdd_vdev = NULL;
if (!vdev)
return -EFAULT;
if (hdd_remove_peer_object(vdev,
wlan_vdev_mlme_get_macaddr(vdev))) {
hdd_err("Self peer delete fails");
return -EINVAL;
}
return qdf_status_to_os_return(wlan_objmgr_vdev_obj_delete(vdev));
}
int hdd_add_peer_object(struct wlan_objmgr_vdev *vdev,
enum tQDF_ADAPTER_MODE adapter_mode,
uint8_t *mac_addr)
{
enum wlan_peer_type peer_type;
struct wlan_objmgr_peer *peer;
if ((adapter_mode == QDF_STA_MODE) ||
(adapter_mode == QDF_P2P_CLIENT_MODE)) {
peer_type = WLAN_PEER_AP;
} else if ((adapter_mode == QDF_SAP_MODE) ||
(adapter_mode == QDF_P2P_GO_MODE)) {
peer_type = WLAN_PEER_STA;
} else if (adapter_mode == QDF_IBSS_MODE) {
peer_type = WLAN_PEER_IBSS;
} else {
hdd_err("Unsupported device mode %d", adapter_mode);
return -EINVAL;
}
if (!vdev) {
hdd_err("vdev NULL");
QDF_ASSERT(0);
return -EFAULT;
}
peer = wlan_objmgr_peer_obj_create(vdev, peer_type, mac_addr);
if (!peer)
return -ENOMEM;
wlan_objmgr_peer_ref_peer(peer);
hdd_info("Peer object "MAC_ADDRESS_STR" add success!",
MAC_ADDR_ARRAY(mac_addr));
return 0;
}
int hdd_remove_peer_object(struct wlan_objmgr_vdev *vdev,
uint8_t *mac_addr)
{
struct wlan_objmgr_psoc *psoc;
struct wlan_objmgr_peer *peer;
if (!vdev) {
hdd_err("vdev NULL");
QDF_ASSERT(0);
return -EINVAL;
}
psoc = wlan_vdev_get_psoc(vdev);
if (!psoc) {
hdd_err("Psoc NUll");
QDF_ASSERT(0);
return -EINVAL;
}
peer = wlan_objmgr_find_peer(psoc, mac_addr);
if (peer) {
/* Unref to decrement ref happened in find_peer */
wlan_objmgr_peer_unref_peer(peer);
/*
* Unref to decrement ref of create_peer. This
* is needed until new ref count implementation
* is done. Object manager will delete peer once
* ref count is 0.
*/
wlan_objmgr_peer_unref_peer(peer);
hdd_info("Peer obj "MAC_ADDRESS_STR" deleted",
MAC_ADDR_ARRAY(mac_addr));
return 0;
}
hdd_err("Peer obj "MAC_ADDRESS_STR" not found",
MAC_ADDR_ARRAY(mac_addr));
return -EINVAL;
}
int hdd_set_peer_mlme_state(struct wlan_objmgr_vdev *vdev,
enum wlan_peer_state peer_state)
{
struct wlan_objmgr_peer *peer;
wlan_vdev_obj_lock(vdev);
peer = wlan_vdev_get_bsspeer(vdev);
wlan_vdev_obj_unlock(vdev);
if (!peer) {
hdd_err("peer is null");
return -EINVAL;
}
wlan_peer_obj_lock(peer);
wlan_peer_mlme_set_state(peer, WLAN_ASSOC_STATE);
wlan_peer_obj_unlock(peer);
return 0;
}