mhi: core: Enabled full NER support
Enable NER support for MHI core. MHI core now enables only event rings required for used channels. This saves a substantial amount of system memory. Change-Id: I3b9d63875cf117fba2ac062f831da1899b355e2c Signed-off-by: Andrei Danaila <adanaila@codeaurora.org>
This commit is contained in:
parent
ab4c04bef6
commit
8d7c29c161
7 changed files with 27 additions and 94 deletions
|
@ -356,7 +356,7 @@ struct mhi_control_seg {
|
||||||
union mhi_cmd_pkt cmd_trb_list[NR_OF_CMD_RINGS][CMD_EL_PER_RING + 1];
|
union mhi_cmd_pkt cmd_trb_list[NR_OF_CMD_RINGS][CMD_EL_PER_RING + 1];
|
||||||
struct mhi_cmd_ctxt mhi_cmd_ctxt_list[NR_OF_CMD_RINGS];
|
struct mhi_cmd_ctxt mhi_cmd_ctxt_list[NR_OF_CMD_RINGS];
|
||||||
struct mhi_chan_ctxt mhi_cc_list[MHI_MAX_CHANNELS];
|
struct mhi_chan_ctxt mhi_cc_list[MHI_MAX_CHANNELS];
|
||||||
struct mhi_event_ctxt mhi_ec_list[MHI_MAX_CHANNELS];
|
struct mhi_event_ctxt mhi_ec_list[EVENT_RINGS_ALLOCATED];
|
||||||
u32 padding;
|
u32 padding;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -31,18 +31,12 @@ static enum MHI_STATUS mhi_create_ctxt(struct mhi_device_ctxt *mhi_dev_ctxt)
|
||||||
mhi_dev_ctxt->nr_of_cmdc = NR_OF_CMD_RINGS;
|
mhi_dev_ctxt->nr_of_cmdc = NR_OF_CMD_RINGS;
|
||||||
|
|
||||||
mhi_dev_ctxt->alloced_ev_rings[PRIMARY_EVENT_RING] = 0;
|
mhi_dev_ctxt->alloced_ev_rings[PRIMARY_EVENT_RING] = 0;
|
||||||
mhi_dev_ctxt->alloced_ev_rings[SOFTWARE_EV_RING] =
|
mhi_dev_ctxt->alloced_ev_rings[IPA_OUT_EV_RING] = IPA_OUT_EV_RING;
|
||||||
SOFTWARE_EV_RING;
|
mhi_dev_ctxt->alloced_ev_rings[IPA_IN_EV_RING] = IPA_IN_EV_RING;
|
||||||
mhi_dev_ctxt->alloced_ev_rings[IPA_OUT_EV_RING] =
|
|
||||||
MHI_CLIENT_IP_HW_0_OUT;
|
|
||||||
mhi_dev_ctxt->alloced_ev_rings[IPA_IN_EV_RING] =
|
|
||||||
MHI_CLIENT_IP_HW_0_IN;
|
|
||||||
MHI_SET_EVENT_RING_INFO(EVENT_RING_POLLING,
|
MHI_SET_EVENT_RING_INFO(EVENT_RING_POLLING,
|
||||||
mhi_dev_ctxt->ev_ring_props[PRIMARY_EVENT_RING],
|
mhi_dev_ctxt->ev_ring_props[PRIMARY_EVENT_RING],
|
||||||
MHI_EVENT_POLLING_ENABLED);
|
MHI_EVENT_POLLING_ENABLED);
|
||||||
MHI_SET_EVENT_RING_INFO(EVENT_RING_POLLING,
|
|
||||||
mhi_dev_ctxt->ev_ring_props[SOFTWARE_EV_RING],
|
|
||||||
MHI_EVENT_POLLING_ENABLED);
|
|
||||||
MHI_SET_EVENT_RING_INFO(EVENT_RING_POLLING,
|
MHI_SET_EVENT_RING_INFO(EVENT_RING_POLLING,
|
||||||
mhi_dev_ctxt->ev_ring_props[IPA_OUT_EV_RING],
|
mhi_dev_ctxt->ev_ring_props[IPA_OUT_EV_RING],
|
||||||
MHI_EVENT_POLLING_ENABLED);
|
MHI_EVENT_POLLING_ENABLED);
|
||||||
|
@ -50,7 +44,7 @@ static enum MHI_STATUS mhi_create_ctxt(struct mhi_device_ctxt *mhi_dev_ctxt)
|
||||||
mhi_dev_ctxt->ev_ring_props[IPA_IN_EV_RING],
|
mhi_dev_ctxt->ev_ring_props[IPA_IN_EV_RING],
|
||||||
MHI_EVENT_POLLING_DISABLED);
|
MHI_EVENT_POLLING_DISABLED);
|
||||||
|
|
||||||
for (i = 0; i < MAX_NR_MSI; ++i) {
|
for (i = 0; i < EVENT_RINGS_ALLOCATED; ++i) {
|
||||||
MHI_SET_EVENT_RING_INFO(EVENT_RING_MSI_VEC,
|
MHI_SET_EVENT_RING_INFO(EVENT_RING_MSI_VEC,
|
||||||
mhi_dev_ctxt->ev_ring_props[i],
|
mhi_dev_ctxt->ev_ring_props[i],
|
||||||
i);
|
i);
|
||||||
|
@ -461,7 +455,7 @@ static enum MHI_STATUS mhi_init_contexts(struct mhi_device_ctxt *mhi_dev_ctxt)
|
||||||
(uintptr_t)trb_list,
|
(uintptr_t)trb_list,
|
||||||
MAX_NR_TRBS_PER_HARD_CHAN,
|
MAX_NR_TRBS_PER_HARD_CHAN,
|
||||||
(i % 2) ? MHI_IN : MHI_OUT,
|
(i % 2) ? MHI_IN : MHI_OUT,
|
||||||
i,
|
EVENT_RINGS_ALLOCATED - (MHI_MAX_CHANNELS - i),
|
||||||
&mhi_dev_ctxt->mhi_local_chan_ctxt[i]);
|
&mhi_dev_ctxt->mhi_local_chan_ctxt[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,13 +35,11 @@ irqreturn_t mhi_msi_handlr(int irq_number, void *dev_id)
|
||||||
switch (IRQ_TO_MSI(mhi_dev_ctxt, irq_number)) {
|
switch (IRQ_TO_MSI(mhi_dev_ctxt, irq_number)) {
|
||||||
case 0:
|
case 0:
|
||||||
case 1:
|
case 1:
|
||||||
case 2:
|
|
||||||
atomic_inc(&mhi_dev_ctxt->flags.events_pending);
|
atomic_inc(&mhi_dev_ctxt->flags.events_pending);
|
||||||
wake_up_interruptible(mhi_dev_ctxt->event_handle);
|
wake_up_interruptible(mhi_dev_ctxt->event_handle);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 2:
|
||||||
client_index =
|
client_index = MHI_CLIENT_IP_HW_0_IN;
|
||||||
mhi_dev_ctxt->alloced_ev_rings[IPA_IN_EV_RING];
|
|
||||||
client_handle = mhi_dev_ctxt->client_handle_list[client_index];
|
client_handle = mhi_dev_ctxt->client_handle_list[client_index];
|
||||||
client_info = &client_handle->client_info;
|
client_info = &client_handle->client_info;
|
||||||
|
|
||||||
|
|
|
@ -32,11 +32,10 @@
|
||||||
|
|
||||||
#define MAX_NR_MSI 4
|
#define MAX_NR_MSI 4
|
||||||
|
|
||||||
#define EVENT_RINGS_ALLOCATED 4
|
#define EVENT_RINGS_ALLOCATED 3
|
||||||
#define PRIMARY_EVENT_RING 0
|
#define PRIMARY_EVENT_RING 0
|
||||||
#define SOFTWARE_EV_RING 1
|
#define IPA_OUT_EV_RING 1
|
||||||
#define IPA_OUT_EV_RING 2
|
#define IPA_IN_EV_RING 2
|
||||||
#define IPA_IN_EV_RING 3
|
|
||||||
|
|
||||||
#define PRIMARY_CMD_RING 0
|
#define PRIMARY_CMD_RING 0
|
||||||
#define MHI_WORK_Q_MAX_SIZE 128
|
#define MHI_WORK_Q_MAX_SIZE 128
|
||||||
|
|
|
@ -50,8 +50,12 @@ static void mhi_update_ctxt(struct mhi_device_ctxt *mhi_dev_ctxt,
|
||||||
mhi_dev_ctxt->mhi_ctrl_seg->mhi_cc_list[chan].
|
mhi_dev_ctxt->mhi_ctrl_seg->mhi_cc_list[chan].
|
||||||
mhi_trb_write_ptr = val;
|
mhi_trb_write_ptr = val;
|
||||||
} else if (mhi_dev_ctxt->event_db_addr == io_addr) {
|
} else if (mhi_dev_ctxt->event_db_addr == io_addr) {
|
||||||
|
if (chan < EVENT_RINGS_ALLOCATED)
|
||||||
mhi_dev_ctxt->mhi_ctrl_seg->mhi_ec_list[chan].
|
mhi_dev_ctxt->mhi_ctrl_seg->mhi_ec_list[chan].
|
||||||
mhi_event_write_ptr = val;
|
mhi_event_write_ptr = val;
|
||||||
|
else
|
||||||
|
mhi_log(MHI_MSG_ERROR,
|
||||||
|
"Bad EV ring index: %lx\n", chan);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,10 +338,9 @@ enum MHI_STATUS mhi_register_channel(struct mhi_client_handle **client_handle,
|
||||||
|
|
||||||
mhi_log(MHI_MSG_VERBOSE,
|
mhi_log(MHI_MSG_VERBOSE,
|
||||||
"Successfuly registered chan 0x%x\n", chan);
|
"Successfuly registered chan 0x%x\n", chan);
|
||||||
return ret_val;
|
|
||||||
|
|
||||||
error_handle:
|
error_handle:
|
||||||
return ret_val;
|
return ret_val;
|
||||||
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(mhi_register_channel);
|
EXPORT_SYMBOL(mhi_register_channel);
|
||||||
|
|
||||||
|
@ -410,8 +413,7 @@ enum MHI_STATUS mhi_add_elements_to_event_rings(
|
||||||
event_ring_state);
|
event_ring_state);
|
||||||
ret_val = mhi_init_event_ring(mhi_dev_ctxt,
|
ret_val = mhi_init_event_ring(mhi_dev_ctxt,
|
||||||
EV_EL_PER_RING,
|
EV_EL_PER_RING,
|
||||||
mhi_dev_ctxt->
|
PRIMARY_EVENT_RING);
|
||||||
alloced_ev_rings[PRIMARY_EVENT_RING]);
|
|
||||||
if (MHI_STATUS_SUCCESS != ret_val) {
|
if (MHI_STATUS_SUCCESS != ret_val) {
|
||||||
|
|
||||||
mhi_log(MHI_MSG_ERROR,
|
mhi_log(MHI_MSG_ERROR,
|
||||||
|
@ -425,7 +427,7 @@ enum MHI_STATUS mhi_add_elements_to_event_rings(
|
||||||
mhi_log(MHI_MSG_ERROR,
|
mhi_log(MHI_MSG_ERROR,
|
||||||
"Event ring initialized ringing, EV DB to resume\n");
|
"Event ring initialized ringing, EV DB to resume\n");
|
||||||
ring_ev_db(mhi_dev_ctxt,
|
ring_ev_db(mhi_dev_ctxt,
|
||||||
mhi_dev_ctxt->alloced_ev_rings[PRIMARY_EVENT_RING]);
|
PRIMARY_EVENT_RING);
|
||||||
break;
|
break;
|
||||||
case STATE_TRANSITION_AMSS:
|
case STATE_TRANSITION_AMSS:
|
||||||
MHI_GET_EVENT_RING_INFO(EVENT_RING_STATE_FIELD,
|
MHI_GET_EVENT_RING_INFO(EVENT_RING_STATE_FIELD,
|
||||||
|
@ -434,8 +436,7 @@ enum MHI_STATUS mhi_add_elements_to_event_rings(
|
||||||
if (MHI_EVENT_RING_UINIT == event_ring_state) {
|
if (MHI_EVENT_RING_UINIT == event_ring_state) {
|
||||||
ret_val = mhi_init_event_ring(mhi_dev_ctxt,
|
ret_val = mhi_init_event_ring(mhi_dev_ctxt,
|
||||||
EV_EL_PER_RING,
|
EV_EL_PER_RING,
|
||||||
mhi_dev_ctxt->
|
IPA_OUT_EV_RING);
|
||||||
alloced_ev_rings[IPA_OUT_EV_RING]);
|
|
||||||
if (MHI_STATUS_SUCCESS != ret_val) {
|
if (MHI_STATUS_SUCCESS != ret_val) {
|
||||||
mhi_log(MHI_MSG_ERROR,
|
mhi_log(MHI_MSG_ERROR,
|
||||||
"Failed to add ev el on event ring\n");
|
"Failed to add ev el on event ring\n");
|
||||||
|
@ -443,7 +444,7 @@ enum MHI_STATUS mhi_add_elements_to_event_rings(
|
||||||
}
|
}
|
||||||
ret_val = mhi_init_event_ring(mhi_dev_ctxt,
|
ret_val = mhi_init_event_ring(mhi_dev_ctxt,
|
||||||
EV_EL_PER_RING,
|
EV_EL_PER_RING,
|
||||||
mhi_dev_ctxt->alloced_ev_rings[IPA_IN_EV_RING]);
|
IPA_IN_EV_RING);
|
||||||
if (MHI_STATUS_SUCCESS != ret_val) {
|
if (MHI_STATUS_SUCCESS != ret_val) {
|
||||||
mhi_log(MHI_MSG_ERROR,
|
mhi_log(MHI_MSG_ERROR,
|
||||||
"Failed to add ev el on event ring\n");
|
"Failed to add ev el on event ring\n");
|
||||||
|
@ -456,12 +457,8 @@ enum MHI_STATUS mhi_add_elements_to_event_rings(
|
||||||
mhi_dev_ctxt->ev_ring_props[IPA_IN_EV_RING],
|
mhi_dev_ctxt->ev_ring_props[IPA_IN_EV_RING],
|
||||||
MHI_EVENT_RING_INIT);
|
MHI_EVENT_RING_INIT);
|
||||||
}
|
}
|
||||||
ring_ev_db(mhi_dev_ctxt,
|
ring_ev_db(mhi_dev_ctxt, IPA_OUT_EV_RING);
|
||||||
mhi_dev_ctxt->alloced_ev_rings[SOFTWARE_EV_RING]);
|
ring_ev_db(mhi_dev_ctxt, IPA_IN_EV_RING);
|
||||||
ring_ev_db(mhi_dev_ctxt,
|
|
||||||
mhi_dev_ctxt->alloced_ev_rings[IPA_OUT_EV_RING]);
|
|
||||||
ring_ev_db(mhi_dev_ctxt,
|
|
||||||
mhi_dev_ctxt->alloced_ev_rings[IPA_IN_EV_RING]);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
mhi_log(MHI_MSG_ERROR,
|
mhi_log(MHI_MSG_ERROR,
|
||||||
|
@ -784,6 +781,9 @@ static enum MHI_STATUS parse_inbound(struct mhi_device_ctxt *mhi_dev_ctxt,
|
||||||
cb_info.result = &client_handle->result;
|
cb_info.result = &client_handle->result;
|
||||||
cb_info.chan = chan;
|
cb_info.chan = chan;
|
||||||
client_handle->client_info.mhi_client_cb(&cb_info);
|
client_handle->client_info.mhi_client_cb(&cb_info);
|
||||||
|
} else {
|
||||||
|
mhi_log(MHI_MSG_VERBOSE,
|
||||||
|
"No client registered chan %d\n", chan);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* IN Hardware channel with no client
|
/* IN Hardware channel with no client
|
||||||
|
|
|
@ -108,7 +108,7 @@ enum MHI_STATUS mhi_init_mmio(struct mhi_device_ctxt *mhi_dev_ctxt)
|
||||||
|
|
||||||
mhi_reg_write_field(mhi_dev_ctxt, mhi_dev_ctxt->mmio_addr, MHICFG,
|
mhi_reg_write_field(mhi_dev_ctxt, mhi_dev_ctxt->mmio_addr, MHICFG,
|
||||||
MHICFG_NER_MASK, MHICFG_NER_SHIFT,
|
MHICFG_NER_MASK, MHICFG_NER_SHIFT,
|
||||||
MHI_MAX_CHANNELS);
|
EVENT_RINGS_ALLOCATED);
|
||||||
|
|
||||||
pcie_dword_val = mhi_v2p_addr(mhi_dev_ctxt->mhi_ctrl_seg_info,
|
pcie_dword_val = mhi_v2p_addr(mhi_dev_ctxt->mhi_ctrl_seg_info,
|
||||||
(uintptr_t)mhi_dev_ctxt->mhi_ctrl_seg->mhi_cc_list);
|
(uintptr_t)mhi_dev_ctxt->mhi_ctrl_seg->mhi_cc_list);
|
||||||
|
|
|
@ -751,64 +751,6 @@ int mhi_state_change_thread(void *ctxt)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* mhi_reset_channel - Reset for a single MHI channel
|
|
||||||
*
|
|
||||||
* @client_handle device context
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
enum MHI_STATUS mhi_reset_channel(struct mhi_client_handle *client_handle)
|
|
||||||
{
|
|
||||||
enum MHI_STATUS ret_val;
|
|
||||||
struct mhi_chan_ctxt *cur_ctxt = NULL;
|
|
||||||
struct mhi_device_ctxt *mhi_dev_ctxt = NULL;
|
|
||||||
u32 chan_id = 0;
|
|
||||||
struct mhi_ring *cur_ring = NULL;
|
|
||||||
|
|
||||||
chan_id = client_handle->chan;
|
|
||||||
mhi_dev_ctxt = client_handle->mhi_dev_ctxt;
|
|
||||||
|
|
||||||
if (chan_id > (MHI_MAX_CHANNELS - 1) || NULL == mhi_dev_ctxt) {
|
|
||||||
mhi_log(MHI_MSG_ERROR, "Bad input parameters\n");
|
|
||||||
return MHI_STATUS_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
mutex_lock(&mhi_dev_ctxt->mhi_chan_mutex[chan_id]);
|
|
||||||
|
|
||||||
/* We need to reset the channel completley, we will assume that our
|
|
||||||
* base is correct*/
|
|
||||||
cur_ctxt = &mhi_dev_ctxt->mhi_ctrl_seg->mhi_cc_list[chan_id];
|
|
||||||
cur_ring = &mhi_dev_ctxt->mhi_local_event_ctxt[chan_id];
|
|
||||||
memset(cur_ring->base, 0, sizeof(char)*cur_ring->len);
|
|
||||||
|
|
||||||
if (IS_HARDWARE_CHANNEL(chan_id)) {
|
|
||||||
ret_val = mhi_init_chan_ctxt(cur_ctxt,
|
|
||||||
mhi_v2p_addr(mhi_dev_ctxt->mhi_ctrl_seg_info,
|
|
||||||
(uintptr_t)cur_ring->base),
|
|
||||||
(uintptr_t)cur_ring->base,
|
|
||||||
MAX_NR_TRBS_PER_HARD_CHAN,
|
|
||||||
(chan_id % 2) ? MHI_IN : MHI_OUT,
|
|
||||||
(chan_id % 2) ? IPA_IN_EV_RING : IPA_OUT_EV_RING,
|
|
||||||
cur_ring);
|
|
||||||
} else {
|
|
||||||
ret_val = mhi_init_chan_ctxt(cur_ctxt,
|
|
||||||
mhi_v2p_addr(mhi_dev_ctxt->mhi_ctrl_seg_info,
|
|
||||||
(uintptr_t)cur_ring->base),
|
|
||||||
(uintptr_t)cur_ring->base,
|
|
||||||
MAX_NR_TRBS_PER_SOFT_CHAN,
|
|
||||||
(chan_id % 2) ? MHI_IN : MHI_OUT,
|
|
||||||
SOFTWARE_EV_RING,
|
|
||||||
cur_ring);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (MHI_STATUS_SUCCESS != ret_val)
|
|
||||||
mhi_log(MHI_MSG_ERROR, "Failed to reset chan ctxt\n");
|
|
||||||
|
|
||||||
|
|
||||||
mutex_unlock(&mhi_dev_ctxt->mhi_chan_mutex[chan_id]);
|
|
||||||
return ret_val;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* mhi_init_state_transition - Add a new state transition work item to
|
* mhi_init_state_transition - Add a new state transition work item to
|
||||||
* the state transition thread work item list.
|
* the state transition thread work item list.
|
||||||
|
|
Loading…
Add table
Reference in a new issue