mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-08 04:42:04 -04:00
Merge "msm: mhi: Send Ch cmd ack in async fashion"
This commit is contained in:
commit
64c433fac3
2 changed files with 198 additions and 29 deletions
|
|
@ -87,6 +87,10 @@ static int mhi_dev_alloc_evt_buf_evt_req(struct mhi_dev *mhi,
|
|||
static int mhi_dev_schedule_msi_ipa(struct mhi_dev *mhi,
|
||||
struct event_req *ereq);
|
||||
static void mhi_dev_event_msi_cb(void *req);
|
||||
static void mhi_dev_cmd_event_msi_cb(void *req);
|
||||
|
||||
static int mhi_dev_alloc_cmd_ack_buf_req(struct mhi_dev *mhi);
|
||||
|
||||
|
||||
static struct mhi_dev_uevent_info channel_state_info[MHI_MAX_CHANNELS];
|
||||
static DECLARE_COMPLETION(read_from_host);
|
||||
|
|
@ -262,7 +266,7 @@ static int mhi_dev_schedule_msi_ipa(struct mhi_dev *mhi, struct event_req *ereq)
|
|||
{
|
||||
struct ep_pcie_msi_config cfg;
|
||||
struct mhi_addr msi_addr;
|
||||
struct mhi_dev_channel *ch = ereq->context;
|
||||
struct mhi_dev_channel *ch;
|
||||
uint64_t evnt_ring_idx = mhi->ev_ring_start + ereq->event_ring;
|
||||
struct mhi_dev_ring *ring = &mhi->ring[evnt_ring_idx];
|
||||
union mhi_dev_ring_ctx *ctx;
|
||||
|
|
@ -283,14 +287,23 @@ static int mhi_dev_schedule_msi_ipa(struct mhi_dev *mhi, struct event_req *ereq)
|
|||
msi_addr.phy_addr = ring->msi_buf_dma_handle;
|
||||
|
||||
ereq->event_type = SEND_MSI;
|
||||
ereq->msi_cb = mhi_dev_event_msi_cb;
|
||||
if (!ereq->is_cmd_cpl) {
|
||||
ch = ereq->context;
|
||||
ereq->msi_cb = mhi_dev_event_msi_cb;
|
||||
ch->msi_cnt++;
|
||||
mhi_log(MHI_MSG_VERBOSE,
|
||||
"Sending MSI %d to 0x%llx as data = 0x%x for ch %d msi_count %d, ereq flush_num %d\n",
|
||||
ctx->ev.msivec, msi_addr.host_pa,
|
||||
*ring->msi_buf, ch->ch_id,
|
||||
ch->msi_cnt, ereq->flush_num);
|
||||
} else {
|
||||
ereq->msi_cb = mhi_dev_cmd_event_msi_cb;
|
||||
mhi_log(MHI_MSG_VERBOSE,
|
||||
"Sending MSI %d to 0x%llx as data = 0x%x for cmd ack, ereq flush_num %d\n",
|
||||
ctx->ev.msivec, msi_addr.host_pa, *ring->msi_buf,
|
||||
ereq->flush_num);
|
||||
}
|
||||
|
||||
ch->msi_cnt++;
|
||||
|
||||
mhi_log(MHI_MSG_VERBOSE,
|
||||
"Sending MSI %d to 0x%llx as data = 0x%x for ch %d msi_count %d, ereq flush_num %d\n",
|
||||
ctx->ev.msivec, msi_addr.host_pa, *ring->msi_buf, ch->ch_id,
|
||||
ch->msi_cnt, ereq->flush_num);
|
||||
mhi_ctx->write_to_host(mhi, &msi_addr, ereq, MHI_DEV_DMA_ASYNC);
|
||||
|
||||
return 0;
|
||||
|
|
@ -314,6 +327,27 @@ static void mhi_dev_event_rd_offset_completion_cb(void *req)
|
|||
sizeof(uint64_t), DMA_TO_DEVICE);
|
||||
}
|
||||
|
||||
static void mhi_dev_cmd_event_msi_cb(void *req)
|
||||
{
|
||||
struct mhi_cmd_cmpl_ctx *cmd_ctx;
|
||||
struct mhi_dev *mhi;
|
||||
struct event_req *ereq = req;
|
||||
unsigned long flags;
|
||||
|
||||
mhi_log(MHI_MSG_VERBOSE, "MSI completed for flush req %d\n",
|
||||
ereq->flush_num);
|
||||
|
||||
/*Cmd completion handling*/
|
||||
mhi = ereq->context;
|
||||
cmd_ctx = mhi->cmd_ctx;
|
||||
cmd_ctx->cmd_buf_wp += ereq->num_events;
|
||||
if (cmd_ctx->cmd_buf_wp == NUM_CMD_EVENTS_DEFAULT)
|
||||
cmd_ctx->cmd_buf_wp = 0;
|
||||
spin_lock_irqsave(&mhi->lock, flags);
|
||||
list_add_tail(&ereq->list, &cmd_ctx->cmd_req_buffers);
|
||||
spin_unlock_irqrestore(&mhi->lock, flags);
|
||||
}
|
||||
|
||||
static void mhi_dev_event_msi_cb(void *req)
|
||||
{
|
||||
struct event_req *ereq = req;
|
||||
|
|
@ -401,7 +435,8 @@ static int mhi_trigger_msi_edma(struct mhi_dev_ring *ring, u32 idx)
|
|||
}
|
||||
|
||||
static int mhi_dev_send_multiple_tr_events(struct mhi_dev *mhi, int evnt_ring,
|
||||
struct event_req *ereq, uint32_t evt_len)
|
||||
struct event_req *ereq, uint32_t evt_len,
|
||||
enum mhi_dev_tr_compl_evt_type event_type)
|
||||
{
|
||||
int rc = 0;
|
||||
uint64_t evnt_ring_idx = mhi->ev_ring_start + evnt_ring;
|
||||
|
|
@ -430,25 +465,25 @@ static int mhi_dev_send_multiple_tr_events(struct mhi_dev *mhi, int evnt_ring,
|
|||
return rc;
|
||||
}
|
||||
}
|
||||
ch = ereq->context;
|
||||
/* Check the limits of the buffer to be flushed */
|
||||
if (ereq->tr_events < ch->tr_events ||
|
||||
(ereq->tr_events + ereq->num_events) >
|
||||
(ch->tr_events + ch->evt_buf_size)) {
|
||||
pr_err("%s: Invalid completion event buffer!\n", __func__);
|
||||
mhi_log(MHI_MSG_ERROR,
|
||||
"Invalid cmpl evt buf - start %pK, end %pK\n",
|
||||
ereq->tr_events, ereq->tr_events + ereq->num_events);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
mutex_lock(&ring->event_lock);
|
||||
mhi_log(MHI_MSG_VERBOSE, "Flushing %d cmpl events of ch %d\n",
|
||||
ereq->num_events, ch->ch_id);
|
||||
|
||||
/* add the events */
|
||||
ereq->client_cb = mhi_dev_event_buf_completion_cb;
|
||||
ereq->is_cmd_cpl = (event_type == SEND_CMD_CMP) ? true:false;
|
||||
ereq->event_type = SEND_EVENT_BUFFER;
|
||||
|
||||
if (!ereq->is_cmd_cpl) {
|
||||
ch = ereq->context;
|
||||
mhi_log(MHI_MSG_VERBOSE, "Flushing %d cmpl events of ch %d\n",
|
||||
ereq->num_events, ch->ch_id);
|
||||
} else {
|
||||
mhi_log(MHI_MSG_VERBOSE,
|
||||
"Flushing %d cmpl events of cmd ring\n",
|
||||
ereq->num_events);
|
||||
}
|
||||
|
||||
rc = mhi_dev_add_element(ring, ereq->tr_events, ereq, evt_len);
|
||||
if (rc) {
|
||||
pr_err("%s(): error in adding element rc %d\n", __func__, rc);
|
||||
|
|
@ -506,6 +541,55 @@ static int mhi_dev_send_multiple_tr_events(struct mhi_dev *mhi, int evnt_ring,
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int mhi_dev_flush_cmd_completion_events(struct mhi_dev *mhi,
|
||||
union mhi_dev_ring_element_type *el)
|
||||
{
|
||||
struct mhi_cmd_cmpl_ctx *cmd_ctx = mhi->cmd_ctx;
|
||||
unsigned long flags;
|
||||
struct event_req *flush_ereq;
|
||||
union mhi_dev_ring_element_type *compl_ev;
|
||||
int rc = 0;
|
||||
|
||||
/*cmd completions are sent on event ring 0 always*/
|
||||
if (!mhi->cmd_ctx) {
|
||||
if (mhi_dev_alloc_cmd_ack_buf_req(mhi)) {
|
||||
mhi_log(MHI_MSG_ERROR, "Alloc cmd ack buff failed");
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
cmd_ctx = mhi->cmd_ctx;
|
||||
if (list_empty(&cmd_ctx->cmd_req_buffers)) {
|
||||
mhi_log(MHI_MSG_ERROR, "cmd req buff list is empty");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&mhi->lock, flags);
|
||||
flush_ereq = container_of(cmd_ctx->cmd_req_buffers.next,
|
||||
struct event_req, list);
|
||||
list_del_init(&flush_ereq->list);
|
||||
flush_ereq->context = mhi;
|
||||
spin_unlock_irqrestore(&mhi->lock, flags);
|
||||
|
||||
compl_ev = cmd_ctx->cmd_events + cmd_ctx->cmd_buf_rp;
|
||||
memcpy(compl_ev, el, sizeof(union mhi_dev_ring_element_type));
|
||||
cmd_ctx->cmd_buf_rp++;
|
||||
if (cmd_ctx->cmd_buf_rp == NUM_CMD_EVENTS_DEFAULT)
|
||||
cmd_ctx->cmd_buf_rp = 0;
|
||||
flush_ereq->tr_events = compl_ev;
|
||||
rc = mhi_dev_send_multiple_tr_events(mhi,
|
||||
0,
|
||||
flush_ereq,
|
||||
(1 *
|
||||
sizeof(union mhi_dev_ring_element_type)),
|
||||
SEND_CMD_CMP);
|
||||
if (rc) {
|
||||
mhi_log(MHI_MSG_ERROR, "failed to send compl evts\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int mhi_dev_flush_transfer_completion_events(struct mhi_dev *mhi,
|
||||
struct mhi_dev_channel *ch)
|
||||
{
|
||||
|
|
@ -539,11 +623,25 @@ static int mhi_dev_flush_transfer_completion_events(struct mhi_dev *mhi,
|
|||
flush_ereq->flush_num = ch->flush_req_cnt;
|
||||
mhi_log(MHI_MSG_DBG, "Flush num %d called for ch %d\n",
|
||||
ch->flush_req_cnt, ch->ch_id);
|
||||
|
||||
/* Check the limits of the buffer to be flushed */
|
||||
if (flush_ereq->tr_events < ch->tr_events ||
|
||||
(flush_ereq->tr_events + flush_ereq->num_events) >
|
||||
(ch->tr_events + ch->evt_buf_size)) {
|
||||
pr_err("%s: Invalid completion event buffer!\n",
|
||||
__func__);
|
||||
mhi_log(MHI_MSG_ERROR,
|
||||
"Invalid cmpl evt buf - start %pK, end %pK\n",
|
||||
flush_ereq->tr_events,
|
||||
flush_ereq->tr_events + flush_ereq->num_events);
|
||||
return -EINVAL;
|
||||
}
|
||||
rc = mhi_dev_send_multiple_tr_events(mhi,
|
||||
mhi->ch_ctx_cache[ch->ch_id].err_indx,
|
||||
flush_ereq,
|
||||
(flush_ereq->num_events *
|
||||
sizeof(union mhi_dev_ring_element_type)));
|
||||
sizeof(union mhi_dev_ring_element_type)),
|
||||
SEND_EVENT_BUFFER);
|
||||
if (rc) {
|
||||
mhi_log(MHI_MSG_ERROR, "failed to send compl evts\n");
|
||||
break;
|
||||
|
|
@ -1608,7 +1706,7 @@ int mhi_dev_send_state_change_event(struct mhi_dev *mhi,
|
|||
event.evt_state_change.type = MHI_DEV_RING_EL_MHI_STATE_CHG;
|
||||
event.evt_state_change.mhistate = state;
|
||||
|
||||
return mhi_dev_send_event(mhi, 0, &event);
|
||||
return mhi_dev_flush_cmd_completion_events(mhi, &event);
|
||||
}
|
||||
EXPORT_SYMBOL(mhi_dev_send_state_change_event);
|
||||
|
||||
|
|
@ -1619,7 +1717,7 @@ int mhi_dev_send_ee_event(struct mhi_dev *mhi, enum mhi_dev_execenv exec_env)
|
|||
event.evt_ee_state.type = MHI_DEV_RING_EL_EE_STATE_CHANGE_NOTIFY;
|
||||
event.evt_ee_state.execenv = exec_env;
|
||||
|
||||
return mhi_dev_send_event(mhi, 0, &event);
|
||||
return mhi_dev_flush_cmd_completion_events(mhi, &event);
|
||||
}
|
||||
EXPORT_SYMBOL(mhi_dev_send_ee_event);
|
||||
|
||||
|
|
@ -1669,7 +1767,7 @@ static int mhi_dev_send_cmd_comp_event(struct mhi_dev *mhi,
|
|||
(size_t) event.evt_cmd_comp.ptr);
|
||||
event.evt_cmd_comp.type = MHI_DEV_RING_EL_CMD_COMPLETION_EVT;
|
||||
event.evt_cmd_comp.code = code;
|
||||
return mhi_dev_send_event(mhi, 0, &event);
|
||||
return mhi_dev_flush_cmd_completion_events(mhi, &event);
|
||||
}
|
||||
|
||||
static int mhi_dev_process_stop_cmd(struct mhi_dev_ring *ring, uint32_t ch_id,
|
||||
|
|
@ -1852,7 +1950,7 @@ send_start_completion_event:
|
|||
event.evt_cmd_comp.code =
|
||||
MHI_CMD_COMPL_CODE_UNDEFINED;
|
||||
|
||||
rc = mhi_dev_send_event(mhi, 0, &event);
|
||||
rc = mhi_dev_flush_cmd_completion_events(mhi, &event);
|
||||
if (rc) {
|
||||
pr_err("stop event send failed\n");
|
||||
return;
|
||||
|
|
@ -1912,7 +2010,7 @@ send_start_completion_event:
|
|||
event.evt_cmd_comp.code =
|
||||
MHI_CMD_COMPL_CODE_UNDEFINED;
|
||||
|
||||
rc = mhi_dev_send_event(mhi, 0, &event);
|
||||
rc = mhi_dev_flush_cmd_completion_events(mhi, &event);
|
||||
if (rc) {
|
||||
pr_err("stop event send failed\n");
|
||||
return;
|
||||
|
|
@ -2723,6 +2821,61 @@ static uint32_t mhi_dev_get_evt_ring_size(struct mhi_dev *mhi, uint32_t ch_id)
|
|||
mhi->ch_ctx_cache[ch_id].err_indx].ring_size;
|
||||
}
|
||||
|
||||
static int mhi_dev_alloc_cmd_ack_buf_req(struct mhi_dev *mhi)
|
||||
{
|
||||
int rc = 0;
|
||||
uint32_t i;
|
||||
struct mhi_cmd_cmpl_ctx *cmd_ctx;
|
||||
union mhi_dev_ring_element_type *cmd_events;
|
||||
|
||||
mhi->cmd_ctx = kmalloc(sizeof(struct mhi_cmd_cmpl_ctx),
|
||||
GFP_KERNEL);
|
||||
if (!mhi->cmd_ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
cmd_ctx = mhi->cmd_ctx;
|
||||
/* Allocate event requests */
|
||||
cmd_ctx->ereqs = kcalloc(NUM_CMD_EVENTS_DEFAULT,
|
||||
sizeof(*cmd_ctx->ereqs),
|
||||
GFP_KERNEL);
|
||||
if (!cmd_ctx->ereqs) {
|
||||
goto free_ereqs;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Allocate buffers to queue transfer completion events */
|
||||
cmd_ctx->cmd_events = kcalloc(NUM_CMD_EVENTS_DEFAULT,
|
||||
sizeof(*cmd_events),
|
||||
GFP_KERNEL);
|
||||
if (!cmd_ctx->cmd_events) {
|
||||
rc = -ENOMEM;
|
||||
goto free_ereqs;
|
||||
}
|
||||
|
||||
/* Organize event flush requests into a linked list */
|
||||
INIT_LIST_HEAD(&cmd_ctx->cmd_req_buffers);
|
||||
|
||||
for (i = 0; i < NUM_CMD_EVENTS_DEFAULT; ++i) {
|
||||
list_add_tail(&cmd_ctx->ereqs[i].list,
|
||||
&cmd_ctx->cmd_req_buffers);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize cmpl event buffer indexes - cmd_buf_rp and
|
||||
* cmd_buf_wp point to the first and last free index available.
|
||||
*/
|
||||
cmd_ctx->cmd_buf_rp = 0;
|
||||
cmd_ctx->cmd_buf_wp = NUM_CMD_EVENTS_DEFAULT - 1;
|
||||
|
||||
return 0;
|
||||
free_ereqs:
|
||||
kfree(mhi->cmd_ctx);
|
||||
kfree(cmd_ctx->ereqs);
|
||||
cmd_ctx->ereqs = NULL;
|
||||
mhi->cmd_ctx = NULL;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int mhi_dev_alloc_evt_buf_evt_req(struct mhi_dev *mhi,
|
||||
struct mhi_dev_channel *ch, struct mhi_dev_ring *evt_ring)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -271,6 +271,8 @@ struct mhi_config {
|
|||
|
||||
/* maximum transfer completion events buffer */
|
||||
#define NUM_TR_EVENTS_DEFAULT 128
|
||||
#define NUM_CMD_EVENTS_DEFAULT 20
|
||||
|
||||
|
||||
/* Set flush threshold to 80% of event buf size */
|
||||
#define MHI_CMPL_EVT_FLUSH_THRSHLD(n) ((n * 8) / 10)
|
||||
|
|
@ -354,7 +356,8 @@ enum mhi_dev_ch_operation {
|
|||
enum mhi_dev_tr_compl_evt_type {
|
||||
SEND_EVENT_BUFFER,
|
||||
SEND_EVENT_RD_OFFSET,
|
||||
SEND_MSI
|
||||
SEND_MSI,
|
||||
SEND_CMD_CMP,
|
||||
};
|
||||
|
||||
enum mhi_dev_transfer_type {
|
||||
|
|
@ -448,6 +451,18 @@ struct event_req {
|
|||
void (*msi_cb)(void *req);
|
||||
struct list_head list;
|
||||
u32 flush_num;
|
||||
bool is_cmd_cpl;
|
||||
};
|
||||
|
||||
struct mhi_cmd_cmpl_ctx {
|
||||
/* Indices for completion event buffer */
|
||||
uint32_t cmd_buf_rp;
|
||||
uint32_t cmd_buf_wp;
|
||||
uint32_t cmd_buf_size;
|
||||
bool mem_allocated;
|
||||
struct list_head cmd_req_buffers;
|
||||
struct event_req *ereqs;
|
||||
union mhi_dev_ring_element_type *cmd_events;
|
||||
};
|
||||
|
||||
struct mhi_dev_channel {
|
||||
|
|
@ -531,6 +546,7 @@ struct mhi_dev {
|
|||
struct mhi_dev_ring *ring;
|
||||
int mhi_irq;
|
||||
struct mhi_dev_channel *ch;
|
||||
struct mhi_cmd_cmpl_ctx *cmd_ctx;
|
||||
|
||||
int ctrl_int;
|
||||
int cmd_int;
|
||||
|
|
|
|||
Loading…
Reference in a new issue