summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@quicinc.com>2017-12-06 07:00:29 -0800
committerGerrit - the friendly Code Review server <code-review@localhost>2017-12-06 07:00:29 -0800
commit99c39f9b501cbb822796cf95041c8224e0352af5 (patch)
treea7ada214c3443f9567f1934b381b458034a811cb
parent152bcf351e971af28cb709b2edc72deb6ad77a77 (diff)
parentb36f40c0d8832c6882829e9aa112e34e327aac57 (diff)
Merge "ath10k: enable gtk offload for the wcn3990 wlan module"
-rw-r--r--drivers/net/wireless/ath/ath10k/core.h1
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c1
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-ops.h19
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-tlv.c35
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-tlv.h8
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.h14
-rw-r--r--drivers/net/wireless/ath/ath10k/wow.c68
-rw-r--r--drivers/net/wireless/ath/ath10k/wow.h4
8 files changed, 147 insertions, 3 deletions
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index f194d434b97c..2ef2e1ec040a 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -433,6 +433,7 @@ struct ath10k_vif {
struct cfg80211_bitrate_mask bitrate_mask;
struct wmi_ns_arp_offload_req arp_offload;
struct wmi_ns_arp_offload_req ns_offload;
+ struct wmi_gtk_rekey_data gtk_rekey_data;
};
struct ath10k_vif_iter {
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 9fcc2866d830..16a5c5fd3925 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -7583,6 +7583,7 @@ static const struct ieee80211_ops ath10k_ops = {
.suspend = ath10k_wow_op_suspend,
.resume = ath10k_wow_op_resume,
.set_wakeup = ath10k_wow_op_set_wakeup,
+ .set_rekey_data = ath10k_wow_op_set_rekey_data,
#endif
#ifdef CONFIG_MAC80211_DEBUGFS
.sta_add_debugfs = ath10k_sta_add_debugfs,
diff --git a/drivers/net/wireless/ath/ath10k/wmi-ops.h b/drivers/net/wireless/ath/ath10k/wmi-ops.h
index dcb0da51530a..cf738efd45c5 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-ops.h
+++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h
@@ -162,6 +162,8 @@ struct wmi_ops {
const struct wmi_sta_keepalive_arg *arg);
struct sk_buff *(*gen_set_arp_ns_offload)(struct ath10k *ar,
struct ath10k_vif *arvif);
+ struct sk_buff *(*gen_gtk_offload)(struct ath10k *ar,
+ struct ath10k_vif *arvif);
struct sk_buff *(*gen_wow_enable)(struct ath10k *ar);
struct sk_buff *(*gen_wow_add_wakeup_event)(struct ath10k *ar, u32 vdev_id,
enum wmi_wow_wakeup_event event,
@@ -1206,6 +1208,23 @@ ath10k_wmi_set_arp_ns_offload(struct ath10k *ar, struct ath10k_vif *arvif)
}
static inline int
+ath10k_wmi_gtk_offload(struct ath10k *ar, struct ath10k_vif *arvif)
+{
+ struct sk_buff *skb;
+ u32 cmd_id;
+
+ if (!ar->wmi.ops->gen_gtk_offload)
+ return -EOPNOTSUPP;
+
+ skb = ar->wmi.ops->gen_gtk_offload(ar, arvif);
+ if (IS_ERR(skb))
+ return PTR_ERR(skb);
+
+ cmd_id = ar->wmi.cmd->gtk_offload_cmdid;
+ return ath10k_wmi_cmd_send(ar, skb, cmd_id);
+}
+
+static inline int
ath10k_wmi_wow_enable(struct ath10k *ar)
{
struct sk_buff *skb;
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
index ad27abc61deb..5ce4fdfca724 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
@@ -3015,6 +3015,40 @@ ath10k_wmi_tlv_op_gen_tdls_peer_update(struct ath10k *ar,
}
static struct sk_buff *
+ath10k_wmi_op_gen_gtk_offload(struct ath10k *ar, struct ath10k_vif *arvif)
+{
+ struct wmi_tlv_gtk_offload_cmd *cmd;
+ struct wmi_tlv *tlv;
+ struct sk_buff *skb;
+ struct wmi_gtk_rekey_data *rekey_data = &arvif->gtk_rekey_data;
+ int len;
+
+ len = sizeof(*cmd) + sizeof(*tlv);
+ skb = ath10k_wmi_alloc_skb(ar, len);
+ if (!skb)
+ return ERR_PTR(-ENOMEM);
+
+ tlv = (void *)skb->data;
+ tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_GTK_OFFLOAD_CMD);
+ tlv->len = __cpu_to_le16(sizeof(*cmd));
+ cmd = (void *)tlv->value;
+ if (rekey_data->enable_offload) {
+ cmd->vdev_id = __cpu_to_le32(arvif->vdev_id);
+ cmd->flags |= __cpu_to_le32(WMI_GTK_OFFLOAD_ENABLE_OPCODE);
+ memcpy(cmd->kek, rekey_data->kek, NL80211_KEK_LEN);
+ memcpy(cmd->kck, rekey_data->kck, NL80211_KCK_LEN);
+ cmd->replay_ctr = __cpu_to_le64(rekey_data->replay_ctr);
+ } else {
+ cmd->vdev_id = __cpu_to_le32(arvif->vdev_id);
+ cmd->flags |= __cpu_to_le32(WMI_GTK_OFFLOAD_DISABLE_OPCODE);
+ }
+
+ ath10k_dbg(ar, ATH10K_DBG_WMI,
+ "wmi GTK offload for vdev: %d\n", arvif->vdev_id);
+ return skb;
+}
+
+static struct sk_buff *
ath10k_wmi_tlv_op_gen_set_arp_ns_offload(struct ath10k *ar,
struct ath10k_vif *arvif)
{
@@ -3778,6 +3812,7 @@ static const struct wmi_ops wmi_tlv_ops = {
.gen_vdev_sta_uapsd = ath10k_wmi_tlv_op_gen_vdev_sta_uapsd,
.gen_sta_keepalive = ath10k_wmi_tlv_op_gen_sta_keepalive,
.gen_set_arp_ns_offload = ath10k_wmi_tlv_op_gen_set_arp_ns_offload,
+ .gen_gtk_offload = ath10k_wmi_op_gen_gtk_offload,
.gen_wow_enable = ath10k_wmi_tlv_op_gen_wow_enable,
.gen_wow_add_wakeup_event = ath10k_wmi_tlv_op_gen_wow_add_wakeup_event,
.gen_wow_host_wakeup_ind = ath10k_wmi_tlv_gen_wow_host_wakeup_ind,
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h
index 39951d273244..18327daade8d 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h
@@ -1567,6 +1567,14 @@ struct wmi_tlv_arp_ns_offload_cmd {
__le32 num_ns_ext_tuples;
} __packed;
+struct wmi_tlv_gtk_offload_cmd {
+ __le32 vdev_id;
+ __le32 flags;
+ u8 kek[NL80211_KEK_LEN];
+ u8 kck[NL80211_KCK_LEN];
+ __le64 replay_ctr;
+} __packed;
+
struct wmi_tlv_wow_host_wakeup_ind {
__le32 reserved;
} __packed;
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 44c237eec157..2694b6aa8b77 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -2933,6 +2933,20 @@ struct wmi_arp_offload {
struct wmi_mac_addr target_mac;
} __packed;
+/* GTK offload data structure */
+#define WMI_GTK_OFFLOAD_ENABLE_OPCODE BIT(24)
+#define WMI_GTK_OFFLOAD_DISABLE_OPCODE BIT(25)
+#define WMI_GTK_OFFLOAD_ENABLE 1
+#define WMI_GTK_OFFLOAD_DISABLE 0
+
+struct wmi_gtk_rekey_data {
+ bool valid;
+ bool enable_offload;
+ u8 kck[NL80211_KCK_LEN];
+ u8 kek[NL80211_KEK_LEN];
+ __le64 replay_ctr;
+} __packed;
+
struct wmi_start_scan_tlvs {
/* TLV parameters. These includes channel list, ssid list, bssid list,
* extra ies.
diff --git a/drivers/net/wireless/ath/ath10k/wow.c b/drivers/net/wireless/ath/ath10k/wow.c
index 429fcce3dd1e..6bbcf8b79d9a 100644
--- a/drivers/net/wireless/ath/ath10k/wow.c
+++ b/drivers/net/wireless/ath/ath10k/wow.c
@@ -320,6 +320,56 @@ static int ath10k_config_wow_listen_interval(struct ath10k *ar)
return 0;
}
+void ath10k_wow_op_set_rekey_data(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct cfg80211_gtk_rekey_data *data)
+{
+ struct ath10k *ar = hw->priv;
+ struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+
+ mutex_lock(&ar->conf_mutex);
+ memcpy(&arvif->gtk_rekey_data.kek, data->kek, NL80211_KEK_LEN);
+ memcpy(&arvif->gtk_rekey_data.kck, data->kck, NL80211_KCK_LEN);
+ arvif->gtk_rekey_data.replay_ctr =
+ __cpu_to_le64(*(__le64 *)data->replay_ctr);
+ arvif->gtk_rekey_data.valid = true;
+ mutex_unlock(&ar->conf_mutex);
+}
+
+static int ath10k_wow_config_gtk_offload(struct ath10k *ar, bool gtk_offload)
+{
+ struct ath10k_vif *arvif;
+ struct ieee80211_bss_conf *bss;
+ struct wmi_gtk_rekey_data *rekey_data;
+ int ret;
+
+ list_for_each_entry(arvif, &ar->arvifs, list) {
+ if (arvif->vdev_type != WMI_VDEV_TYPE_STA)
+ continue;
+
+ bss = &arvif->vif->bss_conf;
+ if (!arvif->is_up || !bss->assoc)
+ continue;
+
+ rekey_data = &arvif->gtk_rekey_data;
+ if (!rekey_data->valid)
+ continue;
+
+ if (gtk_offload)
+ rekey_data->enable_offload = WMI_GTK_OFFLOAD_ENABLE;
+ else
+ rekey_data->enable_offload = WMI_GTK_OFFLOAD_DISABLE;
+ ret = ath10k_wmi_gtk_offload(ar, arvif);
+ if (ret) {
+ ath10k_err(ar, "GTK offload failed for vdev_id: %d\n",
+ arvif->vdev_id);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
int ath10k_wow_op_suspend(struct ieee80211_hw *hw,
struct cfg80211_wowlan *wowlan)
{
@@ -334,10 +384,16 @@ int ath10k_wow_op_suspend(struct ieee80211_hw *hw,
goto exit;
}
+ ret = ath10k_wow_config_gtk_offload(ar, true);
+ if (ret) {
+ ath10k_warn(ar, "failed to enable GTK offload: %d\n", ret);
+ goto exit;
+ }
+
ret = ath10k_wow_enable_ns_arp_offload(ar, true);
if (ret) {
ath10k_warn(ar, "failed to enable ARP-NS offload: %d\n", ret);
- goto exit;
+ goto disable_gtk_offload;
}
ret = ath10k_wow_cleanup(ar);
@@ -384,6 +440,8 @@ cleanup:
disable_ns_arp_offload:
ath10k_wow_enable_ns_arp_offload(ar, false);
+disable_gtk_offload:
+ ath10k_wow_config_gtk_offload(ar, false);
exit:
mutex_unlock(&ar->conf_mutex);
return ret ? 1 : 0;
@@ -427,8 +485,14 @@ int ath10k_wow_op_resume(struct ieee80211_hw *hw)
}
ret = ath10k_wow_enable_ns_arp_offload(ar, false);
- if (ret)
+ if (ret) {
ath10k_warn(ar, "failed to disable ARP-NS offload: %d\n", ret);
+ goto exit;
+ }
+
+ ret = ath10k_wow_config_gtk_offload(ar, false);
+ if (ret)
+ ath10k_warn(ar, "failed to disable GTK offload: %d\n", ret);
exit:
if (ret) {
diff --git a/drivers/net/wireless/ath/ath10k/wow.h b/drivers/net/wireless/ath/ath10k/wow.h
index 9745b9ddc7f5..ce79908cce19 100644
--- a/drivers/net/wireless/ath/ath10k/wow.h
+++ b/drivers/net/wireless/ath/ath10k/wow.h
@@ -29,7 +29,9 @@ int ath10k_wow_op_suspend(struct ieee80211_hw *hw,
struct cfg80211_wowlan *wowlan);
int ath10k_wow_op_resume(struct ieee80211_hw *hw);
void ath10k_wow_op_set_wakeup(struct ieee80211_hw *hw, bool enabled);
-
+void ath10k_wow_op_set_rekey_data(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct cfg80211_gtk_rekey_data *data);
#else
static inline int ath10k_wow_init(struct ath10k *ar)