@@ -488,6 +488,7 @@ enum P2P_MODES {
#define EVENT_UAP_MIC_COUNTERMEASURES 0x0000004c
#define EVENT_HOSTWAKE_STAIE 0x0000004d
#define EVENT_CHANNEL_SWITCH_ANN 0x00000050
+#define EVENT_TDLS_GENERIC_EVENT 0x00000052
#define EVENT_EXT_SCAN_REPORT 0x00000058
#define EVENT_REMAIN_ON_CHAN_EXPIRED 0x0000005f
@@ -520,6 +521,7 @@ enum P2P_MODES {
#define ACT_TDLS_DELETE 0x00
#define ACT_TDLS_CREATE 0x01
#define ACT_TDLS_CONFIG 0x02
+#define TDLS_EVENT_LINK_TEAR_DOWN 3
#define MWIFIEX_FW_V15 15
@@ -1753,6 +1755,15 @@ struct host_cmd_ds_802_11_subsc_evt {
__le16 events;
} __packed;
+struct mwifiex_tdls_generic_event {
+ __le16 type;
+ u8 peer_mac[ETH_ALEN];
+ union {
+ __le16 reason_code;
+ __le16 reserved;
+ } u;
+} __packed;
+
struct mwifiex_ie {
__le16 ie_index;
__le16 mgmt_subtype_mask;
@@ -134,6 +134,42 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason_code)
netif_carrier_off(priv->netdev);
}
+static int mwifiex_parse_tdls_event(struct mwifiex_private *priv,
+ struct sk_buff *event_skb)
+{
+ struct mwifiex_adapter *adapter = priv->adapter;
+ struct mwifiex_sta_node *sta_ptr;
+ struct mwifiex_tdls_generic_event *tdls_evt =
+ (void *)event_skb->data + sizeof(adapter->event_cause);
+
+ /* reserved 2 bytes are not mandatory in tdls event */
+ if (event_skb->len < (sizeof(struct mwifiex_tdls_generic_event) -
+ sizeof(u16) - sizeof(adapter->event_cause))) {
+ dev_err(adapter->dev, "Invalid event length!\n");
+ return -1;
+ }
+
+ sta_ptr = mwifiex_get_sta_entry(priv, tdls_evt->peer_mac);
+ if (!sta_ptr) {
+ dev_err(adapter->dev, "cannot get sta entry!\n");
+ return -1;
+ }
+
+ switch (le16_to_cpu(tdls_evt->type)) {
+ case TDLS_EVENT_LINK_TEAR_DOWN:
+ cfg80211_tdls_oper_request(priv->netdev,
+ tdls_evt->peer_mac,
+ NL80211_TDLS_TEARDOWN,
+ le16_to_cpu(tdls_evt->u.reason_code),
+ GFP_KERNEL);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
/*
* This function handles events generated by firmware.
*
@@ -459,6 +495,10 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
false);
break;
+ case EVENT_TDLS_GENERIC_EVENT:
+ ret = mwifiex_parse_tdls_event(priv, adapter->event_skb);
+ break;
+
default:
dev_dbg(adapter->dev, "event: unknown event id: %#x\n",
eventcause);