drivers/net/wireless/ath/ath11k/htc.c

Source file repositories/reference/linux-study-clean/drivers/net/wireless/ath/ath11k/htc.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/ath/ath11k/htc.c
Extension
.c
Size
22238 bytes
Lines
846
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (ep->tx_credits < credits) {
			ath11k_dbg(ab, ATH11K_DBG_HTC,
				   "ep %d insufficient credits required %d total %d\n",
				   eid, credits, ep->tx_credits);
			spin_unlock_bh(&htc->tx_lock);
			ret = -EAGAIN;
			goto err_pull;
		}
		ep->tx_credits -= credits;
		ath11k_dbg(ab, ATH11K_DBG_HTC,
			   "ep %d credits consumed %d total %d\n",
			   eid, credits, ep->tx_credits);
		spin_unlock_bh(&htc->tx_lock);
	}

	ath11k_htc_prepare_tx_skb(ep, skb);

	skb_cb->eid = eid;
	skb_cb->paddr = dma_map_single(dev, skb->data, skb->len, DMA_TO_DEVICE);
	ret = dma_mapping_error(dev, skb_cb->paddr);
	if (ret) {
		ret = -EIO;
		goto err_credits;
	}

	ath11k_dbg(ab, ATH11K_DBG_HTC, "tx skb %p eid %d paddr %pad\n",
		   skb, skb_cb->eid, &skb_cb->paddr);

	ret = ath11k_ce_send(htc->ab, skb, ep->ul_pipe_id, ep->eid);
	if (ret)
		goto err_unmap;

	return 0;

err_unmap:
	dma_unmap_single(dev, skb_cb->paddr, skb->len, DMA_TO_DEVICE);
err_credits:
	if (credit_flow_enabled) {
		spin_lock_bh(&htc->tx_lock);
		ep->tx_credits += credits;
		ath11k_dbg(ab, ATH11K_DBG_HTC,
			   "ep %d credits reverted %d total %d\n",
			   eid, credits, ep->tx_credits);
		spin_unlock_bh(&htc->tx_lock);

		if (ep->ep_ops.ep_tx_credits)
			ep->ep_ops.ep_tx_credits(htc->ab);
	}
err_pull:
	skb_pull(skb, sizeof(struct ath11k_htc_hdr));
	return ret;
}

static void
ath11k_htc_process_credit_report(struct ath11k_htc *htc,
				 const struct ath11k_htc_credit_report *report,
				 int len,
				 enum ath11k_htc_ep_id eid)
{
	struct ath11k_base *ab = htc->ab;
	struct ath11k_htc_ep *ep;
	int i, n_reports;

	if (len % sizeof(*report))
		ath11k_warn(ab, "Uneven credit report len %d", len);

	n_reports = len / sizeof(*report);

	spin_lock_bh(&htc->tx_lock);
	for (i = 0; i < n_reports; i++, report++) {
		if (report->eid >= ATH11K_HTC_EP_COUNT)
			break;

		ep = &htc->endpoint[report->eid];
		ep->tx_credits += report->credits;

		ath11k_dbg(ab, ATH11K_DBG_HTC, "ep %d credits got %d total %d\n",
			   report->eid, report->credits, ep->tx_credits);

		if (ep->ep_ops.ep_tx_credits) {
			spin_unlock_bh(&htc->tx_lock);
			ep->ep_ops.ep_tx_credits(htc->ab);
			spin_lock_bh(&htc->tx_lock);
		}
	}
	spin_unlock_bh(&htc->tx_lock);
}

static int ath11k_htc_process_trailer(struct ath11k_htc *htc,
				      u8 *buffer,

Annotation

Implementation Notes