Linux Audio

Check our new training course

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