ソースを参照

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
Frank Liu 8 年 前
コミット
f0f46ac045

+ 238 - 0
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;
+}

+ 30 - 0
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

+ 41 - 0
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 = &notify->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;
+}

+ 5 - 0
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)