diff options
Diffstat (limited to 'drivers/net/wireless/quantenna/qtnfmac/commands.c')
-rw-r--r-- | drivers/net/wireless/quantenna/qtnfmac/commands.c | 276 |
1 files changed, 190 insertions, 86 deletions
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c index b81f81bd1411..8bc8dd637315 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/commands.c +++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c | |||
@@ -147,56 +147,66 @@ 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 | int qtnf_cmd_send_start_ap(struct qtnf_vif *vif) | 150 | static void qtnf_cmd_tlv_ie_set_add(struct sk_buff *cmd_skb, u8 frame_type, |
151 | const u8 *buf, size_t len) | ||
151 | { | 152 | { |
152 | struct sk_buff *cmd_skb; | 153 | struct qlink_tlv_ie_set *tlv; |
153 | u16 res_code = QLINK_CMD_RESULT_OK; | ||
154 | int ret; | ||
155 | 154 | ||
156 | cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, | 155 | tlv = (struct qlink_tlv_ie_set *)skb_put(cmd_skb, sizeof(*tlv) + len); |
157 | QLINK_CMD_START_AP, | 156 | tlv->hdr.type = cpu_to_le16(QTN_TLV_ID_IE_SET); |
158 | sizeof(struct qlink_cmd)); | 157 | tlv->hdr.len = cpu_to_le16(len + sizeof(*tlv) - sizeof(tlv->hdr)); |
159 | if (unlikely(!cmd_skb)) | 158 | tlv->type = frame_type; |
160 | return -ENOMEM; | 159 | tlv->flags = 0; |
161 | 160 | ||
162 | qtnf_bus_lock(vif->mac->bus); | 161 | if (len && buf) |
162 | memcpy(tlv->ie_data, buf, len); | ||
163 | } | ||
163 | 164 | ||
164 | ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code); | 165 | static bool qtnf_cmd_start_ap_can_fit(const struct qtnf_vif *vif, |
166 | const struct cfg80211_ap_settings *s) | ||
167 | { | ||
168 | unsigned int len = sizeof(struct qlink_cmd_start_ap); | ||
165 | 169 | ||
166 | if (unlikely(ret)) | 170 | len += s->ssid_len; |
167 | goto out; | 171 | len += s->beacon.head_len; |
172 | len += s->beacon.tail_len; | ||
173 | len += s->beacon.beacon_ies_len; | ||
174 | len += s->beacon.proberesp_ies_len; | ||
175 | len += s->beacon.assocresp_ies_len; | ||
176 | len += s->beacon.probe_resp_len; | ||
168 | 177 | ||
169 | if (unlikely(res_code != QLINK_CMD_RESULT_OK)) { | 178 | if (cfg80211_chandef_valid(&s->chandef)) |
170 | pr_err("VIF%u.%u: CMD failed: %u\n", vif->mac->macid, | 179 | len += sizeof(struct qlink_tlv_chandef); |
171 | vif->vifid, res_code); | ||
172 | ret = -EFAULT; | ||
173 | goto out; | ||
174 | } | ||
175 | 180 | ||
176 | netif_carrier_on(vif->netdev); | 181 | if (len > (sizeof(struct qlink_cmd) + QTNF_MAX_CMD_BUF_SIZE)) { |
182 | pr_err("VIF%u.%u: can not fit AP settings: %u\n", | ||
183 | vif->mac->macid, vif->vifid, len); | ||
184 | return false; | ||
185 | } | ||
177 | 186 | ||
178 | out: | 187 | return true; |
179 | qtnf_bus_unlock(vif->mac->bus); | ||
180 | return ret; | ||
181 | } | 188 | } |
182 | 189 | ||
183 | int qtnf_cmd_send_config_ap(struct qtnf_vif *vif, | 190 | int qtnf_cmd_send_start_ap(struct qtnf_vif *vif, |
184 | const struct cfg80211_ap_settings *s) | 191 | const struct cfg80211_ap_settings *s) |
185 | { | 192 | { |
186 | struct sk_buff *cmd_skb; | 193 | struct sk_buff *cmd_skb; |
187 | struct qlink_cmd_config_ap *cmd; | 194 | struct qlink_cmd_start_ap *cmd; |
188 | struct qlink_auth_encr *aen; | 195 | struct qlink_auth_encr *aen; |
189 | u16 res_code = QLINK_CMD_RESULT_OK; | 196 | u16 res_code = QLINK_CMD_RESULT_OK; |
190 | int ret; | 197 | int ret; |
191 | int i; | 198 | int i; |
192 | 199 | ||
200 | if (!qtnf_cmd_start_ap_can_fit(vif, s)) | ||
201 | return -E2BIG; | ||
202 | |||
193 | cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, | 203 | cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, |
194 | QLINK_CMD_CONFIG_AP, | 204 | QLINK_CMD_START_AP, |
195 | sizeof(*cmd)); | 205 | sizeof(*cmd)); |
196 | if (unlikely(!cmd_skb)) | 206 | if (unlikely(!cmd_skb)) |
197 | return -ENOMEM; | 207 | return -ENOMEM; |
198 | 208 | ||
199 | cmd = (struct qlink_cmd_config_ap *)cmd_skb->data; | 209 | cmd = (struct qlink_cmd_start_ap *)cmd_skb->data; |
200 | cmd->dtim_period = s->dtim_period; | 210 | cmd->dtim_period = s->dtim_period; |
201 | cmd->beacon_interval = cpu_to_le16(s->beacon_interval); | 211 | cmd->beacon_interval = cpu_to_le16(s->beacon_interval); |
202 | cmd->hidden_ssid = qlink_hidden_ssid_nl2q(s->hidden_ssid); | 212 | cmd->hidden_ssid = qlink_hidden_ssid_nl2q(s->hidden_ssid); |
@@ -211,7 +221,6 @@ int qtnf_cmd_send_config_ap(struct qtnf_vif *vif, | |||
211 | aen = &cmd->aen; | 221 | aen = &cmd->aen; |
212 | aen->auth_type = s->auth_type; | 222 | aen->auth_type = s->auth_type; |
213 | aen->privacy = !!s->privacy; | 223 | aen->privacy = !!s->privacy; |
214 | aen->mfp = 0; | ||
215 | aen->wpa_versions = cpu_to_le32(s->crypto.wpa_versions); | 224 | aen->wpa_versions = cpu_to_le32(s->crypto.wpa_versions); |
216 | aen->cipher_group = cpu_to_le32(s->crypto.cipher_group); | 225 | aen->cipher_group = cpu_to_le32(s->crypto.cipher_group); |
217 | aen->n_ciphers_pairwise = cpu_to_le32(s->crypto.n_ciphers_pairwise); | 226 | aen->n_ciphers_pairwise = cpu_to_le32(s->crypto.n_ciphers_pairwise); |
@@ -241,6 +250,39 @@ int qtnf_cmd_send_config_ap(struct qtnf_vif *vif, | |||
241 | qlink_chandef_cfg2q(&s->chandef, &chtlv->chan); | 250 | qlink_chandef_cfg2q(&s->chandef, &chtlv->chan); |
242 | } | 251 | } |
243 | 252 | ||
253 | qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_BEACON_HEAD, | ||
254 | s->beacon.head, s->beacon.head_len); | ||
255 | qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_BEACON_TAIL, | ||
256 | s->beacon.tail, s->beacon.tail_len); | ||
257 | qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_BEACON_IES, | ||
258 | s->beacon.beacon_ies, s->beacon.beacon_ies_len); | ||
259 | qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_PROBE_RESP, | ||
260 | s->beacon.probe_resp, s->beacon.probe_resp_len); | ||
261 | qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_PROBE_RESP_IES, | ||
262 | s->beacon.proberesp_ies, | ||
263 | s->beacon.proberesp_ies_len); | ||
264 | qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_ASSOC_RESP, | ||
265 | s->beacon.assocresp_ies, | ||
266 | s->beacon.assocresp_ies_len); | ||
267 | |||
268 | if (s->ht_cap) { | ||
269 | struct qlink_tlv_hdr *tlv = (struct qlink_tlv_hdr *) | ||
270 | skb_put(cmd_skb, sizeof(*tlv) + sizeof(*s->ht_cap)); | ||
271 | |||
272 | tlv->type = cpu_to_le16(WLAN_EID_HT_CAPABILITY); | ||
273 | tlv->len = cpu_to_le16(sizeof(*s->ht_cap)); | ||
274 | memcpy(tlv->val, s->ht_cap, sizeof(*s->ht_cap)); | ||
275 | } | ||
276 | |||
277 | if (s->vht_cap) { | ||
278 | struct qlink_tlv_hdr *tlv = (struct qlink_tlv_hdr *) | ||
279 | skb_put(cmd_skb, sizeof(*tlv) + sizeof(*s->vht_cap)); | ||
280 | |||
281 | tlv->type = cpu_to_le16(WLAN_EID_VHT_CAPABILITY); | ||
282 | tlv->len = cpu_to_le16(sizeof(*s->vht_cap)); | ||
283 | memcpy(tlv->val, s->vht_cap, sizeof(*s->vht_cap)); | ||
284 | } | ||
285 | |||
244 | qtnf_bus_lock(vif->mac->bus); | 286 | qtnf_bus_lock(vif->mac->bus); |
245 | 287 | ||
246 | ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code); | 288 | ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code); |
@@ -255,6 +297,8 @@ int qtnf_cmd_send_config_ap(struct qtnf_vif *vif, | |||
255 | goto out; | 297 | goto out; |
256 | } | 298 | } |
257 | 299 | ||
300 | netif_carrier_on(vif->netdev); | ||
301 | |||
258 | out: | 302 | out: |
259 | qtnf_bus_unlock(vif->mac->bus); | 303 | qtnf_bus_unlock(vif->mac->bus); |
260 | return ret; | 304 | return ret; |
@@ -380,11 +424,10 @@ int qtnf_cmd_send_mgmt_set_appie(struct qtnf_vif *vif, u8 frame_type, | |||
380 | const u8 *buf, size_t len) | 424 | const u8 *buf, size_t len) |
381 | { | 425 | { |
382 | struct sk_buff *cmd_skb; | 426 | struct sk_buff *cmd_skb; |
383 | struct qlink_cmd_mgmt_append_ie *cmd; | ||
384 | u16 res_code = QLINK_CMD_RESULT_OK; | 427 | u16 res_code = QLINK_CMD_RESULT_OK; |
385 | int ret; | 428 | int ret; |
386 | 429 | ||
387 | if (sizeof(*cmd) + len > QTNF_MAX_CMD_BUF_SIZE) { | 430 | if (len > QTNF_MAX_CMD_BUF_SIZE) { |
388 | pr_warn("VIF%u.%u: %u frame is too big: %zu\n", vif->mac->macid, | 431 | pr_warn("VIF%u.%u: %u frame is too big: %zu\n", vif->mac->macid, |
389 | vif->vifid, frame_type, len); | 432 | vif->vifid, frame_type, len); |
390 | return -E2BIG; | 433 | return -E2BIG; |
@@ -392,21 +435,13 @@ int qtnf_cmd_send_mgmt_set_appie(struct qtnf_vif *vif, u8 frame_type, | |||
392 | 435 | ||
393 | cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, | 436 | cmd_skb = qtnf_cmd_alloc_new_cmdskb(vif->mac->macid, vif->vifid, |
394 | QLINK_CMD_MGMT_SET_APPIE, | 437 | QLINK_CMD_MGMT_SET_APPIE, |
395 | sizeof(*cmd)); | 438 | sizeof(struct qlink_cmd)); |
396 | if (unlikely(!cmd_skb)) | 439 | if (unlikely(!cmd_skb)) |
397 | return -ENOMEM; | 440 | return -ENOMEM; |
398 | 441 | ||
399 | qtnf_bus_lock(vif->mac->bus); | 442 | qtnf_cmd_tlv_ie_set_add(cmd_skb, frame_type, buf, len); |
400 | |||
401 | cmd = (struct qlink_cmd_mgmt_append_ie *)cmd_skb->data; | ||
402 | cmd->type = frame_type; | ||
403 | cmd->flags = 0; | ||
404 | 443 | ||
405 | /* If len == 0 then IE buf for specified frame type | 444 | qtnf_bus_lock(vif->mac->bus); |
406 | * should be cleared on EP. | ||
407 | */ | ||
408 | if (len && buf) | ||
409 | qtnf_cmd_skb_put_buffer(cmd_skb, buf, len); | ||
410 | 445 | ||
411 | ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code); | 446 | ret = qtnf_cmd_send(vif->mac->bus, cmd_skb, &res_code); |
412 | 447 | ||
@@ -1090,7 +1125,6 @@ qtnf_cmd_resp_proc_mac_info(struct qtnf_wmac *mac, | |||
1090 | mac_info = &mac->macinfo; | 1125 | mac_info = &mac->macinfo; |
1091 | 1126 | ||
1092 | mac_info->bands_cap = resp_info->bands_cap; | 1127 | mac_info->bands_cap = resp_info->bands_cap; |
1093 | mac_info->phymode_cap = resp_info->phymode_cap; | ||
1094 | memcpy(&mac_info->dev_mac, &resp_info->dev_mac, | 1128 | memcpy(&mac_info->dev_mac, &resp_info->dev_mac, |
1095 | sizeof(mac_info->dev_mac)); | 1129 | sizeof(mac_info->dev_mac)); |
1096 | 1130 | ||
@@ -1110,24 +1144,56 @@ qtnf_cmd_resp_proc_mac_info(struct qtnf_wmac *mac, | |||
1110 | qlink_chan_width_mask_to_nl(le16_to_cpu( | 1144 | qlink_chan_width_mask_to_nl(le16_to_cpu( |
1111 | resp_info->radar_detect_widths)); | 1145 | resp_info->radar_detect_widths)); |
1112 | 1146 | ||
1113 | memcpy(&mac_info->ht_cap, &resp_info->ht_cap, sizeof(mac_info->ht_cap)); | 1147 | memcpy(&mac_info->ht_cap_mod_mask, &resp_info->ht_cap_mod_mask, |
1114 | memcpy(&mac_info->vht_cap, &resp_info->vht_cap, | 1148 | sizeof(mac_info->ht_cap_mod_mask)); |
1115 | sizeof(mac_info->vht_cap)); | 1149 | memcpy(&mac_info->vht_cap_mod_mask, &resp_info->vht_cap_mod_mask, |
1150 | sizeof(mac_info->vht_cap_mod_mask)); | ||
1151 | } | ||
1152 | |||
1153 | static void qtnf_cmd_resp_band_fill_htcap(const u8 *info, | ||
1154 | struct ieee80211_sta_ht_cap *bcap) | ||
1155 | { | ||
1156 | const struct ieee80211_ht_cap *ht_cap = | ||
1157 | (const struct ieee80211_ht_cap *)info; | ||
1158 | |||
1159 | bcap->ht_supported = true; | ||
1160 | bcap->cap = le16_to_cpu(ht_cap->cap_info); | ||
1161 | bcap->ampdu_factor = | ||
1162 | ht_cap->ampdu_params_info & IEEE80211_HT_AMPDU_PARM_FACTOR; | ||
1163 | bcap->ampdu_density = | ||
1164 | (ht_cap->ampdu_params_info & IEEE80211_HT_AMPDU_PARM_DENSITY) >> | ||
1165 | IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT; | ||
1166 | memcpy(&bcap->mcs, &ht_cap->mcs, sizeof(bcap->mcs)); | ||
1167 | } | ||
1168 | |||
1169 | static void qtnf_cmd_resp_band_fill_vhtcap(const u8 *info, | ||
1170 | struct ieee80211_sta_vht_cap *bcap) | ||
1171 | { | ||
1172 | const struct ieee80211_vht_cap *vht_cap = | ||
1173 | (const struct ieee80211_vht_cap *)info; | ||
1174 | |||
1175 | bcap->vht_supported = true; | ||
1176 | bcap->cap = le32_to_cpu(vht_cap->vht_cap_info); | ||
1177 | memcpy(&bcap->vht_mcs, &vht_cap->supp_mcs, sizeof(bcap->vht_mcs)); | ||
1116 | } | 1178 | } |
1117 | 1179 | ||
1118 | static int | 1180 | static int |
1119 | qtnf_cmd_resp_fill_channels_info(struct ieee80211_supported_band *band, | 1181 | qtnf_cmd_resp_fill_band_info(struct ieee80211_supported_band *band, |
1120 | struct qlink_resp_get_chan_info *resp, | 1182 | struct qlink_resp_band_info_get *resp, |
1121 | size_t payload_len) | 1183 | size_t payload_len) |
1122 | { | 1184 | { |
1123 | u16 tlv_type; | 1185 | u16 tlv_type; |
1124 | size_t tlv_len; | 1186 | size_t tlv_len; |
1187 | size_t tlv_dlen; | ||
1125 | const struct qlink_tlv_hdr *tlv; | 1188 | const struct qlink_tlv_hdr *tlv; |
1126 | const struct qlink_tlv_channel *qchan; | 1189 | const struct qlink_tlv_channel *qchan; |
1127 | struct ieee80211_channel *chan; | 1190 | struct ieee80211_channel *chan; |
1128 | unsigned int chidx = 0; | 1191 | unsigned int chidx = 0; |
1129 | u32 qflags; | 1192 | u32 qflags; |
1130 | 1193 | ||
1194 | memset(&band->ht_cap, 0, sizeof(band->ht_cap)); | ||
1195 | memset(&band->vht_cap, 0, sizeof(band->vht_cap)); | ||
1196 | |||
1131 | if (band->channels) { | 1197 | if (band->channels) { |
1132 | if (band->n_channels == resp->num_chans) { | 1198 | if (band->n_channels == resp->num_chans) { |
1133 | memset(band->channels, 0, | 1199 | memset(band->channels, 0, |
@@ -1155,7 +1221,8 @@ qtnf_cmd_resp_fill_channels_info(struct ieee80211_supported_band *band, | |||
1155 | 1221 | ||
1156 | while (payload_len >= sizeof(*tlv)) { | 1222 | while (payload_len >= sizeof(*tlv)) { |
1157 | tlv_type = le16_to_cpu(tlv->type); | 1223 | tlv_type = le16_to_cpu(tlv->type); |
1158 | tlv_len = le16_to_cpu(tlv->len) + sizeof(*tlv); | 1224 | tlv_dlen = le16_to_cpu(tlv->len); |
1225 | tlv_len = tlv_dlen + sizeof(*tlv); | ||
1159 | 1226 | ||
1160 | if (tlv_len > payload_len) { | 1227 | if (tlv_len > payload_len) { |
1161 | pr_warn("malformed TLV 0x%.2X; LEN: %zu\n", | 1228 | pr_warn("malformed TLV 0x%.2X; LEN: %zu\n", |
@@ -1241,13 +1308,32 @@ qtnf_cmd_resp_fill_channels_info(struct ieee80211_supported_band *band, | |||
1241 | chan->hw_value, chan->flags, chan->max_power, | 1308 | chan->hw_value, chan->flags, chan->max_power, |
1242 | chan->max_reg_power); | 1309 | chan->max_reg_power); |
1243 | break; | 1310 | break; |
1311 | case WLAN_EID_HT_CAPABILITY: | ||
1312 | if (unlikely(tlv_dlen != | ||
1313 | sizeof(struct ieee80211_ht_cap))) { | ||
1314 | pr_err("bad HTCAP TLV len %zu\n", tlv_dlen); | ||
1315 | goto error_ret; | ||
1316 | } | ||
1317 | |||
1318 | qtnf_cmd_resp_band_fill_htcap(tlv->val, &band->ht_cap); | ||
1319 | break; | ||
1320 | case WLAN_EID_VHT_CAPABILITY: | ||
1321 | if (unlikely(tlv_dlen != | ||
1322 | sizeof(struct ieee80211_vht_cap))) { | ||
1323 | pr_err("bad VHTCAP TLV len %zu\n", tlv_dlen); | ||
1324 | goto error_ret; | ||
1325 | } | ||
1326 | |||
1327 | qtnf_cmd_resp_band_fill_vhtcap(tlv->val, | ||
1328 | &band->vht_cap); | ||
1329 | break; | ||
1244 | default: | 1330 | default: |
1245 | pr_warn("unknown TLV type: %#x\n", tlv_type); | 1331 | pr_warn("unknown TLV type: %#x\n", tlv_type); |
1246 | break; | 1332 | break; |
1247 | } | 1333 | } |
1248 | 1334 | ||
1249 | payload_len -= tlv_len; | 1335 | payload_len -= tlv_len; |
1250 | tlv = (struct qlink_tlv_hdr *)((u8 *)tlv + tlv_len); | 1336 | tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_dlen); |
1251 | } | 1337 | } |
1252 | 1338 | ||
1253 | if (payload_len) { | 1339 | if (payload_len) { |
@@ -1469,13 +1555,13 @@ out: | |||
1469 | return ret; | 1555 | return ret; |
1470 | } | 1556 | } |
1471 | 1557 | ||
1472 | int qtnf_cmd_get_mac_chan_info(struct qtnf_wmac *mac, | 1558 | int qtnf_cmd_band_info_get(struct qtnf_wmac *mac, |
1473 | struct ieee80211_supported_band *band) | 1559 | struct ieee80211_supported_band *band) |
1474 | { | 1560 | { |
1475 | struct sk_buff *cmd_skb, *resp_skb = NULL; | 1561 | struct sk_buff *cmd_skb, *resp_skb = NULL; |
1476 | size_t info_len; | 1562 | size_t info_len; |
1477 | struct qlink_cmd_chans_info_get *cmd; | 1563 | struct qlink_cmd_band_info_get *cmd; |
1478 | struct qlink_resp_get_chan_info *resp; | 1564 | struct qlink_resp_band_info_get *resp; |
1479 | u16 res_code = QLINK_CMD_RESULT_OK; | 1565 | u16 res_code = QLINK_CMD_RESULT_OK; |
1480 | int ret = 0; | 1566 | int ret = 0; |
1481 | u8 qband; | 1567 | u8 qband; |
@@ -1495,12 +1581,12 @@ int qtnf_cmd_get_mac_chan_info(struct qtnf_wmac *mac, | |||
1495 | } | 1581 | } |
1496 | 1582 | ||
1497 | cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, 0, | 1583 | cmd_skb = qtnf_cmd_alloc_new_cmdskb(mac->macid, 0, |
1498 | QLINK_CMD_CHANS_INFO_GET, | 1584 | QLINK_CMD_BAND_INFO_GET, |
1499 | sizeof(*cmd)); | 1585 | sizeof(*cmd)); |
1500 | if (!cmd_skb) | 1586 | if (!cmd_skb) |
1501 | return -ENOMEM; | 1587 | return -ENOMEM; |
1502 | 1588 | ||
1503 | cmd = (struct qlink_cmd_chans_info_get *)cmd_skb->data; | 1589 | cmd = (struct qlink_cmd_band_info_get *)cmd_skb->data; |
1504 | cmd->band = qband; | 1590 | cmd->band = qband; |
1505 | 1591 | ||
1506 | qtnf_bus_lock(mac->bus); | 1592 | qtnf_bus_lock(mac->bus); |
@@ -1517,7 +1603,7 @@ int qtnf_cmd_get_mac_chan_info(struct qtnf_wmac *mac, | |||
1517 | goto out; | 1603 | goto out; |
1518 | } | 1604 | } |
1519 | 1605 | ||
1520 | resp = (struct qlink_resp_get_chan_info *)resp_skb->data; | 1606 | resp = (struct qlink_resp_band_info_get *)resp_skb->data; |
1521 | if (resp->band != qband) { | 1607 | if (resp->band != qband) { |
1522 | pr_err("MAC%u: reply band %u != cmd band %u\n", mac->macid, | 1608 | pr_err("MAC%u: reply band %u != cmd band %u\n", mac->macid, |
1523 | resp->band, qband); | 1609 | resp->band, qband); |
@@ -1525,7 +1611,7 @@ int qtnf_cmd_get_mac_chan_info(struct qtnf_wmac *mac, | |||
1525 | goto out; | 1611 | goto out; |
1526 | } | 1612 | } |
1527 | 1613 | ||
1528 | ret = qtnf_cmd_resp_fill_channels_info(band, resp, info_len); | 1614 | ret = qtnf_cmd_resp_fill_band_info(band, resp, info_len); |
1529 | 1615 | ||
1530 | out: | 1616 | out: |
1531 | qtnf_bus_unlock(mac->bus); | 1617 | qtnf_bus_unlock(mac->bus); |
@@ -1942,17 +2028,36 @@ out: | |||
1942 | return ret; | 2028 | return ret; |
1943 | } | 2029 | } |
1944 | 2030 | ||
2031 | static void qtnf_cmd_channel_tlv_add(struct sk_buff *cmd_skb, | ||
2032 | const struct ieee80211_channel *sc) | ||
2033 | { | ||
2034 | struct qlink_tlv_channel *qchan; | ||
2035 | u32 flags = 0; | ||
2036 | |||
2037 | qchan = skb_put_zero(cmd_skb, sizeof(*qchan)); | ||
2038 | qchan->hdr.type = cpu_to_le16(QTN_TLV_ID_CHANNEL); | ||
2039 | qchan->hdr.len = cpu_to_le16(sizeof(*qchan) - sizeof(qchan->hdr)); | ||
2040 | qchan->center_freq = cpu_to_le16(sc->center_freq); | ||
2041 | qchan->hw_value = cpu_to_le16(sc->hw_value); | ||
2042 | |||
2043 | if (sc->flags & IEEE80211_CHAN_NO_IR) | ||
2044 | flags |= QLINK_CHAN_NO_IR; | ||
2045 | |||
2046 | if (sc->flags & IEEE80211_CHAN_RADAR) | ||
2047 | flags |= QLINK_CHAN_RADAR; | ||
2048 | |||
2049 | qchan->flags = cpu_to_le32(flags); | ||
2050 | } | ||
2051 | |||
1945 | int qtnf_cmd_send_scan(struct qtnf_wmac *mac) | 2052 | int qtnf_cmd_send_scan(struct qtnf_wmac *mac) |
1946 | { | 2053 | { |
1947 | struct sk_buff *cmd_skb; | 2054 | struct sk_buff *cmd_skb; |
1948 | u16 res_code = QLINK_CMD_RESULT_OK; | 2055 | u16 res_code = QLINK_CMD_RESULT_OK; |
1949 | struct ieee80211_channel *sc; | 2056 | struct ieee80211_channel *sc; |
1950 | struct cfg80211_scan_request *scan_req = mac->scan_req; | 2057 | struct cfg80211_scan_request *scan_req = mac->scan_req; |
1951 | struct qlink_tlv_channel *qchan; | ||
1952 | int n_channels; | 2058 | int n_channels; |
1953 | int count = 0; | 2059 | int count = 0; |
1954 | int ret; | 2060 | int ret; |
1955 | u32 flags; | ||
1956 | 2061 | ||
1957 | if (scan_req->n_ssids > QTNF_MAX_SSID_LIST_LENGTH) { | 2062 | if (scan_req->n_ssids > QTNF_MAX_SSID_LIST_LENGTH) { |
1958 | pr_err("MAC%u: too many SSIDs in scan request\n", mac->macid); | 2063 | pr_err("MAC%u: too many SSIDs in scan request\n", mac->macid); |
@@ -1977,9 +2082,8 @@ int qtnf_cmd_send_scan(struct qtnf_wmac *mac) | |||
1977 | } | 2082 | } |
1978 | 2083 | ||
1979 | if (scan_req->ie_len != 0) | 2084 | if (scan_req->ie_len != 0) |
1980 | qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_IE_SET, | 2085 | qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_PROBE_REQ, |
1981 | scan_req->ie, | 2086 | scan_req->ie, scan_req->ie_len); |
1982 | scan_req->ie_len); | ||
1983 | 2087 | ||
1984 | if (scan_req->n_channels) { | 2088 | if (scan_req->n_channels) { |
1985 | n_channels = scan_req->n_channels; | 2089 | n_channels = scan_req->n_channels; |
@@ -1995,22 +2099,8 @@ int qtnf_cmd_send_scan(struct qtnf_wmac *mac) | |||
1995 | pr_debug("MAC%u: scan chan=%d, freq=%d, flags=%#x\n", | 2099 | pr_debug("MAC%u: scan chan=%d, freq=%d, flags=%#x\n", |
1996 | mac->macid, sc->hw_value, sc->center_freq, | 2100 | mac->macid, sc->hw_value, sc->center_freq, |
1997 | sc->flags); | 2101 | sc->flags); |
1998 | qchan = skb_put_zero(cmd_skb, sizeof(*qchan)); | ||
1999 | flags = 0; | ||
2000 | |||
2001 | qchan->hdr.type = cpu_to_le16(QTN_TLV_ID_CHANNEL); | ||
2002 | qchan->hdr.len = cpu_to_le16(sizeof(*qchan) - | ||
2003 | sizeof(struct qlink_tlv_hdr)); | ||
2004 | qchan->center_freq = cpu_to_le16(sc->center_freq); | ||
2005 | qchan->hw_value = cpu_to_le16(sc->hw_value); | ||
2006 | |||
2007 | if (sc->flags & IEEE80211_CHAN_NO_IR) | ||
2008 | flags |= QLINK_CHAN_NO_IR; | ||
2009 | |||
2010 | if (sc->flags & IEEE80211_CHAN_RADAR) | ||
2011 | flags |= QLINK_CHAN_RADAR; | ||
2012 | 2102 | ||
2013 | qchan->flags = cpu_to_le32(flags); | 2103 | qtnf_cmd_channel_tlv_add(cmd_skb, sc); |
2014 | n_channels--; | 2104 | n_channels--; |
2015 | count++; | 2105 | count++; |
2016 | } | 2106 | } |
@@ -2054,10 +2144,15 @@ int qtnf_cmd_send_connect(struct qtnf_vif *vif, | |||
2054 | 2144 | ||
2055 | ether_addr_copy(cmd->bssid, vif->bssid); | 2145 | ether_addr_copy(cmd->bssid, vif->bssid); |
2056 | 2146 | ||
2057 | if (sme->channel) | 2147 | if (sme->bssid_hint) |
2058 | cmd->channel = cpu_to_le16(sme->channel->hw_value); | 2148 | ether_addr_copy(cmd->bssid_hint, sme->bssid_hint); |
2149 | else | ||
2150 | eth_zero_addr(cmd->bssid_hint); | ||
2151 | |||
2152 | if (sme->prev_bssid) | ||
2153 | ether_addr_copy(cmd->prev_bssid, sme->prev_bssid); | ||
2059 | else | 2154 | else |
2060 | cmd->channel = 0; | 2155 | eth_zero_addr(cmd->prev_bssid); |
2061 | 2156 | ||
2062 | if ((sme->bg_scan_period > 0) && | 2157 | if ((sme->bg_scan_period > 0) && |
2063 | (sme->bg_scan_period <= QTNF_MAX_BG_SCAN_PERIOD)) | 2158 | (sme->bg_scan_period <= QTNF_MAX_BG_SCAN_PERIOD)) |
@@ -2075,11 +2170,18 @@ int qtnf_cmd_send_connect(struct qtnf_vif *vif, | |||
2075 | connect_flags |= QLINK_STA_CONNECT_USE_RRM; | 2170 | connect_flags |= QLINK_STA_CONNECT_USE_RRM; |
2076 | 2171 | ||
2077 | cmd->flags = cpu_to_le32(connect_flags); | 2172 | cmd->flags = cpu_to_le32(connect_flags); |
2173 | memcpy(&cmd->ht_capa, &sme->ht_capa, sizeof(cmd->ht_capa)); | ||
2174 | memcpy(&cmd->ht_capa_mask, &sme->ht_capa_mask, | ||
2175 | sizeof(cmd->ht_capa_mask)); | ||
2176 | memcpy(&cmd->vht_capa, &sme->vht_capa, sizeof(cmd->vht_capa)); | ||
2177 | memcpy(&cmd->vht_capa_mask, &sme->vht_capa_mask, | ||
2178 | sizeof(cmd->vht_capa_mask)); | ||
2179 | cmd->pbss = sme->pbss; | ||
2078 | 2180 | ||
2079 | aen = &cmd->aen; | 2181 | aen = &cmd->aen; |
2080 | aen->auth_type = sme->auth_type; | 2182 | aen->auth_type = sme->auth_type; |
2081 | aen->privacy = !!sme->privacy; | 2183 | aen->privacy = !!sme->privacy; |
2082 | aen->mfp = sme->mfp; | 2184 | cmd->mfp = sme->mfp; |
2083 | aen->wpa_versions = cpu_to_le32(sme->crypto.wpa_versions); | 2185 | aen->wpa_versions = cpu_to_le32(sme->crypto.wpa_versions); |
2084 | aen->cipher_group = cpu_to_le32(sme->crypto.cipher_group); | 2186 | aen->cipher_group = cpu_to_le32(sme->crypto.cipher_group); |
2085 | aen->n_ciphers_pairwise = cpu_to_le32(sme->crypto.n_ciphers_pairwise); | 2187 | aen->n_ciphers_pairwise = cpu_to_le32(sme->crypto.n_ciphers_pairwise); |
@@ -2103,9 +2205,11 @@ int qtnf_cmd_send_connect(struct qtnf_vif *vif, | |||
2103 | sme->ssid_len); | 2205 | sme->ssid_len); |
2104 | 2206 | ||
2105 | if (sme->ie_len != 0) | 2207 | if (sme->ie_len != 0) |
2106 | qtnf_cmd_skb_put_tlv_arr(cmd_skb, QTN_TLV_ID_IE_SET, | 2208 | qtnf_cmd_tlv_ie_set_add(cmd_skb, QLINK_IE_SET_ASSOC_REQ, |
2107 | sme->ie, | 2209 | sme->ie, sme->ie_len); |
2108 | sme->ie_len); | 2210 | |
2211 | if (sme->channel) | ||
2212 | qtnf_cmd_channel_tlv_add(cmd_skb, sme->channel); | ||
2109 | 2213 | ||
2110 | qtnf_bus_lock(vif->mac->bus); | 2214 | qtnf_bus_lock(vif->mac->bus); |
2111 | 2215 | ||