wireless-drivers-next patches for v5.17
Second set of patches for v5.17, planning to do at least one more. Smaller new features, nothing special this time. Major changes: rtw88 * debugfs file to fix tx rate iwlwifi * support SAR GEO Offset Mapping (SGOM) via BIOS * support firmware API version 68 * add some new device IDs ath11k * support PCI devices with 1 MSI vector * WCN6855 hw2.1 support * 11d scan offload support * full monitor mode, only supported on QCN9074 * scan MAC address randomization support * reserved host DDR addresses from DT for PCI devices support ath9k * switch to rate table based lookup ath * extend South Korea regulatory domain support wcn36xx * beacon filter support -----BEGIN PGP SIGNATURE----- iQFFBAABCgAvFiEEiBjanGPFTz4PRfLobhckVSbrbZsFAmG8i3cRHGt2YWxvQGtl cm5lbC5vcmcACgkQbhckVSbrbZumyAf7BlhO1TUuwhhs9y6fi6KLa/pEOmkx2SRf 9AuEfxxrLPhlzh29Dz4Bn8B+KBG6HFQ1FngSwIAVjLL5pX/1ARBMx9B2TDf9p/Sb UgkE6WOX29s7LXuC2lDnBnvnKbf5/rdLmZPZCFCv/iKaGAJAYYXYSQjtj5/Fmdkc PhQNgALWG9a02bfSLk1MlF1lCqt0hsKFQkza29jTa9CKcWYZFK3sTl1spbHAN5yQ YJMecy+fSxCSuJPZB3elG5os69sz3WGoFY/AYCWoUODNZo18Z4kiAXwurPDIM+GW 3e/lzXe29V1TB36haNe9/C5F2uwoYWGSoWwHcZ62lLpNhJ649wJDbw== =4wFO -----END PGP SIGNATURE----- Merge tag 'wireless-drivers-next-2021-12-17' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next Kalle Valo says: ==================== wireless-drivers-next patches for v5.17 Second set of patches for v5.17, planning to do at least one more. Smaller new features, nothing special this time. Major changes: rtw88 * debugfs file to fix tx rate iwlwifi * support SAR GEO Offset Mapping (SGOM) via BIOS * support firmware API version 68 * add some new device IDs ath11k * support PCI devices with 1 MSI vector * WCN6855 hw2.1 support * 11d scan offload support * full monitor mode, only supported on QCN9074 * scan MAC address randomization support * reserved host DDR addresses from DT for PCI devices support ath9k * switch to rate table based lookup ath * extend South Korea regulatory domain support wcn36xx * beacon filter support * tag 'wireless-drivers-next-2021-12-17' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next: (129 commits) wcn36xx: Implement beacon filtering wcn36xx: Fix physical location of beacon filter comment wcn36xx: Fix beacon filter structure definitions ath11k: Use reserved host DDR addresses from DT for PCI devices dt: bindings: add new DT entry for ath11k PCI device support wilc1000: Improve WILC TX performance when power_save is off wl1251: specify max. IE length rsi: fix array out of bound wilc1000: Rename workqueue from "WILC_wq" to "NETDEV-wq" wilc1000: Rename tx task from "K_TXQ_TASK" to NETDEV-tx wilc1000: Rename irq handler from "WILC_IRQ" to netdev name wilc1000: Rename SPI driver from "WILC_SPI" to "wilc1000_spi" wilc1000: Fix spurious "FW not responding" error wilc1000: Remove misleading USE_SPI_DMA macro wilc1000: Fix missing newline in error message wilc1000: Fix copy-and-paste typo in wilc_set_mac_address rtw89: coex: Update COEX to 5.5.8 rtw89: coex: Cancel PS leaving while C2H comes rtw89: coex: Update BT counters while receiving report rtw89: coex: Define LPS state for BTC using ... ==================== Link: https://lore.kernel.org/r/20211217130952.34887C36AE9@smtp.kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
f75c1d55ec
@ -150,6 +150,12 @@ properties:
|
||||
string to uniquely identify variant of the calibration data in the
|
||||
board-2.bin for designs with colliding bus and device specific ids
|
||||
|
||||
memory-region:
|
||||
maxItems: 1
|
||||
description:
|
||||
phandle to a node describing reserved memory (System RAM memory)
|
||||
used by ath11k firmware (see bindings/reserved-memory/reserved-memory.txt)
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
@ -279,3 +285,27 @@ examples:
|
||||
"tcl2host-status-ring";
|
||||
qcom,rproc = <&q6v5_wcss>;
|
||||
};
|
||||
|
||||
- |
|
||||
|
||||
reserved-memory {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
qcn9074_0: qcn9074_0@51100000 {
|
||||
no-map;
|
||||
reg = <0x0 0x51100000 0x0 0x03500000>;
|
||||
};
|
||||
};
|
||||
|
||||
pci {
|
||||
pcie0 {
|
||||
#size-cells = <2>;
|
||||
#address-cells = <3>;
|
||||
|
||||
wifi_0: wifi@0 {
|
||||
reg = <0 0 0 0 0>;
|
||||
memory-region = <&qcn9074_0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -90,6 +90,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.rri_on_ddr = false,
|
||||
.hw_filter_reset_required = true,
|
||||
.fw_diag_ce_download = false,
|
||||
.credit_size_workaround = false,
|
||||
.tx_stats_over_pktlog = true,
|
||||
.dynamic_sar_support = false,
|
||||
},
|
||||
@ -125,6 +126,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.rri_on_ddr = false,
|
||||
.hw_filter_reset_required = true,
|
||||
.fw_diag_ce_download = false,
|
||||
.credit_size_workaround = false,
|
||||
.tx_stats_over_pktlog = true,
|
||||
.dynamic_sar_support = false,
|
||||
},
|
||||
@ -161,6 +163,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.rri_on_ddr = false,
|
||||
.hw_filter_reset_required = true,
|
||||
.fw_diag_ce_download = false,
|
||||
.credit_size_workaround = false,
|
||||
.tx_stats_over_pktlog = false,
|
||||
.dynamic_sar_support = false,
|
||||
},
|
||||
@ -191,6 +194,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.num_wds_entries = 0x20,
|
||||
.uart_pin_workaround = true,
|
||||
.tx_stats_over_pktlog = false,
|
||||
.credit_size_workaround = false,
|
||||
.bmi_large_size_download = true,
|
||||
.supports_peer_stats_info = true,
|
||||
.dynamic_sar_support = true,
|
||||
@ -227,6 +231,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.rri_on_ddr = false,
|
||||
.hw_filter_reset_required = true,
|
||||
.fw_diag_ce_download = false,
|
||||
.credit_size_workaround = false,
|
||||
.tx_stats_over_pktlog = false,
|
||||
.dynamic_sar_support = false,
|
||||
},
|
||||
@ -262,6 +267,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.rri_on_ddr = false,
|
||||
.hw_filter_reset_required = true,
|
||||
.fw_diag_ce_download = false,
|
||||
.credit_size_workaround = false,
|
||||
.tx_stats_over_pktlog = false,
|
||||
.dynamic_sar_support = false,
|
||||
},
|
||||
@ -297,6 +303,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.rri_on_ddr = false,
|
||||
.hw_filter_reset_required = true,
|
||||
.fw_diag_ce_download = false,
|
||||
.credit_size_workaround = false,
|
||||
.tx_stats_over_pktlog = false,
|
||||
.dynamic_sar_support = false,
|
||||
},
|
||||
@ -335,6 +342,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.rri_on_ddr = false,
|
||||
.hw_filter_reset_required = true,
|
||||
.fw_diag_ce_download = true,
|
||||
.credit_size_workaround = false,
|
||||
.tx_stats_over_pktlog = false,
|
||||
.supports_peer_stats_info = true,
|
||||
.dynamic_sar_support = true,
|
||||
@ -377,6 +385,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.rri_on_ddr = false,
|
||||
.hw_filter_reset_required = true,
|
||||
.fw_diag_ce_download = false,
|
||||
.credit_size_workaround = false,
|
||||
.tx_stats_over_pktlog = false,
|
||||
.dynamic_sar_support = false,
|
||||
},
|
||||
@ -425,6 +434,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.rri_on_ddr = false,
|
||||
.hw_filter_reset_required = true,
|
||||
.fw_diag_ce_download = false,
|
||||
.credit_size_workaround = false,
|
||||
.tx_stats_over_pktlog = false,
|
||||
.dynamic_sar_support = false,
|
||||
},
|
||||
@ -470,6 +480,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.rri_on_ddr = false,
|
||||
.hw_filter_reset_required = true,
|
||||
.fw_diag_ce_download = false,
|
||||
.credit_size_workaround = false,
|
||||
.tx_stats_over_pktlog = false,
|
||||
.dynamic_sar_support = false,
|
||||
},
|
||||
@ -505,6 +516,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.rri_on_ddr = false,
|
||||
.hw_filter_reset_required = true,
|
||||
.fw_diag_ce_download = false,
|
||||
.credit_size_workaround = false,
|
||||
.tx_stats_over_pktlog = false,
|
||||
.dynamic_sar_support = false,
|
||||
},
|
||||
@ -542,6 +554,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.rri_on_ddr = false,
|
||||
.hw_filter_reset_required = true,
|
||||
.fw_diag_ce_download = true,
|
||||
.credit_size_workaround = false,
|
||||
.tx_stats_over_pktlog = false,
|
||||
.dynamic_sar_support = false,
|
||||
},
|
||||
@ -571,6 +584,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.ast_skid_limit = 0x10,
|
||||
.num_wds_entries = 0x20,
|
||||
.uart_pin_workaround = true,
|
||||
.credit_size_workaround = true,
|
||||
.dynamic_sar_support = false,
|
||||
},
|
||||
{
|
||||
@ -612,6 +626,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.rri_on_ddr = false,
|
||||
.hw_filter_reset_required = true,
|
||||
.fw_diag_ce_download = false,
|
||||
.credit_size_workaround = false,
|
||||
.tx_stats_over_pktlog = false,
|
||||
.dynamic_sar_support = false,
|
||||
},
|
||||
@ -640,6 +655,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.rri_on_ddr = true,
|
||||
.hw_filter_reset_required = false,
|
||||
.fw_diag_ce_download = false,
|
||||
.credit_size_workaround = false,
|
||||
.tx_stats_over_pktlog = false,
|
||||
.dynamic_sar_support = true,
|
||||
},
|
||||
@ -715,6 +731,7 @@ static void ath10k_send_suspend_complete(struct ath10k *ar)
|
||||
|
||||
static int ath10k_init_sdio(struct ath10k *ar, enum ath10k_firmware_mode mode)
|
||||
{
|
||||
bool mtu_workaround = ar->hw_params.credit_size_workaround;
|
||||
int ret;
|
||||
u32 param = 0;
|
||||
|
||||
@ -732,7 +749,7 @@ static int ath10k_init_sdio(struct ath10k *ar, enum ath10k_firmware_mode mode)
|
||||
|
||||
param |= HI_ACS_FLAGS_SDIO_REDUCE_TX_COMPL_SET;
|
||||
|
||||
if (mode == ATH10K_FIRMWARE_MODE_NORMAL)
|
||||
if (mode == ATH10K_FIRMWARE_MODE_NORMAL && !mtu_workaround)
|
||||
param |= HI_ACS_FLAGS_ALT_DATA_CREDIT_SIZE;
|
||||
else
|
||||
param &= ~HI_ACS_FLAGS_ALT_DATA_CREDIT_SIZE;
|
||||
|
@ -1400,115 +1400,6 @@ enum htt_dbg_stats_status {
|
||||
HTT_DBG_STATS_STATUS_SERIES_DONE = 7
|
||||
};
|
||||
|
||||
/*
|
||||
* target -> host statistics upload
|
||||
*
|
||||
* The following field definitions describe the format of the HTT target
|
||||
* to host stats upload confirmation message.
|
||||
* The message contains a cookie echoed from the HTT host->target stats
|
||||
* upload request, which identifies which request the confirmation is
|
||||
* for, and a series of tag-length-value stats information elements.
|
||||
* The tag-length header for each stats info element also includes a
|
||||
* status field, to indicate whether the request for the stat type in
|
||||
* question was fully met, partially met, unable to be met, or invalid
|
||||
* (if the stat type in question is disabled in the target).
|
||||
* A special value of all 1's in this status field is used to indicate
|
||||
* the end of the series of stats info elements.
|
||||
*
|
||||
*
|
||||
* |31 16|15 8|7 5|4 0|
|
||||
* |------------------------------------------------------------|
|
||||
* | reserved | msg type |
|
||||
* |------------------------------------------------------------|
|
||||
* | cookie LSBs |
|
||||
* |------------------------------------------------------------|
|
||||
* | cookie MSBs |
|
||||
* |------------------------------------------------------------|
|
||||
* | stats entry length | reserved | S |stat type|
|
||||
* |------------------------------------------------------------|
|
||||
* | |
|
||||
* | type-specific stats info |
|
||||
* | |
|
||||
* |------------------------------------------------------------|
|
||||
* | stats entry length | reserved | S |stat type|
|
||||
* |------------------------------------------------------------|
|
||||
* | |
|
||||
* | type-specific stats info |
|
||||
* | |
|
||||
* |------------------------------------------------------------|
|
||||
* | n/a | reserved | 111 | n/a |
|
||||
* |------------------------------------------------------------|
|
||||
* Header fields:
|
||||
* - MSG_TYPE
|
||||
* Bits 7:0
|
||||
* Purpose: identifies this is a statistics upload confirmation message
|
||||
* Value: 0x9
|
||||
* - COOKIE_LSBS
|
||||
* Bits 31:0
|
||||
* Purpose: Provide a mechanism to match a target->host stats confirmation
|
||||
* message with its preceding host->target stats request message.
|
||||
* Value: LSBs of the opaque cookie specified by the host-side requestor
|
||||
* - COOKIE_MSBS
|
||||
* Bits 31:0
|
||||
* Purpose: Provide a mechanism to match a target->host stats confirmation
|
||||
* message with its preceding host->target stats request message.
|
||||
* Value: MSBs of the opaque cookie specified by the host-side requestor
|
||||
*
|
||||
* Stats Information Element tag-length header fields:
|
||||
* - STAT_TYPE
|
||||
* Bits 4:0
|
||||
* Purpose: identifies the type of statistics info held in the
|
||||
* following information element
|
||||
* Value: htt_dbg_stats_type
|
||||
* - STATUS
|
||||
* Bits 7:5
|
||||
* Purpose: indicate whether the requested stats are present
|
||||
* Value: htt_dbg_stats_status, including a special value (0x7) to mark
|
||||
* the completion of the stats entry series
|
||||
* - LENGTH
|
||||
* Bits 31:16
|
||||
* Purpose: indicate the stats information size
|
||||
* Value: This field specifies the number of bytes of stats information
|
||||
* that follows the element tag-length header.
|
||||
* It is expected but not required that this length is a multiple of
|
||||
* 4 bytes. Even if the length is not an integer multiple of 4, the
|
||||
* subsequent stats entry header will begin on a 4-byte aligned
|
||||
* boundary.
|
||||
*/
|
||||
|
||||
#define HTT_STATS_CONF_ITEM_INFO_STAT_TYPE_MASK 0x1F
|
||||
#define HTT_STATS_CONF_ITEM_INFO_STAT_TYPE_LSB 0
|
||||
#define HTT_STATS_CONF_ITEM_INFO_STATUS_MASK 0xE0
|
||||
#define HTT_STATS_CONF_ITEM_INFO_STATUS_LSB 5
|
||||
|
||||
struct htt_stats_conf_item {
|
||||
union {
|
||||
u8 info;
|
||||
struct {
|
||||
u8 stat_type:5; /* %HTT_DBG_STATS_ */
|
||||
u8 status:3; /* %HTT_DBG_STATS_STATUS_ */
|
||||
} __packed;
|
||||
} __packed;
|
||||
u8 pad;
|
||||
__le16 length;
|
||||
u8 payload[]; /* roundup(length, 4) long */
|
||||
} __packed;
|
||||
|
||||
struct htt_stats_conf {
|
||||
u8 pad[3];
|
||||
__le32 cookie_lsb;
|
||||
__le32 cookie_msb;
|
||||
|
||||
/* each item has variable length! */
|
||||
struct htt_stats_conf_item items[];
|
||||
} __packed;
|
||||
|
||||
static inline struct htt_stats_conf_item *htt_stats_conf_next_item(
|
||||
const struct htt_stats_conf_item *item)
|
||||
{
|
||||
return (void *)item + sizeof(*item) + roundup(item->length, 4);
|
||||
}
|
||||
|
||||
/*
|
||||
* host -> target FRAG DESCRIPTOR/MSDU_EXT DESC bank
|
||||
*
|
||||
@ -1828,7 +1719,6 @@ struct htt_resp {
|
||||
struct htt_rc_update rc_update;
|
||||
struct htt_rx_test rx_test;
|
||||
struct htt_pktlog_msg pktlog_msg;
|
||||
struct htt_stats_conf stats_conf;
|
||||
struct htt_rx_pn_ind rx_pn_ind;
|
||||
struct htt_rx_offload_ind rx_offload_ind;
|
||||
struct htt_rx_in_ord_ind rx_in_ord_ind;
|
||||
|
@ -147,6 +147,9 @@ void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt)
|
||||
htt->num_pending_tx--;
|
||||
if (htt->num_pending_tx == htt->max_num_pending_tx - 1)
|
||||
ath10k_mac_tx_unlock(htt->ar, ATH10K_TX_PAUSE_Q_FULL);
|
||||
|
||||
if (htt->num_pending_tx == 0)
|
||||
wake_up(&htt->empty_tx_wq);
|
||||
}
|
||||
|
||||
int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt)
|
||||
|
@ -618,6 +618,9 @@ struct ath10k_hw_params {
|
||||
*/
|
||||
bool uart_pin_workaround;
|
||||
|
||||
/* Workaround for the credit size calculation */
|
||||
bool credit_size_workaround;
|
||||
|
||||
/* tx stats support over pktlog */
|
||||
bool tx_stats_over_pktlog;
|
||||
|
||||
|
@ -6380,13 +6380,14 @@ static int ath10k_hw_scan(struct ieee80211_hw *hw,
|
||||
scan_timeout = min_t(u32, arg.max_rest_time *
|
||||
(arg.n_channels - 1) + (req->duration +
|
||||
ATH10K_SCAN_CHANNEL_SWITCH_WMI_EVT_OVERHEAD) *
|
||||
arg.n_channels, arg.max_scan_time + 200);
|
||||
|
||||
arg.n_channels, arg.max_scan_time);
|
||||
} else {
|
||||
/* Add a 200ms margin to account for event/command processing */
|
||||
scan_timeout = arg.max_scan_time + 200;
|
||||
scan_timeout = arg.max_scan_time;
|
||||
}
|
||||
|
||||
/* Add a 200ms margin to account for event/command processing */
|
||||
scan_timeout += 200;
|
||||
|
||||
ret = ath10k_start_scan(ar, &arg);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to start hw scan: %d\n", ret);
|
||||
|
@ -82,8 +82,6 @@ int ath10k_txrx_tx_unref(struct ath10k_htt *htt,
|
||||
flags = skb_cb->flags;
|
||||
ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id);
|
||||
ath10k_htt_tx_dec_pending(htt);
|
||||
if (htt->num_pending_tx == 0)
|
||||
wake_up(&htt->empty_tx_wq);
|
||||
spin_unlock_bh(&htt->tx_lock);
|
||||
|
||||
rcu_read_lock();
|
||||
|
@ -2611,9 +2611,30 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
|
||||
ath10k_mac_handle_beacon(ar, skb);
|
||||
|
||||
if (ieee80211_is_beacon(hdr->frame_control) ||
|
||||
ieee80211_is_probe_resp(hdr->frame_control))
|
||||
ieee80211_is_probe_resp(hdr->frame_control)) {
|
||||
struct ieee80211_mgmt *mgmt = (void *)skb->data;
|
||||
u8 *ies;
|
||||
int ies_ch;
|
||||
|
||||
status->boottime_ns = ktime_get_boottime_ns();
|
||||
|
||||
if (!ar->scan_channel)
|
||||
goto drop;
|
||||
|
||||
ies = mgmt->u.beacon.variable;
|
||||
|
||||
ies_ch = cfg80211_get_ies_channel_number(mgmt->u.beacon.variable,
|
||||
skb_tail_pointer(skb) - ies,
|
||||
sband->band);
|
||||
|
||||
if (ies_ch > 0 && ies_ch != channel) {
|
||||
ath10k_dbg(ar, ATH10K_DBG_MGMT,
|
||||
"channel mismatched ds channel %d scan channel %d\n",
|
||||
ies_ch, channel);
|
||||
goto drop;
|
||||
}
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MGMT,
|
||||
"event mgmt rx skb %pK len %d ftype %02x stype %02x\n",
|
||||
skb, skb->len,
|
||||
@ -2627,6 +2648,10 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
|
||||
ieee80211_rx_ni(ar->hw, skb);
|
||||
|
||||
return 0;
|
||||
|
||||
drop:
|
||||
dev_kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int freq_to_idx(struct ath10k *ar, int freq)
|
||||
|
@ -3478,7 +3478,9 @@ struct wmi_phyerr_event {
|
||||
__le32 num_phyerrs;
|
||||
__le32 tsf_l32;
|
||||
__le32 tsf_u32;
|
||||
struct wmi_phyerr phyerrs[];
|
||||
|
||||
/* array of struct wmi_phyerr */
|
||||
u8 phyerrs[];
|
||||
} __packed;
|
||||
|
||||
struct wmi_10_4_phyerr_event {
|
||||
|
@ -206,13 +206,13 @@ static void ath11k_ahb_clearbit32(struct ath11k_base *ab, u8 bit, u32 offset)
|
||||
|
||||
static void ath11k_ahb_ce_irq_enable(struct ath11k_base *ab, u16 ce_id)
|
||||
{
|
||||
const struct ce_pipe_config *ce_config;
|
||||
const struct ce_attr *ce_attr;
|
||||
|
||||
ce_config = &ab->hw_params.target_ce_config[ce_id];
|
||||
if (__le32_to_cpu(ce_config->pipedir) & PIPEDIR_OUT)
|
||||
ce_attr = &ab->hw_params.host_ce_config[ce_id];
|
||||
if (ce_attr->src_nentries)
|
||||
ath11k_ahb_setbit32(ab, ce_id, CE_HOST_IE_ADDRESS);
|
||||
|
||||
if (__le32_to_cpu(ce_config->pipedir) & PIPEDIR_IN) {
|
||||
if (ce_attr->dest_nentries) {
|
||||
ath11k_ahb_setbit32(ab, ce_id, CE_HOST_IE_2_ADDRESS);
|
||||
ath11k_ahb_setbit32(ab, ce_id + CE_HOST_IE_3_SHIFT,
|
||||
CE_HOST_IE_3_ADDRESS);
|
||||
@ -221,13 +221,13 @@ static void ath11k_ahb_ce_irq_enable(struct ath11k_base *ab, u16 ce_id)
|
||||
|
||||
static void ath11k_ahb_ce_irq_disable(struct ath11k_base *ab, u16 ce_id)
|
||||
{
|
||||
const struct ce_pipe_config *ce_config;
|
||||
const struct ce_attr *ce_attr;
|
||||
|
||||
ce_config = &ab->hw_params.target_ce_config[ce_id];
|
||||
if (__le32_to_cpu(ce_config->pipedir) & PIPEDIR_OUT)
|
||||
ce_attr = &ab->hw_params.host_ce_config[ce_id];
|
||||
if (ce_attr->src_nentries)
|
||||
ath11k_ahb_clearbit32(ab, ce_id, CE_HOST_IE_ADDRESS);
|
||||
|
||||
if (__le32_to_cpu(ce_config->pipedir) & PIPEDIR_IN) {
|
||||
if (ce_attr->dest_nentries) {
|
||||
ath11k_ahb_clearbit32(ab, ce_id, CE_HOST_IE_2_ADDRESS);
|
||||
ath11k_ahb_clearbit32(ab, ce_id + CE_HOST_IE_3_SHIFT,
|
||||
CE_HOST_IE_3_ADDRESS);
|
||||
|
@ -74,10 +74,14 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
||||
BIT(NL80211_IFTYPE_AP) |
|
||||
BIT(NL80211_IFTYPE_MESH_POINT),
|
||||
.supports_monitor = true,
|
||||
.full_monitor_mode = false,
|
||||
.supports_shadow_regs = false,
|
||||
.idle_ps = false,
|
||||
.supports_sta_ps = false,
|
||||
.cold_boot_calib = true,
|
||||
.fw_mem_mode = 0,
|
||||
.num_vdevs = 16 + 1,
|
||||
.num_peers = 512,
|
||||
.supports_suspend = false,
|
||||
.hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074),
|
||||
.fix_l1ss = true,
|
||||
@ -128,10 +132,14 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
||||
BIT(NL80211_IFTYPE_AP) |
|
||||
BIT(NL80211_IFTYPE_MESH_POINT),
|
||||
.supports_monitor = true,
|
||||
.full_monitor_mode = false,
|
||||
.supports_shadow_regs = false,
|
||||
.idle_ps = false,
|
||||
.supports_sta_ps = false,
|
||||
.cold_boot_calib = true,
|
||||
.fw_mem_mode = 0,
|
||||
.num_vdevs = 16 + 1,
|
||||
.num_peers = 512,
|
||||
.supports_suspend = false,
|
||||
.hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074),
|
||||
.fix_l1ss = true,
|
||||
@ -181,10 +189,14 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
||||
.interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_AP),
|
||||
.supports_monitor = false,
|
||||
.full_monitor_mode = false,
|
||||
.supports_shadow_regs = true,
|
||||
.idle_ps = true,
|
||||
.supports_sta_ps = true,
|
||||
.cold_boot_calib = false,
|
||||
.fw_mem_mode = 0,
|
||||
.num_vdevs = 16 + 1,
|
||||
.num_peers = 512,
|
||||
.supports_suspend = true,
|
||||
.hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074),
|
||||
.fix_l1ss = true,
|
||||
@ -234,10 +246,14 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
||||
BIT(NL80211_IFTYPE_AP) |
|
||||
BIT(NL80211_IFTYPE_MESH_POINT),
|
||||
.supports_monitor = true,
|
||||
.full_monitor_mode = true,
|
||||
.supports_shadow_regs = false,
|
||||
.idle_ps = false,
|
||||
.supports_sta_ps = false,
|
||||
.cold_boot_calib = false,
|
||||
.fw_mem_mode = 2,
|
||||
.num_vdevs = 8,
|
||||
.num_peers = 128,
|
||||
.supports_suspend = false,
|
||||
.hal_desc_sz = sizeof(struct hal_rx_desc_qcn9074),
|
||||
.fix_l1ss = true,
|
||||
@ -287,10 +303,70 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
|
||||
.interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_AP),
|
||||
.supports_monitor = false,
|
||||
.full_monitor_mode = false,
|
||||
.supports_shadow_regs = true,
|
||||
.idle_ps = true,
|
||||
.supports_sta_ps = true,
|
||||
.cold_boot_calib = false,
|
||||
.fw_mem_mode = 0,
|
||||
.num_vdevs = 16 + 1,
|
||||
.num_peers = 512,
|
||||
.supports_suspend = true,
|
||||
.hal_desc_sz = sizeof(struct hal_rx_desc_wcn6855),
|
||||
.fix_l1ss = false,
|
||||
.credit_flow = true,
|
||||
.max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
|
||||
.hal_params = &ath11k_hw_hal_params_qca6390,
|
||||
.supports_dynamic_smps_6ghz = false,
|
||||
.alloc_cacheable_memory = false,
|
||||
.wakeup_mhi = true,
|
||||
},
|
||||
{
|
||||
.name = "wcn6855 hw2.1",
|
||||
.hw_rev = ATH11K_HW_WCN6855_HW21,
|
||||
.fw = {
|
||||
.dir = "WCN6855/hw2.1",
|
||||
.board_size = 256 * 1024,
|
||||
.cal_offset = 128 * 1024,
|
||||
},
|
||||
.max_radios = 3,
|
||||
.bdf_addr = 0x4B0C0000,
|
||||
.hw_ops = &wcn6855_ops,
|
||||
.ring_mask = &ath11k_hw_ring_mask_qca6390,
|
||||
.internal_sleep_clock = true,
|
||||
.regs = &wcn6855_regs,
|
||||
.qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCA6390,
|
||||
.host_ce_config = ath11k_host_ce_config_qca6390,
|
||||
.ce_count = 9,
|
||||
.target_ce_config = ath11k_target_ce_config_wlan_qca6390,
|
||||
.target_ce_count = 9,
|
||||
.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qca6390,
|
||||
.svc_to_ce_map_len = 14,
|
||||
.single_pdev_only = true,
|
||||
.rxdma1_enable = false,
|
||||
.num_rxmda_per_pdev = 2,
|
||||
.rx_mac_buf_ring = true,
|
||||
.vdev_start_delay = true,
|
||||
.htt_peer_map_v2 = false,
|
||||
|
||||
.spectral = {
|
||||
.fft_sz = 0,
|
||||
.fft_pad_sz = 0,
|
||||
.summary_pad_sz = 0,
|
||||
.fft_hdr_len = 0,
|
||||
.max_fft_bins = 0,
|
||||
},
|
||||
|
||||
.interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_AP),
|
||||
.supports_monitor = false,
|
||||
.supports_shadow_regs = true,
|
||||
.idle_ps = true,
|
||||
.supports_sta_ps = true,
|
||||
.cold_boot_calib = false,
|
||||
.fw_mem_mode = 0,
|
||||
.num_vdevs = 16 + 1,
|
||||
.num_peers = 512,
|
||||
.supports_suspend = true,
|
||||
.hal_desc_sz = sizeof(struct hal_rx_desc_wcn6855),
|
||||
.fix_l1ss = false,
|
||||
@ -1009,7 +1085,7 @@ static int ath11k_core_reconfigure_on_crash(struct ath11k_base *ab)
|
||||
ath11k_dp_free(ab);
|
||||
ath11k_hal_srng_deinit(ab);
|
||||
|
||||
ab->free_vdev_map = (1LL << (ab->num_radios * TARGET_NUM_VDEVS)) - 1;
|
||||
ab->free_vdev_map = (1LL << (ab->num_radios * TARGET_NUM_VDEVS(ab))) - 1;
|
||||
|
||||
ret = ath11k_hal_srng_init(ab);
|
||||
if (ret)
|
||||
@ -1043,6 +1119,7 @@ void ath11k_core_halt(struct ath11k *ar)
|
||||
ath11k_mac_peer_cleanup_all(ar);
|
||||
cancel_delayed_work_sync(&ar->scan.timeout);
|
||||
cancel_work_sync(&ar->regd_update_work);
|
||||
cancel_work_sync(&ab->update_11d_work);
|
||||
|
||||
rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx], NULL);
|
||||
synchronize_rcu();
|
||||
@ -1050,6 +1127,34 @@ void ath11k_core_halt(struct ath11k *ar)
|
||||
idr_init(&ar->txmgmt_idr);
|
||||
}
|
||||
|
||||
static void ath11k_update_11d(struct work_struct *work)
|
||||
{
|
||||
struct ath11k_base *ab = container_of(work, struct ath11k_base, update_11d_work);
|
||||
struct ath11k *ar;
|
||||
struct ath11k_pdev *pdev;
|
||||
struct wmi_set_current_country_params set_current_param = {};
|
||||
int ret, i;
|
||||
|
||||
spin_lock_bh(&ab->base_lock);
|
||||
memcpy(&set_current_param.alpha2, &ab->new_alpha2, 2);
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI, "update 11d new cc %c%c\n",
|
||||
set_current_param.alpha2[0],
|
||||
set_current_param.alpha2[1]);
|
||||
|
||||
for (i = 0; i < ab->num_radios; i++) {
|
||||
pdev = &ab->pdevs[i];
|
||||
ar = pdev->ar;
|
||||
|
||||
ret = ath11k_wmi_send_set_current_country_cmd(ar, &set_current_param);
|
||||
if (ret)
|
||||
ath11k_warn(ar->ab,
|
||||
"pdev id %d failed set current country code: %d\n",
|
||||
i, ret);
|
||||
}
|
||||
}
|
||||
|
||||
static void ath11k_core_restart(struct work_struct *work)
|
||||
{
|
||||
struct ath11k_base *ab = container_of(work, struct ath11k_base, restart_work);
|
||||
@ -1083,6 +1188,7 @@ static void ath11k_core_restart(struct work_struct *work)
|
||||
idr_for_each(&ar->txmgmt_idr,
|
||||
ath11k_mac_tx_mgmt_pending_free, ar);
|
||||
idr_destroy(&ar->txmgmt_idr);
|
||||
wake_up(&ar->txmgmt_empty_waitq);
|
||||
}
|
||||
|
||||
wake_up(&ab->wmi_ab.tx_credits_wq);
|
||||
@ -1219,12 +1325,14 @@ struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size,
|
||||
|
||||
mutex_init(&ab->core_lock);
|
||||
spin_lock_init(&ab->base_lock);
|
||||
mutex_init(&ab->vdev_id_11d_lock);
|
||||
|
||||
INIT_LIST_HEAD(&ab->peers);
|
||||
init_waitqueue_head(&ab->peer_mapping_wq);
|
||||
init_waitqueue_head(&ab->wmi_ab.tx_credits_wq);
|
||||
init_waitqueue_head(&ab->qmi.cold_boot_waitq);
|
||||
INIT_WORK(&ab->restart_work, ath11k_core_restart);
|
||||
INIT_WORK(&ab->update_11d_work, ath11k_update_11d);
|
||||
timer_setup(&ab->rx_replenish_retry, ath11k_ce_rx_replenish_retry, 0);
|
||||
init_completion(&ab->htc_suspend);
|
||||
init_completion(&ab->wow.wakeup_completed);
|
||||
|
@ -117,6 +117,7 @@ enum ath11k_hw_rev {
|
||||
ATH11K_HW_IPQ6018_HW10,
|
||||
ATH11K_HW_QCN9074_HW10,
|
||||
ATH11K_HW_WCN6855_HW20,
|
||||
ATH11K_HW_WCN6855_HW21,
|
||||
};
|
||||
|
||||
enum ath11k_firmware_mode {
|
||||
@ -199,6 +200,9 @@ enum ath11k_dev_flags {
|
||||
ATH11K_FLAG_REGISTERED,
|
||||
ATH11K_FLAG_QMI_FAIL,
|
||||
ATH11K_FLAG_HTC_SUSPEND_COMPLETE,
|
||||
ATH11K_FLAG_CE_IRQ_ENABLED,
|
||||
ATH11K_FLAG_EXT_IRQ_ENABLED,
|
||||
ATH11K_FLAG_FIXED_MEM_RGN,
|
||||
};
|
||||
|
||||
enum ath11k_monitor_flags {
|
||||
@ -547,6 +551,7 @@ struct ath11k {
|
||||
/* protects txmgmt_idr data */
|
||||
spinlock_t txmgmt_idr_lock;
|
||||
atomic_t num_pending_mgmt_tx;
|
||||
wait_queue_head_t txmgmt_empty_waitq;
|
||||
|
||||
/* cycle count is reported twice for each visited channel during scan.
|
||||
* access protected by data_lock
|
||||
@ -585,6 +590,11 @@ struct ath11k {
|
||||
#endif
|
||||
bool dfs_block_radar_events;
|
||||
struct ath11k_thermal thermal;
|
||||
u32 vdev_id_11d_scan;
|
||||
struct completion finish_11d_scan;
|
||||
struct completion finish_11d_ch_list;
|
||||
bool pending_11d;
|
||||
bool regdom_set_by_user;
|
||||
};
|
||||
|
||||
struct ath11k_band_cap {
|
||||
@ -711,6 +721,11 @@ struct ath11k_base {
|
||||
/* Protects data like peers */
|
||||
spinlock_t base_lock;
|
||||
struct ath11k_pdev pdevs[MAX_RADIOS];
|
||||
struct {
|
||||
enum WMI_HOST_WLAN_BAND supported_bands;
|
||||
u32 pdev_id;
|
||||
} target_pdev_ids[MAX_RADIOS];
|
||||
u8 target_pdev_count;
|
||||
struct ath11k_pdev __rcu *pdevs_active[MAX_RADIOS];
|
||||
struct ath11k_hal_reg_capabilities_ext hal_reg_cap[MAX_RADIOS];
|
||||
unsigned long long free_vdev_map;
|
||||
@ -754,6 +769,8 @@ struct ath11k_base {
|
||||
struct completion driver_recovery;
|
||||
struct workqueue_struct *workqueue;
|
||||
struct work_struct restart_work;
|
||||
struct work_struct update_11d_work;
|
||||
u8 new_alpha2[3];
|
||||
struct {
|
||||
/* protected by data_lock */
|
||||
u32 fw_crash_counter;
|
||||
@ -763,6 +780,8 @@ struct ath11k_base {
|
||||
struct ath11k_dbring_cap *db_caps;
|
||||
u32 num_db_cap;
|
||||
|
||||
/* To synchronize 11d scan vdev id */
|
||||
struct mutex vdev_id_11d_lock;
|
||||
struct timer_list mon_reap_timer;
|
||||
|
||||
struct completion htc_suspend;
|
||||
|
@ -6,6 +6,35 @@
|
||||
#include "core.h"
|
||||
#include "debug.h"
|
||||
|
||||
#define ATH11K_DB_MAGIC_VALUE 0xdeadbeaf
|
||||
|
||||
int ath11k_dbring_validate_buffer(struct ath11k *ar, void *buffer, u32 size)
|
||||
{
|
||||
u32 *temp;
|
||||
int idx;
|
||||
|
||||
size = size >> 2;
|
||||
|
||||
for (idx = 0, temp = buffer; idx < size; idx++, temp++) {
|
||||
if (*temp == ATH11K_DB_MAGIC_VALUE)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath11k_dbring_fill_magic_value(struct ath11k *ar,
|
||||
void *buffer, u32 size)
|
||||
{
|
||||
u32 *temp;
|
||||
int idx;
|
||||
|
||||
size = size >> 2;
|
||||
|
||||
for (idx = 0, temp = buffer; idx < size; idx++, temp++)
|
||||
*temp++ = ATH11K_DB_MAGIC_VALUE;
|
||||
}
|
||||
|
||||
static int ath11k_dbring_bufs_replenish(struct ath11k *ar,
|
||||
struct ath11k_dbring *ring,
|
||||
struct ath11k_dbring_element *buff)
|
||||
@ -26,6 +55,7 @@ static int ath11k_dbring_bufs_replenish(struct ath11k *ar,
|
||||
|
||||
ptr_unaligned = buff->payload;
|
||||
ptr_aligned = PTR_ALIGN(ptr_unaligned, ring->buf_align);
|
||||
ath11k_dbring_fill_magic_value(ar, ptr_aligned, ring->buf_sz);
|
||||
paddr = dma_map_single(ab->dev, ptr_aligned, ring->buf_sz,
|
||||
DMA_FROM_DEVICE);
|
||||
|
||||
|
@ -76,4 +76,6 @@ int ath11k_dbring_get_cap(struct ath11k_base *ab,
|
||||
struct ath11k_dbring_cap *db_cap);
|
||||
void ath11k_dbring_srng_cleanup(struct ath11k *ar, struct ath11k_dbring *ring);
|
||||
void ath11k_dbring_buf_cleanup(struct ath11k *ar, struct ath11k_dbring *ring);
|
||||
int ath11k_dbring_validate_buffer(struct ath11k *ar, void *data, u32 size);
|
||||
|
||||
#endif /* ATH11K_DBRING_H */
|
||||
|
@ -1051,6 +1051,7 @@ int ath11k_dp_alloc(struct ath11k_base *ab)
|
||||
|
||||
INIT_LIST_HEAD(&dp->reo_cmd_list);
|
||||
INIT_LIST_HEAD(&dp->reo_cmd_cache_flush_list);
|
||||
INIT_LIST_HEAD(&dp->dp_full_mon_mpdu_list);
|
||||
spin_lock_init(&dp->reo_cmd_lock);
|
||||
|
||||
dp->reo_cmd_cache_flush_count = 0;
|
||||
|
@ -89,6 +89,19 @@ struct dp_tx_ring {
|
||||
int tx_status_tail;
|
||||
};
|
||||
|
||||
enum dp_mon_status_buf_state {
|
||||
/* PPDU id matches in dst ring and status ring */
|
||||
DP_MON_STATUS_MATCH,
|
||||
/* status ring dma is not done */
|
||||
DP_MON_STATUS_NO_DMA,
|
||||
/* status ring is lagging, reap status ring */
|
||||
DP_MON_STATUS_LAG,
|
||||
/* status ring is leading, reap dst ring and drop */
|
||||
DP_MON_STATUS_LEAD,
|
||||
/* replinish monitor status ring */
|
||||
DP_MON_STATUS_REPLINISH,
|
||||
};
|
||||
|
||||
struct ath11k_pdev_mon_stats {
|
||||
u32 status_ppdu_state;
|
||||
u32 status_ppdu_start;
|
||||
@ -104,6 +117,12 @@ struct ath11k_pdev_mon_stats {
|
||||
u32 dup_mon_buf_cnt;
|
||||
};
|
||||
|
||||
struct dp_full_mon_mpdu {
|
||||
struct list_head list;
|
||||
struct sk_buff *head;
|
||||
struct sk_buff *tail;
|
||||
};
|
||||
|
||||
struct dp_link_desc_bank {
|
||||
void *vaddr_unaligned;
|
||||
void *vaddr;
|
||||
@ -135,7 +154,11 @@ struct ath11k_mon_data {
|
||||
u32 mon_last_buf_cookie;
|
||||
u64 mon_last_linkdesc_paddr;
|
||||
u16 chan_noise_floor;
|
||||
|
||||
bool hold_mon_dst_ring;
|
||||
enum dp_mon_status_buf_state buf_state;
|
||||
dma_addr_t mon_status_paddr;
|
||||
struct dp_full_mon_mpdu *mon_mpdu;
|
||||
struct hal_sw_mon_ring_entries sw_mon_entries;
|
||||
struct ath11k_pdev_mon_stats rx_mon_stats;
|
||||
/* lock for monitor data */
|
||||
spinlock_t mon_lock;
|
||||
@ -245,6 +268,7 @@ struct ath11k_dp {
|
||||
struct hal_wbm_idle_scatter_list scatter_list[DP_IDLE_SCATTER_BUFS_MAX];
|
||||
struct list_head reo_cmd_list;
|
||||
struct list_head reo_cmd_cache_flush_list;
|
||||
struct list_head dp_full_mon_mpdu_list;
|
||||
u32 reo_cmd_cache_flush_count;
|
||||
/**
|
||||
* protects access to below fields,
|
||||
@ -292,6 +316,7 @@ enum htt_h2t_msg_type {
|
||||
HTT_H2T_MSG_TYPE_RX_RING_SELECTION_CFG = 0xc,
|
||||
HTT_H2T_MSG_TYPE_EXT_STATS_CFG = 0x10,
|
||||
HTT_H2T_MSG_TYPE_PPDU_STATS_CFG = 0x11,
|
||||
HTT_H2T_MSG_TYPE_RX_FULL_MONITOR_MODE = 0x17,
|
||||
};
|
||||
|
||||
#define HTT_VER_REQ_INFO_MSG_ID GENMASK(7, 0)
|
||||
@ -957,6 +982,33 @@ struct htt_rx_ring_tlv_filter {
|
||||
u32 pkt_filter_flags3; /* DATA */
|
||||
};
|
||||
|
||||
#define HTT_RX_FULL_MON_MODE_CFG_CMD_INFO0_MSG_TYPE GENMASK(7, 0)
|
||||
#define HTT_RX_FULL_MON_MODE_CFG_CMD_INFO0_PDEV_ID GENMASK(15, 8)
|
||||
|
||||
#define HTT_RX_FULL_MON_MODE_CFG_CMD_CFG_ENABLE BIT(0)
|
||||
#define HTT_RX_FULL_MON_MODE_CFG_CMD_CFG_ZERO_MPDUS_END BIT(1)
|
||||
#define HTT_RX_FULL_MON_MODE_CFG_CMD_CFG_NON_ZERO_MPDUS_END BIT(2)
|
||||
#define HTT_RX_FULL_MON_MODE_CFG_CMD_CFG_RELEASE_RING GENMASK(10, 3)
|
||||
|
||||
/**
|
||||
* Enumeration for full monitor mode destination ring select
|
||||
* 0 - REO destination ring select
|
||||
* 1 - FW destination ring select
|
||||
* 2 - SW destination ring select
|
||||
* 3 - Release destination ring select
|
||||
*/
|
||||
enum htt_rx_full_mon_release_ring {
|
||||
HTT_RX_MON_RING_REO,
|
||||
HTT_RX_MON_RING_FW,
|
||||
HTT_RX_MON_RING_SW,
|
||||
HTT_RX_MON_RING_RELEASE,
|
||||
};
|
||||
|
||||
struct htt_rx_full_monitor_mode_cfg_cmd {
|
||||
u32 info0;
|
||||
u32 cfg;
|
||||
} __packed;
|
||||
|
||||
/* HTT message target->host */
|
||||
|
||||
enum htt_t2h_msg_type {
|
||||
|
@ -2942,6 +2942,43 @@ fail_desc_get:
|
||||
return req_entries - num_remain;
|
||||
}
|
||||
|
||||
#define ATH11K_DP_RX_FULL_MON_PPDU_ID_WRAP 32535
|
||||
|
||||
static void
|
||||
ath11k_dp_rx_mon_update_status_buf_state(struct ath11k_mon_data *pmon,
|
||||
struct hal_tlv_hdr *tlv)
|
||||
{
|
||||
struct hal_rx_ppdu_start *ppdu_start;
|
||||
u16 ppdu_id_diff, ppdu_id, tlv_len;
|
||||
u8 *ptr;
|
||||
|
||||
/* PPDU id is part of second tlv, move ptr to second tlv */
|
||||
tlv_len = FIELD_GET(HAL_TLV_HDR_LEN, tlv->tl);
|
||||
ptr = (u8 *)tlv;
|
||||
ptr += sizeof(*tlv) + tlv_len;
|
||||
tlv = (struct hal_tlv_hdr *)ptr;
|
||||
|
||||
if (FIELD_GET(HAL_TLV_HDR_TAG, tlv->tl) != HAL_RX_PPDU_START)
|
||||
return;
|
||||
|
||||
ptr += sizeof(*tlv);
|
||||
ppdu_start = (struct hal_rx_ppdu_start *)ptr;
|
||||
ppdu_id = FIELD_GET(HAL_RX_PPDU_START_INFO0_PPDU_ID,
|
||||
__le32_to_cpu(ppdu_start->info0));
|
||||
|
||||
if (pmon->sw_mon_entries.ppdu_id < ppdu_id) {
|
||||
pmon->buf_state = DP_MON_STATUS_LEAD;
|
||||
ppdu_id_diff = ppdu_id - pmon->sw_mon_entries.ppdu_id;
|
||||
if (ppdu_id_diff > ATH11K_DP_RX_FULL_MON_PPDU_ID_WRAP)
|
||||
pmon->buf_state = DP_MON_STATUS_LAG;
|
||||
} else if (pmon->sw_mon_entries.ppdu_id > ppdu_id) {
|
||||
pmon->buf_state = DP_MON_STATUS_LAG;
|
||||
ppdu_id_diff = pmon->sw_mon_entries.ppdu_id - ppdu_id;
|
||||
if (ppdu_id_diff > ATH11K_DP_RX_FULL_MON_PPDU_ID_WRAP)
|
||||
pmon->buf_state = DP_MON_STATUS_LEAD;
|
||||
}
|
||||
}
|
||||
|
||||
static int ath11k_dp_rx_reap_mon_status_ring(struct ath11k_base *ab, int mac_id,
|
||||
int *budget, struct sk_buff_head *skb_list)
|
||||
{
|
||||
@ -2949,6 +2986,7 @@ static int ath11k_dp_rx_reap_mon_status_ring(struct ath11k_base *ab, int mac_id,
|
||||
const struct ath11k_hw_hal_params *hal_params;
|
||||
struct ath11k_pdev_dp *dp;
|
||||
struct dp_rxdma_ring *rx_ring;
|
||||
struct ath11k_mon_data *pmon;
|
||||
struct hal_srng *srng;
|
||||
void *rx_mon_status_desc;
|
||||
struct sk_buff *skb;
|
||||
@ -2962,6 +3000,7 @@ static int ath11k_dp_rx_reap_mon_status_ring(struct ath11k_base *ab, int mac_id,
|
||||
|
||||
ar = ab->pdevs[ath11k_hw_mac_id_to_pdev_id(&ab->hw_params, mac_id)].ar;
|
||||
dp = &ar->dp;
|
||||
pmon = &dp->mon_data;
|
||||
srng_id = ath11k_hw_mac_id_to_srng_id(&ab->hw_params, mac_id);
|
||||
rx_ring = &dp->rx_mon_status_refill_ring[srng_id];
|
||||
|
||||
@ -2974,8 +3013,10 @@ static int ath11k_dp_rx_reap_mon_status_ring(struct ath11k_base *ab, int mac_id,
|
||||
*budget -= 1;
|
||||
rx_mon_status_desc =
|
||||
ath11k_hal_srng_src_peek(ab, srng);
|
||||
if (!rx_mon_status_desc)
|
||||
if (!rx_mon_status_desc) {
|
||||
pmon->buf_state = DP_MON_STATUS_REPLINISH;
|
||||
break;
|
||||
}
|
||||
|
||||
ath11k_hal_rx_buf_addr_info_get(rx_mon_status_desc, &paddr,
|
||||
&cookie, &rbm);
|
||||
@ -2988,6 +3029,7 @@ static int ath11k_dp_rx_reap_mon_status_ring(struct ath11k_base *ab, int mac_id,
|
||||
ath11k_warn(ab, "rx monitor status with invalid buf_id %d\n",
|
||||
buf_id);
|
||||
spin_unlock_bh(&rx_ring->idr_lock);
|
||||
pmon->buf_state = DP_MON_STATUS_REPLINISH;
|
||||
goto move_next;
|
||||
}
|
||||
|
||||
@ -3007,10 +3049,18 @@ static int ath11k_dp_rx_reap_mon_status_ring(struct ath11k_base *ab, int mac_id,
|
||||
FIELD_GET(HAL_TLV_HDR_TAG,
|
||||
tlv->tl));
|
||||
dev_kfree_skb_any(skb);
|
||||
pmon->buf_state = DP_MON_STATUS_NO_DMA;
|
||||
goto move_next;
|
||||
}
|
||||
|
||||
if (ab->hw_params.full_monitor_mode) {
|
||||
ath11k_dp_rx_mon_update_status_buf_state(pmon, tlv);
|
||||
if (paddr == pmon->mon_status_paddr)
|
||||
pmon->buf_state = DP_MON_STATUS_MATCH;
|
||||
}
|
||||
__skb_queue_tail(skb_list, skb);
|
||||
} else {
|
||||
pmon->buf_state = DP_MON_STATUS_REPLINISH;
|
||||
}
|
||||
move_next:
|
||||
skb = ath11k_dp_rx_alloc_mon_status_buf(ab, rx_ring,
|
||||
@ -3061,10 +3111,10 @@ int ath11k_dp_rx_process_mon_status(struct ath11k_base *ab, int mac_id,
|
||||
if (!num_buffs_reaped)
|
||||
goto exit;
|
||||
|
||||
while ((skb = __skb_dequeue(&skb_list))) {
|
||||
memset(&ppdu_info, 0, sizeof(ppdu_info));
|
||||
ppdu_info.peer_id = HAL_INVALID_PEERID;
|
||||
memset(&ppdu_info, 0, sizeof(ppdu_info));
|
||||
ppdu_info.peer_id = HAL_INVALID_PEERID;
|
||||
|
||||
while ((skb = __skb_dequeue(&skb_list))) {
|
||||
if (ath11k_debugfs_is_pktlog_lite_mode_enabled(ar)) {
|
||||
log_type = ATH11K_PKTLOG_TYPE_LITE_RX;
|
||||
rx_buf_sz = DP_RX_BUFFER_SIZE_LITE;
|
||||
@ -3092,10 +3142,7 @@ int ath11k_dp_rx_process_mon_status(struct ath11k_base *ab, int mac_id,
|
||||
ath11k_dbg(ab, ATH11K_DBG_DATA,
|
||||
"failed to find the peer with peer_id %d\n",
|
||||
ppdu_info.peer_id);
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
rcu_read_unlock();
|
||||
dev_kfree_skb_any(skb);
|
||||
continue;
|
||||
goto next_skb;
|
||||
}
|
||||
|
||||
arsta = (struct ath11k_sta *)peer->sta->drv_priv;
|
||||
@ -3104,10 +3151,13 @@ int ath11k_dp_rx_process_mon_status(struct ath11k_base *ab, int mac_id,
|
||||
if (ath11k_debugfs_is_pktlog_peer_valid(ar, peer->addr))
|
||||
trace_ath11k_htt_rxdesc(ar, skb->data, log_type, rx_buf_sz);
|
||||
|
||||
next_skb:
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
rcu_read_unlock();
|
||||
|
||||
dev_kfree_skb_any(skb);
|
||||
memset(&ppdu_info, 0, sizeof(ppdu_info));
|
||||
ppdu_info.peer_id = HAL_INVALID_PEERID;
|
||||
}
|
||||
exit:
|
||||
return num_buffs_reaped;
|
||||
@ -5098,6 +5148,357 @@ static void ath11k_dp_rx_mon_status_process_tlv(struct ath11k *ar,
|
||||
}
|
||||
}
|
||||
|
||||
static u32
|
||||
ath11k_dp_rx_full_mon_mpdu_pop(struct ath11k *ar,
|
||||
void *ring_entry, struct sk_buff **head_msdu,
|
||||
struct sk_buff **tail_msdu,
|
||||
struct hal_sw_mon_ring_entries *sw_mon_entries)
|
||||
{
|
||||
struct ath11k_pdev_dp *dp = &ar->dp;
|
||||
struct ath11k_mon_data *pmon = &dp->mon_data;
|
||||
struct dp_rxdma_ring *rx_ring = &dp->rxdma_mon_buf_ring;
|
||||
struct sk_buff *msdu = NULL, *last = NULL;
|
||||
struct hal_sw_monitor_ring *sw_desc = ring_entry;
|
||||
struct hal_rx_msdu_list msdu_list;
|
||||
struct hal_rx_desc *rx_desc;
|
||||
struct ath11k_skb_rxcb *rxcb;
|
||||
void *rx_msdu_link_desc;
|
||||
void *p_buf_addr_info, *p_last_buf_addr_info;
|
||||
int buf_id, i = 0;
|
||||
u32 rx_buf_size, rx_pkt_offset, l2_hdr_offset;
|
||||
u32 rx_bufs_used = 0, msdu_cnt = 0;
|
||||
u32 total_len = 0, frag_len = 0, sw_cookie;
|
||||
u16 num_msdus = 0;
|
||||
u8 rxdma_err, rbm;
|
||||
bool is_frag, is_first_msdu;
|
||||
bool drop_mpdu = false;
|
||||
|
||||
ath11k_hal_rx_sw_mon_ring_buf_paddr_get(ring_entry, sw_mon_entries);
|
||||
|
||||
sw_cookie = sw_mon_entries->mon_dst_sw_cookie;
|
||||
sw_mon_entries->end_of_ppdu = false;
|
||||
sw_mon_entries->drop_ppdu = false;
|
||||
p_last_buf_addr_info = sw_mon_entries->dst_buf_addr_info;
|
||||
msdu_cnt = sw_mon_entries->msdu_cnt;
|
||||
|
||||
sw_mon_entries->end_of_ppdu =
|
||||
FIELD_GET(HAL_SW_MON_RING_INFO0_END_OF_PPDU, sw_desc->info0);
|
||||
if (sw_mon_entries->end_of_ppdu)
|
||||
return rx_bufs_used;
|
||||
|
||||
if (FIELD_GET(HAL_SW_MON_RING_INFO0_RXDMA_PUSH_REASON,
|
||||
sw_desc->info0) ==
|
||||
HAL_REO_DEST_RING_PUSH_REASON_ERR_DETECTED) {
|
||||
rxdma_err =
|
||||
FIELD_GET(HAL_SW_MON_RING_INFO0_RXDMA_ERROR_CODE,
|
||||
sw_desc->info0);
|
||||
if (rxdma_err == HAL_REO_ENTR_RING_RXDMA_ECODE_FLUSH_REQUEST_ERR ||
|
||||
rxdma_err == HAL_REO_ENTR_RING_RXDMA_ECODE_MPDU_LEN_ERR ||
|
||||
rxdma_err == HAL_REO_ENTR_RING_RXDMA_ECODE_OVERFLOW_ERR) {
|
||||
pmon->rx_mon_stats.dest_mpdu_drop++;
|
||||
drop_mpdu = true;
|
||||
}
|
||||
}
|
||||
|
||||
is_frag = false;
|
||||
is_first_msdu = true;
|
||||
|
||||
do {
|
||||
rx_msdu_link_desc =
|
||||
(u8 *)pmon->link_desc_banks[sw_cookie].vaddr +
|
||||
(sw_mon_entries->mon_dst_paddr -
|
||||
pmon->link_desc_banks[sw_cookie].paddr);
|
||||
|
||||
ath11k_hal_rx_msdu_list_get(ar, rx_msdu_link_desc, &msdu_list,
|
||||
&num_msdus);
|
||||
|
||||
for (i = 0; i < num_msdus; i++) {
|
||||
buf_id = FIELD_GET(DP_RXDMA_BUF_COOKIE_BUF_ID,
|
||||
msdu_list.sw_cookie[i]);
|
||||
|
||||
spin_lock_bh(&rx_ring->idr_lock);
|
||||
msdu = idr_find(&rx_ring->bufs_idr, buf_id);
|
||||
if (!msdu) {
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_DATA,
|
||||
"full mon msdu_pop: invalid buf_id %d\n",
|
||||
buf_id);
|
||||
spin_unlock_bh(&rx_ring->idr_lock);
|
||||
break;
|
||||
}
|
||||
idr_remove(&rx_ring->bufs_idr, buf_id);
|
||||
spin_unlock_bh(&rx_ring->idr_lock);
|
||||
|
||||
rxcb = ATH11K_SKB_RXCB(msdu);
|
||||
if (!rxcb->unmapped) {
|
||||
dma_unmap_single(ar->ab->dev, rxcb->paddr,
|
||||
msdu->len +
|
||||
skb_tailroom(msdu),
|
||||
DMA_FROM_DEVICE);
|
||||
rxcb->unmapped = 1;
|
||||
}
|
||||
if (drop_mpdu) {
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_DATA,
|
||||
"full mon: i %d drop msdu %p *ppdu_id %x\n",
|
||||
i, msdu, sw_mon_entries->ppdu_id);
|
||||
dev_kfree_skb_any(msdu);
|
||||
msdu_cnt--;
|
||||
goto next_msdu;
|
||||
}
|
||||
|
||||
rx_desc = (struct hal_rx_desc *)msdu->data;
|
||||
|
||||
rx_pkt_offset = sizeof(struct hal_rx_desc);
|
||||
l2_hdr_offset = ath11k_dp_rx_h_msdu_end_l3pad(ar->ab, rx_desc);
|
||||
|
||||
if (is_first_msdu) {
|
||||
if (!ath11k_dp_rxdesc_mpdu_valid(ar->ab, rx_desc)) {
|
||||
drop_mpdu = true;
|
||||
dev_kfree_skb_any(msdu);
|
||||
msdu = NULL;
|
||||
goto next_msdu;
|
||||
}
|
||||
is_first_msdu = false;
|
||||
}
|
||||
|
||||
ath11k_dp_mon_get_buf_len(&msdu_list.msdu_info[i],
|
||||
&is_frag, &total_len,
|
||||
&frag_len, &msdu_cnt);
|
||||
|
||||
rx_buf_size = rx_pkt_offset + l2_hdr_offset + frag_len;
|
||||
|
||||
ath11k_dp_pkt_set_pktlen(msdu, rx_buf_size);
|
||||
|
||||
if (!(*head_msdu))
|
||||
*head_msdu = msdu;
|
||||
else if (last)
|
||||
last->next = msdu;
|
||||
|
||||
last = msdu;
|
||||
next_msdu:
|
||||
rx_bufs_used++;
|
||||
}
|
||||
|
||||
ath11k_dp_rx_mon_next_link_desc_get(rx_msdu_link_desc,
|
||||
&sw_mon_entries->mon_dst_paddr,
|
||||
&sw_mon_entries->mon_dst_sw_cookie,
|
||||
&rbm,
|
||||
&p_buf_addr_info);
|
||||
|
||||
if (ath11k_dp_rx_monitor_link_desc_return(ar,
|
||||
p_last_buf_addr_info,
|
||||
dp->mac_id))
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_DATA,
|
||||
"full mon: dp_rx_monitor_link_desc_return failed\n");
|
||||
|
||||
p_last_buf_addr_info = p_buf_addr_info;
|
||||
|
||||
} while (sw_mon_entries->mon_dst_paddr && msdu_cnt);
|
||||
|
||||
if (last)
|
||||
last->next = NULL;
|
||||
|
||||
*tail_msdu = msdu;
|
||||
|
||||
return rx_bufs_used;
|
||||
}
|
||||
|
||||
static int ath11k_dp_rx_full_mon_prepare_mpdu(struct ath11k_dp *dp,
|
||||
struct dp_full_mon_mpdu *mon_mpdu,
|
||||
struct sk_buff *head,
|
||||
struct sk_buff *tail)
|
||||
{
|
||||
mon_mpdu = kzalloc(sizeof(*mon_mpdu), GFP_ATOMIC);
|
||||
if (!mon_mpdu)
|
||||
return -ENOMEM;
|
||||
|
||||
list_add_tail(&mon_mpdu->list, &dp->dp_full_mon_mpdu_list);
|
||||
mon_mpdu->head = head;
|
||||
mon_mpdu->tail = tail;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath11k_dp_rx_full_mon_drop_ppdu(struct ath11k_dp *dp,
|
||||
struct dp_full_mon_mpdu *mon_mpdu)
|
||||
{
|
||||
struct dp_full_mon_mpdu *tmp;
|
||||
struct sk_buff *tmp_msdu, *skb_next;
|
||||
|
||||
if (list_empty(&dp->dp_full_mon_mpdu_list))
|
||||
return;
|
||||
|
||||
list_for_each_entry_safe(mon_mpdu, tmp, &dp->dp_full_mon_mpdu_list, list) {
|
||||
list_del(&mon_mpdu->list);
|
||||
|
||||
tmp_msdu = mon_mpdu->head;
|
||||
while (tmp_msdu) {
|
||||
skb_next = tmp_msdu->next;
|
||||
dev_kfree_skb_any(tmp_msdu);
|
||||
tmp_msdu = skb_next;
|
||||
}
|
||||
|
||||
kfree(mon_mpdu);
|
||||
}
|
||||
}
|
||||
|
||||
static int ath11k_dp_rx_full_mon_deliver_ppdu(struct ath11k *ar,
|
||||
int mac_id,
|
||||
struct ath11k_mon_data *pmon,
|
||||
struct napi_struct *napi)
|
||||
{
|
||||
struct ath11k_pdev_mon_stats *rx_mon_stats;
|
||||
struct dp_full_mon_mpdu *tmp;
|
||||
struct dp_full_mon_mpdu *mon_mpdu = pmon->mon_mpdu;
|
||||
struct sk_buff *head_msdu, *tail_msdu;
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
struct ath11k_dp *dp = &ab->dp;
|
||||
int ret;
|
||||
|
||||
rx_mon_stats = &pmon->rx_mon_stats;
|
||||
|
||||
list_for_each_entry_safe(mon_mpdu, tmp, &dp->dp_full_mon_mpdu_list, list) {
|
||||
list_del(&mon_mpdu->list);
|
||||
head_msdu = mon_mpdu->head;
|
||||
tail_msdu = mon_mpdu->tail;
|
||||
if (head_msdu && tail_msdu) {
|
||||
ret = ath11k_dp_rx_mon_deliver(ar, mac_id, head_msdu,
|
||||
tail_msdu, napi);
|
||||
rx_mon_stats->dest_mpdu_done++;
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_DATA, "full mon: deliver ppdu\n");
|
||||
}
|
||||
kfree(mon_mpdu);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
ath11k_dp_rx_process_full_mon_status_ring(struct ath11k_base *ab, int mac_id,
|
||||
struct napi_struct *napi, int budget)
|
||||
{
|
||||
struct ath11k *ar = ab->pdevs[mac_id].ar;
|
||||
struct ath11k_pdev_dp *dp = &ar->dp;
|
||||
struct ath11k_mon_data *pmon = &dp->mon_data;
|
||||
struct hal_sw_mon_ring_entries *sw_mon_entries;
|
||||
int quota = 0, work = 0, count;
|
||||
|
||||
sw_mon_entries = &pmon->sw_mon_entries;
|
||||
|
||||
while (pmon->hold_mon_dst_ring) {
|
||||
quota = ath11k_dp_rx_process_mon_status(ab, mac_id,
|
||||
napi, 1);
|
||||
if (pmon->buf_state == DP_MON_STATUS_MATCH) {
|
||||
count = sw_mon_entries->status_buf_count;
|
||||
if (count > 1) {
|
||||
quota += ath11k_dp_rx_process_mon_status(ab, mac_id,
|
||||
napi, count);
|
||||
}
|
||||
|
||||
ath11k_dp_rx_full_mon_deliver_ppdu(ar, dp->mac_id,
|
||||
pmon, napi);
|
||||
pmon->hold_mon_dst_ring = false;
|
||||
} else if (!pmon->mon_status_paddr ||
|
||||
pmon->buf_state == DP_MON_STATUS_LEAD) {
|
||||
sw_mon_entries->drop_ppdu = true;
|
||||
pmon->hold_mon_dst_ring = false;
|
||||
}
|
||||
|
||||
if (!quota)
|
||||
break;
|
||||
|
||||
work += quota;
|
||||
}
|
||||
|
||||
if (sw_mon_entries->drop_ppdu)
|
||||
ath11k_dp_rx_full_mon_drop_ppdu(&ab->dp, pmon->mon_mpdu);
|
||||
|
||||
return work;
|
||||
}
|
||||
|
||||
static int ath11k_dp_full_mon_process_rx(struct ath11k_base *ab, int mac_id,
|
||||
struct napi_struct *napi, int budget)
|
||||
{
|
||||
struct ath11k *ar = ab->pdevs[mac_id].ar;
|
||||
struct ath11k_pdev_dp *dp = &ar->dp;
|
||||
struct ath11k_mon_data *pmon = &dp->mon_data;
|
||||
struct hal_sw_mon_ring_entries *sw_mon_entries;
|
||||
struct ath11k_pdev_mon_stats *rx_mon_stats;
|
||||
struct sk_buff *head_msdu, *tail_msdu;
|
||||
void *mon_dst_srng = &ar->ab->hal.srng_list[dp->rxdma_mon_dst_ring.ring_id];
|
||||
void *ring_entry;
|
||||
u32 rx_bufs_used = 0, mpdu_rx_bufs_used;
|
||||
int quota = 0, ret;
|
||||
bool break_dst_ring = false;
|
||||
|
||||
spin_lock_bh(&pmon->mon_lock);
|
||||
|
||||
sw_mon_entries = &pmon->sw_mon_entries;
|
||||
rx_mon_stats = &pmon->rx_mon_stats;
|
||||
|
||||
if (pmon->hold_mon_dst_ring) {
|
||||
spin_unlock_bh(&pmon->mon_lock);
|
||||
goto reap_status_ring;
|
||||
}
|
||||
|
||||
ath11k_hal_srng_access_begin(ar->ab, mon_dst_srng);
|
||||
while ((ring_entry = ath11k_hal_srng_dst_peek(ar->ab, mon_dst_srng))) {
|
||||
head_msdu = NULL;
|
||||
tail_msdu = NULL;
|
||||
|
||||
mpdu_rx_bufs_used = ath11k_dp_rx_full_mon_mpdu_pop(ar, ring_entry,
|
||||
&head_msdu,
|
||||
&tail_msdu,
|
||||
sw_mon_entries);
|
||||
rx_bufs_used += mpdu_rx_bufs_used;
|
||||
|
||||
if (!sw_mon_entries->end_of_ppdu) {
|
||||
if (head_msdu) {
|
||||
ret = ath11k_dp_rx_full_mon_prepare_mpdu(&ab->dp,
|
||||
pmon->mon_mpdu,
|
||||
head_msdu,
|
||||
tail_msdu);
|
||||
if (ret)
|
||||
break_dst_ring = true;
|
||||
}
|
||||
|
||||
goto next_entry;
|
||||
} else {
|
||||
if (!sw_mon_entries->ppdu_id &&
|
||||
!sw_mon_entries->mon_status_paddr) {
|
||||
break_dst_ring = true;
|
||||
goto next_entry;
|
||||
}
|
||||
}
|
||||
|
||||
rx_mon_stats->dest_ppdu_done++;
|
||||
pmon->mon_ppdu_status = DP_PPDU_STATUS_START;
|
||||
pmon->buf_state = DP_MON_STATUS_LAG;
|
||||
pmon->mon_status_paddr = sw_mon_entries->mon_status_paddr;
|
||||
pmon->hold_mon_dst_ring = true;
|
||||
next_entry:
|
||||
ring_entry = ath11k_hal_srng_dst_get_next_entry(ar->ab,
|
||||
mon_dst_srng);
|
||||
if (break_dst_ring)
|
||||
break;
|
||||
}
|
||||
|
||||
ath11k_hal_srng_access_end(ar->ab, mon_dst_srng);
|
||||
spin_unlock_bh(&pmon->mon_lock);
|
||||
|
||||
if (rx_bufs_used) {
|
||||
ath11k_dp_rxbufs_replenish(ar->ab, dp->mac_id,
|
||||
&dp->rxdma_mon_buf_ring,
|
||||
rx_bufs_used,
|
||||
HAL_RX_BUF_RBM_SW3_BM);
|
||||
}
|
||||
|
||||
reap_status_ring:
|
||||
quota = ath11k_dp_rx_process_full_mon_status_ring(ab, mac_id,
|
||||
napi, budget);
|
||||
|
||||
return quota;
|
||||
}
|
||||
|
||||
static int ath11k_dp_mon_process_rx(struct ath11k_base *ab, int mac_id,
|
||||
struct napi_struct *napi, int budget)
|
||||
{
|
||||
@ -5120,10 +5521,14 @@ int ath11k_dp_rx_process_mon_rings(struct ath11k_base *ab, int mac_id,
|
||||
struct ath11k *ar = ath11k_ab_to_ar(ab, mac_id);
|
||||
int ret = 0;
|
||||
|
||||
if (test_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags))
|
||||
if (test_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags) &&
|
||||
ab->hw_params.full_monitor_mode)
|
||||
ret = ath11k_dp_full_mon_process_rx(ab, mac_id, napi, budget);
|
||||
else if (test_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags))
|
||||
ret = ath11k_dp_mon_process_rx(ab, mac_id, napi, budget);
|
||||
else
|
||||
ret = ath11k_dp_rx_process_mon_status(ab, mac_id, napi, budget);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "debugfs_sta.h"
|
||||
#include "hw.h"
|
||||
#include "peer.h"
|
||||
#include "mac.h"
|
||||
|
||||
static enum hal_tcl_encap_type
|
||||
ath11k_dp_tx_get_encap_type(struct ath11k_vif *arvif, struct sk_buff *skb)
|
||||
@ -985,6 +986,7 @@ ath11k_dp_tx_htt_h2t_ext_stats_req(struct ath11k *ar, u8 type,
|
||||
struct ath11k_dp *dp = &ab->dp;
|
||||
struct sk_buff *skb;
|
||||
struct htt_ext_stats_cfg_cmd *cmd;
|
||||
u32 pdev_id;
|
||||
int len = sizeof(*cmd);
|
||||
int ret;
|
||||
|
||||
@ -998,7 +1000,12 @@ ath11k_dp_tx_htt_h2t_ext_stats_req(struct ath11k *ar, u8 type,
|
||||
memset(cmd, 0, sizeof(*cmd));
|
||||
cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_EXT_STATS_CFG;
|
||||
|
||||
cmd->hdr.pdev_mask = 1 << ar->pdev->pdev_id;
|
||||
if (ab->hw_params.single_pdev_only)
|
||||
pdev_id = ath11k_mac_get_target_pdev_id(ar);
|
||||
else
|
||||
pdev_id = ar->pdev->pdev_id;
|
||||
|
||||
cmd->hdr.pdev_mask = 1 << pdev_id;
|
||||
|
||||
cmd->hdr.stats_type = type;
|
||||
cmd->cfg_param0 = cfg_params->cfg0;
|
||||
@ -1026,6 +1033,15 @@ int ath11k_dp_tx_htt_monitor_mode_ring_config(struct ath11k *ar, bool reset)
|
||||
struct htt_rx_ring_tlv_filter tlv_filter = {0};
|
||||
int ret = 0, ring_id = 0, i;
|
||||
|
||||
if (ab->hw_params.full_monitor_mode) {
|
||||
ret = ath11k_dp_tx_htt_rx_full_mon_setup(ab,
|
||||
dp->mac_id, !reset);
|
||||
if (ret < 0) {
|
||||
ath11k_err(ab, "failed to setup full monitor %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ring_id = dp->rxdma_mon_buf_ring.refill_buf_ring.ring_id;
|
||||
|
||||
if (!reset) {
|
||||
@ -1091,3 +1107,42 @@ int ath11k_dp_tx_htt_monitor_mode_ring_config(struct ath11k *ar, bool reset)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath11k_dp_tx_htt_rx_full_mon_setup(struct ath11k_base *ab, int mac_id,
|
||||
bool config)
|
||||
{
|
||||
struct htt_rx_full_monitor_mode_cfg_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
int ret, len = sizeof(*cmd);
|
||||
|
||||
skb = ath11k_htc_alloc_skb(ab, len);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
skb_put(skb, len);
|
||||
cmd = (struct htt_rx_full_monitor_mode_cfg_cmd *)skb->data;
|
||||
memset(cmd, 0, sizeof(*cmd));
|
||||
cmd->info0 = FIELD_PREP(HTT_RX_FULL_MON_MODE_CFG_CMD_INFO0_MSG_TYPE,
|
||||
HTT_H2T_MSG_TYPE_RX_FULL_MONITOR_MODE);
|
||||
|
||||
cmd->info0 |= FIELD_PREP(HTT_RX_FULL_MON_MODE_CFG_CMD_INFO0_PDEV_ID, mac_id);
|
||||
|
||||
cmd->cfg = HTT_RX_FULL_MON_MODE_CFG_CMD_CFG_ENABLE |
|
||||
FIELD_PREP(HTT_RX_FULL_MON_MODE_CFG_CMD_CFG_RELEASE_RING,
|
||||
HTT_RX_MON_RING_SW);
|
||||
if (config) {
|
||||
cmd->cfg |= HTT_RX_FULL_MON_MODE_CFG_CMD_CFG_ZERO_MPDUS_END |
|
||||
HTT_RX_FULL_MON_MODE_CFG_CMD_CFG_NON_ZERO_MPDUS_END;
|
||||
}
|
||||
|
||||
ret = ath11k_htc_send(&ab->htc, ab->dp.eid, skb);
|
||||
if (ret)
|
||||
goto err_free;
|
||||
|
||||
return 0;
|
||||
|
||||
err_free:
|
||||
dev_kfree_skb_any(skb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -37,4 +37,6 @@ int ath11k_dp_tx_htt_rx_filter_setup(struct ath11k_base *ab, u32 ring_id,
|
||||
int rx_buf_size,
|
||||
struct htt_rx_ring_tlv_filter *tlv_filter);
|
||||
|
||||
int ath11k_dp_tx_htt_rx_full_mon_setup(struct ath11k_base *ab, int mac_id,
|
||||
bool config);
|
||||
#endif
|
||||
|
@ -974,6 +974,7 @@ int ath11k_hal_srng_setup(struct ath11k_base *ab, enum hal_ring_type type,
|
||||
srng->msi_data = params->msi_data;
|
||||
srng->initialized = 1;
|
||||
spin_lock_init(&srng->lock);
|
||||
lockdep_set_class(&srng->lock, hal->srng_key + ring_id);
|
||||
|
||||
for (i = 0; i < HAL_SRNG_NUM_REG_GRP; i++) {
|
||||
srng->hwreg_base[i] = srng_config->reg_start[i] +
|
||||
@ -1260,6 +1261,24 @@ static int ath11k_hal_srng_create_config(struct ath11k_base *ab)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath11k_hal_register_srng_key(struct ath11k_base *ab)
|
||||
{
|
||||
struct ath11k_hal *hal = &ab->hal;
|
||||
u32 ring_id;
|
||||
|
||||
for (ring_id = 0; ring_id < HAL_SRNG_RING_ID_MAX; ring_id++)
|
||||
lockdep_register_key(hal->srng_key + ring_id);
|
||||
}
|
||||
|
||||
static void ath11k_hal_unregister_srng_key(struct ath11k_base *ab)
|
||||
{
|
||||
struct ath11k_hal *hal = &ab->hal;
|
||||
u32 ring_id;
|
||||
|
||||
for (ring_id = 0; ring_id < HAL_SRNG_RING_ID_MAX; ring_id++)
|
||||
lockdep_unregister_key(hal->srng_key + ring_id);
|
||||
}
|
||||
|
||||
int ath11k_hal_srng_init(struct ath11k_base *ab)
|
||||
{
|
||||
struct ath11k_hal *hal = &ab->hal;
|
||||
@ -1279,6 +1298,8 @@ int ath11k_hal_srng_init(struct ath11k_base *ab)
|
||||
if (ret)
|
||||
goto err_free_cont_rdp;
|
||||
|
||||
ath11k_hal_register_srng_key(ab);
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_cont_rdp:
|
||||
@ -1293,6 +1314,7 @@ void ath11k_hal_srng_deinit(struct ath11k_base *ab)
|
||||
{
|
||||
struct ath11k_hal *hal = &ab->hal;
|
||||
|
||||
ath11k_hal_unregister_srng_key(ab);
|
||||
ath11k_hal_free_cont_rdp(ab);
|
||||
ath11k_hal_free_cont_wrp(ab);
|
||||
kfree(hal->srng_config);
|
||||
|
@ -902,6 +902,8 @@ struct ath11k_hal {
|
||||
/* shadow register configuration */
|
||||
u32 shadow_reg_addr[HAL_SHADOW_NUM_REGS];
|
||||
int num_shadow_reg_configured;
|
||||
|
||||
struct lock_class_key srng_key[HAL_SRNG_RING_ID_MAX];
|
||||
};
|
||||
|
||||
u32 ath11k_hal_reo_qdesc_size(u32 ba_window_size, u8 tid);
|
||||
|
@ -858,6 +858,25 @@ struct hal_reo_entrance_ring {
|
||||
* this ring has looped around the ring.
|
||||
*/
|
||||
|
||||
#define HAL_SW_MON_RING_INFO0_RXDMA_PUSH_REASON GENMASK(1, 0)
|
||||
#define HAL_SW_MON_RING_INFO0_RXDMA_ERROR_CODE GENMASK(6, 2)
|
||||
#define HAL_SW_MON_RING_INFO0_MPDU_FRAG_NUMBER GENMASK(10, 7)
|
||||
#define HAL_SW_MON_RING_INFO0_FRAMELESS_BAR BIT(11)
|
||||
#define HAL_SW_MON_RING_INFO0_STATUS_BUF_CNT GENMASK(15, 12)
|
||||
#define HAL_SW_MON_RING_INFO0_END_OF_PPDU BIT(16)
|
||||
|
||||
#define HAL_SW_MON_RING_INFO1_PHY_PPDU_ID GENMASK(15, 0)
|
||||
#define HAL_SW_MON_RING_INFO1_RING_ID GENMASK(27, 20)
|
||||
#define HAL_SW_MON_RING_INFO1_LOOPING_COUNT GENMASK(31, 28)
|
||||
|
||||
struct hal_sw_monitor_ring {
|
||||
struct ath11k_buffer_addr buf_addr_info;
|
||||
struct rx_mpdu_desc rx_mpdu_info;
|
||||
struct ath11k_buffer_addr status_buf_addr_info;
|
||||
u32 info0;
|
||||
u32 info1;
|
||||
} __packed;
|
||||
|
||||
#define HAL_REO_CMD_HDR_INFO0_CMD_NUMBER GENMASK(15, 0)
|
||||
#define HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED BIT(16)
|
||||
|
||||
|
@ -29,8 +29,7 @@ static int ath11k_hal_reo_cmd_queue_stats(struct hal_tlv_hdr *tlv,
|
||||
FIELD_PREP(HAL_TLV_HDR_LEN, sizeof(*desc));
|
||||
|
||||
desc = (struct hal_reo_get_queue_stats *)tlv->value;
|
||||
memset(&desc->queue_addr_lo, 0,
|
||||
(sizeof(*desc) - sizeof(struct hal_reo_cmd_hdr)));
|
||||
memset_startat(desc, 0, queue_addr_lo);
|
||||
|
||||
desc->cmd.info0 &= ~HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED;
|
||||
if (cmd->flag & HAL_REO_CMD_FLG_NEED_STATUS)
|
||||
@ -62,8 +61,7 @@ static int ath11k_hal_reo_cmd_flush_cache(struct ath11k_hal *hal, struct hal_tlv
|
||||
FIELD_PREP(HAL_TLV_HDR_LEN, sizeof(*desc));
|
||||
|
||||
desc = (struct hal_reo_flush_cache *)tlv->value;
|
||||
memset(&desc->cache_addr_lo, 0,
|
||||
(sizeof(*desc) - sizeof(struct hal_reo_cmd_hdr)));
|
||||
memset_startat(desc, 0, cache_addr_lo);
|
||||
|
||||
desc->cmd.info0 &= ~HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED;
|
||||
if (cmd->flag & HAL_REO_CMD_FLG_NEED_STATUS)
|
||||
@ -101,8 +99,7 @@ static int ath11k_hal_reo_cmd_update_rx_queue(struct hal_tlv_hdr *tlv,
|
||||
FIELD_PREP(HAL_TLV_HDR_LEN, sizeof(*desc));
|
||||
|
||||
desc = (struct hal_reo_update_rx_queue *)tlv->value;
|
||||
memset(&desc->queue_addr_lo, 0,
|
||||
(sizeof(*desc) - sizeof(struct hal_reo_cmd_hdr)));
|
||||
memset_startat(desc, 0, queue_addr_lo);
|
||||
|
||||
desc->cmd.info0 &= ~HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED;
|
||||
if (cmd->flag & HAL_REO_CMD_FLG_NEED_STATUS)
|
||||
@ -764,15 +761,17 @@ void ath11k_hal_reo_qdesc_setup(void *vaddr, int tid, u32 ba_window_size,
|
||||
* size changes and also send WMI message to FW to change the REO
|
||||
* queue descriptor in Rx peer entry as part of dp_rx_tid_update.
|
||||
*/
|
||||
memset(ext_desc, 0, 3 * sizeof(*ext_desc));
|
||||
memset(ext_desc, 0, sizeof(*ext_desc));
|
||||
ath11k_hal_reo_set_desc_hdr(&ext_desc->desc_hdr, HAL_DESC_REO_OWNED,
|
||||
HAL_DESC_REO_QUEUE_EXT_DESC,
|
||||
REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_1);
|
||||
ext_desc++;
|
||||
memset(ext_desc, 0, sizeof(*ext_desc));
|
||||
ath11k_hal_reo_set_desc_hdr(&ext_desc->desc_hdr, HAL_DESC_REO_OWNED,
|
||||
HAL_DESC_REO_QUEUE_EXT_DESC,
|
||||
REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_2);
|
||||
ext_desc++;
|
||||
memset(ext_desc, 0, sizeof(*ext_desc));
|
||||
ath11k_hal_reo_set_desc_hdr(&ext_desc->desc_hdr, HAL_DESC_REO_OWNED,
|
||||
HAL_DESC_REO_QUEUE_EXT_DESC,
|
||||
REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_3);
|
||||
@ -1186,3 +1185,47 @@ void ath11k_hal_rx_reo_ent_buf_paddr_get(void *rx_desc, dma_addr_t *paddr,
|
||||
|
||||
*pp_buf_addr = (void *)buf_addr_info;
|
||||
}
|
||||
|
||||
void
|
||||
ath11k_hal_rx_sw_mon_ring_buf_paddr_get(void *rx_desc,
|
||||
struct hal_sw_mon_ring_entries *sw_mon_entries)
|
||||
{
|
||||
struct hal_sw_monitor_ring *sw_mon_ring = rx_desc;
|
||||
struct ath11k_buffer_addr *buf_addr_info;
|
||||
struct ath11k_buffer_addr *status_buf_addr_info;
|
||||
struct rx_mpdu_desc *rx_mpdu_desc_info_details;
|
||||
|
||||
rx_mpdu_desc_info_details = &sw_mon_ring->rx_mpdu_info;
|
||||
|
||||
sw_mon_entries->msdu_cnt = FIELD_GET(RX_MPDU_DESC_INFO0_MSDU_COUNT,
|
||||
rx_mpdu_desc_info_details->info0);
|
||||
|
||||
buf_addr_info = &sw_mon_ring->buf_addr_info;
|
||||
status_buf_addr_info = &sw_mon_ring->status_buf_addr_info;
|
||||
|
||||
sw_mon_entries->mon_dst_paddr = (((u64)FIELD_GET(BUFFER_ADDR_INFO1_ADDR,
|
||||
buf_addr_info->info1)) << 32) |
|
||||
FIELD_GET(BUFFER_ADDR_INFO0_ADDR,
|
||||
buf_addr_info->info0);
|
||||
|
||||
sw_mon_entries->mon_status_paddr =
|
||||
(((u64)FIELD_GET(BUFFER_ADDR_INFO1_ADDR,
|
||||
status_buf_addr_info->info1)) << 32) |
|
||||
FIELD_GET(BUFFER_ADDR_INFO0_ADDR,
|
||||
status_buf_addr_info->info0);
|
||||
|
||||
sw_mon_entries->mon_dst_sw_cookie = FIELD_GET(BUFFER_ADDR_INFO1_SW_COOKIE,
|
||||
buf_addr_info->info1);
|
||||
|
||||
sw_mon_entries->mon_status_sw_cookie = FIELD_GET(BUFFER_ADDR_INFO1_SW_COOKIE,
|
||||
status_buf_addr_info->info1);
|
||||
|
||||
sw_mon_entries->status_buf_count = FIELD_GET(HAL_SW_MON_RING_INFO0_STATUS_BUF_CNT,
|
||||
sw_mon_ring->info0);
|
||||
|
||||
sw_mon_entries->dst_buf_addr_info = buf_addr_info;
|
||||
sw_mon_entries->status_buf_addr_info = status_buf_addr_info;
|
||||
|
||||
sw_mon_entries->ppdu_id =
|
||||
FIELD_GET(HAL_SW_MON_RING_INFO1_PHY_PPDU_ID, sw_mon_ring->info1);
|
||||
}
|
||||
|
@ -77,6 +77,20 @@ enum hal_rx_mon_status {
|
||||
HAL_RX_MON_STATUS_BUF_DONE,
|
||||
};
|
||||
|
||||
struct hal_sw_mon_ring_entries {
|
||||
dma_addr_t mon_dst_paddr;
|
||||
dma_addr_t mon_status_paddr;
|
||||
u32 mon_dst_sw_cookie;
|
||||
u32 mon_status_sw_cookie;
|
||||
void *dst_buf_addr_info;
|
||||
void *status_buf_addr_info;
|
||||
u16 ppdu_id;
|
||||
u8 status_buf_count;
|
||||
u8 msdu_cnt;
|
||||
bool end_of_ppdu;
|
||||
bool drop_ppdu;
|
||||
};
|
||||
|
||||
struct hal_rx_mon_ppdu_info {
|
||||
u32 ppdu_id;
|
||||
u32 ppdu_ts;
|
||||
@ -331,6 +345,9 @@ void ath11k_hal_rx_reo_ent_buf_paddr_get(void *rx_desc,
|
||||
dma_addr_t *paddr, u32 *sw_cookie,
|
||||
void **pp_buf_addr_info, u8 *rbm,
|
||||
u32 *msdu_cnt);
|
||||
void
|
||||
ath11k_hal_rx_sw_mon_ring_buf_paddr_get(void *rx_desc,
|
||||
struct hal_sw_mon_ring_entries *sw_mon_ent);
|
||||
enum hal_rx_mon_status
|
||||
ath11k_hal_rx_parse_mon_status(struct ath11k_base *ab,
|
||||
struct hal_rx_mon_ppdu_info *ppdu_info,
|
||||
|
@ -150,18 +150,18 @@ static void ath11k_hw_ipq8074_reo_setup(struct ath11k_base *ab)
|
||||
static void ath11k_init_wmi_config_ipq8074(struct ath11k_base *ab,
|
||||
struct target_resource_config *config)
|
||||
{
|
||||
config->num_vdevs = ab->num_radios * TARGET_NUM_VDEVS;
|
||||
config->num_vdevs = ab->num_radios * TARGET_NUM_VDEVS(ab);
|
||||
|
||||
if (ab->num_radios == 2) {
|
||||
config->num_peers = TARGET_NUM_PEERS(DBS);
|
||||
config->num_tids = TARGET_NUM_TIDS(DBS);
|
||||
config->num_peers = TARGET_NUM_PEERS(ab, DBS);
|
||||
config->num_tids = TARGET_NUM_TIDS(ab, DBS);
|
||||
} else if (ab->num_radios == 3) {
|
||||
config->num_peers = TARGET_NUM_PEERS(DBS_SBS);
|
||||
config->num_tids = TARGET_NUM_TIDS(DBS_SBS);
|
||||
config->num_peers = TARGET_NUM_PEERS(ab, DBS_SBS);
|
||||
config->num_tids = TARGET_NUM_TIDS(ab, DBS_SBS);
|
||||
} else {
|
||||
/* Control should not reach here */
|
||||
config->num_peers = TARGET_NUM_PEERS(SINGLE);
|
||||
config->num_tids = TARGET_NUM_TIDS(SINGLE);
|
||||
config->num_peers = TARGET_NUM_PEERS(ab, SINGLE);
|
||||
config->num_tids = TARGET_NUM_TIDS(ab, SINGLE);
|
||||
}
|
||||
config->num_offload_peers = TARGET_NUM_OFFLD_PEERS;
|
||||
config->num_offload_reorder_buffs = TARGET_NUM_OFFLD_REORDER_BUFFS;
|
||||
|
@ -12,26 +12,26 @@
|
||||
/* Target configuration defines */
|
||||
|
||||
/* Num VDEVS per radio */
|
||||
#define TARGET_NUM_VDEVS (16 + 1)
|
||||
#define TARGET_NUM_VDEVS(ab) (ab->hw_params.num_vdevs)
|
||||
|
||||
#define TARGET_NUM_PEERS_PDEV (512 + TARGET_NUM_VDEVS)
|
||||
#define TARGET_NUM_PEERS_PDEV(ab) (ab->hw_params.num_peers + TARGET_NUM_VDEVS(ab))
|
||||
|
||||
/* Num of peers for Single Radio mode */
|
||||
#define TARGET_NUM_PEERS_SINGLE (TARGET_NUM_PEERS_PDEV)
|
||||
#define TARGET_NUM_PEERS_SINGLE(ab) (TARGET_NUM_PEERS_PDEV(ab))
|
||||
|
||||
/* Num of peers for DBS */
|
||||
#define TARGET_NUM_PEERS_DBS (2 * TARGET_NUM_PEERS_PDEV)
|
||||
#define TARGET_NUM_PEERS_DBS(ab) (2 * TARGET_NUM_PEERS_PDEV(ab))
|
||||
|
||||
/* Num of peers for DBS_SBS */
|
||||
#define TARGET_NUM_PEERS_DBS_SBS (3 * TARGET_NUM_PEERS_PDEV)
|
||||
#define TARGET_NUM_PEERS_DBS_SBS(ab) (3 * TARGET_NUM_PEERS_PDEV(ab))
|
||||
|
||||
/* Max num of stations (per radio) */
|
||||
#define TARGET_NUM_STATIONS 512
|
||||
#define TARGET_NUM_STATIONS(ab) (ab->hw_params.num_peers)
|
||||
|
||||
#define TARGET_NUM_PEERS(x) TARGET_NUM_PEERS_##x
|
||||
#define TARGET_NUM_PEERS(ab, x) TARGET_NUM_PEERS_##x(ab)
|
||||
#define TARGET_NUM_PEER_KEYS 2
|
||||
#define TARGET_NUM_TIDS(x) (2 * TARGET_NUM_PEERS(x) + \
|
||||
4 * TARGET_NUM_VDEVS + 8)
|
||||
#define TARGET_NUM_TIDS(ab, x) (2 * TARGET_NUM_PEERS(ab, x) + \
|
||||
4 * TARGET_NUM_VDEVS(ab) + 8)
|
||||
|
||||
#define TARGET_AST_SKID_LIMIT 16
|
||||
#define TARGET_NUM_OFFLD_PEERS 4
|
||||
@ -168,10 +168,14 @@ struct ath11k_hw_params {
|
||||
|
||||
u16 interface_modes;
|
||||
bool supports_monitor;
|
||||
bool full_monitor_mode;
|
||||
bool supports_shadow_regs;
|
||||
bool idle_ps;
|
||||
bool supports_sta_ps;
|
||||
bool cold_boot_calib;
|
||||
int fw_mem_mode;
|
||||
u32 num_vdevs;
|
||||
u32 num_peers;
|
||||
bool supports_suspend;
|
||||
u32 hal_desc_sz;
|
||||
bool fix_l1ss;
|
||||
|
@ -1,6 +1,7 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <net/mac80211.h>
|
||||
@ -553,6 +554,67 @@ struct ath11k *ath11k_mac_get_ar_by_pdev_id(struct ath11k_base *ab, u32 pdev_id)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct ath11k_vif *ath11k_mac_get_vif_up(struct ath11k_base *ab)
|
||||
{
|
||||
struct ath11k *ar;
|
||||
struct ath11k_pdev *pdev;
|
||||
struct ath11k_vif *arvif;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ab->num_radios; i++) {
|
||||
pdev = &ab->pdevs[i];
|
||||
ar = pdev->ar;
|
||||
list_for_each_entry(arvif, &ar->arvifs, list) {
|
||||
if (arvif->is_up)
|
||||
return arvif;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool ath11k_mac_band_match(enum nl80211_band band1, enum WMI_HOST_WLAN_BAND band2)
|
||||
{
|
||||
return (((band1 == NL80211_BAND_2GHZ) && (band2 & WMI_HOST_WLAN_2G_CAP)) ||
|
||||
(((band1 == NL80211_BAND_5GHZ) || (band1 == NL80211_BAND_6GHZ)) &&
|
||||
(band2 & WMI_HOST_WLAN_5G_CAP)));
|
||||
}
|
||||
|
||||
u8 ath11k_mac_get_target_pdev_id_from_vif(struct ath11k_vif *arvif)
|
||||
{
|
||||
struct ath11k *ar = arvif->ar;
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
struct ieee80211_vif *vif = arvif->vif;
|
||||
struct cfg80211_chan_def def;
|
||||
enum nl80211_band band;
|
||||
u8 pdev_id = ab->target_pdev_ids[0].pdev_id;
|
||||
int i;
|
||||
|
||||
if (WARN_ON(ath11k_mac_vif_chan(vif, &def)))
|
||||
return pdev_id;
|
||||
|
||||
band = def.chan->band;
|
||||
|
||||
for (i = 0; i < ab->target_pdev_count; i++) {
|
||||
if (ath11k_mac_band_match(band, ab->target_pdev_ids[i].supported_bands))
|
||||
return ab->target_pdev_ids[i].pdev_id;
|
||||
}
|
||||
|
||||
return pdev_id;
|
||||
}
|
||||
|
||||
u8 ath11k_mac_get_target_pdev_id(struct ath11k *ar)
|
||||
{
|
||||
struct ath11k_vif *arvif;
|
||||
|
||||
arvif = ath11k_mac_get_vif_up(ar->ab);
|
||||
|
||||
if (arvif)
|
||||
return ath11k_mac_get_target_pdev_id_from_vif(arvif);
|
||||
else
|
||||
return ar->ab->target_pdev_ids[0].pdev_id;
|
||||
}
|
||||
|
||||
static void ath11k_pdev_caps_update(struct ath11k *ar)
|
||||
{
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
@ -1920,7 +1982,6 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar,
|
||||
struct ath11k_vif *arvif = (void *)vif->drv_priv;
|
||||
struct cfg80211_chan_def def;
|
||||
const struct ieee80211_sta_he_cap *he_cap = &sta->he_cap;
|
||||
u8 ampdu_factor;
|
||||
enum nl80211_band band;
|
||||
u16 *he_mcs_mask;
|
||||
u8 max_nss, he_mcs;
|
||||
@ -1928,6 +1989,9 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar,
|
||||
int i, he_nss, nss_idx;
|
||||
bool user_rate_valid = true;
|
||||
u32 rx_nss, tx_nss, nss_160;
|
||||
u8 ampdu_factor, rx_mcs_80, rx_mcs_160;
|
||||
u16 mcs_160_map, mcs_80_map;
|
||||
bool support_160;
|
||||
|
||||
if (WARN_ON(ath11k_mac_vif_chan(vif, &def)))
|
||||
return;
|
||||
@ -1942,6 +2006,39 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar,
|
||||
return;
|
||||
|
||||
arg->he_flag = true;
|
||||
support_160 = !!(he_cap->he_cap_elem.phy_cap_info[0] &
|
||||
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G);
|
||||
|
||||
/* Supported HE-MCS and NSS Set of peer he_cap is intersection with self he_cp */
|
||||
mcs_160_map = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160);
|
||||
mcs_80_map = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80);
|
||||
|
||||
if (support_160) {
|
||||
for (i = 7; i >= 0; i--) {
|
||||
u8 mcs_160 = (mcs_160_map >> (2 * i)) & 3;
|
||||
|
||||
if (mcs_160 != IEEE80211_VHT_MCS_NOT_SUPPORTED) {
|
||||
rx_mcs_160 = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 7; i >= 0; i--) {
|
||||
u8 mcs_80 = (mcs_80_map >> (2 * i)) & 3;
|
||||
|
||||
if (mcs_80 != IEEE80211_VHT_MCS_NOT_SUPPORTED) {
|
||||
rx_mcs_80 = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (support_160)
|
||||
max_nss = min(rx_mcs_80, rx_mcs_160);
|
||||
else
|
||||
max_nss = rx_mcs_80;
|
||||
|
||||
arg->peer_nss = min(sta->rx_nss, max_nss);
|
||||
|
||||
memcpy_and_pad(&arg->peer_he_cap_macinfo,
|
||||
sizeof(arg->peer_he_cap_macinfo),
|
||||
@ -2584,6 +2681,15 @@ static void ath11k_bss_assoc(struct ieee80211_hw *hw,
|
||||
if (ret)
|
||||
ath11k_warn(ar->ab, "failed to set vdev %i OBSS PD parameters: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
|
||||
ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
|
||||
WMI_VDEV_PARAM_DTIM_POLICY,
|
||||
WMI_DTIM_POLICY_STICK);
|
||||
if (ret)
|
||||
ath11k_warn(ar->ab, "failed to set vdev %d dtim policy: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
|
||||
ath11k_mac_11d_scan_stop_all(ar->ab);
|
||||
}
|
||||
|
||||
static void ath11k_bss_disassoc(struct ieee80211_hw *hw,
|
||||
@ -3313,6 +3419,7 @@ static int ath11k_start_scan(struct ath11k *ar,
|
||||
struct scan_req_params *arg)
|
||||
{
|
||||
int ret;
|
||||
unsigned long timeout = 1 * HZ;
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
@ -3323,7 +3430,14 @@ static int ath11k_start_scan(struct ath11k *ar,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = wait_for_completion_timeout(&ar->scan.started, 1 * HZ);
|
||||
if (test_bit(WMI_TLV_SERVICE_11D_OFFLOAD, ar->ab->wmi_ab.svc_map)) {
|
||||
timeout = 5 * HZ;
|
||||
|
||||
if (ar->supports_6ghz)
|
||||
timeout += 5 * HZ;
|
||||
}
|
||||
|
||||
ret = wait_for_completion_timeout(&ar->scan.started, timeout);
|
||||
if (ret == 0) {
|
||||
ret = ath11k_scan_stop(ar);
|
||||
if (ret)
|
||||
@ -3380,15 +3494,38 @@ static int ath11k_mac_op_hw_scan(struct ieee80211_hw *hw,
|
||||
if (ret)
|
||||
goto exit;
|
||||
|
||||
/* Currently the pending_11d=true only happened 1 time while
|
||||
* wlan interface up in ath11k_mac_11d_scan_start(), it is called by
|
||||
* ath11k_mac_op_add_interface(), after wlan interface up,
|
||||
* pending_11d=false always.
|
||||
* If remove below wait, it always happened scan fail and lead connect
|
||||
* fail while wlan interface up, because it has a 11d scan which is running
|
||||
* in firmware, and lead this scan failed.
|
||||
*/
|
||||
if (ar->pending_11d) {
|
||||
long time_left;
|
||||
unsigned long timeout = 5 * HZ;
|
||||
|
||||
if (ar->supports_6ghz)
|
||||
timeout += 5 * HZ;
|
||||
|
||||
time_left = wait_for_completion_timeout(&ar->finish_11d_ch_list, timeout);
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
|
||||
"mac wait 11d channel list time left %ld\n", time_left);
|
||||
}
|
||||
|
||||
memset(&arg, 0, sizeof(arg));
|
||||
ath11k_wmi_start_scan_init(ar, &arg);
|
||||
arg.vdev_id = arvif->vdev_id;
|
||||
arg.scan_id = ATH11K_SCAN_ID;
|
||||
|
||||
if (req->ie_len) {
|
||||
arg.extraie.ptr = kmemdup(req->ie, req->ie_len, GFP_KERNEL);
|
||||
if (!arg.extraie.ptr) {
|
||||
ret = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
arg.extraie.len = req->ie_len;
|
||||
arg.extraie.ptr = kzalloc(req->ie_len, GFP_KERNEL);
|
||||
memcpy(arg.extraie.ptr, req->ie, req->ie_len);
|
||||
}
|
||||
|
||||
if (req->n_ssids) {
|
||||
@ -3404,10 +3541,24 @@ static int ath11k_mac_op_hw_scan(struct ieee80211_hw *hw,
|
||||
|
||||
if (req->n_channels) {
|
||||
arg.num_chan = req->n_channels;
|
||||
arg.chan_list = kcalloc(arg.num_chan, sizeof(*arg.chan_list),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!arg.chan_list) {
|
||||
ret = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
for (i = 0; i < arg.num_chan; i++)
|
||||
arg.chan_list[i] = req->channels[i]->center_freq;
|
||||
}
|
||||
|
||||
if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
|
||||
arg.scan_f_add_spoofed_mac_in_probe = 1;
|
||||
ether_addr_copy(arg.mac_addr.addr, req->mac_addr);
|
||||
ether_addr_copy(arg.mac_mask.addr, req->mac_addr_mask);
|
||||
}
|
||||
|
||||
ret = ath11k_start_scan(ar, &arg);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to start hw scan: %d\n", ret);
|
||||
@ -3422,6 +3573,8 @@ static int ath11k_mac_op_hw_scan(struct ieee80211_hw *hw,
|
||||
ATH11K_MAC_SCAN_TIMEOUT_MSECS));
|
||||
|
||||
exit:
|
||||
kfree(arg.chan_list);
|
||||
|
||||
if (req->ie_len)
|
||||
kfree(arg.extraie.ptr);
|
||||
|
||||
@ -3597,7 +3750,7 @@ static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
/* flush the fragments cache during key (re)install to
|
||||
* ensure all frags in the new frag list belong to the same key.
|
||||
*/
|
||||
if (peer && cmd == SET_KEY)
|
||||
if (peer && sta && cmd == SET_KEY)
|
||||
ath11k_peer_frags_flush(ar, peer);
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
|
||||
@ -5128,23 +5281,47 @@ static int __ath11k_set_antenna(struct ath11k *ar, u32 tx_ant, u32 rx_ant)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath11k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx)
|
||||
static void ath11k_mgmt_over_wmi_tx_drop(struct ath11k *ar, struct sk_buff *skb)
|
||||
{
|
||||
struct sk_buff *msdu = skb;
|
||||
int num_mgmt;
|
||||
|
||||
ieee80211_free_txskb(ar->hw, skb);
|
||||
|
||||
num_mgmt = atomic_dec_if_positive(&ar->num_pending_mgmt_tx);
|
||||
|
||||
if (num_mgmt < 0)
|
||||
WARN_ON_ONCE(1);
|
||||
|
||||
if (!num_mgmt)
|
||||
wake_up(&ar->txmgmt_empty_waitq);
|
||||
}
|
||||
|
||||
static void ath11k_mac_tx_mgmt_free(struct ath11k *ar, int buf_id)
|
||||
{
|
||||
struct sk_buff *msdu;
|
||||
struct ieee80211_tx_info *info;
|
||||
struct ath11k *ar = ctx;
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
|
||||
spin_lock_bh(&ar->txmgmt_idr_lock);
|
||||
idr_remove(&ar->txmgmt_idr, buf_id);
|
||||
msdu = idr_remove(&ar->txmgmt_idr, buf_id);
|
||||
spin_unlock_bh(&ar->txmgmt_idr_lock);
|
||||
dma_unmap_single(ab->dev, ATH11K_SKB_CB(msdu)->paddr, msdu->len,
|
||||
|
||||
if (!msdu)
|
||||
return;
|
||||
|
||||
dma_unmap_single(ar->ab->dev, ATH11K_SKB_CB(msdu)->paddr, msdu->len,
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
info = IEEE80211_SKB_CB(msdu);
|
||||
memset(&info->status, 0, sizeof(info->status));
|
||||
|
||||
ieee80211_free_txskb(ar->hw, msdu);
|
||||
ath11k_mgmt_over_wmi_tx_drop(ar, msdu);
|
||||
}
|
||||
|
||||
int ath11k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx)
|
||||
{
|
||||
struct ath11k *ar = ctx;
|
||||
|
||||
ath11k_mac_tx_mgmt_free(ar, buf_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -5153,17 +5330,10 @@ static int ath11k_mac_vif_txmgmt_idr_remove(int buf_id, void *skb, void *ctx)
|
||||
{
|
||||
struct ieee80211_vif *vif = ctx;
|
||||
struct ath11k_skb_cb *skb_cb = ATH11K_SKB_CB((struct sk_buff *)skb);
|
||||
struct sk_buff *msdu = skb;
|
||||
struct ath11k *ar = skb_cb->ar;
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
|
||||
if (skb_cb->vif == vif) {
|
||||
spin_lock_bh(&ar->txmgmt_idr_lock);
|
||||
idr_remove(&ar->txmgmt_idr, buf_id);
|
||||
spin_unlock_bh(&ar->txmgmt_idr_lock);
|
||||
dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len,
|
||||
DMA_TO_DEVICE);
|
||||
}
|
||||
if (skb_cb->vif == vif)
|
||||
ath11k_mac_tx_mgmt_free(ar, buf_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -5178,10 +5348,16 @@ static int ath11k_mac_mgmt_tx_wmi(struct ath11k *ar, struct ath11k_vif *arvif,
|
||||
int buf_id;
|
||||
int ret;
|
||||
|
||||
ATH11K_SKB_CB(skb)->ar = ar;
|
||||
|
||||
spin_lock_bh(&ar->txmgmt_idr_lock);
|
||||
buf_id = idr_alloc(&ar->txmgmt_idr, skb, 0,
|
||||
ATH11K_TX_MGMT_NUM_PENDING_MAX, GFP_ATOMIC);
|
||||
spin_unlock_bh(&ar->txmgmt_idr_lock);
|
||||
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
|
||||
"mac tx mgmt frame, buf id %d\n", buf_id);
|
||||
|
||||
if (buf_id < 0)
|
||||
return -ENOSPC;
|
||||
|
||||
@ -5228,7 +5404,7 @@ static void ath11k_mgmt_over_wmi_tx_purge(struct ath11k *ar)
|
||||
struct sk_buff *skb;
|
||||
|
||||
while ((skb = skb_dequeue(&ar->wmi_mgmt_tx_queue)) != NULL)
|
||||
ieee80211_free_txskb(ar->hw, skb);
|
||||
ath11k_mgmt_over_wmi_tx_drop(ar, skb);
|
||||
}
|
||||
|
||||
static void ath11k_mgmt_over_wmi_tx_work(struct work_struct *work)
|
||||
@ -5243,29 +5419,29 @@ static void ath11k_mgmt_over_wmi_tx_work(struct work_struct *work)
|
||||
skb_cb = ATH11K_SKB_CB(skb);
|
||||
if (!skb_cb->vif) {
|
||||
ath11k_warn(ar->ab, "no vif found for mgmt frame\n");
|
||||
ieee80211_free_txskb(ar->hw, skb);
|
||||
ath11k_mgmt_over_wmi_tx_drop(ar, skb);
|
||||
continue;
|
||||
}
|
||||
|
||||
arvif = ath11k_vif_to_arvif(skb_cb->vif);
|
||||
if (ar->allocated_vdev_map & (1LL << arvif->vdev_id) &&
|
||||
arvif->is_started) {
|
||||
atomic_inc(&ar->num_pending_mgmt_tx);
|
||||
ret = ath11k_mac_mgmt_tx_wmi(ar, arvif, skb);
|
||||
if (ret) {
|
||||
if (atomic_dec_if_positive(&ar->num_pending_mgmt_tx) < 0)
|
||||
WARN_ON_ONCE(1);
|
||||
|
||||
ath11k_warn(ar->ab, "failed to tx mgmt frame, vdev_id %d :%d\n",
|
||||
arvif->vdev_id, ret);
|
||||
ieee80211_free_txskb(ar->hw, skb);
|
||||
ath11k_mgmt_over_wmi_tx_drop(ar, skb);
|
||||
} else {
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
|
||||
"mac tx mgmt frame, vdev_id %d\n",
|
||||
arvif->vdev_id);
|
||||
}
|
||||
} else {
|
||||
ath11k_warn(ar->ab,
|
||||
"dropping mgmt frame for vdev %d, is_started %d\n",
|
||||
arvif->vdev_id,
|
||||
arvif->is_started);
|
||||
ieee80211_free_txskb(ar->hw, skb);
|
||||
ath11k_mgmt_over_wmi_tx_drop(ar, skb);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5296,6 +5472,7 @@ static int ath11k_mac_mgmt_tx(struct ath11k *ar, struct sk_buff *skb,
|
||||
}
|
||||
|
||||
skb_queue_tail(q, skb);
|
||||
atomic_inc(&ar->num_pending_mgmt_tx);
|
||||
ieee80211_queue_work(ar->hw, &ar->wmi_mgmt_tx_work);
|
||||
|
||||
return 0;
|
||||
@ -5426,6 +5603,14 @@ static int ath11k_mac_op_start(struct ieee80211_hw *hw)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (test_bit(WMI_TLV_SERVICE_SPOOF_MAC_SUPPORT, ar->wmi->wmi_ab->svc_map)) {
|
||||
ret = ath11k_wmi_scan_prob_req_oui(ar, ar->mac_addr);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to set prob req oui: %i\n", ret);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
ret = ath11k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_ARP_AC_OVERRIDE,
|
||||
0, pdev->pdev_id);
|
||||
if (ret) {
|
||||
@ -5524,6 +5709,7 @@ static void ath11k_mac_op_stop(struct ieee80211_hw *hw)
|
||||
|
||||
cancel_delayed_work_sync(&ar->scan.timeout);
|
||||
cancel_work_sync(&ar->regd_update_work);
|
||||
cancel_work_sync(&ar->ab->update_11d_work);
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
list_for_each_entry_safe(ppdu_stats, tmp, &ar->ppdu_stats_info, list) {
|
||||
@ -5677,6 +5863,122 @@ static void ath11k_mac_op_update_vif_offload(struct ieee80211_hw *hw,
|
||||
}
|
||||
}
|
||||
|
||||
static bool ath11k_mac_vif_ap_active_any(struct ath11k_base *ab)
|
||||
{
|
||||
struct ath11k *ar;
|
||||
struct ath11k_pdev *pdev;
|
||||
struct ath11k_vif *arvif;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ab->num_radios; i++) {
|
||||
pdev = &ab->pdevs[i];
|
||||
ar = pdev->ar;
|
||||
list_for_each_entry(arvif, &ar->arvifs, list) {
|
||||
if (arvif->is_up && arvif->vdev_type == WMI_VDEV_TYPE_AP)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ath11k_mac_11d_scan_start(struct ath11k *ar, u32 vdev_id, bool wait)
|
||||
{
|
||||
struct wmi_11d_scan_start_params param;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&ar->ab->vdev_id_11d_lock);
|
||||
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac vdev id for 11d scan %d\n",
|
||||
ar->vdev_id_11d_scan);
|
||||
|
||||
if (ar->regdom_set_by_user)
|
||||
goto fin;
|
||||
|
||||
if (ar->vdev_id_11d_scan != ATH11K_11D_INVALID_VDEV_ID)
|
||||
goto fin;
|
||||
|
||||
if (!test_bit(WMI_TLV_SERVICE_11D_OFFLOAD, ar->ab->wmi_ab.svc_map))
|
||||
goto fin;
|
||||
|
||||
if (ath11k_mac_vif_ap_active_any(ar->ab))
|
||||
goto fin;
|
||||
|
||||
param.vdev_id = vdev_id;
|
||||
param.start_interval_msec = 0;
|
||||
param.scan_period_msec = ATH11K_SCAN_11D_INTERVAL;
|
||||
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac start 11d scan\n");
|
||||
|
||||
if (wait)
|
||||
reinit_completion(&ar->finish_11d_scan);
|
||||
|
||||
ret = ath11k_wmi_send_11d_scan_start_cmd(ar, ¶m);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to start 11d scan vdev %d ret: %d\n",
|
||||
vdev_id, ret);
|
||||
} else {
|
||||
ar->vdev_id_11d_scan = vdev_id;
|
||||
if (wait) {
|
||||
ar->pending_11d = true;
|
||||
ret = wait_for_completion_timeout(&ar->finish_11d_scan,
|
||||
5 * HZ);
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
|
||||
"mac 11d scan left time %d\n", ret);
|
||||
|
||||
if (!ret)
|
||||
ar->pending_11d = false;
|
||||
}
|
||||
}
|
||||
|
||||
fin:
|
||||
mutex_unlock(&ar->ab->vdev_id_11d_lock);
|
||||
}
|
||||
|
||||
void ath11k_mac_11d_scan_stop(struct ath11k *ar)
|
||||
{
|
||||
int ret;
|
||||
u32 vdev_id;
|
||||
|
||||
if (!test_bit(WMI_TLV_SERVICE_11D_OFFLOAD, ar->ab->wmi_ab.svc_map))
|
||||
return;
|
||||
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac stop 11d scan\n");
|
||||
|
||||
mutex_lock(&ar->ab->vdev_id_11d_lock);
|
||||
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac stop 11d vdev id %d\n",
|
||||
ar->vdev_id_11d_scan);
|
||||
|
||||
if (ar->vdev_id_11d_scan != ATH11K_11D_INVALID_VDEV_ID) {
|
||||
vdev_id = ar->vdev_id_11d_scan;
|
||||
|
||||
ret = ath11k_wmi_send_11d_scan_stop_cmd(ar, vdev_id);
|
||||
if (ret)
|
||||
ath11k_warn(ar->ab,
|
||||
"failed to stopt 11d scan vdev %d ret: %d\n",
|
||||
vdev_id, ret);
|
||||
else
|
||||
ar->vdev_id_11d_scan = ATH11K_11D_INVALID_VDEV_ID;
|
||||
}
|
||||
mutex_unlock(&ar->ab->vdev_id_11d_lock);
|
||||
}
|
||||
|
||||
void ath11k_mac_11d_scan_stop_all(struct ath11k_base *ab)
|
||||
{
|
||||
struct ath11k *ar;
|
||||
struct ath11k_pdev *pdev;
|
||||
int i;
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_MAC, "mac stop soc 11d scan\n");
|
||||
|
||||
for (i = 0; i < ab->num_radios; i++) {
|
||||
pdev = &ab->pdevs[i];
|
||||
ar = pdev->ar;
|
||||
|
||||
ath11k_mac_11d_scan_stop(ar);
|
||||
}
|
||||
}
|
||||
|
||||
static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
@ -5702,9 +6004,9 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (ar->num_created_vdevs > (TARGET_NUM_VDEVS - 1)) {
|
||||
if (ar->num_created_vdevs > (TARGET_NUM_VDEVS(ab) - 1)) {
|
||||
ath11k_warn(ab, "failed to create vdev %u, reached max vdev limit %d\n",
|
||||
ar->num_created_vdevs, TARGET_NUM_VDEVS);
|
||||
ar->num_created_vdevs, TARGET_NUM_VDEVS(ab));
|
||||
ret = -EBUSY;
|
||||
goto err;
|
||||
}
|
||||
@ -5810,6 +6112,8 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
|
||||
arvif->vdev_id, ret);
|
||||
goto err_peer_del;
|
||||
}
|
||||
|
||||
ath11k_mac_11d_scan_stop_all(ar->ab);
|
||||
break;
|
||||
case WMI_VDEV_TYPE_STA:
|
||||
param_id = WMI_STA_PS_PARAM_RX_WAKE_POLICY;
|
||||
@ -5849,6 +6153,9 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
|
||||
arvif->vdev_id, ret);
|
||||
goto err_peer_del;
|
||||
}
|
||||
|
||||
ath11k_mac_11d_scan_start(ar, arvif->vdev_id, true);
|
||||
|
||||
break;
|
||||
case WMI_VDEV_TYPE_MONITOR:
|
||||
set_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags);
|
||||
@ -5950,6 +6257,9 @@ static void ath11k_mac_op_remove_interface(struct ieee80211_hw *hw,
|
||||
ath11k_dbg(ab, ATH11K_DBG_MAC, "mac remove interface (vdev %d)\n",
|
||||
arvif->vdev_id);
|
||||
|
||||
if (arvif->vdev_type == WMI_VDEV_TYPE_STA)
|
||||
ath11k_mac_11d_scan_stop(ar);
|
||||
|
||||
if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
|
||||
ret = ath11k_peer_delete(ar, arvif->vdev_id, vif->addr);
|
||||
if (ret)
|
||||
@ -6363,37 +6673,7 @@ ath11k_mac_update_vif_chan(struct ath11k *ar,
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
for (i = 0; i < n_vifs; i++) {
|
||||
arvif = (void *)vifs[i].vif->drv_priv;
|
||||
|
||||
if (vifs[i].vif->type == NL80211_IFTYPE_MONITOR)
|
||||
monitor_vif = true;
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_MAC,
|
||||
"mac chanctx switch vdev_id %i freq %u->%u width %d->%d\n",
|
||||
arvif->vdev_id,
|
||||
vifs[i].old_ctx->def.chan->center_freq,
|
||||
vifs[i].new_ctx->def.chan->center_freq,
|
||||
vifs[i].old_ctx->def.width,
|
||||
vifs[i].new_ctx->def.width);
|
||||
|
||||
if (WARN_ON(!arvif->is_started))
|
||||
continue;
|
||||
|
||||
if (WARN_ON(!arvif->is_up))
|
||||
continue;
|
||||
|
||||
ret = ath11k_wmi_vdev_down(ar, arvif->vdev_id);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to down vdev %d: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
continue;
|
||||
}
|
||||
|
||||
ar->num_started_vdevs--;
|
||||
}
|
||||
|
||||
/* All relevant vdevs are downed and associated channel resources
|
||||
/* Associated channel resources of all relevant vdevs
|
||||
* should be available for the channel switch now.
|
||||
*/
|
||||
|
||||
@ -6698,6 +6978,9 @@ ath11k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw,
|
||||
ret);
|
||||
}
|
||||
|
||||
if (arvif->vdev_type == WMI_VDEV_TYPE_STA)
|
||||
ath11k_mac_11d_scan_start(ar, arvif->vdev_id, false);
|
||||
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
}
|
||||
|
||||
@ -6784,6 +7067,17 @@ static void ath11k_mac_op_flush(struct ieee80211_hw *hw, struct ieee80211_vif *v
|
||||
ATH11K_FLUSH_TIMEOUT);
|
||||
if (time_left == 0)
|
||||
ath11k_warn(ar->ab, "failed to flush transmit queue %ld\n", time_left);
|
||||
|
||||
time_left = wait_event_timeout(ar->txmgmt_empty_waitq,
|
||||
(atomic_read(&ar->num_pending_mgmt_tx) == 0),
|
||||
ATH11K_FLUSH_TIMEOUT);
|
||||
if (time_left == 0)
|
||||
ath11k_warn(ar->ab, "failed to flush mgmt transmit queue %ld\n",
|
||||
time_left);
|
||||
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
|
||||
"mac mgmt tx flush mgmt pending %d\n",
|
||||
atomic_read(&ar->num_pending_mgmt_tx));
|
||||
}
|
||||
|
||||
static int
|
||||
@ -7849,6 +8143,9 @@ static int __ath11k_mac_register(struct ath11k *ar)
|
||||
|
||||
ar->hw->wiphy->interface_modes = ab->hw_params.interface_modes;
|
||||
|
||||
if (ab->hw_params.single_pdev_only && ar->supports_6ghz)
|
||||
ieee80211_hw_set(ar->hw, SINGLE_SCAN_ON_ALL_BANDS);
|
||||
|
||||
ieee80211_hw_set(ar->hw, SIGNAL_DBM);
|
||||
ieee80211_hw_set(ar->hw, SUPPORTS_PS);
|
||||
ieee80211_hw_set(ar->hw, SUPPORTS_DYNAMIC_PS);
|
||||
@ -7905,11 +8202,16 @@ static int __ath11k_mac_register(struct ath11k *ar)
|
||||
ar->hw->wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE |
|
||||
NL80211_FEATURE_AP_SCAN;
|
||||
|
||||
ar->max_num_stations = TARGET_NUM_STATIONS;
|
||||
ar->max_num_peers = TARGET_NUM_PEERS_PDEV;
|
||||
ar->max_num_stations = TARGET_NUM_STATIONS(ab);
|
||||
ar->max_num_peers = TARGET_NUM_PEERS_PDEV(ab);
|
||||
|
||||
ar->hw->wiphy->max_ap_assoc_sta = ar->max_num_stations;
|
||||
|
||||
if (test_bit(WMI_TLV_SERVICE_SPOOF_MAC_SUPPORT, ar->wmi->wmi_ab->svc_map)) {
|
||||
ar->hw->wiphy->features |=
|
||||
NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
|
||||
}
|
||||
|
||||
ar->hw->queues = ATH11K_HW_MAX_QUEUES;
|
||||
ar->hw->wiphy->tx_queue_len = ATH11K_QUEUE_LEN;
|
||||
ar->hw->offchannel_tx_hw_queue = ATH11K_HW_MAX_QUEUES - 1;
|
||||
@ -8004,7 +8306,7 @@ int ath11k_mac_register(struct ath11k_base *ab)
|
||||
|
||||
/* Initialize channel counters frequency value in hertz */
|
||||
ab->cc_freq_hz = IPQ8074_CC_FREQ_HERTZ;
|
||||
ab->free_vdev_map = (1LL << (ab->num_radios * TARGET_NUM_VDEVS)) - 1;
|
||||
ab->free_vdev_map = (1LL << (ab->num_radios * TARGET_NUM_VDEVS(ab))) - 1;
|
||||
|
||||
for (i = 0; i < ab->num_radios; i++) {
|
||||
pdev = &ab->pdevs[i];
|
||||
@ -8022,6 +8324,8 @@ int ath11k_mac_register(struct ath11k_base *ab)
|
||||
ret = __ath11k_mac_register(ar);
|
||||
if (ret)
|
||||
goto err_cleanup;
|
||||
|
||||
init_waitqueue_head(&ar->txmgmt_empty_waitq);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -8099,6 +8403,9 @@ int ath11k_mac_allocate(struct ath11k_base *ab)
|
||||
|
||||
ar->monitor_vdev_id = -1;
|
||||
clear_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags);
|
||||
ar->vdev_id_11d_scan = ATH11K_11D_INVALID_VDEV_ID;
|
||||
init_completion(&ar->finish_11d_scan);
|
||||
init_completion(&ar->finish_11d_ch_list);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -127,6 +127,13 @@ struct ath11k_generic_iter {
|
||||
|
||||
extern const struct htt_rx_ring_tlv_filter ath11k_mac_mon_status_filter_default;
|
||||
|
||||
#define ATH11K_SCAN_11D_INTERVAL 600000
|
||||
#define ATH11K_11D_INVALID_VDEV_ID 0xFFFF
|
||||
|
||||
void ath11k_mac_11d_scan_start(struct ath11k *ar, u32 vdev_id, bool wait);
|
||||
void ath11k_mac_11d_scan_stop(struct ath11k *ar);
|
||||
void ath11k_mac_11d_scan_stop_all(struct ath11k_base *ab);
|
||||
|
||||
void ath11k_mac_destroy(struct ath11k_base *ab);
|
||||
void ath11k_mac_unregister(struct ath11k_base *ab);
|
||||
int ath11k_mac_register(struct ath11k_base *ab);
|
||||
@ -144,6 +151,10 @@ void ath11k_mac_scan_finish(struct ath11k *ar);
|
||||
struct ath11k_vif *ath11k_mac_get_arvif(struct ath11k *ar, u32 vdev_id);
|
||||
struct ath11k_vif *ath11k_mac_get_arvif_by_vdev_id(struct ath11k_base *ab,
|
||||
u32 vdev_id);
|
||||
u8 ath11k_mac_get_target_pdev_id(struct ath11k *ar);
|
||||
u8 ath11k_mac_get_target_pdev_id_from_vif(struct ath11k_vif *arvif);
|
||||
struct ath11k_vif *ath11k_mac_get_vif_up(struct ath11k_base *ab);
|
||||
|
||||
struct ath11k *ath11k_mac_get_ar_by_vdev_id(struct ath11k_base *ab, u32 vdev_id);
|
||||
struct ath11k *ath11k_mac_get_ar_by_pdev_id(struct ath11k_base *ab, u32 pdev_id);
|
||||
|
||||
|
@ -3,6 +3,9 @@
|
||||
|
||||
#include <linux/msi.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/ioport.h>
|
||||
|
||||
#include "core.h"
|
||||
#include "debug.h"
|
||||
@ -248,6 +251,7 @@ static int ath11k_mhi_get_msi(struct ath11k_pci *ab_pci)
|
||||
u32 user_base_data, base_vector;
|
||||
int ret, num_vectors, i;
|
||||
int *irq;
|
||||
unsigned int msi_data;
|
||||
|
||||
ret = ath11k_pci_get_user_msi_assignment(ab_pci,
|
||||
"MHI", &num_vectors,
|
||||
@ -262,9 +266,15 @@ static int ath11k_mhi_get_msi(struct ath11k_pci *ab_pci)
|
||||
if (!irq)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < num_vectors; i++)
|
||||
for (i = 0; i < num_vectors; i++) {
|
||||
msi_data = base_vector;
|
||||
|
||||
if (test_bit(ATH11K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags))
|
||||
msi_data += i;
|
||||
|
||||
irq[i] = ath11k_pci_get_msi_irq(ab->dev,
|
||||
base_vector + i);
|
||||
msi_data);
|
||||
}
|
||||
|
||||
ab_pci->mhi_ctrl->irq = irq;
|
||||
ab_pci->mhi_ctrl->nr_irqs = num_vectors;
|
||||
@ -311,6 +321,26 @@ static void ath11k_mhi_op_write_reg(struct mhi_controller *mhi_cntrl,
|
||||
writel(val, addr);
|
||||
}
|
||||
|
||||
static int ath11k_mhi_read_addr_from_dt(struct mhi_controller *mhi_ctrl)
|
||||
{
|
||||
struct device_node *np;
|
||||
struct resource res;
|
||||
int ret;
|
||||
|
||||
np = of_find_node_by_type(NULL, "memory");
|
||||
if (!np)
|
||||
return -ENOENT;
|
||||
|
||||
ret = of_address_to_resource(np, 0, &res);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mhi_ctrl->iova_start = res.start + 0x1000000;
|
||||
mhi_ctrl->iova_stop = res.end;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath11k_mhi_register(struct ath11k_pci *ab_pci)
|
||||
{
|
||||
struct ath11k_base *ab = ab_pci->ab;
|
||||
@ -339,8 +369,18 @@ int ath11k_mhi_register(struct ath11k_pci *ab_pci)
|
||||
return ret;
|
||||
}
|
||||
|
||||
mhi_ctrl->iova_start = 0;
|
||||
mhi_ctrl->iova_stop = 0xffffffff;
|
||||
if (!test_bit(ATH11K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags))
|
||||
mhi_ctrl->irq_flags = IRQF_SHARED | IRQF_NOBALANCING;
|
||||
|
||||
if (test_bit(ATH11K_FLAG_FIXED_MEM_RGN, &ab->dev_flags)) {
|
||||
ret = ath11k_mhi_read_addr_from_dt(mhi_ctrl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} else {
|
||||
mhi_ctrl->iova_start = 0;
|
||||
mhi_ctrl->iova_stop = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
mhi_ctrl->sbl_size = SZ_512K;
|
||||
mhi_ctrl->seg_len = SZ_512K;
|
||||
mhi_ctrl->fbc_download = true;
|
||||
@ -356,6 +396,7 @@ int ath11k_mhi_register(struct ath11k_pci *ab_pci)
|
||||
break;
|
||||
case ATH11K_HW_QCA6390_HW20:
|
||||
case ATH11K_HW_WCN6855_HW20:
|
||||
case ATH11K_HW_WCN6855_HW21:
|
||||
ath11k_mhi_config = &ath11k_mhi_config_qca6390;
|
||||
break;
|
||||
default:
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/msi.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include "pci.h"
|
||||
#include "core.h"
|
||||
@ -16,7 +17,8 @@
|
||||
#define ATH11K_PCI_BAR_NUM 0
|
||||
#define ATH11K_PCI_DMA_MASK 32
|
||||
|
||||
#define ATH11K_PCI_IRQ_CE0_OFFSET 3
|
||||
#define ATH11K_PCI_IRQ_CE0_OFFSET 3
|
||||
#define ATH11K_PCI_IRQ_DP_OFFSET 14
|
||||
|
||||
#define WINDOW_ENABLE_BIT 0x40000000
|
||||
#define WINDOW_REG_ADDRESS 0x310c
|
||||
@ -25,7 +27,7 @@
|
||||
#define WINDOW_RANGE_MASK GENMASK(18, 0)
|
||||
|
||||
#define TCSR_SOC_HW_VERSION 0x0224
|
||||
#define TCSR_SOC_HW_VERSION_MAJOR_MASK GENMASK(16, 8)
|
||||
#define TCSR_SOC_HW_VERSION_MAJOR_MASK GENMASK(11, 8)
|
||||
#define TCSR_SOC_HW_VERSION_MINOR_MASK GENMASK(7, 0)
|
||||
|
||||
/* BAR0 + 4k is always accessible, and no
|
||||
@ -76,6 +78,17 @@ static const struct ath11k_msi_config ath11k_msi_config[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct ath11k_msi_config msi_config_one_msi = {
|
||||
.total_vectors = 1,
|
||||
.total_users = 4,
|
||||
.users = (struct ath11k_msi_user[]) {
|
||||
{ .name = "MHI", .num_vectors = 3, .base_vector = 0 },
|
||||
{ .name = "CE", .num_vectors = 1, .base_vector = 0 },
|
||||
{ .name = "WAKE", .num_vectors = 1, .base_vector = 0 },
|
||||
{ .name = "DP", .num_vectors = 1, .base_vector = 0 },
|
||||
},
|
||||
};
|
||||
|
||||
static const char *irq_name[ATH11K_IRQ_NUM_MAX] = {
|
||||
"bhi",
|
||||
"mhi-er0",
|
||||
@ -485,11 +498,11 @@ int ath11k_pci_get_user_msi_assignment(struct ath11k_pci *ab_pci, char *user_nam
|
||||
for (idx = 0; idx < msi_config->total_users; idx++) {
|
||||
if (strcmp(user_name, msi_config->users[idx].name) == 0) {
|
||||
*num_vectors = msi_config->users[idx].num_vectors;
|
||||
*user_base_data = msi_config->users[idx].base_vector
|
||||
+ ab_pci->msi_ep_base_data;
|
||||
*base_vector = msi_config->users[idx].base_vector;
|
||||
*base_vector = msi_config->users[idx].base_vector;
|
||||
*user_base_data = *base_vector + ab_pci->msi_ep_base_data;
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_PCI, "Assign MSI to user: %s, num_vectors: %d, user_base_data: %u, base_vector: %u\n",
|
||||
ath11k_dbg(ab, ATH11K_DBG_PCI,
|
||||
"Assign MSI to user: %s, num_vectors: %d, user_base_data: %u, base_vector: %u\n",
|
||||
user_name, *num_vectors, *user_base_data,
|
||||
*base_vector);
|
||||
|
||||
@ -560,16 +573,30 @@ static void ath11k_pci_free_irq(struct ath11k_base *ab)
|
||||
|
||||
static void ath11k_pci_ce_irq_enable(struct ath11k_base *ab, u16 ce_id)
|
||||
{
|
||||
struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
|
||||
u32 irq_idx;
|
||||
|
||||
/* In case of one MSI vector, we handle irq enable/disable in a
|
||||
* uniform way since we only have one irq
|
||||
*/
|
||||
if (!test_bit(ATH11K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags))
|
||||
return;
|
||||
|
||||
irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_id;
|
||||
enable_irq(ab->irq_num[irq_idx]);
|
||||
}
|
||||
|
||||
static void ath11k_pci_ce_irq_disable(struct ath11k_base *ab, u16 ce_id)
|
||||
{
|
||||
struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
|
||||
u32 irq_idx;
|
||||
|
||||
/* In case of one MSI vector, we handle irq enable/disable in a
|
||||
* uniform way since we only have one irq
|
||||
*/
|
||||
if (!test_bit(ATH11K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags))
|
||||
return;
|
||||
|
||||
irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_id;
|
||||
disable_irq_nosync(ab->irq_num[irq_idx]);
|
||||
}
|
||||
@ -578,6 +605,8 @@ static void ath11k_pci_ce_irqs_disable(struct ath11k_base *ab)
|
||||
{
|
||||
int i;
|
||||
|
||||
clear_bit(ATH11K_FLAG_CE_IRQ_ENABLED, &ab->dev_flags);
|
||||
|
||||
for (i = 0; i < ab->hw_params.ce_count; i++) {
|
||||
if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
|
||||
continue;
|
||||
@ -602,20 +631,27 @@ static void ath11k_pci_sync_ce_irqs(struct ath11k_base *ab)
|
||||
static void ath11k_pci_ce_tasklet(struct tasklet_struct *t)
|
||||
{
|
||||
struct ath11k_ce_pipe *ce_pipe = from_tasklet(ce_pipe, t, intr_tq);
|
||||
int irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_pipe->pipe_num;
|
||||
|
||||
ath11k_ce_per_engine_service(ce_pipe->ab, ce_pipe->pipe_num);
|
||||
|
||||
ath11k_pci_ce_irq_enable(ce_pipe->ab, ce_pipe->pipe_num);
|
||||
enable_irq(ce_pipe->ab->irq_num[irq_idx]);
|
||||
}
|
||||
|
||||
static irqreturn_t ath11k_pci_ce_interrupt_handler(int irq, void *arg)
|
||||
{
|
||||
struct ath11k_ce_pipe *ce_pipe = arg;
|
||||
struct ath11k_base *ab = ce_pipe->ab;
|
||||
int irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_pipe->pipe_num;
|
||||
|
||||
if (!test_bit(ATH11K_FLAG_CE_IRQ_ENABLED, &ab->dev_flags))
|
||||
return IRQ_HANDLED;
|
||||
|
||||
/* last interrupt received for this CE */
|
||||
ce_pipe->timestamp = jiffies;
|
||||
|
||||
ath11k_pci_ce_irq_disable(ce_pipe->ab, ce_pipe->pipe_num);
|
||||
disable_irq_nosync(ab->irq_num[irq_idx]);
|
||||
|
||||
tasklet_schedule(&ce_pipe->intr_tq);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
@ -623,8 +659,15 @@ static irqreturn_t ath11k_pci_ce_interrupt_handler(int irq, void *arg)
|
||||
|
||||
static void ath11k_pci_ext_grp_disable(struct ath11k_ext_irq_grp *irq_grp)
|
||||
{
|
||||
struct ath11k_pci *ab_pci = ath11k_pci_priv(irq_grp->ab);
|
||||
int i;
|
||||
|
||||
/* In case of one MSI vector, we handle irq enable/disable
|
||||
* in a uniform way since we only have one irq
|
||||
*/
|
||||
if (!test_bit(ATH11K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags))
|
||||
return;
|
||||
|
||||
for (i = 0; i < irq_grp->num_irq; i++)
|
||||
disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
|
||||
}
|
||||
@ -633,6 +676,8 @@ static void __ath11k_pci_ext_irq_disable(struct ath11k_base *sc)
|
||||
{
|
||||
int i;
|
||||
|
||||
clear_bit(ATH11K_FLAG_EXT_IRQ_ENABLED, &sc->dev_flags);
|
||||
|
||||
for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
|
||||
struct ath11k_ext_irq_grp *irq_grp = &sc->ext_irq_grp[i];
|
||||
|
||||
@ -645,8 +690,15 @@ static void __ath11k_pci_ext_irq_disable(struct ath11k_base *sc)
|
||||
|
||||
static void ath11k_pci_ext_grp_enable(struct ath11k_ext_irq_grp *irq_grp)
|
||||
{
|
||||
struct ath11k_pci *ab_pci = ath11k_pci_priv(irq_grp->ab);
|
||||
int i;
|
||||
|
||||
/* In case of one MSI vector, we handle irq enable/disable in a
|
||||
* uniform way since we only have one irq
|
||||
*/
|
||||
if (!test_bit(ATH11K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags))
|
||||
return;
|
||||
|
||||
for (i = 0; i < irq_grp->num_irq; i++)
|
||||
enable_irq(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
|
||||
}
|
||||
@ -655,6 +707,8 @@ static void ath11k_pci_ext_irq_enable(struct ath11k_base *ab)
|
||||
{
|
||||
int i;
|
||||
|
||||
set_bit(ATH11K_FLAG_EXT_IRQ_ENABLED, &ab->dev_flags);
|
||||
|
||||
for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
|
||||
struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
|
||||
|
||||
@ -690,11 +744,13 @@ static int ath11k_pci_ext_grp_napi_poll(struct napi_struct *napi, int budget)
|
||||
napi);
|
||||
struct ath11k_base *ab = irq_grp->ab;
|
||||
int work_done;
|
||||
int i;
|
||||
|
||||
work_done = ath11k_dp_service_srng(ab, irq_grp, budget);
|
||||
if (work_done < budget) {
|
||||
napi_complete_done(napi, work_done);
|
||||
ath11k_pci_ext_grp_enable(irq_grp);
|
||||
for (i = 0; i < irq_grp->num_irq; i++)
|
||||
enable_irq(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
|
||||
}
|
||||
|
||||
if (work_done > budget)
|
||||
@ -706,13 +762,19 @@ static int ath11k_pci_ext_grp_napi_poll(struct napi_struct *napi, int budget)
|
||||
static irqreturn_t ath11k_pci_ext_interrupt_handler(int irq, void *arg)
|
||||
{
|
||||
struct ath11k_ext_irq_grp *irq_grp = arg;
|
||||
struct ath11k_base *ab = irq_grp->ab;
|
||||
int i;
|
||||
|
||||
if (!test_bit(ATH11K_FLAG_EXT_IRQ_ENABLED, &ab->dev_flags))
|
||||
return IRQ_HANDLED;
|
||||
|
||||
ath11k_dbg(irq_grp->ab, ATH11K_DBG_PCI, "ext irq:%d\n", irq);
|
||||
|
||||
/* last interrupt received for this group */
|
||||
irq_grp->timestamp = jiffies;
|
||||
|
||||
ath11k_pci_ext_grp_disable(irq_grp);
|
||||
for (i = 0; i < irq_grp->num_irq; i++)
|
||||
disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
|
||||
|
||||
napi_schedule(&irq_grp->napi);
|
||||
|
||||
@ -721,10 +783,10 @@ static irqreturn_t ath11k_pci_ext_interrupt_handler(int irq, void *arg)
|
||||
|
||||
static int ath11k_pci_ext_irq_config(struct ath11k_base *ab)
|
||||
{
|
||||
struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
|
||||
int i, j, ret, num_vectors = 0;
|
||||
u32 user_base_data = 0, base_vector = 0, base_idx;
|
||||
u32 user_base_data = 0, base_vector = 0;
|
||||
|
||||
base_idx = ATH11K_PCI_IRQ_CE0_OFFSET + CE_COUNT_MAX;
|
||||
ret = ath11k_pci_get_user_msi_assignment(ath11k_pci_priv(ab), "DP",
|
||||
&num_vectors,
|
||||
&user_base_data,
|
||||
@ -754,7 +816,7 @@ static int ath11k_pci_ext_irq_config(struct ath11k_base *ab)
|
||||
}
|
||||
|
||||
irq_grp->num_irq = num_irq;
|
||||
irq_grp->irqs[0] = base_idx + i;
|
||||
irq_grp->irqs[0] = ATH11K_PCI_IRQ_DP_OFFSET + i;
|
||||
|
||||
for (j = 0; j < irq_grp->num_irq; j++) {
|
||||
int irq_idx = irq_grp->irqs[j];
|
||||
@ -768,23 +830,32 @@ static int ath11k_pci_ext_irq_config(struct ath11k_base *ab)
|
||||
|
||||
irq_set_status_flags(irq, IRQ_DISABLE_UNLAZY);
|
||||
ret = request_irq(irq, ath11k_pci_ext_interrupt_handler,
|
||||
IRQF_SHARED,
|
||||
ab_pci->irq_flags,
|
||||
"DP_EXT_IRQ", irq_grp);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed request irq %d: %d\n",
|
||||
vector, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
disable_irq_nosync(ab->irq_num[irq_idx]);
|
||||
}
|
||||
ath11k_pci_ext_grp_disable(irq_grp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath11k_pci_set_irq_affinity_hint(struct ath11k_pci *ab_pci,
|
||||
const struct cpumask *m)
|
||||
{
|
||||
if (test_bit(ATH11K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags))
|
||||
return 0;
|
||||
|
||||
return irq_set_affinity_hint(ab_pci->pdev->irq, m);
|
||||
}
|
||||
|
||||
static int ath11k_pci_config_irq(struct ath11k_base *ab)
|
||||
{
|
||||
struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
|
||||
struct ath11k_ce_pipe *ce_pipe;
|
||||
u32 msi_data_start;
|
||||
u32 msi_data_count, msi_data_idx;
|
||||
@ -798,6 +869,12 @@ static int ath11k_pci_config_irq(struct ath11k_base *ab)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ath11k_pci_set_irq_affinity_hint(ab_pci, cpumask_of(0));
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to set irq affinity %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Configure CE irqs */
|
||||
for (i = 0, msi_data_idx = 0; i < ab->hw_params.ce_count; i++) {
|
||||
if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
|
||||
@ -812,12 +889,12 @@ static int ath11k_pci_config_irq(struct ath11k_base *ab)
|
||||
tasklet_setup(&ce_pipe->intr_tq, ath11k_pci_ce_tasklet);
|
||||
|
||||
ret = request_irq(irq, ath11k_pci_ce_interrupt_handler,
|
||||
IRQF_SHARED, irq_name[irq_idx],
|
||||
ab_pci->irq_flags, irq_name[irq_idx],
|
||||
ce_pipe);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to request irq %d: %d\n",
|
||||
irq_idx, ret);
|
||||
return ret;
|
||||
goto err_irq_affinity_cleanup;
|
||||
}
|
||||
|
||||
ab->irq_num[irq_idx] = irq;
|
||||
@ -828,9 +905,13 @@ static int ath11k_pci_config_irq(struct ath11k_base *ab)
|
||||
|
||||
ret = ath11k_pci_ext_irq_config(ab);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err_irq_affinity_cleanup;
|
||||
|
||||
return 0;
|
||||
|
||||
err_irq_affinity_cleanup:
|
||||
ath11k_pci_set_irq_affinity_hint(ab_pci, NULL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath11k_pci_init_qmi_ce_config(struct ath11k_base *ab)
|
||||
@ -852,6 +933,8 @@ static void ath11k_pci_ce_irqs_enable(struct ath11k_base *ab)
|
||||
{
|
||||
int i;
|
||||
|
||||
set_bit(ATH11K_FLAG_CE_IRQ_ENABLED, &ab->dev_flags);
|
||||
|
||||
for (i = 0; i < ab->hw_params.ce_count; i++) {
|
||||
if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
|
||||
continue;
|
||||
@ -896,15 +979,25 @@ static int ath11k_pci_alloc_msi(struct ath11k_pci *ab_pci)
|
||||
msi_config->total_vectors,
|
||||
msi_config->total_vectors,
|
||||
PCI_IRQ_MSI);
|
||||
if (num_vectors != msi_config->total_vectors) {
|
||||
ath11k_err(ab, "failed to get %d MSI vectors, only %d available",
|
||||
msi_config->total_vectors, num_vectors);
|
||||
|
||||
if (num_vectors >= 0)
|
||||
return -EINVAL;
|
||||
else
|
||||
return num_vectors;
|
||||
if (num_vectors == msi_config->total_vectors) {
|
||||
set_bit(ATH11K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags);
|
||||
ab_pci->irq_flags = IRQF_SHARED;
|
||||
} else {
|
||||
num_vectors = pci_alloc_irq_vectors(ab_pci->pdev,
|
||||
1,
|
||||
1,
|
||||
PCI_IRQ_MSI);
|
||||
if (num_vectors < 0) {
|
||||
ret = -EINVAL;
|
||||
goto reset_msi_config;
|
||||
}
|
||||
clear_bit(ATH11K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags);
|
||||
ab_pci->msi_config = &msi_config_one_msi;
|
||||
ab_pci->irq_flags = IRQF_SHARED | IRQF_NOBALANCING;
|
||||
ath11k_dbg(ab, ATH11K_DBG_PCI, "request MSI one vector\n");
|
||||
}
|
||||
ath11k_info(ab, "MSI vectors: %d\n", num_vectors);
|
||||
|
||||
ath11k_pci_msi_disable(ab_pci);
|
||||
|
||||
msi_desc = irq_get_msi_desc(ab_pci->pdev->irq);
|
||||
@ -925,6 +1018,7 @@ static int ath11k_pci_alloc_msi(struct ath11k_pci *ab_pci)
|
||||
free_msi_vector:
|
||||
pci_free_irq_vectors(ab_pci->pdev);
|
||||
|
||||
reset_msi_config:
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -933,6 +1027,25 @@ static void ath11k_pci_free_msi(struct ath11k_pci *ab_pci)
|
||||
pci_free_irq_vectors(ab_pci->pdev);
|
||||
}
|
||||
|
||||
static int ath11k_pci_config_msi_data(struct ath11k_pci *ab_pci)
|
||||
{
|
||||
struct msi_desc *msi_desc;
|
||||
|
||||
msi_desc = irq_get_msi_desc(ab_pci->pdev->irq);
|
||||
if (!msi_desc) {
|
||||
ath11k_err(ab_pci->ab, "msi_desc is NULL!\n");
|
||||
pci_free_irq_vectors(ab_pci->pdev);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ab_pci->msi_ep_base_data = msi_desc->msg.data;
|
||||
|
||||
ath11k_dbg(ab_pci->ab, ATH11K_DBG_PCI, "pci after request_irq msi_ep_base_data %d\n",
|
||||
ab_pci->msi_ep_base_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath11k_pci_claim(struct ath11k_pci *ab_pci, struct pci_dev *pdev)
|
||||
{
|
||||
struct ath11k_base *ab = ab_pci->ab;
|
||||
@ -1130,7 +1243,13 @@ static int ath11k_pci_start(struct ath11k_base *ab)
|
||||
|
||||
set_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags);
|
||||
|
||||
ath11k_pci_aspm_restore(ab_pci);
|
||||
/* TODO: for now don't restore ASPM in case of single MSI
|
||||
* vector as MHI register reading in M2 causes system hang.
|
||||
*/
|
||||
if (test_bit(ATH11K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags))
|
||||
ath11k_pci_aspm_restore(ab_pci);
|
||||
else
|
||||
ath11k_info(ab, "leaving PCI ASPM disabled to avoid MHI M2 problems\n");
|
||||
|
||||
ath11k_pci_ce_irqs_enable(ab);
|
||||
ath11k_ce_rx_post_buf(ab);
|
||||
@ -1229,7 +1348,7 @@ static int ath11k_pci_probe(struct pci_dev *pdev,
|
||||
{
|
||||
struct ath11k_base *ab;
|
||||
struct ath11k_pci *ab_pci;
|
||||
u32 soc_hw_version_major, soc_hw_version_minor;
|
||||
u32 soc_hw_version_major, soc_hw_version_minor, addr;
|
||||
int ret;
|
||||
|
||||
ab = ath11k_core_alloc(&pdev->dev, sizeof(*ab_pci), ATH11K_BUS_PCI,
|
||||
@ -1249,6 +1368,14 @@ static int ath11k_pci_probe(struct pci_dev *pdev,
|
||||
pci_set_drvdata(pdev, ab);
|
||||
spin_lock_init(&ab_pci->window_lock);
|
||||
|
||||
/* Set fixed_mem_region to true for platforms support reserved memory
|
||||
* from DT. If memory is reserved from DT for FW, ath11k driver need not
|
||||
* allocate memory.
|
||||
*/
|
||||
ret = of_property_read_u32(ab->dev->of_node, "memory-region", &addr);
|
||||
if (!ret)
|
||||
set_bit(ATH11K_FLAG_FIXED_MEM_RGN, &ab->dev_flags);
|
||||
|
||||
ret = ath11k_pci_claim(ab_pci, pdev);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to claim device: %d\n", ret);
|
||||
@ -1291,9 +1418,21 @@ static int ath11k_pci_probe(struct pci_dev *pdev,
|
||||
&soc_hw_version_minor);
|
||||
switch (soc_hw_version_major) {
|
||||
case 2:
|
||||
ab->hw_rev = ATH11K_HW_WCN6855_HW20;
|
||||
switch (soc_hw_version_minor) {
|
||||
case 0x00:
|
||||
case 0x01:
|
||||
ab->hw_rev = ATH11K_HW_WCN6855_HW20;
|
||||
break;
|
||||
case 0x10:
|
||||
case 0x11:
|
||||
ab->hw_rev = ATH11K_HW_WCN6855_HW21;
|
||||
break;
|
||||
default:
|
||||
goto unsupported_wcn6855_soc;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
unsupported_wcn6855_soc:
|
||||
dev_err(&pdev->dev, "Unsupported WCN6855 SOC hardware version: %d %d\n",
|
||||
soc_hw_version_major, soc_hw_version_minor);
|
||||
ret = -EOPNOTSUPP;
|
||||
@ -1342,6 +1481,17 @@ static int ath11k_pci_probe(struct pci_dev *pdev,
|
||||
goto err_ce_free;
|
||||
}
|
||||
|
||||
/* kernel may allocate a dummy vector before request_irq and
|
||||
* then allocate a real vector when request_irq is called.
|
||||
* So get msi_data here again to avoid spurious interrupt
|
||||
* as msi_data will configured to srngs.
|
||||
*/
|
||||
ret = ath11k_pci_config_msi_data(ab_pci);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to config msi_data: %d\n", ret);
|
||||
goto err_free_irq;
|
||||
}
|
||||
|
||||
ret = ath11k_core_init(ab);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to init core: %d\n", ret);
|
||||
@ -1378,6 +1528,8 @@ static void ath11k_pci_remove(struct pci_dev *pdev)
|
||||
struct ath11k_base *ab = pci_get_drvdata(pdev);
|
||||
struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
|
||||
|
||||
ath11k_pci_set_irq_affinity_hint(ab_pci, NULL);
|
||||
|
||||
if (test_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags)) {
|
||||
ath11k_pci_power_down(ab);
|
||||
ath11k_debugfs_soc_destroy(ab);
|
||||
|
@ -68,6 +68,7 @@ enum ath11k_pci_flags {
|
||||
ATH11K_PCI_FLAG_INIT_DONE,
|
||||
ATH11K_PCI_FLAG_IS_MSI_64,
|
||||
ATH11K_PCI_ASPM_RESTORE,
|
||||
ATH11K_PCI_FLAG_MULTI_MSI_VECTORS,
|
||||
};
|
||||
|
||||
struct ath11k_pci {
|
||||
@ -87,6 +88,8 @@ struct ath11k_pci {
|
||||
/* enum ath11k_pci_flags */
|
||||
unsigned long flags;
|
||||
u16 link_ctl;
|
||||
|
||||
unsigned long irq_flags;
|
||||
};
|
||||
|
||||
static inline struct ath11k_pci *ath11k_pci_priv(struct ath11k_base *ab)
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include "core.h"
|
||||
#include "debug.h"
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/firmware.h>
|
||||
|
||||
#define SLEEP_CLOCK_SELECT_INTERNAL_BIT 0x02
|
||||
@ -1751,7 +1753,9 @@ static int ath11k_qmi_respond_fw_mem_request(struct ath11k_base *ab)
|
||||
* failure to FW and FW will then request mulitple blocks of small
|
||||
* chunk size memory.
|
||||
*/
|
||||
if (!ab->bus_params.fixed_mem_region && ab->qmi.target_mem_delayed) {
|
||||
if (!(ab->bus_params.fixed_mem_region ||
|
||||
test_bit(ATH11K_FLAG_FIXED_MEM_RGN, &ab->dev_flags)) &&
|
||||
ab->qmi.target_mem_delayed) {
|
||||
delayed = true;
|
||||
ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi delays mem_request %d\n",
|
||||
ab->qmi.mem_seg_count);
|
||||
@ -1818,10 +1822,12 @@ static void ath11k_qmi_free_target_mem_chunk(struct ath11k_base *ab)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (ab->bus_params.fixed_mem_region)
|
||||
return;
|
||||
|
||||
for (i = 0; i < ab->qmi.mem_seg_count; i++) {
|
||||
if ((ab->bus_params.fixed_mem_region ||
|
||||
test_bit(ATH11K_FLAG_FIXED_MEM_RGN, &ab->dev_flags)) &&
|
||||
ab->qmi.target_mem[i].iaddr)
|
||||
iounmap(ab->qmi.target_mem[i].iaddr);
|
||||
|
||||
if (!ab->qmi.target_mem[i].vaddr)
|
||||
continue;
|
||||
|
||||
@ -1869,10 +1875,44 @@ static int ath11k_qmi_alloc_target_mem_chunk(struct ath11k_base *ab)
|
||||
|
||||
static int ath11k_qmi_assign_target_mem_chunk(struct ath11k_base *ab)
|
||||
{
|
||||
int i, idx;
|
||||
struct device *dev = ab->dev;
|
||||
struct device_node *hremote_node = NULL;
|
||||
struct resource res;
|
||||
u32 host_ddr_sz;
|
||||
int i, idx, ret;
|
||||
|
||||
for (i = 0, idx = 0; i < ab->qmi.mem_seg_count; i++) {
|
||||
switch (ab->qmi.target_mem[i].type) {
|
||||
case HOST_DDR_REGION_TYPE:
|
||||
hremote_node = of_parse_phandle(dev->of_node, "memory-region", 0);
|
||||
if (!hremote_node) {
|
||||
ath11k_dbg(ab, ATH11K_DBG_QMI,
|
||||
"qmi fail to get hremote_node\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = of_address_to_resource(hremote_node, 0, &res);
|
||||
if (ret) {
|
||||
ath11k_dbg(ab, ATH11K_DBG_QMI,
|
||||
"qmi fail to get reg from hremote\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (res.end - res.start + 1 < ab->qmi.target_mem[i].size) {
|
||||
ath11k_dbg(ab, ATH11K_DBG_QMI,
|
||||
"qmi fail to assign memory of sz\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ab->qmi.target_mem[idx].paddr = res.start;
|
||||
ab->qmi.target_mem[idx].iaddr =
|
||||
ioremap(ab->qmi.target_mem[idx].paddr,
|
||||
ab->qmi.target_mem[i].size);
|
||||
ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size;
|
||||
host_ddr_sz = ab->qmi.target_mem[i].size;
|
||||
ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type;
|
||||
idx++;
|
||||
break;
|
||||
case BDF_MEM_REGION_TYPE:
|
||||
ab->qmi.target_mem[idx].paddr = ab->hw_params.bdf_addr;
|
||||
ab->qmi.target_mem[idx].vaddr = NULL;
|
||||
@ -1887,10 +1927,16 @@ static int ath11k_qmi_assign_target_mem_chunk(struct ath11k_base *ab)
|
||||
}
|
||||
|
||||
if (ath11k_cold_boot_cal && ab->hw_params.cold_boot_calib) {
|
||||
ab->qmi.target_mem[idx].paddr =
|
||||
ATH11K_QMI_CALDB_ADDRESS;
|
||||
ab->qmi.target_mem[idx].vaddr =
|
||||
(void *)ATH11K_QMI_CALDB_ADDRESS;
|
||||
if (hremote_node) {
|
||||
ab->qmi.target_mem[idx].paddr =
|
||||
res.start + host_ddr_sz;
|
||||
ab->qmi.target_mem[idx].iaddr =
|
||||
ioremap(ab->qmi.target_mem[idx].paddr,
|
||||
ab->qmi.target_mem[i].size);
|
||||
} else {
|
||||
ab->qmi.target_mem[idx].paddr =
|
||||
ATH11K_QMI_CALDB_ADDRESS;
|
||||
}
|
||||
} else {
|
||||
ab->qmi.target_mem[idx].paddr = 0;
|
||||
ab->qmi.target_mem[idx].vaddr = NULL;
|
||||
@ -2621,7 +2667,8 @@ static void ath11k_qmi_msg_mem_request_cb(struct qmi_handle *qmi_hdl,
|
||||
msg->mem_seg[i].type, msg->mem_seg[i].size);
|
||||
}
|
||||
|
||||
if (ab->bus_params.fixed_mem_region) {
|
||||
if (ab->bus_params.fixed_mem_region ||
|
||||
test_bit(ATH11K_FLAG_FIXED_MEM_RGN, &ab->dev_flags)) {
|
||||
ret = ath11k_qmi_assign_target_mem_chunk(ab);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to assign qmi target memory: %d\n",
|
||||
@ -2830,7 +2877,7 @@ int ath11k_qmi_init_service(struct ath11k_base *ab)
|
||||
memset(&ab->qmi.target_mem, 0, sizeof(struct target_mem_chunk));
|
||||
ab->qmi.ab = ab;
|
||||
|
||||
ab->qmi.target_mem_mode = ATH11K_QMI_TARGET_MEM_MODE_DEFAULT;
|
||||
ab->qmi.target_mem_mode = ab->hw_params.fw_mem_mode;
|
||||
ret = qmi_handle_init(&ab->qmi.handle, ATH11K_QMI_RESP_LEN_MAX,
|
||||
&ath11k_qmi_ops, ath11k_qmi_msg_handlers);
|
||||
if (ret < 0) {
|
||||
|
@ -34,14 +34,13 @@
|
||||
|
||||
#define QMI_WLANFW_MAX_DATA_SIZE_V01 6144
|
||||
#define ATH11K_FIRMWARE_MODE_OFF 4
|
||||
#define ATH11K_QMI_TARGET_MEM_MODE_DEFAULT 0
|
||||
#define ATH11K_COLD_BOOT_FW_RESET_DELAY (40 * HZ)
|
||||
|
||||
struct ath11k_base;
|
||||
|
||||
enum ath11k_qmi_file_type {
|
||||
ATH11K_QMI_FILE_TYPE_BDF_GOLDEN,
|
||||
ATH11K_QMI_FILE_TYPE_CALDATA,
|
||||
ATH11K_QMI_FILE_TYPE_CALDATA = 2,
|
||||
ATH11K_QMI_FILE_TYPE_EEPROM,
|
||||
ATH11K_QMI_MAX_FILE_TYPE,
|
||||
};
|
||||
@ -95,6 +94,7 @@ struct target_mem_chunk {
|
||||
u32 type;
|
||||
dma_addr_t paddr;
|
||||
u32 *vaddr;
|
||||
void __iomem *iaddr;
|
||||
};
|
||||
|
||||
struct target_info {
|
||||
|
@ -86,6 +86,9 @@ ath11k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
|
||||
if (ret)
|
||||
ath11k_warn(ar->ab,
|
||||
"INIT Country code set to fw failed : %d\n", ret);
|
||||
|
||||
ath11k_mac_11d_scan_stop(ar);
|
||||
ar->regdom_set_by_user = true;
|
||||
}
|
||||
|
||||
int ath11k_reg_update_chan_list(struct ath11k *ar)
|
||||
@ -179,6 +182,11 @@ int ath11k_reg_update_chan_list(struct ath11k *ar)
|
||||
ret = ath11k_wmi_send_scan_chan_list_cmd(ar, params);
|
||||
kfree(params);
|
||||
|
||||
if (ar->pending_11d) {
|
||||
complete(&ar->finish_11d_ch_list);
|
||||
ar->pending_11d = false;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -244,8 +252,15 @@ int ath11k_regd_update(struct ath11k *ar)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (ar->pending_11d)
|
||||
complete(&ar->finish_11d_scan);
|
||||
|
||||
rtnl_lock();
|
||||
wiphy_lock(ar->hw->wiphy);
|
||||
|
||||
if (ar->pending_11d)
|
||||
reinit_completion(&ar->finish_11d_ch_list);
|
||||
|
||||
ret = regulatory_set_wiphy_regd_sync(ar->hw->wiphy, regd_copy);
|
||||
wiphy_unlock(ar->hw->wiphy);
|
||||
rtnl_unlock();
|
||||
|
@ -581,6 +581,7 @@ int ath11k_spectral_process_fft(struct ath11k *ar,
|
||||
u16 length, freq;
|
||||
u8 chan_width_mhz, bin_sz;
|
||||
int ret;
|
||||
u32 check_length;
|
||||
|
||||
lockdep_assert_held(&ar->spectral.lock);
|
||||
|
||||
@ -614,6 +615,13 @@ int ath11k_spectral_process_fft(struct ath11k *ar,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
check_length = sizeof(*fft_report) + (num_bins * ab->hw_params.spectral.fft_sz);
|
||||
ret = ath11k_dbring_validate_buffer(ar, data, check_length);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "found magic value in fft data, dropping\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ath11k_spectral_pull_search(ar, data, &search);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to pull search report %d\n", ret);
|
||||
@ -747,6 +755,12 @@ static int ath11k_spectral_process_data(struct ath11k *ar,
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = ath11k_dbring_validate_buffer(ar, data, tlv_len);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "found magic value in spectral summary, dropping\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
summary = (struct spectral_summary_fft_report *)tlv;
|
||||
ath11k_spectral_pull_summary(ar, ¶m->meta,
|
||||
summary, &summ_rpt);
|
||||
|
@ -130,6 +130,8 @@ static const struct wmi_tlv_policy wmi_tlv_policies[] = {
|
||||
.min_len = sizeof(struct wmi_vdev_delete_resp_event) },
|
||||
[WMI_TAG_OBSS_COLOR_COLLISION_EVT] = {
|
||||
.min_len = sizeof(struct wmi_obss_color_collision_event) },
|
||||
[WMI_TAG_11D_NEW_COUNTRY_EVENT] = {
|
||||
.min_len = sizeof(struct wmi_11d_new_cc_ev) },
|
||||
};
|
||||
|
||||
#define PRIMAP(_hw_mode_) \
|
||||
@ -337,6 +339,7 @@ ath11k_pull_mac_phy_cap_svc_ready_ext(struct ath11k_pdev_wmi *wmi_handle,
|
||||
struct ath11k_pdev *pdev)
|
||||
{
|
||||
struct wmi_mac_phy_capabilities *mac_phy_caps;
|
||||
struct ath11k_base *ab = wmi_handle->wmi_ab->ab;
|
||||
struct ath11k_band_cap *cap_band;
|
||||
struct ath11k_pdev_cap *pdev_cap = &pdev->cap;
|
||||
u32 phy_map;
|
||||
@ -368,6 +371,10 @@ ath11k_pull_mac_phy_cap_svc_ready_ext(struct ath11k_pdev_wmi *wmi_handle,
|
||||
pdev->pdev_id = mac_phy_caps->pdev_id;
|
||||
pdev_cap->supported_bands |= mac_phy_caps->supported_bands;
|
||||
pdev_cap->ampdu_density = mac_phy_caps->ampdu_density;
|
||||
ab->target_pdev_ids[ab->target_pdev_count].supported_bands =
|
||||
mac_phy_caps->supported_bands;
|
||||
ab->target_pdev_ids[ab->target_pdev_count].pdev_id = mac_phy_caps->pdev_id;
|
||||
ab->target_pdev_count++;
|
||||
|
||||
/* Take non-zero tx/rx chainmask. If tx/rx chainmask differs from
|
||||
* band to band for a single radio, need to see how this should be
|
||||
@ -2106,7 +2113,7 @@ int ath11k_wmi_send_scan_start_cmd(struct ath11k *ar,
|
||||
void *ptr;
|
||||
int i, ret, len;
|
||||
u32 *tmp_ptr;
|
||||
u8 extraie_len_with_pad = 0;
|
||||
u16 extraie_len_with_pad = 0;
|
||||
struct hint_short_ssid *s_ssid = NULL;
|
||||
struct hint_bssid *hint_bssid = NULL;
|
||||
|
||||
@ -2125,7 +2132,7 @@ int ath11k_wmi_send_scan_start_cmd(struct ath11k *ar,
|
||||
len += sizeof(*bssid) * params->num_bssid;
|
||||
|
||||
len += TLV_HDR_SIZE;
|
||||
if (params->extraie.len)
|
||||
if (params->extraie.len && params->extraie.len <= 0xFFFF)
|
||||
extraie_len_with_pad =
|
||||
roundup(params->extraie.len, sizeof(u32));
|
||||
len += extraie_len_with_pad;
|
||||
@ -2174,6 +2181,8 @@ int ath11k_wmi_send_scan_start_cmd(struct ath11k *ar,
|
||||
cmd->num_ssids = params->num_ssids;
|
||||
cmd->ie_len = params->extraie.len;
|
||||
cmd->n_probes = params->n_probes;
|
||||
ether_addr_copy(cmd->mac_addr.addr, params->mac_addr.addr);
|
||||
ether_addr_copy(cmd->mac_mask.addr, params->mac_mask.addr);
|
||||
|
||||
ptr += sizeof(*cmd);
|
||||
|
||||
@ -2232,7 +2241,7 @@ int ath11k_wmi_send_scan_start_cmd(struct ath11k *ar,
|
||||
FIELD_PREP(WMI_TLV_LEN, len);
|
||||
ptr += TLV_HDR_SIZE;
|
||||
|
||||
if (params->extraie.len)
|
||||
if (extraie_len_with_pad)
|
||||
memcpy(ptr, params->extraie.ptr,
|
||||
params->extraie.len);
|
||||
|
||||
@ -2793,6 +2802,42 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath11k_wmi_send_set_current_country_cmd(struct ath11k *ar,
|
||||
struct wmi_set_current_country_params *param)
|
||||
{
|
||||
struct ath11k_pdev_wmi *wmi = ar->wmi;
|
||||
struct wmi_set_current_country_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
int ret;
|
||||
|
||||
skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd = (struct wmi_set_current_country_cmd *)skb->data;
|
||||
cmd->tlv_header =
|
||||
FIELD_PREP(WMI_TLV_TAG, WMI_TAG_SET_CURRENT_COUNTRY_CMD) |
|
||||
FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
|
||||
|
||||
cmd->pdev_id = ar->pdev->pdev_id;
|
||||
memcpy(&cmd->new_alpha2, ¶m->alpha2, 3);
|
||||
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_SET_CURRENT_COUNTRY_CMDID);
|
||||
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
|
||||
"set current country pdev id %d alpha2 %c%c\n",
|
||||
ar->pdev->pdev_id,
|
||||
param->alpha2[0],
|
||||
param->alpha2[1]);
|
||||
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab,
|
||||
"failed to send WMI_SET_CURRENT_COUNTRY_CMDID: %d\n", ret);
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
ath11k_wmi_send_thermal_mitigation_param_cmd(struct ath11k *ar,
|
||||
struct thermal_mitigation_params *param)
|
||||
@ -2857,6 +2902,75 @@ ath11k_wmi_send_thermal_mitigation_param_cmd(struct ath11k *ar,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath11k_wmi_send_11d_scan_start_cmd(struct ath11k *ar,
|
||||
struct wmi_11d_scan_start_params *param)
|
||||
{
|
||||
struct ath11k_pdev_wmi *wmi = ar->wmi;
|
||||
struct wmi_11d_scan_start_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
int ret;
|
||||
|
||||
skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd = (struct wmi_11d_scan_start_cmd *)skb->data;
|
||||
cmd->tlv_header =
|
||||
FIELD_PREP(WMI_TLV_TAG, WMI_TAG_11D_SCAN_START_CMD) |
|
||||
FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
|
||||
|
||||
cmd->vdev_id = param->vdev_id;
|
||||
cmd->scan_period_msec = param->scan_period_msec;
|
||||
cmd->start_interval_msec = param->start_interval_msec;
|
||||
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_11D_SCAN_START_CMDID);
|
||||
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
|
||||
"send 11d scan start vdev id %d period %d ms internal %d ms\n",
|
||||
cmd->vdev_id,
|
||||
cmd->scan_period_msec,
|
||||
cmd->start_interval_msec);
|
||||
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab,
|
||||
"failed to send WMI_11D_SCAN_START_CMDID: %d\n", ret);
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath11k_wmi_send_11d_scan_stop_cmd(struct ath11k *ar, u32 vdev_id)
|
||||
{
|
||||
struct ath11k_pdev_wmi *wmi = ar->wmi;
|
||||
struct wmi_11d_scan_stop_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
int ret;
|
||||
|
||||
skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd = (struct wmi_11d_scan_stop_cmd *)skb->data;
|
||||
cmd->tlv_header =
|
||||
FIELD_PREP(WMI_TLV_TAG, WMI_TAG_11D_SCAN_STOP_CMD) |
|
||||
FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
|
||||
|
||||
cmd->vdev_id = vdev_id;
|
||||
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_11D_SCAN_STOP_CMDID);
|
||||
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
|
||||
"send 11d scan stop vdev id %d\n",
|
||||
cmd->vdev_id);
|
||||
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab,
|
||||
"failed to send WMI_11D_SCAN_STOP_CMDID: %d\n", ret);
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ath11k_wmi_pdev_pktlog_enable(struct ath11k *ar, u32 pktlog_filter)
|
||||
{
|
||||
struct ath11k_pdev_wmi *wmi = ar->wmi;
|
||||
@ -3506,7 +3620,7 @@ ath11k_wmi_obss_color_collision_event(struct ath11k_base *ab, struct sk_buff *sk
|
||||
case WMI_BSS_COLOR_FREE_SLOT_AVAILABLE:
|
||||
break;
|
||||
default:
|
||||
ath11k_warn(ab, "received unknown obss color collision detetction event\n");
|
||||
ath11k_warn(ab, "received unknown obss color collision detection event\n");
|
||||
}
|
||||
|
||||
exit:
|
||||
@ -4230,6 +4344,7 @@ static int ath11k_wmi_tlv_ext_soc_hal_reg_caps_parse(struct ath11k_base *soc,
|
||||
svc_rdy_ext->param.num_phy = svc_rdy_ext->soc_hal_reg_caps->num_phy;
|
||||
|
||||
soc->num_radios = 0;
|
||||
soc->target_pdev_count = 0;
|
||||
phy_id_map = svc_rdy_ext->pref_hw_mode_caps.phy_id_map;
|
||||
|
||||
while (phy_id_map && soc->num_radios < MAX_RADIOS) {
|
||||
@ -4867,6 +4982,7 @@ static int wmi_process_mgmt_tx_comp(struct ath11k *ar, u32 desc_id,
|
||||
struct sk_buff *msdu;
|
||||
struct ieee80211_tx_info *info;
|
||||
struct ath11k_skb_cb *skb_cb;
|
||||
int num_mgmt;
|
||||
|
||||
spin_lock_bh(&ar->txmgmt_idr_lock);
|
||||
msdu = idr_find(&ar->txmgmt_idr, desc_id);
|
||||
@ -4890,10 +5006,19 @@ static int wmi_process_mgmt_tx_comp(struct ath11k *ar, u32 desc_id,
|
||||
|
||||
ieee80211_tx_status_irqsafe(ar->hw, msdu);
|
||||
|
||||
num_mgmt = atomic_dec_if_positive(&ar->num_pending_mgmt_tx);
|
||||
|
||||
/* WARN when we received this event without doing any mgmt tx */
|
||||
if (atomic_dec_if_positive(&ar->num_pending_mgmt_tx) < 0)
|
||||
if (num_mgmt < 0)
|
||||
WARN_ON_ONCE(1);
|
||||
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
|
||||
"wmi mgmt tx comp pending %d desc id %d\n",
|
||||
num_mgmt, desc_id);
|
||||
|
||||
if (!num_mgmt)
|
||||
wake_up(&ar->txmgmt_empty_waitq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -5896,6 +6021,41 @@ static void ath11k_wmi_op_ep_tx_credits(struct ath11k_base *ab)
|
||||
wake_up(&ab->wmi_ab.tx_credits_wq);
|
||||
}
|
||||
|
||||
static int ath11k_reg_11d_new_cc_event(struct ath11k_base *ab, struct sk_buff *skb)
|
||||
{
|
||||
const struct wmi_11d_new_cc_ev *ev;
|
||||
const void **tb;
|
||||
int ret;
|
||||
|
||||
tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
||||
if (IS_ERR(tb)) {
|
||||
ret = PTR_ERR(tb);
|
||||
ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ev = tb[WMI_TAG_11D_NEW_COUNTRY_EVENT];
|
||||
if (!ev) {
|
||||
kfree(tb);
|
||||
ath11k_warn(ab, "failed to fetch 11d new cc ev");
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
spin_lock_bh(&ab->base_lock);
|
||||
memcpy(&ab->new_alpha2, &ev->new_alpha2, 2);
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI, "wmi 11d new cc %c%c\n",
|
||||
ab->new_alpha2[0],
|
||||
ab->new_alpha2[1]);
|
||||
|
||||
kfree(tb);
|
||||
|
||||
queue_work(ab->workqueue, &ab->update_11d_work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath11k_wmi_htc_tx_complete(struct ath11k_base *ab,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
@ -5927,7 +6087,13 @@ static void ath11k_wmi_htc_tx_complete(struct ath11k_base *ab,
|
||||
|
||||
static bool ath11k_reg_is_world_alpha(char *alpha)
|
||||
{
|
||||
return alpha[0] == '0' && alpha[1] == '0';
|
||||
if (alpha[0] == '0' && alpha[1] == '0')
|
||||
return true;
|
||||
|
||||
if (alpha[0] == 'n' && alpha[1] == 'a')
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int ath11k_reg_chan_list_event(struct ath11k_base *ab, struct sk_buff *skb)
|
||||
@ -6020,7 +6186,7 @@ static int ath11k_reg_chan_list_event(struct ath11k_base *ab, struct sk_buff *sk
|
||||
ar = ab->pdevs[pdev_idx].ar;
|
||||
kfree(ab->new_regd[pdev_idx]);
|
||||
ab->new_regd[pdev_idx] = regd;
|
||||
ieee80211_queue_work(ar->hw, &ar->regd_update_work);
|
||||
queue_work(ab->workqueue, &ar->regd_update_work);
|
||||
} else {
|
||||
/* This regd would be applied during mac registration and is
|
||||
* held constant throughout for regd intersection purpose
|
||||
@ -7285,6 +7451,9 @@ static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)
|
||||
case WMI_WOW_WAKEUP_HOST_EVENTID:
|
||||
ath11k_wmi_event_wow_wakeup_host(ab, skb);
|
||||
break;
|
||||
case WMI_11D_NEW_COUNTRY_EVENTID:
|
||||
ath11k_reg_11d_new_cc_event(ab, skb);
|
||||
break;
|
||||
/* TODO: Add remaining events */
|
||||
default:
|
||||
ath11k_dbg(ab, ATH11K_DBG_WMI, "Unknown eventid: 0x%x\n", id);
|
||||
@ -7543,3 +7712,31 @@ int ath11k_wmi_wow_enable(struct ath11k *ar)
|
||||
|
||||
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ENABLE_CMDID);
|
||||
}
|
||||
|
||||
int ath11k_wmi_scan_prob_req_oui(struct ath11k *ar,
|
||||
const u8 mac_addr[ETH_ALEN])
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct wmi_scan_prob_req_oui_cmd *cmd;
|
||||
u32 prob_req_oui;
|
||||
int len;
|
||||
|
||||
prob_req_oui = (((u32)mac_addr[0]) << 16) |
|
||||
(((u32)mac_addr[1]) << 8) | mac_addr[2];
|
||||
|
||||
len = sizeof(*cmd);
|
||||
skb = ath11k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd = (struct wmi_scan_prob_req_oui_cmd *)skb->data;
|
||||
cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG,
|
||||
WMI_TAG_SCAN_PROB_REQ_OUI_CMD) |
|
||||
FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
|
||||
cmd->prob_req_oui = prob_req_oui;
|
||||
|
||||
ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "wmi scan prob req oui %d\n",
|
||||
prob_req_oui);
|
||||
|
||||
return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_SCAN_PROB_REQ_OUI_CMDID);
|
||||
}
|
||||
|
@ -113,10 +113,10 @@ enum wmi_host_hw_mode_priority {
|
||||
WMI_HOST_HW_MODE_MAX_PRI
|
||||
};
|
||||
|
||||
enum {
|
||||
enum WMI_HOST_WLAN_BAND {
|
||||
WMI_HOST_WLAN_2G_CAP = 0x1,
|
||||
WMI_HOST_WLAN_5G_CAP = 0x2,
|
||||
WMI_HOST_WLAN_2G_5G_CAP = 0x3,
|
||||
WMI_HOST_WLAN_2G_5G_CAP = WMI_HOST_WLAN_2G_CAP | WMI_HOST_WLAN_5G_CAP,
|
||||
};
|
||||
|
||||
/* Parameters used for WMI_VDEV_PARAM_AUTORATE_MISC_CFG command.
|
||||
@ -2169,6 +2169,13 @@ enum wmi_nss_ratio {
|
||||
WMI_NSS_RATIO_2_NSS = 0x3,
|
||||
};
|
||||
|
||||
enum wmi_dtim_policy {
|
||||
WMI_DTIM_POLICY_IGNORE = 1,
|
||||
WMI_DTIM_POLICY_NORMAL = 2,
|
||||
WMI_DTIM_POLICY_STICK = 3,
|
||||
WMI_DTIM_POLICY_AUTO = 4,
|
||||
};
|
||||
|
||||
struct wmi_host_pdev_band_to_mac {
|
||||
u32 pdev_id;
|
||||
u32 start_freq;
|
||||
@ -3082,7 +3089,6 @@ enum scan_dwelltime_adaptive_mode {
|
||||
|
||||
#define WLAN_SCAN_MAX_NUM_SSID 10
|
||||
#define WLAN_SCAN_MAX_NUM_BSSID 10
|
||||
#define WLAN_SCAN_MAX_NUM_CHANNELS 40
|
||||
|
||||
#define WLAN_SSID_MAX_LEN 32
|
||||
|
||||
@ -3303,7 +3309,7 @@ struct scan_req_params {
|
||||
u32 num_bssid;
|
||||
u32 num_ssids;
|
||||
u32 n_probes;
|
||||
u32 chan_list[WLAN_SCAN_MAX_NUM_CHANNELS];
|
||||
u32 *chan_list;
|
||||
u32 notify_scan_events;
|
||||
struct wlan_ssid ssid[WLAN_SCAN_MAX_NUM_SSID];
|
||||
struct wmi_mac_addr bssid_list[WLAN_SCAN_MAX_NUM_BSSID];
|
||||
@ -3314,6 +3320,8 @@ struct scan_req_params {
|
||||
u32 num_hint_bssid;
|
||||
struct hint_short_ssid hint_s_ssid[WLAN_SCAN_MAX_HINT_S_SSID];
|
||||
struct hint_bssid hint_bssid[WLAN_SCAN_MAX_HINT_BSSID];
|
||||
struct wmi_mac_addr mac_addr;
|
||||
struct wmi_mac_addr mac_mask;
|
||||
};
|
||||
|
||||
struct wmi_ssid_arg {
|
||||
@ -3677,6 +3685,11 @@ struct wmi_scan_chan_list_cmd {
|
||||
u32 pdev_id;
|
||||
} __packed;
|
||||
|
||||
struct wmi_scan_prob_req_oui_cmd {
|
||||
u32 tlv_header;
|
||||
u32 prob_req_oui;
|
||||
} __packed;
|
||||
|
||||
#define WMI_MGMT_SEND_DOWNLD_LEN 64
|
||||
|
||||
#define WMI_TX_PARAMS_DWORD0_POWER GENMASK(7, 0)
|
||||
@ -3770,6 +3783,16 @@ struct stats_request_params {
|
||||
u32 pdev_id;
|
||||
};
|
||||
|
||||
struct wmi_set_current_country_params {
|
||||
u8 alpha2[3];
|
||||
};
|
||||
|
||||
struct wmi_set_current_country_cmd {
|
||||
u32 tlv_header;
|
||||
u32 pdev_id;
|
||||
u32 new_alpha2;
|
||||
} __packed;
|
||||
|
||||
enum set_init_cc_type {
|
||||
WMI_COUNTRY_INFO_TYPE_ALPHA,
|
||||
WMI_COUNTRY_INFO_TYPE_COUNTRY_CODE,
|
||||
@ -3803,6 +3826,28 @@ struct wmi_init_country_cmd {
|
||||
} cc_info;
|
||||
} __packed;
|
||||
|
||||
struct wmi_11d_scan_start_params {
|
||||
u32 vdev_id;
|
||||
u32 scan_period_msec;
|
||||
u32 start_interval_msec;
|
||||
};
|
||||
|
||||
struct wmi_11d_scan_start_cmd {
|
||||
u32 tlv_header;
|
||||
u32 vdev_id;
|
||||
u32 scan_period_msec;
|
||||
u32 start_interval_msec;
|
||||
} __packed;
|
||||
|
||||
struct wmi_11d_scan_stop_cmd {
|
||||
u32 tlv_header;
|
||||
u32 vdev_id;
|
||||
} __packed;
|
||||
|
||||
struct wmi_11d_new_cc_ev {
|
||||
u32 new_alpha2;
|
||||
} __packed;
|
||||
|
||||
#define THERMAL_LEVELS 1
|
||||
struct tt_level_config {
|
||||
u32 tmplwm;
|
||||
@ -5433,9 +5478,16 @@ int ath11k_wmi_delba_send(struct ath11k *ar, u32 vdev_id, const u8 *mac,
|
||||
u32 tid, u32 initiator, u32 reason);
|
||||
int ath11k_wmi_send_bcn_offload_control_cmd(struct ath11k *ar,
|
||||
u32 vdev_id, u32 bcn_ctrl_op);
|
||||
int ath11k_wmi_send_set_current_country_cmd(struct ath11k *ar,
|
||||
struct wmi_set_current_country_params *param);
|
||||
int
|
||||
ath11k_wmi_send_init_country_cmd(struct ath11k *ar,
|
||||
struct wmi_init_country_params init_cc_param);
|
||||
|
||||
int ath11k_wmi_send_11d_scan_start_cmd(struct ath11k *ar,
|
||||
struct wmi_11d_scan_start_params *param);
|
||||
int ath11k_wmi_send_11d_scan_stop_cmd(struct ath11k *ar, u32 vdev_id);
|
||||
|
||||
int
|
||||
ath11k_wmi_send_thermal_mitigation_param_cmd(struct ath11k *ar,
|
||||
struct thermal_mitigation_params *param);
|
||||
@ -5492,5 +5544,6 @@ int ath11k_wmi_set_hw_mode(struct ath11k_base *ab,
|
||||
enum wmi_host_hw_mode_config_type mode);
|
||||
int ath11k_wmi_wow_host_wakeup_ind(struct ath11k *ar);
|
||||
int ath11k_wmi_wow_enable(struct ath11k *ar);
|
||||
|
||||
int ath11k_wmi_scan_prob_req_oui(struct ath11k *ar,
|
||||
const u8 mac_addr[ETH_ALEN]);
|
||||
#endif
|
||||
|
@ -153,12 +153,19 @@
|
||||
* implementations.
|
||||
*/
|
||||
struct htc_frame_hdr {
|
||||
u8 eid;
|
||||
u8 flags;
|
||||
struct_group_tagged(htc_frame_look_ahead, header,
|
||||
union {
|
||||
struct {
|
||||
u8 eid;
|
||||
u8 flags;
|
||||
|
||||
/* length of data (including trailer) that follows the header */
|
||||
__le16 payld_len;
|
||||
/* length of data (including trailer) that follows the header */
|
||||
__le16 payld_len;
|
||||
|
||||
};
|
||||
u32 word;
|
||||
};
|
||||
);
|
||||
/* end of 4-byte lookahead */
|
||||
|
||||
u8 ctrl[2];
|
||||
|
@ -2260,19 +2260,16 @@ int ath6kl_htc_rxmsg_pending_handler(struct htc_target *target,
|
||||
static struct htc_packet *htc_wait_for_ctrl_msg(struct htc_target *target)
|
||||
{
|
||||
struct htc_packet *packet = NULL;
|
||||
struct htc_frame_hdr *htc_hdr;
|
||||
u32 look_ahead;
|
||||
struct htc_frame_look_ahead look_ahead;
|
||||
|
||||
if (ath6kl_hif_poll_mboxmsg_rx(target->dev, &look_ahead,
|
||||
if (ath6kl_hif_poll_mboxmsg_rx(target->dev, &look_ahead.word,
|
||||
HTC_TARGET_RESPONSE_TIMEOUT))
|
||||
return NULL;
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_HTC,
|
||||
"htc rx wait ctrl look_ahead 0x%X\n", look_ahead);
|
||||
"htc rx wait ctrl look_ahead 0x%X\n", look_ahead.word);
|
||||
|
||||
htc_hdr = (struct htc_frame_hdr *)&look_ahead;
|
||||
|
||||
if (htc_hdr->eid != ENDPOINT_0)
|
||||
if (look_ahead.eid != ENDPOINT_0)
|
||||
return NULL;
|
||||
|
||||
packet = htc_get_control_buf(target, false);
|
||||
@ -2281,8 +2278,8 @@ static struct htc_packet *htc_wait_for_ctrl_msg(struct htc_target *target)
|
||||
return NULL;
|
||||
|
||||
packet->info.rx.rx_flags = 0;
|
||||
packet->info.rx.exp_hdr = look_ahead;
|
||||
packet->act_len = le16_to_cpu(htc_hdr->payld_len) + HTC_HDR_LENGTH;
|
||||
packet->info.rx.exp_hdr = look_ahead.word;
|
||||
packet->act_len = le16_to_cpu(look_ahead.payld_len) + HTC_HDR_LENGTH;
|
||||
|
||||
if (packet->act_len > packet->buf_len)
|
||||
goto fail_ctrl_rx;
|
||||
|
@ -154,11 +154,52 @@ static void ath_send_bar(struct ath_atx_tid *tid, u16 seqno)
|
||||
seqno << IEEE80211_SEQ_SEQ_SHIFT);
|
||||
}
|
||||
|
||||
static bool ath_merge_ratetbl(struct ieee80211_sta *sta, struct ath_buf *bf,
|
||||
struct ieee80211_tx_info *tx_info)
|
||||
{
|
||||
struct ieee80211_sta_rates *ratetbl;
|
||||
u8 i;
|
||||
|
||||
if (!sta)
|
||||
return false;
|
||||
|
||||
ratetbl = rcu_dereference(sta->rates);
|
||||
if (!ratetbl)
|
||||
return false;
|
||||
|
||||
if (tx_info->control.rates[0].idx < 0 ||
|
||||
tx_info->control.rates[0].count == 0)
|
||||
{
|
||||
i = 0;
|
||||
} else {
|
||||
bf->rates[0] = tx_info->control.rates[0];
|
||||
i = 1;
|
||||
}
|
||||
|
||||
for ( ; i < IEEE80211_TX_MAX_RATES; i++) {
|
||||
bf->rates[i].idx = ratetbl->rate[i].idx;
|
||||
bf->rates[i].flags = ratetbl->rate[i].flags;
|
||||
if (tx_info->control.use_rts)
|
||||
bf->rates[i].count = ratetbl->rate[i].count_rts;
|
||||
else if (tx_info->control.use_cts_prot)
|
||||
bf->rates[i].count = ratetbl->rate[i].count_cts;
|
||||
else
|
||||
bf->rates[i].count = ratetbl->rate[i].count;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ath_set_rates(struct ieee80211_vif *vif, struct ieee80211_sta *sta,
|
||||
struct ath_buf *bf)
|
||||
{
|
||||
ieee80211_get_tx_rates(vif, sta, bf->bf_mpdu, bf->rates,
|
||||
ARRAY_SIZE(bf->rates));
|
||||
struct ieee80211_tx_info *tx_info;
|
||||
|
||||
tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
|
||||
|
||||
if (!ath_merge_ratetbl(sta, bf, tx_info))
|
||||
ieee80211_get_tx_rates(vif, sta, bf->bf_mpdu, bf->rates,
|
||||
ARRAY_SIZE(bf->rates));
|
||||
}
|
||||
|
||||
static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq,
|
||||
|
@ -307,8 +307,7 @@ static void carl9170_zap_queues(struct ar9170 *ar)
|
||||
for (i = 0; i < ar->hw->queues; i++)
|
||||
ar->tx_stats[i].limit = CARL9170_NUM_TX_LIMIT_HARD;
|
||||
|
||||
for (i = 0; i < DIV_ROUND_UP(ar->fw.mem_blocks, BITS_PER_LONG); i++)
|
||||
ar->mem_bitmap[i] = 0;
|
||||
bitmap_zero(ar->mem_bitmap, ar->fw.mem_blocks);
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(cvif, &ar->vif_list, list) {
|
||||
@ -1968,9 +1967,7 @@ int carl9170_register(struct ar9170 *ar)
|
||||
if (WARN_ON(ar->mem_bitmap))
|
||||
return -EINVAL;
|
||||
|
||||
ar->mem_bitmap = kcalloc(roundup(ar->fw.mem_blocks, BITS_PER_LONG),
|
||||
sizeof(unsigned long),
|
||||
GFP_KERNEL);
|
||||
ar->mem_bitmap = bitmap_zalloc(ar->fw.mem_blocks, GFP_KERNEL);
|
||||
|
||||
if (!ar->mem_bitmap)
|
||||
return -ENOMEM;
|
||||
@ -2085,7 +2082,7 @@ void carl9170_free(struct ar9170 *ar)
|
||||
kfree_skb(ar->rx_failover);
|
||||
ar->rx_failover = NULL;
|
||||
|
||||
kfree(ar->mem_bitmap);
|
||||
bitmap_free(ar->mem_bitmap);
|
||||
ar->mem_bitmap = NULL;
|
||||
|
||||
kfree(ar->survey);
|
||||
|
@ -126,6 +126,7 @@ enum CountryCode {
|
||||
CTRY_KOREA_ROC = 410,
|
||||
CTRY_KOREA_ROC2 = 411,
|
||||
CTRY_KOREA_ROC3 = 412,
|
||||
CTRY_KOREA_ROC4 = 413,
|
||||
CTRY_KUWAIT = 414,
|
||||
CTRY_LATVIA = 428,
|
||||
CTRY_LEBANON = 422,
|
||||
|
@ -76,6 +76,7 @@ enum EnumRd {
|
||||
APL7_FCCA = 0x5C,
|
||||
APL8_WORLD = 0x5D,
|
||||
APL9_WORLD = 0x5E,
|
||||
APL10_WORLD = 0x5F,
|
||||
|
||||
WOR0_WORLD = 0x60,
|
||||
WOR1_WORLD = 0x61,
|
||||
@ -204,6 +205,7 @@ static struct reg_dmn_pair_mapping regDomainPairs[] = {
|
||||
{APL6_WORLD, CTL_ETSI, CTL_ETSI},
|
||||
{APL8_WORLD, CTL_ETSI, CTL_ETSI},
|
||||
{APL9_WORLD, CTL_ETSI, CTL_ETSI},
|
||||
{APL10_WORLD, CTL_ETSI, CTL_ETSI},
|
||||
|
||||
{APL3_FCCA, CTL_FCC, CTL_FCC},
|
||||
{APL7_FCCA, CTL_FCC, CTL_FCC},
|
||||
@ -426,6 +428,7 @@ static struct country_code_to_enum_rd allCountries[] = {
|
||||
{CTRY_KOREA_ROC, APL9_WORLD, "KR"},
|
||||
{CTRY_KOREA_ROC2, APL2_WORLD, "K2"},
|
||||
{CTRY_KOREA_ROC3, APL9_WORLD, "K3"},
|
||||
{CTRY_KOREA_ROC4, APL10_WORLD, "K4"},
|
||||
{CTRY_KUWAIT, ETSI3_WORLD, "KW"},
|
||||
{CTRY_LATVIA, ETSI1_WORLD, "LV"},
|
||||
{CTRY_LEBANON, NULL1_WORLD, "LB"},
|
||||
|
@ -3459,9 +3459,6 @@ struct wcn36xx_hal_missed_beacon_ind_msg {
|
||||
|
||||
/* Beacon Filtering data structures */
|
||||
|
||||
/* The above structure would be followed by multiple of below mentioned
|
||||
* structure
|
||||
*/
|
||||
struct beacon_filter_ie {
|
||||
u8 element_id;
|
||||
u8 check_ie_presence;
|
||||
@ -3469,7 +3466,27 @@ struct beacon_filter_ie {
|
||||
u8 value;
|
||||
u8 bitmask;
|
||||
u8 ref;
|
||||
};
|
||||
} __packed;
|
||||
|
||||
#define WCN36XX_FILTER_CAPABILITY_MASK 0x73cf
|
||||
#define WCN36XX_FILTER_IE_DS_CHANNEL_MASK 0x00
|
||||
#define WCN36XX_FILTER_IE_ERP_FILTER_MASK 0xF8
|
||||
#define WCN36XX_FILTER_IE_EDCA_FILTER_MASK 0xF0
|
||||
#define WCN36XX_FILTER_IE_QOS_FILTER_MASK 0xF0
|
||||
#define WCN36XX_FILTER_IE_CHANNEL_SWITCH_MASK 0x00
|
||||
#define WCN36XX_FILTER_IE_HT_BYTE0_FILTER_MASK 0x00
|
||||
#define WCN36XX_FILTER_IE_HT_BYTE1_FILTER_MASK 0xF8
|
||||
#define WCN36XX_FILTER_IE_HT_BYTE2_FILTER_MASK 0xEB
|
||||
#define WCN36XX_FILTER_IE_HT_BYTE5_FILTER_MASK 0xFD
|
||||
#define WCN36XX_FILTER_IE_PWR_CONSTRAINT_MASK 0x00
|
||||
#define WCN36XX_FILTER_IE_OPMODE_NOTIF_MASK 0x00
|
||||
#define WCN36XX_FILTER_IE_VHTOP_CHWIDTH_MASK 0xFC
|
||||
#define WCN36XX_FILTER_IE_RSN_MASK 0x00
|
||||
#define WCN36XX_FILTER_IE_VENDOR_MASK 0x00
|
||||
|
||||
/* The above structure would be followed by multiple of below mentioned
|
||||
* structure
|
||||
*/
|
||||
|
||||
struct wcn36xx_hal_add_bcn_filter_req_msg {
|
||||
struct wcn36xx_hal_msg_header header;
|
||||
@ -3480,14 +3497,14 @@ struct wcn36xx_hal_add_bcn_filter_req_msg {
|
||||
u16 ie_num;
|
||||
u8 bss_index;
|
||||
u8 reserved;
|
||||
};
|
||||
} __packed;
|
||||
|
||||
struct wcn36xx_hal_rem_bcn_filter_req {
|
||||
struct wcn36xx_hal_msg_header header;
|
||||
|
||||
u8 ie_Count;
|
||||
u8 rem_ie_id[1];
|
||||
};
|
||||
} __packed;
|
||||
|
||||
#define WCN36XX_HAL_IPV4_ARP_REPLY_OFFLOAD 0
|
||||
#define WCN36XX_HAL_IPV6_NEIGHBOR_DISCOVERY_OFFLOAD 1
|
||||
|
@ -934,6 +934,8 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
|
||||
* place where AID is available.
|
||||
*/
|
||||
wcn36xx_smd_config_sta(wcn, vif, sta);
|
||||
if (vif->type == NL80211_IFTYPE_STATION)
|
||||
wcn36xx_smd_add_beacon_filter(wcn, vif);
|
||||
wcn36xx_enable_keep_alive_null_packet(wcn, vif);
|
||||
} else {
|
||||
wcn36xx_dbg(WCN36XX_DBG_MAC,
|
||||
@ -1220,7 +1222,7 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
|
||||
u16 tid = params->tid;
|
||||
u16 *ssn = ¶ms->ssn;
|
||||
int ret = 0;
|
||||
u8 session;
|
||||
int session;
|
||||
|
||||
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n",
|
||||
action, tid);
|
||||
@ -1232,9 +1234,11 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
|
||||
sta_priv->tid = tid;
|
||||
session = wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 0,
|
||||
get_sta_index(vif, sta_priv));
|
||||
if (session < 0) {
|
||||
ret = session;
|
||||
goto out;
|
||||
}
|
||||
wcn36xx_smd_add_ba(wcn, session);
|
||||
wcn36xx_smd_trigger_ba(wcn, get_sta_index(vif, sta_priv), tid,
|
||||
session);
|
||||
break;
|
||||
case IEEE80211_AMPDU_RX_STOP:
|
||||
wcn36xx_smd_del_ba(wcn, tid, 0, get_sta_index(vif, sta_priv));
|
||||
@ -1244,6 +1248,18 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
|
||||
sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_START;
|
||||
spin_unlock_bh(&sta_priv->ampdu_lock);
|
||||
|
||||
/* Replace the mac80211 ssn with the firmware one */
|
||||
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu ssn = %u\n", *ssn);
|
||||
wcn36xx_smd_trigger_ba(wcn, get_sta_index(vif, sta_priv), tid, ssn);
|
||||
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu fw-ssn = %u\n", *ssn);
|
||||
|
||||
/* Start BA session */
|
||||
session = wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 1,
|
||||
get_sta_index(vif, sta_priv));
|
||||
if (session < 0) {
|
||||
ret = session;
|
||||
goto out;
|
||||
}
|
||||
ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_OPERATIONAL:
|
||||
@ -1251,8 +1267,6 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
|
||||
sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_OPERATIONAL;
|
||||
spin_unlock_bh(&sta_priv->ampdu_lock);
|
||||
|
||||
wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 1,
|
||||
get_sta_index(vif, sta_priv));
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH:
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
|
||||
@ -1268,6 +1282,7 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
|
||||
wcn36xx_err("Unknown AMPDU action\n");
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&wcn->conf_mutex);
|
||||
|
||||
return ret;
|
||||
|
@ -944,7 +944,7 @@ int wcn36xx_smd_update_channel_list(struct wcn36xx *wcn, struct cfg80211_scan_re
|
||||
|
||||
INIT_HAL_MSG((*msg_body), WCN36XX_HAL_UPDATE_CHANNEL_LIST_REQ);
|
||||
|
||||
msg_body->num_channel = min_t(u8, req->n_channels, sizeof(msg_body->channels));
|
||||
msg_body->num_channel = min_t(u8, req->n_channels, ARRAY_SIZE(msg_body->channels));
|
||||
for (i = 0; i < msg_body->num_channel; i++) {
|
||||
struct wcn36xx_hal_channel_param *param = &msg_body->channels[i];
|
||||
u32 min_power = WCN36XX_HAL_DEFAULT_MIN_POWER;
|
||||
@ -2561,6 +2561,7 @@ int wcn36xx_smd_add_ba_session(struct wcn36xx *wcn,
|
||||
&session_id);
|
||||
if (ret) {
|
||||
wcn36xx_err("hal_add_ba_session response failed err=%d\n", ret);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -2626,27 +2627,43 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wcn36xx_smd_trigger_ba_rsp(void *buf, int len)
|
||||
static int wcn36xx_smd_trigger_ba_rsp(void *buf, int len, struct add_ba_info *ba_info)
|
||||
{
|
||||
struct wcn36xx_hal_trigger_ba_rsp_candidate *candidate;
|
||||
struct wcn36xx_hal_trigger_ba_rsp_msg *rsp;
|
||||
int i;
|
||||
|
||||
if (len < sizeof(*rsp))
|
||||
return -EINVAL;
|
||||
|
||||
rsp = (struct wcn36xx_hal_trigger_ba_rsp_msg *) buf;
|
||||
|
||||
if (rsp->candidate_cnt < 1)
|
||||
return rsp->status ? rsp->status : -EINVAL;
|
||||
|
||||
candidate = (struct wcn36xx_hal_trigger_ba_rsp_candidate *)(buf + sizeof(*rsp));
|
||||
|
||||
for (i = 0; i < STACFG_MAX_TC; i++) {
|
||||
ba_info[i] = candidate->ba_info[i];
|
||||
}
|
||||
|
||||
return rsp->status;
|
||||
}
|
||||
|
||||
int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index, u16 tid, u8 session_id)
|
||||
int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index, u16 tid, u16 *ssn)
|
||||
{
|
||||
struct wcn36xx_hal_trigger_ba_req_msg msg_body;
|
||||
struct wcn36xx_hal_trigger_ba_req_candidate *candidate;
|
||||
struct add_ba_info ba_info[STACFG_MAX_TC];
|
||||
int ret;
|
||||
|
||||
if (tid >= STACFG_MAX_TC)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
INIT_HAL_MSG(msg_body, WCN36XX_HAL_TRIGGER_BA_REQ);
|
||||
|
||||
msg_body.session_id = session_id;
|
||||
msg_body.session_id = 0; /* not really used */
|
||||
msg_body.candidate_cnt = 1;
|
||||
msg_body.header.len += sizeof(*candidate);
|
||||
PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
|
||||
@ -2661,13 +2678,17 @@ int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index, u16 tid, u8 sessio
|
||||
wcn36xx_err("Sending hal_trigger_ba failed\n");
|
||||
goto out;
|
||||
}
|
||||
ret = wcn36xx_smd_trigger_ba_rsp(wcn->hal_buf, wcn->hal_rsp_len);
|
||||
ret = wcn36xx_smd_trigger_ba_rsp(wcn->hal_buf, wcn->hal_rsp_len, ba_info);
|
||||
if (ret) {
|
||||
wcn36xx_err("hal_trigger_ba response failed err=%d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&wcn->hal_mutex);
|
||||
|
||||
if (ssn)
|
||||
*ssn = ba_info[tid].starting_seq_num;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -3172,6 +3193,91 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define BEACON_FILTER(eid, presence, offs, val, mask, ref_val) \
|
||||
{ \
|
||||
.element_id = eid, \
|
||||
.check_ie_presence = presence, \
|
||||
.offset = offs, \
|
||||
.value = val, \
|
||||
.bitmask = mask, \
|
||||
.ref = ref_val, \
|
||||
}
|
||||
|
||||
static const struct beacon_filter_ie bcn_filter_ies[] = {
|
||||
BEACON_FILTER(WLAN_EID_DS_PARAMS, 0, 0, 0,
|
||||
WCN36XX_FILTER_IE_DS_CHANNEL_MASK, 0),
|
||||
BEACON_FILTER(WLAN_EID_ERP_INFO, 0, 0, 0,
|
||||
WCN36XX_FILTER_IE_ERP_FILTER_MASK, 0),
|
||||
BEACON_FILTER(WLAN_EID_EDCA_PARAM_SET, 0, 0, 0,
|
||||
WCN36XX_FILTER_IE_EDCA_FILTER_MASK, 0),
|
||||
BEACON_FILTER(WLAN_EID_QOS_CAPA, 0, 0, 0,
|
||||
WCN36XX_FILTER_IE_QOS_FILTER_MASK, 0),
|
||||
BEACON_FILTER(WLAN_EID_CHANNEL_SWITCH, 1, 0, 0,
|
||||
WCN36XX_FILTER_IE_CHANNEL_SWITCH_MASK, 0),
|
||||
BEACON_FILTER(WLAN_EID_HT_OPERATION, 0, 0, 0,
|
||||
WCN36XX_FILTER_IE_HT_BYTE0_FILTER_MASK, 0),
|
||||
BEACON_FILTER(WLAN_EID_HT_OPERATION, 0, 2, 0,
|
||||
WCN36XX_FILTER_IE_HT_BYTE2_FILTER_MASK, 0),
|
||||
BEACON_FILTER(WLAN_EID_HT_OPERATION, 0, 5, 0,
|
||||
WCN36XX_FILTER_IE_HT_BYTE5_FILTER_MASK, 0),
|
||||
BEACON_FILTER(WLAN_EID_PWR_CONSTRAINT, 0, 0, 0,
|
||||
WCN36XX_FILTER_IE_PWR_CONSTRAINT_MASK, 0),
|
||||
BEACON_FILTER(WLAN_EID_OPMODE_NOTIF, 0, 0, 0,
|
||||
WCN36XX_FILTER_IE_OPMODE_NOTIF_MASK, 0),
|
||||
BEACON_FILTER(WLAN_EID_VHT_OPERATION, 0, 0, 0,
|
||||
WCN36XX_FILTER_IE_VHTOP_CHWIDTH_MASK, 0),
|
||||
BEACON_FILTER(WLAN_EID_RSN, 1, 0, 0,
|
||||
WCN36XX_FILTER_IE_RSN_MASK, 0),
|
||||
BEACON_FILTER(WLAN_EID_VENDOR_SPECIFIC, 1, 0, 0,
|
||||
WCN36XX_FILTER_IE_VENDOR_MASK, 0),
|
||||
};
|
||||
|
||||
int wcn36xx_smd_add_beacon_filter(struct wcn36xx *wcn,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct wcn36xx_hal_add_bcn_filter_req_msg msg_body, *body;
|
||||
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
|
||||
u8 *payload;
|
||||
size_t payload_size;
|
||||
int ret;
|
||||
|
||||
if (!get_feat_caps(wcn->fw_feat_caps, BCN_FILTER))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BCN_FILTER_REQ);
|
||||
|
||||
PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
|
||||
|
||||
body = (struct wcn36xx_hal_add_bcn_filter_req_msg *)wcn->hal_buf;
|
||||
body->capability_info = vif->bss_conf.assoc_capability;
|
||||
body->capability_mask = WCN36XX_FILTER_CAPABILITY_MASK;
|
||||
body->beacon_interval = vif->bss_conf.beacon_int;
|
||||
body->ie_num = ARRAY_SIZE(bcn_filter_ies);
|
||||
body->bss_index = vif_priv->bss_index;
|
||||
|
||||
payload = ((u8 *)body) + body->header.len;
|
||||
payload_size = sizeof(bcn_filter_ies);
|
||||
memcpy(payload, &bcn_filter_ies, payload_size);
|
||||
|
||||
body->header.len += payload_size;
|
||||
|
||||
ret = wcn36xx_smd_send_and_wait(wcn, body->header.len);
|
||||
if (ret) {
|
||||
wcn36xx_err("Sending add bcn_filter failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
|
||||
if (ret) {
|
||||
wcn36xx_err("add bcn filter response failed err=%d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&wcn->hal_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wcn36xx_smd_rsp_process(struct rpmsg_device *rpdev,
|
||||
void *buf, int len, void *priv, u32 addr)
|
||||
{
|
||||
@ -3227,6 +3333,7 @@ int wcn36xx_smd_rsp_process(struct rpmsg_device *rpdev,
|
||||
case WCN36XX_HAL_ENTER_IMPS_RSP:
|
||||
case WCN36XX_HAL_EXIT_IMPS_RSP:
|
||||
case WCN36XX_HAL_UPDATE_CHANNEL_LIST_RSP:
|
||||
case WCN36XX_HAL_ADD_BCN_FILTER_RSP:
|
||||
memcpy(wcn->hal_buf, buf, len);
|
||||
wcn->hal_rsp_len = len;
|
||||
complete(&wcn->hal_rsp_compl);
|
||||
|
@ -137,7 +137,7 @@ int wcn36xx_smd_add_ba_session(struct wcn36xx *wcn,
|
||||
u8 sta_index);
|
||||
int wcn36xx_smd_add_ba(struct wcn36xx *wcn, u8 session_id);
|
||||
int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 direction, u8 sta_index);
|
||||
int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index, u16 tid, u8 session_id);
|
||||
int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index, u16 tid, u16 *ssn);
|
||||
|
||||
int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value);
|
||||
|
||||
@ -167,4 +167,7 @@ int wcn36xx_smd_host_resume(struct wcn36xx *wcn);
|
||||
int wcn36xx_smd_enter_imps(struct wcn36xx *wcn);
|
||||
int wcn36xx_smd_exit_imps(struct wcn36xx *wcn);
|
||||
|
||||
int wcn36xx_smd_add_beacon_filter(struct wcn36xx *wcn,
|
||||
struct ieee80211_vif *vif);
|
||||
|
||||
#endif /* _SMD_H_ */
|
||||
|
@ -3908,9 +3908,9 @@ static int brcmf_keepalive_start(struct brcmf_if *ifp, unsigned int interval)
|
||||
|
||||
/* Configure Null function/data keepalive */
|
||||
kalive.version = cpu_to_le16(1);
|
||||
kalive.period_msec = cpu_to_le16(interval * MSEC_PER_SEC);
|
||||
kalive.period_msec = cpu_to_le32(interval * MSEC_PER_SEC);
|
||||
kalive.len_bytes = cpu_to_le16(0);
|
||||
kalive.keep_alive_id = cpu_to_le16(0);
|
||||
kalive.keep_alive_id = 0;
|
||||
|
||||
ret = brcmf_fil_iovar_data_set(ifp, "mkeep_alive", &kalive, sizeof(kalive));
|
||||
if (ret)
|
||||
|
@ -2,6 +2,7 @@
|
||||
config IWLWIFI
|
||||
tristate "Intel Wireless WiFi Next Gen AGN - Wireless-N/Advanced-N/Ultimate-N (iwlwifi) "
|
||||
depends on PCI && HAS_IOMEM && CFG80211
|
||||
depends on IWLMEI || !IWLMEI
|
||||
select FW_LOADER
|
||||
help
|
||||
Select to build the driver supporting the:
|
||||
@ -92,32 +93,6 @@ config IWLWIFI_BCAST_FILTERING
|
||||
If unsure, don't enable this option, as some programs might
|
||||
expect incoming broadcasts for their normal operations.
|
||||
|
||||
config IWLMEI
|
||||
tristate "Intel Management Engine communication over WLAN"
|
||||
depends on INTEL_MEI
|
||||
depends on PM
|
||||
depends on IWLMVM
|
||||
help
|
||||
Enables the iwlmei kernel module.
|
||||
|
||||
CSME stands for Converged Security and Management Engine. It is a CPU
|
||||
on the chipset and runs a dedicated firmware. AMT (Active Management
|
||||
Technology) is one of the applications that run on that CPU. AMT
|
||||
allows to control the platform remotely.
|
||||
|
||||
This kernel module allows to communicate with the Intel Management
|
||||
Engine over Wifi. This is supported starting from Tiger Lake
|
||||
platforms and has been tested on 9260 devices only.
|
||||
If AMT is configured not to use the wireless device, this module is
|
||||
harmless (and useless).
|
||||
Enabling this option on a platform that has a different device and
|
||||
has Wireless enabled on AMT can prevent WiFi from working correctly.
|
||||
|
||||
For more information see
|
||||
<https://software.intel.com/en-us/manageability/>
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
menu "Debugging Options"
|
||||
|
||||
config IWLWIFI_DEBUG
|
||||
@ -172,3 +147,28 @@ config IWLWIFI_DEVICE_TRACING
|
||||
endmenu
|
||||
|
||||
endif
|
||||
|
||||
config IWLMEI
|
||||
tristate "Intel Management Engine communication over WLAN"
|
||||
depends on INTEL_MEI
|
||||
depends on PM
|
||||
help
|
||||
Enables the iwlmei kernel module.
|
||||
|
||||
CSME stands for Converged Security and Management Engine. It is a CPU
|
||||
on the chipset and runs a dedicated firmware. AMT (Active Management
|
||||
Technology) is one of the applications that run on that CPU. AMT
|
||||
allows to control the platform remotely.
|
||||
|
||||
This kernel module allows to communicate with the Intel Management
|
||||
Engine over Wifi. This is supported starting from Tiger Lake
|
||||
platforms and has been tested on 9260 devices only.
|
||||
If AMT is configured not to use the wireless device, this module is
|
||||
harmless (and useless).
|
||||
Enabling this option on a platform that has a different device and
|
||||
has Wireless enabled on AMT can prevent WiFi from working correctly.
|
||||
|
||||
For more information see
|
||||
<https://software.intel.com/en-us/manageability/>
|
||||
|
||||
If unsure, say N.
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include "iwl-prph.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL_22000_UCODE_API_MAX 67
|
||||
#define IWL_22000_UCODE_API_MAX 68
|
||||
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL_22000_UCODE_API_MIN 39
|
||||
@ -54,7 +54,8 @@
|
||||
#define IWL_BZ_A_GF4_A_FW_PRE "iwlwifi-bz-a0-gf4-a0-"
|
||||
#define IWL_BZ_A_MR_A_FW_PRE "iwlwifi-bz-a0-mr-a0-"
|
||||
#define IWL_BZ_A_FM_A_FW_PRE "iwlwifi-bz-a0-fm-a0-"
|
||||
#define IWL_GL_A_FM_A_FW_PRE "iwlwifi-gl-a0-fm7-a0-"
|
||||
#define IWL_GL_A_FM_A_FW_PRE "iwlwifi-gl-a0-fm-a0-"
|
||||
#define IWL_BZ_Z_GF_A_FW_PRE "iwlwifi-bz-z0-gf-a0-"
|
||||
|
||||
|
||||
#define IWL_QU_B_HR_B_MODULE_FIRMWARE(api) \
|
||||
@ -113,6 +114,8 @@
|
||||
IWL_BZ_A_FM_A_FW_PRE __stringify(api) ".ucode"
|
||||
#define IWL_GL_A_FM_A_MODULE_FIRMWARE(api) \
|
||||
IWL_GL_A_FM_A_FW_PRE __stringify(api) ".ucode"
|
||||
#define IWL_BZ_Z_GF_A_MODULE_FIRMWARE(api) \
|
||||
IWL_BZ_Z_GF_A_FW_PRE __stringify(api) ".ucode"
|
||||
|
||||
static const struct iwl_base_params iwl_22000_base_params = {
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
|
||||
@ -626,7 +629,7 @@ const struct iwl_cfg iwl_ax200_cfg_cc = {
|
||||
};
|
||||
|
||||
const struct iwl_cfg killer1650s_2ax_cfg_qu_b0_hr_b0 = {
|
||||
.name = "Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201NGW)",
|
||||
.name = "Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter (201NGW)",
|
||||
.fw_name_pre = IWL_QU_B_HR_B_FW_PRE,
|
||||
IWL_DEVICE_22500,
|
||||
/*
|
||||
@ -639,7 +642,7 @@ const struct iwl_cfg killer1650s_2ax_cfg_qu_b0_hr_b0 = {
|
||||
};
|
||||
|
||||
const struct iwl_cfg killer1650i_2ax_cfg_qu_b0_hr_b0 = {
|
||||
.name = "Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter (201D2W)",
|
||||
.name = "Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201D2W)",
|
||||
.fw_name_pre = IWL_QU_B_HR_B_FW_PRE,
|
||||
IWL_DEVICE_22500,
|
||||
/*
|
||||
@ -652,7 +655,7 @@ const struct iwl_cfg killer1650i_2ax_cfg_qu_b0_hr_b0 = {
|
||||
};
|
||||
|
||||
const struct iwl_cfg killer1650s_2ax_cfg_qu_c0_hr_b0 = {
|
||||
.name = "Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201NGW)",
|
||||
.name = "Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter (201NGW)",
|
||||
.fw_name_pre = IWL_QU_C_HR_B_FW_PRE,
|
||||
IWL_DEVICE_22500,
|
||||
/*
|
||||
@ -665,7 +668,7 @@ const struct iwl_cfg killer1650s_2ax_cfg_qu_c0_hr_b0 = {
|
||||
};
|
||||
|
||||
const struct iwl_cfg killer1650i_2ax_cfg_qu_c0_hr_b0 = {
|
||||
.name = "Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter (201D2W)",
|
||||
.name = "Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201D2W)",
|
||||
.fw_name_pre = IWL_QU_C_HR_B_FW_PRE,
|
||||
IWL_DEVICE_22500,
|
||||
/*
|
||||
@ -696,13 +699,6 @@ const struct iwl_cfg iwlax210_2ax_cfg_so_jf_b0 = {
|
||||
.num_rbds = IWL_NUM_RBDS_NON_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwlax210_2ax_cfg_so_hr_a0 = {
|
||||
.name = "Intel(R) Wi-Fi 6 AX210 160MHz",
|
||||
.fw_name_pre = IWL_SO_A_HR_B_FW_PRE,
|
||||
IWL_DEVICE_AX210,
|
||||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0 = {
|
||||
.name = iwl_ax211_name,
|
||||
.fw_name_pre = IWL_SO_A_GF_A_FW_PRE,
|
||||
@ -879,6 +875,13 @@ const struct iwl_cfg iwl_cfg_gl_a0_fm_a0 = {
|
||||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
};
|
||||
|
||||
const struct iwl_cfg iwl_cfg_bz_z0_gf_a0 = {
|
||||
.fw_name_pre = IWL_BZ_Z_GF_A_FW_PRE,
|
||||
.uhb_supported = true,
|
||||
IWL_DEVICE_BZ,
|
||||
.num_rbds = IWL_NUM_RBDS_AX210_HE,
|
||||
};
|
||||
|
||||
MODULE_FIRMWARE(IWL_QU_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_QNJ_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL_QU_C_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
|
||||
|
@ -1974,12 +1974,8 @@ static void iwl_nic_config(struct iwl_op_mode *op_mode)
|
||||
|
||||
/* SKU Control */
|
||||
iwl_trans_set_bits_mask(priv->trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH |
|
||||
CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP,
|
||||
(CSR_HW_REV_STEP(priv->trans->hw_rev) <<
|
||||
CSR_HW_IF_CONFIG_REG_POS_MAC_STEP) |
|
||||
(CSR_HW_REV_DASH(priv->trans->hw_rev) <<
|
||||
CSR_HW_IF_CONFIG_REG_POS_MAC_DASH));
|
||||
CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP_DASH,
|
||||
CSR_HW_REV_STEP_DASH(priv->trans->hw_rev));
|
||||
|
||||
/* write radio config values to register */
|
||||
if (priv->nvm_data->radio_cfg_type <= EEPROM_RF_CONFIG_TYPE_MAX) {
|
||||
|
@ -789,7 +789,7 @@ int iwl_sar_get_wgds_table(struct iwl_fw_runtime *fwrt)
|
||||
* looking up in ACPI
|
||||
*/
|
||||
if (wifi_pkg->package.count !=
|
||||
min_size + profile_size * num_profiles) {
|
||||
hdr_size + profile_size * num_profiles) {
|
||||
ret = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
@ -852,6 +852,8 @@ read_table:
|
||||
}
|
||||
}
|
||||
|
||||
fwrt->geo_num_profiles = num_profiles;
|
||||
fwrt->geo_enabled = true;
|
||||
ret = 0;
|
||||
out_free:
|
||||
kfree(data);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018, 2020 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018, 2020-2021 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
@ -97,6 +97,21 @@ struct iwl_alive_ntf_v5 {
|
||||
struct iwl_sku_id sku_id;
|
||||
} __packed; /* UCODE_ALIVE_NTFY_API_S_VER_5 */
|
||||
|
||||
struct iwl_imr_alive_info {
|
||||
__le64 base_addr;
|
||||
__le32 size;
|
||||
__le32 enabled;
|
||||
} __packed; /* IMR_ALIVE_INFO_API_S_VER_1 */
|
||||
|
||||
struct iwl_alive_ntf_v6 {
|
||||
__le16 status;
|
||||
__le16 flags;
|
||||
struct iwl_lmac_alive lmac_data[2];
|
||||
struct iwl_umac_alive umac_data;
|
||||
struct iwl_sku_id sku_id;
|
||||
struct iwl_imr_alive_info imr;
|
||||
} __packed; /* UCODE_ALIVE_NTFY_API_S_VER_6 */
|
||||
|
||||
/**
|
||||
* enum iwl_extended_cfg_flag - commands driver may send before
|
||||
* finishing init flow
|
||||
|
@ -51,7 +51,7 @@ enum iwl_legacy_cmds {
|
||||
* @UCODE_ALIVE_NTFY:
|
||||
* Alive data from the firmware, as described in
|
||||
* &struct iwl_alive_ntf_v3 or &struct iwl_alive_ntf_v4 or
|
||||
* &struct iwl_alive_ntf_v5.
|
||||
* &struct iwl_alive_ntf_v5 or &struct iwl_alive_ntf_v6.
|
||||
*/
|
||||
UCODE_ALIVE_NTFY = 0x1,
|
||||
|
||||
@ -72,7 +72,8 @@ enum iwl_legacy_cmds {
|
||||
|
||||
/**
|
||||
* @PHY_CONTEXT_CMD:
|
||||
* Add/modify/remove a PHY context, using &struct iwl_phy_context_cmd.
|
||||
* Add/modify/remove a PHY context, using &struct iwl_phy_context_cmd
|
||||
* or &struct iwl_phy_context_cmd_v1.
|
||||
*/
|
||||
PHY_CONTEXT_CMD = 0x8,
|
||||
|
||||
@ -356,7 +357,7 @@ enum iwl_legacy_cmds {
|
||||
* &struct iwl_notif_statistics_v11,
|
||||
* &struct iwl_notif_statistics_v10,
|
||||
* &struct iwl_notif_statistics,
|
||||
* &struct iwl_statistics_operational_ntfy
|
||||
* &struct iwl_statistics_operational_ntfy_ver_14
|
||||
*/
|
||||
STATISTICS_CMD = 0x9c,
|
||||
|
||||
@ -365,6 +366,7 @@ enum iwl_legacy_cmds {
|
||||
* one of &struct iwl_notif_statistics_v10,
|
||||
* &struct iwl_notif_statistics_v11,
|
||||
* &struct iwl_notif_statistic,
|
||||
* &struct iwl_statistics_operational_ntfy_ver_14
|
||||
* &struct iwl_statistics_operational_ntfy
|
||||
*/
|
||||
STATISTICS_NOTIFICATION = 0x9d,
|
||||
@ -612,6 +614,11 @@ enum iwl_system_subcmd_ids {
|
||||
* @RFI_GET_FREQ_TABLE_CMD: &struct iwl_rfi_config_cmd
|
||||
*/
|
||||
RFI_GET_FREQ_TABLE_CMD = 0xc,
|
||||
|
||||
/**
|
||||
* @SYSTEM_FEATURES_CONTROL_CMD: &struct iwl_system_features_control_cmd
|
||||
*/
|
||||
SYSTEM_FEATURES_CONTROL_CMD = 0xd,
|
||||
};
|
||||
|
||||
#endif /* __iwl_fw_api_commands_h__ */
|
||||
|
@ -554,7 +554,7 @@ struct iwl_wowlan_gtk_status_v1 {
|
||||
} __packed; /* WOWLAN_GTK_MATERIAL_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_wowlan_gtk_status - GTK status
|
||||
* struct iwl_wowlan_gtk_status_v2 - GTK status
|
||||
* @key: GTK material
|
||||
* @key_len: GTK legth, if set to 0, the key is not available
|
||||
* @key_flags: information about the key:
|
||||
@ -565,7 +565,7 @@ struct iwl_wowlan_gtk_status_v1 {
|
||||
* @tkip_mic_key: TKIP RX MIC key
|
||||
* @rsc: TSC RSC counters
|
||||
*/
|
||||
struct iwl_wowlan_gtk_status {
|
||||
struct iwl_wowlan_gtk_status_v2 {
|
||||
u8 key[WOWLAN_KEY_MAX_SIZE];
|
||||
u8 key_len;
|
||||
u8 key_flags;
|
||||
@ -574,6 +574,41 @@ struct iwl_wowlan_gtk_status {
|
||||
struct iwl_wowlan_rsc_tsc_params_cmd_ver_2 rsc;
|
||||
} __packed; /* WOWLAN_GTK_MATERIAL_VER_2 */
|
||||
|
||||
/**
|
||||
* struct iwl_wowlan_all_rsc_tsc_v5 - key counters
|
||||
* @ucast_rsc: unicast RSC values
|
||||
* @mcast_rsc: multicast RSC values (per key map value)
|
||||
* @sta_id: station ID
|
||||
* @mcast_key_id_map: map of key id to @mcast_rsc entry
|
||||
*/
|
||||
struct iwl_wowlan_all_rsc_tsc_v5 {
|
||||
__le64 ucast_rsc[IWL_MAX_TID_COUNT];
|
||||
__le64 mcast_rsc[2][IWL_MAX_TID_COUNT];
|
||||
__le32 sta_id;
|
||||
u8 mcast_key_id_map[4];
|
||||
} __packed; /* ALL_TSC_RSC_API_S_VER_5 */
|
||||
|
||||
/**
|
||||
* struct iwl_wowlan_gtk_status_v3 - GTK status
|
||||
* @key: GTK material
|
||||
* @key_len: GTK length, if set to 0, the key is not available
|
||||
* @key_flags: information about the key:
|
||||
* bits[0:1]: key index assigned by the AP
|
||||
* bits[2:6]: GTK index of the key in the internal DB
|
||||
* bit[7]: Set iff this is the currently used GTK
|
||||
* @reserved: padding
|
||||
* @tkip_mic_key: TKIP RX MIC key
|
||||
* @sc: RSC/TSC counters
|
||||
*/
|
||||
struct iwl_wowlan_gtk_status_v3 {
|
||||
u8 key[WOWLAN_KEY_MAX_SIZE];
|
||||
u8 key_len;
|
||||
u8 key_flags;
|
||||
u8 reserved[2];
|
||||
u8 tkip_mic_key[IWL_MIC_KEY_SIZE];
|
||||
struct iwl_wowlan_all_rsc_tsc_v5 sc;
|
||||
} __packed; /* WOWLAN_GTK_MATERIAL_VER_3 */
|
||||
|
||||
#define IWL_WOWLAN_GTK_IDX_MASK (BIT(0) | BIT(1))
|
||||
|
||||
/**
|
||||
@ -640,7 +675,7 @@ struct iwl_wowlan_status_v6 {
|
||||
* @wake_packet: wakeup packet
|
||||
*/
|
||||
struct iwl_wowlan_status_v7 {
|
||||
struct iwl_wowlan_gtk_status gtk[WOWLAN_GTK_KEYS_NUM];
|
||||
struct iwl_wowlan_gtk_status_v2 gtk[WOWLAN_GTK_KEYS_NUM];
|
||||
struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM];
|
||||
__le64 replay_ctr;
|
||||
__le16 pattern_number;
|
||||
@ -676,7 +711,7 @@ struct iwl_wowlan_status_v7 {
|
||||
* @wake_packet: wakeup packet
|
||||
*/
|
||||
struct iwl_wowlan_status_v9 {
|
||||
struct iwl_wowlan_gtk_status gtk[WOWLAN_GTK_KEYS_NUM];
|
||||
struct iwl_wowlan_gtk_status_v2 gtk[WOWLAN_GTK_KEYS_NUM];
|
||||
struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM];
|
||||
__le64 replay_ctr;
|
||||
__le16 pattern_number;
|
||||
@ -693,6 +728,44 @@ struct iwl_wowlan_status_v9 {
|
||||
u8 wake_packet[]; /* can be truncated from _length to _bufsize */
|
||||
} __packed; /* WOWLAN_STATUSES_RSP_API_S_VER_9 */
|
||||
|
||||
/**
|
||||
* struct iwl_wowlan_status_v12 - WoWLAN status
|
||||
* @gtk: GTK data
|
||||
* @igtk: IGTK data
|
||||
* @replay_ctr: GTK rekey replay counter
|
||||
* @pattern_number: number of the matched pattern
|
||||
* @non_qos_seq_ctr: non-QoS sequence counter to use next.
|
||||
* Reserved if the struct has version >= 10.
|
||||
* @qos_seq_ctr: QoS sequence counters to use next
|
||||
* @wakeup_reasons: wakeup reasons, see &enum iwl_wowlan_wakeup_reason
|
||||
* @num_of_gtk_rekeys: number of GTK rekeys
|
||||
* @transmitted_ndps: number of transmitted neighbor discovery packets
|
||||
* @received_beacons: number of received beacons
|
||||
* @wake_packet_length: wakeup packet length
|
||||
* @wake_packet_bufsize: wakeup packet buffer size
|
||||
* @tid_tear_down: bit mask of tids whose BA sessions were closed
|
||||
* in suspend state
|
||||
* @reserved: unused
|
||||
* @wake_packet: wakeup packet
|
||||
*/
|
||||
struct iwl_wowlan_status_v12 {
|
||||
struct iwl_wowlan_gtk_status_v3 gtk[WOWLAN_GTK_KEYS_NUM];
|
||||
struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM];
|
||||
__le64 replay_ctr;
|
||||
__le16 pattern_number;
|
||||
__le16 non_qos_seq_ctr;
|
||||
__le16 qos_seq_ctr[8];
|
||||
__le32 wakeup_reasons;
|
||||
__le32 num_of_gtk_rekeys;
|
||||
__le32 transmitted_ndps;
|
||||
__le32 received_beacons;
|
||||
__le32 wake_packet_length;
|
||||
__le32 wake_packet_bufsize;
|
||||
u8 tid_tear_down;
|
||||
u8 reserved[3];
|
||||
u8 wake_packet[]; /* can be truncated from _length to _bufsize */
|
||||
} __packed; /* WOWLAN_STATUSES_RSP_API_S_VER_12 */
|
||||
|
||||
/* TODO: NetDetect API */
|
||||
|
||||
#endif /* __iwl_fw_api_d3_h__ */
|
||||
|
@ -31,6 +31,11 @@ enum iwl_data_path_subcmd_ids {
|
||||
*/
|
||||
STA_HE_CTXT_CMD = 0x7,
|
||||
|
||||
/**
|
||||
* @RLC_CONFIG_CMD: &struct iwl_rlc_config_cmd
|
||||
*/
|
||||
RLC_CONFIG_CMD = 0x8,
|
||||
|
||||
/**
|
||||
* @RFH_QUEUE_CONFIG_CMD: &struct iwl_rfh_queue_config
|
||||
*/
|
||||
@ -195,4 +200,61 @@ struct iwl_thermal_dual_chain_request {
|
||||
__le32 event;
|
||||
} __packed; /* THERMAL_DUAL_CHAIN_DISABLE_REQ_NTFY_API_S_VER_1 */
|
||||
|
||||
enum iwl_rlc_chain_info {
|
||||
IWL_RLC_CHAIN_INFO_DRIVER_FORCE = BIT(0),
|
||||
IWL_RLC_CHAIN_INFO_VALID = 0x000e,
|
||||
IWL_RLC_CHAIN_INFO_FORCE = 0x0070,
|
||||
IWL_RLC_CHAIN_INFO_FORCE_MIMO = 0x0380,
|
||||
IWL_RLC_CHAIN_INFO_COUNT = 0x0c00,
|
||||
IWL_RLC_CHAIN_INFO_MIMO_COUNT = 0x3000,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_rlc_properties - RLC properties
|
||||
* @rx_chain_info: RX chain info, &enum iwl_rlc_chain_info
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct iwl_rlc_properties {
|
||||
__le32 rx_chain_info;
|
||||
__le32 reserved;
|
||||
} __packed; /* RLC_PROPERTIES_S_VER_1 */
|
||||
|
||||
enum iwl_sad_mode {
|
||||
IWL_SAD_MODE_ENABLED = BIT(0),
|
||||
IWL_SAD_MODE_DEFAULT_ANT_MSK = 0x6,
|
||||
IWL_SAD_MODE_DEFAULT_ANT_FW = 0x0,
|
||||
IWL_SAD_MODE_DEFAULT_ANT_A = 0x2,
|
||||
IWL_SAD_MODE_DEFAULT_ANT_B = 0x4,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_sad_properties - SAD properties
|
||||
* @chain_a_sad_mode: chain A SAD mode, &enum iwl_sad_mode
|
||||
* @chain_b_sad_mode: chain B SAD mode, &enum iwl_sad_mode
|
||||
* @mac_id: MAC index
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct iwl_sad_properties {
|
||||
__le32 chain_a_sad_mode;
|
||||
__le32 chain_b_sad_mode;
|
||||
__le32 mac_id;
|
||||
__le32 reserved;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_rlc_config_cmd - RLC configuration
|
||||
* @phy_id: PHY index
|
||||
* @rlc: RLC properties, &struct iwl_rlc_properties
|
||||
* @sad: SAD (single antenna diversity) options, &struct iwl_sad_properties
|
||||
* @flags: flags, &enum iwl_rlc_flags
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct iwl_rlc_config_cmd {
|
||||
__le32 phy_id;
|
||||
struct iwl_rlc_properties rlc;
|
||||
struct iwl_sad_properties sad;
|
||||
u8 flags;
|
||||
u8 reserved[3];
|
||||
} __packed; /* RLC_CONFIG_CMD_API_S_VER_2 */
|
||||
|
||||
#endif /* __iwl_fw_api_datapath_h__ */
|
||||
|
@ -7,7 +7,6 @@
|
||||
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#define IWL_FW_INI_HW_SMEM_REGION_ID 15
|
||||
#define IWL_FW_INI_MAX_REGION_ID 64
|
||||
#define IWL_FW_INI_MAX_NAME 32
|
||||
#define IWL_FW_INI_MAX_CFG_NAME 64
|
||||
@ -124,6 +123,9 @@ struct iwl_fw_ini_region_internal_buffer {
|
||||
* @hdr: debug header
|
||||
* @id: region id. Max id is &IWL_FW_INI_MAX_REGION_ID
|
||||
* @type: region type. One of &enum iwl_fw_ini_region_type
|
||||
* @sub_type: region sub type
|
||||
* @sub_type_ver: region sub type
|
||||
* @reserved: not in use
|
||||
* @name: region name
|
||||
* @dev_addr: device address configuration. Used by
|
||||
* &IWL_FW_INI_REGION_DEVICE_MEMORY, &IWL_FW_INI_REGION_PERIPHERY_MAC,
|
||||
@ -146,7 +148,10 @@ struct iwl_fw_ini_region_internal_buffer {
|
||||
struct iwl_fw_ini_region_tlv {
|
||||
struct iwl_fw_ini_header hdr;
|
||||
__le32 id;
|
||||
__le32 type;
|
||||
u8 type;
|
||||
u8 sub_type;
|
||||
u8 sub_type_ver;
|
||||
u8 reserved;
|
||||
u8 name[IWL_FW_INI_MAX_NAME];
|
||||
union {
|
||||
struct iwl_fw_ini_region_dev_addr dev_addr;
|
||||
@ -306,6 +311,7 @@ enum iwl_fw_ini_config_set_type {
|
||||
* @IWL_FW_INI_ALLOCATION_ID_DBGC1: allocation meant for DBGC1 configuration
|
||||
* @IWL_FW_INI_ALLOCATION_ID_DBGC2: allocation meant for DBGC2 configuration
|
||||
* @IWL_FW_INI_ALLOCATION_ID_DBGC3: allocation meant for DBGC3 configuration
|
||||
* @IWL_FW_INI_ALLOCATION_ID_DBGC4: allocation meant for DBGC4 configuration
|
||||
* @IWL_FW_INI_ALLOCATION_NUM: number of allocation ids
|
||||
*/
|
||||
enum iwl_fw_ini_allocation_id {
|
||||
@ -313,6 +319,7 @@ enum iwl_fw_ini_allocation_id {
|
||||
IWL_FW_INI_ALLOCATION_ID_DBGC1,
|
||||
IWL_FW_INI_ALLOCATION_ID_DBGC2,
|
||||
IWL_FW_INI_ALLOCATION_ID_DBGC3,
|
||||
IWL_FW_INI_ALLOCATION_ID_DBGC4,
|
||||
IWL_FW_INI_ALLOCATION_NUM,
|
||||
}; /* FW_DEBUG_TLV_ALLOCATION_ID_E_VER_1 */
|
||||
|
||||
@ -379,6 +386,8 @@ enum iwl_fw_ini_region_type {
|
||||
IWL_FW_INI_REGION_NUM
|
||||
}; /* FW_TLV_DEBUG_REGION_TYPE_API_E */
|
||||
|
||||
#define IWL_FW_INI_REGION_DEVICE_MEMORY_SUBTYPE_HW_SMEM 1
|
||||
|
||||
/**
|
||||
* enum iwl_fw_ini_time_point
|
||||
*
|
||||
|
@ -33,6 +33,11 @@ enum iwl_regulatory_and_nvm_subcmd_ids {
|
||||
*/
|
||||
TAS_CONFIG = 0x3,
|
||||
|
||||
/**
|
||||
* @SAR_OFFSET_MAPPING_TABLE_CMD: &iwl_sar_offset_mapping_cmd
|
||||
*/
|
||||
SAR_OFFSET_MAPPING_TABLE_CMD = 0x4,
|
||||
|
||||
/**
|
||||
* @PNVM_INIT_COMPLETE_NTFY: &struct iwl_pnvm_init_complete_ntfy
|
||||
*/
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018, 2020 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018, 2020-2021 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
@ -150,11 +150,12 @@ struct iwl_phy_context_cmd {
|
||||
/* COMMON_INDEX_HDR_API_S_VER_1 */
|
||||
__le32 id_and_color;
|
||||
__le32 action;
|
||||
/* PHY_CONTEXT_DATA_API_S_VER_3 */
|
||||
/* PHY_CONTEXT_DATA_API_S_VER_3, PHY_CONTEXT_DATA_API_S_VER_4 */
|
||||
struct iwl_fw_channel_info ci;
|
||||
__le32 lmac_id;
|
||||
__le32 rxchain_info;
|
||||
__le32 rxchain_info; /* reserved in _VER_4 */
|
||||
__le32 dsp_cfg_flags;
|
||||
__le32 reserved;
|
||||
} __packed; /* PHY_CONTEXT_CMD_API_VER_3 */
|
||||
} __packed; /* PHY_CONTEXT_CMD_API_VER_3, PHY_CONTEXT_CMD_API_VER_4 */
|
||||
|
||||
#endif /* __iwl_fw_api_phy_ctxt_h__ */
|
||||
|
@ -503,6 +503,20 @@ union iwl_ppag_table_cmd {
|
||||
} v2;
|
||||
} __packed;
|
||||
|
||||
#define MCC_TO_SAR_OFFSET_TABLE_ROW_SIZE 26
|
||||
#define MCC_TO_SAR_OFFSET_TABLE_COL_SIZE 13
|
||||
|
||||
/**
|
||||
* struct iwl_sar_offset_mapping_cmd - struct for SAR_OFFSET_MAPPING_TABLE_CMD
|
||||
* @offset_map: mapping a mcc to a geo sar group
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct iwl_sar_offset_mapping_cmd {
|
||||
u8 offset_map[MCC_TO_SAR_OFFSET_TABLE_ROW_SIZE]
|
||||
[MCC_TO_SAR_OFFSET_TABLE_COL_SIZE];
|
||||
u16 reserved;
|
||||
} __packed; /*SAR_OFFSET_MAPPING_TABLE_CMD_API_S*/
|
||||
|
||||
/**
|
||||
* struct iwl_beacon_filter_cmd
|
||||
* REPLY_BEACON_FILTERING_CMD = 0xd2 (command)
|
||||
|
@ -659,6 +659,19 @@ enum iwl_umac_scan_general_flags_v2 {
|
||||
IWL_UMAC_SCAN_GEN_FLAGS_V2_6GHZ_PASSIVE_SCAN_FILTER_IN = BIT(14),
|
||||
};
|
||||
|
||||
/**
|
||||
* enum iwl_umac_scan_general_params_flags2 - UMAC scan general flags2
|
||||
*
|
||||
* @IWL_UMAC_SCAN_GEN_PARAMS_FLAGS2_RESPECT_P2P_GO_LB: scan event scheduling
|
||||
* should be aware of a P2P GO operation on the 2GHz band.
|
||||
* @IWL_UMAC_SCAN_GEN_PARAMS_FLAGS2_RESPECT_P2P_GO_HB: scan event scheduling
|
||||
* should be aware of a P2P GO operation on the 5GHz or 6GHz band.
|
||||
*/
|
||||
enum iwl_umac_scan_general_params_flags2 {
|
||||
IWL_UMAC_SCAN_GEN_PARAMS_FLAGS2_RESPECT_P2P_GO_LB = BIT(0),
|
||||
IWL_UMAC_SCAN_GEN_PARAMS_FLAGS2_RESPECT_P2P_GO_HB = BIT(1),
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_scan_channel_cfg_umac
|
||||
* @flags: bitmap - 0-19: directed scan to i'th ssid.
|
||||
@ -941,8 +954,8 @@ struct iwl_scan_channel_params_v6 {
|
||||
} __packed; /* SCAN_CHANNEL_PARAMS_API_S_VER_6 */
|
||||
|
||||
/**
|
||||
* struct iwl_scan_general_params_v10
|
||||
* @flags: &enum iwl_umac_scan_flags
|
||||
* struct iwl_scan_general_params_v11
|
||||
* @flags: &enum iwl_umac_scan_general_flags_v2
|
||||
* @reserved: reserved for future
|
||||
* @scan_start_mac_id: report the scan start TSF time according to this mac TSF
|
||||
* @active_dwell: dwell time for active scan per LMAC
|
||||
@ -952,7 +965,8 @@ struct iwl_scan_channel_params_v6 {
|
||||
* for 5GHz channels
|
||||
* @adwell_default_social_chn: adaptive dwell default number of
|
||||
* APs per social channel
|
||||
* @reserved1: reserved for future
|
||||
* @flags2: for version 11 see &enum iwl_umac_scan_general_params_flags2.
|
||||
* Otherwise reserved.
|
||||
* @adwell_max_budget: the maximal number of TUs that adaptive dwell
|
||||
* can add to the total scan time
|
||||
* @max_out_of_time: max out of serving channel time, per LMAC
|
||||
@ -963,7 +977,7 @@ struct iwl_scan_channel_params_v6 {
|
||||
* @num_of_fragments: number of fragments needed for full fragmented
|
||||
* scan coverage.
|
||||
*/
|
||||
struct iwl_scan_general_params_v10 {
|
||||
struct iwl_scan_general_params_v11 {
|
||||
__le16 flags;
|
||||
u8 reserved;
|
||||
u8 scan_start_mac_id;
|
||||
@ -971,14 +985,14 @@ struct iwl_scan_general_params_v10 {
|
||||
u8 adwell_default_2g;
|
||||
u8 adwell_default_5g;
|
||||
u8 adwell_default_social_chn;
|
||||
u8 reserved1;
|
||||
u8 flags2;
|
||||
__le16 adwell_max_budget;
|
||||
__le32 max_out_of_time[SCAN_TWO_LMACS];
|
||||
__le32 suspend_time[SCAN_TWO_LMACS];
|
||||
__le32 scan_priority;
|
||||
u8 passive_dwell[SCAN_TWO_LMACS];
|
||||
u8 num_of_fragments[SCAN_TWO_LMACS];
|
||||
} __packed; /* SCAN_GENERAL_PARAMS_API_S_VER_10 */
|
||||
} __packed; /* SCAN_GENERAL_PARAMS_API_S_VER_11 and *_VER_10 */
|
||||
|
||||
/**
|
||||
* struct iwl_scan_periodic_parms_v1
|
||||
@ -994,31 +1008,31 @@ struct iwl_scan_periodic_parms_v1 {
|
||||
|
||||
/**
|
||||
* struct iwl_scan_req_params_v12
|
||||
* @general_params: &struct iwl_scan_general_params_v10
|
||||
* @general_params: &struct iwl_scan_general_params_v11
|
||||
* @channel_params: &struct iwl_scan_channel_params_v4
|
||||
* @periodic_params: &struct iwl_scan_periodic_parms_v1
|
||||
* @probe_params: &struct iwl_scan_probe_params_v3
|
||||
*/
|
||||
struct iwl_scan_req_params_v12 {
|
||||
struct iwl_scan_general_params_v10 general_params;
|
||||
struct iwl_scan_general_params_v11 general_params;
|
||||
struct iwl_scan_channel_params_v4 channel_params;
|
||||
struct iwl_scan_periodic_parms_v1 periodic_params;
|
||||
struct iwl_scan_probe_params_v3 probe_params;
|
||||
} __packed; /* SCAN_REQUEST_PARAMS_API_S_VER_12 */
|
||||
|
||||
/**
|
||||
* struct iwl_scan_req_params_v14
|
||||
* @general_params: &struct iwl_scan_general_params_v10
|
||||
* struct iwl_scan_req_params_v15
|
||||
* @general_params: &struct iwl_scan_general_params_v11
|
||||
* @channel_params: &struct iwl_scan_channel_params_v6
|
||||
* @periodic_params: &struct iwl_scan_periodic_parms_v1
|
||||
* @probe_params: &struct iwl_scan_probe_params_v4
|
||||
*/
|
||||
struct iwl_scan_req_params_v14 {
|
||||
struct iwl_scan_general_params_v10 general_params;
|
||||
struct iwl_scan_req_params_v15 {
|
||||
struct iwl_scan_general_params_v11 general_params;
|
||||
struct iwl_scan_channel_params_v6 channel_params;
|
||||
struct iwl_scan_periodic_parms_v1 periodic_params;
|
||||
struct iwl_scan_probe_params_v4 probe_params;
|
||||
} __packed; /* SCAN_REQUEST_PARAMS_API_S_VER_14 */
|
||||
} __packed; /* SCAN_REQUEST_PARAMS_API_S_VER_15 and *_VER_14 */
|
||||
|
||||
/**
|
||||
* struct iwl_scan_req_umac_v12
|
||||
@ -1033,16 +1047,16 @@ struct iwl_scan_req_umac_v12 {
|
||||
} __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_12 */
|
||||
|
||||
/**
|
||||
* struct iwl_scan_req_umac_v14
|
||||
* struct iwl_scan_req_umac_v15
|
||||
* @uid: scan id, &enum iwl_umac_scan_uid_offsets
|
||||
* @ooc_priority: out of channel priority - &enum iwl_scan_priority
|
||||
* @scan_params: scan parameters
|
||||
*/
|
||||
struct iwl_scan_req_umac_v14 {
|
||||
struct iwl_scan_req_umac_v15 {
|
||||
__le32 uid;
|
||||
__le32 ooc_priority;
|
||||
struct iwl_scan_req_params_v14 scan_params;
|
||||
} __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_14 */
|
||||
struct iwl_scan_req_params_v15 scan_params;
|
||||
} __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_15 and *_VER_14 */
|
||||
|
||||
/**
|
||||
* struct iwl_umac_scan_abort
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2018, 2020 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2018, 2020 - 2021 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
@ -432,6 +432,7 @@ enum iwl_fw_statistics_type {
|
||||
FW_STATISTICS_HE,
|
||||
}; /* FW_STATISTICS_TYPE_API_E_VER_1 */
|
||||
|
||||
#define IWL_STATISTICS_TYPE_MSK 0x7f
|
||||
/**
|
||||
* struct iwl_statistics_ntfy_hdr
|
||||
*
|
||||
@ -445,11 +446,98 @@ struct iwl_statistics_ntfy_hdr {
|
||||
__le16 size;
|
||||
}; /* STATISTICS_NTFY_HDR_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_statistics_ntfy_per_mac
|
||||
*
|
||||
* @beacon_filter_average_energy: Average energy [-dBm] of the 2
|
||||
* antennas.
|
||||
* @air_time: air time
|
||||
* @beacon_counter: all beacons (both filtered and not filtered)
|
||||
* @beacon_average_energy: all beacons (both filtered and not
|
||||
* filtered)
|
||||
* @beacon_rssi_a: beacon RSSI on antenna A
|
||||
* @beacon_rssi_b: beacon RSSI on antenna B
|
||||
* @rx_bytes: RX byte count
|
||||
*/
|
||||
struct iwl_statistics_ntfy_per_mac {
|
||||
__le32 beacon_filter_average_energy;
|
||||
__le32 air_time;
|
||||
__le32 beacon_counter;
|
||||
__le32 beacon_average_energy;
|
||||
__le32 beacon_rssi_a;
|
||||
__le32 beacon_rssi_b;
|
||||
__le32 rx_bytes;
|
||||
} __packed; /* STATISTICS_NTFY_PER_MAC_API_S_VER_1 */
|
||||
|
||||
#define IWL_STATS_MAX_BW_INDEX 5
|
||||
/** struct iwl_statistics_ntfy_per_phy
|
||||
* @channel_load: channel load
|
||||
* @channel_load_by_us: device contribution to MCLM
|
||||
* @channel_load_not_by_us: other devices' contribution to MCLM
|
||||
* @clt: CLT HW timer (TIM_CH_LOAD2)
|
||||
* @act: active accumulator SW
|
||||
* @elp: elapsed time accumulator SW
|
||||
* @rx_detected_per_ch_width: number of deferred TX per channel width,
|
||||
* 0 - 20, 1/2/3 - 40/80/160
|
||||
* @success_per_ch_width: number of frames that got ACK/BACK/CTS
|
||||
* per channel BW. note, BACK counted as 1
|
||||
* @fail_per_ch_width: number of frames that didn't get ACK/BACK/CTS
|
||||
* per channel BW. note BACK counted as 1
|
||||
* @last_tx_ch_width_indx: last txed frame channel width index
|
||||
*/
|
||||
struct iwl_statistics_ntfy_per_phy {
|
||||
__le32 channel_load;
|
||||
__le32 channel_load_by_us;
|
||||
__le32 channel_load_not_by_us;
|
||||
__le32 clt;
|
||||
__le32 act;
|
||||
__le32 elp;
|
||||
__le32 rx_detected_per_ch_width[IWL_STATS_MAX_BW_INDEX];
|
||||
__le32 success_per_ch_width[IWL_STATS_MAX_BW_INDEX];
|
||||
__le32 fail_per_ch_width[IWL_STATS_MAX_BW_INDEX];
|
||||
__le32 last_tx_ch_width_indx;
|
||||
} __packed; /* STATISTICS_NTFY_PER_PHY_API_S_VER_1 */
|
||||
|
||||
/**
|
||||
* struct iwl_statistics_ntfy_per_sta
|
||||
*
|
||||
* @average_energy: in fact it is minus the energy..
|
||||
*/
|
||||
struct iwl_statistics_ntfy_per_sta {
|
||||
__le32 average_energy;
|
||||
} __packed; /* STATISTICS_NTFY_PER_STA_API_S_VER_1 */
|
||||
|
||||
#define IWL_STATS_MAX_PHY_OPERTINAL 3
|
||||
/**
|
||||
* struct iwl_statistics_operational_ntfy
|
||||
*
|
||||
* @hdr: general statistics header
|
||||
* @flags: bitmap of possible notification structures
|
||||
* @per_mac_stats: per mac statistics, &struct iwl_statistics_ntfy_per_mac
|
||||
* @per_phy_stats: per phy statistics, &struct iwl_statistics_ntfy_per_phy
|
||||
* @per_sta_stats: per sta statistics, &struct iwl_statistics_ntfy_per_sta
|
||||
* @rx_time: rx time
|
||||
* @tx_time: usec the radio is transmitting.
|
||||
* @on_time_rf: The total time in usec the RF is awake.
|
||||
* @on_time_scan: usec the radio is awake due to scan.
|
||||
*/
|
||||
struct iwl_statistics_operational_ntfy {
|
||||
struct iwl_statistics_ntfy_hdr hdr;
|
||||
__le32 flags;
|
||||
struct iwl_statistics_ntfy_per_mac per_mac_stats[MAC_INDEX_AUX];
|
||||
struct iwl_statistics_ntfy_per_phy per_phy_stats[IWL_STATS_MAX_PHY_OPERTINAL];
|
||||
struct iwl_statistics_ntfy_per_sta per_sta_stats[IWL_MVM_STATION_COUNT_MAX];
|
||||
__le64 rx_time;
|
||||
__le64 tx_time;
|
||||
__le64 on_time_rf;
|
||||
__le64 on_time_scan;
|
||||
} __packed; /* STATISTICS_OPERATIONAL_NTFY_API_S_VER_15 */
|
||||
|
||||
/**
|
||||
* struct iwl_statistics_operational_ntfy_ver_14
|
||||
*
|
||||
* @hdr: general statistics header
|
||||
* @flags: bitmap of possible notification structures
|
||||
* @mac_id: mac on which the beacon was received
|
||||
* @beacon_filter_average_energy: Average energy [-dBm] of the 2
|
||||
* antennas.
|
||||
@ -469,7 +557,7 @@ struct iwl_statistics_ntfy_hdr {
|
||||
* @average_energy: in fact it is minus the energy..
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct iwl_statistics_operational_ntfy {
|
||||
struct iwl_statistics_operational_ntfy_ver_14 {
|
||||
struct iwl_statistics_ntfy_hdr hdr;
|
||||
__le32 flags;
|
||||
__le32 mac_id;
|
||||
|
@ -1,11 +1,11 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/*
|
||||
* Copyright (C) 2012-2014, 2019-2020 Intel Corporation
|
||||
* Copyright (C) 2012-2014, 2019-2021 Intel Corporation
|
||||
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
|
||||
* Copyright (C) 2016-2017 Intel Deutschland GmbH
|
||||
*/
|
||||
#ifndef __iwl_fw_api_soc_h__
|
||||
#define __iwl_fw_api_soc_h__
|
||||
#ifndef __iwl_fw_api_system_h__
|
||||
#define __iwl_fw_api_system_h__
|
||||
|
||||
#define SOC_CONFIG_CMD_FLAGS_DISCRETE BIT(0)
|
||||
#define SOC_CONFIG_CMD_FLAGS_LOW_LATENCY BIT(1)
|
||||
@ -32,4 +32,12 @@ struct iwl_soc_configuration_cmd {
|
||||
* SOC_CONFIGURATION_CMD_S_VER_2
|
||||
*/
|
||||
|
||||
#endif /* __iwl_fw_api_soc_h__ */
|
||||
/**
|
||||
* struct iwl_system_features_control_cmd - system features control command
|
||||
* @features: bitmap of features to disable
|
||||
*/
|
||||
struct iwl_system_features_control_cmd {
|
||||
__le32 features[4];
|
||||
} __packed; /* SYSTEM_FEATURES_CONTROL_CMD_API_S_VER_1 */
|
||||
|
||||
#endif /* __iwl_fw_api_system_h__ */
|
@ -880,7 +880,7 @@ iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt,
|
||||
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));
|
||||
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,
|
||||
@ -1165,8 +1165,7 @@ static int iwl_dump_ini_dev_mem_iter(struct iwl_fw_runtime *fwrt,
|
||||
iwl_trans_read_mem_bytes(fwrt->trans, addr, range->data,
|
||||
le32_to_cpu(reg->dev_addr.size));
|
||||
|
||||
if ((le32_to_cpu(reg->id) & IWL_FW_INI_REGION_V2_MASK) ==
|
||||
IWL_FW_INI_HW_SMEM_REGION_ID &&
|
||||
if (reg->sub_type == IWL_FW_INI_REGION_DEVICE_MEMORY_SUBTYPE_HW_SMEM &&
|
||||
fwrt->sanitize_ops && fwrt->sanitize_ops->frob_txf)
|
||||
fwrt->sanitize_ops->frob_txf(fwrt->sanitize_ctx,
|
||||
range->data,
|
||||
@ -1988,17 +1987,18 @@ static u32 iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt, struct list_head *list,
|
||||
{
|
||||
struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data;
|
||||
struct iwl_fw_ini_dump_entry *entry;
|
||||
struct iwl_fw_error_dump_data *tlv;
|
||||
struct iwl_fw_ini_error_dump_data *tlv;
|
||||
struct iwl_fw_ini_error_dump_header *header;
|
||||
u32 type = le32_to_cpu(reg->type), id = le32_to_cpu(reg->id);
|
||||
u32 type = reg->type;
|
||||
u32 id = le32_to_cpu(reg->id);
|
||||
u32 num_of_ranges, i, size;
|
||||
void *range;
|
||||
|
||||
/*
|
||||
* The higher part of the ID in version 2 is irrelevant for
|
||||
* The higher part of the ID from 2 is irrelevant for
|
||||
* us, so mask it out.
|
||||
*/
|
||||
if (le32_to_cpu(reg->hdr.version) == 2)
|
||||
if (le32_to_cpu(reg->hdr.version) >= 2)
|
||||
id &= IWL_FW_INI_REGION_V2_MASK;
|
||||
|
||||
if (!ops->get_num_of_ranges || !ops->get_size || !ops->fill_mem_hdr ||
|
||||
@ -2017,6 +2017,9 @@ static u32 iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt, struct list_head *list,
|
||||
|
||||
tlv = (void *)entry->data;
|
||||
tlv->type = reg->type;
|
||||
tlv->sub_type = reg->sub_type;
|
||||
tlv->sub_type_ver = reg->sub_type_ver;
|
||||
tlv->reserved = reg->reserved;
|
||||
tlv->len = cpu_to_le32(size);
|
||||
|
||||
IWL_DEBUG_FW(fwrt, "WRT: Collecting region: id=%d, type=%d\n", id,
|
||||
@ -2099,7 +2102,7 @@ static u32 iwl_dump_ini_info(struct iwl_fw_runtime *fwrt,
|
||||
dump->ver_type = cpu_to_le32(fwrt->dump.fw_ver.type);
|
||||
dump->ver_subtype = cpu_to_le32(fwrt->dump.fw_ver.subtype);
|
||||
|
||||
dump->hw_step = cpu_to_le32(CSR_HW_REV_STEP(fwrt->trans->hw_rev));
|
||||
dump->hw_step = cpu_to_le32(fwrt->trans->hw_rev_step);
|
||||
|
||||
/*
|
||||
* Several HWs all have type == 0x42, so we'll override this value
|
||||
@ -2291,7 +2294,7 @@ static u32 iwl_dump_ini_trigger(struct iwl_fw_runtime *fwrt,
|
||||
}
|
||||
|
||||
reg = (void *)reg_data.reg_tlv->data;
|
||||
reg_type = le32_to_cpu(reg->type);
|
||||
reg_type = reg->type;
|
||||
if (reg_type >= ARRAY_SIZE(iwl_dump_ini_region_ops))
|
||||
continue;
|
||||
|
||||
|
@ -212,7 +212,9 @@ static void iwl_fwrt_dump_lmac_error_log(struct iwl_fw_runtime *fwrt, u8 lmac_nu
|
||||
IWL_ERR(trans, "HW error, resetting before reading\n");
|
||||
|
||||
/* reset the device */
|
||||
iwl_trans_sw_reset(trans);
|
||||
err = iwl_trans_sw_reset(trans, true);
|
||||
if (err)
|
||||
return;
|
||||
|
||||
err = iwl_finish_nic_init(trans);
|
||||
if (err)
|
||||
|
@ -231,6 +231,24 @@ struct iwl_fw_error_dump_mem {
|
||||
/* Use bit 31 as dump info type to avoid colliding with region types */
|
||||
#define IWL_INI_DUMP_INFO_TYPE BIT(31)
|
||||
|
||||
/**
|
||||
* struct iwl_fw_error_dump_data - data for one type
|
||||
* @type: &enum iwl_fw_ini_region_type
|
||||
* @sub_type: sub type id
|
||||
* @sub_type_ver: sub type version
|
||||
* @reserved: not in use
|
||||
* @len: the length starting from %data
|
||||
* @data: the data itself
|
||||
*/
|
||||
struct iwl_fw_ini_error_dump_data {
|
||||
u8 type;
|
||||
u8 sub_type;
|
||||
u8 sub_type_ver;
|
||||
u8 reserved;
|
||||
__le32 len;
|
||||
__u8 data[];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct iwl_fw_ini_dump_entry
|
||||
* @list: list of dump entries
|
||||
|
@ -8,7 +8,7 @@
|
||||
#include "dbg.h"
|
||||
#include "debugfs.h"
|
||||
|
||||
#include "fw/api/soc.h"
|
||||
#include "fw/api/system.h"
|
||||
#include "fw/api/commands.h"
|
||||
#include "fw/api/rx.h"
|
||||
#include "fw/api/datapath.h"
|
||||
|
@ -156,8 +156,12 @@ struct iwl_fw_runtime {
|
||||
u8 sar_chain_b_profile;
|
||||
struct iwl_geo_profile geo_profiles[ACPI_NUM_GEO_PROFILES_REV3];
|
||||
u32 geo_rev;
|
||||
u32 geo_num_profiles;
|
||||
bool geo_enabled;
|
||||
union iwl_ppag_table_cmd ppag_table;
|
||||
u32 ppag_ver;
|
||||
struct iwl_sar_offset_mapping_cmd sgom_table;
|
||||
bool sgom_enabled;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "fw/uefi.h"
|
||||
#include "fw/api/alive.h"
|
||||
#include <linux/efi.h>
|
||||
#include "fw/runtime.h"
|
||||
|
||||
#define IWL_EFI_VAR_GUID EFI_GUID(0x92daaf2f, 0xc02b, 0x455b, \
|
||||
0xb2, 0xec, 0xf5, 0xa3, \
|
||||
@ -266,3 +267,90 @@ out:
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
static int iwl_uefi_sgom_parse(struct uefi_cnv_wlan_sgom_data *sgom_data,
|
||||
struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (sgom_data->revision != 1)
|
||||
return -EINVAL;
|
||||
|
||||
memcpy(fwrt->sgom_table.offset_map, sgom_data->offset_map,
|
||||
sizeof(fwrt->sgom_table.offset_map));
|
||||
|
||||
for (i = 0; i < MCC_TO_SAR_OFFSET_TABLE_ROW_SIZE; i++) {
|
||||
for (j = 0; j < MCC_TO_SAR_OFFSET_TABLE_COL_SIZE; j++) {
|
||||
/* since each byte is composed of to values, */
|
||||
/* one for each letter, */
|
||||
/* extract and check each of them separately */
|
||||
u8 value = fwrt->sgom_table.offset_map[i][j];
|
||||
u8 low = value & 0xF;
|
||||
u8 high = (value & 0xF0) >> 4;
|
||||
|
||||
if (high > fwrt->geo_num_profiles)
|
||||
high = 0;
|
||||
if (low > fwrt->geo_num_profiles)
|
||||
low = 0;
|
||||
fwrt->sgom_table.offset_map[i][j] = (high << 4) | low;
|
||||
}
|
||||
}
|
||||
|
||||
fwrt->sgom_enabled = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void iwl_uefi_get_sgom_table(struct iwl_trans *trans,
|
||||
struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
struct efivar_entry *sgom_efivar;
|
||||
struct uefi_cnv_wlan_sgom_data *data;
|
||||
unsigned long package_size;
|
||||
int err, ret;
|
||||
|
||||
if (!fwrt->geo_enabled)
|
||||
return;
|
||||
|
||||
sgom_efivar = kzalloc(sizeof(*sgom_efivar), GFP_KERNEL);
|
||||
if (!sgom_efivar)
|
||||
return;
|
||||
|
||||
memcpy(&sgom_efivar->var.VariableName, IWL_UEFI_SGOM_NAME,
|
||||
sizeof(IWL_UEFI_SGOM_NAME));
|
||||
sgom_efivar->var.VendorGuid = IWL_EFI_VAR_GUID;
|
||||
|
||||
/* TODO: we hardcode a maximum length here, because reading
|
||||
* from the UEFI is not working. To implement this properly,
|
||||
* we have to call efivar_entry_size().
|
||||
*/
|
||||
package_size = IWL_HARDCODED_SGOM_SIZE;
|
||||
|
||||
data = kmalloc(package_size, GFP_KERNEL);
|
||||
if (!data) {
|
||||
data = ERR_PTR(-ENOMEM);
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = efivar_entry_get(sgom_efivar, NULL, &package_size, data);
|
||||
if (err) {
|
||||
IWL_DEBUG_FW(trans,
|
||||
"SGOM UEFI variable not found %d\n", err);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
IWL_DEBUG_FW(trans, "Read SGOM from UEFI with size %lu\n",
|
||||
package_size);
|
||||
|
||||
ret = iwl_uefi_sgom_parse(data, fwrt);
|
||||
if (ret < 0)
|
||||
IWL_DEBUG_FW(trans, "Cannot read SGOM tables. rev is invalid\n");
|
||||
|
||||
out_free:
|
||||
kfree(data);
|
||||
|
||||
out:
|
||||
kfree(sgom_efivar);
|
||||
}
|
||||
IWL_EXPORT_SYMBOL(iwl_uefi_get_sgom_table);
|
||||
#endif /* CONFIG_ACPI */
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#define IWL_UEFI_OEM_PNVM_NAME L"UefiCnvWlanOemSignedPnvm"
|
||||
#define IWL_UEFI_REDUCED_POWER_NAME L"UefiCnvWlanReducedPower"
|
||||
#define IWL_UEFI_SGOM_NAME L"UefiCnvWlanSarGeoOffsetMapping"
|
||||
|
||||
/*
|
||||
* TODO: we have these hardcoded values that the caller must pass,
|
||||
@ -16,6 +17,7 @@
|
||||
*/
|
||||
#define IWL_HARDCODED_PNVM_SIZE 4096
|
||||
#define IWL_HARDCODED_REDUCE_POWER_SIZE 32768
|
||||
#define IWL_HARDCODED_SGOM_SIZE 339
|
||||
|
||||
struct pnvm_sku_package {
|
||||
u8 rev;
|
||||
@ -25,6 +27,16 @@ struct pnvm_sku_package {
|
||||
u8 data[];
|
||||
} __packed;
|
||||
|
||||
struct uefi_cnv_wlan_sgom_data {
|
||||
u8 revision;
|
||||
u8 offset_map[IWL_HARDCODED_SGOM_SIZE - 1];
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* This is known to be broken on v4.19 and to work on v5.4. Until we
|
||||
* figure out why this is the case and how to make it work, simply
|
||||
* disable the feature in old kernels.
|
||||
*/
|
||||
#ifdef CONFIG_EFI
|
||||
void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len);
|
||||
void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len);
|
||||
@ -42,4 +54,12 @@ void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len)
|
||||
}
|
||||
#endif /* CONFIG_EFI */
|
||||
|
||||
#if defined(CONFIG_EFI) && defined(CONFIG_ACPI)
|
||||
void iwl_uefi_get_sgom_table(struct iwl_trans *trans, struct iwl_fw_runtime *fwrt);
|
||||
#else
|
||||
static inline
|
||||
void iwl_uefi_get_sgom_table(struct iwl_trans *trans, struct iwl_fw_runtime *fwrt)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
#endif /* __iwl_fw_uefi__ */
|
||||
|
@ -610,7 +610,6 @@ extern const struct iwl_cfg killer1650x_2ax_cfg;
|
||||
extern const struct iwl_cfg killer1650w_2ax_cfg;
|
||||
extern const struct iwl_cfg iwl_qnj_b0_hr_b0_cfg;
|
||||
extern const struct iwl_cfg iwlax210_2ax_cfg_so_jf_b0;
|
||||
extern const struct iwl_cfg iwlax210_2ax_cfg_so_hr_a0;
|
||||
extern const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0;
|
||||
extern const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0_long;
|
||||
extern const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0;
|
||||
@ -634,6 +633,7 @@ extern const struct iwl_cfg iwl_cfg_bz_a0_gf4_a0;
|
||||
extern const struct iwl_cfg iwl_cfg_bz_a0_mr_a0;
|
||||
extern const struct iwl_cfg iwl_cfg_bz_a0_fm_a0;
|
||||
extern const struct iwl_cfg iwl_cfg_gl_a0_fm_a0;
|
||||
extern const struct iwl_cfg iwl_cfg_bz_z0_gf_a0;
|
||||
#endif /* CONFIG_IWLMVM */
|
||||
|
||||
#endif /* __IWL_CONFIG_H__ */
|
||||
|
@ -105,6 +105,10 @@
|
||||
/* GIO Chicken Bits (PCI Express bus link power management) */
|
||||
#define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100)
|
||||
|
||||
#define CSR_IPC_SLEEP_CONTROL (CSR_BASE + 0x114)
|
||||
#define CSR_IPC_SLEEP_CONTROL_SUSPEND 0x3
|
||||
#define CSR_IPC_SLEEP_CONTROL_RESUME 0
|
||||
|
||||
/* Doorbell NMI (since Bz) */
|
||||
#define CSR_DOORBELL_VECTOR (CSR_BASE + 0x130)
|
||||
#define CSR_DOORBELL_VECTOR_NMI BIT(1)
|
||||
@ -143,8 +147,7 @@
|
||||
#define CSR_FUNC_SCRATCH_INIT_VALUE (0x01010101)
|
||||
|
||||
/* Bits for CSR_HW_IF_CONFIG_REG */
|
||||
#define CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH (0x00000003)
|
||||
#define CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP (0x0000000C)
|
||||
#define CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP_DASH (0x0000000F)
|
||||
#define CSR_HW_IF_CONFIG_REG_BIT_MONITOR_SRAM (0x00000080)
|
||||
#define CSR_HW_IF_CONFIG_REG_MSK_BOARD_VER (0x000000C0)
|
||||
#define CSR_HW_IF_CONFIG_REG_BIT_MAC_SI (0x00000100)
|
||||
@ -287,8 +290,7 @@
|
||||
#define CSR_GP_CNTRL_REG_FLAG_SW_RESET BIT(31)
|
||||
|
||||
/* HW REV */
|
||||
#define CSR_HW_REV_DASH(_val) (((_val) & 0x0000003) >> 0)
|
||||
#define CSR_HW_REV_STEP(_val) (((_val) & 0x000000C) >> 2)
|
||||
#define CSR_HW_REV_STEP_DASH(_val) ((_val) & CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP_DASH)
|
||||
#define CSR_HW_REV_TYPE(_val) (((_val) & 0x000FFF0) >> 4)
|
||||
|
||||
/* HW RFID */
|
||||
@ -306,6 +308,7 @@ enum {
|
||||
SILICON_A_STEP = 0,
|
||||
SILICON_B_STEP,
|
||||
SILICON_C_STEP,
|
||||
SILICON_Z_STEP = 0xf,
|
||||
};
|
||||
|
||||
|
||||
@ -328,10 +331,10 @@ enum {
|
||||
#define CSR_HW_REV_TYPE_7265D (0x0000210)
|
||||
#define CSR_HW_REV_TYPE_NONE (0x00001F0)
|
||||
#define CSR_HW_REV_TYPE_QNJ (0x0000360)
|
||||
#define CSR_HW_REV_TYPE_QNJ_B0 (0x0000364)
|
||||
#define CSR_HW_REV_TYPE_QU_B0 (0x0000334)
|
||||
#define CSR_HW_REV_TYPE_QU_C0 (0x0000338)
|
||||
#define CSR_HW_REV_TYPE_QUZ (0x0000354)
|
||||
#define CSR_HW_REV_TYPE_QNJ_B0 (0x0000361)
|
||||
#define CSR_HW_REV_TYPE_QU_B0 (0x0000331)
|
||||
#define CSR_HW_REV_TYPE_QU_C0 (0x0000332)
|
||||
#define CSR_HW_REV_TYPE_QUZ (0x0000351)
|
||||
#define CSR_HW_REV_TYPE_HR_CDB (0x0000340)
|
||||
#define CSR_HW_REV_TYPE_SO (0x0000370)
|
||||
#define CSR_HW_REV_TYPE_TY (0x0000420)
|
||||
|
@ -59,7 +59,7 @@ dbg_ver_table[IWL_DBG_TLV_TYPE_NUM] = {
|
||||
[IWL_DBG_TLV_TYPE_DEBUG_INFO] = {.min_ver = 1, .max_ver = 1,},
|
||||
[IWL_DBG_TLV_TYPE_BUF_ALLOC] = {.min_ver = 1, .max_ver = 1,},
|
||||
[IWL_DBG_TLV_TYPE_HCMD] = {.min_ver = 1, .max_ver = 1,},
|
||||
[IWL_DBG_TLV_TYPE_REGION] = {.min_ver = 1, .max_ver = 2,},
|
||||
[IWL_DBG_TLV_TYPE_REGION] = {.min_ver = 1, .max_ver = 3,},
|
||||
[IWL_DBG_TLV_TYPE_TRIGGER] = {.min_ver = 1, .max_ver = 1,},
|
||||
[IWL_DBG_TLV_TYPE_CONF_SET] = {.min_ver = 1, .max_ver = 1,},
|
||||
};
|
||||
@ -177,14 +177,14 @@ static int iwl_dbg_tlv_alloc_region(struct iwl_trans *trans,
|
||||
const struct iwl_fw_ini_region_tlv *reg = (const void *)tlv->data;
|
||||
struct iwl_ucode_tlv **active_reg;
|
||||
u32 id = le32_to_cpu(reg->id);
|
||||
u32 type = le32_to_cpu(reg->type);
|
||||
u8 type = reg->type;
|
||||
u32 tlv_len = sizeof(*tlv) + le32_to_cpu(tlv->length);
|
||||
|
||||
/*
|
||||
* The higher part of the ID in version 2 is irrelevant for
|
||||
* The higher part of the ID in from version 2 is irrelevant for
|
||||
* us, so mask it out.
|
||||
*/
|
||||
if (le32_to_cpu(reg->hdr.version) == 2)
|
||||
if (le32_to_cpu(reg->hdr.version) >= 2)
|
||||
id &= IWL_FW_INI_REGION_V2_MASK;
|
||||
|
||||
if (le32_to_cpu(tlv->length) < sizeof(*reg))
|
||||
@ -473,7 +473,7 @@ void iwl_dbg_tlv_load_bin(struct device *dev, struct iwl_trans *trans)
|
||||
int res;
|
||||
|
||||
if (!iwlwifi_mod_params.enable_ini ||
|
||||
trans->trans_cfg->device_family <= IWL_DEVICE_FAMILY_9000)
|
||||
trans->trans_cfg->device_family <= IWL_DEVICE_FAMILY_8000)
|
||||
return;
|
||||
|
||||
res = firmware_request_nowarn(&fw, yoyo_bin, dev);
|
||||
@ -1244,7 +1244,7 @@ static void iwl_dbg_tlv_init_cfg(struct iwl_fw_runtime *fwrt)
|
||||
}
|
||||
|
||||
reg = (void *)(*active_reg)->data;
|
||||
reg_type = le32_to_cpu(reg->type);
|
||||
reg_type = reg->type;
|
||||
|
||||
if (reg_type != IWL_FW_INI_REGION_DRAM_BUFFER ||
|
||||
!(BIT(le32_to_cpu(reg->dram_alloc_id)) & failed_alloc))
|
||||
|
@ -163,8 +163,8 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first)
|
||||
char tag[8];
|
||||
|
||||
if (drv->trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_9000 &&
|
||||
(CSR_HW_REV_STEP(drv->trans->hw_rev) != SILICON_B_STEP &&
|
||||
CSR_HW_REV_STEP(drv->trans->hw_rev) != SILICON_C_STEP)) {
|
||||
(drv->trans->hw_rev_step != SILICON_B_STEP &&
|
||||
drv->trans->hw_rev_step != SILICON_C_STEP)) {
|
||||
IWL_ERR(drv,
|
||||
"Only HW steps B and C are currently supported (0x%0x)\n",
|
||||
drv->trans->hw_rev);
|
||||
|
@ -1609,7 +1609,7 @@ int iwl_read_external_nvm(struct iwl_trans *trans,
|
||||
|
||||
/* nvm file validation, dword_buff[2] holds the file version */
|
||||
if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_8000 &&
|
||||
CSR_HW_REV_STEP(trans->hw_rev) == SILICON_C_STEP &&
|
||||
trans->hw_rev_step == SILICON_C_STEP &&
|
||||
le32_to_cpu(dword_buff[2]) < 0xE4A) {
|
||||
ret = -EFAULT;
|
||||
goto out;
|
||||
|
@ -455,6 +455,13 @@ enum {
|
||||
#define UREG_DOORBELL_TO_ISR6_RESUME BIT(19)
|
||||
#define UREG_DOORBELL_TO_ISR6_PNVM BIT(20)
|
||||
|
||||
/*
|
||||
* From BZ family driver triggers this bit for suspend and resume
|
||||
* The driver should update CSR_IPC_SLEEP_CONTROL before triggering
|
||||
* this interrupt with suspend/resume value
|
||||
*/
|
||||
#define UREG_DOORBELL_TO_ISR6_SLEEP_CTRL BIT(31)
|
||||
|
||||
#define CNVI_MBOX_C 0xA3400C
|
||||
|
||||
#define FSEQ_ERROR_CODE 0xA340C8
|
||||
|
@ -296,6 +296,8 @@ enum iwl_d3_status {
|
||||
* are sent
|
||||
* @STATUS_TRANS_IDLE: the trans is idle - general commands are not to be sent
|
||||
* @STATUS_TRANS_DEAD: trans is dead - avoid any read/write operation
|
||||
* @STATUS_SUPPRESS_CMD_ERROR_ONCE: suppress "FW error in SYNC CMD" once,
|
||||
* e.g. for testing
|
||||
*/
|
||||
enum iwl_trans_status {
|
||||
STATUS_SYNC_HCMD_ACTIVE,
|
||||
@ -308,6 +310,7 @@ enum iwl_trans_status {
|
||||
STATUS_TRANS_GOING_IDLE,
|
||||
STATUS_TRANS_IDLE,
|
||||
STATUS_TRANS_DEAD,
|
||||
STATUS_SUPPRESS_CMD_ERROR_ONCE,
|
||||
};
|
||||
|
||||
static inline int
|
||||
@ -593,7 +596,7 @@ struct iwl_trans_ops {
|
||||
void (*configure)(struct iwl_trans *trans,
|
||||
const struct iwl_trans_config *trans_cfg);
|
||||
void (*set_pmi)(struct iwl_trans *trans, bool state);
|
||||
void (*sw_reset)(struct iwl_trans *trans);
|
||||
int (*sw_reset)(struct iwl_trans *trans, bool retake_ownership);
|
||||
bool (*grab_nic_access)(struct iwl_trans *trans);
|
||||
void (*release_nic_access)(struct iwl_trans *trans);
|
||||
void (*set_bits_mask)(struct iwl_trans *trans, u32 reg, u32 mask,
|
||||
@ -938,6 +941,7 @@ struct iwl_trans_txqs {
|
||||
* @hw_id: a u32 with the ID of the device / sub-device.
|
||||
* Set during transport allocation.
|
||||
* @hw_id_str: a string with info about HW ID. Set during transport allocation.
|
||||
* @hw_rev_step: The mac step of the HW
|
||||
* @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
|
||||
@ -971,6 +975,7 @@ struct iwl_trans {
|
||||
struct device *dev;
|
||||
u32 max_skb_frags;
|
||||
u32 hw_rev;
|
||||
u32 hw_rev_step;
|
||||
u32 hw_rf_id;
|
||||
u32 hw_id;
|
||||
char hw_id_str[52];
|
||||
@ -1384,10 +1389,12 @@ static inline void iwl_trans_set_pmi(struct iwl_trans *trans, bool state)
|
||||
trans->ops->set_pmi(trans, state);
|
||||
}
|
||||
|
||||
static inline void iwl_trans_sw_reset(struct iwl_trans *trans)
|
||||
static inline int iwl_trans_sw_reset(struct iwl_trans *trans,
|
||||
bool retake_ownership)
|
||||
{
|
||||
if (trans->ops->sw_reset)
|
||||
trans->ops->sw_reset(trans);
|
||||
return trans->ops->sw_reset(trans, retake_ownership);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
@ -119,6 +119,7 @@ struct iwl_sap_shared_mem_ctrl_blk {
|
||||
struct iwl_mei_shared_mem_ptrs {
|
||||
struct iwl_sap_shared_mem_ctrl_blk *ctrl;
|
||||
void *q_head[SAP_DIRECTION_MAX][SAP_QUEUE_IDX_MAX];
|
||||
size_t q_size[SAP_DIRECTION_MAX][SAP_QUEUE_IDX_MAX];
|
||||
};
|
||||
|
||||
struct iwl_mei_filters {
|
||||
@ -209,7 +210,7 @@ static void iwl_mei_free_shared_mem(struct mei_cl_device *cldev)
|
||||
struct iwl_mei *mei = mei_cldev_get_drvdata(cldev);
|
||||
|
||||
if (mei_cldev_dma_unmap(cldev))
|
||||
dev_err(&cldev->dev, "Coudln't unmap the shared mem properly\n");
|
||||
dev_err(&cldev->dev, "Couldn't unmap the shared mem properly\n");
|
||||
memset(&mei->shared_mem, 0, sizeof(mei->shared_mem));
|
||||
}
|
||||
|
||||
@ -271,6 +272,8 @@ static void iwl_mei_init_shared_mem(struct iwl_mei *mei)
|
||||
mem->q_head[dir][queue] = q_head;
|
||||
q_head +=
|
||||
le32_to_cpu(mem->ctrl->dir[dir].q_ctrl_blk[queue].size);
|
||||
mem->q_size[dir][queue] =
|
||||
le32_to_cpu(mem->ctrl->dir[dir].q_ctrl_blk[queue].size);
|
||||
}
|
||||
}
|
||||
|
||||
@ -280,11 +283,11 @@ static void iwl_mei_init_shared_mem(struct iwl_mei *mei)
|
||||
static ssize_t iwl_mei_write_cyclic_buf(struct mei_cl_device *cldev,
|
||||
struct iwl_sap_q_ctrl_blk *notif_q,
|
||||
u8 *q_head,
|
||||
const struct iwl_sap_hdr *hdr)
|
||||
const struct iwl_sap_hdr *hdr,
|
||||
u32 q_sz)
|
||||
{
|
||||
u32 rd = le32_to_cpu(READ_ONCE(notif_q->rd_ptr));
|
||||
u32 wr = le32_to_cpu(READ_ONCE(notif_q->wr_ptr));
|
||||
u32 q_sz = le32_to_cpu(notif_q->size);
|
||||
size_t room_in_buf;
|
||||
size_t tx_sz = sizeof(*hdr) + le16_to_cpu(hdr->len);
|
||||
|
||||
@ -382,6 +385,7 @@ static int iwl_mei_send_sap_msg_payload(struct mei_cl_device *cldev,
|
||||
struct iwl_sap_q_ctrl_blk *notif_q;
|
||||
struct iwl_sap_dir *dir;
|
||||
void *q_head;
|
||||
u32 q_sz;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&iwl_mei_mutex);
|
||||
@ -404,7 +408,8 @@ static int iwl_mei_send_sap_msg_payload(struct mei_cl_device *cldev,
|
||||
dir = &mei->shared_mem.ctrl->dir[SAP_DIRECTION_HOST_TO_ME];
|
||||
notif_q = &dir->q_ctrl_blk[SAP_QUEUE_IDX_NOTIF];
|
||||
q_head = mei->shared_mem.q_head[SAP_DIRECTION_HOST_TO_ME][SAP_QUEUE_IDX_NOTIF];
|
||||
ret = iwl_mei_write_cyclic_buf(q_head, notif_q, q_head, hdr);
|
||||
q_sz = mei->shared_mem.q_size[SAP_DIRECTION_HOST_TO_ME][SAP_QUEUE_IDX_NOTIF];
|
||||
ret = iwl_mei_write_cyclic_buf(q_head, notif_q, q_head, hdr, q_sz);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@ -454,10 +459,10 @@ void iwl_mei_add_data_to_ring(struct sk_buff *skb, bool cb_tx)
|
||||
dir = &mei->shared_mem.ctrl->dir[SAP_DIRECTION_HOST_TO_ME];
|
||||
notif_q = &dir->q_ctrl_blk[SAP_QUEUE_IDX_DATA];
|
||||
q_head = mei->shared_mem.q_head[SAP_DIRECTION_HOST_TO_ME][SAP_QUEUE_IDX_DATA];
|
||||
q_sz = mei->shared_mem.q_size[SAP_DIRECTION_HOST_TO_ME][SAP_QUEUE_IDX_DATA];
|
||||
|
||||
rd = le32_to_cpu(READ_ONCE(notif_q->rd_ptr));
|
||||
wr = le32_to_cpu(READ_ONCE(notif_q->wr_ptr));
|
||||
q_sz = le32_to_cpu(notif_q->size);
|
||||
hdr_sz = cb_tx ? sizeof(struct iwl_sap_cb_data) :
|
||||
sizeof(struct iwl_sap_hdr);
|
||||
tx_sz = skb->len + hdr_sz;
|
||||
@ -627,6 +632,8 @@ static void iwl_mei_handle_csme_filters(struct mei_cl_device *cldev,
|
||||
lockdep_is_held(&iwl_mei_mutex));
|
||||
|
||||
new_filters = kzalloc(sizeof(*new_filters), GFP_KERNEL);
|
||||
if (!new_filters)
|
||||
return;
|
||||
|
||||
/* Copy the OOB filters */
|
||||
new_filters->filters = filters->filters;
|
||||
@ -1074,11 +1081,11 @@ static void iwl_mei_handle_sap_rx_cmd(struct mei_cl_device *cldev,
|
||||
static void iwl_mei_handle_sap_rx(struct mei_cl_device *cldev,
|
||||
struct iwl_sap_q_ctrl_blk *notif_q,
|
||||
const u8 *q_head,
|
||||
struct sk_buff_head *skbs)
|
||||
struct sk_buff_head *skbs,
|
||||
u32 q_sz)
|
||||
{
|
||||
u32 rd = le32_to_cpu(READ_ONCE(notif_q->rd_ptr));
|
||||
u32 wr = le32_to_cpu(READ_ONCE(notif_q->wr_ptr));
|
||||
u32 q_sz = le32_to_cpu(notif_q->size);
|
||||
ssize_t valid_rx_sz;
|
||||
|
||||
if (rd > q_sz || wr > q_sz) {
|
||||
@ -1110,6 +1117,7 @@ static void iwl_mei_handle_check_shared_area(struct mei_cl_device *cldev)
|
||||
struct sk_buff_head tx_skbs;
|
||||
struct iwl_sap_dir *dir;
|
||||
void *q_head;
|
||||
u32 q_sz;
|
||||
|
||||
if (!mei->shared_mem.ctrl)
|
||||
return;
|
||||
@ -1117,22 +1125,24 @@ static void iwl_mei_handle_check_shared_area(struct mei_cl_device *cldev)
|
||||
dir = &mei->shared_mem.ctrl->dir[SAP_DIRECTION_ME_TO_HOST];
|
||||
notif_q = &dir->q_ctrl_blk[SAP_QUEUE_IDX_NOTIF];
|
||||
q_head = mei->shared_mem.q_head[SAP_DIRECTION_ME_TO_HOST][SAP_QUEUE_IDX_NOTIF];
|
||||
q_sz = mei->shared_mem.q_size[SAP_DIRECTION_ME_TO_HOST][SAP_QUEUE_IDX_NOTIF];
|
||||
|
||||
/*
|
||||
* Do not hold the mutex here, but rather each and every message
|
||||
* handler takes it.
|
||||
* This allows message handlers to take it at a certain time.
|
||||
*/
|
||||
iwl_mei_handle_sap_rx(cldev, notif_q, q_head, NULL);
|
||||
iwl_mei_handle_sap_rx(cldev, notif_q, q_head, NULL, q_sz);
|
||||
|
||||
mutex_lock(&iwl_mei_mutex);
|
||||
dir = &mei->shared_mem.ctrl->dir[SAP_DIRECTION_ME_TO_HOST];
|
||||
notif_q = &dir->q_ctrl_blk[SAP_QUEUE_IDX_DATA];
|
||||
q_head = mei->shared_mem.q_head[SAP_DIRECTION_ME_TO_HOST][SAP_QUEUE_IDX_DATA];
|
||||
q_sz = mei->shared_mem.q_size[SAP_DIRECTION_ME_TO_HOST][SAP_QUEUE_IDX_DATA];
|
||||
|
||||
__skb_queue_head_init(&tx_skbs);
|
||||
|
||||
iwl_mei_handle_sap_rx(cldev, notif_q, q_head, &tx_skbs);
|
||||
iwl_mei_handle_sap_rx(cldev, notif_q, q_head, &tx_skbs, q_sz);
|
||||
|
||||
if (skb_queue_empty(&tx_skbs)) {
|
||||
mutex_unlock(&iwl_mei_mutex);
|
||||
@ -1754,7 +1764,7 @@ static void iwl_mei_dbgfs_register(struct iwl_mei *mei)
|
||||
mei->dbgfs_dir, &iwl_mei_status);
|
||||
debugfs_create_file("send_start_message", S_IWUSR, mei->dbgfs_dir,
|
||||
mei, &iwl_mei_dbgfs_send_start_message_ops);
|
||||
debugfs_create_file("req_ownserhip", S_IWUSR, mei->dbgfs_dir,
|
||||
debugfs_create_file("req_ownership", S_IWUSR, mei->dbgfs_dir,
|
||||
mei, &iwl_mei_dbgfs_req_ownership_ops);
|
||||
}
|
||||
|
||||
|
@ -1390,6 +1390,13 @@ struct iwl_wowlan_status_data {
|
||||
u16 qos_seq_ctr[8];
|
||||
u8 tid_tear_down;
|
||||
|
||||
struct {
|
||||
/* including RX MIC key for TKIP */
|
||||
u8 key[WOWLAN_KEY_MAX_SIZE];
|
||||
u8 len;
|
||||
u8 flags;
|
||||
} gtk;
|
||||
|
||||
struct {
|
||||
/*
|
||||
* We store both the TKIP and AES representations
|
||||
@ -1400,11 +1407,15 @@ struct iwl_wowlan_status_data {
|
||||
struct {
|
||||
struct ieee80211_key_seq seq[IWL_MAX_TID_COUNT];
|
||||
} tkip, aes;
|
||||
/* including RX MIC key for TKIP */
|
||||
u8 key[WOWLAN_KEY_MAX_SIZE];
|
||||
u8 len;
|
||||
u8 flags;
|
||||
} gtk;
|
||||
|
||||
/*
|
||||
* We use -1 for when we have valid data but don't know
|
||||
* the key ID from firmware, and thus it needs to be
|
||||
* installed with the last key (depending on rekeying).
|
||||
*/
|
||||
s8 key_id;
|
||||
bool valid;
|
||||
} gtk_seq[2];
|
||||
|
||||
struct {
|
||||
/* Same as above */
|
||||
@ -1556,12 +1567,10 @@ static void iwl_mvm_report_wakeup_reasons(struct iwl_mvm *mvm,
|
||||
kfree_skb(pkt);
|
||||
}
|
||||
|
||||
static void iwl_mvm_aes_sc_to_seq(struct aes_sc *sc,
|
||||
struct ieee80211_key_seq *seq)
|
||||
static void iwl_mvm_le64_to_aes_seq(__le64 le_pn, struct ieee80211_key_seq *seq)
|
||||
{
|
||||
u64 pn;
|
||||
u64 pn = le64_to_cpu(le_pn);
|
||||
|
||||
pn = le64_to_cpu(sc->pn);
|
||||
seq->ccmp.pn[0] = pn >> 40;
|
||||
seq->ccmp.pn[1] = pn >> 32;
|
||||
seq->ccmp.pn[2] = pn >> 24;
|
||||
@ -1570,6 +1579,20 @@ static void iwl_mvm_aes_sc_to_seq(struct aes_sc *sc,
|
||||
seq->ccmp.pn[5] = pn;
|
||||
}
|
||||
|
||||
static void iwl_mvm_aes_sc_to_seq(struct aes_sc *sc,
|
||||
struct ieee80211_key_seq *seq)
|
||||
{
|
||||
iwl_mvm_le64_to_aes_seq(sc->pn, seq);
|
||||
}
|
||||
|
||||
static void iwl_mvm_le64_to_tkip_seq(__le64 le_pn, struct ieee80211_key_seq *seq)
|
||||
{
|
||||
u64 pn = le64_to_cpu(le_pn);
|
||||
|
||||
seq->tkip.iv16 = (u16)pn;
|
||||
seq->tkip.iv32 = (u32)(pn >> 16);
|
||||
}
|
||||
|
||||
static void iwl_mvm_tkip_sc_to_seq(struct tkip_sc *sc,
|
||||
struct ieee80211_key_seq *seq)
|
||||
{
|
||||
@ -1630,10 +1653,12 @@ static void iwl_mvm_convert_key_counters(struct iwl_wowlan_status_data *status,
|
||||
/* GTK RX counters */
|
||||
for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
|
||||
iwl_mvm_tkip_sc_to_seq(&sc->tkip.multicast_rsc[i],
|
||||
&status->gtk.tkip.seq[i]);
|
||||
&status->gtk_seq[0].tkip.seq[i]);
|
||||
iwl_mvm_aes_sc_to_seq(&sc->aes.multicast_rsc[i],
|
||||
&status->gtk.aes.seq[i]);
|
||||
&status->gtk_seq[0].aes.seq[i]);
|
||||
}
|
||||
status->gtk_seq[0].valid = true;
|
||||
status->gtk_seq[0].key_id = -1;
|
||||
|
||||
/* PTK TX counter */
|
||||
status->ptk.tkip.tx_pn = (u64)le16_to_cpu(sc->tkip.tsc.iv16) |
|
||||
@ -1649,24 +1674,103 @@ static void iwl_mvm_convert_key_counters(struct iwl_wowlan_status_data *status,
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_mvm_set_key_rx_seq(struct iwl_mvm *mvm,
|
||||
struct ieee80211_key_conf *key,
|
||||
struct iwl_wowlan_status_data *status)
|
||||
static void
|
||||
iwl_mvm_convert_key_counters_v5_gtk_seq(struct iwl_wowlan_status_data *status,
|
||||
struct iwl_wowlan_all_rsc_tsc_v5 *sc,
|
||||
unsigned int idx, unsigned int key_id)
|
||||
{
|
||||
int tid;
|
||||
|
||||
for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) {
|
||||
iwl_mvm_le64_to_tkip_seq(sc->mcast_rsc[idx][tid],
|
||||
&status->gtk_seq[idx].tkip.seq[tid]);
|
||||
iwl_mvm_le64_to_aes_seq(sc->mcast_rsc[idx][tid],
|
||||
&status->gtk_seq[idx].aes.seq[tid]);
|
||||
}
|
||||
|
||||
status->gtk_seq[idx].valid = true;
|
||||
status->gtk_seq[idx].key_id = key_id;
|
||||
}
|
||||
|
||||
static void
|
||||
iwl_mvm_convert_key_counters_v5(struct iwl_wowlan_status_data *status,
|
||||
struct iwl_wowlan_all_rsc_tsc_v5 *sc)
|
||||
{
|
||||
int i, tid;
|
||||
|
||||
BUILD_BUG_ON(IWL_MAX_TID_COUNT > IWL_MAX_TID_COUNT);
|
||||
BUILD_BUG_ON(IWL_MAX_TID_COUNT > IWL_NUM_RSC);
|
||||
BUILD_BUG_ON(ARRAY_SIZE(sc->mcast_rsc) != ARRAY_SIZE(status->gtk_seq));
|
||||
|
||||
/* GTK RX counters */
|
||||
for (i = 0; i < ARRAY_SIZE(sc->mcast_key_id_map); i++) {
|
||||
u8 entry = sc->mcast_key_id_map[i];
|
||||
|
||||
if (entry < ARRAY_SIZE(sc->mcast_rsc))
|
||||
iwl_mvm_convert_key_counters_v5_gtk_seq(status, sc,
|
||||
entry, i);
|
||||
}
|
||||
|
||||
/* PTK TX counters not needed, assigned in device */
|
||||
|
||||
/* PTK RX counters */
|
||||
for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) {
|
||||
iwl_mvm_le64_to_tkip_seq(sc->ucast_rsc[tid],
|
||||
&status->ptk.tkip.seq[tid]);
|
||||
iwl_mvm_le64_to_aes_seq(sc->ucast_rsc[tid],
|
||||
&status->ptk.aes.seq[tid]);
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_mvm_set_key_rx_seq_idx(struct ieee80211_key_conf *key,
|
||||
struct iwl_wowlan_status_data *status,
|
||||
int idx)
|
||||
{
|
||||
switch (key->cipher) {
|
||||
case WLAN_CIPHER_SUITE_CCMP:
|
||||
case WLAN_CIPHER_SUITE_GCMP:
|
||||
case WLAN_CIPHER_SUITE_GCMP_256:
|
||||
iwl_mvm_set_key_rx_seq_tids(key, status->gtk.aes.seq);
|
||||
iwl_mvm_set_key_rx_seq_tids(key, status->gtk_seq[idx].aes.seq);
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_TKIP:
|
||||
iwl_mvm_set_key_rx_seq_tids(key, status->gtk.tkip.seq);
|
||||
iwl_mvm_set_key_rx_seq_tids(key, status->gtk_seq[idx].tkip.seq);
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_mvm_set_key_rx_seq(struct ieee80211_key_conf *key,
|
||||
struct iwl_wowlan_status_data *status,
|
||||
bool installed)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(status->gtk_seq); i++) {
|
||||
if (!status->gtk_seq[i].valid)
|
||||
continue;
|
||||
|
||||
/* Handle the case where we know the key ID */
|
||||
if (status->gtk_seq[i].key_id == key->keyidx) {
|
||||
s8 new_key_id = -1;
|
||||
|
||||
if (status->num_of_gtk_rekeys)
|
||||
new_key_id = status->gtk.flags &
|
||||
IWL_WOWLAN_GTK_IDX_MASK;
|
||||
|
||||
/* Don't install a new key's value to an old key */
|
||||
if (new_key_id != key->keyidx)
|
||||
iwl_mvm_set_key_rx_seq_idx(key, status, i);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* handle the case where we didn't, last key only */
|
||||
if (status->gtk_seq[i].key_id == -1 &&
|
||||
(!status->num_of_gtk_rekeys || installed))
|
||||
iwl_mvm_set_key_rx_seq_idx(key, status, i);
|
||||
}
|
||||
}
|
||||
|
||||
struct iwl_mvm_d3_gtk_iter_data {
|
||||
struct iwl_mvm *mvm;
|
||||
struct iwl_wowlan_status_data *status;
|
||||
@ -1740,8 +1844,9 @@ static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
|
||||
|
||||
if (data->status->num_of_gtk_rekeys)
|
||||
ieee80211_remove_key(key);
|
||||
else if (data->last_gtk == key)
|
||||
iwl_mvm_set_key_rx_seq(data->mvm, key, data->status);
|
||||
|
||||
if (data->last_gtk == key)
|
||||
iwl_mvm_set_key_rx_seq(key, data->status, false);
|
||||
}
|
||||
|
||||
static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
|
||||
@ -1825,7 +1930,7 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
|
||||
key = ieee80211_gtk_rekey_add(vif, &conf.conf);
|
||||
if (IS_ERR(key))
|
||||
return false;
|
||||
iwl_mvm_set_key_rx_seq(mvm, key, status);
|
||||
iwl_mvm_set_key_rx_seq(key, status, true);
|
||||
|
||||
replay_ctr = cpu_to_be64(status->replay_ctr);
|
||||
|
||||
@ -1893,9 +1998,10 @@ iwl_mvm_parse_wowlan_status_common_ ## _ver(struct iwl_mvm *mvm, \
|
||||
iwl_mvm_parse_wowlan_status_common(v6)
|
||||
iwl_mvm_parse_wowlan_status_common(v7)
|
||||
iwl_mvm_parse_wowlan_status_common(v9)
|
||||
iwl_mvm_parse_wowlan_status_common(v12)
|
||||
|
||||
static void iwl_mvm_convert_gtk(struct iwl_wowlan_status_data *status,
|
||||
struct iwl_wowlan_gtk_status *data)
|
||||
static void iwl_mvm_convert_gtk_v2(struct iwl_wowlan_status_data *status,
|
||||
struct iwl_wowlan_gtk_status_v2 *data)
|
||||
{
|
||||
BUILD_BUG_ON(sizeof(status->gtk.key) < sizeof(data->key));
|
||||
BUILD_BUG_ON(NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY +
|
||||
@ -1913,6 +2019,26 @@ static void iwl_mvm_convert_gtk(struct iwl_wowlan_status_data *status,
|
||||
data->tkip_mic_key, sizeof(data->tkip_mic_key));
|
||||
}
|
||||
|
||||
static void iwl_mvm_convert_gtk_v3(struct iwl_wowlan_status_data *status,
|
||||
struct iwl_wowlan_gtk_status_v3 *data)
|
||||
{
|
||||
/* The parts we need are identical in v2 and v3 */
|
||||
#define CHECK(_f) do { \
|
||||
BUILD_BUG_ON(offsetof(struct iwl_wowlan_gtk_status_v2, _f) != \
|
||||
offsetof(struct iwl_wowlan_gtk_status_v3, _f)); \
|
||||
BUILD_BUG_ON(offsetofend(struct iwl_wowlan_gtk_status_v2, _f) !=\
|
||||
offsetofend(struct iwl_wowlan_gtk_status_v3, _f)); \
|
||||
} while (0)
|
||||
|
||||
CHECK(key);
|
||||
CHECK(key_len);
|
||||
CHECK(key_flags);
|
||||
CHECK(tkip_mic_key);
|
||||
#undef CHECK
|
||||
|
||||
iwl_mvm_convert_gtk_v2(status, (void *)data);
|
||||
}
|
||||
|
||||
static void iwl_mvm_convert_igtk(struct iwl_wowlan_status_data *status,
|
||||
struct iwl_wowlan_igtk_status *data)
|
||||
{
|
||||
@ -2012,7 +2138,7 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)
|
||||
goto out_free_resp;
|
||||
|
||||
iwl_mvm_convert_key_counters(status, &v7->gtk[0].rsc.all_tsc_rsc);
|
||||
iwl_mvm_convert_gtk(status, &v7->gtk[0]);
|
||||
iwl_mvm_convert_gtk_v2(status, &v7->gtk[0]);
|
||||
iwl_mvm_convert_igtk(status, &v7->igtk[0]);
|
||||
} else if (notif_ver == 9 || notif_ver == 10 || notif_ver == 11) {
|
||||
struct iwl_wowlan_status_v9 *v9 = (void *)cmd.resp_pkt->data;
|
||||
@ -2025,10 +2151,22 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)
|
||||
goto out_free_resp;
|
||||
|
||||
iwl_mvm_convert_key_counters(status, &v9->gtk[0].rsc.all_tsc_rsc);
|
||||
iwl_mvm_convert_gtk(status, &v9->gtk[0]);
|
||||
iwl_mvm_convert_gtk_v2(status, &v9->gtk[0]);
|
||||
iwl_mvm_convert_igtk(status, &v9->igtk[0]);
|
||||
|
||||
status->tid_tear_down = v9->tid_tear_down;
|
||||
} else if (notif_ver == 12) {
|
||||
struct iwl_wowlan_status_v12 *v12 = (void *)cmd.resp_pkt->data;
|
||||
|
||||
status = iwl_mvm_parse_wowlan_status_common_v12(mvm, v12, len);
|
||||
if (IS_ERR(status))
|
||||
goto out_free_resp;
|
||||
|
||||
iwl_mvm_convert_key_counters_v5(status, &v12->gtk[0].sc);
|
||||
iwl_mvm_convert_gtk_v3(status, &v12->gtk[0]);
|
||||
iwl_mvm_convert_igtk(status, &v12->igtk[0]);
|
||||
|
||||
status->tid_tear_down = v12->tid_tear_down;
|
||||
} else {
|
||||
IWL_ERR(mvm,
|
||||
"Firmware advertises unknown WoWLAN status response %d!\n",
|
||||
|
@ -1022,6 +1022,11 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf,
|
||||
if (mvm->fw_restart >= 0)
|
||||
mvm->fw_restart++;
|
||||
|
||||
if (count == 6 && !strcmp(buf, "nolog\n")) {
|
||||
set_bit(IWL_MVM_STATUS_SUPPRESS_ERROR_LOG_ONCE, &mvm->status);
|
||||
set_bit(STATUS_SUPPRESS_CMD_ERROR_ONCE, &mvm->trans->status);
|
||||
}
|
||||
|
||||
/* take the return value to make compiler happy - it will fail anyway */
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm,
|
||||
WIDE_ID(LONG_GROUP, REPLY_ERROR),
|
||||
@ -1038,6 +1043,9 @@ static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mvm *mvm, char *buf,
|
||||
if (!iwl_mvm_firmware_running(mvm))
|
||||
return -EIO;
|
||||
|
||||
if (count == 6 && !strcmp(buf, "nolog\n"))
|
||||
set_bit(IWL_MVM_STATUS_SUPPRESS_ERROR_LOG_ONCE, &mvm->status);
|
||||
|
||||
iwl_force_nmi(mvm->trans);
|
||||
|
||||
return count;
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include "fw/api/datapath.h"
|
||||
#include "fw/api/phy.h"
|
||||
#include "fw/api/config.h"
|
||||
#include "fw/api/soc.h"
|
||||
#include "fw/api/system.h"
|
||||
#include "fw/api/alive.h"
|
||||
#include "fw/api/binding.h"
|
||||
#include "fw/api/cmdhdr.h"
|
||||
|
@ -123,13 +123,15 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
|
||||
struct iwl_lmac_alive *lmac2 = NULL;
|
||||
u16 status;
|
||||
u32 lmac_error_event_table, umac_error_table;
|
||||
u32 version = iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
|
||||
UCODE_ALIVE_NTFY, 0);
|
||||
|
||||
/*
|
||||
* For v5 and above, we can check the version, for older
|
||||
* versions we need to check the size.
|
||||
*/
|
||||
if (iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
|
||||
UCODE_ALIVE_NTFY, 0) == 5) {
|
||||
if (version == 5 || version == 6) {
|
||||
/* v5 and v6 are compatible (only IMR addition) */
|
||||
struct iwl_alive_ntf_v5 *palive;
|
||||
|
||||
if (pkt_len < sizeof(*palive))
|
||||
@ -516,7 +518,6 @@ static void iwl_mvm_phy_filter_init(struct iwl_mvm *mvm,
|
||||
cpu_to_le32(IWL_MVM_PHY_FILTER_CHAIN_D);
|
||||
}
|
||||
}
|
||||
|
||||
#else /* CONFIG_ACPI */
|
||||
|
||||
static void iwl_mvm_phy_filter_init(struct iwl_mvm *mvm,
|
||||
@ -525,6 +526,49 @@ static void iwl_mvm_phy_filter_init(struct iwl_mvm *mvm,
|
||||
}
|
||||
#endif /* CONFIG_ACPI */
|
||||
|
||||
#if defined(CONFIG_ACPI) && defined(CONFIG_EFI)
|
||||
static int iwl_mvm_sgom_init(struct iwl_mvm *mvm)
|
||||
{
|
||||
u8 cmd_ver;
|
||||
int ret;
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = WIDE_ID(REGULATORY_AND_NVM_GROUP,
|
||||
SAR_OFFSET_MAPPING_TABLE_CMD),
|
||||
.flags = 0,
|
||||
.data[0] = &mvm->fwrt.sgom_table,
|
||||
.len[0] = sizeof(mvm->fwrt.sgom_table),
|
||||
.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
|
||||
};
|
||||
|
||||
if (!mvm->fwrt.sgom_enabled) {
|
||||
IWL_DEBUG_RADIO(mvm, "SGOM table is disabled\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, REGULATORY_AND_NVM_GROUP,
|
||||
SAR_OFFSET_MAPPING_TABLE_CMD,
|
||||
IWL_FW_CMD_VER_UNKNOWN);
|
||||
|
||||
if (cmd_ver != 2) {
|
||||
IWL_DEBUG_RADIO(mvm, "command version is unsupported. version = %d\n",
|
||||
cmd_ver);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = iwl_mvm_send_cmd(mvm, &cmd);
|
||||
if (ret < 0)
|
||||
IWL_ERR(mvm, "failed to send SAR_OFFSET_MAPPING_CMD (%d)\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
|
||||
static int iwl_mvm_sgom_init(struct iwl_mvm *mvm)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
|
||||
{
|
||||
struct iwl_phy_cfg_cmd_v3 phy_cfg_cmd;
|
||||
@ -1338,6 +1382,7 @@ static u8 iwl_mvm_eval_dsm_rfi(struct iwl_mvm *mvm)
|
||||
void iwl_mvm_get_acpi_tables(struct iwl_mvm *mvm)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ACPI */
|
||||
|
||||
void iwl_mvm_send_recovery_cmd(struct iwl_mvm *mvm, u32 flags)
|
||||
@ -1632,6 +1677,10 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
|
||||
else if (ret < 0)
|
||||
goto error;
|
||||
|
||||
ret = iwl_mvm_sgom_init(mvm);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
iwl_mvm_tas_init(mvm);
|
||||
iwl_mvm_leds_sync(mvm);
|
||||
|
||||
|
@ -1732,6 +1732,7 @@ static void iwl_mvm_recalc_multicast(struct iwl_mvm *mvm)
|
||||
struct iwl_mvm_mc_iter_data iter_data = {
|
||||
.mvm = mvm,
|
||||
};
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
@ -1741,6 +1742,22 @@ static void iwl_mvm_recalc_multicast(struct iwl_mvm *mvm)
|
||||
ieee80211_iterate_active_interfaces_atomic(
|
||||
mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
|
||||
iwl_mvm_mc_iface_iterator, &iter_data);
|
||||
|
||||
/*
|
||||
* Send a (synchronous) ech command so that we wait for the
|
||||
* multiple asynchronous MCAST_FILTER_CMD commands sent by
|
||||
* the interface iterator. Otherwise, we might get here over
|
||||
* and over again (by userspace just sending a lot of these)
|
||||
* and the CPU can send them faster than the firmware can
|
||||
* process them.
|
||||
* Note that the CPU is still faster - but with this we'll
|
||||
* actually send fewer commands overall because the CPU will
|
||||
* not schedule the work in mac80211 as frequently if it's
|
||||
* still running when rescheduled (possibly multiple times).
|
||||
*/
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, ECHO_CMD, 0, 0, NULL);
|
||||
if (ret)
|
||||
IWL_ERR(mvm, "Failed to synchronize multicast groups update\n");
|
||||
}
|
||||
|
||||
static u64 iwl_mvm_prepare_multicast(struct ieee80211_hw *hw,
|
||||
@ -3388,6 +3405,11 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
|
||||
true);
|
||||
} else if (old_state == IEEE80211_STA_AUTHORIZED &&
|
||||
new_state == IEEE80211_STA_ASSOC) {
|
||||
/* once we move into assoc state, need to update rate scale to
|
||||
* disable using wide bandwidth
|
||||
*/
|
||||
iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band,
|
||||
false);
|
||||
if (!sta->tdls) {
|
||||
/* Multicast data frames are no longer allowed */
|
||||
iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
|
||||
@ -3410,16 +3432,16 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
|
||||
if (vif->type == NL80211_IFTYPE_AP) {
|
||||
mvmvif->ap_assoc_sta_count--;
|
||||
iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
|
||||
} else if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) {
|
||||
/* remove session protection if still running */
|
||||
} else if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
|
||||
iwl_mvm_stop_session_protection(mvm, vif);
|
||||
}
|
||||
ret = 0;
|
||||
} else if (old_state == IEEE80211_STA_AUTH &&
|
||||
new_state == IEEE80211_STA_NONE) {
|
||||
ret = 0;
|
||||
} else if (old_state == IEEE80211_STA_NONE &&
|
||||
new_state == IEEE80211_STA_NOTEXIST) {
|
||||
if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
|
||||
iwl_mvm_stop_session_protection(mvm, vif);
|
||||
ret = iwl_mvm_rm_sta(mvm, vif, sta);
|
||||
if (sta->tdls) {
|
||||
iwl_mvm_recalc_tdls_state(mvm, vif, false);
|
||||
@ -3585,13 +3607,14 @@ static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
|
||||
{
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
struct iwl_mvm_sta *mvmsta;
|
||||
struct iwl_mvm_sta *mvmsta = NULL;
|
||||
struct iwl_mvm_key_pn *ptk_pn;
|
||||
int keyidx = key->keyidx;
|
||||
int ret, i;
|
||||
u8 key_offset;
|
||||
|
||||
mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
if (sta)
|
||||
mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
|
||||
switch (key->cipher) {
|
||||
case WLAN_CIPHER_SUITE_TKIP:
|
||||
@ -3693,7 +3716,7 @@ static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
|
||||
}
|
||||
|
||||
if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) &&
|
||||
sta && iwl_mvm_has_new_rx_api(mvm) &&
|
||||
mvmsta && iwl_mvm_has_new_rx_api(mvm) &&
|
||||
key->flags & IEEE80211_KEY_FLAG_PAIRWISE &&
|
||||
(key->cipher == WLAN_CIPHER_SUITE_CCMP ||
|
||||
key->cipher == WLAN_CIPHER_SUITE_GCMP ||
|
||||
@ -3727,7 +3750,7 @@ static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
|
||||
else
|
||||
key_offset = STA_KEY_IDX_INVALID;
|
||||
|
||||
if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
|
||||
if (mvmsta && key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
|
||||
mvmsta->pairwise_cipher = key->cipher;
|
||||
|
||||
IWL_DEBUG_MAC80211(mvm, "set hwcrypto key\n");
|
||||
@ -3770,7 +3793,7 @@ static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
|
||||
break;
|
||||
}
|
||||
|
||||
if (sta && iwl_mvm_has_new_rx_api(mvm) &&
|
||||
if (mvmsta && iwl_mvm_has_new_rx_api(mvm) &&
|
||||
key->flags & IEEE80211_KEY_FLAG_PAIRWISE &&
|
||||
(key->cipher == WLAN_CIPHER_SUITE_CCMP ||
|
||||
key->cipher == WLAN_CIPHER_SUITE_GCMP ||
|
||||
|
@ -94,11 +94,10 @@ struct iwl_mvm_phy_ctxt {
|
||||
|
||||
enum nl80211_chan_width width;
|
||||
|
||||
/*
|
||||
* TODO: This should probably be removed. Currently here only for rate
|
||||
* scaling algorithm
|
||||
*/
|
||||
struct ieee80211_channel *channel;
|
||||
|
||||
/* track for RLC config command */
|
||||
u32 center_freq1;
|
||||
};
|
||||
|
||||
struct iwl_mvm_time_event_data {
|
||||
@ -1138,6 +1137,8 @@ struct iwl_mvm {
|
||||
* @IWL_MVM_STATUS_FIRMWARE_RUNNING: firmware is running
|
||||
* @IWL_MVM_STATUS_NEED_FLUSH_P2P: need to flush P2P bcast STA
|
||||
* @IWL_MVM_STATUS_IN_D3: in D3 (or at least about to go into it)
|
||||
* @IWL_MVM_STATUS_SUPPRESS_ERROR_LOG_ONCE: suppress one error log
|
||||
* if this is set, when intentionally triggered
|
||||
* @IWL_MVM_STATUS_STARTING: starting mac,
|
||||
* used to disable restart flow while in STARTING state
|
||||
*/
|
||||
@ -1151,6 +1152,7 @@ enum iwl_mvm_status {
|
||||
IWL_MVM_STATUS_FIRMWARE_RUNNING,
|
||||
IWL_MVM_STATUS_NEED_FLUSH_P2P,
|
||||
IWL_MVM_STATUS_IN_D3,
|
||||
IWL_MVM_STATUS_SUPPRESS_ERROR_LOG_ONCE,
|
||||
IWL_MVM_STATUS_STARTING,
|
||||
};
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "time-event.h"
|
||||
#include "fw-api.h"
|
||||
#include "fw/acpi.h"
|
||||
#include "fw/uefi.h"
|
||||
|
||||
#define DRV_DESCRIPTION "The new Intel(R) wireless AGN driver for Linux"
|
||||
MODULE_DESCRIPTION(DRV_DESCRIPTION);
|
||||
@ -78,7 +79,7 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
|
||||
u8 radio_cfg_type, radio_cfg_step, radio_cfg_dash;
|
||||
u32 reg_val = 0;
|
||||
u32 reg_val;
|
||||
u32 phy_config = iwl_mvm_get_phy_config(mvm);
|
||||
|
||||
radio_cfg_type = (phy_config & FW_PHY_CFG_RADIO_TYPE) >>
|
||||
@ -89,10 +90,7 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode)
|
||||
FW_PHY_CFG_RADIO_DASH_POS;
|
||||
|
||||
/* SKU control */
|
||||
reg_val |= CSR_HW_REV_STEP(mvm->trans->hw_rev) <<
|
||||
CSR_HW_IF_CONFIG_REG_POS_MAC_STEP;
|
||||
reg_val |= CSR_HW_REV_DASH(mvm->trans->hw_rev) <<
|
||||
CSR_HW_IF_CONFIG_REG_POS_MAC_DASH;
|
||||
reg_val = CSR_HW_REV_STEP_DASH(mvm->trans->hw_rev);
|
||||
|
||||
/* radio configuration */
|
||||
reg_val |= radio_cfg_type << CSR_HW_IF_CONFIG_REG_POS_PHY_TYPE;
|
||||
@ -117,8 +115,7 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode)
|
||||
reg_val |= CSR_HW_IF_CONFIG_REG_D3_DEBUG;
|
||||
|
||||
iwl_trans_set_bits_mask(mvm->trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH |
|
||||
CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP |
|
||||
CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP_DASH |
|
||||
CSR_HW_IF_CONFIG_REG_MSK_PHY_TYPE |
|
||||
CSR_HW_IF_CONFIG_REG_MSK_PHY_STEP |
|
||||
CSR_HW_IF_CONFIG_REG_MSK_PHY_DASH |
|
||||
@ -502,6 +499,9 @@ static const struct iwl_hcmd_names iwl_mvm_system_names[] = {
|
||||
HCMD_NAME(SHARED_MEM_CFG_CMD),
|
||||
HCMD_NAME(INIT_EXTENDED_CFG_CMD),
|
||||
HCMD_NAME(FW_ERROR_RECOVERY_CMD),
|
||||
HCMD_NAME(RFI_CONFIG_CMD),
|
||||
HCMD_NAME(RFI_GET_FREQ_TABLE_CMD),
|
||||
HCMD_NAME(SYSTEM_FEATURES_CONTROL_CMD),
|
||||
};
|
||||
|
||||
/* Please keep this array *SORTED* by hex value.
|
||||
@ -534,6 +534,7 @@ static const struct iwl_hcmd_names iwl_mvm_data_path_names[] = {
|
||||
HCMD_NAME(UPDATE_MU_GROUPS_CMD),
|
||||
HCMD_NAME(TRIGGER_RX_QUEUES_NOTIF_CMD),
|
||||
HCMD_NAME(STA_HE_CTXT_CMD),
|
||||
HCMD_NAME(RLC_CONFIG_CMD),
|
||||
HCMD_NAME(RFH_QUEUE_CONFIG_CMD),
|
||||
HCMD_NAME(TLC_MNG_CONFIG_CMD),
|
||||
HCMD_NAME(CHEST_COLLECTOR_FILTER_CONFIG_CMD),
|
||||
@ -1057,7 +1058,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
};
|
||||
int scan_size;
|
||||
u32 min_backoff;
|
||||
enum iwl_amsdu_size rb_size_default;
|
||||
struct iwl_mvm_csme_conn_info *csme_conn_info __maybe_unused;
|
||||
|
||||
/*
|
||||
@ -1097,6 +1097,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
&iwl_mvm_sanitize_ops, mvm, dbgfs_dir);
|
||||
|
||||
iwl_mvm_get_acpi_tables(mvm);
|
||||
iwl_uefi_get_sgom_table(trans, &mvm->fwrt);
|
||||
|
||||
mvm->init_status = 0;
|
||||
|
||||
@ -1200,14 +1201,9 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
trans_cfg.no_reclaim_cmds = no_reclaim_cmds;
|
||||
trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds);
|
||||
|
||||
if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
|
||||
rb_size_default = IWL_AMSDU_2K;
|
||||
else
|
||||
rb_size_default = IWL_AMSDU_4K;
|
||||
|
||||
switch (iwlwifi_mod_params.amsdu_size) {
|
||||
case IWL_AMSDU_DEF:
|
||||
trans_cfg.rx_buf_size = rb_size_default;
|
||||
trans_cfg.rx_buf_size = IWL_AMSDU_4K;
|
||||
break;
|
||||
case IWL_AMSDU_4K:
|
||||
trans_cfg.rx_buf_size = IWL_AMSDU_4K;
|
||||
@ -1221,7 +1217,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||
default:
|
||||
pr_err("%s: Unsupported amsdu_size: %d\n", KBUILD_MODNAME,
|
||||
iwlwifi_mod_params.amsdu_size);
|
||||
trans_cfg.rx_buf_size = rb_size_default;
|
||||
trans_cfg.rx_buf_size = IWL_AMSDU_4K;
|
||||
}
|
||||
|
||||
trans->wide_cmd_header = true;
|
||||
@ -1850,7 +1846,9 @@ static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode, bool sync)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
|
||||
|
||||
if (!test_bit(STATUS_TRANS_DEAD, &mvm->trans->status))
|
||||
if (!test_bit(STATUS_TRANS_DEAD, &mvm->trans->status) &&
|
||||
!test_and_clear_bit(IWL_MVM_STATUS_SUPPRESS_ERROR_LOG_ONCE,
|
||||
&mvm->status))
|
||||
iwl_mvm_dump_nic_error_log(mvm);
|
||||
|
||||
if (sync) {
|
||||
|
@ -157,8 +157,43 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm,
|
||||
/* Set the channel info data */
|
||||
iwl_mvm_set_chan_info_chandef(mvm, &cmd->ci, chandef);
|
||||
|
||||
iwl_mvm_phy_ctxt_set_rxchain(mvm, ctxt, &cmd->rxchain_info,
|
||||
/* we only support RLC command version 2 */
|
||||
if (iwl_fw_lookup_cmd_ver(mvm->fw, DATA_PATH_GROUP,
|
||||
RLC_CONFIG_CMD, 0) < 2)
|
||||
iwl_mvm_phy_ctxt_set_rxchain(mvm, ctxt, &cmd->rxchain_info,
|
||||
chains_static, chains_dynamic);
|
||||
}
|
||||
|
||||
static int iwl_mvm_phy_send_rlc(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_phy_ctxt *ctxt,
|
||||
u8 chains_static, u8 chains_dynamic)
|
||||
{
|
||||
struct iwl_rlc_config_cmd cmd = {
|
||||
.phy_id = cpu_to_le32(ctxt->id),
|
||||
};
|
||||
|
||||
if (iwl_fw_lookup_cmd_ver(mvm->fw, DATA_PATH_GROUP,
|
||||
RLC_CONFIG_CMD, 0) < 2)
|
||||
return 0;
|
||||
|
||||
BUILD_BUG_ON(IWL_RLC_CHAIN_INFO_DRIVER_FORCE !=
|
||||
PHY_RX_CHAIN_DRIVER_FORCE_MSK);
|
||||
BUILD_BUG_ON(IWL_RLC_CHAIN_INFO_VALID !=
|
||||
PHY_RX_CHAIN_VALID_MSK);
|
||||
BUILD_BUG_ON(IWL_RLC_CHAIN_INFO_FORCE !=
|
||||
PHY_RX_CHAIN_FORCE_SEL_MSK);
|
||||
BUILD_BUG_ON(IWL_RLC_CHAIN_INFO_FORCE_MIMO !=
|
||||
PHY_RX_CHAIN_FORCE_MIMO_SEL_MSK);
|
||||
BUILD_BUG_ON(IWL_RLC_CHAIN_INFO_COUNT != PHY_RX_CHAIN_CNT_MSK);
|
||||
BUILD_BUG_ON(IWL_RLC_CHAIN_INFO_MIMO_COUNT !=
|
||||
PHY_RX_CHAIN_MIMO_CNT_MSK);
|
||||
|
||||
iwl_mvm_phy_ctxt_set_rxchain(mvm, ctxt, &cmd.rlc.rx_chain_info,
|
||||
chains_static, chains_dynamic);
|
||||
|
||||
return iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(RLC_CONFIG_CMD,
|
||||
DATA_PATH_GROUP, 2),
|
||||
0, sizeof(cmd), &cmd);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -177,7 +212,7 @@ static int iwl_mvm_phy_ctxt_apply(struct iwl_mvm *mvm,
|
||||
int ver = iwl_fw_lookup_cmd_ver(mvm->fw, IWL_ALWAYS_LONG_GROUP,
|
||||
PHY_CONTEXT_CMD, 1);
|
||||
|
||||
if (ver == 3) {
|
||||
if (ver == 3 || ver == 4) {
|
||||
struct iwl_phy_context_cmd cmd = {};
|
||||
|
||||
/* Set the command header fields */
|
||||
@ -211,9 +246,16 @@ static int iwl_mvm_phy_ctxt_apply(struct iwl_mvm *mvm,
|
||||
}
|
||||
|
||||
|
||||
if (ret)
|
||||
if (ret) {
|
||||
IWL_ERR(mvm, "PHY ctxt cmd error. ret=%d\n", ret);
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (action != FW_CTXT_ACTION_REMOVE)
|
||||
return iwl_mvm_phy_send_rlc(mvm, ctxt, chains_static,
|
||||
chains_dynamic);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -228,6 +270,8 @@ int iwl_mvm_phy_ctxt_add(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
ctxt->channel = chandef->chan;
|
||||
ctxt->width = chandef->width;
|
||||
ctxt->center_freq1 = chandef->center_freq1;
|
||||
|
||||
return iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef,
|
||||
chains_static, chains_dynamic,
|
||||
@ -257,6 +301,14 @@ int iwl_mvm_phy_ctxt_changed(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
if (iwl_fw_lookup_cmd_ver(mvm->fw, DATA_PATH_GROUP,
|
||||
RLC_CONFIG_CMD, 0) >= 2 &&
|
||||
ctxt->channel == chandef->chan &&
|
||||
ctxt->width == chandef->width &&
|
||||
ctxt->center_freq1 == chandef->center_freq1)
|
||||
return iwl_mvm_phy_send_rlc(mvm, ctxt, chains_static,
|
||||
chains_dynamic);
|
||||
|
||||
if (fw_has_capa(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT) &&
|
||||
ctxt->channel->band != chandef->chan->band) {
|
||||
@ -275,6 +327,8 @@ int iwl_mvm_phy_ctxt_changed(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
|
||||
|
||||
ctxt->channel = chandef->chan;
|
||||
ctxt->width = chandef->width;
|
||||
ctxt->center_freq1 = chandef->center_freq1;
|
||||
|
||||
return iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef,
|
||||
chains_static, chains_dynamic,
|
||||
action);
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include "fw/api/commands.h"
|
||||
#include "fw/api/phy-ctxt.h"
|
||||
|
||||
/**
|
||||
/*
|
||||
* DDR needs frequency in units of 16.666MHz, so provide FW with the
|
||||
* frequency values in the adjusted format.
|
||||
*/
|
||||
|
@ -291,8 +291,12 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm,
|
||||
notif = (void *)pkt->data;
|
||||
sta = rcu_dereference(mvm->fw_id_to_mac_id[notif->sta_id]);
|
||||
if (IS_ERR_OR_NULL(sta)) {
|
||||
IWL_ERR(mvm, "Invalid sta id (%d) in FW TLC notification\n",
|
||||
notif->sta_id);
|
||||
/* can happen in remove station flow where mvm removed internally
|
||||
* the station before removing from FW
|
||||
*/
|
||||
IWL_DEBUG_RATE(mvm,
|
||||
"Invalid mvm RCU pointer for sta id (%d) in TLC notification\n",
|
||||
notif->sta_id);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -527,40 +527,19 @@ struct iwl_mvm_stat_data {
|
||||
u8 *beacon_average_energy;
|
||||
};
|
||||
|
||||
static void iwl_mvm_stat_iterator(void *_data, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
struct iwl_mvm_stat_data_all_macs {
|
||||
struct iwl_mvm *mvm;
|
||||
__le32 flags;
|
||||
struct iwl_statistics_ntfy_per_mac *per_mac_stats;
|
||||
};
|
||||
|
||||
static void iwl_mvm_update_vif_sig(struct ieee80211_vif *vif, int sig)
|
||||
{
|
||||
struct iwl_mvm_stat_data *data = _data;
|
||||
struct iwl_mvm *mvm = data->mvm;
|
||||
int sig = -data->beacon_filter_average_energy;
|
||||
int last_event;
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
struct iwl_mvm *mvm = mvmvif->mvm;
|
||||
int thold = vif->bss_conf.cqm_rssi_thold;
|
||||
int hyst = vif->bss_conf.cqm_rssi_hyst;
|
||||
u16 id = le32_to_cpu(data->mac_id);
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
u16 vif_id = mvmvif->id;
|
||||
|
||||
/* This doesn't need the MAC ID check since it's not taking the
|
||||
* data copied into the "data" struct, but rather the data from
|
||||
* the notification directly.
|
||||
*/
|
||||
mvmvif->beacon_stats.num_beacons =
|
||||
le32_to_cpu(data->beacon_counter[vif_id]);
|
||||
mvmvif->beacon_stats.avg_signal =
|
||||
-data->beacon_average_energy[vif_id];
|
||||
|
||||
/* make sure that beacon statistics don't go backwards with TCM
|
||||
* request to clear statistics
|
||||
*/
|
||||
if (le32_to_cpu(data->flags) & IWL_STATISTICS_REPLY_FLG_CLEAR)
|
||||
mvmvif->beacon_stats.accu_num_beacons +=
|
||||
mvmvif->beacon_stats.num_beacons;
|
||||
|
||||
if (mvmvif->id != id)
|
||||
return;
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_STATION)
|
||||
return;
|
||||
int last_event;
|
||||
|
||||
if (sig == 0) {
|
||||
IWL_DEBUG_RX(mvm, "RSSI is 0 - skip signal based decision\n");
|
||||
@ -618,6 +597,73 @@ static void iwl_mvm_stat_iterator(void *_data, u8 *mac,
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_mvm_stat_iterator(void *_data, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mvm_stat_data *data = _data;
|
||||
int sig = -data->beacon_filter_average_energy;
|
||||
u16 id = le32_to_cpu(data->mac_id);
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
u16 vif_id = mvmvif->id;
|
||||
|
||||
/* This doesn't need the MAC ID check since it's not taking the
|
||||
* data copied into the "data" struct, but rather the data from
|
||||
* the notification directly.
|
||||
*/
|
||||
mvmvif->beacon_stats.num_beacons =
|
||||
le32_to_cpu(data->beacon_counter[vif_id]);
|
||||
mvmvif->beacon_stats.avg_signal =
|
||||
-data->beacon_average_energy[vif_id];
|
||||
|
||||
if (mvmvif->id != id)
|
||||
return;
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_STATION)
|
||||
return;
|
||||
|
||||
/* make sure that beacon statistics don't go backwards with TCM
|
||||
* request to clear statistics
|
||||
*/
|
||||
if (le32_to_cpu(data->flags) & IWL_STATISTICS_REPLY_FLG_CLEAR)
|
||||
mvmvif->beacon_stats.accu_num_beacons +=
|
||||
mvmvif->beacon_stats.num_beacons;
|
||||
|
||||
iwl_mvm_update_vif_sig(vif, sig);
|
||||
}
|
||||
|
||||
static void iwl_mvm_stat_iterator_all_macs(void *_data, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_mvm_stat_data_all_macs *data = _data;
|
||||
struct iwl_statistics_ntfy_per_mac *mac_stats;
|
||||
int sig;
|
||||
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
|
||||
u16 vif_id = mvmvif->id;
|
||||
|
||||
if (WARN_ONCE(vif_id > MAC_INDEX_AUX, "invalid vif id: %d", vif_id))
|
||||
return;
|
||||
|
||||
if (vif->type != NL80211_IFTYPE_STATION)
|
||||
return;
|
||||
|
||||
mac_stats = &data->per_mac_stats[vif_id];
|
||||
|
||||
mvmvif->beacon_stats.num_beacons =
|
||||
le32_to_cpu(mac_stats->beacon_counter);
|
||||
mvmvif->beacon_stats.avg_signal =
|
||||
-le32_to_cpu(mac_stats->beacon_average_energy);
|
||||
|
||||
/* make sure that beacon statistics don't go backwards with TCM
|
||||
* request to clear statistics
|
||||
*/
|
||||
if (le32_to_cpu(data->flags) & IWL_STATISTICS_REPLY_FLG_CLEAR)
|
||||
mvmvif->beacon_stats.accu_num_beacons +=
|
||||
mvmvif->beacon_stats.num_beacons;
|
||||
|
||||
sig = -le32_to_cpu(mac_stats->beacon_filter_average_energy);
|
||||
iwl_mvm_update_vif_sig(vif, sig);
|
||||
}
|
||||
|
||||
static inline void
|
||||
iwl_mvm_rx_stats_check_trigger(struct iwl_mvm *mvm, struct iwl_rx_packet *pkt)
|
||||
{
|
||||
@ -684,47 +730,41 @@ iwl_mvm_update_tcm_from_stats(struct iwl_mvm *mvm, __le32 *air_time_le,
|
||||
}
|
||||
|
||||
static void
|
||||
iwl_mvm_handle_rx_statistics_tlv(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_packet *pkt)
|
||||
iwl_mvm_stats_ver_15(struct iwl_mvm *mvm,
|
||||
struct iwl_statistics_operational_ntfy *stats)
|
||||
{
|
||||
struct iwl_mvm_stat_data_all_macs data = {
|
||||
.mvm = mvm,
|
||||
.flags = stats->flags,
|
||||
.per_mac_stats = stats->per_mac_stats,
|
||||
};
|
||||
|
||||
ieee80211_iterate_active_interfaces(mvm->hw,
|
||||
IEEE80211_IFACE_ITER_NORMAL,
|
||||
iwl_mvm_stat_iterator_all_macs,
|
||||
&data);
|
||||
}
|
||||
|
||||
static void
|
||||
iwl_mvm_stats_ver_14(struct iwl_mvm *mvm,
|
||||
struct iwl_statistics_operational_ntfy_ver_14 *stats)
|
||||
{
|
||||
struct iwl_mvm_stat_data data = {
|
||||
.mvm = mvm,
|
||||
};
|
||||
|
||||
u8 beacon_average_energy[MAC_INDEX_AUX];
|
||||
u8 average_energy[IWL_MVM_STATION_COUNT_MAX];
|
||||
struct iwl_statistics_operational_ntfy *stats;
|
||||
int expected_size;
|
||||
__le32 flags;
|
||||
int i;
|
||||
|
||||
expected_size = sizeof(*stats);
|
||||
if (WARN_ONCE(iwl_rx_packet_payload_len(pkt) < expected_size,
|
||||
"received invalid statistics size (%d)!, expected_size: %d\n",
|
||||
iwl_rx_packet_payload_len(pkt), expected_size))
|
||||
return;
|
||||
|
||||
stats = (void *)&pkt->data;
|
||||
|
||||
if (WARN_ONCE(stats->hdr.type != FW_STATISTICS_OPERATIONAL ||
|
||||
stats->hdr.version !=
|
||||
iwl_fw_lookup_notif_ver(mvm->fw, LONG_GROUP, STATISTICS_CMD, 0),
|
||||
"received unsupported hdr type %d, version %d\n",
|
||||
stats->hdr.type, stats->hdr.version))
|
||||
return;
|
||||
|
||||
flags = stats->flags;
|
||||
mvm->radio_stats.rx_time = le64_to_cpu(stats->rx_time);
|
||||
mvm->radio_stats.tx_time = le64_to_cpu(stats->tx_time);
|
||||
mvm->radio_stats.on_time_rf = le64_to_cpu(stats->on_time_rf);
|
||||
mvm->radio_stats.on_time_scan = le64_to_cpu(stats->on_time_scan);
|
||||
|
||||
iwl_mvm_rx_stats_check_trigger(mvm, pkt);
|
||||
|
||||
data.mac_id = stats->mac_id;
|
||||
data.beacon_filter_average_energy =
|
||||
le32_to_cpu(stats->beacon_filter_average_energy);
|
||||
data.flags = flags;
|
||||
data.beacon_counter = stats->beacon_counter;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(beacon_average_energy); i++)
|
||||
beacon_average_energy[i] =
|
||||
le32_to_cpu(stats->beacon_average_energy[i]);
|
||||
@ -735,9 +775,105 @@ iwl_mvm_handle_rx_statistics_tlv(struct iwl_mvm *mvm,
|
||||
IEEE80211_IFACE_ITER_NORMAL,
|
||||
iwl_mvm_stat_iterator,
|
||||
&data);
|
||||
}
|
||||
|
||||
static bool iwl_mvm_verify_stats_len(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_packet *pkt,
|
||||
u32 expected_size)
|
||||
{
|
||||
struct iwl_statistics_ntfy_hdr *hdr;
|
||||
|
||||
if (WARN_ONCE(iwl_rx_packet_payload_len(pkt) < expected_size,
|
||||
"received invalid statistics size (%d)!, expected_size: %d\n",
|
||||
iwl_rx_packet_payload_len(pkt), expected_size))
|
||||
return false;
|
||||
|
||||
hdr = (void *)&pkt->data;
|
||||
|
||||
if (WARN_ONCE((hdr->type & IWL_STATISTICS_TYPE_MSK) != FW_STATISTICS_OPERATIONAL ||
|
||||
hdr->version !=
|
||||
iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP, STATISTICS_NOTIFICATION, 0),
|
||||
"received unsupported hdr type %d, version %d\n",
|
||||
hdr->type, hdr->version))
|
||||
return false;
|
||||
|
||||
if (WARN_ONCE(le16_to_cpu(hdr->size) != expected_size,
|
||||
"received invalid statistics size in header (%d)!, expected_size: %d\n",
|
||||
le16_to_cpu(hdr->size), expected_size))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
iwl_mvm_handle_rx_statistics_tlv(struct iwl_mvm *mvm,
|
||||
struct iwl_rx_packet *pkt)
|
||||
{
|
||||
u8 average_energy[IWL_MVM_STATION_COUNT_MAX];
|
||||
__le32 air_time[MAC_INDEX_AUX];
|
||||
__le32 rx_bytes[MAC_INDEX_AUX];
|
||||
__le32 flags = 0;
|
||||
int i;
|
||||
u32 notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
|
||||
STATISTICS_NOTIFICATION, 0);
|
||||
|
||||
if (WARN_ONCE(notif_ver > 15,
|
||||
"invalid statistics version id: %d\n", notif_ver))
|
||||
return;
|
||||
|
||||
if (notif_ver == 14) {
|
||||
struct iwl_statistics_operational_ntfy_ver_14 *stats =
|
||||
(void *)pkt->data;
|
||||
|
||||
if (!iwl_mvm_verify_stats_len(mvm, pkt, sizeof(*stats)))
|
||||
return;
|
||||
|
||||
iwl_mvm_stats_ver_14(mvm, stats);
|
||||
|
||||
flags = stats->flags;
|
||||
mvm->radio_stats.rx_time = le64_to_cpu(stats->rx_time);
|
||||
mvm->radio_stats.tx_time = le64_to_cpu(stats->tx_time);
|
||||
mvm->radio_stats.on_time_rf = le64_to_cpu(stats->on_time_rf);
|
||||
mvm->radio_stats.on_time_scan =
|
||||
le64_to_cpu(stats->on_time_scan);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(average_energy); i++)
|
||||
average_energy[i] = le32_to_cpu(stats->average_energy[i]);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(air_time); i++) {
|
||||
air_time[i] = stats->air_time[i];
|
||||
rx_bytes[i] = stats->rx_bytes[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (notif_ver == 15) {
|
||||
struct iwl_statistics_operational_ntfy *stats =
|
||||
(void *)pkt->data;
|
||||
|
||||
if (!iwl_mvm_verify_stats_len(mvm, pkt, sizeof(*stats)))
|
||||
return;
|
||||
|
||||
iwl_mvm_stats_ver_15(mvm, stats);
|
||||
|
||||
flags = stats->flags;
|
||||
mvm->radio_stats.rx_time = le64_to_cpu(stats->rx_time);
|
||||
mvm->radio_stats.tx_time = le64_to_cpu(stats->tx_time);
|
||||
mvm->radio_stats.on_time_rf = le64_to_cpu(stats->on_time_rf);
|
||||
mvm->radio_stats.on_time_scan =
|
||||
le64_to_cpu(stats->on_time_scan);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(average_energy); i++)
|
||||
average_energy[i] =
|
||||
le32_to_cpu(stats->per_sta_stats[i].average_energy);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(air_time); i++) {
|
||||
air_time[i] = stats->per_mac_stats[i].air_time;
|
||||
rx_bytes[i] = stats->per_mac_stats[i].rx_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
iwl_mvm_rx_stats_check_trigger(mvm, pkt);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(average_energy); i++)
|
||||
average_energy[i] = le32_to_cpu(stats->average_energy[i]);
|
||||
ieee80211_iterate_stations_atomic(mvm->hw, iwl_mvm_stats_energy_iter,
|
||||
average_energy);
|
||||
/*
|
||||
@ -746,8 +882,7 @@ iwl_mvm_handle_rx_statistics_tlv(struct iwl_mvm *mvm,
|
||||
* request and once in statistics notification.
|
||||
*/
|
||||
if (le32_to_cpu(flags) & IWL_STATISTICS_REPLY_FLG_CLEAR)
|
||||
iwl_mvm_update_tcm_from_stats(mvm, stats->air_time,
|
||||
stats->rx_bytes);
|
||||
iwl_mvm_update_tcm_from_stats(mvm, air_time, rx_bytes);
|
||||
}
|
||||
|
||||
void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm,
|
||||
@ -761,8 +896,8 @@ void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm,
|
||||
u8 *energy;
|
||||
|
||||
/* From ver 14 and up we use TLV statistics format */
|
||||
if (iwl_fw_lookup_notif_ver(mvm->fw, LONG_GROUP,
|
||||
STATISTICS_CMD, 0) >= 14)
|
||||
if (iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
|
||||
STATISTICS_NOTIFICATION, 0) >= 14)
|
||||
return iwl_mvm_handle_rx_statistics_tlv(mvm, pkt);
|
||||
|
||||
if (!iwl_mvm_has_new_rx_stats_api(mvm)) {
|
||||
|
@ -766,8 +766,11 @@ static void iwl_mvm_release_frames_from_notif(struct iwl_mvm *mvm,
|
||||
rcu_read_lock();
|
||||
|
||||
ba_data = rcu_dereference(mvm->baid_map[baid]);
|
||||
if (WARN_ON_ONCE(!ba_data))
|
||||
if (!ba_data) {
|
||||
WARN(!(flags & IWL_MVM_RELEASE_FROM_RSS_SYNC),
|
||||
"BAID %d not found in map\n", baid);
|
||||
goto out;
|
||||
}
|
||||
|
||||
sta = rcu_dereference(mvm->fw_id_to_mac_id[ba_data->sta_id]);
|
||||
if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta)))
|
||||
|
@ -1394,8 +1394,8 @@ static u32 iwl_mvm_scan_umac_ooc_priority(struct iwl_mvm_scan_params *params)
|
||||
}
|
||||
|
||||
static void
|
||||
iwl_mvm_scan_umac_dwell_v10(struct iwl_mvm *mvm,
|
||||
struct iwl_scan_general_params_v10 *general_params,
|
||||
iwl_mvm_scan_umac_dwell_v11(struct iwl_mvm *mvm,
|
||||
struct iwl_scan_general_params_v11 *general_params,
|
||||
struct iwl_mvm_scan_params *params)
|
||||
{
|
||||
struct iwl_mvm_scan_timing_params *timing, *hb_timing;
|
||||
@ -2238,15 +2238,15 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
}
|
||||
|
||||
static void
|
||||
iwl_mvm_scan_umac_fill_general_p_v10(struct iwl_mvm *mvm,
|
||||
iwl_mvm_scan_umac_fill_general_p_v11(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_scan_params *params,
|
||||
struct ieee80211_vif *vif,
|
||||
struct iwl_scan_general_params_v10 *gp,
|
||||
struct iwl_scan_general_params_v11 *gp,
|
||||
u16 gen_flags)
|
||||
{
|
||||
struct iwl_mvm_vif *scan_vif = iwl_mvm_vif_from_mac80211(vif);
|
||||
|
||||
iwl_mvm_scan_umac_dwell_v10(mvm, gp, params);
|
||||
iwl_mvm_scan_umac_dwell_v11(mvm, gp, params);
|
||||
|
||||
gp->flags = cpu_to_le16(gen_flags);
|
||||
|
||||
@ -2350,7 +2350,7 @@ static int iwl_mvm_scan_umac_v12(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
cmd->uid = cpu_to_le32(uid);
|
||||
|
||||
gen_flags = iwl_mvm_scan_umac_flags_v2(mvm, params, vif, type);
|
||||
iwl_mvm_scan_umac_fill_general_p_v10(mvm, params, vif,
|
||||
iwl_mvm_scan_umac_fill_general_p_v11(mvm, params, vif,
|
||||
&scan_p->general_params,
|
||||
gen_flags);
|
||||
|
||||
@ -2367,12 +2367,13 @@ static int iwl_mvm_scan_umac_v12(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_mvm_scan_umac_v14(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct iwl_mvm_scan_params *params, int type,
|
||||
int uid)
|
||||
static int iwl_mvm_scan_umac_v14_and_above(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct iwl_mvm_scan_params *params,
|
||||
int type, int uid, u32 version)
|
||||
{
|
||||
struct iwl_scan_req_umac_v14 *cmd = mvm->scan_cmd;
|
||||
struct iwl_scan_req_params_v14 *scan_p = &cmd->scan_params;
|
||||
struct iwl_scan_req_umac_v15 *cmd = mvm->scan_cmd;
|
||||
struct iwl_scan_req_params_v15 *scan_p = &cmd->scan_params;
|
||||
struct iwl_scan_channel_params_v6 *cp = &scan_p->channel_params;
|
||||
struct iwl_scan_probe_params_v4 *pb = &scan_p->probe_params;
|
||||
int ret;
|
||||
@ -2385,7 +2386,7 @@ static int iwl_mvm_scan_umac_v14(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
cmd->uid = cpu_to_le32(uid);
|
||||
|
||||
gen_flags = iwl_mvm_scan_umac_flags_v2(mvm, params, vif, type);
|
||||
iwl_mvm_scan_umac_fill_general_p_v10(mvm, params, vif,
|
||||
iwl_mvm_scan_umac_fill_general_p_v11(mvm, params, vif,
|
||||
&scan_p->general_params,
|
||||
gen_flags);
|
||||
|
||||
@ -2425,6 +2426,20 @@ static int iwl_mvm_scan_umac_v14(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_mvm_scan_umac_v14(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct iwl_mvm_scan_params *params, int type,
|
||||
int uid)
|
||||
{
|
||||
return iwl_mvm_scan_umac_v14_and_above(mvm, vif, params, type, uid, 14);
|
||||
}
|
||||
|
||||
static int iwl_mvm_scan_umac_v15(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct iwl_mvm_scan_params *params, int type,
|
||||
int uid)
|
||||
{
|
||||
return iwl_mvm_scan_umac_v14_and_above(mvm, vif, params, type, uid, 15);
|
||||
}
|
||||
|
||||
static int iwl_mvm_num_scans(struct iwl_mvm *mvm)
|
||||
{
|
||||
return hweight32(mvm->scan_status & IWL_MVM_SCAN_MASK);
|
||||
@ -2540,6 +2555,7 @@ struct iwl_scan_umac_handler {
|
||||
|
||||
static const struct iwl_scan_umac_handler iwl_scan_umac_handlers[] = {
|
||||
/* set the newest version first to shorten the list traverse time */
|
||||
IWL_SCAN_UMAC_HANDLER(15),
|
||||
IWL_SCAN_UMAC_HANDLER(14),
|
||||
IWL_SCAN_UMAC_HANDLER(12),
|
||||
};
|
||||
@ -2940,15 +2956,14 @@ static int iwl_mvm_scan_stop_wait(struct iwl_mvm *mvm, int type)
|
||||
1 * HZ);
|
||||
}
|
||||
|
||||
#define IWL_SCAN_REQ_UMAC_HANDLE_SIZE(_ver) { \
|
||||
case (_ver): return sizeof(struct iwl_scan_req_umac_v##_ver); \
|
||||
}
|
||||
|
||||
static int iwl_scan_req_umac_get_size(u8 scan_ver)
|
||||
{
|
||||
switch (scan_ver) {
|
||||
IWL_SCAN_REQ_UMAC_HANDLE_SIZE(14);
|
||||
IWL_SCAN_REQ_UMAC_HANDLE_SIZE(12);
|
||||
case 12:
|
||||
return sizeof(struct iwl_scan_req_umac_v12);
|
||||
case 14:
|
||||
case 15:
|
||||
return sizeof(struct iwl_scan_req_umac_v15);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -2684,6 +2684,16 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
||||
RCU_INIT_POINTER(mvm->baid_map[baid], NULL);
|
||||
kfree_rcu(baid_data, rcu_head);
|
||||
IWL_DEBUG_HT(mvm, "BAID %d is free\n", baid);
|
||||
|
||||
/*
|
||||
* After we've deleted it, do another queue sync
|
||||
* so if an IWL_MVM_RXQ_NSSN_SYNC was concurrently
|
||||
* running it won't find a new session in the old
|
||||
* BAID. It can find the NULL pointer for the BAID,
|
||||
* but we must not have it find a different session.
|
||||
*/
|
||||
iwl_mvm_sync_rx_queues_internal(mvm, IWL_MVM_RXQ_EMPTY,
|
||||
true, NULL, 0);
|
||||
}
|
||||
return 0;
|
||||
|
||||
|
@ -1158,15 +1158,10 @@ void iwl_mvm_schedule_session_protection(struct iwl_mvm *mvm,
|
||||
cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
|
||||
mvmvif->color)),
|
||||
.action = cpu_to_le32(FW_CTXT_ACTION_ADD),
|
||||
.conf_id = cpu_to_le32(SESSION_PROTECT_CONF_ASSOC),
|
||||
.duration_tu = cpu_to_le32(MSEC_TO_TU(duration)),
|
||||
};
|
||||
|
||||
/* The time_event_data.id field is reused to save session
|
||||
* protection's configuration.
|
||||
*/
|
||||
mvmvif->time_event_data.id = SESSION_PROTECT_CONF_ASSOC;
|
||||
cmd.conf_id = cpu_to_le32(mvmvif->time_event_data.id);
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
spin_lock_bh(&mvm->time_event_lock);
|
||||
@ -1180,6 +1175,11 @@ void iwl_mvm_schedule_session_protection(struct iwl_mvm *mvm,
|
||||
}
|
||||
|
||||
iwl_mvm_te_clear_data(mvm, te_data);
|
||||
/*
|
||||
* The time_event_data.id field is reused to save session
|
||||
* protection's configuration.
|
||||
*/
|
||||
te_data->id = le32_to_cpu(cmd.conf_id);
|
||||
te_data->duration = le32_to_cpu(cmd.duration_tu);
|
||||
te_data->vif = vif;
|
||||
spin_unlock_bh(&mvm->time_event_lock);
|
||||
|
@ -340,25 +340,64 @@ void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
ieee80211_request_smps(vif, smps_mode);
|
||||
}
|
||||
|
||||
static bool iwl_wait_stats_complete(struct iwl_notif_wait_data *notif_wait,
|
||||
struct iwl_rx_packet *pkt, void *data)
|
||||
{
|
||||
WARN_ON(pkt->hdr.cmd != STATISTICS_NOTIFICATION);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int iwl_mvm_request_statistics(struct iwl_mvm *mvm, bool clear)
|
||||
{
|
||||
struct iwl_statistics_cmd scmd = {
|
||||
.flags = clear ? cpu_to_le32(IWL_STATISTICS_FLG_CLEAR) : 0,
|
||||
};
|
||||
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = STATISTICS_CMD,
|
||||
.len[0] = sizeof(scmd),
|
||||
.data[0] = &scmd,
|
||||
.flags = CMD_WANT_SKB,
|
||||
};
|
||||
int ret;
|
||||
|
||||
ret = iwl_mvm_send_cmd(mvm, &cmd);
|
||||
if (ret)
|
||||
return ret;
|
||||
/* From version 15 - STATISTICS_NOTIFICATION, the reply for
|
||||
* STATISTICS_CMD is empty, and the response is with
|
||||
* STATISTICS_NOTIFICATION notification
|
||||
*/
|
||||
if (iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
|
||||
STATISTICS_NOTIFICATION, 0) < 15) {
|
||||
cmd.flags = CMD_WANT_SKB;
|
||||
|
||||
iwl_mvm_handle_rx_statistics(mvm, cmd.resp_pkt);
|
||||
iwl_free_resp(&cmd);
|
||||
ret = iwl_mvm_send_cmd(mvm, &cmd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
iwl_mvm_handle_rx_statistics(mvm, cmd.resp_pkt);
|
||||
iwl_free_resp(&cmd);
|
||||
} else {
|
||||
struct iwl_notification_wait stats_wait;
|
||||
static const u16 stats_complete[] = {
|
||||
STATISTICS_NOTIFICATION,
|
||||
};
|
||||
|
||||
iwl_init_notification_wait(&mvm->notif_wait, &stats_wait,
|
||||
stats_complete, ARRAY_SIZE(stats_complete),
|
||||
iwl_wait_stats_complete, NULL);
|
||||
|
||||
ret = iwl_mvm_send_cmd(mvm, &cmd);
|
||||
if (ret) {
|
||||
iwl_remove_notification(&mvm->notif_wait, &stats_wait);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* 200ms should be enough for FW to collect data from all
|
||||
* LMACs and send STATISTICS_NOTIFICATION to host
|
||||
*/
|
||||
ret = iwl_wait_notification(&mvm->notif_wait, &stats_wait, HZ / 5);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (clear)
|
||||
iwl_mvm_accu_radio_stats(mvm);
|
||||
|
@ -562,6 +562,7 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
|
||||
IWL_DEV_INFO(0x43F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0, iwl_ax201_killer_1650i_name),
|
||||
IWL_DEV_INFO(0x43F0, 0x2074, iwl_ax201_cfg_qu_hr, NULL),
|
||||
IWL_DEV_INFO(0x43F0, 0x4070, iwl_ax201_cfg_qu_hr, NULL),
|
||||
IWL_DEV_INFO(0x43F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0, iwl_ax201_killer_1650s_name),
|
||||
IWL_DEV_INFO(0xA0F0, 0x0070, iwl_ax201_cfg_qu_hr, NULL),
|
||||
IWL_DEV_INFO(0xA0F0, 0x0074, iwl_ax201_cfg_qu_hr, NULL),
|
||||
IWL_DEV_INFO(0xA0F0, 0x0078, iwl_ax201_cfg_qu_hr, NULL),
|
||||
@ -959,6 +960,11 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
|
||||
IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY,
|
||||
IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
|
||||
iwl_qu_c0_hr_b0, iwl_ax203_name),
|
||||
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
|
||||
IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP,
|
||||
IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY,
|
||||
IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
|
||||
iwl_qu_c0_hr_b0, iwl_ax201_name),
|
||||
|
||||
/* QuZ */
|
||||
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
|
||||
@ -1097,6 +1103,11 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
|
||||
IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY,
|
||||
IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
|
||||
iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_name),
|
||||
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
|
||||
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
|
||||
IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY,
|
||||
IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_CDB,
|
||||
iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_name),
|
||||
|
||||
/* Bz */
|
||||
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
|
||||
@ -1130,6 +1141,13 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
|
||||
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,
|
||||
iwl_cfg_gl_a0_fm_a0, iwl_bz_name),
|
||||
|
||||
/* BZ Z step */
|
||||
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
|
||||
IWL_CFG_MAC_TYPE_BZ, SILICON_Z_STEP,
|
||||
IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY,
|
||||
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,
|
||||
iwl_cfg_bz_z0_gf_a0, iwl_bz_name),
|
||||
|
||||
/* SoF with JF2 */
|
||||
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
|
||||
IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
|
||||
@ -1204,6 +1222,11 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
|
||||
IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY,
|
||||
IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
|
||||
iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_name),
|
||||
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
|
||||
IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
|
||||
IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY,
|
||||
IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_CDB,
|
||||
iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_name),
|
||||
|
||||
/* So with JF2 */
|
||||
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
|
||||
@ -1456,7 +1479,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
|
||||
dev_info = iwl_pci_find_dev_info(pdev->device, pdev->subsystem_device,
|
||||
CSR_HW_REV_TYPE(iwl_trans->hw_rev),
|
||||
CSR_HW_REV_STEP(iwl_trans->hw_rev),
|
||||
iwl_trans->hw_rev_step,
|
||||
CSR_HW_RFID_TYPE(iwl_trans->hw_rf_id),
|
||||
CSR_HW_RFID_IS_CDB(iwl_trans->hw_rf_id),
|
||||
IWL_SUBDEVICE_RF_ID(pdev->subsystem_device),
|
||||
@ -1497,21 +1520,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
(iwl_trans->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_7265D)
|
||||
iwl_trans->cfg = cfg_7265d;
|
||||
|
||||
if (cfg == &iwlax210_2ax_cfg_so_hr_a0) {
|
||||
if (iwl_trans->hw_rev == CSR_HW_REV_TYPE_TY) {
|
||||
iwl_trans->cfg = &iwlax210_2ax_cfg_ty_gf_a0;
|
||||
} else if (CSR_HW_RFID_TYPE(iwl_trans->hw_rf_id) ==
|
||||
CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_JF)) {
|
||||
iwl_trans->cfg = &iwlax210_2ax_cfg_so_jf_b0;
|
||||
} else if (CSR_HW_RFID_TYPE(iwl_trans->hw_rf_id) ==
|
||||
CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_GF)) {
|
||||
iwl_trans->cfg = &iwlax211_2ax_cfg_so_gf_a0;
|
||||
} else if (CSR_HW_RFID_TYPE(iwl_trans->hw_rf_id) ==
|
||||
CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_GF4)) {
|
||||
iwl_trans->cfg = &iwlax411_2ax_cfg_so_gf4_a0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a hack to switch from Qu B0 to Qu C0. We need to
|
||||
* do this for all cfgs that use Qu B0, except for those using
|
||||
|
@ -81,7 +81,7 @@ static void iwl_pcie_gen2_apm_stop(struct iwl_trans *trans, bool op_mode_leave)
|
||||
/* Stop device's DMA activity */
|
||||
iwl_pcie_apm_stop_master(trans);
|
||||
|
||||
iwl_trans_sw_reset(trans);
|
||||
iwl_trans_sw_reset(trans, false);
|
||||
|
||||
/*
|
||||
* Clear "initialization complete" bit to move adapter from
|
||||
@ -105,9 +105,12 @@ static void iwl_trans_pcie_fw_reset_handshake(struct iwl_trans *trans)
|
||||
if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
|
||||
iwl_write_umac_prph(trans, UREG_NIC_SET_NMI_DRIVER,
|
||||
UREG_NIC_SET_NMI_DRIVER_RESET_HANDSHAKE);
|
||||
else
|
||||
else if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_AX210)
|
||||
iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6,
|
||||
UREG_DOORBELL_TO_ISR6_RESET_HANDSHAKE);
|
||||
else
|
||||
iwl_write32(trans, CSR_DOORBELL_VECTOR,
|
||||
UREG_DOORBELL_TO_ISR6_RESET_HANDSHAKE);
|
||||
|
||||
/* wait 200ms */
|
||||
ret = wait_event_timeout(trans_pcie->fw_reset_waitq,
|
||||
@ -166,7 +169,8 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans)
|
||||
/* Stop the device, and put it in low power state */
|
||||
iwl_pcie_gen2_apm_stop(trans, false);
|
||||
|
||||
iwl_trans_sw_reset(trans);
|
||||
/* re-take ownership to prevent other users from stealing the device */
|
||||
iwl_trans_sw_reset(trans, true);
|
||||
|
||||
/*
|
||||
* Upon stop, the IVAR table gets erased, so msi-x won't
|
||||
@ -196,9 +200,6 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans)
|
||||
* interrupt
|
||||
*/
|
||||
iwl_enable_rfkill_int(trans);
|
||||
|
||||
/* re-take ownership to prevent other users from stealing the device */
|
||||
iwl_pcie_prepare_card_hw(trans);
|
||||
}
|
||||
|
||||
void iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans)
|
||||
|
@ -127,7 +127,8 @@ out:
|
||||
kfree(buf);
|
||||
}
|
||||
|
||||
static void iwl_trans_pcie_sw_reset(struct iwl_trans *trans)
|
||||
static int iwl_trans_pcie_sw_reset(struct iwl_trans *trans,
|
||||
bool retake_ownership)
|
||||
{
|
||||
/* Reset entire device - do controller reset (results in SHRD_HW_RST) */
|
||||
if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
|
||||
@ -137,6 +138,11 @@ static void iwl_trans_pcie_sw_reset(struct iwl_trans *trans)
|
||||
iwl_set_bit(trans, CSR_RESET,
|
||||
CSR_RESET_REG_FLAG_SW_RESET);
|
||||
usleep_range(5000, 6000);
|
||||
|
||||
if (retake_ownership)
|
||||
return iwl_pcie_prepare_card_hw(trans);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iwl_pcie_free_fw_monitor(struct iwl_trans *trans)
|
||||
@ -382,9 +388,11 @@ static void iwl_pcie_apm_lp_xtal_enable(struct iwl_trans *trans)
|
||||
__iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_XTAL_ON);
|
||||
|
||||
iwl_trans_pcie_sw_reset(trans);
|
||||
ret = iwl_trans_pcie_sw_reset(trans, true);
|
||||
|
||||
if (!ret)
|
||||
ret = iwl_finish_nic_init(trans);
|
||||
|
||||
ret = iwl_finish_nic_init(trans);
|
||||
if (WARN_ON(ret)) {
|
||||
/* Release XTAL ON request */
|
||||
__iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
|
||||
@ -409,7 +417,10 @@ static void iwl_pcie_apm_lp_xtal_enable(struct iwl_trans *trans)
|
||||
apmg_xtal_cfg_reg |
|
||||
SHR_APMG_XTAL_CFG_XTAL_ON_REQ);
|
||||
|
||||
iwl_trans_pcie_sw_reset(trans);
|
||||
ret = iwl_trans_pcie_sw_reset(trans, true);
|
||||
if (ret)
|
||||
IWL_ERR(trans,
|
||||
"iwl_pcie_apm_lp_xtal_enable: failed to retake NIC ownership\n");
|
||||
|
||||
/* Enable LP XTAL by indirect access through CSR */
|
||||
apmg_gp1_reg = iwl_trans_pcie_read_shr(trans, SHR_APMG_GP1_REG);
|
||||
@ -515,7 +526,7 @@ static void iwl_pcie_apm_stop(struct iwl_trans *trans, bool op_mode_leave)
|
||||
return;
|
||||
}
|
||||
|
||||
iwl_trans_pcie_sw_reset(trans);
|
||||
iwl_trans_pcie_sw_reset(trans, false);
|
||||
|
||||
/*
|
||||
* Clear "initialization complete" bit to move adapter from
|
||||
@ -1261,7 +1272,8 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans)
|
||||
/* Stop the device, and put it in low power state */
|
||||
iwl_pcie_apm_stop(trans, false);
|
||||
|
||||
iwl_trans_pcie_sw_reset(trans);
|
||||
/* re-take ownership to prevent other users from stealing the device */
|
||||
iwl_trans_pcie_sw_reset(trans, true);
|
||||
|
||||
/*
|
||||
* Upon stop, the IVAR table gets erased, so msi-x won't
|
||||
@ -1291,9 +1303,6 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans)
|
||||
* interrupt
|
||||
*/
|
||||
iwl_enable_rfkill_int(trans);
|
||||
|
||||
/* re-take ownership to prevent other users from stealing the device */
|
||||
iwl_pcie_prepare_card_hw(trans);
|
||||
}
|
||||
|
||||
void iwl_pcie_synchronize_irqs(struct iwl_trans *trans)
|
||||
@ -1499,33 +1508,54 @@ void iwl_pcie_d3_complete_suspend(struct iwl_trans *trans,
|
||||
iwl_pcie_set_pwr(trans, true);
|
||||
}
|
||||
|
||||
static int iwl_pcie_d3_handshake(struct iwl_trans *trans, bool suspend)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
int ret;
|
||||
|
||||
if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_AX210) {
|
||||
iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6,
|
||||
suspend ? UREG_DOORBELL_TO_ISR6_SUSPEND :
|
||||
UREG_DOORBELL_TO_ISR6_RESUME);
|
||||
} else if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
|
||||
iwl_write32(trans, CSR_IPC_SLEEP_CONTROL,
|
||||
suspend ? CSR_IPC_SLEEP_CONTROL_SUSPEND :
|
||||
CSR_IPC_SLEEP_CONTROL_RESUME);
|
||||
iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6,
|
||||
UREG_DOORBELL_TO_ISR6_SLEEP_CTRL);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = wait_event_timeout(trans_pcie->sx_waitq,
|
||||
trans_pcie->sx_complete, 2 * HZ);
|
||||
|
||||
/* Invalidate it toward next suspend or resume */
|
||||
trans_pcie->sx_complete = false;
|
||||
|
||||
if (!ret) {
|
||||
IWL_ERR(trans, "Timeout %s D3\n",
|
||||
suspend ? "entering" : "exiting");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test,
|
||||
bool reset)
|
||||
{
|
||||
int ret;
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
||||
if (!reset)
|
||||
/* Enable persistence mode to avoid reset */
|
||||
iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_PERSIST_MODE);
|
||||
|
||||
if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
|
||||
iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6,
|
||||
UREG_DOORBELL_TO_ISR6_SUSPEND);
|
||||
ret = iwl_pcie_d3_handshake(trans, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = wait_event_timeout(trans_pcie->sx_waitq,
|
||||
trans_pcie->sx_complete, 2 * HZ);
|
||||
/*
|
||||
* Invalidate it toward resume.
|
||||
*/
|
||||
trans_pcie->sx_complete = false;
|
||||
|
||||
if (!ret) {
|
||||
IWL_ERR(trans, "Timeout entering D3\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
iwl_pcie_d3_complete_suspend(trans, test, reset);
|
||||
|
||||
return 0;
|
||||
@ -1542,6 +1572,7 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
|
||||
if (test) {
|
||||
iwl_enable_interrupts(trans);
|
||||
*status = IWL_D3_STATUS_ALIVE;
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -1590,25 +1621,10 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
|
||||
*status = IWL_D3_STATUS_ALIVE;
|
||||
|
||||
out:
|
||||
if (*status == IWL_D3_STATUS_ALIVE &&
|
||||
trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
|
||||
trans_pcie->sx_complete = false;
|
||||
iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6,
|
||||
UREG_DOORBELL_TO_ISR6_RESUME);
|
||||
if (*status == IWL_D3_STATUS_ALIVE)
|
||||
ret = iwl_pcie_d3_handshake(trans, false);
|
||||
|
||||
ret = wait_event_timeout(trans_pcie->sx_waitq,
|
||||
trans_pcie->sx_complete, 2 * HZ);
|
||||
/*
|
||||
* Invalidate it toward next suspend.
|
||||
*/
|
||||
trans_pcie->sx_complete = false;
|
||||
|
||||
if (!ret) {
|
||||
IWL_ERR(trans, "Timeout exiting D3\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1795,9 +1811,7 @@ static int iwl_pcie_gen2_force_power_gating(struct iwl_trans *trans)
|
||||
iwl_clear_bits_prph(trans, HPM_HIPM_GEN_CFG,
|
||||
HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE);
|
||||
|
||||
iwl_trans_pcie_sw_reset(trans);
|
||||
|
||||
return 0;
|
||||
return iwl_trans_pcie_sw_reset(trans, true);
|
||||
}
|
||||
|
||||
static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans)
|
||||
@ -1817,7 +1831,9 @@ static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
iwl_trans_pcie_sw_reset(trans);
|
||||
err = iwl_trans_pcie_sw_reset(trans, true);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000 &&
|
||||
trans->trans_cfg->integrated) {
|
||||
@ -3616,8 +3632,9 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
||||
* in the old format.
|
||||
*/
|
||||
if (cfg_trans->device_family >= IWL_DEVICE_FAMILY_8000)
|
||||
trans->hw_rev = (trans->hw_rev & 0xfff0) |
|
||||
(CSR_HW_REV_STEP(trans->hw_rev << 2) << 2);
|
||||
trans->hw_rev_step = trans->hw_rev & 0xF;
|
||||
else
|
||||
trans->hw_rev_step = (trans->hw_rev & 0xC) >> 2;
|
||||
|
||||
IWL_DEBUG_INFO(trans, "HW REV: 0x%0x\n", trans->hw_rev);
|
||||
|
||||
|
@ -1072,6 +1072,7 @@ int iwl_txq_alloc(struct iwl_trans *trans, struct iwl_txq *txq, int slots_num,
|
||||
return 0;
|
||||
err_free_tfds:
|
||||
dma_free_coherent(trans->dev, tfd_sz, txq->tfds, txq->dma_addr);
|
||||
txq->tfds = NULL;
|
||||
error:
|
||||
if (txq->entries && cmd_queue)
|
||||
for (i = 0; i < slots_num; i++)
|
||||
@ -1752,8 +1753,11 @@ static int iwl_trans_txq_send_hcmd_sync(struct iwl_trans *trans,
|
||||
}
|
||||
|
||||
if (test_bit(STATUS_FW_ERROR, &trans->status)) {
|
||||
IWL_ERR(trans, "FW error in SYNC CMD %s\n", cmd_str);
|
||||
dump_stack();
|
||||
if (!test_and_clear_bit(STATUS_SUPPRESS_CMD_ERROR_ONCE,
|
||||
&trans->status)) {
|
||||
IWL_ERR(trans, "FW error in SYNC CMD %s\n", cmd_str);
|
||||
dump_stack();
|
||||
}
|
||||
ret = -EIO;
|
||||
goto cancel;
|
||||
}
|
||||
|
@ -308,7 +308,7 @@ struct txpd {
|
||||
__le32 tx_packet_location;
|
||||
/* Tx packet length */
|
||||
__le16 tx_packet_length;
|
||||
struct_group(tx_dest_addr,
|
||||
struct_group_attr(tx_dest_addr, __packed,
|
||||
/* First 2 byte of destination MAC address */
|
||||
u8 tx_dest_addr_high[2];
|
||||
/* Last 4 byte of destination MAC address */
|
||||
|
@ -268,7 +268,7 @@ struct txpd {
|
||||
__le32 tx_packet_location;
|
||||
/* Tx packet length */
|
||||
__le16 tx_packet_length;
|
||||
struct_group(tx_dest_addr,
|
||||
struct_group_attr(tx_dest_addr, __packed,
|
||||
/* First 2 byte of destination MAC address */
|
||||
u8 tx_dest_addr_high[2];
|
||||
/* Last 4 byte of destination MAC address */
|
||||
@ -282,7 +282,7 @@ struct txpd {
|
||||
u8 pktdelay_2ms;
|
||||
/* reserved */
|
||||
u8 reserved1;
|
||||
};
|
||||
} __packed;
|
||||
|
||||
/* RxPD Descriptor */
|
||||
struct rxpd {
|
||||
@ -313,7 +313,7 @@ struct rxpd {
|
||||
/* Pkt Priority */
|
||||
u8 priority;
|
||||
u8 reserved[3];
|
||||
};
|
||||
} __packed;
|
||||
|
||||
struct cmd_header {
|
||||
__le16 command;
|
||||
@ -379,14 +379,14 @@ struct cmd_ds_mac_control {
|
||||
struct cmd_header hdr;
|
||||
__le16 action;
|
||||
u16 reserved;
|
||||
};
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_802_11_mac_address {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
uint8_t macadd[ETH_ALEN];
|
||||
};
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_mac_multicast_addr {
|
||||
struct cmd_header hdr;
|
||||
@ -394,27 +394,27 @@ struct cmd_ds_mac_multicast_addr {
|
||||
__le16 action;
|
||||
__le16 nr_of_adrs;
|
||||
u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE];
|
||||
};
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_set_mode {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 mode;
|
||||
};
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_set_bssid {
|
||||
struct cmd_header hdr;
|
||||
|
||||
u8 bssid[6];
|
||||
u8 activate;
|
||||
};
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_802_11_radio_control {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le16 control;
|
||||
};
|
||||
} __packed;
|
||||
|
||||
|
||||
struct cmd_ds_802_11_rf_channel {
|
||||
@ -425,20 +425,20 @@ struct cmd_ds_802_11_rf_channel {
|
||||
__le16 rftype; /* unused */
|
||||
__le16 reserved; /* unused */
|
||||
u8 channellist[32]; /* unused */
|
||||
};
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_set_boot2_ver {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le16 version;
|
||||
};
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_802_11_reset {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
};
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_802_11_beacon_control {
|
||||
struct cmd_header hdr;
|
||||
@ -446,14 +446,14 @@ struct cmd_ds_802_11_beacon_control {
|
||||
__le16 action;
|
||||
__le16 beacon_enable;
|
||||
__le16 beacon_period;
|
||||
};
|
||||
} __packed;
|
||||
|
||||
struct cmd_ds_802_11_beacon_set {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 len;
|
||||
u8 beacon[MRVL_MAX_BCN_SIZE];
|
||||
};
|
||||
} __packed;
|
||||
|
||||
struct cmd_ctrl_node;
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user