linux/drivers/net/wireless/ath/ath10k/htc.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2005-2011 Atheros Communications Inc.
   3 * Copyright (c) 2011-2017 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 void ath10k_htc_control_tx_complete(struct ath10k *ar,
  27                                           struct sk_buff *skb)
  28{
  29        kfree_skb(skb);
  30}
  31
  32static struct sk_buff *ath10k_htc_build_tx_ctrl_skb(void *ar)
  33{
  34        struct sk_buff *skb;
  35        struct ath10k_skb_cb *skb_cb;
  36
  37        skb = dev_alloc_skb(ATH10K_HTC_CONTROL_BUFFER_SIZE);
  38        if (!skb)
  39                return NULL;
  40
  41        skb_reserve(skb, 20); /* FIXME: why 20 bytes? */
  42        WARN_ONCE((unsigned long)skb->data & 3, "unaligned skb");
  43
  44        skb_cb = ATH10K_SKB_CB(skb);
  45        memset(skb_cb, 0, sizeof(*skb_cb));
  46
  47        ath10k_dbg(ar, ATH10K_DBG_HTC, "%s: skb %pK\n", __func__, skb);
  48        return skb;
  49}
  50
  51static inline void ath10k_htc_restore_tx_skb(struct ath10k_htc *htc,
  52                                             struct sk_buff *skb)
  53{
  54        struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
  55
  56        dma_unmap_single(htc->ar->dev, skb_cb->paddr, skb->len, DMA_TO_DEVICE);
  57        skb_pull(skb, sizeof(struct ath10k_htc_hdr));
  58}
  59
  60void ath10k_htc_notify_tx_completion(struct ath10k_htc_ep *ep,
  61                                     struct sk_buff *skb)
  62{
  63        struct ath10k *ar = ep->htc->ar;
  64
  65        ath10k_dbg(ar, ATH10K_DBG_HTC, "%s: ep %d skb %pK\n", __func__,
  66                   ep->eid, skb);
  67
  68        ath10k_htc_restore_tx_skb(ep->htc, skb);
  69
  70        if (!ep->ep_ops.ep_tx_complete) {
  71                ath10k_warn(ar, "no tx handler for eid %d\n", ep->eid);
  72                dev_kfree_skb_any(skb);
  73                return;
  74        }
  75
  76        ep->ep_ops.ep_tx_complete(ep->htc->ar, skb);
  77}
  78EXPORT_SYMBOL(ath10k_htc_notify_tx_completion);
  79
  80static void ath10k_htc_prepare_tx_skb(struct ath10k_htc_ep *ep,
  81                                      struct sk_buff *skb)
  82{
  83        struct ath10k_htc_hdr *hdr;
  84
  85        hdr = (struct ath10k_htc_hdr *)skb->data;
  86
  87        hdr->eid = ep->eid;
  88        hdr->len = __cpu_to_le16(skb->len - sizeof(*hdr));
  89        hdr->flags = 0;
  90        hdr->flags |= ATH10K_HTC_FLAG_NEED_CREDIT_UPDATE;
  91
  92        spin_lock_bh(&ep->htc->tx_lock);
  93        hdr->seq_no = ep->seq_no++;
  94        spin_unlock_bh(&ep->htc->tx_lock);
  95}
  96
  97int ath10k_htc_send(struct ath10k_htc *htc,
  98                    enum ath10k_htc_ep_id eid,
  99                    struct sk_buff *skb)
 100{
 101        struct ath10k *ar = htc->ar;
 102        struct ath10k_htc_ep *ep = &htc->endpoint[eid];
 103        struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
 104        struct ath10k_hif_sg_item sg_item;
 105        struct device *dev = htc->ar->dev;
 106        int credits = 0;
 107        int ret;
 108
 109        if (htc->ar->state == ATH10K_STATE_WEDGED)
 110                return -ECOMM;
 111
 112        if (eid >= ATH10K_HTC_EP_COUNT) {
 113                ath10k_warn(ar, "Invalid endpoint id: %d\n", eid);
 114                return -ENOENT;
 115        }
 116
 117        skb_push(skb, sizeof(struct ath10k_htc_hdr));
 118
 119        if (ep->tx_credit_flow_enabled) {
 120                credits = DIV_ROUND_UP(skb->len, htc->target_credit_size);
 121                spin_lock_bh(&htc->tx_lock);
 122                if (ep->tx_credits < credits) {
 123                        ath10k_dbg(ar, ATH10K_DBG_HTC,
 124                                   "htc insufficient credits ep %d required %d available %d\n",
 125                                   eid, credits, ep->tx_credits);
 126                        spin_unlock_bh(&htc->tx_lock);
 127                        ret = -EAGAIN;
 128                        goto err_pull;
 129                }
 130                ep->tx_credits -= credits;
 131                ath10k_dbg(ar, ATH10K_DBG_HTC,
 132                           "htc ep %d consumed %d credits (total %d)\n",
 133                           eid, credits, ep->tx_credits);
 134                spin_unlock_bh(&htc->tx_lock);
 135        }
 136
 137        ath10k_htc_prepare_tx_skb(ep, skb);
 138
 139        skb_cb->eid = eid;
 140        skb_cb->paddr = dma_map_single(dev, skb->data, skb->len, DMA_TO_DEVICE);
 141        ret = dma_mapping_error(dev, skb_cb->paddr);
 142        if (ret) {
 143                ret = -EIO;
 144                goto err_credits;
 145        }
 146
 147        sg_item.transfer_id = ep->eid;
 148        sg_item.transfer_context = skb;
 149        sg_item.vaddr = skb->data;
 150        sg_item.paddr = skb_cb->paddr;
 151        sg_item.len = skb->len;
 152
 153        ret = ath10k_hif_tx_sg(htc->ar, ep->ul_pipe_id, &sg_item, 1);
 154        if (ret)
 155                goto err_unmap;
 156
 157        return 0;
 158
 159err_unmap:
 160        dma_unmap_single(dev, skb_cb->paddr, skb->len, DMA_TO_DEVICE);
 161err_credits:
 162        if (ep->tx_credit_flow_enabled) {
 163                spin_lock_bh(&htc->tx_lock);
 164                ep->tx_credits += credits;
 165                ath10k_dbg(ar, ATH10K_DBG_HTC,
 166                           "htc ep %d reverted %d credits back (total %d)\n",
 167                           eid, credits, ep->tx_credits);
 168                spin_unlock_bh(&htc->tx_lock);
 169
 170                if (ep->ep_ops.ep_tx_credits)
 171                        ep->ep_ops.ep_tx_credits(htc->ar);
 172        }
 173err_pull:
 174        skb_pull(skb, sizeof(struct ath10k_htc_hdr));
 175        return ret;
 176}
 177
 178void ath10k_htc_tx_completion_handler(struct ath10k *ar, struct sk_buff *skb)
 179{
 180        struct ath10k_htc *htc = &ar->htc;
 181        struct ath10k_skb_cb *skb_cb;
 182        struct ath10k_htc_ep *ep;
 183
 184        if (WARN_ON_ONCE(!skb))
 185                return;
 186
 187        skb_cb = ATH10K_SKB_CB(skb);
 188        ep = &htc->endpoint[skb_cb->eid];
 189
 190        ath10k_htc_notify_tx_completion(ep, skb);
 191        /* the skb now belongs to the completion handler */
 192}
 193EXPORT_SYMBOL(ath10k_htc_tx_completion_handler);
 194
 195/***********/
 196/* Receive */
 197/***********/
 198
 199static void
 200ath10k_htc_process_credit_report(struct ath10k_htc *htc,
 201                                 const struct ath10k_htc_credit_report *report,
 202                                 int len,
 203                                 enum ath10k_htc_ep_id eid)
 204{
 205        struct ath10k *ar = htc->ar;
 206        struct ath10k_htc_ep *ep;
 207        int i, n_reports;
 208
 209        if (len % sizeof(*report))
 210                ath10k_warn(ar, "Uneven credit report len %d", len);
 211
 212        n_reports = len / sizeof(*report);
 213
 214        spin_lock_bh(&htc->tx_lock);
 215        for (i = 0; i < n_reports; i++, report++) {
 216                if (report->eid >= ATH10K_HTC_EP_COUNT)
 217                        break;
 218
 219                ep = &htc->endpoint[report->eid];
 220                ep->tx_credits += report->credits;
 221
 222                ath10k_dbg(ar, ATH10K_DBG_HTC, "htc ep %d got %d credits (total %d)\n",
 223                           report->eid, report->credits, ep->tx_credits);
 224
 225                if (ep->ep_ops.ep_tx_credits) {
 226                        spin_unlock_bh(&htc->tx_lock);
 227                        ep->ep_ops.ep_tx_credits(htc->ar);
 228                        spin_lock_bh(&htc->tx_lock);
 229                }
 230        }
 231        spin_unlock_bh(&htc->tx_lock);
 232}
 233
 234static int
 235ath10k_htc_process_lookahead(struct ath10k_htc *htc,
 236                             const struct ath10k_htc_lookahead_report *report,
 237                             int len,
 238                             enum ath10k_htc_ep_id eid,
 239                             void *next_lookaheads,
 240                             int *next_lookaheads_len)
 241{
 242        struct ath10k *ar = htc->ar;
 243
 244        /* Invalid lookahead flags are actually transmitted by
 245         * the target in the HTC control message.
 246         * Since this will happen at every boot we silently ignore
 247         * the lookahead in this case
 248         */
 249        if (report->pre_valid != ((~report->post_valid) & 0xFF))
 250                return 0;
 251
 252        if (next_lookaheads && next_lookaheads_len) {
 253                ath10k_dbg(ar, ATH10K_DBG_HTC,
 254                           "htc rx lookahead found pre_valid 0x%x post_valid 0x%x\n",
 255                           report->pre_valid, report->post_valid);
 256
 257                /* look ahead bytes are valid, copy them over */
 258                memcpy((u8 *)next_lookaheads, report->lookahead, 4);
 259
 260                *next_lookaheads_len = 1;
 261        }
 262
 263        return 0;
 264}
 265
 266static int
 267ath10k_htc_process_lookahead_bundle(struct ath10k_htc *htc,
 268                                    const struct ath10k_htc_lookahead_bundle *report,
 269                                    int len,
 270                                    enum ath10k_htc_ep_id eid,
 271                                    void *next_lookaheads,
 272                                    int *next_lookaheads_len)
 273{
 274        struct ath10k *ar = htc->ar;
 275        int bundle_cnt = len / sizeof(*report);
 276
 277        if (!bundle_cnt || (bundle_cnt > HTC_HOST_MAX_MSG_PER_BUNDLE)) {
 278                ath10k_warn(ar, "Invalid lookahead bundle count: %d\n",
 279                            bundle_cnt);
 280                return -EINVAL;
 281        }
 282
 283        if (next_lookaheads && next_lookaheads_len) {
 284                int i;
 285
 286                for (i = 0; i < bundle_cnt; i++) {
 287                        memcpy(((u8 *)next_lookaheads) + 4 * i,
 288                               report->lookahead, 4);
 289                        report++;
 290                }
 291
 292                *next_lookaheads_len = bundle_cnt;
 293        }
 294
 295        return 0;
 296}
 297
 298int ath10k_htc_process_trailer(struct ath10k_htc *htc,
 299                               u8 *buffer,
 300                               int length,
 301                               enum ath10k_htc_ep_id src_eid,
 302                               void *next_lookaheads,
 303                               int *next_lookaheads_len)
 304{
 305        struct ath10k_htc_lookahead_bundle *bundle;
 306        struct ath10k *ar = htc->ar;
 307        int status = 0;
 308        struct ath10k_htc_record *record;
 309        u8 *orig_buffer;
 310        int orig_length;
 311        size_t len;
 312
 313        orig_buffer = buffer;
 314        orig_length = length;
 315
 316        while (length > 0) {
 317                record = (struct ath10k_htc_record *)buffer;
 318
 319                if (length < sizeof(record->hdr)) {
 320                        status = -EINVAL;
 321                        break;
 322                }
 323
 324                if (record->hdr.len > length) {
 325                        /* no room left in buffer for record */
 326                        ath10k_warn(ar, "Invalid record length: %d\n",
 327                                    record->hdr.len);
 328                        status = -EINVAL;
 329                        break;
 330                }
 331
 332                switch (record->hdr.id) {
 333                case ATH10K_HTC_RECORD_CREDITS:
 334                        len = sizeof(struct ath10k_htc_credit_report);
 335                        if (record->hdr.len < len) {
 336                                ath10k_warn(ar, "Credit report too long\n");
 337                                status = -EINVAL;
 338                                break;
 339                        }
 340                        ath10k_htc_process_credit_report(htc,
 341                                                         record->credit_report,
 342                                                         record->hdr.len,
 343                                                         src_eid);
 344                        break;
 345                case ATH10K_HTC_RECORD_LOOKAHEAD:
 346                        len = sizeof(struct ath10k_htc_lookahead_report);
 347                        if (record->hdr.len < len) {
 348                                ath10k_warn(ar, "Lookahead report too long\n");
 349                                status = -EINVAL;
 350                                break;
 351                        }
 352                        status = ath10k_htc_process_lookahead(htc,
 353                                                              record->lookahead_report,
 354                                                              record->hdr.len,
 355                                                              src_eid,
 356                                                              next_lookaheads,
 357                                                              next_lookaheads_len);
 358                        break;
 359                case ATH10K_HTC_RECORD_LOOKAHEAD_BUNDLE:
 360                        bundle = record->lookahead_bundle;
 361                        status = ath10k_htc_process_lookahead_bundle(htc,
 362                                                                     bundle,
 363                                                                     record->hdr.len,
 364                                                                     src_eid,
 365                                                                     next_lookaheads,
 366                                                                     next_lookaheads_len);
 367                        break;
 368                default:
 369                        ath10k_warn(ar, "Unhandled record: id:%d length:%d\n",
 370                                    record->hdr.id, record->hdr.len);
 371                        break;
 372                }
 373
 374                if (status)
 375                        break;
 376
 377                /* multiple records may be present in a trailer */
 378                buffer += sizeof(record->hdr) + record->hdr.len;
 379                length -= sizeof(record->hdr) + record->hdr.len;
 380        }
 381
 382        if (status)
 383                ath10k_dbg_dump(ar, ATH10K_DBG_HTC, "htc rx bad trailer", "",
 384                                orig_buffer, orig_length);
 385
 386        return status;
 387}
 388EXPORT_SYMBOL(ath10k_htc_process_trailer);
 389
 390void ath10k_htc_rx_completion_handler(struct ath10k *ar, struct sk_buff *skb)
 391{
 392        int status = 0;
 393        struct ath10k_htc *htc = &ar->htc;
 394        struct ath10k_htc_hdr *hdr;
 395        struct ath10k_htc_ep *ep;
 396        u16 payload_len;
 397        u32 trailer_len = 0;
 398        size_t min_len;
 399        u8 eid;
 400        bool trailer_present;
 401
 402        hdr = (struct ath10k_htc_hdr *)skb->data;
 403        skb_pull(skb, sizeof(*hdr));
 404
 405        eid = hdr->eid;
 406
 407        if (eid >= ATH10K_HTC_EP_COUNT) {
 408                ath10k_warn(ar, "HTC Rx: invalid eid %d\n", eid);
 409                ath10k_dbg_dump(ar, ATH10K_DBG_HTC, "htc bad header", "",
 410                                hdr, sizeof(*hdr));
 411                goto out;
 412        }
 413
 414        ep = &htc->endpoint[eid];
 415
 416        payload_len = __le16_to_cpu(hdr->len);
 417
 418        if (payload_len + sizeof(*hdr) > ATH10K_HTC_MAX_LEN) {
 419                ath10k_warn(ar, "HTC rx frame too long, len: %zu\n",
 420                            payload_len + sizeof(*hdr));
 421                ath10k_dbg_dump(ar, ATH10K_DBG_HTC, "htc bad rx pkt len", "",
 422                                hdr, sizeof(*hdr));
 423                goto out;
 424        }
 425
 426        if (skb->len < payload_len) {
 427                ath10k_dbg(ar, ATH10K_DBG_HTC,
 428                           "HTC Rx: insufficient length, got %d, expected %d\n",
 429                           skb->len, payload_len);
 430                ath10k_dbg_dump(ar, ATH10K_DBG_HTC, "htc bad rx pkt len",
 431                                "", hdr, sizeof(*hdr));
 432                goto out;
 433        }
 434
 435        /* get flags to check for trailer */
 436        trailer_present = hdr->flags & ATH10K_HTC_FLAG_TRAILER_PRESENT;
 437        if (trailer_present) {
 438                u8 *trailer;
 439
 440                trailer_len = hdr->trailer_len;
 441                min_len = sizeof(struct ath10k_ath10k_htc_record_hdr);
 442
 443                if ((trailer_len < min_len) ||
 444                    (trailer_len > payload_len)) {
 445                        ath10k_warn(ar, "Invalid trailer length: %d\n",
 446                                    trailer_len);
 447                        goto out;
 448                }
 449
 450                trailer = (u8 *)hdr;
 451                trailer += sizeof(*hdr);
 452                trailer += payload_len;
 453                trailer -= trailer_len;
 454                status = ath10k_htc_process_trailer(htc, trailer,
 455                                                    trailer_len, hdr->eid,
 456                                                    NULL, NULL);
 457                if (status)
 458                        goto out;
 459
 460                skb_trim(skb, skb->len - trailer_len);
 461        }
 462
 463        if (((int)payload_len - (int)trailer_len) <= 0)
 464                /* zero length packet with trailer data, just drop these */
 465                goto out;
 466
 467        ath10k_dbg(ar, ATH10K_DBG_HTC, "htc rx completion ep %d skb %pK\n",
 468                   eid, skb);
 469        ep->ep_ops.ep_rx_complete(ar, skb);
 470
 471        /* skb is now owned by the rx completion handler */
 472        skb = NULL;
 473out:
 474        kfree_skb(skb);
 475}
 476EXPORT_SYMBOL(ath10k_htc_rx_completion_handler);
 477
 478static void ath10k_htc_control_rx_complete(struct ath10k *ar,
 479                                           struct sk_buff *skb)
 480{
 481        struct ath10k_htc *htc = &ar->htc;
 482        struct ath10k_htc_msg *msg = (struct ath10k_htc_msg *)skb->data;
 483
 484        switch (__le16_to_cpu(msg->hdr.message_id)) {
 485        case ATH10K_HTC_MSG_READY_ID:
 486        case ATH10K_HTC_MSG_CONNECT_SERVICE_RESP_ID:
 487                /* handle HTC control message */
 488                if (completion_done(&htc->ctl_resp)) {
 489                        /* this is a fatal error, target should not be
 490                         * sending unsolicited messages on the ep 0
 491                         */
 492                        ath10k_warn(ar, "HTC rx ctrl still processing\n");
 493                        complete(&htc->ctl_resp);
 494                        goto out;
 495                }
 496
 497                htc->control_resp_len =
 498                        min_t(int, skb->len,
 499                              ATH10K_HTC_MAX_CTRL_MSG_LEN);
 500
 501                memcpy(htc->control_resp_buffer, skb->data,
 502                       htc->control_resp_len);
 503
 504                complete(&htc->ctl_resp);
 505                break;
 506        case ATH10K_HTC_MSG_SEND_SUSPEND_COMPLETE:
 507                htc->htc_ops.target_send_suspend_complete(ar);
 508                break;
 509        default:
 510                ath10k_warn(ar, "ignoring unsolicited htc ep0 event\n");
 511                break;
 512        }
 513
 514out:
 515        kfree_skb(skb);
 516}
 517
 518/***************/
 519/* Init/Deinit */
 520/***************/
 521
 522static const char *htc_service_name(enum ath10k_htc_svc_id id)
 523{
 524        switch (id) {
 525        case ATH10K_HTC_SVC_ID_RESERVED:
 526                return "Reserved";
 527        case ATH10K_HTC_SVC_ID_RSVD_CTRL:
 528                return "Control";
 529        case ATH10K_HTC_SVC_ID_WMI_CONTROL:
 530                return "WMI";
 531        case ATH10K_HTC_SVC_ID_WMI_DATA_BE:
 532                return "DATA BE";
 533        case ATH10K_HTC_SVC_ID_WMI_DATA_BK:
 534                return "DATA BK";
 535        case ATH10K_HTC_SVC_ID_WMI_DATA_VI:
 536                return "DATA VI";
 537        case ATH10K_HTC_SVC_ID_WMI_DATA_VO:
 538                return "DATA VO";
 539        case ATH10K_HTC_SVC_ID_NMI_CONTROL:
 540                return "NMI Control";
 541        case ATH10K_HTC_SVC_ID_NMI_DATA:
 542                return "NMI Data";
 543        case ATH10K_HTC_SVC_ID_HTT_DATA_MSG:
 544                return "HTT Data";
 545        case ATH10K_HTC_SVC_ID_TEST_RAW_STREAMS:
 546                return "RAW";
 547        }
 548
 549        return "Unknown";
 550}
 551
 552static void ath10k_htc_reset_endpoint_states(struct ath10k_htc *htc)
 553{
 554        struct ath10k_htc_ep *ep;
 555        int i;
 556
 557        for (i = ATH10K_HTC_EP_0; i < ATH10K_HTC_EP_COUNT; i++) {
 558                ep = &htc->endpoint[i];
 559                ep->service_id = ATH10K_HTC_SVC_ID_UNUSED;
 560                ep->max_ep_message_len = 0;
 561                ep->max_tx_queue_depth = 0;
 562                ep->eid = i;
 563                ep->htc = htc;
 564                ep->tx_credit_flow_enabled = true;
 565        }
 566}
 567
 568static u8 ath10k_htc_get_credit_allocation(struct ath10k_htc *htc,
 569                                           u16 service_id)
 570{
 571        u8 allocation = 0;
 572
 573        /* The WMI control service is the only service with flow control.
 574         * Let it have all transmit credits.
 575         */
 576        if (service_id == ATH10K_HTC_SVC_ID_WMI_CONTROL)
 577                allocation = htc->total_transmit_credits;
 578
 579        return allocation;
 580}
 581
 582int ath10k_htc_wait_target(struct ath10k_htc *htc)
 583{
 584        struct ath10k *ar = htc->ar;
 585        int i, status = 0;
 586        unsigned long time_left;
 587        struct ath10k_htc_msg *msg;
 588        u16 message_id;
 589
 590        time_left = wait_for_completion_timeout(&htc->ctl_resp,
 591                                                ATH10K_HTC_WAIT_TIMEOUT_HZ);
 592        if (!time_left) {
 593                /* Workaround: In some cases the PCI HIF doesn't
 594                 * receive interrupt for the control response message
 595                 * even if the buffer was completed. It is suspected
 596                 * iomap writes unmasking PCI CE irqs aren't propagated
 597                 * properly in KVM PCI-passthrough sometimes.
 598                 */
 599                ath10k_warn(ar, "failed to receive control response completion, polling..\n");
 600
 601                for (i = 0; i < CE_COUNT; i++)
 602                        ath10k_hif_send_complete_check(htc->ar, i, 1);
 603
 604                time_left =
 605                wait_for_completion_timeout(&htc->ctl_resp,
 606                                            ATH10K_HTC_WAIT_TIMEOUT_HZ);
 607
 608                if (!time_left)
 609                        status = -ETIMEDOUT;
 610        }
 611
 612        if (status < 0) {
 613                ath10k_err(ar, "ctl_resp never came in (%d)\n", status);
 614                return status;
 615        }
 616
 617        if (htc->control_resp_len < sizeof(msg->hdr) + sizeof(msg->ready)) {
 618                ath10k_err(ar, "Invalid HTC ready msg len:%d\n",
 619                           htc->control_resp_len);
 620                return -ECOMM;
 621        }
 622
 623        msg = (struct ath10k_htc_msg *)htc->control_resp_buffer;
 624        message_id   = __le16_to_cpu(msg->hdr.message_id);
 625
 626        if (message_id != ATH10K_HTC_MSG_READY_ID) {
 627                ath10k_err(ar, "Invalid HTC ready msg: 0x%x\n", message_id);
 628                return -ECOMM;
 629        }
 630
 631        htc->total_transmit_credits = __le16_to_cpu(msg->ready.credit_count);
 632        htc->target_credit_size = __le16_to_cpu(msg->ready.credit_size);
 633
 634        ath10k_dbg(ar, ATH10K_DBG_HTC,
 635                   "Target ready! transmit resources: %d size:%d\n",
 636                   htc->total_transmit_credits,
 637                   htc->target_credit_size);
 638
 639        if ((htc->total_transmit_credits == 0) ||
 640            (htc->target_credit_size == 0)) {
 641                ath10k_err(ar, "Invalid credit size received\n");
 642                return -ECOMM;
 643        }
 644
 645        /* The only way to determine if the ready message is an extended
 646         * message is from the size.
 647         */
 648        if (htc->control_resp_len >=
 649            sizeof(msg->hdr) + sizeof(msg->ready_ext)) {
 650                htc->max_msgs_per_htc_bundle =
 651                        min_t(u8, msg->ready_ext.max_msgs_per_htc_bundle,
 652                              HTC_HOST_MAX_MSG_PER_BUNDLE);
 653                ath10k_dbg(ar, ATH10K_DBG_HTC,
 654                           "Extended ready message. RX bundle size: %d\n",
 655                           htc->max_msgs_per_htc_bundle);
 656        }
 657
 658        return 0;
 659}
 660
 661int ath10k_htc_connect_service(struct ath10k_htc *htc,
 662                               struct ath10k_htc_svc_conn_req *conn_req,
 663                               struct ath10k_htc_svc_conn_resp *conn_resp)
 664{
 665        struct ath10k *ar = htc->ar;
 666        struct ath10k_htc_msg *msg;
 667        struct ath10k_htc_conn_svc *req_msg;
 668        struct ath10k_htc_conn_svc_response resp_msg_dummy;
 669        struct ath10k_htc_conn_svc_response *resp_msg = &resp_msg_dummy;
 670        enum ath10k_htc_ep_id assigned_eid = ATH10K_HTC_EP_COUNT;
 671        struct ath10k_htc_ep *ep;
 672        struct sk_buff *skb;
 673        unsigned int max_msg_size = 0;
 674        int length, status;
 675        unsigned long time_left;
 676        bool disable_credit_flow_ctrl = false;
 677        u16 message_id, service_id, flags = 0;
 678        u8 tx_alloc = 0;
 679
 680        /* special case for HTC pseudo control service */
 681        if (conn_req->service_id == ATH10K_HTC_SVC_ID_RSVD_CTRL) {
 682                disable_credit_flow_ctrl = true;
 683                assigned_eid = ATH10K_HTC_EP_0;
 684                max_msg_size = ATH10K_HTC_MAX_CTRL_MSG_LEN;
 685                memset(&resp_msg_dummy, 0, sizeof(resp_msg_dummy));
 686                goto setup;
 687        }
 688
 689        tx_alloc = ath10k_htc_get_credit_allocation(htc,
 690                                                    conn_req->service_id);
 691        if (!tx_alloc)
 692                ath10k_dbg(ar, ATH10K_DBG_BOOT,
 693                           "boot htc service %s does not allocate target credits\n",
 694                           htc_service_name(conn_req->service_id));
 695
 696        skb = ath10k_htc_build_tx_ctrl_skb(htc->ar);
 697        if (!skb) {
 698                ath10k_err(ar, "Failed to allocate HTC packet\n");
 699                return -ENOMEM;
 700        }
 701
 702        length = sizeof(msg->hdr) + sizeof(msg->connect_service);
 703        skb_put(skb, length);
 704        memset(skb->data, 0, length);
 705
 706        msg = (struct ath10k_htc_msg *)skb->data;
 707        msg->hdr.message_id =
 708                __cpu_to_le16(ATH10K_HTC_MSG_CONNECT_SERVICE_ID);
 709
 710        flags |= SM(tx_alloc, ATH10K_HTC_CONN_FLAGS_RECV_ALLOC);
 711
 712        /* Only enable credit flow control for WMI ctrl service */
 713        if (conn_req->service_id != ATH10K_HTC_SVC_ID_WMI_CONTROL) {
 714                flags |= ATH10K_HTC_CONN_FLAGS_DISABLE_CREDIT_FLOW_CTRL;
 715                disable_credit_flow_ctrl = true;
 716        }
 717
 718        req_msg = &msg->connect_service;
 719        req_msg->flags = __cpu_to_le16(flags);
 720        req_msg->service_id = __cpu_to_le16(conn_req->service_id);
 721
 722        reinit_completion(&htc->ctl_resp);
 723
 724        status = ath10k_htc_send(htc, ATH10K_HTC_EP_0, skb);
 725        if (status) {
 726                kfree_skb(skb);
 727                return status;
 728        }
 729
 730        /* wait for response */
 731        time_left = wait_for_completion_timeout(&htc->ctl_resp,
 732                                                ATH10K_HTC_CONN_SVC_TIMEOUT_HZ);
 733        if (!time_left) {
 734                ath10k_err(ar, "Service connect timeout\n");
 735                return -ETIMEDOUT;
 736        }
 737
 738        /* we controlled the buffer creation, it's aligned */
 739        msg = (struct ath10k_htc_msg *)htc->control_resp_buffer;
 740        resp_msg = &msg->connect_service_response;
 741        message_id = __le16_to_cpu(msg->hdr.message_id);
 742        service_id = __le16_to_cpu(resp_msg->service_id);
 743
 744        if ((message_id != ATH10K_HTC_MSG_CONNECT_SERVICE_RESP_ID) ||
 745            (htc->control_resp_len < sizeof(msg->hdr) +
 746             sizeof(msg->connect_service_response))) {
 747                ath10k_err(ar, "Invalid resp message ID 0x%x", message_id);
 748                return -EPROTO;
 749        }
 750
 751        ath10k_dbg(ar, ATH10K_DBG_HTC,
 752                   "HTC Service %s connect response: status: 0x%x, assigned ep: 0x%x\n",
 753                   htc_service_name(service_id),
 754                   resp_msg->status, resp_msg->eid);
 755
 756        conn_resp->connect_resp_code = resp_msg->status;
 757
 758        /* check response status */
 759        if (resp_msg->status != ATH10K_HTC_CONN_SVC_STATUS_SUCCESS) {
 760                ath10k_err(ar, "HTC Service %s connect request failed: 0x%x)\n",
 761                           htc_service_name(service_id),
 762                           resp_msg->status);
 763                return -EPROTO;
 764        }
 765
 766        assigned_eid = (enum ath10k_htc_ep_id)resp_msg->eid;
 767        max_msg_size = __le16_to_cpu(resp_msg->max_msg_size);
 768
 769setup:
 770
 771        if (assigned_eid >= ATH10K_HTC_EP_COUNT)
 772                return -EPROTO;
 773
 774        if (max_msg_size == 0)
 775                return -EPROTO;
 776
 777        ep = &htc->endpoint[assigned_eid];
 778        ep->eid = assigned_eid;
 779
 780        if (ep->service_id != ATH10K_HTC_SVC_ID_UNUSED)
 781                return -EPROTO;
 782
 783        /* return assigned endpoint to caller */
 784        conn_resp->eid = assigned_eid;
 785        conn_resp->max_msg_len = __le16_to_cpu(resp_msg->max_msg_size);
 786
 787        /* setup the endpoint */
 788        ep->service_id = conn_req->service_id;
 789        ep->max_tx_queue_depth = conn_req->max_send_queue_depth;
 790        ep->max_ep_message_len = __le16_to_cpu(resp_msg->max_msg_size);
 791        ep->tx_credits = tx_alloc;
 792
 793        /* copy all the callbacks */
 794        ep->ep_ops = conn_req->ep_ops;
 795
 796        status = ath10k_hif_map_service_to_pipe(htc->ar,
 797                                                ep->service_id,
 798                                                &ep->ul_pipe_id,
 799                                                &ep->dl_pipe_id);
 800        if (status)
 801                return status;
 802
 803        ath10k_dbg(ar, ATH10K_DBG_BOOT,
 804                   "boot htc service '%s' ul pipe %d dl pipe %d eid %d ready\n",
 805                   htc_service_name(ep->service_id), ep->ul_pipe_id,
 806                   ep->dl_pipe_id, ep->eid);
 807
 808        if (disable_credit_flow_ctrl && ep->tx_credit_flow_enabled) {
 809                ep->tx_credit_flow_enabled = false;
 810                ath10k_dbg(ar, ATH10K_DBG_BOOT,
 811                           "boot htc service '%s' eid %d TX flow control disabled\n",
 812                           htc_service_name(ep->service_id), assigned_eid);
 813        }
 814
 815        return status;
 816}
 817
 818struct sk_buff *ath10k_htc_alloc_skb(struct ath10k *ar, int size)
 819{
 820        struct sk_buff *skb;
 821
 822        skb = dev_alloc_skb(size + sizeof(struct ath10k_htc_hdr));
 823        if (!skb)
 824                return NULL;
 825
 826        skb_reserve(skb, sizeof(struct ath10k_htc_hdr));
 827
 828        /* FW/HTC requires 4-byte aligned streams */
 829        if (!IS_ALIGNED((unsigned long)skb->data, 4))
 830                ath10k_warn(ar, "Unaligned HTC tx skb\n");
 831
 832        return skb;
 833}
 834
 835int ath10k_htc_start(struct ath10k_htc *htc)
 836{
 837        struct ath10k *ar = htc->ar;
 838        struct sk_buff *skb;
 839        int status = 0;
 840        struct ath10k_htc_msg *msg;
 841
 842        skb = ath10k_htc_build_tx_ctrl_skb(htc->ar);
 843        if (!skb)
 844                return -ENOMEM;
 845
 846        skb_put(skb, sizeof(msg->hdr) + sizeof(msg->setup_complete_ext));
 847        memset(skb->data, 0, skb->len);
 848
 849        msg = (struct ath10k_htc_msg *)skb->data;
 850        msg->hdr.message_id =
 851                __cpu_to_le16(ATH10K_HTC_MSG_SETUP_COMPLETE_EX_ID);
 852
 853        if (ar->hif.bus == ATH10K_BUS_SDIO) {
 854                /* Extra setup params used by SDIO */
 855                msg->setup_complete_ext.flags =
 856                        __cpu_to_le32(ATH10K_HTC_SETUP_COMPLETE_FLAGS_RX_BNDL_EN);
 857                msg->setup_complete_ext.max_msgs_per_bundled_recv =
 858                        htc->max_msgs_per_htc_bundle;
 859        }
 860        ath10k_dbg(ar, ATH10K_DBG_HTC, "HTC is using TX credit flow control\n");
 861
 862        status = ath10k_htc_send(htc, ATH10K_HTC_EP_0, skb);
 863        if (status) {
 864                kfree_skb(skb);
 865                return status;
 866        }
 867
 868        return 0;
 869}
 870
 871/* registered target arrival callback from the HIF layer */
 872int ath10k_htc_init(struct ath10k *ar)
 873{
 874        int status;
 875        struct ath10k_htc *htc = &ar->htc;
 876        struct ath10k_htc_svc_conn_req conn_req;
 877        struct ath10k_htc_svc_conn_resp conn_resp;
 878
 879        spin_lock_init(&htc->tx_lock);
 880
 881        ath10k_htc_reset_endpoint_states(htc);
 882
 883        htc->ar = ar;
 884
 885        /* setup our pseudo HTC control endpoint connection */
 886        memset(&conn_req, 0, sizeof(conn_req));
 887        memset(&conn_resp, 0, sizeof(conn_resp));
 888        conn_req.ep_ops.ep_tx_complete = ath10k_htc_control_tx_complete;
 889        conn_req.ep_ops.ep_rx_complete = ath10k_htc_control_rx_complete;
 890        conn_req.max_send_queue_depth = ATH10K_NUM_CONTROL_TX_BUFFERS;
 891        conn_req.service_id = ATH10K_HTC_SVC_ID_RSVD_CTRL;
 892
 893        /* connect fake service */
 894        status = ath10k_htc_connect_service(htc, &conn_req, &conn_resp);
 895        if (status) {
 896                ath10k_err(ar, "could not connect to htc service (%d)\n",
 897                           status);
 898                return status;
 899        }
 900
 901        init_completion(&htc->ctl_resp);
 902
 903        return 0;
 904}
 905