mirror of https://gitee.com/openkylin/linux.git
wireless-drivers fixes for 5.1
Second set of fixes for 5.1. iwlwifi * add some new PCI IDs (plus a struct name change they depend on) * fix crypto with new devices, namely 22560 and above * fix for a potential deadlock in the TX path * a fix for offloaded rate-control * support new PCI HW IDs which use a new FW mt76 * fix lock initialisation and a possible deadlock * aggregation fixes rt2x00 * fix sequence numbering during retransmits -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJctIf2AAoJEG4XJFUm622bm4UH/RjizpPno79+PxKgZFxhYcWJ 4sBW1hDwcO4FNKLX3tf6WR4N/vxkPEWSbB1gGRbHAIeYeb74ab5hYQoCVaOnU8GL uzhjgGVHwUnBi0oluuG12gpU9Zf6raV4Ec9HdRszx1A8DOa0qn5lUrXwWbF3GlZZ BU4ojdOZOVQx+yqE+xIr7okcbBpxRZgLK7KthKWgR4G9RlISIsfMYAHE1fwPmPr8 b7fwqAKkgJ5fGSxez1tv7hlYaRw2zVwFYrVv3TegRKMl1pHTI/ps3ip37JTwv+O0 lv5112AgEO2cSPT/R0wWqEkZ21Rc/AeFbttcQ9Ejw1SPc/w2d+fX8pTY5/RPw8w= =RCyH -----END PGP SIGNATURE----- Merge tag 'wireless-drivers-for-davem-2019-04-15' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers Kalle Valo says: ==================== wireless-drivers fixes for 5.1 Second set of fixes for 5.1. iwlwifi * add some new PCI IDs (plus a struct name change they depend on) * fix crypto with new devices, namely 22560 and above * fix for a potential deadlock in the TX path * a fix for offloaded rate-control * support new PCI HW IDs which use a new FW mt76 * fix lock initialisation and a possible deadlock * aggregation fixes rt2x00 * fix sequence numbering during retransmits ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
a44acf9060
|
@ -82,6 +82,7 @@
|
|||
#define IWL_22000_HR_A0_FW_PRE "iwlwifi-QuQnj-a0-hr-a0-"
|
||||
#define IWL_22000_SU_Z0_FW_PRE "iwlwifi-su-z0-"
|
||||
#define IWL_QU_B_JF_B_FW_PRE "iwlwifi-Qu-b0-jf-b0-"
|
||||
#define IWL_QUZ_A_HR_B_FW_PRE "iwlwifi-QuZ-a0-hr-b0-"
|
||||
#define IWL_QNJ_B_JF_B_FW_PRE "iwlwifi-QuQnj-b0-jf-b0-"
|
||||
#define IWL_CC_A_FW_PRE "iwlwifi-cc-a0-"
|
||||
#define IWL_22000_SO_A_JF_B_FW_PRE "iwlwifi-so-a0-jf-b0-"
|
||||
|
@ -105,8 +106,8 @@
|
|||
IWL_22000_HR_A0_FW_PRE __stringify(api) ".ucode"
|
||||
#define IWL_22000_SU_Z0_MODULE_FIRMWARE(api) \
|
||||
IWL_22000_SU_Z0_FW_PRE __stringify(api) ".ucode"
|
||||
#define IWL_QU_B_JF_B_MODULE_FIRMWARE(api) \
|
||||
IWL_QU_B_JF_B_FW_PRE __stringify(api) ".ucode"
|
||||
#define IWL_QUZ_A_HR_B_MODULE_FIRMWARE(api) \
|
||||
IWL_QUZ_A_HR_B_FW_PRE __stringify(api) ".ucode"
|
||||
#define IWL_QU_B_JF_B_MODULE_FIRMWARE(api) \
|
||||
IWL_QU_B_JF_B_FW_PRE __stringify(api) ".ucode"
|
||||
#define IWL_QNJ_B_JF_B_MODULE_FIRMWARE(api) \
|
||||
|
@ -235,8 +236,20 @@ const struct iwl_cfg iwl_ax101_cfg_qu_hr = {
|
|||
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl22260_2ax_cfg = {
|
||||
.name = "Intel(R) Wireless-AX 22260",
|
||||
const struct iwl_cfg iwl_ax101_cfg_quz_hr = {
|
||||
.name = "Intel(R) Wi-Fi 6 AX101",
|
||||
.fw_name_pre = IWL_QUZ_A_HR_B_FW_PRE,
|
||||
IWL_DEVICE_22500,
|
||||
/*
|
||||
* This device doesn't support receiving BlockAck with a large bitmap
|
||||
* so we need to restrict the size of transmitted aggregation to the
|
||||
* HT size; mac80211 would otherwise pick the HE max (256) by default.
|
||||
*/
|
||||
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl_ax200_cfg_cc = {
|
||||
.name = "Intel(R) Wi-Fi 6 AX200 160MHz",
|
||||
.fw_name_pre = IWL_CC_A_FW_PRE,
|
||||
IWL_DEVICE_22500,
|
||||
/*
|
||||
|
@ -249,7 +262,7 @@ const struct iwl_cfg iwl22260_2ax_cfg = {
|
|||
};
|
||||
|
||||
const struct iwl_cfg killer1650x_2ax_cfg = {
|
||||
.name = "Killer(R) Wireless-AX 1650x Wireless Network Adapter (200NGW)",
|
||||
.name = "Killer(R) Wi-Fi 6 AX1650x 160MHz Wireless Network Adapter (200NGW)",
|
||||
.fw_name_pre = IWL_CC_A_FW_PRE,
|
||||
IWL_DEVICE_22500,
|
||||
/*
|
||||
|
@ -262,7 +275,7 @@ const struct iwl_cfg killer1650x_2ax_cfg = {
|
|||
};
|
||||
|
||||
const struct iwl_cfg killer1650w_2ax_cfg = {
|
||||
.name = "Killer(R) Wireless-AX 1650w Wireless Network Adapter (200D2W)",
|
||||
.name = "Killer(R) Wi-Fi 6 AX1650w 160MHz Wireless Network Adapter (200D2W)",
|
||||
.fw_name_pre = IWL_CC_A_FW_PRE,
|
||||
IWL_DEVICE_22500,
|
||||
/*
|
||||
|
@ -328,7 +341,7 @@ const struct iwl_cfg killer1550s_2ac_cfg_qu_b0_jf_b0 = {
|
|||
};
|
||||
|
||||
const struct iwl_cfg killer1650s_2ax_cfg_qu_b0_hr_b0 = {
|
||||
.name = "Killer(R) Wireless-AX 1650i Wireless Network Adapter (22560NGW)",
|
||||
.name = "Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201NGW)",
|
||||
.fw_name_pre = IWL_22000_QU_B_HR_B_FW_PRE,
|
||||
IWL_DEVICE_22500,
|
||||
/*
|
||||
|
@ -340,7 +353,7 @@ const struct iwl_cfg killer1650s_2ax_cfg_qu_b0_hr_b0 = {
|
|||
};
|
||||
|
||||
const struct iwl_cfg killer1650i_2ax_cfg_qu_b0_hr_b0 = {
|
||||
.name = "Killer(R) Wireless-AX 1650s Wireless Network Adapter (22560D2W)",
|
||||
.name = "Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter (201D2W)",
|
||||
.fw_name_pre = IWL_22000_QU_B_HR_B_FW_PRE,
|
||||
IWL_DEVICE_22500,
|
||||
/*
|
||||
|
@ -444,6 +457,7 @@ MODULE_FIRMWARE(IWL_22000_HR_B_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
|||
MODULE_FIRMWARE(IWL_22000_HR_A0_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_22000_SU_Z0_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_QU_B_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_QUZ_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_QNJ_B_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_CC_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_22000_SO_A_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
|
|
|
@ -1614,6 +1614,7 @@ iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt,
|
|||
if (!range) {
|
||||
IWL_ERR(fwrt, "Failed to fill region header: id=%d, type=%d\n",
|
||||
le32_to_cpu(reg->region_id), type);
|
||||
memset(*data, 0, le32_to_cpu((*data)->len));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1623,6 +1624,7 @@ iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt,
|
|||
if (range_size < 0) {
|
||||
IWL_ERR(fwrt, "Failed to dump region: id=%d, type=%d\n",
|
||||
le32_to_cpu(reg->region_id), type);
|
||||
memset(*data, 0, le32_to_cpu((*data)->len));
|
||||
return;
|
||||
}
|
||||
range = range + range_size;
|
||||
|
@ -1807,12 +1809,12 @@ _iwl_fw_error_ini_dump(struct iwl_fw_runtime *fwrt,
|
|||
|
||||
trigger = fwrt->dump.active_trigs[id].trig;
|
||||
|
||||
size = sizeof(*dump_file);
|
||||
size += iwl_fw_ini_get_trigger_len(fwrt, trigger);
|
||||
|
||||
size = iwl_fw_ini_get_trigger_len(fwrt, trigger);
|
||||
if (!size)
|
||||
return NULL;
|
||||
|
||||
size += sizeof(*dump_file);
|
||||
|
||||
dump_file = vzalloc(size);
|
||||
if (!dump_file)
|
||||
return NULL;
|
||||
|
@ -1942,14 +1944,10 @@ int iwl_fw_dbg_error_collect(struct iwl_fw_runtime *fwrt,
|
|||
iwl_dump_error_desc->len = 0;
|
||||
|
||||
ret = iwl_fw_dbg_collect_desc(fwrt, iwl_dump_error_desc, false, 0);
|
||||
if (ret) {
|
||||
if (ret)
|
||||
kfree(iwl_dump_error_desc);
|
||||
} else {
|
||||
set_bit(STATUS_FW_WAIT_DUMP, &fwrt->trans->status);
|
||||
|
||||
/* trigger nmi to halt the fw */
|
||||
iwl_force_nmi(fwrt->trans);
|
||||
}
|
||||
else
|
||||
iwl_trans_sync_nmi(fwrt->trans);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -2489,22 +2487,6 @@ IWL_EXPORT_SYMBOL(iwl_fw_dbg_apply_point);
|
|||
|
||||
void iwl_fwrt_stop_device(struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
/* if the wait event timeout elapses instead of wake up then
|
||||
* the driver did not receive NMI interrupt and can not assume the FW
|
||||
* is halted
|
||||
*/
|
||||
int ret = wait_event_timeout(fwrt->trans->fw_halt_waitq,
|
||||
!test_bit(STATUS_FW_WAIT_DUMP,
|
||||
&fwrt->trans->status),
|
||||
msecs_to_jiffies(2000));
|
||||
if (!ret) {
|
||||
/* failed to receive NMI interrupt, assuming the FW is stuck */
|
||||
set_bit(STATUS_FW_ERROR, &fwrt->trans->status);
|
||||
|
||||
clear_bit(STATUS_FW_WAIT_DUMP, &fwrt->trans->status);
|
||||
}
|
||||
|
||||
/* Assuming the op mode mutex is held at this point */
|
||||
iwl_fw_dbg_collect_sync(fwrt);
|
||||
|
||||
iwl_trans_stop_device(fwrt->trans);
|
||||
|
|
|
@ -76,7 +76,6 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
|
|||
fwrt->ops_ctx = ops_ctx;
|
||||
INIT_DELAYED_WORK(&fwrt->dump.wk, iwl_fw_error_dump_wk);
|
||||
iwl_fwrt_dbgfs_register(fwrt, dbgfs_dir);
|
||||
init_waitqueue_head(&fwrt->trans->fw_halt_waitq);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_fw_runtime_init);
|
||||
|
||||
|
|
|
@ -549,8 +549,9 @@ extern const struct iwl_cfg iwl22000_2ac_cfg_hr;
|
|||
extern const struct iwl_cfg iwl22000_2ac_cfg_hr_cdb;
|
||||
extern const struct iwl_cfg iwl22000_2ac_cfg_jf;
|
||||
extern const struct iwl_cfg iwl_ax101_cfg_qu_hr;
|
||||
extern const struct iwl_cfg iwl_ax101_cfg_quz_hr;
|
||||
extern const struct iwl_cfg iwl22000_2ax_cfg_hr;
|
||||
extern const struct iwl_cfg iwl22260_2ax_cfg;
|
||||
extern const struct iwl_cfg iwl_ax200_cfg_cc;
|
||||
extern const struct iwl_cfg killer1650s_2ax_cfg_qu_b0_hr_b0;
|
||||
extern const struct iwl_cfg killer1650i_2ax_cfg_qu_b0_hr_b0;
|
||||
extern const struct iwl_cfg killer1650x_2ax_cfg;
|
||||
|
|
|
@ -327,6 +327,7 @@ enum {
|
|||
#define CSR_HW_REV_TYPE_NONE (0x00001F0)
|
||||
#define CSR_HW_REV_TYPE_QNJ (0x0000360)
|
||||
#define CSR_HW_REV_TYPE_QNJ_B0 (0x0000364)
|
||||
#define CSR_HW_REV_TYPE_QUZ (0x0000354)
|
||||
#define CSR_HW_REV_TYPE_HR_CDB (0x0000340)
|
||||
#define CSR_HW_REV_TYPE_SO (0x0000370)
|
||||
#define CSR_HW_REV_TYPE_TY (0x0000420)
|
||||
|
|
|
@ -338,7 +338,6 @@ enum iwl_d3_status {
|
|||
* are sent
|
||||
* @STATUS_TRANS_IDLE: the trans is idle - general commands are not to be sent
|
||||
* @STATUS_TRANS_DEAD: trans is dead - avoid any read/write operation
|
||||
* @STATUS_FW_WAIT_DUMP: if set, wait until cleared before collecting dump
|
||||
*/
|
||||
enum iwl_trans_status {
|
||||
STATUS_SYNC_HCMD_ACTIVE,
|
||||
|
@ -351,7 +350,6 @@ enum iwl_trans_status {
|
|||
STATUS_TRANS_GOING_IDLE,
|
||||
STATUS_TRANS_IDLE,
|
||||
STATUS_TRANS_DEAD,
|
||||
STATUS_FW_WAIT_DUMP,
|
||||
};
|
||||
|
||||
static inline int
|
||||
|
@ -618,6 +616,7 @@ struct iwl_trans_ops {
|
|||
struct iwl_trans_dump_data *(*dump_data)(struct iwl_trans *trans,
|
||||
u32 dump_mask);
|
||||
void (*debugfs_cleanup)(struct iwl_trans *trans);
|
||||
void (*sync_nmi)(struct iwl_trans *trans);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -831,7 +830,6 @@ struct iwl_trans {
|
|||
u32 lmac_error_event_table[2];
|
||||
u32 umac_error_event_table;
|
||||
unsigned int error_event_table_tlv_status;
|
||||
wait_queue_head_t fw_halt_waitq;
|
||||
|
||||
/* pointer to trans specific struct */
|
||||
/*Ensure that this pointer will always be aligned to sizeof pointer */
|
||||
|
@ -1239,10 +1237,12 @@ static inline void iwl_trans_fw_error(struct iwl_trans *trans)
|
|||
/* prevent double restarts due to the same erroneous FW */
|
||||
if (!test_and_set_bit(STATUS_FW_ERROR, &trans->status))
|
||||
iwl_op_mode_nic_error(trans->op_mode);
|
||||
}
|
||||
|
||||
if (test_and_clear_bit(STATUS_FW_WAIT_DUMP, &trans->status))
|
||||
wake_up(&trans->fw_halt_waitq);
|
||||
|
||||
static inline void iwl_trans_sync_nmi(struct iwl_trans *trans)
|
||||
{
|
||||
if (trans->ops->sync_nmi)
|
||||
trans->ops->sync_nmi(trans);
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
|
|
|
@ -2714,9 +2714,6 @@ static void iwl_mvm_stop_ap_ibss(struct ieee80211_hw *hw,
|
|||
|
||||
iwl_mvm_mac_ctxt_remove(mvm, vif);
|
||||
|
||||
kfree(mvmvif->ap_wep_key);
|
||||
mvmvif->ap_wep_key = NULL;
|
||||
|
||||
mutex_unlock(&mvm->mutex);
|
||||
}
|
||||
|
||||
|
@ -3183,24 +3180,7 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
|
|||
ret = iwl_mvm_update_sta(mvm, vif, sta);
|
||||
} else if (old_state == IEEE80211_STA_ASSOC &&
|
||||
new_state == IEEE80211_STA_AUTHORIZED) {
|
||||
/* if wep is used, need to set the key for the station now */
|
||||
if (vif->type == NL80211_IFTYPE_AP && mvmvif->ap_wep_key) {
|
||||
mvm_sta->wep_key =
|
||||
kmemdup(mvmvif->ap_wep_key,
|
||||
sizeof(*mvmvif->ap_wep_key) +
|
||||
mvmvif->ap_wep_key->keylen,
|
||||
GFP_KERNEL);
|
||||
if (!mvm_sta->wep_key) {
|
||||
ret = -ENOMEM;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
ret = iwl_mvm_set_sta_key(mvm, vif, sta,
|
||||
mvm_sta->wep_key,
|
||||
STA_KEY_IDX_INVALID);
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
/* we don't support TDLS during DCM */
|
||||
if (iwl_mvm_phy_ctx_count(mvm) > 1)
|
||||
|
@ -3242,17 +3222,6 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
|
|||
NL80211_TDLS_DISABLE_LINK);
|
||||
}
|
||||
|
||||
/* Remove STA key if this is an AP using WEP */
|
||||
if (vif->type == NL80211_IFTYPE_AP && mvmvif->ap_wep_key) {
|
||||
int rm_ret = iwl_mvm_remove_sta_key(mvm, vif, sta,
|
||||
mvm_sta->wep_key);
|
||||
|
||||
if (!ret)
|
||||
ret = rm_ret;
|
||||
kfree(mvm_sta->wep_key);
|
||||
mvm_sta->wep_key = NULL;
|
||||
}
|
||||
|
||||
if (unlikely(ret &&
|
||||
test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
|
||||
&mvm->status)))
|
||||
|
@ -3289,6 +3258,13 @@ static void iwl_mvm_sta_rc_update(struct ieee80211_hw *hw,
|
|||
struct ieee80211_sta *sta, u32 changed)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
if (changed & (IEEE80211_RC_BW_CHANGED |
|
||||
IEEE80211_RC_SUPP_RATES_CHANGED |
|
||||
IEEE80211_RC_NSS_CHANGED))
|
||||
iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band,
|
||||
true);
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_STATION &&
|
||||
changed & IEEE80211_RC_NSS_CHANGED)
|
||||
|
@ -3439,20 +3415,12 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
|
|||
break;
|
||||
case WLAN_CIPHER_SUITE_WEP40:
|
||||
case WLAN_CIPHER_SUITE_WEP104:
|
||||
if (vif->type == NL80211_IFTYPE_AP) {
|
||||
struct iwl_mvm_vif *mvmvif =
|
||||
iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
mvmvif->ap_wep_key = kmemdup(key,
|
||||
sizeof(*key) + key->keylen,
|
||||
GFP_KERNEL);
|
||||
if (!mvmvif->ap_wep_key)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_STATION)
|
||||
return 0;
|
||||
break;
|
||||
if (vif->type == NL80211_IFTYPE_STATION)
|
||||
break;
|
||||
if (iwl_mvm_has_new_tx_api(mvm))
|
||||
return -EOPNOTSUPP;
|
||||
/* support HW crypto on TX */
|
||||
return 0;
|
||||
default:
|
||||
/* currently FW supports only one optional cipher scheme */
|
||||
if (hw->n_cipher_schemes &&
|
||||
|
@ -3540,12 +3508,17 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
|
|||
ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, key_offset);
|
||||
if (ret) {
|
||||
IWL_WARN(mvm, "set key failed\n");
|
||||
key->hw_key_idx = STA_KEY_IDX_INVALID;
|
||||
/*
|
||||
* can't add key for RX, but we don't need it
|
||||
* in the device for TX so still return 0
|
||||
* in the device for TX so still return 0,
|
||||
* unless we have new TX API where we cannot
|
||||
* put key material into the TX_CMD
|
||||
*/
|
||||
key->hw_key_idx = STA_KEY_IDX_INVALID;
|
||||
ret = 0;
|
||||
if (iwl_mvm_has_new_tx_api(mvm))
|
||||
ret = -EOPNOTSUPP;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
|
@ -498,7 +498,6 @@ struct iwl_mvm_vif {
|
|||
netdev_features_t features;
|
||||
|
||||
struct iwl_probe_resp_data __rcu *probe_resp_data;
|
||||
struct ieee80211_key_conf *ap_wep_key;
|
||||
};
|
||||
|
||||
static inline struct iwl_mvm_vif *
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
* Copyright(c) 2012 - 2015 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -31,7 +31,7 @@
|
|||
* Copyright(c) 2012 - 2015 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -1399,7 +1399,9 @@ void iwl_mvm_add_new_dqa_stream_wk(struct work_struct *wk)
|
|||
|
||||
iwl_mvm_sta_alloc_queue(mvm, txq->sta, txq->ac, tid);
|
||||
list_del_init(&mvmtxq->list);
|
||||
local_bh_disable();
|
||||
iwl_mvm_mac_itxq_xmit(mvm->hw, txq);
|
||||
local_bh_enable();
|
||||
}
|
||||
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
@ -2333,21 +2335,6 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
|||
iwl_mvm_enable_txq(mvm, NULL, mvmvif->cab_queue, 0, &cfg,
|
||||
timeout);
|
||||
|
||||
if (mvmvif->ap_wep_key) {
|
||||
u8 key_offset = iwl_mvm_set_fw_key_idx(mvm);
|
||||
|
||||
__set_bit(key_offset, mvm->fw_key_table);
|
||||
|
||||
if (key_offset == STA_KEY_IDX_INVALID)
|
||||
return -ENOSPC;
|
||||
|
||||
ret = iwl_mvm_send_sta_key(mvm, mvmvif->mcast_sta.sta_id,
|
||||
mvmvif->ap_wep_key, true, 0, NULL, 0,
|
||||
key_offset, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2419,28 +2406,6 @@ int iwl_mvm_rm_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
|||
|
||||
iwl_mvm_disable_txq(mvm, NULL, mvmvif->cab_queue, 0, 0);
|
||||
|
||||
if (mvmvif->ap_wep_key) {
|
||||
int i;
|
||||
|
||||
if (!__test_and_clear_bit(mvmvif->ap_wep_key->hw_key_idx,
|
||||
mvm->fw_key_table)) {
|
||||
IWL_ERR(mvm, "offset %d not used in fw key table.\n",
|
||||
mvmvif->ap_wep_key->hw_key_idx);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/* track which key was deleted last */
|
||||
for (i = 0; i < STA_KEY_MAX_NUM; i++) {
|
||||
if (mvm->fw_key_deleted[i] < U8_MAX)
|
||||
mvm->fw_key_deleted[i]++;
|
||||
}
|
||||
mvm->fw_key_deleted[mvmvif->ap_wep_key->hw_key_idx] = 0;
|
||||
ret = __iwl_mvm_remove_sta_key(mvm, mvmvif->mcast_sta.sta_id,
|
||||
mvmvif->ap_wep_key, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = iwl_mvm_rm_sta_common(mvm, mvmvif->mcast_sta.sta_id);
|
||||
if (ret)
|
||||
IWL_WARN(mvm, "Failed sending remove station\n");
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2015 - 2016 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -31,7 +31,7 @@
|
|||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2015 - 2016 Intel Deutschland GmbH
|
||||
* Copyright(c) 2018 Intel Corporation
|
||||
* Copyright(c) 2018 - 2019 Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -394,7 +394,6 @@ struct iwl_mvm_rxq_dup_data {
|
|||
* the BA window. To be used for UAPSD only.
|
||||
* @ptk_pn: per-queue PTK PN data structures
|
||||
* @dup_data: per queue duplicate packet detection data
|
||||
* @wep_key: used in AP mode. Is a duplicate of the WEP key.
|
||||
* @deferred_traffic_tid_map: indication bitmap of deferred traffic per-TID
|
||||
* @tx_ant: the index of the antenna to use for data tx to this station. Only
|
||||
* used during connection establishment (e.g. for the 4 way handshake
|
||||
|
@ -426,8 +425,6 @@ struct iwl_mvm_sta {
|
|||
struct iwl_mvm_key_pn __rcu *ptk_pn[4];
|
||||
struct iwl_mvm_rxq_dup_data *dup_data;
|
||||
|
||||
struct ieee80211_key_conf *wep_key;
|
||||
|
||||
u8 reserved_queue;
|
||||
|
||||
/* Temporary, until the new TLC will control the Tx protection */
|
||||
|
|
|
@ -953,14 +953,15 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
|
|||
{IWL_PCI_DEVICE(0xA0F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0)},
|
||||
{IWL_PCI_DEVICE(0xA0F0, 0x4070, iwl_ax101_cfg_qu_hr)},
|
||||
|
||||
{IWL_PCI_DEVICE(0x2723, 0x0080, iwl22260_2ax_cfg)},
|
||||
{IWL_PCI_DEVICE(0x2723, 0x0084, iwl22260_2ax_cfg)},
|
||||
{IWL_PCI_DEVICE(0x2723, 0x0088, iwl22260_2ax_cfg)},
|
||||
{IWL_PCI_DEVICE(0x2723, 0x008C, iwl22260_2ax_cfg)},
|
||||
{IWL_PCI_DEVICE(0x2723, 0x0080, iwl_ax200_cfg_cc)},
|
||||
{IWL_PCI_DEVICE(0x2723, 0x0084, iwl_ax200_cfg_cc)},
|
||||
{IWL_PCI_DEVICE(0x2723, 0x0088, iwl_ax200_cfg_cc)},
|
||||
{IWL_PCI_DEVICE(0x2723, 0x008C, iwl_ax200_cfg_cc)},
|
||||
{IWL_PCI_DEVICE(0x2723, 0x1653, killer1650w_2ax_cfg)},
|
||||
{IWL_PCI_DEVICE(0x2723, 0x1654, killer1650x_2ax_cfg)},
|
||||
{IWL_PCI_DEVICE(0x2723, 0x4080, iwl22260_2ax_cfg)},
|
||||
{IWL_PCI_DEVICE(0x2723, 0x4088, iwl22260_2ax_cfg)},
|
||||
{IWL_PCI_DEVICE(0x2723, 0x2080, iwl_ax200_cfg_cc)},
|
||||
{IWL_PCI_DEVICE(0x2723, 0x4080, iwl_ax200_cfg_cc)},
|
||||
{IWL_PCI_DEVICE(0x2723, 0x4088, iwl_ax200_cfg_cc)},
|
||||
|
||||
{IWL_PCI_DEVICE(0x1a56, 0x1653, killer1650w_2ax_cfg)},
|
||||
{IWL_PCI_DEVICE(0x1a56, 0x1654, killer1650x_2ax_cfg)},
|
||||
|
|
|
@ -1043,7 +1043,7 @@ static inline bool iwl_pcie_dbg_on(struct iwl_trans *trans)
|
|||
|
||||
void iwl_trans_pcie_rf_kill(struct iwl_trans *trans, bool state);
|
||||
void iwl_trans_pcie_dump_regs(struct iwl_trans *trans);
|
||||
void iwl_trans_sync_nmi(struct iwl_trans *trans);
|
||||
void iwl_trans_pcie_sync_nmi(struct iwl_trans *trans);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans);
|
||||
|
|
|
@ -3318,7 +3318,8 @@ static void iwl_trans_pcie_resume(struct iwl_trans *trans)
|
|||
.unref = iwl_trans_pcie_unref, \
|
||||
.dump_data = iwl_trans_pcie_dump_data, \
|
||||
.d3_suspend = iwl_trans_pcie_d3_suspend, \
|
||||
.d3_resume = iwl_trans_pcie_d3_resume
|
||||
.d3_resume = iwl_trans_pcie_d3_resume, \
|
||||
.sync_nmi = iwl_trans_pcie_sync_nmi
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
#define IWL_TRANS_PM_OPS \
|
||||
|
@ -3542,6 +3543,10 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
|||
}
|
||||
} else if (cfg == &iwl_ax101_cfg_qu_hr) {
|
||||
if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) ==
|
||||
CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR) &&
|
||||
trans->hw_rev == CSR_HW_REV_TYPE_QNJ_B0) {
|
||||
trans->cfg = &iwl22000_2ax_cfg_qnj_hr_b0;
|
||||
} else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) ==
|
||||
CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR)) {
|
||||
trans->cfg = &iwl_ax101_cfg_qu_hr;
|
||||
} else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) ==
|
||||
|
@ -3560,7 +3565,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
|||
}
|
||||
} else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) ==
|
||||
CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR) &&
|
||||
(trans->cfg != &iwl22260_2ax_cfg ||
|
||||
(trans->cfg != &iwl_ax200_cfg_cc ||
|
||||
trans->hw_rev == CSR_HW_REV_TYPE_QNJ_B0)) {
|
||||
u32 hw_status;
|
||||
|
||||
|
@ -3637,7 +3642,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
|||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
void iwl_trans_sync_nmi(struct iwl_trans *trans)
|
||||
void iwl_trans_pcie_sync_nmi(struct iwl_trans *trans)
|
||||
{
|
||||
unsigned long timeout = jiffies + IWL_TRANS_NMI_TIMEOUT;
|
||||
|
||||
|
|
|
@ -965,7 +965,7 @@ static int iwl_pcie_gen2_send_hcmd_sync(struct iwl_trans *trans,
|
|||
cmd_str);
|
||||
ret = -ETIMEDOUT;
|
||||
|
||||
iwl_trans_sync_nmi(trans);
|
||||
iwl_trans_pcie_sync_nmi(trans);
|
||||
goto cancel;
|
||||
}
|
||||
|
||||
|
|
|
@ -1960,7 +1960,7 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans,
|
|||
iwl_get_cmd_string(trans, cmd->id));
|
||||
ret = -ETIMEDOUT;
|
||||
|
||||
iwl_trans_sync_nmi(trans);
|
||||
iwl_trans_pcie_sync_nmi(trans);
|
||||
goto cancel;
|
||||
}
|
||||
|
||||
|
|
|
@ -510,6 +510,8 @@ int mt7603_register_device(struct mt7603_dev *dev)
|
|||
bus_ops->rmw = mt7603_rmw;
|
||||
dev->mt76.bus = bus_ops;
|
||||
|
||||
spin_lock_init(&dev->ps_lock);
|
||||
|
||||
INIT_DELAYED_WORK(&dev->mac_work, mt7603_mac_work);
|
||||
tasklet_init(&dev->pre_tbtt_tasklet, mt7603_pre_tbtt_tasklet,
|
||||
(unsigned long)dev);
|
||||
|
|
|
@ -343,7 +343,7 @@ void mt7603_mac_rx_ba_reset(struct mt7603_dev *dev, void *addr, u8 tid)
|
|||
MT_BA_CONTROL_1_RESET));
|
||||
}
|
||||
|
||||
void mt7603_mac_tx_ba_reset(struct mt7603_dev *dev, int wcid, int tid, int ssn,
|
||||
void mt7603_mac_tx_ba_reset(struct mt7603_dev *dev, int wcid, int tid,
|
||||
int ba_size)
|
||||
{
|
||||
u32 addr = mt7603_wtbl2_addr(wcid);
|
||||
|
@ -358,43 +358,6 @@ void mt7603_mac_tx_ba_reset(struct mt7603_dev *dev, int wcid, int tid, int ssn,
|
|||
mt76_clear(dev, addr + (15 * 4), tid_mask);
|
||||
return;
|
||||
}
|
||||
mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000);
|
||||
|
||||
mt7603_mac_stop(dev);
|
||||
switch (tid) {
|
||||
case 0:
|
||||
mt76_rmw_field(dev, addr + (2 * 4), MT_WTBL2_W2_TID0_SN, ssn);
|
||||
break;
|
||||
case 1:
|
||||
mt76_rmw_field(dev, addr + (2 * 4), MT_WTBL2_W2_TID1_SN, ssn);
|
||||
break;
|
||||
case 2:
|
||||
mt76_rmw_field(dev, addr + (2 * 4), MT_WTBL2_W2_TID2_SN_LO,
|
||||
ssn);
|
||||
mt76_rmw_field(dev, addr + (3 * 4), MT_WTBL2_W3_TID2_SN_HI,
|
||||
ssn >> 8);
|
||||
break;
|
||||
case 3:
|
||||
mt76_rmw_field(dev, addr + (3 * 4), MT_WTBL2_W3_TID3_SN, ssn);
|
||||
break;
|
||||
case 4:
|
||||
mt76_rmw_field(dev, addr + (3 * 4), MT_WTBL2_W3_TID4_SN, ssn);
|
||||
break;
|
||||
case 5:
|
||||
mt76_rmw_field(dev, addr + (3 * 4), MT_WTBL2_W3_TID5_SN_LO,
|
||||
ssn);
|
||||
mt76_rmw_field(dev, addr + (4 * 4), MT_WTBL2_W4_TID5_SN_HI,
|
||||
ssn >> 4);
|
||||
break;
|
||||
case 6:
|
||||
mt76_rmw_field(dev, addr + (4 * 4), MT_WTBL2_W4_TID6_SN, ssn);
|
||||
break;
|
||||
case 7:
|
||||
mt76_rmw_field(dev, addr + (4 * 4), MT_WTBL2_W4_TID7_SN, ssn);
|
||||
break;
|
||||
}
|
||||
mt7603_wtbl_update(dev, wcid, MT_WTBL_UPDATE_WTBL2);
|
||||
mt7603_mac_start(dev);
|
||||
|
||||
for (i = 7; i > 0; i--) {
|
||||
if (ba_size >= MT_AGG_SIZE_LIMIT(i))
|
||||
|
@ -827,6 +790,7 @@ mt7603_mac_write_txwi(struct mt7603_dev *dev, __le32 *txwi,
|
|||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_tx_rate *rate = &info->control.rates[0];
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
struct ieee80211_bar *bar = (struct ieee80211_bar *)skb->data;
|
||||
struct ieee80211_vif *vif = info->control.vif;
|
||||
struct mt7603_vif *mvif;
|
||||
int wlan_idx;
|
||||
|
@ -834,6 +798,7 @@ mt7603_mac_write_txwi(struct mt7603_dev *dev, __le32 *txwi,
|
|||
int tx_count = 8;
|
||||
u8 frame_type, frame_subtype;
|
||||
u16 fc = le16_to_cpu(hdr->frame_control);
|
||||
u16 seqno = 0;
|
||||
u8 vif_idx = 0;
|
||||
u32 val;
|
||||
u8 bw;
|
||||
|
@ -919,7 +884,17 @@ mt7603_mac_write_txwi(struct mt7603_dev *dev, __le32 *txwi,
|
|||
tx_count = 0x1f;
|
||||
|
||||
val = FIELD_PREP(MT_TXD3_REM_TX_COUNT, tx_count) |
|
||||
FIELD_PREP(MT_TXD3_SEQ, le16_to_cpu(hdr->seq_ctrl));
|
||||
MT_TXD3_SN_VALID;
|
||||
|
||||
if (ieee80211_is_data_qos(hdr->frame_control))
|
||||
seqno = le16_to_cpu(hdr->seq_ctrl);
|
||||
else if (ieee80211_is_back_req(hdr->frame_control))
|
||||
seqno = le16_to_cpu(bar->start_seq_num);
|
||||
else
|
||||
val &= ~MT_TXD3_SN_VALID;
|
||||
|
||||
val |= FIELD_PREP(MT_TXD3_SEQ, seqno >> 4);
|
||||
|
||||
txwi[3] = cpu_to_le32(val);
|
||||
|
||||
if (key) {
|
||||
|
|
|
@ -372,7 +372,7 @@ mt7603_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps)
|
|||
struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv;
|
||||
struct sk_buff_head list;
|
||||
|
||||
mt76_stop_tx_queues(&dev->mt76, sta, false);
|
||||
mt76_stop_tx_queues(&dev->mt76, sta, true);
|
||||
mt7603_wtbl_set_ps(dev, msta, ps);
|
||||
if (ps)
|
||||
return;
|
||||
|
@ -584,13 +584,13 @@ mt7603_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
case IEEE80211_AMPDU_TX_OPERATIONAL:
|
||||
mtxq->aggr = true;
|
||||
mtxq->send_bar = false;
|
||||
mt7603_mac_tx_ba_reset(dev, msta->wcid.idx, tid, *ssn, ba_size);
|
||||
mt7603_mac_tx_ba_reset(dev, msta->wcid.idx, tid, ba_size);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH:
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
|
||||
mtxq->aggr = false;
|
||||
ieee80211_send_bar(vif, sta->addr, tid, mtxq->agg_ssn);
|
||||
mt7603_mac_tx_ba_reset(dev, msta->wcid.idx, tid, *ssn, -1);
|
||||
mt7603_mac_tx_ba_reset(dev, msta->wcid.idx, tid, -1);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_START:
|
||||
mtxq->agg_ssn = *ssn << 4;
|
||||
|
@ -598,7 +598,7 @@ mt7603_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
break;
|
||||
case IEEE80211_AMPDU_TX_STOP_CONT:
|
||||
mtxq->aggr = false;
|
||||
mt7603_mac_tx_ba_reset(dev, msta->wcid.idx, tid, *ssn, -1);
|
||||
mt7603_mac_tx_ba_reset(dev, msta->wcid.idx, tid, -1);
|
||||
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -200,7 +200,7 @@ void mt7603_beacon_set_timer(struct mt7603_dev *dev, int idx, int intval);
|
|||
int mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb);
|
||||
void mt7603_mac_add_txs(struct mt7603_dev *dev, void *data);
|
||||
void mt7603_mac_rx_ba_reset(struct mt7603_dev *dev, void *addr, u8 tid);
|
||||
void mt7603_mac_tx_ba_reset(struct mt7603_dev *dev, int wcid, int tid, int ssn,
|
||||
void mt7603_mac_tx_ba_reset(struct mt7603_dev *dev, int wcid, int tid,
|
||||
int ba_size);
|
||||
|
||||
void mt7603_pse_client_reset(struct mt7603_dev *dev);
|
||||
|
|
|
@ -466,7 +466,6 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev,
|
|||
return;
|
||||
|
||||
rcu_read_lock();
|
||||
mt76_tx_status_lock(mdev, &list);
|
||||
|
||||
if (stat->wcid < ARRAY_SIZE(dev->mt76.wcid))
|
||||
wcid = rcu_dereference(dev->mt76.wcid[stat->wcid]);
|
||||
|
@ -479,6 +478,8 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev,
|
|||
drv_priv);
|
||||
}
|
||||
|
||||
mt76_tx_status_lock(mdev, &list);
|
||||
|
||||
if (wcid) {
|
||||
if (stat->pktid >= MT_PACKET_ID_FIRST)
|
||||
status.skb = mt76_tx_status_skb_get(mdev, wcid,
|
||||
|
@ -498,7 +499,9 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev,
|
|||
if (*update == 0 && stat_val == stat_cache &&
|
||||
stat->wcid == msta->status.wcid && msta->n_frames < 32) {
|
||||
msta->n_frames++;
|
||||
goto out;
|
||||
mt76_tx_status_unlock(mdev, &list);
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
mt76x02_mac_fill_tx_status(dev, status.info, &msta->status,
|
||||
|
@ -514,11 +517,10 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev,
|
|||
|
||||
if (status.skb)
|
||||
mt76_tx_status_skb_done(mdev, status.skb, &list);
|
||||
else
|
||||
ieee80211_tx_status_ext(mt76_hw(dev), &status);
|
||||
|
||||
out:
|
||||
mt76_tx_status_unlock(mdev, &list);
|
||||
|
||||
if (!status.skb)
|
||||
ieee80211_tx_status_ext(mt76_hw(dev), &status);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
|
|
|
@ -673,7 +673,6 @@ enum rt2x00_state_flags {
|
|||
CONFIG_CHANNEL_HT40,
|
||||
CONFIG_POWERSAVING,
|
||||
CONFIG_HT_DISABLED,
|
||||
CONFIG_QOS_DISABLED,
|
||||
CONFIG_MONITORING,
|
||||
|
||||
/*
|
||||
|
|
|
@ -642,18 +642,8 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
|
|||
rt2x00dev->intf_associated--;
|
||||
|
||||
rt2x00leds_led_assoc(rt2x00dev, !!rt2x00dev->intf_associated);
|
||||
|
||||
clear_bit(CONFIG_QOS_DISABLED, &rt2x00dev->flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for access point which do not support 802.11e . We have to
|
||||
* generate data frames sequence number in S/W for such AP, because
|
||||
* of H/W bug.
|
||||
*/
|
||||
if (changes & BSS_CHANGED_QOS && !bss_conf->qos)
|
||||
set_bit(CONFIG_QOS_DISABLED, &rt2x00dev->flags);
|
||||
|
||||
/*
|
||||
* When the erp information has changed, we should perform
|
||||
* additional configuration steps. For all other changes we are done.
|
||||
|
|
|
@ -201,15 +201,18 @@ static void rt2x00queue_create_tx_descriptor_seq(struct rt2x00_dev *rt2x00dev,
|
|||
if (!rt2x00_has_cap_flag(rt2x00dev, REQUIRE_SW_SEQNO)) {
|
||||
/*
|
||||
* rt2800 has a H/W (or F/W) bug, device incorrectly increase
|
||||
* seqno on retransmited data (non-QOS) frames. To workaround
|
||||
* the problem let's generate seqno in software if QOS is
|
||||
* disabled.
|
||||
* seqno on retransmitted data (non-QOS) and management frames.
|
||||
* To workaround the problem let's generate seqno in software.
|
||||
* Except for beacons which are transmitted periodically by H/W
|
||||
* hence hardware has to assign seqno for them.
|
||||
*/
|
||||
if (test_bit(CONFIG_QOS_DISABLED, &rt2x00dev->flags))
|
||||
__clear_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags);
|
||||
else
|
||||
if (ieee80211_is_beacon(hdr->frame_control)) {
|
||||
__set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags);
|
||||
/* H/W will generate sequence number */
|
||||
return;
|
||||
}
|
||||
|
||||
__clear_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue