htc.c (33949B)
1// SPDX-License-Identifier: ISC 2/* 3 * Copyright (c) 2005-2011 Atheros Communications Inc. 4 * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. 5 */ 6 7#include "core.h" 8#include "hif.h" 9#include "debug.h" 10 11/********/ 12/* Send */ 13/********/ 14 15static void ath10k_htc_control_tx_complete(struct ath10k *ar, 16 struct sk_buff *skb) 17{ 18 kfree_skb(skb); 19} 20 21static struct sk_buff *ath10k_htc_build_tx_ctrl_skb(void *ar) 22{ 23 struct sk_buff *skb; 24 struct ath10k_skb_cb *skb_cb; 25 26 skb = dev_alloc_skb(ATH10K_HTC_CONTROL_BUFFER_SIZE); 27 if (!skb) 28 return NULL; 29 30 skb_reserve(skb, 20); /* FIXME: why 20 bytes? */ 31 WARN_ONCE((unsigned long)skb->data & 3, "unaligned skb"); 32 33 skb_cb = ATH10K_SKB_CB(skb); 34 memset(skb_cb, 0, sizeof(*skb_cb)); 35 36 ath10k_dbg(ar, ATH10K_DBG_HTC, "%s: skb %pK\n", __func__, skb); 37 return skb; 38} 39 40static inline void ath10k_htc_restore_tx_skb(struct ath10k_htc *htc, 41 struct sk_buff *skb) 42{ 43 struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb); 44 45 if (htc->ar->bus_param.dev_type != ATH10K_DEV_TYPE_HL) 46 dma_unmap_single(htc->ar->dev, skb_cb->paddr, skb->len, DMA_TO_DEVICE); 47 skb_pull(skb, sizeof(struct ath10k_htc_hdr)); 48} 49 50void ath10k_htc_notify_tx_completion(struct ath10k_htc_ep *ep, 51 struct sk_buff *skb) 52{ 53 struct ath10k *ar = ep->htc->ar; 54 struct ath10k_htc_hdr *hdr; 55 56 ath10k_dbg(ar, ATH10K_DBG_HTC, "%s: ep %d skb %pK\n", __func__, 57 ep->eid, skb); 58 59 hdr = (struct ath10k_htc_hdr *)skb->data; 60 ath10k_htc_restore_tx_skb(ep->htc, skb); 61 62 if (!ep->ep_ops.ep_tx_complete) { 63 ath10k_warn(ar, "no tx handler for eid %d\n", ep->eid); 64 dev_kfree_skb_any(skb); 65 return; 66 } 67 68 if (hdr->flags & ATH10K_HTC_FLAG_SEND_BUNDLE) { 69 dev_kfree_skb_any(skb); 70 return; 71 } 72 73 ep->ep_ops.ep_tx_complete(ep->htc->ar, skb); 74} 75EXPORT_SYMBOL(ath10k_htc_notify_tx_completion); 76 77static void ath10k_htc_prepare_tx_skb(struct ath10k_htc_ep *ep, 78 struct sk_buff *skb) 79{ 80 struct ath10k_htc_hdr *hdr; 81 82 hdr = (struct ath10k_htc_hdr *)skb->data; 83 memset(hdr, 0, sizeof(struct ath10k_htc_hdr)); 84 85 hdr->eid = ep->eid; 86 hdr->len = __cpu_to_le16(skb->len - sizeof(*hdr)); 87 hdr->flags = 0; 88 if (ep->tx_credit_flow_enabled && !ep->bundle_tx) 89 hdr->flags |= ATH10K_HTC_FLAG_NEED_CREDIT_UPDATE; 90 91 spin_lock_bh(&ep->htc->tx_lock); 92 hdr->seq_no = ep->seq_no++; 93 spin_unlock_bh(&ep->htc->tx_lock); 94} 95 96static int ath10k_htc_consume_credit(struct ath10k_htc_ep *ep, 97 unsigned int len, 98 bool consume) 99{ 100 struct ath10k_htc *htc = ep->htc; 101 struct ath10k *ar = htc->ar; 102 enum ath10k_htc_ep_id eid = ep->eid; 103 int credits, ret = 0; 104 105 if (!ep->tx_credit_flow_enabled) 106 return 0; 107 108 credits = DIV_ROUND_UP(len, ep->tx_credit_size); 109 spin_lock_bh(&htc->tx_lock); 110 111 if (ep->tx_credits < credits) { 112 ath10k_dbg(ar, ATH10K_DBG_HTC, 113 "htc insufficient credits ep %d required %d available %d consume %d\n", 114 eid, credits, ep->tx_credits, consume); 115 ret = -EAGAIN; 116 goto unlock; 117 } 118 119 if (consume) { 120 ep->tx_credits -= credits; 121 ath10k_dbg(ar, ATH10K_DBG_HTC, 122 "htc ep %d consumed %d credits total %d\n", 123 eid, credits, ep->tx_credits); 124 } 125 126unlock: 127 spin_unlock_bh(&htc->tx_lock); 128 return ret; 129} 130 131static void ath10k_htc_release_credit(struct ath10k_htc_ep *ep, unsigned int len) 132{ 133 struct ath10k_htc *htc = ep->htc; 134 struct ath10k *ar = htc->ar; 135 enum ath10k_htc_ep_id eid = ep->eid; 136 int credits; 137 138 if (!ep->tx_credit_flow_enabled) 139 return; 140 141 credits = DIV_ROUND_UP(len, ep->tx_credit_size); 142 spin_lock_bh(&htc->tx_lock); 143 ep->tx_credits += credits; 144 ath10k_dbg(ar, ATH10K_DBG_HTC, 145 "htc ep %d reverted %d credits back total %d\n", 146 eid, credits, ep->tx_credits); 147 spin_unlock_bh(&htc->tx_lock); 148 149 if (ep->ep_ops.ep_tx_credits) 150 ep->ep_ops.ep_tx_credits(htc->ar); 151} 152 153int ath10k_htc_send(struct ath10k_htc *htc, 154 enum ath10k_htc_ep_id eid, 155 struct sk_buff *skb) 156{ 157 struct ath10k *ar = htc->ar; 158 struct ath10k_htc_ep *ep = &htc->endpoint[eid]; 159 struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb); 160 struct ath10k_hif_sg_item sg_item; 161 struct device *dev = htc->ar->dev; 162 int ret; 163 unsigned int skb_len; 164 165 if (htc->ar->state == ATH10K_STATE_WEDGED) 166 return -ECOMM; 167 168 if (eid >= ATH10K_HTC_EP_COUNT) { 169 ath10k_warn(ar, "Invalid endpoint id: %d\n", eid); 170 return -ENOENT; 171 } 172 173 skb_push(skb, sizeof(struct ath10k_htc_hdr)); 174 175 skb_len = skb->len; 176 ret = ath10k_htc_consume_credit(ep, skb_len, true); 177 if (ret) 178 goto err_pull; 179 180 ath10k_htc_prepare_tx_skb(ep, skb); 181 182 skb_cb->eid = eid; 183 if (ar->bus_param.dev_type != ATH10K_DEV_TYPE_HL) { 184 skb_cb->paddr = dma_map_single(dev, skb->data, skb->len, 185 DMA_TO_DEVICE); 186 ret = dma_mapping_error(dev, skb_cb->paddr); 187 if (ret) { 188 ret = -EIO; 189 goto err_credits; 190 } 191 } 192 193 sg_item.transfer_id = ep->eid; 194 sg_item.transfer_context = skb; 195 sg_item.vaddr = skb->data; 196 sg_item.paddr = skb_cb->paddr; 197 sg_item.len = skb->len; 198 199 ret = ath10k_hif_tx_sg(htc->ar, ep->ul_pipe_id, &sg_item, 1); 200 if (ret) 201 goto err_unmap; 202 203 return 0; 204 205err_unmap: 206 if (ar->bus_param.dev_type != ATH10K_DEV_TYPE_HL) 207 dma_unmap_single(dev, skb_cb->paddr, skb->len, DMA_TO_DEVICE); 208err_credits: 209 ath10k_htc_release_credit(ep, skb_len); 210err_pull: 211 skb_pull(skb, sizeof(struct ath10k_htc_hdr)); 212 return ret; 213} 214 215void ath10k_htc_tx_completion_handler(struct ath10k *ar, struct sk_buff *skb) 216{ 217 struct ath10k_htc *htc = &ar->htc; 218 struct ath10k_skb_cb *skb_cb; 219 struct ath10k_htc_ep *ep; 220 221 if (WARN_ON_ONCE(!skb)) 222 return; 223 224 skb_cb = ATH10K_SKB_CB(skb); 225 ep = &htc->endpoint[skb_cb->eid]; 226 227 ath10k_htc_notify_tx_completion(ep, skb); 228 /* the skb now belongs to the completion handler */ 229} 230EXPORT_SYMBOL(ath10k_htc_tx_completion_handler); 231 232/***********/ 233/* Receive */ 234/***********/ 235 236static void 237ath10k_htc_process_credit_report(struct ath10k_htc *htc, 238 const struct ath10k_htc_credit_report *report, 239 int len, 240 enum ath10k_htc_ep_id eid) 241{ 242 struct ath10k *ar = htc->ar; 243 struct ath10k_htc_ep *ep; 244 int i, n_reports; 245 246 if (len % sizeof(*report)) 247 ath10k_warn(ar, "Uneven credit report len %d", len); 248 249 n_reports = len / sizeof(*report); 250 251 spin_lock_bh(&htc->tx_lock); 252 for (i = 0; i < n_reports; i++, report++) { 253 if (report->eid >= ATH10K_HTC_EP_COUNT) 254 break; 255 256 ep = &htc->endpoint[report->eid]; 257 ep->tx_credits += report->credits; 258 259 ath10k_dbg(ar, ATH10K_DBG_HTC, "htc ep %d got %d credits (total %d)\n", 260 report->eid, report->credits, ep->tx_credits); 261 262 if (ep->ep_ops.ep_tx_credits) { 263 spin_unlock_bh(&htc->tx_lock); 264 ep->ep_ops.ep_tx_credits(htc->ar); 265 spin_lock_bh(&htc->tx_lock); 266 } 267 } 268 spin_unlock_bh(&htc->tx_lock); 269} 270 271static int 272ath10k_htc_process_lookahead(struct ath10k_htc *htc, 273 const struct ath10k_htc_lookahead_report *report, 274 int len, 275 enum ath10k_htc_ep_id eid, 276 void *next_lookaheads, 277 int *next_lookaheads_len) 278{ 279 struct ath10k *ar = htc->ar; 280 281 /* Invalid lookahead flags are actually transmitted by 282 * the target in the HTC control message. 283 * Since this will happen at every boot we silently ignore 284 * the lookahead in this case 285 */ 286 if (report->pre_valid != ((~report->post_valid) & 0xFF)) 287 return 0; 288 289 if (next_lookaheads && next_lookaheads_len) { 290 ath10k_dbg(ar, ATH10K_DBG_HTC, 291 "htc rx lookahead found pre_valid 0x%x post_valid 0x%x\n", 292 report->pre_valid, report->post_valid); 293 294 /* look ahead bytes are valid, copy them over */ 295 memcpy((u8 *)next_lookaheads, report->lookahead, 4); 296 297 *next_lookaheads_len = 1; 298 } 299 300 return 0; 301} 302 303static int 304ath10k_htc_process_lookahead_bundle(struct ath10k_htc *htc, 305 const struct ath10k_htc_lookahead_bundle *report, 306 int len, 307 enum ath10k_htc_ep_id eid, 308 void *next_lookaheads, 309 int *next_lookaheads_len) 310{ 311 struct ath10k *ar = htc->ar; 312 int bundle_cnt = len / sizeof(*report); 313 314 if (!bundle_cnt || (bundle_cnt > htc->max_msgs_per_htc_bundle)) { 315 ath10k_warn(ar, "Invalid lookahead bundle count: %d\n", 316 bundle_cnt); 317 return -EINVAL; 318 } 319 320 if (next_lookaheads && next_lookaheads_len) { 321 int i; 322 323 for (i = 0; i < bundle_cnt; i++) { 324 memcpy(((u8 *)next_lookaheads) + 4 * i, 325 report->lookahead, 4); 326 report++; 327 } 328 329 *next_lookaheads_len = bundle_cnt; 330 } 331 332 return 0; 333} 334 335int ath10k_htc_process_trailer(struct ath10k_htc *htc, 336 u8 *buffer, 337 int length, 338 enum ath10k_htc_ep_id src_eid, 339 void *next_lookaheads, 340 int *next_lookaheads_len) 341{ 342 struct ath10k_htc_lookahead_bundle *bundle; 343 struct ath10k *ar = htc->ar; 344 int status = 0; 345 struct ath10k_htc_record *record; 346 u8 *orig_buffer; 347 int orig_length; 348 size_t len; 349 350 orig_buffer = buffer; 351 orig_length = length; 352 353 while (length > 0) { 354 record = (struct ath10k_htc_record *)buffer; 355 356 if (length < sizeof(record->hdr)) { 357 status = -EINVAL; 358 break; 359 } 360 361 if (record->hdr.len > length) { 362 /* no room left in buffer for record */ 363 ath10k_warn(ar, "Invalid record length: %d\n", 364 record->hdr.len); 365 status = -EINVAL; 366 break; 367 } 368 369 switch (record->hdr.id) { 370 case ATH10K_HTC_RECORD_CREDITS: 371 len = sizeof(struct ath10k_htc_credit_report); 372 if (record->hdr.len < len) { 373 ath10k_warn(ar, "Credit report too long\n"); 374 status = -EINVAL; 375 break; 376 } 377 ath10k_htc_process_credit_report(htc, 378 record->credit_report, 379 record->hdr.len, 380 src_eid); 381 break; 382 case ATH10K_HTC_RECORD_LOOKAHEAD: 383 len = sizeof(struct ath10k_htc_lookahead_report); 384 if (record->hdr.len < len) { 385 ath10k_warn(ar, "Lookahead report too long\n"); 386 status = -EINVAL; 387 break; 388 } 389 status = ath10k_htc_process_lookahead(htc, 390 record->lookahead_report, 391 record->hdr.len, 392 src_eid, 393 next_lookaheads, 394 next_lookaheads_len); 395 break; 396 case ATH10K_HTC_RECORD_LOOKAHEAD_BUNDLE: 397 bundle = record->lookahead_bundle; 398 status = ath10k_htc_process_lookahead_bundle(htc, 399 bundle, 400 record->hdr.len, 401 src_eid, 402 next_lookaheads, 403 next_lookaheads_len); 404 break; 405 default: 406 ath10k_warn(ar, "Unhandled record: id:%d length:%d\n", 407 record->hdr.id, record->hdr.len); 408 break; 409 } 410 411 if (status) 412 break; 413 414 /* multiple records may be present in a trailer */ 415 buffer += sizeof(record->hdr) + record->hdr.len; 416 length -= sizeof(record->hdr) + record->hdr.len; 417 } 418 419 if (status) 420 ath10k_dbg_dump(ar, ATH10K_DBG_HTC, "htc rx bad trailer", "", 421 orig_buffer, orig_length); 422 423 return status; 424} 425EXPORT_SYMBOL(ath10k_htc_process_trailer); 426 427void ath10k_htc_rx_completion_handler(struct ath10k *ar, struct sk_buff *skb) 428{ 429 int status = 0; 430 struct ath10k_htc *htc = &ar->htc; 431 struct ath10k_htc_hdr *hdr; 432 struct ath10k_htc_ep *ep; 433 u16 payload_len; 434 u32 trailer_len = 0; 435 size_t min_len; 436 u8 eid; 437 bool trailer_present; 438 439 hdr = (struct ath10k_htc_hdr *)skb->data; 440 skb_pull(skb, sizeof(*hdr)); 441 442 eid = hdr->eid; 443 444 if (eid >= ATH10K_HTC_EP_COUNT) { 445 ath10k_warn(ar, "HTC Rx: invalid eid %d\n", eid); 446 ath10k_dbg_dump(ar, ATH10K_DBG_HTC, "htc bad header", "", 447 hdr, sizeof(*hdr)); 448 goto out; 449 } 450 451 ep = &htc->endpoint[eid]; 452 if (ep->service_id == ATH10K_HTC_SVC_ID_UNUSED) { 453 ath10k_warn(ar, "htc rx endpoint %d is not connected\n", eid); 454 goto out; 455 } 456 457 payload_len = __le16_to_cpu(hdr->len); 458 459 if (payload_len + sizeof(*hdr) > ATH10K_HTC_MAX_LEN) { 460 ath10k_warn(ar, "HTC rx frame too long, len: %zu\n", 461 payload_len + sizeof(*hdr)); 462 ath10k_dbg_dump(ar, ATH10K_DBG_HTC, "htc bad rx pkt len", "", 463 hdr, sizeof(*hdr)); 464 goto out; 465 } 466 467 if (skb->len < payload_len) { 468 ath10k_dbg(ar, ATH10K_DBG_HTC, 469 "HTC Rx: insufficient length, got %d, expected %d\n", 470 skb->len, payload_len); 471 ath10k_dbg_dump(ar, ATH10K_DBG_HTC, "htc bad rx pkt len", 472 "", hdr, sizeof(*hdr)); 473 goto out; 474 } 475 476 /* get flags to check for trailer */ 477 trailer_present = hdr->flags & ATH10K_HTC_FLAG_TRAILER_PRESENT; 478 if (trailer_present) { 479 u8 *trailer; 480 481 trailer_len = hdr->trailer_len; 482 min_len = sizeof(struct ath10k_ath10k_htc_record_hdr); 483 484 if ((trailer_len < min_len) || 485 (trailer_len > payload_len)) { 486 ath10k_warn(ar, "Invalid trailer length: %d\n", 487 trailer_len); 488 goto out; 489 } 490 491 trailer = (u8 *)hdr; 492 trailer += sizeof(*hdr); 493 trailer += payload_len; 494 trailer -= trailer_len; 495 status = ath10k_htc_process_trailer(htc, trailer, 496 trailer_len, hdr->eid, 497 NULL, NULL); 498 if (status) 499 goto out; 500 501 skb_trim(skb, skb->len - trailer_len); 502 } 503 504 if (((int)payload_len - (int)trailer_len) <= 0) 505 /* zero length packet with trailer data, just drop these */ 506 goto out; 507 508 ath10k_dbg(ar, ATH10K_DBG_HTC, "htc rx completion ep %d skb %pK\n", 509 eid, skb); 510 ep->ep_ops.ep_rx_complete(ar, skb); 511 512 /* skb is now owned by the rx completion handler */ 513 skb = NULL; 514out: 515 kfree_skb(skb); 516} 517EXPORT_SYMBOL(ath10k_htc_rx_completion_handler); 518 519static void ath10k_htc_control_rx_complete(struct ath10k *ar, 520 struct sk_buff *skb) 521{ 522 struct ath10k_htc *htc = &ar->htc; 523 struct ath10k_htc_msg *msg = (struct ath10k_htc_msg *)skb->data; 524 525 switch (__le16_to_cpu(msg->hdr.message_id)) { 526 case ATH10K_HTC_MSG_READY_ID: 527 case ATH10K_HTC_MSG_CONNECT_SERVICE_RESP_ID: 528 /* handle HTC control message */ 529 if (completion_done(&htc->ctl_resp)) { 530 /* this is a fatal error, target should not be 531 * sending unsolicited messages on the ep 0 532 */ 533 ath10k_warn(ar, "HTC rx ctrl still processing\n"); 534 complete(&htc->ctl_resp); 535 goto out; 536 } 537 538 htc->control_resp_len = 539 min_t(int, skb->len, 540 ATH10K_HTC_MAX_CTRL_MSG_LEN); 541 542 memcpy(htc->control_resp_buffer, skb->data, 543 htc->control_resp_len); 544 545 complete(&htc->ctl_resp); 546 break; 547 case ATH10K_HTC_MSG_SEND_SUSPEND_COMPLETE: 548 htc->htc_ops.target_send_suspend_complete(ar); 549 break; 550 default: 551 ath10k_warn(ar, "ignoring unsolicited htc ep0 event\n"); 552 break; 553 } 554 555out: 556 kfree_skb(skb); 557} 558 559/***************/ 560/* Init/Deinit */ 561/***************/ 562 563static const char *htc_service_name(enum ath10k_htc_svc_id id) 564{ 565 switch (id) { 566 case ATH10K_HTC_SVC_ID_RESERVED: 567 return "Reserved"; 568 case ATH10K_HTC_SVC_ID_RSVD_CTRL: 569 return "Control"; 570 case ATH10K_HTC_SVC_ID_WMI_CONTROL: 571 return "WMI"; 572 case ATH10K_HTC_SVC_ID_WMI_DATA_BE: 573 return "DATA BE"; 574 case ATH10K_HTC_SVC_ID_WMI_DATA_BK: 575 return "DATA BK"; 576 case ATH10K_HTC_SVC_ID_WMI_DATA_VI: 577 return "DATA VI"; 578 case ATH10K_HTC_SVC_ID_WMI_DATA_VO: 579 return "DATA VO"; 580 case ATH10K_HTC_SVC_ID_NMI_CONTROL: 581 return "NMI Control"; 582 case ATH10K_HTC_SVC_ID_NMI_DATA: 583 return "NMI Data"; 584 case ATH10K_HTC_SVC_ID_HTT_DATA_MSG: 585 return "HTT Data"; 586 case ATH10K_HTC_SVC_ID_HTT_DATA2_MSG: 587 return "HTT Data"; 588 case ATH10K_HTC_SVC_ID_HTT_DATA3_MSG: 589 return "HTT Data"; 590 case ATH10K_HTC_SVC_ID_TEST_RAW_STREAMS: 591 return "RAW"; 592 case ATH10K_HTC_SVC_ID_HTT_LOG_MSG: 593 return "PKTLOG"; 594 } 595 596 return "Unknown"; 597} 598 599static void ath10k_htc_reset_endpoint_states(struct ath10k_htc *htc) 600{ 601 struct ath10k_htc_ep *ep; 602 int i; 603 604 for (i = ATH10K_HTC_EP_0; i < ATH10K_HTC_EP_COUNT; i++) { 605 ep = &htc->endpoint[i]; 606 ep->service_id = ATH10K_HTC_SVC_ID_UNUSED; 607 ep->max_ep_message_len = 0; 608 ep->max_tx_queue_depth = 0; 609 ep->eid = i; 610 ep->htc = htc; 611 ep->tx_credit_flow_enabled = true; 612 } 613} 614 615static u8 ath10k_htc_get_credit_allocation(struct ath10k_htc *htc, 616 u16 service_id) 617{ 618 u8 allocation = 0; 619 620 /* The WMI control service is the only service with flow control. 621 * Let it have all transmit credits. 622 */ 623 if (service_id == ATH10K_HTC_SVC_ID_WMI_CONTROL) 624 allocation = htc->total_transmit_credits; 625 626 return allocation; 627} 628 629static int ath10k_htc_send_bundle(struct ath10k_htc_ep *ep, 630 struct sk_buff *bundle_skb, 631 struct sk_buff_head *tx_save_head) 632{ 633 struct ath10k_hif_sg_item sg_item; 634 struct ath10k_htc *htc = ep->htc; 635 struct ath10k *ar = htc->ar; 636 struct sk_buff *skb; 637 int ret, cn = 0; 638 unsigned int skb_len; 639 640 ath10k_dbg(ar, ATH10K_DBG_HTC, "bundle skb len %d\n", bundle_skb->len); 641 skb_len = bundle_skb->len; 642 ret = ath10k_htc_consume_credit(ep, skb_len, true); 643 644 if (!ret) { 645 sg_item.transfer_id = ep->eid; 646 sg_item.transfer_context = bundle_skb; 647 sg_item.vaddr = bundle_skb->data; 648 sg_item.len = bundle_skb->len; 649 650 ret = ath10k_hif_tx_sg(htc->ar, ep->ul_pipe_id, &sg_item, 1); 651 if (ret) 652 ath10k_htc_release_credit(ep, skb_len); 653 } 654 655 if (ret) 656 dev_kfree_skb_any(bundle_skb); 657 658 for (cn = 0; (skb = skb_dequeue_tail(tx_save_head)); cn++) { 659 if (ret) { 660 skb_pull(skb, sizeof(struct ath10k_htc_hdr)); 661 skb_queue_head(&ep->tx_req_head, skb); 662 } else { 663 skb_queue_tail(&ep->tx_complete_head, skb); 664 } 665 } 666 667 if (!ret) 668 queue_work(ar->workqueue_tx_complete, &ar->tx_complete_work); 669 670 ath10k_dbg(ar, ATH10K_DBG_HTC, 671 "bundle tx status %d eid %d req count %d count %d len %d\n", 672 ret, ep->eid, skb_queue_len(&ep->tx_req_head), cn, skb_len); 673 return ret; 674} 675 676static void ath10k_htc_send_one_skb(struct ath10k_htc_ep *ep, struct sk_buff *skb) 677{ 678 struct ath10k_htc *htc = ep->htc; 679 struct ath10k *ar = htc->ar; 680 int ret; 681 682 ret = ath10k_htc_send(htc, ep->eid, skb); 683 684 if (ret) 685 skb_queue_head(&ep->tx_req_head, skb); 686 687 ath10k_dbg(ar, ATH10K_DBG_HTC, "tx one status %d eid %d len %d pending count %d\n", 688 ret, ep->eid, skb->len, skb_queue_len(&ep->tx_req_head)); 689} 690 691static int ath10k_htc_send_bundle_skbs(struct ath10k_htc_ep *ep) 692{ 693 struct ath10k_htc *htc = ep->htc; 694 struct sk_buff *bundle_skb, *skb; 695 struct sk_buff_head tx_save_head; 696 struct ath10k_htc_hdr *hdr; 697 u8 *bundle_buf; 698 int ret = 0, credit_pad, credit_remainder, trans_len, bundles_left = 0; 699 700 if (htc->ar->state == ATH10K_STATE_WEDGED) 701 return -ECOMM; 702 703 if (ep->tx_credit_flow_enabled && 704 ep->tx_credits < ATH10K_MIN_CREDIT_PER_HTC_TX_BUNDLE) 705 return 0; 706 707 bundles_left = ATH10K_MAX_MSG_PER_HTC_TX_BUNDLE * ep->tx_credit_size; 708 bundle_skb = dev_alloc_skb(bundles_left); 709 710 if (!bundle_skb) 711 return -ENOMEM; 712 713 bundle_buf = bundle_skb->data; 714 skb_queue_head_init(&tx_save_head); 715 716 while (true) { 717 skb = skb_dequeue(&ep->tx_req_head); 718 if (!skb) 719 break; 720 721 credit_pad = 0; 722 trans_len = skb->len + sizeof(*hdr); 723 credit_remainder = trans_len % ep->tx_credit_size; 724 725 if (credit_remainder != 0) { 726 credit_pad = ep->tx_credit_size - credit_remainder; 727 trans_len += credit_pad; 728 } 729 730 ret = ath10k_htc_consume_credit(ep, 731 bundle_buf + trans_len - bundle_skb->data, 732 false); 733 if (ret) { 734 skb_queue_head(&ep->tx_req_head, skb); 735 break; 736 } 737 738 if (bundles_left < trans_len) { 739 bundle_skb->len = bundle_buf - bundle_skb->data; 740 ret = ath10k_htc_send_bundle(ep, bundle_skb, &tx_save_head); 741 742 if (ret) { 743 skb_queue_head(&ep->tx_req_head, skb); 744 return ret; 745 } 746 747 if (skb_queue_len(&ep->tx_req_head) == 0) { 748 ath10k_htc_send_one_skb(ep, skb); 749 return ret; 750 } 751 752 if (ep->tx_credit_flow_enabled && 753 ep->tx_credits < ATH10K_MIN_CREDIT_PER_HTC_TX_BUNDLE) { 754 skb_queue_head(&ep->tx_req_head, skb); 755 return 0; 756 } 757 758 bundles_left = 759 ATH10K_MAX_MSG_PER_HTC_TX_BUNDLE * ep->tx_credit_size; 760 bundle_skb = dev_alloc_skb(bundles_left); 761 762 if (!bundle_skb) { 763 skb_queue_head(&ep->tx_req_head, skb); 764 return -ENOMEM; 765 } 766 bundle_buf = bundle_skb->data; 767 skb_queue_head_init(&tx_save_head); 768 } 769 770 skb_push(skb, sizeof(struct ath10k_htc_hdr)); 771 ath10k_htc_prepare_tx_skb(ep, skb); 772 773 memcpy(bundle_buf, skb->data, skb->len); 774 hdr = (struct ath10k_htc_hdr *)bundle_buf; 775 hdr->flags |= ATH10K_HTC_FLAG_SEND_BUNDLE; 776 hdr->pad_len = __cpu_to_le16(credit_pad); 777 bundle_buf += trans_len; 778 bundles_left -= trans_len; 779 skb_queue_tail(&tx_save_head, skb); 780 } 781 782 if (bundle_buf != bundle_skb->data) { 783 bundle_skb->len = bundle_buf - bundle_skb->data; 784 ret = ath10k_htc_send_bundle(ep, bundle_skb, &tx_save_head); 785 } else { 786 dev_kfree_skb_any(bundle_skb); 787 } 788 789 return ret; 790} 791 792static void ath10k_htc_bundle_tx_work(struct work_struct *work) 793{ 794 struct ath10k *ar = container_of(work, struct ath10k, bundle_tx_work); 795 struct ath10k_htc_ep *ep; 796 struct sk_buff *skb; 797 int i; 798 799 for (i = 0; i < ARRAY_SIZE(ar->htc.endpoint); i++) { 800 ep = &ar->htc.endpoint[i]; 801 802 if (!ep->bundle_tx) 803 continue; 804 805 ath10k_dbg(ar, ATH10K_DBG_HTC, "bundle tx work eid %d count %d\n", 806 ep->eid, skb_queue_len(&ep->tx_req_head)); 807 808 if (skb_queue_len(&ep->tx_req_head) >= 809 ATH10K_MIN_MSG_PER_HTC_TX_BUNDLE) { 810 ath10k_htc_send_bundle_skbs(ep); 811 } else { 812 skb = skb_dequeue(&ep->tx_req_head); 813 814 if (!skb) 815 continue; 816 ath10k_htc_send_one_skb(ep, skb); 817 } 818 } 819} 820 821static void ath10k_htc_tx_complete_work(struct work_struct *work) 822{ 823 struct ath10k *ar = container_of(work, struct ath10k, tx_complete_work); 824 struct ath10k_htc_ep *ep; 825 enum ath10k_htc_ep_id eid; 826 struct sk_buff *skb; 827 int i; 828 829 for (i = 0; i < ARRAY_SIZE(ar->htc.endpoint); i++) { 830 ep = &ar->htc.endpoint[i]; 831 eid = ep->eid; 832 if (ep->bundle_tx && eid == ar->htt.eid) { 833 ath10k_dbg(ar, ATH10K_DBG_HTC, "bundle tx complete eid %d pending complete count%d\n", 834 ep->eid, skb_queue_len(&ep->tx_complete_head)); 835 836 while (true) { 837 skb = skb_dequeue(&ep->tx_complete_head); 838 if (!skb) 839 break; 840 ath10k_htc_notify_tx_completion(ep, skb); 841 } 842 } 843 } 844} 845 846int ath10k_htc_send_hl(struct ath10k_htc *htc, 847 enum ath10k_htc_ep_id eid, 848 struct sk_buff *skb) 849{ 850 struct ath10k_htc_ep *ep = &htc->endpoint[eid]; 851 struct ath10k *ar = htc->ar; 852 853 if (sizeof(struct ath10k_htc_hdr) + skb->len > ep->tx_credit_size) { 854 ath10k_dbg(ar, ATH10K_DBG_HTC, "tx exceed max len %d\n", skb->len); 855 return -ENOMEM; 856 } 857 858 ath10k_dbg(ar, ATH10K_DBG_HTC, "htc send hl eid %d bundle %d tx count %d len %d\n", 859 eid, ep->bundle_tx, skb_queue_len(&ep->tx_req_head), skb->len); 860 861 if (ep->bundle_tx) { 862 skb_queue_tail(&ep->tx_req_head, skb); 863 queue_work(ar->workqueue, &ar->bundle_tx_work); 864 return 0; 865 } else { 866 return ath10k_htc_send(htc, eid, skb); 867 } 868} 869 870void ath10k_htc_setup_tx_req(struct ath10k_htc_ep *ep) 871{ 872 if (ep->htc->max_msgs_per_htc_bundle >= ATH10K_MIN_MSG_PER_HTC_TX_BUNDLE && 873 !ep->bundle_tx) { 874 ep->bundle_tx = true; 875 skb_queue_head_init(&ep->tx_req_head); 876 skb_queue_head_init(&ep->tx_complete_head); 877 } 878} 879 880void ath10k_htc_stop_hl(struct ath10k *ar) 881{ 882 struct ath10k_htc_ep *ep; 883 int i; 884 885 cancel_work_sync(&ar->bundle_tx_work); 886 cancel_work_sync(&ar->tx_complete_work); 887 888 for (i = 0; i < ARRAY_SIZE(ar->htc.endpoint); i++) { 889 ep = &ar->htc.endpoint[i]; 890 891 if (!ep->bundle_tx) 892 continue; 893 894 ath10k_dbg(ar, ATH10K_DBG_HTC, "stop tx work eid %d count %d\n", 895 ep->eid, skb_queue_len(&ep->tx_req_head)); 896 897 skb_queue_purge(&ep->tx_req_head); 898 } 899} 900 901int ath10k_htc_wait_target(struct ath10k_htc *htc) 902{ 903 struct ath10k *ar = htc->ar; 904 int i, status = 0; 905 unsigned long time_left; 906 struct ath10k_htc_msg *msg; 907 u16 message_id; 908 909 time_left = wait_for_completion_timeout(&htc->ctl_resp, 910 ATH10K_HTC_WAIT_TIMEOUT_HZ); 911 if (!time_left) { 912 /* Workaround: In some cases the PCI HIF doesn't 913 * receive interrupt for the control response message 914 * even if the buffer was completed. It is suspected 915 * iomap writes unmasking PCI CE irqs aren't propagated 916 * properly in KVM PCI-passthrough sometimes. 917 */ 918 ath10k_warn(ar, "failed to receive control response completion, polling..\n"); 919 920 for (i = 0; i < CE_COUNT; i++) 921 ath10k_hif_send_complete_check(htc->ar, i, 1); 922 923 time_left = 924 wait_for_completion_timeout(&htc->ctl_resp, 925 ATH10K_HTC_WAIT_TIMEOUT_HZ); 926 927 if (!time_left) 928 status = -ETIMEDOUT; 929 } 930 931 if (status < 0) { 932 ath10k_err(ar, "ctl_resp never came in (%d)\n", status); 933 return status; 934 } 935 936 if (htc->control_resp_len < sizeof(msg->hdr) + sizeof(msg->ready)) { 937 ath10k_err(ar, "Invalid HTC ready msg len:%d\n", 938 htc->control_resp_len); 939 return -ECOMM; 940 } 941 942 msg = (struct ath10k_htc_msg *)htc->control_resp_buffer; 943 message_id = __le16_to_cpu(msg->hdr.message_id); 944 945 if (message_id != ATH10K_HTC_MSG_READY_ID) { 946 ath10k_err(ar, "Invalid HTC ready msg: 0x%x\n", message_id); 947 return -ECOMM; 948 } 949 950 htc->total_transmit_credits = __le16_to_cpu(msg->ready.credit_count); 951 htc->target_credit_size = __le16_to_cpu(msg->ready.credit_size); 952 953 ath10k_dbg(ar, ATH10K_DBG_HTC, 954 "Target ready! transmit resources: %d size:%d\n", 955 htc->total_transmit_credits, 956 htc->target_credit_size); 957 958 if ((htc->total_transmit_credits == 0) || 959 (htc->target_credit_size == 0)) { 960 ath10k_err(ar, "Invalid credit size received\n"); 961 return -ECOMM; 962 } 963 964 /* The only way to determine if the ready message is an extended 965 * message is from the size. 966 */ 967 if (htc->control_resp_len >= 968 sizeof(msg->hdr) + sizeof(msg->ready_ext)) { 969 htc->alt_data_credit_size = 970 __le16_to_cpu(msg->ready_ext.reserved) & 971 ATH10K_HTC_MSG_READY_EXT_ALT_DATA_MASK; 972 htc->max_msgs_per_htc_bundle = 973 min_t(u8, msg->ready_ext.max_msgs_per_htc_bundle, 974 HTC_HOST_MAX_MSG_PER_RX_BUNDLE); 975 ath10k_dbg(ar, ATH10K_DBG_HTC, 976 "Extended ready message RX bundle size %d alt size %d\n", 977 htc->max_msgs_per_htc_bundle, 978 htc->alt_data_credit_size); 979 } 980 981 INIT_WORK(&ar->bundle_tx_work, ath10k_htc_bundle_tx_work); 982 INIT_WORK(&ar->tx_complete_work, ath10k_htc_tx_complete_work); 983 984 return 0; 985} 986 987void ath10k_htc_change_tx_credit_flow(struct ath10k_htc *htc, 988 enum ath10k_htc_ep_id eid, 989 bool enable) 990{ 991 struct ath10k *ar = htc->ar; 992 struct ath10k_htc_ep *ep = &ar->htc.endpoint[eid]; 993 994 ep->tx_credit_flow_enabled = enable; 995} 996 997int ath10k_htc_connect_service(struct ath10k_htc *htc, 998 struct ath10k_htc_svc_conn_req *conn_req, 999 struct ath10k_htc_svc_conn_resp *conn_resp) 1000{ 1001 struct ath10k *ar = htc->ar; 1002 struct ath10k_htc_msg *msg; 1003 struct ath10k_htc_conn_svc *req_msg; 1004 struct ath10k_htc_conn_svc_response resp_msg_dummy; 1005 struct ath10k_htc_conn_svc_response *resp_msg = &resp_msg_dummy; 1006 enum ath10k_htc_ep_id assigned_eid = ATH10K_HTC_EP_COUNT; 1007 struct ath10k_htc_ep *ep; 1008 struct sk_buff *skb; 1009 unsigned int max_msg_size = 0; 1010 int length, status; 1011 unsigned long time_left; 1012 bool disable_credit_flow_ctrl = false; 1013 u16 message_id, service_id, flags = 0; 1014 u8 tx_alloc = 0; 1015 1016 /* special case for HTC pseudo control service */ 1017 if (conn_req->service_id == ATH10K_HTC_SVC_ID_RSVD_CTRL) { 1018 disable_credit_flow_ctrl = true; 1019 assigned_eid = ATH10K_HTC_EP_0; 1020 max_msg_size = ATH10K_HTC_MAX_CTRL_MSG_LEN; 1021 memset(&resp_msg_dummy, 0, sizeof(resp_msg_dummy)); 1022 goto setup; 1023 } 1024 1025 tx_alloc = ath10k_htc_get_credit_allocation(htc, 1026 conn_req->service_id); 1027 if (!tx_alloc) 1028 ath10k_dbg(ar, ATH10K_DBG_BOOT, 1029 "boot htc service %s does not allocate target credits\n", 1030 htc_service_name(conn_req->service_id)); 1031 1032 skb = ath10k_htc_build_tx_ctrl_skb(htc->ar); 1033 if (!skb) { 1034 ath10k_err(ar, "Failed to allocate HTC packet\n"); 1035 return -ENOMEM; 1036 } 1037 1038 length = sizeof(msg->hdr) + sizeof(msg->connect_service); 1039 skb_put(skb, length); 1040 memset(skb->data, 0, length); 1041 1042 msg = (struct ath10k_htc_msg *)skb->data; 1043 msg->hdr.message_id = 1044 __cpu_to_le16(ATH10K_HTC_MSG_CONNECT_SERVICE_ID); 1045 1046 flags |= SM(tx_alloc, ATH10K_HTC_CONN_FLAGS_RECV_ALLOC); 1047 1048 /* Only enable credit flow control for WMI ctrl service */ 1049 if (conn_req->service_id != ATH10K_HTC_SVC_ID_WMI_CONTROL) { 1050 flags |= ATH10K_HTC_CONN_FLAGS_DISABLE_CREDIT_FLOW_CTRL; 1051 disable_credit_flow_ctrl = true; 1052 } 1053 1054 req_msg = &msg->connect_service; 1055 req_msg->flags = __cpu_to_le16(flags); 1056 req_msg->service_id = __cpu_to_le16(conn_req->service_id); 1057 1058 reinit_completion(&htc->ctl_resp); 1059 1060 status = ath10k_htc_send(htc, ATH10K_HTC_EP_0, skb); 1061 if (status) { 1062 kfree_skb(skb); 1063 return status; 1064 } 1065 1066 /* wait for response */ 1067 time_left = wait_for_completion_timeout(&htc->ctl_resp, 1068 ATH10K_HTC_CONN_SVC_TIMEOUT_HZ); 1069 if (!time_left) { 1070 ath10k_err(ar, "Service connect timeout\n"); 1071 return -ETIMEDOUT; 1072 } 1073 1074 /* we controlled the buffer creation, it's aligned */ 1075 msg = (struct ath10k_htc_msg *)htc->control_resp_buffer; 1076 resp_msg = &msg->connect_service_response; 1077 message_id = __le16_to_cpu(msg->hdr.message_id); 1078 service_id = __le16_to_cpu(resp_msg->service_id); 1079 1080 if ((message_id != ATH10K_HTC_MSG_CONNECT_SERVICE_RESP_ID) || 1081 (htc->control_resp_len < sizeof(msg->hdr) + 1082 sizeof(msg->connect_service_response))) { 1083 ath10k_err(ar, "Invalid resp message ID 0x%x", message_id); 1084 return -EPROTO; 1085 } 1086 1087 ath10k_dbg(ar, ATH10K_DBG_HTC, 1088 "HTC Service %s connect response: status: 0x%x, assigned ep: 0x%x\n", 1089 htc_service_name(service_id), 1090 resp_msg->status, resp_msg->eid); 1091 1092 conn_resp->connect_resp_code = resp_msg->status; 1093 1094 /* check response status */ 1095 if (resp_msg->status != ATH10K_HTC_CONN_SVC_STATUS_SUCCESS) { 1096 ath10k_err(ar, "HTC Service %s connect request failed: 0x%x)\n", 1097 htc_service_name(service_id), 1098 resp_msg->status); 1099 return -EPROTO; 1100 } 1101 1102 assigned_eid = (enum ath10k_htc_ep_id)resp_msg->eid; 1103 max_msg_size = __le16_to_cpu(resp_msg->max_msg_size); 1104 1105setup: 1106 1107 if (assigned_eid >= ATH10K_HTC_EP_COUNT) 1108 return -EPROTO; 1109 1110 if (max_msg_size == 0) 1111 return -EPROTO; 1112 1113 ep = &htc->endpoint[assigned_eid]; 1114 ep->eid = assigned_eid; 1115 1116 if (ep->service_id != ATH10K_HTC_SVC_ID_UNUSED) 1117 return -EPROTO; 1118 1119 /* return assigned endpoint to caller */ 1120 conn_resp->eid = assigned_eid; 1121 conn_resp->max_msg_len = __le16_to_cpu(resp_msg->max_msg_size); 1122 1123 /* setup the endpoint */ 1124 ep->service_id = conn_req->service_id; 1125 ep->max_tx_queue_depth = conn_req->max_send_queue_depth; 1126 ep->max_ep_message_len = __le16_to_cpu(resp_msg->max_msg_size); 1127 ep->tx_credits = tx_alloc; 1128 ep->tx_credit_size = htc->target_credit_size; 1129 1130 if (conn_req->service_id == ATH10K_HTC_SVC_ID_HTT_DATA_MSG && 1131 htc->alt_data_credit_size != 0) 1132 ep->tx_credit_size = htc->alt_data_credit_size; 1133 1134 /* copy all the callbacks */ 1135 ep->ep_ops = conn_req->ep_ops; 1136 1137 status = ath10k_hif_map_service_to_pipe(htc->ar, 1138 ep->service_id, 1139 &ep->ul_pipe_id, 1140 &ep->dl_pipe_id); 1141 if (status) { 1142 ath10k_dbg(ar, ATH10K_DBG_BOOT, "unsupported HTC service id: %d\n", 1143 ep->service_id); 1144 return status; 1145 } 1146 1147 ath10k_dbg(ar, ATH10K_DBG_BOOT, 1148 "boot htc service '%s' ul pipe %d dl pipe %d eid %d ready\n", 1149 htc_service_name(ep->service_id), ep->ul_pipe_id, 1150 ep->dl_pipe_id, ep->eid); 1151 1152 if (disable_credit_flow_ctrl && ep->tx_credit_flow_enabled) { 1153 ep->tx_credit_flow_enabled = false; 1154 ath10k_dbg(ar, ATH10K_DBG_BOOT, 1155 "boot htc service '%s' eid %d TX flow control disabled\n", 1156 htc_service_name(ep->service_id), assigned_eid); 1157 } 1158 1159 return status; 1160} 1161 1162struct sk_buff *ath10k_htc_alloc_skb(struct ath10k *ar, int size) 1163{ 1164 struct sk_buff *skb; 1165 1166 skb = dev_alloc_skb(size + sizeof(struct ath10k_htc_hdr)); 1167 if (!skb) 1168 return NULL; 1169 1170 skb_reserve(skb, sizeof(struct ath10k_htc_hdr)); 1171 1172 /* FW/HTC requires 4-byte aligned streams */ 1173 if (!IS_ALIGNED((unsigned long)skb->data, 4)) 1174 ath10k_warn(ar, "Unaligned HTC tx skb\n"); 1175 1176 return skb; 1177} 1178 1179static void ath10k_htc_pktlog_process_rx(struct ath10k *ar, struct sk_buff *skb) 1180{ 1181 trace_ath10k_htt_pktlog(ar, skb->data, skb->len); 1182 dev_kfree_skb_any(skb); 1183} 1184 1185static int ath10k_htc_pktlog_connect(struct ath10k *ar) 1186{ 1187 struct ath10k_htc_svc_conn_resp conn_resp; 1188 struct ath10k_htc_svc_conn_req conn_req; 1189 int status; 1190 1191 memset(&conn_req, 0, sizeof(conn_req)); 1192 memset(&conn_resp, 0, sizeof(conn_resp)); 1193 1194 conn_req.ep_ops.ep_tx_complete = NULL; 1195 conn_req.ep_ops.ep_rx_complete = ath10k_htc_pktlog_process_rx; 1196 conn_req.ep_ops.ep_tx_credits = NULL; 1197 1198 /* connect to control service */ 1199 conn_req.service_id = ATH10K_HTC_SVC_ID_HTT_LOG_MSG; 1200 status = ath10k_htc_connect_service(&ar->htc, &conn_req, &conn_resp); 1201 if (status) { 1202 ath10k_warn(ar, "failed to connect to PKTLOG service: %d\n", 1203 status); 1204 return status; 1205 } 1206 1207 return 0; 1208} 1209 1210static bool ath10k_htc_pktlog_svc_supported(struct ath10k *ar) 1211{ 1212 u8 ul_pipe_id; 1213 u8 dl_pipe_id; 1214 int status; 1215 1216 status = ath10k_hif_map_service_to_pipe(ar, ATH10K_HTC_SVC_ID_HTT_LOG_MSG, 1217 &ul_pipe_id, 1218 &dl_pipe_id); 1219 if (status) { 1220 ath10k_dbg(ar, ATH10K_DBG_BOOT, "unsupported HTC pktlog service id: %d\n", 1221 ATH10K_HTC_SVC_ID_HTT_LOG_MSG); 1222 1223 return false; 1224 } 1225 1226 return true; 1227} 1228 1229int ath10k_htc_start(struct ath10k_htc *htc) 1230{ 1231 struct ath10k *ar = htc->ar; 1232 struct sk_buff *skb; 1233 int status = 0; 1234 struct ath10k_htc_msg *msg; 1235 1236 skb = ath10k_htc_build_tx_ctrl_skb(htc->ar); 1237 if (!skb) 1238 return -ENOMEM; 1239 1240 skb_put(skb, sizeof(msg->hdr) + sizeof(msg->setup_complete_ext)); 1241 memset(skb->data, 0, skb->len); 1242 1243 msg = (struct ath10k_htc_msg *)skb->data; 1244 msg->hdr.message_id = 1245 __cpu_to_le16(ATH10K_HTC_MSG_SETUP_COMPLETE_EX_ID); 1246 1247 if (ar->hif.bus == ATH10K_BUS_SDIO) { 1248 /* Extra setup params used by SDIO */ 1249 msg->setup_complete_ext.flags = 1250 __cpu_to_le32(ATH10K_HTC_SETUP_COMPLETE_FLAGS_RX_BNDL_EN); 1251 msg->setup_complete_ext.max_msgs_per_bundled_recv = 1252 htc->max_msgs_per_htc_bundle; 1253 } 1254 ath10k_dbg(ar, ATH10K_DBG_HTC, "HTC is using TX credit flow control\n"); 1255 1256 status = ath10k_htc_send(htc, ATH10K_HTC_EP_0, skb); 1257 if (status) { 1258 kfree_skb(skb); 1259 return status; 1260 } 1261 1262 if (ath10k_htc_pktlog_svc_supported(ar)) { 1263 status = ath10k_htc_pktlog_connect(ar); 1264 if (status) { 1265 ath10k_err(ar, "failed to connect to pktlog: %d\n", status); 1266 return status; 1267 } 1268 } 1269 1270 return 0; 1271} 1272 1273/* registered target arrival callback from the HIF layer */ 1274int ath10k_htc_init(struct ath10k *ar) 1275{ 1276 int status; 1277 struct ath10k_htc *htc = &ar->htc; 1278 struct ath10k_htc_svc_conn_req conn_req; 1279 struct ath10k_htc_svc_conn_resp conn_resp; 1280 1281 spin_lock_init(&htc->tx_lock); 1282 1283 ath10k_htc_reset_endpoint_states(htc); 1284 1285 htc->ar = ar; 1286 1287 /* setup our pseudo HTC control endpoint connection */ 1288 memset(&conn_req, 0, sizeof(conn_req)); 1289 memset(&conn_resp, 0, sizeof(conn_resp)); 1290 conn_req.ep_ops.ep_tx_complete = ath10k_htc_control_tx_complete; 1291 conn_req.ep_ops.ep_rx_complete = ath10k_htc_control_rx_complete; 1292 conn_req.max_send_queue_depth = ATH10K_NUM_CONTROL_TX_BUFFERS; 1293 conn_req.service_id = ATH10K_HTC_SVC_ID_RSVD_CTRL; 1294 1295 /* connect fake service */ 1296 status = ath10k_htc_connect_service(htc, &conn_req, &conn_resp); 1297 if (status) { 1298 ath10k_err(ar, "could not connect to htc service (%d)\n", 1299 status); 1300 return status; 1301 } 1302 1303 init_completion(&htc->ctl_resp); 1304 1305 return 0; 1306}