Skip to content

Commit

Permalink
mt76: mt7615: add gtk rekey offload support
Browse files Browse the repository at this point in the history
Add KCK and KEK offload support to mt7615 driver in order to
support GTK rekeying during PM suspend

Co-developed-by: Sean Wang <[email protected]>
Signed-off-by: Sean Wang <[email protected]>
Co-developed-by: Wan-Feng Jiang <[email protected]>
Signed-off-by: Wan-Feng Jiang <[email protected]>
Co-developed-by: Soul Huang <[email protected]>
Signed-off-by: Soul Huang <[email protected]>
Signed-off-by: Lorenzo Bianconi <[email protected]>
Signed-off-by: Felix Fietkau <[email protected]>
  • Loading branch information
LorenzoBianconi authored and nbd168 committed May 5, 2020
1 parent 20db7e7 commit 523716b
Show file tree
Hide file tree
Showing 5 changed files with 142 additions and 1 deletion.
1 change: 1 addition & 0 deletions mt7615/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ void mt7615_check_offload_capability(struct mt7615_dev *dev)
dev->ops->cancel_hw_scan = NULL;
dev->ops->sched_scan_start = NULL;
dev->ops->sched_scan_stop = NULL;
dev->ops->set_rekey_data = NULL;

wiphy->max_sched_scan_plan_interval = 0;
wiphy->max_sched_scan_ie_len = 0;
Expand Down
8 changes: 8 additions & 0 deletions mt7615/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -935,6 +935,13 @@ static void mt7615_set_wakeup(struct ieee80211_hw *hw, bool enabled)

device_set_wakeup_enable(mdev->dev, enabled);
}

static void mt7615_set_rekey_data(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct cfg80211_gtk_rekey_data *data)
{
mt7615_mcu_update_gtk_rekey(hw, vif, data);
}
#endif /* CONFIG_PM */

const struct ieee80211_ops mt7615_ops = {
Expand Down Expand Up @@ -974,6 +981,7 @@ const struct ieee80211_ops mt7615_ops = {
.suspend = mt7615_suspend,
.resume = mt7615_resume,
.set_wakeup = mt7615_set_wakeup,
.set_rekey_data = mt7615_set_rekey_data,
#endif /* CONFIG_PM */
};
EXPORT_SYMBOL_GPL(mt7615_ops);
Expand Down
102 changes: 101 additions & 1 deletion mt7615/mcu.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ mt7615_mcu_parse_response(struct mt7615_dev *dev, int cmd,
case MCU_UNI_CMD_BSS_INFO_UPDATE:
case MCU_UNI_CMD_STA_REC_UPDATE:
case MCU_UNI_CMD_HIF_CTRL:
case MCU_UNI_CMD_OFFLOAD:
case MCU_UNI_CMD_SUSPEND: {
struct mt7615_mcu_uni_event *event;

Expand Down Expand Up @@ -1839,7 +1840,8 @@ mt7615_mcu_send_ram_firmware(struct mt7615_dev *dev,
}

static const struct wiphy_wowlan_support mt7615_wowlan_support = {
.flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT,
.flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT |
WIPHY_WOWLAN_SUPPORTS_GTK_REKEY,
.n_patterns = 1,
.pattern_min_len = 1,
.pattern_max_len = MT7615_WOW_PATTEN_MAX_LEN,
Expand Down Expand Up @@ -3373,6 +3375,33 @@ mt7615_mcu_set_suspend_mode(struct mt7615_dev *dev,
&req, sizeof(req), true);
}

static int
mt7615_mcu_set_gtk_rekey(struct mt7615_dev *dev,
struct ieee80211_vif *vif,
bool suspend)
{
struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
struct {
struct {
u8 bss_idx;
u8 pad[3];
} __packed hdr;
struct mt7615_gtk_rekey_tlv gtk_tlv;
} __packed req = {
.hdr = {
.bss_idx = mvif->idx,
},
.gtk_tlv = {
.tag = cpu_to_le16(UNI_OFFLOAD_OFFLOAD_GTK_REKEY),
.len = cpu_to_le16(sizeof(struct mt7615_gtk_rekey_tlv)),
.rekey_mode = !suspend,
},
};

return __mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD_OFFLOAD,
&req, sizeof(req), true);
}

void mt7615_mcu_set_suspend_iter(void *priv, u8 *mac,
struct ieee80211_vif *vif)
{
Expand All @@ -3384,11 +3413,82 @@ void mt7615_mcu_set_suspend_iter(void *priv, u8 *mac,

mt7615_mcu_set_bss_pm(phy->dev, vif, suspend);

mt7615_mcu_set_gtk_rekey(phy->dev, vif, suspend);

mt7615_mcu_set_suspend_mode(phy->dev, vif, suspend, 1, true);

for (i = 0; i < wowlan->n_patterns; i++)
mt7615_mcu_set_wow_pattern(phy->dev, vif, i, suspend,
&wowlan->patterns[i]);
mt7615_mcu_set_wow_ctrl(phy->dev, vif, suspend, wowlan);
}

static void
mt7615_mcu_key_iter(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, struct ieee80211_key_conf *key,
void *data)
{
struct mt7615_gtk_rekey_tlv *gtk_tlv = data;
u32 cipher;

if (key->cipher != WLAN_CIPHER_SUITE_AES_CMAC &&
key->cipher != WLAN_CIPHER_SUITE_CCMP &&
key->cipher != WLAN_CIPHER_SUITE_TKIP)
return;

if (key->cipher == WLAN_CIPHER_SUITE_TKIP) {
gtk_tlv->proto = cpu_to_le32(NL80211_WPA_VERSION_1);
cipher = BIT(3);
} else {
gtk_tlv->proto = cpu_to_le32(NL80211_WPA_VERSION_2);
cipher = BIT(4);
}

/* we are assuming here to have a single pairwise key */
if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
gtk_tlv->pairwise_cipher = cpu_to_le32(cipher);
gtk_tlv->group_cipher = cpu_to_le32(cipher);
gtk_tlv->keyid = key->keyidx;
}
}

int mt7615_mcu_update_gtk_rekey(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct cfg80211_gtk_rekey_data *key)
{
struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;
struct mt7615_dev *dev = mt7615_hw_dev(hw);
struct mt7615_gtk_rekey_tlv *gtk_tlv;
struct sk_buff *skb;
struct {
u8 bss_idx;
u8 pad[3];
} __packed hdr = {
.bss_idx = mvif->idx,
};

skb = mt76_mcu_msg_alloc(&dev->mt76, NULL,
sizeof(hdr) + sizeof(*gtk_tlv));
if (!skb)
return -ENOMEM;

skb_put_data(skb, &hdr, sizeof(hdr));
gtk_tlv = (struct mt7615_gtk_rekey_tlv *)skb_put(skb,
sizeof(*gtk_tlv));
gtk_tlv->tag = cpu_to_le16(UNI_OFFLOAD_OFFLOAD_GTK_REKEY);
gtk_tlv->len = cpu_to_le16(sizeof(*gtk_tlv));
gtk_tlv->rekey_mode = 2;
gtk_tlv->option = 1;

rcu_read_lock();
ieee80211_iter_keys_rcu(hw, vif, mt7615_mcu_key_iter, gtk_tlv);
rcu_read_unlock();

memcpy(gtk_tlv->kek, key->kek, NL80211_KEK_LEN);
memcpy(gtk_tlv->kck, key->kck, NL80211_KCK_LEN);
memcpy(gtk_tlv->replay_ctr, key->replay_ctr, NL80211_REPLAY_CTR_LEN);

return __mt76_mcu_skb_send_msg(&dev->mt76, skb,
MCU_UNI_CMD_OFFLOAD, true);
}
#endif /* CONFIG_PM */
29 changes: 29 additions & 0 deletions mt7615/mcu.h
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ enum {
MCU_UNI_CMD_BSS_INFO_UPDATE = MCU_UNI_PREFIX | 0x02,
MCU_UNI_CMD_STA_REC_UPDATE = MCU_UNI_PREFIX | 0x03,
MCU_UNI_CMD_SUSPEND = MCU_UNI_PREFIX | 0x05,
MCU_UNI_CMD_OFFLOAD = MCU_UNI_PREFIX | 0x06,
MCU_UNI_CMD_HIF_CTRL = MCU_UNI_PREFIX | 0x07,
};

Expand Down Expand Up @@ -469,6 +470,27 @@ struct mt7615_suspend_tlv {
u8 pad[5];
} __packed;

struct mt7615_gtk_rekey_tlv {
__le16 tag;
__le16 len;
u8 kek[NL80211_KEK_LEN];
u8 kck[NL80211_KCK_LEN];
u8 replay_ctr[NL80211_REPLAY_CTR_LEN];
u8 rekey_mode; /* 0: rekey offload enable
* 1: rekey offload disable
* 2: rekey update
*/
u8 keyid;
u8 pad[2];
__le32 proto; /* WPA-RSN-WAPI-OPSN */
__le32 pairwise_cipher;
__le32 group_cipher;
__le32 key_mgmt; /* NONE-PSK-IEEE802.1X */
__le32 mgmt_group_cipher;
u8 option; /* 1: rekey data update without enabling offload */
u8 reserverd[3];
} __packed;

/* offload mcu commands */
enum {
MCU_CMD_START_HW_SCAN = MCU_CE_PREFIX | 0x03,
Expand Down Expand Up @@ -501,6 +523,13 @@ enum {
UNI_SUSPEND_WOW_PATTERN,
};

enum {
UNI_OFFLOAD_OFFLOAD_ARPNS_IPV4,
UNI_OFFLOAD_OFFLOAD_ARPNS_IPV6,
UNI_OFFLOAD_OFFLOAD_GTK_REKEY,
UNI_OFFLOAD_OFFLOAD_BMC_RPY_DETECT,
};

enum {
PATCH_SEM_RELEASE = 0x0,
PATCH_SEM_GET = 0x1
Expand Down
3 changes: 3 additions & 0 deletions mt7615/mt7615.h
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,9 @@ int mt7615_mcu_wait_response(struct mt7615_dev *dev, int cmd, int seq);
int mt7615_mcu_set_hif_suspend(struct mt7615_dev *dev, bool suspend);
void mt7615_mcu_set_suspend_iter(void *priv, u8 *mac,
struct ieee80211_vif *vif);
int mt7615_mcu_update_gtk_rekey(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct cfg80211_gtk_rekey_data *key);

int __mt7663_load_firmware(struct mt7615_dev *dev);

Expand Down

0 comments on commit 523716b

Please sign in to comment.