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:
Andrei Danaila 2015-07-30 16:44:46 -07:00 committed by David Keitel
parent c2bcc4280d
commit 74c1e7710f

View file

@ -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,