From: Igor Mitsyanko <igor.mitsyanko...@quantenna.com> Specifying frame type for "IE set" TLV will allow to use several TLVs in a single message. Modify users accordingly.
Signed-off-by: Igor Mitsyanko <igor.mitsyanko...@quantenna.com> --- drivers/net/wireless/quantenna/qtnfmac/commands.c | 25 +++++++--- drivers/net/wireless/quantenna/qtnfmac/event.c | 58 +++++++++++++---------- drivers/net/wireless/quantenna/qtnfmac/qlink.h | 27 +++++++++++ 3 files changed, 80 insertions(+), 30 deletions(-) diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c index 79a3e75..cc37114 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.c +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c @@ -147,6 +147,21 @@ static struct sk_buff *qtnf_cmd_alloc_new_cmdskb(u8 macid, u8 vifid, u16 cmd_no, return cmd_skb; } +static void qtnf_cmd_tlv_ie_set_add(struct sk_buff *cmd_skb, u8 frame_type, + const u8 *buf, size_t len) +{ + struct qlink_tlv_ie_set *tlv; + + tlv = (struct qlink_tlv_ie_set *)skb_put(cmd_skb, sizeof(*tlv) + len); + tlv->hdr.type = cpu_to_le16(QTN_TLV_ID_IE_SET); + tlv->hdr.len = cpu_to_le16(len + sizeof(*tlv) - sizeof(tlv->hdr)); + tlv->type = frame_type; + tlv->flags = 0; + + if (len && buf) + memcpy(tlv->ie_data, buf, len); +} + int qtnf_cmd_send_start_ap(struct qtnf_vif *vif) { struct sk_buff *cmd_skb; @@ -2026,9 +2041,8 @@ int qtnf_cmd_send_scan(struct qtnf_wmac *mac) } if (scan_req->ie_len != 0) - qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_IE_SET, - scan_req->ie, - scan_req->ie_len); + qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_PROBE_REQ, + scan_req->ie, scan_req->ie_len); if (scan_req->n_channels) { n_channels = scan_req->n_channels; @@ -2152,9 +2166,8 @@ int qtnf_cmd_send_connect(struct qtnf_vif *vif, sme->ssid_len); if (sme->ie_len != 0) - qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_IE_SET, - sme->ie, - sme->ie_len); + qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_ASSOC_REQ, + sme->ie, sme->ie_len); qtnf_bus_lock(vif->mac->bus); diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c b/drivers/net/wireless/quantenna/qtnfmac/event.c index b2f6410..c2452dc 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/event.c +++ b/drivers/net/wireless/quantenna/qtnfmac/event.c @@ -65,34 +65,39 @@ qtnf_event_handle_sta_assoc(struct qtnf_wmac *mac, struct qtnf_vif *vif, sinfo.assoc_req_ies_len = 0; payload_len = len - sizeof(*sta_assoc); - tlv = (struct qlink_tlv_hdr *)sta_assoc->ies; + tlv = (const struct qlink_tlv_hdr *)sta_assoc->ies; - while (payload_len >= sizeof(struct qlink_tlv_hdr)) { + while (payload_len >= sizeof(*tlv)) { tlv_type = le16_to_cpu(tlv->type); tlv_value_len = le16_to_cpu(tlv->len); tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr); - if (tlv_full_len > payload_len) { - pr_warn("VIF%u.%u: malformed TLV 0x%.2X; LEN: %u\n", - mac->macid, vif->vifid, tlv_type, - tlv_value_len); + if (tlv_full_len > payload_len) return -EINVAL; - } if (tlv_type == QTN_TLV_ID_IE_SET) { - sinfo.assoc_req_ies = tlv->val; - sinfo.assoc_req_ies_len = tlv_value_len; + const struct qlink_tlv_ie_set *ie_set; + unsigned int ie_len; + + if (payload_len < sizeof(*ie_set)) + return -EINVAL; + + ie_set = (const struct qlink_tlv_ie_set *)tlv; + ie_len = tlv_value_len - + (sizeof(*ie_set) - sizeof(ie_set->hdr)); + + if (ie_set->type == QLINK_IE_SET_ASSOC_REQ && ie_len) { + sinfo.assoc_req_ies = ie_set->ie_data; + sinfo.assoc_req_ies_len = ie_len; + } } payload_len -= tlv_full_len; tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len); } - if (payload_len) { - pr_warn("VIF%u.%u: malformed TLV buf; bytes left: %zu\n", - mac->macid, vif->vifid, payload_len); + if (payload_len) return -EINVAL; - } cfg80211_new_sta(vif->netdev, sta_assoc->sta_addr, &sinfo, GFP_KERNEL); @@ -289,27 +294,32 @@ qtnf_event_handle_scan_results(struct qtnf_vif *vif, tlv_value_len = le16_to_cpu(tlv->len); tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr); - if (tlv_full_len > payload_len) { - pr_warn("VIF%u.%u: malformed TLV 0x%.2X; LEN: %u\n", - vif->mac->macid, vif->vifid, tlv_type, - tlv_value_len); + if (tlv_full_len > payload_len) return -EINVAL; - } if (tlv_type == QTN_TLV_ID_IE_SET) { - ies = tlv->val; - ies_len = tlv_value_len; + const struct qlink_tlv_ie_set *ie_set; + unsigned int ie_len; + + if (payload_len < sizeof(*ie_set)) + return -EINVAL; + + ie_set = (const struct qlink_tlv_ie_set *)tlv; + ie_len = tlv_value_len - + (sizeof(*ie_set) - sizeof(ie_set->hdr)); + + if (ie_len) { + ies = ie_set->ie_data; + ies_len = ie_len; + } } payload_len -= tlv_full_len; tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len); } - if (payload_len) { - pr_warn("VIF%u.%u: malformed TLV buf; bytes left: %zu\n", - vif->mac->macid, vif->vifid, payload_len); + if (payload_len) return -EINVAL; - } bss = cfg80211_inform_bss(wiphy, channel, frame_type, sr->bssid, get_unaligned_le64(&sr->tsf), diff --git a/drivers/net/wireless/quantenna/qtnfmac/qlink.h b/drivers/net/wireless/quantenna/qtnfmac/qlink.h index e4d3e7f..ecf493d 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h @@ -1138,6 +1138,33 @@ struct qlink_tlv_chandef { struct qlink_chandef chan; } __packed; +enum qlink_ie_set_type { + QLINK_IE_SET_UNKNOWN, + QLINK_IE_SET_ASSOC_REQ, + QLINK_IE_SET_ASSOC_RESP, + QLINK_IE_SET_PROBE_REQ, + QLINK_IE_SET_SCAN, + QLINK_IE_SET_BEACON_HEAD, + QLINK_IE_SET_BEACON_TAIL, + QLINK_IE_SET_BEACON_IES, + QLINK_IE_SET_PROBE_RESP, + QLINK_IE_SET_PROBE_RESP_IES, +}; + +/** + * struct qlink_tlv_ie_set - data for QTN_TLV_ID_IE_SET + * + * @type: type of MGMT frame IEs belong to, one of &enum qlink_ie_set_type. + * @flags: for future use. + * @ie_data: IEs data. + */ +struct qlink_tlv_ie_set { + struct qlink_tlv_hdr hdr; + u8 type; + u8 flags; + u8 ie_data[0]; +} __packed; + struct qlink_chan_stats { __le32 chan_num; __le32 cca_tx; -- 2.9.5