static int
mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
struct ieee80211_key_conf *key,
- enum mt7615_cipher_type cipher,
+ enum mt7615_cipher_type cipher, u16 cipher_mask,
enum set_key_cmd cmd)
{
u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx) + 30 * 4;
memcpy(data + 16, key->key + 24, 8);
memcpy(data + 24, key->key + 16, 8);
} else {
- if (cipher != MT_CIPHER_BIP_CMAC_128 && wcid->cipher)
- memmove(data + 16, data, 16);
- if (cipher != MT_CIPHER_BIP_CMAC_128 || !wcid->cipher)
+ if (cipher_mask == BIT(cipher))
memcpy(data, key->key, key->keylen);
- else if (cipher == MT_CIPHER_BIP_CMAC_128)
+ else if (cipher != MT_CIPHER_BIP_CMAC_128)
+ memcpy(data, key->key, 16);
+ if (cipher == MT_CIPHER_BIP_CMAC_128)
memcpy(data + 16, key->key, 16);
}
} else {
- if (wcid->cipher & ~BIT(cipher)) {
- if (cipher != MT_CIPHER_BIP_CMAC_128)
- memmove(data, data + 16, 16);
+ if (cipher == MT_CIPHER_BIP_CMAC_128)
memset(data + 16, 0, 16);
- } else {
+ else if (cipher_mask)
+ memset(data, 0, 16);
+ if (!cipher_mask)
memset(data, 0, sizeof(data));
- }
}
+
mt76_wr_copy(dev, addr, data, sizeof(data));
return 0;
static int
mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid,
- enum mt7615_cipher_type cipher,
+ enum mt7615_cipher_type cipher, u16 cipher_mask,
int keyidx, enum set_key_cmd cmd)
{
u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx), w0, w1;
w0 = mt76_rr(dev, addr);
w1 = mt76_rr(dev, addr + 4);
- if (cmd == SET_KEY) {
- w0 |= MT_WTBL_W0_RX_KEY_VALID |
- FIELD_PREP(MT_WTBL_W0_RX_IK_VALID,
- cipher == MT_CIPHER_BIP_CMAC_128);
- if (cipher != MT_CIPHER_BIP_CMAC_128 ||
- !wcid->cipher)
- w0 |= FIELD_PREP(MT_WTBL_W0_KEY_IDX, keyidx);
- } else {
- if (!(wcid->cipher & ~BIT(cipher)))
- w0 &= ~(MT_WTBL_W0_RX_KEY_VALID |
- MT_WTBL_W0_KEY_IDX);
- if (cipher == MT_CIPHER_BIP_CMAC_128)
- w0 &= ~MT_WTBL_W0_RX_IK_VALID;
+
+ if (cipher_mask)
+ w0 |= MT_WTBL_W0_RX_KEY_VALID;
+ else
+ w0 &= ~(MT_WTBL_W0_RX_KEY_VALID | MT_WTBL_W0_KEY_IDX);
+ if (cipher_mask & BIT(MT_CIPHER_BIP_CMAC_128))
+ w0 |= MT_WTBL_W0_RX_IK_VALID;
+ else
+ w0 &= ~MT_WTBL_W0_RX_IK_VALID;
+
+ if (cmd == SET_KEY &&
+ (cipher != MT_CIPHER_BIP_CMAC_128 ||
+ cipher_mask == BIT(cipher))) {
+ w0 &= ~MT_WTBL_W0_KEY_IDX;
+ w0 |= FIELD_PREP(MT_WTBL_W0_KEY_IDX, keyidx);
}
+
mt76_wr(dev, MT_WTBL_RICR0, w0);
mt76_wr(dev, MT_WTBL_RICR1, w1);
static void
mt7615_mac_wtbl_update_cipher(struct mt7615_dev *dev, struct mt76_wcid *wcid,
- enum mt7615_cipher_type cipher,
+ enum mt7615_cipher_type cipher, u16 cipher_mask,
enum set_key_cmd cmd)
{
u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx);
- if (cmd == SET_KEY) {
- if (cipher != MT_CIPHER_BIP_CMAC_128 || !wcid->cipher)
- mt76_rmw(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE,
- FIELD_PREP(MT_WTBL_W2_KEY_TYPE, cipher));
- } else {
- if (cipher != MT_CIPHER_BIP_CMAC_128 &&
- wcid->cipher & BIT(MT_CIPHER_BIP_CMAC_128))
- mt76_rmw(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE,
- FIELD_PREP(MT_WTBL_W2_KEY_TYPE,
- MT_CIPHER_BIP_CMAC_128));
- else if (!(wcid->cipher & ~BIT(cipher)))
- mt76_clear(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE);
+ if (!cipher_mask) {
+ mt76_clear(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE);
+ return;
}
+
+ if (cmd != SET_KEY)
+ return;
+
+ if (cipher == MT_CIPHER_BIP_CMAC_128 &&
+ cipher_mask & ~BIT(MT_CIPHER_BIP_CMAC_128))
+ return;
+
+ mt76_rmw(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE,
+ FIELD_PREP(MT_WTBL_W2_KEY_TYPE, cipher));
}
int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
enum set_key_cmd cmd)
{
enum mt7615_cipher_type cipher;
+ u16 cipher_mask = wcid->cipher;
int err;
cipher = mt7615_mac_get_cipher(key->cipher);
if (cipher == MT_CIPHER_NONE)
return -EOPNOTSUPP;
- mt7615_mac_wtbl_update_cipher(dev, wcid, cipher, cmd);
- err = mt7615_mac_wtbl_update_key(dev, wcid, key, cipher, cmd);
+ if (cmd == SET_KEY)
+ cipher_mask |= BIT(cipher);
+ else
+ cipher_mask &= ~BIT(cipher);
+
+ mt7615_mac_wtbl_update_cipher(dev, wcid, cipher, cipher_mask, cmd);
+ err = mt7615_mac_wtbl_update_key(dev, wcid, key, cipher, cipher_mask,
+ cmd);
if (err < 0)
return err;
- err = mt7615_mac_wtbl_update_pk(dev, wcid, cipher, key->keyidx, cmd);
+ err = mt7615_mac_wtbl_update_pk(dev, wcid, cipher, cipher_mask,
+ key->keyidx, cmd);
if (err < 0)
return err;
- if (cmd == SET_KEY)
- wcid->cipher |= BIT(cipher);
- else
- wcid->cipher &= ~BIT(cipher);
+ wcid->cipher = cipher_mask;
return 0;
}