Commit 31c5770b authored by John W. Linville's avatar John W. Linville
parents c78b3841 e635c797
...@@ -1266,7 +1266,3 @@ module_param_named(auto_agg, iwlwifi_mod_params.auto_agg, ...@@ -1266,7 +1266,3 @@ module_param_named(auto_agg, iwlwifi_mod_params.auto_agg,
bool, S_IRUGO); bool, S_IRUGO);
MODULE_PARM_DESC(auto_agg, MODULE_PARM_DESC(auto_agg,
"enable agg w/o check traffic load (default: enable)"); "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 { ...@@ -154,6 +154,19 @@ struct iwl_tlv_calib_ctrl {
__le32 event_trigger; __le32 event_trigger;
} __packed; } __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 * struct iwl_fw - variables associated with the firmware
* *
...@@ -190,4 +203,16 @@ struct iwl_fw { ...@@ -190,4 +203,16 @@ struct iwl_fw {
bool mvm_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__ */ #endif /* __iwl_fw_h__ */
...@@ -103,7 +103,6 @@ enum iwl_power_level { ...@@ -103,7 +103,6 @@ enum iwl_power_level {
* @ant_coupling: antenna coupling in dB, default = 0 * @ant_coupling: antenna coupling in dB, default = 0
* @bt_ch_announce: BT channel inhibition, default = enable * @bt_ch_announce: BT channel inhibition, default = enable
* @auto_agg: enable agg. without check, default = true * @auto_agg: enable agg. without check, default = true
* @disable_5ghz: disable 5GHz capability, default = false
*/ */
struct iwl_mod_params { struct iwl_mod_params {
int sw_crypto; int sw_crypto;
...@@ -120,7 +119,6 @@ struct iwl_mod_params { ...@@ -120,7 +119,6 @@ struct iwl_mod_params {
int ant_coupling; int ant_coupling;
bool bt_ch_announce; bool bt_ch_announce;
bool auto_agg; bool auto_agg;
bool disable_5ghz;
}; };
#endif /* #__iwl_modparams_h__ */ #endif /* #__iwl_modparams_h__ */
...@@ -272,7 +272,7 @@ static int iwl_test_fw_cmd(struct iwl_test *tst, struct nlattr **tb) ...@@ -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; reply_len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
skb = iwl_test_alloc_reply(tst, reply_len + 20); 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) { if (!skb || !reply_buf) {
kfree_skb(skb); kfree_skb(skb);
kfree(reply_buf); kfree(reply_buf);
...@@ -280,7 +280,6 @@ static int iwl_test_fw_cmd(struct iwl_test *tst, struct nlattr **tb) ...@@ -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. */ /* The reply is in a page, that we cannot send to user space. */
memcpy(reply_buf, &(pkt->hdr), reply_len);
iwl_free_resp(&cmd); iwl_free_resp(&cmd);
if (nla_put_u32(skb, IWL_TM_ATTR_COMMAND, if (nla_put_u32(skb, IWL_TM_ATTR_COMMAND,
......
...@@ -125,15 +125,15 @@ enum iwl_bt_kill_msk { ...@@ -125,15 +125,15 @@ enum iwl_bt_kill_msk {
}; };
static const u32 iwl_bt_ack_kill_msk[BT_KILL_MSK_MAX] = { static const u32 iwl_bt_ack_kill_msk[BT_KILL_MSK_MAX] = {
0xffffffff, [BT_KILL_MSK_DEFAULT] = 0xffff0000,
0xfffffc00, [BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff,
0, [BT_KILL_MSK_REDUCED_TXPOW] = 0,
}; };
static const u32 iwl_bt_cts_kill_msk[BT_KILL_MSK_MAX] = { static const u32 iwl_bt_cts_kill_msk[BT_KILL_MSK_MAX] = {
0xffffffff, [BT_KILL_MSK_DEFAULT] = 0xffff0000,
0xfffffc00, [BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff,
0, [BT_KILL_MSK_REDUCED_TXPOW] = 0,
}; };
#define IWL_BT_DEFAULT_BOOST (0xf0f0f0f0) #define IWL_BT_DEFAULT_BOOST (0xf0f0f0f0)
...@@ -188,6 +188,8 @@ static const __le32 iwl_concurrent_lookup[BT_COEX_LUT_SIZE] = { ...@@ -188,6 +188,8 @@ static const __le32 iwl_concurrent_lookup[BT_COEX_LUT_SIZE] = {
/* BT Antenna Coupling Threshold (dB) */ /* BT Antenna Coupling Threshold (dB) */
#define IWL_BT_ANTENNA_COUPLING_THRESHOLD (35) #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) int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
{ {
...@@ -201,8 +203,7 @@ 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 ? cmd.flags = iwlwifi_mod_params.bt_coex_active ?
BT_COEX_NW : BT_COEX_DISABLE; BT_COEX_NW : BT_COEX_DISABLE;
cmd.flags |= iwlwifi_mod_params.bt_ch_announce ? cmd.flags |= iwlwifi_mod_params.bt_ch_announce ? BT_CH_PRIMARY_EN : 0;
BT_CH_PRIMARY_EN | BT_CH_SECONDARY_EN : 0;
cmd.flags |= BT_SYNC_2_BT_DISABLE; cmd.flags |= BT_SYNC_2_BT_DISABLE;
cmd.valid_bit_msk = cpu_to_le16(BT_VALID_ENABLE | 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, ...@@ -275,7 +276,7 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
if (data->notif->bt_status) if (data->notif->bt_status)
smps_mode = IEEE80211_SMPS_DYNAMIC; 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; smps_mode = IEEE80211_SMPS_STATIC;
IWL_DEBUG_COEX(data->mvm, IWL_DEBUG_COEX(data->mvm,
...@@ -327,7 +328,7 @@ int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm, ...@@ -327,7 +328,7 @@ int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
return 0; return 0;
IWL_DEBUG_COEX(mvm, 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_kill_msk,
BT_MBOX_MSG(notif, 3, SCO_STATE) ? "" : "in", BT_MBOX_MSG(notif, 3, SCO_STATE) ? "" : "in",
BT_MBOX_MSG(notif, 3, A2DP_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) ...@@ -866,17 +866,13 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
cpu_to_le32(IWL_WOWLAN_WAKEUP_PATTERN_MATCH); cpu_to_le32(IWL_WOWLAN_WAKEUP_PATTERN_MATCH);
if (wowlan->rfkill_release) if (wowlan->rfkill_release)
d3_cfg_cmd.wakeup_flags |= wowlan_config_cmd.wakeup_filter |=
cpu_to_le32(IWL_WOWLAN_WAKEUP_RF_KILL_DEASSERT); cpu_to_le32(IWL_WOWLAN_WAKEUP_RF_KILL_DEASSERT);
if (wowlan->tcp) { if (wowlan->tcp) {
/* /*
* The firmware currently doesn't really look at these, only * Set the "link change" (really "link lost") flag as well
* the IWL_WOWLAN_WAKEUP_LINK_CHANGE bit. We have to set that * since that implies losing the TCP connection.
* 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.
*/ */
wowlan_config_cmd.wakeup_filter |= wowlan_config_cmd.wakeup_filter |=
cpu_to_le32(IWL_WOWLAN_WAKEUP_REMOTE_LINK_LOSS | cpu_to_le32(IWL_WOWLAN_WAKEUP_REMOTE_LINK_LOSS |
......
...@@ -537,6 +537,12 @@ struct iwl_mac_beacon_cmd { ...@@ -537,6 +537,12 @@ struct iwl_mac_beacon_cmd {
struct ieee80211_hdr frame[0]; struct ieee80211_hdr frame[0];
} __packed; } __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 * enum iwl_dump_control - dump (flush) control flags
* @DUMP_TX_FIFO_FLUSH: Dump MSDUs until the the FIFO is empty * @DUMP_TX_FIFO_FLUSH: Dump MSDUs until the the FIFO is empty
......
...@@ -151,6 +151,7 @@ enum { ...@@ -151,6 +151,7 @@ enum {
SET_CALIB_DEFAULT_CMD = 0x8e, SET_CALIB_DEFAULT_CMD = 0x8e,
BEACON_NOTIFICATION = 0x90,
BEACON_TEMPLATE_CMD = 0x91, BEACON_TEMPLATE_CMD = 0x91,
TX_ANT_CONFIGURATION_CMD = 0x98, TX_ANT_CONFIGURATION_CMD = 0x98,
BT_CONFIG = 0x9b, BT_CONFIG = 0x9b,
...@@ -278,38 +279,7 @@ enum { ...@@ -278,38 +279,7 @@ enum {
NVM_ACCESS_TARGET_EEPROM = 2, NVM_ACCESS_TARGET_EEPROM = 2,
}; };
/** /* Section types for NVM_ACCESS_CMD */
* 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 */
enum { enum {
NVM_SECTION_TYPE_HW = 0, NVM_SECTION_TYPE_HW = 0,
NVM_SECTION_TYPE_SW, NVM_SECTION_TYPE_SW,
...@@ -330,7 +300,7 @@ enum { ...@@ -330,7 +300,7 @@ enum {
* @length: in bytes, to read/write * @length: in bytes, to read/write
* @data: if write operation, the data to write. On read its empty * @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 op_code;
u8 target; u8 target;
__le16 type; __le16 type;
...@@ -347,7 +317,7 @@ struct iwl_nvm_access_cmd_ver2 { ...@@ -347,7 +317,7 @@ struct iwl_nvm_access_cmd_ver2 {
* @status: 0 for success, fail otherwise * @status: 0 for success, fail otherwise
* @data: if read operation, the data returned. Empty on write. * @data: if read operation, the data returned. Empty on write.
*/ */
struct iwl_nvm_access_resp_ver2 { struct iwl_nvm_access_resp {
__le16 offset; __le16 offset;
__le16 length; __le16 length;
__le16 type; __le16 type;
......
...@@ -114,7 +114,7 @@ static int iwl_send_tx_ant_cfg(struct iwl_mvm *mvm, u8 valid_tx_ant) ...@@ -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), .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, return iwl_mvm_send_cmd_pdu(mvm, TX_ANT_CONFIGURATION_CMD, CMD_SYNC,
sizeof(tx_ant_cmd), &tx_ant_cmd); sizeof(tx_ant_cmd), &tx_ant_cmd);
} }
...@@ -134,9 +134,10 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait, ...@@ -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->scd_base_addr = le32_to_cpu(palive->scd_base_ptr);
alive_data->valid = le16_to_cpu(palive->status) == IWL_ALIVE_STATUS_OK; 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, le16_to_cpu(palive->status), palive->ver_type,
palive->ver_subtype); palive->ver_subtype, palive->flags);
return true; return true;
} }
...@@ -326,16 +327,14 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) ...@@ -326,16 +327,14 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
WARN_ON(ret); WARN_ON(ret);
/* Send TX valid antennas before triggering calibrations */ /* 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) if (ret)
goto error; goto error;
/* WkP doesn't have all calibrations, need to set default values */ /* need to set default values */
if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) { ret = iwl_set_default_calibrations(mvm);
ret = iwl_set_default_calibrations(mvm); if (ret)
if (ret) goto error;
goto error;
}
/* /*
* Send phy configurations command to init uCode * Send phy configurations command to init uCode
...@@ -414,7 +413,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm) ...@@ -414,7 +413,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
goto error; 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) if (ret)
goto error; goto error;
...@@ -468,7 +467,7 @@ int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm) ...@@ -468,7 +467,7 @@ int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm)
goto error; 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) if (ret)
goto error; goto error;
......
...@@ -196,7 +196,7 @@ u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm, ...@@ -196,7 +196,7 @@ u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm,
u32 qmask, ac; u32 qmask, ac;
if (vif->type == NL80211_IFTYPE_P2P_DEVICE) 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) ? qmask = (vif->cab_queue != IEEE80211_INVAL_HW_QUEUE) ?
BIT(vif->cab_queue) : 0; BIT(vif->cab_queue) : 0;
...@@ -692,7 +692,12 @@ static int iwl_mvm_mac_ctxt_cmd_listener(struct iwl_mvm *mvm, ...@@ -692,7 +692,12 @@ static int iwl_mvm_mac_ctxt_cmd_listener(struct iwl_mvm *mvm,
WARN_ON(vif->type != NL80211_IFTYPE_MONITOR); WARN_ON(vif->type != NL80211_IFTYPE_MONITOR);
iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action); 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); 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, ...@@ -798,7 +803,7 @@ static int iwl_mvm_mac_ctxt_send_beacon(struct iwl_mvm *mvm,
TX_CMD_FLG_TSF); TX_CMD_FLG_TSF);
mvm->mgmt_last_antenna_idx = 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); mvm->mgmt_last_antenna_idx);
beacon_cmd.tx.rate_n_flags = beacon_cmd.tx.rate_n_flags =
...@@ -1013,3 +1018,22 @@ int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif) ...@@ -1013,3 +1018,22 @@ int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
mvmvif->uploaded = false; mvmvif->uploaded = false;
return 0; 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) ...@@ -143,8 +143,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
IEEE80211_HW_AMPDU_AGGREGATION | IEEE80211_HW_AMPDU_AGGREGATION |
IEEE80211_HW_TIMING_BEACON_ONLY; IEEE80211_HW_TIMING_BEACON_ONLY;
hw->queues = IWL_FIRST_AMPDU_QUEUE; hw->queues = IWL_MVM_FIRST_AGG_QUEUE;
hw->offchannel_tx_hw_queue = IWL_OFFCHANNEL_QUEUE; hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE;
hw->rate_control_algorithm = "iwl-mvm-rs"; hw->rate_control_algorithm = "iwl-mvm-rs";
/* /*
...@@ -174,7 +174,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) ...@@ -174,7 +174,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
hw->wiphy->n_iface_combinations = hw->wiphy->n_iface_combinations =
ARRAY_SIZE(iwl_mvm_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; hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL;
/* Extract MAC address */ /* Extract MAC address */
...@@ -257,7 +257,7 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw, ...@@ -257,7 +257,7 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
goto drop; 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)) !test_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status))
goto drop; goto drop;
...@@ -1087,6 +1087,13 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw, ...@@ -1087,6 +1087,13 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
switch (cmd) { switch (cmd) {
case SET_KEY: 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"); IWL_DEBUG_MAC80211(mvm, "set hwcrypto key\n");
ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, false); ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, false);
if (ret) { if (ret) {
...@@ -1095,11 +1102,17 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw, ...@@ -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 * can't add key for RX, but we don't need it
* in the device for TX so still return 0 * in the device for TX so still return 0
*/ */
key->hw_key_idx = STA_KEY_IDX_INVALID;
ret = 0; ret = 0;
} }
break; break;
case DISABLE_KEY: case DISABLE_KEY:
if (key->hw_key_idx == STA_KEY_IDX_INVALID) {
ret = 0;
break;
}
IWL_DEBUG_MAC80211(mvm, "disable hwcrypto key\n"); IWL_DEBUG_MAC80211(mvm, "disable hwcrypto key\n");
ret = iwl_mvm_remove_sta_key(mvm, vif, sta, key); ret = iwl_mvm_remove_sta_key(mvm, vif, sta, key);
break; break;
...@@ -1148,7 +1161,7 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw, ...@@ -1148,7 +1161,7 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
&chandef, 1, 1); &chandef, 1, 1);
/* Schedule the time events */ /* 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); mutex_unlock(&mvm->mutex);
IWL_DEBUG_MAC80211(mvm, "leave\n"); IWL_DEBUG_MAC80211(mvm, "leave\n");
...@@ -1252,6 +1265,7 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw, ...@@ -1252,6 +1265,7 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw,
* will handle quota settings. * will handle quota settings.
*/ */
if (vif->type == NL80211_IFTYPE_MONITOR) { if (vif->type == NL80211_IFTYPE_MONITOR) {
mvmvif->monitor_active = true;
ret = iwl_mvm_update_quotas(mvm, vif); ret = iwl_mvm_update_quotas(mvm, vif);
if (ret) if (ret)
goto out_remove_binding; goto out_remove_binding;
...@@ -1282,15 +1296,16 @@ static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw, ...@@ -1282,15 +1296,16 @@ static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw,
if (vif->type == NL80211_IFTYPE_AP) if (vif->type == NL80211_IFTYPE_AP)
goto out_unlock; goto out_unlock;
iwl_mvm_binding_remove_vif(mvm, vif);
switch (vif->type) { switch (vif->type) {
case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_MONITOR:
iwl_mvm_update_quotas(mvm, vif); mvmvif->monitor_active = false;
iwl_mvm_update_quotas(mvm, NULL);
break; break;
default: default:
break; break;
} }
iwl_mvm_binding_remove_vif(mvm, vif);
out_unlock: out_unlock:
mvmvif->phy_ctxt = NULL; mvmvif->phy_ctxt = NULL;
mutex_unlock(&mvm->mutex); mutex_unlock(&mvm->mutex);
......
...@@ -90,10 +90,6 @@ enum iwl_mvm_tx_fifo { ...@@ -90,10 +90,6 @@ enum iwl_mvm_tx_fifo {
IWL_MVM_TX_FIFO_VO, 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; extern struct ieee80211_ops iwl_mvm_hw_ops;
/** /**
* struct iwl_mvm_mod_params - module parameters for iwlmvm * struct iwl_mvm_mod_params - module parameters for iwlmvm
...@@ -161,6 +157,8 @@ enum iwl_power_scheme { ...@@ -161,6 +157,8 @@ enum iwl_power_scheme {
* @uploaded: indicates the MAC context has been added to the device * @uploaded: indicates the MAC context has been added to the device
* @ap_active: indicates that ap context is configured, and that the interface * @ap_active: indicates that ap context is configured, and that the interface
* should get quota etc. * 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 * @queue_params: QoS params for this MAC
* @bcast_sta: station used for broadcast packets. Used by the following * @bcast_sta: station used for broadcast packets. Used by the following
* vifs: P2P_DEVICE, GO and AP. * vifs: P2P_DEVICE, GO and AP.
...@@ -173,6 +171,7 @@ struct iwl_mvm_vif { ...@@ -173,6 +171,7 @@ struct iwl_mvm_vif {
bool uploaded; bool uploaded;
bool ap_active; bool ap_active;
bool monitor_active;
u32 ap_beacon_time; u32 ap_beacon_time;
...@@ -281,10 +280,7 @@ struct iwl_mvm { ...@@ -281,10 +280,7 @@ struct iwl_mvm {
atomic_t queue_stop_count[IWL_MAX_HW_QUEUES]; atomic_t queue_stop_count[IWL_MAX_HW_QUEUES];
struct iwl_nvm_data *nvm_data; struct iwl_nvm_data *nvm_data;
/* eeprom blob for debugfs/testmode */ /* NVM sections */
u8 *eeprom_blob;
size_t eeprom_blob_size;
/* NVM sections for 7000 family */
struct iwl_nvm_section nvm_sections[NVM_NUM_OF_SECTIONS]; struct iwl_nvm_section nvm_sections[NVM_NUM_OF_SECTIONS];
/* EEPROM MAC addresses */ /* EEPROM MAC addresses */
...@@ -451,6 +447,9 @@ u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm, ...@@ -451,6 +447,9 @@ u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm,
struct ieee80211_vif *vif); struct ieee80211_vif *vif);
int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm, int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm,
struct ieee80211_vif *vif); 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 */ /* Bindings */
int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif); int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
......
...@@ -77,26 +77,8 @@ static const int nvm_to_read[] = { ...@@ -77,26 +77,8 @@ static const int nvm_to_read[] = {
/* Default NVM size to read */ /* Default NVM size to read */
#define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024); #define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024);
/* used to simplify the shared operations on NCM_ACCESS_CMD versions */ static inline void iwl_nvm_fill_read(struct iwl_nvm_access_cmd *cmd,
union iwl_nvm_access_cmd { u16 offset, u16 length, u16 section)
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)
{ {
cmd->offset = cpu_to_le16(offset); cmd->offset = cpu_to_le16(offset);
cmd->length = cpu_to_le16(length); 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, ...@@ -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, static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section,
u16 offset, u16 length, u8 *data) u16 offset, u16 length, u8 *data)
{ {
union iwl_nvm_access_cmd nvm_access_cmd; struct iwl_nvm_access_cmd nvm_access_cmd = {};
union iwl_nvm_access_resp *nvm_resp; struct iwl_nvm_access_resp *nvm_resp;
struct iwl_rx_packet *pkt; struct iwl_rx_packet *pkt;
struct iwl_host_cmd cmd = { struct iwl_host_cmd cmd = {
.id = NVM_ACCESS_CMD, .id = NVM_ACCESS_CMD,
...@@ -117,18 +99,8 @@ static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section, ...@@ -117,18 +99,8 @@ static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section,
int ret, bytes_read, offset_read; int ret, bytes_read, offset_read;
u8 *resp_data; u8 *resp_data;
memset(&nvm_access_cmd, 0, sizeof(nvm_access_cmd)); iwl_nvm_fill_read(&nvm_access_cmd, offset, length, section);
cmd.len[0] = sizeof(struct iwl_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);
}
ret = iwl_mvm_send_cmd(mvm, &cmd); ret = iwl_mvm_send_cmd(mvm, &cmd);
if (ret) if (ret)
...@@ -144,17 +116,10 @@ static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section, ...@@ -144,17 +116,10 @@ static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section,
/* Extract NVM response */ /* Extract NVM response */
nvm_resp = (void *)pkt->data; nvm_resp = (void *)pkt->data;
if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) { ret = le16_to_cpu(nvm_resp->status);
ret = le16_to_cpu(nvm_resp->ver2.status); bytes_read = le16_to_cpu(nvm_resp->length);
bytes_read = le16_to_cpu(nvm_resp->ver2.length); offset_read = le16_to_cpu(nvm_resp->offset);
offset_read = le16_to_cpu(nvm_resp->ver2.offset); resp_data = nvm_resp->data;
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;
}
if (ret) { if (ret) {
IWL_ERR(mvm, IWL_ERR(mvm,
"NVM access command failed with status %d (device: %s)\n", "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, ...@@ -194,17 +159,10 @@ static int iwl_nvm_read_section(struct iwl_mvm *mvm, u16 section,
{ {
u16 length, offset = 0; u16 length, offset = 0;
int ret; int ret;
bool old_eeprom = mvm->cfg->device_family != IWL_DEVICE_FAMILY_7000;
/* Set nvm section read length */ /* Set nvm section read length */
length = IWL_NVM_DEFAULT_CHUNK_SIZE; 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; ret = length;
/* Read the NVM until exhausted (reading less than requested) */ /* 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, ...@@ -217,8 +175,6 @@ static int iwl_nvm_read_section(struct iwl_mvm *mvm, u16 section,
return ret; return ret;
} }
offset += ret; offset += ret;
if (old_eeprom && offset == mvm->cfg->base_params->eeprom_size)
break;
} }
IWL_INFO(mvm, "NVM section %d read completed\n", section); IWL_INFO(mvm, "NVM section %d read completed\n", section);
...@@ -252,63 +208,31 @@ int iwl_nvm_init(struct iwl_mvm *mvm) ...@@ -252,63 +208,31 @@ int iwl_nvm_init(struct iwl_mvm *mvm)
int ret, i, section; int ret, i, section;
u8 *nvm_buffer, *temp; u8 *nvm_buffer, *temp;
if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) { /* TODO: find correct NVM max size for a section */
/* TODO: find correct NVM max size for a section */ nvm_buffer = kmalloc(mvm->cfg->base_params->eeprom_size,
nvm_buffer = kmalloc(mvm->cfg->base_params->eeprom_size, GFP_KERNEL);
GFP_KERNEL); if (!nvm_buffer)
if (!nvm_buffer) return -ENOMEM;
return -ENOMEM; for (i = 0; i < ARRAY_SIZE(nvm_to_read); i++) {
for (i = 0; i < ARRAY_SIZE(nvm_to_read); i++) { section = nvm_to_read[i];
section = nvm_to_read[i]; /* we override the constness for initial read */
/* we override the constness for initial read */ ret = iwl_nvm_read_section(mvm, section, nvm_buffer);
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);
if (ret < 0) if (ret < 0)
return ret; break;
} else { temp = kmemdup(nvm_buffer, ret, GFP_KERNEL);
/* allocate eeprom */ if (!temp) {
mvm->eeprom_blob_size = mvm->cfg->base_params->eeprom_size; ret = -ENOMEM;
IWL_DEBUG_EEPROM(mvm->trans->dev, "NVM size = %zd\n", break;
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;
} }
mvm->nvm_sections[section].data = temp;
mvm->nvm_sections[section].length = ret;
} }
kfree(nvm_buffer);
if (ret < 0)
return ret;
ret = 0; ret = 0;
if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) mvm->nvm_data = iwl_parse_nvm_sections(mvm);
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;
}
return ret; return ret;
} }
...@@ -143,21 +143,12 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode) ...@@ -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; u8 radio_cfg_type, radio_cfg_step, radio_cfg_dash;
u32 reg_val = 0; u32 reg_val = 0;
/* radio_cfg_type = (mvm->fw->phy_config & FW_PHY_CFG_RADIO_TYPE) >>
* We can't upload the correct value to the INIT image FW_PHY_CFG_RADIO_TYPE_POS;
* as we don't have nvm_data by that time. radio_cfg_step = (mvm->fw->phy_config & FW_PHY_CFG_RADIO_STEP) >>
* FW_PHY_CFG_RADIO_STEP_POS;
* TODO: Figure out what we should do here radio_cfg_dash = (mvm->fw->phy_config & FW_PHY_CFG_RADIO_DASH) >>
*/ FW_PHY_CFG_RADIO_DASH_POS;
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;
}
/* SKU control */ /* SKU control */
reg_val |= CSR_HW_REV_STEP(mvm->trans->hw_rev) << 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) ...@@ -175,7 +166,6 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode)
/* silicon bits */ /* silicon bits */
reg_val |= CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI; 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, iwl_trans_set_bits_mask(mvm->trans, CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH | CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH |
...@@ -231,6 +221,7 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { ...@@ -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(SCAN_COMPLETE_NOTIFICATION, iwl_mvm_rx_scan_complete, false),
RX_HANDLER(BT_PROFILE_NOTIFICATION, iwl_mvm_rx_bt_coex_notif, true), 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(RADIO_VERSION_NOTIFICATION, iwl_mvm_rx_radio_ver, false),
RX_HANDLER(CARD_STATE_NOTIFICATION, iwl_mvm_rx_card_state_notif, 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] = { ...@@ -276,6 +267,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = {
CMD(WEP_KEY), CMD(WEP_KEY),
CMD(REPLY_RX_PHY_CMD), CMD(REPLY_RX_PHY_CMD),
CMD(REPLY_RX_MPDU_CMD), CMD(REPLY_RX_MPDU_CMD),
CMD(BEACON_NOTIFICATION),
CMD(BEACON_TEMPLATE_CMD), CMD(BEACON_TEMPLATE_CMD),
CMD(STATISTICS_NOTIFICATION), CMD(STATISTICS_NOTIFICATION),
CMD(TX_ANT_CONFIGURATION_CMD), CMD(TX_ANT_CONFIGURATION_CMD),
...@@ -319,16 +311,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, ...@@ -319,16 +311,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
}; };
int err, scan_size; 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 * 1. Allocating and configuring HW data
********************************/ ********************************/
...@@ -444,7 +426,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, ...@@ -444,7 +426,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
out_free: out_free:
iwl_phy_db_free(mvm->phy_db); iwl_phy_db_free(mvm->phy_db);
kfree(mvm->scan_cmd); kfree(mvm->scan_cmd);
kfree(mvm->eeprom_blob);
iwl_trans_stop_hw(trans, true); iwl_trans_stop_hw(trans, true);
ieee80211_free_hw(mvm->hw); ieee80211_free_hw(mvm->hw);
return NULL; return NULL;
...@@ -466,7 +447,6 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode) ...@@ -466,7 +447,6 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
iwl_phy_db_free(mvm->phy_db); iwl_phy_db_free(mvm->phy_db);
mvm->phy_db = NULL; mvm->phy_db = NULL;
kfree(mvm->eeprom_blob);
iwl_free_nvm_data(mvm->nvm_data); iwl_free_nvm_data(mvm->nvm_data);
for (i = 0; i < NVM_NUM_OF_SECTIONS; i++) for (i = 0; i < NVM_NUM_OF_SECTIONS; i++)
kfree(mvm->nvm_sections[i].data); kfree(mvm->nvm_sections[i].data);
......
...@@ -142,7 +142,7 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm, ...@@ -142,7 +142,7 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm,
struct cfg80211_chan_def *chandef, struct cfg80211_chan_def *chandef,
u8 chains_static, u8 chains_dynamic) u8 chains_static, u8 chains_dynamic)
{ {
u8 valid_rx_chains, active_cnt, idle_cnt; u8 active_cnt, idle_cnt;
/* Set the channel info data */ /* Set the channel info data */
cmd->ci.band = (chandef->chan->band == IEEE80211_BAND_2GHZ ? 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, ...@@ -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 * Need to add on chain noise calibration limitations, and
* BT coex considerations. * BT coex considerations.
*/ */
valid_rx_chains = mvm->nvm_data->valid_rx_ant;
idle_cnt = chains_static; idle_cnt = chains_static;
active_cnt = chains_dynamic; 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); PHY_RX_CHAIN_VALID_POS);
cmd->rxchain_info |= cpu_to_le32(idle_cnt << PHY_RX_CHAIN_CNT_POS); cmd->rxchain_info |= cpu_to_le32(idle_cnt << PHY_RX_CHAIN_CNT_POS);
cmd->rxchain_info |= cpu_to_le32(active_cnt << cmd->rxchain_info |= cpu_to_le32(active_cnt <<
PHY_RX_CHAIN_MIMO_CNT_POS); 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, ...@@ -114,7 +114,8 @@ static void iwl_mvm_quota_iterator(void *_data, u8 *mac,
data->n_interfaces[id]++; data->n_interfaces[id]++;
break; break;
case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_MONITOR:
data->n_interfaces[id]++; if (mvmvif->monitor_active)
data->n_interfaces[id]++;
break; break;
case NL80211_IFTYPE_P2P_DEVICE: case NL80211_IFTYPE_P2P_DEVICE:
break; break;
......
...@@ -74,7 +74,7 @@ ...@@ -74,7 +74,7 @@
static inline __le16 iwl_mvm_scan_rx_chain(struct iwl_mvm *mvm) static inline __le16 iwl_mvm_scan_rx_chain(struct iwl_mvm *mvm)
{ {
u16 rx_chain; 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_VALID_POS;
rx_chain |= rx_ant << PHY_RX_CHAIN_FORCE_MIMO_SEL_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, ...@@ -115,7 +115,7 @@ iwl_mvm_scan_rate_n_flags(struct iwl_mvm *mvm, enum ieee80211_band band,
u32 tx_ant; u32 tx_ant;
mvm->scan_last_antenna_idx = 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); mvm->scan_last_antenna_idx);
tx_ant = BIT(mvm->scan_last_antenna_idx) << RATE_MCS_ANT_POS; tx_ant = BIT(mvm->scan_last_antenna_idx) << RATE_MCS_ANT_POS;
......
...@@ -76,14 +76,12 @@ ...@@ -76,14 +76,12 @@
#define TU_TO_JIFFIES(_tu) (usecs_to_jiffies((_tu) * 1024)) #define TU_TO_JIFFIES(_tu) (usecs_to_jiffies((_tu) * 1024))
#define MSEC_TO_TU(_msec) (_msec*1000/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 * For the high priority TE use a time event type that has similar priority to
* priority similar to the TE priority used for action scans by the FW. * the FW's action scan priority.
* 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
*/ */
#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, void iwl_mvm_te_clear_data(struct iwl_mvm *mvm,
struct iwl_mvm_time_event_data *te_data) struct iwl_mvm_time_event_data *te_data)
...@@ -116,7 +114,7 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk) ...@@ -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 * issue as it will have to complete before the next command is
* executed, and a new time event means a new command. * 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) static void iwl_mvm_roc_finished(struct iwl_mvm *mvm)
...@@ -438,7 +436,7 @@ void iwl_mvm_stop_session_protection(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 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_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data; 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, ...@@ -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.action = cpu_to_le32(FW_CTXT_ACTION_ADD);
time_cmd.id_and_color = time_cmd.id_and_color =
cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->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.apply_time = cpu_to_le32(0);
time_cmd.dep_policy = cpu_to_le32(TE_INDEPENDENT); time_cmd.dep_policy = cpu_to_le32(TE_INDEPENDENT);
time_cmd.is_present = cpu_to_le32(1); time_cmd.is_present = cpu_to_le32(1);
time_cmd.interval = 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 * 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 * scheduled. To improve the chances of it being scheduled, allow them
* be fragmented. * to be fragmented, and in addition allow them to be delayed.
* In addition, for the same reasons, allow to delay the scheduling of
* the time event.
*/ */
time_cmd.max_frags = cpu_to_le32(MSEC_TO_TU(duration)/20); time_cmd.max_frags = cpu_to_le32(MSEC_TO_TU(duration)/20);
time_cmd.max_delay = cpu_to_le32(MSEC_TO_TU(duration/2)); 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, ...@@ -162,6 +162,7 @@ int iwl_mvm_rx_time_event_notif(struct iwl_mvm *mvm,
* that the vif type is NL80211_IFTYPE_P2P_DEVICE * that the vif type is NL80211_IFTYPE_P2P_DEVICE
* @duration: the requested duration in millisecond for the fw to be on the * @duration: the requested duration in millisecond for the fw to be on the
* channel that is bound to the vif. * 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, * 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 * 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, ...@@ -172,7 +173,7 @@ int iwl_mvm_rx_time_event_notif(struct iwl_mvm *mvm,
* another notification to the driver. * another notification to the driver.
*/ */
int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 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 * 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, ...@@ -417,7 +417,7 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
spin_unlock(&mvmsta->lock); spin_unlock(&mvmsta->lock);
if (mvmsta->vif->type == NL80211_IFTYPE_AP && 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); atomic_inc(&mvmsta->pending_frames);
return 0; return 0;
...@@ -606,7 +606,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, ...@@ -606,7 +606,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
info); info);
/* Single frame failure in an AMPDU queue => send BAR */ /* 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_ACK))
info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
...@@ -619,7 +619,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, ...@@ -619,7 +619,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
ieee80211_tx_status_ni(mvm->hw, skb); 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: /* If this is an aggregation queue, we use the ssn since:
* ssn = wifi seq_num % 256. * ssn = wifi seq_num % 256.
* The seq_ctl is the sequence control of the packet to which * 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, ...@@ -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 * If there are no pending frames for this STA, notify mac80211 that
* this station can go to sleep in its STA table. * 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) && !WARN_ON(skb_freed > 1) &&
mvmsta->vif->type == NL80211_IFTYPE_AP && mvmsta->vif->type == NL80211_IFTYPE_AP &&
atomic_sub_and_test(skb_freed, &mvmsta->pending_frames)) { 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, ...@@ -750,7 +750,7 @@ static void iwl_mvm_rx_tx_cmd_agg(struct iwl_mvm *mvm,
u16 sequence = le16_to_cpu(pkt->hdr.sequence); u16 sequence = le16_to_cpu(pkt->hdr.sequence);
struct ieee80211_sta *sta; 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; return;
if (WARN_ON_ONCE(tid == IWL_TID_NON_QOS)) 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) ...@@ -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)) if (test_bit(STATUS_FW_ERROR, &trans_pcie->status))
return -EIO; 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; return -ERFKILL;
}
if (cmd->flags & CMD_ASYNC) if (cmd->flags & CMD_ASYNC)
return iwl_pcie_send_hcmd_async(trans, cmd); return iwl_pcie_send_hcmd_async(trans, cmd);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment