net/qrtr/mhi.c

Source file repositories/reference/linux-study-clean/net/qrtr/mhi.c

File Facts

System
Linux kernel
Corpus path
net/qrtr/mhi.c
Extension
.c
Size
5458 bytes
Lines
231
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: implementation source
Status
source implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

struct qrtr_mhi_dev {
	struct qrtr_endpoint ep;
	struct mhi_device *mhi_dev;
	struct device *dev;
};

/* From MHI to QRTR */
static void qcom_mhi_qrtr_dl_callback(struct mhi_device *mhi_dev,
				      struct mhi_result *mhi_res)
{
	struct qrtr_mhi_dev *qdev = dev_get_drvdata(&mhi_dev->dev);
	int rc;

	if (!qdev || (mhi_res->transaction_status && mhi_res->transaction_status != -ENOTCONN))
		return;

	/* Channel got reset. So just free the buffer */
	if (mhi_res->transaction_status == -ENOTCONN) {
		devm_kfree(&mhi_dev->dev, mhi_res->buf_addr);
		return;
	}

	rc = qrtr_endpoint_post(&qdev->ep, mhi_res->buf_addr,
				mhi_res->bytes_xferd);
	if (rc == -EINVAL)
		dev_err(qdev->dev, "invalid ipcrouter packet\n");

	/* Done with the buffer, now recycle it for future use */
	rc = mhi_queue_buf(mhi_dev, DMA_FROM_DEVICE, mhi_res->buf_addr,
			   mhi_dev->mhi_cntrl->buffer_len, MHI_EOT);
	if (rc)
		dev_err(&mhi_dev->dev, "Failed to recycle the buffer: %d\n", rc);
}

/* From QRTR to MHI */
static void qcom_mhi_qrtr_ul_callback(struct mhi_device *mhi_dev,
				      struct mhi_result *mhi_res)
{
	struct sk_buff *skb = mhi_res->buf_addr;

	if (skb->sk)
		sock_put(skb->sk);
	consume_skb(skb);
}

/* Send data over MHI */
static int qcom_mhi_qrtr_send(struct qrtr_endpoint *ep, struct sk_buff *skb)
{
	struct qrtr_mhi_dev *qdev = container_of(ep, struct qrtr_mhi_dev, ep);
	int rc;

	if (skb->sk)
		sock_hold(skb->sk);

	rc = skb_linearize(skb);
	if (rc)
		goto free_skb;

	rc = mhi_queue_skb(qdev->mhi_dev, DMA_TO_DEVICE, skb, skb->len,
			   MHI_EOT);
	if (rc)
		goto free_skb;

	return rc;

free_skb:
	if (skb->sk)
		sock_put(skb->sk);
	kfree_skb(skb);

	return rc;
}

static int qcom_mhi_qrtr_queue_dl_buffers(struct mhi_device *mhi_dev)
{
	u32 free_desc;
	void *buf;
	int ret;

	free_desc = mhi_get_free_desc_count(mhi_dev, DMA_FROM_DEVICE);
	while (free_desc--) {
		buf = devm_kmalloc(&mhi_dev->dev, mhi_dev->mhi_cntrl->buffer_len, GFP_KERNEL);
		if (!buf)
			return -ENOMEM;

		ret = mhi_queue_buf(mhi_dev, DMA_FROM_DEVICE, buf, mhi_dev->mhi_cntrl->buffer_len,
				    MHI_EOT);
		if (ret) {
			dev_err(&mhi_dev->dev, "Failed to queue buffer: %d\n", ret);
			return ret;

Annotation

Implementation Notes