summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorTony Truong <truong@codeaurora.org>2015-08-20 18:00:30 -0700
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 21:24:45 -0700
commitd3d1144ee507880a2325f13615dc32a2f599a202 (patch)
tree749bf9cabcfc5771f01141a01f6f2cfc5ae00cc0 /drivers
parent6ad91fea76ea37f267701ceb6ad0b0b2100f8220 (diff)
mhi: core: Enable correct channel alignment
Enable correct allignment of MHI channels to the ring size rounded up to the next power of two as per device requirement. Change-Id: Ic77c43fdbcde2ec3b6f08e3062eaf778eb13ec5b Signed-off-by: Andrei Danaila <adanaila@codeaurora.org> Signed-off-by: Tony Truong <truong@codeaurora.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/platform/msm/mhi/mhi_init.c80
-rw-r--r--drivers/platform/msm/mhi/mhi_main.c98
-rw-r--r--drivers/platform/msm/mhi/mhi_states.c3
3 files changed, 100 insertions, 81 deletions
diff --git a/drivers/platform/msm/mhi/mhi_init.c b/drivers/platform/msm/mhi/mhi_init.c
index e6a90be6b760..b70972f19fdf 100644
--- a/drivers/platform/msm/mhi/mhi_init.c
+++ b/drivers/platform/msm/mhi/mhi_init.c
@@ -71,9 +71,8 @@ ev_mutex_free:
size_t calculate_mhi_space(struct mhi_device_ctxt *mhi_dev_ctxt)
{
- int i, r;
+ int i = 0;
size_t mhi_dev_mem = 0;
- struct mhi_chan_info chan_info;
/* Calculate size needed for contexts */
mhi_dev_mem += (MHI_MAX_CHANNELS * sizeof(struct mhi_chan_ctxt)) +
@@ -90,23 +89,6 @@ size_t calculate_mhi_space(struct mhi_device_ctxt *mhi_dev_ctxt)
mhi_dev_mem += (sizeof(union mhi_event_pkt) *
mhi_dev_ctxt->ev_ring_props[i].nr_desc);
- /* Calculate size needed for xfer TREs and bounce buffers */
- for (i = 0; i < MHI_MAX_CHANNELS; ++i)
- if (VALID_CHAN_NR(i)) {
- r = get_chan_props(mhi_dev_ctxt, i, &chan_info);
- if (r)
- continue;
- /* Add size of TREs */
- mhi_dev_mem += (sizeof(union mhi_xfer_pkt) *
- chan_info.max_desc);
- /* Add bounce buffer size */
- if (mhi_dev_ctxt->flags.bb_enabled) {
- mhi_log(MHI_MSG_INFO,
- "Enabling BB list, chan %d\n", i);
- /*mhi_dev_mem += (MAX_BOUNCE_BUF_SIZE *
- chan_info.max_desc); */
- }
- }
mhi_log(MHI_MSG_INFO, "Final bytes for MHI device space %zd\n",
mhi_dev_mem);
return mhi_dev_mem;
@@ -201,20 +183,6 @@ static int mhi_cmd_ring_init(struct mhi_cmd_ctxt *cmd_ctxt,
return 0;
}
-
-static int enable_bb_ctxt(struct mhi_ring *bb_ctxt, int nr_el)
-{
- bb_ctxt->el_size = sizeof(struct mhi_buf_info);
- bb_ctxt->len = bb_ctxt->el_size * nr_el;
- bb_ctxt->base = kzalloc(bb_ctxt->len, GFP_KERNEL);
- bb_ctxt->wp = bb_ctxt->base;
- bb_ctxt->rp = bb_ctxt->base;
- bb_ctxt->ack_rp = bb_ctxt->base;
- if (!bb_ctxt->base)
- return -ENOMEM;
- return 0;
-}
-
/*
* The device can have severe addressing limitations, and in this case
* the MHI driver may be restricted on where memory can be allocated.
@@ -311,7 +279,7 @@ int init_mhi_dev_mem(struct mhi_device_ctxt *mhi_dev_ctxt)
calculate_mhi_space(mhi_dev_ctxt);
mhi_dev_ctxt->dev_space.dev_mem_start =
- dma_alloc_coherent(&mhi_dev_ctxt->dev_info->plat_dev->dev,
+ dma_alloc_coherent(&mhi_dev_ctxt->dev_info->pcie_device->dev,
mhi_dev_ctxt->dev_space.dev_mem_len,
&mhi_dev_ctxt->dev_space.dma_dev_mem_start,
GFP_KERNEL);
@@ -392,49 +360,9 @@ int init_mhi_dev_mem(struct mhi_device_ctxt *mhi_dev_ctxt)
(u64)dma_dev_mem_start + mhi_mem_index);
mhi_mem_index += ring_len;
}
-
- /* Initialize both the local and device xfer contexts */
- for (i = 0; i < MHI_MAX_CHANNELS; ++i)
- if (VALID_CHAN_NR(i)) {
- struct mhi_chan_info chan_info;
-
- r = get_chan_props(mhi_dev_ctxt, i, &chan_info);
- if (r)
- continue;
- mhi_log(MHI_MSG_INFO, "Initializing chan ctxt %d\n", i);
- ring_len = (sizeof(union mhi_xfer_pkt) *
- chan_info.max_desc);
- init_dev_chan_ctxt(
- &mhi_dev_ctxt->dev_space.ring_ctxt.cc_list[i],
- dma_dev_mem_start + mhi_mem_index,
- ring_len, chan_info.ev_ring);
- /* TODO: May not need to do this. It would be best for
- * the client to set it during chan open */
- mhi_dev_ctxt->dev_space.ring_ctxt.cc_list[i].
- mhi_chan_type = (i % 2) + 1;
- init_local_chan_ctxt(
- &mhi_dev_ctxt->mhi_local_chan_ctxt[i],
- dev_mem_start + mhi_mem_index,
- ring_len);
- /* TODO: May not need to do this. It would be best for
- * the client to set it during chan open */
- mhi_dev_ctxt->mhi_local_chan_ctxt[i].dir = (i % 2) + 1;
- /* Add size of TREs */
- mhi_mem_index += ring_len;
- if (mhi_dev_ctxt->flags.bb_enabled) {
- r = enable_bb_ctxt(
- &mhi_dev_ctxt->chan_bb_list[i],
- chan_info.max_desc);
- if (r)
- goto error_during_bb_list;
- }
- }
return 0;
-error_during_bb_list:
- for (; i >= 0; --i)
- kfree(mhi_dev_ctxt->chan_bb_list[i].base);
- dma_free_coherent(&mhi_dev_ctxt->dev_info->plat_dev->dev,
+ dma_free_coherent(&mhi_dev_ctxt->dev_info->pcie_device->dev,
mhi_dev_ctxt->dev_space.dev_mem_len,
mhi_dev_ctxt->dev_space.dev_mem_start,
mhi_dev_ctxt->dev_space.dma_dev_mem_start);
@@ -629,7 +557,7 @@ error_during_thread_init:
kfree(mhi_dev_ctxt->mhi_ev_wq.m3_event);
kfree(mhi_dev_ctxt->mhi_ev_wq.bhi_event);
error_wq_init:
- dma_free_coherent(&mhi_dev_ctxt->dev_info->plat_dev->dev,
+ dma_free_coherent(&mhi_dev_ctxt->dev_info->pcie_device->dev,
mhi_dev_ctxt->dev_space.dev_mem_len,
mhi_dev_ctxt->dev_space.dev_mem_start,
mhi_dev_ctxt->dev_space.dma_dev_mem_start);
diff --git a/drivers/platform/msm/mhi/mhi_main.c b/drivers/platform/msm/mhi/mhi_main.c
index 2a5e92380b25..4ea80fcf4d0e 100644
--- a/drivers/platform/msm/mhi/mhi_main.c
+++ b/drivers/platform/msm/mhi/mhi_main.c
@@ -29,6 +29,19 @@
#include "mhi_macros.h"
#include "mhi_trace.h"
+static int enable_bb_ctxt(struct mhi_ring *bb_ctxt, int nr_el)
+{
+ bb_ctxt->el_size = sizeof(struct mhi_buf_info);
+ bb_ctxt->len = bb_ctxt->el_size * nr_el;
+ bb_ctxt->base = kzalloc(bb_ctxt->len, GFP_KERNEL);
+ bb_ctxt->wp = bb_ctxt->base;
+ bb_ctxt->rp = bb_ctxt->base;
+ bb_ctxt->ack_rp = bb_ctxt->base;
+ if (!bb_ctxt->base)
+ return -ENOMEM;
+ return 0;
+}
+
static void mhi_write_db(struct mhi_device_ctxt *mhi_dev_ctxt,
void __iomem *io_addr_lower,
uintptr_t chan, u64 val)
@@ -188,6 +201,69 @@ int get_chan_props(struct mhi_device_ctxt *mhi_dev_ctxt, int chan,
return r;
}
+int mhi_release_chan_ctxt(struct mhi_device_ctxt *mhi_dev_ctxt,
+ struct mhi_chan_ctxt *cc_list,
+ struct mhi_ring *ring)
+{
+ if (cc_list == NULL || ring == NULL)
+ return -EINVAL;
+
+ dma_free_coherent(&mhi_dev_ctxt->dev_info->pcie_device->dev,
+ ring->len, ring->base,
+ cc_list->mhi_trb_ring_base_addr);
+ mhi_init_chan_ctxt(cc_list, 0, 0, 0, 0, 0, ring,
+ MHI_CHAN_STATE_DISABLED);
+ return 0;
+}
+
+void free_tre_ring(struct mhi_client_handle *client_handle)
+{
+ struct mhi_chan_ctxt *chan_ctxt;
+ struct mhi_device_ctxt *mhi_dev_ctxt = client_handle->mhi_dev_ctxt;
+ int chan = client_handle->chan_info.chan_nr;
+ int r;
+
+ chan_ctxt = &mhi_dev_ctxt->dev_space.ring_ctxt.cc_list[chan];
+ r = mhi_release_chan_ctxt(mhi_dev_ctxt, chan_ctxt,
+ &mhi_dev_ctxt->mhi_local_chan_ctxt[chan]);
+ if (r)
+ mhi_log(MHI_MSG_ERROR,
+ "Failed to release chan %d ret %d\n", chan, r);
+}
+
+static int populate_tre_ring(struct mhi_client_handle *client_handle)
+{
+ dma_addr_t ring_dma_addr;
+ void *ring_local_addr;
+ struct mhi_chan_ctxt *chan_ctxt;
+ struct mhi_device_ctxt *mhi_dev_ctxt = client_handle->mhi_dev_ctxt;
+ u32 chan = client_handle->chan_info.chan_nr;
+ u32 nr_desc = client_handle->chan_info.max_desc;
+
+ mhi_log(MHI_MSG_INFO,
+ "Entered chan %d requested desc %d\n", chan, nr_desc);
+
+ chan_ctxt = &mhi_dev_ctxt->dev_space.ring_ctxt.cc_list[chan];
+ ring_local_addr = dma_alloc_coherent(
+ &mhi_dev_ctxt->dev_info->pcie_device->dev,
+ nr_desc * sizeof(union mhi_xfer_pkt),
+ &ring_dma_addr, GFP_KERNEL);
+
+ if (ring_local_addr == NULL)
+ return -ENOMEM;
+
+ mhi_init_chan_ctxt(chan_ctxt, ring_dma_addr,
+ (uintptr_t)ring_local_addr,
+ nr_desc,
+ GET_CHAN_PROPS(CHAN_DIR,
+ client_handle->chan_info.flags),
+ client_handle->chan_info.ev_ring,
+ &mhi_dev_ctxt->mhi_local_chan_ctxt[chan],
+ MHI_CHAN_STATE_ENABLED);
+ mhi_log(MHI_MSG_INFO, "Exited\n");
+ return 0;
+}
+
enum MHI_STATUS mhi_open_channel(struct mhi_client_handle *client_handle)
{
enum MHI_STATUS ret_val = MHI_STATUS_SUCCESS;
@@ -217,10 +293,24 @@ enum MHI_STATUS mhi_open_channel(struct mhi_client_handle *client_handle)
chan, mhi_dev_ctxt->dev_exec_env);
return MHI_STATUS_DEVICE_NOT_READY;
}
-
client_handle->event_ring_index =
mhi_dev_ctxt->dev_space.ring_ctxt.
cc_list[chan].mhi_event_ring_index;
+ r = enable_bb_ctxt(&mhi_dev_ctxt->chan_bb_list[chan],
+ client_handle->chan_info.max_desc);
+ if (r) {
+ mhi_log(MHI_MSG_ERROR,
+ "Failed to initialize bb ctxt chan %d ret %d\n",
+ chan, r);
+ return r;
+ }
+ r = populate_tre_ring(client_handle);
+ if (r) {
+ mhi_log(MHI_MSG_ERROR,
+ "Failed to initialize tre ring chan %d ret %d\n",
+ chan, r);
+ return r;
+ }
client_handle->msi_vec =
mhi_dev_ctxt->dev_space.ring_ctxt.ec_list[
@@ -480,7 +570,7 @@ static int create_bb(struct mhi_device_ctxt *mhi_dev_ctxt,
bb_info->dir);
mhi_log(MHI_MSG_RAW, "Allocating BB, chan %d\n", chan);
bb_info->bb_v_addr = dma_alloc_coherent(
- &mhi_dev_ctxt->dev_info->plat_dev->dev,
+ &mhi_dev_ctxt->dev_info->pcie_device->dev,
bb_info->buf_len,
&bb_info->bb_p_addr,
GFP_ATOMIC);
@@ -510,7 +600,7 @@ static void free_bounce_buffer(struct mhi_device_ctxt *mhi_dev_ctxt,
bb->bb_p_addr, bb->buf_len, bb->dir);
else
/* This buffer was bounced */
- dma_free_coherent(&mhi_dev_ctxt->dev_info->plat_dev->dev,
+ dma_free_coherent(&mhi_dev_ctxt->dev_info->pcie_device->dev,
bb->buf_len,
bb->bb_v_addr,
bb->bb_p_addr);
@@ -1013,7 +1103,7 @@ enum MHI_STATUS parse_xfer_event(struct mhi_device_ctxt *ctxt,
/* Get the TRB this event points to */
local_ev_trb_loc = (void *)mhi_p2v_addr(mhi_dev_ctxt,
- MHI_RING_TYPE_EVENT_RING, event_id,
+ MHI_RING_TYPE_XFER_RING, chan,
phy_ev_trb_loc);
local_trb_loc = (union mhi_xfer_pkt *)local_chan_ctxt->rp;
diff --git a/drivers/platform/msm/mhi/mhi_states.c b/drivers/platform/msm/mhi/mhi_states.c
index bda1701fa1a1..1f2cc0bf9489 100644
--- a/drivers/platform/msm/mhi/mhi_states.c
+++ b/drivers/platform/msm/mhi/mhi_states.c
@@ -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
@@ -619,6 +619,7 @@ static enum MHI_STATUS process_amss_transition(
}
ring_all_chan_dbs(mhi_dev_ctxt);
}
+ ring_all_ev_dbs(mhi_dev_ctxt);
atomic_dec(&mhi_dev_ctxt->flags.data_pending);
if (!mhi_dev_ctxt->flags.pending_M3 &&
mhi_dev_ctxt->flags.link_up)