mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-02-05 08:05:19 +07:00
* added support for MU-MIMO sniffer
* added support for RRM by scan * added support for packet injection * migrate to devm memory allocation handling * some fixes, mostly in DQA and new HW support * other generic cleanups -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJX36ObAAoJEKFHnKIaPMX6LhkP+wfLwbFRxPjjgDw3lmCKkNVG 00TwrKNjZUeVR0CPkwnBb4QZHVMAvDP/EoOGbdBNCKI0RJL6PC/Qs68TegYiVCL6 9xzYEVD/vkABXugIrhAU3U8xAZPYbqHmMw/swbZkp+9pi+8GddpRcmkQnB9WElQ2 /dsWOFF12AdONCO/u8j7w/pfSd0p3iN9dcZHHQc19+KlFYEUaryLFoL1PTzz5DV1 WbtCWBinE1dUbmnZHBgoXfTL2A1sopLwMr6RJ8yqlMAGIG7sndNJ0OzEFy8IdTvm irEmkwcYlAH5ZjJ7MKlCrsUNErescNnTqcLCRK850VCBxLIwnGvJtIMBJjR/cY0X SvejNom5xEy48WUhx6yFbutsRih5bq0yglsL298pAuwQLpLXBetplozrtlGXK6hV 1x+R1kBkFleBoHTWamImBLzP5fJHIHxHEHoZqTAzvXDsQp/4ZLpugi6Y91Z4BtRv yHg3CN0ebPmGTM2yMgXlRynY2xrvM5MlCPq+n9zLEy4bQ6BDa+IsX9BgMK0cdBXC eSk5T3pq+csGSAZ/1EBCKNaEQ7qDGKtf9YWpd/d5hsxVsGEMcCj0jjGV7km/ikQJ 2yQmAiKB2Rn0KI9ABUQGDDGPdxoFVT8Jdd/qBy0RC9ERNl1B1rLiqdpST8KVkTkr 4tHK6tvJUELZsZqzyJgn =42wP -----END PGP SIGNATURE----- Merge tag 'iwlwifi-next-for-kalle-2016-09-19-2' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next * added support for MU-MIMO sniffer * added support for RRM by scan * added support for packet injection * migrate to devm memory allocation handling * some fixes, mostly in DQA and new HW support * other generic cleanups
This commit is contained in:
commit
9c95fd662a
@ -33,9 +33,6 @@
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include "iwl-devtrace.h"
|
||||
|
||||
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_iowrite8);
|
||||
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ioread32);
|
||||
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_iowrite32);
|
||||
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_event);
|
||||
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_error);
|
||||
EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_cont_event);
|
||||
|
@ -256,6 +256,10 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_api_t;
|
||||
* instead of 3.
|
||||
* @IWL_UCODE_TLV_API_TX_POWER_CHAIN: TX power API has larger command size
|
||||
* (command version 3) that supports per-chain limits
|
||||
* @IWL_UCODE_TLV_API_SCAN_TSF_REPORT: Scan start time reported in scan
|
||||
* iteration complete notification, and the timestamp reported for RX
|
||||
* received during scan, are reported in TSF of the mac specified in the
|
||||
* scan request.
|
||||
*
|
||||
* @NUM_IWL_UCODE_TLV_API: number of bits used
|
||||
*/
|
||||
@ -267,6 +271,7 @@ enum iwl_ucode_tlv_api {
|
||||
IWL_UCODE_TLV_API_NEW_VERSION = (__force iwl_ucode_tlv_api_t)20,
|
||||
IWL_UCODE_TLV_API_EXT_SCAN_PRIORITY = (__force iwl_ucode_tlv_api_t)24,
|
||||
IWL_UCODE_TLV_API_TX_POWER_CHAIN = (__force iwl_ucode_tlv_api_t)27,
|
||||
IWL_UCODE_TLV_API_SCAN_TSF_REPORT = (__force iwl_ucode_tlv_api_t)28,
|
||||
|
||||
NUM_IWL_UCODE_TLV_API
|
||||
#ifdef __CHECKER__
|
||||
|
@ -99,8 +99,12 @@ void iwl_notification_wait_notify(struct iwl_notif_wait_data *notif_wait,
|
||||
continue;
|
||||
|
||||
for (i = 0; i < w->n_cmds; i++) {
|
||||
if (w->cmds[i] ==
|
||||
WIDE_ID(pkt->hdr.group_id, pkt->hdr.cmd)) {
|
||||
u16 rec_id = WIDE_ID(pkt->hdr.group_id,
|
||||
pkt->hdr.cmd);
|
||||
|
||||
if (w->cmds[i] == rec_id ||
|
||||
(!iwl_cmd_groupid(w->cmds[i]) &&
|
||||
DEF_ID(w->cmds[i]) == rec_id)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
@ -67,6 +67,7 @@
|
||||
#include <linux/export.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/acpi.h>
|
||||
#include "iwl-drv.h"
|
||||
#include "iwl-modparams.h"
|
||||
#include "iwl-nvm-parse.h"
|
||||
@ -564,11 +565,16 @@ static void iwl_set_hw_address_from_csr(struct iwl_trans *trans,
|
||||
__le32 mac_addr0 = cpu_to_le32(iwl_read32(trans, CSR_MAC_ADDR0_STRAP));
|
||||
__le32 mac_addr1 = cpu_to_le32(iwl_read32(trans, CSR_MAC_ADDR1_STRAP));
|
||||
|
||||
/* If OEM did not fuse address - get it from OTP */
|
||||
if (!mac_addr0 && !mac_addr1) {
|
||||
mac_addr0 = cpu_to_le32(iwl_read32(trans, CSR_MAC_ADDR0_OTP));
|
||||
mac_addr1 = cpu_to_le32(iwl_read32(trans, CSR_MAC_ADDR1_OTP));
|
||||
}
|
||||
iwl_flip_hw_address(mac_addr0, mac_addr1, data->hw_addr);
|
||||
/*
|
||||
* If the OEM fused a valid address, use it instead of the one in the
|
||||
* OTP
|
||||
*/
|
||||
if (is_valid_ether_addr(data->hw_addr))
|
||||
return;
|
||||
|
||||
mac_addr0 = cpu_to_le32(iwl_read32(trans, CSR_MAC_ADDR0_OTP));
|
||||
mac_addr1 = cpu_to_le32(iwl_read32(trans, CSR_MAC_ADDR1_OTP));
|
||||
|
||||
iwl_flip_hw_address(mac_addr0, mac_addr1, data->hw_addr);
|
||||
}
|
||||
@ -899,3 +905,91 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
|
||||
return regd;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_parse_nvm_mcc_info);
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
#define WRDD_METHOD "WRDD"
|
||||
#define WRDD_WIFI (0x07)
|
||||
#define WRDD_WIGIG (0x10)
|
||||
|
||||
static u32 iwl_wrdd_get_mcc(struct device *dev, union acpi_object *wrdd)
|
||||
{
|
||||
union acpi_object *mcc_pkg, *domain_type, *mcc_value;
|
||||
u32 i;
|
||||
|
||||
if (wrdd->type != ACPI_TYPE_PACKAGE ||
|
||||
wrdd->package.count < 2 ||
|
||||
wrdd->package.elements[0].type != ACPI_TYPE_INTEGER ||
|
||||
wrdd->package.elements[0].integer.value != 0) {
|
||||
IWL_DEBUG_EEPROM(dev, "Unsupported wrdd structure\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 1 ; i < wrdd->package.count ; ++i) {
|
||||
mcc_pkg = &wrdd->package.elements[i];
|
||||
|
||||
if (mcc_pkg->type != ACPI_TYPE_PACKAGE ||
|
||||
mcc_pkg->package.count < 2 ||
|
||||
mcc_pkg->package.elements[0].type != ACPI_TYPE_INTEGER ||
|
||||
mcc_pkg->package.elements[1].type != ACPI_TYPE_INTEGER) {
|
||||
mcc_pkg = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
domain_type = &mcc_pkg->package.elements[0];
|
||||
if (domain_type->integer.value == WRDD_WIFI)
|
||||
break;
|
||||
|
||||
mcc_pkg = NULL;
|
||||
}
|
||||
|
||||
if (mcc_pkg) {
|
||||
mcc_value = &mcc_pkg->package.elements[1];
|
||||
return mcc_value->integer.value;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwl_get_bios_mcc(struct device *dev, char *mcc)
|
||||
{
|
||||
acpi_handle root_handle;
|
||||
acpi_handle handle;
|
||||
struct acpi_buffer wrdd = {ACPI_ALLOCATE_BUFFER, NULL};
|
||||
acpi_status status;
|
||||
u32 mcc_val;
|
||||
|
||||
root_handle = ACPI_HANDLE(dev);
|
||||
if (!root_handle) {
|
||||
IWL_DEBUG_EEPROM(dev,
|
||||
"Could not retrieve root port ACPI handle\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/* Get the method's handle */
|
||||
status = acpi_get_handle(root_handle, (acpi_string)WRDD_METHOD,
|
||||
&handle);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
IWL_DEBUG_EEPROM(dev, "WRD method not found\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/* Call WRDD with no arguments */
|
||||
status = acpi_evaluate_object(handle, NULL, NULL, &wrdd);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
IWL_DEBUG_EEPROM(dev, "WRDC invocation failed (0x%x)\n",
|
||||
status);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
mcc_val = iwl_wrdd_get_mcc(dev, wrdd.pointer);
|
||||
kfree(wrdd.pointer);
|
||||
if (!mcc_val)
|
||||
return -ENOENT;
|
||||
|
||||
mcc[0] = (mcc_val >> 8) & 0xff;
|
||||
mcc[1] = mcc_val & 0xff;
|
||||
mcc[2] = '\0';
|
||||
return 0;
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_get_bios_mcc);
|
||||
#endif
|
||||
|
@ -5,7 +5,8 @@
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2008 - 2015 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2016 Intel Deutschland GmbH
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
@ -93,4 +94,21 @@ struct ieee80211_regdomain *
|
||||
iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
|
||||
int num_of_ch, __le32 *channels, u16 fw_mcc);
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
/**
|
||||
* iwl_get_bios_mcc - read MCC from BIOS, if available
|
||||
*
|
||||
* @dev: the struct device
|
||||
* @mcc: output buffer (3 bytes) that will get the MCC
|
||||
*
|
||||
* This function tries to read the current MCC from ACPI if available.
|
||||
*/
|
||||
int iwl_get_bios_mcc(struct device *dev, char *mcc);
|
||||
#else
|
||||
static inline int iwl_get_bios_mcc(struct device *dev, char *mcc)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __iwl_nvm_parse_h__ */
|
||||
|
@ -110,7 +110,7 @@ enum iwl_phy_db_section_type {
|
||||
IWL_PHY_DB_MAX
|
||||
};
|
||||
|
||||
#define PHY_DB_CMD 0x6c /* TEMP API - The actual is 0x8c */
|
||||
#define PHY_DB_CMD 0x6c
|
||||
|
||||
/*
|
||||
* phy db - configure operational ucode
|
||||
|
@ -78,7 +78,7 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
|
||||
static struct lock_class_key __key;
|
||||
#endif
|
||||
|
||||
trans = kzalloc(sizeof(*trans) + priv_size, GFP_KERNEL);
|
||||
trans = devm_kzalloc(dev, sizeof(*trans) + priv_size, GFP_KERNEL);
|
||||
if (!trans)
|
||||
return NULL;
|
||||
|
||||
@ -103,18 +103,14 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
|
||||
SLAB_HWCACHE_ALIGN,
|
||||
NULL);
|
||||
if (!trans->dev_cmd_pool)
|
||||
goto free;
|
||||
return NULL;
|
||||
|
||||
return trans;
|
||||
free:
|
||||
kfree(trans);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void iwl_trans_free(struct iwl_trans *trans)
|
||||
{
|
||||
kmem_cache_destroy(trans->dev_cmd_pool);
|
||||
kfree(trans);
|
||||
}
|
||||
|
||||
int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
|
||||
@ -140,6 +136,9 @@ int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
|
||||
if (!(cmd->flags & CMD_ASYNC))
|
||||
lock_map_acquire_read(&trans->sync_cmd_lockdep_map);
|
||||
|
||||
if (trans->wide_cmd_header && !iwl_cmd_groupid(cmd->id))
|
||||
cmd->id = DEF_ID(cmd->id);
|
||||
|
||||
ret = trans->ops->send_cmd(trans, cmd);
|
||||
|
||||
if (!(cmd->flags & CMD_ASYNC))
|
||||
|
@ -153,6 +153,7 @@ static inline u32 iwl_cmd_id(u8 opcode, u8 groupid, u8 version)
|
||||
|
||||
/* make u16 wide id out of u8 group and opcode */
|
||||
#define WIDE_ID(grp, opcode) ((grp << 8) | opcode)
|
||||
#define DEF_ID(opcode) ((1 << 8) | (opcode))
|
||||
|
||||
/* due to the conversion, this group is special; new groups
|
||||
* should be defined in the appropriate fw-api header files
|
||||
@ -484,7 +485,6 @@ struct iwl_hcmd_arr {
|
||||
* @bc_table_dword: set to true if the BC table expects the byte count to be
|
||||
* in DWORD (as opposed to bytes)
|
||||
* @scd_set_active: should the transport configure the SCD for HCMD queue
|
||||
* @wide_cmd_header: firmware supports wide host command header
|
||||
* @sw_csum_tx: transport should compute the TCP checksum
|
||||
* @command_groups: array of command groups, each member is an array of the
|
||||
* commands in the group; for debugging only
|
||||
@ -506,7 +506,6 @@ struct iwl_trans_config {
|
||||
enum iwl_amsdu_size rx_buf_size;
|
||||
bool bc_table_dword;
|
||||
bool scd_set_active;
|
||||
bool wide_cmd_header;
|
||||
bool sw_csum_tx;
|
||||
const struct iwl_hcmd_arr *command_groups;
|
||||
int command_groups_size;
|
||||
@ -770,6 +769,7 @@ enum iwl_plat_pm_mode {
|
||||
* @hw_id_str: a string with info about HW ID. Set during transport allocation.
|
||||
* @pm_support: set to true in start_hw if link pm is supported
|
||||
* @ltr_enabled: set to true if the LTR is enabled
|
||||
* @wide_cmd_header: true when ucode supports wide command header format
|
||||
* @num_rx_queues: number of RX queues allocated by the transport;
|
||||
* the transport must set this before calling iwl_drv_start()
|
||||
* @dev_cmd_pool: pool for Tx cmd allocation - for internal use only.
|
||||
@ -821,6 +821,7 @@ struct iwl_trans {
|
||||
|
||||
const struct iwl_hcmd_arr *command_groups;
|
||||
int command_groups_size;
|
||||
bool wide_cmd_header;
|
||||
|
||||
u8 num_rx_queues;
|
||||
|
||||
|
@ -504,6 +504,28 @@ static inline char *iwl_dbgfs_is_match(char *name, char *buf)
|
||||
return !strncmp(name, buf, len) ? buf + len : NULL;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_os_device_timediff_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ieee80211_vif *vif = file->private_data;
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mvm *mvm = mvmvif->mvm;
|
||||
u32 curr_gp2;
|
||||
u64 curr_os;
|
||||
s64 diff;
|
||||
char buf[64];
|
||||
const size_t bufsz = sizeof(buf);
|
||||
int pos = 0;
|
||||
|
||||
iwl_mvm_get_sync_time(mvm, &curr_gp2, &curr_os);
|
||||
do_div(curr_os, NSEC_PER_USEC);
|
||||
diff = curr_os - curr_gp2;
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "diff=%lld\n", diff);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_tof_enable_write(struct ieee80211_vif *vif,
|
||||
char *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
@ -1530,6 +1552,8 @@ MVM_DEBUGFS_READ_FILE_OPS(tof_range_response);
|
||||
MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_responder_params, 32);
|
||||
MVM_DEBUGFS_READ_WRITE_FILE_OPS(quota_min, 32);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(lqm_send_cmd, 64);
|
||||
MVM_DEBUGFS_READ_FILE_OPS(os_device_timediff);
|
||||
|
||||
|
||||
void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
{
|
||||
@ -1570,6 +1594,8 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
MVM_DEBUGFS_ADD_FILE_VIF(quota_min, mvmvif->dbgfs_dir,
|
||||
S_IRUSR | S_IWUSR);
|
||||
MVM_DEBUGFS_ADD_FILE_VIF(lqm_send_cmd, mvmvif->dbgfs_dir, S_IWUSR);
|
||||
MVM_DEBUGFS_ADD_FILE_VIF(os_device_timediff,
|
||||
mvmvif->dbgfs_dir, S_IRUSR);
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_STATION && !vif->p2p &&
|
||||
mvmvif == mvm->bf_allowed_vif)
|
||||
|
@ -917,6 +917,59 @@ static ssize_t iwl_dbgfs_indirection_tbl_write(struct iwl_mvm *mvm,
|
||||
return ret ?: count;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_inject_packet_write(struct iwl_mvm *mvm,
|
||||
char *buf, size_t count,
|
||||
loff_t *ppos)
|
||||
{
|
||||
struct iwl_rx_cmd_buffer rxb = {
|
||||
._rx_page_order = 0,
|
||||
.truesize = 0, /* not used */
|
||||
._offset = 0,
|
||||
};
|
||||
struct iwl_rx_packet *pkt;
|
||||
struct iwl_rx_mpdu_desc *desc;
|
||||
int bin_len = count / 2;
|
||||
int ret = -EINVAL;
|
||||
|
||||
/* supporting only 9000 descriptor */
|
||||
if (!mvm->trans->cfg->mq_rx_supported)
|
||||
return -ENOTSUPP;
|
||||
|
||||
rxb._page = alloc_pages(GFP_ATOMIC, 0);
|
||||
if (!rxb._page)
|
||||
return -ENOMEM;
|
||||
pkt = rxb_addr(&rxb);
|
||||
|
||||
ret = hex2bin(page_address(rxb._page), buf, bin_len);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* avoid invalid memory access */
|
||||
if (bin_len < sizeof(*pkt) + sizeof(*desc))
|
||||
goto out;
|
||||
|
||||
/* check this is RX packet */
|
||||
if (WIDE_ID(pkt->hdr.group_id, pkt->hdr.cmd) !=
|
||||
WIDE_ID(LEGACY_GROUP, REPLY_RX_MPDU_CMD))
|
||||
goto out;
|
||||
|
||||
/* check the length in metadata matches actual received length */
|
||||
desc = (void *)pkt->data;
|
||||
if (le16_to_cpu(desc->mpdu_len) !=
|
||||
(bin_len - sizeof(*desc) - sizeof(*pkt)))
|
||||
goto out;
|
||||
|
||||
local_bh_disable();
|
||||
iwl_mvm_rx_mpdu_mq(mvm, NULL, &rxb, 0);
|
||||
local_bh_enable();
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
iwl_free_rxb(&rxb);
|
||||
|
||||
return ret ?: count;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_fw_dbg_conf_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
@ -1454,6 +1507,7 @@ MVM_DEBUGFS_WRITE_FILE_OPS(cont_recording, 8);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(max_amsdu_len, 8);
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(indirection_tbl,
|
||||
(IWL_RSS_INDIRECTION_TABLE_SIZE * 2));
|
||||
MVM_DEBUGFS_WRITE_FILE_OPS(inject_packet, 512);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_BCAST_FILTERING
|
||||
MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256);
|
||||
@ -1464,6 +1518,132 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters_macs, 256);
|
||||
MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram, 8);
|
||||
#endif
|
||||
|
||||
static ssize_t iwl_dbgfs_mem_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_mvm *mvm = file->private_data;
|
||||
struct iwl_dbg_mem_access_cmd cmd = {};
|
||||
struct iwl_dbg_mem_access_rsp *rsp;
|
||||
struct iwl_host_cmd hcmd = {
|
||||
.flags = CMD_WANT_SKB | CMD_SEND_IN_RFKILL,
|
||||
.data = { &cmd, },
|
||||
.len = { sizeof(cmd) },
|
||||
};
|
||||
size_t delta, len;
|
||||
ssize_t ret;
|
||||
|
||||
hcmd.id = iwl_cmd_id(*ppos >> 24 ? UMAC_RD_WR : LMAC_RD_WR,
|
||||
DEBUG_GROUP, 0);
|
||||
cmd.op = cpu_to_le32(DEBUG_MEM_OP_READ);
|
||||
|
||||
/* Take care of alignment of both the position and the length */
|
||||
delta = *ppos & 0x3;
|
||||
cmd.addr = cpu_to_le32(*ppos - delta);
|
||||
cmd.len = cpu_to_le32(min(ALIGN(count + delta, 4) / 4,
|
||||
(size_t)DEBUG_MEM_MAX_SIZE_DWORDS));
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
ret = iwl_mvm_send_cmd(mvm, &hcmd);
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
rsp = (void *)hcmd.resp_pkt->data;
|
||||
if (le32_to_cpu(rsp->status) != DEBUG_MEM_STATUS_SUCCESS) {
|
||||
ret = -ENXIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
len = min((size_t)le32_to_cpu(rsp->len) << 2,
|
||||
iwl_rx_packet_payload_len(hcmd.resp_pkt) - sizeof(*rsp));
|
||||
len = min(len - delta, count);
|
||||
if (len < 0) {
|
||||
ret = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = len - copy_to_user(user_buf, (void *)rsp->data + delta, len);
|
||||
*ppos += ret;
|
||||
|
||||
out:
|
||||
iwl_free_resp(&hcmd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_mem_write(struct file *file,
|
||||
const char __user *user_buf, size_t count,
|
||||
loff_t *ppos)
|
||||
{
|
||||
struct iwl_mvm *mvm = file->private_data;
|
||||
struct iwl_dbg_mem_access_cmd *cmd;
|
||||
struct iwl_dbg_mem_access_rsp *rsp;
|
||||
struct iwl_host_cmd hcmd = {};
|
||||
size_t cmd_size;
|
||||
size_t data_size;
|
||||
u32 op, len;
|
||||
ssize_t ret;
|
||||
|
||||
hcmd.id = iwl_cmd_id(*ppos >> 24 ? UMAC_RD_WR : LMAC_RD_WR,
|
||||
DEBUG_GROUP, 0);
|
||||
|
||||
if (*ppos & 0x3 || count < 4) {
|
||||
op = DEBUG_MEM_OP_WRITE_BYTES;
|
||||
len = min(count, (size_t)(4 - (*ppos & 0x3)));
|
||||
data_size = len;
|
||||
} else {
|
||||
op = DEBUG_MEM_OP_WRITE;
|
||||
len = min(count >> 2, (size_t)DEBUG_MEM_MAX_SIZE_DWORDS);
|
||||
data_size = len << 2;
|
||||
}
|
||||
|
||||
cmd_size = sizeof(*cmd) + ALIGN(data_size, 4);
|
||||
cmd = kzalloc(cmd_size, GFP_KERNEL);
|
||||
if (!cmd)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd->op = cpu_to_le32(op);
|
||||
cmd->len = cpu_to_le32(len);
|
||||
cmd->addr = cpu_to_le32(*ppos);
|
||||
if (copy_from_user((void *)cmd->data, user_buf, data_size)) {
|
||||
kfree(cmd);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
hcmd.flags = CMD_WANT_SKB | CMD_SEND_IN_RFKILL,
|
||||
hcmd.data[0] = (void *)cmd;
|
||||
hcmd.len[0] = cmd_size;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
ret = iwl_mvm_send_cmd(mvm, &hcmd);
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
kfree(cmd);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
rsp = (void *)hcmd.resp_pkt->data;
|
||||
if (rsp->status != DEBUG_MEM_STATUS_SUCCESS) {
|
||||
ret = -ENXIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = data_size;
|
||||
*ppos += ret;
|
||||
|
||||
out:
|
||||
iwl_free_resp(&hcmd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct file_operations iwl_dbgfs_mem_ops = {
|
||||
.read = iwl_dbgfs_mem_read,
|
||||
.write = iwl_dbgfs_mem_write,
|
||||
.open = simple_open,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
|
||||
{
|
||||
struct dentry *bcast_dir __maybe_unused;
|
||||
@ -1502,6 +1682,7 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
|
||||
MVM_DEBUGFS_ADD_FILE(send_echo_cmd, mvm->debugfs_dir, S_IWUSR);
|
||||
MVM_DEBUGFS_ADD_FILE(cont_recording, mvm->debugfs_dir, S_IWUSR);
|
||||
MVM_DEBUGFS_ADD_FILE(indirection_tbl, mvm->debugfs_dir, S_IWUSR);
|
||||
MVM_DEBUGFS_ADD_FILE(inject_packet, mvm->debugfs_dir, S_IWUSR);
|
||||
if (!debugfs_create_bool("enable_scan_iteration_notif",
|
||||
S_IRUSR | S_IWUSR,
|
||||
mvm->debugfs_dir,
|
||||
@ -1560,6 +1741,9 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
|
||||
mvm->debugfs_dir, &mvm->nvm_phy_sku_blob))
|
||||
goto err;
|
||||
|
||||
debugfs_create_file("mem", S_IRUSR | S_IWUSR, dbgfs_dir, mvm,
|
||||
&iwl_dbgfs_mem_ops);
|
||||
|
||||
/*
|
||||
* Create a symlink with mac80211. It will be removed when mac80211
|
||||
* exists (before the opmode exists which removes the target.)
|
||||
|
@ -7,6 +7,7 @@
|
||||
*
|
||||
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
||||
* Copyright(c) 2016 Intel Deutschland GmbH
|
||||
*
|
||||
* 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
|
||||
@ -603,6 +604,8 @@ struct iwl_scan_req_umac_tail {
|
||||
* @uid: scan id, &enum iwl_umac_scan_uid_offsets
|
||||
* @ooc_priority: out of channel priority - &enum iwl_scan_priority
|
||||
* @general_flags: &enum iwl_umac_scan_general_flags
|
||||
* @reserved2: for future use and alignment
|
||||
* @scan_start_mac_id: report the scan start TSF time according to this mac TSF
|
||||
* @extended_dwell: dwell time for channels 1, 6 and 11
|
||||
* @active_dwell: dwell time for active scan
|
||||
* @passive_dwell: dwell time for passive scan
|
||||
@ -620,8 +623,10 @@ struct iwl_scan_req_umac {
|
||||
__le32 flags;
|
||||
__le32 uid;
|
||||
__le32 ooc_priority;
|
||||
/* SCAN_GENERAL_PARAMS_API_S_VER_1 */
|
||||
__le32 general_flags;
|
||||
/* SCAN_GENERAL_PARAMS_API_S_VER_4 */
|
||||
__le16 general_flags;
|
||||
u8 reserved2;
|
||||
u8 scan_start_mac_id;
|
||||
u8 extended_dwell;
|
||||
u8 active_dwell;
|
||||
u8 passive_dwell;
|
||||
@ -629,7 +634,7 @@ struct iwl_scan_req_umac {
|
||||
__le32 max_out_time;
|
||||
__le32 suspend_time;
|
||||
__le32 scan_priority;
|
||||
/* SCAN_CHANNEL_PARAMS_API_S_VER_1 */
|
||||
/* SCAN_CHANNEL_PARAMS_API_S_VER_4 */
|
||||
u8 channel_flags;
|
||||
u8 n_channels;
|
||||
__le16 reserved;
|
||||
@ -718,8 +723,8 @@ struct iwl_scan_offload_profiles_query {
|
||||
* @status: one of SCAN_COMP_STATUS_*
|
||||
* @bt_status: BT on/off status
|
||||
* @last_channel: last channel that was scanned
|
||||
* @tsf_low: TSF timer (lower half) in usecs
|
||||
* @tsf_high: TSF timer (higher half) in usecs
|
||||
* @start_tsf: TSF timer in usecs of the scan start time for the mac specified
|
||||
* in &struct iwl_scan_req_umac.
|
||||
* @results: array of scan results, only "scanned_channels" of them are valid
|
||||
*/
|
||||
struct iwl_umac_scan_iter_complete_notif {
|
||||
@ -728,9 +733,8 @@ struct iwl_umac_scan_iter_complete_notif {
|
||||
u8 status;
|
||||
u8 bt_status;
|
||||
u8 last_channel;
|
||||
__le32 tsf_low;
|
||||
__le32 tsf_high;
|
||||
__le64 start_tsf;
|
||||
struct iwl_scan_results_notif results[];
|
||||
} __packed; /* SCAN_ITER_COMPLETE_NTF_UMAC_API_S_VER_1 */
|
||||
} __packed; /* SCAN_ITER_COMPLETE_NTF_UMAC_API_S_VER_2 */
|
||||
|
||||
#endif
|
||||
|
@ -205,7 +205,7 @@ enum {
|
||||
/* Phy */
|
||||
PHY_CONFIGURATION_CMD = 0x6a,
|
||||
CALIB_RES_NOTIF_PHY_DB = 0x6b,
|
||||
/* PHY_DB_CMD = 0x6c, */
|
||||
PHY_DB_CMD = 0x6c,
|
||||
|
||||
/* ToF - 802.11mc FTM */
|
||||
TOF_CMD = 0x10,
|
||||
@ -340,6 +340,11 @@ enum iwl_prot_offload_subcmd_ids {
|
||||
STORED_BEACON_NTF = 0xFF,
|
||||
};
|
||||
|
||||
enum iwl_fmac_debug_cmds {
|
||||
LMAC_RD_WR = 0x0,
|
||||
UMAC_RD_WR = 0x1,
|
||||
};
|
||||
|
||||
/* command groups */
|
||||
enum {
|
||||
LEGACY_GROUP = 0x0,
|
||||
@ -349,6 +354,7 @@ enum {
|
||||
PHY_OPS_GROUP = 0x4,
|
||||
DATA_PATH_GROUP = 0x5,
|
||||
PROT_OFFLOAD_GROUP = 0xb,
|
||||
DEBUG_GROUP = 0xf,
|
||||
};
|
||||
|
||||
/**
|
||||
@ -2149,4 +2155,48 @@ struct iwl_channel_switch_noa_notif {
|
||||
__le32 id_and_color;
|
||||
} __packed; /* CHANNEL_SWITCH_START_NTFY_API_S_VER_1 */
|
||||
|
||||
/* Operation types for the debug mem access */
|
||||
enum {
|
||||
DEBUG_MEM_OP_READ = 0,
|
||||
DEBUG_MEM_OP_WRITE = 1,
|
||||
DEBUG_MEM_OP_WRITE_BYTES = 2,
|
||||
};
|
||||
|
||||
#define DEBUG_MEM_MAX_SIZE_DWORDS 32
|
||||
|
||||
/**
|
||||
* struct iwl_dbg_mem_access_cmd - Request the device to read/write memory
|
||||
* @op: DEBUG_MEM_OP_*
|
||||
* @addr: address to read/write from/to
|
||||
* @len: in dwords, to read/write
|
||||
* @data: for write opeations, contains the source buffer
|
||||
*/
|
||||
struct iwl_dbg_mem_access_cmd {
|
||||
__le32 op;
|
||||
__le32 addr;
|
||||
__le32 len;
|
||||
__le32 data[];
|
||||
} __packed; /* DEBUG_(U|L)MAC_RD_WR_CMD_API_S_VER_1 */
|
||||
|
||||
/* Status responses for the debug mem access */
|
||||
enum {
|
||||
DEBUG_MEM_STATUS_SUCCESS = 0x0,
|
||||
DEBUG_MEM_STATUS_FAILED = 0x1,
|
||||
DEBUG_MEM_STATUS_LOCKED = 0x2,
|
||||
DEBUG_MEM_STATUS_HIDDEN = 0x3,
|
||||
DEBUG_MEM_STATUS_LENGTH = 0x4,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_dbg_mem_access_rsp - Response to debug mem commands
|
||||
* @status: DEBUG_MEM_STATUS_*
|
||||
* @len: read dwords (0 for write operations)
|
||||
* @data: contains the read DWs
|
||||
*/
|
||||
struct iwl_dbg_mem_access_rsp {
|
||||
__le32 status;
|
||||
__le32 len;
|
||||
__le32 data[];
|
||||
} __packed; /* DEBUG_(U|L)MAC_RD_WR_RSP_API_S_VER_1 */
|
||||
|
||||
#endif /* __fw_api_h__ */
|
||||
|
@ -539,6 +539,11 @@ void iwl_mvm_mac_ctxt_release(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
|
||||
iwl_mvm_disable_txq(mvm, IWL_MVM_OFFCHANNEL_QUEUE,
|
||||
IWL_MVM_OFFCHANNEL_QUEUE,
|
||||
IWL_MAX_TID_COUNT, 0);
|
||||
else
|
||||
iwl_mvm_disable_txq(mvm,
|
||||
IWL_MVM_DQA_P2P_DEVICE_QUEUE,
|
||||
vif->hw_queue[0], IWL_MAX_TID_COUNT,
|
||||
0);
|
||||
|
||||
break;
|
||||
case NL80211_IFTYPE_AP:
|
||||
@ -769,26 +774,6 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
|
||||
cmd->ac[txf].fifos_mask = BIT(txf);
|
||||
}
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_AP) {
|
||||
/* in AP mode, the MCAST FIFO takes the EDCA params from VO */
|
||||
cmd->ac[IWL_MVM_TX_FIFO_VO].fifos_mask |=
|
||||
BIT(IWL_MVM_TX_FIFO_MCAST);
|
||||
|
||||
/*
|
||||
* in AP mode, pass probe requests and beacons from other APs
|
||||
* (needed for ht protection); when there're no any associated
|
||||
* station don't ask FW to pass beacons to prevent unnecessary
|
||||
* wake-ups.
|
||||
*/
|
||||
cmd->filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST);
|
||||
if (mvmvif->ap_assoc_sta_count || !mvm->drop_bcn_ap_mode) {
|
||||
cmd->filter_flags |= cpu_to_le32(MAC_FILTER_IN_BEACON);
|
||||
IWL_DEBUG_HC(mvm, "Asking FW to pass beacons\n");
|
||||
} else {
|
||||
IWL_DEBUG_HC(mvm, "No need to receive beacons\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (vif->bss_conf.qos)
|
||||
cmd->qos_flags |= cpu_to_le32(MAC_QOS_FLG_UPDATE_EDCA);
|
||||
|
||||
@ -1186,6 +1171,7 @@ static void iwl_mvm_mac_ap_iterator(void *_data, u8 *mac,
|
||||
*/
|
||||
static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct iwl_mac_ctx_cmd *cmd,
|
||||
struct iwl_mac_data_ap *ctxt_ap,
|
||||
bool add)
|
||||
{
|
||||
@ -1196,6 +1182,23 @@ static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm,
|
||||
.beacon_device_ts = 0
|
||||
};
|
||||
|
||||
/* in AP mode, the MCAST FIFO takes the EDCA params from VO */
|
||||
cmd->ac[IWL_MVM_TX_FIFO_VO].fifos_mask |= BIT(IWL_MVM_TX_FIFO_MCAST);
|
||||
|
||||
/*
|
||||
* in AP mode, pass probe requests and beacons from other APs
|
||||
* (needed for ht protection); when there're no any associated
|
||||
* station don't ask FW to pass beacons to prevent unnecessary
|
||||
* wake-ups.
|
||||
*/
|
||||
cmd->filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST);
|
||||
if (mvmvif->ap_assoc_sta_count || !mvm->drop_bcn_ap_mode) {
|
||||
cmd->filter_flags |= cpu_to_le32(MAC_FILTER_IN_BEACON);
|
||||
IWL_DEBUG_HC(mvm, "Asking FW to pass beacons\n");
|
||||
} else {
|
||||
IWL_DEBUG_HC(mvm, "No need to receive beacons\n");
|
||||
}
|
||||
|
||||
ctxt_ap->bi = cpu_to_le32(vif->bss_conf.beacon_int);
|
||||
ctxt_ap->bi_reciprocal =
|
||||
cpu_to_le32(iwl_mvm_reciprocal(vif->bss_conf.beacon_int));
|
||||
@ -1253,7 +1256,7 @@ static int iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm *mvm,
|
||||
iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action);
|
||||
|
||||
/* 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, &cmd.ap,
|
||||
action == FW_CTXT_ACTION_ADD);
|
||||
|
||||
return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
|
||||
@ -1272,7 +1275,7 @@ static int iwl_mvm_mac_ctxt_cmd_go(struct iwl_mvm *mvm,
|
||||
iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, 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, &cmd.go.ap,
|
||||
action == FW_CTXT_ACTION_ADD);
|
||||
|
||||
cmd.go.ctwin = cpu_to_le32(noa->oppps_ctwindow &
|
||||
|
@ -653,6 +653,16 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
|
||||
IWL_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT))
|
||||
hw->wiphy->features |= NL80211_FEATURE_WFA_TPC_IE_IN_PROBES;
|
||||
|
||||
if (fw_has_api(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_API_SCAN_TSF_REPORT)) {
|
||||
wiphy_ext_feature_set(hw->wiphy,
|
||||
NL80211_EXT_FEATURE_SCAN_START_TIME);
|
||||
wiphy_ext_feature_set(hw->wiphy,
|
||||
NL80211_EXT_FEATURE_BSS_PARENT_TSF);
|
||||
wiphy_ext_feature_set(hw->wiphy,
|
||||
NL80211_EXT_FEATURE_SET_SCAN_DWELL);
|
||||
}
|
||||
|
||||
mvm->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
@ -720,6 +730,10 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
|
||||
if (ret)
|
||||
iwl_mvm_leds_exit(mvm);
|
||||
|
||||
if (mvm->cfg->vht_mu_mimo_supported)
|
||||
wiphy_ext_feature_set(hw->wiphy,
|
||||
NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2229,6 +2243,10 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
iwl_mvm_bss_info_changed_ap_ibss(mvm, vif, bss_conf, changes);
|
||||
break;
|
||||
case NL80211_IFTYPE_MONITOR:
|
||||
if (changes & BSS_CHANGED_MU_GROUPS)
|
||||
iwl_mvm_update_mu_groups(mvm, vif);
|
||||
break;
|
||||
default:
|
||||
/* shouldn't happen */
|
||||
WARN_ON_ONCE(1);
|
||||
|
@ -821,6 +821,12 @@ struct iwl_mvm {
|
||||
/* UMAC scan tracking */
|
||||
u32 scan_uid_status[IWL_MVM_MAX_UMAC_SCANS];
|
||||
|
||||
/* start time of last scan in TSF of the mac that requested the scan */
|
||||
u64 scan_start;
|
||||
|
||||
/* the vif that requested the current scan */
|
||||
struct iwl_mvm_vif *scan_vif;
|
||||
|
||||
/* rx chain antennas set through debugfs for the scan command */
|
||||
u8 scan_rx_ant;
|
||||
|
||||
@ -1262,6 +1268,7 @@ u8 iwl_mvm_mac80211_idx_to_hwrate(int rate_idx);
|
||||
void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm);
|
||||
u8 first_antenna(u8 mask);
|
||||
u8 iwl_mvm_next_antenna(struct iwl_mvm *mvm, u8 valid, u8 last_idx);
|
||||
void iwl_mvm_get_sync_time(struct iwl_mvm *mvm, u32 *gp2, u64 *boottime);
|
||||
|
||||
/* Tx / Host Commands */
|
||||
int __must_check iwl_mvm_send_cmd(struct iwl_mvm *mvm,
|
||||
|
@ -66,7 +66,6 @@
|
||||
*****************************************************************************/
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/acpi.h>
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-csr.h"
|
||||
#include "mvm.h"
|
||||
@ -751,96 +750,6 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2,
|
||||
return resp_cp;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
#define WRD_METHOD "WRDD"
|
||||
#define WRDD_WIFI (0x07)
|
||||
#define WRDD_WIGIG (0x10)
|
||||
|
||||
static u32 iwl_mvm_wrdd_get_mcc(struct iwl_mvm *mvm, union acpi_object *wrdd)
|
||||
{
|
||||
union acpi_object *mcc_pkg, *domain_type, *mcc_value;
|
||||
u32 i;
|
||||
|
||||
if (wrdd->type != ACPI_TYPE_PACKAGE ||
|
||||
wrdd->package.count < 2 ||
|
||||
wrdd->package.elements[0].type != ACPI_TYPE_INTEGER ||
|
||||
wrdd->package.elements[0].integer.value != 0) {
|
||||
IWL_DEBUG_LAR(mvm, "Unsupported wrdd structure\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 1 ; i < wrdd->package.count ; ++i) {
|
||||
mcc_pkg = &wrdd->package.elements[i];
|
||||
|
||||
if (mcc_pkg->type != ACPI_TYPE_PACKAGE ||
|
||||
mcc_pkg->package.count < 2 ||
|
||||
mcc_pkg->package.elements[0].type != ACPI_TYPE_INTEGER ||
|
||||
mcc_pkg->package.elements[1].type != ACPI_TYPE_INTEGER) {
|
||||
mcc_pkg = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
domain_type = &mcc_pkg->package.elements[0];
|
||||
if (domain_type->integer.value == WRDD_WIFI)
|
||||
break;
|
||||
|
||||
mcc_pkg = NULL;
|
||||
}
|
||||
|
||||
if (mcc_pkg) {
|
||||
mcc_value = &mcc_pkg->package.elements[1];
|
||||
return mcc_value->integer.value;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_mvm_get_bios_mcc(struct iwl_mvm *mvm, char *mcc)
|
||||
{
|
||||
acpi_handle root_handle;
|
||||
acpi_handle handle;
|
||||
struct acpi_buffer wrdd = {ACPI_ALLOCATE_BUFFER, NULL};
|
||||
acpi_status status;
|
||||
u32 mcc_val;
|
||||
|
||||
root_handle = ACPI_HANDLE(mvm->dev);
|
||||
if (!root_handle) {
|
||||
IWL_DEBUG_LAR(mvm,
|
||||
"Could not retrieve root port ACPI handle\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/* Get the method's handle */
|
||||
status = acpi_get_handle(root_handle, (acpi_string)WRD_METHOD, &handle);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
IWL_DEBUG_LAR(mvm, "WRD method not found\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/* Call WRDD with no arguments */
|
||||
status = acpi_evaluate_object(handle, NULL, NULL, &wrdd);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
IWL_DEBUG_LAR(mvm, "WRDC invocation failed (0x%x)\n", status);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
mcc_val = iwl_mvm_wrdd_get_mcc(mvm, wrdd.pointer);
|
||||
kfree(wrdd.pointer);
|
||||
if (!mcc_val)
|
||||
return -ENOENT;
|
||||
|
||||
mcc[0] = (mcc_val >> 8) & 0xff;
|
||||
mcc[1] = mcc_val & 0xff;
|
||||
mcc[2] = '\0';
|
||||
return 0;
|
||||
}
|
||||
#else /* CONFIG_ACPI */
|
||||
static int iwl_mvm_get_bios_mcc(struct iwl_mvm *mvm, char *mcc)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
#endif
|
||||
|
||||
int iwl_mvm_init_mcc(struct iwl_mvm *mvm)
|
||||
{
|
||||
bool tlv_lar;
|
||||
@ -884,7 +793,7 @@ int iwl_mvm_init_mcc(struct iwl_mvm *mvm)
|
||||
return -EIO;
|
||||
|
||||
if (iwl_mvm_is_wifi_mcc_supported(mvm) &&
|
||||
!iwl_mvm_get_bios_mcc(mvm, mcc)) {
|
||||
!iwl_get_bios_mcc(mvm->dev, mcc)) {
|
||||
kfree(regd);
|
||||
regd = iwl_mvm_get_regdomain(mvm->hw->wiphy, mcc,
|
||||
MCC_SOURCE_BIOS, NULL);
|
||||
|
@ -359,6 +359,7 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = {
|
||||
HCMD_NAME(BT_COEX_CI),
|
||||
HCMD_NAME(PHY_CONFIGURATION_CMD),
|
||||
HCMD_NAME(CALIB_RES_NOTIF_PHY_DB),
|
||||
HCMD_NAME(PHY_DB_CMD),
|
||||
HCMD_NAME(SCAN_OFFLOAD_COMPLETE),
|
||||
HCMD_NAME(SCAN_OFFLOAD_UPDATE_PROFILES_CMD),
|
||||
HCMD_NAME(SCAN_OFFLOAD_CONFIG_CMD),
|
||||
@ -652,8 +653,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
/* the hardware splits the A-MSDU */
|
||||
if (mvm->cfg->mq_rx_supported)
|
||||
trans_cfg.rx_buf_size = IWL_AMSDU_4K;
|
||||
trans_cfg.wide_cmd_header = fw_has_api(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_API_WIDE_CMD_HDR);
|
||||
trans->wide_cmd_header = fw_has_api(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_API_WIDE_CMD_HDR);
|
||||
|
||||
if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DW_BC_TABLE)
|
||||
trans_cfg.bc_table_dword = true;
|
||||
@ -857,9 +858,7 @@ static void iwl_mvm_async_handlers_wk(struct work_struct *wk)
|
||||
struct iwl_mvm *mvm =
|
||||
container_of(wk, struct iwl_mvm, async_handlers_wk);
|
||||
struct iwl_async_handler_entry *entry, *tmp;
|
||||
struct list_head local_list;
|
||||
|
||||
INIT_LIST_HEAD(&local_list);
|
||||
LIST_HEAD(local_list);
|
||||
|
||||
/* Ensure that we are not in stop flow (check iwl_mvm_mac_stop) */
|
||||
|
||||
@ -966,10 +965,11 @@ static void iwl_mvm_rx(struct iwl_op_mode *op_mode,
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
|
||||
u16 cmd = WIDE_ID(pkt->hdr.group_id, pkt->hdr.cmd);
|
||||
|
||||
if (likely(pkt->hdr.cmd == REPLY_RX_MPDU_CMD))
|
||||
if (likely(cmd == WIDE_ID(LEGACY_GROUP, REPLY_RX_MPDU_CMD)))
|
||||
iwl_mvm_rx_rx_mpdu(mvm, napi, rxb);
|
||||
else if (pkt->hdr.cmd == REPLY_RX_PHY_CMD)
|
||||
else if (cmd == WIDE_ID(LEGACY_GROUP, REPLY_RX_PHY_CMD))
|
||||
iwl_mvm_rx_rx_phy_cmd(mvm, rxb);
|
||||
else
|
||||
iwl_mvm_rx_common(mvm, rxb, pkt);
|
||||
@ -981,13 +981,14 @@ static void iwl_mvm_rx_mq(struct iwl_op_mode *op_mode,
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
|
||||
u16 cmd = WIDE_ID(pkt->hdr.group_id, pkt->hdr.cmd);
|
||||
|
||||
if (likely(pkt->hdr.cmd == REPLY_RX_MPDU_CMD))
|
||||
if (likely(cmd == WIDE_ID(LEGACY_GROUP, REPLY_RX_MPDU_CMD)))
|
||||
iwl_mvm_rx_mpdu_mq(mvm, napi, rxb, 0);
|
||||
else if (unlikely(pkt->hdr.group_id == DATA_PATH_GROUP &&
|
||||
pkt->hdr.cmd == RX_QUEUES_NOTIFICATION))
|
||||
else if (unlikely(cmd == WIDE_ID(DATA_PATH_GROUP,
|
||||
RX_QUEUES_NOTIFICATION)))
|
||||
iwl_mvm_rx_queue_notif(mvm, rxb, 0);
|
||||
else if (pkt->hdr.cmd == FRAME_RELEASE)
|
||||
else if (cmd == WIDE_ID(LEGACY_GROUP, FRAME_RELEASE))
|
||||
iwl_mvm_rx_frame_release(mvm, napi, rxb, 0);
|
||||
else
|
||||
iwl_mvm_rx_common(mvm, rxb, pkt);
|
||||
@ -1666,13 +1667,14 @@ static void iwl_mvm_rx_mq_rss(struct iwl_op_mode *op_mode,
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
u16 cmd = WIDE_ID(pkt->hdr.group_id, pkt->hdr.cmd);
|
||||
|
||||
if (unlikely(pkt->hdr.cmd == FRAME_RELEASE))
|
||||
if (unlikely(cmd == WIDE_ID(LEGACY_GROUP, FRAME_RELEASE)))
|
||||
iwl_mvm_rx_frame_release(mvm, napi, rxb, queue);
|
||||
else if (unlikely(pkt->hdr.cmd == RX_QUEUES_NOTIFICATION &&
|
||||
pkt->hdr.group_id == DATA_PATH_GROUP))
|
||||
else if (unlikely(cmd == WIDE_ID(DATA_PATH_GROUP,
|
||||
RX_QUEUES_NOTIFICATION)))
|
||||
iwl_mvm_rx_queue_notif(mvm, rxb, queue);
|
||||
else if (likely(pkt->hdr.cmd == REPLY_RX_MPDU_CMD))
|
||||
else if (likely(cmd == WIDE_ID(LEGACY_GROUP, REPLY_RX_MPDU_CMD)))
|
||||
iwl_mvm_rx_mpdu_mq(mvm, napi, rxb, queue);
|
||||
}
|
||||
|
||||
|
@ -418,10 +418,11 @@ static void iwl_mvm_release_frames(struct iwl_mvm *mvm,
|
||||
|
||||
ssn = ieee80211_sn_inc(ssn);
|
||||
|
||||
/* holes are valid since nssn indicates frames were received. */
|
||||
if (skb_queue_empty(skb_list) || !skb_peek_tail(skb_list))
|
||||
continue;
|
||||
/* Empty the list. Will have more than one frame for A-MSDU */
|
||||
/*
|
||||
* Empty the list. Will have more than one frame for A-MSDU.
|
||||
* Empty list is valid as well since nssn indicates frames were
|
||||
* received.
|
||||
*/
|
||||
while ((skb = __skb_dequeue(skb_list))) {
|
||||
iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb,
|
||||
reorder_buf->queue,
|
||||
@ -434,7 +435,7 @@ static void iwl_mvm_release_frames(struct iwl_mvm *mvm,
|
||||
if (reorder_buf->num_stored && !reorder_buf->removed) {
|
||||
u16 index = reorder_buf->head_sn % reorder_buf->buf_size;
|
||||
|
||||
while (!skb_peek_tail(&reorder_buf->entries[index]))
|
||||
while (skb_queue_empty(&reorder_buf->entries[index]))
|
||||
index = (index + 1) % reorder_buf->buf_size;
|
||||
/* modify timer to match next frame's expiration time */
|
||||
mod_timer(&reorder_buf->reorder_timer,
|
||||
@ -462,7 +463,7 @@ void iwl_mvm_reorder_timer_expired(unsigned long data)
|
||||
for (i = 0; i < buf->buf_size ; i++) {
|
||||
index = (buf->head_sn + i) % buf->buf_size;
|
||||
|
||||
if (!skb_peek_tail(&buf->entries[index]))
|
||||
if (skb_queue_empty(&buf->entries[index]))
|
||||
continue;
|
||||
if (!time_after(jiffies, buf->reorder_time[index] +
|
||||
RX_REORDER_BUF_TIMEOUT_MQ))
|
||||
@ -590,6 +591,11 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
|
||||
baid = (reorder & IWL_RX_MPDU_REORDER_BAID_MASK) >>
|
||||
IWL_RX_MPDU_REORDER_BAID_SHIFT;
|
||||
|
||||
/*
|
||||
* This also covers the case of receiving a Block Ack Request
|
||||
* outside a BA session; we'll pass it to mac80211 and that
|
||||
* then sends a delBA action frame.
|
||||
*/
|
||||
if (baid == IWL_RX_REORDER_DATA_INVALID_BAID)
|
||||
return false;
|
||||
|
||||
@ -599,9 +605,10 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
|
||||
|
||||
mvm_sta = iwl_mvm_sta_from_mac80211(sta);
|
||||
|
||||
/* not a data packet */
|
||||
if (!ieee80211_is_data_qos(hdr->frame_control) ||
|
||||
is_multicast_ether_addr(hdr->addr1))
|
||||
/* not a data packet or a bar */
|
||||
if (!ieee80211_is_back_req(hdr->frame_control) &&
|
||||
(!ieee80211_is_data_qos(hdr->frame_control) ||
|
||||
is_multicast_ether_addr(hdr->addr1)))
|
||||
return false;
|
||||
|
||||
if (unlikely(!ieee80211_is_data_present(hdr->frame_control)))
|
||||
@ -625,6 +632,11 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
|
||||
|
||||
spin_lock_bh(&buffer->lock);
|
||||
|
||||
if (ieee80211_is_back_req(hdr->frame_control)) {
|
||||
iwl_mvm_release_frames(mvm, sta, napi, buffer, nssn);
|
||||
goto drop;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there was a significant jump in the nssn - adjust.
|
||||
* If the SN is smaller than the NSSN it might need to first go into
|
||||
|
@ -141,6 +141,7 @@ struct iwl_mvm_scan_params {
|
||||
struct cfg80211_match_set *match_sets;
|
||||
int n_scan_plans;
|
||||
struct cfg80211_sched_scan_plan *scan_plans;
|
||||
u32 measurement_dwell;
|
||||
};
|
||||
|
||||
static u8 iwl_mvm_scan_rx_ant(struct iwl_mvm *mvm)
|
||||
@ -232,6 +233,27 @@ iwl_mvm_scan_type iwl_mvm_get_scan_type(struct iwl_mvm *mvm, bool p2p_device)
|
||||
return IWL_SCAN_TYPE_WILD;
|
||||
}
|
||||
|
||||
static int
|
||||
iwl_mvm_get_measurement_dwell(struct iwl_mvm *mvm,
|
||||
struct cfg80211_scan_request *req,
|
||||
struct iwl_mvm_scan_params *params)
|
||||
{
|
||||
if (!req->duration)
|
||||
return 0;
|
||||
|
||||
if (req->duration_mandatory &&
|
||||
req->duration > scan_timing[params->type].max_out_time) {
|
||||
IWL_DEBUG_SCAN(mvm,
|
||||
"Measurement scan - too long dwell %hu (max out time %u)\n",
|
||||
req->duration,
|
||||
scan_timing[params->type].max_out_time);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return min_t(u32, (u32)req->duration,
|
||||
scan_timing[params->type].max_out_time);
|
||||
}
|
||||
|
||||
static inline bool iwl_mvm_rrm_scan_needed(struct iwl_mvm *mvm)
|
||||
{
|
||||
/* require rrm scan whenever the fw supports it */
|
||||
@ -1033,9 +1055,15 @@ static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm,
|
||||
struct iwl_scan_req_umac *cmd,
|
||||
struct iwl_mvm_scan_params *params)
|
||||
{
|
||||
cmd->extended_dwell = scan_timing[params->type].dwell_extended;
|
||||
cmd->active_dwell = scan_timing[params->type].dwell_active;
|
||||
cmd->passive_dwell = scan_timing[params->type].dwell_passive;
|
||||
if (params->measurement_dwell) {
|
||||
cmd->active_dwell = params->measurement_dwell;
|
||||
cmd->passive_dwell = params->measurement_dwell;
|
||||
cmd->extended_dwell = params->measurement_dwell;
|
||||
} else {
|
||||
cmd->active_dwell = scan_timing[params->type].dwell_active;
|
||||
cmd->passive_dwell = scan_timing[params->type].dwell_passive;
|
||||
cmd->extended_dwell = scan_timing[params->type].dwell_extended;
|
||||
}
|
||||
cmd->fragmented_dwell = scan_timing[params->type].dwell_fragmented;
|
||||
cmd->max_out_time = cpu_to_le32(scan_timing[params->type].max_out_time);
|
||||
cmd->suspend_time = cpu_to_le32(scan_timing[params->type].suspend_time);
|
||||
@ -1067,11 +1095,11 @@ iwl_mvm_umac_scan_cfg_channels(struct iwl_mvm *mvm,
|
||||
}
|
||||
}
|
||||
|
||||
static u32 iwl_mvm_scan_umac_flags(struct iwl_mvm *mvm,
|
||||
static u16 iwl_mvm_scan_umac_flags(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_scan_params *params,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
int flags = 0;
|
||||
u16 flags = 0;
|
||||
|
||||
if (params->n_ssids == 0)
|
||||
flags = IWL_UMAC_SCAN_GEN_FLAGS_PASSIVE;
|
||||
@ -1093,6 +1121,9 @@ static u32 iwl_mvm_scan_umac_flags(struct iwl_mvm *mvm,
|
||||
if (!iwl_mvm_is_regular_scan(params))
|
||||
flags |= IWL_UMAC_SCAN_GEN_FLAGS_PERIODIC;
|
||||
|
||||
if (params->measurement_dwell)
|
||||
flags |= IWL_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE;
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
if (mvm->scan_iter_notif_enabled)
|
||||
flags |= IWL_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE;
|
||||
@ -1119,6 +1150,7 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
mvm->fw->ucode_capa.n_scan_channels;
|
||||
int uid, i;
|
||||
u32 ssid_bitmap = 0;
|
||||
struct iwl_mvm_vif *scan_vif = iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
@ -1136,8 +1168,9 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
mvm->scan_uid_status[uid] = type;
|
||||
|
||||
cmd->uid = cpu_to_le32(uid);
|
||||
cmd->general_flags = cpu_to_le32(iwl_mvm_scan_umac_flags(mvm, params,
|
||||
cmd->general_flags = cpu_to_le16(iwl_mvm_scan_umac_flags(mvm, params,
|
||||
vif));
|
||||
cmd->scan_start_mac_id = scan_vif->id;
|
||||
|
||||
if (type == IWL_MVM_SCAN_SCHED || type == IWL_MVM_SCAN_NETDETECT)
|
||||
cmd->flags = cpu_to_le32(IWL_UMAC_SCAN_FLAG_PREEMPTIVE);
|
||||
@ -1289,6 +1322,12 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
iwl_mvm_get_scan_type(mvm,
|
||||
vif->type == NL80211_IFTYPE_P2P_DEVICE);
|
||||
|
||||
ret = iwl_mvm_get_measurement_dwell(mvm, req, ¶ms);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
params.measurement_dwell = ret;
|
||||
|
||||
iwl_mvm_build_scan_probe(mvm, vif, ies, ¶ms);
|
||||
|
||||
if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN)) {
|
||||
@ -1315,6 +1354,7 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
|
||||
IWL_DEBUG_SCAN(mvm, "Scan request was sent successfully\n");
|
||||
mvm->scan_status |= IWL_MVM_SCAN_REGULAR;
|
||||
mvm->scan_vif = iwl_mvm_vif_from_mac80211(vif);
|
||||
iwl_mvm_ref(mvm, IWL_MVM_REF_SCAN);
|
||||
|
||||
queue_delayed_work(system_wq, &mvm->scan_timeout_dwork,
|
||||
@ -1437,9 +1477,12 @@ void iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm,
|
||||
if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_REGULAR) {
|
||||
struct cfg80211_scan_info info = {
|
||||
.aborted = aborted,
|
||||
.scan_start_tsf = mvm->scan_start,
|
||||
};
|
||||
|
||||
memcpy(info.tsf_bssid, mvm->scan_vif->bssid, ETH_ALEN);
|
||||
ieee80211_scan_completed(mvm->hw, &info);
|
||||
mvm->scan_vif = NULL;
|
||||
iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
|
||||
cancel_delayed_work(&mvm->scan_timeout_dwork);
|
||||
} else if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_SCHED) {
|
||||
@ -1473,6 +1516,8 @@ void iwl_mvm_rx_umac_scan_iter_complete_notif(struct iwl_mvm *mvm,
|
||||
struct iwl_umac_scan_iter_complete_notif *notif = (void *)pkt->data;
|
||||
u8 buf[256];
|
||||
|
||||
mvm->scan_start = le64_to_cpu(notif->start_tsf);
|
||||
|
||||
IWL_DEBUG_SCAN(mvm,
|
||||
"UMAC Scan iteration complete: status=0x%x scanned_channels=%d channels list: %s\n",
|
||||
notif->status, notif->scanned_channels,
|
||||
@ -1485,6 +1530,10 @@ void iwl_mvm_rx_umac_scan_iter_complete_notif(struct iwl_mvm *mvm,
|
||||
ieee80211_sched_scan_results(mvm->hw);
|
||||
mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_ENABLED;
|
||||
}
|
||||
|
||||
IWL_DEBUG_SCAN(mvm,
|
||||
"UMAC Scan iteration complete: scan started at %llu (TSF)\n",
|
||||
mvm->scan_start);
|
||||
}
|
||||
|
||||
static int iwl_mvm_umac_scan_abort(struct iwl_mvm *mvm, int type)
|
||||
|
@ -745,14 +745,14 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm,
|
||||
.scd_queue = queue,
|
||||
.action = SCD_CFG_DISABLE_QUEUE,
|
||||
};
|
||||
u8 ac;
|
||||
u8 txq_curr_ac;
|
||||
|
||||
disable_agg_tids = iwl_mvm_remove_sta_queue_marking(mvm, queue);
|
||||
|
||||
spin_lock_bh(&mvm->queue_info_lock);
|
||||
ac = mvm->queue_info[queue].mac80211_ac;
|
||||
txq_curr_ac = mvm->queue_info[queue].mac80211_ac;
|
||||
cmd.sta_id = mvm->queue_info[queue].ra_sta_id;
|
||||
cmd.tx_fifo = iwl_mvm_ac_to_tx_fifo[ac];
|
||||
cmd.tx_fifo = iwl_mvm_ac_to_tx_fifo[txq_curr_ac];
|
||||
cmd.tid = mvm->queue_info[queue].txq_tid;
|
||||
spin_unlock_bh(&mvm->queue_info_lock);
|
||||
|
||||
@ -1297,13 +1297,6 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_mvm_update_sta(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
return iwl_mvm_sta_send_to_fw(mvm, sta, true, 0);
|
||||
}
|
||||
|
||||
int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
|
||||
bool drain)
|
||||
{
|
||||
|
@ -473,9 +473,14 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
||||
int iwl_mvm_add_sta(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta);
|
||||
int iwl_mvm_update_sta(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta);
|
||||
|
||||
static inline int iwl_mvm_update_sta(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
return iwl_mvm_sta_send_to_fw(mvm, sta, true, 0);
|
||||
}
|
||||
|
||||
int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta);
|
||||
|
@ -490,16 +490,34 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
|
||||
static int iwl_mvm_get_ctrl_vif_queue(struct iwl_mvm *mvm,
|
||||
struct ieee80211_tx_info *info, __le16 fc)
|
||||
{
|
||||
if (iwl_mvm_is_dqa_supported(mvm)) {
|
||||
if (info->control.vif->type == NL80211_IFTYPE_AP &&
|
||||
ieee80211_is_probe_resp(fc))
|
||||
return IWL_MVM_DQA_AP_PROBE_RESP_QUEUE;
|
||||
else if (ieee80211_is_mgmt(fc) &&
|
||||
info->control.vif->type == NL80211_IFTYPE_P2P_DEVICE)
|
||||
return IWL_MVM_DQA_P2P_DEVICE_QUEUE;
|
||||
}
|
||||
if (!iwl_mvm_is_dqa_supported(mvm))
|
||||
return info->hw_queue;
|
||||
|
||||
return info->hw_queue;
|
||||
switch (info->control.vif->type) {
|
||||
case NL80211_IFTYPE_AP:
|
||||
/*
|
||||
* handle legacy hostapd as well, where station may be added
|
||||
* only after assoc.
|
||||
*/
|
||||
if (ieee80211_is_probe_resp(fc) || ieee80211_is_auth(fc))
|
||||
return IWL_MVM_DQA_AP_PROBE_RESP_QUEUE;
|
||||
if (info->hw_queue == info->control.vif->cab_queue)
|
||||
return info->hw_queue;
|
||||
|
||||
WARN_ON_ONCE(1);
|
||||
return IWL_MVM_DQA_AP_PROBE_RESP_QUEUE;
|
||||
case NL80211_IFTYPE_P2P_DEVICE:
|
||||
if (ieee80211_is_mgmt(fc))
|
||||
return IWL_MVM_DQA_P2P_DEVICE_QUEUE;
|
||||
if (info->hw_queue == info->control.vif->cab_queue)
|
||||
return info->hw_queue;
|
||||
|
||||
WARN_ON_ONCE(1);
|
||||
return IWL_MVM_DQA_P2P_DEVICE_QUEUE;
|
||||
default:
|
||||
WARN_ONCE(1, "Not a ctrl vif, no available queue\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
|
||||
@ -560,6 +578,9 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
|
||||
sta_id = mvmvif->bcast_sta.sta_id;
|
||||
queue = iwl_mvm_get_ctrl_vif_queue(mvm, &info,
|
||||
hdr->frame_control);
|
||||
if (queue < 0)
|
||||
return -1;
|
||||
|
||||
} else if (info.control.vif->type == NL80211_IFTYPE_STATION &&
|
||||
is_multicast_ether_addr(hdr->addr1)) {
|
||||
u8 ap_sta_id = ACCESS_ONCE(mvmvif->ap_sta_id);
|
||||
|
@ -1225,6 +1225,28 @@ void iwl_mvm_inactivity_check(struct iwl_mvm *mvm)
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
void iwl_mvm_get_sync_time(struct iwl_mvm *mvm, u32 *gp2, u64 *boottime)
|
||||
{
|
||||
bool ps_disabled;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
/* Disable power save when reading GP2 */
|
||||
ps_disabled = mvm->ps_disabled;
|
||||
if (!ps_disabled) {
|
||||
mvm->ps_disabled = true;
|
||||
iwl_mvm_power_update_device(mvm);
|
||||
}
|
||||
|
||||
*gp2 = iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG);
|
||||
*boottime = ktime_get_boot_ns();
|
||||
|
||||
if (!ps_disabled) {
|
||||
mvm->ps_disabled = ps_disabled;
|
||||
iwl_mvm_power_update_device(mvm);
|
||||
}
|
||||
}
|
||||
|
||||
int iwl_mvm_send_lqm_cmd(struct ieee80211_vif *vif,
|
||||
enum iwl_lqm_cmd_operatrions operation,
|
||||
u32 duration, u32 timeout)
|
||||
|
@ -487,6 +487,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
|
||||
{IWL_PCI_DEVICE(0x24FD, 0x1130, iwl8265_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x24FD, 0x0130, iwl8265_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x24FD, 0x1010, iwl8265_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x24FD, 0x10D0, iwl8265_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x24FD, 0x0050, iwl8265_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x24FD, 0x0150, iwl8265_2ac_cfg)},
|
||||
{IWL_PCI_DEVICE(0x24FD, 0x9010, iwl8265_2ac_cfg)},
|
||||
|
@ -332,7 +332,6 @@ enum iwl_shared_irq_flags {
|
||||
* @rx_buf_size: Rx buffer size
|
||||
* @bc_table_dword: true if the BC table expects DWORD (as opposed to bytes)
|
||||
* @scd_set_active: should the transport configure the SCD for HCMD queue
|
||||
* @wide_cmd_header: true when ucode supports wide command header format
|
||||
* @sw_csum_tx: if true, then the transport will compute the csum of the TXed
|
||||
* frame.
|
||||
* @rx_page_order: page order for receive buffer size
|
||||
@ -405,7 +404,6 @@ struct iwl_trans_pcie {
|
||||
enum iwl_amsdu_size rx_buf_size;
|
||||
bool bc_table_dword;
|
||||
bool scd_set_active;
|
||||
bool wide_cmd_header;
|
||||
bool sw_csum_tx;
|
||||
u32 rx_page_order;
|
||||
|
||||
|
@ -487,15 +487,13 @@ static void iwl_pcie_rx_allocator(struct iwl_trans *trans)
|
||||
|
||||
while (pending) {
|
||||
int i;
|
||||
struct list_head local_allocated;
|
||||
LIST_HEAD(local_allocated);
|
||||
gfp_t gfp_mask = GFP_KERNEL;
|
||||
|
||||
/* Do not post a warning if there are only a few requests */
|
||||
if (pending < RX_PENDING_WATERMARK)
|
||||
gfp_mask |= __GFP_NOWARN;
|
||||
|
||||
INIT_LIST_HEAD(&local_allocated);
|
||||
|
||||
for (i = 0; i < RX_CLAIM_REQ_ALLOC;) {
|
||||
struct iwl_rx_mem_buffer *rxb;
|
||||
struct page *page;
|
||||
@ -1108,13 +1106,14 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
|
||||
FH_RSCSR_RXQ_POS != rxq->id);
|
||||
|
||||
IWL_DEBUG_RX(trans,
|
||||
"cmd at offset %d: %s (0x%.2x, seq 0x%x)\n",
|
||||
"cmd at offset %d: %s (%.2x.%2x, seq 0x%x)\n",
|
||||
rxcb._offset,
|
||||
iwl_get_cmd_string(trans,
|
||||
iwl_cmd_id(pkt->hdr.cmd,
|
||||
pkt->hdr.group_id,
|
||||
0)),
|
||||
pkt->hdr.cmd, le16_to_cpu(pkt->hdr.sequence));
|
||||
pkt->hdr.group_id, pkt->hdr.cmd,
|
||||
le16_to_cpu(pkt->hdr.sequence));
|
||||
|
||||
len = iwl_rx_packet_len(pkt);
|
||||
len += sizeof(u32); /* account for status word */
|
||||
|
@ -1605,24 +1605,22 @@ static int iwl_pcie_init_msix_handler(struct pci_dev *pdev,
|
||||
|
||||
for (i = 0; i < trans_pcie->alloc_vecs; i++) {
|
||||
int ret;
|
||||
struct msix_entry *msix_entry;
|
||||
|
||||
ret = request_threaded_irq(trans_pcie->msix_entries[i].vector,
|
||||
iwl_pcie_msix_isr,
|
||||
(i == trans_pcie->def_irq) ?
|
||||
iwl_pcie_irq_msix_handler :
|
||||
iwl_pcie_irq_rx_msix_handler,
|
||||
IRQF_SHARED,
|
||||
DRV_NAME,
|
||||
&trans_pcie->msix_entries[i]);
|
||||
msix_entry = &trans_pcie->msix_entries[i];
|
||||
ret = devm_request_threaded_irq(&pdev->dev,
|
||||
msix_entry->vector,
|
||||
iwl_pcie_msix_isr,
|
||||
(i == trans_pcie->def_irq) ?
|
||||
iwl_pcie_irq_msix_handler :
|
||||
iwl_pcie_irq_rx_msix_handler,
|
||||
IRQF_SHARED,
|
||||
DRV_NAME,
|
||||
msix_entry);
|
||||
if (ret) {
|
||||
int j;
|
||||
|
||||
IWL_ERR(trans_pcie->trans,
|
||||
"Error allocating IRQ %d\n", i);
|
||||
for (j = 0; j < i; j++)
|
||||
free_irq(trans_pcie->msix_entries[j].vector,
|
||||
&trans_pcie->msix_entries[j]);
|
||||
pci_disable_msix(pdev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@ -1755,7 +1753,6 @@ static void iwl_trans_pcie_configure(struct iwl_trans *trans,
|
||||
trans_pcie->rx_page_order =
|
||||
iwl_trans_get_rb_size_order(trans_pcie->rx_buf_size);
|
||||
|
||||
trans_pcie->wide_cmd_header = trans_cfg->wide_cmd_header;
|
||||
trans_pcie->bc_table_dword = trans_cfg->bc_table_dword;
|
||||
trans_pcie->scd_set_active = trans_cfg->scd_set_active;
|
||||
trans_pcie->sw_csum_tx = trans_cfg->sw_csum_tx;
|
||||
@ -1790,23 +1787,12 @@ void iwl_trans_pcie_free(struct iwl_trans *trans)
|
||||
irq_set_affinity_hint(
|
||||
trans_pcie->msix_entries[i].vector,
|
||||
NULL);
|
||||
|
||||
free_irq(trans_pcie->msix_entries[i].vector,
|
||||
&trans_pcie->msix_entries[i]);
|
||||
}
|
||||
|
||||
pci_disable_msix(trans_pcie->pci_dev);
|
||||
trans_pcie->msix_enabled = false;
|
||||
} else {
|
||||
free_irq(trans_pcie->pci_dev->irq, trans);
|
||||
|
||||
iwl_pcie_free_ict(trans);
|
||||
|
||||
pci_disable_msi(trans_pcie->pci_dev);
|
||||
}
|
||||
iounmap(trans_pcie->hw_base);
|
||||
pci_release_regions(trans_pcie->pci_dev);
|
||||
pci_disable_device(trans_pcie->pci_dev);
|
||||
|
||||
iwl_pcie_free_fw_monitor(trans);
|
||||
|
||||
@ -2913,6 +2899,10 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
||||
struct iwl_trans *trans;
|
||||
int ret, addr_size;
|
||||
|
||||
ret = pcim_enable_device(pdev);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
trans = iwl_trans_alloc(sizeof(struct iwl_trans_pcie),
|
||||
&pdev->dev, cfg, &trans_ops_pcie, 0);
|
||||
if (!trans)
|
||||
@ -2931,9 +2921,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
||||
goto out_no_pci;
|
||||
}
|
||||
|
||||
ret = pci_enable_device(pdev);
|
||||
if (ret)
|
||||
goto out_no_pci;
|
||||
|
||||
if (!cfg->base_params->pcie_l1_allowed) {
|
||||
/*
|
||||
@ -2953,7 +2940,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
||||
|
||||
if (cfg->use_tfh) {
|
||||
trans_pcie->max_tbs = IWL_TFH_NUM_TBS;
|
||||
trans_pcie->tfd_size = sizeof(struct iwl_tfh_tb);
|
||||
trans_pcie->tfd_size = sizeof(struct iwl_tfh_tfd);
|
||||
|
||||
} else {
|
||||
trans_pcie->max_tbs = IWL_NUM_OF_TBS;
|
||||
@ -2975,21 +2962,21 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
||||
/* both attempts failed: */
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "No suitable DMA available\n");
|
||||
goto out_pci_disable_device;
|
||||
goto out_no_pci;
|
||||
}
|
||||
}
|
||||
|
||||
ret = pci_request_regions(pdev, DRV_NAME);
|
||||
ret = pcim_iomap_regions_request_all(pdev, BIT(0), DRV_NAME);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "pci_request_regions failed\n");
|
||||
goto out_pci_disable_device;
|
||||
dev_err(&pdev->dev, "pcim_iomap_regions_request_all failed\n");
|
||||
goto out_no_pci;
|
||||
}
|
||||
|
||||
trans_pcie->hw_base = pci_ioremap_bar(pdev, 0);
|
||||
trans_pcie->hw_base = pcim_iomap_table(pdev)[0];
|
||||
if (!trans_pcie->hw_base) {
|
||||
dev_err(&pdev->dev, "pci_ioremap_bar failed\n");
|
||||
dev_err(&pdev->dev, "pcim_iomap_table failed\n");
|
||||
ret = -ENODEV;
|
||||
goto out_pci_release_regions;
|
||||
goto out_no_pci;
|
||||
}
|
||||
|
||||
/* We disable the RETRY_TIMEOUT register (0x41) to keep
|
||||
@ -3016,7 +3003,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
||||
ret = iwl_pcie_prepare_card_hw(trans);
|
||||
if (ret) {
|
||||
IWL_WARN(trans, "Exit HW not ready\n");
|
||||
goto out_pci_disable_msi;
|
||||
goto out_no_pci;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3033,7 +3020,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
||||
25000);
|
||||
if (ret < 0) {
|
||||
IWL_DEBUG_INFO(trans, "Failed to wake up the nic\n");
|
||||
goto out_pci_disable_msi;
|
||||
goto out_no_pci;
|
||||
}
|
||||
|
||||
if (iwl_trans_grab_nic_access(trans, &flags)) {
|
||||
@ -3065,15 +3052,16 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
||||
|
||||
if (trans_pcie->msix_enabled) {
|
||||
if (iwl_pcie_init_msix_handler(pdev, trans_pcie))
|
||||
goto out_pci_release_regions;
|
||||
goto out_no_pci;
|
||||
} else {
|
||||
ret = iwl_pcie_alloc_ict(trans);
|
||||
if (ret)
|
||||
goto out_pci_disable_msi;
|
||||
goto out_no_pci;
|
||||
|
||||
ret = request_threaded_irq(pdev->irq, iwl_pcie_isr,
|
||||
iwl_pcie_irq_handler,
|
||||
IRQF_SHARED, DRV_NAME, trans);
|
||||
ret = devm_request_threaded_irq(&pdev->dev, pdev->irq,
|
||||
iwl_pcie_isr,
|
||||
iwl_pcie_irq_handler,
|
||||
IRQF_SHARED, DRV_NAME, trans);
|
||||
if (ret) {
|
||||
IWL_ERR(trans, "Error allocating IRQ %d\n", pdev->irq);
|
||||
goto out_free_ict;
|
||||
@ -3091,12 +3079,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
||||
|
||||
out_free_ict:
|
||||
iwl_pcie_free_ict(trans);
|
||||
out_pci_disable_msi:
|
||||
pci_disable_msi(pdev);
|
||||
out_pci_release_regions:
|
||||
pci_release_regions(pdev);
|
||||
out_pci_disable_device:
|
||||
pci_disable_device(pdev);
|
||||
out_no_pci:
|
||||
free_percpu(trans_pcie->tso_hdr_page);
|
||||
iwl_trans_free(trans);
|
||||
|
@ -1493,7 +1493,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
|
||||
const u8 *cmddata[IWL_MAX_CMD_TBS_PER_TFD];
|
||||
u16 cmdlen[IWL_MAX_CMD_TBS_PER_TFD];
|
||||
|
||||
if (WARN(!trans_pcie->wide_cmd_header &&
|
||||
if (WARN(!trans->wide_cmd_header &&
|
||||
group_id > IWL_ALWAYS_LONG_GROUP,
|
||||
"unsupported wide command %#x\n", cmd->id))
|
||||
return -EINVAL;
|
||||
|
Loading…
Reference in New Issue
Block a user