Commit faa72684 authored by Lorenzo Bianconi's avatar Lorenzo Bianconi Committed by Felix Fietkau
Browse files

mt76: mt7615: run key configuration in mt7615_set_key for usb/sdio devices



Since rate configuration is run holding dev mutex, we can run key
configuration in mt7615_set_key for usb/sdio devices avoiding to
schedule the workqueue

Tested-by: default avatarTested-by: YN Chen <yn.chen@mediatek.com>
Signed-off-by: default avatarLorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
parent 930e0ead
Loading
Loading
Loading
Loading
+39 −35
Original line number Diff line number Diff line
@@ -1030,32 +1030,32 @@ void mt7615_mac_set_rates(struct mt7615_phy *phy, struct mt7615_sta *sta,
}
EXPORT_SYMBOL_GPL(mt7615_mac_set_rates);

int mt7615_mac_wtbl_update_key(struct mt7615_dev *dev,
			       struct mt76_wcid *wcid,
			       u8 *key, u8 keylen,
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 set_key_cmd cmd)
{
	u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx) + 30 * 4;
	u8 data[32] = {};

	if (keylen > sizeof(data))
	if (key->keylen > sizeof(data))
		return -EINVAL;

	mt76_rr_copy(dev, addr, data, sizeof(data));
	if (cmd == SET_KEY) {
		if (cipher == MT_CIPHER_TKIP) {
			/* Rx/Tx MIC keys are swapped */
			memcpy(data, key, 16);
			memcpy(data + 16, key + 24, 8);
			memcpy(data + 24, key + 16, 8);
			memcpy(data, key->key, 16);
			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)
				memcpy(data, key, keylen);
				memcpy(data, key->key, key->keylen);
			else if (cipher == MT_CIPHER_BIP_CMAC_128)
				memcpy(data + 16, key, 16);
				memcpy(data + 16, key->key, 16);
		}
	} else {
		if (wcid->cipher & ~BIT(cipher)) {
@@ -1070,10 +1070,9 @@ int mt7615_mac_wtbl_update_key(struct mt7615_dev *dev,

	return 0;
}
EXPORT_SYMBOL_GPL(mt7615_mac_wtbl_update_key);

int mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev,
			      struct mt76_wcid *wcid,
static int
mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid,
			  enum mt7615_cipher_type cipher,
			  int keyidx, enum set_key_cmd cmd)
{
@@ -1107,10 +1106,9 @@ int mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev,

	return 0;
}
EXPORT_SYMBOL_GPL(mt7615_mac_wtbl_update_pk);

void mt7615_mac_wtbl_update_cipher(struct mt7615_dev *dev,
				   struct mt76_wcid *wcid,
static void
mt7615_mac_wtbl_update_cipher(struct mt7615_dev *dev, struct mt76_wcid *wcid,
			      enum mt7615_cipher_type cipher,
			      enum set_key_cmd cmd)
{
@@ -1130,9 +1128,8 @@ void mt7615_mac_wtbl_update_cipher(struct mt7615_dev *dev,
			mt76_clear(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE);
	}
}
EXPORT_SYMBOL_GPL(mt7615_mac_wtbl_update_cipher);

int mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
			      struct mt76_wcid *wcid,
			      struct ieee80211_key_conf *key,
			      enum set_key_cmd cmd)
@@ -1144,25 +1141,32 @@ int mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
	if (cipher == MT_CIPHER_NONE)
		return -EOPNOTSUPP;

	spin_lock_bh(&dev->mt76.lock);

	mt7615_mac_wtbl_update_cipher(dev, wcid, cipher, cmd);
	err = mt7615_mac_wtbl_update_key(dev, wcid, key->key, key->keylen,
					 cipher, cmd);
	err = mt7615_mac_wtbl_update_key(dev, wcid, key, cipher, cmd);
	if (err < 0)
		goto out;
		return err;

	err = mt7615_mac_wtbl_update_pk(dev, wcid, cipher, key->keyidx,
					cmd);
	err = mt7615_mac_wtbl_update_pk(dev, wcid, cipher, key->keyidx, cmd);
	if (err < 0)
		goto out;
		return err;

	if (cmd == SET_KEY)
		wcid->cipher |= BIT(cipher);
	else
		wcid->cipher &= ~BIT(cipher);

out:
	return 0;
}

int mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
			    struct mt76_wcid *wcid,
			    struct ieee80211_key_conf *key,
			    enum set_key_cmd cmd)
{
	int err;

	spin_lock_bh(&dev->mt76.lock);
	err = __mt7615_mac_wtbl_set_key(dev, wcid, key, cmd);
	spin_unlock_bh(&dev->mt76.lock);

	return err;
+1 −34
Original line number Diff line number Diff line
@@ -320,39 +320,6 @@ int mt7615_set_channel(struct mt7615_phy *phy)
	return ret;
}

static int
mt7615_queue_key_update(struct mt7615_dev *dev, enum set_key_cmd cmd,
			struct mt7615_sta *msta,
			struct ieee80211_key_conf *key)
{
	struct mt7615_wtbl_desc *wd;

	wd = kzalloc(sizeof(*wd), GFP_KERNEL);
	if (!wd)
		return -ENOMEM;

	wd->type = MT7615_WTBL_KEY_DESC;
	wd->sta = msta;

	wd->key.key = kmemdup(key->key, key->keylen, GFP_KERNEL);
	if (!wd->key.key) {
		kfree(wd);
		return -ENOMEM;
	}
	wd->key.cipher = key->cipher;
	wd->key.keyidx = key->keyidx;
	wd->key.keylen = key->keylen;
	wd->key.cmd = cmd;

	spin_lock_bh(&dev->mt76.lock);
	list_add_tail(&wd->node, &dev->wd_head);
	spin_unlock_bh(&dev->mt76.lock);

	queue_work(dev->mt76.wq, &dev->wtbl_work);

	return 0;
}

static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
			  struct ieee80211_vif *vif, struct ieee80211_sta *sta,
			  struct ieee80211_key_conf *key)
@@ -406,7 +373,7 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
	if (mt76_is_mmio(&dev->mt76))
		err = mt7615_mac_wtbl_set_key(dev, wcid, key, cmd);
	else
		err = mt7615_queue_key_update(dev, cmd, msta, key);
		err = __mt7615_mac_wtbl_set_key(dev, wcid, key, cmd);

	mt7615_mutex_release(dev);

+4 −23
Original line number Diff line number Diff line
@@ -108,15 +108,6 @@ struct mt7615_rate_desc {

enum mt7615_wtbl_desc_type {
	MT7615_WTBL_RATE_DESC,
	MT7615_WTBL_KEY_DESC
};

struct mt7615_key_desc {
	enum set_key_cmd cmd;
	u32 cipher;
	s8 keyidx;
	u8 keylen;
	u8 *key;
};

struct mt7615_wtbl_desc {
@@ -127,7 +118,6 @@ struct mt7615_wtbl_desc {

	union {
		struct mt7615_rate_desc rate;
		struct mt7615_key_desc key;
	};
};

@@ -571,21 +561,12 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi,
			  struct ieee80211_sta *sta, int pid,
			  struct ieee80211_key_conf *key, bool beacon);
void mt7615_mac_set_timing(struct mt7615_phy *phy);
int mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
			    struct ieee80211_key_conf *key,
			    enum set_key_cmd cmd);
int mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev,
int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
			      struct mt76_wcid *wcid,
			      enum mt7615_cipher_type cipher,
			      int keyidx, enum set_key_cmd cmd);
void mt7615_mac_wtbl_update_cipher(struct mt7615_dev *dev,
				   struct mt76_wcid *wcid,
				   enum mt7615_cipher_type cipher,
			      struct ieee80211_key_conf *key,
			      enum set_key_cmd cmd);
int mt7615_mac_wtbl_update_key(struct mt7615_dev *dev,
			       struct mt76_wcid *wcid,
			       u8 *key, u8 keylen,
			       enum mt7615_cipher_type cipher,
int mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
			    struct ieee80211_key_conf *key,
			    enum set_key_cmd cmd);
void mt7615_mac_reset_work(struct work_struct *work);
u32 mt7615_mac_get_sta_tid_sn(struct mt7615_dev *dev, int wcid, u8 tid);
+0 −49
Original line number Diff line number Diff line
@@ -132,52 +132,6 @@ mt7663_usb_sdio_set_rates(struct mt7615_dev *dev,
	return 0;
}

static int
mt7663_usb_sdio_set_key(struct mt7615_dev *dev,
			struct mt7615_wtbl_desc *wd)
{
	struct mt7615_key_desc *key = &wd->key;
	struct mt7615_sta *sta = wd->sta;
	enum mt7615_cipher_type cipher;
	struct mt76_wcid *wcid;
	int err;

	lockdep_assert_held(&dev->mt76.mutex);

	if (!sta) {
		err = -EINVAL;
		goto out;
	}

	cipher = mt7615_mac_get_cipher(key->cipher);
	if (cipher == MT_CIPHER_NONE) {
		err = -EOPNOTSUPP;
		goto out;
	}

	wcid = &wd->sta->wcid;

	mt7615_mac_wtbl_update_cipher(dev, wcid, cipher, key->cmd);
	err = mt7615_mac_wtbl_update_key(dev, wcid, key->key, key->keylen,
					 cipher, key->cmd);
	if (err < 0)
		goto out;

	err = mt7615_mac_wtbl_update_pk(dev, wcid, cipher, key->keyidx,
					key->cmd);
	if (err < 0)
		goto out;

	if (key->cmd == SET_KEY)
		wcid->cipher |= BIT(cipher);
	else
		wcid->cipher &= ~BIT(cipher);
out:
	kfree(key->key);

	return err;
}

void mt7663_usb_sdio_wtbl_work(struct work_struct *work)
{
	struct mt7615_wtbl_desc *wd, *wd_next;
@@ -201,9 +155,6 @@ void mt7663_usb_sdio_wtbl_work(struct work_struct *work)
		case MT7615_WTBL_RATE_DESC:
			mt7663_usb_sdio_set_rates(dev, wd);
			break;
		case MT7615_WTBL_KEY_DESC:
			mt7663_usb_sdio_set_key(dev, wd);
			break;
		}

		mt7615_mutex_release(dev);