···20612061 return 0;20622062}2063206320642064+static void ath10k_htt_rx_mpdu_desc_pn_hl(struct htt_hl_rx_desc *rx_desc,20652065+ union htt_rx_pn_t *pn,20662066+ int pn_len_bits)20672067+{20682068+ switch (pn_len_bits) {20692069+ case 48:20702070+ pn->pn48 = __le32_to_cpu(rx_desc->pn_31_0) +20712071+ ((u64)(__le32_to_cpu(rx_desc->u0.pn_63_32) & 0xFFFF) << 32);20722072+ break;20732073+ case 24:20742074+ pn->pn24 = __le32_to_cpu(rx_desc->pn_31_0);20752075+ break;20762076+ };20772077+}20782078+20792079+static bool ath10k_htt_rx_pn_cmp48(union htt_rx_pn_t *new_pn,20802080+ union htt_rx_pn_t *old_pn)20812081+{20822082+ return ((new_pn->pn48 & 0xffffffffffffULL) <=20832083+ (old_pn->pn48 & 0xffffffffffffULL));20842084+}20852085+20862086+static bool ath10k_htt_rx_pn_check_replay_hl(struct ath10k *ar,20872087+ struct ath10k_peer *peer,20882088+ struct htt_rx_indication_hl *rx)20892089+{20902090+ bool last_pn_valid, pn_invalid = false;20912091+ enum htt_txrx_sec_cast_type sec_index;20922092+ enum htt_security_types sec_type;20932093+ union htt_rx_pn_t new_pn = {0};20942094+ struct htt_hl_rx_desc *rx_desc;20952095+ union htt_rx_pn_t *last_pn;20962096+ u32 rx_desc_info, tid;20972097+ int num_mpdu_ranges;20982098+20992099+ lockdep_assert_held(&ar->data_lock);21002100+21012101+ if (!peer)21022102+ return false;21032103+21042104+ if (!(rx->fw_desc.flags & FW_RX_DESC_FLAGS_FIRST_MSDU))21052105+ return false;21062106+21072107+ num_mpdu_ranges = MS(__le32_to_cpu(rx->hdr.info1),21082108+ HTT_RX_INDICATION_INFO1_NUM_MPDU_RANGES);21092109+21102110+ rx_desc = (struct htt_hl_rx_desc *)&rx->mpdu_ranges[num_mpdu_ranges];21112111+ rx_desc_info = __le32_to_cpu(rx_desc->info);21122112+21132113+ if (!MS(rx_desc_info, HTT_RX_DESC_HL_INFO_ENCRYPTED))21142114+ return false;21152115+21162116+ tid = MS(rx->hdr.info0, HTT_RX_INDICATION_INFO0_EXT_TID);21172117+ last_pn_valid = peer->tids_last_pn_valid[tid];21182118+ last_pn = &peer->tids_last_pn[tid];21192119+21202120+ if (MS(rx_desc_info, HTT_RX_DESC_HL_INFO_MCAST_BCAST))21212121+ sec_index = HTT_TXRX_SEC_MCAST;21222122+ else21232123+ sec_index = HTT_TXRX_SEC_UCAST;21242124+21252125+ sec_type = peer->rx_pn[sec_index].sec_type;21262126+ ath10k_htt_rx_mpdu_desc_pn_hl(rx_desc, &new_pn, peer->rx_pn[sec_index].pn_len);21272127+21282128+ if (sec_type != HTT_SECURITY_AES_CCMP &&21292129+ sec_type != HTT_SECURITY_TKIP &&21302130+ sec_type != HTT_SECURITY_TKIP_NOMIC)21312131+ return false;21322132+21332133+ if (last_pn_valid)21342134+ pn_invalid = ath10k_htt_rx_pn_cmp48(&new_pn, last_pn);21352135+ else21362136+ peer->tids_last_pn_valid[tid] = 1;21372137+21382138+ if (!pn_invalid)21392139+ last_pn->pn48 = new_pn.pn48;21402140+21412141+ return pn_invalid;21422142+}21432143+20642144static bool ath10k_htt_rx_proc_rx_ind_hl(struct ath10k_htt *htt,20652145 struct htt_rx_indication_hl *rx,20662066- struct sk_buff *skb)21462146+ struct sk_buff *skb,21472147+ enum htt_rx_pn_check_type check_pn_type,21482148+ enum htt_rx_tkip_demic_type tkip_mic_type)20672149{20682150 struct ath10k *ar = htt->ar;20692151 struct ath10k_peer *peer;···21892107 goto err;21902108 }2191210921102110+ if (check_pn_type == HTT_RX_PN_CHECK &&21112111+ ath10k_htt_rx_pn_check_replay_hl(ar, peer, rx))21122112+ goto err;21132113+21922114 /* Strip off all headers before the MAC header before delivery to21932115 * mac8021121942116 */···22002114 sizeof(rx->ppdu) + sizeof(rx->prefix) +22012115 sizeof(rx->fw_desc) +22022116 sizeof(*mpdu_ranges) * num_mpdu_ranges + rx_desc_len;21172117+22032118 skb_pull(skb, tot_hdr_len);2204211922052120 hdr = (struct ieee80211_hdr *)skb->data;···22492162 RX_FLAG_MMIC_STRIPPED;22502163 }2251216421652165+ if (tkip_mic_type == HTT_RX_TKIP_MIC)21662166+ rx_status->flag &= ~RX_FLAG_IV_STRIPPED &21672167+ ~RX_FLAG_MMIC_STRIPPED;21682168+22522169 ieee80211_rx_ni(ar->hw, skb);2253217022542171 /* We have delivered the skb to the upper layers (mac80211) so we···22602169 */22612170 return false;22622171err:21722172+ /* Tell the caller that it must free the skb since we have not21732173+ * consumed it21742174+ */21752175+ return true;21762176+}21772177+21782178+static int ath10k_htt_rx_frag_tkip_decap_nomic(struct sk_buff *skb,21792179+ u16 head_len,21802180+ u16 hdr_len)21812181+{21822182+ u8 *ivp, *orig_hdr;21832183+21842184+ orig_hdr = skb->data;21852185+ ivp = orig_hdr + hdr_len + head_len;21862186+21872187+ /* the ExtIV bit is always set to 1 for TKIP */21882188+ if (!(ivp[IEEE80211_WEP_IV_LEN - 1] & ATH10K_IEEE80211_EXTIV))21892189+ return -EINVAL;21902190+21912191+ memmove(orig_hdr + IEEE80211_TKIP_IV_LEN, orig_hdr, head_len + hdr_len);21922192+ skb_pull(skb, IEEE80211_TKIP_IV_LEN);21932193+ skb_trim(skb, skb->len - ATH10K_IEEE80211_TKIP_MICLEN);21942194+ return 0;21952195+}21962196+21972197+static int ath10k_htt_rx_frag_tkip_decap_withmic(struct sk_buff *skb,21982198+ u16 head_len,21992199+ u16 hdr_len)22002200+{22012201+ u8 *ivp, *orig_hdr;22022202+22032203+ orig_hdr = skb->data;22042204+ ivp = orig_hdr + hdr_len + head_len;22052205+22062206+ /* the ExtIV bit is always set to 1 for TKIP */22072207+ if (!(ivp[IEEE80211_WEP_IV_LEN - 1] & ATH10K_IEEE80211_EXTIV))22082208+ return -EINVAL;22092209+22102210+ memmove(orig_hdr + IEEE80211_TKIP_IV_LEN, orig_hdr, head_len + hdr_len);22112211+ skb_pull(skb, IEEE80211_TKIP_IV_LEN);22122212+ skb_trim(skb, skb->len - IEEE80211_TKIP_ICV_LEN);22132213+ return 0;22142214+}22152215+22162216+static int ath10k_htt_rx_frag_ccmp_decap(struct sk_buff *skb,22172217+ u16 head_len,22182218+ u16 hdr_len)22192219+{22202220+ u8 *ivp, *orig_hdr;22212221+22222222+ orig_hdr = skb->data;22232223+ ivp = orig_hdr + hdr_len + head_len;22242224+22252225+ /* the ExtIV bit is always set to 1 for CCMP */22262226+ if (!(ivp[IEEE80211_WEP_IV_LEN - 1] & ATH10K_IEEE80211_EXTIV))22272227+ return -EINVAL;22282228+22292229+ skb_trim(skb, skb->len - IEEE80211_CCMP_MIC_LEN);22302230+ memmove(orig_hdr + IEEE80211_CCMP_HDR_LEN, orig_hdr, head_len + hdr_len);22312231+ skb_pull(skb, IEEE80211_CCMP_HDR_LEN);22322232+ return 0;22332233+}22342234+22352235+static int ath10k_htt_rx_frag_wep_decap(struct sk_buff *skb,22362236+ u16 head_len,22372237+ u16 hdr_len)22382238+{22392239+ u8 *orig_hdr;22402240+22412241+ orig_hdr = skb->data;22422242+22432243+ memmove(orig_hdr + IEEE80211_WEP_IV_LEN,22442244+ orig_hdr, head_len + hdr_len);22452245+ skb_pull(skb, IEEE80211_WEP_IV_LEN);22462246+ skb_trim(skb, skb->len - IEEE80211_WEP_ICV_LEN);22472247+ return 0;22482248+}22492249+22502250+static bool ath10k_htt_rx_proc_rx_frag_ind_hl(struct ath10k_htt *htt,22512251+ struct htt_rx_fragment_indication *rx,22522252+ struct sk_buff *skb)22532253+{22542254+ struct ath10k *ar = htt->ar;22552255+ enum htt_rx_tkip_demic_type tkip_mic = HTT_RX_NON_TKIP_MIC;22562256+ enum htt_txrx_sec_cast_type sec_index;22572257+ struct htt_rx_indication_hl *rx_hl;22582258+ enum htt_security_types sec_type;22592259+ u32 tid, frag, seq, rx_desc_info;22602260+ union htt_rx_pn_t new_pn = {0};22612261+ struct htt_hl_rx_desc *rx_desc;22622262+ u16 peer_id, sc, hdr_space;22632263+ union htt_rx_pn_t *last_pn;22642264+ struct ieee80211_hdr *hdr;22652265+ int ret, num_mpdu_ranges;22662266+ struct ath10k_peer *peer;22672267+ struct htt_resp *resp;22682268+ size_t tot_hdr_len;22692269+22702270+ resp = (struct htt_resp *)(skb->data + HTT_RX_FRAG_IND_INFO0_HEADER_LEN);22712271+ skb_pull(skb, HTT_RX_FRAG_IND_INFO0_HEADER_LEN);22722272+ skb_trim(skb, skb->len - FCS_LEN);22732273+22742274+ peer_id = __le16_to_cpu(rx->peer_id);22752275+ rx_hl = (struct htt_rx_indication_hl *)(&resp->rx_ind_hl);22762276+22772277+ spin_lock_bh(&ar->data_lock);22782278+ peer = ath10k_peer_find_by_id(ar, peer_id);22792279+ if (!peer) {22802280+ ath10k_dbg(ar, ATH10K_DBG_HTT, "invalid peer: %u\n", peer_id);22812281+ goto err;22822282+ }22832283+22842284+ num_mpdu_ranges = MS(__le32_to_cpu(rx_hl->hdr.info1),22852285+ HTT_RX_INDICATION_INFO1_NUM_MPDU_RANGES);22862286+22872287+ tot_hdr_len = sizeof(struct htt_resp_hdr) +22882288+ sizeof(rx_hl->hdr) +22892289+ sizeof(rx_hl->ppdu) +22902290+ sizeof(rx_hl->prefix) +22912291+ sizeof(rx_hl->fw_desc) +22922292+ sizeof(struct htt_rx_indication_mpdu_range) * num_mpdu_ranges;22932293+22942294+ tid = MS(rx_hl->hdr.info0, HTT_RX_INDICATION_INFO0_EXT_TID);22952295+ rx_desc = (struct htt_hl_rx_desc *)(skb->data + tot_hdr_len);22962296+ rx_desc_info = __le32_to_cpu(rx_desc->info);22972297+22982298+ if (!MS(rx_desc_info, HTT_RX_DESC_HL_INFO_ENCRYPTED)) {22992299+ spin_unlock_bh(&ar->data_lock);23002300+ return ath10k_htt_rx_proc_rx_ind_hl(htt, &resp->rx_ind_hl, skb,23012301+ HTT_RX_NON_PN_CHECK,23022302+ HTT_RX_NON_TKIP_MIC);23032303+ }23042304+23052305+ hdr = (struct ieee80211_hdr *)((u8 *)rx_desc + rx_hl->fw_desc.len);23062306+23072307+ if (ieee80211_has_retry(hdr->frame_control))23082308+ goto err;23092309+23102310+ hdr_space = ieee80211_hdrlen(hdr->frame_control);23112311+ sc = __le16_to_cpu(hdr->seq_ctrl);23122312+ seq = (sc & IEEE80211_SCTL_SEQ) >> 4;23132313+ frag = sc & IEEE80211_SCTL_FRAG;23142314+23152315+ sec_index = MS(rx_desc_info, HTT_RX_DESC_HL_INFO_MCAST_BCAST) ?23162316+ HTT_TXRX_SEC_MCAST : HTT_TXRX_SEC_UCAST;23172317+ sec_type = peer->rx_pn[sec_index].sec_type;23182318+ ath10k_htt_rx_mpdu_desc_pn_hl(rx_desc, &new_pn, peer->rx_pn[sec_index].pn_len);23192319+23202320+ switch (sec_type) {23212321+ case HTT_SECURITY_TKIP:23222322+ tkip_mic = HTT_RX_TKIP_MIC;23232323+ ret = ath10k_htt_rx_frag_tkip_decap_withmic(skb,23242324+ tot_hdr_len +23252325+ rx_hl->fw_desc.len,23262326+ hdr_space);23272327+ if (ret)23282328+ goto err;23292329+ break;23302330+ case HTT_SECURITY_TKIP_NOMIC:23312331+ ret = ath10k_htt_rx_frag_tkip_decap_nomic(skb,23322332+ tot_hdr_len +23332333+ rx_hl->fw_desc.len,23342334+ hdr_space);23352335+ if (ret)23362336+ goto err;23372337+ break;23382338+ case HTT_SECURITY_AES_CCMP:23392339+ ret = ath10k_htt_rx_frag_ccmp_decap(skb,23402340+ tot_hdr_len + rx_hl->fw_desc.len,23412341+ hdr_space);23422342+ if (ret)23432343+ goto err;23442344+ break;23452345+ case HTT_SECURITY_WEP128:23462346+ case HTT_SECURITY_WEP104:23472347+ case HTT_SECURITY_WEP40:23482348+ ret = ath10k_htt_rx_frag_wep_decap(skb,23492349+ tot_hdr_len + rx_hl->fw_desc.len,23502350+ hdr_space);23512351+ if (ret)23522352+ goto err;23532353+ break;23542354+ default:23552355+ break;23562356+ }23572357+23582358+ resp = (struct htt_resp *)(skb->data);23592359+23602360+ if (sec_type != HTT_SECURITY_AES_CCMP &&23612361+ sec_type != HTT_SECURITY_TKIP &&23622362+ sec_type != HTT_SECURITY_TKIP_NOMIC) {23632363+ spin_unlock_bh(&ar->data_lock);23642364+ return ath10k_htt_rx_proc_rx_ind_hl(htt, &resp->rx_ind_hl, skb,23652365+ HTT_RX_NON_PN_CHECK,23662366+ HTT_RX_NON_TKIP_MIC);23672367+ }23682368+23692369+ last_pn = &peer->frag_tids_last_pn[tid];23702370+23712371+ if (frag == 0) {23722372+ if (ath10k_htt_rx_pn_check_replay_hl(ar, peer, &resp->rx_ind_hl))23732373+ goto err;23742374+23752375+ last_pn->pn48 = new_pn.pn48;23762376+ peer->frag_tids_seq[tid] = seq;23772377+ } else if (sec_type == HTT_SECURITY_AES_CCMP) {23782378+ if (seq != peer->frag_tids_seq[tid])23792379+ goto err;23802380+23812381+ if (new_pn.pn48 != last_pn->pn48 + 1)23822382+ goto err;23832383+23842384+ last_pn->pn48 = new_pn.pn48;23852385+ last_pn = &peer->tids_last_pn[tid];23862386+ last_pn->pn48 = new_pn.pn48;23872387+ }23882388+23892389+ spin_unlock_bh(&ar->data_lock);23902390+23912391+ return ath10k_htt_rx_proc_rx_ind_hl(htt, &resp->rx_ind_hl, skb,23922392+ HTT_RX_NON_PN_CHECK, tkip_mic);23932393+23942394+err:23952395+ spin_unlock_bh(&ar->data_lock);23962396+22632397 /* Tell the caller that it must free the skb since we have not22642398 * consumed it22652399 */···25092193 mpdu_ranges = htt_rx_ind_get_mpdu_ranges(rx);2510219425112195 ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt rx ind: ",25122512- rx, sizeof(*rx) +25132513- (sizeof(struct htt_rx_indication_mpdu_range) *25142514- num_mpdu_ranges));21962196+ rx, struct_size(rx, mpdu_ranges, num_mpdu_ranges));2515219725162198 for (i = 0; i < num_mpdu_ranges; i++)25172199 mpdu_count += mpdu_ranges[i].mpdu_count;···25912277 * Note that with only one concurrent reader and one concurrent25922278 * writer, you don't need extra locking to use these macro.25932279 */25942594- if (!kfifo_put(&htt->txdone_fifo, tx_done)) {22802280+ if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL) {22812281+ ath10k_txrx_tx_unref(htt, &tx_done);22822282+ } else if (!kfifo_put(&htt->txdone_fifo, tx_done)) {25952283 ath10k_warn(ar, "txdone fifo overrun, msdu_id %d status %d\n",25962284 tx_done.msdu_id, tx_done.status);25972285 ath10k_txrx_tx_unref(htt, &tx_done);···3254293832552939#define STATS_OP_FMT(name) tx_stats->stats[ATH10K_STATS_TYPE_##name]3256294032573257- if (txrate->flags == RATE_INFO_FLAGS_VHT_MCS) {29412941+ if (txrate->flags & RATE_INFO_FLAGS_VHT_MCS) {32582942 STATS_OP_FMT(SUCC).vht[0][mcs] += pstats->succ_bytes;32592943 STATS_OP_FMT(SUCC).vht[1][mcs] += pstats->succ_pkts;32602944 STATS_OP_FMT(FAIL).vht[0][mcs] += pstats->failed_bytes;32612945 STATS_OP_FMT(FAIL).vht[1][mcs] += pstats->failed_pkts;32622946 STATS_OP_FMT(RETRY).vht[0][mcs] += pstats->retry_bytes;32632947 STATS_OP_FMT(RETRY).vht[1][mcs] += pstats->retry_pkts;32643264- } else if (txrate->flags == RATE_INFO_FLAGS_MCS) {29482948+ } else if (txrate->flags & RATE_INFO_FLAGS_MCS) {32652949 STATS_OP_FMT(SUCC).ht[0][ht_idx] += pstats->succ_bytes;32662950 STATS_OP_FMT(SUCC).ht[1][ht_idx] += pstats->succ_pkts;32672951 STATS_OP_FMT(FAIL).ht[0][ht_idx] += pstats->failed_bytes;···32822966 if (ATH10K_HW_AMPDU(pstats->flags)) {32832967 tx_stats->ba_fails += ATH10K_HW_BA_FAIL(pstats->flags);3284296832853285- if (txrate->flags == RATE_INFO_FLAGS_MCS) {29692969+ if (txrate->flags & RATE_INFO_FLAGS_MCS) {32862970 STATS_OP_FMT(AMPDU).ht[0][ht_idx] +=32872971 pstats->succ_bytes + pstats->retry_bytes;32882972 STATS_OP_FMT(AMPDU).ht[1][ht_idx] +=···35813265 rcu_read_unlock();35823266}3583326732683268+static int ath10k_htt_rx_pn_len(enum htt_security_types sec_type)32693269+{32703270+ switch (sec_type) {32713271+ case HTT_SECURITY_TKIP:32723272+ case HTT_SECURITY_TKIP_NOMIC:32733273+ case HTT_SECURITY_AES_CCMP:32743274+ return 48;32753275+ default:32763276+ return 0;32773277+ }32783278+}32793279+32803280+static void ath10k_htt_rx_sec_ind_handler(struct ath10k *ar,32813281+ struct htt_security_indication *ev)32823282+{32833283+ enum htt_txrx_sec_cast_type sec_index;32843284+ enum htt_security_types sec_type;32853285+ struct ath10k_peer *peer;32863286+32873287+ spin_lock_bh(&ar->data_lock);32883288+32893289+ peer = ath10k_peer_find_by_id(ar, __le16_to_cpu(ev->peer_id));32903290+ if (!peer) {32913291+ ath10k_warn(ar, "failed to find peer id %d for security indication",32923292+ __le16_to_cpu(ev->peer_id));32933293+ goto out;32943294+ }32953295+32963296+ sec_type = MS(ev->flags, HTT_SECURITY_TYPE);32973297+32983298+ if (ev->flags & HTT_SECURITY_IS_UNICAST)32993299+ sec_index = HTT_TXRX_SEC_UCAST;33003300+ else33013301+ sec_index = HTT_TXRX_SEC_MCAST;33023302+33033303+ peer->rx_pn[sec_index].sec_type = sec_type;33043304+ peer->rx_pn[sec_index].pn_len = ath10k_htt_rx_pn_len(sec_type);33053305+33063306+ memset(peer->tids_last_pn_valid, 0, sizeof(peer->tids_last_pn_valid));33073307+ memset(peer->tids_last_pn, 0, sizeof(peer->tids_last_pn));33083308+33093309+out:33103310+ spin_unlock_bh(&ar->data_lock);33113311+}33123312+35843313bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)35853314{35863315 struct ath10k_htt *htt = &ar->htt;···36573296 if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL)36583297 return ath10k_htt_rx_proc_rx_ind_hl(htt,36593298 &resp->rx_ind_hl,36603660- skb);32993299+ skb,33003300+ HTT_RX_PN_CHECK,33013301+ HTT_RX_NON_TKIP_MIC);36613302 else36623303 ath10k_htt_rx_proc_rx_ind_ll(htt, &resp->rx_ind);36633304 break;···37213358 struct ath10k *ar = htt->ar;37223359 struct htt_security_indication *ev = &resp->security_indication;3723336033613361+ ath10k_htt_rx_sec_ind_handler(ar, ev);37243362 ath10k_dbg(ar, ATH10K_DBG_HTT,37253363 "sec ind peer_id %d unicast %d type %d\n",37263364 __le16_to_cpu(ev->peer_id),···37343370 ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt event: ",37353371 skb->data, skb->len);37363372 atomic_inc(&htt->num_mpdus_ready);33733373+33743374+ return ath10k_htt_rx_proc_rx_frag_ind(htt,33753375+ &resp->rx_frag_ind,33763376+ skb);37373377 break;37383378 }37393379 case HTT_T2H_MSG_TYPE_TEST:···39513583};3952358439533585static const struct ath10k_htt_rx_ops htt_rx_ops_hl = {35863586+ .htt_rx_proc_rx_frag_ind = ath10k_htt_rx_proc_rx_frag_ind_hl,39543587};3955358839563589void ath10k_htt_set_rx_ops(struct ath10k_htt *htt)
+24-5
drivers/net/wireless/ath/ath10k/htt_tx.c
···580580 return 0;581581}582582583583-int ath10k_htt_h2t_stats_req(struct ath10k_htt *htt, u8 mask, u64 cookie)583583+int ath10k_htt_h2t_stats_req(struct ath10k_htt *htt, u32 mask, u32 reset_mask,584584+ u64 cookie)584585{585586 struct ath10k *ar = htt->ar;586587 struct htt_stats_req *req;···604603605604 memset(req, 0, sizeof(*req));606605607607- /* currently we support only max 8 bit masks so no need to worry606606+ /* currently we support only max 24 bit masks so no need to worry608607 * about endian support609608 */610610- req->upload_types[0] = mask;611611- req->reset_types[0] = mask;609609+ memcpy(req->upload_types, &mask, 3);610610+ memcpy(req->reset_types, &reset_mask, 3);612611 req->stat_type = HTT_STATS_REQ_CFG_STAT_TYPE_INVALID;613612 req->cookie_lsb = cpu_to_le32(cookie & 0xffffffff);614613 req->cookie_msb = cpu_to_le32((cookie & 0xffffffff00000000ULL) >> 32);···12451244 u8 tid = ath10k_htt_tx_get_tid(msdu, is_eth);12461245 u8 flags0 = 0;12471246 u16 flags1 = 0;12471247+ u16 msdu_id = 0;1248124812491249 data_len = msdu->len;12501250···12931291 }12941292 }1295129312941294+ if (ar->bus_param.hl_msdu_ids) {12951295+ flags1 |= HTT_DATA_TX_DESC_FLAGS1_POSTPONED;12961296+ res = ath10k_htt_tx_alloc_msdu_id(htt, msdu);12971297+ if (res < 0) {12981298+ ath10k_err(ar, "msdu_id allocation failed %d\n", res);12991299+ goto out;13001300+ }13011301+ msdu_id = res;13021302+ }13031303+13041304+ /* As msdu is freed by mac80211 (in ieee80211_tx_status()) and by13051305+ * ath10k (in ath10k_htt_htc_tx_complete()) we have to increase13061306+ * reference by one to avoid a use-after-free case and a double13071307+ * free.13081308+ */13091309+ skb_get(msdu);13101310+12961311 skb_push(msdu, sizeof(*cmd_hdr));12971312 skb_push(msdu, sizeof(*tx_desc));12981313 cmd_hdr = (struct htt_cmd_hdr *)msdu->data;···13191300 tx_desc->flags0 = flags0;13201301 tx_desc->flags1 = __cpu_to_le16(flags1);13211302 tx_desc->len = __cpu_to_le16(data_len);13221322- tx_desc->id = 0;13031303+ tx_desc->id = __cpu_to_le16(msdu_id);13231304 tx_desc->frags_paddr = 0; /* always zero */13241305 /* Initialize peer_id to INVALID_PEER because this is NOT13251306 * Reinjection path
+6
drivers/net/wireless/ath/ath10k/hw.h
···2424#define QCA988X_2_0_DEVICE_ID (0x003c)2525#define QCA6164_2_1_DEVICE_ID (0x0041)2626#define QCA6174_2_1_DEVICE_ID (0x003e)2727+#define QCA6174_3_2_DEVICE_ID (0x0042)2728#define QCA99X0_2_0_DEVICE_ID (0x0040)2829#define QCA9888_2_0_DEVICE_ID (0x0056)2930#define QCA9984_1_0_DEVICE_ID (0x0046)···607606608607 /* target supporting fw download via diag ce */609608 bool fw_diag_ce_download;609609+610610+ /* need to set uart pin if disable uart print, workaround for a611611+ * firmware bug612612+ */613613+ bool uart_pin_workaround;610614};611615612616struct htt_rx_desc;
+11-3
drivers/net/wireless/ath/ath10k/mac.c
···16301630 if (arvif->vdev_type != WMI_VDEV_TYPE_AP)16311631 return 0;1632163216331633+ /* For mesh, probe response and beacon share the same template */16341634+ if (ieee80211_vif_is_mesh(vif))16351635+ return 0;16361636+16331637 prb = ieee80211_proberesp_get(hw, vif);16341638 if (!prb) {16351639 ath10k_warn(ar, "failed to get probe resp template from mac80211\n");···55925588 struct cfg80211_chan_def def;55935589 u32 vdev_param, pdev_param, slottime, preamble;55945590 u16 bitrate, hw_value;55955595- u8 rate, basic_rate_idx;55965596- int rateidx, ret = 0, hw_rate_code;55915591+ u8 rate, basic_rate_idx, rateidx;55925592+ int ret = 0, hw_rate_code, mcast_rate;55975593 enum nl80211_band band;55985594 const struct ieee80211_supported_band *sband;55995595···57805776 if (changed & BSS_CHANGED_MCAST_RATE &&57815777 !ath10k_mac_vif_chan(arvif->vif, &def)) {57825778 band = def.chan->band;57835783- rateidx = vif->bss_conf.mcast_rate[band] - 1;57795779+ mcast_rate = vif->bss_conf.mcast_rate[band];57805780+ if (mcast_rate > 0)57815781+ rateidx = mcast_rate - 1;57825782+ else57835783+ rateidx = ffs(vif->bss_conf.basic_rates) - 1;5784578457855785 if (ar->phy_capability & WHAL_WLAN_11A_CAPABILITY)57865786 rateidx += ATH10K_MAC_FIRST_OFDM_RATE_IDX;
···973973 struct usb_device *dev = interface_to_usbdev(interface);974974 int ret, vendor_id, product_id;975975 enum ath10k_hw_rev hw_rev;976976- struct ath10k_bus_params bus_params;976976+ struct ath10k_bus_params bus_params = {};977977978978 /* Assumption: All USB based chipsets (so far) are QCA9377 based.979979 * If there will be newer chipsets that does not use the hw reg
···898898 break;899899 }900900901901- if (status != 0)902902- break;903903-904901 /* advance buffer past this record for next time around */905902 buffer += record->len;906903 len -= record->len;
+10-3
drivers/net/wireless/ath/ath6kl/wmi.c
···11761176 return -EINVAL;1177117711781178 ev = (struct wmi_pstream_timeout_event *) datap;11791179+ if (ev->traffic_class >= WMM_NUM_AC) {11801180+ ath6kl_err("invalid traffic class: %d\n", ev->traffic_class);11811181+ return -EINVAL;11821182+ }1179118311801184 /*11811185 * When the pstream (fat pipe == AC) timesout, it means there were···12991295 if (len < sizeof(*ev))13001296 return -EINVAL;13011297 ev = (struct wmi_neighbor_report_event *) datap;13021302- if (sizeof(*ev) + ev->num_neighbors * sizeof(struct wmi_neighbor_info)13031303- > len) {12981298+ if (struct_size(ev, neighbor, ev->num_neighbors) > len) {13041299 ath6kl_dbg(ATH6KL_DBG_WMI,13051300 "truncated neighbor event (num=%d len=%d)\n",13061301 ev->num_neighbors, len);···15201517 return -EINVAL;1521151815221519 reply = (struct wmi_cac_event *) datap;15201520+ if (reply->ac >= WMM_NUM_AC) {15211521+ ath6kl_err("invalid AC: %d\n", reply->ac);15221522+ return -EINVAL;15231523+ }1523152415241525 if ((reply->cac_indication == CAC_INDICATION_ADMISSION_RESP) &&15251526 (reply->status_code != IEEE80211_TSPEC_STATUS_ADMISS_ACCEPTED)) {···26402633 u16 active_tsids = 0;26412634 int ret;2642263526432643- if (traffic_class > 3) {26362636+ if (traffic_class >= WMM_NUM_AC) {26442637 ath6kl_err("invalid traffic class: %d\n", traffic_class);26452638 return -EINVAL;26462639 }
···395395{396396 int i;397397398398- for (i = 0; i < max_assoc_sta; i++) {398398+ for (i = 0; i < wil->max_assoc_sta; i++) {399399 if (wil->sta[i].status == wil_sta_unused)400400 continue;401401 if (wil->sta[i].mid != mid)···30223022 wil, vif->mid, WMI_INVALID_RF_SECTOR_INDEX,30233023 sector_type, WIL_CID_ALL);30243024 if (rc == -EINVAL) {30253025- for (i = 0; i < max_assoc_sta; i++) {30253025+ for (i = 0; i < wil->max_assoc_sta; i++) {30263026 if (wil->sta[i].mid != vif->mid)30273027 continue;30283028 rc = wil_rf_sector_wmi_set_selected(
+49-21
drivers/net/wireless/ath/wil6210/debugfs.c
···6363 &ring->va[idx].rx.enhanced;6464 u16 buff_id = le16_to_cpu(rx_d->mac.buff_id);65656666- has_skb = wil->rx_buff_mgmt.buff_arr[buff_id].skb;6666+ if (wil->rx_buff_mgmt.buff_arr &&6767+ wil_val_in_range(buff_id, 0, wil->rx_buff_mgmt.size))6868+ has_skb = wil->rx_buff_mgmt.buff_arr[buff_id].skb;6769 seq_printf(s, "%c", (has_skb) ? _h : _s);6870 } else {6971 struct wil_tx_enhanced_desc *d =···7371 &ring->va[idx].tx.enhanced;74727573 num_of_descs = (u8)d->mac.d[2];7676- has_skb = ring->ctx[idx].skb;7474+ has_skb = ring->ctx && ring->ctx[idx].skb;7775 if (num_of_descs >= 1)7878- seq_printf(s, "%c", ring->ctx[idx].skb ? _h : _s);7676+ seq_printf(s, "%c", has_skb ? _h : _s);7977 else8078 /* num_of_descs == 0, it's a frag in a list of descs */8179 seq_printf(s, "%c", has_skb ? 'h' : _s);···8684 const char *name, struct wil_ring *ring,8785 char _s, char _h)8886{8989- void __iomem *x = wmi_addr(wil, ring->hwtail);8787+ void __iomem *x;9088 u32 v;91899290 seq_printf(s, "RING %s = {\n", name);···9896 else9997 seq_printf(s, " swtail = %d\n", ring->swtail);10098 seq_printf(s, " swhead = %d\n", ring->swhead);9999+ if (wil->use_enhanced_dma_hw) {100100+ int ring_id = ring->is_rx ?101101+ WIL_RX_DESC_RING_ID : ring - wil->ring_tx;102102+ /* SUBQ_CONS is a table of 32 entries, one for each Q pair.103103+ * lower 16bits are for even ring_id and upper 16bits are for104104+ * odd ring_id105105+ */106106+ x = wmi_addr(wil, RGF_DMA_SCM_SUBQ_CONS + 4 * (ring_id / 2));107107+ v = readl_relaxed(x);108108+109109+ v = (ring_id % 2 ? (v >> 16) : (v & 0xffff));110110+ seq_printf(s, " hwhead = %u\n", v);111111+ }101112 seq_printf(s, " hwtail = [0x%08x] -> ", ring->hwtail);113113+ x = wmi_addr(wil, ring->hwtail);102114 if (x) {103115 v = readl(x);104116 seq_printf(s, "0x%08x = %d\n", v, v);···178162179163 snprintf(name, sizeof(name), "tx_%2d", i);180164181181- if (cid < max_assoc_sta)165165+ if (cid < wil->max_assoc_sta)182166 seq_printf(s,183167 "\n%pM CID %d TID %d 1x%s BACK([%u] %u TU A%s) [%3d|%3d] idle %s\n",184168 wil->sta[cid].addr, cid, tid,···204188static void wil_print_sring(struct seq_file *s, struct wil6210_priv *wil,205189 struct wil_status_ring *sring)206190{207207- void __iomem *x = wmi_addr(wil, sring->hwtail);191191+ void __iomem *x;208192 int sring_idx = sring - wil->srings;209193 u32 v;210194···215199 seq_printf(s, " size = %d\n", sring->size);216200 seq_printf(s, " elem_size = %zu\n", sring->elem_size);217201 seq_printf(s, " swhead = %d\n", sring->swhead);202202+ if (wil->use_enhanced_dma_hw) {203203+ /* COMPQ_PROD is a table of 32 entries, one for each Q pair.204204+ * lower 16bits are for even ring_id and upper 16bits are for205205+ * odd ring_id206206+ */207207+ x = wmi_addr(wil, RGF_DMA_SCM_COMPQ_PROD + 4 * (sring_idx / 2));208208+ v = readl_relaxed(x);209209+210210+ v = (sring_idx % 2 ? (v >> 16) : (v & 0xffff));211211+ seq_printf(s, " hwhead = %u\n", v);212212+ }218213 seq_printf(s, " hwtail = [0x%08x] -> ", sring->hwtail);214214+ x = wmi_addr(wil, sring->hwtail);219215 if (x) {220216 v = readl_relaxed(x);221217 seq_printf(s, "0x%08x = %d\n", v, v);···839811 "BACK: del_rx require at least 2 params\n");840812 return -EINVAL;841813 }842842- if (p1 < 0 || p1 >= max_assoc_sta) {814814+ if (p1 < 0 || p1 >= wil->max_assoc_sta) {843815 wil_err(wil, "BACK: invalid CID %d\n", p1);844816 return -EINVAL;845817 }···1119109111201092 if (wil->use_enhanced_dma_hw) {11211093 if (tx) {11221122- skb = ring->ctx[txdesc_idx].skb;11231123- } else {10941094+ skb = ring->ctx ? ring->ctx[txdesc_idx].skb : NULL;10951095+ } else if (wil->rx_buff_mgmt.buff_arr) {11241096 struct wil_rx_enhanced_desc *rx_d =11251097 (struct wil_rx_enhanced_desc *)11261098 &ring->va[txdesc_idx].rx.enhanced;11271099 u16 buff_id = le16_to_cpu(rx_d->mac.buff_id);1128110011291101 if (!wil_val_in_range(buff_id, 0,11301130- wil->rx_buff_mgmt.size)) {11021102+ wil->rx_buff_mgmt.size))11311103 seq_printf(s, "invalid buff_id %d\n", buff_id);11321132- return 0;11331133- }11341134- skb = wil->rx_buff_mgmt.buff_arr[buff_id].skb;11041104+ else11051105+ skb = wil->rx_buff_mgmt.buff_arr[buff_id].skb;11351106 }11361107 } else {11371108 skb = ring->ctx[txdesc_idx].skb;···11631136 struct wil6210_priv *wil = s->private;11641137 int sring_idx = dbg_sring_index;11651138 struct wil_status_ring *sring;11661166- bool tx = sring_idx == wil->tx_sring_idx ? 1 : 0;11391139+ bool tx;11671140 u32 status_msg_idx = dbg_status_msg_index;11681141 u32 *u;11691142···11731146 }1174114711751148 sring = &wil->srings[sring_idx];11491149+ tx = !sring->is_rx;1176115011771151 if (!sring->va) {11781152 seq_printf(s, "No %cX status ring\n", tx ? 'T' : 'R');···1290126212911263 memset(&reply, 0, sizeof(reply));1292126412931293- for (i = 0; i < max_assoc_sta; i++) {12651265+ for (i = 0; i < wil->max_assoc_sta; i++) {12941266 u32 status;1295126712961268 cmd.cid = i;···13871359 if (!sinfo)13881360 return -ENOMEM;1389136113901390- for (i = 0; i < max_assoc_sta; i++) {13621362+ for (i = 0; i < wil->max_assoc_sta; i++) {13911363 struct wil_sta_info *p = &wil->sta[i];13921364 char *status = "unknown";13931365 struct wil6210_vif *vif;···15891561 struct wil6210_priv *wil = s->private;15901562 int i, tid, mcs;1591156315921592- for (i = 0; i < max_assoc_sta; i++) {15641564+ for (i = 0; i < wil->max_assoc_sta; i++) {15931565 struct wil_sta_info *p = &wil->sta[i];15941566 char *status = "unknown";15951567 u8 aid = 0;···16981670 struct wil6210_priv *wil = s->private;16991671 int i, bin;1700167217011701- for (i = 0; i < max_assoc_sta; i++) {16731673+ for (i = 0; i < wil->max_assoc_sta; i++) {17021674 struct wil_sta_info *p = &wil->sta[i];17031675 char *status = "unknown";17041676 u8 aid = 0;···17871759 size_t sz = sizeof(u64) * WIL_NUM_LATENCY_BINS;1788176017891761 wil->tx_latency_res = val;17901790- for (i = 0; i < max_assoc_sta; i++) {17621762+ for (i = 0; i < wil->max_assoc_sta; i++) {17911763 struct wil_sta_info *sta = &wil->sta[i];1792176417931765 kfree(sta->tx_latency_bins);···18721844 }1873184518741846 seq_printf(s, "TSF %lld\n", vif->fw_stats_tsf);18751875- for (i = 0; i < max_assoc_sta; i++) {18471847+ for (i = 0; i < wil->max_assoc_sta; i++) {18761848 if (wil->sta[i].status == wil_sta_unused)18771849 continue;18781850 if (wil->sta[i].mid != vif->mid)···24882460 wil->debug = NULL;2489246124902462 kfree(wil->dbg_data.data_arr);24912491- for (i = 0; i < max_assoc_sta; i++)24632463+ for (i = 0; i < wil->max_assoc_sta; i++)24922464 kfree(wil->sta[i].tx_latency_bins);2493246524942466 /* free pmc memory without sending command to fw, as it will
+8-3
drivers/net/wireless/ath/wil6210/fw.h
···11/*22 * Copyright (c) 2014,2016 Qualcomm Atheros, Inc.33- * Copyright (c) 2018, The Linux Foundation. All rights reserved.33+ * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.44 *55 * Permission to use, copy, modify, and/or distribute this software for any66 * purpose with or without fee is hereby granted, provided that the above···109109110110/* brd file info encoded inside a comment record */111111#define WIL_BRD_FILE_MAGIC (0xabcddcbb)112112+113113+struct brd_info {114114+ __le32 base_addr;115115+ __le32 max_size_bytes;116116+} __packed;117117+112118struct wil_fw_record_brd_file { /* type == wil_fw_type_comment */113119 /* identifies brd file record */114120 struct wil_fw_record_comment_hdr hdr;115121 __le32 version;116116- __le32 base_addr;117117- __le32 max_size_bytes;122122+ struct brd_info brd_info[0];118123} __packed;119124120125/* perform action
+110-40
drivers/net/wireless/ath/wil6210/fw_inc.c
···156156 size_t size)157157{158158 const struct wil_fw_record_brd_file *rec = data;159159+ u32 max_num_ent, i, ent_size;159160160160- if (size < sizeof(*rec)) {161161- wil_err_fw(wil, "brd_file record too short: %zu\n", size);162162- return 0;161161+ if (size <= offsetof(struct wil_fw_record_brd_file, brd_info)) {162162+ wil_err(wil, "board record too short, size %zu\n", size);163163+ return -EINVAL;163164 }164165165165- wil->brd_file_addr = le32_to_cpu(rec->base_addr);166166- wil->brd_file_max_size = le32_to_cpu(rec->max_size_bytes);166166+ ent_size = size - offsetof(struct wil_fw_record_brd_file, brd_info);167167+ max_num_ent = ent_size / sizeof(struct brd_info);167168168168- wil_dbg_fw(wil, "brd_file_addr 0x%x, brd_file_max_size %d\n",169169- wil->brd_file_addr, wil->brd_file_max_size);169169+ if (!max_num_ent) {170170+ wil_err(wil, "brd info entries are missing\n");171171+ return -EINVAL;172172+ }173173+174174+ wil->brd_info = kcalloc(max_num_ent, sizeof(struct wil_brd_info),175175+ GFP_KERNEL);176176+ if (!wil->brd_info)177177+ return -ENOMEM;178178+179179+ for (i = 0; i < max_num_ent; i++) {180180+ wil->brd_info[i].file_addr =181181+ le32_to_cpu(rec->brd_info[i].base_addr);182182+ wil->brd_info[i].file_max_size =183183+ le32_to_cpu(rec->brd_info[i].max_size_bytes);184184+185185+ if (!wil->brd_info[i].file_addr)186186+ break;187187+188188+ wil_dbg_fw(wil,189189+ "brd info %d: file_addr 0x%x, file_max_size %d\n",190190+ i, wil->brd_info[i].file_addr,191191+ wil->brd_info[i].file_max_size);192192+ }193193+194194+ wil->num_of_brd_entries = i;195195+ if (wil->num_of_brd_entries == 0) {196196+ kfree(wil->brd_info);197197+ wil->brd_info = NULL;198198+ wil_dbg_fw(wil,199199+ "no valid brd info entries, using brd file addr\n");200200+201201+ } else {202202+ wil_dbg_fw(wil, "num of brd info entries %d\n",203203+ wil->num_of_brd_entries);204204+ }170205171206 return 0;172207}···669634 }670635 wil_dbg_fw(wil, "Loading <%s>, %zu bytes\n", name, fw->size);671636637637+ /* re-initialize board info params */638638+ wil->num_of_brd_entries = 0;639639+ kfree(wil->brd_info);640640+ wil->brd_info = NULL;641641+672642 for (sz = fw->size, d = fw->data; sz; sz -= rc1, d += rc1) {673643 rc1 = wil_fw_verify(wil, d, sz);674644 if (rc1 < 0) {···702662{703663 int rc = 0;704664 const struct wil_fw_record_head *hdr = data;705705- size_t s, hdr_sz;665665+ size_t s, hdr_sz = 0;706666 u16 type;667667+ int i = 0;707668708708- /* Assuming the board file includes only one header record and one data709709- * record. Each record starts with wil_fw_record_head.669669+ /* Assuming the board file includes only one file header670670+ * and one or several data records.671671+ * Each record starts with wil_fw_record_head.710672 */711673 if (size < sizeof(*hdr))712674 return -EINVAL;···716674 if (s > size)717675 return -EINVAL;718676719719- /* Skip the header record and handle the data record */720720- hdr = (const void *)hdr + s;677677+ /* Skip the header record and handle the data records */721678 size -= s;722722- if (size < sizeof(*hdr))723723- return -EINVAL;724724- hdr_sz = le32_to_cpu(hdr->size);725679726726- if (wil->brd_file_max_size && hdr_sz > wil->brd_file_max_size)727727- return -EINVAL;728728- if (sizeof(*hdr) + hdr_sz > size)729729- return -EINVAL;730730- if (hdr_sz % 4) {731731- wil_err_fw(wil, "unaligned record size: %zu\n",732732- hdr_sz);680680+ for (hdr = data + s;; hdr = (const void *)hdr + s, size -= s, i++) {681681+ if (size < sizeof(*hdr))682682+ break;683683+684684+ if (i >= wil->num_of_brd_entries) {685685+ wil_err_fw(wil,686686+ "Too many brd records: %d, num of expected entries %d\n",687687+ i, wil->num_of_brd_entries);688688+ break;689689+ }690690+691691+ hdr_sz = le32_to_cpu(hdr->size);692692+ s = sizeof(*hdr) + hdr_sz;693693+ if (wil->brd_info[i].file_max_size &&694694+ hdr_sz > wil->brd_info[i].file_max_size)695695+ return -EINVAL;696696+ if (sizeof(*hdr) + hdr_sz > size)697697+ return -EINVAL;698698+ if (hdr_sz % 4) {699699+ wil_err_fw(wil, "unaligned record size: %zu\n",700700+ hdr_sz);701701+ return -EINVAL;702702+ }703703+ type = le16_to_cpu(hdr->type);704704+ if (type != wil_fw_type_data) {705705+ wil_err_fw(wil,706706+ "invalid record type for board file: %d\n",707707+ type);708708+ return -EINVAL;709709+ }710710+ if (hdr_sz < sizeof(struct wil_fw_record_data)) {711711+ wil_err_fw(wil, "data record too short: %zu\n", hdr_sz);712712+ return -EINVAL;713713+ }714714+715715+ wil_dbg_fw(wil,716716+ "using info from fw file for record %d: addr[0x%08x], max size %d\n",717717+ i, wil->brd_info[i].file_addr,718718+ wil->brd_info[i].file_max_size);719719+720720+ rc = __fw_handle_data(wil, &hdr[1], hdr_sz,721721+ cpu_to_le32(wil->brd_info[i].file_addr));722722+ if (rc)723723+ return rc;724724+ }725725+726726+ if (size) {727727+ wil_err_fw(wil, "unprocessed bytes: %zu\n", size);728728+ if (size >= sizeof(*hdr)) {729729+ wil_err_fw(wil,730730+ "Stop at offset %ld record type %d [%zd bytes]\n",731731+ (long)((const void *)hdr - data),732732+ le16_to_cpu(hdr->type), hdr_sz);733733+ }733734 return -EINVAL;734735 }735735- type = le16_to_cpu(hdr->type);736736- if (type != wil_fw_type_data) {737737- wil_err_fw(wil, "invalid record type for board file: %d\n",738738- type);739739- return -EINVAL;740740- }741741- if (hdr_sz < sizeof(struct wil_fw_record_data)) {742742- wil_err_fw(wil, "data record too short: %zu\n", hdr_sz);743743- return -EINVAL;744744- }745736746746- wil_dbg_fw(wil, "using addr from fw file: [0x%08x]\n",747747- wil->brd_file_addr);748748-749749- rc = __fw_handle_data(wil, &hdr[1], hdr_sz,750750- cpu_to_le32(wil->brd_file_addr));751751-752752- return rc;737737+ return 0;753738}754739755740/**···807738 rc = dlen;808739 goto out;809740 }810810- /* Process the data record */741741+742742+ /* Process the data records */811743 rc = wil_brd_process(wil, brd->data, dlen);812744813745out: