Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next
This commit is contained in:
Коммит
31c5770b5d
|
@ -1266,7 +1266,3 @@ module_param_named(auto_agg, iwlwifi_mod_params.auto_agg,
|
|||
bool, S_IRUGO);
|
||||
MODULE_PARM_DESC(auto_agg,
|
||||
"enable agg w/o check traffic load (default: enable)");
|
||||
|
||||
module_param_named(5ghz_disable, iwlwifi_mod_params.disable_5ghz,
|
||||
bool, S_IRUGO);
|
||||
MODULE_PARM_DESC(5ghz_disable, "disable 5GHz band (default: 0 [enabled])");
|
||||
|
|
|
@ -154,6 +154,19 @@ struct iwl_tlv_calib_ctrl {
|
|||
__le32 event_trigger;
|
||||
} __packed;
|
||||
|
||||
enum iwl_fw_phy_cfg {
|
||||
FW_PHY_CFG_RADIO_TYPE_POS = 0,
|
||||
FW_PHY_CFG_RADIO_TYPE = 0x3 << FW_PHY_CFG_RADIO_TYPE_POS,
|
||||
FW_PHY_CFG_RADIO_STEP_POS = 2,
|
||||
FW_PHY_CFG_RADIO_STEP = 0x3 << FW_PHY_CFG_RADIO_STEP_POS,
|
||||
FW_PHY_CFG_RADIO_DASH_POS = 4,
|
||||
FW_PHY_CFG_RADIO_DASH = 0x3 << FW_PHY_CFG_RADIO_DASH_POS,
|
||||
FW_PHY_CFG_TX_CHAIN_POS = 16,
|
||||
FW_PHY_CFG_TX_CHAIN = 0xf << FW_PHY_CFG_TX_CHAIN_POS,
|
||||
FW_PHY_CFG_RX_CHAIN_POS = 20,
|
||||
FW_PHY_CFG_RX_CHAIN = 0xf << FW_PHY_CFG_RX_CHAIN_POS,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_fw - variables associated with the firmware
|
||||
*
|
||||
|
@ -190,4 +203,16 @@ struct iwl_fw {
|
|||
bool mvm_fw;
|
||||
};
|
||||
|
||||
static inline u8 iwl_fw_valid_tx_ant(const struct iwl_fw *fw)
|
||||
{
|
||||
return (fw->phy_config & FW_PHY_CFG_TX_CHAIN) >>
|
||||
FW_PHY_CFG_TX_CHAIN_POS;
|
||||
}
|
||||
|
||||
static inline u8 iwl_fw_valid_rx_ant(const struct iwl_fw *fw)
|
||||
{
|
||||
return (fw->phy_config & FW_PHY_CFG_RX_CHAIN) >>
|
||||
FW_PHY_CFG_RX_CHAIN_POS;
|
||||
}
|
||||
|
||||
#endif /* __iwl_fw_h__ */
|
||||
|
|
|
@ -103,7 +103,6 @@ enum iwl_power_level {
|
|||
* @ant_coupling: antenna coupling in dB, default = 0
|
||||
* @bt_ch_announce: BT channel inhibition, default = enable
|
||||
* @auto_agg: enable agg. without check, default = true
|
||||
* @disable_5ghz: disable 5GHz capability, default = false
|
||||
*/
|
||||
struct iwl_mod_params {
|
||||
int sw_crypto;
|
||||
|
@ -120,7 +119,6 @@ struct iwl_mod_params {
|
|||
int ant_coupling;
|
||||
bool bt_ch_announce;
|
||||
bool auto_agg;
|
||||
bool disable_5ghz;
|
||||
};
|
||||
|
||||
#endif /* #__iwl_modparams_h__ */
|
||||
|
|
|
@ -272,7 +272,7 @@ static int iwl_test_fw_cmd(struct iwl_test *tst, struct nlattr **tb)
|
|||
|
||||
reply_len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
|
||||
skb = iwl_test_alloc_reply(tst, reply_len + 20);
|
||||
reply_buf = kmalloc(reply_len, GFP_KERNEL);
|
||||
reply_buf = kmemdup(&pkt->hdr, reply_len, GFP_KERNEL);
|
||||
if (!skb || !reply_buf) {
|
||||
kfree_skb(skb);
|
||||
kfree(reply_buf);
|
||||
|
@ -280,7 +280,6 @@ static int iwl_test_fw_cmd(struct iwl_test *tst, struct nlattr **tb)
|
|||
}
|
||||
|
||||
/* The reply is in a page, that we cannot send to user space. */
|
||||
memcpy(reply_buf, &(pkt->hdr), reply_len);
|
||||
iwl_free_resp(&cmd);
|
||||
|
||||
if (nla_put_u32(skb, IWL_TM_ATTR_COMMAND,
|
||||
|
|
|
@ -125,15 +125,15 @@ enum iwl_bt_kill_msk {
|
|||
};
|
||||
|
||||
static const u32 iwl_bt_ack_kill_msk[BT_KILL_MSK_MAX] = {
|
||||
0xffffffff,
|
||||
0xfffffc00,
|
||||
0,
|
||||
[BT_KILL_MSK_DEFAULT] = 0xffff0000,
|
||||
[BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff,
|
||||
[BT_KILL_MSK_REDUCED_TXPOW] = 0,
|
||||
};
|
||||
|
||||
static const u32 iwl_bt_cts_kill_msk[BT_KILL_MSK_MAX] = {
|
||||
0xffffffff,
|
||||
0xfffffc00,
|
||||
0,
|
||||
[BT_KILL_MSK_DEFAULT] = 0xffff0000,
|
||||
[BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff,
|
||||
[BT_KILL_MSK_REDUCED_TXPOW] = 0,
|
||||
};
|
||||
|
||||
#define IWL_BT_DEFAULT_BOOST (0xf0f0f0f0)
|
||||
|
@ -188,6 +188,8 @@ static const __le32 iwl_concurrent_lookup[BT_COEX_LUT_SIZE] = {
|
|||
|
||||
/* BT Antenna Coupling Threshold (dB) */
|
||||
#define IWL_BT_ANTENNA_COUPLING_THRESHOLD (35)
|
||||
#define IWL_BT_LOAD_FORCE_SISO_THRESHOLD (3)
|
||||
|
||||
|
||||
int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
|
||||
{
|
||||
|
@ -201,8 +203,7 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
|
|||
|
||||
cmd.flags = iwlwifi_mod_params.bt_coex_active ?
|
||||
BT_COEX_NW : BT_COEX_DISABLE;
|
||||
cmd.flags |= iwlwifi_mod_params.bt_ch_announce ?
|
||||
BT_CH_PRIMARY_EN | BT_CH_SECONDARY_EN : 0;
|
||||
cmd.flags |= iwlwifi_mod_params.bt_ch_announce ? BT_CH_PRIMARY_EN : 0;
|
||||
cmd.flags |= BT_SYNC_2_BT_DISABLE;
|
||||
|
||||
cmd.valid_bit_msk = cpu_to_le16(BT_VALID_ENABLE |
|
||||
|
@ -275,7 +276,7 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
|
|||
if (data->notif->bt_status)
|
||||
smps_mode = IEEE80211_SMPS_DYNAMIC;
|
||||
|
||||
if (data->notif->bt_traffic_load)
|
||||
if (data->notif->bt_traffic_load >= IWL_BT_LOAD_FORCE_SISO_THRESHOLD)
|
||||
smps_mode = IEEE80211_SMPS_STATIC;
|
||||
|
||||
IWL_DEBUG_COEX(data->mvm,
|
||||
|
@ -327,7 +328,7 @@ int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
|
|||
return 0;
|
||||
|
||||
IWL_DEBUG_COEX(mvm,
|
||||
"Udpate kill_msk: %d\n\t SCO %sactive A2DP %sactive SNIFF %sactive\n",
|
||||
"Update kill_msk: %d - SCO %sactive A2DP %sactive SNIFF %sactive\n",
|
||||
bt_kill_msk,
|
||||
BT_MBOX_MSG(notif, 3, SCO_STATE) ? "" : "in",
|
||||
BT_MBOX_MSG(notif, 3, A2DP_STATE) ? "" : "in",
|
||||
|
|
|
@ -866,17 +866,13 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
|
|||
cpu_to_le32(IWL_WOWLAN_WAKEUP_PATTERN_MATCH);
|
||||
|
||||
if (wowlan->rfkill_release)
|
||||
d3_cfg_cmd.wakeup_flags |=
|
||||
wowlan_config_cmd.wakeup_filter |=
|
||||
cpu_to_le32(IWL_WOWLAN_WAKEUP_RF_KILL_DEASSERT);
|
||||
|
||||
if (wowlan->tcp) {
|
||||
/*
|
||||
* The firmware currently doesn't really look at these, only
|
||||
* the IWL_WOWLAN_WAKEUP_LINK_CHANGE bit. We have to set that
|
||||
* reason bit since losing the connection to the AP implies
|
||||
* losing the TCP connection.
|
||||
* Set the flags anyway as long as they exist, in case this
|
||||
* will be changed in the firmware.
|
||||
* Set the "link change" (really "link lost") flag as well
|
||||
* since that implies losing the TCP connection.
|
||||
*/
|
||||
wowlan_config_cmd.wakeup_filter |=
|
||||
cpu_to_le32(IWL_WOWLAN_WAKEUP_REMOTE_LINK_LOSS |
|
||||
|
|
|
@ -537,6 +537,12 @@ struct iwl_mac_beacon_cmd {
|
|||
struct ieee80211_hdr frame[0];
|
||||
} __packed;
|
||||
|
||||
struct iwl_beacon_notif {
|
||||
struct iwl_mvm_tx_resp beacon_notify_hdr;
|
||||
__le64 tsf;
|
||||
__le32 ibss_mgr_status;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* enum iwl_dump_control - dump (flush) control flags
|
||||
* @DUMP_TX_FIFO_FLUSH: Dump MSDUs until the the FIFO is empty
|
||||
|
|
|
@ -151,6 +151,7 @@ enum {
|
|||
|
||||
SET_CALIB_DEFAULT_CMD = 0x8e,
|
||||
|
||||
BEACON_NOTIFICATION = 0x90,
|
||||
BEACON_TEMPLATE_CMD = 0x91,
|
||||
TX_ANT_CONFIGURATION_CMD = 0x98,
|
||||
BT_CONFIG = 0x9b,
|
||||
|
@ -278,38 +279,7 @@ enum {
|
|||
NVM_ACCESS_TARGET_EEPROM = 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_nvm_access_cmd_ver1 - Request the device to send the NVM.
|
||||
* @op_code: 0 - read, 1 - write.
|
||||
* @target: NVM_ACCESS_TARGET_*. should be 0 for read.
|
||||
* @cache_refresh: 0 - None, 1- NVM.
|
||||
* @offset: offset in the nvm data.
|
||||
* @length: of the chunk.
|
||||
* @data: empty on read, the NVM chunk on write
|
||||
*/
|
||||
struct iwl_nvm_access_cmd_ver1 {
|
||||
u8 op_code;
|
||||
u8 target;
|
||||
u8 cache_refresh;
|
||||
u8 reserved;
|
||||
__le16 offset;
|
||||
__le16 length;
|
||||
u8 data[];
|
||||
} __packed; /* NVM_ACCESS_CMD_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_nvm_access_resp_ver1 - response to NVM_ACCESS_CMD
|
||||
* @offset: the offset in the nvm data
|
||||
* @length: of the chunk
|
||||
* @data: the nvm chunk on when NVM_ACCESS_CMD was read, nothing on write
|
||||
*/
|
||||
struct iwl_nvm_access_resp_ver1 {
|
||||
__le16 offset;
|
||||
__le16 length;
|
||||
u8 data[];
|
||||
} __packed; /* NVM_ACCESS_CMD_RESP_API_S_VER_1 */
|
||||
|
||||
/* Section types for NVM_ACCESS_CMD version 2 */
|
||||
/* Section types for NVM_ACCESS_CMD */
|
||||
enum {
|
||||
NVM_SECTION_TYPE_HW = 0,
|
||||
NVM_SECTION_TYPE_SW,
|
||||
|
@ -330,7 +300,7 @@ enum {
|
|||
* @length: in bytes, to read/write
|
||||
* @data: if write operation, the data to write. On read its empty
|
||||
*/
|
||||
struct iwl_nvm_access_cmd_ver2 {
|
||||
struct iwl_nvm_access_cmd {
|
||||
u8 op_code;
|
||||
u8 target;
|
||||
__le16 type;
|
||||
|
@ -347,7 +317,7 @@ struct iwl_nvm_access_cmd_ver2 {
|
|||
* @status: 0 for success, fail otherwise
|
||||
* @data: if read operation, the data returned. Empty on write.
|
||||
*/
|
||||
struct iwl_nvm_access_resp_ver2 {
|
||||
struct iwl_nvm_access_resp {
|
||||
__le16 offset;
|
||||
__le16 length;
|
||||
__le16 type;
|
||||
|
|
|
@ -114,7 +114,7 @@ static int iwl_send_tx_ant_cfg(struct iwl_mvm *mvm, u8 valid_tx_ant)
|
|||
.valid = cpu_to_le32(valid_tx_ant),
|
||||
};
|
||||
|
||||
IWL_DEBUG_HC(mvm, "select valid tx ant: %u\n", valid_tx_ant);
|
||||
IWL_DEBUG_FW(mvm, "select valid tx ant: %u\n", valid_tx_ant);
|
||||
return iwl_mvm_send_cmd_pdu(mvm, TX_ANT_CONFIGURATION_CMD, CMD_SYNC,
|
||||
sizeof(tx_ant_cmd), &tx_ant_cmd);
|
||||
}
|
||||
|
@ -134,9 +134,10 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
|
|||
alive_data->scd_base_addr = le32_to_cpu(palive->scd_base_ptr);
|
||||
|
||||
alive_data->valid = le16_to_cpu(palive->status) == IWL_ALIVE_STATUS_OK;
|
||||
IWL_DEBUG_FW(mvm, "Alive ucode status 0x%04x revision 0x%01X 0x%01X\n",
|
||||
IWL_DEBUG_FW(mvm,
|
||||
"Alive ucode status 0x%04x revision 0x%01X 0x%01X flags 0x%01X\n",
|
||||
le16_to_cpu(palive->status), palive->ver_type,
|
||||
palive->ver_subtype);
|
||||
palive->ver_subtype, palive->flags);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -326,16 +327,14 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
|
|||
WARN_ON(ret);
|
||||
|
||||
/* Send TX valid antennas before triggering calibrations */
|
||||
ret = iwl_send_tx_ant_cfg(mvm, mvm->nvm_data->valid_tx_ant);
|
||||
ret = iwl_send_tx_ant_cfg(mvm, iwl_fw_valid_tx_ant(mvm->fw));
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* WkP doesn't have all calibrations, need to set default values */
|
||||
if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
|
||||
ret = iwl_set_default_calibrations(mvm);
|
||||
if (ret)
|
||||
goto error;
|
||||
}
|
||||
/* need to set default values */
|
||||
ret = iwl_set_default_calibrations(mvm);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/*
|
||||
* Send phy configurations command to init uCode
|
||||
|
@ -414,7 +413,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
|
|||
goto error;
|
||||
}
|
||||
|
||||
ret = iwl_send_tx_ant_cfg(mvm, mvm->nvm_data->valid_tx_ant);
|
||||
ret = iwl_send_tx_ant_cfg(mvm, iwl_fw_valid_tx_ant(mvm->fw));
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
|
@ -468,7 +467,7 @@ int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm)
|
|||
goto error;
|
||||
}
|
||||
|
||||
ret = iwl_send_tx_ant_cfg(mvm, mvm->nvm_data->valid_tx_ant);
|
||||
ret = iwl_send_tx_ant_cfg(mvm, iwl_fw_valid_tx_ant(mvm->fw));
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
|
|
|
@ -196,7 +196,7 @@ u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm,
|
|||
u32 qmask, ac;
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
|
||||
return BIT(IWL_OFFCHANNEL_QUEUE);
|
||||
return BIT(IWL_MVM_OFFCHANNEL_QUEUE);
|
||||
|
||||
qmask = (vif->cab_queue != IEEE80211_INVAL_HW_QUEUE) ?
|
||||
BIT(vif->cab_queue) : 0;
|
||||
|
@ -692,7 +692,12 @@ static int iwl_mvm_mac_ctxt_cmd_listener(struct iwl_mvm *mvm,
|
|||
WARN_ON(vif->type != NL80211_IFTYPE_MONITOR);
|
||||
|
||||
iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
|
||||
/* No other data to be filled */
|
||||
|
||||
cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_PROMISC |
|
||||
MAC_FILTER_IN_CONTROL_AND_MGMT |
|
||||
MAC_FILTER_IN_BEACON |
|
||||
MAC_FILTER_IN_PROBE_REQUEST);
|
||||
|
||||
return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
|
||||
}
|
||||
|
||||
|
@ -798,7 +803,7 @@ static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
|
|||
TX_CMD_FLG_TSF);
|
||||
|
||||
mvm->mgmt_last_antenna_idx =
|
||||
iwl_mvm_next_antenna(mvm, mvm->nvm_data->valid_tx_ant,
|
||||
iwl_mvm_next_antenna(mvm, iwl_fw_valid_tx_ant(mvm->fw),
|
||||
mvm->mgmt_last_antenna_idx);
|
||||
|
||||
beacon_cmd.tx.rate_n_flags =
|
||||
|
@ -1013,3 +1018,22 @@ int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
|||
mvmvif->uploaded = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_beacon_notif *beacon = (void *)pkt->data;
|
||||
u16 status __maybe_unused =
|
||||
le16_to_cpu(beacon->beacon_notify_hdr.status.status);
|
||||
u32 rate __maybe_unused =
|
||||
le32_to_cpu(beacon->beacon_notify_hdr.initial_rate);
|
||||
|
||||
IWL_DEBUG_RX(mvm, "beacon status %#x retries:%d tsf:0x%16llX rate:%d\n",
|
||||
status & TX_STATUS_MSK,
|
||||
beacon->beacon_notify_hdr.failure_frame,
|
||||
le64_to_cpu(beacon->tsf),
|
||||
rate);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -143,8 +143,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
|
|||
IEEE80211_HW_AMPDU_AGGREGATION |
|
||||
IEEE80211_HW_TIMING_BEACON_ONLY;
|
||||
|
||||
hw->queues = IWL_FIRST_AMPDU_QUEUE;
|
||||
hw->offchannel_tx_hw_queue = IWL_OFFCHANNEL_QUEUE;
|
||||
hw->queues = IWL_MVM_FIRST_AGG_QUEUE;
|
||||
hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE;
|
||||
hw->rate_control_algorithm = "iwl-mvm-rs";
|
||||
|
||||
/*
|
||||
|
@ -174,7 +174,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
|
|||
hw->wiphy->n_iface_combinations =
|
||||
ARRAY_SIZE(iwl_mvm_iface_combinations);
|
||||
|
||||
hw->wiphy->max_remain_on_channel_duration = 500;
|
||||
hw->wiphy->max_remain_on_channel_duration = 10000;
|
||||
hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL;
|
||||
|
||||
/* Extract MAC address */
|
||||
|
@ -257,7 +257,7 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
|
|||
goto drop;
|
||||
}
|
||||
|
||||
if (IEEE80211_SKB_CB(skb)->hw_queue == IWL_OFFCHANNEL_QUEUE &&
|
||||
if (IEEE80211_SKB_CB(skb)->hw_queue == IWL_MVM_OFFCHANNEL_QUEUE &&
|
||||
!test_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status))
|
||||
goto drop;
|
||||
|
||||
|
@ -1087,6 +1087,13 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
|
|||
|
||||
switch (cmd) {
|
||||
case SET_KEY:
|
||||
if (vif->type == NL80211_IFTYPE_AP && !sta) {
|
||||
/* GTK on AP interface is a TX-only key, return 0 */
|
||||
ret = 0;
|
||||
key->hw_key_idx = STA_KEY_IDX_INVALID;
|
||||
break;
|
||||
}
|
||||
|
||||
IWL_DEBUG_MAC80211(mvm, "set hwcrypto key\n");
|
||||
ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, false);
|
||||
if (ret) {
|
||||
|
@ -1095,11 +1102,17 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
|
|||
* can't add key for RX, but we don't need it
|
||||
* in the device for TX so still return 0
|
||||
*/
|
||||
key->hw_key_idx = STA_KEY_IDX_INVALID;
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
case DISABLE_KEY:
|
||||
if (key->hw_key_idx == STA_KEY_IDX_INVALID) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
IWL_DEBUG_MAC80211(mvm, "disable hwcrypto key\n");
|
||||
ret = iwl_mvm_remove_sta_key(mvm, vif, sta, key);
|
||||
break;
|
||||
|
@ -1148,7 +1161,7 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
|
|||
&chandef, 1, 1);
|
||||
|
||||
/* Schedule the time events */
|
||||
ret = iwl_mvm_start_p2p_roc(mvm, vif, duration);
|
||||
ret = iwl_mvm_start_p2p_roc(mvm, vif, duration, type);
|
||||
|
||||
mutex_unlock(&mvm->mutex);
|
||||
IWL_DEBUG_MAC80211(mvm, "leave\n");
|
||||
|
@ -1252,6 +1265,7 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw,
|
|||
* will handle quota settings.
|
||||
*/
|
||||
if (vif->type == NL80211_IFTYPE_MONITOR) {
|
||||
mvmvif->monitor_active = true;
|
||||
ret = iwl_mvm_update_quotas(mvm, vif);
|
||||
if (ret)
|
||||
goto out_remove_binding;
|
||||
|
@ -1282,15 +1296,16 @@ static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw,
|
|||
if (vif->type == NL80211_IFTYPE_AP)
|
||||
goto out_unlock;
|
||||
|
||||
iwl_mvm_binding_remove_vif(mvm, vif);
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_MONITOR:
|
||||
iwl_mvm_update_quotas(mvm, vif);
|
||||
mvmvif->monitor_active = false;
|
||||
iwl_mvm_update_quotas(mvm, NULL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
iwl_mvm_binding_remove_vif(mvm, vif);
|
||||
out_unlock:
|
||||
mvmvif->phy_ctxt = NULL;
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
|
|
@ -90,10 +90,6 @@ enum iwl_mvm_tx_fifo {
|
|||
IWL_MVM_TX_FIFO_VO,
|
||||
};
|
||||
|
||||
/* Placeholder */
|
||||
#define IWL_OFFCHANNEL_QUEUE 8
|
||||
#define IWL_FIRST_AMPDU_QUEUE 11
|
||||
|
||||
extern struct ieee80211_ops iwl_mvm_hw_ops;
|
||||
/**
|
||||
* struct iwl_mvm_mod_params - module parameters for iwlmvm
|
||||
|
@ -161,6 +157,8 @@ enum iwl_power_scheme {
|
|||
* @uploaded: indicates the MAC context has been added to the device
|
||||
* @ap_active: indicates that ap context is configured, and that the interface
|
||||
* should get quota etc.
|
||||
* @monitor_active: indicates that monitor context is configured, and that the
|
||||
* interface should get quota etc.
|
||||
* @queue_params: QoS params for this MAC
|
||||
* @bcast_sta: station used for broadcast packets. Used by the following
|
||||
* vifs: P2P_DEVICE, GO and AP.
|
||||
|
@ -173,6 +171,7 @@ struct iwl_mvm_vif {
|
|||
|
||||
bool uploaded;
|
||||
bool ap_active;
|
||||
bool monitor_active;
|
||||
|
||||
u32 ap_beacon_time;
|
||||
|
||||
|
@ -281,10 +280,7 @@ struct iwl_mvm {
|
|||
atomic_t queue_stop_count[IWL_MAX_HW_QUEUES];
|
||||
|
||||
struct iwl_nvm_data *nvm_data;
|
||||
/* eeprom blob for debugfs/testmode */
|
||||
u8 *eeprom_blob;
|
||||
size_t eeprom_blob_size;
|
||||
/* NVM sections for 7000 family */
|
||||
/* NVM sections */
|
||||
struct iwl_nvm_section nvm_sections[NVM_NUM_OF_SECTIONS];
|
||||
|
||||
/* EEPROM MAC addresses */
|
||||
|
@ -451,6 +447,9 @@ u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm,
|
|||
struct ieee80211_vif *vif);
|
||||
int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif);
|
||||
int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd);
|
||||
|
||||
/* Bindings */
|
||||
int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
|
|
|
@ -77,26 +77,8 @@ static const int nvm_to_read[] = {
|
|||
/* Default NVM size to read */
|
||||
#define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024);
|
||||
|
||||
/* used to simplify the shared operations on NCM_ACCESS_CMD versions */
|
||||
union iwl_nvm_access_cmd {
|
||||
struct iwl_nvm_access_cmd_ver1 ver1;
|
||||
struct iwl_nvm_access_cmd_ver2 ver2;
|
||||
};
|
||||
union iwl_nvm_access_resp {
|
||||
struct iwl_nvm_access_resp_ver1 ver1;
|
||||
struct iwl_nvm_access_resp_ver2 ver2;
|
||||
};
|
||||
|
||||
static inline void iwl_nvm_fill_read_ver1(struct iwl_nvm_access_cmd_ver1 *cmd,
|
||||
u16 offset, u16 length)
|
||||
{
|
||||
cmd->offset = cpu_to_le16(offset);
|
||||
cmd->length = cpu_to_le16(length);
|
||||
cmd->cache_refresh = 1;
|
||||
}
|
||||
|
||||
static inline void iwl_nvm_fill_read_ver2(struct iwl_nvm_access_cmd_ver2 *cmd,
|
||||
u16 offset, u16 length, u16 section)
|
||||
static inline void iwl_nvm_fill_read(struct iwl_nvm_access_cmd *cmd,
|
||||
u16 offset, u16 length, u16 section)
|
||||
{
|
||||
cmd->offset = cpu_to_le16(offset);
|
||||
cmd->length = cpu_to_le16(length);
|
||||
|
@ -106,8 +88,8 @@ static inline void iwl_nvm_fill_read_ver2(struct iwl_nvm_access_cmd_ver2 *cmd,
|
|||
static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section,
|
||||
u16 offset, u16 length, u8 *data)
|
||||
{
|
||||
union iwl_nvm_access_cmd nvm_access_cmd;
|
||||
union iwl_nvm_access_resp *nvm_resp;
|
||||
struct iwl_nvm_access_cmd nvm_access_cmd = {};
|
||||
struct iwl_nvm_access_resp *nvm_resp;
|
||||
struct iwl_rx_packet *pkt;
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = NVM_ACCESS_CMD,
|
||||
|
@ -117,18 +99,8 @@ static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section,
|
|||
int ret, bytes_read, offset_read;
|
||||
u8 *resp_data;
|
||||
|
||||
memset(&nvm_access_cmd, 0, sizeof(nvm_access_cmd));
|
||||
|
||||
/* TODO: not sure family should be the decider, maybe FW version? */
|
||||
if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
|
||||
iwl_nvm_fill_read_ver2(&(nvm_access_cmd.ver2),
|
||||
offset, length, section);
|
||||
cmd.len[0] = sizeof(struct iwl_nvm_access_cmd_ver2);
|
||||
} else {
|
||||
iwl_nvm_fill_read_ver1(&(nvm_access_cmd.ver1),
|
||||
offset, length);
|
||||
cmd.len[0] = sizeof(struct iwl_nvm_access_cmd_ver1);
|
||||
}
|
||||
iwl_nvm_fill_read(&nvm_access_cmd, offset, length, section);
|
||||
cmd.len[0] = sizeof(struct iwl_nvm_access_cmd);
|
||||
|
||||
ret = iwl_mvm_send_cmd(mvm, &cmd);
|
||||
if (ret)
|
||||
|
@ -144,17 +116,10 @@ static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section,
|
|||
|
||||
/* Extract NVM response */
|
||||
nvm_resp = (void *)pkt->data;
|
||||
if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
|
||||
ret = le16_to_cpu(nvm_resp->ver2.status);
|
||||
bytes_read = le16_to_cpu(nvm_resp->ver2.length);
|
||||
offset_read = le16_to_cpu(nvm_resp->ver2.offset);
|
||||
resp_data = nvm_resp->ver2.data;
|
||||
} else {
|
||||
ret = le16_to_cpu(nvm_resp->ver1.length) <= 0;
|
||||
bytes_read = le16_to_cpu(nvm_resp->ver1.length);
|
||||
offset_read = le16_to_cpu(nvm_resp->ver1.offset);
|
||||
resp_data = nvm_resp->ver1.data;
|
||||
}
|
||||
ret = le16_to_cpu(nvm_resp->status);
|
||||
bytes_read = le16_to_cpu(nvm_resp->length);
|
||||
offset_read = le16_to_cpu(nvm_resp->offset);
|
||||
resp_data = nvm_resp->data;
|
||||
if (ret) {
|
||||
IWL_ERR(mvm,
|
||||
"NVM access command failed with status %d (device: %s)\n",
|
||||
|
@ -194,17 +159,10 @@ static int iwl_nvm_read_section(struct iwl_mvm *mvm, u16 section,
|
|||
{
|
||||
u16 length, offset = 0;
|
||||
int ret;
|
||||
bool old_eeprom = mvm->cfg->device_family != IWL_DEVICE_FAMILY_7000;
|
||||
|
||||
/* Set nvm section read length */
|
||||
length = IWL_NVM_DEFAULT_CHUNK_SIZE;
|
||||
|
||||
/*
|
||||
* if length is greater than EEPROM size, truncate it because uCode
|
||||
* doesn't check it by itself, and exit the loop when reached.
|
||||
*/
|
||||
if (old_eeprom && length > mvm->cfg->base_params->eeprom_size)
|
||||
length = mvm->cfg->base_params->eeprom_size;
|
||||
ret = length;
|
||||
|
||||
/* Read the NVM until exhausted (reading less than requested) */
|
||||
|
@ -217,8 +175,6 @@ static int iwl_nvm_read_section(struct iwl_mvm *mvm, u16 section,
|
|||
return ret;
|
||||
}
|
||||
offset += ret;
|
||||
if (old_eeprom && offset == mvm->cfg->base_params->eeprom_size)
|
||||
break;
|
||||
}
|
||||
|
||||
IWL_INFO(mvm, "NVM section %d read completed\n", section);
|
||||
|
@ -252,63 +208,31 @@ int iwl_nvm_init(struct iwl_mvm *mvm)
|
|||
int ret, i, section;
|
||||
u8 *nvm_buffer, *temp;
|
||||
|
||||
if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
|
||||
/* TODO: find correct NVM max size for a section */
|
||||
nvm_buffer = kmalloc(mvm->cfg->base_params->eeprom_size,
|
||||
GFP_KERNEL);
|
||||
if (!nvm_buffer)
|
||||
return -ENOMEM;
|
||||
for (i = 0; i < ARRAY_SIZE(nvm_to_read); i++) {
|
||||
section = nvm_to_read[i];
|
||||
/* we override the constness for initial read */
|
||||
ret = iwl_nvm_read_section(mvm, section, nvm_buffer);
|
||||
if (ret < 0)
|
||||
break;
|
||||
temp = kmemdup(nvm_buffer, ret, GFP_KERNEL);
|
||||
if (!temp) {
|
||||
ret = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
mvm->nvm_sections[section].data = temp;
|
||||
mvm->nvm_sections[section].length = ret;
|
||||
}
|
||||
kfree(nvm_buffer);
|
||||
/* TODO: find correct NVM max size for a section */
|
||||
nvm_buffer = kmalloc(mvm->cfg->base_params->eeprom_size,
|
||||
GFP_KERNEL);
|
||||
if (!nvm_buffer)
|
||||
return -ENOMEM;
|
||||
for (i = 0; i < ARRAY_SIZE(nvm_to_read); i++) {
|
||||
section = nvm_to_read[i];
|
||||
/* we override the constness for initial read */
|
||||
ret = iwl_nvm_read_section(mvm, section, nvm_buffer);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} else {
|
||||
/* allocate eeprom */
|
||||
mvm->eeprom_blob_size = mvm->cfg->base_params->eeprom_size;
|
||||
IWL_DEBUG_EEPROM(mvm->trans->dev, "NVM size = %zd\n",
|
||||
mvm->eeprom_blob_size);
|
||||
mvm->eeprom_blob = kzalloc(mvm->eeprom_blob_size, GFP_KERNEL);
|
||||
if (!mvm->eeprom_blob)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = iwl_nvm_read_section(mvm, 0, mvm->eeprom_blob);
|
||||
if (ret != mvm->eeprom_blob_size) {
|
||||
IWL_ERR(mvm, "Read partial NVM %d/%zd\n",
|
||||
ret, mvm->eeprom_blob_size);
|
||||
kfree(mvm->eeprom_blob);
|
||||
mvm->eeprom_blob = NULL;
|
||||
return -EINVAL;
|
||||
break;
|
||||
temp = kmemdup(nvm_buffer, ret, GFP_KERNEL);
|
||||
if (!temp) {
|
||||
ret = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
mvm->nvm_sections[section].data = temp;
|
||||
mvm->nvm_sections[section].length = ret;
|
||||
}
|
||||
kfree(nvm_buffer);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = 0;
|
||||
if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000)
|
||||
mvm->nvm_data = iwl_parse_nvm_sections(mvm);
|
||||
else
|
||||
mvm->nvm_data =
|
||||
iwl_parse_eeprom_data(mvm->trans->dev,
|
||||
mvm->cfg,
|
||||
mvm->eeprom_blob,
|
||||
mvm->eeprom_blob_size);
|
||||
|
||||
if (!mvm->nvm_data) {
|
||||
kfree(mvm->eeprom_blob);
|
||||
mvm->eeprom_blob = NULL;
|
||||
ret = -ENOMEM;
|
||||
}
|
||||
mvm->nvm_data = iwl_parse_nvm_sections(mvm);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -143,21 +143,12 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode)
|
|||
u8 radio_cfg_type, radio_cfg_step, radio_cfg_dash;
|
||||
u32 reg_val = 0;
|
||||
|
||||
/*
|
||||
* We can't upload the correct value to the INIT image
|
||||
* as we don't have nvm_data by that time.
|
||||
*
|
||||
* TODO: Figure out what we should do here
|
||||
*/
|
||||
if (mvm->nvm_data) {
|
||||
radio_cfg_type = mvm->nvm_data->radio_cfg_type;
|
||||
radio_cfg_step = mvm->nvm_data->radio_cfg_step;
|
||||
radio_cfg_dash = mvm->nvm_data->radio_cfg_dash;
|
||||
} else {
|
||||
radio_cfg_type = 0;
|
||||
radio_cfg_step = 0;
|
||||
radio_cfg_dash = 0;
|
||||
}
|
||||
radio_cfg_type = (mvm->fw->phy_config & FW_PHY_CFG_RADIO_TYPE) >>
|
||||
FW_PHY_CFG_RADIO_TYPE_POS;
|
||||
radio_cfg_step = (mvm->fw->phy_config & FW_PHY_CFG_RADIO_STEP) >>
|
||||
FW_PHY_CFG_RADIO_STEP_POS;
|
||||
radio_cfg_dash = (mvm->fw->phy_config & FW_PHY_CFG_RADIO_DASH) >>
|
||||
FW_PHY_CFG_RADIO_DASH_POS;
|
||||
|
||||
/* SKU control */
|
||||
reg_val |= CSR_HW_REV_STEP(mvm->trans->hw_rev) <<
|
||||
|
@ -175,7 +166,6 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode)
|
|||
|
||||
/* silicon bits */
|
||||
reg_val |= CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI;
|
||||
reg_val |= CSR_HW_IF_CONFIG_REG_BIT_MAC_SI;
|
||||
|
||||
iwl_trans_set_bits_mask(mvm->trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH |
|
||||
|
@ -231,6 +221,7 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
|
|||
RX_HANDLER(SCAN_COMPLETE_NOTIFICATION, iwl_mvm_rx_scan_complete, false),
|
||||
|
||||
RX_HANDLER(BT_PROFILE_NOTIFICATION, iwl_mvm_rx_bt_coex_notif, true),
|
||||
RX_HANDLER(BEACON_NOTIFICATION, iwl_mvm_rx_beacon_notif, false),
|
||||
|
||||
RX_HANDLER(RADIO_VERSION_NOTIFICATION, iwl_mvm_rx_radio_ver, false),
|
||||
RX_HANDLER(CARD_STATE_NOTIFICATION, iwl_mvm_rx_card_state_notif, false),
|
||||
|
@ -276,6 +267,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = {
|
|||
CMD(WEP_KEY),
|
||||
CMD(REPLY_RX_PHY_CMD),
|
||||
CMD(REPLY_RX_MPDU_CMD),
|
||||
CMD(BEACON_NOTIFICATION),
|
||||
CMD(BEACON_TEMPLATE_CMD),
|
||||
CMD(STATISTICS_NOTIFICATION),
|
||||
CMD(TX_ANT_CONFIGURATION_CMD),
|
||||
|
@ -319,16 +311,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
|||
};
|
||||
int err, scan_size;
|
||||
|
||||
switch (cfg->device_family) {
|
||||
case IWL_DEVICE_FAMILY_6030:
|
||||
case IWL_DEVICE_FAMILY_6005:
|
||||
case IWL_DEVICE_FAMILY_7000:
|
||||
break;
|
||||
default:
|
||||
IWL_ERR(trans, "Trying to load mvm on an unsupported device\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/********************************
|
||||
* 1. Allocating and configuring HW data
|
||||
********************************/
|
||||
|
@ -444,7 +426,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
|||
out_free:
|
||||
iwl_phy_db_free(mvm->phy_db);
|
||||
kfree(mvm->scan_cmd);
|
||||
kfree(mvm->eeprom_blob);
|
||||
iwl_trans_stop_hw(trans, true);
|
||||
ieee80211_free_hw(mvm->hw);
|
||||
return NULL;
|
||||
|
@ -466,7 +447,6 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
|
|||
iwl_phy_db_free(mvm->phy_db);
|
||||
mvm->phy_db = NULL;
|
||||
|
||||
kfree(mvm->eeprom_blob);
|
||||
iwl_free_nvm_data(mvm->nvm_data);
|
||||
for (i = 0; i < NVM_NUM_OF_SECTIONS; i++)
|
||||
kfree(mvm->nvm_sections[i].data);
|
||||
|
|
|
@ -142,7 +142,7 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm,
|
|||
struct cfg80211_chan_def *chandef,
|
||||
u8 chains_static, u8 chains_dynamic)
|
||||
{
|
||||
u8 valid_rx_chains, active_cnt, idle_cnt;
|
||||
u8 active_cnt, idle_cnt;
|
||||
|
||||
/* Set the channel info data */
|
||||
cmd->ci.band = (chandef->chan->band == IEEE80211_BAND_2GHZ ?
|
||||
|
@ -158,17 +158,16 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm,
|
|||
* Need to add on chain noise calibration limitations, and
|
||||
* BT coex considerations.
|
||||
*/
|
||||
valid_rx_chains = mvm->nvm_data->valid_rx_ant;
|
||||
idle_cnt = chains_static;
|
||||
active_cnt = chains_dynamic;
|
||||
|
||||
cmd->rxchain_info = cpu_to_le32(valid_rx_chains <<
|
||||
cmd->rxchain_info = cpu_to_le32(iwl_fw_valid_rx_ant(mvm->fw) <<
|
||||
PHY_RX_CHAIN_VALID_POS);
|
||||
cmd->rxchain_info |= cpu_to_le32(idle_cnt << PHY_RX_CHAIN_CNT_POS);
|
||||
cmd->rxchain_info |= cpu_to_le32(active_cnt <<
|
||||
PHY_RX_CHAIN_MIMO_CNT_POS);
|
||||
|
||||
cmd->txchain_info = cpu_to_le32(mvm->nvm_data->valid_tx_ant);
|
||||
cmd->txchain_info = cpu_to_le32(iwl_fw_valid_tx_ant(mvm->fw));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -114,7 +114,8 @@ static void iwl_mvm_quota_iterator(void *_data, u8 *mac,
|
|||
data->n_interfaces[id]++;
|
||||
break;
|
||||
case NL80211_IFTYPE_MONITOR:
|
||||
data->n_interfaces[id]++;
|
||||
if (mvmvif->monitor_active)
|
||||
data->n_interfaces[id]++;
|
||||
break;
|
||||
case NL80211_IFTYPE_P2P_DEVICE:
|
||||
break;
|
||||
|
|
|
@ -74,7 +74,7 @@
|
|||
static inline __le16 iwl_mvm_scan_rx_chain(struct iwl_mvm *mvm)
|
||||
{
|
||||
u16 rx_chain;
|
||||
u8 rx_ant = mvm->nvm_data->valid_rx_ant;
|
||||
u8 rx_ant = iwl_fw_valid_rx_ant(mvm->fw);
|
||||
|
||||
rx_chain = rx_ant << PHY_RX_CHAIN_VALID_POS;
|
||||
rx_chain |= rx_ant << PHY_RX_CHAIN_FORCE_MIMO_SEL_POS;
|
||||
|
@ -115,7 +115,7 @@ iwl_mvm_scan_rate_n_flags(struct iwl_mvm *mvm, enum ieee80211_band band,
|
|||
u32 tx_ant;
|
||||
|
||||
mvm->scan_last_antenna_idx =
|
||||
iwl_mvm_next_antenna(mvm, mvm->nvm_data->valid_tx_ant,
|
||||
iwl_mvm_next_antenna(mvm, iwl_fw_valid_tx_ant(mvm->fw),
|
||||
mvm->scan_last_antenna_idx);
|
||||
tx_ant = BIT(mvm->scan_last_antenna_idx) << RATE_MCS_ANT_POS;
|
||||
|
||||
|
|
|
@ -76,14 +76,12 @@
|
|||
#define TU_TO_JIFFIES(_tu) (usecs_to_jiffies((_tu) * 1024))
|
||||
#define MSEC_TO_TU(_msec) (_msec*1000/1024)
|
||||
|
||||
/* For ROC use a TE type which has priority high enough to be scheduled when
|
||||
* there is a concurrent BSS or GO/AP. Currently, use a TE type that has
|
||||
* priority similar to the TE priority used for action scans by the FW.
|
||||
* TODO: This needs to be changed, based on the reason for the ROC, i.e., use
|
||||
* TE_P2P_DEVICE_DISCOVERABLE for remain on channel without mgmt skb, and use
|
||||
* TE_P2P_DEVICE_ACTION_SCAN
|
||||
/*
|
||||
* For the high priority TE use a time event type that has similar priority to
|
||||
* the FW's action scan priority.
|
||||
*/
|
||||
#define IWL_MVM_ROC_TE_TYPE TE_P2P_DEVICE_ACTION_SCAN
|
||||
#define IWL_MVM_ROC_TE_TYPE_NORMAL TE_P2P_DEVICE_DISCOVERABLE
|
||||
#define IWL_MVM_ROC_TE_TYPE_MGMT_TX TE_P2P_CLIENT_ASSOC
|
||||
|
||||
void iwl_mvm_te_clear_data(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_time_event_data *te_data)
|
||||
|
@ -116,7 +114,7 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk)
|
|||
* issue as it will have to complete before the next command is
|
||||
* executed, and a new time event means a new command.
|
||||
*/
|
||||
iwl_mvm_flush_tx_path(mvm, BIT(IWL_OFFCHANNEL_QUEUE), false);
|
||||
iwl_mvm_flush_tx_path(mvm, BIT(IWL_MVM_OFFCHANNEL_QUEUE), false);
|
||||
}
|
||||
|
||||
static void iwl_mvm_roc_finished(struct iwl_mvm *mvm)
|
||||
|
@ -438,7 +436,7 @@ void iwl_mvm_stop_session_protection(struct iwl_mvm *mvm,
|
|||
}
|
||||
|
||||
int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
int duration)
|
||||
int duration, enum ieee80211_roc_type type)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data;
|
||||
|
@ -459,21 +457,29 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
time_cmd.action = cpu_to_le32(FW_CTXT_ACTION_ADD);
|
||||
time_cmd.id_and_color =
|
||||
cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color));
|
||||
time_cmd.id = cpu_to_le32(IWL_MVM_ROC_TE_TYPE);
|
||||
|
||||
switch (type) {
|
||||
case IEEE80211_ROC_TYPE_NORMAL:
|
||||
time_cmd.id = cpu_to_le32(IWL_MVM_ROC_TE_TYPE_NORMAL);
|
||||
break;
|
||||
case IEEE80211_ROC_TYPE_MGMT_TX:
|
||||
time_cmd.id = cpu_to_le32(IWL_MVM_ROC_TE_TYPE_MGMT_TX);
|
||||
break;
|
||||
default:
|
||||
WARN_ONCE(1, "Got an invalid ROC type\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
time_cmd.apply_time = cpu_to_le32(0);
|
||||
time_cmd.dep_policy = cpu_to_le32(TE_INDEPENDENT);
|
||||
time_cmd.is_present = cpu_to_le32(1);
|
||||
|
||||
time_cmd.interval = cpu_to_le32(1);
|
||||
|
||||
/*
|
||||
* IWL_MVM_ROC_TE_TYPE can have lower priority than other events
|
||||
* The P2P Device TEs can have lower priority than other events
|
||||
* that are being scheduled by the driver/fw, and thus it might not be
|
||||
* scheduled. To improve the chances of it being scheduled, allow it to
|
||||
* be fragmented.
|
||||
* In addition, for the same reasons, allow to delay the scheduling of
|
||||
* the time event.
|
||||
* scheduled. To improve the chances of it being scheduled, allow them
|
||||
* to be fragmented, and in addition allow them to be delayed.
|
||||
*/
|
||||
time_cmd.max_frags = cpu_to_le32(MSEC_TO_TU(duration)/20);
|
||||
time_cmd.max_delay = cpu_to_le32(MSEC_TO_TU(duration/2));
|
||||
|
|
|
@ -162,6 +162,7 @@ int iwl_mvm_rx_time_event_notif(struct iwl_mvm *mvm,
|
|||
* that the vif type is NL80211_IFTYPE_P2P_DEVICE
|
||||
* @duration: the requested duration in millisecond for the fw to be on the
|
||||
* channel that is bound to the vif.
|
||||
* @type: the remain on channel request type
|
||||
*
|
||||
* This function can be used to issue a remain on channel session,
|
||||
* which means that the fw will stay in the channel for the request %duration
|
||||
|
@ -172,7 +173,7 @@ int iwl_mvm_rx_time_event_notif(struct iwl_mvm *mvm,
|
|||
* another notification to the driver.
|
||||
*/
|
||||
int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
int duration);
|
||||
int duration, enum ieee80211_roc_type type);
|
||||
|
||||
/**
|
||||
* iwl_mvm_stop_p2p_roc - stop remain on channel for p2p device functionlity
|
||||
|
|
|
@ -417,7 +417,7 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
|
|||
spin_unlock(&mvmsta->lock);
|
||||
|
||||
if (mvmsta->vif->type == NL80211_IFTYPE_AP &&
|
||||
txq_id < IWL_FIRST_AMPDU_QUEUE)
|
||||
txq_id < IWL_MVM_FIRST_AGG_QUEUE)
|
||||
atomic_inc(&mvmsta->pending_frames);
|
||||
|
||||
return 0;
|
||||
|
@ -606,7 +606,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
|
|||
info);
|
||||
|
||||
/* Single frame failure in an AMPDU queue => send BAR */
|
||||
if (txq_id >= IWL_FIRST_AMPDU_QUEUE &&
|
||||
if (txq_id >= IWL_MVM_FIRST_AGG_QUEUE &&
|
||||
!(info->flags & IEEE80211_TX_STAT_ACK))
|
||||
info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
|
||||
|
||||
|
@ -619,7 +619,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
|
|||
ieee80211_tx_status_ni(mvm->hw, skb);
|
||||
}
|
||||
|
||||
if (txq_id >= IWL_FIRST_AMPDU_QUEUE) {
|
||||
if (txq_id >= IWL_MVM_FIRST_AGG_QUEUE) {
|
||||
/* If this is an aggregation queue, we use the ssn since:
|
||||
* ssn = wifi seq_num % 256.
|
||||
* The seq_ctl is the sequence control of the packet to which
|
||||
|
@ -681,7 +681,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
|
|||
* If there are no pending frames for this STA, notify mac80211 that
|
||||
* this station can go to sleep in its STA table.
|
||||
*/
|
||||
if (txq_id < IWL_FIRST_AMPDU_QUEUE && mvmsta &&
|
||||
if (txq_id < IWL_MVM_FIRST_AGG_QUEUE && mvmsta &&
|
||||
!WARN_ON(skb_freed > 1) &&
|
||||
mvmsta->vif->type == NL80211_IFTYPE_AP &&
|
||||
atomic_sub_and_test(skb_freed, &mvmsta->pending_frames)) {
|
||||
|
@ -750,7 +750,7 @@ static void iwl_mvm_rx_tx_cmd_agg(struct iwl_mvm *mvm,
|
|||
u16 sequence = le16_to_cpu(pkt->hdr.sequence);
|
||||
struct ieee80211_sta *sta;
|
||||
|
||||
if (WARN_ON_ONCE(SEQ_TO_QUEUE(sequence) < IWL_FIRST_AMPDU_QUEUE))
|
||||
if (WARN_ON_ONCE(SEQ_TO_QUEUE(sequence) < IWL_MVM_FIRST_AGG_QUEUE))
|
||||
return;
|
||||
|
||||
if (WARN_ON_ONCE(tid == IWL_TID_NON_QOS))
|
||||
|
|
|
@ -1566,8 +1566,11 @@ int iwl_trans_pcie_send_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
|
|||
if (test_bit(STATUS_FW_ERROR, &trans_pcie->status))
|
||||
return -EIO;
|
||||
|
||||
if (test_bit(STATUS_RFKILL, &trans_pcie->status))
|
||||
if (test_bit(STATUS_RFKILL, &trans_pcie->status)) {
|
||||
IWL_DEBUG_RF_KILL(trans, "Dropping CMD 0x%x: RF KILL\n",
|
||||
cmd->id);
|
||||
return -ERFKILL;
|
||||
}
|
||||
|
||||
if (cmd->flags & CMD_ASYNC)
|
||||
return iwl_pcie_send_hcmd_async(trans, cmd);
|
||||
|
|
Загрузка…
Ссылка в новой задаче