1 /* 2 * Copyright (c) 2004-2011 Atheros Communications Inc. 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 <linux/ip.h> 18 #include "core.h" 19 #include "debug.h" 20 21 static int ath6kl_wmi_sync_point(struct wmi *wmi); 22 23 static const s32 wmi_rate_tbl[][2] = { 24 /* {W/O SGI, with SGI} */ 25 {1000, 1000}, 26 {2000, 2000}, 27 {5500, 5500}, 28 {11000, 11000}, 29 {6000, 6000}, 30 {9000, 9000}, 31 {12000, 12000}, 32 {18000, 18000}, 33 {24000, 24000}, 34 {36000, 36000}, 35 {48000, 48000}, 36 {54000, 54000}, 37 {6500, 7200}, 38 {13000, 14400}, 39 {19500, 21700}, 40 {26000, 28900}, 41 {39000, 43300}, 42 {52000, 57800}, 43 {58500, 65000}, 44 {65000, 72200}, 45 {13500, 15000}, 46 {27000, 30000}, 47 {40500, 45000}, 48 {54000, 60000}, 49 {81000, 90000}, 50 {108000, 120000}, 51 {121500, 135000}, 52 {135000, 150000}, 53 {0, 0} 54 }; 55 56 /* 802.1d to AC mapping. Refer pg 57 of WMM-test-plan-v1.2 */ 57 static const u8 up_to_ac[] = { 58 WMM_AC_BE, 59 WMM_AC_BK, 60 WMM_AC_BK, 61 WMM_AC_BE, 62 WMM_AC_VI, 63 WMM_AC_VI, 64 WMM_AC_VO, 65 WMM_AC_VO, 66 }; 67 68 void ath6kl_wmi_set_control_ep(struct wmi *wmi, enum htc_endpoint_id ep_id) 69 { 70 if (WARN_ON(ep_id == ENDPOINT_UNUSED || ep_id >= ENDPOINT_MAX)) 71 return; 72 73 wmi->ep_id = ep_id; 74 } 75 76 enum htc_endpoint_id ath6kl_wmi_get_control_ep(struct wmi *wmi) 77 { 78 return wmi->ep_id; 79 } 80 81 /* Performs DIX to 802.3 encapsulation for transmit packets. 82 * Assumes the entire DIX header is contigous and that there is 83 * enough room in the buffer for a 802.3 mac header and LLC+SNAP headers. 84 */ 85 int ath6kl_wmi_dix_2_dot3(struct wmi *wmi, struct sk_buff *skb) 86 { 87 struct ath6kl_llc_snap_hdr *llc_hdr; 88 struct ethhdr *eth_hdr; 89 size_t new_len; 90 __be16 type; 91 u8 *datap; 92 u16 size; 93 94 if (WARN_ON(skb == NULL)) 95 return -EINVAL; 96 97 size = sizeof(struct ath6kl_llc_snap_hdr) + sizeof(struct wmi_data_hdr); 98 if (skb_headroom(skb) < size) 99 return -ENOMEM; 100 101 eth_hdr = (struct ethhdr *) skb->data; 102 type = eth_hdr->h_proto; 103 104 if (!is_ethertype(be16_to_cpu(type))) { 105 ath6kl_dbg(ATH6KL_DBG_WMI, 106 "%s: pkt is already in 802.3 format\n", __func__); 107 return 0; 108 } 109 110 new_len = skb->len - sizeof(*eth_hdr) + sizeof(*llc_hdr); 111 112 skb_push(skb, sizeof(struct ath6kl_llc_snap_hdr)); 113 datap = skb->data; 114 115 eth_hdr->h_proto = cpu_to_be16(new_len); 116 117 memcpy(datap, eth_hdr, sizeof(*eth_hdr)); 118 119 llc_hdr = (struct ath6kl_llc_snap_hdr *)(datap + sizeof(*eth_hdr)); 120 llc_hdr->dsap = 0xAA; 121 llc_hdr->ssap = 0xAA; 122 llc_hdr->cntl = 0x03; 123 llc_hdr->org_code[0] = 0x0; 124 llc_hdr->org_code[1] = 0x0; 125 llc_hdr->org_code[2] = 0x0; 126 llc_hdr->eth_type = type; 127 128 return 0; 129 } 130 131 static int ath6kl_wmi_meta_add(struct wmi *wmi, struct sk_buff *skb, 132 u8 *version, void *tx_meta_info) 133 { 134 struct wmi_tx_meta_v1 *v1; 135 struct wmi_tx_meta_v2 *v2; 136 137 if (WARN_ON(skb == NULL || version == NULL)) 138 return -EINVAL; 139 140 switch (*version) { 141 case WMI_META_VERSION_1: 142 skb_push(skb, WMI_MAX_TX_META_SZ); 143 v1 = (struct wmi_tx_meta_v1 *) skb->data; 144 v1->pkt_id = 0; 145 v1->rate_plcy_id = 0; 146 *version = WMI_META_VERSION_1; 147 break; 148 case WMI_META_VERSION_2: 149 skb_push(skb, WMI_MAX_TX_META_SZ); 150 v2 = (struct wmi_tx_meta_v2 *) skb->data; 151 memcpy(v2, (struct wmi_tx_meta_v2 *) tx_meta_info, 152 sizeof(struct wmi_tx_meta_v2)); 153 break; 154 } 155 156 return 0; 157 } 158 159 int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb, 160 u8 msg_type, bool more_data, 161 enum wmi_data_hdr_data_type data_type, 162 u8 meta_ver, void *tx_meta_info) 163 { 164 struct wmi_data_hdr *data_hdr; 165 int ret; 166 167 if (WARN_ON(skb == NULL)) 168 return -EINVAL; 169 170 ret = ath6kl_wmi_meta_add(wmi, skb, &meta_ver, tx_meta_info); 171 if (ret) 172 return ret; 173 174 skb_push(skb, sizeof(struct wmi_data_hdr)); 175 176 data_hdr = (struct wmi_data_hdr *)skb->data; 177 memset(data_hdr, 0, sizeof(struct wmi_data_hdr)); 178 179 data_hdr->info = msg_type << WMI_DATA_HDR_MSG_TYPE_SHIFT; 180 data_hdr->info |= data_type << WMI_DATA_HDR_DATA_TYPE_SHIFT; 181 182 if (more_data) 183 data_hdr->info |= 184 WMI_DATA_HDR_MORE_MASK << WMI_DATA_HDR_MORE_SHIFT; 185 186 data_hdr->info2 = cpu_to_le16(meta_ver << WMI_DATA_HDR_META_SHIFT); 187 data_hdr->info3 = 0; 188 189 return 0; 190 } 191 192 static u8 ath6kl_wmi_determine_user_priority(u8 *pkt, u32 layer2_pri) 193 { 194 struct iphdr *ip_hdr = (struct iphdr *) pkt; 195 u8 ip_pri; 196 197 /* 198 * Determine IPTOS priority 199 * 200 * IP-TOS - 8bits 201 * : DSCP(6-bits) ECN(2-bits) 202 * : DSCP - P2 P1 P0 X X X 203 * where (P2 P1 P0) form 802.1D 204 */ 205 ip_pri = ip_hdr->tos >> 5; 206 ip_pri &= 0x7; 207 208 if ((layer2_pri & 0x7) > ip_pri) 209 return (u8) layer2_pri & 0x7; 210 else 211 return ip_pri; 212 } 213 214 int ath6kl_wmi_implicit_create_pstream(struct wmi *wmi, struct sk_buff *skb, 215 u32 layer2_priority, bool wmm_enabled, 216 u8 *ac) 217 { 218 struct wmi_data_hdr *data_hdr; 219 struct ath6kl_llc_snap_hdr *llc_hdr; 220 struct wmi_create_pstream_cmd cmd; 221 u32 meta_size, hdr_size; 222 u16 ip_type = IP_ETHERTYPE; 223 u8 stream_exist, usr_pri; 224 u8 traffic_class = WMM_AC_BE; 225 u8 *datap; 226 227 if (WARN_ON(skb == NULL)) 228 return -EINVAL; 229 230 datap = skb->data; 231 data_hdr = (struct wmi_data_hdr *) datap; 232 233 meta_size = ((le16_to_cpu(data_hdr->info2) >> WMI_DATA_HDR_META_SHIFT) & 234 WMI_DATA_HDR_META_MASK) ? WMI_MAX_TX_META_SZ : 0; 235 236 if (!wmm_enabled) { 237 /* If WMM is disabled all traffic goes as BE traffic */ 238 usr_pri = 0; 239 } else { 240 hdr_size = sizeof(struct ethhdr); 241 242 llc_hdr = (struct ath6kl_llc_snap_hdr *)(datap + 243 sizeof(struct 244 wmi_data_hdr) + 245 meta_size + hdr_size); 246 247 if (llc_hdr->eth_type == htons(ip_type)) { 248 /* 249 * Extract the endpoint info from the TOS field 250 * in the IP header. 251 */ 252 usr_pri = 253 ath6kl_wmi_determine_user_priority(((u8 *) llc_hdr) + 254 sizeof(struct ath6kl_llc_snap_hdr), 255 layer2_priority); 256 } else 257 usr_pri = layer2_priority & 0x7; 258 } 259 260 /* workaround for WMM S5 */ 261 if ((wmi->traffic_class == WMM_AC_VI) && 262 ((usr_pri == 5) || (usr_pri == 4))) 263 usr_pri = 1; 264 265 /* Convert user priority to traffic class */ 266 traffic_class = up_to_ac[usr_pri & 0x7]; 267 268 wmi_data_hdr_set_up(data_hdr, usr_pri); 269 270 spin_lock_bh(&wmi->lock); 271 stream_exist = wmi->fat_pipe_exist; 272 spin_unlock_bh(&wmi->lock); 273 274 if (!(stream_exist & (1 << traffic_class))) { 275 memset(&cmd, 0, sizeof(cmd)); 276 cmd.traffic_class = traffic_class; 277 cmd.user_pri = usr_pri; 278 cmd.inactivity_int = 279 cpu_to_le32(WMI_IMPLICIT_PSTREAM_INACTIVITY_INT); 280 /* Implicit streams are created with TSID 0xFF */ 281 cmd.tsid = WMI_IMPLICIT_PSTREAM; 282 ath6kl_wmi_create_pstream_cmd(wmi, &cmd); 283 } 284 285 *ac = traffic_class; 286 287 return 0; 288 } 289 290 int ath6kl_wmi_dot11_hdr_remove(struct wmi *wmi, struct sk_buff *skb) 291 { 292 struct ieee80211_hdr_3addr *pwh, wh; 293 struct ath6kl_llc_snap_hdr *llc_hdr; 294 struct ethhdr eth_hdr; 295 u32 hdr_size; 296 u8 *datap; 297 __le16 sub_type; 298 299 if (WARN_ON(skb == NULL)) 300 return -EINVAL; 301 302 datap = skb->data; 303 pwh = (struct ieee80211_hdr_3addr *) datap; 304 305 sub_type = pwh->frame_control & cpu_to_le16(IEEE80211_FCTL_STYPE); 306 307 memcpy((u8 *) &wh, datap, sizeof(struct ieee80211_hdr_3addr)); 308 309 /* Strip off the 802.11 header */ 310 if (sub_type == cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) { 311 hdr_size = roundup(sizeof(struct ieee80211_qos_hdr), 312 sizeof(u32)); 313 skb_pull(skb, hdr_size); 314 } else if (sub_type == cpu_to_le16(IEEE80211_STYPE_DATA)) 315 skb_pull(skb, sizeof(struct ieee80211_hdr_3addr)); 316 317 datap = skb->data; 318 llc_hdr = (struct ath6kl_llc_snap_hdr *)(datap); 319 320 memset(ð_hdr, 0, sizeof(eth_hdr)); 321 eth_hdr.h_proto = llc_hdr->eth_type; 322 323 switch ((le16_to_cpu(wh.frame_control)) & 324 (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) { 325 case 0: 326 memcpy(eth_hdr.h_dest, wh.addr1, ETH_ALEN); 327 memcpy(eth_hdr.h_source, wh.addr2, ETH_ALEN); 328 break; 329 case IEEE80211_FCTL_TODS: 330 memcpy(eth_hdr.h_dest, wh.addr3, ETH_ALEN); 331 memcpy(eth_hdr.h_source, wh.addr2, ETH_ALEN); 332 break; 333 case IEEE80211_FCTL_FROMDS: 334 memcpy(eth_hdr.h_dest, wh.addr1, ETH_ALEN); 335 memcpy(eth_hdr.h_source, wh.addr3, ETH_ALEN); 336 break; 337 case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS: 338 break; 339 } 340 341 skb_pull(skb, sizeof(struct ath6kl_llc_snap_hdr)); 342 skb_push(skb, sizeof(eth_hdr)); 343 344 datap = skb->data; 345 346 memcpy(datap, ð_hdr, sizeof(eth_hdr)); 347 348 return 0; 349 } 350 351 /* 352 * Performs 802.3 to DIX encapsulation for received packets. 353 * Assumes the entire 802.3 header is contigous. 354 */ 355 int ath6kl_wmi_dot3_2_dix(struct sk_buff *skb) 356 { 357 struct ath6kl_llc_snap_hdr *llc_hdr; 358 struct ethhdr eth_hdr; 359 u8 *datap; 360 361 if (WARN_ON(skb == NULL)) 362 return -EINVAL; 363 364 datap = skb->data; 365 366 memcpy(ð_hdr, datap, sizeof(eth_hdr)); 367 368 llc_hdr = (struct ath6kl_llc_snap_hdr *) (datap + sizeof(eth_hdr)); 369 eth_hdr.h_proto = llc_hdr->eth_type; 370 371 skb_pull(skb, sizeof(struct ath6kl_llc_snap_hdr)); 372 datap = skb->data; 373 374 memcpy(datap, ð_hdr, sizeof(eth_hdr)); 375 376 return 0; 377 } 378 379 int ath6kl_wmi_data_hdr_remove(struct wmi *wmi, struct sk_buff *skb) 380 { 381 if (WARN_ON(skb == NULL)) 382 return -EINVAL; 383 384 skb_pull(skb, sizeof(struct wmi_data_hdr)); 385 386 return 0; 387 } 388 389 static void ath6kl_wmi_convert_bssinfo_hdr2_to_hdr(struct sk_buff *skb, 390 u8 *datap) 391 { 392 struct wmi_bss_info_hdr2 bih2; 393 struct wmi_bss_info_hdr *bih; 394 395 memcpy(&bih2, datap, sizeof(struct wmi_bss_info_hdr2)); 396 397 skb_push(skb, 4); 398 bih = (struct wmi_bss_info_hdr *) skb->data; 399 400 bih->ch = bih2.ch; 401 bih->frame_type = bih2.frame_type; 402 bih->snr = bih2.snr; 403 bih->rssi = a_cpu_to_sle16(bih2.snr - 95); 404 bih->ie_mask = cpu_to_le32(le16_to_cpu(bih2.ie_mask)); 405 memcpy(bih->bssid, bih2.bssid, ETH_ALEN); 406 } 407 408 static int ath6kl_wmi_tx_complete_event_rx(u8 *datap, int len) 409 { 410 struct tx_complete_msg_v1 *msg_v1; 411 struct wmi_tx_complete_event *evt; 412 int index; 413 u16 size; 414 415 evt = (struct wmi_tx_complete_event *) datap; 416 417 ath6kl_dbg(ATH6KL_DBG_WMI, "comp: %d %d %d\n", 418 evt->num_msg, evt->msg_len, evt->msg_type); 419 420 if (!AR_DBG_LVL_CHECK(ATH6KL_DBG_WMI)) 421 return 0; 422 423 for (index = 0; index < evt->num_msg; index++) { 424 size = sizeof(struct wmi_tx_complete_event) + 425 (index * sizeof(struct tx_complete_msg_v1)); 426 msg_v1 = (struct tx_complete_msg_v1 *)(datap + size); 427 428 ath6kl_dbg(ATH6KL_DBG_WMI, "msg: %d %d %d %d\n", 429 msg_v1->status, msg_v1->pkt_id, 430 msg_v1->rate_idx, msg_v1->ack_failures); 431 } 432 433 return 0; 434 } 435 436 static inline struct sk_buff *ath6kl_wmi_get_new_buf(u32 size) 437 { 438 struct sk_buff *skb; 439 440 skb = ath6kl_buf_alloc(size); 441 if (!skb) 442 return NULL; 443 444 skb_put(skb, size); 445 if (size) 446 memset(skb->data, 0, size); 447 448 return skb; 449 } 450 451 /* Send a "simple" wmi command -- one with no arguments */ 452 static int ath6kl_wmi_simple_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id) 453 { 454 struct sk_buff *skb; 455 int ret; 456 457 skb = ath6kl_wmi_get_new_buf(0); 458 if (!skb) 459 return -ENOMEM; 460 461 ret = ath6kl_wmi_cmd_send(wmi, skb, cmd_id, NO_SYNC_WMIFLAG); 462 463 return ret; 464 } 465 466 static int ath6kl_wmi_ready_event_rx(struct wmi *wmi, u8 *datap, int len) 467 { 468 struct wmi_ready_event_2 *ev = (struct wmi_ready_event_2 *) datap; 469 470 if (len < sizeof(struct wmi_ready_event_2)) 471 return -EINVAL; 472 473 wmi->ready = true; 474 ath6kl_ready_event(wmi->parent_dev, ev->mac_addr, 475 le32_to_cpu(ev->sw_version), 476 le32_to_cpu(ev->abi_version)); 477 478 return 0; 479 } 480 481 static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len) 482 { 483 struct wmi_connect_event *ev; 484 u8 *pie, *peie; 485 486 if (len < sizeof(struct wmi_connect_event)) 487 return -EINVAL; 488 489 ev = (struct wmi_connect_event *) datap; 490 491 ath6kl_dbg(ATH6KL_DBG_WMI, "%s: freq %d bssid %pM\n", 492 __func__, ev->ch, ev->bssid); 493 494 /* Start of assoc rsp IEs */ 495 pie = ev->assoc_info + ev->beacon_ie_len + 496 ev->assoc_req_len + (sizeof(u16) * 3); /* capinfo, status, aid */ 497 498 /* End of assoc rsp IEs */ 499 peie = ev->assoc_info + ev->beacon_ie_len + ev->assoc_req_len + 500 ev->assoc_resp_len; 501 502 while (pie < peie) { 503 switch (*pie) { 504 case WLAN_EID_VENDOR_SPECIFIC: 505 if (pie[1] > 3 && pie[2] == 0x00 && pie[3] == 0x50 && 506 pie[4] == 0xf2 && pie[5] == WMM_OUI_TYPE) { 507 /* WMM OUT (00:50:F2) */ 508 if (pie[1] > 5 509 && pie[6] == WMM_PARAM_OUI_SUBTYPE) 510 wmi->is_wmm_enabled = true; 511 } 512 break; 513 } 514 515 if (wmi->is_wmm_enabled) 516 break; 517 518 pie += pie[1] + 2; 519 } 520 521 ath6kl_connect_event(wmi->parent_dev, le16_to_cpu(ev->ch), ev->bssid, 522 le16_to_cpu(ev->listen_intvl), 523 le16_to_cpu(ev->beacon_intvl), 524 le32_to_cpu(ev->nw_type), 525 ev->beacon_ie_len, ev->assoc_req_len, 526 ev->assoc_resp_len, ev->assoc_info); 527 528 return 0; 529 } 530 531 static int ath6kl_wmi_disconnect_event_rx(struct wmi *wmi, u8 *datap, int len) 532 { 533 struct wmi_disconnect_event *ev; 534 wmi->traffic_class = 100; 535 536 if (len < sizeof(struct wmi_disconnect_event)) 537 return -EINVAL; 538 539 ev = (struct wmi_disconnect_event *) datap; 540 541 wmi->is_wmm_enabled = false; 542 wmi->pair_crypto_type = NONE_CRYPT; 543 wmi->grp_crypto_type = NONE_CRYPT; 544 545 ath6kl_disconnect_event(wmi->parent_dev, ev->disconn_reason, 546 ev->bssid, ev->assoc_resp_len, ev->assoc_info, 547 le16_to_cpu(ev->proto_reason_status)); 548 549 return 0; 550 } 551 552 static int ath6kl_wmi_peer_node_event_rx(struct wmi *wmi, u8 *datap, int len) 553 { 554 struct wmi_peer_node_event *ev; 555 556 if (len < sizeof(struct wmi_peer_node_event)) 557 return -EINVAL; 558 559 ev = (struct wmi_peer_node_event *) datap; 560 561 if (ev->event_code == PEER_NODE_JOIN_EVENT) 562 ath6kl_dbg(ATH6KL_DBG_WMI, "joined node with mac addr: %pM\n", 563 ev->peer_mac_addr); 564 else if (ev->event_code == PEER_NODE_LEAVE_EVENT) 565 ath6kl_dbg(ATH6KL_DBG_WMI, "left node with mac addr: %pM\n", 566 ev->peer_mac_addr); 567 568 return 0; 569 } 570 571 static int ath6kl_wmi_tkip_micerr_event_rx(struct wmi *wmi, u8 *datap, int len) 572 { 573 struct wmi_tkip_micerr_event *ev; 574 575 if (len < sizeof(struct wmi_tkip_micerr_event)) 576 return -EINVAL; 577 578 ev = (struct wmi_tkip_micerr_event *) datap; 579 580 ath6kl_tkip_micerr_event(wmi->parent_dev, ev->key_id, ev->is_mcast); 581 582 return 0; 583 } 584 585 static int ath6kl_wlan_parse_beacon(u8 *buf, int frame_len, 586 struct ath6kl_common_ie *cie) 587 { 588 u8 *frm, *efrm; 589 u8 elemid_ssid = false; 590 591 frm = buf; 592 efrm = (u8 *) (frm + frame_len); 593 594 /* 595 * beacon/probe response frame format 596 * [8] time stamp 597 * [2] beacon interval 598 * [2] capability information 599 * [tlv] ssid 600 * [tlv] supported rates 601 * [tlv] country information 602 * [tlv] parameter set (FH/DS) 603 * [tlv] erp information 604 * [tlv] extended supported rates 605 * [tlv] WMM 606 * [tlv] WPA or RSN 607 * [tlv] Atheros Advanced Capabilities 608 */ 609 if ((efrm - frm) < 12) 610 return -EINVAL; 611 612 memset(cie, 0, sizeof(*cie)); 613 614 cie->ie_tstamp = frm; 615 frm += 8; 616 cie->ie_beaconInt = *(u16 *) frm; 617 frm += 2; 618 cie->ie_capInfo = *(u16 *) frm; 619 frm += 2; 620 cie->ie_chan = 0; 621 622 while (frm < efrm) { 623 switch (*frm) { 624 case WLAN_EID_SSID: 625 if (!elemid_ssid) { 626 cie->ie_ssid = frm; 627 elemid_ssid = true; 628 } 629 break; 630 case WLAN_EID_SUPP_RATES: 631 cie->ie_rates = frm; 632 break; 633 case WLAN_EID_COUNTRY: 634 cie->ie_country = frm; 635 break; 636 case WLAN_EID_FH_PARAMS: 637 break; 638 case WLAN_EID_DS_PARAMS: 639 cie->ie_chan = frm[2]; 640 break; 641 case WLAN_EID_TIM: 642 cie->ie_tim = frm; 643 break; 644 case WLAN_EID_IBSS_PARAMS: 645 break; 646 case WLAN_EID_EXT_SUPP_RATES: 647 cie->ie_xrates = frm; 648 break; 649 case WLAN_EID_ERP_INFO: 650 if (frm[1] != 1) 651 return -EINVAL; 652 653 cie->ie_erp = frm[2]; 654 break; 655 case WLAN_EID_RSN: 656 cie->ie_rsn = frm; 657 break; 658 case WLAN_EID_HT_CAPABILITY: 659 cie->ie_htcap = frm; 660 break; 661 case WLAN_EID_HT_INFORMATION: 662 cie->ie_htop = frm; 663 break; 664 case WLAN_EID_VENDOR_SPECIFIC: 665 if (frm[1] > 3 && frm[2] == 0x00 && frm[3] == 0x50 && 666 frm[4] == 0xf2) { 667 /* OUT Type (00:50:F2) */ 668 669 if (frm[5] == WPA_OUI_TYPE) { 670 /* WPA OUT */ 671 cie->ie_wpa = frm; 672 } else if (frm[5] == WMM_OUI_TYPE) { 673 /* WMM OUT */ 674 cie->ie_wmm = frm; 675 } else if (frm[5] == WSC_OUT_TYPE) { 676 /* WSC OUT */ 677 cie->ie_wsc = frm; 678 } 679 680 } else if (frm[1] > 3 && frm[2] == 0x00 681 && frm[3] == 0x03 && frm[4] == 0x7f 682 && frm[5] == ATH_OUI_TYPE) { 683 /* Atheros OUI (00:03:7f) */ 684 cie->ie_ath = frm; 685 } 686 break; 687 default: 688 break; 689 } 690 frm += frm[1] + 2; 691 } 692 693 if ((cie->ie_rates == NULL) 694 || (cie->ie_rates[1] > ATH6KL_RATE_MAXSIZE)) 695 return -EINVAL; 696 697 if ((cie->ie_ssid == NULL) 698 || (cie->ie_ssid[1] > IEEE80211_MAX_SSID_LEN)) 699 return -EINVAL; 700 701 return 0; 702 } 703 704 static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len) 705 { 706 struct bss *bss = NULL; 707 struct wmi_bss_info_hdr *bih; 708 u8 cached_ssid_len = 0; 709 u8 cached_ssid[IEEE80211_MAX_SSID_LEN] = { 0 }; 710 u8 beacon_ssid_len = 0; 711 u8 *buf, *ie_ssid; 712 u8 *ni_buf; 713 int buf_len; 714 715 int ret; 716 717 if (len <= sizeof(struct wmi_bss_info_hdr)) 718 return -EINVAL; 719 720 bih = (struct wmi_bss_info_hdr *) datap; 721 bss = wlan_find_node(&wmi->parent_dev->scan_table, bih->bssid); 722 723 if (a_sle16_to_cpu(bih->rssi) > 0) { 724 if (bss == NULL) 725 return 0; 726 else 727 bih->rssi = a_cpu_to_sle16(bss->ni_rssi); 728 } 729 730 buf = datap + sizeof(struct wmi_bss_info_hdr); 731 len -= sizeof(struct wmi_bss_info_hdr); 732 733 ath6kl_dbg(ATH6KL_DBG_WMI, 734 "bss info evt - ch %u, rssi %02x, bssid \"%pM\"\n", 735 bih->ch, a_sle16_to_cpu(bih->rssi), bih->bssid); 736 737 if (bss != NULL) { 738 /* 739 * Free up the node. We are about to allocate a new node. 740 * In case of hidden AP, beacon will not have ssid, 741 * but a directed probe response will have it, 742 * so cache the probe-resp-ssid if already present. 743 */ 744 if (wmi->is_probe_ssid && (bih->frame_type == BEACON_FTYPE)) { 745 ie_ssid = bss->ni_cie.ie_ssid; 746 if (ie_ssid && (ie_ssid[1] <= IEEE80211_MAX_SSID_LEN) && 747 (ie_ssid[2] != 0)) { 748 cached_ssid_len = ie_ssid[1]; 749 memcpy(cached_ssid, ie_ssid + 2, 750 cached_ssid_len); 751 } 752 } 753 754 /* 755 * Use the current average rssi of associated AP base on 756 * assumption 757 * 1. Most os with GUI will update RSSI by 758 * ath6kl_wmi_get_stats_cmd() periodically. 759 * 2. ath6kl_wmi_get_stats_cmd(..) will be called when calling 760 * ath6kl_wmi_startscan_cmd(...) 761 * The average value of RSSI give end-user better feeling for 762 * instance value of scan result. It also sync up RSSI info 763 * in GUI between scan result and RSSI signal icon. 764 */ 765 if (memcmp(wmi->parent_dev->bssid, bih->bssid, ETH_ALEN) == 0) { 766 bih->rssi = a_cpu_to_sle16(bss->ni_rssi); 767 bih->snr = bss->ni_snr; 768 } 769 770 wlan_node_reclaim(&wmi->parent_dev->scan_table, bss); 771 } 772 773 /* 774 * beacon/probe response frame format 775 * [8] time stamp 776 * [2] beacon interval 777 * [2] capability information 778 * [tlv] ssid 779 */ 780 beacon_ssid_len = buf[SSID_IE_LEN_INDEX]; 781 782 /* 783 * If ssid is cached for this hidden AP, then change 784 * buffer len accordingly. 785 */ 786 if (wmi->is_probe_ssid && (bih->frame_type == BEACON_FTYPE) && 787 (cached_ssid_len != 0) && 788 (beacon_ssid_len == 0 || (cached_ssid_len > beacon_ssid_len && 789 buf[SSID_IE_LEN_INDEX + 1] == 0))) { 790 791 len += (cached_ssid_len - beacon_ssid_len); 792 } 793 794 bss = wlan_node_alloc(len); 795 if (!bss) 796 return -ENOMEM; 797 798 bss->ni_snr = bih->snr; 799 bss->ni_rssi = a_sle16_to_cpu(bih->rssi); 800 801 if (WARN_ON(!bss->ni_buf)) 802 return -EINVAL; 803 804 /* 805 * In case of hidden AP, beacon will not have ssid, 806 * but a directed probe response will have it, 807 * so place the cached-ssid(probe-resp) in the bss info. 808 */ 809 if (wmi->is_probe_ssid && (bih->frame_type == BEACON_FTYPE) && 810 (cached_ssid_len != 0) && 811 (beacon_ssid_len == 0 || (beacon_ssid_len && 812 buf[SSID_IE_LEN_INDEX + 1] == 0))) { 813 ni_buf = bss->ni_buf; 814 buf_len = len; 815 816 /* 817 * Copy the first 14 bytes: 818 * time-stamp(8), beacon-interval(2), 819 * cap-info(2), ssid-id(1), ssid-len(1). 820 */ 821 memcpy(ni_buf, buf, SSID_IE_LEN_INDEX + 1); 822 823 ni_buf[SSID_IE_LEN_INDEX] = cached_ssid_len; 824 ni_buf += (SSID_IE_LEN_INDEX + 1); 825 826 buf += (SSID_IE_LEN_INDEX + 1); 827 buf_len -= (SSID_IE_LEN_INDEX + 1); 828 829 memcpy(ni_buf, cached_ssid, cached_ssid_len); 830 ni_buf += cached_ssid_len; 831 832 buf += beacon_ssid_len; 833 buf_len -= beacon_ssid_len; 834 835 if (cached_ssid_len > beacon_ssid_len) 836 buf_len -= (cached_ssid_len - beacon_ssid_len); 837 838 memcpy(ni_buf, buf, buf_len); 839 } else 840 memcpy(bss->ni_buf, buf, len); 841 842 bss->ni_framelen = len; 843 844 ret = ath6kl_wlan_parse_beacon(bss->ni_buf, len, &bss->ni_cie); 845 if (ret) { 846 wlan_node_free(bss); 847 return -EINVAL; 848 } 849 850 /* 851 * Update the frequency in ie_chan, overwriting of channel number 852 * which is done in ath6kl_wlan_parse_beacon 853 */ 854 bss->ni_cie.ie_chan = le16_to_cpu(bih->ch); 855 wlan_setup_node(&wmi->parent_dev->scan_table, bss, bih->bssid); 856 857 return 0; 858 } 859 860 static int ath6kl_wmi_opt_frame_event_rx(struct wmi *wmi, u8 *datap, int len) 861 { 862 struct bss *bss; 863 struct wmi_opt_rx_info_hdr *bih; 864 u8 *buf; 865 866 if (len <= sizeof(struct wmi_opt_rx_info_hdr)) 867 return -EINVAL; 868 869 bih = (struct wmi_opt_rx_info_hdr *) datap; 870 buf = datap + sizeof(struct wmi_opt_rx_info_hdr); 871 len -= sizeof(struct wmi_opt_rx_info_hdr); 872 873 ath6kl_dbg(ATH6KL_DBG_WMI, "opt frame event %2.2x:%2.2x\n", 874 bih->bssid[4], bih->bssid[5]); 875 876 bss = wlan_find_node(&wmi->parent_dev->scan_table, bih->bssid); 877 if (bss != NULL) { 878 /* Free up the node. We are about to allocate a new node. */ 879 wlan_node_reclaim(&wmi->parent_dev->scan_table, bss); 880 } 881 882 bss = wlan_node_alloc(len); 883 if (!bss) 884 return -ENOMEM; 885 886 bss->ni_snr = bih->snr; 887 bss->ni_cie.ie_chan = le16_to_cpu(bih->ch); 888 889 if (WARN_ON(!bss->ni_buf)) 890 return -EINVAL; 891 892 memcpy(bss->ni_buf, buf, len); 893 wlan_setup_node(&wmi->parent_dev->scan_table, bss, bih->bssid); 894 895 return 0; 896 } 897 898 /* Inactivity timeout of a fatpipe(pstream) at the target */ 899 static int ath6kl_wmi_pstream_timeout_event_rx(struct wmi *wmi, u8 *datap, 900 int len) 901 { 902 struct wmi_pstream_timeout_event *ev; 903 904 if (len < sizeof(struct wmi_pstream_timeout_event)) 905 return -EINVAL; 906 907 ev = (struct wmi_pstream_timeout_event *) datap; 908 909 /* 910 * When the pstream (fat pipe == AC) timesout, it means there were 911 * no thinStreams within this pstream & it got implicitly created 912 * due to data flow on this AC. We start the inactivity timer only 913 * for implicitly created pstream. Just reset the host state. 914 */ 915 spin_lock_bh(&wmi->lock); 916 wmi->stream_exist_for_ac[ev->traffic_class] = 0; 917 wmi->fat_pipe_exist &= ~(1 << ev->traffic_class); 918 spin_unlock_bh(&wmi->lock); 919 920 /* Indicate inactivity to driver layer for this fatpipe (pstream) */ 921 ath6kl_indicate_tx_activity(wmi->parent_dev, ev->traffic_class, false); 922 923 return 0; 924 } 925 926 static int ath6kl_wmi_bitrate_reply_rx(struct wmi *wmi, u8 *datap, int len) 927 { 928 struct wmi_bit_rate_reply *reply; 929 s32 rate; 930 u32 sgi, index; 931 932 if (len < sizeof(struct wmi_bit_rate_reply)) 933 return -EINVAL; 934 935 reply = (struct wmi_bit_rate_reply *) datap; 936 937 ath6kl_dbg(ATH6KL_DBG_WMI, "rateindex %d\n", reply->rate_index); 938 939 if (reply->rate_index == (s8) RATE_AUTO) { 940 rate = RATE_AUTO; 941 } else { 942 index = reply->rate_index & 0x7f; 943 sgi = (reply->rate_index & 0x80) ? 1 : 0; 944 rate = wmi_rate_tbl[index][sgi]; 945 } 946 947 ath6kl_wakeup_event(wmi->parent_dev); 948 949 return 0; 950 } 951 952 static int ath6kl_wmi_ratemask_reply_rx(struct wmi *wmi, u8 *datap, int len) 953 { 954 if (len < sizeof(struct wmi_fix_rates_reply)) 955 return -EINVAL; 956 957 ath6kl_wakeup_event(wmi->parent_dev); 958 959 return 0; 960 } 961 962 static int ath6kl_wmi_ch_list_reply_rx(struct wmi *wmi, u8 *datap, int len) 963 { 964 if (len < sizeof(struct wmi_channel_list_reply)) 965 return -EINVAL; 966 967 ath6kl_wakeup_event(wmi->parent_dev); 968 969 return 0; 970 } 971 972 static int ath6kl_wmi_tx_pwr_reply_rx(struct wmi *wmi, u8 *datap, int len) 973 { 974 struct wmi_tx_pwr_reply *reply; 975 976 if (len < sizeof(struct wmi_tx_pwr_reply)) 977 return -EINVAL; 978 979 reply = (struct wmi_tx_pwr_reply *) datap; 980 ath6kl_txpwr_rx_evt(wmi->parent_dev, reply->dbM); 981 982 return 0; 983 } 984 985 static int ath6kl_wmi_keepalive_reply_rx(struct wmi *wmi, u8 *datap, int len) 986 { 987 if (len < sizeof(struct wmi_get_keepalive_cmd)) 988 return -EINVAL; 989 990 ath6kl_wakeup_event(wmi->parent_dev); 991 992 return 0; 993 } 994 995 static int ath6kl_wmi_scan_complete_rx(struct wmi *wmi, u8 *datap, int len) 996 { 997 struct wmi_scan_complete_event *ev; 998 999 ev = (struct wmi_scan_complete_event *) datap; 1000 1001 if (a_sle32_to_cpu(ev->status) == 0) 1002 wlan_refresh_inactive_nodes(wmi->parent_dev); 1003 1004 ath6kl_scan_complete_evt(wmi->parent_dev, a_sle32_to_cpu(ev->status)); 1005 wmi->is_probe_ssid = false; 1006 1007 return 0; 1008 } 1009 1010 /* 1011 * Target is reporting a programming error. This is for 1012 * developer aid only. Target only checks a few common violations 1013 * and it is responsibility of host to do all error checking. 1014 * Behavior of target after wmi error event is undefined. 1015 * A reset is recommended. 1016 */ 1017 static int ath6kl_wmi_error_event_rx(struct wmi *wmi, u8 *datap, int len) 1018 { 1019 const char *type = "unknown error"; 1020 struct wmi_cmd_error_event *ev; 1021 ev = (struct wmi_cmd_error_event *) datap; 1022 1023 switch (ev->err_code) { 1024 case INVALID_PARAM: 1025 type = "invalid parameter"; 1026 break; 1027 case ILLEGAL_STATE: 1028 type = "invalid state"; 1029 break; 1030 case INTERNAL_ERROR: 1031 type = "internal error"; 1032 break; 1033 } 1034 1035 ath6kl_dbg(ATH6KL_DBG_WMI, "programming error, cmd=%d %s\n", 1036 ev->cmd_id, type); 1037 1038 return 0; 1039 } 1040 1041 static int ath6kl_wmi_stats_event_rx(struct wmi *wmi, u8 *datap, int len) 1042 { 1043 ath6kl_tgt_stats_event(wmi->parent_dev, datap, len); 1044 1045 return 0; 1046 } 1047 1048 static u8 ath6kl_wmi_get_upper_threshold(s16 rssi, 1049 struct sq_threshold_params *sq_thresh, 1050 u32 size) 1051 { 1052 u32 index; 1053 u8 threshold = (u8) sq_thresh->upper_threshold[size - 1]; 1054 1055 /* The list is already in sorted order. Get the next lower value */ 1056 for (index = 0; index < size; index++) { 1057 if (rssi < sq_thresh->upper_threshold[index]) { 1058 threshold = (u8) sq_thresh->upper_threshold[index]; 1059 break; 1060 } 1061 } 1062 1063 return threshold; 1064 } 1065 1066 static u8 ath6kl_wmi_get_lower_threshold(s16 rssi, 1067 struct sq_threshold_params *sq_thresh, 1068 u32 size) 1069 { 1070 u32 index; 1071 u8 threshold = (u8) sq_thresh->lower_threshold[size - 1]; 1072 1073 /* The list is already in sorted order. Get the next lower value */ 1074 for (index = 0; index < size; index++) { 1075 if (rssi > sq_thresh->lower_threshold[index]) { 1076 threshold = (u8) sq_thresh->lower_threshold[index]; 1077 break; 1078 } 1079 } 1080 1081 return threshold; 1082 } 1083 1084 static int ath6kl_wmi_send_rssi_threshold_params(struct wmi *wmi, 1085 struct wmi_rssi_threshold_params_cmd *rssi_cmd) 1086 { 1087 struct sk_buff *skb; 1088 struct wmi_rssi_threshold_params_cmd *cmd; 1089 1090 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 1091 if (!skb) 1092 return -ENOMEM; 1093 1094 cmd = (struct wmi_rssi_threshold_params_cmd *) skb->data; 1095 memcpy(cmd, rssi_cmd, sizeof(struct wmi_rssi_threshold_params_cmd)); 1096 1097 return ath6kl_wmi_cmd_send(wmi, skb, WMI_RSSI_THRESHOLD_PARAMS_CMDID, 1098 NO_SYNC_WMIFLAG); 1099 } 1100 1101 static int ath6kl_wmi_rssi_threshold_event_rx(struct wmi *wmi, u8 *datap, 1102 int len) 1103 { 1104 struct wmi_rssi_threshold_event *reply; 1105 struct wmi_rssi_threshold_params_cmd cmd; 1106 struct sq_threshold_params *sq_thresh; 1107 enum wmi_rssi_threshold_val new_threshold; 1108 u8 upper_rssi_threshold, lower_rssi_threshold; 1109 s16 rssi; 1110 int ret; 1111 1112 if (len < sizeof(struct wmi_rssi_threshold_event)) 1113 return -EINVAL; 1114 1115 reply = (struct wmi_rssi_threshold_event *) datap; 1116 new_threshold = (enum wmi_rssi_threshold_val) reply->range; 1117 rssi = a_sle16_to_cpu(reply->rssi); 1118 1119 sq_thresh = &wmi->sq_threshld[SIGNAL_QUALITY_METRICS_RSSI]; 1120 1121 /* 1122 * Identify the threshold breached and communicate that to the app. 1123 * After that install a new set of thresholds based on the signal 1124 * quality reported by the target 1125 */ 1126 if (new_threshold) { 1127 /* Upper threshold breached */ 1128 if (rssi < sq_thresh->upper_threshold[0]) { 1129 ath6kl_dbg(ATH6KL_DBG_WMI, 1130 "spurious upper rssi threshold event: %d\n", 1131 rssi); 1132 } else if ((rssi < sq_thresh->upper_threshold[1]) && 1133 (rssi >= sq_thresh->upper_threshold[0])) { 1134 new_threshold = WMI_RSSI_THRESHOLD1_ABOVE; 1135 } else if ((rssi < sq_thresh->upper_threshold[2]) && 1136 (rssi >= sq_thresh->upper_threshold[1])) { 1137 new_threshold = WMI_RSSI_THRESHOLD2_ABOVE; 1138 } else if ((rssi < sq_thresh->upper_threshold[3]) && 1139 (rssi >= sq_thresh->upper_threshold[2])) { 1140 new_threshold = WMI_RSSI_THRESHOLD3_ABOVE; 1141 } else if ((rssi < sq_thresh->upper_threshold[4]) && 1142 (rssi >= sq_thresh->upper_threshold[3])) { 1143 new_threshold = WMI_RSSI_THRESHOLD4_ABOVE; 1144 } else if ((rssi < sq_thresh->upper_threshold[5]) && 1145 (rssi >= sq_thresh->upper_threshold[4])) { 1146 new_threshold = WMI_RSSI_THRESHOLD5_ABOVE; 1147 } else if (rssi >= sq_thresh->upper_threshold[5]) { 1148 new_threshold = WMI_RSSI_THRESHOLD6_ABOVE; 1149 } 1150 } else { 1151 /* Lower threshold breached */ 1152 if (rssi > sq_thresh->lower_threshold[0]) { 1153 ath6kl_dbg(ATH6KL_DBG_WMI, 1154 "spurious lower rssi threshold event: %d %d\n", 1155 rssi, sq_thresh->lower_threshold[0]); 1156 } else if ((rssi > sq_thresh->lower_threshold[1]) && 1157 (rssi <= sq_thresh->lower_threshold[0])) { 1158 new_threshold = WMI_RSSI_THRESHOLD6_BELOW; 1159 } else if ((rssi > sq_thresh->lower_threshold[2]) && 1160 (rssi <= sq_thresh->lower_threshold[1])) { 1161 new_threshold = WMI_RSSI_THRESHOLD5_BELOW; 1162 } else if ((rssi > sq_thresh->lower_threshold[3]) && 1163 (rssi <= sq_thresh->lower_threshold[2])) { 1164 new_threshold = WMI_RSSI_THRESHOLD4_BELOW; 1165 } else if ((rssi > sq_thresh->lower_threshold[4]) && 1166 (rssi <= sq_thresh->lower_threshold[3])) { 1167 new_threshold = WMI_RSSI_THRESHOLD3_BELOW; 1168 } else if ((rssi > sq_thresh->lower_threshold[5]) && 1169 (rssi <= sq_thresh->lower_threshold[4])) { 1170 new_threshold = WMI_RSSI_THRESHOLD2_BELOW; 1171 } else if (rssi <= sq_thresh->lower_threshold[5]) { 1172 new_threshold = WMI_RSSI_THRESHOLD1_BELOW; 1173 } 1174 } 1175 1176 /* Calculate and install the next set of thresholds */ 1177 lower_rssi_threshold = ath6kl_wmi_get_lower_threshold(rssi, sq_thresh, 1178 sq_thresh->lower_threshold_valid_count); 1179 upper_rssi_threshold = ath6kl_wmi_get_upper_threshold(rssi, sq_thresh, 1180 sq_thresh->upper_threshold_valid_count); 1181 1182 /* Issue a wmi command to install the thresholds */ 1183 cmd.thresh_above1_val = a_cpu_to_sle16(upper_rssi_threshold); 1184 cmd.thresh_below1_val = a_cpu_to_sle16(lower_rssi_threshold); 1185 cmd.weight = sq_thresh->weight; 1186 cmd.poll_time = cpu_to_le32(sq_thresh->polling_interval); 1187 1188 ret = ath6kl_wmi_send_rssi_threshold_params(wmi, &cmd); 1189 if (ret) { 1190 ath6kl_err("unable to configure rssi thresholds\n"); 1191 return -EIO; 1192 } 1193 1194 return 0; 1195 } 1196 1197 static int ath6kl_wmi_cac_event_rx(struct wmi *wmi, u8 *datap, int len) 1198 { 1199 struct wmi_cac_event *reply; 1200 struct ieee80211_tspec_ie *ts; 1201 u16 active_tsids, tsinfo; 1202 u8 tsid, index; 1203 u8 ts_id; 1204 1205 if (len < sizeof(struct wmi_cac_event)) 1206 return -EINVAL; 1207 1208 reply = (struct wmi_cac_event *) datap; 1209 1210 if ((reply->cac_indication == CAC_INDICATION_ADMISSION_RESP) && 1211 (reply->status_code != IEEE80211_TSPEC_STATUS_ADMISS_ACCEPTED)) { 1212 1213 ts = (struct ieee80211_tspec_ie *) &(reply->tspec_suggestion); 1214 tsinfo = le16_to_cpu(ts->tsinfo); 1215 tsid = (tsinfo >> IEEE80211_WMM_IE_TSPEC_TID_SHIFT) & 1216 IEEE80211_WMM_IE_TSPEC_TID_MASK; 1217 1218 ath6kl_wmi_delete_pstream_cmd(wmi, reply->ac, tsid); 1219 } else if (reply->cac_indication == CAC_INDICATION_NO_RESP) { 1220 /* 1221 * Following assumes that there is only one outstanding 1222 * ADDTS request when this event is received 1223 */ 1224 spin_lock_bh(&wmi->lock); 1225 active_tsids = wmi->stream_exist_for_ac[reply->ac]; 1226 spin_unlock_bh(&wmi->lock); 1227 1228 for (index = 0; index < sizeof(active_tsids) * 8; index++) { 1229 if ((active_tsids >> index) & 1) 1230 break; 1231 } 1232 if (index < (sizeof(active_tsids) * 8)) 1233 ath6kl_wmi_delete_pstream_cmd(wmi, reply->ac, index); 1234 } 1235 1236 /* 1237 * Clear active tsids and Add missing handling 1238 * for delete qos stream from AP 1239 */ 1240 else if (reply->cac_indication == CAC_INDICATION_DELETE) { 1241 1242 ts = (struct ieee80211_tspec_ie *) &(reply->tspec_suggestion); 1243 tsinfo = le16_to_cpu(ts->tsinfo); 1244 ts_id = ((tsinfo >> IEEE80211_WMM_IE_TSPEC_TID_SHIFT) & 1245 IEEE80211_WMM_IE_TSPEC_TID_MASK); 1246 1247 spin_lock_bh(&wmi->lock); 1248 wmi->stream_exist_for_ac[reply->ac] &= ~(1 << ts_id); 1249 active_tsids = wmi->stream_exist_for_ac[reply->ac]; 1250 spin_unlock_bh(&wmi->lock); 1251 1252 /* Indicate stream inactivity to driver layer only if all tsids 1253 * within this AC are deleted. 1254 */ 1255 if (!active_tsids) { 1256 ath6kl_indicate_tx_activity(wmi->parent_dev, reply->ac, 1257 false); 1258 wmi->fat_pipe_exist &= ~(1 << reply->ac); 1259 } 1260 } 1261 1262 return 0; 1263 } 1264 1265 static int ath6kl_wmi_send_snr_threshold_params(struct wmi *wmi, 1266 struct wmi_snr_threshold_params_cmd *snr_cmd) 1267 { 1268 struct sk_buff *skb; 1269 struct wmi_snr_threshold_params_cmd *cmd; 1270 1271 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 1272 if (!skb) 1273 return -ENOMEM; 1274 1275 cmd = (struct wmi_snr_threshold_params_cmd *) skb->data; 1276 memcpy(cmd, snr_cmd, sizeof(struct wmi_snr_threshold_params_cmd)); 1277 1278 return ath6kl_wmi_cmd_send(wmi, skb, WMI_SNR_THRESHOLD_PARAMS_CMDID, 1279 NO_SYNC_WMIFLAG); 1280 } 1281 1282 static int ath6kl_wmi_snr_threshold_event_rx(struct wmi *wmi, u8 *datap, 1283 int len) 1284 { 1285 struct wmi_snr_threshold_event *reply; 1286 struct sq_threshold_params *sq_thresh; 1287 struct wmi_snr_threshold_params_cmd cmd; 1288 enum wmi_snr_threshold_val new_threshold; 1289 u8 upper_snr_threshold, lower_snr_threshold; 1290 s16 snr; 1291 int ret; 1292 1293 if (len < sizeof(struct wmi_snr_threshold_event)) 1294 return -EINVAL; 1295 1296 reply = (struct wmi_snr_threshold_event *) datap; 1297 1298 new_threshold = (enum wmi_snr_threshold_val) reply->range; 1299 snr = reply->snr; 1300 1301 sq_thresh = &wmi->sq_threshld[SIGNAL_QUALITY_METRICS_SNR]; 1302 1303 /* 1304 * Identify the threshold breached and communicate that to the app. 1305 * After that install a new set of thresholds based on the signal 1306 * quality reported by the target. 1307 */ 1308 if (new_threshold) { 1309 /* Upper threshold breached */ 1310 if (snr < sq_thresh->upper_threshold[0]) { 1311 ath6kl_dbg(ATH6KL_DBG_WMI, 1312 "spurious upper snr threshold event: %d\n", 1313 snr); 1314 } else if ((snr < sq_thresh->upper_threshold[1]) && 1315 (snr >= sq_thresh->upper_threshold[0])) { 1316 new_threshold = WMI_SNR_THRESHOLD1_ABOVE; 1317 } else if ((snr < sq_thresh->upper_threshold[2]) && 1318 (snr >= sq_thresh->upper_threshold[1])) { 1319 new_threshold = WMI_SNR_THRESHOLD2_ABOVE; 1320 } else if ((snr < sq_thresh->upper_threshold[3]) && 1321 (snr >= sq_thresh->upper_threshold[2])) { 1322 new_threshold = WMI_SNR_THRESHOLD3_ABOVE; 1323 } else if (snr >= sq_thresh->upper_threshold[3]) { 1324 new_threshold = WMI_SNR_THRESHOLD4_ABOVE; 1325 } 1326 } else { 1327 /* Lower threshold breached */ 1328 if (snr > sq_thresh->lower_threshold[0]) { 1329 ath6kl_dbg(ATH6KL_DBG_WMI, 1330 "spurious lower snr threshold event: %d\n", 1331 sq_thresh->lower_threshold[0]); 1332 } else if ((snr > sq_thresh->lower_threshold[1]) && 1333 (snr <= sq_thresh->lower_threshold[0])) { 1334 new_threshold = WMI_SNR_THRESHOLD4_BELOW; 1335 } else if ((snr > sq_thresh->lower_threshold[2]) && 1336 (snr <= sq_thresh->lower_threshold[1])) { 1337 new_threshold = WMI_SNR_THRESHOLD3_BELOW; 1338 } else if ((snr > sq_thresh->lower_threshold[3]) && 1339 (snr <= sq_thresh->lower_threshold[2])) { 1340 new_threshold = WMI_SNR_THRESHOLD2_BELOW; 1341 } else if (snr <= sq_thresh->lower_threshold[3]) { 1342 new_threshold = WMI_SNR_THRESHOLD1_BELOW; 1343 } 1344 } 1345 1346 /* Calculate and install the next set of thresholds */ 1347 lower_snr_threshold = ath6kl_wmi_get_lower_threshold(snr, sq_thresh, 1348 sq_thresh->lower_threshold_valid_count); 1349 upper_snr_threshold = ath6kl_wmi_get_upper_threshold(snr, sq_thresh, 1350 sq_thresh->upper_threshold_valid_count); 1351 1352 /* Issue a wmi command to install the thresholds */ 1353 cmd.thresh_above1_val = upper_snr_threshold; 1354 cmd.thresh_below1_val = lower_snr_threshold; 1355 cmd.weight = sq_thresh->weight; 1356 cmd.poll_time = cpu_to_le32(sq_thresh->polling_interval); 1357 1358 ath6kl_dbg(ATH6KL_DBG_WMI, 1359 "snr: %d, threshold: %d, lower: %d, upper: %d\n", 1360 snr, new_threshold, 1361 lower_snr_threshold, upper_snr_threshold); 1362 1363 ret = ath6kl_wmi_send_snr_threshold_params(wmi, &cmd); 1364 if (ret) { 1365 ath6kl_err("unable to configure snr threshold\n"); 1366 return -EIO; 1367 } 1368 1369 return 0; 1370 } 1371 1372 static int ath6kl_wmi_aplist_event_rx(struct wmi *wmi, u8 *datap, int len) 1373 { 1374 u16 ap_info_entry_size; 1375 struct wmi_aplist_event *ev = (struct wmi_aplist_event *) datap; 1376 struct wmi_ap_info_v1 *ap_info_v1; 1377 u8 index; 1378 1379 if (len < sizeof(struct wmi_aplist_event) || 1380 ev->ap_list_ver != APLIST_VER1) 1381 return -EINVAL; 1382 1383 ap_info_entry_size = sizeof(struct wmi_ap_info_v1); 1384 ap_info_v1 = (struct wmi_ap_info_v1 *) ev->ap_list; 1385 1386 ath6kl_dbg(ATH6KL_DBG_WMI, 1387 "number of APs in aplist event: %d\n", ev->num_ap); 1388 1389 if (len < (int) (sizeof(struct wmi_aplist_event) + 1390 (ev->num_ap - 1) * ap_info_entry_size)) 1391 return -EINVAL; 1392 1393 /* AP list version 1 contents */ 1394 for (index = 0; index < ev->num_ap; index++) { 1395 ath6kl_dbg(ATH6KL_DBG_WMI, "AP#%d BSSID %pM Channel %d\n", 1396 index, ap_info_v1->bssid, ap_info_v1->channel); 1397 ap_info_v1++; 1398 } 1399 1400 return 0; 1401 } 1402 1403 int ath6kl_wmi_cmd_send(struct wmi *wmi, struct sk_buff *skb, 1404 enum wmi_cmd_id cmd_id, enum wmi_sync_flag sync_flag) 1405 { 1406 struct wmi_cmd_hdr *cmd_hdr; 1407 enum htc_endpoint_id ep_id = wmi->ep_id; 1408 int ret; 1409 1410 if (WARN_ON(skb == NULL)) 1411 return -EINVAL; 1412 1413 if (sync_flag >= END_WMIFLAG) { 1414 dev_kfree_skb(skb); 1415 return -EINVAL; 1416 } 1417 1418 if ((sync_flag == SYNC_BEFORE_WMIFLAG) || 1419 (sync_flag == SYNC_BOTH_WMIFLAG)) { 1420 /* 1421 * Make sure all data currently queued is transmitted before 1422 * the cmd execution. Establish a new sync point. 1423 */ 1424 ath6kl_wmi_sync_point(wmi); 1425 } 1426 1427 skb_push(skb, sizeof(struct wmi_cmd_hdr)); 1428 1429 cmd_hdr = (struct wmi_cmd_hdr *) skb->data; 1430 cmd_hdr->cmd_id = cpu_to_le16(cmd_id); 1431 cmd_hdr->info1 = 0; /* added for virtual interface */ 1432 1433 /* Only for OPT_TX_CMD, use BE endpoint. */ 1434 if (cmd_id == WMI_OPT_TX_FRAME_CMDID) { 1435 ret = ath6kl_wmi_data_hdr_add(wmi, skb, OPT_MSGTYPE, 1436 false, false, 0, NULL); 1437 if (ret) { 1438 dev_kfree_skb(skb); 1439 return ret; 1440 } 1441 ep_id = ath6kl_ac2_endpoint_id(wmi->parent_dev, WMM_AC_BE); 1442 } 1443 1444 ath6kl_control_tx(wmi->parent_dev, skb, ep_id); 1445 1446 if ((sync_flag == SYNC_AFTER_WMIFLAG) || 1447 (sync_flag == SYNC_BOTH_WMIFLAG)) { 1448 /* 1449 * Make sure all new data queued waits for the command to 1450 * execute. Establish a new sync point. 1451 */ 1452 ath6kl_wmi_sync_point(wmi); 1453 } 1454 1455 return 0; 1456 } 1457 1458 int ath6kl_wmi_connect_cmd(struct wmi *wmi, enum network_type nw_type, 1459 enum dot11_auth_mode dot11_auth_mode, 1460 enum auth_mode auth_mode, 1461 enum crypto_type pairwise_crypto, 1462 u8 pairwise_crypto_len, 1463 enum crypto_type group_crypto, 1464 u8 group_crypto_len, int ssid_len, u8 *ssid, 1465 u8 *bssid, u16 channel, u32 ctrl_flags) 1466 { 1467 struct sk_buff *skb; 1468 struct wmi_connect_cmd *cc; 1469 int ret; 1470 1471 wmi->traffic_class = 100; 1472 1473 if ((pairwise_crypto == NONE_CRYPT) && (group_crypto != NONE_CRYPT)) 1474 return -EINVAL; 1475 1476 if ((pairwise_crypto != NONE_CRYPT) && (group_crypto == NONE_CRYPT)) 1477 return -EINVAL; 1478 1479 skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_connect_cmd)); 1480 if (!skb) 1481 return -ENOMEM; 1482 1483 cc = (struct wmi_connect_cmd *) skb->data; 1484 1485 if (ssid_len) 1486 memcpy(cc->ssid, ssid, ssid_len); 1487 1488 cc->ssid_len = ssid_len; 1489 cc->nw_type = nw_type; 1490 cc->dot11_auth_mode = dot11_auth_mode; 1491 cc->auth_mode = auth_mode; 1492 cc->prwise_crypto_type = pairwise_crypto; 1493 cc->prwise_crypto_len = pairwise_crypto_len; 1494 cc->grp_crypto_type = group_crypto; 1495 cc->grp_crypto_len = group_crypto_len; 1496 cc->ch = cpu_to_le16(channel); 1497 cc->ctrl_flags = cpu_to_le32(ctrl_flags); 1498 1499 if (bssid != NULL) 1500 memcpy(cc->bssid, bssid, ETH_ALEN); 1501 1502 wmi->pair_crypto_type = pairwise_crypto; 1503 wmi->grp_crypto_type = group_crypto; 1504 1505 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_CONNECT_CMDID, NO_SYNC_WMIFLAG); 1506 1507 return ret; 1508 } 1509 1510 int ath6kl_wmi_reconnect_cmd(struct wmi *wmi, u8 *bssid, u16 channel) 1511 { 1512 struct sk_buff *skb; 1513 struct wmi_reconnect_cmd *cc; 1514 int ret; 1515 1516 wmi->traffic_class = 100; 1517 1518 skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_reconnect_cmd)); 1519 if (!skb) 1520 return -ENOMEM; 1521 1522 cc = (struct wmi_reconnect_cmd *) skb->data; 1523 cc->channel = cpu_to_le16(channel); 1524 1525 if (bssid != NULL) 1526 memcpy(cc->bssid, bssid, ETH_ALEN); 1527 1528 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_RECONNECT_CMDID, 1529 NO_SYNC_WMIFLAG); 1530 1531 return ret; 1532 } 1533 1534 int ath6kl_wmi_disconnect_cmd(struct wmi *wmi) 1535 { 1536 int ret; 1537 1538 wmi->traffic_class = 100; 1539 1540 /* Disconnect command does not need to do a SYNC before. */ 1541 ret = ath6kl_wmi_simple_cmd(wmi, WMI_DISCONNECT_CMDID); 1542 1543 return ret; 1544 } 1545 1546 int ath6kl_wmi_startscan_cmd(struct wmi *wmi, enum wmi_scan_type scan_type, 1547 u32 force_fgscan, u32 is_legacy, 1548 u32 home_dwell_time, u32 force_scan_interval, 1549 s8 num_chan, u16 *ch_list) 1550 { 1551 struct sk_buff *skb; 1552 struct wmi_start_scan_cmd *sc; 1553 s8 size; 1554 int ret; 1555 1556 size = sizeof(struct wmi_start_scan_cmd); 1557 1558 if ((scan_type != WMI_LONG_SCAN) && (scan_type != WMI_SHORT_SCAN)) 1559 return -EINVAL; 1560 1561 if (num_chan > WMI_MAX_CHANNELS) 1562 return -EINVAL; 1563 1564 if (num_chan) 1565 size += sizeof(u16) * (num_chan - 1); 1566 1567 skb = ath6kl_wmi_get_new_buf(size); 1568 if (!skb) 1569 return -ENOMEM; 1570 1571 sc = (struct wmi_start_scan_cmd *) skb->data; 1572 sc->scan_type = scan_type; 1573 sc->force_fg_scan = cpu_to_le32(force_fgscan); 1574 sc->is_legacy = cpu_to_le32(is_legacy); 1575 sc->home_dwell_time = cpu_to_le32(home_dwell_time); 1576 sc->force_scan_intvl = cpu_to_le32(force_scan_interval); 1577 sc->num_ch = num_chan; 1578 1579 if (num_chan) 1580 memcpy(sc->ch_list, ch_list, num_chan * sizeof(u16)); 1581 1582 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_START_SCAN_CMDID, 1583 NO_SYNC_WMIFLAG); 1584 1585 return ret; 1586 } 1587 1588 int ath6kl_wmi_scanparams_cmd(struct wmi *wmi, u16 fg_start_sec, 1589 u16 fg_end_sec, u16 bg_sec, 1590 u16 minact_chdw_msec, u16 maxact_chdw_msec, 1591 u16 pas_chdw_msec, u8 short_scan_ratio, 1592 u8 scan_ctrl_flag, u32 max_dfsch_act_time, 1593 u16 maxact_scan_per_ssid) 1594 { 1595 struct sk_buff *skb; 1596 struct wmi_scan_params_cmd *sc; 1597 int ret; 1598 1599 skb = ath6kl_wmi_get_new_buf(sizeof(*sc)); 1600 if (!skb) 1601 return -ENOMEM; 1602 1603 sc = (struct wmi_scan_params_cmd *) skb->data; 1604 sc->fg_start_period = cpu_to_le16(fg_start_sec); 1605 sc->fg_end_period = cpu_to_le16(fg_end_sec); 1606 sc->bg_period = cpu_to_le16(bg_sec); 1607 sc->minact_chdwell_time = cpu_to_le16(minact_chdw_msec); 1608 sc->maxact_chdwell_time = cpu_to_le16(maxact_chdw_msec); 1609 sc->pas_chdwell_time = cpu_to_le16(pas_chdw_msec); 1610 sc->short_scan_ratio = short_scan_ratio; 1611 sc->scan_ctrl_flags = scan_ctrl_flag; 1612 sc->max_dfsch_act_time = cpu_to_le32(max_dfsch_act_time); 1613 sc->maxact_scan_per_ssid = cpu_to_le16(maxact_scan_per_ssid); 1614 1615 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_SCAN_PARAMS_CMDID, 1616 NO_SYNC_WMIFLAG); 1617 return ret; 1618 } 1619 1620 int ath6kl_wmi_bssfilter_cmd(struct wmi *wmi, u8 filter, u32 ie_mask) 1621 { 1622 struct sk_buff *skb; 1623 struct wmi_bss_filter_cmd *cmd; 1624 int ret; 1625 1626 if (filter >= LAST_BSS_FILTER) 1627 return -EINVAL; 1628 1629 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 1630 if (!skb) 1631 return -ENOMEM; 1632 1633 cmd = (struct wmi_bss_filter_cmd *) skb->data; 1634 cmd->bss_filter = filter; 1635 cmd->ie_mask = cpu_to_le32(ie_mask); 1636 1637 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_BSS_FILTER_CMDID, 1638 NO_SYNC_WMIFLAG); 1639 return ret; 1640 } 1641 1642 int ath6kl_wmi_probedssid_cmd(struct wmi *wmi, u8 index, u8 flag, 1643 u8 ssid_len, u8 *ssid) 1644 { 1645 struct sk_buff *skb; 1646 struct wmi_probed_ssid_cmd *cmd; 1647 int ret; 1648 1649 if (index > MAX_PROBED_SSID_INDEX) 1650 return -EINVAL; 1651 1652 if (ssid_len > sizeof(cmd->ssid)) 1653 return -EINVAL; 1654 1655 if ((flag & (DISABLE_SSID_FLAG | ANY_SSID_FLAG)) && (ssid_len > 0)) 1656 return -EINVAL; 1657 1658 if ((flag & SPECIFIC_SSID_FLAG) && !ssid_len) 1659 return -EINVAL; 1660 1661 if (flag & SPECIFIC_SSID_FLAG) 1662 wmi->is_probe_ssid = true; 1663 1664 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 1665 if (!skb) 1666 return -ENOMEM; 1667 1668 cmd = (struct wmi_probed_ssid_cmd *) skb->data; 1669 cmd->entry_index = index; 1670 cmd->flag = flag; 1671 cmd->ssid_len = ssid_len; 1672 memcpy(cmd->ssid, ssid, ssid_len); 1673 1674 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_PROBED_SSID_CMDID, 1675 NO_SYNC_WMIFLAG); 1676 return ret; 1677 } 1678 1679 int ath6kl_wmi_listeninterval_cmd(struct wmi *wmi, u16 listen_interval, 1680 u16 listen_beacons) 1681 { 1682 struct sk_buff *skb; 1683 struct wmi_listen_int_cmd *cmd; 1684 int ret; 1685 1686 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 1687 if (!skb) 1688 return -ENOMEM; 1689 1690 cmd = (struct wmi_listen_int_cmd *) skb->data; 1691 cmd->listen_intvl = cpu_to_le16(listen_interval); 1692 cmd->num_beacons = cpu_to_le16(listen_beacons); 1693 1694 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_LISTEN_INT_CMDID, 1695 NO_SYNC_WMIFLAG); 1696 return ret; 1697 } 1698 1699 int ath6kl_wmi_powermode_cmd(struct wmi *wmi, u8 pwr_mode) 1700 { 1701 struct sk_buff *skb; 1702 struct wmi_power_mode_cmd *cmd; 1703 int ret; 1704 1705 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 1706 if (!skb) 1707 return -ENOMEM; 1708 1709 cmd = (struct wmi_power_mode_cmd *) skb->data; 1710 cmd->pwr_mode = pwr_mode; 1711 wmi->pwr_mode = pwr_mode; 1712 1713 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_POWER_MODE_CMDID, 1714 NO_SYNC_WMIFLAG); 1715 return ret; 1716 } 1717 1718 int ath6kl_wmi_pmparams_cmd(struct wmi *wmi, u16 idle_period, 1719 u16 ps_poll_num, u16 dtim_policy, 1720 u16 tx_wakeup_policy, u16 num_tx_to_wakeup, 1721 u16 ps_fail_event_policy) 1722 { 1723 struct sk_buff *skb; 1724 struct wmi_power_params_cmd *pm; 1725 int ret; 1726 1727 skb = ath6kl_wmi_get_new_buf(sizeof(*pm)); 1728 if (!skb) 1729 return -ENOMEM; 1730 1731 pm = (struct wmi_power_params_cmd *)skb->data; 1732 pm->idle_period = cpu_to_le16(idle_period); 1733 pm->pspoll_number = cpu_to_le16(ps_poll_num); 1734 pm->dtim_policy = cpu_to_le16(dtim_policy); 1735 pm->tx_wakeup_policy = cpu_to_le16(tx_wakeup_policy); 1736 pm->num_tx_to_wakeup = cpu_to_le16(num_tx_to_wakeup); 1737 pm->ps_fail_event_policy = cpu_to_le16(ps_fail_event_policy); 1738 1739 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_POWER_PARAMS_CMDID, 1740 NO_SYNC_WMIFLAG); 1741 return ret; 1742 } 1743 1744 int ath6kl_wmi_disctimeout_cmd(struct wmi *wmi, u8 timeout) 1745 { 1746 struct sk_buff *skb; 1747 struct wmi_disc_timeout_cmd *cmd; 1748 int ret; 1749 1750 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 1751 if (!skb) 1752 return -ENOMEM; 1753 1754 cmd = (struct wmi_disc_timeout_cmd *) skb->data; 1755 cmd->discon_timeout = timeout; 1756 1757 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_DISC_TIMEOUT_CMDID, 1758 NO_SYNC_WMIFLAG); 1759 return ret; 1760 } 1761 1762 int ath6kl_wmi_addkey_cmd(struct wmi *wmi, u8 key_index, 1763 enum crypto_type key_type, 1764 u8 key_usage, u8 key_len, 1765 u8 *key_rsc, u8 *key_material, 1766 u8 key_op_ctrl, u8 *mac_addr, 1767 enum wmi_sync_flag sync_flag) 1768 { 1769 struct sk_buff *skb; 1770 struct wmi_add_cipher_key_cmd *cmd; 1771 int ret; 1772 1773 if ((key_index > WMI_MAX_KEY_INDEX) || (key_len > WMI_MAX_KEY_LEN) || 1774 (key_material == NULL)) 1775 return -EINVAL; 1776 1777 if ((WEP_CRYPT != key_type) && (NULL == key_rsc)) 1778 return -EINVAL; 1779 1780 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 1781 if (!skb) 1782 return -ENOMEM; 1783 1784 cmd = (struct wmi_add_cipher_key_cmd *) skb->data; 1785 cmd->key_index = key_index; 1786 cmd->key_type = key_type; 1787 cmd->key_usage = key_usage; 1788 cmd->key_len = key_len; 1789 memcpy(cmd->key, key_material, key_len); 1790 1791 if (key_rsc != NULL) 1792 memcpy(cmd->key_rsc, key_rsc, sizeof(cmd->key_rsc)); 1793 1794 cmd->key_op_ctrl = key_op_ctrl; 1795 1796 if (mac_addr) 1797 memcpy(cmd->key_mac_addr, mac_addr, ETH_ALEN); 1798 1799 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_ADD_CIPHER_KEY_CMDID, 1800 sync_flag); 1801 1802 return ret; 1803 } 1804 1805 int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 *krk) 1806 { 1807 struct sk_buff *skb; 1808 struct wmi_add_krk_cmd *cmd; 1809 int ret; 1810 1811 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 1812 if (!skb) 1813 return -ENOMEM; 1814 1815 cmd = (struct wmi_add_krk_cmd *) skb->data; 1816 memcpy(cmd->krk, krk, WMI_KRK_LEN); 1817 1818 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_ADD_KRK_CMDID, NO_SYNC_WMIFLAG); 1819 1820 return ret; 1821 } 1822 1823 int ath6kl_wmi_deletekey_cmd(struct wmi *wmi, u8 key_index) 1824 { 1825 struct sk_buff *skb; 1826 struct wmi_delete_cipher_key_cmd *cmd; 1827 int ret; 1828 1829 if (key_index > WMI_MAX_KEY_INDEX) 1830 return -EINVAL; 1831 1832 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 1833 if (!skb) 1834 return -ENOMEM; 1835 1836 cmd = (struct wmi_delete_cipher_key_cmd *) skb->data; 1837 cmd->key_index = key_index; 1838 1839 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_DELETE_CIPHER_KEY_CMDID, 1840 NO_SYNC_WMIFLAG); 1841 1842 return ret; 1843 } 1844 1845 int ath6kl_wmi_setpmkid_cmd(struct wmi *wmi, const u8 *bssid, 1846 const u8 *pmkid, bool set) 1847 { 1848 struct sk_buff *skb; 1849 struct wmi_setpmkid_cmd *cmd; 1850 int ret; 1851 1852 if (bssid == NULL) 1853 return -EINVAL; 1854 1855 if (set && pmkid == NULL) 1856 return -EINVAL; 1857 1858 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 1859 if (!skb) 1860 return -ENOMEM; 1861 1862 cmd = (struct wmi_setpmkid_cmd *) skb->data; 1863 memcpy(cmd->bssid, bssid, ETH_ALEN); 1864 if (set) { 1865 memcpy(cmd->pmkid, pmkid, sizeof(cmd->pmkid)); 1866 cmd->enable = PMKID_ENABLE; 1867 } else { 1868 memset(cmd->pmkid, 0, sizeof(cmd->pmkid)); 1869 cmd->enable = PMKID_DISABLE; 1870 } 1871 1872 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_PMKID_CMDID, 1873 NO_SYNC_WMIFLAG); 1874 1875 return ret; 1876 } 1877 1878 static int ath6kl_wmi_data_sync_send(struct wmi *wmi, struct sk_buff *skb, 1879 enum htc_endpoint_id ep_id) 1880 { 1881 struct wmi_data_hdr *data_hdr; 1882 int ret; 1883 1884 if (WARN_ON(skb == NULL || ep_id == wmi->ep_id)) 1885 return -EINVAL; 1886 1887 skb_push(skb, sizeof(struct wmi_data_hdr)); 1888 1889 data_hdr = (struct wmi_data_hdr *) skb->data; 1890 data_hdr->info = SYNC_MSGTYPE << WMI_DATA_HDR_MSG_TYPE_SHIFT; 1891 data_hdr->info3 = 0; 1892 1893 ret = ath6kl_control_tx(wmi->parent_dev, skb, ep_id); 1894 1895 return ret; 1896 } 1897 1898 static int ath6kl_wmi_sync_point(struct wmi *wmi) 1899 { 1900 struct sk_buff *skb; 1901 struct wmi_sync_cmd *cmd; 1902 struct wmi_data_sync_bufs data_sync_bufs[WMM_NUM_AC]; 1903 enum htc_endpoint_id ep_id; 1904 u8 index, num_pri_streams = 0; 1905 int ret = 0; 1906 1907 memset(data_sync_bufs, 0, sizeof(data_sync_bufs)); 1908 1909 spin_lock_bh(&wmi->lock); 1910 1911 for (index = 0; index < WMM_NUM_AC; index++) { 1912 if (wmi->fat_pipe_exist & (1 << index)) { 1913 num_pri_streams++; 1914 data_sync_bufs[num_pri_streams - 1].traffic_class = 1915 index; 1916 } 1917 } 1918 1919 spin_unlock_bh(&wmi->lock); 1920 1921 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 1922 if (!skb) { 1923 ret = -ENOMEM; 1924 goto free_skb; 1925 } 1926 1927 cmd = (struct wmi_sync_cmd *) skb->data; 1928 1929 /* 1930 * In the SYNC cmd sent on the control Ep, send a bitmap 1931 * of the data eps on which the Data Sync will be sent 1932 */ 1933 cmd->data_sync_map = wmi->fat_pipe_exist; 1934 1935 for (index = 0; index < num_pri_streams; index++) { 1936 data_sync_bufs[index].skb = ath6kl_buf_alloc(0); 1937 if (data_sync_bufs[index].skb == NULL) { 1938 ret = -ENOMEM; 1939 break; 1940 } 1941 } 1942 1943 /* 1944 * If buffer allocation for any of the dataSync fails, 1945 * then do not send the Synchronize cmd on the control ep 1946 */ 1947 if (ret) 1948 goto free_skb; 1949 1950 /* 1951 * Send sync cmd followed by sync data messages on all 1952 * endpoints being used 1953 */ 1954 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SYNCHRONIZE_CMDID, 1955 NO_SYNC_WMIFLAG); 1956 1957 if (ret) 1958 goto free_skb; 1959 1960 /* cmd buffer sent, we no longer own it */ 1961 skb = NULL; 1962 1963 for (index = 0; index < num_pri_streams; index++) { 1964 1965 if (WARN_ON(!data_sync_bufs[index].skb)) 1966 break; 1967 1968 ep_id = ath6kl_ac2_endpoint_id(wmi->parent_dev, 1969 data_sync_bufs[index]. 1970 traffic_class); 1971 ret = 1972 ath6kl_wmi_data_sync_send(wmi, data_sync_bufs[index].skb, 1973 ep_id); 1974 1975 if (ret) 1976 break; 1977 1978 data_sync_bufs[index].skb = NULL; 1979 } 1980 1981 free_skb: 1982 /* free up any resources left over (possibly due to an error) */ 1983 if (skb) 1984 dev_kfree_skb(skb); 1985 1986 for (index = 0; index < num_pri_streams; index++) { 1987 if (data_sync_bufs[index].skb != NULL) { 1988 dev_kfree_skb((struct sk_buff *)data_sync_bufs[index]. 1989 skb); 1990 } 1991 } 1992 1993 return ret; 1994 } 1995 1996 int ath6kl_wmi_create_pstream_cmd(struct wmi *wmi, 1997 struct wmi_create_pstream_cmd *params) 1998 { 1999 struct sk_buff *skb; 2000 struct wmi_create_pstream_cmd *cmd; 2001 u8 fatpipe_exist_for_ac = 0; 2002 s32 min_phy = 0; 2003 s32 nominal_phy = 0; 2004 int ret; 2005 2006 if (!((params->user_pri < 8) && 2007 (params->user_pri <= 0x7) && 2008 (up_to_ac[params->user_pri & 0x7] == params->traffic_class) && 2009 (params->traffic_direc == UPLINK_TRAFFIC || 2010 params->traffic_direc == DNLINK_TRAFFIC || 2011 params->traffic_direc == BIDIR_TRAFFIC) && 2012 (params->traffic_type == TRAFFIC_TYPE_APERIODIC || 2013 params->traffic_type == TRAFFIC_TYPE_PERIODIC) && 2014 (params->voice_psc_cap == DISABLE_FOR_THIS_AC || 2015 params->voice_psc_cap == ENABLE_FOR_THIS_AC || 2016 params->voice_psc_cap == ENABLE_FOR_ALL_AC) && 2017 (params->tsid == WMI_IMPLICIT_PSTREAM || 2018 params->tsid <= WMI_MAX_THINSTREAM))) { 2019 return -EINVAL; 2020 } 2021 2022 /* 2023 * Check nominal PHY rate is >= minimalPHY, 2024 * so that DUT can allow TSRS IE 2025 */ 2026 2027 /* Get the physical rate (units of bps) */ 2028 min_phy = ((le32_to_cpu(params->min_phy_rate) / 1000) / 1000); 2029 2030 /* Check minimal phy < nominal phy rate */ 2031 if (params->nominal_phy >= min_phy) { 2032 /* unit of 500 kbps */ 2033 nominal_phy = (params->nominal_phy * 1000) / 500; 2034 ath6kl_dbg(ATH6KL_DBG_WMI, 2035 "TSRS IE enabled::MinPhy %x->NominalPhy ===> %x\n", 2036 min_phy, nominal_phy); 2037 2038 params->nominal_phy = nominal_phy; 2039 } else { 2040 params->nominal_phy = 0; 2041 } 2042 2043 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 2044 if (!skb) 2045 return -ENOMEM; 2046 2047 ath6kl_dbg(ATH6KL_DBG_WMI, 2048 "sending create_pstream_cmd: ac=%d tsid:%d\n", 2049 params->traffic_class, params->tsid); 2050 2051 cmd = (struct wmi_create_pstream_cmd *) skb->data; 2052 memcpy(cmd, params, sizeof(*cmd)); 2053 2054 /* This is an implicitly created Fat pipe */ 2055 if ((u32) params->tsid == (u32) WMI_IMPLICIT_PSTREAM) { 2056 spin_lock_bh(&wmi->lock); 2057 fatpipe_exist_for_ac = (wmi->fat_pipe_exist & 2058 (1 << params->traffic_class)); 2059 wmi->fat_pipe_exist |= (1 << params->traffic_class); 2060 spin_unlock_bh(&wmi->lock); 2061 } else { 2062 /* explicitly created thin stream within a fat pipe */ 2063 spin_lock_bh(&wmi->lock); 2064 fatpipe_exist_for_ac = (wmi->fat_pipe_exist & 2065 (1 << params->traffic_class)); 2066 wmi->stream_exist_for_ac[params->traffic_class] |= 2067 (1 << params->tsid); 2068 /* 2069 * If a thinstream becomes active, the fat pipe automatically 2070 * becomes active 2071 */ 2072 wmi->fat_pipe_exist |= (1 << params->traffic_class); 2073 spin_unlock_bh(&wmi->lock); 2074 } 2075 2076 /* 2077 * Indicate activty change to driver layer only if this is the 2078 * first TSID to get created in this AC explicitly or an implicit 2079 * fat pipe is getting created. 2080 */ 2081 if (!fatpipe_exist_for_ac) 2082 ath6kl_indicate_tx_activity(wmi->parent_dev, 2083 params->traffic_class, true); 2084 2085 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_CREATE_PSTREAM_CMDID, 2086 NO_SYNC_WMIFLAG); 2087 return ret; 2088 } 2089 2090 int ath6kl_wmi_delete_pstream_cmd(struct wmi *wmi, u8 traffic_class, u8 tsid) 2091 { 2092 struct sk_buff *skb; 2093 struct wmi_delete_pstream_cmd *cmd; 2094 u16 active_tsids = 0; 2095 int ret; 2096 2097 if (traffic_class > 3) { 2098 ath6kl_err("invalid traffic class: %d\n", traffic_class); 2099 return -EINVAL; 2100 } 2101 2102 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 2103 if (!skb) 2104 return -ENOMEM; 2105 2106 cmd = (struct wmi_delete_pstream_cmd *) skb->data; 2107 cmd->traffic_class = traffic_class; 2108 cmd->tsid = tsid; 2109 2110 spin_lock_bh(&wmi->lock); 2111 active_tsids = wmi->stream_exist_for_ac[traffic_class]; 2112 spin_unlock_bh(&wmi->lock); 2113 2114 if (!(active_tsids & (1 << tsid))) { 2115 dev_kfree_skb(skb); 2116 ath6kl_dbg(ATH6KL_DBG_WMI, 2117 "TSID %d doesn't exist for traffic class: %d\n", 2118 tsid, traffic_class); 2119 return -ENODATA; 2120 } 2121 2122 ath6kl_dbg(ATH6KL_DBG_WMI, 2123 "sending delete_pstream_cmd: traffic class: %d tsid=%d\n", 2124 traffic_class, tsid); 2125 2126 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_DELETE_PSTREAM_CMDID, 2127 SYNC_BEFORE_WMIFLAG); 2128 2129 spin_lock_bh(&wmi->lock); 2130 wmi->stream_exist_for_ac[traffic_class] &= ~(1 << tsid); 2131 active_tsids = wmi->stream_exist_for_ac[traffic_class]; 2132 spin_unlock_bh(&wmi->lock); 2133 2134 /* 2135 * Indicate stream inactivity to driver layer only if all tsids 2136 * within this AC are deleted. 2137 */ 2138 if (!active_tsids) { 2139 ath6kl_indicate_tx_activity(wmi->parent_dev, 2140 traffic_class, false); 2141 wmi->fat_pipe_exist &= ~(1 << traffic_class); 2142 } 2143 2144 return ret; 2145 } 2146 2147 int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, struct wmi_set_ip_cmd *ip_cmd) 2148 { 2149 struct sk_buff *skb; 2150 struct wmi_set_ip_cmd *cmd; 2151 int ret; 2152 2153 /* Multicast address are not valid */ 2154 if ((*((u8 *) &ip_cmd->ips[0]) >= 0xE0) || 2155 (*((u8 *) &ip_cmd->ips[1]) >= 0xE0)) 2156 return -EINVAL; 2157 2158 skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_ip_cmd)); 2159 if (!skb) 2160 return -ENOMEM; 2161 2162 cmd = (struct wmi_set_ip_cmd *) skb->data; 2163 memcpy(cmd, ip_cmd, sizeof(struct wmi_set_ip_cmd)); 2164 2165 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_IP_CMDID, NO_SYNC_WMIFLAG); 2166 return ret; 2167 } 2168 2169 static int ath6kl_wmi_get_wow_list_event_rx(struct wmi *wmi, u8 * datap, 2170 int len) 2171 { 2172 if (len < sizeof(struct wmi_get_wow_list_reply)) 2173 return -EINVAL; 2174 2175 return 0; 2176 } 2177 2178 static int ath6kl_wmi_cmd_send_xtnd(struct wmi *wmi, struct sk_buff *skb, 2179 enum wmix_command_id cmd_id, 2180 enum wmi_sync_flag sync_flag) 2181 { 2182 struct wmix_cmd_hdr *cmd_hdr; 2183 int ret; 2184 2185 skb_push(skb, sizeof(struct wmix_cmd_hdr)); 2186 2187 cmd_hdr = (struct wmix_cmd_hdr *) skb->data; 2188 cmd_hdr->cmd_id = cpu_to_le32(cmd_id); 2189 2190 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_EXTENSION_CMDID, sync_flag); 2191 2192 return ret; 2193 } 2194 2195 int ath6kl_wmi_get_challenge_resp_cmd(struct wmi *wmi, u32 cookie, u32 source) 2196 { 2197 struct sk_buff *skb; 2198 struct wmix_hb_challenge_resp_cmd *cmd; 2199 int ret; 2200 2201 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 2202 if (!skb) 2203 return -ENOMEM; 2204 2205 cmd = (struct wmix_hb_challenge_resp_cmd *) skb->data; 2206 cmd->cookie = cpu_to_le32(cookie); 2207 cmd->source = cpu_to_le32(source); 2208 2209 ret = ath6kl_wmi_cmd_send_xtnd(wmi, skb, WMIX_HB_CHALLENGE_RESP_CMDID, 2210 NO_SYNC_WMIFLAG); 2211 return ret; 2212 } 2213 2214 int ath6kl_wmi_get_stats_cmd(struct wmi *wmi) 2215 { 2216 return ath6kl_wmi_simple_cmd(wmi, WMI_GET_STATISTICS_CMDID); 2217 } 2218 2219 int ath6kl_wmi_set_tx_pwr_cmd(struct wmi *wmi, u8 dbM) 2220 { 2221 struct sk_buff *skb; 2222 struct wmi_set_tx_pwr_cmd *cmd; 2223 int ret; 2224 2225 skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_tx_pwr_cmd)); 2226 if (!skb) 2227 return -ENOMEM; 2228 2229 cmd = (struct wmi_set_tx_pwr_cmd *) skb->data; 2230 cmd->dbM = dbM; 2231 2232 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_TX_PWR_CMDID, 2233 NO_SYNC_WMIFLAG); 2234 2235 return ret; 2236 } 2237 2238 int ath6kl_wmi_get_tx_pwr_cmd(struct wmi *wmi) 2239 { 2240 return ath6kl_wmi_simple_cmd(wmi, WMI_GET_TX_PWR_CMDID); 2241 } 2242 2243 int ath6kl_wmi_set_lpreamble_cmd(struct wmi *wmi, u8 status, u8 preamble_policy) 2244 { 2245 struct sk_buff *skb; 2246 struct wmi_set_lpreamble_cmd *cmd; 2247 int ret; 2248 2249 skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_lpreamble_cmd)); 2250 if (!skb) 2251 return -ENOMEM; 2252 2253 cmd = (struct wmi_set_lpreamble_cmd *) skb->data; 2254 cmd->status = status; 2255 cmd->preamble_policy = preamble_policy; 2256 2257 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_LPREAMBLE_CMDID, 2258 NO_SYNC_WMIFLAG); 2259 return ret; 2260 } 2261 2262 int ath6kl_wmi_set_rts_cmd(struct wmi *wmi, u16 threshold) 2263 { 2264 struct sk_buff *skb; 2265 struct wmi_set_rts_cmd *cmd; 2266 int ret; 2267 2268 skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_rts_cmd)); 2269 if (!skb) 2270 return -ENOMEM; 2271 2272 cmd = (struct wmi_set_rts_cmd *) skb->data; 2273 cmd->threshold = cpu_to_le16(threshold); 2274 2275 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_RTS_CMDID, NO_SYNC_WMIFLAG); 2276 return ret; 2277 } 2278 2279 int ath6kl_wmi_set_wmm_txop(struct wmi *wmi, enum wmi_txop_cfg cfg) 2280 { 2281 struct sk_buff *skb; 2282 struct wmi_set_wmm_txop_cmd *cmd; 2283 int ret; 2284 2285 if (!((cfg == WMI_TXOP_DISABLED) || (cfg == WMI_TXOP_ENABLED))) 2286 return -EINVAL; 2287 2288 skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_wmm_txop_cmd)); 2289 if (!skb) 2290 return -ENOMEM; 2291 2292 cmd = (struct wmi_set_wmm_txop_cmd *) skb->data; 2293 cmd->txop_enable = cfg; 2294 2295 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_WMM_TXOP_CMDID, 2296 NO_SYNC_WMIFLAG); 2297 return ret; 2298 } 2299 2300 int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 keep_alive_intvl) 2301 { 2302 struct sk_buff *skb; 2303 struct wmi_set_keepalive_cmd *cmd; 2304 int ret; 2305 2306 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 2307 if (!skb) 2308 return -ENOMEM; 2309 2310 cmd = (struct wmi_set_keepalive_cmd *) skb->data; 2311 cmd->keep_alive_intvl = keep_alive_intvl; 2312 wmi->keep_alive_intvl = keep_alive_intvl; 2313 2314 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_KEEPALIVE_CMDID, 2315 NO_SYNC_WMIFLAG); 2316 return ret; 2317 } 2318 2319 s32 ath6kl_wmi_get_rate(s8 rate_index) 2320 { 2321 if (rate_index == RATE_AUTO) 2322 return 0; 2323 2324 return wmi_rate_tbl[(u32) rate_index][0]; 2325 } 2326 2327 void ath6kl_wmi_node_return(struct wmi *wmi, struct bss *bss) 2328 { 2329 if (bss) 2330 wlan_node_return(&wmi->parent_dev->scan_table, bss); 2331 } 2332 2333 struct bss *ath6kl_wmi_find_ssid_node(struct wmi *wmi, u8 * ssid, 2334 u32 ssid_len, bool is_wpa2, 2335 bool match_ssid) 2336 { 2337 struct bss *node = NULL; 2338 2339 node = wlan_find_ssid_node(&wmi->parent_dev->scan_table, ssid, 2340 ssid_len, is_wpa2, match_ssid); 2341 return node; 2342 } 2343 2344 struct bss *ath6kl_wmi_find_node(struct wmi *wmi, const u8 * mac_addr) 2345 { 2346 struct bss *ni = NULL; 2347 2348 ni = wlan_find_node(&wmi->parent_dev->scan_table, mac_addr); 2349 2350 return ni; 2351 } 2352 2353 void ath6kl_wmi_node_free(struct wmi *wmi, const u8 * mac_addr) 2354 { 2355 struct bss *ni = NULL; 2356 2357 ni = wlan_find_node(&wmi->parent_dev->scan_table, mac_addr); 2358 if (ni != NULL) 2359 wlan_node_reclaim(&wmi->parent_dev->scan_table, ni); 2360 2361 return; 2362 } 2363 2364 static int ath6kl_wmi_get_pmkid_list_event_rx(struct wmi *wmi, u8 *datap, 2365 u32 len) 2366 { 2367 struct wmi_pmkid_list_reply *reply; 2368 u32 expected_len; 2369 2370 if (len < sizeof(struct wmi_pmkid_list_reply)) 2371 return -EINVAL; 2372 2373 reply = (struct wmi_pmkid_list_reply *)datap; 2374 expected_len = sizeof(reply->num_pmkid) + 2375 le32_to_cpu(reply->num_pmkid) * WMI_PMKID_LEN; 2376 2377 if (len < expected_len) 2378 return -EINVAL; 2379 2380 return 0; 2381 } 2382 2383 static int ath6kl_wmi_addba_req_event_rx(struct wmi *wmi, u8 *datap, int len) 2384 { 2385 struct wmi_addba_req_event *cmd = (struct wmi_addba_req_event *) datap; 2386 2387 aggr_recv_addba_req_evt(wmi->parent_dev, cmd->tid, 2388 le16_to_cpu(cmd->st_seq_no), cmd->win_sz); 2389 2390 return 0; 2391 } 2392 2393 static int ath6kl_wmi_delba_req_event_rx(struct wmi *wmi, u8 *datap, int len) 2394 { 2395 struct wmi_delba_event *cmd = (struct wmi_delba_event *) datap; 2396 2397 aggr_recv_delba_req_evt(wmi->parent_dev, cmd->tid); 2398 2399 return 0; 2400 } 2401 2402 /* AP mode functions */ 2403 static int ath6kl_wmi_pspoll_event_rx(struct wmi *wmi, u8 *datap, int len) 2404 { 2405 struct wmi_pspoll_event *ev; 2406 2407 if (len < sizeof(struct wmi_pspoll_event)) 2408 return -EINVAL; 2409 2410 ev = (struct wmi_pspoll_event *) datap; 2411 2412 ath6kl_pspoll_event(wmi->parent_dev, le16_to_cpu(ev->aid)); 2413 2414 return 0; 2415 } 2416 2417 static int ath6kl_wmi_dtimexpiry_event_rx(struct wmi *wmi, u8 *datap, int len) 2418 { 2419 ath6kl_dtimexpiry_event(wmi->parent_dev); 2420 2421 return 0; 2422 } 2423 2424 int ath6kl_wmi_set_pvb_cmd(struct wmi *wmi, u16 aid, bool flag) 2425 { 2426 struct sk_buff *skb; 2427 struct wmi_ap_set_pvb_cmd *cmd; 2428 int ret; 2429 2430 skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_ap_set_pvb_cmd)); 2431 if (!skb) 2432 return -ENOMEM; 2433 2434 cmd = (struct wmi_ap_set_pvb_cmd *) skb->data; 2435 cmd->aid = cpu_to_le16(aid); 2436 cmd->flag = cpu_to_le32(flag); 2437 2438 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_AP_SET_PVB_CMDID, 2439 NO_SYNC_WMIFLAG); 2440 2441 return 0; 2442 } 2443 2444 int ath6kl_wmi_set_rx_frame_format_cmd(struct wmi *wmi, u8 rx_meta_ver, 2445 bool rx_dot11_hdr, bool defrag_on_host) 2446 { 2447 struct sk_buff *skb; 2448 struct wmi_rx_frame_format_cmd *cmd; 2449 int ret; 2450 2451 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 2452 if (!skb) 2453 return -ENOMEM; 2454 2455 cmd = (struct wmi_rx_frame_format_cmd *) skb->data; 2456 cmd->dot11_hdr = rx_dot11_hdr ? 1 : 0; 2457 cmd->defrag_on_host = defrag_on_host ? 1 : 0; 2458 cmd->meta_ver = rx_meta_ver; 2459 2460 /* Delete the local aggr state, on host */ 2461 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_RX_FRAME_FORMAT_CMDID, 2462 NO_SYNC_WMIFLAG); 2463 2464 return ret; 2465 } 2466 2467 static int ath6kl_wmi_control_rx_xtnd(struct wmi *wmi, struct sk_buff *skb) 2468 { 2469 struct wmix_cmd_hdr *cmd; 2470 u32 len; 2471 u16 id; 2472 u8 *datap; 2473 int ret = 0; 2474 2475 if (skb->len < sizeof(struct wmix_cmd_hdr)) { 2476 ath6kl_err("bad packet 1\n"); 2477 wmi->stat.cmd_len_err++; 2478 return -EINVAL; 2479 } 2480 2481 cmd = (struct wmix_cmd_hdr *) skb->data; 2482 id = le32_to_cpu(cmd->cmd_id); 2483 2484 skb_pull(skb, sizeof(struct wmix_cmd_hdr)); 2485 2486 datap = skb->data; 2487 len = skb->len; 2488 2489 switch (id) { 2490 case WMIX_HB_CHALLENGE_RESP_EVENTID: 2491 break; 2492 case WMIX_DBGLOG_EVENTID: 2493 break; 2494 default: 2495 ath6kl_err("unknown cmd id 0x%x\n", id); 2496 wmi->stat.cmd_id_err++; 2497 ret = -EINVAL; 2498 break; 2499 } 2500 2501 return ret; 2502 } 2503 2504 /* Control Path */ 2505 int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb) 2506 { 2507 struct wmi_cmd_hdr *cmd; 2508 u32 len; 2509 u16 id; 2510 u8 *datap; 2511 int ret = 0; 2512 2513 if (WARN_ON(skb == NULL)) 2514 return -EINVAL; 2515 2516 if (skb->len < sizeof(struct wmi_cmd_hdr)) { 2517 ath6kl_err("bad packet 1\n"); 2518 dev_kfree_skb(skb); 2519 wmi->stat.cmd_len_err++; 2520 return -EINVAL; 2521 } 2522 2523 cmd = (struct wmi_cmd_hdr *) skb->data; 2524 id = le16_to_cpu(cmd->cmd_id); 2525 2526 skb_pull(skb, sizeof(struct wmi_cmd_hdr)); 2527 2528 datap = skb->data; 2529 len = skb->len; 2530 2531 ath6kl_dbg(ATH6KL_DBG_WMI, "%s: wmi id: %d\n", __func__, id); 2532 ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "msg payload ", datap, len); 2533 2534 switch (id) { 2535 case WMI_GET_BITRATE_CMDID: 2536 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_BITRATE_CMDID\n"); 2537 ret = ath6kl_wmi_bitrate_reply_rx(wmi, datap, len); 2538 break; 2539 case WMI_GET_CHANNEL_LIST_CMDID: 2540 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_CHANNEL_LIST_CMDID\n"); 2541 ret = ath6kl_wmi_ch_list_reply_rx(wmi, datap, len); 2542 break; 2543 case WMI_GET_TX_PWR_CMDID: 2544 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_TX_PWR_CMDID\n"); 2545 ret = ath6kl_wmi_tx_pwr_reply_rx(wmi, datap, len); 2546 break; 2547 case WMI_READY_EVENTID: 2548 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_READY_EVENTID\n"); 2549 ret = ath6kl_wmi_ready_event_rx(wmi, datap, len); 2550 break; 2551 case WMI_CONNECT_EVENTID: 2552 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CONNECT_EVENTID\n"); 2553 ret = ath6kl_wmi_connect_event_rx(wmi, datap, len); 2554 break; 2555 case WMI_DISCONNECT_EVENTID: 2556 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_DISCONNECT_EVENTID\n"); 2557 ret = ath6kl_wmi_disconnect_event_rx(wmi, datap, len); 2558 break; 2559 case WMI_PEER_NODE_EVENTID: 2560 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_PEER_NODE_EVENTID\n"); 2561 ret = ath6kl_wmi_peer_node_event_rx(wmi, datap, len); 2562 break; 2563 case WMI_TKIP_MICERR_EVENTID: 2564 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TKIP_MICERR_EVENTID\n"); 2565 ret = ath6kl_wmi_tkip_micerr_event_rx(wmi, datap, len); 2566 break; 2567 case WMI_BSSINFO_EVENTID: 2568 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_BSSINFO_EVENTID\n"); 2569 ath6kl_wmi_convert_bssinfo_hdr2_to_hdr(skb, datap); 2570 ret = ath6kl_wmi_bssinfo_event_rx(wmi, skb->data, skb->len); 2571 break; 2572 case WMI_REGDOMAIN_EVENTID: 2573 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REGDOMAIN_EVENTID\n"); 2574 break; 2575 case WMI_PSTREAM_TIMEOUT_EVENTID: 2576 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_PSTREAM_TIMEOUT_EVENTID\n"); 2577 ret = ath6kl_wmi_pstream_timeout_event_rx(wmi, datap, len); 2578 break; 2579 case WMI_NEIGHBOR_REPORT_EVENTID: 2580 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_NEIGHBOR_REPORT_EVENTID\n"); 2581 break; 2582 case WMI_SCAN_COMPLETE_EVENTID: 2583 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_SCAN_COMPLETE_EVENTID\n"); 2584 ret = ath6kl_wmi_scan_complete_rx(wmi, datap, len); 2585 break; 2586 case WMI_CMDERROR_EVENTID: 2587 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CMDERROR_EVENTID\n"); 2588 ret = ath6kl_wmi_error_event_rx(wmi, datap, len); 2589 break; 2590 case WMI_REPORT_STATISTICS_EVENTID: 2591 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REPORT_STATISTICS_EVENTID\n"); 2592 ret = ath6kl_wmi_stats_event_rx(wmi, datap, len); 2593 break; 2594 case WMI_RSSI_THRESHOLD_EVENTID: 2595 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_RSSI_THRESHOLD_EVENTID\n"); 2596 ret = ath6kl_wmi_rssi_threshold_event_rx(wmi, datap, len); 2597 break; 2598 case WMI_ERROR_REPORT_EVENTID: 2599 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_ERROR_REPORT_EVENTID\n"); 2600 break; 2601 case WMI_OPT_RX_FRAME_EVENTID: 2602 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_OPT_RX_FRAME_EVENTID\n"); 2603 ret = ath6kl_wmi_opt_frame_event_rx(wmi, datap, len); 2604 break; 2605 case WMI_REPORT_ROAM_TBL_EVENTID: 2606 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REPORT_ROAM_TBL_EVENTID\n"); 2607 break; 2608 case WMI_EXTENSION_EVENTID: 2609 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_EXTENSION_EVENTID\n"); 2610 ret = ath6kl_wmi_control_rx_xtnd(wmi, skb); 2611 break; 2612 case WMI_CAC_EVENTID: 2613 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CAC_EVENTID\n"); 2614 ret = ath6kl_wmi_cac_event_rx(wmi, datap, len); 2615 break; 2616 case WMI_CHANNEL_CHANGE_EVENTID: 2617 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CHANNEL_CHANGE_EVENTID\n"); 2618 break; 2619 case WMI_REPORT_ROAM_DATA_EVENTID: 2620 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REPORT_ROAM_DATA_EVENTID\n"); 2621 break; 2622 case WMI_GET_FIXRATES_CMDID: 2623 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_FIXRATES_CMDID\n"); 2624 ret = ath6kl_wmi_ratemask_reply_rx(wmi, datap, len); 2625 break; 2626 case WMI_TX_RETRY_ERR_EVENTID: 2627 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TX_RETRY_ERR_EVENTID\n"); 2628 break; 2629 case WMI_SNR_THRESHOLD_EVENTID: 2630 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_SNR_THRESHOLD_EVENTID\n"); 2631 ret = ath6kl_wmi_snr_threshold_event_rx(wmi, datap, len); 2632 break; 2633 case WMI_LQ_THRESHOLD_EVENTID: 2634 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_LQ_THRESHOLD_EVENTID\n"); 2635 break; 2636 case WMI_APLIST_EVENTID: 2637 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_APLIST_EVENTID\n"); 2638 ret = ath6kl_wmi_aplist_event_rx(wmi, datap, len); 2639 break; 2640 case WMI_GET_KEEPALIVE_CMDID: 2641 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_KEEPALIVE_CMDID\n"); 2642 ret = ath6kl_wmi_keepalive_reply_rx(wmi, datap, len); 2643 break; 2644 case WMI_GET_WOW_LIST_EVENTID: 2645 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_WOW_LIST_EVENTID\n"); 2646 ret = ath6kl_wmi_get_wow_list_event_rx(wmi, datap, len); 2647 break; 2648 case WMI_GET_PMKID_LIST_EVENTID: 2649 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_PMKID_LIST_EVENTID\n"); 2650 ret = ath6kl_wmi_get_pmkid_list_event_rx(wmi, datap, len); 2651 break; 2652 case WMI_PSPOLL_EVENTID: 2653 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_PSPOLL_EVENTID\n"); 2654 ret = ath6kl_wmi_pspoll_event_rx(wmi, datap, len); 2655 break; 2656 case WMI_DTIMEXPIRY_EVENTID: 2657 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_DTIMEXPIRY_EVENTID\n"); 2658 ret = ath6kl_wmi_dtimexpiry_event_rx(wmi, datap, len); 2659 break; 2660 case WMI_SET_PARAMS_REPLY_EVENTID: 2661 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_SET_PARAMS_REPLY_EVENTID\n"); 2662 break; 2663 case WMI_ADDBA_REQ_EVENTID: 2664 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_ADDBA_REQ_EVENTID\n"); 2665 ret = ath6kl_wmi_addba_req_event_rx(wmi, datap, len); 2666 break; 2667 case WMI_ADDBA_RESP_EVENTID: 2668 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_ADDBA_RESP_EVENTID\n"); 2669 break; 2670 case WMI_DELBA_REQ_EVENTID: 2671 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_DELBA_REQ_EVENTID\n"); 2672 ret = ath6kl_wmi_delba_req_event_rx(wmi, datap, len); 2673 break; 2674 case WMI_REPORT_BTCOEX_CONFIG_EVENTID: 2675 ath6kl_dbg(ATH6KL_DBG_WMI, 2676 "WMI_REPORT_BTCOEX_CONFIG_EVENTID\n"); 2677 break; 2678 case WMI_REPORT_BTCOEX_STATS_EVENTID: 2679 ath6kl_dbg(ATH6KL_DBG_WMI, 2680 "WMI_REPORT_BTCOEX_STATS_EVENTID\n"); 2681 break; 2682 case WMI_TX_COMPLETE_EVENTID: 2683 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TX_COMPLETE_EVENTID\n"); 2684 ret = ath6kl_wmi_tx_complete_event_rx(datap, len); 2685 break; 2686 default: 2687 ath6kl_dbg(ATH6KL_DBG_WMI, "unknown cmd id 0x%x\n", id); 2688 wmi->stat.cmd_id_err++; 2689 ret = -EINVAL; 2690 break; 2691 } 2692 2693 dev_kfree_skb(skb); 2694 2695 return ret; 2696 } 2697 2698 static void ath6kl_wmi_qos_state_init(struct wmi *wmi) 2699 { 2700 if (!wmi) 2701 return; 2702 2703 spin_lock_bh(&wmi->lock); 2704 2705 wmi->fat_pipe_exist = 0; 2706 memset(wmi->stream_exist_for_ac, 0, sizeof(wmi->stream_exist_for_ac)); 2707 2708 spin_unlock_bh(&wmi->lock); 2709 } 2710 2711 void *ath6kl_wmi_init(struct ath6kl *dev) 2712 { 2713 struct wmi *wmi; 2714 2715 wmi = kzalloc(sizeof(struct wmi), GFP_KERNEL); 2716 if (!wmi) 2717 return NULL; 2718 2719 spin_lock_init(&wmi->lock); 2720 2721 wmi->parent_dev = dev; 2722 2723 ath6kl_wmi_qos_state_init(wmi); 2724 2725 wmi->pwr_mode = REC_POWER; 2726 wmi->phy_mode = WMI_11G_MODE; 2727 2728 wmi->pair_crypto_type = NONE_CRYPT; 2729 wmi->grp_crypto_type = NONE_CRYPT; 2730 2731 wmi->ht_allowed[A_BAND_24GHZ] = 1; 2732 wmi->ht_allowed[A_BAND_5GHZ] = 1; 2733 2734 return wmi; 2735 } 2736 2737 void ath6kl_wmi_shutdown(struct wmi *wmi) 2738 { 2739 if (!wmi) 2740 return; 2741 2742 kfree(wmi); 2743 } 2744