ath10k: add HTC TX credits replenishing notification
[cascardo/linux.git] / drivers / net / wireless / ath / ath10k / htc.c
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
26 static 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
36 static void ath10k_htc_control_tx_complete(struct ath10k *ar,
37                                            struct sk_buff *skb)
38 {
39         kfree_skb(skb);
40 }
41
42 static 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
63 static 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
70 static 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 */
88 static 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
100 static 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
120 static 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;
146 err:
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         if (ep->ep_ops.ep_tx_credits)
154                 ep->ep_ops.ep_tx_credits(htc->ar);
155
156         /* this is the simplest way to handle out-of-resources for non-credit
157          * based endpoints. credit based endpoints can still get -ENOSR, but
158          * this is highly unlikely as credit reservation should prevent that */
159         if (ret == -ENOSR) {
160                 spin_lock_bh(&htc->tx_lock);
161                 __skb_queue_head(&ep->tx_queue, skb);
162                 spin_unlock_bh(&htc->tx_lock);
163
164                 return ret;
165         }
166
167         skb_cb->is_aborted = true;
168         ath10k_htc_notify_tx_completion(ep, skb);
169
170         return ret;
171 }
172
173 static void ath10k_htc_send_work(struct work_struct *work)
174 {
175         struct ath10k_htc_ep *ep = container_of(work,
176                                         struct ath10k_htc_ep, send_work);
177         struct ath10k_htc *htc = ep->htc;
178         struct sk_buff *skb;
179         u8 credits = 0;
180         int ret;
181
182         while (true) {
183                 if (ep->ul_is_polled)
184                         ath10k_htc_send_complete_check(ep, 0);
185
186                 spin_lock_bh(&htc->tx_lock);
187                 skb = __skb_dequeue(&ep->tx_queue);
188
189                 if (ep->tx_credit_flow_enabled) {
190                         credits = DIV_ROUND_UP(skb->len,
191                                                htc->target_credit_size);
192                         if (ep->tx_credits < credits) {
193                                 __skb_queue_head(&ep->tx_queue, skb);
194                                 skb = NULL;
195                         }
196                 }
197                 spin_unlock_bh(&htc->tx_lock);
198
199                 if (!skb)
200                         break;
201
202                 ret = ath10k_htc_issue_skb(htc, ep, skb, credits);
203                 if (ret == -ENOSR)
204                         break;
205         }
206 }
207
208 int ath10k_htc_send(struct ath10k_htc *htc,
209                     enum ath10k_htc_ep_id eid,
210                     struct sk_buff *skb)
211 {
212         struct ath10k_htc_ep *ep = &htc->endpoint[eid];
213
214         if (htc->ar->state == ATH10K_STATE_WEDGED)
215                 return -ECOMM;
216
217         if (eid >= ATH10K_HTC_EP_COUNT) {
218                 ath10k_warn("Invalid endpoint id: %d\n", eid);
219                 return -ENOENT;
220         }
221
222         spin_lock_bh(&htc->tx_lock);
223         if (htc->stopped) {
224                 spin_unlock_bh(&htc->tx_lock);
225                 return -ESHUTDOWN;
226         }
227
228         __skb_queue_tail(&ep->tx_queue, skb);
229         skb_push(skb, sizeof(struct ath10k_htc_hdr));
230         spin_unlock_bh(&htc->tx_lock);
231
232         queue_work(htc->ar->workqueue, &ep->send_work);
233         return 0;
234 }
235
236 static int ath10k_htc_tx_completion_handler(struct ath10k *ar,
237                                             struct sk_buff *skb,
238                                             unsigned int eid)
239 {
240         struct ath10k_htc *htc = &ar->htc;
241         struct ath10k_htc_ep *ep = &htc->endpoint[eid];
242
243         ath10k_htc_notify_tx_completion(ep, skb);
244         /* the skb now belongs to the completion handler */
245
246         /* note: when using TX credit flow, the re-checking of queues happens
247          * when credits flow back from the target.  in the non-TX credit case,
248          * we recheck after the packet completes */
249         spin_lock_bh(&htc->tx_lock);
250         if (!ep->tx_credit_flow_enabled && !htc->stopped)
251                 queue_work(ar->workqueue, &ep->send_work);
252         spin_unlock_bh(&htc->tx_lock);
253
254         return 0;
255 }
256
257 /* flush endpoint TX queue */
258 static void ath10k_htc_flush_endpoint_tx(struct ath10k_htc *htc,
259                                          struct ath10k_htc_ep *ep)
260 {
261         struct sk_buff *skb;
262         struct ath10k_skb_cb *skb_cb;
263
264         spin_lock_bh(&htc->tx_lock);
265         for (;;) {
266                 skb = __skb_dequeue(&ep->tx_queue);
267                 if (!skb)
268                         break;
269
270                 skb_cb = ATH10K_SKB_CB(skb);
271                 skb_cb->is_aborted = true;
272                 ath10k_htc_notify_tx_completion(ep, skb);
273         }
274         spin_unlock_bh(&htc->tx_lock);
275
276         cancel_work_sync(&ep->send_work);
277 }
278
279 /***********/
280 /* Receive */
281 /***********/
282
283 static void
284 ath10k_htc_process_credit_report(struct ath10k_htc *htc,
285                                  const struct ath10k_htc_credit_report *report,
286                                  int len,
287                                  enum ath10k_htc_ep_id eid)
288 {
289         struct ath10k_htc_ep *ep;
290         int i, n_reports;
291
292         if (len % sizeof(*report))
293                 ath10k_warn("Uneven credit report len %d", len);
294
295         n_reports = len / sizeof(*report);
296
297         spin_lock_bh(&htc->tx_lock);
298         for (i = 0; i < n_reports; i++, report++) {
299                 if (report->eid >= ATH10K_HTC_EP_COUNT)
300                         break;
301
302                 ath10k_dbg(ATH10K_DBG_HTC, "ep %d got %d credits\n",
303                            report->eid, report->credits);
304
305                 ep = &htc->endpoint[report->eid];
306                 ep->tx_credits += report->credits;
307
308                 if (ep->ep_ops.ep_tx_credits) {
309                         spin_unlock_bh(&htc->tx_lock);
310                         ep->ep_ops.ep_tx_credits(htc->ar);
311                         spin_lock_bh(&htc->tx_lock);
312                 }
313
314                 if (ep->tx_credits && !skb_queue_empty(&ep->tx_queue))
315                         queue_work(htc->ar->workqueue, &ep->send_work);
316         }
317         spin_unlock_bh(&htc->tx_lock);
318 }
319
320 static int ath10k_htc_process_trailer(struct ath10k_htc *htc,
321                                       u8 *buffer,
322                                       int length,
323                                       enum ath10k_htc_ep_id src_eid)
324 {
325         int status = 0;
326         struct ath10k_htc_record *record;
327         u8 *orig_buffer;
328         int orig_length;
329         size_t len;
330
331         orig_buffer = buffer;
332         orig_length = length;
333
334         while (length > 0) {
335                 record = (struct ath10k_htc_record *)buffer;
336
337                 if (length < sizeof(record->hdr)) {
338                         status = -EINVAL;
339                         break;
340                 }
341
342                 if (record->hdr.len > length) {
343                         /* no room left in buffer for record */
344                         ath10k_warn("Invalid record length: %d\n",
345                                     record->hdr.len);
346                         status = -EINVAL;
347                         break;
348                 }
349
350                 switch (record->hdr.id) {
351                 case ATH10K_HTC_RECORD_CREDITS:
352                         len = sizeof(struct ath10k_htc_credit_report);
353                         if (record->hdr.len < len) {
354                                 ath10k_warn("Credit report too long\n");
355                                 status = -EINVAL;
356                                 break;
357                         }
358                         ath10k_htc_process_credit_report(htc,
359                                                          record->credit_report,
360                                                          record->hdr.len,
361                                                          src_eid);
362                         break;
363                 default:
364                         ath10k_warn("Unhandled record: id:%d length:%d\n",
365                                     record->hdr.id, record->hdr.len);
366                         break;
367                 }
368
369                 if (status)
370                         break;
371
372                 /* multiple records may be present in a trailer */
373                 buffer += sizeof(record->hdr) + record->hdr.len;
374                 length -= sizeof(record->hdr) + record->hdr.len;
375         }
376
377         if (status)
378                 ath10k_dbg_dump(ATH10K_DBG_HTC, "htc rx bad trailer", "",
379                                 orig_buffer, orig_length);
380
381         return status;
382 }
383
384 static int ath10k_htc_rx_completion_handler(struct ath10k *ar,
385                                             struct sk_buff *skb,
386                                             u8 pipe_id)
387 {
388         int status = 0;
389         struct ath10k_htc *htc = &ar->htc;
390         struct ath10k_htc_hdr *hdr;
391         struct ath10k_htc_ep *ep;
392         u16 payload_len;
393         u32 trailer_len = 0;
394         size_t min_len;
395         u8 eid;
396         bool trailer_present;
397
398         hdr = (struct ath10k_htc_hdr *)skb->data;
399         skb_pull(skb, sizeof(*hdr));
400
401         eid = hdr->eid;
402
403         if (eid >= ATH10K_HTC_EP_COUNT) {
404                 ath10k_warn("HTC Rx: invalid eid %d\n", eid);
405                 ath10k_dbg_dump(ATH10K_DBG_HTC, "htc bad header", "",
406                                 hdr, sizeof(*hdr));
407                 status = -EINVAL;
408                 goto out;
409         }
410
411         ep = &htc->endpoint[eid];
412
413         /*
414          * If this endpoint that received a message from the target has
415          * a to-target HIF pipe whose send completions are polled rather
416          * than interrupt-driven, this is a good point to ask HIF to check
417          * whether it has any completed sends to handle.
418          */
419         if (ep->ul_is_polled)
420                 ath10k_htc_send_complete_check(ep, 1);
421
422         payload_len = __le16_to_cpu(hdr->len);
423
424         if (payload_len + sizeof(*hdr) > ATH10K_HTC_MAX_LEN) {
425                 ath10k_warn("HTC rx frame too long, len: %zu\n",
426                             payload_len + sizeof(*hdr));
427                 ath10k_dbg_dump(ATH10K_DBG_HTC, "htc bad rx pkt len", "",
428                                 hdr, sizeof(*hdr));
429                 status = -EINVAL;
430                 goto out;
431         }
432
433         if (skb->len < payload_len) {
434                 ath10k_dbg(ATH10K_DBG_HTC,
435                            "HTC Rx: insufficient length, got %d, expected %d\n",
436                            skb->len, payload_len);
437                 ath10k_dbg_dump(ATH10K_DBG_HTC, "htc bad rx pkt len",
438                                 "", hdr, sizeof(*hdr));
439                 status = -EINVAL;
440                 goto out;
441         }
442
443         /* get flags to check for trailer */
444         trailer_present = hdr->flags & ATH10K_HTC_FLAG_TRAILER_PRESENT;
445         if (trailer_present) {
446                 u8 *trailer;
447
448                 trailer_len = hdr->trailer_len;
449                 min_len = sizeof(struct ath10k_ath10k_htc_record_hdr);
450
451                 if ((trailer_len < min_len) ||
452                     (trailer_len > payload_len)) {
453                         ath10k_warn("Invalid trailer length: %d\n",
454                                     trailer_len);
455                         status = -EPROTO;
456                         goto out;
457                 }
458
459                 trailer = (u8 *)hdr;
460                 trailer += sizeof(*hdr);
461                 trailer += payload_len;
462                 trailer -= trailer_len;
463                 status = ath10k_htc_process_trailer(htc, trailer,
464                                                     trailer_len, hdr->eid);
465                 if (status)
466                         goto out;
467
468                 skb_trim(skb, skb->len - trailer_len);
469         }
470
471         if (((int)payload_len - (int)trailer_len) <= 0)
472                 /* zero length packet with trailer data, just drop these */
473                 goto out;
474
475         if (eid == ATH10K_HTC_EP_0) {
476                 struct ath10k_htc_msg *msg = (struct ath10k_htc_msg *)skb->data;
477
478                 switch (__le16_to_cpu(msg->hdr.message_id)) {
479                 default:
480                         /* handle HTC control message */
481                         if (completion_done(&htc->ctl_resp)) {
482                                 /*
483                                  * this is a fatal error, target should not be
484                                  * sending unsolicited messages on the ep 0
485                                  */
486                                 ath10k_warn("HTC rx ctrl still processing\n");
487                                 status = -EINVAL;
488                                 complete(&htc->ctl_resp);
489                                 goto out;
490                         }
491
492                         htc->control_resp_len =
493                                 min_t(int, skb->len,
494                                       ATH10K_HTC_MAX_CTRL_MSG_LEN);
495
496                         memcpy(htc->control_resp_buffer, skb->data,
497                                htc->control_resp_len);
498
499                         complete(&htc->ctl_resp);
500                         break;
501                 case ATH10K_HTC_MSG_SEND_SUSPEND_COMPLETE:
502                         htc->htc_ops.target_send_suspend_complete(ar);
503                 }
504                 goto out;
505         }
506
507         ath10k_dbg(ATH10K_DBG_HTC, "htc rx completion ep %d skb %p\n",
508                    eid, skb);
509         ep->ep_ops.ep_rx_complete(ar, skb);
510
511         /* skb is now owned by the rx completion handler */
512         skb = NULL;
513 out:
514         kfree_skb(skb);
515
516         return status;
517 }
518
519 static void ath10k_htc_control_rx_complete(struct ath10k *ar,
520                                            struct sk_buff *skb)
521 {
522         /* This is unexpected. FW is not supposed to send regular rx on this
523          * endpoint. */
524         ath10k_warn("unexpected htc rx\n");
525         kfree_skb(skb);
526 }
527
528 /***************/
529 /* Init/Deinit */
530 /***************/
531
532 static const char *htc_service_name(enum ath10k_htc_svc_id id)
533 {
534         switch (id) {
535         case ATH10K_HTC_SVC_ID_RESERVED:
536                 return "Reserved";
537         case ATH10K_HTC_SVC_ID_RSVD_CTRL:
538                 return "Control";
539         case ATH10K_HTC_SVC_ID_WMI_CONTROL:
540                 return "WMI";
541         case ATH10K_HTC_SVC_ID_WMI_DATA_BE:
542                 return "DATA BE";
543         case ATH10K_HTC_SVC_ID_WMI_DATA_BK:
544                 return "DATA BK";
545         case ATH10K_HTC_SVC_ID_WMI_DATA_VI:
546                 return "DATA VI";
547         case ATH10K_HTC_SVC_ID_WMI_DATA_VO:
548                 return "DATA VO";
549         case ATH10K_HTC_SVC_ID_NMI_CONTROL:
550                 return "NMI Control";
551         case ATH10K_HTC_SVC_ID_NMI_DATA:
552                 return "NMI Data";
553         case ATH10K_HTC_SVC_ID_HTT_DATA_MSG:
554                 return "HTT Data";
555         case ATH10K_HTC_SVC_ID_TEST_RAW_STREAMS:
556                 return "RAW";
557         }
558
559         return "Unknown";
560 }
561
562 static void ath10k_htc_reset_endpoint_states(struct ath10k_htc *htc)
563 {
564         struct ath10k_htc_ep *ep;
565         int i;
566
567         for (i = ATH10K_HTC_EP_0; i < ATH10K_HTC_EP_COUNT; i++) {
568                 ep = &htc->endpoint[i];
569                 ep->service_id = ATH10K_HTC_SVC_ID_UNUSED;
570                 ep->max_ep_message_len = 0;
571                 ep->max_tx_queue_depth = 0;
572                 ep->eid = i;
573                 skb_queue_head_init(&ep->tx_queue);
574                 ep->htc = htc;
575                 ep->tx_credit_flow_enabled = true;
576                 INIT_WORK(&ep->send_work, ath10k_htc_send_work);
577         }
578 }
579
580 static void ath10k_htc_setup_target_buffer_assignments(struct ath10k_htc *htc)
581 {
582         struct ath10k_htc_svc_tx_credits *entry;
583
584         entry = &htc->service_tx_alloc[0];
585
586         /*
587          * for PCIE allocate all credists/HTC buffers to WMI.
588          * no buffers are used/required for data. data always
589          * remains on host.
590          */
591         entry++;
592         entry->service_id = ATH10K_HTC_SVC_ID_WMI_CONTROL;
593         entry->credit_allocation = htc->total_transmit_credits;
594 }
595
596 static u8 ath10k_htc_get_credit_allocation(struct ath10k_htc *htc,
597                                            u16 service_id)
598 {
599         u8 allocation = 0;
600         int i;
601
602         for (i = 0; i < ATH10K_HTC_EP_COUNT; i++) {
603                 if (htc->service_tx_alloc[i].service_id == service_id)
604                         allocation =
605                             htc->service_tx_alloc[i].credit_allocation;
606         }
607
608         return allocation;
609 }
610
611 int ath10k_htc_wait_target(struct ath10k_htc *htc)
612 {
613         int status = 0;
614         struct ath10k_htc_svc_conn_req conn_req;
615         struct ath10k_htc_svc_conn_resp conn_resp;
616         struct ath10k_htc_msg *msg;
617         u16 message_id;
618         u16 credit_count;
619         u16 credit_size;
620
621         INIT_COMPLETION(htc->ctl_resp);
622
623         status = ath10k_hif_start(htc->ar);
624         if (status) {
625                 ath10k_err("could not start HIF (%d)\n", status);
626                 goto err_start;
627         }
628
629         status = wait_for_completion_timeout(&htc->ctl_resp,
630                                              ATH10K_HTC_WAIT_TIMEOUT_HZ);
631         if (status <= 0) {
632                 if (status == 0)
633                         status = -ETIMEDOUT;
634
635                 ath10k_err("ctl_resp never came in (%d)\n", status);
636                 goto err_target;
637         }
638
639         if (htc->control_resp_len < sizeof(msg->hdr) + sizeof(msg->ready)) {
640                 ath10k_err("Invalid HTC ready msg len:%d\n",
641                            htc->control_resp_len);
642
643                 status = -ECOMM;
644                 goto err_target;
645         }
646
647         msg = (struct ath10k_htc_msg *)htc->control_resp_buffer;
648         message_id   = __le16_to_cpu(msg->hdr.message_id);
649         credit_count = __le16_to_cpu(msg->ready.credit_count);
650         credit_size  = __le16_to_cpu(msg->ready.credit_size);
651
652         if (message_id != ATH10K_HTC_MSG_READY_ID) {
653                 ath10k_err("Invalid HTC ready msg: 0x%x\n", message_id);
654                 status = -ECOMM;
655                 goto err_target;
656         }
657
658         htc->total_transmit_credits = credit_count;
659         htc->target_credit_size = credit_size;
660
661         ath10k_dbg(ATH10K_DBG_HTC,
662                    "Target ready! transmit resources: %d size:%d\n",
663                    htc->total_transmit_credits,
664                    htc->target_credit_size);
665
666         if ((htc->total_transmit_credits == 0) ||
667             (htc->target_credit_size == 0)) {
668                 status = -ECOMM;
669                 ath10k_err("Invalid credit size received\n");
670                 goto err_target;
671         }
672
673         ath10k_htc_setup_target_buffer_assignments(htc);
674
675         /* setup our pseudo HTC control endpoint connection */
676         memset(&conn_req, 0, sizeof(conn_req));
677         memset(&conn_resp, 0, sizeof(conn_resp));
678         conn_req.ep_ops.ep_tx_complete = ath10k_htc_control_tx_complete;
679         conn_req.ep_ops.ep_rx_complete = ath10k_htc_control_rx_complete;
680         conn_req.max_send_queue_depth = ATH10K_NUM_CONTROL_TX_BUFFERS;
681         conn_req.service_id = ATH10K_HTC_SVC_ID_RSVD_CTRL;
682
683         /* connect fake service */
684         status = ath10k_htc_connect_service(htc, &conn_req, &conn_resp);
685         if (status) {
686                 ath10k_err("could not connect to htc service (%d)\n", status);
687                 goto err_target;
688         }
689
690         return 0;
691 err_target:
692         ath10k_hif_stop(htc->ar);
693 err_start:
694         return status;
695 }
696
697 int ath10k_htc_connect_service(struct ath10k_htc *htc,
698                                struct ath10k_htc_svc_conn_req *conn_req,
699                                struct ath10k_htc_svc_conn_resp *conn_resp)
700 {
701         struct ath10k_htc_msg *msg;
702         struct ath10k_htc_conn_svc *req_msg;
703         struct ath10k_htc_conn_svc_response resp_msg_dummy;
704         struct ath10k_htc_conn_svc_response *resp_msg = &resp_msg_dummy;
705         enum ath10k_htc_ep_id assigned_eid = ATH10K_HTC_EP_COUNT;
706         struct ath10k_htc_ep *ep;
707         struct sk_buff *skb;
708         unsigned int max_msg_size = 0;
709         int length, status;
710         bool disable_credit_flow_ctrl = false;
711         u16 message_id, service_id, flags = 0;
712         u8 tx_alloc = 0;
713
714         /* special case for HTC pseudo control service */
715         if (conn_req->service_id == ATH10K_HTC_SVC_ID_RSVD_CTRL) {
716                 disable_credit_flow_ctrl = true;
717                 assigned_eid = ATH10K_HTC_EP_0;
718                 max_msg_size = ATH10K_HTC_MAX_CTRL_MSG_LEN;
719                 memset(&resp_msg_dummy, 0, sizeof(resp_msg_dummy));
720                 goto setup;
721         }
722
723         tx_alloc = ath10k_htc_get_credit_allocation(htc,
724                                                     conn_req->service_id);
725         if (!tx_alloc)
726                 ath10k_dbg(ATH10K_DBG_BOOT,
727                            "boot htc service %s does not allocate target credits\n",
728                            htc_service_name(conn_req->service_id));
729
730         skb = ath10k_htc_build_tx_ctrl_skb(htc->ar);
731         if (!skb) {
732                 ath10k_err("Failed to allocate HTC packet\n");
733                 return -ENOMEM;
734         }
735
736         length = sizeof(msg->hdr) + sizeof(msg->connect_service);
737         skb_put(skb, length);
738         memset(skb->data, 0, length);
739
740         msg = (struct ath10k_htc_msg *)skb->data;
741         msg->hdr.message_id =
742                 __cpu_to_le16(ATH10K_HTC_MSG_CONNECT_SERVICE_ID);
743
744         flags |= SM(tx_alloc, ATH10K_HTC_CONN_FLAGS_RECV_ALLOC);
745
746         /* Only enable credit flow control for WMI ctrl service */
747         if (conn_req->service_id != ATH10K_HTC_SVC_ID_WMI_CONTROL) {
748                 flags |= ATH10K_HTC_CONN_FLAGS_DISABLE_CREDIT_FLOW_CTRL;
749                 disable_credit_flow_ctrl = true;
750         }
751
752         req_msg = &msg->connect_service;
753         req_msg->flags = __cpu_to_le16(flags);
754         req_msg->service_id = __cpu_to_le16(conn_req->service_id);
755
756         INIT_COMPLETION(htc->ctl_resp);
757
758         status = ath10k_htc_send(htc, ATH10K_HTC_EP_0, skb);
759         if (status) {
760                 kfree_skb(skb);
761                 return status;
762         }
763
764         /* wait for response */
765         status = wait_for_completion_timeout(&htc->ctl_resp,
766                                              ATH10K_HTC_CONN_SVC_TIMEOUT_HZ);
767         if (status <= 0) {
768                 if (status == 0)
769                         status = -ETIMEDOUT;
770                 ath10k_err("Service connect timeout: %d\n", status);
771                 return status;
772         }
773
774         /* we controlled the buffer creation, it's aligned */
775         msg = (struct ath10k_htc_msg *)htc->control_resp_buffer;
776         resp_msg = &msg->connect_service_response;
777         message_id = __le16_to_cpu(msg->hdr.message_id);
778         service_id = __le16_to_cpu(resp_msg->service_id);
779
780         if ((message_id != ATH10K_HTC_MSG_CONNECT_SERVICE_RESP_ID) ||
781             (htc->control_resp_len < sizeof(msg->hdr) +
782              sizeof(msg->connect_service_response))) {
783                 ath10k_err("Invalid resp message ID 0x%x", message_id);
784                 return -EPROTO;
785         }
786
787         ath10k_dbg(ATH10K_DBG_HTC,
788                    "HTC Service %s connect response: status: 0x%x, assigned ep: 0x%x\n",
789                    htc_service_name(service_id),
790                    resp_msg->status, resp_msg->eid);
791
792         conn_resp->connect_resp_code = resp_msg->status;
793
794         /* check response status */
795         if (resp_msg->status != ATH10K_HTC_CONN_SVC_STATUS_SUCCESS) {
796                 ath10k_err("HTC Service %s connect request failed: 0x%x)\n",
797                            htc_service_name(service_id),
798                            resp_msg->status);
799                 return -EPROTO;
800         }
801
802         assigned_eid = (enum ath10k_htc_ep_id)resp_msg->eid;
803         max_msg_size = __le16_to_cpu(resp_msg->max_msg_size);
804
805 setup:
806
807         if (assigned_eid >= ATH10K_HTC_EP_COUNT)
808                 return -EPROTO;
809
810         if (max_msg_size == 0)
811                 return -EPROTO;
812
813         ep = &htc->endpoint[assigned_eid];
814         ep->eid = assigned_eid;
815
816         if (ep->service_id != ATH10K_HTC_SVC_ID_UNUSED)
817                 return -EPROTO;
818
819         /* return assigned endpoint to caller */
820         conn_resp->eid = assigned_eid;
821         conn_resp->max_msg_len = __le16_to_cpu(resp_msg->max_msg_size);
822
823         /* setup the endpoint */
824         ep->service_id = conn_req->service_id;
825         ep->max_tx_queue_depth = conn_req->max_send_queue_depth;
826         ep->max_ep_message_len = __le16_to_cpu(resp_msg->max_msg_size);
827         ep->tx_credits = tx_alloc;
828         ep->tx_credit_size = htc->target_credit_size;
829         ep->tx_credits_per_max_message = ep->max_ep_message_len /
830                                          htc->target_credit_size;
831
832         if (ep->max_ep_message_len % htc->target_credit_size)
833                 ep->tx_credits_per_max_message++;
834
835         /* copy all the callbacks */
836         ep->ep_ops = conn_req->ep_ops;
837
838         status = ath10k_hif_map_service_to_pipe(htc->ar,
839                                                 ep->service_id,
840                                                 &ep->ul_pipe_id,
841                                                 &ep->dl_pipe_id,
842                                                 &ep->ul_is_polled,
843                                                 &ep->dl_is_polled);
844         if (status)
845                 return status;
846
847         ath10k_dbg(ATH10K_DBG_BOOT,
848                    "boot htc service '%s' ul pipe %d dl pipe %d eid %d ready\n",
849                    htc_service_name(ep->service_id), ep->ul_pipe_id,
850                    ep->dl_pipe_id, ep->eid);
851
852         ath10k_dbg(ATH10K_DBG_BOOT,
853                    "boot htc ep %d ul polled %d dl polled %d\n",
854                    ep->eid, ep->ul_is_polled, ep->dl_is_polled);
855
856         if (disable_credit_flow_ctrl && ep->tx_credit_flow_enabled) {
857                 ep->tx_credit_flow_enabled = false;
858                 ath10k_dbg(ATH10K_DBG_BOOT,
859                            "boot htc service '%s' eid %d TX flow control disabled\n",
860                            htc_service_name(ep->service_id), assigned_eid);
861         }
862
863         return status;
864 }
865
866 struct sk_buff *ath10k_htc_alloc_skb(int size)
867 {
868         struct sk_buff *skb;
869
870         skb = dev_alloc_skb(size + sizeof(struct ath10k_htc_hdr));
871         if (!skb) {
872                 ath10k_warn("could not allocate HTC tx skb\n");
873                 return NULL;
874         }
875
876         skb_reserve(skb, sizeof(struct ath10k_htc_hdr));
877
878         /* FW/HTC requires 4-byte aligned streams */
879         if (!IS_ALIGNED((unsigned long)skb->data, 4))
880                 ath10k_warn("Unaligned HTC tx skb\n");
881
882         return skb;
883 }
884
885 int ath10k_htc_start(struct ath10k_htc *htc)
886 {
887         struct sk_buff *skb;
888         int status = 0;
889         struct ath10k_htc_msg *msg;
890
891         skb = ath10k_htc_build_tx_ctrl_skb(htc->ar);
892         if (!skb)
893                 return -ENOMEM;
894
895         skb_put(skb, sizeof(msg->hdr) + sizeof(msg->setup_complete_ext));
896         memset(skb->data, 0, skb->len);
897
898         msg = (struct ath10k_htc_msg *)skb->data;
899         msg->hdr.message_id =
900                 __cpu_to_le16(ATH10K_HTC_MSG_SETUP_COMPLETE_EX_ID);
901
902         ath10k_dbg(ATH10K_DBG_HTC, "HTC is using TX credit flow control\n");
903
904         status = ath10k_htc_send(htc, ATH10K_HTC_EP_0, skb);
905         if (status) {
906                 kfree_skb(skb);
907                 return status;
908         }
909
910         return 0;
911 }
912
913 /*
914  * stop HTC communications, i.e. stop interrupt reception, and flush all
915  * queued buffers
916  */
917 void ath10k_htc_stop(struct ath10k_htc *htc)
918 {
919         int i;
920         struct ath10k_htc_ep *ep;
921
922         spin_lock_bh(&htc->tx_lock);
923         htc->stopped = true;
924         spin_unlock_bh(&htc->tx_lock);
925
926         for (i = ATH10K_HTC_EP_0; i < ATH10K_HTC_EP_COUNT; i++) {
927                 ep = &htc->endpoint[i];
928                 ath10k_htc_flush_endpoint_tx(htc, ep);
929         }
930
931         ath10k_hif_stop(htc->ar);
932 }
933
934 /* registered target arrival callback from the HIF layer */
935 int ath10k_htc_init(struct ath10k *ar)
936 {
937         struct ath10k_hif_cb htc_callbacks;
938         struct ath10k_htc_ep *ep = NULL;
939         struct ath10k_htc *htc = &ar->htc;
940
941         spin_lock_init(&htc->tx_lock);
942
943         htc->stopped = false;
944         ath10k_htc_reset_endpoint_states(htc);
945
946         /* setup HIF layer callbacks */
947         htc_callbacks.rx_completion = ath10k_htc_rx_completion_handler;
948         htc_callbacks.tx_completion = ath10k_htc_tx_completion_handler;
949         htc->ar = ar;
950
951         /* Get HIF default pipe for HTC message exchange */
952         ep = &htc->endpoint[ATH10K_HTC_EP_0];
953
954         ath10k_hif_set_callbacks(ar, &htc_callbacks);
955         ath10k_hif_get_default_pipe(ar, &ep->ul_pipe_id, &ep->dl_pipe_id);
956
957         init_completion(&htc->ctl_resp);
958
959         return 0;
960 }