mt76: mt7615: add gtk rekey offload support
Add KCK and KEK offload support to mt7615 driver in order to support GTK rekeying during PM suspend Co-developed-by: Sean Wang <sean.wang@mediatek.com> Signed-off-by: Sean Wang <sean.wang@mediatek.com> Co-developed-by: Wan-Feng Jiang <Wan-Feng.Jiang@mediatek.com> Signed-off-by: Wan-Feng Jiang <Wan-Feng.Jiang@mediatek.com> Co-developed-by: Soul Huang <Soul.Huang@mediatek.com> Signed-off-by: Soul Huang <Soul.Huang@mediatek.com> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
parent
6dd4072c1e
commit
b47e21e75c
5 changed files with 142 additions and 1 deletions
|
@ -145,6 +145,7 @@ void mt7615_check_offload_capability(struct mt7615_dev *dev)
|
||||||
dev->ops->cancel_hw_scan = NULL;
|
dev->ops->cancel_hw_scan = NULL;
|
||||||
dev->ops->sched_scan_start = NULL;
|
dev->ops->sched_scan_start = NULL;
|
||||||
dev->ops->sched_scan_stop = NULL;
|
dev->ops->sched_scan_stop = NULL;
|
||||||
|
dev->ops->set_rekey_data = NULL;
|
||||||
|
|
||||||
wiphy->max_sched_scan_plan_interval = 0;
|
wiphy->max_sched_scan_plan_interval = 0;
|
||||||
wiphy->max_sched_scan_ie_len = 0;
|
wiphy->max_sched_scan_ie_len = 0;
|
||||||
|
|
|
@ -936,6 +936,13 @@ static void mt7615_set_wakeup(struct ieee80211_hw *hw, bool enabled)
|
||||||
|
|
||||||
device_set_wakeup_enable(mdev->dev, 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 */
|
#endif /* CONFIG_PM */
|
||||||
|
|
||||||
const struct ieee80211_ops mt7615_ops = {
|
const struct ieee80211_ops mt7615_ops = {
|
||||||
|
@ -975,6 +982,7 @@ const struct ieee80211_ops mt7615_ops = {
|
||||||
.suspend = mt7615_suspend,
|
.suspend = mt7615_suspend,
|
||||||
.resume = mt7615_resume,
|
.resume = mt7615_resume,
|
||||||
.set_wakeup = mt7615_set_wakeup,
|
.set_wakeup = mt7615_set_wakeup,
|
||||||
|
.set_rekey_data = mt7615_set_rekey_data,
|
||||||
#endif /* CONFIG_PM */
|
#endif /* CONFIG_PM */
|
||||||
};
|
};
|
||||||
EXPORT_SYMBOL_GPL(mt7615_ops);
|
EXPORT_SYMBOL_GPL(mt7615_ops);
|
||||||
|
|
|
@ -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_BSS_INFO_UPDATE:
|
||||||
case MCU_UNI_CMD_STA_REC_UPDATE:
|
case MCU_UNI_CMD_STA_REC_UPDATE:
|
||||||
case MCU_UNI_CMD_HIF_CTRL:
|
case MCU_UNI_CMD_HIF_CTRL:
|
||||||
|
case MCU_UNI_CMD_OFFLOAD:
|
||||||
case MCU_UNI_CMD_SUSPEND: {
|
case MCU_UNI_CMD_SUSPEND: {
|
||||||
struct mt7615_mcu_uni_event *event;
|
struct mt7615_mcu_uni_event *event;
|
||||||
|
|
||||||
|
@ -1839,7 +1840,8 @@ mt7615_mcu_send_ram_firmware(struct mt7615_dev *dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wiphy_wowlan_support mt7615_wowlan_support = {
|
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,
|
.n_patterns = 1,
|
||||||
.pattern_min_len = 1,
|
.pattern_min_len = 1,
|
||||||
.pattern_max_len = MT7615_WOW_PATTEN_MAX_LEN,
|
.pattern_max_len = MT7615_WOW_PATTEN_MAX_LEN,
|
||||||
|
@ -3373,6 +3375,33 @@ mt7615_mcu_set_suspend_mode(struct mt7615_dev *dev,
|
||||||
&req, sizeof(req), true);
|
&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,
|
void mt7615_mcu_set_suspend_iter(void *priv, u8 *mac,
|
||||||
struct ieee80211_vif *vif)
|
struct ieee80211_vif *vif)
|
||||||
{
|
{
|
||||||
|
@ -3384,6 +3413,8 @@ void mt7615_mcu_set_suspend_iter(void *priv, u8 *mac,
|
||||||
|
|
||||||
mt7615_mcu_set_bss_pm(phy->dev, vif, suspend);
|
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);
|
mt7615_mcu_set_suspend_mode(phy->dev, vif, suspend, 1, true);
|
||||||
|
|
||||||
for (i = 0; i < wowlan->n_patterns; i++)
|
for (i = 0; i < wowlan->n_patterns; i++)
|
||||||
|
@ -3391,4 +3422,73 @@ void mt7615_mcu_set_suspend_iter(void *priv, u8 *mac,
|
||||||
&wowlan->patterns[i]);
|
&wowlan->patterns[i]);
|
||||||
mt7615_mcu_set_wow_ctrl(phy->dev, vif, suspend, wowlan);
|
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 */
|
#endif /* CONFIG_PM */
|
||||||
|
|
|
@ -281,6 +281,7 @@ enum {
|
||||||
MCU_UNI_CMD_BSS_INFO_UPDATE = MCU_UNI_PREFIX | 0x02,
|
MCU_UNI_CMD_BSS_INFO_UPDATE = MCU_UNI_PREFIX | 0x02,
|
||||||
MCU_UNI_CMD_STA_REC_UPDATE = MCU_UNI_PREFIX | 0x03,
|
MCU_UNI_CMD_STA_REC_UPDATE = MCU_UNI_PREFIX | 0x03,
|
||||||
MCU_UNI_CMD_SUSPEND = MCU_UNI_PREFIX | 0x05,
|
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,
|
MCU_UNI_CMD_HIF_CTRL = MCU_UNI_PREFIX | 0x07,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -469,6 +470,27 @@ struct mt7615_suspend_tlv {
|
||||||
u8 pad[5];
|
u8 pad[5];
|
||||||
} __packed;
|
} __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 */
|
/* offload mcu commands */
|
||||||
enum {
|
enum {
|
||||||
MCU_CMD_START_HW_SCAN = MCU_CE_PREFIX | 0x03,
|
MCU_CMD_START_HW_SCAN = MCU_CE_PREFIX | 0x03,
|
||||||
|
@ -501,6 +523,13 @@ enum {
|
||||||
UNI_SUSPEND_WOW_PATTERN,
|
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 {
|
enum {
|
||||||
PATCH_SEM_RELEASE = 0x0,
|
PATCH_SEM_RELEASE = 0x0,
|
||||||
PATCH_SEM_GET = 0x1
|
PATCH_SEM_GET = 0x1
|
||||||
|
|
|
@ -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);
|
int mt7615_mcu_set_hif_suspend(struct mt7615_dev *dev, bool suspend);
|
||||||
void mt7615_mcu_set_suspend_iter(void *priv, u8 *mac,
|
void mt7615_mcu_set_suspend_iter(void *priv, u8 *mac,
|
||||||
struct ieee80211_vif *vif);
|
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);
|
int __mt7663_load_firmware(struct mt7615_dev *dev);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue