Skip to content

Commit

Permalink
Merge tag 'iwlwifi-for-kalle-2017-06-05' of git://git.kernel.org/pub/…
Browse files Browse the repository at this point in the history
…scm/linux/kernel/git/iwlwifi/iwlwifi-fixes

Fixes for 4.12:

* Some memory leaks;
* IBSS support;
* Some bugzilla bugs;
* Some runtime PM fixes;
* Rate-scaling issues;
* Some locking problems;
  • Loading branch information
Kalle Valo committed Jun 5, 2017
2 parents 1dbf647 + dc1cd1d commit dc89481
Show file tree
Hide file tree
Showing 17 changed files with 115 additions and 78 deletions.
4 changes: 2 additions & 2 deletions drivers/net/wireless/intel/iwlwifi/iwl-7000.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@
/* Lowest firmware API version supported */
#define IWL7260_UCODE_API_MIN 17
#define IWL7265_UCODE_API_MIN 17
#define IWL7265D_UCODE_API_MIN 17
#define IWL3168_UCODE_API_MIN 20
#define IWL7265D_UCODE_API_MIN 22
#define IWL3168_UCODE_API_MIN 22

/* NVM versions */
#define IWL7260_NVM_VERSION 0x0a1d
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/wireless/intel/iwlwifi/iwl-8000.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@
#define IWL8265_UCODE_API_MAX 30

/* Lowest firmware API version supported */
#define IWL8000_UCODE_API_MIN 17
#define IWL8265_UCODE_API_MIN 20
#define IWL8000_UCODE_API_MIN 22
#define IWL8265_UCODE_API_MIN 22

/* NVM versions */
#define IWL8000_NVM_VERSION 0x0a1d
Expand Down
1 change: 1 addition & 0 deletions drivers/net/wireless/intel/iwlwifi/iwl-prph.h
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@
#define MON_DMARB_RD_DATA_ADDR (0xa03c5c)

#define DBGC_IN_SAMPLE (0xa03c00)
#define DBGC_OUT_CTRL (0xa03c0c)

/* enable the ID buf for read */
#define WFPM_PS_CTL_CLR 0xA0300C
Expand Down
5 changes: 5 additions & 0 deletions drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rs.h
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,11 @@ enum {
/* Bit 1-3: LQ command color. Used to match responses to LQ commands */
#define LQ_FLAG_COLOR_POS 1
#define LQ_FLAG_COLOR_MSK (7 << LQ_FLAG_COLOR_POS)
#define LQ_FLAG_COLOR_GET(_f) (((_f) & LQ_FLAG_COLOR_MSK) >>\
LQ_FLAG_COLOR_POS)
#define LQ_FLAGS_COLOR_INC(_c) ((((_c) + 1) << LQ_FLAG_COLOR_POS) &\
LQ_FLAG_COLOR_MSK)
#define LQ_FLAG_COLOR_SET(_f, _c) ((_c) | ((_f) & ~LQ_FLAG_COLOR_MSK))

/* Bit 4-5: Tx RTS BW Signalling
* (0) No RTS BW signalling
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/wireless/intel/iwlwifi/mvm/fw-api-tx.h
Original file line number Diff line number Diff line change
Expand Up @@ -519,8 +519,11 @@ struct agg_tx_status {
* bit-7 invalid rate indication
*/
#define TX_RES_INIT_RATE_INDEX_MSK 0x0f
#define TX_RES_RATE_TABLE_COLOR_POS 4
#define TX_RES_RATE_TABLE_COLOR_MSK 0x70
#define TX_RES_INV_RATE_INDEX_MSK 0x80
#define TX_RES_RATE_TABLE_COL_GET(_f) (((_f) & TX_RES_RATE_TABLE_COLOR_MSK) >>\
TX_RES_RATE_TABLE_COLOR_POS)

#define IWL_MVM_TX_RES_GET_TID(_ra_tid) ((_ra_tid) & 0x0f)
#define IWL_MVM_TX_RES_GET_RA(_ra_tid) ((_ra_tid) >> 4)
Expand Down
12 changes: 1 addition & 11 deletions drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c
Original file line number Diff line number Diff line change
Expand Up @@ -1002,14 +1002,6 @@ int iwl_mvm_fw_dbg_collect_trig(struct iwl_mvm *mvm,
return 0;
}

static inline void iwl_mvm_restart_early_start(struct iwl_mvm *mvm)
{
if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000)
iwl_clear_bits_prph(mvm->trans, MON_BUFF_SAMPLE_CTL, 0x100);
else
iwl_write_prph(mvm->trans, DBGC_IN_SAMPLE, 1);
}

int iwl_mvm_start_fw_dbg_conf(struct iwl_mvm *mvm, u8 conf_id)
{
u8 *ptr;
Expand All @@ -1023,10 +1015,8 @@ int iwl_mvm_start_fw_dbg_conf(struct iwl_mvm *mvm, u8 conf_id)
/* EARLY START - firmware's configuration is hard coded */
if ((!mvm->fw->dbg_conf_tlv[conf_id] ||
!mvm->fw->dbg_conf_tlv[conf_id]->num_of_hcmds) &&
conf_id == FW_DBG_START_FROM_ALIVE) {
iwl_mvm_restart_early_start(mvm);
conf_id == FW_DBG_START_FROM_ALIVE)
return 0;
}

if (!mvm->fw->dbg_conf_tlv[conf_id])
return -EINVAL;
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
Original file line number Diff line number Diff line change
Expand Up @@ -1040,7 +1040,7 @@ static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
struct iwl_mac_beacon_cmd_v6 beacon_cmd_v6;
struct iwl_mac_beacon_cmd_v7 beacon_cmd;
} u = {};
struct iwl_mac_beacon_cmd beacon_cmd;
struct iwl_mac_beacon_cmd beacon_cmd = {};
struct ieee80211_tx_info *info;
u32 beacon_skb_len;
u32 rate, tx_flags;
Expand Down
6 changes: 5 additions & 1 deletion drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -1730,8 +1730,11 @@ int iwl_mvm_find_free_queue(struct iwl_mvm *mvm, u8 sta_id, u8 minq, u8 maxq);
*/
static inline u32 iwl_mvm_flushable_queues(struct iwl_mvm *mvm)
{
u32 cmd_queue = iwl_mvm_is_dqa_supported(mvm) ? IWL_MVM_DQA_CMD_QUEUE :
IWL_MVM_CMD_QUEUE;

return ((BIT(mvm->cfg->base_params->num_of_queues) - 1) &
~BIT(IWL_MVM_CMD_QUEUE));
~BIT(cmd_queue));
}

static inline
Expand All @@ -1753,6 +1756,7 @@ static inline void iwl_mvm_stop_device(struct iwl_mvm *mvm)
if (!iwl_mvm_has_new_tx_api(mvm))
iwl_free_fw_paging(mvm);
mvm->ucode_loaded = false;
mvm->fw_dbg_conf = FW_DBG_INVALID;
iwl_trans_stop_device(mvm->trans);
}

Expand Down
32 changes: 24 additions & 8 deletions drivers/net/wireless/intel/iwlwifi/mvm/ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -1149,21 +1149,37 @@ static void iwl_mvm_fw_error_dump_wk(struct work_struct *work)

mutex_lock(&mvm->mutex);

/* stop recording */
if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
/* stop recording */
iwl_set_bits_prph(mvm->trans, MON_BUFF_SAMPLE_CTL, 0x100);

iwl_mvm_fw_error_dump(mvm);

/* start recording again if the firmware is not crashed */
if (!test_bit(STATUS_FW_ERROR, &mvm->trans->status) &&
mvm->fw->dbg_dest_tlv)
iwl_clear_bits_prph(mvm->trans,
MON_BUFF_SAMPLE_CTL, 0x100);
} else {
u32 in_sample = iwl_read_prph(mvm->trans, DBGC_IN_SAMPLE);
u32 out_ctrl = iwl_read_prph(mvm->trans, DBGC_OUT_CTRL);

/* stop recording */
iwl_write_prph(mvm->trans, DBGC_IN_SAMPLE, 0);
/* wait before we collect the data till the DBGC stop */
udelay(100);
}
iwl_write_prph(mvm->trans, DBGC_OUT_CTRL, 0);
/* wait before we collect the data till the DBGC stop */
udelay(500);

iwl_mvm_fw_error_dump(mvm);
iwl_mvm_fw_error_dump(mvm);

/* start recording again if the firmware is not crashed */
WARN_ON_ONCE((!test_bit(STATUS_FW_ERROR, &mvm->trans->status)) &&
mvm->fw->dbg_dest_tlv &&
iwl_mvm_start_fw_dbg_conf(mvm, mvm->fw_dbg_conf));
/* start recording again if the firmware is not crashed */
if (!test_bit(STATUS_FW_ERROR, &mvm->trans->status) &&
mvm->fw->dbg_dest_tlv) {
iwl_write_prph(mvm->trans, DBGC_IN_SAMPLE, in_sample);
iwl_write_prph(mvm->trans, DBGC_OUT_CTRL, out_ctrl);
}
}

mutex_unlock(&mvm->mutex);

Expand Down
46 changes: 11 additions & 35 deletions drivers/net/wireless/intel/iwlwifi/mvm/rs.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
*
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 Intel Deutschland GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
*
* 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
Expand Down Expand Up @@ -1083,34 +1083,6 @@ static void rs_get_lower_rate_down_column(struct iwl_lq_sta *lq_sta,
rs_get_lower_rate_in_column(lq_sta, rate);
}

/* Check if both rates are identical
* allow_ant_mismatch enables matching a SISO rate on ANT_A or ANT_B
* with a rate indicating STBC/BFER and ANT_AB.
*/
static inline bool rs_rate_equal(struct rs_rate *a,
struct rs_rate *b,
bool allow_ant_mismatch)

{
bool ant_match = (a->ant == b->ant) && (a->stbc == b->stbc) &&
(a->bfer == b->bfer);

if (allow_ant_mismatch) {
if (a->stbc || a->bfer) {
WARN_ONCE(a->ant != ANT_AB, "stbc %d bfer %d ant %d",
a->stbc, a->bfer, a->ant);
ant_match |= (b->ant == ANT_A || b->ant == ANT_B);
} else if (b->stbc || b->bfer) {
WARN_ONCE(b->ant != ANT_AB, "stbc %d bfer %d ant %d",
b->stbc, b->bfer, b->ant);
ant_match |= (a->ant == ANT_A || a->ant == ANT_B);
}
}

return (a->type == b->type) && (a->bw == b->bw) && (a->sgi == b->sgi) &&
(a->ldpc == b->ldpc) && (a->index == b->index) && ant_match;
}

/* Check if both rates share the same column */
static inline bool rs_rate_column_match(struct rs_rate *a,
struct rs_rate *b)
Expand Down Expand Up @@ -1182,12 +1154,12 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
u32 lq_hwrate;
struct rs_rate lq_rate, tx_resp_rate;
struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl;
u8 reduced_txp = (uintptr_t)info->status.status_driver_data[0];
u32 tlc_info = (uintptr_t)info->status.status_driver_data[0];
u8 reduced_txp = tlc_info & RS_DRV_DATA_TXP_MSK;
u8 lq_color = RS_DRV_DATA_LQ_COLOR_GET(tlc_info);
u32 tx_resp_hwrate = (uintptr_t)info->status.status_driver_data[1];
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
struct iwl_lq_sta *lq_sta = &mvmsta->lq_sta;
bool allow_ant_mismatch = fw_has_api(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_API_LQ_SS_PARAMS);

/* Treat uninitialized rate scaling data same as non-existing. */
if (!lq_sta) {
Expand Down Expand Up @@ -1262,10 +1234,10 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
rs_rate_from_ucode_rate(lq_hwrate, info->band, &lq_rate);

/* Here we actually compare this rate to the latest LQ command */
if (!rs_rate_equal(&tx_resp_rate, &lq_rate, allow_ant_mismatch)) {
if (lq_color != LQ_FLAG_COLOR_GET(table->flags)) {
IWL_DEBUG_RATE(mvm,
"initial tx resp rate 0x%x does not match 0x%x\n",
tx_resp_hwrate, lq_hwrate);
"tx resp color 0x%x does not match 0x%x\n",
lq_color, LQ_FLAG_COLOR_GET(table->flags));

/*
* Since rates mis-match, the last LQ command may have failed.
Expand Down Expand Up @@ -3326,6 +3298,7 @@ static void rs_build_rates_table(struct iwl_mvm *mvm,
u8 valid_tx_ant = 0;
struct iwl_lq_cmd *lq_cmd = &lq_sta->lq;
bool toggle_ant = false;
u32 color;

memcpy(&rate, initial_rate, sizeof(rate));

Expand Down Expand Up @@ -3380,6 +3353,9 @@ static void rs_build_rates_table(struct iwl_mvm *mvm,
num_rates, num_retries, valid_tx_ant,
toggle_ant);

/* update the color of the LQ command (as a counter at bits 1-3) */
color = LQ_FLAGS_COLOR_INC(LQ_FLAG_COLOR_GET(lq_cmd->flags));
lq_cmd->flags = LQ_FLAG_COLOR_SET(lq_cmd->flags, color);
}

struct rs_bfer_active_iter_data {
Expand Down
15 changes: 15 additions & 0 deletions drivers/net/wireless/intel/iwlwifi/mvm/rs.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
*
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2015 Intel Mobile Communications GmbH
* Copyright(c) 2017 Intel Deutschland GmbH
*
* 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
Expand Down Expand Up @@ -357,6 +358,20 @@ struct iwl_lq_sta {
} pers;
};

/* ieee80211_tx_info's status_driver_data[0] is packed with lq color and txp
* Note, it's iwlmvm <-> mac80211 interface.
* bits 0-7: reduced tx power
* bits 8-10: LQ command's color
*/
#define RS_DRV_DATA_TXP_MSK 0xff
#define RS_DRV_DATA_LQ_COLOR_POS 8
#define RS_DRV_DATA_LQ_COLOR_MSK (7 << RS_DRV_DATA_LQ_COLOR_POS)
#define RS_DRV_DATA_LQ_COLOR_GET(_f) (((_f) & RS_DRV_DATA_LQ_COLOR_MSK) >>\
RS_DRV_DATA_LQ_COLOR_POS)
#define RS_DRV_DATA_PACK(_c, _p) ((void *)(uintptr_t)\
(((uintptr_t)_p) |\
((_c) << RS_DRV_DATA_LQ_COLOR_POS)))

/* Initialize station's rate scaling information after adding station */
void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
enum nl80211_band band, bool init);
Expand Down
26 changes: 17 additions & 9 deletions drivers/net/wireless/intel/iwlwifi/mvm/sta.c
Original file line number Diff line number Diff line change
Expand Up @@ -2120,7 +2120,8 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
if (!iwl_mvm_is_dqa_supported(mvm))
return 0;

if (WARN_ON(vif->type != NL80211_IFTYPE_AP))
if (WARN_ON(vif->type != NL80211_IFTYPE_AP &&
vif->type != NL80211_IFTYPE_ADHOC))
return -ENOTSUPP;

/*
Expand Down Expand Up @@ -2155,6 +2156,16 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
mvmvif->cab_queue = queue;
} else if (!fw_has_api(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_API_STA_TYPE)) {
/*
* In IBSS, ieee80211_check_queues() sets the cab_queue to be
* invalid, so make sure we use the queue we want.
* Note that this is done here as we want to avoid making DQA
* changes in mac80211 layer.
*/
if (vif->type == NL80211_IFTYPE_ADHOC) {
vif->cab_queue = IWL_MVM_DQA_GCAST_QUEUE;
mvmvif->cab_queue = vif->cab_queue;
}
iwl_mvm_enable_txq(mvm, vif->cab_queue, vif->cab_queue, 0,
&cfg, timeout);
}
Expand Down Expand Up @@ -3321,18 +3332,15 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,

/* Get the station from the mvm local station table */
mvm_sta = iwl_mvm_get_key_sta(mvm, vif, sta);
if (!mvm_sta) {
IWL_ERR(mvm, "Failed to find station\n");
return -EINVAL;
}
sta_id = mvm_sta->sta_id;
if (mvm_sta)
sta_id = mvm_sta->sta_id;

IWL_DEBUG_WEP(mvm, "mvm remove dynamic key: idx=%d sta=%d\n",
keyconf->keyidx, sta_id);

if (keyconf->cipher == WLAN_CIPHER_SUITE_AES_CMAC ||
keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 ||
keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256)
if (mvm_sta && (keyconf->cipher == WLAN_CIPHER_SUITE_AES_CMAC ||
keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 ||
keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256))
return iwl_mvm_send_sta_igtk(mvm, keyconf, sta_id, true);

if (!__test_and_clear_bit(keyconf->hw_key_idx, mvm->fw_key_table)) {
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/wireless/intel/iwlwifi/mvm/sta.h
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ enum iwl_mvm_agg_state {
* This is basically (last acked packet++).
* @rate_n_flags: Rate at which Tx was attempted. Holds the data between the
* Tx response (TX_CMD), and the block ack notification (COMPRESSED_BA).
* @lq_color: the color of the LQ command as it appears in tx response.
* @amsdu_in_ampdu_allowed: true if A-MSDU in A-MPDU is allowed.
* @state: state of the BA agreement establishment / tear down.
* @txq_id: Tx queue used by the BA session / DQA
Expand All @@ -331,6 +332,7 @@ struct iwl_mvm_tid_data {
u16 next_reclaimed;
/* The rest is Tx AGG related */
u32 rate_n_flags;
u8 lq_color;
bool amsdu_in_ampdu_allowed;
enum iwl_mvm_agg_state state;
u16 txq_id;
Expand Down
8 changes: 5 additions & 3 deletions drivers/net/wireless/intel/iwlwifi/mvm/tt.c
Original file line number Diff line number Diff line change
Expand Up @@ -790,11 +790,13 @@ static int iwl_mvm_tcool_set_cur_state(struct thermal_cooling_device *cdev,
struct iwl_mvm *mvm = (struct iwl_mvm *)(cdev->devdata);
int ret;

if (!mvm->ucode_loaded || !(mvm->cur_ucode == IWL_UCODE_REGULAR))
return -EIO;

mutex_lock(&mvm->mutex);

if (!mvm->ucode_loaded || !(mvm->cur_ucode == IWL_UCODE_REGULAR)) {
ret = -EIO;
goto unlock;
}

if (new_state >= ARRAY_SIZE(iwl_mvm_cdev_budgets)) {
ret = -EINVAL;
goto unlock;
Expand Down
Loading

0 comments on commit dc89481

Please sign in to comment.