diff options
Diffstat (limited to 'drivers/net/wireless')
102 files changed, 7102 insertions, 768 deletions
diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index cc154a81737d..24b983edb357 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c | |||
| @@ -1066,8 +1066,8 @@ EXPORT_SYMBOL(ath10k_ce_revoke_recv_next); | |||
| 1066 | * Guts of ath10k_ce_completed_send_next. | 1066 | * Guts of ath10k_ce_completed_send_next. |
| 1067 | * The caller takes responsibility for any necessary locking. | 1067 | * The caller takes responsibility for any necessary locking. |
| 1068 | */ | 1068 | */ |
| 1069 | int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, | 1069 | static int _ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, |
| 1070 | void **per_transfer_contextp) | 1070 | void **per_transfer_contextp) |
| 1071 | { | 1071 | { |
| 1072 | struct ath10k_ce_ring *src_ring = ce_state->src_ring; | 1072 | struct ath10k_ce_ring *src_ring = ce_state->src_ring; |
| 1073 | u32 ctrl_addr = ce_state->ctrl_addr; | 1073 | u32 ctrl_addr = ce_state->ctrl_addr; |
| @@ -1118,6 +1118,66 @@ int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, | |||
| 1118 | 1118 | ||
| 1119 | return 0; | 1119 | return 0; |
| 1120 | } | 1120 | } |
| 1121 | |||
| 1122 | static int _ath10k_ce_completed_send_next_nolock_64(struct ath10k_ce_pipe *ce_state, | ||
| 1123 | void **per_transfer_contextp) | ||
| 1124 | { | ||
| 1125 | struct ath10k_ce_ring *src_ring = ce_state->src_ring; | ||
| 1126 | u32 ctrl_addr = ce_state->ctrl_addr; | ||
| 1127 | struct ath10k *ar = ce_state->ar; | ||
| 1128 | unsigned int nentries_mask = src_ring->nentries_mask; | ||
| 1129 | unsigned int sw_index = src_ring->sw_index; | ||
| 1130 | unsigned int read_index; | ||
| 1131 | struct ce_desc_64 *desc; | ||
| 1132 | |||
| 1133 | if (src_ring->hw_index == sw_index) { | ||
| 1134 | /* | ||
| 1135 | * The SW completion index has caught up with the cached | ||
| 1136 | * version of the HW completion index. | ||
| 1137 | * Update the cached HW completion index to see whether | ||
| 1138 | * the SW has really caught up to the HW, or if the cached | ||
| 1139 | * value of the HW index has become stale. | ||
| 1140 | */ | ||
| 1141 | |||
| 1142 | read_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr); | ||
| 1143 | if (read_index == 0xffffffff) | ||
| 1144 | return -ENODEV; | ||
| 1145 | |||
| 1146 | read_index &= nentries_mask; | ||
| 1147 | src_ring->hw_index = read_index; | ||
| 1148 | } | ||
| 1149 | |||
| 1150 | if (ar->hw_params.rri_on_ddr) | ||
| 1151 | read_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr); | ||
| 1152 | else | ||
| 1153 | read_index = src_ring->hw_index; | ||
| 1154 | |||
| 1155 | if (read_index == sw_index) | ||
| 1156 | return -EIO; | ||
| 1157 | |||
| 1158 | if (per_transfer_contextp) | ||
| 1159 | *per_transfer_contextp = | ||
| 1160 | src_ring->per_transfer_context[sw_index]; | ||
| 1161 | |||
| 1162 | /* sanity */ | ||
| 1163 | src_ring->per_transfer_context[sw_index] = NULL; | ||
| 1164 | desc = CE_SRC_RING_TO_DESC_64(src_ring->base_addr_owner_space, | ||
| 1165 | sw_index); | ||
| 1166 | desc->nbytes = 0; | ||
| 1167 | |||
| 1168 | /* Update sw_index */ | ||
| 1169 | sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index); | ||
| 1170 | src_ring->sw_index = sw_index; | ||
| 1171 | |||
| 1172 | return 0; | ||
| 1173 | } | ||
| 1174 | |||
| 1175 | int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, | ||
| 1176 | void **per_transfer_contextp) | ||
| 1177 | { | ||
| 1178 | return ce_state->ops->ce_completed_send_next_nolock(ce_state, | ||
| 1179 | per_transfer_contextp); | ||
| 1180 | } | ||
| 1121 | EXPORT_SYMBOL(ath10k_ce_completed_send_next_nolock); | 1181 | EXPORT_SYMBOL(ath10k_ce_completed_send_next_nolock); |
| 1122 | 1182 | ||
| 1123 | static void ath10k_ce_extract_desc_data(struct ath10k *ar, | 1183 | static void ath10k_ce_extract_desc_data(struct ath10k *ar, |
| @@ -1839,6 +1899,7 @@ static const struct ath10k_ce_ops ce_ops = { | |||
| 1839 | .ce_send_nolock = _ath10k_ce_send_nolock, | 1899 | .ce_send_nolock = _ath10k_ce_send_nolock, |
| 1840 | .ce_set_src_ring_base_addr_hi = NULL, | 1900 | .ce_set_src_ring_base_addr_hi = NULL, |
| 1841 | .ce_set_dest_ring_base_addr_hi = NULL, | 1901 | .ce_set_dest_ring_base_addr_hi = NULL, |
| 1902 | .ce_completed_send_next_nolock = _ath10k_ce_completed_send_next_nolock, | ||
| 1842 | }; | 1903 | }; |
| 1843 | 1904 | ||
| 1844 | static const struct ath10k_ce_ops ce_64_ops = { | 1905 | static const struct ath10k_ce_ops ce_64_ops = { |
| @@ -1853,6 +1914,7 @@ static const struct ath10k_ce_ops ce_64_ops = { | |||
| 1853 | .ce_send_nolock = _ath10k_ce_send_nolock_64, | 1914 | .ce_send_nolock = _ath10k_ce_send_nolock_64, |
| 1854 | .ce_set_src_ring_base_addr_hi = ath10k_ce_set_src_ring_base_addr_hi, | 1915 | .ce_set_src_ring_base_addr_hi = ath10k_ce_set_src_ring_base_addr_hi, |
| 1855 | .ce_set_dest_ring_base_addr_hi = ath10k_ce_set_dest_ring_base_addr_hi, | 1916 | .ce_set_dest_ring_base_addr_hi = ath10k_ce_set_dest_ring_base_addr_hi, |
| 1917 | .ce_completed_send_next_nolock = _ath10k_ce_completed_send_next_nolock_64, | ||
| 1856 | }; | 1918 | }; |
| 1857 | 1919 | ||
| 1858 | static void ath10k_ce_set_ops(struct ath10k *ar, | 1920 | static void ath10k_ce_set_ops(struct ath10k *ar, |
diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index 692b3a8957a9..a7478c240f78 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h | |||
| @@ -329,6 +329,8 @@ struct ath10k_ce_ops { | |||
| 329 | void (*ce_set_dest_ring_base_addr_hi)(struct ath10k *ar, | 329 | void (*ce_set_dest_ring_base_addr_hi)(struct ath10k *ar, |
| 330 | u32 ce_ctrl_addr, | 330 | u32 ce_ctrl_addr, |
| 331 | u64 addr); | 331 | u64 addr); |
| 332 | int (*ce_completed_send_next_nolock)(struct ath10k_ce_pipe *ce_state, | ||
| 333 | void **per_transfer_contextp); | ||
| 332 | }; | 334 | }; |
| 333 | 335 | ||
| 334 | static inline u32 ath10k_ce_base_address(struct ath10k *ar, unsigned int ce_id) | 336 | static inline u32 ath10k_ce_base_address(struct ath10k *ar, unsigned int ce_id) |
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index ac2cf3f1c7b4..835b8de92d55 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c | |||
| @@ -549,10 +549,10 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { | |||
| 549 | .sw_decrypt_mcast_mgmt = true, | 549 | .sw_decrypt_mcast_mgmt = true, |
| 550 | .hw_ops = &wcn3990_ops, | 550 | .hw_ops = &wcn3990_ops, |
| 551 | .decap_align_bytes = 1, | 551 | .decap_align_bytes = 1, |
| 552 | .num_peers = TARGET_HL_10_TLV_NUM_PEERS, | 552 | .num_peers = TARGET_HL_TLV_NUM_PEERS, |
| 553 | .n_cipher_suites = 11, | 553 | .n_cipher_suites = 11, |
| 554 | .ast_skid_limit = TARGET_HL_10_TLV_AST_SKID_LIMIT, | 554 | .ast_skid_limit = TARGET_HL_TLV_AST_SKID_LIMIT, |
| 555 | .num_wds_entries = TARGET_HL_10_TLV_NUM_WDS_ENTRIES, | 555 | .num_wds_entries = TARGET_HL_TLV_NUM_WDS_ENTRIES, |
| 556 | .target_64bit = true, | 556 | .target_64bit = true, |
| 557 | .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL_DUAL_MAC, | 557 | .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL_DUAL_MAC, |
| 558 | .per_ce_irq = true, | 558 | .per_ce_irq = true, |
| @@ -637,11 +637,24 @@ static void ath10k_init_sdio(struct ath10k *ar) | |||
| 637 | ath10k_bmi_write32(ar, hi_mbox_isr_yield_limit, 99); | 637 | ath10k_bmi_write32(ar, hi_mbox_isr_yield_limit, 99); |
| 638 | ath10k_bmi_read32(ar, hi_acs_flags, ¶m); | 638 | ath10k_bmi_read32(ar, hi_acs_flags, ¶m); |
| 639 | 639 | ||
| 640 | param |= (HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_SET | | 640 | /* Data transfer is not initiated, when reduced Tx completion |
| 641 | HI_ACS_FLAGS_SDIO_REDUCE_TX_COMPL_SET | | 641 | * is used for SDIO. disable it until fixed |
| 642 | HI_ACS_FLAGS_ALT_DATA_CREDIT_SIZE); | 642 | */ |
| 643 | param &= ~HI_ACS_FLAGS_SDIO_REDUCE_TX_COMPL_SET; | ||
| 643 | 644 | ||
| 645 | /* Alternate credit size of 1544 as used by SDIO firmware is | ||
| 646 | * not big enough for mac80211 / native wifi frames. disable it | ||
| 647 | */ | ||
| 648 | param &= ~HI_ACS_FLAGS_ALT_DATA_CREDIT_SIZE; | ||
| 649 | param |= HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_SET; | ||
| 644 | ath10k_bmi_write32(ar, hi_acs_flags, param); | 650 | ath10k_bmi_write32(ar, hi_acs_flags, param); |
| 651 | |||
| 652 | /* Explicitly set fwlog prints to zero as target may turn it on | ||
| 653 | * based on scratch registers. | ||
| 654 | */ | ||
| 655 | ath10k_bmi_read32(ar, hi_option_flag, ¶m); | ||
| 656 | param |= HI_OPTION_DISABLE_DBGLOG; | ||
| 657 | ath10k_bmi_write32(ar, hi_option_flag, param); | ||
| 645 | } | 658 | } |
| 646 | 659 | ||
| 647 | static int ath10k_init_configure_target(struct ath10k *ar) | 660 | static int ath10k_init_configure_target(struct ath10k *ar) |
| @@ -2304,8 +2317,8 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) | |||
| 2304 | else | 2317 | else |
| 2305 | ar->htt.max_num_pending_tx = TARGET_TLV_NUM_MSDU_DESC; | 2318 | ar->htt.max_num_pending_tx = TARGET_TLV_NUM_MSDU_DESC; |
| 2306 | ar->wow.max_num_patterns = TARGET_TLV_NUM_WOW_PATTERNS; | 2319 | ar->wow.max_num_patterns = TARGET_TLV_NUM_WOW_PATTERNS; |
| 2307 | ar->fw_stats_req_mask = WMI_STAT_PDEV | WMI_STAT_VDEV | | 2320 | ar->fw_stats_req_mask = WMI_TLV_STAT_PDEV | WMI_TLV_STAT_VDEV | |
| 2308 | WMI_STAT_PEER; | 2321 | WMI_TLV_STAT_PEER | WMI_TLV_STAT_PEER_EXTD; |
| 2309 | ar->max_spatial_stream = WMI_MAX_SPATIAL_STREAM; | 2322 | ar->max_spatial_stream = WMI_MAX_SPATIAL_STREAM; |
| 2310 | ar->wmi.mgmt_max_num_pending_tx = TARGET_TLV_MGMT_NUM_MSDU_DESC; | 2323 | ar->wmi.mgmt_max_num_pending_tx = TARGET_TLV_MGMT_NUM_MSDU_DESC; |
| 2311 | break; | 2324 | break; |
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 27ec5557de88..e08a17b01e03 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h | |||
| @@ -189,7 +189,7 @@ struct ath10k_fw_stats_peer { | |||
| 189 | u32 peer_rssi; | 189 | u32 peer_rssi; |
| 190 | u32 peer_tx_rate; | 190 | u32 peer_tx_rate; |
| 191 | u32 peer_rx_rate; /* 10x only */ | 191 | u32 peer_rx_rate; /* 10x only */ |
| 192 | u32 rx_duration; | 192 | u64 rx_duration; |
| 193 | }; | 193 | }; |
| 194 | 194 | ||
| 195 | struct ath10k_fw_extd_stats_peer { | 195 | struct ath10k_fw_extd_stats_peer { |
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 1b8903280d42..32d967a31c65 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c | |||
| @@ -1252,6 +1252,9 @@ static int ath10k_debug_cal_data_fetch(struct ath10k *ar) | |||
| 1252 | if (WARN_ON(ar->hw_params.cal_data_len > ATH10K_DEBUG_CAL_DATA_LEN)) | 1252 | if (WARN_ON(ar->hw_params.cal_data_len > ATH10K_DEBUG_CAL_DATA_LEN)) |
| 1253 | return -EINVAL; | 1253 | return -EINVAL; |
| 1254 | 1254 | ||
| 1255 | if (ar->hw_params.cal_data_len == 0) | ||
| 1256 | return -EOPNOTSUPP; | ||
| 1257 | |||
| 1255 | hi_addr = host_interest_item_address(HI_ITEM(hi_board_data)); | 1258 | hi_addr = host_interest_item_address(HI_ITEM(hi_board_data)); |
| 1256 | 1259 | ||
| 1257 | ret = ath10k_hif_diag_read(ar, hi_addr, &addr, sizeof(addr)); | 1260 | ret = ath10k_hif_diag_read(ar, hi_addr, &addr, sizeof(addr)); |
diff --git a/drivers/net/wireless/ath/ath10k/debugfs_sta.c b/drivers/net/wireless/ath/ath10k/debugfs_sta.c index 8331d8b09987..c704ae371c4d 100644 --- a/drivers/net/wireless/ath/ath10k/debugfs_sta.c +++ b/drivers/net/wireless/ath/ath10k/debugfs_sta.c | |||
| @@ -685,11 +685,12 @@ static ssize_t ath10k_dbg_sta_dump_tx_stats(struct file *file, | |||
| 685 | " %llu ", stats->ht[j][i]); | 685 | " %llu ", stats->ht[j][i]); |
| 686 | len += scnprintf(buf + len, size - len, "\n"); | 686 | len += scnprintf(buf + len, size - len, "\n"); |
| 687 | len += scnprintf(buf + len, size - len, | 687 | len += scnprintf(buf + len, size - len, |
| 688 | " BW %s (20,40,80,160 MHz)\n", str[j]); | 688 | " BW %s (20,5,10,40,80,160 MHz)\n", str[j]); |
| 689 | len += scnprintf(buf + len, size - len, | 689 | len += scnprintf(buf + len, size - len, |
| 690 | " %llu %llu %llu %llu\n", | 690 | " %llu %llu %llu %llu %llu %llu\n", |
| 691 | stats->bw[j][0], stats->bw[j][1], | 691 | stats->bw[j][0], stats->bw[j][1], |
| 692 | stats->bw[j][2], stats->bw[j][3]); | 692 | stats->bw[j][2], stats->bw[j][3], |
| 693 | stats->bw[j][4], stats->bw[j][5]); | ||
| 693 | len += scnprintf(buf + len, size - len, | 694 | len += scnprintf(buf + len, size - len, |
| 694 | " NSS %s (1x1,2x2,3x3,4x4)\n", str[j]); | 695 | " NSS %s (1x1,2x2,3x3,4x4)\n", str[j]); |
| 695 | len += scnprintf(buf + len, size - len, | 696 | len += scnprintf(buf + len, size - len, |
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index fef716aa8f3a..4cee5492abc8 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h | |||
| @@ -578,6 +578,10 @@ struct htt_mgmt_tx_completion { | |||
| 578 | #define HTT_TX_CMPL_FLAG_PA_PRESENT BIT(2) | 578 | #define HTT_TX_CMPL_FLAG_PA_PRESENT BIT(2) |
| 579 | #define HTT_TX_CMPL_FLAG_PPDU_DURATION_PRESENT BIT(3) | 579 | #define HTT_TX_CMPL_FLAG_PPDU_DURATION_PRESENT BIT(3) |
| 580 | 580 | ||
| 581 | #define HTT_TX_DATA_RSSI_ENABLE_WCN3990 BIT(3) | ||
| 582 | #define HTT_TX_DATA_APPEND_RETRIES BIT(0) | ||
| 583 | #define HTT_TX_DATA_APPEND_TIMESTAMP BIT(1) | ||
| 584 | |||
| 581 | struct htt_rx_indication_hdr { | 585 | struct htt_rx_indication_hdr { |
| 582 | u8 info0; /* %HTT_RX_INDICATION_INFO0_ */ | 586 | u8 info0; /* %HTT_RX_INDICATION_INFO0_ */ |
| 583 | __le16 peer_id; | 587 | __le16 peer_id; |
| @@ -852,6 +856,88 @@ enum htt_data_tx_flags { | |||
| 852 | 856 | ||
| 853 | #define HTT_TX_COMPL_INV_MSDU_ID 0xFFFF | 857 | #define HTT_TX_COMPL_INV_MSDU_ID 0xFFFF |
| 854 | 858 | ||
| 859 | struct htt_append_retries { | ||
| 860 | __le16 msdu_id; | ||
| 861 | u8 tx_retries; | ||
| 862 | u8 flag; | ||
| 863 | } __packed; | ||
| 864 | |||
| 865 | struct htt_data_tx_completion_ext { | ||
| 866 | struct htt_append_retries a_retries; | ||
| 867 | __le32 t_stamp; | ||
| 868 | __le16 msdus_rssi[0]; | ||
| 869 | } __packed; | ||
| 870 | |||
| 871 | /** | ||
| 872 | * @brief target -> host TX completion indication message definition | ||
| 873 | * | ||
| 874 | * @details | ||
| 875 | * The following diagram shows the format of the TX completion indication sent | ||
| 876 | * from the target to the host | ||
| 877 | * | ||
| 878 | * |31 28|27|26|25|24|23 16| 15 |14 11|10 8|7 0| | ||
| 879 | * |-------------------------------------------------------------| | ||
| 880 | * header: |rsvd |A2|TP|A1|A0| num | t_i| tid |status| msg_type | | ||
| 881 | * |-------------------------------------------------------------| | ||
| 882 | * payload: | MSDU1 ID | MSDU0 ID | | ||
| 883 | * |-------------------------------------------------------------| | ||
| 884 | * : MSDU3 ID : MSDU2 ID : | ||
| 885 | * |-------------------------------------------------------------| | ||
| 886 | * | struct htt_tx_compl_ind_append_retries | | ||
| 887 | * |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -| | ||
| 888 | * | struct htt_tx_compl_ind_append_tx_tstamp | | ||
| 889 | * |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -| | ||
| 890 | * | MSDU1 ACK RSSI | MSDU0 ACK RSSI | | ||
| 891 | * |-------------------------------------------------------------| | ||
| 892 | * : MSDU3 ACK RSSI : MSDU2 ACK RSSI : | ||
| 893 | * |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -| | ||
| 894 | * -msg_type | ||
| 895 | * Bits 7:0 | ||
| 896 | * Purpose: identifies this as HTT TX completion indication | ||
| 897 | * -status | ||
| 898 | * Bits 10:8 | ||
| 899 | * Purpose: the TX completion status of payload fragmentations descriptors | ||
| 900 | * Value: could be HTT_TX_COMPL_IND_STAT_OK or HTT_TX_COMPL_IND_STAT_DISCARD | ||
| 901 | * -tid | ||
| 902 | * Bits 14:11 | ||
| 903 | * Purpose: the tid associated with those fragmentation descriptors. It is | ||
| 904 | * valid or not, depending on the tid_invalid bit. | ||
| 905 | * Value: 0 to 15 | ||
| 906 | * -tid_invalid | ||
| 907 | * Bits 15:15 | ||
| 908 | * Purpose: this bit indicates whether the tid field is valid or not | ||
| 909 | * Value: 0 indicates valid, 1 indicates invalid | ||
| 910 | * -num | ||
| 911 | * Bits 23:16 | ||
| 912 | * Purpose: the number of payload in this indication | ||
| 913 | * Value: 1 to 255 | ||
| 914 | * -A0 = append | ||
| 915 | * Bits 24:24 | ||
| 916 | * Purpose: append the struct htt_tx_compl_ind_append_retries which contains | ||
| 917 | * the number of tx retries for one MSDU at the end of this message | ||
| 918 | * Value: 0 indicates no appending, 1 indicates appending | ||
| 919 | * -A1 = append1 | ||
| 920 | * Bits 25:25 | ||
| 921 | * Purpose: Append the struct htt_tx_compl_ind_append_tx_tstamp which | ||
| 922 | * contains the timestamp info for each TX msdu id in payload. | ||
| 923 | * Value: 0 indicates no appending, 1 indicates appending | ||
| 924 | * -TP = MSDU tx power presence | ||
| 925 | * Bits 26:26 | ||
| 926 | * Purpose: Indicate whether the TX_COMPL_IND includes a tx power report | ||
| 927 | * for each MSDU referenced by the TX_COMPL_IND message. | ||
| 928 | * The order of the per-MSDU tx power reports matches the order | ||
| 929 | * of the MSDU IDs. | ||
| 930 | * Value: 0 indicates not appending, 1 indicates appending | ||
| 931 | * -A2 = append2 | ||
| 932 | * Bits 27:27 | ||
| 933 | * Purpose: Indicate whether data ACK RSSI is appended for each MSDU in | ||
| 934 | * TX_COMP_IND message. The order of the per-MSDU ACK RSSI report | ||
| 935 | * matches the order of the MSDU IDs. | ||
| 936 | * The ACK RSSI values are valid when status is COMPLETE_OK (and | ||
| 937 | * this append2 bit is set). | ||
| 938 | * Value: 0 indicates not appending, 1 indicates appending | ||
| 939 | */ | ||
| 940 | |||
| 855 | struct htt_data_tx_completion { | 941 | struct htt_data_tx_completion { |
| 856 | union { | 942 | union { |
| 857 | u8 flags; | 943 | u8 flags; |
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 4fc885617de1..a20ea270d519 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c | |||
| @@ -2119,9 +2119,15 @@ static bool ath10k_htt_rx_proc_rx_ind_hl(struct ath10k_htt *htt, | |||
| 2119 | hdr = (struct ieee80211_hdr *)skb->data; | 2119 | hdr = (struct ieee80211_hdr *)skb->data; |
| 2120 | rx_status = IEEE80211_SKB_RXCB(skb); | 2120 | rx_status = IEEE80211_SKB_RXCB(skb); |
| 2121 | rx_status->chains |= BIT(0); | 2121 | rx_status->chains |= BIT(0); |
| 2122 | rx_status->signal = ATH10K_DEFAULT_NOISE_FLOOR + | 2122 | if (rx->ppdu.combined_rssi == 0) { |
| 2123 | rx->ppdu.combined_rssi; | 2123 | /* SDIO firmware does not provide signal */ |
| 2124 | rx_status->flag &= ~RX_FLAG_NO_SIGNAL_VAL; | 2124 | rx_status->signal = 0; |
| 2125 | rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL; | ||
| 2126 | } else { | ||
| 2127 | rx_status->signal = ATH10K_DEFAULT_NOISE_FLOOR + | ||
| 2128 | rx->ppdu.combined_rssi; | ||
| 2129 | rx_status->flag &= ~RX_FLAG_NO_SIGNAL_VAL; | ||
| 2130 | } | ||
| 2125 | 2131 | ||
| 2126 | spin_lock_bh(&ar->data_lock); | 2132 | spin_lock_bh(&ar->data_lock); |
| 2127 | ch = ar->scan_channel; | 2133 | ch = ar->scan_channel; |
| @@ -2210,7 +2216,7 @@ static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar, | |||
| 2210 | __le16 msdu_id, *msdus; | 2216 | __le16 msdu_id, *msdus; |
| 2211 | bool rssi_enabled = false; | 2217 | bool rssi_enabled = false; |
| 2212 | u8 msdu_count = 0, num_airtime_records, tid; | 2218 | u8 msdu_count = 0, num_airtime_records, tid; |
| 2213 | int i; | 2219 | int i, htt_pad = 0; |
| 2214 | struct htt_data_tx_compl_ppdu_dur *ppdu_info; | 2220 | struct htt_data_tx_compl_ppdu_dur *ppdu_info; |
| 2215 | struct ath10k_peer *peer; | 2221 | struct ath10k_peer *peer; |
| 2216 | u16 ppdu_info_offset = 0, peer_id; | 2222 | u16 ppdu_info_offset = 0, peer_id; |
| @@ -2239,9 +2245,11 @@ static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar, | |||
| 2239 | 2245 | ||
| 2240 | msdu_count = resp->data_tx_completion.num_msdus; | 2246 | msdu_count = resp->data_tx_completion.num_msdus; |
| 2241 | msdus = resp->data_tx_completion.msdus; | 2247 | msdus = resp->data_tx_completion.msdus; |
| 2248 | rssi_enabled = ath10k_is_rssi_enable(&ar->hw_params, resp); | ||
| 2242 | 2249 | ||
| 2243 | if (resp->data_tx_completion.flags2 & HTT_TX_CMPL_FLAG_DATA_RSSI) | 2250 | if (rssi_enabled) |
| 2244 | rssi_enabled = true; | 2251 | htt_pad = ath10k_tx_data_rssi_get_pad_bytes(&ar->hw_params, |
| 2252 | resp); | ||
| 2245 | 2253 | ||
| 2246 | for (i = 0; i < msdu_count; i++) { | 2254 | for (i = 0; i < msdu_count; i++) { |
| 2247 | msdu_id = msdus[i]; | 2255 | msdu_id = msdus[i]; |
| @@ -2253,10 +2261,10 @@ static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar, | |||
| 2253 | * last msdu id with 0xffff | 2261 | * last msdu id with 0xffff |
| 2254 | */ | 2262 | */ |
| 2255 | if (msdu_count & 0x01) { | 2263 | if (msdu_count & 0x01) { |
| 2256 | msdu_id = msdus[msdu_count + i + 1]; | 2264 | msdu_id = msdus[msdu_count + i + 1 + htt_pad]; |
| 2257 | tx_done.ack_rssi = __le16_to_cpu(msdu_id); | 2265 | tx_done.ack_rssi = __le16_to_cpu(msdu_id); |
| 2258 | } else { | 2266 | } else { |
| 2259 | msdu_id = msdus[msdu_count + i]; | 2267 | msdu_id = msdus[msdu_count + i + htt_pad]; |
| 2260 | tx_done.ack_rssi = __le16_to_cpu(msdu_id); | 2268 | tx_done.ack_rssi = __le16_to_cpu(msdu_id); |
| 2261 | } | 2269 | } |
| 2262 | } | 2270 | } |
| @@ -2913,17 +2921,19 @@ ath10k_accumulate_per_peer_tx_stats(struct ath10k *ar, | |||
| 2913 | struct rate_info *txrate = &arsta->txrate; | 2921 | struct rate_info *txrate = &arsta->txrate; |
| 2914 | struct ath10k_htt_tx_stats *tx_stats; | 2922 | struct ath10k_htt_tx_stats *tx_stats; |
| 2915 | int idx, ht_idx, gi, mcs, bw, nss; | 2923 | int idx, ht_idx, gi, mcs, bw, nss; |
| 2924 | unsigned long flags; | ||
| 2916 | 2925 | ||
| 2917 | if (!arsta->tx_stats) | 2926 | if (!arsta->tx_stats) |
| 2918 | return; | 2927 | return; |
| 2919 | 2928 | ||
| 2920 | tx_stats = arsta->tx_stats; | 2929 | tx_stats = arsta->tx_stats; |
| 2921 | gi = (arsta->txrate.flags & RATE_INFO_FLAGS_SHORT_GI); | 2930 | flags = txrate->flags; |
| 2922 | ht_idx = txrate->mcs + txrate->nss * 8; | 2931 | gi = test_bit(ATH10K_RATE_INFO_FLAGS_SGI_BIT, &flags); |
| 2923 | mcs = txrate->mcs; | 2932 | mcs = ATH10K_HW_MCS_RATE(pstats->ratecode); |
| 2924 | bw = txrate->bw; | 2933 | bw = txrate->bw; |
| 2925 | nss = txrate->nss; | 2934 | nss = txrate->nss; |
| 2926 | idx = mcs * 8 + 8 * 10 * nss; | 2935 | ht_idx = mcs + (nss - 1) * 8; |
| 2936 | idx = mcs * 8 + 8 * 10 * (nss - 1); | ||
| 2927 | idx += bw * 2 + gi; | 2937 | idx += bw * 2 + gi; |
| 2928 | 2938 | ||
| 2929 | #define STATS_OP_FMT(name) tx_stats->stats[ATH10K_STATS_TYPE_##name] | 2939 | #define STATS_OP_FMT(name) tx_stats->stats[ATH10K_STATS_TYPE_##name] |
| @@ -2969,7 +2979,7 @@ ath10k_accumulate_per_peer_tx_stats(struct ath10k *ar, | |||
| 2969 | } | 2979 | } |
| 2970 | STATS_OP_FMT(AMPDU).bw[0][bw] += | 2980 | STATS_OP_FMT(AMPDU).bw[0][bw] += |
| 2971 | pstats->succ_bytes + pstats->retry_bytes; | 2981 | pstats->succ_bytes + pstats->retry_bytes; |
| 2972 | STATS_OP_FMT(AMPDU).nss[0][nss] += | 2982 | STATS_OP_FMT(AMPDU).nss[0][nss - 1] += |
| 2973 | pstats->succ_bytes + pstats->retry_bytes; | 2983 | pstats->succ_bytes + pstats->retry_bytes; |
| 2974 | STATS_OP_FMT(AMPDU).gi[0][gi] += | 2984 | STATS_OP_FMT(AMPDU).gi[0][gi] += |
| 2975 | pstats->succ_bytes + pstats->retry_bytes; | 2985 | pstats->succ_bytes + pstats->retry_bytes; |
| @@ -2977,7 +2987,7 @@ ath10k_accumulate_per_peer_tx_stats(struct ath10k *ar, | |||
| 2977 | pstats->succ_bytes + pstats->retry_bytes; | 2987 | pstats->succ_bytes + pstats->retry_bytes; |
| 2978 | STATS_OP_FMT(AMPDU).bw[1][bw] += | 2988 | STATS_OP_FMT(AMPDU).bw[1][bw] += |
| 2979 | pstats->succ_pkts + pstats->retry_pkts; | 2989 | pstats->succ_pkts + pstats->retry_pkts; |
| 2980 | STATS_OP_FMT(AMPDU).nss[1][nss] += | 2990 | STATS_OP_FMT(AMPDU).nss[1][nss - 1] += |
| 2981 | pstats->succ_pkts + pstats->retry_pkts; | 2991 | pstats->succ_pkts + pstats->retry_pkts; |
| 2982 | STATS_OP_FMT(AMPDU).gi[1][gi] += | 2992 | STATS_OP_FMT(AMPDU).gi[1][gi] += |
| 2983 | pstats->succ_pkts + pstats->retry_pkts; | 2993 | pstats->succ_pkts + pstats->retry_pkts; |
| @@ -2989,27 +2999,27 @@ ath10k_accumulate_per_peer_tx_stats(struct ath10k *ar, | |||
| 2989 | } | 2999 | } |
| 2990 | 3000 | ||
| 2991 | STATS_OP_FMT(SUCC).bw[0][bw] += pstats->succ_bytes; | 3001 | STATS_OP_FMT(SUCC).bw[0][bw] += pstats->succ_bytes; |
| 2992 | STATS_OP_FMT(SUCC).nss[0][nss] += pstats->succ_bytes; | 3002 | STATS_OP_FMT(SUCC).nss[0][nss - 1] += pstats->succ_bytes; |
| 2993 | STATS_OP_FMT(SUCC).gi[0][gi] += pstats->succ_bytes; | 3003 | STATS_OP_FMT(SUCC).gi[0][gi] += pstats->succ_bytes; |
| 2994 | 3004 | ||
| 2995 | STATS_OP_FMT(SUCC).bw[1][bw] += pstats->succ_pkts; | 3005 | STATS_OP_FMT(SUCC).bw[1][bw] += pstats->succ_pkts; |
| 2996 | STATS_OP_FMT(SUCC).nss[1][nss] += pstats->succ_pkts; | 3006 | STATS_OP_FMT(SUCC).nss[1][nss - 1] += pstats->succ_pkts; |
| 2997 | STATS_OP_FMT(SUCC).gi[1][gi] += pstats->succ_pkts; | 3007 | STATS_OP_FMT(SUCC).gi[1][gi] += pstats->succ_pkts; |
| 2998 | 3008 | ||
| 2999 | STATS_OP_FMT(FAIL).bw[0][bw] += pstats->failed_bytes; | 3009 | STATS_OP_FMT(FAIL).bw[0][bw] += pstats->failed_bytes; |
| 3000 | STATS_OP_FMT(FAIL).nss[0][nss] += pstats->failed_bytes; | 3010 | STATS_OP_FMT(FAIL).nss[0][nss - 1] += pstats->failed_bytes; |
| 3001 | STATS_OP_FMT(FAIL).gi[0][gi] += pstats->failed_bytes; | 3011 | STATS_OP_FMT(FAIL).gi[0][gi] += pstats->failed_bytes; |
| 3002 | 3012 | ||
| 3003 | STATS_OP_FMT(FAIL).bw[1][bw] += pstats->failed_pkts; | 3013 | STATS_OP_FMT(FAIL).bw[1][bw] += pstats->failed_pkts; |
| 3004 | STATS_OP_FMT(FAIL).nss[1][nss] += pstats->failed_pkts; | 3014 | STATS_OP_FMT(FAIL).nss[1][nss - 1] += pstats->failed_pkts; |
| 3005 | STATS_OP_FMT(FAIL).gi[1][gi] += pstats->failed_pkts; | 3015 | STATS_OP_FMT(FAIL).gi[1][gi] += pstats->failed_pkts; |
| 3006 | 3016 | ||
| 3007 | STATS_OP_FMT(RETRY).bw[0][bw] += pstats->retry_bytes; | 3017 | STATS_OP_FMT(RETRY).bw[0][bw] += pstats->retry_bytes; |
| 3008 | STATS_OP_FMT(RETRY).nss[0][nss] += pstats->retry_bytes; | 3018 | STATS_OP_FMT(RETRY).nss[0][nss - 1] += pstats->retry_bytes; |
| 3009 | STATS_OP_FMT(RETRY).gi[0][gi] += pstats->retry_bytes; | 3019 | STATS_OP_FMT(RETRY).gi[0][gi] += pstats->retry_bytes; |
| 3010 | 3020 | ||
| 3011 | STATS_OP_FMT(RETRY).bw[1][bw] += pstats->retry_pkts; | 3021 | STATS_OP_FMT(RETRY).bw[1][bw] += pstats->retry_pkts; |
| 3012 | STATS_OP_FMT(RETRY).nss[1][nss] += pstats->retry_pkts; | 3022 | STATS_OP_FMT(RETRY).nss[1][nss - 1] += pstats->retry_pkts; |
| 3013 | STATS_OP_FMT(RETRY).gi[1][gi] += pstats->retry_pkts; | 3023 | STATS_OP_FMT(RETRY).gi[1][gi] += pstats->retry_pkts; |
| 3014 | 3024 | ||
| 3015 | if (txrate->flags >= RATE_INFO_FLAGS_MCS) { | 3025 | if (txrate->flags >= RATE_INFO_FLAGS_MCS) { |
diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c index eeaee8e41b28..ad082b7d7643 100644 --- a/drivers/net/wireless/ath/ath10k/hw.c +++ b/drivers/net/wireless/ath/ath10k/hw.c | |||
| @@ -1100,6 +1100,32 @@ int ath10k_hw_diag_fast_download(struct ath10k *ar, | |||
| 1100 | return ret; | 1100 | return ret; |
| 1101 | } | 1101 | } |
| 1102 | 1102 | ||
| 1103 | static int ath10k_htt_tx_rssi_enable(struct htt_resp *resp) | ||
| 1104 | { | ||
| 1105 | return (resp->data_tx_completion.flags2 & HTT_TX_CMPL_FLAG_DATA_RSSI); | ||
| 1106 | } | ||
| 1107 | |||
| 1108 | static int ath10k_htt_tx_rssi_enable_wcn3990(struct htt_resp *resp) | ||
| 1109 | { | ||
| 1110 | return (resp->data_tx_completion.flags2 & | ||
| 1111 | HTT_TX_DATA_RSSI_ENABLE_WCN3990); | ||
| 1112 | } | ||
| 1113 | |||
| 1114 | static int ath10k_get_htt_tx_data_rssi_pad(struct htt_resp *resp) | ||
| 1115 | { | ||
| 1116 | struct htt_data_tx_completion_ext extd; | ||
| 1117 | int pad_bytes = 0; | ||
| 1118 | |||
| 1119 | if (resp->data_tx_completion.flags2 & HTT_TX_DATA_APPEND_RETRIES) | ||
| 1120 | pad_bytes += sizeof(extd.a_retries) / | ||
| 1121 | sizeof(extd.msdus_rssi[0]); | ||
| 1122 | |||
| 1123 | if (resp->data_tx_completion.flags2 & HTT_TX_DATA_APPEND_TIMESTAMP) | ||
| 1124 | pad_bytes += sizeof(extd.t_stamp) / sizeof(extd.msdus_rssi[0]); | ||
| 1125 | |||
| 1126 | return pad_bytes; | ||
| 1127 | } | ||
| 1128 | |||
| 1103 | const struct ath10k_hw_ops qca988x_ops = { | 1129 | const struct ath10k_hw_ops qca988x_ops = { |
| 1104 | .set_coverage_class = ath10k_hw_qca988x_set_coverage_class, | 1130 | .set_coverage_class = ath10k_hw_qca988x_set_coverage_class, |
| 1105 | }; | 1131 | }; |
| @@ -1124,6 +1150,10 @@ const struct ath10k_hw_ops qca99x0_ops = { | |||
| 1124 | const struct ath10k_hw_ops qca6174_ops = { | 1150 | const struct ath10k_hw_ops qca6174_ops = { |
| 1125 | .set_coverage_class = ath10k_hw_qca988x_set_coverage_class, | 1151 | .set_coverage_class = ath10k_hw_qca988x_set_coverage_class, |
| 1126 | .enable_pll_clk = ath10k_hw_qca6174_enable_pll_clock, | 1152 | .enable_pll_clk = ath10k_hw_qca6174_enable_pll_clock, |
| 1153 | .is_rssi_enable = ath10k_htt_tx_rssi_enable, | ||
| 1127 | }; | 1154 | }; |
| 1128 | 1155 | ||
| 1129 | const struct ath10k_hw_ops wcn3990_ops = {}; | 1156 | const struct ath10k_hw_ops wcn3990_ops = { |
| 1157 | .tx_data_rssi_pad_bytes = ath10k_get_htt_tx_data_rssi_pad, | ||
| 1158 | .is_rssi_enable = ath10k_htt_tx_rssi_enable_wcn3990, | ||
| 1159 | }; | ||
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index de7dc01bf51d..71314999aa24 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h | |||
| @@ -609,6 +609,8 @@ struct ath10k_hw_params { | |||
| 609 | }; | 609 | }; |
| 610 | 610 | ||
| 611 | struct htt_rx_desc; | 611 | struct htt_rx_desc; |
| 612 | struct htt_resp; | ||
| 613 | struct htt_data_tx_completion_ext; | ||
| 612 | 614 | ||
| 613 | /* Defines needed for Rx descriptor abstraction */ | 615 | /* Defines needed for Rx descriptor abstraction */ |
| 614 | struct ath10k_hw_ops { | 616 | struct ath10k_hw_ops { |
| @@ -616,6 +618,8 @@ struct ath10k_hw_ops { | |||
| 616 | void (*set_coverage_class)(struct ath10k *ar, s16 value); | 618 | void (*set_coverage_class)(struct ath10k *ar, s16 value); |
| 617 | int (*enable_pll_clk)(struct ath10k *ar); | 619 | int (*enable_pll_clk)(struct ath10k *ar); |
| 618 | bool (*rx_desc_get_msdu_limit_error)(struct htt_rx_desc *rxd); | 620 | bool (*rx_desc_get_msdu_limit_error)(struct htt_rx_desc *rxd); |
| 621 | int (*tx_data_rssi_pad_bytes)(struct htt_resp *htt); | ||
| 622 | int (*is_rssi_enable)(struct htt_resp *resp); | ||
| 619 | }; | 623 | }; |
| 620 | 624 | ||
| 621 | extern const struct ath10k_hw_ops qca988x_ops; | 625 | extern const struct ath10k_hw_ops qca988x_ops; |
| @@ -643,6 +647,24 @@ ath10k_rx_desc_msdu_limit_error(struct ath10k_hw_params *hw, | |||
| 643 | return false; | 647 | return false; |
| 644 | } | 648 | } |
| 645 | 649 | ||
| 650 | static inline int | ||
| 651 | ath10k_tx_data_rssi_get_pad_bytes(struct ath10k_hw_params *hw, | ||
| 652 | struct htt_resp *htt) | ||
| 653 | { | ||
| 654 | if (hw->hw_ops->tx_data_rssi_pad_bytes) | ||
| 655 | return hw->hw_ops->tx_data_rssi_pad_bytes(htt); | ||
| 656 | return 0; | ||
| 657 | } | ||
| 658 | |||
| 659 | static inline int | ||
| 660 | ath10k_is_rssi_enable(struct ath10k_hw_params *hw, | ||
| 661 | struct htt_resp *resp) | ||
| 662 | { | ||
| 663 | if (hw->hw_ops->is_rssi_enable) | ||
| 664 | return hw->hw_ops->is_rssi_enable(resp); | ||
| 665 | return 0; | ||
| 666 | } | ||
| 667 | |||
| 646 | /* Target specific defines for MAIN firmware */ | 668 | /* Target specific defines for MAIN firmware */ |
| 647 | #define TARGET_NUM_VDEVS 8 | 669 | #define TARGET_NUM_VDEVS 8 |
| 648 | #define TARGET_NUM_PEER_AST 2 | 670 | #define TARGET_NUM_PEER_AST 2 |
| @@ -730,9 +752,9 @@ ath10k_rx_desc_msdu_limit_error(struct ath10k_hw_params *hw, | |||
| 730 | #define TARGET_TLV_MGMT_NUM_MSDU_DESC (50) | 752 | #define TARGET_TLV_MGMT_NUM_MSDU_DESC (50) |
| 731 | 753 | ||
| 732 | /* Target specific defines for WMI-HL-1.0 firmware */ | 754 | /* Target specific defines for WMI-HL-1.0 firmware */ |
| 733 | #define TARGET_HL_10_TLV_NUM_PEERS 14 | 755 | #define TARGET_HL_TLV_NUM_PEERS 33 |
| 734 | #define TARGET_HL_10_TLV_AST_SKID_LIMIT 6 | 756 | #define TARGET_HL_TLV_AST_SKID_LIMIT 16 |
| 735 | #define TARGET_HL_10_TLV_NUM_WDS_ENTRIES 2 | 757 | #define TARGET_HL_TLV_NUM_WDS_ENTRIES 2 |
| 736 | 758 | ||
| 737 | /* Diagnostic Window */ | 759 | /* Diagnostic Window */ |
| 738 | #define CE_DIAG_PIPE 7 | 760 | #define CE_DIAG_PIPE 7 |
diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c index d62502f386f2..fae56c67766f 100644 --- a/drivers/net/wireless/ath/ath10k/sdio.c +++ b/drivers/net/wireless/ath/ath10k/sdio.c | |||
| @@ -1382,6 +1382,12 @@ static int ath10k_sdio_hif_power_up(struct ath10k *ar, | |||
| 1382 | 1382 | ||
| 1383 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "sdio power on\n"); | 1383 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "sdio power on\n"); |
| 1384 | 1384 | ||
| 1385 | ret = ath10k_sdio_config(ar); | ||
| 1386 | if (ret) { | ||
| 1387 | ath10k_err(ar, "failed to config sdio: %d\n", ret); | ||
| 1388 | return ret; | ||
| 1389 | } | ||
| 1390 | |||
| 1385 | sdio_claim_host(func); | 1391 | sdio_claim_host(func); |
| 1386 | 1392 | ||
| 1387 | ret = sdio_enable_func(func); | 1393 | ret = sdio_enable_func(func); |
| @@ -1419,11 +1425,19 @@ static void ath10k_sdio_hif_power_down(struct ath10k *ar) | |||
| 1419 | 1425 | ||
| 1420 | /* Disable the card */ | 1426 | /* Disable the card */ |
| 1421 | sdio_claim_host(ar_sdio->func); | 1427 | sdio_claim_host(ar_sdio->func); |
| 1428 | |||
| 1422 | ret = sdio_disable_func(ar_sdio->func); | 1429 | ret = sdio_disable_func(ar_sdio->func); |
| 1423 | sdio_release_host(ar_sdio->func); | 1430 | if (ret) { |
| 1431 | ath10k_warn(ar, "unable to disable sdio function: %d\n", ret); | ||
| 1432 | sdio_release_host(ar_sdio->func); | ||
| 1433 | return; | ||
| 1434 | } | ||
| 1424 | 1435 | ||
| 1436 | ret = mmc_hw_reset(ar_sdio->func->card->host); | ||
| 1425 | if (ret) | 1437 | if (ret) |
| 1426 | ath10k_warn(ar, "unable to disable sdio function: %d\n", ret); | 1438 | ath10k_warn(ar, "unable to reset sdio: %d\n", ret); |
| 1439 | |||
| 1440 | sdio_release_host(ar_sdio->func); | ||
| 1427 | 1441 | ||
| 1428 | ar_sdio->is_disabled = true; | 1442 | ar_sdio->is_disabled = true; |
| 1429 | } | 1443 | } |
| @@ -2028,12 +2042,6 @@ static int ath10k_sdio_probe(struct sdio_func *func, | |||
| 2028 | 2042 | ||
| 2029 | ath10k_sdio_set_mbox_info(ar); | 2043 | ath10k_sdio_set_mbox_info(ar); |
| 2030 | 2044 | ||
| 2031 | ret = ath10k_sdio_config(ar); | ||
| 2032 | if (ret) { | ||
| 2033 | ath10k_err(ar, "failed to config sdio: %d\n", ret); | ||
| 2034 | goto err_free_wq; | ||
| 2035 | } | ||
| 2036 | |||
| 2037 | bus_params.dev_type = ATH10K_DEV_TYPE_HL; | 2045 | bus_params.dev_type = ATH10K_DEV_TYPE_HL; |
| 2038 | /* TODO: don't know yet how to get chip_id with SDIO */ | 2046 | /* TODO: don't know yet how to get chip_id with SDIO */ |
| 2039 | bus_params.chip_id = 0; | 2047 | bus_params.chip_id = 0; |
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index fc62174a115c..582fb11f648a 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include "wmi-tlv.h" | 13 | #include "wmi-tlv.h" |
| 14 | #include "p2p.h" | 14 | #include "p2p.h" |
| 15 | #include "testmode.h" | 15 | #include "testmode.h" |
| 16 | #include <linux/bitfield.h> | ||
| 16 | 17 | ||
| 17 | /***************/ | 18 | /***************/ |
| 18 | /* TLV helpers */ | 19 | /* TLV helpers */ |
| @@ -673,6 +674,10 @@ ath10k_wmi_tlv_op_pull_mgmt_tx_compl_ev(struct ath10k *ar, struct sk_buff *skb, | |||
| 673 | arg->desc_id = ev->desc_id; | 674 | arg->desc_id = ev->desc_id; |
| 674 | arg->status = ev->status; | 675 | arg->status = ev->status; |
| 675 | arg->pdev_id = ev->pdev_id; | 676 | arg->pdev_id = ev->pdev_id; |
| 677 | arg->ppdu_id = ev->ppdu_id; | ||
| 678 | |||
| 679 | if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map)) | ||
| 680 | arg->ack_rssi = ev->ack_rssi; | ||
| 676 | 681 | ||
| 677 | kfree(tb); | 682 | kfree(tb); |
| 678 | return 0; | 683 | return 0; |
| @@ -682,8 +687,12 @@ struct wmi_tlv_tx_bundle_compl_parse { | |||
| 682 | const __le32 *num_reports; | 687 | const __le32 *num_reports; |
| 683 | const __le32 *desc_ids; | 688 | const __le32 *desc_ids; |
| 684 | const __le32 *status; | 689 | const __le32 *status; |
| 690 | const __le32 *ppdu_ids; | ||
| 691 | const __le32 *ack_rssi; | ||
| 685 | bool desc_ids_done; | 692 | bool desc_ids_done; |
| 686 | bool status_done; | 693 | bool status_done; |
| 694 | bool ppdu_ids_done; | ||
| 695 | bool ack_rssi_done; | ||
| 687 | }; | 696 | }; |
| 688 | 697 | ||
| 689 | static int | 698 | static int |
| @@ -703,6 +712,12 @@ ath10k_wmi_tlv_mgmt_tx_bundle_compl_parse(struct ath10k *ar, u16 tag, u16 len, | |||
| 703 | } else if (!bundle_tx_compl->status_done) { | 712 | } else if (!bundle_tx_compl->status_done) { |
| 704 | bundle_tx_compl->status_done = true; | 713 | bundle_tx_compl->status_done = true; |
| 705 | bundle_tx_compl->status = ptr; | 714 | bundle_tx_compl->status = ptr; |
| 715 | } else if (!bundle_tx_compl->ppdu_ids_done) { | ||
| 716 | bundle_tx_compl->ppdu_ids_done = true; | ||
| 717 | bundle_tx_compl->ppdu_ids = ptr; | ||
| 718 | } else if (!bundle_tx_compl->ack_rssi_done) { | ||
| 719 | bundle_tx_compl->ack_rssi_done = true; | ||
| 720 | bundle_tx_compl->ack_rssi = ptr; | ||
| 706 | } | 721 | } |
| 707 | break; | 722 | break; |
| 708 | default: | 723 | default: |
| @@ -733,6 +748,10 @@ static int ath10k_wmi_tlv_op_pull_mgmt_tx_bundle_compl_ev( | |||
| 733 | arg->num_reports = *bundle_tx_compl.num_reports; | 748 | arg->num_reports = *bundle_tx_compl.num_reports; |
| 734 | arg->desc_ids = bundle_tx_compl.desc_ids; | 749 | arg->desc_ids = bundle_tx_compl.desc_ids; |
| 735 | arg->status = bundle_tx_compl.status; | 750 | arg->status = bundle_tx_compl.status; |
| 751 | arg->ppdu_ids = bundle_tx_compl.ppdu_ids; | ||
| 752 | |||
| 753 | if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map)) | ||
| 754 | arg->ack_rssi = bundle_tx_compl.ack_rssi; | ||
| 736 | 755 | ||
| 737 | return 0; | 756 | return 0; |
| 738 | } | 757 | } |
| @@ -1278,6 +1297,7 @@ static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar, | |||
| 1278 | { | 1297 | { |
| 1279 | const void **tb; | 1298 | const void **tb; |
| 1280 | const struct wmi_tlv_stats_ev *ev; | 1299 | const struct wmi_tlv_stats_ev *ev; |
| 1300 | u32 num_peer_stats_extd; | ||
| 1281 | const void *data; | 1301 | const void *data; |
| 1282 | u32 num_pdev_stats; | 1302 | u32 num_pdev_stats; |
| 1283 | u32 num_vdev_stats; | 1303 | u32 num_vdev_stats; |
| @@ -1285,6 +1305,7 @@ static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar, | |||
| 1285 | u32 num_bcnflt_stats; | 1305 | u32 num_bcnflt_stats; |
| 1286 | u32 num_chan_stats; | 1306 | u32 num_chan_stats; |
| 1287 | size_t data_len; | 1307 | size_t data_len; |
| 1308 | u32 stats_id; | ||
| 1288 | int ret; | 1309 | int ret; |
| 1289 | int i; | 1310 | int i; |
| 1290 | 1311 | ||
| @@ -1309,11 +1330,13 @@ static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar, | |||
| 1309 | num_peer_stats = __le32_to_cpu(ev->num_peer_stats); | 1330 | num_peer_stats = __le32_to_cpu(ev->num_peer_stats); |
| 1310 | num_bcnflt_stats = __le32_to_cpu(ev->num_bcnflt_stats); | 1331 | num_bcnflt_stats = __le32_to_cpu(ev->num_bcnflt_stats); |
| 1311 | num_chan_stats = __le32_to_cpu(ev->num_chan_stats); | 1332 | num_chan_stats = __le32_to_cpu(ev->num_chan_stats); |
| 1333 | stats_id = __le32_to_cpu(ev->stats_id); | ||
| 1334 | num_peer_stats_extd = __le32_to_cpu(ev->num_peer_stats_extd); | ||
| 1312 | 1335 | ||
| 1313 | ath10k_dbg(ar, ATH10K_DBG_WMI, | 1336 | ath10k_dbg(ar, ATH10K_DBG_WMI, |
| 1314 | "wmi tlv stats update pdev %i vdev %i peer %i bcnflt %i chan %i\n", | 1337 | "wmi tlv stats update pdev %i vdev %i peer %i bcnflt %i chan %i peer_extd %i\n", |
| 1315 | num_pdev_stats, num_vdev_stats, num_peer_stats, | 1338 | num_pdev_stats, num_vdev_stats, num_peer_stats, |
| 1316 | num_bcnflt_stats, num_chan_stats); | 1339 | num_bcnflt_stats, num_chan_stats, num_peer_stats_extd); |
| 1317 | 1340 | ||
| 1318 | for (i = 0; i < num_pdev_stats; i++) { | 1341 | for (i = 0; i < num_pdev_stats; i++) { |
| 1319 | const struct wmi_pdev_stats *src; | 1342 | const struct wmi_pdev_stats *src; |
| @@ -1378,6 +1401,28 @@ static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar, | |||
| 1378 | 1401 | ||
| 1379 | ath10k_wmi_pull_peer_stats(&src->old, dst); | 1402 | ath10k_wmi_pull_peer_stats(&src->old, dst); |
| 1380 | dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate); | 1403 | dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate); |
| 1404 | |||
| 1405 | if (stats_id & WMI_TLV_STAT_PEER_EXTD) { | ||
| 1406 | const struct wmi_tlv_peer_stats_extd *extd; | ||
| 1407 | unsigned long rx_duration_high; | ||
| 1408 | |||
| 1409 | extd = data + sizeof(*src) * (num_peer_stats - i - 1) | ||
| 1410 | + sizeof(*extd) * i; | ||
| 1411 | |||
| 1412 | dst->rx_duration = __le32_to_cpu(extd->rx_duration); | ||
| 1413 | rx_duration_high = __le32_to_cpu | ||
| 1414 | (extd->rx_duration_high); | ||
| 1415 | |||
| 1416 | if (test_bit(WMI_TLV_PEER_RX_DURATION_HIGH_VALID_BIT, | ||
| 1417 | &rx_duration_high)) { | ||
| 1418 | rx_duration_high = | ||
| 1419 | FIELD_GET(WMI_TLV_PEER_RX_DURATION_HIGH_MASK, | ||
| 1420 | rx_duration_high); | ||
| 1421 | dst->rx_duration |= (u64)rx_duration_high << | ||
| 1422 | WMI_TLV_PEER_RX_DURATION_SHIFT; | ||
| 1423 | } | ||
| 1424 | } | ||
| 1425 | |||
| 1381 | list_add_tail(&dst->list, &stats->peers); | 1426 | list_add_tail(&dst->list, &stats->peers); |
| 1382 | } | 1427 | } |
| 1383 | 1428 | ||
| @@ -1565,21 +1610,55 @@ ath10k_wmi_tlv_op_gen_pdev_set_param(struct ath10k *ar, u32 param_id, | |||
| 1565 | cmd->param_id = __cpu_to_le32(param_id); | 1610 | cmd->param_id = __cpu_to_le32(param_id); |
| 1566 | cmd->param_value = __cpu_to_le32(param_value); | 1611 | cmd->param_value = __cpu_to_le32(param_value); |
| 1567 | 1612 | ||
| 1568 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev set param\n"); | 1613 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev set param %d value 0x%x\n", |
| 1614 | param_id, param_value); | ||
| 1569 | return skb; | 1615 | return skb; |
| 1570 | } | 1616 | } |
| 1571 | 1617 | ||
| 1618 | static void | ||
| 1619 | ath10k_wmi_tlv_put_host_mem_chunks(struct ath10k *ar, void *host_mem_chunks) | ||
| 1620 | { | ||
| 1621 | struct host_memory_chunk *chunk; | ||
| 1622 | struct wmi_tlv *tlv; | ||
| 1623 | int i; | ||
| 1624 | __le16 tlv_len, tlv_tag; | ||
| 1625 | |||
| 1626 | tlv_tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WLAN_HOST_MEMORY_CHUNK); | ||
| 1627 | tlv_len = __cpu_to_le16(sizeof(*chunk)); | ||
| 1628 | for (i = 0; i < ar->wmi.num_mem_chunks; i++) { | ||
| 1629 | tlv = host_mem_chunks; | ||
| 1630 | tlv->tag = tlv_tag; | ||
| 1631 | tlv->len = tlv_len; | ||
| 1632 | chunk = (void *)tlv->value; | ||
| 1633 | |||
| 1634 | chunk->ptr = __cpu_to_le32(ar->wmi.mem_chunks[i].paddr); | ||
| 1635 | chunk->size = __cpu_to_le32(ar->wmi.mem_chunks[i].len); | ||
| 1636 | chunk->req_id = __cpu_to_le32(ar->wmi.mem_chunks[i].req_id); | ||
| 1637 | |||
| 1638 | ath10k_dbg(ar, ATH10K_DBG_WMI, | ||
| 1639 | "wmi-tlv chunk %d len %d, addr 0x%llx, id 0x%x\n", | ||
| 1640 | i, | ||
| 1641 | ar->wmi.mem_chunks[i].len, | ||
| 1642 | (unsigned long long)ar->wmi.mem_chunks[i].paddr, | ||
| 1643 | ar->wmi.mem_chunks[i].req_id); | ||
| 1644 | |||
| 1645 | host_mem_chunks += sizeof(*tlv); | ||
| 1646 | host_mem_chunks += sizeof(*chunk); | ||
| 1647 | } | ||
| 1648 | } | ||
| 1649 | |||
| 1572 | static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar) | 1650 | static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar) |
| 1573 | { | 1651 | { |
| 1574 | struct sk_buff *skb; | 1652 | struct sk_buff *skb; |
| 1575 | struct wmi_tlv *tlv; | 1653 | struct wmi_tlv *tlv; |
| 1576 | struct wmi_tlv_init_cmd *cmd; | 1654 | struct wmi_tlv_init_cmd *cmd; |
| 1577 | struct wmi_tlv_resource_config *cfg; | 1655 | struct wmi_tlv_resource_config *cfg; |
| 1578 | struct wmi_host_mem_chunks *chunks; | 1656 | void *chunks; |
| 1579 | size_t len, chunks_len; | 1657 | size_t len, chunks_len; |
| 1580 | void *ptr; | 1658 | void *ptr; |
| 1581 | 1659 | ||
| 1582 | chunks_len = ar->wmi.num_mem_chunks * sizeof(struct host_memory_chunk); | 1660 | chunks_len = ar->wmi.num_mem_chunks * |
| 1661 | (sizeof(struct host_memory_chunk) + sizeof(*tlv)); | ||
| 1583 | len = (sizeof(*tlv) + sizeof(*cmd)) + | 1662 | len = (sizeof(*tlv) + sizeof(*cmd)) + |
| 1584 | (sizeof(*tlv) + sizeof(*cfg)) + | 1663 | (sizeof(*tlv) + sizeof(*cfg)) + |
| 1585 | (sizeof(*tlv) + chunks_len); | 1664 | (sizeof(*tlv) + chunks_len); |
| @@ -1679,7 +1758,10 @@ static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar) | |||
| 1679 | cfg->num_ocb_schedules = __cpu_to_le32(0); | 1758 | cfg->num_ocb_schedules = __cpu_to_le32(0); |
| 1680 | cfg->host_capab = __cpu_to_le32(WMI_TLV_FLAG_MGMT_BUNDLE_TX_COMPL); | 1759 | cfg->host_capab = __cpu_to_le32(WMI_TLV_FLAG_MGMT_BUNDLE_TX_COMPL); |
| 1681 | 1760 | ||
| 1682 | ath10k_wmi_put_host_mem_chunks(ar, chunks); | 1761 | if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map)) |
| 1762 | cfg->host_capab |= __cpu_to_le32(WMI_RSRC_CFG_FLAG_TX_ACK_RSSI); | ||
| 1763 | |||
| 1764 | ath10k_wmi_tlv_put_host_mem_chunks(ar, chunks); | ||
| 1683 | 1765 | ||
| 1684 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv init\n"); | 1766 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv init\n"); |
| 1685 | return skb; | 1767 | return skb; |
| @@ -2035,7 +2117,8 @@ ath10k_wmi_tlv_op_gen_vdev_set_param(struct ath10k *ar, u32 vdev_id, | |||
| 2035 | cmd->param_id = __cpu_to_le32(param_id); | 2117 | cmd->param_id = __cpu_to_le32(param_id); |
| 2036 | cmd->param_value = __cpu_to_le32(param_value); | 2118 | cmd->param_value = __cpu_to_le32(param_value); |
| 2037 | 2119 | ||
| 2038 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev set param\n"); | 2120 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev %d set param %d value 0x%x\n", |
| 2121 | vdev_id, param_id, param_value); | ||
| 2039 | return skb; | 2122 | return skb; |
| 2040 | } | 2123 | } |
| 2041 | 2124 | ||
| @@ -2351,7 +2434,9 @@ ath10k_wmi_tlv_op_gen_peer_set_param(struct ath10k *ar, u32 vdev_id, | |||
| 2351 | cmd->param_value = __cpu_to_le32(param_value); | 2434 | cmd->param_value = __cpu_to_le32(param_value); |
| 2352 | ether_addr_copy(cmd->peer_macaddr.addr, peer_addr); | 2435 | ether_addr_copy(cmd->peer_macaddr.addr, peer_addr); |
| 2353 | 2436 | ||
| 2354 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer set param\n"); | 2437 | ath10k_dbg(ar, ATH10K_DBG_WMI, |
| 2438 | "wmi tlv vdev %d peer %pM set param %d value 0x%x\n", | ||
| 2439 | vdev_id, peer_addr, param_id, param_value); | ||
| 2355 | return skb; | 2440 | return skb; |
| 2356 | } | 2441 | } |
| 2357 | 2442 | ||
| @@ -2745,7 +2830,9 @@ ath10k_wmi_tlv_op_gen_mgmt_tx_send(struct ath10k *ar, struct sk_buff *msdu, | |||
| 2745 | arvif = (void *)cb->vif->drv_priv; | 2830 | arvif = (void *)cb->vif->drv_priv; |
| 2746 | vdev_id = arvif->vdev_id; | 2831 | vdev_id = arvif->vdev_id; |
| 2747 | 2832 | ||
| 2748 | if (WARN_ON_ONCE(!ieee80211_is_mgmt(hdr->frame_control))) | 2833 | if (WARN_ON_ONCE(!ieee80211_is_mgmt(hdr->frame_control) && |
| 2834 | (!(ieee80211_is_nullfunc(hdr->frame_control) || | ||
| 2835 | ieee80211_is_qos_nullfunc(hdr->frame_control))))) | ||
| 2749 | return ERR_PTR(-EINVAL); | 2836 | return ERR_PTR(-EINVAL); |
| 2750 | 2837 | ||
| 2751 | len = sizeof(*cmd) + 2 * sizeof(*tlv); | 2838 | len = sizeof(*cmd) + 2 * sizeof(*tlv); |
| @@ -2753,10 +2840,8 @@ ath10k_wmi_tlv_op_gen_mgmt_tx_send(struct ath10k *ar, struct sk_buff *msdu, | |||
| 2753 | if ((ieee80211_is_action(hdr->frame_control) || | 2840 | if ((ieee80211_is_action(hdr->frame_control) || |
| 2754 | ieee80211_is_deauth(hdr->frame_control) || | 2841 | ieee80211_is_deauth(hdr->frame_control) || |
| 2755 | ieee80211_is_disassoc(hdr->frame_control)) && | 2842 | ieee80211_is_disassoc(hdr->frame_control)) && |
| 2756 | ieee80211_has_protected(hdr->frame_control)) { | 2843 | ieee80211_has_protected(hdr->frame_control)) |
| 2757 | len += IEEE80211_CCMP_MIC_LEN; | ||
| 2758 | buf_len += IEEE80211_CCMP_MIC_LEN; | 2844 | buf_len += IEEE80211_CCMP_MIC_LEN; |
| 2759 | } | ||
| 2760 | 2845 | ||
| 2761 | buf_len = min_t(u32, buf_len, WMI_TLV_MGMT_TX_FRAME_MAX_LEN); | 2846 | buf_len = min_t(u32, buf_len, WMI_TLV_MGMT_TX_FRAME_MAX_LEN); |
| 2762 | buf_len = round_up(buf_len, 4); | 2847 | buf_len = round_up(buf_len, 4); |
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h index af4cb0e14952..65e6aa520b06 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h | |||
| @@ -14,6 +14,8 @@ | |||
| 14 | #define WMI_TLV_VDEV_PARAM_UNSUPPORTED 0 | 14 | #define WMI_TLV_VDEV_PARAM_UNSUPPORTED 0 |
| 15 | #define WMI_TLV_MGMT_TX_FRAME_MAX_LEN 64 | 15 | #define WMI_TLV_MGMT_TX_FRAME_MAX_LEN 64 |
| 16 | 16 | ||
| 17 | #define WMI_RSRC_CFG_FLAG_TX_ACK_RSSI BIT(18) | ||
| 18 | |||
| 17 | enum wmi_tlv_grp_id { | 19 | enum wmi_tlv_grp_id { |
| 18 | WMI_TLV_GRP_START = 0x3, | 20 | WMI_TLV_GRP_START = 0x3, |
| 19 | WMI_TLV_GRP_SCAN = WMI_TLV_GRP_START, | 21 | WMI_TLV_GRP_SCAN = WMI_TLV_GRP_START, |
| @@ -1384,6 +1386,25 @@ enum wmi_tlv_service { | |||
| 1384 | WMI_TLV_SERVICE_AP_TWT = 153, | 1386 | WMI_TLV_SERVICE_AP_TWT = 153, |
| 1385 | WMI_TLV_SERVICE_GMAC_OFFLOAD_SUPPORT = 154, | 1387 | WMI_TLV_SERVICE_GMAC_OFFLOAD_SUPPORT = 154, |
| 1386 | WMI_TLV_SERVICE_SPOOF_MAC_SUPPORT = 155, | 1388 | WMI_TLV_SERVICE_SPOOF_MAC_SUPPORT = 155, |
| 1389 | WMI_TLV_SERVICE_PEER_TID_CONFIGS_SUPPORT = 156, | ||
| 1390 | WMI_TLV_SERVICE_VDEV_SWRETRY_PER_AC_CONFIG_SUPPORT = 157, | ||
| 1391 | WMI_TLV_SERVICE_DUAL_BEACON_ON_SINGLE_MAC_SCC_SUPPORT = 158, | ||
| 1392 | WMI_TLV_SERVICE_DUAL_BEACON_ON_SINGLE_MAC_MCC_SUPPORT = 159, | ||
| 1393 | WMI_TLV_SERVICE_MOTION_DET = 160, | ||
| 1394 | WMI_TLV_SERVICE_INFRA_MBSSID = 161, | ||
| 1395 | WMI_TLV_SERVICE_OBSS_SPATIAL_REUSE = 162, | ||
| 1396 | WMI_TLV_SERVICE_VDEV_DIFFERENT_BEACON_INTERVAL_SUPPORT = 163, | ||
| 1397 | WMI_TLV_SERVICE_NAN_DBS_SUPPORT = 164, | ||
| 1398 | WMI_TLV_SERVICE_NDI_DBS_SUPPORT = 165, | ||
| 1399 | WMI_TLV_SERVICE_NAN_SAP_SUPPORT = 166, | ||
| 1400 | WMI_TLV_SERVICE_NDI_SAP_SUPPORT = 167, | ||
| 1401 | WMI_TLV_SERVICE_CFR_CAPTURE_SUPPORT = 168, | ||
| 1402 | WMI_TLV_SERVICE_CFR_CAPTURE_IND_MSG_TYPE_1 = 169, | ||
| 1403 | WMI_TLV_SERVICE_ESP_SUPPORT = 170, | ||
| 1404 | WMI_TLV_SERVICE_PEER_CHWIDTH_CHANGE = 171, | ||
| 1405 | WMI_TLV_SERVICE_WLAN_HPCS_PULSE = 172, | ||
| 1406 | WMI_TLV_SERVICE_PER_VDEV_CHAINMASK_CONFIG_SUPPORT = 173, | ||
| 1407 | WMI_TLV_SERVICE_TX_DATA_MGMT_ACK_RSSI = 174, | ||
| 1387 | 1408 | ||
| 1388 | WMI_TLV_MAX_EXT_SERVICE = 256, | 1409 | WMI_TLV_MAX_EXT_SERVICE = 256, |
| 1389 | }; | 1410 | }; |
| @@ -1557,6 +1578,8 @@ wmi_tlv_svc_map_ext(const __le32 *in, unsigned long *out, size_t len) | |||
| 1557 | SVCMAP(WMI_TLV_SERVICE_THERM_THROT, | 1578 | SVCMAP(WMI_TLV_SERVICE_THERM_THROT, |
| 1558 | WMI_SERVICE_THERM_THROT, | 1579 | WMI_SERVICE_THERM_THROT, |
| 1559 | WMI_TLV_MAX_SERVICE); | 1580 | WMI_TLV_MAX_SERVICE); |
| 1581 | SVCMAP(WMI_TLV_SERVICE_TX_DATA_MGMT_ACK_RSSI, | ||
| 1582 | WMI_SERVICE_TX_DATA_ACK_RSSI, WMI_TLV_MAX_SERVICE); | ||
| 1560 | } | 1583 | } |
| 1561 | 1584 | ||
| 1562 | #undef SVCMAP | 1585 | #undef SVCMAP |
| @@ -1588,6 +1611,8 @@ struct wmi_tlv_mgmt_tx_compl_ev { | |||
| 1588 | __le32 desc_id; | 1611 | __le32 desc_id; |
| 1589 | __le32 status; | 1612 | __le32 status; |
| 1590 | __le32 pdev_id; | 1613 | __le32 pdev_id; |
| 1614 | __le32 ppdu_id; | ||
| 1615 | __le32 ack_rssi; | ||
| 1591 | }; | 1616 | }; |
| 1592 | 1617 | ||
| 1593 | #define WMI_TLV_MGMT_RX_NUM_RSSI 4 | 1618 | #define WMI_TLV_MGMT_RX_NUM_RSSI 4 |
| @@ -1864,6 +1889,22 @@ struct wmi_tlv_req_stats_cmd { | |||
| 1864 | struct wmi_mac_addr peer_macaddr; | 1889 | struct wmi_mac_addr peer_macaddr; |
| 1865 | } __packed; | 1890 | } __packed; |
| 1866 | 1891 | ||
| 1892 | #define WMI_TLV_PEER_RX_DURATION_HIGH_VALID_BIT 31 | ||
| 1893 | #define WMI_TLV_PEER_RX_DURATION_HIGH_MASK GENMASK(30, 0) | ||
| 1894 | #define WMI_TLV_PEER_RX_DURATION_SHIFT 32 | ||
| 1895 | |||
| 1896 | struct wmi_tlv_peer_stats_extd { | ||
| 1897 | struct wmi_mac_addr peer_macaddr; | ||
| 1898 | __le32 rx_duration; | ||
| 1899 | __le32 peer_tx_bytes; | ||
| 1900 | __le32 peer_rx_bytes; | ||
| 1901 | __le32 last_tx_rate_code; | ||
| 1902 | __le32 last_tx_power; | ||
| 1903 | __le32 rx_mc_bc_cnt; | ||
| 1904 | __le32 rx_duration_high; | ||
| 1905 | __le32 reserved[2]; | ||
| 1906 | } __packed; | ||
| 1907 | |||
| 1867 | struct wmi_tlv_vdev_stats { | 1908 | struct wmi_tlv_vdev_stats { |
| 1868 | __le32 vdev_id; | 1909 | __le32 vdev_id; |
| 1869 | __le32 beacon_snr; | 1910 | __le32 beacon_snr; |
| @@ -1957,6 +1998,10 @@ struct wmi_tlv_stats_ev { | |||
| 1957 | __le32 num_peer_stats; | 1998 | __le32 num_peer_stats; |
| 1958 | __le32 num_bcnflt_stats; | 1999 | __le32 num_bcnflt_stats; |
| 1959 | __le32 num_chan_stats; | 2000 | __le32 num_chan_stats; |
| 2001 | __le32 num_mib_stats; | ||
| 2002 | __le32 pdev_id; | ||
| 2003 | __le32 num_bcn_stats; | ||
| 2004 | __le32 num_peer_stats_extd; | ||
| 1960 | } __packed; | 2005 | } __packed; |
| 1961 | 2006 | ||
| 1962 | struct wmi_tlv_p2p_noa_ev { | 2007 | struct wmi_tlv_p2p_noa_ev { |
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 97e5b2eb8a91..98a90e49d666 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c | |||
| @@ -2342,8 +2342,8 @@ static bool ath10k_wmi_rx_is_decrypted(struct ath10k *ar, | |||
| 2342 | return true; | 2342 | return true; |
| 2343 | } | 2343 | } |
| 2344 | 2344 | ||
| 2345 | static int wmi_process_mgmt_tx_comp(struct ath10k *ar, u32 desc_id, | 2345 | static int |
| 2346 | u32 status) | 2346 | wmi_process_mgmt_tx_comp(struct ath10k *ar, struct mgmt_tx_compl_params *param) |
| 2347 | { | 2347 | { |
| 2348 | struct ath10k_mgmt_tx_pkt_addr *pkt_addr; | 2348 | struct ath10k_mgmt_tx_pkt_addr *pkt_addr; |
| 2349 | struct ath10k_wmi *wmi = &ar->wmi; | 2349 | struct ath10k_wmi *wmi = &ar->wmi; |
| @@ -2353,10 +2353,10 @@ static int wmi_process_mgmt_tx_comp(struct ath10k *ar, u32 desc_id, | |||
| 2353 | 2353 | ||
| 2354 | spin_lock_bh(&ar->data_lock); | 2354 | spin_lock_bh(&ar->data_lock); |
| 2355 | 2355 | ||
| 2356 | pkt_addr = idr_find(&wmi->mgmt_pending_tx, desc_id); | 2356 | pkt_addr = idr_find(&wmi->mgmt_pending_tx, param->desc_id); |
| 2357 | if (!pkt_addr) { | 2357 | if (!pkt_addr) { |
| 2358 | ath10k_warn(ar, "received mgmt tx completion for invalid msdu_id: %d\n", | 2358 | ath10k_warn(ar, "received mgmt tx completion for invalid msdu_id: %d\n", |
| 2359 | desc_id); | 2359 | param->desc_id); |
| 2360 | ret = -ENOENT; | 2360 | ret = -ENOENT; |
| 2361 | goto out; | 2361 | goto out; |
| 2362 | } | 2362 | } |
| @@ -2366,17 +2366,21 @@ static int wmi_process_mgmt_tx_comp(struct ath10k *ar, u32 desc_id, | |||
| 2366 | msdu->len, DMA_TO_DEVICE); | 2366 | msdu->len, DMA_TO_DEVICE); |
| 2367 | info = IEEE80211_SKB_CB(msdu); | 2367 | info = IEEE80211_SKB_CB(msdu); |
| 2368 | 2368 | ||
| 2369 | if (status) | 2369 | if (param->status) { |
| 2370 | info->flags &= ~IEEE80211_TX_STAT_ACK; | 2370 | info->flags &= ~IEEE80211_TX_STAT_ACK; |
| 2371 | else | 2371 | } else { |
| 2372 | info->flags |= IEEE80211_TX_STAT_ACK; | 2372 | info->flags |= IEEE80211_TX_STAT_ACK; |
| 2373 | info->status.ack_signal = ATH10K_DEFAULT_NOISE_FLOOR + | ||
| 2374 | param->ack_rssi; | ||
| 2375 | info->status.is_valid_ack_signal = true; | ||
| 2376 | } | ||
| 2373 | 2377 | ||
| 2374 | ieee80211_tx_status_irqsafe(ar->hw, msdu); | 2378 | ieee80211_tx_status_irqsafe(ar->hw, msdu); |
| 2375 | 2379 | ||
| 2376 | ret = 0; | 2380 | ret = 0; |
| 2377 | 2381 | ||
| 2378 | out: | 2382 | out: |
| 2379 | idr_remove(&wmi->mgmt_pending_tx, desc_id); | 2383 | idr_remove(&wmi->mgmt_pending_tx, param->desc_id); |
| 2380 | spin_unlock_bh(&ar->data_lock); | 2384 | spin_unlock_bh(&ar->data_lock); |
| 2381 | return ret; | 2385 | return ret; |
| 2382 | } | 2386 | } |
| @@ -2384,6 +2388,7 @@ out: | |||
| 2384 | int ath10k_wmi_event_mgmt_tx_compl(struct ath10k *ar, struct sk_buff *skb) | 2388 | int ath10k_wmi_event_mgmt_tx_compl(struct ath10k *ar, struct sk_buff *skb) |
| 2385 | { | 2389 | { |
| 2386 | struct wmi_tlv_mgmt_tx_compl_ev_arg arg; | 2390 | struct wmi_tlv_mgmt_tx_compl_ev_arg arg; |
| 2391 | struct mgmt_tx_compl_params param; | ||
| 2387 | int ret; | 2392 | int ret; |
| 2388 | 2393 | ||
| 2389 | ret = ath10k_wmi_pull_mgmt_tx_compl(ar, skb, &arg); | 2394 | ret = ath10k_wmi_pull_mgmt_tx_compl(ar, skb, &arg); |
| @@ -2392,8 +2397,14 @@ int ath10k_wmi_event_mgmt_tx_compl(struct ath10k *ar, struct sk_buff *skb) | |||
| 2392 | return ret; | 2397 | return ret; |
| 2393 | } | 2398 | } |
| 2394 | 2399 | ||
| 2395 | wmi_process_mgmt_tx_comp(ar, __le32_to_cpu(arg.desc_id), | 2400 | memset(¶m, 0, sizeof(struct mgmt_tx_compl_params)); |
| 2396 | __le32_to_cpu(arg.status)); | 2401 | param.desc_id = __le32_to_cpu(arg.desc_id); |
| 2402 | param.status = __le32_to_cpu(arg.status); | ||
| 2403 | |||
| 2404 | if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map)) | ||
| 2405 | param.ack_rssi = __le32_to_cpu(arg.ack_rssi); | ||
| 2406 | |||
| 2407 | wmi_process_mgmt_tx_comp(ar, ¶m); | ||
| 2397 | 2408 | ||
| 2398 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv evnt mgmt tx completion\n"); | 2409 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv evnt mgmt tx completion\n"); |
| 2399 | 2410 | ||
| @@ -2403,6 +2414,7 @@ int ath10k_wmi_event_mgmt_tx_compl(struct ath10k *ar, struct sk_buff *skb) | |||
| 2403 | int ath10k_wmi_event_mgmt_tx_bundle_compl(struct ath10k *ar, struct sk_buff *skb) | 2414 | int ath10k_wmi_event_mgmt_tx_bundle_compl(struct ath10k *ar, struct sk_buff *skb) |
| 2404 | { | 2415 | { |
| 2405 | struct wmi_tlv_mgmt_tx_bundle_compl_ev_arg arg; | 2416 | struct wmi_tlv_mgmt_tx_bundle_compl_ev_arg arg; |
| 2417 | struct mgmt_tx_compl_params param; | ||
| 2406 | u32 num_reports; | 2418 | u32 num_reports; |
| 2407 | int i, ret; | 2419 | int i, ret; |
| 2408 | 2420 | ||
| @@ -2414,9 +2426,15 @@ int ath10k_wmi_event_mgmt_tx_bundle_compl(struct ath10k *ar, struct sk_buff *skb | |||
| 2414 | 2426 | ||
| 2415 | num_reports = __le32_to_cpu(arg.num_reports); | 2427 | num_reports = __le32_to_cpu(arg.num_reports); |
| 2416 | 2428 | ||
| 2417 | for (i = 0; i < num_reports; i++) | 2429 | for (i = 0; i < num_reports; i++) { |
| 2418 | wmi_process_mgmt_tx_comp(ar, __le32_to_cpu(arg.desc_ids[i]), | 2430 | memset(¶m, 0, sizeof(struct mgmt_tx_compl_params)); |
| 2419 | __le32_to_cpu(arg.status[i])); | 2431 | param.desc_id = __le32_to_cpu(arg.desc_ids[i]); |
| 2432 | param.status = __le32_to_cpu(arg.desc_ids[i]); | ||
| 2433 | |||
| 2434 | if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map)) | ||
| 2435 | param.ack_rssi = __le32_to_cpu(arg.ack_rssi[i]); | ||
| 2436 | wmi_process_mgmt_tx_comp(ar, ¶m); | ||
| 2437 | } | ||
| 2420 | 2438 | ||
| 2421 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv event bundle mgmt tx completion\n"); | 2439 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv event bundle mgmt tx completion\n"); |
| 2422 | 2440 | ||
| @@ -8304,7 +8322,7 @@ ath10k_wmi_fw_peer_stats_fill(const struct ath10k_fw_stats_peer *peer, | |||
| 8304 | "Peer TX rate", peer->peer_tx_rate); | 8322 | "Peer TX rate", peer->peer_tx_rate); |
| 8305 | len += scnprintf(buf + len, buf_len - len, "%30s %u\n", | 8323 | len += scnprintf(buf + len, buf_len - len, "%30s %u\n", |
| 8306 | "Peer RX rate", peer->peer_rx_rate); | 8324 | "Peer RX rate", peer->peer_rx_rate); |
| 8307 | len += scnprintf(buf + len, buf_len - len, "%30s %u\n", | 8325 | len += scnprintf(buf + len, buf_len - len, "%30s %llu\n", |
| 8308 | "Peer RX duration", peer->rx_duration); | 8326 | "Peer RX duration", peer->rx_duration); |
| 8309 | 8327 | ||
| 8310 | len += scnprintf(buf + len, buf_len - len, "\n"); | 8328 | len += scnprintf(buf + len, buf_len - len, "\n"); |
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index d9b646f3dcc2..e1c40bb69932 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h | |||
| @@ -4534,6 +4534,13 @@ enum wmi_10_4_stats_id { | |||
| 4534 | WMI_10_4_STAT_VDEV_EXTD = BIT(4), | 4534 | WMI_10_4_STAT_VDEV_EXTD = BIT(4), |
| 4535 | }; | 4535 | }; |
| 4536 | 4536 | ||
| 4537 | enum wmi_tlv_stats_id { | ||
| 4538 | WMI_TLV_STAT_PDEV = BIT(0), | ||
| 4539 | WMI_TLV_STAT_VDEV = BIT(1), | ||
| 4540 | WMI_TLV_STAT_PEER = BIT(2), | ||
| 4541 | WMI_TLV_STAT_PEER_EXTD = BIT(10), | ||
| 4542 | }; | ||
| 4543 | |||
| 4537 | struct wlan_inst_rssi_args { | 4544 | struct wlan_inst_rssi_args { |
| 4538 | __le16 cfg_retry_count; | 4545 | __le16 cfg_retry_count; |
| 4539 | __le16 retry_count; | 4546 | __le16 retry_count; |
| @@ -5045,12 +5052,13 @@ enum wmi_rate_preamble { | |||
| 5045 | #define ATH10K_FW_SKIPPED_RATE_CTRL(flags) (((flags) >> 6) & 0x1) | 5052 | #define ATH10K_FW_SKIPPED_RATE_CTRL(flags) (((flags) >> 6) & 0x1) |
| 5046 | 5053 | ||
| 5047 | #define ATH10K_VHT_MCS_NUM 10 | 5054 | #define ATH10K_VHT_MCS_NUM 10 |
| 5048 | #define ATH10K_BW_NUM 4 | 5055 | #define ATH10K_BW_NUM 6 |
| 5049 | #define ATH10K_NSS_NUM 4 | 5056 | #define ATH10K_NSS_NUM 4 |
| 5050 | #define ATH10K_LEGACY_NUM 12 | 5057 | #define ATH10K_LEGACY_NUM 12 |
| 5051 | #define ATH10K_GI_NUM 2 | 5058 | #define ATH10K_GI_NUM 2 |
| 5052 | #define ATH10K_HT_MCS_NUM 32 | 5059 | #define ATH10K_HT_MCS_NUM 32 |
| 5053 | #define ATH10K_RATE_TABLE_NUM 320 | 5060 | #define ATH10K_RATE_TABLE_NUM 320 |
| 5061 | #define ATH10K_RATE_INFO_FLAGS_SGI_BIT 2 | ||
| 5054 | 5062 | ||
| 5055 | /* Value to disable fixed rate setting */ | 5063 | /* Value to disable fixed rate setting */ |
| 5056 | #define WMI_FIXED_RATE_NONE (0xff) | 5064 | #define WMI_FIXED_RATE_NONE (0xff) |
| @@ -6725,16 +6733,27 @@ struct wmi_scan_ev_arg { | |||
| 6725 | __le32 vdev_id; | 6733 | __le32 vdev_id; |
| 6726 | }; | 6734 | }; |
| 6727 | 6735 | ||
| 6736 | struct mgmt_tx_compl_params { | ||
| 6737 | u32 desc_id; | ||
| 6738 | u32 status; | ||
| 6739 | u32 ppdu_id; | ||
| 6740 | int ack_rssi; | ||
| 6741 | }; | ||
| 6742 | |||
| 6728 | struct wmi_tlv_mgmt_tx_compl_ev_arg { | 6743 | struct wmi_tlv_mgmt_tx_compl_ev_arg { |
| 6729 | __le32 desc_id; | 6744 | __le32 desc_id; |
| 6730 | __le32 status; | 6745 | __le32 status; |
| 6731 | __le32 pdev_id; | 6746 | __le32 pdev_id; |
| 6747 | __le32 ppdu_id; | ||
| 6748 | __le32 ack_rssi; | ||
| 6732 | }; | 6749 | }; |
| 6733 | 6750 | ||
| 6734 | struct wmi_tlv_mgmt_tx_bundle_compl_ev_arg { | 6751 | struct wmi_tlv_mgmt_tx_bundle_compl_ev_arg { |
| 6735 | __le32 num_reports; | 6752 | __le32 num_reports; |
| 6736 | const __le32 *desc_ids; | 6753 | const __le32 *desc_ids; |
| 6737 | const __le32 *status; | 6754 | const __le32 *status; |
| 6755 | const __le32 *ppdu_ids; | ||
| 6756 | const __le32 *ack_rssi; | ||
| 6738 | }; | 6757 | }; |
| 6739 | 6758 | ||
| 6740 | struct wmi_mgmt_rx_ev_arg { | 6759 | struct wmi_mgmt_rx_ev_arg { |
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 0dfea5d6e949..26ea51a72156 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
| @@ -148,7 +148,7 @@ static ssize_t read_file_ani(struct file *file, char __user *user_buf, | |||
| 148 | { "OFDM LEVEL", ah->ani.ofdmNoiseImmunityLevel }, | 148 | { "OFDM LEVEL", ah->ani.ofdmNoiseImmunityLevel }, |
| 149 | { "CCK LEVEL", ah->ani.cckNoiseImmunityLevel }, | 149 | { "CCK LEVEL", ah->ani.cckNoiseImmunityLevel }, |
| 150 | { "SPUR UP", ah->stats.ast_ani_spurup }, | 150 | { "SPUR UP", ah->stats.ast_ani_spurup }, |
| 151 | { "SPUR DOWN", ah->stats.ast_ani_spurup }, | 151 | { "SPUR DOWN", ah->stats.ast_ani_spurdown }, |
| 152 | { "OFDM WS-DET ON", ah->stats.ast_ani_ofdmon }, | 152 | { "OFDM WS-DET ON", ah->stats.ast_ani_ofdmon }, |
| 153 | { "OFDM WS-DET OFF", ah->stats.ast_ani_ofdmoff }, | 153 | { "OFDM WS-DET OFF", ah->stats.ast_ani_ofdmoff }, |
| 154 | { "MRC-CCK ON", ah->stats.ast_ani_ccklow }, | 154 | { "MRC-CCK ON", ah->stats.ast_ani_ccklow }, |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 285a62d3019d..4e97f7f3b2a3 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
| @@ -1006,9 +1006,6 @@ static void ath_rx_count_airtime(struct ath_softc *sc, | |||
| 1006 | struct ath_rx_status *rs, | 1006 | struct ath_rx_status *rs, |
| 1007 | struct sk_buff *skb) | 1007 | struct sk_buff *skb) |
| 1008 | { | 1008 | { |
| 1009 | struct ath_node *an; | ||
| 1010 | struct ath_acq *acq; | ||
| 1011 | struct ath_vif *avp; | ||
| 1012 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 1009 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
| 1013 | struct ath_hw *ah = sc->sc_ah; | 1010 | struct ath_hw *ah = sc->sc_ah; |
| 1014 | struct ath_common *common = ath9k_hw_common(ah); | 1011 | struct ath_common *common = ath9k_hw_common(ah); |
| @@ -1019,7 +1016,7 @@ static void ath_rx_count_airtime(struct ath_softc *sc, | |||
| 1019 | int phy; | 1016 | int phy; |
| 1020 | u16 len = rs->rs_datalen; | 1017 | u16 len = rs->rs_datalen; |
| 1021 | u32 airtime = 0; | 1018 | u32 airtime = 0; |
| 1022 | u8 tidno, acno; | 1019 | u8 tidno; |
| 1023 | 1020 | ||
| 1024 | if (!ieee80211_is_data(hdr->frame_control)) | 1021 | if (!ieee80211_is_data(hdr->frame_control)) |
| 1025 | return; | 1022 | return; |
| @@ -1029,11 +1026,7 @@ static void ath_rx_count_airtime(struct ath_softc *sc, | |||
| 1029 | sta = ieee80211_find_sta_by_ifaddr(sc->hw, hdr->addr2, NULL); | 1026 | sta = ieee80211_find_sta_by_ifaddr(sc->hw, hdr->addr2, NULL); |
| 1030 | if (!sta) | 1027 | if (!sta) |
| 1031 | goto exit; | 1028 | goto exit; |
| 1032 | an = (struct ath_node *) sta->drv_priv; | ||
| 1033 | avp = (struct ath_vif *) an->vif->drv_priv; | ||
| 1034 | tidno = skb->priority & IEEE80211_QOS_CTL_TID_MASK; | 1029 | tidno = skb->priority & IEEE80211_QOS_CTL_TID_MASK; |
| 1035 | acno = TID_TO_WME_AC(tidno); | ||
| 1036 | acq = &avp->chanctx->acq[acno]; | ||
| 1037 | 1030 | ||
| 1038 | rxs = IEEE80211_SKB_RXCB(skb); | 1031 | rxs = IEEE80211_SKB_RXCB(skb); |
| 1039 | 1032 | ||
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 06e0c5a6fab6..773d428ff1b0 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
| @@ -2552,6 +2552,9 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf, | |||
| 2552 | } | 2552 | } |
| 2553 | 2553 | ||
| 2554 | tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1; | 2554 | tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1; |
| 2555 | |||
| 2556 | /* we report airtime in ath_tx_count_airtime(), don't report twice */ | ||
| 2557 | tx_info->status.tx_time = 0; | ||
| 2555 | } | 2558 | } |
| 2556 | 2559 | ||
| 2557 | static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | 2560 | static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) |
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 9b2f9f543952..a1e226652b4a 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. |
| 3 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | 3 | * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * Permission to use, copy, modify, and/or distribute this software for any |
| 6 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
| @@ -395,7 +395,7 @@ static int wil_find_cid_by_idx(struct wil6210_priv *wil, u8 mid, int idx) | |||
| 395 | { | 395 | { |
| 396 | int i; | 396 | int i; |
| 397 | 397 | ||
| 398 | for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { | 398 | for (i = 0; i < max_assoc_sta; i++) { |
| 399 | if (wil->sta[i].status == wil_sta_unused) | 399 | if (wil->sta[i].status == wil_sta_unused) |
| 400 | continue; | 400 | continue; |
| 401 | if (wil->sta[i].mid != mid) | 401 | if (wil->sta[i].mid != mid) |
| @@ -1580,6 +1580,12 @@ static int _wil_cfg80211_merge_extra_ies(const u8 *ies1, u16 ies1_len, | |||
| 1580 | u8 *buf, *dpos; | 1580 | u8 *buf, *dpos; |
| 1581 | const u8 *spos; | 1581 | const u8 *spos; |
| 1582 | 1582 | ||
| 1583 | if (!ies1) | ||
| 1584 | ies1_len = 0; | ||
| 1585 | |||
| 1586 | if (!ies2) | ||
| 1587 | ies2_len = 0; | ||
| 1588 | |||
| 1583 | if (ies1_len == 0 && ies2_len == 0) { | 1589 | if (ies1_len == 0 && ies2_len == 0) { |
| 1584 | *merged_ies = NULL; | 1590 | *merged_ies = NULL; |
| 1585 | *merged_len = 0; | 1591 | *merged_len = 0; |
| @@ -1589,17 +1595,19 @@ static int _wil_cfg80211_merge_extra_ies(const u8 *ies1, u16 ies1_len, | |||
| 1589 | buf = kmalloc(ies1_len + ies2_len, GFP_KERNEL); | 1595 | buf = kmalloc(ies1_len + ies2_len, GFP_KERNEL); |
| 1590 | if (!buf) | 1596 | if (!buf) |
| 1591 | return -ENOMEM; | 1597 | return -ENOMEM; |
| 1592 | memcpy(buf, ies1, ies1_len); | 1598 | if (ies1) |
| 1599 | memcpy(buf, ies1, ies1_len); | ||
| 1593 | dpos = buf + ies1_len; | 1600 | dpos = buf + ies1_len; |
| 1594 | spos = ies2; | 1601 | spos = ies2; |
| 1595 | while (spos + 1 < ies2 + ies2_len) { | 1602 | while (spos && (spos + 1 < ies2 + ies2_len)) { |
| 1596 | /* IE tag at offset 0, length at offset 1 */ | 1603 | /* IE tag at offset 0, length at offset 1 */ |
| 1597 | u16 ielen = 2 + spos[1]; | 1604 | u16 ielen = 2 + spos[1]; |
| 1598 | 1605 | ||
| 1599 | if (spos + ielen > ies2 + ies2_len) | 1606 | if (spos + ielen > ies2 + ies2_len) |
| 1600 | break; | 1607 | break; |
| 1601 | if (spos[0] == WLAN_EID_VENDOR_SPECIFIC && | 1608 | if (spos[0] == WLAN_EID_VENDOR_SPECIFIC && |
| 1602 | !_wil_cfg80211_find_ie(ies1, ies1_len, spos, ielen)) { | 1609 | (!ies1 || !_wil_cfg80211_find_ie(ies1, ies1_len, |
| 1610 | spos, ielen))) { | ||
| 1603 | memcpy(dpos, spos, ielen); | 1611 | memcpy(dpos, spos, ielen); |
| 1604 | dpos += ielen; | 1612 | dpos += ielen; |
| 1605 | } | 1613 | } |
| @@ -3007,7 +3015,7 @@ static int wil_rf_sector_set_selected(struct wiphy *wiphy, | |||
| 3007 | wil, vif->mid, WMI_INVALID_RF_SECTOR_INDEX, | 3015 | wil, vif->mid, WMI_INVALID_RF_SECTOR_INDEX, |
| 3008 | sector_type, WIL_CID_ALL); | 3016 | sector_type, WIL_CID_ALL); |
| 3009 | if (rc == -EINVAL) { | 3017 | if (rc == -EINVAL) { |
| 3010 | for (i = 0; i < WIL6210_MAX_CID; i++) { | 3018 | for (i = 0; i < max_assoc_sta; i++) { |
| 3011 | if (wil->sta[i].mid != vif->mid) | 3019 | if (wil->sta[i].mid != vif->mid) |
| 3012 | continue; | 3020 | continue; |
| 3013 | rc = wil_rf_sector_wmi_set_selected( | 3021 | rc = wil_rf_sector_wmi_set_selected( |
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index 835c902b84c1..7ad4e5328439 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. |
| 3 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | 3 | * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * Permission to use, copy, modify, and/or distribute this software for any |
| 6 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
| @@ -162,7 +162,7 @@ static int ring_show(struct seq_file *s, void *data) | |||
| 162 | 162 | ||
| 163 | snprintf(name, sizeof(name), "tx_%2d", i); | 163 | snprintf(name, sizeof(name), "tx_%2d", i); |
| 164 | 164 | ||
| 165 | if (cid < WIL6210_MAX_CID) | 165 | if (cid < max_assoc_sta) |
| 166 | seq_printf(s, | 166 | seq_printf(s, |
| 167 | "\n%pM CID %d TID %d 1x%s BACK([%u] %u TU A%s) [%3d|%3d] idle %s\n", | 167 | "\n%pM CID %d TID %d 1x%s BACK([%u] %u TU A%s) [%3d|%3d] idle %s\n", |
| 168 | wil->sta[cid].addr, cid, tid, | 168 | wil->sta[cid].addr, cid, tid, |
| @@ -792,14 +792,14 @@ static ssize_t wil_write_back(struct file *file, const char __user *buf, | |||
| 792 | "BACK: del_rx require at least 2 params\n"); | 792 | "BACK: del_rx require at least 2 params\n"); |
| 793 | return -EINVAL; | 793 | return -EINVAL; |
| 794 | } | 794 | } |
| 795 | if (p1 < 0 || p1 >= WIL6210_MAX_CID) { | 795 | if (p1 < 0 || p1 >= max_assoc_sta) { |
| 796 | wil_err(wil, "BACK: invalid CID %d\n", p1); | 796 | wil_err(wil, "BACK: invalid CID %d\n", p1); |
| 797 | return -EINVAL; | 797 | return -EINVAL; |
| 798 | } | 798 | } |
| 799 | if (rc < 4) | 799 | if (rc < 4) |
| 800 | p3 = WLAN_REASON_QSTA_LEAVE_QBSS; | 800 | p3 = WLAN_REASON_QSTA_LEAVE_QBSS; |
| 801 | sta = &wil->sta[p1]; | 801 | sta = &wil->sta[p1]; |
| 802 | wmi_delba_rx(wil, sta->mid, mk_cidxtid(p1, p2), p3); | 802 | wmi_delba_rx(wil, sta->mid, p1, p2, p3); |
| 803 | } else { | 803 | } else { |
| 804 | wil_err(wil, "BACK: Unrecognized command \"%s\"\n", cmd); | 804 | wil_err(wil, "BACK: Unrecognized command \"%s\"\n", cmd); |
| 805 | return -EINVAL; | 805 | return -EINVAL; |
| @@ -1243,7 +1243,7 @@ static int bf_show(struct seq_file *s, void *data) | |||
| 1243 | 1243 | ||
| 1244 | memset(&reply, 0, sizeof(reply)); | 1244 | memset(&reply, 0, sizeof(reply)); |
| 1245 | 1245 | ||
| 1246 | for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { | 1246 | for (i = 0; i < max_assoc_sta; i++) { |
| 1247 | u32 status; | 1247 | u32 status; |
| 1248 | 1248 | ||
| 1249 | cmd.cid = i; | 1249 | cmd.cid = i; |
| @@ -1340,7 +1340,7 @@ static int link_show(struct seq_file *s, void *data) | |||
| 1340 | if (!sinfo) | 1340 | if (!sinfo) |
| 1341 | return -ENOMEM; | 1341 | return -ENOMEM; |
| 1342 | 1342 | ||
| 1343 | for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { | 1343 | for (i = 0; i < max_assoc_sta; i++) { |
| 1344 | struct wil_sta_info *p = &wil->sta[i]; | 1344 | struct wil_sta_info *p = &wil->sta[i]; |
| 1345 | char *status = "unknown"; | 1345 | char *status = "unknown"; |
| 1346 | struct wil6210_vif *vif; | 1346 | struct wil6210_vif *vif; |
| @@ -1542,7 +1542,7 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock) | |||
| 1542 | struct wil6210_priv *wil = s->private; | 1542 | struct wil6210_priv *wil = s->private; |
| 1543 | int i, tid, mcs; | 1543 | int i, tid, mcs; |
| 1544 | 1544 | ||
| 1545 | for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { | 1545 | for (i = 0; i < max_assoc_sta; i++) { |
| 1546 | struct wil_sta_info *p = &wil->sta[i]; | 1546 | struct wil_sta_info *p = &wil->sta[i]; |
| 1547 | char *status = "unknown"; | 1547 | char *status = "unknown"; |
| 1548 | u8 aid = 0; | 1548 | u8 aid = 0; |
| @@ -1651,7 +1651,7 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock) | |||
| 1651 | struct wil6210_priv *wil = s->private; | 1651 | struct wil6210_priv *wil = s->private; |
| 1652 | int i, bin; | 1652 | int i, bin; |
| 1653 | 1653 | ||
| 1654 | for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { | 1654 | for (i = 0; i < max_assoc_sta; i++) { |
| 1655 | struct wil_sta_info *p = &wil->sta[i]; | 1655 | struct wil_sta_info *p = &wil->sta[i]; |
| 1656 | char *status = "unknown"; | 1656 | char *status = "unknown"; |
| 1657 | u8 aid = 0; | 1657 | u8 aid = 0; |
| @@ -1740,7 +1740,7 @@ static ssize_t wil_tx_latency_write(struct file *file, const char __user *buf, | |||
| 1740 | size_t sz = sizeof(u64) * WIL_NUM_LATENCY_BINS; | 1740 | size_t sz = sizeof(u64) * WIL_NUM_LATENCY_BINS; |
| 1741 | 1741 | ||
| 1742 | wil->tx_latency_res = val; | 1742 | wil->tx_latency_res = val; |
| 1743 | for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { | 1743 | for (i = 0; i < max_assoc_sta; i++) { |
| 1744 | struct wil_sta_info *sta = &wil->sta[i]; | 1744 | struct wil_sta_info *sta = &wil->sta[i]; |
| 1745 | 1745 | ||
| 1746 | kfree(sta->tx_latency_bins); | 1746 | kfree(sta->tx_latency_bins); |
| @@ -1825,7 +1825,7 @@ static void wil_link_stats_debugfs_show_vif(struct wil6210_vif *vif, | |||
| 1825 | } | 1825 | } |
| 1826 | 1826 | ||
| 1827 | seq_printf(s, "TSF %lld\n", vif->fw_stats_tsf); | 1827 | seq_printf(s, "TSF %lld\n", vif->fw_stats_tsf); |
| 1828 | for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { | 1828 | for (i = 0; i < max_assoc_sta; i++) { |
| 1829 | if (wil->sta[i].status == wil_sta_unused) | 1829 | if (wil->sta[i].status == wil_sta_unused) |
| 1830 | continue; | 1830 | continue; |
| 1831 | if (wil->sta[i].mid != vif->mid) | 1831 | if (wil->sta[i].mid != vif->mid) |
| @@ -2386,6 +2386,7 @@ static const struct dbg_off dbg_statics[] = { | |||
| 2386 | {"led_polarity", 0644, (ulong)&led_polarity, doff_u8}, | 2386 | {"led_polarity", 0644, (ulong)&led_polarity, doff_u8}, |
| 2387 | {"status_index", 0644, (ulong)&dbg_status_msg_index, doff_u32}, | 2387 | {"status_index", 0644, (ulong)&dbg_status_msg_index, doff_u32}, |
| 2388 | {"sring_index", 0644, (ulong)&dbg_sring_index, doff_u32}, | 2388 | {"sring_index", 0644, (ulong)&dbg_sring_index, doff_u32}, |
| 2389 | {"drop_if_ring_full", 0644, (ulong)&drop_if_ring_full, doff_u8}, | ||
| 2389 | {}, | 2390 | {}, |
| 2390 | }; | 2391 | }; |
| 2391 | 2392 | ||
| @@ -2439,7 +2440,7 @@ void wil6210_debugfs_remove(struct wil6210_priv *wil) | |||
| 2439 | wil->debug = NULL; | 2440 | wil->debug = NULL; |
| 2440 | 2441 | ||
| 2441 | kfree(wil->dbg_data.data_arr); | 2442 | kfree(wil->dbg_data.data_arr); |
| 2442 | for (i = 0; i < ARRAY_SIZE(wil->sta); i++) | 2443 | for (i = 0; i < max_assoc_sta; i++) |
| 2443 | kfree(wil->sta[i].tx_latency_bins); | 2444 | kfree(wil->sta[i].tx_latency_bins); |
| 2444 | 2445 | ||
| 2445 | /* free pmc memory without sending command to fw, as it will | 2446 | /* free pmc memory without sending command to fw, as it will |
diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c index 5d287a8e1b45..3f5bd177d55f 100644 --- a/drivers/net/wireless/ath/wil6210/interrupt.c +++ b/drivers/net/wireless/ath/wil6210/interrupt.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. |
| 3 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | 3 | * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * Permission to use, copy, modify, and/or distribute this software for any |
| 6 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
| @@ -575,10 +575,14 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie) | |||
| 575 | } | 575 | } |
| 576 | 576 | ||
| 577 | if (isr & BIT_DMA_EP_MISC_ICR_HALP) { | 577 | if (isr & BIT_DMA_EP_MISC_ICR_HALP) { |
| 578 | wil_dbg_irq(wil, "irq_misc: HALP IRQ invoked\n"); | ||
| 579 | wil6210_mask_halp(wil); | ||
| 580 | isr &= ~BIT_DMA_EP_MISC_ICR_HALP; | 578 | isr &= ~BIT_DMA_EP_MISC_ICR_HALP; |
| 581 | complete(&wil->halp.comp); | 579 | if (wil->halp.handle_icr) { |
| 580 | /* no need to handle HALP ICRs until next vote */ | ||
| 581 | wil->halp.handle_icr = false; | ||
| 582 | wil_dbg_irq(wil, "irq_misc: HALP IRQ invoked\n"); | ||
| 583 | wil6210_mask_halp(wil); | ||
| 584 | complete(&wil->halp.comp); | ||
| 585 | } | ||
| 582 | } | 586 | } |
| 583 | 587 | ||
| 584 | wil->isr_misc = isr; | 588 | wil->isr_misc = isr; |
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 5b7de00affe2..277abfdf3322 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. |
| 3 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | 3 | * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * Permission to use, copy, modify, and/or distribute this software for any |
| 6 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
| @@ -219,7 +219,7 @@ static bool wil_vif_is_connected(struct wil6210_priv *wil, u8 mid) | |||
| 219 | { | 219 | { |
| 220 | int i; | 220 | int i; |
| 221 | 221 | ||
| 222 | for (i = 0; i < WIL6210_MAX_CID; i++) { | 222 | for (i = 0; i < max_assoc_sta; i++) { |
| 223 | if (wil->sta[i].mid == mid && | 223 | if (wil->sta[i].mid == mid && |
| 224 | wil->sta[i].status == wil_sta_connected) | 224 | wil->sta[i].status == wil_sta_connected) |
| 225 | return true; | 225 | return true; |
| @@ -322,7 +322,7 @@ static void _wil6210_disconnect_complete(struct wil6210_vif *vif, | |||
| 322 | wil_disconnect_cid_complete(vif, cid, reason_code); | 322 | wil_disconnect_cid_complete(vif, cid, reason_code); |
| 323 | } else { /* all */ | 323 | } else { /* all */ |
| 324 | wil_dbg_misc(wil, "Disconnect complete all\n"); | 324 | wil_dbg_misc(wil, "Disconnect complete all\n"); |
| 325 | for (cid = 0; cid < WIL6210_MAX_CID; cid++) | 325 | for (cid = 0; cid < max_assoc_sta; cid++) |
| 326 | wil_disconnect_cid_complete(vif, cid, reason_code); | 326 | wil_disconnect_cid_complete(vif, cid, reason_code); |
| 327 | } | 327 | } |
| 328 | 328 | ||
| @@ -434,7 +434,7 @@ static void _wil6210_disconnect(struct wil6210_vif *vif, const u8 *bssid, | |||
| 434 | wil_disconnect_cid(vif, cid, reason_code); | 434 | wil_disconnect_cid(vif, cid, reason_code); |
| 435 | } else { /* all */ | 435 | } else { /* all */ |
| 436 | wil_dbg_misc(wil, "Disconnect all\n"); | 436 | wil_dbg_misc(wil, "Disconnect all\n"); |
| 437 | for (cid = 0; cid < WIL6210_MAX_CID; cid++) | 437 | for (cid = 0; cid < max_assoc_sta; cid++) |
| 438 | wil_disconnect_cid(vif, cid, reason_code); | 438 | wil_disconnect_cid(vif, cid, reason_code); |
| 439 | } | 439 | } |
| 440 | 440 | ||
| @@ -1895,7 +1895,7 @@ int wil_find_cid(struct wil6210_priv *wil, u8 mid, const u8 *mac) | |||
| 1895 | int i; | 1895 | int i; |
| 1896 | int rc = -ENOENT; | 1896 | int rc = -ENOENT; |
| 1897 | 1897 | ||
| 1898 | for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { | 1898 | for (i = 0; i < max_assoc_sta; i++) { |
| 1899 | if (wil->sta[i].mid == mid && | 1899 | if (wil->sta[i].mid == mid && |
| 1900 | wil->sta[i].status != wil_sta_unused && | 1900 | wil->sta[i].status != wil_sta_unused && |
| 1901 | ether_addr_equal(wil->sta[i].addr, mac)) { | 1901 | ether_addr_equal(wil->sta[i].addr, mac)) { |
| @@ -1919,11 +1919,14 @@ void wil_halp_vote(struct wil6210_priv *wil) | |||
| 1919 | 1919 | ||
| 1920 | if (++wil->halp.ref_cnt == 1) { | 1920 | if (++wil->halp.ref_cnt == 1) { |
| 1921 | reinit_completion(&wil->halp.comp); | 1921 | reinit_completion(&wil->halp.comp); |
| 1922 | /* mark to IRQ context to handle HALP ICR */ | ||
| 1923 | wil->halp.handle_icr = true; | ||
| 1922 | wil6210_set_halp(wil); | 1924 | wil6210_set_halp(wil); |
| 1923 | rc = wait_for_completion_timeout(&wil->halp.comp, to_jiffies); | 1925 | rc = wait_for_completion_timeout(&wil->halp.comp, to_jiffies); |
| 1924 | if (!rc) { | 1926 | if (!rc) { |
| 1925 | wil_err(wil, "HALP vote timed out\n"); | 1927 | wil_err(wil, "HALP vote timed out\n"); |
| 1926 | /* Mask HALP as done in case the interrupt is raised */ | 1928 | /* Mask HALP as done in case the interrupt is raised */ |
| 1929 | wil->halp.handle_icr = false; | ||
| 1927 | wil6210_mask_halp(wil); | 1930 | wil6210_mask_halp(wil); |
| 1928 | } else { | 1931 | } else { |
| 1929 | wil_dbg_irq(wil, | 1932 | wil_dbg_irq(wil, |
diff --git a/drivers/net/wireless/ath/wil6210/rx_reorder.c b/drivers/net/wireless/ath/wil6210/rx_reorder.c index 983bd001b53b..32b14fc33a59 100644 --- a/drivers/net/wireless/ath/wil6210/rx_reorder.c +++ b/drivers/net/wireless/ath/wil6210/rx_reorder.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2014-2017 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2014-2017 Qualcomm Atheros, Inc. |
| 3 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | 3 | * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * Permission to use, copy, modify, and/or distribute this software for any |
| 6 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
| @@ -307,8 +307,8 @@ static u16 wil_agg_size(struct wil6210_priv *wil, u16 req_agg_wsize) | |||
| 307 | } | 307 | } |
| 308 | 308 | ||
| 309 | /* Block Ack - Rx side (recipient) */ | 309 | /* Block Ack - Rx side (recipient) */ |
| 310 | int wil_addba_rx_request(struct wil6210_priv *wil, u8 mid, | 310 | int wil_addba_rx_request(struct wil6210_priv *wil, u8 mid, u8 cid, u8 tid, |
| 311 | u8 cidxtid, u8 dialog_token, __le16 ba_param_set, | 311 | u8 dialog_token, __le16 ba_param_set, |
| 312 | __le16 ba_timeout, __le16 ba_seq_ctrl) | 312 | __le16 ba_timeout, __le16 ba_seq_ctrl) |
| 313 | __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) | 313 | __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) |
| 314 | { | 314 | { |
| @@ -316,7 +316,6 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) | |||
| 316 | u16 agg_timeout = le16_to_cpu(ba_timeout); | 316 | u16 agg_timeout = le16_to_cpu(ba_timeout); |
| 317 | u16 seq_ctrl = le16_to_cpu(ba_seq_ctrl); | 317 | u16 seq_ctrl = le16_to_cpu(ba_seq_ctrl); |
| 318 | struct wil_sta_info *sta; | 318 | struct wil_sta_info *sta; |
| 319 | u8 cid, tid; | ||
| 320 | u16 agg_wsize = 0; | 319 | u16 agg_wsize = 0; |
| 321 | /* bit 0: A-MSDU supported | 320 | /* bit 0: A-MSDU supported |
| 322 | * bit 1: policy (should be 0 for us) | 321 | * bit 1: policy (should be 0 for us) |
| @@ -335,10 +334,9 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) | |||
| 335 | int rc = 0; | 334 | int rc = 0; |
| 336 | 335 | ||
| 337 | might_sleep(); | 336 | might_sleep(); |
| 338 | parse_cidxtid(cidxtid, &cid, &tid); | ||
| 339 | 337 | ||
| 340 | /* sanity checks */ | 338 | /* sanity checks */ |
| 341 | if (cid >= WIL6210_MAX_CID) { | 339 | if (cid >= max_assoc_sta) { |
| 342 | wil_err(wil, "BACK: invalid CID %d\n", cid); | 340 | wil_err(wil, "BACK: invalid CID %d\n", cid); |
| 343 | rc = -EINVAL; | 341 | rc = -EINVAL; |
| 344 | goto out; | 342 | goto out; |
diff --git a/drivers/net/wireless/ath/wil6210/trace.h b/drivers/net/wireless/ath/wil6210/trace.h index 853abc3a73e4..36ebfcf9ef30 100644 --- a/drivers/net/wireless/ath/wil6210/trace.h +++ b/drivers/net/wireless/ath/wil6210/trace.h | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2013-2016 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2013-2016 Qualcomm Atheros, Inc. |
| 3 | * Copyright (c) 2019, The Linux Foundation. All rights reserved. | ||
| 3 | * | 4 | * |
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * Permission to use, copy, modify, and/or distribute this software for any |
| 5 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
| @@ -181,7 +182,7 @@ TRACE_EVENT(wil6210_rx, | |||
| 181 | __entry->seq = wil_rxdesc_seq(d); | 182 | __entry->seq = wil_rxdesc_seq(d); |
| 182 | __entry->mcs = wil_rxdesc_mcs(d); | 183 | __entry->mcs = wil_rxdesc_mcs(d); |
| 183 | ), | 184 | ), |
| 184 | TP_printk("index %d len %d mid %d cid %d tid %d mcs %d seq 0x%03x" | 185 | TP_printk("index %d len %d mid %d cid (%%8) %d tid %d mcs %d seq 0x%03x" |
| 185 | " type 0x%1x subtype 0x%1x", __entry->index, __entry->len, | 186 | " type 0x%1x subtype 0x%1x", __entry->index, __entry->len, |
| 186 | __entry->mid, __entry->cid, __entry->tid, __entry->mcs, | 187 | __entry->mid, __entry->cid, __entry->tid, __entry->mcs, |
| 187 | __entry->seq, __entry->type, __entry->subtype) | 188 | __entry->seq, __entry->type, __entry->subtype) |
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 3e1c831ab2fb..4ccfd1404458 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. |
| 3 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | 3 | * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * Permission to use, copy, modify, and/or distribute this software for any |
| 6 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
| @@ -30,11 +30,6 @@ | |||
| 30 | #include "trace.h" | 30 | #include "trace.h" |
| 31 | #include "txrx_edma.h" | 31 | #include "txrx_edma.h" |
| 32 | 32 | ||
| 33 | static bool rtap_include_phy_info; | ||
| 34 | module_param(rtap_include_phy_info, bool, 0444); | ||
| 35 | MODULE_PARM_DESC(rtap_include_phy_info, | ||
| 36 | " Include PHY info in the radiotap header, default - no"); | ||
| 37 | |||
| 38 | bool rx_align_2; | 33 | bool rx_align_2; |
| 39 | module_param(rx_align_2, bool, 0444); | 34 | module_param(rx_align_2, bool, 0444); |
| 40 | MODULE_PARM_DESC(rx_align_2, " align Rx buffers on 4*n+2, default - no"); | 35 | MODULE_PARM_DESC(rx_align_2, " align Rx buffers on 4*n+2, default - no"); |
| @@ -43,6 +38,9 @@ bool rx_large_buf; | |||
| 43 | module_param(rx_large_buf, bool, 0444); | 38 | module_param(rx_large_buf, bool, 0444); |
| 44 | MODULE_PARM_DESC(rx_large_buf, " allocate 8KB RX buffers, default - no"); | 39 | MODULE_PARM_DESC(rx_large_buf, " allocate 8KB RX buffers, default - no"); |
| 45 | 40 | ||
| 41 | /* Drop Tx packets in case Tx ring is full */ | ||
| 42 | bool drop_if_ring_full; | ||
| 43 | |||
| 46 | static inline uint wil_rx_snaplen(void) | 44 | static inline uint wil_rx_snaplen(void) |
| 47 | { | 45 | { |
| 48 | return rx_align_2 ? 6 : 0; | 46 | return rx_align_2 ? 6 : 0; |
| @@ -332,87 +330,34 @@ static void wil_rx_add_radiotap_header(struct wil6210_priv *wil, | |||
| 332 | u8 mcs_flags; | 330 | u8 mcs_flags; |
| 333 | u8 mcs_index; | 331 | u8 mcs_index; |
| 334 | } __packed; | 332 | } __packed; |
| 335 | struct wil6210_rtap_vendor { | ||
| 336 | struct wil6210_rtap rtap; | ||
| 337 | /* vendor */ | ||
| 338 | u8 vendor_oui[3] __aligned(2); | ||
| 339 | u8 vendor_ns; | ||
| 340 | __le16 vendor_skip; | ||
| 341 | u8 vendor_data[0]; | ||
| 342 | } __packed; | ||
| 343 | struct vring_rx_desc *d = wil_skb_rxdesc(skb); | 333 | struct vring_rx_desc *d = wil_skb_rxdesc(skb); |
| 344 | struct wil6210_rtap_vendor *rtap_vendor; | 334 | struct wil6210_rtap *rtap; |
| 345 | int rtap_len = sizeof(struct wil6210_rtap); | 335 | int rtap_len = sizeof(struct wil6210_rtap); |
| 346 | int phy_length = 0; /* phy info header size, bytes */ | ||
| 347 | static char phy_data[128]; | ||
| 348 | struct ieee80211_channel *ch = wil->monitor_chandef.chan; | 336 | struct ieee80211_channel *ch = wil->monitor_chandef.chan; |
| 349 | 337 | ||
| 350 | if (rtap_include_phy_info) { | ||
| 351 | rtap_len = sizeof(*rtap_vendor) + sizeof(*d); | ||
| 352 | /* calculate additional length */ | ||
| 353 | if (d->dma.status & RX_DMA_STATUS_PHY_INFO) { | ||
| 354 | /** | ||
| 355 | * PHY info starts from 8-byte boundary | ||
| 356 | * there are 8-byte lines, last line may be partially | ||
| 357 | * written (HW bug), thus FW configures for last line | ||
| 358 | * to be excessive. Driver skips this last line. | ||
| 359 | */ | ||
| 360 | int len = min_t(int, 8 + sizeof(phy_data), | ||
| 361 | wil_rxdesc_phy_length(d)); | ||
| 362 | |||
| 363 | if (len > 8) { | ||
| 364 | void *p = skb_tail_pointer(skb); | ||
| 365 | void *pa = PTR_ALIGN(p, 8); | ||
| 366 | |||
| 367 | if (skb_tailroom(skb) >= len + (pa - p)) { | ||
| 368 | phy_length = len - 8; | ||
| 369 | memcpy(phy_data, pa, phy_length); | ||
| 370 | } | ||
| 371 | } | ||
| 372 | } | ||
| 373 | rtap_len += phy_length; | ||
| 374 | } | ||
| 375 | |||
| 376 | if (skb_headroom(skb) < rtap_len && | 338 | if (skb_headroom(skb) < rtap_len && |
| 377 | pskb_expand_head(skb, rtap_len, 0, GFP_ATOMIC)) { | 339 | pskb_expand_head(skb, rtap_len, 0, GFP_ATOMIC)) { |
| 378 | wil_err(wil, "Unable to expand headroom to %d\n", rtap_len); | 340 | wil_err(wil, "Unable to expand headroom to %d\n", rtap_len); |
| 379 | return; | 341 | return; |
| 380 | } | 342 | } |
| 381 | 343 | ||
| 382 | rtap_vendor = skb_push(skb, rtap_len); | 344 | rtap = skb_push(skb, rtap_len); |
| 383 | memset(rtap_vendor, 0, rtap_len); | 345 | memset(rtap, 0, rtap_len); |
| 384 | 346 | ||
| 385 | rtap_vendor->rtap.rthdr.it_version = PKTHDR_RADIOTAP_VERSION; | 347 | rtap->rthdr.it_version = PKTHDR_RADIOTAP_VERSION; |
| 386 | rtap_vendor->rtap.rthdr.it_len = cpu_to_le16(rtap_len); | 348 | rtap->rthdr.it_len = cpu_to_le16(rtap_len); |
| 387 | rtap_vendor->rtap.rthdr.it_present = cpu_to_le32( | 349 | rtap->rthdr.it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) | |
| 388 | (1 << IEEE80211_RADIOTAP_FLAGS) | | ||
| 389 | (1 << IEEE80211_RADIOTAP_CHANNEL) | | 350 | (1 << IEEE80211_RADIOTAP_CHANNEL) | |
| 390 | (1 << IEEE80211_RADIOTAP_MCS)); | 351 | (1 << IEEE80211_RADIOTAP_MCS)); |
| 391 | if (d->dma.status & RX_DMA_STATUS_ERROR) | 352 | if (d->dma.status & RX_DMA_STATUS_ERROR) |
| 392 | rtap_vendor->rtap.flags |= IEEE80211_RADIOTAP_F_BADFCS; | 353 | rtap->flags |= IEEE80211_RADIOTAP_F_BADFCS; |
| 393 | 354 | ||
| 394 | rtap_vendor->rtap.chnl_freq = cpu_to_le16(ch ? ch->center_freq : 58320); | 355 | rtap->chnl_freq = cpu_to_le16(ch ? ch->center_freq : 58320); |
| 395 | rtap_vendor->rtap.chnl_flags = cpu_to_le16(0); | 356 | rtap->chnl_flags = cpu_to_le16(0); |
| 396 | 357 | ||
| 397 | rtap_vendor->rtap.mcs_present = IEEE80211_RADIOTAP_MCS_HAVE_MCS; | 358 | rtap->mcs_present = IEEE80211_RADIOTAP_MCS_HAVE_MCS; |
| 398 | rtap_vendor->rtap.mcs_flags = 0; | 359 | rtap->mcs_flags = 0; |
| 399 | rtap_vendor->rtap.mcs_index = wil_rxdesc_mcs(d); | 360 | rtap->mcs_index = wil_rxdesc_mcs(d); |
| 400 | |||
| 401 | if (rtap_include_phy_info) { | ||
| 402 | rtap_vendor->rtap.rthdr.it_present |= cpu_to_le32(1 << | ||
| 403 | IEEE80211_RADIOTAP_VENDOR_NAMESPACE); | ||
| 404 | /* OUI for Wilocity 04:ce:14 */ | ||
| 405 | rtap_vendor->vendor_oui[0] = 0x04; | ||
| 406 | rtap_vendor->vendor_oui[1] = 0xce; | ||
| 407 | rtap_vendor->vendor_oui[2] = 0x14; | ||
| 408 | rtap_vendor->vendor_ns = 1; | ||
| 409 | /* Rx descriptor + PHY data */ | ||
| 410 | rtap_vendor->vendor_skip = cpu_to_le16(sizeof(*d) + | ||
| 411 | phy_length); | ||
| 412 | memcpy(rtap_vendor->vendor_data, (void *)d, sizeof(*d)); | ||
| 413 | memcpy(rtap_vendor->vendor_data + sizeof(*d), phy_data, | ||
| 414 | phy_length); | ||
| 415 | } | ||
| 416 | } | 361 | } |
| 417 | 362 | ||
| 418 | static bool wil_is_rx_idle(struct wil6210_priv *wil) | 363 | static bool wil_is_rx_idle(struct wil6210_priv *wil) |
| @@ -427,6 +372,76 @@ static bool wil_is_rx_idle(struct wil6210_priv *wil) | |||
| 427 | return true; | 372 | return true; |
| 428 | } | 373 | } |
| 429 | 374 | ||
| 375 | static int wil_rx_get_cid_by_skb(struct wil6210_priv *wil, struct sk_buff *skb) | ||
| 376 | { | ||
| 377 | struct vring_rx_desc *d = wil_skb_rxdesc(skb); | ||
| 378 | int mid = wil_rxdesc_mid(d); | ||
| 379 | struct wil6210_vif *vif = wil->vifs[mid]; | ||
| 380 | /* cid from DMA descriptor is limited to 3 bits. | ||
| 381 | * In case of cid>=8, the value would be cid modulo 8 and we need to | ||
| 382 | * find real cid by locating the transmitter (ta) inside sta array | ||
| 383 | */ | ||
| 384 | int cid = wil_rxdesc_cid(d); | ||
| 385 | unsigned int snaplen = wil_rx_snaplen(); | ||
| 386 | struct ieee80211_hdr_3addr *hdr; | ||
| 387 | int i; | ||
| 388 | unsigned char *ta; | ||
| 389 | u8 ftype; | ||
| 390 | |||
| 391 | /* in monitor mode there are no connections */ | ||
| 392 | if (vif->wdev.iftype == NL80211_IFTYPE_MONITOR) | ||
| 393 | return cid; | ||
| 394 | |||
| 395 | ftype = wil_rxdesc_ftype(d) << 2; | ||
| 396 | if (likely(ftype == IEEE80211_FTYPE_DATA)) { | ||
| 397 | if (unlikely(skb->len < ETH_HLEN + snaplen)) { | ||
| 398 | wil_err_ratelimited(wil, | ||
| 399 | "Short data frame, len = %d\n", | ||
| 400 | skb->len); | ||
| 401 | return -ENOENT; | ||
| 402 | } | ||
| 403 | ta = wil_skb_get_sa(skb); | ||
| 404 | } else { | ||
| 405 | if (unlikely(skb->len < sizeof(struct ieee80211_hdr_3addr))) { | ||
| 406 | wil_err_ratelimited(wil, "Short frame, len = %d\n", | ||
| 407 | skb->len); | ||
| 408 | return -ENOENT; | ||
| 409 | } | ||
| 410 | hdr = (void *)skb->data; | ||
| 411 | ta = hdr->addr2; | ||
| 412 | } | ||
| 413 | |||
| 414 | if (max_assoc_sta <= WIL6210_RX_DESC_MAX_CID) | ||
| 415 | return cid; | ||
| 416 | |||
| 417 | /* assuming no concurrency between AP interfaces and STA interfaces. | ||
| 418 | * multista is used only in P2P_GO or AP mode. In other modes return | ||
| 419 | * cid from the rx descriptor | ||
| 420 | */ | ||
| 421 | if (vif->wdev.iftype != NL80211_IFTYPE_P2P_GO && | ||
| 422 | vif->wdev.iftype != NL80211_IFTYPE_AP) | ||
| 423 | return cid; | ||
| 424 | |||
| 425 | /* For Rx packets cid from rx descriptor is limited to 3 bits (0..7), | ||
| 426 | * to find the real cid, compare transmitter address with the stored | ||
| 427 | * stations mac address in the driver sta array | ||
| 428 | */ | ||
| 429 | for (i = cid; i < max_assoc_sta; i += WIL6210_RX_DESC_MAX_CID) { | ||
| 430 | if (wil->sta[i].status != wil_sta_unused && | ||
| 431 | ether_addr_equal(wil->sta[i].addr, ta)) { | ||
| 432 | cid = i; | ||
| 433 | break; | ||
| 434 | } | ||
| 435 | } | ||
| 436 | if (i >= max_assoc_sta) { | ||
| 437 | wil_err_ratelimited(wil, "Could not find cid for frame with transmit addr = %pM, iftype = %d, frametype = %d, len = %d\n", | ||
| 438 | ta, vif->wdev.iftype, ftype, skb->len); | ||
| 439 | cid = -ENOENT; | ||
| 440 | } | ||
| 441 | |||
| 442 | return cid; | ||
| 443 | } | ||
| 444 | |||
| 430 | /** | 445 | /** |
| 431 | * reap 1 frame from @swhead | 446 | * reap 1 frame from @swhead |
| 432 | * | 447 | * |
| @@ -452,7 +467,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, | |||
| 452 | int i; | 467 | int i; |
| 453 | struct wil_net_stats *stats; | 468 | struct wil_net_stats *stats; |
| 454 | 469 | ||
| 455 | BUILD_BUG_ON(sizeof(struct vring_rx_desc) > sizeof(skb->cb)); | 470 | BUILD_BUG_ON(sizeof(struct skb_rx_info) > sizeof(skb->cb)); |
| 456 | 471 | ||
| 457 | again: | 472 | again: |
| 458 | if (unlikely(wil_ring_is_empty(vring))) | 473 | if (unlikely(wil_ring_is_empty(vring))) |
| @@ -484,7 +499,6 @@ again: | |||
| 484 | wil_hex_dump_txrx("RxD ", DUMP_PREFIX_NONE, 32, 4, | 499 | wil_hex_dump_txrx("RxD ", DUMP_PREFIX_NONE, 32, 4, |
| 485 | (const void *)d, sizeof(*d), false); | 500 | (const void *)d, sizeof(*d), false); |
| 486 | 501 | ||
| 487 | cid = wil_rxdesc_cid(d); | ||
| 488 | mid = wil_rxdesc_mid(d); | 502 | mid = wil_rxdesc_mid(d); |
| 489 | vif = wil->vifs[mid]; | 503 | vif = wil->vifs[mid]; |
| 490 | 504 | ||
| @@ -495,11 +509,9 @@ again: | |||
| 495 | goto again; | 509 | goto again; |
| 496 | } | 510 | } |
| 497 | ndev = vif_to_ndev(vif); | 511 | ndev = vif_to_ndev(vif); |
| 498 | stats = &wil->sta[cid].stats; | ||
| 499 | |||
| 500 | if (unlikely(dmalen > sz)) { | 512 | if (unlikely(dmalen > sz)) { |
| 501 | wil_err(wil, "Rx size too large: %d bytes!\n", dmalen); | 513 | wil_err_ratelimited(wil, "Rx size too large: %d bytes!\n", |
| 502 | stats->rx_large_frame++; | 514 | dmalen); |
| 503 | kfree_skb(skb); | 515 | kfree_skb(skb); |
| 504 | goto again; | 516 | goto again; |
| 505 | } | 517 | } |
| @@ -510,6 +522,14 @@ again: | |||
| 510 | wil_hex_dump_txrx("Rx ", DUMP_PREFIX_OFFSET, 16, 1, | 522 | wil_hex_dump_txrx("Rx ", DUMP_PREFIX_OFFSET, 16, 1, |
| 511 | skb->data, skb_headlen(skb), false); | 523 | skb->data, skb_headlen(skb), false); |
| 512 | 524 | ||
| 525 | cid = wil_rx_get_cid_by_skb(wil, skb); | ||
| 526 | if (cid == -ENOENT) { | ||
| 527 | kfree_skb(skb); | ||
| 528 | goto again; | ||
| 529 | } | ||
| 530 | wil_skb_set_cid(skb, (u8)cid); | ||
| 531 | stats = &wil->sta[cid].stats; | ||
| 532 | |||
| 513 | stats->last_mcs_rx = wil_rxdesc_mcs(d); | 533 | stats->last_mcs_rx = wil_rxdesc_mcs(d); |
| 514 | if (stats->last_mcs_rx < ARRAY_SIZE(stats->rx_per_mcs)) | 534 | if (stats->last_mcs_rx < ARRAY_SIZE(stats->rx_per_mcs)) |
| 515 | stats->rx_per_mcs[stats->last_mcs_rx]++; | 535 | stats->rx_per_mcs[stats->last_mcs_rx]++; |
| @@ -556,13 +576,6 @@ again: | |||
| 556 | goto again; | 576 | goto again; |
| 557 | } | 577 | } |
| 558 | 578 | ||
| 559 | if (unlikely(skb->len < ETH_HLEN + snaplen)) { | ||
| 560 | wil_err(wil, "Short frame, len = %d\n", skb->len); | ||
| 561 | stats->rx_short_frame++; | ||
| 562 | kfree_skb(skb); | ||
| 563 | goto again; | ||
| 564 | } | ||
| 565 | |||
| 566 | /* L4 IDENT is on when HW calculated checksum, check status | 579 | /* L4 IDENT is on when HW calculated checksum, check status |
| 567 | * and in case of error drop the packet | 580 | * and in case of error drop the packet |
| 568 | * higher stack layers will handle retransmission (if required) | 581 | * higher stack layers will handle retransmission (if required) |
| @@ -659,7 +672,7 @@ int reverse_memcmp(const void *cs, const void *ct, size_t count) | |||
| 659 | static int wil_rx_crypto_check(struct wil6210_priv *wil, struct sk_buff *skb) | 672 | static int wil_rx_crypto_check(struct wil6210_priv *wil, struct sk_buff *skb) |
| 660 | { | 673 | { |
| 661 | struct vring_rx_desc *d = wil_skb_rxdesc(skb); | 674 | struct vring_rx_desc *d = wil_skb_rxdesc(skb); |
| 662 | int cid = wil_rxdesc_cid(d); | 675 | int cid = wil_skb_get_cid(skb); |
| 663 | int tid = wil_rxdesc_tid(d); | 676 | int tid = wil_rxdesc_tid(d); |
| 664 | int key_id = wil_rxdesc_key_id(d); | 677 | int key_id = wil_rxdesc_key_id(d); |
| 665 | int mc = wil_rxdesc_mcast(d); | 678 | int mc = wil_rxdesc_mcast(d); |
| @@ -707,7 +720,7 @@ static void wil_get_netif_rx_params(struct sk_buff *skb, int *cid, | |||
| 707 | { | 720 | { |
| 708 | struct vring_rx_desc *d = wil_skb_rxdesc(skb); | 721 | struct vring_rx_desc *d = wil_skb_rxdesc(skb); |
| 709 | 722 | ||
| 710 | *cid = wil_rxdesc_cid(d); /* always 0..7, no need to check */ | 723 | *cid = wil_skb_get_cid(skb); |
| 711 | *security = wil_rxdesc_security(d); | 724 | *security = wil_rxdesc_security(d); |
| 712 | } | 725 | } |
| 713 | 726 | ||
| @@ -724,11 +737,11 @@ void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) | |||
| 724 | unsigned int len = skb->len; | 737 | unsigned int len = skb->len; |
| 725 | int cid; | 738 | int cid; |
| 726 | int security; | 739 | int security; |
| 727 | struct ethhdr *eth = (void *)skb->data; | 740 | u8 *sa, *da = wil_skb_get_da(skb); |
| 728 | /* here looking for DA, not A1, thus Rxdesc's 'mcast' indication | 741 | /* here looking for DA, not A1, thus Rxdesc's 'mcast' indication |
| 729 | * is not suitable, need to look at data | 742 | * is not suitable, need to look at data |
| 730 | */ | 743 | */ |
| 731 | int mcast = is_multicast_ether_addr(eth->h_dest); | 744 | int mcast = is_multicast_ether_addr(da); |
| 732 | struct wil_net_stats *stats; | 745 | struct wil_net_stats *stats; |
| 733 | struct sk_buff *xmit_skb = NULL; | 746 | struct sk_buff *xmit_skb = NULL; |
| 734 | static const char * const gro_res_str[] = { | 747 | static const char * const gro_res_str[] = { |
| @@ -759,7 +772,8 @@ void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) | |||
| 759 | } | 772 | } |
| 760 | 773 | ||
| 761 | if (wdev->iftype == NL80211_IFTYPE_STATION) { | 774 | if (wdev->iftype == NL80211_IFTYPE_STATION) { |
| 762 | if (mcast && ether_addr_equal(eth->h_source, ndev->dev_addr)) { | 775 | sa = wil_skb_get_sa(skb); |
| 776 | if (mcast && ether_addr_equal(sa, ndev->dev_addr)) { | ||
| 763 | /* mcast packet looped back to us */ | 777 | /* mcast packet looped back to us */ |
| 764 | rc = GRO_DROP; | 778 | rc = GRO_DROP; |
| 765 | dev_kfree_skb(skb); | 779 | dev_kfree_skb(skb); |
| @@ -772,8 +786,7 @@ void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) | |||
| 772 | */ | 786 | */ |
| 773 | xmit_skb = skb_copy(skb, GFP_ATOMIC); | 787 | xmit_skb = skb_copy(skb, GFP_ATOMIC); |
| 774 | } else { | 788 | } else { |
| 775 | int xmit_cid = wil_find_cid(wil, vif->mid, | 789 | int xmit_cid = wil_find_cid(wil, vif->mid, da); |
| 776 | eth->h_dest); | ||
| 777 | 790 | ||
| 778 | if (xmit_cid >= 0) { | 791 | if (xmit_cid >= 0) { |
| 779 | /* The destination station is associated to | 792 | /* The destination station is associated to |
| @@ -971,7 +984,6 @@ static int wil_vring_init_tx(struct wil6210_vif *vif, int id, int size, | |||
| 971 | .ring_size = cpu_to_le16(size), | 984 | .ring_size = cpu_to_le16(size), |
| 972 | }, | 985 | }, |
| 973 | .ringid = id, | 986 | .ringid = id, |
| 974 | .cidxtid = mk_cidxtid(cid, tid), | ||
| 975 | .encap_trans_type = WMI_VRING_ENC_TYPE_802_3, | 987 | .encap_trans_type = WMI_VRING_ENC_TYPE_802_3, |
| 976 | .mac_ctrl = 0, | 988 | .mac_ctrl = 0, |
| 977 | .to_resolution = 0, | 989 | .to_resolution = 0, |
| @@ -991,6 +1003,14 @@ static int wil_vring_init_tx(struct wil6210_vif *vif, int id, int size, | |||
| 991 | struct wil_ring *vring = &wil->ring_tx[id]; | 1003 | struct wil_ring *vring = &wil->ring_tx[id]; |
| 992 | struct wil_ring_tx_data *txdata = &wil->ring_tx_data[id]; | 1004 | struct wil_ring_tx_data *txdata = &wil->ring_tx_data[id]; |
| 993 | 1005 | ||
| 1006 | if (cid >= WIL6210_RX_DESC_MAX_CID) { | ||
| 1007 | cmd.vring_cfg.cidxtid = CIDXTID_EXTENDED_CID_TID; | ||
| 1008 | cmd.vring_cfg.cid = cid; | ||
| 1009 | cmd.vring_cfg.tid = tid; | ||
| 1010 | } else { | ||
| 1011 | cmd.vring_cfg.cidxtid = mk_cidxtid(cid, tid); | ||
| 1012 | } | ||
| 1013 | |||
| 994 | wil_dbg_misc(wil, "vring_init_tx: max_mpdu_size %d\n", | 1014 | wil_dbg_misc(wil, "vring_init_tx: max_mpdu_size %d\n", |
| 995 | cmd.vring_cfg.tx_sw_ring.max_mpdu_size); | 1015 | cmd.vring_cfg.tx_sw_ring.max_mpdu_size); |
| 996 | lockdep_assert_held(&wil->mutex); | 1016 | lockdep_assert_held(&wil->mutex); |
| @@ -1043,7 +1063,7 @@ static int wil_vring_init_tx(struct wil6210_vif *vif, int id, int size, | |||
| 1043 | txdata->enabled = 0; | 1063 | txdata->enabled = 0; |
| 1044 | spin_unlock_bh(&txdata->lock); | 1064 | spin_unlock_bh(&txdata->lock); |
| 1045 | wil_vring_free(wil, vring); | 1065 | wil_vring_free(wil, vring); |
| 1046 | wil->ring2cid_tid[id][0] = WIL6210_MAX_CID; | 1066 | wil->ring2cid_tid[id][0] = max_assoc_sta; |
| 1047 | wil->ring2cid_tid[id][1] = 0; | 1067 | wil->ring2cid_tid[id][1] = 0; |
| 1048 | 1068 | ||
| 1049 | out: | 1069 | out: |
| @@ -1128,7 +1148,7 @@ fail: | |||
| 1128 | txdata->dot1x_open = false; | 1148 | txdata->dot1x_open = false; |
| 1129 | txdata->enabled = 0; | 1149 | txdata->enabled = 0; |
| 1130 | spin_unlock_bh(&txdata->lock); | 1150 | spin_unlock_bh(&txdata->lock); |
| 1131 | wil->ring2cid_tid[ring_id][0] = WIL6210_MAX_CID; | 1151 | wil->ring2cid_tid[ring_id][0] = max_assoc_sta; |
| 1132 | wil->ring2cid_tid[ring_id][1] = 0; | 1152 | wil->ring2cid_tid[ring_id][1] = 0; |
| 1133 | return rc; | 1153 | return rc; |
| 1134 | } | 1154 | } |
| @@ -1175,7 +1195,7 @@ int wil_vring_init_bcast(struct wil6210_vif *vif, int id, int size) | |||
| 1175 | if (rc) | 1195 | if (rc) |
| 1176 | goto out; | 1196 | goto out; |
| 1177 | 1197 | ||
| 1178 | wil->ring2cid_tid[id][0] = WIL6210_MAX_CID; /* CID */ | 1198 | wil->ring2cid_tid[id][0] = max_assoc_sta; /* CID */ |
| 1179 | wil->ring2cid_tid[id][1] = 0; /* TID */ | 1199 | wil->ring2cid_tid[id][1] = 0; /* TID */ |
| 1180 | 1200 | ||
| 1181 | cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa); | 1201 | cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa); |
| @@ -1217,12 +1237,13 @@ static struct wil_ring *wil_find_tx_ucast(struct wil6210_priv *wil, | |||
| 1217 | struct wil6210_vif *vif, | 1237 | struct wil6210_vif *vif, |
| 1218 | struct sk_buff *skb) | 1238 | struct sk_buff *skb) |
| 1219 | { | 1239 | { |
| 1220 | int i; | 1240 | int i, cid; |
| 1221 | struct ethhdr *eth = (void *)skb->data; | 1241 | const u8 *da = wil_skb_get_da(skb); |
| 1222 | int cid = wil_find_cid(wil, vif->mid, eth->h_dest); | ||
| 1223 | int min_ring_id = wil_get_min_tx_ring_id(wil); | 1242 | int min_ring_id = wil_get_min_tx_ring_id(wil); |
| 1224 | 1243 | ||
| 1225 | if (cid < 0) | 1244 | cid = wil_find_cid(wil, vif->mid, da); |
| 1245 | |||
| 1246 | if (cid < 0 || cid >= max_assoc_sta) | ||
| 1226 | return NULL; | 1247 | return NULL; |
| 1227 | 1248 | ||
| 1228 | /* TODO: fix for multiple TID */ | 1249 | /* TODO: fix for multiple TID */ |
| @@ -1235,7 +1256,7 @@ static struct wil_ring *wil_find_tx_ucast(struct wil6210_priv *wil, | |||
| 1235 | struct wil_ring_tx_data *txdata = &wil->ring_tx_data[i]; | 1256 | struct wil_ring_tx_data *txdata = &wil->ring_tx_data[i]; |
| 1236 | 1257 | ||
| 1237 | wil_dbg_txrx(wil, "find_tx_ucast: (%pM) -> [%d]\n", | 1258 | wil_dbg_txrx(wil, "find_tx_ucast: (%pM) -> [%d]\n", |
| 1238 | eth->h_dest, i); | 1259 | da, i); |
| 1239 | if (v->va && txdata->enabled) { | 1260 | if (v->va && txdata->enabled) { |
| 1240 | return v; | 1261 | return v; |
| 1241 | } else { | 1262 | } else { |
| @@ -1274,7 +1295,7 @@ static struct wil_ring *wil_find_tx_ring_sta(struct wil6210_priv *wil, | |||
| 1274 | continue; | 1295 | continue; |
| 1275 | 1296 | ||
| 1276 | cid = wil->ring2cid_tid[i][0]; | 1297 | cid = wil->ring2cid_tid[i][0]; |
| 1277 | if (cid >= WIL6210_MAX_CID) /* skip BCAST */ | 1298 | if (cid >= max_assoc_sta) /* skip BCAST */ |
| 1278 | continue; | 1299 | continue; |
| 1279 | 1300 | ||
| 1280 | if (!wil->ring_tx_data[i].dot1x_open && | 1301 | if (!wil->ring_tx_data[i].dot1x_open && |
| @@ -1326,10 +1347,10 @@ static struct wil_ring *wil_find_tx_bcast_1(struct wil6210_priv *wil, | |||
| 1326 | static void wil_set_da_for_vring(struct wil6210_priv *wil, | 1347 | static void wil_set_da_for_vring(struct wil6210_priv *wil, |
| 1327 | struct sk_buff *skb, int vring_index) | 1348 | struct sk_buff *skb, int vring_index) |
| 1328 | { | 1349 | { |
| 1329 | struct ethhdr *eth = (void *)skb->data; | 1350 | u8 *da = wil_skb_get_da(skb); |
| 1330 | int cid = wil->ring2cid_tid[vring_index][0]; | 1351 | int cid = wil->ring2cid_tid[vring_index][0]; |
| 1331 | 1352 | ||
| 1332 | ether_addr_copy(eth->h_dest, wil->sta[cid].addr); | 1353 | ether_addr_copy(da, wil->sta[cid].addr); |
| 1333 | } | 1354 | } |
| 1334 | 1355 | ||
| 1335 | static struct wil_ring *wil_find_tx_bcast_2(struct wil6210_priv *wil, | 1356 | static struct wil_ring *wil_find_tx_bcast_2(struct wil6210_priv *wil, |
| @@ -1340,8 +1361,7 @@ static struct wil_ring *wil_find_tx_bcast_2(struct wil6210_priv *wil, | |||
| 1340 | struct sk_buff *skb2; | 1361 | struct sk_buff *skb2; |
| 1341 | int i; | 1362 | int i; |
| 1342 | u8 cid; | 1363 | u8 cid; |
| 1343 | struct ethhdr *eth = (void *)skb->data; | 1364 | const u8 *src = wil_skb_get_sa(skb); |
| 1344 | char *src = eth->h_source; | ||
| 1345 | struct wil_ring_tx_data *txdata, *txdata2; | 1365 | struct wil_ring_tx_data *txdata, *txdata2; |
| 1346 | int min_ring_id = wil_get_min_tx_ring_id(wil); | 1366 | int min_ring_id = wil_get_min_tx_ring_id(wil); |
| 1347 | 1367 | ||
| @@ -1353,7 +1373,7 @@ static struct wil_ring *wil_find_tx_bcast_2(struct wil6210_priv *wil, | |||
| 1353 | continue; | 1373 | continue; |
| 1354 | 1374 | ||
| 1355 | cid = wil->ring2cid_tid[i][0]; | 1375 | cid = wil->ring2cid_tid[i][0]; |
| 1356 | if (cid >= WIL6210_MAX_CID) /* skip BCAST */ | 1376 | if (cid >= max_assoc_sta) /* skip BCAST */ |
| 1357 | continue; | 1377 | continue; |
| 1358 | if (!wil->ring_tx_data[i].dot1x_open && | 1378 | if (!wil->ring_tx_data[i].dot1x_open && |
| 1359 | skb->protocol != cpu_to_be16(ETH_P_PAE)) | 1379 | skb->protocol != cpu_to_be16(ETH_P_PAE)) |
| @@ -1381,7 +1401,7 @@ found: | |||
| 1381 | if (!v2->va || txdata2->mid != vif->mid) | 1401 | if (!v2->va || txdata2->mid != vif->mid) |
| 1382 | continue; | 1402 | continue; |
| 1383 | cid = wil->ring2cid_tid[i][0]; | 1403 | cid = wil->ring2cid_tid[i][0]; |
| 1384 | if (cid >= WIL6210_MAX_CID) /* skip BCAST */ | 1404 | if (cid >= max_assoc_sta) /* skip BCAST */ |
| 1385 | continue; | 1405 | continue; |
| 1386 | if (!wil->ring_tx_data[i].dot1x_open && | 1406 | if (!wil->ring_tx_data[i].dot1x_open && |
| 1387 | skb->protocol != cpu_to_be16(ETH_P_PAE)) | 1407 | skb->protocol != cpu_to_be16(ETH_P_PAE)) |
| @@ -2032,6 +2052,10 @@ static inline void __wil_update_net_queues(struct wil6210_priv *wil, | |||
| 2032 | wil_dbg_txrx(wil, "check_stop=%d, mid=%d, stopped=%d", | 2052 | wil_dbg_txrx(wil, "check_stop=%d, mid=%d, stopped=%d", |
| 2033 | check_stop, vif->mid, vif->net_queue_stopped); | 2053 | check_stop, vif->mid, vif->net_queue_stopped); |
| 2034 | 2054 | ||
| 2055 | if (ring && drop_if_ring_full) | ||
| 2056 | /* no need to stop/wake net queues */ | ||
| 2057 | return; | ||
| 2058 | |||
| 2035 | if (check_stop == vif->net_queue_stopped) | 2059 | if (check_stop == vif->net_queue_stopped) |
| 2036 | /* net queues already in desired state */ | 2060 | /* net queues already in desired state */ |
| 2037 | return; | 2061 | return; |
| @@ -2095,8 +2119,8 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) | |||
| 2095 | { | 2119 | { |
| 2096 | struct wil6210_vif *vif = ndev_to_vif(ndev); | 2120 | struct wil6210_vif *vif = ndev_to_vif(ndev); |
| 2097 | struct wil6210_priv *wil = vif_to_wil(vif); | 2121 | struct wil6210_priv *wil = vif_to_wil(vif); |
| 2098 | struct ethhdr *eth = (void *)skb->data; | 2122 | const u8 *da = wil_skb_get_da(skb); |
| 2099 | bool bcast = is_multicast_ether_addr(eth->h_dest); | 2123 | bool bcast = is_multicast_ether_addr(da); |
| 2100 | struct wil_ring *ring; | 2124 | struct wil_ring *ring; |
| 2101 | static bool pr_once_fw; | 2125 | static bool pr_once_fw; |
| 2102 | int rc; | 2126 | int rc; |
| @@ -2143,7 +2167,7 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) | |||
| 2143 | ring = wil_find_tx_ucast(wil, vif, skb); | 2167 | ring = wil_find_tx_ucast(wil, vif, skb); |
| 2144 | } | 2168 | } |
| 2145 | if (unlikely(!ring)) { | 2169 | if (unlikely(!ring)) { |
| 2146 | wil_dbg_txrx(wil, "No Tx RING found for %pM\n", eth->h_dest); | 2170 | wil_dbg_txrx(wil, "No Tx RING found for %pM\n", da); |
| 2147 | goto drop; | 2171 | goto drop; |
| 2148 | } | 2172 | } |
| 2149 | /* set up vring entry */ | 2173 | /* set up vring entry */ |
| @@ -2157,6 +2181,8 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) | |||
| 2157 | dev_kfree_skb_any(skb); | 2181 | dev_kfree_skb_any(skb); |
| 2158 | return NETDEV_TX_OK; | 2182 | return NETDEV_TX_OK; |
| 2159 | case -ENOMEM: | 2183 | case -ENOMEM: |
| 2184 | if (drop_if_ring_full) | ||
| 2185 | goto drop; | ||
| 2160 | return NETDEV_TX_BUSY; | 2186 | return NETDEV_TX_BUSY; |
| 2161 | default: | 2187 | default: |
| 2162 | break; /* goto drop; */ | 2188 | break; /* goto drop; */ |
| @@ -2228,7 +2254,7 @@ int wil_tx_complete(struct wil6210_vif *vif, int ringid) | |||
| 2228 | 2254 | ||
| 2229 | used_before_complete = wil_ring_used_tx(vring); | 2255 | used_before_complete = wil_ring_used_tx(vring); |
| 2230 | 2256 | ||
| 2231 | if (cid < WIL6210_MAX_CID) | 2257 | if (cid < max_assoc_sta) |
| 2232 | stats = &wil->sta[cid].stats; | 2258 | stats = &wil->sta[cid].stats; |
| 2233 | 2259 | ||
| 2234 | while (!wil_ring_is_empty(vring)) { | 2260 | while (!wil_ring_is_empty(vring)) { |
| @@ -2337,7 +2363,7 @@ static void wil_get_reorder_params(struct wil6210_priv *wil, | |||
| 2337 | struct vring_rx_desc *d = wil_skb_rxdesc(skb); | 2363 | struct vring_rx_desc *d = wil_skb_rxdesc(skb); |
| 2338 | 2364 | ||
| 2339 | *tid = wil_rxdesc_tid(d); | 2365 | *tid = wil_rxdesc_tid(d); |
| 2340 | *cid = wil_rxdesc_cid(d); | 2366 | *cid = wil_skb_get_cid(skb); |
| 2341 | *mid = wil_rxdesc_mid(d); | 2367 | *mid = wil_rxdesc_mid(d); |
| 2342 | *seq = wil_rxdesc_seq(d); | 2368 | *seq = wil_rxdesc_seq(d); |
| 2343 | *mcast = wil_rxdesc_mcast(d); | 2369 | *mcast = wil_rxdesc_mcast(d); |
diff --git a/drivers/net/wireless/ath/wil6210/txrx.h b/drivers/net/wireless/ath/wil6210/txrx.h index 9d83be481839..c0da1340c2d2 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.h +++ b/drivers/net/wireless/ath/wil6210/txrx.h | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2012-2016 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2012-2016 Qualcomm Atheros, Inc. |
| 3 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | 3 | * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * Permission to use, copy, modify, and/or distribute this software for any |
| 6 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
| @@ -458,6 +458,18 @@ union wil_ring_desc { | |||
| 458 | union wil_rx_desc rx; | 458 | union wil_rx_desc rx; |
| 459 | } __packed; | 459 | } __packed; |
| 460 | 460 | ||
| 461 | struct packet_rx_info { | ||
| 462 | u8 cid; | ||
| 463 | }; | ||
| 464 | |||
| 465 | /* this struct will be stored in the skb cb buffer | ||
| 466 | * max length of the struct is limited to 48 bytes | ||
| 467 | */ | ||
| 468 | struct skb_rx_info { | ||
| 469 | struct vring_rx_desc rx_desc; | ||
| 470 | struct packet_rx_info rx_info; | ||
| 471 | }; | ||
| 472 | |||
| 461 | static inline int wil_rxdesc_tid(struct vring_rx_desc *d) | 473 | static inline int wil_rxdesc_tid(struct vring_rx_desc *d) |
| 462 | { | 474 | { |
| 463 | return WIL_GET_BITS(d->mac.d0, 0, 3); | 475 | return WIL_GET_BITS(d->mac.d0, 0, 3); |
| @@ -530,11 +542,6 @@ static inline int wil_rxdesc_mcast(struct vring_rx_desc *d) | |||
| 530 | return WIL_GET_BITS(d->mac.d1, 13, 14); | 542 | return WIL_GET_BITS(d->mac.d1, 13, 14); |
| 531 | } | 543 | } |
| 532 | 544 | ||
| 533 | static inline int wil_rxdesc_phy_length(struct vring_rx_desc *d) | ||
| 534 | { | ||
| 535 | return WIL_GET_BITS(d->dma.d0, 16, 29); | ||
| 536 | } | ||
| 537 | |||
| 538 | static inline struct vring_rx_desc *wil_skb_rxdesc(struct sk_buff *skb) | 545 | static inline struct vring_rx_desc *wil_skb_rxdesc(struct sk_buff *skb) |
| 539 | { | 546 | { |
| 540 | return (void *)skb->cb; | 547 | return (void *)skb->cb; |
| @@ -560,11 +567,25 @@ static inline int wil_ring_is_full(struct wil_ring *ring) | |||
| 560 | return wil_ring_next_tail(ring) == ring->swhead; | 567 | return wil_ring_next_tail(ring) == ring->swhead; |
| 561 | } | 568 | } |
| 562 | 569 | ||
| 563 | static inline bool wil_need_txstat(struct sk_buff *skb) | 570 | static inline u8 *wil_skb_get_da(struct sk_buff *skb) |
| 571 | { | ||
| 572 | struct ethhdr *eth = (void *)skb->data; | ||
| 573 | |||
| 574 | return eth->h_dest; | ||
| 575 | } | ||
| 576 | |||
| 577 | static inline u8 *wil_skb_get_sa(struct sk_buff *skb) | ||
| 564 | { | 578 | { |
| 565 | struct ethhdr *eth = (void *)skb->data; | 579 | struct ethhdr *eth = (void *)skb->data; |
| 566 | 580 | ||
| 567 | return is_unicast_ether_addr(eth->h_dest) && skb->sk && | 581 | return eth->h_source; |
| 582 | } | ||
| 583 | |||
| 584 | static inline bool wil_need_txstat(struct sk_buff *skb) | ||
| 585 | { | ||
| 586 | const u8 *da = wil_skb_get_da(skb); | ||
| 587 | |||
| 588 | return is_unicast_ether_addr(da) && skb->sk && | ||
| 568 | (skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS); | 589 | (skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS); |
| 569 | } | 590 | } |
| 570 | 591 | ||
| @@ -610,6 +631,20 @@ static inline bool wil_val_in_range(int val, int min, int max) | |||
| 610 | return val >= min && val < max; | 631 | return val >= min && val < max; |
| 611 | } | 632 | } |
| 612 | 633 | ||
| 634 | static inline u8 wil_skb_get_cid(struct sk_buff *skb) | ||
| 635 | { | ||
| 636 | struct skb_rx_info *skb_rx_info = (void *)skb->cb; | ||
| 637 | |||
| 638 | return skb_rx_info->rx_info.cid; | ||
| 639 | } | ||
| 640 | |||
| 641 | static inline void wil_skb_set_cid(struct sk_buff *skb, u8 cid) | ||
| 642 | { | ||
| 643 | struct skb_rx_info *skb_rx_info = (void *)skb->cb; | ||
| 644 | |||
| 645 | skb_rx_info->rx_info.cid = cid; | ||
| 646 | } | ||
| 647 | |||
| 613 | void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev); | 648 | void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev); |
| 614 | void wil_rx_reorder(struct wil6210_priv *wil, struct sk_buff *skb); | 649 | void wil_rx_reorder(struct wil6210_priv *wil, struct sk_buff *skb); |
| 615 | void wil_rx_bar(struct wil6210_priv *wil, struct wil6210_vif *vif, | 650 | void wil_rx_bar(struct wil6210_priv *wil, struct wil6210_vif *vif, |
diff --git a/drivers/net/wireless/ath/wil6210/txrx_edma.c b/drivers/net/wireless/ath/wil6210/txrx_edma.c index 3380aaef456c..c38773878ae3 100644 --- a/drivers/net/wireless/ath/wil6210/txrx_edma.c +++ b/drivers/net/wireless/ath/wil6210/txrx_edma.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. | 2 | * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. |
| 3 | * | 3 | * |
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
| 5 | * purpose with or without fee is hereby granted, provided that the above | 5 | * purpose with or without fee is hereby granted, provided that the above |
| @@ -727,7 +727,7 @@ static int wil_ring_init_tx_edma(struct wil6210_vif *vif, int ring_id, | |||
| 727 | txdata->enabled = 0; | 727 | txdata->enabled = 0; |
| 728 | spin_unlock_bh(&txdata->lock); | 728 | spin_unlock_bh(&txdata->lock); |
| 729 | wil_ring_free_edma(wil, ring); | 729 | wil_ring_free_edma(wil, ring); |
| 730 | wil->ring2cid_tid[ring_id][0] = WIL6210_MAX_CID; | 730 | wil->ring2cid_tid[ring_id][0] = max_assoc_sta; |
| 731 | wil->ring2cid_tid[ring_id][1] = 0; | 731 | wil->ring2cid_tid[ring_id][1] = 0; |
| 732 | 732 | ||
| 733 | out: | 733 | out: |
| @@ -932,7 +932,7 @@ again: | |||
| 932 | eop = wil_rx_status_get_eop(msg); | 932 | eop = wil_rx_status_get_eop(msg); |
| 933 | 933 | ||
| 934 | cid = wil_rx_status_get_cid(msg); | 934 | cid = wil_rx_status_get_cid(msg); |
| 935 | if (unlikely(!wil_val_in_range(cid, 0, WIL6210_MAX_CID))) { | 935 | if (unlikely(!wil_val_in_range(cid, 0, max_assoc_sta))) { |
| 936 | wil_err(wil, "Corrupt cid=%d, sring->swhead=%d\n", | 936 | wil_err(wil, "Corrupt cid=%d, sring->swhead=%d\n", |
| 937 | cid, sring->swhead); | 937 | cid, sring->swhead); |
| 938 | rxdata->skipping = true; | 938 | rxdata->skipping = true; |
| @@ -1137,7 +1137,7 @@ int wil_tx_sring_handler(struct wil6210_priv *wil, | |||
| 1137 | /* Total number of completed descriptors in all descriptor rings */ | 1137 | /* Total number of completed descriptors in all descriptor rings */ |
| 1138 | int desc_cnt = 0; | 1138 | int desc_cnt = 0; |
| 1139 | int cid; | 1139 | int cid; |
| 1140 | struct wil_net_stats *stats = NULL; | 1140 | struct wil_net_stats *stats; |
| 1141 | struct wil_tx_enhanced_desc *_d; | 1141 | struct wil_tx_enhanced_desc *_d; |
| 1142 | unsigned int ring_id; | 1142 | unsigned int ring_id; |
| 1143 | unsigned int num_descs; | 1143 | unsigned int num_descs; |
| @@ -1187,8 +1187,7 @@ int wil_tx_sring_handler(struct wil6210_priv *wil, | |||
| 1187 | ndev = vif_to_ndev(vif); | 1187 | ndev = vif_to_ndev(vif); |
| 1188 | 1188 | ||
| 1189 | cid = wil->ring2cid_tid[ring_id][0]; | 1189 | cid = wil->ring2cid_tid[ring_id][0]; |
| 1190 | if (cid < WIL6210_MAX_CID) | 1190 | stats = (cid < max_assoc_sta ? &wil->sta[cid].stats : NULL); |
| 1191 | stats = &wil->sta[cid].stats; | ||
| 1192 | 1191 | ||
| 1193 | wil_dbg_txrx(wil, | 1192 | wil_dbg_txrx(wil, |
| 1194 | "tx_status: completed desc_ring (%d), num_descs (%d)\n", | 1193 | "tx_status: completed desc_ring (%d), num_descs (%d)\n", |
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 0f3be3ffc6a2..e1b1039b13ab 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. |
| 3 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | 3 | * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * Permission to use, copy, modify, and/or distribute this software for any |
| 6 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
| @@ -38,6 +38,8 @@ extern bool rx_large_buf; | |||
| 38 | extern bool debug_fw; | 38 | extern bool debug_fw; |
| 39 | extern bool disable_ap_sme; | 39 | extern bool disable_ap_sme; |
| 40 | extern bool ftm_mode; | 40 | extern bool ftm_mode; |
| 41 | extern bool drop_if_ring_full; | ||
| 42 | extern uint max_assoc_sta; | ||
| 41 | 43 | ||
| 42 | struct wil6210_priv; | 44 | struct wil6210_priv; |
| 43 | struct wil6210_vif; | 45 | struct wil6210_vif; |
| @@ -89,7 +91,8 @@ static inline u32 WIL_GET_BITS(u32 x, int b0, int b1) | |||
| 89 | #define WIL_RING_SIZE_ORDER_MIN (5) | 91 | #define WIL_RING_SIZE_ORDER_MIN (5) |
| 90 | #define WIL_RING_SIZE_ORDER_MAX (15) | 92 | #define WIL_RING_SIZE_ORDER_MAX (15) |
| 91 | #define WIL6210_MAX_TX_RINGS (24) /* HW limit */ | 93 | #define WIL6210_MAX_TX_RINGS (24) /* HW limit */ |
| 92 | #define WIL6210_MAX_CID (8) /* HW limit */ | 94 | #define WIL6210_MAX_CID (20) /* max number of stations */ |
| 95 | #define WIL6210_RX_DESC_MAX_CID (8) /* HW limit */ | ||
| 93 | #define WIL6210_NAPI_BUDGET (16) /* arbitrary */ | 96 | #define WIL6210_NAPI_BUDGET (16) /* arbitrary */ |
| 94 | #define WIL_MAX_AMPDU_SIZE (64 * 1024) /* FW/HW limit */ | 97 | #define WIL_MAX_AMPDU_SIZE (64 * 1024) /* FW/HW limit */ |
| 95 | #define WIL_MAX_AGG_WSIZE (32) /* FW/HW limit */ | 98 | #define WIL_MAX_AGG_WSIZE (32) /* FW/HW limit */ |
| @@ -457,7 +460,7 @@ static inline void parse_cidxtid(u8 cidxtid, u8 *cid, u8 *tid) | |||
| 457 | */ | 460 | */ |
| 458 | static inline bool wil_cid_valid(u8 cid) | 461 | static inline bool wil_cid_valid(u8 cid) |
| 459 | { | 462 | { |
| 460 | return cid < WIL6210_MAX_CID; | 463 | return (cid >= 0 && cid < max_assoc_sta); |
| 461 | } | 464 | } |
| 462 | 465 | ||
| 463 | struct wil6210_mbox_ring { | 466 | struct wil6210_mbox_ring { |
| @@ -791,6 +794,7 @@ struct wil_halp { | |||
| 791 | struct mutex lock; /* protect halp ref_cnt */ | 794 | struct mutex lock; /* protect halp ref_cnt */ |
| 792 | unsigned int ref_cnt; | 795 | unsigned int ref_cnt; |
| 793 | struct completion comp; | 796 | struct completion comp; |
| 797 | u8 handle_icr; | ||
| 794 | }; | 798 | }; |
| 795 | 799 | ||
| 796 | struct wil_blob_wrapper { | 800 | struct wil_blob_wrapper { |
| @@ -1235,7 +1239,7 @@ int wmi_disconnect_sta(struct wil6210_vif *vif, const u8 *mac, u16 reason, | |||
| 1235 | int wmi_addba(struct wil6210_priv *wil, u8 mid, | 1239 | int wmi_addba(struct wil6210_priv *wil, u8 mid, |
| 1236 | u8 ringid, u8 size, u16 timeout); | 1240 | u8 ringid, u8 size, u16 timeout); |
| 1237 | int wmi_delba_tx(struct wil6210_priv *wil, u8 mid, u8 ringid, u16 reason); | 1241 | int wmi_delba_tx(struct wil6210_priv *wil, u8 mid, u8 ringid, u16 reason); |
| 1238 | int wmi_delba_rx(struct wil6210_priv *wil, u8 mid, u8 cidxtid, u16 reason); | 1242 | int wmi_delba_rx(struct wil6210_priv *wil, u8 mid, u8 cid, u8 tid, u16 reason); |
| 1239 | int wmi_addba_rx_resp(struct wil6210_priv *wil, | 1243 | int wmi_addba_rx_resp(struct wil6210_priv *wil, |
| 1240 | u8 mid, u8 cid, u8 tid, u8 token, | 1244 | u8 mid, u8 cid, u8 tid, u8 token, |
| 1241 | u16 status, bool amsdu, u16 agg_wsize, u16 timeout); | 1245 | u16 status, bool amsdu, u16 agg_wsize, u16 timeout); |
| @@ -1248,8 +1252,8 @@ int wmi_port_allocate(struct wil6210_priv *wil, u8 mid, | |||
| 1248 | const u8 *mac, enum nl80211_iftype iftype); | 1252 | const u8 *mac, enum nl80211_iftype iftype); |
| 1249 | int wmi_port_delete(struct wil6210_priv *wil, u8 mid); | 1253 | int wmi_port_delete(struct wil6210_priv *wil, u8 mid); |
| 1250 | int wmi_link_stats_cfg(struct wil6210_vif *vif, u32 type, u8 cid, u32 interval); | 1254 | int wmi_link_stats_cfg(struct wil6210_vif *vif, u32 type, u8 cid, u32 interval); |
| 1251 | int wil_addba_rx_request(struct wil6210_priv *wil, u8 mid, | 1255 | int wil_addba_rx_request(struct wil6210_priv *wil, u8 mid, u8 cid, u8 tid, |
| 1252 | u8 cidxtid, u8 dialog_token, __le16 ba_param_set, | 1256 | u8 dialog_token, __le16 ba_param_set, |
| 1253 | __le16 ba_timeout, __le16 ba_seq_ctrl); | 1257 | __le16 ba_timeout, __le16 ba_seq_ctrl); |
| 1254 | int wil_addba_tx_request(struct wil6210_priv *wil, u8 ringid, u16 wsize); | 1258 | int wil_addba_tx_request(struct wil6210_priv *wil, u8 ringid, u16 wsize); |
| 1255 | 1259 | ||
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 345f05969190..bda4a9712f91 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. | 2 | * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. |
| 3 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | 3 | * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. |
| 4 | * | 4 | * |
| 5 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * Permission to use, copy, modify, and/or distribute this software for any |
| 6 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
| @@ -24,8 +24,9 @@ | |||
| 24 | #include "wmi.h" | 24 | #include "wmi.h" |
| 25 | #include "trace.h" | 25 | #include "trace.h" |
| 26 | 26 | ||
| 27 | static uint max_assoc_sta = WIL6210_MAX_CID; | 27 | /* set the default max assoc sta to max supported by driver */ |
| 28 | module_param(max_assoc_sta, uint, 0644); | 28 | uint max_assoc_sta = WIL6210_MAX_CID; |
| 29 | module_param(max_assoc_sta, uint, 0444); | ||
| 29 | MODULE_PARM_DESC(max_assoc_sta, " Max number of stations associated to the AP"); | 30 | MODULE_PARM_DESC(max_assoc_sta, " Max number of stations associated to the AP"); |
| 30 | 31 | ||
| 31 | int agg_wsize; /* = 0; */ | 32 | int agg_wsize; /* = 0; */ |
| @@ -770,6 +771,7 @@ static void wmi_evt_ready(struct wil6210_vif *vif, int id, void *d, int len) | |||
| 770 | struct wil6210_priv *wil = vif_to_wil(vif); | 771 | struct wil6210_priv *wil = vif_to_wil(vif); |
| 771 | struct wiphy *wiphy = wil_to_wiphy(wil); | 772 | struct wiphy *wiphy = wil_to_wiphy(wil); |
| 772 | struct wmi_ready_event *evt = d; | 773 | struct wmi_ready_event *evt = d; |
| 774 | u8 fw_max_assoc_sta; | ||
| 773 | 775 | ||
| 774 | wil_info(wil, "FW ver. %s(SW %d); MAC %pM; %d MID's\n", | 776 | wil_info(wil, "FW ver. %s(SW %d); MAC %pM; %d MID's\n", |
| 775 | wil->fw_version, le32_to_cpu(evt->sw_version), | 777 | wil->fw_version, le32_to_cpu(evt->sw_version), |
| @@ -787,6 +789,25 @@ static void wmi_evt_ready(struct wil6210_vif *vif, int id, void *d, int len) | |||
| 787 | evt->rfc_read_calib_result); | 789 | evt->rfc_read_calib_result); |
| 788 | wil->fw_calib_result = evt->rfc_read_calib_result; | 790 | wil->fw_calib_result = evt->rfc_read_calib_result; |
| 789 | } | 791 | } |
| 792 | |||
| 793 | fw_max_assoc_sta = WIL6210_RX_DESC_MAX_CID; | ||
| 794 | if (len > offsetof(struct wmi_ready_event, max_assoc_sta) && | ||
| 795 | evt->max_assoc_sta > 0) { | ||
| 796 | fw_max_assoc_sta = evt->max_assoc_sta; | ||
| 797 | wil_dbg_wmi(wil, "fw reported max assoc sta %d\n", | ||
| 798 | fw_max_assoc_sta); | ||
| 799 | |||
| 800 | if (fw_max_assoc_sta > WIL6210_MAX_CID) { | ||
| 801 | wil_dbg_wmi(wil, | ||
| 802 | "fw max assoc sta %d exceeds max driver supported %d\n", | ||
| 803 | fw_max_assoc_sta, WIL6210_MAX_CID); | ||
| 804 | fw_max_assoc_sta = WIL6210_MAX_CID; | ||
| 805 | } | ||
| 806 | } | ||
| 807 | |||
| 808 | max_assoc_sta = min_t(uint, max_assoc_sta, fw_max_assoc_sta); | ||
| 809 | wil_dbg_wmi(wil, "setting max assoc sta to %d\n", max_assoc_sta); | ||
| 810 | |||
| 790 | wil_set_recovery_state(wil, fw_recovery_idle); | 811 | wil_set_recovery_state(wil, fw_recovery_idle); |
| 791 | set_bit(wil_status_fwready, wil->status); | 812 | set_bit(wil_status_fwready, wil->status); |
| 792 | /* let the reset sequence continue */ | 813 | /* let the reset sequence continue */ |
| @@ -952,7 +973,7 @@ static void wmi_evt_connect(struct wil6210_vif *vif, int id, void *d, int len) | |||
| 952 | evt->assoc_req_len, evt->assoc_resp_len); | 973 | evt->assoc_req_len, evt->assoc_resp_len); |
| 953 | return; | 974 | return; |
| 954 | } | 975 | } |
| 955 | if (evt->cid >= WIL6210_MAX_CID) { | 976 | if (evt->cid >= max_assoc_sta) { |
| 956 | wil_err(wil, "Connect CID invalid : %d\n", evt->cid); | 977 | wil_err(wil, "Connect CID invalid : %d\n", evt->cid); |
| 957 | return; | 978 | return; |
| 958 | } | 979 | } |
| @@ -1271,9 +1292,16 @@ static void wmi_evt_addba_rx_req(struct wil6210_vif *vif, int id, | |||
| 1271 | void *d, int len) | 1292 | void *d, int len) |
| 1272 | { | 1293 | { |
| 1273 | struct wil6210_priv *wil = vif_to_wil(vif); | 1294 | struct wil6210_priv *wil = vif_to_wil(vif); |
| 1295 | u8 cid, tid; | ||
| 1274 | struct wmi_rcp_addba_req_event *evt = d; | 1296 | struct wmi_rcp_addba_req_event *evt = d; |
| 1275 | 1297 | ||
| 1276 | wil_addba_rx_request(wil, vif->mid, evt->cidxtid, evt->dialog_token, | 1298 | if (evt->cidxtid != CIDXTID_EXTENDED_CID_TID) { |
| 1299 | parse_cidxtid(evt->cidxtid, &cid, &tid); | ||
| 1300 | } else { | ||
| 1301 | cid = evt->cid; | ||
| 1302 | tid = evt->tid; | ||
| 1303 | } | ||
| 1304 | wil_addba_rx_request(wil, vif->mid, cid, tid, evt->dialog_token, | ||
| 1277 | evt->ba_param_set, evt->ba_timeout, | 1305 | evt->ba_param_set, evt->ba_timeout, |
| 1278 | evt->ba_seq_ctrl); | 1306 | evt->ba_seq_ctrl); |
| 1279 | } | 1307 | } |
| @@ -1289,7 +1317,13 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) | |||
| 1289 | struct wil_tid_ampdu_rx *r; | 1317 | struct wil_tid_ampdu_rx *r; |
| 1290 | 1318 | ||
| 1291 | might_sleep(); | 1319 | might_sleep(); |
| 1292 | parse_cidxtid(evt->cidxtid, &cid, &tid); | 1320 | |
| 1321 | if (evt->cidxtid != CIDXTID_EXTENDED_CID_TID) { | ||
| 1322 | parse_cidxtid(evt->cidxtid, &cid, &tid); | ||
| 1323 | } else { | ||
| 1324 | cid = evt->cid; | ||
| 1325 | tid = evt->tid; | ||
| 1326 | } | ||
| 1293 | wil_dbg_wmi(wil, "DELBA MID %d CID %d TID %d from %s reason %d\n", | 1327 | wil_dbg_wmi(wil, "DELBA MID %d CID %d TID %d from %s reason %d\n", |
| 1294 | vif->mid, cid, tid, | 1328 | vif->mid, cid, tid, |
| 1295 | evt->from_initiator ? "originator" : "recipient", | 1329 | evt->from_initiator ? "originator" : "recipient", |
| @@ -1404,7 +1438,7 @@ static void wil_link_stats_store_basic(struct wil6210_vif *vif, | |||
| 1404 | u8 cid = basic->cid; | 1438 | u8 cid = basic->cid; |
| 1405 | struct wil_sta_info *sta; | 1439 | struct wil_sta_info *sta; |
| 1406 | 1440 | ||
| 1407 | if (cid < 0 || cid >= WIL6210_MAX_CID) { | 1441 | if (cid < 0 || cid >= max_assoc_sta) { |
| 1408 | wil_err(wil, "invalid cid %d\n", cid); | 1442 | wil_err(wil, "invalid cid %d\n", cid); |
| 1409 | return; | 1443 | return; |
| 1410 | } | 1444 | } |
| @@ -1554,7 +1588,7 @@ static int wil_find_cid_ringid_sta(struct wil6210_priv *wil, | |||
| 1554 | continue; | 1588 | continue; |
| 1555 | 1589 | ||
| 1556 | lcid = wil->ring2cid_tid[i][0]; | 1590 | lcid = wil->ring2cid_tid[i][0]; |
| 1557 | if (lcid >= WIL6210_MAX_CID) /* skip BCAST */ | 1591 | if (lcid >= max_assoc_sta) /* skip BCAST */ |
| 1558 | continue; | 1592 | continue; |
| 1559 | 1593 | ||
| 1560 | wil_dbg_wmi(wil, "find sta -> ringid %d cid %d\n", i, lcid); | 1594 | wil_dbg_wmi(wil, "find sta -> ringid %d cid %d\n", i, lcid); |
| @@ -2120,10 +2154,9 @@ int wmi_pcp_start(struct wil6210_vif *vif, | |||
| 2120 | 2154 | ||
| 2121 | if ((cmd.pcp_max_assoc_sta > WIL6210_MAX_CID) || | 2155 | if ((cmd.pcp_max_assoc_sta > WIL6210_MAX_CID) || |
| 2122 | (cmd.pcp_max_assoc_sta <= 0)) { | 2156 | (cmd.pcp_max_assoc_sta <= 0)) { |
| 2123 | wil_info(wil, | 2157 | wil_err(wil, "unexpected max_assoc_sta %d\n", |
| 2124 | "Requested connection limit %u, valid values are 1 - %d. Setting to %d\n", | 2158 | cmd.pcp_max_assoc_sta); |
| 2125 | max_assoc_sta, WIL6210_MAX_CID, WIL6210_MAX_CID); | 2159 | return -EOPNOTSUPP; |
| 2126 | cmd.pcp_max_assoc_sta = WIL6210_MAX_CID; | ||
| 2127 | } | 2160 | } |
| 2128 | 2161 | ||
| 2129 | if (disable_ap_sme && | 2162 | if (disable_ap_sme && |
| @@ -2516,7 +2549,7 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct wil_ring *vring) | |||
| 2516 | if (ch) | 2549 | if (ch) |
| 2517 | cmd.sniffer_cfg.channel = ch->hw_value - 1; | 2550 | cmd.sniffer_cfg.channel = ch->hw_value - 1; |
| 2518 | cmd.sniffer_cfg.phy_info_mode = | 2551 | cmd.sniffer_cfg.phy_info_mode = |
| 2519 | cpu_to_le32(ndev->type == ARPHRD_IEEE80211_RADIOTAP); | 2552 | cpu_to_le32(WMI_SNIFFER_PHY_INFO_DISABLED); |
| 2520 | cmd.sniffer_cfg.phy_support = | 2553 | cmd.sniffer_cfg.phy_support = |
| 2521 | cpu_to_le32((wil->monitor_flags & MONITOR_FLAG_CONTROL) | 2554 | cpu_to_le32((wil->monitor_flags & MONITOR_FLAG_CONTROL) |
| 2522 | ? WMI_SNIFFER_CP : WMI_SNIFFER_BOTH_PHYS); | 2555 | ? WMI_SNIFFER_CP : WMI_SNIFFER_BOTH_PHYS); |
| @@ -2651,15 +2684,22 @@ int wmi_delba_tx(struct wil6210_priv *wil, u8 mid, u8 ringid, u16 reason) | |||
| 2651 | return wmi_send(wil, WMI_RING_BA_DIS_CMDID, mid, &cmd, sizeof(cmd)); | 2684 | return wmi_send(wil, WMI_RING_BA_DIS_CMDID, mid, &cmd, sizeof(cmd)); |
| 2652 | } | 2685 | } |
| 2653 | 2686 | ||
| 2654 | int wmi_delba_rx(struct wil6210_priv *wil, u8 mid, u8 cidxtid, u16 reason) | 2687 | int wmi_delba_rx(struct wil6210_priv *wil, u8 mid, u8 cid, u8 tid, u16 reason) |
| 2655 | { | 2688 | { |
| 2656 | struct wmi_rcp_delba_cmd cmd = { | 2689 | struct wmi_rcp_delba_cmd cmd = { |
| 2657 | .cidxtid = cidxtid, | ||
| 2658 | .reason = cpu_to_le16(reason), | 2690 | .reason = cpu_to_le16(reason), |
| 2659 | }; | 2691 | }; |
| 2660 | 2692 | ||
| 2661 | wil_dbg_wmi(wil, "delba_rx: (CID %d TID %d reason %d)\n", cidxtid & 0xf, | 2693 | if (cid >= WIL6210_RX_DESC_MAX_CID) { |
| 2662 | (cidxtid >> 4) & 0xf, reason); | 2694 | cmd.cidxtid = CIDXTID_EXTENDED_CID_TID; |
| 2695 | cmd.cid = cid; | ||
| 2696 | cmd.tid = tid; | ||
| 2697 | } else { | ||
| 2698 | cmd.cidxtid = mk_cidxtid(cid, tid); | ||
| 2699 | } | ||
| 2700 | |||
| 2701 | wil_dbg_wmi(wil, "delba_rx: (CID %d TID %d reason %d)\n", cid, | ||
| 2702 | tid, reason); | ||
| 2663 | 2703 | ||
| 2664 | return wmi_send(wil, WMI_RCP_DELBA_CMDID, mid, &cmd, sizeof(cmd)); | 2704 | return wmi_send(wil, WMI_RCP_DELBA_CMDID, mid, &cmd, sizeof(cmd)); |
| 2665 | } | 2705 | } |
| @@ -2670,7 +2710,6 @@ int wmi_addba_rx_resp(struct wil6210_priv *wil, | |||
| 2670 | { | 2710 | { |
| 2671 | int rc; | 2711 | int rc; |
| 2672 | struct wmi_rcp_addba_resp_cmd cmd = { | 2712 | struct wmi_rcp_addba_resp_cmd cmd = { |
| 2673 | .cidxtid = mk_cidxtid(cid, tid), | ||
| 2674 | .dialog_token = token, | 2713 | .dialog_token = token, |
| 2675 | .status_code = cpu_to_le16(status), | 2714 | .status_code = cpu_to_le16(status), |
| 2676 | /* bit 0: A-MSDU supported | 2715 | /* bit 0: A-MSDU supported |
| @@ -2689,6 +2728,14 @@ int wmi_addba_rx_resp(struct wil6210_priv *wil, | |||
| 2689 | .evt = {.status = cpu_to_le16(WMI_FW_STATUS_FAILURE)}, | 2728 | .evt = {.status = cpu_to_le16(WMI_FW_STATUS_FAILURE)}, |
| 2690 | }; | 2729 | }; |
| 2691 | 2730 | ||
| 2731 | if (cid >= WIL6210_RX_DESC_MAX_CID) { | ||
| 2732 | cmd.cidxtid = CIDXTID_EXTENDED_CID_TID; | ||
| 2733 | cmd.cid = cid; | ||
| 2734 | cmd.tid = tid; | ||
| 2735 | } else { | ||
| 2736 | cmd.cidxtid = mk_cidxtid(cid, tid); | ||
| 2737 | } | ||
| 2738 | |||
| 2692 | wil_dbg_wmi(wil, | 2739 | wil_dbg_wmi(wil, |
| 2693 | "ADDBA response for MID %d CID %d TID %d size %d timeout %d status %d AMSDU%s\n", | 2740 | "ADDBA response for MID %d CID %d TID %d size %d timeout %d status %d AMSDU%s\n", |
| 2694 | mid, cid, tid, agg_wsize, | 2741 | mid, cid, tid, agg_wsize, |
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c index aef2d4092872..d3780eae7f19 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c | |||
| @@ -134,12 +134,20 @@ struct msgbuf_completion_hdr { | |||
| 134 | __le16 flow_ring_id; | 134 | __le16 flow_ring_id; |
| 135 | }; | 135 | }; |
| 136 | 136 | ||
| 137 | /* Data struct for the MSGBUF_TYPE_GEN_STATUS */ | ||
| 138 | struct msgbuf_gen_status { | ||
| 139 | struct msgbuf_common_hdr msg; | ||
| 140 | struct msgbuf_completion_hdr compl_hdr; | ||
| 141 | __le16 write_idx; | ||
| 142 | __le32 rsvd0[3]; | ||
| 143 | }; | ||
| 144 | |||
| 137 | /* Data struct for the MSGBUF_TYPE_RING_STATUS */ | 145 | /* Data struct for the MSGBUF_TYPE_RING_STATUS */ |
| 138 | struct msgbuf_ring_status { | 146 | struct msgbuf_ring_status { |
| 139 | struct msgbuf_common_hdr msg; | 147 | struct msgbuf_common_hdr msg; |
| 140 | struct msgbuf_completion_hdr compl_hdr; | 148 | struct msgbuf_completion_hdr compl_hdr; |
| 141 | __le16 write_idx; | 149 | __le16 write_idx; |
| 142 | __le32 rsvd0[5]; | 150 | __le16 rsvd0[5]; |
| 143 | }; | 151 | }; |
| 144 | 152 | ||
| 145 | struct msgbuf_rx_event { | 153 | struct msgbuf_rx_event { |
| @@ -1194,6 +1202,18 @@ brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf) | |||
| 1194 | brcmf_netif_rx(ifp, skb); | 1202 | brcmf_netif_rx(ifp, skb); |
| 1195 | } | 1203 | } |
| 1196 | 1204 | ||
| 1205 | static void brcmf_msgbuf_process_gen_status(struct brcmf_msgbuf *msgbuf, | ||
| 1206 | void *buf) | ||
| 1207 | { | ||
| 1208 | struct msgbuf_gen_status *gen_status = buf; | ||
| 1209 | struct brcmf_pub *drvr = msgbuf->drvr; | ||
| 1210 | int err; | ||
| 1211 | |||
| 1212 | err = le16_to_cpu(gen_status->compl_hdr.status); | ||
| 1213 | if (err) | ||
| 1214 | bphy_err(drvr, "Firmware reported general error: %d\n", err); | ||
| 1215 | } | ||
| 1216 | |||
| 1197 | static void brcmf_msgbuf_process_ring_status(struct brcmf_msgbuf *msgbuf, | 1217 | static void brcmf_msgbuf_process_ring_status(struct brcmf_msgbuf *msgbuf, |
| 1198 | void *buf) | 1218 | void *buf) |
| 1199 | { | 1219 | { |
| @@ -1273,6 +1293,10 @@ static void brcmf_msgbuf_process_msgtype(struct brcmf_msgbuf *msgbuf, void *buf) | |||
| 1273 | 1293 | ||
| 1274 | msg = (struct msgbuf_common_hdr *)buf; | 1294 | msg = (struct msgbuf_common_hdr *)buf; |
| 1275 | switch (msg->msgtype) { | 1295 | switch (msg->msgtype) { |
| 1296 | case MSGBUF_TYPE_GEN_STATUS: | ||
| 1297 | brcmf_dbg(MSGBUF, "MSGBUF_TYPE_GEN_STATUS\n"); | ||
| 1298 | brcmf_msgbuf_process_gen_status(msgbuf, buf); | ||
| 1299 | break; | ||
| 1276 | case MSGBUF_TYPE_RING_STATUS: | 1300 | case MSGBUF_TYPE_RING_STATUS: |
| 1277 | brcmf_dbg(MSGBUF, "MSGBUF_TYPE_RING_STATUS\n"); | 1301 | brcmf_dbg(MSGBUF, "MSGBUF_TYPE_RING_STATUS\n"); |
| 1278 | brcmf_msgbuf_process_ring_status(msgbuf, buf); | 1302 | brcmf_msgbuf_process_ring_status(msgbuf, buf); |
diff --git a/drivers/net/wireless/mediatek/mt76/Kconfig b/drivers/net/wireless/mediatek/mt76/Kconfig index c30d8f5bbf2a..dbe8c70a8f73 100644 --- a/drivers/net/wireless/mediatek/mt76/Kconfig +++ b/drivers/net/wireless/mediatek/mt76/Kconfig | |||
| @@ -21,3 +21,4 @@ config MT76x02_USB | |||
| 21 | 21 | ||
| 22 | source "drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig" | 22 | source "drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig" |
| 23 | source "drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig" | 23 | source "drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig" |
| 24 | source "drivers/net/wireless/mediatek/mt76/mt7603/Kconfig" | ||
diff --git a/drivers/net/wireless/mediatek/mt76/Makefile b/drivers/net/wireless/mediatek/mt76/Makefile index fa7a44edd02d..3fd1b64b4aa7 100644 --- a/drivers/net/wireless/mediatek/mt76/Makefile +++ b/drivers/net/wireless/mediatek/mt76/Makefile | |||
| @@ -7,7 +7,7 @@ mt76-y := \ | |||
| 7 | mmio.o util.o trace.o dma.o mac80211.o debugfs.o eeprom.o \ | 7 | mmio.o util.o trace.o dma.o mac80211.o debugfs.o eeprom.o \ |
| 8 | tx.o agg-rx.o mcu.o | 8 | tx.o agg-rx.o mcu.o |
| 9 | 9 | ||
| 10 | mt76-usb-y := usb.o usb_trace.o usb_mcu.o | 10 | mt76-usb-y := usb.o usb_trace.o |
| 11 | 11 | ||
| 12 | CFLAGS_trace.o := -I$(src) | 12 | CFLAGS_trace.o := -I$(src) |
| 13 | CFLAGS_usb_trace.o := -I$(src) | 13 | CFLAGS_usb_trace.o := -I$(src) |
| @@ -22,3 +22,4 @@ mt76x02-usb-y := mt76x02_usb_mcu.o mt76x02_usb_core.o | |||
| 22 | 22 | ||
| 23 | obj-$(CONFIG_MT76x0_COMMON) += mt76x0/ | 23 | obj-$(CONFIG_MT76x0_COMMON) += mt76x0/ |
| 24 | obj-$(CONFIG_MT76x2_COMMON) += mt76x2/ | 24 | obj-$(CONFIG_MT76x2_COMMON) += mt76x2/ |
| 25 | obj-$(CONFIG_MT7603E) += mt7603/ | ||
diff --git a/drivers/net/wireless/mediatek/mt76/eeprom.c b/drivers/net/wireless/mediatek/mt76/eeprom.c index 530e5593765c..a1529920d877 100644 --- a/drivers/net/wireless/mediatek/mt76/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/eeprom.c | |||
| @@ -54,22 +54,30 @@ mt76_get_of_eeprom(struct mt76_dev *dev, int len) | |||
| 54 | part = np->name; | 54 | part = np->name; |
| 55 | 55 | ||
| 56 | mtd = get_mtd_device_nm(part); | 56 | mtd = get_mtd_device_nm(part); |
| 57 | if (IS_ERR(mtd)) | 57 | if (IS_ERR(mtd)) { |
| 58 | return PTR_ERR(mtd); | 58 | ret = PTR_ERR(mtd); |
| 59 | goto out_put_node; | ||
| 60 | } | ||
| 59 | 61 | ||
| 60 | if (size <= sizeof(*list)) | 62 | if (size <= sizeof(*list)) { |
| 61 | return -EINVAL; | 63 | ret = -EINVAL; |
| 64 | goto out_put_node; | ||
| 65 | } | ||
| 62 | 66 | ||
| 63 | offset = be32_to_cpup(list); | 67 | offset = be32_to_cpup(list); |
| 64 | ret = mtd_read(mtd, offset, len, &retlen, dev->eeprom.data); | 68 | ret = mtd_read(mtd, offset, len, &retlen, dev->eeprom.data); |
| 65 | put_mtd_device(mtd); | 69 | put_mtd_device(mtd); |
| 66 | if (ret) | 70 | if (ret) |
| 67 | return ret; | 71 | goto out_put_node; |
| 68 | 72 | ||
| 69 | if (retlen < len) | 73 | if (retlen < len) { |
| 70 | return -EINVAL; | 74 | ret = -EINVAL; |
| 75 | goto out_put_node; | ||
| 76 | } | ||
| 71 | 77 | ||
| 72 | return 0; | 78 | out_put_node: |
| 79 | of_node_put(np); | ||
| 80 | return ret; | ||
| 73 | #else | 81 | #else |
| 74 | return -ENOENT; | 82 | return -ENOENT; |
| 75 | #endif | 83 | #endif |
diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 82e9f78ef328..a033745adb2f 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c | |||
| @@ -714,6 +714,11 @@ int mt76_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
| 714 | new_state == IEEE80211_STA_NONE) | 714 | new_state == IEEE80211_STA_NONE) |
| 715 | return mt76_sta_add(dev, vif, sta); | 715 | return mt76_sta_add(dev, vif, sta); |
| 716 | 716 | ||
| 717 | if (old_state == IEEE80211_STA_AUTH && | ||
| 718 | new_state == IEEE80211_STA_ASSOC && | ||
| 719 | dev->drv->sta_assoc) | ||
| 720 | dev->drv->sta_assoc(dev, vif, sta); | ||
| 721 | |||
| 717 | if (old_state == IEEE80211_STA_NONE && | 722 | if (old_state == IEEE80211_STA_NONE && |
| 718 | new_state == IEEE80211_STA_NOTEXIST) | 723 | new_state == IEEE80211_STA_NOTEXIST) |
| 719 | mt76_sta_remove(dev, vif, sta); | 724 | mt76_sta_remove(dev, vif, sta); |
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index f55dc621e060..5dfb0601f101 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h | |||
| @@ -304,6 +304,9 @@ struct mt76_driver_ops { | |||
| 304 | int (*sta_add)(struct mt76_dev *dev, struct ieee80211_vif *vif, | 304 | int (*sta_add)(struct mt76_dev *dev, struct ieee80211_vif *vif, |
| 305 | struct ieee80211_sta *sta); | 305 | struct ieee80211_sta *sta); |
| 306 | 306 | ||
| 307 | void (*sta_assoc)(struct mt76_dev *dev, struct ieee80211_vif *vif, | ||
| 308 | struct ieee80211_sta *sta); | ||
| 309 | |||
| 307 | void (*sta_remove)(struct mt76_dev *dev, struct ieee80211_vif *vif, | 310 | void (*sta_remove)(struct mt76_dev *dev, struct ieee80211_vif *vif, |
| 308 | struct ieee80211_sta *sta); | 311 | struct ieee80211_sta *sta); |
| 309 | }; | 312 | }; |
| @@ -384,8 +387,7 @@ struct mt76_usb { | |||
| 384 | 387 | ||
| 385 | struct mt76u_mcu { | 388 | struct mt76u_mcu { |
| 386 | struct mutex mutex; | 389 | struct mutex mutex; |
| 387 | struct completion cmpl; | 390 | u8 *data; |
| 388 | struct mt76u_buf res; | ||
| 389 | u32 msg_seq; | 391 | u32 msg_seq; |
| 390 | 392 | ||
| 391 | /* multiple reads */ | 393 | /* multiple reads */ |
| @@ -729,16 +731,20 @@ static inline u8 q2ep(u8 qid) | |||
| 729 | } | 731 | } |
| 730 | 732 | ||
| 731 | static inline int | 733 | static inline int |
| 732 | mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int timeout) | 734 | mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int *actual_len, |
| 735 | int timeout) | ||
| 733 | { | 736 | { |
| 734 | struct usb_interface *intf = to_usb_interface(dev->dev); | 737 | struct usb_interface *intf = to_usb_interface(dev->dev); |
| 735 | struct usb_device *udev = interface_to_usbdev(intf); | 738 | struct usb_device *udev = interface_to_usbdev(intf); |
| 736 | struct mt76_usb *usb = &dev->usb; | 739 | struct mt76_usb *usb = &dev->usb; |
| 737 | unsigned int pipe; | 740 | unsigned int pipe; |
| 738 | int sent; | ||
| 739 | 741 | ||
| 740 | pipe = usb_sndbulkpipe(udev, usb->out_ep[MT_EP_OUT_INBAND_CMD]); | 742 | if (actual_len) |
| 741 | return usb_bulk_msg(udev, pipe, data, len, &sent, timeout); | 743 | pipe = usb_rcvbulkpipe(udev, usb->in_ep[MT_EP_IN_CMD_RESP]); |
| 744 | else | ||
| 745 | pipe = usb_sndbulkpipe(udev, usb->out_ep[MT_EP_OUT_INBAND_CMD]); | ||
| 746 | |||
| 747 | return usb_bulk_msg(udev, pipe, data, len, actual_len, timeout); | ||
| 742 | } | 748 | } |
| 743 | 749 | ||
| 744 | int mt76u_vendor_request(struct mt76_dev *dev, u8 req, | 750 | int mt76u_vendor_request(struct mt76_dev *dev, u8 req, |
| @@ -747,13 +753,6 @@ int mt76u_vendor_request(struct mt76_dev *dev, u8 req, | |||
| 747 | void mt76u_single_wr(struct mt76_dev *dev, const u8 req, | 753 | void mt76u_single_wr(struct mt76_dev *dev, const u8 req, |
| 748 | const u16 offset, const u32 val); | 754 | const u16 offset, const u32 val); |
| 749 | int mt76u_init(struct mt76_dev *dev, struct usb_interface *intf); | 755 | int mt76u_init(struct mt76_dev *dev, struct usb_interface *intf); |
| 750 | void mt76u_deinit(struct mt76_dev *dev); | ||
| 751 | int mt76u_buf_alloc(struct mt76_dev *dev, struct mt76u_buf *buf, | ||
| 752 | int len, int data_len, gfp_t gfp); | ||
| 753 | void mt76u_buf_free(struct mt76u_buf *buf); | ||
| 754 | int mt76u_submit_buf(struct mt76_dev *dev, int dir, int index, | ||
| 755 | struct mt76u_buf *buf, gfp_t gfp, | ||
| 756 | usb_complete_t complete_fn, void *context); | ||
| 757 | int mt76u_submit_rx_buffers(struct mt76_dev *dev); | 756 | int mt76u_submit_rx_buffers(struct mt76_dev *dev); |
| 758 | int mt76u_alloc_queues(struct mt76_dev *dev); | 757 | int mt76u_alloc_queues(struct mt76_dev *dev); |
| 759 | void mt76u_stop_queues(struct mt76_dev *dev); | 758 | void mt76u_stop_queues(struct mt76_dev *dev); |
| @@ -767,8 +766,4 @@ void mt76_mcu_rx_event(struct mt76_dev *dev, struct sk_buff *skb); | |||
| 767 | struct sk_buff *mt76_mcu_get_response(struct mt76_dev *dev, | 766 | struct sk_buff *mt76_mcu_get_response(struct mt76_dev *dev, |
| 768 | unsigned long expires); | 767 | unsigned long expires); |
| 769 | 768 | ||
| 770 | void mt76u_mcu_complete_urb(struct urb *urb); | ||
| 771 | int mt76u_mcu_init_rx(struct mt76_dev *dev); | ||
| 772 | void mt76u_mcu_deinit(struct mt76_dev *dev); | ||
| 773 | |||
| 774 | #endif | 769 | #endif |
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7603/Kconfig new file mode 100644 index 000000000000..087945c3d8f3 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7603/Kconfig | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | config MT7603E | ||
| 2 | tristate "MediaTek MT7603E (PCIe) and MT76x8 WLAN support" | ||
| 3 | select MT76_CORE | ||
| 4 | depends on MAC80211 | ||
| 5 | depends on PCI | ||
| 6 | help | ||
| 7 | This adds support for MT7603E wireless PCIe devices and the WLAN core on | ||
| 8 | MT7628/MT7688 SoC devices | ||
| 9 | |||
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/Makefile b/drivers/net/wireless/mediatek/mt76/mt7603/Makefile new file mode 100644 index 000000000000..d95a30421c62 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7603/Makefile | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | obj-$(CONFIG_MT7603E) += mt7603e.o | ||
| 2 | |||
| 3 | mt7603e-y := \ | ||
| 4 | pci.o soc.o main.o init.o mcu.o \ | ||
| 5 | core.o dma.o mac.o eeprom.o \ | ||
| 6 | beacon.o debugfs.o | ||
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c b/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c new file mode 100644 index 000000000000..afcd86f735b4 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7603/beacon.c | |||
| @@ -0,0 +1,186 @@ | |||
| 1 | /* SPDX-License-Identifier: ISC */ | ||
| 2 | |||
| 3 | #include "mt7603.h" | ||
| 4 | |||
| 5 | struct beacon_bc_data { | ||
| 6 | struct mt7603_dev *dev; | ||
| 7 | struct sk_buff_head q; | ||
| 8 | struct sk_buff *tail[MT7603_MAX_INTERFACES]; | ||
| 9 | int count[MT7603_MAX_INTERFACES]; | ||
| 10 | }; | ||
| 11 | |||
| 12 | static void | ||
| 13 | mt7603_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) | ||
| 14 | { | ||
| 15 | struct mt7603_dev *dev = (struct mt7603_dev *)priv; | ||
| 16 | struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv; | ||
| 17 | struct sk_buff *skb = NULL; | ||
| 18 | |||
| 19 | if (!(dev->beacon_mask & BIT(mvif->idx))) | ||
| 20 | return; | ||
| 21 | |||
| 22 | skb = ieee80211_beacon_get(mt76_hw(dev), vif); | ||
| 23 | if (!skb) | ||
| 24 | return; | ||
| 25 | |||
| 26 | mt76_dma_tx_queue_skb(&dev->mt76, &dev->mt76.q_tx[MT_TXQ_BEACON], skb, | ||
| 27 | &mvif->sta.wcid, NULL); | ||
| 28 | |||
| 29 | spin_lock_bh(&dev->ps_lock); | ||
| 30 | mt76_wr(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY | | ||
| 31 | FIELD_PREP(MT_DMA_FQCR0_TARGET_WCID, mvif->sta.wcid.idx) | | ||
| 32 | FIELD_PREP(MT_DMA_FQCR0_TARGET_QID, | ||
| 33 | dev->mt76.q_tx[MT_TXQ_CAB].hw_idx) | | ||
| 34 | FIELD_PREP(MT_DMA_FQCR0_DEST_PORT_ID, 3) | | ||
| 35 | FIELD_PREP(MT_DMA_FQCR0_DEST_QUEUE_ID, 8)); | ||
| 36 | |||
| 37 | if (!mt76_poll(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY, 0, 5000)) | ||
| 38 | dev->beacon_check = MT7603_WATCHDOG_TIMEOUT; | ||
| 39 | |||
| 40 | spin_unlock_bh(&dev->ps_lock); | ||
| 41 | } | ||
| 42 | |||
| 43 | static void | ||
| 44 | mt7603_add_buffered_bc(void *priv, u8 *mac, struct ieee80211_vif *vif) | ||
| 45 | { | ||
| 46 | struct beacon_bc_data *data = priv; | ||
| 47 | struct mt7603_dev *dev = data->dev; | ||
| 48 | struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv; | ||
| 49 | struct ieee80211_tx_info *info; | ||
| 50 | struct sk_buff *skb; | ||
| 51 | |||
| 52 | if (!(dev->beacon_mask & BIT(mvif->idx))) | ||
| 53 | return; | ||
| 54 | |||
| 55 | skb = ieee80211_get_buffered_bc(mt76_hw(dev), vif); | ||
| 56 | if (!skb) | ||
| 57 | return; | ||
| 58 | |||
| 59 | info = IEEE80211_SKB_CB(skb); | ||
| 60 | info->control.vif = vif; | ||
| 61 | info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ; | ||
| 62 | mt76_skb_set_moredata(skb, true); | ||
| 63 | __skb_queue_tail(&data->q, skb); | ||
| 64 | data->tail[mvif->idx] = skb; | ||
| 65 | data->count[mvif->idx]++; | ||
| 66 | } | ||
| 67 | |||
| 68 | void mt7603_pre_tbtt_tasklet(unsigned long arg) | ||
| 69 | { | ||
| 70 | struct mt7603_dev *dev = (struct mt7603_dev *)arg; | ||
| 71 | struct mt76_queue *q; | ||
| 72 | struct beacon_bc_data data = {}; | ||
| 73 | struct sk_buff *skb; | ||
| 74 | int i, nframes; | ||
| 75 | |||
| 76 | data.dev = dev; | ||
| 77 | __skb_queue_head_init(&data.q); | ||
| 78 | |||
| 79 | q = &dev->mt76.q_tx[MT_TXQ_BEACON]; | ||
| 80 | spin_lock_bh(&q->lock); | ||
| 81 | ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev), | ||
| 82 | IEEE80211_IFACE_ITER_RESUME_ALL, | ||
| 83 | mt7603_update_beacon_iter, dev); | ||
| 84 | mt76_queue_kick(dev, q); | ||
| 85 | spin_unlock_bh(&q->lock); | ||
| 86 | |||
| 87 | /* Flush all previous CAB queue packets */ | ||
| 88 | mt76_wr(dev, MT_WF_ARB_CAB_FLUSH, GENMASK(30, 16) | BIT(0)); | ||
| 89 | |||
| 90 | mt76_queue_tx_cleanup(dev, MT_TXQ_CAB, false); | ||
| 91 | |||
| 92 | mt76_csa_check(&dev->mt76); | ||
| 93 | if (dev->mt76.csa_complete) | ||
| 94 | goto out; | ||
| 95 | |||
| 96 | q = &dev->mt76.q_tx[MT_TXQ_CAB]; | ||
| 97 | do { | ||
| 98 | nframes = skb_queue_len(&data.q); | ||
| 99 | ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev), | ||
| 100 | IEEE80211_IFACE_ITER_RESUME_ALL, | ||
| 101 | mt7603_add_buffered_bc, &data); | ||
| 102 | } while (nframes != skb_queue_len(&data.q) && | ||
| 103 | skb_queue_len(&data.q) < 8); | ||
| 104 | |||
| 105 | if (skb_queue_empty(&data.q)) | ||
| 106 | goto out; | ||
| 107 | |||
| 108 | for (i = 0; i < ARRAY_SIZE(data.tail); i++) { | ||
| 109 | if (!data.tail[i]) | ||
| 110 | continue; | ||
| 111 | |||
| 112 | mt76_skb_set_moredata(data.tail[i], false); | ||
| 113 | } | ||
| 114 | |||
| 115 | spin_lock_bh(&q->lock); | ||
| 116 | while ((skb = __skb_dequeue(&data.q)) != NULL) { | ||
| 117 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
| 118 | struct ieee80211_vif *vif = info->control.vif; | ||
| 119 | struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv; | ||
| 120 | |||
| 121 | mt76_dma_tx_queue_skb(&dev->mt76, q, skb, &mvif->sta.wcid, | ||
| 122 | NULL); | ||
| 123 | } | ||
| 124 | mt76_queue_kick(dev, q); | ||
| 125 | spin_unlock_bh(&q->lock); | ||
| 126 | |||
| 127 | for (i = 0; i < ARRAY_SIZE(data.count); i++) | ||
| 128 | mt76_wr(dev, MT_WF_ARB_CAB_COUNT_B0_REG(i), | ||
| 129 | data.count[i] << MT_WF_ARB_CAB_COUNT_B0_SHIFT(i)); | ||
| 130 | |||
| 131 | mt76_wr(dev, MT_WF_ARB_CAB_START, | ||
| 132 | MT_WF_ARB_CAB_START_BSSn(0) | | ||
| 133 | (MT_WF_ARB_CAB_START_BSS0n(1) * | ||
| 134 | ((1 << (MT7603_MAX_INTERFACES - 1)) - 1))); | ||
| 135 | |||
| 136 | out: | ||
| 137 | mt76_queue_tx_cleanup(dev, MT_TXQ_BEACON, false); | ||
| 138 | if (dev->mt76.q_tx[MT_TXQ_BEACON].queued > | ||
| 139 | __sw_hweight8(dev->beacon_mask)) | ||
| 140 | dev->beacon_check++; | ||
| 141 | } | ||
| 142 | |||
| 143 | void mt7603_beacon_set_timer(struct mt7603_dev *dev, int idx, int intval) | ||
| 144 | { | ||
| 145 | u32 pre_tbtt = MT7603_PRE_TBTT_TIME / 64; | ||
| 146 | |||
| 147 | if (idx >= 0) { | ||
| 148 | if (intval) | ||
| 149 | dev->beacon_mask |= BIT(idx); | ||
| 150 | else | ||
| 151 | dev->beacon_mask &= ~BIT(idx); | ||
| 152 | } | ||
| 153 | |||
| 154 | if (!dev->beacon_mask || (!intval && idx < 0)) { | ||
| 155 | mt7603_irq_disable(dev, MT_INT_MAC_IRQ3); | ||
| 156 | mt76_clear(dev, MT_ARB_SCR, MT_ARB_SCR_BCNQ_OPMODE_MASK); | ||
| 157 | mt76_wr(dev, MT_HW_INT_MASK(3), 0); | ||
| 158 | return; | ||
| 159 | } | ||
| 160 | |||
| 161 | dev->beacon_int = intval; | ||
| 162 | mt76_wr(dev, MT_TBTT, | ||
| 163 | FIELD_PREP(MT_TBTT_PERIOD, intval) | MT_TBTT_CAL_ENABLE); | ||
| 164 | |||
| 165 | mt76_wr(dev, MT_TBTT_TIMER_CFG, 0x99); /* start timer */ | ||
| 166 | |||
| 167 | mt76_rmw_field(dev, MT_ARB_SCR, MT_ARB_SCR_BCNQ_OPMODE_MASK, | ||
| 168 | MT_BCNQ_OPMODE_AP); | ||
| 169 | mt76_clear(dev, MT_ARB_SCR, MT_ARB_SCR_TBTT_BCN_PRIO); | ||
| 170 | mt76_set(dev, MT_ARB_SCR, MT_ARB_SCR_TBTT_BCAST_PRIO); | ||
| 171 | |||
| 172 | mt76_wr(dev, MT_PRE_TBTT, pre_tbtt); | ||
| 173 | |||
| 174 | mt76_set(dev, MT_HW_INT_MASK(3), | ||
| 175 | MT_HW_INT3_PRE_TBTT0 | MT_HW_INT3_TBTT0); | ||
| 176 | |||
| 177 | mt76_set(dev, MT_WF_ARB_BCN_START, | ||
| 178 | MT_WF_ARB_BCN_START_BSSn(0) | | ||
| 179 | ((dev->beacon_mask >> 1) * MT_WF_ARB_BCN_START_BSS0n(1))); | ||
| 180 | mt7603_irq_enable(dev, MT_INT_MAC_IRQ3); | ||
| 181 | |||
| 182 | if (dev->beacon_mask & ~BIT(0)) | ||
| 183 | mt76_set(dev, MT_LPON_SBTOR(0), MT_LPON_SBTOR_SUB_BSS_EN); | ||
| 184 | else | ||
| 185 | mt76_clear(dev, MT_LPON_SBTOR(0), MT_LPON_SBTOR_SUB_BSS_EN); | ||
| 186 | } | ||
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/core.c b/drivers/net/wireless/mediatek/mt76/mt7603/core.c new file mode 100644 index 000000000000..1086dcd376a0 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7603/core.c | |||
| @@ -0,0 +1,73 @@ | |||
| 1 | /* SPDX-License-Identifier: ISC */ | ||
| 2 | |||
| 3 | #include "mt7603.h" | ||
| 4 | |||
| 5 | void mt7603_set_irq_mask(struct mt7603_dev *dev, u32 clear, u32 set) | ||
| 6 | { | ||
| 7 | unsigned long flags; | ||
| 8 | |||
| 9 | spin_lock_irqsave(&dev->mt76.mmio.irq_lock, flags); | ||
| 10 | dev->mt76.mmio.irqmask &= ~clear; | ||
| 11 | dev->mt76.mmio.irqmask |= set; | ||
| 12 | mt76_wr(dev, MT_INT_MASK_CSR, dev->mt76.mmio.irqmask); | ||
| 13 | spin_unlock_irqrestore(&dev->mt76.mmio.irq_lock, flags); | ||
| 14 | } | ||
| 15 | |||
| 16 | void mt7603_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q) | ||
| 17 | { | ||
| 18 | struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); | ||
| 19 | |||
| 20 | mt7603_irq_enable(dev, MT_INT_RX_DONE(q)); | ||
| 21 | } | ||
| 22 | |||
| 23 | irqreturn_t mt7603_irq_handler(int irq, void *dev_instance) | ||
| 24 | { | ||
| 25 | struct mt7603_dev *dev = dev_instance; | ||
| 26 | u32 intr; | ||
| 27 | |||
| 28 | intr = mt76_rr(dev, MT_INT_SOURCE_CSR); | ||
| 29 | mt76_wr(dev, MT_INT_SOURCE_CSR, intr); | ||
| 30 | |||
| 31 | if (!test_bit(MT76_STATE_INITIALIZED, &dev->mt76.state)) | ||
| 32 | return IRQ_NONE; | ||
| 33 | |||
| 34 | intr &= dev->mt76.mmio.irqmask; | ||
| 35 | |||
| 36 | if (intr & MT_INT_MAC_IRQ3) { | ||
| 37 | u32 hwintr = mt76_rr(dev, MT_HW_INT_STATUS(3)); | ||
| 38 | |||
| 39 | mt76_wr(dev, MT_HW_INT_STATUS(3), hwintr); | ||
| 40 | if (hwintr & MT_HW_INT3_PRE_TBTT0) | ||
| 41 | tasklet_schedule(&dev->pre_tbtt_tasklet); | ||
| 42 | |||
| 43 | if ((hwintr & MT_HW_INT3_TBTT0) && dev->mt76.csa_complete) | ||
| 44 | mt76_csa_finish(&dev->mt76); | ||
| 45 | } | ||
| 46 | |||
| 47 | if (intr & MT_INT_TX_DONE_ALL) { | ||
| 48 | mt7603_irq_disable(dev, MT_INT_TX_DONE_ALL); | ||
| 49 | tasklet_schedule(&dev->tx_tasklet); | ||
| 50 | } | ||
| 51 | |||
| 52 | if (intr & MT_INT_RX_DONE(0)) { | ||
| 53 | mt7603_irq_disable(dev, MT_INT_RX_DONE(0)); | ||
| 54 | napi_schedule(&dev->mt76.napi[0]); | ||
| 55 | } | ||
| 56 | |||
| 57 | if (intr & MT_INT_RX_DONE(1)) { | ||
| 58 | mt7603_irq_disable(dev, MT_INT_RX_DONE(1)); | ||
| 59 | napi_schedule(&dev->mt76.napi[1]); | ||
| 60 | } | ||
| 61 | |||
| 62 | return IRQ_HANDLED; | ||
| 63 | } | ||
| 64 | |||
| 65 | u32 mt7603_reg_map(struct mt7603_dev *dev, u32 addr) | ||
| 66 | { | ||
| 67 | u32 base = addr & GENMASK(31, 19); | ||
| 68 | u32 offset = addr & GENMASK(18, 0); | ||
| 69 | |||
| 70 | dev->bus_ops->wr(&dev->mt76, MT_MCU_PCIE_REMAP_2, base); | ||
| 71 | |||
| 72 | return MT_PCIE_REMAP_BASE_2 + offset; | ||
| 73 | } | ||
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7603/debugfs.c new file mode 100644 index 000000000000..f8b3b6ab6297 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7603/debugfs.c | |||
| @@ -0,0 +1,56 @@ | |||
| 1 | /* SPDX-License-Identifier: ISC */ | ||
| 2 | |||
| 3 | #include "mt7603.h" | ||
| 4 | |||
| 5 | static int | ||
| 6 | mt7603_reset_read(struct seq_file *s, void *data) | ||
| 7 | { | ||
| 8 | struct mt7603_dev *dev = dev_get_drvdata(s->private); | ||
| 9 | static const char * const reset_cause_str[] = { | ||
| 10 | [RESET_CAUSE_TX_HANG] = "TX hang", | ||
| 11 | [RESET_CAUSE_TX_BUSY] = "TX DMA busy stuck", | ||
| 12 | [RESET_CAUSE_RX_BUSY] = "RX DMA busy stuck", | ||
| 13 | [RESET_CAUSE_RX_PSE_BUSY] = "RX PSE busy stuck", | ||
| 14 | [RESET_CAUSE_BEACON_STUCK] = "Beacon stuck", | ||
| 15 | [RESET_CAUSE_MCU_HANG] = "MCU hang", | ||
| 16 | [RESET_CAUSE_RESET_FAILED] = "PSE reset failed", | ||
| 17 | }; | ||
| 18 | int i; | ||
| 19 | |||
| 20 | for (i = 0; i < ARRAY_SIZE(reset_cause_str); i++) { | ||
| 21 | if (!reset_cause_str[i]) | ||
| 22 | continue; | ||
| 23 | |||
| 24 | seq_printf(s, "%20s: %u\n", reset_cause_str[i], | ||
| 25 | dev->reset_cause[i]); | ||
| 26 | } | ||
| 27 | |||
| 28 | return 0; | ||
| 29 | } | ||
| 30 | |||
| 31 | static int | ||
| 32 | mt7603_radio_read(struct seq_file *s, void *data) | ||
| 33 | { | ||
| 34 | struct mt7603_dev *dev = dev_get_drvdata(s->private); | ||
| 35 | |||
| 36 | seq_printf(s, "Sensitivity: %d\n", dev->sensitivity); | ||
| 37 | seq_printf(s, "False CCA: ofdm=%d cck=%d\n", | ||
| 38 | dev->false_cca_ofdm, dev->false_cca_cck); | ||
| 39 | |||
| 40 | return 0; | ||
| 41 | } | ||
| 42 | |||
| 43 | void mt7603_init_debugfs(struct mt7603_dev *dev) | ||
| 44 | { | ||
| 45 | struct dentry *dir; | ||
| 46 | |||
| 47 | dir = mt76_register_debugfs(&dev->mt76); | ||
| 48 | if (!dir) | ||
| 49 | return; | ||
| 50 | |||
| 51 | debugfs_create_u32("reset_test", 0600, dir, &dev->reset_test); | ||
| 52 | debugfs_create_devm_seqfile(dev->mt76.dev, "reset", dir, | ||
| 53 | mt7603_reset_read); | ||
| 54 | debugfs_create_devm_seqfile(dev->mt76.dev, "radio", dir, | ||
| 55 | mt7603_radio_read); | ||
| 56 | } | ||
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c new file mode 100644 index 000000000000..d69e82c66ab2 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c | |||
| @@ -0,0 +1,215 @@ | |||
| 1 | /* SPDX-License-Identifier: ISC */ | ||
| 2 | |||
| 3 | #include "mt7603.h" | ||
| 4 | #include "mac.h" | ||
| 5 | #include "../dma.h" | ||
| 6 | |||
| 7 | static int | ||
| 8 | mt7603_init_tx_queue(struct mt7603_dev *dev, struct mt76_queue *q, | ||
| 9 | int idx, int n_desc) | ||
| 10 | { | ||
| 11 | int ret; | ||
| 12 | |||
| 13 | q->hw_idx = idx; | ||
| 14 | q->regs = dev->mt76.mmio.regs + MT_TX_RING_BASE + idx * MT_RING_SIZE; | ||
| 15 | q->ndesc = n_desc; | ||
| 16 | |||
| 17 | ret = mt76_queue_alloc(dev, q); | ||
| 18 | if (ret) | ||
| 19 | return ret; | ||
| 20 | |||
| 21 | mt7603_irq_enable(dev, MT_INT_TX_DONE(idx)); | ||
| 22 | |||
| 23 | return 0; | ||
| 24 | } | ||
| 25 | |||
| 26 | static void | ||
| 27 | mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb) | ||
| 28 | { | ||
| 29 | __le32 *txd = (__le32 *)skb->data; | ||
| 30 | struct mt7603_sta *msta; | ||
| 31 | struct mt76_wcid *wcid; | ||
| 32 | int idx; | ||
| 33 | u32 val; | ||
| 34 | |||
| 35 | if (skb->len < sizeof(MT_TXD_SIZE) + sizeof(struct ieee80211_hdr)) | ||
| 36 | goto free; | ||
| 37 | |||
| 38 | val = le32_to_cpu(txd[1]); | ||
| 39 | idx = FIELD_GET(MT_TXD1_WLAN_IDX, val); | ||
| 40 | skb->priority = FIELD_GET(MT_TXD1_TID, val); | ||
| 41 | |||
| 42 | if (idx >= MT7603_WTBL_STA - 1) | ||
| 43 | goto free; | ||
| 44 | |||
| 45 | wcid = rcu_dereference(dev->mt76.wcid[idx]); | ||
| 46 | if (!wcid) | ||
| 47 | goto free; | ||
| 48 | |||
| 49 | msta = container_of(wcid, struct mt7603_sta, wcid); | ||
| 50 | val = le32_to_cpu(txd[0]); | ||
| 51 | skb_set_queue_mapping(skb, FIELD_GET(MT_TXD0_Q_IDX, val)); | ||
| 52 | |||
| 53 | spin_lock_bh(&dev->ps_lock); | ||
| 54 | __skb_queue_tail(&msta->psq, skb); | ||
| 55 | if (skb_queue_len(&msta->psq) >= 64) { | ||
| 56 | skb = __skb_dequeue(&msta->psq); | ||
| 57 | dev_kfree_skb(skb); | ||
| 58 | } | ||
| 59 | spin_unlock_bh(&dev->ps_lock); | ||
| 60 | return; | ||
| 61 | |||
| 62 | free: | ||
| 63 | dev_kfree_skb(skb); | ||
| 64 | } | ||
| 65 | |||
| 66 | void mt7603_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, | ||
| 67 | struct sk_buff *skb) | ||
| 68 | { | ||
| 69 | struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); | ||
| 70 | __le32 *rxd = (__le32 *)skb->data; | ||
| 71 | __le32 *end = (__le32 *)&skb->data[skb->len]; | ||
| 72 | enum rx_pkt_type type; | ||
| 73 | |||
| 74 | type = FIELD_GET(MT_RXD0_PKT_TYPE, le32_to_cpu(rxd[0])); | ||
| 75 | |||
| 76 | if (q == MT_RXQ_MCU) { | ||
| 77 | if (type == PKT_TYPE_RX_EVENT) | ||
| 78 | mt76_mcu_rx_event(&dev->mt76, skb); | ||
| 79 | else | ||
| 80 | mt7603_rx_loopback_skb(dev, skb); | ||
| 81 | return; | ||
| 82 | } | ||
| 83 | |||
| 84 | switch (type) { | ||
| 85 | case PKT_TYPE_TXS: | ||
| 86 | for (rxd++; rxd + 5 <= end; rxd += 5) | ||
| 87 | mt7603_mac_add_txs(dev, rxd); | ||
| 88 | dev_kfree_skb(skb); | ||
| 89 | break; | ||
| 90 | case PKT_TYPE_RX_EVENT: | ||
| 91 | mt76_mcu_rx_event(&dev->mt76, skb); | ||
| 92 | return; | ||
| 93 | case PKT_TYPE_NORMAL: | ||
| 94 | if (mt7603_mac_fill_rx(dev, skb) == 0) { | ||
| 95 | mt76_rx(&dev->mt76, q, skb); | ||
| 96 | return; | ||
| 97 | } | ||
| 98 | /* fall through */ | ||
| 99 | default: | ||
| 100 | dev_kfree_skb(skb); | ||
| 101 | break; | ||
| 102 | } | ||
| 103 | } | ||
| 104 | |||
| 105 | static int | ||
| 106 | mt7603_init_rx_queue(struct mt7603_dev *dev, struct mt76_queue *q, | ||
| 107 | int idx, int n_desc, int bufsize) | ||
| 108 | { | ||
| 109 | int ret; | ||
| 110 | |||
| 111 | q->regs = dev->mt76.mmio.regs + MT_RX_RING_BASE + idx * MT_RING_SIZE; | ||
| 112 | q->ndesc = n_desc; | ||
| 113 | q->buf_size = bufsize; | ||
| 114 | |||
| 115 | ret = mt76_queue_alloc(dev, q); | ||
| 116 | if (ret) | ||
| 117 | return ret; | ||
| 118 | |||
| 119 | mt7603_irq_enable(dev, MT_INT_RX_DONE(idx)); | ||
| 120 | |||
| 121 | return 0; | ||
| 122 | } | ||
| 123 | |||
| 124 | static void | ||
| 125 | mt7603_tx_tasklet(unsigned long data) | ||
| 126 | { | ||
| 127 | struct mt7603_dev *dev = (struct mt7603_dev *)data; | ||
| 128 | int i; | ||
| 129 | |||
| 130 | dev->tx_dma_check = 0; | ||
| 131 | for (i = MT_TXQ_MCU; i >= 0; i--) | ||
| 132 | mt76_queue_tx_cleanup(dev, i, false); | ||
| 133 | |||
| 134 | mt7603_irq_enable(dev, MT_INT_TX_DONE_ALL); | ||
| 135 | } | ||
| 136 | |||
| 137 | int mt7603_dma_init(struct mt7603_dev *dev) | ||
| 138 | { | ||
| 139 | static const u8 wmm_queue_map[] = { | ||
| 140 | [IEEE80211_AC_BK] = 0, | ||
| 141 | [IEEE80211_AC_BE] = 1, | ||
| 142 | [IEEE80211_AC_VI] = 2, | ||
| 143 | [IEEE80211_AC_VO] = 3, | ||
| 144 | }; | ||
| 145 | int ret; | ||
| 146 | int i; | ||
| 147 | |||
| 148 | mt76_dma_attach(&dev->mt76); | ||
| 149 | |||
| 150 | init_waitqueue_head(&dev->mt76.mmio.mcu.wait); | ||
| 151 | skb_queue_head_init(&dev->mt76.mmio.mcu.res_q); | ||
| 152 | |||
| 153 | tasklet_init(&dev->tx_tasklet, mt7603_tx_tasklet, (unsigned long)dev); | ||
| 154 | |||
| 155 | mt76_clear(dev, MT_WPDMA_GLO_CFG, | ||
| 156 | MT_WPDMA_GLO_CFG_TX_DMA_EN | | ||
| 157 | MT_WPDMA_GLO_CFG_RX_DMA_EN | | ||
| 158 | MT_WPDMA_GLO_CFG_DMA_BURST_SIZE | | ||
| 159 | MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE); | ||
| 160 | |||
| 161 | mt76_wr(dev, MT_WPDMA_RST_IDX, ~0); | ||
| 162 | mt7603_pse_client_reset(dev); | ||
| 163 | |||
| 164 | for (i = 0; i < ARRAY_SIZE(wmm_queue_map); i++) { | ||
| 165 | ret = mt7603_init_tx_queue(dev, &dev->mt76.q_tx[i], | ||
| 166 | wmm_queue_map[i], | ||
| 167 | MT_TX_RING_SIZE); | ||
| 168 | if (ret) | ||
| 169 | return ret; | ||
| 170 | } | ||
| 171 | |||
| 172 | ret = mt7603_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_PSD], | ||
| 173 | MT_TX_HW_QUEUE_MGMT, MT_TX_RING_SIZE); | ||
| 174 | if (ret) | ||
| 175 | return ret; | ||
| 176 | |||
| 177 | ret = mt7603_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_MCU], | ||
| 178 | MT_TX_HW_QUEUE_MCU, MT_MCU_RING_SIZE); | ||
| 179 | if (ret) | ||
| 180 | return ret; | ||
| 181 | |||
| 182 | ret = mt7603_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_BEACON], | ||
| 183 | MT_TX_HW_QUEUE_BCN, MT_MCU_RING_SIZE); | ||
| 184 | if (ret) | ||
| 185 | return ret; | ||
| 186 | |||
| 187 | ret = mt7603_init_tx_queue(dev, &dev->mt76.q_tx[MT_TXQ_CAB], | ||
| 188 | MT_TX_HW_QUEUE_BMC, MT_MCU_RING_SIZE); | ||
| 189 | if (ret) | ||
| 190 | return ret; | ||
| 191 | |||
| 192 | ret = mt7603_init_rx_queue(dev, &dev->mt76.q_rx[MT_RXQ_MCU], 1, | ||
| 193 | MT_MCU_RING_SIZE, MT_RX_BUF_SIZE); | ||
| 194 | if (ret) | ||
| 195 | return ret; | ||
| 196 | |||
| 197 | ret = mt7603_init_rx_queue(dev, &dev->mt76.q_rx[MT_RXQ_MAIN], 0, | ||
| 198 | MT7603_RX_RING_SIZE, MT_RX_BUF_SIZE); | ||
| 199 | if (ret) | ||
| 200 | return ret; | ||
| 201 | |||
| 202 | mt76_wr(dev, MT_DELAY_INT_CFG, 0); | ||
| 203 | return mt76_init_queues(dev); | ||
| 204 | } | ||
| 205 | |||
| 206 | void mt7603_dma_cleanup(struct mt7603_dev *dev) | ||
| 207 | { | ||
| 208 | mt76_clear(dev, MT_WPDMA_GLO_CFG, | ||
| 209 | MT_WPDMA_GLO_CFG_TX_DMA_EN | | ||
| 210 | MT_WPDMA_GLO_CFG_RX_DMA_EN | | ||
| 211 | MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE); | ||
| 212 | |||
| 213 | tasklet_kill(&dev->tx_tasklet); | ||
| 214 | mt76_dma_cleanup(&dev->mt76); | ||
| 215 | } | ||
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.c new file mode 100644 index 000000000000..8c120e4461b0 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.c | |||
| @@ -0,0 +1,168 @@ | |||
| 1 | /* SPDX-License-Identifier: ISC */ | ||
| 2 | |||
| 3 | #include "mt7603.h" | ||
| 4 | #include "eeprom.h" | ||
| 5 | |||
| 6 | static int | ||
| 7 | mt7603_efuse_read(struct mt7603_dev *dev, u32 base, u16 addr, u8 *data) | ||
| 8 | { | ||
| 9 | u32 val; | ||
| 10 | int i; | ||
| 11 | |||
| 12 | val = mt76_rr(dev, base + MT_EFUSE_CTRL); | ||
| 13 | val &= ~(MT_EFUSE_CTRL_AIN | | ||
| 14 | MT_EFUSE_CTRL_MODE); | ||
| 15 | val |= FIELD_PREP(MT_EFUSE_CTRL_AIN, addr & ~0xf); | ||
| 16 | val |= MT_EFUSE_CTRL_KICK; | ||
| 17 | mt76_wr(dev, base + MT_EFUSE_CTRL, val); | ||
| 18 | |||
| 19 | if (!mt76_poll(dev, base + MT_EFUSE_CTRL, MT_EFUSE_CTRL_KICK, 0, 1000)) | ||
| 20 | return -ETIMEDOUT; | ||
| 21 | |||
| 22 | udelay(2); | ||
| 23 | |||
| 24 | val = mt76_rr(dev, base + MT_EFUSE_CTRL); | ||
| 25 | if ((val & MT_EFUSE_CTRL_AOUT) == MT_EFUSE_CTRL_AOUT || | ||
| 26 | WARN_ON_ONCE(!(val & MT_EFUSE_CTRL_VALID))) { | ||
| 27 | memset(data, 0xff, 16); | ||
| 28 | return 0; | ||
| 29 | } | ||
| 30 | |||
| 31 | for (i = 0; i < 4; i++) { | ||
| 32 | val = mt76_rr(dev, base + MT_EFUSE_RDATA(i)); | ||
| 33 | put_unaligned_le32(val, data + 4 * i); | ||
| 34 | } | ||
| 35 | |||
| 36 | return 0; | ||
| 37 | } | ||
| 38 | |||
| 39 | static int | ||
| 40 | mt7603_efuse_init(struct mt7603_dev *dev) | ||
| 41 | { | ||
| 42 | u32 base = mt7603_reg_map(dev, MT_EFUSE_BASE); | ||
| 43 | int len = MT7603_EEPROM_SIZE; | ||
| 44 | void *buf; | ||
| 45 | int ret, i; | ||
| 46 | |||
| 47 | if (mt76_rr(dev, base + MT_EFUSE_BASE_CTRL) & MT_EFUSE_BASE_CTRL_EMPTY) | ||
| 48 | return 0; | ||
| 49 | |||
| 50 | dev->mt76.otp.data = devm_kzalloc(dev->mt76.dev, len, GFP_KERNEL); | ||
| 51 | dev->mt76.otp.size = len; | ||
| 52 | if (!dev->mt76.otp.data) | ||
| 53 | return -ENOMEM; | ||
| 54 | |||
| 55 | buf = dev->mt76.otp.data; | ||
| 56 | for (i = 0; i + 16 <= len; i += 16) { | ||
| 57 | ret = mt7603_efuse_read(dev, base, i, buf + i); | ||
| 58 | if (ret) | ||
| 59 | return ret; | ||
| 60 | } | ||
| 61 | |||
| 62 | return 0; | ||
| 63 | } | ||
| 64 | |||
| 65 | static bool | ||
| 66 | mt7603_has_cal_free_data(struct mt7603_dev *dev, u8 *efuse) | ||
| 67 | { | ||
| 68 | if (!efuse[MT_EE_TEMP_SENSOR_CAL]) | ||
| 69 | return false; | ||
| 70 | |||
| 71 | if (get_unaligned_le16(efuse + MT_EE_TX_POWER_0_START_2G) == 0) | ||
| 72 | return false; | ||
| 73 | |||
| 74 | if (get_unaligned_le16(efuse + MT_EE_TX_POWER_1_START_2G) == 0) | ||
| 75 | return false; | ||
| 76 | |||
| 77 | if (!efuse[MT_EE_CP_FT_VERSION]) | ||
| 78 | return false; | ||
| 79 | |||
| 80 | if (!efuse[MT_EE_XTAL_FREQ_OFFSET]) | ||
| 81 | return false; | ||
| 82 | |||
| 83 | if (!efuse[MT_EE_XTAL_WF_RFCAL]) | ||
| 84 | return false; | ||
| 85 | |||
| 86 | return true; | ||
| 87 | } | ||
| 88 | |||
| 89 | static void | ||
| 90 | mt7603_apply_cal_free_data(struct mt7603_dev *dev, u8 *efuse) | ||
| 91 | { | ||
| 92 | static const u8 cal_free_bytes[] = { | ||
| 93 | MT_EE_TEMP_SENSOR_CAL, | ||
| 94 | MT_EE_CP_FT_VERSION, | ||
| 95 | MT_EE_XTAL_FREQ_OFFSET, | ||
| 96 | MT_EE_XTAL_WF_RFCAL, | ||
| 97 | /* Skip for MT7628 */ | ||
| 98 | MT_EE_TX_POWER_0_START_2G, | ||
| 99 | MT_EE_TX_POWER_0_START_2G + 1, | ||
| 100 | MT_EE_TX_POWER_1_START_2G, | ||
| 101 | MT_EE_TX_POWER_1_START_2G + 1, | ||
| 102 | }; | ||
| 103 | u8 *eeprom = dev->mt76.eeprom.data; | ||
| 104 | int n = ARRAY_SIZE(cal_free_bytes); | ||
| 105 | int i; | ||
| 106 | |||
| 107 | if (!mt7603_has_cal_free_data(dev, efuse)) | ||
| 108 | return; | ||
| 109 | |||
| 110 | if (is_mt7628(dev)) | ||
| 111 | n -= 4; | ||
| 112 | |||
| 113 | for (i = 0; i < n; i++) { | ||
| 114 | int offset = cal_free_bytes[i]; | ||
| 115 | |||
| 116 | eeprom[offset] = efuse[offset]; | ||
| 117 | } | ||
| 118 | } | ||
| 119 | |||
| 120 | static int | ||
| 121 | mt7603_eeprom_load(struct mt7603_dev *dev) | ||
| 122 | { | ||
| 123 | int ret; | ||
| 124 | |||
| 125 | ret = mt76_eeprom_init(&dev->mt76, MT7603_EEPROM_SIZE); | ||
| 126 | if (ret < 0) | ||
| 127 | return ret; | ||
| 128 | |||
| 129 | return mt7603_efuse_init(dev); | ||
| 130 | } | ||
| 131 | |||
| 132 | static int mt7603_check_eeprom(struct mt76_dev *dev) | ||
| 133 | { | ||
| 134 | u16 val = get_unaligned_le16(dev->eeprom.data); | ||
| 135 | |||
| 136 | switch (val) { | ||
| 137 | case 0x7628: | ||
| 138 | case 0x7603: | ||
| 139 | return 0; | ||
| 140 | default: | ||
| 141 | return -EINVAL; | ||
| 142 | } | ||
| 143 | } | ||
| 144 | |||
| 145 | int mt7603_eeprom_init(struct mt7603_dev *dev) | ||
| 146 | { | ||
| 147 | int ret; | ||
| 148 | |||
| 149 | ret = mt7603_eeprom_load(dev); | ||
| 150 | if (ret < 0) | ||
| 151 | return ret; | ||
| 152 | |||
| 153 | if (dev->mt76.otp.data) { | ||
| 154 | if (mt7603_check_eeprom(&dev->mt76) == 0) | ||
| 155 | mt7603_apply_cal_free_data(dev, dev->mt76.otp.data); | ||
| 156 | else | ||
| 157 | memcpy(dev->mt76.eeprom.data, dev->mt76.otp.data, | ||
| 158 | MT7603_EEPROM_SIZE); | ||
| 159 | } | ||
| 160 | |||
| 161 | dev->mt76.cap.has_2ghz = true; | ||
| 162 | memcpy(dev->mt76.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR, | ||
| 163 | ETH_ALEN); | ||
| 164 | |||
| 165 | mt76_eeprom_override(&dev->mt76); | ||
| 166 | |||
| 167 | return 0; | ||
| 168 | } | ||
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.h new file mode 100644 index 000000000000..f27b99b7e359 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7603/eeprom.h | |||
| @@ -0,0 +1,86 @@ | |||
| 1 | /* SPDX-License-Identifier: ISC */ | ||
| 2 | |||
| 3 | #ifndef __MT7603_EEPROM_H | ||
| 4 | #define __MT7603_EEPROM_H | ||
| 5 | |||
| 6 | #include "mt7603.h" | ||
| 7 | |||
| 8 | enum mt7603_eeprom_field { | ||
| 9 | MT_EE_CHIP_ID = 0x000, | ||
| 10 | MT_EE_VERSION = 0x002, | ||
| 11 | MT_EE_MAC_ADDR = 0x004, | ||
| 12 | MT_EE_NIC_CONF_0 = 0x034, | ||
| 13 | MT_EE_NIC_CONF_1 = 0x036, | ||
| 14 | MT_EE_NIC_CONF_2 = 0x042, | ||
| 15 | |||
| 16 | MT_EE_XTAL_TRIM_1 = 0x03a, | ||
| 17 | |||
| 18 | MT_EE_RSSI_OFFSET_2G = 0x046, | ||
| 19 | MT_EE_WIFI_RF_SETTING = 0x048, | ||
| 20 | MT_EE_RSSI_OFFSET_5G = 0x04a, | ||
| 21 | |||
| 22 | MT_EE_TX_POWER_DELTA_BW40 = 0x050, | ||
| 23 | MT_EE_TX_POWER_DELTA_BW80 = 0x052, | ||
| 24 | |||
| 25 | MT_EE_TX_POWER_EXT_PA_5G = 0x054, | ||
| 26 | |||
| 27 | MT_EE_TEMP_SENSOR_CAL = 0x055, | ||
| 28 | |||
| 29 | MT_EE_TX_POWER_0_START_2G = 0x056, | ||
| 30 | MT_EE_TX_POWER_1_START_2G = 0x05c, | ||
| 31 | |||
| 32 | /* used as byte arrays */ | ||
| 33 | #define MT_TX_POWER_GROUP_SIZE_5G 5 | ||
| 34 | #define MT_TX_POWER_GROUPS_5G 6 | ||
| 35 | MT_EE_TX_POWER_0_START_5G = 0x062, | ||
| 36 | |||
| 37 | MT_EE_TX_POWER_0_GRP3_TX_POWER_DELTA = 0x074, | ||
| 38 | MT_EE_TX_POWER_0_GRP4_TSSI_SLOPE = 0x076, | ||
| 39 | |||
| 40 | MT_EE_TX_POWER_1_START_5G = 0x080, | ||
| 41 | |||
| 42 | MT_EE_TX_POWER_CCK = 0x0a0, | ||
| 43 | MT_EE_TX_POWER_OFDM_2G_6M = 0x0a2, | ||
| 44 | MT_EE_TX_POWER_OFDM_2G_24M = 0x0a4, | ||
| 45 | MT_EE_TX_POWER_OFDM_2G_54M = 0x0a6, | ||
| 46 | MT_EE_TX_POWER_HT_BPSK_QPSK = 0x0a8, | ||
| 47 | MT_EE_TX_POWER_HT_16_64_QAM = 0x0aa, | ||
| 48 | MT_EE_TX_POWER_HT_64_QAM = 0x0ac, | ||
| 49 | |||
| 50 | MT_EE_ELAN_RX_MODE_GAIN = 0x0c0, | ||
| 51 | MT_EE_ELAN_RX_MODE_NF = 0x0c1, | ||
| 52 | MT_EE_ELAN_RX_MODE_P1DB = 0x0c2, | ||
| 53 | |||
| 54 | MT_EE_ELAN_BYPASS_MODE_GAIN = 0x0c3, | ||
| 55 | MT_EE_ELAN_BYPASS_MODE_NF = 0x0c4, | ||
| 56 | MT_EE_ELAN_BYPASS_MODE_P1DB = 0x0c5, | ||
| 57 | |||
| 58 | MT_EE_STEP_NUM_NEG_6_7 = 0x0c6, | ||
| 59 | MT_EE_STEP_NUM_NEG_4_5 = 0x0c8, | ||
| 60 | MT_EE_STEP_NUM_NEG_2_3 = 0x0ca, | ||
| 61 | MT_EE_STEP_NUM_NEG_0_1 = 0x0cc, | ||
| 62 | |||
| 63 | MT_EE_REF_STEP_24G = 0x0ce, | ||
| 64 | |||
| 65 | MT_EE_STEP_NUM_PLUS_1_2 = 0x0d0, | ||
| 66 | MT_EE_STEP_NUM_PLUS_3_4 = 0x0d2, | ||
| 67 | MT_EE_STEP_NUM_PLUS_5_6 = 0x0d4, | ||
| 68 | MT_EE_STEP_NUM_PLUS_7 = 0x0d6, | ||
| 69 | |||
| 70 | MT_EE_CP_FT_VERSION = 0x0f0, | ||
| 71 | |||
| 72 | MT_EE_XTAL_FREQ_OFFSET = 0x0f4, | ||
| 73 | MT_EE_XTAL_TRIM_2_COMP = 0x0f5, | ||
| 74 | MT_EE_XTAL_TRIM_3_COMP = 0x0f6, | ||
| 75 | MT_EE_XTAL_WF_RFCAL = 0x0f7, | ||
| 76 | |||
| 77 | __MT_EE_MAX | ||
| 78 | }; | ||
| 79 | |||
| 80 | enum mt7603_eeprom_source { | ||
| 81 | MT_EE_SRC_PROM, | ||
| 82 | MT_EE_SRC_EFUSE, | ||
| 83 | MT_EE_SRC_FLASH, | ||
| 84 | }; | ||
| 85 | |||
| 86 | #endif | ||
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/init.c b/drivers/net/wireless/mediatek/mt76/mt7603/init.c new file mode 100644 index 000000000000..15cc8f33b34d --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7603/init.c | |||
| @@ -0,0 +1,578 @@ | |||
| 1 | /* SPDX-License-Identifier: ISC */ | ||
| 2 | |||
| 3 | #include <linux/etherdevice.h> | ||
| 4 | #include "mt7603.h" | ||
| 5 | #include "mac.h" | ||
| 6 | #include "eeprom.h" | ||
| 7 | |||
| 8 | const struct mt76_driver_ops mt7603_drv_ops = { | ||
| 9 | .txwi_size = MT_TXD_SIZE, | ||
| 10 | .tx_prepare_skb = mt7603_tx_prepare_skb, | ||
| 11 | .tx_complete_skb = mt7603_tx_complete_skb, | ||
| 12 | .rx_skb = mt7603_queue_rx_skb, | ||
| 13 | .rx_poll_complete = mt7603_rx_poll_complete, | ||
| 14 | .sta_ps = mt7603_sta_ps, | ||
| 15 | .sta_add = mt7603_sta_add, | ||
| 16 | .sta_assoc = mt7603_sta_assoc, | ||
| 17 | .sta_remove = mt7603_sta_remove, | ||
| 18 | .update_survey = mt7603_update_channel, | ||
| 19 | }; | ||
| 20 | |||
| 21 | static void | ||
| 22 | mt7603_set_tmac_template(struct mt7603_dev *dev) | ||
| 23 | { | ||
| 24 | u32 desc[5] = { | ||
| 25 | [1] = FIELD_PREP(MT_TXD3_REM_TX_COUNT, 0xf), | ||
| 26 | [3] = MT_TXD5_SW_POWER_MGMT | ||
| 27 | }; | ||
| 28 | u32 addr; | ||
| 29 | int i; | ||
| 30 | |||
| 31 | addr = mt7603_reg_map(dev, MT_CLIENT_BASE_PHYS_ADDR); | ||
| 32 | addr += MT_CLIENT_TMAC_INFO_TEMPLATE; | ||
| 33 | for (i = 0; i < ARRAY_SIZE(desc); i++) | ||
| 34 | mt76_wr(dev, addr + 4 * i, desc[i]); | ||
| 35 | } | ||
| 36 | |||
| 37 | static void | ||
| 38 | mt7603_dma_sched_init(struct mt7603_dev *dev) | ||
| 39 | { | ||
| 40 | int page_size = 128; | ||
| 41 | int page_count; | ||
| 42 | int max_len = 1792; | ||
| 43 | int max_amsdu_pages = 4096 / page_size; | ||
| 44 | int max_mcu_len = 4096; | ||
| 45 | int max_beacon_len = 512 * 4 + max_len; | ||
| 46 | int max_mcast_pages = 4 * max_len / page_size; | ||
| 47 | int reserved_count = 0; | ||
| 48 | int beacon_pages; | ||
| 49 | int mcu_pages; | ||
| 50 | int i; | ||
| 51 | |||
| 52 | page_count = mt76_get_field(dev, MT_PSE_FC_P0, | ||
| 53 | MT_PSE_FC_P0_MAX_QUOTA); | ||
| 54 | beacon_pages = 4 * (max_beacon_len / page_size); | ||
| 55 | mcu_pages = max_mcu_len / page_size; | ||
| 56 | |||
| 57 | mt76_wr(dev, MT_PSE_FRP, | ||
| 58 | FIELD_PREP(MT_PSE_FRP_P0, 7) | | ||
| 59 | FIELD_PREP(MT_PSE_FRP_P1, 6) | | ||
| 60 | FIELD_PREP(MT_PSE_FRP_P2_RQ2, 4)); | ||
| 61 | |||
| 62 | mt76_wr(dev, MT_HIGH_PRIORITY_1, 0x55555553); | ||
| 63 | mt76_wr(dev, MT_HIGH_PRIORITY_2, 0x78555555); | ||
| 64 | |||
| 65 | mt76_wr(dev, MT_QUEUE_PRIORITY_1, 0x2b1a096e); | ||
| 66 | mt76_wr(dev, MT_QUEUE_PRIORITY_2, 0x785f4d3c); | ||
| 67 | |||
| 68 | mt76_wr(dev, MT_PRIORITY_MASK, 0xffffffff); | ||
| 69 | |||
| 70 | mt76_wr(dev, MT_SCH_1, page_count | (2 << 28)); | ||
| 71 | mt76_wr(dev, MT_SCH_2, max_amsdu_pages); | ||
| 72 | |||
| 73 | for (i = 0; i <= 4; i++) | ||
| 74 | mt76_wr(dev, MT_PAGE_COUNT(i), max_amsdu_pages); | ||
| 75 | reserved_count += 5 * max_amsdu_pages; | ||
| 76 | |||
| 77 | mt76_wr(dev, MT_PAGE_COUNT(5), mcu_pages); | ||
| 78 | reserved_count += mcu_pages; | ||
| 79 | |||
| 80 | mt76_wr(dev, MT_PAGE_COUNT(7), beacon_pages); | ||
| 81 | reserved_count += beacon_pages; | ||
| 82 | |||
| 83 | mt76_wr(dev, MT_PAGE_COUNT(8), max_mcast_pages); | ||
| 84 | reserved_count += max_mcast_pages; | ||
| 85 | |||
| 86 | if (is_mt7603(dev)) | ||
| 87 | reserved_count = 0; | ||
| 88 | |||
| 89 | mt76_wr(dev, MT_RSV_MAX_THRESH, page_count - reserved_count); | ||
| 90 | |||
| 91 | if (is_mt7603(dev) && mt76xx_rev(dev) >= MT7603_REV_E2) { | ||
| 92 | mt76_wr(dev, MT_GROUP_THRESH(0), | ||
| 93 | page_count - beacon_pages - mcu_pages); | ||
| 94 | mt76_wr(dev, MT_GROUP_THRESH(1), beacon_pages); | ||
| 95 | mt76_wr(dev, MT_BMAP_0, 0x0080ff5f); | ||
| 96 | mt76_wr(dev, MT_GROUP_THRESH(2), mcu_pages); | ||
| 97 | mt76_wr(dev, MT_BMAP_1, 0x00000020); | ||
| 98 | } else { | ||
| 99 | mt76_wr(dev, MT_GROUP_THRESH(0), page_count); | ||
| 100 | mt76_wr(dev, MT_BMAP_0, 0xffff); | ||
| 101 | } | ||
| 102 | |||
| 103 | mt76_wr(dev, MT_SCH_4, 0); | ||
| 104 | |||
| 105 | for (i = 0; i <= 15; i++) | ||
| 106 | mt76_wr(dev, MT_TXTIME_THRESH(i), 0xfffff); | ||
| 107 | |||
| 108 | mt76_set(dev, MT_SCH_4, BIT(6)); | ||
| 109 | } | ||
| 110 | |||
| 111 | static void | ||
| 112 | mt7603_phy_init(struct mt7603_dev *dev) | ||
| 113 | { | ||
| 114 | int rx_chains = dev->mt76.antenna_mask; | ||
| 115 | int tx_chains = __sw_hweight8(rx_chains) - 1; | ||
| 116 | |||
| 117 | mt76_rmw(dev, MT_WF_RMAC_RMCR, | ||
| 118 | (MT_WF_RMAC_RMCR_SMPS_MODE | | ||
| 119 | MT_WF_RMAC_RMCR_RX_STREAMS), | ||
| 120 | (FIELD_PREP(MT_WF_RMAC_RMCR_SMPS_MODE, 3) | | ||
| 121 | FIELD_PREP(MT_WF_RMAC_RMCR_RX_STREAMS, rx_chains))); | ||
| 122 | |||
| 123 | mt76_rmw_field(dev, MT_TMAC_TCR, MT_TMAC_TCR_TX_STREAMS, | ||
| 124 | tx_chains); | ||
| 125 | |||
| 126 | dev->agc0 = mt76_rr(dev, MT_AGC(0)); | ||
| 127 | dev->agc3 = mt76_rr(dev, MT_AGC(3)); | ||
| 128 | } | ||
| 129 | |||
| 130 | static void | ||
| 131 | mt7603_mac_init(struct mt7603_dev *dev) | ||
| 132 | { | ||
| 133 | u8 bc_addr[ETH_ALEN]; | ||
| 134 | u32 addr; | ||
| 135 | int i; | ||
| 136 | |||
| 137 | mt76_wr(dev, MT_AGG_BA_SIZE_LIMIT_0, | ||
| 138 | (MT_AGG_SIZE_LIMIT(0) << 0 * MT_AGG_BA_SIZE_LIMIT_SHIFT) | | ||
| 139 | (MT_AGG_SIZE_LIMIT(1) << 1 * MT_AGG_BA_SIZE_LIMIT_SHIFT) | | ||
| 140 | (MT_AGG_SIZE_LIMIT(2) << 2 * MT_AGG_BA_SIZE_LIMIT_SHIFT) | | ||
| 141 | (MT_AGG_SIZE_LIMIT(3) << 3 * MT_AGG_BA_SIZE_LIMIT_SHIFT)); | ||
| 142 | |||
| 143 | mt76_wr(dev, MT_AGG_BA_SIZE_LIMIT_1, | ||
| 144 | (MT_AGG_SIZE_LIMIT(4) << 0 * MT_AGG_BA_SIZE_LIMIT_SHIFT) | | ||
| 145 | (MT_AGG_SIZE_LIMIT(5) << 1 * MT_AGG_BA_SIZE_LIMIT_SHIFT) | | ||
| 146 | (MT_AGG_SIZE_LIMIT(6) << 2 * MT_AGG_BA_SIZE_LIMIT_SHIFT) | | ||
| 147 | (MT_AGG_SIZE_LIMIT(7) << 3 * MT_AGG_BA_SIZE_LIMIT_SHIFT)); | ||
| 148 | |||
| 149 | mt76_wr(dev, MT_AGG_LIMIT, | ||
| 150 | FIELD_PREP(MT_AGG_LIMIT_AC(0), 24) | | ||
| 151 | FIELD_PREP(MT_AGG_LIMIT_AC(1), 24) | | ||
| 152 | FIELD_PREP(MT_AGG_LIMIT_AC(2), 24) | | ||
| 153 | FIELD_PREP(MT_AGG_LIMIT_AC(3), 24)); | ||
| 154 | |||
| 155 | mt76_wr(dev, MT_AGG_LIMIT_1, | ||
| 156 | FIELD_PREP(MT_AGG_LIMIT_AC(0), 24) | | ||
| 157 | FIELD_PREP(MT_AGG_LIMIT_AC(1), 24) | | ||
| 158 | FIELD_PREP(MT_AGG_LIMIT_AC(2), 24) | | ||
| 159 | FIELD_PREP(MT_AGG_LIMIT_AC(3), 24)); | ||
| 160 | |||
| 161 | mt76_wr(dev, MT_AGG_CONTROL, | ||
| 162 | FIELD_PREP(MT_AGG_CONTROL_BAR_RATE, 0x4b) | | ||
| 163 | FIELD_PREP(MT_AGG_CONTROL_CFEND_RATE, 0x69) | | ||
| 164 | MT_AGG_CONTROL_NO_BA_AR_RULE); | ||
| 165 | |||
| 166 | mt76_wr(dev, MT_AGG_RETRY_CONTROL, | ||
| 167 | FIELD_PREP(MT_AGG_RETRY_CONTROL_BAR_LIMIT, 1) | | ||
| 168 | FIELD_PREP(MT_AGG_RETRY_CONTROL_RTS_LIMIT, 15)); | ||
| 169 | |||
| 170 | mt76_rmw(dev, MT_DMA_DCR0, ~0xfffc, 4096); | ||
| 171 | |||
| 172 | mt76_rmw(dev, MT_DMA_VCFR0, BIT(0), BIT(13)); | ||
| 173 | mt76_rmw(dev, MT_DMA_TMCFR0, BIT(0) | BIT(1), BIT(13)); | ||
| 174 | |||
| 175 | mt76_clear(dev, MT_WF_RMAC_TMR_PA, BIT(31)); | ||
| 176 | |||
| 177 | mt76_set(dev, MT_WF_RMACDR, MT_WF_RMACDR_MAXLEN_20BIT); | ||
| 178 | mt76_rmw(dev, MT_WF_RMAC_MAXMINLEN, 0xffffff, 0x19000); | ||
| 179 | |||
| 180 | mt76_wr(dev, MT_WF_RFCR1, 0); | ||
| 181 | |||
| 182 | mt76_set(dev, MT_TMAC_TCR, MT_TMAC_TCR_RX_RIFS_MODE); | ||
| 183 | |||
| 184 | mt7603_set_tmac_template(dev); | ||
| 185 | |||
| 186 | /* Enable RX group to HIF */ | ||
| 187 | addr = mt7603_reg_map(dev, MT_CLIENT_BASE_PHYS_ADDR); | ||
| 188 | mt76_set(dev, addr + MT_CLIENT_RXINF, MT_CLIENT_RXINF_RXSH_GROUPS); | ||
| 189 | |||
| 190 | /* Enable RX group to MCU */ | ||
| 191 | mt76_set(dev, MT_DMA_DCR1, GENMASK(13, 11)); | ||
| 192 | |||
| 193 | mt76_rmw_field(dev, MT_AGG_PCR_RTS, MT_AGG_PCR_RTS_PKT_THR, 3); | ||
| 194 | mt76_set(dev, MT_TMAC_PCR, MT_TMAC_PCR_SPE_EN); | ||
| 195 | |||
| 196 | /* include preamble detection in CCA trigger signal */ | ||
| 197 | mt76_rmw_field(dev, MT_TXREQ, MT_TXREQ_CCA_SRC_SEL, 2); | ||
| 198 | |||
| 199 | mt76_wr(dev, MT_RXREQ, 4); | ||
| 200 | |||
| 201 | /* Configure all rx packets to HIF */ | ||
| 202 | mt76_wr(dev, MT_DMA_RCFR0, 0xc0000000); | ||
| 203 | |||
| 204 | /* Configure MCU txs selection with aggregation */ | ||
| 205 | mt76_wr(dev, MT_DMA_TCFR0, | ||
| 206 | FIELD_PREP(MT_DMA_TCFR_TXS_AGGR_TIMEOUT, 1) | /* 32 us */ | ||
| 207 | MT_DMA_TCFR_TXS_AGGR_COUNT); | ||
| 208 | |||
| 209 | /* Configure HIF txs selection with aggregation */ | ||
| 210 | mt76_wr(dev, MT_DMA_TCFR1, | ||
| 211 | FIELD_PREP(MT_DMA_TCFR_TXS_AGGR_TIMEOUT, 1) | /* 32 us */ | ||
| 212 | MT_DMA_TCFR_TXS_AGGR_COUNT | /* Maximum count */ | ||
| 213 | MT_DMA_TCFR_TXS_BIT_MAP); | ||
| 214 | |||
| 215 | mt76_wr(dev, MT_MCU_PCIE_REMAP_1, MT_PSE_WTBL_2_PHYS_ADDR); | ||
| 216 | |||
| 217 | for (i = 0; i < MT7603_WTBL_SIZE; i++) | ||
| 218 | mt7603_wtbl_clear(dev, i); | ||
| 219 | |||
| 220 | eth_broadcast_addr(bc_addr); | ||
| 221 | mt7603_wtbl_init(dev, MT7603_WTBL_RESERVED, -1, bc_addr); | ||
| 222 | dev->global_sta.wcid.idx = MT7603_WTBL_RESERVED; | ||
| 223 | rcu_assign_pointer(dev->mt76.wcid[MT7603_WTBL_RESERVED], | ||
| 224 | &dev->global_sta.wcid); | ||
| 225 | |||
| 226 | mt76_rmw_field(dev, MT_LPON_BTEIR, MT_LPON_BTEIR_MBSS_MODE, 2); | ||
| 227 | mt76_rmw_field(dev, MT_WF_RMACDR, MT_WF_RMACDR_MBSSID_MASK, 2); | ||
| 228 | |||
| 229 | mt76_wr(dev, MT_AGG_ARUCR, FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), 7)); | ||
| 230 | mt76_wr(dev, MT_AGG_ARDCR, | ||
| 231 | FIELD_PREP(MT_AGG_ARxCR_LIMIT(0), 0) | | ||
| 232 | FIELD_PREP(MT_AGG_ARxCR_LIMIT(1), | ||
| 233 | max_t(int, 0, MT7603_RATE_RETRY - 2)) | | ||
| 234 | FIELD_PREP(MT_AGG_ARxCR_LIMIT(2), MT7603_RATE_RETRY - 1) | | ||
| 235 | FIELD_PREP(MT_AGG_ARxCR_LIMIT(3), MT7603_RATE_RETRY - 1) | | ||
| 236 | FIELD_PREP(MT_AGG_ARxCR_LIMIT(4), MT7603_RATE_RETRY - 1) | | ||
| 237 | FIELD_PREP(MT_AGG_ARxCR_LIMIT(5), MT7603_RATE_RETRY - 1) | | ||
| 238 | FIELD_PREP(MT_AGG_ARxCR_LIMIT(6), MT7603_RATE_RETRY - 1) | | ||
| 239 | FIELD_PREP(MT_AGG_ARxCR_LIMIT(7), MT7603_RATE_RETRY - 1)); | ||
| 240 | |||
| 241 | mt76_wr(dev, MT_AGG_ARCR, | ||
| 242 | (MT_AGG_ARCR_INIT_RATE1 | | ||
| 243 | FIELD_PREP(MT_AGG_ARCR_RTS_RATE_THR, 2) | | ||
| 244 | MT_AGG_ARCR_RATE_DOWN_RATIO_EN | | ||
| 245 | FIELD_PREP(MT_AGG_ARCR_RATE_DOWN_RATIO, 1) | | ||
| 246 | FIELD_PREP(MT_AGG_ARCR_RATE_UP_EXTRA_TH, 4))); | ||
| 247 | |||
| 248 | mt76_set(dev, MT_WTBL_RMVTCR, MT_WTBL_RMVTCR_RX_MV_MODE); | ||
| 249 | |||
| 250 | mt76_clear(dev, MT_SEC_SCR, MT_SEC_SCR_MASK_ORDER); | ||
| 251 | mt76_clear(dev, MT_SEC_SCR, BIT(18)); | ||
| 252 | |||
| 253 | /* Set secondary beacon time offsets */ | ||
| 254 | for (i = 0; i <= 4; i++) | ||
| 255 | mt76_rmw_field(dev, MT_LPON_SBTOR(i), MT_LPON_SBTOR_TIME_OFFSET, | ||
| 256 | (i + 1) * (20 + 4096)); | ||
| 257 | } | ||
| 258 | |||
| 259 | static int | ||
| 260 | mt7603_init_hardware(struct mt7603_dev *dev) | ||
| 261 | { | ||
| 262 | int i, ret; | ||
| 263 | |||
| 264 | mt76_wr(dev, MT_INT_SOURCE_CSR, ~0); | ||
| 265 | |||
| 266 | ret = mt7603_eeprom_init(dev); | ||
| 267 | if (ret < 0) | ||
| 268 | return ret; | ||
| 269 | |||
| 270 | ret = mt7603_dma_init(dev); | ||
| 271 | if (ret) | ||
| 272 | return ret; | ||
| 273 | |||
| 274 | mt76_wr(dev, MT_WPDMA_GLO_CFG, 0x52000850); | ||
| 275 | mt7603_mac_dma_start(dev); | ||
| 276 | dev->rxfilter = mt76_rr(dev, MT_WF_RFCR); | ||
| 277 | set_bit(MT76_STATE_INITIALIZED, &dev->mt76.state); | ||
| 278 | |||
| 279 | for (i = 0; i < MT7603_WTBL_SIZE; i++) { | ||
| 280 | mt76_wr(dev, MT_PSE_RTA, MT_PSE_RTA_BUSY | MT_PSE_RTA_WRITE | | ||
| 281 | FIELD_PREP(MT_PSE_RTA_TAG_ID, i)); | ||
| 282 | mt76_poll(dev, MT_PSE_RTA, MT_PSE_RTA_BUSY, 0, 5000); | ||
| 283 | } | ||
| 284 | |||
| 285 | ret = mt7603_mcu_init(dev); | ||
| 286 | if (ret) | ||
| 287 | return ret; | ||
| 288 | |||
| 289 | mt7603_dma_sched_init(dev); | ||
| 290 | mt7603_mcu_set_eeprom(dev); | ||
| 291 | mt7603_phy_init(dev); | ||
| 292 | mt7603_mac_init(dev); | ||
| 293 | |||
| 294 | return 0; | ||
| 295 | } | ||
| 296 | |||
| 297 | #define CCK_RATE(_idx, _rate) { \ | ||
| 298 | .bitrate = _rate, \ | ||
| 299 | .flags = IEEE80211_RATE_SHORT_PREAMBLE, \ | ||
| 300 | .hw_value = (MT_PHY_TYPE_CCK << 8) | (_idx), \ | ||
| 301 | .hw_value_short = (MT_PHY_TYPE_CCK << 8) | (4 + _idx), \ | ||
| 302 | } | ||
| 303 | |||
| 304 | #define OFDM_RATE(_idx, _rate) { \ | ||
| 305 | .bitrate = _rate, \ | ||
| 306 | .hw_value = (MT_PHY_TYPE_OFDM << 8) | (_idx), \ | ||
| 307 | .hw_value_short = (MT_PHY_TYPE_OFDM << 8) | (_idx), \ | ||
| 308 | } | ||
| 309 | |||
| 310 | static struct ieee80211_rate mt7603_rates[] = { | ||
| 311 | CCK_RATE(0, 10), | ||
| 312 | CCK_RATE(1, 20), | ||
| 313 | CCK_RATE(2, 55), | ||
| 314 | CCK_RATE(3, 110), | ||
| 315 | OFDM_RATE(11, 60), | ||
| 316 | OFDM_RATE(15, 90), | ||
| 317 | OFDM_RATE(10, 120), | ||
| 318 | OFDM_RATE(14, 180), | ||
| 319 | OFDM_RATE(9, 240), | ||
| 320 | OFDM_RATE(13, 360), | ||
| 321 | OFDM_RATE(8, 480), | ||
| 322 | OFDM_RATE(12, 540), | ||
| 323 | }; | ||
| 324 | |||
| 325 | static const struct ieee80211_iface_limit if_limits[] = { | ||
| 326 | { | ||
| 327 | .max = 1, | ||
| 328 | .types = BIT(NL80211_IFTYPE_ADHOC) | ||
| 329 | }, { | ||
| 330 | .max = MT7603_MAX_INTERFACES, | ||
| 331 | .types = BIT(NL80211_IFTYPE_STATION) | | ||
| 332 | #ifdef CONFIG_MAC80211_MESH | ||
| 333 | BIT(NL80211_IFTYPE_MESH_POINT) | | ||
| 334 | #endif | ||
| 335 | BIT(NL80211_IFTYPE_AP) | ||
| 336 | }, | ||
| 337 | }; | ||
| 338 | |||
| 339 | static const struct ieee80211_iface_combination if_comb[] = { | ||
| 340 | { | ||
| 341 | .limits = if_limits, | ||
| 342 | .n_limits = ARRAY_SIZE(if_limits), | ||
| 343 | .max_interfaces = 4, | ||
| 344 | .num_different_channels = 1, | ||
| 345 | .beacon_int_infra_match = true, | ||
| 346 | } | ||
| 347 | }; | ||
| 348 | |||
| 349 | static void mt7603_led_set_config(struct mt76_dev *mt76, u8 delay_on, | ||
| 350 | u8 delay_off) | ||
| 351 | { | ||
| 352 | struct mt7603_dev *dev = container_of(mt76, struct mt7603_dev, | ||
| 353 | mt76); | ||
| 354 | u32 val, addr; | ||
| 355 | |||
| 356 | val = MT_LED_STATUS_DURATION(0xffff) | | ||
| 357 | MT_LED_STATUS_OFF(delay_off) | | ||
| 358 | MT_LED_STATUS_ON(delay_on); | ||
| 359 | |||
| 360 | addr = mt7603_reg_map(dev, MT_LED_STATUS_0(mt76->led_pin)); | ||
| 361 | mt76_wr(dev, addr, val); | ||
| 362 | addr = mt7603_reg_map(dev, MT_LED_STATUS_1(mt76->led_pin)); | ||
| 363 | mt76_wr(dev, addr, val); | ||
| 364 | |||
| 365 | val = MT_LED_CTRL_REPLAY(mt76->led_pin) | | ||
| 366 | MT_LED_CTRL_KICK(mt76->led_pin); | ||
| 367 | if (mt76->led_al) | ||
| 368 | val |= MT_LED_CTRL_POLARITY(mt76->led_pin); | ||
| 369 | addr = mt7603_reg_map(dev, MT_LED_CTRL); | ||
| 370 | mt76_wr(dev, addr, val); | ||
| 371 | } | ||
| 372 | |||
| 373 | static int mt7603_led_set_blink(struct led_classdev *led_cdev, | ||
| 374 | unsigned long *delay_on, | ||
| 375 | unsigned long *delay_off) | ||
| 376 | { | ||
| 377 | struct mt76_dev *mt76 = container_of(led_cdev, struct mt76_dev, | ||
| 378 | led_cdev); | ||
| 379 | u8 delta_on, delta_off; | ||
| 380 | |||
| 381 | delta_off = max_t(u8, *delay_off / 10, 1); | ||
| 382 | delta_on = max_t(u8, *delay_on / 10, 1); | ||
| 383 | |||
| 384 | mt7603_led_set_config(mt76, delta_on, delta_off); | ||
| 385 | return 0; | ||
| 386 | } | ||
| 387 | |||
| 388 | static void mt7603_led_set_brightness(struct led_classdev *led_cdev, | ||
| 389 | enum led_brightness brightness) | ||
| 390 | { | ||
| 391 | struct mt76_dev *mt76 = container_of(led_cdev, struct mt76_dev, | ||
| 392 | led_cdev); | ||
| 393 | |||
| 394 | if (!brightness) | ||
| 395 | mt7603_led_set_config(mt76, 0, 0xff); | ||
| 396 | else | ||
| 397 | mt7603_led_set_config(mt76, 0xff, 0); | ||
| 398 | } | ||
| 399 | |||
| 400 | static u32 __mt7603_reg_addr(struct mt7603_dev *dev, u32 addr) | ||
| 401 | { | ||
| 402 | if (addr < 0x100000) | ||
| 403 | return addr; | ||
| 404 | |||
| 405 | return mt7603_reg_map(dev, addr); | ||
| 406 | } | ||
| 407 | |||
| 408 | static u32 mt7603_rr(struct mt76_dev *mdev, u32 offset) | ||
| 409 | { | ||
| 410 | struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); | ||
| 411 | u32 addr = __mt7603_reg_addr(dev, offset); | ||
| 412 | |||
| 413 | return dev->bus_ops->rr(mdev, addr); | ||
| 414 | } | ||
| 415 | |||
| 416 | static void mt7603_wr(struct mt76_dev *mdev, u32 offset, u32 val) | ||
| 417 | { | ||
| 418 | struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); | ||
| 419 | u32 addr = __mt7603_reg_addr(dev, offset); | ||
| 420 | |||
| 421 | dev->bus_ops->wr(mdev, addr, val); | ||
| 422 | } | ||
| 423 | |||
| 424 | static u32 mt7603_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val) | ||
| 425 | { | ||
| 426 | struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); | ||
| 427 | u32 addr = __mt7603_reg_addr(dev, offset); | ||
| 428 | |||
| 429 | return dev->bus_ops->rmw(mdev, addr, mask, val); | ||
| 430 | } | ||
| 431 | |||
| 432 | static void | ||
| 433 | mt7603_regd_notifier(struct wiphy *wiphy, | ||
| 434 | struct regulatory_request *request) | ||
| 435 | { | ||
| 436 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); | ||
| 437 | struct mt7603_dev *dev = hw->priv; | ||
| 438 | |||
| 439 | dev->ed_monitor = request->dfs_region == NL80211_DFS_ETSI; | ||
| 440 | } | ||
| 441 | |||
| 442 | static int | ||
| 443 | mt7603_txpower_signed(int val) | ||
| 444 | { | ||
| 445 | bool sign = val & BIT(6); | ||
| 446 | |||
| 447 | if (!(val & BIT(7))) | ||
| 448 | return 0; | ||
| 449 | |||
| 450 | val &= GENMASK(5, 0); | ||
| 451 | if (!sign) | ||
| 452 | val = -val; | ||
| 453 | |||
| 454 | return val; | ||
| 455 | } | ||
| 456 | |||
| 457 | static void | ||
| 458 | mt7603_init_txpower(struct mt7603_dev *dev, | ||
| 459 | struct ieee80211_supported_band *sband) | ||
| 460 | { | ||
| 461 | struct ieee80211_channel *chan; | ||
| 462 | u8 *eeprom = (u8 *)dev->mt76.eeprom.data; | ||
| 463 | int target_power = eeprom[MT_EE_TX_POWER_0_START_2G + 2] & ~BIT(7); | ||
| 464 | u8 *rate_power = &eeprom[MT_EE_TX_POWER_CCK]; | ||
| 465 | int max_offset, cur_offset; | ||
| 466 | int i; | ||
| 467 | |||
| 468 | if (target_power & BIT(6)) | ||
| 469 | target_power = -(target_power & GENMASK(5, 0)); | ||
| 470 | |||
| 471 | max_offset = 0; | ||
| 472 | for (i = 0; i < 14; i++) { | ||
| 473 | cur_offset = mt7603_txpower_signed(rate_power[i]); | ||
| 474 | max_offset = max(max_offset, cur_offset); | ||
| 475 | } | ||
| 476 | |||
| 477 | target_power += max_offset; | ||
| 478 | |||
| 479 | dev->tx_power_limit = target_power; | ||
| 480 | dev->mt76.txpower_cur = target_power; | ||
| 481 | |||
| 482 | target_power = DIV_ROUND_UP(target_power, 2); | ||
| 483 | |||
| 484 | /* add 3 dBm for 2SS devices (combined output) */ | ||
| 485 | if (dev->mt76.antenna_mask & BIT(1)) | ||
| 486 | target_power += 3; | ||
| 487 | |||
| 488 | for (i = 0; i < sband->n_channels; i++) { | ||
| 489 | chan = &sband->channels[i]; | ||
| 490 | chan->max_power = target_power; | ||
| 491 | } | ||
| 492 | } | ||
| 493 | |||
| 494 | |||
| 495 | int mt7603_register_device(struct mt7603_dev *dev) | ||
| 496 | { | ||
| 497 | struct mt76_bus_ops *bus_ops; | ||
| 498 | struct ieee80211_hw *hw = mt76_hw(dev); | ||
| 499 | struct wiphy *wiphy = hw->wiphy; | ||
| 500 | int ret; | ||
| 501 | |||
| 502 | dev->bus_ops = dev->mt76.bus; | ||
| 503 | bus_ops = devm_kmemdup(dev->mt76.dev, dev->bus_ops, sizeof(*bus_ops), | ||
| 504 | GFP_KERNEL); | ||
| 505 | if (!bus_ops) | ||
| 506 | return -ENOMEM; | ||
| 507 | |||
| 508 | bus_ops->rr = mt7603_rr; | ||
| 509 | bus_ops->wr = mt7603_wr; | ||
| 510 | bus_ops->rmw = mt7603_rmw; | ||
| 511 | dev->mt76.bus = bus_ops; | ||
| 512 | |||
| 513 | INIT_DELAYED_WORK(&dev->mac_work, mt7603_mac_work); | ||
| 514 | tasklet_init(&dev->pre_tbtt_tasklet, mt7603_pre_tbtt_tasklet, | ||
| 515 | (unsigned long)dev); | ||
| 516 | |||
| 517 | /* Check for 7688, which only has 1SS */ | ||
| 518 | dev->mt76.antenna_mask = 3; | ||
| 519 | if (mt76_rr(dev, MT_EFUSE_BASE + 0x64) & BIT(4)) | ||
| 520 | dev->mt76.antenna_mask = 1; | ||
| 521 | |||
| 522 | dev->slottime = 9; | ||
| 523 | |||
| 524 | ret = mt7603_init_hardware(dev); | ||
| 525 | if (ret) | ||
| 526 | return ret; | ||
| 527 | |||
| 528 | hw->queues = 4; | ||
| 529 | hw->max_rates = 3; | ||
| 530 | hw->max_report_rates = 7; | ||
| 531 | hw->max_rate_tries = 11; | ||
| 532 | |||
| 533 | hw->sta_data_size = sizeof(struct mt7603_sta); | ||
| 534 | hw->vif_data_size = sizeof(struct mt7603_vif); | ||
| 535 | |||
| 536 | wiphy->iface_combinations = if_comb; | ||
| 537 | wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); | ||
| 538 | |||
| 539 | ieee80211_hw_set(hw, SUPPORTS_REORDERING_BUFFER); | ||
| 540 | ieee80211_hw_set(hw, TX_STATUS_NO_AMPDU_LEN); | ||
| 541 | |||
| 542 | /* init led callbacks */ | ||
| 543 | if (IS_ENABLED(CONFIG_MT76_LEDS)) { | ||
| 544 | dev->mt76.led_cdev.brightness_set = mt7603_led_set_brightness; | ||
| 545 | dev->mt76.led_cdev.blink_set = mt7603_led_set_blink; | ||
| 546 | } | ||
| 547 | |||
| 548 | wiphy->interface_modes = | ||
| 549 | BIT(NL80211_IFTYPE_STATION) | | ||
| 550 | BIT(NL80211_IFTYPE_AP) | | ||
| 551 | #ifdef CONFIG_MAC80211_MESH | ||
| 552 | BIT(NL80211_IFTYPE_MESH_POINT) | | ||
| 553 | #endif | ||
| 554 | BIT(NL80211_IFTYPE_ADHOC); | ||
| 555 | |||
| 556 | wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; | ||
| 557 | |||
| 558 | wiphy->reg_notifier = mt7603_regd_notifier; | ||
| 559 | |||
| 560 | ret = mt76_register_device(&dev->mt76, true, mt7603_rates, | ||
| 561 | ARRAY_SIZE(mt7603_rates)); | ||
| 562 | if (ret) | ||
| 563 | return ret; | ||
| 564 | |||
| 565 | mt7603_init_debugfs(dev); | ||
| 566 | mt7603_init_txpower(dev, &dev->mt76.sband_2g.sband); | ||
| 567 | |||
| 568 | return 0; | ||
| 569 | } | ||
| 570 | |||
| 571 | void mt7603_unregister_device(struct mt7603_dev *dev) | ||
| 572 | { | ||
| 573 | tasklet_disable(&dev->pre_tbtt_tasklet); | ||
| 574 | mt76_unregister_device(&dev->mt76); | ||
| 575 | mt7603_mcu_exit(dev); | ||
| 576 | mt7603_dma_cleanup(dev); | ||
| 577 | ieee80211_free_hw(mt76_hw(dev)); | ||
| 578 | } | ||
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c new file mode 100644 index 000000000000..0a0115861b51 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c | |||
| @@ -0,0 +1,1749 @@ | |||
| 1 | /* SPDX-License-Identifier: ISC */ | ||
| 2 | |||
| 3 | #include <linux/etherdevice.h> | ||
| 4 | #include <linux/timekeeping.h> | ||
| 5 | #include "mt7603.h" | ||
| 6 | #include "mac.h" | ||
| 7 | |||
| 8 | #define MT_PSE_PAGE_SIZE 128 | ||
| 9 | |||
| 10 | static u32 | ||
| 11 | mt7603_ac_queue_mask0(u32 mask) | ||
| 12 | { | ||
| 13 | u32 ret = 0; | ||
| 14 | |||
| 15 | ret |= GENMASK(3, 0) * !!(mask & BIT(0)); | ||
| 16 | ret |= GENMASK(8, 5) * !!(mask & BIT(1)); | ||
| 17 | ret |= GENMASK(13, 10) * !!(mask & BIT(2)); | ||
| 18 | ret |= GENMASK(19, 16) * !!(mask & BIT(3)); | ||
| 19 | return ret; | ||
| 20 | } | ||
| 21 | |||
| 22 | static void | ||
| 23 | mt76_stop_tx_ac(struct mt7603_dev *dev, u32 mask) | ||
| 24 | { | ||
| 25 | mt76_set(dev, MT_WF_ARB_TX_STOP_0, mt7603_ac_queue_mask0(mask)); | ||
| 26 | } | ||
| 27 | |||
| 28 | static void | ||
| 29 | mt76_start_tx_ac(struct mt7603_dev *dev, u32 mask) | ||
| 30 | { | ||
| 31 | mt76_set(dev, MT_WF_ARB_TX_START_0, mt7603_ac_queue_mask0(mask)); | ||
| 32 | } | ||
| 33 | |||
| 34 | void mt7603_mac_set_timing(struct mt7603_dev *dev) | ||
| 35 | { | ||
| 36 | u32 cck = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 231) | | ||
| 37 | FIELD_PREP(MT_TIMEOUT_VAL_CCA, 48); | ||
| 38 | u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) | | ||
| 39 | FIELD_PREP(MT_TIMEOUT_VAL_CCA, 24); | ||
| 40 | int offset = 3 * dev->coverage_class; | ||
| 41 | u32 reg_offset = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, offset) | | ||
| 42 | FIELD_PREP(MT_TIMEOUT_VAL_CCA, offset); | ||
| 43 | int sifs; | ||
| 44 | u32 val; | ||
| 45 | |||
| 46 | if (dev->mt76.chandef.chan->band == NL80211_BAND_5GHZ) | ||
| 47 | sifs = 16; | ||
| 48 | else | ||
| 49 | sifs = 10; | ||
| 50 | |||
| 51 | mt76_set(dev, MT_ARB_SCR, | ||
| 52 | MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE); | ||
| 53 | udelay(1); | ||
| 54 | |||
| 55 | mt76_wr(dev, MT_TIMEOUT_CCK, cck + reg_offset); | ||
| 56 | mt76_wr(dev, MT_TIMEOUT_OFDM, ofdm + reg_offset); | ||
| 57 | mt76_wr(dev, MT_IFS, | ||
| 58 | FIELD_PREP(MT_IFS_EIFS, 360) | | ||
| 59 | FIELD_PREP(MT_IFS_RIFS, 2) | | ||
| 60 | FIELD_PREP(MT_IFS_SIFS, sifs) | | ||
| 61 | FIELD_PREP(MT_IFS_SLOT, dev->slottime)); | ||
| 62 | |||
| 63 | if (dev->slottime < 20) | ||
| 64 | val = MT7603_CFEND_RATE_DEFAULT; | ||
| 65 | else | ||
| 66 | val = MT7603_CFEND_RATE_11B; | ||
| 67 | |||
| 68 | mt76_rmw_field(dev, MT_AGG_CONTROL, MT_AGG_CONTROL_CFEND_RATE, val); | ||
| 69 | |||
| 70 | mt76_clear(dev, MT_ARB_SCR, | ||
| 71 | MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE); | ||
| 72 | } | ||
| 73 | |||
| 74 | static void | ||
| 75 | mt7603_wtbl_update(struct mt7603_dev *dev, int idx, u32 mask) | ||
| 76 | { | ||
| 77 | mt76_rmw(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_WLAN_IDX, | ||
| 78 | FIELD_PREP(MT_WTBL_UPDATE_WLAN_IDX, idx) | mask); | ||
| 79 | |||
| 80 | mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000); | ||
| 81 | } | ||
| 82 | |||
| 83 | static u32 | ||
| 84 | mt7603_wtbl1_addr(int idx) | ||
| 85 | { | ||
| 86 | return MT_WTBL1_BASE + idx * MT_WTBL1_SIZE; | ||
| 87 | } | ||
| 88 | |||
| 89 | static u32 | ||
| 90 | mt7603_wtbl2_addr(int idx) | ||
| 91 | { | ||
| 92 | /* Mapped to WTBL2 */ | ||
| 93 | return MT_PCIE_REMAP_BASE_1 + idx * MT_WTBL2_SIZE; | ||
| 94 | } | ||
| 95 | |||
| 96 | static u32 | ||
| 97 | mt7603_wtbl3_addr(int idx) | ||
| 98 | { | ||
| 99 | u32 base = mt7603_wtbl2_addr(MT7603_WTBL_SIZE); | ||
| 100 | |||
| 101 | return base + idx * MT_WTBL3_SIZE; | ||
| 102 | } | ||
| 103 | |||
| 104 | static u32 | ||
| 105 | mt7603_wtbl4_addr(int idx) | ||
| 106 | { | ||
| 107 | u32 base = mt7603_wtbl3_addr(MT7603_WTBL_SIZE); | ||
| 108 | |||
| 109 | return base + idx * MT_WTBL4_SIZE; | ||
| 110 | } | ||
| 111 | |||
| 112 | void mt7603_wtbl_init(struct mt7603_dev *dev, int idx, int vif, | ||
| 113 | const u8 *mac_addr) | ||
| 114 | { | ||
| 115 | const void *_mac = mac_addr; | ||
| 116 | u32 addr = mt7603_wtbl1_addr(idx); | ||
| 117 | u32 w0 = 0, w1 = 0; | ||
| 118 | int i; | ||
| 119 | |||
| 120 | if (_mac) { | ||
| 121 | w0 = FIELD_PREP(MT_WTBL1_W0_ADDR_HI, | ||
| 122 | get_unaligned_le16(_mac + 4)); | ||
| 123 | w1 = FIELD_PREP(MT_WTBL1_W1_ADDR_LO, | ||
| 124 | get_unaligned_le32(_mac)); | ||
| 125 | } | ||
| 126 | |||
| 127 | if (vif < 0) | ||
| 128 | vif = 0; | ||
| 129 | else | ||
| 130 | w0 |= MT_WTBL1_W0_RX_CHECK_A1; | ||
| 131 | w0 |= FIELD_PREP(MT_WTBL1_W0_MUAR_IDX, vif); | ||
| 132 | |||
| 133 | mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000); | ||
| 134 | |||
| 135 | mt76_set(dev, addr + 0 * 4, w0); | ||
| 136 | mt76_set(dev, addr + 1 * 4, w1); | ||
| 137 | mt76_set(dev, addr + 2 * 4, MT_WTBL1_W2_ADMISSION_CONTROL); | ||
| 138 | |||
| 139 | mt76_stop_tx_ac(dev, GENMASK(3, 0)); | ||
| 140 | addr = mt7603_wtbl2_addr(idx); | ||
| 141 | for (i = 0; i < MT_WTBL2_SIZE; i += 4) | ||
| 142 | mt76_wr(dev, addr + i, 0); | ||
| 143 | mt7603_wtbl_update(dev, idx, MT_WTBL_UPDATE_WTBL2); | ||
| 144 | mt76_start_tx_ac(dev, GENMASK(3, 0)); | ||
| 145 | |||
| 146 | addr = mt7603_wtbl3_addr(idx); | ||
| 147 | for (i = 0; i < MT_WTBL3_SIZE; i += 4) | ||
| 148 | mt76_wr(dev, addr + i, 0); | ||
| 149 | |||
| 150 | addr = mt7603_wtbl4_addr(idx); | ||
| 151 | for (i = 0; i < MT_WTBL4_SIZE; i += 4) | ||
| 152 | mt76_wr(dev, addr + i, 0); | ||
| 153 | } | ||
| 154 | |||
| 155 | static void | ||
| 156 | mt7603_wtbl_set_skip_tx(struct mt7603_dev *dev, int idx, bool enabled) | ||
| 157 | { | ||
| 158 | u32 addr = mt7603_wtbl1_addr(idx); | ||
| 159 | u32 val = mt76_rr(dev, addr + 3 * 4); | ||
| 160 | |||
| 161 | val &= ~MT_WTBL1_W3_SKIP_TX; | ||
| 162 | val |= enabled * MT_WTBL1_W3_SKIP_TX; | ||
| 163 | |||
| 164 | mt76_wr(dev, addr + 3 * 4, val); | ||
| 165 | } | ||
| 166 | |||
| 167 | void mt7603_filter_tx(struct mt7603_dev *dev, int idx, bool abort) | ||
| 168 | { | ||
| 169 | int i, port, queue; | ||
| 170 | |||
| 171 | if (abort) { | ||
| 172 | port = 3; /* PSE */ | ||
| 173 | queue = 8; /* free queue */ | ||
| 174 | } else { | ||
| 175 | port = 0; /* HIF */ | ||
| 176 | queue = 1; /* MCU queue */ | ||
| 177 | } | ||
| 178 | |||
| 179 | mt7603_wtbl_set_skip_tx(dev, idx, true); | ||
| 180 | |||
| 181 | mt76_wr(dev, MT_TX_ABORT, MT_TX_ABORT_EN | | ||
| 182 | FIELD_PREP(MT_TX_ABORT_WCID, idx)); | ||
| 183 | |||
| 184 | for (i = 0; i < 4; i++) { | ||
| 185 | mt76_wr(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY | | ||
| 186 | FIELD_PREP(MT_DMA_FQCR0_TARGET_WCID, idx) | | ||
| 187 | FIELD_PREP(MT_DMA_FQCR0_TARGET_QID, i) | | ||
| 188 | FIELD_PREP(MT_DMA_FQCR0_DEST_PORT_ID, port) | | ||
| 189 | FIELD_PREP(MT_DMA_FQCR0_DEST_QUEUE_ID, queue)); | ||
| 190 | |||
| 191 | WARN_ON_ONCE(!mt76_poll(dev, MT_DMA_FQCR0, MT_DMA_FQCR0_BUSY, | ||
| 192 | 0, 5000)); | ||
| 193 | } | ||
| 194 | |||
| 195 | mt76_wr(dev, MT_TX_ABORT, 0); | ||
| 196 | |||
| 197 | mt7603_wtbl_set_skip_tx(dev, idx, false); | ||
| 198 | } | ||
| 199 | |||
| 200 | void mt7603_wtbl_set_smps(struct mt7603_dev *dev, struct mt7603_sta *sta, | ||
| 201 | bool enabled) | ||
| 202 | { | ||
| 203 | u32 addr = mt7603_wtbl1_addr(sta->wcid.idx); | ||
| 204 | |||
| 205 | if (sta->smps == enabled) | ||
| 206 | return; | ||
| 207 | |||
| 208 | mt76_rmw_field(dev, addr + 2 * 4, MT_WTBL1_W2_SMPS, enabled); | ||
| 209 | sta->smps = enabled; | ||
| 210 | } | ||
| 211 | |||
| 212 | void mt7603_wtbl_set_ps(struct mt7603_dev *dev, struct mt7603_sta *sta, | ||
| 213 | bool enabled) | ||
| 214 | { | ||
| 215 | int idx = sta->wcid.idx; | ||
| 216 | u32 addr; | ||
| 217 | |||
| 218 | spin_lock_bh(&dev->ps_lock); | ||
| 219 | |||
| 220 | if (sta->ps == enabled) | ||
| 221 | goto out; | ||
| 222 | |||
| 223 | mt76_wr(dev, MT_PSE_RTA, | ||
| 224 | FIELD_PREP(MT_PSE_RTA_TAG_ID, idx) | | ||
| 225 | FIELD_PREP(MT_PSE_RTA_PORT_ID, 0) | | ||
| 226 | FIELD_PREP(MT_PSE_RTA_QUEUE_ID, 1) | | ||
| 227 | FIELD_PREP(MT_PSE_RTA_REDIRECT_EN, enabled) | | ||
| 228 | MT_PSE_RTA_WRITE | MT_PSE_RTA_BUSY); | ||
| 229 | |||
| 230 | mt76_poll(dev, MT_PSE_RTA, MT_PSE_RTA_BUSY, 0, 5000); | ||
| 231 | |||
| 232 | if (enabled) | ||
| 233 | mt7603_filter_tx(dev, idx, false); | ||
| 234 | |||
| 235 | addr = mt7603_wtbl1_addr(idx); | ||
| 236 | mt76_set(dev, MT_WTBL1_OR, MT_WTBL1_OR_PSM_WRITE); | ||
| 237 | mt76_rmw(dev, addr + 3 * 4, MT_WTBL1_W3_POWER_SAVE, | ||
| 238 | enabled * MT_WTBL1_W3_POWER_SAVE); | ||
| 239 | mt76_clear(dev, MT_WTBL1_OR, MT_WTBL1_OR_PSM_WRITE); | ||
| 240 | sta->ps = enabled; | ||
| 241 | |||
| 242 | out: | ||
| 243 | spin_unlock_bh(&dev->ps_lock); | ||
| 244 | } | ||
| 245 | |||
| 246 | void mt7603_wtbl_clear(struct mt7603_dev *dev, int idx) | ||
| 247 | { | ||
| 248 | int wtbl2_frame_size = MT_PSE_PAGE_SIZE / MT_WTBL2_SIZE; | ||
| 249 | int wtbl2_frame = idx / wtbl2_frame_size; | ||
| 250 | int wtbl2_entry = idx % wtbl2_frame_size; | ||
| 251 | |||
| 252 | int wtbl3_base_frame = MT_WTBL3_OFFSET / MT_PSE_PAGE_SIZE; | ||
| 253 | int wtbl3_frame_size = MT_PSE_PAGE_SIZE / MT_WTBL3_SIZE; | ||
| 254 | int wtbl3_frame = wtbl3_base_frame + idx / wtbl3_frame_size; | ||
| 255 | int wtbl3_entry = (idx % wtbl3_frame_size) * 2; | ||
| 256 | |||
| 257 | int wtbl4_base_frame = MT_WTBL4_OFFSET / MT_PSE_PAGE_SIZE; | ||
| 258 | int wtbl4_frame_size = MT_PSE_PAGE_SIZE / MT_WTBL4_SIZE; | ||
| 259 | int wtbl4_frame = wtbl4_base_frame + idx / wtbl4_frame_size; | ||
| 260 | int wtbl4_entry = idx % wtbl4_frame_size; | ||
| 261 | |||
| 262 | u32 addr = MT_WTBL1_BASE + idx * MT_WTBL1_SIZE; | ||
| 263 | int i; | ||
| 264 | |||
| 265 | mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000); | ||
| 266 | |||
| 267 | mt76_wr(dev, addr + 0 * 4, | ||
| 268 | MT_WTBL1_W0_RX_CHECK_A1 | | ||
| 269 | MT_WTBL1_W0_RX_CHECK_A2 | | ||
| 270 | MT_WTBL1_W0_RX_VALID); | ||
| 271 | mt76_wr(dev, addr + 1 * 4, 0); | ||
| 272 | mt76_wr(dev, addr + 2 * 4, 0); | ||
| 273 | |||
| 274 | mt76_set(dev, MT_WTBL1_OR, MT_WTBL1_OR_PSM_WRITE); | ||
| 275 | |||
| 276 | mt76_wr(dev, addr + 3 * 4, | ||
| 277 | FIELD_PREP(MT_WTBL1_W3_WTBL2_FRAME_ID, wtbl2_frame) | | ||
| 278 | FIELD_PREP(MT_WTBL1_W3_WTBL2_ENTRY_ID, wtbl2_entry) | | ||
| 279 | FIELD_PREP(MT_WTBL1_W3_WTBL4_FRAME_ID, wtbl4_frame) | | ||
| 280 | MT_WTBL1_W3_I_PSM | MT_WTBL1_W3_KEEP_I_PSM); | ||
| 281 | mt76_wr(dev, addr + 4 * 4, | ||
| 282 | FIELD_PREP(MT_WTBL1_W4_WTBL3_FRAME_ID, wtbl3_frame) | | ||
| 283 | FIELD_PREP(MT_WTBL1_W4_WTBL3_ENTRY_ID, wtbl3_entry) | | ||
| 284 | FIELD_PREP(MT_WTBL1_W4_WTBL4_ENTRY_ID, wtbl4_entry)); | ||
| 285 | |||
| 286 | mt76_clear(dev, MT_WTBL1_OR, MT_WTBL1_OR_PSM_WRITE); | ||
| 287 | |||
| 288 | addr = mt7603_wtbl2_addr(idx); | ||
| 289 | |||
| 290 | /* Clear BA information */ | ||
| 291 | mt76_wr(dev, addr + (15 * 4), 0); | ||
| 292 | |||
| 293 | mt76_stop_tx_ac(dev, GENMASK(3, 0)); | ||
| 294 | for (i = 2; i <= 4; i++) | ||
| 295 | mt76_wr(dev, addr + (i * 4), 0); | ||
| 296 | mt7603_wtbl_update(dev, idx, MT_WTBL_UPDATE_WTBL2); | ||
| 297 | mt76_start_tx_ac(dev, GENMASK(3, 0)); | ||
| 298 | |||
| 299 | mt7603_wtbl_update(dev, idx, MT_WTBL_UPDATE_RX_COUNT_CLEAR); | ||
| 300 | mt7603_wtbl_update(dev, idx, MT_WTBL_UPDATE_TX_COUNT_CLEAR); | ||
| 301 | mt7603_wtbl_update(dev, idx, MT_WTBL_UPDATE_ADM_COUNT_CLEAR); | ||
| 302 | } | ||
| 303 | |||
| 304 | void mt7603_wtbl_update_cap(struct mt7603_dev *dev, struct ieee80211_sta *sta) | ||
| 305 | { | ||
| 306 | struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv; | ||
| 307 | int idx = msta->wcid.idx; | ||
| 308 | u32 addr; | ||
| 309 | u32 val; | ||
| 310 | |||
| 311 | addr = mt7603_wtbl1_addr(idx); | ||
| 312 | |||
| 313 | val = mt76_rr(dev, addr + 2 * 4); | ||
| 314 | val &= MT_WTBL1_W2_KEY_TYPE | MT_WTBL1_W2_ADMISSION_CONTROL; | ||
| 315 | val |= FIELD_PREP(MT_WTBL1_W2_AMPDU_FACTOR, sta->ht_cap.ampdu_factor) | | ||
| 316 | FIELD_PREP(MT_WTBL1_W2_MPDU_DENSITY, sta->ht_cap.ampdu_density) | | ||
| 317 | MT_WTBL1_W2_TXS_BAF_REPORT; | ||
| 318 | |||
| 319 | if (sta->ht_cap.cap) | ||
| 320 | val |= MT_WTBL1_W2_HT; | ||
| 321 | if (sta->vht_cap.cap) | ||
| 322 | val |= MT_WTBL1_W2_VHT; | ||
| 323 | |||
| 324 | mt76_wr(dev, addr + 2 * 4, val); | ||
| 325 | |||
| 326 | addr = mt7603_wtbl2_addr(idx); | ||
| 327 | val = mt76_rr(dev, addr + 9 * 4); | ||
| 328 | val &= ~(MT_WTBL2_W9_SHORT_GI_20 | MT_WTBL2_W9_SHORT_GI_40 | | ||
| 329 | MT_WTBL2_W9_SHORT_GI_80); | ||
| 330 | if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) | ||
| 331 | val |= MT_WTBL2_W9_SHORT_GI_20; | ||
| 332 | if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) | ||
| 333 | val |= MT_WTBL2_W9_SHORT_GI_40; | ||
| 334 | mt76_wr(dev, addr + 9 * 4, val); | ||
| 335 | } | ||
| 336 | |||
| 337 | void mt7603_mac_rx_ba_reset(struct mt7603_dev *dev, void *addr, u8 tid) | ||
| 338 | { | ||
| 339 | mt76_wr(dev, MT_BA_CONTROL_0, get_unaligned_le32(addr)); | ||
| 340 | mt76_wr(dev, MT_BA_CONTROL_1, | ||
| 341 | (get_unaligned_le16(addr + 4) | | ||
| 342 | FIELD_PREP(MT_BA_CONTROL_1_TID, tid) | | ||
| 343 | MT_BA_CONTROL_1_RESET)); | ||
| 344 | } | ||
| 345 | |||
| 346 | void mt7603_mac_tx_ba_reset(struct mt7603_dev *dev, int wcid, int tid, int ssn, | ||
| 347 | int ba_size) | ||
| 348 | { | ||
| 349 | u32 addr = mt7603_wtbl2_addr(wcid); | ||
| 350 | u32 tid_mask = FIELD_PREP(MT_WTBL2_W15_BA_EN_TIDS, BIT(tid)) | | ||
| 351 | (MT_WTBL2_W15_BA_WIN_SIZE << | ||
| 352 | (tid * MT_WTBL2_W15_BA_WIN_SIZE_SHIFT)); | ||
| 353 | u32 tid_val; | ||
| 354 | int i; | ||
| 355 | |||
| 356 | if (ba_size < 0) { | ||
| 357 | /* disable */ | ||
| 358 | mt76_clear(dev, addr + (15 * 4), tid_mask); | ||
| 359 | return; | ||
| 360 | } | ||
| 361 | mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000); | ||
| 362 | |||
| 363 | mt7603_mac_stop(dev); | ||
| 364 | switch (tid) { | ||
| 365 | case 0: | ||
| 366 | mt76_rmw_field(dev, addr + (2 * 4), MT_WTBL2_W2_TID0_SN, ssn); | ||
| 367 | break; | ||
| 368 | case 1: | ||
| 369 | mt76_rmw_field(dev, addr + (2 * 4), MT_WTBL2_W2_TID1_SN, ssn); | ||
| 370 | break; | ||
| 371 | case 2: | ||
| 372 | mt76_rmw_field(dev, addr + (2 * 4), MT_WTBL2_W2_TID2_SN_LO, | ||
| 373 | ssn); | ||
| 374 | mt76_rmw_field(dev, addr + (3 * 4), MT_WTBL2_W3_TID2_SN_HI, | ||
| 375 | ssn >> 8); | ||
| 376 | break; | ||
| 377 | case 3: | ||
| 378 | mt76_rmw_field(dev, addr + (3 * 4), MT_WTBL2_W3_TID3_SN, ssn); | ||
| 379 | break; | ||
| 380 | case 4: | ||
| 381 | mt76_rmw_field(dev, addr + (3 * 4), MT_WTBL2_W3_TID4_SN, ssn); | ||
| 382 | break; | ||
| 383 | case 5: | ||
| 384 | mt76_rmw_field(dev, addr + (3 * 4), MT_WTBL2_W3_TID5_SN_LO, | ||
| 385 | ssn); | ||
| 386 | mt76_rmw_field(dev, addr + (4 * 4), MT_WTBL2_W4_TID5_SN_HI, | ||
| 387 | ssn >> 4); | ||
| 388 | break; | ||
| 389 | case 6: | ||
| 390 | mt76_rmw_field(dev, addr + (4 * 4), MT_WTBL2_W4_TID6_SN, ssn); | ||
| 391 | break; | ||
| 392 | case 7: | ||
| 393 | mt76_rmw_field(dev, addr + (4 * 4), MT_WTBL2_W4_TID7_SN, ssn); | ||
| 394 | break; | ||
| 395 | } | ||
| 396 | mt7603_wtbl_update(dev, wcid, MT_WTBL_UPDATE_WTBL2); | ||
| 397 | mt7603_mac_start(dev); | ||
| 398 | |||
| 399 | for (i = 7; i > 0; i--) { | ||
| 400 | if (ba_size >= MT_AGG_SIZE_LIMIT(i)) | ||
| 401 | break; | ||
| 402 | } | ||
| 403 | |||
| 404 | tid_val = FIELD_PREP(MT_WTBL2_W15_BA_EN_TIDS, BIT(tid)) | | ||
| 405 | i << (tid * MT_WTBL2_W15_BA_WIN_SIZE_SHIFT); | ||
| 406 | |||
| 407 | mt76_rmw(dev, addr + (15 * 4), tid_mask, tid_val); | ||
| 408 | } | ||
| 409 | |||
| 410 | static int | ||
| 411 | mt7603_get_rate(struct mt7603_dev *dev, struct ieee80211_supported_band *sband, | ||
| 412 | int idx, bool cck) | ||
| 413 | { | ||
| 414 | int offset = 0; | ||
| 415 | int len = sband->n_bitrates; | ||
| 416 | int i; | ||
| 417 | |||
| 418 | if (cck) { | ||
| 419 | if (sband == &dev->mt76.sband_5g.sband) | ||
| 420 | return 0; | ||
| 421 | |||
| 422 | idx &= ~BIT(2); /* short preamble */ | ||
| 423 | } else if (sband == &dev->mt76.sband_2g.sband) { | ||
| 424 | offset = 4; | ||
| 425 | } | ||
| 426 | |||
| 427 | for (i = offset; i < len; i++) { | ||
| 428 | if ((sband->bitrates[i].hw_value & GENMASK(7, 0)) == idx) | ||
| 429 | return i; | ||
| 430 | } | ||
| 431 | |||
| 432 | return 0; | ||
| 433 | } | ||
| 434 | |||
| 435 | static struct mt76_wcid * | ||
| 436 | mt7603_rx_get_wcid(struct mt7603_dev *dev, u8 idx, bool unicast) | ||
| 437 | { | ||
| 438 | struct mt7603_sta *sta; | ||
| 439 | struct mt76_wcid *wcid; | ||
| 440 | |||
| 441 | if (idx >= ARRAY_SIZE(dev->mt76.wcid)) | ||
| 442 | return NULL; | ||
| 443 | |||
| 444 | wcid = rcu_dereference(dev->mt76.wcid[idx]); | ||
| 445 | if (unicast || !wcid) | ||
| 446 | return wcid; | ||
| 447 | |||
| 448 | if (!wcid->sta) | ||
| 449 | return NULL; | ||
| 450 | |||
| 451 | sta = container_of(wcid, struct mt7603_sta, wcid); | ||
| 452 | if (!sta->vif) | ||
| 453 | return NULL; | ||
| 454 | |||
| 455 | return &sta->vif->sta.wcid; | ||
| 456 | } | ||
| 457 | |||
| 458 | static void | ||
| 459 | mt7603_insert_ccmp_hdr(struct sk_buff *skb, u8 key_id) | ||
| 460 | { | ||
| 461 | struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; | ||
| 462 | int hdr_len = ieee80211_get_hdrlen_from_skb(skb); | ||
| 463 | u8 *pn = status->iv; | ||
| 464 | u8 *hdr; | ||
| 465 | |||
| 466 | __skb_push(skb, 8); | ||
| 467 | memmove(skb->data, skb->data + 8, hdr_len); | ||
| 468 | hdr = skb->data + hdr_len; | ||
| 469 | |||
| 470 | hdr[0] = pn[5]; | ||
| 471 | hdr[1] = pn[4]; | ||
| 472 | hdr[2] = 0; | ||
| 473 | hdr[3] = 0x20 | (key_id << 6); | ||
| 474 | hdr[4] = pn[3]; | ||
| 475 | hdr[5] = pn[2]; | ||
| 476 | hdr[6] = pn[1]; | ||
| 477 | hdr[7] = pn[0]; | ||
| 478 | |||
| 479 | status->flag &= ~RX_FLAG_IV_STRIPPED; | ||
| 480 | } | ||
| 481 | |||
| 482 | int | ||
| 483 | mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb) | ||
| 484 | { | ||
| 485 | struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; | ||
| 486 | struct ieee80211_supported_band *sband; | ||
| 487 | struct ieee80211_hdr *hdr; | ||
| 488 | __le32 *rxd = (__le32 *)skb->data; | ||
| 489 | u32 rxd0 = le32_to_cpu(rxd[0]); | ||
| 490 | u32 rxd1 = le32_to_cpu(rxd[1]); | ||
| 491 | u32 rxd2 = le32_to_cpu(rxd[2]); | ||
| 492 | bool unicast = rxd1 & MT_RXD1_NORMAL_U2M; | ||
| 493 | bool insert_ccmp_hdr = false; | ||
| 494 | bool remove_pad; | ||
| 495 | int idx; | ||
| 496 | int i; | ||
| 497 | |||
| 498 | memset(status, 0, sizeof(*status)); | ||
| 499 | |||
| 500 | i = FIELD_GET(MT_RXD1_NORMAL_CH_FREQ, rxd1); | ||
| 501 | sband = (i & 1) ? &dev->mt76.sband_5g.sband : &dev->mt76.sband_2g.sband; | ||
| 502 | i >>= 1; | ||
| 503 | |||
| 504 | idx = FIELD_GET(MT_RXD2_NORMAL_WLAN_IDX, rxd2); | ||
| 505 | status->wcid = mt7603_rx_get_wcid(dev, idx, unicast); | ||
| 506 | |||
| 507 | status->band = sband->band; | ||
| 508 | if (i < sband->n_channels) | ||
| 509 | status->freq = sband->channels[i].center_freq; | ||
| 510 | |||
| 511 | if (rxd2 & MT_RXD2_NORMAL_FCS_ERR) | ||
| 512 | status->flag |= RX_FLAG_FAILED_FCS_CRC; | ||
| 513 | |||
| 514 | if (rxd2 & MT_RXD2_NORMAL_TKIP_MIC_ERR) | ||
| 515 | status->flag |= RX_FLAG_MMIC_ERROR; | ||
| 516 | |||
| 517 | if (FIELD_GET(MT_RXD2_NORMAL_SEC_MODE, rxd2) != 0 && | ||
| 518 | !(rxd2 & (MT_RXD2_NORMAL_CLM | MT_RXD2_NORMAL_CM))) { | ||
| 519 | status->flag |= RX_FLAG_DECRYPTED; | ||
| 520 | status->flag |= RX_FLAG_IV_STRIPPED; | ||
| 521 | status->flag |= RX_FLAG_MMIC_STRIPPED | RX_FLAG_MIC_STRIPPED; | ||
| 522 | } | ||
| 523 | |||
| 524 | remove_pad = rxd1 & MT_RXD1_NORMAL_HDR_OFFSET; | ||
| 525 | |||
| 526 | if (rxd2 & MT_RXD2_NORMAL_MAX_LEN_ERROR) | ||
| 527 | return -EINVAL; | ||
| 528 | |||
| 529 | if (!sband->channels) | ||
| 530 | return -EINVAL; | ||
| 531 | |||
| 532 | rxd += 4; | ||
| 533 | if (rxd0 & MT_RXD0_NORMAL_GROUP_4) { | ||
| 534 | rxd += 4; | ||
| 535 | if ((u8 *)rxd - skb->data >= skb->len) | ||
| 536 | return -EINVAL; | ||
| 537 | } | ||
| 538 | if (rxd0 & MT_RXD0_NORMAL_GROUP_1) { | ||
| 539 | u8 *data = (u8 *)rxd; | ||
| 540 | |||
| 541 | if (status->flag & RX_FLAG_DECRYPTED) { | ||
| 542 | status->iv[0] = data[5]; | ||
| 543 | status->iv[1] = data[4]; | ||
| 544 | status->iv[2] = data[3]; | ||
| 545 | status->iv[3] = data[2]; | ||
| 546 | status->iv[4] = data[1]; | ||
| 547 | status->iv[5] = data[0]; | ||
| 548 | |||
| 549 | insert_ccmp_hdr = FIELD_GET(MT_RXD2_NORMAL_FRAG, rxd2); | ||
| 550 | } | ||
| 551 | |||
| 552 | rxd += 4; | ||
| 553 | if ((u8 *)rxd - skb->data >= skb->len) | ||
| 554 | return -EINVAL; | ||
| 555 | } | ||
| 556 | if (rxd0 & MT_RXD0_NORMAL_GROUP_2) { | ||
| 557 | rxd += 2; | ||
| 558 | if ((u8 *)rxd - skb->data >= skb->len) | ||
| 559 | return -EINVAL; | ||
| 560 | } | ||
| 561 | if (rxd0 & MT_RXD0_NORMAL_GROUP_3) { | ||
| 562 | u32 rxdg0 = le32_to_cpu(rxd[0]); | ||
| 563 | u32 rxdg3 = le32_to_cpu(rxd[3]); | ||
| 564 | bool cck = false; | ||
| 565 | |||
| 566 | i = FIELD_GET(MT_RXV1_TX_RATE, rxdg0); | ||
| 567 | switch (FIELD_GET(MT_RXV1_TX_MODE, rxdg0)) { | ||
| 568 | case MT_PHY_TYPE_CCK: | ||
| 569 | cck = true; | ||
| 570 | /* fall through */ | ||
| 571 | case MT_PHY_TYPE_OFDM: | ||
| 572 | i = mt7603_get_rate(dev, sband, i, cck); | ||
| 573 | break; | ||
| 574 | case MT_PHY_TYPE_HT_GF: | ||
| 575 | case MT_PHY_TYPE_HT: | ||
| 576 | status->encoding = RX_ENC_HT; | ||
| 577 | if (i > 15) | ||
| 578 | return -EINVAL; | ||
| 579 | break; | ||
| 580 | default: | ||
| 581 | return -EINVAL; | ||
| 582 | } | ||
| 583 | |||
| 584 | if (rxdg0 & MT_RXV1_HT_SHORT_GI) | ||
| 585 | status->enc_flags |= RX_ENC_FLAG_SHORT_GI; | ||
| 586 | if (rxdg0 & MT_RXV1_HT_AD_CODE) | ||
| 587 | status->enc_flags |= RX_ENC_FLAG_LDPC; | ||
| 588 | |||
| 589 | status->enc_flags |= RX_ENC_FLAG_STBC_MASK * | ||
| 590 | FIELD_GET(MT_RXV1_HT_STBC, rxdg0); | ||
| 591 | |||
| 592 | status->rate_idx = i; | ||
| 593 | |||
| 594 | status->chains = dev->mt76.antenna_mask; | ||
| 595 | status->chain_signal[0] = FIELD_GET(MT_RXV4_IB_RSSI0, rxdg3) + | ||
| 596 | dev->rssi_offset[0]; | ||
| 597 | status->chain_signal[1] = FIELD_GET(MT_RXV4_IB_RSSI1, rxdg3) + | ||
| 598 | dev->rssi_offset[1]; | ||
| 599 | |||
| 600 | status->signal = status->chain_signal[0]; | ||
| 601 | if (status->chains & BIT(1)) | ||
| 602 | status->signal = max(status->signal, | ||
| 603 | status->chain_signal[1]); | ||
| 604 | |||
| 605 | if (FIELD_GET(MT_RXV1_FRAME_MODE, rxdg0) == 1) | ||
| 606 | status->bw = RATE_INFO_BW_40; | ||
| 607 | |||
| 608 | rxd += 6; | ||
| 609 | if ((u8 *)rxd - skb->data >= skb->len) | ||
| 610 | return -EINVAL; | ||
| 611 | } else { | ||
| 612 | return -EINVAL; | ||
| 613 | } | ||
| 614 | |||
| 615 | skb_pull(skb, (u8 *)rxd - skb->data + 2 * remove_pad); | ||
| 616 | |||
| 617 | if (insert_ccmp_hdr) { | ||
| 618 | u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1); | ||
| 619 | |||
| 620 | mt7603_insert_ccmp_hdr(skb, key_id); | ||
| 621 | } | ||
| 622 | |||
| 623 | hdr = (struct ieee80211_hdr *)skb->data; | ||
| 624 | if (!status->wcid || !ieee80211_is_data_qos(hdr->frame_control)) | ||
| 625 | return 0; | ||
| 626 | |||
| 627 | status->aggr = unicast && | ||
| 628 | !ieee80211_is_qos_nullfunc(hdr->frame_control); | ||
| 629 | status->tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; | ||
| 630 | status->seqno = hdr->seq_ctrl >> 4; | ||
| 631 | |||
| 632 | return 0; | ||
| 633 | } | ||
| 634 | |||
| 635 | static u16 | ||
| 636 | mt7603_mac_tx_rate_val(struct mt7603_dev *dev, | ||
| 637 | const struct ieee80211_tx_rate *rate, bool stbc, u8 *bw) | ||
| 638 | { | ||
| 639 | u8 phy, nss, rate_idx; | ||
| 640 | u16 rateval; | ||
| 641 | |||
| 642 | *bw = 0; | ||
| 643 | if (rate->flags & IEEE80211_TX_RC_MCS) { | ||
| 644 | rate_idx = rate->idx; | ||
| 645 | nss = 1 + (rate->idx >> 3); | ||
| 646 | phy = MT_PHY_TYPE_HT; | ||
| 647 | if (rate->flags & IEEE80211_TX_RC_GREEN_FIELD) | ||
| 648 | phy = MT_PHY_TYPE_HT_GF; | ||
| 649 | if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) | ||
| 650 | *bw = 1; | ||
| 651 | } else { | ||
| 652 | const struct ieee80211_rate *r; | ||
| 653 | int band = dev->mt76.chandef.chan->band; | ||
| 654 | u16 val; | ||
| 655 | |||
| 656 | nss = 1; | ||
| 657 | r = &mt76_hw(dev)->wiphy->bands[band]->bitrates[rate->idx]; | ||
| 658 | if (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) | ||
| 659 | val = r->hw_value_short; | ||
| 660 | else | ||
| 661 | val = r->hw_value; | ||
| 662 | |||
| 663 | phy = val >> 8; | ||
| 664 | rate_idx = val & 0xff; | ||
| 665 | } | ||
| 666 | |||
| 667 | rateval = (FIELD_PREP(MT_TX_RATE_IDX, rate_idx) | | ||
| 668 | FIELD_PREP(MT_TX_RATE_MODE, phy)); | ||
| 669 | |||
| 670 | if (stbc && nss == 1) | ||
| 671 | rateval |= MT_TX_RATE_STBC; | ||
| 672 | |||
| 673 | return rateval; | ||
| 674 | } | ||
| 675 | |||
| 676 | void mt7603_wtbl_set_rates(struct mt7603_dev *dev, struct mt7603_sta *sta, | ||
| 677 | struct ieee80211_tx_rate *probe_rate, | ||
| 678 | struct ieee80211_tx_rate *rates) | ||
| 679 | { | ||
| 680 | int wcid = sta->wcid.idx; | ||
| 681 | u32 addr = mt7603_wtbl2_addr(wcid); | ||
| 682 | bool stbc = false; | ||
| 683 | int n_rates = sta->n_rates; | ||
| 684 | u8 bw, bw_prev, bw_idx = 0; | ||
| 685 | u16 val[4]; | ||
| 686 | u16 probe_val; | ||
| 687 | u32 w9 = mt76_rr(dev, addr + 9 * 4); | ||
| 688 | int i; | ||
| 689 | |||
| 690 | if (!mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000)) | ||
| 691 | return; | ||
| 692 | |||
| 693 | for (i = n_rates; i < 4; i++) | ||
| 694 | rates[i] = rates[n_rates - 1]; | ||
| 695 | |||
| 696 | w9 &= MT_WTBL2_W9_SHORT_GI_20 | MT_WTBL2_W9_SHORT_GI_40 | | ||
| 697 | MT_WTBL2_W9_SHORT_GI_80; | ||
| 698 | |||
| 699 | val[0] = mt7603_mac_tx_rate_val(dev, &rates[0], stbc, &bw); | ||
| 700 | bw_prev = bw; | ||
| 701 | |||
| 702 | if (probe_rate) { | ||
| 703 | probe_val = mt7603_mac_tx_rate_val(dev, probe_rate, stbc, &bw); | ||
| 704 | if (bw) | ||
| 705 | bw_idx = 1; | ||
| 706 | else | ||
| 707 | bw_prev = 0; | ||
| 708 | } else { | ||
| 709 | probe_val = val[0]; | ||
| 710 | } | ||
| 711 | |||
| 712 | w9 |= FIELD_PREP(MT_WTBL2_W9_CC_BW_SEL, bw); | ||
| 713 | w9 |= FIELD_PREP(MT_WTBL2_W9_BW_CAP, bw); | ||
| 714 | |||
| 715 | val[1] = mt7603_mac_tx_rate_val(dev, &rates[1], stbc, &bw); | ||
| 716 | if (bw_prev) { | ||
| 717 | bw_idx = 3; | ||
| 718 | bw_prev = bw; | ||
| 719 | } | ||
| 720 | |||
| 721 | val[2] = mt7603_mac_tx_rate_val(dev, &rates[2], stbc, &bw); | ||
| 722 | if (bw_prev) { | ||
| 723 | bw_idx = 5; | ||
| 724 | bw_prev = bw; | ||
| 725 | } | ||
| 726 | |||
| 727 | val[3] = mt7603_mac_tx_rate_val(dev, &rates[3], stbc, &bw); | ||
| 728 | if (bw_prev) | ||
| 729 | bw_idx = 7; | ||
| 730 | |||
| 731 | w9 |= FIELD_PREP(MT_WTBL2_W9_CHANGE_BW_RATE, | ||
| 732 | bw_idx ? bw_idx - 1 : 7); | ||
| 733 | |||
| 734 | mt76_wr(dev, MT_WTBL_RIUCR0, w9); | ||
| 735 | |||
| 736 | mt76_wr(dev, MT_WTBL_RIUCR1, | ||
| 737 | FIELD_PREP(MT_WTBL_RIUCR1_RATE0, probe_val) | | ||
| 738 | FIELD_PREP(MT_WTBL_RIUCR1_RATE1, val[0]) | | ||
| 739 | FIELD_PREP(MT_WTBL_RIUCR1_RATE2_LO, val[0])); | ||
| 740 | |||
| 741 | mt76_wr(dev, MT_WTBL_RIUCR2, | ||
| 742 | FIELD_PREP(MT_WTBL_RIUCR2_RATE2_HI, val[0] >> 8) | | ||
| 743 | FIELD_PREP(MT_WTBL_RIUCR2_RATE3, val[1]) | | ||
| 744 | FIELD_PREP(MT_WTBL_RIUCR2_RATE4, val[1]) | | ||
| 745 | FIELD_PREP(MT_WTBL_RIUCR2_RATE5_LO, val[2])); | ||
| 746 | |||
| 747 | mt76_wr(dev, MT_WTBL_RIUCR3, | ||
| 748 | FIELD_PREP(MT_WTBL_RIUCR3_RATE5_HI, val[2] >> 4) | | ||
| 749 | FIELD_PREP(MT_WTBL_RIUCR3_RATE6, val[2]) | | ||
| 750 | FIELD_PREP(MT_WTBL_RIUCR3_RATE7, val[3])); | ||
| 751 | |||
| 752 | mt76_wr(dev, MT_WTBL_UPDATE, | ||
| 753 | FIELD_PREP(MT_WTBL_UPDATE_WLAN_IDX, wcid) | | ||
| 754 | MT_WTBL_UPDATE_RATE_UPDATE | | ||
| 755 | MT_WTBL_UPDATE_TX_COUNT_CLEAR); | ||
| 756 | |||
| 757 | if (!sta->wcid.tx_rate_set) | ||
| 758 | mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000); | ||
| 759 | |||
| 760 | sta->rate_count = 2 * MT7603_RATE_RETRY * n_rates; | ||
| 761 | sta->wcid.tx_rate_set = true; | ||
| 762 | } | ||
| 763 | |||
| 764 | static enum mt7603_cipher_type | ||
| 765 | mt7603_mac_get_key_info(struct ieee80211_key_conf *key, u8 *key_data) | ||
| 766 | { | ||
| 767 | memset(key_data, 0, 32); | ||
| 768 | if (!key) | ||
| 769 | return MT_CIPHER_NONE; | ||
| 770 | |||
| 771 | if (key->keylen > 32) | ||
| 772 | return MT_CIPHER_NONE; | ||
| 773 | |||
| 774 | memcpy(key_data, key->key, key->keylen); | ||
| 775 | |||
| 776 | switch (key->cipher) { | ||
| 777 | case WLAN_CIPHER_SUITE_WEP40: | ||
| 778 | return MT_CIPHER_WEP40; | ||
| 779 | case WLAN_CIPHER_SUITE_WEP104: | ||
| 780 | return MT_CIPHER_WEP104; | ||
| 781 | case WLAN_CIPHER_SUITE_TKIP: | ||
| 782 | /* Rx/Tx MIC keys are swapped */ | ||
| 783 | memcpy(key_data + 16, key->key + 24, 8); | ||
| 784 | memcpy(key_data + 24, key->key + 16, 8); | ||
| 785 | return MT_CIPHER_TKIP; | ||
| 786 | case WLAN_CIPHER_SUITE_CCMP: | ||
| 787 | return MT_CIPHER_AES_CCMP; | ||
| 788 | default: | ||
| 789 | return MT_CIPHER_NONE; | ||
| 790 | } | ||
| 791 | } | ||
| 792 | |||
| 793 | int mt7603_wtbl_set_key(struct mt7603_dev *dev, int wcid, | ||
| 794 | struct ieee80211_key_conf *key) | ||
| 795 | { | ||
| 796 | enum mt7603_cipher_type cipher; | ||
| 797 | u32 addr = mt7603_wtbl3_addr(wcid); | ||
| 798 | u8 key_data[32]; | ||
| 799 | int key_len = sizeof(key_data); | ||
| 800 | |||
| 801 | cipher = mt7603_mac_get_key_info(key, key_data); | ||
| 802 | if (cipher == MT_CIPHER_NONE && key) | ||
| 803 | return -EOPNOTSUPP; | ||
| 804 | |||
| 805 | if (key && (cipher == MT_CIPHER_WEP40 || cipher == MT_CIPHER_WEP104)) { | ||
| 806 | addr += key->keyidx * 16; | ||
| 807 | key_len = 16; | ||
| 808 | } | ||
| 809 | |||
| 810 | mt76_wr_copy(dev, addr, key_data, key_len); | ||
| 811 | |||
| 812 | addr = mt7603_wtbl1_addr(wcid); | ||
| 813 | mt76_rmw_field(dev, addr + 2 * 4, MT_WTBL1_W2_KEY_TYPE, cipher); | ||
| 814 | if (key) | ||
| 815 | mt76_rmw_field(dev, addr, MT_WTBL1_W0_KEY_IDX, key->keyidx); | ||
| 816 | mt76_rmw_field(dev, addr, MT_WTBL1_W0_RX_KEY_VALID, !!key); | ||
| 817 | |||
| 818 | return 0; | ||
| 819 | } | ||
| 820 | |||
| 821 | static int | ||
| 822 | mt7603_mac_write_txwi(struct mt7603_dev *dev, __le32 *txwi, | ||
| 823 | struct sk_buff *skb, struct mt76_queue *q, | ||
| 824 | struct mt76_wcid *wcid, struct ieee80211_sta *sta, | ||
| 825 | int pid, struct ieee80211_key_conf *key) | ||
| 826 | { | ||
| 827 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
| 828 | struct ieee80211_tx_rate *rate = &info->control.rates[0]; | ||
| 829 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
| 830 | struct ieee80211_vif *vif = info->control.vif; | ||
| 831 | struct mt7603_vif *mvif; | ||
| 832 | int wlan_idx; | ||
| 833 | int hdr_len = ieee80211_get_hdrlen_from_skb(skb); | ||
| 834 | int tx_count = 8; | ||
| 835 | u8 frame_type, frame_subtype; | ||
| 836 | u16 fc = le16_to_cpu(hdr->frame_control); | ||
| 837 | u8 vif_idx = 0; | ||
| 838 | u32 val; | ||
| 839 | u8 bw; | ||
| 840 | |||
| 841 | if (vif) { | ||
| 842 | mvif = (struct mt7603_vif *)vif->drv_priv; | ||
| 843 | vif_idx = mvif->idx; | ||
| 844 | if (vif_idx && q >= &dev->mt76.q_tx[MT_TXQ_BEACON]) | ||
| 845 | vif_idx += 0x10; | ||
| 846 | } | ||
| 847 | |||
| 848 | if (sta) { | ||
| 849 | struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv; | ||
| 850 | |||
| 851 | tx_count = msta->rate_count; | ||
| 852 | } | ||
| 853 | |||
| 854 | if (wcid) | ||
| 855 | wlan_idx = wcid->idx; | ||
| 856 | else | ||
| 857 | wlan_idx = MT7603_WTBL_RESERVED; | ||
| 858 | |||
| 859 | frame_type = (fc & IEEE80211_FCTL_FTYPE) >> 2; | ||
| 860 | frame_subtype = (fc & IEEE80211_FCTL_STYPE) >> 4; | ||
| 861 | |||
| 862 | val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + MT_TXD_SIZE) | | ||
| 863 | FIELD_PREP(MT_TXD0_Q_IDX, q->hw_idx); | ||
| 864 | txwi[0] = cpu_to_le32(val); | ||
| 865 | |||
| 866 | val = MT_TXD1_LONG_FORMAT | | ||
| 867 | FIELD_PREP(MT_TXD1_OWN_MAC, vif_idx) | | ||
| 868 | FIELD_PREP(MT_TXD1_TID, | ||
| 869 | skb->priority & IEEE80211_QOS_CTL_TID_MASK) | | ||
| 870 | FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) | | ||
| 871 | FIELD_PREP(MT_TXD1_HDR_INFO, hdr_len / 2) | | ||
| 872 | FIELD_PREP(MT_TXD1_WLAN_IDX, wlan_idx) | | ||
| 873 | FIELD_PREP(MT_TXD1_PROTECTED, !!key); | ||
| 874 | txwi[1] = cpu_to_le32(val); | ||
| 875 | |||
| 876 | if (info->flags & IEEE80211_TX_CTL_NO_ACK) | ||
| 877 | txwi[1] |= cpu_to_le32(MT_TXD1_NO_ACK); | ||
| 878 | |||
| 879 | val = FIELD_PREP(MT_TXD2_FRAME_TYPE, frame_type) | | ||
| 880 | FIELD_PREP(MT_TXD2_SUB_TYPE, frame_subtype) | | ||
| 881 | FIELD_PREP(MT_TXD2_MULTICAST, | ||
| 882 | is_multicast_ether_addr(hdr->addr1)); | ||
| 883 | txwi[2] = cpu_to_le32(val); | ||
| 884 | |||
| 885 | if (!(info->flags & IEEE80211_TX_CTL_AMPDU)) | ||
| 886 | txwi[2] |= cpu_to_le32(MT_TXD2_BA_DISABLE); | ||
| 887 | |||
| 888 | txwi[4] = 0; | ||
| 889 | |||
| 890 | val = MT_TXD5_TX_STATUS_HOST | MT_TXD5_SW_POWER_MGMT | | ||
| 891 | FIELD_PREP(MT_TXD5_PID, pid); | ||
| 892 | txwi[5] = cpu_to_le32(val); | ||
| 893 | |||
| 894 | txwi[6] = 0; | ||
| 895 | |||
| 896 | if (rate->idx >= 0 && rate->count && | ||
| 897 | !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)) { | ||
| 898 | bool stbc = info->flags & IEEE80211_TX_CTL_STBC; | ||
| 899 | u16 rateval = mt7603_mac_tx_rate_val(dev, rate, stbc, &bw); | ||
| 900 | |||
| 901 | txwi[2] |= cpu_to_le32(MT_TXD2_FIX_RATE); | ||
| 902 | |||
| 903 | val = MT_TXD6_FIXED_BW | | ||
| 904 | FIELD_PREP(MT_TXD6_BW, bw) | | ||
| 905 | FIELD_PREP(MT_TXD6_TX_RATE, rateval); | ||
| 906 | txwi[6] |= cpu_to_le32(val); | ||
| 907 | |||
| 908 | if (rate->flags & IEEE80211_TX_RC_SHORT_GI) | ||
| 909 | txwi[6] |= cpu_to_le32(MT_TXD6_SGI); | ||
| 910 | |||
| 911 | if (!(rate->flags & IEEE80211_TX_RC_MCS)) | ||
| 912 | txwi[2] |= cpu_to_le32(MT_TXD2_BA_DISABLE); | ||
| 913 | |||
| 914 | tx_count = rate->count; | ||
| 915 | } | ||
| 916 | |||
| 917 | /* use maximum tx count for beacons and buffered multicast */ | ||
| 918 | if (q >= &dev->mt76.q_tx[MT_TXQ_BEACON]) | ||
| 919 | tx_count = 0x1f; | ||
| 920 | |||
| 921 | val = FIELD_PREP(MT_TXD3_REM_TX_COUNT, tx_count) | | ||
| 922 | FIELD_PREP(MT_TXD3_SEQ, le16_to_cpu(hdr->seq_ctrl)); | ||
| 923 | txwi[3] = cpu_to_le32(val); | ||
| 924 | |||
| 925 | if (key) { | ||
| 926 | u64 pn = atomic64_inc_return(&key->tx_pn); | ||
| 927 | |||
| 928 | txwi[3] |= cpu_to_le32(MT_TXD3_PN_VALID); | ||
| 929 | txwi[4] = cpu_to_le32(pn & GENMASK(31, 0)); | ||
| 930 | txwi[5] |= cpu_to_le32(FIELD_PREP(MT_TXD5_PN_HIGH, pn >> 32)); | ||
| 931 | } | ||
| 932 | |||
| 933 | txwi[7] = 0; | ||
| 934 | |||
| 935 | return 0; | ||
| 936 | } | ||
| 937 | |||
| 938 | int mt7603_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, | ||
| 939 | struct sk_buff *skb, struct mt76_queue *q, | ||
| 940 | struct mt76_wcid *wcid, struct ieee80211_sta *sta, | ||
| 941 | u32 *tx_info) | ||
| 942 | { | ||
| 943 | struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); | ||
| 944 | struct mt7603_sta *msta = container_of(wcid, struct mt7603_sta, wcid); | ||
| 945 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
| 946 | struct ieee80211_key_conf *key = info->control.hw_key; | ||
| 947 | int pid; | ||
| 948 | |||
| 949 | if (!wcid) | ||
| 950 | wcid = &dev->global_sta.wcid; | ||
| 951 | |||
| 952 | if (sta) { | ||
| 953 | msta = (struct mt7603_sta *)sta->drv_priv; | ||
| 954 | |||
| 955 | if ((info->flags & (IEEE80211_TX_CTL_NO_PS_BUFFER | | ||
| 956 | IEEE80211_TX_CTL_CLEAR_PS_FILT)) || | ||
| 957 | (info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE)) | ||
| 958 | mt7603_wtbl_set_ps(dev, msta, false); | ||
| 959 | } | ||
| 960 | |||
| 961 | pid = mt76_tx_status_skb_add(mdev, wcid, skb); | ||
| 962 | |||
| 963 | if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) { | ||
| 964 | spin_lock_bh(&dev->mt76.lock); | ||
| 965 | msta->rate_probe = true; | ||
| 966 | mt7603_wtbl_set_rates(dev, msta, &info->control.rates[0], | ||
| 967 | msta->rates); | ||
| 968 | spin_unlock_bh(&dev->mt76.lock); | ||
| 969 | } | ||
| 970 | |||
| 971 | mt7603_mac_write_txwi(dev, txwi_ptr, skb, q, wcid, sta, pid, key); | ||
| 972 | |||
| 973 | return 0; | ||
| 974 | } | ||
| 975 | |||
| 976 | static bool | ||
| 977 | mt7603_fill_txs(struct mt7603_dev *dev, struct mt7603_sta *sta, | ||
| 978 | struct ieee80211_tx_info *info, __le32 *txs_data) | ||
| 979 | { | ||
| 980 | struct ieee80211_supported_band *sband; | ||
| 981 | int final_idx = 0; | ||
| 982 | u32 final_rate; | ||
| 983 | u32 final_rate_flags; | ||
| 984 | bool final_mpdu; | ||
| 985 | bool ack_timeout; | ||
| 986 | bool fixed_rate; | ||
| 987 | bool probe; | ||
| 988 | bool ampdu; | ||
| 989 | bool cck = false; | ||
| 990 | int count; | ||
| 991 | u32 txs; | ||
| 992 | u8 pid; | ||
| 993 | int idx; | ||
| 994 | int i; | ||
| 995 | |||
| 996 | fixed_rate = info->status.rates[0].count; | ||
| 997 | probe = !!(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE); | ||
| 998 | |||
| 999 | txs = le32_to_cpu(txs_data[4]); | ||
| 1000 | final_mpdu = txs & MT_TXS4_ACKED_MPDU; | ||
| 1001 | ampdu = !fixed_rate && (txs & MT_TXS4_AMPDU); | ||
| 1002 | pid = FIELD_GET(MT_TXS4_PID, txs); | ||
| 1003 | count = FIELD_GET(MT_TXS4_TX_COUNT, txs); | ||
| 1004 | |||
| 1005 | txs = le32_to_cpu(txs_data[0]); | ||
| 1006 | final_rate = FIELD_GET(MT_TXS0_TX_RATE, txs); | ||
| 1007 | ack_timeout = txs & MT_TXS0_ACK_TIMEOUT; | ||
| 1008 | |||
| 1009 | if (!ampdu && (txs & MT_TXS0_RTS_TIMEOUT)) | ||
| 1010 | return false; | ||
| 1011 | |||
| 1012 | if (txs & MT_TXS0_QUEUE_TIMEOUT) | ||
| 1013 | return false; | ||
| 1014 | |||
| 1015 | if (!ack_timeout) | ||
| 1016 | info->flags |= IEEE80211_TX_STAT_ACK; | ||
| 1017 | |||
| 1018 | info->status.ampdu_len = 1; | ||
| 1019 | info->status.ampdu_ack_len = !!(info->flags & | ||
| 1020 | IEEE80211_TX_STAT_ACK); | ||
| 1021 | |||
| 1022 | if (ampdu || (info->flags & IEEE80211_TX_CTL_AMPDU)) | ||
| 1023 | info->flags |= IEEE80211_TX_STAT_AMPDU | IEEE80211_TX_CTL_AMPDU; | ||
| 1024 | |||
| 1025 | if (fixed_rate && !probe) { | ||
| 1026 | info->status.rates[0].count = count; | ||
| 1027 | goto out; | ||
| 1028 | } | ||
| 1029 | |||
| 1030 | for (i = 0, idx = 0; i < ARRAY_SIZE(info->status.rates); i++) { | ||
| 1031 | int cur_count = min_t(int, count, 2 * MT7603_RATE_RETRY); | ||
| 1032 | |||
| 1033 | if (!i && probe) { | ||
| 1034 | cur_count = 1; | ||
| 1035 | } else { | ||
| 1036 | info->status.rates[i] = sta->rates[idx]; | ||
| 1037 | idx++; | ||
| 1038 | } | ||
| 1039 | |||
| 1040 | if (i && info->status.rates[i].idx < 0) { | ||
| 1041 | info->status.rates[i - 1].count += count; | ||
| 1042 | break; | ||
| 1043 | } | ||
| 1044 | |||
| 1045 | if (!count) { | ||
| 1046 | info->status.rates[i].idx = -1; | ||
| 1047 | break; | ||
| 1048 | } | ||
| 1049 | |||
| 1050 | info->status.rates[i].count = cur_count; | ||
| 1051 | final_idx = i; | ||
| 1052 | count -= cur_count; | ||
| 1053 | } | ||
| 1054 | |||
| 1055 | out: | ||
| 1056 | final_rate_flags = info->status.rates[final_idx].flags; | ||
| 1057 | |||
| 1058 | switch (FIELD_GET(MT_TX_RATE_MODE, final_rate)) { | ||
| 1059 | case MT_PHY_TYPE_CCK: | ||
| 1060 | cck = true; | ||
| 1061 | /* fall through */ | ||
| 1062 | case MT_PHY_TYPE_OFDM: | ||
| 1063 | if (dev->mt76.chandef.chan->band == NL80211_BAND_5GHZ) | ||
| 1064 | sband = &dev->mt76.sband_5g.sband; | ||
| 1065 | else | ||
| 1066 | sband = &dev->mt76.sband_2g.sband; | ||
| 1067 | final_rate &= GENMASK(5, 0); | ||
| 1068 | final_rate = mt7603_get_rate(dev, sband, final_rate, cck); | ||
| 1069 | final_rate_flags = 0; | ||
| 1070 | break; | ||
| 1071 | case MT_PHY_TYPE_HT_GF: | ||
| 1072 | case MT_PHY_TYPE_HT: | ||
| 1073 | final_rate_flags |= IEEE80211_TX_RC_MCS; | ||
| 1074 | final_rate &= GENMASK(5, 0); | ||
| 1075 | if (i > 15) | ||
| 1076 | return false; | ||
| 1077 | break; | ||
| 1078 | default: | ||
| 1079 | return false; | ||
| 1080 | } | ||
| 1081 | |||
| 1082 | info->status.rates[final_idx].idx = final_rate; | ||
| 1083 | info->status.rates[final_idx].flags = final_rate_flags; | ||
| 1084 | |||
| 1085 | return true; | ||
| 1086 | } | ||
| 1087 | |||
| 1088 | static bool | ||
| 1089 | mt7603_mac_add_txs_skb(struct mt7603_dev *dev, struct mt7603_sta *sta, int pid, | ||
| 1090 | __le32 *txs_data) | ||
| 1091 | { | ||
| 1092 | struct mt76_dev *mdev = &dev->mt76; | ||
| 1093 | struct sk_buff_head list; | ||
| 1094 | struct sk_buff *skb; | ||
| 1095 | |||
| 1096 | if (pid < MT_PACKET_ID_FIRST) | ||
| 1097 | return false; | ||
| 1098 | |||
| 1099 | mt76_tx_status_lock(mdev, &list); | ||
| 1100 | skb = mt76_tx_status_skb_get(mdev, &sta->wcid, pid, &list); | ||
| 1101 | if (skb) { | ||
| 1102 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
| 1103 | |||
| 1104 | if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) { | ||
| 1105 | spin_lock_bh(&dev->mt76.lock); | ||
| 1106 | if (sta->rate_probe) { | ||
| 1107 | mt7603_wtbl_set_rates(dev, sta, NULL, | ||
| 1108 | sta->rates); | ||
| 1109 | sta->rate_probe = false; | ||
| 1110 | } | ||
| 1111 | spin_unlock_bh(&dev->mt76.lock); | ||
| 1112 | } | ||
| 1113 | |||
| 1114 | if (!mt7603_fill_txs(dev, sta, info, txs_data)) { | ||
| 1115 | ieee80211_tx_info_clear_status(info); | ||
| 1116 | info->status.rates[0].idx = -1; | ||
| 1117 | } | ||
| 1118 | |||
| 1119 | mt76_tx_status_skb_done(mdev, skb, &list); | ||
| 1120 | } | ||
| 1121 | mt76_tx_status_unlock(mdev, &list); | ||
| 1122 | |||
| 1123 | return !!skb; | ||
| 1124 | } | ||
| 1125 | |||
| 1126 | void mt7603_mac_add_txs(struct mt7603_dev *dev, void *data) | ||
| 1127 | { | ||
| 1128 | struct ieee80211_tx_info info = {}; | ||
| 1129 | struct ieee80211_sta *sta = NULL; | ||
| 1130 | struct mt7603_sta *msta = NULL; | ||
| 1131 | struct mt76_wcid *wcid; | ||
| 1132 | __le32 *txs_data = data; | ||
| 1133 | u32 txs; | ||
| 1134 | u8 wcidx; | ||
| 1135 | u8 pid; | ||
| 1136 | |||
| 1137 | txs = le32_to_cpu(txs_data[4]); | ||
| 1138 | pid = FIELD_GET(MT_TXS4_PID, txs); | ||
| 1139 | txs = le32_to_cpu(txs_data[3]); | ||
| 1140 | wcidx = FIELD_GET(MT_TXS3_WCID, txs); | ||
| 1141 | |||
| 1142 | if (pid == MT_PACKET_ID_NO_ACK) | ||
| 1143 | return; | ||
| 1144 | |||
| 1145 | if (wcidx >= ARRAY_SIZE(dev->mt76.wcid)) | ||
| 1146 | return; | ||
| 1147 | |||
| 1148 | rcu_read_lock(); | ||
| 1149 | |||
| 1150 | wcid = rcu_dereference(dev->mt76.wcid[wcidx]); | ||
| 1151 | if (!wcid) | ||
| 1152 | goto out; | ||
| 1153 | |||
| 1154 | msta = container_of(wcid, struct mt7603_sta, wcid); | ||
| 1155 | sta = wcid_to_sta(wcid); | ||
| 1156 | |||
| 1157 | if (mt7603_mac_add_txs_skb(dev, msta, pid, txs_data)) | ||
| 1158 | goto out; | ||
| 1159 | |||
| 1160 | if (wcidx >= MT7603_WTBL_STA || !sta) | ||
| 1161 | goto out; | ||
| 1162 | |||
| 1163 | if (mt7603_fill_txs(dev, msta, &info, txs_data)) | ||
| 1164 | ieee80211_tx_status_noskb(mt76_hw(dev), sta, &info); | ||
| 1165 | |||
| 1166 | out: | ||
| 1167 | rcu_read_unlock(); | ||
| 1168 | } | ||
| 1169 | |||
| 1170 | void mt7603_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q, | ||
| 1171 | struct mt76_queue_entry *e, bool flush) | ||
| 1172 | { | ||
| 1173 | struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); | ||
| 1174 | struct sk_buff *skb = e->skb; | ||
| 1175 | |||
| 1176 | if (!e->txwi) { | ||
| 1177 | dev_kfree_skb_any(skb); | ||
| 1178 | return; | ||
| 1179 | } | ||
| 1180 | |||
| 1181 | if (q - dev->mt76.q_tx < 4) | ||
| 1182 | dev->tx_hang_check = 0; | ||
| 1183 | |||
| 1184 | mt76_tx_complete_skb(mdev, skb); | ||
| 1185 | } | ||
| 1186 | |||
| 1187 | static bool | ||
| 1188 | wait_for_wpdma(struct mt7603_dev *dev) | ||
| 1189 | { | ||
| 1190 | return mt76_poll(dev, MT_WPDMA_GLO_CFG, | ||
| 1191 | MT_WPDMA_GLO_CFG_TX_DMA_BUSY | | ||
| 1192 | MT_WPDMA_GLO_CFG_RX_DMA_BUSY, | ||
| 1193 | 0, 1000); | ||
| 1194 | } | ||
| 1195 | |||
| 1196 | static void mt7603_pse_reset(struct mt7603_dev *dev) | ||
| 1197 | { | ||
| 1198 | /* Clear previous reset result */ | ||
| 1199 | if (!dev->reset_cause[RESET_CAUSE_RESET_FAILED]) | ||
| 1200 | mt76_clear(dev, MT_MCU_DEBUG_RESET, MT_MCU_DEBUG_RESET_PSE_S); | ||
| 1201 | |||
| 1202 | /* Reset PSE */ | ||
| 1203 | mt76_set(dev, MT_MCU_DEBUG_RESET, MT_MCU_DEBUG_RESET_PSE); | ||
| 1204 | |||
| 1205 | if (!mt76_poll_msec(dev, MT_MCU_DEBUG_RESET, | ||
| 1206 | MT_MCU_DEBUG_RESET_PSE_S, | ||
| 1207 | MT_MCU_DEBUG_RESET_PSE_S, 500)) { | ||
| 1208 | dev->reset_cause[RESET_CAUSE_RESET_FAILED]++; | ||
| 1209 | mt76_clear(dev, MT_MCU_DEBUG_RESET, MT_MCU_DEBUG_RESET_PSE); | ||
| 1210 | } else { | ||
| 1211 | dev->reset_cause[RESET_CAUSE_RESET_FAILED] = 0; | ||
| 1212 | mt76_clear(dev, MT_MCU_DEBUG_RESET, MT_MCU_DEBUG_RESET_QUEUES); | ||
| 1213 | } | ||
| 1214 | |||
| 1215 | if (dev->reset_cause[RESET_CAUSE_RESET_FAILED] >= 3) | ||
| 1216 | dev->reset_cause[RESET_CAUSE_RESET_FAILED] = 0; | ||
| 1217 | } | ||
| 1218 | |||
| 1219 | void mt7603_mac_dma_start(struct mt7603_dev *dev) | ||
| 1220 | { | ||
| 1221 | mt7603_mac_start(dev); | ||
| 1222 | |||
| 1223 | wait_for_wpdma(dev); | ||
| 1224 | usleep_range(50, 100); | ||
| 1225 | |||
| 1226 | mt76_set(dev, MT_WPDMA_GLO_CFG, | ||
| 1227 | (MT_WPDMA_GLO_CFG_TX_DMA_EN | | ||
| 1228 | MT_WPDMA_GLO_CFG_RX_DMA_EN | | ||
| 1229 | FIELD_PREP(MT_WPDMA_GLO_CFG_DMA_BURST_SIZE, 3) | | ||
| 1230 | MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE)); | ||
| 1231 | |||
| 1232 | mt7603_irq_enable(dev, MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL); | ||
| 1233 | } | ||
| 1234 | |||
| 1235 | void mt7603_mac_start(struct mt7603_dev *dev) | ||
| 1236 | { | ||
| 1237 | mt76_clear(dev, MT_ARB_SCR, | ||
| 1238 | MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE); | ||
| 1239 | mt76_wr(dev, MT_WF_ARB_TX_START_0, ~0); | ||
| 1240 | mt76_set(dev, MT_WF_ARB_RQCR, MT_WF_ARB_RQCR_RX_START); | ||
| 1241 | } | ||
| 1242 | |||
| 1243 | void mt7603_mac_stop(struct mt7603_dev *dev) | ||
| 1244 | { | ||
| 1245 | mt76_set(dev, MT_ARB_SCR, | ||
| 1246 | MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE); | ||
| 1247 | mt76_wr(dev, MT_WF_ARB_TX_START_0, 0); | ||
| 1248 | mt76_clear(dev, MT_WF_ARB_RQCR, MT_WF_ARB_RQCR_RX_START); | ||
| 1249 | } | ||
| 1250 | |||
| 1251 | void mt7603_pse_client_reset(struct mt7603_dev *dev) | ||
| 1252 | { | ||
| 1253 | u32 addr; | ||
| 1254 | |||
| 1255 | addr = mt7603_reg_map(dev, MT_CLIENT_BASE_PHYS_ADDR + | ||
| 1256 | MT_CLIENT_RESET_TX); | ||
| 1257 | |||
| 1258 | /* Clear previous reset state */ | ||
| 1259 | mt76_clear(dev, addr, | ||
| 1260 | MT_CLIENT_RESET_TX_R_E_1 | | ||
| 1261 | MT_CLIENT_RESET_TX_R_E_2 | | ||
| 1262 | MT_CLIENT_RESET_TX_R_E_1_S | | ||
| 1263 | MT_CLIENT_RESET_TX_R_E_2_S); | ||
| 1264 | |||
| 1265 | /* Start PSE client TX abort */ | ||
| 1266 | mt76_set(dev, addr, MT_CLIENT_RESET_TX_R_E_1); | ||
| 1267 | mt76_poll_msec(dev, addr, MT_CLIENT_RESET_TX_R_E_1_S, | ||
| 1268 | MT_CLIENT_RESET_TX_R_E_1_S, 500); | ||
| 1269 | |||
| 1270 | mt76_set(dev, addr, MT_CLIENT_RESET_TX_R_E_2); | ||
| 1271 | mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_SW_RESET); | ||
| 1272 | |||
| 1273 | /* Wait for PSE client to clear TX FIFO */ | ||
| 1274 | mt76_poll_msec(dev, addr, MT_CLIENT_RESET_TX_R_E_2_S, | ||
| 1275 | MT_CLIENT_RESET_TX_R_E_2_S, 500); | ||
| 1276 | |||
| 1277 | /* Clear PSE client TX abort state */ | ||
| 1278 | mt76_clear(dev, addr, | ||
| 1279 | MT_CLIENT_RESET_TX_R_E_1 | | ||
| 1280 | MT_CLIENT_RESET_TX_R_E_2); | ||
| 1281 | } | ||
| 1282 | |||
| 1283 | static void mt7603_dma_sched_reset(struct mt7603_dev *dev) | ||
| 1284 | { | ||
| 1285 | if (!is_mt7628(dev)) | ||
| 1286 | return; | ||
| 1287 | |||
| 1288 | mt76_set(dev, MT_SCH_4, MT_SCH_4_RESET); | ||
| 1289 | mt76_clear(dev, MT_SCH_4, MT_SCH_4_RESET); | ||
| 1290 | } | ||
| 1291 | |||
| 1292 | static void mt7603_mac_watchdog_reset(struct mt7603_dev *dev) | ||
| 1293 | { | ||
| 1294 | int beacon_int = dev->beacon_int; | ||
| 1295 | u32 mask = dev->mt76.mmio.irqmask; | ||
| 1296 | int i; | ||
| 1297 | |||
| 1298 | ieee80211_stop_queues(dev->mt76.hw); | ||
| 1299 | set_bit(MT76_RESET, &dev->mt76.state); | ||
| 1300 | |||
| 1301 | /* lock/unlock all queues to ensure that no tx is pending */ | ||
| 1302 | mt76_txq_schedule_all(&dev->mt76); | ||
| 1303 | |||
| 1304 | tasklet_disable(&dev->tx_tasklet); | ||
| 1305 | tasklet_disable(&dev->pre_tbtt_tasklet); | ||
| 1306 | napi_disable(&dev->mt76.napi[0]); | ||
| 1307 | napi_disable(&dev->mt76.napi[1]); | ||
| 1308 | |||
| 1309 | mutex_lock(&dev->mt76.mutex); | ||
| 1310 | |||
| 1311 | mt7603_beacon_set_timer(dev, -1, 0); | ||
| 1312 | |||
| 1313 | if (dev->reset_cause[RESET_CAUSE_RESET_FAILED] || | ||
| 1314 | dev->cur_reset_cause == RESET_CAUSE_RX_PSE_BUSY || | ||
| 1315 | dev->cur_reset_cause == RESET_CAUSE_BEACON_STUCK || | ||
| 1316 | dev->cur_reset_cause == RESET_CAUSE_TX_HANG) | ||
| 1317 | mt7603_pse_reset(dev); | ||
| 1318 | |||
| 1319 | if (dev->reset_cause[RESET_CAUSE_RESET_FAILED]) | ||
| 1320 | goto skip_dma_reset; | ||
| 1321 | |||
| 1322 | mt7603_mac_stop(dev); | ||
| 1323 | |||
| 1324 | mt76_clear(dev, MT_WPDMA_GLO_CFG, | ||
| 1325 | MT_WPDMA_GLO_CFG_RX_DMA_EN | MT_WPDMA_GLO_CFG_TX_DMA_EN | | ||
| 1326 | MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE); | ||
| 1327 | usleep_range(1000, 2000); | ||
| 1328 | |||
| 1329 | mt7603_irq_disable(dev, mask); | ||
| 1330 | |||
| 1331 | mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_FORCE_TX_EOF); | ||
| 1332 | |||
| 1333 | mt7603_pse_client_reset(dev); | ||
| 1334 | |||
| 1335 | for (i = 0; i < ARRAY_SIZE(dev->mt76.q_tx); i++) | ||
| 1336 | mt76_queue_tx_cleanup(dev, i, true); | ||
| 1337 | |||
| 1338 | for (i = 0; i < ARRAY_SIZE(dev->mt76.q_rx); i++) | ||
| 1339 | mt76_queue_rx_reset(dev, i); | ||
| 1340 | |||
| 1341 | mt7603_dma_sched_reset(dev); | ||
| 1342 | |||
| 1343 | mt7603_mac_dma_start(dev); | ||
| 1344 | |||
| 1345 | mt7603_irq_enable(dev, mask); | ||
| 1346 | |||
| 1347 | skip_dma_reset: | ||
| 1348 | clear_bit(MT76_RESET, &dev->mt76.state); | ||
| 1349 | mutex_unlock(&dev->mt76.mutex); | ||
| 1350 | |||
| 1351 | tasklet_enable(&dev->tx_tasklet); | ||
| 1352 | tasklet_schedule(&dev->tx_tasklet); | ||
| 1353 | |||
| 1354 | tasklet_enable(&dev->pre_tbtt_tasklet); | ||
| 1355 | mt7603_beacon_set_timer(dev, -1, beacon_int); | ||
| 1356 | |||
| 1357 | napi_enable(&dev->mt76.napi[0]); | ||
| 1358 | napi_schedule(&dev->mt76.napi[0]); | ||
| 1359 | |||
| 1360 | napi_enable(&dev->mt76.napi[1]); | ||
| 1361 | napi_schedule(&dev->mt76.napi[1]); | ||
| 1362 | |||
| 1363 | ieee80211_wake_queues(dev->mt76.hw); | ||
| 1364 | mt76_txq_schedule_all(&dev->mt76); | ||
| 1365 | } | ||
| 1366 | |||
| 1367 | static u32 mt7603_dma_debug(struct mt7603_dev *dev, u8 index) | ||
| 1368 | { | ||
| 1369 | u32 val; | ||
| 1370 | |||
| 1371 | mt76_wr(dev, MT_WPDMA_DEBUG, | ||
| 1372 | FIELD_PREP(MT_WPDMA_DEBUG_IDX, index) | | ||
| 1373 | MT_WPDMA_DEBUG_SEL); | ||
| 1374 | |||
| 1375 | val = mt76_rr(dev, MT_WPDMA_DEBUG); | ||
| 1376 | return FIELD_GET(MT_WPDMA_DEBUG_VALUE, val); | ||
| 1377 | } | ||
| 1378 | |||
| 1379 | static bool mt7603_rx_fifo_busy(struct mt7603_dev *dev) | ||
| 1380 | { | ||
| 1381 | if (is_mt7628(dev)) | ||
| 1382 | return mt7603_dma_debug(dev, 9) & BIT(9); | ||
| 1383 | |||
| 1384 | return mt7603_dma_debug(dev, 2) & BIT(8); | ||
| 1385 | } | ||
| 1386 | |||
| 1387 | static bool mt7603_rx_dma_busy(struct mt7603_dev *dev) | ||
| 1388 | { | ||
| 1389 | if (!(mt76_rr(dev, MT_WPDMA_GLO_CFG) & MT_WPDMA_GLO_CFG_RX_DMA_BUSY)) | ||
| 1390 | return false; | ||
| 1391 | |||
| 1392 | return mt7603_rx_fifo_busy(dev); | ||
| 1393 | } | ||
| 1394 | |||
| 1395 | static bool mt7603_tx_dma_busy(struct mt7603_dev *dev) | ||
| 1396 | { | ||
| 1397 | u32 val; | ||
| 1398 | |||
| 1399 | if (!(mt76_rr(dev, MT_WPDMA_GLO_CFG) & MT_WPDMA_GLO_CFG_TX_DMA_BUSY)) | ||
| 1400 | return false; | ||
| 1401 | |||
| 1402 | val = mt7603_dma_debug(dev, 9); | ||
| 1403 | return (val & BIT(8)) && (val & 0xf) != 0xf; | ||
| 1404 | } | ||
| 1405 | |||
| 1406 | static bool mt7603_tx_hang(struct mt7603_dev *dev) | ||
| 1407 | { | ||
| 1408 | struct mt76_queue *q; | ||
| 1409 | u32 dma_idx, prev_dma_idx; | ||
| 1410 | int i; | ||
| 1411 | |||
| 1412 | for (i = 0; i < 4; i++) { | ||
| 1413 | q = &dev->mt76.q_tx[i]; | ||
| 1414 | |||
| 1415 | if (!q->queued) | ||
| 1416 | continue; | ||
| 1417 | |||
| 1418 | prev_dma_idx = dev->tx_dma_idx[i]; | ||
| 1419 | dma_idx = ioread32(&q->regs->dma_idx); | ||
| 1420 | dev->tx_dma_idx[i] = dma_idx; | ||
| 1421 | |||
| 1422 | if (dma_idx == prev_dma_idx && | ||
| 1423 | dma_idx != ioread32(&q->regs->cpu_idx)) | ||
| 1424 | break; | ||
| 1425 | } | ||
| 1426 | |||
| 1427 | return i < 4; | ||
| 1428 | } | ||
| 1429 | |||
| 1430 | static bool mt7603_rx_pse_busy(struct mt7603_dev *dev) | ||
| 1431 | { | ||
| 1432 | u32 addr, val; | ||
| 1433 | |||
| 1434 | if (mt76_rr(dev, MT_MCU_DEBUG_RESET) & MT_MCU_DEBUG_RESET_QUEUES) | ||
| 1435 | return true; | ||
| 1436 | |||
| 1437 | if (mt7603_rx_fifo_busy(dev)) | ||
| 1438 | return false; | ||
| 1439 | |||
| 1440 | addr = mt7603_reg_map(dev, MT_CLIENT_BASE_PHYS_ADDR + MT_CLIENT_STATUS); | ||
| 1441 | mt76_wr(dev, addr, 3); | ||
| 1442 | val = mt76_rr(dev, addr) >> 16; | ||
| 1443 | |||
| 1444 | if (is_mt7628(dev) && (val & 0x4001) == 0x4001) | ||
| 1445 | return true; | ||
| 1446 | |||
| 1447 | return (val & 0x8001) == 0x8001 || (val & 0xe001) == 0xe001; | ||
| 1448 | } | ||
| 1449 | |||
| 1450 | static bool | ||
| 1451 | mt7603_watchdog_check(struct mt7603_dev *dev, u8 *counter, | ||
| 1452 | enum mt7603_reset_cause cause, | ||
| 1453 | bool (*check)(struct mt7603_dev *dev)) | ||
| 1454 | { | ||
| 1455 | if (dev->reset_test == cause + 1) { | ||
| 1456 | dev->reset_test = 0; | ||
| 1457 | goto trigger; | ||
| 1458 | } | ||
| 1459 | |||
| 1460 | if (check) { | ||
| 1461 | if (!check(dev) && *counter < MT7603_WATCHDOG_TIMEOUT) { | ||
| 1462 | *counter = 0; | ||
| 1463 | return false; | ||
| 1464 | } | ||
| 1465 | |||
| 1466 | (*counter)++; | ||
| 1467 | } | ||
| 1468 | |||
| 1469 | if (*counter < MT7603_WATCHDOG_TIMEOUT) | ||
| 1470 | return false; | ||
| 1471 | trigger: | ||
| 1472 | dev->cur_reset_cause = cause; | ||
| 1473 | dev->reset_cause[cause]++; | ||
| 1474 | return true; | ||
| 1475 | } | ||
| 1476 | |||
| 1477 | void mt7603_update_channel(struct mt76_dev *mdev) | ||
| 1478 | { | ||
| 1479 | struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); | ||
| 1480 | struct mt76_channel_state *state; | ||
| 1481 | ktime_t cur_time; | ||
| 1482 | u32 busy; | ||
| 1483 | |||
| 1484 | if (!test_bit(MT76_STATE_RUNNING, &dev->mt76.state)) | ||
| 1485 | return; | ||
| 1486 | |||
| 1487 | state = mt76_channel_state(&dev->mt76, dev->mt76.chandef.chan); | ||
| 1488 | busy = mt76_rr(dev, MT_MIB_STAT_PSCCA); | ||
| 1489 | |||
| 1490 | spin_lock_bh(&dev->mt76.cc_lock); | ||
| 1491 | cur_time = ktime_get_boottime(); | ||
| 1492 | state->cc_busy += busy; | ||
| 1493 | state->cc_active += ktime_to_us(ktime_sub(cur_time, dev->survey_time)); | ||
| 1494 | dev->survey_time = cur_time; | ||
| 1495 | spin_unlock_bh(&dev->mt76.cc_lock); | ||
| 1496 | } | ||
| 1497 | |||
| 1498 | void | ||
| 1499 | mt7603_edcca_set_strict(struct mt7603_dev *dev, bool val) | ||
| 1500 | { | ||
| 1501 | u32 rxtd_6 = 0xd7c80000; | ||
| 1502 | |||
| 1503 | if (val == dev->ed_strict_mode) | ||
| 1504 | return; | ||
| 1505 | |||
| 1506 | dev->ed_strict_mode = val; | ||
| 1507 | |||
| 1508 | /* Ensure that ED/CCA does not trigger if disabled */ | ||
| 1509 | if (!dev->ed_monitor) | ||
| 1510 | rxtd_6 |= FIELD_PREP(MT_RXTD_6_CCAED_TH, 0x34); | ||
| 1511 | else | ||
| 1512 | rxtd_6 |= FIELD_PREP(MT_RXTD_6_CCAED_TH, 0x7d); | ||
| 1513 | |||
| 1514 | if (dev->ed_monitor && !dev->ed_strict_mode) | ||
| 1515 | rxtd_6 |= FIELD_PREP(MT_RXTD_6_ACI_TH, 0x0f); | ||
| 1516 | else | ||
| 1517 | rxtd_6 |= FIELD_PREP(MT_RXTD_6_ACI_TH, 0x10); | ||
| 1518 | |||
| 1519 | mt76_wr(dev, MT_RXTD(6), rxtd_6); | ||
| 1520 | |||
| 1521 | mt76_rmw_field(dev, MT_RXTD(13), MT_RXTD_13_ACI_TH_EN, | ||
| 1522 | dev->ed_monitor && !dev->ed_strict_mode); | ||
| 1523 | } | ||
| 1524 | |||
| 1525 | static void | ||
| 1526 | mt7603_edcca_check(struct mt7603_dev *dev) | ||
| 1527 | { | ||
| 1528 | u32 val = mt76_rr(dev, MT_AGC(41)); | ||
| 1529 | ktime_t cur_time; | ||
| 1530 | int rssi0, rssi1; | ||
| 1531 | u32 active; | ||
| 1532 | u32 ed_busy; | ||
| 1533 | |||
| 1534 | if (!dev->ed_monitor) | ||
| 1535 | return; | ||
| 1536 | |||
| 1537 | rssi0 = FIELD_GET(MT_AGC_41_RSSI_0, val); | ||
| 1538 | if (rssi0 > 128) | ||
| 1539 | rssi0 -= 256; | ||
| 1540 | |||
| 1541 | rssi1 = FIELD_GET(MT_AGC_41_RSSI_1, val); | ||
| 1542 | if (rssi1 > 128) | ||
| 1543 | rssi1 -= 256; | ||
| 1544 | |||
| 1545 | if (max(rssi0, rssi1) >= -40 && | ||
| 1546 | dev->ed_strong_signal < MT7603_EDCCA_BLOCK_TH) | ||
| 1547 | dev->ed_strong_signal++; | ||
| 1548 | else if (dev->ed_strong_signal > 0) | ||
| 1549 | dev->ed_strong_signal--; | ||
| 1550 | |||
| 1551 | cur_time = ktime_get_boottime(); | ||
| 1552 | ed_busy = mt76_rr(dev, MT_MIB_STAT_ED) & MT_MIB_STAT_ED_MASK; | ||
| 1553 | |||
| 1554 | active = ktime_to_us(ktime_sub(cur_time, dev->ed_time)); | ||
| 1555 | dev->ed_time = cur_time; | ||
| 1556 | |||
| 1557 | if (!active) | ||
| 1558 | return; | ||
| 1559 | |||
| 1560 | if (100 * ed_busy / active > 90) { | ||
| 1561 | if (dev->ed_trigger < 0) | ||
| 1562 | dev->ed_trigger = 0; | ||
| 1563 | dev->ed_trigger++; | ||
| 1564 | } else { | ||
| 1565 | if (dev->ed_trigger > 0) | ||
| 1566 | dev->ed_trigger = 0; | ||
| 1567 | dev->ed_trigger--; | ||
| 1568 | } | ||
| 1569 | |||
| 1570 | if (dev->ed_trigger > MT7603_EDCCA_BLOCK_TH || | ||
| 1571 | dev->ed_strong_signal < MT7603_EDCCA_BLOCK_TH / 2) { | ||
| 1572 | mt7603_edcca_set_strict(dev, true); | ||
| 1573 | } else if (dev->ed_trigger < -MT7603_EDCCA_BLOCK_TH) { | ||
| 1574 | mt7603_edcca_set_strict(dev, false); | ||
| 1575 | } | ||
| 1576 | |||
| 1577 | if (dev->ed_trigger > MT7603_EDCCA_BLOCK_TH) | ||
| 1578 | dev->ed_trigger = MT7603_EDCCA_BLOCK_TH; | ||
| 1579 | else if (dev->ed_trigger < -MT7603_EDCCA_BLOCK_TH) | ||
| 1580 | dev->ed_trigger = -MT7603_EDCCA_BLOCK_TH; | ||
| 1581 | } | ||
| 1582 | |||
| 1583 | void mt7603_cca_stats_reset(struct mt7603_dev *dev) | ||
| 1584 | { | ||
| 1585 | mt76_set(dev, MT_PHYCTRL(2), MT_PHYCTRL_2_STATUS_RESET); | ||
| 1586 | mt76_clear(dev, MT_PHYCTRL(2), MT_PHYCTRL_2_STATUS_RESET); | ||
| 1587 | mt76_set(dev, MT_PHYCTRL(2), MT_PHYCTRL_2_STATUS_EN); | ||
| 1588 | } | ||
| 1589 | |||
| 1590 | static void | ||
| 1591 | mt7603_adjust_sensitivity(struct mt7603_dev *dev) | ||
| 1592 | { | ||
| 1593 | u32 agc0 = dev->agc0, agc3 = dev->agc3; | ||
| 1594 | u32 adj; | ||
| 1595 | |||
| 1596 | if (!dev->sensitivity || dev->sensitivity < -100) { | ||
| 1597 | dev->sensitivity = 0; | ||
| 1598 | } else if (dev->sensitivity <= -84) { | ||
| 1599 | adj = 7 + (dev->sensitivity + 92) / 2; | ||
| 1600 | |||
| 1601 | agc0 = 0x56f0076f; | ||
| 1602 | agc0 |= adj << 12; | ||
| 1603 | agc0 |= adj << 16; | ||
| 1604 | agc3 = 0x81d0d5e3; | ||
| 1605 | } else if (dev->sensitivity <= -72) { | ||
| 1606 | adj = 7 + (dev->sensitivity + 80) / 2; | ||
| 1607 | |||
| 1608 | agc0 = 0x6af0006f; | ||
| 1609 | agc0 |= adj << 8; | ||
| 1610 | agc0 |= adj << 12; | ||
| 1611 | agc0 |= adj << 16; | ||
| 1612 | |||
| 1613 | agc3 = 0x8181d5e3; | ||
| 1614 | } else { | ||
| 1615 | if (dev->sensitivity > -54) | ||
| 1616 | dev->sensitivity = -54; | ||
| 1617 | |||
| 1618 | adj = 7 + (dev->sensitivity + 80) / 2; | ||
| 1619 | |||
| 1620 | agc0 = 0x7ff0000f; | ||
| 1621 | agc0 |= adj << 4; | ||
| 1622 | agc0 |= adj << 8; | ||
| 1623 | agc0 |= adj << 12; | ||
| 1624 | agc0 |= adj << 16; | ||
| 1625 | |||
| 1626 | agc3 = 0x818181e3; | ||
| 1627 | } | ||
| 1628 | |||
| 1629 | mt76_wr(dev, MT_AGC(0), agc0); | ||
| 1630 | mt76_wr(dev, MT_AGC1(0), agc0); | ||
| 1631 | |||
| 1632 | mt76_wr(dev, MT_AGC(3), agc3); | ||
| 1633 | mt76_wr(dev, MT_AGC1(3), agc3); | ||
| 1634 | } | ||
| 1635 | |||
| 1636 | static void | ||
| 1637 | mt7603_false_cca_check(struct mt7603_dev *dev) | ||
| 1638 | { | ||
| 1639 | int pd_cck, pd_ofdm, mdrdy_cck, mdrdy_ofdm; | ||
| 1640 | int false_cca; | ||
| 1641 | int min_signal; | ||
| 1642 | u32 val; | ||
| 1643 | |||
| 1644 | val = mt76_rr(dev, MT_PHYCTRL_STAT_PD); | ||
| 1645 | pd_cck = FIELD_GET(MT_PHYCTRL_STAT_PD_CCK, val); | ||
| 1646 | pd_ofdm = FIELD_GET(MT_PHYCTRL_STAT_PD_OFDM, val); | ||
| 1647 | |||
| 1648 | val = mt76_rr(dev, MT_PHYCTRL_STAT_MDRDY); | ||
| 1649 | mdrdy_cck = FIELD_GET(MT_PHYCTRL_STAT_MDRDY_CCK, val); | ||
| 1650 | mdrdy_ofdm = FIELD_GET(MT_PHYCTRL_STAT_MDRDY_OFDM, val); | ||
| 1651 | |||
| 1652 | dev->false_cca_ofdm = pd_ofdm - mdrdy_ofdm; | ||
| 1653 | dev->false_cca_cck = pd_cck - mdrdy_cck; | ||
| 1654 | |||
| 1655 | mt7603_cca_stats_reset(dev); | ||
| 1656 | |||
| 1657 | min_signal = mt76_get_min_avg_rssi(&dev->mt76); | ||
| 1658 | if (!min_signal) { | ||
| 1659 | dev->sensitivity = 0; | ||
| 1660 | dev->last_cca_adj = jiffies; | ||
| 1661 | goto out; | ||
| 1662 | } | ||
| 1663 | |||
| 1664 | min_signal -= 15; | ||
| 1665 | |||
| 1666 | false_cca = dev->false_cca_ofdm + dev->false_cca_cck; | ||
| 1667 | if (false_cca > 600) { | ||
| 1668 | if (!dev->sensitivity) | ||
| 1669 | dev->sensitivity = -92; | ||
| 1670 | else | ||
| 1671 | dev->sensitivity += 2; | ||
| 1672 | dev->last_cca_adj = jiffies; | ||
| 1673 | } else if (false_cca < 100 || | ||
| 1674 | time_after(jiffies, dev->last_cca_adj + 10 * HZ)) { | ||
| 1675 | dev->last_cca_adj = jiffies; | ||
| 1676 | if (!dev->sensitivity) | ||
| 1677 | goto out; | ||
| 1678 | |||
| 1679 | dev->sensitivity -= 2; | ||
| 1680 | } | ||
| 1681 | |||
| 1682 | if (dev->sensitivity && dev->sensitivity > min_signal) { | ||
| 1683 | dev->sensitivity = min_signal; | ||
| 1684 | dev->last_cca_adj = jiffies; | ||
| 1685 | } | ||
| 1686 | |||
| 1687 | out: | ||
| 1688 | mt7603_adjust_sensitivity(dev); | ||
| 1689 | } | ||
| 1690 | |||
| 1691 | void mt7603_mac_work(struct work_struct *work) | ||
| 1692 | { | ||
| 1693 | struct mt7603_dev *dev = container_of(work, struct mt7603_dev, | ||
| 1694 | mac_work.work); | ||
| 1695 | bool reset = false; | ||
| 1696 | |||
| 1697 | mt76_tx_status_check(&dev->mt76, NULL, false); | ||
| 1698 | |||
| 1699 | mutex_lock(&dev->mt76.mutex); | ||
| 1700 | |||
| 1701 | dev->mac_work_count++; | ||
| 1702 | mt7603_update_channel(&dev->mt76); | ||
| 1703 | mt7603_edcca_check(dev); | ||
| 1704 | |||
| 1705 | if (dev->mac_work_count == 10) | ||
| 1706 | mt7603_false_cca_check(dev); | ||
| 1707 | |||
| 1708 | if (mt7603_watchdog_check(dev, &dev->rx_pse_check, | ||
| 1709 | RESET_CAUSE_RX_PSE_BUSY, | ||
| 1710 | mt7603_rx_pse_busy) || | ||
| 1711 | mt7603_watchdog_check(dev, &dev->beacon_check, | ||
| 1712 | RESET_CAUSE_BEACON_STUCK, | ||
| 1713 | NULL) || | ||
| 1714 | mt7603_watchdog_check(dev, &dev->tx_hang_check, | ||
| 1715 | RESET_CAUSE_TX_HANG, | ||
| 1716 | mt7603_tx_hang) || | ||
| 1717 | mt7603_watchdog_check(dev, &dev->tx_dma_check, | ||
| 1718 | RESET_CAUSE_TX_BUSY, | ||
| 1719 | mt7603_tx_dma_busy) || | ||
| 1720 | mt7603_watchdog_check(dev, &dev->rx_dma_check, | ||
| 1721 | RESET_CAUSE_RX_BUSY, | ||
| 1722 | mt7603_rx_dma_busy) || | ||
| 1723 | mt7603_watchdog_check(dev, &dev->mcu_hang, | ||
| 1724 | RESET_CAUSE_MCU_HANG, | ||
| 1725 | NULL) || | ||
| 1726 | dev->reset_cause[RESET_CAUSE_RESET_FAILED]) { | ||
| 1727 | dev->beacon_check = 0; | ||
| 1728 | dev->tx_dma_check = 0; | ||
| 1729 | dev->tx_hang_check = 0; | ||
| 1730 | dev->rx_dma_check = 0; | ||
| 1731 | dev->rx_pse_check = 0; | ||
| 1732 | dev->mcu_hang = 0; | ||
| 1733 | dev->rx_dma_idx = ~0; | ||
| 1734 | memset(dev->tx_dma_idx, 0xff, sizeof(dev->tx_dma_idx)); | ||
| 1735 | reset = true; | ||
| 1736 | dev->mac_work_count = 0; | ||
| 1737 | } | ||
| 1738 | |||
| 1739 | if (dev->mac_work_count >= 10) | ||
| 1740 | dev->mac_work_count = 0; | ||
| 1741 | |||
| 1742 | mutex_unlock(&dev->mt76.mutex); | ||
| 1743 | |||
| 1744 | if (reset) | ||
| 1745 | mt7603_mac_watchdog_reset(dev); | ||
| 1746 | |||
| 1747 | ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work, | ||
| 1748 | msecs_to_jiffies(MT7603_WATCHDOG_TIME)); | ||
| 1749 | } | ||
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.h b/drivers/net/wireless/mediatek/mt76/mt7603/mac.h new file mode 100644 index 000000000000..17e34ecf2bfb --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.h | |||
| @@ -0,0 +1,242 @@ | |||
| 1 | /* SPDX-License-Identifier: ISC */ | ||
| 2 | |||
| 3 | #ifndef __MT7603_MAC_H | ||
| 4 | #define __MT7603_MAC_H | ||
| 5 | |||
| 6 | #define MT_RXD0_LENGTH GENMASK(15, 0) | ||
| 7 | #define MT_RXD0_PKT_TYPE GENMASK(31, 29) | ||
| 8 | |||
| 9 | #define MT_RXD0_NORMAL_ETH_TYPE_OFS GENMASK(22, 16) | ||
| 10 | #define MT_RXD0_NORMAL_IP_SUM BIT(23) | ||
| 11 | #define MT_RXD0_NORMAL_UDP_TCP_SUM BIT(24) | ||
| 12 | #define MT_RXD0_NORMAL_GROUP_1 BIT(25) | ||
| 13 | #define MT_RXD0_NORMAL_GROUP_2 BIT(26) | ||
| 14 | #define MT_RXD0_NORMAL_GROUP_3 BIT(27) | ||
| 15 | #define MT_RXD0_NORMAL_GROUP_4 BIT(28) | ||
| 16 | |||
| 17 | enum rx_pkt_type { | ||
| 18 | PKT_TYPE_TXS = 0, | ||
| 19 | PKT_TYPE_TXRXV = 1, | ||
| 20 | PKT_TYPE_NORMAL = 2, | ||
| 21 | PKT_TYPE_RX_DUP_RFB = 3, | ||
| 22 | PKT_TYPE_RX_TMR = 4, | ||
| 23 | PKT_TYPE_RETRIEVE = 5, | ||
| 24 | PKT_TYPE_RX_EVENT = 7, | ||
| 25 | }; | ||
| 26 | |||
| 27 | #define MT_RXD1_NORMAL_BSSID GENMASK(31, 26) | ||
| 28 | #define MT_RXD1_NORMAL_PAYLOAD_FORMAT GENMASK(25, 24) | ||
| 29 | #define MT_RXD1_NORMAL_HDR_TRANS BIT(23) | ||
| 30 | #define MT_RXD1_NORMAL_HDR_OFFSET BIT(22) | ||
| 31 | #define MT_RXD1_NORMAL_MAC_HDR_LEN GENMASK(21, 16) | ||
| 32 | #define MT_RXD1_NORMAL_CH_FREQ GENMASK(15, 8) | ||
| 33 | #define MT_RXD1_NORMAL_KEY_ID GENMASK(7, 6) | ||
| 34 | #define MT_RXD1_NORMAL_BEACON_UC BIT(5) | ||
| 35 | #define MT_RXD1_NORMAL_BEACON_MC BIT(4) | ||
| 36 | #define MT_RXD1_NORMAL_BCAST BIT(3) | ||
| 37 | #define MT_RXD1_NORMAL_MCAST BIT(2) | ||
| 38 | #define MT_RXD1_NORMAL_U2M BIT(1) | ||
| 39 | #define MT_RXD1_NORMAL_HTC_VLD BIT(0) | ||
| 40 | |||
| 41 | #define MT_RXD2_NORMAL_NON_AMPDU BIT(31) | ||
| 42 | #define MT_RXD2_NORMAL_NON_AMPDU_SUB BIT(30) | ||
| 43 | #define MT_RXD2_NORMAL_NDATA BIT(29) | ||
| 44 | #define MT_RXD2_NORMAL_NULL_FRAME BIT(28) | ||
| 45 | #define MT_RXD2_NORMAL_FRAG BIT(27) | ||
| 46 | #define MT_RXD2_NORMAL_UDF_VALID BIT(26) | ||
| 47 | #define MT_RXD2_NORMAL_LLC_MIS BIT(25) | ||
| 48 | #define MT_RXD2_NORMAL_MAX_LEN_ERROR BIT(24) | ||
| 49 | #define MT_RXD2_NORMAL_AMSDU_ERR BIT(23) | ||
| 50 | #define MT_RXD2_NORMAL_LEN_MISMATCH BIT(22) | ||
| 51 | #define MT_RXD2_NORMAL_TKIP_MIC_ERR BIT(21) | ||
| 52 | #define MT_RXD2_NORMAL_ICV_ERR BIT(20) | ||
| 53 | #define MT_RXD2_NORMAL_CLM BIT(19) | ||
| 54 | #define MT_RXD2_NORMAL_CM BIT(18) | ||
| 55 | #define MT_RXD2_NORMAL_FCS_ERR BIT(17) | ||
| 56 | #define MT_RXD2_NORMAL_SW_BIT BIT(16) | ||
| 57 | #define MT_RXD2_NORMAL_SEC_MODE GENMASK(15, 12) | ||
| 58 | #define MT_RXD2_NORMAL_TID GENMASK(11, 8) | ||
| 59 | #define MT_RXD2_NORMAL_WLAN_IDX GENMASK(7, 0) | ||
| 60 | |||
| 61 | #define MT_RXD3_NORMAL_PF_STS GENMASK(31, 30) | ||
| 62 | #define MT_RXD3_NORMAL_PF_MODE BIT(29) | ||
| 63 | #define MT_RXD3_NORMAL_CLS_BITMAP GENMASK(28, 19) | ||
| 64 | #define MT_RXD3_NORMAL_WOL GENMASK(18, 14) | ||
| 65 | #define MT_RXD3_NORMAL_MAGIC_PKT BIT(13) | ||
| 66 | #define MT_RXD3_NORMAL_OFLD GENMASK(12, 11) | ||
| 67 | #define MT_RXD3_NORMAL_CLS BIT(10) | ||
| 68 | #define MT_RXD3_NORMAL_PATTERN_DROP BIT(9) | ||
| 69 | #define MT_RXD3_NORMAL_TSF_COMPARE_LOSS BIT(8) | ||
| 70 | #define MT_RXD3_NORMAL_RXV_SEQ GENMASK(7, 0) | ||
| 71 | |||
| 72 | #define MT_RXV1_VHTA1_B5_B4 GENMASK(31, 30) | ||
| 73 | #define MT_RXV1_VHTA2_B8_B1 GENMASK(29, 22) | ||
| 74 | #define MT_RXV1_HT_NO_SOUND BIT(21) | ||
| 75 | #define MT_RXV1_HT_SMOOTH BIT(20) | ||
| 76 | #define MT_RXV1_HT_SHORT_GI BIT(19) | ||
| 77 | #define MT_RXV1_HT_AGGR BIT(18) | ||
| 78 | #define MT_RXV1_VHTA1_B22 BIT(17) | ||
| 79 | #define MT_RXV1_FRAME_MODE GENMASK(16, 15) | ||
| 80 | #define MT_RXV1_TX_MODE GENMASK(14, 12) | ||
| 81 | #define MT_RXV1_HT_EXT_LTF GENMASK(11, 10) | ||
| 82 | #define MT_RXV1_HT_AD_CODE BIT(9) | ||
| 83 | #define MT_RXV1_HT_STBC GENMASK(8, 7) | ||
| 84 | #define MT_RXV1_TX_RATE GENMASK(6, 0) | ||
| 85 | |||
| 86 | #define MT_RXV2_VHTA1_B16_B6 GENMASK(31, 21) | ||
| 87 | #define MT_RXV2_LENGTH GENMASK(20, 0) | ||
| 88 | |||
| 89 | #define MT_RXV3_F_AGC1_CAL_GAIN GENMASK(31, 29) | ||
| 90 | #define MT_RXV3_F_AGC1_EQ_CAL BIT(28) | ||
| 91 | #define MT_RXV3_RCPI1 GENMASK(27, 20) | ||
| 92 | #define MT_RXV3_F_AGC0_CAL_GAIN GENMASK(19, 17) | ||
| 93 | #define MT_RXV3_F_AGC0_EQ_CAL BIT(16) | ||
| 94 | #define MT_RXV3_RCPI0 GENMASK(15, 8) | ||
| 95 | #define MT_RXV3_SEL_ANT BIT(7) | ||
| 96 | #define MT_RXV3_ACI_DET_X BIT(6) | ||
| 97 | #define MT_RXV3_OFDM_FREQ_TRANS_DETECT BIT(5) | ||
| 98 | #define MT_RXV3_VHTA1_B21_B17 GENMASK(4, 0) | ||
| 99 | |||
| 100 | #define MT_RXV4_F_AGC_CAL_GAIN GENMASK(31, 29) | ||
| 101 | #define MT_RXV4_F_AGC2_EQ_CAL BIT(28) | ||
| 102 | #define MT_RXV4_IB_RSSI1 GENMASK(27, 20) | ||
| 103 | #define MT_RXV4_F_AGC_LPF_GAIN_X GENMASK(19, 16) | ||
| 104 | #define MT_RXV4_WB_RSSI_X GENMASK(15, 8) | ||
| 105 | #define MT_RXV4_IB_RSSI0 GENMASK(7, 0) | ||
| 106 | |||
| 107 | #define MT_RXV5_LTF_SNR0 GENMASK(31, 26) | ||
| 108 | #define MT_RXV5_LTF_PROC_TIME GENMASK(25, 19) | ||
| 109 | #define MT_RXV5_FOE GENMASK(18, 7) | ||
| 110 | #define MT_RXV5_C_AGC_SATE GENMASK(6, 4) | ||
| 111 | #define MT_RXV5_F_AGC_LNA_GAIN_0 GENMASK(3, 2) | ||
| 112 | #define MT_RXV5_F_AGC_LNA_GAIN_1 GENMASK(1, 0) | ||
| 113 | |||
| 114 | #define MT_RXV6_C_AGC_STATE GENMASK(30, 28) | ||
| 115 | #define MT_RXV6_NS_TS_FIELD GENMASK(27, 25) | ||
| 116 | #define MT_RXV6_RX_VALID BIT(24) | ||
| 117 | #define MT_RXV6_NF2 GENMASK(23, 16) | ||
| 118 | #define MT_RXV6_NF1 GENMASK(15, 8) | ||
| 119 | #define MT_RXV6_NF0 GENMASK(7, 0) | ||
| 120 | |||
| 121 | enum mt7603_tx_header_format { | ||
| 122 | MT_HDR_FORMAT_802_3, | ||
| 123 | MT_HDR_FORMAT_CMD, | ||
| 124 | MT_HDR_FORMAT_802_11, | ||
| 125 | MT_HDR_FORMAT_802_11_EXT, | ||
| 126 | }; | ||
| 127 | |||
| 128 | #define MT_TXD_SIZE (8 * 4) | ||
| 129 | |||
| 130 | #define MT_TXD0_P_IDX BIT(31) | ||
| 131 | #define MT_TXD0_Q_IDX GENMASK(30, 27) | ||
| 132 | #define MT_TXD0_UTXB BIT(26) | ||
| 133 | #define MT_TXD0_UNXV BIT(25) | ||
| 134 | #define MT_TXD0_UDP_TCP_SUM BIT(24) | ||
| 135 | #define MT_TXD0_IP_SUM BIT(23) | ||
| 136 | #define MT_TXD0_ETH_TYPE_OFFSET GENMASK(22, 16) | ||
| 137 | #define MT_TXD0_TX_BYTES GENMASK(15, 0) | ||
| 138 | |||
| 139 | #define MT_TXD1_OWN_MAC GENMASK(31, 26) | ||
| 140 | #define MT_TXD1_PROTECTED BIT(23) | ||
| 141 | #define MT_TXD1_TID GENMASK(22, 20) | ||
| 142 | #define MT_TXD1_NO_ACK BIT(19) | ||
| 143 | #define MT_TXD1_HDR_PAD GENMASK(18, 16) | ||
| 144 | #define MT_TXD1_LONG_FORMAT BIT(15) | ||
| 145 | #define MT_TXD1_HDR_FORMAT GENMASK(14, 13) | ||
| 146 | #define MT_TXD1_HDR_INFO GENMASK(12, 8) | ||
| 147 | #define MT_TXD1_WLAN_IDX GENMASK(7, 0) | ||
| 148 | |||
| 149 | #define MT_TXD2_FIX_RATE BIT(31) | ||
| 150 | #define MT_TXD2_TIMING_MEASURE BIT(30) | ||
| 151 | #define MT_TXD2_BA_DISABLE BIT(29) | ||
| 152 | #define MT_TXD2_POWER_OFFSET GENMASK(28, 24) | ||
| 153 | #define MT_TXD2_MAX_TX_TIME GENMASK(23, 16) | ||
| 154 | #define MT_TXD2_FRAG GENMASK(15, 14) | ||
| 155 | #define MT_TXD2_HTC_VLD BIT(13) | ||
| 156 | #define MT_TXD2_DURATION BIT(12) | ||
| 157 | #define MT_TXD2_BIP BIT(11) | ||
| 158 | #define MT_TXD2_MULTICAST BIT(10) | ||
| 159 | #define MT_TXD2_RTS BIT(9) | ||
| 160 | #define MT_TXD2_SOUNDING BIT(8) | ||
| 161 | #define MT_TXD2_NDPA BIT(7) | ||
| 162 | #define MT_TXD2_NDP BIT(6) | ||
| 163 | #define MT_TXD2_FRAME_TYPE GENMASK(5, 4) | ||
| 164 | #define MT_TXD2_SUB_TYPE GENMASK(3, 0) | ||
| 165 | |||
| 166 | #define MT_TXD3_SN_VALID BIT(31) | ||
| 167 | #define MT_TXD3_PN_VALID BIT(30) | ||
| 168 | #define MT_TXD3_SEQ GENMASK(27, 16) | ||
| 169 | #define MT_TXD3_REM_TX_COUNT GENMASK(15, 11) | ||
| 170 | #define MT_TXD3_TX_COUNT GENMASK(10, 6) | ||
| 171 | |||
| 172 | #define MT_TXD4_PN_LOW GENMASK(31, 0) | ||
| 173 | |||
| 174 | #define MT_TXD5_PN_HIGH GENMASK(31, 16) | ||
| 175 | #define MT_TXD5_SW_POWER_MGMT BIT(13) | ||
| 176 | #define MT_TXD5_BA_SEQ_CTRL BIT(12) | ||
| 177 | #define MT_TXD5_DA_SELECT BIT(11) | ||
| 178 | #define MT_TXD5_TX_STATUS_HOST BIT(10) | ||
| 179 | #define MT_TXD5_TX_STATUS_MCU BIT(9) | ||
| 180 | #define MT_TXD5_TX_STATUS_FMT BIT(8) | ||
| 181 | #define MT_TXD5_PID GENMASK(7, 0) | ||
| 182 | |||
| 183 | #define MT_TXD6_SGI BIT(31) | ||
| 184 | #define MT_TXD6_LDPC BIT(30) | ||
| 185 | #define MT_TXD6_TX_RATE GENMASK(29, 18) | ||
| 186 | #define MT_TXD6_I_TXBF BIT(17) | ||
| 187 | #define MT_TXD6_E_TXBF BIT(16) | ||
| 188 | #define MT_TXD6_DYN_BW BIT(15) | ||
| 189 | #define MT_TXD6_ANT_PRI GENMASK(14, 12) | ||
| 190 | #define MT_TXD6_SPE_EN BIT(11) | ||
| 191 | #define MT_TXD6_FIXED_BW BIT(10) | ||
| 192 | #define MT_TXD6_BW GENMASK(9, 8) | ||
| 193 | #define MT_TXD6_ANT_ID GENMASK(7, 2) | ||
| 194 | #define MT_TXD6_FIXED_RATE BIT(0) | ||
| 195 | |||
| 196 | #define MT_TX_RATE_STBC BIT(11) | ||
| 197 | #define MT_TX_RATE_NSS GENMASK(10, 9) | ||
| 198 | #define MT_TX_RATE_MODE GENMASK(8, 6) | ||
| 199 | #define MT_TX_RATE_IDX GENMASK(5, 0) | ||
| 200 | |||
| 201 | #define MT_TXS0_ANTENNA GENMASK(31, 26) | ||
| 202 | #define MT_TXS0_TID GENMASK(25, 22) | ||
| 203 | #define MT_TXS0_BA_ERROR BIT(22) | ||
| 204 | #define MT_TXS0_PS_FLAG BIT(21) | ||
| 205 | #define MT_TXS0_TXOP_TIMEOUT BIT(20) | ||
| 206 | #define MT_TXS0_BIP_ERROR BIT(19) | ||
| 207 | |||
| 208 | #define MT_TXS0_QUEUE_TIMEOUT BIT(18) | ||
| 209 | #define MT_TXS0_RTS_TIMEOUT BIT(17) | ||
| 210 | #define MT_TXS0_ACK_TIMEOUT BIT(16) | ||
| 211 | #define MT_TXS0_ACK_ERROR_MASK GENMASK(18, 16) | ||
| 212 | |||
| 213 | #define MT_TXS0_TX_STATUS_HOST BIT(15) | ||
| 214 | #define MT_TXS0_TX_STATUS_MCU BIT(14) | ||
| 215 | #define MT_TXS0_TXS_FORMAT BIT(13) | ||
| 216 | #define MT_TXS0_FIXED_RATE BIT(12) | ||
| 217 | #define MT_TXS0_TX_RATE GENMASK(11, 0) | ||
| 218 | |||
| 219 | #define MT_TXS1_F0_TIMESTAMP GENMASK(31, 0) | ||
| 220 | #define MT_TXS1_F1_NOISE_2 GENMASK(23, 16) | ||
| 221 | #define MT_TXS1_F1_NOISE_1 GENMASK(15, 8) | ||
| 222 | #define MT_TXS1_F1_NOISE_0 GENMASK(7, 0) | ||
| 223 | |||
| 224 | #define MT_TXS2_F0_FRONT_TIME GENMASK(24, 0) | ||
| 225 | #define MT_TXS2_F1_RCPI_2 GENMASK(23, 16) | ||
| 226 | #define MT_TXS2_F1_RCPI_1 GENMASK(15, 8) | ||
| 227 | #define MT_TXS2_F1_RCPI_0 GENMASK(7, 0) | ||
| 228 | |||
| 229 | #define MT_TXS3_WCID GENMASK(31, 24) | ||
| 230 | #define MT_TXS3_RXV_SEQNO GENMASK(23, 16) | ||
| 231 | #define MT_TXS3_TX_DELAY GENMASK(15, 0) | ||
| 232 | |||
| 233 | #define MT_TXS4_LAST_TX_RATE GENMASK(31, 29) | ||
| 234 | #define MT_TXS4_TX_COUNT GENMASK(28, 24) | ||
| 235 | #define MT_TXS4_AMPDU BIT(23) | ||
| 236 | #define MT_TXS4_ACKED_MPDU BIT(22) | ||
| 237 | #define MT_TXS4_PID GENMASK(21, 14) | ||
| 238 | #define MT_TXS4_BW GENMASK(13, 12) | ||
| 239 | #define MT_TXS4_F0_SEQNO GENMASK(11, 0) | ||
| 240 | #define MT_TXS4_F1_TSSI GENMASK(11, 0) | ||
| 241 | |||
| 242 | #endif | ||
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c new file mode 100644 index 000000000000..b10775ed92e6 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c | |||
| @@ -0,0 +1,709 @@ | |||
| 1 | /* SPDX-License-Identifier: ISC */ | ||
| 2 | |||
| 3 | #include <linux/etherdevice.h> | ||
| 4 | #include <linux/platform_device.h> | ||
| 5 | #include <linux/pci.h> | ||
| 6 | #include <linux/module.h> | ||
| 7 | #include "mt7603.h" | ||
| 8 | #include "eeprom.h" | ||
| 9 | |||
| 10 | static int | ||
| 11 | mt7603_start(struct ieee80211_hw *hw) | ||
| 12 | { | ||
| 13 | struct mt7603_dev *dev = hw->priv; | ||
| 14 | |||
| 15 | mt7603_mac_start(dev); | ||
| 16 | dev->survey_time = ktime_get_boottime(); | ||
| 17 | set_bit(MT76_STATE_RUNNING, &dev->mt76.state); | ||
| 18 | mt7603_mac_work(&dev->mac_work.work); | ||
| 19 | |||
| 20 | return 0; | ||
| 21 | } | ||
| 22 | |||
| 23 | static void | ||
| 24 | mt7603_stop(struct ieee80211_hw *hw) | ||
| 25 | { | ||
| 26 | struct mt7603_dev *dev = hw->priv; | ||
| 27 | |||
| 28 | clear_bit(MT76_STATE_RUNNING, &dev->mt76.state); | ||
| 29 | cancel_delayed_work_sync(&dev->mac_work); | ||
| 30 | mt7603_mac_stop(dev); | ||
| 31 | } | ||
| 32 | |||
| 33 | static int | ||
| 34 | mt7603_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | ||
| 35 | { | ||
| 36 | struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv; | ||
| 37 | struct mt7603_dev *dev = hw->priv; | ||
| 38 | struct mt76_txq *mtxq; | ||
| 39 | u8 bc_addr[ETH_ALEN]; | ||
| 40 | int idx; | ||
| 41 | int ret = 0; | ||
| 42 | |||
| 43 | mutex_lock(&dev->mt76.mutex); | ||
| 44 | |||
| 45 | mvif->idx = ffs(~dev->vif_mask) - 1; | ||
| 46 | if (mvif->idx >= MT7603_MAX_INTERFACES) { | ||
| 47 | ret = -ENOSPC; | ||
| 48 | goto out; | ||
| 49 | } | ||
| 50 | |||
| 51 | mt76_wr(dev, MT_MAC_ADDR0(mvif->idx), | ||
| 52 | get_unaligned_le32(vif->addr)); | ||
| 53 | mt76_wr(dev, MT_MAC_ADDR1(mvif->idx), | ||
| 54 | (get_unaligned_le16(vif->addr + 4) | | ||
| 55 | MT_MAC_ADDR1_VALID)); | ||
| 56 | |||
| 57 | if (vif->type == NL80211_IFTYPE_AP) { | ||
| 58 | mt76_wr(dev, MT_BSSID0(mvif->idx), | ||
| 59 | get_unaligned_le32(vif->addr)); | ||
| 60 | mt76_wr(dev, MT_BSSID1(mvif->idx), | ||
| 61 | (get_unaligned_le16(vif->addr + 4) | | ||
| 62 | MT_BSSID1_VALID)); | ||
| 63 | } | ||
| 64 | |||
| 65 | idx = MT7603_WTBL_RESERVED - 1 - mvif->idx; | ||
| 66 | dev->vif_mask |= BIT(mvif->idx); | ||
| 67 | mvif->sta.wcid.idx = idx; | ||
| 68 | mvif->sta.wcid.hw_key_idx = -1; | ||
| 69 | |||
| 70 | eth_broadcast_addr(bc_addr); | ||
| 71 | mt7603_wtbl_init(dev, idx, mvif->idx, bc_addr); | ||
| 72 | |||
| 73 | mtxq = (struct mt76_txq *)vif->txq->drv_priv; | ||
| 74 | mtxq->wcid = &mvif->sta.wcid; | ||
| 75 | mt76_txq_init(&dev->mt76, vif->txq); | ||
| 76 | rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid); | ||
| 77 | |||
| 78 | out: | ||
| 79 | mutex_unlock(&dev->mt76.mutex); | ||
| 80 | |||
| 81 | return ret; | ||
| 82 | } | ||
| 83 | |||
| 84 | static void | ||
| 85 | mt7603_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | ||
| 86 | { | ||
| 87 | struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv; | ||
| 88 | struct mt7603_dev *dev = hw->priv; | ||
| 89 | int idx = mvif->sta.wcid.idx; | ||
| 90 | |||
| 91 | mt76_wr(dev, MT_MAC_ADDR0(mvif->idx), 0); | ||
| 92 | mt76_wr(dev, MT_MAC_ADDR1(mvif->idx), 0); | ||
| 93 | mt76_wr(dev, MT_BSSID0(mvif->idx), 0); | ||
| 94 | mt76_wr(dev, MT_BSSID1(mvif->idx), 0); | ||
| 95 | mt7603_beacon_set_timer(dev, mvif->idx, 0); | ||
| 96 | |||
| 97 | rcu_assign_pointer(dev->mt76.wcid[idx], NULL); | ||
| 98 | mt76_txq_remove(&dev->mt76, vif->txq); | ||
| 99 | |||
| 100 | mutex_lock(&dev->mt76.mutex); | ||
| 101 | dev->vif_mask &= ~BIT(mvif->idx); | ||
| 102 | mutex_unlock(&dev->mt76.mutex); | ||
| 103 | } | ||
| 104 | |||
| 105 | static void | ||
| 106 | mt7603_init_edcca(struct mt7603_dev *dev) | ||
| 107 | { | ||
| 108 | /* Set lower signal level to -65dBm */ | ||
| 109 | mt76_rmw_field(dev, MT_RXTD(8), MT_RXTD_8_LOWER_SIGNAL, 0x23); | ||
| 110 | |||
| 111 | /* clear previous energy detect monitor results */ | ||
| 112 | mt76_rr(dev, MT_MIB_STAT_ED); | ||
| 113 | |||
| 114 | if (dev->ed_monitor) | ||
| 115 | mt76_set(dev, MT_MIB_CTL, MT_MIB_CTL_ED_TIME); | ||
| 116 | else | ||
| 117 | mt76_clear(dev, MT_MIB_CTL, MT_MIB_CTL_ED_TIME); | ||
| 118 | |||
| 119 | dev->ed_strict_mode = 0xff; | ||
| 120 | dev->ed_strong_signal = 0; | ||
| 121 | dev->ed_time = ktime_get_boottime(); | ||
| 122 | |||
| 123 | mt7603_edcca_set_strict(dev, false); | ||
| 124 | } | ||
| 125 | |||
| 126 | static int | ||
| 127 | mt7603_set_channel(struct mt7603_dev *dev, struct cfg80211_chan_def *def) | ||
| 128 | { | ||
| 129 | u8 *rssi_data = (u8 *)dev->mt76.eeprom.data; | ||
| 130 | int idx, ret; | ||
| 131 | u8 bw = MT_BW_20; | ||
| 132 | bool failed = false; | ||
| 133 | |||
| 134 | cancel_delayed_work_sync(&dev->mac_work); | ||
| 135 | |||
| 136 | mutex_lock(&dev->mt76.mutex); | ||
| 137 | set_bit(MT76_RESET, &dev->mt76.state); | ||
| 138 | |||
| 139 | mt76_set_channel(&dev->mt76); | ||
| 140 | mt7603_mac_stop(dev); | ||
| 141 | |||
| 142 | if (def->width == NL80211_CHAN_WIDTH_40) | ||
| 143 | bw = MT_BW_40; | ||
| 144 | |||
| 145 | dev->mt76.chandef = *def; | ||
| 146 | mt76_rmw_field(dev, MT_AGG_BWCR, MT_AGG_BWCR_BW, bw); | ||
| 147 | ret = mt7603_mcu_set_channel(dev); | ||
| 148 | if (ret) { | ||
| 149 | failed = true; | ||
| 150 | goto out; | ||
| 151 | } | ||
| 152 | |||
| 153 | if (def->chan->band == NL80211_BAND_5GHZ) { | ||
| 154 | idx = 1; | ||
| 155 | rssi_data += MT_EE_RSSI_OFFSET_5G; | ||
| 156 | } else { | ||
| 157 | idx = 0; | ||
| 158 | rssi_data += MT_EE_RSSI_OFFSET_2G; | ||
| 159 | } | ||
| 160 | |||
| 161 | memcpy(dev->rssi_offset, rssi_data, sizeof(dev->rssi_offset)); | ||
| 162 | |||
| 163 | idx |= (def->chan - | ||
| 164 | mt76_hw(dev)->wiphy->bands[def->chan->band]->channels) << 1; | ||
| 165 | mt76_wr(dev, MT_WF_RMAC_CH_FREQ, idx); | ||
| 166 | mt7603_mac_set_timing(dev); | ||
| 167 | mt7603_mac_start(dev); | ||
| 168 | |||
| 169 | clear_bit(MT76_RESET, &dev->mt76.state); | ||
| 170 | |||
| 171 | mt76_txq_schedule_all(&dev->mt76); | ||
| 172 | |||
| 173 | ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work, | ||
| 174 | MT7603_WATCHDOG_TIME); | ||
| 175 | |||
| 176 | /* reset channel stats */ | ||
| 177 | mt76_clear(dev, MT_MIB_CTL, MT_MIB_CTL_READ_CLR_DIS); | ||
| 178 | mt76_set(dev, MT_MIB_CTL, | ||
| 179 | MT_MIB_CTL_CCA_NAV_TX | MT_MIB_CTL_PSCCA_TIME); | ||
| 180 | mt76_rr(dev, MT_MIB_STAT_PSCCA); | ||
| 181 | mt7603_cca_stats_reset(dev); | ||
| 182 | |||
| 183 | dev->survey_time = ktime_get_boottime(); | ||
| 184 | |||
| 185 | mt7603_init_edcca(dev); | ||
| 186 | |||
| 187 | out: | ||
| 188 | mutex_unlock(&dev->mt76.mutex); | ||
| 189 | |||
| 190 | if (failed) | ||
| 191 | mt7603_mac_work(&dev->mac_work.work); | ||
| 192 | |||
| 193 | return ret; | ||
| 194 | } | ||
| 195 | |||
| 196 | static int | ||
| 197 | mt7603_config(struct ieee80211_hw *hw, u32 changed) | ||
| 198 | { | ||
| 199 | struct mt7603_dev *dev = hw->priv; | ||
| 200 | int ret = 0; | ||
| 201 | |||
| 202 | if (changed & (IEEE80211_CONF_CHANGE_CHANNEL | | ||
| 203 | IEEE80211_CONF_CHANGE_POWER)) | ||
| 204 | ret = mt7603_set_channel(dev, &hw->conf.chandef); | ||
| 205 | |||
| 206 | if (changed & IEEE80211_CONF_CHANGE_MONITOR) { | ||
| 207 | mutex_lock(&dev->mt76.mutex); | ||
| 208 | |||
| 209 | if (!(hw->conf.flags & IEEE80211_CONF_MONITOR)) | ||
| 210 | dev->rxfilter |= MT_WF_RFCR_DROP_OTHER_UC; | ||
| 211 | else | ||
| 212 | dev->rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC; | ||
| 213 | |||
| 214 | mt76_wr(dev, MT_WF_RFCR, dev->rxfilter); | ||
| 215 | |||
| 216 | mutex_unlock(&dev->mt76.mutex); | ||
| 217 | } | ||
| 218 | |||
| 219 | return ret; | ||
| 220 | } | ||
| 221 | |||
| 222 | static void | ||
| 223 | mt7603_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, | ||
| 224 | unsigned int *total_flags, u64 multicast) | ||
| 225 | { | ||
| 226 | struct mt7603_dev *dev = hw->priv; | ||
| 227 | u32 flags = 0; | ||
| 228 | |||
| 229 | #define MT76_FILTER(_flag, _hw) do { \ | ||
| 230 | flags |= *total_flags & FIF_##_flag; \ | ||
| 231 | dev->rxfilter &= ~(_hw); \ | ||
| 232 | dev->rxfilter |= !(flags & FIF_##_flag) * (_hw); \ | ||
| 233 | } while (0) | ||
| 234 | |||
| 235 | dev->rxfilter &= ~(MT_WF_RFCR_DROP_OTHER_BSS | | ||
| 236 | MT_WF_RFCR_DROP_OTHER_BEACON | | ||
| 237 | MT_WF_RFCR_DROP_FRAME_REPORT | | ||
| 238 | MT_WF_RFCR_DROP_PROBEREQ | | ||
| 239 | MT_WF_RFCR_DROP_MCAST_FILTERED | | ||
| 240 | MT_WF_RFCR_DROP_MCAST | | ||
| 241 | MT_WF_RFCR_DROP_BCAST | | ||
| 242 | MT_WF_RFCR_DROP_DUPLICATE | | ||
| 243 | MT_WF_RFCR_DROP_A2_BSSID | | ||
| 244 | MT_WF_RFCR_DROP_UNWANTED_CTL | | ||
| 245 | MT_WF_RFCR_DROP_STBC_MULTI); | ||
| 246 | |||
| 247 | MT76_FILTER(OTHER_BSS, MT_WF_RFCR_DROP_OTHER_TIM | | ||
| 248 | MT_WF_RFCR_DROP_A3_MAC | | ||
| 249 | MT_WF_RFCR_DROP_A3_BSSID); | ||
| 250 | |||
| 251 | MT76_FILTER(FCSFAIL, MT_WF_RFCR_DROP_FCSFAIL); | ||
| 252 | |||
| 253 | MT76_FILTER(CONTROL, MT_WF_RFCR_DROP_CTS | | ||
| 254 | MT_WF_RFCR_DROP_RTS | | ||
| 255 | MT_WF_RFCR_DROP_CTL_RSV | | ||
| 256 | MT_WF_RFCR_DROP_NDPA); | ||
| 257 | |||
| 258 | *total_flags = flags; | ||
| 259 | mt76_wr(dev, MT_WF_RFCR, dev->rxfilter); | ||
| 260 | } | ||
| 261 | |||
| 262 | static void | ||
| 263 | mt7603_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | ||
| 264 | struct ieee80211_bss_conf *info, u32 changed) | ||
| 265 | { | ||
| 266 | struct mt7603_dev *dev = hw->priv; | ||
| 267 | struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv; | ||
| 268 | |||
| 269 | mutex_lock(&dev->mt76.mutex); | ||
| 270 | |||
| 271 | if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_BSSID)) { | ||
| 272 | if (info->assoc || info->ibss_joined) { | ||
| 273 | mt76_wr(dev, MT_BSSID0(mvif->idx), | ||
| 274 | get_unaligned_le32(info->bssid)); | ||
| 275 | mt76_wr(dev, MT_BSSID1(mvif->idx), | ||
| 276 | (get_unaligned_le16(info->bssid + 4) | | ||
| 277 | MT_BSSID1_VALID)); | ||
| 278 | } else { | ||
| 279 | mt76_wr(dev, MT_BSSID0(mvif->idx), 0); | ||
| 280 | mt76_wr(dev, MT_BSSID1(mvif->idx), 0); | ||
| 281 | } | ||
| 282 | } | ||
| 283 | |||
| 284 | if (changed & BSS_CHANGED_ERP_SLOT) { | ||
| 285 | int slottime = info->use_short_slot ? 9 : 20; | ||
| 286 | |||
| 287 | if (slottime != dev->slottime) { | ||
| 288 | dev->slottime = slottime; | ||
| 289 | mt7603_mac_set_timing(dev); | ||
| 290 | } | ||
| 291 | } | ||
| 292 | |||
| 293 | if (changed & (BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_BEACON_INT)) { | ||
| 294 | int beacon_int = !!info->enable_beacon * info->beacon_int; | ||
| 295 | |||
| 296 | tasklet_disable(&dev->pre_tbtt_tasklet); | ||
| 297 | mt7603_beacon_set_timer(dev, mvif->idx, beacon_int); | ||
| 298 | tasklet_enable(&dev->pre_tbtt_tasklet); | ||
| 299 | } | ||
| 300 | |||
| 301 | mutex_unlock(&dev->mt76.mutex); | ||
| 302 | } | ||
| 303 | |||
| 304 | int | ||
| 305 | mt7603_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, | ||
| 306 | struct ieee80211_sta *sta) | ||
| 307 | { | ||
| 308 | struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); | ||
| 309 | struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv; | ||
| 310 | struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv; | ||
| 311 | int idx; | ||
| 312 | int ret = 0; | ||
| 313 | |||
| 314 | idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7603_WTBL_STA - 1); | ||
| 315 | if (idx < 0) | ||
| 316 | return -ENOSPC; | ||
| 317 | |||
| 318 | __skb_queue_head_init(&msta->psq); | ||
| 319 | msta->ps = ~0; | ||
| 320 | msta->smps = ~0; | ||
| 321 | msta->wcid.sta = 1; | ||
| 322 | msta->wcid.idx = idx; | ||
| 323 | mt7603_wtbl_init(dev, idx, mvif->idx, sta->addr); | ||
| 324 | mt7603_wtbl_set_ps(dev, msta, false); | ||
| 325 | |||
| 326 | if (vif->type == NL80211_IFTYPE_AP) | ||
| 327 | set_bit(MT_WCID_FLAG_CHECK_PS, &msta->wcid.flags); | ||
| 328 | |||
| 329 | return ret; | ||
| 330 | } | ||
| 331 | |||
| 332 | void | ||
| 333 | mt7603_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif, | ||
| 334 | struct ieee80211_sta *sta) | ||
| 335 | { | ||
| 336 | struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); | ||
| 337 | |||
| 338 | mt7603_wtbl_update_cap(dev, sta); | ||
| 339 | } | ||
| 340 | |||
| 341 | void | ||
| 342 | mt7603_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, | ||
| 343 | struct ieee80211_sta *sta) | ||
| 344 | { | ||
| 345 | struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); | ||
| 346 | struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv; | ||
| 347 | struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv; | ||
| 348 | |||
| 349 | spin_lock_bh(&dev->ps_lock); | ||
| 350 | __skb_queue_purge(&msta->psq); | ||
| 351 | mt7603_filter_tx(dev, wcid->idx, true); | ||
| 352 | spin_unlock_bh(&dev->ps_lock); | ||
| 353 | |||
| 354 | mt7603_wtbl_clear(dev, wcid->idx); | ||
| 355 | } | ||
| 356 | |||
| 357 | static void | ||
| 358 | mt7603_ps_tx_list(struct mt7603_dev *dev, struct sk_buff_head *list) | ||
| 359 | { | ||
| 360 | struct sk_buff *skb; | ||
| 361 | |||
| 362 | while ((skb = __skb_dequeue(list)) != NULL) | ||
| 363 | mt76_tx_queue_skb_raw(dev, skb_get_queue_mapping(skb), | ||
| 364 | skb, 0); | ||
| 365 | } | ||
| 366 | |||
| 367 | void | ||
| 368 | mt7603_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps) | ||
| 369 | { | ||
| 370 | struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); | ||
| 371 | struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv; | ||
| 372 | struct sk_buff_head list; | ||
| 373 | |||
| 374 | mt76_stop_tx_queues(&dev->mt76, sta, false); | ||
| 375 | mt7603_wtbl_set_ps(dev, msta, ps); | ||
| 376 | if (ps) | ||
| 377 | return; | ||
| 378 | |||
| 379 | __skb_queue_head_init(&list); | ||
| 380 | |||
| 381 | spin_lock_bh(&dev->ps_lock); | ||
| 382 | skb_queue_splice_tail_init(&msta->psq, &list); | ||
| 383 | spin_unlock_bh(&dev->ps_lock); | ||
| 384 | |||
| 385 | mt7603_ps_tx_list(dev, &list); | ||
| 386 | } | ||
| 387 | |||
| 388 | static void | ||
| 389 | mt7603_release_buffered_frames(struct ieee80211_hw *hw, | ||
| 390 | struct ieee80211_sta *sta, | ||
| 391 | u16 tids, int nframes, | ||
| 392 | enum ieee80211_frame_release_type reason, | ||
| 393 | bool more_data) | ||
| 394 | { | ||
| 395 | struct mt7603_dev *dev = hw->priv; | ||
| 396 | struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv; | ||
| 397 | struct sk_buff_head list; | ||
| 398 | struct sk_buff *skb, *tmp; | ||
| 399 | |||
| 400 | __skb_queue_head_init(&list); | ||
| 401 | |||
| 402 | spin_lock_bh(&dev->ps_lock); | ||
| 403 | skb_queue_walk_safe(&msta->psq, skb, tmp) { | ||
| 404 | if (!nframes) | ||
| 405 | break; | ||
| 406 | |||
| 407 | if (!(tids & BIT(skb->priority))) | ||
| 408 | continue; | ||
| 409 | |||
| 410 | skb_set_queue_mapping(skb, MT_TXQ_PSD); | ||
| 411 | __skb_unlink(skb, &msta->psq); | ||
| 412 | __skb_queue_tail(&list, skb); | ||
| 413 | nframes--; | ||
| 414 | } | ||
| 415 | spin_unlock_bh(&dev->ps_lock); | ||
| 416 | |||
| 417 | mt7603_ps_tx_list(dev, &list); | ||
| 418 | |||
| 419 | if (nframes) | ||
| 420 | mt76_release_buffered_frames(hw, sta, tids, nframes, reason, | ||
| 421 | more_data); | ||
| 422 | } | ||
| 423 | |||
| 424 | static int | ||
| 425 | mt7603_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | ||
| 426 | struct ieee80211_vif *vif, struct ieee80211_sta *sta, | ||
| 427 | struct ieee80211_key_conf *key) | ||
| 428 | { | ||
| 429 | struct mt7603_dev *dev = hw->priv; | ||
| 430 | struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv; | ||
| 431 | struct mt7603_sta *msta = sta ? (struct mt7603_sta *)sta->drv_priv : | ||
| 432 | &mvif->sta; | ||
| 433 | struct mt76_wcid *wcid = &msta->wcid; | ||
| 434 | int idx = key->keyidx; | ||
| 435 | |||
| 436 | /* fall back to sw encryption for unsupported ciphers */ | ||
| 437 | switch (key->cipher) { | ||
| 438 | case WLAN_CIPHER_SUITE_TKIP: | ||
| 439 | case WLAN_CIPHER_SUITE_CCMP: | ||
| 440 | break; | ||
| 441 | default: | ||
| 442 | return -EOPNOTSUPP; | ||
| 443 | } | ||
| 444 | |||
| 445 | /* | ||
| 446 | * The hardware does not support per-STA RX GTK, fall back | ||
| 447 | * to software mode for these. | ||
| 448 | */ | ||
| 449 | if ((vif->type == NL80211_IFTYPE_ADHOC || | ||
| 450 | vif->type == NL80211_IFTYPE_MESH_POINT) && | ||
| 451 | (key->cipher == WLAN_CIPHER_SUITE_TKIP || | ||
| 452 | key->cipher == WLAN_CIPHER_SUITE_CCMP) && | ||
| 453 | !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) | ||
| 454 | return -EOPNOTSUPP; | ||
| 455 | |||
| 456 | if (cmd == SET_KEY) { | ||
| 457 | key->hw_key_idx = wcid->idx; | ||
| 458 | wcid->hw_key_idx = idx; | ||
| 459 | } else { | ||
| 460 | if (idx == wcid->hw_key_idx) | ||
| 461 | wcid->hw_key_idx = -1; | ||
| 462 | |||
| 463 | key = NULL; | ||
| 464 | } | ||
| 465 | mt76_wcid_key_setup(&dev->mt76, wcid, key); | ||
| 466 | |||
| 467 | return mt7603_wtbl_set_key(dev, wcid->idx, key); | ||
| 468 | } | ||
| 469 | |||
| 470 | static int | ||
| 471 | mt7603_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue, | ||
| 472 | const struct ieee80211_tx_queue_params *params) | ||
| 473 | { | ||
| 474 | struct mt7603_dev *dev = hw->priv; | ||
| 475 | u16 cw_min = (1 << 5) - 1; | ||
| 476 | u16 cw_max = (1 << 10) - 1; | ||
| 477 | u32 val; | ||
| 478 | |||
| 479 | queue = dev->mt76.q_tx[queue].hw_idx; | ||
| 480 | |||
| 481 | if (params->cw_min) | ||
| 482 | cw_min = params->cw_min; | ||
| 483 | if (params->cw_max) | ||
| 484 | cw_max = params->cw_max; | ||
| 485 | |||
| 486 | mutex_lock(&dev->mt76.mutex); | ||
| 487 | mt7603_mac_stop(dev); | ||
| 488 | |||
| 489 | val = mt76_rr(dev, MT_WMM_TXOP(queue)); | ||
| 490 | val &= ~(MT_WMM_TXOP_MASK << MT_WMM_TXOP_SHIFT(queue)); | ||
| 491 | val |= params->txop << MT_WMM_TXOP_SHIFT(queue); | ||
| 492 | mt76_wr(dev, MT_WMM_TXOP(queue), val); | ||
| 493 | |||
| 494 | val = mt76_rr(dev, MT_WMM_AIFSN); | ||
| 495 | val &= ~(MT_WMM_AIFSN_MASK << MT_WMM_AIFSN_SHIFT(queue)); | ||
| 496 | val |= params->aifs << MT_WMM_AIFSN_SHIFT(queue); | ||
| 497 | mt76_wr(dev, MT_WMM_AIFSN, val); | ||
| 498 | |||
| 499 | val = mt76_rr(dev, MT_WMM_CWMIN); | ||
| 500 | val &= ~(MT_WMM_CWMIN_MASK << MT_WMM_CWMIN_SHIFT(queue)); | ||
| 501 | val |= cw_min << MT_WMM_CWMIN_SHIFT(queue); | ||
| 502 | mt76_wr(dev, MT_WMM_CWMIN, val); | ||
| 503 | |||
| 504 | val = mt76_rr(dev, MT_WMM_CWMAX(queue)); | ||
| 505 | val &= ~(MT_WMM_CWMAX_MASK << MT_WMM_CWMAX_SHIFT(queue)); | ||
| 506 | val |= cw_max << MT_WMM_CWMAX_SHIFT(queue); | ||
| 507 | mt76_wr(dev, MT_WMM_CWMAX(queue), val); | ||
| 508 | |||
| 509 | mt7603_mac_start(dev); | ||
| 510 | mutex_unlock(&dev->mt76.mutex); | ||
| 511 | |||
| 512 | return 0; | ||
| 513 | } | ||
| 514 | |||
| 515 | static void | ||
| 516 | mt7603_sw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | ||
| 517 | const u8 *mac) | ||
| 518 | { | ||
| 519 | struct mt7603_dev *dev = hw->priv; | ||
| 520 | |||
| 521 | set_bit(MT76_SCANNING, &dev->mt76.state); | ||
| 522 | mt7603_beacon_set_timer(dev, -1, 0); | ||
| 523 | } | ||
| 524 | |||
| 525 | static void | ||
| 526 | mt7603_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | ||
| 527 | { | ||
| 528 | struct mt7603_dev *dev = hw->priv; | ||
| 529 | |||
| 530 | clear_bit(MT76_SCANNING, &dev->mt76.state); | ||
| 531 | mt7603_beacon_set_timer(dev, -1, dev->beacon_int); | ||
| 532 | } | ||
| 533 | |||
| 534 | static void | ||
| 535 | mt7603_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | ||
| 536 | u32 queues, bool drop) | ||
| 537 | { | ||
| 538 | } | ||
| 539 | |||
| 540 | static int | ||
| 541 | mt7603_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | ||
| 542 | struct ieee80211_ampdu_params *params) | ||
| 543 | { | ||
| 544 | enum ieee80211_ampdu_mlme_action action = params->action; | ||
| 545 | struct mt7603_dev *dev = hw->priv; | ||
| 546 | struct ieee80211_sta *sta = params->sta; | ||
| 547 | struct ieee80211_txq *txq = sta->txq[params->tid]; | ||
| 548 | struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv; | ||
| 549 | u16 tid = params->tid; | ||
| 550 | u16 *ssn = ¶ms->ssn; | ||
| 551 | u8 ba_size = params->buf_size; | ||
| 552 | struct mt76_txq *mtxq; | ||
| 553 | |||
| 554 | if (!txq) | ||
| 555 | return -EINVAL; | ||
| 556 | |||
| 557 | mtxq = (struct mt76_txq *)txq->drv_priv; | ||
| 558 | |||
| 559 | switch (action) { | ||
| 560 | case IEEE80211_AMPDU_RX_START: | ||
| 561 | mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid, *ssn, | ||
| 562 | params->buf_size); | ||
| 563 | mt7603_mac_rx_ba_reset(dev, sta->addr, tid); | ||
| 564 | break; | ||
| 565 | case IEEE80211_AMPDU_RX_STOP: | ||
| 566 | mt76_rx_aggr_stop(&dev->mt76, &msta->wcid, tid); | ||
| 567 | break; | ||
| 568 | case IEEE80211_AMPDU_TX_OPERATIONAL: | ||
| 569 | mtxq->aggr = true; | ||
| 570 | mtxq->send_bar = false; | ||
| 571 | mt7603_mac_tx_ba_reset(dev, msta->wcid.idx, tid, *ssn, ba_size); | ||
| 572 | break; | ||
| 573 | case IEEE80211_AMPDU_TX_STOP_FLUSH: | ||
| 574 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: | ||
| 575 | mtxq->aggr = false; | ||
| 576 | ieee80211_send_bar(vif, sta->addr, tid, mtxq->agg_ssn); | ||
| 577 | mt7603_mac_tx_ba_reset(dev, msta->wcid.idx, tid, *ssn, -1); | ||
| 578 | break; | ||
| 579 | case IEEE80211_AMPDU_TX_START: | ||
| 580 | mtxq->agg_ssn = *ssn << 4; | ||
| 581 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); | ||
| 582 | break; | ||
| 583 | case IEEE80211_AMPDU_TX_STOP_CONT: | ||
| 584 | mtxq->aggr = false; | ||
| 585 | mt7603_mac_tx_ba_reset(dev, msta->wcid.idx, tid, *ssn, -1); | ||
| 586 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); | ||
| 587 | break; | ||
| 588 | } | ||
| 589 | |||
| 590 | return 0; | ||
| 591 | } | ||
| 592 | |||
| 593 | static void | ||
| 594 | mt7603_sta_rate_tbl_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | ||
| 595 | struct ieee80211_sta *sta) | ||
| 596 | { | ||
| 597 | struct mt7603_dev *dev = hw->priv; | ||
| 598 | struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv; | ||
| 599 | struct ieee80211_sta_rates *sta_rates = rcu_dereference(sta->rates); | ||
| 600 | int i; | ||
| 601 | |||
| 602 | spin_lock_bh(&dev->mt76.lock); | ||
| 603 | for (i = 0; i < ARRAY_SIZE(msta->rates); i++) { | ||
| 604 | msta->rates[i].idx = sta_rates->rate[i].idx; | ||
| 605 | msta->rates[i].count = sta_rates->rate[i].count; | ||
| 606 | msta->rates[i].flags = sta_rates->rate[i].flags; | ||
| 607 | |||
| 608 | if (msta->rates[i].idx < 0 || !msta->rates[i].count) | ||
| 609 | break; | ||
| 610 | } | ||
| 611 | msta->n_rates = i; | ||
| 612 | mt7603_wtbl_set_rates(dev, msta, NULL, msta->rates); | ||
| 613 | msta->rate_probe = false; | ||
| 614 | mt7603_wtbl_set_smps(dev, msta, | ||
| 615 | sta->smps_mode == IEEE80211_SMPS_DYNAMIC); | ||
| 616 | spin_unlock_bh(&dev->mt76.lock); | ||
| 617 | } | ||
| 618 | |||
| 619 | static void | ||
| 620 | mt7603_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class) | ||
| 621 | { | ||
| 622 | struct mt7603_dev *dev = hw->priv; | ||
| 623 | |||
| 624 | dev->coverage_class = coverage_class; | ||
| 625 | mt7603_mac_set_timing(dev); | ||
| 626 | } | ||
| 627 | |||
| 628 | static void mt7603_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, | ||
| 629 | struct sk_buff *skb) | ||
| 630 | { | ||
| 631 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
| 632 | struct ieee80211_vif *vif = info->control.vif; | ||
| 633 | struct mt7603_dev *dev = hw->priv; | ||
| 634 | struct mt76_wcid *wcid = &dev->global_sta.wcid; | ||
| 635 | |||
| 636 | if (control->sta) { | ||
| 637 | struct mt7603_sta *msta; | ||
| 638 | |||
| 639 | msta = (struct mt7603_sta *)control->sta->drv_priv; | ||
| 640 | wcid = &msta->wcid; | ||
| 641 | } else if (vif) { | ||
| 642 | struct mt7603_vif *mvif; | ||
| 643 | |||
| 644 | mvif = (struct mt7603_vif *)vif->drv_priv; | ||
| 645 | wcid = &mvif->sta.wcid; | ||
| 646 | } | ||
| 647 | |||
| 648 | mt76_tx(&dev->mt76, control->sta, wcid, skb); | ||
| 649 | } | ||
| 650 | |||
| 651 | static int | ||
| 652 | mt7603_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set) | ||
| 653 | { | ||
| 654 | return 0; | ||
| 655 | } | ||
| 656 | |||
| 657 | const struct ieee80211_ops mt7603_ops = { | ||
| 658 | .tx = mt7603_tx, | ||
| 659 | .start = mt7603_start, | ||
| 660 | .stop = mt7603_stop, | ||
| 661 | .add_interface = mt7603_add_interface, | ||
| 662 | .remove_interface = mt7603_remove_interface, | ||
| 663 | .config = mt7603_config, | ||
| 664 | .configure_filter = mt7603_configure_filter, | ||
| 665 | .bss_info_changed = mt7603_bss_info_changed, | ||
| 666 | .sta_state = mt76_sta_state, | ||
| 667 | .set_key = mt7603_set_key, | ||
| 668 | .conf_tx = mt7603_conf_tx, | ||
| 669 | .sw_scan_start = mt7603_sw_scan, | ||
| 670 | .sw_scan_complete = mt7603_sw_scan_complete, | ||
| 671 | .flush = mt7603_flush, | ||
| 672 | .ampdu_action = mt7603_ampdu_action, | ||
| 673 | .get_txpower = mt76_get_txpower, | ||
| 674 | .wake_tx_queue = mt76_wake_tx_queue, | ||
| 675 | .sta_rate_tbl_update = mt7603_sta_rate_tbl_update, | ||
| 676 | .release_buffered_frames = mt7603_release_buffered_frames, | ||
| 677 | .set_coverage_class = mt7603_set_coverage_class, | ||
| 678 | .set_tim = mt7603_set_tim, | ||
| 679 | .get_survey = mt76_get_survey, | ||
| 680 | }; | ||
| 681 | |||
| 682 | MODULE_LICENSE("Dual BSD/GPL"); | ||
| 683 | |||
| 684 | static int __init mt7603_init(void) | ||
| 685 | { | ||
| 686 | int ret; | ||
| 687 | |||
| 688 | ret = platform_driver_register(&mt76_wmac_driver); | ||
| 689 | if (ret) | ||
| 690 | return ret; | ||
| 691 | |||
| 692 | #ifdef CONFIG_PCI | ||
| 693 | ret = pci_register_driver(&mt7603_pci_driver); | ||
| 694 | if (ret) | ||
| 695 | platform_driver_unregister(&mt76_wmac_driver); | ||
| 696 | #endif | ||
| 697 | return ret; | ||
| 698 | } | ||
| 699 | |||
| 700 | static void __exit mt7603_exit(void) | ||
| 701 | { | ||
| 702 | #ifdef CONFIG_PCI | ||
| 703 | pci_unregister_driver(&mt7603_pci_driver); | ||
| 704 | #endif | ||
| 705 | platform_driver_unregister(&mt76_wmac_driver); | ||
| 706 | } | ||
| 707 | |||
| 708 | module_init(mt7603_init); | ||
| 709 | module_exit(mt7603_exit); | ||
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c new file mode 100644 index 000000000000..4b0713f1fd5e --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.c | |||
| @@ -0,0 +1,483 @@ | |||
| 1 | /* SPDX-License-Identifier: ISC */ | ||
| 2 | |||
| 3 | #include <linux/firmware.h> | ||
| 4 | #include "mt7603.h" | ||
| 5 | #include "mcu.h" | ||
| 6 | #include "eeprom.h" | ||
| 7 | |||
| 8 | #define MCU_SKB_RESERVE 8 | ||
| 9 | |||
| 10 | struct mt7603_fw_trailer { | ||
| 11 | char fw_ver[10]; | ||
| 12 | char build_date[15]; | ||
| 13 | __le32 dl_len; | ||
| 14 | } __packed; | ||
| 15 | |||
| 16 | static int | ||
| 17 | __mt7603_mcu_msg_send(struct mt7603_dev *dev, struct sk_buff *skb, int cmd, | ||
| 18 | int query, int *wait_seq) | ||
| 19 | { | ||
| 20 | int hdrlen = dev->mcu_running ? sizeof(struct mt7603_mcu_txd) : 12; | ||
| 21 | struct mt76_dev *mdev = &dev->mt76; | ||
| 22 | struct mt7603_mcu_txd *txd; | ||
| 23 | u8 seq; | ||
| 24 | |||
| 25 | if (!skb) | ||
| 26 | return -EINVAL; | ||
| 27 | |||
| 28 | seq = ++mdev->mmio.mcu.msg_seq & 0xf; | ||
| 29 | if (!seq) | ||
| 30 | seq = ++mdev->mmio.mcu.msg_seq & 0xf; | ||
| 31 | |||
| 32 | txd = (struct mt7603_mcu_txd *)skb_push(skb, hdrlen); | ||
| 33 | memset(txd, 0, hdrlen); | ||
| 34 | |||
| 35 | txd->len = cpu_to_le16(skb->len); | ||
| 36 | if (cmd == -MCU_CMD_FW_SCATTER) | ||
| 37 | txd->pq_id = cpu_to_le16(MCU_PORT_QUEUE_FW); | ||
| 38 | else | ||
| 39 | txd->pq_id = cpu_to_le16(MCU_PORT_QUEUE); | ||
| 40 | txd->pkt_type = MCU_PKT_ID; | ||
| 41 | txd->seq = seq; | ||
| 42 | |||
| 43 | if (cmd < 0) { | ||
| 44 | txd->cid = -cmd; | ||
| 45 | } else { | ||
| 46 | txd->cid = MCU_CMD_EXT_CID; | ||
| 47 | txd->ext_cid = cmd; | ||
| 48 | if (query != MCU_Q_NA) | ||
| 49 | txd->ext_cid_ack = 1; | ||
| 50 | } | ||
| 51 | |||
| 52 | txd->set_query = query; | ||
| 53 | |||
| 54 | if (wait_seq) | ||
| 55 | *wait_seq = seq; | ||
| 56 | |||
| 57 | return mt76_tx_queue_skb_raw(dev, MT_TXQ_MCU, skb, 0); | ||
| 58 | } | ||
| 59 | |||
| 60 | static int | ||
| 61 | mt7603_mcu_msg_send(struct mt7603_dev *dev, struct sk_buff *skb, int cmd, | ||
| 62 | int query) | ||
| 63 | { | ||
| 64 | struct mt76_dev *mdev = &dev->mt76; | ||
| 65 | unsigned long expires = jiffies + 3 * HZ; | ||
| 66 | struct mt7603_mcu_rxd *rxd; | ||
| 67 | int ret, seq; | ||
| 68 | |||
| 69 | mutex_lock(&mdev->mmio.mcu.mutex); | ||
| 70 | |||
| 71 | ret = __mt7603_mcu_msg_send(dev, skb, cmd, query, &seq); | ||
| 72 | if (ret) | ||
| 73 | goto out; | ||
| 74 | |||
| 75 | while (1) { | ||
| 76 | bool check_seq = false; | ||
| 77 | |||
| 78 | skb = mt76_mcu_get_response(&dev->mt76, expires); | ||
| 79 | if (!skb) { | ||
| 80 | dev_err(mdev->dev, | ||
| 81 | "MCU message %d (seq %d) timed out\n", | ||
| 82 | cmd, seq); | ||
| 83 | dev->mcu_hang = MT7603_WATCHDOG_TIMEOUT; | ||
| 84 | ret = -ETIMEDOUT; | ||
| 85 | break; | ||
| 86 | } | ||
| 87 | |||
| 88 | rxd = (struct mt7603_mcu_rxd *)skb->data; | ||
| 89 | if (seq == rxd->seq) | ||
| 90 | check_seq = true; | ||
| 91 | |||
| 92 | dev_kfree_skb(skb); | ||
| 93 | |||
| 94 | if (check_seq) | ||
| 95 | break; | ||
| 96 | } | ||
| 97 | |||
| 98 | out: | ||
| 99 | mutex_unlock(&mdev->mmio.mcu.mutex); | ||
| 100 | |||
| 101 | return ret; | ||
| 102 | } | ||
| 103 | |||
| 104 | static int | ||
| 105 | mt7603_mcu_init_download(struct mt7603_dev *dev, u32 addr, u32 len) | ||
| 106 | { | ||
| 107 | struct { | ||
| 108 | __le32 addr; | ||
| 109 | __le32 len; | ||
| 110 | __le32 mode; | ||
| 111 | } req = { | ||
| 112 | .addr = cpu_to_le32(addr), | ||
| 113 | .len = cpu_to_le32(len), | ||
| 114 | .mode = cpu_to_le32(BIT(31)), | ||
| 115 | }; | ||
| 116 | struct sk_buff *skb = mt7603_mcu_msg_alloc(&req, sizeof(req)); | ||
| 117 | |||
| 118 | return mt7603_mcu_msg_send(dev, skb, -MCU_CMD_TARGET_ADDRESS_LEN_REQ, | ||
| 119 | MCU_Q_NA); | ||
| 120 | } | ||
| 121 | |||
| 122 | static int | ||
| 123 | mt7603_mcu_send_firmware(struct mt7603_dev *dev, const void *data, int len) | ||
| 124 | { | ||
| 125 | struct sk_buff *skb; | ||
| 126 | int ret = 0; | ||
| 127 | |||
| 128 | while (len > 0) { | ||
| 129 | int cur_len = min_t(int, 4096 - sizeof(struct mt7603_mcu_txd), | ||
| 130 | len); | ||
| 131 | |||
| 132 | skb = mt7603_mcu_msg_alloc(data, cur_len); | ||
| 133 | if (!skb) | ||
| 134 | return -ENOMEM; | ||
| 135 | |||
| 136 | ret = __mt7603_mcu_msg_send(dev, skb, -MCU_CMD_FW_SCATTER, | ||
| 137 | MCU_Q_NA, NULL); | ||
| 138 | if (ret) | ||
| 139 | break; | ||
| 140 | |||
| 141 | data += cur_len; | ||
| 142 | len -= cur_len; | ||
| 143 | } | ||
| 144 | |||
| 145 | return ret; | ||
| 146 | } | ||
| 147 | |||
| 148 | static int | ||
| 149 | mt7603_mcu_start_firmware(struct mt7603_dev *dev, u32 addr) | ||
| 150 | { | ||
| 151 | struct { | ||
| 152 | __le32 override; | ||
| 153 | __le32 addr; | ||
| 154 | } req = { | ||
| 155 | .override = cpu_to_le32(addr ? 1 : 0), | ||
| 156 | .addr = cpu_to_le32(addr), | ||
| 157 | }; | ||
| 158 | struct sk_buff *skb = mt7603_mcu_msg_alloc(&req, sizeof(req)); | ||
| 159 | |||
| 160 | return mt7603_mcu_msg_send(dev, skb, -MCU_CMD_FW_START_REQ, | ||
| 161 | MCU_Q_NA); | ||
| 162 | } | ||
| 163 | |||
| 164 | static int | ||
| 165 | mt7603_mcu_restart(struct mt7603_dev *dev) | ||
| 166 | { | ||
| 167 | struct sk_buff *skb = mt7603_mcu_msg_alloc(NULL, 0); | ||
| 168 | |||
| 169 | return mt7603_mcu_msg_send(dev, skb, -MCU_CMD_RESTART_DL_REQ, | ||
| 170 | MCU_Q_NA); | ||
| 171 | } | ||
| 172 | |||
| 173 | static int | ||
| 174 | mt7603_load_firmware(struct mt7603_dev *dev) | ||
| 175 | { | ||
| 176 | const struct firmware *fw; | ||
| 177 | const struct mt7603_fw_trailer *hdr; | ||
| 178 | const char *firmware; | ||
| 179 | int dl_len; | ||
| 180 | u32 addr, val; | ||
| 181 | int ret; | ||
| 182 | |||
| 183 | if (is_mt7628(dev)) { | ||
| 184 | if (mt76xx_rev(dev) == MT7628_REV_E1) | ||
| 185 | firmware = MT7628_FIRMWARE_E1; | ||
| 186 | else | ||
| 187 | firmware = MT7628_FIRMWARE_E2; | ||
| 188 | } else { | ||
| 189 | if (mt76xx_rev(dev) < MT7603_REV_E2) | ||
| 190 | firmware = MT7603_FIRMWARE_E1; | ||
| 191 | else | ||
| 192 | firmware = MT7603_FIRMWARE_E2; | ||
| 193 | } | ||
| 194 | |||
| 195 | ret = request_firmware(&fw, firmware, dev->mt76.dev); | ||
| 196 | if (ret) | ||
| 197 | return ret; | ||
| 198 | |||
| 199 | if (!fw || !fw->data || fw->size < sizeof(*hdr)) { | ||
| 200 | dev_err(dev->mt76.dev, "Invalid firmware\n"); | ||
| 201 | ret = -EINVAL; | ||
| 202 | goto out; | ||
| 203 | } | ||
| 204 | |||
| 205 | hdr = (const struct mt7603_fw_trailer *)(fw->data + fw->size - | ||
| 206 | sizeof(*hdr)); | ||
| 207 | |||
| 208 | dev_info(dev->mt76.dev, "Firmware Version: %.10s\n", hdr->fw_ver); | ||
| 209 | dev_info(dev->mt76.dev, "Build Time: %.15s\n", hdr->build_date); | ||
| 210 | |||
| 211 | addr = mt7603_reg_map(dev, 0x50012498); | ||
| 212 | mt76_wr(dev, addr, 0x5); | ||
| 213 | mt76_wr(dev, addr, 0x5); | ||
| 214 | udelay(1); | ||
| 215 | |||
| 216 | /* switch to bypass mode */ | ||
| 217 | mt76_rmw(dev, MT_SCH_4, MT_SCH_4_FORCE_QID, | ||
| 218 | MT_SCH_4_BYPASS | FIELD_PREP(MT_SCH_4_FORCE_QID, 5)); | ||
| 219 | |||
| 220 | val = mt76_rr(dev, MT_TOP_MISC2); | ||
| 221 | if (val & BIT(1)) { | ||
| 222 | dev_info(dev->mt76.dev, "Firmware already running...\n"); | ||
| 223 | goto running; | ||
| 224 | } | ||
| 225 | |||
| 226 | if (!mt76_poll_msec(dev, MT_TOP_MISC2, BIT(0) | BIT(1), BIT(0), 500)) { | ||
| 227 | dev_err(dev->mt76.dev, "Timeout waiting for ROM code to become ready\n"); | ||
| 228 | ret = -EIO; | ||
| 229 | goto out; | ||
| 230 | } | ||
| 231 | |||
| 232 | dl_len = le32_to_cpu(hdr->dl_len) + 4; | ||
| 233 | ret = mt7603_mcu_init_download(dev, MCU_FIRMWARE_ADDRESS, dl_len); | ||
| 234 | if (ret) { | ||
| 235 | dev_err(dev->mt76.dev, "Download request failed\n"); | ||
| 236 | goto out; | ||
| 237 | } | ||
| 238 | |||
| 239 | ret = mt7603_mcu_send_firmware(dev, fw->data, dl_len); | ||
| 240 | if (ret) { | ||
| 241 | dev_err(dev->mt76.dev, "Failed to send firmware to device\n"); | ||
| 242 | goto out; | ||
| 243 | } | ||
| 244 | |||
| 245 | ret = mt7603_mcu_start_firmware(dev, MCU_FIRMWARE_ADDRESS); | ||
| 246 | if (ret) { | ||
| 247 | dev_err(dev->mt76.dev, "Failed to start firmware\n"); | ||
| 248 | goto out; | ||
| 249 | } | ||
| 250 | |||
| 251 | if (!mt76_poll_msec(dev, MT_TOP_MISC2, BIT(1), BIT(1), 500)) { | ||
| 252 | dev_err(dev->mt76.dev, "Timeout waiting for firmware to initialize\n"); | ||
| 253 | ret = -EIO; | ||
| 254 | goto out; | ||
| 255 | } | ||
| 256 | |||
| 257 | running: | ||
| 258 | mt76_clear(dev, MT_SCH_4, MT_SCH_4_FORCE_QID | MT_SCH_4_BYPASS); | ||
| 259 | |||
| 260 | mt76_set(dev, MT_SCH_4, BIT(8)); | ||
| 261 | mt76_clear(dev, MT_SCH_4, BIT(8)); | ||
| 262 | |||
| 263 | dev->mcu_running = true; | ||
| 264 | dev_info(dev->mt76.dev, "firmware init done\n"); | ||
| 265 | |||
| 266 | out: | ||
| 267 | release_firmware(fw); | ||
| 268 | |||
| 269 | return ret; | ||
| 270 | } | ||
| 271 | |||
| 272 | int mt7603_mcu_init(struct mt7603_dev *dev) | ||
| 273 | { | ||
| 274 | mutex_init(&dev->mt76.mmio.mcu.mutex); | ||
| 275 | |||
| 276 | return mt7603_load_firmware(dev); | ||
| 277 | } | ||
| 278 | |||
| 279 | void mt7603_mcu_exit(struct mt7603_dev *dev) | ||
| 280 | { | ||
| 281 | mt7603_mcu_restart(dev); | ||
| 282 | skb_queue_purge(&dev->mt76.mmio.mcu.res_q); | ||
| 283 | } | ||
| 284 | |||
| 285 | int mt7603_mcu_set_eeprom(struct mt7603_dev *dev) | ||
| 286 | { | ||
| 287 | static const u16 req_fields[] = { | ||
| 288 | #define WORD(_start) \ | ||
| 289 | _start, \ | ||
| 290 | _start + 1 | ||
| 291 | #define GROUP_2G(_start) \ | ||
| 292 | WORD(_start), \ | ||
| 293 | WORD(_start + 2), \ | ||
| 294 | WORD(_start + 4) | ||
| 295 | |||
| 296 | MT_EE_NIC_CONF_0 + 1, | ||
| 297 | WORD(MT_EE_NIC_CONF_1), | ||
| 298 | MT_EE_WIFI_RF_SETTING, | ||
| 299 | MT_EE_TX_POWER_DELTA_BW40, | ||
| 300 | MT_EE_TX_POWER_DELTA_BW80 + 1, | ||
| 301 | MT_EE_TX_POWER_EXT_PA_5G, | ||
| 302 | MT_EE_TEMP_SENSOR_CAL, | ||
| 303 | GROUP_2G(MT_EE_TX_POWER_0_START_2G), | ||
| 304 | GROUP_2G(MT_EE_TX_POWER_1_START_2G), | ||
| 305 | WORD(MT_EE_TX_POWER_CCK), | ||
| 306 | WORD(MT_EE_TX_POWER_OFDM_2G_6M), | ||
| 307 | WORD(MT_EE_TX_POWER_OFDM_2G_24M), | ||
| 308 | WORD(MT_EE_TX_POWER_OFDM_2G_54M), | ||
| 309 | WORD(MT_EE_TX_POWER_HT_BPSK_QPSK), | ||
| 310 | WORD(MT_EE_TX_POWER_HT_16_64_QAM), | ||
| 311 | WORD(MT_EE_TX_POWER_HT_64_QAM), | ||
| 312 | MT_EE_ELAN_RX_MODE_GAIN, | ||
| 313 | MT_EE_ELAN_RX_MODE_NF, | ||
| 314 | MT_EE_ELAN_RX_MODE_P1DB, | ||
| 315 | MT_EE_ELAN_BYPASS_MODE_GAIN, | ||
| 316 | MT_EE_ELAN_BYPASS_MODE_NF, | ||
| 317 | MT_EE_ELAN_BYPASS_MODE_P1DB, | ||
| 318 | WORD(MT_EE_STEP_NUM_NEG_6_7), | ||
| 319 | WORD(MT_EE_STEP_NUM_NEG_4_5), | ||
| 320 | WORD(MT_EE_STEP_NUM_NEG_2_3), | ||
| 321 | WORD(MT_EE_STEP_NUM_NEG_0_1), | ||
| 322 | WORD(MT_EE_REF_STEP_24G), | ||
| 323 | WORD(MT_EE_STEP_NUM_PLUS_1_2), | ||
| 324 | WORD(MT_EE_STEP_NUM_PLUS_3_4), | ||
| 325 | WORD(MT_EE_STEP_NUM_PLUS_5_6), | ||
| 326 | MT_EE_STEP_NUM_PLUS_7, | ||
| 327 | MT_EE_XTAL_FREQ_OFFSET, | ||
| 328 | MT_EE_XTAL_TRIM_2_COMP, | ||
| 329 | MT_EE_XTAL_TRIM_3_COMP, | ||
| 330 | MT_EE_XTAL_WF_RFCAL, | ||
| 331 | |||
| 332 | /* unknown fields below */ | ||
| 333 | WORD(0x24), | ||
| 334 | 0x34, | ||
| 335 | 0x39, | ||
| 336 | 0x3b, | ||
| 337 | WORD(0x42), | ||
| 338 | WORD(0x9e), | ||
| 339 | 0xf2, | ||
| 340 | WORD(0xf8), | ||
| 341 | 0xfa, | ||
| 342 | 0x12e, | ||
| 343 | WORD(0x130), WORD(0x132), WORD(0x134), WORD(0x136), | ||
| 344 | WORD(0x138), WORD(0x13a), WORD(0x13c), WORD(0x13e), | ||
| 345 | |||
| 346 | #undef GROUP_2G | ||
| 347 | #undef WORD | ||
| 348 | |||
| 349 | }; | ||
| 350 | struct req_data { | ||
| 351 | u16 addr; | ||
| 352 | u8 val; | ||
| 353 | u8 pad; | ||
| 354 | } __packed; | ||
| 355 | struct { | ||
| 356 | u8 buffer_mode; | ||
| 357 | u8 len; | ||
| 358 | u8 pad[2]; | ||
| 359 | } req_hdr = { | ||
| 360 | .buffer_mode = 1, | ||
| 361 | .len = ARRAY_SIZE(req_fields) - 1, | ||
| 362 | }; | ||
| 363 | struct sk_buff *skb; | ||
| 364 | struct req_data *data; | ||
| 365 | const int size = 0xff * sizeof(struct req_data); | ||
| 366 | u8 *eep = (u8 *)dev->mt76.eeprom.data; | ||
| 367 | int i; | ||
| 368 | |||
| 369 | BUILD_BUG_ON(ARRAY_SIZE(req_fields) * sizeof(*data) > size); | ||
| 370 | |||
| 371 | skb = mt7603_mcu_msg_alloc(NULL, size + sizeof(req_hdr)); | ||
| 372 | memcpy(skb_put(skb, sizeof(req_hdr)), &req_hdr, sizeof(req_hdr)); | ||
| 373 | data = (struct req_data *)skb_put(skb, size); | ||
| 374 | memset(data, 0, size); | ||
| 375 | |||
| 376 | for (i = 0; i < ARRAY_SIZE(req_fields); i++) { | ||
| 377 | data[i].addr = cpu_to_le16(req_fields[i]); | ||
| 378 | data[i].val = eep[req_fields[i]]; | ||
| 379 | data[i].pad = 0; | ||
| 380 | } | ||
| 381 | |||
| 382 | return mt7603_mcu_msg_send(dev, skb, MCU_EXT_CMD_EFUSE_BUFFER_MODE, | ||
| 383 | MCU_Q_SET); | ||
| 384 | } | ||
| 385 | |||
| 386 | static int mt7603_mcu_set_tx_power(struct mt7603_dev *dev) | ||
| 387 | { | ||
| 388 | struct { | ||
| 389 | u8 center_channel; | ||
| 390 | u8 tssi; | ||
| 391 | u8 temp_comp; | ||
| 392 | u8 target_power[2]; | ||
| 393 | u8 rate_power_delta[14]; | ||
| 394 | u8 bw_power_delta; | ||
| 395 | u8 ch_power_delta[6]; | ||
| 396 | u8 temp_comp_power[17]; | ||
| 397 | u8 reserved; | ||
| 398 | } req = { | ||
| 399 | .center_channel = dev->mt76.chandef.chan->hw_value, | ||
| 400 | #define EEP_VAL(n) ((u8 *)dev->mt76.eeprom.data)[n] | ||
| 401 | .tssi = EEP_VAL(MT_EE_NIC_CONF_1 + 1), | ||
| 402 | .temp_comp = EEP_VAL(MT_EE_NIC_CONF_1), | ||
| 403 | .target_power = { | ||
| 404 | EEP_VAL(MT_EE_TX_POWER_0_START_2G + 2), | ||
| 405 | EEP_VAL(MT_EE_TX_POWER_1_START_2G + 2) | ||
| 406 | }, | ||
| 407 | .bw_power_delta = EEP_VAL(MT_EE_TX_POWER_DELTA_BW40), | ||
| 408 | .ch_power_delta = { | ||
| 409 | EEP_VAL(MT_EE_TX_POWER_0_START_2G + 3), | ||
| 410 | EEP_VAL(MT_EE_TX_POWER_0_START_2G + 4), | ||
| 411 | EEP_VAL(MT_EE_TX_POWER_0_START_2G + 5), | ||
| 412 | EEP_VAL(MT_EE_TX_POWER_1_START_2G + 3), | ||
| 413 | EEP_VAL(MT_EE_TX_POWER_1_START_2G + 4), | ||
| 414 | EEP_VAL(MT_EE_TX_POWER_1_START_2G + 5) | ||
| 415 | }, | ||
| 416 | #undef EEP_VAL | ||
| 417 | }; | ||
| 418 | struct sk_buff *skb; | ||
| 419 | u8 *eep = (u8 *)dev->mt76.eeprom.data; | ||
| 420 | |||
| 421 | memcpy(req.rate_power_delta, eep + MT_EE_TX_POWER_CCK, | ||
| 422 | sizeof(req.rate_power_delta)); | ||
| 423 | |||
| 424 | memcpy(req.temp_comp_power, eep + MT_EE_STEP_NUM_NEG_6_7, | ||
| 425 | sizeof(req.temp_comp_power)); | ||
| 426 | |||
| 427 | skb = mt7603_mcu_msg_alloc(&req, sizeof(req)); | ||
| 428 | return mt7603_mcu_msg_send(dev, skb, MCU_EXT_CMD_SET_TX_POWER_CTRL, | ||
| 429 | MCU_Q_SET); | ||
| 430 | } | ||
| 431 | |||
| 432 | int mt7603_mcu_set_channel(struct mt7603_dev *dev) | ||
| 433 | { | ||
| 434 | struct cfg80211_chan_def *chandef = &dev->mt76.chandef; | ||
| 435 | struct ieee80211_hw *hw = mt76_hw(dev); | ||
| 436 | int n_chains = __sw_hweight8(dev->mt76.antenna_mask); | ||
| 437 | struct { | ||
| 438 | u8 control_chan; | ||
| 439 | u8 center_chan; | ||
| 440 | u8 bw; | ||
| 441 | u8 tx_streams; | ||
| 442 | u8 rx_streams; | ||
| 443 | u8 _res0[7]; | ||
| 444 | u8 txpower[21]; | ||
| 445 | u8 _res1[3]; | ||
| 446 | } req = { | ||
| 447 | .control_chan = chandef->chan->hw_value, | ||
| 448 | .center_chan = chandef->chan->hw_value, | ||
| 449 | .bw = MT_BW_20, | ||
| 450 | .tx_streams = n_chains, | ||
| 451 | .rx_streams = n_chains, | ||
| 452 | }; | ||
| 453 | struct sk_buff *skb; | ||
| 454 | s8 tx_power; | ||
| 455 | int ret; | ||
| 456 | int i; | ||
| 457 | |||
| 458 | if (dev->mt76.chandef.width == NL80211_CHAN_WIDTH_40) { | ||
| 459 | req.bw = MT_BW_40; | ||
| 460 | if (chandef->center_freq1 > chandef->chan->center_freq) | ||
| 461 | req.center_chan += 2; | ||
| 462 | else | ||
| 463 | req.center_chan -= 2; | ||
| 464 | } | ||
| 465 | |||
| 466 | tx_power = hw->conf.power_level * 2; | ||
| 467 | if (dev->mt76.antenna_mask == 3) | ||
| 468 | tx_power -= 6; | ||
| 469 | tx_power = min(tx_power, dev->tx_power_limit); | ||
| 470 | |||
| 471 | dev->mt76.txpower_cur = tx_power; | ||
| 472 | |||
| 473 | for (i = 0; i < ARRAY_SIZE(req.txpower); i++) | ||
| 474 | req.txpower[i] = tx_power; | ||
| 475 | |||
| 476 | skb = mt7603_mcu_msg_alloc(&req, sizeof(req)); | ||
| 477 | ret = mt7603_mcu_msg_send(dev, skb, MCU_EXT_CMD_CHANNEL_SWITCH, | ||
| 478 | MCU_Q_SET); | ||
| 479 | if (ret) | ||
| 480 | return ret; | ||
| 481 | |||
| 482 | return mt7603_mcu_set_tx_power(dev); | ||
| 483 | } | ||
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.h new file mode 100644 index 000000000000..1bba369d5c8a --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mcu.h | |||
| @@ -0,0 +1,110 @@ | |||
| 1 | /* SPDX-License-Identifier: ISC */ | ||
| 2 | |||
| 3 | #ifndef __MT7603_MCU_H | ||
| 4 | #define __MT7603_MCU_H | ||
| 5 | |||
| 6 | struct mt7603_mcu_txd { | ||
| 7 | __le16 len; | ||
| 8 | __le16 pq_id; | ||
| 9 | |||
| 10 | u8 cid; | ||
| 11 | u8 pkt_type; | ||
| 12 | u8 set_query; | ||
| 13 | u8 seq; | ||
| 14 | |||
| 15 | u8 uc_d2b0_rev; | ||
| 16 | u8 ext_cid; | ||
| 17 | u8 uc_d2b2_rev; | ||
| 18 | u8 ext_cid_ack; | ||
| 19 | |||
| 20 | u32 au4_d3_to_d7_rev[5]; | ||
| 21 | } __packed __aligned(4); | ||
| 22 | |||
| 23 | struct mt7603_mcu_rxd { | ||
| 24 | __le16 len; | ||
| 25 | __le16 pkt_type_id; | ||
| 26 | |||
| 27 | u8 eid; | ||
| 28 | u8 seq; | ||
| 29 | __le16 __rsv; | ||
| 30 | |||
| 31 | u8 ext_eid; | ||
| 32 | u8 __rsv1[3]; | ||
| 33 | }; | ||
| 34 | |||
| 35 | #define MCU_PKT_ID 0xa0 | ||
| 36 | #define MCU_PORT_QUEUE 0x8000 | ||
| 37 | #define MCU_PORT_QUEUE_FW 0xc000 | ||
| 38 | |||
| 39 | #define MCU_FIRMWARE_ADDRESS 0x100000 | ||
| 40 | |||
| 41 | enum { | ||
| 42 | MCU_Q_QUERY, | ||
| 43 | MCU_Q_SET, | ||
| 44 | MCU_Q_RESERVED, | ||
| 45 | MCU_Q_NA | ||
| 46 | }; | ||
| 47 | |||
| 48 | enum { | ||
| 49 | MCU_CMD_TARGET_ADDRESS_LEN_REQ = 0x01, | ||
| 50 | MCU_CMD_FW_START_REQ = 0x02, | ||
| 51 | MCU_CMD_INIT_ACCESS_REG = 0x3, | ||
| 52 | MCU_CMD_PATCH_START_REQ = 0x05, | ||
| 53 | MCU_CMD_PATCH_FINISH_REQ = 0x07, | ||
| 54 | MCU_CMD_PATCH_SEM_CONTROL = 0x10, | ||
| 55 | MCU_CMD_HIF_LOOPBACK = 0x20, | ||
| 56 | MCU_CMD_CH_PRIVILEGE = 0x20, | ||
| 57 | MCU_CMD_ACCESS_REG = 0xC2, | ||
| 58 | MCU_CMD_EXT_CID = 0xED, | ||
| 59 | MCU_CMD_FW_SCATTER = 0xEE, | ||
| 60 | MCU_CMD_RESTART_DL_REQ = 0xEF, | ||
| 61 | }; | ||
| 62 | |||
| 63 | enum { | ||
| 64 | MCU_EXT_CMD_RF_REG_ACCESS = 0x02, | ||
| 65 | MCU_EXT_CMD_RF_TEST = 0x04, | ||
| 66 | MCU_EXT_CMD_RADIO_ON_OFF_CTRL = 0x05, | ||
| 67 | MCU_EXT_CMD_WIFI_RX_DISABLE = 0x06, | ||
| 68 | MCU_EXT_CMD_PM_STATE_CTRL = 0x07, | ||
| 69 | MCU_EXT_CMD_CHANNEL_SWITCH = 0x08, | ||
| 70 | MCU_EXT_CMD_NIC_CAPABILITY = 0x09, | ||
| 71 | MCU_EXT_CMD_PWR_SAVING = 0x0A, | ||
| 72 | MCU_EXT_CMD_MULTIPLE_REG_ACCESS = 0x0E, | ||
| 73 | MCU_EXT_CMD_AP_PWR_SAVING_CAPABILITY = 0xF, | ||
| 74 | MCU_EXT_CMD_SEC_ADDREMOVE_KEY = 0x10, | ||
| 75 | MCU_EXT_CMD_SET_TX_POWER_CTRL = 0x11, | ||
| 76 | MCU_EXT_CMD_FW_LOG_2_HOST = 0x13, | ||
| 77 | MCU_EXT_CMD_PS_RETRIEVE_START = 0x14, | ||
| 78 | MCU_EXT_CMD_LED_CTRL = 0x17, | ||
| 79 | MCU_EXT_CMD_PACKET_FILTER = 0x18, | ||
| 80 | MCU_EXT_CMD_PWR_MGT_BIT_WIFI = 0x1B, | ||
| 81 | MCU_EXT_CMD_EFUSE_BUFFER_MODE = 0x21, | ||
| 82 | MCU_EXT_CMD_THERMAL_PROTECT = 0x23, | ||
| 83 | MCU_EXT_CMD_EDCA_SET = 0x27, | ||
| 84 | MCU_EXT_CMD_SLOT_TIME_SET = 0x28, | ||
| 85 | MCU_EXT_CMD_CONFIG_INTERNAL_SETTING = 0x29, | ||
| 86 | MCU_EXT_CMD_NOA_OFFLOAD_CTRL = 0x2B, | ||
| 87 | MCU_EXT_CMD_GET_THEMAL_SENSOR = 0x2C, | ||
| 88 | MCU_EXT_CMD_WAKEUP_OPTION = 0x2E, | ||
| 89 | MCU_EXT_CMD_AC_QUEUE_CONTROL = 0x31, | ||
| 90 | MCU_EXT_CMD_BCN_UPDATE = 0x33 | ||
| 91 | }; | ||
| 92 | |||
| 93 | enum { | ||
| 94 | MCU_EXT_EVENT_CMD_RESULT = 0x0, | ||
| 95 | MCU_EXT_EVENT_RF_REG_ACCESS = 0x2, | ||
| 96 | MCU_EXT_EVENT_MULTI_CR_ACCESS = 0x0E, | ||
| 97 | MCU_EXT_EVENT_FW_LOG_2_HOST = 0x13, | ||
| 98 | MCU_EXT_EVENT_BEACON_LOSS = 0x1A, | ||
| 99 | MCU_EXT_EVENT_THERMAL_PROTECT = 0x22, | ||
| 100 | MCU_EXT_EVENT_BCN_UPDATE = 0x31, | ||
| 101 | }; | ||
| 102 | |||
| 103 | static inline struct sk_buff * | ||
| 104 | mt7603_mcu_msg_alloc(const void *data, int len) | ||
| 105 | { | ||
| 106 | return mt76_mcu_msg_alloc(data, sizeof(struct mt7603_mcu_txd), | ||
| 107 | len, 0); | ||
| 108 | } | ||
| 109 | |||
| 110 | #endif | ||
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h new file mode 100644 index 000000000000..79f332429432 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7603/mt7603.h | |||
| @@ -0,0 +1,253 @@ | |||
| 1 | /* SPDX-License-Identifier: ISC */ | ||
| 2 | |||
| 3 | #ifndef __MT7603_H | ||
| 4 | #define __MT7603_H | ||
| 5 | |||
| 6 | #include <linux/interrupt.h> | ||
| 7 | #include <linux/ktime.h> | ||
| 8 | #include "../mt76.h" | ||
| 9 | #include "regs.h" | ||
| 10 | |||
| 11 | #define MT7603_MAX_INTERFACES 4 | ||
| 12 | #define MT7603_WTBL_SIZE 128 | ||
| 13 | #define MT7603_WTBL_RESERVED (MT7603_WTBL_SIZE - 1) | ||
| 14 | #define MT7603_WTBL_STA (MT7603_WTBL_RESERVED - MT7603_MAX_INTERFACES) | ||
| 15 | |||
| 16 | #define MT7603_RATE_RETRY 2 | ||
| 17 | |||
| 18 | #define MT7603_RX_RING_SIZE 128 | ||
| 19 | |||
| 20 | #define MT7603_FIRMWARE_E1 "mt7603_e1.bin" | ||
| 21 | #define MT7603_FIRMWARE_E2 "mt7603_e2.bin" | ||
| 22 | #define MT7628_FIRMWARE_E1 "mt7628_e1.bin" | ||
| 23 | #define MT7628_FIRMWARE_E2 "mt7628_e2.bin" | ||
| 24 | |||
| 25 | #define MT7603_EEPROM_SIZE 1024 | ||
| 26 | |||
| 27 | #define MT_AGG_SIZE_LIMIT(_n) (((_n) + 1) * 4) | ||
| 28 | |||
| 29 | #define MT7603_PRE_TBTT_TIME 5000 /* ms */ | ||
| 30 | |||
| 31 | #define MT7603_WATCHDOG_TIME 100 /* ms */ | ||
| 32 | #define MT7603_WATCHDOG_TIMEOUT 10 /* number of checks */ | ||
| 33 | |||
| 34 | #define MT7603_EDCCA_BLOCK_TH 10 | ||
| 35 | |||
| 36 | #define MT7603_CFEND_RATE_DEFAULT 0x69 /* chip default (24M) */ | ||
| 37 | #define MT7603_CFEND_RATE_11B 0x03 /* 11B LP, 11M */ | ||
| 38 | |||
| 39 | struct mt7603_vif; | ||
| 40 | struct mt7603_sta; | ||
| 41 | |||
| 42 | enum { | ||
| 43 | MT7603_REV_E1 = 0x00, | ||
| 44 | MT7603_REV_E2 = 0x10, | ||
| 45 | MT7628_REV_E1 = 0x8a00, | ||
| 46 | }; | ||
| 47 | |||
| 48 | enum mt7603_bw { | ||
| 49 | MT_BW_20, | ||
| 50 | MT_BW_40, | ||
| 51 | MT_BW_80, | ||
| 52 | }; | ||
| 53 | |||
| 54 | struct mt7603_sta { | ||
| 55 | struct mt76_wcid wcid; /* must be first */ | ||
| 56 | |||
| 57 | struct mt7603_vif *vif; | ||
| 58 | |||
| 59 | struct sk_buff_head psq; | ||
| 60 | |||
| 61 | struct ieee80211_tx_rate rates[8]; | ||
| 62 | u8 rate_count; | ||
| 63 | u8 n_rates; | ||
| 64 | |||
| 65 | u8 rate_probe; | ||
| 66 | u8 smps; | ||
| 67 | |||
| 68 | u8 ps; | ||
| 69 | }; | ||
| 70 | |||
| 71 | struct mt7603_vif { | ||
| 72 | struct mt7603_sta sta; /* must be first */ | ||
| 73 | |||
| 74 | u8 idx; | ||
| 75 | }; | ||
| 76 | |||
| 77 | enum mt7603_reset_cause { | ||
| 78 | RESET_CAUSE_TX_HANG, | ||
| 79 | RESET_CAUSE_TX_BUSY, | ||
| 80 | RESET_CAUSE_RX_BUSY, | ||
| 81 | RESET_CAUSE_BEACON_STUCK, | ||
| 82 | RESET_CAUSE_RX_PSE_BUSY, | ||
| 83 | RESET_CAUSE_MCU_HANG, | ||
| 84 | RESET_CAUSE_RESET_FAILED, | ||
| 85 | __RESET_CAUSE_MAX | ||
| 86 | }; | ||
| 87 | |||
| 88 | struct mt7603_dev { | ||
| 89 | struct mt76_dev mt76; /* must be first */ | ||
| 90 | |||
| 91 | const struct mt76_bus_ops *bus_ops; | ||
| 92 | |||
| 93 | u32 rxfilter; | ||
| 94 | |||
| 95 | u8 vif_mask; | ||
| 96 | |||
| 97 | struct mt7603_sta global_sta; | ||
| 98 | |||
| 99 | u32 agc0, agc3; | ||
| 100 | u32 false_cca_ofdm, false_cca_cck; | ||
| 101 | unsigned long last_cca_adj; | ||
| 102 | |||
| 103 | u8 rssi_offset[3]; | ||
| 104 | |||
| 105 | u8 slottime; | ||
| 106 | s16 coverage_class; | ||
| 107 | |||
| 108 | s8 tx_power_limit; | ||
| 109 | |||
| 110 | ktime_t survey_time; | ||
| 111 | ktime_t ed_time; | ||
| 112 | int beacon_int; | ||
| 113 | |||
| 114 | struct mt76_queue q_rx; | ||
| 115 | |||
| 116 | spinlock_t ps_lock; | ||
| 117 | |||
| 118 | u8 mac_work_count; | ||
| 119 | |||
| 120 | u8 mcu_running; | ||
| 121 | u8 ed_monitor; | ||
| 122 | |||
| 123 | s8 ed_trigger; | ||
| 124 | u8 ed_strict_mode; | ||
| 125 | u8 ed_strong_signal; | ||
| 126 | |||
| 127 | s8 sensitivity; | ||
| 128 | |||
| 129 | u8 beacon_mask; | ||
| 130 | |||
| 131 | u8 beacon_check; | ||
| 132 | u8 tx_hang_check; | ||
| 133 | u8 tx_dma_check; | ||
| 134 | u8 rx_dma_check; | ||
| 135 | u8 rx_pse_check; | ||
| 136 | u8 mcu_hang; | ||
| 137 | |||
| 138 | enum mt7603_reset_cause cur_reset_cause; | ||
| 139 | |||
| 140 | u16 tx_dma_idx[4]; | ||
| 141 | u16 rx_dma_idx; | ||
| 142 | |||
| 143 | u32 reset_test; | ||
| 144 | |||
| 145 | unsigned int reset_cause[__RESET_CAUSE_MAX]; | ||
| 146 | |||
| 147 | struct delayed_work mac_work; | ||
| 148 | struct tasklet_struct tx_tasklet; | ||
| 149 | struct tasklet_struct pre_tbtt_tasklet; | ||
| 150 | }; | ||
| 151 | |||
| 152 | extern const struct mt76_driver_ops mt7603_drv_ops; | ||
| 153 | extern const struct ieee80211_ops mt7603_ops; | ||
| 154 | extern struct pci_driver mt7603_pci_driver; | ||
| 155 | extern struct platform_driver mt76_wmac_driver; | ||
| 156 | |||
| 157 | static inline bool is_mt7603(struct mt7603_dev *dev) | ||
| 158 | { | ||
| 159 | return mt76xx_chip(dev) == 0x7603; | ||
| 160 | } | ||
| 161 | |||
| 162 | static inline bool is_mt7628(struct mt7603_dev *dev) | ||
| 163 | { | ||
| 164 | return mt76xx_chip(dev) == 0x7628; | ||
| 165 | } | ||
| 166 | |||
| 167 | /* need offset to prevent conflict with ampdu_ack_len */ | ||
| 168 | #define MT_RATE_DRIVER_DATA_OFFSET 4 | ||
| 169 | |||
| 170 | u32 mt7603_reg_map(struct mt7603_dev *dev, u32 addr); | ||
| 171 | |||
| 172 | irqreturn_t mt7603_irq_handler(int irq, void *dev_instance); | ||
| 173 | |||
| 174 | int mt7603_register_device(struct mt7603_dev *dev); | ||
| 175 | void mt7603_unregister_device(struct mt7603_dev *dev); | ||
| 176 | int mt7603_eeprom_init(struct mt7603_dev *dev); | ||
| 177 | int mt7603_dma_init(struct mt7603_dev *dev); | ||
| 178 | void mt7603_dma_cleanup(struct mt7603_dev *dev); | ||
| 179 | int mt7603_mcu_init(struct mt7603_dev *dev); | ||
| 180 | void mt7603_init_debugfs(struct mt7603_dev *dev); | ||
| 181 | |||
| 182 | void mt7603_set_irq_mask(struct mt7603_dev *dev, u32 clear, u32 set); | ||
| 183 | |||
| 184 | static inline void mt7603_irq_enable(struct mt7603_dev *dev, u32 mask) | ||
| 185 | { | ||
| 186 | mt7603_set_irq_mask(dev, 0, mask); | ||
| 187 | } | ||
| 188 | |||
| 189 | static inline void mt7603_irq_disable(struct mt7603_dev *dev, u32 mask) | ||
| 190 | { | ||
| 191 | mt7603_set_irq_mask(dev, mask, 0); | ||
| 192 | } | ||
| 193 | |||
| 194 | void mt7603_mac_dma_start(struct mt7603_dev *dev); | ||
| 195 | void mt7603_mac_start(struct mt7603_dev *dev); | ||
| 196 | void mt7603_mac_stop(struct mt7603_dev *dev); | ||
| 197 | void mt7603_mac_work(struct work_struct *work); | ||
| 198 | void mt7603_mac_set_timing(struct mt7603_dev *dev); | ||
| 199 | void mt7603_beacon_set_timer(struct mt7603_dev *dev, int idx, int intval); | ||
| 200 | int mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb); | ||
| 201 | void mt7603_mac_add_txs(struct mt7603_dev *dev, void *data); | ||
| 202 | void mt7603_mac_rx_ba_reset(struct mt7603_dev *dev, void *addr, u8 tid); | ||
| 203 | void mt7603_mac_tx_ba_reset(struct mt7603_dev *dev, int wcid, int tid, int ssn, | ||
| 204 | int ba_size); | ||
| 205 | |||
| 206 | void mt7603_pse_client_reset(struct mt7603_dev *dev); | ||
| 207 | |||
| 208 | int mt7603_mcu_set_channel(struct mt7603_dev *dev); | ||
| 209 | int mt7603_mcu_set_eeprom(struct mt7603_dev *dev); | ||
| 210 | void mt7603_mcu_exit(struct mt7603_dev *dev); | ||
| 211 | |||
| 212 | void mt7603_wtbl_init(struct mt7603_dev *dev, int idx, int vif, | ||
| 213 | const u8 *mac_addr); | ||
| 214 | void mt7603_wtbl_clear(struct mt7603_dev *dev, int idx); | ||
| 215 | void mt7603_wtbl_update_cap(struct mt7603_dev *dev, struct ieee80211_sta *sta); | ||
| 216 | void mt7603_wtbl_set_rates(struct mt7603_dev *dev, struct mt7603_sta *sta, | ||
| 217 | struct ieee80211_tx_rate *probe_rate, | ||
| 218 | struct ieee80211_tx_rate *rates); | ||
| 219 | int mt7603_wtbl_set_key(struct mt7603_dev *dev, int wcid, | ||
| 220 | struct ieee80211_key_conf *key); | ||
| 221 | void mt7603_wtbl_set_ps(struct mt7603_dev *dev, struct mt7603_sta *sta, | ||
| 222 | bool enabled); | ||
| 223 | void mt7603_wtbl_set_smps(struct mt7603_dev *dev, struct mt7603_sta *sta, | ||
| 224 | bool enabled); | ||
| 225 | void mt7603_filter_tx(struct mt7603_dev *dev, int idx, bool abort); | ||
| 226 | |||
| 227 | int mt7603_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, | ||
| 228 | struct sk_buff *skb, struct mt76_queue *q, | ||
| 229 | struct mt76_wcid *wcid, struct ieee80211_sta *sta, | ||
| 230 | u32 *tx_info); | ||
| 231 | |||
| 232 | void mt7603_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q, | ||
| 233 | struct mt76_queue_entry *e, bool flush); | ||
| 234 | |||
| 235 | void mt7603_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q, | ||
| 236 | struct sk_buff *skb); | ||
| 237 | void mt7603_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q); | ||
| 238 | void mt7603_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps); | ||
| 239 | int mt7603_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif, | ||
| 240 | struct ieee80211_sta *sta); | ||
| 241 | void mt7603_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif, | ||
| 242 | struct ieee80211_sta *sta); | ||
| 243 | void mt7603_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif, | ||
| 244 | struct ieee80211_sta *sta); | ||
| 245 | |||
| 246 | void mt7603_pre_tbtt_tasklet(unsigned long arg); | ||
| 247 | |||
| 248 | void mt7603_update_channel(struct mt76_dev *mdev); | ||
| 249 | |||
| 250 | void mt7603_edcca_set_strict(struct mt7603_dev *dev, bool val); | ||
| 251 | void mt7603_cca_stats_reset(struct mt7603_dev *dev); | ||
| 252 | |||
| 253 | #endif | ||
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/pci.c b/drivers/net/wireless/mediatek/mt76/mt7603/pci.c new file mode 100644 index 000000000000..4acdbf5d8968 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7603/pci.c | |||
| @@ -0,0 +1,80 @@ | |||
| 1 | /* SPDX-License-Identifier: ISC */ | ||
| 2 | |||
| 3 | #include <linux/kernel.h> | ||
| 4 | #include <linux/module.h> | ||
| 5 | #include <linux/pci.h> | ||
| 6 | |||
| 7 | #include "mt7603.h" | ||
| 8 | |||
| 9 | static const struct pci_device_id mt76pci_device_table[] = { | ||
| 10 | { PCI_DEVICE(0x14c3, 0x7603) }, | ||
| 11 | { }, | ||
| 12 | }; | ||
| 13 | |||
| 14 | static int | ||
| 15 | mt76pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | ||
| 16 | { | ||
| 17 | struct mt7603_dev *dev; | ||
| 18 | struct mt76_dev *mdev; | ||
| 19 | int ret; | ||
| 20 | |||
| 21 | ret = pcim_enable_device(pdev); | ||
| 22 | if (ret) | ||
| 23 | return ret; | ||
| 24 | |||
| 25 | ret = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev)); | ||
| 26 | if (ret) | ||
| 27 | return ret; | ||
| 28 | |||
| 29 | pci_set_master(pdev); | ||
| 30 | |||
| 31 | ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); | ||
| 32 | if (ret) | ||
| 33 | return ret; | ||
| 34 | |||
| 35 | mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt7603_ops, | ||
| 36 | &mt7603_drv_ops); | ||
| 37 | if (!mdev) | ||
| 38 | return -ENOMEM; | ||
| 39 | |||
| 40 | dev = container_of(mdev, struct mt7603_dev, mt76); | ||
| 41 | mt76_mmio_init(mdev, pcim_iomap_table(pdev)[0]); | ||
| 42 | |||
| 43 | mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) | | ||
| 44 | (mt76_rr(dev, MT_HW_REV) & 0xff); | ||
| 45 | dev_info(mdev->dev, "ASIC revision: %04x\n", mdev->rev); | ||
| 46 | |||
| 47 | ret = devm_request_irq(mdev->dev, pdev->irq, mt7603_irq_handler, | ||
| 48 | IRQF_SHARED, KBUILD_MODNAME, dev); | ||
| 49 | if (ret) | ||
| 50 | goto error; | ||
| 51 | |||
| 52 | ret = mt7603_register_device(dev); | ||
| 53 | if (ret) | ||
| 54 | goto error; | ||
| 55 | |||
| 56 | return 0; | ||
| 57 | error: | ||
| 58 | ieee80211_free_hw(mt76_hw(dev)); | ||
| 59 | return ret; | ||
| 60 | } | ||
| 61 | |||
| 62 | static void | ||
| 63 | mt76pci_remove(struct pci_dev *pdev) | ||
| 64 | { | ||
| 65 | struct mt76_dev *mdev = pci_get_drvdata(pdev); | ||
| 66 | struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); | ||
| 67 | |||
| 68 | mt7603_unregister_device(dev); | ||
| 69 | } | ||
| 70 | |||
| 71 | MODULE_DEVICE_TABLE(pci, mt76pci_device_table); | ||
| 72 | MODULE_FIRMWARE(MT7603_FIRMWARE_E1); | ||
| 73 | MODULE_FIRMWARE(MT7603_FIRMWARE_E2); | ||
| 74 | |||
| 75 | struct pci_driver mt7603_pci_driver = { | ||
| 76 | .name = KBUILD_MODNAME, | ||
| 77 | .id_table = mt76pci_device_table, | ||
| 78 | .probe = mt76pci_probe, | ||
| 79 | .remove = mt76pci_remove, | ||
| 80 | }; | ||
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/regs.h b/drivers/net/wireless/mediatek/mt76/mt7603/regs.h new file mode 100644 index 000000000000..da6827ae6cee --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7603/regs.h | |||
| @@ -0,0 +1,774 @@ | |||
| 1 | /* SPDX-License-Identifier: ISC */ | ||
| 2 | |||
| 3 | #ifndef __MT7603_REGS_H | ||
| 4 | #define __MT7603_REGS_H | ||
| 5 | |||
| 6 | #define MT_HW_REV 0x1000 | ||
| 7 | #define MT_HW_CHIPID 0x1008 | ||
| 8 | #define MT_TOP_MISC2 0x1134 | ||
| 9 | |||
| 10 | #define MT_MCU_BASE 0x2000 | ||
| 11 | #define MT_MCU(ofs) (MT_MCU_BASE + (ofs)) | ||
| 12 | |||
| 13 | #define MT_MCU_PCIE_REMAP_1 MT_MCU(0x500) | ||
| 14 | #define MT_MCU_PCIE_REMAP_1_OFFSET GENMASK(17, 0) | ||
| 15 | #define MT_MCU_PCIE_REMAP_1_BASE GENMASK(31, 18) | ||
| 16 | |||
| 17 | #define MT_MCU_PCIE_REMAP_2 MT_MCU(0x504) | ||
| 18 | #define MT_MCU_PCIE_REMAP_2_OFFSET GENMASK(18, 0) | ||
| 19 | #define MT_MCU_PCIE_REMAP_2_BASE GENMASK(31, 19) | ||
| 20 | |||
| 21 | #define MT_HIF_BASE 0x4000 | ||
| 22 | #define MT_HIF(ofs) (MT_HIF_BASE + (ofs)) | ||
| 23 | |||
| 24 | #define MT_INT_SOURCE_CSR MT_HIF(0x200) | ||
| 25 | #define MT_INT_MASK_CSR MT_HIF(0x204) | ||
| 26 | #define MT_DELAY_INT_CFG MT_HIF(0x210) | ||
| 27 | |||
| 28 | #define MT_INT_RX_DONE(_n) BIT(_n) | ||
| 29 | #define MT_INT_RX_DONE_ALL GENMASK(1, 0) | ||
| 30 | #define MT_INT_TX_DONE_ALL GENMASK(19, 4) | ||
| 31 | #define MT_INT_TX_DONE(_n) BIT((_n) + 4) | ||
| 32 | |||
| 33 | #define MT_INT_RX_COHERENT BIT(20) | ||
| 34 | #define MT_INT_TX_COHERENT BIT(21) | ||
| 35 | #define MT_INT_MAC_IRQ3 BIT(27) | ||
| 36 | |||
| 37 | #define MT_INT_MCU_CMD BIT(30) | ||
| 38 | |||
| 39 | #define MT_WPDMA_GLO_CFG MT_HIF(0x208) | ||
| 40 | #define MT_WPDMA_GLO_CFG_TX_DMA_EN BIT(0) | ||
| 41 | #define MT_WPDMA_GLO_CFG_TX_DMA_BUSY BIT(1) | ||
| 42 | #define MT_WPDMA_GLO_CFG_RX_DMA_EN BIT(2) | ||
| 43 | #define MT_WPDMA_GLO_CFG_RX_DMA_BUSY BIT(3) | ||
| 44 | #define MT_WPDMA_GLO_CFG_DMA_BURST_SIZE GENMASK(5, 4) | ||
| 45 | #define MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE BIT(6) | ||
| 46 | #define MT_WPDMA_GLO_CFG_BIG_ENDIAN BIT(7) | ||
| 47 | #define MT_WPDMA_GLO_CFG_HDR_SEG_LEN GENMASK(15, 8) | ||
| 48 | #define MT_WPDMA_GLO_CFG_SW_RESET BIT(24) | ||
| 49 | #define MT_WPDMA_GLO_CFG_FORCE_TX_EOF BIT(25) | ||
| 50 | #define MT_WPDMA_GLO_CFG_CLK_GATE_DIS BIT(30) | ||
| 51 | #define MT_WPDMA_GLO_CFG_RX_2B_OFFSET BIT(31) | ||
| 52 | |||
| 53 | #define MT_WPDMA_RST_IDX MT_HIF(0x20c) | ||
| 54 | |||
| 55 | #define MT_WPDMA_DEBUG MT_HIF(0x244) | ||
| 56 | #define MT_WPDMA_DEBUG_VALUE GENMASK(17, 0) | ||
| 57 | #define MT_WPDMA_DEBUG_SEL BIT(27) | ||
| 58 | #define MT_WPDMA_DEBUG_IDX GENMASK(31, 28) | ||
| 59 | |||
| 60 | #define MT_TX_RING_BASE MT_HIF(0x300) | ||
| 61 | #define MT_RX_RING_BASE MT_HIF(0x400) | ||
| 62 | |||
| 63 | #define MT_TXTIME_THRESH_BASE MT_HIF(0x500) | ||
| 64 | #define MT_TXTIME_THRESH(n) (MT_TXTIME_THRESH_BASE + ((n) * 4)) | ||
| 65 | |||
| 66 | #define MT_PAGE_COUNT_BASE MT_HIF(0x540) | ||
| 67 | #define MT_PAGE_COUNT(n) (MT_PAGE_COUNT_BASE + ((n) * 4)) | ||
| 68 | |||
| 69 | #define MT_SCH_1 MT_HIF(0x588) | ||
| 70 | #define MT_SCH_2 MT_HIF(0x58c) | ||
| 71 | #define MT_SCH_3 MT_HIF(0x590) | ||
| 72 | |||
| 73 | #define MT_SCH_4 MT_HIF(0x594) | ||
| 74 | #define MT_SCH_4_FORCE_QID GENMASK(4, 0) | ||
| 75 | #define MT_SCH_4_BYPASS BIT(5) | ||
| 76 | #define MT_SCH_4_RESET BIT(8) | ||
| 77 | |||
| 78 | #define MT_GROUP_THRESH_BASE MT_HIF(0x598) | ||
| 79 | #define MT_GROUP_THRESH(n) (MT_GROUP_THRESH_BASE + ((n) * 4)) | ||
| 80 | |||
| 81 | #define MT_QUEUE_PRIORITY_1 MT_HIF(0x580) | ||
| 82 | #define MT_QUEUE_PRIORITY_2 MT_HIF(0x584) | ||
| 83 | |||
| 84 | #define MT_BMAP_0 MT_HIF(0x5b0) | ||
| 85 | #define MT_BMAP_1 MT_HIF(0x5b4) | ||
| 86 | #define MT_BMAP_2 MT_HIF(0x5b8) | ||
| 87 | |||
| 88 | #define MT_HIGH_PRIORITY_1 MT_HIF(0x5bc) | ||
| 89 | #define MT_HIGH_PRIORITY_2 MT_HIF(0x5c0) | ||
| 90 | |||
| 91 | #define MT_PRIORITY_MASK MT_HIF(0x5c4) | ||
| 92 | |||
| 93 | #define MT_RSV_MAX_THRESH MT_HIF(0x5c8) | ||
| 94 | |||
| 95 | #define MT_PSE_BASE 0x8000 | ||
| 96 | #define MT_PSE(ofs) (MT_PSE_BASE + (ofs)) | ||
| 97 | |||
| 98 | #define MT_MCU_DEBUG_RESET MT_PSE(0x16c) | ||
| 99 | #define MT_MCU_DEBUG_RESET_PSE BIT(0) | ||
| 100 | #define MT_MCU_DEBUG_RESET_PSE_S BIT(1) | ||
| 101 | #define MT_MCU_DEBUG_RESET_QUEUES GENMASK(6, 2) | ||
| 102 | |||
| 103 | #define MT_PSE_FC_P0 MT_PSE(0x120) | ||
| 104 | #define MT_PSE_FC_P0_MIN_RESERVE GENMASK(11, 0) | ||
| 105 | #define MT_PSE_FC_P0_MAX_QUOTA GENMASK(27, 16) | ||
| 106 | |||
| 107 | #define MT_PSE_FRP MT_PSE(0x138) | ||
| 108 | #define MT_PSE_FRP_P0 GENMASK(2, 0) | ||
| 109 | #define MT_PSE_FRP_P1 GENMASK(5, 3) | ||
| 110 | #define MT_PSE_FRP_P2_RQ0 GENMASK(8, 6) | ||
| 111 | #define MT_PSE_FRP_P2_RQ1 GENMASK(11, 9) | ||
| 112 | #define MT_PSE_FRP_P2_RQ2 GENMASK(14, 12) | ||
| 113 | |||
| 114 | #define MT_FC_RSV_COUNT_0 MT_PSE(0x13c) | ||
| 115 | #define MT_FC_RSV_COUNT_0_P0 GENMASK(11, 0) | ||
| 116 | #define MT_FC_RSV_COUNT_0_P1 GENMASK(27, 16) | ||
| 117 | |||
| 118 | #define MT_FC_SP2_Q0Q1 MT_PSE(0x14c) | ||
| 119 | #define MT_FC_SP2_Q0Q1_SRC_COUNT_Q0 GENMASK(11, 0) | ||
| 120 | #define MT_FC_SP2_Q0Q1_SRC_COUNT_Q1 GENMASK(27, 16) | ||
| 121 | |||
| 122 | #define MT_PSE_FW_SHARED MT_PSE(0x17c) | ||
| 123 | |||
| 124 | #define MT_PSE_RTA MT_PSE(0x194) | ||
| 125 | #define MT_PSE_RTA_QUEUE_ID GENMASK(4, 0) | ||
| 126 | #define MT_PSE_RTA_PORT_ID GENMASK(6, 5) | ||
| 127 | #define MT_PSE_RTA_REDIRECT_EN BIT(7) | ||
| 128 | #define MT_PSE_RTA_TAG_ID GENMASK(15, 8) | ||
| 129 | #define MT_PSE_RTA_WRITE BIT(16) | ||
| 130 | #define MT_PSE_RTA_BUSY BIT(31) | ||
| 131 | |||
| 132 | #define MT_WF_PHY_BASE 0x10000 | ||
| 133 | #define MT_WF_PHY_OFFSET 0x1000 | ||
| 134 | #define MT_WF_PHY(ofs) (MT_WF_PHY_BASE + (ofs)) | ||
| 135 | |||
| 136 | #define MT_AGC_BASE MT_WF_PHY(0x500) | ||
| 137 | #define MT_AGC(n) (MT_AGC_BASE + ((n) * 4)) | ||
| 138 | |||
| 139 | #define MT_AGC1_BASE MT_WF_PHY(0x1500) | ||
| 140 | #define MT_AGC1(n) (MT_AGC1_BASE + ((n) * 4)) | ||
| 141 | |||
| 142 | #define MT_AGC_41_RSSI_0 GENMASK(23, 16) | ||
| 143 | #define MT_AGC_41_RSSI_1 GENMASK(7, 0) | ||
| 144 | |||
| 145 | #define MT_RXTD_BASE MT_WF_PHY(0x600) | ||
| 146 | #define MT_RXTD(n) (MT_RXTD_BASE + ((n) * 4)) | ||
| 147 | |||
| 148 | #define MT_RXTD_6_ACI_TH GENMASK(4, 0) | ||
| 149 | #define MT_RXTD_6_CCAED_TH GENMASK(14, 8) | ||
| 150 | |||
| 151 | #define MT_RXTD_8_LOWER_SIGNAL GENMASK(5, 0) | ||
| 152 | |||
| 153 | #define MT_RXTD_13_ACI_TH_EN BIT(0) | ||
| 154 | |||
| 155 | #define MT_WF_PHY_CR_TSSI_BASE MT_WF_PHY(0xd00) | ||
| 156 | #define MT_WF_PHY_CR_TSSI(phy, n) (MT_WF_PHY_CR_TSSI_BASE + \ | ||
| 157 | ((phy) * MT_WF_PHY_OFFSET) + \ | ||
| 158 | ((n) * 4)) | ||
| 159 | |||
| 160 | #define MT_PHYCTRL_BASE MT_WF_PHY(0x4100) | ||
| 161 | #define MT_PHYCTRL(n) (MT_PHYCTRL_BASE + ((n) * 4)) | ||
| 162 | |||
| 163 | #define MT_PHYCTRL_2_STATUS_RESET BIT(6) | ||
| 164 | #define MT_PHYCTRL_2_STATUS_EN BIT(7) | ||
| 165 | |||
| 166 | #define MT_PHYCTRL_STAT_PD MT_PHYCTRL(3) | ||
| 167 | #define MT_PHYCTRL_STAT_PD_OFDM GENMASK(31, 16) | ||
| 168 | #define MT_PHYCTRL_STAT_PD_CCK GENMASK(15, 0) | ||
| 169 | |||
| 170 | #define MT_PHYCTRL_STAT_MDRDY MT_PHYCTRL(8) | ||
| 171 | #define MT_PHYCTRL_STAT_MDRDY_OFDM GENMASK(31, 16) | ||
| 172 | #define MT_PHYCTRL_STAT_MDRDY_CCK GENMASK(15, 0) | ||
| 173 | |||
| 174 | #define MT_WF_AGG_BASE 0x21200 | ||
| 175 | #define MT_WF_AGG(ofs) (MT_WF_AGG_BASE + (ofs)) | ||
| 176 | |||
| 177 | #define MT_AGG_ARCR MT_WF_AGG(0x010) | ||
| 178 | #define MT_AGG_ARCR_INIT_RATE1 BIT(0) | ||
| 179 | #define MT_AGG_ARCR_FB_SGI_DISABLE BIT(1) | ||
| 180 | #define MT_AGG_ARCR_RATE8_DOWN_WRAP BIT(2) | ||
| 181 | #define MT_AGG_ARCR_RTS_RATE_THR GENMASK(12, 8) | ||
| 182 | #define MT_AGG_ARCR_RATE_DOWN_RATIO GENMASK(17, 16) | ||
| 183 | #define MT_AGG_ARCR_RATE_DOWN_RATIO_EN BIT(19) | ||
| 184 | #define MT_AGG_ARCR_RATE_UP_EXTRA_TH GENMASK(22, 20) | ||
| 185 | #define MT_AGG_ARCR_SPE_DIS_TH GENMASK(27, 24) | ||
| 186 | |||
| 187 | #define MT_AGG_ARUCR MT_WF_AGG(0x014) | ||
| 188 | #define MT_AGG_ARDCR MT_WF_AGG(0x018) | ||
| 189 | #define MT_AGG_ARxCR_LIMIT_SHIFT(_n) (4 * (_n)) | ||
| 190 | #define MT_AGG_ARxCR_LIMIT(_n) GENMASK(2 + \ | ||
| 191 | MT_AGG_ARxCR_LIMIT_SHIFT(_n), \ | ||
| 192 | MT_AGG_ARxCR_LIMIT_SHIFT(_n)) | ||
| 193 | |||
| 194 | #define MT_AGG_LIMIT MT_WF_AGG(0x040) | ||
| 195 | #define MT_AGG_LIMIT_1 MT_WF_AGG(0x044) | ||
| 196 | #define MT_AGG_LIMIT_AC(_n) GENMASK(((_n) + 1) * 8 - 1, (_n) * 8) | ||
| 197 | |||
| 198 | #define MT_AGG_BA_SIZE_LIMIT_0 MT_WF_AGG(0x048) | ||
| 199 | #define MT_AGG_BA_SIZE_LIMIT_1 MT_WF_AGG(0x04c) | ||
| 200 | #define MT_AGG_BA_SIZE_LIMIT_SHIFT 8 | ||
| 201 | |||
| 202 | #define MT_AGG_PCR MT_WF_AGG(0x050) | ||
| 203 | #define MT_AGG_PCR_MM BIT(16) | ||
| 204 | #define MT_AGG_PCR_GF BIT(17) | ||
| 205 | #define MT_AGG_PCR_BW40 BIT(18) | ||
| 206 | #define MT_AGG_PCR_RIFS BIT(19) | ||
| 207 | #define MT_AGG_PCR_BW80 BIT(20) | ||
| 208 | #define MT_AGG_PCR_BW160 BIT(21) | ||
| 209 | #define MT_AGG_PCR_ERP BIT(22) | ||
| 210 | |||
| 211 | #define MT_AGG_PCR_RTS MT_WF_AGG(0x054) | ||
| 212 | #define MT_AGG_PCR_RTS_THR GENMASK(19, 0) | ||
| 213 | #define MT_AGG_PCR_RTS_PKT_THR GENMASK(31, 25) | ||
| 214 | |||
| 215 | #define MT_AGG_CONTROL MT_WF_AGG(0x070) | ||
| 216 | #define MT_AGG_CONTROL_NO_BA_RULE BIT(0) | ||
| 217 | #define MT_AGG_CONTROL_NO_BA_AR_RULE BIT(1) | ||
| 218 | #define MT_AGG_CONTROL_CFEND_SPE_EN BIT(3) | ||
| 219 | #define MT_AGG_CONTROL_CFEND_RATE GENMASK(15, 4) | ||
| 220 | #define MT_AGG_CONTROL_BAR_SPE_EN BIT(19) | ||
| 221 | #define MT_AGG_CONTROL_BAR_RATE GENMASK(31, 20) | ||
| 222 | |||
| 223 | #define MT_AGG_TMP MT_WF_AGG(0x0d8) | ||
| 224 | |||
| 225 | #define MT_AGG_BWCR MT_WF_AGG(0x0ec) | ||
| 226 | #define MT_AGG_BWCR_BW GENMASK(3, 2) | ||
| 227 | |||
| 228 | #define MT_AGG_RETRY_CONTROL MT_WF_AGG(0x0f4) | ||
| 229 | #define MT_AGG_RETRY_CONTROL_RTS_LIMIT GENMASK(11, 7) | ||
| 230 | #define MT_AGG_RETRY_CONTROL_BAR_LIMIT GENMASK(15, 12) | ||
| 231 | |||
| 232 | #define MT_WF_DMA_BASE 0x21c00 | ||
| 233 | #define MT_WF_DMA(ofs) (MT_WF_DMA_BASE + (ofs)) | ||
| 234 | |||
| 235 | #define MT_DMA_DCR0 MT_WF_DMA(0x000) | ||
| 236 | #define MT_DMA_DCR1 MT_WF_DMA(0x004) | ||
| 237 | |||
| 238 | #define MT_DMA_FQCR0 MT_WF_DMA(0x008) | ||
| 239 | #define MT_DMA_FQCR0_TARGET_WCID GENMASK(7, 0) | ||
| 240 | #define MT_DMA_FQCR0_TARGET_BSS GENMASK(13, 8) | ||
| 241 | #define MT_DMA_FQCR0_TARGET_QID GENMASK(20, 16) | ||
| 242 | #define MT_DMA_FQCR0_DEST_PORT_ID GENMASK(23, 22) | ||
| 243 | #define MT_DMA_FQCR0_DEST_QUEUE_ID GENMASK(28, 24) | ||
| 244 | #define MT_DMA_FQCR0_MODE BIT(29) | ||
| 245 | #define MT_DMA_FQCR0_STATUS BIT(30) | ||
| 246 | #define MT_DMA_FQCR0_BUSY BIT(31) | ||
| 247 | |||
| 248 | #define MT_DMA_RCFR0 MT_WF_DMA(0x070) | ||
| 249 | #define MT_DMA_VCFR0 MT_WF_DMA(0x07c) | ||
| 250 | |||
| 251 | #define MT_DMA_TCFR0 MT_WF_DMA(0x080) | ||
| 252 | #define MT_DMA_TCFR1 MT_WF_DMA(0x084) | ||
| 253 | #define MT_DMA_TCFR_TXS_AGGR_TIMEOUT GENMASK(27, 16) | ||
| 254 | #define MT_DMA_TCFR_TXS_QUEUE BIT(14) | ||
| 255 | #define MT_DMA_TCFR_TXS_AGGR_COUNT GENMASK(12, 8) | ||
| 256 | #define MT_DMA_TCFR_TXS_BIT_MAP GENMASK(6, 0) | ||
| 257 | |||
| 258 | #define MT_DMA_TMCFR0 MT_WF_DMA(0x088) | ||
| 259 | |||
| 260 | #define MT_WF_ARB_BASE 0x21400 | ||
| 261 | #define MT_WF_ARB(ofs) (MT_WF_ARB_BASE + (ofs)) | ||
| 262 | |||
| 263 | #define MT_WMM_AIFSN MT_WF_ARB(0x020) | ||
| 264 | #define MT_WMM_AIFSN_MASK GENMASK(3, 0) | ||
| 265 | #define MT_WMM_AIFSN_SHIFT(_n) ((_n) * 4) | ||
| 266 | |||
| 267 | #define MT_WMM_CWMAX_BASE MT_WF_ARB(0x028) | ||
| 268 | #define MT_WMM_CWMAX(_n) (MT_WMM_CWMAX_BASE + (((_n) / 2) << 2)) | ||
| 269 | #define MT_WMM_CWMAX_SHIFT(_n) (((_n) & 1) * 16) | ||
| 270 | #define MT_WMM_CWMAX_MASK GENMASK(15, 0) | ||
| 271 | |||
| 272 | #define MT_WMM_CWMIN MT_WF_ARB(0x040) | ||
| 273 | #define MT_WMM_CWMIN_MASK GENMASK(7, 0) | ||
| 274 | #define MT_WMM_CWMIN_SHIFT(_n) ((_n) * 8) | ||
| 275 | |||
| 276 | #define MT_WF_ARB_RQCR MT_WF_ARB(0x070) | ||
| 277 | #define MT_WF_ARB_RQCR_RX_START BIT(0) | ||
| 278 | #define MT_WF_ARB_RQCR_RXV_START BIT(4) | ||
| 279 | #define MT_WF_ARB_RQCR_RXV_R_EN BIT(7) | ||
| 280 | #define MT_WF_ARB_RQCR_RXV_T_EN BIT(8) | ||
| 281 | |||
| 282 | #define MT_ARB_SCR MT_WF_ARB(0x080) | ||
| 283 | #define MT_ARB_SCR_BCNQ_OPMODE_MASK GENMASK(1, 0) | ||
| 284 | #define MT_ARB_SCR_BCNQ_OPMODE_SHIFT(n) ((n) * 2) | ||
| 285 | #define MT_ARB_SCR_TX_DISABLE BIT(8) | ||
| 286 | #define MT_ARB_SCR_RX_DISABLE BIT(9) | ||
| 287 | #define MT_ARB_SCR_BCNQ_EMPTY_SKIP BIT(28) | ||
| 288 | #define MT_ARB_SCR_TTTT_BTIM_PRIO BIT(29) | ||
| 289 | #define MT_ARB_SCR_TBTT_BCN_PRIO BIT(30) | ||
| 290 | #define MT_ARB_SCR_TBTT_BCAST_PRIO BIT(31) | ||
| 291 | |||
| 292 | enum { | ||
| 293 | MT_BCNQ_OPMODE_STA = 0, | ||
| 294 | MT_BCNQ_OPMODE_AP = 1, | ||
| 295 | MT_BCNQ_OPMODE_ADHOC = 2, | ||
| 296 | }; | ||
| 297 | |||
| 298 | #define MT_WF_ARB_TX_START_0 MT_WF_ARB(0x100) | ||
| 299 | #define MT_WF_ARB_TX_START_1 MT_WF_ARB(0x104) | ||
| 300 | #define MT_WF_ARB_TX_FLUSH_0 MT_WF_ARB(0x108) | ||
| 301 | #define MT_WF_ARB_TX_FLUSH_1 MT_WF_ARB(0x10c) | ||
| 302 | #define MT_WF_ARB_TX_STOP_0 MT_WF_ARB(0x110) | ||
| 303 | #define MT_WF_ARB_TX_STOP_1 MT_WF_ARB(0x114) | ||
| 304 | |||
| 305 | #define MT_WF_ARB_BCN_START MT_WF_ARB(0x118) | ||
| 306 | #define MT_WF_ARB_BCN_START_BSSn(n) BIT(0 + (n)) | ||
| 307 | #define MT_WF_ARB_BCN_START_T_PRE_TTTT BIT(10) | ||
| 308 | #define MT_WF_ARB_BCN_START_T_TTTT BIT(11) | ||
| 309 | #define MT_WF_ARB_BCN_START_T_PRE_TBTT BIT(12) | ||
| 310 | #define MT_WF_ARB_BCN_START_T_TBTT BIT(13) | ||
| 311 | #define MT_WF_ARB_BCN_START_T_SLOT_IDLE BIT(14) | ||
| 312 | #define MT_WF_ARB_BCN_START_T_TX_START BIT(15) | ||
| 313 | #define MT_WF_ARB_BCN_START_BSS0n(n) BIT((n) ? 16 + ((n) - 1) : 0) | ||
| 314 | |||
| 315 | #define MT_WF_ARB_BCN_FLUSH MT_WF_ARB(0x11c) | ||
| 316 | #define MT_WF_ARB_BCN_FLUSH_BSSn(n) BIT(0 + (n)) | ||
| 317 | #define MT_WF_ARB_BCN_FLUSH_BSS0n(n) BIT((n) ? 16 + ((n) - 1) : 0) | ||
| 318 | |||
| 319 | #define MT_WF_ARB_CAB_START MT_WF_ARB(0x120) | ||
| 320 | #define MT_WF_ARB_CAB_START_BSSn(n) BIT(0 + (n)) | ||
| 321 | #define MT_WF_ARB_CAB_START_BSS0n(n) BIT((n) ? 16 + ((n) - 1) : 0) | ||
| 322 | |||
| 323 | #define MT_WF_ARB_CAB_FLUSH MT_WF_ARB(0x124) | ||
| 324 | #define MT_WF_ARB_CAB_FLUSH_BSSn(n) BIT(0 + (n)) | ||
| 325 | #define MT_WF_ARB_CAB_FLUSH_BSS0n(n) BIT((n) ? 16 + ((n) - 1) : 0) | ||
| 326 | |||
| 327 | #define MT_WF_ARB_CAB_COUNT(n) MT_WF_ARB(0x128 + (n) * 4) | ||
| 328 | #define MT_WF_ARB_CAB_COUNT_SHIFT 4 | ||
| 329 | #define MT_WF_ARB_CAB_COUNT_MASK GENMASK(3, 0) | ||
| 330 | #define MT_WF_ARB_CAB_COUNT_B0_REG(n) MT_WF_ARB_CAB_COUNT(((n) > 12 ? 2 : \ | ||
| 331 | ((n) > 4 ? 1 : 0))) | ||
| 332 | #define MT_WF_ARB_CAB_COUNT_B0_SHIFT(n) (((n) > 12 ? (n) - 12 : \ | ||
| 333 | ((n) > 4 ? (n) - 4 : \ | ||
| 334 | (n) ? (n) + 3 : 0)) * 4) | ||
| 335 | |||
| 336 | #define MT_TX_ABORT MT_WF_ARB(0x134) | ||
| 337 | #define MT_TX_ABORT_EN BIT(0) | ||
| 338 | #define MT_TX_ABORT_WCID GENMASK(15, 8) | ||
| 339 | |||
| 340 | #define MT_WF_TMAC_BASE 0x21600 | ||
| 341 | #define MT_WF_TMAC(ofs) (MT_WF_TMAC_BASE + (ofs)) | ||
| 342 | |||
| 343 | #define MT_TMAC_TCR MT_WF_TMAC(0x000) | ||
| 344 | #define MT_TMAC_TCR_BLINK_SEL GENMASK(7, 6) | ||
| 345 | #define MT_TMAC_TCR_PRE_RTS_GUARD GENMASK(11, 8) | ||
| 346 | #define MT_TMAC_TCR_PRE_RTS_SEC_IDLE GENMASK(13, 12) | ||
| 347 | #define MT_TMAC_TCR_RTS_SIGTA BIT(14) | ||
| 348 | #define MT_TMAC_TCR_LDPC_OFS BIT(15) | ||
| 349 | #define MT_TMAC_TCR_TX_STREAMS GENMASK(17, 16) | ||
| 350 | #define MT_TMAC_TCR_SCH_IDLE_SEL GENMASK(19, 18) | ||
| 351 | #define MT_TMAC_TCR_SCH_DET_PER_IOD BIT(20) | ||
| 352 | #define MT_TMAC_TCR_DCH_DET_DISABLE BIT(21) | ||
| 353 | #define MT_TMAC_TCR_TX_RIFS BIT(22) | ||
| 354 | #define MT_TMAC_TCR_RX_RIFS_MODE BIT(23) | ||
| 355 | #define MT_TMAC_TCR_TXOP_TBTT_CTL BIT(24) | ||
| 356 | #define MT_TMAC_TCR_TBTT_TX_STOP_CTL BIT(25) | ||
| 357 | #define MT_TMAC_TCR_TXOP_BURST_STOP BIT(26) | ||
| 358 | #define MT_TMAC_TCR_RDG_RA_MODE BIT(27) | ||
| 359 | #define MT_TMAC_TCR_RDG_RESP BIT(29) | ||
| 360 | #define MT_TMAC_TCR_RDG_NO_PENDING BIT(30) | ||
| 361 | #define MT_TMAC_TCR_SMOOTHING BIT(31) | ||
| 362 | |||
| 363 | #define MT_WMM_TXOP_BASE MT_WF_TMAC(0x010) | ||
| 364 | #define MT_WMM_TXOP(_n) (MT_WMM_TXOP_BASE + \ | ||
| 365 | ((((_n) / 2) ^ 0x1) << 2)) | ||
| 366 | #define MT_WMM_TXOP_SHIFT(_n) (((_n) & 1) * 16) | ||
| 367 | #define MT_WMM_TXOP_MASK GENMASK(15, 0) | ||
| 368 | |||
| 369 | #define MT_TIMEOUT_CCK MT_WF_TMAC(0x090) | ||
| 370 | #define MT_TIMEOUT_OFDM MT_WF_TMAC(0x094) | ||
| 371 | #define MT_TIMEOUT_VAL_PLCP GENMASK(15, 0) | ||
| 372 | #define MT_TIMEOUT_VAL_CCA GENMASK(31, 16) | ||
| 373 | |||
| 374 | #define MT_TXREQ MT_WF_TMAC(0x09c) | ||
| 375 | #define MT_TXREQ_CCA_SRC_SEL GENMASK(31, 30) | ||
| 376 | |||
| 377 | #define MT_RXREQ MT_WF_TMAC(0x0a0) | ||
| 378 | #define MT_RXREQ_DELAY GENMASK(8, 0) | ||
| 379 | |||
| 380 | #define MT_IFS MT_WF_TMAC(0x0a4) | ||
| 381 | #define MT_IFS_EIFS GENMASK(8, 0) | ||
| 382 | #define MT_IFS_RIFS GENMASK(14, 10) | ||
| 383 | #define MT_IFS_SIFS GENMASK(22, 16) | ||
| 384 | #define MT_IFS_SLOT GENMASK(30, 24) | ||
| 385 | |||
| 386 | #define MT_TMAC_PCR MT_WF_TMAC(0x0b4) | ||
| 387 | #define MT_TMAC_PCR_RATE GENMASK(8, 0) | ||
| 388 | #define MT_TMAC_PCR_RATE_FIXED BIT(15) | ||
| 389 | #define MT_TMAC_PCR_ANT_ID GENMASK(21, 16) | ||
| 390 | #define MT_TMAC_PCR_ANT_ID_SEL BIT(22) | ||
| 391 | #define MT_TMAC_PCR_SPE_EN BIT(23) | ||
| 392 | #define MT_TMAC_PCR_ANT_PRI GENMASK(26, 24) | ||
| 393 | #define MT_TMAC_PCR_ANT_PRI_SEL GENMASK(27) | ||
| 394 | |||
| 395 | #define MT_WF_RMAC_BASE 0x21800 | ||
| 396 | #define MT_WF_RMAC(ofs) (MT_WF_RMAC_BASE + (ofs)) | ||
| 397 | |||
| 398 | #define MT_WF_RFCR MT_WF_RMAC(0x000) | ||
| 399 | #define MT_WF_RFCR_DROP_STBC_MULTI BIT(0) | ||
| 400 | #define MT_WF_RFCR_DROP_FCSFAIL BIT(1) | ||
| 401 | #define MT_WF_RFCR_DROP_VERSION BIT(3) | ||
| 402 | #define MT_WF_RFCR_DROP_PROBEREQ BIT(4) | ||
| 403 | #define MT_WF_RFCR_DROP_MCAST BIT(5) | ||
| 404 | #define MT_WF_RFCR_DROP_BCAST BIT(6) | ||
| 405 | #define MT_WF_RFCR_DROP_MCAST_FILTERED BIT(7) | ||
| 406 | #define MT_WF_RFCR_DROP_A3_MAC BIT(8) | ||
| 407 | #define MT_WF_RFCR_DROP_A3_BSSID BIT(9) | ||
| 408 | #define MT_WF_RFCR_DROP_A2_BSSID BIT(10) | ||
| 409 | #define MT_WF_RFCR_DROP_OTHER_BEACON BIT(11) | ||
| 410 | #define MT_WF_RFCR_DROP_FRAME_REPORT BIT(12) | ||
| 411 | #define MT_WF_RFCR_DROP_CTL_RSV BIT(13) | ||
| 412 | #define MT_WF_RFCR_DROP_CTS BIT(14) | ||
| 413 | #define MT_WF_RFCR_DROP_RTS BIT(15) | ||
| 414 | #define MT_WF_RFCR_DROP_DUPLICATE BIT(16) | ||
| 415 | #define MT_WF_RFCR_DROP_OTHER_BSS BIT(17) | ||
| 416 | #define MT_WF_RFCR_DROP_OTHER_UC BIT(18) | ||
| 417 | #define MT_WF_RFCR_DROP_OTHER_TIM BIT(19) | ||
| 418 | #define MT_WF_RFCR_DROP_NDPA BIT(20) | ||
| 419 | #define MT_WF_RFCR_DROP_UNWANTED_CTL BIT(21) | ||
| 420 | |||
| 421 | #define MT_BSSID0(idx) MT_WF_RMAC(0x004 + (idx) * 8) | ||
| 422 | #define MT_BSSID1(idx) MT_WF_RMAC(0x008 + (idx) * 8) | ||
| 423 | #define MT_BSSID1_VALID BIT(16) | ||
| 424 | |||
| 425 | #define MT_MAC_ADDR0(idx) MT_WF_RMAC(0x024 + (idx) * 8) | ||
| 426 | #define MT_MAC_ADDR1(idx) MT_WF_RMAC(0x028 + (idx) * 8) | ||
| 427 | #define MT_MAC_ADDR1_ADDR GENMASK(15, 0) | ||
| 428 | #define MT_MAC_ADDR1_VALID BIT(16) | ||
| 429 | |||
| 430 | #define MT_BA_CONTROL_0 MT_WF_RMAC(0x068) | ||
| 431 | #define MT_BA_CONTROL_1 MT_WF_RMAC(0x06c) | ||
| 432 | #define MT_BA_CONTROL_1_ADDR GENMASK(15, 0) | ||
| 433 | #define MT_BA_CONTROL_1_TID GENMASK(19, 16) | ||
| 434 | #define MT_BA_CONTROL_1_IGNORE_TID BIT(20) | ||
| 435 | #define MT_BA_CONTROL_1_IGNORE_ALL BIT(21) | ||
| 436 | #define MT_BA_CONTROL_1_RESET BIT(22) | ||
| 437 | |||
| 438 | #define MT_WF_RMACDR MT_WF_RMAC(0x078) | ||
| 439 | #define MT_WF_RMACDR_TSF_PROBERSP_DIS BIT(0) | ||
| 440 | #define MT_WF_RMACDR_TSF_TIM BIT(4) | ||
| 441 | #define MT_WF_RMACDR_MBSSID_MASK GENMASK(25, 24) | ||
| 442 | #define MT_WF_RMACDR_CHECK_HTC_BY_RATE BIT(26) | ||
| 443 | #define MT_WF_RMACDR_MAXLEN_20BIT BIT(30) | ||
| 444 | |||
| 445 | #define MT_WF_RMAC_RMCR MT_WF_RMAC(0x080) | ||
| 446 | #define MT_WF_RMAC_RMCR_SMPS_MODE GENMASK(21, 20) | ||
| 447 | #define MT_WF_RMAC_RMCR_RX_STREAMS GENMASK(24, 22) | ||
| 448 | #define MT_WF_RMAC_RMCR_SMPS_RTS BIT(25) | ||
| 449 | |||
| 450 | #define MT_WF_RMAC_CH_FREQ MT_WF_RMAC(0x090) | ||
| 451 | #define MT_WF_RMAC_MAXMINLEN MT_WF_RMAC(0x098) | ||
| 452 | #define MT_WF_RFCR1 MT_WF_RMAC(0x0a4) | ||
| 453 | #define MT_WF_RMAC_TMR_PA MT_WF_RMAC(0x0e0) | ||
| 454 | |||
| 455 | #define MT_WF_SEC_BASE 0x21a00 | ||
| 456 | #define MT_WF_SEC(ofs) (MT_WF_SEC_BASE + (ofs)) | ||
| 457 | |||
| 458 | #define MT_SEC_SCR MT_WF_SEC(0x004) | ||
| 459 | #define MT_SEC_SCR_MASK_ORDER GENMASK(1, 0) | ||
| 460 | |||
| 461 | #define MT_WTBL_OFF_BASE 0x23000 | ||
| 462 | #define MT_WTBL_OFF(n) (MT_WTBL_OFF_BASE + (n)) | ||
| 463 | |||
| 464 | #define MT_WTBL_UPDATE MT_WTBL_OFF(0x000) | ||
| 465 | #define MT_WTBL_UPDATE_WLAN_IDX GENMASK(7, 0) | ||
| 466 | #define MT_WTBL_UPDATE_WTBL2 BIT(11) | ||
| 467 | #define MT_WTBL_UPDATE_ADM_COUNT_CLEAR BIT(12) | ||
| 468 | #define MT_WTBL_UPDATE_RATE_UPDATE BIT(13) | ||
| 469 | #define MT_WTBL_UPDATE_TX_COUNT_CLEAR BIT(14) | ||
| 470 | #define MT_WTBL_UPDATE_RX_COUNT_CLEAR BIT(15) | ||
| 471 | #define MT_WTBL_UPDATE_BUSY BIT(16) | ||
| 472 | |||
| 473 | #define MT_WTBL_RMVTCR MT_WTBL_OFF(0x008) | ||
| 474 | #define MT_WTBL_RMVTCR_RX_MV_MODE BIT(23) | ||
| 475 | |||
| 476 | #define MT_LPON_BASE 0x24000 | ||
| 477 | #define MT_LPON(n) (MT_LPON_BASE + (n)) | ||
| 478 | |||
| 479 | #define MT_LPON_BTEIR MT_LPON(0x020) | ||
| 480 | #define MT_LPON_BTEIR_MBSS_MODE GENMASK(31, 29) | ||
| 481 | |||
| 482 | #define MT_PRE_TBTT MT_LPON(0x030) | ||
| 483 | #define MT_PRE_TBTT_MASK GENMASK(7, 0) | ||
| 484 | #define MT_PRE_TBTT_SHIFT 8 | ||
| 485 | |||
| 486 | #define MT_TBTT MT_LPON(0x034) | ||
| 487 | #define MT_TBTT_PERIOD GENMASK(15, 0) | ||
| 488 | #define MT_TBTT_DTIM_PERIOD GENMASK(23, 16) | ||
| 489 | #define MT_TBTT_TBTT_WAKE_PERIOD GENMASK(27, 24) | ||
| 490 | #define MT_TBTT_DTIM_WAKE_PERIOD GENMASK(30, 28) | ||
| 491 | #define MT_TBTT_CAL_ENABLE BIT(31) | ||
| 492 | |||
| 493 | #define MT_TBTT_TIMER_CFG MT_LPON(0x05c) | ||
| 494 | |||
| 495 | #define MT_LPON_SBTOR(n) MT_LPON(0x0a0) | ||
| 496 | #define MT_LPON_SBTOR_SUB_BSS_EN BIT(29) | ||
| 497 | #define MT_LPON_SBTOR_TIME_OFFSET GENMASK(19, 0) | ||
| 498 | |||
| 499 | #define MT_INT_WAKEUP_BASE 0x24400 | ||
| 500 | #define MT_INT_WAKEUP(n) (MT_INT_WAKEUP_BASE + (n)) | ||
| 501 | |||
| 502 | #define MT_HW_INT_STATUS(n) MT_INT_WAKEUP(0x3c + (n) * 8) | ||
| 503 | #define MT_HW_INT_MASK(n) MT_INT_WAKEUP(0x40 + (n) * 8) | ||
| 504 | |||
| 505 | #define MT_HW_INT3_TBTT0 BIT(15) | ||
| 506 | #define MT_HW_INT3_PRE_TBTT0 BIT(31) | ||
| 507 | |||
| 508 | #define MT_WTBL1_BASE 0x28000 | ||
| 509 | |||
| 510 | #define MT_WTBL_ON_BASE (MT_WTBL1_BASE + 0x2000) | ||
| 511 | #define MT_WTBL_ON(_n) (MT_WTBL_ON_BASE + (_n)) | ||
| 512 | |||
| 513 | #define MT_WTBL_RIUCR0 MT_WTBL_ON(0x200) | ||
| 514 | |||
| 515 | #define MT_WTBL_RIUCR1 MT_WTBL_ON(0x204) | ||
| 516 | #define MT_WTBL_RIUCR1_RATE0 GENMASK(11, 0) | ||
| 517 | #define MT_WTBL_RIUCR1_RATE1 GENMASK(23, 12) | ||
| 518 | #define MT_WTBL_RIUCR1_RATE2_LO GENMASK(31, 24) | ||
| 519 | |||
| 520 | #define MT_WTBL_RIUCR2 MT_WTBL_ON(0x208) | ||
| 521 | #define MT_WTBL_RIUCR2_RATE2_HI GENMASK(3, 0) | ||
| 522 | #define MT_WTBL_RIUCR2_RATE3 GENMASK(15, 4) | ||
| 523 | #define MT_WTBL_RIUCR2_RATE4 GENMASK(27, 16) | ||
| 524 | #define MT_WTBL_RIUCR2_RATE5_LO GENMASK(31, 28) | ||
| 525 | |||
| 526 | #define MT_WTBL_RIUCR3 MT_WTBL_ON(0x20c) | ||
| 527 | #define MT_WTBL_RIUCR3_RATE5_HI GENMASK(7, 0) | ||
| 528 | #define MT_WTBL_RIUCR3_RATE6 GENMASK(19, 8) | ||
| 529 | #define MT_WTBL_RIUCR3_RATE7 GENMASK(31, 20) | ||
| 530 | |||
| 531 | #define MT_MIB_BASE 0x2c000 | ||
| 532 | #define MT_MIB(_n) (MT_MIB_BASE + (_n)) | ||
| 533 | |||
| 534 | #define MT_MIB_CTL MT_MIB(0x00) | ||
| 535 | #define MT_MIB_CTL_PSCCA_TIME GENMASK(13, 11) | ||
| 536 | #define MT_MIB_CTL_CCA_NAV_TX GENMASK(16, 14) | ||
| 537 | #define MT_MIB_CTL_ED_TIME GENMASK(30, 28) | ||
| 538 | #define MT_MIB_CTL_READ_CLR_DIS BIT(31) | ||
| 539 | |||
| 540 | #define MT_MIB_STAT(_n) MT_MIB(0x08 + (_n) * 4) | ||
| 541 | |||
| 542 | #define MT_MIB_STAT_CCA MT_MIB_STAT(9) | ||
| 543 | #define MT_MIB_STAT_CCA_MASK GENMASK(23, 0) | ||
| 544 | |||
| 545 | #define MT_MIB_STAT_PSCCA MT_MIB_STAT(16) | ||
| 546 | #define MT_MIB_STAT_PSCCA_MASK GENMASK(23, 0) | ||
| 547 | |||
| 548 | #define MT_MIB_STAT_ED MT_MIB_STAT(18) | ||
| 549 | #define MT_MIB_STAT_ED_MASK GENMASK(23, 0) | ||
| 550 | |||
| 551 | #define MT_PCIE_REMAP_BASE_1 0x40000 | ||
| 552 | #define MT_PCIE_REMAP_BASE_2 0x80000 | ||
| 553 | |||
| 554 | #define MT_TX_HW_QUEUE_MGMT 4 | ||
| 555 | #define MT_TX_HW_QUEUE_MCU 5 | ||
| 556 | #define MT_TX_HW_QUEUE_BCN 7 | ||
| 557 | #define MT_TX_HW_QUEUE_BMC 8 | ||
| 558 | |||
| 559 | #define MT_LED_BASE_PHYS 0x80024000 | ||
| 560 | #define MT_LED_PHYS(_n) (MT_LED_BASE_PHYS + (_n)) | ||
| 561 | |||
| 562 | #define MT_LED_CTRL MT_LED_PHYS(0x00) | ||
| 563 | |||
| 564 | #define MT_LED_CTRL_REPLAY(_n) BIT(0 + (8 * (_n))) | ||
| 565 | #define MT_LED_CTRL_POLARITY(_n) BIT(1 + (8 * (_n))) | ||
| 566 | #define MT_LED_CTRL_TX_BLINK_MODE(_n) BIT(2 + (8 * (_n))) | ||
| 567 | #define MT_LED_CTRL_TX_MANUAL_BLINK(_n) BIT(3 + (8 * (_n))) | ||
| 568 | #define MT_LED_CTRL_TX_OVER_BLINK(_n) BIT(5 + (8 * (_n))) | ||
| 569 | #define MT_LED_CTRL_KICK(_n) BIT(7 + (8 * (_n))) | ||
| 570 | |||
| 571 | #define MT_LED_STATUS_0(_n) MT_LED_PHYS(0x10 + ((_n) * 8)) | ||
| 572 | #define MT_LED_STATUS_1(_n) MT_LED_PHYS(0x14 + ((_n) * 8)) | ||
| 573 | #define MT_LED_STATUS_OFF_MASK GENMASK(31, 24) | ||
| 574 | #define MT_LED_STATUS_OFF(_v) (((_v) << \ | ||
| 575 | __ffs(MT_LED_STATUS_OFF_MASK)) & \ | ||
| 576 | MT_LED_STATUS_OFF_MASK) | ||
| 577 | #define MT_LED_STATUS_ON_MASK GENMASK(23, 16) | ||
| 578 | #define MT_LED_STATUS_ON(_v) (((_v) << \ | ||
| 579 | __ffs(MT_LED_STATUS_ON_MASK)) & \ | ||
| 580 | MT_LED_STATUS_ON_MASK) | ||
| 581 | #define MT_LED_STATUS_DURATION_MASK GENMASK(15, 0) | ||
| 582 | #define MT_LED_STATUS_DURATION(_v) (((_v) << \ | ||
| 583 | __ffs(MT_LED_STATUS_DURATION_MASK)) &\ | ||
| 584 | MT_LED_STATUS_DURATION_MASK) | ||
| 585 | |||
| 586 | #define MT_CLIENT_BASE_PHYS_ADDR 0x800c0000 | ||
| 587 | |||
| 588 | #define MT_CLIENT_TMAC_INFO_TEMPLATE 0x040 | ||
| 589 | |||
| 590 | #define MT_CLIENT_STATUS 0x06c | ||
| 591 | |||
| 592 | #define MT_CLIENT_RESET_TX 0x070 | ||
| 593 | #define MT_CLIENT_RESET_TX_R_E_1 BIT(16) | ||
| 594 | #define MT_CLIENT_RESET_TX_R_E_2 BIT(17) | ||
| 595 | #define MT_CLIENT_RESET_TX_R_E_1_S BIT(20) | ||
| 596 | #define MT_CLIENT_RESET_TX_R_E_2_S BIT(21) | ||
| 597 | |||
| 598 | #define MT_EFUSE_BASE 0x81070000 | ||
| 599 | |||
| 600 | #define MT_EFUSE_BASE_CTRL 0x000 | ||
| 601 | #define MT_EFUSE_BASE_CTRL_EMPTY BIT(30) | ||
| 602 | |||
| 603 | #define MT_EFUSE_CTRL 0x008 | ||
| 604 | #define MT_EFUSE_CTRL_AOUT GENMASK(5, 0) | ||
| 605 | #define MT_EFUSE_CTRL_MODE GENMASK(7, 6) | ||
| 606 | #define MT_EFUSE_CTRL_LDO_OFF_TIME GENMASK(13, 8) | ||
| 607 | #define MT_EFUSE_CTRL_LDO_ON_TIME GENMASK(15, 14) | ||
| 608 | #define MT_EFUSE_CTRL_AIN GENMASK(25, 16) | ||
| 609 | #define MT_EFUSE_CTRL_VALID BIT(29) | ||
| 610 | #define MT_EFUSE_CTRL_KICK BIT(30) | ||
| 611 | #define MT_EFUSE_CTRL_SEL BIT(31) | ||
| 612 | |||
| 613 | #define MT_EFUSE_WDATA(_i) (0x010 + ((_i) * 4)) | ||
| 614 | #define MT_EFUSE_RDATA(_i) (0x030 + ((_i) * 4)) | ||
| 615 | |||
| 616 | #define MT_CLIENT_RXINF 0x068 | ||
| 617 | #define MT_CLIENT_RXINF_RXSH_GROUPS GENMASK(2, 0) | ||
| 618 | |||
| 619 | #define MT_PSE_BASE_PHYS_ADDR 0xa0000000 | ||
| 620 | |||
| 621 | #define MT_PSE_WTBL_2_PHYS_ADDR 0xa5000000 | ||
| 622 | |||
| 623 | #define MT_WTBL1_SIZE (8 * 4) | ||
| 624 | #define MT_WTBL2_SIZE (16 * 4) | ||
| 625 | #define MT_WTBL3_OFFSET (MT7603_WTBL_SIZE * MT_WTBL2_SIZE) | ||
| 626 | #define MT_WTBL3_SIZE (16 * 4) | ||
| 627 | #define MT_WTBL4_OFFSET (MT7603_WTBL_SIZE * MT_WTBL3_SIZE + \ | ||
| 628 | MT_WTBL3_OFFSET) | ||
| 629 | #define MT_WTBL4_SIZE (8 * 4) | ||
| 630 | |||
| 631 | #define MT_WTBL1_W0_ADDR_HI GENMASK(15, 0) | ||
| 632 | #define MT_WTBL1_W0_MUAR_IDX GENMASK(21, 16) | ||
| 633 | #define MT_WTBL1_W0_RX_CHECK_A1 BIT(22) | ||
| 634 | #define MT_WTBL1_W0_KEY_IDX GENMASK(24, 23) | ||
| 635 | #define MT_WTBL1_W0_RX_CHECK_KEY_IDX BIT(25) | ||
| 636 | #define MT_WTBL1_W0_RX_KEY_VALID BIT(26) | ||
| 637 | #define MT_WTBL1_W0_RX_IK_VALID BIT(27) | ||
| 638 | #define MT_WTBL1_W0_RX_VALID BIT(28) | ||
| 639 | #define MT_WTBL1_W0_RX_CHECK_A2 BIT(29) | ||
| 640 | #define MT_WTBL1_W0_RX_DATA_VALID BIT(30) | ||
| 641 | #define MT_WTBL1_W0_WRITE_BURST BIT(31) | ||
| 642 | |||
| 643 | #define MT_WTBL1_W1_ADDR_LO GENMASK(31, 0) | ||
| 644 | |||
| 645 | #define MT_WTBL1_W2_MPDU_DENSITY GENMASK(2, 0) | ||
| 646 | #define MT_WTBL1_W2_KEY_TYPE GENMASK(6, 3) | ||
| 647 | #define MT_WTBL1_W2_EVEN_PN BIT(7) | ||
| 648 | #define MT_WTBL1_W2_TO_DS BIT(8) | ||
| 649 | #define MT_WTBL1_W2_FROM_DS BIT(9) | ||
| 650 | #define MT_WTBL1_W2_HEADER_TRANS BIT(10) | ||
| 651 | #define MT_WTBL1_W2_AMPDU_FACTOR GENMASK(13, 11) | ||
| 652 | #define MT_WTBL1_W2_PWR_MGMT BIT(14) | ||
| 653 | #define MT_WTBL1_W2_RDG BIT(15) | ||
| 654 | #define MT_WTBL1_W2_RTS BIT(16) | ||
| 655 | #define MT_WTBL1_W2_CFACK BIT(17) | ||
| 656 | #define MT_WTBL1_W2_RDG_BA BIT(18) | ||
| 657 | #define MT_WTBL1_W2_SMPS BIT(19) | ||
| 658 | #define MT_WTBL1_W2_TXS_BAF_REPORT BIT(20) | ||
| 659 | #define MT_WTBL1_W2_DYN_BW BIT(21) | ||
| 660 | #define MT_WTBL1_W2_LDPC BIT(22) | ||
| 661 | #define MT_WTBL1_W2_ITXBF BIT(23) | ||
| 662 | #define MT_WTBL1_W2_ETXBF BIT(24) | ||
| 663 | #define MT_WTBL1_W2_TXOP_PS BIT(25) | ||
| 664 | #define MT_WTBL1_W2_MESH BIT(26) | ||
| 665 | #define MT_WTBL1_W2_QOS BIT(27) | ||
| 666 | #define MT_WTBL1_W2_HT BIT(28) | ||
| 667 | #define MT_WTBL1_W2_VHT BIT(29) | ||
| 668 | #define MT_WTBL1_W2_ADMISSION_CONTROL BIT(30) | ||
| 669 | #define MT_WTBL1_W2_GROUP_ID BIT(31) | ||
| 670 | |||
| 671 | #define MT_WTBL1_W3_WTBL2_FRAME_ID GENMASK(10, 0) | ||
| 672 | #define MT_WTBL1_W3_WTBL2_ENTRY_ID GENMASK(15, 11) | ||
| 673 | #define MT_WTBL1_W3_WTBL4_FRAME_ID GENMASK(26, 16) | ||
| 674 | #define MT_WTBL1_W3_CHECK_PER BIT(27) | ||
| 675 | #define MT_WTBL1_W3_KEEP_I_PSM BIT(28) | ||
| 676 | #define MT_WTBL1_W3_I_PSM BIT(29) | ||
| 677 | #define MT_WTBL1_W3_POWER_SAVE BIT(30) | ||
| 678 | #define MT_WTBL1_W3_SKIP_TX BIT(31) | ||
| 679 | |||
| 680 | #define MT_WTBL1_W4_WTBL3_FRAME_ID GENMASK(10, 0) | ||
| 681 | #define MT_WTBL1_W4_WTBL3_ENTRY_ID GENMASK(16, 11) | ||
| 682 | #define MT_WTBL1_W4_WTBL4_ENTRY_ID GENMASK(22, 17) | ||
| 683 | #define MT_WTBL1_W4_PARTIAL_AID GENMASK(31, 23) | ||
| 684 | |||
| 685 | #define MT_WTBL2_W0_PN_LO GENMASK(31, 0) | ||
| 686 | |||
| 687 | #define MT_WTBL2_W1_PN_HI GENMASK(15, 0) | ||
| 688 | #define MT_WTBL2_W1_NON_QOS_SEQNO GENMASK(27, 16) | ||
| 689 | |||
| 690 | #define MT_WTBL2_W2_TID0_SN GENMASK(11, 0) | ||
| 691 | #define MT_WTBL2_W2_TID1_SN GENMASK(23, 12) | ||
| 692 | #define MT_WTBL2_W2_TID2_SN_LO GENMASK(31, 24) | ||
| 693 | |||
| 694 | #define MT_WTBL2_W3_TID2_SN_HI GENMASK(3, 0) | ||
| 695 | #define MT_WTBL2_W3_TID3_SN GENMASK(15, 4) | ||
| 696 | #define MT_WTBL2_W3_TID4_SN GENMASK(27, 16) | ||
| 697 | #define MT_WTBL2_W3_TID5_SN_LO GENMASK(31, 28) | ||
| 698 | |||
| 699 | #define MT_WTBL2_W4_TID5_SN_HI GENMASK(7, 0) | ||
| 700 | #define MT_WTBL2_W4_TID6_SN GENMASK(19, 8) | ||
| 701 | #define MT_WTBL2_W4_TID7_SN GENMASK(31, 20) | ||
| 702 | |||
| 703 | #define MT_WTBL2_W5_TX_COUNT_RATE1 GENMASK(15, 0) | ||
| 704 | #define MT_WTBL2_W5_FAIL_COUNT_RATE1 GENAMSK(31, 16) | ||
| 705 | |||
| 706 | #define MT_WTBL2_W6_TX_COUNT_RATE2 GENMASK(7, 0) | ||
| 707 | #define MT_WTBL2_W6_TX_COUNT_RATE3 GENMASK(15, 8) | ||
| 708 | #define MT_WTBL2_W6_TX_COUNT_RATE4 GENMASK(23, 16) | ||
| 709 | #define MT_WTBL2_W6_TX_COUNT_RATE5 GENMASK(31, 24) | ||
| 710 | |||
| 711 | #define MT_WTBL2_W7_TX_COUNT_CUR_BW GENMASK(15, 0) | ||
| 712 | #define MT_WTBL2_W7_FAIL_COUNT_CUR_BW GENMASK(31, 16) | ||
| 713 | |||
| 714 | #define MT_WTBL2_W8_TX_COUNT_OTHER_BW GENMASK(15, 0) | ||
| 715 | #define MT_WTBL2_W8_FAIL_COUNT_OTHER_BW GENMASK(31, 16) | ||
| 716 | |||
| 717 | #define MT_WTBL2_W9_POWER_OFFSET GENMASK(4, 0) | ||
| 718 | #define MT_WTBL2_W9_SPATIAL_EXT BIT(5) | ||
| 719 | #define MT_WTBL2_W9_ANT_PRIORITY GENMASK(8, 6) | ||
| 720 | #define MT_WTBL2_W9_CC_BW_SEL GENMASK(10, 9) | ||
| 721 | #define MT_WTBL2_W9_CHANGE_BW_RATE GENMASK(13, 11) | ||
| 722 | #define MT_WTBL2_W9_BW_CAP GENMASK(15, 14) | ||
| 723 | #define MT_WTBL2_W9_SHORT_GI_20 BIT(16) | ||
| 724 | #define MT_WTBL2_W9_SHORT_GI_40 BIT(17) | ||
| 725 | #define MT_WTBL2_W9_SHORT_GI_80 BIT(18) | ||
| 726 | #define MT_WTBL2_W9_SHORT_GI_160 BIT(19) | ||
| 727 | #define MT_WTBL2_W9_MPDU_FAIL_COUNT GENMASK(25, 23) | ||
| 728 | #define MT_WTBL2_W9_MPDU_OK_COUNT GENMASK(28, 26) | ||
| 729 | #define MT_WTBL2_W9_RATE_IDX GENMASK(31, 29) | ||
| 730 | |||
| 731 | #define MT_WTBL2_W10_RATE1 GENMASK(11, 0) | ||
| 732 | #define MT_WTBL2_W10_RATE2 GENMASK(23, 12) | ||
| 733 | #define MT_WTBL2_W10_RATE3_LO GENMASK(31, 24) | ||
| 734 | |||
| 735 | #define MT_WTBL2_W11_RATE3_HI GENMASK(3, 0) | ||
| 736 | #define MT_WTBL2_W11_RATE4 GENMASK(15, 4) | ||
| 737 | #define MT_WTBL2_W11_RATE5 GENMASK(27, 16) | ||
| 738 | #define MT_WTBL2_W11_RATE6_LO GENMASK(31, 28) | ||
| 739 | |||
| 740 | #define MT_WTBL2_W12_RATE6_HI GENMASK(7, 0) | ||
| 741 | #define MT_WTBL2_W12_RATE7 GENMASK(19, 8) | ||
| 742 | #define MT_WTBL2_W12_RATE8 GENMASK(31, 20) | ||
| 743 | |||
| 744 | #define MT_WTBL2_W13_AVG_RCPI0 GENMASK(7, 0) | ||
| 745 | #define MT_WTBL2_W13_AVG_RCPI1 GENMASK(15, 8) | ||
| 746 | #define MT_WTBL2_W13_AVG_RCPI2 GENAMSK(23, 16) | ||
| 747 | |||
| 748 | #define MT_WTBL2_W14_CC_NOISE_1S GENMASK(6, 0) | ||
| 749 | #define MT_WTBL2_W14_CC_NOISE_2S GENMASK(13, 7) | ||
| 750 | #define MT_WTBL2_W14_CC_NOISE_3S GENMASK(20, 14) | ||
| 751 | #define MT_WTBL2_W14_CHAN_EST_RMS GENMASK(24, 21) | ||
| 752 | #define MT_WTBL2_W14_CC_NOISE_SEL BIT(15) | ||
| 753 | #define MT_WTBL2_W14_ANT_SEL GENMASK(31, 26) | ||
| 754 | |||
| 755 | #define MT_WTBL2_W15_BA_WIN_SIZE GENMASK(2, 0) | ||
| 756 | #define MT_WTBL2_W15_BA_WIN_SIZE_SHIFT 3 | ||
| 757 | #define MT_WTBL2_W15_BA_EN_TIDS GENMASK(31, 24) | ||
| 758 | |||
| 759 | #define MT_WTBL1_OR (MT_WTBL1_BASE + 0x2300) | ||
| 760 | #define MT_WTBL1_OR_PSM_WRITE BIT(31) | ||
| 761 | |||
| 762 | enum mt7603_cipher_type { | ||
| 763 | MT_CIPHER_NONE, | ||
| 764 | MT_CIPHER_WEP40, | ||
| 765 | MT_CIPHER_TKIP, | ||
| 766 | MT_CIPHER_TKIP_NO_MIC, | ||
| 767 | MT_CIPHER_AES_CCMP, | ||
| 768 | MT_CIPHER_WEP104, | ||
| 769 | MT_CIPHER_BIP_CMAC_128, | ||
| 770 | MT_CIPHER_WEP128, | ||
| 771 | MT_CIPHER_WAPI, | ||
| 772 | }; | ||
| 773 | |||
| 774 | #endif | ||
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/soc.c b/drivers/net/wireless/mediatek/mt76/mt7603/soc.c new file mode 100644 index 000000000000..e13fea80d970 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt7603/soc.c | |||
| @@ -0,0 +1,85 @@ | |||
| 1 | /* SPDX-License-Identifier: ISC */ | ||
| 2 | |||
| 3 | #include <linux/kernel.h> | ||
| 4 | #include <linux/module.h> | ||
| 5 | #include <linux/platform_device.h> | ||
| 6 | |||
| 7 | #include "mt7603.h" | ||
| 8 | |||
| 9 | static int | ||
| 10 | mt76_wmac_probe(struct platform_device *pdev) | ||
| 11 | { | ||
| 12 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 13 | struct mt7603_dev *dev; | ||
| 14 | void __iomem *mem_base; | ||
| 15 | struct mt76_dev *mdev; | ||
| 16 | int irq; | ||
| 17 | int ret; | ||
| 18 | |||
| 19 | irq = platform_get_irq(pdev, 0); | ||
| 20 | if (irq < 0) { | ||
| 21 | dev_err(&pdev->dev, "Failed to get device IRQ\n"); | ||
| 22 | return irq; | ||
| 23 | } | ||
| 24 | |||
| 25 | mem_base = devm_ioremap_resource(&pdev->dev, res); | ||
| 26 | if (!mem_base) { | ||
| 27 | dev_err(&pdev->dev, "Failed to get memory resource\n"); | ||
| 28 | return -EINVAL; | ||
| 29 | } | ||
| 30 | |||
| 31 | mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt7603_ops, | ||
| 32 | &mt7603_drv_ops); | ||
| 33 | if (!mdev) | ||
| 34 | return -ENOMEM; | ||
| 35 | |||
| 36 | dev = container_of(mdev, struct mt7603_dev, mt76); | ||
| 37 | mt76_mmio_init(mdev, mem_base); | ||
| 38 | |||
| 39 | mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) | | ||
| 40 | (mt76_rr(dev, MT_HW_REV) & 0xff); | ||
| 41 | dev_info(mdev->dev, "ASIC revision: %04x\n", mdev->rev); | ||
| 42 | |||
| 43 | ret = devm_request_irq(mdev->dev, irq, mt7603_irq_handler, | ||
| 44 | IRQF_SHARED, KBUILD_MODNAME, dev); | ||
| 45 | if (ret) | ||
| 46 | goto error; | ||
| 47 | |||
| 48 | ret = mt7603_register_device(dev); | ||
| 49 | if (ret) | ||
| 50 | goto error; | ||
| 51 | |||
| 52 | return 0; | ||
| 53 | error: | ||
| 54 | ieee80211_free_hw(mt76_hw(dev)); | ||
| 55 | return ret; | ||
| 56 | } | ||
| 57 | |||
| 58 | static int | ||
| 59 | mt76_wmac_remove(struct platform_device *pdev) | ||
| 60 | { | ||
| 61 | struct mt76_dev *mdev = platform_get_drvdata(pdev); | ||
| 62 | struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76); | ||
| 63 | |||
| 64 | mt7603_unregister_device(dev); | ||
| 65 | |||
| 66 | return 0; | ||
| 67 | } | ||
| 68 | |||
| 69 | static const struct of_device_id of_wmac_match[] = { | ||
| 70 | { .compatible = "mediatek,mt7628-wmac" }, | ||
| 71 | {}, | ||
| 72 | }; | ||
| 73 | |||
| 74 | MODULE_DEVICE_TABLE(of, of_wmac_match); | ||
| 75 | MODULE_FIRMWARE(MT7628_FIRMWARE_E1); | ||
| 76 | MODULE_FIRMWARE(MT7628_FIRMWARE_E2); | ||
| 77 | |||
| 78 | struct platform_driver mt76_wmac_driver = { | ||
| 79 | .probe = mt76_wmac_probe, | ||
| 80 | .remove = mt76_wmac_remove, | ||
| 81 | .driver = { | ||
| 82 | .name = "mt76_wmac", | ||
| 83 | .of_match_table = of_wmac_match, | ||
| 84 | }, | ||
| 85 | }; | ||
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c index a529ce111c20..bcb72e019fd2 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c | |||
| @@ -187,6 +187,8 @@ void mt76x0_mac_stop(struct mt76x02_dev *dev) | |||
| 187 | { | 187 | { |
| 188 | int i = 200, ok = 0; | 188 | int i = 200, ok = 0; |
| 189 | 189 | ||
| 190 | mt76_clear(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN); | ||
| 191 | |||
| 190 | /* Page count on TxQ */ | 192 | /* Page count on TxQ */ |
| 191 | while (i-- && ((mt76_rr(dev, 0x0438) & 0xffffffff) || | 193 | while (i-- && ((mt76_rr(dev, 0x0438) & 0xffffffff) || |
| 192 | (mt76_rr(dev, 0x0a30) & 0x000000ff) || | 194 | (mt76_rr(dev, 0x0a30) & 0x000000ff) || |
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c index a803a9b6a4c5..fee16ab21edb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c | |||
| @@ -34,6 +34,8 @@ mt76x0_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) | |||
| 34 | mt76_rr(dev, MT_CH_IDLE); | 34 | mt76_rr(dev, MT_CH_IDLE); |
| 35 | mt76_rr(dev, MT_CH_BUSY); | 35 | mt76_rr(dev, MT_CH_BUSY); |
| 36 | 36 | ||
| 37 | mt76x02_edcca_init(dev, true); | ||
| 38 | |||
| 37 | if (mt76_is_mmio(dev)) { | 39 | if (mt76_is_mmio(dev)) { |
| 38 | mt76x02_dfs_init_params(dev); | 40 | mt76x02_dfs_init_params(dev); |
| 39 | tasklet_enable(&dev->pre_tbtt_tasklet); | 41 | tasklet_enable(&dev->pre_tbtt_tasklet); |
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c index 3467a32f5fda..1fd22eb841c3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c | |||
| @@ -1007,17 +1007,13 @@ int mt76x0_phy_set_channel(struct mt76x02_dev *dev, | |||
| 1007 | 1007 | ||
| 1008 | /* enable vco */ | 1008 | /* enable vco */ |
| 1009 | mt76x0_rf_set(dev, MT_RF(0, 4), BIT(7)); | 1009 | mt76x0_rf_set(dev, MT_RF(0, 4), BIT(7)); |
| 1010 | if (scan) { | 1010 | if (scan) |
| 1011 | mt76x02_edcca_init(dev, false); | ||
| 1012 | return 0; | 1011 | return 0; |
| 1013 | } | ||
| 1014 | 1012 | ||
| 1015 | mt76x02_init_agc_gain(dev); | 1013 | mt76x02_init_agc_gain(dev); |
| 1016 | mt76x0_phy_calibrate(dev, false); | 1014 | mt76x0_phy_calibrate(dev, false); |
| 1017 | mt76x0_phy_set_txpower(dev); | 1015 | mt76x0_phy_set_txpower(dev); |
| 1018 | 1016 | ||
| 1019 | mt76x02_edcca_init(dev, true); | ||
| 1020 | |||
| 1021 | ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work, | 1017 | ieee80211_queue_delayed_work(dev->mt76.hw, &dev->cal_work, |
| 1022 | MT_CALIBRATE_INTERVAL); | 1018 | MT_CALIBRATE_INTERVAL); |
| 1023 | 1019 | ||
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c index da9d05f6074d..91718647da02 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c | |||
| @@ -79,7 +79,6 @@ static void mt76x0u_cleanup(struct mt76x02_dev *dev) | |||
| 79 | clear_bit(MT76_STATE_INITIALIZED, &dev->mt76.state); | 79 | clear_bit(MT76_STATE_INITIALIZED, &dev->mt76.state); |
| 80 | mt76x0_chip_onoff(dev, false, false); | 80 | mt76x0_chip_onoff(dev, false, false); |
| 81 | mt76u_queues_deinit(&dev->mt76); | 81 | mt76u_queues_deinit(&dev->mt76); |
| 82 | mt76u_mcu_deinit(&dev->mt76); | ||
| 83 | } | 82 | } |
| 84 | 83 | ||
| 85 | static void mt76x0u_mac_stop(struct mt76x02_dev *dev) | 84 | static void mt76x0u_mac_stop(struct mt76x02_dev *dev) |
| @@ -193,10 +192,6 @@ static int mt76x0u_register_device(struct mt76x02_dev *dev) | |||
| 193 | if (err < 0) | 192 | if (err < 0) |
| 194 | goto out_err; | 193 | goto out_err; |
| 195 | 194 | ||
| 196 | err = mt76u_mcu_init_rx(&dev->mt76); | ||
| 197 | if (err < 0) | ||
| 198 | goto out_err; | ||
| 199 | |||
| 200 | err = mt76x0u_init_hardware(dev); | 195 | err = mt76x0u_init_hardware(dev); |
| 201 | if (err < 0) | 196 | if (err < 0) |
| 202 | goto out_err; | 197 | goto out_err; |
| @@ -311,13 +306,11 @@ static int __maybe_unused mt76x0_suspend(struct usb_interface *usb_intf, | |||
| 311 | pm_message_t state) | 306 | pm_message_t state) |
| 312 | { | 307 | { |
| 313 | struct mt76x02_dev *dev = usb_get_intfdata(usb_intf); | 308 | struct mt76x02_dev *dev = usb_get_intfdata(usb_intf); |
| 314 | struct mt76_usb *usb = &dev->mt76.usb; | ||
| 315 | 309 | ||
| 316 | mt76u_stop_queues(&dev->mt76); | 310 | mt76u_stop_queues(&dev->mt76); |
| 317 | mt76x0u_mac_stop(dev); | 311 | mt76x0u_mac_stop(dev); |
| 318 | clear_bit(MT76_STATE_MCU_RUNNING, &dev->mt76.state); | 312 | clear_bit(MT76_STATE_MCU_RUNNING, &dev->mt76.state); |
| 319 | mt76x0_chip_onoff(dev, false, false); | 313 | mt76x0_chip_onoff(dev, false, false); |
| 320 | usb_kill_urb(usb->mcu.res.urb); | ||
| 321 | 314 | ||
| 322 | return 0; | 315 | return 0; |
| 323 | } | 316 | } |
| @@ -328,15 +321,6 @@ static int __maybe_unused mt76x0_resume(struct usb_interface *usb_intf) | |||
| 328 | struct mt76_usb *usb = &dev->mt76.usb; | 321 | struct mt76_usb *usb = &dev->mt76.usb; |
| 329 | int ret; | 322 | int ret; |
| 330 | 323 | ||
| 331 | reinit_completion(&usb->mcu.cmpl); | ||
| 332 | ret = mt76u_submit_buf(&dev->mt76, USB_DIR_IN, | ||
| 333 | MT_EP_IN_CMD_RESP, | ||
| 334 | &usb->mcu.res, GFP_KERNEL, | ||
| 335 | mt76u_mcu_complete_urb, | ||
| 336 | &usb->mcu.cmpl); | ||
| 337 | if (ret < 0) | ||
| 338 | goto err; | ||
| 339 | |||
| 340 | ret = mt76u_submit_rx_buffers(&dev->mt76); | 324 | ret = mt76u_submit_rx_buffers(&dev->mt76); |
| 341 | if (ret < 0) | 325 | if (ret < 0) |
| 342 | goto err; | 326 | goto err; |
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h index 3464b4ca2ea8..6915cce5def9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h | |||
| @@ -98,6 +98,7 @@ struct mt76x02_dev { | |||
| 98 | 98 | ||
| 99 | u32 tx_hang_reset; | 99 | u32 tx_hang_reset; |
| 100 | u8 tx_hang_check; | 100 | u8 tx_hang_check; |
| 101 | u8 mcu_timeout; | ||
| 101 | 102 | ||
| 102 | struct mt76x02_calibration cal; | 103 | struct mt76x02_calibration cal; |
| 103 | 104 | ||
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c index be2979f34f31..91ff6598eccf 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | |||
| @@ -905,14 +905,14 @@ void mt76x02_edcca_init(struct mt76x02_dev *dev, bool enable) | |||
| 905 | mt76_set(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN); | 905 | mt76_set(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN); |
| 906 | mt76_rmw(dev, MT_BBP(AGC, 2), GENMASK(15, 0), | 906 | mt76_rmw(dev, MT_BBP(AGC, 2), GENMASK(15, 0), |
| 907 | ed_th << 8 | ed_th); | 907 | ed_th << 8 | ed_th); |
| 908 | if (!is_mt76x2(dev)) | 908 | mt76_set(dev, MT_TXOP_HLDR_ET, MT_TXOP_HLDR_TX40M_BLK_EN); |
| 909 | mt76_set(dev, MT_TXOP_HLDR_ET, | ||
| 910 | MT_TXOP_HLDR_TX40M_BLK_EN); | ||
| 911 | } else { | 909 | } else { |
| 912 | mt76_set(dev, MT_TX_LINK_CFG, MT_TX_CFACK_EN); | 910 | mt76_set(dev, MT_TX_LINK_CFG, MT_TX_CFACK_EN); |
| 913 | mt76_clear(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN); | 911 | mt76_clear(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN); |
| 914 | if (is_mt76x2(dev)) { | 912 | if (is_mt76x2(dev)) { |
| 915 | mt76_wr(dev, MT_BBP(AGC, 2), 0x00007070); | 913 | mt76_wr(dev, MT_BBP(AGC, 2), 0x00007070); |
| 914 | mt76_set(dev, MT_TXOP_HLDR_ET, | ||
| 915 | MT_TXOP_HLDR_TX40M_BLK_EN); | ||
| 916 | } else { | 916 | } else { |
| 917 | mt76_wr(dev, MT_BBP(AGC, 2), 0x003a6464); | 917 | mt76_wr(dev, MT_BBP(AGC, 2), 0x003a6464); |
| 918 | mt76_clear(dev, MT_TXOP_HLDR_ET, | 918 | mt76_clear(dev, MT_TXOP_HLDR_ET, |
| @@ -1126,6 +1126,9 @@ void mt76x02_mac_set_beacon_enable(struct mt76x02_dev *dev, | |||
| 1126 | else if (val) | 1126 | else if (val) |
| 1127 | skb = ieee80211_beacon_get(mt76_hw(dev), vif); | 1127 | skb = ieee80211_beacon_get(mt76_hw(dev), vif); |
| 1128 | 1128 | ||
| 1129 | if (!dev->beacon_mask) | ||
| 1130 | dev->tbtt_count = 0; | ||
| 1131 | |||
| 1129 | __mt76x02_mac_set_beacon_enable(dev, vif_idx, val, skb); | 1132 | __mt76x02_mac_set_beacon_enable(dev, vif_idx, val, skb); |
| 1130 | 1133 | ||
| 1131 | if (mt76_is_mmio(dev)) | 1134 | if (mt76_is_mmio(dev)) |
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c index 4752c104abf3..6501b853b65c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mcu.c | |||
| @@ -61,6 +61,7 @@ int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, | |||
| 61 | "MCU message %d (seq %d) timed out\n", cmd, | 61 | "MCU message %d (seq %d) timed out\n", cmd, |
| 62 | seq); | 62 | seq); |
| 63 | ret = -ETIMEDOUT; | 63 | ret = -ETIMEDOUT; |
| 64 | dev->mcu_timeout = 1; | ||
| 64 | break; | 65 | break; |
| 65 | } | 66 | } |
| 66 | 67 | ||
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c index 374bc9d91f12..1229f19f2b02 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c | |||
| @@ -79,24 +79,24 @@ mt76x02_resync_beacon_timer(struct mt76x02_dev *dev) | |||
| 79 | * Beacon timer drifts by 1us every tick, the timer is configured | 79 | * Beacon timer drifts by 1us every tick, the timer is configured |
| 80 | * in 1/16 TU (64us) units. | 80 | * in 1/16 TU (64us) units. |
| 81 | */ | 81 | */ |
| 82 | if (dev->tbtt_count < 62) | 82 | if (dev->tbtt_count < 63) |
| 83 | return; | 83 | return; |
| 84 | 84 | ||
| 85 | if (dev->tbtt_count >= 64) { | ||
| 86 | dev->tbtt_count = 0; | ||
| 87 | return; | ||
| 88 | } | ||
| 89 | |||
| 90 | /* | 85 | /* |
| 91 | * The updated beacon interval takes effect after two TBTT, because | 86 | * The updated beacon interval takes effect after two TBTT, because |
| 92 | * at this point the original interval has already been loaded into | 87 | * at this point the original interval has already been loaded into |
| 93 | * the next TBTT_TIMER value | 88 | * the next TBTT_TIMER value |
| 94 | */ | 89 | */ |
| 95 | if (dev->tbtt_count == 62) | 90 | if (dev->tbtt_count == 63) |
| 96 | timer_val -= 1; | 91 | timer_val -= 1; |
| 97 | 92 | ||
| 98 | mt76_rmw_field(dev, MT_BEACON_TIME_CFG, | 93 | mt76_rmw_field(dev, MT_BEACON_TIME_CFG, |
| 99 | MT_BEACON_TIME_CFG_INTVAL, timer_val); | 94 | MT_BEACON_TIME_CFG_INTVAL, timer_val); |
| 95 | |||
| 96 | if (dev->tbtt_count >= 64) { | ||
| 97 | dev->tbtt_count = 0; | ||
| 98 | return; | ||
| 99 | } | ||
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | static void mt76x02_pre_tbtt_tasklet(unsigned long arg) | 102 | static void mt76x02_pre_tbtt_tasklet(unsigned long arg) |
| @@ -494,18 +494,28 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev) | |||
| 494 | static void mt76x02_check_tx_hang(struct mt76x02_dev *dev) | 494 | static void mt76x02_check_tx_hang(struct mt76x02_dev *dev) |
| 495 | { | 495 | { |
| 496 | if (mt76x02_tx_hang(dev)) { | 496 | if (mt76x02_tx_hang(dev)) { |
| 497 | if (++dev->tx_hang_check < MT_TX_HANG_TH) | 497 | if (++dev->tx_hang_check >= MT_TX_HANG_TH) |
| 498 | return; | 498 | goto restart; |
| 499 | |||
| 500 | mt76x02_watchdog_reset(dev); | ||
| 501 | |||
| 502 | dev->tx_hang_reset++; | ||
| 503 | dev->tx_hang_check = 0; | ||
| 504 | memset(dev->mt76.tx_dma_idx, 0xff, | ||
| 505 | sizeof(dev->mt76.tx_dma_idx)); | ||
| 506 | } else { | 499 | } else { |
| 507 | dev->tx_hang_check = 0; | 500 | dev->tx_hang_check = 0; |
| 508 | } | 501 | } |
| 502 | |||
| 503 | if (dev->mcu_timeout) | ||
| 504 | goto restart; | ||
| 505 | |||
| 506 | return; | ||
| 507 | |||
| 508 | restart: | ||
| 509 | mt76x02_watchdog_reset(dev); | ||
| 510 | |||
| 511 | mutex_lock(&dev->mt76.mmio.mcu.mutex); | ||
| 512 | dev->mcu_timeout = 0; | ||
| 513 | mutex_unlock(&dev->mt76.mmio.mcu.mutex); | ||
| 514 | |||
| 515 | dev->tx_hang_reset++; | ||
| 516 | dev->tx_hang_check = 0; | ||
| 517 | memset(dev->mt76.tx_dma_idx, 0xff, | ||
| 518 | sizeof(dev->mt76.tx_dma_idx)); | ||
| 509 | } | 519 | } |
| 510 | 520 | ||
| 511 | void mt76x02_wdt_work(struct work_struct *work) | 521 | void mt76x02_wdt_work(struct work_struct *work) |
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c index e469e383cb88..0cb8751321a1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c | |||
| @@ -61,33 +61,21 @@ mt76x02u_multiple_mcu_reads(struct mt76_dev *dev, u8 *data, int len) | |||
| 61 | static int mt76x02u_mcu_wait_resp(struct mt76_dev *dev, u8 seq) | 61 | static int mt76x02u_mcu_wait_resp(struct mt76_dev *dev, u8 seq) |
| 62 | { | 62 | { |
| 63 | struct mt76_usb *usb = &dev->usb; | 63 | struct mt76_usb *usb = &dev->usb; |
| 64 | struct mt76u_buf *buf = &usb->mcu.res; | 64 | u8 *data = usb->mcu.data; |
| 65 | struct urb *urb = buf->urb; | 65 | int i, len, ret; |
| 66 | u8 *data = buf->buf; | ||
| 67 | int i, ret; | ||
| 68 | u32 rxfce; | 66 | u32 rxfce; |
| 69 | 67 | ||
| 70 | for (i = 0; i < 5; i++) { | 68 | for (i = 0; i < 5; i++) { |
| 71 | if (!wait_for_completion_timeout(&usb->mcu.cmpl, | 69 | ret = mt76u_bulk_msg(dev, data, MCU_RESP_URB_SIZE, &len, 300); |
| 72 | msecs_to_jiffies(300))) | 70 | if (ret == -ETIMEDOUT) |
| 73 | continue; | 71 | continue; |
| 74 | 72 | if (ret) | |
| 75 | if (urb->status) | 73 | goto out; |
| 76 | return -EIO; | ||
| 77 | 74 | ||
| 78 | if (usb->mcu.rp) | 75 | if (usb->mcu.rp) |
| 79 | mt76x02u_multiple_mcu_reads(dev, data + 4, | 76 | mt76x02u_multiple_mcu_reads(dev, data + 4, len - 8); |
| 80 | urb->actual_length - 8); | ||
| 81 | 77 | ||
| 82 | rxfce = get_unaligned_le32(data); | 78 | rxfce = get_unaligned_le32(data); |
| 83 | ret = mt76u_submit_buf(dev, USB_DIR_IN, | ||
| 84 | MT_EP_IN_CMD_RESP, | ||
| 85 | buf, GFP_KERNEL, | ||
| 86 | mt76u_mcu_complete_urb, | ||
| 87 | &usb->mcu.cmpl); | ||
| 88 | if (ret) | ||
| 89 | return ret; | ||
| 90 | |||
| 91 | if (seq == FIELD_GET(MT_RX_FCE_INFO_CMD_SEQ, rxfce) && | 79 | if (seq == FIELD_GET(MT_RX_FCE_INFO_CMD_SEQ, rxfce) && |
| 92 | FIELD_GET(MT_RX_FCE_INFO_EVT_TYPE, rxfce) == EVT_CMD_DONE) | 80 | FIELD_GET(MT_RX_FCE_INFO_EVT_TYPE, rxfce) == EVT_CMD_DONE) |
| 93 | return 0; | 81 | return 0; |
| @@ -96,9 +84,9 @@ static int mt76x02u_mcu_wait_resp(struct mt76_dev *dev, u8 seq) | |||
| 96 | FIELD_GET(MT_RX_FCE_INFO_EVT_TYPE, rxfce), | 84 | FIELD_GET(MT_RX_FCE_INFO_EVT_TYPE, rxfce), |
| 97 | seq, FIELD_GET(MT_RX_FCE_INFO_CMD_SEQ, rxfce)); | 85 | seq, FIELD_GET(MT_RX_FCE_INFO_CMD_SEQ, rxfce)); |
| 98 | } | 86 | } |
| 99 | 87 | out: | |
| 100 | dev_err(dev->dev, "error: %s timed out\n", __func__); | 88 | dev_err(dev->dev, "error: %s failed with %d\n", __func__, ret); |
| 101 | return -ETIMEDOUT; | 89 | return ret; |
| 102 | } | 90 | } |
| 103 | 91 | ||
| 104 | static int | 92 | static int |
| @@ -126,7 +114,7 @@ __mt76x02u_mcu_send_msg(struct mt76_dev *dev, struct sk_buff *skb, | |||
| 126 | if (ret) | 114 | if (ret) |
| 127 | return ret; | 115 | return ret; |
| 128 | 116 | ||
| 129 | ret = mt76u_bulk_msg(dev, skb->data, skb->len, 500); | 117 | ret = mt76u_bulk_msg(dev, skb->data, skb->len, NULL, 500); |
| 130 | if (ret) | 118 | if (ret) |
| 131 | return ret; | 119 | return ret; |
| 132 | 120 | ||
| @@ -271,7 +259,7 @@ __mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, u8 *data, | |||
| 271 | 259 | ||
| 272 | data_len = MT_CMD_HDR_LEN + len + sizeof(info); | 260 | data_len = MT_CMD_HDR_LEN + len + sizeof(info); |
| 273 | 261 | ||
| 274 | err = mt76u_bulk_msg(&dev->mt76, data, data_len, 1000); | 262 | err = mt76u_bulk_msg(&dev->mt76, data, data_len, NULL, 1000); |
| 275 | if (err) { | 263 | if (err) { |
| 276 | dev_err(dev->mt76.dev, "firmware upload failed: %d\n", err); | 264 | dev_err(dev->mt76.dev, "firmware upload failed: %d\n", err); |
| 277 | return err; | 265 | return err; |
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index 11b5f664f5b1..a48c261b0c63 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c | |||
| @@ -679,9 +679,9 @@ void mt76x02_init_beacon_config(struct mt76x02_dev *dev) | |||
| 679 | } | 679 | } |
| 680 | 680 | ||
| 681 | mt76_clear(dev, MT_BEACON_TIME_CFG, (MT_BEACON_TIME_CFG_TIMER_EN | | 681 | mt76_clear(dev, MT_BEACON_TIME_CFG, (MT_BEACON_TIME_CFG_TIMER_EN | |
| 682 | MT_BEACON_TIME_CFG_SYNC_MODE | | ||
| 683 | MT_BEACON_TIME_CFG_TBTT_EN | | 682 | MT_BEACON_TIME_CFG_TBTT_EN | |
| 684 | MT_BEACON_TIME_CFG_BEACON_TX)); | 683 | MT_BEACON_TIME_CFG_BEACON_TX)); |
| 684 | mt76_set(dev, MT_BEACON_TIME_CFG, MT_BEACON_TIME_CFG_SYNC_MODE); | ||
| 685 | mt76_wr(dev, MT_BCN_BYPASS_MASK, 0xffff); | 685 | mt76_wr(dev, MT_BCN_BYPASS_MASK, 0xffff); |
| 686 | 686 | ||
| 687 | for (i = 0; i < 8; i++) | 687 | for (i = 0; i < 8; i++) |
| @@ -704,9 +704,6 @@ void mt76x02_bss_info_changed(struct ieee80211_hw *hw, | |||
| 704 | if (changed & BSS_CHANGED_BSSID) | 704 | if (changed & BSS_CHANGED_BSSID) |
| 705 | mt76x02_mac_set_bssid(dev, mvif->idx, info->bssid); | 705 | mt76x02_mac_set_bssid(dev, mvif->idx, info->bssid); |
| 706 | 706 | ||
| 707 | if (changed & BSS_CHANGED_BEACON_ENABLED) | ||
| 708 | mt76x02_mac_set_beacon_enable(dev, vif, info->enable_beacon); | ||
| 709 | |||
| 710 | if (changed & BSS_CHANGED_HT || changed & BSS_CHANGED_ERP_CTS_PROT) | 707 | if (changed & BSS_CHANGED_HT || changed & BSS_CHANGED_ERP_CTS_PROT) |
| 711 | mt76x02_mac_set_tx_protection(dev, info->use_cts_prot, | 708 | mt76x02_mac_set_tx_protection(dev, info->use_cts_prot, |
| 712 | info->ht_operation_mode); | 709 | info->ht_operation_mode); |
| @@ -716,9 +713,11 @@ void mt76x02_bss_info_changed(struct ieee80211_hw *hw, | |||
| 716 | MT_BEACON_TIME_CFG_INTVAL, | 713 | MT_BEACON_TIME_CFG_INTVAL, |
| 717 | info->beacon_int << 4); | 714 | info->beacon_int << 4); |
| 718 | dev->beacon_int = info->beacon_int; | 715 | dev->beacon_int = info->beacon_int; |
| 719 | dev->tbtt_count = 0; | ||
| 720 | } | 716 | } |
| 721 | 717 | ||
| 718 | if (changed & BSS_CHANGED_BEACON_ENABLED) | ||
| 719 | mt76x02_mac_set_beacon_enable(dev, vif, info->enable_beacon); | ||
| 720 | |||
| 722 | if (changed & BSS_CHANGED_ERP_PREAMBLE) | 721 | if (changed & BSS_CHANGED_ERP_PREAMBLE) |
| 723 | mt76x02_mac_set_short_preamble(dev, info->use_short_preamble); | 722 | mt76x02_mac_set_short_preamble(dev, info->use_short_preamble); |
| 724 | 723 | ||
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/mac.c b/drivers/net/wireless/mediatek/mt76/mt76x2/mac.c index e25905c91ee2..e99d4c9bd428 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mac.c | |||
| @@ -23,6 +23,9 @@ void mt76x2_mac_stop(struct mt76x02_dev *dev, bool force) | |||
| 23 | u32 rts_cfg; | 23 | u32 rts_cfg; |
| 24 | int i; | 24 | int i; |
| 25 | 25 | ||
| 26 | mt76_clear(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN); | ||
| 27 | mt76_clear(dev, MT_TXOP_HLDR_ET, MT_TXOP_HLDR_TX40M_BLK_EN); | ||
| 28 | |||
| 26 | mt76_wr(dev, MT_MAC_SYS_CTRL, 0); | 29 | mt76_wr(dev, MT_MAC_SYS_CTRL, 0); |
| 27 | 30 | ||
| 28 | rts_cfg = mt76_rr(dev, MT_TX_RTS_CFG); | 31 | rts_cfg = mt76_rr(dev, MT_TX_RTS_CFG); |
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/mac.h b/drivers/net/wireless/mediatek/mt76/mt76x2/mac.h index 4c8e20bce920..42ff221d7706 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mac.h | |||
| @@ -25,6 +25,12 @@ struct mt76x02_vif; | |||
| 25 | 25 | ||
| 26 | int mt76x2_mac_start(struct mt76x02_dev *dev); | 26 | int mt76x2_mac_start(struct mt76x02_dev *dev); |
| 27 | void mt76x2_mac_stop(struct mt76x02_dev *dev, bool force); | 27 | void mt76x2_mac_stop(struct mt76x02_dev *dev, bool force); |
| 28 | void mt76x2_mac_resume(struct mt76x02_dev *dev); | 28 | |
| 29 | static inline void mt76x2_mac_resume(struct mt76x02_dev *dev) | ||
| 30 | { | ||
| 31 | mt76_wr(dev, MT_MAC_SYS_CTRL, | ||
| 32 | MT_MAC_SYS_CTRL_ENABLE_TX | | ||
| 33 | MT_MAC_SYS_CTRL_ENABLE_RX); | ||
| 34 | } | ||
| 29 | 35 | ||
| 30 | #endif | 36 | #endif |
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2u.h b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2u.h index 787cdfdf5db5..76cb1f84eff5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2u.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/mt76x2u.h | |||
| @@ -35,7 +35,6 @@ void mt76x2u_cleanup(struct mt76x02_dev *dev); | |||
| 35 | void mt76x2u_stop_hw(struct mt76x02_dev *dev); | 35 | void mt76x2u_stop_hw(struct mt76x02_dev *dev); |
| 36 | 36 | ||
| 37 | int mt76x2u_mac_reset(struct mt76x02_dev *dev); | 37 | int mt76x2u_mac_reset(struct mt76x02_dev *dev); |
| 38 | void mt76x2u_mac_resume(struct mt76x02_dev *dev); | ||
| 39 | int mt76x2u_mac_start(struct mt76x02_dev *dev); | 38 | int mt76x2u_mac_start(struct mt76x02_dev *dev); |
| 40 | int mt76x2u_mac_stop(struct mt76x02_dev *dev); | 39 | int mt76x2u_mac_stop(struct mt76x02_dev *dev); |
| 41 | 40 | ||
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c index d4e3d7c11d74..984d9c4c2e1a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c | |||
| @@ -173,13 +173,6 @@ int mt76x2_mac_start(struct mt76x02_dev *dev) | |||
| 173 | return 0; | 173 | return 0; |
| 174 | } | 174 | } |
| 175 | 175 | ||
| 176 | void mt76x2_mac_resume(struct mt76x02_dev *dev) | ||
| 177 | { | ||
| 178 | mt76_wr(dev, MT_MAC_SYS_CTRL, | ||
| 179 | MT_MAC_SYS_CTRL_ENABLE_TX | | ||
| 180 | MT_MAC_SYS_CTRL_ENABLE_RX); | ||
| 181 | } | ||
| 182 | |||
| 183 | static void | 176 | static void |
| 184 | mt76x2_power_on_rf_patch(struct mt76x02_dev *dev) | 177 | mt76x2_power_on_rf_patch(struct mt76x02_dev *dev) |
| 185 | { | 178 | { |
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c index 97ec575699d0..cc1aebcb0696 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_phy.c | |||
| @@ -74,6 +74,7 @@ mt76x2_phy_channel_calibrate(struct mt76x02_dev *dev, bool mac_stopped) | |||
| 74 | mt76x2_mac_resume(dev); | 74 | mt76x2_mac_resume(dev); |
| 75 | 75 | ||
| 76 | mt76x2_apply_gain_adj(dev); | 76 | mt76x2_apply_gain_adj(dev); |
| 77 | mt76x02_edcca_init(dev, true); | ||
| 77 | 78 | ||
| 78 | dev->cal.channel_cal_done = true; | 79 | dev->cal.channel_cal_done = true; |
| 79 | } | 80 | } |
| @@ -240,10 +241,8 @@ int mt76x2_phy_set_channel(struct mt76x02_dev *dev, | |||
| 240 | mt76_wr(dev, MT_BBP(AGC, 2), 0x00007070); | 241 | mt76_wr(dev, MT_BBP(AGC, 2), 0x00007070); |
| 241 | mt76_wr(dev, MT_TXOP_CTRL_CFG, 0x04101B3F); | 242 | mt76_wr(dev, MT_TXOP_CTRL_CFG, 0x04101B3F); |
| 242 | 243 | ||
| 243 | if (scan) { | 244 | if (scan) |
| 244 | mt76x02_edcca_init(dev, false); | ||
| 245 | return 0; | 245 | return 0; |
| 246 | } | ||
| 247 | 246 | ||
| 248 | mt76x2_phy_channel_calibrate(dev, true); | 247 | mt76x2_phy_channel_calibrate(dev, true); |
| 249 | mt76x02_init_agc_gain(dev); | 248 | mt76x02_init_agc_gain(dev); |
| @@ -256,8 +255,6 @@ int mt76x2_phy_set_channel(struct mt76x02_dev *dev, | |||
| 256 | 0x38); | 255 | 0x38); |
| 257 | } | 256 | } |
| 258 | 257 | ||
| 259 | mt76x02_edcca_init(dev, true); | ||
| 260 | |||
| 261 | ieee80211_queue_delayed_work(mt76_hw(dev), &dev->cal_work, | 258 | ieee80211_queue_delayed_work(mt76_hw(dev), &dev->cal_work, |
| 262 | MT_CALIBRATE_INTERVAL); | 259 | MT_CALIBRATE_INTERVAL); |
| 263 | 260 | ||
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c index f81a85e96922..ddb6b2c48e01 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c | |||
| @@ -100,11 +100,9 @@ static int __maybe_unused mt76x2u_suspend(struct usb_interface *intf, | |||
| 100 | pm_message_t state) | 100 | pm_message_t state) |
| 101 | { | 101 | { |
| 102 | struct mt76x02_dev *dev = usb_get_intfdata(intf); | 102 | struct mt76x02_dev *dev = usb_get_intfdata(intf); |
| 103 | struct mt76_usb *usb = &dev->mt76.usb; | ||
| 104 | 103 | ||
| 105 | mt76u_stop_queues(&dev->mt76); | 104 | mt76u_stop_queues(&dev->mt76); |
| 106 | mt76x2u_stop_hw(dev); | 105 | mt76x2u_stop_hw(dev); |
| 107 | usb_kill_urb(usb->mcu.res.urb); | ||
| 108 | 106 | ||
| 109 | return 0; | 107 | return 0; |
| 110 | } | 108 | } |
| @@ -115,15 +113,6 @@ static int __maybe_unused mt76x2u_resume(struct usb_interface *intf) | |||
| 115 | struct mt76_usb *usb = &dev->mt76.usb; | 113 | struct mt76_usb *usb = &dev->mt76.usb; |
| 116 | int err; | 114 | int err; |
| 117 | 115 | ||
| 118 | reinit_completion(&usb->mcu.cmpl); | ||
| 119 | err = mt76u_submit_buf(&dev->mt76, USB_DIR_IN, | ||
| 120 | MT_EP_IN_CMD_RESP, | ||
| 121 | &usb->mcu.res, GFP_KERNEL, | ||
| 122 | mt76u_mcu_complete_urb, | ||
| 123 | &usb->mcu.cmpl); | ||
| 124 | if (err < 0) | ||
| 125 | goto err; | ||
| 126 | |||
| 127 | err = mt76u_submit_rx_buffers(&dev->mt76); | 116 | err = mt76u_submit_rx_buffers(&dev->mt76); |
| 128 | if (err < 0) | 117 | if (err < 0) |
| 129 | goto err; | 118 | goto err; |
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c index 090aaf71b3ef..1da90e58d942 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c | |||
| @@ -214,10 +214,6 @@ int mt76x2u_register_device(struct mt76x02_dev *dev) | |||
| 214 | if (err < 0) | 214 | if (err < 0) |
| 215 | goto fail; | 215 | goto fail; |
| 216 | 216 | ||
| 217 | err = mt76u_mcu_init_rx(&dev->mt76); | ||
| 218 | if (err < 0) | ||
| 219 | goto fail; | ||
| 220 | |||
| 221 | err = mt76x2u_init_hardware(dev); | 217 | err = mt76x2u_init_hardware(dev); |
| 222 | if (err < 0) | 218 | if (err < 0) |
| 223 | goto fail; | 219 | goto fail; |
| @@ -259,5 +255,4 @@ void mt76x2u_cleanup(struct mt76x02_dev *dev) | |||
| 259 | mt76x02_mcu_set_radio_state(dev, false); | 255 | mt76x02_mcu_set_radio_state(dev, false); |
| 260 | mt76x2u_stop_hw(dev); | 256 | mt76x2u_stop_hw(dev); |
| 261 | mt76u_queues_deinit(&dev->mt76); | 257 | mt76u_queues_deinit(&dev->mt76); |
| 262 | mt76u_mcu_deinit(&dev->mt76); | ||
| 263 | } | 258 | } |
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c index db2194a92e67..5e84b4535cb1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mac.c | |||
| @@ -143,8 +143,8 @@ int mt76x2u_mac_stop(struct mt76x02_dev *dev) | |||
| 143 | rts_cfg = mt76_rr(dev, MT_TX_RTS_CFG); | 143 | rts_cfg = mt76_rr(dev, MT_TX_RTS_CFG); |
| 144 | mt76_wr(dev, MT_TX_RTS_CFG, rts_cfg & ~MT_TX_RTS_CFG_RETRY_LIMIT); | 144 | mt76_wr(dev, MT_TX_RTS_CFG, rts_cfg & ~MT_TX_RTS_CFG_RETRY_LIMIT); |
| 145 | 145 | ||
| 146 | mt76_clear(dev, MT_TXOP_CTRL_CFG, BIT(20)); | 146 | mt76_clear(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN); |
| 147 | mt76_clear(dev, MT_TXOP_HLDR_ET, BIT(1)); | 147 | mt76_clear(dev, MT_TXOP_HLDR_ET, MT_TXOP_HLDR_TX40M_BLK_EN); |
| 148 | 148 | ||
| 149 | /* wait tx dma to stop */ | 149 | /* wait tx dma to stop */ |
| 150 | for (i = 0; i < 2000; i++) { | 150 | for (i = 0; i < 2000; i++) { |
| @@ -211,12 +211,3 @@ int mt76x2u_mac_stop(struct mt76x02_dev *dev) | |||
| 211 | 211 | ||
| 212 | return 0; | 212 | return 0; |
| 213 | } | 213 | } |
| 214 | |||
| 215 | void mt76x2u_mac_resume(struct mt76x02_dev *dev) | ||
| 216 | { | ||
| 217 | mt76_wr(dev, MT_MAC_SYS_CTRL, | ||
| 218 | MT_MAC_SYS_CTRL_ENABLE_TX | | ||
| 219 | MT_MAC_SYS_CTRL_ENABLE_RX); | ||
| 220 | mt76_set(dev, MT_TXOP_CTRL_CFG, BIT(20)); | ||
| 221 | mt76_set(dev, MT_TXOP_HLDR_ET, BIT(1)); | ||
| 222 | } | ||
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c index 10633b8de8e8..2ac78e4dc41a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_main.c | |||
| @@ -57,13 +57,12 @@ mt76x2u_set_channel(struct mt76x02_dev *dev, | |||
| 57 | 57 | ||
| 58 | mt76_set_channel(&dev->mt76); | 58 | mt76_set_channel(&dev->mt76); |
| 59 | 59 | ||
| 60 | mt76_clear(dev, MT_TXOP_CTRL_CFG, BIT(20)); | ||
| 61 | mt76_clear(dev, MT_TXOP_HLDR_ET, BIT(1)); | ||
| 62 | mt76x2_mac_stop(dev, false); | 60 | mt76x2_mac_stop(dev, false); |
| 63 | 61 | ||
| 64 | err = mt76x2u_phy_set_channel(dev, chandef); | 62 | err = mt76x2u_phy_set_channel(dev, chandef); |
| 65 | 63 | ||
| 66 | mt76x2u_mac_resume(dev); | 64 | mt76x2_mac_resume(dev); |
| 65 | mt76x02_edcca_init(dev, true); | ||
| 67 | 66 | ||
| 68 | clear_bit(MT76_RESET, &dev->mt76.state); | 67 | clear_bit(MT76_RESET, &dev->mt76.state); |
| 69 | mt76_txq_schedule_all(&dev->mt76); | 68 | mt76_txq_schedule_all(&dev->mt76); |
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c index 11d414d86c68..07f67cb6854c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_phy.c | |||
| @@ -43,8 +43,9 @@ mt76x2u_phy_channel_calibrate(struct mt76x02_dev *dev, bool mac_stopped) | |||
| 43 | mt76x02_mcu_calibrate(dev, MCU_CAL_TX_SHAPING, 0); | 43 | mt76x02_mcu_calibrate(dev, MCU_CAL_TX_SHAPING, 0); |
| 44 | 44 | ||
| 45 | if (!mac_stopped) | 45 | if (!mac_stopped) |
| 46 | mt76x2u_mac_resume(dev); | 46 | mt76x2_mac_resume(dev); |
| 47 | mt76x2_apply_gain_adj(dev); | 47 | mt76x2_apply_gain_adj(dev); |
| 48 | mt76x02_edcca_init(dev, true); | ||
| 48 | 49 | ||
| 49 | dev->cal.channel_cal_done = true; | 50 | dev->cal.channel_cal_done = true; |
| 50 | } | 51 | } |
diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index 78191968b4fa..ae6ada370597 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c | |||
| @@ -324,66 +324,61 @@ mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76u_buf *buf, | |||
| 324 | } | 324 | } |
| 325 | 325 | ||
| 326 | static int | 326 | static int |
| 327 | mt76u_buf_alloc_sg(struct mt76_dev *dev, struct mt76u_buf *buf, | 327 | mt76u_refill_rx(struct mt76_dev *dev, struct mt76_queue *q, |
| 328 | int nsgs, int len, int sglen, gfp_t gfp) | 328 | struct mt76u_buf *buf, int nsgs, gfp_t gfp) |
| 329 | { | 329 | { |
| 330 | buf->urb = usb_alloc_urb(0, gfp); | 330 | if (dev->usb.sg_en) { |
| 331 | if (!buf->urb) | 331 | return mt76u_fill_rx_sg(dev, buf, nsgs, q->buf_size, |
| 332 | return -ENOMEM; | 332 | SKB_WITH_OVERHEAD(q->buf_size)); |
| 333 | 333 | } else { | |
| 334 | buf->urb->sg = devm_kcalloc(dev->dev, nsgs, sizeof(*buf->urb->sg), | 334 | buf->buf = page_frag_alloc(&q->rx_page, q->buf_size, gfp); |
| 335 | gfp); | 335 | return buf->buf ? 0 : -ENOMEM; |
| 336 | if (!buf->urb->sg) | 336 | } |
| 337 | return -ENOMEM; | ||
| 338 | |||
| 339 | sg_init_table(buf->urb->sg, nsgs); | ||
| 340 | buf->dev = dev; | ||
| 341 | |||
| 342 | return mt76u_fill_rx_sg(dev, buf, nsgs, len, sglen); | ||
| 343 | } | 337 | } |
| 344 | 338 | ||
| 345 | int mt76u_buf_alloc(struct mt76_dev *dev, struct mt76u_buf *buf, | 339 | static int |
| 346 | int len, int data_len, gfp_t gfp) | 340 | mt76u_buf_alloc(struct mt76_dev *dev, struct mt76u_buf *buf) |
| 347 | { | 341 | { |
| 348 | struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; | 342 | struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; |
| 349 | 343 | ||
| 350 | buf->urb = usb_alloc_urb(0, gfp); | 344 | buf->len = SKB_WITH_OVERHEAD(q->buf_size); |
| 345 | buf->dev = dev; | ||
| 346 | |||
| 347 | buf->urb = usb_alloc_urb(0, GFP_KERNEL); | ||
| 351 | if (!buf->urb) | 348 | if (!buf->urb) |
| 352 | return -ENOMEM; | 349 | return -ENOMEM; |
| 353 | 350 | ||
| 354 | buf->buf = page_frag_alloc(&q->rx_page, len, gfp); | 351 | if (dev->usb.sg_en) { |
| 355 | if (!buf->buf) | 352 | buf->urb->sg = devm_kcalloc(dev->dev, MT_SG_MAX_SIZE, |
| 356 | return -ENOMEM; | 353 | sizeof(*buf->urb->sg), |
| 354 | GFP_KERNEL); | ||
| 355 | if (!buf->urb->sg) | ||
| 356 | return -ENOMEM; | ||
| 357 | 357 | ||
| 358 | buf->len = data_len; | 358 | sg_init_table(buf->urb->sg, MT_SG_MAX_SIZE); |
| 359 | buf->dev = dev; | 359 | } |
| 360 | 360 | ||
| 361 | return 0; | 361 | return mt76u_refill_rx(dev, q, buf, MT_SG_MAX_SIZE, GFP_KERNEL); |
| 362 | } | 362 | } |
| 363 | 363 | ||
| 364 | void mt76u_buf_free(struct mt76u_buf *buf) | 364 | static void mt76u_buf_free(struct mt76u_buf *buf) |
| 365 | { | 365 | { |
| 366 | struct urb *urb = buf->urb; | 366 | struct urb *urb = buf->urb; |
| 367 | struct scatterlist *sg; | ||
| 368 | int i; | 367 | int i; |
| 369 | 368 | ||
| 370 | for (i = 0; i < urb->num_sgs; i++) { | 369 | for (i = 0; i < urb->num_sgs; i++) |
| 371 | sg = &urb->sg[i]; | 370 | skb_free_frag(sg_virt(&urb->sg[i])); |
| 372 | if (!sg) | ||
| 373 | continue; | ||
| 374 | 371 | ||
| 375 | skb_free_frag(sg_virt(sg)); | ||
| 376 | } | ||
| 377 | if (buf->buf) | 372 | if (buf->buf) |
| 378 | skb_free_frag(buf->buf); | 373 | skb_free_frag(buf->buf); |
| 379 | 374 | ||
| 380 | usb_free_urb(buf->urb); | 375 | usb_free_urb(buf->urb); |
| 381 | } | 376 | } |
| 382 | EXPORT_SYMBOL_GPL(mt76u_buf_free); | ||
| 383 | 377 | ||
| 384 | int mt76u_submit_buf(struct mt76_dev *dev, int dir, int index, | 378 | static void |
| 385 | struct mt76u_buf *buf, gfp_t gfp, | 379 | mt76u_fill_bulk_urb(struct mt76_dev *dev, int dir, int index, |
| 386 | usb_complete_t complete_fn, void *context) | 380 | struct mt76u_buf *buf, usb_complete_t complete_fn, |
| 381 | void *context) | ||
| 387 | { | 382 | { |
| 388 | struct usb_interface *intf = to_usb_interface(dev->dev); | 383 | struct usb_interface *intf = to_usb_interface(dev->dev); |
| 389 | struct usb_device *udev = interface_to_usbdev(intf); | 384 | struct usb_device *udev = interface_to_usbdev(intf); |
| @@ -397,11 +392,19 @@ int mt76u_submit_buf(struct mt76_dev *dev, int dir, int index, | |||
| 397 | 392 | ||
| 398 | usb_fill_bulk_urb(buf->urb, udev, pipe, data, buf->len, | 393 | usb_fill_bulk_urb(buf->urb, udev, pipe, data, buf->len, |
| 399 | complete_fn, context); | 394 | complete_fn, context); |
| 395 | } | ||
| 396 | |||
| 397 | static int | ||
| 398 | mt76u_submit_buf(struct mt76_dev *dev, int dir, int index, | ||
| 399 | struct mt76u_buf *buf, gfp_t gfp, | ||
| 400 | usb_complete_t complete_fn, void *context) | ||
| 401 | { | ||
| 402 | mt76u_fill_bulk_urb(dev, dir, index, buf, complete_fn, | ||
| 403 | context); | ||
| 400 | trace_submit_urb(dev, buf->urb); | 404 | trace_submit_urb(dev, buf->urb); |
| 401 | 405 | ||
| 402 | return usb_submit_urb(buf->urb, gfp); | 406 | return usb_submit_urb(buf->urb, gfp); |
| 403 | } | 407 | } |
| 404 | EXPORT_SYMBOL_GPL(mt76u_submit_buf); | ||
| 405 | 408 | ||
| 406 | static inline struct mt76u_buf | 409 | static inline struct mt76u_buf |
| 407 | *mt76u_get_next_rx_entry(struct mt76_queue *q) | 410 | *mt76u_get_next_rx_entry(struct mt76_queue *q) |
| @@ -464,7 +467,7 @@ mt76u_process_rx_entry(struct mt76_dev *dev, struct mt76u_buf *buf) | |||
| 464 | __skb_put(skb, data_len); | 467 | __skb_put(skb, data_len); |
| 465 | len -= data_len; | 468 | len -= data_len; |
| 466 | 469 | ||
| 467 | while (len > 0 && urb->num_sgs) { | 470 | while (len > 0 && nsgs < urb->num_sgs) { |
| 468 | data_len = min_t(int, len, urb->sg[nsgs].length); | 471 | data_len = min_t(int, len, urb->sg[nsgs].length); |
| 469 | skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, | 472 | skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, |
| 470 | sg_page(&urb->sg[nsgs]), | 473 | sg_page(&urb->sg[nsgs]), |
| @@ -510,20 +513,6 @@ out: | |||
| 510 | spin_unlock_irqrestore(&q->lock, flags); | 513 | spin_unlock_irqrestore(&q->lock, flags); |
| 511 | } | 514 | } |
| 512 | 515 | ||
| 513 | static int | ||
| 514 | mt76u_refill_rx(struct mt76_dev *dev, struct mt76_queue *q, | ||
| 515 | struct mt76u_buf *buf, int nsgs) | ||
| 516 | { | ||
| 517 | if (dev->usb.sg_en) { | ||
| 518 | return mt76u_fill_rx_sg(dev, buf, nsgs, q->buf_size, | ||
| 519 | SKB_WITH_OVERHEAD(q->buf_size)); | ||
| 520 | } else { | ||
| 521 | buf->buf = page_frag_alloc(&q->rx_page, q->buf_size, | ||
| 522 | GFP_ATOMIC); | ||
| 523 | return buf->buf ? 0 : -ENOMEM; | ||
| 524 | } | ||
| 525 | } | ||
| 526 | |||
| 527 | static void mt76u_rx_tasklet(unsigned long data) | 516 | static void mt76u_rx_tasklet(unsigned long data) |
| 528 | { | 517 | { |
| 529 | struct mt76_dev *dev = (struct mt76_dev *)data; | 518 | struct mt76_dev *dev = (struct mt76_dev *)data; |
| @@ -540,7 +529,8 @@ static void mt76u_rx_tasklet(unsigned long data) | |||
| 540 | 529 | ||
| 541 | count = mt76u_process_rx_entry(dev, buf); | 530 | count = mt76u_process_rx_entry(dev, buf); |
| 542 | if (count > 0) { | 531 | if (count > 0) { |
| 543 | err = mt76u_refill_rx(dev, q, buf, count); | 532 | err = mt76u_refill_rx(dev, q, buf, count, |
| 533 | GFP_ATOMIC); | ||
| 544 | if (err < 0) | 534 | if (err < 0) |
| 545 | break; | 535 | break; |
| 546 | } | 536 | } |
| @@ -577,9 +567,14 @@ EXPORT_SYMBOL_GPL(mt76u_submit_rx_buffers); | |||
| 577 | 567 | ||
| 578 | static int mt76u_alloc_rx(struct mt76_dev *dev) | 568 | static int mt76u_alloc_rx(struct mt76_dev *dev) |
| 579 | { | 569 | { |
| 570 | struct mt76_usb *usb = &dev->usb; | ||
| 580 | struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; | 571 | struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN]; |
| 581 | int i, err; | 572 | int i, err; |
| 582 | 573 | ||
| 574 | usb->mcu.data = devm_kmalloc(dev->dev, MCU_RESP_URB_SIZE, GFP_KERNEL); | ||
| 575 | if (!usb->mcu.data) | ||
| 576 | return -ENOMEM; | ||
| 577 | |||
| 583 | spin_lock_init(&q->rx_page_lock); | 578 | spin_lock_init(&q->rx_page_lock); |
| 584 | spin_lock_init(&q->lock); | 579 | spin_lock_init(&q->lock); |
| 585 | q->entry = devm_kcalloc(dev->dev, | 580 | q->entry = devm_kcalloc(dev->dev, |
| @@ -591,16 +586,7 @@ static int mt76u_alloc_rx(struct mt76_dev *dev) | |||
| 591 | q->buf_size = dev->usb.sg_en ? MT_RX_BUF_SIZE : PAGE_SIZE; | 586 | q->buf_size = dev->usb.sg_en ? MT_RX_BUF_SIZE : PAGE_SIZE; |
| 592 | q->ndesc = MT_NUM_RX_ENTRIES; | 587 | q->ndesc = MT_NUM_RX_ENTRIES; |
| 593 | for (i = 0; i < q->ndesc; i++) { | 588 | for (i = 0; i < q->ndesc; i++) { |
| 594 | if (dev->usb.sg_en) | 589 | err = mt76u_buf_alloc(dev, &q->entry[i].ubuf); |
| 595 | err = mt76u_buf_alloc_sg(dev, &q->entry[i].ubuf, | ||
| 596 | MT_SG_MAX_SIZE, q->buf_size, | ||
| 597 | SKB_WITH_OVERHEAD(q->buf_size), | ||
| 598 | GFP_KERNEL); | ||
| 599 | else | ||
| 600 | err = mt76u_buf_alloc(dev, &q->entry[i].ubuf, | ||
| 601 | q->buf_size, | ||
| 602 | SKB_WITH_OVERHEAD(q->buf_size), | ||
| 603 | GFP_KERNEL); | ||
| 604 | if (err < 0) | 590 | if (err < 0) |
| 605 | return err; | 591 | return err; |
| 606 | } | 592 | } |
| @@ -724,21 +710,15 @@ static void mt76u_complete_tx(struct urb *urb) | |||
| 724 | } | 710 | } |
| 725 | 711 | ||
| 726 | static int | 712 | static int |
| 727 | mt76u_tx_build_sg(struct sk_buff *skb, struct urb *urb) | 713 | mt76u_tx_build_sg(struct mt76_dev *dev, struct sk_buff *skb, |
| 714 | struct urb *urb) | ||
| 728 | { | 715 | { |
| 729 | int nsgs = 1 + skb_shinfo(skb)->nr_frags; | 716 | if (!dev->usb.sg_en) |
| 730 | struct sk_buff *iter; | 717 | return 0; |
| 731 | |||
| 732 | skb_walk_frags(skb, iter) | ||
| 733 | nsgs += 1 + skb_shinfo(iter)->nr_frags; | ||
| 734 | |||
| 735 | memset(urb->sg, 0, sizeof(*urb->sg) * MT_SG_MAX_SIZE); | ||
| 736 | |||
| 737 | nsgs = min_t(int, MT_SG_MAX_SIZE, nsgs); | ||
| 738 | sg_init_marker(urb->sg, nsgs); | ||
| 739 | urb->num_sgs = nsgs; | ||
| 740 | 718 | ||
| 741 | return skb_to_sgvec_nomark(skb, urb->sg, 0, skb->len); | 719 | sg_init_table(urb->sg, MT_SG_MAX_SIZE); |
| 720 | urb->num_sgs = skb_to_sgvec(skb, urb->sg, 0, skb->len); | ||
| 721 | return urb->num_sgs; | ||
| 742 | } | 722 | } |
| 743 | 723 | ||
| 744 | static int | 724 | static int |
| @@ -746,12 +726,8 @@ mt76u_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, | |||
| 746 | struct sk_buff *skb, struct mt76_wcid *wcid, | 726 | struct sk_buff *skb, struct mt76_wcid *wcid, |
| 747 | struct ieee80211_sta *sta) | 727 | struct ieee80211_sta *sta) |
| 748 | { | 728 | { |
| 749 | struct usb_interface *intf = to_usb_interface(dev->dev); | ||
| 750 | struct usb_device *udev = interface_to_usbdev(intf); | ||
| 751 | u8 *data = NULL, ep = q2ep(q->hw_idx); | ||
| 752 | struct mt76u_buf *buf; | 729 | struct mt76u_buf *buf; |
| 753 | u16 idx = q->tail; | 730 | u16 idx = q->tail; |
| 754 | unsigned int pipe; | ||
| 755 | int err; | 731 | int err; |
| 756 | 732 | ||
| 757 | if (q->queued == q->ndesc) | 733 | if (q->queued == q->ndesc) |
| @@ -763,19 +739,16 @@ mt76u_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q, | |||
| 763 | return err; | 739 | return err; |
| 764 | 740 | ||
| 765 | buf = &q->entry[idx].ubuf; | 741 | buf = &q->entry[idx].ubuf; |
| 742 | buf->buf = skb->data; | ||
| 743 | buf->len = skb->len; | ||
| 766 | buf->done = false; | 744 | buf->done = false; |
| 767 | 745 | ||
| 768 | if (dev->usb.sg_en) { | 746 | err = mt76u_tx_build_sg(dev, skb, buf->urb); |
| 769 | err = mt76u_tx_build_sg(skb, buf->urb); | 747 | if (err < 0) |
| 770 | if (err < 0) | 748 | return err; |
| 771 | return err; | ||
| 772 | } else { | ||
| 773 | data = skb->data; | ||
| 774 | } | ||
| 775 | 749 | ||
| 776 | pipe = usb_sndbulkpipe(udev, dev->usb.out_ep[ep]); | 750 | mt76u_fill_bulk_urb(dev, USB_DIR_OUT, q2ep(q->hw_idx), |
| 777 | usb_fill_bulk_urb(buf->urb, udev, pipe, data, skb->len, | 751 | buf, mt76u_complete_tx, buf); |
| 778 | mt76u_complete_tx, buf); | ||
| 779 | 752 | ||
| 780 | q->tail = (q->tail + 1) % q->ndesc; | 753 | q->tail = (q->tail + 1) % q->ndesc; |
| 781 | q->entry[idx].skb = skb; | 754 | q->entry[idx].skb = skb; |
| @@ -933,7 +906,6 @@ int mt76u_init(struct mt76_dev *dev, | |||
| 933 | INIT_DELAYED_WORK(&usb->stat_work, mt76u_tx_status_data); | 906 | INIT_DELAYED_WORK(&usb->stat_work, mt76u_tx_status_data); |
| 934 | skb_queue_head_init(&dev->rx_skb[MT_RXQ_MAIN]); | 907 | skb_queue_head_init(&dev->rx_skb[MT_RXQ_MAIN]); |
| 935 | 908 | ||
| 936 | init_completion(&usb->mcu.cmpl); | ||
| 937 | mutex_init(&usb->mcu.mutex); | 909 | mutex_init(&usb->mcu.mutex); |
| 938 | 910 | ||
| 939 | mutex_init(&usb->usb_ctrl_mtx); | 911 | mutex_init(&usb->usb_ctrl_mtx); |
diff --git a/drivers/net/wireless/mediatek/mt76/usb_mcu.c b/drivers/net/wireless/mediatek/mt76/usb_mcu.c deleted file mode 100644 index 72c8607da4b4..000000000000 --- a/drivers/net/wireless/mediatek/mt76/usb_mcu.c +++ /dev/null | |||
| @@ -1,57 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
| 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
| 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
| 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include "mt76.h" | ||
| 18 | |||
| 19 | void mt76u_mcu_complete_urb(struct urb *urb) | ||
| 20 | { | ||
| 21 | struct completion *cmpl = urb->context; | ||
| 22 | |||
| 23 | complete(cmpl); | ||
| 24 | } | ||
| 25 | EXPORT_SYMBOL_GPL(mt76u_mcu_complete_urb); | ||
| 26 | |||
| 27 | int mt76u_mcu_init_rx(struct mt76_dev *dev) | ||
| 28 | { | ||
| 29 | struct mt76_usb *usb = &dev->usb; | ||
| 30 | int err; | ||
| 31 | |||
| 32 | err = mt76u_buf_alloc(dev, &usb->mcu.res, MCU_RESP_URB_SIZE, | ||
| 33 | MCU_RESP_URB_SIZE, GFP_KERNEL); | ||
| 34 | if (err < 0) | ||
| 35 | return err; | ||
| 36 | |||
| 37 | err = mt76u_submit_buf(dev, USB_DIR_IN, MT_EP_IN_CMD_RESP, | ||
| 38 | &usb->mcu.res, GFP_KERNEL, | ||
| 39 | mt76u_mcu_complete_urb, | ||
| 40 | &usb->mcu.cmpl); | ||
| 41 | if (err < 0) | ||
| 42 | mt76u_buf_free(&usb->mcu.res); | ||
| 43 | |||
| 44 | return err; | ||
| 45 | } | ||
| 46 | EXPORT_SYMBOL_GPL(mt76u_mcu_init_rx); | ||
| 47 | |||
| 48 | void mt76u_mcu_deinit(struct mt76_dev *dev) | ||
| 49 | { | ||
| 50 | struct mt76u_buf *buf = &dev->usb.mcu.res; | ||
| 51 | |||
| 52 | if (buf->urb) { | ||
| 53 | usb_kill_urb(buf->urb); | ||
| 54 | mt76u_buf_free(buf); | ||
| 55 | } | ||
| 56 | } | ||
| 57 | EXPORT_SYMBOL_GPL(mt76u_mcu_deinit); | ||
diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c index 672c0b73cb65..217d2a7a43c7 100644 --- a/drivers/net/wireless/realtek/rtlwifi/base.c +++ b/drivers/net/wireless/realtek/rtlwifi/base.c | |||
| @@ -430,6 +430,7 @@ static void _rtl_init_mac80211(struct ieee80211_hw *hw) | |||
| 430 | SET_IEEE80211_PERM_ADDR(hw, rtlefuse->dev_addr); | 430 | SET_IEEE80211_PERM_ADDR(hw, rtlefuse->dev_addr); |
| 431 | } else { | 431 | } else { |
| 432 | u8 rtlmac1[] = { 0x00, 0xe0, 0x4c, 0x81, 0x92, 0x00 }; | 432 | u8 rtlmac1[] = { 0x00, 0xe0, 0x4c, 0x81, 0x92, 0x00 }; |
| 433 | |||
| 433 | get_random_bytes((rtlmac1 + (ETH_ALEN - 1)), 1); | 434 | get_random_bytes((rtlmac1 + (ETH_ALEN - 1)), 1); |
| 434 | SET_IEEE80211_PERM_ADDR(hw, rtlmac1); | 435 | SET_IEEE80211_PERM_ADDR(hw, rtlmac1); |
| 435 | } | 436 | } |
| @@ -459,7 +460,6 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw) | |||
| 459 | (void *)rtl_fwevt_wq_callback); | 460 | (void *)rtl_fwevt_wq_callback); |
| 460 | INIT_DELAYED_WORK(&rtlpriv->works.c2hcmd_wq, | 461 | INIT_DELAYED_WORK(&rtlpriv->works.c2hcmd_wq, |
| 461 | (void *)rtl_c2hcmd_wq_callback); | 462 | (void *)rtl_c2hcmd_wq_callback); |
| 462 | |||
| 463 | } | 463 | } |
| 464 | 464 | ||
| 465 | void rtl_deinit_deferred_work(struct ieee80211_hw *hw, bool ips_wq) | 465 | void rtl_deinit_deferred_work(struct ieee80211_hw *hw, bool ips_wq) |
| @@ -618,6 +618,7 @@ static void _rtl_query_shortgi(struct ieee80211_hw *hw, | |||
| 618 | u8 rate_flag = info->control.rates[0].flags; | 618 | u8 rate_flag = info->control.rates[0].flags; |
| 619 | u8 sgi_40 = 0, sgi_20 = 0, bw_40 = 0; | 619 | u8 sgi_40 = 0, sgi_20 = 0, bw_40 = 0; |
| 620 | u8 sgi_80 = 0, bw_80 = 0; | 620 | u8 sgi_80 = 0, bw_80 = 0; |
| 621 | |||
| 621 | tcb_desc->use_shortgi = false; | 622 | tcb_desc->use_shortgi = false; |
| 622 | 623 | ||
| 623 | if (sta == NULL) | 624 | if (sta == NULL) |
| @@ -1850,6 +1851,7 @@ int rtl_rx_agg_stop(struct ieee80211_hw *hw, | |||
| 1850 | 1851 | ||
| 1851 | return 0; | 1852 | return 0; |
| 1852 | } | 1853 | } |
| 1854 | |||
| 1853 | int rtl_tx_agg_oper(struct ieee80211_hw *hw, | 1855 | int rtl_tx_agg_oper(struct ieee80211_hw *hw, |
| 1854 | struct ieee80211_sta *sta, u16 tid) | 1856 | struct ieee80211_sta *sta, u16 tid) |
| 1855 | { | 1857 | { |
| @@ -2073,7 +2075,6 @@ void rtl_watchdog_wq_callback(void *data) | |||
| 2073 | * busytraffic we don't change channel | 2075 | * busytraffic we don't change channel |
| 2074 | */ | 2076 | */ |
| 2075 | if (mac->link_state >= MAC80211_LINKED) { | 2077 | if (mac->link_state >= MAC80211_LINKED) { |
| 2076 | |||
| 2077 | /* (1) get aver_rx_cnt_inperiod & aver_tx_cnt_inperiod */ | 2078 | /* (1) get aver_rx_cnt_inperiod & aver_tx_cnt_inperiod */ |
| 2078 | for (idx = 0; idx <= 2; idx++) { | 2079 | for (idx = 0; idx <= 2; idx++) { |
| 2079 | rtlpriv->link_info.num_rx_in4period[idx] = | 2080 | rtlpriv->link_info.num_rx_in4period[idx] = |
| @@ -2233,6 +2234,7 @@ void rtl_watch_dog_timer_callback(struct timer_list *t) | |||
| 2233 | mod_timer(&rtlpriv->works.watchdog_timer, | 2234 | mod_timer(&rtlpriv->works.watchdog_timer, |
| 2234 | jiffies + MSECS(RTL_WATCH_DOG_TIME)); | 2235 | jiffies + MSECS(RTL_WATCH_DOG_TIME)); |
| 2235 | } | 2236 | } |
| 2237 | |||
| 2236 | void rtl_fwevt_wq_callback(void *data) | 2238 | void rtl_fwevt_wq_callback(void *data) |
| 2237 | { | 2239 | { |
| 2238 | struct rtl_works *rtlworks = | 2240 | struct rtl_works *rtlworks = |
| @@ -2384,6 +2386,7 @@ void rtl_easy_concurrent_retrytimer_callback(struct timer_list *t) | |||
| 2384 | 2386 | ||
| 2385 | rtlpriv->cfg->ops->dualmac_easy_concurrent(hw); | 2387 | rtlpriv->cfg->ops->dualmac_easy_concurrent(hw); |
| 2386 | } | 2388 | } |
| 2389 | |||
| 2387 | /********************************************************* | 2390 | /********************************************************* |
| 2388 | * | 2391 | * |
| 2389 | * frame process functions | 2392 | * frame process functions |
diff --git a/drivers/net/wireless/realtek/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c index 0913f02b7ff1..f73e690bbe8e 100644 --- a/drivers/net/wireless/realtek/rtlwifi/core.c +++ b/drivers/net/wireless/realtek/rtlwifi/core.c | |||
| @@ -188,6 +188,7 @@ static void rtl_op_tx(struct ieee80211_hw *hw, | |||
| 188 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | 188 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
| 189 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | 189 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); |
| 190 | struct rtl_tcb_desc tcb_desc; | 190 | struct rtl_tcb_desc tcb_desc; |
| 191 | |||
| 191 | memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); | 192 | memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); |
| 192 | 193 | ||
| 193 | if (unlikely(is_hal_stop(rtlhal) || ppsc->rfpwr_state != ERFON)) | 194 | if (unlikely(is_hal_stop(rtlhal) || ppsc->rfpwr_state != ERFON)) |
| @@ -346,12 +347,14 @@ static void rtl_op_remove_interface(struct ieee80211_hw *hw, | |||
| 346 | 347 | ||
| 347 | mutex_unlock(&rtlpriv->locks.conf_mutex); | 348 | mutex_unlock(&rtlpriv->locks.conf_mutex); |
| 348 | } | 349 | } |
| 350 | |||
| 349 | static int rtl_op_change_interface(struct ieee80211_hw *hw, | 351 | static int rtl_op_change_interface(struct ieee80211_hw *hw, |
| 350 | struct ieee80211_vif *vif, | 352 | struct ieee80211_vif *vif, |
| 351 | enum nl80211_iftype new_type, bool p2p) | 353 | enum nl80211_iftype new_type, bool p2p) |
| 352 | { | 354 | { |
| 353 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 355 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 354 | int ret; | 356 | int ret; |
| 357 | |||
| 355 | rtl_op_remove_interface(hw, vif); | 358 | rtl_op_remove_interface(hw, vif); |
| 356 | 359 | ||
| 357 | vif->type = new_type; | 360 | vif->type = new_type; |
| @@ -881,6 +884,7 @@ static void rtl_op_configure_filter(struct ieee80211_hw *hw, | |||
| 881 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, | 884 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, |
| 882 | (u8 *)(&mac->rx_conf)); | 885 | (u8 *)(&mac->rx_conf)); |
| 883 | } | 886 | } |
| 887 | |||
| 884 | static int rtl_op_sta_add(struct ieee80211_hw *hw, | 888 | static int rtl_op_sta_add(struct ieee80211_hw *hw, |
| 885 | struct ieee80211_vif *vif, | 889 | struct ieee80211_vif *vif, |
| 886 | struct ieee80211_sta *sta) | 890 | struct ieee80211_sta *sta) |
| @@ -933,6 +937,7 @@ static int rtl_op_sta_remove(struct ieee80211_hw *hw, | |||
| 933 | { | 937 | { |
| 934 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 938 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 935 | struct rtl_sta_info *sta_entry; | 939 | struct rtl_sta_info *sta_entry; |
| 940 | |||
| 936 | if (sta) { | 941 | if (sta) { |
| 937 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, | 942 | RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, |
| 938 | "Remove sta addr is %pM\n", sta->addr); | 943 | "Remove sta addr is %pM\n", sta->addr); |
| @@ -945,6 +950,7 @@ static int rtl_op_sta_remove(struct ieee80211_hw *hw, | |||
| 945 | } | 950 | } |
| 946 | return 0; | 951 | return 0; |
| 947 | } | 952 | } |
| 953 | |||
| 948 | static int _rtl_get_hal_qnum(u16 queue) | 954 | static int _rtl_get_hal_qnum(u16 queue) |
| 949 | { | 955 | { |
| 950 | int qnum; | 956 | int qnum; |
| @@ -1066,6 +1072,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, | |||
| 1066 | /*TODO: reference to enum ieee80211_bss_change */ | 1072 | /*TODO: reference to enum ieee80211_bss_change */ |
| 1067 | if (changed & BSS_CHANGED_ASSOC) { | 1073 | if (changed & BSS_CHANGED_ASSOC) { |
| 1068 | u8 mstatus; | 1074 | u8 mstatus; |
| 1075 | |||
| 1069 | if (bss_conf->assoc) { | 1076 | if (bss_conf->assoc) { |
| 1070 | struct ieee80211_sta *sta = NULL; | 1077 | struct ieee80211_sta *sta = NULL; |
| 1071 | u8 keep_alive = 10; | 1078 | u8 keep_alive = 10; |
| @@ -1294,6 +1301,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, | |||
| 1294 | * set in sta_add, and will be NULL here */ | 1301 | * set in sta_add, and will be NULL here */ |
| 1295 | if (vif->type == NL80211_IFTYPE_STATION) { | 1302 | if (vif->type == NL80211_IFTYPE_STATION) { |
| 1296 | struct rtl_sta_info *sta_entry; | 1303 | struct rtl_sta_info *sta_entry; |
| 1304 | |||
| 1297 | sta_entry = (struct rtl_sta_info *)sta->drv_priv; | 1305 | sta_entry = (struct rtl_sta_info *)sta->drv_priv; |
| 1298 | sta_entry->wireless_mode = mac->mode; | 1306 | sta_entry->wireless_mode = mac->mode; |
| 1299 | } | 1307 | } |
diff --git a/drivers/net/wireless/realtek/rtlwifi/efuse.c b/drivers/net/wireless/realtek/rtlwifi/efuse.c index de0437b3cb95..e68340dfd980 100644 --- a/drivers/net/wireless/realtek/rtlwifi/efuse.c +++ b/drivers/net/wireless/realtek/rtlwifi/efuse.c | |||
| @@ -474,6 +474,7 @@ bool efuse_shadow_update(struct ieee80211_hw *hw) | |||
| 474 | 474 | ||
| 475 | if (word_en != 0x0F) { | 475 | if (word_en != 0x0F) { |
| 476 | u8 tmpdata[8]; | 476 | u8 tmpdata[8]; |
| 477 | |||
| 477 | memcpy(tmpdata, | 478 | memcpy(tmpdata, |
| 478 | &rtlefuse->efuse_map[EFUSE_MODIFY_MAP][base], | 479 | &rtlefuse->efuse_map[EFUSE_MODIFY_MAP][base], |
| 479 | 8); | 480 | 8); |
| @@ -487,7 +488,6 @@ bool efuse_shadow_update(struct ieee80211_hw *hw) | |||
| 487 | break; | 488 | break; |
| 488 | } | 489 | } |
| 489 | } | 490 | } |
| 490 | |||
| 491 | } | 491 | } |
| 492 | 492 | ||
| 493 | efuse_power_switch(hw, true, false); | 493 | efuse_power_switch(hw, true, false); |
| @@ -662,6 +662,7 @@ static int efuse_one_byte_write(struct ieee80211_hw *hw, u16 addr, u8 data) | |||
| 662 | static void efuse_read_all_map(struct ieee80211_hw *hw, u8 *efuse) | 662 | static void efuse_read_all_map(struct ieee80211_hw *hw, u8 *efuse) |
| 663 | { | 663 | { |
| 664 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 664 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 665 | |||
| 665 | efuse_power_switch(hw, false, true); | 666 | efuse_power_switch(hw, false, true); |
| 666 | read_efuse(hw, 0, rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE], efuse); | 667 | read_efuse(hw, 0, rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE], efuse); |
| 667 | efuse_power_switch(hw, false, false); | 668 | efuse_power_switch(hw, false, false); |
| @@ -812,6 +813,7 @@ static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, | |||
| 812 | if (0x0F != (badworden & 0x0F)) { | 813 | if (0x0F != (badworden & 0x0F)) { |
| 813 | u8 reorg_offset = offset; | 814 | u8 reorg_offset = offset; |
| 814 | u8 reorg_worden = badworden; | 815 | u8 reorg_worden = badworden; |
| 816 | |||
| 815 | efuse_pg_packet_write(hw, reorg_offset, | 817 | efuse_pg_packet_write(hw, reorg_offset, |
| 816 | reorg_worden, | 818 | reorg_worden, |
| 817 | originaldata); | 819 | originaldata); |
| @@ -901,6 +903,7 @@ static void efuse_write_data_case2(struct ieee80211_hw *hw, u16 *efuse_addr, | |||
| 901 | if (0x0F != (badworden & 0x0F)) { | 903 | if (0x0F != (badworden & 0x0F)) { |
| 902 | u8 reorg_offset = tmp_pkt.offset; | 904 | u8 reorg_offset = tmp_pkt.offset; |
| 903 | u8 reorg_worden = badworden; | 905 | u8 reorg_worden = badworden; |
| 906 | |||
| 904 | efuse_pg_packet_write(hw, reorg_offset, | 907 | efuse_pg_packet_write(hw, reorg_offset, |
| 905 | reorg_worden, | 908 | reorg_worden, |
| 906 | originaldata); | 909 | originaldata); |
| @@ -957,7 +960,6 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw, | |||
| 957 | 960 | ||
| 958 | while (continual && (efuse_addr < (EFUSE_MAX_SIZE - | 961 | while (continual && (efuse_addr < (EFUSE_MAX_SIZE - |
| 959 | rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN]))) { | 962 | rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN]))) { |
| 960 | |||
| 961 | if (write_state == PG_STATE_HEADER) { | 963 | if (write_state == PG_STATE_HEADER) { |
| 962 | dataempty = true; | 964 | dataempty = true; |
| 963 | badworden = 0x0F; | 965 | badworden = 0x0F; |
| @@ -1114,7 +1116,6 @@ void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate) | |||
| 1114 | u16 tmpv16; | 1116 | u16 tmpv16; |
| 1115 | 1117 | ||
| 1116 | if (pwrstate && (rtlhal->hw_type != HARDWARE_TYPE_RTL8192SE)) { | 1118 | if (pwrstate && (rtlhal->hw_type != HARDWARE_TYPE_RTL8192SE)) { |
| 1117 | |||
| 1118 | if (rtlhal->hw_type != HARDWARE_TYPE_RTL8192CE && | 1119 | if (rtlhal->hw_type != HARDWARE_TYPE_RTL8192CE && |
| 1119 | rtlhal->hw_type != HARDWARE_TYPE_RTL8192DE) { | 1120 | rtlhal->hw_type != HARDWARE_TYPE_RTL8192DE) { |
| 1120 | rtl_write_byte(rtlpriv, | 1121 | rtl_write_byte(rtlpriv, |
| @@ -1219,6 +1220,7 @@ static u16 efuse_get_current_size(struct ieee80211_hw *hw) | |||
| 1219 | static u8 efuse_calculate_word_cnts(u8 word_en) | 1220 | static u8 efuse_calculate_word_cnts(u8 word_en) |
| 1220 | { | 1221 | { |
| 1221 | u8 word_cnts = 0; | 1222 | u8 word_cnts = 0; |
| 1223 | |||
| 1222 | if (!(word_en & BIT(0))) | 1224 | if (!(word_en & BIT(0))) |
| 1223 | word_cnts++; | 1225 | word_cnts++; |
| 1224 | if (!(word_en & BIT(1))) | 1226 | if (!(word_en & BIT(1))) |
diff --git a/drivers/net/wireless/realtek/rtlwifi/ps.c b/drivers/net/wireless/realtek/rtlwifi/ps.c index dca70d239760..70f04c2f5b17 100644 --- a/drivers/net/wireless/realtek/rtlwifi/ps.c +++ b/drivers/net/wireless/realtek/rtlwifi/ps.c | |||
| @@ -718,6 +718,7 @@ static void rtl_p2p_noa_ie(struct ieee80211_hw *hw, void *data, | |||
| 718 | static u8 p2p_oui_ie_type[4] = {0x50, 0x6f, 0x9a, 0x09}; | 718 | static u8 p2p_oui_ie_type[4] = {0x50, 0x6f, 0x9a, 0x09}; |
| 719 | u8 noa_num, index , i, noa_index = 0; | 719 | u8 noa_num, index , i, noa_index = 0; |
| 720 | bool find_p2p_ie = false , find_p2p_ps_ie = false; | 720 | bool find_p2p_ie = false , find_p2p_ps_ie = false; |
| 721 | |||
| 721 | pos = (u8 *)mgmt->u.beacon.variable; | 722 | pos = (u8 *)mgmt->u.beacon.variable; |
| 722 | end = data + len; | 723 | end = data + len; |
| 723 | ie = NULL; | 724 | ie = NULL; |
diff --git a/drivers/net/wireless/realtek/rtlwifi/rc.c b/drivers/net/wireless/realtek/rtlwifi/rc.c index 8fa76eab61d2..cf8e42a01015 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rc.c +++ b/drivers/net/wireless/realtek/rtlwifi/rc.c | |||
| @@ -236,6 +236,7 @@ static void rtl_tx_status(void *ppriv, | |||
| 236 | !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { | 236 | !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { |
| 237 | if (ieee80211_is_data_qos(fc)) { | 237 | if (ieee80211_is_data_qos(fc)) { |
| 238 | u8 tid = rtl_get_tid(skb); | 238 | u8 tid = rtl_get_tid(skb); |
| 239 | |||
| 239 | if (_rtl_tx_aggr_check(rtlpriv, sta_entry, | 240 | if (_rtl_tx_aggr_check(rtlpriv, sta_entry, |
| 240 | tid)) { | 241 | tid)) { |
| 241 | sta_entry->tids[tid].agg.agg_state = | 242 | sta_entry->tids[tid].agg.agg_state = |
| @@ -293,6 +294,7 @@ static void rtl_rate_free_sta(void *rtlpriv, | |||
| 293 | struct ieee80211_sta *sta, void *priv_sta) | 294 | struct ieee80211_sta *sta, void *priv_sta) |
| 294 | { | 295 | { |
| 295 | struct rtl_rate_priv *rate_priv = priv_sta; | 296 | struct rtl_rate_priv *rate_priv = priv_sta; |
| 297 | |||
| 296 | kfree(rate_priv); | 298 | kfree(rate_priv); |
| 297 | } | 299 | } |
| 298 | 300 | ||
diff --git a/drivers/net/wireless/realtek/rtlwifi/regd.c b/drivers/net/wireless/realtek/rtlwifi/regd.c index c7048830decd..6ccb5b93a595 100644 --- a/drivers/net/wireless/realtek/rtlwifi/regd.c +++ b/drivers/net/wireless/realtek/rtlwifi/regd.c | |||
| @@ -41,7 +41,6 @@ static struct country_code_to_enum_rd all_countries[] = { | |||
| 41 | NL80211_RRF_PASSIVE_SCAN | \ | 41 | NL80211_RRF_PASSIVE_SCAN | \ |
| 42 | NL80211_RRF_NO_OFDM) | 42 | NL80211_RRF_NO_OFDM) |
| 43 | 43 | ||
| 44 | |||
| 45 | /* 5G chan 36 - chan 64*/ | 44 | /* 5G chan 36 - chan 64*/ |
| 46 | #define RTL819x_5GHZ_5150_5350 \ | 45 | #define RTL819x_5GHZ_5150_5350 \ |
| 47 | REG_RULE(5150-10, 5350+10, 80, 0, 30, 0) | 46 | REG_RULE(5150-10, 5350+10, 80, 0, 30, 0) |
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c index 2f633118c717..f2908ee5f860 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c | |||
| @@ -425,7 +425,6 @@ static void rtl92c_dm_initial_gain_sta(struct ieee80211_hw *hw) | |||
| 425 | if (dm_digtable->presta_cstate == dm_digtable->cursta_cstate || | 425 | if (dm_digtable->presta_cstate == dm_digtable->cursta_cstate || |
| 426 | dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT || | 426 | dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT || |
| 427 | dm_digtable->cursta_cstate == DIG_STA_CONNECT) { | 427 | dm_digtable->cursta_cstate == DIG_STA_CONNECT) { |
| 428 | |||
| 429 | if (dm_digtable->cursta_cstate != DIG_STA_DISCONNECT) { | 428 | if (dm_digtable->cursta_cstate != DIG_STA_DISCONNECT) { |
| 430 | dm_digtable->rssi_val_min = | 429 | dm_digtable->rssi_val_min = |
| 431 | rtl92c_dm_initial_gain_min_pwdb(hw); | 430 | rtl92c_dm_initial_gain_min_pwdb(hw); |
| @@ -504,7 +503,6 @@ static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw) | |||
| 504 | rtl92c_dm_cck_packet_detection_thresh(hw); | 503 | rtl92c_dm_cck_packet_detection_thresh(hw); |
| 505 | 504 | ||
| 506 | dm_digtable->presta_cstate = dm_digtable->cursta_cstate; | 505 | dm_digtable->presta_cstate = dm_digtable->cursta_cstate; |
| 507 | |||
| 508 | } | 506 | } |
| 509 | 507 | ||
| 510 | static void rtl92c_dm_dig(struct ieee80211_hw *hw) | 508 | static void rtl92c_dm_dig(struct ieee80211_hw *hw) |
| @@ -607,6 +605,7 @@ static void rtl92c_dm_pwdb_monitor(struct ieee80211_hw *hw) | |||
| 607 | void rtl92c_dm_init_edca_turbo(struct ieee80211_hw *hw) | 605 | void rtl92c_dm_init_edca_turbo(struct ieee80211_hw *hw) |
| 608 | { | 606 | { |
| 609 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 607 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 608 | |||
| 610 | rtlpriv->dm.current_turbo_edca = false; | 609 | rtlpriv->dm.current_turbo_edca = false; |
| 611 | rtlpriv->dm.is_any_nonbepkts = false; | 610 | rtlpriv->dm.is_any_nonbepkts = false; |
| 612 | rtlpriv->dm.is_cur_rdlstate = false; | 611 | rtlpriv->dm.is_cur_rdlstate = false; |
| @@ -660,7 +659,6 @@ static void rtl92c_dm_check_edca_turbo(struct ieee80211_hw *hw) | |||
| 660 | 659 | ||
| 661 | if ((bt_change_edca) || ((!rtlpriv->dm.is_any_nonbepkts) && | 660 | if ((bt_change_edca) || ((!rtlpriv->dm.is_any_nonbepkts) && |
| 662 | (!rtlpriv->dm.disable_framebursting))) { | 661 | (!rtlpriv->dm.disable_framebursting))) { |
| 663 | |||
| 664 | cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt; | 662 | cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt; |
| 665 | cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt; | 663 | cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt; |
| 666 | 664 | ||
| @@ -685,6 +683,7 @@ static void rtl92c_dm_check_edca_turbo(struct ieee80211_hw *hw) | |||
| 685 | } else { | 683 | } else { |
| 686 | if (rtlpriv->dm.current_turbo_edca) { | 684 | if (rtlpriv->dm.current_turbo_edca) { |
| 687 | u8 tmp = AC0_BE; | 685 | u8 tmp = AC0_BE; |
| 686 | |||
| 688 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, | 687 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, |
| 689 | &tmp); | 688 | &tmp); |
| 690 | rtlpriv->dm.current_turbo_edca = false; | 689 | rtlpriv->dm.current_turbo_edca = false; |
| @@ -1635,7 +1634,6 @@ static void rtl92c_bt_ant_isolation(struct ieee80211_hw *hw, u8 tmp1byte) | |||
| 1635 | { | 1634 | { |
| 1636 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1635 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 1637 | 1636 | ||
| 1638 | |||
| 1639 | /* Only enable HW BT coexist when BT in "Busy" state. */ | 1637 | /* Only enable HW BT coexist when BT in "Busy" state. */ |
| 1640 | if (rtlpriv->mac80211.vendor == PEER_CISCO && | 1638 | if (rtlpriv->mac80211.vendor == PEER_CISCO && |
| 1641 | rtlpriv->btcoexist.bt_service == BT_OTHER_ACTION) { | 1639 | rtlpriv->btcoexist.bt_service == BT_OTHER_ACTION) { |
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c index 6af72799e09c..18c76990a089 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c | |||
| @@ -18,6 +18,7 @@ static void _rtl92c_enable_fw_download(struct ieee80211_hw *hw, bool enable) | |||
| 18 | 18 | ||
| 19 | if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CU) { | 19 | if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CU) { |
| 20 | u32 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); | 20 | u32 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); |
| 21 | |||
| 21 | if (enable) | 22 | if (enable) |
| 22 | value32 |= MCUFWDL_EN; | 23 | value32 |= MCUFWDL_EN; |
| 23 | else | 24 | else |
| @@ -25,8 +26,8 @@ static void _rtl92c_enable_fw_download(struct ieee80211_hw *hw, bool enable) | |||
| 25 | rtl_write_dword(rtlpriv, REG_MCUFWDL, value32); | 26 | rtl_write_dword(rtlpriv, REG_MCUFWDL, value32); |
| 26 | } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CE) { | 27 | } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CE) { |
| 27 | u8 tmp; | 28 | u8 tmp; |
| 28 | if (enable) { | ||
| 29 | 29 | ||
| 30 | if (enable) { | ||
| 30 | tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); | 31 | tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); |
| 31 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, | 32 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, |
| 32 | tmp | 0x04); | 33 | tmp | 0x04); |
| @@ -37,7 +38,6 @@ static void _rtl92c_enable_fw_download(struct ieee80211_hw *hw, bool enable) | |||
| 37 | tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2); | 38 | tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2); |
| 38 | rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7); | 39 | rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7); |
| 39 | } else { | 40 | } else { |
| 40 | |||
| 41 | tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); | 41 | tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); |
| 42 | rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe); | 42 | rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe); |
| 43 | 43 | ||
| @@ -622,7 +622,6 @@ void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, | |||
| 622 | "rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", | 622 | "rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", |
| 623 | u1rsvdpageloc, 3); | 623 | u1rsvdpageloc, 3); |
| 624 | 624 | ||
| 625 | |||
| 626 | skb = dev_alloc_skb(totalpacketlen); | 625 | skb = dev_alloc_skb(totalpacketlen); |
| 627 | skb_put_data(skb, &reserved_page_packet, totalpacketlen); | 626 | skb_put_data(skb, &reserved_page_packet, totalpacketlen); |
| 628 | 627 | ||
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/main.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/main.c index e8af1952d243..97ad21c3964f 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/main.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/main.c | |||
| @@ -4,7 +4,6 @@ | |||
| 4 | #include "../wifi.h" | 4 | #include "../wifi.h" |
| 5 | #include <linux/module.h> | 5 | #include <linux/module.h> |
| 6 | 6 | ||
| 7 | |||
| 8 | MODULE_AUTHOR("lizhaoming <chaoming_li@realsil.com.cn>"); | 7 | MODULE_AUTHOR("lizhaoming <chaoming_li@realsil.com.cn>"); |
| 9 | MODULE_AUTHOR("Realtek WlanFAE <wlanfae@realtek.com>"); | 8 | MODULE_AUTHOR("Realtek WlanFAE <wlanfae@realtek.com>"); |
| 10 | MODULE_AUTHOR("Georgia <georgia@realtek.com>"); | 9 | MODULE_AUTHOR("Georgia <georgia@realtek.com>"); |
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c index c6a3ed441c3f..0efd19aa4fe5 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c | |||
| @@ -747,6 +747,7 @@ static void _rtl92c_phy_sw_rf_seting(struct ieee80211_hw *hw, u8 channel) | |||
| 747 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 747 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 748 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | 748 | struct rtl_phy *rtlphy = &(rtlpriv->phy); |
| 749 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | 749 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
| 750 | |||
| 750 | if (IS_81XXC_VENDOR_UMC_B_CUT(rtlhal->version)) { | 751 | if (IS_81XXC_VENDOR_UMC_B_CUT(rtlhal->version)) { |
| 751 | if (channel == 6 && | 752 | if (channel == 6 && |
| 752 | rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) { | 753 | rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) { |
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c index d8f496e2d68b..a52dd64d528d 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c | |||
| @@ -144,6 +144,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) | |||
| 144 | case HW_VAR_BASIC_RATE:{ | 144 | case HW_VAR_BASIC_RATE:{ |
| 145 | u16 rate_cfg = ((u16 *) val)[0]; | 145 | u16 rate_cfg = ((u16 *) val)[0]; |
| 146 | u8 rate_index = 0; | 146 | u8 rate_index = 0; |
| 147 | |||
| 147 | rate_cfg &= 0x15f; | 148 | rate_cfg &= 0x15f; |
| 148 | rate_cfg |= 0x01; | 149 | rate_cfg |= 0x01; |
| 149 | rtl_write_byte(rtlpriv, REG_RRSR, rate_cfg & 0xff); | 150 | rtl_write_byte(rtlpriv, REG_RRSR, rate_cfg & 0xff); |
| @@ -197,6 +198,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) | |||
| 197 | case HW_VAR_ACK_PREAMBLE:{ | 198 | case HW_VAR_ACK_PREAMBLE:{ |
| 198 | u8 reg_tmp; | 199 | u8 reg_tmp; |
| 199 | u8 short_preamble = (bool)*val; | 200 | u8 short_preamble = (bool)*val; |
| 201 | |||
| 200 | reg_tmp = (mac->cur_40_prime_sc) << 5; | 202 | reg_tmp = (mac->cur_40_prime_sc) << 5; |
| 201 | if (short_preamble) | 203 | if (short_preamble) |
| 202 | reg_tmp |= 0x80; | 204 | reg_tmp |= 0x80; |
| @@ -293,6 +295,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) | |||
| 293 | } | 295 | } |
| 294 | case HW_VAR_AC_PARAM:{ | 296 | case HW_VAR_AC_PARAM:{ |
| 295 | u8 e_aci = *(val); | 297 | u8 e_aci = *(val); |
| 298 | |||
| 296 | rtl92c_dm_init_edca_turbo(hw); | 299 | rtl92c_dm_init_edca_turbo(hw); |
| 297 | 300 | ||
| 298 | if (rtlpci->acm_method != EACMWAY2_SW) | 301 | if (rtlpci->acm_method != EACMWAY2_SW) |
| @@ -456,6 +459,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) | |||
| 456 | break; | 459 | break; |
| 457 | case HW_VAR_AID:{ | 460 | case HW_VAR_AID:{ |
| 458 | u16 u2btmp; | 461 | u16 u2btmp; |
| 462 | |||
| 459 | u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT); | 463 | u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT); |
| 460 | u2btmp &= 0xC000; | 464 | u2btmp &= 0xC000; |
| 461 | rtl_write_word(rtlpriv, REG_BCN_PSR_RPT, (u2btmp | | 465 | rtl_write_word(rtlpriv, REG_BCN_PSR_RPT, (u2btmp | |
| @@ -661,6 +665,7 @@ static bool _rtl92ce_init_mac(struct ieee80211_hw *hw) | |||
| 661 | rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x00); | 665 | rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x00); |
| 662 | if (rtlpriv->btcoexist.bt_coexistence) { | 666 | if (rtlpriv->btcoexist.bt_coexistence) { |
| 663 | u32 value32; | 667 | u32 value32; |
| 668 | |||
| 664 | value32 = rtl_read_dword(rtlpriv, REG_APS_FSMCO); | 669 | value32 = rtl_read_dword(rtlpriv, REG_APS_FSMCO); |
| 665 | value32 |= (SOP_ABG | SOP_AMB | XOP_BTCK); | 670 | value32 |= (SOP_ABG | SOP_AMB | XOP_BTCK); |
| 666 | rtl_write_dword(rtlpriv, REG_APS_FSMCO, value32); | 671 | rtl_write_dword(rtlpriv, REG_APS_FSMCO, value32); |
| @@ -1245,6 +1250,7 @@ int rtl92ce_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) | |||
| 1245 | void rtl92ce_set_qos(struct ieee80211_hw *hw, int aci) | 1250 | void rtl92ce_set_qos(struct ieee80211_hw *hw, int aci) |
| 1246 | { | 1251 | { |
| 1247 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1252 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 1253 | |||
| 1248 | rtl92c_dm_init_edca_turbo(hw); | 1254 | rtl92c_dm_init_edca_turbo(hw); |
| 1249 | switch (aci) { | 1255 | switch (aci) { |
| 1250 | case AC1_BK: | 1256 | case AC1_BK: |
| @@ -2279,7 +2285,6 @@ void rtl8192ce_bt_reg_init(struct ieee80211_hw *hw) | |||
| 2279 | rtlpriv->btcoexist.reg_bt_sco = 0; | 2285 | rtlpriv->btcoexist.reg_bt_sco = 0; |
| 2280 | } | 2286 | } |
| 2281 | 2287 | ||
| 2282 | |||
| 2283 | void rtl8192ce_bt_hw_init(struct ieee80211_hw *hw) | 2288 | void rtl8192ce_bt_hw_init(struct ieee80211_hw *hw) |
| 2284 | { | 2289 | { |
| 2285 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 2290 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c index 8d18210dd5c8..f6574f31fa3b 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c | |||
| @@ -443,6 +443,7 @@ static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw, | |||
| 443 | RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { | 443 | RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { |
| 444 | bool rtstatus; | 444 | bool rtstatus; |
| 445 | u32 initializecount = 0; | 445 | u32 initializecount = 0; |
| 446 | |||
| 446 | do { | 447 | do { |
| 447 | initializecount++; | 448 | initializecount++; |
| 448 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, | 449 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, |
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.c index e258b0803699..58878db404ed 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.c | |||
| @@ -3,7 +3,6 @@ | |||
| 3 | 3 | ||
| 4 | #include "table.h" | 4 | #include "table.h" |
| 5 | 5 | ||
| 6 | |||
| 7 | u32 RTL8192CEPHY_REG_2TARRAY[PHY_REG_2TARRAY_LENGTH] = { | 6 | u32 RTL8192CEPHY_REG_2TARRAY[PHY_REG_2TARRAY_LENGTH] = { |
| 8 | 0x024, 0x0011800f, | 7 | 0x024, 0x0011800f, |
| 9 | 0x028, 0x00ffdb83, | 8 | 0x028, 0x00ffdb83, |
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c index b08fb1bf6709..18a0ab59631a 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c | |||
| @@ -36,6 +36,7 @@ static u8 _rtl92c_query_rxpwrpercentage(s8 antpower) | |||
| 36 | static u8 _rtl92c_evm_db_to_percentage(s8 value) | 36 | static u8 _rtl92c_evm_db_to_percentage(s8 value) |
| 37 | { | 37 | { |
| 38 | s8 ret_val; | 38 | s8 ret_val; |
| 39 | |||
| 39 | ret_val = value; | 40 | ret_val = value; |
| 40 | 41 | ||
| 41 | if (ret_val >= 0) | 42 | if (ret_val >= 0) |
| @@ -109,6 +110,7 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, | |||
| 109 | 110 | ||
| 110 | if (is_cck_rate) { | 111 | if (is_cck_rate) { |
| 111 | u8 report, cck_highpwr; | 112 | u8 report, cck_highpwr; |
| 113 | |||
| 112 | cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo; | 114 | cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo; |
| 113 | 115 | ||
| 114 | if (ppsc->rfpwr_state == ERFON) | 116 | if (ppsc->rfpwr_state == ERFON) |
| @@ -120,6 +122,7 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, | |||
| 120 | 122 | ||
| 121 | if (!cck_highpwr) { | 123 | if (!cck_highpwr) { |
| 122 | u8 cck_agc_rpt = cck_buf->cck_agc_rpt; | 124 | u8 cck_agc_rpt = cck_buf->cck_agc_rpt; |
| 125 | |||
| 123 | report = cck_buf->cck_agc_rpt & 0xc0; | 126 | report = cck_buf->cck_agc_rpt & 0xc0; |
| 124 | report = report >> 6; | 127 | report = report >> 6; |
| 125 | switch (report) { | 128 | switch (report) { |
| @@ -138,6 +141,7 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, | |||
| 138 | } | 141 | } |
| 139 | } else { | 142 | } else { |
| 140 | u8 cck_agc_rpt = cck_buf->cck_agc_rpt; | 143 | u8 cck_agc_rpt = cck_buf->cck_agc_rpt; |
| 144 | |||
| 141 | report = p_drvinfo->cfosho[0] & 0x60; | 145 | report = p_drvinfo->cfosho[0] & 0x60; |
| 142 | report = report >> 5; | 146 | report = report >> 5; |
| 143 | switch (report) { | 147 | switch (report) { |
| @@ -182,6 +186,7 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, | |||
| 182 | /* (3) Get Signal Quality (EVM) */ | 186 | /* (3) Get Signal Quality (EVM) */ |
| 183 | if (packet_match_bssid) { | 187 | if (packet_match_bssid) { |
| 184 | u8 sq; | 188 | u8 sq; |
| 189 | |||
| 185 | if (pstats->rx_pwdb_all > 40) | 190 | if (pstats->rx_pwdb_all > 40) |
| 186 | sq = 100; | 191 | sq = 100; |
| 187 | else { | 192 | else { |
| @@ -318,6 +323,7 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, | |||
| 318 | struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc; | 323 | struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc; |
| 319 | struct ieee80211_hdr *hdr; | 324 | struct ieee80211_hdr *hdr; |
| 320 | u32 phystatus = GET_RX_DESC_PHYST(pdesc); | 325 | u32 phystatus = GET_RX_DESC_PHYST(pdesc); |
| 326 | |||
| 321 | stats->length = (u16) GET_RX_DESC_PKT_LEN(pdesc); | 327 | stats->length = (u16) GET_RX_DESC_PKT_LEN(pdesc); |
| 322 | stats->rx_drvinfo_size = (u8) GET_RX_DESC_DRV_INFO_SIZE(pdesc) * | 328 | stats->rx_drvinfo_size = (u8) GET_RX_DESC_DRV_INFO_SIZE(pdesc) * |
| 323 | RX_DRV_INFO_SIZE_UNIT; | 329 | RX_DRV_INFO_SIZE_UNIT; |
| @@ -497,6 +503,7 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, | |||
| 497 | 503 | ||
| 498 | if (sta) { | 504 | if (sta) { |
| 499 | u8 ampdu_density = sta->ht_cap.ampdu_density; | 505 | u8 ampdu_density = sta->ht_cap.ampdu_density; |
| 506 | |||
| 500 | SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density); | 507 | SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density); |
| 501 | } | 508 | } |
| 502 | 509 | ||
| @@ -733,6 +740,7 @@ bool rtl92ce_is_tx_desc_closed(struct ieee80211_hw *hw, | |||
| 733 | void rtl92ce_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) | 740 | void rtl92ce_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) |
| 734 | { | 741 | { |
| 735 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 742 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 743 | |||
| 736 | if (hw_queue == BEACON_QUEUE) { | 744 | if (hw_queue == BEACON_QUEUE) { |
| 737 | rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, BIT(4)); | 745 | rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, BIT(4)); |
| 738 | } else { | 746 | } else { |
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c index 52ee713d50f5..56cc3bc30860 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c | |||
| @@ -747,6 +747,7 @@ static void _rtl92cu_init_queue_priority(struct ieee80211_hw *hw, | |||
| 747 | u8 queue_sel) | 747 | u8 queue_sel) |
| 748 | { | 748 | { |
| 749 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | 749 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
| 750 | |||
| 750 | if (IS_NORMAL_CHIP(rtlhal->version)) | 751 | if (IS_NORMAL_CHIP(rtlhal->version)) |
| 751 | _rtl92cu_init_chipn_queue_priority(hw, wmm_enable, out_ep_num, | 752 | _rtl92cu_init_chipn_queue_priority(hw, wmm_enable, out_ep_num, |
| 752 | queue_sel); | 753 | queue_sel); |
| @@ -813,6 +814,7 @@ static int _rtl92cu_init_mac(struct ieee80211_hw *hw) | |||
| 813 | u8 wmm_enable = false; /* TODO */ | 814 | u8 wmm_enable = false; /* TODO */ |
| 814 | u8 out_ep_nums = rtlusb->out_ep_nums; | 815 | u8 out_ep_nums = rtlusb->out_ep_nums; |
| 815 | u8 queue_sel = rtlusb->out_queue_sel; | 816 | u8 queue_sel = rtlusb->out_queue_sel; |
| 817 | |||
| 816 | err = _rtl92cu_init_power_on(hw); | 818 | err = _rtl92cu_init_power_on(hw); |
| 817 | 819 | ||
| 818 | if (err) { | 820 | if (err) { |
| @@ -1013,6 +1015,7 @@ d. SYS_FUNC_EN 0x02[7:0] = 0x16 reset BB state machine | |||
| 1013 | e. SYS_FUNC_EN 0x02[7:0] = 0x14 reset BB state machine | 1015 | e. SYS_FUNC_EN 0x02[7:0] = 0x14 reset BB state machine |
| 1014 | ***************************************/ | 1016 | ***************************************/ |
| 1015 | u8 erfpath = 0, value8 = 0; | 1017 | u8 erfpath = 0, value8 = 0; |
| 1018 | |||
| 1016 | rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); | 1019 | rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); |
| 1017 | rtl_set_rfreg(hw, (enum radio_path)erfpath, 0x0, MASKBYTE0, 0x0); | 1020 | rtl_set_rfreg(hw, (enum radio_path)erfpath, 0x0, MASKBYTE0, 0x0); |
| 1018 | 1021 | ||
| @@ -1204,6 +1207,7 @@ static void _rtl92cu_stop_tx_beacon(struct ieee80211_hw *hw) | |||
| 1204 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1207 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 1205 | struct rtl_hal *rtlhal = rtl_hal(rtlpriv); | 1208 | struct rtl_hal *rtlhal = rtl_hal(rtlpriv); |
| 1206 | u8 tmp1byte = 0; | 1209 | u8 tmp1byte = 0; |
| 1210 | |||
| 1207 | if (IS_NORMAL_CHIP(rtlhal->version)) { | 1211 | if (IS_NORMAL_CHIP(rtlhal->version)) { |
| 1208 | tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); | 1212 | tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); |
| 1209 | rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, | 1213 | rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, |
| @@ -1353,6 +1357,7 @@ void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) | |||
| 1353 | 1357 | ||
| 1354 | if (check_bssid) { | 1358 | if (check_bssid) { |
| 1355 | u8 tmp; | 1359 | u8 tmp; |
| 1360 | |||
| 1356 | if (IS_NORMAL_CHIP(rtlhal->version)) { | 1361 | if (IS_NORMAL_CHIP(rtlhal->version)) { |
| 1357 | reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN); | 1362 | reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN); |
| 1358 | tmp = BIT(4); | 1363 | tmp = BIT(4); |
| @@ -1365,6 +1370,7 @@ void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) | |||
| 1365 | _rtl92cu_set_bcn_ctrl_reg(hw, 0, tmp); | 1370 | _rtl92cu_set_bcn_ctrl_reg(hw, 0, tmp); |
| 1366 | } else { | 1371 | } else { |
| 1367 | u8 tmp; | 1372 | u8 tmp; |
| 1373 | |||
| 1368 | if (IS_NORMAL_CHIP(rtlhal->version)) { | 1374 | if (IS_NORMAL_CHIP(rtlhal->version)) { |
| 1369 | reg_rcr &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN); | 1375 | reg_rcr &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN); |
| 1370 | tmp = BIT(4); | 1376 | tmp = BIT(4); |
| @@ -1631,6 +1637,7 @@ void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) | |||
| 1631 | case HW_VAR_ACK_PREAMBLE:{ | 1637 | case HW_VAR_ACK_PREAMBLE:{ |
| 1632 | u8 reg_tmp; | 1638 | u8 reg_tmp; |
| 1633 | u8 short_preamble = (bool)*val; | 1639 | u8 short_preamble = (bool)*val; |
| 1640 | |||
| 1634 | reg_tmp = 0; | 1641 | reg_tmp = 0; |
| 1635 | if (short_preamble) | 1642 | if (short_preamble) |
| 1636 | reg_tmp |= 0x80; | 1643 | reg_tmp |= 0x80; |
| @@ -1881,6 +1888,7 @@ void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) | |||
| 1881 | break; | 1888 | break; |
| 1882 | case HW_VAR_KEEP_ALIVE:{ | 1889 | case HW_VAR_KEEP_ALIVE:{ |
| 1883 | u8 array[2]; | 1890 | u8 array[2]; |
| 1891 | |||
| 1884 | array[0] = 0xff; | 1892 | array[0] = 0xff; |
| 1885 | array[1] = *((u8 *)val); | 1893 | array[1] = *((u8 *)val); |
| 1886 | rtl92c_fill_h2c_cmd(hw, H2C_92C_KEEP_ALIVE_CTRL, 2, | 1894 | rtl92c_fill_h2c_cmd(hw, H2C_92C_KEEP_ALIVE_CTRL, 2, |
| @@ -1963,7 +1971,6 @@ static void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw, | |||
| 1963 | if (nmode && ((curtxbw_40mhz && | 1971 | if (nmode && ((curtxbw_40mhz && |
| 1964 | curshortgi_40mhz) || (!curtxbw_40mhz && | 1972 | curshortgi_40mhz) || (!curtxbw_40mhz && |
| 1965 | curshortgi_20mhz))) { | 1973 | curshortgi_20mhz))) { |
| 1966 | |||
| 1967 | ratr_value |= 0x10000000; | 1974 | ratr_value |= 0x10000000; |
| 1968 | tmp_ratr_value = (ratr_value >> 12); | 1975 | tmp_ratr_value = (ratr_value >> 12); |
| 1969 | 1976 | ||
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h index 0ccc47e36652..5c48c3fd45e4 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h | |||
| @@ -14,14 +14,12 @@ | |||
| 14 | #define TX_TOTAL_PAGE_NUMBER 0xF8 | 14 | #define TX_TOTAL_PAGE_NUMBER 0xF8 |
| 15 | #define TX_PAGE_BOUNDARY (TX_TOTAL_PAGE_NUMBER + 1) | 15 | #define TX_PAGE_BOUNDARY (TX_TOTAL_PAGE_NUMBER + 1) |
| 16 | 16 | ||
| 17 | |||
| 18 | #define CHIP_B_PAGE_NUM_PUBQ 0xE7 | 17 | #define CHIP_B_PAGE_NUM_PUBQ 0xE7 |
| 19 | 18 | ||
| 20 | /* For Test Chip Setting | 19 | /* For Test Chip Setting |
| 21 | * (HPQ + LPQ + PUBQ) shall be TX_TOTAL_PAGE_NUMBER */ | 20 | * (HPQ + LPQ + PUBQ) shall be TX_TOTAL_PAGE_NUMBER */ |
| 22 | #define CHIP_A_PAGE_NUM_PUBQ 0x7E | 21 | #define CHIP_A_PAGE_NUM_PUBQ 0x7E |
| 23 | 22 | ||
| 24 | |||
| 25 | /* For Chip A Setting */ | 23 | /* For Chip A Setting */ |
| 26 | #define WMM_CHIP_A_TX_TOTAL_PAGE_NUMBER 0xF5 | 24 | #define WMM_CHIP_A_TX_TOTAL_PAGE_NUMBER 0xF5 |
| 27 | #define WMM_CHIP_A_TX_PAGE_BOUNDARY \ | 25 | #define WMM_CHIP_A_TX_PAGE_BOUNDARY \ |
| @@ -31,8 +29,6 @@ | |||
| 31 | #define WMM_CHIP_A_PAGE_NUM_HPQ 0x29 | 29 | #define WMM_CHIP_A_PAGE_NUM_HPQ 0x29 |
| 32 | #define WMM_CHIP_A_PAGE_NUM_LPQ 0x29 | 30 | #define WMM_CHIP_A_PAGE_NUM_LPQ 0x29 |
| 33 | 31 | ||
| 34 | |||
| 35 | |||
| 36 | /* Note: For Chip B Setting ,modify later */ | 32 | /* Note: For Chip B Setting ,modify later */ |
| 37 | #define WMM_CHIP_B_TX_TOTAL_PAGE_NUMBER 0xF5 | 33 | #define WMM_CHIP_B_TX_TOTAL_PAGE_NUMBER 0xF5 |
| 38 | #define WMM_CHIP_B_TX_PAGE_BOUNDARY \ | 34 | #define WMM_CHIP_B_TX_PAGE_BOUNDARY \ |
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c index cc2ba74bff81..b3ce8000d52d 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c | |||
| @@ -24,7 +24,6 @@ | |||
| 24 | #define RX_EVM rx_evm_percentage | 24 | #define RX_EVM rx_evm_percentage |
| 25 | #define RX_SIGQ rx_mimo_sig_qual | 25 | #define RX_SIGQ rx_mimo_sig_qual |
| 26 | 26 | ||
| 27 | |||
| 28 | void rtl92c_read_chip_version(struct ieee80211_hw *hw) | 27 | void rtl92c_read_chip_version(struct ieee80211_hw *hw) |
| 29 | { | 28 | { |
| 30 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 29 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| @@ -143,6 +142,7 @@ bool rtl92c_llt_write(struct ieee80211_hw *hw, u32 address, u32 data) | |||
| 143 | } while (++count); | 142 | } while (++count); |
| 144 | return status; | 143 | return status; |
| 145 | } | 144 | } |
| 145 | |||
| 146 | /** | 146 | /** |
| 147 | * rtl92c_init_LLT_table - Init LLT table | 147 | * rtl92c_init_LLT_table - Init LLT table |
| 148 | * @io: io callback | 148 | * @io: io callback |
| @@ -189,6 +189,7 @@ bool rtl92c_init_llt_table(struct ieee80211_hw *hw, u32 boundary) | |||
| 189 | } | 189 | } |
| 190 | return rst; | 190 | return rst; |
| 191 | } | 191 | } |
| 192 | |||
| 192 | void rtl92c_set_key(struct ieee80211_hw *hw, u32 key_index, | 193 | void rtl92c_set_key(struct ieee80211_hw *hw, u32 key_index, |
| 193 | u8 *p_macaddr, bool is_group, u8 enc_algo, | 194 | u8 *p_macaddr, bool is_group, u8 enc_algo, |
| 194 | bool is_wepkey, bool clear_all) | 195 | bool is_wepkey, bool clear_all) |
| @@ -370,6 +371,7 @@ void rtl92c_set_qos(struct ieee80211_hw *hw, int aci) | |||
| 370 | void rtl92c_init_driver_info_size(struct ieee80211_hw *hw, u8 size) | 371 | void rtl92c_init_driver_info_size(struct ieee80211_hw *hw, u8 size) |
| 371 | { | 372 | { |
| 372 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 373 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 374 | |||
| 373 | rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, size); | 375 | rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, size); |
| 374 | } | 376 | } |
| 375 | 377 | ||
| @@ -647,6 +649,7 @@ static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw, | |||
| 647 | pstats->RX_SIGQ[1] = -1; | 649 | pstats->RX_SIGQ[1] = -1; |
| 648 | if (is_cck_rate) { | 650 | if (is_cck_rate) { |
| 649 | u8 report, cck_highpwr; | 651 | u8 report, cck_highpwr; |
| 652 | |||
| 650 | cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo; | 653 | cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo; |
| 651 | if (!in_powersavemode) | 654 | if (!in_powersavemode) |
| 652 | cck_highpwr = rtlphy->cck_high_power; | 655 | cck_highpwr = rtlphy->cck_high_power; |
| @@ -654,6 +657,7 @@ static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw, | |||
| 654 | cck_highpwr = false; | 657 | cck_highpwr = false; |
| 655 | if (!cck_highpwr) { | 658 | if (!cck_highpwr) { |
| 656 | u8 cck_agc_rpt = cck_buf->cck_agc_rpt; | 659 | u8 cck_agc_rpt = cck_buf->cck_agc_rpt; |
| 660 | |||
| 657 | report = cck_buf->cck_agc_rpt & 0xc0; | 661 | report = cck_buf->cck_agc_rpt & 0xc0; |
| 658 | report = report >> 6; | 662 | report = report >> 6; |
| 659 | switch (report) { | 663 | switch (report) { |
| @@ -672,6 +676,7 @@ static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw, | |||
| 672 | } | 676 | } |
| 673 | } else { | 677 | } else { |
| 674 | u8 cck_agc_rpt = cck_buf->cck_agc_rpt; | 678 | u8 cck_agc_rpt = cck_buf->cck_agc_rpt; |
| 679 | |||
| 675 | report = p_drvinfo->cfosho[0] & 0x60; | 680 | report = p_drvinfo->cfosho[0] & 0x60; |
| 676 | report = report >> 5; | 681 | report = report >> 5; |
| 677 | switch (report) { | 682 | switch (report) { |
| @@ -694,6 +699,7 @@ static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw, | |||
| 694 | pstats->recvsignalpower = rx_pwr_all; | 699 | pstats->recvsignalpower = rx_pwr_all; |
| 695 | if (packet_match_bssid) { | 700 | if (packet_match_bssid) { |
| 696 | u8 sq; | 701 | u8 sq; |
| 702 | |||
| 697 | if (pstats->rx_pwdb_all > 40) | 703 | if (pstats->rx_pwdb_all > 40) |
| 698 | sq = 100; | 704 | sq = 100; |
| 699 | else { | 705 | else { |
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h index 62eb3c5adec1..dd76a05829d5 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h | |||
| @@ -18,7 +18,6 @@ void rtl92c_enable_interrupt(struct ieee80211_hw *hw); | |||
| 18 | void rtl92c_disable_interrupt(struct ieee80211_hw *hw); | 18 | void rtl92c_disable_interrupt(struct ieee80211_hw *hw); |
| 19 | void rtl92c_set_qos(struct ieee80211_hw *hw, int aci); | 19 | void rtl92c_set_qos(struct ieee80211_hw *hw, int aci); |
| 20 | 20 | ||
| 21 | |||
| 22 | /*--------------------------------------------------------------- | 21 | /*--------------------------------------------------------------- |
| 23 | * Hardware init functions | 22 | * Hardware init functions |
| 24 | *---------------------------------------------------------------*/ | 23 | *---------------------------------------------------------------*/ |
| @@ -130,6 +129,4 @@ void rtl92c_translate_rx_signal_stuff(struct ieee80211_hw *hw, | |||
| 130 | * Card disable functions | 129 | * Card disable functions |
| 131 | *---------------------------------------------------------------*/ | 130 | *---------------------------------------------------------------*/ |
| 132 | 131 | ||
| 133 | |||
| 134 | |||
| 135 | #endif | 132 | #endif |
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c index 4293d0640310..0020adc004a5 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c | |||
| @@ -108,6 +108,7 @@ static void threeoutepmapping(struct ieee80211_hw *hw, bool bwificfg, | |||
| 108 | struct rtl_ep_map *ep_map) | 108 | struct rtl_ep_map *ep_map) |
| 109 | { | 109 | { |
| 110 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 110 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 111 | |||
| 111 | if (bwificfg) { /* for WMM */ | 112 | if (bwificfg) { /* for WMM */ |
| 112 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, | 113 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, |
| 113 | "USB 3EP Setting for WMM.....\n"); | 114 | "USB 3EP Setting for WMM.....\n"); |
| @@ -141,6 +142,7 @@ static void oneoutepmapping(struct ieee80211_hw *hw, struct rtl_ep_map *ep_map) | |||
| 141 | ep_map->ep_mapping[RTL_TXQ_BCN] = 2; | 142 | ep_map->ep_mapping[RTL_TXQ_BCN] = 2; |
| 142 | ep_map->ep_mapping[RTL_TXQ_HI] = 2; | 143 | ep_map->ep_mapping[RTL_TXQ_HI] = 2; |
| 143 | } | 144 | } |
| 145 | |||
| 144 | static int _out_ep_mapping(struct ieee80211_hw *hw) | 146 | static int _out_ep_mapping(struct ieee80211_hw *hw) |
| 145 | { | 147 | { |
| 146 | int err = 0; | 148 | int err = 0; |
| @@ -174,11 +176,13 @@ err_out: | |||
| 174 | return err; | 176 | return err; |
| 175 | 177 | ||
| 176 | } | 178 | } |
| 179 | |||
| 177 | /* endpoint mapping */ | 180 | /* endpoint mapping */ |
| 178 | int rtl8192cu_endpoint_mapping(struct ieee80211_hw *hw) | 181 | int rtl8192cu_endpoint_mapping(struct ieee80211_hw *hw) |
| 179 | { | 182 | { |
| 180 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | 183 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
| 181 | int error = 0; | 184 | int error = 0; |
| 185 | |||
| 182 | if (likely(IS_NORMAL_CHIP(rtlhal->version))) | 186 | if (likely(IS_NORMAL_CHIP(rtlhal->version))) |
| 183 | error = configvernoutep(hw); | 187 | error = configvernoutep(hw); |
| 184 | else | 188 | else |
| @@ -442,6 +446,7 @@ static void _rtl_fill_usb_tx_desc(u8 *txdesc) | |||
| 442 | SET_TX_DESC_LAST_SEG(txdesc, 1); | 446 | SET_TX_DESC_LAST_SEG(txdesc, 1); |
| 443 | SET_TX_DESC_FIRST_SEG(txdesc, 1); | 447 | SET_TX_DESC_FIRST_SEG(txdesc, 1); |
| 444 | } | 448 | } |
| 449 | |||
| 445 | /** | 450 | /** |
| 446 | * For HW recovery information | 451 | * For HW recovery information |
| 447 | */ | 452 | */ |
| @@ -531,11 +536,13 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, | |||
| 531 | sta = ieee80211_find_sta(mac->vif, mac->bssid); | 536 | sta = ieee80211_find_sta(mac->vif, mac->bssid); |
| 532 | if (sta) { | 537 | if (sta) { |
| 533 | u8 ampdu_density = sta->ht_cap.ampdu_density; | 538 | u8 ampdu_density = sta->ht_cap.ampdu_density; |
| 539 | |||
| 534 | SET_TX_DESC_AMPDU_DENSITY(txdesc, ampdu_density); | 540 | SET_TX_DESC_AMPDU_DENSITY(txdesc, ampdu_density); |
| 535 | } | 541 | } |
| 536 | rcu_read_unlock(); | 542 | rcu_read_unlock(); |
| 537 | if (info->control.hw_key) { | 543 | if (info->control.hw_key) { |
| 538 | struct ieee80211_key_conf *keyconf = info->control.hw_key; | 544 | struct ieee80211_key_conf *keyconf = info->control.hw_key; |
| 545 | |||
| 539 | switch (keyconf->cipher) { | 546 | switch (keyconf->cipher) { |
| 540 | case WLAN_CIPHER_SUITE_WEP40: | 547 | case WLAN_CIPHER_SUITE_WEP40: |
| 541 | case WLAN_CIPHER_SUITE_WEP104: | 548 | case WLAN_CIPHER_SUITE_WEP104: |
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h index 439ced0e18fa..ae2e8aa212de 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h | |||
| @@ -198,7 +198,6 @@ struct rx_drv_info_92c { | |||
| 198 | #define SET_TX_DESC_OWN(__txdesc, __value) \ | 198 | #define SET_TX_DESC_OWN(__txdesc, __value) \ |
| 199 | SET_BITS_TO_LE_4BYTE(__txdesc, 31, 1, __value) | 199 | SET_BITS_TO_LE_4BYTE(__txdesc, 31, 1, __value) |
| 200 | 200 | ||
| 201 | |||
| 202 | /* Dword 1 */ | 201 | /* Dword 1 */ |
| 203 | #define SET_TX_DESC_MACID(__txdesc, __value) \ | 202 | #define SET_TX_DESC_MACID(__txdesc, __value) \ |
| 204 | SET_BITS_TO_LE_4BYTE(__txdesc + 4, 0, 5, __value) | 203 | SET_BITS_TO_LE_4BYTE(__txdesc + 4, 0, 5, __value) |
| @@ -355,7 +354,6 @@ struct rx_drv_info_92c { | |||
| 355 | #define SET_TX_DESC_MCSG15_MAX_LEN(__txdesc, __value) \ | 354 | #define SET_TX_DESC_MCSG15_MAX_LEN(__txdesc, __value) \ |
| 356 | SET_BITS_TO_LE_4BYTE(__txdesc + 28, 28, 4, __value) | 355 | SET_BITS_TO_LE_4BYTE(__txdesc + 28, 28, 4, __value) |
| 357 | 356 | ||
| 358 | |||
| 359 | int rtl8192cu_endpoint_mapping(struct ieee80211_hw *hw); | 357 | int rtl8192cu_endpoint_mapping(struct ieee80211_hw *hw); |
| 360 | u16 rtl8192cu_mq_to_hwq(__le16 fc, u16 mac80211_queue_index); | 358 | u16 rtl8192cu_mq_to_hwq(__le16 fc, u16 mac80211_queue_index); |
| 361 | bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw, | 359 | bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw, |
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c index faa307a0b148..541b7881735e 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c | |||
| @@ -136,7 +136,6 @@ static bool _rtl92s_firmware_downloadcode(struct ieee80211_hw *hw, | |||
| 136 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 136 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 137 | struct sk_buff *skb; | 137 | struct sk_buff *skb; |
| 138 | struct rtl_tcb_desc *tcb_desc; | 138 | struct rtl_tcb_desc *tcb_desc; |
| 139 | unsigned char *seg_ptr; | ||
| 140 | u16 frag_threshold = MAX_FIRMWARE_CODE_SIZE; | 139 | u16 frag_threshold = MAX_FIRMWARE_CODE_SIZE; |
| 141 | u16 frag_length, frag_offset = 0; | 140 | u16 frag_length, frag_offset = 0; |
| 142 | u16 extra_descoffset = 0; | 141 | u16 extra_descoffset = 0; |
| @@ -166,9 +165,8 @@ static bool _rtl92s_firmware_downloadcode(struct ieee80211_hw *hw, | |||
| 166 | if (!skb) | 165 | if (!skb) |
| 167 | return false; | 166 | return false; |
| 168 | skb_reserve(skb, extra_descoffset); | 167 | skb_reserve(skb, extra_descoffset); |
| 169 | seg_ptr = skb_put_data(skb, | 168 | skb_put_data(skb, code_virtual_address + frag_offset, |
| 170 | code_virtual_address + frag_offset, | 169 | (u32)(frag_length - extra_descoffset)); |
| 171 | (u32)(frag_length - extra_descoffset)); | ||
| 172 | 170 | ||
| 173 | tcb_desc = (struct rtl_tcb_desc *)(skb->cb); | 171 | tcb_desc = (struct rtl_tcb_desc *)(skb->cb); |
| 174 | tcb_desc->queue_index = TXCMD_QUEUE; | 172 | tcb_desc->queue_index = TXCMD_QUEUE; |
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c index a6b31dae5691..680198280f8f 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c | |||
| @@ -1405,7 +1405,6 @@ static void rtl8723e_dm_bt_reset_action_profile_state(struct ieee80211_hw *hw) | |||
| 1405 | static void _rtl8723e_dm_bt_coexist_2_ant(struct ieee80211_hw *hw) | 1405 | static void _rtl8723e_dm_bt_coexist_2_ant(struct ieee80211_hw *hw) |
| 1406 | { | 1406 | { |
| 1407 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1407 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 1408 | u8 bt_retry_cnt; | ||
| 1409 | u8 bt_info_original; | 1408 | u8 bt_info_original; |
| 1410 | RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, | 1409 | RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, |
| 1411 | "[BTCoex] Get bt info by fw!!\n"); | 1410 | "[BTCoex] Get bt info by fw!!\n"); |
| @@ -1417,7 +1416,6 @@ static void _rtl8723e_dm_bt_coexist_2_ant(struct ieee80211_hw *hw) | |||
| 1417 | "[BTCoex] c2h for bt_info not rcvd yet!!\n"); | 1416 | "[BTCoex] c2h for bt_info not rcvd yet!!\n"); |
| 1418 | } | 1417 | } |
| 1419 | 1418 | ||
| 1420 | bt_retry_cnt = hal_coex_8723.bt_retry_cnt; | ||
| 1421 | bt_info_original = hal_coex_8723.c2h_bt_info_original; | 1419 | bt_info_original = hal_coex_8723.c2h_bt_info_original; |
| 1422 | 1420 | ||
| 1423 | /* when bt inquiry or page scan, we have to set h2c 0x25 */ | 1421 | /* when bt inquiry or page scan, we have to set h2c 0x25 */ |
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.c index ef355aa88117..b13fd3c0c832 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.c | |||
| @@ -995,12 +995,9 @@ static void rtl8723be_dm_check_edca_turbo(struct ieee80211_hw *hw) | |||
| 995 | u32 edca_be = 0x5ea42b; | 995 | u32 edca_be = 0x5ea42b; |
| 996 | u32 iot_peer = 0; | 996 | u32 iot_peer = 0; |
| 997 | bool b_is_cur_rdlstate; | 997 | bool b_is_cur_rdlstate; |
| 998 | bool b_last_is_cur_rdlstate = false; | ||
| 999 | bool b_bias_on_rx = false; | 998 | bool b_bias_on_rx = false; |
| 1000 | bool b_edca_turbo_on = false; | 999 | bool b_edca_turbo_on = false; |
| 1001 | 1000 | ||
| 1002 | b_last_is_cur_rdlstate = rtlpriv->dm.is_cur_rdlstate; | ||
| 1003 | |||
| 1004 | cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt; | 1001 | cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt; |
| 1005 | cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt; | 1002 | cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt; |
| 1006 | 1003 | ||
diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c index 525f72bad433..e24fda5e9087 100644 --- a/drivers/net/wireless/realtek/rtlwifi/usb.c +++ b/drivers/net/wireless/realtek/rtlwifi/usb.c | |||
| @@ -267,6 +267,7 @@ static int _rtl_usb_init_tx(struct ieee80211_hw *hw) | |||
| 267 | 267 | ||
| 268 | for (i = 0; i < __RTL_TXQ_NUM; i++) { | 268 | for (i = 0; i < __RTL_TXQ_NUM; i++) { |
| 269 | u32 ep_num = rtlusb->ep_map.ep_mapping[i]; | 269 | u32 ep_num = rtlusb->ep_map.ep_mapping[i]; |
| 270 | |||
| 270 | if (!ep_num) { | 271 | if (!ep_num) { |
| 271 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, | 272 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, |
| 272 | "Invalid endpoint map setting!\n"); | 273 | "Invalid endpoint map setting!\n"); |
| @@ -331,6 +332,7 @@ static int _rtl_usb_init(struct ieee80211_hw *hw) | |||
| 331 | rtlusb->out_ep_nums = rtlusb->in_ep_nums = 0; | 332 | rtlusb->out_ep_nums = rtlusb->in_ep_nums = 0; |
| 332 | for (epidx = 0; epidx < epnums; epidx++) { | 333 | for (epidx = 0; epidx < epnums; epidx++) { |
| 333 | struct usb_endpoint_descriptor *pep_desc; | 334 | struct usb_endpoint_descriptor *pep_desc; |
| 335 | |||
| 334 | pep_desc = &usb_intf->cur_altsetting->endpoint[epidx].desc; | 336 | pep_desc = &usb_intf->cur_altsetting->endpoint[epidx].desc; |
| 335 | 337 | ||
| 336 | if (usb_endpoint_dir_in(pep_desc)) | 338 | if (usb_endpoint_dir_in(pep_desc)) |
| @@ -753,6 +755,7 @@ static int rtl_usb_start(struct ieee80211_hw *hw) | |||
| 753 | 755 | ||
| 754 | return err; | 756 | return err; |
| 755 | } | 757 | } |
| 758 | |||
| 756 | /** | 759 | /** |
| 757 | * | 760 | * |
| 758 | * | 761 | * |
diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.h b/drivers/net/wireless/realtek/rtlwifi/usb.h index 09bbcdbe0dbf..3bf85b23eec1 100644 --- a/drivers/net/wireless/realtek/rtlwifi/usb.h +++ b/drivers/net/wireless/realtek/rtlwifi/usb.h | |||
| @@ -17,7 +17,6 @@ | |||
| 17 | #define USB_HIGH_SPEED_BULK_SIZE 512 | 17 | #define USB_HIGH_SPEED_BULK_SIZE 512 |
| 18 | #define USB_FULL_SPEED_BULK_SIZE 64 | 18 | #define USB_FULL_SPEED_BULK_SIZE 64 |
| 19 | 19 | ||
| 20 | |||
| 21 | #define RTL_USB_MAX_TXQ_NUM 4 /* max tx queue */ | 20 | #define RTL_USB_MAX_TXQ_NUM 4 /* max tx queue */ |
| 22 | #define RTL_USB_MAX_EP_NUM 6 /* max ep number */ | 21 | #define RTL_USB_MAX_EP_NUM 6 /* max ep number */ |
| 23 | #define RTL_USB_MAX_TX_URBS_NUM 8 | 22 | #define RTL_USB_MAX_TX_URBS_NUM 8 |
| @@ -53,11 +52,11 @@ static inline void _rtl_install_trx_info(struct rtl_usb *rtlusb, | |||
| 53 | u32 ep_num) | 52 | u32 ep_num) |
| 54 | { | 53 | { |
| 55 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 54 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
| 55 | |||
| 56 | info->rate_driver_data[0] = rtlusb; | 56 | info->rate_driver_data[0] = rtlusb; |
| 57 | info->rate_driver_data[1] = (void *)(__kernel_size_t)ep_num; | 57 | info->rate_driver_data[1] = (void *)(__kernel_size_t)ep_num; |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | |||
| 61 | /* Add suspend/resume later */ | 60 | /* Add suspend/resume later */ |
| 62 | enum rtl_usb_state { | 61 | enum rtl_usb_state { |
| 63 | USB_STATE_STOP = 0, | 62 | USB_STATE_STOP = 0, |
| @@ -133,8 +132,6 @@ struct rtl_usb_priv { | |||
| 133 | #define rtl_usbpriv(hw) (((struct rtl_usb_priv *)(rtl_priv(hw))->priv)) | 132 | #define rtl_usbpriv(hw) (((struct rtl_usb_priv *)(rtl_priv(hw))->priv)) |
| 134 | #define rtl_usbdev(usbpriv) (&((usbpriv)->dev)) | 133 | #define rtl_usbdev(usbpriv) (&((usbpriv)->dev)) |
| 135 | 134 | ||
| 136 | |||
| 137 | |||
| 138 | int rtl_usb_probe(struct usb_interface *intf, | 135 | int rtl_usb_probe(struct usb_interface *intf, |
| 139 | const struct usb_device_id *id, | 136 | const struct usb_device_id *id, |
| 140 | struct rtl_hal_cfg *rtl92cu_hal_cfg); | 137 | struct rtl_hal_cfg *rtl92cu_hal_cfg); |
diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h index 1ad71fb0ebf2..e32e9ffa3192 100644 --- a/drivers/net/wireless/realtek/rtlwifi/wifi.h +++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h | |||
| @@ -413,8 +413,8 @@ enum hw_variables { | |||
| 413 | HW_VAR_MULTICAST_REG = 0x1, | 413 | HW_VAR_MULTICAST_REG = 0x1, |
| 414 | HW_VAR_BASIC_RATE = 0x2, | 414 | HW_VAR_BASIC_RATE = 0x2, |
| 415 | HW_VAR_BSSID = 0x3, | 415 | HW_VAR_BSSID = 0x3, |
| 416 | HW_VAR_MEDIA_STATUS= 0x4, | 416 | HW_VAR_MEDIA_STATUS = 0x4, |
| 417 | HW_VAR_SECURITY_CONF= 0x5, | 417 | HW_VAR_SECURITY_CONF = 0x5, |
| 418 | HW_VAR_BEACON_INTERVAL = 0x6, | 418 | HW_VAR_BEACON_INTERVAL = 0x6, |
| 419 | HW_VAR_ATIM_WINDOW = 0x7, | 419 | HW_VAR_ATIM_WINDOW = 0x7, |
| 420 | HW_VAR_LISTEN_INTERVAL = 0x8, | 420 | HW_VAR_LISTEN_INTERVAL = 0x8, |
| @@ -431,7 +431,7 @@ enum hw_variables { | |||
| 431 | HW_VAR_ACK_PREAMBLE = 0x13, | 431 | HW_VAR_ACK_PREAMBLE = 0x13, |
| 432 | HW_VAR_CW_CONFIG = 0x14, | 432 | HW_VAR_CW_CONFIG = 0x14, |
| 433 | HW_VAR_CW_VALUES = 0x15, | 433 | HW_VAR_CW_VALUES = 0x15, |
| 434 | HW_VAR_RATE_FALLBACK_CONTROL= 0x16, | 434 | HW_VAR_RATE_FALLBACK_CONTROL = 0x16, |
| 435 | HW_VAR_CONTENTION_WINDOW = 0x17, | 435 | HW_VAR_CONTENTION_WINDOW = 0x17, |
| 436 | HW_VAR_RETRY_COUNT = 0x18, | 436 | HW_VAR_RETRY_COUNT = 0x18, |
| 437 | HW_VAR_TR_SWITCH = 0x19, | 437 | HW_VAR_TR_SWITCH = 0x19, |
| @@ -598,7 +598,8 @@ enum ht_channel_width { | |||
| 598 | }; | 598 | }; |
| 599 | 599 | ||
| 600 | /* Ref: 802.11i sepc D10.0 7.3.2.25.1 | 600 | /* Ref: 802.11i sepc D10.0 7.3.2.25.1 |
| 601 | Cipher Suites Encryption Algorithms */ | 601 | * Cipher Suites Encryption Algorithms |
| 602 | */ | ||
| 602 | enum rt_enc_alg { | 603 | enum rt_enc_alg { |
| 603 | NO_ENCRYPTION = 0, | 604 | NO_ENCRYPTION = 0, |
| 604 | WEP40_ENCRYPTION = 1, | 605 | WEP40_ENCRYPTION = 1, |
| @@ -748,7 +749,8 @@ enum rtl_var_map { | |||
| 748 | RTL_IMR_ROK, /*Receive DMA OK Interrupt */ | 749 | RTL_IMR_ROK, /*Receive DMA OK Interrupt */ |
| 749 | RTL_IMR_HSISR_IND, /*HSISR Interrupt*/ | 750 | RTL_IMR_HSISR_IND, /*HSISR Interrupt*/ |
| 750 | RTL_IBSS_INT_MASKS, /*(RTL_IMR_BCNINT | RTL_IMR_TBDOK | | 751 | RTL_IBSS_INT_MASKS, /*(RTL_IMR_BCNINT | RTL_IMR_TBDOK | |
| 751 | * RTL_IMR_TBDER) */ | 752 | * RTL_IMR_TBDER) |
| 753 | */ | ||
| 752 | RTL_IMR_C2HCMD, /*fw interrupt*/ | 754 | RTL_IMR_C2HCMD, /*fw interrupt*/ |
| 753 | 755 | ||
| 754 | /*CCK Rates, TxHT = 0 */ | 756 | /*CCK Rates, TxHT = 0 */ |
| @@ -845,8 +847,9 @@ enum band_type { | |||
| 845 | BANDMAX | 847 | BANDMAX |
| 846 | }; | 848 | }; |
| 847 | 849 | ||
| 848 | /*aci/aifsn Field. | 850 | /* aci/aifsn Field. |
| 849 | Ref: WMM spec 2.2.2: WME Parameter Element, p.12.*/ | 851 | * Ref: WMM spec 2.2.2: WME Parameter Element, p.12. |
| 852 | */ | ||
| 850 | union aci_aifsn { | 853 | union aci_aifsn { |
| 851 | u8 char_data; | 854 | u8 char_data; |
| 852 | 855 | ||
| @@ -1062,7 +1065,8 @@ struct rtl_probe_rsp { | |||
| 1062 | __le16 beacon_interval; | 1065 | __le16 beacon_interval; |
| 1063 | __le16 capability; | 1066 | __le16 capability; |
| 1064 | /*SSID, supported rates, FH params, DS params, | 1067 | /*SSID, supported rates, FH params, DS params, |
| 1065 | CF params, IBSS params, TIM (if beacon), RSN */ | 1068 | * CF params, IBSS params, TIM (if beacon), RSN |
| 1069 | */ | ||
| 1066 | struct rtl_info_element info_element[0]; | 1070 | struct rtl_info_element info_element[0]; |
| 1067 | } __packed; | 1071 | } __packed; |
| 1068 | 1072 | ||
| @@ -1136,7 +1140,8 @@ struct wireless_stats { | |||
| 1136 | 1140 | ||
| 1137 | long rx_snr_db[4]; | 1141 | long rx_snr_db[4]; |
| 1138 | /*Correct smoothed ss in Dbm, only used | 1142 | /*Correct smoothed ss in Dbm, only used |
| 1139 | in driver to report real power now. */ | 1143 | * in driver to report real power now. |
| 1144 | */ | ||
| 1140 | long recv_signal_power; | 1145 | long recv_signal_power; |
| 1141 | long signal_quality; | 1146 | long signal_quality; |
| 1142 | long last_sigstrength_inpercent; | 1147 | long last_sigstrength_inpercent; |
| @@ -1144,8 +1149,9 @@ struct wireless_stats { | |||
| 1144 | u32 rssi_calculate_cnt; | 1149 | u32 rssi_calculate_cnt; |
| 1145 | u32 pwdb_all_cnt; | 1150 | u32 pwdb_all_cnt; |
| 1146 | 1151 | ||
| 1147 | /*Transformed, in dbm. Beautified signal | 1152 | /* Transformed, in dbm. Beautified signal |
| 1148 | strength for UI, not correct. */ | 1153 | * strength for UI, not correct. |
| 1154 | */ | ||
| 1149 | long signal_strength; | 1155 | long signal_strength; |
| 1150 | 1156 | ||
| 1151 | u8 rx_rssi_percentage[4]; | 1157 | u8 rx_rssi_percentage[4]; |
| @@ -1456,15 +1462,15 @@ struct rtl_io { | |||
| 1456 | /*PCI IO map */ | 1462 | /*PCI IO map */ |
| 1457 | unsigned long pci_base_addr; /*device I/O address */ | 1463 | unsigned long pci_base_addr; /*device I/O address */ |
| 1458 | 1464 | ||
| 1459 | void (*write8_async) (struct rtl_priv *rtlpriv, u32 addr, u8 val); | 1465 | void (*write8_async)(struct rtl_priv *rtlpriv, u32 addr, u8 val); |
| 1460 | void (*write16_async) (struct rtl_priv *rtlpriv, u32 addr, u16 val); | 1466 | void (*write16_async)(struct rtl_priv *rtlpriv, u32 addr, u16 val); |
| 1461 | void (*write32_async) (struct rtl_priv *rtlpriv, u32 addr, u32 val); | 1467 | void (*write32_async)(struct rtl_priv *rtlpriv, u32 addr, u32 val); |
| 1462 | void (*writen_sync)(struct rtl_priv *rtlpriv, u32 addr, void *buf, | 1468 | void (*writen_sync)(struct rtl_priv *rtlpriv, u32 addr, void *buf, |
| 1463 | u16 len); | 1469 | u16 len); |
| 1464 | 1470 | ||
| 1465 | u8(*read8_sync) (struct rtl_priv *rtlpriv, u32 addr); | 1471 | u8 (*read8_sync)(struct rtl_priv *rtlpriv, u32 addr); |
| 1466 | u16(*read16_sync) (struct rtl_priv *rtlpriv, u32 addr); | 1472 | u16 (*read16_sync)(struct rtl_priv *rtlpriv, u32 addr); |
| 1467 | u32(*read32_sync) (struct rtl_priv *rtlpriv, u32 addr); | 1473 | u32 (*read32_sync)(struct rtl_priv *rtlpriv, u32 addr); |
| 1468 | 1474 | ||
| 1469 | }; | 1475 | }; |
| 1470 | 1476 | ||
| @@ -1689,7 +1695,8 @@ struct rtl_hal { | |||
| 1689 | bool during_mac1init_radioa; | 1695 | bool during_mac1init_radioa; |
| 1690 | bool reloadtxpowerindex; | 1696 | bool reloadtxpowerindex; |
| 1691 | /* True if IMR or IQK have done | 1697 | /* True if IMR or IQK have done |
| 1692 | for 2.4G in scan progress */ | 1698 | * for 2.4G in scan progress |
| 1699 | */ | ||
| 1693 | bool load_imrandiqk_setting_for2g; | 1700 | bool load_imrandiqk_setting_for2g; |
| 1694 | 1701 | ||
| 1695 | bool disable_amsdu_8k; | 1702 | bool disable_amsdu_8k; |
| @@ -1728,12 +1735,14 @@ struct rtl_security { | |||
| 1728 | u32 hwsec_cam_bitmap; | 1735 | u32 hwsec_cam_bitmap; |
| 1729 | u8 hwsec_cam_sta_addr[TOTAL_CAM_ENTRY][ETH_ALEN]; | 1736 | u8 hwsec_cam_sta_addr[TOTAL_CAM_ENTRY][ETH_ALEN]; |
| 1730 | /*local Key buffer, indx 0 is for | 1737 | /*local Key buffer, indx 0 is for |
| 1731 | pairwise key 1-4 is for agoup key. */ | 1738 | * pairwise key 1-4 is for agoup key. |
| 1739 | */ | ||
| 1732 | u8 key_buf[KEY_BUF_SIZE][MAX_KEY_LEN]; | 1740 | u8 key_buf[KEY_BUF_SIZE][MAX_KEY_LEN]; |
| 1733 | u8 key_len[KEY_BUF_SIZE]; | 1741 | u8 key_len[KEY_BUF_SIZE]; |
| 1734 | 1742 | ||
| 1735 | /*The pointer of Pairwise Key, | 1743 | /*The pointer of Pairwise Key, |
| 1736 | it always points to KeyBuf[4] */ | 1744 | * it always points to KeyBuf[4] |
| 1745 | */ | ||
| 1737 | u8 *pairwise_key; | 1746 | u8 *pairwise_key; |
| 1738 | }; | 1747 | }; |
| 1739 | 1748 | ||
| @@ -1997,11 +2006,10 @@ struct rtl_ps_ctl { | |||
| 1997 | bool rfchange_inprogress; | 2006 | bool rfchange_inprogress; |
| 1998 | bool swrf_processing; | 2007 | bool swrf_processing; |
| 1999 | bool hwradiooff; | 2008 | bool hwradiooff; |
| 2000 | /* | 2009 | /* just for PCIE ASPM |
| 2001 | * just for PCIE ASPM | ||
| 2002 | * If it supports ASPM, Offset[560h] = 0x40, | 2010 | * If it supports ASPM, Offset[560h] = 0x40, |
| 2003 | * otherwise Offset[560h] = 0x00. | 2011 | * otherwise Offset[560h] = 0x00. |
| 2004 | * */ | 2012 | */ |
| 2005 | bool support_aspm; | 2013 | bool support_aspm; |
| 2006 | bool support_backdoor; | 2014 | bool support_backdoor; |
| 2007 | 2015 | ||
| @@ -2081,10 +2089,9 @@ struct rtl_stats { | |||
| 2081 | u8 nic_type; | 2089 | u8 nic_type; |
| 2082 | u16 length; | 2090 | u16 length; |
| 2083 | u8 signalquality; /*in 0-100 index. */ | 2091 | u8 signalquality; /*in 0-100 index. */ |
| 2084 | /* | 2092 | /* Real power in dBm for this packet, |
| 2085 | * Real power in dBm for this packet, | ||
| 2086 | * no beautification and aggregation. | 2093 | * no beautification and aggregation. |
| 2087 | * */ | 2094 | */ |
| 2088 | s32 recvsignalpower; | 2095 | s32 recvsignalpower; |
| 2089 | s8 rxpower; /*in dBm Translate from PWdB */ | 2096 | s8 rxpower; /*in dBm Translate from PWdB */ |
| 2090 | u8 signalstrength; /*in 0-100 index. */ | 2097 | u8 signalstrength; /*in 0-100 index. */ |
| @@ -2136,7 +2143,6 @@ struct rtl_stats { | |||
| 2136 | u32 macid_valid_entry[2]; | 2143 | u32 macid_valid_entry[2]; |
| 2137 | }; | 2144 | }; |
| 2138 | 2145 | ||
| 2139 | |||
| 2140 | struct rt_link_detect { | 2146 | struct rt_link_detect { |
| 2141 | /* count for roaming */ | 2147 | /* count for roaming */ |
| 2142 | u32 bcn_rx_inperiod; | 2148 | u32 bcn_rx_inperiod; |
| @@ -2210,114 +2216,114 @@ struct rtl_int { | |||
| 2210 | }; | 2216 | }; |
| 2211 | 2217 | ||
| 2212 | struct rtl_hal_ops { | 2218 | struct rtl_hal_ops { |
| 2213 | int (*init_sw_vars) (struct ieee80211_hw *hw); | 2219 | int (*init_sw_vars)(struct ieee80211_hw *hw); |
| 2214 | void (*deinit_sw_vars) (struct ieee80211_hw *hw); | 2220 | void (*deinit_sw_vars)(struct ieee80211_hw *hw); |
| 2215 | void (*read_chip_version)(struct ieee80211_hw *hw); | 2221 | void (*read_chip_version)(struct ieee80211_hw *hw); |
| 2216 | void (*read_eeprom_info) (struct ieee80211_hw *hw); | 2222 | void (*read_eeprom_info)(struct ieee80211_hw *hw); |
| 2217 | void (*interrupt_recognized) (struct ieee80211_hw *hw, | 2223 | void (*interrupt_recognized)(struct ieee80211_hw *hw, |
| 2218 | struct rtl_int *intvec); | 2224 | struct rtl_int *intvec); |
| 2219 | int (*hw_init) (struct ieee80211_hw *hw); | 2225 | int (*hw_init)(struct ieee80211_hw *hw); |
| 2220 | void (*hw_disable) (struct ieee80211_hw *hw); | 2226 | void (*hw_disable)(struct ieee80211_hw *hw); |
| 2221 | void (*hw_suspend) (struct ieee80211_hw *hw); | 2227 | void (*hw_suspend)(struct ieee80211_hw *hw); |
| 2222 | void (*hw_resume) (struct ieee80211_hw *hw); | 2228 | void (*hw_resume)(struct ieee80211_hw *hw); |
| 2223 | void (*enable_interrupt) (struct ieee80211_hw *hw); | 2229 | void (*enable_interrupt)(struct ieee80211_hw *hw); |
| 2224 | void (*disable_interrupt) (struct ieee80211_hw *hw); | 2230 | void (*disable_interrupt)(struct ieee80211_hw *hw); |
| 2225 | int (*set_network_type) (struct ieee80211_hw *hw, | 2231 | int (*set_network_type)(struct ieee80211_hw *hw, |
| 2226 | enum nl80211_iftype type); | 2232 | enum nl80211_iftype type); |
| 2227 | void (*set_chk_bssid)(struct ieee80211_hw *hw, | 2233 | void (*set_chk_bssid)(struct ieee80211_hw *hw, |
| 2228 | bool check_bssid); | 2234 | bool check_bssid); |
| 2229 | void (*set_bw_mode) (struct ieee80211_hw *hw, | 2235 | void (*set_bw_mode)(struct ieee80211_hw *hw, |
| 2230 | enum nl80211_channel_type ch_type); | 2236 | enum nl80211_channel_type ch_type); |
| 2231 | u8(*switch_channel) (struct ieee80211_hw *hw); | 2237 | u8 (*switch_channel)(struct ieee80211_hw *hw); |
| 2232 | void (*set_qos) (struct ieee80211_hw *hw, int aci); | 2238 | void (*set_qos)(struct ieee80211_hw *hw, int aci); |
| 2233 | void (*set_bcn_reg) (struct ieee80211_hw *hw); | 2239 | void (*set_bcn_reg)(struct ieee80211_hw *hw); |
| 2234 | void (*set_bcn_intv) (struct ieee80211_hw *hw); | 2240 | void (*set_bcn_intv)(struct ieee80211_hw *hw); |
| 2235 | void (*update_interrupt_mask) (struct ieee80211_hw *hw, | 2241 | void (*update_interrupt_mask)(struct ieee80211_hw *hw, |
| 2236 | u32 add_msr, u32 rm_msr); | 2242 | u32 add_msr, u32 rm_msr); |
| 2237 | void (*get_hw_reg) (struct ieee80211_hw *hw, u8 variable, u8 *val); | 2243 | void (*get_hw_reg)(struct ieee80211_hw *hw, u8 variable, u8 *val); |
| 2238 | void (*set_hw_reg) (struct ieee80211_hw *hw, u8 variable, u8 *val); | 2244 | void (*set_hw_reg)(struct ieee80211_hw *hw, u8 variable, u8 *val); |
| 2239 | void (*update_rate_tbl) (struct ieee80211_hw *hw, | 2245 | void (*update_rate_tbl)(struct ieee80211_hw *hw, |
| 2240 | struct ieee80211_sta *sta, u8 rssi_leve, | 2246 | struct ieee80211_sta *sta, u8 rssi_leve, |
| 2241 | bool update_bw); | 2247 | bool update_bw); |
| 2242 | void (*pre_fill_tx_bd_desc)(struct ieee80211_hw *hw, u8 *tx_bd_desc, | 2248 | void (*pre_fill_tx_bd_desc)(struct ieee80211_hw *hw, u8 *tx_bd_desc, |
| 2243 | u8 *desc, u8 queue_index, | 2249 | u8 *desc, u8 queue_index, |
| 2244 | struct sk_buff *skb, dma_addr_t addr); | 2250 | struct sk_buff *skb, dma_addr_t addr); |
| 2245 | void (*update_rate_mask) (struct ieee80211_hw *hw, u8 rssi_level); | 2251 | void (*update_rate_mask)(struct ieee80211_hw *hw, u8 rssi_level); |
| 2246 | u16 (*rx_desc_buff_remained_cnt)(struct ieee80211_hw *hw, | 2252 | u16 (*rx_desc_buff_remained_cnt)(struct ieee80211_hw *hw, |
| 2247 | u8 queue_index); | 2253 | u8 queue_index); |
| 2248 | void (*rx_check_dma_ok)(struct ieee80211_hw *hw, u8 *header_desc, | 2254 | void (*rx_check_dma_ok)(struct ieee80211_hw *hw, u8 *header_desc, |
| 2249 | u8 queue_index); | 2255 | u8 queue_index); |
| 2250 | void (*fill_tx_desc) (struct ieee80211_hw *hw, | 2256 | void (*fill_tx_desc)(struct ieee80211_hw *hw, |
| 2251 | struct ieee80211_hdr *hdr, u8 *pdesc_tx, | 2257 | struct ieee80211_hdr *hdr, u8 *pdesc_tx, |
| 2252 | u8 *pbd_desc_tx, | 2258 | u8 *pbd_desc_tx, |
| 2253 | struct ieee80211_tx_info *info, | 2259 | struct ieee80211_tx_info *info, |
| 2254 | struct ieee80211_sta *sta, | 2260 | struct ieee80211_sta *sta, |
| 2255 | struct sk_buff *skb, u8 hw_queue, | 2261 | struct sk_buff *skb, u8 hw_queue, |
| 2256 | struct rtl_tcb_desc *ptcb_desc); | 2262 | struct rtl_tcb_desc *ptcb_desc); |
| 2257 | void (*fill_fake_txdesc)(struct ieee80211_hw *hw, u8 *pdesc, | 2263 | void (*fill_fake_txdesc)(struct ieee80211_hw *hw, u8 *pdesc, |
| 2258 | u32 buffer_len, bool bsspspoll); | 2264 | u32 buffer_len, bool bsspspoll); |
| 2259 | void (*fill_tx_cmddesc) (struct ieee80211_hw *hw, u8 *pdesc, | 2265 | void (*fill_tx_cmddesc)(struct ieee80211_hw *hw, u8 *pdesc, |
| 2260 | bool firstseg, bool lastseg, | 2266 | bool firstseg, bool lastseg, |
| 2261 | struct sk_buff *skb); | 2267 | struct sk_buff *skb); |
| 2262 | void (*fill_tx_special_desc)(struct ieee80211_hw *hw, | 2268 | void (*fill_tx_special_desc)(struct ieee80211_hw *hw, |
| 2263 | u8 *pdesc, u8 *pbd_desc, | 2269 | u8 *pdesc, u8 *pbd_desc, |
| 2264 | struct sk_buff *skb, u8 hw_queue); | 2270 | struct sk_buff *skb, u8 hw_queue); |
| 2265 | bool (*query_rx_desc) (struct ieee80211_hw *hw, | 2271 | bool (*query_rx_desc)(struct ieee80211_hw *hw, |
| 2266 | struct rtl_stats *stats, | 2272 | struct rtl_stats *stats, |
| 2267 | struct ieee80211_rx_status *rx_status, | 2273 | struct ieee80211_rx_status *rx_status, |
| 2268 | u8 *pdesc, struct sk_buff *skb); | 2274 | u8 *pdesc, struct sk_buff *skb); |
| 2269 | void (*set_channel_access) (struct ieee80211_hw *hw); | 2275 | void (*set_channel_access)(struct ieee80211_hw *hw); |
| 2270 | bool (*radio_onoff_checking) (struct ieee80211_hw *hw, u8 *valid); | 2276 | bool (*radio_onoff_checking)(struct ieee80211_hw *hw, u8 *valid); |
| 2271 | void (*dm_watchdog) (struct ieee80211_hw *hw); | 2277 | void (*dm_watchdog)(struct ieee80211_hw *hw); |
| 2272 | void (*scan_operation_backup) (struct ieee80211_hw *hw, u8 operation); | 2278 | void (*scan_operation_backup)(struct ieee80211_hw *hw, u8 operation); |
| 2273 | bool (*set_rf_power_state) (struct ieee80211_hw *hw, | 2279 | bool (*set_rf_power_state)(struct ieee80211_hw *hw, |
| 2274 | enum rf_pwrstate rfpwr_state); | 2280 | enum rf_pwrstate rfpwr_state); |
| 2275 | void (*led_control) (struct ieee80211_hw *hw, | 2281 | void (*led_control)(struct ieee80211_hw *hw, |
| 2276 | enum led_ctl_mode ledaction); | 2282 | enum led_ctl_mode ledaction); |
| 2277 | void (*set_desc)(struct ieee80211_hw *hw, u8 *pdesc, bool istx, | 2283 | void (*set_desc)(struct ieee80211_hw *hw, u8 *pdesc, bool istx, |
| 2278 | u8 desc_name, u8 *val); | 2284 | u8 desc_name, u8 *val); |
| 2279 | u64 (*get_desc)(struct ieee80211_hw *hw, u8 *pdesc, bool istx, | 2285 | u64 (*get_desc)(struct ieee80211_hw *hw, u8 *pdesc, bool istx, |
| 2280 | u8 desc_name); | 2286 | u8 desc_name); |
| 2281 | bool (*is_tx_desc_closed) (struct ieee80211_hw *hw, | 2287 | bool (*is_tx_desc_closed)(struct ieee80211_hw *hw, |
| 2282 | u8 hw_queue, u16 index); | 2288 | u8 hw_queue, u16 index); |
| 2283 | void (*tx_polling) (struct ieee80211_hw *hw, u8 hw_queue); | 2289 | void (*tx_polling)(struct ieee80211_hw *hw, u8 hw_queue); |
| 2284 | void (*enable_hw_sec) (struct ieee80211_hw *hw); | 2290 | void (*enable_hw_sec)(struct ieee80211_hw *hw); |
| 2285 | void (*set_key) (struct ieee80211_hw *hw, u32 key_index, | 2291 | void (*set_key)(struct ieee80211_hw *hw, u32 key_index, |
| 2286 | u8 *macaddr, bool is_group, u8 enc_algo, | 2292 | u8 *macaddr, bool is_group, u8 enc_algo, |
| 2287 | bool is_wepkey, bool clear_all); | 2293 | bool is_wepkey, bool clear_all); |
| 2288 | void (*init_sw_leds) (struct ieee80211_hw *hw); | 2294 | void (*init_sw_leds)(struct ieee80211_hw *hw); |
| 2289 | void (*deinit_sw_leds) (struct ieee80211_hw *hw); | 2295 | void (*deinit_sw_leds)(struct ieee80211_hw *hw); |
| 2290 | u32 (*get_bbreg) (struct ieee80211_hw *hw, u32 regaddr, u32 bitmask); | 2296 | u32 (*get_bbreg)(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask); |
| 2291 | void (*set_bbreg) (struct ieee80211_hw *hw, u32 regaddr, u32 bitmask, | 2297 | void (*set_bbreg)(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask, |
| 2292 | u32 data); | 2298 | u32 data); |
| 2293 | u32 (*get_rfreg) (struct ieee80211_hw *hw, enum radio_path rfpath, | 2299 | u32 (*get_rfreg)(struct ieee80211_hw *hw, enum radio_path rfpath, |
| 2294 | u32 regaddr, u32 bitmask); | 2300 | u32 regaddr, u32 bitmask); |
| 2295 | void (*set_rfreg) (struct ieee80211_hw *hw, enum radio_path rfpath, | 2301 | void (*set_rfreg)(struct ieee80211_hw *hw, enum radio_path rfpath, |
| 2296 | u32 regaddr, u32 bitmask, u32 data); | 2302 | u32 regaddr, u32 bitmask, u32 data); |
| 2297 | void (*linked_set_reg) (struct ieee80211_hw *hw); | 2303 | void (*linked_set_reg)(struct ieee80211_hw *hw); |
| 2298 | void (*chk_switch_dmdp) (struct ieee80211_hw *hw); | 2304 | void (*chk_switch_dmdp)(struct ieee80211_hw *hw); |
| 2299 | void (*dualmac_easy_concurrent) (struct ieee80211_hw *hw); | 2305 | void (*dualmac_easy_concurrent)(struct ieee80211_hw *hw); |
| 2300 | void (*dualmac_switch_to_dmdp) (struct ieee80211_hw *hw); | 2306 | void (*dualmac_switch_to_dmdp)(struct ieee80211_hw *hw); |
| 2301 | bool (*phy_rf6052_config) (struct ieee80211_hw *hw); | 2307 | bool (*phy_rf6052_config)(struct ieee80211_hw *hw); |
| 2302 | void (*phy_rf6052_set_cck_txpower) (struct ieee80211_hw *hw, | 2308 | void (*phy_rf6052_set_cck_txpower)(struct ieee80211_hw *hw, |
| 2303 | u8 *powerlevel); | 2309 | u8 *powerlevel); |
| 2304 | void (*phy_rf6052_set_ofdm_txpower) (struct ieee80211_hw *hw, | 2310 | void (*phy_rf6052_set_ofdm_txpower)(struct ieee80211_hw *hw, |
| 2305 | u8 *ppowerlevel, u8 channel); | 2311 | u8 *ppowerlevel, u8 channel); |
| 2306 | bool (*config_bb_with_headerfile) (struct ieee80211_hw *hw, | 2312 | bool (*config_bb_with_headerfile)(struct ieee80211_hw *hw, |
| 2307 | u8 configtype); | 2313 | u8 configtype); |
| 2308 | bool (*config_bb_with_pgheaderfile) (struct ieee80211_hw *hw, | 2314 | bool (*config_bb_with_pgheaderfile)(struct ieee80211_hw *hw, |
| 2309 | u8 configtype); | 2315 | u8 configtype); |
| 2310 | void (*phy_lc_calibrate) (struct ieee80211_hw *hw, bool is2t); | 2316 | void (*phy_lc_calibrate)(struct ieee80211_hw *hw, bool is2t); |
| 2311 | void (*phy_set_bw_mode_callback) (struct ieee80211_hw *hw); | 2317 | void (*phy_set_bw_mode_callback)(struct ieee80211_hw *hw); |
| 2312 | void (*dm_dynamic_txpower) (struct ieee80211_hw *hw); | 2318 | void (*dm_dynamic_txpower)(struct ieee80211_hw *hw); |
| 2313 | void (*c2h_command_handle) (struct ieee80211_hw *hw); | 2319 | void (*c2h_command_handle)(struct ieee80211_hw *hw); |
| 2314 | void (*bt_wifi_media_status_notify) (struct ieee80211_hw *hw, | 2320 | void (*bt_wifi_media_status_notify)(struct ieee80211_hw *hw, |
| 2315 | bool mstate); | 2321 | bool mstate); |
| 2316 | void (*bt_coex_off_before_lps) (struct ieee80211_hw *hw); | 2322 | void (*bt_coex_off_before_lps)(struct ieee80211_hw *hw); |
| 2317 | void (*fill_h2c_cmd) (struct ieee80211_hw *hw, u8 element_id, | 2323 | void (*fill_h2c_cmd)(struct ieee80211_hw *hw, u8 element_id, |
| 2318 | u32 cmd_len, u8 *p_cmdbuffer); | 2324 | u32 cmd_len, u8 *p_cmdbuffer); |
| 2319 | void (*set_default_port_id_cmd)(struct ieee80211_hw *hw); | 2325 | void (*set_default_port_id_cmd)(struct ieee80211_hw *hw); |
| 2320 | bool (*get_btc_status) (void); | 2326 | bool (*get_btc_status)(void); |
| 2321 | bool (*is_fw_header)(struct rtlwifi_firmware_header *hdr); | 2327 | bool (*is_fw_header)(struct rtlwifi_firmware_header *hdr); |
| 2322 | void (*add_wowlan_pattern)(struct ieee80211_hw *hw, | 2328 | void (*add_wowlan_pattern)(struct ieee80211_hw *hw, |
| 2323 | struct rtl_wow_pattern *rtl_pattern, | 2329 | struct rtl_wow_pattern *rtl_pattern, |
| @@ -2330,24 +2336,24 @@ struct rtl_hal_ops { | |||
| 2330 | struct rtl_intf_ops { | 2336 | struct rtl_intf_ops { |
| 2331 | /*com */ | 2337 | /*com */ |
| 2332 | void (*read_efuse_byte)(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf); | 2338 | void (*read_efuse_byte)(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf); |
| 2333 | int (*adapter_start) (struct ieee80211_hw *hw); | 2339 | int (*adapter_start)(struct ieee80211_hw *hw); |
| 2334 | void (*adapter_stop) (struct ieee80211_hw *hw); | 2340 | void (*adapter_stop)(struct ieee80211_hw *hw); |
| 2335 | bool (*check_buddy_priv)(struct ieee80211_hw *hw, | 2341 | bool (*check_buddy_priv)(struct ieee80211_hw *hw, |
| 2336 | struct rtl_priv **buddy_priv); | 2342 | struct rtl_priv **buddy_priv); |
| 2337 | 2343 | ||
| 2338 | int (*adapter_tx) (struct ieee80211_hw *hw, | 2344 | int (*adapter_tx)(struct ieee80211_hw *hw, |
| 2339 | struct ieee80211_sta *sta, | 2345 | struct ieee80211_sta *sta, |
| 2340 | struct sk_buff *skb, | 2346 | struct sk_buff *skb, |
| 2341 | struct rtl_tcb_desc *ptcb_desc); | 2347 | struct rtl_tcb_desc *ptcb_desc); |
| 2342 | void (*flush)(struct ieee80211_hw *hw, u32 queues, bool drop); | 2348 | void (*flush)(struct ieee80211_hw *hw, u32 queues, bool drop); |
| 2343 | int (*reset_trx_ring) (struct ieee80211_hw *hw); | 2349 | int (*reset_trx_ring)(struct ieee80211_hw *hw); |
| 2344 | bool (*waitq_insert) (struct ieee80211_hw *hw, | 2350 | bool (*waitq_insert)(struct ieee80211_hw *hw, |
| 2345 | struct ieee80211_sta *sta, | 2351 | struct ieee80211_sta *sta, |
| 2346 | struct sk_buff *skb); | 2352 | struct sk_buff *skb); |
| 2347 | 2353 | ||
| 2348 | /*pci */ | 2354 | /*pci */ |
| 2349 | void (*disable_aspm) (struct ieee80211_hw *hw); | 2355 | void (*disable_aspm)(struct ieee80211_hw *hw); |
| 2350 | void (*enable_aspm) (struct ieee80211_hw *hw); | 2356 | void (*enable_aspm)(struct ieee80211_hw *hw); |
| 2351 | 2357 | ||
| 2352 | /*usb */ | 2358 | /*usb */ |
| 2353 | }; | 2359 | }; |
| @@ -2425,7 +2431,8 @@ struct rtl_hal_cfg { | |||
| 2425 | enum rtl_spec_ver spec_ver; | 2431 | enum rtl_spec_ver spec_ver; |
| 2426 | 2432 | ||
| 2427 | /*this map used for some registers or vars | 2433 | /*this map used for some registers or vars |
| 2428 | defined int HAL but used in MAIN */ | 2434 | * defined int HAL but used in MAIN |
| 2435 | */ | ||
| 2429 | u32 maps[RTL_VAR_MAP_MAX]; | 2436 | u32 maps[RTL_VAR_MAP_MAX]; |
| 2430 | 2437 | ||
| 2431 | }; | 2438 | }; |
| @@ -2587,7 +2594,8 @@ struct dig_t { | |||
| 2587 | 2594 | ||
| 2588 | struct rtl_global_var { | 2595 | struct rtl_global_var { |
| 2589 | /* from this list we can get | 2596 | /* from this list we can get |
| 2590 | * other adapter's rtl_priv */ | 2597 | * other adapter's rtl_priv |
| 2598 | */ | ||
| 2591 | struct list_head glb_priv_list; | 2599 | struct list_head glb_priv_list; |
| 2592 | spinlock_t glb_list_lock; | 2600 | spinlock_t glb_list_lock; |
| 2593 | }; | 2601 | }; |
| @@ -2666,30 +2674,30 @@ struct bt_coexist_info { | |||
| 2666 | }; | 2674 | }; |
| 2667 | 2675 | ||
| 2668 | struct rtl_btc_ops { | 2676 | struct rtl_btc_ops { |
| 2669 | void (*btc_init_variables) (struct rtl_priv *rtlpriv); | 2677 | void (*btc_init_variables)(struct rtl_priv *rtlpriv); |
| 2670 | void (*btc_init_variables_wifi_only)(struct rtl_priv *rtlpriv); | 2678 | void (*btc_init_variables_wifi_only)(struct rtl_priv *rtlpriv); |
| 2671 | void (*btc_deinit_variables)(struct rtl_priv *rtlpriv); | 2679 | void (*btc_deinit_variables)(struct rtl_priv *rtlpriv); |
| 2672 | void (*btc_init_hal_vars) (struct rtl_priv *rtlpriv); | 2680 | void (*btc_init_hal_vars)(struct rtl_priv *rtlpriv); |
| 2673 | void (*btc_power_on_setting)(struct rtl_priv *rtlpriv); | 2681 | void (*btc_power_on_setting)(struct rtl_priv *rtlpriv); |
| 2674 | void (*btc_init_hw_config) (struct rtl_priv *rtlpriv); | 2682 | void (*btc_init_hw_config)(struct rtl_priv *rtlpriv); |
| 2675 | void (*btc_init_hw_config_wifi_only)(struct rtl_priv *rtlpriv); | 2683 | void (*btc_init_hw_config_wifi_only)(struct rtl_priv *rtlpriv); |
| 2676 | void (*btc_ips_notify) (struct rtl_priv *rtlpriv, u8 type); | 2684 | void (*btc_ips_notify)(struct rtl_priv *rtlpriv, u8 type); |
| 2677 | void (*btc_lps_notify)(struct rtl_priv *rtlpriv, u8 type); | 2685 | void (*btc_lps_notify)(struct rtl_priv *rtlpriv, u8 type); |
| 2678 | void (*btc_scan_notify) (struct rtl_priv *rtlpriv, u8 scantype); | 2686 | void (*btc_scan_notify)(struct rtl_priv *rtlpriv, u8 scantype); |
| 2679 | void (*btc_scan_notify_wifi_only)(struct rtl_priv *rtlpriv, | 2687 | void (*btc_scan_notify_wifi_only)(struct rtl_priv *rtlpriv, |
| 2680 | u8 scantype); | 2688 | u8 scantype); |
| 2681 | void (*btc_connect_notify) (struct rtl_priv *rtlpriv, u8 action); | 2689 | void (*btc_connect_notify)(struct rtl_priv *rtlpriv, u8 action); |
| 2682 | void (*btc_mediastatus_notify) (struct rtl_priv *rtlpriv, | 2690 | void (*btc_mediastatus_notify)(struct rtl_priv *rtlpriv, |
| 2683 | enum rt_media_status mstatus); | 2691 | enum rt_media_status mstatus); |
| 2684 | void (*btc_periodical) (struct rtl_priv *rtlpriv); | 2692 | void (*btc_periodical)(struct rtl_priv *rtlpriv); |
| 2685 | void (*btc_halt_notify)(struct rtl_priv *rtlpriv); | 2693 | void (*btc_halt_notify)(struct rtl_priv *rtlpriv); |
| 2686 | void (*btc_btinfo_notify) (struct rtl_priv *rtlpriv, | 2694 | void (*btc_btinfo_notify)(struct rtl_priv *rtlpriv, |
| 2687 | u8 *tmp_buf, u8 length); | 2695 | u8 *tmp_buf, u8 length); |
| 2688 | void (*btc_btmpinfo_notify)(struct rtl_priv *rtlpriv, | 2696 | void (*btc_btmpinfo_notify)(struct rtl_priv *rtlpriv, |
| 2689 | u8 *tmp_buf, u8 length); | 2697 | u8 *tmp_buf, u8 length); |
| 2690 | bool (*btc_is_limited_dig) (struct rtl_priv *rtlpriv); | 2698 | bool (*btc_is_limited_dig)(struct rtl_priv *rtlpriv); |
| 2691 | bool (*btc_is_disable_edca_turbo) (struct rtl_priv *rtlpriv); | 2699 | bool (*btc_is_disable_edca_turbo)(struct rtl_priv *rtlpriv); |
| 2692 | bool (*btc_is_bt_disabled) (struct rtl_priv *rtlpriv); | 2700 | bool (*btc_is_bt_disabled)(struct rtl_priv *rtlpriv); |
| 2693 | void (*btc_special_packet_notify)(struct rtl_priv *rtlpriv, | 2701 | void (*btc_special_packet_notify)(struct rtl_priv *rtlpriv, |
| 2694 | u8 pkt_type); | 2702 | u8 pkt_type); |
| 2695 | void (*btc_switch_band_notify)(struct rtl_priv *rtlpriv, u8 type, | 2703 | void (*btc_switch_band_notify)(struct rtl_priv *rtlpriv, u8 type, |
| @@ -2775,16 +2783,16 @@ struct rtl_priv { | |||
| 2775 | struct rtl_debug dbg; | 2783 | struct rtl_debug dbg; |
| 2776 | int max_fw_size; | 2784 | int max_fw_size; |
| 2777 | 2785 | ||
| 2778 | /* | 2786 | /* hal_cfg : for diff cards |
| 2779 | *hal_cfg : for diff cards | 2787 | * intf_ops : for diff interrface usb/pcie |
| 2780 | *intf_ops : for diff interrface usb/pcie | ||
| 2781 | */ | 2788 | */ |
| 2782 | struct rtl_hal_cfg *cfg; | 2789 | struct rtl_hal_cfg *cfg; |
| 2783 | const struct rtl_intf_ops *intf_ops; | 2790 | const struct rtl_intf_ops *intf_ops; |
| 2784 | 2791 | ||
| 2785 | /*this var will be set by set_bit, | 2792 | /* this var will be set by set_bit, |
| 2786 | and was used to indicate status of | 2793 | * and was used to indicate status of |
| 2787 | interface or hardware */ | 2794 | * interface or hardware |
| 2795 | */ | ||
| 2788 | unsigned long status; | 2796 | unsigned long status; |
| 2789 | 2797 | ||
| 2790 | /* tables for dm */ | 2798 | /* tables for dm */ |
| @@ -2820,10 +2828,11 @@ struct rtl_priv { | |||
| 2820 | #ifdef CONFIG_PM | 2828 | #ifdef CONFIG_PM |
| 2821 | struct wiphy_wowlan_support wowlan; | 2829 | struct wiphy_wowlan_support wowlan; |
| 2822 | #endif | 2830 | #endif |
| 2823 | /*This must be the last item so | 2831 | /* This must be the last item so |
| 2824 | that it points to the data allocated | 2832 | * that it points to the data allocated |
| 2825 | beyond this structure like: | 2833 | * beyond this structure like: |
| 2826 | rtl_pci_priv or rtl_usb_priv */ | 2834 | * rtl_pci_priv or rtl_usb_priv |
| 2835 | */ | ||
| 2827 | u8 priv[0] __aligned(sizeof(void *)); | 2836 | u8 priv[0] __aligned(sizeof(void *)); |
| 2828 | }; | 2837 | }; |
| 2829 | 2838 | ||
| @@ -2833,10 +2842,7 @@ struct rtl_priv { | |||
| 2833 | #define rtl_efuse(rtlpriv) (&((rtlpriv)->efuse)) | 2842 | #define rtl_efuse(rtlpriv) (&((rtlpriv)->efuse)) |
| 2834 | #define rtl_psc(rtlpriv) (&((rtlpriv)->psc)) | 2843 | #define rtl_psc(rtlpriv) (&((rtlpriv)->psc)) |
| 2835 | 2844 | ||
| 2836 | 2845 | /* Bluetooth Co-existence Related */ | |
| 2837 | /*************************************** | ||
| 2838 | Bluetooth Co-existence Related | ||
| 2839 | ****************************************/ | ||
| 2840 | 2846 | ||
| 2841 | enum bt_ant_num { | 2847 | enum bt_ant_num { |
| 2842 | ANT_X2 = 0, | 2848 | ANT_X2 = 0, |
| @@ -2885,14 +2891,13 @@ enum bt_radio_shared { | |||
| 2885 | BT_RADIO_INDIVIDUAL = 1, | 2891 | BT_RADIO_INDIVIDUAL = 1, |
| 2886 | }; | 2892 | }; |
| 2887 | 2893 | ||
| 2888 | |||
| 2889 | /**************************************** | 2894 | /**************************************** |
| 2890 | mem access macro define start | 2895 | * mem access macro define start |
| 2891 | Call endian free function when | 2896 | * Call endian free function when |
| 2892 | 1. Read/write packet content. | 2897 | * 1. Read/write packet content. |
| 2893 | 2. Before write integer to IO. | 2898 | * 2. Before write integer to IO. |
| 2894 | 3. After read integer from IO. | 2899 | * 3. After read integer from IO. |
| 2895 | ****************************************/ | 2900 | ****************************************/ |
| 2896 | /* Convert little data endian to host ordering */ | 2901 | /* Convert little data endian to host ordering */ |
| 2897 | #define EF1BYTE(_val) \ | 2902 | #define EF1BYTE(_val) \ |
| 2898 | ((u8)(_val)) | 2903 | ((u8)(_val)) |
| @@ -2948,8 +2953,9 @@ enum bt_radio_shared { | |||
| 2948 | (EF1BYTE(*((u8 *)(__pstart)))) | 2953 | (EF1BYTE(*((u8 *)(__pstart)))) |
| 2949 | 2954 | ||
| 2950 | /*Description: | 2955 | /*Description: |
| 2951 | Translate subfield (continuous bits in little-endian) of 4-byte | 2956 | * Translate subfield (continuous bits in little-endian) of 4-byte |
| 2952 | value to host byte ordering.*/ | 2957 | * value to host byte ordering. |
| 2958 | */ | ||
| 2953 | #define LE_BITS_TO_4BYTE(__pstart, __bitoffset, __bitlen) \ | 2959 | #define LE_BITS_TO_4BYTE(__pstart, __bitoffset, __bitlen) \ |
| 2954 | ( \ | 2960 | ( \ |
| 2955 | (LE_P4BYTE_TO_HOST_4BYTE(__pstart) >> (__bitoffset)) & \ | 2961 | (LE_P4BYTE_TO_HOST_4BYTE(__pstart) >> (__bitoffset)) & \ |
| @@ -3011,9 +3017,7 @@ value to host byte ordering.*/ | |||
| 3011 | #define N_BYTE_ALIGMENT(__value, __aligment) ((__aligment == 1) ? \ | 3017 | #define N_BYTE_ALIGMENT(__value, __aligment) ((__aligment == 1) ? \ |
| 3012 | (__value) : (((__value + __aligment - 1) / __aligment) * __aligment)) | 3018 | (__value) : (((__value + __aligment - 1) / __aligment) * __aligment)) |
| 3013 | 3019 | ||
| 3014 | /**************************************** | 3020 | /* mem access macro define end */ |
| 3015 | mem access macro define end | ||
| 3016 | ****************************************/ | ||
| 3017 | 3021 | ||
| 3018 | #define byte(x, n) ((x >> (8 * n)) & 0xff) | 3022 | #define byte(x, n) ((x >> (8 * n)) & 0xff) |
| 3019 | 3023 | ||
| @@ -3148,7 +3152,7 @@ static inline void rtl_set_bbreg(struct ieee80211_hw *hw, u32 regaddr, | |||
| 3148 | } | 3152 | } |
| 3149 | 3153 | ||
| 3150 | static inline void rtl_set_bbreg_with_dwmask(struct ieee80211_hw *hw, | 3154 | static inline void rtl_set_bbreg_with_dwmask(struct ieee80211_hw *hw, |
| 3151 | u32 regaddr, u32 data) | 3155 | u32 regaddr, u32 data) |
| 3152 | { | 3156 | { |
| 3153 | rtl_set_bbreg(hw, regaddr, 0xffffffff, data); | 3157 | rtl_set_bbreg(hw, regaddr, 0xffffffff, data); |
| 3154 | } | 3158 | } |
| @@ -3219,9 +3223,10 @@ static inline struct ieee80211_sta *get_sta(struct ieee80211_hw *hw, | |||
| 3219 | } | 3223 | } |
| 3220 | 3224 | ||
| 3221 | static inline struct ieee80211_sta *rtl_find_sta(struct ieee80211_hw *hw, | 3225 | static inline struct ieee80211_sta *rtl_find_sta(struct ieee80211_hw *hw, |
| 3222 | u8 *mac_addr) | 3226 | u8 *mac_addr) |
| 3223 | { | 3227 | { |
| 3224 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | 3228 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
| 3229 | |||
| 3225 | return ieee80211_find_sta(mac->vif, mac_addr); | 3230 | return ieee80211_find_sta(mac->vif, mac_addr); |
| 3226 | } | 3231 | } |
| 3227 | 3232 | ||
diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c index 8c17842ac507..844f2fac298f 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c +++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c | |||
| @@ -1726,6 +1726,10 @@ int rsi_send_bgscan_probe_req(struct rsi_common *common, | |||
| 1726 | 1726 | ||
| 1727 | probereq_skb = ieee80211_probereq_get(common->priv->hw, vif->addr, ssid, | 1727 | probereq_skb = ieee80211_probereq_get(common->priv->hw, vif->addr, ssid, |
| 1728 | ssid_len, scan_req->ie_len); | 1728 | ssid_len, scan_req->ie_len); |
| 1729 | if (!probereq_skb) { | ||
| 1730 | dev_kfree_skb(skb); | ||
| 1731 | return -ENOMEM; | ||
| 1732 | } | ||
| 1729 | 1733 | ||
| 1730 | memcpy(&skb->data[frame_len], probereq_skb->data, probereq_skb->len); | 1734 | memcpy(&skb->data[frame_len], probereq_skb->data, probereq_skb->len); |
| 1731 | 1735 | ||
