diff options
Diffstat (limited to 'drivers/net/wireless/intel')
39 files changed, 267 insertions, 217 deletions
diff --git a/drivers/net/wireless/intel/iwlegacy/4965-mac.c b/drivers/net/wireless/intel/iwlegacy/4965-mac.c index 69276266ce6f..70e420df1643 100644 --- a/drivers/net/wireless/intel/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/intel/iwlegacy/4965-mac.c @@ -4231,8 +4231,6 @@ il4965_rx_handle(struct il_priv *il) fill_rx = 1; while (i != r) { - int len; - rxb = rxq->queue[i]; /* If an RXB doesn't have a Rx queue slot associated with it, @@ -4246,10 +4244,6 @@ il4965_rx_handle(struct il_priv *il) PAGE_SIZE << il->hw_params.rx_page_order, DMA_FROM_DEVICE); pkt = rxb_addr(rxb); - - len = le32_to_cpu(pkt->len_n_flags) & IL_RX_FRAME_SIZE_MSK; - len += sizeof(u32); /* account for status word */ - reclaim = il_need_reclaim(il, pkt); /* Based on type of command response or notification, diff --git a/drivers/net/wireless/intel/iwlegacy/common.c b/drivers/net/wireless/intel/iwlegacy/common.c index 054fef680aba..17570d62c896 100644 --- a/drivers/net/wireless/intel/iwlegacy/common.c +++ b/drivers/net/wireless/intel/iwlegacy/common.c @@ -541,6 +541,9 @@ il_leds_init(struct il_priv *il) il->led.name = kasprintf(GFP_KERNEL, "%s-led", wiphy_name(il->hw->wiphy)); + if (!il->led.name) + return; + il->led.brightness_set = il_led_brightness_set; il->led.blink_set = il_led_blink_set; il->led.max_brightness = 1; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h b/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h index 7b18e098b125..798731ecbefd 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h @@ -60,6 +60,12 @@ enum iwl_debug_cmds { */ FW_DUMP_COMPLETE_CMD = 0xB, /** + * @FW_CLEAR_BUFFER: + * clears the firmware's internal buffer + * no payload + */ + FW_CLEAR_BUFFER = 0xD, + /** * @MFU_ASSERT_DUMP_NTF: * &struct iwl_mfu_assert_dump_notif */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h index dfe0bebabc81..7ec959244ffc 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h @@ -269,6 +269,9 @@ struct iwl_nvm_access_complete_cmd { __le32 reserved; } __packed; /* NVM_ACCESS_COMPLETE_CMD_API_S_VER_1 */ +#define IWL_MCC_US 0x5553 +#define IWL_MCC_CANADA 0x4341 + /** * struct iwl_mcc_update_cmd - Request the device to update geographic * regulatory profile according to the given MCC (Mobile Country Code). diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 3975a53a9f20..e27774e7ed74 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -880,10 +880,10 @@ iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt, cpu_to_le32(fwrt->trans->hw_rev_step); memcpy(dump_info->fw_human_readable, fwrt->fw->human_readable, sizeof(dump_info->fw_human_readable)); - strncpy(dump_info->dev_human_readable, fwrt->trans->name, - sizeof(dump_info->dev_human_readable) - 1); - strncpy(dump_info->bus_human_readable, fwrt->dev->bus->name, - sizeof(dump_info->bus_human_readable) - 1); + strscpy_pad(dump_info->dev_human_readable, fwrt->trans->name, + sizeof(dump_info->dev_human_readable)); + strscpy_pad(dump_info->bus_human_readable, fwrt->dev->bus->name, + sizeof(dump_info->bus_human_readable)); dump_info->num_of_lmacs = fwrt->smem_cfg.num_lmacs; dump_info->lmac_err_id[0] = cpu_to_le32(fwrt->dump.lmac_err_id[0]); @@ -3395,3 +3395,22 @@ void iwl_fw_disable_dbg_asserts(struct iwl_fw_runtime *fwrt) iwl_trans_send_cmd(fwrt->trans, &hcmd); } IWL_EXPORT_SYMBOL(iwl_fw_disable_dbg_asserts); + +void iwl_fw_dbg_clear_monitor_buf(struct iwl_fw_runtime *fwrt) +{ + struct iwl_fw_dbg_params params = {0}; + + iwl_fw_dbg_stop_sync(fwrt); + + if (fw_has_api(&fwrt->fw->ucode_capa, + IWL_UCODE_TLV_API_INT_DBG_BUF_CLEAR)) { + struct iwl_host_cmd hcmd = { + .id = WIDE_ID(DEBUG_GROUP, FW_CLEAR_BUFFER), + }; + iwl_trans_send_cmd(fwrt->trans, &hcmd); + } + + iwl_dbg_tlv_init_cfg(fwrt); + iwl_fw_dbg_stop_restart_recording(fwrt, ¶ms, false); +} +IWL_EXPORT_SYMBOL(iwl_fw_dbg_clear_monitor_buf); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h index 66b233250c7c..eb38c686b5cb 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h @@ -330,6 +330,7 @@ void iwl_send_dbg_dump_complete_cmd(struct iwl_fw_runtime *fwrt, u32 timepoint, u32 timepoint_data); void iwl_fw_disable_dbg_asserts(struct iwl_fw_runtime *fwrt); +void iwl_fw_dbg_clear_monitor_buf(struct iwl_fw_runtime *fwrt); #define IWL_FW_CHECK_FAILED(_obj, _fmt, ...) \ IWL_ERR_LIMIT(_obj, _fmt, __VA_ARGS__) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h index 03f6e520145f..bfc39bd5bbc6 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/file.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h @@ -20,7 +20,7 @@ struct iwl_ucode_header { __le32 init_size; /* bytes of init code */ __le32 init_data_size; /* bytes of init data */ __le32 boot_size; /* bytes of bootstrap code */ - u8 data[0]; /* in same order as sizes */ + u8 data[]; /* in same order as sizes */ } v1; struct { __le32 build; /* build number */ @@ -29,7 +29,7 @@ struct iwl_ucode_header { __le32 init_size; /* bytes of init code */ __le32 init_data_size; /* bytes of init data */ __le32 boot_size; /* bytes of bootstrap code */ - u8 data[0]; /* in same order as sizes */ + u8 data[]; /* in same order as sizes */ } v2; } u; }; @@ -243,6 +243,10 @@ typedef unsigned int __bitwise iwl_ucode_tlv_api_t; * version tables. * @IWL_UCODE_TLV_API_REDUCED_SCAN_CONFIG: This ucode supports v3 of * SCAN_CONFIG_DB_CMD_API_S. + * @IWL_UCODE_TLV_API_NO_HOST_DISABLE_TX: Firmware offloaded the station disable tx + * logic. + * @IWL_UCODE_TLV_API_INT_DBG_BUF_CLEAR: Firmware supports clearing the debug + * internal buffer * * @NUM_IWL_UCODE_TLV_API: number of bits used */ @@ -280,6 +284,9 @@ enum iwl_ucode_tlv_api { IWL_UCODE_TLV_API_ADWELL_HB_DEF_N_AP = (__force iwl_ucode_tlv_api_t)57, IWL_UCODE_TLV_API_SCAN_EXT_CHAN_VER = (__force iwl_ucode_tlv_api_t)58, IWL_UCODE_TLV_API_BAND_IN_RX_DATA = (__force iwl_ucode_tlv_api_t)59, + /* API Set 2 */ + IWL_UCODE_TLV_API_NO_HOST_DISABLE_TX = (__force iwl_ucode_tlv_api_t)66, + IWL_UCODE_TLV_API_INT_DBG_BUF_CLEAR = (__force iwl_ucode_tlv_api_t)67, NUM_IWL_UCODE_TLV_API /* diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index 02ded22295c1..ae6f1cd4d660 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -377,7 +377,6 @@ struct iwl_cfg { u16 nvm_calib_ver; u32 rx_with_siso_diversity:1, tx_with_siso_diversity:1, - bt_shared_single_ant:1, internal_wimax_coex:1, host_interrupt_operation_mode:1, high_temp:1, diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h index a4df67ff21ba..4511d7fb2279 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-csr.h @@ -354,6 +354,8 @@ enum { #define CSR_HW_RF_ID_TYPE_GF (0x0010D000) #define CSR_HW_RF_ID_TYPE_GF4 (0x0010E000) #define CSR_HW_RF_ID_TYPE_MS (0x00111000) +#define CSR_HW_RF_ID_TYPE_FM (0x00112000) +#define CSR_HW_RF_ID_TYPE_WP (0x00113000) /* HW_RF CHIP STEP */ #define CSR_HW_RF_STEP(_val) (((_val) >> 8) & 0xF) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c index b658cf228fbe..3b14f6476743 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c @@ -1274,7 +1274,7 @@ iwl_dbg_tlv_tp_trigger(struct iwl_fw_runtime *fwrt, bool sync, return 0; } -static void iwl_dbg_tlv_init_cfg(struct iwl_fw_runtime *fwrt) +void iwl_dbg_tlv_init_cfg(struct iwl_fw_runtime *fwrt) { enum iwl_fw_ini_buffer_location *ini_dest = &fwrt->trans->dbg.ini_dest; int ret, i; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.h b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.h index 06fb7d665390..7ed6329fd8ca 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.h @@ -57,6 +57,7 @@ void _iwl_dbg_tlv_time_point(struct iwl_fw_runtime *fwrt, enum iwl_fw_ini_time_point tp_id, union iwl_dbg_tlv_tp_data *tp_data, bool sync); +void iwl_dbg_tlv_init_cfg(struct iwl_fw_runtime *fwrt); static inline void iwl_dbg_tlv_time_point(struct iwl_fw_runtime *fwrt, enum iwl_fw_ini_time_point tp_id, diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-data.h b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-data.h index 347fd95c4e3a..2c280a2fe3df 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-data.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-data.h @@ -3,7 +3,7 @@ * * Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2015 Intel Deutschland GmbH - * Copyright(c) 2018 - 2019 Intel Corporation + * Copyright(c) 2018 - 2019, 2023 Intel Corporation *****************************************************************************/ #if !defined(__IWLWIFI_DEVICE_TRACE_DATA) || defined(TRACE_HEADER_MULTI_READ) @@ -36,20 +36,17 @@ TRACE_EVENT(iwlwifi_dev_tx_tb, TRACE_EVENT(iwlwifi_dev_rx_data, TP_PROTO(const struct device *dev, - const struct iwl_trans *trans, - void *rxbuf, size_t len), - TP_ARGS(dev, trans, rxbuf, len), + void *rxbuf, size_t len, size_t start), + TP_ARGS(dev, rxbuf, len, start), TP_STRUCT__entry( DEV_ENTRY - __dynamic_array(u8, data, - len - iwl_rx_trace_len(trans, rxbuf, len, NULL)) + __dynamic_array(u8, data, len - start) ), TP_fast_assign( - size_t offs = iwl_rx_trace_len(trans, rxbuf, len, NULL); DEV_ASSIGN; - if (offs < len) + if (start < len) memcpy(__get_dynamic_array(data), - ((u8 *)rxbuf) + offs, len - offs); + ((u8 *)rxbuf) + start, len - start); ), TP_printk("[%s] RX frame data", __get_str(dev)) ); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-iwlwifi.h b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-iwlwifi.h index 46ed723f138a..e656bf6bc003 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-iwlwifi.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-iwlwifi.h @@ -4,7 +4,7 @@ * Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018, 2023 Intel Corporation *****************************************************************************/ #if !defined(__IWLWIFI_DEVICE_TRACE_IWLWIFI) || defined(TRACE_HEADER_MULTI_READ) @@ -50,23 +50,20 @@ TRACE_EVENT(iwlwifi_dev_hcmd, ); TRACE_EVENT(iwlwifi_dev_rx, - TP_PROTO(const struct device *dev, const struct iwl_trans *trans, - struct iwl_rx_packet *pkt, size_t len), - TP_ARGS(dev, trans, pkt, len), + TP_PROTO(const struct device *dev, + struct iwl_rx_packet *pkt, size_t len, size_t trace_len, + size_t hdr_offset), + TP_ARGS(dev, pkt, len, trace_len, hdr_offset), TP_STRUCT__entry( DEV_ENTRY __field(u16, cmd) __field(u8, hdr_offset) - __dynamic_array(u8, rxbuf, - iwl_rx_trace_len(trans, pkt, len, NULL)) + __dynamic_array(u8, rxbuf, trace_len) ), TP_fast_assign( - size_t hdr_offset = 0; - DEV_ASSIGN; __entry->cmd = WIDE_ID(pkt->hdr.group_id, pkt->hdr.cmd); - memcpy(__get_dynamic_array(rxbuf), pkt, - iwl_rx_trace_len(trans, pkt, len, &hdr_offset)); + memcpy(__get_dynamic_array(rxbuf), pkt, trace_len); __entry->hdr_offset = hdr_offset; ), TP_printk("[%s] RX cmd %#.2x", diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.c b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.c index e46639b097f4..7e686297963d 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.c @@ -2,7 +2,7 @@ /****************************************************************************** * * Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved. - * Copyright (C) 2018 Intel Corporation + * Copyright (C) 2018, 2023 Intel Corporation *****************************************************************************/ #include <linux/module.h> @@ -20,4 +20,17 @@ EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_event); EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_cont_event); EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_wrap_event); -#endif +#else +#include "iwl-devtrace.h" +#endif /* __CHECKER__ */ + +void __trace_iwlwifi_dev_rx(struct iwl_trans *trans, void *pkt, size_t len) +{ + size_t hdr_offset = 0, trace_len; + + trace_len = iwl_rx_trace_len(trans, pkt, len, &hdr_offset); + trace_iwlwifi_dev_rx(trans->dev, pkt, len, trace_len, hdr_offset); + + if (trace_len < len) + trace_iwlwifi_dev_rx_data(trans->dev, pkt, len, trace_len); +} diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.h index 01fb7b900a6d..c3e09f4fefeb 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.h @@ -7,12 +7,12 @@ *****************************************************************************/ #ifndef __IWLWIFI_DEVICE_TRACE +#define __IWLWIFI_DEVICE_TRACE #include <linux/skbuff.h> #include <linux/ieee80211.h> #include <net/cfg80211.h> #include <net/mac80211.h> #include "iwl-trans.h" -#if !defined(__IWLWIFI_DEVICE_TRACE) static inline bool iwl_trace_data(struct sk_buff *skb) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); @@ -70,9 +70,6 @@ static inline size_t iwl_rx_trace_len(const struct iwl_trans *trans, return sizeof(__le32) + sizeof(*cmd) + trans->rx_mpdu_cmd_hdr_size + ieee80211_hdrlen(hdr->frame_control); } -#endif - -#define __IWLWIFI_DEVICE_TRACE #include <linux/tracepoint.h> #include <linux/device.h> @@ -98,4 +95,20 @@ static inline void trace_ ## name(proto) {} #include "iwl-devtrace-data.h" #include "iwl-devtrace-iwlwifi.h" +#ifdef CONFIG_IWLWIFI_DEVICE_TRACING +DECLARE_TRACEPOINT(iwlwifi_dev_rx); +DECLARE_TRACEPOINT(iwlwifi_dev_rx_data); +#endif + +void __trace_iwlwifi_dev_rx(struct iwl_trans *trans, void *pkt, size_t len); + +static inline void maybe_trace_iwlwifi_dev_rx(struct iwl_trans *trans, + void *pkt, size_t len) +{ +#ifdef CONFIG_IWLWIFI_DEVICE_TRACING + if (tracepoint_enabled(iwlwifi_dev_rx) || + tracepoint_enabled(iwlwifi_dev_rx_data)) + __trace_iwlwifi_dev_rx(trans, pkt, len); +#endif +} #endif /* __IWLWIFI_DEVICE_TRACE */ diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index 6015e1255d2a..402896988686 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c @@ -1029,7 +1029,8 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans, IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK | IEEE80211_EHT_PHY_CAP3_CODEBOOK_4_2_SU_FDBK | IEEE80211_EHT_PHY_CAP3_CODEBOOK_7_5_MU_FDBK | - IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK); + IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK | + IEEE80211_EHT_PHY_CAP3_TRIG_CQI_FDBK); iftype_data->eht_cap.eht_cap_elem.phy_cap_info[4] &= ~(IEEE80211_EHT_PHY_CAP4_PART_BW_DL_MU_MIMO | IEEE80211_EHT_PHY_CAP4_POWER_BOOST_FACT_SUPP); @@ -1608,10 +1609,17 @@ static u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan, /* Set the GO concurrent flag only in case that NO_IR is set. * Otherwise it is meaningless */ - if ((nvm_flags & NVM_CHANNEL_GO_CONCURRENT) && - (flags & NL80211_RRF_NO_IR)) - flags |= NL80211_RRF_GO_CONCURRENT; - + if ((nvm_flags & NVM_CHANNEL_GO_CONCURRENT)) { + if (flags & NL80211_RRF_NO_IR) + flags |= NL80211_RRF_GO_CONCURRENT; + if (flags & NL80211_RRF_DFS) { + flags |= NL80211_RRF_DFS_CONCURRENT; + /* Our device doesn't set active bit for DFS channels + * however, once marked as DFS no-ir is not needed. + */ + flags &= ~NL80211_RRF_NO_IR; + } + } /* * reg_capa is per regulatory domain so apply it for every channel */ diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-op-mode.h b/drivers/net/wireless/intel/iwlwifi/iwl-op-mode.h index af5f9b210f22..3dc618a7c70f 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-op-mode.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-op-mode.h @@ -64,8 +64,6 @@ struct iwl_cfg; * received on the RSS queue(s). The queue parameter indicates which of the * RSS queues received this frame; it will always be non-zero. * This method must not sleep. - * @async_cb: called when an ASYNC command with CMD_WANT_ASYNC_CALLBACK set - * completes. Must be atomic. * @queue_full: notifies that a HW queue is full. * Must be atomic and called with BH disabled. * @queue_not_full: notifies that a HW queue is not full any more. @@ -96,8 +94,6 @@ struct iwl_op_mode_ops { struct iwl_rx_cmd_buffer *rxb); void (*rx_rss)(struct iwl_op_mode *op_mode, struct napi_struct *napi, struct iwl_rx_cmd_buffer *rxb, unsigned int queue); - void (*async_cb)(struct iwl_op_mode *op_mode, - const struct iwl_device_cmd *cmd); void (*queue_full)(struct iwl_op_mode *op_mode, int queue); void (*queue_not_full)(struct iwl_op_mode *op_mode, int queue); bool (*hw_rf_kill)(struct iwl_op_mode *op_mode, bool state); @@ -147,13 +143,6 @@ static inline void iwl_op_mode_rx_rss(struct iwl_op_mode *op_mode, op_mode->ops->rx_rss(op_mode, napi, rxb, queue); } -static inline void iwl_op_mode_async_cb(struct iwl_op_mode *op_mode, - const struct iwl_device_cmd *cmd) -{ - if (op_mode->ops->async_cb) - op_mode->ops->async_cb(op_mode, cmd); -} - static inline void iwl_op_mode_queue_full(struct iwl_op_mode *op_mode, int queue) { diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c index 4bd759432d44..f95098c21c7d 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c @@ -172,10 +172,6 @@ int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) return -EIO; } - if (WARN_ON((cmd->flags & CMD_WANT_ASYNC_CALLBACK) && - !(cmd->flags & CMD_ASYNC))) - return -EINVAL; - if (!(cmd->flags & CMD_ASYNC)) lock_map_acquire_read(&trans->sync_cmd_lockdep_map); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index 05e72a2125b3..5789a8735976 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -110,8 +110,7 @@ static inline u32 iwl_rx_packet_payload_len(const struct iwl_rx_packet *pkt) * @CMD_WANT_SKB: Not valid with CMD_ASYNC. The caller needs the buffer of * the response. The caller needs to call iwl_free_resp when done. * @CMD_SEND_IN_RFKILL: Send the command even if the NIC is in RF-kill. - * @CMD_WANT_ASYNC_CALLBACK: the op_mode's async callback function must be - * called after this command completes. Valid only with CMD_ASYNC. + * @CMD_BLOCK_TXQS: Block TXQs while the comment is executing. * @CMD_SEND_IN_D3: Allow the command to be sent in D3 mode, relevant to * SUSPEND and RESUME commands. We are in D3 mode when we set * trans->system_pm_mode to IWL_PLAT_PM_MODE_D3. @@ -120,7 +119,7 @@ enum CMD_MODE { CMD_ASYNC = BIT(0), CMD_WANT_SKB = BIT(1), CMD_SEND_IN_RFKILL = BIT(2), - CMD_WANT_ASYNC_CALLBACK = BIT(3), + CMD_BLOCK_TXQS = BIT(3), CMD_SEND_IN_D3 = BIT(4), }; @@ -534,11 +533,6 @@ struct iwl_pnvm_image { * @wait_txq_empty: wait until specific tx queue is empty. May sleep. * @freeze_txq_timer: prevents the timer of the queue from firing until the * queue is set to awake. Must be atomic. - * @block_txq_ptrs: stop updating the write pointers of the Tx queues. Note - * that the transport needs to refcount the calls since this function - * will be called several times with block = true, and then the queues - * need to be unblocked only after the same number of calls with - * block = false. * @write8: write a u8 to a register at offset ofs from the BAR * @write32: write a u32 to a register at offset ofs from the BAR * @read32: read a u32 register at offset ofs from the BAR @@ -613,7 +607,6 @@ struct iwl_trans_ops { int (*wait_txq_empty)(struct iwl_trans *trans, int queue); void (*freeze_txq_timer)(struct iwl_trans *trans, unsigned long txqs, bool freeze); - void (*block_txq_ptrs)(struct iwl_trans *trans, bool block); void (*write8)(struct iwl_trans *trans, u32 ofs, u8 val); void (*write32)(struct iwl_trans *trans, u32 ofs, u32 val); @@ -1323,7 +1316,7 @@ iwl_trans_get_rxq_dma_data(struct iwl_trans *trans, int queue, struct iwl_trans_rxq_dma_data *data) { if (WARN_ON_ONCE(!trans->ops->rxq_dma_data)) - return -ENOTSUPP; + return -EOPNOTSUPP; return trans->ops->rxq_dma_data(trans, queue, data); } @@ -1345,7 +1338,7 @@ iwl_trans_txq_alloc(struct iwl_trans *trans, might_sleep(); if (WARN_ON_ONCE(!trans->ops->txq_alloc)) - return -ENOTSUPP; + return -EOPNOTSUPP; if (WARN_ON_ONCE(trans->state != IWL_TRANS_FW_ALIVE)) { IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state); @@ -1407,23 +1400,11 @@ static inline void iwl_trans_freeze_txq_timer(struct iwl_trans *trans, trans->ops->freeze_txq_timer(trans, txqs, freeze); } -static inline void iwl_trans_block_txq_ptrs(struct iwl_trans *trans, - bool block) -{ - if (WARN_ON_ONCE(trans->state != IWL_TRANS_FW_ALIVE)) { - IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state); - return; - } - - if (trans->ops->block_txq_ptrs) - trans->ops->block_txq_ptrs(trans, block); -} - static inline int iwl_trans_wait_tx_queues_empty(struct iwl_trans *trans, u32 txqs) { if (WARN_ON_ONCE(!trans->ops->wait_tx_queues_empty)) - return -ENOTSUPP; + return -EOPNOTSUPP; /* No need to wait if the firmware is not alive */ if (trans->state != IWL_TRANS_FW_ALIVE) { @@ -1437,7 +1418,7 @@ static inline int iwl_trans_wait_tx_queues_empty(struct iwl_trans *trans, static inline int iwl_trans_wait_txq_empty(struct iwl_trans *trans, int queue) { if (WARN_ON_ONCE(!trans->ops->wait_txq_empty)) - return -ENOTSUPP; + return -EOPNOTSUPP; if (WARN_ON_ONCE(trans->state != IWL_TRANS_FW_ALIVE)) { IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c index 5a5b1128e75c..9fe1761691ec 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2013-2014, 2018-2020, 2022 Intel Corporation + * Copyright (C) 2013-2014, 2018-2020, 2022-2023 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH */ #include <linux/ieee80211.h> @@ -116,11 +116,6 @@ iwl_get_coex_type(struct iwl_mvm *mvm, const struct ieee80211_vif *vif) ret = BT_COEX_TX_DIS_LUT; - if (mvm->cfg->bt_shared_single_ant) { - rcu_read_unlock(); - return ret; - } - phy_ctx_id = *((u16 *)chanctx_conf->drv_priv); primary_ch_phy_id = le32_to_cpu(mvm->last_bt_ci_cmd.primary_ch_phy_id); secondary_ch_phy_id = @@ -383,13 +378,12 @@ static void iwl_mvm_bt_notif_per_link(struct iwl_mvm *mvm, /* * don't reduce the Tx power if one of these is true: * we are in LOOSE - * single share antenna product * BT is inactive * we are not associated */ if (iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT || - mvm->cfg->bt_shared_single_ant || !vif->cfg.assoc || - le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) == BT_OFF) { + le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) == BT_OFF || + !vif->cfg.assoc) { iwl_mvm_bt_coex_reduced_txp(mvm, link_info->ap_sta_id, false); /* FIXME: should this be per link? */ iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0); @@ -570,7 +564,7 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, * Check if rssi is good enough for reduced Tx power, but not in loose * scheme. */ - if (rssi_event == RSSI_EVENT_LOW || mvm->cfg->bt_shared_single_ant || + if (rssi_event == RSSI_EVENT_LOW || iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT) ret = iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->deflink.ap_sta_id, @@ -639,10 +633,6 @@ bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm, bool iwl_mvm_bt_coex_is_ant_avail(struct iwl_mvm *mvm, u8 ant) { - /* there is no other antenna, shared antenna is always available */ - if (mvm->cfg->bt_shared_single_ant) - return true; - if (ant & mvm->cfg->non_shared_ant) return true; @@ -652,10 +642,6 @@ bool iwl_mvm_bt_coex_is_ant_avail(struct iwl_mvm *mvm, u8 ant) bool iwl_mvm_bt_coex_is_shared_ant_avail(struct iwl_mvm *mvm) { - /* there is no other antenna, shared antenna is always available */ - if (mvm->cfg->bt_shared_single_ant) - return true; - return le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) < BT_HIGH_TRAFFIC; } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index 92c45571bd69..4582afb149d7 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c @@ -1130,14 +1130,7 @@ iwl_mvm_wowlan_config(struct iwl_mvm *mvm, return ret; } - /* - * This needs to be unlocked due to lock ordering - * constraints. Since we're in the suspend path - * that isn't really a problem though. - */ - mutex_unlock(&mvm->mutex); ret = iwl_mvm_wowlan_config_key_params(mvm, vif); - mutex_lock(&mvm->mutex); if (ret) return ret; @@ -2497,7 +2490,7 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, struct iwl_wowlan_status_data *status) { int i; - bool keep; + bool keep = false; struct iwl_mvm_sta *mvm_ap_sta; if (!status) @@ -2525,18 +2518,12 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, mvm_ap_sta->tid_data[i].seq_number >> 4); } - /* now we have all the data we need, unlock to avoid mac80211 issues */ - mutex_unlock(&mvm->mutex); - iwl_mvm_report_wakeup_reasons(mvm, vif, status); keep = iwl_mvm_setup_connection_keep(mvm, vif, status); - - return keep; - out_unlock: mutex_unlock(&mvm->mutex); - return false; + return keep; } #define ND_QUERY_BUF_LEN (sizeof(struct iwl_scan_offload_profile_match) * \ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index 329c545f65fd..edc8204f7c0e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -1521,7 +1521,7 @@ static ssize_t iwl_dbgfs_inject_packet_write(struct iwl_mvm *mvm, /* supporting only MQ RX */ if (!mvm->trans->trans_cfg->mq_rx_supported) - return -ENOTSUPP; + return -EOPNOTSUPP; rxb._page = alloc_pages(GFP_ATOMIC, 0); if (!rxb._page) @@ -1714,6 +1714,20 @@ static ssize_t iwl_dbgfs_fw_dbg_collect_write(struct iwl_mvm *mvm, return count; } +static ssize_t iwl_dbgfs_fw_dbg_clear_write(struct iwl_mvm *mvm, + char *buf, size_t count, + loff_t *ppos) +{ + if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_9000) + return -EOPNOTSUPP; + + mutex_lock(&mvm->mutex); + iwl_fw_dbg_clear_monitor_buf(&mvm->fwrt); + mutex_unlock(&mvm->mutex); + + return count; +} + static ssize_t iwl_dbgfs_dbg_time_point_write(struct iwl_mvm *mvm, char *buf, size_t count, loff_t *ppos) @@ -1815,7 +1829,7 @@ static ssize_t _iwl_dbgfs_link_sta_##name##_write(struct file *file, \ char buf[buflen] = {}; \ size_t buf_size = min(count, sizeof(buf) - 1); \ \ - if (copy_from_user(buf, user_buf, sizeof(buf))) \ + if (copy_from_user(buf, user_buf, buf_size)) \ return -EFAULT; \ \ return _iwl_dbgfs_link_sta_wrap_write(iwl_dbgfs_##name##_write, \ @@ -2166,6 +2180,7 @@ MVM_DEBUGFS_WRITE_FILE_OPS(bt_force_ant, 10); MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8); MVM_DEBUGFS_READ_WRITE_FILE_OPS(fw_dbg_conf, 8); MVM_DEBUGFS_WRITE_FILE_OPS(fw_dbg_collect, 64); +MVM_DEBUGFS_WRITE_FILE_OPS(fw_dbg_clear, 64); MVM_DEBUGFS_WRITE_FILE_OPS(dbg_time_point, 64); MVM_DEBUGFS_WRITE_FILE_OPS(indirection_tbl, (IWL_RSS_INDIRECTION_TABLE_SIZE * 2)); @@ -2372,6 +2387,7 @@ void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm) MVM_DEBUGFS_ADD_FILE(prph_reg, mvm->debugfs_dir, 0600); MVM_DEBUGFS_ADD_FILE(fw_dbg_conf, mvm->debugfs_dir, 0600); MVM_DEBUGFS_ADD_FILE(fw_dbg_collect, mvm->debugfs_dir, 0200); + MVM_DEBUGFS_ADD_FILE(fw_dbg_clear, mvm->debugfs_dir, 0200); MVM_DEBUGFS_ADD_FILE(dbg_time_point, mvm->debugfs_dir, 0200); MVM_DEBUGFS_ADD_FILE(send_echo_cmd, mvm->debugfs_dir, 0200); MVM_DEBUGFS_ADD_FILE(indirection_tbl, mvm->debugfs_dir, 0200); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c index 10b9219b3bfd..8f10590f9cdd 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c @@ -39,7 +39,7 @@ static int iwl_mvm_ftm_responder_set_bw_v1(struct cfg80211_chan_def *chandef, *ctrl_ch_position = iwl_mvm_get_ctrl_pos(chandef); break; default: - return -ENOTSUPP; + return -EOPNOTSUPP; } return 0; @@ -77,7 +77,7 @@ static int iwl_mvm_ftm_responder_set_bw_v2(struct cfg80211_chan_def *chandef, } fallthrough; default: - return -ENOTSUPP; + return -EOPNOTSUPP; } return 0; @@ -291,7 +291,7 @@ iwl_mvm_ftm_responder_dyn_cfg_cmd(struct iwl_mvm *mvm, default: IWL_ERR(mvm, "Unsupported DYN_CONFIG_CMD version %u\n", cmd_ver); - ret = -ENOTSUPP; + ret = -EOPNOTSUPP; } return ret; @@ -333,7 +333,7 @@ int iwl_mvm_ftm_respoder_add_pasn_sta(struct iwl_mvm *mvm, if (cmd_ver < 3) { IWL_ERR(mvm, "Adding PASN station not supported by FW\n"); - return -ENOTSUPP; + return -EOPNOTSUPP; } if ((!hltk || !hltk_len) && (!tk || !tk_len)) { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 403bd17b8b7a..1252084662c6 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -27,9 +27,6 @@ #define MVM_UCODE_ALIVE_TIMEOUT (2 * HZ) #define MVM_UCODE_CALIB_TIMEOUT (2 * HZ) -#define IWL_TAS_US_MCC 0x5553 -#define IWL_TAS_CANADA_MCC 0x4341 - #define IWL_UATS_VLP_AP_SUPPORTED BIT(29) #define IWL_UATS_AFC_AP_SUPPORTED BIT(30) @@ -1234,10 +1231,10 @@ static void iwl_mvm_tas_init(struct iwl_mvm *mvm) dmi_get_system_info(DMI_SYS_VENDOR)); if ((!iwl_mvm_add_to_tas_block_list(cmd.v4.block_list_array, &cmd.v4.block_list_size, - IWL_TAS_US_MCC)) || + IWL_MCC_US)) || (!iwl_mvm_add_to_tas_block_list(cmd.v4.block_list_array, &cmd.v4.block_list_size, - IWL_TAS_CANADA_MCC))) { + IWL_MCC_CANADA))) { IWL_DEBUG_RADIO(mvm, "Unable to add US/Canada to TAS block list, disabling TAS\n"); return; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index a64600f0ed9f..7f13dff04b26 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -152,6 +152,16 @@ struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy, mvm->lar_regdom_set = true; mvm->mcc_src = src_id; + /* Some kind of regulatory mess means we need to currently disallow + * puncturing in the US and Canada. Do that here, at least until we + * figure out the new chanctx APIs for puncturing. + */ + if (resp->mcc == cpu_to_le16(IWL_MCC_US) || + resp->mcc == cpu_to_le16(IWL_MCC_CANADA)) + ieee80211_hw_set(mvm->hw, DISALLOW_PUNCTURING); + else + __clear_bit(IEEE80211_HW_DISALLOW_PUNCTURING, mvm->hw->flags); + iwl_mei_set_country_code(__le16_to_cpu(resp->mcc)); out: @@ -288,7 +298,7 @@ int iwl_mvm_op_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) /* This has been tested on those devices only */ if (mvm->trans->trans_cfg->device_family != IWL_DEVICE_FAMILY_9000 && mvm->trans->trans_cfg->device_family != IWL_DEVICE_FAMILY_22000) - return -ENOTSUPP; + return -EOPNOTSUPP; if (!mvm->nvm_data) return -EBUSY; @@ -517,6 +527,10 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG | REGULATORY_DISABLE_BEACON_HINTS; + if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) + wiphy_ext_feature_set(hw->wiphy, + NL80211_EXT_FEATURE_DFS_CONCURRENT); + hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; hw->wiphy->flags |= WIPHY_FLAG_SPLIT_SCAN_6GHZ; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c index ff6cb064051b..61170173f917 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c @@ -271,17 +271,17 @@ __iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm, } } + mvmvif->link[link_id]->phy_ctxt = phy_ctxt; + if (iwl_mvm_is_esr_supported(mvm->fwrt.trans) && n_active > 1) { mvmvif->link[link_id]->listen_lmac = true; ret = iwl_mvm_esr_mode_active(mvm, vif); if (ret) { IWL_ERR(mvm, "failed to activate ESR mode (%d)\n", ret); - return ret; + goto out; } } - mvmvif->link[link_id]->phy_ctxt = phy_ctxt; - if (switching_chanctx) { /* reactivate if we turned this off during channel switch */ if (vif->type == NL80211_IFTYPE_AP) @@ -716,7 +716,7 @@ void iwl_mvm_mld_select_links(struct iwl_mvm *mvm, struct ieee80211_vif *vif, } } - if (WARN_ON(!new_active_links)) + if (!new_active_links) return; if (vif->active_links != new_active_links) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c index 6af606e5da65..1628bf55458f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c @@ -874,6 +874,9 @@ void iwl_mvm_mld_sta_modify_disable_tx(struct iwl_mvm *mvm, cmd.sta_id = cpu_to_le32(mvmsta->deflink.sta_id); cmd.disable = cpu_to_le32(disable); + if (WARN_ON(iwl_mvm_has_no_host_disable_tx(mvm))) + return; + ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(MAC_CONF_GROUP, STA_DISABLE_TX_CMD), CMD_ASYNC, sizeof(cmd), &cmd); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index f2af3e571409..40627961b834 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -947,6 +947,7 @@ struct iwl_mvm { /* the vif that requested the current scan */ struct iwl_mvm_vif *scan_vif; + u8 scan_link_id; /* rx chain antennas set through debugfs for the scan command */ u8 scan_rx_ant; @@ -1513,6 +1514,12 @@ static inline bool iwl_mvm_has_quota_low_latency(struct iwl_mvm *mvm) IWL_UCODE_TLV_API_QUOTA_LOW_LATENCY); } +static inline bool iwl_mvm_has_no_host_disable_tx(struct iwl_mvm *mvm) +{ + return fw_has_api(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_API_NO_HOST_DISABLE_TX); +} + static inline bool iwl_mvm_has_tlc_offload(const struct iwl_mvm *mvm) { return fw_has_capa(&mvm->fw->ucode_capa, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 1627b2f819db..adbbe19aeae5 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -1703,18 +1703,6 @@ void iwl_mvm_rx_mq(struct iwl_op_mode *op_mode, iwl_mvm_rx_common(mvm, rxb, pkt); } -static void iwl_mvm_async_cb(struct iwl_op_mode *op_mode, - const struct iwl_device_cmd *cmd) -{ - struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); - - /* - * For now, we only set the CMD_WANT_ASYNC_CALLBACK for ADD_STA - * commands that need to block the Tx queues. - */ - iwl_trans_block_txq_ptrs(mvm->trans, false); -} - static int iwl_mvm_is_static_queue(struct iwl_mvm *mvm, int queue) { return queue == mvm->aux_queue || queue == mvm->probe_queue || @@ -2024,7 +2012,6 @@ static void iwl_op_mode_mvm_time_point(struct iwl_op_mode *op_mode, #define IWL_MVM_COMMON_OPS \ /* these could be differentiated */ \ - .async_cb = iwl_mvm_async_cb, \ .queue_full = iwl_mvm_stop_sw_queue, \ .queue_not_full = iwl_mvm_wake_sw_queue, \ .hw_rf_kill = iwl_mvm_set_hw_rfkill_state, \ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c index 4e1fccff3987..334d1f59f6e4 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c @@ -99,17 +99,6 @@ static void iwl_mvm_phy_ctxt_set_rxchain(struct iwl_mvm *mvm, active_cnt = 2; } - /* - * If the firmware requested it, then we know that it supports - * getting zero for the values to indicate "use one, but pick - * which one yourself", which means it can dynamically pick one - * that e.g. has better RSSI. - */ - if (mvm->fw_static_smps_request && active_cnt == 1 && idle_cnt == 1) { - idle_cnt = 0; - active_cnt = 0; - } - *rxchain_info = cpu_to_le32(iwl_mvm_get_valid_rx_ant(mvm) << PHY_RX_CHAIN_VALID_POS); *rxchain_info |= cpu_to_le32(idle_cnt << PHY_RX_CHAIN_CNT_POS); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index 75c5c58e14a5..7b6f1cdca067 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c @@ -101,6 +101,7 @@ struct iwl_mvm_scan_params { bool scan_6ghz; bool enable_6ghz_passive; bool respect_p2p_go, respect_p2p_go_hb; + s8 tsf_report_link_id; u8 bssid[ETH_ALEN] __aligned(2); }; @@ -2342,20 +2343,15 @@ iwl_mvm_scan_umac_fill_general_p_v12(struct iwl_mvm *mvm, if (gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC2) gp->num_of_fragments[SCAN_HB_LMAC_IDX] = IWL_SCAN_NUM_OF_FRAGS; + mvm->scan_link_id = 0; + if (version < 16) { gp->scan_start_mac_or_link_id = scan_vif->id; } else { - struct iwl_mvm_vif_link_info *link_info; - u8 link_id = 0; + struct iwl_mvm_vif_link_info *link_info = + scan_vif->link[params->tsf_report_link_id]; - /* Use one of the active link (if any). In the future it would - * be possible that the link ID would be part of the scan - * request coming from upper layers so we would need to use it. - */ - if (vif->active_links) - link_id = ffs(vif->active_links) - 1; - - link_info = scan_vif->link[link_id]; + mvm->scan_link_id = params->tsf_report_link_id; if (!WARN_ON(!link_info)) gp->scan_start_mac_or_link_id = link_info->fw_link_id; } @@ -2977,6 +2973,14 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, if (req->duration) params.iter_notif = true; + params.tsf_report_link_id = req->tsf_report_link_id; + if (params.tsf_report_link_id < 0) { + if (vif->active_links) + params.tsf_report_link_id = __ffs(vif->active_links); + else + params.tsf_report_link_id = 0; + } + iwl_mvm_build_scan_probe(mvm, vif, ies, ¶ms); iwl_mvm_scan_6ghz_passive_scan(mvm, ¶ms, vif); @@ -3164,8 +3168,13 @@ void iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm, .aborted = aborted, .scan_start_tsf = mvm->scan_start, }; + struct iwl_mvm_vif *scan_vif = mvm->scan_vif; + struct iwl_mvm_vif_link_info *link_info = + scan_vif->link[mvm->scan_link_id]; + + if (!WARN_ON(!link_info)) + memcpy(info.tsf_bssid, link_info->bssid, ETH_ALEN); - memcpy(info.tsf_bssid, mvm->scan_vif->deflink.bssid, ETH_ALEN); ieee80211_scan_completed(mvm->hw, &info); mvm->scan_vif = NULL; cancel_delayed_work(&mvm->scan_timeout_dwork); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index bba96a968890..2a3ca9785974 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -2550,7 +2550,7 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) if (WARN_ON(vif->type != NL80211_IFTYPE_AP && vif->type != NL80211_IFTYPE_ADHOC)) - return -ENOTSUPP; + return -EOPNOTSUPP; /* * In IBSS, ieee80211_check_queues() sets the cab_queue to be @@ -3234,7 +3234,7 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif, * should be updated as well. */ if (buf_size < IWL_FRAME_LIMIT) - return -ENOTSUPP; + return -EOPNOTSUPP; ret = iwl_mvm_sta_tx_agg(mvm, sta, tid, queue, true); if (ret) @@ -4111,10 +4111,8 @@ void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm, } /* block the Tx queues until the FW updated the sleep Tx count */ - iwl_trans_block_txq_ptrs(mvm->trans, true); - ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, - CMD_ASYNC | CMD_WANT_ASYNC_CALLBACK, + CMD_ASYNC | CMD_BLOCK_TXQS, iwl_mvm_add_sta_cmd_size(mvm), &cmd); if (ret) IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret); @@ -4152,7 +4150,8 @@ void iwl_mvm_sta_modify_disable_tx(struct iwl_mvm *mvm, int ret; if (mvm->mld_api_is_used) { - iwl_mvm_mld_sta_modify_disable_tx(mvm, mvmsta, disable); + if (!iwl_mvm_has_no_host_disable_tx(mvm)) + iwl_mvm_mld_sta_modify_disable_tx(mvm, mvmsta, disable); return; } @@ -4169,7 +4168,8 @@ void iwl_mvm_sta_modify_disable_tx_ap(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta); if (mvm->mld_api_is_used) { - iwl_mvm_mld_sta_modify_disable_tx_ap(mvm, sta, disable); + if (!iwl_mvm_has_no_host_disable_tx(mvm)) + iwl_mvm_mld_sta_modify_disable_tx_ap(mvm, sta, disable); return; } @@ -4224,7 +4224,9 @@ void iwl_mvm_modify_all_sta_disable_tx(struct iwl_mvm *mvm, int i; if (mvm->mld_api_is_used) { - iwl_mvm_mld_modify_all_sta_disable_tx(mvm, mvmvif, disable); + if (!iwl_mvm_has_no_host_disable_tx(mvm)) + iwl_mvm_mld_modify_all_sta_disable_tx(mvm, mvmvif, + disable); return; } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index ae5cd13cd6dd..db986bfc4dc3 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -2256,7 +2256,7 @@ int iwl_mvm_flush_sta_tids(struct iwl_mvm *mvm, u32 sta_id, u16 tids) WARN_ON(!iwl_mvm_has_new_tx_api(mvm)); if (iwl_fw_lookup_notif_ver(mvm->fw, LONG_GROUP, TXPATH_FLUSH, 0) > 0) - cmd.flags |= CMD_WANT_SKB; + cmd.flags |= CMD_WANT_SKB | CMD_SEND_IN_RFKILL; IWL_DEBUG_TX_QUEUES(mvm, "flush for sta id %d tid mask 0x%x\n", sta_id, tids); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 26a0953603ab..2c9b98c8184b 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -1121,9 +1121,8 @@ static const struct iwl_dev_info iwl_dev_info_table[] = { /* * Read rf id and cdb info from prph register and store it */ -static int get_crf_id(struct iwl_trans *iwl_trans) +static void get_crf_id(struct iwl_trans *iwl_trans) { - int ret = 0; u32 sd_reg_ver_addr; u32 val = 0; @@ -1150,8 +1149,6 @@ static int get_crf_id(struct iwl_trans *iwl_trans) IWL_INFO(iwl_trans, "Detected crf-id 0x%x, cnv-id 0x%x wfpm id 0x%x\n", iwl_trans->hw_crf_id, iwl_trans->hw_cnv_id, iwl_trans->hw_wfpm_id); - - return ret; } /* diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index 07931c2db494..9c2461ba13c5 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -1351,8 +1351,7 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans, if (len < sizeof(*pkt) || offset > max_len) break; - trace_iwlwifi_dev_rx(trans->dev, trans, pkt, len); - trace_iwlwifi_dev_rx_data(trans->dev, trans, pkt, len); + maybe_trace_iwlwifi_dev_rx(trans, pkt, len); /* Reclaim a command buffer only if this packet is a response * to a (driver-originated) command. diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c index c9e5bda8f0b7..a4a4772330cf 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c @@ -290,6 +290,16 @@ static void iwl_pcie_get_rf_name(struct iwl_trans *trans) case CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_MS): pos = scnprintf(buf, buflen, "MS"); break; + case CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_FM): + pos = scnprintf(buf, buflen, "FM"); + break; + case CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_WP): + if (SILICON_Z_STEP == + CSR_HW_RFID_STEP(trans->hw_rf_id)) + pos = scnprintf(buf, buflen, "WHTC"); + else + pos = scnprintf(buf, buflen, "WH"); + break; default: return; } diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index d10208075ae5..63e13577aff8 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -2108,18 +2108,29 @@ static void iwl_trans_pcie_removal_wk(struct work_struct *wk) container_of(wk, struct iwl_trans_pcie_removal, work); struct pci_dev *pdev = removal->pdev; static char *prop[] = {"EVENT=INACCESSIBLE", NULL}; - struct pci_bus *bus = pdev->bus; + struct pci_bus *bus; + + pci_lock_rescan_remove(); + + bus = pdev->bus; + /* in this case, something else already removed the device */ + if (!bus) + goto out; dev_err(&pdev->dev, "Device gone - attempting removal\n"); + kobject_uevent_env(&pdev->dev.kobj, KOBJ_CHANGE, prop); - pci_lock_rescan_remove(); - pci_dev_put(pdev); + pci_stop_and_remove_bus_device(pdev); - if (removal->rescan && bus) { + pci_dev_put(pdev); + + if (removal->rescan) { if (bus->parent) bus = bus->parent; pci_rescan_bus(bus); } + +out: pci_unlock_rescan_remove(); kfree(removal); @@ -2134,6 +2145,7 @@ void iwl_trans_pcie_remove(struct iwl_trans *trans, bool rescan) return; IWL_ERR(trans, "Device gone - scheduling removal!\n"); + iwl_pcie_dump_csr(trans); /* * get a module reference to avoid doing this @@ -2366,32 +2378,6 @@ static int iwl_trans_pcie_read_config32(struct iwl_trans *trans, u32 ofs, ofs, val); } -static void iwl_trans_pcie_block_txq_ptrs(struct iwl_trans *trans, bool block) -{ - int i; - - for (i = 0; i < trans->trans_cfg->base_params->num_of_queues; i++) { - struct iwl_txq *txq = trans->txqs.txq[i]; - - if (i == trans->txqs.cmd.q_id) - continue; - - spin_lock_bh(&txq->lock); - - if (!block && !(WARN_ON_ONCE(!txq->block))) { - txq->block--; - if (!txq->block) { - iwl_write32(trans, HBUS_TARG_WRPTR, - txq->write_ptr | (i << 8)); - } - } else if (block) { - txq->block++; - } - - spin_unlock_bh(&txq->lock); - } -} - #define IWL_FLUSH_WAIT_MS 2000 static int iwl_trans_pcie_rxq_dma_data(struct iwl_trans *trans, int queue, @@ -3573,7 +3559,6 @@ static const struct iwl_trans_ops trans_ops_pcie = { .wait_tx_queues_empty = iwl_trans_pcie_wait_txqs_empty, .freeze_txq_timer = iwl_trans_txq_freeze_timer, - .block_txq_ptrs = iwl_trans_pcie_block_txq_ptrs, #ifdef CONFIG_IWLWIFI_DEBUGFS .debugfs_cleanup = iwl_trans_pcie_debugfs_cleanup, #endif diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c index c72a84d8bb4f..aabbef114bc2 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* * Copyright (C) 2017 Intel Deutschland GmbH - * Copyright (C) 2018-2020 Intel Corporation + * Copyright (C) 2018-2020, 2023 Intel Corporation */ #include <net/tso.h> #include <linux/tcp.h> @@ -42,6 +42,9 @@ int iwl_pcie_gen2_enqueue_hcmd(struct iwl_trans *trans, struct iwl_tfh_tfd *tfd; unsigned long flags; + if (WARN_ON(cmd->flags & CMD_BLOCK_TXQS)) + return -EINVAL; + copy_size = sizeof(struct iwl_cmd_header_wide); cmd_size = sizeof(struct iwl_cmd_header_wide); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index 2f39b639c43f..6c2b37e56c78 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -873,6 +873,33 @@ void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id, /*************** HOST COMMAND QUEUE FUNCTIONS *****/ +static void iwl_trans_pcie_block_txq_ptrs(struct iwl_trans *trans, bool block) +{ + int i; + + for (i = 0; i < trans->trans_cfg->base_params->num_of_queues; i++) { + struct iwl_txq *txq = trans->txqs.txq[i]; + + if (i == trans->txqs.cmd.q_id) + continue; + + /* we skip the command queue (obviously) so it's OK to nest */ + spin_lock_nested(&txq->lock, 1); + + if (!block && !(WARN_ON_ONCE(!txq->block))) { + txq->block--; + if (!txq->block) { + iwl_write32(trans, HBUS_TARG_WRPTR, + txq->write_ptr | (i << 8)); + } + } else if (block) { + txq->block++; + } + + spin_unlock(&txq->lock); + } +} + /* * iwl_pcie_enqueue_hcmd - enqueue a uCode command * @priv: device private data point @@ -1137,6 +1164,9 @@ int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, goto out; } + if (cmd->flags & CMD_BLOCK_TXQS) + iwl_trans_pcie_block_txq_ptrs(trans, true); + /* Increment and update queue's write index */ txq->write_ptr = iwl_txq_inc_wrap(trans, txq->write_ptr); iwl_pcie_txq_inc_wr_ptr(trans, txq); @@ -1202,8 +1232,8 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans, meta->source->_rx_page_order = trans_pcie->rx_page_order; } - if (meta->flags & CMD_WANT_ASYNC_CALLBACK) - iwl_op_mode_async_cb(trans->op_mode, cmd); + if (meta->flags & CMD_BLOCK_TXQS) + iwl_trans_pcie_block_txq_ptrs(trans, false); iwl_pcie_cmdq_reclaim(trans, txq_id, index); |