Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: ISC
0002 /*
0003  * Copyright (c) 2005-2011 Atheros Communications Inc.
0004  * Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
0005  */
0006 
0007 #include "core.h"
0008 #include "hif.h"
0009 #include "debug.h"
0010 
0011 /********/
0012 /* Send */
0013 /********/
0014 
0015 static void ath10k_htc_control_tx_complete(struct ath10k *ar,
0016                        struct sk_buff *skb)
0017 {
0018     kfree_skb(skb);
0019 }
0020 
0021 static struct sk_buff *ath10k_htc_build_tx_ctrl_skb(void *ar)
0022 {
0023     struct sk_buff *skb;
0024     struct ath10k_skb_cb *skb_cb;
0025 
0026     skb = dev_alloc_skb(ATH10K_HTC_CONTROL_BUFFER_SIZE);
0027     if (!skb)
0028         return NULL;
0029 
0030     skb_reserve(skb, 20); /* FIXME: why 20 bytes? */
0031     WARN_ONCE((unsigned long)skb->data & 3, "unaligned skb");
0032 
0033     skb_cb = ATH10K_SKB_CB(skb);
0034     memset(skb_cb, 0, sizeof(*skb_cb));
0035 
0036     ath10k_dbg(ar, ATH10K_DBG_HTC, "%s: skb %pK\n", __func__, skb);
0037     return skb;
0038 }
0039 
0040 static inline void ath10k_htc_restore_tx_skb(struct ath10k_htc *htc,
0041                          struct sk_buff *skb)
0042 {
0043     struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
0044 
0045     if (htc->ar->bus_param.dev_type != ATH10K_DEV_TYPE_HL)
0046         dma_unmap_single(htc->ar->dev, skb_cb->paddr, skb->len, DMA_TO_DEVICE);
0047     skb_pull(skb, sizeof(struct ath10k_htc_hdr));
0048 }
0049 
0050 void ath10k_htc_notify_tx_completion(struct ath10k_htc_ep *ep,
0051                      struct sk_buff *skb)
0052 {
0053     struct ath10k *ar = ep->htc->ar;
0054     struct ath10k_htc_hdr *hdr;
0055 
0056     ath10k_dbg(ar, ATH10K_DBG_HTC, "%s: ep %d skb %pK\n", __func__,
0057            ep->eid, skb);
0058 
0059     hdr = (struct ath10k_htc_hdr *)skb->data;
0060     ath10k_htc_restore_tx_skb(ep->htc, skb);
0061 
0062     if (!ep->ep_ops.ep_tx_complete) {
0063         ath10k_warn(ar, "no tx handler for eid %d\n", ep->eid);
0064         dev_kfree_skb_any(skb);
0065         return;
0066     }
0067 
0068     if (hdr->flags & ATH10K_HTC_FLAG_SEND_BUNDLE) {
0069         dev_kfree_skb_any(skb);
0070         return;
0071     }
0072 
0073     ep->ep_ops.ep_tx_complete(ep->htc->ar, skb);
0074 }
0075 EXPORT_SYMBOL(ath10k_htc_notify_tx_completion);
0076 
0077 static void ath10k_htc_prepare_tx_skb(struct ath10k_htc_ep *ep,
0078                       struct sk_buff *skb)
0079 {
0080     struct ath10k_htc_hdr *hdr;
0081 
0082     hdr = (struct ath10k_htc_hdr *)skb->data;
0083     memset(hdr, 0, sizeof(struct ath10k_htc_hdr));
0084 
0085     hdr->eid = ep->eid;
0086     hdr->len = __cpu_to_le16(skb->len - sizeof(*hdr));
0087     hdr->flags = 0;
0088     if (ep->tx_credit_flow_enabled && !ep->bundle_tx)
0089         hdr->flags |= ATH10K_HTC_FLAG_NEED_CREDIT_UPDATE;
0090 
0091     spin_lock_bh(&ep->htc->tx_lock);
0092     hdr->seq_no = ep->seq_no++;
0093     spin_unlock_bh(&ep->htc->tx_lock);
0094 }
0095 
0096 static int ath10k_htc_consume_credit(struct ath10k_htc_ep *ep,
0097                      unsigned int len,
0098                      bool consume)
0099 {
0100     struct ath10k_htc *htc = ep->htc;
0101     struct ath10k *ar = htc->ar;
0102     enum ath10k_htc_ep_id eid = ep->eid;
0103     int credits, ret = 0;
0104 
0105     if (!ep->tx_credit_flow_enabled)
0106         return 0;
0107 
0108     credits = DIV_ROUND_UP(len, ep->tx_credit_size);
0109     spin_lock_bh(&htc->tx_lock);
0110 
0111     if (ep->tx_credits < credits) {
0112         ath10k_dbg(ar, ATH10K_DBG_HTC,
0113                "htc insufficient credits ep %d required %d available %d consume %d\n",
0114                eid, credits, ep->tx_credits, consume);
0115         ret = -EAGAIN;
0116         goto unlock;
0117     }
0118 
0119     if (consume) {
0120         ep->tx_credits -= credits;
0121         ath10k_dbg(ar, ATH10K_DBG_HTC,
0122                "htc ep %d consumed %d credits total %d\n",
0123                eid, credits, ep->tx_credits);
0124     }
0125 
0126 unlock:
0127     spin_unlock_bh(&htc->tx_lock);
0128     return ret;
0129 }
0130 
0131 static void ath10k_htc_release_credit(struct ath10k_htc_ep *ep, unsigned int len)
0132 {
0133     struct ath10k_htc *htc = ep->htc;
0134     struct ath10k *ar = htc->ar;
0135     enum ath10k_htc_ep_id eid = ep->eid;
0136     int credits;
0137 
0138     if (!ep->tx_credit_flow_enabled)
0139         return;
0140 
0141     credits = DIV_ROUND_UP(len, ep->tx_credit_size);
0142     spin_lock_bh(&htc->tx_lock);
0143     ep->tx_credits += credits;
0144     ath10k_dbg(ar, ATH10K_DBG_HTC,
0145            "htc ep %d reverted %d credits back total %d\n",
0146            eid, credits, ep->tx_credits);
0147     spin_unlock_bh(&htc->tx_lock);
0148 
0149     if (ep->ep_ops.ep_tx_credits)
0150         ep->ep_ops.ep_tx_credits(htc->ar);
0151 }
0152 
0153 int ath10k_htc_send(struct ath10k_htc *htc,
0154             enum ath10k_htc_ep_id eid,
0155             struct sk_buff *skb)
0156 {
0157     struct ath10k *ar = htc->ar;
0158     struct ath10k_htc_ep *ep = &htc->endpoint[eid];
0159     struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
0160     struct ath10k_hif_sg_item sg_item;
0161     struct device *dev = htc->ar->dev;
0162     int ret;
0163     unsigned int skb_len;
0164 
0165     if (htc->ar->state == ATH10K_STATE_WEDGED)
0166         return -ECOMM;
0167 
0168     if (eid >= ATH10K_HTC_EP_COUNT) {
0169         ath10k_warn(ar, "Invalid endpoint id: %d\n", eid);
0170         return -ENOENT;
0171     }
0172 
0173     skb_push(skb, sizeof(struct ath10k_htc_hdr));
0174 
0175     skb_len = skb->len;
0176     ret = ath10k_htc_consume_credit(ep, skb_len, true);
0177     if (ret)
0178         goto err_pull;
0179 
0180     ath10k_htc_prepare_tx_skb(ep, skb);
0181 
0182     skb_cb->eid = eid;
0183     if (ar->bus_param.dev_type != ATH10K_DEV_TYPE_HL) {
0184         skb_cb->paddr = dma_map_single(dev, skb->data, skb->len,
0185                            DMA_TO_DEVICE);
0186         ret = dma_mapping_error(dev, skb_cb->paddr);
0187         if (ret) {
0188             ret = -EIO;
0189             goto err_credits;
0190         }
0191     }
0192 
0193     sg_item.transfer_id = ep->eid;
0194     sg_item.transfer_context = skb;
0195     sg_item.vaddr = skb->data;
0196     sg_item.paddr = skb_cb->paddr;
0197     sg_item.len = skb->len;
0198 
0199     ret = ath10k_hif_tx_sg(htc->ar, ep->ul_pipe_id, &sg_item, 1);
0200     if (ret)
0201         goto err_unmap;
0202 
0203     return 0;
0204 
0205 err_unmap:
0206     if (ar->bus_param.dev_type != ATH10K_DEV_TYPE_HL)
0207         dma_unmap_single(dev, skb_cb->paddr, skb->len, DMA_TO_DEVICE);
0208 err_credits:
0209     ath10k_htc_release_credit(ep, skb_len);
0210 err_pull:
0211     skb_pull(skb, sizeof(struct ath10k_htc_hdr));
0212     return ret;
0213 }
0214 
0215 void ath10k_htc_tx_completion_handler(struct ath10k *ar, struct sk_buff *skb)
0216 {
0217     struct ath10k_htc *htc = &ar->htc;
0218     struct ath10k_skb_cb *skb_cb;
0219     struct ath10k_htc_ep *ep;
0220 
0221     if (WARN_ON_ONCE(!skb))
0222         return;
0223 
0224     skb_cb = ATH10K_SKB_CB(skb);
0225     ep = &htc->endpoint[skb_cb->eid];
0226 
0227     ath10k_htc_notify_tx_completion(ep, skb);
0228     /* the skb now belongs to the completion handler */
0229 }
0230 EXPORT_SYMBOL(ath10k_htc_tx_completion_handler);
0231 
0232 /***********/
0233 /* Receive */
0234 /***********/
0235 
0236 static void
0237 ath10k_htc_process_credit_report(struct ath10k_htc *htc,
0238                  const struct ath10k_htc_credit_report *report,
0239                  int len,
0240                  enum ath10k_htc_ep_id eid)
0241 {
0242     struct ath10k *ar = htc->ar;
0243     struct ath10k_htc_ep *ep;
0244     int i, n_reports;
0245 
0246     if (len % sizeof(*report))
0247         ath10k_warn(ar, "Uneven credit report len %d", len);
0248 
0249     n_reports = len / sizeof(*report);
0250 
0251     spin_lock_bh(&htc->tx_lock);
0252     for (i = 0; i < n_reports; i++, report++) {
0253         if (report->eid >= ATH10K_HTC_EP_COUNT)
0254             break;
0255 
0256         ep = &htc->endpoint[report->eid];
0257         ep->tx_credits += report->credits;
0258 
0259         ath10k_dbg(ar, ATH10K_DBG_HTC, "htc ep %d got %d credits (total %d)\n",
0260                report->eid, report->credits, ep->tx_credits);
0261 
0262         if (ep->ep_ops.ep_tx_credits) {
0263             spin_unlock_bh(&htc->tx_lock);
0264             ep->ep_ops.ep_tx_credits(htc->ar);
0265             spin_lock_bh(&htc->tx_lock);
0266         }
0267     }
0268     spin_unlock_bh(&htc->tx_lock);
0269 }
0270 
0271 static int
0272 ath10k_htc_process_lookahead(struct ath10k_htc *htc,
0273                  const struct ath10k_htc_lookahead_report *report,
0274                  int len,
0275                  enum ath10k_htc_ep_id eid,
0276                  void *next_lookaheads,
0277                  int *next_lookaheads_len)
0278 {
0279     struct ath10k *ar = htc->ar;
0280 
0281     /* Invalid lookahead flags are actually transmitted by
0282      * the target in the HTC control message.
0283      * Since this will happen at every boot we silently ignore
0284      * the lookahead in this case
0285      */
0286     if (report->pre_valid != ((~report->post_valid) & 0xFF))
0287         return 0;
0288 
0289     if (next_lookaheads && next_lookaheads_len) {
0290         ath10k_dbg(ar, ATH10K_DBG_HTC,
0291                "htc rx lookahead found pre_valid 0x%x post_valid 0x%x\n",
0292                report->pre_valid, report->post_valid);
0293 
0294         /* look ahead bytes are valid, copy them over */
0295         memcpy((u8 *)next_lookaheads, report->lookahead, 4);
0296 
0297         *next_lookaheads_len = 1;
0298     }
0299 
0300     return 0;
0301 }
0302 
0303 static int
0304 ath10k_htc_process_lookahead_bundle(struct ath10k_htc *htc,
0305                     const struct ath10k_htc_lookahead_bundle *report,
0306                     int len,
0307                     enum ath10k_htc_ep_id eid,
0308                     void *next_lookaheads,
0309                     int *next_lookaheads_len)
0310 {
0311     struct ath10k *ar = htc->ar;
0312     int bundle_cnt = len / sizeof(*report);
0313 
0314     if (!bundle_cnt || (bundle_cnt > htc->max_msgs_per_htc_bundle)) {
0315         ath10k_warn(ar, "Invalid lookahead bundle count: %d\n",
0316                 bundle_cnt);
0317         return -EINVAL;
0318     }
0319 
0320     if (next_lookaheads && next_lookaheads_len) {
0321         int i;
0322 
0323         for (i = 0; i < bundle_cnt; i++) {
0324             memcpy(((u8 *)next_lookaheads) + 4 * i,
0325                    report->lookahead, 4);
0326             report++;
0327         }
0328 
0329         *next_lookaheads_len = bundle_cnt;
0330     }
0331 
0332     return 0;
0333 }
0334 
0335 int ath10k_htc_process_trailer(struct ath10k_htc *htc,
0336                    u8 *buffer,
0337                    int length,
0338                    enum ath10k_htc_ep_id src_eid,
0339                    void *next_lookaheads,
0340                    int *next_lookaheads_len)
0341 {
0342     struct ath10k_htc_lookahead_bundle *bundle;
0343     struct ath10k *ar = htc->ar;
0344     int status = 0;
0345     struct ath10k_htc_record *record;
0346     u8 *orig_buffer;
0347     int orig_length;
0348     size_t len;
0349 
0350     orig_buffer = buffer;
0351     orig_length = length;
0352 
0353     while (length > 0) {
0354         record = (struct ath10k_htc_record *)buffer;
0355 
0356         if (length < sizeof(record->hdr)) {
0357             status = -EINVAL;
0358             break;
0359         }
0360 
0361         if (record->hdr.len > length) {
0362             /* no room left in buffer for record */
0363             ath10k_warn(ar, "Invalid record length: %d\n",
0364                     record->hdr.len);
0365             status = -EINVAL;
0366             break;
0367         }
0368 
0369         switch (record->hdr.id) {
0370         case ATH10K_HTC_RECORD_CREDITS:
0371             len = sizeof(struct ath10k_htc_credit_report);
0372             if (record->hdr.len < len) {
0373                 ath10k_warn(ar, "Credit report too long\n");
0374                 status = -EINVAL;
0375                 break;
0376             }
0377             ath10k_htc_process_credit_report(htc,
0378                              record->credit_report,
0379                              record->hdr.len,
0380                              src_eid);
0381             break;
0382         case ATH10K_HTC_RECORD_LOOKAHEAD:
0383             len = sizeof(struct ath10k_htc_lookahead_report);
0384             if (record->hdr.len < len) {
0385                 ath10k_warn(ar, "Lookahead report too long\n");
0386                 status = -EINVAL;
0387                 break;
0388             }
0389             status = ath10k_htc_process_lookahead(htc,
0390                                   record->lookahead_report,
0391                                   record->hdr.len,
0392                                   src_eid,
0393                                   next_lookaheads,
0394                                   next_lookaheads_len);
0395             break;
0396         case ATH10K_HTC_RECORD_LOOKAHEAD_BUNDLE:
0397             bundle = record->lookahead_bundle;
0398             status = ath10k_htc_process_lookahead_bundle(htc,
0399                                      bundle,
0400                                      record->hdr.len,
0401                                      src_eid,
0402                                      next_lookaheads,
0403                                      next_lookaheads_len);
0404             break;
0405         default:
0406             ath10k_warn(ar, "Unhandled record: id:%d length:%d\n",
0407                     record->hdr.id, record->hdr.len);
0408             break;
0409         }
0410 
0411         if (status)
0412             break;
0413 
0414         /* multiple records may be present in a trailer */
0415         buffer += sizeof(record->hdr) + record->hdr.len;
0416         length -= sizeof(record->hdr) + record->hdr.len;
0417     }
0418 
0419     if (status)
0420         ath10k_dbg_dump(ar, ATH10K_DBG_HTC, "htc rx bad trailer", "",
0421                 orig_buffer, orig_length);
0422 
0423     return status;
0424 }
0425 EXPORT_SYMBOL(ath10k_htc_process_trailer);
0426 
0427 void ath10k_htc_rx_completion_handler(struct ath10k *ar, struct sk_buff *skb)
0428 {
0429     int status = 0;
0430     struct ath10k_htc *htc = &ar->htc;
0431     struct ath10k_htc_hdr *hdr;
0432     struct ath10k_htc_ep *ep;
0433     u16 payload_len;
0434     u32 trailer_len = 0;
0435     size_t min_len;
0436     u8 eid;
0437     bool trailer_present;
0438 
0439     hdr = (struct ath10k_htc_hdr *)skb->data;
0440     skb_pull(skb, sizeof(*hdr));
0441 
0442     eid = hdr->eid;
0443 
0444     if (eid >= ATH10K_HTC_EP_COUNT) {
0445         ath10k_warn(ar, "HTC Rx: invalid eid %d\n", eid);
0446         ath10k_dbg_dump(ar, ATH10K_DBG_HTC, "htc bad header", "",
0447                 hdr, sizeof(*hdr));
0448         goto out;
0449     }
0450 
0451     ep = &htc->endpoint[eid];
0452     if (ep->service_id == ATH10K_HTC_SVC_ID_UNUSED) {
0453         ath10k_warn(ar, "htc rx endpoint %d is not connected\n", eid);
0454         goto out;
0455     }
0456 
0457     payload_len = __le16_to_cpu(hdr->len);
0458 
0459     if (payload_len + sizeof(*hdr) > ATH10K_HTC_MAX_LEN) {
0460         ath10k_warn(ar, "HTC rx frame too long, len: %zu\n",
0461                 payload_len + sizeof(*hdr));
0462         ath10k_dbg_dump(ar, ATH10K_DBG_HTC, "htc bad rx pkt len", "",
0463                 hdr, sizeof(*hdr));
0464         goto out;
0465     }
0466 
0467     if (skb->len < payload_len) {
0468         ath10k_dbg(ar, ATH10K_DBG_HTC,
0469                "HTC Rx: insufficient length, got %d, expected %d\n",
0470                skb->len, payload_len);
0471         ath10k_dbg_dump(ar, ATH10K_DBG_HTC, "htc bad rx pkt len",
0472                 "", hdr, sizeof(*hdr));
0473         goto out;
0474     }
0475 
0476     /* get flags to check for trailer */
0477     trailer_present = hdr->flags & ATH10K_HTC_FLAG_TRAILER_PRESENT;
0478     if (trailer_present) {
0479         u8 *trailer;
0480 
0481         trailer_len = hdr->trailer_len;
0482         min_len = sizeof(struct ath10k_ath10k_htc_record_hdr);
0483 
0484         if ((trailer_len < min_len) ||
0485             (trailer_len > payload_len)) {
0486             ath10k_warn(ar, "Invalid trailer length: %d\n",
0487                     trailer_len);
0488             goto out;
0489         }
0490 
0491         trailer = (u8 *)hdr;
0492         trailer += sizeof(*hdr);
0493         trailer += payload_len;
0494         trailer -= trailer_len;
0495         status = ath10k_htc_process_trailer(htc, trailer,
0496                             trailer_len, hdr->eid,
0497                             NULL, NULL);
0498         if (status)
0499             goto out;
0500 
0501         skb_trim(skb, skb->len - trailer_len);
0502     }
0503 
0504     if (((int)payload_len - (int)trailer_len) <= 0)
0505         /* zero length packet with trailer data, just drop these */
0506         goto out;
0507 
0508     ath10k_dbg(ar, ATH10K_DBG_HTC, "htc rx completion ep %d skb %pK\n",
0509            eid, skb);
0510     ep->ep_ops.ep_rx_complete(ar, skb);
0511 
0512     /* skb is now owned by the rx completion handler */
0513     skb = NULL;
0514 out:
0515     kfree_skb(skb);
0516 }
0517 EXPORT_SYMBOL(ath10k_htc_rx_completion_handler);
0518 
0519 static void ath10k_htc_control_rx_complete(struct ath10k *ar,
0520                        struct sk_buff *skb)
0521 {
0522     struct ath10k_htc *htc = &ar->htc;
0523     struct ath10k_htc_msg *msg = (struct ath10k_htc_msg *)skb->data;
0524 
0525     switch (__le16_to_cpu(msg->hdr.message_id)) {
0526     case ATH10K_HTC_MSG_READY_ID:
0527     case ATH10K_HTC_MSG_CONNECT_SERVICE_RESP_ID:
0528         /* handle HTC control message */
0529         if (completion_done(&htc->ctl_resp)) {
0530             /* this is a fatal error, target should not be
0531              * sending unsolicited messages on the ep 0
0532              */
0533             ath10k_warn(ar, "HTC rx ctrl still processing\n");
0534             complete(&htc->ctl_resp);
0535             goto out;
0536         }
0537 
0538         htc->control_resp_len =
0539             min_t(int, skb->len,
0540                   ATH10K_HTC_MAX_CTRL_MSG_LEN);
0541 
0542         memcpy(htc->control_resp_buffer, skb->data,
0543                htc->control_resp_len);
0544 
0545         complete(&htc->ctl_resp);
0546         break;
0547     case ATH10K_HTC_MSG_SEND_SUSPEND_COMPLETE:
0548         htc->htc_ops.target_send_suspend_complete(ar);
0549         break;
0550     default:
0551         ath10k_warn(ar, "ignoring unsolicited htc ep0 event\n");
0552         break;
0553     }
0554 
0555 out:
0556     kfree_skb(skb);
0557 }
0558 
0559 /***************/
0560 /* Init/Deinit */
0561 /***************/
0562 
0563 static const char *htc_service_name(enum ath10k_htc_svc_id id)
0564 {
0565     switch (id) {
0566     case ATH10K_HTC_SVC_ID_RESERVED:
0567         return "Reserved";
0568     case ATH10K_HTC_SVC_ID_RSVD_CTRL:
0569         return "Control";
0570     case ATH10K_HTC_SVC_ID_WMI_CONTROL:
0571         return "WMI";
0572     case ATH10K_HTC_SVC_ID_WMI_DATA_BE:
0573         return "DATA BE";
0574     case ATH10K_HTC_SVC_ID_WMI_DATA_BK:
0575         return "DATA BK";
0576     case ATH10K_HTC_SVC_ID_WMI_DATA_VI:
0577         return "DATA VI";
0578     case ATH10K_HTC_SVC_ID_WMI_DATA_VO:
0579         return "DATA VO";
0580     case ATH10K_HTC_SVC_ID_NMI_CONTROL:
0581         return "NMI Control";
0582     case ATH10K_HTC_SVC_ID_NMI_DATA:
0583         return "NMI Data";
0584     case ATH10K_HTC_SVC_ID_HTT_DATA_MSG:
0585         return "HTT Data";
0586     case ATH10K_HTC_SVC_ID_HTT_DATA2_MSG:
0587         return "HTT Data";
0588     case ATH10K_HTC_SVC_ID_HTT_DATA3_MSG:
0589         return "HTT Data";
0590     case ATH10K_HTC_SVC_ID_TEST_RAW_STREAMS:
0591         return "RAW";
0592     case ATH10K_HTC_SVC_ID_HTT_LOG_MSG:
0593         return "PKTLOG";
0594     }
0595 
0596     return "Unknown";
0597 }
0598 
0599 static void ath10k_htc_reset_endpoint_states(struct ath10k_htc *htc)
0600 {
0601     struct ath10k_htc_ep *ep;
0602     int i;
0603 
0604     for (i = ATH10K_HTC_EP_0; i < ATH10K_HTC_EP_COUNT; i++) {
0605         ep = &htc->endpoint[i];
0606         ep->service_id = ATH10K_HTC_SVC_ID_UNUSED;
0607         ep->max_ep_message_len = 0;
0608         ep->max_tx_queue_depth = 0;
0609         ep->eid = i;
0610         ep->htc = htc;
0611         ep->tx_credit_flow_enabled = true;
0612     }
0613 }
0614 
0615 static u8 ath10k_htc_get_credit_allocation(struct ath10k_htc *htc,
0616                        u16 service_id)
0617 {
0618     u8 allocation = 0;
0619 
0620     /* The WMI control service is the only service with flow control.
0621      * Let it have all transmit credits.
0622      */
0623     if (service_id == ATH10K_HTC_SVC_ID_WMI_CONTROL)
0624         allocation = htc->total_transmit_credits;
0625 
0626     return allocation;
0627 }
0628 
0629 static int ath10k_htc_send_bundle(struct ath10k_htc_ep *ep,
0630                   struct sk_buff *bundle_skb,
0631                   struct sk_buff_head *tx_save_head)
0632 {
0633     struct ath10k_hif_sg_item sg_item;
0634     struct ath10k_htc *htc = ep->htc;
0635     struct ath10k *ar = htc->ar;
0636     struct sk_buff *skb;
0637     int ret, cn = 0;
0638     unsigned int skb_len;
0639 
0640     ath10k_dbg(ar, ATH10K_DBG_HTC, "bundle skb len %d\n", bundle_skb->len);
0641     skb_len = bundle_skb->len;
0642     ret = ath10k_htc_consume_credit(ep, skb_len, true);
0643 
0644     if (!ret) {
0645         sg_item.transfer_id = ep->eid;
0646         sg_item.transfer_context = bundle_skb;
0647         sg_item.vaddr = bundle_skb->data;
0648         sg_item.len = bundle_skb->len;
0649 
0650         ret = ath10k_hif_tx_sg(htc->ar, ep->ul_pipe_id, &sg_item, 1);
0651         if (ret)
0652             ath10k_htc_release_credit(ep, skb_len);
0653     }
0654 
0655     if (ret)
0656         dev_kfree_skb_any(bundle_skb);
0657 
0658     for (cn = 0; (skb = skb_dequeue_tail(tx_save_head)); cn++) {
0659         if (ret) {
0660             skb_pull(skb, sizeof(struct ath10k_htc_hdr));
0661             skb_queue_head(&ep->tx_req_head, skb);
0662         } else {
0663             skb_queue_tail(&ep->tx_complete_head, skb);
0664         }
0665     }
0666 
0667     if (!ret)
0668         queue_work(ar->workqueue_tx_complete, &ar->tx_complete_work);
0669 
0670     ath10k_dbg(ar, ATH10K_DBG_HTC,
0671            "bundle tx status %d eid %d req count %d count %d len %d\n",
0672            ret, ep->eid, skb_queue_len(&ep->tx_req_head), cn, skb_len);
0673     return ret;
0674 }
0675 
0676 static void ath10k_htc_send_one_skb(struct ath10k_htc_ep *ep, struct sk_buff *skb)
0677 {
0678     struct ath10k_htc *htc = ep->htc;
0679     struct ath10k *ar = htc->ar;
0680     int ret;
0681 
0682     ret = ath10k_htc_send(htc, ep->eid, skb);
0683 
0684     if (ret)
0685         skb_queue_head(&ep->tx_req_head, skb);
0686 
0687     ath10k_dbg(ar, ATH10K_DBG_HTC, "tx one status %d eid %d len %d pending count %d\n",
0688            ret, ep->eid, skb->len, skb_queue_len(&ep->tx_req_head));
0689 }
0690 
0691 static int ath10k_htc_send_bundle_skbs(struct ath10k_htc_ep *ep)
0692 {
0693     struct ath10k_htc *htc = ep->htc;
0694     struct sk_buff *bundle_skb, *skb;
0695     struct sk_buff_head tx_save_head;
0696     struct ath10k_htc_hdr *hdr;
0697     u8 *bundle_buf;
0698     int ret = 0, credit_pad, credit_remainder, trans_len, bundles_left = 0;
0699 
0700     if (htc->ar->state == ATH10K_STATE_WEDGED)
0701         return -ECOMM;
0702 
0703     if (ep->tx_credit_flow_enabled &&
0704         ep->tx_credits < ATH10K_MIN_CREDIT_PER_HTC_TX_BUNDLE)
0705         return 0;
0706 
0707     bundles_left = ATH10K_MAX_MSG_PER_HTC_TX_BUNDLE * ep->tx_credit_size;
0708     bundle_skb = dev_alloc_skb(bundles_left);
0709 
0710     if (!bundle_skb)
0711         return -ENOMEM;
0712 
0713     bundle_buf = bundle_skb->data;
0714     skb_queue_head_init(&tx_save_head);
0715 
0716     while (true) {
0717         skb = skb_dequeue(&ep->tx_req_head);
0718         if (!skb)
0719             break;
0720 
0721         credit_pad = 0;
0722         trans_len = skb->len + sizeof(*hdr);
0723         credit_remainder = trans_len % ep->tx_credit_size;
0724 
0725         if (credit_remainder != 0) {
0726             credit_pad = ep->tx_credit_size - credit_remainder;
0727             trans_len += credit_pad;
0728         }
0729 
0730         ret = ath10k_htc_consume_credit(ep,
0731                         bundle_buf + trans_len - bundle_skb->data,
0732                         false);
0733         if (ret) {
0734             skb_queue_head(&ep->tx_req_head, skb);
0735             break;
0736         }
0737 
0738         if (bundles_left < trans_len) {
0739             bundle_skb->len = bundle_buf - bundle_skb->data;
0740             ret = ath10k_htc_send_bundle(ep, bundle_skb, &tx_save_head);
0741 
0742             if (ret) {
0743                 skb_queue_head(&ep->tx_req_head, skb);
0744                 return ret;
0745             }
0746 
0747             if (skb_queue_len(&ep->tx_req_head) == 0) {
0748                 ath10k_htc_send_one_skb(ep, skb);
0749                 return ret;
0750             }
0751 
0752             if (ep->tx_credit_flow_enabled &&
0753                 ep->tx_credits < ATH10K_MIN_CREDIT_PER_HTC_TX_BUNDLE) {
0754                 skb_queue_head(&ep->tx_req_head, skb);
0755                 return 0;
0756             }
0757 
0758             bundles_left =
0759                 ATH10K_MAX_MSG_PER_HTC_TX_BUNDLE * ep->tx_credit_size;
0760             bundle_skb = dev_alloc_skb(bundles_left);
0761 
0762             if (!bundle_skb) {
0763                 skb_queue_head(&ep->tx_req_head, skb);
0764                 return -ENOMEM;
0765             }
0766             bundle_buf = bundle_skb->data;
0767             skb_queue_head_init(&tx_save_head);
0768         }
0769 
0770         skb_push(skb, sizeof(struct ath10k_htc_hdr));
0771         ath10k_htc_prepare_tx_skb(ep, skb);
0772 
0773         memcpy(bundle_buf, skb->data, skb->len);
0774         hdr = (struct ath10k_htc_hdr *)bundle_buf;
0775         hdr->flags |= ATH10K_HTC_FLAG_SEND_BUNDLE;
0776         hdr->pad_len = __cpu_to_le16(credit_pad);
0777         bundle_buf += trans_len;
0778         bundles_left -= trans_len;
0779         skb_queue_tail(&tx_save_head, skb);
0780     }
0781 
0782     if (bundle_buf != bundle_skb->data) {
0783         bundle_skb->len = bundle_buf - bundle_skb->data;
0784         ret = ath10k_htc_send_bundle(ep, bundle_skb, &tx_save_head);
0785     } else {
0786         dev_kfree_skb_any(bundle_skb);
0787     }
0788 
0789     return ret;
0790 }
0791 
0792 static void ath10k_htc_bundle_tx_work(struct work_struct *work)
0793 {
0794     struct ath10k *ar = container_of(work, struct ath10k, bundle_tx_work);
0795     struct ath10k_htc_ep *ep;
0796     struct sk_buff *skb;
0797     int i;
0798 
0799     for (i = 0; i < ARRAY_SIZE(ar->htc.endpoint); i++) {
0800         ep = &ar->htc.endpoint[i];
0801 
0802         if (!ep->bundle_tx)
0803             continue;
0804 
0805         ath10k_dbg(ar, ATH10K_DBG_HTC, "bundle tx work eid %d count %d\n",
0806                ep->eid, skb_queue_len(&ep->tx_req_head));
0807 
0808         if (skb_queue_len(&ep->tx_req_head) >=
0809             ATH10K_MIN_MSG_PER_HTC_TX_BUNDLE) {
0810             ath10k_htc_send_bundle_skbs(ep);
0811         } else {
0812             skb = skb_dequeue(&ep->tx_req_head);
0813 
0814             if (!skb)
0815                 continue;
0816             ath10k_htc_send_one_skb(ep, skb);
0817         }
0818     }
0819 }
0820 
0821 static void ath10k_htc_tx_complete_work(struct work_struct *work)
0822 {
0823     struct ath10k *ar = container_of(work, struct ath10k, tx_complete_work);
0824     struct ath10k_htc_ep *ep;
0825     enum ath10k_htc_ep_id eid;
0826     struct sk_buff *skb;
0827     int i;
0828 
0829     for (i = 0; i < ARRAY_SIZE(ar->htc.endpoint); i++) {
0830         ep = &ar->htc.endpoint[i];
0831         eid = ep->eid;
0832         if (ep->bundle_tx && eid == ar->htt.eid) {
0833             ath10k_dbg(ar, ATH10K_DBG_HTC, "bundle tx complete eid %d pending complete count%d\n",
0834                    ep->eid, skb_queue_len(&ep->tx_complete_head));
0835 
0836             while (true) {
0837                 skb = skb_dequeue(&ep->tx_complete_head);
0838                 if (!skb)
0839                     break;
0840                 ath10k_htc_notify_tx_completion(ep, skb);
0841             }
0842         }
0843     }
0844 }
0845 
0846 int ath10k_htc_send_hl(struct ath10k_htc *htc,
0847                enum ath10k_htc_ep_id eid,
0848                struct sk_buff *skb)
0849 {
0850     struct ath10k_htc_ep *ep = &htc->endpoint[eid];
0851     struct ath10k *ar = htc->ar;
0852 
0853     if (sizeof(struct ath10k_htc_hdr) + skb->len > ep->tx_credit_size) {
0854         ath10k_dbg(ar, ATH10K_DBG_HTC, "tx exceed max len %d\n", skb->len);
0855         return -ENOMEM;
0856     }
0857 
0858     ath10k_dbg(ar, ATH10K_DBG_HTC, "htc send hl eid %d bundle %d tx count %d len %d\n",
0859            eid, ep->bundle_tx, skb_queue_len(&ep->tx_req_head), skb->len);
0860 
0861     if (ep->bundle_tx) {
0862         skb_queue_tail(&ep->tx_req_head, skb);
0863         queue_work(ar->workqueue, &ar->bundle_tx_work);
0864         return 0;
0865     } else {
0866         return ath10k_htc_send(htc, eid, skb);
0867     }
0868 }
0869 
0870 void ath10k_htc_setup_tx_req(struct ath10k_htc_ep *ep)
0871 {
0872     if (ep->htc->max_msgs_per_htc_bundle >= ATH10K_MIN_MSG_PER_HTC_TX_BUNDLE &&
0873         !ep->bundle_tx) {
0874         ep->bundle_tx = true;
0875         skb_queue_head_init(&ep->tx_req_head);
0876         skb_queue_head_init(&ep->tx_complete_head);
0877     }
0878 }
0879 
0880 void ath10k_htc_stop_hl(struct ath10k *ar)
0881 {
0882     struct ath10k_htc_ep *ep;
0883     int i;
0884 
0885     cancel_work_sync(&ar->bundle_tx_work);
0886     cancel_work_sync(&ar->tx_complete_work);
0887 
0888     for (i = 0; i < ARRAY_SIZE(ar->htc.endpoint); i++) {
0889         ep = &ar->htc.endpoint[i];
0890 
0891         if (!ep->bundle_tx)
0892             continue;
0893 
0894         ath10k_dbg(ar, ATH10K_DBG_HTC, "stop tx work eid %d count %d\n",
0895                ep->eid, skb_queue_len(&ep->tx_req_head));
0896 
0897         skb_queue_purge(&ep->tx_req_head);
0898     }
0899 }
0900 
0901 int ath10k_htc_wait_target(struct ath10k_htc *htc)
0902 {
0903     struct ath10k *ar = htc->ar;
0904     int i, status = 0;
0905     unsigned long time_left;
0906     struct ath10k_htc_msg *msg;
0907     u16 message_id;
0908 
0909     time_left = wait_for_completion_timeout(&htc->ctl_resp,
0910                         ATH10K_HTC_WAIT_TIMEOUT_HZ);
0911     if (!time_left) {
0912         /* Workaround: In some cases the PCI HIF doesn't
0913          * receive interrupt for the control response message
0914          * even if the buffer was completed. It is suspected
0915          * iomap writes unmasking PCI CE irqs aren't propagated
0916          * properly in KVM PCI-passthrough sometimes.
0917          */
0918         ath10k_warn(ar, "failed to receive control response completion, polling..\n");
0919 
0920         for (i = 0; i < CE_COUNT; i++)
0921             ath10k_hif_send_complete_check(htc->ar, i, 1);
0922 
0923         time_left =
0924         wait_for_completion_timeout(&htc->ctl_resp,
0925                         ATH10K_HTC_WAIT_TIMEOUT_HZ);
0926 
0927         if (!time_left)
0928             status = -ETIMEDOUT;
0929     }
0930 
0931     if (status < 0) {
0932         ath10k_err(ar, "ctl_resp never came in (%d)\n", status);
0933         return status;
0934     }
0935 
0936     if (htc->control_resp_len < sizeof(msg->hdr) + sizeof(msg->ready)) {
0937         ath10k_err(ar, "Invalid HTC ready msg len:%d\n",
0938                htc->control_resp_len);
0939         return -ECOMM;
0940     }
0941 
0942     msg = (struct ath10k_htc_msg *)htc->control_resp_buffer;
0943     message_id   = __le16_to_cpu(msg->hdr.message_id);
0944 
0945     if (message_id != ATH10K_HTC_MSG_READY_ID) {
0946         ath10k_err(ar, "Invalid HTC ready msg: 0x%x\n", message_id);
0947         return -ECOMM;
0948     }
0949 
0950     htc->total_transmit_credits = __le16_to_cpu(msg->ready.credit_count);
0951     htc->target_credit_size = __le16_to_cpu(msg->ready.credit_size);
0952 
0953     ath10k_dbg(ar, ATH10K_DBG_HTC,
0954            "Target ready! transmit resources: %d size:%d\n",
0955            htc->total_transmit_credits,
0956            htc->target_credit_size);
0957 
0958     if ((htc->total_transmit_credits == 0) ||
0959         (htc->target_credit_size == 0)) {
0960         ath10k_err(ar, "Invalid credit size received\n");
0961         return -ECOMM;
0962     }
0963 
0964     /* The only way to determine if the ready message is an extended
0965      * message is from the size.
0966      */
0967     if (htc->control_resp_len >=
0968         sizeof(msg->hdr) + sizeof(msg->ready_ext)) {
0969         htc->alt_data_credit_size =
0970             __le16_to_cpu(msg->ready_ext.reserved) &
0971             ATH10K_HTC_MSG_READY_EXT_ALT_DATA_MASK;
0972         htc->max_msgs_per_htc_bundle =
0973             min_t(u8, msg->ready_ext.max_msgs_per_htc_bundle,
0974                   HTC_HOST_MAX_MSG_PER_RX_BUNDLE);
0975         ath10k_dbg(ar, ATH10K_DBG_HTC,
0976                "Extended ready message RX bundle size %d alt size %d\n",
0977                htc->max_msgs_per_htc_bundle,
0978                htc->alt_data_credit_size);
0979     }
0980 
0981     INIT_WORK(&ar->bundle_tx_work, ath10k_htc_bundle_tx_work);
0982     INIT_WORK(&ar->tx_complete_work, ath10k_htc_tx_complete_work);
0983 
0984     return 0;
0985 }
0986 
0987 void ath10k_htc_change_tx_credit_flow(struct ath10k_htc *htc,
0988                       enum ath10k_htc_ep_id eid,
0989                       bool enable)
0990 {
0991     struct ath10k *ar = htc->ar;
0992     struct ath10k_htc_ep *ep = &ar->htc.endpoint[eid];
0993 
0994     ep->tx_credit_flow_enabled = enable;
0995 }
0996 
0997 int ath10k_htc_connect_service(struct ath10k_htc *htc,
0998                    struct ath10k_htc_svc_conn_req *conn_req,
0999                    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 
1105 setup:
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 
1162 struct 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 
1179 static 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 
1185 static 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 
1210 static 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 
1229 int 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 */
1274 int 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 }