forked from Minki/linux
Major changes:
iwlwifi: * some more work on LAR * fixes for UMAC scan * more work on debugging framework * more work for 8000 devices * cleanups and small bugfixes -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQEcBAABAgAGBQJVJli2AAoJEG4XJFUm622bh6YH/1oKWWYkzCmAKVT3T3PKYcz8 wSUDp0iOQD/f8bXG6qm9lKeqzsJvvUSYaIJRH/Vh7g0uBGzZ+0aK+Tle7zdsKe9i OrI+yK65jBWyNMfVO4yl3/Nb9ER3TneEDyrOPkXGnFJcyVnCugPcPRZVXiLS3scq fQrzZkEOM6Fl+nqMAXK7R9Vhk+Oz2U4Dm2r/Qq9sncAZwWUPGC60Vxc0iVcBKOhH bFZlvnO0RGeU2DMC0RuDkDhaWAsoUvkkR/EsNCwk38Hs2AOag3hBr8METaIF4S0R 83ftVvjD8eJ8hDKP0AtQtMjZCjtAz+GR6D+maoUKxFQbMUq0xn7E2MqOOLxDeq0= =25In -----END PGP SIGNATURE----- Merge tag 'wireless-drivers-next-for-davem-2015-04-09' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next Kalle Valo says: ==================== Major changes: iwlwifi: * some more work on LAR * fixes for UMAC scan * more work on debugging framework * more work for 8000 devices * cleanups and small bugfixes ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
3ab1a30fbd
@ -69,9 +69,15 @@ void ath_fill_led_pin(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
|
||||
if (AR_SREV_9100(ah) || (ah->led_pin >= 0))
|
||||
if (AR_SREV_9100(ah))
|
||||
return;
|
||||
|
||||
if (ah->led_pin >= 0) {
|
||||
if (!((1 << ah->led_pin) & AR_GPIO_OE_OUT_MASK))
|
||||
ath9k_hw_request_gpio(ah, ah->led_pin, "ath9k-led");
|
||||
return;
|
||||
}
|
||||
|
||||
if (AR_SREV_9287(ah))
|
||||
ah->led_pin = ATH_LED_PIN_9287;
|
||||
else if (AR_SREV_9485(sc->sc_ah))
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <linux/time.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include "hw.h"
|
||||
@ -2711,11 +2712,23 @@ void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val)
|
||||
if (AR_SREV_9271(ah))
|
||||
val = ~val;
|
||||
|
||||
REG_RMW(ah, AR_GPIO_IN_OUT, ((val & 1) << gpio),
|
||||
AR_GPIO_BIT(gpio));
|
||||
if ((1 << gpio) & AR_GPIO_OE_OUT_MASK)
|
||||
REG_RMW(ah, AR_GPIO_IN_OUT, ((val & 1) << gpio),
|
||||
AR_GPIO_BIT(gpio));
|
||||
else
|
||||
gpio_set_value(gpio, val & 1);
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_set_gpio);
|
||||
|
||||
void ath9k_hw_request_gpio(struct ath_hw *ah, u32 gpio, const char *label)
|
||||
{
|
||||
if (gpio >= ah->caps.num_gpio_pins)
|
||||
return;
|
||||
|
||||
gpio_request_one(gpio, GPIOF_DIR_OUT | GPIOF_INIT_LOW, label);
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_request_gpio);
|
||||
|
||||
void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna)
|
||||
{
|
||||
REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7));
|
||||
|
@ -1024,6 +1024,7 @@ u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio);
|
||||
void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio,
|
||||
u32 ah_signal_type);
|
||||
void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val);
|
||||
void ath9k_hw_request_gpio(struct ath_hw *ah, u32 gpio, const char *label);
|
||||
void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna);
|
||||
|
||||
/* General Operation */
|
||||
|
@ -958,6 +958,8 @@
|
||||
|
||||
#define AR_SREV_9550(_ah) \
|
||||
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9550))
|
||||
#define AR_SREV_9550_OR_LATER(_ah) \
|
||||
(((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9550))
|
||||
|
||||
#define AR_SREV_9580(_ah) \
|
||||
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9580) && \
|
||||
@ -1128,6 +1130,8 @@ enum {
|
||||
|
||||
#define AR_GPIO_OE_OUT (AR_SREV_9340(ah) ? 0x4030 : \
|
||||
(AR_SREV_9300_20_OR_LATER(ah) ? 0x4050 : 0x404c))
|
||||
#define AR_GPIO_OE_OUT_MASK (AR_SREV_9550_OR_LATER(ah) ? \
|
||||
0x0000000F : 0xFFFFFFFF)
|
||||
#define AR_GPIO_OE_OUT_DRV 0x3
|
||||
#define AR_GPIO_OE_OUT_DRV_NO 0x0
|
||||
#define AR_GPIO_OE_OUT_DRV_LOW 0x1
|
||||
|
@ -227,7 +227,7 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb,
|
||||
|
||||
/* Check if there has been a timeout. */
|
||||
spin_lock(&wmi->wmi_lock);
|
||||
if (cmd_id != wmi->last_cmd_id) {
|
||||
if (be16_to_cpu(hdr->seq_no) != wmi->last_seq_id) {
|
||||
spin_unlock(&wmi->wmi_lock);
|
||||
goto free_skb;
|
||||
}
|
||||
@ -275,11 +275,16 @@ static int ath9k_wmi_cmd_issue(struct wmi *wmi,
|
||||
enum wmi_cmd_id cmd, u16 len)
|
||||
{
|
||||
struct wmi_cmd_hdr *hdr;
|
||||
unsigned long flags;
|
||||
|
||||
hdr = (struct wmi_cmd_hdr *) skb_push(skb, sizeof(struct wmi_cmd_hdr));
|
||||
hdr->command_id = cpu_to_be16(cmd);
|
||||
hdr->seq_no = cpu_to_be16(++wmi->tx_seq_id);
|
||||
|
||||
spin_lock_irqsave(&wmi->wmi_lock, flags);
|
||||
wmi->last_seq_id = wmi->tx_seq_id;
|
||||
spin_unlock_irqrestore(&wmi->wmi_lock, flags);
|
||||
|
||||
return htc_send_epid(wmi->htc, skb, wmi->ctrl_epid);
|
||||
}
|
||||
|
||||
@ -295,7 +300,6 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
|
||||
struct sk_buff *skb;
|
||||
u8 *data;
|
||||
int time_left, ret = 0;
|
||||
unsigned long flags;
|
||||
|
||||
if (ah->ah_flags & AH_UNPLUGGED)
|
||||
return 0;
|
||||
@ -323,10 +327,6 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
|
||||
wmi->cmd_rsp_buf = rsp_buf;
|
||||
wmi->cmd_rsp_len = rsp_len;
|
||||
|
||||
spin_lock_irqsave(&wmi->wmi_lock, flags);
|
||||
wmi->last_cmd_id = cmd_id;
|
||||
spin_unlock_irqrestore(&wmi->wmi_lock, flags);
|
||||
|
||||
ret = ath9k_wmi_cmd_issue(wmi, skb, cmd_id, cmd_len);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
@ -151,7 +151,7 @@ struct wmi {
|
||||
enum htc_endpoint_id ctrl_epid;
|
||||
struct mutex op_mutex;
|
||||
struct completion cmd_wait;
|
||||
enum wmi_cmd_id last_cmd_id;
|
||||
u16 last_seq_id;
|
||||
struct sk_buff_head wmi_event_queue;
|
||||
struct tasklet_struct wmi_event_tasklet;
|
||||
u16 tx_seq_id;
|
||||
|
@ -553,7 +553,7 @@ static bool b43_dma_mapping_error(struct b43_dmaring *ring,
|
||||
size_t buffersize, bool dma_to_device)
|
||||
{
|
||||
if (unlikely(dma_mapping_error(ring->dev->dev->dma_dev, addr)))
|
||||
return 1;
|
||||
return true;
|
||||
|
||||
switch (ring->type) {
|
||||
case B43_DMA_30BIT:
|
||||
@ -571,13 +571,13 @@ static bool b43_dma_mapping_error(struct b43_dmaring *ring,
|
||||
}
|
||||
|
||||
/* The address is OK. */
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
address_error:
|
||||
/* We can't support this address. Unmap it again. */
|
||||
unmap_descbuffer(ring, addr, buffersize, dma_to_device);
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool b43_rx_buffer_is_poisoned(struct b43_dmaring *ring, struct sk_buff *skb)
|
||||
@ -1099,16 +1099,16 @@ static bool b43_dma_translation_in_low_word(struct b43_wldev *dev,
|
||||
enum b43_dmatype type)
|
||||
{
|
||||
if (type != B43_DMA_64BIT)
|
||||
return 1;
|
||||
return true;
|
||||
|
||||
#ifdef CONFIG_B43_SSB
|
||||
if (dev->dev->bus_type == B43_BUS_SSB &&
|
||||
dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI &&
|
||||
!(pci_is_pcie(dev->dev->sdev->bus->host_pci) &&
|
||||
ssb_read32(dev->dev->sdev, SSB_TMSHIGH) & SSB_TMSHIGH_DMA64))
|
||||
return 1;
|
||||
return true;
|
||||
#endif
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
int b43_dma_init(struct b43_wldev *dev)
|
||||
|
@ -427,7 +427,7 @@ static bool b43legacy_dma_mapping_error(struct b43legacy_dmaring *ring,
|
||||
bool dma_to_device)
|
||||
{
|
||||
if (unlikely(dma_mapping_error(ring->dev->dev->dma_dev, addr)))
|
||||
return 1;
|
||||
return true;
|
||||
|
||||
switch (ring->type) {
|
||||
case B43legacy_DMA_30BIT:
|
||||
@ -441,13 +441,13 @@ static bool b43legacy_dma_mapping_error(struct b43legacy_dmaring *ring,
|
||||
}
|
||||
|
||||
/* The address is OK. */
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
address_error:
|
||||
/* We can't support this address. Unmap it again. */
|
||||
unmap_descbuffer(ring, addr, buffersize, dma_to_device);
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int setup_rx_descbuffer(struct b43legacy_dmaring *ring,
|
||||
|
@ -32,7 +32,7 @@ bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev)
|
||||
if (dev->dev->id.revision >= 3) {
|
||||
if (!(b43legacy_read32(dev, B43legacy_MMIO_RADIO_HWENABLED_HI)
|
||||
& B43legacy_MMIO_RADIO_HWENABLED_HI_MASK))
|
||||
return 1;
|
||||
return true;
|
||||
} else {
|
||||
/* To prevent CPU fault on PPC, do not read a register
|
||||
* unless the interface is started; however, on resume
|
||||
@ -40,12 +40,12 @@ bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev)
|
||||
* that happens, unconditionally return TRUE.
|
||||
*/
|
||||
if (b43legacy_status(dev) < B43legacy_STAT_STARTED)
|
||||
return 1;
|
||||
return true;
|
||||
if (b43legacy_read16(dev, B43legacy_MMIO_RADIO_HWENABLED_LO)
|
||||
& B43legacy_MMIO_RADIO_HWENABLED_LO_MASK)
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* The poll callback for the hardware button. */
|
||||
|
@ -2949,5 +2949,5 @@ bool wlc_phy_txpower_ipa_ison(struct brcms_phy_pub *ppi)
|
||||
if (ISNPHY(pi))
|
||||
return wlc_phy_n_txpower_ipa_ison(pi);
|
||||
else
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
@ -4999,7 +4999,7 @@ void wlc_2064_vco_cal(struct brcms_phy *pi)
|
||||
bool wlc_phy_tpc_isenabled_lcnphy(struct brcms_phy *pi)
|
||||
{
|
||||
if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
|
||||
return 0;
|
||||
return false;
|
||||
else
|
||||
return (LCNPHY_TX_PWR_CTRL_HW ==
|
||||
wlc_lcnphy_get_tx_pwr_ctrl((pi)));
|
||||
|
@ -94,8 +94,8 @@
|
||||
IWL8000_FW_PRE "-" __stringify(api) ".ucode"
|
||||
|
||||
#define NVM_HW_SECTION_NUM_FAMILY_8000 10
|
||||
#define DEFAULT_NVM_FILE_FAMILY_8000A "iwl_nvm_8000.bin"
|
||||
#define DEFAULT_NVM_FILE_FAMILY_8000 "iwl_nvm_8000B.bin"
|
||||
#define DEFAULT_NVM_FILE_FAMILY_8000B "nvmData-8000B"
|
||||
#define DEFAULT_NVM_FILE_FAMILY_8000C "nvmData-8000C"
|
||||
|
||||
/* Max SDIO RX aggregation size of the ADDBA request/response */
|
||||
#define MAX_RX_AGG_SIZE_8260_SDIO 28
|
||||
@ -177,8 +177,8 @@ const struct iwl_cfg iwl8260_2ac_sdio_cfg = {
|
||||
.ht_params = &iwl8000_ht_params,
|
||||
.nvm_ver = IWL8000_NVM_VERSION,
|
||||
.nvm_calib_ver = IWL8000_TX_POWER_VERSION,
|
||||
.default_nvm_file = DEFAULT_NVM_FILE_FAMILY_8000,
|
||||
.default_nvm_file_8000A = DEFAULT_NVM_FILE_FAMILY_8000A,
|
||||
.default_nvm_file_B_step = DEFAULT_NVM_FILE_FAMILY_8000B,
|
||||
.default_nvm_file_C_step = DEFAULT_NVM_FILE_FAMILY_8000C,
|
||||
.max_rx_agg_size = MAX_RX_AGG_SIZE_8260_SDIO,
|
||||
.disable_dummy_notification = true,
|
||||
.max_ht_ampdu_exponent = MAX_HT_AMPDU_EXPONENT_8260_SDIO,
|
||||
@ -192,8 +192,8 @@ const struct iwl_cfg iwl4165_2ac_sdio_cfg = {
|
||||
.ht_params = &iwl8000_ht_params,
|
||||
.nvm_ver = IWL8000_NVM_VERSION,
|
||||
.nvm_calib_ver = IWL8000_TX_POWER_VERSION,
|
||||
.default_nvm_file = DEFAULT_NVM_FILE_FAMILY_8000,
|
||||
.default_nvm_file_8000A = DEFAULT_NVM_FILE_FAMILY_8000A,
|
||||
.default_nvm_file_B_step = DEFAULT_NVM_FILE_FAMILY_8000B,
|
||||
.default_nvm_file_C_step = DEFAULT_NVM_FILE_FAMILY_8000C,
|
||||
.max_rx_agg_size = MAX_RX_AGG_SIZE_8260_SDIO,
|
||||
.bt_shared_single_ant = true,
|
||||
.disable_dummy_notification = true,
|
||||
|
@ -92,9 +92,9 @@ static inline bool iwl_has_secure_boot(u32 hw_rev,
|
||||
{
|
||||
/* return 1 only for family 8000 B0 */
|
||||
if ((family == IWL_DEVICE_FAMILY_8000) && (hw_rev & 0xC))
|
||||
return 1;
|
||||
return true;
|
||||
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -228,7 +228,7 @@ struct iwl_pwr_tx_backoff {
|
||||
|
||||
/**
|
||||
* struct iwl_cfg
|
||||
* @name: Offical name of the device
|
||||
* @name: Official name of the device
|
||||
* @fw_name_pre: Firmware filename prefix. The api version and extension
|
||||
* (.ucode) will be added to filename before loading from disk. The
|
||||
* filename is constructed as fw_name_pre<api>.ucode.
|
||||
@ -303,8 +303,8 @@ struct iwl_cfg {
|
||||
bool lp_xtal_workaround;
|
||||
const struct iwl_pwr_tx_backoff *pwr_tx_backoffs;
|
||||
bool no_power_up_nic_in_init;
|
||||
const char *default_nvm_file;
|
||||
const char *default_nvm_file_8000A;
|
||||
const char *default_nvm_file_B_step;
|
||||
const char *default_nvm_file_C_step;
|
||||
unsigned int max_rx_agg_size;
|
||||
bool disable_dummy_notification;
|
||||
unsigned int max_tx_agg_size;
|
||||
|
@ -145,7 +145,7 @@ static struct iwlwifi_opmode_table {
|
||||
#define IWL_DEFAULT_SCAN_CHANNELS 40
|
||||
|
||||
/*
|
||||
* struct fw_sec: Just for the image parsing proccess.
|
||||
* struct fw_sec: Just for the image parsing process.
|
||||
* For the fw storage we are using struct fw_desc.
|
||||
*/
|
||||
struct fw_sec {
|
||||
@ -241,16 +241,10 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first)
|
||||
* previous name and uses the new format.
|
||||
*/
|
||||
if (drv->trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) {
|
||||
char rev_step[2] = {
|
||||
'A' + CSR_HW_REV_STEP(drv->trans->hw_rev), 0
|
||||
};
|
||||
|
||||
/* A-step doesn't have an indication */
|
||||
if (CSR_HW_REV_STEP(drv->trans->hw_rev) == SILICON_A_STEP)
|
||||
rev_step[0] = 0;
|
||||
char rev_step = 'A' + CSR_HW_REV_STEP(drv->trans->hw_rev);
|
||||
|
||||
snprintf(drv->firmware_name, sizeof(drv->firmware_name),
|
||||
"%s%s-%s.ucode", name_pre, rev_step, tag);
|
||||
"%s%c-%s.ucode", name_pre, rev_step, tag);
|
||||
}
|
||||
|
||||
IWL_DEBUG_INFO(drv, "attempting to load firmware %s'%s'\n",
|
||||
@ -1108,6 +1102,7 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
|
||||
const unsigned int api_max = drv->cfg->ucode_api_max;
|
||||
unsigned int api_ok = drv->cfg->ucode_api_ok;
|
||||
const unsigned int api_min = drv->cfg->ucode_api_min;
|
||||
size_t trigger_tlv_sz[FW_DBG_TRIGGER_MAX];
|
||||
u32 api_ver;
|
||||
int i;
|
||||
bool load_module = false;
|
||||
@ -1227,8 +1222,37 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
|
||||
}
|
||||
}
|
||||
|
||||
memset(&trigger_tlv_sz, 0xff, sizeof(trigger_tlv_sz));
|
||||
|
||||
trigger_tlv_sz[FW_DBG_TRIGGER_MISSED_BEACONS] =
|
||||
sizeof(struct iwl_fw_dbg_trigger_missed_bcon);
|
||||
trigger_tlv_sz[FW_DBG_TRIGGER_CHANNEL_SWITCH] = 0;
|
||||
trigger_tlv_sz[FW_DBG_TRIGGER_FW_NOTIF] =
|
||||
sizeof(struct iwl_fw_dbg_trigger_cmd);
|
||||
trigger_tlv_sz[FW_DBG_TRIGGER_MLME] =
|
||||
sizeof(struct iwl_fw_dbg_trigger_mlme);
|
||||
trigger_tlv_sz[FW_DBG_TRIGGER_STATS] =
|
||||
sizeof(struct iwl_fw_dbg_trigger_stats);
|
||||
trigger_tlv_sz[FW_DBG_TRIGGER_RSSI] =
|
||||
sizeof(struct iwl_fw_dbg_trigger_low_rssi);
|
||||
trigger_tlv_sz[FW_DBG_TRIGGER_TXQ_TIMERS] =
|
||||
sizeof(struct iwl_fw_dbg_trigger_txq_timer);
|
||||
trigger_tlv_sz[FW_DBG_TRIGGER_TIME_EVENT] =
|
||||
sizeof(struct iwl_fw_dbg_trigger_time_event);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(drv->fw.dbg_trigger_tlv); i++) {
|
||||
if (pieces->dbg_trigger_tlv[i]) {
|
||||
/*
|
||||
* If the trigger isn't long enough, WARN and exit.
|
||||
* Someone is trying to debug something and he won't
|
||||
* be able to catch the bug he is trying to chase.
|
||||
* We'd better be noisy to be sure he knows what's
|
||||
* going on.
|
||||
*/
|
||||
if (WARN_ON(pieces->dbg_trigger_tlv_len[i] <
|
||||
(trigger_tlv_sz[i] +
|
||||
sizeof(struct iwl_fw_dbg_trigger_tlv))))
|
||||
goto out_free_fw;
|
||||
drv->fw.dbg_trigger_tlv_len[i] =
|
||||
pieces->dbg_trigger_tlv_len[i];
|
||||
drv->fw.dbg_trigger_tlv[i] =
|
||||
|
@ -123,7 +123,7 @@ struct iwl_cfg;
|
||||
* starts the driver: fetches the firmware. This should be called by bus
|
||||
* specific system flows implementations. For example, the bus specific probe
|
||||
* function should do bus related operations only, and then call to this
|
||||
* function. It returns the driver object or %NULL if an error occured.
|
||||
* function. It returns the driver object or %NULL if an error occurred.
|
||||
*/
|
||||
struct iwl_drv *iwl_drv_start(struct iwl_trans *trans,
|
||||
const struct iwl_cfg *cfg);
|
||||
|
@ -248,7 +248,7 @@ static int iwl_read_otp_word(struct iwl_trans *trans, u16 addr,
|
||||
otpgp = iwl_read32(trans, CSR_OTP_GP_REG);
|
||||
if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) {
|
||||
/* stop in this case */
|
||||
/* set the uncorrectable OTP ECC bit for acknowledgement */
|
||||
/* set the uncorrectable OTP ECC bit for acknowledgment */
|
||||
iwl_set_bit(trans, CSR_OTP_GP_REG,
|
||||
CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK);
|
||||
IWL_ERR(trans, "Uncorrectable OTP ECC error, abort OTP read\n");
|
||||
@ -256,7 +256,7 @@ static int iwl_read_otp_word(struct iwl_trans *trans, u16 addr,
|
||||
}
|
||||
if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) {
|
||||
/* continue in this case */
|
||||
/* set the correctable OTP ECC bit for acknowledgement */
|
||||
/* set the correctable OTP ECC bit for acknowledgment */
|
||||
iwl_set_bit(trans, CSR_OTP_GP_REG,
|
||||
CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK);
|
||||
IWL_ERR(trans, "Correctable OTP ECC error, continue read\n");
|
||||
|
@ -445,7 +445,7 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(unsigned int chnl)
|
||||
#define RX_LOW_WATERMARK 8
|
||||
|
||||
/**
|
||||
* struct iwl_rb_status - reseve buffer status
|
||||
* struct iwl_rb_status - reserve buffer status
|
||||
* host memory mapped FH registers
|
||||
* @closed_rb_num [0:11] - Indicates the index of the RB which was closed
|
||||
* @closed_fr_num [0:11] - Indicates the index of the RX Frame which was closed
|
||||
|
@ -183,7 +183,7 @@ struct iwl_fw_error_dump_info {
|
||||
* struct iwl_fw_error_dump_fw_mon - FW monitor data
|
||||
* @fw_mon_wr_ptr: the position of the write pointer in the cyclic buffer
|
||||
* @fw_mon_base_ptr: base pointer of the data
|
||||
* @fw_mon_cycle_cnt: number of wrap arounds
|
||||
* @fw_mon_cycle_cnt: number of wraparounds
|
||||
* @reserved: for future use
|
||||
* @data: captured data
|
||||
*/
|
||||
@ -246,10 +246,14 @@ iwl_fw_error_next_data(struct iwl_fw_error_dump_data *data)
|
||||
* @FW_DBG_TRIGGER_CHANNEL_SWITCH: trigger log collection upon channel switch.
|
||||
* @FW_DBG_TRIGGER_FW_NOTIF: trigger log collection when the firmware sends a
|
||||
* command response or a notification.
|
||||
* @FW_DB_TRIGGER_RESERVED: reserved
|
||||
* @FW_DBG_TRIGGER_MLME: trigger log collection upon MLME event.
|
||||
* @FW_DBG_TRIGGER_STATS: trigger log collection upon statistics threshold.
|
||||
* @FW_DBG_TRIGGER_RSSI: trigger log collection when the rssi of the beacon
|
||||
* goes below a threshold.
|
||||
* @FW_DBG_TRIGGER_TXQ_TIMERS: configures the timers for the Tx queue hang
|
||||
* detection.
|
||||
* @FW_DBG_TRIGGER_TIME_EVENT: trigger log collection upon time events related
|
||||
* events.
|
||||
*/
|
||||
enum iwl_fw_dbg_trigger {
|
||||
FW_DBG_TRIGGER_INVALID = 0,
|
||||
@ -258,9 +262,11 @@ enum iwl_fw_dbg_trigger {
|
||||
FW_DBG_TRIGGER_MISSED_BEACONS,
|
||||
FW_DBG_TRIGGER_CHANNEL_SWITCH,
|
||||
FW_DBG_TRIGGER_FW_NOTIF,
|
||||
FW_DB_TRIGGER_RESERVED,
|
||||
FW_DBG_TRIGGER_MLME,
|
||||
FW_DBG_TRIGGER_STATS,
|
||||
FW_DBG_TRIGGER_RSSI,
|
||||
FW_DBG_TRIGGER_TXQ_TIMERS,
|
||||
FW_DBG_TRIGGER_TIME_EVENT,
|
||||
|
||||
/* must be last */
|
||||
FW_DBG_TRIGGER_MAX,
|
||||
|
@ -191,7 +191,7 @@ struct iwl_ucode_capa {
|
||||
* enum iwl_ucode_tlv_flag - ucode API flags
|
||||
* @IWL_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously
|
||||
* was a separate TLV but moved here to save space.
|
||||
* @IWL_UCODE_TLV_FLAGS_NEWSCAN: new uCode scan behaviour on hidden SSID,
|
||||
* @IWL_UCODE_TLV_FLAGS_NEWSCAN: new uCode scan behavior on hidden SSID,
|
||||
* treats good CRC threshold as a boolean
|
||||
* @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w).
|
||||
* @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P.
|
||||
@ -290,6 +290,10 @@ enum iwl_ucode_tlv_api {
|
||||
* @IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT: supports Hot Spot Command
|
||||
* @IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS: support radio and beacon statistics
|
||||
* @IWL_UCODE_TLV_CAPA_BT_COEX_PLCR: enabled BT Coex packet level co-running
|
||||
* @IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC: ucode supports LAR updates with different
|
||||
* sources for the MCC. This TLV bit is a future replacement to
|
||||
* IWL_UCODE_TLV_API_WIFI_MCC_UPDATE. When either is set, multi-source LAR
|
||||
* is supported.
|
||||
* @IWL_UCODE_TLV_CAPA_BT_COEX_RRC: supports BT Coex RRC
|
||||
*/
|
||||
enum iwl_ucode_tlv_capa {
|
||||
@ -307,6 +311,7 @@ enum iwl_ucode_tlv_capa {
|
||||
IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT = BIT(18),
|
||||
IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS = BIT(22),
|
||||
IWL_UCODE_TLV_CAPA_BT_COEX_PLCR = BIT(28),
|
||||
IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC = BIT(29),
|
||||
IWL_UCODE_TLV_CAPA_BT_COEX_RRC = BIT(30),
|
||||
};
|
||||
|
||||
@ -573,6 +578,84 @@ struct iwl_fw_dbg_trigger_low_rssi {
|
||||
__le32 rssi;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_fw_dbg_trigger_mlme - configures trigger for mlme events
|
||||
* @stop_auth_denied: number of denied authentication to collect
|
||||
* @stop_auth_timeout: number of authentication timeout to collect
|
||||
* @stop_rx_deauth: number of Rx deauth before to collect
|
||||
* @stop_tx_deauth: number of Tx deauth before to collect
|
||||
* @stop_assoc_denied: number of denied association to collect
|
||||
* @stop_assoc_timeout: number of association timeout to collect
|
||||
* @stop_connection_loss: number of connection loss to collect
|
||||
* @start_auth_denied: number of denied authentication to start recording
|
||||
* @start_auth_timeout: number of authentication timeout to start recording
|
||||
* @start_rx_deauth: number of Rx deauth to start recording
|
||||
* @start_tx_deauth: number of Tx deauth to start recording
|
||||
* @start_assoc_denied: number of denied association to start recording
|
||||
* @start_assoc_timeout: number of association timeout to start recording
|
||||
* @start_connection_loss: number of connection loss to start recording
|
||||
*/
|
||||
struct iwl_fw_dbg_trigger_mlme {
|
||||
u8 stop_auth_denied;
|
||||
u8 stop_auth_timeout;
|
||||
u8 stop_rx_deauth;
|
||||
u8 stop_tx_deauth;
|
||||
|
||||
u8 stop_assoc_denied;
|
||||
u8 stop_assoc_timeout;
|
||||
u8 stop_connection_loss;
|
||||
u8 reserved;
|
||||
|
||||
u8 start_auth_denied;
|
||||
u8 start_auth_timeout;
|
||||
u8 start_rx_deauth;
|
||||
u8 start_tx_deauth;
|
||||
|
||||
u8 start_assoc_denied;
|
||||
u8 start_assoc_timeout;
|
||||
u8 start_connection_loss;
|
||||
u8 reserved2;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_fw_dbg_trigger_txq_timer - configures the Tx queue's timer
|
||||
* @command_queue: timeout for the command queue in ms
|
||||
* @bss: timeout for the queues of a BSS (except for TDLS queues) in ms
|
||||
* @softap: timeout for the queues of a softAP in ms
|
||||
* @p2p_go: timeout for the queues of a P2P GO in ms
|
||||
* @p2p_client: timeout for the queues of a P2P client in ms
|
||||
* @p2p_device: timeout for the queues of a P2P device in ms
|
||||
* @ibss: timeout for the queues of an IBSS in ms
|
||||
* @tdls: timeout for the queues of a TDLS station in ms
|
||||
*/
|
||||
struct iwl_fw_dbg_trigger_txq_timer {
|
||||
__le32 command_queue;
|
||||
__le32 bss;
|
||||
__le32 softap;
|
||||
__le32 p2p_go;
|
||||
__le32 p2p_client;
|
||||
__le32 p2p_device;
|
||||
__le32 ibss;
|
||||
__le32 tdls;
|
||||
__le32 reserved[4];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_fw_dbg_trigger_time_event - configures a time event trigger
|
||||
* time_Events: a list of tuples <id, action_bitmap>. The driver will issue a
|
||||
* trigger each time a time event notification that relates to time event
|
||||
* id with one of the actions in the bitmap is received and
|
||||
* BIT(notif->status) is set in status_bitmap.
|
||||
*
|
||||
*/
|
||||
struct iwl_fw_dbg_trigger_time_event {
|
||||
struct {
|
||||
__le32 id;
|
||||
__le32 action_bitmap;
|
||||
__le32 status_bitmap;
|
||||
} __packed time_events[16];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_fw_dbg_conf_tlv - a TLV that describes a debug configuration.
|
||||
* @id: conf id
|
||||
|
@ -186,21 +186,14 @@ IWL_EXPORT_SYMBOL(iwl_clear_bits_prph);
|
||||
|
||||
void iwl_force_nmi(struct iwl_trans *trans)
|
||||
{
|
||||
/*
|
||||
* In HW previous to the 8000 HW family, and in the 8000 HW family
|
||||
* itself when the revision step==0, the DEVICE_SET_NMI_REG is used
|
||||
* to force an NMI. Otherwise, a different register -
|
||||
* DEVICE_SET_NMI_8000B_REG - is used.
|
||||
*/
|
||||
if ((trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) ||
|
||||
(CSR_HW_REV_STEP(trans->hw_rev) == SILICON_A_STEP)) {
|
||||
if (trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) {
|
||||
iwl_write_prph(trans, DEVICE_SET_NMI_REG,
|
||||
DEVICE_SET_NMI_VAL_DRV);
|
||||
iwl_write_prph(trans, DEVICE_SET_NMI_REG,
|
||||
DEVICE_SET_NMI_VAL_HW);
|
||||
} else {
|
||||
iwl_write_prph(trans, DEVICE_SET_NMI_8000B_REG,
|
||||
DEVICE_SET_NMI_8000B_VAL);
|
||||
iwl_write_prph(trans, DEVICE_SET_NMI_8000_REG,
|
||||
DEVICE_SET_NMI_8000_VAL);
|
||||
iwl_write_prph(trans, DEVICE_SET_NMI_REG,
|
||||
DEVICE_SET_NMI_VAL_DRV);
|
||||
}
|
||||
|
@ -99,14 +99,9 @@ enum family_8000_nvm_offsets {
|
||||
/* NVM SW-Section offset (in words) definitions */
|
||||
NVM_SW_SECTION_FAMILY_8000 = 0x1C0,
|
||||
NVM_VERSION_FAMILY_8000 = 0,
|
||||
RADIO_CFG_FAMILY_8000 = 2,
|
||||
SKU_FAMILY_8000 = 4,
|
||||
N_HW_ADDRS_FAMILY_8000 = 5,
|
||||
|
||||
/* NVM PHY-SKU-Section offset (in words) for B0 */
|
||||
RADIO_CFG_FAMILY_8000_B0 = 0,
|
||||
SKU_FAMILY_8000_B0 = 2,
|
||||
N_HW_ADDRS_FAMILY_8000_B0 = 3,
|
||||
RADIO_CFG_FAMILY_8000 = 0,
|
||||
SKU_FAMILY_8000 = 2,
|
||||
N_HW_ADDRS_FAMILY_8000 = 3,
|
||||
|
||||
/* NVM REGULATORY -Section offset (in words) definitions */
|
||||
NVM_CHANNELS_FAMILY_8000 = 0,
|
||||
@ -446,22 +441,16 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
|
||||
n_used, n_channels);
|
||||
}
|
||||
|
||||
static int iwl_get_sku(const struct iwl_cfg *cfg,
|
||||
const __le16 *nvm_sw, const __le16 *phy_sku,
|
||||
bool is_family_8000_a_step)
|
||||
static int iwl_get_sku(const struct iwl_cfg *cfg, const __le16 *nvm_sw,
|
||||
const __le16 *phy_sku)
|
||||
{
|
||||
if (cfg->device_family != IWL_DEVICE_FAMILY_8000)
|
||||
return le16_to_cpup(nvm_sw + SKU);
|
||||
|
||||
if (!is_family_8000_a_step)
|
||||
return le32_to_cpup((__le32 *)(phy_sku +
|
||||
SKU_FAMILY_8000_B0));
|
||||
else
|
||||
return le32_to_cpup((__le32 *)(nvm_sw + SKU_FAMILY_8000));
|
||||
return le32_to_cpup((__le32 *)(phy_sku + SKU_FAMILY_8000));
|
||||
}
|
||||
|
||||
static int iwl_get_nvm_version(const struct iwl_cfg *cfg,
|
||||
const __le16 *nvm_sw)
|
||||
static int iwl_get_nvm_version(const struct iwl_cfg *cfg, const __le16 *nvm_sw)
|
||||
{
|
||||
if (cfg->device_family != IWL_DEVICE_FAMILY_8000)
|
||||
return le16_to_cpup(nvm_sw + NVM_VERSION);
|
||||
@ -470,35 +459,24 @@ static int iwl_get_nvm_version(const struct iwl_cfg *cfg,
|
||||
NVM_VERSION_FAMILY_8000));
|
||||
}
|
||||
|
||||
static int iwl_get_radio_cfg(const struct iwl_cfg *cfg,
|
||||
const __le16 *nvm_sw, const __le16 *phy_sku,
|
||||
bool is_family_8000_a_step)
|
||||
static int iwl_get_radio_cfg(const struct iwl_cfg *cfg, const __le16 *nvm_sw,
|
||||
const __le16 *phy_sku)
|
||||
{
|
||||
if (cfg->device_family != IWL_DEVICE_FAMILY_8000)
|
||||
return le16_to_cpup(nvm_sw + RADIO_CFG);
|
||||
|
||||
if (!is_family_8000_a_step)
|
||||
return le32_to_cpup((__le32 *)(phy_sku +
|
||||
RADIO_CFG_FAMILY_8000_B0));
|
||||
else
|
||||
return le32_to_cpup((__le32 *)(nvm_sw + RADIO_CFG_FAMILY_8000));
|
||||
return le32_to_cpup((__le32 *)(nvm_sw + RADIO_CFG_FAMILY_8000));
|
||||
|
||||
}
|
||||
|
||||
static int iwl_get_n_hw_addrs(const struct iwl_cfg *cfg,
|
||||
const __le16 *nvm_sw, bool is_family_8000_a_step)
|
||||
static int iwl_get_n_hw_addrs(const struct iwl_cfg *cfg, const __le16 *nvm_sw)
|
||||
{
|
||||
int n_hw_addr;
|
||||
|
||||
if (cfg->device_family != IWL_DEVICE_FAMILY_8000)
|
||||
return le16_to_cpup(nvm_sw + N_HW_ADDRS);
|
||||
|
||||
if (!is_family_8000_a_step)
|
||||
n_hw_addr = le32_to_cpup((__le32 *)(nvm_sw +
|
||||
N_HW_ADDRS_FAMILY_8000_B0));
|
||||
else
|
||||
n_hw_addr = le32_to_cpup((__le32 *)(nvm_sw +
|
||||
N_HW_ADDRS_FAMILY_8000));
|
||||
n_hw_addr = le32_to_cpup((__le32 *)(nvm_sw + N_HW_ADDRS_FAMILY_8000));
|
||||
|
||||
return n_hw_addr & N_HW_ADDR_MASK;
|
||||
}
|
||||
@ -594,8 +572,7 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
|
||||
const __le16 *nvm_hw, const __le16 *nvm_sw,
|
||||
const __le16 *nvm_calib, const __le16 *regulatory,
|
||||
const __le16 *mac_override, const __le16 *phy_sku,
|
||||
u8 tx_chains, u8 rx_chains,
|
||||
bool lar_fw_supported, bool is_family_8000_a_step,
|
||||
u8 tx_chains, u8 rx_chains, bool lar_fw_supported,
|
||||
u32 mac_addr0, u32 mac_addr1)
|
||||
{
|
||||
struct iwl_nvm_data *data;
|
||||
@ -618,15 +595,14 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
|
||||
|
||||
data->nvm_version = iwl_get_nvm_version(cfg, nvm_sw);
|
||||
|
||||
radio_cfg =
|
||||
iwl_get_radio_cfg(cfg, nvm_sw, phy_sku, is_family_8000_a_step);
|
||||
radio_cfg = iwl_get_radio_cfg(cfg, nvm_sw, phy_sku);
|
||||
iwl_set_radio_cfg(cfg, data, radio_cfg);
|
||||
if (data->valid_tx_ant)
|
||||
tx_chains &= data->valid_tx_ant;
|
||||
if (data->valid_rx_ant)
|
||||
rx_chains &= data->valid_rx_ant;
|
||||
|
||||
sku = iwl_get_sku(cfg, nvm_sw, phy_sku, is_family_8000_a_step);
|
||||
sku = iwl_get_sku(cfg, nvm_sw, phy_sku);
|
||||
data->sku_cap_band_24GHz_enable = sku & NVM_SKU_CAP_BAND_24GHZ;
|
||||
data->sku_cap_band_52GHz_enable = sku & NVM_SKU_CAP_BAND_52GHZ;
|
||||
data->sku_cap_11n_enable = sku & NVM_SKU_CAP_11N_ENABLE;
|
||||
@ -635,8 +611,7 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
|
||||
data->sku_cap_11ac_enable = data->sku_cap_11n_enable &&
|
||||
(sku & NVM_SKU_CAP_11AC_ENABLE);
|
||||
|
||||
data->n_hw_addrs =
|
||||
iwl_get_n_hw_addrs(cfg, nvm_sw, is_family_8000_a_step);
|
||||
data->n_hw_addrs = iwl_get_n_hw_addrs(cfg, nvm_sw);
|
||||
|
||||
if (cfg->device_family != IWL_DEVICE_FAMILY_8000) {
|
||||
/* Checking for required sections */
|
||||
|
@ -78,8 +78,7 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
|
||||
const __le16 *nvm_hw, const __le16 *nvm_sw,
|
||||
const __le16 *nvm_calib, const __le16 *regulatory,
|
||||
const __le16 *mac_override, const __le16 *phy_sku,
|
||||
u8 tx_chains, u8 rx_chains,
|
||||
bool lar_fw_supported, bool is_family_8000_a_step,
|
||||
u8 tx_chains, u8 rx_chains, bool lar_fw_supported,
|
||||
u32 mac_addr0, u32 mac_addr1);
|
||||
|
||||
/**
|
||||
|
@ -94,7 +94,7 @@ struct iwl_cfg;
|
||||
* The operational mode has a very simple life cycle.
|
||||
*
|
||||
* 1) The driver layer (iwl-drv.c) chooses the op_mode based on the
|
||||
* capabilities advertized by the fw file (in TLV format).
|
||||
* capabilities advertised by the fw file (in TLV format).
|
||||
* 2) The driver layer starts the op_mode (ops->start)
|
||||
* 3) The op_mode registers mac80211
|
||||
* 4) The op_mode is governed by mac80211
|
||||
@ -116,7 +116,7 @@ struct iwl_cfg;
|
||||
* May sleep
|
||||
* @rx: Rx notification to the op_mode. rxb is the Rx buffer itself. Cmd is the
|
||||
* HCMD this Rx responds to. Can't sleep.
|
||||
* @napi_add: NAPI initialisation. The transport is fully responsible for NAPI,
|
||||
* @napi_add: NAPI initialization. The transport is fully responsible for NAPI,
|
||||
* but the higher layers need to know about it (in particular mac80211 to
|
||||
* to able to call the right NAPI RX functions); this function is needed
|
||||
* to eventually call netif_napi_add() with higher layer involvement.
|
||||
|
@ -125,7 +125,7 @@ struct iwl_phy_db_chg_txp {
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* phy db - Receieve phy db chunk after calibrations
|
||||
* phy db - Receive phy db chunk after calibrations
|
||||
*/
|
||||
struct iwl_calib_res_notif_phy_db {
|
||||
__le16 type;
|
||||
|
@ -110,8 +110,8 @@
|
||||
#define DEVICE_SET_NMI_REG 0x00a01c30
|
||||
#define DEVICE_SET_NMI_VAL_HW BIT(0)
|
||||
#define DEVICE_SET_NMI_VAL_DRV BIT(7)
|
||||
#define DEVICE_SET_NMI_8000B_REG 0x00a01c24
|
||||
#define DEVICE_SET_NMI_8000B_VAL 0x1000000
|
||||
#define DEVICE_SET_NMI_8000_REG 0x00a01c24
|
||||
#define DEVICE_SET_NMI_8000_VAL 0x1000000
|
||||
|
||||
/* Shared registers (0x0..0x3ff, via target indirect or periphery */
|
||||
#define SHR_BASE 0x00a10000
|
||||
@ -295,25 +295,6 @@
|
||||
#define OSC_CLK (0xa04068)
|
||||
#define OSC_CLK_FORCE_CONTROL (0x8)
|
||||
|
||||
/* SECURE boot registers */
|
||||
#define LMPM_SECURE_BOOT_CONFIG_ADDR (0x100)
|
||||
enum secure_boot_config_reg {
|
||||
LMPM_SECURE_BOOT_CONFIG_INSPECTOR_BURNED_IN_OTP = 0x00000001,
|
||||
LMPM_SECURE_BOOT_CONFIG_INSPECTOR_NOT_REQ = 0x00000002,
|
||||
};
|
||||
|
||||
#define LMPM_SECURE_BOOT_CPU1_STATUS_ADDR_B0 (0xA01E30)
|
||||
#define LMPM_SECURE_BOOT_CPU1_STATUS_ADDR (0x1E30)
|
||||
#define LMPM_SECURE_BOOT_CPU2_STATUS_ADDR (0x1E34)
|
||||
enum secure_boot_status_reg {
|
||||
LMPM_SECURE_BOOT_CPU_STATUS_VERF_STATUS = 0x00000001,
|
||||
LMPM_SECURE_BOOT_CPU_STATUS_VERF_COMPLETED = 0x00000002,
|
||||
LMPM_SECURE_BOOT_CPU_STATUS_VERF_SUCCESS = 0x00000004,
|
||||
LMPM_SECURE_BOOT_CPU_STATUS_VERF_FAIL = 0x00000008,
|
||||
LMPM_SECURE_BOOT_CPU_STATUS_SIGN_VERF_FAIL = 0x00000010,
|
||||
LMPM_SECURE_BOOT_STATUS_SUCCESS = 0x00000003,
|
||||
};
|
||||
|
||||
#define FH_UCODE_LOAD_STATUS (0x1AF0)
|
||||
#define CSR_UCODE_LOAD_STATUS_ADDR (0x1E70)
|
||||
enum secure_load_status_reg {
|
||||
@ -334,8 +315,6 @@ enum secure_load_status_reg {
|
||||
#define LMPM_SECURE_CPU1_HDR_MEM_SPACE (0x420000)
|
||||
#define LMPM_SECURE_CPU2_HDR_MEM_SPACE (0x420400)
|
||||
|
||||
#define LMPM_SECURE_TIME_OUT (100) /* 10 micro */
|
||||
|
||||
/* Rx FIFO */
|
||||
#define RXF_SIZE_ADDR (0xa00c88)
|
||||
#define RXF_RD_D_SPACE (0xa00c40)
|
||||
|
@ -77,10 +77,10 @@
|
||||
/**
|
||||
* DOC: Transport layer - what is it ?
|
||||
*
|
||||
* The tranport layer is the layer that deals with the HW directly. It provides
|
||||
* The transport layer is the layer that deals with the HW directly. It provides
|
||||
* an abstraction of the underlying HW to the upper layer. The transport layer
|
||||
* doesn't provide any policy, algorithm or anything of this kind, but only
|
||||
* mechanisms to make the HW do something.It is not completely stateless but
|
||||
* mechanisms to make the HW do something. It is not completely stateless but
|
||||
* close to it.
|
||||
* We will have an implementation for each different supported bus.
|
||||
*/
|
||||
@ -111,10 +111,10 @@
|
||||
/**
|
||||
* DOC: Host command section
|
||||
*
|
||||
* A host command is a commaned issued by the upper layer to the fw. There are
|
||||
* A host command is a command issued by the upper layer to the fw. There are
|
||||
* several versions of fw that have several APIs. The transport layer is
|
||||
* completely agnostic to these differences.
|
||||
* The transport does provide helper functionnality (i.e. SYNC / ASYNC mode),
|
||||
* The transport does provide helper functionality (i.e. SYNC / ASYNC mode),
|
||||
*/
|
||||
#define SEQ_TO_QUEUE(s) (((s) >> 8) & 0x1f)
|
||||
#define QUEUE_TO_SEQ(q) (((q) & 0x1f) << 8)
|
||||
@ -195,7 +195,7 @@ static inline u32 iwl_rx_packet_payload_len(const struct iwl_rx_packet *pkt)
|
||||
* @CMD_WANT_SKB: Not valid with CMD_ASYNC. The caller needs the buffer of
|
||||
* the response. The caller needs to call iwl_free_resp when done.
|
||||
* @CMD_HIGH_PRIO: The command is high priority - it goes to the front of the
|
||||
* command queue, but after other high priority commands. valid only
|
||||
* command queue, but after other high priority commands. Valid only
|
||||
* with CMD_ASYNC.
|
||||
* @CMD_SEND_IN_IDLE: The command should be sent even when the trans is idle.
|
||||
* @CMD_MAKE_TRANS_IDLE: The command response should mark the trans as idle.
|
||||
@ -582,7 +582,7 @@ enum iwl_d0i3_mode {
|
||||
* @cfg - pointer to the configuration
|
||||
* @status: a bit-mask of transport status flags
|
||||
* @dev - pointer to struct device * that represents the device
|
||||
* @hw_id: a u32 with the ID of the device / subdevice.
|
||||
* @hw_id: a u32 with the ID of the device / sub-device.
|
||||
* Set during transport allocation.
|
||||
* @hw_id_str: a string with info about HW ID. Set during transport allocation.
|
||||
* @pm_support: set to true in start_hw if link pm is supported
|
||||
|
@ -1131,6 +1131,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
|
||||
iwl_trans_d3_suspend(mvm->trans, test);
|
||||
out:
|
||||
if (ret < 0) {
|
||||
iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN);
|
||||
ieee80211_restart_hw(mvm->hw);
|
||||
iwl_mvm_free_nd(mvm);
|
||||
}
|
||||
@ -1725,6 +1726,10 @@ 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
|
||||
mvm->last_netdetect_scans = le32_to_cpu(query->n_scans_done);
|
||||
#endif
|
||||
|
||||
out_free_resp:
|
||||
iwl_free_resp(&cmd);
|
||||
return ret;
|
||||
@ -2016,6 +2021,7 @@ static int iwl_mvm_d3_test_release(struct inode *inode, struct file *file)
|
||||
__iwl_mvm_resume(mvm, true);
|
||||
rtnl_unlock();
|
||||
iwl_abort_notification_waits(&mvm->notif_wait);
|
||||
iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN);
|
||||
ieee80211_restart_hw(mvm->hw);
|
||||
|
||||
/* wait for restart and disconnect all interfaces */
|
||||
|
@ -1473,26 +1473,6 @@ out:
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_enable_scan_iteration_notif_write(struct iwl_mvm *mvm,
|
||||
char *buf,
|
||||
size_t count,
|
||||
loff_t *ppos)
|
||||
{
|
||||
int val;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
|
||||
if (kstrtoint(buf, 10, &val)) {
|
||||
mutex_unlock(&mvm->mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mvm->scan_iter_notif_enabled = val;
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
MVM_DEBUGFS_READ_WRITE_FILE_OPS(prph_reg, 64);
|
||||
|
||||
/* Device wide debugfs entries */
|
||||
@ -1515,7 +1495,6 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8);
|
||||
MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8);
|
||||
MVM_DEBUGFS_READ_WRITE_FILE_OPS(fw_dbg_conf, 8);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(fw_dbg_collect, 8);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(enable_scan_iteration_notif, 8);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_BCAST_FILTERING
|
||||
MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256);
|
||||
@ -1559,8 +1538,11 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
|
||||
MVM_DEBUGFS_ADD_FILE(d0i3_refs, mvm->debugfs_dir, S_IRUSR | S_IWUSR);
|
||||
MVM_DEBUGFS_ADD_FILE(fw_dbg_conf, mvm->debugfs_dir, S_IRUSR | S_IWUSR);
|
||||
MVM_DEBUGFS_ADD_FILE(fw_dbg_collect, mvm->debugfs_dir, S_IWUSR);
|
||||
MVM_DEBUGFS_ADD_FILE(enable_scan_iteration_notif, mvm->debugfs_dir,
|
||||
S_IWUSR);
|
||||
if (!debugfs_create_bool("enable_scan_iteration_notif",
|
||||
S_IRUSR | S_IWUSR,
|
||||
mvm->debugfs_dir,
|
||||
&mvm->scan_iter_notif_enabled))
|
||||
goto err;
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_BCAST_FILTERING
|
||||
if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BCAST_FILTERING) {
|
||||
@ -1587,6 +1569,9 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
|
||||
if (!debugfs_create_bool("d3_wake_sysassert", S_IRUSR | S_IWUSR,
|
||||
mvm->debugfs_dir, &mvm->d3_wake_sysassert))
|
||||
goto err;
|
||||
if (!debugfs_create_u32("last_netdetect_scans", S_IRUSR,
|
||||
mvm->debugfs_dir, &mvm->last_netdetect_scans))
|
||||
goto err;
|
||||
MVM_DEBUGFS_ADD_FILE(netdetect, mvm->debugfs_dir, S_IRUSR | S_IWUSR);
|
||||
#endif
|
||||
|
||||
|
@ -132,7 +132,7 @@ struct iwl_proto_offload_cmd_common {
|
||||
* @solicited_node_ipv6_addr: broken -- solicited node address exists
|
||||
* for each target address
|
||||
* @target_ipv6_addr: our target addresses
|
||||
* @ndp_mac_addr: neighbor soliciation response MAC address
|
||||
* @ndp_mac_addr: neighbor solicitation response MAC address
|
||||
*/
|
||||
struct iwl_proto_offload_cmd_v1 {
|
||||
struct iwl_proto_offload_cmd_common common;
|
||||
@ -150,7 +150,7 @@ struct iwl_proto_offload_cmd_v1 {
|
||||
* @solicited_node_ipv6_addr: broken -- solicited node address exists
|
||||
* for each target address
|
||||
* @target_ipv6_addr: our target addresses
|
||||
* @ndp_mac_addr: neighbor soliciation response MAC address
|
||||
* @ndp_mac_addr: neighbor solicitation response MAC address
|
||||
*/
|
||||
struct iwl_proto_offload_cmd_v2 {
|
||||
struct iwl_proto_offload_cmd_common common;
|
||||
|
@ -255,7 +255,7 @@ struct iwl_mac_data_p2p_dev {
|
||||
/**
|
||||
* enum iwl_mac_filter_flags - MAC context filter flags
|
||||
* @MAC_FILTER_IN_PROMISC: accept all data frames
|
||||
* @MAC_FILTER_IN_CONTROL_AND_MGMT: pass all mangement and
|
||||
* @MAC_FILTER_IN_CONTROL_AND_MGMT: pass all management and
|
||||
* control frames to the host
|
||||
* @MAC_FILTER_ACCEPT_GRP: accept multicast frames
|
||||
* @MAC_FILTER_DIS_DECRYPT: don't decrypt unicast frames
|
||||
|
@ -103,7 +103,7 @@ struct iwl_ssid_ie {
|
||||
* @SCAN_COMP_STATUS_ERR_COEX: medium was lost ot WiMax
|
||||
* @SCAN_COMP_STATUS_P2P_ACTION_OK: P2P public action frame TX was successful
|
||||
* (not an error!)
|
||||
* @SCAN_COMP_STATUS_ITERATION_END: indicates end of one repeatition the driver
|
||||
* @SCAN_COMP_STATUS_ITERATION_END: indicates end of one repetition the driver
|
||||
* asked for
|
||||
* @SCAN_COMP_STATUS_ERR_ALLOC_TE: scan could not allocate time events
|
||||
*/
|
||||
@ -187,11 +187,11 @@ enum scan_framework_client {
|
||||
* struct iwl_scan_offload_cmd - SCAN_REQUEST_FIXED_PART_API_S_VER_6
|
||||
* @scan_flags: see enum iwl_scan_flags
|
||||
* @channel_count: channels in channel list
|
||||
* @quiet_time: dwell time, in milisiconds, on quiet channel
|
||||
* @quiet_time: dwell time, in milliseconds, on quiet channel
|
||||
* @quiet_plcp_th: quiet channel num of packets threshold
|
||||
* @good_CRC_th: passive to active promotion threshold
|
||||
* @rx_chain: RXON rx chain.
|
||||
* @max_out_time: max TUs to be out of assoceated channel
|
||||
* @max_out_time: max TUs to be out of associated channel
|
||||
* @suspend_time: pause scan this TUs when returning to service channel
|
||||
* @flags: RXON flags
|
||||
* @filter_flags: RXONfilter
|
||||
@ -232,7 +232,7 @@ enum iwl_scan_offload_channel_flags {
|
||||
* see enum iwl_scan_offload_channel_flags.
|
||||
* __le16 channel_number: channel number 1-13 etc.
|
||||
* __le16 iter_count: repetition count for the channel.
|
||||
* __le32 iter_interval: interval between two innteration on one channel.
|
||||
* __le32 iter_interval: interval between two iterations on one channel.
|
||||
* u8 active_dwell.
|
||||
* u8 passive_dwell.
|
||||
*/
|
||||
@ -275,8 +275,8 @@ enum iwl_scan_offload_band_selection {
|
||||
/**
|
||||
* iwl_scan_offload_profile - SCAN_OFFLOAD_PROFILE_S
|
||||
* @ssid_index: index to ssid list in fixed part
|
||||
* @unicast_cipher: encryption olgorithm to match - bitmap
|
||||
* @aut_alg: authentication olgorithm to match - bitmap
|
||||
* @unicast_cipher: encryption algorithm to match - bitmap
|
||||
* @aut_alg: authentication algorithm to match - bitmap
|
||||
* @network_type: enum iwl_scan_offload_network_type
|
||||
* @band_selection: enum iwl_scan_offload_band_selection
|
||||
* @client_bitmap: clients waiting for match - enum scan_framework_client
|
||||
@ -748,7 +748,7 @@ enum iwl_umac_scan_general_flags {
|
||||
* @flags: bitmap - 0-19: directed scan to i'th ssid.
|
||||
* @channel_num: channel number 1-13 etc.
|
||||
* @iter_count: repetition count for the channel.
|
||||
* @iter_interval: interval between two scan interations on one channel.
|
||||
* @iter_interval: interval between two scan iterations on one channel.
|
||||
*/
|
||||
struct iwl_scan_channel_cfg_umac {
|
||||
__le32 flags;
|
||||
|
@ -526,16 +526,33 @@ int iwl_mvm_fw_dbg_collect(struct iwl_mvm *mvm, enum iwl_fw_dbg_trigger trig,
|
||||
|
||||
int iwl_mvm_fw_dbg_collect_trig(struct iwl_mvm *mvm,
|
||||
struct iwl_fw_dbg_trigger_tlv *trigger,
|
||||
const char *str, size_t len)
|
||||
const char *fmt, ...)
|
||||
{
|
||||
unsigned int delay = msecs_to_jiffies(le32_to_cpu(trigger->stop_delay));
|
||||
u16 occurrences = le16_to_cpu(trigger->occurrences);
|
||||
int ret;
|
||||
int ret, len = 0;
|
||||
char buf[64];
|
||||
|
||||
if (!occurrences)
|
||||
return 0;
|
||||
|
||||
ret = iwl_mvm_fw_dbg_collect(mvm, le32_to_cpu(trigger->id), str,
|
||||
if (fmt) {
|
||||
va_list ap;
|
||||
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
/* check for truncation */
|
||||
if (WARN_ON_ONCE(buf[sizeof(buf) - 1]))
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
|
||||
len = strlen(buf) + 1;
|
||||
}
|
||||
|
||||
ret = iwl_mvm_fw_dbg_collect(mvm, le32_to_cpu(trigger->id), buf,
|
||||
len, delay);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -470,9 +470,8 @@ exit_fail:
|
||||
|
||||
int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
{
|
||||
unsigned int wdg_timeout = iwlmvm_mod_params.tfd_q_hang_detect ?
|
||||
mvm->cfg->base_params->wd_timeout :
|
||||
IWL_WATCHDOG_DISABLED;
|
||||
unsigned int wdg_timeout =
|
||||
iwl_mvm_get_wd_timeout(mvm, vif, false, false);
|
||||
u32 ac;
|
||||
int ret;
|
||||
|
||||
@ -1413,7 +1412,7 @@ static void iwl_mvm_beacon_loss_iterator(void *_data, u8 *mac,
|
||||
|
||||
if (rx_missed_bcon_since_rx >= stop_trig_missed_bcon_since_rx ||
|
||||
rx_missed_bcon >= stop_trig_missed_bcon)
|
||||
iwl_mvm_fw_dbg_collect_trig(mvm, trigger, NULL, 0);
|
||||
iwl_mvm_fw_dbg_collect_trig(mvm, trigger, NULL);
|
||||
}
|
||||
|
||||
int iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
|
||||
|
@ -379,11 +379,13 @@ int iwl_mvm_init_fw_regd(struct iwl_mvm *mvm)
|
||||
{
|
||||
enum iwl_mcc_source used_src;
|
||||
struct ieee80211_regdomain *regd;
|
||||
int ret;
|
||||
bool changed;
|
||||
const struct ieee80211_regdomain *r =
|
||||
rtnl_dereference(mvm->hw->wiphy->regd);
|
||||
|
||||
if (!r)
|
||||
return 0;
|
||||
return -ENOENT;
|
||||
|
||||
/* save the last source in case we overwrite it below */
|
||||
used_src = mvm->mcc_src;
|
||||
@ -395,14 +397,19 @@ int iwl_mvm_init_fw_regd(struct iwl_mvm *mvm)
|
||||
}
|
||||
|
||||
/* Now set our last stored MCC and source */
|
||||
regd = iwl_mvm_get_regdomain(mvm->hw->wiphy, r->alpha2, used_src, NULL);
|
||||
regd = iwl_mvm_get_regdomain(mvm->hw->wiphy, r->alpha2, used_src,
|
||||
&changed);
|
||||
if (IS_ERR_OR_NULL(regd))
|
||||
return -EIO;
|
||||
|
||||
regulatory_set_wiphy_regd(mvm->hw->wiphy, regd);
|
||||
kfree(regd);
|
||||
/* update cfg80211 if the regdomain was changed */
|
||||
if (changed)
|
||||
ret = regulatory_set_wiphy_regd_sync_rtnl(mvm->hw->wiphy, regd);
|
||||
else
|
||||
ret = 0;
|
||||
|
||||
return 0;
|
||||
kfree(regd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
|
||||
@ -1007,6 +1014,9 @@ void iwl_mvm_free_fw_dump_desc(struct iwl_mvm *mvm)
|
||||
mvm->fw_dump_desc = NULL;
|
||||
}
|
||||
|
||||
#define IWL8260_ICCM_OFFSET 0x44000 /* Only for B-step */
|
||||
#define IWL8260_ICCM_LEN 0xC000 /* Only for B-step */
|
||||
|
||||
void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
|
||||
{
|
||||
struct iwl_fw_error_dump_file *dump_file;
|
||||
@ -1022,16 +1032,6 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
/* W/A for 8000 HW family A-step */
|
||||
if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_8000 &&
|
||||
CSR_HW_REV_STEP(mvm->trans->hw_rev) == SILICON_A_STEP) {
|
||||
if (smem_len)
|
||||
smem_len = 0x38000;
|
||||
|
||||
if (sram2_len)
|
||||
sram2_len = 0x10000;
|
||||
}
|
||||
|
||||
fw_error_dump = kzalloc(sizeof(*fw_error_dump), GFP_KERNEL);
|
||||
if (!fw_error_dump)
|
||||
return;
|
||||
@ -1083,6 +1083,14 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
|
||||
fifo_data_len +
|
||||
sizeof(*dump_info);
|
||||
|
||||
/*
|
||||
* In 8000 HW family B-step include the ICCM (which resides separately)
|
||||
*/
|
||||
if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_8000 &&
|
||||
CSR_HW_REV_STEP(mvm->trans->hw_rev) == SILICON_B_STEP)
|
||||
file_len += sizeof(*dump_data) + sizeof(*dump_mem) +
|
||||
IWL8260_ICCM_LEN;
|
||||
|
||||
if (mvm->fw_dump_desc)
|
||||
file_len += sizeof(*dump_data) + sizeof(*dump_trig) +
|
||||
mvm->fw_dump_desc->len;
|
||||
@ -1170,6 +1178,19 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
|
||||
dump_mem->data, sram2_len);
|
||||
}
|
||||
|
||||
if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_8000 &&
|
||||
CSR_HW_REV_STEP(mvm->trans->hw_rev) == SILICON_B_STEP) {
|
||||
dump_data = iwl_fw_error_next_data(dump_data);
|
||||
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
|
||||
dump_data->len = cpu_to_le32(IWL8260_ICCM_LEN +
|
||||
sizeof(*dump_mem));
|
||||
dump_mem = (void *)dump_data->data;
|
||||
dump_mem->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_SRAM);
|
||||
dump_mem->offset = cpu_to_le32(IWL8260_ICCM_OFFSET);
|
||||
iwl_trans_read_mem_bytes(mvm->trans, IWL8260_ICCM_OFFSET,
|
||||
dump_mem->data, IWL8260_ICCM_LEN);
|
||||
}
|
||||
|
||||
fw_error_dump->trans_ptr = iwl_trans_dump_data(mvm->trans);
|
||||
fw_error_dump->op_mode_len = file_len;
|
||||
if (fw_error_dump->trans_ptr)
|
||||
@ -1399,6 +1420,20 @@ void __iwl_mvm_mac_stop(struct iwl_mvm *mvm)
|
||||
*/
|
||||
clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);
|
||||
|
||||
/* We shouldn't have any UIDs still set. Loop over all the UIDs to
|
||||
* make sure there's nothing left there and warn if any is found.
|
||||
*/
|
||||
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++) {
|
||||
if (WARN_ONCE(mvm->scan_uid[i],
|
||||
"UMAC scan UID %d was not cleaned\n",
|
||||
mvm->scan_uid[i]))
|
||||
mvm->scan_uid[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
mvm->ucode_loaded = false;
|
||||
}
|
||||
|
||||
@ -1595,9 +1630,33 @@ static void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm,
|
||||
u32 tfd_msk = iwl_mvm_mac_get_queues_mask(vif);
|
||||
|
||||
if (tfd_msk) {
|
||||
/*
|
||||
* mac80211 first removes all the stations of the vif and
|
||||
* then removes the vif. When it removes a station it also
|
||||
* flushes the AMPDU session. So by now, all the AMPDU sessions
|
||||
* of all the stations of this vif are closed, and the queues
|
||||
* of these AMPDU sessions are properly closed.
|
||||
* We still need to take care of the shared queues of the vif.
|
||||
* Flush them here.
|
||||
*/
|
||||
mutex_lock(&mvm->mutex);
|
||||
iwl_mvm_flush_tx_path(mvm, tfd_msk, true);
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
/*
|
||||
* There are transports that buffer a few frames in the host.
|
||||
* For these, the flush above isn't enough since while we were
|
||||
* flushing, the transport might have sent more frames to the
|
||||
* device. To solve this, wait here until the transport is
|
||||
* empty. Technically, this could have replaced the flush
|
||||
* above, but flush is much faster than draining. So flush
|
||||
* first, and drain to make sure we have no frames in the
|
||||
* transport anymore.
|
||||
* If a station still had frames on the shared queues, it is
|
||||
* already marked as draining, so to complete the draining, we
|
||||
* just need to wait until the transport is empty.
|
||||
*/
|
||||
iwl_trans_wait_tx_queue_empty(mvm->trans, tfd_msk);
|
||||
}
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
|
||||
@ -2167,8 +2226,7 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
|
||||
if (iwl_mvm_phy_ctx_count(mvm) > 1)
|
||||
iwl_mvm_teardown_tdls_peers(mvm);
|
||||
|
||||
mutex_unlock(&mvm->mutex);
|
||||
return 0;
|
||||
goto out_unlock;
|
||||
|
||||
out_quota_failed:
|
||||
iwl_mvm_power_update_mac(mvm);
|
||||
@ -3022,6 +3080,8 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
|
||||
IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value,
|
||||
duration, type);
|
||||
|
||||
flush_work(&mvm->roc_done_wk);
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
|
||||
switch (vif->type) {
|
||||
@ -3646,11 +3706,12 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
|
||||
mvmvif->csa_failed = false;
|
||||
|
||||
IWL_DEBUG_MAC80211(mvm, "pre CSA to freq %d\n",
|
||||
chsw->chandef.center_freq1);
|
||||
|
||||
iwl_fw_dbg_trigger_simple_stop(mvm, vif, FW_DBG_TRIGGER_CHANNEL_SWITCH,
|
||||
NULL, 0);
|
||||
iwl_fw_dbg_trigger_simple_stop(mvm, vif, FW_DBG_TRIGGER_CHANNEL_SWITCH);
|
||||
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_AP:
|
||||
@ -3721,6 +3782,12 @@ static int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw,
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
|
||||
if (mvmvif->csa_failed) {
|
||||
mvmvif->csa_failed = false;
|
||||
ret = -EIO;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_STATION) {
|
||||
struct iwl_mvm_sta *mvmsta;
|
||||
|
||||
@ -3844,6 +3911,7 @@ static int iwl_mvm_mac_get_survey(struct ieee80211_hw *hw, int idx,
|
||||
mvm->radio_stats.on_time_scan;
|
||||
do_div(survey->time_scan, USEC_PER_MSEC);
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
mutex_unlock(&mvm->mutex);
|
||||
return ret;
|
||||
@ -3889,6 +3957,64 @@ static void iwl_mvm_mac_sta_statistics(struct ieee80211_hw *hw,
|
||||
mutex_unlock(&mvm->mutex);
|
||||
}
|
||||
|
||||
static void iwl_mvm_mac_event_callback(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
const struct ieee80211_event *event)
|
||||
{
|
||||
#define CHECK_MLME_TRIGGER(_mvm, _trig, _buf, _cnt, _fmt...) \
|
||||
do { \
|
||||
if ((_cnt) && --(_cnt)) \
|
||||
break; \
|
||||
iwl_mvm_fw_dbg_collect_trig(_mvm, _trig, _fmt);\
|
||||
} while (0)
|
||||
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
struct iwl_fw_dbg_trigger_tlv *trig;
|
||||
struct iwl_fw_dbg_trigger_mlme *trig_mlme;
|
||||
|
||||
if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_MLME))
|
||||
return;
|
||||
|
||||
if (event->u.mlme.status == MLME_SUCCESS)
|
||||
return;
|
||||
|
||||
trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_MLME);
|
||||
trig_mlme = (void *)trig->data;
|
||||
if (!iwl_fw_dbg_trigger_check_stop(mvm, vif, trig))
|
||||
return;
|
||||
|
||||
if (event->u.mlme.data == ASSOC_EVENT) {
|
||||
if (event->u.mlme.status == MLME_DENIED)
|
||||
CHECK_MLME_TRIGGER(mvm, trig, buf,
|
||||
trig_mlme->stop_assoc_denied,
|
||||
"DENIED ASSOC: reason %d",
|
||||
event->u.mlme.reason);
|
||||
else if (event->u.mlme.status == MLME_TIMEOUT)
|
||||
CHECK_MLME_TRIGGER(mvm, trig, buf,
|
||||
trig_mlme->stop_assoc_timeout,
|
||||
"ASSOC TIMEOUT");
|
||||
} else if (event->u.mlme.data == AUTH_EVENT) {
|
||||
if (event->u.mlme.status == MLME_DENIED)
|
||||
CHECK_MLME_TRIGGER(mvm, trig, buf,
|
||||
trig_mlme->stop_auth_denied,
|
||||
"DENIED AUTH: reason %d",
|
||||
event->u.mlme.reason);
|
||||
else if (event->u.mlme.status == MLME_TIMEOUT)
|
||||
CHECK_MLME_TRIGGER(mvm, trig, buf,
|
||||
trig_mlme->stop_auth_timeout,
|
||||
"AUTH TIMEOUT");
|
||||
} else if (event->u.mlme.data == DEAUTH_RX_EVENT) {
|
||||
CHECK_MLME_TRIGGER(mvm, trig, buf,
|
||||
trig_mlme->stop_rx_deauth,
|
||||
"DEAUTH RX %d", event->u.mlme.reason);
|
||||
} else if (event->u.mlme.data == DEAUTH_TX_EVENT) {
|
||||
CHECK_MLME_TRIGGER(mvm, trig, buf,
|
||||
trig_mlme->stop_tx_deauth,
|
||||
"DEAUTH TX %d", event->u.mlme.reason);
|
||||
}
|
||||
#undef CHECK_MLME_TRIGGER
|
||||
}
|
||||
|
||||
const struct ieee80211_ops iwl_mvm_hw_ops = {
|
||||
.tx = iwl_mvm_mac_tx,
|
||||
.ampdu_action = iwl_mvm_mac_ampdu_action,
|
||||
@ -3942,6 +4068,8 @@ const struct ieee80211_ops iwl_mvm_hw_ops = {
|
||||
.tdls_cancel_channel_switch = iwl_mvm_tdls_cancel_channel_switch,
|
||||
.tdls_recv_channel_switch = iwl_mvm_tdls_recv_channel_switch,
|
||||
|
||||
.event_callback = iwl_mvm_mac_event_callback,
|
||||
|
||||
CFG80211_TESTMODE_CMD(iwl_mvm_mac_testmode_cmd)
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
@ -349,11 +349,12 @@ struct iwl_mvm_vif_bf_data {
|
||||
* @bcast_sta: station used for broadcast packets. Used by the following
|
||||
* vifs: P2P_DEVICE, GO and AP.
|
||||
* @beacon_skb: the skb used to hold the AP/GO beacon template
|
||||
* @smps_requests: the SMPS requests of differents parts of the driver,
|
||||
* @smps_requests: the SMPS requests of different parts of the driver,
|
||||
* combined on update to yield the overall request to mac80211.
|
||||
* @beacon_stats: beacon statistics, containing the # of received beacons,
|
||||
* # of received beacons accumulated over FW restart, and the current
|
||||
* average signal of beacons retrieved from the firmware
|
||||
* @csa_failed: CSA failed to schedule time event, report an error later
|
||||
*/
|
||||
struct iwl_mvm_vif {
|
||||
struct iwl_mvm *mvm;
|
||||
@ -433,6 +434,7 @@ struct iwl_mvm_vif {
|
||||
|
||||
/* Indicates that CSA countdown may be started */
|
||||
bool csa_countdown;
|
||||
bool csa_failed;
|
||||
};
|
||||
|
||||
static inline struct iwl_mvm_vif *
|
||||
@ -686,7 +688,7 @@ struct iwl_mvm {
|
||||
bool disable_power_off;
|
||||
bool disable_power_off_d3;
|
||||
|
||||
bool scan_iter_notif_enabled;
|
||||
u32 scan_iter_notif_enabled; /* must be u32 for debugfs_create_bool */
|
||||
|
||||
struct debugfs_blob_wrapper nvm_hw_blob;
|
||||
struct debugfs_blob_wrapper nvm_sw_blob;
|
||||
@ -746,6 +748,7 @@ struct iwl_mvm {
|
||||
void *d3_resume_sram;
|
||||
u32 d3_test_pme_ptr;
|
||||
struct ieee80211_vif *keep_vif;
|
||||
u32 last_netdetect_scans; /* no. of scans in the last net-detect wake */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -934,7 +937,8 @@ static inline bool iwl_mvm_is_lar_supported(struct iwl_mvm *mvm)
|
||||
|
||||
static inline bool iwl_mvm_is_wifi_mcc_supported(struct iwl_mvm *mvm)
|
||||
{
|
||||
return mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_WIFI_MCC_UPDATE;
|
||||
return mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_WIFI_MCC_UPDATE ||
|
||||
mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC;
|
||||
}
|
||||
|
||||
static inline bool iwl_mvm_is_scd_cfg_supported(struct iwl_mvm *mvm)
|
||||
@ -1146,6 +1150,7 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, bool force_upload,
|
||||
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);
|
||||
void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm);
|
||||
|
||||
/* Scheduled scan */
|
||||
int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm,
|
||||
@ -1475,8 +1480,12 @@ int iwl_mvm_fw_dbg_collect_desc(struct iwl_mvm *mvm,
|
||||
void iwl_mvm_free_fw_dump_desc(struct iwl_mvm *mvm);
|
||||
int iwl_mvm_fw_dbg_collect_trig(struct iwl_mvm *mvm,
|
||||
struct iwl_fw_dbg_trigger_tlv *trigger,
|
||||
const char *str, size_t len);
|
||||
|
||||
const char *fmt, ...) __printf(3, 4);
|
||||
unsigned int iwl_mvm_get_wd_timeout(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
bool tdls, bool cmd_q);
|
||||
void iwl_mvm_connection_loss(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
const char *errmsg);
|
||||
static inline bool
|
||||
iwl_fw_dbg_trigger_vif_match(struct iwl_fw_dbg_trigger_tlv *trig,
|
||||
struct ieee80211_vif *vif)
|
||||
@ -1509,8 +1518,7 @@ iwl_fw_dbg_trigger_check_stop(struct iwl_mvm *mvm,
|
||||
static inline void
|
||||
iwl_fw_dbg_trigger_simple_stop(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
enum iwl_fw_dbg_trigger trig,
|
||||
const char *str, size_t len)
|
||||
enum iwl_fw_dbg_trigger trig)
|
||||
{
|
||||
struct iwl_fw_dbg_trigger_tlv *trigger;
|
||||
|
||||
@ -1521,7 +1529,7 @@ iwl_fw_dbg_trigger_simple_stop(struct iwl_mvm *mvm,
|
||||
if (!iwl_fw_dbg_trigger_check_stop(mvm, vif, trigger))
|
||||
return;
|
||||
|
||||
iwl_mvm_fw_dbg_collect_trig(mvm, trigger, str, len);
|
||||
iwl_mvm_fw_dbg_collect_trig(mvm, trigger, NULL);
|
||||
}
|
||||
|
||||
#endif /* __IWL_MVM_H__ */
|
||||
|
@ -77,8 +77,7 @@
|
||||
/* Default NVM size to read */
|
||||
#define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024)
|
||||
#define IWL_MAX_NVM_SECTION_SIZE 0x1b58
|
||||
#define IWL_MAX_NVM_8000A_SECTION_SIZE 0xffc
|
||||
#define IWL_MAX_NVM_8000B_SECTION_SIZE 0x1ffc
|
||||
#define IWL_MAX_NVM_8000_SECTION_SIZE 0x1ffc
|
||||
|
||||
#define NVM_WRITE_OPCODE 1
|
||||
#define NVM_READ_OPCODE 0
|
||||
@ -267,7 +266,7 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
|
||||
{
|
||||
struct iwl_nvm_section *sections = mvm->nvm_sections;
|
||||
const __le16 *hw, *sw, *calib, *regulatory, *mac_override, *phy_sku;
|
||||
bool is_family_8000_a_step = false, lar_enabled;
|
||||
bool lar_enabled;
|
||||
u32 mac_addr0, mac_addr1;
|
||||
|
||||
/* Checking for required sections */
|
||||
@ -293,12 +292,8 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (CSR_HW_REV_STEP(mvm->trans->hw_rev) == SILICON_A_STEP)
|
||||
is_family_8000_a_step = true;
|
||||
|
||||
/* PHY_SKU section is mandatory in B0 */
|
||||
if (!is_family_8000_a_step &&
|
||||
!mvm->nvm_sections[NVM_SECTION_TYPE_PHY_SKU].data) {
|
||||
if (!mvm->nvm_sections[NVM_SECTION_TYPE_PHY_SKU].data) {
|
||||
IWL_ERR(mvm,
|
||||
"Can't parse phy_sku in B0, empty sections\n");
|
||||
return NULL;
|
||||
@ -327,8 +322,7 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
|
||||
return iwl_parse_nvm_data(mvm->trans->dev, mvm->cfg, hw, sw, calib,
|
||||
regulatory, mac_override, phy_sku,
|
||||
mvm->fw->valid_tx_ant, mvm->fw->valid_rx_ant,
|
||||
lar_enabled, is_family_8000_a_step,
|
||||
mac_addr0, mac_addr1);
|
||||
lar_enabled, mac_addr0, mac_addr1);
|
||||
}
|
||||
|
||||
#define MAX_NVM_FILE_LEN 16384
|
||||
@ -381,10 +375,8 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm)
|
||||
/* Maximal size depends on HW family and step */
|
||||
if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000)
|
||||
max_section_size = IWL_MAX_NVM_SECTION_SIZE;
|
||||
else if (CSR_HW_REV_STEP(mvm->trans->hw_rev) == SILICON_A_STEP)
|
||||
max_section_size = IWL_MAX_NVM_8000A_SECTION_SIZE;
|
||||
else /* Family 8000 B-step or C-step */
|
||||
max_section_size = IWL_MAX_NVM_8000B_SECTION_SIZE;
|
||||
else
|
||||
max_section_size = IWL_MAX_NVM_8000_SECTION_SIZE;
|
||||
|
||||
/*
|
||||
* Obtain NVM image via request_firmware. Since we already used
|
||||
@ -426,6 +418,15 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm)
|
||||
IWL_INFO(mvm, "NVM Version %08X\n", le32_to_cpu(dword_buff[2]));
|
||||
IWL_INFO(mvm, "NVM Manufacturing date %08X\n",
|
||||
le32_to_cpu(dword_buff[3]));
|
||||
|
||||
/* nvm file validation, dword_buff[2] holds the file version */
|
||||
if ((CSR_HW_REV_STEP(mvm->trans->hw_rev) == SILICON_C_STEP &&
|
||||
le32_to_cpu(dword_buff[2]) < 0xE4A) ||
|
||||
(CSR_HW_REV_STEP(mvm->trans->hw_rev) == SILICON_B_STEP &&
|
||||
le32_to_cpu(dword_buff[2]) >= 0xE4A)) {
|
||||
ret = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
file_sec = (void *)fw_entry->data;
|
||||
}
|
||||
@ -524,6 +525,8 @@ int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic)
|
||||
int ret, section;
|
||||
u32 size_read = 0;
|
||||
u8 *nvm_buffer, *temp;
|
||||
const char *nvm_file_B = mvm->cfg->default_nvm_file_B_step;
|
||||
const char *nvm_file_C = mvm->cfg->default_nvm_file_C_step;
|
||||
|
||||
if (WARN_ON_ONCE(mvm->cfg->nvm_hw_section_num >= NVM_MAX_NUM_SECTIONS))
|
||||
return -EINVAL;
|
||||
@ -582,10 +585,27 @@ int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic)
|
||||
|
||||
/* load external NVM if configured */
|
||||
if (mvm->nvm_file_name) {
|
||||
/* move to External NVM flow */
|
||||
/* read External NVM file - take the default */
|
||||
ret = iwl_mvm_read_external_nvm(mvm);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (ret) {
|
||||
/* choose the nvm_file name according to the
|
||||
* HW step
|
||||
*/
|
||||
if (CSR_HW_REV_STEP(mvm->trans->hw_rev) ==
|
||||
SILICON_B_STEP)
|
||||
mvm->nvm_file_name = nvm_file_B;
|
||||
else
|
||||
mvm->nvm_file_name = nvm_file_C;
|
||||
|
||||
if (ret == -EFAULT && mvm->nvm_file_name) {
|
||||
/* in case nvm file was failed try again */
|
||||
ret = iwl_mvm_read_external_nvm(mvm);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* parse the relevant nvm sections */
|
||||
@ -786,13 +806,12 @@ int iwl_mvm_init_mcc(struct iwl_mvm *mvm)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* During HW restart, only replay the last set MCC to FW. Otherwise,
|
||||
* try to replay the last set MCC to FW. If it doesn't exist,
|
||||
* queue an update to cfg80211 to retrieve the default alpha2 from FW.
|
||||
*/
|
||||
if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
|
||||
/* This should only be called during vif up and hold RTNL */
|
||||
return iwl_mvm_init_fw_regd(mvm);
|
||||
}
|
||||
retval = iwl_mvm_init_fw_regd(mvm);
|
||||
if (retval != -ENOENT)
|
||||
return retval;
|
||||
|
||||
/*
|
||||
* Driver regulatory hint for initial update, this also informs the
|
||||
|
@ -488,8 +488,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
|
||||
/* Set a short watchdog for the command queue */
|
||||
trans_cfg.cmd_q_wdg_timeout =
|
||||
iwlmvm_mod_params.tfd_q_hang_detect ? IWL_DEF_WD_TIMEOUT :
|
||||
IWL_WATCHDOG_DISABLED;
|
||||
iwl_mvm_get_wd_timeout(mvm, NULL, false, true);
|
||||
|
||||
snprintf(mvm->hw->wiphy->fw_version,
|
||||
sizeof(mvm->hw->wiphy->fw_version),
|
||||
@ -524,12 +523,11 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
/* set the nvm_file_name according to priority */
|
||||
if (iwlwifi_mod_params.nvm_file) {
|
||||
mvm->nvm_file_name = iwlwifi_mod_params.nvm_file;
|
||||
} else {
|
||||
if ((trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) &&
|
||||
(CSR_HW_REV_STEP(trans->hw_rev) == SILICON_A_STEP))
|
||||
mvm->nvm_file_name = mvm->cfg->default_nvm_file_8000A;
|
||||
} else if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) {
|
||||
if (CSR_HW_REV_STEP(trans->hw_rev) == SILICON_B_STEP)
|
||||
mvm->nvm_file_name = mvm->cfg->default_nvm_file_B_step;
|
||||
else
|
||||
mvm->nvm_file_name = mvm->cfg->default_nvm_file;
|
||||
mvm->nvm_file_name = mvm->cfg->default_nvm_file_C_step;
|
||||
}
|
||||
|
||||
if (WARN(cfg->no_power_up_nic_in_init && !mvm->nvm_file_name,
|
||||
@ -691,7 +689,6 @@ static inline void iwl_mvm_rx_check_trigger(struct iwl_mvm *mvm,
|
||||
{
|
||||
struct iwl_fw_dbg_trigger_tlv *trig;
|
||||
struct iwl_fw_dbg_trigger_cmd *cmds_trig;
|
||||
char buf[32];
|
||||
int i;
|
||||
|
||||
if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_FW_NOTIF))
|
||||
@ -711,9 +708,9 @@ static inline void iwl_mvm_rx_check_trigger(struct iwl_mvm *mvm,
|
||||
if (cmds_trig->cmds[i].cmd_id != pkt->hdr.cmd)
|
||||
continue;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
snprintf(buf, sizeof(buf), "CMD 0x%02x received", pkt->hdr.cmd);
|
||||
iwl_mvm_fw_dbg_collect_trig(mvm, trig, buf, sizeof(buf));
|
||||
iwl_mvm_fw_dbg_collect_trig(mvm, trig,
|
||||
"CMD 0x%02x received",
|
||||
pkt->hdr.cmd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -894,18 +891,7 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error)
|
||||
* the next start() call from mac80211. If restart isn't called
|
||||
* (no fw restart) scan status will stay busy.
|
||||
*/
|
||||
switch (mvm->scan_status) {
|
||||
case IWL_MVM_SCAN_NONE:
|
||||
break;
|
||||
case IWL_MVM_SCAN_OS:
|
||||
ieee80211_scan_completed(mvm->hw, true);
|
||||
break;
|
||||
case IWL_MVM_SCAN_SCHED:
|
||||
/* Sched scan will be restarted by mac80211 in restart_hw. */
|
||||
if (!mvm->restart_fw)
|
||||
ieee80211_sched_scan_stopped(mvm->hw);
|
||||
break;
|
||||
}
|
||||
iwl_mvm_report_scan_aborted(mvm);
|
||||
|
||||
/*
|
||||
* If we're restarting already, don't cycle restarts.
|
||||
@ -1175,7 +1161,7 @@ static void iwl_mvm_d0i3_disconnect_iter(void *data, u8 *mac,
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_STATION && vif->bss_conf.assoc &&
|
||||
mvm->d0i3_ap_sta_id == mvmvif->ap_sta_id)
|
||||
ieee80211_connection_loss(vif);
|
||||
iwl_mvm_connection_loss(mvm, vif, "D0i3");
|
||||
}
|
||||
|
||||
void iwl_mvm_d0i3_enable_tx(struct iwl_mvm *mvm, __le16 *qos_seq)
|
||||
|
@ -67,7 +67,7 @@
|
||||
#include "fw-api.h"
|
||||
#include "mvm.h"
|
||||
|
||||
/* Maps the driver specific channel width definition to the the fw values */
|
||||
/* Maps the driver specific channel width definition to the fw values */
|
||||
u8 iwl_mvm_get_channel_width(struct cfg80211_chan_def *chandef)
|
||||
{
|
||||
switch (chandef->width) {
|
||||
|
@ -1277,9 +1277,7 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
||||
info->status.ampdu_ack_len);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* For legacy, update frame history with for each Tx retry.
|
||||
*/
|
||||
/* For legacy, update frame history with for each Tx retry. */
|
||||
retries = info->status.rates[0].count - 1;
|
||||
/* HW doesn't send more than 15 retries */
|
||||
retries = min(retries, 15);
|
||||
@ -1615,9 +1613,9 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search)
|
||||
static void rs_update_rate_tbl(struct iwl_mvm *mvm,
|
||||
struct ieee80211_sta *sta,
|
||||
struct iwl_lq_sta *lq_sta,
|
||||
struct rs_rate *rate)
|
||||
struct iwl_scale_tbl_info *tbl)
|
||||
{
|
||||
rs_fill_lq_cmd(mvm, sta, lq_sta, rate);
|
||||
rs_fill_lq_cmd(mvm, sta, lq_sta, &tbl->rate);
|
||||
iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, false);
|
||||
}
|
||||
|
||||
@ -2147,7 +2145,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
|
||||
rate->type = LQ_NONE;
|
||||
lq_sta->search_better_tbl = 0;
|
||||
tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
|
||||
rs_update_rate_tbl(mvm, sta, lq_sta, &tbl->rate);
|
||||
rs_update_rate_tbl(mvm, sta, lq_sta, tbl);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -2310,7 +2308,7 @@ lq_update:
|
||||
/* Replace uCode's rate table for the destination station. */
|
||||
if (update_lq) {
|
||||
tbl->rate.index = index;
|
||||
rs_update_rate_tbl(mvm, sta, lq_sta, &tbl->rate);
|
||||
rs_update_rate_tbl(mvm, sta, lq_sta, tbl);
|
||||
}
|
||||
|
||||
rs_stay_in_table(lq_sta, false);
|
||||
@ -2357,8 +2355,7 @@ lq_update:
|
||||
|
||||
rs_dump_rate(mvm, &tbl->rate,
|
||||
"Switch to SEARCH TABLE:");
|
||||
rs_fill_lq_cmd(mvm, sta, lq_sta, &tbl->rate);
|
||||
iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, false);
|
||||
rs_update_rate_tbl(mvm, sta, lq_sta, tbl);
|
||||
} else {
|
||||
done_search = 1;
|
||||
}
|
||||
@ -3238,7 +3235,7 @@ static void rs_fill_lq_cmd(struct iwl_mvm *mvm,
|
||||
lq_cmd->agg_frame_cnt_limit = mvmsta->max_agg_bufsize;
|
||||
|
||||
/*
|
||||
* In case of low latency, tell the firwmare to leave a frame in the
|
||||
* In case of low latency, tell the firmware to leave a frame in the
|
||||
* Tx Fifo so that it can start a transaction in the same TxOP. This
|
||||
* basically allows the firmware to send bursts.
|
||||
*/
|
||||
@ -3745,7 +3742,7 @@ void iwl_mvm_rate_control_unregister(void)
|
||||
|
||||
/**
|
||||
* iwl_mvm_tx_protection - Gets LQ command, change it to enable/disable
|
||||
* Tx protection, according to this rquest and previous requests,
|
||||
* Tx protection, according to this request and previous requests,
|
||||
* and send the LQ command.
|
||||
* @mvmsta: The station
|
||||
* @enable: Enable Tx protection?
|
||||
|
@ -362,7 +362,7 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
|
||||
iwl_fw_dbg_trigger_check_stop(mvm, mvmsta->vif,
|
||||
trig);
|
||||
if (trig_check && rx_status->signal < rssi)
|
||||
iwl_mvm_fw_dbg_collect_trig(mvm, trig, NULL, 0);
|
||||
iwl_mvm_fw_dbg_collect_trig(mvm, trig, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -552,7 +552,7 @@ iwl_mvm_rx_stats_check_trigger(struct iwl_mvm *mvm, struct iwl_rx_packet *pkt)
|
||||
if (le32_to_cpup((__le32 *) (pkt->data + trig_offset)) < trig_thold)
|
||||
return;
|
||||
|
||||
iwl_mvm_fw_dbg_collect_trig(mvm, trig, NULL, 0);
|
||||
iwl_mvm_fw_dbg_collect_trig(mvm, trig, NULL);
|
||||
}
|
||||
|
||||
void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm,
|
||||
|
@ -935,6 +935,8 @@ int iwl_mvm_unified_sched_scan_lmac(struct iwl_mvm *mvm,
|
||||
|
||||
cmd->n_channels = (u8)req->n_channels;
|
||||
|
||||
cmd->delay = cpu_to_le32(req->delay);
|
||||
|
||||
if (iwl_mvm_scan_pass_all(mvm, req))
|
||||
flags |= IWL_MVM_LMAC_SCAN_FLAG_PASS_ALL;
|
||||
else
|
||||
@ -1177,6 +1179,18 @@ static bool iwl_mvm_find_scan_type(struct iwl_mvm *mvm,
|
||||
return false;
|
||||
}
|
||||
|
||||
static int iwl_mvm_find_first_scan(struct iwl_mvm *mvm,
|
||||
enum iwl_umac_scan_uid_type type)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < IWL_MVM_MAX_SIMULTANEOUS_SCANS; i++)
|
||||
if (mvm->scan_uid[i] & type)
|
||||
return i;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static u32 iwl_generate_scan_uid(struct iwl_mvm *mvm,
|
||||
enum iwl_umac_scan_uid_type type)
|
||||
{
|
||||
@ -1436,7 +1450,13 @@ int iwl_mvm_sched_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
cpu_to_le16(req->interval / MSEC_PER_SEC);
|
||||
sec_part->schedule[0].iter_count = 0xff;
|
||||
|
||||
sec_part->delay = 0;
|
||||
if (req->delay > U16_MAX) {
|
||||
IWL_DEBUG_SCAN(mvm,
|
||||
"delay value is > 16-bits, set to max possible\n");
|
||||
sec_part->delay = cpu_to_le16(U16_MAX);
|
||||
} else {
|
||||
sec_part->delay = cpu_to_le16(req->delay);
|
||||
}
|
||||
|
||||
iwl_mvm_build_unified_scan_probe(mvm, vif, ies, &sec_part->preq,
|
||||
req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR ?
|
||||
@ -1613,3 +1633,54 @@ int iwl_mvm_scan_size(struct iwl_mvm *mvm)
|
||||
mvm->fw->ucode_capa.n_scan_channels +
|
||||
sizeof(struct iwl_scan_probe_req);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is used in nic restart flow, to inform mac80211 about scans
|
||||
* that was aborted by restart flow or by an assert.
|
||||
*/
|
||||
void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm)
|
||||
{
|
||||
if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN) {
|
||||
u32 uid, i;
|
||||
|
||||
uid = iwl_mvm_find_first_scan(mvm, IWL_UMAC_SCAN_UID_REG_SCAN);
|
||||
if (uid < IWL_MVM_MAX_SIMULTANEOUS_SCANS) {
|
||||
ieee80211_scan_completed(mvm->hw, true);
|
||||
mvm->scan_uid[uid] = 0;
|
||||
}
|
||||
uid = iwl_mvm_find_first_scan(mvm,
|
||||
IWL_UMAC_SCAN_UID_SCHED_SCAN);
|
||||
if (uid < IWL_MVM_MAX_SIMULTANEOUS_SCANS && !mvm->restart_fw) {
|
||||
ieee80211_sched_scan_stopped(mvm->hw);
|
||||
mvm->scan_uid[uid] = 0;
|
||||
}
|
||||
|
||||
/* We shouldn't have any UIDs still set. Loop over all the
|
||||
* UIDs to make sure there's nothing left there and warn if
|
||||
* any is found.
|
||||
*/
|
||||
for (i = 0; i < IWL_MVM_MAX_SIMULTANEOUS_SCANS; i++) {
|
||||
if (WARN_ONCE(mvm->scan_uid[i],
|
||||
"UMAC scan UID %d was not cleaned\n",
|
||||
mvm->scan_uid[i]))
|
||||
mvm->scan_uid[i] = 0;
|
||||
}
|
||||
} else {
|
||||
switch (mvm->scan_status) {
|
||||
case IWL_MVM_SCAN_NONE:
|
||||
break;
|
||||
case IWL_MVM_SCAN_OS:
|
||||
ieee80211_scan_completed(mvm->hw, true);
|
||||
break;
|
||||
case IWL_MVM_SCAN_SCHED:
|
||||
/*
|
||||
* Sched scan will be restarted by mac80211 in
|
||||
* restart_hw, so do not report if FW is about to be
|
||||
* restarted.
|
||||
*/
|
||||
if (!mvm->restart_fw)
|
||||
ieee80211_sched_scan_stopped(mvm->hw);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -209,9 +209,8 @@ static int iwl_mvm_tdls_sta_init(struct iwl_mvm *mvm,
|
||||
{
|
||||
unsigned long used_hw_queues;
|
||||
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
unsigned int wdg_timeout = iwlmvm_mod_params.tfd_q_hang_detect ?
|
||||
mvm->cfg->base_params->wd_timeout :
|
||||
IWL_WATCHDOG_DISABLED;
|
||||
unsigned int wdg_timeout =
|
||||
iwl_mvm_get_wd_timeout(mvm, NULL, true, false);
|
||||
u32 ac;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
@ -491,8 +490,18 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_STATION &&
|
||||
mvmvif->ap_sta_id == mvm_sta->sta_id) {
|
||||
ret = iwl_mvm_drain_sta(mvm, mvm_sta, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
/* flush its queues here since we are freeing mvm_sta */
|
||||
ret = iwl_mvm_flush_tx_path(mvm, mvm_sta->tfd_queue_msk, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = iwl_trans_wait_tx_queue_empty(mvm->trans,
|
||||
mvm_sta->tfd_queue_msk);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = iwl_mvm_drain_sta(mvm, mvm_sta, false);
|
||||
|
||||
/* if we are associated - we can't remove the AP STA now */
|
||||
if (vif->bss_conf.assoc)
|
||||
@ -971,9 +980,8 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
{
|
||||
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid];
|
||||
unsigned int wdg_timeout = iwlmvm_mod_params.tfd_q_hang_detect ?
|
||||
mvm->cfg->base_params->wd_timeout :
|
||||
IWL_WATCHDOG_DISABLED;
|
||||
unsigned int wdg_timeout =
|
||||
iwl_mvm_get_wd_timeout(mvm, vif, sta->tdls, false);
|
||||
int queue, fifo, ret;
|
||||
u16 ssn;
|
||||
|
||||
@ -1120,8 +1128,12 @@ int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
spin_unlock_bh(&mvmsta->lock);
|
||||
|
||||
if (old_state >= IWL_AGG_ON) {
|
||||
iwl_mvm_drain_sta(mvm, mvmsta, true);
|
||||
if (iwl_mvm_flush_tx_path(mvm, BIT(txq_id), true))
|
||||
IWL_ERR(mvm, "Couldn't flush the AGG queue\n");
|
||||
iwl_trans_wait_tx_queue_empty(mvm->trans,
|
||||
mvmsta->tfd_queue_msk);
|
||||
iwl_mvm_drain_sta(mvm, mvmsta, false);
|
||||
|
||||
iwl_mvm_sta_tx_agg(mvm, sta, tid, txq_id, false);
|
||||
|
||||
@ -1702,8 +1714,8 @@ void iwl_mvm_sta_modify_disable_tx_ap(struct iwl_mvm *mvm,
|
||||
mvm_sta->disable_tx = disable;
|
||||
|
||||
/*
|
||||
* Tell mac80211 to start/stop queueing tx for this station,
|
||||
* but don't stop queueing if there are still pending frames
|
||||
* Tell mac80211 to start/stop queuing tx for this station,
|
||||
* but don't stop queuing if there are still pending frames
|
||||
* for this station.
|
||||
*/
|
||||
if (disable || !atomic_read(&mvm->pending_frames[mvm_sta->sta_id]))
|
||||
|
@ -150,7 +150,7 @@ struct iwl_mvm_vif;
|
||||
* DOC: station table - AP Station in STA mode
|
||||
*
|
||||
* %iwl_mvm_vif includes the index of the AP station in the fw's STA table:
|
||||
* %ap_sta_id. To get the point to the coresponsding %ieee80211_sta,
|
||||
* %ap_sta_id. To get the point to the corresponding %ieee80211_sta,
|
||||
* &fw_id_to_mac_id can be used. Due to the way the fw works, we must not remove
|
||||
* the AP station from the fw before setting the MAC context as unassociated.
|
||||
* Hence, %fw_id_to_mac_id[%ap_sta_id] will be NULLed when the AP station is
|
||||
@ -209,14 +209,14 @@ struct iwl_mvm_vif;
|
||||
* When a trigger frame is received, mac80211 tells the driver to send frames
|
||||
* from the AMPDU queues or sends frames to non-aggregation queues itself,
|
||||
* depending on which ACs are delivery-enabled and what TID has frames to
|
||||
* transmit. Note that mac80211 has all the knowledege since all the non-agg
|
||||
* transmit. Note that mac80211 has all the knowledge since all the non-agg
|
||||
* frames are buffered / filtered, and the driver tells mac80211 about agg
|
||||
* frames). The driver needs to tell the fw to let frames out even if the
|
||||
* station is asleep. This is done by %iwl_mvm_sta_modify_sleep_tx_count.
|
||||
*
|
||||
* When we receive a frame from that station with PM bit unset, the driver
|
||||
* needs to let the fw know that this station isn't asleep any more. This is
|
||||
* done by %iwl_mvm_sta_modify_ps_wake in response to mac80211 signalling the
|
||||
* done by %iwl_mvm_sta_modify_ps_wake in response to mac80211 signaling the
|
||||
* station's wakeup.
|
||||
*
|
||||
* For a GO, the Service Period might be cut short due to an absence period
|
||||
|
@ -119,7 +119,7 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk)
|
||||
|
||||
/*
|
||||
* Flush the offchannel queue -- this is called when the time
|
||||
* event finishes or is cancelled, so that frames queued for it
|
||||
* event finishes or is canceled, so that frames queued for it
|
||||
* won't get stuck on the queue and be transmitted in the next
|
||||
* time event.
|
||||
* We have to send the command asynchronously since this cannot
|
||||
@ -187,7 +187,8 @@ static bool iwl_mvm_te_check_disconnect(struct iwl_mvm *mvm,
|
||||
return false;
|
||||
if (errmsg)
|
||||
IWL_ERR(mvm, "%s\n", errmsg);
|
||||
ieee80211_connection_loss(vif);
|
||||
|
||||
iwl_mvm_connection_loss(mvm, vif, errmsg);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -196,19 +197,24 @@ iwl_mvm_te_handle_notify_csa(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_time_event_data *te_data,
|
||||
struct iwl_time_event_notif *notif)
|
||||
{
|
||||
if (!le32_to_cpu(notif->status)) {
|
||||
if (te_data->vif->type == NL80211_IFTYPE_STATION)
|
||||
ieee80211_connection_loss(te_data->vif);
|
||||
struct ieee80211_vif *vif = te_data->vif;
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
if (!notif->status)
|
||||
IWL_DEBUG_TE(mvm, "CSA time event failed to start\n");
|
||||
iwl_mvm_te_clear_data(mvm, te_data);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (te_data->vif->type) {
|
||||
case NL80211_IFTYPE_AP:
|
||||
if (!notif->status)
|
||||
mvmvif->csa_failed = true;
|
||||
iwl_mvm_csa_noa_start(mvm);
|
||||
break;
|
||||
case NL80211_IFTYPE_STATION:
|
||||
if (!notif->status) {
|
||||
iwl_mvm_connection_loss(mvm, vif,
|
||||
"CSA TE failed to start");
|
||||
break;
|
||||
}
|
||||
iwl_mvm_csa_client_absent(mvm, te_data->vif);
|
||||
ieee80211_chswitch_done(te_data->vif, true);
|
||||
break;
|
||||
@ -222,6 +228,44 @@ iwl_mvm_te_handle_notify_csa(struct iwl_mvm *mvm,
|
||||
iwl_mvm_te_clear_data(mvm, te_data);
|
||||
}
|
||||
|
||||
static void iwl_mvm_te_check_trigger(struct iwl_mvm *mvm,
|
||||
struct iwl_time_event_notif *notif,
|
||||
struct iwl_mvm_time_event_data *te_data)
|
||||
{
|
||||
struct iwl_fw_dbg_trigger_tlv *trig;
|
||||
struct iwl_fw_dbg_trigger_time_event *te_trig;
|
||||
int i;
|
||||
|
||||
if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_TIME_EVENT))
|
||||
return;
|
||||
|
||||
trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_TIME_EVENT);
|
||||
te_trig = (void *)trig->data;
|
||||
|
||||
if (!iwl_fw_dbg_trigger_check_stop(mvm, te_data->vif, trig))
|
||||
return;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(te_trig->time_events); i++) {
|
||||
u32 trig_te_id = le32_to_cpu(te_trig->time_events[i].id);
|
||||
u32 trig_action_bitmap =
|
||||
le32_to_cpu(te_trig->time_events[i].action_bitmap);
|
||||
u32 trig_status_bitmap =
|
||||
le32_to_cpu(te_trig->time_events[i].status_bitmap);
|
||||
|
||||
if (trig_te_id != te_data->id ||
|
||||
!(trig_action_bitmap & le32_to_cpu(notif->action)) ||
|
||||
!(trig_status_bitmap & BIT(le32_to_cpu(notif->status))))
|
||||
continue;
|
||||
|
||||
iwl_mvm_fw_dbg_collect_trig(mvm, trig,
|
||||
"Time event %d Action 0x%x received status: %d",
|
||||
te_data->id,
|
||||
le32_to_cpu(notif->action),
|
||||
le32_to_cpu(notif->status));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Handles a FW notification for an event that is known to the driver.
|
||||
*
|
||||
@ -239,6 +283,8 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
|
||||
le32_to_cpu(notif->unique_id),
|
||||
le32_to_cpu(notif->action));
|
||||
|
||||
iwl_mvm_te_check_trigger(mvm, notif, te_data);
|
||||
|
||||
/*
|
||||
* The FW sends the start/end time event notifications even for events
|
||||
* that it fails to schedule. This is indicated in the status field of
|
||||
@ -248,11 +294,16 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
|
||||
* events in the system).
|
||||
*/
|
||||
if (!le32_to_cpu(notif->status)) {
|
||||
bool start = le32_to_cpu(notif->action) &
|
||||
TE_V2_NOTIF_HOST_EVENT_START;
|
||||
IWL_WARN(mvm, "Time Event %s notification failure\n",
|
||||
start ? "start" : "end");
|
||||
if (iwl_mvm_te_check_disconnect(mvm, te_data->vif, NULL)) {
|
||||
const char *msg;
|
||||
|
||||
if (notif->action & cpu_to_le32(TE_V2_NOTIF_HOST_EVENT_START))
|
||||
msg = "Time Event start notification failure";
|
||||
else
|
||||
msg = "Time Event end notification failure";
|
||||
|
||||
IWL_DEBUG_TE(mvm, "%s\n", msg);
|
||||
|
||||
if (iwl_mvm_te_check_disconnect(mvm, te_data->vif, msg)) {
|
||||
iwl_mvm_te_clear_data(mvm, te_data);
|
||||
return;
|
||||
}
|
||||
@ -315,6 +366,8 @@ static int iwl_mvm_aux_roc_te_handle_notif(struct iwl_mvm *mvm,
|
||||
if (!aux_roc_te) /* Not a Aux ROC time event */
|
||||
return -EINVAL;
|
||||
|
||||
iwl_mvm_te_check_trigger(mvm, notif, te_data);
|
||||
|
||||
if (!le32_to_cpu(notif->status)) {
|
||||
IWL_DEBUG_TE(mvm,
|
||||
"ERROR: Aux ROC Time Event %s notification failure\n",
|
||||
@ -769,7 +822,7 @@ void iwl_mvm_stop_roc(struct iwl_mvm *mvm)
|
||||
* Iterate over the list of aux roc time events and find the time
|
||||
* event that is associated with a BSS interface.
|
||||
* This assumes that a BSS interface can have only a single time
|
||||
* event at any given time and this time event coresponds to a ROC
|
||||
* event at any given time and this time event corresponds to a ROC
|
||||
* request
|
||||
*/
|
||||
list_for_each_entry(te_data, &mvm->aux_roc_te_list, list) {
|
||||
|
@ -147,7 +147,7 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm,
|
||||
* @vif: the virtual interface for which the session is issued
|
||||
*
|
||||
* This functions cancels the session protection which is an act of good
|
||||
* citizenship. If it is not needed any more it should be cancelled because
|
||||
* citizenship. If it is not needed any more it should be canceled because
|
||||
* the other bindings wait for the medium during that time.
|
||||
* This funtions doesn't sleep.
|
||||
*/
|
||||
@ -162,7 +162,7 @@ int iwl_mvm_rx_time_event_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_device_cmd *cmd);
|
||||
|
||||
/**
|
||||
* iwl_mvm_start_p2p_roc - start remain on channel for p2p device functionlity
|
||||
* iwl_mvm_start_p2p_roc - start remain on channel for p2p device functionality
|
||||
* @mvm: the mvm component
|
||||
* @vif: the virtual interface for which the roc is requested. It is assumed
|
||||
* that the vif type is NL80211_IFTYPE_P2P_DEVICE
|
||||
|
@ -1049,6 +1049,14 @@ out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that there are transports that buffer frames before they reach
|
||||
* the firmware. This means that after flush_tx_path is called, the
|
||||
* queue might not be empty. The race-free way to handle this is to:
|
||||
* 1) set the station as draining
|
||||
* 2) flush the Tx path
|
||||
* 3) wait for the transport queues to be empty
|
||||
*/
|
||||
int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, bool sync)
|
||||
{
|
||||
int ret;
|
||||
|
@ -122,7 +122,7 @@ int iwl_mvm_send_cmd_pdu(struct iwl_mvm *mvm, u8 id,
|
||||
}
|
||||
|
||||
/*
|
||||
* We assume that the caller set the status to the sucess value
|
||||
* We assume that the caller set the status to the success value
|
||||
*/
|
||||
int iwl_mvm_send_cmd_status(struct iwl_mvm *mvm, struct iwl_host_cmd *cmd,
|
||||
u32 *status)
|
||||
@ -737,7 +737,7 @@ int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, bool init)
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_mvm_update_smps - Get a requst to change the SMPS mode
|
||||
* iwl_mvm_update_smps - Get a request to change the SMPS mode
|
||||
* @req_type: The part of the driver who call for a change.
|
||||
* @smps_requests: The request to change the SMPS mode.
|
||||
*
|
||||
@ -921,3 +921,71 @@ struct ieee80211_vif *iwl_mvm_get_bss_vif(struct iwl_mvm *mvm)
|
||||
|
||||
return bss_iter_data.vif;
|
||||
}
|
||||
|
||||
unsigned int iwl_mvm_get_wd_timeout(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
bool tdls, bool cmd_q)
|
||||
{
|
||||
struct iwl_fw_dbg_trigger_tlv *trigger;
|
||||
struct iwl_fw_dbg_trigger_txq_timer *txq_timer;
|
||||
unsigned int default_timeout =
|
||||
cmd_q ? IWL_DEF_WD_TIMEOUT : mvm->cfg->base_params->wd_timeout;
|
||||
|
||||
if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_TXQ_TIMERS))
|
||||
return iwlmvm_mod_params.tfd_q_hang_detect ?
|
||||
default_timeout : IWL_WATCHDOG_DISABLED;
|
||||
|
||||
trigger = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_TXQ_TIMERS);
|
||||
txq_timer = (void *)trigger->data;
|
||||
|
||||
if (tdls)
|
||||
return le32_to_cpu(txq_timer->tdls);
|
||||
|
||||
if (cmd_q)
|
||||
return le32_to_cpu(txq_timer->command_queue);
|
||||
|
||||
if (WARN_ON(!vif))
|
||||
return default_timeout;
|
||||
|
||||
switch (ieee80211_vif_type_p2p(vif)) {
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
return le32_to_cpu(txq_timer->ibss);
|
||||
case NL80211_IFTYPE_STATION:
|
||||
return le32_to_cpu(txq_timer->bss);
|
||||
case NL80211_IFTYPE_AP:
|
||||
return le32_to_cpu(txq_timer->softap);
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
return le32_to_cpu(txq_timer->p2p_client);
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
return le32_to_cpu(txq_timer->p2p_go);
|
||||
case NL80211_IFTYPE_P2P_DEVICE:
|
||||
return le32_to_cpu(txq_timer->p2p_device);
|
||||
default:
|
||||
WARN_ON(1);
|
||||
return mvm->cfg->base_params->wd_timeout;
|
||||
}
|
||||
}
|
||||
|
||||
void iwl_mvm_connection_loss(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
const char *errmsg)
|
||||
{
|
||||
struct iwl_fw_dbg_trigger_tlv *trig;
|
||||
struct iwl_fw_dbg_trigger_mlme *trig_mlme;
|
||||
|
||||
if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_MLME))
|
||||
goto out;
|
||||
|
||||
trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_MLME);
|
||||
trig_mlme = (void *)trig->data;
|
||||
if (!iwl_fw_dbg_trigger_check_stop(mvm, vif, trig))
|
||||
goto out;
|
||||
|
||||
if (trig_mlme->stop_connection_loss &&
|
||||
--trig_mlme->stop_connection_loss)
|
||||
goto out;
|
||||
|
||||
iwl_mvm_fw_dbg_collect_trig(mvm, trig, "%s", errmsg);
|
||||
|
||||
out:
|
||||
ieee80211_connection_loss(vif);
|
||||
}
|
||||
|
@ -600,9 +600,11 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
|
||||
if (pkt->len_n_flags == cpu_to_le32(FH_RSCSR_FRAME_INVALID))
|
||||
break;
|
||||
|
||||
IWL_DEBUG_RX(trans, "cmd at offset %d: %s (0x%.2x)\n",
|
||||
rxcb._offset, get_cmd_string(trans_pcie, pkt->hdr.cmd),
|
||||
pkt->hdr.cmd);
|
||||
IWL_DEBUG_RX(trans,
|
||||
"cmd at offset %d: %s (0x%.2x, seq 0x%x)\n",
|
||||
rxcb._offset,
|
||||
get_cmd_string(trans_pcie, pkt->hdr.cmd),
|
||||
pkt->hdr.cmd, le16_to_cpu(pkt->hdr.sequence));
|
||||
|
||||
len = iwl_rx_packet_len(pkt);
|
||||
len += sizeof(u32); /* account for status word */
|
||||
|
@ -691,11 +691,15 @@ static int iwl_pcie_rsa_race_bug_wa(struct iwl_trans *trans)
|
||||
{
|
||||
u32 val, loop = 1000;
|
||||
|
||||
/* Check the RSA semaphore is accessible - if not, we are in trouble */
|
||||
/*
|
||||
* Check the RSA semaphore is accessible.
|
||||
* If the HW isn't locked and the rsa semaphore isn't accessible,
|
||||
* we are in trouble.
|
||||
*/
|
||||
val = iwl_read_prph(trans, PREG_AUX_BUS_WPROT_0);
|
||||
if (val & (BIT(1) | BIT(17))) {
|
||||
IWL_ERR(trans,
|
||||
"can't access the RSA semaphore it is write protected\n");
|
||||
IWL_INFO(trans,
|
||||
"can't access the RSA semaphore it is write protected\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -719,10 +723,10 @@ static int iwl_pcie_rsa_race_bug_wa(struct iwl_trans *trans)
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static int iwl_pcie_load_cpu_sections_8000b(struct iwl_trans *trans,
|
||||
const struct fw_img *image,
|
||||
int cpu,
|
||||
int *first_ucode_section)
|
||||
static int iwl_pcie_load_cpu_sections_8000(struct iwl_trans *trans,
|
||||
const struct fw_img *image,
|
||||
int cpu,
|
||||
int *first_ucode_section)
|
||||
{
|
||||
int shift_param;
|
||||
int i, ret = 0, sec_num = 0x1;
|
||||
@ -917,20 +921,16 @@ static int iwl_pcie_load_given_ucode(struct iwl_trans *trans,
|
||||
}
|
||||
|
||||
/* release CPU reset */
|
||||
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
|
||||
iwl_write_prph(trans, RELEASE_CPU_RESET, RELEASE_CPU_RESET_BIT);
|
||||
else
|
||||
iwl_write32(trans, CSR_RESET, 0);
|
||||
iwl_write32(trans, CSR_RESET, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_pcie_load_given_ucode_8000b(struct iwl_trans *trans,
|
||||
const struct fw_img *image)
|
||||
static int iwl_pcie_load_given_ucode_8000(struct iwl_trans *trans,
|
||||
const struct fw_img *image)
|
||||
{
|
||||
int ret = 0;
|
||||
int first_ucode_section;
|
||||
u32 reg;
|
||||
|
||||
IWL_DEBUG_FW(trans, "working with %s CPU\n",
|
||||
image->is_dual_cpus ? "Dual" : "Single");
|
||||
@ -948,38 +948,23 @@ static int iwl_pcie_load_given_ucode_8000b(struct iwl_trans *trans,
|
||||
iwl_write_prph(trans, RELEASE_CPU_RESET, RELEASE_CPU_RESET_BIT);
|
||||
|
||||
/* load to FW the binary Secured sections of CPU1 */
|
||||
ret = iwl_pcie_load_cpu_sections_8000b(trans, image, 1,
|
||||
&first_ucode_section);
|
||||
ret = iwl_pcie_load_cpu_sections_8000(trans, image, 1,
|
||||
&first_ucode_section);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* load to FW the binary sections of CPU2 */
|
||||
ret = iwl_pcie_load_cpu_sections_8000b(trans, image, 2,
|
||||
&first_ucode_section);
|
||||
ret = iwl_pcie_load_cpu_sections_8000(trans, image, 2,
|
||||
&first_ucode_section);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* wait for image verification to complete */
|
||||
ret = iwl_poll_prph_bit(trans, LMPM_SECURE_BOOT_CPU1_STATUS_ADDR_B0,
|
||||
LMPM_SECURE_BOOT_STATUS_SUCCESS,
|
||||
LMPM_SECURE_BOOT_STATUS_SUCCESS,
|
||||
LMPM_SECURE_TIME_OUT);
|
||||
if (ret < 0) {
|
||||
reg = iwl_read_prph(trans,
|
||||
LMPM_SECURE_BOOT_CPU1_STATUS_ADDR_B0);
|
||||
|
||||
IWL_ERR(trans, "Timeout on secure boot process, reg = %x\n",
|
||||
reg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
|
||||
const struct fw_img *fw, bool run_in_rfkill)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
int ret;
|
||||
bool hw_rfkill;
|
||||
|
||||
@ -1009,9 +994,6 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* init ref_count to 1 (should be cleared when ucode is loaded) */
|
||||
trans_pcie->ref_count = 1;
|
||||
|
||||
/* make sure rfkill handshake bits are cleared */
|
||||
iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
|
||||
iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR,
|
||||
@ -1026,9 +1008,8 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
|
||||
iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
|
||||
|
||||
/* Load the given image to the HW */
|
||||
if ((trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) &&
|
||||
(CSR_HW_REV_STEP(trans->hw_rev) != SILICON_A_STEP))
|
||||
return iwl_pcie_load_given_ucode_8000b(trans, fw);
|
||||
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
|
||||
return iwl_pcie_load_given_ucode_8000(trans, fw);
|
||||
else
|
||||
return iwl_pcie_load_given_ucode(trans, fw);
|
||||
}
|
||||
@ -1330,6 +1311,9 @@ static void iwl_trans_pcie_configure(struct iwl_trans *trans,
|
||||
trans_pcie->bc_table_dword = trans_cfg->bc_table_dword;
|
||||
trans_pcie->scd_set_active = trans_cfg->scd_set_active;
|
||||
|
||||
/* init ref_count to 1 (should be cleared when ucode is loaded) */
|
||||
trans_pcie->ref_count = 1;
|
||||
|
||||
/* Initialize NAPI here - it should be before registering to mac80211
|
||||
* in the opmode but after the HW struct is allocated.
|
||||
* As this function may be called again in some corner cases don't
|
||||
|
@ -1315,7 +1315,8 @@ static void setup_arp_tx(struct rtl_priv *rtlpriv, struct rtl_ps_ctl *ppsc)
|
||||
}
|
||||
|
||||
/*should call before software enc*/
|
||||
u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
|
||||
u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx,
|
||||
bool is_enc)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
|
||||
@ -1344,7 +1345,9 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
|
||||
break;
|
||||
}
|
||||
|
||||
offset = mac_hdr_len + SNAP_SIZE + encrypt_header_len;
|
||||
offset = mac_hdr_len + SNAP_SIZE;
|
||||
if (is_enc)
|
||||
offset += encrypt_header_len;
|
||||
ether_type = be16_to_cpup((__be16 *)(skb->data + offset));
|
||||
|
||||
if (ETH_P_IP == ether_type) {
|
||||
|
@ -120,7 +120,8 @@ bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx);
|
||||
int rtlwifi_rate_mapping(struct ieee80211_hw *hw, bool isht,
|
||||
bool isvht, u8 desc_rate);
|
||||
bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb);
|
||||
u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx);
|
||||
u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx,
|
||||
bool is_enc);
|
||||
|
||||
void rtl_beacon_statistic(struct ieee80211_hw *hw, struct sk_buff *skb);
|
||||
int rtl_tx_agg_start(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
|
@ -887,7 +887,7 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
|
||||
unicast = true;
|
||||
rtlpriv->stats.rxbytesunicast += skb->len;
|
||||
}
|
||||
rtl_is_special_data(hw, skb, false);
|
||||
rtl_is_special_data(hw, skb, false, true);
|
||||
|
||||
if (ieee80211_is_data(fc)) {
|
||||
rtlpriv->cfg->ops->led_control(hw, LED_CTL_RX);
|
||||
|
@ -56,7 +56,8 @@ static u8 _rtl_rc_get_highest_rix(struct rtl_priv *rtlpriv,
|
||||
wireless_mode = sta_entry->wireless_mode;
|
||||
}
|
||||
|
||||
if (rtl_is_special_data(rtlpriv->mac80211.hw, skb, true) || not_data) {
|
||||
if (rtl_is_special_data(rtlpriv->mac80211.hw, skb, true, false) ||
|
||||
not_data) {
|
||||
return 0;
|
||||
} else {
|
||||
if (rtlhal->current_bandtype == BAND_ON_2_4G) {
|
||||
@ -201,7 +202,7 @@ static void rtl_tx_status(void *ppriv,
|
||||
if (!priv_sta || !ieee80211_is_data(fc))
|
||||
return;
|
||||
|
||||
if (rtl_is_special_data(mac->hw, skb, true))
|
||||
if (rtl_is_special_data(mac->hw, skb, true, true))
|
||||
return;
|
||||
|
||||
if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) ||
|
||||
|
@ -1608,7 +1608,7 @@ int wl1251_free_hw(struct wl1251 *wl)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wl1251_free_hw);
|
||||
|
||||
MODULE_DESCRIPTION("TI wl1251 Wireles LAN Driver Core");
|
||||
MODULE_DESCRIPTION("TI wl1251 Wireless LAN Driver Core");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Kalle Valo <kvalo@adurom.com>");
|
||||
MODULE_FIRMWARE(WL1251_FW_NAME);
|
||||
|
@ -357,6 +357,15 @@ static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)
|
||||
pcicore_write32(pc, SSB_PCICORE_SBTOPCI2,
|
||||
SSB_PCICORE_SBTOPCI_MEM | SSB_PCI_DMA);
|
||||
|
||||
/*
|
||||
* Accessing PCI config without a proper delay after devices reset (not
|
||||
* GPIO reset) was causing reboots on WRT300N v1.0.
|
||||
* Tested delay 850 us lowered reboot chance to 50-80%, 1000 us fixed it
|
||||
* completely. Flushing all writes was also tested but with no luck.
|
||||
*/
|
||||
if (pc->dev->bus->chip_id == 0x4704)
|
||||
usleep_range(1000, 2000);
|
||||
|
||||
/* Enable PCI bridge BAR0 prefetch and burst */
|
||||
val = PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
|
||||
ssb_extpci_write_config(pc, 0, 0, 0, PCI_COMMAND, &val, 2);
|
||||
|
Loading…
Reference in New Issue
Block a user