mirror of
https://github.com/outbackdingo/mt76.git
synced 2026-10-24 13:26:48 +00:00
mt7603: implement hardware crypto support for unicast
Signed-off-by: Felix Fietkau <[email protected]>
This commit is contained in:
@@ -190,6 +190,8 @@ void mt7603_wtbl_init(struct mt7603_dev *dev, int idx, const u8 *addr);
|
||||
void mt7603_wtbl_clear(struct mt7603_dev *dev, int idx);
|
||||
void mt7603_wtbl_update_cap(struct mt7603_dev *dev, struct ieee80211_sta *sta);
|
||||
void mt7603_wtbl_set_rates(struct mt7603_dev *dev, struct mt7603_sta *sta);
|
||||
int mt7603_wtbl_set_key(struct mt7603_dev *dev, int wcid,
|
||||
struct ieee80211_key_conf *key);
|
||||
|
||||
int mt7603_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
struct sk_buff *skb, struct mt76_wcid *wcid,
|
||||
|
||||
+87
-9
@@ -79,6 +79,12 @@ mt7603_wtbl_update(struct mt7603_dev *dev, int idx, u32 mask)
|
||||
mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000);
|
||||
}
|
||||
|
||||
static u32
|
||||
mt7603_wtbl1_addr(int idx)
|
||||
{
|
||||
return MT_WTBL1_BASE + idx * MT_WTBL1_SIZE;
|
||||
}
|
||||
|
||||
static u32
|
||||
mt7603_wtbl2_addr(int idx)
|
||||
{
|
||||
@@ -87,9 +93,10 @@ mt7603_wtbl2_addr(int idx)
|
||||
}
|
||||
|
||||
static u32
|
||||
mt7603_wtbl1_addr(int idx)
|
||||
mt7603_wtbl3_addr(int idx)
|
||||
{
|
||||
return MT_WTBL1_BASE + idx * MT_WTBL1_SIZE;
|
||||
u32 base = mt7603_wtbl2_addr(MT7603_WTBL_SIZE);
|
||||
return base + idx * MT_WTBL3_SIZE;
|
||||
}
|
||||
|
||||
void mt7603_wtbl_init(struct mt7603_dev *dev, int idx, const u8 *mac_addr)
|
||||
@@ -165,9 +172,11 @@ void mt7603_wtbl_update_cap(struct mt7603_dev *dev, struct ieee80211_sta *sta)
|
||||
|
||||
addr = mt7603_wtbl1_addr(idx);
|
||||
|
||||
val = MT76_SET(MT_WTBL1_W2_AMPDU_FACTOR, sta->ht_cap.ampdu_factor) |
|
||||
MT76_SET(MT_WTBL1_W2_MPDU_DENSITY, sta->ht_cap.ampdu_density) |
|
||||
MT_WTBL1_W2_TXS_BAF_REPORT;
|
||||
val = mt76_rr(dev, addr + 2 * 4);
|
||||
val &= MT_WTBL1_W2_KEY_TYPE | MT_WTBL1_W2_ADMISSION_CONTROL;
|
||||
val |= MT76_SET(MT_WTBL1_W2_AMPDU_FACTOR, sta->ht_cap.ampdu_factor) |
|
||||
MT76_SET(MT_WTBL1_W2_MPDU_DENSITY, sta->ht_cap.ampdu_density) |
|
||||
MT_WTBL1_W2_TXS_BAF_REPORT;
|
||||
|
||||
if (sta->ht_cap.cap)
|
||||
val |= MT_WTBL1_W2_HT;
|
||||
@@ -314,8 +323,10 @@ mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb)
|
||||
status->flag |= RX_FLAG_MMIC_ERROR;
|
||||
|
||||
if (MT76_GET(MT_RXD2_NORMAL_SEC_MODE, rxd[2]) != 0 &&
|
||||
!(rxd[2] & (MT_RXD2_NORMAL_CLM | MT_RXD2_NORMAL_CM)))
|
||||
!(rxd[2] & (MT_RXD2_NORMAL_CLM | MT_RXD2_NORMAL_CM))) {
|
||||
status->flag |= RX_FLAG_DECRYPTED;
|
||||
status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED;
|
||||
}
|
||||
|
||||
remove_pad = rxd[1] & MT_RXD1_NORMAL_HDR_OFFSET;
|
||||
|
||||
@@ -470,10 +481,75 @@ void mt7603_wtbl_set_rates(struct mt7603_dev *dev, struct mt7603_sta *sta)
|
||||
bw_idx ? bw_idx - 1 : 7);
|
||||
}
|
||||
|
||||
static enum mt7603_cipher_type
|
||||
mt7603_mac_get_key_info(struct ieee80211_key_conf *key, u8 *key_data)
|
||||
{
|
||||
memset(key_data, 0, 32);
|
||||
if (!key)
|
||||
return MT_CIPHER_NONE;
|
||||
|
||||
if (key->keylen > 32)
|
||||
return MT_CIPHER_NONE;
|
||||
|
||||
memcpy(key_data, key->key, key->keylen);
|
||||
|
||||
switch(key->cipher) {
|
||||
case WLAN_CIPHER_SUITE_WEP40:
|
||||
return MT_CIPHER_WEP40;
|
||||
case WLAN_CIPHER_SUITE_WEP104:
|
||||
return MT_CIPHER_WEP104;
|
||||
case WLAN_CIPHER_SUITE_TKIP:
|
||||
return MT_CIPHER_TKIP;
|
||||
case WLAN_CIPHER_SUITE_CCMP:
|
||||
return MT_CIPHER_AES_CCMP;
|
||||
default:
|
||||
return MT_CIPHER_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
int mt7603_wtbl_set_key(struct mt7603_dev *dev, int wcid,
|
||||
struct ieee80211_key_conf *key)
|
||||
{
|
||||
enum mt7603_cipher_type cipher;
|
||||
u32 addr = mt7603_wtbl3_addr(wcid);
|
||||
u8 key_data[32];
|
||||
u8 iv_data[8];
|
||||
int key_len = sizeof(key_data);
|
||||
|
||||
cipher = mt7603_mac_get_key_info(key, key_data);
|
||||
if (cipher == MT_CIPHER_NONE && key)
|
||||
return -EINVAL;
|
||||
|
||||
memset(iv_data, 0, sizeof(iv_data));
|
||||
if (key) {
|
||||
if (cipher == MT_CIPHER_WEP40 || cipher == MT_CIPHER_WEP104) {
|
||||
addr += key->keyidx * 16;
|
||||
key_len = 16;
|
||||
}
|
||||
|
||||
iv_data[3] = key->keyidx << 6;
|
||||
if (cipher >= MT_CIPHER_TKIP)
|
||||
iv_data[3] |= 0x20;
|
||||
}
|
||||
|
||||
mt76_wr_copy(dev, addr, key_data, key_len);
|
||||
|
||||
if (cipher != MT_CIPHER_WEP40 && cipher != MT_CIPHER_WEP104)
|
||||
mt76_wr_copy(dev, addr + 32, iv_data, sizeof(iv_data));
|
||||
|
||||
addr = mt7603_wtbl1_addr(wcid);
|
||||
mt76_rmw_field(dev, addr + 2 * 4, MT_WTBL1_W2_KEY_TYPE, cipher);
|
||||
if (key)
|
||||
mt76_rmw_field(dev, addr, MT_WTBL1_W0_KEY_IDX, key->keyidx);
|
||||
mt76_rmw_field(dev, addr, MT_WTBL1_W0_RX_KEY_VALID, !!key);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mt7603_mac_write_txwi(struct mt7603_dev *dev, __le32 *txwi,
|
||||
struct sk_buff *skb, struct mt76_wcid *wcid,
|
||||
struct ieee80211_sta *sta, int pid)
|
||||
struct ieee80211_sta *sta, int pid, bool key)
|
||||
{
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_tx_rate *rate = &info->control.rates[0];
|
||||
@@ -510,7 +586,8 @@ mt7603_mac_write_txwi(struct mt7603_dev *dev, __le32 *txwi,
|
||||
IEEE80211_QOS_CTL_TID_MASK) |
|
||||
MT76_SET(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) |
|
||||
MT76_SET(MT_TXD1_HDR_INFO, hdr_len / 2) |
|
||||
MT76_SET(MT_TXD1_WLAN_IDX, wlan_idx)
|
||||
MT76_SET(MT_TXD1_WLAN_IDX, wlan_idx) |
|
||||
MT76_SET(MT_TXD1_PROTECTED, key)
|
||||
);
|
||||
|
||||
if (info->flags & IEEE80211_TX_CTL_NO_ACK) {
|
||||
@@ -566,6 +643,7 @@ int mt7603_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct mt7603_sta *msta = container_of(wcid, struct mt7603_sta, wcid);
|
||||
struct mt7603_cb *cb = mt7603_skb_cb(skb);
|
||||
bool key = info->control.hw_key;
|
||||
int pid = 0;
|
||||
|
||||
if (!wcid)
|
||||
@@ -589,7 +667,7 @@ int mt7603_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
||||
INIT_LIST_HEAD(&cb->list);
|
||||
}
|
||||
|
||||
mt7603_mac_write_txwi(dev, txwi_ptr, skb, wcid, sta, pid);
|
||||
mt7603_mac_write_txwi(dev, txwi_ptr, skb, wcid, sta, pid, key);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+20
-1
@@ -286,7 +286,26 @@ mt7603_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
struct ieee80211_vif *vif, struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key)
|
||||
{
|
||||
return -EINVAL;
|
||||
struct mt7603_dev *dev = hw->priv;
|
||||
struct mt7603_vif *mvif = (struct mt7603_vif *) vif->drv_priv;
|
||||
struct mt7603_sta *msta = sta ? (struct mt7603_sta *) sta->drv_priv : NULL;
|
||||
struct mt76_wcid *wcid = msta ? &msta->wcid : &mvif->sta.wcid;
|
||||
int idx = key->keyidx;
|
||||
|
||||
if (cmd == SET_KEY) {
|
||||
key->hw_key_idx = wcid->idx;
|
||||
wcid->hw_key_idx = idx;
|
||||
} else {
|
||||
if (idx == wcid->hw_key_idx)
|
||||
wcid->hw_key_idx = -1;
|
||||
|
||||
key = NULL;
|
||||
}
|
||||
|
||||
if (!msta)
|
||||
return -EINVAL;
|
||||
|
||||
return mt7603_wtbl_set_key(dev, msta->wcid.idx, key);
|
||||
}
|
||||
|
||||
static int
|
||||
|
||||
@@ -487,4 +487,17 @@
|
||||
#define MT_WTBL1_OR (MT_WTBL1_BASE + 0x2300)
|
||||
#define MT_WTBL1_OR_PSM_WRITE BIT(31)
|
||||
|
||||
enum mt7603_cipher_type {
|
||||
MT_CIPHER_NONE,
|
||||
MT_CIPHER_WEP40,
|
||||
MT_CIPHER_TKIP,
|
||||
MT_CIPHER_TKIP_NO_MIC,
|
||||
MT_CIPHER_AES_CCMP,
|
||||
MT_CIPHER_WEP104,
|
||||
MT_CIPHER_BIP_CMAC_128,
|
||||
MT_CIPHER_WEP128,
|
||||
MT_CIPHER_WAPI,
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user