mhi: uci: Enable virtual MHI queueing
Enable the queueing of virtual buffers to MHI instead of buffers obtained from streaming DMA. Change-Id: I8ba25c1f28cbd1cb302aec184864ed2e25672d4a Signed-off-by: Andrei Danaila <adanaila@codeaurora.org>
This commit is contained in:
parent
c2bcc4280d
commit
74c1e7710f
1 changed files with 23 additions and 67 deletions
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -24,7 +24,6 @@
|
|||
#include <linux/tty.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/ipc_logging.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
#define MHI_DEV_NODE_NAME_LEN 13
|
||||
|
@ -115,7 +114,7 @@ struct uci_client {
|
|||
int mhi_status;
|
||||
void *pkt_loc;
|
||||
size_t pkt_size;
|
||||
dma_addr_t *in_buf_list;
|
||||
void **in_buf_list;
|
||||
atomic_t out_pkt_pend_ack;
|
||||
atomic_t mhi_disabled;
|
||||
struct mhi_uci_ctxt_t *uci_ctxt;
|
||||
|
@ -256,7 +255,6 @@ static enum MHI_STATUS mhi_init_inbound(struct uci_client *client_handle,
|
|||
{
|
||||
enum MHI_STATUS ret_val = MHI_STATUS_SUCCESS;
|
||||
u32 i = 0;
|
||||
dma_addr_t dma_addr = 0;
|
||||
struct chan_attr *chan_attributes =
|
||||
&uci_ctxt.chan_attrib[chan];
|
||||
void *data_loc = NULL;
|
||||
|
@ -269,7 +267,7 @@ static enum MHI_STATUS mhi_init_inbound(struct uci_client *client_handle,
|
|||
chan_attributes->nr_trbs =
|
||||
mhi_get_free_desc(client_handle->in_handle);
|
||||
client_handle->in_buf_list =
|
||||
kmalloc(sizeof(dma_addr_t) * chan_attributes->nr_trbs,
|
||||
kmalloc(sizeof(void *) * chan_attributes->nr_trbs,
|
||||
GFP_KERNEL);
|
||||
if (!client_handle->in_buf_list)
|
||||
return MHI_STATUS_ERROR;
|
||||
|
@ -282,18 +280,10 @@ static enum MHI_STATUS mhi_init_inbound(struct uci_client *client_handle,
|
|||
data_loc, buf_size);
|
||||
if (data_loc == NULL)
|
||||
return -ENOMEM;
|
||||
dma_addr = dma_map_single(NULL, data_loc,
|
||||
buf_size, DMA_FROM_DEVICE);
|
||||
if (dma_mapping_error(NULL, dma_addr)) {
|
||||
uci_log(UCI_DBG_ERROR, "Failed to Map DMA\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
client_handle->in_buf_list[i] = dma_addr;
|
||||
client_handle->in_buf_list[i] = data_loc;
|
||||
ret_val = mhi_queue_xfer(client_handle->in_handle,
|
||||
dma_addr, buf_size, MHI_EOT);
|
||||
data_loc, buf_size, MHI_EOT);
|
||||
if (MHI_STATUS_SUCCESS != ret_val) {
|
||||
dma_unmap_single(NULL, dma_addr,
|
||||
buf_size, DMA_FROM_DEVICE);
|
||||
kfree(data_loc);
|
||||
uci_log(UCI_DBG_ERROR,
|
||||
"Failed insertion for chan %d, ret %d\n",
|
||||
|
@ -314,7 +304,6 @@ static int mhi_uci_send_packet(struct mhi_client_handle **client_handle,
|
|||
int data_left_to_insert = 0;
|
||||
size_t data_to_insert_now = 0;
|
||||
u32 data_inserted_so_far = 0;
|
||||
dma_addr_t dma_addr = 0;
|
||||
int ret_val = 0;
|
||||
enum MHI_FLAGS flags;
|
||||
struct uci_client *uci_handle;
|
||||
|
@ -353,27 +342,19 @@ static int mhi_uci_send_packet(struct mhi_client_handle **client_handle,
|
|||
data_loc = buf;
|
||||
}
|
||||
|
||||
dma_addr = dma_map_single(NULL, data_loc,
|
||||
data_to_insert_now, DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(NULL, dma_addr)) {
|
||||
uci_log(UCI_DBG_ERROR,
|
||||
"Failed to Map DMA 0x%x\n", size);
|
||||
data_inserted_so_far = -ENOMEM;
|
||||
goto error_memcpy;
|
||||
}
|
||||
|
||||
flags = MHI_EOT;
|
||||
if (data_left_to_insert - data_to_insert_now > 0)
|
||||
flags |= MHI_CHAIN | MHI_EOB;
|
||||
uci_log(UCI_DBG_VERBOSE,
|
||||
"At trb i = %d/%d, chain = %d, eob = %d, addr 0x%lx chan %d\n",
|
||||
"At trb i = %d/%d, chain = %d, eob = %d, addr 0x%p chan %d\n",
|
||||
i, nr_avail_trbs,
|
||||
flags & MHI_CHAIN,
|
||||
flags & MHI_EOB,
|
||||
(uintptr_t)dma_addr,
|
||||
data_loc,
|
||||
uci_handle->out_chan);
|
||||
ret_val = mhi_queue_xfer(*client_handle, dma_addr,
|
||||
ret_val = mhi_queue_xfer(*client_handle, data_loc,
|
||||
data_to_insert_now, flags);
|
||||
|
||||
if (0 != ret_val) {
|
||||
goto error_queue;
|
||||
} else {
|
||||
|
@ -387,10 +368,6 @@ static int mhi_uci_send_packet(struct mhi_client_handle **client_handle,
|
|||
return data_inserted_so_far;
|
||||
|
||||
error_queue:
|
||||
dma_unmap_single(NULL,
|
||||
(dma_addr_t)dma_addr,
|
||||
data_to_insert_now,
|
||||
DMA_TO_DEVICE);
|
||||
error_memcpy:
|
||||
kfree(data_loc);
|
||||
return data_inserted_so_far;
|
||||
|
@ -676,10 +653,6 @@ static int mhi_uci_client_release(struct inode *mhi_inode,
|
|||
uci_handle->in_chan_state = 0;
|
||||
atomic_set(&uci_handle->out_pkt_pend_ack, 0);
|
||||
for (i = 0; i < nr_in_bufs; ++i) {
|
||||
dma_unmap_single(NULL,
|
||||
uci_handle->in_buf_list[i],
|
||||
buf_size,
|
||||
DMA_FROM_DEVICE);
|
||||
kfree((void *)uci_handle->in_buf_list[i]);
|
||||
}
|
||||
kfree(uci_handle->in_buf_list);
|
||||
|
@ -697,7 +670,6 @@ static ssize_t mhi_uci_client_read(struct file *file, char __user *buf,
|
|||
size_t uspace_buf_size, loff_t *bytes_pending)
|
||||
{
|
||||
struct uci_client *uci_handle = NULL;
|
||||
uintptr_t phy_buf = 0;
|
||||
struct mhi_client_handle *client_handle = NULL;
|
||||
int ret_val = 0;
|
||||
size_t buf_size = 0;
|
||||
|
@ -728,19 +700,16 @@ static ssize_t mhi_uci_client_read(struct file *file, char __user *buf,
|
|||
"Failed to poll inbound ret %d avail pkt %d\n",
|
||||
ret_val, atomic_read(&uci_handle->avail_pkts));
|
||||
}
|
||||
phy_buf = result.payload_buf;
|
||||
if (phy_buf != 0)
|
||||
uci_handle->pkt_loc = (void *)phy_buf;
|
||||
if (result.buf_addr)
|
||||
uci_handle->pkt_loc = result.buf_addr;
|
||||
else
|
||||
uci_handle->pkt_loc = 0;
|
||||
uci_handle->pkt_size = result.bytes_xferd;
|
||||
*bytes_pending = uci_handle->pkt_size;
|
||||
uci_log(UCI_DBG_VERBOSE,
|
||||
"Got pkt of size 0x%zx at addr 0x%lx, chan %d\n",
|
||||
uci_handle->pkt_size, (uintptr_t)phy_buf, chan);
|
||||
dma_unmap_single(NULL, (dma_addr_t)phy_buf,
|
||||
buf_size,
|
||||
DMA_FROM_DEVICE);
|
||||
"Got pkt size 0x%zx at addr 0x%lx, chan %d\n",
|
||||
uci_handle->pkt_size,
|
||||
(uintptr_t)result.buf_addr, chan);
|
||||
}
|
||||
if ((*bytes_pending == 0 || uci_handle->pkt_loc == 0) &&
|
||||
(atomic_read(&uci_handle->avail_pkts) <= 0)) {
|
||||
|
@ -774,9 +743,9 @@ static ssize_t mhi_uci_client_read(struct file *file, char __user *buf,
|
|||
uci_handle->pkt_size != 0 &&
|
||||
uci_handle->pkt_loc != 0) {
|
||||
uci_log(UCI_DBG_VERBOSE,
|
||||
"Got packet: avail pkts %d phy_adr 0x%lx, chan %d\n",
|
||||
"Got packet: avail pkts %d phy_adr 0x%p, chan %d\n",
|
||||
atomic_read(&uci_handle->avail_pkts),
|
||||
phy_buf,
|
||||
result.buf_addr,
|
||||
chan);
|
||||
break;
|
||||
/*
|
||||
|
@ -785,10 +754,10 @@ static ssize_t mhi_uci_client_read(struct file *file, char __user *buf,
|
|||
*/
|
||||
} else {
|
||||
uci_log(UCI_DBG_CRITICAL,
|
||||
"chan %d err: avail pkts %d phy_adr 0x%lx mhi_stat%d\n",
|
||||
"chan %d err: avail pkts %d phy_adr 0x%p mhi_stat%d\n",
|
||||
chan,
|
||||
atomic_read(&uci_handle->avail_pkts),
|
||||
phy_buf,
|
||||
result.buf_addr,
|
||||
uci_handle->mhi_status);
|
||||
return -EIO;
|
||||
}
|
||||
|
@ -830,16 +799,12 @@ static ssize_t mhi_uci_client_read(struct file *file, char __user *buf,
|
|||
uci_log(UCI_DBG_VERBOSE, "Pkt loc %p ,chan %d\n",
|
||||
uci_handle->pkt_loc, chan);
|
||||
memset(uci_handle->pkt_loc, 0, buf_size);
|
||||
phy_buf = dma_map_single(NULL, uci_handle->pkt_loc,
|
||||
buf_size, DMA_FROM_DEVICE);
|
||||
atomic_dec(&uci_handle->avail_pkts);
|
||||
uci_log(UCI_DBG_VERBOSE,
|
||||
"Decremented avail pkts avail 0x%x\n",
|
||||
atomic_read(&uci_handle->avail_pkts));
|
||||
|
||||
ret_val = mhi_queue_xfer(client_handle, phy_buf,
|
||||
ret_val = mhi_queue_xfer(client_handle, uci_handle->pkt_loc,
|
||||
buf_size, MHI_EOT);
|
||||
|
||||
if (MHI_STATUS_SUCCESS != ret_val) {
|
||||
uci_log(UCI_DBG_ERROR,
|
||||
"Failed to recycle element\n");
|
||||
|
@ -987,13 +952,11 @@ static void process_rs232_state(struct mhi_result *result)
|
|||
}
|
||||
if (result->bytes_xferd != sizeof(struct rs232_ctrl_msg)) {
|
||||
uci_log(UCI_DBG_ERROR,
|
||||
"Buffer is of wrong size is: 0x%x: expected 0x%zx\n",
|
||||
"Buffer is of wrong size is: 0x%zx: expected 0x%zx\n",
|
||||
result->bytes_xferd, sizeof(struct rs232_ctrl_msg));
|
||||
goto error_size;
|
||||
}
|
||||
dma_unmap_single(NULL, result->payload_buf,
|
||||
result->bytes_xferd, DMA_FROM_DEVICE);
|
||||
rs232_pkt = (void *)result->payload_buf;
|
||||
rs232_pkt = result->buf_addr;
|
||||
MHI_GET_CTRL_DEST_ID(CTRL_DEST_ID, rs232_pkt, chan);
|
||||
client = &uci_ctxt.client_handles[chan / 2];
|
||||
|
||||
|
@ -1014,11 +977,8 @@ static void process_rs232_state(struct mhi_result *result)
|
|||
error_bad_xfer:
|
||||
error_size:
|
||||
memset(rs232_pkt, 0, sizeof(struct rs232_ctrl_msg));
|
||||
dma_map_single(NULL, rs232_pkt,
|
||||
sizeof(struct rs232_ctrl_msg),
|
||||
DMA_FROM_DEVICE);
|
||||
ret_val = mhi_queue_xfer(client->in_handle,
|
||||
result->payload_buf,
|
||||
result->buf_addr,
|
||||
result->bytes_xferd,
|
||||
result->flags);
|
||||
if (MHI_STATUS_SUCCESS != ret_val) {
|
||||
|
@ -1044,11 +1004,7 @@ static void parse_inbound_ack(struct uci_client *uci_handle,
|
|||
static void parse_outbound_ack(struct uci_client *uci_handle,
|
||||
struct mhi_result *result)
|
||||
{
|
||||
dma_unmap_single(NULL,
|
||||
result->payload_buf,
|
||||
result->bytes_xferd,
|
||||
DMA_TO_DEVICE);
|
||||
kfree((void *) result->payload_buf);
|
||||
kfree(result->buf_addr);
|
||||
uci_log(UCI_DBG_VERBOSE,
|
||||
"Received ack on chan %d, pending acks: 0x%x\n",
|
||||
uci_handle->out_chan,
|
||||
|
|
Loading…
Add table
Reference in a new issue