Skip to content

Commit

Permalink
Merge tag 'iwlwifi-next-for-kalle-2019-04-29' of git://git.kernel.org…
Browse files Browse the repository at this point in the history
…/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next

Fourth batch of patches intended for v5.2

* Fix a bug we introduced in the RX path in a previous patch;
* Add command version parsing from the FW TLVs;
* Some fixes and improvements in the new debugging framework;
* Bump the FW API supported for 22000 series;
* Small improvement in FTM;
* Some RF-Kill interrupt handling fixes;
* Support for a new WoWLAN patterns FW API;
* Other small fixes and improvements;
  • Loading branch information
Kalle Valo committed Apr 29, 2019
2 parents 9ef77fb + a0eaead commit c745f72
Show file tree
Hide file tree
Showing 22 changed files with 373 additions and 50 deletions.
2 changes: 1 addition & 1 deletion drivers/net/wireless/intel/iwlwifi/cfg/22000.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
#include "iwl-config.h"

/* Highest firmware API version supported */
#define IWL_22000_UCODE_API_MAX 47
#define IWL_22000_UCODE_API_MAX 48

/* Lowest firmware API version supported */
#define IWL_22000_UCODE_API_MIN 39
Expand Down
136 changes: 130 additions & 6 deletions drivers/net/wireless/intel/iwlwifi/fw/api/d3.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation
* Copyright(c) 2018 - 2019 Intel Corporation
*
* 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
Expand All @@ -31,7 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation
* Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -214,7 +214,7 @@ struct iwl_proto_offload_cmd_v3_large {
#define IWL_WOWLAN_MIN_PATTERN_LEN 16
#define IWL_WOWLAN_MAX_PATTERN_LEN 128

struct iwl_wowlan_pattern {
struct iwl_wowlan_pattern_v1 {
u8 mask[IWL_WOWLAN_MAX_PATTERN_LEN / 8];
u8 pattern[IWL_WOWLAN_MAX_PATTERN_LEN];
u8 mask_size;
Expand All @@ -227,7 +227,7 @@ struct iwl_wowlan_pattern {
/**
* struct iwl_wowlan_patterns_cmd - WoWLAN wakeup patterns
*/
struct iwl_wowlan_patterns_cmd {
struct iwl_wowlan_patterns_cmd_v1 {
/**
* @n_patterns: number of patterns
*/
Expand All @@ -236,9 +236,129 @@ struct iwl_wowlan_patterns_cmd {
/**
* @patterns: the patterns, array length in @n_patterns
*/
struct iwl_wowlan_pattern patterns[];
struct iwl_wowlan_pattern_v1 patterns[];
} __packed; /* WOWLAN_PATTERN_ARRAY_API_S_VER_1 */

#define IPV4_ADDR_SIZE 4
#define IPV6_ADDR_SIZE 16

enum iwl_wowlan_pattern_type {
WOWLAN_PATTERN_TYPE_BITMASK,
WOWLAN_PATTERN_TYPE_IPV4_TCP_SYN,
WOWLAN_PATTERN_TYPE_IPV6_TCP_SYN,
WOWLAN_PATTERN_TYPE_IPV4_TCP_SYN_WILDCARD,
WOWLAN_PATTERN_TYPE_IPV6_TCP_SYN_WILDCARD,
}; /* WOWLAN_PATTERN_TYPE_API_E_VER_1 */

/**
* struct iwl_wowlan_ipv4_tcp_syn - WoWLAN IPv4 TCP SYN pattern data
*/
struct iwl_wowlan_ipv4_tcp_syn {
/**
* @src_addr: source IP address to match
*/
u8 src_addr[IPV4_ADDR_SIZE];

/**
* @dst_addr: destination IP address to match
*/
u8 dst_addr[IPV4_ADDR_SIZE];

/**
* @src_port: source TCP port to match
*/
__le16 src_port;

/**
* @dst_port: destination TCP port to match
*/
__le16 dst_port;
} __packed; /* WOWLAN_IPV4_TCP_SYN_API_S_VER_1 */

/**
* struct iwl_wowlan_ipv6_tcp_syn - WoWLAN Ipv6 TCP SYN pattern data
*/
struct iwl_wowlan_ipv6_tcp_syn {
/**
* @src_addr: source IP address to match
*/
u8 src_addr[IPV6_ADDR_SIZE];

/**
* @dst_addr: destination IP address to match
*/
u8 dst_addr[IPV6_ADDR_SIZE];

/**
* @src_port: source TCP port to match
*/
__le16 src_port;

/**
* @dst_port: destination TCP port to match
*/
__le16 dst_port;
} __packed; /* WOWLAN_IPV6_TCP_SYN_API_S_VER_1 */

/**
* union iwl_wowlan_pattern_data - Data for the different pattern types
*
* If wildcard addresses/ports are to be used, the union can be left
* undefined.
*/
union iwl_wowlan_pattern_data {
/**
* @bitmask: bitmask pattern data
*/
struct iwl_wowlan_pattern_v1 bitmask;

/**
* @ipv4_tcp_syn: IPv4 TCP SYN pattern data
*/
struct iwl_wowlan_ipv4_tcp_syn ipv4_tcp_syn;

/**
* @ipv6_tcp_syn: IPv6 TCP SYN pattern data
*/
struct iwl_wowlan_ipv6_tcp_syn ipv6_tcp_syn;
}; /* WOWLAN_PATTERN_API_U_VER_1 */

/**
* struct iwl_wowlan_pattern_v2 - Pattern entry for the WoWLAN wakeup patterns
*/
struct iwl_wowlan_pattern_v2 {
/**
* @pattern_type: defines the struct type to be used in the union
*/
u8 pattern_type;

/**
* @reserved: reserved for alignment
*/
u8 reserved[3];

/**
* @u: the union containing the match data, or undefined for
* wildcard matches
*/
union iwl_wowlan_pattern_data u;
} __packed; /* WOWLAN_PATTERN_API_S_VER_2 */

/**
* struct iwl_wowlan_patterns_cmd - WoWLAN wakeup patterns command
*/
struct iwl_wowlan_patterns_cmd {
/**
* @n_patterns: number of patterns
*/
__le32 n_patterns;

/**
* @patterns: the patterns, array length in @n_patterns
*/
struct iwl_wowlan_pattern_v2 patterns[];
} __packed; /* WOWLAN_PATTERN_ARRAY_API_S_VER_2 */

enum iwl_wowlan_wakeup_filters {
IWL_WOWLAN_WAKEUP_MAGIC_PACKET = BIT(0),
IWL_WOWLAN_WAKEUP_PATTERN_MATCH = BIT(1),
Expand Down Expand Up @@ -383,7 +503,11 @@ enum iwl_wowlan_wakeup_reason {
IWL_WOWLAN_WAKEUP_BY_D3_WAKEUP_HOST_TIMER = BIT(14),
IWL_WOWLAN_WAKEUP_BY_RXFRAME_FILTERED_IN = BIT(15),
IWL_WOWLAN_WAKEUP_BY_BEACON_FILTERED_IN = BIT(16),

IWL_WAKEUP_BY_11W_UNPROTECTED_DEAUTH_OR_DISASSOC = BIT(17),
IWL_WAKEUP_BY_PATTERN_IPV4_TCP_SYN = BIT(18),
IWL_WAKEUP_BY_PATTERN_IPV4_TCP_SYN_WILDCARD = BIT(19),
IWL_WAKEUP_BY_PATTERN_IPV6_TCP_SYN = BIT(20),
IWL_WAKEUP_BY_PATTERN_IPV6_TCP_SYN_WILDCARD = BIT(21),
}; /* WOWLAN_WAKE_UP_REASON_API_E_VER_2 */

struct iwl_wowlan_gtk_status_v1 {
Expand Down
4 changes: 4 additions & 0 deletions drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,8 @@ enum iwl_fw_ini_debug_flow {
* @IWL_FW_INI_REGION_CSR: CSR registers
* @IWL_FW_INI_REGION_NOTIFICATION: FW notification data
* @IWL_FW_INI_REGION_DHC: dhc response to dump
* @IWL_FW_INI_REGION_LMAC_ERROR_TABLE: lmac error table
* @IWL_FW_INI_REGION_UMAC_ERROR_TABLE: umac error table
* @IWL_FW_INI_REGION_NUM: number of region types
*/
enum iwl_fw_ini_region_type {
Expand All @@ -490,6 +492,8 @@ enum iwl_fw_ini_region_type {
IWL_FW_INI_REGION_CSR,
IWL_FW_INI_REGION_NOTIFICATION,
IWL_FW_INI_REGION_DHC,
IWL_FW_INI_REGION_LMAC_ERROR_TABLE,
IWL_FW_INI_REGION_UMAC_ERROR_TABLE,
IWL_FW_INI_REGION_NUM
}; /* FW_DEBUG_TLV_REGION_TYPE_E_VER_1 */

Expand Down
70 changes: 61 additions & 9 deletions drivers/net/wireless/intel/iwlwifi/fw/dbg.c
Original file line number Diff line number Diff line change
Expand Up @@ -917,11 +917,8 @@ iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt,
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_DEV_FW_INFO);
dump_data->len = cpu_to_le32(sizeof(*dump_info));
dump_info = (void *)dump_data->data;
dump_info->device_family =
fwrt->trans->cfg->device_family ==
IWL_DEVICE_FAMILY_7000 ?
cpu_to_le32(IWL_FW_ERROR_DUMP_FAMILY_7) :
cpu_to_le32(IWL_FW_ERROR_DUMP_FAMILY_8);
dump_info->hw_type =
cpu_to_le32(CSR_HW_REV_TYPE(fwrt->trans->hw_rev));
dump_info->hw_step =
cpu_to_le32(CSR_HW_REV_STEP(fwrt->trans->hw_rev));
memcpy(dump_info->fw_human_readable, fwrt->fw->human_readable,
Expand Down Expand Up @@ -1754,12 +1751,18 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt,
continue;
}

/* currently the driver supports always on domain only */
if (le32_to_cpu(reg->domain) != IWL_FW_INI_DBG_DOMAIN_ALWAYS_ON)
continue;

switch (le32_to_cpu(reg->region_type)) {
case IWL_FW_INI_REGION_DEVICE_MEMORY:
case IWL_FW_INI_REGION_PERIPHERY_MAC:
case IWL_FW_INI_REGION_PERIPHERY_PHY:
case IWL_FW_INI_REGION_PERIPHERY_AUX:
case IWL_FW_INI_REGION_CSR:
case IWL_FW_INI_REGION_LMAC_ERROR_TABLE:
case IWL_FW_INI_REGION_UMAC_ERROR_TABLE:
size += hdr_len + iwl_dump_ini_mem_get_size(fwrt, reg);
break;
case IWL_FW_INI_REGION_TXF:
Expand Down Expand Up @@ -1821,6 +1824,8 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt,

switch (le32_to_cpu(reg->region_type)) {
case IWL_FW_INI_REGION_DEVICE_MEMORY:
case IWL_FW_INI_REGION_LMAC_ERROR_TABLE:
case IWL_FW_INI_REGION_UMAC_ERROR_TABLE:
ops.get_num_of_ranges = iwl_dump_ini_mem_ranges;
ops.get_size = iwl_dump_ini_mem_get_size;
ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header;
Expand Down Expand Up @@ -2464,15 +2469,20 @@ static void iwl_fw_dbg_update_regions(struct iwl_fw_runtime *fwrt,
{
void *iter = (void *)tlv->region_config;
int i, size = le32_to_cpu(tlv->num_regions);
const char *err_st =
"WRT: ext=%d. Invalid region %s %d for apply point %d\n";

for (i = 0; i < size; i++) {
struct iwl_fw_ini_region_cfg *reg = iter, **active;
int id = le32_to_cpu(reg->region_id);
u32 type = le32_to_cpu(reg->region_type);

if (WARN(id >= ARRAY_SIZE(fwrt->dump.active_regs),
"WRT: ext=%d. Invalid region id %d for apply point %d\n",
ext, id, pnt))
if (WARN(id >= ARRAY_SIZE(fwrt->dump.active_regs), err_st, ext,
"id", id, pnt))
break;

if (WARN(type == 0 || type >= IWL_FW_INI_REGION_NUM, err_st,
ext, "type", type, pnt))
break;

active = &fwrt->dump.active_regs[id];
Expand All @@ -2498,7 +2508,9 @@ static void iwl_fw_dbg_update_regions(struct iwl_fw_runtime *fwrt,
type == IWL_FW_INI_REGION_PERIPHERY_AUX ||
type == IWL_FW_INI_REGION_INTERNAL_BUFFER ||
type == IWL_FW_INI_REGION_PAGING ||
type == IWL_FW_INI_REGION_CSR)
type == IWL_FW_INI_REGION_CSR ||
type == IWL_FW_INI_REGION_LMAC_ERROR_TABLE ||
type == IWL_FW_INI_REGION_UMAC_ERROR_TABLE)
iter += le32_to_cpu(reg->internal.num_of_ranges) *
sizeof(__le32);

Expand Down Expand Up @@ -2610,6 +2622,20 @@ static void iwl_fw_dbg_update_triggers(struct iwl_fw_runtime *fwrt,
active->trig->occurrences = cpu_to_le32(-1);

active->active = true;

if (id == IWL_FW_TRIGGER_ID_PERIODIC_TRIGGER) {
u32 collect_interval = le32_to_cpu(trig->trigger_data);

/* the minimum allowed interval is 50ms */
if (collect_interval < 50) {
collect_interval = 50;
trig->trigger_data =
cpu_to_le32(collect_interval);
}

mod_timer(&fwrt->dump.periodic_trig,
jiffies + msecs_to_jiffies(collect_interval));
}
next:
iter += sizeof(*trig) + trig_regs_size;

Expand Down Expand Up @@ -2690,8 +2716,34 @@ IWL_EXPORT_SYMBOL(iwl_fw_dbg_apply_point);

void iwl_fwrt_stop_device(struct iwl_fw_runtime *fwrt)
{
del_timer(&fwrt->dump.periodic_trig);
iwl_fw_dbg_collect_sync(fwrt);

iwl_trans_stop_device(fwrt->trans);
}
IWL_EXPORT_SYMBOL(iwl_fwrt_stop_device);

void iwl_fw_dbg_periodic_trig_handler(struct timer_list *t)
{
struct iwl_fw_runtime *fwrt;
enum iwl_fw_ini_trigger_id id = IWL_FW_TRIGGER_ID_PERIODIC_TRIGGER;
int ret;
typeof(fwrt->dump) *dump_ptr = container_of(t, typeof(fwrt->dump),
periodic_trig);

fwrt = container_of(dump_ptr, typeof(*fwrt), dump);

ret = _iwl_fw_dbg_ini_collect(fwrt, id);
if (!ret || ret == -EBUSY) {
struct iwl_fw_ini_trigger *trig =
fwrt->dump.active_trigs[id].trig;
u32 occur = le32_to_cpu(trig->occurrences);
u32 collect_interval = le32_to_cpu(trig->trigger_data);

if (!occur)
return;

mod_timer(&fwrt->dump.periodic_trig,
jiffies + msecs_to_jiffies(collect_interval));
}
}
3 changes: 3 additions & 0 deletions drivers/net/wireless/intel/iwlwifi/fw/dbg.h
Original file line number Diff line number Diff line change
Expand Up @@ -385,11 +385,13 @@ void iwl_fw_dbg_read_d3_debug_data(struct iwl_fw_runtime *fwrt);

static inline void iwl_fw_flush_dump(struct iwl_fw_runtime *fwrt)
{
del_timer(&fwrt->dump.periodic_trig);
flush_delayed_work(&fwrt->dump.wk);
}

static inline void iwl_fw_cancel_dump(struct iwl_fw_runtime *fwrt)
{
del_timer(&fwrt->dump.periodic_trig);
cancel_delayed_work_sync(&fwrt->dump.wk);
}

Expand Down Expand Up @@ -468,4 +470,5 @@ static inline void iwl_fw_error_collect(struct iwl_fw_runtime *fwrt)
}
}

void iwl_fw_dbg_periodic_trig_handler(struct timer_list *t);
#endif /* __iwl_fw_dbg_h__ */
4 changes: 2 additions & 2 deletions drivers/net/wireless/intel/iwlwifi/fw/error-dump.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ enum iwl_fw_error_dump_family {

/**
* struct iwl_fw_error_dump_info - info on the device / firmware
* @device_family: the family of the device (7 / 8)
* @hw_type: the type of the device
* @hw_step: the step of the device
* @fw_human_readable: human readable FW version
* @dev_human_readable: name of the device
Expand All @@ -196,7 +196,7 @@ enum iwl_fw_error_dump_family {
* if the dump collection was not initiated by an assert, the value is 0
*/
struct iwl_fw_error_dump_info {
__le32 device_family;
__le32 hw_type;
__le32 hw_step;
u8 fw_human_readable[FW_VER_HUMAN_READABLE_SZ];
u8 dev_human_readable[64];
Expand Down
Loading

0 comments on commit c745f72

Please sign in to comment.