Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c745f722 authored by Kalle Valo's avatar Kalle Valo
Browse files

Merge tag 'iwlwifi-next-for-kalle-2019-04-29' of...

Merge tag 'iwlwifi-next-for-kalle-2019-04-29' of git://git.kernel.org/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;
parents 9ef77fbe a0eaead4
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -56,7 +56,7 @@
#include "iwl-config.h"
#include "iwl-config.h"


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


/* Lowest firmware API version supported */
/* Lowest firmware API version supported */
#define IWL_22000_UCODE_API_MIN	39
#define IWL_22000_UCODE_API_MIN	39
+130 −6
Original line number Original line Diff line number Diff line
@@ -8,7 +8,7 @@
 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
 * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
 * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
 * Copyright(c) 2015 - 2017 Intel Deutschland 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
 * 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
 * it under the terms of version 2 of the GNU General Public License as
@@ -31,7 +31,7 @@
 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
 * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
 * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
 * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
 * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
 * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
 * Copyright(c) 2018        Intel Corporation
 * Copyright(c) 2018 - 2019 Intel Corporation
 * All rights reserved.
 * All rights reserved.
 *
 *
 * Redistribution and use in source and binary forms, with or without
 * Redistribution and use in source and binary forms, with or without
@@ -214,7 +214,7 @@ struct iwl_proto_offload_cmd_v3_large {
#define IWL_WOWLAN_MIN_PATTERN_LEN	16
#define IWL_WOWLAN_MIN_PATTERN_LEN	16
#define IWL_WOWLAN_MAX_PATTERN_LEN	128
#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 mask[IWL_WOWLAN_MAX_PATTERN_LEN / 8];
	u8 pattern[IWL_WOWLAN_MAX_PATTERN_LEN];
	u8 pattern[IWL_WOWLAN_MAX_PATTERN_LEN];
	u8 mask_size;
	u8 mask_size;
@@ -227,7 +227,7 @@ struct iwl_wowlan_pattern {
/**
/**
 * struct iwl_wowlan_patterns_cmd - WoWLAN wakeup patterns
 * struct iwl_wowlan_patterns_cmd - WoWLAN wakeup patterns
 */
 */
struct iwl_wowlan_patterns_cmd {
struct iwl_wowlan_patterns_cmd_v1 {
	/**
	/**
	 * @n_patterns: number of patterns
	 * @n_patterns: number of patterns
	 */
	 */
@@ -236,9 +236,129 @@ struct iwl_wowlan_patterns_cmd {
	/**
	/**
	 * @patterns: the patterns, array length in @n_patterns
	 * @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 */
} __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 {
enum iwl_wowlan_wakeup_filters {
	IWL_WOWLAN_WAKEUP_MAGIC_PACKET			= BIT(0),
	IWL_WOWLAN_WAKEUP_MAGIC_PACKET			= BIT(0),
	IWL_WOWLAN_WAKEUP_PATTERN_MATCH			= BIT(1),
	IWL_WOWLAN_WAKEUP_PATTERN_MATCH			= BIT(1),
@@ -383,7 +503,11 @@ enum iwl_wowlan_wakeup_reason {
	IWL_WOWLAN_WAKEUP_BY_D3_WAKEUP_HOST_TIMER		= BIT(14),
	IWL_WOWLAN_WAKEUP_BY_D3_WAKEUP_HOST_TIMER		= BIT(14),
	IWL_WOWLAN_WAKEUP_BY_RXFRAME_FILTERED_IN		= BIT(15),
	IWL_WOWLAN_WAKEUP_BY_RXFRAME_FILTERED_IN		= BIT(15),
	IWL_WOWLAN_WAKEUP_BY_BEACON_FILTERED_IN			= BIT(16),
	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 */
}; /* WOWLAN_WAKE_UP_REASON_API_E_VER_2 */


struct iwl_wowlan_gtk_status_v1 {
struct iwl_wowlan_gtk_status_v1 {
+4 −0
Original line number Original line Diff line number Diff line
@@ -473,6 +473,8 @@ enum iwl_fw_ini_debug_flow {
 * @IWL_FW_INI_REGION_CSR: CSR registers
 * @IWL_FW_INI_REGION_CSR: CSR registers
 * @IWL_FW_INI_REGION_NOTIFICATION: FW notification data
 * @IWL_FW_INI_REGION_NOTIFICATION: FW notification data
 * @IWL_FW_INI_REGION_DHC: dhc response to dump
 * @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
 * @IWL_FW_INI_REGION_NUM: number of region types
 */
 */
enum iwl_fw_ini_region_type {
enum iwl_fw_ini_region_type {
@@ -490,6 +492,8 @@ enum iwl_fw_ini_region_type {
	IWL_FW_INI_REGION_CSR,
	IWL_FW_INI_REGION_CSR,
	IWL_FW_INI_REGION_NOTIFICATION,
	IWL_FW_INI_REGION_NOTIFICATION,
	IWL_FW_INI_REGION_DHC,
	IWL_FW_INI_REGION_DHC,
	IWL_FW_INI_REGION_LMAC_ERROR_TABLE,
	IWL_FW_INI_REGION_UMAC_ERROR_TABLE,
	IWL_FW_INI_REGION_NUM
	IWL_FW_INI_REGION_NUM
}; /* FW_DEBUG_TLV_REGION_TYPE_E_VER_1 */
}; /* FW_DEBUG_TLV_REGION_TYPE_E_VER_1 */


+61 −9
Original line number Original line Diff line number Diff line
@@ -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->type = cpu_to_le32(IWL_FW_ERROR_DUMP_DEV_FW_INFO);
		dump_data->len = cpu_to_le32(sizeof(*dump_info));
		dump_data->len = cpu_to_le32(sizeof(*dump_info));
		dump_info = (void *)dump_data->data;
		dump_info = (void *)dump_data->data;
		dump_info->device_family =
		dump_info->hw_type =
			fwrt->trans->cfg->device_family ==
			cpu_to_le32(CSR_HW_REV_TYPE(fwrt->trans->hw_rev));
			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_step =
		dump_info->hw_step =
			cpu_to_le32(CSR_HW_REV_STEP(fwrt->trans->hw_rev));
			cpu_to_le32(CSR_HW_REV_STEP(fwrt->trans->hw_rev));
		memcpy(dump_info->fw_human_readable, fwrt->fw->human_readable,
		memcpy(dump_info->fw_human_readable, fwrt->fw->human_readable,
@@ -1754,12 +1751,18 @@ static int iwl_fw_ini_get_trigger_len(struct iwl_fw_runtime *fwrt,
			continue;
			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)) {
		switch (le32_to_cpu(reg->region_type)) {
		case IWL_FW_INI_REGION_DEVICE_MEMORY:
		case IWL_FW_INI_REGION_DEVICE_MEMORY:
		case IWL_FW_INI_REGION_PERIPHERY_MAC:
		case IWL_FW_INI_REGION_PERIPHERY_MAC:
		case IWL_FW_INI_REGION_PERIPHERY_PHY:
		case IWL_FW_INI_REGION_PERIPHERY_PHY:
		case IWL_FW_INI_REGION_PERIPHERY_AUX:
		case IWL_FW_INI_REGION_PERIPHERY_AUX:
		case IWL_FW_INI_REGION_CSR:
		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);
			size += hdr_len + iwl_dump_ini_mem_get_size(fwrt, reg);
			break;
			break;
		case IWL_FW_INI_REGION_TXF:
		case IWL_FW_INI_REGION_TXF:
@@ -1821,6 +1824,8 @@ static void iwl_fw_ini_dump_trigger(struct iwl_fw_runtime *fwrt,


		switch (le32_to_cpu(reg->region_type)) {
		switch (le32_to_cpu(reg->region_type)) {
		case IWL_FW_INI_REGION_DEVICE_MEMORY:
		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_num_of_ranges = iwl_dump_ini_mem_ranges;
			ops.get_size = iwl_dump_ini_mem_get_size;
			ops.get_size = iwl_dump_ini_mem_get_size;
			ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header;
			ops.fill_mem_hdr = iwl_dump_ini_mem_fill_header;
@@ -2464,15 +2469,20 @@ static void iwl_fw_dbg_update_regions(struct iwl_fw_runtime *fwrt,
{
{
	void *iter = (void *)tlv->region_config;
	void *iter = (void *)tlv->region_config;
	int i, size = le32_to_cpu(tlv->num_regions);
	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++) {
	for (i = 0; i < size; i++) {
		struct iwl_fw_ini_region_cfg *reg = iter, **active;
		struct iwl_fw_ini_region_cfg *reg = iter, **active;
		int id = le32_to_cpu(reg->region_id);
		int id = le32_to_cpu(reg->region_id);
		u32 type = le32_to_cpu(reg->region_type);
		u32 type = le32_to_cpu(reg->region_type);


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

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


		active = &fwrt->dump.active_regs[id];
		active = &fwrt->dump.active_regs[id];
@@ -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_PERIPHERY_AUX ||
			 type == IWL_FW_INI_REGION_INTERNAL_BUFFER ||
			 type == IWL_FW_INI_REGION_INTERNAL_BUFFER ||
			 type == IWL_FW_INI_REGION_PAGING ||
			 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) *
			iter += le32_to_cpu(reg->internal.num_of_ranges) *
				sizeof(__le32);
				sizeof(__le32);


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


		active->active = true;
		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:
next:
		iter += sizeof(*trig) + trig_regs_size;
		iter += sizeof(*trig) + trig_regs_size;


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


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


	iwl_trans_stop_device(fwrt->trans);
	iwl_trans_stop_device(fwrt->trans);
}
}
IWL_EXPORT_SYMBOL(iwl_fwrt_stop_device);
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 −0
Original line number Original line Diff line number Diff line
@@ -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)
static inline void iwl_fw_flush_dump(struct iwl_fw_runtime *fwrt)
{
{
	del_timer(&fwrt->dump.periodic_trig);
	flush_delayed_work(&fwrt->dump.wk);
	flush_delayed_work(&fwrt->dump.wk);
}
}


static inline void iwl_fw_cancel_dump(struct iwl_fw_runtime *fwrt)
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);
	cancel_delayed_work_sync(&fwrt->dump.wk);
}
}


@@ -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__ */
#endif  /* __iwl_fw_dbg_h__ */
Loading