diff options
author | Igor Mitsyanko <igor.mitsyanko.os@quantenna.com> | 2017-10-30 21:04:50 -0400 |
---|---|---|
committer | Kalle Valo <kvalo@codeaurora.org> | 2017-11-09 21:30:56 -0500 |
commit | 18b7470f92dfbea3e5ef82cab70edfc559d46735 (patch) | |
tree | cae86e88506436ab01e368b8bbb06a19f68967f4 | |
parent | d1398b5b34cca945cadf75f29833785cf6a675b1 (diff) |
qtnfmac: extend "IE set" TLV to include frame type info
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.os@quantenna.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
-rw-r--r-- | drivers/net/wireless/quantenna/qtnfmac/commands.c | 25 | ||||
-rw-r--r-- | drivers/net/wireless/quantenna/qtnfmac/event.c | 58 | ||||
-rw-r--r-- | 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 503187a371ae..8d3cdba99390 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, | |||
147 | return cmd_skb; | 147 | return cmd_skb; |
148 | } | 148 | } |
149 | 149 | ||
150 | static void qtnf_cmd_tlv_ie_set_add(struct sk_buff *cmd_skb, u8 frame_type, | ||
151 | const u8 *buf, size_t len) | ||
152 | { | ||
153 | struct qlink_tlv_ie_set *tlv; | ||
154 | |||
155 | tlv = (struct qlink_tlv_ie_set *)skb_put(cmd_skb, sizeof(*tlv) + len); | ||
156 | tlv->hdr.type = cpu_to_le16(QTN_TLV_ID_IE_SET); | ||
157 | tlv->hdr.len = cpu_to_le16(len + sizeof(*tlv) - sizeof(tlv->hdr)); | ||
158 | tlv->type = frame_type; | ||
159 | tlv->flags = 0; | ||
160 | |||
161 | if (len && buf) | ||
162 | memcpy(tlv->ie_data, buf, len); | ||
163 | } | ||
164 | |||
150 | int qtnf_cmd_send_start_ap(struct qtnf_vif *vif) | 165 | int qtnf_cmd_send_start_ap(struct qtnf_vif *vif) |
151 | { | 166 | { |
152 | struct sk_buff *cmd_skb; | 167 | struct sk_buff *cmd_skb; |
@@ -2028,9 +2043,8 @@ int qtnf_cmd_send_scan(struct qtnf_wmac *mac) | |||
2028 | } | 2043 | } |
2029 | 2044 | ||
2030 | if (scan_req->ie_len != 0) | 2045 | if (scan_req->ie_len != 0) |
2031 | qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_IE_SET, | 2046 | qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_PROBE_REQ, |
2032 | scan_req->ie, | 2047 | scan_req->ie, scan_req->ie_len); |
2033 | scan_req->ie_len); | ||
2034 | 2048 | ||
2035 | if (scan_req->n_channels) { | 2049 | if (scan_req->n_channels) { |
2036 | n_channels = scan_req->n_channels; | 2050 | n_channels = scan_req->n_channels; |
@@ -2154,9 +2168,8 @@ int qtnf_cmd_send_connect(struct qtnf_vif *vif, | |||
2154 | sme->ssid_len); | 2168 | sme->ssid_len); |
2155 | 2169 | ||
2156 | if (sme->ie_len != 0) | 2170 | if (sme->ie_len != 0) |
2157 | qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_IE_SET, | 2171 | qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_ASSOC_REQ, |
2158 | sme->ie, | 2172 | sme->ie, sme->ie_len); |
2159 | sme->ie_len); | ||
2160 | 2173 | ||
2161 | qtnf_bus_lock(vif->mac->bus); | 2174 | qtnf_bus_lock(vif->mac->bus); |
2162 | 2175 | ||
diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c b/drivers/net/wireless/quantenna/qtnfmac/event.c index 4b29f9fb9c3c..b67a082eed69 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, | |||
65 | sinfo.assoc_req_ies_len = 0; | 65 | sinfo.assoc_req_ies_len = 0; |
66 | 66 | ||
67 | payload_len = len - sizeof(*sta_assoc); | 67 | payload_len = len - sizeof(*sta_assoc); |
68 | tlv = (struct qlink_tlv_hdr *)sta_assoc->ies; | 68 | tlv = (const struct qlink_tlv_hdr *)sta_assoc->ies; |
69 | 69 | ||
70 | while (payload_len >= sizeof(struct qlink_tlv_hdr)) { | 70 | while (payload_len >= sizeof(*tlv)) { |
71 | tlv_type = le16_to_cpu(tlv->type); | 71 | tlv_type = le16_to_cpu(tlv->type); |
72 | tlv_value_len = le16_to_cpu(tlv->len); | 72 | tlv_value_len = le16_to_cpu(tlv->len); |
73 | tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr); | 73 | tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr); |
74 | 74 | ||
75 | if (tlv_full_len > payload_len) { | 75 | if (tlv_full_len > payload_len) |
76 | pr_warn("VIF%u.%u: malformed TLV 0x%.2X; LEN: %u\n", | ||
77 | mac->macid, vif->vifid, tlv_type, | ||
78 | tlv_value_len); | ||
79 | return -EINVAL; | 76 | return -EINVAL; |
80 | } | ||
81 | 77 | ||
82 | if (tlv_type == QTN_TLV_ID_IE_SET) { | 78 | if (tlv_type == QTN_TLV_ID_IE_SET) { |
83 | sinfo.assoc_req_ies = tlv->val; | 79 | const struct qlink_tlv_ie_set *ie_set; |
84 | sinfo.assoc_req_ies_len = tlv_value_len; | 80 | unsigned int ie_len; |
81 | |||
82 | if (payload_len < sizeof(*ie_set)) | ||
83 | return -EINVAL; | ||
84 | |||
85 | ie_set = (const struct qlink_tlv_ie_set *)tlv; | ||
86 | ie_len = tlv_value_len - | ||
87 | (sizeof(*ie_set) - sizeof(ie_set->hdr)); | ||
88 | |||
89 | if (ie_set->type == QLINK_IE_SET_ASSOC_REQ && ie_len) { | ||
90 | sinfo.assoc_req_ies = ie_set->ie_data; | ||
91 | sinfo.assoc_req_ies_len = ie_len; | ||
92 | } | ||
85 | } | 93 | } |
86 | 94 | ||
87 | payload_len -= tlv_full_len; | 95 | payload_len -= tlv_full_len; |
88 | tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len); | 96 | tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len); |
89 | } | 97 | } |
90 | 98 | ||
91 | if (payload_len) { | 99 | if (payload_len) |
92 | pr_warn("VIF%u.%u: malformed TLV buf; bytes left: %zu\n", | ||
93 | mac->macid, vif->vifid, payload_len); | ||
94 | return -EINVAL; | 100 | return -EINVAL; |
95 | } | ||
96 | 101 | ||
97 | cfg80211_new_sta(vif->netdev, sta_assoc->sta_addr, &sinfo, | 102 | cfg80211_new_sta(vif->netdev, sta_assoc->sta_addr, &sinfo, |
98 | GFP_KERNEL); | 103 | GFP_KERNEL); |
@@ -289,27 +294,32 @@ qtnf_event_handle_scan_results(struct qtnf_vif *vif, | |||
289 | tlv_value_len = le16_to_cpu(tlv->len); | 294 | tlv_value_len = le16_to_cpu(tlv->len); |
290 | tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr); | 295 | tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr); |
291 | 296 | ||
292 | if (tlv_full_len > payload_len) { | 297 | if (tlv_full_len > payload_len) |
293 | pr_warn("VIF%u.%u: malformed TLV 0x%.2X; LEN: %u\n", | ||
294 | vif->mac->macid, vif->vifid, tlv_type, | ||
295 | tlv_value_len); | ||
296 | return -EINVAL; | 298 | return -EINVAL; |
297 | } | ||
298 | 299 | ||
299 | if (tlv_type == QTN_TLV_ID_IE_SET) { | 300 | if (tlv_type == QTN_TLV_ID_IE_SET) { |
300 | ies = tlv->val; | 301 | const struct qlink_tlv_ie_set *ie_set; |
301 | ies_len = tlv_value_len; | 302 | unsigned int ie_len; |
303 | |||
304 | if (payload_len < sizeof(*ie_set)) | ||
305 | return -EINVAL; | ||
306 | |||
307 | ie_set = (const struct qlink_tlv_ie_set *)tlv; | ||
308 | ie_len = tlv_value_len - | ||
309 | (sizeof(*ie_set) - sizeof(ie_set->hdr)); | ||
310 | |||
311 | if (ie_len) { | ||
312 | ies = ie_set->ie_data; | ||
313 | ies_len = ie_len; | ||
314 | } | ||
302 | } | 315 | } |
303 | 316 | ||
304 | payload_len -= tlv_full_len; | 317 | payload_len -= tlv_full_len; |
305 | tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len); | 318 | tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len); |
306 | } | 319 | } |
307 | 320 | ||
308 | if (payload_len) { | 321 | if (payload_len) |
309 | pr_warn("VIF%u.%u: malformed TLV buf; bytes left: %zu\n", | ||
310 | vif->mac->macid, vif->vifid, payload_len); | ||
311 | return -EINVAL; | 322 | return -EINVAL; |
312 | } | ||
313 | 323 | ||
314 | bss = cfg80211_inform_bss(wiphy, channel, frame_type, | 324 | bss = cfg80211_inform_bss(wiphy, channel, frame_type, |
315 | sr->bssid, get_unaligned_le64(&sr->tsf), | 325 | 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 c558d819a966..f491942eb6d0 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/qlink.h +++ b/drivers/net/wireless/quantenna/qtnfmac/qlink.h | |||
@@ -1147,6 +1147,33 @@ struct qlink_tlv_chandef { | |||
1147 | struct qlink_chandef chan; | 1147 | struct qlink_chandef chan; |
1148 | } __packed; | 1148 | } __packed; |
1149 | 1149 | ||
1150 | enum qlink_ie_set_type { | ||
1151 | QLINK_IE_SET_UNKNOWN, | ||
1152 | QLINK_IE_SET_ASSOC_REQ, | ||
1153 | QLINK_IE_SET_ASSOC_RESP, | ||
1154 | QLINK_IE_SET_PROBE_REQ, | ||
1155 | QLINK_IE_SET_SCAN, | ||
1156 | QLINK_IE_SET_BEACON_HEAD, | ||
1157 | QLINK_IE_SET_BEACON_TAIL, | ||
1158 | QLINK_IE_SET_BEACON_IES, | ||
1159 | QLINK_IE_SET_PROBE_RESP, | ||
1160 | QLINK_IE_SET_PROBE_RESP_IES, | ||
1161 | }; | ||
1162 | |||
1163 | /** | ||
1164 | * struct qlink_tlv_ie_set - data for QTN_TLV_ID_IE_SET | ||
1165 | * | ||
1166 | * @type: type of MGMT frame IEs belong to, one of &enum qlink_ie_set_type. | ||
1167 | * @flags: for future use. | ||
1168 | * @ie_data: IEs data. | ||
1169 | */ | ||
1170 | struct qlink_tlv_ie_set { | ||
1171 | struct qlink_tlv_hdr hdr; | ||
1172 | u8 type; | ||
1173 | u8 flags; | ||
1174 | u8 ie_data[0]; | ||
1175 | } __packed; | ||
1176 | |||
1150 | struct qlink_chan_stats { | 1177 | struct qlink_chan_stats { |
1151 | __le32 chan_num; | 1178 | __le32 chan_num; |
1152 | __le32 cca_tx; | 1179 | __le32 cca_tx; |