Commit 3968e3ca authored by David S. Miller's avatar David S. Miller

Merge tag 'wireless-drivers-2021-12-01' of...

Merge tag 'wireless-drivers-2021-12-01' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers

Kalle Valo says:

====================
wireless-drivers fixes for v5.16

First set of fixes for v5.16. Mostly crash and driver initialisation
fixes, the fix for rtw89 being most important.

iwlwifi

* compiler, lockdep and smatch warning fixes

* fix for a rare driver initialisation failure

* fix a memory leak

rtw89

* fix const buffer modification causing a kernel crash

mt76

* fix null pointer access

* fix idr leak

rt2x00

* fix driver initialisation errors, a regression since v5.2-rc1
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 4326d04f 191587cd
...@@ -86,6 +86,7 @@ static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans, ...@@ -86,6 +86,7 @@ static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans,
if (len < tlv_len) { if (len < tlv_len) {
IWL_ERR(trans, "invalid TLV len: %zd/%u\n", IWL_ERR(trans, "invalid TLV len: %zd/%u\n",
len, tlv_len); len, tlv_len);
kfree(reduce_power_data);
reduce_power_data = ERR_PTR(-EINVAL); reduce_power_data = ERR_PTR(-EINVAL);
goto out; goto out;
} }
...@@ -105,6 +106,7 @@ static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans, ...@@ -105,6 +106,7 @@ static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans,
IWL_DEBUG_FW(trans, IWL_DEBUG_FW(trans,
"Couldn't allocate (more) reduce_power_data\n"); "Couldn't allocate (more) reduce_power_data\n");
kfree(reduce_power_data);
reduce_power_data = ERR_PTR(-ENOMEM); reduce_power_data = ERR_PTR(-ENOMEM);
goto out; goto out;
} }
...@@ -134,6 +136,10 @@ static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans, ...@@ -134,6 +136,10 @@ static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans,
done: done:
if (!size) { if (!size) {
IWL_DEBUG_FW(trans, "Empty REDUCE_POWER, skipping.\n"); IWL_DEBUG_FW(trans, "Empty REDUCE_POWER, skipping.\n");
/* Better safe than sorry, but 'reduce_power_data' should
* always be NULL if !size.
*/
kfree(reduce_power_data);
reduce_power_data = ERR_PTR(-ENOENT); reduce_power_data = ERR_PTR(-ENOENT);
goto out; goto out;
} }
......
...@@ -1313,23 +1313,31 @@ _iwl_op_mode_start(struct iwl_drv *drv, struct iwlwifi_opmode_table *op) ...@@ -1313,23 +1313,31 @@ _iwl_op_mode_start(struct iwl_drv *drv, struct iwlwifi_opmode_table *op)
const struct iwl_op_mode_ops *ops = op->ops; const struct iwl_op_mode_ops *ops = op->ops;
struct dentry *dbgfs_dir = NULL; struct dentry *dbgfs_dir = NULL;
struct iwl_op_mode *op_mode = NULL; struct iwl_op_mode *op_mode = NULL;
int retry, max_retry = !!iwlwifi_mod_params.fw_restart * IWL_MAX_INIT_RETRY;
for (retry = 0; retry <= max_retry; retry++) {
#ifdef CONFIG_IWLWIFI_DEBUGFS #ifdef CONFIG_IWLWIFI_DEBUGFS
drv->dbgfs_op_mode = debugfs_create_dir(op->name, drv->dbgfs_op_mode = debugfs_create_dir(op->name,
drv->dbgfs_drv); drv->dbgfs_drv);
dbgfs_dir = drv->dbgfs_op_mode; dbgfs_dir = drv->dbgfs_op_mode;
#endif #endif
op_mode = ops->start(drv->trans, drv->trans->cfg, &drv->fw, dbgfs_dir); op_mode = ops->start(drv->trans, drv->trans->cfg,
&drv->fw, dbgfs_dir);
if (op_mode)
return op_mode;
IWL_ERR(drv, "retry init count %d\n", retry);
#ifdef CONFIG_IWLWIFI_DEBUGFS #ifdef CONFIG_IWLWIFI_DEBUGFS
if (!op_mode) {
debugfs_remove_recursive(drv->dbgfs_op_mode); debugfs_remove_recursive(drv->dbgfs_op_mode);
drv->dbgfs_op_mode = NULL; drv->dbgfs_op_mode = NULL;
}
#endif #endif
}
return op_mode; return NULL;
} }
static void _iwl_op_mode_stop(struct iwl_drv *drv) static void _iwl_op_mode_stop(struct iwl_drv *drv)
......
...@@ -89,4 +89,7 @@ void iwl_drv_stop(struct iwl_drv *drv); ...@@ -89,4 +89,7 @@ void iwl_drv_stop(struct iwl_drv *drv);
#define IWL_EXPORT_SYMBOL(sym) #define IWL_EXPORT_SYMBOL(sym)
#endif #endif
/* max retry for init flow */
#define IWL_MAX_INIT_RETRY 2
#endif /* __iwl_drv_h__ */ #endif /* __iwl_drv_h__ */
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <net/ieee80211_radiotap.h> #include <net/ieee80211_radiotap.h>
#include <net/tcp.h> #include <net/tcp.h>
#include "iwl-drv.h"
#include "iwl-op-mode.h" #include "iwl-op-mode.h"
#include "iwl-io.h" #include "iwl-io.h"
#include "mvm.h" #include "mvm.h"
...@@ -1117,9 +1118,30 @@ static int iwl_mvm_mac_start(struct ieee80211_hw *hw) ...@@ -1117,9 +1118,30 @@ static int iwl_mvm_mac_start(struct ieee80211_hw *hw)
{ {
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
int ret; int ret;
int retry, max_retry = 0;
mutex_lock(&mvm->mutex); mutex_lock(&mvm->mutex);
ret = __iwl_mvm_mac_start(mvm);
/* we are starting the mac not in error flow, and restart is enabled */
if (!test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status) &&
iwlwifi_mod_params.fw_restart) {
max_retry = IWL_MAX_INIT_RETRY;
/*
* This will prevent mac80211 recovery flows to trigger during
* init failures
*/
set_bit(IWL_MVM_STATUS_STARTING, &mvm->status);
}
for (retry = 0; retry <= max_retry; retry++) {
ret = __iwl_mvm_mac_start(mvm);
if (!ret)
break;
IWL_ERR(mvm, "mac start retry %d\n", retry);
}
clear_bit(IWL_MVM_STATUS_STARTING, &mvm->status);
mutex_unlock(&mvm->mutex); mutex_unlock(&mvm->mutex);
return ret; return ret;
......
...@@ -1123,6 +1123,8 @@ struct iwl_mvm { ...@@ -1123,6 +1123,8 @@ struct iwl_mvm {
* @IWL_MVM_STATUS_FIRMWARE_RUNNING: firmware is running * @IWL_MVM_STATUS_FIRMWARE_RUNNING: firmware is running
* @IWL_MVM_STATUS_NEED_FLUSH_P2P: need to flush P2P bcast STA * @IWL_MVM_STATUS_NEED_FLUSH_P2P: need to flush P2P bcast STA
* @IWL_MVM_STATUS_IN_D3: in D3 (or at least about to go into it) * @IWL_MVM_STATUS_IN_D3: in D3 (or at least about to go into it)
* @IWL_MVM_STATUS_STARTING: starting mac,
* used to disable restart flow while in STARTING state
*/ */
enum iwl_mvm_status { enum iwl_mvm_status {
IWL_MVM_STATUS_HW_RFKILL, IWL_MVM_STATUS_HW_RFKILL,
...@@ -1134,6 +1136,7 @@ enum iwl_mvm_status { ...@@ -1134,6 +1136,7 @@ enum iwl_mvm_status {
IWL_MVM_STATUS_FIRMWARE_RUNNING, IWL_MVM_STATUS_FIRMWARE_RUNNING,
IWL_MVM_STATUS_NEED_FLUSH_P2P, IWL_MVM_STATUS_NEED_FLUSH_P2P,
IWL_MVM_STATUS_IN_D3, IWL_MVM_STATUS_IN_D3,
IWL_MVM_STATUS_STARTING,
}; };
/* Keep track of completed init configuration */ /* Keep track of completed init configuration */
......
...@@ -686,6 +686,7 @@ static int iwl_mvm_start_get_nvm(struct iwl_mvm *mvm) ...@@ -686,6 +686,7 @@ static int iwl_mvm_start_get_nvm(struct iwl_mvm *mvm)
int ret; int ret;
rtnl_lock(); rtnl_lock();
wiphy_lock(mvm->hw->wiphy);
mutex_lock(&mvm->mutex); mutex_lock(&mvm->mutex);
ret = iwl_run_init_mvm_ucode(mvm); ret = iwl_run_init_mvm_ucode(mvm);
...@@ -701,6 +702,7 @@ static int iwl_mvm_start_get_nvm(struct iwl_mvm *mvm) ...@@ -701,6 +702,7 @@ static int iwl_mvm_start_get_nvm(struct iwl_mvm *mvm)
iwl_mvm_stop_device(mvm); iwl_mvm_stop_device(mvm);
mutex_unlock(&mvm->mutex); mutex_unlock(&mvm->mutex);
wiphy_unlock(mvm->hw->wiphy);
rtnl_unlock(); rtnl_unlock();
if (ret < 0) if (ret < 0)
...@@ -1600,6 +1602,9 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error) ...@@ -1600,6 +1602,9 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error)
*/ */
if (!mvm->fw_restart && fw_error) { if (!mvm->fw_restart && fw_error) {
iwl_fw_error_collect(&mvm->fwrt, false); iwl_fw_error_collect(&mvm->fwrt, false);
} else if (test_bit(IWL_MVM_STATUS_STARTING,
&mvm->status)) {
IWL_ERR(mvm, "Starting mac, retry will be triggered anyway\n");
} else if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { } else if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
struct iwl_mvm_reprobe *reprobe; struct iwl_mvm_reprobe *reprobe;
......
...@@ -1339,9 +1339,13 @@ iwl_pci_find_dev_info(u16 device, u16 subsystem_device, ...@@ -1339,9 +1339,13 @@ iwl_pci_find_dev_info(u16 device, u16 subsystem_device,
u16 mac_type, u8 mac_step, u16 mac_type, u8 mac_step,
u16 rf_type, u8 cdb, u8 rf_id, u8 no_160, u8 cores) u16 rf_type, u8 cdb, u8 rf_id, u8 no_160, u8 cores)
{ {
int num_devices = ARRAY_SIZE(iwl_dev_info_table);
int i; int i;
for (i = ARRAY_SIZE(iwl_dev_info_table) - 1; i >= 0; i--) { if (!num_devices)
return NULL;
for (i = num_devices - 1; i >= 0; i--) {
const struct iwl_dev_info *dev_info = &iwl_dev_info_table[i]; const struct iwl_dev_info *dev_info = &iwl_dev_info_table[i];
if (dev_info->device != (u16)IWL_CFG_ANY && if (dev_info->device != (u16)IWL_CFG_ANY &&
...@@ -1442,8 +1446,10 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1442,8 +1446,10 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
*/ */
if (iwl_trans->trans_cfg->rf_id && if (iwl_trans->trans_cfg->rf_id &&
iwl_trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_9000 && iwl_trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_9000 &&
!CSR_HW_RFID_TYPE(iwl_trans->hw_rf_id) && get_crf_id(iwl_trans)) !CSR_HW_RFID_TYPE(iwl_trans->hw_rf_id) && get_crf_id(iwl_trans)) {
ret = -EINVAL;
goto out_free_trans; goto out_free_trans;
}
dev_info = iwl_pci_find_dev_info(pdev->device, pdev->subsystem_device, dev_info = iwl_pci_find_dev_info(pdev->device, pdev->subsystem_device,
CSR_HW_REV_TYPE(iwl_trans->hw_rev), CSR_HW_REV_TYPE(iwl_trans->hw_rev),
......
...@@ -143,8 +143,6 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, ...@@ -143,8 +143,6 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
if (!wcid) if (!wcid)
wcid = &dev->mt76.global_wcid; wcid = &dev->mt76.global_wcid;
pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb);
if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && msta) { if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && msta) {
struct mt7615_phy *phy = &dev->phy; struct mt7615_phy *phy = &dev->phy;
...@@ -164,6 +162,7 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, ...@@ -164,6 +162,7 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
if (id < 0) if (id < 0)
return id; return id;
pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb);
mt7615_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, sta, mt7615_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, sta,
pid, key, false); pid, key, false);
......
...@@ -43,19 +43,11 @@ EXPORT_SYMBOL_GPL(mt7663_usb_sdio_reg_map); ...@@ -43,19 +43,11 @@ EXPORT_SYMBOL_GPL(mt7663_usb_sdio_reg_map);
static void static void
mt7663_usb_sdio_write_txwi(struct mt7615_dev *dev, struct mt76_wcid *wcid, mt7663_usb_sdio_write_txwi(struct mt7615_dev *dev, struct mt76_wcid *wcid,
enum mt76_txq_id qid, struct ieee80211_sta *sta, enum mt76_txq_id qid, struct ieee80211_sta *sta,
struct ieee80211_key_conf *key, int pid,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); __le32 *txwi = (__le32 *)(skb->data - MT_USB_TXD_SIZE);
struct ieee80211_key_conf *key = info->control.hw_key;
__le32 *txwi;
int pid;
if (!wcid)
wcid = &dev->mt76.global_wcid;
pid = mt76_tx_status_skb_add(&dev->mt76, wcid, skb);
txwi = (__le32 *)(skb->data - MT_USB_TXD_SIZE);
memset(txwi, 0, MT_USB_TXD_SIZE); memset(txwi, 0, MT_USB_TXD_SIZE);
mt7615_mac_write_txwi(dev, txwi, skb, wcid, sta, pid, key, false); mt7615_mac_write_txwi(dev, txwi, skb, wcid, sta, pid, key, false);
skb_push(skb, MT_USB_TXD_SIZE); skb_push(skb, MT_USB_TXD_SIZE);
...@@ -194,10 +186,14 @@ int mt7663_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, ...@@ -194,10 +186,14 @@ int mt7663_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);
struct sk_buff *skb = tx_info->skb; struct sk_buff *skb = tx_info->skb;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_key_conf *key = info->control.hw_key;
struct mt7615_sta *msta; struct mt7615_sta *msta;
int pad; int pad, err, pktid;
msta = wcid ? container_of(wcid, struct mt7615_sta, wcid) : NULL; msta = wcid ? container_of(wcid, struct mt7615_sta, wcid) : NULL;
if (!wcid)
wcid = &dev->mt76.global_wcid;
if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) &&
msta && !msta->rate_probe) { msta && !msta->rate_probe) {
/* request to configure sampling rate */ /* request to configure sampling rate */
...@@ -207,7 +203,8 @@ int mt7663_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, ...@@ -207,7 +203,8 @@ int mt7663_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
spin_unlock_bh(&dev->mt76.lock); spin_unlock_bh(&dev->mt76.lock);
} }
mt7663_usb_sdio_write_txwi(dev, wcid, qid, sta, skb); pktid = mt76_tx_status_skb_add(&dev->mt76, wcid, skb);
mt7663_usb_sdio_write_txwi(dev, wcid, qid, sta, key, pktid, skb);
if (mt76_is_usb(mdev)) { if (mt76_is_usb(mdev)) {
u32 len = skb->len; u32 len = skb->len;
...@@ -217,7 +214,12 @@ int mt7663_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, ...@@ -217,7 +214,12 @@ int mt7663_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
pad = round_up(skb->len, 4) - skb->len; pad = round_up(skb->len, 4) - skb->len;
} }
return mt76_skb_adjust_pad(skb, pad); err = mt76_skb_adjust_pad(skb, pad);
if (err)
/* Release pktid in case of error. */
idr_remove(&wcid->pktid, pktid);
return err;
} }
EXPORT_SYMBOL_GPL(mt7663_usb_sdio_tx_prepare_skb); EXPORT_SYMBOL_GPL(mt7663_usb_sdio_tx_prepare_skb);
......
...@@ -72,6 +72,7 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data, ...@@ -72,6 +72,7 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data,
bool ampdu = IEEE80211_SKB_CB(tx_info->skb)->flags & IEEE80211_TX_CTL_AMPDU; bool ampdu = IEEE80211_SKB_CB(tx_info->skb)->flags & IEEE80211_TX_CTL_AMPDU;
enum mt76_qsel qsel; enum mt76_qsel qsel;
u32 flags; u32 flags;
int err;
mt76_insert_hdr_pad(tx_info->skb); mt76_insert_hdr_pad(tx_info->skb);
...@@ -106,7 +107,12 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data, ...@@ -106,7 +107,12 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data,
ewma_pktlen_add(&msta->pktlen, tx_info->skb->len); ewma_pktlen_add(&msta->pktlen, tx_info->skb->len);
} }
return mt76x02u_skb_dma_info(tx_info->skb, WLAN_PORT, flags); err = mt76x02u_skb_dma_info(tx_info->skb, WLAN_PORT, flags);
if (err && wcid)
/* Release pktid in case of error. */
idr_remove(&wcid->pktid, pid);
return err;
} }
EXPORT_SYMBOL_GPL(mt76x02u_tx_prepare_skb); EXPORT_SYMBOL_GPL(mt76x02u_tx_prepare_skb);
......
...@@ -1151,8 +1151,14 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, ...@@ -1151,8 +1151,14 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
} }
} }
pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb); t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size);
t->skb = tx_info->skb;
id = mt76_token_consume(mdev, &t);
if (id < 0)
return id;
pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb);
mt7915_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, pid, key, mt7915_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, pid, key,
false); false);
...@@ -1178,13 +1184,6 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, ...@@ -1178,13 +1184,6 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
txp->bss_idx = mvif->idx; txp->bss_idx = mvif->idx;
} }
t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size);
t->skb = tx_info->skb;
id = mt76_token_consume(mdev, &t);
if (id < 0)
return id;
txp->token = cpu_to_le16(id); txp->token = cpu_to_le16(id);
if (test_bit(MT_WCID_FLAG_4ADDR, &wcid->flags)) if (test_bit(MT_WCID_FLAG_4ADDR, &wcid->flags))
txp->rept_wds_wcid = cpu_to_le16(wcid->idx); txp->rept_wds_wcid = cpu_to_le16(wcid->idx);
......
...@@ -176,7 +176,7 @@ mt7915_get_phy_mode(struct ieee80211_vif *vif, struct ieee80211_sta *sta) ...@@ -176,7 +176,7 @@ mt7915_get_phy_mode(struct ieee80211_vif *vif, struct ieee80211_sta *sta)
if (ht_cap->ht_supported) if (ht_cap->ht_supported)
mode |= PHY_MODE_GN; mode |= PHY_MODE_GN;
if (he_cap->has_he) if (he_cap && he_cap->has_he)
mode |= PHY_MODE_AX_24G; mode |= PHY_MODE_AX_24G;
} else if (band == NL80211_BAND_5GHZ) { } else if (band == NL80211_BAND_5GHZ) {
mode |= PHY_MODE_A; mode |= PHY_MODE_A;
...@@ -187,7 +187,7 @@ mt7915_get_phy_mode(struct ieee80211_vif *vif, struct ieee80211_sta *sta) ...@@ -187,7 +187,7 @@ mt7915_get_phy_mode(struct ieee80211_vif *vif, struct ieee80211_sta *sta)
if (vht_cap->vht_supported) if (vht_cap->vht_supported)
mode |= PHY_MODE_AC; mode |= PHY_MODE_AC;
if (he_cap->has_he) if (he_cap && he_cap->has_he)
mode |= PHY_MODE_AX_5G; mode |= PHY_MODE_AX_5G;
} }
......
...@@ -142,15 +142,11 @@ int mt7921s_mac_reset(struct mt7921_dev *dev) ...@@ -142,15 +142,11 @@ int mt7921s_mac_reset(struct mt7921_dev *dev)
static void static void
mt7921s_write_txwi(struct mt7921_dev *dev, struct mt76_wcid *wcid, mt7921s_write_txwi(struct mt7921_dev *dev, struct mt76_wcid *wcid,
enum mt76_txq_id qid, struct ieee80211_sta *sta, enum mt76_txq_id qid, struct ieee80211_sta *sta,
struct ieee80211_key_conf *key, int pid,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); __le32 *txwi = (__le32 *)(skb->data - MT_SDIO_TXD_SIZE);
struct ieee80211_key_conf *key = info->control.hw_key;
__le32 *txwi;
int pid;
pid = mt76_tx_status_skb_add(&dev->mt76, wcid, skb);
txwi = (__le32 *)(skb->data - MT_SDIO_TXD_SIZE);
memset(txwi, 0, MT_SDIO_TXD_SIZE); memset(txwi, 0, MT_SDIO_TXD_SIZE);
mt7921_mac_write_txwi(dev, txwi, skb, wcid, key, pid, false); mt7921_mac_write_txwi(dev, txwi, skb, wcid, key, pid, false);
skb_push(skb, MT_SDIO_TXD_SIZE); skb_push(skb, MT_SDIO_TXD_SIZE);
...@@ -163,8 +159,9 @@ int mt7921s_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, ...@@ -163,8 +159,9 @@ int mt7921s_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
{ {
struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb);
struct ieee80211_key_conf *key = info->control.hw_key;
struct sk_buff *skb = tx_info->skb; struct sk_buff *skb = tx_info->skb;
int pad; int err, pad, pktid;
if (unlikely(tx_info->skb->len <= ETH_HLEN)) if (unlikely(tx_info->skb->len <= ETH_HLEN))
return -EINVAL; return -EINVAL;
...@@ -181,12 +178,18 @@ int mt7921s_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, ...@@ -181,12 +178,18 @@ int mt7921s_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
} }
} }
mt7921s_write_txwi(dev, wcid, qid, sta, skb); pktid = mt76_tx_status_skb_add(&dev->mt76, wcid, skb);
mt7921s_write_txwi(dev, wcid, qid, sta, key, pktid, skb);
mt7921_skb_add_sdio_hdr(skb, MT7921_SDIO_DATA); mt7921_skb_add_sdio_hdr(skb, MT7921_SDIO_DATA);
pad = round_up(skb->len, 4) - skb->len; pad = round_up(skb->len, 4) - skb->len;
return mt76_skb_adjust_pad(skb, pad); err = mt76_skb_adjust_pad(skb, pad);
if (err)
/* Release pktid in case of error. */
idr_remove(&wcid->pktid, pktid);
return err;
} }
void mt7921s_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e) void mt7921s_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e)
......
...@@ -173,7 +173,7 @@ mt76_tx_status_skb_get(struct mt76_dev *dev, struct mt76_wcid *wcid, int pktid, ...@@ -173,7 +173,7 @@ mt76_tx_status_skb_get(struct mt76_dev *dev, struct mt76_wcid *wcid, int pktid,
if (!(cb->flags & MT_TX_CB_DMA_DONE)) if (!(cb->flags & MT_TX_CB_DMA_DONE))
continue; continue;
if (!time_is_after_jiffies(cb->jiffies + if (time_is_after_jiffies(cb->jiffies +
MT_TX_STATUS_SKB_TIMEOUT)) MT_TX_STATUS_SKB_TIMEOUT))
continue; continue;
} }
......
...@@ -25,6 +25,9 @@ static bool rt2x00usb_check_usb_error(struct rt2x00_dev *rt2x00dev, int status) ...@@ -25,6 +25,9 @@ static bool rt2x00usb_check_usb_error(struct rt2x00_dev *rt2x00dev, int status)
if (status == -ENODEV || status == -ENOENT) if (status == -ENODEV || status == -ENOENT)
return true; return true;
if (!test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags))
return false;
if (status == -EPROTO || status == -ETIMEDOUT) if (status == -EPROTO || status == -ETIMEDOUT)
rt2x00dev->num_proto_errs++; rt2x00dev->num_proto_errs++;
else else
......
...@@ -91,7 +91,6 @@ static int rtw89_fw_hdr_parser(struct rtw89_dev *rtwdev, const u8 *fw, u32 len, ...@@ -91,7 +91,6 @@ static int rtw89_fw_hdr_parser(struct rtw89_dev *rtwdev, const u8 *fw, u32 len,
info->section_num = GET_FW_HDR_SEC_NUM(fw); info->section_num = GET_FW_HDR_SEC_NUM(fw);
info->hdr_len = RTW89_FW_HDR_SIZE + info->hdr_len = RTW89_FW_HDR_SIZE +
info->section_num * RTW89_FW_SECTION_HDR_SIZE; info->section_num * RTW89_FW_SECTION_HDR_SIZE;
SET_FW_HDR_PART_SIZE(fw, FWDL_SECTION_PER_PKT_LEN);
bin = fw + info->hdr_len; bin = fw + info->hdr_len;
...@@ -275,6 +274,7 @@ static int __rtw89_fw_download_hdr(struct rtw89_dev *rtwdev, const u8 *fw, u32 l ...@@ -275,6 +274,7 @@ static int __rtw89_fw_download_hdr(struct rtw89_dev *rtwdev, const u8 *fw, u32 l
} }
skb_put_data(skb, fw, len); skb_put_data(skb, fw, len);
SET_FW_HDR_PART_SIZE(skb->data, FWDL_SECTION_PER_PKT_LEN);
rtw89_h2c_pkt_set_hdr_fwdl(rtwdev, skb, FWCMD_TYPE_H2C, rtw89_h2c_pkt_set_hdr_fwdl(rtwdev, skb, FWCMD_TYPE_H2C,
H2C_CAT_MAC, H2C_CL_MAC_FWDL, H2C_CAT_MAC, H2C_CL_MAC_FWDL,
H2C_FUNC_MAC_FWHDR_DL, len); H2C_FUNC_MAC_FWHDR_DL, len);
......
...@@ -282,8 +282,10 @@ struct rtw89_h2creg_sch_tx_en { ...@@ -282,8 +282,10 @@ struct rtw89_h2creg_sch_tx_en {
le32_get_bits(*((__le32 *)(fwhdr) + 6), GENMASK(15, 8)) le32_get_bits(*((__le32 *)(fwhdr) + 6), GENMASK(15, 8))
#define GET_FW_HDR_CMD_VERSERION(fwhdr) \ #define GET_FW_HDR_CMD_VERSERION(fwhdr) \
le32_get_bits(*((__le32 *)(fwhdr) + 7), GENMASK(31, 24)) le32_get_bits(*((__le32 *)(fwhdr) + 7), GENMASK(31, 24))
#define SET_FW_HDR_PART_SIZE(fwhdr, val) \ static inline void SET_FW_HDR_PART_SIZE(void *fwhdr, u32 val)
le32p_replace_bits((__le32 *)(fwhdr) + 7, val, GENMASK(15, 0)) {
le32p_replace_bits((__le32 *)fwhdr + 7, val, GENMASK(15, 0));
}
#define SET_CTRL_INFO_MACID(table, val) \ #define SET_CTRL_INFO_MACID(table, val) \
le32p_replace_bits((__le32 *)(table) + 0, val, GENMASK(6, 0)) le32p_replace_bits((__le32 *)(table) + 0, val, GENMASK(6, 0))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment