| /* |
| * 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; |
| } |
| |