mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-07 12:25:00 -04:00
Merge "mhi: core: Add range check for channel id received in event ring"
This commit is contained in:
commit
a2c09fa854
5 changed files with 230 additions and 3 deletions
|
|
@ -75,6 +75,19 @@ static const char * const mhi_pm_state_str[] = {
|
|||
|
||||
struct mhi_bus mhi_bus;
|
||||
|
||||
struct mhi_controller *find_mhi_controller_by_name(const char *name)
|
||||
{
|
||||
struct mhi_controller *mhi_cntrl, *tmp_cntrl;
|
||||
|
||||
list_for_each_entry_safe(mhi_cntrl, tmp_cntrl, &mhi_bus.controller_list,
|
||||
node) {
|
||||
if (mhi_cntrl->name && (!strcmp(name, mhi_cntrl->name)))
|
||||
return mhi_cntrl;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *to_mhi_pm_state_str(enum MHI_PM_STATE state)
|
||||
{
|
||||
int index = find_last_bit((unsigned long *)&state, 32);
|
||||
|
|
@ -360,6 +373,11 @@ static int mhi_init_debugfs_mhi_chan_open(struct inode *inode, struct file *fp)
|
|||
return single_open(fp, mhi_debugfs_mhi_chan_show, inode->i_private);
|
||||
}
|
||||
|
||||
static int mhi_init_debugfs_mhi_vote_open(struct inode *inode, struct file *fp)
|
||||
{
|
||||
return single_open(fp, mhi_debugfs_mhi_vote_show, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations debugfs_state_ops = {
|
||||
.open = mhi_init_debugfs_mhi_states_open,
|
||||
.release = single_release,
|
||||
|
|
@ -378,6 +396,12 @@ static const struct file_operations debugfs_chan_ops = {
|
|||
.read = seq_read,
|
||||
};
|
||||
|
||||
static const struct file_operations debugfs_vote_ops = {
|
||||
.open = mhi_init_debugfs_mhi_vote_open,
|
||||
.release = single_release,
|
||||
.read = seq_read,
|
||||
};
|
||||
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(debugfs_trigger_reset_fops, NULL,
|
||||
mhi_debugfs_trigger_reset, "%llu\n");
|
||||
|
||||
|
|
@ -403,6 +427,8 @@ void mhi_init_debugfs(struct mhi_controller *mhi_cntrl)
|
|||
&debugfs_ev_ops);
|
||||
debugfs_create_file_unsafe("chan", 0444, dentry, mhi_cntrl,
|
||||
&debugfs_chan_ops);
|
||||
debugfs_create_file_unsafe("vote", 0444, dentry, mhi_cntrl,
|
||||
&debugfs_vote_ops);
|
||||
debugfs_create_file_unsafe("reset", 0444, dentry, mhi_cntrl,
|
||||
&debugfs_trigger_reset_fops);
|
||||
mhi_cntrl->dentry = dentry;
|
||||
|
|
@ -687,6 +713,42 @@ exit_timesync:
|
|||
return ret;
|
||||
}
|
||||
|
||||
int mhi_init_sfr(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
struct mhi_sfr_info *sfr_info = mhi_cntrl->mhi_sfr;
|
||||
int ret = -EIO;
|
||||
|
||||
if (!sfr_info)
|
||||
return ret;
|
||||
|
||||
/* do a clean-up if we reach here post SSR */
|
||||
memset(sfr_info->str, 0, sfr_info->len);
|
||||
|
||||
sfr_info->buf_addr = mhi_alloc_coherent(mhi_cntrl, sfr_info->len,
|
||||
&sfr_info->dma_addr, GFP_KERNEL);
|
||||
if (!sfr_info->buf_addr) {
|
||||
MHI_ERR("Failed to allocate memory for sfr\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
init_completion(&sfr_info->completion);
|
||||
|
||||
ret = mhi_send_cmd(mhi_cntrl, NULL, MHI_CMD_SFR_CFG);
|
||||
if (ret) {
|
||||
MHI_ERR("Failed to send sfr cfg cmd\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = wait_for_completion_timeout(&sfr_info->completion,
|
||||
msecs_to_jiffies(mhi_cntrl->timeout_ms));
|
||||
if (!ret || sfr_info->ccs != MHI_EV_CC_SUCCESS) {
|
||||
MHI_ERR("Failed to get sfr cfg cmd completion\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mhi_init_bw_scale(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
int ret, er_index;
|
||||
|
|
@ -1347,6 +1409,8 @@ static int of_parse_dt(struct mhi_controller *mhi_cntrl,
|
|||
if (!ret)
|
||||
mhi_cntrl->bhie = mhi_cntrl->regs + bhie_offset;
|
||||
|
||||
of_property_read_string(of_node, "mhi,name", &mhi_cntrl->name);
|
||||
|
||||
return 0;
|
||||
|
||||
error_ev_cfg:
|
||||
|
|
@ -1363,6 +1427,7 @@ int of_register_mhi_controller(struct mhi_controller *mhi_cntrl)
|
|||
struct mhi_chan *mhi_chan;
|
||||
struct mhi_cmd *mhi_cmd;
|
||||
struct mhi_device *mhi_dev;
|
||||
struct mhi_sfr_info *sfr_info;
|
||||
u32 soc_info;
|
||||
|
||||
if (!mhi_cntrl->of_node)
|
||||
|
|
@ -1473,6 +1538,7 @@ int of_register_mhi_controller(struct mhi_controller *mhi_cntrl)
|
|||
}
|
||||
|
||||
mhi_dev->dev_type = MHI_CONTROLLER_TYPE;
|
||||
mhi_dev->chan_name = mhi_cntrl->name;
|
||||
mhi_dev->mhi_cntrl = mhi_cntrl;
|
||||
dev_set_name(&mhi_dev->dev, "%04x_%02u.%02u.%02u", mhi_dev->dev_id,
|
||||
mhi_dev->domain, mhi_dev->bus, mhi_dev->slot);
|
||||
|
|
@ -1486,6 +1552,23 @@ int of_register_mhi_controller(struct mhi_controller *mhi_cntrl)
|
|||
|
||||
mhi_cntrl->mhi_dev = mhi_dev;
|
||||
|
||||
if (mhi_cntrl->sfr_len) {
|
||||
sfr_info = kzalloc(sizeof(*sfr_info), GFP_KERNEL);
|
||||
if (!sfr_info) {
|
||||
ret = -ENOMEM;
|
||||
goto error_add_dev;
|
||||
}
|
||||
|
||||
sfr_info->str = kzalloc(mhi_cntrl->sfr_len, GFP_KERNEL);
|
||||
if (!sfr_info->str) {
|
||||
ret = -ENOMEM;
|
||||
goto error_alloc_sfr;
|
||||
}
|
||||
|
||||
sfr_info->len = mhi_cntrl->sfr_len;
|
||||
mhi_cntrl->mhi_sfr = sfr_info;
|
||||
}
|
||||
|
||||
mhi_cntrl->parent = debugfs_lookup(mhi_bus_type.name, NULL);
|
||||
mhi_cntrl->klog_lvl = MHI_MSG_LVL_ERROR;
|
||||
|
||||
|
|
@ -1496,6 +1579,9 @@ int of_register_mhi_controller(struct mhi_controller *mhi_cntrl)
|
|||
|
||||
return 0;
|
||||
|
||||
error_alloc_sfr:
|
||||
kfree(sfr_info);
|
||||
|
||||
error_add_dev:
|
||||
mhi_dealloc_device(mhi_cntrl, mhi_dev);
|
||||
|
||||
|
|
@ -1514,12 +1600,18 @@ EXPORT_SYMBOL(of_register_mhi_controller);
|
|||
void mhi_unregister_mhi_controller(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
struct mhi_device *mhi_dev = mhi_cntrl->mhi_dev;
|
||||
struct mhi_sfr_info *sfr_info = mhi_cntrl->mhi_sfr;
|
||||
|
||||
kfree(mhi_cntrl->mhi_cmd);
|
||||
kfree(mhi_cntrl->mhi_event);
|
||||
vfree(mhi_cntrl->mhi_chan);
|
||||
kfree(mhi_cntrl->mhi_tsync);
|
||||
|
||||
if (sfr_info) {
|
||||
kfree(sfr_info->str);
|
||||
kfree(sfr_info);
|
||||
}
|
||||
|
||||
device_del(&mhi_dev->dev);
|
||||
put_device(&mhi_dev->dev);
|
||||
|
||||
|
|
|
|||
|
|
@ -299,6 +299,7 @@ enum mhi_cmd_type {
|
|||
MHI_CMD_TYPE_STOP = 17,
|
||||
MHI_CMD_TYPE_START = 18,
|
||||
MHI_CMD_TYPE_TSYNC = 24,
|
||||
MHI_CMD_TYPE_SFR_CFG = 73,
|
||||
};
|
||||
|
||||
/* no operation command */
|
||||
|
|
@ -329,6 +330,11 @@ enum mhi_cmd_type {
|
|||
#define MHI_TRE_CMD_TSYNC_CFG_DWORD1(er) ((MHI_CMD_TYPE_TSYNC << 16) | \
|
||||
(er << 24))
|
||||
|
||||
/* subsystem failure reason cfg command */
|
||||
#define MHI_TRE_CMD_SFR_CFG_PTR(ptr) (ptr)
|
||||
#define MHI_TRE_CMD_SFR_CFG_DWORD0(len) (len)
|
||||
#define MHI_TRE_CMD_SFR_CFG_DWORD1 (MHI_CMD_TYPE_SFR_CFG << 16)
|
||||
|
||||
#define MHI_TRE_GET_CMD_CHID(tre) (((tre)->dword[1] >> 24) & 0xFF)
|
||||
#define MHI_TRE_GET_CMD_TYPE(tre) (((tre)->dword[1] >> 16) & 0xFF)
|
||||
|
||||
|
|
@ -369,6 +375,7 @@ enum MHI_CMD {
|
|||
MHI_CMD_START_CHAN,
|
||||
MHI_CMD_STOP_CHAN,
|
||||
MHI_CMD_TIMSYNC_CFG,
|
||||
MHI_CMD_SFR_CFG,
|
||||
};
|
||||
|
||||
enum MHI_PKT_TYPE {
|
||||
|
|
@ -385,6 +392,7 @@ enum MHI_PKT_TYPE {
|
|||
MHI_PKT_TYPE_RSC_TX_EVENT = 0x28,
|
||||
MHI_PKT_TYPE_EE_EVENT = 0x40,
|
||||
MHI_PKT_TYPE_TSYNC_EVENT = 0x48,
|
||||
MHI_PKT_TYPE_SFR_CFG_CMD = 0x49,
|
||||
MHI_PKT_TYPE_BW_REQ_EVENT = 0x50,
|
||||
MHI_PKT_TYPE_STALE_EVENT, /* internal event */
|
||||
};
|
||||
|
|
@ -725,6 +733,15 @@ struct mhi_timesync {
|
|||
struct list_head head;
|
||||
};
|
||||
|
||||
struct mhi_sfr_info {
|
||||
void *buf_addr;
|
||||
dma_addr_t dma_addr;
|
||||
size_t len;
|
||||
char *str;
|
||||
enum MHI_EV_CCS ccs;
|
||||
struct completion completion;
|
||||
};
|
||||
|
||||
struct mhi_bus {
|
||||
struct list_head controller_list;
|
||||
struct mutex lock;
|
||||
|
|
@ -734,7 +751,10 @@ struct mhi_bus {
|
|||
#define MHI_TIMEOUT_MS (1000)
|
||||
extern struct mhi_bus mhi_bus;
|
||||
|
||||
struct mhi_controller *find_mhi_controller_by_name(const char *name);
|
||||
|
||||
/* debug fs related functions */
|
||||
int mhi_debugfs_mhi_vote_show(struct seq_file *m, void *d);
|
||||
int mhi_debugfs_mhi_chan_show(struct seq_file *m, void *d);
|
||||
int mhi_debugfs_mhi_event_show(struct seq_file *m, void *d);
|
||||
int mhi_debugfs_mhi_states_show(struct seq_file *m, void *d);
|
||||
|
|
@ -821,6 +841,7 @@ int mhi_get_capability_offset(struct mhi_controller *mhi_cntrl, u32 capability,
|
|||
u32 *offset);
|
||||
void *mhi_to_virtual(struct mhi_ring *ring, dma_addr_t addr);
|
||||
int mhi_init_timesync(struct mhi_controller *mhi_cntrl);
|
||||
int mhi_init_sfr(struct mhi_controller *mhi_cntrl);
|
||||
int mhi_create_timesync_sysfs(struct mhi_controller *mhi_cntrl);
|
||||
void mhi_destroy_timesync(struct mhi_controller *mhi_cntrl);
|
||||
int mhi_create_sysfs(struct mhi_controller *mhi_cntrl);
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@
|
|||
#include <linux/mhi.h>
|
||||
#include "mhi_internal.h"
|
||||
|
||||
static char *mhi_generic_sfr = "unknown reason";
|
||||
|
||||
static void __mhi_unprepare_channel(struct mhi_controller *mhi_cntrl,
|
||||
struct mhi_chan *mhi_chan);
|
||||
|
||||
|
|
@ -1169,6 +1171,7 @@ static void mhi_process_cmd_completion(struct mhi_controller *mhi_cntrl,
|
|||
struct mhi_tre *cmd_pkt;
|
||||
struct mhi_chan *mhi_chan;
|
||||
struct mhi_timesync *mhi_tsync;
|
||||
struct mhi_sfr_info *sfr_info;
|
||||
enum mhi_cmd_type type;
|
||||
u32 chan;
|
||||
|
||||
|
|
@ -1179,11 +1182,18 @@ static void mhi_process_cmd_completion(struct mhi_controller *mhi_cntrl,
|
|||
|
||||
type = MHI_TRE_GET_CMD_TYPE(cmd_pkt);
|
||||
|
||||
if (type == MHI_CMD_TYPE_TSYNC) {
|
||||
switch (type) {
|
||||
case MHI_CMD_TYPE_TSYNC:
|
||||
mhi_tsync = mhi_cntrl->mhi_tsync;
|
||||
mhi_tsync->ccs = MHI_TRE_GET_EV_CODE(tre);
|
||||
complete(&mhi_tsync->completion);
|
||||
} else {
|
||||
break;
|
||||
case MHI_CMD_TYPE_SFR_CFG:
|
||||
sfr_info = mhi_cntrl->mhi_sfr;
|
||||
sfr_info->ccs = MHI_TRE_GET_EV_CODE(tre);
|
||||
complete(&sfr_info->completion);
|
||||
break;
|
||||
default:
|
||||
chan = MHI_TRE_GET_CMD_CHID(cmd_pkt);
|
||||
if (chan >= mhi_cntrl->max_chan) {
|
||||
MHI_ERR("invalid channel id %u\n", chan);
|
||||
|
|
@ -1194,6 +1204,7 @@ static void mhi_process_cmd_completion(struct mhi_controller *mhi_cntrl,
|
|||
mhi_chan->ccs = MHI_TRE_GET_EV_CODE(tre);
|
||||
complete(&mhi_chan->completion);
|
||||
write_unlock_bh(&mhi_chan->lock);
|
||||
break;
|
||||
}
|
||||
|
||||
del_ring_el:
|
||||
|
|
@ -1369,6 +1380,10 @@ int mhi_process_data_event_ring(struct mhi_controller *mhi_cntrl,
|
|||
mhi_event->last_dev_rp = (u64)dev_rp;
|
||||
|
||||
chan = MHI_TRE_GET_EV_CHID(local_rp);
|
||||
if (chan >= mhi_cntrl->max_chan) {
|
||||
MHI_ERR("invalid channel id %u\n", chan);
|
||||
continue;
|
||||
}
|
||||
mhi_chan = &mhi_cntrl->mhi_chan[chan];
|
||||
|
||||
if (likely(type == MHI_PKT_TYPE_TX_EVENT)) {
|
||||
|
|
@ -1750,6 +1765,7 @@ int mhi_send_cmd(struct mhi_controller *mhi_cntrl,
|
|||
struct mhi_tre *cmd_tre = NULL;
|
||||
struct mhi_cmd *mhi_cmd = &mhi_cntrl->mhi_cmd[PRIMARY_CMD_RING];
|
||||
struct mhi_ring *ring = &mhi_cmd->ring;
|
||||
struct mhi_sfr_info *sfr_info;
|
||||
int chan = 0;
|
||||
|
||||
MHI_VERB("Entered, MHI pm_state:%s dev_state:%s ee:%s\n",
|
||||
|
|
@ -1790,6 +1806,14 @@ int mhi_send_cmd(struct mhi_controller *mhi_cntrl,
|
|||
cmd_tre->dword[1] = MHI_TRE_CMD_TSYNC_CFG_DWORD1
|
||||
(mhi_cntrl->mhi_tsync->er_index);
|
||||
break;
|
||||
case MHI_CMD_SFR_CFG:
|
||||
sfr_info = mhi_cntrl->mhi_sfr;
|
||||
cmd_tre->ptr = MHI_TRE_CMD_SFR_CFG_PTR
|
||||
(sfr_info->dma_addr);
|
||||
cmd_tre->dword[0] = MHI_TRE_CMD_SFR_CFG_DWORD0
|
||||
(sfr_info->len - 1);
|
||||
cmd_tre->dword[1] = MHI_TRE_CMD_SFR_CFG_DWORD1;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -2204,6 +2228,49 @@ int mhi_debugfs_mhi_chan_show(struct seq_file *m, void *d)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* show bus/device votes for a specific device */
|
||||
static int mhi_device_vote_show(struct device *dev, void *data)
|
||||
{
|
||||
struct mhi_device *mhi_dev;
|
||||
struct mhi_controller *mhi_cntrl;
|
||||
|
||||
if (dev->bus != &mhi_bus_type)
|
||||
return 0;
|
||||
|
||||
mhi_dev = to_mhi_device(dev);
|
||||
mhi_cntrl = mhi_dev->mhi_cntrl;
|
||||
|
||||
/* we dont care about timesync or similar special devices */
|
||||
if (mhi_dev->dev_type == MHI_TIMESYNC_TYPE)
|
||||
return 0;
|
||||
|
||||
seq_printf((struct seq_file *)data, "%s: device:%u, bus:%u\n",
|
||||
mhi_dev->chan_name, atomic_read(&mhi_dev->dev_vote),
|
||||
atomic_read(&mhi_dev->bus_vote));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mhi_debugfs_mhi_vote_show(struct seq_file *m, void *d)
|
||||
{
|
||||
struct mhi_controller *mhi_cntrl = m->private;
|
||||
struct mhi_device *mhi_dev;
|
||||
|
||||
if (!mhi_cntrl)
|
||||
return 0;
|
||||
|
||||
mhi_dev = mhi_cntrl->mhi_dev;
|
||||
|
||||
seq_printf(m, "At %llu ns:\n", sched_clock());
|
||||
seq_printf(m, "%s: device:%u, bus:%u\n", mhi_dev->chan_name,
|
||||
atomic_read(&mhi_dev->dev_vote),
|
||||
atomic_read(&mhi_dev->bus_vote));
|
||||
|
||||
device_for_each_child(mhi_cntrl->dev, m, mhi_device_vote_show);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* move channel to start state */
|
||||
int mhi_prepare_for_transfer(struct mhi_device *mhi_dev)
|
||||
{
|
||||
|
|
@ -2648,3 +2715,20 @@ void mhi_debug_reg_dump(struct mhi_controller *mhi_cntrl)
|
|||
}
|
||||
}
|
||||
EXPORT_SYMBOL(mhi_debug_reg_dump);
|
||||
|
||||
char *mhi_get_restart_reason(const char *name)
|
||||
{
|
||||
struct mhi_controller *mhi_cntrl;
|
||||
struct mhi_sfr_info *sfr_info;
|
||||
|
||||
mhi_cntrl = find_mhi_controller_by_name(name);
|
||||
if (!mhi_cntrl)
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
sfr_info = mhi_cntrl->mhi_sfr;
|
||||
if (!sfr_info)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
return strlen(sfr_info->str) ? sfr_info->str : mhi_generic_sfr;
|
||||
}
|
||||
EXPORT_SYMBOL(mhi_get_restart_reason);
|
||||
|
|
|
|||
|
|
@ -527,7 +527,8 @@ static int mhi_pm_mission_mode_transition(struct mhi_controller *mhi_cntrl)
|
|||
|
||||
read_unlock_bh(&mhi_cntrl->pm_lock);
|
||||
|
||||
/* setup support for time sync */
|
||||
/* setup support for additional features (SFR, timesync, etc.) */
|
||||
mhi_init_sfr(mhi_cntrl);
|
||||
mhi_init_timesync(mhi_cntrl);
|
||||
|
||||
if (MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state))
|
||||
|
|
@ -563,6 +564,7 @@ static void mhi_pm_disable_transition(struct mhi_controller *mhi_cntrl,
|
|||
struct mhi_cmd_ctxt *cmd_ctxt;
|
||||
struct mhi_cmd *mhi_cmd;
|
||||
struct mhi_event_ctxt *er_ctxt;
|
||||
struct mhi_sfr_info *sfr_info = mhi_cntrl->mhi_sfr;
|
||||
int ret, i;
|
||||
|
||||
MHI_LOG("Enter with from pm_state:%s MHI_STATE:%s to pm_state:%s\n",
|
||||
|
|
@ -655,6 +657,12 @@ static void mhi_pm_disable_transition(struct mhi_controller *mhi_cntrl,
|
|||
/* remove support for time sync */
|
||||
mhi_destroy_timesync(mhi_cntrl);
|
||||
|
||||
if (sfr_info && sfr_info->buf_addr) {
|
||||
mhi_free_coherent(mhi_cntrl, sfr_info->len, sfr_info->buf_addr,
|
||||
sfr_info->dma_addr);
|
||||
sfr_info->buf_addr = NULL;
|
||||
}
|
||||
|
||||
mutex_lock(&mhi_cntrl->pm_mutex);
|
||||
|
||||
MHI_ASSERT(atomic_read(&mhi_cntrl->dev_wake), "dev_wake != 0");
|
||||
|
|
@ -996,11 +1004,19 @@ EXPORT_SYMBOL(mhi_async_power_up);
|
|||
void mhi_control_error(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
enum MHI_PM_STATE cur_state, transition_state;
|
||||
struct mhi_sfr_info *sfr_info = mhi_cntrl->mhi_sfr;
|
||||
|
||||
MHI_LOG("Enter with pm_state:%s MHI_STATE:%s\n",
|
||||
to_mhi_pm_state_str(mhi_cntrl->pm_state),
|
||||
TO_MHI_STATE_STR(mhi_cntrl->dev_state));
|
||||
|
||||
/* copy subsystem failure reason string if supported */
|
||||
if (sfr_info && sfr_info->buf_addr) {
|
||||
memcpy(sfr_info->str, sfr_info->buf_addr, sfr_info->len);
|
||||
pr_err("mhi: %s sfr: %s\n", mhi_cntrl->name,
|
||||
sfr_info->buf_addr);
|
||||
}
|
||||
|
||||
/* link is not down if device is in RDDM */
|
||||
transition_state = (mhi_cntrl->ee == MHI_EE_RDDM) ?
|
||||
MHI_PM_DEVICE_ERR_DETECT : MHI_PM_LD_ERR_FATAL_DETECT;
|
||||
|
|
@ -1530,6 +1546,7 @@ void mhi_device_get(struct mhi_device *mhi_dev, int vote)
|
|||
if (vote & MHI_VOTE_DEVICE) {
|
||||
read_lock_bh(&mhi_cntrl->pm_lock);
|
||||
mhi_cntrl->wake_get(mhi_cntrl, true);
|
||||
MHI_LOG("dev_wake %d\n", atomic_read(&mhi_cntrl->dev_wake));
|
||||
read_unlock_bh(&mhi_cntrl->pm_lock);
|
||||
atomic_inc(&mhi_dev->dev_vote);
|
||||
}
|
||||
|
|
@ -1583,6 +1600,7 @@ void mhi_device_put(struct mhi_device *mhi_dev, int vote)
|
|||
mhi_trigger_resume(mhi_cntrl);
|
||||
|
||||
mhi_cntrl->wake_put(mhi_cntrl, false);
|
||||
MHI_LOG("dev_wake %d\n", atomic_read(&mhi_cntrl->dev_wake));
|
||||
read_unlock_bh(&mhi_cntrl->pm_lock);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ struct image_info;
|
|||
struct bhi_vec_entry;
|
||||
struct mhi_timesync;
|
||||
struct mhi_buf_info;
|
||||
struct mhi_sfr_info;
|
||||
|
||||
#define REG_WRITE_QUEUE_LEN 1024
|
||||
|
||||
|
|
@ -391,6 +392,10 @@ struct mhi_controller {
|
|||
u64 local_timer_freq;
|
||||
u64 remote_timer_freq;
|
||||
|
||||
/* subsytem failure reason retrieval feature */
|
||||
struct mhi_sfr_info *mhi_sfr;
|
||||
size_t sfr_len;
|
||||
|
||||
/* kernel log level */
|
||||
enum MHI_DEBUG_LEVEL klog_lvl;
|
||||
|
||||
|
|
@ -398,6 +403,7 @@ struct mhi_controller {
|
|||
enum MHI_DEBUG_LEVEL log_lvl;
|
||||
|
||||
/* controller specific data */
|
||||
const char *name;
|
||||
bool power_down;
|
||||
void *priv_data;
|
||||
void *log_buf;
|
||||
|
|
@ -843,6 +849,12 @@ void mhi_control_error(struct mhi_controller *mhi_cntrl);
|
|||
*/
|
||||
void mhi_debug_reg_dump(struct mhi_controller *mhi_cntrl);
|
||||
|
||||
/**
|
||||
* mhi_get_restart_reason - retrieve the subsystem failure reason
|
||||
* @name: controller name
|
||||
*/
|
||||
char *mhi_get_restart_reason(const char *name);
|
||||
|
||||
#ifndef CONFIG_ARCH_QCOM
|
||||
|
||||
#ifdef CONFIG_MHI_DEBUG
|
||||
|
|
|
|||
Loading…
Reference in a new issue