Commit 7c79f1c9 authored by Kalle Valo's avatar Kalle Valo

Merge tag 'iwlwifi-next-for-kalle-2015-05-03' of...

Merge tag 'iwlwifi-next-for-kalle-2015-05-03' of https://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next

* major rework of the scan code (Luca)
* some work on the thermal code (Chaya Rachel)
* some work on the firwmare debugging infrastructure
parents 73b25f66 05c3274d
......@@ -21,6 +21,7 @@ config IWLWIFI
Intel 7260 Wi-Fi Adapter
Intel 3160 Wi-Fi Adapter
Intel 7265 Wi-Fi Adapter
Intel 8260 Wi-Fi Adapter
This driver uses the kernel's mac80211 subsystem.
......@@ -53,16 +54,17 @@ config IWLDVM
tristate "Intel Wireless WiFi DVM Firmware support"
default IWLWIFI
help
This is the driver that supports the DVM firmware which is
used by most existing devices (with the exception of 7260
and 3160).
This is the driver that supports the DVM firmware. The list
of the devices that use this firmware is available here:
https://wireless.wiki.kernel.org/en/users/drivers/iwlwifi#firmware
config IWLMVM
tristate "Intel Wireless WiFi MVM Firmware support"
select WANT_DEV_COREDUMP
help
This is the driver that supports the MVM firmware which is
currently only available for 7260 and 3160 devices.
This is the driver that supports the MVM firmware. The list
of the devices that use this firmware is available here:
https://wireless.wiki.kernel.org/en/users/drivers/iwlwifi#firmware
# don't call it _MODULE -- will confuse Kconfig/fixdep/...
config IWLWIFI_OPMODE_MODULAR
......
......@@ -128,6 +128,28 @@ static const struct iwl_base_params iwl7000_base_params = {
.apmg_wake_up_wa = true,
};
static const struct iwl_tt_params iwl7000_high_temp_tt_params = {
.ct_kill_entry = 118,
.ct_kill_exit = 96,
.ct_kill_duration = 5,
.dynamic_smps_entry = 114,
.dynamic_smps_exit = 110,
.tx_protection_entry = 114,
.tx_protection_exit = 108,
.tx_backoff = {
{.temperature = 112, .backoff = 300},
{.temperature = 113, .backoff = 800},
{.temperature = 114, .backoff = 1500},
{.temperature = 115, .backoff = 3000},
{.temperature = 116, .backoff = 5000},
{.temperature = 117, .backoff = 10000},
},
.support_ct_kill = true,
.support_dynamic_smps = true,
.support_tx_protection = true,
.support_tx_backoff = true,
};
static const struct iwl_ht_params iwl7000_ht_params = {
.stbc = true,
.ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ),
......@@ -170,6 +192,7 @@ const struct iwl_cfg iwl7260_2ac_cfg_high_temp = {
.host_interrupt_operation_mode = true,
.lp_xtal_workaround = true,
.dccm_len = IWL7260_DCCM_LEN,
.thermal_params = &iwl7000_high_temp_tt_params,
};
const struct iwl_cfg iwl7260_2n_cfg = {
......
......@@ -194,6 +194,49 @@ struct iwl_ht_params {
u8 ht40_bands;
};
/*
* Tx-backoff threshold
* @temperature: The threshold in Celsius
* @backoff: The tx-backoff in uSec
*/
struct iwl_tt_tx_backoff {
s32 temperature;
u32 backoff;
};
#define TT_TX_BACKOFF_SIZE 6
/**
* struct iwl_tt_params - thermal throttling parameters
* @ct_kill_entry: CT Kill entry threshold
* @ct_kill_exit: CT Kill exit threshold
* @ct_kill_duration: The time intervals (in uSec) in which the driver needs
* to checks whether to exit CT Kill.
* @dynamic_smps_entry: Dynamic SMPS entry threshold
* @dynamic_smps_exit: Dynamic SMPS exit threshold
* @tx_protection_entry: TX protection entry threshold
* @tx_protection_exit: TX protection exit threshold
* @tx_backoff: Array of thresholds for tx-backoff , in ascending order.
* @support_ct_kill: Support CT Kill?
* @support_dynamic_smps: Support dynamic SMPS?
* @support_tx_protection: Support tx protection?
* @support_tx_backoff: Support tx-backoff?
*/
struct iwl_tt_params {
s32 ct_kill_entry;
s32 ct_kill_exit;
u32 ct_kill_duration;
s32 dynamic_smps_entry;
s32 dynamic_smps_exit;
s32 tx_protection_entry;
s32 tx_protection_exit;
struct iwl_tt_tx_backoff tx_backoff[TT_TX_BACKOFF_SIZE];
bool support_ct_kill;
bool support_dynamic_smps;
bool support_tx_protection;
bool support_tx_backoff;
};
/*
* information on how to parse the EEPROM
*/
......@@ -316,6 +359,7 @@ struct iwl_cfg {
const u32 dccm2_len;
const u32 smem_offset;
const u32 smem_len;
const struct iwl_tt_params *thermal_params;
};
/*
......
......@@ -6,7 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
......@@ -32,7 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -244,6 +244,7 @@ enum iwl_ucode_tlv_flag {
* longer than the passive one, which is essential for fragmented scan.
* @IWL_UCODE_TLV_API_WIFI_MCC_UPDATE: ucode supports MCC updates with source.
* IWL_UCODE_TLV_API_HDC_PHASE_0: ucode supports finer configuration of LTR
* @IWL_UCODE_TLV_API_TX_POWER_DEV: new API for tx power.
* @IWL_UCODE_TLV_API_BASIC_DWELL: use only basic dwell time in scan command,
* regardless of the band or the number of the probes. FW will calculate
* the actual dwell time.
......@@ -260,6 +261,7 @@ enum iwl_ucode_tlv_api {
IWL_UCODE_TLV_API_FRAGMENTED_SCAN = BIT(8),
IWL_UCODE_TLV_API_WIFI_MCC_UPDATE = BIT(9),
IWL_UCODE_TLV_API_HDC_PHASE_0 = BIT(10),
IWL_UCODE_TLV_API_TX_POWER_DEV = BIT(11),
IWL_UCODE_TLV_API_BASIC_DWELL = BIT(13),
IWL_UCODE_TLV_API_SCD_CFG = BIT(15),
IWL_UCODE_TLV_API_SINGLE_SCAN_EBS = BIT(16),
......@@ -434,6 +436,7 @@ enum iwl_fw_dbg_monitor_mode {
*
* @version: version of the TLV - currently 0
* @monitor_mode: %enum iwl_fw_dbg_monitor_mode
* @size_power: buffer size will be 2^(size_power + 11)
* @base_reg: addr of the base addr register (PRPH)
* @end_reg: addr of the end addr register (PRPH)
* @write_ptr_reg: the addr of the reg of the write pointer
......@@ -447,7 +450,8 @@ enum iwl_fw_dbg_monitor_mode {
struct iwl_fw_dbg_dest_tlv {
u8 version;
u8 monitor_mode;
u8 reserved[2];
u8 size_power;
u8 reserved;
__le32 base_reg;
__le32 end_reg;
__le32 write_ptr_reg;
......
......@@ -348,6 +348,9 @@ enum secure_load_status_reg {
#define MON_BUFF_WRPTR (0xa03c44)
#define MON_BUFF_CYCLE_CNT (0xa03c48)
#define MON_DMARB_RD_CTL_ADDR (0xa03c60)
#define MON_DMARB_RD_DATA_ADDR (0xa03c5c)
#define DBGC_IN_SAMPLE (0xa03c00)
/* enable the ID buf for read */
......
......@@ -6,7 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
......@@ -32,7 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -421,8 +421,9 @@ struct iwl_trans_txq_scd_cfg {
*
* All the handlers MUST be implemented
*
* @start_hw: starts the HW- from that point on, the HW can send interrupts
* May sleep
* @start_hw: starts the HW. If low_power is true, the NIC needs to be taken
* out of a low power state. From that point on, the HW can send
* interrupts. May sleep.
* @op_mode_leave: Turn off the HW RF kill indication if on
* May sleep
* @start_fw: allocates and inits all the resources for the transport
......@@ -432,10 +433,11 @@ struct iwl_trans_txq_scd_cfg {
* the SCD base address in SRAM, then provide it here, or 0 otherwise.
* May sleep
* @stop_device: stops the whole device (embedded CPU put to reset) and stops
* the HW. From that point on, the HW will be in low power but will still
* issue interrupt if the HW RF kill is triggered. This callback must do
* the right thing and not crash even if start_hw() was called but not
* start_fw(). May sleep
* the HW. If low_power is true, the NIC will be put in low power state.
* From that point on, the HW will be stopped but will still issue an
* interrupt if the HW RF kill switch is triggered.
* This callback must do the right thing and not crash even if %start_hw()
* was called but not &start_fw(). May sleep.
* @d3_suspend: put the device into the correct mode for WoWLAN during
* suspend. This is optional, if not implemented WoWLAN will not be
* supported. This callback may sleep.
......@@ -491,14 +493,14 @@ struct iwl_trans_txq_scd_cfg {
*/
struct iwl_trans_ops {
int (*start_hw)(struct iwl_trans *iwl_trans);
int (*start_hw)(struct iwl_trans *iwl_trans, bool low_power);
void (*op_mode_leave)(struct iwl_trans *iwl_trans);
int (*start_fw)(struct iwl_trans *trans, const struct fw_img *fw,
bool run_in_rfkill);
int (*update_sf)(struct iwl_trans *trans,
struct iwl_sf_region *st_fwrd_space);
void (*fw_alive)(struct iwl_trans *trans, u32 scd_addr);
void (*stop_device)(struct iwl_trans *trans);
void (*stop_device)(struct iwl_trans *trans, bool low_power);
void (*d3_suspend)(struct iwl_trans *trans, bool test);
int (*d3_resume)(struct iwl_trans *trans, enum iwl_d3_status *status,
......@@ -652,11 +654,16 @@ static inline void iwl_trans_configure(struct iwl_trans *trans,
trans->ops->configure(trans, trans_cfg);
}
static inline int iwl_trans_start_hw(struct iwl_trans *trans)
static inline int _iwl_trans_start_hw(struct iwl_trans *trans, bool low_power)
{
might_sleep();
return trans->ops->start_hw(trans);
return trans->ops->start_hw(trans, low_power);
}
static inline int iwl_trans_start_hw(struct iwl_trans *trans)
{
return trans->ops->start_hw(trans, true);
}
static inline void iwl_trans_op_mode_leave(struct iwl_trans *trans)
......@@ -703,15 +710,21 @@ static inline int iwl_trans_update_sf(struct iwl_trans *trans,
return 0;
}
static inline void iwl_trans_stop_device(struct iwl_trans *trans)
static inline void _iwl_trans_stop_device(struct iwl_trans *trans,
bool low_power)
{
might_sleep();
trans->ops->stop_device(trans);
trans->ops->stop_device(trans, low_power);
trans->state = IWL_TRANS_NO_FW;
}
static inline void iwl_trans_stop_device(struct iwl_trans *trans)
{
_iwl_trans_stop_device(trans, true);
}
static inline void iwl_trans_d3_suspend(struct iwl_trans *trans, bool test)
{
might_sleep();
......
......@@ -6,7 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
......@@ -32,7 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -981,7 +981,8 @@ iwl_mvm_netdetect_config(struct iwl_mvm *mvm,
if (ret)
return ret;
ret = iwl_mvm_scan_offload_start(mvm, vif, nd_config, &mvm->nd_ies);
ret = iwl_mvm_sched_scan_start(mvm, vif, nd_config, &mvm->nd_ies,
IWL_MVM_SCAN_NETDETECT);
if (ret)
return ret;
......@@ -1726,7 +1727,7 @@ iwl_mvm_netdetect_query_results(struct iwl_mvm *mvm,
results->matched_profiles = le32_to_cpu(query->matched_profiles);
memcpy(results->matches, query->matches, sizeof(results->matches));
#ifdef CPTCFG_IWLWIFI_DEBUGFS
#ifdef CONFIG_IWLWIFI_DEBUGFS
mvm->last_netdetect_scans = le32_to_cpu(query->n_scans_done);
#endif
......
......@@ -297,6 +297,40 @@ struct iwl_uapsd_misbehaving_ap_notif {
u8 reserved[3];
} __packed;
/**
* struct iwl_reduce_tx_power_cmd - TX power reduction command
* REDUCE_TX_POWER_CMD = 0x9f
* @flags: (reserved for future implementation)
* @mac_context_id: id of the mac ctx for which we are reducing TX power.
* @pwr_restriction: TX power restriction in dBms.
*/
struct iwl_reduce_tx_power_cmd {
u8 flags;
u8 mac_context_id;
__le16 pwr_restriction;
} __packed; /* TX_REDUCED_POWER_API_S_VER_1 */
/**
* struct iwl_dev_tx_power_cmd - TX power reduction command
* REDUCE_TX_POWER_CMD = 0x9f
* @set_mode: 0 - MAC tx power, 1 - device tx power
* @mac_context_id: id of the mac ctx for which we are reducing TX power.
* @pwr_restriction: TX power restriction in 1/8 dBms.
* @dev_24: device TX power restriction in 1/8 dBms
* @dev_52_low: device TX power restriction upper band - low
* @dev_52_high: device TX power restriction upper band - high
*/
struct iwl_dev_tx_power_cmd {
__le32 set_mode;
__le32 mac_context_id;
__le16 pwr_restriction;
__le16 dev_24;
__le16 dev_52_low;
__le16 dev_52_high;
} __packed; /* TX_REDUCED_POWER_API_S_VER_2 */
#define IWL_DEV_MAX_TX_POWER 0x7FFF
/**
* struct iwl_beacon_filter_cmd
* REPLY_BEACON_FILTERING_CMD = 0xd2 (command)
......
......@@ -6,7 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
......@@ -32,7 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -122,46 +122,6 @@ enum iwl_scan_complete_status {
SCAN_COMP_STATUS_ERR_ALLOC_TE = 0x0C,
};
/**
* struct iwl_scan_results_notif - scan results for one channel
* ( SCAN_RESULTS_NOTIFICATION = 0x83 )
* @channel: which channel the results are from
* @band: 0 for 5.2 GHz, 1 for 2.4 GHz
* @probe_status: SCAN_PROBE_STATUS_*, indicates success of probe request
* @num_probe_not_sent: # of request that weren't sent due to not enough time
* @duration: duration spent in channel, in usecs
* @statistics: statistics gathered for this channel
*/
struct iwl_scan_results_notif {
u8 channel;
u8 band;
u8 probe_status;
u8 num_probe_not_sent;
__le32 duration;
__le32 statistics[SCAN_RESULTS_STATISTICS];
} __packed; /* SCAN_RESULT_NTF_API_S_VER_2 */
/**
* struct iwl_scan_complete_notif - notifies end of scanning (all channels)
* ( SCAN_COMPLETE_NOTIFICATION = 0x84 )
* @scanned_channels: number of channels scanned (and number of valid results)
* @status: one of SCAN_COMP_STATUS_*
* @bt_status: BT on/off status
* @last_channel: last channel that was scanned
* @tsf_low: TSF timer (lower half) in usecs
* @tsf_high: TSF timer (higher half) in usecs
* @results: array of scan results, only "scanned_channels" of them are valid
*/
struct iwl_scan_complete_notif {
u8 scanned_channels;
u8 status;
u8 bt_status;
u8 last_channel;
__le32 tsf_low;
__le32 tsf_high;
struct iwl_scan_results_notif results[];
} __packed; /* SCAN_COMPLETE_NTF_API_S_VER_2 */
/* scan offload */
#define IWL_SCAN_MAX_BLACKLIST_LEN 64
#define IWL_SCAN_SHORT_BLACKLIST_LEN 16
......@@ -314,50 +274,18 @@ struct iwl_scan_offload_profile_cfg {
} __packed;
/**
* iwl_scan_offload_schedule - schedule of scan offload
* iwl_scan_schedule_lmac - schedule of scan offload
* @delay: delay between iterations, in seconds.
* @iterations: num of scan iterations
* @full_scan_mul: number of partial scans before each full scan
*/
struct iwl_scan_offload_schedule {
struct iwl_scan_schedule_lmac {
__le16 delay;
u8 iterations;
u8 full_scan_mul;
} __packed;
/*
* iwl_scan_offload_flags
*
* IWL_SCAN_OFFLOAD_FLAG_PASS_ALL: pass all results - no filtering.
* IWL_SCAN_OFFLOAD_FLAG_CACHED_CHANNEL: add cached channels to partial scan.
* IWL_SCAN_OFFLOAD_FLAG_EBS_QUICK_MODE: EBS duration is 100mSec - typical
* beacon period. Finding channel activity in this mode is not guaranteed.
* IWL_SCAN_OFFLOAD_FLAG_EBS_ACCURATE_MODE: EBS duration is 200mSec.
* Assuming beacon period is 100ms finding channel activity is guaranteed.
*/
enum iwl_scan_offload_flags {
IWL_SCAN_OFFLOAD_FLAG_PASS_ALL = BIT(0),
IWL_SCAN_OFFLOAD_FLAG_CACHED_CHANNEL = BIT(2),
IWL_SCAN_OFFLOAD_FLAG_EBS_QUICK_MODE = BIT(5),
IWL_SCAN_OFFLOAD_FLAG_EBS_ACCURATE_MODE = BIT(6),
};
} __packed; /* SCAN_SCHEDULE_API_S */
/**
* iwl_scan_offload_req - scan offload request command
* @flags: bitmap - enum iwl_scan_offload_flags.
* @watchdog: maximum scan duration in TU.
* @delay: delay in seconds before first iteration.
* @schedule_line: scan offload schedule, for fast and regular scan.
*/
struct iwl_scan_offload_req {
__le16 flags;
__le16 watchdog;
__le16 delay;
__le16 reserved;
struct iwl_scan_offload_schedule schedule_line[2];
} __packed;
enum iwl_scan_offload_compleate_status {
enum iwl_scan_offload_complete_status {
IWL_SCAN_OFFLOAD_COMPLETED = 1,
IWL_SCAN_OFFLOAD_ABORTED = 2,
};
......@@ -504,7 +432,7 @@ enum iwl_scan_priority {
};
/**
* iwl_scan_req_unified_lmac - SCAN_REQUEST_CMD_API_S_VER_1
* iwl_scan_req_lmac - SCAN_REQUEST_CMD_API_S_VER_1
* @reserved1: for alignment and future use
* @channel_num: num of channels to scan
* @active-dwell: dwell time for active channels
......@@ -527,7 +455,7 @@ enum iwl_scan_priority {
* @channel_opt: channel optimization options, for full and partial scan
* @data: channel configuration and probe request packet.
*/
struct iwl_scan_req_unified_lmac {
struct iwl_scan_req_lmac {
/* SCAN_REQUEST_FIXED_PART_API_S_VER_7 */
__le32 reserved1;
u8 n_channels;
......@@ -548,13 +476,13 @@ struct iwl_scan_req_unified_lmac {
/* SCAN_REQ_PERIODIC_PARAMS_API_S */
__le32 iter_num;
__le32 delay;
struct iwl_scan_offload_schedule schedule[2];
struct iwl_scan_schedule_lmac schedule[2];
struct iwl_scan_channel_opt channel_opt[2];
u8 data[];
} __packed;
/**
* struct iwl_lmac_scan_results_notif - scan results for one channel -
* struct iwl_scan_results_notif - scan results for one channel -
* SCAN_RESULT_NTF_API_S_VER_3
* @channel: which channel the results are from
* @band: 0 for 5.2 GHz, 1 for 2.4 GHz
......@@ -562,7 +490,7 @@ struct iwl_scan_req_unified_lmac {
* @num_probe_not_sent: # of request that weren't sent due to not enough time
* @duration: duration spent in channel, in usecs
*/
struct iwl_lmac_scan_results_notif {
struct iwl_scan_results_notif {
u8 channel;
u8 band;
u8 probe_status;
......@@ -622,7 +550,11 @@ struct iwl_mvm_umac_cmd_hdr {
u8 ver;
} __packed;
#define IWL_MVM_MAX_SIMULTANEOUS_SCANS 8
/* The maximum of either of these cannot exceed 8, because we use an
* 8-bit mask (see IWL_MVM_SCAN_MASK in mvm.h).
*/
#define IWL_MVM_MAX_UMAC_SCANS 8
#define IWL_MVM_MAX_LMAC_SCANS 1
enum scan_config_flags {
SCAN_CONFIG_FLAG_ACTIVATE = BIT(0),
......
......@@ -147,13 +147,6 @@ enum {
LQ_CMD = 0x4e,
/* Calibration */
TEMPERATURE_NOTIFICATION = 0x62,
CALIBRATION_CFG_CMD = 0x65,
CALIBRATION_RES_NOTIFICATION = 0x66,
CALIBRATION_COMPLETE_NOTIFICATION = 0x67,
RADIO_VERSION_NOTIFICATION = 0x68,
/* Scan offload */
SCAN_OFFLOAD_REQUEST_CMD = 0x51,
SCAN_OFFLOAD_ABORT_CMD = 0x52,
......@@ -281,19 +274,6 @@ struct iwl_tx_ant_cfg_cmd {
__le32 valid;
} __packed;
/**
* struct iwl_reduce_tx_power_cmd - TX power reduction command
* REDUCE_TX_POWER_CMD = 0x9f
* @flags: (reserved for future implementation)
* @mac_context_id: id of the mac ctx for which we are reducing TX power.
* @pwr_restriction: TX power restriction in dBms.
*/
struct iwl_reduce_tx_power_cmd {
u8 flags;
u8 mac_context_id;
__le16 pwr_restriction;
} __packed; /* TX_REDUCED_POWER_API_S_VER_1 */
/*
* Calibration control struct.
* Sent as part of the phy configuration command.
......
......@@ -6,7 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
......@@ -32,7 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -322,7 +322,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
lockdep_assert_held(&mvm->mutex);
if (WARN_ON_ONCE(mvm->init_ucode_complete || mvm->calibrating))
if (WARN_ON_ONCE(mvm->calibrating))
return 0;
iwl_init_notification_wait(&mvm->notif_wait,
......@@ -396,8 +396,6 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
*/
ret = iwl_wait_notification(&mvm->notif_wait, &calib_wait,
MVM_UCODE_CALIB_TIMEOUT);
if (!ret)
mvm->init_ucode_complete = true;
if (ret && iwl_mvm_is_radio_killed(mvm)) {
IWL_DEBUG_RF_KILL(mvm, "RFKILL while calibrating.\n");
......@@ -494,15 +492,6 @@ int iwl_mvm_fw_dbg_collect_desc(struct iwl_mvm *mvm,
mvm->fw_dump_desc = desc;
/* stop recording */
if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
iwl_set_bits_prph(mvm->trans, MON_BUFF_SAMPLE_CTL, 0x100);
} else {
iwl_write_prph(mvm->trans, DBGC_IN_SAMPLE, 0);
/* wait before we collect the data till the DBGC stop */
udelay(100);
}
queue_delayed_work(system_wq, &mvm->fw_dump_wk, delay);
return 0;
......@@ -658,25 +647,24 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
* module loading, load init ucode now
* (for example, if we were in RFKILL)
*/
if (!mvm->init_ucode_complete) {
ret = iwl_run_init_mvm_ucode(mvm, false);
if (ret && !iwlmvm_mod_params.init_dbg) {
IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", ret);
/* this can't happen */
if (WARN_ON(ret > 0))
ret = -ERFKILL;
goto error;
}
if (!iwlmvm_mod_params.init_dbg) {
/*
* should stop and start HW since that INIT
* image just loaded
*/
iwl_trans_stop_device(mvm->trans);
ret = iwl_trans_start_hw(mvm->trans);
if (ret)
return ret;
}
ret = iwl_run_init_mvm_ucode(mvm, false);
if (ret && !iwlmvm_mod_params.init_dbg) {
IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", ret);
/* this can't happen */
if (WARN_ON(ret > 0))
ret = -ERFKILL;
goto error;
}
if (!iwlmvm_mod_params.init_dbg) {
/*
* Stop and start the transport without entering low power
* mode. This will save the state of other components on the
* device that are triggered by the INIT firwmare (MFUART).
*/
_iwl_trans_stop_device(mvm->trans, false);
_iwl_trans_start_hw(mvm->trans, false);
if (ret)
return ret;
}
if (iwlmvm_mod_params.init_dbg)
......@@ -844,21 +832,6 @@ int iwl_mvm_rx_card_state_notif(struct iwl_mvm *mvm,
return 0;
}
int iwl_mvm_rx_radio_ver(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_radio_version_notif *radio_version = (void *)pkt->data;
/* TODO: what to do with that? */
IWL_DEBUG_INFO(mvm,
"Radio version: flavor: 0x%08x, step 0x%08x, dash 0x%08x\n",
le32_to_cpu(radio_version->radio_flavor),
le32_to_cpu(radio_version->radio_step),
le32_to_cpu(radio_version->radio_dash));
return 0;
}
int iwl_mvm_rx_mfuart_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd)
......
......@@ -80,7 +80,6 @@
#include "sta.h"
#include "time-event.h"
#include "iwl-eeprom-parse.h"
#include "fw-api-scan.h"
#include "iwl-phy-db.h"
#include "testmode.h"
#include "iwl-fw-error-dump.h"
......@@ -506,10 +505,18 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
iwl_mvm_reset_phy_ctxts(mvm);
hw->wiphy->max_scan_ie_len = iwl_mvm_max_scan_ie_len(mvm, false);
hw->wiphy->max_scan_ie_len = iwl_mvm_max_scan_ie_len(mvm);
hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX;
BUILD_BUG_ON(IWL_MVM_MAX_UMAC_SCANS > HWEIGHT32(IWL_MVM_SCAN_MASK) ||
IWL_MVM_MAX_LMAC_SCANS > HWEIGHT32(IWL_MVM_SCAN_MASK));
if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN)
mvm->max_scans = IWL_MVM_MAX_UMAC_SCANS;
else
mvm->max_scans = IWL_MVM_MAX_LMAC_SCANS;
if (mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels)
hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
&mvm->nvm_data->bands[IEEE80211_BAND_2GHZ];
......@@ -532,14 +539,12 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
else
hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
if (IWL_UCODE_API(mvm->fw->ucode_ver) >= 10) {
hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
hw->wiphy->max_sched_scan_ssids = PROBE_OPTION_MAX;
hw->wiphy->max_match_sets = IWL_SCAN_MAX_PROFILES;
/* we create the 802.11 header and zero length SSID IE. */
hw->wiphy->max_sched_scan_ie_len =
SCAN_OFFLOAD_PROBE_REQ_SIZE - 24 - 2;
}
hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
hw->wiphy->max_sched_scan_ssids = PROBE_OPTION_MAX;
hw->wiphy->max_match_sets = IWL_SCAN_MAX_PROFILES;
/* we create the 802.11 header and zero length SSID IE. */
hw->wiphy->max_sched_scan_ie_len =
SCAN_OFFLOAD_PROBE_REQ_SIZE - 24 - 2;
hw->wiphy->features |= NL80211_FEATURE_P2P_GO_CTWIN |
NL80211_FEATURE_LOW_PRIORITY_SCAN |
......@@ -1227,22 +1232,23 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
iwl_trans_stop_device(mvm->trans);
mvm->scan_status = IWL_MVM_SCAN_NONE;
mvm->scan_status = 0;
mvm->ps_disabled = false;
mvm->calibrating = false;
/* just in case one was running */
ieee80211_remain_on_channel_expired(mvm->hw);
ieee80211_iterate_active_interfaces_atomic(
mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
iwl_mvm_cleanup_iterator, mvm);
/*
* cleanup all interfaces, even inactive ones, as some might have
* gone down during the HW restart
*/
ieee80211_iterate_interfaces(mvm->hw, 0, iwl_mvm_cleanup_iterator, mvm);
mvm->p2p_device_vif = NULL;
mvm->d0i3_ap_sta_id = IWL_MVM_STATION_COUNT;
iwl_mvm_reset_phy_ctxts(mvm);
memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table));
memset(mvm->sta_drained, 0, sizeof(mvm->sta_drained));
memset(mvm->tfd_drained, 0, sizeof(mvm->tfd_drained));
memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
......@@ -1322,7 +1328,7 @@ static void iwl_mvm_restart_complete(struct iwl_mvm *mvm)
clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);
iwl_mvm_d0i3_enable_tx(mvm, NULL);
ret = iwl_mvm_update_quotas(mvm, false, NULL);
ret = iwl_mvm_update_quotas(mvm, true, NULL);
if (ret)
IWL_ERR(mvm, "Failed to update quotas after restart (%d)\n",
ret);
......@@ -1426,7 +1432,7 @@ void __iwl_mvm_mac_stop(struct iwl_mvm *mvm)
if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN) {
int i;
for (i = 0; i < IWL_MVM_MAX_SIMULTANEOUS_SCANS; i++) {
for (i = 0; i < mvm->max_scans; i++) {
if (WARN_ONCE(mvm->scan_uid[i],
"UMAC scan UID %d was not cleaned\n",
mvm->scan_uid[i]))
......@@ -1471,8 +1477,8 @@ static struct iwl_mvm_phy_ctxt *iwl_mvm_get_free_phy_ctxt(struct iwl_mvm *mvm)
return NULL;
}
static int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
s8 tx_power)
static int iwl_mvm_set_tx_power_old(struct iwl_mvm *mvm,
struct ieee80211_vif *vif, s8 tx_power)
{
/* FW is in charge of regulatory enforcement */
struct iwl_reduce_tx_power_cmd reduce_txpwr_cmd = {
......@@ -1485,6 +1491,26 @@ static int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
&reduce_txpwr_cmd);
}
static int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
s16 tx_power)
{
struct iwl_dev_tx_power_cmd cmd = {
.set_mode = 0,
.mac_context_id =
cpu_to_le32(iwl_mvm_vif_from_mac80211(vif)->id),
.pwr_restriction = cpu_to_le16(8 * tx_power),
};
if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_TX_POWER_DEV))
return iwl_mvm_set_tx_power_old(mvm, vif, tx_power);
if (tx_power == IWL_DEFAULT_MAX_TX_POWER)
cmd.pwr_restriction = cpu_to_le16(IWL_DEV_MAX_TX_POWER);
return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, 0,
sizeof(cmd), &cmd);
}
static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
......@@ -2353,89 +2379,21 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
iwl_mvm_unref(mvm, IWL_MVM_REF_BSS_CHANGED);
}
static int iwl_mvm_cancel_scan_wait_notif(struct iwl_mvm *mvm,
enum iwl_scan_status scan_type)
{
int ret;
bool wait_for_handlers = false;
mutex_lock(&mvm->mutex);
if (mvm->scan_status != scan_type) {
ret = 0;
/* make sure there are no pending notifications */
wait_for_handlers = true;
goto out;
}
switch (scan_type) {
case IWL_MVM_SCAN_SCHED:
ret = iwl_mvm_scan_offload_stop(mvm, true);
break;
case IWL_MVM_SCAN_OS:
ret = iwl_mvm_cancel_scan(mvm);
break;
case IWL_MVM_SCAN_NONE:
default:
WARN_ON_ONCE(1);
ret = -EINVAL;
break;
}
if (ret)
goto out;
wait_for_handlers = true;
out:
mutex_unlock(&mvm->mutex);
/* make sure we consume the completion notification */
if (wait_for_handlers)
iwl_mvm_wait_for_async_handlers(mvm);
return ret;
}
static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_scan_request *hw_req)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct cfg80211_scan_request *req = &hw_req->req;
int ret;
if (req->n_channels == 0 ||
req->n_channels > mvm->fw->ucode_capa.n_scan_channels)
if (hw_req->req.n_channels == 0 ||
hw_req->req.n_channels > mvm->fw->ucode_capa.n_scan_channels)
return -EINVAL;
if (!(mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN)) {
ret = iwl_mvm_cancel_scan_wait_notif(mvm, IWL_MVM_SCAN_SCHED);
if (ret)
return ret;
}
mutex_lock(&mvm->mutex);
if (iwl_mvm_is_lar_supported(mvm) && !mvm->lar_regdom_set) {
IWL_ERR(mvm, "scan while LAR regdomain is not set\n");
ret = -EBUSY;
goto out;
}
if (mvm->scan_status != IWL_MVM_SCAN_NONE) {
ret = -EBUSY;
goto out;
}
iwl_mvm_ref(mvm, IWL_MVM_REF_SCAN);
if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN)
ret = iwl_mvm_scan_umac(mvm, vif, hw_req);
else
ret = iwl_mvm_unified_scan_lmac(mvm, vif, hw_req);
if (ret)
iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
out:
ret = iwl_mvm_reg_scan_start(mvm, vif, &hw_req->req, &hw_req->ies);
mutex_unlock(&mvm->mutex);
return ret;
}
......@@ -2456,7 +2414,7 @@ static void iwl_mvm_mac_cancel_hw_scan(struct ieee80211_hw *hw,
/* FIXME: for now, we ignore this race for UMAC scans, since
* they don't set the scan_status.
*/
if ((mvm->scan_status == IWL_MVM_SCAN_OS) ||
if ((mvm->scan_status & IWL_MVM_SCAN_REGULAR) ||
(mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN))
iwl_mvm_cancel_scan(mvm);
......@@ -2774,35 +2732,17 @@ static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
struct ieee80211_scan_ies *ies)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
int ret;
if (!(mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN)) {
ret = iwl_mvm_cancel_scan_wait_notif(mvm, IWL_MVM_SCAN_OS);
if (ret)
return ret;
}
int ret;
mutex_lock(&mvm->mutex);
if (iwl_mvm_is_lar_supported(mvm) && !mvm->lar_regdom_set) {
IWL_ERR(mvm, "sched-scan while LAR regdomain is not set\n");
ret = -EBUSY;
goto out;
}
if (!vif->bss_conf.idle) {
ret = -EBUSY;
goto out;
}
if (mvm->scan_status != IWL_MVM_SCAN_NONE) {
ret = -EBUSY;
goto out;
}
ret = iwl_mvm_scan_offload_start(mvm, vif, req, ies);
if (ret)
mvm->scan_status = IWL_MVM_SCAN_NONE;
ret = iwl_mvm_sched_scan_start(mvm, vif, req, ies, IWL_MVM_SCAN_SCHED);
out:
mutex_unlock(&mvm->mutex);
......@@ -2828,7 +2768,7 @@ static int iwl_mvm_mac_sched_scan_stop(struct ieee80211_hw *hw,
/* FIXME: for now, we ignore this race for UMAC scans, since
* they don't set the scan_status.
*/
if (mvm->scan_status != IWL_MVM_SCAN_SCHED &&
if (!(mvm->scan_status & IWL_MVM_SCAN_SCHED) &&
!(mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN)) {
mutex_unlock(&mvm->mutex);
return 0;
......@@ -2902,8 +2842,21 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
break;
}
/* During FW restart, in order to restore the state as it was,
* don't try to reprogram keys we previously failed for.
*/
if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) &&
key->hw_key_idx == STA_KEY_IDX_INVALID) {
IWL_DEBUG_MAC80211(mvm,
"skip invalid idx key programming during restart\n");
ret = 0;
break;
}
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,
test_bit(IWL_MVM_STATUS_IN_HW_RESTART,
&mvm->status));
if (ret) {
IWL_WARN(mvm, "set key failed\n");
/*
......@@ -2981,7 +2934,7 @@ static bool iwl_mvm_rx_aux_roc(struct iwl_notif_wait_data *notif_wait,
return true;
}
#define AUX_ROC_MAX_DELAY_ON_CHANNEL 5000
#define AUX_ROC_MAX_DELAY_ON_CHANNEL 200
static int iwl_mvm_send_aux_roc_cmd(struct iwl_mvm *mvm,
struct ieee80211_channel *channel,
struct ieee80211_vif *vif,
......
......@@ -6,7 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
......@@ -32,7 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -76,6 +76,7 @@
#include "iwl-notif-wait.h"
#include "iwl-eeprom-parse.h"
#include "iwl-fw-file.h"
#include "iwl-config.h"
#include "sta.h"
#include "fw-api.h"
#include "constants.h"
......@@ -446,9 +447,23 @@ iwl_mvm_vif_from_mac80211(struct ieee80211_vif *vif)
extern const u8 tid_to_mac80211_ac[];
enum iwl_scan_status {
IWL_MVM_SCAN_NONE,
IWL_MVM_SCAN_OS,
IWL_MVM_SCAN_SCHED,
IWL_MVM_SCAN_REGULAR = BIT(0),
IWL_MVM_SCAN_SCHED = BIT(1),
IWL_MVM_SCAN_NETDETECT = BIT(2),
IWL_MVM_SCAN_STOPPING_REGULAR = BIT(8),
IWL_MVM_SCAN_STOPPING_SCHED = BIT(9),
IWL_MVM_SCAN_STOPPING_NETDETECT = BIT(10),
IWL_MVM_SCAN_REGULAR_MASK = IWL_MVM_SCAN_REGULAR |
IWL_MVM_SCAN_STOPPING_REGULAR,
IWL_MVM_SCAN_SCHED_MASK = IWL_MVM_SCAN_SCHED |
IWL_MVM_SCAN_STOPPING_SCHED,
IWL_MVM_SCAN_NETDETECT_MASK = IWL_MVM_SCAN_NETDETECT |
IWL_MVM_SCAN_STOPPING_NETDETECT,
IWL_MVM_SCAN_STOPPING_MASK = 0xff00,
IWL_MVM_SCAN_MASK = 0x00ff,
};
/**
......@@ -463,49 +478,6 @@ struct iwl_nvm_section {
const u8 *data;
};
/*
* Tx-backoff threshold
* @temperature: The threshold in Celsius
* @backoff: The tx-backoff in uSec
*/
struct iwl_tt_tx_backoff {
s32 temperature;
u32 backoff;
};
#define TT_TX_BACKOFF_SIZE 6
/**
* struct iwl_tt_params - thermal throttling parameters
* @ct_kill_entry: CT Kill entry threshold
* @ct_kill_exit: CT Kill exit threshold
* @ct_kill_duration: The time intervals (in uSec) in which the driver needs
* to checks whether to exit CT Kill.
* @dynamic_smps_entry: Dynamic SMPS entry threshold
* @dynamic_smps_exit: Dynamic SMPS exit threshold
* @tx_protection_entry: TX protection entry threshold
* @tx_protection_exit: TX protection exit threshold
* @tx_backoff: Array of thresholds for tx-backoff , in ascending order.
* @support_ct_kill: Support CT Kill?
* @support_dynamic_smps: Support dynamic SMPS?
* @support_tx_protection: Support tx protection?
* @support_tx_backoff: Support tx-backoff?
*/
struct iwl_tt_params {
s32 ct_kill_entry;
s32 ct_kill_exit;
u32 ct_kill_duration;
s32 dynamic_smps_entry;
s32 dynamic_smps_exit;
s32 tx_protection_entry;
s32 tx_protection_exit;
struct iwl_tt_tx_backoff tx_backoff[TT_TX_BACKOFF_SIZE];
bool support_ct_kill;
bool support_dynamic_smps;
bool support_tx_protection;
bool support_tx_backoff;
};
/**
* struct iwl_mvm_tt_mgnt - Thermal Throttling Management structure
* @ct_kill_exit: worker to exit thermal kill
......@@ -520,7 +492,7 @@ struct iwl_mvm_tt_mgmt {
bool dynamic_smps;
u32 tx_backoff;
u32 min_backoff;
const struct iwl_tt_params *params;
struct iwl_tt_params params;
bool throttle;
};
......@@ -603,7 +575,6 @@ struct iwl_mvm {
enum iwl_ucode_type cur_ucode;
bool ucode_loaded;
bool init_ucode_complete;
bool calibrating;
u32 error_event_table;
u32 log_event_table;
......@@ -648,12 +619,15 @@ struct iwl_mvm {
u32 rts_threshold;
/* Scan status, cmd (pre-allocated) and auxiliary station */
enum iwl_scan_status scan_status;
unsigned int scan_status;
void *scan_cmd;
struct iwl_mcast_filter_cmd *mcast_filter_cmd;
/* max number of simultaneous scans the FW supports */
unsigned int max_scans;
/* UMAC scan tracking */
u32 scan_uid[IWL_MVM_MAX_SIMULTANEOUS_SCANS];
u32 scan_uid[IWL_MVM_MAX_UMAC_SCANS];
u8 scan_seq_num, sched_scan_seq_num;
/* rx chain antennas set through debugfs for the scan command */
......@@ -1084,8 +1058,6 @@ int iwl_mvm_rx_tx_cmd(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd);
int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd);
int iwl_mvm_rx_radio_ver(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd);
int iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd);
......@@ -1094,8 +1066,6 @@ int iwl_mvm_rx_fw_error(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
int iwl_mvm_rx_card_state_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd);
int iwl_mvm_rx_radio_ver(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd);
int iwl_mvm_rx_mfuart_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd);
int iwl_mvm_rx_shared_mem_cfg_notif(struct iwl_mvm *mvm,
......@@ -1147,9 +1117,12 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, bool force_upload,
struct ieee80211_vif *disabled_vif);
/* Scanning */
int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct cfg80211_scan_request *req,
struct ieee80211_scan_ies *ies);
int iwl_mvm_scan_size(struct iwl_mvm *mvm);
int iwl_mvm_cancel_scan(struct iwl_mvm *mvm);
int iwl_mvm_max_scan_ie_len(struct iwl_mvm *mvm, bool is_sched_scan);
int iwl_mvm_max_scan_ie_len(struct iwl_mvm *mvm);
void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm);
/* Scheduled scan */
......@@ -1161,31 +1134,18 @@ int iwl_mvm_rx_scan_offload_iter_complete_notif(struct iwl_mvm *mvm,
struct iwl_device_cmd *cmd);
int iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm,
struct cfg80211_sched_scan_request *req);
int iwl_mvm_scan_offload_start(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct cfg80211_sched_scan_request *req,
struct ieee80211_scan_ies *ies);
int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct cfg80211_sched_scan_request *req,
struct ieee80211_scan_ies *ies,
int type);
int iwl_mvm_scan_offload_stop(struct iwl_mvm *mvm, bool notify);
int iwl_mvm_rx_scan_offload_results(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd);
/* Unified scan */
int iwl_mvm_unified_scan_lmac(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_scan_request *req);
int iwl_mvm_unified_sched_scan_lmac(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct cfg80211_sched_scan_request *req,
struct ieee80211_scan_ies *ies);
/* UMAC scan */
int iwl_mvm_config_scan(struct iwl_mvm *mvm);
int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_scan_request *req);
int iwl_mvm_sched_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct cfg80211_sched_scan_request *req,
struct ieee80211_scan_ies *ies);
int iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd);
......
......@@ -246,7 +246,6 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
RX_HANDLER(SCAN_COMPLETE_UMAC, iwl_mvm_rx_umac_scan_complete_notif,
true),
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(MISSED_BEACONS_NOTIFICATION, iwl_mvm_rx_missed_beacons_notif,
......@@ -280,7 +279,6 @@ static const char *const iwl_mvm_cmd_strings[REPLY_MAX] = {
CMD(BINDING_CONTEXT_CMD),
CMD(TIME_QUOTA_CMD),
CMD(NON_QOS_TX_COUNTER_CMD),
CMD(RADIO_VERSION_NOTIFICATION),
CMD(SCAN_REQUEST_CMD),
CMD(SCAN_ABORT_CMD),
CMD(SCAN_START_NOTIFICATION),
......@@ -290,7 +288,6 @@ static const char *const iwl_mvm_cmd_strings[REPLY_MAX] = {
CMD(PHY_CONFIGURATION_CMD),
CMD(CALIB_RES_NOTIF_PHY_DB),
CMD(SET_CALIB_DEFAULT_CMD),
CMD(CALIBRATION_COMPLETE_NOTIFICATION),
CMD(ADD_STA_KEY),
CMD(ADD_STA),
CMD(REMOVE_STA),
......@@ -865,6 +862,16 @@ static void iwl_mvm_fw_error_dump_wk(struct work_struct *work)
return;
mutex_lock(&mvm->mutex);
/* stop recording */
if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
iwl_set_bits_prph(mvm->trans, MON_BUFF_SAMPLE_CTL, 0x100);
} else {
iwl_write_prph(mvm->trans, DBGC_IN_SAMPLE, 0);
/* wait before we collect the data till the DBGC stop */
udelay(100);
}
iwl_mvm_fw_error_dump(mvm);
/* start recording again if the firmware is not crashed */
......@@ -1253,11 +1260,13 @@ static void iwl_mvm_d0i3_exit_work(struct work_struct *wk)
ieee80211_iterate_active_interfaces(
mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_d0i3_disconnect_iter, mvm);
iwl_free_resp(&get_status_cmd);
out:
iwl_mvm_d0i3_enable_tx(mvm, qos_seq);
/* qos_seq might point inside resp_pkt, so free it only now */
if (get_status_cmd.resp_pkt)
iwl_free_resp(&get_status_cmd);
/* the FW might have updated the regdomain */
iwl_mvm_update_changed_regdom(mvm);
......
/******************************************************************************
*
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
......@@ -2133,7 +2133,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
}
/* current tx rate */
index = lq_sta->last_txrate_idx;
index = rate->index;
/* rates available for this association, and for modulation mode */
rate_mask = rs_get_supported_rates(lq_sta, rate);
......@@ -2181,14 +2181,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
* or search for a new one? */
rs_stay_in_table(lq_sta, false);
goto out;
}
/* Else we have enough samples; calculate estimate of
* actual average throughput */
if (window->average_tpt != ((window->success_ratio *
tbl->expected_tpt[index] + 64) / 128)) {
window->average_tpt = ((window->success_ratio *
tbl->expected_tpt[index] + 64) / 128);
return;
}
/* If we are searching for better modulation mode, check success. */
......@@ -2400,9 +2393,6 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
rs_set_stay_in_table(mvm, 0, lq_sta);
}
}
out:
lq_sta->last_txrate_idx = index;
}
struct rs_init_rate_info {
......@@ -2545,7 +2535,6 @@ static void rs_initialize_lq(struct iwl_mvm *mvm,
rate = &tbl->rate;
rs_get_initial_rate(mvm, lq_sta, band, rate);
lq_sta->last_txrate_idx = rate->index;
WARN_ON_ONCE(rate->ant != ANT_A && rate->ant != ANT_B);
if (rate->ant == ANT_A)
......@@ -3223,9 +3212,6 @@ static void rs_fill_lq_cmd(struct iwl_mvm *mvm,
if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LQ_SS_PARAMS)
rs_set_lq_ss_params(mvm, sta, lq_sta, initial_rate);
if (num_of_ant(initial_rate->ant) == 1)
lq_cmd->single_stream_ant_msk = initial_rate->ant;
mvmsta = iwl_mvm_sta_from_mac80211(sta);
mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif);
......
......@@ -322,8 +322,6 @@ struct iwl_lq_sta {
struct iwl_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */
u8 tx_agg_tid_en;
/* used to be in sta_info */
int last_txrate_idx;
/* last tx rate_n_flags */
u32 last_rate_n_flags;
/* packets destined for this STA are aggregated */
......
......@@ -478,6 +478,11 @@ static void iwl_mvm_stat_iterator(void *_data, u8 *mac,
if (vif->type != NL80211_IFTYPE_STATION)
return;
if (sig == 0) {
IWL_DEBUG_RX(mvm, "RSSI is 0 - skip signal based decision\n");
return;
}
mvmvif->bf_data.ave_beacon_signal = sig;
/* BT Coex */
......
This diff is collapsed.
......@@ -70,7 +70,7 @@
static void iwl_mvm_enter_ctkill(struct iwl_mvm *mvm)
{
struct iwl_mvm_tt_mgmt *tt = &mvm->thermal_throttle;
u32 duration = mvm->thermal_throttle.params->ct_kill_duration;
u32 duration = tt->params.ct_kill_duration;
if (test_bit(IWL_MVM_STATUS_HW_CTKILL, &mvm->status))
return;
......@@ -223,7 +223,7 @@ static void check_exit_ctkill(struct work_struct *work)
tt = container_of(work, struct iwl_mvm_tt_mgmt, ct_kill_exit.work);
mvm = container_of(tt, struct iwl_mvm, thermal_throttle);
duration = tt->params->ct_kill_duration;
duration = tt->params.ct_kill_duration;
mutex_lock(&mvm->mutex);
......@@ -247,7 +247,7 @@ static void check_exit_ctkill(struct work_struct *work)
IWL_DEBUG_TEMP(mvm, "NIC temperature: %d\n", temp);
if (temp <= tt->params->ct_kill_exit) {
if (temp <= tt->params.ct_kill_exit) {
mutex_unlock(&mvm->mutex);
iwl_mvm_exit_ctkill(mvm);
return;
......@@ -325,7 +325,7 @@ void iwl_mvm_tt_tx_backoff(struct iwl_mvm *mvm, u32 backoff)
void iwl_mvm_tt_handler(struct iwl_mvm *mvm)
{
const struct iwl_tt_params *params = mvm->thermal_throttle.params;
struct iwl_tt_params *params = &mvm->thermal_throttle.params;
struct iwl_mvm_tt_mgmt *tt = &mvm->thermal_throttle;
s32 temperature = mvm->temperature;
bool throttle_enable = false;
......@@ -340,7 +340,7 @@ void iwl_mvm_tt_handler(struct iwl_mvm *mvm)
}
if (params->support_ct_kill &&
temperature <= tt->params->ct_kill_exit) {
temperature <= params->ct_kill_exit) {
iwl_mvm_exit_ctkill(mvm);
return;
}
......@@ -400,7 +400,7 @@ void iwl_mvm_tt_handler(struct iwl_mvm *mvm)
}
}
static const struct iwl_tt_params iwl7000_tt_params = {
static const struct iwl_tt_params iwl_mvm_default_tt_params = {
.ct_kill_entry = 118,
.ct_kill_exit = 96,
.ct_kill_duration = 5,
......@@ -422,38 +422,16 @@ static const struct iwl_tt_params iwl7000_tt_params = {
.support_tx_backoff = true,
};
static const struct iwl_tt_params iwl7000_high_temp_tt_params = {
.ct_kill_entry = 118,
.ct_kill_exit = 96,
.ct_kill_duration = 5,
.dynamic_smps_entry = 114,
.dynamic_smps_exit = 110,
.tx_protection_entry = 114,
.tx_protection_exit = 108,
.tx_backoff = {
{.temperature = 112, .backoff = 300},
{.temperature = 113, .backoff = 800},
{.temperature = 114, .backoff = 1500},
{.temperature = 115, .backoff = 3000},
{.temperature = 116, .backoff = 5000},
{.temperature = 117, .backoff = 10000},
},
.support_ct_kill = true,
.support_dynamic_smps = true,
.support_tx_protection = true,
.support_tx_backoff = true,
};
void iwl_mvm_tt_initialize(struct iwl_mvm *mvm, u32 min_backoff)
{
struct iwl_mvm_tt_mgmt *tt = &mvm->thermal_throttle;
IWL_DEBUG_TEMP(mvm, "Initialize Thermal Throttling\n");
if (mvm->cfg->high_temp)
tt->params = &iwl7000_high_temp_tt_params;
if (mvm->cfg->thermal_params)
tt->params = *mvm->cfg->thermal_params;
else
tt->params = &iwl7000_tt_params;
tt->params = iwl_mvm_default_tt_params;
tt->throttle = false;
tt->dynamic_smps = false;
......
......@@ -5,8 +5,8 @@
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2007 - 2015 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
......@@ -31,8 +31,8 @@
*
* BSD LICENSE
*
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2005 - 2015 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -101,14 +101,26 @@ static void iwl_pcie_free_fw_monitor(struct iwl_trans *trans)
trans_pcie->fw_mon_size = 0;
}
static void iwl_pcie_alloc_fw_monitor(struct iwl_trans *trans)
static void iwl_pcie_alloc_fw_monitor(struct iwl_trans *trans, u8 max_power)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct page *page;
struct page *page = NULL;
dma_addr_t phys;
u32 size;
u32 size = 0;
u8 power;
if (!max_power) {
/* default max_power is maximum */
max_power = 26;
} else {
max_power += 11;
}
if (WARN(max_power > 26,
"External buffer size for monitor is too big %d, check the FW TLV\n",
max_power))
return;
if (trans_pcie->fw_mon_page) {
dma_sync_single_for_device(trans->dev, trans_pcie->fw_mon_phys,
trans_pcie->fw_mon_size,
......@@ -117,7 +129,7 @@ static void iwl_pcie_alloc_fw_monitor(struct iwl_trans *trans)
}
phys = 0;
for (power = 26; power >= 11; power--) {
for (power = max_power; power >= 11; power--) {
int order;
size = BIT(power);
......@@ -131,6 +143,7 @@ static void iwl_pcie_alloc_fw_monitor(struct iwl_trans *trans)
DMA_FROM_DEVICE);
if (dma_mapping_error(trans->dev, phys)) {
__free_pages(page, order);
page = NULL;
continue;
}
IWL_INFO(trans,
......@@ -142,6 +155,12 @@ static void iwl_pcie_alloc_fw_monitor(struct iwl_trans *trans)
if (WARN_ON_ONCE(!page))
return;
if (power != max_power)
IWL_ERR(trans,
"Sorry - debug buffer is only %luK while you requested %luK\n",
(unsigned long)BIT(power - 10),
(unsigned long)BIT(max_power - 10));
trans_pcie->fw_mon_page = page;
trans_pcie->fw_mon_phys = phys;
trans_pcie->fw_mon_size = size;
......@@ -833,7 +852,7 @@ static void iwl_pcie_apply_destination(struct iwl_trans *trans)
get_fw_dbg_mode_string(dest->monitor_mode));
if (dest->monitor_mode == EXTERNAL_MODE)
iwl_pcie_alloc_fw_monitor(trans);
iwl_pcie_alloc_fw_monitor(trans, dest->size_power);
else
IWL_WARN(trans, "PCI should have external buffer debug\n");
......@@ -907,7 +926,7 @@ static int iwl_pcie_load_given_ucode(struct iwl_trans *trans,
/* supported for 7000 only for the moment */
if (iwlwifi_mod_params.fw_monitor &&
trans->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
iwl_pcie_alloc_fw_monitor(trans);
iwl_pcie_alloc_fw_monitor(trans, 0);
if (trans_pcie->fw_mon_size) {
iwl_write_prph(trans, MON_BUFF_BASE_ADDR,
......@@ -1020,7 +1039,7 @@ static void iwl_trans_pcie_fw_alive(struct iwl_trans *trans, u32 scd_addr)
iwl_pcie_tx_start(trans, scd_addr);
}
static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
static void iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
bool hw_rfkill, was_hw_rfkill;
......@@ -1115,7 +1134,7 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
void iwl_trans_pcie_rf_kill(struct iwl_trans *trans, bool state)
{
if (iwl_op_mode_hw_rf_kill(trans->op_mode, state))
iwl_trans_pcie_stop_device(trans);
iwl_trans_pcie_stop_device(trans, true);
}
static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test)
......@@ -1200,7 +1219,7 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
return 0;
}
static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
static int iwl_trans_pcie_start_hw(struct iwl_trans *trans, bool low_power)
{
bool hw_rfkill;
int err;
......@@ -2197,6 +2216,29 @@ static u32 iwl_trans_pcie_fh_regs_dump(struct iwl_trans *trans,
return sizeof(**data) + fh_regs_len;
}
static u32
iwl_trans_pci_dump_marbh_monitor(struct iwl_trans *trans,
struct iwl_fw_error_dump_fw_mon *fw_mon_data,
u32 monitor_len)
{
u32 buf_size_in_dwords = (monitor_len >> 2);
u32 *buffer = (u32 *)fw_mon_data->data;
unsigned long flags;
u32 i;
if (!iwl_trans_grab_nic_access(trans, false, &flags))
return 0;
__iwl_write_prph(trans, MON_DMARB_RD_CTL_ADDR, 0x1);
for (i = 0; i < buf_size_in_dwords; i++)
buffer[i] = __iwl_read_prph(trans, MON_DMARB_RD_DATA_ADDR);
__iwl_write_prph(trans, MON_DMARB_RD_CTL_ADDR, 0x0);
iwl_trans_release_nic_access(trans, &flags);
return monitor_len;
}
static
struct iwl_trans_dump_data *iwl_trans_pcie_dump_data(struct iwl_trans *trans)
{
......@@ -2249,7 +2291,8 @@ struct iwl_trans_dump_data *iwl_trans_pcie_dump_data(struct iwl_trans *trans)
trans->dbg_dest_tlv->end_shift;
/* Make "end" point to the actual end */
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000 ||
trans->dbg_dest_tlv->monitor_mode == MARBH_MODE)
end += (1 << trans->dbg_dest_tlv->end_shift);
monitor_len = end - base;
len += sizeof(*data) + sizeof(struct iwl_fw_error_dump_fw_mon) +
......@@ -2325,9 +2368,6 @@ struct iwl_trans_dump_data *iwl_trans_pcie_dump_data(struct iwl_trans *trans)
len += sizeof(*data) + sizeof(*fw_mon_data);
if (trans_pcie->fw_mon_page) {
data->len = cpu_to_le32(trans_pcie->fw_mon_size +
sizeof(*fw_mon_data));
/*
* The firmware is now asserted, it won't write anything
* to the buffer. CPU can take ownership to fetch the
......@@ -2342,10 +2382,8 @@ struct iwl_trans_dump_data *iwl_trans_pcie_dump_data(struct iwl_trans *trans)
page_address(trans_pcie->fw_mon_page),
trans_pcie->fw_mon_size);
len += trans_pcie->fw_mon_size;
} else {
/* If we are here then the buffer is internal */
monitor_len = trans_pcie->fw_mon_size;
} else if (trans->dbg_dest_tlv->monitor_mode == SMEM_MODE) {
/*
* Update pointers to reflect actual values after
* shifting
......@@ -2354,10 +2392,18 @@ struct iwl_trans_dump_data *iwl_trans_pcie_dump_data(struct iwl_trans *trans)
trans->dbg_dest_tlv->base_shift;
iwl_trans_read_mem(trans, base, fw_mon_data->data,
monitor_len / sizeof(u32));
data->len = cpu_to_le32(sizeof(*fw_mon_data) +
monitor_len);
len += monitor_len;
} else if (trans->dbg_dest_tlv->monitor_mode == MARBH_MODE) {
monitor_len =
iwl_trans_pci_dump_marbh_monitor(trans,
fw_mon_data,
monitor_len);
} else {
/* Didn't match anything - output no monitor data */
monitor_len = 0;
}
len += monitor_len;
data->len = cpu_to_le32(monitor_len + sizeof(*fw_mon_data));
}
dump_data->len = len;
......
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