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 #include "testmode.h" 21 #include "../regd.h" 22 #include "../regd_common.h" 23 24 static int ath6kl_wmi_sync_point(struct wmi *wmi, u8 if_idx); 25 26 static const s32 wmi_rate_tbl[][2] = { 27 /* {W/O SGI, with SGI} */ 28 {1000, 1000}, 29 {2000, 2000}, 30 {5500, 5500}, 31 {11000, 11000}, 32 {6000, 6000}, 33 {9000, 9000}, 34 {12000, 12000}, 35 {18000, 18000}, 36 {24000, 24000}, 37 {36000, 36000}, 38 {48000, 48000}, 39 {54000, 54000}, 40 {6500, 7200}, 41 {13000, 14400}, 42 {19500, 21700}, 43 {26000, 28900}, 44 {39000, 43300}, 45 {52000, 57800}, 46 {58500, 65000}, 47 {65000, 72200}, 48 {13500, 15000}, 49 {27000, 30000}, 50 {40500, 45000}, 51 {54000, 60000}, 52 {81000, 90000}, 53 {108000, 120000}, 54 {121500, 135000}, 55 {135000, 150000}, 56 {0, 0} 57 }; 58 59 /* 802.1d to AC mapping. Refer pg 57 of WMM-test-plan-v1.2 */ 60 static const u8 up_to_ac[] = { 61 WMM_AC_BE, 62 WMM_AC_BK, 63 WMM_AC_BK, 64 WMM_AC_BE, 65 WMM_AC_VI, 66 WMM_AC_VI, 67 WMM_AC_VO, 68 WMM_AC_VO, 69 }; 70 71 void ath6kl_wmi_set_control_ep(struct wmi *wmi, enum htc_endpoint_id ep_id) 72 { 73 if (WARN_ON(ep_id == ENDPOINT_UNUSED || ep_id >= ENDPOINT_MAX)) 74 return; 75 76 wmi->ep_id = ep_id; 77 } 78 79 enum htc_endpoint_id ath6kl_wmi_get_control_ep(struct wmi *wmi) 80 { 81 return wmi->ep_id; 82 } 83 84 struct ath6kl_vif *ath6kl_get_vif_by_index(struct ath6kl *ar, u8 if_idx) 85 { 86 struct ath6kl_vif *vif, *found = NULL; 87 88 if (WARN_ON(if_idx > (MAX_NUM_VIF - 1))) 89 return NULL; 90 91 /* FIXME: Locking */ 92 spin_lock(&ar->list_lock); 93 list_for_each_entry(vif, &ar->vif_list, list) { 94 if (vif->fw_vif_idx == if_idx) { 95 found = vif; 96 break; 97 } 98 } 99 spin_unlock(&ar->list_lock); 100 101 return found; 102 } 103 104 /* Performs DIX to 802.3 encapsulation for transmit packets. 105 * Assumes the entire DIX header is contigous and that there is 106 * enough room in the buffer for a 802.3 mac header and LLC+SNAP headers. 107 */ 108 int ath6kl_wmi_dix_2_dot3(struct wmi *wmi, struct sk_buff *skb) 109 { 110 struct ath6kl_llc_snap_hdr *llc_hdr; 111 struct ethhdr *eth_hdr; 112 size_t new_len; 113 __be16 type; 114 u8 *datap; 115 u16 size; 116 117 if (WARN_ON(skb == NULL)) 118 return -EINVAL; 119 120 size = sizeof(struct ath6kl_llc_snap_hdr) + sizeof(struct wmi_data_hdr); 121 if (skb_headroom(skb) < size) 122 return -ENOMEM; 123 124 eth_hdr = (struct ethhdr *) skb->data; 125 type = eth_hdr->h_proto; 126 127 if (!is_ethertype(be16_to_cpu(type))) { 128 ath6kl_dbg(ATH6KL_DBG_WMI, 129 "%s: pkt is already in 802.3 format\n", __func__); 130 return 0; 131 } 132 133 new_len = skb->len - sizeof(*eth_hdr) + sizeof(*llc_hdr); 134 135 skb_push(skb, sizeof(struct ath6kl_llc_snap_hdr)); 136 datap = skb->data; 137 138 eth_hdr->h_proto = cpu_to_be16(new_len); 139 140 memcpy(datap, eth_hdr, sizeof(*eth_hdr)); 141 142 llc_hdr = (struct ath6kl_llc_snap_hdr *)(datap + sizeof(*eth_hdr)); 143 llc_hdr->dsap = 0xAA; 144 llc_hdr->ssap = 0xAA; 145 llc_hdr->cntl = 0x03; 146 llc_hdr->org_code[0] = 0x0; 147 llc_hdr->org_code[1] = 0x0; 148 llc_hdr->org_code[2] = 0x0; 149 llc_hdr->eth_type = type; 150 151 return 0; 152 } 153 154 static int ath6kl_wmi_meta_add(struct wmi *wmi, struct sk_buff *skb, 155 u8 *version, void *tx_meta_info) 156 { 157 struct wmi_tx_meta_v1 *v1; 158 struct wmi_tx_meta_v2 *v2; 159 160 if (WARN_ON(skb == NULL || version == NULL)) 161 return -EINVAL; 162 163 switch (*version) { 164 case WMI_META_VERSION_1: 165 skb_push(skb, WMI_MAX_TX_META_SZ); 166 v1 = (struct wmi_tx_meta_v1 *) skb->data; 167 v1->pkt_id = 0; 168 v1->rate_plcy_id = 0; 169 *version = WMI_META_VERSION_1; 170 break; 171 case WMI_META_VERSION_2: 172 skb_push(skb, WMI_MAX_TX_META_SZ); 173 v2 = (struct wmi_tx_meta_v2 *) skb->data; 174 memcpy(v2, (struct wmi_tx_meta_v2 *) tx_meta_info, 175 sizeof(struct wmi_tx_meta_v2)); 176 break; 177 } 178 179 return 0; 180 } 181 182 int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb, 183 u8 msg_type, bool more_data, 184 enum wmi_data_hdr_data_type data_type, 185 u8 meta_ver, void *tx_meta_info, u8 if_idx) 186 { 187 struct wmi_data_hdr *data_hdr; 188 int ret; 189 190 if (WARN_ON(skb == NULL || (if_idx > MAX_NUM_VIF - 1))) 191 return -EINVAL; 192 193 if (tx_meta_info) { 194 ret = ath6kl_wmi_meta_add(wmi, skb, &meta_ver, tx_meta_info); 195 if (ret) 196 return ret; 197 } 198 199 skb_push(skb, sizeof(struct wmi_data_hdr)); 200 201 data_hdr = (struct wmi_data_hdr *)skb->data; 202 memset(data_hdr, 0, sizeof(struct wmi_data_hdr)); 203 204 data_hdr->info = msg_type << WMI_DATA_HDR_MSG_TYPE_SHIFT; 205 data_hdr->info |= data_type << WMI_DATA_HDR_DATA_TYPE_SHIFT; 206 207 if (more_data) 208 data_hdr->info |= 209 WMI_DATA_HDR_MORE_MASK << WMI_DATA_HDR_MORE_SHIFT; 210 211 data_hdr->info2 = cpu_to_le16(meta_ver << WMI_DATA_HDR_META_SHIFT); 212 data_hdr->info3 = cpu_to_le16(if_idx & WMI_DATA_HDR_IF_IDX_MASK); 213 214 return 0; 215 } 216 217 static u8 ath6kl_wmi_determine_user_priority(u8 *pkt, u32 layer2_pri) 218 { 219 struct iphdr *ip_hdr = (struct iphdr *) pkt; 220 u8 ip_pri; 221 222 /* 223 * Determine IPTOS priority 224 * 225 * IP-TOS - 8bits 226 * : DSCP(6-bits) ECN(2-bits) 227 * : DSCP - P2 P1 P0 X X X 228 * where (P2 P1 P0) form 802.1D 229 */ 230 ip_pri = ip_hdr->tos >> 5; 231 ip_pri &= 0x7; 232 233 if ((layer2_pri & 0x7) > ip_pri) 234 return (u8) layer2_pri & 0x7; 235 else 236 return ip_pri; 237 } 238 239 int ath6kl_wmi_implicit_create_pstream(struct wmi *wmi, u8 if_idx, 240 struct sk_buff *skb, 241 u32 layer2_priority, bool wmm_enabled, 242 u8 *ac) 243 { 244 struct wmi_data_hdr *data_hdr; 245 struct ath6kl_llc_snap_hdr *llc_hdr; 246 struct wmi_create_pstream_cmd cmd; 247 u32 meta_size, hdr_size; 248 u16 ip_type = IP_ETHERTYPE; 249 u8 stream_exist, usr_pri; 250 u8 traffic_class = WMM_AC_BE; 251 u8 *datap; 252 253 if (WARN_ON(skb == NULL)) 254 return -EINVAL; 255 256 datap = skb->data; 257 data_hdr = (struct wmi_data_hdr *) datap; 258 259 meta_size = ((le16_to_cpu(data_hdr->info2) >> WMI_DATA_HDR_META_SHIFT) & 260 WMI_DATA_HDR_META_MASK) ? WMI_MAX_TX_META_SZ : 0; 261 262 if (!wmm_enabled) { 263 /* If WMM is disabled all traffic goes as BE traffic */ 264 usr_pri = 0; 265 } else { 266 hdr_size = sizeof(struct ethhdr); 267 268 llc_hdr = (struct ath6kl_llc_snap_hdr *)(datap + 269 sizeof(struct 270 wmi_data_hdr) + 271 meta_size + hdr_size); 272 273 if (llc_hdr->eth_type == htons(ip_type)) { 274 /* 275 * Extract the endpoint info from the TOS field 276 * in the IP header. 277 */ 278 usr_pri = 279 ath6kl_wmi_determine_user_priority(((u8 *) llc_hdr) + 280 sizeof(struct ath6kl_llc_snap_hdr), 281 layer2_priority); 282 } else 283 usr_pri = layer2_priority & 0x7; 284 } 285 286 /* 287 * workaround for WMM S5 288 * 289 * FIXME: wmi->traffic_class is always 100 so this test doesn't 290 * make sense 291 */ 292 if ((wmi->traffic_class == WMM_AC_VI) && 293 ((usr_pri == 5) || (usr_pri == 4))) 294 usr_pri = 1; 295 296 /* Convert user priority to traffic class */ 297 traffic_class = up_to_ac[usr_pri & 0x7]; 298 299 wmi_data_hdr_set_up(data_hdr, usr_pri); 300 301 spin_lock_bh(&wmi->lock); 302 stream_exist = wmi->fat_pipe_exist; 303 spin_unlock_bh(&wmi->lock); 304 305 if (!(stream_exist & (1 << traffic_class))) { 306 memset(&cmd, 0, sizeof(cmd)); 307 cmd.traffic_class = traffic_class; 308 cmd.user_pri = usr_pri; 309 cmd.inactivity_int = 310 cpu_to_le32(WMI_IMPLICIT_PSTREAM_INACTIVITY_INT); 311 /* Implicit streams are created with TSID 0xFF */ 312 cmd.tsid = WMI_IMPLICIT_PSTREAM; 313 ath6kl_wmi_create_pstream_cmd(wmi, if_idx, &cmd); 314 } 315 316 *ac = traffic_class; 317 318 return 0; 319 } 320 321 int ath6kl_wmi_dot11_hdr_remove(struct wmi *wmi, struct sk_buff *skb) 322 { 323 struct ieee80211_hdr_3addr *pwh, wh; 324 struct ath6kl_llc_snap_hdr *llc_hdr; 325 struct ethhdr eth_hdr; 326 u32 hdr_size; 327 u8 *datap; 328 __le16 sub_type; 329 330 if (WARN_ON(skb == NULL)) 331 return -EINVAL; 332 333 datap = skb->data; 334 pwh = (struct ieee80211_hdr_3addr *) datap; 335 336 sub_type = pwh->frame_control & cpu_to_le16(IEEE80211_FCTL_STYPE); 337 338 memcpy((u8 *) &wh, datap, sizeof(struct ieee80211_hdr_3addr)); 339 340 /* Strip off the 802.11 header */ 341 if (sub_type == cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) { 342 hdr_size = roundup(sizeof(struct ieee80211_qos_hdr), 343 sizeof(u32)); 344 skb_pull(skb, hdr_size); 345 } else if (sub_type == cpu_to_le16(IEEE80211_STYPE_DATA)) 346 skb_pull(skb, sizeof(struct ieee80211_hdr_3addr)); 347 348 datap = skb->data; 349 llc_hdr = (struct ath6kl_llc_snap_hdr *)(datap); 350 351 memset(ð_hdr, 0, sizeof(eth_hdr)); 352 eth_hdr.h_proto = llc_hdr->eth_type; 353 354 switch ((le16_to_cpu(wh.frame_control)) & 355 (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) { 356 case 0: 357 memcpy(eth_hdr.h_dest, wh.addr1, ETH_ALEN); 358 memcpy(eth_hdr.h_source, wh.addr2, ETH_ALEN); 359 break; 360 case IEEE80211_FCTL_TODS: 361 memcpy(eth_hdr.h_dest, wh.addr3, ETH_ALEN); 362 memcpy(eth_hdr.h_source, wh.addr2, ETH_ALEN); 363 break; 364 case IEEE80211_FCTL_FROMDS: 365 memcpy(eth_hdr.h_dest, wh.addr1, ETH_ALEN); 366 memcpy(eth_hdr.h_source, wh.addr3, ETH_ALEN); 367 break; 368 case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS: 369 break; 370 } 371 372 skb_pull(skb, sizeof(struct ath6kl_llc_snap_hdr)); 373 skb_push(skb, sizeof(eth_hdr)); 374 375 datap = skb->data; 376 377 memcpy(datap, ð_hdr, sizeof(eth_hdr)); 378 379 return 0; 380 } 381 382 /* 383 * Performs 802.3 to DIX encapsulation for received packets. 384 * Assumes the entire 802.3 header is contigous. 385 */ 386 int ath6kl_wmi_dot3_2_dix(struct sk_buff *skb) 387 { 388 struct ath6kl_llc_snap_hdr *llc_hdr; 389 struct ethhdr eth_hdr; 390 u8 *datap; 391 392 if (WARN_ON(skb == NULL)) 393 return -EINVAL; 394 395 datap = skb->data; 396 397 memcpy(ð_hdr, datap, sizeof(eth_hdr)); 398 399 llc_hdr = (struct ath6kl_llc_snap_hdr *) (datap + sizeof(eth_hdr)); 400 eth_hdr.h_proto = llc_hdr->eth_type; 401 402 skb_pull(skb, sizeof(struct ath6kl_llc_snap_hdr)); 403 datap = skb->data; 404 405 memcpy(datap, ð_hdr, sizeof(eth_hdr)); 406 407 return 0; 408 } 409 410 static int ath6kl_wmi_tx_complete_event_rx(u8 *datap, int len) 411 { 412 struct tx_complete_msg_v1 *msg_v1; 413 struct wmi_tx_complete_event *evt; 414 int index; 415 u16 size; 416 417 evt = (struct wmi_tx_complete_event *) datap; 418 419 ath6kl_dbg(ATH6KL_DBG_WMI, "comp: %d %d %d\n", 420 evt->num_msg, evt->msg_len, evt->msg_type); 421 422 if (!AR_DBG_LVL_CHECK(ATH6KL_DBG_WMI)) 423 return 0; 424 425 for (index = 0; index < evt->num_msg; index++) { 426 size = sizeof(struct wmi_tx_complete_event) + 427 (index * sizeof(struct tx_complete_msg_v1)); 428 msg_v1 = (struct tx_complete_msg_v1 *)(datap + size); 429 430 ath6kl_dbg(ATH6KL_DBG_WMI, "msg: %d %d %d %d\n", 431 msg_v1->status, msg_v1->pkt_id, 432 msg_v1->rate_idx, msg_v1->ack_failures); 433 } 434 435 return 0; 436 } 437 438 static int ath6kl_wmi_remain_on_chnl_event_rx(struct wmi *wmi, u8 *datap, 439 int len, struct ath6kl_vif *vif) 440 { 441 struct wmi_remain_on_chnl_event *ev; 442 u32 freq; 443 u32 dur; 444 struct ieee80211_channel *chan; 445 struct ath6kl *ar = wmi->parent_dev; 446 447 if (len < sizeof(*ev)) 448 return -EINVAL; 449 450 ev = (struct wmi_remain_on_chnl_event *) datap; 451 freq = le32_to_cpu(ev->freq); 452 dur = le32_to_cpu(ev->duration); 453 ath6kl_dbg(ATH6KL_DBG_WMI, "remain_on_chnl: freq=%u dur=%u\n", 454 freq, dur); 455 chan = ieee80211_get_channel(ar->wiphy, freq); 456 if (!chan) { 457 ath6kl_dbg(ATH6KL_DBG_WMI, "remain_on_chnl: Unknown channel " 458 "(freq=%u)\n", freq); 459 return -EINVAL; 460 } 461 cfg80211_ready_on_channel(vif->ndev, 1, chan, NL80211_CHAN_NO_HT, 462 dur, GFP_ATOMIC); 463 464 return 0; 465 } 466 467 static int ath6kl_wmi_cancel_remain_on_chnl_event_rx(struct wmi *wmi, 468 u8 *datap, int len, 469 struct ath6kl_vif *vif) 470 { 471 struct wmi_cancel_remain_on_chnl_event *ev; 472 u32 freq; 473 u32 dur; 474 struct ieee80211_channel *chan; 475 struct ath6kl *ar = wmi->parent_dev; 476 477 if (len < sizeof(*ev)) 478 return -EINVAL; 479 480 ev = (struct wmi_cancel_remain_on_chnl_event *) datap; 481 freq = le32_to_cpu(ev->freq); 482 dur = le32_to_cpu(ev->duration); 483 ath6kl_dbg(ATH6KL_DBG_WMI, "cancel_remain_on_chnl: freq=%u dur=%u " 484 "status=%u\n", freq, dur, ev->status); 485 chan = ieee80211_get_channel(ar->wiphy, freq); 486 if (!chan) { 487 ath6kl_dbg(ATH6KL_DBG_WMI, "cancel_remain_on_chnl: Unknown " 488 "channel (freq=%u)\n", freq); 489 return -EINVAL; 490 } 491 cfg80211_remain_on_channel_expired(vif->ndev, 1, chan, 492 NL80211_CHAN_NO_HT, GFP_ATOMIC); 493 494 return 0; 495 } 496 497 static int ath6kl_wmi_tx_status_event_rx(struct wmi *wmi, u8 *datap, int len, 498 struct ath6kl_vif *vif) 499 { 500 struct wmi_tx_status_event *ev; 501 u32 id; 502 503 if (len < sizeof(*ev)) 504 return -EINVAL; 505 506 ev = (struct wmi_tx_status_event *) datap; 507 id = le32_to_cpu(ev->id); 508 ath6kl_dbg(ATH6KL_DBG_WMI, "tx_status: id=%x ack_status=%u\n", 509 id, ev->ack_status); 510 if (wmi->last_mgmt_tx_frame) { 511 cfg80211_mgmt_tx_status(vif->ndev, id, 512 wmi->last_mgmt_tx_frame, 513 wmi->last_mgmt_tx_frame_len, 514 !!ev->ack_status, GFP_ATOMIC); 515 kfree(wmi->last_mgmt_tx_frame); 516 wmi->last_mgmt_tx_frame = NULL; 517 wmi->last_mgmt_tx_frame_len = 0; 518 } 519 520 return 0; 521 } 522 523 static int ath6kl_wmi_rx_probe_req_event_rx(struct wmi *wmi, u8 *datap, int len, 524 struct ath6kl_vif *vif) 525 { 526 struct wmi_p2p_rx_probe_req_event *ev; 527 u32 freq; 528 u16 dlen; 529 530 if (len < sizeof(*ev)) 531 return -EINVAL; 532 533 ev = (struct wmi_p2p_rx_probe_req_event *) datap; 534 freq = le32_to_cpu(ev->freq); 535 dlen = le16_to_cpu(ev->len); 536 if (datap + len < ev->data + dlen) { 537 ath6kl_err("invalid wmi_p2p_rx_probe_req_event: " 538 "len=%d dlen=%u\n", len, dlen); 539 return -EINVAL; 540 } 541 ath6kl_dbg(ATH6KL_DBG_WMI, "rx_probe_req: len=%u freq=%u " 542 "probe_req_report=%d\n", 543 dlen, freq, vif->probe_req_report); 544 545 if (vif->probe_req_report || vif->nw_type == AP_NETWORK) 546 cfg80211_rx_mgmt(vif->ndev, freq, ev->data, dlen, GFP_ATOMIC); 547 548 return 0; 549 } 550 551 static int ath6kl_wmi_p2p_capabilities_event_rx(u8 *datap, int len) 552 { 553 struct wmi_p2p_capabilities_event *ev; 554 u16 dlen; 555 556 if (len < sizeof(*ev)) 557 return -EINVAL; 558 559 ev = (struct wmi_p2p_capabilities_event *) datap; 560 dlen = le16_to_cpu(ev->len); 561 ath6kl_dbg(ATH6KL_DBG_WMI, "p2p_capab: len=%u\n", dlen); 562 563 return 0; 564 } 565 566 static int ath6kl_wmi_rx_action_event_rx(struct wmi *wmi, u8 *datap, int len, 567 struct ath6kl_vif *vif) 568 { 569 struct wmi_rx_action_event *ev; 570 u32 freq; 571 u16 dlen; 572 573 if (len < sizeof(*ev)) 574 return -EINVAL; 575 576 ev = (struct wmi_rx_action_event *) datap; 577 freq = le32_to_cpu(ev->freq); 578 dlen = le16_to_cpu(ev->len); 579 if (datap + len < ev->data + dlen) { 580 ath6kl_err("invalid wmi_rx_action_event: " 581 "len=%d dlen=%u\n", len, dlen); 582 return -EINVAL; 583 } 584 ath6kl_dbg(ATH6KL_DBG_WMI, "rx_action: len=%u freq=%u\n", dlen, freq); 585 cfg80211_rx_mgmt(vif->ndev, freq, ev->data, dlen, GFP_ATOMIC); 586 587 return 0; 588 } 589 590 static int ath6kl_wmi_p2p_info_event_rx(u8 *datap, int len) 591 { 592 struct wmi_p2p_info_event *ev; 593 u32 flags; 594 u16 dlen; 595 596 if (len < sizeof(*ev)) 597 return -EINVAL; 598 599 ev = (struct wmi_p2p_info_event *) datap; 600 flags = le32_to_cpu(ev->info_req_flags); 601 dlen = le16_to_cpu(ev->len); 602 ath6kl_dbg(ATH6KL_DBG_WMI, "p2p_info: flags=%x len=%d\n", flags, dlen); 603 604 if (flags & P2P_FLAG_CAPABILITIES_REQ) { 605 struct wmi_p2p_capabilities *cap; 606 if (dlen < sizeof(*cap)) 607 return -EINVAL; 608 cap = (struct wmi_p2p_capabilities *) ev->data; 609 ath6kl_dbg(ATH6KL_DBG_WMI, "p2p_info: GO Power Save = %d\n", 610 cap->go_power_save); 611 } 612 613 if (flags & P2P_FLAG_MACADDR_REQ) { 614 struct wmi_p2p_macaddr *mac; 615 if (dlen < sizeof(*mac)) 616 return -EINVAL; 617 mac = (struct wmi_p2p_macaddr *) ev->data; 618 ath6kl_dbg(ATH6KL_DBG_WMI, "p2p_info: MAC Address = %pM\n", 619 mac->mac_addr); 620 } 621 622 if (flags & P2P_FLAG_HMODEL_REQ) { 623 struct wmi_p2p_hmodel *mod; 624 if (dlen < sizeof(*mod)) 625 return -EINVAL; 626 mod = (struct wmi_p2p_hmodel *) ev->data; 627 ath6kl_dbg(ATH6KL_DBG_WMI, "p2p_info: P2P Model = %d (%s)\n", 628 mod->p2p_model, 629 mod->p2p_model ? "host" : "firmware"); 630 } 631 return 0; 632 } 633 634 static inline struct sk_buff *ath6kl_wmi_get_new_buf(u32 size) 635 { 636 struct sk_buff *skb; 637 638 skb = ath6kl_buf_alloc(size); 639 if (!skb) 640 return NULL; 641 642 skb_put(skb, size); 643 if (size) 644 memset(skb->data, 0, size); 645 646 return skb; 647 } 648 649 /* Send a "simple" wmi command -- one with no arguments */ 650 static int ath6kl_wmi_simple_cmd(struct wmi *wmi, u8 if_idx, 651 enum wmi_cmd_id cmd_id) 652 { 653 struct sk_buff *skb; 654 int ret; 655 656 skb = ath6kl_wmi_get_new_buf(0); 657 if (!skb) 658 return -ENOMEM; 659 660 ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, cmd_id, NO_SYNC_WMIFLAG); 661 662 return ret; 663 } 664 665 static int ath6kl_wmi_ready_event_rx(struct wmi *wmi, u8 *datap, int len) 666 { 667 struct wmi_ready_event_2 *ev = (struct wmi_ready_event_2 *) datap; 668 669 if (len < sizeof(struct wmi_ready_event_2)) 670 return -EINVAL; 671 672 ath6kl_ready_event(wmi->parent_dev, ev->mac_addr, 673 le32_to_cpu(ev->sw_version), 674 le32_to_cpu(ev->abi_version)); 675 676 return 0; 677 } 678 679 /* 680 * Mechanism to modify the roaming behavior in the firmware. The lower rssi 681 * at which the station has to roam can be passed with 682 * WMI_SET_LRSSI_SCAN_PARAMS. Subtract 96 from RSSI to get the signal level 683 * in dBm. 684 */ 685 int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi) 686 { 687 struct sk_buff *skb; 688 struct roam_ctrl_cmd *cmd; 689 690 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 691 if (!skb) 692 return -ENOMEM; 693 694 cmd = (struct roam_ctrl_cmd *) skb->data; 695 696 cmd->info.params.lrssi_scan_period = cpu_to_le16(DEF_LRSSI_SCAN_PERIOD); 697 cmd->info.params.lrssi_scan_threshold = a_cpu_to_sle16(lrssi + 698 DEF_SCAN_FOR_ROAM_INTVL); 699 cmd->info.params.lrssi_roam_threshold = a_cpu_to_sle16(lrssi); 700 cmd->info.params.roam_rssi_floor = DEF_LRSSI_ROAM_FLOOR; 701 cmd->roam_ctrl = WMI_SET_LRSSI_SCAN_PARAMS; 702 703 ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_SET_ROAM_CTRL_CMDID, 704 NO_SYNC_WMIFLAG); 705 706 return 0; 707 } 708 709 int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid) 710 { 711 struct sk_buff *skb; 712 struct roam_ctrl_cmd *cmd; 713 714 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 715 if (!skb) 716 return -ENOMEM; 717 718 cmd = (struct roam_ctrl_cmd *) skb->data; 719 memset(cmd, 0, sizeof(*cmd)); 720 721 memcpy(cmd->info.bssid, bssid, ETH_ALEN); 722 cmd->roam_ctrl = WMI_FORCE_ROAM; 723 724 ath6kl_dbg(ATH6KL_DBG_WMI, "force roam to %pM\n", bssid); 725 return ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_SET_ROAM_CTRL_CMDID, 726 NO_SYNC_WMIFLAG); 727 } 728 729 int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode) 730 { 731 struct sk_buff *skb; 732 struct roam_ctrl_cmd *cmd; 733 734 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 735 if (!skb) 736 return -ENOMEM; 737 738 cmd = (struct roam_ctrl_cmd *) skb->data; 739 memset(cmd, 0, sizeof(*cmd)); 740 741 cmd->info.roam_mode = mode; 742 cmd->roam_ctrl = WMI_SET_ROAM_MODE; 743 744 ath6kl_dbg(ATH6KL_DBG_WMI, "set roam mode %d\n", mode); 745 return ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_SET_ROAM_CTRL_CMDID, 746 NO_SYNC_WMIFLAG); 747 } 748 749 static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len, 750 struct ath6kl_vif *vif) 751 { 752 struct wmi_connect_event *ev; 753 u8 *pie, *peie; 754 755 if (len < sizeof(struct wmi_connect_event)) 756 return -EINVAL; 757 758 ev = (struct wmi_connect_event *) datap; 759 760 if (vif->nw_type == AP_NETWORK) { 761 /* AP mode start/STA connected event */ 762 struct net_device *dev = vif->ndev; 763 if (memcmp(dev->dev_addr, ev->u.ap_bss.bssid, ETH_ALEN) == 0) { 764 ath6kl_dbg(ATH6KL_DBG_WMI, "%s: freq %d bssid %pM " 765 "(AP started)\n", 766 __func__, le16_to_cpu(ev->u.ap_bss.ch), 767 ev->u.ap_bss.bssid); 768 ath6kl_connect_ap_mode_bss( 769 vif, le16_to_cpu(ev->u.ap_bss.ch)); 770 } else { 771 ath6kl_dbg(ATH6KL_DBG_WMI, "%s: aid %u mac_addr %pM " 772 "auth=%u keymgmt=%u cipher=%u apsd_info=%u " 773 "(STA connected)\n", 774 __func__, ev->u.ap_sta.aid, 775 ev->u.ap_sta.mac_addr, 776 ev->u.ap_sta.auth, 777 ev->u.ap_sta.keymgmt, 778 le16_to_cpu(ev->u.ap_sta.cipher), 779 ev->u.ap_sta.apsd_info); 780 ath6kl_connect_ap_mode_sta( 781 vif, ev->u.ap_sta.aid, ev->u.ap_sta.mac_addr, 782 ev->u.ap_sta.keymgmt, 783 le16_to_cpu(ev->u.ap_sta.cipher), 784 ev->u.ap_sta.auth, ev->assoc_req_len, 785 ev->assoc_info + ev->beacon_ie_len); 786 } 787 return 0; 788 } 789 790 /* STA/IBSS mode connection event */ 791 792 ath6kl_dbg(ATH6KL_DBG_WMI, 793 "wmi event connect freq %d bssid %pM listen_intvl %d beacon_intvl %d type %d\n", 794 le16_to_cpu(ev->u.sta.ch), ev->u.sta.bssid, 795 le16_to_cpu(ev->u.sta.listen_intvl), 796 le16_to_cpu(ev->u.sta.beacon_intvl), 797 le32_to_cpu(ev->u.sta.nw_type)); 798 799 /* Start of assoc rsp IEs */ 800 pie = ev->assoc_info + ev->beacon_ie_len + 801 ev->assoc_req_len + (sizeof(u16) * 3); /* capinfo, status, aid */ 802 803 /* End of assoc rsp IEs */ 804 peie = ev->assoc_info + ev->beacon_ie_len + ev->assoc_req_len + 805 ev->assoc_resp_len; 806 807 while (pie < peie) { 808 switch (*pie) { 809 case WLAN_EID_VENDOR_SPECIFIC: 810 if (pie[1] > 3 && pie[2] == 0x00 && pie[3] == 0x50 && 811 pie[4] == 0xf2 && pie[5] == WMM_OUI_TYPE) { 812 /* WMM OUT (00:50:F2) */ 813 if (pie[1] > 5 814 && pie[6] == WMM_PARAM_OUI_SUBTYPE) 815 wmi->is_wmm_enabled = true; 816 } 817 break; 818 } 819 820 if (wmi->is_wmm_enabled) 821 break; 822 823 pie += pie[1] + 2; 824 } 825 826 ath6kl_connect_event(vif, le16_to_cpu(ev->u.sta.ch), 827 ev->u.sta.bssid, 828 le16_to_cpu(ev->u.sta.listen_intvl), 829 le16_to_cpu(ev->u.sta.beacon_intvl), 830 le32_to_cpu(ev->u.sta.nw_type), 831 ev->beacon_ie_len, ev->assoc_req_len, 832 ev->assoc_resp_len, ev->assoc_info); 833 834 return 0; 835 } 836 837 static struct country_code_to_enum_rd * 838 ath6kl_regd_find_country(u16 countryCode) 839 { 840 int i; 841 842 for (i = 0; i < ARRAY_SIZE(allCountries); i++) { 843 if (allCountries[i].countryCode == countryCode) 844 return &allCountries[i]; 845 } 846 847 return NULL; 848 } 849 850 static struct reg_dmn_pair_mapping * 851 ath6kl_get_regpair(u16 regdmn) 852 { 853 int i; 854 855 if (regdmn == NO_ENUMRD) 856 return NULL; 857 858 for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) { 859 if (regDomainPairs[i].regDmnEnum == regdmn) 860 return ®DomainPairs[i]; 861 } 862 863 return NULL; 864 } 865 866 static struct country_code_to_enum_rd * 867 ath6kl_regd_find_country_by_rd(u16 regdmn) 868 { 869 int i; 870 871 for (i = 0; i < ARRAY_SIZE(allCountries); i++) { 872 if (allCountries[i].regDmnEnum == regdmn) 873 return &allCountries[i]; 874 } 875 876 return NULL; 877 } 878 879 static void ath6kl_wmi_regdomain_event(struct wmi *wmi, u8 *datap, int len) 880 { 881 882 struct ath6kl_wmi_regdomain *ev; 883 struct country_code_to_enum_rd *country = NULL; 884 struct reg_dmn_pair_mapping *regpair = NULL; 885 char alpha2[2]; 886 u32 reg_code; 887 888 ev = (struct ath6kl_wmi_regdomain *) datap; 889 reg_code = le32_to_cpu(ev->reg_code); 890 891 if ((reg_code >> ATH6KL_COUNTRY_RD_SHIFT) & COUNTRY_ERD_FLAG) 892 country = ath6kl_regd_find_country((u16) reg_code); 893 else if (!(((u16) reg_code & WORLD_SKU_MASK) == WORLD_SKU_PREFIX)) { 894 895 regpair = ath6kl_get_regpair((u16) reg_code); 896 country = ath6kl_regd_find_country_by_rd((u16) reg_code); 897 ath6kl_dbg(ATH6KL_DBG_WMI, "Regpair used: 0x%0x\n", 898 regpair->regDmnEnum); 899 } 900 901 if (country) { 902 alpha2[0] = country->isoName[0]; 903 alpha2[1] = country->isoName[1]; 904 905 regulatory_hint(wmi->parent_dev->wiphy, alpha2); 906 907 ath6kl_dbg(ATH6KL_DBG_WMI, "Country alpha2 being used: %c%c\n", 908 alpha2[0], alpha2[1]); 909 } 910 } 911 912 static int ath6kl_wmi_disconnect_event_rx(struct wmi *wmi, u8 *datap, int len, 913 struct ath6kl_vif *vif) 914 { 915 struct wmi_disconnect_event *ev; 916 wmi->traffic_class = 100; 917 918 if (len < sizeof(struct wmi_disconnect_event)) 919 return -EINVAL; 920 921 ev = (struct wmi_disconnect_event *) datap; 922 923 ath6kl_dbg(ATH6KL_DBG_WMI, 924 "wmi event disconnect proto_reason %d bssid %pM wmi_reason %d assoc_resp_len %d\n", 925 le16_to_cpu(ev->proto_reason_status), ev->bssid, 926 ev->disconn_reason, ev->assoc_resp_len); 927 928 wmi->is_wmm_enabled = false; 929 930 ath6kl_disconnect_event(vif, ev->disconn_reason, 931 ev->bssid, ev->assoc_resp_len, ev->assoc_info, 932 le16_to_cpu(ev->proto_reason_status)); 933 934 return 0; 935 } 936 937 static int ath6kl_wmi_peer_node_event_rx(struct wmi *wmi, u8 *datap, int len) 938 { 939 struct wmi_peer_node_event *ev; 940 941 if (len < sizeof(struct wmi_peer_node_event)) 942 return -EINVAL; 943 944 ev = (struct wmi_peer_node_event *) datap; 945 946 if (ev->event_code == PEER_NODE_JOIN_EVENT) 947 ath6kl_dbg(ATH6KL_DBG_WMI, "joined node with mac addr: %pM\n", 948 ev->peer_mac_addr); 949 else if (ev->event_code == PEER_NODE_LEAVE_EVENT) 950 ath6kl_dbg(ATH6KL_DBG_WMI, "left node with mac addr: %pM\n", 951 ev->peer_mac_addr); 952 953 return 0; 954 } 955 956 static int ath6kl_wmi_tkip_micerr_event_rx(struct wmi *wmi, u8 *datap, int len, 957 struct ath6kl_vif *vif) 958 { 959 struct wmi_tkip_micerr_event *ev; 960 961 if (len < sizeof(struct wmi_tkip_micerr_event)) 962 return -EINVAL; 963 964 ev = (struct wmi_tkip_micerr_event *) datap; 965 966 ath6kl_tkip_micerr_event(vif, ev->key_id, ev->is_mcast); 967 968 return 0; 969 } 970 971 static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len, 972 struct ath6kl_vif *vif) 973 { 974 struct wmi_bss_info_hdr2 *bih; 975 u8 *buf; 976 struct ieee80211_channel *channel; 977 struct ath6kl *ar = wmi->parent_dev; 978 struct ieee80211_mgmt *mgmt; 979 struct cfg80211_bss *bss; 980 981 if (len <= sizeof(struct wmi_bss_info_hdr2)) 982 return -EINVAL; 983 984 bih = (struct wmi_bss_info_hdr2 *) datap; 985 buf = datap + sizeof(struct wmi_bss_info_hdr2); 986 len -= sizeof(struct wmi_bss_info_hdr2); 987 988 ath6kl_dbg(ATH6KL_DBG_WMI, 989 "bss info evt - ch %u, snr %d, rssi %d, bssid \"%pM\" " 990 "frame_type=%d\n", 991 bih->ch, bih->snr, bih->snr - 95, bih->bssid, 992 bih->frame_type); 993 994 if (bih->frame_type != BEACON_FTYPE && 995 bih->frame_type != PROBERESP_FTYPE) 996 return 0; /* Only update BSS table for now */ 997 998 if (bih->frame_type == BEACON_FTYPE && 999 test_bit(CLEAR_BSSFILTER_ON_BEACON, &vif->flags)) { 1000 clear_bit(CLEAR_BSSFILTER_ON_BEACON, &vif->flags); 1001 ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx, 1002 NONE_BSS_FILTER, 0); 1003 } 1004 1005 channel = ieee80211_get_channel(ar->wiphy, le16_to_cpu(bih->ch)); 1006 if (channel == NULL) 1007 return -EINVAL; 1008 1009 if (len < 8 + 2 + 2) 1010 return -EINVAL; 1011 1012 if (bih->frame_type == BEACON_FTYPE && test_bit(CONNECTED, &vif->flags) 1013 && memcmp(bih->bssid, vif->bssid, ETH_ALEN) == 0) { 1014 const u8 *tim; 1015 tim = cfg80211_find_ie(WLAN_EID_TIM, buf + 8 + 2 + 2, 1016 len - 8 - 2 - 2); 1017 if (tim && tim[1] >= 2) { 1018 vif->assoc_bss_dtim_period = tim[3]; 1019 set_bit(DTIM_PERIOD_AVAIL, &vif->flags); 1020 } 1021 } 1022 1023 /* 1024 * In theory, use of cfg80211_inform_bss() would be more natural here 1025 * since we do not have the full frame. However, at least for now, 1026 * cfg80211 can only distinguish Beacon and Probe Response frames from 1027 * each other when using cfg80211_inform_bss_frame(), so let's build a 1028 * fake IEEE 802.11 header to be able to take benefit of this. 1029 */ 1030 mgmt = kmalloc(24 + len, GFP_ATOMIC); 1031 if (mgmt == NULL) 1032 return -EINVAL; 1033 1034 if (bih->frame_type == BEACON_FTYPE) { 1035 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 1036 IEEE80211_STYPE_BEACON); 1037 memset(mgmt->da, 0xff, ETH_ALEN); 1038 } else { 1039 struct net_device *dev = vif->ndev; 1040 1041 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 1042 IEEE80211_STYPE_PROBE_RESP); 1043 memcpy(mgmt->da, dev->dev_addr, ETH_ALEN); 1044 } 1045 mgmt->duration = cpu_to_le16(0); 1046 memcpy(mgmt->sa, bih->bssid, ETH_ALEN); 1047 memcpy(mgmt->bssid, bih->bssid, ETH_ALEN); 1048 mgmt->seq_ctrl = cpu_to_le16(0); 1049 1050 memcpy(&mgmt->u.beacon, buf, len); 1051 1052 bss = cfg80211_inform_bss_frame(ar->wiphy, channel, mgmt, 1053 24 + len, (bih->snr - 95) * 100, 1054 GFP_ATOMIC); 1055 kfree(mgmt); 1056 if (bss == NULL) 1057 return -ENOMEM; 1058 cfg80211_put_bss(bss); 1059 1060 return 0; 1061 } 1062 1063 /* Inactivity timeout of a fatpipe(pstream) at the target */ 1064 static int ath6kl_wmi_pstream_timeout_event_rx(struct wmi *wmi, u8 *datap, 1065 int len) 1066 { 1067 struct wmi_pstream_timeout_event *ev; 1068 1069 if (len < sizeof(struct wmi_pstream_timeout_event)) 1070 return -EINVAL; 1071 1072 ev = (struct wmi_pstream_timeout_event *) datap; 1073 1074 /* 1075 * When the pstream (fat pipe == AC) timesout, it means there were 1076 * no thinStreams within this pstream & it got implicitly created 1077 * due to data flow on this AC. We start the inactivity timer only 1078 * for implicitly created pstream. Just reset the host state. 1079 */ 1080 spin_lock_bh(&wmi->lock); 1081 wmi->stream_exist_for_ac[ev->traffic_class] = 0; 1082 wmi->fat_pipe_exist &= ~(1 << ev->traffic_class); 1083 spin_unlock_bh(&wmi->lock); 1084 1085 /* Indicate inactivity to driver layer for this fatpipe (pstream) */ 1086 ath6kl_indicate_tx_activity(wmi->parent_dev, ev->traffic_class, false); 1087 1088 return 0; 1089 } 1090 1091 static int ath6kl_wmi_bitrate_reply_rx(struct wmi *wmi, u8 *datap, int len) 1092 { 1093 struct wmi_bit_rate_reply *reply; 1094 s32 rate; 1095 u32 sgi, index; 1096 1097 if (len < sizeof(struct wmi_bit_rate_reply)) 1098 return -EINVAL; 1099 1100 reply = (struct wmi_bit_rate_reply *) datap; 1101 1102 ath6kl_dbg(ATH6KL_DBG_WMI, "rateindex %d\n", reply->rate_index); 1103 1104 if (reply->rate_index == (s8) RATE_AUTO) { 1105 rate = RATE_AUTO; 1106 } else { 1107 index = reply->rate_index & 0x7f; 1108 sgi = (reply->rate_index & 0x80) ? 1 : 0; 1109 rate = wmi_rate_tbl[index][sgi]; 1110 } 1111 1112 ath6kl_wakeup_event(wmi->parent_dev); 1113 1114 return 0; 1115 } 1116 1117 static int ath6kl_wmi_tcmd_test_report_rx(struct wmi *wmi, u8 *datap, int len) 1118 { 1119 ath6kl_tm_rx_report_event(wmi->parent_dev, datap, len); 1120 1121 return 0; 1122 } 1123 1124 static int ath6kl_wmi_ratemask_reply_rx(struct wmi *wmi, u8 *datap, int len) 1125 { 1126 if (len < sizeof(struct wmi_fix_rates_reply)) 1127 return -EINVAL; 1128 1129 ath6kl_wakeup_event(wmi->parent_dev); 1130 1131 return 0; 1132 } 1133 1134 static int ath6kl_wmi_ch_list_reply_rx(struct wmi *wmi, u8 *datap, int len) 1135 { 1136 if (len < sizeof(struct wmi_channel_list_reply)) 1137 return -EINVAL; 1138 1139 ath6kl_wakeup_event(wmi->parent_dev); 1140 1141 return 0; 1142 } 1143 1144 static int ath6kl_wmi_tx_pwr_reply_rx(struct wmi *wmi, u8 *datap, int len) 1145 { 1146 struct wmi_tx_pwr_reply *reply; 1147 1148 if (len < sizeof(struct wmi_tx_pwr_reply)) 1149 return -EINVAL; 1150 1151 reply = (struct wmi_tx_pwr_reply *) datap; 1152 ath6kl_txpwr_rx_evt(wmi->parent_dev, reply->dbM); 1153 1154 return 0; 1155 } 1156 1157 static int ath6kl_wmi_keepalive_reply_rx(struct wmi *wmi, u8 *datap, int len) 1158 { 1159 if (len < sizeof(struct wmi_get_keepalive_cmd)) 1160 return -EINVAL; 1161 1162 ath6kl_wakeup_event(wmi->parent_dev); 1163 1164 return 0; 1165 } 1166 1167 static int ath6kl_wmi_scan_complete_rx(struct wmi *wmi, u8 *datap, int len, 1168 struct ath6kl_vif *vif) 1169 { 1170 struct wmi_scan_complete_event *ev; 1171 1172 ev = (struct wmi_scan_complete_event *) datap; 1173 1174 ath6kl_scan_complete_evt(vif, a_sle32_to_cpu(ev->status)); 1175 wmi->is_probe_ssid = false; 1176 1177 return 0; 1178 } 1179 1180 static int ath6kl_wmi_neighbor_report_event_rx(struct wmi *wmi, u8 *datap, 1181 int len, struct ath6kl_vif *vif) 1182 { 1183 struct wmi_neighbor_report_event *ev; 1184 u8 i; 1185 1186 if (len < sizeof(*ev)) 1187 return -EINVAL; 1188 ev = (struct wmi_neighbor_report_event *) datap; 1189 if (sizeof(*ev) + ev->num_neighbors * sizeof(struct wmi_neighbor_info) 1190 > len) { 1191 ath6kl_dbg(ATH6KL_DBG_WMI, "truncated neighbor event " 1192 "(num=%d len=%d)\n", ev->num_neighbors, len); 1193 return -EINVAL; 1194 } 1195 for (i = 0; i < ev->num_neighbors; i++) { 1196 ath6kl_dbg(ATH6KL_DBG_WMI, "neighbor %d/%d - %pM 0x%x\n", 1197 i + 1, ev->num_neighbors, ev->neighbor[i].bssid, 1198 ev->neighbor[i].bss_flags); 1199 cfg80211_pmksa_candidate_notify(vif->ndev, i, 1200 ev->neighbor[i].bssid, 1201 !!(ev->neighbor[i].bss_flags & 1202 WMI_PREAUTH_CAPABLE_BSS), 1203 GFP_ATOMIC); 1204 } 1205 1206 return 0; 1207 } 1208 1209 /* 1210 * Target is reporting a programming error. This is for 1211 * developer aid only. Target only checks a few common violations 1212 * and it is responsibility of host to do all error checking. 1213 * Behavior of target after wmi error event is undefined. 1214 * A reset is recommended. 1215 */ 1216 static int ath6kl_wmi_error_event_rx(struct wmi *wmi, u8 *datap, int len) 1217 { 1218 const char *type = "unknown error"; 1219 struct wmi_cmd_error_event *ev; 1220 ev = (struct wmi_cmd_error_event *) datap; 1221 1222 switch (ev->err_code) { 1223 case INVALID_PARAM: 1224 type = "invalid parameter"; 1225 break; 1226 case ILLEGAL_STATE: 1227 type = "invalid state"; 1228 break; 1229 case INTERNAL_ERROR: 1230 type = "internal error"; 1231 break; 1232 } 1233 1234 ath6kl_dbg(ATH6KL_DBG_WMI, "programming error, cmd=%d %s\n", 1235 ev->cmd_id, type); 1236 1237 return 0; 1238 } 1239 1240 static int ath6kl_wmi_stats_event_rx(struct wmi *wmi, u8 *datap, int len, 1241 struct ath6kl_vif *vif) 1242 { 1243 ath6kl_tgt_stats_event(vif, datap, len); 1244 1245 return 0; 1246 } 1247 1248 static u8 ath6kl_wmi_get_upper_threshold(s16 rssi, 1249 struct sq_threshold_params *sq_thresh, 1250 u32 size) 1251 { 1252 u32 index; 1253 u8 threshold = (u8) sq_thresh->upper_threshold[size - 1]; 1254 1255 /* The list is already in sorted order. Get the next lower value */ 1256 for (index = 0; index < size; index++) { 1257 if (rssi < sq_thresh->upper_threshold[index]) { 1258 threshold = (u8) sq_thresh->upper_threshold[index]; 1259 break; 1260 } 1261 } 1262 1263 return threshold; 1264 } 1265 1266 static u8 ath6kl_wmi_get_lower_threshold(s16 rssi, 1267 struct sq_threshold_params *sq_thresh, 1268 u32 size) 1269 { 1270 u32 index; 1271 u8 threshold = (u8) sq_thresh->lower_threshold[size - 1]; 1272 1273 /* The list is already in sorted order. Get the next lower value */ 1274 for (index = 0; index < size; index++) { 1275 if (rssi > sq_thresh->lower_threshold[index]) { 1276 threshold = (u8) sq_thresh->lower_threshold[index]; 1277 break; 1278 } 1279 } 1280 1281 return threshold; 1282 } 1283 1284 static int ath6kl_wmi_send_rssi_threshold_params(struct wmi *wmi, 1285 struct wmi_rssi_threshold_params_cmd *rssi_cmd) 1286 { 1287 struct sk_buff *skb; 1288 struct wmi_rssi_threshold_params_cmd *cmd; 1289 1290 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 1291 if (!skb) 1292 return -ENOMEM; 1293 1294 cmd = (struct wmi_rssi_threshold_params_cmd *) skb->data; 1295 memcpy(cmd, rssi_cmd, sizeof(struct wmi_rssi_threshold_params_cmd)); 1296 1297 return ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_RSSI_THRESHOLD_PARAMS_CMDID, 1298 NO_SYNC_WMIFLAG); 1299 } 1300 1301 static int ath6kl_wmi_rssi_threshold_event_rx(struct wmi *wmi, u8 *datap, 1302 int len) 1303 { 1304 struct wmi_rssi_threshold_event *reply; 1305 struct wmi_rssi_threshold_params_cmd cmd; 1306 struct sq_threshold_params *sq_thresh; 1307 enum wmi_rssi_threshold_val new_threshold; 1308 u8 upper_rssi_threshold, lower_rssi_threshold; 1309 s16 rssi; 1310 int ret; 1311 1312 if (len < sizeof(struct wmi_rssi_threshold_event)) 1313 return -EINVAL; 1314 1315 reply = (struct wmi_rssi_threshold_event *) datap; 1316 new_threshold = (enum wmi_rssi_threshold_val) reply->range; 1317 rssi = a_sle16_to_cpu(reply->rssi); 1318 1319 sq_thresh = &wmi->sq_threshld[SIGNAL_QUALITY_METRICS_RSSI]; 1320 1321 /* 1322 * Identify the threshold breached and communicate that to the app. 1323 * After that install a new set of thresholds based on the signal 1324 * quality reported by the target 1325 */ 1326 if (new_threshold) { 1327 /* Upper threshold breached */ 1328 if (rssi < sq_thresh->upper_threshold[0]) { 1329 ath6kl_dbg(ATH6KL_DBG_WMI, 1330 "spurious upper rssi threshold event: %d\n", 1331 rssi); 1332 } else if ((rssi < sq_thresh->upper_threshold[1]) && 1333 (rssi >= sq_thresh->upper_threshold[0])) { 1334 new_threshold = WMI_RSSI_THRESHOLD1_ABOVE; 1335 } else if ((rssi < sq_thresh->upper_threshold[2]) && 1336 (rssi >= sq_thresh->upper_threshold[1])) { 1337 new_threshold = WMI_RSSI_THRESHOLD2_ABOVE; 1338 } else if ((rssi < sq_thresh->upper_threshold[3]) && 1339 (rssi >= sq_thresh->upper_threshold[2])) { 1340 new_threshold = WMI_RSSI_THRESHOLD3_ABOVE; 1341 } else if ((rssi < sq_thresh->upper_threshold[4]) && 1342 (rssi >= sq_thresh->upper_threshold[3])) { 1343 new_threshold = WMI_RSSI_THRESHOLD4_ABOVE; 1344 } else if ((rssi < sq_thresh->upper_threshold[5]) && 1345 (rssi >= sq_thresh->upper_threshold[4])) { 1346 new_threshold = WMI_RSSI_THRESHOLD5_ABOVE; 1347 } else if (rssi >= sq_thresh->upper_threshold[5]) { 1348 new_threshold = WMI_RSSI_THRESHOLD6_ABOVE; 1349 } 1350 } else { 1351 /* Lower threshold breached */ 1352 if (rssi > sq_thresh->lower_threshold[0]) { 1353 ath6kl_dbg(ATH6KL_DBG_WMI, 1354 "spurious lower rssi threshold event: %d %d\n", 1355 rssi, sq_thresh->lower_threshold[0]); 1356 } else if ((rssi > sq_thresh->lower_threshold[1]) && 1357 (rssi <= sq_thresh->lower_threshold[0])) { 1358 new_threshold = WMI_RSSI_THRESHOLD6_BELOW; 1359 } else if ((rssi > sq_thresh->lower_threshold[2]) && 1360 (rssi <= sq_thresh->lower_threshold[1])) { 1361 new_threshold = WMI_RSSI_THRESHOLD5_BELOW; 1362 } else if ((rssi > sq_thresh->lower_threshold[3]) && 1363 (rssi <= sq_thresh->lower_threshold[2])) { 1364 new_threshold = WMI_RSSI_THRESHOLD4_BELOW; 1365 } else if ((rssi > sq_thresh->lower_threshold[4]) && 1366 (rssi <= sq_thresh->lower_threshold[3])) { 1367 new_threshold = WMI_RSSI_THRESHOLD3_BELOW; 1368 } else if ((rssi > sq_thresh->lower_threshold[5]) && 1369 (rssi <= sq_thresh->lower_threshold[4])) { 1370 new_threshold = WMI_RSSI_THRESHOLD2_BELOW; 1371 } else if (rssi <= sq_thresh->lower_threshold[5]) { 1372 new_threshold = WMI_RSSI_THRESHOLD1_BELOW; 1373 } 1374 } 1375 1376 /* Calculate and install the next set of thresholds */ 1377 lower_rssi_threshold = ath6kl_wmi_get_lower_threshold(rssi, sq_thresh, 1378 sq_thresh->lower_threshold_valid_count); 1379 upper_rssi_threshold = ath6kl_wmi_get_upper_threshold(rssi, sq_thresh, 1380 sq_thresh->upper_threshold_valid_count); 1381 1382 /* Issue a wmi command to install the thresholds */ 1383 cmd.thresh_above1_val = a_cpu_to_sle16(upper_rssi_threshold); 1384 cmd.thresh_below1_val = a_cpu_to_sle16(lower_rssi_threshold); 1385 cmd.weight = sq_thresh->weight; 1386 cmd.poll_time = cpu_to_le32(sq_thresh->polling_interval); 1387 1388 ret = ath6kl_wmi_send_rssi_threshold_params(wmi, &cmd); 1389 if (ret) { 1390 ath6kl_err("unable to configure rssi thresholds\n"); 1391 return -EIO; 1392 } 1393 1394 return 0; 1395 } 1396 1397 static int ath6kl_wmi_cac_event_rx(struct wmi *wmi, u8 *datap, int len, 1398 struct ath6kl_vif *vif) 1399 { 1400 struct wmi_cac_event *reply; 1401 struct ieee80211_tspec_ie *ts; 1402 u16 active_tsids, tsinfo; 1403 u8 tsid, index; 1404 u8 ts_id; 1405 1406 if (len < sizeof(struct wmi_cac_event)) 1407 return -EINVAL; 1408 1409 reply = (struct wmi_cac_event *) datap; 1410 1411 if ((reply->cac_indication == CAC_INDICATION_ADMISSION_RESP) && 1412 (reply->status_code != IEEE80211_TSPEC_STATUS_ADMISS_ACCEPTED)) { 1413 1414 ts = (struct ieee80211_tspec_ie *) &(reply->tspec_suggestion); 1415 tsinfo = le16_to_cpu(ts->tsinfo); 1416 tsid = (tsinfo >> IEEE80211_WMM_IE_TSPEC_TID_SHIFT) & 1417 IEEE80211_WMM_IE_TSPEC_TID_MASK; 1418 1419 ath6kl_wmi_delete_pstream_cmd(wmi, vif->fw_vif_idx, 1420 reply->ac, tsid); 1421 } else if (reply->cac_indication == CAC_INDICATION_NO_RESP) { 1422 /* 1423 * Following assumes that there is only one outstanding 1424 * ADDTS request when this event is received 1425 */ 1426 spin_lock_bh(&wmi->lock); 1427 active_tsids = wmi->stream_exist_for_ac[reply->ac]; 1428 spin_unlock_bh(&wmi->lock); 1429 1430 for (index = 0; index < sizeof(active_tsids) * 8; index++) { 1431 if ((active_tsids >> index) & 1) 1432 break; 1433 } 1434 if (index < (sizeof(active_tsids) * 8)) 1435 ath6kl_wmi_delete_pstream_cmd(wmi, vif->fw_vif_idx, 1436 reply->ac, index); 1437 } 1438 1439 /* 1440 * Clear active tsids and Add missing handling 1441 * for delete qos stream from AP 1442 */ 1443 else if (reply->cac_indication == CAC_INDICATION_DELETE) { 1444 1445 ts = (struct ieee80211_tspec_ie *) &(reply->tspec_suggestion); 1446 tsinfo = le16_to_cpu(ts->tsinfo); 1447 ts_id = ((tsinfo >> IEEE80211_WMM_IE_TSPEC_TID_SHIFT) & 1448 IEEE80211_WMM_IE_TSPEC_TID_MASK); 1449 1450 spin_lock_bh(&wmi->lock); 1451 wmi->stream_exist_for_ac[reply->ac] &= ~(1 << ts_id); 1452 active_tsids = wmi->stream_exist_for_ac[reply->ac]; 1453 spin_unlock_bh(&wmi->lock); 1454 1455 /* Indicate stream inactivity to driver layer only if all tsids 1456 * within this AC are deleted. 1457 */ 1458 if (!active_tsids) { 1459 ath6kl_indicate_tx_activity(wmi->parent_dev, reply->ac, 1460 false); 1461 wmi->fat_pipe_exist &= ~(1 << reply->ac); 1462 } 1463 } 1464 1465 return 0; 1466 } 1467 1468 static int ath6kl_wmi_send_snr_threshold_params(struct wmi *wmi, 1469 struct wmi_snr_threshold_params_cmd *snr_cmd) 1470 { 1471 struct sk_buff *skb; 1472 struct wmi_snr_threshold_params_cmd *cmd; 1473 1474 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 1475 if (!skb) 1476 return -ENOMEM; 1477 1478 cmd = (struct wmi_snr_threshold_params_cmd *) skb->data; 1479 memcpy(cmd, snr_cmd, sizeof(struct wmi_snr_threshold_params_cmd)); 1480 1481 return ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_SNR_THRESHOLD_PARAMS_CMDID, 1482 NO_SYNC_WMIFLAG); 1483 } 1484 1485 static int ath6kl_wmi_snr_threshold_event_rx(struct wmi *wmi, u8 *datap, 1486 int len) 1487 { 1488 struct wmi_snr_threshold_event *reply; 1489 struct sq_threshold_params *sq_thresh; 1490 struct wmi_snr_threshold_params_cmd cmd; 1491 enum wmi_snr_threshold_val new_threshold; 1492 u8 upper_snr_threshold, lower_snr_threshold; 1493 s16 snr; 1494 int ret; 1495 1496 if (len < sizeof(struct wmi_snr_threshold_event)) 1497 return -EINVAL; 1498 1499 reply = (struct wmi_snr_threshold_event *) datap; 1500 1501 new_threshold = (enum wmi_snr_threshold_val) reply->range; 1502 snr = reply->snr; 1503 1504 sq_thresh = &wmi->sq_threshld[SIGNAL_QUALITY_METRICS_SNR]; 1505 1506 /* 1507 * Identify the threshold breached and communicate that to the app. 1508 * After that install a new set of thresholds based on the signal 1509 * quality reported by the target. 1510 */ 1511 if (new_threshold) { 1512 /* Upper threshold breached */ 1513 if (snr < sq_thresh->upper_threshold[0]) { 1514 ath6kl_dbg(ATH6KL_DBG_WMI, 1515 "spurious upper snr threshold event: %d\n", 1516 snr); 1517 } else if ((snr < sq_thresh->upper_threshold[1]) && 1518 (snr >= sq_thresh->upper_threshold[0])) { 1519 new_threshold = WMI_SNR_THRESHOLD1_ABOVE; 1520 } else if ((snr < sq_thresh->upper_threshold[2]) && 1521 (snr >= sq_thresh->upper_threshold[1])) { 1522 new_threshold = WMI_SNR_THRESHOLD2_ABOVE; 1523 } else if ((snr < sq_thresh->upper_threshold[3]) && 1524 (snr >= sq_thresh->upper_threshold[2])) { 1525 new_threshold = WMI_SNR_THRESHOLD3_ABOVE; 1526 } else if (snr >= sq_thresh->upper_threshold[3]) { 1527 new_threshold = WMI_SNR_THRESHOLD4_ABOVE; 1528 } 1529 } else { 1530 /* Lower threshold breached */ 1531 if (snr > sq_thresh->lower_threshold[0]) { 1532 ath6kl_dbg(ATH6KL_DBG_WMI, 1533 "spurious lower snr threshold event: %d\n", 1534 sq_thresh->lower_threshold[0]); 1535 } else if ((snr > sq_thresh->lower_threshold[1]) && 1536 (snr <= sq_thresh->lower_threshold[0])) { 1537 new_threshold = WMI_SNR_THRESHOLD4_BELOW; 1538 } else if ((snr > sq_thresh->lower_threshold[2]) && 1539 (snr <= sq_thresh->lower_threshold[1])) { 1540 new_threshold = WMI_SNR_THRESHOLD3_BELOW; 1541 } else if ((snr > sq_thresh->lower_threshold[3]) && 1542 (snr <= sq_thresh->lower_threshold[2])) { 1543 new_threshold = WMI_SNR_THRESHOLD2_BELOW; 1544 } else if (snr <= sq_thresh->lower_threshold[3]) { 1545 new_threshold = WMI_SNR_THRESHOLD1_BELOW; 1546 } 1547 } 1548 1549 /* Calculate and install the next set of thresholds */ 1550 lower_snr_threshold = ath6kl_wmi_get_lower_threshold(snr, sq_thresh, 1551 sq_thresh->lower_threshold_valid_count); 1552 upper_snr_threshold = ath6kl_wmi_get_upper_threshold(snr, sq_thresh, 1553 sq_thresh->upper_threshold_valid_count); 1554 1555 /* Issue a wmi command to install the thresholds */ 1556 cmd.thresh_above1_val = upper_snr_threshold; 1557 cmd.thresh_below1_val = lower_snr_threshold; 1558 cmd.weight = sq_thresh->weight; 1559 cmd.poll_time = cpu_to_le32(sq_thresh->polling_interval); 1560 1561 ath6kl_dbg(ATH6KL_DBG_WMI, 1562 "snr: %d, threshold: %d, lower: %d, upper: %d\n", 1563 snr, new_threshold, 1564 lower_snr_threshold, upper_snr_threshold); 1565 1566 ret = ath6kl_wmi_send_snr_threshold_params(wmi, &cmd); 1567 if (ret) { 1568 ath6kl_err("unable to configure snr threshold\n"); 1569 return -EIO; 1570 } 1571 1572 return 0; 1573 } 1574 1575 static int ath6kl_wmi_aplist_event_rx(struct wmi *wmi, u8 *datap, int len) 1576 { 1577 u16 ap_info_entry_size; 1578 struct wmi_aplist_event *ev = (struct wmi_aplist_event *) datap; 1579 struct wmi_ap_info_v1 *ap_info_v1; 1580 u8 index; 1581 1582 if (len < sizeof(struct wmi_aplist_event) || 1583 ev->ap_list_ver != APLIST_VER1) 1584 return -EINVAL; 1585 1586 ap_info_entry_size = sizeof(struct wmi_ap_info_v1); 1587 ap_info_v1 = (struct wmi_ap_info_v1 *) ev->ap_list; 1588 1589 ath6kl_dbg(ATH6KL_DBG_WMI, 1590 "number of APs in aplist event: %d\n", ev->num_ap); 1591 1592 if (len < (int) (sizeof(struct wmi_aplist_event) + 1593 (ev->num_ap - 1) * ap_info_entry_size)) 1594 return -EINVAL; 1595 1596 /* AP list version 1 contents */ 1597 for (index = 0; index < ev->num_ap; index++) { 1598 ath6kl_dbg(ATH6KL_DBG_WMI, "AP#%d BSSID %pM Channel %d\n", 1599 index, ap_info_v1->bssid, ap_info_v1->channel); 1600 ap_info_v1++; 1601 } 1602 1603 return 0; 1604 } 1605 1606 int ath6kl_wmi_cmd_send(struct wmi *wmi, u8 if_idx, struct sk_buff *skb, 1607 enum wmi_cmd_id cmd_id, enum wmi_sync_flag sync_flag) 1608 { 1609 struct wmi_cmd_hdr *cmd_hdr; 1610 enum htc_endpoint_id ep_id = wmi->ep_id; 1611 int ret; 1612 u16 info1; 1613 1614 if (WARN_ON(skb == NULL || (if_idx > (MAX_NUM_VIF - 1)))) 1615 return -EINVAL; 1616 1617 ath6kl_dbg(ATH6KL_DBG_WMI, "wmi tx id %d len %d flag %d\n", 1618 cmd_id, skb->len, sync_flag); 1619 ath6kl_dbg_dump(ATH6KL_DBG_WMI_DUMP, NULL, "wmi tx ", 1620 skb->data, skb->len); 1621 1622 if (sync_flag >= END_WMIFLAG) { 1623 dev_kfree_skb(skb); 1624 return -EINVAL; 1625 } 1626 1627 if ((sync_flag == SYNC_BEFORE_WMIFLAG) || 1628 (sync_flag == SYNC_BOTH_WMIFLAG)) { 1629 /* 1630 * Make sure all data currently queued is transmitted before 1631 * the cmd execution. Establish a new sync point. 1632 */ 1633 ath6kl_wmi_sync_point(wmi, if_idx); 1634 } 1635 1636 skb_push(skb, sizeof(struct wmi_cmd_hdr)); 1637 1638 cmd_hdr = (struct wmi_cmd_hdr *) skb->data; 1639 cmd_hdr->cmd_id = cpu_to_le16(cmd_id); 1640 info1 = if_idx & WMI_CMD_HDR_IF_ID_MASK; 1641 cmd_hdr->info1 = cpu_to_le16(info1); 1642 1643 /* Only for OPT_TX_CMD, use BE endpoint. */ 1644 if (cmd_id == WMI_OPT_TX_FRAME_CMDID) { 1645 ret = ath6kl_wmi_data_hdr_add(wmi, skb, OPT_MSGTYPE, 1646 false, false, 0, NULL, if_idx); 1647 if (ret) { 1648 dev_kfree_skb(skb); 1649 return ret; 1650 } 1651 ep_id = ath6kl_ac2_endpoint_id(wmi->parent_dev, WMM_AC_BE); 1652 } 1653 1654 ath6kl_control_tx(wmi->parent_dev, skb, ep_id); 1655 1656 if ((sync_flag == SYNC_AFTER_WMIFLAG) || 1657 (sync_flag == SYNC_BOTH_WMIFLAG)) { 1658 /* 1659 * Make sure all new data queued waits for the command to 1660 * execute. Establish a new sync point. 1661 */ 1662 ath6kl_wmi_sync_point(wmi, if_idx); 1663 } 1664 1665 return 0; 1666 } 1667 1668 int ath6kl_wmi_connect_cmd(struct wmi *wmi, u8 if_idx, 1669 enum network_type nw_type, 1670 enum dot11_auth_mode dot11_auth_mode, 1671 enum auth_mode auth_mode, 1672 enum crypto_type pairwise_crypto, 1673 u8 pairwise_crypto_len, 1674 enum crypto_type group_crypto, 1675 u8 group_crypto_len, int ssid_len, u8 *ssid, 1676 u8 *bssid, u16 channel, u32 ctrl_flags) 1677 { 1678 struct sk_buff *skb; 1679 struct wmi_connect_cmd *cc; 1680 int ret; 1681 1682 ath6kl_dbg(ATH6KL_DBG_WMI, 1683 "wmi connect bssid %pM freq %d flags 0x%x ssid_len %d " 1684 "type %d dot11_auth %d auth %d pairwise %d group %d\n", 1685 bssid, channel, ctrl_flags, ssid_len, nw_type, 1686 dot11_auth_mode, auth_mode, pairwise_crypto, group_crypto); 1687 ath6kl_dbg_dump(ATH6KL_DBG_WMI, NULL, "ssid ", ssid, ssid_len); 1688 1689 wmi->traffic_class = 100; 1690 1691 if ((pairwise_crypto == NONE_CRYPT) && (group_crypto != NONE_CRYPT)) 1692 return -EINVAL; 1693 1694 if ((pairwise_crypto != NONE_CRYPT) && (group_crypto == NONE_CRYPT)) 1695 return -EINVAL; 1696 1697 skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_connect_cmd)); 1698 if (!skb) 1699 return -ENOMEM; 1700 1701 cc = (struct wmi_connect_cmd *) skb->data; 1702 1703 if (ssid_len) 1704 memcpy(cc->ssid, ssid, ssid_len); 1705 1706 cc->ssid_len = ssid_len; 1707 cc->nw_type = nw_type; 1708 cc->dot11_auth_mode = dot11_auth_mode; 1709 cc->auth_mode = auth_mode; 1710 cc->prwise_crypto_type = pairwise_crypto; 1711 cc->prwise_crypto_len = pairwise_crypto_len; 1712 cc->grp_crypto_type = group_crypto; 1713 cc->grp_crypto_len = group_crypto_len; 1714 cc->ch = cpu_to_le16(channel); 1715 cc->ctrl_flags = cpu_to_le32(ctrl_flags); 1716 1717 if (bssid != NULL) 1718 memcpy(cc->bssid, bssid, ETH_ALEN); 1719 1720 ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_CONNECT_CMDID, 1721 NO_SYNC_WMIFLAG); 1722 1723 return ret; 1724 } 1725 1726 int ath6kl_wmi_reconnect_cmd(struct wmi *wmi, u8 if_idx, u8 *bssid, 1727 u16 channel) 1728 { 1729 struct sk_buff *skb; 1730 struct wmi_reconnect_cmd *cc; 1731 int ret; 1732 1733 ath6kl_dbg(ATH6KL_DBG_WMI, "wmi reconnect bssid %pM freq %d\n", 1734 bssid, channel); 1735 1736 wmi->traffic_class = 100; 1737 1738 skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_reconnect_cmd)); 1739 if (!skb) 1740 return -ENOMEM; 1741 1742 cc = (struct wmi_reconnect_cmd *) skb->data; 1743 cc->channel = cpu_to_le16(channel); 1744 1745 if (bssid != NULL) 1746 memcpy(cc->bssid, bssid, ETH_ALEN); 1747 1748 ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_RECONNECT_CMDID, 1749 NO_SYNC_WMIFLAG); 1750 1751 return ret; 1752 } 1753 1754 int ath6kl_wmi_disconnect_cmd(struct wmi *wmi, u8 if_idx) 1755 { 1756 int ret; 1757 1758 ath6kl_dbg(ATH6KL_DBG_WMI, "wmi disconnect\n"); 1759 1760 wmi->traffic_class = 100; 1761 1762 /* Disconnect command does not need to do a SYNC before. */ 1763 ret = ath6kl_wmi_simple_cmd(wmi, if_idx, WMI_DISCONNECT_CMDID); 1764 1765 return ret; 1766 } 1767 1768 int ath6kl_wmi_startscan_cmd(struct wmi *wmi, u8 if_idx, 1769 enum wmi_scan_type scan_type, 1770 u32 force_fgscan, u32 is_legacy, 1771 u32 home_dwell_time, u32 force_scan_interval, 1772 s8 num_chan, u16 *ch_list) 1773 { 1774 struct sk_buff *skb; 1775 struct wmi_start_scan_cmd *sc; 1776 s8 size; 1777 int i, ret; 1778 1779 size = sizeof(struct wmi_start_scan_cmd); 1780 1781 if ((scan_type != WMI_LONG_SCAN) && (scan_type != WMI_SHORT_SCAN)) 1782 return -EINVAL; 1783 1784 if (num_chan > WMI_MAX_CHANNELS) 1785 return -EINVAL; 1786 1787 if (num_chan) 1788 size += sizeof(u16) * (num_chan - 1); 1789 1790 skb = ath6kl_wmi_get_new_buf(size); 1791 if (!skb) 1792 return -ENOMEM; 1793 1794 sc = (struct wmi_start_scan_cmd *) skb->data; 1795 sc->scan_type = scan_type; 1796 sc->force_fg_scan = cpu_to_le32(force_fgscan); 1797 sc->is_legacy = cpu_to_le32(is_legacy); 1798 sc->home_dwell_time = cpu_to_le32(home_dwell_time); 1799 sc->force_scan_intvl = cpu_to_le32(force_scan_interval); 1800 sc->num_ch = num_chan; 1801 1802 for (i = 0; i < num_chan; i++) 1803 sc->ch_list[i] = cpu_to_le16(ch_list[i]); 1804 1805 ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_START_SCAN_CMDID, 1806 NO_SYNC_WMIFLAG); 1807 1808 return ret; 1809 } 1810 1811 int ath6kl_wmi_scanparams_cmd(struct wmi *wmi, u8 if_idx, 1812 u16 fg_start_sec, 1813 u16 fg_end_sec, u16 bg_sec, 1814 u16 minact_chdw_msec, u16 maxact_chdw_msec, 1815 u16 pas_chdw_msec, u8 short_scan_ratio, 1816 u8 scan_ctrl_flag, u32 max_dfsch_act_time, 1817 u16 maxact_scan_per_ssid) 1818 { 1819 struct sk_buff *skb; 1820 struct wmi_scan_params_cmd *sc; 1821 int ret; 1822 1823 skb = ath6kl_wmi_get_new_buf(sizeof(*sc)); 1824 if (!skb) 1825 return -ENOMEM; 1826 1827 sc = (struct wmi_scan_params_cmd *) skb->data; 1828 sc->fg_start_period = cpu_to_le16(fg_start_sec); 1829 sc->fg_end_period = cpu_to_le16(fg_end_sec); 1830 sc->bg_period = cpu_to_le16(bg_sec); 1831 sc->minact_chdwell_time = cpu_to_le16(minact_chdw_msec); 1832 sc->maxact_chdwell_time = cpu_to_le16(maxact_chdw_msec); 1833 sc->pas_chdwell_time = cpu_to_le16(pas_chdw_msec); 1834 sc->short_scan_ratio = short_scan_ratio; 1835 sc->scan_ctrl_flags = scan_ctrl_flag; 1836 sc->max_dfsch_act_time = cpu_to_le32(max_dfsch_act_time); 1837 sc->maxact_scan_per_ssid = cpu_to_le16(maxact_scan_per_ssid); 1838 1839 ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_SCAN_PARAMS_CMDID, 1840 NO_SYNC_WMIFLAG); 1841 return ret; 1842 } 1843 1844 int ath6kl_wmi_bssfilter_cmd(struct wmi *wmi, u8 if_idx, u8 filter, u32 ie_mask) 1845 { 1846 struct sk_buff *skb; 1847 struct wmi_bss_filter_cmd *cmd; 1848 int ret; 1849 1850 if (filter >= LAST_BSS_FILTER) 1851 return -EINVAL; 1852 1853 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 1854 if (!skb) 1855 return -ENOMEM; 1856 1857 cmd = (struct wmi_bss_filter_cmd *) skb->data; 1858 cmd->bss_filter = filter; 1859 cmd->ie_mask = cpu_to_le32(ie_mask); 1860 1861 ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_BSS_FILTER_CMDID, 1862 NO_SYNC_WMIFLAG); 1863 return ret; 1864 } 1865 1866 int ath6kl_wmi_probedssid_cmd(struct wmi *wmi, u8 if_idx, u8 index, u8 flag, 1867 u8 ssid_len, u8 *ssid) 1868 { 1869 struct sk_buff *skb; 1870 struct wmi_probed_ssid_cmd *cmd; 1871 int ret; 1872 1873 if (index > MAX_PROBED_SSID_INDEX) 1874 return -EINVAL; 1875 1876 if (ssid_len > sizeof(cmd->ssid)) 1877 return -EINVAL; 1878 1879 if ((flag & (DISABLE_SSID_FLAG | ANY_SSID_FLAG)) && (ssid_len > 0)) 1880 return -EINVAL; 1881 1882 if ((flag & SPECIFIC_SSID_FLAG) && !ssid_len) 1883 return -EINVAL; 1884 1885 if (flag & SPECIFIC_SSID_FLAG) 1886 wmi->is_probe_ssid = true; 1887 1888 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 1889 if (!skb) 1890 return -ENOMEM; 1891 1892 cmd = (struct wmi_probed_ssid_cmd *) skb->data; 1893 cmd->entry_index = index; 1894 cmd->flag = flag; 1895 cmd->ssid_len = ssid_len; 1896 memcpy(cmd->ssid, ssid, ssid_len); 1897 1898 ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_PROBED_SSID_CMDID, 1899 NO_SYNC_WMIFLAG); 1900 return ret; 1901 } 1902 1903 int ath6kl_wmi_listeninterval_cmd(struct wmi *wmi, u8 if_idx, 1904 u16 listen_interval, 1905 u16 listen_beacons) 1906 { 1907 struct sk_buff *skb; 1908 struct wmi_listen_int_cmd *cmd; 1909 int ret; 1910 1911 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 1912 if (!skb) 1913 return -ENOMEM; 1914 1915 cmd = (struct wmi_listen_int_cmd *) skb->data; 1916 cmd->listen_intvl = cpu_to_le16(listen_interval); 1917 cmd->num_beacons = cpu_to_le16(listen_beacons); 1918 1919 ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_LISTEN_INT_CMDID, 1920 NO_SYNC_WMIFLAG); 1921 return ret; 1922 } 1923 1924 int ath6kl_wmi_powermode_cmd(struct wmi *wmi, u8 if_idx, u8 pwr_mode) 1925 { 1926 struct sk_buff *skb; 1927 struct wmi_power_mode_cmd *cmd; 1928 int ret; 1929 1930 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 1931 if (!skb) 1932 return -ENOMEM; 1933 1934 cmd = (struct wmi_power_mode_cmd *) skb->data; 1935 cmd->pwr_mode = pwr_mode; 1936 wmi->pwr_mode = pwr_mode; 1937 1938 ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_POWER_MODE_CMDID, 1939 NO_SYNC_WMIFLAG); 1940 return ret; 1941 } 1942 1943 int ath6kl_wmi_pmparams_cmd(struct wmi *wmi, u8 if_idx, u16 idle_period, 1944 u16 ps_poll_num, u16 dtim_policy, 1945 u16 tx_wakeup_policy, u16 num_tx_to_wakeup, 1946 u16 ps_fail_event_policy) 1947 { 1948 struct sk_buff *skb; 1949 struct wmi_power_params_cmd *pm; 1950 int ret; 1951 1952 skb = ath6kl_wmi_get_new_buf(sizeof(*pm)); 1953 if (!skb) 1954 return -ENOMEM; 1955 1956 pm = (struct wmi_power_params_cmd *)skb->data; 1957 pm->idle_period = cpu_to_le16(idle_period); 1958 pm->pspoll_number = cpu_to_le16(ps_poll_num); 1959 pm->dtim_policy = cpu_to_le16(dtim_policy); 1960 pm->tx_wakeup_policy = cpu_to_le16(tx_wakeup_policy); 1961 pm->num_tx_to_wakeup = cpu_to_le16(num_tx_to_wakeup); 1962 pm->ps_fail_event_policy = cpu_to_le16(ps_fail_event_policy); 1963 1964 ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_POWER_PARAMS_CMDID, 1965 NO_SYNC_WMIFLAG); 1966 return ret; 1967 } 1968 1969 int ath6kl_wmi_disctimeout_cmd(struct wmi *wmi, u8 if_idx, u8 timeout) 1970 { 1971 struct sk_buff *skb; 1972 struct wmi_disc_timeout_cmd *cmd; 1973 int ret; 1974 1975 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 1976 if (!skb) 1977 return -ENOMEM; 1978 1979 cmd = (struct wmi_disc_timeout_cmd *) skb->data; 1980 cmd->discon_timeout = timeout; 1981 1982 ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_DISC_TIMEOUT_CMDID, 1983 NO_SYNC_WMIFLAG); 1984 1985 if (ret == 0) 1986 ath6kl_debug_set_disconnect_timeout(wmi->parent_dev, timeout); 1987 1988 return ret; 1989 } 1990 1991 int ath6kl_wmi_addkey_cmd(struct wmi *wmi, u8 if_idx, u8 key_index, 1992 enum crypto_type key_type, 1993 u8 key_usage, u8 key_len, 1994 u8 *key_rsc, u8 *key_material, 1995 u8 key_op_ctrl, u8 *mac_addr, 1996 enum wmi_sync_flag sync_flag) 1997 { 1998 struct sk_buff *skb; 1999 struct wmi_add_cipher_key_cmd *cmd; 2000 int ret; 2001 2002 ath6kl_dbg(ATH6KL_DBG_WMI, "addkey cmd: key_index=%u key_type=%d " 2003 "key_usage=%d key_len=%d key_op_ctrl=%d\n", 2004 key_index, key_type, key_usage, key_len, key_op_ctrl); 2005 2006 if ((key_index > WMI_MAX_KEY_INDEX) || (key_len > WMI_MAX_KEY_LEN) || 2007 (key_material == NULL)) 2008 return -EINVAL; 2009 2010 if ((WEP_CRYPT != key_type) && (NULL == key_rsc)) 2011 return -EINVAL; 2012 2013 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 2014 if (!skb) 2015 return -ENOMEM; 2016 2017 cmd = (struct wmi_add_cipher_key_cmd *) skb->data; 2018 cmd->key_index = key_index; 2019 cmd->key_type = key_type; 2020 cmd->key_usage = key_usage; 2021 cmd->key_len = key_len; 2022 memcpy(cmd->key, key_material, key_len); 2023 2024 if (key_rsc != NULL) 2025 memcpy(cmd->key_rsc, key_rsc, sizeof(cmd->key_rsc)); 2026 2027 cmd->key_op_ctrl = key_op_ctrl; 2028 2029 if (mac_addr) 2030 memcpy(cmd->key_mac_addr, mac_addr, ETH_ALEN); 2031 2032 ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_ADD_CIPHER_KEY_CMDID, 2033 sync_flag); 2034 2035 return ret; 2036 } 2037 2038 int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 if_idx, u8 *krk) 2039 { 2040 struct sk_buff *skb; 2041 struct wmi_add_krk_cmd *cmd; 2042 int ret; 2043 2044 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 2045 if (!skb) 2046 return -ENOMEM; 2047 2048 cmd = (struct wmi_add_krk_cmd *) skb->data; 2049 memcpy(cmd->krk, krk, WMI_KRK_LEN); 2050 2051 ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_ADD_KRK_CMDID, 2052 NO_SYNC_WMIFLAG); 2053 2054 return ret; 2055 } 2056 2057 int ath6kl_wmi_deletekey_cmd(struct wmi *wmi, u8 if_idx, u8 key_index) 2058 { 2059 struct sk_buff *skb; 2060 struct wmi_delete_cipher_key_cmd *cmd; 2061 int ret; 2062 2063 if (key_index > WMI_MAX_KEY_INDEX) 2064 return -EINVAL; 2065 2066 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 2067 if (!skb) 2068 return -ENOMEM; 2069 2070 cmd = (struct wmi_delete_cipher_key_cmd *) skb->data; 2071 cmd->key_index = key_index; 2072 2073 ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_DELETE_CIPHER_KEY_CMDID, 2074 NO_SYNC_WMIFLAG); 2075 2076 return ret; 2077 } 2078 2079 int ath6kl_wmi_setpmkid_cmd(struct wmi *wmi, u8 if_idx, const u8 *bssid, 2080 const u8 *pmkid, bool set) 2081 { 2082 struct sk_buff *skb; 2083 struct wmi_setpmkid_cmd *cmd; 2084 int ret; 2085 2086 if (bssid == NULL) 2087 return -EINVAL; 2088 2089 if (set && pmkid == NULL) 2090 return -EINVAL; 2091 2092 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 2093 if (!skb) 2094 return -ENOMEM; 2095 2096 cmd = (struct wmi_setpmkid_cmd *) skb->data; 2097 memcpy(cmd->bssid, bssid, ETH_ALEN); 2098 if (set) { 2099 memcpy(cmd->pmkid, pmkid, sizeof(cmd->pmkid)); 2100 cmd->enable = PMKID_ENABLE; 2101 } else { 2102 memset(cmd->pmkid, 0, sizeof(cmd->pmkid)); 2103 cmd->enable = PMKID_DISABLE; 2104 } 2105 2106 ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_PMKID_CMDID, 2107 NO_SYNC_WMIFLAG); 2108 2109 return ret; 2110 } 2111 2112 static int ath6kl_wmi_data_sync_send(struct wmi *wmi, struct sk_buff *skb, 2113 enum htc_endpoint_id ep_id, u8 if_idx) 2114 { 2115 struct wmi_data_hdr *data_hdr; 2116 int ret; 2117 2118 if (WARN_ON(skb == NULL || ep_id == wmi->ep_id)) 2119 return -EINVAL; 2120 2121 skb_push(skb, sizeof(struct wmi_data_hdr)); 2122 2123 data_hdr = (struct wmi_data_hdr *) skb->data; 2124 data_hdr->info = SYNC_MSGTYPE << WMI_DATA_HDR_MSG_TYPE_SHIFT; 2125 data_hdr->info3 = cpu_to_le16(if_idx & WMI_DATA_HDR_IF_IDX_MASK); 2126 2127 ret = ath6kl_control_tx(wmi->parent_dev, skb, ep_id); 2128 2129 return ret; 2130 } 2131 2132 static int ath6kl_wmi_sync_point(struct wmi *wmi, u8 if_idx) 2133 { 2134 struct sk_buff *skb; 2135 struct wmi_sync_cmd *cmd; 2136 struct wmi_data_sync_bufs data_sync_bufs[WMM_NUM_AC]; 2137 enum htc_endpoint_id ep_id; 2138 u8 index, num_pri_streams = 0; 2139 int ret = 0; 2140 2141 memset(data_sync_bufs, 0, sizeof(data_sync_bufs)); 2142 2143 spin_lock_bh(&wmi->lock); 2144 2145 for (index = 0; index < WMM_NUM_AC; index++) { 2146 if (wmi->fat_pipe_exist & (1 << index)) { 2147 num_pri_streams++; 2148 data_sync_bufs[num_pri_streams - 1].traffic_class = 2149 index; 2150 } 2151 } 2152 2153 spin_unlock_bh(&wmi->lock); 2154 2155 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 2156 if (!skb) { 2157 ret = -ENOMEM; 2158 goto free_skb; 2159 } 2160 2161 cmd = (struct wmi_sync_cmd *) skb->data; 2162 2163 /* 2164 * In the SYNC cmd sent on the control Ep, send a bitmap 2165 * of the data eps on which the Data Sync will be sent 2166 */ 2167 cmd->data_sync_map = wmi->fat_pipe_exist; 2168 2169 for (index = 0; index < num_pri_streams; index++) { 2170 data_sync_bufs[index].skb = ath6kl_buf_alloc(0); 2171 if (data_sync_bufs[index].skb == NULL) { 2172 ret = -ENOMEM; 2173 break; 2174 } 2175 } 2176 2177 /* 2178 * If buffer allocation for any of the dataSync fails, 2179 * then do not send the Synchronize cmd on the control ep 2180 */ 2181 if (ret) 2182 goto free_skb; 2183 2184 /* 2185 * Send sync cmd followed by sync data messages on all 2186 * endpoints being used 2187 */ 2188 ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SYNCHRONIZE_CMDID, 2189 NO_SYNC_WMIFLAG); 2190 2191 if (ret) 2192 goto free_skb; 2193 2194 /* cmd buffer sent, we no longer own it */ 2195 skb = NULL; 2196 2197 for (index = 0; index < num_pri_streams; index++) { 2198 2199 if (WARN_ON(!data_sync_bufs[index].skb)) 2200 break; 2201 2202 ep_id = ath6kl_ac2_endpoint_id(wmi->parent_dev, 2203 data_sync_bufs[index]. 2204 traffic_class); 2205 ret = 2206 ath6kl_wmi_data_sync_send(wmi, data_sync_bufs[index].skb, 2207 ep_id, if_idx); 2208 2209 if (ret) 2210 break; 2211 2212 data_sync_bufs[index].skb = NULL; 2213 } 2214 2215 free_skb: 2216 /* free up any resources left over (possibly due to an error) */ 2217 if (skb) 2218 dev_kfree_skb(skb); 2219 2220 for (index = 0; index < num_pri_streams; index++) { 2221 if (data_sync_bufs[index].skb != NULL) { 2222 dev_kfree_skb((struct sk_buff *)data_sync_bufs[index]. 2223 skb); 2224 } 2225 } 2226 2227 return ret; 2228 } 2229 2230 int ath6kl_wmi_create_pstream_cmd(struct wmi *wmi, u8 if_idx, 2231 struct wmi_create_pstream_cmd *params) 2232 { 2233 struct sk_buff *skb; 2234 struct wmi_create_pstream_cmd *cmd; 2235 u8 fatpipe_exist_for_ac = 0; 2236 s32 min_phy = 0; 2237 s32 nominal_phy = 0; 2238 int ret; 2239 2240 if (!((params->user_pri < 8) && 2241 (params->user_pri <= 0x7) && 2242 (up_to_ac[params->user_pri & 0x7] == params->traffic_class) && 2243 (params->traffic_direc == UPLINK_TRAFFIC || 2244 params->traffic_direc == DNLINK_TRAFFIC || 2245 params->traffic_direc == BIDIR_TRAFFIC) && 2246 (params->traffic_type == TRAFFIC_TYPE_APERIODIC || 2247 params->traffic_type == TRAFFIC_TYPE_PERIODIC) && 2248 (params->voice_psc_cap == DISABLE_FOR_THIS_AC || 2249 params->voice_psc_cap == ENABLE_FOR_THIS_AC || 2250 params->voice_psc_cap == ENABLE_FOR_ALL_AC) && 2251 (params->tsid == WMI_IMPLICIT_PSTREAM || 2252 params->tsid <= WMI_MAX_THINSTREAM))) { 2253 return -EINVAL; 2254 } 2255 2256 /* 2257 * Check nominal PHY rate is >= minimalPHY, 2258 * so that DUT can allow TSRS IE 2259 */ 2260 2261 /* Get the physical rate (units of bps) */ 2262 min_phy = ((le32_to_cpu(params->min_phy_rate) / 1000) / 1000); 2263 2264 /* Check minimal phy < nominal phy rate */ 2265 if (params->nominal_phy >= min_phy) { 2266 /* unit of 500 kbps */ 2267 nominal_phy = (params->nominal_phy * 1000) / 500; 2268 ath6kl_dbg(ATH6KL_DBG_WMI, 2269 "TSRS IE enabled::MinPhy %x->NominalPhy ===> %x\n", 2270 min_phy, nominal_phy); 2271 2272 params->nominal_phy = nominal_phy; 2273 } else { 2274 params->nominal_phy = 0; 2275 } 2276 2277 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 2278 if (!skb) 2279 return -ENOMEM; 2280 2281 ath6kl_dbg(ATH6KL_DBG_WMI, 2282 "sending create_pstream_cmd: ac=%d tsid:%d\n", 2283 params->traffic_class, params->tsid); 2284 2285 cmd = (struct wmi_create_pstream_cmd *) skb->data; 2286 memcpy(cmd, params, sizeof(*cmd)); 2287 2288 /* This is an implicitly created Fat pipe */ 2289 if ((u32) params->tsid == (u32) WMI_IMPLICIT_PSTREAM) { 2290 spin_lock_bh(&wmi->lock); 2291 fatpipe_exist_for_ac = (wmi->fat_pipe_exist & 2292 (1 << params->traffic_class)); 2293 wmi->fat_pipe_exist |= (1 << params->traffic_class); 2294 spin_unlock_bh(&wmi->lock); 2295 } else { 2296 /* explicitly created thin stream within a fat pipe */ 2297 spin_lock_bh(&wmi->lock); 2298 fatpipe_exist_for_ac = (wmi->fat_pipe_exist & 2299 (1 << params->traffic_class)); 2300 wmi->stream_exist_for_ac[params->traffic_class] |= 2301 (1 << params->tsid); 2302 /* 2303 * If a thinstream becomes active, the fat pipe automatically 2304 * becomes active 2305 */ 2306 wmi->fat_pipe_exist |= (1 << params->traffic_class); 2307 spin_unlock_bh(&wmi->lock); 2308 } 2309 2310 /* 2311 * Indicate activty change to driver layer only if this is the 2312 * first TSID to get created in this AC explicitly or an implicit 2313 * fat pipe is getting created. 2314 */ 2315 if (!fatpipe_exist_for_ac) 2316 ath6kl_indicate_tx_activity(wmi->parent_dev, 2317 params->traffic_class, true); 2318 2319 ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_CREATE_PSTREAM_CMDID, 2320 NO_SYNC_WMIFLAG); 2321 return ret; 2322 } 2323 2324 int ath6kl_wmi_delete_pstream_cmd(struct wmi *wmi, u8 if_idx, u8 traffic_class, 2325 u8 tsid) 2326 { 2327 struct sk_buff *skb; 2328 struct wmi_delete_pstream_cmd *cmd; 2329 u16 active_tsids = 0; 2330 int ret; 2331 2332 if (traffic_class > 3) { 2333 ath6kl_err("invalid traffic class: %d\n", traffic_class); 2334 return -EINVAL; 2335 } 2336 2337 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 2338 if (!skb) 2339 return -ENOMEM; 2340 2341 cmd = (struct wmi_delete_pstream_cmd *) skb->data; 2342 cmd->traffic_class = traffic_class; 2343 cmd->tsid = tsid; 2344 2345 spin_lock_bh(&wmi->lock); 2346 active_tsids = wmi->stream_exist_for_ac[traffic_class]; 2347 spin_unlock_bh(&wmi->lock); 2348 2349 if (!(active_tsids & (1 << tsid))) { 2350 dev_kfree_skb(skb); 2351 ath6kl_dbg(ATH6KL_DBG_WMI, 2352 "TSID %d doesn't exist for traffic class: %d\n", 2353 tsid, traffic_class); 2354 return -ENODATA; 2355 } 2356 2357 ath6kl_dbg(ATH6KL_DBG_WMI, 2358 "sending delete_pstream_cmd: traffic class: %d tsid=%d\n", 2359 traffic_class, tsid); 2360 2361 ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_DELETE_PSTREAM_CMDID, 2362 SYNC_BEFORE_WMIFLAG); 2363 2364 spin_lock_bh(&wmi->lock); 2365 wmi->stream_exist_for_ac[traffic_class] &= ~(1 << tsid); 2366 active_tsids = wmi->stream_exist_for_ac[traffic_class]; 2367 spin_unlock_bh(&wmi->lock); 2368 2369 /* 2370 * Indicate stream inactivity to driver layer only if all tsids 2371 * within this AC are deleted. 2372 */ 2373 if (!active_tsids) { 2374 ath6kl_indicate_tx_activity(wmi->parent_dev, 2375 traffic_class, false); 2376 wmi->fat_pipe_exist &= ~(1 << traffic_class); 2377 } 2378 2379 return ret; 2380 } 2381 2382 int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, struct wmi_set_ip_cmd *ip_cmd) 2383 { 2384 struct sk_buff *skb; 2385 struct wmi_set_ip_cmd *cmd; 2386 int ret; 2387 2388 /* Multicast address are not valid */ 2389 if ((*((u8 *) &ip_cmd->ips[0]) >= 0xE0) || 2390 (*((u8 *) &ip_cmd->ips[1]) >= 0xE0)) 2391 return -EINVAL; 2392 2393 skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_ip_cmd)); 2394 if (!skb) 2395 return -ENOMEM; 2396 2397 cmd = (struct wmi_set_ip_cmd *) skb->data; 2398 memcpy(cmd, ip_cmd, sizeof(struct wmi_set_ip_cmd)); 2399 2400 ret = ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_SET_IP_CMDID, 2401 NO_SYNC_WMIFLAG); 2402 return ret; 2403 } 2404 2405 static int ath6kl_wmi_get_wow_list_event_rx(struct wmi *wmi, u8 * datap, 2406 int len) 2407 { 2408 if (len < sizeof(struct wmi_get_wow_list_reply)) 2409 return -EINVAL; 2410 2411 return 0; 2412 } 2413 2414 static int ath6kl_wmi_cmd_send_xtnd(struct wmi *wmi, struct sk_buff *skb, 2415 enum wmix_command_id cmd_id, 2416 enum wmi_sync_flag sync_flag) 2417 { 2418 struct wmix_cmd_hdr *cmd_hdr; 2419 int ret; 2420 2421 skb_push(skb, sizeof(struct wmix_cmd_hdr)); 2422 2423 cmd_hdr = (struct wmix_cmd_hdr *) skb->data; 2424 cmd_hdr->cmd_id = cpu_to_le32(cmd_id); 2425 2426 ret = ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_EXTENSION_CMDID, sync_flag); 2427 2428 return ret; 2429 } 2430 2431 int ath6kl_wmi_get_challenge_resp_cmd(struct wmi *wmi, u32 cookie, u32 source) 2432 { 2433 struct sk_buff *skb; 2434 struct wmix_hb_challenge_resp_cmd *cmd; 2435 int ret; 2436 2437 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 2438 if (!skb) 2439 return -ENOMEM; 2440 2441 cmd = (struct wmix_hb_challenge_resp_cmd *) skb->data; 2442 cmd->cookie = cpu_to_le32(cookie); 2443 cmd->source = cpu_to_le32(source); 2444 2445 ret = ath6kl_wmi_cmd_send_xtnd(wmi, skb, WMIX_HB_CHALLENGE_RESP_CMDID, 2446 NO_SYNC_WMIFLAG); 2447 return ret; 2448 } 2449 2450 int ath6kl_wmi_config_debug_module_cmd(struct wmi *wmi, u32 valid, u32 config) 2451 { 2452 struct ath6kl_wmix_dbglog_cfg_module_cmd *cmd; 2453 struct sk_buff *skb; 2454 int ret; 2455 2456 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 2457 if (!skb) 2458 return -ENOMEM; 2459 2460 cmd = (struct ath6kl_wmix_dbglog_cfg_module_cmd *) skb->data; 2461 cmd->valid = cpu_to_le32(valid); 2462 cmd->config = cpu_to_le32(config); 2463 2464 ret = ath6kl_wmi_cmd_send_xtnd(wmi, skb, WMIX_DBGLOG_CFG_MODULE_CMDID, 2465 NO_SYNC_WMIFLAG); 2466 return ret; 2467 } 2468 2469 int ath6kl_wmi_get_stats_cmd(struct wmi *wmi, u8 if_idx) 2470 { 2471 return ath6kl_wmi_simple_cmd(wmi, if_idx, WMI_GET_STATISTICS_CMDID); 2472 } 2473 2474 int ath6kl_wmi_set_tx_pwr_cmd(struct wmi *wmi, u8 if_idx, u8 dbM) 2475 { 2476 struct sk_buff *skb; 2477 struct wmi_set_tx_pwr_cmd *cmd; 2478 int ret; 2479 2480 skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_tx_pwr_cmd)); 2481 if (!skb) 2482 return -ENOMEM; 2483 2484 cmd = (struct wmi_set_tx_pwr_cmd *) skb->data; 2485 cmd->dbM = dbM; 2486 2487 ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_TX_PWR_CMDID, 2488 NO_SYNC_WMIFLAG); 2489 2490 return ret; 2491 } 2492 2493 int ath6kl_wmi_get_tx_pwr_cmd(struct wmi *wmi, u8 if_idx) 2494 { 2495 return ath6kl_wmi_simple_cmd(wmi, if_idx, WMI_GET_TX_PWR_CMDID); 2496 } 2497 2498 int ath6kl_wmi_get_roam_tbl_cmd(struct wmi *wmi) 2499 { 2500 return ath6kl_wmi_simple_cmd(wmi, 0, WMI_GET_ROAM_TBL_CMDID); 2501 } 2502 2503 int ath6kl_wmi_set_lpreamble_cmd(struct wmi *wmi, u8 if_idx, u8 status, 2504 u8 preamble_policy) 2505 { 2506 struct sk_buff *skb; 2507 struct wmi_set_lpreamble_cmd *cmd; 2508 int ret; 2509 2510 skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_lpreamble_cmd)); 2511 if (!skb) 2512 return -ENOMEM; 2513 2514 cmd = (struct wmi_set_lpreamble_cmd *) skb->data; 2515 cmd->status = status; 2516 cmd->preamble_policy = preamble_policy; 2517 2518 ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_LPREAMBLE_CMDID, 2519 NO_SYNC_WMIFLAG); 2520 return ret; 2521 } 2522 2523 int ath6kl_wmi_set_rts_cmd(struct wmi *wmi, u16 threshold) 2524 { 2525 struct sk_buff *skb; 2526 struct wmi_set_rts_cmd *cmd; 2527 int ret; 2528 2529 skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_rts_cmd)); 2530 if (!skb) 2531 return -ENOMEM; 2532 2533 cmd = (struct wmi_set_rts_cmd *) skb->data; 2534 cmd->threshold = cpu_to_le16(threshold); 2535 2536 ret = ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_SET_RTS_CMDID, 2537 NO_SYNC_WMIFLAG); 2538 return ret; 2539 } 2540 2541 int ath6kl_wmi_set_wmm_txop(struct wmi *wmi, u8 if_idx, enum wmi_txop_cfg cfg) 2542 { 2543 struct sk_buff *skb; 2544 struct wmi_set_wmm_txop_cmd *cmd; 2545 int ret; 2546 2547 if (!((cfg == WMI_TXOP_DISABLED) || (cfg == WMI_TXOP_ENABLED))) 2548 return -EINVAL; 2549 2550 skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_wmm_txop_cmd)); 2551 if (!skb) 2552 return -ENOMEM; 2553 2554 cmd = (struct wmi_set_wmm_txop_cmd *) skb->data; 2555 cmd->txop_enable = cfg; 2556 2557 ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_WMM_TXOP_CMDID, 2558 NO_SYNC_WMIFLAG); 2559 return ret; 2560 } 2561 2562 int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 if_idx, 2563 u8 keep_alive_intvl) 2564 { 2565 struct sk_buff *skb; 2566 struct wmi_set_keepalive_cmd *cmd; 2567 int ret; 2568 2569 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 2570 if (!skb) 2571 return -ENOMEM; 2572 2573 cmd = (struct wmi_set_keepalive_cmd *) skb->data; 2574 cmd->keep_alive_intvl = keep_alive_intvl; 2575 2576 ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_KEEPALIVE_CMDID, 2577 NO_SYNC_WMIFLAG); 2578 2579 if (ret == 0) 2580 ath6kl_debug_set_keepalive(wmi->parent_dev, keep_alive_intvl); 2581 2582 return ret; 2583 } 2584 2585 int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len) 2586 { 2587 struct sk_buff *skb; 2588 int ret; 2589 2590 skb = ath6kl_wmi_get_new_buf(len); 2591 if (!skb) 2592 return -ENOMEM; 2593 2594 memcpy(skb->data, buf, len); 2595 2596 ret = ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_TEST_CMDID, NO_SYNC_WMIFLAG); 2597 2598 return ret; 2599 } 2600 2601 2602 s32 ath6kl_wmi_get_rate(s8 rate_index) 2603 { 2604 if (rate_index == RATE_AUTO) 2605 return 0; 2606 2607 return wmi_rate_tbl[(u32) rate_index][0]; 2608 } 2609 2610 static int ath6kl_wmi_get_pmkid_list_event_rx(struct wmi *wmi, u8 *datap, 2611 u32 len) 2612 { 2613 struct wmi_pmkid_list_reply *reply; 2614 u32 expected_len; 2615 2616 if (len < sizeof(struct wmi_pmkid_list_reply)) 2617 return -EINVAL; 2618 2619 reply = (struct wmi_pmkid_list_reply *)datap; 2620 expected_len = sizeof(reply->num_pmkid) + 2621 le32_to_cpu(reply->num_pmkid) * WMI_PMKID_LEN; 2622 2623 if (len < expected_len) 2624 return -EINVAL; 2625 2626 return 0; 2627 } 2628 2629 static int ath6kl_wmi_addba_req_event_rx(struct wmi *wmi, u8 *datap, int len, 2630 struct ath6kl_vif *vif) 2631 { 2632 struct wmi_addba_req_event *cmd = (struct wmi_addba_req_event *) datap; 2633 2634 aggr_recv_addba_req_evt(vif, cmd->tid, 2635 le16_to_cpu(cmd->st_seq_no), cmd->win_sz); 2636 2637 return 0; 2638 } 2639 2640 static int ath6kl_wmi_delba_req_event_rx(struct wmi *wmi, u8 *datap, int len, 2641 struct ath6kl_vif *vif) 2642 { 2643 struct wmi_delba_event *cmd = (struct wmi_delba_event *) datap; 2644 2645 aggr_recv_delba_req_evt(vif, cmd->tid); 2646 2647 return 0; 2648 } 2649 2650 /* AP mode functions */ 2651 2652 int ath6kl_wmi_ap_profile_commit(struct wmi *wmip, u8 if_idx, 2653 struct wmi_connect_cmd *p) 2654 { 2655 struct sk_buff *skb; 2656 struct wmi_connect_cmd *cm; 2657 int res; 2658 2659 skb = ath6kl_wmi_get_new_buf(sizeof(*cm)); 2660 if (!skb) 2661 return -ENOMEM; 2662 2663 cm = (struct wmi_connect_cmd *) skb->data; 2664 memcpy(cm, p, sizeof(*cm)); 2665 2666 res = ath6kl_wmi_cmd_send(wmip, if_idx, skb, WMI_AP_CONFIG_COMMIT_CMDID, 2667 NO_SYNC_WMIFLAG); 2668 ath6kl_dbg(ATH6KL_DBG_WMI, "%s: nw_type=%u auth_mode=%u ch=%u " 2669 "ctrl_flags=0x%x-> res=%d\n", 2670 __func__, p->nw_type, p->auth_mode, le16_to_cpu(p->ch), 2671 le32_to_cpu(p->ctrl_flags), res); 2672 return res; 2673 } 2674 2675 int ath6kl_wmi_ap_set_mlme(struct wmi *wmip, u8 if_idx, u8 cmd, const u8 *mac, 2676 u16 reason) 2677 { 2678 struct sk_buff *skb; 2679 struct wmi_ap_set_mlme_cmd *cm; 2680 2681 skb = ath6kl_wmi_get_new_buf(sizeof(*cm)); 2682 if (!skb) 2683 return -ENOMEM; 2684 2685 cm = (struct wmi_ap_set_mlme_cmd *) skb->data; 2686 memcpy(cm->mac, mac, ETH_ALEN); 2687 cm->reason = cpu_to_le16(reason); 2688 cm->cmd = cmd; 2689 2690 return ath6kl_wmi_cmd_send(wmip, if_idx, skb, WMI_AP_SET_MLME_CMDID, 2691 NO_SYNC_WMIFLAG); 2692 } 2693 2694 static int ath6kl_wmi_pspoll_event_rx(struct wmi *wmi, u8 *datap, int len, 2695 struct ath6kl_vif *vif) 2696 { 2697 struct wmi_pspoll_event *ev; 2698 2699 if (len < sizeof(struct wmi_pspoll_event)) 2700 return -EINVAL; 2701 2702 ev = (struct wmi_pspoll_event *) datap; 2703 2704 ath6kl_pspoll_event(vif, le16_to_cpu(ev->aid)); 2705 2706 return 0; 2707 } 2708 2709 static int ath6kl_wmi_dtimexpiry_event_rx(struct wmi *wmi, u8 *datap, int len, 2710 struct ath6kl_vif *vif) 2711 { 2712 ath6kl_dtimexpiry_event(vif); 2713 2714 return 0; 2715 } 2716 2717 int ath6kl_wmi_set_pvb_cmd(struct wmi *wmi, u8 if_idx, u16 aid, 2718 bool flag) 2719 { 2720 struct sk_buff *skb; 2721 struct wmi_ap_set_pvb_cmd *cmd; 2722 int ret; 2723 2724 skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_ap_set_pvb_cmd)); 2725 if (!skb) 2726 return -ENOMEM; 2727 2728 cmd = (struct wmi_ap_set_pvb_cmd *) skb->data; 2729 cmd->aid = cpu_to_le16(aid); 2730 cmd->rsvd = cpu_to_le16(0); 2731 cmd->flag = cpu_to_le32(flag); 2732 2733 ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_AP_SET_PVB_CMDID, 2734 NO_SYNC_WMIFLAG); 2735 2736 return 0; 2737 } 2738 2739 int ath6kl_wmi_set_rx_frame_format_cmd(struct wmi *wmi, u8 if_idx, 2740 u8 rx_meta_ver, 2741 bool rx_dot11_hdr, bool defrag_on_host) 2742 { 2743 struct sk_buff *skb; 2744 struct wmi_rx_frame_format_cmd *cmd; 2745 int ret; 2746 2747 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 2748 if (!skb) 2749 return -ENOMEM; 2750 2751 cmd = (struct wmi_rx_frame_format_cmd *) skb->data; 2752 cmd->dot11_hdr = rx_dot11_hdr ? 1 : 0; 2753 cmd->defrag_on_host = defrag_on_host ? 1 : 0; 2754 cmd->meta_ver = rx_meta_ver; 2755 2756 /* Delete the local aggr state, on host */ 2757 ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_RX_FRAME_FORMAT_CMDID, 2758 NO_SYNC_WMIFLAG); 2759 2760 return ret; 2761 } 2762 2763 int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 if_idx, u8 mgmt_frm_type, 2764 const u8 *ie, u8 ie_len) 2765 { 2766 struct sk_buff *skb; 2767 struct wmi_set_appie_cmd *p; 2768 2769 skb = ath6kl_wmi_get_new_buf(sizeof(*p) + ie_len); 2770 if (!skb) 2771 return -ENOMEM; 2772 2773 ath6kl_dbg(ATH6KL_DBG_WMI, "set_appie_cmd: mgmt_frm_type=%u " 2774 "ie_len=%u\n", mgmt_frm_type, ie_len); 2775 p = (struct wmi_set_appie_cmd *) skb->data; 2776 p->mgmt_frm_type = mgmt_frm_type; 2777 p->ie_len = ie_len; 2778 memcpy(p->ie_info, ie, ie_len); 2779 return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_APPIE_CMDID, 2780 NO_SYNC_WMIFLAG); 2781 } 2782 2783 int ath6kl_wmi_disable_11b_rates_cmd(struct wmi *wmi, bool disable) 2784 { 2785 struct sk_buff *skb; 2786 struct wmi_disable_11b_rates_cmd *cmd; 2787 2788 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 2789 if (!skb) 2790 return -ENOMEM; 2791 2792 ath6kl_dbg(ATH6KL_DBG_WMI, "disable_11b_rates_cmd: disable=%u\n", 2793 disable); 2794 cmd = (struct wmi_disable_11b_rates_cmd *) skb->data; 2795 cmd->disable = disable ? 1 : 0; 2796 2797 return ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_DISABLE_11B_RATES_CMDID, 2798 NO_SYNC_WMIFLAG); 2799 } 2800 2801 int ath6kl_wmi_remain_on_chnl_cmd(struct wmi *wmi, u8 if_idx, u32 freq, u32 dur) 2802 { 2803 struct sk_buff *skb; 2804 struct wmi_remain_on_chnl_cmd *p; 2805 2806 skb = ath6kl_wmi_get_new_buf(sizeof(*p)); 2807 if (!skb) 2808 return -ENOMEM; 2809 2810 ath6kl_dbg(ATH6KL_DBG_WMI, "remain_on_chnl_cmd: freq=%u dur=%u\n", 2811 freq, dur); 2812 p = (struct wmi_remain_on_chnl_cmd *) skb->data; 2813 p->freq = cpu_to_le32(freq); 2814 p->duration = cpu_to_le32(dur); 2815 return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_REMAIN_ON_CHNL_CMDID, 2816 NO_SYNC_WMIFLAG); 2817 } 2818 2819 int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u8 if_idx, u32 id, u32 freq, 2820 u32 wait, const u8 *data, u16 data_len) 2821 { 2822 struct sk_buff *skb; 2823 struct wmi_send_action_cmd *p; 2824 u8 *buf; 2825 2826 if (wait) 2827 return -EINVAL; /* Offload for wait not supported */ 2828 2829 buf = kmalloc(data_len, GFP_KERNEL); 2830 if (!buf) 2831 return -ENOMEM; 2832 2833 skb = ath6kl_wmi_get_new_buf(sizeof(*p) + data_len); 2834 if (!skb) { 2835 kfree(buf); 2836 return -ENOMEM; 2837 } 2838 2839 kfree(wmi->last_mgmt_tx_frame); 2840 wmi->last_mgmt_tx_frame = buf; 2841 wmi->last_mgmt_tx_frame_len = data_len; 2842 2843 ath6kl_dbg(ATH6KL_DBG_WMI, "send_action_cmd: id=%u freq=%u wait=%u " 2844 "len=%u\n", id, freq, wait, data_len); 2845 p = (struct wmi_send_action_cmd *) skb->data; 2846 p->id = cpu_to_le32(id); 2847 p->freq = cpu_to_le32(freq); 2848 p->wait = cpu_to_le32(wait); 2849 p->len = cpu_to_le16(data_len); 2850 memcpy(p->data, data, data_len); 2851 return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SEND_ACTION_CMDID, 2852 NO_SYNC_WMIFLAG); 2853 } 2854 2855 int ath6kl_wmi_send_probe_response_cmd(struct wmi *wmi, u8 if_idx, u32 freq, 2856 const u8 *dst, const u8 *data, 2857 u16 data_len) 2858 { 2859 struct sk_buff *skb; 2860 struct wmi_p2p_probe_response_cmd *p; 2861 2862 skb = ath6kl_wmi_get_new_buf(sizeof(*p) + data_len); 2863 if (!skb) 2864 return -ENOMEM; 2865 2866 ath6kl_dbg(ATH6KL_DBG_WMI, "send_probe_response_cmd: freq=%u dst=%pM " 2867 "len=%u\n", freq, dst, data_len); 2868 p = (struct wmi_p2p_probe_response_cmd *) skb->data; 2869 p->freq = cpu_to_le32(freq); 2870 memcpy(p->destination_addr, dst, ETH_ALEN); 2871 p->len = cpu_to_le16(data_len); 2872 memcpy(p->data, data, data_len); 2873 return ath6kl_wmi_cmd_send(wmi, if_idx, skb, 2874 WMI_SEND_PROBE_RESPONSE_CMDID, 2875 NO_SYNC_WMIFLAG); 2876 } 2877 2878 int ath6kl_wmi_probe_report_req_cmd(struct wmi *wmi, u8 if_idx, bool enable) 2879 { 2880 struct sk_buff *skb; 2881 struct wmi_probe_req_report_cmd *p; 2882 2883 skb = ath6kl_wmi_get_new_buf(sizeof(*p)); 2884 if (!skb) 2885 return -ENOMEM; 2886 2887 ath6kl_dbg(ATH6KL_DBG_WMI, "probe_report_req_cmd: enable=%u\n", 2888 enable); 2889 p = (struct wmi_probe_req_report_cmd *) skb->data; 2890 p->enable = enable ? 1 : 0; 2891 return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_PROBE_REQ_REPORT_CMDID, 2892 NO_SYNC_WMIFLAG); 2893 } 2894 2895 int ath6kl_wmi_info_req_cmd(struct wmi *wmi, u8 if_idx, u32 info_req_flags) 2896 { 2897 struct sk_buff *skb; 2898 struct wmi_get_p2p_info *p; 2899 2900 skb = ath6kl_wmi_get_new_buf(sizeof(*p)); 2901 if (!skb) 2902 return -ENOMEM; 2903 2904 ath6kl_dbg(ATH6KL_DBG_WMI, "info_req_cmd: flags=%x\n", 2905 info_req_flags); 2906 p = (struct wmi_get_p2p_info *) skb->data; 2907 p->info_req_flags = cpu_to_le32(info_req_flags); 2908 return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_GET_P2P_INFO_CMDID, 2909 NO_SYNC_WMIFLAG); 2910 } 2911 2912 int ath6kl_wmi_cancel_remain_on_chnl_cmd(struct wmi *wmi, u8 if_idx) 2913 { 2914 ath6kl_dbg(ATH6KL_DBG_WMI, "cancel_remain_on_chnl_cmd\n"); 2915 return ath6kl_wmi_simple_cmd(wmi, if_idx, 2916 WMI_CANCEL_REMAIN_ON_CHNL_CMDID); 2917 } 2918 2919 static int ath6kl_wmi_control_rx_xtnd(struct wmi *wmi, struct sk_buff *skb) 2920 { 2921 struct wmix_cmd_hdr *cmd; 2922 u32 len; 2923 u16 id; 2924 u8 *datap; 2925 int ret = 0; 2926 2927 if (skb->len < sizeof(struct wmix_cmd_hdr)) { 2928 ath6kl_err("bad packet 1\n"); 2929 return -EINVAL; 2930 } 2931 2932 cmd = (struct wmix_cmd_hdr *) skb->data; 2933 id = le32_to_cpu(cmd->cmd_id); 2934 2935 skb_pull(skb, sizeof(struct wmix_cmd_hdr)); 2936 2937 datap = skb->data; 2938 len = skb->len; 2939 2940 switch (id) { 2941 case WMIX_HB_CHALLENGE_RESP_EVENTID: 2942 ath6kl_dbg(ATH6KL_DBG_WMI, "wmi event hb challenge resp\n"); 2943 break; 2944 case WMIX_DBGLOG_EVENTID: 2945 ath6kl_dbg(ATH6KL_DBG_WMI, "wmi event dbglog len %d\n", len); 2946 ath6kl_debug_fwlog_event(wmi->parent_dev, datap, len); 2947 break; 2948 default: 2949 ath6kl_warn("unknown cmd id 0x%x\n", id); 2950 ret = -EINVAL; 2951 break; 2952 } 2953 2954 return ret; 2955 } 2956 2957 static int ath6kl_wmi_roam_tbl_event_rx(struct wmi *wmi, u8 *datap, int len) 2958 { 2959 return ath6kl_debug_roam_tbl_event(wmi->parent_dev, datap, len); 2960 } 2961 2962 /* Control Path */ 2963 int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb) 2964 { 2965 struct wmi_cmd_hdr *cmd; 2966 struct ath6kl_vif *vif; 2967 u32 len; 2968 u16 id; 2969 u8 if_idx; 2970 u8 *datap; 2971 int ret = 0; 2972 2973 if (WARN_ON(skb == NULL)) 2974 return -EINVAL; 2975 2976 if (skb->len < sizeof(struct wmi_cmd_hdr)) { 2977 ath6kl_err("bad packet 1\n"); 2978 dev_kfree_skb(skb); 2979 return -EINVAL; 2980 } 2981 2982 cmd = (struct wmi_cmd_hdr *) skb->data; 2983 id = le16_to_cpu(cmd->cmd_id); 2984 if_idx = le16_to_cpu(cmd->info1) & WMI_CMD_HDR_IF_ID_MASK; 2985 2986 skb_pull(skb, sizeof(struct wmi_cmd_hdr)); 2987 2988 datap = skb->data; 2989 len = skb->len; 2990 2991 ath6kl_dbg(ATH6KL_DBG_WMI, "wmi rx id %d len %d\n", id, len); 2992 ath6kl_dbg_dump(ATH6KL_DBG_WMI_DUMP, NULL, "wmi rx ", 2993 datap, len); 2994 2995 vif = ath6kl_get_vif_by_index(wmi->parent_dev, if_idx); 2996 if (!vif) { 2997 ath6kl_dbg(ATH6KL_DBG_WMI, 2998 "Wmi event for unavailable vif, vif_index:%d\n", 2999 if_idx); 3000 dev_kfree_skb(skb); 3001 return -EINVAL; 3002 } 3003 3004 switch (id) { 3005 case WMI_GET_BITRATE_CMDID: 3006 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_BITRATE_CMDID\n"); 3007 ret = ath6kl_wmi_bitrate_reply_rx(wmi, datap, len); 3008 break; 3009 case WMI_GET_CHANNEL_LIST_CMDID: 3010 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_CHANNEL_LIST_CMDID\n"); 3011 ret = ath6kl_wmi_ch_list_reply_rx(wmi, datap, len); 3012 break; 3013 case WMI_GET_TX_PWR_CMDID: 3014 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_TX_PWR_CMDID\n"); 3015 ret = ath6kl_wmi_tx_pwr_reply_rx(wmi, datap, len); 3016 break; 3017 case WMI_READY_EVENTID: 3018 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_READY_EVENTID\n"); 3019 ret = ath6kl_wmi_ready_event_rx(wmi, datap, len); 3020 break; 3021 case WMI_CONNECT_EVENTID: 3022 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CONNECT_EVENTID\n"); 3023 ret = ath6kl_wmi_connect_event_rx(wmi, datap, len, vif); 3024 break; 3025 case WMI_DISCONNECT_EVENTID: 3026 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_DISCONNECT_EVENTID\n"); 3027 ret = ath6kl_wmi_disconnect_event_rx(wmi, datap, len, vif); 3028 break; 3029 case WMI_PEER_NODE_EVENTID: 3030 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_PEER_NODE_EVENTID\n"); 3031 ret = ath6kl_wmi_peer_node_event_rx(wmi, datap, len); 3032 break; 3033 case WMI_TKIP_MICERR_EVENTID: 3034 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TKIP_MICERR_EVENTID\n"); 3035 ret = ath6kl_wmi_tkip_micerr_event_rx(wmi, datap, len, vif); 3036 break; 3037 case WMI_BSSINFO_EVENTID: 3038 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_BSSINFO_EVENTID\n"); 3039 ret = ath6kl_wmi_bssinfo_event_rx(wmi, datap, len, vif); 3040 break; 3041 case WMI_REGDOMAIN_EVENTID: 3042 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REGDOMAIN_EVENTID\n"); 3043 ath6kl_wmi_regdomain_event(wmi, datap, len); 3044 break; 3045 case WMI_PSTREAM_TIMEOUT_EVENTID: 3046 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_PSTREAM_TIMEOUT_EVENTID\n"); 3047 ret = ath6kl_wmi_pstream_timeout_event_rx(wmi, datap, len); 3048 break; 3049 case WMI_NEIGHBOR_REPORT_EVENTID: 3050 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_NEIGHBOR_REPORT_EVENTID\n"); 3051 ret = ath6kl_wmi_neighbor_report_event_rx(wmi, datap, len, 3052 vif); 3053 break; 3054 case WMI_SCAN_COMPLETE_EVENTID: 3055 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_SCAN_COMPLETE_EVENTID\n"); 3056 ret = ath6kl_wmi_scan_complete_rx(wmi, datap, len, vif); 3057 break; 3058 case WMI_CMDERROR_EVENTID: 3059 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CMDERROR_EVENTID\n"); 3060 ret = ath6kl_wmi_error_event_rx(wmi, datap, len); 3061 break; 3062 case WMI_REPORT_STATISTICS_EVENTID: 3063 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REPORT_STATISTICS_EVENTID\n"); 3064 ret = ath6kl_wmi_stats_event_rx(wmi, datap, len, vif); 3065 break; 3066 case WMI_RSSI_THRESHOLD_EVENTID: 3067 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_RSSI_THRESHOLD_EVENTID\n"); 3068 ret = ath6kl_wmi_rssi_threshold_event_rx(wmi, datap, len); 3069 break; 3070 case WMI_ERROR_REPORT_EVENTID: 3071 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_ERROR_REPORT_EVENTID\n"); 3072 break; 3073 case WMI_OPT_RX_FRAME_EVENTID: 3074 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_OPT_RX_FRAME_EVENTID\n"); 3075 /* this event has been deprecated */ 3076 break; 3077 case WMI_REPORT_ROAM_TBL_EVENTID: 3078 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REPORT_ROAM_TBL_EVENTID\n"); 3079 ret = ath6kl_wmi_roam_tbl_event_rx(wmi, datap, len); 3080 break; 3081 case WMI_EXTENSION_EVENTID: 3082 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_EXTENSION_EVENTID\n"); 3083 ret = ath6kl_wmi_control_rx_xtnd(wmi, skb); 3084 break; 3085 case WMI_CAC_EVENTID: 3086 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CAC_EVENTID\n"); 3087 ret = ath6kl_wmi_cac_event_rx(wmi, datap, len, vif); 3088 break; 3089 case WMI_CHANNEL_CHANGE_EVENTID: 3090 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CHANNEL_CHANGE_EVENTID\n"); 3091 break; 3092 case WMI_REPORT_ROAM_DATA_EVENTID: 3093 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REPORT_ROAM_DATA_EVENTID\n"); 3094 break; 3095 case WMI_TEST_EVENTID: 3096 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TEST_EVENTID\n"); 3097 ret = ath6kl_wmi_tcmd_test_report_rx(wmi, datap, len); 3098 break; 3099 case WMI_GET_FIXRATES_CMDID: 3100 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_FIXRATES_CMDID\n"); 3101 ret = ath6kl_wmi_ratemask_reply_rx(wmi, datap, len); 3102 break; 3103 case WMI_TX_RETRY_ERR_EVENTID: 3104 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TX_RETRY_ERR_EVENTID\n"); 3105 break; 3106 case WMI_SNR_THRESHOLD_EVENTID: 3107 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_SNR_THRESHOLD_EVENTID\n"); 3108 ret = ath6kl_wmi_snr_threshold_event_rx(wmi, datap, len); 3109 break; 3110 case WMI_LQ_THRESHOLD_EVENTID: 3111 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_LQ_THRESHOLD_EVENTID\n"); 3112 break; 3113 case WMI_APLIST_EVENTID: 3114 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_APLIST_EVENTID\n"); 3115 ret = ath6kl_wmi_aplist_event_rx(wmi, datap, len); 3116 break; 3117 case WMI_GET_KEEPALIVE_CMDID: 3118 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_KEEPALIVE_CMDID\n"); 3119 ret = ath6kl_wmi_keepalive_reply_rx(wmi, datap, len); 3120 break; 3121 case WMI_GET_WOW_LIST_EVENTID: 3122 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_WOW_LIST_EVENTID\n"); 3123 ret = ath6kl_wmi_get_wow_list_event_rx(wmi, datap, len); 3124 break; 3125 case WMI_GET_PMKID_LIST_EVENTID: 3126 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_PMKID_LIST_EVENTID\n"); 3127 ret = ath6kl_wmi_get_pmkid_list_event_rx(wmi, datap, len); 3128 break; 3129 case WMI_PSPOLL_EVENTID: 3130 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_PSPOLL_EVENTID\n"); 3131 ret = ath6kl_wmi_pspoll_event_rx(wmi, datap, len, vif); 3132 break; 3133 case WMI_DTIMEXPIRY_EVENTID: 3134 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_DTIMEXPIRY_EVENTID\n"); 3135 ret = ath6kl_wmi_dtimexpiry_event_rx(wmi, datap, len, vif); 3136 break; 3137 case WMI_SET_PARAMS_REPLY_EVENTID: 3138 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_SET_PARAMS_REPLY_EVENTID\n"); 3139 break; 3140 case WMI_ADDBA_REQ_EVENTID: 3141 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_ADDBA_REQ_EVENTID\n"); 3142 ret = ath6kl_wmi_addba_req_event_rx(wmi, datap, len, vif); 3143 break; 3144 case WMI_ADDBA_RESP_EVENTID: 3145 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_ADDBA_RESP_EVENTID\n"); 3146 break; 3147 case WMI_DELBA_REQ_EVENTID: 3148 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_DELBA_REQ_EVENTID\n"); 3149 ret = ath6kl_wmi_delba_req_event_rx(wmi, datap, len, vif); 3150 break; 3151 case WMI_REPORT_BTCOEX_CONFIG_EVENTID: 3152 ath6kl_dbg(ATH6KL_DBG_WMI, 3153 "WMI_REPORT_BTCOEX_CONFIG_EVENTID\n"); 3154 break; 3155 case WMI_REPORT_BTCOEX_STATS_EVENTID: 3156 ath6kl_dbg(ATH6KL_DBG_WMI, 3157 "WMI_REPORT_BTCOEX_STATS_EVENTID\n"); 3158 break; 3159 case WMI_TX_COMPLETE_EVENTID: 3160 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TX_COMPLETE_EVENTID\n"); 3161 ret = ath6kl_wmi_tx_complete_event_rx(datap, len); 3162 break; 3163 case WMI_REMAIN_ON_CHNL_EVENTID: 3164 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REMAIN_ON_CHNL_EVENTID\n"); 3165 ret = ath6kl_wmi_remain_on_chnl_event_rx(wmi, datap, len, vif); 3166 break; 3167 case WMI_CANCEL_REMAIN_ON_CHNL_EVENTID: 3168 ath6kl_dbg(ATH6KL_DBG_WMI, 3169 "WMI_CANCEL_REMAIN_ON_CHNL_EVENTID\n"); 3170 ret = ath6kl_wmi_cancel_remain_on_chnl_event_rx(wmi, datap, 3171 len, vif); 3172 break; 3173 case WMI_TX_STATUS_EVENTID: 3174 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TX_STATUS_EVENTID\n"); 3175 ret = ath6kl_wmi_tx_status_event_rx(wmi, datap, len, vif); 3176 break; 3177 case WMI_RX_PROBE_REQ_EVENTID: 3178 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_RX_PROBE_REQ_EVENTID\n"); 3179 ret = ath6kl_wmi_rx_probe_req_event_rx(wmi, datap, len, vif); 3180 break; 3181 case WMI_P2P_CAPABILITIES_EVENTID: 3182 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_P2P_CAPABILITIES_EVENTID\n"); 3183 ret = ath6kl_wmi_p2p_capabilities_event_rx(datap, len); 3184 break; 3185 case WMI_RX_ACTION_EVENTID: 3186 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_RX_ACTION_EVENTID\n"); 3187 ret = ath6kl_wmi_rx_action_event_rx(wmi, datap, len, vif); 3188 break; 3189 case WMI_P2P_INFO_EVENTID: 3190 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_P2P_INFO_EVENTID\n"); 3191 ret = ath6kl_wmi_p2p_info_event_rx(datap, len); 3192 break; 3193 default: 3194 ath6kl_dbg(ATH6KL_DBG_WMI, "unknown cmd id 0x%x\n", id); 3195 ret = -EINVAL; 3196 break; 3197 } 3198 3199 dev_kfree_skb(skb); 3200 3201 return ret; 3202 } 3203 3204 static void ath6kl_wmi_qos_state_init(struct wmi *wmi) 3205 { 3206 if (!wmi) 3207 return; 3208 3209 spin_lock_bh(&wmi->lock); 3210 3211 wmi->fat_pipe_exist = 0; 3212 memset(wmi->stream_exist_for_ac, 0, sizeof(wmi->stream_exist_for_ac)); 3213 3214 spin_unlock_bh(&wmi->lock); 3215 } 3216 3217 void *ath6kl_wmi_init(struct ath6kl *dev) 3218 { 3219 struct wmi *wmi; 3220 3221 wmi = kzalloc(sizeof(struct wmi), GFP_KERNEL); 3222 if (!wmi) 3223 return NULL; 3224 3225 spin_lock_init(&wmi->lock); 3226 3227 wmi->parent_dev = dev; 3228 3229 wmi->pwr_mode = REC_POWER; 3230 3231 ath6kl_wmi_qos_state_init(wmi); 3232 3233 return wmi; 3234 } 3235 3236 void ath6kl_wmi_shutdown(struct wmi *wmi) 3237 { 3238 if (!wmi) 3239 return; 3240 3241 kfree(wmi->last_mgmt_tx_frame); 3242 kfree(wmi); 3243 } 3244