linux/drivers/net/wireless/ath/ath10k/htc.c
<<
>>
Prefs
   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}
1307