diff options
93 files changed, 1097 insertions, 442 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 9f338ed0d9ab..5d81c002232a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14066,7 +14066,7 @@ F: drivers/net/wireless/ath/wcn36xx/ QUANTENNA QTNFMAC WIRELESS DRIVER M: Igor Mitsyanko <imitsyanko@quantenna.com> -M: Sergey Matyukevich <smatyukevich@quantenna.com> +R: Sergey Matyukevich <geomatsi@gmail.com> L: linux-wireless@vger.kernel.org S: Maintained F: drivers/net/wireless/quantenna diff --git a/drivers/net/wireless/ath/ath10k/Kconfig b/drivers/net/wireless/ath/ath10k/Kconfig index 6b3ff02a373d..b99fd0eff994 100644 --- a/drivers/net/wireless/ath/ath10k/Kconfig +++ b/drivers/net/wireless/ath/ath10k/Kconfig @@ -28,11 +28,10 @@ config ATH10K_AHB This module adds support for AHB bus config ATH10K_SDIO - tristate "Atheros ath10k SDIO support (EXPERIMENTAL)" + tristate "Atheros ath10k SDIO support" depends on ATH10K && MMC ---help--- - This module adds experimental support for SDIO/MMC bus. Currently - work in progress and will not fully work. + This module adds support for SDIO/MMC bus. config ATH10K_USB tristate "Atheros ath10k USB support (EXPERIMENTAL)" @@ -42,7 +41,7 @@ config ATH10K_USB work in progress and will not fully work. config ATH10K_SNOC - tristate "Qualcomm ath10k SNOC support (EXPERIMENTAL)" + tristate "Qualcomm ath10k SNOC support" depends on ATH10K depends on ARCH_QCOM || COMPILE_TEST select QCOM_QMI_HELPERS diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index 9711f0eb9117..75df79d43120 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h @@ -110,7 +110,7 @@ struct ath10k_ce_ring { struct ce_desc_64 *shadow_base; /* keep last */ - void *per_transfer_context[0]; + void *per_transfer_context[]; }; struct ath10k_ce_pipe { diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index ceac76553b8f..5c18f6c20462 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -1262,7 +1262,7 @@ struct ath10k { int coex_gpio_pin; /* must be last */ - u8 drv_priv[0] __aligned(sizeof(void *)); + u8 drv_priv[] __aligned(sizeof(void *)); }; static inline bool ath10k_peer_stats_enabled(struct ath10k *ar) diff --git a/drivers/net/wireless/ath/ath10k/coredump.h b/drivers/net/wireless/ath/ath10k/coredump.h index 8bf03e8c1d3a..e760ce1a5f1e 100644 --- a/drivers/net/wireless/ath/ath10k/coredump.h +++ b/drivers/net/wireless/ath/ath10k/coredump.h @@ -88,7 +88,7 @@ struct ath10k_dump_file_data { u8 unused[128]; /* struct ath10k_tlv_dump_data + more */ - u8 data[0]; + u8 data[]; } __packed; struct ath10k_dump_ram_data_hdr { @@ -100,7 +100,7 @@ struct ath10k_dump_ram_data_hdr { /* length of payload data, not including this header */ __le32 length; - u8 data[0]; + u8 data[]; }; /* magic number to fill the holes not copied due to sections in regions */ diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h index 4cbfd9279d6f..997c1c80aba7 100644 --- a/drivers/net/wireless/ath/ath10k/debug.h +++ b/drivers/net/wireless/ath/ath10k/debug.h @@ -65,7 +65,7 @@ struct ath10k_pktlog_hdr { __le16 log_type; /* Type of log information foll this header */ __le16 size; /* Size of variable length log information in bytes */ __le32 timestamp; - u8 payload[0]; + u8 payload[]; } __packed; /* FIXME: How to calculate the buffer size sanely? */ diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 8f3710cf28f4..cad59494f175 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -289,12 +289,12 @@ struct htt_rx_ring_setup_hdr { struct htt_rx_ring_setup_32 { struct htt_rx_ring_setup_hdr hdr; - struct htt_rx_ring_setup_ring32 rings[0]; + struct htt_rx_ring_setup_ring32 rings[]; } __packed; struct htt_rx_ring_setup_64 { struct htt_rx_ring_setup_hdr hdr; - struct htt_rx_ring_setup_ring64 rings[0]; + struct htt_rx_ring_setup_ring64 rings[]; } __packed; /* @@ -732,7 +732,7 @@ struct htt_rx_indication { * %mpdu_ranges starts after &%prefix + roundup(%fw_rx_desc_bytes, 4) * and has %num_mpdu_ranges elements. */ - struct htt_rx_indication_mpdu_range mpdu_ranges[0]; + struct htt_rx_indication_mpdu_range mpdu_ranges[]; } __packed; /* High latency version of the RX indication */ @@ -741,7 +741,7 @@ struct htt_rx_indication_hl { struct htt_rx_indication_ppdu ppdu; struct htt_rx_indication_prefix prefix; struct fw_rx_desc_hl fw_desc; - struct htt_rx_indication_mpdu_range mpdu_ranges[0]; + struct htt_rx_indication_mpdu_range mpdu_ranges[]; } __packed; struct htt_hl_rx_desc { @@ -908,7 +908,7 @@ struct htt_append_retries { struct htt_data_tx_completion_ext { struct htt_append_retries a_retries; __le32 t_stamp; - __le16 msdus_rssi[0]; + __le16 msdus_rssi[]; } __packed; /** @@ -992,7 +992,7 @@ struct htt_data_tx_completion { } __packed; u8 num_msdus; u8 flags2; /* HTT_TX_CMPL_FLAG_DATA_RSSI */ - __le16 msdus[0]; /* variable length based on %num_msdus */ + __le16 msdus[]; /* variable length based on %num_msdus */ } __packed; #define HTT_TX_PPDU_DUR_INFO0_PEER_ID_MASK GENMASK(15, 0) @@ -1007,7 +1007,7 @@ struct htt_data_tx_ppdu_dur { struct htt_data_tx_compl_ppdu_dur { __le32 info0; /* HTT_TX_COMPL_PPDU_DUR_INFO0_ */ - struct htt_data_tx_ppdu_dur ppdu_dur[0]; + struct htt_data_tx_ppdu_dur ppdu_dur[]; } __packed; struct htt_tx_compl_ind_base { @@ -1033,7 +1033,7 @@ struct htt_rc_update { u8 addr[6]; u8 num_elems; u8 rsvd0; - struct htt_rc_tx_done_params params[0]; /* variable length %num_elems */ + struct htt_rc_tx_done_params params[]; /* variable length %num_elems */ } __packed; /* see htt_rx_indication for similar fields and descriptions */ @@ -1050,7 +1050,7 @@ struct htt_rx_fragment_indication { __le16 fw_rx_desc_bytes; __le16 rsvd0; - u8 fw_msdu_rx_desc[0]; + u8 fw_msdu_rx_desc[]; } __packed; #define ATH10K_IEEE80211_EXTIV BIT(5) @@ -1075,7 +1075,7 @@ struct htt_rx_pn_ind { u8 seqno_end; u8 pn_ie_count; u8 reserved; - u8 pn_ies[0]; + u8 pn_ies[]; } __packed; struct htt_rx_offload_msdu { @@ -1084,7 +1084,7 @@ struct htt_rx_offload_msdu { u8 vdev_id; u8 tid; u8 fw_desc; - u8 payload[0]; + u8 payload[]; } __packed; struct htt_rx_offload_ind { @@ -1167,7 +1167,7 @@ struct htt_rx_test { * a) num_ints * sizeof(__le32) * b) num_chars * sizeof(u8) aligned to 4bytes */ - u8 payload[0]; + u8 payload[]; } __packed; static inline __le32 *htt_rx_test_get_ints(struct htt_rx_test *rx_test) @@ -1201,7 +1201,7 @@ static inline u8 *htt_rx_test_get_chars(struct htt_rx_test *rx_test) */ struct htt_pktlog_msg { u8 pad[3]; - u8 payload[0]; + u8 payload[]; } __packed; struct htt_dbg_stats_rx_reorder_stats { @@ -1490,7 +1490,7 @@ struct htt_stats_conf_item { } __packed; u8 pad; __le16 length; - u8 payload[0]; /* roundup(length, 4) long */ + u8 payload[]; /* roundup(length, 4) long */ } __packed; struct htt_stats_conf { @@ -1499,7 +1499,7 @@ struct htt_stats_conf { __le32 cookie_msb; /* each item has variable length! */ - struct htt_stats_conf_item items[0]; + struct htt_stats_conf_item items[]; } __packed; static inline struct htt_stats_conf_item *htt_stats_conf_next_item( @@ -1673,8 +1673,8 @@ struct htt_tx_fetch_ind { __le32 token; __le16 num_resp_ids; __le16 num_records; - struct htt_tx_fetch_record records[0]; __le32 resp_ids[0]; /* ath10k_htt_get_tx_fetch_ind_resp_ids() */ + struct htt_tx_fetch_record records[]; } __packed; static inline void * @@ -1689,13 +1689,13 @@ struct htt_tx_fetch_resp { __le16 fetch_seq_num; __le16 num_records; __le32 token; - struct htt_tx_fetch_record records[0]; + struct htt_tx_fetch_record records[]; } __packed; struct htt_tx_fetch_confirm { u8 pad0; __le16 num_resp_ids; - __le32 resp_ids[0]; + __le32 resp_ids[]; } __packed; enum htt_tx_mode_switch_mode { @@ -1727,7 +1727,7 @@ struct htt_tx_mode_switch_ind { __le16 info0; /* HTT_TX_MODE_SWITCH_IND_INFO0_ */ __le16 info1; /* HTT_TX_MODE_SWITCH_IND_INFO1_ */ u8 pad1[2]; - struct htt_tx_mode_switch_record records[0]; + struct htt_tx_mode_switch_record records[]; } __packed; struct htt_channel_change { @@ -1757,7 +1757,7 @@ struct htt_peer_tx_stats { u8 num_ppdu; u8 ppdu_len; u8 version; - u8 payload[0]; + u8 payload[]; } __packed; #define ATH10K_10_2_TX_STATS_OFFSET 136 @@ -2206,7 +2206,7 @@ struct htt_rx_desc { struct rx_ppdu_end ppdu_end; } __packed; u8 rx_hdr_status[RX_HTT_HDR_STATUS_LEN]; - u8 msdu_payload[0]; + u8 msdu_payload[]; }; #define HTT_RX_DESC_HL_INFO_SEQ_NUM_MASK 0x00000fff diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index d9907a4648a8..f16edcb9f326 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -165,7 +165,7 @@ enum qca9377_chip_id_rev { struct ath10k_fw_ie { __le32 id; __le32 len; - u8 data[0]; + u8 data[]; }; enum ath10k_fw_ie_type { diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 91f5444ecedb..919d15584d4a 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3967,6 +3967,9 @@ void ath10k_mgmt_over_wmi_tx_work(struct work_struct *work) if (ret) { ath10k_warn(ar, "failed to transmit management frame by ref via WMI: %d\n", ret); + /* remove this msdu from idr tracking */ + ath10k_wmi_cleanup_mgmt_tx_send(ar, skb); + dma_unmap_single(ar->dev, paddr, skb->len, DMA_TO_DEVICE); ieee80211_free_txskb(ar->hw, skb); diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index e3cbd259a2dc..862d0901c5b8 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h @@ -178,15 +178,16 @@ struct ath10k_pci { */ u32 (*targ_cpu_to_ce_addr)(struct ath10k *ar, u32 addr); + struct ce_attr *attr; + struct ce_pipe_config *pipe_config; + struct ce_service_to_pipe *serv_to_pipe; + /* Keep this entry in the last, memory for struct ath10k_ahb is * allocated (ahb support enabled case) in the continuation of * this struct. */ - struct ath10k_ahb ahb[0]; + struct ath10k_ahb ahb[]; - struct ce_attr *attr; - struct ce_pipe_config *pipe_config; - struct ce_service_to_pipe *serv_to_pipe; }; static inline struct ath10k_pci *ath10k_pci_priv(struct ath10k *ar) diff --git a/drivers/net/wireless/ath/ath10k/qmi.c b/drivers/net/wireless/ath/ath10k/qmi.c index 5ae829b46c3d..5468a41e928e 100644 --- a/drivers/net/wireless/ath/ath10k/qmi.c +++ b/drivers/net/wireless/ath/ath10k/qmi.c @@ -961,7 +961,16 @@ static void ath10k_qmi_del_server(struct qmi_handle *qmi_hdl, container_of(qmi_hdl, struct ath10k_qmi, qmi_hdl); qmi->fw_ready = false; - ath10k_qmi_driver_event_post(qmi, ATH10K_QMI_EVENT_SERVER_EXIT, NULL); + + /* + * The del_server event is to be processed only if coming from + * the qmi server. The qmi infrastructure sends del_server, when + * any client releases the qmi handle. In this case do not process + * this del_server event. + */ + if (qmi->state == ATH10K_QMI_STATE_INIT_DONE) + ath10k_qmi_driver_event_post(qmi, ATH10K_QMI_EVENT_SERVER_EXIT, + NULL); } static struct qmi_ops ath10k_qmi_ops = { @@ -1046,6 +1055,7 @@ int ath10k_qmi_init(struct ath10k *ar, u32 msa_size) if (ret) goto err_qmi_lookup; + qmi->state = ATH10K_QMI_STATE_INIT_DONE; return 0; err_qmi_lookup: @@ -1064,6 +1074,7 @@ int ath10k_qmi_deinit(struct ath10k *ar) struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); struct ath10k_qmi *qmi = ar_snoc->qmi; + qmi->state = ATH10K_QMI_STATE_DEINIT; qmi_handle_release(&qmi->qmi_hdl); cancel_work_sync(&qmi->event_work); destroy_workqueue(qmi->event_wq); diff --git a/drivers/net/wireless/ath/ath10k/qmi.h b/drivers/net/wireless/ath/ath10k/qmi.h index 450be18b60ad..16190511318d 100644 --- a/drivers/net/wireless/ath/ath10k/qmi.h +++ b/drivers/net/wireless/ath/ath10k/qmi.h @@ -83,6 +83,11 @@ struct ath10k_qmi_driver_event { void *data; }; +enum ath10k_qmi_state { + ATH10K_QMI_STATE_INIT_DONE, + ATH10K_QMI_STATE_DEINIT, +}; + struct ath10k_qmi { struct ath10k *ar; struct qmi_handle qmi_hdl; @@ -102,6 +107,7 @@ struct ath10k_qmi { char fw_build_timestamp[MAX_TIMESTAMP_LEN + 1]; struct ath10k_qmi_cal_data cal_data[MAX_NUM_CAL_V01]; bool msa_fixed_perm; + enum ath10k_qmi_state state; }; int ath10k_qmi_wlan_enable(struct ath10k *ar, diff --git a/drivers/net/wireless/ath/ath10k/wmi-ops.h b/drivers/net/wireless/ath/ath10k/wmi-ops.h index 6b730f59fd5b..0dd484f85082 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-ops.h +++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h @@ -140,6 +140,7 @@ struct wmi_ops { struct sk_buff *(*gen_mgmt_tx_send)(struct ath10k *ar, struct sk_buff *skb, dma_addr_t paddr); + int (*cleanup_mgmt_tx_send)(struct ath10k *ar, struct sk_buff *msdu); struct sk_buff *(*gen_dbglog_cfg)(struct ath10k *ar, u64 module_enable, u32 log_level); struct sk_buff *(*gen_pktlog_enable)(struct ath10k *ar, u32 filter); @@ -449,6 +450,15 @@ ath10k_wmi_get_txbf_conf_scheme(struct ath10k *ar) } static inline int +ath10k_wmi_cleanup_mgmt_tx_send(struct ath10k *ar, struct sk_buff *msdu) +{ + if (!ar->wmi.ops->cleanup_mgmt_tx_send) + return -EOPNOTSUPP; + + return ar->wmi.ops->cleanup_mgmt_tx_send(ar, msdu); +} + +static inline int ath10k_wmi_mgmt_tx_send(struct ath10k *ar, struct sk_buff *msdu, dma_addr_t paddr) { diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 9187b62b331c..932266d1111b 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -3010,12 +3010,24 @@ ath10k_wmi_tlv_op_gen_request_peer_stats_info(struct ath10k *ar, if (type == WMI_REQUEST_ONE_PEER_STATS_INFO) ether_addr_copy(cmd->peer_macaddr.addr, addr); - cmd->reset_after_request = reset; + cmd->reset_after_request = __cpu_to_le32(reset); ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv request peer stats info\n"); return skb; } static int +ath10k_wmi_tlv_op_cleanup_mgmt_tx_send(struct ath10k *ar, + struct sk_buff *msdu) +{ + struct ath10k_skb_cb *cb = ATH10K_SKB_CB(msdu); + struct ath10k_wmi *wmi = &ar->wmi; + + idr_remove(&wmi->mgmt_pending_tx, cb->msdu_id); + + return 0; +} + +static int ath10k_wmi_mgmt_tx_alloc_msdu_id(struct ath10k *ar, struct sk_buff *skb, dma_addr_t paddr) { @@ -3089,6 +3101,8 @@ ath10k_wmi_tlv_op_gen_mgmt_tx_send(struct ath10k *ar, struct sk_buff *msdu, if (desc_id < 0) goto err_free_skb; + cb->msdu_id = desc_id; + ptr = (void *)skb->data; tlv = ptr; tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_MGMT_TX_CMD); @@ -4540,6 +4554,7 @@ static const struct wmi_ops wmi_tlv_ops = { .gen_force_fw_hang = ath10k_wmi_tlv_op_gen_force_fw_hang, /* .gen_mgmt_tx = not implemented; HTT is used */ .gen_mgmt_tx_send = ath10k_wmi_tlv_op_gen_mgmt_tx_send, + .cleanup_mgmt_tx_send = ath10k_wmi_tlv_op_cleanup_mgmt_tx_send, .gen_dbglog_cfg = ath10k_wmi_tlv_op_gen_dbglog_cfg, .gen_pktlog_enable = ath10k_wmi_tlv_op_gen_pktlog_enable, .gen_pktlog_disable = ath10k_wmi_tlv_op_gen_pktlog_disable, diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h index 6e0537dabd1d..e77b97ca5c7f 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h @@ -1637,7 +1637,7 @@ wmi_tlv_svc_map_ext(const __le32 *in, unsigned long *out, size_t len) struct wmi_tlv { __le16 len; __le16 tag; - u8 value[0]; + u8 value[]; } __packed; struct ath10k_mgmt_tx_pkt_addr { @@ -2037,7 +2037,7 @@ struct wmi_tlv_bcn_tx_status_ev { struct wmi_tlv_bcn_prb_info { __le32 caps; __le32 erp; - u8 ies[0]; + u8 ies[]; } __packed; struct wmi_tlv_bcn_tmpl_cmd { @@ -2068,7 +2068,7 @@ struct wmi_tlv_diag_item { __le16 len; __le32 timestamp; __le32 code; - u8 payload[0]; + u8 payload[]; } __packed; struct wmi_tlv_diag_data_ev { diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 0f05405bebc0..511144b36231 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -2292,7 +2292,7 @@ struct wmi_service_ready_event { * where FW can access this memory directly (or) by DMA. */ __le32 num_mem_reqs; - struct wlan_host_mem_req mem_reqs[0]; + struct wlan_host_mem_req mem_reqs[]; } __packed; /* This is the definition from 10.X firmware branch */ @@ -2331,7 +2331,7 @@ struct wmi_10x_service_ready_event { */ __le32 num_mem_reqs; - struct wlan_host_mem_req mem_reqs[0]; + struct wlan_host_mem_req mem_reqs[]; } __packed; #define WMI_SERVICE_READY_TIMEOUT_HZ (5 * HZ) @@ -3086,19 +3086,19 @@ struct wmi_chan_list_entry { struct wmi_chan_list { __le32 tag; /* WMI_CHAN_LIST_TAG */ __le32 num_chan; - struct wmi_chan_list_entry channel_list[0]; + struct wmi_chan_list_entry channel_list[]; } __packed; struct wmi_bssid_list { __le32 tag; /* WMI_BSSID_LIST_TAG */ __le32 num_bssid; - struct wmi_mac_addr bssid_list[0]; + struct wmi_mac_addr bssid_list[]; } __packed; struct wmi_ie_data { __le32 tag; /* WMI_IE_TAG */ __le32 ie_len; - u8 ie_data[0]; + u8 ie_data[]; } __packed; struct wmi_ssid { @@ -3109,7 +3109,7 @@ struct wmi_ssid { struct wmi_ssid_list { __le32 tag; /* WMI_SSID_LIST_TAG */ __le32 num_ssids; - struct wmi_ssid ssids[0]; + struct wmi_ssid ssids[]; } __packed; /* prefix used by scan requestor ids on the host */ @@ -3311,7 +3311,7 @@ struct wmi_stop_scan_arg { struct wmi_scan_chan_list_cmd { __le32 num_scan_chans; - struct wmi_channel chan_info[0]; + struct wmi_channel chan_info[]; } __packed; struct wmi_scan_chan_list_arg { @@ -3395,12 +3395,12 @@ struct wmi_mgmt_rx_hdr_v2 { struct wmi_mgmt_rx_event_v1 { struct wmi_mgmt_rx_hdr_v1 hdr; - u8 buf[0]; + u8 buf[]; } __packed; struct wmi_mgmt_rx_event_v2 { struct wmi_mgmt_rx_hdr_v2 hdr; - u8 buf[0]; + u8 buf[]; } __packed; struct wmi_10_4_mgmt_rx_hdr { @@ -3415,7 +3415,7 @@ struct wmi_10_4_mgmt_rx_hdr { struct wmi_10_4_mgmt_rx_event { struct wmi_10_4_mgmt_rx_hdr hdr; - u8 buf[0]; + u8 buf[]; } __packed; struct wmi_mgmt_rx_ext_info { @@ -3455,14 +3455,14 @@ struct wmi_phyerr { __le32 rssi_chains[4]; __le16 nf_chains[4]; __le32 buf_len; - u8 buf[0]; + u8 buf[]; } __packed; struct wmi_phyerr_event { __le32 num_phyerrs; __le32 tsf_l32; __le32 tsf_u32; - struct wmi_phyerr phyerrs[0]; + struct wmi_phyerr phyerrs[]; } __packed; struct wmi_10_4_phyerr_event { @@ -3479,7 +3479,7 @@ struct wmi_10_4_phyerr_event { __le32 phy_err_mask[2]; __le32 tsf_timestamp; __le32 buf_len; - u8 buf[0]; + u8 buf[]; } __packed; struct wmi_radar_found_info { @@ -3592,7 +3592,7 @@ struct wmi_mgmt_tx_hdr { struct wmi_mgmt_tx_cmd { struct wmi_mgmt_tx_hdr hdr; - u8 buf[0]; + u8 buf[]; } __packed; struct wmi_echo_event { @@ -4628,7 +4628,7 @@ struct wmi_stats_event { * By having a zero sized array, the pointer to data area * becomes available without increasing the struct size */ - u8 data[0]; + u8 data[]; } __packed; struct wmi_10_2_stats_event { @@ -4638,7 +4638,7 @@ struct wmi_10_2_stats_event { __le32 num_vdev_stats; __le32 num_peer_stats; __le32 num_bcnflt_stats; - u8 data[0]; + u8 data[]; } __packed; /* @@ -5033,7 +5033,7 @@ struct wmi_vdev_install_key_cmd { __le32 key_rxmic_len; /* contains key followed by tx mic followed by rx mic */ - u8 key_data[0]; + u8 key_data[]; } __packed; struct wmi_vdev_install_key_arg { @@ -5703,7 +5703,7 @@ struct wmi_bcn_tx_hdr { struct wmi_bcn_tx_cmd { struct wmi_bcn_tx_hdr hdr; - u8 *bcn[0]; + u8 *bcn[]; } __packed; struct wmi_bcn_tx_arg { @@ -6120,7 +6120,7 @@ struct wmi_bcn_info { struct wmi_host_swba_event { __le32 vdev_map; - struct wmi_bcn_info bcn_info[0]; + struct wmi_bcn_info bcn_info[]; } __packed; struct wmi_10_2_4_bcn_info { @@ -6130,7 +6130,7 @@ struct wmi_10_2_4_bcn_info { struct wmi_10_2_4_host_swba_event { __le32 vdev_map; - struct wmi_10_2_4_bcn_info bcn_info[0]; + struct wmi_10_2_4_bcn_info bcn_info[]; } __packed; /* 16 words = 512 client + 1 word = for guard */ @@ -6171,7 +6171,7 @@ struct wmi_10_4_bcn_info { struct wmi_10_4_host_swba_event { __le32 vdev_map; - struct wmi_10_4_bcn_info bcn_info[0]; + struct wmi_10_4_bcn_info bcn_info[]; } __packed; #define WMI_MAX_AP_VDEV 16 diff --git a/drivers/net/wireless/ath/ath11k/ahb.c b/drivers/net/wireless/ath/ath11k/ahb.c index 3b2b76d602f2..30092841ac46 100644 --- a/drivers/net/wireless/ath/ath11k/ahb.c +++ b/drivers/net/wireless/ath/ath11k/ahb.c @@ -10,6 +10,7 @@ #include <linux/dma-mapping.h> #include "ahb.h" #include "debug.h" +#include "hif.h" #include <linux/remoteproc.h> static const struct of_device_id ath11k_ahb_of_match[] = { @@ -434,6 +435,16 @@ enum ext_irq_num { tcl2host_status_ring, }; +static inline u32 ath11k_ahb_read32(struct ath11k_base *ab, u32 offset) +{ + return ioread32(ab->mem + offset); +} + +static inline void ath11k_ahb_write32(struct ath11k_base *ab, u32 offset, u32 value) +{ + iowrite32(value, ab->mem + offset); +} + static void ath11k_ahb_kill_tasklets(struct ath11k_base *ab) { int i; @@ -575,7 +586,7 @@ static void ath11k_ahb_ce_irqs_disable(struct ath11k_base *ab) } } -int ath11k_ahb_start(struct ath11k_base *ab) +static int ath11k_ahb_start(struct ath11k_base *ab) { ath11k_ahb_ce_irqs_enable(ab); ath11k_ce_rx_post_buf(ab); @@ -583,7 +594,7 @@ int ath11k_ahb_start(struct ath11k_base *ab) return 0; } -void ath11k_ahb_ext_irq_enable(struct ath11k_base *ab) +static void ath11k_ahb_ext_irq_enable(struct ath11k_base *ab) { int i; @@ -595,13 +606,13 @@ void ath11k_ahb_ext_irq_enable(struct ath11k_base *ab) } } -void ath11k_ahb_ext_irq_disable(struct ath11k_base *ab) +static void ath11k_ahb_ext_irq_disable(struct ath11k_base *ab) { __ath11k_ahb_ext_irq_disable(ab); ath11k_ahb_sync_ext_irqs(ab); } -void ath11k_ahb_stop(struct ath11k_base *ab) +static void ath11k_ahb_stop(struct ath11k_base *ab) { if (!test_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags)) ath11k_ahb_ce_irqs_disable(ab); @@ -611,7 +622,7 @@ void ath11k_ahb_stop(struct ath11k_base *ab) ath11k_ce_cleanup_pipes(ab); } -int ath11k_ahb_power_up(struct ath11k_base *ab) +static int ath11k_ahb_power_up(struct ath11k_base *ab) { int ret; @@ -622,7 +633,7 @@ int ath11k_ahb_power_up(struct ath11k_base *ab) return ret; } -void ath11k_ahb_power_down(struct ath11k_base *ab) +static void ath11k_ahb_power_down(struct ath11k_base *ab) { rproc_shutdown(ab->tgt_rproc); } @@ -834,8 +845,8 @@ static int ath11k_ahb_config_irq(struct ath11k_base *ab) return ret; } -int ath11k_ahb_map_service_to_pipe(struct ath11k_base *ab, u16 service_id, - u8 *ul_pipe, u8 *dl_pipe) +static int ath11k_ahb_map_service_to_pipe(struct ath11k_base *ab, u16 service_id, + u8 *ul_pipe, u8 *dl_pipe) { const struct service_to_pipe *entry; bool ul_set = false, dl_set = false; @@ -877,6 +888,18 @@ int ath11k_ahb_map_service_to_pipe(struct ath11k_base *ab, u16 service_id, return 0; } +static const struct ath11k_hif_ops ath11k_ahb_hif_ops = { + .start = ath11k_ahb_start, + .stop = ath11k_ahb_stop, + .read32 = ath11k_ahb_read32, + .write32 = ath11k_ahb_write32, + .irq_enable = ath11k_ahb_ext_irq_enable, + .irq_disable = ath11k_ahb_ext_irq_disable, + .map_service_to_pipe = ath11k_ahb_map_service_to_pipe, + .power_down = ath11k_ahb_power_down, + .power_up = ath11k_ahb_power_up, +}; + static int ath11k_ahb_probe(struct platform_device *pdev) { struct ath11k_base *ab; @@ -891,13 +914,7 @@ static int ath11k_ahb_probe(struct platform_device *pdev) return -EINVAL; } - mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem_res) { - dev_err(&pdev->dev, "failed to get IO memory resource\n"); - return -ENXIO; - } - - mem = devm_ioremap_resource(&pdev->dev, mem_res); + mem = devm_platform_get_and_ioremap_resource(pdev, 0, &mem_res); if (IS_ERR(mem)) { dev_err(&pdev->dev, "ioremap error\n"); return PTR_ERR(mem); @@ -909,12 +926,13 @@ static int ath11k_ahb_probe(struct platform_device *pdev) return ret; } - ab = ath11k_core_alloc(&pdev->dev); + ab = ath11k_core_alloc(&pdev->dev, 0, ATH11K_BUS_AHB); if (!ab) { dev_err(&pdev->dev, "failed to allocate ath11k base\n"); return -ENOMEM; } + ab->hif.ops = &ath11k_ahb_hif_ops; ab->pdev = pdev; ab->hw_rev = (enum ath11k_hw_rev)of_id->data; ab->mem = mem; @@ -993,12 +1011,17 @@ static struct platform_driver ath11k_ahb_driver = { .remove = ath11k_ahb_remove, }; -int ath11k_ahb_init(void) +static int ath11k_ahb_init(void) { return platform_driver_register(&ath11k_ahb_driver); } +module_init(ath11k_ahb_init); -void ath11k_ahb_exit(void) +static void ath11k_ahb_exit(void) { platform_driver_unregister(&ath11k_ahb_driver); } +module_exit(ath11k_ahb_exit); + +MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11ax wireless chip"); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/ath/ath11k/ahb.h b/drivers/net/wireless/ath/ath11k/ahb.h index 93f46dfe22df..6c7b26ac6545 100644 --- a/drivers/net/wireless/ath/ath11k/ahb.h +++ b/drivers/net/wireless/ath/ath11k/ahb.h @@ -10,26 +10,4 @@ #define ATH11K_AHB_RECOVERY_TIMEOUT (3 * HZ) struct ath11k_base; -static inline u32 ath11k_ahb_read32(struct ath11k_base *ab, u32 offset) -{ - return ioread32(ab->mem + offset); -} - -static inline void ath11k_ahb_write32(struct ath11k_base *ab, u32 offset, u32 value) -{ - iowrite32(value, ab->mem + offset); -} - -void ath11k_ahb_ext_irq_enable(struct ath11k_base *ab); -void ath11k_ahb_ext_irq_disable(struct ath11k_base *ab); -int ath11k_ahb_start(struct ath11k_base *ab); -void ath11k_ahb_stop(struct ath11k_base *ab); -int ath11k_ahb_power_up(struct ath11k_base *ab); -void ath11k_ahb_power_down(struct ath11k_base *ab); -int ath11k_ahb_map_service_to_pipe(struct ath11k_base *ab, u16 service_id, - u8 *ul_pipe, u8 *dl_pipe); - -int ath11k_ahb_init(void); -void ath11k_ahb_exit(void); - #endif diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c index bf5657d2ae18..02501cc154fe 100644 --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c @@ -7,11 +7,11 @@ #include <linux/slab.h> #include <linux/remoteproc.h> #include <linux/firmware.h> -#include "ahb.h" #include "core.h" #include "dp_tx.h" #include "dp_rx.h" #include "debug.h" +#include "hif.h" unsigned int ath11k_debug_mask; module_param_named(debug_mask, ath11k_debug_mask, uint, 0644); @@ -41,6 +41,7 @@ u8 ath11k_core_get_hw_mac_id(struct ath11k_base *ab, int pdev_idx) return ATH11K_INVALID_HW_MAC_ID; } } +EXPORT_SYMBOL(ath11k_core_get_hw_mac_id); static int ath11k_core_create_board_name(struct ath11k_base *ab, char *name, size_t name_len) @@ -324,7 +325,7 @@ static void ath11k_core_stop(struct ath11k_base *ab) { if (!test_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags)) ath11k_qmi_firmware_stop(ab); - ath11k_ahb_stop(ab); + ath11k_hif_stop(ab); ath11k_wmi_detach(ab); ath11k_dp_pdev_reo_cleanup(ab); @@ -347,7 +348,7 @@ static int ath11k_core_soc_create(struct ath11k_base *ab) goto err_qmi_deinit; } - ret = ath11k_ahb_power_up(ab); + ret = ath11k_hif_power_up(ab); if (ret) { ath11k_err(ab, "failed to power up :%d\n", ret); goto err_debugfs_reg; @@ -415,7 +416,7 @@ static void ath11k_core_pdev_destroy(struct ath11k_base *ab) { ath11k_thermal_unregister(ab); ath11k_mac_unregister(ab); - ath11k_ahb_ext_irq_disable(ab); + ath11k_hif_irq_disable(ab); ath11k_dp_pdev_free(ab); ath11k_debug_pdev_destroy(ab); } @@ -443,7 +444,7 @@ static int ath11k_core_start(struct ath11k_base *ab, goto err_wmi_detach; } - ret = ath11k_ahb_start(ab); + ret = ath11k_hif_start(ab); if (ret) { ath11k_err(ab, "failed to start HIF: %d\n", ret); goto err_wmi_detach; @@ -522,7 +523,7 @@ err_reo_cleanup: err_mac_destroy: ath11k_mac_destroy(ab); err_hif_stop: - ath11k_ahb_stop(ab); + ath11k_hif_stop(ab); err_wmi_detach: ath11k_wmi_detach(ab); err_firmware_stop: @@ -559,7 +560,7 @@ int ath11k_core_qmi_firmware_ready(struct ath11k_base *ab) ath11k_err(ab, "failed to create pdev core: %d\n", ret); goto err_core_stop; } - ath11k_ahb_ext_irq_enable(ab); + ath11k_hif_irq_enable(ab); mutex_unlock(&ab->core_lock); return 0; @@ -579,9 +580,9 @@ static int ath11k_core_reconfigure_on_crash(struct ath11k_base *ab) mutex_lock(&ab->core_lock); ath11k_thermal_unregister(ab); - ath11k_ahb_ext_irq_disable(ab); + ath11k_hif_irq_disable(ab); ath11k_dp_pdev_free(ab); - ath11k_ahb_stop(ab); + ath11k_hif_stop(ab); ath11k_wmi_detach(ab); ath11k_dp_pdev_reo_cleanup(ab); mutex_unlock(&ab->core_lock); @@ -744,7 +745,7 @@ void ath11k_core_deinit(struct ath11k_base *ab) mutex_unlock(&ab->core_lock); - ath11k_ahb_power_down(ab); + ath11k_hif_power_down(ab); ath11k_mac_destroy(ab); ath11k_core_soc_destroy(ab); } @@ -754,11 +755,12 @@ void ath11k_core_free(struct ath11k_base *ab) kfree(ab); } -struct ath11k_base *ath11k_core_alloc(struct device *dev) +struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size, + enum ath11k_bus bus) { struct ath11k_base *ab; - ab = kzalloc(sizeof(*ab), GFP_KERNEL); + ab = kzalloc(sizeof(*ab) + priv_size, GFP_KERNEL); if (!ab) return NULL; @@ -784,24 +786,3 @@ err_sc_free: kfree(ab); return NULL; } - -static int __init ath11k_init(void) -{ - int ret; - - ret = ath11k_ahb_init(); - if (ret) - printk(KERN_ERR "failed to register ath11k ahb driver: %d\n", - ret); - return ret; -} -module_init(ath11k_init); - -static void __exit ath11k_exit(void) -{ - ath11k_ahb_exit(); -} -module_exit(ath11k_exit); - -MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11ax wireless chip"); -MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h index 70ec544eee67..e04f0e711779 100644 --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h @@ -607,7 +607,9 @@ struct ath11k_base { void __iomem *mem; unsigned long mem_len; - const struct ath11k_hif_ops *hif_ops; + struct { + const struct ath11k_hif_ops *ops; + } hif; struct ath11k_ce ce; struct timer_list rx_replenish_retry; @@ -665,6 +667,9 @@ struct ath11k_base { /* Round robbin based TCL ring selector */ atomic_t tcl_ring_selector; + + /* must be last */ + u8 drv_priv[0] __aligned(sizeof(void *)); }; struct ath11k_fw_stats_pdev { @@ -801,7 +806,8 @@ struct ath11k_peer *ath11k_peer_find_by_id(struct ath11k_base *ab, int peer_id); int ath11k_core_qmi_firmware_ready(struct ath11k_base *ab); int ath11k_core_init(struct ath11k_base *ath11k); void ath11k_core_deinit(struct ath11k_base *ath11k); -struct ath11k_base *ath11k_core_alloc(struct device *dev); +struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size, + enum ath11k_bus bus); void ath11k_core_free(struct ath11k_base *ath11k); int ath11k_core_fetch_bdf(struct ath11k_base *ath11k, struct ath11k_board_data *bd); diff --git a/drivers/net/wireless/ath/ath11k/debug_htt_stats.c b/drivers/net/wireless/ath/ath11k/debug_htt_stats.c index 5db0c27de475..6b532dc99c98 100644 --- a/drivers/net/wireless/ath/ath11k/debug_htt_stats.c +++ b/drivers/net/wireless/ath/ath11k/debug_htt_stats.c @@ -4306,6 +4306,7 @@ void ath11k_dbg_htt_ext_stats_handler(struct ath11k_base *ab, u32 len; u64 cookie; int ret; + bool send_completion = false; u8 pdev_id; msg = (struct ath11k_htt_extd_stats_msg *)skb->data; @@ -4330,11 +4331,11 @@ void ath11k_dbg_htt_ext_stats_handler(struct ath11k_base *ab, return; spin_lock_bh(&ar->debug.htt_stats.lock); - if (stats_req->done) { - spin_unlock_bh(&ar->debug.htt_stats.lock); - return; - } - stats_req->done = true; + + stats_req->done = FIELD_GET(HTT_T2H_EXT_STATS_INFO1_DONE, msg->info1); + if (stats_req->done) + send_completion = true; + spin_unlock_bh(&ar->debug.htt_stats.lock); len = FIELD_GET(HTT_T2H_EXT_STATS_INFO1_LENGTH, msg->info1); @@ -4344,7 +4345,8 @@ void ath11k_dbg_htt_ext_stats_handler(struct ath11k_base *ab, if (ret) ath11k_warn(ab, "Failed to parse tlv %d\n", ret); - complete(&stats_req->cmpln); + if (send_completion) + complete(&stats_req->cmpln); } static ssize_t ath11k_read_htt_stats_type(struct file *file, @@ -4497,28 +4499,54 @@ static int ath11k_open_htt_stats(struct inode *inode, struct file *file) if (type == ATH11K_DBG_HTT_EXT_STATS_RESET) return -EPERM; + mutex_lock(&ar->conf_mutex); + + if (ar->state != ATH11K_STATE_ON) { + ret = -ENETDOWN; + goto err_unlock; + } + + if (ar->debug.htt_stats.stats_req) { + ret = -EAGAIN; + goto err_unlock; + } + stats_req = vzalloc(sizeof(*stats_req) + ATH11K_HTT_STATS_BUF_SIZE); - if (!stats_req) - return -ENOMEM; + if (!stats_req) { + ret = -ENOMEM; + goto err_unlock; + } - mutex_lock(&ar->conf_mutex); ar->debug.htt_stats.stats_req = stats_req; stats_req->type = type; + ret = ath11k_dbg_htt_stats_req(ar); - mutex_unlock(&ar->conf_mutex); if (ret < 0) goto out; file->private_data = stats_req; + + mutex_unlock(&ar->conf_mutex); + return 0; out: vfree(stats_req); + ar->debug.htt_stats.stats_req = NULL; +err_unlock: + mutex_unlock(&ar->conf_mutex); + return ret; } static int ath11k_release_htt_stats(struct inode *inode, struct file *file) { + struct ath11k *ar = inode->i_private; + + mutex_lock(&ar->conf_mutex); vfree(file->private_data); + ar->debug.htt_stats.stats_req = NULL; + mutex_unlock(&ar->conf_mutex); + return 0; } diff --git a/drivers/net/wireless/ath/ath11k/dp.c b/drivers/net/wireless/ath/ath11k/dp.c index 145015d2f49c..9ae743e528af 100644 --- a/drivers/net/wireless/ath/ath11k/dp.c +++ b/drivers/net/wireless/ath/ath11k/dp.c @@ -701,6 +701,7 @@ int ath11k_dp_service_srng(struct ath11k_base *ab, done: return tot_work_done; } +EXPORT_SYMBOL(ath11k_dp_service_srng); void ath11k_dp_pdev_free(struct ath11k_base *ab) { diff --git a/drivers/net/wireless/ath/ath11k/dp.h b/drivers/net/wireless/ath/ath11k/dp.h index 222de10e4b93..058a5c1d86ff 100644 --- a/drivers/net/wireless/ath/ath11k/dp.h +++ b/drivers/net/wireless/ath/ath11k/dp.h @@ -1517,6 +1517,7 @@ struct htt_ext_stats_cfg_params { * 4 bytes. */ +#define HTT_T2H_EXT_STATS_INFO1_DONE BIT(11) #define HTT_T2H_EXT_STATS_INFO1_LENGTH GENMASK(31, 16) struct ath11k_htt_extd_stats_msg { diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c index 85670608c3e2..a54610d75c40 100644 --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c @@ -2728,7 +2728,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); - continue; + goto move_next; } idr_remove(&rx_ring->bufs_idr, buf_id); @@ -2747,13 +2747,16 @@ static int ath11k_dp_rx_reap_mon_status_ring(struct ath11k_base *ab, int mac_id, tlv = (struct hal_tlv_hdr *)skb->data; if (FIELD_GET(HAL_TLV_HDR_TAG, tlv->tl) != HAL_RX_STATUS_BUFFER_DONE) { - ath11k_hal_srng_src_get_next_entry(ab, srng); - continue; + ath11k_warn(ab, "mon status DONE not set %lx\n", + FIELD_GET(HAL_TLV_HDR_TAG, + tlv->tl)); + dev_kfree_skb_any(skb); + goto move_next; } __skb_queue_tail(skb_list, skb); } - +move_next: skb = ath11k_dp_rx_alloc_mon_status_buf(ab, rx_ring, &buf_id, GFP_ATOMIC); diff --git a/drivers/net/wireless/ath/ath11k/hal.c b/drivers/net/wireless/ath/ath11k/hal.c index 9e40c4bdd674..d63785178afa 100644 --- a/drivers/net/wireless/ath/ath11k/hal.c +++ b/drivers/net/wireless/ath/ath11k/hal.c @@ -3,10 +3,10 @@ * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. */ #include <linux/dma-mapping.h> -#include "ahb.h" #include "hal_tx.h" #include "debug.h" #include "hal_desc.h" +#include "hif.h" static const struct hal_srng_config hw_srng_config[] = { /* TODO: max_rings can populated by querying HW capabilities */ @@ -351,11 +351,12 @@ static void ath11k_hal_ce_dst_setup(struct ath11k_base *ab, addr = HAL_CE_DST_RING_CTRL + srng_config->reg_start[HAL_SRNG_REG_GRP_R0] + ring_num * srng_config->reg_size[HAL_SRNG_REG_GRP_R0]; - val = ath11k_ahb_read32(ab, addr); + + val = ath11k_hif_read32(ab, addr); val &= ~HAL_CE_DST_R0_DEST_CTRL_MAX_LEN; val |= FIELD_PREP(HAL_CE_DST_R0_DEST_CTRL_MAX_LEN, srng->u.dst_ring.max_buffer_length); - ath11k_ahb_write32(ab, addr, val); + ath11k_hif_write32(ab, addr, val); } static void ath11k_hal_srng_dst_hw_init(struct ath11k_base *ab, @@ -369,34 +370,34 @@ static void ath11k_hal_srng_dst_hw_init(struct ath11k_base *ab, reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R0]; if (srng->flags & HAL_SRNG_FLAGS_MSI_INTR) { - ath11k_ahb_write32(ab, reg_base + - HAL_REO1_RING_MSI1_BASE_LSB_OFFSET, + ath11k_hif_write32(ab, reg_base + + HAL_REO1_RING_MSI1_BASE_LSB_OFFSET, (u32)srng->msi_addr); val = FIELD_PREP(HAL_REO1_RING_MSI1_BASE_MSB_ADDR, ((u64)srng->msi_addr >> HAL_ADDR_MSB_REG_SHIFT)) | HAL_REO1_RING_MSI1_BASE_MSB_MSI1_ENABLE; - ath11k_ahb_write32(ab, reg_base + + ath11k_hif_write32(ab, reg_base + HAL_REO1_RING_MSI1_BASE_MSB_OFFSET, val); - ath11k_ahb_write32(ab, + ath11k_hif_write32(ab, reg_base + HAL_REO1_RING_MSI1_DATA_OFFSET, srng->msi_data); } - ath11k_ahb_write32(ab, reg_base, (u32)srng->ring_base_paddr); + ath11k_hif_write32(ab, reg_base, (u32)srng->ring_base_paddr); val = FIELD_PREP(HAL_REO1_RING_BASE_MSB_RING_BASE_ADDR_MSB, ((u64)srng->ring_base_paddr >> HAL_ADDR_MSB_REG_SHIFT)) | FIELD_PREP(HAL_REO1_RING_BASE_MSB_RING_SIZE, (srng->entry_size * srng->num_entries)); - ath11k_ahb_write32(ab, reg_base + HAL_REO1_RING_BASE_MSB_OFFSET, val); + ath11k_hif_write32(ab, reg_base + HAL_REO1_RING_BASE_MSB_OFFSET, val); val = FIELD_PREP(HAL_REO1_RING_ID_RING_ID, srng->ring_id) | FIELD_PREP(HAL_REO1_RING_ID_ENTRY_SIZE, srng->entry_size); - ath11k_ahb_write32(ab, reg_base + HAL_REO1_RING_ID_OFFSET, val); + ath11k_hif_write32(ab, reg_base + HAL_REO1_RING_ID_OFFSET, val); /* interrupt setup */ val = FIELD_PREP(HAL_REO1_RING_PRDR_INT_SETUP_INTR_TMR_THOLD, @@ -406,22 +407,22 @@ static void ath11k_hal_srng_dst_hw_init(struct ath11k_base *ab, (srng->intr_batch_cntr_thres_entries * srng->entry_size)); - ath11k_ahb_write32(ab, + ath11k_hif_write32(ab, reg_base + HAL_REO1_RING_PRODUCER_INT_SETUP_OFFSET, val); hp_addr = hal->rdp.paddr + ((unsigned long)srng->u.dst_ring.hp_addr - (unsigned long)hal->rdp.vaddr); - ath11k_ahb_write32(ab, reg_base + HAL_REO1_RING_HP_ADDR_LSB_OFFSET, + ath11k_hif_write32(ab, reg_base + HAL_REO1_RING_HP_ADDR_LSB_OFFSET, hp_addr & HAL_ADDR_LSB_REG_MASK); - ath11k_ahb_write32(ab, reg_base + HAL_REO1_RING_HP_ADDR_MSB_OFFSET, + ath11k_hif_write32(ab, reg_base + HAL_REO1_RING_HP_ADDR_MSB_OFFSET, hp_addr >> HAL_ADDR_MSB_REG_SHIFT); /* Initialize head and tail pointers to indicate ring is empty */ reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R2]; - ath11k_ahb_write32(ab, reg_base, 0); - ath11k_ahb_write32(ab, reg_base + HAL_REO1_RING_TP_OFFSET, 0); + ath11k_hif_write32(ab, reg_base, 0); + ath11k_hif_write32(ab, reg_base + HAL_REO1_RING_TP_OFFSET, 0); *srng->u.dst_ring.hp_addr = 0; reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R0]; @@ -434,7 +435,7 @@ static void ath11k_hal_srng_dst_hw_init(struct ath11k_base *ab, val |= HAL_REO1_RING_MISC_MSI_SWAP; val |= HAL_REO1_RING_MISC_SRNG_ENABLE; - ath11k_ahb_write32(ab, reg_base + HAL_REO1_RING_MISC_OFFSET, val); + ath11k_hif_write32(ab, reg_base + HAL_REO1_RING_MISC_OFFSET, val); } static void ath11k_hal_srng_src_hw_init(struct ath11k_base *ab, @@ -448,34 +449,34 @@ static void ath11k_hal_srng_src_hw_init(struct ath11k_base *ab, reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R0]; if (srng->flags & HAL_SRNG_FLAGS_MSI_INTR) { - ath11k_ahb_write32(ab, reg_base + - HAL_TCL1_RING_MSI1_BASE_LSB_OFFSET, + ath11k_hif_write32(ab, reg_base + + HAL_TCL1_RING_MSI1_BASE_LSB_OFFSET, (u32)srng->msi_addr); val = FIELD_PREP(HAL_TCL1_RING_MSI1_BASE_MSB_ADDR, ((u64)srng->msi_addr >> HAL_ADDR_MSB_REG_SHIFT)) | HAL_TCL1_RING_MSI1_BASE_MSB_MSI1_ENABLE; - ath11k_ahb_write32(ab, reg_base + + ath11k_hif_write32(ab, reg_base + HAL_TCL1_RING_MSI1_BASE_MSB_OFFSET, val); - ath11k_ahb_write32(ab, reg_base + + ath11k_hif_write32(ab, reg_base + HAL_TCL1_RING_MSI1_DATA_OFFSET, srng->msi_data); } - ath11k_ahb_write32(ab, reg_base, (u32)srng->ring_base_paddr); + ath11k_hif_write32(ab, reg_base, (u32)srng->ring_base_paddr); val = FIELD_PREP(HAL_TCL1_RING_BASE_MSB_RING_BASE_ADDR_MSB, ((u64)srng->ring_base_paddr >> HAL_ADDR_MSB_REG_SHIFT)) | FIELD_PREP(HAL_TCL1_RING_BASE_MSB_RING_SIZE, (srng->entry_size * srng->num_entries)); - ath11k_ahb_write32(ab, reg_base + HAL_TCL1_RING_BASE_MSB_OFFSET, val); + ath11k_hif_write32(ab, reg_base + HAL_TCL1_RING_BASE_MSB_OFFSET, val); val = FIELD_PREP(HAL_REO1_RING_ID_ENTRY_SIZE, srng->entry_size); - ath11k_ahb_write32(ab, reg_base + HAL_TCL1_RING_ID_OFFSET, val); + ath11k_hif_write32(ab, reg_base + HAL_TCL1_RING_ID_OFFSET, val); /* interrupt setup */ /* NOTE: IPQ8074 v2 requires the interrupt timer threshold in the @@ -488,7 +489,7 @@ static void ath11k_hal_srng_src_hw_init(struct ath11k_base *ab, (srng->intr_batch_cntr_thres_entries * srng->entry_size)); - ath11k_ahb_write32(ab, + ath11k_hif_write32(ab, reg_base + HAL_TCL1_RING_CONSR_INT_SETUP_IX0_OFFSET, val); @@ -497,7 +498,7 @@ static void ath11k_hal_srng_src_hw_init(struct ath11k_base *ab, val |= FIELD_PREP(HAL_TCL1_RING_CONSR_INT_SETUP_IX1_LOW_THOLD, srng->u.src_ring.low_threshold); } - ath11k_ahb_write32(ab, + ath11k_hif_write32(ab, reg_base + HAL_TCL1_RING_CONSR_INT_SETUP_IX1_OFFSET, val); @@ -505,18 +506,18 @@ static void ath11k_hal_srng_src_hw_init(struct ath11k_base *ab, tp_addr = hal->rdp.paddr + ((unsigned long)srng->u.src_ring.tp_addr - (unsigned long)hal->rdp.vaddr); - ath11k_ahb_write32(ab, + ath11k_hif_write32(ab, reg_base + HAL_TCL1_RING_TP_ADDR_LSB_OFFSET, tp_addr & HAL_ADDR_LSB_REG_MASK); - ath11k_ahb_write32(ab, + ath11k_hif_write32(ab, reg_base + HAL_TCL1_RING_TP_ADDR_MSB_OFFSET, tp_addr >> HAL_ADDR_MSB_REG_SHIFT); } /* Initialize head and tail pointers to indicate ring is empty */ reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R2]; - ath11k_ahb_write32(ab, reg_base, 0); - ath11k_ahb_write32(ab, reg_base + HAL_TCL1_RING_TP_OFFSET, 0); + ath11k_hif_write32(ab, reg_base, 0); + ath11k_hif_write32(ab, reg_base + HAL_TCL1_RING_TP_OFFSET, 0); *srng->u.src_ring.tp_addr = 0; reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R0]; @@ -533,7 +534,7 @@ static void ath11k_hal_srng_src_hw_init(struct ath11k_base *ab, val |= HAL_TCL1_RING_MISC_SRNG_ENABLE; - ath11k_ahb_write32(ab, reg_base + HAL_TCL1_RING_MISC_OFFSET, val); + ath11k_hif_write32(ab, reg_base + HAL_TCL1_RING_MISC_OFFSET, val); } static void ath11k_hal_srng_hw_init(struct ath11k_base *ab, @@ -889,13 +890,13 @@ void ath11k_hal_srng_access_end(struct ath11k_base *ab, struct hal_srng *srng) if (srng->ring_dir == HAL_SRNG_DIR_SRC) { srng->u.src_ring.last_tp = *(volatile u32 *)srng->u.src_ring.tp_addr; - ath11k_ahb_write32(ab, + ath11k_hif_write32(ab, (unsigned long)srng->u.src_ring.hp_addr - (unsigned long)ab->mem, srng->u.src_ring.hp); } else { srng->u.dst_ring.last_hp = *srng->u.dst_ring.hp_addr; - ath11k_ahb_write32(ab, + ath11k_hif_write32(ab, (unsigned long)srng->u.dst_ring.tp_addr - (unsigned long)ab->mem, srng->u.dst_ring.tp); @@ -929,20 +930,20 @@ void ath11k_hal_setup_link_idle_list(struct ath11k_base *ab, HAL_WBM_IDLE_SCATTER_BUF_SIZE; } - ath11k_ahb_write32(ab, + ath11k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_R0_IDLE_LIST_CONTROL_ADDR, FIELD_PREP(HAL_WBM_SCATTER_BUFFER_SIZE, reg_scatter_buf_sz) | FIELD_PREP(HAL_WBM_LINK_DESC_IDLE_LIST_MODE, 0x1)); - ath11k_ahb_write32(ab, + ath11k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_R0_IDLE_LIST_SIZE_ADDR, FIELD_PREP(HAL_WBM_SCATTER_RING_SIZE_OF_IDLE_LINK_DESC_LIST, reg_scatter_buf_sz * nsbufs)); - ath11k_ahb_write32(ab, + ath11k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_SCATTERED_RING_BASE_LSB, FIELD_PREP(BUFFER_ADDR_INFO0_ADDR, sbuf[0].paddr & HAL_ADDR_LSB_REG_MASK)); - ath11k_ahb_write32(ab, + ath11k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_SCATTERED_RING_BASE_MSB, FIELD_PREP( @@ -953,12 +954,12 @@ void ath11k_hal_setup_link_idle_list(struct ath11k_base *ab, BASE_ADDR_MATCH_TAG_VAL)); /* Setup head and tail pointers for the idle list */ - ath11k_ahb_write32(ab, + ath11k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_SCATTERED_DESC_PTR_HEAD_INFO_IX0, FIELD_PREP(BUFFER_ADDR_INFO0_ADDR, sbuf[nsbufs - 1].paddr)); - ath11k_ahb_write32(ab, + ath11k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_SCATTERED_DESC_PTR_HEAD_INFO_IX1, FIELD_PREP( @@ -967,18 +968,18 @@ void ath11k_hal_setup_link_idle_list(struct ath11k_base *ab, HAL_ADDR_MSB_REG_SHIFT)) | FIELD_PREP(HAL_WBM_SCATTERED_DESC_HEAD_P_OFFSET_IX1, (end_offset >> 2))); - ath11k_ahb_write32(ab, + ath11k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_SCATTERED_DESC_PTR_HEAD_INFO_IX0, FIELD_PREP(BUFFER_ADDR_INFO0_ADDR, sbuf[0].paddr)); - ath11k_ahb_write32(ab, + ath11k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_SCATTERED_DESC_PTR_TAIL_INFO_IX0, FIELD_PREP(BUFFER_ADDR_INFO0_ADDR, sbuf[0].paddr)); - ath11k_ahb_write32(ab, + ath11k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_SCATTERED_DESC_PTR_TAIL_INFO_IX1, FIELD_PREP( @@ -986,13 +987,13 @@ void ath11k_hal_setup_link_idle_list(struct ath11k_base *ab, ((u64)sbuf[0].paddr >> HAL_ADDR_MSB_REG_SHIFT)) | FIELD_PREP(HAL_WBM_SCATTERED_DESC_TAIL_P_OFFSET_IX1, 0)); - ath11k_ahb_write32(ab, + ath11k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_SCATTERED_DESC_PTR_HP_ADDR, 2 * tot_link_desc); /* Enable the SRNG */ - ath11k_ahb_write32(ab, + ath11k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_WBM_REG + HAL_WBM_IDLE_LINK_RING_MISC_ADDR, 0x40); } diff --git a/drivers/net/wireless/ath/ath11k/hal_desc.h b/drivers/net/wireless/ath/ath11k/hal_desc.h index a1f747c1c44d..8a592814efa0 100644 --- a/drivers/net/wireless/ath/ath11k/hal_desc.h +++ b/drivers/net/wireless/ath/ath11k/hal_desc.h @@ -2,6 +2,8 @@ /* * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. */ +#include "core.h" + #ifndef ATH11K_HAL_DESC_H #define ATH11K_HAL_DESC_H diff --git a/drivers/net/wireless/ath/ath11k/hal_rx.c b/drivers/net/wireless/ath/ath11k/hal_rx.c index f277c9434a25..129c9e1efeb9 100644 --- a/drivers/net/wireless/ath/ath11k/hal_rx.c +++ b/drivers/net/wireless/ath/ath11k/hal_rx.c @@ -3,12 +3,12 @@ * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. */ -#include "ahb.h" #include "debug.h" #include "hal.h" #include "hal_tx.h" #include "hal_rx.h" #include "hal_desc.h" +#include "hif.h" static void ath11k_hal_reo_set_desc_hdr(struct hal_desc_header *hdr, u8 owner, u8 buffer_type, u32 magic) @@ -804,34 +804,34 @@ void ath11k_hal_reo_hw_setup(struct ath11k_base *ab, u32 ring_hash_map) u32 reo_base = HAL_SEQ_WCSS_UMAC_REO_REG; u32 val; - val = ath11k_ahb_read32(ab, reo_base + HAL_REO1_GEN_ENABLE); + val = ath11k_hif_read32(ab, reo_base + HAL_REO1_GEN_ENABLE); val &= ~HAL_REO1_GEN_ENABLE_FRAG_DST_RING; val |= FIELD_PREP(HAL_REO1_GEN_ENABLE_FRAG_DST_RING, HAL_SRNG_RING_ID_REO2SW1) | FIELD_PREP(HAL_REO1_GEN_ENABLE_AGING_LIST_ENABLE, 1) | FIELD_PREP(HAL_REO1_GEN_ENABLE_AGING_FLUSH_ENABLE, 1); - ath11k_ahb_write32(ab, reo_base + HAL_REO1_GEN_ENABLE, val); + ath11k_hif_write32(ab, reo_base + HAL_REO1_GEN_ENABLE, val); - ath11k_ahb_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_0, + ath11k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_0, HAL_DEFAULT_REO_TIMEOUT_USEC); - ath11k_ahb_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_1, + ath11k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_1, HAL_DEFAULT_REO_TIMEOUT_USEC); - ath11k_ahb_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_2, + ath11k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_2, HAL_DEFAULT_REO_TIMEOUT_USEC); - ath11k_ahb_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_3, + ath11k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_3, HAL_DEFAULT_REO_TIMEOUT_USEC); - ath11k_ahb_write32(ab, reo_base + HAL_REO1_DEST_RING_CTRL_IX_0, + ath11k_hif_write32(ab, reo_base + HAL_REO1_DEST_RING_CTRL_IX_0, FIELD_PREP(HAL_REO_DEST_RING_CTRL_HASH_RING_MAP, ring_hash_map)); - ath11k_ahb_write32(ab, reo_base + HAL_REO1_DEST_RING_CTRL_IX_1, + ath11k_hif_write32(ab, reo_base + HAL_REO1_DEST_RING_CTRL_IX_1, FIELD_PREP(HAL_REO_DEST_RING_CTRL_HASH_RING_MAP, ring_hash_map)); - ath11k_ahb_write32(ab, reo_base + HAL_REO1_DEST_RING_CTRL_IX_2, + ath11k_hif_write32(ab, reo_base + HAL_REO1_DEST_RING_CTRL_IX_2, FIELD_PREP(HAL_REO_DEST_RING_CTRL_HASH_RING_MAP, ring_hash_map)); - ath11k_ahb_write32(ab, reo_base + HAL_REO1_DEST_RING_CTRL_IX_3, + ath11k_hif_write32(ab, reo_base + HAL_REO1_DEST_RING_CTRL_IX_3, FIELD_PREP(HAL_REO_DEST_RING_CTRL_HASH_RING_MAP, ring_hash_map)); } diff --git a/drivers/net/wireless/ath/ath11k/hal_tx.c b/drivers/net/wireless/ath/ath11k/hal_tx.c index e4aa7e8a1284..81937c29ffca 100644 --- a/drivers/net/wireless/ath/ath11k/hal_tx.c +++ b/drivers/net/wireless/ath/ath11k/hal_tx.c @@ -3,9 +3,10 @@ * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. */ -#include "ahb.h" +#include "hal_desc.h" #include "hal.h" #include "hal_tx.h" +#include "hif.h" #define DSCP_TID_MAP_TBL_ENTRY_SIZE 64 @@ -83,11 +84,11 @@ void ath11k_hal_tx_set_dscp_tid_map(struct ath11k_base *ab, int id) u32 value; int cnt = 0; - ctrl_reg_val = ath11k_ahb_read32(ab, HAL_SEQ_WCSS_UMAC_TCL_REG + + ctrl_reg_val = ath11k_hif_read32(ab, HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_CMN_CTRL_REG); /* Enable read/write access */ ctrl_reg_val |= HAL_TCL1_RING_CMN_CTRL_DSCP_TID_MAP_PROG_EN; - ath11k_ahb_write32(ab, HAL_SEQ_WCSS_UMAC_TCL_REG + + ath11k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_CMN_CTRL_REG, ctrl_reg_val); addr = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_DSCP_TID_MAP + @@ -118,15 +119,15 @@ void ath11k_hal_tx_set_dscp_tid_map(struct ath11k_base *ab, int id) } for (i = 0; i < HAL_DSCP_TID_TBL_SIZE; i += 4) { - ath11k_ahb_write32(ab, addr, *(u32 *)&hw_map_val[i]); + ath11k_hif_write32(ab, addr, *(u32 *)&hw_map_val[i]); addr += 4; } /* Disable read/write access */ - ctrl_reg_val = ath11k_ahb_read32(ab, HAL_SEQ_WCSS_UMAC_TCL_REG + + ctrl_reg_val = ath11k_hif_read32(ab, HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_CMN_CTRL_REG); ctrl_reg_val &= ~HAL_TCL1_RING_CMN_CTRL_DSCP_TID_MAP_PROG_EN; - ath11k_ahb_write32(ab, HAL_SEQ_WCSS_UMAC_TCL_REG + + ath11k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_CMN_CTRL_REG, ctrl_reg_val); } diff --git a/drivers/net/wireless/ath/ath11k/hal_tx.h b/drivers/net/wireless/ath/ath11k/hal_tx.h index ce48a61bfb66..d4760a20fdac 100644 --- a/drivers/net/wireless/ath/ath11k/hal_tx.h +++ b/drivers/net/wireless/ath/ath11k/hal_tx.h @@ -7,6 +7,7 @@ #define ATH11K_HAL_TX_H #include "hal_desc.h" +#include "core.h" #define HAL_TX_ADDRX_EN 1 #define HAL_TX_ADDRY_EN 2 diff --git a/drivers/net/wireless/ath/ath11k/hif.h b/drivers/net/wireless/ath/ath11k/hif.h new file mode 100644 index 000000000000..165f7e51c238 --- /dev/null +++ b/drivers/net/wireless/ath/ath11k/hif.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: BSD-3-Clause-Clear */ +/* + * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved. + */ + +#include "core.h" + +struct ath11k_hif_ops { + u32 (*read32)(struct ath11k_base *sc, u32 address); + void (*write32)(struct ath11k_base *sc, u32 address, u32 data); + void (*irq_enable)(struct ath11k_base *sc); + void (*irq_disable)(struct ath11k_base *sc); + int (*start)(struct ath11k_base *sc); + void (*stop)(struct ath11k_base *sc); + int (*power_up)(struct ath11k_base *sc); + void (*power_down)(struct ath11k_base *sc); + int (*map_service_to_pipe)(struct ath11k_base *sc, u16 service_id, + u8 *ul_pipe, u8 *dl_pipe); +}; + +static inline int ath11k_hif_start(struct ath11k_base *sc) +{ + return sc->hif.ops->start(sc); +} + +static inline void ath11k_hif_stop(struct ath11k_base *sc) +{ + sc->hif.ops->stop(sc); +} + +static inline void ath11k_hif_irq_enable(struct ath11k_base *sc) +{ + sc->hif.ops->irq_enable(sc); +} + +static inline void ath11k_hif_irq_disable(struct ath11k_base *sc) +{ + sc->hif.ops->irq_disable(sc); +} + +static inline int ath11k_hif_power_up(struct ath11k_base *sc) +{ + return sc->hif.ops->power_up(sc); +} + +static inline void ath11k_hif_power_down(struct ath11k_base *sc) +{ + sc->hif.ops->power_down(sc); +} + +static inline u32 ath11k_hif_read32(struct ath11k_base *sc, u32 address) +{ + return sc->hif.ops->read32(sc, address); +} + +static inline void ath11k_hif_write32(struct ath11k_base *sc, u32 address, u32 data) +{ + sc->hif.ops->write32(sc, address, data); +} + +static inline int ath11k_hif_map_service_to_pipe(struct ath11k_base *sc, u16 service_id, + u8 *ul_pipe, u8 *dl_pipe) +{ + return sc->hif.ops->map_service_to_pipe(sc, service_id, ul_pipe, dl_pipe); +} diff --git a/drivers/net/wireless/ath/ath11k/htc.c b/drivers/net/wireless/ath/ath11k/htc.c index 8f54f58b83e6..ad13c648b679 100644 --- a/drivers/net/wireless/ath/ath11k/htc.c +++ b/drivers/net/wireless/ath/ath11k/htc.c @@ -5,8 +5,8 @@ #include <linux/skbuff.h> #include <linux/ctype.h> -#include "ahb.h" #include "debug.h" +#include "hif.h" struct sk_buff *ath11k_htc_alloc_skb(struct ath11k_base *ab, int size) { @@ -672,7 +672,7 @@ setup: /* copy all the callbacks */ ep->ep_ops = conn_req->ep_ops; - status = ath11k_ahb_map_service_to_pipe(htc->ab, + status = ath11k_hif_map_service_to_pipe(htc->ab, ep->service_id, &ep->ul_pipe_id, &ep->dl_pipe_id); diff --git a/drivers/net/wireless/ath/ath11k/hw.h b/drivers/net/wireless/ath/ath11k/hw.h index cdec95644758..dc4434aefbbe 100644 --- a/drivers/net/wireless/ath/ath11k/hw.h +++ b/drivers/net/wireless/ath/ath11k/hw.h @@ -99,6 +99,11 @@ enum ath11k_hw_rate_ofdm { ATH11K_HW_RATE_OFDM_9M, }; +enum ath11k_bus { + ATH11K_BUS_AHB, + ATH11K_BUS_PCI, +}; + struct ath11k_hw_params { const char *name; struct { diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index d9117ebf2809..1a7e5817e5c8 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -3692,7 +3692,7 @@ static int __ath11k_set_antenna(struct ath11k *ar, u32 tx_ant, u32 rx_ant) int ath11k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx) { struct sk_buff *msdu = skb; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(msdu); + struct ieee80211_tx_info *info; struct ath11k *ar = ctx; struct ath11k_base *ab = ar->ab; diff --git a/drivers/net/wireless/ath/ath11k/thermal.c b/drivers/net/wireless/ath/ath11k/thermal.c index 259dddbda2c7..5a7e150c621b 100644 --- a/drivers/net/wireless/ath/ath11k/thermal.c +++ b/drivers/net/wireless/ath/ath11k/thermal.c @@ -174,9 +174,12 @@ int ath11k_thermal_register(struct ath11k_base *sc) if (IS_ERR(cdev)) { ath11k_err(sc, "failed to setup thermal device result: %ld\n", PTR_ERR(cdev)); - return -EINVAL; + ret = -EINVAL; + goto err_thermal_destroy; } + ar->thermal.cdev = cdev; + ret = sysfs_create_link(&ar->hw->wiphy->dev.kobj, &cdev->device.kobj, "cooling_device"); if (ret) { @@ -184,7 +187,6 @@ int ath11k_thermal_register(struct ath11k_base *sc) goto err_thermal_destroy; } - ar->thermal.cdev = cdev; if (!IS_REACHABLE(CONFIG_HWMON)) return 0; diff --git a/drivers/net/wireless/ath/carl9170/fwcmd.h b/drivers/net/wireless/ath/carl9170/fwcmd.h index ea1d80f9a50e..56999a3b9d3b 100644 --- a/drivers/net/wireless/ath/carl9170/fwcmd.h +++ b/drivers/net/wireless/ath/carl9170/fwcmd.h @@ -127,7 +127,7 @@ struct carl9170_write_reg { struct carl9170_write_reg_byte { __le32 addr; __le32 count; - u8 val[0]; + u8 val[]; } __packed; #define CARL9170FW_PHY_HT_ENABLE 0x4 diff --git a/drivers/net/wireless/ath/carl9170/hw.h b/drivers/net/wireless/ath/carl9170/hw.h index 08e0ae9c5836..555ad4975970 100644 --- a/drivers/net/wireless/ath/carl9170/hw.h +++ b/drivers/net/wireless/ath/carl9170/hw.h @@ -851,7 +851,7 @@ struct ar9170_stream { __le16 length; __le16 tag; - u8 payload[0]; + u8 payload[]; } __packed __aligned(4); #define AR9170_STREAM_LEN 4 diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h b/drivers/net/wireless/ath/wcn36xx/hal.h index 6ba0fd57c951..aab5a58616fc 100644 --- a/drivers/net/wireless/ath/wcn36xx/hal.h +++ b/drivers/net/wireless/ath/wcn36xx/hal.h @@ -2240,7 +2240,7 @@ struct wcn36xx_hal_process_ptt_msg_req_msg { struct wcn36xx_hal_msg_header header; /* Actual FTM Command body */ - u8 ptt_msg[0]; + u8 ptt_msg[]; } __packed; struct wcn36xx_hal_process_ptt_msg_rsp_msg { @@ -2249,7 +2249,7 @@ struct wcn36xx_hal_process_ptt_msg_rsp_msg { /* FTM Command response status */ u32 ptt_msg_resp_status; /* Actual FTM Command body */ - u8 ptt_msg[0]; + u8 ptt_msg[]; } __packed; struct update_edca_params_req_msg { diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index e49c306e0eef..702b689c06df 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -1339,7 +1339,7 @@ static int wcn36xx_probe(struct platform_device *pdev) if (addr && ret != ETH_ALEN) { wcn36xx_err("invalid local-mac-address\n"); ret = -EINVAL; - goto out_wq; + goto out_destroy_ept; } else if (addr) { wcn36xx_info("mac address: %pM\n", addr); SET_IEEE80211_PERM_ADDR(wcn->hw, addr); @@ -1347,7 +1347,7 @@ static int wcn36xx_probe(struct platform_device *pdev) ret = wcn36xx_platform_get_resources(wcn, pdev); if (ret) - goto out_wq; + goto out_destroy_ept; wcn36xx_init_ieee80211(wcn); ret = ieee80211_register_hw(wcn->hw); @@ -1359,6 +1359,8 @@ static int wcn36xx_probe(struct platform_device *pdev) out_unmap: iounmap(wcn->ccu_base); iounmap(wcn->dxe_base); +out_destroy_ept: + rpmsg_destroy_ept(wcn->smd_channel); out_wq: ieee80211_free_hw(hw); out_err: diff --git a/drivers/net/wireless/ath/wcn36xx/testmode.h b/drivers/net/wireless/ath/wcn36xx/testmode.h index 4c6cfdb46580..09d68fab9add 100644 --- a/drivers/net/wireless/ath/wcn36xx/testmode.h +++ b/drivers/net/wireless/ath/wcn36xx/testmode.h @@ -20,7 +20,7 @@ struct ftm_rsp_msg { u16 msg_id; u16 msg_body_length; u32 resp_status; - u8 msg_response[0]; + u8 msg_response[]; } __packed; /* The request buffer of FTM which contains a byte of command and the request */ diff --git a/drivers/net/wireless/ath/wil6210/fw.h b/drivers/net/wireless/ath/wil6210/fw.h index 540fa1607794..440614d61156 100644 --- a/drivers/net/wireless/ath/wil6210/fw.h +++ b/drivers/net/wireless/ath/wil6210/fw.h @@ -33,7 +33,7 @@ struct wil_fw_record_head { */ struct wil_fw_record_data { /* type == wil_fw_type_data */ __le32 addr; - __le32 data[0]; /* [data_size], see above */ + __le32 data[]; /* [data_size], see above */ } __packed; /* fill with constant @value, @size bytes starting from @addr */ @@ -61,7 +61,7 @@ struct wil_fw_record_capabilities { /* type == wil_fw_type_comment */ /* identifies capabilities record */ struct wil_fw_record_comment_hdr hdr; /* capabilities (variable size), see enum wmi_fw_capability */ - u8 capabilities[0]; + u8 capabilities[]; } __packed; /* FW VIF concurrency encoded inside a comment record @@ -80,7 +80,7 @@ struct wil_fw_concurrency_combo { u8 n_diff_channels; /* total number of different channels allowed */ u8 same_bi; /* for APs, 1 if all APs must have same BI */ /* keep last - concurrency limits, variable size by n_limits */ - struct wil_fw_concurrency_limit limits[0]; + struct wil_fw_concurrency_limit limits[]; } __packed; struct wil_fw_record_concurrency { /* type == wil_fw_type_comment */ @@ -93,7 +93,7 @@ struct wil_fw_record_concurrency { /* type == wil_fw_type_comment */ /* number of concurrency combinations that follow */ __le16 n_combos; /* keep last - combinations, variable size by n_combos */ - struct wil_fw_concurrency_combo combos[0]; + struct wil_fw_concurrency_combo combos[]; } __packed; /* brd file info encoded inside a comment record */ @@ -108,7 +108,7 @@ struct wil_fw_record_brd_file { /* type == wil_fw_type_comment */ /* identifies brd file record */ struct wil_fw_record_comment_hdr hdr; __le32 version; - struct brd_info brd_info[0]; + struct brd_info brd_info[]; } __packed; /* perform action @@ -116,7 +116,7 @@ struct wil_fw_record_brd_file { /* type == wil_fw_type_comment */ */ struct wil_fw_record_action { /* type == wil_fw_type_action */ __le32 action; /* action to perform: reset, wait for fw ready etc. */ - __le32 data[0]; /* action specific, [data_size], see above */ + __le32 data[]; /* action specific, [data_size], see above */ } __packed; /* data block for struct wil_fw_record_direct_write */ @@ -179,7 +179,7 @@ struct wil_fw_record_gateway_data { /* type == wil_fw_type_gateway_data */ #define WIL_FW_GW_CTL_BUSY BIT(29) /* gateway busy performing operation */ #define WIL_FW_GW_CTL_RUN BIT(30) /* start gateway operation */ __le32 command; - struct wil_fw_data_gw data[0]; /* total size [data_size], see above */ + struct wil_fw_data_gw data[]; /* total size [data_size], see above */ } __packed; /* 4-dword gateway */ @@ -201,7 +201,7 @@ struct wil_fw_record_gateway_data4 { /* type == wil_fw_type_gateway_data4 */ __le32 gateway_cmd_addr; __le32 gateway_ctrl_address; /* same logic as for 1-dword gw */ __le32 command; - struct wil_fw_data_gw4 data[0]; /* total size [data_size], see above */ + struct wil_fw_data_gw4 data[]; /* total size [data_size], see above */ } __packed; #endif /* __WIL_FW_H__ */ diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 23e1ed6a9d6d..c7136ce567ee 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -222,7 +222,7 @@ struct auth_no_hdr { __le16 auth_transaction; __le16 status_code; /* possibly followed by Challenge text */ - u8 variable[0]; + u8 variable[]; } __packed; u8 led_polarity = LED_POLARITY_LOW_ACTIVE; diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h index e3558136e0c4..9affa4525609 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.h +++ b/drivers/net/wireless/ath/wil6210/wmi.h @@ -474,7 +474,7 @@ struct wmi_start_scan_cmd { struct { u8 channel; u8 reserved; - } channel_list[0]; + } channel_list[]; } __packed; #define WMI_MAX_PNO_SSID_NUM (16) @@ -530,7 +530,7 @@ struct wmi_update_ft_ies_cmd { /* Length of the FT IEs */ __le16 ie_len; u8 reserved[2]; - u8 ie_info[0]; + u8 ie_info[]; } __packed; /* WMI_SET_PROBED_SSID_CMDID */ @@ -575,7 +575,7 @@ struct wmi_set_appie_cmd { u8 reserved; /* Length of the IE to be added to MGMT frame */ __le16 ie_len; - u8 ie_info[0]; + u8 ie_info[]; } __packed; /* WMI_PXMT_RANGE_CFG_CMDID */ @@ -850,7 +850,7 @@ struct wmi_pcp_start_cmd { struct wmi_sw_tx_req_cmd { u8 dst_mac[WMI_MAC_LEN]; __le16 len; - u8 payload[0]; + u8 payload[]; } __packed; /* WMI_SW_TX_REQ_EXT_CMDID */ @@ -861,7 +861,7 @@ struct wmi_sw_tx_req_ext_cmd { /* Channel to use, 0xFF for currently active channel */ u8 channel; u8 reserved[5]; - u8 payload[0]; + u8 payload[]; } __packed; /* WMI_VRING_SWITCH_TIMING_CONFIG_CMDID */ @@ -1423,7 +1423,7 @@ struct wmi_rf_xpm_write_cmd { u8 verify; u8 reserved1[3]; /* actual size=num_bytes */ - u8 data_bytes[0]; + u8 data_bytes[]; } __packed; /* Possible modes for temperature measurement */ @@ -1572,7 +1572,7 @@ struct wmi_tof_session_start_cmd { u8 aoa_type; __le16 num_of_dest; u8 reserved[4]; - struct wmi_ftm_dest_info ftm_dest_info[0]; + struct wmi_ftm_dest_info ftm_dest_info[]; } __packed; /* WMI_TOF_CFG_RESPONDER_CMDID */ @@ -1766,7 +1766,7 @@ struct wmi_internal_fw_ioctl_cmd { /* payload max size is WMI_MAX_IOCTL_PAYLOAD_SIZE * Must be the last member of the struct */ - __le32 payload[0]; + __le32 payload[]; } __packed; /* WMI_INTERNAL_FW_IOCTL_EVENTID */ @@ -1778,7 +1778,7 @@ struct wmi_internal_fw_ioctl_event { /* payload max size is WMI_MAX_IOCTL_REPLY_PAYLOAD_SIZE * Must be the last member of the struct */ - __le32 payload[0]; + __le32 payload[]; } __packed; /* WMI_INTERNAL_FW_EVENT_EVENTID */ @@ -1788,7 +1788,7 @@ struct wmi_internal_fw_event_event { /* payload max size is WMI_MAX_INTERNAL_EVENT_PAYLOAD_SIZE * Must be the last member of the struct */ - __le32 payload[0]; + __le32 payload[]; } __packed; /* WMI_SET_VRING_PRIORITY_WEIGHT_CMDID */ @@ -1818,7 +1818,7 @@ struct wmi_set_vring_priority_cmd { */ u8 num_of_vrings; u8 reserved[3]; - struct wmi_vring_priority vring_priority[0]; + struct wmi_vring_priority vring_priority[]; } __packed; /* WMI_BF_CONTROL_CMDID - deprecated */ @@ -1910,7 +1910,7 @@ struct wmi_bf_control_ex_cmd { u8 each_mcs_cfg_size; u8 reserved1; /* Configuration for each MCS */ - struct wmi_bf_control_ex_mcs each_mcs_cfg[0]; + struct wmi_bf_control_ex_mcs each_mcs_cfg[]; } __packed; /* WMI_LINK_STATS_CMD */ @@ -2192,7 +2192,7 @@ struct wmi_fw_ver_event { /* FW capabilities info * Must be the last member of the struct */ - __le32 fw_capabilities[0]; + __le32 fw_capabilities[]; } __packed; /* WMI_GET_RF_STATUS_EVENTID */ @@ -2270,7 +2270,7 @@ struct wmi_mac_addr_resp_event { struct wmi_eapol_rx_event { u8 src_mac[WMI_MAC_LEN]; __le16 eapol_len; - u8 eapol[0]; + u8 eapol[]; } __packed; /* WMI_READY_EVENTID */ @@ -2343,7 +2343,7 @@ struct wmi_connect_event { u8 aid; u8 reserved2[2]; /* not in use */ - u8 assoc_info[0]; + u8 assoc_info[]; } __packed; /* disconnect_reason */ @@ -2376,7 +2376,7 @@ struct wmi_disconnect_event { /* last assoc req may passed to host - not in used */ u8 assoc_resp_len; /* last assoc req may passed to host - not in used */ - u8 assoc_info[0]; + u8 assoc_info[]; } __packed; /* WMI_SCAN_COMPLETE_EVENTID */ @@ -2400,7 +2400,7 @@ struct wmi_ft_auth_status_event { u8 reserved[3]; u8 mac_addr[WMI_MAC_LEN]; __le16 ie_len; - u8 ie_info[0]; + u8 ie_info[]; } __packed; /* WMI_FT_REASSOC_STATUS_EVENTID */ @@ -2418,7 +2418,7 @@ struct wmi_ft_reassoc_status_event { __le16 reassoc_req_ie_len; __le16 reassoc_resp_ie_len; u8 reserved[4]; - u8 ie_info[0]; + u8 ie_info[]; } __packed; /* wmi_rx_mgmt_info */ @@ -2461,7 +2461,7 @@ struct wmi_stop_sched_scan_event { struct wmi_sched_scan_result_event { struct wmi_rx_mgmt_info info; - u8 payload[0]; + u8 payload[]; } __packed; /* WMI_ACS_PASSIVE_SCAN_COMPLETE_EVENT */ @@ -2492,7 +2492,7 @@ struct wmi_acs_passive_scan_complete_event { __le16 filled; u8 num_scanned_channels; u8 reserved; - struct scan_acs_info scan_info_list[0]; + struct scan_acs_info scan_info_list[]; } __packed; /* WMI_BA_STATUS_EVENTID */ @@ -2751,7 +2751,7 @@ struct wmi_rf_xpm_read_result_event { u8 status; u8 reserved[3]; /* requested num_bytes of data */ - u8 data_bytes[0]; + u8 data_bytes[]; } __packed; /* EVENT: WMI_RF_XPM_WRITE_RESULT_EVENTID */ @@ -2769,7 +2769,7 @@ struct wmi_tx_mgmt_packet_event { /* WMI_RX_MGMT_PACKET_EVENTID */ struct wmi_rx_mgmt_packet_event { struct wmi_rx_mgmt_info info; - u8 payload[0]; + u8 payload[]; } __packed; /* WMI_ECHO_RSP_EVENTID */ @@ -2969,7 +2969,7 @@ struct wmi_rs_cfg_ex_cmd { u8 each_mcs_cfg_size; u8 reserved[3]; /* Configuration for each MCS */ - struct wmi_rs_cfg_ex_mcs each_mcs_cfg[0]; + struct wmi_rs_cfg_ex_mcs each_mcs_cfg[]; } __packed; /* WMI_RS_CFG_EX_EVENTID */ @@ -3178,7 +3178,7 @@ struct wmi_get_detailed_rs_res_ex_event { u8 each_mcs_results_size; u8 reserved1[3]; /* Results for each MCS */ - struct wmi_rs_results_ex_mcs each_mcs_results[0]; + struct wmi_rs_results_ex_mcs each_mcs_results[]; } __packed; /* BRP antenna limit mode */ @@ -3320,7 +3320,7 @@ struct wmi_set_link_monitor_cmd { u8 rssi_hyst; u8 reserved[12]; u8 rssi_thresholds_list_size; - s8 rssi_thresholds_list[0]; + s8 rssi_thresholds_list[]; } __packed; /* wmi_link_monitor_event_type */ @@ -3637,7 +3637,7 @@ struct wmi_tof_ftm_per_dest_res_event { /* Measurments are from RFs, defined by the mask */ __le32 meas_rf_mask; u8 reserved0[3]; - struct wmi_responder_ftm_res responder_ftm_res[0]; + struct wmi_responder_ftm_res responder_ftm_res[]; } __packed; /* WMI_TOF_CFG_RESPONDER_EVENTID */ @@ -3669,7 +3669,7 @@ struct wmi_tof_channel_info_event { /* data report length */ u8 len; /* data report payload */ - u8 report[0]; + u8 report[]; } __packed; /* WMI_TOF_SET_TX_RX_OFFSET_EVENTID */ @@ -4085,7 +4085,7 @@ struct wmi_link_stats_event { u8 has_next; u8 reserved[5]; /* a stream of wmi_link_stats_record_s */ - u8 payload[0]; + u8 payload[]; } __packed; /* WMI_LINK_STATS_EVENT */ @@ -4094,7 +4094,7 @@ struct wmi_link_stats_record { u8 record_type_id; u8 reserved; __le16 record_size; - u8 record[0]; + u8 record[]; } __packed; /* WMI_LINK_STATS_TYPE_BASIC */ diff --git a/drivers/net/wireless/atmel/atmel.c b/drivers/net/wireless/atmel/atmel.c index 74538085cfb7..d5875836068c 100644 --- a/drivers/net/wireless/atmel/atmel.c +++ b/drivers/net/wireless/atmel/atmel.c @@ -798,7 +798,6 @@ static void tx_update_descriptor(struct atmel_private *priv, int is_bcast, static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev) { - static const u8 SNAP_RFC1024[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; struct atmel_private *priv = netdev_priv(dev); struct ieee80211_hdr header; unsigned long flags; @@ -853,7 +852,7 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev) } if (priv->use_wpa) - memcpy(&header.addr4, SNAP_RFC1024, ETH_ALEN); + memcpy(&header.addr4, rfc1042_header, ETH_ALEN); header.frame_control = cpu_to_le16(frame_ctl); /* Copy the wireless header into the card */ diff --git a/drivers/net/wireless/broadcom/b43/main.c b/drivers/net/wireless/broadcom/b43/main.c index 39da1a4c30ac..3ad94dad2d89 100644 --- a/drivers/net/wireless/broadcom/b43/main.c +++ b/drivers/net/wireless/broadcom/b43/main.c @@ -5569,7 +5569,7 @@ static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev) /* fill hw info */ ieee80211_hw_set(hw, RX_INCLUDES_FCS); ieee80211_hw_set(hw, SIGNAL_DBM); - + ieee80211_hw_set(hw, MFP_CAPABLE); hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MESH_POINT) | diff --git a/drivers/net/wireless/broadcom/b43legacy/main.c b/drivers/net/wireless/broadcom/b43legacy/main.c index 8b6b657c4b85..5208a39fd6f7 100644 --- a/drivers/net/wireless/broadcom/b43legacy/main.c +++ b/drivers/net/wireless/broadcom/b43legacy/main.c @@ -3801,6 +3801,7 @@ static int b43legacy_wireless_init(struct ssb_device *dev) /* fill hw info */ ieee80211_hw_set(hw, RX_INCLUDES_FCS); ieee80211_hw_set(hw, SIGNAL_DBM); + ieee80211_hw_set(hw, MFP_CAPABLE); /* Allow WPA3 in software */ hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_AP) | diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c index 22a17ae09e94..b1a66320ba54 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c @@ -43,7 +43,8 @@ #define SDIO_FUNC1_BLOCKSIZE 64 #define SDIO_FUNC2_BLOCKSIZE 512 -#define SDIO_4359_FUNC2_BLOCKSIZE 256 +#define SDIO_4373_FUNC2_BLOCKSIZE 256 +#define SDIO_435X_FUNC2_BLOCKSIZE 256 /* Maximum milliseconds to wait for F2 to come up */ #define SDIO_WAIT_F2RDY 3000 @@ -910,13 +911,28 @@ static int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev) sdio_release_host(sdiodev->func1); goto out; } - if (sdiodev->func2->device == SDIO_DEVICE_ID_BROADCOM_4359) - f2_blksz = SDIO_4359_FUNC2_BLOCKSIZE; + switch (sdiodev->func2->device) { + case SDIO_DEVICE_ID_CYPRESS_4373: + f2_blksz = SDIO_4373_FUNC2_BLOCKSIZE; + break; + case SDIO_DEVICE_ID_BROADCOM_4359: + /* fallthrough */ + case SDIO_DEVICE_ID_BROADCOM_4354: + /* fallthrough */ + case SDIO_DEVICE_ID_BROADCOM_4356: + f2_blksz = SDIO_435X_FUNC2_BLOCKSIZE; + break; + default: + break; + } + ret = sdio_set_block_size(sdiodev->func2, f2_blksz); if (ret) { brcmf_err("Failed to set F2 blocksize\n"); sdio_release_host(sdiodev->func1); goto out; + } else { + brcmf_dbg(SDIO, "set F2 blocksize to %d\n", f2_blksz); } /* increase F2 timeout */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index ce6f15284277..760b7737e745 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -41,9 +41,22 @@ /* watermark expressed in number of words */ #define DEFAULT_F2_WATERMARK 0x8 #define CY_4373_F2_WATERMARK 0x40 +#define CY_4373_F1_MESBUSYCTRL (CY_4373_F2_WATERMARK | SBSDIO_MESBUSYCTRL_ENAB) #define CY_43012_F2_WATERMARK 0x60 -#define CY_4359_F2_WATERMARK 0x40 -#define CY_4359_F1_MESBUSYCTRL (CY_4359_F2_WATERMARK | SBSDIO_MESBUSYCTRL_ENAB) +#define CY_43012_MES_WATERMARK 0x50 +#define CY_43012_MESBUSYCTRL (CY_43012_MES_WATERMARK | \ + SBSDIO_MESBUSYCTRL_ENAB) +#define CY_4339_F2_WATERMARK 48 +#define CY_4339_MES_WATERMARK 80 +#define CY_4339_MESBUSYCTRL (CY_4339_MES_WATERMARK | \ + SBSDIO_MESBUSYCTRL_ENAB) +#define CY_43455_F2_WATERMARK 0x60 +#define CY_43455_MES_WATERMARK 0x50 +#define CY_43455_MESBUSYCTRL (CY_43455_MES_WATERMARK | \ + SBSDIO_MESBUSYCTRL_ENAB) +#define CY_435X_F2_WATERMARK 0x40 +#define CY_435X_F1_MESBUSYCTRL (CY_435X_F2_WATERMARK | \ + SBSDIO_MESBUSYCTRL_ENAB) #ifdef DEBUG @@ -4195,8 +4208,7 @@ static void brcmf_sdio_firmware_callback(struct device *dev, int err, brcmf_sdiod_writeb(sdiod, SBSDIO_DEVICE_CTL, devctl, &err); brcmf_sdiod_writeb(sdiod, SBSDIO_FUNC1_MESBUSYCTRL, - CY_4373_F2_WATERMARK | - SBSDIO_MESBUSYCTRL_ENAB, &err); + CY_4373_F1_MESBUSYCTRL, &err); break; case SDIO_DEVICE_ID_CYPRESS_43012: brcmf_dbg(INFO, "set F2 watermark to 0x%x*4 bytes\n", @@ -4208,19 +4220,51 @@ static void brcmf_sdio_firmware_callback(struct device *dev, int err, devctl |= SBSDIO_DEVCTL_F2WM_ENAB; brcmf_sdiod_writeb(sdiod, SBSDIO_DEVICE_CTL, devctl, &err); + brcmf_sdiod_writeb(sdiod, SBSDIO_FUNC1_MESBUSYCTRL, + CY_43012_MESBUSYCTRL, &err); + break; + case SDIO_DEVICE_ID_BROADCOM_4339: + brcmf_dbg(INFO, "set F2 watermark to 0x%x*4 bytes for 4339\n", + CY_4339_F2_WATERMARK); + brcmf_sdiod_writeb(sdiod, SBSDIO_WATERMARK, + CY_4339_F2_WATERMARK, &err); + devctl = brcmf_sdiod_readb(sdiod, SBSDIO_DEVICE_CTL, + &err); + devctl |= SBSDIO_DEVCTL_F2WM_ENAB; + brcmf_sdiod_writeb(sdiod, SBSDIO_DEVICE_CTL, devctl, + &err); + brcmf_sdiod_writeb(sdiod, SBSDIO_FUNC1_MESBUSYCTRL, + CY_4339_MESBUSYCTRL, &err); + break; + case SDIO_DEVICE_ID_BROADCOM_43455: + brcmf_dbg(INFO, "set F2 watermark to 0x%x*4 bytes for 43455\n", + CY_43455_F2_WATERMARK); + brcmf_sdiod_writeb(sdiod, SBSDIO_WATERMARK, + CY_43455_F2_WATERMARK, &err); + devctl = brcmf_sdiod_readb(sdiod, SBSDIO_DEVICE_CTL, + &err); + devctl |= SBSDIO_DEVCTL_F2WM_ENAB; + brcmf_sdiod_writeb(sdiod, SBSDIO_DEVICE_CTL, devctl, + &err); + brcmf_sdiod_writeb(sdiod, SBSDIO_FUNC1_MESBUSYCTRL, + CY_43455_MESBUSYCTRL, &err); break; case SDIO_DEVICE_ID_BROADCOM_4359: + /* fallthrough */ + case SDIO_DEVICE_ID_BROADCOM_4354: + /* fallthrough */ + case SDIO_DEVICE_ID_BROADCOM_4356: brcmf_dbg(INFO, "set F2 watermark to 0x%x*4 bytes\n", - CY_4359_F2_WATERMARK); + CY_435X_F2_WATERMARK); brcmf_sdiod_writeb(sdiod, SBSDIO_WATERMARK, - CY_4359_F2_WATERMARK, &err); + CY_435X_F2_WATERMARK, &err); devctl = brcmf_sdiod_readb(sdiod, SBSDIO_DEVICE_CTL, &err); devctl |= SBSDIO_DEVCTL_F2WM_ENAB; brcmf_sdiod_writeb(sdiod, SBSDIO_DEVICE_CTL, devctl, &err); brcmf_sdiod_writeb(sdiod, SBSDIO_FUNC1_MESBUSYCTRL, - CY_4359_F1_MESBUSYCTRL, &err); + CY_435X_F1_MESBUSYCTRL, &err); break; default: brcmf_sdiod_writeb(sdiod, SBSDIO_WATERMARK, diff --git a/drivers/net/wireless/cisco/airo.c b/drivers/net/wireless/cisco/airo.c index 8363f91df7ea..827bb6d74815 100644 --- a/drivers/net/wireless/cisco/airo.c +++ b/drivers/net/wireless/cisco/airo.c @@ -1925,6 +1925,10 @@ static netdev_tx_t mpi_start_xmit(struct sk_buff *skb, airo_print_err(dev->name, "%s: skb == NULL!",__func__); return NETDEV_TX_OK; } + if (skb_padto(skb, ETH_ZLEN)) { + dev->stats.tx_dropped++; + return NETDEV_TX_OK; + } npacks = skb_queue_len (&ai->txq); if (npacks >= MAXTXQ - 1) { @@ -2127,6 +2131,10 @@ static netdev_tx_t airo_start_xmit(struct sk_buff *skb, airo_print_err(dev->name, "%s: skb == NULL!", __func__); return NETDEV_TX_OK; } + if (skb_padto(skb, ETH_ZLEN)) { + dev->stats.tx_dropped++; + return NETDEV_TX_OK; + } /* Find a vacant FID */ for( i = 0; i < MAX_FIDS / 2 && (fids[i] & 0xffff0000); i++ ); @@ -2201,6 +2209,10 @@ static netdev_tx_t airo_start_xmit11(struct sk_buff *skb, airo_print_err(dev->name, "%s: skb == NULL!", __func__); return NETDEV_TX_OK; } + if (skb_padto(skb, ETH_ZLEN)) { + dev->stats.tx_dropped++; + return NETDEV_TX_OK; + } /* Find a vacant FID */ for( i = MAX_FIDS / 2; i < MAX_FIDS && (fids[i] & 0xffff0000); i++ ); diff --git a/drivers/net/wireless/marvell/libertas/rx.c b/drivers/net/wireless/marvell/libertas/rx.c index 58a1fc433b73..f28aa09d1f9e 100644 --- a/drivers/net/wireless/marvell/libertas/rx.c +++ b/drivers/net/wireless/marvell/libertas/rx.c @@ -62,9 +62,6 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) struct rxpd *p_rx_pd; int hdrchop; struct ethhdr *p_ethhdr; - static const u8 rfc1042_eth_hdr[] = { - 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 - }; BUG_ON(!skb); @@ -102,7 +99,7 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) sizeof(p_rx_pkt->eth803_hdr.src_addr)); if (memcmp(&p_rx_pkt->rfc1042_hdr, - rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr)) == 0) { + rfc1042_header, sizeof(rfc1042_header)) == 0) { /* * Replace the 803 header and rfc1042 header (llc/snap) with an * EthernetII header, keep the src/dst and snap_type (ethertype) diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index 97813ac291ae..4e4f59c17ded 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c @@ -4335,6 +4335,11 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta; wiphy->n_iface_combinations = 1; + if (adapter->max_sta_conn > adapter->max_p2p_conn) + wiphy->max_ap_assoc_sta = adapter->max_sta_conn; + else + wiphy->max_ap_assoc_sta = adapter->max_p2p_conn; + /* Initialize cipher suits */ wiphy->cipher_suites = mwifiex_cipher_suites; wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites); diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c index 7e4b8cd52605..d068b9075c32 100644 --- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c +++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c @@ -1495,6 +1495,7 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv, struct mwifiex_adapter *adapter = priv->adapter; struct mwifiex_ie_types_header *tlv; struct hw_spec_api_rev *api_rev; + struct hw_spec_max_conn *max_conn; u16 resp_size, api_id; int i, left_len, parsed_len = 0; @@ -1581,8 +1582,21 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv, adapter->fw_api_ver = api_rev->major_ver; mwifiex_dbg(adapter, INFO, - "Firmware api version %d\n", - adapter->fw_api_ver); + "Firmware api version %d.%d\n", + adapter->fw_api_ver, + api_rev->minor_ver); + break; + case UAP_FW_API_VER_ID: + mwifiex_dbg(adapter, INFO, + "uAP api version %d.%d\n", + api_rev->major_ver, + api_rev->minor_ver); + break; + case CHANRPT_API_VER_ID: + mwifiex_dbg(adapter, INFO, + "channel report api version %d.%d\n", + api_rev->major_ver, + api_rev->minor_ver); break; default: mwifiex_dbg(adapter, FATAL, @@ -1591,6 +1605,17 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv, break; } break; + case TLV_TYPE_MAX_CONN: + max_conn = (struct hw_spec_max_conn *)tlv; + adapter->max_p2p_conn = max_conn->max_p2p_conn; + adapter->max_sta_conn = max_conn->max_sta_conn; + mwifiex_dbg(adapter, INFO, + "max p2p connections: %u\n", + adapter->max_p2p_conn); + mwifiex_dbg(adapter, INFO, + "max sta connections: %u\n", + adapter->max_sta_conn); + break; default: mwifiex_dbg(adapter, FATAL, "Unknown GET_HW_SPEC TLV type: %#x\n", diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h index a415d73a73e6..8047e307892e 100644 --- a/drivers/net/wireless/marvell/mwifiex/fw.h +++ b/drivers/net/wireless/marvell/mwifiex/fw.h @@ -220,6 +220,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { #define TLV_TYPE_BSS_MODE (PROPRIETARY_TLV_BASE_ID + 206) #define TLV_TYPE_RANDOM_MAC (PROPRIETARY_TLV_BASE_ID + 236) #define TLV_TYPE_CHAN_ATTR_CFG (PROPRIETARY_TLV_BASE_ID + 237) +#define TLV_TYPE_MAX_CONN (PROPRIETARY_TLV_BASE_ID + 279) #define MWIFIEX_TX_DATA_BUF_SIZE_2K 2048 @@ -1052,6 +1053,8 @@ struct host_cmd_ds_802_11_ps_mode_enh { enum API_VER_ID { KEY_API_VER_ID = 1, FW_API_VER_ID = 2, + UAP_FW_API_VER_ID = 3, + CHANRPT_API_VER_ID = 4, }; struct hw_spec_api_rev { @@ -2386,4 +2389,11 @@ struct mwifiex_opt_sleep_confirm { __le16 action; __le16 resp_ctrl; } __packed; + +struct hw_spec_max_conn { + struct mwifiex_ie_types_header header; + u8 max_p2p_conn; + u8 max_sta_conn; +} __packed; + #endif /* !_MWIFIEX_FW_H_ */ diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index afaffc325452..5923c5c14c8d 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -1022,6 +1022,7 @@ struct mwifiex_adapter { bool ext_scan; u8 fw_api_ver; u8 key_api_major_ver, key_api_minor_ver; + u8 max_p2p_conn, max_sta_conn; struct memory_type_mapping *mem_type_mapping_tbl; u8 num_mem_types; bool scan_chan_gap_enabled; diff --git a/drivers/net/wireless/mediatek/mt76/debugfs.c b/drivers/net/wireless/mediatek/mt76/debugfs.c index 0278e1b44576..3a5de1d1b121 100644 --- a/drivers/net/wireless/mediatek/mt76/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/debugfs.c @@ -51,7 +51,7 @@ static int mt76_rx_queues_read(struct seq_file *s, void *data) struct mt76_dev *dev = dev_get_drvdata(s->private); int i, queued; - for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++) { + mt76_for_each_q_rx(dev, i) { struct mt76_queue *q = &dev->q_rx[i]; if (!q->ndesc) diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 75e659774e07..f4d6074fe32a 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -576,7 +576,7 @@ mt76_dma_init(struct mt76_dev *dev) init_dummy_netdev(&dev->napi_dev); - for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++) { + mt76_for_each_q_rx(dev, i) { netif_napi_add(&dev->napi_dev, &dev->napi[i], mt76_dma_rx_poll, 64); mt76_dma_rx_fill(dev, &dev->q_rx[i]); @@ -610,7 +610,7 @@ void mt76_dma_cleanup(struct mt76_dev *dev) for (i = 0; i < ARRAY_SIZE(dev->q_tx); i++) mt76_dma_tx_cleanup(dev, i, true); - for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++) { + mt76_for_each_q_rx(dev, i) { netif_napi_del(&dev->napi[i]); mt76_dma_rx_cleanup(dev, &dev->q_rx[i]); } diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index e6de4a1b8f26..dfe625a53c63 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -288,8 +288,8 @@ enum { MT76_REMOVED, MT76_READING_STATS, MT76_STATE_POWER_OFF, - MT76_STATE_PS, MT76_STATE_SUSPEND, + MT76_STATE_ROC, }; struct mt76_hw_cap { @@ -537,8 +537,8 @@ struct mt76_dev { wait_queue_head_t tx_wait; struct sk_buff_head status_list; - unsigned long wcid_mask[MT76_N_WCIDS / BITS_PER_LONG]; - unsigned long wcid_phy_mask[MT76_N_WCIDS / BITS_PER_LONG]; + u32 wcid_mask[DIV_ROUND_UP(MT76_N_WCIDS, 32)]; + u32 wcid_phy_mask[DIV_ROUND_UP(MT76_N_WCIDS, 32)]; struct mt76_wcid global_wcid; struct mt76_wcid __rcu *wcid[MT76_N_WCIDS]; @@ -671,6 +671,10 @@ static inline u16 mt76_rev(struct mt76_dev *dev) #define mt76_queue_tx_cleanup(dev, ...) (dev)->mt76.queue_ops->tx_cleanup(&((dev)->mt76), __VA_ARGS__) #define mt76_queue_kick(dev, ...) (dev)->mt76.queue_ops->kick(&((dev)->mt76), __VA_ARGS__) +#define mt76_for_each_q_rx(dev, i) \ + for (i = 0; i < ARRAY_SIZE((dev)->q_rx) && \ + (dev)->q_rx[i].ndesc; i++) + struct mt76_dev *mt76_alloc_device(struct device *pdev, unsigned int size, const struct ieee80211_ops *ops, const struct mt76_driver_ops *drv_ops); diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c index f8c0c957ca01..8060c1514396 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c @@ -473,7 +473,7 @@ mt7603_rx_get_wcid(struct mt7603_dev *dev, u8 idx, bool unicast) struct mt7603_sta *sta; struct mt76_wcid *wcid; - if (idx >= ARRAY_SIZE(dev->mt76.wcid)) + if (idx >= MT7603_WTBL_SIZE) return NULL; wcid = rcu_dereference(dev->mt76.wcid[idx]); @@ -1238,7 +1238,7 @@ void mt7603_mac_add_txs(struct mt7603_dev *dev, void *data) if (pid == MT_PACKET_ID_NO_ACK) return; - if (wcidx >= ARRAY_SIZE(dev->mt76.wcid)) + if (wcidx >= MT7603_WTBL_SIZE) return; rcu_read_lock(); @@ -1438,8 +1438,9 @@ static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev) for (i = 0; i < __MT_TXQ_MAX; i++) mt76_queue_tx_cleanup(dev, i, true); - for (i = 0; i < ARRAY_SIZE(dev->mt76.q_rx); i++) + mt76_for_each_q_rx(&dev->mt76, i) { mt76_queue_rx_reset(dev, i); + } mt7603_dma_sched_reset(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c index 6a5ae047c63b..edac37e7847b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c @@ -111,6 +111,12 @@ mt7615_eeprom_parse_hw_band_cap(struct mt7615_dev *dev) return; } + if (is_mt7611(&dev->mt76)) { + /* 5GHz only */ + dev->mt76.cap.has_5ghz = true; + return; + } + val = FIELD_GET(MT_EE_NIC_WIFI_CONF_BAND_SEL, eeprom[MT_EE_WIFI_CONF]); switch (val) { @@ -310,6 +316,7 @@ static void mt7615_cal_free_data(struct mt7615_dev *dev) mt7622_apply_cal_free_data(dev); break; case 0x7615: + case 0x7611: mt7615_apply_cal_free_data(dev); break; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c index 1d8fdc7e062b..e2d80518e5af 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c @@ -139,8 +139,10 @@ void mt7615_check_offload_capability(struct mt7615_dev *dev) ieee80211_hw_set(hw, SUPPORTS_PS); ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS); + wiphy->max_remain_on_channel_duration = 5000; wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR | NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR | + WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | NL80211_FEATURE_P2P_GO_CTWIN | NL80211_FEATURE_P2P_GO_OPPPS; } else { @@ -149,6 +151,8 @@ void mt7615_check_offload_capability(struct mt7615_dev *dev) dev->ops->sched_scan_start = NULL; dev->ops->sched_scan_stop = NULL; dev->ops->set_rekey_data = NULL; + dev->ops->remain_on_channel = NULL; + dev->ops->cancel_remain_on_channel = NULL; wiphy->max_sched_scan_plan_interval = 0; wiphy->max_sched_scan_ie_len = 0; @@ -368,12 +372,6 @@ int mt7615_register_ext_phy(struct mt7615_dev *dev) if (phy) return 0; - INIT_DELAYED_WORK(&phy->mac_work, mt7615_mac_work); - INIT_DELAYED_WORK(&phy->scan_work, mt7615_scan_work); - skb_queue_head_init(&phy->scan_event_list); - - INIT_WORK(&phy->ps_work, mt7615_ps_work); - mt7615_cap_dbdc_enable(dev); mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7615_ops); if (!mphy) @@ -386,6 +384,14 @@ int mt7615_register_ext_phy(struct mt7615_dev *dev) mphy->antenna_mask = BIT(hweight8(phy->chainmask)) - 1; mt7615_init_wiphy(mphy->hw); + INIT_DELAYED_WORK(&phy->mac_work, mt7615_mac_work); + INIT_DELAYED_WORK(&phy->scan_work, mt7615_scan_work); + skb_queue_head_init(&phy->scan_event_list); + + INIT_WORK(&phy->roc_work, mt7615_roc_work); + timer_setup(&phy->roc_timer, mt7615_roc_timer, 0); + init_waitqueue_head(&phy->roc_wait); + mt7615_mac_set_scs(phy, true); /* @@ -437,9 +443,11 @@ void mt7615_init_device(struct mt7615_dev *dev) INIT_LIST_HEAD(&dev->sta_poll_list); spin_lock_init(&dev->sta_poll_lock); init_waitqueue_head(&dev->reset_wait); + init_waitqueue_head(&dev->phy.roc_wait); INIT_WORK(&dev->reset_work, mt7615_mac_reset_work); - INIT_WORK(&dev->phy.ps_work, mt7615_ps_work); + INIT_WORK(&dev->phy.roc_work, mt7615_roc_work); + timer_setup(&dev->phy.roc_timer, mt7615_roc_timer, 0); mt7615_init_wiphy(hw); dev->mphy.sband_2g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 7d65a3fb0c23..9f1c6ca7a665 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -61,7 +61,7 @@ static struct mt76_wcid *mt7615_rx_get_wcid(struct mt7615_dev *dev, struct mt7615_sta *sta; struct mt76_wcid *wcid; - if (idx >= ARRAY_SIZE(dev->mt76.wcid)) + if (idx >= MT7615_WTBL_SIZE) return NULL; wcid = rcu_dereference(dev->mt76.wcid[idx]); @@ -175,7 +175,8 @@ mt7615_get_status_freq_info(struct mt7615_dev *dev, struct mt76_phy *mphy, struct mt76_rx_status *status, u8 chfreq) { if (!test_bit(MT76_HW_SCANNING, &mphy->state) && - !test_bit(MT76_HW_SCHED_SCANNING, &mphy->state)) { + !test_bit(MT76_HW_SCHED_SCANNING, &mphy->state) && + !test_bit(MT76_STATE_ROC, &mphy->state)) { status->freq = mphy->chandef.chan->center_freq; status->band = mphy->chandef.chan->band; return; @@ -1302,7 +1303,7 @@ static void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data) if (pid == MT_PACKET_ID_NO_ACK) return; - if (wcidx >= ARRAY_SIZE(dev->mt76.wcid)) + if (wcidx >= MT7615_WTBL_SIZE) return; rcu_read_lock(); @@ -1819,8 +1820,9 @@ void mt7615_dma_reset(struct mt7615_dev *dev) for (i = 0; i < __MT_TXQ_MAX; i++) mt76_queue_tx_cleanup(dev, i, true); - for (i = 0; i < ARRAY_SIZE(dev->mt76.q_rx); i++) + mt76_for_each_q_rx(&dev->mt76, i) { mt76_queue_rx_reset(dev, i); + } mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_RX_DMA_EN | MT_WPDMA_GLO_CFG_TX_DMA_EN | @@ -1849,8 +1851,13 @@ void mt7615_mac_reset_work(struct work_struct *work) set_bit(MT76_MCU_RESET, &dev->mphy.state); wake_up(&dev->mt76.mcu.wait); cancel_delayed_work_sync(&dev->phy.mac_work); - if (phy2) + del_timer_sync(&dev->phy.roc_timer); + cancel_work_sync(&dev->phy.roc_work); + if (phy2) { cancel_delayed_work_sync(&phy2->mac_work); + del_timer_sync(&phy2->roc_timer); + cancel_work_sync(&phy2->roc_work); + } /* lock/unlock all queues to ensure that no tx is pending */ mt76_txq_schedule_all(&dev->mphy); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 2e9e9d3519d7..c26f99b368d9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -71,7 +71,8 @@ static void mt7615_stop(struct ieee80211_hw *hw) struct mt7615_phy *phy = mt7615_hw_phy(hw); cancel_delayed_work_sync(&phy->mac_work); - cancel_work_sync(&phy->ps_work); + del_timer_sync(&phy->roc_timer); + cancel_work_sync(&phy->roc_work); mutex_lock(&dev->mt76.mutex); @@ -289,12 +290,11 @@ mt7615_queue_key_update(struct mt7615_dev *dev, enum set_key_cmd cmd, wd->type = MT7615_WTBL_KEY_DESC; wd->sta = msta; - wd->key.key = kzalloc(key->keylen, GFP_KERNEL); + wd->key.key = kmemdup(key->key, key->keylen, GFP_KERNEL); if (!wd->key.key) { kfree(wd); return -ENOMEM; } - memcpy(wd->key.key, key->key, key->keylen); wd->key.cipher = key->cipher; wd->key.keyidx = key->keyidx; wd->key.keylen = key->keylen; @@ -360,20 +360,6 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return mt7615_mac_wtbl_set_key(dev, wcid, key, cmd); } -void mt7615_ps_work(struct work_struct *work) -{ - struct mt7615_phy *phy; - - phy = (struct mt7615_phy *)container_of(work, struct mt7615_phy, - ps_work); - - mutex_lock(&phy->dev->mt76.mutex); - ieee80211_iterate_active_interfaces(phy->mt76->hw, - IEEE80211_IFACE_ITER_RESUME_ALL, - m7615_mcu_set_ps_iter, phy); - mutex_unlock(&phy->dev->mt76.mutex); -} - static int mt7615_config(struct ieee80211_hw *hw, u32 changed) { struct mt7615_dev *dev = mt7615_hw_dev(hw); @@ -399,14 +385,6 @@ static int mt7615_config(struct ieee80211_hw *hw, u32 changed) mt76_wr(dev, MT_WF_RFCR(band), phy->rxfilter); } - if (changed & IEEE80211_CONF_CHANGE_PS) { - if (hw->conf.flags & IEEE80211_CONF_PS) - set_bit(MT76_STATE_PS, &phy->mt76->state); - else - clear_bit(MT76_STATE_PS, &phy->mt76->state); - ieee80211_queue_work(hw, &phy->ps_work); - } - mutex_unlock(&dev->mt76.mutex); return ret; @@ -509,6 +487,9 @@ static void mt7615_bss_info_changed(struct ieee80211_hw *hw, BSS_CHANGED_BEACON_ENABLED)) mt7615_mcu_add_beacon(dev, hw, vif, info->enable_beacon); + if (changed & BSS_CHANGED_PS) + mt7615_mcu_set_vif_ps(dev, vif); + mutex_unlock(&dev->mt76.mutex); } @@ -791,6 +772,37 @@ mt7615_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) return 0; } +static void mt7615_roc_iter(void *priv, u8 *mac, + struct ieee80211_vif *vif) +{ + struct mt7615_phy *phy = priv; + + mt7615_mcu_set_roc(phy, vif, NULL, 0); +} + +void mt7615_roc_work(struct work_struct *work) +{ + struct mt7615_phy *phy; + + phy = (struct mt7615_phy *)container_of(work, struct mt7615_phy, + roc_work); + + if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state)) + return; + + ieee80211_iterate_active_interfaces(phy->mt76->hw, + IEEE80211_IFACE_ITER_RESUME_ALL, + mt7615_roc_iter, phy); + ieee80211_remain_on_channel_expired(phy->mt76->hw); +} + +void mt7615_roc_timer(struct timer_list *timer) +{ + struct mt7615_phy *phy = from_timer(phy, timer, roc_timer); + + ieee80211_queue_work(phy->mt76->hw, &phy->roc_work); +} + void mt7615_scan_work(struct work_struct *work) { struct mt7615_phy *phy; @@ -864,6 +876,50 @@ mt7615_stop_sched_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif) return mt7615_mcu_sched_scan_enable(mphy->priv, vif, false); } +static int mt7615_remain_on_channel(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_channel *chan, + int duration, + enum ieee80211_roc_type type) +{ + struct mt7615_phy *phy = mt7615_hw_phy(hw); + int err; + + if (test_and_set_bit(MT76_STATE_ROC, &phy->mt76->state)) + return 0; + + err = mt7615_mcu_set_roc(phy, vif, chan, duration); + if (err < 0) { + clear_bit(MT76_STATE_ROC, &phy->mt76->state); + return err; + } + + if (!wait_event_timeout(phy->roc_wait, phy->roc_grant, HZ)) { + mt7615_mcu_set_roc(phy, vif, NULL, 0); + clear_bit(MT76_STATE_ROC, &phy->mt76->state); + + return -ETIMEDOUT; + } + + return 0; +} + +static int mt7615_cancel_remain_on_channel(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct mt7615_phy *phy = mt7615_hw_phy(hw); + + if (!test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state)) + return 0; + + del_timer_sync(&phy->roc_timer); + cancel_work_sync(&phy->roc_work); + + mt7615_mcu_set_roc(phy, vif, NULL, 0); + + return 0; +} + #ifdef CONFIG_PM static int mt7615_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) @@ -978,6 +1034,8 @@ const struct ieee80211_ops mt7615_ops = { .cancel_hw_scan = mt7615_cancel_hw_scan, .sched_scan_start = mt7615_start_sched_scan, .sched_scan_stop = mt7615_stop_sched_scan, + .remain_on_channel = mt7615_remain_on_channel, + .cancel_remain_on_channel = mt7615_cancel_remain_on_channel, #ifdef CONFIG_PM .suspend = mt7615_suspend, .resume = mt7615_resume, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c index b944f372738a..6e869b8c5e26 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -360,6 +360,33 @@ mt7615_mcu_scan_event(struct mt7615_dev *dev, struct sk_buff *skb) } static void +mt7615_mcu_roc_event(struct mt7615_dev *dev, struct sk_buff *skb) +{ + struct mt7615_roc_tlv *event; + struct mt7615_phy *phy; + struct mt76_phy *mphy; + int duration; + + skb_pull(skb, sizeof(struct mt7615_mcu_rxd)); + event = (struct mt7615_roc_tlv *)skb->data; + + if (event->dbdc_band && dev->mt76.phy2) + mphy = dev->mt76.phy2; + else + mphy = &dev->mt76.phy; + + ieee80211_ready_on_channel(mphy->hw); + + phy = (struct mt7615_phy *)mphy->priv; + phy->roc_grant = true; + wake_up(&phy->roc_wait); + + duration = le32_to_cpu(event->max_interval); + mod_timer(&phy->roc_timer, + round_jiffies_up(jiffies + msecs_to_jiffies(duration))); +} + +static void mt7615_mcu_beacon_loss_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) { struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; @@ -426,6 +453,9 @@ mt7615_mcu_rx_unsolicited_event(struct mt7615_dev *dev, struct sk_buff *skb) case MCU_EVENT_BSS_BEACON_LOSS: mt7615_mcu_beacon_loss_event(dev, skb); break; + case MCU_EVENT_ROC: + mt7615_mcu_roc_event(dev, skb); + break; case MCU_EVENT_SCHED_SCAN_DONE: case MCU_EVENT_SCAN_DONE: mt7615_mcu_scan_event(dev, skb); @@ -451,6 +481,7 @@ void mt7615_mcu_rx_event(struct mt7615_dev *dev, struct sk_buff *skb) rxd->eid == MCU_EVENT_SCHED_SCAN_DONE || rxd->eid == MCU_EVENT_BSS_ABSENCE || rxd->eid == MCU_EVENT_SCAN_DONE || + rxd->eid == MCU_EVENT_ROC || !rxd->seq) mt7615_mcu_rx_unsolicited_event(dev, skb); else @@ -2741,11 +2772,9 @@ int mt7615_mcu_set_sku_en(struct mt7615_phy *phy, bool enable) sizeof(req), true); } -void m7615_mcu_set_ps_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) +int mt7615_mcu_set_vif_ps(struct mt7615_dev *dev, struct ieee80211_vif *vif) { struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; - struct mt7615_phy *phy = priv; - struct mt76_phy *mphy = phy->mt76; struct { u8 bss_idx; u8 ps_state; /* 0: device awake @@ -2754,12 +2783,14 @@ void m7615_mcu_set_ps_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) */ } req = { .bss_idx = mvif->idx, - .ps_state = test_bit(MT76_STATE_PS, &mphy->state) ? 2 : 0, + .ps_state = vif->bss_conf.ps ? 2 : 0, }; - if (vif->type == NL80211_IFTYPE_STATION) - __mt76_mcu_send_msg(&phy->dev->mt76, MCU_CMD_SET_PS_PROFILE, - &req, sizeof(req), false); + if (vif->type != NL80211_IFTYPE_STATION) + return -ENOTSUPP; + + return __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SET_PS_PROFILE, + &req, sizeof(req), false); } int mt7615_mcu_set_channel_domain(struct mt7615_phy *phy) @@ -2867,6 +2898,7 @@ int mt7615_mcu_hw_scan(struct mt7615_phy *phy, struct ieee80211_vif *vif, n_ssids++; } req->ssid_type = n_ssids ? BIT(2) : BIT(0); + req->ssid_type_ext = n_ssids ? BIT(0) : 0; req->ssids_num = n_ssids; /* increase channel time for passive scan */ @@ -3601,6 +3633,26 @@ int mt7615_mcu_update_gtk_rekey(struct ieee80211_hw *hw, } #endif /* CONFIG_PM */ +int mt7615_mcu_set_roc(struct mt7615_phy *phy, struct ieee80211_vif *vif, + struct ieee80211_channel *chan, int duration) +{ + struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; + struct mt7615_dev *dev = phy->dev; + struct mt7615_roc_tlv req = { + .bss_idx = mvif->idx, + .active = !chan, + .max_interval = cpu_to_le32(duration), + .primary_chan = chan ? chan->hw_value : 0, + .band = chan ? chan->band : 0, + .req_type = 2, + }; + + phy->roc_grant = false; + + return __mt76_mcu_send_msg(&dev->mt76, MCU_CMD_SET_ROC, &req, + sizeof(req), false); +} + int mt7615_mcu_set_p2p_oppps(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h index 348521b0d44c..2314d0b23af1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.h @@ -82,6 +82,7 @@ enum { MCU_EVENT_ACCESS_REG = 0x02, MCU_EVENT_MT_PATCH_SEM = 0x04, MCU_EVENT_SCAN_DONE = 0x0d, + MCU_EVENT_ROC = 0x10, MCU_EVENT_BSS_ABSENCE = 0x11, MCU_EVENT_BSS_BEACON_LOSS = 0x13, MCU_EVENT_CH_PRIVILEGE = 0x18, @@ -326,7 +327,8 @@ struct mt7615_hw_scan_req { */ u8 ssid_type; /* BIT(0) wildcard SSID * BIT(1) P2P wildcard SSID - * BIT(2) specified SSID + * BIT(2) specified SSID + wildcard SSID + * BIT(2) + ssid_type_ext BIT(0) specified SSID only */ u8 ssids_num; u8 probe_req_num; /* Number of probe request for each SSID */ @@ -361,7 +363,8 @@ struct mt7615_hw_scan_req { struct mt7615_mcu_scan_ssid ext_ssids[6]; u8 bssid[ETH_ALEN]; u8 random_mac[ETH_ALEN]; /* valid when BIT(1) in scan_func is set. */ - u8 pad[64]; + u8 pad[63]; + u8 ssid_type_ext; } __packed; #define SCAN_DONE_EVENT_MAX_CHANNEL_NUM 64 @@ -525,6 +528,23 @@ struct mt7615_gtk_rekey_tlv { u8 reserverd[3]; } __packed; +struct mt7615_roc_tlv { + u8 bss_idx; + u8 token; + u8 active; + u8 primary_chan; + u8 sco; + u8 band; + u8 width; /* To support 80/160MHz bandwidth */ + u8 freq_seg1; /* To support 80/160MHz bandwidth */ + u8 freq_seg2; /* To support 80/160MHz bandwidth */ + u8 req_type; + u8 dbdc_band; + u8 rsv0; + __le32 max_interval; /* ms */ + u8 rsv1[8]; +} __packed; + /* offload mcu commands */ enum { MCU_CMD_START_HW_SCAN = MCU_CE_PREFIX | 0x03, @@ -533,6 +553,7 @@ enum { MCU_CMD_SET_BSS_CONNECTED = MCU_CE_PREFIX | 0x16, MCU_CMD_SET_BSS_ABORT = MCU_CE_PREFIX | 0x17, MCU_CMD_CANCEL_HW_SCAN = MCU_CE_PREFIX | 0x1b, + MCU_CMD_SET_ROC = MCU_CE_PREFIX | 0x1c, MCU_CMD_SET_P2P_OPPPS = MCU_CE_PREFIX | 0x33, MCU_CMD_SCHED_SCAN_ENABLE = MCU_CE_PREFIX | 0x61, MCU_CMD_SCHED_SCAN_REQ = MCU_CE_PREFIX | 0x62, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index ebdfca64b079..d6176d316bee 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -201,7 +201,10 @@ struct mt7615_phy { struct sk_buff_head scan_event_list; struct delayed_work scan_work; - struct work_struct ps_work; + struct work_struct roc_work; + struct timer_list roc_timer; + wait_queue_head_t roc_wait; + bool roc_grant; }; #define mt7615_mcu_add_tx_ba(dev, ...) (dev)->mcu_ops->add_tx_ba((dev), __VA_ARGS__) @@ -411,7 +414,7 @@ static inline bool is_mt7622(struct mt76_dev *dev) static inline bool is_mt7615(struct mt76_dev *dev) { - return mt76_chip(dev) == 0x7615; + return mt76_chip(dev) == 0x7615 || mt76_chip(dev) == 0x7611; } static inline bool is_mt7663(struct mt76_dev *dev) @@ -419,6 +422,11 @@ static inline bool is_mt7663(struct mt76_dev *dev) return mt76_chip(dev) == 0x7663; } +static inline bool is_mt7611(struct mt76_dev *dev) +{ + return mt76_chip(dev) == 0x7611; +} + static inline void mt7615_irq_enable(struct mt7615_dev *dev, u32 mask) { mt76_set_irq_mask(&dev->mt76, 0, 0, mask); @@ -441,7 +449,8 @@ static inline u16 mt7615_wtbl_size(struct mt7615_dev *dev) void mt7615_dma_reset(struct mt7615_dev *dev); void mt7615_scan_work(struct work_struct *work); -void mt7615_ps_work(struct work_struct *work); +void mt7615_roc_work(struct work_struct *work); +void mt7615_roc_timer(struct timer_list *timer); void mt7615_init_txpower(struct mt7615_dev *dev, struct ieee80211_supported_band *sband); void mt7615_phy_init(struct mt7615_dev *dev); @@ -527,11 +536,13 @@ int mt7615_mcu_set_radar_th(struct mt7615_dev *dev, int index, int mt7615_mcu_set_sku_en(struct mt7615_phy *phy, bool enable); int mt7615_mcu_apply_rx_dcoc(struct mt7615_phy *phy); int mt7615_mcu_apply_tx_dpd(struct mt7615_phy *phy); -void m7615_mcu_set_ps_iter(void *priv, u8 *mac, struct ieee80211_vif *vif); +int mt7615_mcu_set_vif_ps(struct mt7615_dev *dev, struct ieee80211_vif *vif); int mt7615_dfs_init_radar_detector(struct mt7615_phy *phy); int mt7615_mcu_set_p2p_oppps(struct ieee80211_hw *hw, struct ieee80211_vif *vif); +int mt7615_mcu_set_roc(struct mt7615_phy *phy, struct ieee80211_vif *vif, + struct ieee80211_channel *chan, int duration); int mt7615_firmware_own(struct mt7615_dev *dev); int mt7615_driver_own(struct mt7615_dev *dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c index 88ff14564521..ba12f199bce0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci.c @@ -14,6 +14,7 @@ static const struct pci_device_id mt7615_pci_device_table[] = { { PCI_DEVICE(0x14c3, 0x7615) }, { PCI_DEVICE(0x14c3, 0x7663) }, + { PCI_DEVICE(0x14c3, 0x7611) }, { }, }; @@ -85,8 +86,9 @@ static int mt7615_pci_suspend(struct pci_dev *pdev, pm_message_t state) napi_disable(&mdev->tx_napi); tasklet_kill(&mdev->tx_tasklet); - for (i = 0; i < ARRAY_SIZE(mdev->q_rx); i++) + mt76_for_each_q_rx(mdev, i) { napi_disable(&mdev->napi[i]); + } tasklet_kill(&dev->irq_tasklet); mt7615_dma_reset(dev); @@ -119,8 +121,9 @@ static int mt7615_pci_suspend(struct pci_dev *pdev, pm_message_t state) return 0; restore: - for (i = 0; i < ARRAY_SIZE(mdev->q_rx); i++) + mt76_for_each_q_rx(mdev, i) { napi_enable(&mdev->napi[i]); + } napi_enable(&mdev->tx_napi); if (hif_suspend) mt7615_mcu_set_hif_suspend(dev, false); @@ -155,7 +158,7 @@ static int mt7615_pci_resume(struct pci_dev *pdev) if (pdma_reset) dev_err(mdev->dev, "PDMA engine must be reinitialized\n"); - for (i = 0; i < ARRAY_SIZE(mdev->q_rx); i++) { + mt76_for_each_q_rx(mdev, i) { napi_enable(&mdev->napi[i]); napi_schedule(&mdev->napi[i]); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/usb.c b/drivers/net/wireless/mediatek/mt76/mt7615/usb.c index d74253319622..a50077eb24d7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/usb.c @@ -51,7 +51,8 @@ static void mt7663u_stop(struct ieee80211_hw *hw) struct mt7615_dev *dev = hw->priv; clear_bit(MT76_STATE_RUNNING, &dev->mphy.state); - cancel_work_sync(&phy->ps_work); + del_timer_sync(&phy->roc_timer); + cancel_work_sync(&phy->roc_work); cancel_delayed_work_sync(&phy->scan_work); cancel_delayed_work_sync(&phy->mac_work); mt76u_stop_tx(&dev->mt76); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h index 6ea210bd3f07..4c9bbc7ce023 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h @@ -15,6 +15,7 @@ #include "mt76x02_dfs.h" #include "mt76x02_dma.h" +#define MT76x02_N_WCIDS 128 #define MT_CALIBRATE_INTERVAL HZ #define MT_MAC_WORK_INTERVAL (HZ / 10) @@ -246,7 +247,7 @@ mt76x02_rx_get_sta(struct mt76_dev *dev, u8 idx) { struct mt76_wcid *wcid; - if (idx >= ARRAY_SIZE(dev->wcid)) + if (idx >= MT76x02_N_WCIDS) return NULL; wcid = rcu_dereference(dev->wcid[idx]); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index a5a3bcd30d6f..e4e03beabe43 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c @@ -561,7 +561,7 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev, rcu_read_lock(); - if (stat->wcid < ARRAY_SIZE(dev->mt76.wcid)) + if (stat->wcid < MT76x02_N_WCIDS) wcid = rcu_dereference(dev->mt76.wcid[stat->wcid]); if (wcid && wcid->sta) { diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c index 89a8992d84fa..267058086a90 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c @@ -20,7 +20,7 @@ int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, int ret; u8 seq; - if (mt76_is_mmio(&dev->mt76) && dev->mcu_timeout) + if (dev->mcu_timeout) return -EIO; skb = mt76_mcu_msg_alloc(mdev, data, len); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c index 7e389dbccfeb..cbbe986655fe 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c @@ -415,7 +415,7 @@ static void mt76x02_reset_state(struct mt76x02_dev *dev) ieee80211_iter_keys_rcu(dev->mt76.hw, NULL, mt76x02_key_sync, NULL); rcu_read_unlock(); - for (i = 0; i < ARRAY_SIZE(dev->mt76.wcid); i++) { + for (i = 0; i < MT76x02_N_WCIDS; i++) { struct ieee80211_sta *sta; struct ieee80211_vif *vif; struct mt76x02_sta *msta; @@ -489,8 +489,9 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev) for (i = 0; i < __MT_TXQ_MAX; i++) mt76_queue_tx_cleanup(dev, i, true); - for (i = 0; i < ARRAY_SIZE(dev->mt76.q_rx); i++) + mt76_for_each_q_rx(&dev->mt76, i) { mt76_queue_rx_reset(dev, i); + } mt76x02_mac_start(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index 9a2c9afa2fb5..44822a849eb1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -249,7 +249,7 @@ int mt76x02_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, memset(msta, 0, sizeof(*msta)); - idx = mt76_wcid_alloc(dev->mt76.wcid_mask, ARRAY_SIZE(dev->mt76.wcid)); + idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT76x02_N_WCIDS); if (idx < 0) return -ENOSPC; diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c index ee0066fedd04..5278bee812f1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c @@ -173,14 +173,14 @@ mt7915_txbf_stat_read_phy(struct mt7915_phy *phy, struct seq_file *s) /* Tx Beamformee Rx NDPA & Tx feedback report */ cnt = mt76_rr(dev, MT_ETBF_TX_NDP_BFRP(ext_phy)); - seq_printf(s, "Tx Beamformee sucessful feedback frames: %ld\n", + seq_printf(s, "Tx Beamformee successful feedback frames: %ld\n", FIELD_GET(MT_ETBF_TX_FB_CPL, cnt)); - seq_printf(s, "Tx Beamformee feedback triggerd counts: %ld\n", + seq_printf(s, "Tx Beamformee feedback triggered counts: %ld\n", FIELD_GET(MT_ETBF_TX_FB_TRI, cnt)); /* Tx SU counters */ cnt = mt76_rr(dev, MT_MIB_DR11(ext_phy)); - seq_printf(s, "Tx single-user sucessful MPDU counts: %d\n", cnt); + seq_printf(s, "Tx single-user successful MPDU counts: %d\n", cnt); seq_puts(s, "\n"); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index 6f200ab3ac28..aadf56e80bae 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -592,7 +592,6 @@ int mt7915_register_ext_phy(struct mt7915_dev *dev) if (phy) return 0; - INIT_DELAYED_WORK(&phy->mac_work, mt7915_mac_work); mt7915_cap_dbdc_enable(dev); mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7915_ops); if (!mphy) @@ -605,6 +604,8 @@ int mt7915_register_ext_phy(struct mt7915_dev *dev) mphy->antenna_mask = BIT(hweight8(phy->chainmask)) - 1; mt7915_init_wiphy(mphy->hw); + INIT_DELAYED_WORK(&phy->mac_work, mt7915_mac_work); + /* * Make the secondary PHY MAC address local without overlapping with * the usual MAC address allocation scheme on multiple virtual interfaces diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index 7ad7c2b7afdc..a264e304a3df 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -235,9 +235,14 @@ mt7915_mac_decode_he_radiotap(struct sk_buff *skb, .data1 = HE_BITS(DATA1_DATA_MCS_KNOWN) | HE_BITS(DATA1_DATA_DCM_KNOWN) | HE_BITS(DATA1_STBC_KNOWN) | - HE_BITS(DATA1_CODING_KNOWN), + HE_BITS(DATA1_CODING_KNOWN) | + HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) | + HE_BITS(DATA1_DOPPLER_KNOWN) | + HE_BITS(DATA1_BSS_COLOR_KNOWN), .data2 = HE_BITS(DATA2_GI_KNOWN) | - HE_BITS(DATA2_TXBF_KNOWN), + HE_BITS(DATA2_TXBF_KNOWN) | + HE_BITS(DATA2_PE_DISAMBIG_KNOWN) | + HE_BITS(DATA2_TXOP_KNOWN), }; struct ieee80211_radiotap_he *he = NULL; __le32 v2 = rxv->v[2]; @@ -248,12 +253,6 @@ mt7915_mac_decode_he_radiotap(struct sk_buff *skb, he = skb_push(skb, sizeof(known)); memcpy(he, &known, sizeof(known)); - he->data1 = HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) | - HE_BITS(DATA1_DOPPLER_KNOWN) | - HE_BITS(DATA1_BSS_COLOR_KNOWN); - he->data2 = HE_BITS(DATA2_PE_DISAMBIG_KNOWN) | - HE_BITS(DATA2_TXOP_KNOWN); - he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, v14) | HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, v2); he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, v2) | @@ -296,10 +295,10 @@ mt7915_mac_decode_he_radiotap(struct sk_buff *skb, HE_BITS(DATA1_SPTL_REUSE3_KNOWN) | HE_BITS(DATA1_SPTL_REUSE4_KNOWN); - he->data4 = HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK, v11) | - HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK, v11) | - HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK, v11) | - HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK, v11); + he->data4 |= HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK, v11) | + HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK, v11) | + HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK, v11) | + HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK, v11); mt7915_mac_decode_he_radiotap_ru(status, rxv, he); break; @@ -426,20 +425,26 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) /* RXD Group 3 - P-RXV */ if (rxd1 & MT_RXD1_NORMAL_GROUP_3) { + u32 v0, v1, v2; + memcpy(rxv.v, rxd, sizeof(rxv.v)); rxd += 2; if ((u8 *)rxd - skb->data >= skb->len) return -EINVAL; - if (rxv.v[0] & MT_PRXV_HT_AD_CODE) + v0 = le32_to_cpu(rxv.v[0]); + v1 = le32_to_cpu(rxv.v[1]); + v2 = le32_to_cpu(rxv.v[2]); + + if (v0 & MT_PRXV_HT_AD_CODE) status->enc_flags |= RX_ENC_FLAG_LDPC; status->chains = mphy->antenna_mask; - status->chain_signal[0] = to_rssi(MT_PRXV_RCPI0, rxv.v[1]); - status->chain_signal[1] = to_rssi(MT_PRXV_RCPI1, rxv.v[1]); - status->chain_signal[2] = to_rssi(MT_PRXV_RCPI2, rxv.v[1]); - status->chain_signal[3] = to_rssi(MT_PRXV_RCPI3, rxv.v[1]); + status->chain_signal[0] = to_rssi(MT_PRXV_RCPI0, v1); + status->chain_signal[1] = to_rssi(MT_PRXV_RCPI1, v1); + status->chain_signal[2] = to_rssi(MT_PRXV_RCPI2, v1); + status->chain_signal[3] = to_rssi(MT_PRXV_RCPI3, v1); status->signal = status->chain_signal[0]; for (i = 1; i < hweight8(mphy->antenna_mask); i++) { @@ -452,16 +457,16 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) /* RXD Group 5 - C-RXV */ if (rxd1 & MT_RXD1_NORMAL_GROUP_5) { - u8 stbc = FIELD_GET(MT_CRXV_HT_STBC, rxv.v[2]); - u8 gi = FIELD_GET(MT_CRXV_HT_SHORT_GI, rxv.v[2]); + u8 stbc = FIELD_GET(MT_CRXV_HT_STBC, v2); + u8 gi = FIELD_GET(MT_CRXV_HT_SHORT_GI, v2); bool cck = false; rxd += 18; if ((u8 *)rxd - skb->data >= skb->len) return -EINVAL; - idx = i = FIELD_GET(MT_PRXV_TX_RATE, rxv.v[0]); - rxv.phy = FIELD_GET(MT_CRXV_TX_MODE, rxv.v[2]); + idx = i = FIELD_GET(MT_PRXV_TX_RATE, v0); + rxv.phy = FIELD_GET(MT_CRXV_TX_MODE, v2); switch (rxv.phy) { case MT_PHY_TYPE_CCK: @@ -478,7 +483,7 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) break; case MT_PHY_TYPE_VHT: status->nss = - FIELD_GET(MT_PRXV_NSTS, rxv.v[0]) + 1; + FIELD_GET(MT_PRXV_NSTS, v0) + 1; status->encoding = RX_ENC_VHT; if (i > 9) return -EINVAL; @@ -490,7 +495,7 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) case MT_PHY_TYPE_HE_EXT_SU: case MT_PHY_TYPE_HE_TB: status->nss = - FIELD_GET(MT_PRXV_NSTS, rxv.v[0]) + 1; + FIELD_GET(MT_PRXV_NSTS, v0) + 1; status->encoding = RX_ENC_HE; status->flag |= RX_FLAG_RADIOTAP_HE; i &= GENMASK(3, 0); @@ -506,7 +511,7 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) } status->rate_idx = i; - switch (FIELD_GET(MT_CRXV_FRAME_MODE, rxv.v[2])) { + switch (FIELD_GET(MT_CRXV_FRAME_MODE, v2)) { case IEEE80211_STA_RX_BW_20: break; case IEEE80211_STA_RX_BW_40: @@ -612,7 +617,7 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi, skb->priority & IEEE80211_QOS_CTL_TID_MASK) | FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx); if (ext_phy && q_idx >= MT_LMAC_ALTX0 && q_idx <= MT_LMAC_BCN0) - val |= cpu_to_le32(MT_TXD1_TGID); + val |= MT_TXD1_TGID; txwi[1] = cpu_to_le32(val); @@ -1141,8 +1146,9 @@ mt7915_dma_reset(struct mt7915_dev *dev) for (i = 0; i < __MT_TXQ_MAX; i++) mt76_queue_tx_cleanup(dev, i, true); - for (i = 0; i < ARRAY_SIZE(dev->mt76.q_rx); i++) + mt76_for_each_q_rx(&dev->mt76, i) { mt76_queue_rx_reset(dev, i); + } /* re-init prefetch settings after reset */ mt7915_dma_prefetch(dev); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index 98567374c2c9..0575c259f245 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -437,8 +437,10 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw, mt7915_mcu_add_sta(dev, vif, NULL, join); } - if (changed & BSS_CHANGED_ASSOC) + if (changed & BSS_CHANGED_ASSOC) { mt7915_mcu_add_bss_info(phy, vif, info->assoc); + mt7915_mcu_add_obss_spr(dev, vif, info->he_obss_pd.enable); + } if (changed & BSS_CHANGED_ERP_SLOT) { int slottime = info->use_short_slot ? 9 : 20; @@ -458,6 +460,9 @@ static void mt7915_bss_info_changed(struct ieee80211_hw *hw, if (changed & (BSS_CHANGED_QOS | BSS_CHANGED_BEACON_ENABLED)) mt7915_mcu_set_tx(dev, vif); + if (changed & BSS_CHANGED_HE_OBSS_PD) + mt7915_mcu_add_obss_spr(dev, vif, info->he_obss_pd.enable); + if (changed & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED)) mt7915_mcu_add_beacon(hw, vif, info->enable_beacon); @@ -790,7 +795,7 @@ mt7915_sta_rc_update(struct ieee80211_hw *hw, rcu_read_unlock(); return; } - rcu_read_lock(); + rcu_read_unlock(); set_bit(changed, &msta->stats.changed); ieee80211_queue_work(hw, &msta->stats_work); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index 99eeea42478f..c8c12c740c1a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -220,7 +220,7 @@ static int __mt7915_mcu_msg_send(struct mt7915_dev *dev, struct sk_buff *skb, { struct mt7915_mcu_txd *mcu_txd; u8 seq, pkt_fmt, qidx; - enum mt7915_txq_id txq; + enum mt76_txq_id txq; __le32 *txd; u32 val; @@ -815,8 +815,7 @@ static void mt7915_check_he_obss_narrow_bw_ru_iter(struct wiphy *wiphy, struct mt7915_he_obss_narrow_bw_ru_data *data = _data; const struct element *elem; - elem = cfg80211_find_elem(WLAN_EID_EXT_CAPABILITY, bss->ies->data, - bss->ies->len); + elem = ieee80211_bss_get_elem(bss, WLAN_EID_EXT_CAPABILITY); if (!elem || elem->datalen < 10 || !(elem->data[10] & @@ -1802,15 +1801,12 @@ static u8 mt7915_mcu_sta_txbf_type(struct mt7915_phy *phy, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { - struct mt7915_sta *msta; u8 type = 0; if (vif->type != NL80211_IFTYPE_STATION && vif->type != NL80211_IFTYPE_AP) return 0; - msta = (struct mt7915_sta *)sta->drv_priv; - if (sta->he_cap.has_he) { struct ieee80211_he_cap_elem *pe; const struct ieee80211_he_cap_elem *ve; @@ -1954,7 +1950,7 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev, ra->supp_ht_mcs = *(__le32 *)ra->ht_mcs; ra->supp_mode |= MODE_HT; - mcs = hweight32(ra->supp_ht_mcs) - 1; + mcs = hweight32(le32_to_cpu(ra->supp_ht_mcs)) - 1; ra->af = sta->ht_cap.ampdu_factor; ra->ht_gf = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD); @@ -1972,7 +1968,7 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev, } if (sta->vht_cap.vht_supported) { - __le16 mcs_map = sta->vht_cap.vht_mcs.rx_mcs_map; + u16 mcs_map = le16_to_cpu(sta->vht_cap.vht_mcs.rx_mcs_map); u16 vht_mcs; u8 af, mcs_prev; @@ -2399,7 +2395,7 @@ static int mt7915_mcu_init_download(struct mt7915_dev *dev, u32 addr, }; int attr; - if (req.addr == MCU_PATCH_ADDRESS) + if (req.addr == cpu_to_le32(MCU_PATCH_ADDRESS)) attr = -MCU_CMD_PATCH_START_REQ; else attr = -MCU_CMD_TARGET_ADDRESS_LEN_REQ; @@ -2672,7 +2668,7 @@ int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level) u16 len; u8 level; u8 rsv[3]; - u32 module_idx; + __le32 module_idx; } data = { .module_idx = cpu_to_le32(module), .level = level, @@ -3159,3 +3155,28 @@ int mt7915_mcu_set_txbf_sounding(struct mt7915_dev *dev) return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_TXBF_ACTION, &req, sizeof(req), true); } + +int mt7915_mcu_add_obss_spr(struct mt7915_dev *dev, struct ieee80211_vif *vif, + bool enable) +{ +#define MT_SPR_ENABLE 1 + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + struct { + u8 action; + u8 arg_num; + u8 band_idx; + u8 status; + u8 drop_tx_idx; + u8 sta_idx; /* 256 sta */ + u8 rsv[2]; + u32 val; + } __packed req = { + .action = MT_SPR_ENABLE, + .arg_num = 1, + .band_idx = mvif->band_idx, + .val = enable, + }; + + return __mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_SPR, + &req, sizeof(req), true); +} diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h index 34ace6e672d0..c241dd7c4c36 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h @@ -212,6 +212,7 @@ enum { MCU_EXT_CMD_RATE_CTRL = 0x87, MCU_EXT_CMD_FW_DBG_CTRL = 0x95, MCU_EXT_CMD_SET_RDD_TH = 0x9d, + MCU_EXT_CMD_SET_SPR = 0xa8, }; enum { diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h index 5392292a838e..85d74ecd0351 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h @@ -301,6 +301,8 @@ int mt7915_mcu_add_key(struct mt7915_dev *dev, struct ieee80211_vif *vif, enum set_key_cmd cmd); int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int enable); +int mt7915_mcu_add_obss_spr(struct mt7915_dev *dev, struct ieee80211_vif *vif, + bool enable); int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta); int mt7915_mcu_add_smps(struct mt7915_dev *dev, struct ieee80211_vif *vif, diff --git a/drivers/net/wireless/mediatek/mt76/util.c b/drivers/net/wireless/mediatek/mt76/util.c index 07cf71242d9e..ecde87465bf6 100644 --- a/drivers/net/wireless/mediatek/mt76/util.c +++ b/drivers/net/wireless/mediatek/mt76/util.c @@ -42,17 +42,17 @@ bool __mt76_poll_msec(struct mt76_dev *dev, u32 offset, u32 mask, u32 val, } EXPORT_SYMBOL_GPL(__mt76_poll_msec); -int mt76_wcid_alloc(unsigned long *mask, int size) +int mt76_wcid_alloc(u32 *mask, int size) { int i, idx = 0, cur; - for (i = 0; i < DIV_ROUND_UP(size, BITS_PER_LONG); i++) { + for (i = 0; i < DIV_ROUND_UP(size, 32); i++) { idx = ffs(~mask[i]); if (!idx) continue; idx--; - cur = i * BITS_PER_LONG + idx; + cur = i * 32 + idx; if (cur >= size) break; @@ -74,13 +74,13 @@ int mt76_get_min_avg_rssi(struct mt76_dev *dev, bool ext_phy) rcu_read_lock(); for (i = 0; i < ARRAY_SIZE(dev->wcid_mask); i++) { - unsigned long mask = dev->wcid_mask[i]; - unsigned long phy_mask = dev->wcid_phy_mask[i]; + u32 mask = dev->wcid_mask[i]; + u32 phy_mask = dev->wcid_phy_mask[i]; if (!mask) continue; - for (j = i * BITS_PER_LONG; mask; j++, mask >>= 1, phy_mask >>= 1) { + for (j = i * 32; mask; j++, mask >>= 1, phy_mask >>= 1) { if (!(mask & 1)) continue; diff --git a/drivers/net/wireless/mediatek/mt76/util.h b/drivers/net/wireless/mediatek/mt76/util.h index 48a71e7479e5..fd1a68820e0a 100644 --- a/drivers/net/wireless/mediatek/mt76/util.h +++ b/drivers/net/wireless/mediatek/mt76/util.h @@ -14,24 +14,24 @@ #define MT76_INCR(_var, _size) \ (_var = (((_var) + 1) % (_size))) -int mt76_wcid_alloc(unsigned long *mask, int size); +int mt76_wcid_alloc(u32 *mask, int size); static inline bool -mt76_wcid_mask_test(unsigned long *mask, int idx) +mt76_wcid_mask_test(u32 *mask, int idx) { - return mask[idx / BITS_PER_LONG] & BIT(idx % BITS_PER_LONG); + return mask[idx / 32] & BIT(idx % 32); } static inline void -mt76_wcid_mask_set(unsigned long *mask, int idx) +mt76_wcid_mask_set(u32 *mask, int idx) { - mask[idx / BITS_PER_LONG] |= BIT(idx % BITS_PER_LONG); + mask[idx / 32] |= BIT(idx % 32); } static inline void -mt76_wcid_mask_clear(unsigned long *mask, int idx) +mt76_wcid_mask_clear(u32 *mask, int idx) { - mask[idx / BITS_PER_LONG] &= ~BIT(idx % BITS_PER_LONG); + mask[idx / 32] &= ~BIT(idx % 32); } static inline void diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c index 6beac1f74e7c..a779fe771a55 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c @@ -9971,9 +9971,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) if (!rt2x00_is_usb(rt2x00dev)) ieee80211_hw_set(rt2x00dev->hw, HOST_BROADCAST_PS_BUFFERING); - /* Set MFP if HW crypto is disabled. */ - if (rt2800_hwcrypt_disabled(rt2x00dev)) - ieee80211_hw_set(rt2x00dev->hw, MFP_CAPABLE); + ieee80211_hw_set(rt2x00dev->hw, MFP_CAPABLE); SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c b/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c index 32efbc8e9f92..2f68a31072ae 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c @@ -468,7 +468,8 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) return 0; - if (!rt2x00_has_cap_hw_crypto(rt2x00dev)) + /* The hardware can't do MFP */ + if (!rt2x00_has_cap_hw_crypto(rt2x00dev) || (sta && sta->mfp)) return -EOPNOTSUPP; /* diff --git a/drivers/net/wireless/realtek/rtw88/coex.c b/drivers/net/wireless/realtek/rtw88/coex.c index 924dccd5d146..cbf3d503df1c 100644 --- a/drivers/net/wireless/realtek/rtw88/coex.c +++ b/drivers/net/wireless/realtek/rtw88/coex.c @@ -751,10 +751,18 @@ EXPORT_SYMBOL(rtw_coex_write_indirect_reg); static void rtw_coex_coex_ctrl_owner(struct rtw_dev *rtwdev, bool wifi_control) { - if (wifi_control) + struct rtw_chip_info *chip = rtwdev->chip; + const struct rtw_hw_reg *btg_reg = chip->btg_reg; + + if (wifi_control) { rtw_write32_set(rtwdev, REG_SYS_SDIO_CTRL, BIT_LTE_MUX_CTRL_PATH); - else + if (btg_reg) + rtw_write8_set(rtwdev, btg_reg->addr, btg_reg->mask); + } else { rtw_write32_clr(rtwdev, REG_SYS_SDIO_CTRL, BIT_LTE_MUX_CTRL_PATH); + if (btg_reg) + rtw_write8_clr(rtwdev, btg_reg->addr, btg_reg->mask); + } } static void rtw_coex_set_gnt_bt(struct rtw_dev *rtwdev, u8 state) @@ -1346,12 +1354,15 @@ static void rtw_coex_action_bt_inquiry(struct rtw_dev *rtwdev) tdma_case = 108; else tdma_case = 109; + } else if (coex_stat->wl_gl_busy) { + table_case = 114; + tdma_case = 121; } else if (coex_stat->wl_connected) { - table_case = 101; - tdma_case = 110; - } else { table_case = 100; tdma_case = 100; + } else { + table_case = 101; + tdma_case = 100; } } diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c index 98d2ac22f6f6..c412bc54efde 100644 --- a/drivers/net/wireless/realtek/rtw88/mac80211.c +++ b/drivers/net/wireless/realtek/rtw88/mac80211.c @@ -341,13 +341,11 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw, rtw_leave_lps_deep(rtwdev); if (changed & BSS_CHANGED_ASSOC) { - struct rtw_chip_info *chip = rtwdev->chip; enum rtw_net_type net_type; if (conf->assoc) { rtw_coex_connect_notify(rtwdev, COEX_ASSOCIATE_FINISH); net_type = RTW_NET_MGD_LINKED; - chip->ops->phy_calibration(rtwdev); rtwvif->aid = conf->aid; rtw_fw_download_rsvd_page(rtwdev); @@ -663,6 +661,7 @@ static void rtw_ops_mgd_prepare_tx(struct ieee80211_hw *hw, mutex_lock(&rtwdev->mutex); rtw_leave_lps_deep(rtwdev); rtw_coex_connect_notify(rtwdev, COEX_ASSOCIATE_START); + rtw_chip_prepare_tx(rtwdev); mutex_unlock(&rtwdev->mutex); } diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c index f88a7d2370aa..0eefafc51c62 100644 --- a/drivers/net/wireless/realtek/rtw88/main.c +++ b/drivers/net/wireless/realtek/rtw88/main.c @@ -408,6 +408,23 @@ void rtw_set_channel(struct rtw_dev *rtwdev) } rtw_phy_set_tx_power_level(rtwdev, center_chan); + + /* if the channel isn't set for scanning, we will do RF calibration + * in ieee80211_ops::mgd_prepare_tx(). Performing the calibration + * during scanning on each channel takes too long. + */ + if (!test_bit(RTW_FLAG_SCANNING, rtwdev->flags)) + rtwdev->need_rfk = true; +} + +void rtw_chip_prepare_tx(struct rtw_dev *rtwdev) +{ + struct rtw_chip_info *chip = rtwdev->chip; + + if (rtwdev->need_rfk) { + rtwdev->need_rfk = false; + chip->ops->phy_calibration(rtwdev); + } } static void rtw_vif_write_addr(struct rtw_dev *rtwdev, u32 start, u8 *addr) diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h index 7ee09c008cd4..0841f5fa4bf2 100644 --- a/drivers/net/wireless/realtek/rtw88/main.h +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -1174,6 +1174,7 @@ struct rtw_chip_info { const struct coex_rf_para *wl_rf_para_tx; const struct coex_rf_para *wl_rf_para_rx; const struct coex_5g_afh_map *afh_5g; + const struct rtw_hw_reg *btg_reg; const struct rtw_reg_domain *coex_info_hw_regs; }; @@ -1719,6 +1720,8 @@ struct rtw_dev { struct rtw_fw_state wow_fw; struct rtw_wow_param wow; + bool need_rfk; + /* hci related data, must be last */ u8 priv[] __aligned(sizeof(void *)); }; @@ -1792,6 +1795,7 @@ void rtw_restore_reg(struct rtw_dev *rtwdev, struct rtw_backup_info *bckp, u32 num); void rtw_desc_to_mcsrate(u16 rate, u8 *mcs, u8 *nss); void rtw_set_channel(struct rtw_dev *rtwdev); +void rtw_chip_prepare_tx(struct rtw_dev *rtwdev); void rtw_vif_port_config(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif, u32 config); void rtw_tx_report_purge_timer(struct timer_list *t); diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c index 8641ea645c4b..4700195c8eef 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c @@ -2040,7 +2040,7 @@ static const struct coex_tdma_para tdma_sant_8723d[] = { /* Non-Shared-Antenna TDMA */ static const struct coex_tdma_para tdma_nsant_8723d[] = { - { {0x00, 0x00, 0x00, 0x40, 0x00} }, /* case-100 */ + { {0x00, 0x00, 0x00, 0x40, 0x01} }, /* case-100 */ { {0x61, 0x45, 0x03, 0x11, 0x11} }, /* case-101 */ { {0x61, 0x3a, 0x03, 0x11, 0x11} }, { {0x61, 0x30, 0x03, 0x11, 0x11} }, @@ -2060,7 +2060,8 @@ static const struct coex_tdma_para tdma_nsant_8723d[] = { { {0x51, 0x3a, 0x03, 0x10, 0x50} }, { {0x51, 0x30, 0x03, 0x10, 0x50} }, { {0x51, 0x20, 0x03, 0x10, 0x50} }, - { {0x51, 0x10, 0x03, 0x10, 0x50} } + { {0x51, 0x10, 0x03, 0x10, 0x50} }, /* case-120 */ + { {0x51, 0x08, 0x03, 0x10, 0x50} }, }; /* rssi in percentage % (dbm = % - 100) */ @@ -2068,6 +2069,10 @@ static const u8 wl_rssi_step_8723d[] = {60, 50, 44, 30}; static const u8 bt_rssi_step_8723d[] = {30, 30, 30, 30}; static const struct coex_5g_afh_map afh_5g_8723d[] = { {0, 0, 0} }; +static const struct rtw_hw_reg btg_reg_8723d = { + .addr = REG_BTG_SEL, .mask = BIT_MASK_BTG_WL, +}; + /* wl_tx_dec_power, bt_tx_dec_power, wl_rx_gain, bt_rx_lna_constrain */ static const struct coex_rf_para rf_para_tx_8723d[] = { {0, 0, false, 7}, /* for normal */ @@ -2093,6 +2098,16 @@ static const struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8723d[] = { RTW_PWR_INTF_ALL_MSK, RTW_PWR_ADDR_MAC, RTW_PWR_CMD_WRITE, BIT(3) | BIT(7), 0}, + {0x0086, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_SDIO, + RTW_PWR_CMD_WRITE, BIT(0), 0}, + {0x0086, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_SDIO, + RTW_PWR_CMD_POLLING, BIT(1), BIT(1)}, {0x004A, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_USB_MSK, @@ -2103,6 +2118,11 @@ static const struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8723d[] = { RTW_PWR_INTF_ALL_MSK, RTW_PWR_ADDR_MAC, RTW_PWR_CMD_WRITE, BIT(3) | BIT(4), 0}, + {0x0023, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(4), 0}, {0x0301, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_PCI_MSK, @@ -2310,6 +2330,11 @@ static const struct rtw_pwr_seq_cmd trans_act_to_lps_8723d[] = { RTW_PWR_INTF_ALL_MSK, RTW_PWR_ADDR_MAC, RTW_PWR_CMD_WRITE, BIT(1), 0}, + {0x0093, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, 0xFF, 0x00}, {0x0553, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_ALL_MSK, @@ -2389,6 +2414,11 @@ static const struct rtw_pwr_seq_cmd trans_act_to_cardemu_8723d[] = { }; static const struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8723d[] = { + {0x0007, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, 0xFF, 0x20}, {0x0005, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK, @@ -2409,6 +2439,21 @@ static const struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8723d[] = { RTW_PWR_INTF_USB_MSK, RTW_PWR_ADDR_MAC, RTW_PWR_CMD_WRITE, BIT(0), 1}, + {0x0023, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(4), BIT(4)}, + {0x0086, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_SDIO, + RTW_PWR_CMD_WRITE, BIT(0), BIT(0)}, + {0x0086, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_SDIO, + RTW_PWR_CMD_POLLING, BIT(1), 0}, {0xFFFF, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_ALL_MSK, @@ -2694,6 +2739,7 @@ struct rtw_chip_info rtw8723d_hw_spec = { .bt_afh_span_bw40 = 0x30, .afh_5g_num = ARRAY_SIZE(afh_5g_8723d), .afh_5g = afh_5g_8723d, + .btg_reg = &btg_reg_8723d, .coex_info_hw_regs_num = ARRAY_SIZE(coex_info_hw_regs_8723d), .coex_info_hw_regs = coex_info_hw_regs_8723d, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.h b/drivers/net/wireless/realtek/rtw88/rtw8723d.h index 31b8ed9ee652..7894d321cd7e 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8723d.h +++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.h @@ -145,6 +145,7 @@ static inline s32 iqk_mult(s32 x, s32 y, s32 *ext) #define REG_GPIO_INTM 0x0048 #define REG_BTG_SEL 0x0067 +#define BIT_MASK_BTG_WL BIT(7) #define REG_LTECOEX_PATH_CONTROL 0x0070 #define REG_LTECOEX_CTRL 0x07c0 #define REG_LTECOEX_WRITE_DATA 0x07c4 diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c index 6abcdf4070a2..e49bdd76ab9a 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c @@ -1551,6 +1551,16 @@ static void rtw8822b_bf_config_bfee(struct rtw_dev *rtwdev, struct rtw_vif *vif, } static const struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8822b[] = { + {0x0086, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_SDIO, + RTW_PWR_CMD_WRITE, BIT(0), 0}, + {0x0086, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_SDIO, + RTW_PWR_CMD_POLLING, BIT(1), BIT(1)}, {0x004A, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_USB_MSK, @@ -1679,6 +1689,11 @@ static const struct rtw_pwr_seq_cmd trans_cardemu_to_act_8822b[] = { RTW_PWR_INTF_ALL_MSK, RTW_PWR_ADDR_MAC, RTW_PWR_CMD_WRITE, 0xFF, 0x0c}, + {0x0068, + RTW_PWR_CUT_C_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(4), BIT(4)}, {0x0029, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_ALL_MSK, @@ -1707,6 +1722,11 @@ static const struct rtw_pwr_seq_cmd trans_cardemu_to_act_8822b[] = { }; static const struct rtw_pwr_seq_cmd trans_act_to_cardemu_8822b[] = { + {0x0003, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(2), 0}, {0x0093, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_ALL_MSK, @@ -1775,6 +1795,11 @@ static const struct rtw_pwr_seq_cmd trans_act_to_cardemu_8822b[] = { }; static const struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8822b[] = { + {0x0005, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(7), BIT(7)}, {0x0007, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK, @@ -1795,6 +1820,46 @@ static const struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8822b[] = { RTW_PWR_INTF_USB_MSK, RTW_PWR_ADDR_MAC, RTW_PWR_CMD_WRITE, BIT(0), 0}, + {0x0067, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(5), 0}, + {0x0067, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(4), 0}, + {0x004F, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(0), 0}, + {0x0067, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(1), 0}, + {0x0046, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(6), BIT(6)}, + {0x0067, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(2), 0}, + {0x0046, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(7), BIT(7)}, + {0x0062, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(4), BIT(4)}, {0x0081, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_ALL_MSK, @@ -1805,11 +1870,41 @@ static const struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8822b[] = { RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK, RTW_PWR_ADDR_MAC, RTW_PWR_CMD_WRITE, BIT(3) | BIT(4), BIT(3)}, + {0x0086, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_SDIO, + RTW_PWR_CMD_WRITE, BIT(0), BIT(0)}, + {0x0086, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_SDIO, + RTW_PWR_CMD_POLLING, BIT(1), 0}, {0x0090, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_PCI_MSK, RTW_PWR_ADDR_MAC, RTW_PWR_CMD_WRITE, BIT(1), 0}, + {0x0044, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_SDIO, + RTW_PWR_CMD_WRITE, 0xFF, 0}, + {0x0040, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_SDIO, + RTW_PWR_CMD_WRITE, 0xFF, 0x90}, + {0x0041, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_SDIO, + RTW_PWR_CMD_WRITE, 0xFF, 0x00}, + {0x0042, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_SDIO, + RTW_PWR_CMD_WRITE, 0xFF, 0x04}, {0xFFFF, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_ALL_MSK, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c index fe995bb4e43e..c3d72ef611c6 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c @@ -1037,7 +1037,7 @@ static void rtw8822c_set_power_trim(struct rtw_dev *rtwdev, s8 bb_gain[2][8]) static void rtw8822c_power_trim(struct rtw_dev *rtwdev) { u8 pg_pwr = 0xff, i, path, idx; - s8 bb_gain[2][8] = {0}; + s8 bb_gain[2][8] = {}; u16 rf_efuse_2g[3] = {PPG_2GL_TXAB, PPG_2GM_TXAB, PPG_2GH_TXAB}; u16 rf_efuse_5g[2][5] = {{PPG_5GL1_TXA, PPG_5GL2_TXA, PPG_5GM1_TXA, PPG_5GM2_TXA, PPG_5GH1_TXA}, @@ -1496,7 +1496,6 @@ static void rtw8822c_set_channel_bb(struct rtw_dev *rtwdev, u8 channel, u8 bw, { if (IS_CH_2G_BAND(channel)) { rtw_write32_clr(rtwdev, REG_BGCTRL, BITS_RX_IQ_WEIGHT); - rtw_write32_mask(rtwdev, REG_RXCCKSEL, 0xf0000000, 0x8); rtw_write32_set(rtwdev, REG_TXF4, BIT(20)); rtw_write32_clr(rtwdev, REG_CCK_CHECK, BIT_CHECK_CCK_EN); rtw_write32_clr(rtwdev, REG_CCKTXONLY, BIT_BB_CCK_CHECK_EN); @@ -1564,7 +1563,6 @@ static void rtw8822c_set_channel_bb(struct rtw_dev *rtwdev, u8 channel, u8 bw, rtw_write32_set(rtwdev, REG_CCK_CHECK, BIT_CHECK_CCK_EN); rtw_write32_set(rtwdev, REG_BGCTRL, BITS_RX_IQ_WEIGHT); rtw_write32_clr(rtwdev, REG_TXF4, BIT(20)); - rtw_write32_mask(rtwdev, REG_RXCCKSEL, 0xf0000000, 0x0); rtw_write32_mask(rtwdev, REG_CCAMSK, 0x3F000000, 0x22); rtw_write32_mask(rtwdev, REG_TXDFIR0, 0x70, 0x3); if (IS_CH_5G_BAND_1(channel) || IS_CH_5G_BAND_2(channel)) { @@ -3563,6 +3561,16 @@ static void rtw8822c_pwr_track(struct rtw_dev *rtwdev) } static const struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8822c[] = { + {0x0086, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_SDIO, + RTW_PWR_CMD_WRITE, BIT(0), 0}, + {0x0086, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_SDIO, + RTW_PWR_CMD_POLLING, BIT(1), BIT(1)}, {0x002E, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_ALL_MSK, @@ -3773,6 +3781,11 @@ static const struct rtw_pwr_seq_cmd trans_act_to_cardemu_8822c[] = { }; static const struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8822c[] = { + {0x0005, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_MAC, + RTW_PWR_CMD_WRITE, BIT(7), BIT(7)}, {0x0007, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK, @@ -3818,6 +3831,11 @@ static const struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8822c[] = { RTW_PWR_INTF_PCI_MSK, RTW_PWR_ADDR_MAC, RTW_PWR_CMD_WRITE, BIT(2), BIT(2)}, + {0x0086, + RTW_PWR_CUT_ALL_MSK, + RTW_PWR_INTF_SDIO_MSK, + RTW_PWR_ADDR_SDIO, + RTW_PWR_CMD_WRITE, BIT(0), BIT(0)}, {0xFFFF, RTW_PWR_CUT_ALL_MSK, RTW_PWR_INTF_ALL_MSK, diff --git a/drivers/net/wireless/st/cw1200/cw1200_sdio.c b/drivers/net/wireless/st/cw1200/cw1200_sdio.c index 43e012073dbf..b65ec14136c7 100644 --- a/drivers/net/wireless/st/cw1200/cw1200_sdio.c +++ b/drivers/net/wireless/st/cw1200/cw1200_sdio.c @@ -14,6 +14,7 @@ #include <linux/mmc/sdio_func.h> #include <linux/mmc/card.h> #include <linux/mmc/sdio.h> +#include <linux/mmc/sdio_ids.h> #include <net/mac80211.h> #include "cw1200.h" @@ -48,14 +49,6 @@ struct hwbus_priv { const struct cw1200_platform_data_sdio *pdata; }; -#ifndef SDIO_VENDOR_ID_STE -#define SDIO_VENDOR_ID_STE 0x0020 -#endif - -#ifndef SDIO_DEVICE_ID_STE_CW1200 -#define SDIO_DEVICE_ID_STE_CW1200 0x2280 -#endif - static const struct sdio_device_id cw1200_sdio_ids[] = { { SDIO_DEVICE(SDIO_VENDOR_ID_STE, SDIO_DEVICE_ID_STE_CW1200) }, { /* end: all zeroes */ }, diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 4421fc656b1c..de6c8a7589ca 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -548,7 +548,7 @@ static int wlcore_irq_locked(struct wl1271 *wl) ret = wlcore_fw_status(wl, wl->fw_status); if (ret < 0) - goto out; + goto err_ret; wlcore_hw_tx_immediate_compl(wl); @@ -565,7 +565,7 @@ static int wlcore_irq_locked(struct wl1271 *wl) ret = -EIO; /* restarting the chip. ignore any other interrupt. */ - goto out; + goto err_ret; } if (unlikely(intr & WL1271_ACX_SW_INTR_WATCHDOG)) { @@ -575,7 +575,7 @@ static int wlcore_irq_locked(struct wl1271 *wl) ret = -EIO; /* restarting the chip. ignore any other interrupt. */ - goto out; + goto err_ret; } if (likely(intr & WL1271_ACX_INTR_DATA)) { @@ -583,7 +583,7 @@ static int wlcore_irq_locked(struct wl1271 *wl) ret = wlcore_rx(wl, wl->fw_status); if (ret < 0) - goto out; + goto err_ret; /* Check if any tx blocks were freed */ spin_lock_irqsave(&wl->wl_lock, flags); @@ -596,7 +596,7 @@ static int wlcore_irq_locked(struct wl1271 *wl) */ ret = wlcore_tx_work_locked(wl); if (ret < 0) - goto out; + goto err_ret; } else { spin_unlock_irqrestore(&wl->wl_lock, flags); } @@ -604,7 +604,7 @@ static int wlcore_irq_locked(struct wl1271 *wl) /* check for tx results */ ret = wlcore_hw_tx_delayed_compl(wl); if (ret < 0) - goto out; + goto err_ret; /* Make sure the deferred queues don't get too long */ defer_count = skb_queue_len(&wl->deferred_tx_queue) + @@ -617,14 +617,14 @@ static int wlcore_irq_locked(struct wl1271 *wl) wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A"); ret = wl1271_event_handle(wl, 0); if (ret < 0) - goto out; + goto err_ret; } if (intr & WL1271_ACX_INTR_EVENT_B) { wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B"); ret = wl1271_event_handle(wl, 1); if (ret < 0) - goto out; + goto err_ret; } if (intr & WL1271_ACX_INTR_INIT_COMPLETE) @@ -635,6 +635,7 @@ static int wlcore_irq_locked(struct wl1271 *wl) wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE"); } +err_ret: pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); @@ -1746,9 +1747,7 @@ static int __maybe_unused wl1271_op_suspend(struct ieee80211_hw *hw, ret = wl1271_configure_suspend(wl, wlvif, wow); if (ret < 0) { - mutex_unlock(&wl->mutex); - wl1271_warning("couldn't prepare device to suspend"); - return ret; + goto out_sleep; } } @@ -2698,12 +2697,16 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, if (!wlcore_is_p2p_mgmt(wlvif)) { ret = wl12xx_cmd_role_disable(wl, &wlvif->role_id); - if (ret < 0) + if (ret < 0) { + pm_runtime_put_noidle(wl->dev); goto deinit; + } } else { ret = wl12xx_cmd_role_disable(wl, &wlvif->dev_role_id); - if (ret < 0) + if (ret < 0) { + pm_runtime_put_noidle(wl->dev); goto deinit; + } } pm_runtime_mark_last_busy(wl->dev); @@ -3665,8 +3668,10 @@ void wlcore_regdomain_config(struct wl1271 *wl) goto out; ret = pm_runtime_get_sync(wl->dev); - if (ret < 0) + if (ret < 0) { + pm_runtime_put_autosuspend(wl->dev); goto out; + } ret = wlcore_cmd_regdomain_config_locked(wl); if (ret < 0) { diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c index 90e56d4c3df3..e20e18cd04ae 100644 --- a/drivers/net/wireless/ti/wlcore/tx.c +++ b/drivers/net/wireless/ti/wlcore/tx.c @@ -863,6 +863,7 @@ void wl1271_tx_work(struct work_struct *work) ret = wlcore_tx_work_locked(wl); if (ret < 0) { + pm_runtime_put_noidle(wl->dev); wl12xx_queue_recovery_work(wl); goto out; } |