linux/drivers/net/wireless/ath/ath10k/htc.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2005-2011 Atheros Communications Inc.
   3 * Copyright (c) 2011-2013 Qualcomm Atheros, Inc.
   4 *
   5 * Permission to use, copy, modify, and/or distribute this software for any
   6 * purpose with or without fee is hereby granted, provided that the above
   7 * copyright notice and this permission notice appear in all copies.
   8 *
   9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16 */
  17
  18#include "core.h"
  19#include "hif.h"
  20#include "debug.h"
  21
  22/********/
  23/* Send */
  24/********/
  25
  26static inline void ath10k_htc_send_complete_check(struct ath10k_htc_ep *ep,
  27                                                  int force)
  28{
  29        /*
  30         * Check whether HIF has any prior sends that have finished,
  31         * have not had the post-processing done.
  32         */
  33        ath10k_hif_send_complete_check(ep->htc->ar, ep->ul_pipe_id, force);
  34}
  35
  36static void ath10k_htc_control_tx_complete(struct ath10k *ar,
  37                                           struct sk_buff *skb)
  38{
  39        kfree_skb(skb);
  40}
  41
  42static struct sk_buff *ath10k_htc_build_tx_ctrl_skb(void *ar)
  43{
  44        struct sk_buff *skb;
  45        struct ath10k_skb_cb *skb_cb;
  46
  47        skb = dev_alloc_skb(ATH10K_HTC_CONTROL_BUFFER_SIZE);
  48        if (!skb) {
  49                ath10k_warn("Unable to allocate ctrl skb\n");
  50                return NULL;
  51        }
  52
  53        skb_reserve(skb, 20); /* FIXME: why 20 bytes? */
  54        WARN_ONCE((unsigned long)skb->data & 3, "unaligned skb");
  55
  56        skb_cb = ATH10K_SKB_CB(skb);
  57        memset(skb_cb, 0, sizeof(*skb_cb));
  58
  59        ath10k_dbg(ATH10K_DBG_HTC, "%s: skb %p\n", __func__, skb);
  60        return skb;
  61}
  62
  63static inline void ath10k_htc_restore_tx_skb(struct ath10k_htc *htc,
  64                                             struct sk_buff *skb)
  65{
  66        ath10k_skb_unmap(htc->ar->dev, skb);
  67        skb_pull(skb, sizeof(struct ath10k_htc_hdr));
  68}
  69
  70static void ath10k_htc_notify_tx_completion(struct ath10k_htc_ep *ep,
  71                                            struct sk_buff *skb)
  72{
  73        ath10k_dbg(ATH10K_DBG_HTC, "%s: ep %d skb %p\n", __func__,
  74                   ep->eid, skb);
  75
  76        ath10k_htc_restore_tx_skb(ep->htc, skb);
  77
  78        if (!ep->ep_ops.ep_tx_complete) {
  79                ath10k_warn("no tx handler for eid %d\n", ep->eid);
  80                dev_kfree_skb_any(skb);
  81                return;
  82        }
  83
  84        ep->ep_ops.ep_tx_complete(ep->htc->ar, skb);
  85}
  86
  87/* assumes tx_lock is held */
  88static bool ath10k_htc_ep_need_credit_update(struct ath10k_htc_ep *ep)
  89{
  90        if (!ep->tx_credit_flow_enabled)
  91                return false;
  92        if (ep->tx_credits >= ep->tx_credits_per_max_message)
  93                return false;
  94
  95        ath10k_dbg(ATH10K_DBG_HTC, "HTC: endpoint %d needs credit update\n",
  96                   ep->eid);
  97        return true;
  98}
  99
 100static void ath10k_htc_prepare_tx_skb(struct ath10k_htc_ep *ep,
 101                                      struct sk_buff *skb)
 102{
 103        struct ath10k_htc_hdr *hdr;
 104
 105        hdr = (struct ath10k_htc_hdr *)skb->data;
 106        memset(hdr, 0, sizeof(*hdr));
 107
 108        hdr->eid = ep->eid;
 109        hdr->len = __cpu_to_le16(skb->len - sizeof(*hdr));
 110
 111        spin_lock_bh(&ep->htc->tx_lock);
 112        hdr->seq_no = ep->seq_no++;
 113
 114        if (ath10k_htc_ep_need_credit_update(ep))
 115                hdr->flags |= ATH10K_HTC_FLAG_NEED_CREDIT_UPDATE;
 116
 117        spin_unlock_bh(&ep->htc->tx_lock);
 118}
 119
 120static int ath10k_htc_issue_skb(struct ath10k_htc *htc,
 121                                struct ath10k_htc_ep *ep,
 122                                struct sk_buff *skb,
 123                                u8 credits)
 124{
 125        struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
 126        int ret;
 127
 128        ath10k_dbg(ATH10K_DBG_HTC, "%s: ep %d skb %p\n", __func__,
 129                   ep->eid, skb);
 130
 131        ath10k_htc_prepare_tx_skb(ep, skb);
 132
 133        ret = ath10k_skb_map(htc->ar->dev, skb);
 134        if (ret)
 135                goto err;
 136
 137        ret = ath10k_hif_send_head(htc->ar,
 138                                   ep->ul_pipe_id,
 139                                   ep->eid,
 140                                   skb->len,
 141                                   skb);
 142        if (unlikely(ret))
 143                goto err;
 144
 145        return 0;
 146err:
 147        ath10k_warn("HTC issue failed: %d\n", ret);
 148
 149        spin_lock_bh(&htc->tx_lock);
 150        ep->tx_credits += credits;
 151        spin_unlock_bh(&htc->tx_lock);
 152
 153        /* this is the simplest way to handle out-of-resources for non-credit
 154         * based endpoints. credit based endpoints can still get -ENOSR, but
 155         * this is highly unlikely as credit reservation should prevent that */
 156        if (ret == -ENOSR) {
 157                spin_lock_bh(&htc->tx_lock);
 158                __skb_queue_head(&ep->tx_queue, skb);
 159                spin_unlock_bh(&htc->tx_lock);
 160
 161                return ret;
 162        }
 163
 164        skb_cb->is_aborted = true;
 165        ath10k_htc_notify_tx_completion(ep, skb);
 166
 167        return ret;
 168}
 169
 170static struct sk_buff *ath10k_htc_get_skb_credit_based(struct ath10k_htc *htc,
 171                                                       struct ath10k_htc_ep *ep,
 172                                                       u8 *credits)
 173{
 174        struct sk_buff *skb;
 175        struct ath10k_skb_cb *skb_cb;
 176        int credits_required;
 177        int remainder;
 178        unsigned int transfer_len;
 179
 180        lockdep_assert_held(&htc->tx_lock);
 181
 182        skb = __skb_dequeue(&ep->tx_queue);
 183        if (!skb)
 184                return NULL;
 185
 186        skb_cb = ATH10K_SKB_CB(skb);
 187        transfer_len = skb->len;
 188
 189        if (likely(transfer_len <= htc->target_credit_size)) {
 190                credits_required = 1;
 191        } else {
 192                /* figure out how many credits this message requires */
 193                credits_required = transfer_len / htc->target_credit_size;
 194                remainder = transfer_len % htc->target_credit_size;
 195
 196                if (remainder)
 197                        credits_required++;
 198        }
 199
 200        ath10k_dbg(ATH10K_DBG_HTC, "Credits required %d got %d\n",
 201                   credits_required, ep->tx_credits);
 202
 203        if (ep->tx_credits < credits_required) {
 204                __skb_queue_head(&ep->tx_queue, skb);
 205                return NULL;
 206        }
 207
 208        ep->tx_credits -= credits_required;
 209        *credits = credits_required;
 210        return skb;
 211}
 212
 213static void ath10k_htc_send_work(struct work_struct *work)
 214{
 215        struct ath10k_htc_ep *ep = container_of(work,
 216                                        struct ath10k_htc_ep, send_work);
 217        struct ath10k_htc *htc = ep->htc;
 218        struct sk_buff *skb;
 219        u8 credits = 0;
 220        int ret;
 221
 222        while (true) {
 223                if (ep->ul_is_polled)
 224                        ath10k_htc_send_complete_check(ep, 0);
 225
 226                spin_lock_bh(&htc->tx_lock);
 227                if (ep->tx_credit_flow_enabled)
 228                        skb = ath10k_htc_get_skb_credit_based(htc, ep,
 229                                                              &credits);
 230                else
 231                        skb = __skb_dequeue(&ep->tx_queue);
 232                spin_unlock_bh(&htc->tx_lock);
 233
 234                if (!skb)
 235                        break;
 236
 237                ret = ath10k_htc_issue_skb(htc, ep, skb, credits);
 238                if (ret == -ENOSR)
 239                        break;
 240        }
 241}
 242
 243int ath10k_htc_send(struct ath10k_htc *htc,
 244                    enum ath10k_htc_ep_id eid,
 245                    struct sk_buff *skb)
 246{
 247        struct ath10k_htc_ep *ep = &htc->endpoint[eid];
 248
 249        if (eid >= ATH10K_HTC_EP_COUNT) {
 250                ath10k_warn("Invalid endpoint id: %d\n", eid);
 251                return -ENOENT;
 252        }
 253
 254        skb_push(skb, sizeof(struct ath10k_htc_hdr));
 255
 256        spin_lock_bh(&htc->tx_lock);
 257        __skb_queue_tail(&ep->tx_queue, skb);
 258        spin_unlock_bh(&htc->tx_lock);
 259
 260        queue_work(htc->ar->workqueue, &ep->send_work);
 261        return 0;
 262}
 263
 264static int ath10k_htc_tx_completion_handler(struct ath10k *ar,
 265                                            struct sk_buff *skb,
 266                                            unsigned int eid)
 267{
 268        struct ath10k_htc *htc = ar->htc;
 269        struct ath10k_htc_ep *ep = &htc->endpoint[eid];
 270        bool stopping;
 271
 272        ath10k_htc_notify_tx_completion(ep, skb);
 273        /* the skb now belongs to the completion handler */
 274
 275        spin_lock_bh(&htc->tx_lock);
 276        stopping = htc->stopping;
 277        spin_unlock_bh(&htc->tx_lock);
 278
 279        if (!ep->tx_credit_flow_enabled && !stopping)
 280                /*
 281                 * note: when using TX credit flow, the re-checking of
 282                 * queues happens when credits flow back from the target.
 283                 * in the non-TX credit case, we recheck after the packet
 284                 * completes
 285                 */
 286                queue_work(ar->workqueue, &ep->send_work);
 287
 288        return 0;
 289}
 290
 291/* flush endpoint TX queue */
 292static void ath10k_htc_flush_endpoint_tx(struct ath10k_htc *htc,
 293                                         struct ath10k_htc_ep *ep)
 294{
 295        struct sk_buff *skb;
 296        struct ath10k_skb_cb *skb_cb;
 297
 298        spin_lock_bh(&htc->tx_lock);
 299        for (;;) {
 300                skb = __skb_dequeue(&ep->tx_queue);
 301                if (!skb)
 302                        break;
 303
 304                skb_cb = ATH10K_SKB_CB(skb);
 305                skb_cb->is_aborted = true;
 306                ath10k_htc_notify_tx_completion(ep, skb);
 307        }
 308        spin_unlock_bh(&htc->tx_lock);
 309
 310        cancel_work_sync(&ep->send_work);
 311}
 312
 313/***********/
 314/* Receive */
 315/***********/
 316
 317static void
 318ath10k_htc_process_credit_report(struct ath10k_htc *htc,
 319                                 const struct ath10k_htc_credit_report *report,
 320                                 int len,
 321                                 enum ath10k_htc_ep_id eid)
 322{
 323        struct ath10k_htc_ep *ep;
 324        int i, n_reports;
 325
 326        if (len % sizeof(*report))
 327                ath10k_warn("Uneven credit report len %d", len);
 328
 329        n_reports = len / sizeof(*report);
 330
 331        spin_lock_bh(&htc->tx_lock);
 332        for (i = 0; i < n_reports; i++, report++) {
 333                if (report->eid >= ATH10K_HTC_EP_COUNT)
 334                        break;
 335
 336                ath10k_dbg(ATH10K_DBG_HTC, "ep %d got %d credits\n",
 337                           report->eid, report->credits);
 338
 339                ep = &htc->endpoint[report->eid];
 340                ep->tx_credits += report->credits;
 341
 342                if (ep->tx_credits && !skb_queue_empty(&ep->tx_queue))
 343                        queue_work(htc->ar->workqueue, &ep->send_work);
 344        }
 345        spin_unlock_bh(&htc->tx_lock);
 346}
 347
 348static int ath10k_htc_process_trailer(struct ath10k_htc *htc,
 349                                      u8 *buffer,
 350                                      int length,
 351                                      enum ath10k_htc_ep_id src_eid)
 352{
 353        int status = 0;
 354        struct ath10k_htc_record *record;
 355        u8 *orig_buffer;
 356        int orig_length;
 357        size_t len;
 358
 359        orig_buffer = buffer;
 360        orig_length = length;
 361
 362        while (length > 0) {
 363                record = (struct ath10k_htc_record *)buffer;
 364
 365                if (length < sizeof(record->hdr)) {
 366                        status = -EINVAL;
 367                        break;
 368                }
 369
 370                if (record->hdr.len > length) {
 371                        /* no room left in buffer for record */
 372                        ath10k_warn("Invalid record length: %d\n",
 373                                    record->hdr.len);
 374                        status = -EINVAL;
 375                        break;
 376                }
 377
 378                switch (record->hdr.id) {
 379                case ATH10K_HTC_RECORD_CREDITS:
 380                        len = sizeof(struct ath10k_htc_credit_report);
 381                        if (record->hdr.len < len) {
 382                                ath10k_warn("Credit report too long\n");
 383                                status = -EINVAL;
 384                                break;
 385                        }
 386                        ath10k_htc_process_credit_report(htc,
 387                                                         record->credit_report,
 388                                                         record->hdr.len,
 389                                                         src_eid);
 390                        break;
 391                default:
 392                        ath10k_warn("Unhandled record: id:%d length:%d\n",
 393                                    record->hdr.id, record->hdr.len);
 394                        break;
 395                }
 396
 397                if (status)
 398                        break;
 399
 400                /* multiple records may be present in a trailer */
 401                buffer += sizeof(record->hdr) + record->hdr.len;
 402                length -= sizeof(record->hdr) + record->hdr.len;
 403        }
 404
 405        if (status)
 406                ath10k_dbg_dump(ATH10K_DBG_HTC, "htc rx bad trailer", "",
 407                                orig_buffer, orig_length);
 408
 409        return status;
 410}
 411
 412static int ath10k_htc_rx_completion_handler(struct ath10k *ar,
 413                                            struct sk_buff *skb,
 414                                            u8 pipe_id)
 415{
 416        int status = 0;
 417        struct ath10k_htc *htc = ar->htc;
 418        struct ath10k_htc_hdr *hdr;
 419        struct ath10k_htc_ep *ep;
 420        u16 payload_len;
 421        u32 trailer_len = 0;
 422        size_t min_len;
 423        u8 eid;
 424        bool trailer_present;
 425
 426        hdr = (struct ath10k_htc_hdr *)skb->data;
 427        skb_pull(skb, sizeof(*hdr));
 428
 429        eid = hdr->eid;
 430
 431        if (eid >= ATH10K_HTC_EP_COUNT) {
 432                ath10k_warn("HTC Rx: invalid eid %d\n", eid);
 433                ath10k_dbg_dump(ATH10K_DBG_HTC, "htc bad header", "",
 434                                hdr, sizeof(*hdr));
 435                status = -EINVAL;
 436                goto out;
 437        }
 438
 439        ep = &htc->endpoint[eid];
 440
 441        /*
 442         * If this endpoint that received a message from the target has
 443         * a to-target HIF pipe whose send completions are polled rather
 444         * than interrupt-driven, this is a good point to ask HIF to check
 445         * whether it has any completed sends to handle.
 446         */
 447        if (ep->ul_is_polled)
 448                ath10k_htc_send_complete_check(ep, 1);
 449
 450        payload_len = __le16_to_cpu(hdr->len);
 451
 452        if (payload_len + sizeof(*hdr) > ATH10K_HTC_MAX_LEN) {
 453                ath10k_warn("HTC rx frame too long, len: %zu\n",
 454                            payload_len + sizeof(*hdr));
 455                ath10k_dbg_dump(ATH10K_DBG_HTC, "htc bad rx pkt len", "",
 456                                hdr, sizeof(*hdr));
 457                status = -EINVAL;
 458                goto out;
 459        }
 460
 461        if (skb->len < payload_len) {
 462                ath10k_dbg(ATH10K_DBG_HTC,
 463                           "HTC Rx: insufficient length, got %d, expected %d\n",
 464                           skb->len, payload_len);
 465                ath10k_dbg_dump(ATH10K_DBG_HTC, "htc bad rx pkt len",
 466                                "", hdr, sizeof(*hdr));
 467                status = -EINVAL;
 468                goto out;
 469        }
 470
 471        /* get flags to check for trailer */
 472        trailer_present = hdr->flags & ATH10K_HTC_FLAG_TRAILER_PRESENT;
 473        if (trailer_present) {
 474                u8 *trailer;
 475
 476                trailer_len = hdr->trailer_len;
 477                min_len = sizeof(struct ath10k_ath10k_htc_record_hdr);
 478
 479                if ((trailer_len < min_len) ||
 480                    (trailer_len > payload_len)) {
 481                        ath10k_warn("Invalid trailer length: %d\n",
 482                                    trailer_len);
 483                        status = -EPROTO;
 484                        goto out;
 485                }
 486
 487                trailer = (u8 *)hdr;
 488                trailer += sizeof(*hdr);
 489                trailer += payload_len;
 490                trailer -= trailer_len;
 491                status = ath10k_htc_process_trailer(htc, trailer,
 492                                                    trailer_len, hdr->eid);
 493                if (status)
 494                        goto out;
 495
 496                skb_trim(skb, skb->len - trailer_len);
 497        }
 498
 499        if (((int)payload_len - (int)trailer_len) <= 0)
 500                /* zero length packet with trailer data, just drop these */
 501                goto out;
 502
 503        if (eid == ATH10K_HTC_EP_0) {
 504                struct ath10k_htc_msg *msg = (struct ath10k_htc_msg *)skb->data;
 505
 506                switch (__le16_to_cpu(msg->hdr.message_id)) {
 507                default:
 508                        /* handle HTC control message */
 509                        if (completion_done(&htc->ctl_resp)) {
 510                                /*
 511                                 * this is a fatal error, target should not be
 512                                 * sending unsolicited messages on the ep 0
 513                                 */
 514                                ath10k_warn("HTC rx ctrl still processing\n");
 515                                status = -EINVAL;
 516                                complete(&htc->ctl_resp);
 517                                goto out;
 518                        }
 519
 520                        htc->control_resp_len =
 521                                min_t(int, skb->len,
 522                                      ATH10K_HTC_MAX_CTRL_MSG_LEN);
 523
 524                        memcpy(htc->control_resp_buffer, skb->data,
 525                               htc->control_resp_len);
 526
 527                        complete(&htc->ctl_resp);
 528                        break;
 529                case ATH10K_HTC_MSG_SEND_SUSPEND_COMPLETE:
 530                        htc->htc_ops.target_send_suspend_complete(ar);
 531                }
 532                goto out;
 533        }
 534
 535        ath10k_dbg(ATH10K_DBG_HTC, "htc rx completion ep %d skb %p\n",
 536                   eid, skb);
 537        ep->ep_ops.ep_rx_complete(ar, skb);
 538
 539        /* skb is now owned by the rx completion handler */
 540        skb = NULL;
 541out:
 542        kfree_skb(skb);
 543
 544        return status;
 545}
 546
 547static void ath10k_htc_control_rx_complete(struct ath10k *ar,
 548                                           struct sk_buff *skb)
 549{
 550        /* This is unexpected. FW is not supposed to send regular rx on this
 551         * endpoint. */
 552        ath10k_warn("unexpected htc rx\n");
 553        kfree_skb(skb);
 554}
 555
 556/***************/
 557/* Init/Deinit */
 558/***************/
 559
 560static const char *htc_service_name(enum ath10k_htc_svc_id id)
 561{
 562        switch (id) {
 563        case ATH10K_HTC_SVC_ID_RESERVED:
 564                return "Reserved";
 565        case ATH10K_HTC_SVC_ID_RSVD_CTRL:
 566                return "Control";
 567        case ATH10K_HTC_SVC_ID_WMI_CONTROL:
 568                return "WMI";
 569        case ATH10K_HTC_SVC_ID_WMI_DATA_BE:
 570                return "DATA BE";
 571        case ATH10K_HTC_SVC_ID_WMI_DATA_BK:
 572                return "DATA BK";
 573        case ATH10K_HTC_SVC_ID_WMI_DATA_VI:
 574                return "DATA VI";
 575        case ATH10K_HTC_SVC_ID_WMI_DATA_VO:
 576                return "DATA VO";
 577        case ATH10K_HTC_SVC_ID_NMI_CONTROL:
 578                return "NMI Control";
 579        case ATH10K_HTC_SVC_ID_NMI_DATA:
 580                return "NMI Data";
 581        case ATH10K_HTC_SVC_ID_HTT_DATA_MSG:
 582                return "HTT Data";
 583        case ATH10K_HTC_SVC_ID_TEST_RAW_STREAMS:
 584                return "RAW";
 585        }
 586
 587        return "Unknown";
 588}
 589
 590static void ath10k_htc_reset_endpoint_states(struct ath10k_htc *htc)
 591{
 592        struct ath10k_htc_ep *ep;
 593        int i;
 594
 595        for (i = ATH10K_HTC_EP_0; i < ATH10K_HTC_EP_COUNT; i++) {
 596                ep = &htc->endpoint[i];
 597                ep->service_id = ATH10K_HTC_SVC_ID_UNUSED;
 598                ep->max_ep_message_len = 0;
 599                ep->max_tx_queue_depth = 0;
 600                ep->eid = i;
 601                skb_queue_head_init(&ep->tx_queue);
 602                ep->htc = htc;
 603                ep->tx_credit_flow_enabled = true;
 604                INIT_WORK(&ep->send_work, ath10k_htc_send_work);
 605        }
 606}
 607
 608static void ath10k_htc_setup_target_buffer_assignments(struct ath10k_htc *htc)
 609{
 610        struct ath10k_htc_svc_tx_credits *entry;
 611
 612        entry = &htc->service_tx_alloc[0];
 613
 614        /*
 615         * for PCIE allocate all credists/HTC buffers to WMI.
 616         * no buffers are used/required for data. data always
 617         * remains on host.
 618         */
 619        entry++;
 620        entry->service_id = ATH10K_HTC_SVC_ID_WMI_CONTROL;
 621        entry->credit_allocation = htc->total_transmit_credits;
 622}
 623
 624static u8 ath10k_htc_get_credit_allocation(struct ath10k_htc *htc,
 625                                           u16 service_id)
 626{
 627        u8 allocation = 0;
 628        int i;
 629
 630        for (i = 0; i < ATH10K_HTC_EP_COUNT; i++) {
 631                if (htc->service_tx_alloc[i].service_id == service_id)
 632                        allocation =
 633                            htc->service_tx_alloc[i].credit_allocation;
 634        }
 635
 636        return allocation;
 637}
 638
 639int ath10k_htc_wait_target(struct ath10k_htc *htc)
 640{
 641        int status = 0;
 642        struct ath10k_htc_svc_conn_req conn_req;
 643        struct ath10k_htc_svc_conn_resp conn_resp;
 644        struct ath10k_htc_msg *msg;
 645        u16 message_id;
 646        u16 credit_count;
 647        u16 credit_size;
 648
 649        INIT_COMPLETION(htc->ctl_resp);
 650
 651        status = ath10k_hif_start(htc->ar);
 652        if (status) {
 653                ath10k_err("could not start HIF (%d)\n", status);
 654                goto err_start;
 655        }
 656
 657        status = wait_for_completion_timeout(&htc->ctl_resp,
 658                                             ATH10K_HTC_WAIT_TIMEOUT_HZ);
 659        if (status <= 0) {
 660                if (status == 0)
 661                        status = -ETIMEDOUT;
 662
 663                ath10k_err("ctl_resp never came in (%d)\n", status);
 664                goto err_target;
 665        }
 666
 667        if (htc->control_resp_len < sizeof(msg->hdr) + sizeof(msg->ready)) {
 668                ath10k_err("Invalid HTC ready msg len:%d\n",
 669                           htc->control_resp_len);
 670
 671                status = -ECOMM;
 672                goto err_target;
 673        }
 674
 675        msg = (struct ath10k_htc_msg *)htc->control_resp_buffer;
 676        message_id   = __le16_to_cpu(msg->hdr.message_id);
 677        credit_count = __le16_to_cpu(msg->ready.credit_count);
 678        credit_size  = __le16_to_cpu(msg->ready.credit_size);
 679
 680        if (message_id != ATH10K_HTC_MSG_READY_ID) {
 681                ath10k_err("Invalid HTC ready msg: 0x%x\n", message_id);
 682                status = -ECOMM;
 683                goto err_target;
 684        }
 685
 686        htc->total_transmit_credits = credit_count;
 687        htc->target_credit_size = credit_size;
 688
 689        ath10k_dbg(ATH10K_DBG_HTC,
 690                   "Target ready! transmit resources: %d size:%d\n",
 691                   htc->total_transmit_credits,
 692                   htc->target_credit_size);
 693
 694        if ((htc->total_transmit_credits == 0) ||
 695            (htc->target_credit_size == 0)) {
 696                status = -ECOMM;
 697                ath10k_err("Invalid credit size received\n");
 698                goto err_target;
 699        }
 700
 701        ath10k_htc_setup_target_buffer_assignments(htc);
 702
 703        /* setup our pseudo HTC control endpoint connection */
 704        memset(&conn_req, 0, sizeof(conn_req));
 705        memset(&conn_resp, 0, sizeof(conn_resp));
 706        conn_req.ep_ops.ep_tx_complete = ath10k_htc_control_tx_complete;
 707        conn_req.ep_ops.ep_rx_complete = ath10k_htc_control_rx_complete;
 708        conn_req.max_send_queue_depth = ATH10K_NUM_CONTROL_TX_BUFFERS;
 709        conn_req.service_id = ATH10K_HTC_SVC_ID_RSVD_CTRL;
 710
 711        /* connect fake service */
 712        status = ath10k_htc_connect_service(htc, &conn_req, &conn_resp);
 713        if (status) {
 714                ath10k_err("could not connect to htc service (%d)\n", status);
 715                goto err_target;
 716        }
 717
 718        return 0;
 719err_target:
 720        ath10k_hif_stop(htc->ar);
 721err_start:
 722        return status;
 723}
 724
 725int ath10k_htc_connect_service(struct ath10k_htc *htc,
 726                               struct ath10k_htc_svc_conn_req *conn_req,
 727                               struct ath10k_htc_svc_conn_resp *conn_resp)
 728{
 729        struct ath10k_htc_msg *msg;
 730        struct ath10k_htc_conn_svc *req_msg;
 731        struct ath10k_htc_conn_svc_response resp_msg_dummy;
 732        struct ath10k_htc_conn_svc_response *resp_msg = &resp_msg_dummy;
 733        enum ath10k_htc_ep_id assigned_eid = ATH10K_HTC_EP_COUNT;
 734        struct ath10k_htc_ep *ep;
 735        struct sk_buff *skb;
 736        unsigned int max_msg_size = 0;
 737        int length, status;
 738        bool disable_credit_flow_ctrl = false;
 739        u16 message_id, service_id, flags = 0;
 740        u8 tx_alloc = 0;
 741
 742        /* special case for HTC pseudo control service */
 743        if (conn_req->service_id == ATH10K_HTC_SVC_ID_RSVD_CTRL) {
 744                disable_credit_flow_ctrl = true;
 745                assigned_eid = ATH10K_HTC_EP_0;
 746                max_msg_size = ATH10K_HTC_MAX_CTRL_MSG_LEN;
 747                memset(&resp_msg_dummy, 0, sizeof(resp_msg_dummy));
 748                goto setup;
 749        }
 750
 751        tx_alloc = ath10k_htc_get_credit_allocation(htc,
 752                                                    conn_req->service_id);
 753        if (!tx_alloc)
 754                ath10k_warn("HTC Service %s does not allocate target credits\n",
 755                            htc_service_name(conn_req->service_id));
 756
 757        skb = ath10k_htc_build_tx_ctrl_skb(htc->ar);
 758        if (!skb) {
 759                ath10k_err("Failed to allocate HTC packet\n");
 760                return -ENOMEM;
 761        }
 762
 763        length = sizeof(msg->hdr) + sizeof(msg->connect_service);
 764        skb_put(skb, length);
 765        memset(skb->data, 0, length);
 766
 767        msg = (struct ath10k_htc_msg *)skb->data;
 768        msg->hdr.message_id =
 769                __cpu_to_le16(ATH10K_HTC_MSG_CONNECT_SERVICE_ID);
 770
 771        flags |= SM(tx_alloc, ATH10K_HTC_CONN_FLAGS_RECV_ALLOC);
 772
 773        req_msg = &msg->connect_service;
 774        req_msg->flags = __cpu_to_le16(flags);
 775        req_msg->service_id = __cpu_to_le16(conn_req->service_id);
 776
 777        /* Only enable credit flow control for WMI ctrl service */
 778        if (conn_req->service_id != ATH10K_HTC_SVC_ID_WMI_CONTROL) {
 779                flags |= ATH10K_HTC_CONN_FLAGS_DISABLE_CREDIT_FLOW_CTRL;
 780                disable_credit_flow_ctrl = true;
 781        }
 782
 783        INIT_COMPLETION(htc->ctl_resp);
 784
 785        status = ath10k_htc_send(htc, ATH10K_HTC_EP_0, skb);
 786        if (status) {
 787                kfree_skb(skb);
 788                return status;
 789        }
 790
 791        /* wait for response */
 792        status = wait_for_completion_timeout(&htc->ctl_resp,
 793                                             ATH10K_HTC_CONN_SVC_TIMEOUT_HZ);
 794        if (status <= 0) {
 795                if (status == 0)
 796                        status = -ETIMEDOUT;
 797                ath10k_err("Service connect timeout: %d\n", status);
 798                return status;
 799        }
 800
 801        /* we controlled the buffer creation, it's aligned */
 802        msg = (struct ath10k_htc_msg *)htc->control_resp_buffer;
 803        resp_msg = &msg->connect_service_response;
 804        message_id = __le16_to_cpu(msg->hdr.message_id);
 805        service_id = __le16_to_cpu(resp_msg->service_id);
 806
 807        if ((message_id != ATH10K_HTC_MSG_CONNECT_SERVICE_RESP_ID) ||
 808            (htc->control_resp_len < sizeof(msg->hdr) +
 809             sizeof(msg->connect_service_response))) {
 810                ath10k_err("Invalid resp message ID 0x%x", message_id);
 811                return -EPROTO;
 812        }
 813
 814        ath10k_dbg(ATH10K_DBG_HTC,
 815                   "HTC Service %s connect response: status: 0x%x, assigned ep: 0x%x\n",
 816                   htc_service_name(service_id),
 817                   resp_msg->status, resp_msg->eid);
 818
 819        conn_resp->connect_resp_code = resp_msg->status;
 820
 821        /* check response status */
 822        if (resp_msg->status != ATH10K_HTC_CONN_SVC_STATUS_SUCCESS) {
 823                ath10k_err("HTC Service %s connect request failed: 0x%x)\n",
 824                           htc_service_name(service_id),
 825                           resp_msg->status);
 826                return -EPROTO;
 827        }
 828
 829        assigned_eid = (enum ath10k_htc_ep_id)resp_msg->eid;
 830        max_msg_size = __le16_to_cpu(resp_msg->max_msg_size);
 831
 832setup:
 833
 834        if (assigned_eid >= ATH10K_HTC_EP_COUNT)
 835                return -EPROTO;
 836
 837        if (max_msg_size == 0)
 838                return -EPROTO;
 839
 840        ep = &htc->endpoint[assigned_eid];
 841        ep->eid = assigned_eid;
 842
 843        if (ep->service_id != ATH10K_HTC_SVC_ID_UNUSED)
 844                return -EPROTO;
 845
 846        /* return assigned endpoint to caller */
 847        conn_resp->eid = assigned_eid;
 848        conn_resp->max_msg_len = __le16_to_cpu(resp_msg->max_msg_size);
 849
 850        /* setup the endpoint */
 851        ep->service_id = conn_req->service_id;
 852        ep->max_tx_queue_depth = conn_req->max_send_queue_depth;
 853        ep->max_ep_message_len = __le16_to_cpu(resp_msg->max_msg_size);
 854        ep->tx_credits = tx_alloc;
 855        ep->tx_credit_size = htc->target_credit_size;
 856        ep->tx_credits_per_max_message = ep->max_ep_message_len /
 857                                         htc->target_credit_size;
 858
 859        if (ep->max_ep_message_len % htc->target_credit_size)
 860                ep->tx_credits_per_max_message++;
 861
 862        /* copy all the callbacks */
 863        ep->ep_ops = conn_req->ep_ops;
 864
 865        status = ath10k_hif_map_service_to_pipe(htc->ar,
 866                                                ep->service_id,
 867                                                &ep->ul_pipe_id,
 868                                                &ep->dl_pipe_id,
 869                                                &ep->ul_is_polled,
 870                                                &ep->dl_is_polled);
 871        if (status)
 872                return status;
 873
 874        ath10k_dbg(ATH10K_DBG_HTC,
 875                   "HTC service: %s UL pipe: %d DL pipe: %d eid: %d ready\n",
 876                   htc_service_name(ep->service_id), ep->ul_pipe_id,
 877                   ep->dl_pipe_id, ep->eid);
 878
 879        ath10k_dbg(ATH10K_DBG_HTC,
 880                   "EP %d UL polled: %d, DL polled: %d\n",
 881                   ep->eid, ep->ul_is_polled, ep->dl_is_polled);
 882
 883        if (disable_credit_flow_ctrl && ep->tx_credit_flow_enabled) {
 884                ep->tx_credit_flow_enabled = false;
 885                ath10k_dbg(ATH10K_DBG_HTC,
 886                           "HTC service: %s eid: %d TX flow control disabled\n",
 887                           htc_service_name(ep->service_id), assigned_eid);
 888        }
 889
 890        return status;
 891}
 892
 893struct sk_buff *ath10k_htc_alloc_skb(int size)
 894{
 895        struct sk_buff *skb;
 896
 897        skb = dev_alloc_skb(size + sizeof(struct ath10k_htc_hdr));
 898        if (!skb) {
 899                ath10k_warn("could not allocate HTC tx skb\n");
 900                return NULL;
 901        }
 902
 903        skb_reserve(skb, sizeof(struct ath10k_htc_hdr));
 904
 905        /* FW/HTC requires 4-byte aligned streams */
 906        if (!IS_ALIGNED((unsigned long)skb->data, 4))
 907                ath10k_warn("Unaligned HTC tx skb\n");
 908
 909        return skb;
 910}
 911
 912int ath10k_htc_start(struct ath10k_htc *htc)
 913{
 914        struct sk_buff *skb;
 915        int status = 0;
 916        struct ath10k_htc_msg *msg;
 917
 918        skb = ath10k_htc_build_tx_ctrl_skb(htc->ar);
 919        if (!skb)
 920                return -ENOMEM;
 921
 922        skb_put(skb, sizeof(msg->hdr) + sizeof(msg->setup_complete_ext));
 923        memset(skb->data, 0, skb->len);
 924
 925        msg = (struct ath10k_htc_msg *)skb->data;
 926        msg->hdr.message_id =
 927                __cpu_to_le16(ATH10K_HTC_MSG_SETUP_COMPLETE_EX_ID);
 928
 929        ath10k_dbg(ATH10K_DBG_HTC, "HTC is using TX credit flow control\n");
 930
 931        status = ath10k_htc_send(htc, ATH10K_HTC_EP_0, skb);
 932        if (status) {
 933                kfree_skb(skb);
 934                return status;
 935        }
 936
 937        return 0;
 938}
 939
 940/*
 941 * stop HTC communications, i.e. stop interrupt reception, and flush all
 942 * queued buffers
 943 */
 944void ath10k_htc_stop(struct ath10k_htc *htc)
 945{
 946        int i;
 947        struct ath10k_htc_ep *ep;
 948
 949        spin_lock_bh(&htc->tx_lock);
 950        htc->stopping = true;
 951        spin_unlock_bh(&htc->tx_lock);
 952
 953        for (i = ATH10K_HTC_EP_0; i < ATH10K_HTC_EP_COUNT; i++) {
 954                ep = &htc->endpoint[i];
 955                ath10k_htc_flush_endpoint_tx(htc, ep);
 956        }
 957
 958        ath10k_hif_stop(htc->ar);
 959        ath10k_htc_reset_endpoint_states(htc);
 960}
 961
 962/* registered target arrival callback from the HIF layer */
 963struct ath10k_htc *ath10k_htc_create(struct ath10k *ar,
 964                                     struct ath10k_htc_ops *htc_ops)
 965{
 966        struct ath10k_hif_cb htc_callbacks;
 967        struct ath10k_htc_ep *ep = NULL;
 968        struct ath10k_htc *htc = NULL;
 969
 970        /* FIXME: use struct ath10k instead */
 971        htc = kzalloc(sizeof(struct ath10k_htc), GFP_KERNEL);
 972        if (!htc)
 973                return ERR_PTR(-ENOMEM);
 974
 975        spin_lock_init(&htc->tx_lock);
 976
 977        memcpy(&htc->htc_ops, htc_ops, sizeof(struct ath10k_htc_ops));
 978
 979        ath10k_htc_reset_endpoint_states(htc);
 980
 981        /* setup HIF layer callbacks */
 982        htc_callbacks.rx_completion = ath10k_htc_rx_completion_handler;
 983        htc_callbacks.tx_completion = ath10k_htc_tx_completion_handler;
 984        htc->ar = ar;
 985
 986        /* Get HIF default pipe for HTC message exchange */
 987        ep = &htc->endpoint[ATH10K_HTC_EP_0];
 988
 989        ath10k_hif_init(ar, &htc_callbacks);
 990        ath10k_hif_get_default_pipe(ar, &ep->ul_pipe_id, &ep->dl_pipe_id);
 991
 992        init_completion(&htc->ctl_resp);
 993
 994        return htc;
 995}
 996
 997void ath10k_htc_destroy(struct ath10k_htc *htc)
 998{
 999        kfree(htc);
1000}
1001