bus: mhi: ep: Add mhi_ep_queue_buf() API for raw buffer queuing

Some MHI endpoint clients do not use socket buffers and need a way to queue
raw buffers for DL transfers. Add mhi_ep_queue_buf() to support this use
case.

Refactor mhi_ep_queue_skb() to delegate to a new internal mhi_ep_queue()
helper shared by both APIs, and rename mhi_ep_skb_completion() to
mhi_ep_buf_completion() to reflect its broader use.

Signed-off-by: Sumit Kumar <sumit.kumar@oss.qualcomm.com>
Link: https://patch.msgid.link/20261005-lb-v7-2-36a268b6386f@oss.qualcomm.com
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
This commit is contained in:
Sumit Kumar 2026-10-05 16:09:30 +05:30 committed by Manivannan Sadhasivam
parent dd93cef28d
commit f9ff616f57
2 changed files with 36 additions and 8 deletions

View File

@ -504,7 +504,7 @@ static int mhi_ep_process_ch_ring(struct mhi_ep_ring *ring)
return 0;
}
static void mhi_ep_skb_completion(struct mhi_ep_buf_info *buf_info)
static void mhi_ep_buf_completion(struct mhi_ep_buf_info *buf_info)
{
struct mhi_ep_device *mhi_dev = buf_info->mhi_dev;
struct mhi_ep_cntrl *mhi_cntrl = mhi_dev->mhi_cntrl;
@ -534,20 +534,21 @@ static void mhi_ep_skb_completion(struct mhi_ep_buf_info *buf_info)
}
/* TODO: Handle partially formed TDs */
int mhi_ep_queue_skb(struct mhi_ep_device *mhi_dev, struct sk_buff *skb)
static int mhi_ep_queue(struct mhi_ep_device *mhi_dev, void *buf, size_t len,
void *cb_buf)
{
struct mhi_ep_cntrl *mhi_cntrl = mhi_dev->mhi_cntrl;
struct mhi_ep_chan *mhi_chan = mhi_dev->dl_chan;
struct device *dev = &mhi_chan->mhi_dev->dev;
struct mhi_ep_buf_info buf_info = {};
struct mhi_ring_element *el;
u32 buf_left, read_offset;
size_t buf_left, read_offset;
struct mhi_ep_ring *ring;
size_t tr_len;
u32 tre_len;
int ret;
buf_left = skb->len;
buf_left = len;
ring = &mhi_cntrl->mhi_chan[mhi_chan->chan].ring;
mutex_lock(&mhi_chan->lock);
@ -570,13 +571,13 @@ int mhi_ep_queue_skb(struct mhi_ep_device *mhi_dev, struct sk_buff *skb)
tre_len = MHI_TRE_DATA_GET_LEN(el);
tr_len = min(buf_left, tre_len);
read_offset = skb->len - buf_left;
read_offset = len - buf_left;
buf_info.dev_addr = skb->data + read_offset;
buf_info.dev_addr = buf + read_offset;
buf_info.host_addr = MHI_TRE_DATA_GET_PTR(el);
buf_info.size = tr_len;
buf_info.cb = mhi_ep_skb_completion;
buf_info.cb_buf = skb;
buf_info.cb = mhi_ep_buf_completion;
buf_info.cb_buf = cb_buf;
buf_info.mhi_dev = mhi_dev;
/*
@ -615,8 +616,19 @@ int mhi_ep_queue_skb(struct mhi_ep_device *mhi_dev, struct sk_buff *skb)
return ret;
}
int mhi_ep_queue_skb(struct mhi_ep_device *mhi_dev, struct sk_buff *skb)
{
return mhi_ep_queue(mhi_dev, skb->data, skb->len, skb);
}
EXPORT_SYMBOL_GPL(mhi_ep_queue_skb);
int mhi_ep_queue_buf(struct mhi_ep_device *mhi_dev, void *buf, size_t len)
{
return mhi_ep_queue(mhi_dev, buf, len, buf);
}
EXPORT_SYMBOL_GPL(mhi_ep_queue_buf);
static int mhi_ep_cache_host_cfg(struct mhi_ep_cntrl *mhi_cntrl)
{
size_t cmd_ctx_host_size, ch_ctx_host_size, ev_ctx_host_size;

View File

@ -304,4 +304,20 @@ bool mhi_ep_queue_is_empty(struct mhi_ep_device *mhi_dev, enum dma_data_directio
*/
int mhi_ep_queue_skb(struct mhi_ep_device *mhi_dev, struct sk_buff *skb);
/**
* mhi_ep_queue_buf - Transfer buffer contents to host over MHI Endpoint
* @mhi_dev: Device associated with the DL channel
* @buf: Buffer to be queued. On success, ownership passes to the MHI stack;
* the caller must not free @buf until the DL transfer callback fires
* with result->buf_addr equal to @buf. On failure, the caller retains
* ownership and must free @buf.
* Note: if @len spans multiple host DL TREs, the DL transfer callback
* fires once per TRE, each time with result->buf_addr equal to @buf.
* @len: Size of the buffer
*
* Return: 0 if the buffer contents have been transferred successfully, a
* negative error code otherwise.
*/
int mhi_ep_queue_buf(struct mhi_ep_device *mhi_dev, void *buf, size_t len);
#endif