ath10k: enable TDLS peer inactivity detection
authorYingying Tang <yintang@qti.qualcomm.com>
Wed, 28 Mar 2018 09:13:07 +0000 (12:13 +0300)
committerKalle Valo <kvalo@codeaurora.org>
Thu, 29 Mar 2018 09:00:06 +0000 (12:00 +0300)
Enable TDLS peer inactivity detetion feature.
QCA6174 firmware(version: WLAN.RM.4.4) support TDLS link inactivity detecting.
Set related parameters in TDLS WMI command to enable this feature.

Signed-off-by: Yingying Tang <yintang@qti.qualcomm.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/ath/ath10k/wmi-tlv.c
drivers/net/wireless/ath/ath10k/wmi-tlv.h
drivers/net/wireless/ath/ath10k/wmi.h

index cb723a7..9d1b0a4 100644 (file)
@@ -426,6 +426,49 @@ static int ath10k_wmi_tlv_event_temperature(struct ath10k *ar,
        return 0;
 }
 
+static void ath10k_wmi_event_tdls_peer(struct ath10k *ar, struct sk_buff *skb)
+{
+       struct ieee80211_sta *station;
+       const struct wmi_tlv_tdls_peer_event *ev;
+       const void **tb;
+       struct ath10k_vif *arvif;
+
+       tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
+       if (IS_ERR(tb)) {
+               ath10k_warn(ar, "tdls peer failed to parse tlv");
+               return;
+       }
+       ev = tb[WMI_TLV_TAG_STRUCT_TDLS_PEER_EVENT];
+       if (!ev) {
+               kfree(tb);
+               ath10k_warn(ar, "tdls peer NULL event");
+               return;
+       }
+
+       switch (__le32_to_cpu(ev->peer_reason)) {
+       case WMI_TDLS_TEARDOWN_REASON_TX:
+       case WMI_TDLS_TEARDOWN_REASON_RSSI:
+       case WMI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT:
+               station = ieee80211_find_sta_by_ifaddr(ar->hw,
+                                                      ev->peer_macaddr.addr,
+                                                      NULL);
+               if (!station) {
+                       ath10k_warn(ar, "did not find station from tdls peer event");
+                       kfree(tb);
+                       return;
+               }
+               arvif = ath10k_get_arvif(ar, __le32_to_cpu(ev->vdev_id));
+               ieee80211_tdls_oper_request(
+                                       arvif->vif, station->addr,
+                                       NL80211_TDLS_TEARDOWN,
+                                       WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE,
+                                       GFP_ATOMIC
+                                       );
+               break;
+       }
+       kfree(tb);
+}
+
 /***********/
 /* TLV ops */
 /***********/
@@ -569,6 +612,9 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb)
        case WMI_TLV_PDEV_TEMPERATURE_EVENTID:
                ath10k_wmi_tlv_event_temperature(ar, skb);
                break;
+       case WMI_TLV_TDLS_PEER_EVENTID:
+               ath10k_wmi_event_tdls_peer(ar, skb);
+               break;
        default:
                ath10k_warn(ar, "Unknown eventid: %d\n", id);
                break;
@@ -2889,6 +2935,12 @@ ath10k_wmi_tlv_op_gen_update_fw_tdls_state(struct ath10k *ar, u32 vdev_id,
        if (test_bit(WMI_SERVICE_TDLS_UAPSD_BUFFER_STA, ar->wmi.svc_map))
                options |=  WMI_TLV_TDLS_BUFFER_STA_EN;
 
+       /* WMI_TDLS_ENABLE_ACTIVE_EXTERNAL_CONTROL means firm will handle TDLS
+        * link inactivity detecting logic.
+        */
+       if (state == WMI_TDLS_ENABLE_ACTIVE)
+               state = WMI_TDLS_ENABLE_ACTIVE_EXTERNAL_CONTROL;
+
        len = sizeof(*tlv) + sizeof(*cmd);
        skb = ath10k_wmi_alloc_skb(ar, len);
        if (!skb)
index b07b690..fa3773e 100644 (file)
@@ -1757,6 +1757,13 @@ struct wmi_tlv_tx_pause_ev {
        __le32 tid_map;
 } __packed;
 
+struct wmi_tlv_tdls_peer_event {
+       struct wmi_mac_addr    peer_macaddr;
+       __le32 peer_status;
+       __le32 peer_reason;
+       __le32 vdev_id;
+} __packed;
+
 void ath10k_wmi_tlv_attach(struct ath10k *ar);
 
 struct wmi_tlv_mgmt_tx_cmd {
index c8fc45d..6da2583 100644 (file)
@@ -6792,6 +6792,7 @@ enum wmi_tdls_state {
        WMI_TDLS_DISABLE,
        WMI_TDLS_ENABLE_PASSIVE,
        WMI_TDLS_ENABLE_ACTIVE,
+       WMI_TDLS_ENABLE_ACTIVE_EXTERNAL_CONTROL,
 };
 
 enum wmi_tdls_peer_state {