cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

htc.c (33949B)


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