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,
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) {
/* 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,25 +77,7 @@ 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,
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);
......@@ -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,7 +208,6 @@ 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);
......@@ -275,40 +230,9 @@ int iwl_nvm_init(struct iwl_mvm *mvm)
kfree(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;
}
}
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;
}
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,6 +114,7 @@ static void iwl_mvm_quota_iterator(void *_data, u8 *mac,
data->n_interfaces[id]++;
break;
case NL80211_IFTYPE_MONITOR:
if (mvmvif->monitor_active)
data->n_interfaces[id]++;
break;
case NL80211_IFTYPE_P2P_DEVICE:
......
......@@ -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);
......
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