mirror of
https://github.com/torvalds/linux.git
synced 2024-11-20 11:01:38 +00:00
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next
This commit is contained in:
commit
d3d3e0017f
@ -81,7 +81,7 @@
|
||||
#define IWL8000_NVM_VERSION 0x0a1d
|
||||
#define IWL8000_TX_POWER_VERSION 0xffff /* meaningless */
|
||||
|
||||
#define IWL8000_FW_PRE "iwlwifi-8000-"
|
||||
#define IWL8000_FW_PRE "iwlwifi-8000"
|
||||
#define IWL8000_MODULE_FIRMWARE(api) IWL8000_FW_PRE __stringify(api) ".ucode"
|
||||
|
||||
#define NVM_HW_SECTION_NUM_FAMILY_8000 10
|
||||
|
@ -69,6 +69,7 @@
|
||||
#include <linux/vmalloc.h>
|
||||
|
||||
#include "iwl-drv.h"
|
||||
#include "iwl-csr.h"
|
||||
#include "iwl-debug.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-op-mode.h"
|
||||
@ -244,6 +245,23 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first)
|
||||
snprintf(drv->firmware_name, sizeof(drv->firmware_name), "%s%s.ucode",
|
||||
name_pre, tag);
|
||||
|
||||
/*
|
||||
* Starting 8000B - FW name format has changed. This overwrites the
|
||||
* previous name and uses the new format.
|
||||
*/
|
||||
if (drv->trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) {
|
||||
char rev_step[2] = {
|
||||
'A' + CSR_HW_REV_STEP(drv->trans->hw_rev), 0
|
||||
};
|
||||
|
||||
/* A-step doesn't have an indication */
|
||||
if (CSR_HW_REV_STEP(drv->trans->hw_rev) == SILICON_A_STEP)
|
||||
rev_step[0] = 0;
|
||||
|
||||
snprintf(drv->firmware_name, sizeof(drv->firmware_name),
|
||||
"%s%s-%s.ucode", name_pre, rev_step, tag);
|
||||
}
|
||||
|
||||
IWL_DEBUG_INFO(drv, "attempting to load firmware %s'%s'\n",
|
||||
(drv->fw_index == UCODE_EXPERIMENTAL_INDEX)
|
||||
? "EXPERIMENTAL " : "",
|
||||
|
@ -145,9 +145,24 @@ enum iwl_ucode_tlv_api {
|
||||
/**
|
||||
* enum iwl_ucode_tlv_capa - ucode capabilities
|
||||
* @IWL_UCODE_TLV_CAPA_D0I3_SUPPORT: supports D0i3
|
||||
* @IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT: supports insertion of current
|
||||
* tx power value into TPC Report action frame and Link Measurement Report
|
||||
* action frame
|
||||
* @IWL_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT: supports adding DS params
|
||||
* element in probe requests.
|
||||
* @IWL_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT: supports adding TPC Report IE in
|
||||
* probe requests.
|
||||
* @IWL_UCODE_TLV_CAPA_QUIET_PERIOD_SUPPORT: supports Quiet Period requests
|
||||
* @IWL_UCODE_TLV_CAPA_DQA_SUPPORT: supports dynamic queue allocation (DQA),
|
||||
* which also implies support for the scheduler configuration command
|
||||
*/
|
||||
enum iwl_ucode_tlv_capa {
|
||||
IWL_UCODE_TLV_CAPA_D0I3_SUPPORT = BIT(0),
|
||||
IWL_UCODE_TLV_CAPA_D0I3_SUPPORT = BIT(0),
|
||||
IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT = BIT(8),
|
||||
IWL_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT = BIT(9),
|
||||
IWL_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT = BIT(10),
|
||||
IWL_UCODE_TLV_CAPA_QUIET_PERIOD_SUPPORT = BIT(11),
|
||||
IWL_UCODE_TLV_CAPA_DQA_SUPPORT = BIT(12),
|
||||
};
|
||||
|
||||
/* The default calibrate table size if not specified by firmware file */
|
||||
|
@ -90,9 +90,10 @@
|
||||
#define IWL_MVM_BT_COEX_EN_RED_TXP_THRESH 62
|
||||
#define IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH 65
|
||||
#define IWL_MVM_BT_COEX_SYNC2SCO 1
|
||||
#define IWL_MVM_BT_COEX_CORUNNING 1
|
||||
#define IWL_MVM_BT_COEX_CORUNNING 0
|
||||
#define IWL_MVM_BT_COEX_MPLUT 1
|
||||
#define IWL_MVM_FW_MCAST_FILTER_PASS_ALL 0
|
||||
#define IWL_MVM_QUOTA_THRESHOLD 8
|
||||
#define IWL_MVM_RS_RSSI_BASED_INIT_RATE 0
|
||||
|
||||
#endif /* __MVM_CONSTANTS_H */
|
||||
|
@ -326,6 +326,29 @@ out:
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_nic_temp_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_mvm *mvm = file->private_data;
|
||||
char buf[16];
|
||||
int pos, temp;
|
||||
|
||||
if (!mvm->ucode_loaded)
|
||||
return -EIO;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
temp = iwl_mvm_get_temp(mvm);
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
if (temp < 0)
|
||||
return temp;
|
||||
|
||||
pos = scnprintf(buf , sizeof(buf), "%d\n", temp);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
@ -1378,6 +1401,7 @@ MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush, 16);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain, 8);
|
||||
MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram, 64);
|
||||
MVM_DEBUGFS_READ_WRITE_FILE_OPS(set_nic_temperature, 64);
|
||||
MVM_DEBUGFS_READ_FILE_OPS(nic_temp);
|
||||
MVM_DEBUGFS_READ_FILE_OPS(stations);
|
||||
MVM_DEBUGFS_READ_FILE_OPS(bt_notif);
|
||||
MVM_DEBUGFS_READ_FILE_OPS(bt_cmd);
|
||||
@ -1420,6 +1444,7 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
|
||||
MVM_DEBUGFS_ADD_FILE(sram, mvm->debugfs_dir, S_IWUSR | S_IRUSR);
|
||||
MVM_DEBUGFS_ADD_FILE(set_nic_temperature, mvm->debugfs_dir,
|
||||
S_IWUSR | S_IRUSR);
|
||||
MVM_DEBUGFS_ADD_FILE(nic_temp, dbgfs_dir, S_IRUSR);
|
||||
MVM_DEBUGFS_ADD_FILE(stations, dbgfs_dir, S_IRUSR);
|
||||
MVM_DEBUGFS_ADD_FILE(fw_error_dump, dbgfs_dir, S_IRUSR);
|
||||
MVM_DEBUGFS_ADD_FILE(bt_notif, dbgfs_dir, S_IRUSR);
|
||||
|
@ -670,6 +670,8 @@ struct iwl_scan_channel_opt {
|
||||
* @IWL_MVM_LMAC_SCAN_FLAG_ITER_COMPLETE: send iteration complete notification
|
||||
* @IWL_MVM_LMAC_SCAN_FLAG_MULTIPLE_SSIDS multiple SSID matching
|
||||
* @IWL_MVM_LMAC_SCAN_FLAG_FRAGMENTED: all passive scans will be fragmented
|
||||
* @IWL_MVM_LMAC_SCAN_FLAGS_RRM_ENABLED: insert WFA vendor-specific TPC report
|
||||
* and DS parameter set IEs into probe requests.
|
||||
*/
|
||||
enum iwl_mvm_lmac_scan_flags {
|
||||
IWL_MVM_LMAC_SCAN_FLAG_PASS_ALL = BIT(0),
|
||||
@ -678,6 +680,7 @@ enum iwl_mvm_lmac_scan_flags {
|
||||
IWL_MVM_LMAC_SCAN_FLAG_ITER_COMPLETE = BIT(3),
|
||||
IWL_MVM_LMAC_SCAN_FLAG_MULTIPLE_SSIDS = BIT(4),
|
||||
IWL_MVM_LMAC_SCAN_FLAG_FRAGMENTED = BIT(5),
|
||||
IWL_MVM_LMAC_SCAN_FLAGS_RRM_ENABLED = BIT(6),
|
||||
};
|
||||
|
||||
enum iwl_scan_priority {
|
||||
|
@ -66,6 +66,7 @@
|
||||
/**
|
||||
* enum iwl_tx_flags - bitmasks for tx_flags in TX command
|
||||
* @TX_CMD_FLG_PROT_REQUIRE: use RTS or CTS-to-self to protect the frame
|
||||
* @TX_CMD_FLG_WRITE_TX_POWER: update current tx power value in the mgmt frame
|
||||
* @TX_CMD_FLG_ACK: expect ACK from receiving station
|
||||
* @TX_CMD_FLG_STA_RATE: use RS table with initial index from the TX command.
|
||||
* Otherwise, use rate_n_flags from the TX command
|
||||
@ -97,6 +98,7 @@
|
||||
*/
|
||||
enum iwl_tx_flags {
|
||||
TX_CMD_FLG_PROT_REQUIRE = BIT(0),
|
||||
TX_CMD_FLG_WRITE_TX_POWER = BIT(1),
|
||||
TX_CMD_FLG_ACK = BIT(3),
|
||||
TX_CMD_FLG_STA_RATE = BIT(4),
|
||||
TX_CMD_FLG_BAR = BIT(6),
|
||||
|
@ -116,6 +116,9 @@ enum {
|
||||
TXPATH_FLUSH = 0x1e,
|
||||
MGMT_MCAST_KEY = 0x1f,
|
||||
|
||||
/* scheduler config */
|
||||
SCD_QUEUE_CFG = 0x1d,
|
||||
|
||||
/* global key */
|
||||
WEP_KEY = 0x20,
|
||||
|
||||
@ -1650,4 +1653,61 @@ struct iwl_dts_measurement_notif {
|
||||
__le32 voltage;
|
||||
} __packed; /* TEMPERATURE_MEASUREMENT_TRIGGER_NTFY_S */
|
||||
|
||||
/**
|
||||
* enum iwl_scd_control - scheduler config command control flags
|
||||
* @IWL_SCD_CONTROL_RM_TID: remove TID from this queue
|
||||
* @IWL_SCD_CONTROL_SET_SSN: use the SSN and program it into HW
|
||||
*/
|
||||
enum iwl_scd_control {
|
||||
IWL_SCD_CONTROL_RM_TID = BIT(4),
|
||||
IWL_SCD_CONTROL_SET_SSN = BIT(5),
|
||||
};
|
||||
|
||||
/**
|
||||
* enum iwl_scd_flags - scheduler config command flags
|
||||
* @IWL_SCD_FLAGS_SHARE_TID: multiple TIDs map to this queue
|
||||
* @IWL_SCD_FLAGS_SHARE_RA: multiple RAs map to this queue
|
||||
* @IWL_SCD_FLAGS_DQA_ENABLED: DQA is enabled
|
||||
*/
|
||||
enum iwl_scd_flags {
|
||||
IWL_SCD_FLAGS_SHARE_TID = BIT(0),
|
||||
IWL_SCD_FLAGS_SHARE_RA = BIT(1),
|
||||
IWL_SCD_FLAGS_DQA_ENABLED = BIT(2),
|
||||
};
|
||||
|
||||
#define IWL_SCDQ_INVALID_STA 0xff
|
||||
|
||||
/**
|
||||
* struct iwl_scd_txq_cfg_cmd - New txq hw scheduler config command
|
||||
* @token: dialog token addba - unused legacy
|
||||
* @sta_id: station id 4-bit
|
||||
* @tid: TID 0..7
|
||||
* @scd_queue: TFD queue num 0 .. 31
|
||||
* @enable: 1 queue enable, 0 queue disable
|
||||
* @aggregate: 1 aggregated queue, 0 otherwise
|
||||
* @tx_fifo: tx fifo num 0..7
|
||||
* @window: up to 64
|
||||
* @ssn: starting seq num 12-bit
|
||||
* @control: command control flags
|
||||
* @flags: flags - see &enum iwl_scd_flags
|
||||
*
|
||||
* Note that every time the command is sent, all parameters must
|
||||
* be filled with the exception of
|
||||
* - the SSN, which is only used with @IWL_SCD_CONTROL_SET_SSN
|
||||
* - the window, which is only relevant when starting aggregation
|
||||
*/
|
||||
struct iwl_scd_txq_cfg_cmd {
|
||||
u8 token;
|
||||
u8 sta_id;
|
||||
u8 tid;
|
||||
u8 scd_queue;
|
||||
u8 enable;
|
||||
u8 aggregate;
|
||||
u8 tx_fifo;
|
||||
u8 window;
|
||||
__le16 ssn;
|
||||
u8 control;
|
||||
u8 flags;
|
||||
} __packed;
|
||||
|
||||
#endif /* __fw_api_h__ */
|
||||
|
@ -427,17 +427,17 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_P2P_DEVICE:
|
||||
iwl_trans_ac_txq_enable(mvm->trans, IWL_MVM_OFFCHANNEL_QUEUE,
|
||||
IWL_MVM_TX_FIFO_VO);
|
||||
iwl_mvm_enable_ac_txq(mvm, IWL_MVM_OFFCHANNEL_QUEUE,
|
||||
IWL_MVM_TX_FIFO_VO);
|
||||
break;
|
||||
case NL80211_IFTYPE_AP:
|
||||
iwl_trans_ac_txq_enable(mvm->trans, vif->cab_queue,
|
||||
IWL_MVM_TX_FIFO_MCAST);
|
||||
iwl_mvm_enable_ac_txq(mvm, vif->cab_queue,
|
||||
IWL_MVM_TX_FIFO_MCAST);
|
||||
/* fall through */
|
||||
default:
|
||||
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
|
||||
iwl_trans_ac_txq_enable(mvm->trans, vif->hw_queue[ac],
|
||||
iwl_mvm_ac_to_tx_fifo[ac]);
|
||||
iwl_mvm_enable_ac_txq(mvm, vif->hw_queue[ac],
|
||||
iwl_mvm_ac_to_tx_fifo[ac]);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -452,16 +452,14 @@ void iwl_mvm_mac_ctxt_release(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_P2P_DEVICE:
|
||||
iwl_trans_txq_disable(mvm->trans, IWL_MVM_OFFCHANNEL_QUEUE,
|
||||
true);
|
||||
iwl_mvm_disable_txq(mvm, IWL_MVM_OFFCHANNEL_QUEUE);
|
||||
break;
|
||||
case NL80211_IFTYPE_AP:
|
||||
iwl_trans_txq_disable(mvm->trans, vif->cab_queue, true);
|
||||
iwl_mvm_disable_txq(mvm, vif->cab_queue);
|
||||
/* fall through */
|
||||
default:
|
||||
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
|
||||
iwl_trans_txq_disable(mvm->trans, vif->hw_queue[ac],
|
||||
true);
|
||||
iwl_mvm_disable_txq(mvm, vif->hw_queue[ac]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -279,14 +279,6 @@ static void iwl_mvm_reset_phy_ctxts(struct iwl_mvm *mvm)
|
||||
}
|
||||
}
|
||||
|
||||
static int iwl_mvm_max_scan_ie_len(struct iwl_mvm *mvm)
|
||||
{
|
||||
/* we create the 802.11 header and SSID element */
|
||||
if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID)
|
||||
return mvm->fw->ucode_capa.max_probe_length - 24 - 2;
|
||||
return mvm->fw->ucode_capa.max_probe_length - 24 - 34;
|
||||
}
|
||||
|
||||
int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
|
||||
{
|
||||
struct ieee80211_hw *hw = mvm->hw;
|
||||
@ -303,7 +295,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
|
||||
IEEE80211_HW_AMPDU_AGGREGATION |
|
||||
IEEE80211_HW_TIMING_BEACON_ONLY |
|
||||
IEEE80211_HW_CONNECTION_MONITOR |
|
||||
IEEE80211_HW_CHANCTX_STA_CSA;
|
||||
IEEE80211_HW_CHANCTX_STA_CSA |
|
||||
IEEE80211_HW_SUPPORTS_CLONED_SKBS;
|
||||
|
||||
hw->queues = mvm->first_agg_queue;
|
||||
hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE;
|
||||
@ -378,7 +371,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
|
||||
|
||||
iwl_mvm_reset_phy_ctxts(mvm);
|
||||
|
||||
hw->wiphy->max_scan_ie_len = iwl_mvm_max_scan_ie_len(mvm);
|
||||
hw->wiphy->max_scan_ie_len = iwl_mvm_max_scan_ie_len(mvm, false);
|
||||
|
||||
hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX;
|
||||
|
||||
@ -411,6 +404,22 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
|
||||
NL80211_FEATURE_DYNAMIC_SMPS |
|
||||
NL80211_FEATURE_STATIC_SMPS;
|
||||
|
||||
if (mvm->fw->ucode_capa.capa[0] &
|
||||
IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT)
|
||||
hw->wiphy->features |= NL80211_FEATURE_TX_POWER_INSERTION;
|
||||
if (mvm->fw->ucode_capa.capa[0] &
|
||||
IWL_UCODE_TLV_CAPA_QUIET_PERIOD_SUPPORT)
|
||||
hw->wiphy->features |= NL80211_FEATURE_QUIET;
|
||||
|
||||
if (mvm->fw->ucode_capa.capa[0] &
|
||||
IWL_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT)
|
||||
hw->wiphy->features |=
|
||||
NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES;
|
||||
|
||||
if (mvm->fw->ucode_capa.capa[0] &
|
||||
IWL_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT)
|
||||
hw->wiphy->features |= NL80211_FEATURE_WFA_TPC_IE_IN_PROBES;
|
||||
|
||||
mvm->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
|
||||
|
||||
/* currently FW API supports only one optional cipher scheme */
|
||||
@ -2135,7 +2144,13 @@ static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
|
||||
if (!iwl_mvm_is_idle(mvm)) {
|
||||
/* Newest FW fixes sched scan while connected on another interface */
|
||||
if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN) {
|
||||
if (!vif->bss_conf.idle) {
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
} else if (!iwl_mvm_is_idle(mvm)) {
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
@ -779,6 +779,11 @@ static inline bool iwl_mvm_is_d0i3_supported(struct iwl_mvm *mvm)
|
||||
(mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_D0I3_SUPPORT);
|
||||
}
|
||||
|
||||
static inline bool iwl_mvm_is_dqa_supported(struct iwl_mvm *mvm)
|
||||
{
|
||||
return mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_DQA_SUPPORT;
|
||||
}
|
||||
|
||||
extern const u8 iwl_mvm_ac_to_tx_fifo[];
|
||||
|
||||
struct iwl_rate_info {
|
||||
@ -930,6 +935,7 @@ int iwl_mvm_rx_scan_response(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
|
||||
int iwl_mvm_rx_scan_complete(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd);
|
||||
int iwl_mvm_cancel_scan(struct iwl_mvm *mvm);
|
||||
int iwl_mvm_max_scan_ie_len(struct iwl_mvm *mvm, bool is_sched_scan);
|
||||
|
||||
/* Scheduled scan */
|
||||
int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm,
|
||||
@ -984,6 +990,9 @@ void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_frame_stats *stats,
|
||||
u32 rate, bool agg);
|
||||
int rs_pretty_print_rate(char *buf, const u32 rate);
|
||||
void rs_update_last_rssi(struct iwl_mvm *mvm,
|
||||
struct iwl_lq_sta *lq_sta,
|
||||
struct ieee80211_rx_status *rx_status);
|
||||
|
||||
/* power management */
|
||||
int iwl_mvm_power_update_device(struct iwl_mvm *mvm);
|
||||
@ -1141,6 +1150,39 @@ static inline bool iwl_mvm_vif_low_latency(struct iwl_mvm_vif *mvmvif)
|
||||
return mvmvif->low_latency;
|
||||
}
|
||||
|
||||
/* hw scheduler queue config */
|
||||
void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, u16 ssn,
|
||||
const struct iwl_trans_txq_scd_cfg *cfg);
|
||||
void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue);
|
||||
|
||||
static inline void iwl_mvm_enable_ac_txq(struct iwl_mvm *mvm, int queue,
|
||||
u8 fifo)
|
||||
{
|
||||
struct iwl_trans_txq_scd_cfg cfg = {
|
||||
.fifo = fifo,
|
||||
.tid = IWL_MAX_TID_COUNT,
|
||||
.aggregate = false,
|
||||
.frame_limit = IWL_FRAME_LIMIT,
|
||||
};
|
||||
|
||||
iwl_mvm_enable_txq(mvm, queue, 0, &cfg);
|
||||
}
|
||||
|
||||
static inline void iwl_mvm_enable_agg_txq(struct iwl_mvm *mvm, int queue,
|
||||
int fifo, int sta_id, int tid,
|
||||
int frame_limit, u16 ssn)
|
||||
{
|
||||
struct iwl_trans_txq_scd_cfg cfg = {
|
||||
.fifo = fifo,
|
||||
.sta_id = sta_id,
|
||||
.tid = tid,
|
||||
.frame_limit = frame_limit,
|
||||
.aggregate = true,
|
||||
};
|
||||
|
||||
iwl_mvm_enable_txq(mvm, queue, ssn, &cfg);
|
||||
}
|
||||
|
||||
/* Assoc status */
|
||||
bool iwl_mvm_is_idle(struct iwl_mvm *mvm);
|
||||
|
||||
@ -1150,6 +1192,7 @@ void iwl_mvm_tt_handler(struct iwl_mvm *mvm);
|
||||
void iwl_mvm_tt_initialize(struct iwl_mvm *mvm, u32 min_backoff);
|
||||
void iwl_mvm_tt_exit(struct iwl_mvm *mvm);
|
||||
void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state);
|
||||
int iwl_mvm_get_temp(struct iwl_mvm *mvm);
|
||||
|
||||
/* smart fifo */
|
||||
int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
|
@ -342,6 +342,7 @@ static const char *const iwl_mvm_cmd_strings[REPLY_MAX] = {
|
||||
CMD(BT_COEX_UPDATE_REDUCED_TXP),
|
||||
CMD(PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION),
|
||||
CMD(ANTENNA_COUPLING_NOTIFICATION),
|
||||
CMD(SCD_QUEUE_CFG),
|
||||
};
|
||||
#undef CMD
|
||||
|
||||
@ -421,7 +422,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
mvm->first_agg_queue = 12;
|
||||
}
|
||||
mvm->sf_state = SF_UNINIT;
|
||||
mvm->low_latency_agg_frame_limit = 1;
|
||||
mvm->low_latency_agg_frame_limit = 6;
|
||||
|
||||
mutex_init(&mvm->mutex);
|
||||
mutex_init(&mvm->d0i3_suspend_mutex);
|
||||
|
@ -377,9 +377,9 @@ static int iwl_hwrate_to_plcp_idx(u32 rate_n_flags)
|
||||
}
|
||||
|
||||
static void rs_rate_scale_perform(struct iwl_mvm *mvm,
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_sta *sta,
|
||||
struct iwl_lq_sta *lq_sta);
|
||||
struct ieee80211_sta *sta,
|
||||
struct iwl_lq_sta *lq_sta,
|
||||
int tid);
|
||||
static void rs_fill_lq_cmd(struct iwl_mvm *mvm,
|
||||
struct ieee80211_sta *sta,
|
||||
struct iwl_lq_sta *lq_sta,
|
||||
@ -1007,27 +1007,35 @@ static u32 rs_ch_width_from_mac_flags(enum mac80211_rate_control_flags flags)
|
||||
return RATE_MCS_CHAN_WIDTH_20;
|
||||
}
|
||||
|
||||
/*
|
||||
* mac80211 sends us Tx status
|
||||
*/
|
||||
static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband,
|
||||
struct ieee80211_sta *sta, void *priv_sta,
|
||||
struct sk_buff *skb)
|
||||
static u8 rs_get_tid(struct ieee80211_hdr *hdr)
|
||||
{
|
||||
u8 tid = IWL_MAX_TID_COUNT;
|
||||
|
||||
if (ieee80211_is_data_qos(hdr->frame_control)) {
|
||||
u8 *qc = ieee80211_get_qos_ctl(hdr);
|
||||
tid = qc[0] & 0xf;
|
||||
}
|
||||
|
||||
if (unlikely(tid > IWL_MAX_TID_COUNT))
|
||||
tid = IWL_MAX_TID_COUNT;
|
||||
|
||||
return tid;
|
||||
}
|
||||
|
||||
void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
||||
int tid, struct ieee80211_tx_info *info)
|
||||
{
|
||||
int legacy_success;
|
||||
int retries;
|
||||
int mac_index, i;
|
||||
struct iwl_lq_sta *lq_sta = priv_sta;
|
||||
struct iwl_lq_cmd *table;
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
struct iwl_op_mode *op_mode = (struct iwl_op_mode *)mvm_r;
|
||||
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
enum mac80211_rate_control_flags mac_flags;
|
||||
u32 ucode_rate;
|
||||
struct rs_rate rate;
|
||||
struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl;
|
||||
u8 reduced_txp = (uintptr_t)info->status.status_driver_data[0];
|
||||
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
struct iwl_lq_sta *lq_sta = &mvmsta->lq_sta;
|
||||
|
||||
/* Treat uninitialized rate scaling data same as non-existing. */
|
||||
if (!lq_sta) {
|
||||
@ -1045,10 +1053,6 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband,
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (!ieee80211_is_data(hdr->frame_control) ||
|
||||
info->flags & IEEE80211_TX_CTL_NO_ACK)
|
||||
return;
|
||||
|
||||
/* This packet was aggregated but doesn't carry status info */
|
||||
if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
|
||||
!(info->flags & IEEE80211_TX_STAT_AMPDU))
|
||||
@ -1094,7 +1098,7 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband,
|
||||
for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++)
|
||||
ieee80211_stop_tx_ba_session(sta, tid);
|
||||
|
||||
iwl_mvm_rs_rate_init(mvm, sta, sband->band, false);
|
||||
iwl_mvm_rs_rate_init(mvm, sta, info->band, false);
|
||||
return;
|
||||
}
|
||||
lq_sta->last_tx = jiffies;
|
||||
@ -1221,8 +1225,28 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband,
|
||||
IWL_DEBUG_RATE(mvm, "reduced txpower: %d\n", reduced_txp);
|
||||
done:
|
||||
/* See if there's a better rate or modulation mode to try. */
|
||||
if (sta && sta->supp_rates[sband->band])
|
||||
rs_rate_scale_perform(mvm, skb, sta, lq_sta);
|
||||
if (sta && sta->supp_rates[info->band])
|
||||
rs_rate_scale_perform(mvm, sta, lq_sta, tid);
|
||||
}
|
||||
|
||||
/*
|
||||
* mac80211 sends us Tx status
|
||||
*/
|
||||
static void rs_mac80211_tx_status(void *mvm_r,
|
||||
struct ieee80211_supported_band *sband,
|
||||
struct ieee80211_sta *sta, void *priv_sta,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
struct iwl_op_mode *op_mode = (struct iwl_op_mode *)mvm_r;
|
||||
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
if (!ieee80211_is_data(hdr->frame_control) ||
|
||||
info->flags & IEEE80211_TX_CTL_NO_ACK)
|
||||
return;
|
||||
|
||||
iwl_mvm_rs_tx_status(mvm, sta, rs_get_tid(hdr), info);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1493,22 +1517,6 @@ static void rs_update_rate_tbl(struct iwl_mvm *mvm,
|
||||
iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, false);
|
||||
}
|
||||
|
||||
static u8 rs_get_tid(struct iwl_lq_sta *lq_data,
|
||||
struct ieee80211_hdr *hdr)
|
||||
{
|
||||
u8 tid = IWL_MAX_TID_COUNT;
|
||||
|
||||
if (ieee80211_is_data_qos(hdr->frame_control)) {
|
||||
u8 *qc = ieee80211_get_qos_ctl(hdr);
|
||||
tid = qc[0] & 0xf;
|
||||
}
|
||||
|
||||
if (unlikely(tid > IWL_MAX_TID_COUNT))
|
||||
tid = IWL_MAX_TID_COUNT;
|
||||
|
||||
return tid;
|
||||
}
|
||||
|
||||
static enum rs_column rs_get_next_column(struct iwl_mvm *mvm,
|
||||
struct iwl_lq_sta *lq_sta,
|
||||
struct ieee80211_sta *sta,
|
||||
@ -1947,12 +1955,10 @@ static bool rs_tpc_perform(struct iwl_mvm *mvm,
|
||||
* Do rate scaling and search for new modulation mode.
|
||||
*/
|
||||
static void rs_rate_scale_perform(struct iwl_mvm *mvm,
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_sta *sta,
|
||||
struct iwl_lq_sta *lq_sta)
|
||||
struct iwl_lq_sta *lq_sta,
|
||||
int tid)
|
||||
{
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
int low = IWL_RATE_INVALID;
|
||||
int high = IWL_RATE_INVALID;
|
||||
int index;
|
||||
@ -1969,29 +1975,12 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
|
||||
u8 done_search = 0;
|
||||
u16 high_low;
|
||||
s32 sr;
|
||||
u8 tid = IWL_MAX_TID_COUNT;
|
||||
u8 prev_agg = lq_sta->is_agg;
|
||||
struct iwl_mvm_sta *sta_priv = (void *)sta->drv_priv;
|
||||
struct iwl_mvm_tid_data *tid_data;
|
||||
struct rs_rate *rate;
|
||||
|
||||
/* Send management frames and NO_ACK data using lowest rate. */
|
||||
/* TODO: this could probably be improved.. */
|
||||
if (!ieee80211_is_data(hdr->frame_control) ||
|
||||
info->flags & IEEE80211_TX_CTL_NO_ACK)
|
||||
return;
|
||||
|
||||
tid = rs_get_tid(lq_sta, hdr);
|
||||
if ((tid != IWL_MAX_TID_COUNT) &&
|
||||
(lq_sta->tx_agg_tid_en & (1 << tid))) {
|
||||
tid_data = &sta_priv->tid_data[tid];
|
||||
if (tid_data->state == IWL_AGG_OFF)
|
||||
lq_sta->is_agg = 0;
|
||||
else
|
||||
lq_sta->is_agg = 1;
|
||||
} else {
|
||||
lq_sta->is_agg = 0;
|
||||
}
|
||||
lq_sta->is_agg = !!sta_priv->agg_tids;
|
||||
|
||||
/*
|
||||
* Select rate-scale / modulation-mode table to work with in
|
||||
@ -2288,6 +2277,110 @@ out:
|
||||
lq_sta->last_txrate_idx = index;
|
||||
}
|
||||
|
||||
struct rs_init_rate_info {
|
||||
s8 rssi;
|
||||
u8 rate_idx;
|
||||
};
|
||||
|
||||
static const struct rs_init_rate_info rs_init_rates_24ghz[] = {
|
||||
{ -60, IWL_RATE_54M_INDEX },
|
||||
{ -64, IWL_RATE_48M_INDEX },
|
||||
{ -68, IWL_RATE_36M_INDEX },
|
||||
{ -80, IWL_RATE_24M_INDEX },
|
||||
{ -84, IWL_RATE_18M_INDEX },
|
||||
{ -85, IWL_RATE_12M_INDEX },
|
||||
{ -86, IWL_RATE_11M_INDEX },
|
||||
{ -88, IWL_RATE_5M_INDEX },
|
||||
{ -90, IWL_RATE_2M_INDEX },
|
||||
{ S8_MIN, IWL_RATE_1M_INDEX },
|
||||
};
|
||||
|
||||
static const struct rs_init_rate_info rs_init_rates_5ghz[] = {
|
||||
{ -60, IWL_RATE_54M_INDEX },
|
||||
{ -64, IWL_RATE_48M_INDEX },
|
||||
{ -72, IWL_RATE_36M_INDEX },
|
||||
{ -80, IWL_RATE_24M_INDEX },
|
||||
{ -84, IWL_RATE_18M_INDEX },
|
||||
{ -85, IWL_RATE_12M_INDEX },
|
||||
{ -87, IWL_RATE_9M_INDEX },
|
||||
{ S8_MIN, IWL_RATE_6M_INDEX },
|
||||
};
|
||||
|
||||
/* Choose an initial legacy rate and antenna to use based on the RSSI
|
||||
* of last Rx
|
||||
*/
|
||||
static void rs_get_initial_rate(struct iwl_mvm *mvm,
|
||||
struct iwl_lq_sta *lq_sta,
|
||||
enum ieee80211_band band,
|
||||
struct rs_rate *rate)
|
||||
{
|
||||
int i, nentries;
|
||||
s8 best_rssi = S8_MIN;
|
||||
u8 best_ant = ANT_NONE;
|
||||
u8 valid_tx_ant = mvm->fw->valid_tx_ant;
|
||||
const struct rs_init_rate_info *initial_rates;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(lq_sta->pers.chain_signal); i++) {
|
||||
if (!(lq_sta->pers.chains & BIT(i)))
|
||||
continue;
|
||||
|
||||
if (lq_sta->pers.chain_signal[i] > best_rssi) {
|
||||
best_rssi = lq_sta->pers.chain_signal[i];
|
||||
best_ant = BIT(i);
|
||||
}
|
||||
}
|
||||
|
||||
IWL_DEBUG_RATE(mvm, "Best ANT: %s Best RSSI: %d\n",
|
||||
rs_pretty_ant(best_ant), best_rssi);
|
||||
|
||||
if (best_ant != ANT_A && best_ant != ANT_B)
|
||||
rate->ant = first_antenna(valid_tx_ant);
|
||||
else
|
||||
rate->ant = best_ant;
|
||||
|
||||
rate->sgi = false;
|
||||
rate->ldpc = false;
|
||||
rate->bw = RATE_MCS_CHAN_WIDTH_20;
|
||||
|
||||
rate->index = find_first_bit(&lq_sta->active_legacy_rate,
|
||||
BITS_PER_LONG);
|
||||
|
||||
if (band == IEEE80211_BAND_5GHZ) {
|
||||
rate->type = LQ_LEGACY_A;
|
||||
initial_rates = rs_init_rates_5ghz;
|
||||
nentries = ARRAY_SIZE(rs_init_rates_5ghz);
|
||||
} else {
|
||||
rate->type = LQ_LEGACY_G;
|
||||
initial_rates = rs_init_rates_24ghz;
|
||||
nentries = ARRAY_SIZE(rs_init_rates_24ghz);
|
||||
}
|
||||
|
||||
if (IWL_MVM_RS_RSSI_BASED_INIT_RATE) {
|
||||
for (i = 0; i < nentries; i++) {
|
||||
int rate_idx = initial_rates[i].rate_idx;
|
||||
if ((best_rssi >= initial_rates[i].rssi) &&
|
||||
(BIT(rate_idx) & lq_sta->active_legacy_rate)) {
|
||||
rate->index = rate_idx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IWL_DEBUG_RATE(mvm, "rate_idx %d ANT %s\n", rate->index,
|
||||
rs_pretty_ant(rate->ant));
|
||||
}
|
||||
|
||||
/* Save info about RSSI of last Rx */
|
||||
void rs_update_last_rssi(struct iwl_mvm *mvm,
|
||||
struct iwl_lq_sta *lq_sta,
|
||||
struct ieee80211_rx_status *rx_status)
|
||||
{
|
||||
lq_sta->pers.chains = rx_status->chains;
|
||||
lq_sta->pers.chain_signal[0] = rx_status->chain_signal[0];
|
||||
lq_sta->pers.chain_signal[1] = rx_status->chain_signal[1];
|
||||
lq_sta->pers.chain_signal[2] = rx_status->chain_signal[2];
|
||||
}
|
||||
|
||||
/**
|
||||
* rs_initialize_lq - Initialize a station's hardware rate table
|
||||
*
|
||||
@ -2310,17 +2403,11 @@ static void rs_initialize_lq(struct iwl_mvm *mvm,
|
||||
{
|
||||
struct iwl_scale_tbl_info *tbl;
|
||||
struct rs_rate *rate;
|
||||
int i;
|
||||
u8 active_tbl = 0;
|
||||
u8 valid_tx_ant;
|
||||
|
||||
if (!sta || !lq_sta)
|
||||
return;
|
||||
|
||||
i = lq_sta->last_txrate_idx;
|
||||
|
||||
valid_tx_ant = mvm->fw->valid_tx_ant;
|
||||
|
||||
if (!lq_sta->search_better_tbl)
|
||||
active_tbl = lq_sta->active_tbl;
|
||||
else
|
||||
@ -2329,18 +2416,8 @@ static void rs_initialize_lq(struct iwl_mvm *mvm,
|
||||
tbl = &(lq_sta->lq_info[active_tbl]);
|
||||
rate = &tbl->rate;
|
||||
|
||||
if ((i < 0) || (i >= IWL_RATE_COUNT))
|
||||
i = 0;
|
||||
|
||||
rate->index = i;
|
||||
rate->ant = first_antenna(valid_tx_ant);
|
||||
rate->sgi = false;
|
||||
rate->ldpc = false;
|
||||
rate->bw = RATE_MCS_CHAN_WIDTH_20;
|
||||
if (band == IEEE80211_BAND_5GHZ)
|
||||
rate->type = LQ_LEGACY_A;
|
||||
else
|
||||
rate->type = LQ_LEGACY_G;
|
||||
rs_get_initial_rate(mvm, lq_sta, band, rate);
|
||||
lq_sta->last_txrate_idx = rate->index;
|
||||
|
||||
WARN_ON_ONCE(rate->ant != ANT_A && rate->ant != ANT_B);
|
||||
if (rate->ant == ANT_A)
|
||||
@ -2397,6 +2474,8 @@ static void *rs_alloc_sta(void *mvm_rate, struct ieee80211_sta *sta,
|
||||
lq_sta->pers.dbg_fixed_rate = 0;
|
||||
lq_sta->pers.dbg_fixed_txp_reduction = TPC_INVALID;
|
||||
#endif
|
||||
lq_sta->pers.chains = 0;
|
||||
memset(lq_sta->pers.chain_signal, 0, sizeof(lq_sta->pers.chain_signal));
|
||||
|
||||
return &sta_priv->lq_sta;
|
||||
}
|
||||
@ -2630,11 +2709,6 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
||||
|
||||
/* as default allow aggregation for all tids */
|
||||
lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID;
|
||||
|
||||
/* Set last_txrate_idx to lowest rate */
|
||||
lq_sta->last_txrate_idx = rate_lowest_index(sband, sta);
|
||||
if (sband->band == IEEE80211_BAND_5GHZ)
|
||||
lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
|
||||
lq_sta->is_agg = 0;
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
iwl_mvm_reset_frame_stats(mvm, &mvm->drv_rx_stats);
|
||||
@ -3238,7 +3312,7 @@ static void rs_rate_init_stub(void *mvm_r,
|
||||
|
||||
static const struct rate_control_ops rs_mvm_ops = {
|
||||
.name = RS_NAME,
|
||||
.tx_status = rs_tx_status,
|
||||
.tx_status = rs_mac80211_tx_status,
|
||||
.get_rate = rs_get_rate,
|
||||
.rate_init = rs_rate_init_stub,
|
||||
.alloc = rs_alloc,
|
||||
|
@ -376,6 +376,10 @@ struct iwl_lq_sta {
|
||||
void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
||||
enum ieee80211_band band, bool init);
|
||||
|
||||
/* Notify RS about Tx status */
|
||||
void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
||||
int tid, struct ieee80211_tx_info *info);
|
||||
|
||||
/**
|
||||
* iwl_rate_control_register - Register the rate control algorithm callbacks
|
||||
*
|
||||
|
@ -246,6 +246,7 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_rx_phy_info *phy_info;
|
||||
struct iwl_rx_mpdu_res_start *rx_res;
|
||||
struct ieee80211_sta *sta;
|
||||
u32 len;
|
||||
u32 ampdu_status;
|
||||
u32 rate_n_flags;
|
||||
@ -260,23 +261,6 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
|
||||
|
||||
memset(&rx_status, 0, sizeof(rx_status));
|
||||
|
||||
/*
|
||||
* We have tx blocked stations (with CS bit). If we heard frames from
|
||||
* a blocked station on a new channel we can TX to it again.
|
||||
*/
|
||||
if (unlikely(mvm->csa_tx_block_bcn_timeout)) {
|
||||
struct ieee80211_sta *sta;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
sta = ieee80211_find_sta(
|
||||
rcu_dereference(mvm->csa_tx_blocked_vif), hdr->addr2);
|
||||
if (sta)
|
||||
iwl_mvm_sta_modify_disable_tx_ap(mvm, sta, false);
|
||||
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
/*
|
||||
* drop the packet if it has failed being decrypted by HW
|
||||
*/
|
||||
@ -325,6 +309,29 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
|
||||
IWL_DEBUG_STATS_LIMIT(mvm, "Rssi %d, TSF %llu\n", rx_status.signal,
|
||||
(unsigned long long)rx_status.mactime);
|
||||
|
||||
rcu_read_lock();
|
||||
/*
|
||||
* We have tx blocked stations (with CS bit). If we heard frames from
|
||||
* a blocked station on a new channel we can TX to it again.
|
||||
*/
|
||||
if (unlikely(mvm->csa_tx_block_bcn_timeout)) {
|
||||
sta = ieee80211_find_sta(
|
||||
rcu_dereference(mvm->csa_tx_blocked_vif), hdr->addr2);
|
||||
if (sta)
|
||||
iwl_mvm_sta_modify_disable_tx_ap(mvm, sta, false);
|
||||
}
|
||||
|
||||
/* This is fine since we don't support multiple AP interfaces */
|
||||
sta = ieee80211_find_sta_by_ifaddr(mvm->hw, hdr->addr2, NULL);
|
||||
if (sta) {
|
||||
struct iwl_mvm_sta *mvmsta;
|
||||
mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
rs_update_last_rssi(mvm, &mvmsta->lq_sta,
|
||||
&rx_status);
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
/* set the preamble flag if appropriate */
|
||||
if (phy_info->phy_flags & cpu_to_le16(RX_RES_PHY_FLAGS_SHORT_PREAMBLE))
|
||||
rx_status.flag |= RX_FLAG_SHORTPRE;
|
||||
|
@ -339,6 +339,55 @@ not_bound:
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool iwl_mvm_rrm_scan_needed(struct iwl_mvm *mvm)
|
||||
{
|
||||
/* require rrm scan whenever the fw supports it */
|
||||
return mvm->fw->ucode_capa.capa[0] &
|
||||
IWL_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT;
|
||||
}
|
||||
|
||||
static int iwl_mvm_max_scan_ie_fw_cmd_room(struct iwl_mvm *mvm,
|
||||
bool is_sched_scan)
|
||||
{
|
||||
int max_probe_len;
|
||||
|
||||
if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)
|
||||
max_probe_len = SCAN_OFFLOAD_PROBE_REQ_SIZE;
|
||||
else
|
||||
max_probe_len = mvm->fw->ucode_capa.max_probe_length;
|
||||
|
||||
/* we create the 802.11 header and SSID element */
|
||||
max_probe_len -= 24 + 2;
|
||||
|
||||
/* basic ssid is added only for hw_scan with and old api */
|
||||
if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID) &&
|
||||
!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN) &&
|
||||
!is_sched_scan)
|
||||
max_probe_len -= 32;
|
||||
|
||||
return max_probe_len;
|
||||
}
|
||||
|
||||
int iwl_mvm_max_scan_ie_len(struct iwl_mvm *mvm, bool is_sched_scan)
|
||||
{
|
||||
int max_ie_len = iwl_mvm_max_scan_ie_fw_cmd_room(mvm, is_sched_scan);
|
||||
|
||||
if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN))
|
||||
return max_ie_len;
|
||||
|
||||
/* TODO: [BUG] This function should return the maximum allowed size of
|
||||
* scan IEs, however the LMAC scan api contains both 2GHZ and 5GHZ IEs
|
||||
* in the same command. So the correct implementation of this function
|
||||
* is just iwl_mvm_max_scan_ie_fw_cmd_room() / 2. Currently the scan
|
||||
* command has only 512 bytes and it would leave us with about 240
|
||||
* bytes for scan IEs, which is clearly not enough. So meanwhile
|
||||
* we will report an incorrect value. This may result in a failure to
|
||||
* issue a scan in unified_scan_lmac and unified_sched_scan_lmac
|
||||
* functions with -ENOBUFS, if a large enough probe will be provided.
|
||||
*/
|
||||
return max_ie_len;
|
||||
}
|
||||
|
||||
int iwl_mvm_scan_request(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_scan_request *req)
|
||||
@ -1153,6 +1202,10 @@ iwl_mvm_build_generic_unified_scan_cmd(struct iwl_mvm *mvm,
|
||||
IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE |
|
||||
IWL_SCAN_CHANNEL_FLAG_CACHE_ADD);
|
||||
}
|
||||
|
||||
if (iwl_mvm_rrm_scan_needed(mvm))
|
||||
cmd->scan_flags |=
|
||||
cpu_to_le32(IWL_MVM_LMAC_SCAN_FLAGS_RRM_ENABLED);
|
||||
}
|
||||
|
||||
int iwl_mvm_unified_scan_lmac(struct iwl_mvm *mvm,
|
||||
@ -1180,13 +1233,12 @@ int iwl_mvm_unified_scan_lmac(struct iwl_mvm *mvm,
|
||||
if (WARN_ON(mvm->scan_cmd == NULL))
|
||||
return -ENOMEM;
|
||||
|
||||
if (WARN_ON_ONCE(req->req.n_ssids > PROBE_OPTION_MAX ||
|
||||
req->ies.common_ie_len + req->ies.len[0] +
|
||||
req->ies.len[1] + 24 + 2 >
|
||||
SCAN_OFFLOAD_PROBE_REQ_SIZE ||
|
||||
req->req.n_channels >
|
||||
mvm->fw->ucode_capa.n_scan_channels))
|
||||
return -1;
|
||||
if (req->req.n_ssids > PROBE_OPTION_MAX ||
|
||||
req->ies.common_ie_len + req->ies.len[NL80211_BAND_2GHZ] +
|
||||
req->ies.len[NL80211_BAND_5GHZ] >
|
||||
iwl_mvm_max_scan_ie_fw_cmd_room(mvm, false) ||
|
||||
req->req.n_channels > mvm->fw->ucode_capa.n_scan_channels)
|
||||
return -ENOBUFS;
|
||||
|
||||
mvm->scan_status = IWL_MVM_SCAN_OS;
|
||||
|
||||
@ -1208,7 +1260,7 @@ int iwl_mvm_unified_scan_lmac(struct iwl_mvm *mvm,
|
||||
if (req->req.n_ssids == 0)
|
||||
flags |= IWL_MVM_LMAC_SCAN_FLAG_PASSIVE;
|
||||
|
||||
cmd->scan_flags = cpu_to_le32(flags);
|
||||
cmd->scan_flags |= cpu_to_le32(flags);
|
||||
|
||||
cmd->flags = iwl_mvm_scan_rxon_flags(req->req.channels[0]->band);
|
||||
cmd->filter_flags = cpu_to_le32(MAC_FILTER_ACCEPT_GRP |
|
||||
@ -1274,10 +1326,11 @@ int iwl_mvm_unified_sched_scan_lmac(struct iwl_mvm *mvm,
|
||||
if (WARN_ON(mvm->scan_cmd == NULL))
|
||||
return -ENOMEM;
|
||||
|
||||
if (WARN_ON_ONCE(req->n_ssids > PROBE_OPTION_MAX ||
|
||||
ies->common_ie_len + ies->len[0] + ies->len[1] + 24 + 2
|
||||
> SCAN_OFFLOAD_PROBE_REQ_SIZE ||
|
||||
req->n_channels > mvm->fw->ucode_capa.n_scan_channels))
|
||||
if (req->n_ssids > PROBE_OPTION_MAX ||
|
||||
ies->common_ie_len + ies->len[NL80211_BAND_2GHZ] +
|
||||
ies->len[NL80211_BAND_5GHZ] >
|
||||
iwl_mvm_max_scan_ie_fw_cmd_room(mvm, true) ||
|
||||
req->n_channels > mvm->fw->ucode_capa.n_scan_channels)
|
||||
return -ENOBUFS;
|
||||
|
||||
iwl_mvm_scan_calc_params(mvm, vif, req->n_ssids, 0, ¶ms);
|
||||
@ -1305,7 +1358,7 @@ int iwl_mvm_unified_sched_scan_lmac(struct iwl_mvm *mvm,
|
||||
if (req->n_ssids == 0)
|
||||
flags |= IWL_MVM_LMAC_SCAN_FLAG_PASSIVE;
|
||||
|
||||
cmd->scan_flags = cpu_to_le32(flags);
|
||||
cmd->scan_flags |= cpu_to_le32(flags);
|
||||
|
||||
cmd->flags = iwl_mvm_scan_rxon_flags(req->channels[0]->band);
|
||||
cmd->filter_flags = cpu_to_le32(MAC_FILTER_ACCEPT_GRP |
|
||||
|
@ -247,6 +247,7 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
|
||||
memset(&mvm_sta->tid_data[i], 0, sizeof(mvm_sta->tid_data[i]));
|
||||
mvm_sta->tid_data[i].seq_number = seq;
|
||||
}
|
||||
mvm_sta->agg_tids = 0;
|
||||
|
||||
ret = iwl_mvm_sta_send_to_fw(mvm, sta, false);
|
||||
if (ret)
|
||||
@ -535,8 +536,8 @@ int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm)
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
/* Map Aux queue to fifo - needs to happen before adding Aux station */
|
||||
iwl_trans_ac_txq_enable(mvm->trans, mvm->aux_queue,
|
||||
IWL_MVM_TX_FIFO_MCAST);
|
||||
iwl_mvm_enable_ac_txq(mvm, mvm->aux_queue,
|
||||
IWL_MVM_TX_FIFO_MCAST);
|
||||
|
||||
/* Allocate aux station and assign to it the aux queue */
|
||||
ret = iwl_mvm_allocate_int_sta(mvm, &mvm->aux_sta, BIT(mvm->aux_queue),
|
||||
@ -872,12 +873,16 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
int queue, fifo, ret;
|
||||
u16 ssn;
|
||||
|
||||
BUILD_BUG_ON((sizeof(mvmsta->agg_tids) * BITS_PER_BYTE)
|
||||
!= IWL_MAX_TID_COUNT);
|
||||
|
||||
buf_size = min_t(int, buf_size, LINK_QUAL_AGG_FRAME_LIMIT_DEF);
|
||||
|
||||
spin_lock_bh(&mvmsta->lock);
|
||||
ssn = tid_data->ssn;
|
||||
queue = tid_data->txq_id;
|
||||
tid_data->state = IWL_AGG_ON;
|
||||
mvmsta->agg_tids |= BIT(tid);
|
||||
tid_data->ssn = 0xffff;
|
||||
spin_unlock_bh(&mvmsta->lock);
|
||||
|
||||
@ -887,8 +892,8 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
if (ret)
|
||||
return -EIO;
|
||||
|
||||
iwl_trans_txq_enable(mvm->trans, queue, fifo, mvmsta->sta_id, tid,
|
||||
buf_size, ssn);
|
||||
iwl_mvm_enable_agg_txq(mvm, queue, fifo, mvmsta->sta_id, tid,
|
||||
buf_size, ssn);
|
||||
|
||||
/*
|
||||
* Even though in theory the peer could have different
|
||||
@ -932,6 +937,8 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
IWL_DEBUG_TX_QUEUES(mvm, "Stop AGG: sta %d tid %d q %d state %d\n",
|
||||
mvmsta->sta_id, tid, txq_id, tid_data->state);
|
||||
|
||||
mvmsta->agg_tids &= ~BIT(tid);
|
||||
|
||||
switch (tid_data->state) {
|
||||
case IWL_AGG_ON:
|
||||
tid_data->ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number);
|
||||
@ -956,7 +963,7 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
|
||||
iwl_mvm_sta_tx_agg(mvm, sta, tid, txq_id, false);
|
||||
|
||||
iwl_trans_txq_disable(mvm->trans, txq_id, true);
|
||||
iwl_mvm_disable_txq(mvm, txq_id);
|
||||
return 0;
|
||||
case IWL_AGG_STARTING:
|
||||
case IWL_EMPTYING_HW_QUEUE_ADDBA:
|
||||
@ -1005,6 +1012,7 @@ int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
mvmsta->sta_id, tid, txq_id, tid_data->state);
|
||||
old_state = tid_data->state;
|
||||
tid_data->state = IWL_AGG_OFF;
|
||||
mvmsta->agg_tids &= ~BIT(tid);
|
||||
spin_unlock_bh(&mvmsta->lock);
|
||||
|
||||
if (old_state >= IWL_AGG_ON) {
|
||||
@ -1013,7 +1021,7 @@ int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
|
||||
iwl_mvm_sta_tx_agg(mvm, sta, tid, txq_id, false);
|
||||
|
||||
iwl_trans_txq_disable(mvm->trans, tid_data->txq_id, true);
|
||||
iwl_mvm_disable_txq(mvm, tid_data->txq_id);
|
||||
}
|
||||
|
||||
mvm->queue_to_mac80211[tid_data->txq_id] =
|
||||
|
@ -299,6 +299,7 @@ static inline u16 iwl_mvm_tid_queued(struct iwl_mvm_tid_data *tid_data)
|
||||
* @tx_protection: reference counter for controlling the Tx protection.
|
||||
* @tt_tx_protection: is thermal throttling enable Tx protection?
|
||||
* @disable_tx: is tx to this STA disabled?
|
||||
* @agg_tids: bitmap of tids whose status is operational aggregated (IWL_AGG_ON)
|
||||
*
|
||||
* When mac80211 creates a station it reserves some space (hw->sta_data_size)
|
||||
* in the structure for use by driver. This structure is placed in that
|
||||
@ -323,6 +324,7 @@ struct iwl_mvm_sta {
|
||||
bool tt_tx_protection;
|
||||
|
||||
bool disable_tx;
|
||||
u8 agg_tids;
|
||||
};
|
||||
|
||||
static inline struct iwl_mvm_sta *
|
||||
|
@ -135,7 +135,7 @@ static int iwl_mvm_get_temp_cmd(struct iwl_mvm *mvm)
|
||||
sizeof(cmd), &cmd);
|
||||
}
|
||||
|
||||
static int iwl_mvm_get_temp(struct iwl_mvm *mvm)
|
||||
int iwl_mvm_get_temp(struct iwl_mvm *mvm)
|
||||
{
|
||||
struct iwl_notification_wait wait_temp_notif;
|
||||
static const u8 temp_notif[] = { DTS_MEASUREMENT_NOTIFICATION };
|
||||
|
@ -133,6 +133,11 @@ static void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
|
||||
!is_multicast_ether_addr(ieee80211_get_DA(hdr)))
|
||||
tx_flags |= TX_CMD_FLG_PROT_REQUIRE;
|
||||
|
||||
if ((mvm->fw->ucode_capa.capa[0] &
|
||||
IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT) &&
|
||||
ieee80211_action_contains_tpc(skb))
|
||||
tx_flags |= TX_CMD_FLG_WRITE_TX_POWER;
|
||||
|
||||
tx_cmd->tx_flags = cpu_to_le32(tx_flags);
|
||||
/* Total # bytes to be transmitted */
|
||||
tx_cmd->len = cpu_to_le16((u16)skb->len);
|
||||
@ -488,11 +493,11 @@ static void iwl_mvm_check_ratid_empty(struct iwl_mvm *mvm,
|
||||
IWL_DEBUG_TX_QUEUES(mvm,
|
||||
"Can continue DELBA flow ssn = next_recl = %d\n",
|
||||
tid_data->next_reclaimed);
|
||||
iwl_trans_txq_disable(mvm->trans, tid_data->txq_id, true);
|
||||
iwl_mvm_disable_txq(mvm, tid_data->txq_id);
|
||||
tid_data->state = IWL_AGG_OFF;
|
||||
/*
|
||||
* we can't hold the mutex - but since we are after a sequence
|
||||
* point (call to iwl_trans_txq_disable), so we don't even need
|
||||
* point (call to iwl_mvm_disable_txq(), so we don't even need
|
||||
* a memory barrier.
|
||||
*/
|
||||
mvm->queue_to_mac80211[tid_data->txq_id] =
|
||||
@ -868,6 +873,19 @@ int iwl_mvm_rx_tx_cmd(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iwl_mvm_tx_info_from_ba_notif(struct ieee80211_tx_info *info,
|
||||
struct iwl_mvm_ba_notif *ba_notif,
|
||||
struct iwl_mvm_tid_data *tid_data)
|
||||
{
|
||||
info->flags |= IEEE80211_TX_STAT_AMPDU;
|
||||
info->status.ampdu_ack_len = ba_notif->txed_2_done;
|
||||
info->status.ampdu_len = ba_notif->txed;
|
||||
iwl_mvm_hwrate_to_tx_status(tid_data->rate_n_flags,
|
||||
info);
|
||||
info->status.status_driver_data[0] =
|
||||
(void *)(uintptr_t)tid_data->reduced_tpc;
|
||||
}
|
||||
|
||||
int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
@ -954,21 +972,37 @@ int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
|
||||
*/
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
|
||||
if (freed == 1) {
|
||||
/* this is the first skb we deliver in this batch */
|
||||
/* put the rate scaling data there */
|
||||
info->flags |= IEEE80211_TX_STAT_AMPDU;
|
||||
info->status.ampdu_ack_len = ba_notif->txed_2_done;
|
||||
info->status.ampdu_len = ba_notif->txed;
|
||||
iwl_mvm_hwrate_to_tx_status(tid_data->rate_n_flags,
|
||||
info);
|
||||
info->status.status_driver_data[0] =
|
||||
(void *)(uintptr_t)tid_data->reduced_tpc;
|
||||
}
|
||||
/* this is the first skb we deliver in this batch */
|
||||
/* put the rate scaling data there */
|
||||
if (freed == 1)
|
||||
iwl_mvm_tx_info_from_ba_notif(info, ba_notif, tid_data);
|
||||
}
|
||||
|
||||
spin_unlock_bh(&mvmsta->lock);
|
||||
|
||||
/* We got a BA notif with 0 acked or scd_ssn didn't progress which is
|
||||
* possible (i.e. first MPDU in the aggregation wasn't acked)
|
||||
* Still it's important to update RS about sent vs. acked.
|
||||
*/
|
||||
if (skb_queue_empty(&reclaimed_skbs)) {
|
||||
struct ieee80211_tx_info ba_info = {};
|
||||
struct ieee80211_chanctx_conf *chanctx_conf = NULL;
|
||||
|
||||
if (mvmsta->vif)
|
||||
chanctx_conf =
|
||||
rcu_dereference(mvmsta->vif->chanctx_conf);
|
||||
|
||||
if (WARN_ON_ONCE(!chanctx_conf))
|
||||
goto out;
|
||||
|
||||
ba_info.band = chanctx_conf->def.chan->band;
|
||||
iwl_mvm_tx_info_from_ba_notif(&ba_info, ba_notif, tid_data);
|
||||
|
||||
IWL_DEBUG_TX_REPLY(mvm, "No reclaim. Update rs directly\n");
|
||||
iwl_mvm_rs_tx_status(mvm, sta, tid, &ba_info);
|
||||
}
|
||||
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
|
||||
while (!skb_queue_empty(&reclaimed_skbs)) {
|
||||
|
@ -530,6 +530,52 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm)
|
||||
iwl_mvm_dump_umac_error_log(mvm);
|
||||
}
|
||||
|
||||
void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, u16 ssn,
|
||||
const struct iwl_trans_txq_scd_cfg *cfg)
|
||||
{
|
||||
if (iwl_mvm_is_dqa_supported(mvm)) {
|
||||
struct iwl_scd_txq_cfg_cmd cmd = {
|
||||
.scd_queue = queue,
|
||||
.enable = 1,
|
||||
.window = cfg->frame_limit,
|
||||
.sta_id = cfg->sta_id,
|
||||
.ssn = cpu_to_le16(ssn),
|
||||
.tx_fifo = cfg->fifo,
|
||||
.aggregate = cfg->aggregate,
|
||||
.flags = IWL_SCD_FLAGS_DQA_ENABLED,
|
||||
.tid = cfg->tid,
|
||||
.control = IWL_SCD_CONTROL_SET_SSN,
|
||||
};
|
||||
int ret = iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, 0,
|
||||
sizeof(cmd), &cmd);
|
||||
if (ret)
|
||||
IWL_ERR(mvm,
|
||||
"Failed to configure queue %d on FIFO %d\n",
|
||||
queue, cfg->fifo);
|
||||
}
|
||||
|
||||
iwl_trans_txq_enable_cfg(mvm->trans, queue, ssn,
|
||||
iwl_mvm_is_dqa_supported(mvm) ? NULL : cfg);
|
||||
}
|
||||
|
||||
void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue)
|
||||
{
|
||||
iwl_trans_txq_disable(mvm->trans, queue,
|
||||
!iwl_mvm_is_dqa_supported(mvm));
|
||||
|
||||
if (iwl_mvm_is_dqa_supported(mvm)) {
|
||||
struct iwl_scd_txq_cfg_cmd cmd = {
|
||||
.scd_queue = queue,
|
||||
.enable = 0,
|
||||
};
|
||||
int ret = iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, CMD_ASYNC,
|
||||
sizeof(cmd), &cmd);
|
||||
if (ret)
|
||||
IWL_ERR(mvm, "Failed to disable queue %d (ret=%d)\n",
|
||||
queue, ret);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_mvm_send_lq_cmd() - Send link quality command
|
||||
* @init: This command is sent as part of station initialization right
|
||||
|
@ -275,6 +275,8 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
|
||||
{IWL_PCI_DEVICE(0x08B1, 0x4070, iwl7260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0x4072, iwl7260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0x4170, iwl7260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0x4C60, iwl7260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0x4C70, iwl7260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0x4060, iwl7260_2n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0x406A, iwl7260_2n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0x4160, iwl7260_2n_cfg)},
|
||||
@ -318,6 +320,8 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
|
||||
{IWL_PCI_DEVICE(0x08B1, 0xC770, iwl7260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0xC760, iwl7260_2n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B2, 0xC270, iwl7260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0xCC70, iwl7260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B1, 0xCC60, iwl7260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B2, 0xC272, iwl7260_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B2, 0xC260, iwl7260_2n_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08B2, 0xC26A, iwl7260_n_cfg)},
|
||||
|
@ -2190,7 +2190,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
||||
*/
|
||||
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
|
||||
trans->hw_rev = (trans->hw_rev & 0xfff0) |
|
||||
(CSR_HW_REV_STEP(trans->hw_rev << 2));
|
||||
(CSR_HW_REV_STEP(trans->hw_rev << 2) << 2);
|
||||
|
||||
trans->hw_id = (pdev->device << 16) + pdev->subsystem_device;
|
||||
snprintf(trans->hw_id_str, sizeof(trans->hw_id_str),
|
||||
|
Loading…
Reference in New Issue
Block a user