mirror of https://gitee.com/openkylin/linux.git
Patches intended for v4.12:
* Some small fixes here and there; * The usual cleanups and small improvements; * Work to support A000 devices continues; * New FW API version; * Some debugging improvements; -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEF3LNfgb2BPWm68smoUecoho8xfoFAljvb0UACgkQoUecoho8 xfoBYRAAshN9NSZK7Q4OlXkb5sVrhz6Q2HaH490Nby+nzSx7C5ZAR+q6PU/U963b /fqnD5EMTjQA57hoVElgmEGj7JZAqvZrTOvhTVTk7U3znoVBhbmXQxLJRsJLqrQ1 vx8RCqa6XOD90cMBr5sZ4qzPDiRxpAaxJ/VcJ78ER3yNIu4fSBoyF5lLc+Ao0pdy 2/E8dr3LBSqEHUEeLDdB1/VXWUnBLlWR+L4WHNNrnoBaDO+azuGaD0GxHifdw+sP BgdhlypbnVmeDGSZktegfdAvfaLQKtsG31sxyUDmgqgp9Coev1WSlzYd16sajmrP e6YKBmlVJFIMJ3sriVozRj1eNhuULbq1w6yxBORRnZ5ertgYyoAZ5TUqKu0ssiFj zb2xT4rT/b1iRKDtYJSgSa1EyxEw6hwMyo0PW5KWfsH8SOeWro12jweqQuEKgKqR jVcBPb0q7OxjRkiRjxBkxQj0n6zYIkapdldpwHk8eXh/keRyWz2Ns+AcyYOxgOkk ioX6MzTaMCXMsQnXRcl1MiM2oP24r5T6Sds1NSGvSZ759KD/S0l/ge0UUAoDxsoy pE1CxsHZwCvqMGNICsPUbti4VkLu7wHss9W50SdHh42GuGyp0+tpU41Sv2KL6HyN OoPA6rrCuME99vrUYblAT7U8GDb3mNjiIu064ovPSP4nvLHqIuc= =iKI9 -----END PGP SIGNATURE----- Merge tag 'iwlwifi-next-for-kalle-2017-04-13' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next Patches intended for v4.12: * Some small fixes here and there; * The usual cleanups and small improvements; * Work to support A000 devices continues; * New FW API version; * Some debugging improvements;
This commit is contained in:
commit
d074e0b84a
|
@ -7,6 +7,7 @@ iwlwifi-objs += iwl-notif-wait.o
|
|||
iwlwifi-objs += iwl-eeprom-read.o iwl-eeprom-parse.o
|
||||
iwlwifi-objs += iwl-phy-db.o iwl-nvm-parse.o
|
||||
iwlwifi-objs += pcie/drv.o pcie/rx.o pcie/tx.o pcie/trans.o
|
||||
iwlwifi-objs += pcie/ctxt-info.o pcie/trans-gen2.o
|
||||
iwlwifi-$(CONFIG_IWLDVM) += iwl-1000.o iwl-2000.o iwl-5000.o iwl-6000.o
|
||||
iwlwifi-$(CONFIG_IWLMVM) += iwl-7000.o iwl-8000.o iwl-9000.o iwl-a000.o
|
||||
iwlwifi-objs += iwl-trans.o
|
||||
|
|
|
@ -73,8 +73,8 @@
|
|||
/* Highest firmware API version supported */
|
||||
#define IWL7260_UCODE_API_MAX 17
|
||||
#define IWL7265_UCODE_API_MAX 17
|
||||
#define IWL7265D_UCODE_API_MAX 28
|
||||
#define IWL3168_UCODE_API_MAX 28
|
||||
#define IWL7265D_UCODE_API_MAX 30
|
||||
#define IWL3168_UCODE_API_MAX 30
|
||||
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL7260_UCODE_API_MIN 17
|
||||
|
|
|
@ -70,8 +70,8 @@
|
|||
#include "iwl-agn-hw.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL8000_UCODE_API_MAX 28
|
||||
#define IWL8265_UCODE_API_MAX 28
|
||||
#define IWL8000_UCODE_API_MAX 30
|
||||
#define IWL8265_UCODE_API_MAX 30
|
||||
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL8000_UCODE_API_MIN 17
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2015-2016 Intel Deutschland GmbH
|
||||
* Copyright(c) 2015-2017 Intel Deutschland GmbH
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -18,7 +18,7 @@
|
|||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2015-2016 Intel Deutschland GmbH
|
||||
* Copyright(c) 2015-2017 Intel Deutschland GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -55,7 +55,7 @@
|
|||
#include "iwl-agn-hw.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL9000_UCODE_API_MAX 28
|
||||
#define IWL9000_UCODE_API_MAX 30
|
||||
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL9000_UCODE_API_MIN 17
|
||||
|
@ -73,14 +73,14 @@
|
|||
#define IWL9000_SMEM_LEN 0x68000
|
||||
|
||||
#define IWL9000_FW_PRE "iwlwifi-9000-pu-a0-jf-a0-"
|
||||
#define IWL9260_FW_PRE "iwlwifi-9260-th-a0-jf-a0-"
|
||||
#define IWL9000LC_FW_PRE "iwlwifi-9000-pu-a0-lc-a0-"
|
||||
#define IWL9260A_FW_PRE "iwlwifi-9260-th-a0-jf-a0-"
|
||||
#define IWL9260B_FW_PRE "iwlwifi-9260-th-b0-jf-b0-"
|
||||
#define IWL9000_MODULE_FIRMWARE(api) \
|
||||
IWL9000_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL9260_MODULE_FIRMWARE(api) \
|
||||
IWL9260_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL9000LC_MODULE_FIRMWARE(api) \
|
||||
IWL9000LC_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL9260A_MODULE_FIRMWARE(api) \
|
||||
IWL9260A_FW_PRE "-" __stringify(api) ".ucode"
|
||||
#define IWL9260B_MODULE_FIRMWARE(api) \
|
||||
IWL9260B_FW_PRE "-" __stringify(api) ".ucode"
|
||||
|
||||
#define NVM_HW_SECTION_NUM_FAMILY_9000 10
|
||||
|
||||
|
@ -148,7 +148,8 @@ static const struct iwl_tt_params iwl9000_tt_params = {
|
|||
|
||||
const struct iwl_cfg iwl9160_2ac_cfg = {
|
||||
.name = "Intel(R) Dual Band Wireless AC 9160",
|
||||
.fw_name_pre = IWL9260_FW_PRE,
|
||||
.fw_name_pre = IWL9260A_FW_PRE,
|
||||
.fw_name_pre_next_step = IWL9260B_FW_PRE,
|
||||
IWL_DEVICE_9000,
|
||||
.ht_params = &iwl9000_ht_params,
|
||||
.nvm_ver = IWL9000_NVM_VERSION,
|
||||
|
@ -158,7 +159,8 @@ const struct iwl_cfg iwl9160_2ac_cfg = {
|
|||
|
||||
const struct iwl_cfg iwl9260_2ac_cfg = {
|
||||
.name = "Intel(R) Dual Band Wireless AC 9260",
|
||||
.fw_name_pre = IWL9260_FW_PRE,
|
||||
.fw_name_pre = IWL9260A_FW_PRE,
|
||||
.fw_name_pre_next_step = IWL9260B_FW_PRE,
|
||||
IWL_DEVICE_9000,
|
||||
.ht_params = &iwl9000_ht_params,
|
||||
.nvm_ver = IWL9000_NVM_VERSION,
|
||||
|
@ -168,7 +170,8 @@ const struct iwl_cfg iwl9260_2ac_cfg = {
|
|||
|
||||
const struct iwl_cfg iwl9270_2ac_cfg = {
|
||||
.name = "Intel(R) Dual Band Wireless AC 9270",
|
||||
.fw_name_pre = IWL9260_FW_PRE,
|
||||
.fw_name_pre = IWL9260A_FW_PRE,
|
||||
.fw_name_pre_next_step = IWL9260B_FW_PRE,
|
||||
IWL_DEVICE_9000,
|
||||
.ht_params = &iwl9000_ht_params,
|
||||
.nvm_ver = IWL9000_NVM_VERSION,
|
||||
|
@ -198,21 +201,6 @@ const struct iwl_cfg iwl9560_2ac_cfg = {
|
|||
.integrated = true,
|
||||
};
|
||||
|
||||
/*
|
||||
* TODO the struct below is for internal testing only this should be
|
||||
* removed by EO 2016~
|
||||
*/
|
||||
const struct iwl_cfg iwl9000lc_2ac_cfg = {
|
||||
.name = "Intel(R) Dual Band Wireless AC 9000",
|
||||
.fw_name_pre = IWL9000LC_FW_PRE,
|
||||
IWL_DEVICE_9000,
|
||||
.ht_params = &iwl9000_ht_params,
|
||||
.nvm_ver = IWL9000_NVM_VERSION,
|
||||
.nvm_calib_ver = IWL9000_TX_POWER_VERSION,
|
||||
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
|
||||
.integrated = true,
|
||||
};
|
||||
|
||||
MODULE_FIRMWARE(IWL9000_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL9260_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL9000LC_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL9260A_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL9260B_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX));
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
#include "iwl-agn-hw.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL_A000_UCODE_API_MAX 28
|
||||
#define IWL_A000_UCODE_API_MAX 30
|
||||
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL_A000_UCODE_API_MIN 24
|
||||
|
@ -121,7 +121,8 @@ static const struct iwl_ht_params iwl_a000_ht_params = {
|
|||
.vht_mu_mimo_supported = true, \
|
||||
.mac_addr_from_csr = true, \
|
||||
.use_tfh = true, \
|
||||
.rf_id = true
|
||||
.rf_id = true, \
|
||||
.gen2 = true
|
||||
|
||||
const struct iwl_cfg iwla000_2ac_cfg_hr = {
|
||||
.name = "Intel(R) Dual Band Wireless AC a000",
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2016 Intel Deutschland GmbH
|
||||
* Copyright (C) 2016 - 2017 Intel Deutschland GmbH
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -32,7 +32,7 @@
|
|||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright (C) 2016 Intel Deutschland GmbH
|
||||
* Copyright (C) 2016 - 2017 Intel Deutschland GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -283,6 +283,8 @@ struct iwl_pwr_tx_backoff {
|
|||
* @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.
|
||||
* @fw_name_pre_next_step: same as @fw_name_pre, only for next step
|
||||
* (if supported)
|
||||
* @ucode_api_max: Highest version of uCode API supported by driver.
|
||||
* @ucode_api_min: Lowest version of uCode API supported by driver.
|
||||
* @max_inst_size: The maximal length of the fw inst section
|
||||
|
@ -321,6 +323,7 @@ struct iwl_pwr_tx_backoff {
|
|||
* @vht_mu_mimo_supported: VHT MU-MIMO support
|
||||
* @rf_id: need to read rf_id to determine the firmware image
|
||||
* @integrated: discrete or integrated
|
||||
* @gen2: a000 and on transport operation
|
||||
*
|
||||
* We enable the driver to be backward compatible wrt. hardware features.
|
||||
* API differences in uCode shouldn't be handled here but through TLVs
|
||||
|
@ -330,6 +333,7 @@ struct iwl_cfg {
|
|||
/* params specific to an individual device within a device family */
|
||||
const char *name;
|
||||
const char *fw_name_pre;
|
||||
const char *fw_name_pre_next_step;
|
||||
/* params not likely to change within a device family */
|
||||
const struct iwl_base_params *base_params;
|
||||
/* params likely to change within a device family */
|
||||
|
@ -365,7 +369,8 @@ struct iwl_cfg {
|
|||
vht_mu_mimo_supported:1,
|
||||
rf_id:1,
|
||||
integrated:1,
|
||||
use_tfh:1;
|
||||
use_tfh:1,
|
||||
gen2:1;
|
||||
u8 valid_tx_ant;
|
||||
u8 valid_rx_ant;
|
||||
u8 non_shared_ant;
|
||||
|
@ -449,7 +454,6 @@ extern const struct iwl_cfg iwl4165_2ac_cfg;
|
|||
extern const struct iwl_cfg iwl8260_2ac_sdio_cfg;
|
||||
extern const struct iwl_cfg iwl8265_2ac_sdio_cfg;
|
||||
extern const struct iwl_cfg iwl4165_2ac_sdio_cfg;
|
||||
extern const struct iwl_cfg iwl9000lc_2ac_cfg;
|
||||
extern const struct iwl_cfg iwl9160_2ac_cfg;
|
||||
extern const struct iwl_cfg iwl9260_2ac_cfg;
|
||||
extern const struct iwl_cfg iwl9270_2ac_cfg;
|
||||
|
|
|
@ -0,0 +1,203 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2017 Intel Deutschland GmbH
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2017 Intel Deutschland GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __iwl_context_info_file_h__
|
||||
#define __iwl_context_info_file_h__
|
||||
|
||||
/* maximmum number of DRAM map entries supported by FW */
|
||||
#define IWL_MAX_DRAM_ENTRY 64
|
||||
#define CSR_CTXT_INFO_BA 0x40
|
||||
|
||||
/**
|
||||
* enum iwl_context_info_flags - Context information control flags
|
||||
* @IWL_CTXT_INFO_AUTO_FUNC_INIT: If set, FW will not wait before interrupting
|
||||
* the init done for driver command that configures several system modes
|
||||
* @IWL_CTXT_INFO_EARLY_DEBUG: enable early debug
|
||||
* @IWL_CTXT_INFO_ENABLE_CDMP: enable core dump
|
||||
* @IWL_CTXT_INFO_RB_SIZE_4K: Use 4K RB size (the default is 2K)
|
||||
* @IWL_CTXT_INFO_RB_CB_SIZE_POS: position of the RBD Cyclic Buffer Size
|
||||
* exponent, the actual size is 2**value, valid sizes are 8-2048.
|
||||
* The value is four bits long. Maximum valid exponent is 12
|
||||
* @IWL_CTXT_INFO_TFD_FORMAT_LONG: use long TFD Format (the
|
||||
* default is short format - not supported by the driver)
|
||||
*/
|
||||
enum iwl_context_info_flags {
|
||||
IWL_CTXT_INFO_AUTO_FUNC_INIT = BIT(0),
|
||||
IWL_CTXT_INFO_EARLY_DEBUG = BIT(1),
|
||||
IWL_CTXT_INFO_ENABLE_CDMP = BIT(2),
|
||||
IWL_CTXT_INFO_RB_SIZE_4K = BIT(3),
|
||||
IWL_CTXT_INFO_RB_CB_SIZE_POS = 4,
|
||||
IWL_CTXT_INFO_TFD_FORMAT_LONG = BIT(8),
|
||||
};
|
||||
|
||||
/*
|
||||
* struct iwl_context_info_version - version structure
|
||||
* @mac_id: SKU and revision id
|
||||
* @version: context information version id
|
||||
* @size: the size of the context information in DWs
|
||||
*/
|
||||
struct iwl_context_info_version {
|
||||
__le16 mac_id;
|
||||
__le16 version;
|
||||
__le16 size;
|
||||
__le16 reserved;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* struct iwl_context_info_control - version structure
|
||||
* @control_flags: context information flags see &enum iwl_context_info_flags
|
||||
*/
|
||||
struct iwl_context_info_control {
|
||||
__le32 control_flags;
|
||||
__le32 reserved;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* struct iwl_context_info_dram - images DRAM map
|
||||
* each entry in the map represents a DRAM chunk of up to 32 KB
|
||||
* @umac_img: UMAC image DRAM map
|
||||
* @lmac_img: LMAC image DRAM map
|
||||
* @virtual_img: paged image DRAM map
|
||||
*/
|
||||
struct iwl_context_info_dram {
|
||||
__le64 umac_img[IWL_MAX_DRAM_ENTRY];
|
||||
__le64 lmac_img[IWL_MAX_DRAM_ENTRY];
|
||||
__le64 virtual_img[IWL_MAX_DRAM_ENTRY];
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* struct iwl_context_info_rbd_cfg - RBDs configuration
|
||||
* @free_rbd_addr: default queue free RB CB base address
|
||||
* @used_rbd_addr: default queue used RB CB base address
|
||||
* @status_wr_ptr: default queue used RB status write pointer
|
||||
*/
|
||||
struct iwl_context_info_rbd_cfg {
|
||||
__le64 free_rbd_addr;
|
||||
__le64 used_rbd_addr;
|
||||
__le64 status_wr_ptr;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* struct iwl_context_info_hcmd_cfg - command queue configuration
|
||||
* @cmd_queue_addr: address of command queue
|
||||
* @cmd_queue_size: number of entries
|
||||
*/
|
||||
struct iwl_context_info_hcmd_cfg {
|
||||
__le64 cmd_queue_addr;
|
||||
u8 cmd_queue_size;
|
||||
u8 reserved[7];
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* struct iwl_context_info_dump_cfg - Core Dump configuration
|
||||
* @core_dump_addr: core dump (debug DRAM address) start address
|
||||
* @core_dump_size: size, in DWs
|
||||
*/
|
||||
struct iwl_context_info_dump_cfg {
|
||||
__le64 core_dump_addr;
|
||||
__le32 core_dump_size;
|
||||
__le32 reserved;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* struct iwl_context_info_pnvm_cfg - platform NVM data configuration
|
||||
* @platform_nvm_addr: Platform NVM data start address
|
||||
* @platform_nvm_size: size in DWs
|
||||
*/
|
||||
struct iwl_context_info_pnvm_cfg {
|
||||
__le64 platform_nvm_addr;
|
||||
__le32 platform_nvm_size;
|
||||
__le32 reserved;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* struct iwl_context_info_early_dbg_cfg - early debug configuration for
|
||||
* dumping DRAM addresses
|
||||
* @early_debug_addr: early debug start address
|
||||
* @early_debug_size: size in DWs
|
||||
*/
|
||||
struct iwl_context_info_early_dbg_cfg {
|
||||
__le64 early_debug_addr;
|
||||
__le32 early_debug_size;
|
||||
__le32 reserved;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* struct iwl_context_info - device INIT configuration
|
||||
* @version: version information of context info and HW
|
||||
* @control: control flags of FH configurations
|
||||
* @rbd_cfg: default RX queue configuration
|
||||
* @hcmd_cfg: command queue configuration
|
||||
* @dump_cfg: core dump data
|
||||
* @edbg_cfg: early debug configuration
|
||||
* @pnvm_cfg: platform nvm configuration
|
||||
* @dram: firmware image addresses in DRAM
|
||||
*/
|
||||
struct iwl_context_info {
|
||||
struct iwl_context_info_version version;
|
||||
struct iwl_context_info_control control;
|
||||
__le64 reserved0;
|
||||
struct iwl_context_info_rbd_cfg rbd_cfg;
|
||||
struct iwl_context_info_hcmd_cfg hcmd_cfg;
|
||||
__le32 reserved1[4];
|
||||
struct iwl_context_info_dump_cfg dump_cfg;
|
||||
struct iwl_context_info_early_dbg_cfg edbg_cfg;
|
||||
struct iwl_context_info_pnvm_cfg pnvm_cfg;
|
||||
__le32 reserved2[16];
|
||||
struct iwl_context_info_dram dram;
|
||||
__le32 reserved3[16];
|
||||
} __packed;
|
||||
|
||||
int iwl_pcie_ctxt_info_init(struct iwl_trans *trans, const struct fw_img *fw);
|
||||
void iwl_pcie_ctxt_info_free(struct iwl_trans *trans);
|
||||
void iwl_pcie_ctxt_info_free_paging(struct iwl_trans *trans);
|
||||
|
||||
#endif /* __iwl_context_info_file_h__ */
|
|
@ -348,7 +348,6 @@ enum {
|
|||
|
||||
/* RF_ID value */
|
||||
#define CSR_HW_RF_ID_TYPE_JF (0x00105000)
|
||||
#define CSR_HW_RF_ID_TYPE_LC (0x00101000)
|
||||
#define CSR_HW_RF_ID_TYPE_HR (0x00109000)
|
||||
|
||||
/* EEPROM REG */
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*
|
||||
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 Intel Deutschland GmbH
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -34,7 +34,7 @@
|
|||
*
|
||||
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 Intel Deutschland GmbH
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -211,24 +211,46 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw,
|
|||
|
||||
static int iwl_request_firmware(struct iwl_drv *drv, bool first)
|
||||
{
|
||||
const char *name_pre = drv->trans->cfg->fw_name_pre;
|
||||
const struct iwl_cfg *cfg = drv->trans->cfg;
|
||||
char tag[8];
|
||||
const char *fw_pre_name;
|
||||
|
||||
if (drv->trans->cfg->device_family == IWL_DEVICE_FAMILY_8000 &&
|
||||
CSR_HW_REV_STEP(drv->trans->hw_rev) == SILICON_B_STEP)
|
||||
fw_pre_name = cfg->fw_name_pre_next_step;
|
||||
else
|
||||
fw_pre_name = cfg->fw_name_pre;
|
||||
|
||||
if (first) {
|
||||
drv->fw_index = drv->trans->cfg->ucode_api_max;
|
||||
drv->fw_index = cfg->ucode_api_max;
|
||||
sprintf(tag, "%d", drv->fw_index);
|
||||
} else {
|
||||
drv->fw_index--;
|
||||
sprintf(tag, "%d", drv->fw_index);
|
||||
}
|
||||
|
||||
if (drv->fw_index < drv->trans->cfg->ucode_api_min) {
|
||||
if (drv->fw_index < cfg->ucode_api_min) {
|
||||
IWL_ERR(drv, "no suitable firmware found!\n");
|
||||
|
||||
if (cfg->ucode_api_min == cfg->ucode_api_max) {
|
||||
IWL_ERR(drv, "%s%d is required\n", fw_pre_name,
|
||||
cfg->ucode_api_max);
|
||||
} else {
|
||||
IWL_ERR(drv, "minimum version required: %s%d\n",
|
||||
fw_pre_name,
|
||||
cfg->ucode_api_min);
|
||||
IWL_ERR(drv, "maximum version supported: %s%d\n",
|
||||
fw_pre_name,
|
||||
cfg->ucode_api_max);
|
||||
}
|
||||
|
||||
IWL_ERR(drv,
|
||||
"check git://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
snprintf(drv->firmware_name, sizeof(drv->firmware_name), "%s%s.ucode",
|
||||
name_pre, tag);
|
||||
fw_pre_name, tag);
|
||||
|
||||
IWL_DEBUG_INFO(drv, "attempting to load firmware '%s'\n",
|
||||
drv->firmware_name);
|
||||
|
|
|
@ -614,6 +614,8 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(struct iwl_trans *trans,
|
|||
#define RX_POOL_SIZE (MQ_RX_NUM_RBDS + \
|
||||
IWL_MAX_RX_HW_QUEUES * \
|
||||
(RX_CLAIM_REQ_ALLOC - RX_POST_REQ_ALLOC))
|
||||
/* cb size is the exponent */
|
||||
#define RX_QUEUE_CB_SIZE(x) ilog2(x)
|
||||
|
||||
#define RX_QUEUE_SIZE 256
|
||||
#define RX_QUEUE_MASK 255
|
||||
|
@ -639,6 +641,8 @@ struct iwl_rb_status {
|
|||
|
||||
|
||||
#define TFD_QUEUE_SIZE_MAX (256)
|
||||
/* cb size is the exponent - 3 */
|
||||
#define TFD_QUEUE_CB_SIZE(x) (ilog2(x) - 3)
|
||||
#define TFD_QUEUE_SIZE_BC_DUP (64)
|
||||
#define TFD_QUEUE_BC_SIZE (TFD_QUEUE_SIZE_MAX + TFD_QUEUE_SIZE_BC_DUP)
|
||||
#define IWL_TX_DMA_MASK DMA_BIT_MASK(36)
|
||||
|
@ -647,7 +651,7 @@ struct iwl_rb_status {
|
|||
|
||||
static inline u8 iwl_get_dma_hi_addr(dma_addr_t addr)
|
||||
{
|
||||
return (sizeof(addr) > sizeof(u32) ? (addr >> 16) >> 16 : 0) & 0xF;
|
||||
return (sizeof(addr) > sizeof(u32) ? upper_32_bits(addr) : 0) & 0xF;
|
||||
}
|
||||
/**
|
||||
* struct iwl_tfd_tb transmit buffer descriptor within transmit frame descriptor
|
||||
|
|
|
@ -241,6 +241,8 @@ typedef unsigned int __bitwise iwl_ucode_tlv_api_t;
|
|||
* iteration complete notification, and the timestamp reported for RX
|
||||
* received during scan, are reported in TSF of the mac specified in the
|
||||
* scan request.
|
||||
* @IWL_UCODE_TLV_API_TKIP_MIC_KEYS: This ucode supports version 2 of
|
||||
* ADD_MODIFY_STA_KEY_API_S_VER_2.
|
||||
*
|
||||
* @NUM_IWL_UCODE_TLV_API: number of bits used
|
||||
*/
|
||||
|
@ -250,6 +252,7 @@ enum iwl_ucode_tlv_api {
|
|||
IWL_UCODE_TLV_API_LQ_SS_PARAMS = (__force iwl_ucode_tlv_api_t)18,
|
||||
IWL_UCODE_TLV_API_NEW_VERSION = (__force iwl_ucode_tlv_api_t)20,
|
||||
IWL_UCODE_TLV_API_SCAN_TSF_REPORT = (__force iwl_ucode_tlv_api_t)28,
|
||||
IWL_UCODE_TLV_API_TKIP_MIC_KEYS = (__force iwl_ucode_tlv_api_t)29,
|
||||
|
||||
NUM_IWL_UCODE_TLV_API
|
||||
#ifdef __CHECKER__
|
||||
|
@ -344,6 +347,8 @@ enum iwl_ucode_tlv_capa {
|
|||
IWL_UCODE_TLV_CAPA_BT_COEX_RRC = (__force iwl_ucode_tlv_capa_t)30,
|
||||
IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT = (__force iwl_ucode_tlv_capa_t)31,
|
||||
IWL_UCODE_TLV_CAPA_STA_PM_NOTIF = (__force iwl_ucode_tlv_capa_t)38,
|
||||
IWL_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT = (__force iwl_ucode_tlv_capa_t)39,
|
||||
IWL_UCODE_TLV_CAPA_CDB_SUPPORT = (__force iwl_ucode_tlv_capa_t)40,
|
||||
IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE = (__force iwl_ucode_tlv_capa_t)64,
|
||||
IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS = (__force iwl_ucode_tlv_capa_t)65,
|
||||
IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT = (__force iwl_ucode_tlv_capa_t)67,
|
||||
|
|
|
@ -54,8 +54,8 @@ IWL_EXPORT_SYMBOL(iwl_write32);
|
|||
void iwl_write64(struct iwl_trans *trans, u64 ofs, u64 val)
|
||||
{
|
||||
trace_iwlwifi_dev_iowrite64(trans->dev, ofs, val);
|
||||
iwl_trans_write32(trans, ofs, val & 0xffffffff);
|
||||
iwl_trans_write32(trans, ofs + 4, val >> 32);
|
||||
iwl_trans_write32(trans, ofs, lower_32_bits(val));
|
||||
iwl_trans_write32(trans, ofs + 4, upper_32_bits(val));
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_write64);
|
||||
|
||||
|
|
|
@ -309,6 +309,7 @@
|
|||
* Note this address is cleared after MAC reset.
|
||||
*/
|
||||
#define UREG_UCODE_LOAD_STATUS (0xa05c40)
|
||||
#define UREG_CPU_INIT_RUN (0xa05c44)
|
||||
|
||||
#define LMPM_SECURE_UCODE_LOAD_CPU1_HDR_ADDR (0x1E78)
|
||||
#define LMPM_SECURE_UCODE_LOAD_CPU2_HDR_ADDR (0x1E7C)
|
||||
|
@ -378,6 +379,7 @@
|
|||
#define RADIO_REG_SYS_MANUAL_DFT_0 0xAD4078
|
||||
#define RFIC_REG_RD 0xAD0470
|
||||
#define WFPM_CTRL_REG 0xA03030
|
||||
#define WFPM_GP2 0xA030B4
|
||||
enum {
|
||||
ENABLE_WFPM = BIT(31),
|
||||
WFPM_AUX_CTL_AUX_IF_MAC_OWNER_MSK = 0x80000000,
|
||||
|
|
|
@ -70,8 +70,7 @@
|
|||
struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
|
||||
struct device *dev,
|
||||
const struct iwl_cfg *cfg,
|
||||
const struct iwl_trans_ops *ops,
|
||||
size_t dev_cmd_headroom)
|
||||
const struct iwl_trans_ops *ops)
|
||||
{
|
||||
struct iwl_trans *trans;
|
||||
#ifdef CONFIG_LOCKDEP
|
||||
|
@ -90,15 +89,13 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
|
|||
trans->dev = dev;
|
||||
trans->cfg = cfg;
|
||||
trans->ops = ops;
|
||||
trans->dev_cmd_headroom = dev_cmd_headroom;
|
||||
trans->num_rx_queues = 1;
|
||||
|
||||
snprintf(trans->dev_cmd_pool_name, sizeof(trans->dev_cmd_pool_name),
|
||||
"iwl_cmd_pool:%s", dev_name(trans->dev));
|
||||
trans->dev_cmd_pool =
|
||||
kmem_cache_create(trans->dev_cmd_pool_name,
|
||||
sizeof(struct iwl_device_cmd)
|
||||
+ trans->dev_cmd_headroom,
|
||||
sizeof(struct iwl_device_cmd),
|
||||
sizeof(void *),
|
||||
SLAB_HWCACHE_ALIGN,
|
||||
NULL);
|
||||
|
|
|
@ -644,8 +644,6 @@ struct iwl_trans_ops {
|
|||
void (*txq_set_shared_mode)(struct iwl_trans *trans, u32 txq_id,
|
||||
bool shared);
|
||||
|
||||
dma_addr_t (*get_txq_byte_table)(struct iwl_trans *trans, int txq_id);
|
||||
|
||||
int (*wait_tx_queue_empty)(struct iwl_trans *trans, u32 txq_bm);
|
||||
void (*freeze_txq_timer)(struct iwl_trans *trans, unsigned long txqs,
|
||||
bool freeze);
|
||||
|
@ -774,9 +772,6 @@ enum iwl_plat_pm_mode {
|
|||
* the transport must set this before calling iwl_drv_start()
|
||||
* @dev_cmd_pool: pool for Tx cmd allocation - for internal use only.
|
||||
* The user should use iwl_trans_{alloc,free}_tx_cmd.
|
||||
* @dev_cmd_headroom: room needed for the transport's private use before the
|
||||
* device_cmd for Tx - for internal use only
|
||||
* The user should use iwl_trans_{alloc,free}_tx_cmd.
|
||||
* @rx_mpdu_cmd: MPDU RX command ID, must be assigned by opmode before
|
||||
* starting the firmware, used for tracing
|
||||
* @rx_mpdu_cmd_hdr_size: used for tracing, amount of data before the
|
||||
|
@ -827,7 +822,6 @@ struct iwl_trans {
|
|||
|
||||
/* The following fields are internal only */
|
||||
struct kmem_cache *dev_cmd_pool;
|
||||
size_t dev_cmd_headroom;
|
||||
char dev_cmd_pool_name[50];
|
||||
|
||||
struct dentry *dbgfs_dir;
|
||||
|
@ -1000,13 +994,13 @@ iwl_trans_dump_data(struct iwl_trans *trans,
|
|||
static inline struct iwl_device_cmd *
|
||||
iwl_trans_alloc_tx_cmd(struct iwl_trans *trans)
|
||||
{
|
||||
u8 *dev_cmd_ptr = kmem_cache_alloc(trans->dev_cmd_pool, GFP_ATOMIC);
|
||||
struct iwl_device_cmd *dev_cmd_ptr =
|
||||
kmem_cache_alloc(trans->dev_cmd_pool, GFP_ATOMIC);
|
||||
|
||||
if (unlikely(dev_cmd_ptr == NULL))
|
||||
return NULL;
|
||||
|
||||
return (struct iwl_device_cmd *)
|
||||
(dev_cmd_ptr + trans->dev_cmd_headroom);
|
||||
return dev_cmd_ptr;
|
||||
}
|
||||
|
||||
int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd);
|
||||
|
@ -1014,9 +1008,7 @@ int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd);
|
|||
static inline void iwl_trans_free_tx_cmd(struct iwl_trans *trans,
|
||||
struct iwl_device_cmd *dev_cmd)
|
||||
{
|
||||
u8 *dev_cmd_ptr = (u8 *)dev_cmd - trans->dev_cmd_headroom;
|
||||
|
||||
kmem_cache_free(trans->dev_cmd_pool, dev_cmd_ptr);
|
||||
kmem_cache_free(trans->dev_cmd_pool, dev_cmd);
|
||||
}
|
||||
|
||||
static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb,
|
||||
|
@ -1072,15 +1064,6 @@ static inline void iwl_trans_txq_set_shared_mode(struct iwl_trans *trans,
|
|||
trans->ops->txq_set_shared_mode(trans, queue, shared_mode);
|
||||
}
|
||||
|
||||
static inline dma_addr_t iwl_trans_get_txq_byte_table(struct iwl_trans *trans,
|
||||
int queue)
|
||||
{
|
||||
/* we should never be called if the trans doesn't support it */
|
||||
BUG_ON(!trans->ops->get_txq_byte_table);
|
||||
|
||||
return trans->ops->get_txq_byte_table(trans, queue);
|
||||
}
|
||||
|
||||
static inline void iwl_trans_txq_enable(struct iwl_trans *trans, int queue,
|
||||
int fifo, int sta_id, int tid,
|
||||
int frame_limit, u16 ssn,
|
||||
|
@ -1248,8 +1231,7 @@ static inline void iwl_trans_fw_error(struct iwl_trans *trans)
|
|||
struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
|
||||
struct device *dev,
|
||||
const struct iwl_cfg *cfg,
|
||||
const struct iwl_trans_ops *ops,
|
||||
size_t dev_cmd_headroom);
|
||||
const struct iwl_trans_ops *ops);
|
||||
void iwl_trans_free(struct iwl_trans *trans);
|
||||
|
||||
/*****************************************************
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2016 Intel Deutschland GmbH
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -31,6 +32,7 @@
|
|||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2016 Intel Deutschland GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -82,6 +84,19 @@ static int iwl_mvm_binding_cmd(struct iwl_mvm *mvm, u32 action,
|
|||
struct iwl_mvm_phy_ctxt *phyctxt = data->phyctxt;
|
||||
int i, ret;
|
||||
u32 status;
|
||||
int size;
|
||||
|
||||
if (fw_has_capa(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT)) {
|
||||
size = sizeof(cmd);
|
||||
if (phyctxt->channel->band == NL80211_BAND_2GHZ ||
|
||||
!iwl_mvm_is_cdb_supported(mvm))
|
||||
cmd.lmac_id = cpu_to_le32(IWL_LMAC_24G_INDEX);
|
||||
else
|
||||
cmd.lmac_id = cpu_to_le32(IWL_LMAC_5G_INDEX);
|
||||
} else {
|
||||
size = IWL_BINDING_CMD_SIZE_V1;
|
||||
}
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
|
||||
|
@ -99,7 +114,7 @@ static int iwl_mvm_binding_cmd(struct iwl_mvm *mvm, u32 action,
|
|||
|
||||
status = 0;
|
||||
ret = iwl_mvm_send_cmd_pdu_status(mvm, BINDING_CONTEXT_CMD,
|
||||
sizeof(cmd), &cmd, &status);
|
||||
size, &cmd, &status);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Failed to send binding (action:%d): %d\n",
|
||||
action, ret);
|
||||
|
|
|
@ -665,6 +665,19 @@ static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
struct iwl_binding_cmd binding_cmd = {};
|
||||
struct iwl_time_quota_cmd quota_cmd = {};
|
||||
u32 status;
|
||||
int size;
|
||||
|
||||
if (fw_has_capa(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT)) {
|
||||
size = sizeof(binding_cmd);
|
||||
if (mvmvif->phy_ctxt->channel->band == NL80211_BAND_2GHZ ||
|
||||
!iwl_mvm_is_cdb_supported(mvm))
|
||||
binding_cmd.lmac_id = cpu_to_le32(IWL_LMAC_24G_INDEX);
|
||||
else
|
||||
binding_cmd.lmac_id = cpu_to_le32(IWL_LMAC_5G_INDEX);
|
||||
} else {
|
||||
size = IWL_BINDING_CMD_SIZE_V1;
|
||||
}
|
||||
|
||||
/* add back the PHY */
|
||||
if (WARN_ON(!mvmvif->phy_ctxt))
|
||||
|
@ -711,8 +724,7 @@ static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
|||
|
||||
status = 0;
|
||||
ret = iwl_mvm_send_cmd_pdu_status(mvm, BINDING_CONTEXT_CMD,
|
||||
sizeof(binding_cmd), &binding_cmd,
|
||||
&status);
|
||||
size, &binding_cmd, &status);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Failed to add binding: %d\n", ret);
|
||||
return ret;
|
||||
|
@ -986,7 +998,9 @@ int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (key_data.use_tkip) {
|
||||
if (key_data.use_tkip &&
|
||||
!fw_has_api(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_API_TKIP_MIC_KEYS)) {
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm,
|
||||
WOWLAN_TKIP_PARAM,
|
||||
cmd_flags, sizeof(tkip_cmd),
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*
|
||||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 Intel Deutschland GmbH
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -34,7 +34,7 @@
|
|||
*
|
||||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 Intel Deutschland GmbH
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -389,27 +389,49 @@ struct iwl_mvm_add_sta_cmd {
|
|||
} __packed; /* ADD_STA_CMD_API_S_VER_8 */
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_add_sta_key_cmd - add/modify sta key
|
||||
* struct iwl_mvm_add_sta_key_common - add/modify sta key common part
|
||||
* ( REPLY_ADD_STA_KEY = 0x17 )
|
||||
* @sta_id: index of station in uCode's station table
|
||||
* @key_offset: key offset in key storage
|
||||
* @key_flags: type %iwl_sta_key_flag
|
||||
* @key: key material data
|
||||
* @rx_secur_seq_cnt: RX security sequence counter for the key
|
||||
* @tkip_rx_tsc_byte2: TSC[2] for key mix ph1 detection
|
||||
* @tkip_rx_ttak: 10-byte unicast TKIP TTAK for Rx
|
||||
*/
|
||||
struct iwl_mvm_add_sta_key_cmd {
|
||||
struct iwl_mvm_add_sta_key_common {
|
||||
u8 sta_id;
|
||||
u8 key_offset;
|
||||
__le16 key_flags;
|
||||
u8 key[32];
|
||||
u8 rx_secur_seq_cnt[16];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_add_sta_key_cmd_v1 - add/modify sta key
|
||||
* @common: see &struct iwl_mvm_add_sta_key_common
|
||||
* @tkip_rx_tsc_byte2: TSC[2] for key mix ph1 detection
|
||||
* @tkip_rx_ttak: 10-byte unicast TKIP TTAK for Rx
|
||||
*/
|
||||
struct iwl_mvm_add_sta_key_cmd_v1 {
|
||||
struct iwl_mvm_add_sta_key_common common;
|
||||
u8 tkip_rx_tsc_byte2;
|
||||
u8 reserved;
|
||||
__le16 tkip_rx_ttak[5];
|
||||
} __packed; /* ADD_MODIFY_STA_KEY_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_mvm_add_sta_key_cmd - add/modify sta key
|
||||
* @common: see &struct iwl_mvm_add_sta_key_common
|
||||
* @rx_mic_key: TKIP RX unicast or multicast key
|
||||
* @tx_mic_key: TKIP TX key
|
||||
* @transmit_seq_cnt: TSC, transmit packet number
|
||||
*/
|
||||
struct iwl_mvm_add_sta_key_cmd {
|
||||
struct iwl_mvm_add_sta_key_common common;
|
||||
__le64 rx_mic_key;
|
||||
__le64 tx_mic_key;
|
||||
__le64 transmit_seq_cnt;
|
||||
} __packed; /* ADD_MODIFY_STA_KEY_API_S_VER_2 */
|
||||
|
||||
/**
|
||||
* enum iwl_mvm_add_sta_rsp_status - status in the response to ADD_STA command
|
||||
* @ADD_STA_SUCCESS: operation was executed successfully
|
||||
|
|
|
@ -635,6 +635,10 @@ enum iwl_mvm_ba_resp_flags {
|
|||
* @tx_rate: the rate the aggregation was sent at
|
||||
* @tfd_cnt: number of TFD-Q elements
|
||||
* @ra_tid_cnt: number of RATID-Q elements
|
||||
* @ba_tfd: array of TFD queue status updates. See &iwl_mvm_compressed_ba_tfd
|
||||
* for details.
|
||||
* @ra_tid: array of RA-TID queue status updates. For debug purposes only. See
|
||||
* &iwl_mvm_compressed_ba_ratid for more details.
|
||||
*/
|
||||
struct iwl_mvm_compressed_ba_notif {
|
||||
__le32 flags;
|
||||
|
@ -646,6 +650,7 @@ struct iwl_mvm_compressed_ba_notif {
|
|||
__le16 query_frame_cnt;
|
||||
__le16 txed;
|
||||
__le16 done;
|
||||
__le16 reserved;
|
||||
__le32 wireless_time;
|
||||
__le32 tx_rate;
|
||||
__le16 tfd_cnt;
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*
|
||||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 Intel Deutschland GmbH
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -34,7 +34,7 @@
|
|||
*
|
||||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 Intel Deutschland GmbH
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -345,9 +345,10 @@ enum iwl_regulatory_and_nvm_subcmd_ids {
|
|||
NVM_ACCESS_COMPLETE = 0x0,
|
||||
};
|
||||
|
||||
enum iwl_fmac_debug_cmds {
|
||||
enum iwl_debug_cmds {
|
||||
LMAC_RD_WR = 0x0,
|
||||
UMAC_RD_WR = 0x1,
|
||||
MFU_ASSERT_DUMP_NTF = 0xFE,
|
||||
};
|
||||
|
||||
/* command groups */
|
||||
|
@ -673,10 +674,8 @@ struct iwl_error_resp {
|
|||
|
||||
|
||||
/* Common PHY, MAC and Bindings definitions */
|
||||
|
||||
#define MAX_MACS_IN_BINDING (3)
|
||||
#define MAX_BINDINGS (4)
|
||||
#define AUX_BINDING_INDEX (3)
|
||||
|
||||
/* Used to extract ID and color from the context dword */
|
||||
#define FW_CTXT_ID_POS (0)
|
||||
|
@ -960,6 +959,7 @@ struct iwl_time_event_notif {
|
|||
* @action: action to perform, one of FW_CTXT_ACTION_*
|
||||
* @macs: array of MAC id and colors which belong to the binding
|
||||
* @phy: PHY id and color which belongs to the binding
|
||||
* @lmac_id: the lmac id the binding belongs to
|
||||
*/
|
||||
struct iwl_binding_cmd {
|
||||
/* COMMON_INDEX_HDR_API_S_VER_1 */
|
||||
|
@ -968,7 +968,13 @@ struct iwl_binding_cmd {
|
|||
/* BINDING_DATA_API_S_VER_1 */
|
||||
__le32 macs[MAX_MACS_IN_BINDING];
|
||||
__le32 phy;
|
||||
} __packed; /* BINDING_CMD_API_S_VER_1 */
|
||||
/* BINDING_CMD_API_S_VER_1 */
|
||||
__le32 lmac_id;
|
||||
} __packed; /* BINDING_CMD_API_S_VER_2 */
|
||||
|
||||
#define IWL_BINDING_CMD_SIZE_V1 offsetof(struct iwl_binding_cmd, lmac_id)
|
||||
#define IWL_LMAC_24G_INDEX 0
|
||||
#define IWL_LMAC_5G_INDEX 1
|
||||
|
||||
/* The maximal number of fragments in the FW's schedule session */
|
||||
#define IWL_MVM_MAX_QUOTA 128
|
||||
|
@ -990,6 +996,9 @@ struct iwl_time_quota_data {
|
|||
* struct iwl_time_quota_cmd - configuration of time quota between bindings
|
||||
* ( TIME_QUOTA_CMD = 0x2c )
|
||||
* @quotas: allocations per binding
|
||||
* Note: on non-CDB the fourth one is the auxilary mac and is
|
||||
* essentially zero.
|
||||
* On CDB the fourth one is a regular binding.
|
||||
*/
|
||||
struct iwl_time_quota_cmd {
|
||||
struct iwl_time_quota_data quotas[MAX_BINDINGS];
|
||||
|
@ -1230,6 +1239,25 @@ struct iwl_mfuart_load_notif {
|
|||
__le32 image_size;
|
||||
} __packed; /*MFU_LOADER_NTFY_API_S_VER_2*/
|
||||
|
||||
/**
|
||||
* struct iwl_mfu_assert_dump_notif - mfuart dump logs
|
||||
* ( MFU_ASSERT_DUMP_NTF = 0xfe )
|
||||
* @assert_id: mfuart assert id that cause the notif
|
||||
* @curr_reset_num: number of asserts since uptime
|
||||
* @index_num: current chunk id
|
||||
* @parts_num: total number of chunks
|
||||
* @data_size: number of data bytes sent
|
||||
* @data: data buffer
|
||||
*/
|
||||
struct iwl_mfu_assert_dump_notif {
|
||||
__le32 assert_id;
|
||||
__le32 curr_reset_num;
|
||||
__le16 index_num;
|
||||
__le16 parts_num;
|
||||
__le32 data_size;
|
||||
__le32 data[0];
|
||||
} __packed; /*MFU_DUMP_ASSERT_API_S_VER_1*/
|
||||
|
||||
/**
|
||||
* struct iwl_set_calib_default_cmd - set default value for calibration.
|
||||
* ( SET_CALIB_DEFAULT_CMD = 0x8e )
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*
|
||||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 Intel Deutschland GmbH
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -34,6 +34,7 @@
|
|||
*
|
||||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -271,6 +272,27 @@ static int iwl_fill_paging_mem(struct iwl_mvm *mvm, const struct fw_img *image)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void iwl_mvm_mfu_assert_dump_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_mfu_assert_dump_notif *mfu_dump_notif = (void *)pkt->data;
|
||||
__le32 *dump_data = mfu_dump_notif->data;
|
||||
int n_words = le32_to_cpu(mfu_dump_notif->data_size) / sizeof(__le32);
|
||||
int i;
|
||||
|
||||
if (mfu_dump_notif->index_num == 0)
|
||||
IWL_INFO(mvm, "MFUART assert id 0x%x occurred\n",
|
||||
le32_to_cpu(mfu_dump_notif->assert_id));
|
||||
|
||||
for (i = 0; i < n_words; i++)
|
||||
IWL_DEBUG_INFO(mvm,
|
||||
"MFUART assert dump, dword %u: 0x%08x\n",
|
||||
le16_to_cpu(mfu_dump_notif->index_num) *
|
||||
n_words + i,
|
||||
le32_to_cpu(dump_data[i]));
|
||||
}
|
||||
|
||||
static int iwl_alloc_fw_paging_mem(struct iwl_mvm *mvm,
|
||||
const struct fw_img *image)
|
||||
{
|
||||
|
@ -828,14 +850,6 @@ int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
|
|||
goto error;
|
||||
}
|
||||
|
||||
/* TODO: remove when integrating context info */
|
||||
ret = iwl_mvm_init_paging(mvm);
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "Failed to init paging: %d\n",
|
||||
ret);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Read the NVM only at driver load time, no need to do this twice */
|
||||
if (read_nvm) {
|
||||
/* Read nvm */
|
||||
|
|
|
@ -473,6 +473,7 @@ static int iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm *mvm,
|
|||
}
|
||||
|
||||
mvmvif->bcast_sta.sta_id = IWL_MVM_STATION_COUNT;
|
||||
mvmvif->mcast_sta.sta_id = IWL_MVM_STATION_COUNT;
|
||||
mvmvif->ap_sta_id = IWL_MVM_STATION_COUNT;
|
||||
|
||||
for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++)
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 Intel Deutschland GmbH
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -33,7 +33,8 @@
|
|||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -1351,6 +1352,17 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
|
|||
goto out_release;
|
||||
}
|
||||
|
||||
if (iwl_mvm_is_dqa_supported(mvm)) {
|
||||
/*
|
||||
* Only queue for this station is the mcast queue,
|
||||
* which shouldn't be in TFD mask anyway
|
||||
*/
|
||||
ret = iwl_mvm_allocate_int_sta(mvm, &mvmvif->mcast_sta,
|
||||
0, vif->type);
|
||||
if (ret)
|
||||
goto out_release;
|
||||
}
|
||||
|
||||
iwl_mvm_vif_dbgfs_register(mvm, vif);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
@ -1516,6 +1528,7 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
|
|||
mvm->noa_duration = 0;
|
||||
}
|
||||
#endif
|
||||
iwl_mvm_dealloc_int_sta(mvm, &mvmvif->mcast_sta);
|
||||
iwl_mvm_dealloc_bcast_sta(mvm, vif);
|
||||
goto out_release;
|
||||
}
|
||||
|
@ -2104,6 +2117,10 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
|
|||
if (ret)
|
||||
goto out_unbind;
|
||||
|
||||
ret = iwl_mvm_add_mcast_sta(mvm, vif);
|
||||
if (ret)
|
||||
goto out_rm_bcast;
|
||||
|
||||
/* must be set before quota calculations */
|
||||
mvmvif->ap_ibss_active = true;
|
||||
|
||||
|
@ -2131,6 +2148,8 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
|
|||
out_quota_failed:
|
||||
iwl_mvm_power_update_mac(mvm);
|
||||
mvmvif->ap_ibss_active = false;
|
||||
iwl_mvm_rm_mcast_sta(mvm, vif);
|
||||
out_rm_bcast:
|
||||
iwl_mvm_send_rm_bcast_sta(mvm, vif);
|
||||
out_unbind:
|
||||
iwl_mvm_binding_remove_vif(mvm, vif);
|
||||
|
@ -2177,6 +2196,7 @@ static void iwl_mvm_stop_ap_ibss(struct ieee80211_hw *hw,
|
|||
iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif, false, NULL);
|
||||
|
||||
iwl_mvm_update_quotas(mvm, false, NULL);
|
||||
iwl_mvm_rm_mcast_sta(mvm, vif);
|
||||
iwl_mvm_send_rm_bcast_sta(mvm, vif);
|
||||
iwl_mvm_binding_remove_vif(mvm, vif);
|
||||
|
||||
|
@ -2343,6 +2363,9 @@ static void __iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
|
|||
tid_data->state != IWL_EMPTYING_HW_QUEUE_DELBA)
|
||||
continue;
|
||||
|
||||
if (tid_data->txq_id == IEEE80211_INVAL_HW_QUEUE)
|
||||
continue;
|
||||
|
||||
__set_bit(tid_data->txq_id, &txqs);
|
||||
|
||||
if (iwl_mvm_tid_queued(tid_data) == 0)
|
||||
|
|
|
@ -407,6 +407,7 @@ struct iwl_mvm_vif {
|
|||
struct iwl_mvm_time_event_data hs_time_event_data;
|
||||
|
||||
struct iwl_mvm_int_sta bcast_sta;
|
||||
struct iwl_mvm_int_sta mcast_sta;
|
||||
|
||||
/*
|
||||
* Assigned while mac80211 has the interface in a channel context,
|
||||
|
@ -975,7 +976,10 @@ struct iwl_mvm {
|
|||
#endif
|
||||
|
||||
/* Tx queues */
|
||||
u8 aux_queue;
|
||||
u16 aux_queue;
|
||||
u16 probe_queue;
|
||||
u16 p2p_dev_queue;
|
||||
|
||||
u8 first_agg_queue;
|
||||
u8 last_agg_queue;
|
||||
|
||||
|
@ -1222,13 +1226,15 @@ static inline bool iwl_mvm_is_cdb_supported(struct iwl_mvm *mvm)
|
|||
{
|
||||
/*
|
||||
* TODO:
|
||||
* The issue of how to determine CDB support is still not well defined.
|
||||
* It may be that it will be for all next HW devices and it may be per
|
||||
* FW compilation and it may also differ between different devices.
|
||||
* For now take a ride on the new TX API and get back to it when
|
||||
* it is well defined.
|
||||
* The issue of how to determine CDB APIs and usage is still not fully
|
||||
* defined.
|
||||
* There is a compilation for CDB and non-CDB FW, but there may
|
||||
* be also runtime check.
|
||||
* For now there is a TLV for checking compilation mode, but a
|
||||
* runtime check will also have to be here - once defined.
|
||||
*/
|
||||
return iwl_mvm_has_new_tx_api(mvm);
|
||||
return fw_has_capa(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_CDB_SUPPORT);
|
||||
}
|
||||
|
||||
static inline bool iwl_mvm_is_tt_in_fw(struct iwl_mvm *mvm)
|
||||
|
@ -1389,6 +1395,8 @@ int iwl_mvm_notify_rx_queue(struct iwl_mvm *mvm, u32 rxq_mask,
|
|||
void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
|
||||
int queue);
|
||||
void iwl_mvm_rx_tx_cmd(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb);
|
||||
void iwl_mvm_mfu_assert_dump_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb);
|
||||
void iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb);
|
||||
void iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb);
|
||||
|
@ -1701,7 +1709,8 @@ void iwl_mvm_enable_ac_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue,
|
|||
|
||||
static inline void iwl_mvm_stop_device(struct iwl_mvm *mvm)
|
||||
{
|
||||
iwl_free_fw_paging(mvm);
|
||||
if (!iwl_mvm_has_new_tx_api(mvm))
|
||||
iwl_free_fw_paging(mvm);
|
||||
mvm->ucode_loaded = false;
|
||||
iwl_trans_stop_device(mvm->trans);
|
||||
}
|
||||
|
|
|
@ -302,6 +302,8 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
|
|||
RX_HANDLER_SYNC),
|
||||
RX_HANDLER(TOF_NOTIFICATION, iwl_mvm_tof_resp_handler,
|
||||
RX_HANDLER_ASYNC_LOCKED),
|
||||
RX_HANDLER_GRP(DEBUG_GROUP, MFU_ASSERT_DUMP_NTF,
|
||||
iwl_mvm_mfu_assert_dump_notif, RX_HANDLER_SYNC),
|
||||
RX_HANDLER_GRP(PROT_OFFLOAD_GROUP, STORED_BEACON_NTF,
|
||||
iwl_mvm_rx_stored_beacon_notif, RX_HANDLER_SYNC),
|
||||
RX_HANDLER_GRP(DATA_PATH_GROUP, MU_GROUP_MGMT_NOTIF,
|
||||
|
@ -452,6 +454,7 @@ static const struct iwl_hcmd_names iwl_mvm_phy_names[] = {
|
|||
* Access is done through binary search
|
||||
*/
|
||||
static const struct iwl_hcmd_names iwl_mvm_data_path_names[] = {
|
||||
HCMD_NAME(DQA_ENABLE_CMD),
|
||||
HCMD_NAME(UPDATE_MU_GROUPS_CMD),
|
||||
HCMD_NAME(TRIGGER_RX_QUEUES_NOTIF_CMD),
|
||||
HCMD_NAME(STA_PM_NOTIF),
|
||||
|
@ -459,6 +462,13 @@ static const struct iwl_hcmd_names iwl_mvm_data_path_names[] = {
|
|||
HCMD_NAME(RX_QUEUES_NOTIFICATION),
|
||||
};
|
||||
|
||||
/* Please keep this array *SORTED* by hex value.
|
||||
* Access is done through binary search
|
||||
*/
|
||||
static const struct iwl_hcmd_names iwl_mvm_debug_names[] = {
|
||||
HCMD_NAME(MFU_ASSERT_DUMP_NTF),
|
||||
};
|
||||
|
||||
/* Please keep this array *SORTED* by hex value.
|
||||
* Access is done through binary search
|
||||
*/
|
||||
|
@ -602,6 +612,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
|||
}
|
||||
} else {
|
||||
mvm->aux_queue = IWL_MVM_DQA_AUX_QUEUE;
|
||||
mvm->probe_queue = IWL_MVM_DQA_AP_PROBE_RESP_QUEUE;
|
||||
mvm->p2p_dev_queue = IWL_MVM_DQA_P2P_DEVICE_QUEUE;
|
||||
mvm->first_agg_queue = IWL_MVM_DQA_MIN_DATA_QUEUE;
|
||||
mvm->last_agg_queue = IWL_MVM_DQA_MAX_DATA_QUEUE;
|
||||
}
|
||||
|
|
|
@ -104,7 +104,20 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,
|
|||
u8 crypt_len,
|
||||
struct iwl_rx_cmd_buffer *rxb)
|
||||
{
|
||||
unsigned int hdrlen, fraglen;
|
||||
unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control);
|
||||
unsigned int fraglen;
|
||||
|
||||
/*
|
||||
* The 'hdrlen' (plus the 8 bytes for the SNAP and the crypt_len,
|
||||
* but those are all multiples of 4 long) all goes away, but we
|
||||
* want the *end* of it, which is going to be the start of the IP
|
||||
* header, to be aligned when it gets pulled in.
|
||||
* The beginning of the skb->data is aligned on at least a 4-byte
|
||||
* boundary after allocation. Everything here is aligned at least
|
||||
* on a 2-byte boundary so we can just take hdrlen & 3 and pad by
|
||||
* the result.
|
||||
*/
|
||||
skb_reserve(skb, hdrlen & 3);
|
||||
|
||||
/* If frame is small enough to fit in skb->head, pull it completely.
|
||||
* If not, only pull ieee80211_hdr (including crypto if present, and
|
||||
|
@ -118,8 +131,7 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,
|
|||
* If the latter changes (there are efforts in the standards group
|
||||
* to do so) we should revisit this and ieee80211_data_to_8023().
|
||||
*/
|
||||
hdrlen = (len <= skb_tailroom(skb)) ? len :
|
||||
sizeof(*hdr) + crypt_len + 8;
|
||||
hdrlen = (len <= skb_tailroom(skb)) ? len : hdrlen + crypt_len + 8;
|
||||
|
||||
memcpy(skb_put(skb, hdrlen), hdr, hdrlen);
|
||||
fraglen = len - hdrlen;
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*
|
||||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2015 - 2016 Intel Deutschland GmbH
|
||||
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -29,7 +29,7 @@
|
|||
*
|
||||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2015 - 2016 Intel Deutschland GmbH
|
||||
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -462,6 +462,7 @@ void iwl_mvm_reorder_timer_expired(unsigned long data)
|
|||
int i;
|
||||
u16 sn = 0, index = 0;
|
||||
bool expired = false;
|
||||
bool cont = false;
|
||||
|
||||
spin_lock(&buf->lock);
|
||||
|
||||
|
@ -473,12 +474,21 @@ void iwl_mvm_reorder_timer_expired(unsigned long data)
|
|||
for (i = 0; i < buf->buf_size ; i++) {
|
||||
index = (buf->head_sn + i) % buf->buf_size;
|
||||
|
||||
if (skb_queue_empty(&buf->entries[index]))
|
||||
if (skb_queue_empty(&buf->entries[index])) {
|
||||
/*
|
||||
* If there is a hole and the next frame didn't expire
|
||||
* we want to break and not advance SN
|
||||
*/
|
||||
cont = false;
|
||||
continue;
|
||||
if (!time_after(jiffies, buf->reorder_time[index] +
|
||||
RX_REORDER_BUF_TIMEOUT_MQ))
|
||||
}
|
||||
if (!cont && !time_after(jiffies, buf->reorder_time[index] +
|
||||
RX_REORDER_BUF_TIMEOUT_MQ))
|
||||
break;
|
||||
|
||||
expired = true;
|
||||
/* continue until next hole after this expired frames */
|
||||
cont = true;
|
||||
sn = ieee80211_sn_add(buf->head_sn, i + 1);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*
|
||||
* Copyright(c) 2012 - 2015 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 Intel Deutschland GmbH
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -34,7 +34,7 @@
|
|||
*
|
||||
* Copyright(c) 2012 - 2015 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 Intel Deutschland GmbH
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -1652,8 +1652,7 @@ int iwl_mvm_allocate_int_sta(struct iwl_mvm *mvm,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void iwl_mvm_dealloc_int_sta(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_int_sta *sta)
|
||||
void iwl_mvm_dealloc_int_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *sta)
|
||||
{
|
||||
RCU_INIT_POINTER(mvm->fw_id_to_mac_id[sta->sta_id], NULL);
|
||||
memset(sta, 0, sizeof(struct iwl_mvm_int_sta));
|
||||
|
@ -1808,9 +1807,9 @@ int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
|||
|
||||
if (vif->type == NL80211_IFTYPE_AP ||
|
||||
vif->type == NL80211_IFTYPE_ADHOC)
|
||||
queue = IWL_MVM_DQA_AP_PROBE_RESP_QUEUE;
|
||||
queue = mvm->probe_queue;
|
||||
else if (vif->type == NL80211_IFTYPE_P2P_DEVICE)
|
||||
queue = IWL_MVM_DQA_P2P_DEVICE_QUEUE;
|
||||
queue = mvm->p2p_dev_queue;
|
||||
else if (WARN(1, "Missing required TXQ for adding bcast STA\n"))
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -1869,24 +1868,18 @@ static void iwl_mvm_free_bcast_sta_queues(struct iwl_mvm *mvm,
|
|||
iwl_mvm_disable_txq(mvm, vif->cab_queue, vif->cab_queue,
|
||||
IWL_MAX_TID_COUNT, 0);
|
||||
|
||||
if (mvmvif->bcast_sta.tfd_queue_msk &
|
||||
BIT(IWL_MVM_DQA_AP_PROBE_RESP_QUEUE)) {
|
||||
iwl_mvm_disable_txq(mvm,
|
||||
IWL_MVM_DQA_AP_PROBE_RESP_QUEUE,
|
||||
if (mvmvif->bcast_sta.tfd_queue_msk & BIT(mvm->probe_queue)) {
|
||||
iwl_mvm_disable_txq(mvm, mvm->probe_queue,
|
||||
vif->hw_queue[0], IWL_MAX_TID_COUNT,
|
||||
0);
|
||||
mvmvif->bcast_sta.tfd_queue_msk &=
|
||||
~BIT(IWL_MVM_DQA_AP_PROBE_RESP_QUEUE);
|
||||
mvmvif->bcast_sta.tfd_queue_msk &= ~BIT(mvm->probe_queue);
|
||||
}
|
||||
|
||||
if (mvmvif->bcast_sta.tfd_queue_msk &
|
||||
BIT(IWL_MVM_DQA_P2P_DEVICE_QUEUE)) {
|
||||
iwl_mvm_disable_txq(mvm,
|
||||
IWL_MVM_DQA_P2P_DEVICE_QUEUE,
|
||||
if (mvmvif->bcast_sta.tfd_queue_msk & BIT(mvm->p2p_dev_queue)) {
|
||||
iwl_mvm_disable_txq(mvm, mvm->p2p_dev_queue,
|
||||
vif->hw_queue[0], IWL_MAX_TID_COUNT,
|
||||
0);
|
||||
mvmvif->bcast_sta.tfd_queue_msk &=
|
||||
~BIT(IWL_MVM_DQA_P2P_DEVICE_QUEUE);
|
||||
mvmvif->bcast_sta.tfd_queue_msk &= ~BIT(mvm->p2p_dev_queue);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1982,6 +1975,80 @@ int iwl_mvm_rm_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a new station entry for the multicast station to the given vif,
|
||||
* and send it to the FW.
|
||||
* Note that each AP/GO mac should have its own multicast station.
|
||||
*
|
||||
* @mvm: the mvm component
|
||||
* @vif: the interface to which the multicast station is added
|
||||
*/
|
||||
int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mvm_int_sta *msta = &mvmvif->mcast_sta;
|
||||
static const u8 _maddr[] = {0x03, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
const u8 *maddr = _maddr;
|
||||
struct iwl_trans_txq_scd_cfg cfg = {
|
||||
.fifo = IWL_MVM_TX_FIFO_MCAST,
|
||||
.sta_id = msta->sta_id,
|
||||
.tid = IWL_MAX_TID_COUNT,
|
||||
.aggregate = false,
|
||||
.frame_limit = IWL_FRAME_LIMIT,
|
||||
};
|
||||
unsigned int timeout = iwl_mvm_get_wd_timeout(mvm, vif, false, false);
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
if (!iwl_mvm_is_dqa_supported(mvm))
|
||||
return 0;
|
||||
|
||||
if (WARN_ON(vif->type != NL80211_IFTYPE_AP))
|
||||
return -ENOTSUPP;
|
||||
|
||||
ret = iwl_mvm_add_int_sta_common(mvm, msta, maddr,
|
||||
mvmvif->id, mvmvif->color);
|
||||
if (ret) {
|
||||
iwl_mvm_dealloc_int_sta(mvm, msta);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable cab queue after the ADD_STA command is sent.
|
||||
* This is needed for a000 firmware which won't accept SCD_QUEUE_CFG
|
||||
* command with unknown station id.
|
||||
*/
|
||||
iwl_mvm_enable_txq(mvm, vif->cab_queue, vif->cab_queue, 0, &cfg,
|
||||
timeout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send the FW a request to remove the station from it's internal data
|
||||
* structures, and in addition remove it from the local data structure.
|
||||
*/
|
||||
int iwl_mvm_rm_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
if (!iwl_mvm_is_dqa_supported(mvm))
|
||||
return 0;
|
||||
|
||||
iwl_mvm_disable_txq(mvm, vif->cab_queue, vif->cab_queue,
|
||||
IWL_MAX_TID_COUNT, 0);
|
||||
|
||||
ret = iwl_mvm_rm_sta_common(mvm, mvmvif->mcast_sta.sta_id);
|
||||
if (ret)
|
||||
IWL_WARN(mvm, "Failed sending remove station\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define IWL_MAX_RX_BA_SESSIONS 16
|
||||
|
||||
static void iwl_mvm_sync_rxq_del_ba(struct iwl_mvm *mvm, u8 baid)
|
||||
|
@ -2697,68 +2764,97 @@ static struct iwl_mvm_sta *iwl_mvm_get_key_sta(struct iwl_mvm *mvm,
|
|||
|
||||
static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_sta *mvm_sta,
|
||||
struct ieee80211_key_conf *keyconf, bool mcast,
|
||||
struct ieee80211_key_conf *key, bool mcast,
|
||||
u32 tkip_iv32, u16 *tkip_p1k, u32 cmd_flags,
|
||||
u8 key_offset)
|
||||
{
|
||||
struct iwl_mvm_add_sta_key_cmd cmd = {};
|
||||
union {
|
||||
struct iwl_mvm_add_sta_key_cmd_v1 cmd_v1;
|
||||
struct iwl_mvm_add_sta_key_cmd cmd;
|
||||
} u = {};
|
||||
__le16 key_flags;
|
||||
int ret;
|
||||
u32 status;
|
||||
u16 keyidx;
|
||||
int i;
|
||||
u8 sta_id = mvm_sta->sta_id;
|
||||
u64 pn = 0;
|
||||
int i, size;
|
||||
bool new_api = fw_has_api(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_API_TKIP_MIC_KEYS);
|
||||
|
||||
keyidx = (keyconf->keyidx << STA_KEY_FLG_KEYID_POS) &
|
||||
keyidx = (key->keyidx << STA_KEY_FLG_KEYID_POS) &
|
||||
STA_KEY_FLG_KEYID_MSK;
|
||||
key_flags = cpu_to_le16(keyidx);
|
||||
key_flags |= cpu_to_le16(STA_KEY_FLG_WEP_KEY_MAP);
|
||||
|
||||
switch (keyconf->cipher) {
|
||||
switch (key->cipher) {
|
||||
case WLAN_CIPHER_SUITE_TKIP:
|
||||
key_flags |= cpu_to_le16(STA_KEY_FLG_TKIP);
|
||||
cmd.tkip_rx_tsc_byte2 = tkip_iv32;
|
||||
for (i = 0; i < 5; i++)
|
||||
cmd.tkip_rx_ttak[i] = cpu_to_le16(tkip_p1k[i]);
|
||||
memcpy(cmd.key, keyconf->key, keyconf->keylen);
|
||||
if (new_api) {
|
||||
memcpy((void *)&u.cmd.tx_mic_key,
|
||||
&key->key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY],
|
||||
IWL_MIC_KEY_SIZE);
|
||||
|
||||
memcpy((void *)&u.cmd.rx_mic_key,
|
||||
&key->key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY],
|
||||
IWL_MIC_KEY_SIZE);
|
||||
pn = atomic64_read(&key->tx_pn);
|
||||
|
||||
} else {
|
||||
u.cmd_v1.tkip_rx_tsc_byte2 = tkip_iv32;
|
||||
for (i = 0; i < 5; i++)
|
||||
u.cmd_v1.tkip_rx_ttak[i] =
|
||||
cpu_to_le16(tkip_p1k[i]);
|
||||
}
|
||||
memcpy(u.cmd.common.key, key->key, key->keylen);
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_CCMP:
|
||||
key_flags |= cpu_to_le16(STA_KEY_FLG_CCM);
|
||||
memcpy(cmd.key, keyconf->key, keyconf->keylen);
|
||||
memcpy(u.cmd.common.key, key->key, key->keylen);
|
||||
if (new_api)
|
||||
pn = atomic64_read(&key->tx_pn);
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_WEP104:
|
||||
key_flags |= cpu_to_le16(STA_KEY_FLG_WEP_13BYTES);
|
||||
/* fall through */
|
||||
case WLAN_CIPHER_SUITE_WEP40:
|
||||
key_flags |= cpu_to_le16(STA_KEY_FLG_WEP);
|
||||
memcpy(cmd.key + 3, keyconf->key, keyconf->keylen);
|
||||
memcpy(u.cmd.common.key + 3, key->key, key->keylen);
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_GCMP_256:
|
||||
key_flags |= cpu_to_le16(STA_KEY_FLG_KEY_32BYTES);
|
||||
/* fall through */
|
||||
case WLAN_CIPHER_SUITE_GCMP:
|
||||
key_flags |= cpu_to_le16(STA_KEY_FLG_GCMP);
|
||||
memcpy(cmd.key, keyconf->key, keyconf->keylen);
|
||||
memcpy(u.cmd.common.key, key->key, key->keylen);
|
||||
if (new_api)
|
||||
pn = atomic64_read(&key->tx_pn);
|
||||
break;
|
||||
default:
|
||||
key_flags |= cpu_to_le16(STA_KEY_FLG_EXT);
|
||||
memcpy(cmd.key, keyconf->key, keyconf->keylen);
|
||||
memcpy(u.cmd.common.key, key->key, key->keylen);
|
||||
}
|
||||
|
||||
if (mcast)
|
||||
key_flags |= cpu_to_le16(STA_KEY_MULTICAST);
|
||||
|
||||
cmd.key_offset = key_offset;
|
||||
cmd.key_flags = key_flags;
|
||||
cmd.sta_id = sta_id;
|
||||
u.cmd.common.key_offset = key_offset;
|
||||
u.cmd.common.key_flags = key_flags;
|
||||
u.cmd.common.sta_id = mvm_sta->sta_id;
|
||||
|
||||
if (new_api) {
|
||||
u.cmd.transmit_seq_cnt = cpu_to_le64(pn);
|
||||
size = sizeof(u.cmd);
|
||||
} else {
|
||||
size = sizeof(u.cmd_v1);
|
||||
}
|
||||
|
||||
status = ADD_STA_SUCCESS;
|
||||
if (cmd_flags & CMD_ASYNC)
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA_KEY, CMD_ASYNC,
|
||||
sizeof(cmd), &cmd);
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA_KEY, CMD_ASYNC, size,
|
||||
&u.cmd);
|
||||
else
|
||||
ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA_KEY, sizeof(cmd),
|
||||
&cmd, &status);
|
||||
ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA_KEY, size,
|
||||
&u.cmd, &status);
|
||||
|
||||
switch (status) {
|
||||
case ADD_STA_SUCCESS:
|
||||
|
@ -2911,9 +3007,14 @@ static int __iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, u8 sta_id,
|
|||
struct ieee80211_key_conf *keyconf,
|
||||
bool mcast)
|
||||
{
|
||||
struct iwl_mvm_add_sta_key_cmd cmd = {};
|
||||
union {
|
||||
struct iwl_mvm_add_sta_key_cmd_v1 cmd_v1;
|
||||
struct iwl_mvm_add_sta_key_cmd cmd;
|
||||
} u = {};
|
||||
bool new_api = fw_has_api(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_API_TKIP_MIC_KEYS);
|
||||
__le16 key_flags;
|
||||
int ret;
|
||||
int ret, size;
|
||||
u32 status;
|
||||
|
||||
key_flags = cpu_to_le16((keyconf->keyidx << STA_KEY_FLG_KEYID_POS) &
|
||||
|
@ -2924,13 +3025,19 @@ static int __iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, u8 sta_id,
|
|||
if (mcast)
|
||||
key_flags |= cpu_to_le16(STA_KEY_MULTICAST);
|
||||
|
||||
cmd.key_flags = key_flags;
|
||||
cmd.key_offset = keyconf->hw_key_idx;
|
||||
cmd.sta_id = sta_id;
|
||||
/*
|
||||
* The fields assigned here are in the same location at the start
|
||||
* of the command, so we can do this union trick.
|
||||
*/
|
||||
u.cmd.common.key_flags = key_flags;
|
||||
u.cmd.common.key_offset = keyconf->hw_key_idx;
|
||||
u.cmd.common.sta_id = sta_id;
|
||||
|
||||
size = new_api ? sizeof(u.cmd) : sizeof(u.cmd_v1);
|
||||
|
||||
status = ADD_STA_SUCCESS;
|
||||
ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA_KEY, sizeof(cmd),
|
||||
&cmd, &status);
|
||||
ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA_KEY, size, &u.cmd,
|
||||
&status);
|
||||
|
||||
switch (status) {
|
||||
case ADD_STA_SUCCESS:
|
||||
|
|
|
@ -532,10 +532,13 @@ int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
|||
int iwl_mvm_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
int iwl_mvm_send_rm_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
int iwl_mvm_rm_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
int iwl_mvm_rm_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
int iwl_mvm_allocate_int_sta(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_int_sta *sta,
|
||||
u32 qmask, enum nl80211_iftype iftype);
|
||||
void iwl_mvm_dealloc_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
void iwl_mvm_dealloc_int_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *sta);
|
||||
int iwl_mvm_add_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
int iwl_mvm_rm_snif_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
|
||||
void iwl_mvm_dealloc_snif_sta(struct iwl_mvm *mvm);
|
||||
|
|
|
@ -514,21 +514,21 @@ static int iwl_mvm_get_ctrl_vif_queue(struct iwl_mvm *mvm,
|
|||
*/
|
||||
if (ieee80211_is_probe_resp(fc) || ieee80211_is_auth(fc) ||
|
||||
ieee80211_is_deauth(fc))
|
||||
return IWL_MVM_DQA_AP_PROBE_RESP_QUEUE;
|
||||
return mvm->probe_queue;
|
||||
if (info->hw_queue == info->control.vif->cab_queue)
|
||||
return info->hw_queue;
|
||||
|
||||
WARN_ONCE(info->control.vif->type != NL80211_IFTYPE_ADHOC,
|
||||
"fc=0x%02x", le16_to_cpu(fc));
|
||||
return IWL_MVM_DQA_AP_PROBE_RESP_QUEUE;
|
||||
return mvm->probe_queue;
|
||||
case NL80211_IFTYPE_P2P_DEVICE:
|
||||
if (ieee80211_is_mgmt(fc))
|
||||
return IWL_MVM_DQA_P2P_DEVICE_QUEUE;
|
||||
return mvm->p2p_dev_queue;
|
||||
if (info->hw_queue == info->control.vif->cab_queue)
|
||||
return info->hw_queue;
|
||||
|
||||
WARN_ON_ONCE(1);
|
||||
return IWL_MVM_DQA_P2P_DEVICE_QUEUE;
|
||||
return mvm->p2p_dev_queue;
|
||||
default:
|
||||
WARN_ONCE(1, "Not a ctrl vif, no available queue\n");
|
||||
return -1;
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*
|
||||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2015 Intel Deutschland GmbH
|
||||
* Copyright (C) 2015 - 2017 Intel Deutschland GmbH
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -34,6 +34,7 @@
|
|||
*
|
||||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2015 - 2017 Intel Deutschland GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -644,20 +645,19 @@ int iwl_mvm_reconfig_scd(struct iwl_mvm *mvm, int queue, int fifo, int sta_id,
|
|||
return ret;
|
||||
}
|
||||
|
||||
void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue,
|
||||
u16 ssn, const struct iwl_trans_txq_scd_cfg *cfg,
|
||||
unsigned int wdg_timeout)
|
||||
static bool iwl_mvm_update_txq_mapping(struct iwl_mvm *mvm, int queue,
|
||||
int mac80211_queue, u8 sta_id, u8 tid)
|
||||
{
|
||||
bool enable_queue = true;
|
||||
|
||||
spin_lock_bh(&mvm->queue_info_lock);
|
||||
|
||||
/* Make sure this TID isn't already enabled */
|
||||
if (mvm->queue_info[queue].tid_bitmap & BIT(cfg->tid)) {
|
||||
if (mvm->queue_info[queue].tid_bitmap & BIT(tid)) {
|
||||
spin_unlock_bh(&mvm->queue_info_lock);
|
||||
IWL_ERR(mvm, "Trying to enable TXQ %d with existing TID %d\n",
|
||||
queue, cfg->tid);
|
||||
return;
|
||||
queue, tid);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Update mappings and refcounts */
|
||||
|
@ -666,17 +666,17 @@ void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue,
|
|||
|
||||
mvm->queue_info[queue].hw_queue_to_mac80211 |= BIT(mac80211_queue);
|
||||
mvm->queue_info[queue].hw_queue_refcount++;
|
||||
mvm->queue_info[queue].tid_bitmap |= BIT(cfg->tid);
|
||||
mvm->queue_info[queue].ra_sta_id = cfg->sta_id;
|
||||
mvm->queue_info[queue].tid_bitmap |= BIT(tid);
|
||||
mvm->queue_info[queue].ra_sta_id = sta_id;
|
||||
|
||||
if (enable_queue) {
|
||||
if (cfg->tid != IWL_MAX_TID_COUNT)
|
||||
if (tid != IWL_MAX_TID_COUNT)
|
||||
mvm->queue_info[queue].mac80211_ac =
|
||||
tid_to_mac80211_ac[cfg->tid];
|
||||
tid_to_mac80211_ac[tid];
|
||||
else
|
||||
mvm->queue_info[queue].mac80211_ac = IEEE80211_AC_VO;
|
||||
|
||||
mvm->queue_info[queue].txq_tid = cfg->tid;
|
||||
mvm->queue_info[queue].txq_tid = tid;
|
||||
}
|
||||
|
||||
IWL_DEBUG_TX_QUEUES(mvm,
|
||||
|
@ -686,8 +686,16 @@ void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue,
|
|||
|
||||
spin_unlock_bh(&mvm->queue_info_lock);
|
||||
|
||||
return enable_queue;
|
||||
}
|
||||
|
||||
void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue,
|
||||
u16 ssn, const struct iwl_trans_txq_scd_cfg *cfg,
|
||||
unsigned int wdg_timeout)
|
||||
{
|
||||
/* Send the enabling command if we need to */
|
||||
if (enable_queue) {
|
||||
if (iwl_mvm_update_txq_mapping(mvm, queue, mac80211_queue,
|
||||
cfg->sta_id, cfg->tid)) {
|
||||
struct iwl_scd_txq_cfg_cmd cmd = {
|
||||
.scd_queue = queue,
|
||||
.action = SCD_CFG_ENABLE_QUEUE,
|
||||
|
|
|
@ -0,0 +1,274 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2017 Intel Deutschland GmbH
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2017 Intel Deutschland GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-fh.h"
|
||||
#include "iwl-context-info.h"
|
||||
#include "internal.h"
|
||||
#include "iwl-prph.h"
|
||||
|
||||
static int iwl_pcie_get_num_sections(const struct fw_img *fw,
|
||||
int start)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (start < fw->num_sec &&
|
||||
fw->sec[start].offset != CPU1_CPU2_SEPARATOR_SECTION &&
|
||||
fw->sec[start].offset != PAGING_SEPARATOR_SECTION) {
|
||||
start++;
|
||||
i++;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static int iwl_pcie_ctxt_info_alloc_dma(struct iwl_trans *trans,
|
||||
const struct fw_desc *sec,
|
||||
struct iwl_dram_data *dram)
|
||||
{
|
||||
dram->block = dma_alloc_coherent(trans->dev, sec->len,
|
||||
&dram->physical,
|
||||
GFP_KERNEL);
|
||||
if (!dram->block)
|
||||
return -ENOMEM;
|
||||
|
||||
dram->size = sec->len;
|
||||
memcpy(dram->block, sec->data, sec->len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iwl_pcie_ctxt_info_free_fw_img(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
struct iwl_self_init_dram *dram = &trans_pcie->init_dram;
|
||||
int i;
|
||||
|
||||
if (!dram->fw) {
|
||||
WARN_ON(dram->fw_cnt);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < dram->fw_cnt; i++)
|
||||
dma_free_coherent(trans->dev, dram->fw[i].size,
|
||||
dram->fw[i].block, dram->fw[i].physical);
|
||||
|
||||
kfree(dram->fw);
|
||||
dram->fw_cnt = 0;
|
||||
}
|
||||
|
||||
void iwl_pcie_ctxt_info_free_paging(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
struct iwl_self_init_dram *dram = &trans_pcie->init_dram;
|
||||
int i;
|
||||
|
||||
if (!dram->paging) {
|
||||
WARN_ON(dram->paging_cnt);
|
||||
return;
|
||||
}
|
||||
|
||||
/* free paging*/
|
||||
for (i = 0; i < dram->paging_cnt; i++)
|
||||
dma_free_coherent(trans->dev, dram->paging[i].size,
|
||||
dram->paging[i].block,
|
||||
dram->paging[i].physical);
|
||||
|
||||
kfree(dram->paging);
|
||||
dram->paging_cnt = 0;
|
||||
}
|
||||
|
||||
static int iwl_pcie_ctxt_info_init_fw_sec(struct iwl_trans *trans,
|
||||
const struct fw_img *fw,
|
||||
struct iwl_context_info *ctxt_info)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
struct iwl_self_init_dram *dram = &trans_pcie->init_dram;
|
||||
struct iwl_context_info_dram *ctxt_dram = &ctxt_info->dram;
|
||||
int i, ret, lmac_cnt, umac_cnt, paging_cnt;
|
||||
|
||||
lmac_cnt = iwl_pcie_get_num_sections(fw, 0);
|
||||
/* add 1 due to separator */
|
||||
umac_cnt = iwl_pcie_get_num_sections(fw, lmac_cnt + 1);
|
||||
/* add 2 due to separators */
|
||||
paging_cnt = iwl_pcie_get_num_sections(fw, lmac_cnt + umac_cnt + 2);
|
||||
|
||||
dram->fw = kcalloc(umac_cnt + lmac_cnt, sizeof(*dram->fw), GFP_KERNEL);
|
||||
if (!dram->fw)
|
||||
return -ENOMEM;
|
||||
dram->paging = kcalloc(paging_cnt, sizeof(*dram->paging), GFP_KERNEL);
|
||||
if (!dram->paging)
|
||||
return -ENOMEM;
|
||||
|
||||
/* initialize lmac sections */
|
||||
for (i = 0; i < lmac_cnt; i++) {
|
||||
ret = iwl_pcie_ctxt_info_alloc_dma(trans, &fw->sec[i],
|
||||
&dram->fw[dram->fw_cnt]);
|
||||
if (ret)
|
||||
return ret;
|
||||
ctxt_dram->lmac_img[i] =
|
||||
cpu_to_le64(dram->fw[dram->fw_cnt].physical);
|
||||
dram->fw_cnt++;
|
||||
}
|
||||
|
||||
/* initialize umac sections */
|
||||
for (i = 0; i < umac_cnt; i++) {
|
||||
/* access FW with +1 to make up for lmac separator */
|
||||
ret = iwl_pcie_ctxt_info_alloc_dma(trans,
|
||||
&fw->sec[dram->fw_cnt + 1],
|
||||
&dram->fw[dram->fw_cnt]);
|
||||
if (ret)
|
||||
return ret;
|
||||
ctxt_dram->umac_img[i] =
|
||||
cpu_to_le64(dram->fw[dram->fw_cnt].physical);
|
||||
dram->fw_cnt++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize paging.
|
||||
* Paging memory isn't stored in dram->fw as the umac and lmac - it is
|
||||
* stored separately.
|
||||
* This is since the timing of its release is different -
|
||||
* while fw memory can be released on alive, the paging memory can be
|
||||
* freed only when the device goes down.
|
||||
* Given that, the logic here in accessing the fw image is a bit
|
||||
* different - fw_cnt isn't changing so loop counter is added to it.
|
||||
*/
|
||||
for (i = 0; i < paging_cnt; i++) {
|
||||
/* access FW with +2 to make up for lmac & umac separators */
|
||||
int fw_idx = dram->fw_cnt + i + 2;
|
||||
|
||||
ret = iwl_pcie_ctxt_info_alloc_dma(trans, &fw->sec[fw_idx],
|
||||
&dram->paging[i]);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ctxt_dram->virtual_img[i] =
|
||||
cpu_to_le64(dram->paging[i].physical);
|
||||
dram->paging_cnt++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwl_pcie_ctxt_info_init(struct iwl_trans *trans,
|
||||
const struct fw_img *fw)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
struct iwl_context_info *ctxt_info;
|
||||
struct iwl_context_info_rbd_cfg *rx_cfg;
|
||||
u32 control_flags = 0;
|
||||
int ret;
|
||||
|
||||
ctxt_info = dma_alloc_coherent(trans->dev, sizeof(*ctxt_info),
|
||||
&trans_pcie->ctxt_info_dma_addr,
|
||||
GFP_KERNEL);
|
||||
if (!ctxt_info)
|
||||
return -ENOMEM;
|
||||
|
||||
ctxt_info->version.version = 0;
|
||||
ctxt_info->version.mac_id =
|
||||
cpu_to_le16((u16)iwl_read32(trans, CSR_HW_REV));
|
||||
/* size is in DWs */
|
||||
ctxt_info->version.size = cpu_to_le16(sizeof(*ctxt_info) / 4);
|
||||
|
||||
BUILD_BUG_ON(RX_QUEUE_CB_SIZE(MQ_RX_TABLE_SIZE) > 0xF);
|
||||
control_flags = IWL_CTXT_INFO_RB_SIZE_4K |
|
||||
IWL_CTXT_INFO_TFD_FORMAT_LONG |
|
||||
RX_QUEUE_CB_SIZE(MQ_RX_TABLE_SIZE) <<
|
||||
IWL_CTXT_INFO_RB_CB_SIZE_POS;
|
||||
ctxt_info->control.control_flags = cpu_to_le32(control_flags);
|
||||
|
||||
/* initialize RX default queue */
|
||||
rx_cfg = &ctxt_info->rbd_cfg;
|
||||
rx_cfg->free_rbd_addr = cpu_to_le64(trans_pcie->rxq->bd_dma);
|
||||
rx_cfg->used_rbd_addr = cpu_to_le64(trans_pcie->rxq->used_bd_dma);
|
||||
rx_cfg->status_wr_ptr = cpu_to_le64(trans_pcie->rxq->rb_stts_dma);
|
||||
|
||||
/* initialize TX command queue */
|
||||
ctxt_info->hcmd_cfg.cmd_queue_addr =
|
||||
cpu_to_le64(trans_pcie->txq[trans_pcie->cmd_queue].dma_addr);
|
||||
ctxt_info->hcmd_cfg.cmd_queue_size =
|
||||
TFD_QUEUE_CB_SIZE(TFD_QUEUE_SIZE_MAX);
|
||||
|
||||
/* allocate ucode sections in dram and set addresses */
|
||||
ret = iwl_pcie_ctxt_info_init_fw_sec(trans, fw, ctxt_info);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
trans_pcie->ctxt_info = ctxt_info;
|
||||
|
||||
iwl_enable_interrupts(trans);
|
||||
|
||||
/* kick FW self load */
|
||||
iwl_write64(trans, CSR_CTXT_INFO_BA, trans_pcie->ctxt_info_dma_addr);
|
||||
iwl_write_prph(trans, UREG_CPU_INIT_RUN, 1);
|
||||
|
||||
/* Context info will be released upon alive or failure to get one */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void iwl_pcie_ctxt_info_free(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
||||
if (!trans_pcie->ctxt_info)
|
||||
return;
|
||||
|
||||
dma_free_coherent(trans->dev, sizeof(*trans_pcie->ctxt_info),
|
||||
trans_pcie->ctxt_info,
|
||||
trans_pcie->ctxt_info_dma_addr);
|
||||
trans_pcie->ctxt_info_dma_addr = 0;
|
||||
trans_pcie->ctxt_info = NULL;
|
||||
|
||||
iwl_pcie_ctxt_info_free_fw_img(trans);
|
||||
}
|
|
@ -667,18 +667,11 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
iwl_trans->cfg = cfg_7265d;
|
||||
}
|
||||
|
||||
if (iwl_trans->cfg->rf_id) {
|
||||
if (cfg == &iwl9460_2ac_cfg &&
|
||||
iwl_trans->hw_rf_id == CSR_HW_RF_ID_TYPE_LC) {
|
||||
cfg = &iwl9000lc_2ac_cfg;
|
||||
iwl_trans->cfg = cfg;
|
||||
}
|
||||
|
||||
if (cfg == &iwla000_2ac_cfg_hr &&
|
||||
iwl_trans->hw_rf_id == CSR_HW_RF_ID_TYPE_JF) {
|
||||
cfg = &iwla000_2ac_cfg_jf;
|
||||
iwl_trans->cfg = cfg;
|
||||
}
|
||||
if (iwl_trans->cfg->rf_id &&
|
||||
(cfg == &iwla000_2ac_cfg_hr &&
|
||||
iwl_trans->hw_rf_id == CSR_HW_RF_ID_TYPE_JF)) {
|
||||
cfg = &iwla000_2ac_cfg_jf;
|
||||
iwl_trans->cfg = cfg;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
*
|
||||
* Copyright(c) 2003 - 2015 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 Intel Deutschland GmbH
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
*
|
||||
* Portions of this file are derived from the ipw3945 project, as well
|
||||
* as portions of the ieee80211 subsystem header files.
|
||||
|
@ -237,7 +237,6 @@ struct iwl_pcie_first_tb_buf {
|
|||
* @stuck_timer: timer that fires if queue gets stuck
|
||||
* @trans_pcie: pointer back to transport (for timer)
|
||||
* @need_update: indicates need to update read/write index
|
||||
* @active: stores if queue is active
|
||||
* @ampdu: true if this queue is an ampdu queue for an specific RA/TID
|
||||
* @wd_timeout: queue watchdog timeout (jiffies) - per queue
|
||||
* @frozen: tx stuck queue timer is frozen
|
||||
|
@ -277,7 +276,6 @@ struct iwl_txq {
|
|||
struct iwl_trans_pcie *trans_pcie;
|
||||
bool need_update;
|
||||
bool frozen;
|
||||
u8 active;
|
||||
bool ampdu;
|
||||
int block;
|
||||
unsigned long wd_timeout;
|
||||
|
@ -314,12 +312,44 @@ enum iwl_shared_irq_flags {
|
|||
IWL_SHARED_IRQ_FIRST_RSS = BIT(1),
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_dram_data
|
||||
* @physical: page phy pointer
|
||||
* @block: pointer to the allocated block/page
|
||||
* @size: size of the block/page
|
||||
*/
|
||||
struct iwl_dram_data {
|
||||
dma_addr_t physical;
|
||||
void *block;
|
||||
int size;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_self_init_dram - dram data used by self init process
|
||||
* @fw: lmac and umac dram data
|
||||
* @fw_cnt: total number of items in array
|
||||
* @paging: paging dram data
|
||||
* @paging_cnt: total number of items in array
|
||||
*/
|
||||
struct iwl_self_init_dram {
|
||||
struct iwl_dram_data *fw;
|
||||
int fw_cnt;
|
||||
struct iwl_dram_data *paging;
|
||||
int paging_cnt;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_trans_pcie - PCIe transport specific data
|
||||
* @rxq: all the RX queue data
|
||||
* @rx_pool: initial pool of iwl_rx_mem_buffer for all the queues
|
||||
* @global_table: table mapping received VID from hw to rxb
|
||||
* @rba: allocator for RX replenishing
|
||||
* @ctxt_info: context information for FW self init
|
||||
* @ctxt_info_dma_addr: dma addr of context information
|
||||
* @init_dram: DRAM data of firmware image (including paging).
|
||||
* Context information addresses will be taken from here.
|
||||
* This is driver's local copy for keeping track of size and
|
||||
* count for allocating and freeing the memory.
|
||||
* @trans: pointer to the generic transport area
|
||||
* @scd_base_addr: scheduler sram base address in SRAM
|
||||
* @scd_bc_tbls: pointer to the byte count table of the scheduler
|
||||
|
@ -357,6 +387,9 @@ struct iwl_trans_pcie {
|
|||
struct iwl_rx_mem_buffer rx_pool[RX_POOL_SIZE];
|
||||
struct iwl_rx_mem_buffer *global_table[RX_POOL_SIZE];
|
||||
struct iwl_rb_allocator rba;
|
||||
struct iwl_context_info *ctxt_info;
|
||||
dma_addr_t ctxt_info_dma_addr;
|
||||
struct iwl_self_init_dram init_dram;
|
||||
struct iwl_trans *trans;
|
||||
|
||||
struct net_device napi_dev;
|
||||
|
@ -454,6 +487,7 @@ void iwl_trans_pcie_free(struct iwl_trans *trans);
|
|||
* RX
|
||||
******************************************************/
|
||||
int iwl_pcie_rx_init(struct iwl_trans *trans);
|
||||
int iwl_pcie_gen2_rx_init(struct iwl_trans *trans);
|
||||
irqreturn_t iwl_pcie_msix_isr(int irq, void *data);
|
||||
irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id);
|
||||
irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id);
|
||||
|
@ -474,6 +508,7 @@ void iwl_pcie_disable_ict(struct iwl_trans *trans);
|
|||
* TX / HCMD
|
||||
******************************************************/
|
||||
int iwl_pcie_tx_init(struct iwl_trans *trans);
|
||||
int iwl_pcie_gen2_tx_init(struct iwl_trans *trans);
|
||||
void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr);
|
||||
int iwl_pcie_tx_stop(struct iwl_trans *trans);
|
||||
void iwl_pcie_tx_free(struct iwl_trans *trans);
|
||||
|
@ -484,7 +519,6 @@ void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int queue,
|
|||
bool configure_scd);
|
||||
void iwl_trans_pcie_txq_set_shared_mode(struct iwl_trans *trans, u32 txq_id,
|
||||
bool shared_mode);
|
||||
dma_addr_t iwl_trans_pcie_get_txq_byte_table(struct iwl_trans *trans, int txq);
|
||||
void iwl_trans_pcie_log_scd_error(struct iwl_trans *trans,
|
||||
struct iwl_txq *txq);
|
||||
int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
|
||||
|
@ -719,4 +753,15 @@ int iwl_pci_fw_enter_d0i3(struct iwl_trans *trans);
|
|||
|
||||
void iwl_pcie_enable_rx_wake(struct iwl_trans *trans, bool enable);
|
||||
|
||||
/* common functions that are used by gen2 transport */
|
||||
void iwl_pcie_apm_config(struct iwl_trans *trans);
|
||||
int iwl_pcie_prepare_card_hw(struct iwl_trans *trans);
|
||||
void iwl_pcie_synchronize_irqs(struct iwl_trans *trans);
|
||||
bool iwl_trans_check_hw_rf_kill(struct iwl_trans *trans);
|
||||
|
||||
/* transport gen 2 exported functions */
|
||||
int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans,
|
||||
const struct fw_img *fw, bool run_in_rfkill);
|
||||
void iwl_trans_pcie_gen2_fw_alive(struct iwl_trans *trans, u32 scd_addr);
|
||||
|
||||
#endif /* __iwl_trans_int_pcie_h__ */
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
*
|
||||
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 Intel Deutschland GmbH
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
*
|
||||
* Portions of this file are derived from the ipw3945 project, as well
|
||||
* as portions of the ieee80211 subsystem header files.
|
||||
|
@ -880,7 +880,7 @@ static int iwl_pcie_dummy_napi_poll(struct napi_struct *napi, int budget)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int iwl_pcie_rx_init(struct iwl_trans *trans)
|
||||
static int _iwl_pcie_rx_init(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
struct iwl_rxq *def_rxq;
|
||||
|
@ -958,20 +958,40 @@ int iwl_pcie_rx_init(struct iwl_trans *trans)
|
|||
|
||||
iwl_pcie_rxq_alloc_rbs(trans, GFP_KERNEL, def_rxq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwl_pcie_rx_init(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
int ret = _iwl_pcie_rx_init(trans);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (trans->cfg->mq_rx_supported)
|
||||
iwl_pcie_rx_mq_hw_init(trans);
|
||||
else
|
||||
iwl_pcie_rx_hw_init(trans, def_rxq);
|
||||
iwl_pcie_rx_hw_init(trans, trans_pcie->rxq);
|
||||
|
||||
iwl_pcie_rxq_restock(trans, def_rxq);
|
||||
iwl_pcie_rxq_restock(trans, trans_pcie->rxq);
|
||||
|
||||
spin_lock(&def_rxq->lock);
|
||||
iwl_pcie_rxq_inc_wr_ptr(trans, def_rxq);
|
||||
spin_unlock(&def_rxq->lock);
|
||||
spin_lock(&trans_pcie->rxq->lock);
|
||||
iwl_pcie_rxq_inc_wr_ptr(trans, trans_pcie->rxq);
|
||||
spin_unlock(&trans_pcie->rxq->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwl_pcie_gen2_rx_init(struct iwl_trans *trans)
|
||||
{
|
||||
/*
|
||||
* We don't configure the RFH.
|
||||
* Restock will be done at alive, after firmware configured the RFH.
|
||||
*/
|
||||
return _iwl_pcie_rx_init(trans);
|
||||
}
|
||||
|
||||
void iwl_pcie_rx_free(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
@ -1393,9 +1413,6 @@ static void iwl_pcie_irq_handle_error(struct iwl_trans *trans)
|
|||
return;
|
||||
}
|
||||
|
||||
iwl_pcie_dump_csr(trans);
|
||||
iwl_dump_fh(trans, NULL);
|
||||
|
||||
local_bh_disable();
|
||||
/* The STATUS_FW_ERROR bit is set in this function. This must happen
|
||||
* before we wake up the command caller, to ensure a proper cleanup. */
|
||||
|
@ -1597,6 +1614,13 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
|
|||
if (inta & CSR_INT_BIT_ALIVE) {
|
||||
IWL_DEBUG_ISR(trans, "Alive interrupt\n");
|
||||
isr_stats->alive++;
|
||||
if (trans->cfg->gen2) {
|
||||
/*
|
||||
* We can restock, since firmware configured
|
||||
* the RFH
|
||||
*/
|
||||
iwl_pcie_rxmq_restock(trans, trans_pcie->rxq);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1933,6 +1957,10 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
|
|||
if (inta_hw & MSIX_HW_INT_CAUSES_REG_ALIVE) {
|
||||
IWL_DEBUG_ISR(trans, "Alive interrupt\n");
|
||||
isr_stats->alive++;
|
||||
if (trans->cfg->gen2) {
|
||||
/* We can restock, since firmware configured the RFH */
|
||||
iwl_pcie_rxmq_restock(trans, trans_pcie->rxq);
|
||||
}
|
||||
}
|
||||
|
||||
/* uCode wakes up after power-down sleep */
|
||||
|
|
|
@ -0,0 +1,226 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2017 Intel Deutschland GmbH
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2017 Intel Deutschland GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-context-info.h"
|
||||
#include "internal.h"
|
||||
|
||||
/*
|
||||
* Start up NIC's basic functionality after it has been reset
|
||||
* (e.g. after platform boot, or shutdown via iwl_pcie_apm_stop())
|
||||
* NOTE: This does not load uCode nor start the embedded processor
|
||||
*/
|
||||
static int iwl_pcie_gen2_apm_init(struct iwl_trans *trans)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
IWL_DEBUG_INFO(trans, "Init card's basic functions\n");
|
||||
|
||||
/*
|
||||
* Use "set_bit" below rather than "write", to preserve any hardware
|
||||
* bits already set by default after reset.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Disable L0s without affecting L1;
|
||||
* don't wait for ICH L0s (ICH bug W/A)
|
||||
*/
|
||||
iwl_set_bit(trans, CSR_GIO_CHICKEN_BITS,
|
||||
CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX);
|
||||
|
||||
/* Set FH wait threshold to maximum (HW error during stress W/A) */
|
||||
iwl_set_bit(trans, CSR_DBG_HPET_MEM_REG, CSR_DBG_HPET_MEM_REG_VAL);
|
||||
|
||||
/*
|
||||
* Enable HAP INTA (interrupt from management bus) to
|
||||
* wake device's PCI Express link L1a -> L0s
|
||||
*/
|
||||
iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A);
|
||||
|
||||
iwl_pcie_apm_config(trans);
|
||||
|
||||
/*
|
||||
* Set "initialization complete" bit to move adapter from
|
||||
* D0U* --> D0A* (powered-up active) state.
|
||||
*/
|
||||
iwl_set_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
|
||||
|
||||
/*
|
||||
* Wait for clock stabilization; once stabilized, access to
|
||||
* device-internal resources is supported, e.g. iwl_write_prph()
|
||||
* and accesses to uCode SRAM.
|
||||
*/
|
||||
ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
|
||||
if (ret < 0) {
|
||||
IWL_DEBUG_INFO(trans, "Failed to init the card\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
set_bit(STATUS_DEVICE_ENABLED, &trans->status);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_pcie_gen2_nic_init(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
||||
/* TODO: most of the logic can be removed in A0 - but not in Z0 */
|
||||
spin_lock(&trans_pcie->irq_lock);
|
||||
iwl_pcie_gen2_apm_init(trans);
|
||||
spin_unlock(&trans_pcie->irq_lock);
|
||||
|
||||
iwl_op_mode_nic_config(trans->op_mode);
|
||||
|
||||
/* Allocate the RX queue, or reset if it is already allocated */
|
||||
if (iwl_pcie_gen2_rx_init(trans))
|
||||
return -ENOMEM;
|
||||
|
||||
/* Allocate or reset and init all Tx and Command queues */
|
||||
if (iwl_pcie_gen2_tx_init(trans))
|
||||
return -ENOMEM;
|
||||
|
||||
/* enable shadow regs in HW */
|
||||
iwl_set_bit(trans, CSR_MAC_SHADOW_REG_CTRL, 0x800FFFFF);
|
||||
IWL_DEBUG_INFO(trans, "Enabling shadow registers in device\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void iwl_trans_pcie_gen2_fw_alive(struct iwl_trans *trans, u32 scd_addr)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
||||
iwl_pcie_reset_ict(trans);
|
||||
|
||||
/* make sure all queue are not stopped/used */
|
||||
memset(trans_pcie->queue_stopped, 0, sizeof(trans_pcie->queue_stopped));
|
||||
memset(trans_pcie->queue_used, 0, sizeof(trans_pcie->queue_used));
|
||||
|
||||
/* now that we got alive we can free the fw image & the context info.
|
||||
* paging memory cannot be freed included since FW will still use it
|
||||
*/
|
||||
iwl_pcie_ctxt_info_free(trans);
|
||||
}
|
||||
|
||||
int iwl_trans_pcie_gen2_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);
|
||||
bool hw_rfkill;
|
||||
int ret;
|
||||
|
||||
/* This may fail if AMT took ownership of the device */
|
||||
if (iwl_pcie_prepare_card_hw(trans)) {
|
||||
IWL_WARN(trans, "Exit HW not ready\n");
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
iwl_enable_rfkill_int(trans);
|
||||
|
||||
iwl_write32(trans, CSR_INT, 0xFFFFFFFF);
|
||||
|
||||
/*
|
||||
* We enabled the RF-Kill interrupt and the handler may very
|
||||
* well be running. Disable the interrupts to make sure no other
|
||||
* interrupt can be fired.
|
||||
*/
|
||||
iwl_disable_interrupts(trans);
|
||||
|
||||
/* Make sure it finished running */
|
||||
iwl_pcie_synchronize_irqs(trans);
|
||||
|
||||
mutex_lock(&trans_pcie->mutex);
|
||||
|
||||
/* If platform's RF_KILL switch is NOT set to KILL */
|
||||
hw_rfkill = iwl_trans_check_hw_rf_kill(trans);
|
||||
if (hw_rfkill && !run_in_rfkill) {
|
||||
ret = -ERFKILL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Someone called stop_device, don't try to start_fw */
|
||||
if (trans_pcie->is_down) {
|
||||
IWL_WARN(trans,
|
||||
"Can't start_fw since the HW hasn't been started\n");
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* 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,
|
||||
CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
|
||||
|
||||
/* clear (again), then enable host interrupts */
|
||||
iwl_write32(trans, CSR_INT, 0xFFFFFFFF);
|
||||
|
||||
ret = iwl_pcie_gen2_nic_init(trans);
|
||||
if (ret) {
|
||||
IWL_ERR(trans, "Unable to init nic\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (iwl_pcie_ctxt_info_init(trans, fw))
|
||||
return -ENOMEM;
|
||||
|
||||
/* re-check RF-Kill state since we may have missed the interrupt */
|
||||
hw_rfkill = iwl_trans_check_hw_rf_kill(trans);
|
||||
if (hw_rfkill && !run_in_rfkill)
|
||||
ret = -ERFKILL;
|
||||
|
||||
out:
|
||||
mutex_unlock(&trans_pcie->mutex);
|
||||
return ret;
|
||||
}
|
|
@ -7,7 +7,7 @@
|
|||
*
|
||||
* Copyright(c) 2007 - 2015 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 Intel Deutschland GmbH
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
|
@ -34,7 +34,7 @@
|
|||
*
|
||||
* Copyright(c) 2005 - 2015 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 Intel Deutschland GmbH
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -80,6 +80,7 @@
|
|||
#include "iwl-prph.h"
|
||||
#include "iwl-scd.h"
|
||||
#include "iwl-agn-hw.h"
|
||||
#include "iwl-context-info.h"
|
||||
#include "iwl-fw-error-dump.h"
|
||||
#include "internal.h"
|
||||
#include "iwl-fh.h"
|
||||
|
@ -201,7 +202,7 @@ static void iwl_pcie_set_pwr(struct iwl_trans *trans, bool vaux)
|
|||
/* PCI registers */
|
||||
#define PCI_CFG_RETRY_TIMEOUT 0x041
|
||||
|
||||
static void iwl_pcie_apm_config(struct iwl_trans *trans)
|
||||
void iwl_pcie_apm_config(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
u16 lctl;
|
||||
|
@ -567,7 +568,7 @@ static int iwl_pcie_set_hw_ready(struct iwl_trans *trans)
|
|||
}
|
||||
|
||||
/* Note: returns standard 0/-ERROR code */
|
||||
static int iwl_pcie_prepare_card_hw(struct iwl_trans *trans)
|
||||
int iwl_pcie_prepare_card_hw(struct iwl_trans *trans)
|
||||
{
|
||||
int ret;
|
||||
int t = 0;
|
||||
|
@ -636,29 +637,6 @@ static void iwl_pcie_load_firmware_chunk_fh(struct iwl_trans *trans,
|
|||
FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD);
|
||||
}
|
||||
|
||||
static void iwl_pcie_load_firmware_chunk_tfh(struct iwl_trans *trans,
|
||||
u32 dst_addr, dma_addr_t phy_addr,
|
||||
u32 byte_cnt)
|
||||
{
|
||||
/* Stop DMA channel */
|
||||
iwl_write32(trans, TFH_SRV_DMA_CHNL0_CTRL, 0);
|
||||
|
||||
/* Configure SRAM address */
|
||||
iwl_write32(trans, TFH_SRV_DMA_CHNL0_SRAM_ADDR,
|
||||
dst_addr);
|
||||
|
||||
/* Configure DRAM address - 64 bit */
|
||||
iwl_write64(trans, TFH_SRV_DMA_CHNL0_DRAM_ADDR, phy_addr);
|
||||
|
||||
/* Configure byte count to transfer */
|
||||
iwl_write32(trans, TFH_SRV_DMA_CHNL0_BC, byte_cnt);
|
||||
|
||||
/* Enable the DRAM2SRAM to start */
|
||||
iwl_write32(trans, TFH_SRV_DMA_CHNL0_CTRL, TFH_SRV_DMA_SNOOP |
|
||||
TFH_SRV_DMA_TO_DRIVER |
|
||||
TFH_SRV_DMA_START);
|
||||
}
|
||||
|
||||
static int iwl_pcie_load_firmware_chunk(struct iwl_trans *trans,
|
||||
u32 dst_addr, dma_addr_t phy_addr,
|
||||
u32 byte_cnt)
|
||||
|
@ -672,12 +650,8 @@ static int iwl_pcie_load_firmware_chunk(struct iwl_trans *trans,
|
|||
if (!iwl_trans_grab_nic_access(trans, &flags))
|
||||
return -EIO;
|
||||
|
||||
if (trans->cfg->use_tfh)
|
||||
iwl_pcie_load_firmware_chunk_tfh(trans, dst_addr, phy_addr,
|
||||
byte_cnt);
|
||||
else
|
||||
iwl_pcie_load_firmware_chunk_fh(trans, dst_addr, phy_addr,
|
||||
byte_cnt);
|
||||
iwl_pcie_load_firmware_chunk_fh(trans, dst_addr, phy_addr,
|
||||
byte_cnt);
|
||||
iwl_trans_release_nic_access(trans, &flags);
|
||||
|
||||
ret = wait_event_timeout(trans_pcie->ucode_write_waitq,
|
||||
|
@ -828,15 +802,10 @@ static int iwl_pcie_load_cpu_sections_8000(struct iwl_trans *trans,
|
|||
return ret;
|
||||
|
||||
/* Notify ucode of loaded section number and status */
|
||||
if (trans->cfg->use_tfh) {
|
||||
val = iwl_read_prph(trans, UREG_UCODE_LOAD_STATUS);
|
||||
val = val | (sec_num << shift_param);
|
||||
iwl_write_prph(trans, UREG_UCODE_LOAD_STATUS, val);
|
||||
} else {
|
||||
val = iwl_read_direct32(trans, FH_UCODE_LOAD_STATUS);
|
||||
val = val | (sec_num << shift_param);
|
||||
iwl_write_direct32(trans, FH_UCODE_LOAD_STATUS, val);
|
||||
}
|
||||
val = iwl_read_direct32(trans, FH_UCODE_LOAD_STATUS);
|
||||
val = val | (sec_num << shift_param);
|
||||
iwl_write_direct32(trans, FH_UCODE_LOAD_STATUS, val);
|
||||
|
||||
sec_num = (sec_num << 1) | 0x1;
|
||||
}
|
||||
|
||||
|
@ -1047,6 +1016,16 @@ static int iwl_pcie_load_given_ucode_8000(struct iwl_trans *trans,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
IWL_DEBUG_POWER(trans, "Original WFPM value = 0x%08X\n",
|
||||
iwl_read_prph(trans, WFPM_GP2));
|
||||
|
||||
/*
|
||||
* Set default value. On resume reading the values that were
|
||||
* zeored can provide debug data on the resume flow.
|
||||
* This is for debugging only and has no functional impact.
|
||||
*/
|
||||
iwl_write_prph(trans, WFPM_GP2, 0x01010101);
|
||||
|
||||
/* configure the ucode to be ready to get the secured image */
|
||||
/* release CPU reset */
|
||||
iwl_write_prph(trans, RELEASE_CPU_RESET, RELEASE_CPU_RESET_BIT);
|
||||
|
@ -1062,7 +1041,7 @@ static int iwl_pcie_load_given_ucode_8000(struct iwl_trans *trans,
|
|||
&first_ucode_section);
|
||||
}
|
||||
|
||||
static bool iwl_trans_check_hw_rf_kill(struct iwl_trans *trans)
|
||||
bool iwl_trans_check_hw_rf_kill(struct iwl_trans *trans)
|
||||
{
|
||||
bool hw_rfkill = iwl_is_rfkill_set(trans);
|
||||
|
||||
|
@ -1234,6 +1213,9 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power)
|
|||
}
|
||||
}
|
||||
|
||||
iwl_pcie_ctxt_info_free_paging(trans);
|
||||
iwl_pcie_ctxt_info_free(trans);
|
||||
|
||||
/* Make sure (redundant) we've released our request to stay awake */
|
||||
iwl_clear_bit(trans, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
|
||||
|
@ -1299,7 +1281,7 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power)
|
|||
iwl_pcie_prepare_card_hw(trans);
|
||||
}
|
||||
|
||||
static void iwl_pcie_synchronize_irqs(struct iwl_trans *trans)
|
||||
void iwl_pcie_synchronize_irqs(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
||||
|
@ -1527,6 +1509,9 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
|
|||
}
|
||||
}
|
||||
|
||||
IWL_DEBUG_POWER(trans, "WFPM value upon resume = 0x%08X\n",
|
||||
iwl_read_prph(trans, WFPM_GP2));
|
||||
|
||||
val = iwl_read32(trans, CSR_RESET);
|
||||
if (val & CSR_RESET_REG_FLAG_NEVO_RESET)
|
||||
*status = IWL_D3_STATUS_RESET;
|
||||
|
@ -2075,48 +2060,32 @@ static void iwl_trans_pcie_block_txq_ptrs(struct iwl_trans *trans, bool block)
|
|||
|
||||
void iwl_trans_pcie_log_scd_error(struct iwl_trans *trans, struct iwl_txq *txq)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
u32 scd_sram_addr;
|
||||
u8 buf[16];
|
||||
int cnt;
|
||||
u32 txq_id = txq->id;
|
||||
u32 status;
|
||||
bool active;
|
||||
u8 fifo;
|
||||
|
||||
IWL_ERR(trans, "Current SW read_ptr %d write_ptr %d\n",
|
||||
txq->read_ptr, txq->write_ptr);
|
||||
|
||||
if (trans->cfg->use_tfh)
|
||||
if (trans->cfg->use_tfh) {
|
||||
IWL_ERR(trans, "Queue %d is stuck %d %d\n", txq_id,
|
||||
txq->read_ptr, txq->write_ptr);
|
||||
/* TODO: access new SCD registers and dump them */
|
||||
return;
|
||||
|
||||
scd_sram_addr = trans_pcie->scd_base_addr +
|
||||
SCD_TX_STTS_QUEUE_OFFSET(txq->id);
|
||||
iwl_trans_read_mem_bytes(trans, scd_sram_addr, buf, sizeof(buf));
|
||||
|
||||
iwl_print_hex_error(trans, buf, sizeof(buf));
|
||||
|
||||
for (cnt = 0; cnt < FH_TCSR_CHNL_NUM; cnt++)
|
||||
IWL_ERR(trans, "FH TRBs(%d) = 0x%08x\n", cnt,
|
||||
iwl_read_direct32(trans, FH_TX_TRB_REG(cnt)));
|
||||
|
||||
for (cnt = 0; cnt < trans->cfg->base_params->num_of_queues; cnt++) {
|
||||
u32 status = iwl_read_prph(trans, SCD_QUEUE_STATUS_BITS(cnt));
|
||||
u8 fifo = (status >> SCD_QUEUE_STTS_REG_POS_TXF) & 0x7;
|
||||
bool active = !!(status & BIT(SCD_QUEUE_STTS_REG_POS_ACTIVE));
|
||||
u32 tbl_dw =
|
||||
iwl_trans_read_mem32(trans, trans_pcie->scd_base_addr +
|
||||
SCD_TRANS_TBL_OFFSET_QUEUE(cnt));
|
||||
|
||||
if (cnt & 0x1)
|
||||
tbl_dw = (tbl_dw & 0xFFFF0000) >> 16;
|
||||
else
|
||||
tbl_dw = tbl_dw & 0x0000FFFF;
|
||||
|
||||
IWL_ERR(trans,
|
||||
"Q %d is %sactive and mapped to fifo %d ra_tid 0x%04x [%d,%d]\n",
|
||||
cnt, active ? "" : "in", fifo, tbl_dw,
|
||||
iwl_read_prph(trans, SCD_QUEUE_RDPTR(cnt)) &
|
||||
(TFD_QUEUE_SIZE_MAX - 1),
|
||||
iwl_read_prph(trans, SCD_QUEUE_WRPTR(cnt)));
|
||||
}
|
||||
|
||||
status = iwl_read_prph(trans, SCD_QUEUE_STATUS_BITS(txq_id));
|
||||
fifo = (status >> SCD_QUEUE_STTS_REG_POS_TXF) & 0x7;
|
||||
active = !!(status & BIT(SCD_QUEUE_STTS_REG_POS_ACTIVE));
|
||||
|
||||
IWL_ERR(trans,
|
||||
"Queue %d is %sactive on fifo %d and stuck for %u ms. SW [%d, %d] HW [%d, %d] FH TRB=0x0%x\n",
|
||||
txq_id, active ? "" : "in", fifo,
|
||||
jiffies_to_msecs(txq->wd_timeout),
|
||||
txq->read_ptr, txq->write_ptr,
|
||||
iwl_read_prph(trans, SCD_QUEUE_RDPTR(txq_id)) &
|
||||
(TFD_QUEUE_SIZE_MAX - 1),
|
||||
iwl_read_prph(trans, SCD_QUEUE_WRPTR(txq_id)) &
|
||||
(TFD_QUEUE_SIZE_MAX - 1),
|
||||
iwl_read_direct32(trans, FH_TX_TRB_REG(fifo)));
|
||||
}
|
||||
|
||||
static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans, u32 txq_bm)
|
||||
|
@ -2890,21 +2859,43 @@ static void iwl_trans_pcie_resume(struct iwl_trans *trans)
|
|||
}
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
#define IWL_TRANS_COMMON_OPS \
|
||||
.op_mode_leave = iwl_trans_pcie_op_mode_leave, \
|
||||
.write8 = iwl_trans_pcie_write8, \
|
||||
.write32 = iwl_trans_pcie_write32, \
|
||||
.read32 = iwl_trans_pcie_read32, \
|
||||
.read_prph = iwl_trans_pcie_read_prph, \
|
||||
.write_prph = iwl_trans_pcie_write_prph, \
|
||||
.read_mem = iwl_trans_pcie_read_mem, \
|
||||
.write_mem = iwl_trans_pcie_write_mem, \
|
||||
.configure = iwl_trans_pcie_configure, \
|
||||
.set_pmi = iwl_trans_pcie_set_pmi, \
|
||||
.grab_nic_access = iwl_trans_pcie_grab_nic_access, \
|
||||
.release_nic_access = iwl_trans_pcie_release_nic_access, \
|
||||
.set_bits_mask = iwl_trans_pcie_set_bits_mask, \
|
||||
.ref = iwl_trans_pcie_ref, \
|
||||
.unref = iwl_trans_pcie_unref, \
|
||||
.dump_data = iwl_trans_pcie_dump_data, \
|
||||
.wait_tx_queue_empty = iwl_trans_pcie_wait_txq_empty, \
|
||||
.d3_suspend = iwl_trans_pcie_d3_suspend, \
|
||||
.d3_resume = iwl_trans_pcie_d3_resume
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
#define IWL_TRANS_PM_OPS \
|
||||
.suspend = iwl_trans_pcie_suspend, \
|
||||
.resume = iwl_trans_pcie_resume,
|
||||
#else
|
||||
#define IWL_TRANS_PM_OPS
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
static const struct iwl_trans_ops trans_ops_pcie = {
|
||||
IWL_TRANS_COMMON_OPS,
|
||||
IWL_TRANS_PM_OPS
|
||||
.start_hw = iwl_trans_pcie_start_hw,
|
||||
.op_mode_leave = iwl_trans_pcie_op_mode_leave,
|
||||
.fw_alive = iwl_trans_pcie_fw_alive,
|
||||
.start_fw = iwl_trans_pcie_start_fw,
|
||||
.stop_device = iwl_trans_pcie_stop_device,
|
||||
|
||||
.d3_suspend = iwl_trans_pcie_d3_suspend,
|
||||
.d3_resume = iwl_trans_pcie_d3_resume,
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
.suspend = iwl_trans_pcie_suspend,
|
||||
.resume = iwl_trans_pcie_resume,
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
.send_cmd = iwl_trans_pcie_send_hcmd,
|
||||
|
||||
.tx = iwl_trans_pcie_tx,
|
||||
|
@ -2913,31 +2904,32 @@ static const struct iwl_trans_ops trans_ops_pcie = {
|
|||
.txq_disable = iwl_trans_pcie_txq_disable,
|
||||
.txq_enable = iwl_trans_pcie_txq_enable,
|
||||
|
||||
.get_txq_byte_table = iwl_trans_pcie_get_txq_byte_table,
|
||||
.txq_set_shared_mode = iwl_trans_pcie_txq_set_shared_mode,
|
||||
|
||||
.freeze_txq_timer = iwl_trans_pcie_freeze_txq_timer,
|
||||
.block_txq_ptrs = iwl_trans_pcie_block_txq_ptrs,
|
||||
};
|
||||
|
||||
static const struct iwl_trans_ops trans_ops_pcie_gen2 = {
|
||||
IWL_TRANS_COMMON_OPS,
|
||||
IWL_TRANS_PM_OPS
|
||||
.start_hw = iwl_trans_pcie_start_hw,
|
||||
.fw_alive = iwl_trans_pcie_gen2_fw_alive,
|
||||
.start_fw = iwl_trans_pcie_gen2_start_fw,
|
||||
.stop_device = iwl_trans_pcie_stop_device,
|
||||
|
||||
.send_cmd = iwl_trans_pcie_send_hcmd,
|
||||
|
||||
.tx = iwl_trans_pcie_tx,
|
||||
.reclaim = iwl_trans_pcie_reclaim,
|
||||
|
||||
.txq_disable = iwl_trans_pcie_txq_disable,
|
||||
.txq_enable = iwl_trans_pcie_txq_enable,
|
||||
|
||||
.txq_set_shared_mode = iwl_trans_pcie_txq_set_shared_mode,
|
||||
|
||||
.wait_tx_queue_empty = iwl_trans_pcie_wait_txq_empty,
|
||||
.freeze_txq_timer = iwl_trans_pcie_freeze_txq_timer,
|
||||
.block_txq_ptrs = iwl_trans_pcie_block_txq_ptrs,
|
||||
|
||||
.write8 = iwl_trans_pcie_write8,
|
||||
.write32 = iwl_trans_pcie_write32,
|
||||
.read32 = iwl_trans_pcie_read32,
|
||||
.read_prph = iwl_trans_pcie_read_prph,
|
||||
.write_prph = iwl_trans_pcie_write_prph,
|
||||
.read_mem = iwl_trans_pcie_read_mem,
|
||||
.write_mem = iwl_trans_pcie_write_mem,
|
||||
.configure = iwl_trans_pcie_configure,
|
||||
.set_pmi = iwl_trans_pcie_set_pmi,
|
||||
.grab_nic_access = iwl_trans_pcie_grab_nic_access,
|
||||
.release_nic_access = iwl_trans_pcie_release_nic_access,
|
||||
.set_bits_mask = iwl_trans_pcie_set_bits_mask,
|
||||
|
||||
.ref = iwl_trans_pcie_ref,
|
||||
.unref = iwl_trans_pcie_unref,
|
||||
|
||||
.dump_data = iwl_trans_pcie_dump_data,
|
||||
};
|
||||
|
||||
struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
||||
|
@ -2952,8 +2944,12 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
|||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
trans = iwl_trans_alloc(sizeof(struct iwl_trans_pcie),
|
||||
&pdev->dev, cfg, &trans_ops_pcie, 0);
|
||||
if (cfg->gen2)
|
||||
trans = iwl_trans_alloc(sizeof(struct iwl_trans_pcie),
|
||||
&pdev->dev, cfg, &trans_ops_pcie_gen2);
|
||||
else
|
||||
trans = iwl_trans_alloc(sizeof(struct iwl_trans_pcie),
|
||||
&pdev->dev, cfg, &trans_ops_pcie);
|
||||
if (!trans)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
*
|
||||
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 Intel Deutschland GmbH
|
||||
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
|
||||
*
|
||||
* Portions of this file are derived from the ipw3945 project, as well
|
||||
* as portions of the ieee80211 subsystem header files.
|
||||
|
@ -164,9 +164,6 @@ static void iwl_pcie_txq_stuck_timer(unsigned long data)
|
|||
}
|
||||
spin_unlock(&txq->lock);
|
||||
|
||||
IWL_ERR(trans, "Queue %d stuck for %u ms.\n", txq->id,
|
||||
jiffies_to_msecs(txq->wd_timeout));
|
||||
|
||||
iwl_trans_pcie_log_scd_error(trans, txq);
|
||||
|
||||
iwl_force_nmi(trans);
|
||||
|
@ -383,8 +380,7 @@ static inline void iwl_pcie_tfd_set_tb(struct iwl_trans *trans, void *tfd,
|
|||
u16 hi_n_len = len << 4;
|
||||
|
||||
put_unaligned_le32(addr, &tb->lo);
|
||||
if (sizeof(dma_addr_t) > sizeof(u32))
|
||||
hi_n_len |= ((addr >> 16) >> 16) & 0xF;
|
||||
hi_n_len |= iwl_get_dma_hi_addr(addr);
|
||||
|
||||
tb->hi_n_len = cpu_to_le16(hi_n_len);
|
||||
|
||||
|
@ -616,18 +612,6 @@ static int iwl_pcie_txq_init(struct iwl_trans *trans, struct iwl_txq *txq,
|
|||
|
||||
__skb_queue_head_init(&txq->overflow_q);
|
||||
|
||||
/*
|
||||
* Tell nic where to find circular buffer of Tx Frame Descriptors for
|
||||
* given Tx queue, and enable the DMA channel used for that queue.
|
||||
* Circular buffer (TFD queue in DRAM) physical base address */
|
||||
if (trans->cfg->use_tfh)
|
||||
iwl_write_direct64(trans,
|
||||
FH_MEM_CBBC_QUEUE(trans, txq_id),
|
||||
txq->dma_addr);
|
||||
else
|
||||
iwl_write_direct32(trans, FH_MEM_CBBC_QUEUE(trans, txq_id),
|
||||
txq->dma_addr >> 8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -704,7 +688,6 @@ static void iwl_pcie_txq_unmap(struct iwl_trans *trans, int txq_id)
|
|||
spin_unlock_irqrestore(&trans_pcie->reg_lock, flags);
|
||||
}
|
||||
}
|
||||
txq->active = false;
|
||||
|
||||
while (!skb_queue_empty(&txq->overflow_q)) {
|
||||
struct sk_buff *skb = __skb_dequeue(&txq->overflow_q);
|
||||
|
@ -780,9 +763,6 @@ void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr)
|
|||
memset(trans_pcie->queue_stopped, 0, sizeof(trans_pcie->queue_stopped));
|
||||
memset(trans_pcie->queue_used, 0, sizeof(trans_pcie->queue_used));
|
||||
|
||||
if (trans->cfg->use_tfh)
|
||||
return;
|
||||
|
||||
trans_pcie->scd_base_addr =
|
||||
iwl_read_prph(trans, SCD_SRAM_BASE_ADDR);
|
||||
|
||||
|
@ -935,6 +915,8 @@ void iwl_pcie_tx_free(struct iwl_trans *trans)
|
|||
int txq_id;
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
||||
memset(trans_pcie->queue_used, 0, sizeof(trans_pcie->queue_used));
|
||||
|
||||
/* Tx queues */
|
||||
if (trans_pcie->txq) {
|
||||
for (txq_id = 0;
|
||||
|
@ -1012,6 +994,7 @@ static int iwl_pcie_tx_alloc(struct iwl_trans *trans)
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_pcie_tx_init(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
@ -1048,14 +1031,15 @@ int iwl_pcie_tx_init(struct iwl_trans *trans)
|
|||
IWL_ERR(trans, "Tx %d queue init failed\n", txq_id);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if (trans->cfg->use_tfh) {
|
||||
iwl_write_direct32(trans, TFH_TRANSFER_MODE,
|
||||
TFH_TRANSFER_MAX_PENDING_REQ |
|
||||
TFH_CHUNK_SIZE_128 |
|
||||
TFH_CHUNK_SPLIT_MODE);
|
||||
return 0;
|
||||
/*
|
||||
* Tell nic where to find circular buffer of TFDs for a
|
||||
* given Tx queue, and enable the DMA channel used for that
|
||||
* queue.
|
||||
* Circular buffer (TFD queue in DRAM) physical base address
|
||||
*/
|
||||
iwl_write_direct32(trans, FH_MEM_CBBC_QUEUE(trans, txq_id),
|
||||
trans_pcie->txq[txq_id].dma_addr >> 8);
|
||||
}
|
||||
|
||||
iwl_set_bits_prph(trans, SCD_GP_CTRL, SCD_GP_CTRL_AUTO_ACTIVE_MODE);
|
||||
|
@ -1071,6 +1055,51 @@ int iwl_pcie_tx_init(struct iwl_trans *trans)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int iwl_pcie_gen2_tx_init(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
int ret;
|
||||
int txq_id, slots_num;
|
||||
bool alloc = false;
|
||||
|
||||
if (!trans_pcie->txq) {
|
||||
/* TODO: change this when moving to new TX alloc model */
|
||||
ret = iwl_pcie_tx_alloc(trans);
|
||||
if (ret)
|
||||
goto error;
|
||||
alloc = true;
|
||||
}
|
||||
|
||||
spin_lock(&trans_pcie->irq_lock);
|
||||
|
||||
/* Tell NIC where to find the "keep warm" buffer */
|
||||
iwl_write_direct32(trans, FH_KW_MEM_ADDR_REG,
|
||||
trans_pcie->kw.dma >> 4);
|
||||
|
||||
spin_unlock(&trans_pcie->irq_lock);
|
||||
|
||||
/* TODO: remove this when moving to new TX alloc model */
|
||||
for (txq_id = 0; txq_id < trans->cfg->base_params->num_of_queues;
|
||||
txq_id++) {
|
||||
slots_num = (txq_id == trans_pcie->cmd_queue) ?
|
||||
TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
|
||||
ret = iwl_pcie_txq_init(trans, &trans_pcie->txq[txq_id],
|
||||
slots_num, txq_id);
|
||||
if (ret) {
|
||||
IWL_ERR(trans, "Tx %d queue init failed\n", txq_id);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
/* Upon error, free only if we allocated something */
|
||||
if (alloc)
|
||||
iwl_pcie_tx_free(trans);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void iwl_pcie_txq_progress(struct iwl_txq *txq)
|
||||
{
|
||||
lockdep_assert_held(&txq->lock);
|
||||
|
@ -1110,7 +1139,7 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
|
|||
|
||||
spin_lock_bh(&txq->lock);
|
||||
|
||||
if (!txq->active) {
|
||||
if (!test_bit(txq_id, trans_pcie->queue_used)) {
|
||||
IWL_DEBUG_TX_QUEUES(trans, "Q %d inactive - ignoring idx %d\n",
|
||||
txq_id, ssn);
|
||||
goto out;
|
||||
|
@ -1414,8 +1443,6 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, u16 ssn,
|
|||
"Activate queue %d WrPtr: %d\n",
|
||||
txq_id, ssn & 0xff);
|
||||
}
|
||||
|
||||
txq->active = true;
|
||||
}
|
||||
|
||||
void iwl_trans_pcie_txq_set_shared_mode(struct iwl_trans *trans, u32 txq_id,
|
||||
|
@ -1427,14 +1454,6 @@ void iwl_trans_pcie_txq_set_shared_mode(struct iwl_trans *trans, u32 txq_id,
|
|||
txq->ampdu = !shared_mode;
|
||||
}
|
||||
|
||||
dma_addr_t iwl_trans_pcie_get_txq_byte_table(struct iwl_trans *trans, int txq)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
||||
return trans_pcie->scd_bc_tbls.dma +
|
||||
txq * sizeof(struct iwlagn_scd_bc_tbl);
|
||||
}
|
||||
|
||||
void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id,
|
||||
bool configure_scd)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue