forked from Minki/linux
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next
This commit is contained in:
commit
cd309ab393
@ -6,7 +6,6 @@ config IWLWIFI
|
||||
select LEDS_CLASS
|
||||
select LEDS_TRIGGERS
|
||||
select MAC80211_LEDS
|
||||
select IWLDVM
|
||||
---help---
|
||||
Select to build the driver supporting the:
|
||||
|
||||
@ -45,6 +44,7 @@ config IWLWIFI
|
||||
config IWLDVM
|
||||
tristate "Intel Wireless WiFi DVM Firmware support"
|
||||
depends on IWLWIFI
|
||||
default IWLWIFI
|
||||
help
|
||||
This is the driver supporting the DVM firmware which is
|
||||
currently the only firmware available for existing devices.
|
||||
@ -58,6 +58,15 @@ config IWLMVM
|
||||
|
||||
Say yes if you have such a device.
|
||||
|
||||
# don't call it _MODULE -- will confuse Kconfig/fixdep/...
|
||||
config IWLWIFI_OPMODE_MODULAR
|
||||
bool
|
||||
default y if IWLDVM=m
|
||||
default y if IWLMVM=m
|
||||
|
||||
comment "WARNING: iwlwifi is useless without IWLDVM or IWLMVM"
|
||||
depends on IWLWIFI && IWLDVM=n && IWLMVM=n
|
||||
|
||||
menu "Debugging Options"
|
||||
depends on IWLWIFI
|
||||
|
||||
|
@ -7,8 +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/1000.o pcie/2000.o pcie/5000.o pcie/6000.o
|
||||
iwlwifi-objs += pcie/7000.o
|
||||
iwlwifi-objs += iwl-1000.o iwl-2000.o iwl-5000.o iwl-6000.o iwl-7000.o
|
||||
|
||||
iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
|
||||
iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TESTMODE) += iwl-test.o
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
@ -1526,6 +1526,7 @@ struct iwl_compressed_ba_resp {
|
||||
__le16 scd_ssn;
|
||||
u8 txed; /* number of frames sent */
|
||||
u8 txed_2_done; /* number of frames acked */
|
||||
__le16 reserved1;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
|
@ -19,7 +19,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
@ -2324,6 +2324,28 @@ static ssize_t iwl_dbgfs_calib_disabled_write(struct file *file,
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_fw_restart_write(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_priv *priv = file->private_data;
|
||||
bool restart_fw = iwlwifi_mod_params.restart_fw;
|
||||
int ret;
|
||||
|
||||
iwlwifi_mod_params.restart_fw = true;
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
/* take the return value to make compiler happy - it will fail anyway */
|
||||
ret = iwl_dvm_send_cmd_pdu(priv, REPLY_ERROR, CMD_SYNC, 0, NULL);
|
||||
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
iwlwifi_mod_params.restart_fw = restart_fw;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
DEBUGFS_READ_FILE_OPS(ucode_rx_stats);
|
||||
DEBUGFS_READ_FILE_OPS(ucode_tx_stats);
|
||||
DEBUGFS_READ_FILE_OPS(ucode_general_stats);
|
||||
@ -2343,6 +2365,7 @@ DEBUGFS_READ_FILE_OPS(bt_traffic);
|
||||
DEBUGFS_READ_WRITE_FILE_OPS(protection_mode);
|
||||
DEBUGFS_READ_FILE_OPS(reply_tx_error);
|
||||
DEBUGFS_WRITE_FILE_OPS(echo_test);
|
||||
DEBUGFS_WRITE_FILE_OPS(fw_restart);
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
DEBUGFS_READ_WRITE_FILE_OPS(log_event);
|
||||
#endif
|
||||
@ -2400,6 +2423,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, struct dentry *dbgfs_dir)
|
||||
DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR);
|
||||
DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR);
|
||||
DEBUGFS_ADD_FILE(echo_test, dir_debug, S_IWUSR);
|
||||
DEBUGFS_ADD_FILE(fw_restart, dir_debug, S_IWUSR);
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
DEBUGFS_ADD_FILE(log_event, dir_debug, S_IWUSR | S_IRUSR);
|
||||
#endif
|
||||
|
@ -19,7 +19,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
|
@ -19,7 +19,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
|
@ -151,7 +151,7 @@ int iwl_send_add_sta(struct iwl_priv *priv,
|
||||
sta_id, sta->sta.addr, flags & CMD_ASYNC ? "a" : "");
|
||||
|
||||
if (!(flags & CMD_ASYNC)) {
|
||||
cmd.flags |= CMD_WANT_SKB | CMD_WANT_HCMD;
|
||||
cmd.flags |= CMD_WANT_SKB;
|
||||
might_sleep();
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
|
@ -19,7 +19,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
|
@ -19,7 +19,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
|
@ -29,7 +29,6 @@
|
||||
#include "iwl-config.h"
|
||||
#include "iwl-csr.h"
|
||||
#include "iwl-agn-hw.h"
|
||||
#include "cfg.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL1000_UCODE_API_MAX 5
|
@ -28,7 +28,6 @@
|
||||
#include <linux/stringify.h>
|
||||
#include "iwl-config.h"
|
||||
#include "iwl-agn-hw.h"
|
||||
#include "cfg.h"
|
||||
#include "dvm/commands.h" /* needed for BT for now */
|
||||
|
||||
/* Highest firmware API version supported */
|
@ -29,7 +29,6 @@
|
||||
#include "iwl-config.h"
|
||||
#include "iwl-agn-hw.h"
|
||||
#include "iwl-csr.h"
|
||||
#include "cfg.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL5000_UCODE_API_MAX 5
|
@ -28,7 +28,6 @@
|
||||
#include <linux/stringify.h>
|
||||
#include "iwl-config.h"
|
||||
#include "iwl-agn-hw.h"
|
||||
#include "cfg.h"
|
||||
#include "dvm/commands.h" /* needed for BT for now */
|
||||
|
||||
/* Highest firmware API version supported */
|
@ -1,34 +1,70 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2008 - 2013 Intel Corporation. All rights reserved.
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* 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
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in the
|
||||
* file called LICENSE.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved.
|
||||
* 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 <linux/module.h>
|
||||
#include <linux/stringify.h>
|
||||
#include "iwl-config.h"
|
||||
#include "iwl-agn-hw.h"
|
||||
#include "cfg.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL7260_UCODE_API_MAX 6
|
||||
@ -70,7 +106,6 @@ static const struct iwl_base_params iwl7000_base_params = {
|
||||
};
|
||||
|
||||
static const struct iwl_ht_params iwl7000_ht_params = {
|
||||
.ht_greenfield_support = true,
|
||||
.use_rts_for_aggregation = true, /* use rts/cts protection */
|
||||
.ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ),
|
||||
};
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
@ -275,4 +275,51 @@ struct iwl_cfg {
|
||||
const bool temp_offset_v2;
|
||||
};
|
||||
|
||||
/*
|
||||
* This list declares the config structures for all devices.
|
||||
*/
|
||||
extern const struct iwl_cfg iwl5300_agn_cfg;
|
||||
extern const struct iwl_cfg iwl5100_agn_cfg;
|
||||
extern const struct iwl_cfg iwl5350_agn_cfg;
|
||||
extern const struct iwl_cfg iwl5100_bgn_cfg;
|
||||
extern const struct iwl_cfg iwl5100_abg_cfg;
|
||||
extern const struct iwl_cfg iwl5150_agn_cfg;
|
||||
extern const struct iwl_cfg iwl5150_abg_cfg;
|
||||
extern const struct iwl_cfg iwl6005_2agn_cfg;
|
||||
extern const struct iwl_cfg iwl6005_2abg_cfg;
|
||||
extern const struct iwl_cfg iwl6005_2bg_cfg;
|
||||
extern const struct iwl_cfg iwl6005_2agn_sff_cfg;
|
||||
extern const struct iwl_cfg iwl6005_2agn_d_cfg;
|
||||
extern const struct iwl_cfg iwl6005_2agn_mow1_cfg;
|
||||
extern const struct iwl_cfg iwl6005_2agn_mow2_cfg;
|
||||
extern const struct iwl_cfg iwl1030_bgn_cfg;
|
||||
extern const struct iwl_cfg iwl1030_bg_cfg;
|
||||
extern const struct iwl_cfg iwl6030_2agn_cfg;
|
||||
extern const struct iwl_cfg iwl6030_2abg_cfg;
|
||||
extern const struct iwl_cfg iwl6030_2bgn_cfg;
|
||||
extern const struct iwl_cfg iwl6030_2bg_cfg;
|
||||
extern const struct iwl_cfg iwl6000i_2agn_cfg;
|
||||
extern const struct iwl_cfg iwl6000i_2abg_cfg;
|
||||
extern const struct iwl_cfg iwl6000i_2bg_cfg;
|
||||
extern const struct iwl_cfg iwl6000_3agn_cfg;
|
||||
extern const struct iwl_cfg iwl6050_2agn_cfg;
|
||||
extern const struct iwl_cfg iwl6050_2abg_cfg;
|
||||
extern const struct iwl_cfg iwl6150_bgn_cfg;
|
||||
extern const struct iwl_cfg iwl6150_bg_cfg;
|
||||
extern const struct iwl_cfg iwl1000_bgn_cfg;
|
||||
extern const struct iwl_cfg iwl1000_bg_cfg;
|
||||
extern const struct iwl_cfg iwl100_bgn_cfg;
|
||||
extern const struct iwl_cfg iwl100_bg_cfg;
|
||||
extern const struct iwl_cfg iwl130_bgn_cfg;
|
||||
extern const struct iwl_cfg iwl130_bg_cfg;
|
||||
extern const struct iwl_cfg iwl2000_2bgn_cfg;
|
||||
extern const struct iwl_cfg iwl2000_2bgn_d_cfg;
|
||||
extern const struct iwl_cfg iwl2030_2bgn_cfg;
|
||||
extern const struct iwl_cfg iwl6035_2agn_cfg;
|
||||
extern const struct iwl_cfg iwl105_bgn_cfg;
|
||||
extern const struct iwl_cfg iwl105_bgn_d_cfg;
|
||||
extern const struct iwl_cfg iwl135_bgn_cfg;
|
||||
extern const struct iwl_cfg iwl7260_2ac_cfg;
|
||||
extern const struct iwl_cfg iwl3160_ac_cfg;
|
||||
|
||||
#endif /* __IWL_CONFIG_H__ */
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
@ -66,6 +66,7 @@
|
||||
#include <linux/device.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/export.h>
|
||||
#include "iwl-drv.h"
|
||||
#include "iwl-debug.h"
|
||||
#include "iwl-devtrace.h"
|
||||
|
||||
@ -85,11 +86,11 @@ void __iwl_ ##fn(struct device *dev, const char *fmt, ...) \
|
||||
}
|
||||
|
||||
__iwl_fn(warn)
|
||||
EXPORT_SYMBOL_GPL(__iwl_warn);
|
||||
IWL_EXPORT_SYMBOL(__iwl_warn);
|
||||
__iwl_fn(info)
|
||||
EXPORT_SYMBOL_GPL(__iwl_info);
|
||||
IWL_EXPORT_SYMBOL(__iwl_info);
|
||||
__iwl_fn(crit)
|
||||
EXPORT_SYMBOL_GPL(__iwl_crit);
|
||||
IWL_EXPORT_SYMBOL(__iwl_crit);
|
||||
|
||||
void __iwl_err(struct device *dev, bool rfkill_prefix, bool trace_only,
|
||||
const char *fmt, ...)
|
||||
@ -110,7 +111,7 @@ void __iwl_err(struct device *dev, bool rfkill_prefix, bool trace_only,
|
||||
trace_iwlwifi_err(&vaf);
|
||||
va_end(args);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__iwl_err);
|
||||
IWL_EXPORT_SYMBOL(__iwl_err);
|
||||
|
||||
#if defined(CONFIG_IWLWIFI_DEBUG) || defined(CONFIG_IWLWIFI_DEVICE_TRACING)
|
||||
void __iwl_dbg(struct device *dev,
|
||||
@ -133,5 +134,5 @@ void __iwl_dbg(struct device *dev,
|
||||
trace_iwlwifi_dbg(level, in_interrupt(), function, &vaf);
|
||||
va_end(args);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__iwl_dbg);
|
||||
IWL_EXPORT_SYMBOL(__iwl_dbg);
|
||||
#endif
|
||||
|
@ -298,7 +298,7 @@ TRACE_EVENT(iwlwifi_dbg,
|
||||
MAX_MSG_LEN, vaf->fmt,
|
||||
*vaf->va) >= MAX_MSG_LEN);
|
||||
),
|
||||
TP_printk("%s", (char *)__get_dynamic_array(msg))
|
||||
TP_printk("%s", __get_str(msg))
|
||||
);
|
||||
|
||||
#undef TRACE_SYSTEM
|
||||
@ -349,25 +349,23 @@ TRACE_EVENT(iwlwifi_dev_rx_data,
|
||||
TRACE_EVENT(iwlwifi_dev_hcmd,
|
||||
TP_PROTO(const struct device *dev,
|
||||
struct iwl_host_cmd *cmd, u16 total_size,
|
||||
const void *hdr, size_t hdr_len),
|
||||
TP_ARGS(dev, cmd, total_size, hdr, hdr_len),
|
||||
struct iwl_cmd_header *hdr),
|
||||
TP_ARGS(dev, cmd, total_size, hdr),
|
||||
TP_STRUCT__entry(
|
||||
DEV_ENTRY
|
||||
__dynamic_array(u8, hcmd, total_size)
|
||||
__field(u32, flags)
|
||||
),
|
||||
TP_fast_assign(
|
||||
int i, offset = hdr_len;
|
||||
int i, offset = sizeof(*hdr);
|
||||
|
||||
DEV_ASSIGN;
|
||||
__entry->flags = cmd->flags;
|
||||
memcpy(__get_dynamic_array(hcmd), hdr, hdr_len);
|
||||
memcpy(__get_dynamic_array(hcmd), hdr, sizeof(*hdr));
|
||||
|
||||
for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
|
||||
for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) {
|
||||
if (!cmd->len[i])
|
||||
continue;
|
||||
if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY))
|
||||
continue;
|
||||
memcpy((u8 *)__get_dynamic_array(hcmd) + offset,
|
||||
cmd->data[i], cmd->len[i]);
|
||||
offset += cmd->len[i];
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
@ -1102,8 +1102,7 @@ void iwl_drv_stop(struct iwl_drv *drv)
|
||||
|
||||
/* shared module parameters */
|
||||
struct iwl_mod_params iwlwifi_mod_params = {
|
||||
.amsdu_size_8K = 1,
|
||||
.restart_fw = 1,
|
||||
.restart_fw = true,
|
||||
.plcp_check = true,
|
||||
.bt_coex_active = true,
|
||||
.power_level = IWL_POWER_INDEX_1,
|
||||
@ -1112,7 +1111,7 @@ struct iwl_mod_params iwlwifi_mod_params = {
|
||||
.wd_disable = true,
|
||||
/* the rest are 0 by default */
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(iwlwifi_mod_params);
|
||||
IWL_EXPORT_SYMBOL(iwlwifi_mod_params);
|
||||
|
||||
int iwl_opmode_register(const char *name, const struct iwl_op_mode_ops *ops)
|
||||
{
|
||||
@ -1136,7 +1135,7 @@ int iwl_opmode_register(const char *name, const struct iwl_op_mode_ops *ops)
|
||||
mutex_unlock(&iwlwifi_opmode_table_mtx);
|
||||
return -EIO;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_opmode_register);
|
||||
IWL_EXPORT_SYMBOL(iwl_opmode_register);
|
||||
|
||||
void iwl_opmode_deregister(const char *name)
|
||||
{
|
||||
@ -1158,7 +1157,7 @@ void iwl_opmode_deregister(const char *name)
|
||||
}
|
||||
mutex_unlock(&iwlwifi_opmode_table_mtx);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_opmode_deregister);
|
||||
IWL_EXPORT_SYMBOL(iwl_opmode_deregister);
|
||||
|
||||
static int __init iwl_drv_init(void)
|
||||
{
|
||||
@ -1207,9 +1206,9 @@ MODULE_PARM_DESC(11n_disable,
|
||||
"disable 11n functionality, bitmap: 1: full, 2: agg TX, 4: agg RX");
|
||||
module_param_named(amsdu_size_8K, iwlwifi_mod_params.amsdu_size_8K,
|
||||
int, S_IRUGO);
|
||||
MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size");
|
||||
module_param_named(fw_restart, iwlwifi_mod_params.restart_fw, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(fw_restart, "restart firmware in case of error");
|
||||
MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size (default 0)");
|
||||
module_param_named(fw_restart, iwlwifi_mod_params.restart_fw, bool, S_IRUGO);
|
||||
MODULE_PARM_DESC(fw_restart, "restart firmware in case of error (default true)");
|
||||
|
||||
module_param_named(antenna_coupling, iwlwifi_mod_params.ant_coupling,
|
||||
int, S_IRUGO);
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
@ -63,6 +63,8 @@
|
||||
#ifndef __iwl_drv_h__
|
||||
#define __iwl_drv_h__
|
||||
|
||||
#include <linux/module.h>
|
||||
|
||||
/* for all modules */
|
||||
#define DRV_NAME "iwlwifi"
|
||||
#define IWLWIFI_VERSION "in-tree:"
|
||||
@ -123,4 +125,17 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans,
|
||||
*/
|
||||
void iwl_drv_stop(struct iwl_drv *drv);
|
||||
|
||||
/*
|
||||
* exported symbol management
|
||||
*
|
||||
* The driver can be split into multiple modules, in which case some symbols
|
||||
* must be exported for the sub-modules. However, if it's not split and
|
||||
* everything is built-in, then we can avoid that.
|
||||
*/
|
||||
#ifdef CONFIG_IWLWIFI_OPMODE_MODULAR
|
||||
#define IWL_EXPORT_SYMBOL(sym) EXPORT_SYMBOL_GPL(sym)
|
||||
#else
|
||||
#define IWL_EXPORT_SYMBOL(sym)
|
||||
#endif
|
||||
|
||||
#endif /* __iwl_drv_h__ */
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
@ -62,6 +62,7 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/export.h>
|
||||
#include "iwl-drv.h"
|
||||
#include "iwl-modparams.h"
|
||||
#include "iwl-eeprom-parse.h"
|
||||
|
||||
@ -749,7 +750,7 @@ void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg,
|
||||
}
|
||||
|
||||
ht_info->ht_supported = true;
|
||||
ht_info->cap = 0;
|
||||
ht_info->cap = IEEE80211_HT_CAP_DSSSCCK40;
|
||||
|
||||
if (iwlwifi_mod_params.amsdu_size_8K)
|
||||
ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU;
|
||||
@ -909,7 +910,7 @@ iwl_parse_eeprom_data(struct device *dev, const struct iwl_cfg *cfg,
|
||||
kfree(data);
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_parse_eeprom_data);
|
||||
IWL_EXPORT_SYMBOL(iwl_parse_eeprom_data);
|
||||
|
||||
/* helper functions */
|
||||
int iwl_nvm_check_version(struct iwl_nvm_data *data,
|
||||
@ -928,4 +929,4 @@ int iwl_nvm_check_version(struct iwl_nvm_data *data,
|
||||
data->calib_version, trans->cfg->nvm_calib_ver);
|
||||
return -EINVAL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_nvm_check_version);
|
||||
IWL_EXPORT_SYMBOL(iwl_nvm_check_version);
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
@ -63,6 +63,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/export.h>
|
||||
|
||||
#include "iwl-drv.h"
|
||||
#include "iwl-debug.h"
|
||||
#include "iwl-eeprom-read.h"
|
||||
#include "iwl-io.h"
|
||||
@ -460,4 +461,4 @@ int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size)
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_read_eeprom);
|
||||
IWL_EXPORT_SYMBOL(iwl_read_eeprom);
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
@ -73,12 +73,14 @@
|
||||
* treats good CRC threshold as a boolean
|
||||
* @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w).
|
||||
* @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P.
|
||||
* @IWL_UCODE_TLV_FLAGS_DW_BC_TABLE: The SCD byte count table is in DWORDS
|
||||
*/
|
||||
enum iwl_ucode_tlv_flag {
|
||||
IWL_UCODE_TLV_FLAGS_PAN = BIT(0),
|
||||
IWL_UCODE_TLV_FLAGS_NEWSCAN = BIT(1),
|
||||
IWL_UCODE_TLV_FLAGS_MFP = BIT(2),
|
||||
IWL_UCODE_TLV_FLAGS_P2P = BIT(3),
|
||||
IWL_UCODE_TLV_FLAGS_DW_BC_TABLE = BIT(4),
|
||||
};
|
||||
|
||||
/* The default calibrate table size if not specified by firmware file */
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <linux/device.h>
|
||||
#include <linux/export.h>
|
||||
|
||||
#include "iwl-drv.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-csr.h"
|
||||
#include "iwl-debug.h"
|
||||
@ -49,7 +50,7 @@ int iwl_poll_bit(struct iwl_trans *trans, u32 addr,
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_poll_bit);
|
||||
IWL_EXPORT_SYMBOL(iwl_poll_bit);
|
||||
|
||||
u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg)
|
||||
{
|
||||
@ -62,7 +63,7 @@ u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg)
|
||||
|
||||
return value;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_read_direct32);
|
||||
IWL_EXPORT_SYMBOL(iwl_read_direct32);
|
||||
|
||||
void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value)
|
||||
{
|
||||
@ -73,7 +74,7 @@ void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value)
|
||||
iwl_trans_release_nic_access(trans, &flags);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_write_direct32);
|
||||
IWL_EXPORT_SYMBOL(iwl_write_direct32);
|
||||
|
||||
int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask,
|
||||
int timeout)
|
||||
@ -89,7 +90,7 @@ int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask,
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_poll_direct_bit);
|
||||
IWL_EXPORT_SYMBOL(iwl_poll_direct_bit);
|
||||
|
||||
static inline u32 __iwl_read_prph(struct iwl_trans *trans, u32 ofs)
|
||||
{
|
||||
@ -115,7 +116,7 @@ u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs)
|
||||
}
|
||||
return val;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_read_prph);
|
||||
IWL_EXPORT_SYMBOL(iwl_read_prph);
|
||||
|
||||
void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val)
|
||||
{
|
||||
@ -126,7 +127,7 @@ void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val)
|
||||
iwl_trans_release_nic_access(trans, &flags);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_write_prph);
|
||||
IWL_EXPORT_SYMBOL(iwl_write_prph);
|
||||
|
||||
void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
|
||||
{
|
||||
@ -138,7 +139,7 @@ void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
|
||||
iwl_trans_release_nic_access(trans, &flags);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_set_bits_prph);
|
||||
IWL_EXPORT_SYMBOL(iwl_set_bits_prph);
|
||||
|
||||
void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs,
|
||||
u32 bits, u32 mask)
|
||||
@ -151,7 +152,7 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs,
|
||||
iwl_trans_release_nic_access(trans, &flags);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_set_bits_mask_prph);
|
||||
IWL_EXPORT_SYMBOL(iwl_set_bits_mask_prph);
|
||||
|
||||
void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
|
||||
{
|
||||
@ -164,4 +165,4 @@ void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
|
||||
iwl_trans_release_nic_access(trans, &flags);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_clear_bits_prph);
|
||||
IWL_EXPORT_SYMBOL(iwl_clear_bits_prph);
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
@ -91,7 +91,7 @@ enum iwl_power_level {
|
||||
* @sw_crypto: using hardware encryption, default = 0
|
||||
* @disable_11n: disable 11n capabilities, default = 0,
|
||||
* use IWL_DISABLE_HT_* constants
|
||||
* @amsdu_size_8K: enable 8K amsdu size, default = 1
|
||||
* @amsdu_size_8K: enable 8K amsdu size, default = 0
|
||||
* @restart_fw: restart firmware, default = 1
|
||||
* @plcp_check: enable plcp health check, default = true
|
||||
* @wd_disable: enable stuck queue check, default = 0
|
||||
@ -109,7 +109,7 @@ struct iwl_mod_params {
|
||||
int sw_crypto;
|
||||
unsigned int disable_11n;
|
||||
int amsdu_size_8K;
|
||||
int restart_fw;
|
||||
bool restart_fw;
|
||||
bool plcp_check;
|
||||
int wd_disable;
|
||||
bool bt_coex_active;
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
@ -63,6 +63,7 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/export.h>
|
||||
|
||||
#include "iwl-drv.h"
|
||||
#include "iwl-notif-wait.h"
|
||||
|
||||
|
||||
@ -72,7 +73,7 @@ void iwl_notification_wait_init(struct iwl_notif_wait_data *notif_wait)
|
||||
INIT_LIST_HEAD(¬if_wait->notif_waits);
|
||||
init_waitqueue_head(¬if_wait->notif_waitq);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_notification_wait_init);
|
||||
IWL_EXPORT_SYMBOL(iwl_notification_wait_init);
|
||||
|
||||
void iwl_notification_wait_notify(struct iwl_notif_wait_data *notif_wait,
|
||||
struct iwl_rx_packet *pkt)
|
||||
@ -117,7 +118,7 @@ void iwl_notification_wait_notify(struct iwl_notif_wait_data *notif_wait,
|
||||
if (triggered)
|
||||
wake_up_all(¬if_wait->notif_waitq);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_notification_wait_notify);
|
||||
IWL_EXPORT_SYMBOL(iwl_notification_wait_notify);
|
||||
|
||||
void iwl_abort_notification_waits(struct iwl_notif_wait_data *notif_wait)
|
||||
{
|
||||
@ -130,7 +131,7 @@ void iwl_abort_notification_waits(struct iwl_notif_wait_data *notif_wait)
|
||||
|
||||
wake_up_all(¬if_wait->notif_waitq);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_abort_notification_waits);
|
||||
IWL_EXPORT_SYMBOL(iwl_abort_notification_waits);
|
||||
|
||||
void
|
||||
iwl_init_notification_wait(struct iwl_notif_wait_data *notif_wait,
|
||||
@ -154,7 +155,7 @@ iwl_init_notification_wait(struct iwl_notif_wait_data *notif_wait,
|
||||
list_add(&wait_entry->list, ¬if_wait->notif_waits);
|
||||
spin_unlock_bh(¬if_wait->notif_wait_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_init_notification_wait);
|
||||
IWL_EXPORT_SYMBOL(iwl_init_notification_wait);
|
||||
|
||||
int iwl_wait_notification(struct iwl_notif_wait_data *notif_wait,
|
||||
struct iwl_notification_wait *wait_entry,
|
||||
@ -178,7 +179,7 @@ int iwl_wait_notification(struct iwl_notif_wait_data *notif_wait,
|
||||
return -ETIMEDOUT;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_wait_notification);
|
||||
IWL_EXPORT_SYMBOL(iwl_wait_notification);
|
||||
|
||||
void iwl_remove_notification(struct iwl_notif_wait_data *notif_wait,
|
||||
struct iwl_notification_wait *wait_entry)
|
||||
@ -187,4 +188,4 @@ void iwl_remove_notification(struct iwl_notif_wait_data *notif_wait,
|
||||
list_del(&wait_entry->list);
|
||||
spin_unlock_bh(¬if_wait->notif_wait_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_remove_notification);
|
||||
IWL_EXPORT_SYMBOL(iwl_remove_notification);
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
@ -62,6 +62,7 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/export.h>
|
||||
#include "iwl-drv.h"
|
||||
#include "iwl-modparams.h"
|
||||
#include "iwl-nvm-parse.h"
|
||||
|
||||
@ -149,6 +150,8 @@ static struct ieee80211_rate iwl_cfg80211_rates[] = {
|
||||
* @NVM_CHANNEL_DFS: dynamic freq selection candidate
|
||||
* @NVM_CHANNEL_WIDE: 20 MHz channel okay (?)
|
||||
* @NVM_CHANNEL_40MHZ: 40 MHz channel okay (?)
|
||||
* @NVM_CHANNEL_80MHZ: 80 MHz channel okay (?)
|
||||
* @NVM_CHANNEL_160MHZ: 160 MHz channel okay (?)
|
||||
*/
|
||||
enum iwl_nvm_channel_flags {
|
||||
NVM_CHANNEL_VALID = BIT(0),
|
||||
@ -158,6 +161,8 @@ enum iwl_nvm_channel_flags {
|
||||
NVM_CHANNEL_DFS = BIT(7),
|
||||
NVM_CHANNEL_WIDE = BIT(8),
|
||||
NVM_CHANNEL_40MHZ = BIT(9),
|
||||
NVM_CHANNEL_80MHZ = BIT(10),
|
||||
NVM_CHANNEL_160MHZ = BIT(11),
|
||||
};
|
||||
|
||||
#define CHECK_AND_PRINT_I(x) \
|
||||
@ -210,6 +215,10 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
|
||||
else
|
||||
channel->flags &= ~IEEE80211_CHAN_NO_HT40MINUS;
|
||||
}
|
||||
if (!(ch_flags & NVM_CHANNEL_80MHZ))
|
||||
channel->flags |= IEEE80211_CHAN_NO_80MHZ;
|
||||
if (!(ch_flags & NVM_CHANNEL_160MHZ))
|
||||
channel->flags |= IEEE80211_CHAN_NO_160MHZ;
|
||||
|
||||
if (!(ch_flags & NVM_CHANNEL_IBSS))
|
||||
channel->flags |= IEEE80211_CHAN_NO_IBSS;
|
||||
@ -245,6 +254,43 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
|
||||
return n_channels;
|
||||
}
|
||||
|
||||
static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg,
|
||||
struct iwl_nvm_data *data,
|
||||
struct ieee80211_sta_vht_cap *vht_cap)
|
||||
{
|
||||
/* For now, assume new devices with NVM are VHT capable */
|
||||
|
||||
vht_cap->vht_supported = true;
|
||||
|
||||
vht_cap->cap = IEEE80211_VHT_CAP_SHORT_GI_80 |
|
||||
IEEE80211_VHT_CAP_RXSTBC_1 |
|
||||
IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
|
||||
7 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
|
||||
|
||||
if (iwlwifi_mod_params.amsdu_size_8K)
|
||||
vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991;
|
||||
|
||||
vht_cap->vht_mcs.rx_mcs_map =
|
||||
cpu_to_le16(IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 |
|
||||
IEEE80211_VHT_MCS_SUPPORT_0_9 << 2 |
|
||||
IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 |
|
||||
IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 |
|
||||
IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 |
|
||||
IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 |
|
||||
IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 |
|
||||
IEEE80211_VHT_MCS_NOT_SUPPORTED << 14);
|
||||
|
||||
if (data->valid_rx_ant == 1 || cfg->rx_with_siso_diversity) {
|
||||
vht_cap->cap |= IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN |
|
||||
IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN;
|
||||
/* this works because NOT_SUPPORTED == 3 */
|
||||
vht_cap->vht_mcs.rx_mcs_map |=
|
||||
cpu_to_le16(IEEE80211_VHT_MCS_NOT_SUPPORTED << 2);
|
||||
}
|
||||
|
||||
vht_cap->vht_mcs.tx_mcs_map = vht_cap->vht_mcs.rx_mcs_map;
|
||||
}
|
||||
|
||||
static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
|
||||
struct iwl_nvm_data *data, const __le16 *nvm_sw)
|
||||
{
|
||||
@ -268,6 +314,7 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
|
||||
n_used += iwl_init_sband_channels(data, sband, n_channels,
|
||||
IEEE80211_BAND_5GHZ);
|
||||
iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ);
|
||||
iwl_init_vht_hw_capab(cfg, data, &sband->vht_cap);
|
||||
|
||||
if (n_channels != n_used)
|
||||
IWL_ERR_DEV(dev, "NVM: used only %d of %d channels\n",
|
||||
@ -343,4 +390,4 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
|
||||
|
||||
return data;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_parse_nvm_data);
|
||||
IWL_EXPORT_SYMBOL(iwl_parse_nvm_data);
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
@ -65,6 +65,7 @@
|
||||
#include <linux/string.h>
|
||||
#include <linux/export.h>
|
||||
|
||||
#include "iwl-drv.h"
|
||||
#include "iwl-phy-db.h"
|
||||
#include "iwl-debug.h"
|
||||
#include "iwl-op-mode.h"
|
||||
@ -136,12 +137,6 @@ struct iwl_calib_res_notif_phy_db {
|
||||
u8 data[];
|
||||
} __packed;
|
||||
|
||||
#define IWL_PHY_DB_STATIC_PIC cpu_to_le32(0x21436587)
|
||||
static inline void iwl_phy_db_test_pic(__le32 pic)
|
||||
{
|
||||
WARN_ON(IWL_PHY_DB_STATIC_PIC != pic);
|
||||
}
|
||||
|
||||
struct iwl_phy_db *iwl_phy_db_init(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_phy_db *phy_db = kzalloc(sizeof(struct iwl_phy_db),
|
||||
@ -155,7 +150,7 @@ struct iwl_phy_db *iwl_phy_db_init(struct iwl_trans *trans)
|
||||
/* TODO: add default values of the phy db. */
|
||||
return phy_db;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_phy_db_init);
|
||||
IWL_EXPORT_SYMBOL(iwl_phy_db_init);
|
||||
|
||||
/*
|
||||
* get phy db section: returns a pointer to a phy db section specified by
|
||||
@ -221,7 +216,7 @@ void iwl_phy_db_free(struct iwl_phy_db *phy_db)
|
||||
|
||||
kfree(phy_db);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_phy_db_free);
|
||||
IWL_EXPORT_SYMBOL(iwl_phy_db_free);
|
||||
|
||||
int iwl_phy_db_set_section(struct iwl_phy_db *phy_db, struct iwl_rx_packet *pkt,
|
||||
gfp_t alloc_ctx)
|
||||
@ -260,18 +255,13 @@ int iwl_phy_db_set_section(struct iwl_phy_db *phy_db, struct iwl_rx_packet *pkt,
|
||||
(size - CHANNEL_NUM_SIZE) / phy_db->channel_num;
|
||||
}
|
||||
|
||||
/* Test PIC */
|
||||
if (type != IWL_PHY_DB_CFG)
|
||||
iwl_phy_db_test_pic(*(((__le32 *)phy_db_notif->data) +
|
||||
(size / sizeof(__le32)) - 1));
|
||||
|
||||
IWL_DEBUG_INFO(phy_db->trans,
|
||||
"%s(%d): [PHYDB]SET: Type %d , Size: %d\n",
|
||||
__func__, __LINE__, type, size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_phy_db_set_section);
|
||||
IWL_EXPORT_SYMBOL(iwl_phy_db_set_section);
|
||||
|
||||
static int is_valid_channel(u16 ch_id)
|
||||
{
|
||||
@ -372,11 +362,6 @@ int iwl_phy_db_get_section_data(struct iwl_phy_db *phy_db,
|
||||
*size = entry->size;
|
||||
}
|
||||
|
||||
/* Test PIC */
|
||||
if (type != IWL_PHY_DB_CFG)
|
||||
iwl_phy_db_test_pic(*(((__le32 *)*data) +
|
||||
(*size / sizeof(__le32)) - 1));
|
||||
|
||||
IWL_DEBUG_INFO(phy_db->trans,
|
||||
"%s(%d): [PHYDB] GET: Type %d , Size: %d\n",
|
||||
__func__, __LINE__, type, *size);
|
||||
@ -511,4 +496,4 @@ int iwl_send_phy_db_data(struct iwl_phy_db *phy_db)
|
||||
"Finished sending phy db non channel data\n");
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_send_phy_db_data);
|
||||
IWL_EXPORT_SYMBOL(iwl_send_phy_db_data);
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
@ -64,6 +64,7 @@
|
||||
#include <linux/export.h>
|
||||
#include <net/netlink.h>
|
||||
|
||||
#include "iwl-drv.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-fh.h"
|
||||
#include "iwl-prph.h"
|
||||
@ -653,7 +654,7 @@ int iwl_test_parse(struct iwl_test *tst, struct nlattr **tb,
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_test_parse);
|
||||
IWL_EXPORT_SYMBOL(iwl_test_parse);
|
||||
|
||||
/*
|
||||
* Handle test commands.
|
||||
@ -715,7 +716,7 @@ int iwl_test_handle_cmd(struct iwl_test *tst, struct nlattr **tb)
|
||||
}
|
||||
return result;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_test_handle_cmd);
|
||||
IWL_EXPORT_SYMBOL(iwl_test_handle_cmd);
|
||||
|
||||
static int iwl_test_trace_dump(struct iwl_test *tst, struct sk_buff *skb,
|
||||
struct netlink_callback *cb)
|
||||
@ -803,7 +804,7 @@ int iwl_test_dump(struct iwl_test *tst, u32 cmd, struct sk_buff *skb,
|
||||
}
|
||||
return result;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_test_dump);
|
||||
IWL_EXPORT_SYMBOL(iwl_test_dump);
|
||||
|
||||
/*
|
||||
* Multicast a spontaneous messages from the device to the user space.
|
||||
@ -849,4 +850,4 @@ void iwl_test_rx(struct iwl_test *tst, struct iwl_rx_cmd_buffer *rxb)
|
||||
if (tst->notify)
|
||||
iwl_test_send_rx(tst, rxb);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_test_rx);
|
||||
IWL_EXPORT_SYMBOL(iwl_test_rx);
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
@ -183,19 +183,13 @@ struct iwl_rx_packet {
|
||||
* @CMD_ASYNC: Return right away and don't want for the response
|
||||
* @CMD_WANT_SKB: valid only with CMD_SYNC. The caller needs the buffer of the
|
||||
* response. The caller needs to call iwl_free_resp when done.
|
||||
* @CMD_WANT_HCMD: The caller needs to get the HCMD that was sent in the
|
||||
* response handler. Chunks flagged by %IWL_HCMD_DFL_NOCOPY won't be
|
||||
* copied. The pointer passed to the response handler is in the transport
|
||||
* ownership and don't need to be freed by the op_mode. This also means
|
||||
* that the pointer is invalidated after the op_mode's handler returns.
|
||||
* @CMD_ON_DEMAND: This command is sent by the test mode pipe.
|
||||
*/
|
||||
enum CMD_MODE {
|
||||
CMD_SYNC = 0,
|
||||
CMD_ASYNC = BIT(0),
|
||||
CMD_WANT_SKB = BIT(1),
|
||||
CMD_WANT_HCMD = BIT(2),
|
||||
CMD_ON_DEMAND = BIT(3),
|
||||
CMD_ON_DEMAND = BIT(2),
|
||||
};
|
||||
|
||||
#define DEF_CMD_PAYLOAD_SIZE 320
|
||||
@ -214,7 +208,11 @@ struct iwl_device_cmd {
|
||||
|
||||
#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd))
|
||||
|
||||
#define IWL_MAX_CMD_TFDS 2
|
||||
/*
|
||||
* number of transfer buffers (fragments) per transmit frame descriptor;
|
||||
* this is just the driver's idea, the hardware supports 20
|
||||
*/
|
||||
#define IWL_MAX_CMD_TBS_PER_TFD 2
|
||||
|
||||
/**
|
||||
* struct iwl_hcmd_dataflag - flag for each one of the chunks of the command
|
||||
@ -251,15 +249,15 @@ enum iwl_hcmd_dataflag {
|
||||
* @id: id of the host command
|
||||
*/
|
||||
struct iwl_host_cmd {
|
||||
const void *data[IWL_MAX_CMD_TFDS];
|
||||
const void *data[IWL_MAX_CMD_TBS_PER_TFD];
|
||||
struct iwl_rx_packet *resp_pkt;
|
||||
unsigned long _rx_page_addr;
|
||||
u32 _rx_page_order;
|
||||
int handler_status;
|
||||
|
||||
u32 flags;
|
||||
u16 len[IWL_MAX_CMD_TFDS];
|
||||
u8 dataflags[IWL_MAX_CMD_TFDS];
|
||||
u16 len[IWL_MAX_CMD_TBS_PER_TFD];
|
||||
u8 dataflags[IWL_MAX_CMD_TBS_PER_TFD];
|
||||
u8 id;
|
||||
};
|
||||
|
||||
|
@ -2,7 +2,7 @@ obj-$(CONFIG_IWLMVM) += iwlmvm.o
|
||||
iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o
|
||||
iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o
|
||||
iwlmvm-y += scan.o time-event.o rs.o
|
||||
iwlmvm-y += power.o
|
||||
iwlmvm-y += power.o bt-coex.o
|
||||
iwlmvm-y += led.o
|
||||
iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o
|
||||
iwlmvm-$(CONFIG_PM_SLEEP) += d3.o
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
|
347
drivers/net/wireless/iwlwifi/mvm/bt-coex.c
Normal file
347
drivers/net/wireless/iwlwifi/mvm/bt-coex.c
Normal file
@ -0,0 +1,347 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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) 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2013 Intel Corporation. All rights reserved.
|
||||
* 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 "fw-api-bt-coex.h"
|
||||
#include "iwl-modparams.h"
|
||||
#include "mvm.h"
|
||||
#include "iwl-debug.h"
|
||||
|
||||
#define EVENT_PRIO_ANT(_evt, _prio, _shrd_ant) \
|
||||
[(_evt)] = (((_prio) << BT_COEX_PRIO_TBL_PRIO_POS) | \
|
||||
((_shrd_ant) << BT_COEX_PRIO_TBL_SHRD_ANT_POS))
|
||||
|
||||
static const u8 iwl_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = {
|
||||
EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_INIT_CALIB1,
|
||||
BT_COEX_PRIO_TBL_PRIO_BYPASS, 0),
|
||||
EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_INIT_CALIB2,
|
||||
BT_COEX_PRIO_TBL_PRIO_BYPASS, 1),
|
||||
EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_LOW1,
|
||||
BT_COEX_PRIO_TBL_PRIO_LOW, 0),
|
||||
EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_LOW2,
|
||||
BT_COEX_PRIO_TBL_PRIO_LOW, 1),
|
||||
EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_HIGH1,
|
||||
BT_COEX_PRIO_TBL_PRIO_HIGH, 0),
|
||||
EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_HIGH2,
|
||||
BT_COEX_PRIO_TBL_PRIO_HIGH, 1),
|
||||
EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_DTIM,
|
||||
BT_COEX_PRIO_TBL_DISABLED, 0),
|
||||
EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_SCAN52,
|
||||
BT_COEX_PRIO_TBL_PRIO_COEX_OFF, 0),
|
||||
EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_SCAN24,
|
||||
BT_COEX_PRIO_TBL_PRIO_COEX_ON, 0),
|
||||
EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_IDLE,
|
||||
BT_COEX_PRIO_TBL_PRIO_COEX_IDLE, 0),
|
||||
0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
#undef EVENT_PRIO_ANT
|
||||
|
||||
int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm)
|
||||
{
|
||||
return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_PRIO_TABLE, CMD_SYNC,
|
||||
sizeof(struct iwl_bt_coex_prio_tbl_cmd),
|
||||
&iwl_bt_prio_tbl);
|
||||
}
|
||||
|
||||
static int iwl_send_bt_env(struct iwl_mvm *mvm, u8 action, u8 type)
|
||||
{
|
||||
struct iwl_bt_coex_prot_env_cmd env_cmd;
|
||||
int ret;
|
||||
|
||||
env_cmd.action = action;
|
||||
env_cmd.type = type;
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, BT_COEX_PROT_ENV, CMD_SYNC,
|
||||
sizeof(env_cmd), &env_cmd);
|
||||
if (ret)
|
||||
IWL_ERR(mvm, "failed to send BT env command\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
enum iwl_bt_kill_msk {
|
||||
BT_KILL_MSK_DEFAULT,
|
||||
BT_KILL_MSK_SCO_HID_A2DP,
|
||||
BT_KILL_MSK_REDUCED_TXPOW,
|
||||
BT_KILL_MSK_MAX,
|
||||
};
|
||||
|
||||
static const u32 iwl_bt_ack_kill_msk[BT_KILL_MSK_MAX] = {
|
||||
0xffffffff,
|
||||
0xfffffc00,
|
||||
0,
|
||||
};
|
||||
|
||||
static const u32 iwl_bt_cts_kill_msk[BT_KILL_MSK_MAX] = {
|
||||
0xffffffff,
|
||||
0xfffffc00,
|
||||
0,
|
||||
};
|
||||
|
||||
#define IWL_BT_DEFAULT_BOOST (0xf0f0f0f0)
|
||||
|
||||
/* Tight Coex */
|
||||
static const __le32 iwl_tight_lookup[BT_COEX_LUT_SIZE] = {
|
||||
cpu_to_le32(0xaaaaaaaa),
|
||||
cpu_to_le32(0xaaaaaaaa),
|
||||
cpu_to_le32(0xaeaaaaaa),
|
||||
cpu_to_le32(0xaaaaaaaa),
|
||||
cpu_to_le32(0xcc00ff28),
|
||||
cpu_to_le32(0x0000aaaa),
|
||||
cpu_to_le32(0xcc00aaaa),
|
||||
cpu_to_le32(0x0000aaaa),
|
||||
cpu_to_le32(0xc0004000),
|
||||
cpu_to_le32(0x00000000),
|
||||
cpu_to_le32(0xf0005000),
|
||||
cpu_to_le32(0xf0005000),
|
||||
};
|
||||
|
||||
/* Loose Coex */
|
||||
static const __le32 iwl_loose_lookup[BT_COEX_LUT_SIZE] = {
|
||||
cpu_to_le32(0xaaaaaaaa),
|
||||
cpu_to_le32(0xaaaaaaaa),
|
||||
cpu_to_le32(0xaeaaaaaa),
|
||||
cpu_to_le32(0xaaaaaaaa),
|
||||
cpu_to_le32(0xcc00ff28),
|
||||
cpu_to_le32(0x0000aaaa),
|
||||
cpu_to_le32(0xcc00aaaa),
|
||||
cpu_to_le32(0x0000aaaa),
|
||||
cpu_to_le32(0x00000000),
|
||||
cpu_to_le32(0x00000000),
|
||||
cpu_to_le32(0xf0005000),
|
||||
cpu_to_le32(0xf0005000),
|
||||
};
|
||||
|
||||
/* Full concurrency */
|
||||
static const __le32 iwl_concurrent_lookup[BT_COEX_LUT_SIZE] = {
|
||||
cpu_to_le32(0xaaaaaaaa),
|
||||
cpu_to_le32(0xaaaaaaaa),
|
||||
cpu_to_le32(0xaaaaaaaa),
|
||||
cpu_to_le32(0xaaaaaaaa),
|
||||
cpu_to_le32(0xaaaaaaaa),
|
||||
cpu_to_le32(0xaaaaaaaa),
|
||||
cpu_to_le32(0xaaaaaaaa),
|
||||
cpu_to_le32(0xaaaaaaaa),
|
||||
cpu_to_le32(0x00000000),
|
||||
cpu_to_le32(0x00000000),
|
||||
cpu_to_le32(0x00000000),
|
||||
cpu_to_le32(0x00000000),
|
||||
};
|
||||
|
||||
/* BT Antenna Coupling Threshold (dB) */
|
||||
#define IWL_BT_ANTENNA_COUPLING_THRESHOLD (35)
|
||||
|
||||
int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
|
||||
{
|
||||
struct iwl_bt_coex_cmd cmd = {
|
||||
.max_kill = 5,
|
||||
.bt3_time_t7_value = 1,
|
||||
.bt3_prio_sample_time = 2,
|
||||
.bt3_timer_t2_value = 0xc,
|
||||
};
|
||||
int ret;
|
||||
|
||||
cmd.flags = iwlwifi_mod_params.bt_coex_active ?
|
||||
BT_COEX_NW : BT_COEX_DISABLE;
|
||||
cmd.flags |= iwlwifi_mod_params.bt_ch_announce ?
|
||||
BT_CH_PRIMARY_EN | BT_CH_SECONDARY_EN : 0;
|
||||
cmd.flags |= BT_SYNC_2_BT_DISABLE;
|
||||
|
||||
cmd.valid_bit_msk = cpu_to_le16(BT_VALID_ENABLE |
|
||||
BT_VALID_BT_PRIO_BOOST |
|
||||
BT_VALID_MAX_KILL |
|
||||
BT_VALID_3W_TMRS |
|
||||
BT_VALID_KILL_ACK |
|
||||
BT_VALID_KILL_CTS |
|
||||
BT_VALID_REDUCED_TX_POWER |
|
||||
BT_VALID_LUT);
|
||||
|
||||
if (iwlwifi_mod_params.ant_coupling > IWL_BT_ANTENNA_COUPLING_THRESHOLD)
|
||||
memcpy(&cmd.decision_lut, iwl_loose_lookup,
|
||||
sizeof(iwl_tight_lookup));
|
||||
else
|
||||
memcpy(&cmd.decision_lut, iwl_tight_lookup,
|
||||
sizeof(iwl_tight_lookup));
|
||||
|
||||
cmd.bt_prio_boost = cpu_to_le32(IWL_BT_DEFAULT_BOOST);
|
||||
cmd.kill_ack_msk =
|
||||
cpu_to_le32(iwl_bt_ack_kill_msk[BT_KILL_MSK_DEFAULT]);
|
||||
cmd.kill_cts_msk =
|
||||
cpu_to_le32(iwl_bt_cts_kill_msk[BT_KILL_MSK_DEFAULT]);
|
||||
|
||||
/* go to CALIB state in internal BT-Coex state machine */
|
||||
ret = iwl_send_bt_env(mvm, BT_COEX_ENV_OPEN,
|
||||
BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = iwl_send_bt_env(mvm, BT_COEX_ENV_CLOSE,
|
||||
BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return iwl_mvm_send_cmd_pdu(mvm, BT_CONFIG, CMD_SYNC,
|
||||
sizeof(cmd), &cmd);
|
||||
}
|
||||
|
||||
struct iwl_bt_notif_iterator_data {
|
||||
struct iwl_mvm *mvm;
|
||||
struct iwl_bt_coex_profile_notif *notif;
|
||||
};
|
||||
|
||||
static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_bt_notif_iterator_data *data = _data;
|
||||
struct ieee80211_chanctx_conf *chanctx_conf;
|
||||
enum ieee80211_smps_mode smps_mode;
|
||||
enum ieee80211_band band;
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_STATION)
|
||||
return;
|
||||
|
||||
rcu_read_lock();
|
||||
chanctx_conf = rcu_dereference(vif->chanctx_conf);
|
||||
if (chanctx_conf && chanctx_conf->def.chan)
|
||||
band = chanctx_conf->def.chan->band;
|
||||
else
|
||||
band = -1;
|
||||
rcu_read_unlock();
|
||||
|
||||
if (band != IEEE80211_BAND_2GHZ)
|
||||
return;
|
||||
|
||||
smps_mode = IEEE80211_SMPS_AUTOMATIC;
|
||||
|
||||
if (data->notif->bt_status)
|
||||
smps_mode = IEEE80211_SMPS_DYNAMIC;
|
||||
|
||||
if (data->notif->bt_traffic_load)
|
||||
smps_mode = IEEE80211_SMPS_STATIC;
|
||||
|
||||
IWL_DEBUG_COEX(data->mvm,
|
||||
"mac %d: bt_status %d traffic_load %d smps_req %d\n",
|
||||
mvmvif->id, data->notif->bt_status,
|
||||
data->notif->bt_traffic_load, smps_mode);
|
||||
|
||||
ieee80211_request_smps(vif, smps_mode);
|
||||
}
|
||||
|
||||
int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *dev_cmd)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_bt_coex_profile_notif *notif = (void *)pkt->data;
|
||||
struct iwl_bt_notif_iterator_data data = {
|
||||
.mvm = mvm,
|
||||
.notif = notif,
|
||||
};
|
||||
struct iwl_bt_coex_cmd cmd = {};
|
||||
enum iwl_bt_kill_msk bt_kill_msk;
|
||||
|
||||
IWL_DEBUG_COEX(mvm, "BT Coex Notification received\n");
|
||||
IWL_DEBUG_COEX(mvm, "\tBT %salive\n", notif->bt_status ? "" : "not ");
|
||||
IWL_DEBUG_COEX(mvm, "\tBT open conn %d\n", notif->bt_open_conn);
|
||||
IWL_DEBUG_COEX(mvm, "\tBT traffic load %d\n", notif->bt_traffic_load);
|
||||
IWL_DEBUG_COEX(mvm, "\tBT agg traffic load %d\n",
|
||||
notif->bt_agg_traffic_load);
|
||||
IWL_DEBUG_COEX(mvm, "\tBT ci compliance %d\n", notif->bt_ci_compliance);
|
||||
|
||||
/* remember this notification for future use: rssi fluctuations */
|
||||
memcpy(&mvm->last_bt_notif, notif, sizeof(mvm->last_bt_notif));
|
||||
|
||||
ieee80211_iterate_active_interfaces_atomic(
|
||||
mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
|
||||
iwl_mvm_bt_notif_iterator, &data);
|
||||
|
||||
/* Low latency BT profile is active: give higher prio to BT */
|
||||
if (BT_MBOX_MSG(notif, 3, SCO_STATE) ||
|
||||
BT_MBOX_MSG(notif, 3, A2DP_STATE) ||
|
||||
BT_MBOX_MSG(notif, 3, SNIFF_STATE))
|
||||
bt_kill_msk = BT_KILL_MSK_SCO_HID_A2DP;
|
||||
else
|
||||
bt_kill_msk = BT_KILL_MSK_DEFAULT;
|
||||
|
||||
/* Don't send HCMD if there is no update */
|
||||
if (bt_kill_msk == mvm->bt_kill_msk)
|
||||
return 0;
|
||||
|
||||
IWL_DEBUG_COEX(mvm,
|
||||
"Udpate kill_msk: %d\n\t SCO %sactive A2DP %sactive SNIFF %sactive\n",
|
||||
bt_kill_msk,
|
||||
BT_MBOX_MSG(notif, 3, SCO_STATE) ? "" : "in",
|
||||
BT_MBOX_MSG(notif, 3, A2DP_STATE) ? "" : "in",
|
||||
BT_MBOX_MSG(notif, 3, SNIFF_STATE) ? "" : "in");
|
||||
|
||||
mvm->bt_kill_msk = bt_kill_msk;
|
||||
cmd.kill_ack_msk = cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]);
|
||||
cmd.kill_cts_msk = cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]);
|
||||
|
||||
cmd.valid_bit_msk = cpu_to_le16(BT_VALID_KILL_ACK | BT_VALID_KILL_CTS);
|
||||
|
||||
if (iwl_mvm_send_cmd_pdu(mvm, BT_CONFIG, CMD_SYNC, sizeof(cmd), &cmd))
|
||||
IWL_ERR(mvm, "Failed to sent BT Coex CMD\n");
|
||||
|
||||
/* This handler is ASYNC */
|
||||
return 0;
|
||||
}
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
@ -61,8 +61,11 @@
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/ip.h>
|
||||
#include <net/cfg80211.h>
|
||||
#include <net/ipv6.h>
|
||||
#include <net/tcp.h>
|
||||
#include "iwl-modparams.h"
|
||||
#include "fw-api.h"
|
||||
#include "mvm.h"
|
||||
@ -192,6 +195,11 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
|
||||
sizeof(wkc), &wkc);
|
||||
data->error = ret != 0;
|
||||
|
||||
mvm->ptk_ivlen = key->iv_len;
|
||||
mvm->ptk_icvlen = key->icv_len;
|
||||
mvm->gtk_ivlen = key->iv_len;
|
||||
mvm->gtk_icvlen = key->icv_len;
|
||||
|
||||
/* don't upload key again */
|
||||
goto out_unlock;
|
||||
}
|
||||
@ -304,9 +312,13 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
|
||||
*/
|
||||
if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
|
||||
key->hw_key_idx = 0;
|
||||
mvm->ptk_ivlen = key->iv_len;
|
||||
mvm->ptk_icvlen = key->icv_len;
|
||||
} else {
|
||||
data->gtk_key_idx++;
|
||||
key->hw_key_idx = data->gtk_key_idx;
|
||||
mvm->gtk_ivlen = key->iv_len;
|
||||
mvm->gtk_icvlen = key->icv_len;
|
||||
}
|
||||
|
||||
ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, true);
|
||||
@ -392,6 +404,233 @@ static int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm,
|
||||
sizeof(cmd), &cmd);
|
||||
}
|
||||
|
||||
enum iwl_mvm_tcp_packet_type {
|
||||
MVM_TCP_TX_SYN,
|
||||
MVM_TCP_RX_SYNACK,
|
||||
MVM_TCP_TX_DATA,
|
||||
MVM_TCP_RX_ACK,
|
||||
MVM_TCP_RX_WAKE,
|
||||
MVM_TCP_TX_FIN,
|
||||
};
|
||||
|
||||
static __le16 pseudo_hdr_check(int len, __be32 saddr, __be32 daddr)
|
||||
{
|
||||
__sum16 check = tcp_v4_check(len, saddr, daddr, 0);
|
||||
return cpu_to_le16(be16_to_cpu((__force __be16)check));
|
||||
}
|
||||
|
||||
static void iwl_mvm_build_tcp_packet(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_wowlan_tcp *tcp,
|
||||
void *_pkt, u8 *mask,
|
||||
__le16 *pseudo_hdr_csum,
|
||||
enum iwl_mvm_tcp_packet_type ptype)
|
||||
{
|
||||
struct {
|
||||
struct ethhdr eth;
|
||||
struct iphdr ip;
|
||||
struct tcphdr tcp;
|
||||
u8 data[];
|
||||
} __packed *pkt = _pkt;
|
||||
u16 ip_tot_len = sizeof(struct iphdr) + sizeof(struct tcphdr);
|
||||
int i;
|
||||
|
||||
pkt->eth.h_proto = cpu_to_be16(ETH_P_IP),
|
||||
pkt->ip.version = 4;
|
||||
pkt->ip.ihl = 5;
|
||||
pkt->ip.protocol = IPPROTO_TCP;
|
||||
|
||||
switch (ptype) {
|
||||
case MVM_TCP_TX_SYN:
|
||||
case MVM_TCP_TX_DATA:
|
||||
case MVM_TCP_TX_FIN:
|
||||
memcpy(pkt->eth.h_dest, tcp->dst_mac, ETH_ALEN);
|
||||
memcpy(pkt->eth.h_source, vif->addr, ETH_ALEN);
|
||||
pkt->ip.ttl = 128;
|
||||
pkt->ip.saddr = tcp->src;
|
||||
pkt->ip.daddr = tcp->dst;
|
||||
pkt->tcp.source = cpu_to_be16(tcp->src_port);
|
||||
pkt->tcp.dest = cpu_to_be16(tcp->dst_port);
|
||||
/* overwritten for TX SYN later */
|
||||
pkt->tcp.doff = sizeof(struct tcphdr) / 4;
|
||||
pkt->tcp.window = cpu_to_be16(65000);
|
||||
break;
|
||||
case MVM_TCP_RX_SYNACK:
|
||||
case MVM_TCP_RX_ACK:
|
||||
case MVM_TCP_RX_WAKE:
|
||||
memcpy(pkt->eth.h_dest, vif->addr, ETH_ALEN);
|
||||
memcpy(pkt->eth.h_source, tcp->dst_mac, ETH_ALEN);
|
||||
pkt->ip.saddr = tcp->dst;
|
||||
pkt->ip.daddr = tcp->src;
|
||||
pkt->tcp.source = cpu_to_be16(tcp->dst_port);
|
||||
pkt->tcp.dest = cpu_to_be16(tcp->src_port);
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ptype) {
|
||||
case MVM_TCP_TX_SYN:
|
||||
/* firmware assumes 8 option bytes - 8 NOPs for now */
|
||||
memset(pkt->data, 0x01, 8);
|
||||
ip_tot_len += 8;
|
||||
pkt->tcp.doff = (sizeof(struct tcphdr) + 8) / 4;
|
||||
pkt->tcp.syn = 1;
|
||||
break;
|
||||
case MVM_TCP_TX_DATA:
|
||||
ip_tot_len += tcp->payload_len;
|
||||
memcpy(pkt->data, tcp->payload, tcp->payload_len);
|
||||
pkt->tcp.psh = 1;
|
||||
pkt->tcp.ack = 1;
|
||||
break;
|
||||
case MVM_TCP_TX_FIN:
|
||||
pkt->tcp.fin = 1;
|
||||
pkt->tcp.ack = 1;
|
||||
break;
|
||||
case MVM_TCP_RX_SYNACK:
|
||||
pkt->tcp.syn = 1;
|
||||
pkt->tcp.ack = 1;
|
||||
break;
|
||||
case MVM_TCP_RX_ACK:
|
||||
pkt->tcp.ack = 1;
|
||||
break;
|
||||
case MVM_TCP_RX_WAKE:
|
||||
ip_tot_len += tcp->wake_len;
|
||||
pkt->tcp.psh = 1;
|
||||
pkt->tcp.ack = 1;
|
||||
memcpy(pkt->data, tcp->wake_data, tcp->wake_len);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (ptype) {
|
||||
case MVM_TCP_TX_SYN:
|
||||
case MVM_TCP_TX_DATA:
|
||||
case MVM_TCP_TX_FIN:
|
||||
pkt->ip.tot_len = cpu_to_be16(ip_tot_len);
|
||||
pkt->ip.check = ip_fast_csum(&pkt->ip, pkt->ip.ihl);
|
||||
break;
|
||||
case MVM_TCP_RX_WAKE:
|
||||
for (i = 0; i < DIV_ROUND_UP(tcp->wake_len, 8); i++) {
|
||||
u8 tmp = tcp->wake_mask[i];
|
||||
mask[i + 6] |= tmp << 6;
|
||||
if (i + 1 < DIV_ROUND_UP(tcp->wake_len, 8))
|
||||
mask[i + 7] = tmp >> 2;
|
||||
}
|
||||
/* fall through for ethernet/IP/TCP headers mask */
|
||||
case MVM_TCP_RX_SYNACK:
|
||||
case MVM_TCP_RX_ACK:
|
||||
mask[0] = 0xff; /* match ethernet */
|
||||
/*
|
||||
* match ethernet, ip.version, ip.ihl
|
||||
* the ip.ihl half byte is really masked out by firmware
|
||||
*/
|
||||
mask[1] = 0x7f;
|
||||
mask[2] = 0x80; /* match ip.protocol */
|
||||
mask[3] = 0xfc; /* match ip.saddr, ip.daddr */
|
||||
mask[4] = 0x3f; /* match ip.daddr, tcp.source, tcp.dest */
|
||||
mask[5] = 0x80; /* match tcp flags */
|
||||
/* leave rest (0 or set for MVM_TCP_RX_WAKE) */
|
||||
break;
|
||||
};
|
||||
|
||||
*pseudo_hdr_csum = pseudo_hdr_check(ip_tot_len - sizeof(struct iphdr),
|
||||
pkt->ip.saddr, pkt->ip.daddr);
|
||||
}
|
||||
|
||||
static int iwl_mvm_send_remote_wake_cfg(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_wowlan_tcp *tcp)
|
||||
{
|
||||
struct iwl_wowlan_remote_wake_config *cfg;
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = REMOTE_WAKE_CONFIG_CMD,
|
||||
.len = { sizeof(*cfg), },
|
||||
.dataflags = { IWL_HCMD_DFL_NOCOPY, },
|
||||
.flags = CMD_SYNC,
|
||||
};
|
||||
int ret;
|
||||
|
||||
if (!tcp)
|
||||
return 0;
|
||||
|
||||
cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
|
||||
if (!cfg)
|
||||
return -ENOMEM;
|
||||
cmd.data[0] = cfg;
|
||||
|
||||
cfg->max_syn_retries = 10;
|
||||
cfg->max_data_retries = 10;
|
||||
cfg->tcp_syn_ack_timeout = 1; /* seconds */
|
||||
cfg->tcp_ack_timeout = 1; /* seconds */
|
||||
|
||||
/* SYN (TX) */
|
||||
iwl_mvm_build_tcp_packet(
|
||||
mvm, vif, tcp, cfg->syn_tx.data, NULL,
|
||||
&cfg->syn_tx.info.tcp_pseudo_header_checksum,
|
||||
MVM_TCP_TX_SYN);
|
||||
cfg->syn_tx.info.tcp_payload_length = 0;
|
||||
|
||||
/* SYN/ACK (RX) */
|
||||
iwl_mvm_build_tcp_packet(
|
||||
mvm, vif, tcp, cfg->synack_rx.data, cfg->synack_rx.rx_mask,
|
||||
&cfg->synack_rx.info.tcp_pseudo_header_checksum,
|
||||
MVM_TCP_RX_SYNACK);
|
||||
cfg->synack_rx.info.tcp_payload_length = 0;
|
||||
|
||||
/* KEEPALIVE/ACK (TX) */
|
||||
iwl_mvm_build_tcp_packet(
|
||||
mvm, vif, tcp, cfg->keepalive_tx.data, NULL,
|
||||
&cfg->keepalive_tx.info.tcp_pseudo_header_checksum,
|
||||
MVM_TCP_TX_DATA);
|
||||
cfg->keepalive_tx.info.tcp_payload_length =
|
||||
cpu_to_le16(tcp->payload_len);
|
||||
cfg->sequence_number_offset = tcp->payload_seq.offset;
|
||||
/* length must be 0..4, the field is little endian */
|
||||
cfg->sequence_number_length = tcp->payload_seq.len;
|
||||
cfg->initial_sequence_number = cpu_to_le32(tcp->payload_seq.start);
|
||||
cfg->keepalive_interval = cpu_to_le16(tcp->data_interval);
|
||||
if (tcp->payload_tok.len) {
|
||||
cfg->token_offset = tcp->payload_tok.offset;
|
||||
cfg->token_length = tcp->payload_tok.len;
|
||||
cfg->num_tokens =
|
||||
cpu_to_le16(tcp->tokens_size % tcp->payload_tok.len);
|
||||
memcpy(cfg->tokens, tcp->payload_tok.token_stream,
|
||||
tcp->tokens_size);
|
||||
} else {
|
||||
/* set tokens to max value to almost never run out */
|
||||
cfg->num_tokens = cpu_to_le16(65535);
|
||||
}
|
||||
|
||||
/* ACK (RX) */
|
||||
iwl_mvm_build_tcp_packet(
|
||||
mvm, vif, tcp, cfg->keepalive_ack_rx.data,
|
||||
cfg->keepalive_ack_rx.rx_mask,
|
||||
&cfg->keepalive_ack_rx.info.tcp_pseudo_header_checksum,
|
||||
MVM_TCP_RX_ACK);
|
||||
cfg->keepalive_ack_rx.info.tcp_payload_length = 0;
|
||||
|
||||
/* WAKEUP (RX) */
|
||||
iwl_mvm_build_tcp_packet(
|
||||
mvm, vif, tcp, cfg->wake_rx.data, cfg->wake_rx.rx_mask,
|
||||
&cfg->wake_rx.info.tcp_pseudo_header_checksum,
|
||||
MVM_TCP_RX_WAKE);
|
||||
cfg->wake_rx.info.tcp_payload_length =
|
||||
cpu_to_le16(tcp->wake_len);
|
||||
|
||||
/* FIN */
|
||||
iwl_mvm_build_tcp_packet(
|
||||
mvm, vif, tcp, cfg->fin_tx.data, NULL,
|
||||
&cfg->fin_tx.info.tcp_pseudo_header_checksum,
|
||||
MVM_TCP_TX_FIN);
|
||||
cfg->fin_tx.info.tcp_payload_length = 0;
|
||||
|
||||
ret = iwl_mvm_send_cmd(mvm, &cmd);
|
||||
kfree(cfg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct iwl_d3_iter_data {
|
||||
struct iwl_mvm *mvm;
|
||||
struct ieee80211_vif *vif;
|
||||
@ -630,6 +869,22 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
|
||||
d3_cfg_cmd.wakeup_flags |=
|
||||
cpu_to_le32(IWL_WOWLAN_WAKEUP_RF_KILL_DEASSERT);
|
||||
|
||||
if (wowlan->tcp) {
|
||||
/*
|
||||
* The firmware currently doesn't really look at these, only
|
||||
* the IWL_WOWLAN_WAKEUP_LINK_CHANGE bit. We have to set that
|
||||
* reason bit since losing the connection to the AP implies
|
||||
* losing the TCP connection.
|
||||
* Set the flags anyway as long as they exist, in case this
|
||||
* will be changed in the firmware.
|
||||
*/
|
||||
wowlan_config_cmd.wakeup_filter |=
|
||||
cpu_to_le32(IWL_WOWLAN_WAKEUP_REMOTE_LINK_LOSS |
|
||||
IWL_WOWLAN_WAKEUP_REMOTE_SIGNATURE_TABLE |
|
||||
IWL_WOWLAN_WAKEUP_REMOTE_WAKEUP_PACKET |
|
||||
IWL_WOWLAN_WAKEUP_LINK_CHANGE);
|
||||
}
|
||||
|
||||
iwl_mvm_cancel_scan(mvm);
|
||||
|
||||
iwl_trans_stop_device(mvm->trans);
|
||||
@ -649,6 +904,11 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
|
||||
/* We reprogram keys and shouldn't allocate new key indices */
|
||||
memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table));
|
||||
|
||||
mvm->ptk_ivlen = 0;
|
||||
mvm->ptk_icvlen = 0;
|
||||
mvm->ptk_ivlen = 0;
|
||||
mvm->ptk_icvlen = 0;
|
||||
|
||||
/*
|
||||
* The D3 firmware still hardcodes the AP station ID for the
|
||||
* BSS we're associated with as 0. As a result, we have to move
|
||||
@ -740,6 +1000,10 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = iwl_mvm_send_remote_wake_cfg(mvm, vif, wowlan->tcp);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* must be last -- this switches firmware state */
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, D3_CONFIG_CMD, CMD_SYNC,
|
||||
sizeof(d3_cfg_cmd), &d3_cfg_cmd);
|
||||
@ -783,7 +1047,6 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
|
||||
struct iwl_wowlan_status *status;
|
||||
u32 reasons;
|
||||
int ret, len;
|
||||
bool pkt8023 = false;
|
||||
struct sk_buff *pkt = NULL;
|
||||
|
||||
iwl_trans_read_mem_bytes(mvm->trans, base,
|
||||
@ -824,7 +1087,8 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
|
||||
status = (void *)cmd.resp_pkt->data;
|
||||
|
||||
if (len - sizeof(struct iwl_cmd_header) !=
|
||||
sizeof(*status) + le32_to_cpu(status->wake_packet_bufsize)) {
|
||||
sizeof(*status) +
|
||||
ALIGN(le32_to_cpu(status->wake_packet_bufsize), 4)) {
|
||||
IWL_ERR(mvm, "Invalid WoWLAN status response!\n");
|
||||
goto out;
|
||||
}
|
||||
@ -836,61 +1100,105 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
|
||||
goto report;
|
||||
}
|
||||
|
||||
if (reasons & IWL_WOWLAN_WAKEUP_BY_MAGIC_PACKET) {
|
||||
if (reasons & IWL_WOWLAN_WAKEUP_BY_MAGIC_PACKET)
|
||||
wakeup.magic_pkt = true;
|
||||
pkt8023 = true;
|
||||
}
|
||||
|
||||
if (reasons & IWL_WOWLAN_WAKEUP_BY_PATTERN) {
|
||||
if (reasons & IWL_WOWLAN_WAKEUP_BY_PATTERN)
|
||||
wakeup.pattern_idx =
|
||||
le16_to_cpu(status->pattern_number);
|
||||
pkt8023 = true;
|
||||
}
|
||||
|
||||
if (reasons & (IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_MISSED_BEACON |
|
||||
IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_DEAUTH))
|
||||
wakeup.disconnect = true;
|
||||
|
||||
if (reasons & IWL_WOWLAN_WAKEUP_BY_GTK_REKEY_FAILURE) {
|
||||
if (reasons & IWL_WOWLAN_WAKEUP_BY_GTK_REKEY_FAILURE)
|
||||
wakeup.gtk_rekey_failure = true;
|
||||
pkt8023 = true;
|
||||
}
|
||||
|
||||
if (reasons & IWL_WOWLAN_WAKEUP_BY_RFKILL_DEASSERTED) {
|
||||
if (reasons & IWL_WOWLAN_WAKEUP_BY_RFKILL_DEASSERTED)
|
||||
wakeup.rfkill_release = true;
|
||||
pkt8023 = true;
|
||||
}
|
||||
|
||||
if (reasons & IWL_WOWLAN_WAKEUP_BY_EAPOL_REQUEST) {
|
||||
if (reasons & IWL_WOWLAN_WAKEUP_BY_EAPOL_REQUEST)
|
||||
wakeup.eap_identity_req = true;
|
||||
pkt8023 = true;
|
||||
}
|
||||
|
||||
if (reasons & IWL_WOWLAN_WAKEUP_BY_FOUR_WAY_HANDSHAKE) {
|
||||
if (reasons & IWL_WOWLAN_WAKEUP_BY_FOUR_WAY_HANDSHAKE)
|
||||
wakeup.four_way_handshake = true;
|
||||
pkt8023 = true;
|
||||
}
|
||||
|
||||
if (reasons & IWL_WOWLAN_WAKEUP_BY_REM_WAKE_LINK_LOSS)
|
||||
wakeup.tcp_connlost = true;
|
||||
|
||||
if (reasons & IWL_WOWLAN_WAKEUP_BY_REM_WAKE_SIGNATURE_TABLE)
|
||||
wakeup.tcp_nomoretokens = true;
|
||||
|
||||
if (reasons & IWL_WOWLAN_WAKEUP_BY_REM_WAKE_WAKEUP_PACKET)
|
||||
wakeup.tcp_match = true;
|
||||
|
||||
if (status->wake_packet_bufsize) {
|
||||
u32 pktsize = le32_to_cpu(status->wake_packet_bufsize);
|
||||
u32 pktlen = le32_to_cpu(status->wake_packet_length);
|
||||
int pktsize = le32_to_cpu(status->wake_packet_bufsize);
|
||||
int pktlen = le32_to_cpu(status->wake_packet_length);
|
||||
const u8 *pktdata = status->wake_packet;
|
||||
struct ieee80211_hdr *hdr = (void *)pktdata;
|
||||
int truncated = pktlen - pktsize;
|
||||
|
||||
/* this would be a firmware bug */
|
||||
if (WARN_ON_ONCE(truncated < 0))
|
||||
truncated = 0;
|
||||
|
||||
if (ieee80211_is_data(hdr->frame_control)) {
|
||||
int hdrlen = ieee80211_hdrlen(hdr->frame_control);
|
||||
int ivlen = 0, icvlen = 4; /* also FCS */
|
||||
|
||||
if (pkt8023) {
|
||||
pkt = alloc_skb(pktsize, GFP_KERNEL);
|
||||
if (!pkt)
|
||||
goto report;
|
||||
memcpy(skb_put(pkt, pktsize), status->wake_packet,
|
||||
pktsize);
|
||||
|
||||
memcpy(skb_put(pkt, hdrlen), pktdata, hdrlen);
|
||||
pktdata += hdrlen;
|
||||
pktsize -= hdrlen;
|
||||
|
||||
if (ieee80211_has_protected(hdr->frame_control)) {
|
||||
if (is_multicast_ether_addr(hdr->addr1)) {
|
||||
ivlen = mvm->gtk_ivlen;
|
||||
icvlen += mvm->gtk_icvlen;
|
||||
} else {
|
||||
ivlen = mvm->ptk_ivlen;
|
||||
icvlen += mvm->ptk_icvlen;
|
||||
}
|
||||
}
|
||||
|
||||
/* if truncated, FCS/ICV is (partially) gone */
|
||||
if (truncated >= icvlen) {
|
||||
icvlen = 0;
|
||||
truncated -= icvlen;
|
||||
} else {
|
||||
icvlen -= truncated;
|
||||
truncated = 0;
|
||||
}
|
||||
|
||||
pktsize -= ivlen + icvlen;
|
||||
pktdata += ivlen;
|
||||
|
||||
memcpy(skb_put(pkt, pktsize), pktdata, pktsize);
|
||||
|
||||
if (ieee80211_data_to_8023(pkt, vif->addr, vif->type))
|
||||
goto report;
|
||||
wakeup.packet = pkt->data;
|
||||
wakeup.packet_present_len = pkt->len;
|
||||
wakeup.packet_len = pkt->len - (pktlen - pktsize);
|
||||
wakeup.packet_len = pkt->len - truncated;
|
||||
wakeup.packet_80211 = false;
|
||||
} else {
|
||||
int fcslen = 4;
|
||||
|
||||
if (truncated >= 4) {
|
||||
truncated -= 4;
|
||||
fcslen = 0;
|
||||
} else {
|
||||
fcslen -= truncated;
|
||||
truncated = 0;
|
||||
}
|
||||
pktsize -= fcslen;
|
||||
wakeup.packet = status->wake_packet;
|
||||
wakeup.packet_present_len = pktsize;
|
||||
wakeup.packet_len = pktlen;
|
||||
wakeup.packet_len = pktlen - truncated;
|
||||
wakeup.packet_80211 = true;
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
@ -69,12 +69,6 @@ struct iwl_dbgfs_mvm_ctx {
|
||||
struct ieee80211_vif *vif;
|
||||
};
|
||||
|
||||
static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file)
|
||||
{
|
||||
file->private_data = inode->i_private;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_tx_flush_write(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
@ -306,10 +300,130 @@ static ssize_t iwl_dbgfs_power_down_d3_allow_write(struct file *file,
|
||||
return count;
|
||||
}
|
||||
|
||||
#define BT_MBOX_MSG(_notif, _num, _field) \
|
||||
((le32_to_cpu((_notif)->mbox_msg[(_num)]) & BT_MBOX##_num##_##_field)\
|
||||
>> BT_MBOX##_num##_##_field##_POS)
|
||||
|
||||
|
||||
#define BT_MBOX_PRINT(_num, _field, _end) \
|
||||
pos += scnprintf(buf + pos, bufsz - pos, \
|
||||
"\t%s: %d%s", \
|
||||
#_field, \
|
||||
BT_MBOX_MSG(notif, _num, _field), \
|
||||
true ? "\n" : ", ");
|
||||
|
||||
static ssize_t iwl_dbgfs_bt_notif_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_mvm *mvm = file->private_data;
|
||||
struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif;
|
||||
char *buf;
|
||||
int ret, pos = 0, bufsz = sizeof(char) * 1024;
|
||||
|
||||
buf = kmalloc(bufsz, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw0:\n");
|
||||
|
||||
BT_MBOX_PRINT(0, LE_SLAVE_LAT, false);
|
||||
BT_MBOX_PRINT(0, LE_PROF1, false);
|
||||
BT_MBOX_PRINT(0, LE_PROF2, false);
|
||||
BT_MBOX_PRINT(0, LE_PROF_OTHER, false);
|
||||
BT_MBOX_PRINT(0, CHL_SEQ_N, false);
|
||||
BT_MBOX_PRINT(0, INBAND_S, false);
|
||||
BT_MBOX_PRINT(0, LE_MIN_RSSI, false);
|
||||
BT_MBOX_PRINT(0, LE_SCAN, false);
|
||||
BT_MBOX_PRINT(0, LE_ADV, false);
|
||||
BT_MBOX_PRINT(0, LE_MAX_TX_POWER, false);
|
||||
BT_MBOX_PRINT(0, OPEN_CON_1, true);
|
||||
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw1:\n");
|
||||
|
||||
BT_MBOX_PRINT(1, BR_MAX_TX_POWER, false);
|
||||
BT_MBOX_PRINT(1, IP_SR, false);
|
||||
BT_MBOX_PRINT(1, LE_MSTR, false);
|
||||
BT_MBOX_PRINT(1, AGGR_TRFC_LD, false);
|
||||
BT_MBOX_PRINT(1, MSG_TYPE, false);
|
||||
BT_MBOX_PRINT(1, SSN, true);
|
||||
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw2:\n");
|
||||
|
||||
BT_MBOX_PRINT(2, SNIFF_ACT, false);
|
||||
BT_MBOX_PRINT(2, PAG, false);
|
||||
BT_MBOX_PRINT(2, INQUIRY, false);
|
||||
BT_MBOX_PRINT(2, CONN, false);
|
||||
BT_MBOX_PRINT(2, SNIFF_INTERVAL, false);
|
||||
BT_MBOX_PRINT(2, DISC, false);
|
||||
BT_MBOX_PRINT(2, SCO_TX_ACT, false);
|
||||
BT_MBOX_PRINT(2, SCO_RX_ACT, false);
|
||||
BT_MBOX_PRINT(2, ESCO_RE_TX, false);
|
||||
BT_MBOX_PRINT(2, SCO_DURATION, true);
|
||||
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw3:\n");
|
||||
|
||||
BT_MBOX_PRINT(3, SCO_STATE, false);
|
||||
BT_MBOX_PRINT(3, SNIFF_STATE, false);
|
||||
BT_MBOX_PRINT(3, A2DP_STATE, false);
|
||||
BT_MBOX_PRINT(3, ACL_STATE, false);
|
||||
BT_MBOX_PRINT(3, MSTR_STATE, false);
|
||||
BT_MBOX_PRINT(3, OBX_STATE, false);
|
||||
BT_MBOX_PRINT(3, OPEN_CON_2, false);
|
||||
BT_MBOX_PRINT(3, TRAFFIC_LOAD, false);
|
||||
BT_MBOX_PRINT(3, CHL_SEQN_LSB, false);
|
||||
BT_MBOX_PRINT(3, INBAND_P, false);
|
||||
BT_MBOX_PRINT(3, MSG_TYPE_2, false);
|
||||
BT_MBOX_PRINT(3, SSN_2, false);
|
||||
BT_MBOX_PRINT(3, UPDATE_REQUEST, true);
|
||||
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "bt_status = %d\n",
|
||||
notif->bt_status);
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "bt_open_conn = %d\n",
|
||||
notif->bt_open_conn);
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "bt_traffic_load = %d\n",
|
||||
notif->bt_traffic_load);
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "bt_agg_traffic_load = %d\n",
|
||||
notif->bt_agg_traffic_load);
|
||||
pos += scnprintf(buf+pos, bufsz-pos, "bt_ci_compliance = %d\n",
|
||||
notif->bt_ci_compliance);
|
||||
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
kfree(buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#undef BT_MBOX_PRINT
|
||||
|
||||
static ssize_t iwl_dbgfs_fw_restart_write(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_mvm *mvm = file->private_data;
|
||||
bool restart_fw = iwlwifi_mod_params.restart_fw;
|
||||
int ret;
|
||||
|
||||
iwlwifi_mod_params.restart_fw = true;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
|
||||
/* take the return value to make compiler happy - it will fail anyway */
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, REPLY_ERROR, CMD_SYNC, 0, NULL);
|
||||
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
iwlwifi_mod_params.restart_fw = restart_fw;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
#define MVM_DEBUGFS_READ_FILE_OPS(name) \
|
||||
static const struct file_operations iwl_dbgfs_##name##_ops = { \
|
||||
.read = iwl_dbgfs_##name##_read, \
|
||||
.open = iwl_dbgfs_open_file_generic, \
|
||||
.open = simple_open, \
|
||||
.llseek = generic_file_llseek, \
|
||||
}
|
||||
|
||||
@ -317,14 +431,14 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \
|
||||
static const struct file_operations iwl_dbgfs_##name##_ops = { \
|
||||
.write = iwl_dbgfs_##name##_write, \
|
||||
.read = iwl_dbgfs_##name##_read, \
|
||||
.open = iwl_dbgfs_open_file_generic, \
|
||||
.open = simple_open, \
|
||||
.llseek = generic_file_llseek, \
|
||||
};
|
||||
|
||||
#define MVM_DEBUGFS_WRITE_FILE_OPS(name) \
|
||||
static const struct file_operations iwl_dbgfs_##name##_ops = { \
|
||||
.write = iwl_dbgfs_##name##_write, \
|
||||
.open = iwl_dbgfs_open_file_generic, \
|
||||
.open = simple_open, \
|
||||
.llseek = generic_file_llseek, \
|
||||
};
|
||||
|
||||
@ -345,8 +459,10 @@ MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain);
|
||||
MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram);
|
||||
MVM_DEBUGFS_READ_FILE_OPS(stations);
|
||||
MVM_DEBUGFS_READ_FILE_OPS(bt_notif);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(power_down_allow);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(power_down_d3_allow);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart);
|
||||
|
||||
int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
|
||||
{
|
||||
@ -358,8 +474,10 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
|
||||
MVM_DEBUGFS_ADD_FILE(sta_drain, mvm->debugfs_dir, S_IWUSR);
|
||||
MVM_DEBUGFS_ADD_FILE(sram, mvm->debugfs_dir, S_IWUSR | S_IRUSR);
|
||||
MVM_DEBUGFS_ADD_FILE(stations, dbgfs_dir, S_IRUSR);
|
||||
MVM_DEBUGFS_ADD_FILE(bt_notif, dbgfs_dir, S_IRUSR);
|
||||
MVM_DEBUGFS_ADD_FILE(power_down_allow, mvm->debugfs_dir, S_IWUSR);
|
||||
MVM_DEBUGFS_ADD_FILE(power_down_d3_allow, mvm->debugfs_dir, S_IWUSR);
|
||||
MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR);
|
||||
|
||||
/*
|
||||
* Create a symlink with mac80211. It will be removed when mac80211
|
||||
|
319
drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h
Normal file
319
drivers/net/wireless/iwlwifi/mvm/fw-api-bt-coex.h
Normal file
@ -0,0 +1,319 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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) 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2013 Intel Corporation. All rights reserved.
|
||||
* 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 __fw_api_bt_coex_h__
|
||||
#define __fw_api_bt_coex_h__
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#define BITS(nb) (BIT(nb) - 1)
|
||||
|
||||
/**
|
||||
* enum iwl_bt_coex_flags - flags for BT_COEX command
|
||||
* @BT_CH_PRIMARY_EN:
|
||||
* @BT_CH_SECONDARY_EN:
|
||||
* @BT_NOTIF_COEX_OFF:
|
||||
* @BT_COEX_MODE_POS:
|
||||
* @BT_COEX_MODE_MSK:
|
||||
* @BT_COEX_DISABLE:
|
||||
* @BT_COEX_2W:
|
||||
* @BT_COEX_3W:
|
||||
* @BT_COEX_NW:
|
||||
* @BT_USE_DEFAULTS:
|
||||
* @BT_SYNC_2_BT_DISABLE:
|
||||
* @BT_COEX_CORUNNING_TBL_EN:
|
||||
*/
|
||||
enum iwl_bt_coex_flags {
|
||||
BT_CH_PRIMARY_EN = BIT(0),
|
||||
BT_CH_SECONDARY_EN = BIT(1),
|
||||
BT_NOTIF_COEX_OFF = BIT(2),
|
||||
BT_COEX_MODE_POS = 3,
|
||||
BT_COEX_MODE_MSK = BITS(3) << BT_COEX_MODE_POS,
|
||||
BT_COEX_DISABLE = 0x0 << BT_COEX_MODE_POS,
|
||||
BT_COEX_2W = 0x1 << BT_COEX_MODE_POS,
|
||||
BT_COEX_3W = 0x2 << BT_COEX_MODE_POS,
|
||||
BT_COEX_NW = 0x3 << BT_COEX_MODE_POS,
|
||||
BT_USE_DEFAULTS = BIT(6),
|
||||
BT_SYNC_2_BT_DISABLE = BIT(7),
|
||||
/*
|
||||
* For future use - when the flags will be enlarged
|
||||
* BT_COEX_CORUNNING_TBL_EN = BIT(8),
|
||||
*/
|
||||
};
|
||||
|
||||
/*
|
||||
* indicates what has changed in the BT_COEX command.
|
||||
*/
|
||||
enum iwl_bt_coex_valid_bit_msk {
|
||||
BT_VALID_ENABLE = BIT(0),
|
||||
BT_VALID_BT_PRIO_BOOST = BIT(1),
|
||||
BT_VALID_MAX_KILL = BIT(2),
|
||||
BT_VALID_3W_TMRS = BIT(3),
|
||||
BT_VALID_KILL_ACK = BIT(4),
|
||||
BT_VALID_KILL_CTS = BIT(5),
|
||||
BT_VALID_REDUCED_TX_POWER = BIT(6),
|
||||
BT_VALID_LUT = BIT(7),
|
||||
BT_VALID_WIFI_RX_SW_PRIO_BOOST = BIT(8),
|
||||
BT_VALID_WIFI_TX_SW_PRIO_BOOST = BIT(9),
|
||||
BT_VALID_MULTI_PRIO_LUT = BIT(10),
|
||||
BT_VALID_TRM_KICK_FILTER = BIT(11),
|
||||
BT_VALID_CORUN_LUT_20 = BIT(12),
|
||||
BT_VALID_CORUN_LUT_40 = BIT(13),
|
||||
BT_VALID_ANT_ISOLATION = BIT(14),
|
||||
BT_VALID_ANT_ISOLATION_THRS = BIT(15),
|
||||
/*
|
||||
* For future use - when the valid flags will be enlarged
|
||||
* BT_VALID_TXTX_DELTA_FREQ_THRS = BIT(16),
|
||||
* BT_VALID_TXRX_MAX_FREQ_0 = BIT(17),
|
||||
*/
|
||||
};
|
||||
|
||||
/**
|
||||
* enum iwl_bt_reduced_tx_power - allows to reduce txpower for WiFi frames.
|
||||
* @BT_REDUCED_TX_POWER_CTL: reduce Tx power for control frames
|
||||
* @BT_REDUCED_TX_POWER_DATA: reduce Tx power for data frames
|
||||
*
|
||||
* This mechanism allows to have BT and WiFi run concurrently. Since WiFi
|
||||
* reduces its Tx power, it can work along with BT, hence reducing the amount
|
||||
* of WiFi frames being killed by BT.
|
||||
*/
|
||||
enum iwl_bt_reduced_tx_power {
|
||||
BT_REDUCED_TX_POWER_CTL = BIT(0),
|
||||
BT_REDUCED_TX_POWER_DATA = BIT(1),
|
||||
};
|
||||
|
||||
#define BT_COEX_LUT_SIZE (12)
|
||||
|
||||
/**
|
||||
* struct iwl_bt_coex_cmd - bt coex configuration command
|
||||
* @flags:&enum iwl_bt_coex_flags
|
||||
* @lead_time:
|
||||
* @max_kill:
|
||||
* @bt3_time_t7_value:
|
||||
* @kill_ack_msk:
|
||||
* @kill_cts_msk:
|
||||
* @bt3_prio_sample_time:
|
||||
* @bt3_timer_t2_value:
|
||||
* @bt4_reaction_time:
|
||||
* @decision_lut[12]:
|
||||
* @bt_reduced_tx_power: enum %iwl_bt_reduced_tx_power
|
||||
* @valid_bit_msk: enum %iwl_bt_coex_valid_bit_msk
|
||||
* @bt_prio_boost: values for PTA boost register
|
||||
* @wifi_tx_prio_boost: SW boost of wifi tx priority
|
||||
* @wifi_rx_prio_boost: SW boost of wifi rx priority
|
||||
*
|
||||
* The structure is used for the BT_COEX command.
|
||||
*/
|
||||
struct iwl_bt_coex_cmd {
|
||||
u8 flags;
|
||||
u8 lead_time;
|
||||
u8 max_kill;
|
||||
u8 bt3_time_t7_value;
|
||||
__le32 kill_ack_msk;
|
||||
__le32 kill_cts_msk;
|
||||
u8 bt3_prio_sample_time;
|
||||
u8 bt3_timer_t2_value;
|
||||
__le16 bt4_reaction_time;
|
||||
__le32 decision_lut[BT_COEX_LUT_SIZE];
|
||||
u8 bt_reduced_tx_power;
|
||||
u8 reserved;
|
||||
__le16 valid_bit_msk;
|
||||
__le32 bt_prio_boost;
|
||||
u8 reserved2;
|
||||
u8 wifi_tx_prio_boost;
|
||||
__le16 wifi_rx_prio_boost;
|
||||
} __packed; /* BT_COEX_CMD_API_S_VER_3 */
|
||||
|
||||
#define BT_MBOX(n_dw, _msg, _pos, _nbits) \
|
||||
BT_MBOX##n_dw##_##_msg##_POS = (_pos), \
|
||||
BT_MBOX##n_dw##_##_msg = BITS(_nbits) << BT_MBOX##n_dw##_##_msg##_POS
|
||||
|
||||
enum iwl_bt_mxbox_dw0 {
|
||||
BT_MBOX(0, LE_SLAVE_LAT, 0, 3),
|
||||
BT_MBOX(0, LE_PROF1, 3, 1),
|
||||
BT_MBOX(0, LE_PROF2, 4, 1),
|
||||
BT_MBOX(0, LE_PROF_OTHER, 5, 1),
|
||||
BT_MBOX(0, CHL_SEQ_N, 8, 4),
|
||||
BT_MBOX(0, INBAND_S, 13, 1),
|
||||
BT_MBOX(0, LE_MIN_RSSI, 16, 4),
|
||||
BT_MBOX(0, LE_SCAN, 20, 1),
|
||||
BT_MBOX(0, LE_ADV, 21, 1),
|
||||
BT_MBOX(0, LE_MAX_TX_POWER, 24, 4),
|
||||
BT_MBOX(0, OPEN_CON_1, 28, 2),
|
||||
};
|
||||
|
||||
enum iwl_bt_mxbox_dw1 {
|
||||
BT_MBOX(1, BR_MAX_TX_POWER, 0, 4),
|
||||
BT_MBOX(1, IP_SR, 4, 1),
|
||||
BT_MBOX(1, LE_MSTR, 5, 1),
|
||||
BT_MBOX(1, AGGR_TRFC_LD, 8, 6),
|
||||
BT_MBOX(1, MSG_TYPE, 16, 3),
|
||||
BT_MBOX(1, SSN, 19, 2),
|
||||
};
|
||||
|
||||
enum iwl_bt_mxbox_dw2 {
|
||||
BT_MBOX(2, SNIFF_ACT, 0, 3),
|
||||
BT_MBOX(2, PAG, 3, 1),
|
||||
BT_MBOX(2, INQUIRY, 4, 1),
|
||||
BT_MBOX(2, CONN, 5, 1),
|
||||
BT_MBOX(2, SNIFF_INTERVAL, 8, 5),
|
||||
BT_MBOX(2, DISC, 13, 1),
|
||||
BT_MBOX(2, SCO_TX_ACT, 16, 2),
|
||||
BT_MBOX(2, SCO_RX_ACT, 18, 2),
|
||||
BT_MBOX(2, ESCO_RE_TX, 20, 2),
|
||||
BT_MBOX(2, SCO_DURATION, 24, 6),
|
||||
};
|
||||
|
||||
enum iwl_bt_mxbox_dw3 {
|
||||
BT_MBOX(3, SCO_STATE, 0, 1),
|
||||
BT_MBOX(3, SNIFF_STATE, 1, 1),
|
||||
BT_MBOX(3, A2DP_STATE, 2, 1),
|
||||
BT_MBOX(3, ACL_STATE, 3, 1),
|
||||
BT_MBOX(3, MSTR_STATE, 4, 1),
|
||||
BT_MBOX(3, OBX_STATE, 5, 1),
|
||||
BT_MBOX(3, OPEN_CON_2, 8, 2),
|
||||
BT_MBOX(3, TRAFFIC_LOAD, 10, 2),
|
||||
BT_MBOX(3, CHL_SEQN_LSB, 12, 1),
|
||||
BT_MBOX(3, INBAND_P, 13, 1),
|
||||
BT_MBOX(3, MSG_TYPE_2, 16, 3),
|
||||
BT_MBOX(3, SSN_2, 19, 2),
|
||||
BT_MBOX(3, UPDATE_REQUEST, 21, 1),
|
||||
};
|
||||
|
||||
#define BT_MBOX_MSG(_notif, _num, _field) \
|
||||
((le32_to_cpu((_notif)->mbox_msg[(_num)]) & BT_MBOX##_num##_##_field)\
|
||||
>> BT_MBOX##_num##_##_field##_POS)
|
||||
|
||||
/**
|
||||
* struct iwl_bt_coex_profile_notif - notification about BT coex
|
||||
* @mbox_msg: message from BT to WiFi
|
||||
* @:bt_status: 0 - off, 1 - on
|
||||
* @:bt_open_conn: number of BT connections open
|
||||
* @:bt_traffic_load: load of BT traffic
|
||||
* @:bt_agg_traffic_load: aggregated load of BT traffic
|
||||
* @:bt_ci_compliance: 0 - no CI compliance, 1 - CI compliant
|
||||
*/
|
||||
struct iwl_bt_coex_profile_notif {
|
||||
__le32 mbox_msg[4];
|
||||
u8 bt_status;
|
||||
u8 bt_open_conn;
|
||||
u8 bt_traffic_load;
|
||||
u8 bt_agg_traffic_load;
|
||||
u8 bt_ci_compliance;
|
||||
u8 reserved[3];
|
||||
} __packed; /* BT_COEX_PROFILE_NTFY_API_S_VER_2 */
|
||||
|
||||
enum iwl_bt_coex_prio_table_event {
|
||||
BT_COEX_PRIO_TBL_EVT_INIT_CALIB1 = 0,
|
||||
BT_COEX_PRIO_TBL_EVT_INIT_CALIB2 = 1,
|
||||
BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_LOW1 = 2,
|
||||
BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_LOW2 = 3,
|
||||
BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_HIGH1 = 4,
|
||||
BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_HIGH2 = 5,
|
||||
BT_COEX_PRIO_TBL_EVT_DTIM = 6,
|
||||
BT_COEX_PRIO_TBL_EVT_SCAN52 = 7,
|
||||
BT_COEX_PRIO_TBL_EVT_SCAN24 = 8,
|
||||
BT_COEX_PRIO_TBL_EVT_IDLE = 9,
|
||||
BT_COEX_PRIO_TBL_EVT_MAX = 16,
|
||||
}; /* BT_COEX_PRIO_TABLE_EVENTS_API_E_VER_1 */
|
||||
|
||||
enum iwl_bt_coex_prio_table_prio {
|
||||
BT_COEX_PRIO_TBL_DISABLED = 0,
|
||||
BT_COEX_PRIO_TBL_PRIO_LOW = 1,
|
||||
BT_COEX_PRIO_TBL_PRIO_HIGH = 2,
|
||||
BT_COEX_PRIO_TBL_PRIO_BYPASS = 3,
|
||||
BT_COEX_PRIO_TBL_PRIO_COEX_OFF = 4,
|
||||
BT_COEX_PRIO_TBL_PRIO_COEX_ON = 5,
|
||||
BT_COEX_PRIO_TBL_PRIO_COEX_IDLE = 6,
|
||||
BT_COEX_PRIO_TBL_MAX = 8,
|
||||
}; /* BT_COEX_PRIO_TABLE_PRIORITIES_API_E_VER_1 */
|
||||
|
||||
#define BT_COEX_PRIO_TBL_SHRD_ANT_POS (0)
|
||||
#define BT_COEX_PRIO_TBL_PRIO_POS (1)
|
||||
#define BT_COEX_PRIO_TBL_RESERVED_POS (4)
|
||||
|
||||
/**
|
||||
* struct iwl_bt_coex_prio_tbl_cmd - priority table for BT coex
|
||||
* @prio_tbl:
|
||||
*/
|
||||
struct iwl_bt_coex_prio_tbl_cmd {
|
||||
u8 prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX];
|
||||
} __packed;
|
||||
|
||||
enum iwl_bt_coex_env_action {
|
||||
BT_COEX_ENV_CLOSE = 0,
|
||||
BT_COEX_ENV_OPEN = 1,
|
||||
}; /* BT_COEX_PROT_ENV_ACTION_API_E_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_bt_coex_prot_env_cmd - BT Protection Envelope
|
||||
* @action: enum %iwl_bt_coex_env_action
|
||||
* @type: enum %iwl_bt_coex_prio_table_event
|
||||
*/
|
||||
struct iwl_bt_coex_prot_env_cmd {
|
||||
u8 action; /* 0 = closed, 1 = open */
|
||||
u8 type; /* 0 .. 15 */
|
||||
u8 reserved[2];
|
||||
} __packed;
|
||||
|
||||
#endif /* __fw_api_bt_coex_h__ */
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
@ -258,7 +258,7 @@ enum iwl_wowlan_wakeup_reason {
|
||||
IWL_WOWLAN_WAKEUP_BY_FOUR_WAY_HANDSHAKE = BIT(8),
|
||||
IWL_WOWLAN_WAKEUP_BY_REM_WAKE_LINK_LOSS = BIT(9),
|
||||
IWL_WOWLAN_WAKEUP_BY_REM_WAKE_SIGNATURE_TABLE = BIT(10),
|
||||
IWL_WOWLAN_WAKEUP_BY_REM_WAKE_TCP_EXTERNAL = BIT(11),
|
||||
/* BIT(11) reserved */
|
||||
IWL_WOWLAN_WAKEUP_BY_REM_WAKE_WAKEUP_PACKET = BIT(12),
|
||||
}; /* WOWLAN_WAKE_UP_REASON_API_E_VER_2 */
|
||||
|
||||
@ -277,6 +277,55 @@ struct iwl_wowlan_status {
|
||||
u8 wake_packet[]; /* can be truncated from _length to _bufsize */
|
||||
} __packed; /* WOWLAN_STATUSES_API_S_VER_4 */
|
||||
|
||||
#define IWL_WOWLAN_TCP_MAX_PACKET_LEN 64
|
||||
#define IWL_WOWLAN_REMOTE_WAKE_MAX_PACKET_LEN 128
|
||||
#define IWL_WOWLAN_REMOTE_WAKE_MAX_TOKENS 2048
|
||||
|
||||
struct iwl_tcp_packet_info {
|
||||
__le16 tcp_pseudo_header_checksum;
|
||||
__le16 tcp_payload_length;
|
||||
} __packed; /* TCP_PACKET_INFO_API_S_VER_2 */
|
||||
|
||||
struct iwl_tcp_packet {
|
||||
struct iwl_tcp_packet_info info;
|
||||
u8 rx_mask[IWL_WOWLAN_MAX_PATTERN_LEN / 8];
|
||||
u8 data[IWL_WOWLAN_TCP_MAX_PACKET_LEN];
|
||||
} __packed; /* TCP_PROTOCOL_PACKET_API_S_VER_1 */
|
||||
|
||||
struct iwl_remote_wake_packet {
|
||||
struct iwl_tcp_packet_info info;
|
||||
u8 rx_mask[IWL_WOWLAN_MAX_PATTERN_LEN / 8];
|
||||
u8 data[IWL_WOWLAN_REMOTE_WAKE_MAX_PACKET_LEN];
|
||||
} __packed; /* TCP_PROTOCOL_PACKET_API_S_VER_1 */
|
||||
|
||||
struct iwl_wowlan_remote_wake_config {
|
||||
__le32 connection_max_time; /* unused */
|
||||
/* TCP_PROTOCOL_CONFIG_API_S_VER_1 */
|
||||
u8 max_syn_retries;
|
||||
u8 max_data_retries;
|
||||
u8 tcp_syn_ack_timeout;
|
||||
u8 tcp_ack_timeout;
|
||||
|
||||
struct iwl_tcp_packet syn_tx;
|
||||
struct iwl_tcp_packet synack_rx;
|
||||
struct iwl_tcp_packet keepalive_ack_rx;
|
||||
struct iwl_tcp_packet fin_tx;
|
||||
|
||||
struct iwl_remote_wake_packet keepalive_tx;
|
||||
struct iwl_remote_wake_packet wake_rx;
|
||||
|
||||
/* REMOTE_WAKE_OFFSET_INFO_API_S_VER_1 */
|
||||
u8 sequence_number_offset;
|
||||
u8 sequence_number_length;
|
||||
u8 token_offset;
|
||||
u8 token_length;
|
||||
/* REMOTE_WAKE_PROTOCOL_PARAMS_API_S_VER_1 */
|
||||
__le32 initial_sequence_number;
|
||||
__le16 keepalive_interval;
|
||||
__le16 num_tokens;
|
||||
u8 tokens[IWL_WOWLAN_REMOTE_WAKE_MAX_TOKENS];
|
||||
} __packed; /* REMOTE_WAKE_CONFIG_API_S_VER_2 */
|
||||
|
||||
/* TODO: NetDetect API */
|
||||
|
||||
#endif /* __fw_api_d3_h__ */
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
@ -70,6 +70,7 @@
|
||||
#include "fw-api-mac.h"
|
||||
#include "fw-api-power.h"
|
||||
#include "fw-api-d3.h"
|
||||
#include "fw-api-bt-coex.h"
|
||||
|
||||
/* queue and FIFO numbers by usage */
|
||||
enum {
|
||||
@ -152,6 +153,7 @@ enum {
|
||||
|
||||
BEACON_TEMPLATE_CMD = 0x91,
|
||||
TX_ANT_CONFIGURATION_CMD = 0x98,
|
||||
BT_CONFIG = 0x9b,
|
||||
STATISTICS_NOTIFICATION = 0x9d,
|
||||
|
||||
/* RF-KILL commands and notifications */
|
||||
@ -162,6 +164,11 @@ enum {
|
||||
REPLY_RX_MPDU_CMD = 0xc1,
|
||||
BA_NOTIF = 0xc5,
|
||||
|
||||
/* BT Coex */
|
||||
BT_COEX_PRIO_TABLE = 0xcc,
|
||||
BT_COEX_PROT_ENV = 0xcd,
|
||||
BT_PROFILE_NOTIFICATION = 0xce,
|
||||
|
||||
REPLY_DEBUG_CMD = 0xf0,
|
||||
DEBUG_LOG_MSG = 0xf7,
|
||||
|
||||
@ -762,18 +769,20 @@ struct iwl_phy_context_cmd {
|
||||
#define IWL_RX_INFO_PHY_CNT 8
|
||||
#define IWL_RX_INFO_AGC_IDX 1
|
||||
#define IWL_RX_INFO_RSSI_AB_IDX 2
|
||||
#define IWL_RX_INFO_RSSI_C_IDX 3
|
||||
#define IWL_OFDM_AGC_DB_MSK 0xfe00
|
||||
#define IWL_OFDM_AGC_DB_POS 9
|
||||
#define IWL_OFDM_AGC_A_MSK 0x0000007f
|
||||
#define IWL_OFDM_AGC_A_POS 0
|
||||
#define IWL_OFDM_AGC_B_MSK 0x00003f80
|
||||
#define IWL_OFDM_AGC_B_POS 7
|
||||
#define IWL_OFDM_AGC_CODE_MSK 0x3fe00000
|
||||
#define IWL_OFDM_AGC_CODE_POS 20
|
||||
#define IWL_OFDM_RSSI_INBAND_A_MSK 0x00ff
|
||||
#define IWL_OFDM_RSSI_ALLBAND_A_MSK 0xff00
|
||||
#define IWL_OFDM_RSSI_A_POS 0
|
||||
#define IWL_OFDM_RSSI_ALLBAND_A_MSK 0xff00
|
||||
#define IWL_OFDM_RSSI_ALLBAND_A_POS 8
|
||||
#define IWL_OFDM_RSSI_INBAND_B_MSK 0xff0000
|
||||
#define IWL_OFDM_RSSI_ALLBAND_B_MSK 0xff000000
|
||||
#define IWL_OFDM_RSSI_B_POS 16
|
||||
#define IWL_OFDM_RSSI_INBAND_C_MSK 0x00ff
|
||||
#define IWL_OFDM_RSSI_ALLBAND_C_MSK 0xff00
|
||||
#define IWL_OFDM_RSSI_C_POS 0
|
||||
#define IWL_OFDM_RSSI_ALLBAND_B_MSK 0xff000000
|
||||
#define IWL_OFDM_RSSI_ALLBAND_B_POS 24
|
||||
|
||||
/**
|
||||
* struct iwl_rx_phy_info - phy info
|
||||
@ -792,6 +801,7 @@ struct iwl_phy_context_cmd {
|
||||
* @byte_count: frame's byte-count
|
||||
* @frame_time: frame's time on the air, based on byte count and frame rate
|
||||
* calculation
|
||||
* @mac_active_msk: what MACs were active when the frame was received
|
||||
*
|
||||
* Before each Rx, the device sends this data. It contains PHY information
|
||||
* about the reception of the packet.
|
||||
@ -809,7 +819,7 @@ struct iwl_rx_phy_info {
|
||||
__le32 non_cfg_phy[IWL_RX_INFO_PHY_CNT];
|
||||
__le32 rate_n_flags;
|
||||
__le32 byte_count;
|
||||
__le16 reserved2;
|
||||
__le16 mac_active_msk;
|
||||
__le16 frame_time;
|
||||
} __packed;
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
@ -79,17 +79,8 @@
|
||||
#define UCODE_VALID_OK cpu_to_le32(0x1)
|
||||
|
||||
/* Default calibration values for WkP - set to INIT image w/o running */
|
||||
static const u8 wkp_calib_values_bb_filter[] = { 0xbf, 0x00, 0x5f, 0x00, 0x2f,
|
||||
0x00, 0x18, 0x00 };
|
||||
static const u8 wkp_calib_values_rx_dc[] = { 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
|
||||
0x7f, 0x7f, 0x7f };
|
||||
static const u8 wkp_calib_values_tx_lo[] = { 0x00, 0x00, 0x00, 0x00 };
|
||||
static const u8 wkp_calib_values_tx_iq[] = { 0xff, 0x00, 0xff, 0x00, 0x00,
|
||||
0x00 };
|
||||
static const u8 wkp_calib_values_rx_iq[] = { 0xff, 0x00, 0x00, 0x00 };
|
||||
static const u8 wkp_calib_values_rx_iq_skew[] = { 0x00, 0x00, 0x01, 0x00 };
|
||||
static const u8 wkp_calib_values_tx_iq_skew[] = { 0x01, 0x00, 0x00, 0x00 };
|
||||
static const u8 wkp_calib_values_xtal[] = { 0xd2, 0xd2 };
|
||||
|
||||
struct iwl_calib_default_data {
|
||||
u16 size;
|
||||
@ -99,12 +90,7 @@ struct iwl_calib_default_data {
|
||||
#define CALIB_SIZE_N_DATA(_buf) {.size = sizeof(_buf), .data = &_buf}
|
||||
|
||||
static const struct iwl_calib_default_data wkp_calib_default_data[12] = {
|
||||
[5] = CALIB_SIZE_N_DATA(wkp_calib_values_rx_dc),
|
||||
[6] = CALIB_SIZE_N_DATA(wkp_calib_values_bb_filter),
|
||||
[7] = CALIB_SIZE_N_DATA(wkp_calib_values_tx_lo),
|
||||
[8] = CALIB_SIZE_N_DATA(wkp_calib_values_tx_iq),
|
||||
[9] = CALIB_SIZE_N_DATA(wkp_calib_values_tx_iq_skew),
|
||||
[10] = CALIB_SIZE_N_DATA(wkp_calib_values_rx_iq),
|
||||
[11] = CALIB_SIZE_N_DATA(wkp_calib_values_rx_iq_skew),
|
||||
};
|
||||
|
||||
@ -241,20 +227,6 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
|
||||
|
||||
return 0;
|
||||
}
|
||||
#define IWL_HW_REV_ID_RAINBOW 0x2
|
||||
#define IWL_PROJ_TYPE_LHP 0x5
|
||||
|
||||
static u32 iwl_mvm_build_phy_cfg(struct iwl_mvm *mvm)
|
||||
{
|
||||
struct iwl_nvm_data *data = mvm->nvm_data;
|
||||
/* Temp calls to static definitions, will be changed to CSR calls */
|
||||
u8 hw_rev_id = IWL_HW_REV_ID_RAINBOW;
|
||||
u8 project_type = IWL_PROJ_TYPE_LHP;
|
||||
|
||||
return data->radio_cfg_dash | (data->radio_cfg_step << 2) |
|
||||
(hw_rev_id << 4) | ((project_type & 0x7f) << 6) |
|
||||
(data->valid_tx_ant << 16) | (data->valid_rx_ant << 20);
|
||||
}
|
||||
|
||||
static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
|
||||
{
|
||||
@ -262,7 +234,7 @@ static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
|
||||
enum iwl_ucode_type ucode_type = mvm->cur_ucode;
|
||||
|
||||
/* Set parameters */
|
||||
phy_cfg_cmd.phy_cfg = cpu_to_le32(iwl_mvm_build_phy_cfg(mvm));
|
||||
phy_cfg_cmd.phy_cfg = cpu_to_le32(mvm->fw->phy_config);
|
||||
phy_cfg_cmd.calib_control.event_trigger =
|
||||
mvm->fw->default_calib[ucode_type].event_trigger;
|
||||
phy_cfg_cmd.calib_control.flow_trigger =
|
||||
@ -275,103 +247,6 @@ static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
|
||||
sizeof(phy_cfg_cmd), &phy_cfg_cmd);
|
||||
}
|
||||
|
||||
/* Starting with the new PHY DB implementation - New calibs are enabled */
|
||||
/* Value - 0x405e7 */
|
||||
#define IWL_CALIB_DEFAULT_FLOW_INIT (IWL_CALIB_CFG_XTAL_IDX |\
|
||||
IWL_CALIB_CFG_TEMPERATURE_IDX |\
|
||||
IWL_CALIB_CFG_VOLTAGE_READ_IDX |\
|
||||
IWL_CALIB_CFG_DC_IDX |\
|
||||
IWL_CALIB_CFG_BB_FILTER_IDX |\
|
||||
IWL_CALIB_CFG_LO_LEAKAGE_IDX |\
|
||||
IWL_CALIB_CFG_TX_IQ_IDX |\
|
||||
IWL_CALIB_CFG_RX_IQ_IDX |\
|
||||
IWL_CALIB_CFG_AGC_IDX)
|
||||
|
||||
#define IWL_CALIB_DEFAULT_EVENT_INIT 0x0
|
||||
|
||||
/* Value 0x41567 */
|
||||
#define IWL_CALIB_DEFAULT_FLOW_RUN (IWL_CALIB_CFG_XTAL_IDX |\
|
||||
IWL_CALIB_CFG_TEMPERATURE_IDX |\
|
||||
IWL_CALIB_CFG_VOLTAGE_READ_IDX |\
|
||||
IWL_CALIB_CFG_BB_FILTER_IDX |\
|
||||
IWL_CALIB_CFG_DC_IDX |\
|
||||
IWL_CALIB_CFG_TX_IQ_IDX |\
|
||||
IWL_CALIB_CFG_RX_IQ_IDX |\
|
||||
IWL_CALIB_CFG_SENSITIVITY_IDX |\
|
||||
IWL_CALIB_CFG_AGC_IDX)
|
||||
|
||||
#define IWL_CALIB_DEFAULT_EVENT_RUN (IWL_CALIB_CFG_XTAL_IDX |\
|
||||
IWL_CALIB_CFG_TEMPERATURE_IDX |\
|
||||
IWL_CALIB_CFG_VOLTAGE_READ_IDX |\
|
||||
IWL_CALIB_CFG_TX_PWR_IDX |\
|
||||
IWL_CALIB_CFG_DC_IDX |\
|
||||
IWL_CALIB_CFG_TX_IQ_IDX |\
|
||||
IWL_CALIB_CFG_SENSITIVITY_IDX)
|
||||
|
||||
/*
|
||||
* Sets the calibrations trigger values that will be sent to the FW for runtime
|
||||
* and init calibrations.
|
||||
* The ones given in the FW TLV are not correct.
|
||||
*/
|
||||
static void iwl_set_default_calib_trigger(struct iwl_mvm *mvm)
|
||||
{
|
||||
struct iwl_tlv_calib_ctrl default_calib;
|
||||
|
||||
/*
|
||||
* WkP FW TLV calib bits are wrong, overwrite them.
|
||||
* This defines the dynamic calibrations which are implemented in the
|
||||
* uCode both for init(flow) calculation and event driven calibs.
|
||||
*/
|
||||
|
||||
/* Init Image */
|
||||
default_calib.event_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_EVENT_INIT);
|
||||
default_calib.flow_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_FLOW_INIT);
|
||||
|
||||
if (default_calib.event_trigger !=
|
||||
mvm->fw->default_calib[IWL_UCODE_INIT].event_trigger)
|
||||
IWL_ERR(mvm,
|
||||
"Updating the event calib for INIT image: 0x%x -> 0x%x\n",
|
||||
mvm->fw->default_calib[IWL_UCODE_INIT].event_trigger,
|
||||
default_calib.event_trigger);
|
||||
if (default_calib.flow_trigger !=
|
||||
mvm->fw->default_calib[IWL_UCODE_INIT].flow_trigger)
|
||||
IWL_ERR(mvm,
|
||||
"Updating the flow calib for INIT image: 0x%x -> 0x%x\n",
|
||||
mvm->fw->default_calib[IWL_UCODE_INIT].flow_trigger,
|
||||
default_calib.flow_trigger);
|
||||
|
||||
memcpy((void *)&mvm->fw->default_calib[IWL_UCODE_INIT],
|
||||
&default_calib, sizeof(struct iwl_tlv_calib_ctrl));
|
||||
IWL_ERR(mvm,
|
||||
"Setting uCode init calibrations event 0x%x, trigger 0x%x\n",
|
||||
default_calib.event_trigger,
|
||||
default_calib.flow_trigger);
|
||||
|
||||
/* Run time image */
|
||||
default_calib.event_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_EVENT_RUN);
|
||||
default_calib.flow_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_FLOW_RUN);
|
||||
|
||||
if (default_calib.event_trigger !=
|
||||
mvm->fw->default_calib[IWL_UCODE_REGULAR].event_trigger)
|
||||
IWL_ERR(mvm,
|
||||
"Updating the event calib for RT image: 0x%x -> 0x%x\n",
|
||||
mvm->fw->default_calib[IWL_UCODE_REGULAR].event_trigger,
|
||||
default_calib.event_trigger);
|
||||
if (default_calib.flow_trigger !=
|
||||
mvm->fw->default_calib[IWL_UCODE_REGULAR].flow_trigger)
|
||||
IWL_ERR(mvm,
|
||||
"Updating the flow calib for RT image: 0x%x -> 0x%x\n",
|
||||
mvm->fw->default_calib[IWL_UCODE_REGULAR].flow_trigger,
|
||||
default_calib.flow_trigger);
|
||||
|
||||
memcpy((void *)&mvm->fw->default_calib[IWL_UCODE_REGULAR],
|
||||
&default_calib, sizeof(struct iwl_tlv_calib_ctrl));
|
||||
IWL_ERR(mvm,
|
||||
"Setting uCode runtime calibs event 0x%x, trigger 0x%x\n",
|
||||
default_calib.event_trigger,
|
||||
default_calib.flow_trigger);
|
||||
}
|
||||
|
||||
static int iwl_set_default_calibrations(struct iwl_mvm *mvm)
|
||||
{
|
||||
u8 cmd_raw[16]; /* holds the variable size commands */
|
||||
@ -434,6 +309,10 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = iwl_send_bt_prio_tbl(mvm);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
if (read_nvm) {
|
||||
/* Read nvm */
|
||||
ret = iwl_nvm_init(mvm);
|
||||
@ -446,8 +325,10 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
|
||||
ret = iwl_nvm_check_version(mvm->nvm_data, mvm->trans);
|
||||
WARN_ON(ret);
|
||||
|
||||
/* Override the calibrations from TLV and the const of fw */
|
||||
iwl_set_default_calib_trigger(mvm);
|
||||
/* Send TX valid antennas before triggering calibrations */
|
||||
ret = iwl_send_tx_ant_cfg(mvm, mvm->nvm_data->valid_tx_ant);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* WkP doesn't have all calibrations, need to set default values */
|
||||
if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
|
||||
@ -537,6 +418,14 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
ret = iwl_send_bt_prio_tbl(mvm);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
ret = iwl_send_bt_init_conf(mvm);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* Send phy db control command and then phy db calibration*/
|
||||
ret = iwl_send_phy_db_data(mvm->phy_db);
|
||||
if (ret)
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
@ -553,9 +553,9 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
|
||||
if (vif->bss_conf.qos)
|
||||
cmd->qos_flags |= cpu_to_le32(MAC_QOS_FLG_UPDATE_EDCA);
|
||||
|
||||
/* Don't use cts to self as the fw doesn't support it currently. */
|
||||
if (vif->bss_conf.use_cts_prot)
|
||||
cmd->protection_flags |= cpu_to_le32(MAC_PROT_FLG_TGG_PROTECT |
|
||||
MAC_PROT_FLG_SELF_CTS_EN);
|
||||
cmd->protection_flags |= cpu_to_le32(MAC_PROT_FLG_TGG_PROTECT);
|
||||
|
||||
/*
|
||||
* I think that we should enable these 2 flags regardless the HT PROT
|
||||
@ -651,6 +651,13 @@ static int iwl_mvm_mac_ctxt_cmd_station(struct iwl_mvm *mvm,
|
||||
/* Fill the common data for all mac context types */
|
||||
iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
|
||||
|
||||
/* Allow beacons to pass through as long as we are not associated,or we
|
||||
* do not have dtim period information */
|
||||
if (!vif->bss_conf.assoc || !vif->bss_conf.dtim_period)
|
||||
cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_BEACON);
|
||||
else
|
||||
cmd.filter_flags &= ~cpu_to_le32(MAC_FILTER_IN_BEACON);
|
||||
|
||||
/* Fill the data specific for station mode */
|
||||
iwl_mvm_mac_ctxt_cmd_fill_sta(mvm, vif, &cmd.sta);
|
||||
|
||||
@ -714,7 +721,9 @@ static int iwl_mvm_mac_ctxt_cmd_p2p_device(struct iwl_mvm *mvm,
|
||||
iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
|
||||
|
||||
cmd.protection_flags |= cpu_to_le32(MAC_PROT_FLG_TGG_PROTECT);
|
||||
cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROMISC);
|
||||
|
||||
/* Override the filter flags to accept only probe requests */
|
||||
cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST);
|
||||
|
||||
/*
|
||||
* This flag should be set to true when the P2P Device is
|
||||
@ -846,10 +855,10 @@ int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm,
|
||||
*/
|
||||
static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct iwl_mac_data_ap *ctxt_ap)
|
||||
struct iwl_mac_data_ap *ctxt_ap,
|
||||
bool add)
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
u32 curr_dev_time;
|
||||
|
||||
ctxt_ap->bi = cpu_to_le32(vif->bss_conf.beacon_int);
|
||||
ctxt_ap->bi_reciprocal =
|
||||
@ -861,10 +870,19 @@ static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm,
|
||||
vif->bss_conf.dtim_period));
|
||||
|
||||
ctxt_ap->mcast_qid = cpu_to_le32(vif->cab_queue);
|
||||
curr_dev_time = iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG);
|
||||
ctxt_ap->beacon_time = cpu_to_le32(curr_dev_time);
|
||||
|
||||
ctxt_ap->beacon_tsf = cpu_to_le64(curr_dev_time);
|
||||
/*
|
||||
* Only read the system time when the MAC is being added, when we
|
||||
* just modify the MAC then we should keep the time -- the firmware
|
||||
* can otherwise have a "jumping" TBTT.
|
||||
*/
|
||||
if (add)
|
||||
mvmvif->ap_beacon_time =
|
||||
iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG);
|
||||
|
||||
ctxt_ap->beacon_time = cpu_to_le32(mvmvif->ap_beacon_time);
|
||||
|
||||
ctxt_ap->beacon_tsf = 0; /* unused */
|
||||
|
||||
/* TODO: Assume that the beacon id == mac context id */
|
||||
ctxt_ap->beacon_template = cpu_to_le32(mvmvif->id);
|
||||
@ -881,8 +899,12 @@ static int iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm *mvm,
|
||||
/* Fill the common data for all mac context types */
|
||||
iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
|
||||
|
||||
/* Also enable probe requests to pass */
|
||||
cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST);
|
||||
|
||||
/* Fill the data specific for ap mode */
|
||||
iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.ap);
|
||||
iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.ap,
|
||||
action == FW_CTXT_ACTION_ADD);
|
||||
|
||||
return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
|
||||
}
|
||||
@ -899,7 +921,8 @@ static int iwl_mvm_mac_ctxt_cmd_go(struct iwl_mvm *mvm,
|
||||
iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
|
||||
|
||||
/* Fill the data specific for GO mode */
|
||||
iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.go.ap);
|
||||
iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.go.ap,
|
||||
action == FW_CTXT_ACTION_ADD);
|
||||
|
||||
cmd.go.ctwin = cpu_to_le32(vif->bss_conf.p2p_ctwindow);
|
||||
cmd.go.opp_ps_enabled = cpu_to_le32(!!vif->bss_conf.p2p_oppps);
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
@ -65,7 +65,9 @@
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/ip.h>
|
||||
#include <net/mac80211.h>
|
||||
#include <net/tcp.h>
|
||||
|
||||
#include "iwl-op-mode.h"
|
||||
#include "iwl-io.h"
|
||||
@ -102,10 +104,33 @@ static const struct ieee80211_iface_combination iwl_mvm_iface_combinations[] = {
|
||||
},
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static const struct nl80211_wowlan_tcp_data_token_feature
|
||||
iwl_mvm_wowlan_tcp_token_feature = {
|
||||
.min_len = 0,
|
||||
.max_len = 255,
|
||||
.bufsize = IWL_WOWLAN_REMOTE_WAKE_MAX_TOKENS,
|
||||
};
|
||||
|
||||
static const struct wiphy_wowlan_tcp_support iwl_mvm_wowlan_tcp_support = {
|
||||
.tok = &iwl_mvm_wowlan_tcp_token_feature,
|
||||
.data_payload_max = IWL_WOWLAN_TCP_MAX_PACKET_LEN -
|
||||
sizeof(struct ethhdr) -
|
||||
sizeof(struct iphdr) -
|
||||
sizeof(struct tcphdr),
|
||||
.data_interval_max = 65535, /* __le16 in API */
|
||||
.wake_payload_max = IWL_WOWLAN_REMOTE_WAKE_MAX_PACKET_LEN -
|
||||
sizeof(struct ethhdr) -
|
||||
sizeof(struct iphdr) -
|
||||
sizeof(struct tcphdr),
|
||||
.seq = true,
|
||||
};
|
||||
#endif
|
||||
|
||||
int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
|
||||
{
|
||||
struct ieee80211_hw *hw = mvm->hw;
|
||||
int num_mac, ret;
|
||||
int num_mac, ret, i;
|
||||
|
||||
/* Tell mac80211 our characteristics */
|
||||
hw->flags = IEEE80211_HW_SIGNAL_DBM |
|
||||
@ -156,11 +181,15 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
|
||||
memcpy(mvm->addresses[0].addr, mvm->nvm_data->hw_addr, ETH_ALEN);
|
||||
hw->wiphy->addresses = mvm->addresses;
|
||||
hw->wiphy->n_addresses = 1;
|
||||
num_mac = mvm->nvm_data->n_hw_addrs;
|
||||
if (num_mac > 1) {
|
||||
memcpy(mvm->addresses[1].addr, mvm->addresses[0].addr,
|
||||
|
||||
/* Extract additional MAC addresses if available */
|
||||
num_mac = (mvm->nvm_data->n_hw_addrs > 1) ?
|
||||
min(IWL_MVM_MAX_ADDRESSES, mvm->nvm_data->n_hw_addrs) : 1;
|
||||
|
||||
for (i = 1; i < num_mac; i++) {
|
||||
memcpy(mvm->addresses[i].addr, mvm->addresses[i-1].addr,
|
||||
ETH_ALEN);
|
||||
mvm->addresses[1].addr[5]++;
|
||||
mvm->addresses[i].addr[5]++;
|
||||
hw->wiphy->n_addresses++;
|
||||
}
|
||||
|
||||
@ -206,6 +235,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
|
||||
hw->wiphy->wowlan.n_patterns = IWL_WOWLAN_MAX_PATTERNS;
|
||||
hw->wiphy->wowlan.pattern_min_len = IWL_WOWLAN_MIN_PATTERN_LEN;
|
||||
hw->wiphy->wowlan.pattern_max_len = IWL_WOWLAN_MAX_PATTERN_LEN;
|
||||
hw->wiphy->wowlan.tcp = &iwl_mvm_wowlan_tcp_support;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -273,12 +303,18 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
|
||||
ret = iwl_mvm_sta_rx_agg(mvm, sta, tid, 0, false);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_START:
|
||||
if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
ret = iwl_mvm_sta_tx_agg_start(mvm, vif, sta, tid, ssn);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_STOP_CONT:
|
||||
ret = iwl_mvm_sta_tx_agg_stop(mvm, vif, sta, tid);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH:
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
|
||||
ret = iwl_mvm_sta_tx_agg_stop(mvm, vif, sta, tid);
|
||||
ret = iwl_mvm_sta_tx_agg_flush(mvm, vif, sta, tid);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_OPERATIONAL:
|
||||
ret = iwl_mvm_sta_tx_agg_oper(mvm, vif, sta, tid, buf_size);
|
||||
@ -557,11 +593,9 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
static void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
u32 tfd_msk = 0, ac;
|
||||
|
||||
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
|
||||
@ -594,12 +628,21 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
|
||||
*/
|
||||
flush_work(&mvm->sta_drained_wk);
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
iwl_mvm_prepare_mac_removal(mvm, vif);
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
|
||||
/*
|
||||
* For AP/GO interface, the tear down of the resources allocated to the
|
||||
* interface should be handled as part of the bss_info_changed flow.
|
||||
* interface is be handled as part of the stop_ap flow.
|
||||
*/
|
||||
if (vif->type == NL80211_IFTYPE_AP) {
|
||||
iwl_mvm_dealloc_int_sta(mvm, &mvmvif->bcast_sta);
|
||||
@ -763,6 +806,8 @@ static void iwl_mvm_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
iwl_mvm_prepare_mac_removal(mvm, vif);
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
|
||||
mvmvif->ap_active = false;
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
@ -79,8 +79,9 @@
|
||||
#include "fw-api.h"
|
||||
|
||||
#define IWL_INVALID_MAC80211_QUEUE 0xff
|
||||
#define IWL_MVM_MAX_ADDRESSES 2
|
||||
#define IWL_RSSI_OFFSET 44
|
||||
#define IWL_MVM_MAX_ADDRESSES 5
|
||||
/* RSSI offset for WkP */
|
||||
#define IWL_RSSI_OFFSET 50
|
||||
|
||||
enum iwl_mvm_tx_fifo {
|
||||
IWL_MVM_TX_FIFO_BK = 0,
|
||||
@ -173,6 +174,8 @@ struct iwl_mvm_vif {
|
||||
bool uploaded;
|
||||
bool ap_active;
|
||||
|
||||
u32 ap_beacon_time;
|
||||
|
||||
enum iwl_tsf_id tsf_id;
|
||||
|
||||
/*
|
||||
@ -327,6 +330,14 @@ struct iwl_mvm {
|
||||
struct led_classdev led;
|
||||
|
||||
struct ieee80211_vif *p2p_device_vif;
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
int gtk_ivlen, gtk_icvlen, ptk_ivlen, ptk_icvlen;
|
||||
#endif
|
||||
|
||||
/* BT-Coex */
|
||||
u8 bt_kill_msk;
|
||||
struct iwl_bt_coex_profile_notif last_bt_notif;
|
||||
};
|
||||
|
||||
/* Extract MVM priv from op_mode and _hw */
|
||||
@ -497,4 +508,11 @@ void iwl_mvm_ipv6_addr_change(struct ieee80211_hw *hw,
|
||||
void iwl_mvm_set_default_unicast_key(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif, int idx);
|
||||
|
||||
/* BT Coex */
|
||||
int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm);
|
||||
int iwl_send_bt_init_conf(struct iwl_mvm *mvm);
|
||||
int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd);
|
||||
|
||||
#endif /* __IWL_MVM_H__ */
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
@ -74,6 +74,9 @@ static const int nvm_to_read[] = {
|
||||
NVM_SECTION_TYPE_PRODUCTION,
|
||||
};
|
||||
|
||||
/* Default NVM size to read */
|
||||
#define IWL_NVM_DEFAULT_CHUNK_SIZE (2*1024);
|
||||
|
||||
/* used to simplify the shared operations on NCM_ACCESS_CMD versions */
|
||||
union iwl_nvm_access_cmd {
|
||||
struct iwl_nvm_access_cmd_ver1 ver1;
|
||||
@ -193,9 +196,9 @@ static int iwl_nvm_read_section(struct iwl_mvm *mvm, u16 section,
|
||||
int ret;
|
||||
bool old_eeprom = mvm->cfg->device_family != IWL_DEVICE_FAMILY_7000;
|
||||
|
||||
length = (iwlwifi_mod_params.amsdu_size_8K ? (8 * 1024) : (4 * 1024))
|
||||
- sizeof(union iwl_nvm_access_cmd)
|
||||
- sizeof(struct iwl_rx_packet);
|
||||
/* Set nvm section read length */
|
||||
length = IWL_NVM_DEFAULT_CHUNK_SIZE;
|
||||
|
||||
/*
|
||||
* if length is greater than EEPROM size, truncate it because uCode
|
||||
* doesn't check it by itself, and exit the loop when reached.
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
@ -230,6 +230,8 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
|
||||
RX_HANDLER(SCAN_REQUEST_CMD, iwl_mvm_rx_scan_response, false),
|
||||
RX_HANDLER(SCAN_COMPLETE_NOTIFICATION, iwl_mvm_rx_scan_complete, false),
|
||||
|
||||
RX_HANDLER(BT_PROFILE_NOTIFICATION, iwl_mvm_rx_bt_coex_notif, true),
|
||||
|
||||
RX_HANDLER(RADIO_VERSION_NOTIFICATION, iwl_mvm_rx_radio_ver, false),
|
||||
RX_HANDLER(CARD_STATE_NOTIFICATION, iwl_mvm_rx_card_state_notif, false),
|
||||
|
||||
@ -293,6 +295,11 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = {
|
||||
CMD(NET_DETECT_PROFILES_CMD),
|
||||
CMD(NET_DETECT_HOTSPOTS_CMD),
|
||||
CMD(NET_DETECT_HOTSPOTS_QUERY_CMD),
|
||||
CMD(CARD_STATE_NOTIFICATION),
|
||||
CMD(BT_COEX_PRIO_TABLE),
|
||||
CMD(BT_COEX_PROT_ENV),
|
||||
CMD(BT_PROFILE_NOTIFICATION),
|
||||
CMD(BT_CONFIG),
|
||||
};
|
||||
#undef CMD
|
||||
|
||||
@ -363,8 +370,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds);
|
||||
trans_cfg.rx_buf_size_8k = iwlwifi_mod_params.amsdu_size_8K;
|
||||
|
||||
/* TODO: this should really be a TLV */
|
||||
if (cfg->device_family == IWL_DEVICE_FAMILY_7000)
|
||||
if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DW_BC_TABLE)
|
||||
trans_cfg.bc_table_dword = true;
|
||||
|
||||
if (!iwlwifi_mod_params.wd_disable)
|
||||
@ -624,12 +630,8 @@ static void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
|
||||
ieee80211_free_txskb(mvm->hw, skb);
|
||||
}
|
||||
|
||||
static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode)
|
||||
static void iwl_mvm_nic_restart(struct iwl_mvm *mvm)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
|
||||
|
||||
iwl_mvm_dump_nic_error_log(mvm);
|
||||
|
||||
iwl_abort_notification_waits(&mvm->notif_wait);
|
||||
|
||||
/*
|
||||
@ -663,9 +665,21 @@ static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode)
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
|
||||
|
||||
iwl_mvm_dump_nic_error_log(mvm);
|
||||
|
||||
iwl_mvm_nic_restart(mvm);
|
||||
}
|
||||
|
||||
static void iwl_mvm_cmd_queue_full(struct iwl_op_mode *op_mode)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
|
||||
|
||||
WARN_ON(1);
|
||||
iwl_mvm_nic_restart(mvm);
|
||||
}
|
||||
|
||||
static const struct iwl_op_mode_ops iwl_mvm_ops = {
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
|
@ -680,12 +680,14 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags,
|
||||
*/
|
||||
static bool rs_use_green(struct ieee80211_sta *sta)
|
||||
{
|
||||
struct iwl_mvm_sta *sta_priv = (void *)sta->drv_priv;
|
||||
|
||||
bool use_green = !(sta_priv->vif->bss_conf.ht_operation_mode &
|
||||
IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
|
||||
|
||||
return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) && use_green;
|
||||
/*
|
||||
* There's a bug somewhere in this code that causes the
|
||||
* scaling to get stuck because GF+SGI can't be combined
|
||||
* in SISO rates. Until we find that bug, disable GF, it
|
||||
* has only limited benefit and we still interoperate with
|
||||
* GF APs since we can always receive GF transmissions.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
@ -131,33 +131,42 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,
|
||||
static int iwl_mvm_calc_rssi(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_phy_info *phy_info)
|
||||
{
|
||||
u32 rssi_a, rssi_b, rssi_c, max_rssi, agc_db;
|
||||
int rssi_a, rssi_b, rssi_a_dbm, rssi_b_dbm, max_rssi_dbm;
|
||||
int rssi_all_band_a, rssi_all_band_b;
|
||||
u32 agc_a, agc_b, max_agc;
|
||||
u32 val;
|
||||
|
||||
/* Find max rssi among 3 possible receivers.
|
||||
/* Find max rssi among 2 possible receivers.
|
||||
* These values are measured by the Digital Signal Processor (DSP).
|
||||
* They should stay fairly constant even as the signal strength varies,
|
||||
* if the radio's Automatic Gain Control (AGC) is working right.
|
||||
* AGC value (see below) will provide the "interesting" info.
|
||||
*/
|
||||
val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_AGC_IDX]);
|
||||
agc_a = (val & IWL_OFDM_AGC_A_MSK) >> IWL_OFDM_AGC_A_POS;
|
||||
agc_b = (val & IWL_OFDM_AGC_B_MSK) >> IWL_OFDM_AGC_B_POS;
|
||||
max_agc = max_t(u32, agc_a, agc_b);
|
||||
|
||||
val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_RSSI_AB_IDX]);
|
||||
rssi_a = (val & IWL_OFDM_RSSI_INBAND_A_MSK) >> IWL_OFDM_RSSI_A_POS;
|
||||
rssi_b = (val & IWL_OFDM_RSSI_INBAND_B_MSK) >> IWL_OFDM_RSSI_B_POS;
|
||||
val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_RSSI_C_IDX]);
|
||||
rssi_c = (val & IWL_OFDM_RSSI_INBAND_C_MSK) >> IWL_OFDM_RSSI_C_POS;
|
||||
rssi_all_band_a = (val & IWL_OFDM_RSSI_ALLBAND_A_MSK) >>
|
||||
IWL_OFDM_RSSI_ALLBAND_A_POS;
|
||||
rssi_all_band_b = (val & IWL_OFDM_RSSI_ALLBAND_B_MSK) >>
|
||||
IWL_OFDM_RSSI_ALLBAND_B_POS;
|
||||
|
||||
val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_AGC_IDX]);
|
||||
agc_db = (val & IWL_OFDM_AGC_DB_MSK) >> IWL_OFDM_AGC_DB_POS;
|
||||
/*
|
||||
* dBm = rssi dB - agc dB - constant.
|
||||
* Higher AGC (higher radio gain) means lower signal.
|
||||
*/
|
||||
rssi_a_dbm = rssi_a - IWL_RSSI_OFFSET - agc_a;
|
||||
rssi_b_dbm = rssi_b - IWL_RSSI_OFFSET - agc_b;
|
||||
max_rssi_dbm = max_t(int, rssi_a_dbm, rssi_b_dbm);
|
||||
|
||||
max_rssi = max_t(u32, rssi_a, rssi_b);
|
||||
max_rssi = max_t(u32, max_rssi, rssi_c);
|
||||
IWL_DEBUG_STATS(mvm, "Rssi In A %d B %d Max %d AGCA %d AGCB %d\n",
|
||||
rssi_a_dbm, rssi_b_dbm, max_rssi_dbm, agc_a, agc_b);
|
||||
|
||||
IWL_DEBUG_STATS(mvm, "Rssi In A %d B %d C %d Max %d AGC dB %d\n",
|
||||
rssi_a, rssi_b, rssi_c, max_rssi, agc_db);
|
||||
|
||||
/* dBm = max_rssi dB - agc dB - constant.
|
||||
* Higher AGC (higher radio gain) means lower signal. */
|
||||
return max_rssi - agc_db - IWL_RSSI_OFFSET;
|
||||
return max_rssi_dbm;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
@ -101,8 +101,55 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
||||
}
|
||||
add_sta_cmd.add_modify = update ? 1 : 0;
|
||||
|
||||
/* STA_FLG_FAT_EN_MSK ? */
|
||||
/* STA_FLG_MIMO_EN_MSK ? */
|
||||
add_sta_cmd.station_flags_msk |= cpu_to_le32(STA_FLG_FAT_EN_MSK |
|
||||
STA_FLG_MIMO_EN_MSK);
|
||||
|
||||
switch (sta->bandwidth) {
|
||||
case IEEE80211_STA_RX_BW_160:
|
||||
add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_FAT_EN_160MHZ);
|
||||
/* fall through */
|
||||
case IEEE80211_STA_RX_BW_80:
|
||||
add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_FAT_EN_80MHZ);
|
||||
/* fall through */
|
||||
case IEEE80211_STA_RX_BW_40:
|
||||
add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_FAT_EN_40MHZ);
|
||||
/* fall through */
|
||||
case IEEE80211_STA_RX_BW_20:
|
||||
if (sta->ht_cap.ht_supported)
|
||||
add_sta_cmd.station_flags |=
|
||||
cpu_to_le32(STA_FLG_FAT_EN_20MHZ);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (sta->rx_nss) {
|
||||
case 1:
|
||||
add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_MIMO_EN_SISO);
|
||||
break;
|
||||
case 2:
|
||||
add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_MIMO_EN_MIMO2);
|
||||
break;
|
||||
case 3 ... 8:
|
||||
add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_MIMO_EN_MIMO3);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (sta->smps_mode) {
|
||||
case IEEE80211_SMPS_AUTOMATIC:
|
||||
case IEEE80211_SMPS_NUM_MODES:
|
||||
WARN_ON(1);
|
||||
break;
|
||||
case IEEE80211_SMPS_STATIC:
|
||||
/* override NSS */
|
||||
add_sta_cmd.station_flags &= ~cpu_to_le32(STA_FLG_MIMO_EN_MSK);
|
||||
add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_MIMO_EN_SISO);
|
||||
break;
|
||||
case IEEE80211_SMPS_DYNAMIC:
|
||||
add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_RTS_MIMO_PROT);
|
||||
break;
|
||||
case IEEE80211_SMPS_OFF:
|
||||
/* nothing */
|
||||
break;
|
||||
}
|
||||
|
||||
if (sta->ht_cap.ht_supported) {
|
||||
add_sta_cmd.station_flags_msk |=
|
||||
@ -340,6 +387,9 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_STATION &&
|
||||
mvmvif->ap_sta_id == mvm_sta->sta_id) {
|
||||
/* flush its queues here since we are freeing mvm_sta */
|
||||
ret = iwl_mvm_flush_tx_path(mvm, mvm_sta->tfd_queue_msk, true);
|
||||
|
||||
/*
|
||||
* Put a non-NULL since the fw station isn't removed.
|
||||
* It will be removed after the MAC will be set as
|
||||
@ -348,9 +398,6 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
|
||||
rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id],
|
||||
ERR_PTR(-EINVAL));
|
||||
|
||||
/* flush its queues here since we are freeing mvm_sta */
|
||||
ret = iwl_mvm_flush_tx_path(mvm, mvm_sta->tfd_queue_msk, true);
|
||||
|
||||
/* if we are associated - we can't remove the AP STA now */
|
||||
if (vif->bss_conf.assoc)
|
||||
return ret;
|
||||
@ -770,6 +817,16 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
u16 txq_id;
|
||||
int err;
|
||||
|
||||
|
||||
/*
|
||||
* If mac80211 is cleaning its state, then say that we finished since
|
||||
* our state has been cleared anyway.
|
||||
*/
|
||||
if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
|
||||
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
spin_lock_bh(&mvmsta->lock);
|
||||
|
||||
txq_id = tid_data->txq_id;
|
||||
@ -824,6 +881,34 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
return err;
|
||||
}
|
||||
|
||||
int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, u16 tid)
|
||||
{
|
||||
struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv;
|
||||
struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid];
|
||||
u16 txq_id;
|
||||
|
||||
/*
|
||||
* First set the agg state to OFF to avoid calling
|
||||
* ieee80211_stop_tx_ba_cb in iwl_mvm_check_ratid_empty.
|
||||
*/
|
||||
spin_lock_bh(&mvmsta->lock);
|
||||
txq_id = tid_data->txq_id;
|
||||
IWL_DEBUG_TX_QUEUES(mvm, "Flush AGG: sta %d tid %d q %d state %d\n",
|
||||
mvmsta->sta_id, tid, txq_id, tid_data->state);
|
||||
tid_data->state = IWL_AGG_OFF;
|
||||
spin_unlock_bh(&mvmsta->lock);
|
||||
|
||||
if (iwl_mvm_flush_tx_path(mvm, BIT(txq_id), true))
|
||||
IWL_ERR(mvm, "Couldn't flush the AGG queue\n");
|
||||
|
||||
iwl_trans_txq_disable(mvm->trans, tid_data->txq_id);
|
||||
mvm->queue_to_mac80211[tid_data->txq_id] =
|
||||
IWL_INVALID_MAC80211_QUEUE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_mvm_set_fw_key_idx(struct iwl_mvm *mvm)
|
||||
{
|
||||
int i;
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
@ -348,6 +348,8 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, u16 tid, u8 buf_size);
|
||||
int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, u16 tid);
|
||||
int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, u16 tid);
|
||||
|
||||
int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm);
|
||||
int iwl_mvm_allocate_int_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *sta,
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
@ -607,12 +607,8 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
|
||||
|
||||
/* Single frame failure in an AMPDU queue => send BAR */
|
||||
if (txq_id >= IWL_FIRST_AMPDU_QUEUE &&
|
||||
!(info->flags & IEEE80211_TX_STAT_ACK)) {
|
||||
/* there must be only one skb in the skb_list */
|
||||
WARN_ON_ONCE(skb_freed > 1 ||
|
||||
!skb_queue_empty(&skbs));
|
||||
!(info->flags & IEEE80211_TX_STAT_ACK))
|
||||
info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
|
||||
}
|
||||
|
||||
/* W/A FW bug: seq_ctl is wrong when the queue is flushed */
|
||||
if (status == TX_STATUS_FAIL_FIFO_FLUSHED) {
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
|
@ -1,115 +0,0 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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) 2007 - 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2013 Intel Corporation. All rights reserved.
|
||||
* 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_pci_h__
|
||||
#define __iwl_pci_h__
|
||||
|
||||
|
||||
/*
|
||||
* This file declares the config structures for all devices.
|
||||
*/
|
||||
|
||||
extern const struct iwl_cfg iwl5300_agn_cfg;
|
||||
extern const struct iwl_cfg iwl5100_agn_cfg;
|
||||
extern const struct iwl_cfg iwl5350_agn_cfg;
|
||||
extern const struct iwl_cfg iwl5100_bgn_cfg;
|
||||
extern const struct iwl_cfg iwl5100_abg_cfg;
|
||||
extern const struct iwl_cfg iwl5150_agn_cfg;
|
||||
extern const struct iwl_cfg iwl5150_abg_cfg;
|
||||
extern const struct iwl_cfg iwl6005_2agn_cfg;
|
||||
extern const struct iwl_cfg iwl6005_2abg_cfg;
|
||||
extern const struct iwl_cfg iwl6005_2bg_cfg;
|
||||
extern const struct iwl_cfg iwl6005_2agn_sff_cfg;
|
||||
extern const struct iwl_cfg iwl6005_2agn_d_cfg;
|
||||
extern const struct iwl_cfg iwl6005_2agn_mow1_cfg;
|
||||
extern const struct iwl_cfg iwl6005_2agn_mow2_cfg;
|
||||
extern const struct iwl_cfg iwl1030_bgn_cfg;
|
||||
extern const struct iwl_cfg iwl1030_bg_cfg;
|
||||
extern const struct iwl_cfg iwl6030_2agn_cfg;
|
||||
extern const struct iwl_cfg iwl6030_2abg_cfg;
|
||||
extern const struct iwl_cfg iwl6030_2bgn_cfg;
|
||||
extern const struct iwl_cfg iwl6030_2bg_cfg;
|
||||
extern const struct iwl_cfg iwl6000i_2agn_cfg;
|
||||
extern const struct iwl_cfg iwl6000i_2abg_cfg;
|
||||
extern const struct iwl_cfg iwl6000i_2bg_cfg;
|
||||
extern const struct iwl_cfg iwl6000_3agn_cfg;
|
||||
extern const struct iwl_cfg iwl6050_2agn_cfg;
|
||||
extern const struct iwl_cfg iwl6050_2abg_cfg;
|
||||
extern const struct iwl_cfg iwl6150_bgn_cfg;
|
||||
extern const struct iwl_cfg iwl6150_bg_cfg;
|
||||
extern const struct iwl_cfg iwl1000_bgn_cfg;
|
||||
extern const struct iwl_cfg iwl1000_bg_cfg;
|
||||
extern const struct iwl_cfg iwl100_bgn_cfg;
|
||||
extern const struct iwl_cfg iwl100_bg_cfg;
|
||||
extern const struct iwl_cfg iwl130_bgn_cfg;
|
||||
extern const struct iwl_cfg iwl130_bg_cfg;
|
||||
extern const struct iwl_cfg iwl2000_2bgn_cfg;
|
||||
extern const struct iwl_cfg iwl2000_2bgn_d_cfg;
|
||||
extern const struct iwl_cfg iwl2030_2bgn_cfg;
|
||||
extern const struct iwl_cfg iwl6035_2agn_cfg;
|
||||
extern const struct iwl_cfg iwl105_bgn_cfg;
|
||||
extern const struct iwl_cfg iwl105_bgn_d_cfg;
|
||||
extern const struct iwl_cfg iwl135_bgn_cfg;
|
||||
extern const struct iwl_cfg iwl7260_2ac_cfg;
|
||||
extern const struct iwl_cfg iwl3160_ac_cfg;
|
||||
|
||||
#endif /* __iwl_pci_h__ */
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
@ -69,8 +69,6 @@
|
||||
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-drv.h"
|
||||
|
||||
#include "cfg.h"
|
||||
#include "internal.h"
|
||||
|
||||
#define IWL_PCI_DEVICE(dev, subdev, cfg) \
|
||||
|
@ -137,10 +137,6 @@ static inline int iwl_queue_dec_wrap(int index, int n_bd)
|
||||
struct iwl_cmd_meta {
|
||||
/* only for SYNC commands, iff the reply skb is wanted */
|
||||
struct iwl_host_cmd *source;
|
||||
|
||||
DEFINE_DMA_UNMAP_ADDR(mapping);
|
||||
DEFINE_DMA_UNMAP_LEN(len);
|
||||
|
||||
u32 flags;
|
||||
};
|
||||
|
||||
@ -182,19 +178,39 @@ struct iwl_queue {
|
||||
#define TFD_TX_CMD_SLOTS 256
|
||||
#define TFD_CMD_SLOTS 32
|
||||
|
||||
/*
|
||||
* The FH will write back to the first TB only, so we need
|
||||
* to copy some data into the buffer regardless of whether
|
||||
* it should be mapped or not. This indicates how big the
|
||||
* first TB must be to include the scratch buffer. Since
|
||||
* the scratch is 4 bytes at offset 12, it's 16 now. If we
|
||||
* make it bigger then allocations will be bigger and copy
|
||||
* slower, so that's probably not useful.
|
||||
*/
|
||||
#define IWL_HCMD_SCRATCHBUF_SIZE 16
|
||||
|
||||
struct iwl_pcie_txq_entry {
|
||||
struct iwl_device_cmd *cmd;
|
||||
struct iwl_device_cmd *copy_cmd;
|
||||
struct sk_buff *skb;
|
||||
/* buffer to free after command completes */
|
||||
const void *free_buf;
|
||||
struct iwl_cmd_meta meta;
|
||||
};
|
||||
|
||||
struct iwl_pcie_txq_scratch_buf {
|
||||
struct iwl_cmd_header hdr;
|
||||
u8 buf[8];
|
||||
__le32 scratch;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_txq - Tx Queue for DMA
|
||||
* @q: generic Rx/Tx queue descriptor
|
||||
* @tfds: transmit frame descriptors (DMA memory)
|
||||
* @scratchbufs: start of command headers, including scratch buffers, for
|
||||
* the writeback -- this is DMA memory and an array holding one buffer
|
||||
* for each command on the queue
|
||||
* @scratchbufs_dma: DMA address for the scratchbufs start
|
||||
* @entries: transmit entries (driver state)
|
||||
* @lock: queue lock
|
||||
* @stuck_timer: timer that fires if queue gets stuck
|
||||
@ -208,6 +224,8 @@ struct iwl_pcie_txq_entry {
|
||||
struct iwl_txq {
|
||||
struct iwl_queue q;
|
||||
struct iwl_tfd *tfds;
|
||||
struct iwl_pcie_txq_scratch_buf *scratchbufs;
|
||||
dma_addr_t scratchbufs_dma;
|
||||
struct iwl_pcie_txq_entry *entries;
|
||||
spinlock_t lock;
|
||||
struct timer_list stuck_timer;
|
||||
@ -216,6 +234,13 @@ struct iwl_txq {
|
||||
u8 active;
|
||||
};
|
||||
|
||||
static inline dma_addr_t
|
||||
iwl_pcie_get_scratchbuf_dma(struct iwl_txq *txq, int idx)
|
||||
{
|
||||
return txq->scratchbufs_dma +
|
||||
sizeof(struct iwl_pcie_txq_scratch_buf) * idx;
|
||||
}
|
||||
|
||||
/**
|
||||
* struct iwl_trans_pcie - PCIe transport specific data
|
||||
* @rxq: all the RX queue data
|
||||
|
@ -637,22 +637,14 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
|
||||
index = SEQ_TO_INDEX(sequence);
|
||||
cmd_index = get_cmd_index(&txq->q, index);
|
||||
|
||||
if (reclaim) {
|
||||
struct iwl_pcie_txq_entry *ent;
|
||||
ent = &txq->entries[cmd_index];
|
||||
cmd = ent->copy_cmd;
|
||||
WARN_ON_ONCE(!cmd && ent->meta.flags & CMD_WANT_HCMD);
|
||||
} else {
|
||||
if (reclaim)
|
||||
cmd = txq->entries[cmd_index].cmd;
|
||||
else
|
||||
cmd = NULL;
|
||||
}
|
||||
|
||||
err = iwl_op_mode_rx(trans->op_mode, &rxcb, cmd);
|
||||
|
||||
if (reclaim) {
|
||||
/* The original command isn't needed any more */
|
||||
kfree(txq->entries[cmd_index].copy_cmd);
|
||||
txq->entries[cmd_index].copy_cmd = NULL;
|
||||
/* nor is the duplicated part of the command */
|
||||
kfree(txq->entries[cmd_index].free_buf);
|
||||
txq->entries[cmd_index].free_buf = NULL;
|
||||
}
|
||||
|
@ -22,7 +22,7 @@
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
* in the file called COPYING.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
@ -715,7 +715,8 @@ static u32 iwl_trans_pcie_read32(struct iwl_trans *trans, u32 ofs)
|
||||
|
||||
static u32 iwl_trans_pcie_read_prph(struct iwl_trans *trans, u32 reg)
|
||||
{
|
||||
iwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_RADDR, reg | (3 << 24));
|
||||
iwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_RADDR,
|
||||
((reg & 0x000FFFFF) | (3 << 24)));
|
||||
return iwl_trans_pcie_read32(trans, HBUS_TARG_PRPH_RDAT);
|
||||
}
|
||||
|
||||
@ -723,7 +724,7 @@ static void iwl_trans_pcie_write_prph(struct iwl_trans *trans, u32 addr,
|
||||
u32 val)
|
||||
{
|
||||
iwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_WADDR,
|
||||
((addr & 0x0000FFFF) | (3 << 24)));
|
||||
((addr & 0x000FFFFF) | (3 << 24)));
|
||||
iwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_WDAT, val);
|
||||
}
|
||||
|
||||
@ -1370,28 +1371,11 @@ static ssize_t iwl_dbgfs_fh_reg_read(struct file *file,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_fw_restart_write(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_trans *trans = file->private_data;
|
||||
|
||||
if (!trans->op_mode)
|
||||
return -EAGAIN;
|
||||
|
||||
local_bh_disable();
|
||||
iwl_op_mode_nic_error(trans->op_mode);
|
||||
local_bh_enable();
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
|
||||
DEBUGFS_READ_FILE_OPS(fh_reg);
|
||||
DEBUGFS_READ_FILE_OPS(rx_queue);
|
||||
DEBUGFS_READ_FILE_OPS(tx_queue);
|
||||
DEBUGFS_WRITE_FILE_OPS(csr);
|
||||
DEBUGFS_WRITE_FILE_OPS(fw_restart);
|
||||
|
||||
/*
|
||||
* Create the debugfs files and directories
|
||||
@ -1405,7 +1389,6 @@ static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
|
||||
DEBUGFS_ADD_FILE(interrupt, dir, S_IWUSR | S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(csr, dir, S_IWUSR);
|
||||
DEBUGFS_ADD_FILE(fh_reg, dir, S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(fw_restart, dir, S_IWUSR);
|
||||
return 0;
|
||||
|
||||
err:
|
||||
|
@ -191,12 +191,9 @@ static void iwl_pcie_txq_stuck_timer(unsigned long data)
|
||||
}
|
||||
|
||||
for (i = q->read_ptr; i != q->write_ptr;
|
||||
i = iwl_queue_inc_wrap(i, q->n_bd)) {
|
||||
struct iwl_tx_cmd *tx_cmd =
|
||||
(struct iwl_tx_cmd *)txq->entries[i].cmd->payload;
|
||||
i = iwl_queue_inc_wrap(i, q->n_bd))
|
||||
IWL_ERR(trans, "scratch %d = 0x%08x\n", i,
|
||||
get_unaligned_le32(&tx_cmd->scratch));
|
||||
}
|
||||
le32_to_cpu(txq->scratchbufs[i].scratch));
|
||||
|
||||
iwl_op_mode_nic_error(trans->op_mode);
|
||||
}
|
||||
@ -367,8 +364,8 @@ static inline u8 iwl_pcie_tfd_get_num_tbs(struct iwl_tfd *tfd)
|
||||
}
|
||||
|
||||
static void iwl_pcie_tfd_unmap(struct iwl_trans *trans,
|
||||
struct iwl_cmd_meta *meta, struct iwl_tfd *tfd,
|
||||
enum dma_data_direction dma_dir)
|
||||
struct iwl_cmd_meta *meta,
|
||||
struct iwl_tfd *tfd)
|
||||
{
|
||||
int i;
|
||||
int num_tbs;
|
||||
@ -382,17 +379,12 @@ static void iwl_pcie_tfd_unmap(struct iwl_trans *trans,
|
||||
return;
|
||||
}
|
||||
|
||||
/* Unmap tx_cmd */
|
||||
if (num_tbs)
|
||||
dma_unmap_single(trans->dev,
|
||||
dma_unmap_addr(meta, mapping),
|
||||
dma_unmap_len(meta, len),
|
||||
DMA_BIDIRECTIONAL);
|
||||
/* first TB is never freed - it's the scratchbuf data */
|
||||
|
||||
/* Unmap chunks, if any. */
|
||||
for (i = 1; i < num_tbs; i++)
|
||||
dma_unmap_single(trans->dev, iwl_pcie_tfd_tb_get_addr(tfd, i),
|
||||
iwl_pcie_tfd_tb_get_len(tfd, i), dma_dir);
|
||||
iwl_pcie_tfd_tb_get_len(tfd, i),
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
tfd->num_tbs = 0;
|
||||
}
|
||||
@ -406,8 +398,7 @@ static void iwl_pcie_tfd_unmap(struct iwl_trans *trans,
|
||||
* Does NOT advance any TFD circular buffer read/write indexes
|
||||
* Does NOT free the TFD itself (which is within circular buffer)
|
||||
*/
|
||||
static void iwl_pcie_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq,
|
||||
enum dma_data_direction dma_dir)
|
||||
static void iwl_pcie_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq)
|
||||
{
|
||||
struct iwl_tfd *tfd_tmp = txq->tfds;
|
||||
|
||||
@ -418,8 +409,7 @@ static void iwl_pcie_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq,
|
||||
lockdep_assert_held(&txq->lock);
|
||||
|
||||
/* We have only q->n_window txq->entries, but we use q->n_bd tfds */
|
||||
iwl_pcie_tfd_unmap(trans, &txq->entries[idx].meta, &tfd_tmp[rd_ptr],
|
||||
dma_dir);
|
||||
iwl_pcie_tfd_unmap(trans, &txq->entries[idx].meta, &tfd_tmp[rd_ptr]);
|
||||
|
||||
/* free SKB */
|
||||
if (txq->entries) {
|
||||
@ -479,6 +469,7 @@ static int iwl_pcie_txq_alloc(struct iwl_trans *trans,
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
size_t tfd_sz = sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX;
|
||||
size_t scratchbuf_sz;
|
||||
int i;
|
||||
|
||||
if (WARN_ON(txq->entries || txq->tfds))
|
||||
@ -514,9 +505,25 @@ static int iwl_pcie_txq_alloc(struct iwl_trans *trans,
|
||||
IWL_ERR(trans, "dma_alloc_coherent(%zd) failed\n", tfd_sz);
|
||||
goto error;
|
||||
}
|
||||
|
||||
BUILD_BUG_ON(IWL_HCMD_SCRATCHBUF_SIZE != sizeof(*txq->scratchbufs));
|
||||
BUILD_BUG_ON(offsetof(struct iwl_pcie_txq_scratch_buf, scratch) !=
|
||||
sizeof(struct iwl_cmd_header) +
|
||||
offsetof(struct iwl_tx_cmd, scratch));
|
||||
|
||||
scratchbuf_sz = sizeof(*txq->scratchbufs) * slots_num;
|
||||
|
||||
txq->scratchbufs = dma_alloc_coherent(trans->dev, scratchbuf_sz,
|
||||
&txq->scratchbufs_dma,
|
||||
GFP_KERNEL);
|
||||
if (!txq->scratchbufs)
|
||||
goto err_free_tfds;
|
||||
|
||||
txq->q.id = txq_id;
|
||||
|
||||
return 0;
|
||||
err_free_tfds:
|
||||
dma_free_coherent(trans->dev, tfd_sz, txq->tfds, txq->q.dma_addr);
|
||||
error:
|
||||
if (txq->entries && txq_id == trans_pcie->cmd_queue)
|
||||
for (i = 0; i < slots_num; i++)
|
||||
@ -565,22 +572,13 @@ static void iwl_pcie_txq_unmap(struct iwl_trans *trans, int txq_id)
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
struct iwl_txq *txq = &trans_pcie->txq[txq_id];
|
||||
struct iwl_queue *q = &txq->q;
|
||||
enum dma_data_direction dma_dir;
|
||||
|
||||
if (!q->n_bd)
|
||||
return;
|
||||
|
||||
/* In the command queue, all the TBs are mapped as BIDI
|
||||
* so unmap them as such.
|
||||
*/
|
||||
if (txq_id == trans_pcie->cmd_queue)
|
||||
dma_dir = DMA_BIDIRECTIONAL;
|
||||
else
|
||||
dma_dir = DMA_TO_DEVICE;
|
||||
|
||||
spin_lock_bh(&txq->lock);
|
||||
while (q->write_ptr != q->read_ptr) {
|
||||
iwl_pcie_txq_free_tfd(trans, txq, dma_dir);
|
||||
iwl_pcie_txq_free_tfd(trans, txq);
|
||||
q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
|
||||
}
|
||||
spin_unlock_bh(&txq->lock);
|
||||
@ -610,7 +608,6 @@ static void iwl_pcie_txq_free(struct iwl_trans *trans, int txq_id)
|
||||
if (txq_id == trans_pcie->cmd_queue)
|
||||
for (i = 0; i < txq->q.n_window; i++) {
|
||||
kfree(txq->entries[i].cmd);
|
||||
kfree(txq->entries[i].copy_cmd);
|
||||
kfree(txq->entries[i].free_buf);
|
||||
}
|
||||
|
||||
@ -619,6 +616,10 @@ static void iwl_pcie_txq_free(struct iwl_trans *trans, int txq_id)
|
||||
dma_free_coherent(dev, sizeof(struct iwl_tfd) *
|
||||
txq->q.n_bd, txq->tfds, txq->q.dma_addr);
|
||||
txq->q.dma_addr = 0;
|
||||
|
||||
dma_free_coherent(dev,
|
||||
sizeof(*txq->scratchbufs) * txq->q.n_window,
|
||||
txq->scratchbufs, txq->scratchbufs_dma);
|
||||
}
|
||||
|
||||
kfree(txq->entries);
|
||||
@ -962,7 +963,7 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
|
||||
|
||||
iwl_pcie_txq_inval_byte_cnt_tbl(trans, txq);
|
||||
|
||||
iwl_pcie_txq_free_tfd(trans, txq, DMA_TO_DEVICE);
|
||||
iwl_pcie_txq_free_tfd(trans, txq);
|
||||
}
|
||||
|
||||
iwl_pcie_txq_progress(trans_pcie, txq);
|
||||
@ -1152,20 +1153,37 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
|
||||
void *dup_buf = NULL;
|
||||
dma_addr_t phys_addr;
|
||||
int idx;
|
||||
u16 copy_size, cmd_size;
|
||||
u16 copy_size, cmd_size, scratch_size;
|
||||
bool had_nocopy = false;
|
||||
int i;
|
||||
u32 cmd_pos;
|
||||
const u8 *cmddata[IWL_MAX_CMD_TBS_PER_TFD];
|
||||
u16 cmdlen[IWL_MAX_CMD_TBS_PER_TFD];
|
||||
|
||||
copy_size = sizeof(out_cmd->hdr);
|
||||
cmd_size = sizeof(out_cmd->hdr);
|
||||
|
||||
/* need one for the header if the first is NOCOPY */
|
||||
BUILD_BUG_ON(IWL_MAX_CMD_TFDS > IWL_NUM_OF_TBS - 1);
|
||||
BUILD_BUG_ON(IWL_MAX_CMD_TBS_PER_TFD > IWL_NUM_OF_TBS - 1);
|
||||
|
||||
for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) {
|
||||
cmddata[i] = cmd->data[i];
|
||||
cmdlen[i] = cmd->len[i];
|
||||
|
||||
for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
|
||||
if (!cmd->len[i])
|
||||
continue;
|
||||
|
||||
/* need at least IWL_HCMD_SCRATCHBUF_SIZE copied */
|
||||
if (copy_size < IWL_HCMD_SCRATCHBUF_SIZE) {
|
||||
int copy = IWL_HCMD_SCRATCHBUF_SIZE - copy_size;
|
||||
|
||||
if (copy > cmdlen[i])
|
||||
copy = cmdlen[i];
|
||||
cmdlen[i] -= copy;
|
||||
cmddata[i] += copy;
|
||||
copy_size += copy;
|
||||
}
|
||||
|
||||
if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY) {
|
||||
had_nocopy = true;
|
||||
if (WARN_ON(cmd->dataflags[i] & IWL_HCMD_DFL_DUP)) {
|
||||
@ -1185,7 +1203,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
|
||||
goto free_dup_buf;
|
||||
}
|
||||
|
||||
dup_buf = kmemdup(cmd->data[i], cmd->len[i],
|
||||
dup_buf = kmemdup(cmddata[i], cmdlen[i],
|
||||
GFP_ATOMIC);
|
||||
if (!dup_buf)
|
||||
return -ENOMEM;
|
||||
@ -1195,7 +1213,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
|
||||
idx = -EINVAL;
|
||||
goto free_dup_buf;
|
||||
}
|
||||
copy_size += cmd->len[i];
|
||||
copy_size += cmdlen[i];
|
||||
}
|
||||
cmd_size += cmd->len[i];
|
||||
}
|
||||
@ -1242,30 +1260,30 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
|
||||
|
||||
/* and copy the data that needs to be copied */
|
||||
cmd_pos = offsetof(struct iwl_device_cmd, payload);
|
||||
for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
|
||||
if (!cmd->len[i])
|
||||
copy_size = sizeof(out_cmd->hdr);
|
||||
for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) {
|
||||
int copy = 0;
|
||||
|
||||
if (!cmd->len)
|
||||
continue;
|
||||
if (cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY |
|
||||
IWL_HCMD_DFL_DUP))
|
||||
break;
|
||||
memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], cmd->len[i]);
|
||||
cmd_pos += cmd->len[i];
|
||||
}
|
||||
|
||||
WARN_ON_ONCE(txq->entries[idx].copy_cmd);
|
||||
/* need at least IWL_HCMD_SCRATCHBUF_SIZE copied */
|
||||
if (copy_size < IWL_HCMD_SCRATCHBUF_SIZE) {
|
||||
copy = IWL_HCMD_SCRATCHBUF_SIZE - copy_size;
|
||||
|
||||
/*
|
||||
* since out_cmd will be the source address of the FH, it will write
|
||||
* the retry count there. So when the user needs to receivce the HCMD
|
||||
* that corresponds to the response in the response handler, it needs
|
||||
* to set CMD_WANT_HCMD.
|
||||
*/
|
||||
if (cmd->flags & CMD_WANT_HCMD) {
|
||||
txq->entries[idx].copy_cmd =
|
||||
kmemdup(out_cmd, cmd_pos, GFP_ATOMIC);
|
||||
if (unlikely(!txq->entries[idx].copy_cmd)) {
|
||||
idx = -ENOMEM;
|
||||
goto out;
|
||||
if (copy > cmd->len[i])
|
||||
copy = cmd->len[i];
|
||||
}
|
||||
|
||||
/* copy everything if not nocopy/dup */
|
||||
if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY |
|
||||
IWL_HCMD_DFL_DUP)))
|
||||
copy = cmd->len[i];
|
||||
|
||||
if (copy) {
|
||||
memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], copy);
|
||||
cmd_pos += copy;
|
||||
copy_size += copy;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1275,22 +1293,35 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
|
||||
out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence),
|
||||
cmd_size, q->write_ptr, idx, trans_pcie->cmd_queue);
|
||||
|
||||
phys_addr = dma_map_single(trans->dev, &out_cmd->hdr, copy_size,
|
||||
DMA_BIDIRECTIONAL);
|
||||
if (unlikely(dma_mapping_error(trans->dev, phys_addr))) {
|
||||
idx = -ENOMEM;
|
||||
goto out;
|
||||
/* start the TFD with the scratchbuf */
|
||||
scratch_size = min_t(int, copy_size, IWL_HCMD_SCRATCHBUF_SIZE);
|
||||
memcpy(&txq->scratchbufs[q->write_ptr], &out_cmd->hdr, scratch_size);
|
||||
iwl_pcie_txq_build_tfd(trans, txq,
|
||||
iwl_pcie_get_scratchbuf_dma(txq, q->write_ptr),
|
||||
scratch_size, 1);
|
||||
|
||||
/* map first command fragment, if any remains */
|
||||
if (copy_size > scratch_size) {
|
||||
phys_addr = dma_map_single(trans->dev,
|
||||
((u8 *)&out_cmd->hdr) + scratch_size,
|
||||
copy_size - scratch_size,
|
||||
DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(trans->dev, phys_addr)) {
|
||||
iwl_pcie_tfd_unmap(trans, out_meta,
|
||||
&txq->tfds[q->write_ptr]);
|
||||
idx = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
iwl_pcie_txq_build_tfd(trans, txq, phys_addr,
|
||||
copy_size - scratch_size, 0);
|
||||
}
|
||||
|
||||
dma_unmap_addr_set(out_meta, mapping, phys_addr);
|
||||
dma_unmap_len_set(out_meta, len, copy_size);
|
||||
/* map the remaining (adjusted) nocopy/dup fragments */
|
||||
for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) {
|
||||
const void *data = cmddata[i];
|
||||
|
||||
iwl_pcie_txq_build_tfd(trans, txq, phys_addr, copy_size, 1);
|
||||
|
||||
for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
|
||||
const void *data = cmd->data[i];
|
||||
|
||||
if (!cmd->len[i])
|
||||
if (!cmdlen[i])
|
||||
continue;
|
||||
if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY |
|
||||
IWL_HCMD_DFL_DUP)))
|
||||
@ -1298,16 +1329,15 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
|
||||
if (cmd->dataflags[i] & IWL_HCMD_DFL_DUP)
|
||||
data = dup_buf;
|
||||
phys_addr = dma_map_single(trans->dev, (void *)data,
|
||||
cmd->len[i], DMA_BIDIRECTIONAL);
|
||||
cmdlen[i], DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(trans->dev, phys_addr)) {
|
||||
iwl_pcie_tfd_unmap(trans, out_meta,
|
||||
&txq->tfds[q->write_ptr],
|
||||
DMA_BIDIRECTIONAL);
|
||||
&txq->tfds[q->write_ptr]);
|
||||
idx = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
iwl_pcie_txq_build_tfd(trans, txq, phys_addr, cmd->len[i], 0);
|
||||
iwl_pcie_txq_build_tfd(trans, txq, phys_addr, cmdlen[i], 0);
|
||||
}
|
||||
|
||||
out_meta->flags = cmd->flags;
|
||||
@ -1317,8 +1347,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
|
||||
|
||||
txq->need_update = 1;
|
||||
|
||||
trace_iwlwifi_dev_hcmd(trans->dev, cmd, cmd_size,
|
||||
&out_cmd->hdr, copy_size);
|
||||
trace_iwlwifi_dev_hcmd(trans->dev, cmd, cmd_size, &out_cmd->hdr);
|
||||
|
||||
/* start timer if queue currently empty */
|
||||
if (q->read_ptr == q->write_ptr && trans_pcie->wd_timeout)
|
||||
@ -1377,7 +1406,7 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans,
|
||||
cmd = txq->entries[cmd_index].cmd;
|
||||
meta = &txq->entries[cmd_index].meta;
|
||||
|
||||
iwl_pcie_tfd_unmap(trans, meta, &txq->tfds[index], DMA_BIDIRECTIONAL);
|
||||
iwl_pcie_tfd_unmap(trans, meta, &txq->tfds[index]);
|
||||
|
||||
/* Input error checking is done when commands are added to queue. */
|
||||
if (meta->flags & CMD_WANT_SKB) {
|
||||
@ -1556,10 +1585,9 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
|
||||
struct iwl_cmd_meta *out_meta;
|
||||
struct iwl_txq *txq;
|
||||
struct iwl_queue *q;
|
||||
dma_addr_t phys_addr = 0;
|
||||
dma_addr_t txcmd_phys;
|
||||
dma_addr_t scratch_phys;
|
||||
u16 len, firstlen, secondlen;
|
||||
dma_addr_t tb0_phys, tb1_phys, scratch_phys;
|
||||
void *tb1_addr;
|
||||
u16 len, tb1_len, tb2_len;
|
||||
u8 wait_write_ptr = 0;
|
||||
__le16 fc = hdr->frame_control;
|
||||
u8 hdr_len = ieee80211_hdrlen(fc);
|
||||
@ -1597,35 +1625,73 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
|
||||
cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
|
||||
INDEX_TO_SEQ(q->write_ptr)));
|
||||
|
||||
tb0_phys = iwl_pcie_get_scratchbuf_dma(txq, q->write_ptr);
|
||||
scratch_phys = tb0_phys + sizeof(struct iwl_cmd_header) +
|
||||
offsetof(struct iwl_tx_cmd, scratch);
|
||||
|
||||
tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys);
|
||||
tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys);
|
||||
|
||||
/* Set up first empty entry in queue's array of Tx/cmd buffers */
|
||||
out_meta = &txq->entries[q->write_ptr].meta;
|
||||
|
||||
/*
|
||||
* Use the first empty entry in this queue's command buffer array
|
||||
* to contain the Tx command and MAC header concatenated together
|
||||
* (payload data will be in another buffer).
|
||||
* Size of this varies, due to varying MAC header length.
|
||||
* If end is not dword aligned, we'll have 2 extra bytes at the end
|
||||
* of the MAC header (device reads on dword boundaries).
|
||||
* We'll tell device about this padding later.
|
||||
* The second TB (tb1) points to the remainder of the TX command
|
||||
* and the 802.11 header - dword aligned size
|
||||
* (This calculation modifies the TX command, so do it before the
|
||||
* setup of the first TB)
|
||||
*/
|
||||
len = sizeof(struct iwl_tx_cmd) +
|
||||
sizeof(struct iwl_cmd_header) + hdr_len;
|
||||
firstlen = (len + 3) & ~3;
|
||||
len = sizeof(struct iwl_tx_cmd) + sizeof(struct iwl_cmd_header) +
|
||||
hdr_len - IWL_HCMD_SCRATCHBUF_SIZE;
|
||||
tb1_len = (len + 3) & ~3;
|
||||
|
||||
/* Tell NIC about any 2-byte padding after MAC header */
|
||||
if (firstlen != len)
|
||||
if (tb1_len != len)
|
||||
tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK;
|
||||
|
||||
/* Physical address of this Tx command's header (not MAC header!),
|
||||
* within command buffer array. */
|
||||
txcmd_phys = dma_map_single(trans->dev,
|
||||
&dev_cmd->hdr, firstlen,
|
||||
DMA_BIDIRECTIONAL);
|
||||
if (unlikely(dma_mapping_error(trans->dev, txcmd_phys)))
|
||||
/* The first TB points to the scratchbuf data - min_copy bytes */
|
||||
memcpy(&txq->scratchbufs[q->write_ptr], &dev_cmd->hdr,
|
||||
IWL_HCMD_SCRATCHBUF_SIZE);
|
||||
iwl_pcie_txq_build_tfd(trans, txq, tb0_phys,
|
||||
IWL_HCMD_SCRATCHBUF_SIZE, 1);
|
||||
|
||||
/* there must be data left over for TB1 or this code must be changed */
|
||||
BUILD_BUG_ON(sizeof(struct iwl_tx_cmd) < IWL_HCMD_SCRATCHBUF_SIZE);
|
||||
|
||||
/* map the data for TB1 */
|
||||
tb1_addr = ((u8 *)&dev_cmd->hdr) + IWL_HCMD_SCRATCHBUF_SIZE;
|
||||
tb1_phys = dma_map_single(trans->dev, tb1_addr, tb1_len, DMA_TO_DEVICE);
|
||||
if (unlikely(dma_mapping_error(trans->dev, tb1_phys)))
|
||||
goto out_err;
|
||||
dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
|
||||
dma_unmap_len_set(out_meta, len, firstlen);
|
||||
iwl_pcie_txq_build_tfd(trans, txq, tb1_phys, tb1_len, 0);
|
||||
|
||||
/*
|
||||
* Set up TFD's third entry to point directly to remainder
|
||||
* of skb, if any (802.11 null frames have no payload).
|
||||
*/
|
||||
tb2_len = skb->len - hdr_len;
|
||||
if (tb2_len > 0) {
|
||||
dma_addr_t tb2_phys = dma_map_single(trans->dev,
|
||||
skb->data + hdr_len,
|
||||
tb2_len, DMA_TO_DEVICE);
|
||||
if (unlikely(dma_mapping_error(trans->dev, tb2_phys))) {
|
||||
iwl_pcie_tfd_unmap(trans, out_meta,
|
||||
&txq->tfds[q->write_ptr]);
|
||||
goto out_err;
|
||||
}
|
||||
iwl_pcie_txq_build_tfd(trans, txq, tb2_phys, tb2_len, 0);
|
||||
}
|
||||
|
||||
/* Set up entry for this TFD in Tx byte-count array */
|
||||
iwl_pcie_txq_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->len));
|
||||
|
||||
trace_iwlwifi_dev_tx(trans->dev, skb,
|
||||
&txq->tfds[txq->q.write_ptr],
|
||||
sizeof(struct iwl_tfd),
|
||||
&dev_cmd->hdr, IWL_HCMD_SCRATCHBUF_SIZE + tb1_len,
|
||||
skb->data + hdr_len, tb2_len);
|
||||
trace_iwlwifi_dev_tx_data(trans->dev, skb,
|
||||
skb->data + hdr_len, tb2_len);
|
||||
|
||||
if (!ieee80211_has_morefrags(fc)) {
|
||||
txq->need_update = 1;
|
||||
@ -1634,49 +1700,6 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
|
||||
txq->need_update = 0;
|
||||
}
|
||||
|
||||
/* Set up TFD's 2nd entry to point directly to remainder of skb,
|
||||
* if any (802.11 null frames have no payload). */
|
||||
secondlen = skb->len - hdr_len;
|
||||
if (secondlen > 0) {
|
||||
phys_addr = dma_map_single(trans->dev, skb->data + hdr_len,
|
||||
secondlen, DMA_TO_DEVICE);
|
||||
if (unlikely(dma_mapping_error(trans->dev, phys_addr))) {
|
||||
dma_unmap_single(trans->dev,
|
||||
dma_unmap_addr(out_meta, mapping),
|
||||
dma_unmap_len(out_meta, len),
|
||||
DMA_BIDIRECTIONAL);
|
||||
goto out_err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Attach buffers to TFD */
|
||||
iwl_pcie_txq_build_tfd(trans, txq, txcmd_phys, firstlen, 1);
|
||||
if (secondlen > 0)
|
||||
iwl_pcie_txq_build_tfd(trans, txq, phys_addr, secondlen, 0);
|
||||
|
||||
scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) +
|
||||
offsetof(struct iwl_tx_cmd, scratch);
|
||||
|
||||
/* take back ownership of DMA buffer to enable update */
|
||||
dma_sync_single_for_cpu(trans->dev, txcmd_phys, firstlen,
|
||||
DMA_BIDIRECTIONAL);
|
||||
tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys);
|
||||
tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys);
|
||||
|
||||
/* Set up entry for this TFD in Tx byte-count array */
|
||||
iwl_pcie_txq_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->len));
|
||||
|
||||
dma_sync_single_for_device(trans->dev, txcmd_phys, firstlen,
|
||||
DMA_BIDIRECTIONAL);
|
||||
|
||||
trace_iwlwifi_dev_tx(trans->dev, skb,
|
||||
&txq->tfds[txq->q.write_ptr],
|
||||
sizeof(struct iwl_tfd),
|
||||
&dev_cmd->hdr, firstlen,
|
||||
skb->data + hdr_len, secondlen);
|
||||
trace_iwlwifi_dev_tx_data(trans->dev, skb,
|
||||
skb->data + hdr_len, secondlen);
|
||||
|
||||
/* start timer if queue currently empty */
|
||||
if (txq->need_update && q->read_ptr == q->write_ptr &&
|
||||
trans_pcie->wd_timeout)
|
||||
|
Loading…
Reference in New Issue
Block a user