From f0f46ac045c23d9a1b761eb352b91d4ae598e1c2 Mon Sep 17 00:00:00 2001 From: Frank Liu Date: Thu, 16 Mar 2017 19:28:51 +0800 Subject: [PATCH] qcacmn: TDLS component: handle TDLS firmware event Handle TDLS related firmware event: tear down, discovery, disconnect, and send correspond indication to upper layer Change-Id: I6cff95904d06408f9458132ab5ce69f1a129e993 CRs-Fixed: 2011330 --- umac/tdls/core/src/wlan_tdls_cmds_process.c | 238 ++++++++++++++++++++ umac/tdls/core/src/wlan_tdls_cmds_process.h | 30 +++ umac/tdls/core/src/wlan_tdls_main.c | 41 ++++ umac/tdls/core/src/wlan_tdls_main.h | 5 + 4 files changed, 314 insertions(+) diff --git a/umac/tdls/core/src/wlan_tdls_cmds_process.c b/umac/tdls/core/src/wlan_tdls_cmds_process.c index 1c5d68454bbd..57e718d82d79 100644 --- a/umac/tdls/core/src/wlan_tdls_cmds_process.c +++ b/umac/tdls/core/src/wlan_tdls_cmds_process.c @@ -1611,3 +1611,241 @@ error: return status; } + +static const char *tdls_evt_to_str(enum tdls_event_msg_type type) +{ + switch (type) { + case TDLS_SHOULD_DISCOVER: + return "SHOULD_DISCOVER"; + case TDLS_SHOULD_TEARDOWN: + return "SHOULD_TEARDOWN"; + case TDLS_PEER_DISCONNECTED: + return "SHOULD_PEER_DISCONNECTED"; + case TDLS_CONNECTION_TRACKER_NOTIFY: + return "CONNECTION_TRACKER_NOTIFICATION"; + default: + return "INVALID_TYPE"; + } +} + +static void +tdls_implicit_send_discovery_request(struct tdls_vdev_priv_obj *vdev_obj) +{ + struct tdls_soc_priv_obj *soc_obj; + struct tdls_peer *curr_peer, *temp_peer; + struct tdls_osif_indication ind; + + if (!vdev_obj) { + tdls_err("vdev_obj is NULL"); + return; + } + + soc_obj = wlan_vdev_get_tdls_soc_obj(vdev_obj->vdev); + if (!soc_obj) { + tdls_err("soc_obj is NULL"); + return; + } + + curr_peer = vdev_obj->curr_candidate; + if (!curr_peer) { + tdls_err("curr_peer is NULL"); + return; + } + + temp_peer = tdls_is_progress(vdev_obj, NULL, 0); + if (temp_peer) { + tdls_notice(QDF_MAC_ADDRESS_STR " ongoing. pre_setup ignored", + QDF_MAC_ADDR_ARRAY(temp_peer->peer_mac.bytes)); + goto done; + } + + if (TDLS_CAP_UNKNOWN != curr_peer->tdls_support) + tdls_set_peer_link_status(curr_peer, TDLS_LINK_DISCOVERING, + TDLS_LINK_SUCCESS); + + tdls_debug("Implicit TDLS, Send Discovery request event"); + + qdf_mem_copy(ind.peer_mac, curr_peer->peer_mac.bytes, + QDF_MAC_ADDR_SIZE); + ind.vdev = vdev_obj->vdev; + + if (soc_obj->tdls_event_cb) + soc_obj->tdls_event_cb(soc_obj->tdls_evt_cb_data, + TDLS_EVENT_DISCOVERY_REQ, &ind); + + vdev_obj->discovery_sent_cnt++; + /*TODO restart peer discovery timeout*/ + + tdls_debug("discovery count %u, timeout %u msec", + vdev_obj->discovery_sent_cnt, + vdev_obj->threshold_config.tx_period_t - + TDLS_DISCOVERY_TIMEOUT_BEFORE_UPDATE); +done: + vdev_obj->curr_candidate = NULL; + vdev_obj->magic = 0; +} + +QDF_STATUS tdls_process_should_discover(struct wlan_objmgr_vdev *vdev, + struct tdls_event_info *evt) +{ + struct tdls_soc_priv_obj *soc_obj; + struct tdls_vdev_priv_obj *vdev_obj; + struct tdls_peer *curr_peer; + uint32_t feature; + uint16_t type; + + /*TODO ignore this if any concurrency detected*/ + soc_obj = wlan_vdev_get_tdls_soc_obj(vdev); + vdev_obj = wlan_vdev_get_tdls_vdev_obj(vdev); + type = evt->message_type; + + tdls_debug("TDLS %s: " QDF_MAC_ADDRESS_STR "reason %d", + tdls_evt_to_str(type), + QDF_MAC_ADDR_ARRAY(evt->peermac.bytes), + evt->peer_reason); + if (!soc_obj || !vdev_obj) { + tdls_err("soc_obj: %p, vdev_obj: %p, ignore %s", + soc_obj, vdev_obj, tdls_evt_to_str(type)); + return QDF_STATUS_E_NULL_VALUE; + } + if (soc_obj->tdls_nss_switch_in_progress) { + tdls_err("TDLS antenna switching, ignore %s", + tdls_evt_to_str(type)); + return QDF_STATUS_SUCCESS; + } + + curr_peer = tdls_get_peer(vdev_obj, evt->peermac.bytes); + if (!curr_peer) { + tdls_notice("curr_peer is null"); + return QDF_STATUS_E_NULL_VALUE; + } + + if (TDLS_LINK_CONNECTED == curr_peer->link_status) { + tdls_err("TDLS link status is connected, ignore"); + return QDF_STATUS_SUCCESS; + } + + feature = soc_obj->tdls_configs.tdls_feature_flags; + if (TDLS_IS_EXTERNAL_CONTROL_ENABLED(feature) && + !curr_peer->is_forced_peer) { + tdls_debug("curr_peer is not forced, ignore %s", + tdls_evt_to_str(type)); + return QDF_STATUS_SUCCESS; + } + + tdls_debug("initiate TDLS setup on %s, ext: %d, force: %d, reason: %d", + tdls_evt_to_str(type), + TDLS_IS_EXTERNAL_CONTROL_ENABLED(feature), + curr_peer->is_forced_peer, evt->peer_reason); + vdev_obj->curr_candidate = curr_peer; + tdls_implicit_send_discovery_request(vdev_obj); + + return QDF_STATUS_SUCCESS; +} + +static void +tdls_indicate_teardown(struct tdls_vdev_priv_obj *vdev_obj, + struct tdls_peer *curr_peer, uint16_t reason) +{ + struct tdls_soc_priv_obj *soc_obj; + struct tdls_osif_indication ind; + + soc_obj = wlan_vdev_get_tdls_soc_obj(vdev_obj->vdev); + if (!soc_obj || !vdev_obj || !curr_peer) { + tdls_err("soc_obj: %p, vdev_obj: %p, curr_peer: %p", + soc_obj, vdev_obj, curr_peer); + return; + } + + if (TDLS_LINK_CONNECTED != curr_peer->link_status) { + tdls_debug("peer not connected"); + return; + } + + tdls_set_peer_link_status(curr_peer, TDLS_LINK_TEARING, + TDLS_LINK_UNSPECIFIED); + + tdls_debug("Teardown peer " QDF_MAC_ADDRESS_STR "reason %d", + QDF_MAC_ADDR_ARRAY(curr_peer->peer_mac.bytes), reason); + + qdf_mem_copy(ind.peer_mac, curr_peer->peer_mac.bytes, + QDF_MAC_ADDR_SIZE); + ind.reason = reason; + ind.vdev = vdev_obj->vdev; + + if (soc_obj->tdls_event_cb) + soc_obj->tdls_event_cb(soc_obj->tdls_evt_cb_data, + TDLS_EVENT_TEARDOWN_REQ, &ind); +} + +QDF_STATUS tdls_process_should_teardown(struct wlan_objmgr_vdev *vdev, + struct tdls_event_info *evt) +{ + struct tdls_soc_priv_obj *soc_obj; + struct tdls_vdev_priv_obj *vdev_obj; + struct tdls_peer *curr_peer; + uint32_t reason; + uint16_t type; + + type = evt->message_type; + soc_obj = wlan_vdev_get_tdls_soc_obj(vdev); + vdev_obj = wlan_vdev_get_tdls_vdev_obj(vdev); + + tdls_debug("TDLS %s: " QDF_MAC_ADDRESS_STR "reason %d", + tdls_evt_to_str(type), + QDF_MAC_ADDR_ARRAY(evt->peermac.bytes), evt->peer_reason); + + if (!soc_obj || !vdev_obj) { + tdls_err("soc_obj: %p, vdev_obj: %p, ignore %s", + soc_obj, vdev_obj, tdls_evt_to_str(type)); + return QDF_STATUS_E_NULL_VALUE; + } + + curr_peer = tdls_find_peer(vdev_obj, evt->peermac.bytes); + if (!curr_peer) { + tdls_notice("curr_peer is null"); + return QDF_STATUS_E_NULL_VALUE; + } + + reason = evt->peer_reason; + if (TDLS_LINK_CONNECTED == curr_peer->link_status) { + tdls_err("%s reason: %d for" QDF_MAC_ADDRESS_STR, + tdls_evt_to_str(type), evt->peer_reason, + QDF_MAC_ADDR_ARRAY(evt->peermac.bytes)); + if (reason == TDLS_TEARDOWN_RSSI || + reason == TDLS_DISCONNECTED_PEER_DELETE || + reason == TDLS_TEARDOWN_PTR_TIMEOUT || + reason == TDLS_TEARDOWN_NO_RSP) + reason = TDLS_TEARDOWN_PEER_UNREACHABLE; + else + reason = TDLS_TEARDOWN_PEER_UNSPEC_REASON; + + tdls_indicate_teardown(vdev_obj, curr_peer, reason); + } else { + tdls_err("TDLS link is not connected, ignore %s", + tdls_evt_to_str(type)); + } + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS tdls_process_connection_tracker_notify(struct wlan_objmgr_vdev *vdev, + struct tdls_event_info *evt) +{ + struct tdls_soc_priv_obj *soc_obj; + struct tdls_vdev_priv_obj *vdev_obj; + uint16_t type; + + type = evt->message_type; + soc_obj = wlan_vdev_get_tdls_soc_obj(vdev); + vdev_obj = wlan_vdev_get_tdls_vdev_obj(vdev); + + if (!soc_obj || !vdev_obj) { + tdls_err("soc_obj: %p, vdev_obj: %p, ignore %s", + soc_obj, vdev_obj, tdls_evt_to_str(type)); + return QDF_STATUS_E_NULL_VALUE; + } + + /*TODO connection tracker update*/ + return QDF_STATUS_SUCCESS; +} diff --git a/umac/tdls/core/src/wlan_tdls_cmds_process.h b/umac/tdls/core/src/wlan_tdls_cmds_process.h index ff643199b19f..17201b792749 100644 --- a/umac/tdls/core/src/wlan_tdls_cmds_process.h +++ b/umac/tdls/core/src/wlan_tdls_cmds_process.h @@ -220,4 +220,34 @@ QDF_STATUS tdls_process_add_peer_rsp(struct tdls_add_sta_rsp *rsp); * Return: QDF status */ QDF_STATUS tdls_process_del_peer_rsp(struct tdls_del_sta_rsp *rsp); + +/** + * tdls_process_should_discover() - handle tdls should_discover event + * @vdev: vdev object + * @evt: event info + * + * Return: QDF_STATUS + */ +QDF_STATUS tdls_process_should_discover(struct wlan_objmgr_vdev *vdev, + struct tdls_event_info *evt); + +/** + * tdls_process_should_teardown() - handle tdls should_teardown event + * @vdev: vdev object + * @evt: event info + * + * Return: QDF_STATUS + */ +QDF_STATUS tdls_process_should_teardown(struct wlan_objmgr_vdev *vdev, + struct tdls_event_info *evt); + +/** + * tdls_process_connection_tracker_notify() -handle tdls connect tracker notify + * @vdev: vdev object + * @evt: event info + * + * Return: QDF_STATUS + */ +QDF_STATUS tdls_process_connection_tracker_notify(struct wlan_objmgr_vdev *vdev, + struct tdls_event_info *evt); #endif diff --git a/umac/tdls/core/src/wlan_tdls_main.c b/umac/tdls/core/src/wlan_tdls_main.c index 4023edd5e444..a3409b80cf08 100644 --- a/umac/tdls/core/src/wlan_tdls_main.c +++ b/umac/tdls/core/src/wlan_tdls_main.c @@ -239,3 +239,44 @@ QDF_STATUS tdls_process_cmd(struct scheduler_msg *msg) return status; } + +QDF_STATUS tdls_process_evt(struct scheduler_msg *msg) +{ + struct wlan_objmgr_vdev *vdev; + struct tdls_event_notify *notify; + struct tdls_event_info *event; + + if (!msg || !msg->bodyptr) { + tdls_err("msg: %p", msg); + return QDF_STATUS_E_NULL_VALUE; + } + notify = msg->bodyptr; + vdev = notify->vdev; + if (!vdev) { + tdls_err("NULL vdev object"); + qdf_mem_free(notify); + return QDF_STATUS_E_NULL_VALUE; + } + event = ¬ify->event; + + tdls_debug("evt type: %d", event->message_type); + switch (event->message_type) { + case TDLS_SHOULD_DISCOVER: + tdls_process_should_discover(vdev, event); + break; + case TDLS_SHOULD_TEARDOWN: + case TDLS_PEER_DISCONNECTED: + tdls_process_should_teardown(vdev, event); + break; + case TDLS_CONNECTION_TRACKER_NOTIFY: + tdls_process_connection_tracker_notify(vdev, event); + break; + default: + break; + } + + wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_SB_ID); + qdf_mem_free(notify); + + return QDF_STATUS_SUCCESS; +} diff --git a/umac/tdls/core/src/wlan_tdls_main.h b/umac/tdls/core/src/wlan_tdls_main.h index 043250203436..5087c905d97a 100644 --- a/umac/tdls/core/src/wlan_tdls_main.h +++ b/umac/tdls/core/src/wlan_tdls_main.h @@ -49,6 +49,11 @@ #define TDLS_SEC_OFFCHAN_OFFSET_40MINUS (-40) #define TDLS_SEC_OFFCHAN_OFFSET_80 80 #define TDLS_SEC_OFFCHAN_OFFSET_160 160 +/* + * Before UpdateTimer expires, we want to timeout discovery response + * should not be more than 2000. + */ +#define TDLS_DISCOVERY_TIMEOUT_BEFORE_UPDATE 1000 #define tdls_log(level, args...) \ QDF_TRACE(QDF_MODULE_ID_TDLS, level, ## args)