Commit 2d06aec5 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'mhi-for-v6.9' of...

Merge tag 'mhi-for-v6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/mani/mhi into char-misc-next

Manivannan writes:

MHI Host
========

- Added new MHI_PM_SYS_ERR_FAIL state to the MHI state machine to properly
  cleanup the channel state if the device fails to respond to the MHI reset
  during SYS_ERR handling. This issue was discovered with the Qualcomm AIC100 AI
  accelerator device.

- Modified the code that reads and exposes the OEM_PK_HASH registers through
  sysfs to read them on-demand instead of reading once during boot. Qualcomm
  AIC100 devices support provisioning the keys dynamically, so this allows the
  users to know the upto date information.

- Added tracepoint support to expose the debug information over tracefs.

- Reverted the commit that reads the MHI device revision from the device during
  boot. This is done because the read info was not used anywhere (dead code) and
  also it is not possible to read the revision info from all the devices.

- Constified the modem config for Telit FN980 modem as required by the MHI core.

MHI Endpoint
============

- Replaced kzalloc() with kcalloc() in an effort to avoid integer overflows
  during multiplication. Even though there is no potential overflow in the
  endpoint code, this is done for the sake of uniformity and best practice.

- Fixed the kmem_cache_create() failure check to use the correct variable.

* tag 'mhi-for-v6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/mani/mhi:
  bus: mhi: host: pci_generic: constify modem_telit_fn980_hw_v1_config
  bus: mhi: host: Change the trace string for the userspace tools mapping
  bus: mhi: ep: check the correct variable in mhi_ep_register_controller()
  Revert "bus: mhi: core: Add support for reading MHI info from device"
  bus: mhi: host: Add tracing support
  bus: mhi: ep: Use kcalloc() instead of kzalloc()
  bus: mhi: host: Read PK HASH dynamically
  bus: mhi: host: Add MHI_PM_SYS_ERR_FAIL state
parents d4551c18 2ec11b5d
......@@ -297,30 +297,30 @@ struct mhi_ring_element {
__le32 dword[2];
};
#define MHI_STATE_LIST \
mhi_state(RESET, "RESET") \
mhi_state(READY, "READY") \
mhi_state(M0, "M0") \
mhi_state(M1, "M1") \
mhi_state(M2, "M2") \
mhi_state(M3, "M3") \
mhi_state(M3_FAST, "M3_FAST") \
mhi_state(BHI, "BHI") \
mhi_state_end(SYS_ERR, "SYS ERROR")
#undef mhi_state
#undef mhi_state_end
#define mhi_state(a, b) case MHI_STATE_##a: return b;
#define mhi_state_end(a, b) case MHI_STATE_##a: return b;
static inline const char *mhi_state_str(enum mhi_state state)
{
switch (state) {
case MHI_STATE_RESET:
return "RESET";
case MHI_STATE_READY:
return "READY";
case MHI_STATE_M0:
return "M0";
case MHI_STATE_M1:
return "M1";
case MHI_STATE_M2:
return "M2";
case MHI_STATE_M3:
return "M3";
case MHI_STATE_M3_FAST:
return "M3 FAST";
case MHI_STATE_BHI:
return "BHI";
case MHI_STATE_SYS_ERR:
return "SYS ERROR";
MHI_STATE_LIST
default:
return "Unknown state";
}
};
}
#endif /* _MHI_COMMON_H */
......@@ -1149,8 +1149,9 @@ int mhi_ep_power_up(struct mhi_ep_cntrl *mhi_cntrl)
mhi_ep_mmio_mask_interrupts(mhi_cntrl);
mhi_ep_mmio_init(mhi_cntrl);
mhi_cntrl->mhi_event = kzalloc(mhi_cntrl->event_rings * (sizeof(*mhi_cntrl->mhi_event)),
GFP_KERNEL);
mhi_cntrl->mhi_event = kcalloc(mhi_cntrl->event_rings,
sizeof(*mhi_cntrl->mhi_event),
GFP_KERNEL);
if (!mhi_cntrl->mhi_event)
return -ENOMEM;
......@@ -1496,7 +1497,7 @@ int mhi_ep_register_controller(struct mhi_ep_cntrl *mhi_cntrl,
mhi_cntrl->ring_item_cache = kmem_cache_create("mhi_ep_ring_item",
sizeof(struct mhi_ep_ring_item), 0,
0, NULL);
if (!mhi_cntrl->ev_ring_el_cache) {
if (!mhi_cntrl->ring_item_cache) {
ret = -ENOMEM;
goto err_destroy_tre_buf_cache;
}
......
......@@ -395,7 +395,7 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl)
void *buf;
dma_addr_t dma_addr;
size_t size, fw_sz;
int i, ret;
int ret;
if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) {
dev_err(dev, "Device MHI is not in valid state\n");
......@@ -408,15 +408,6 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl)
if (ret)
dev_err(dev, "Could not capture serial number via BHI\n");
for (i = 0; i < ARRAY_SIZE(mhi_cntrl->oem_pk_hash); i++) {
ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->bhi, BHI_OEMPKHASH(i),
&mhi_cntrl->oem_pk_hash[i]);
if (ret) {
dev_err(dev, "Could not capture OEM PK HASH via BHI\n");
break;
}
}
/* wait for ready on pass through or any other execution environment */
if (!MHI_FW_LOAD_CAPABLE(mhi_cntrl->ee))
goto fw_load_ready_state;
......
......@@ -20,50 +20,49 @@
#include <linux/wait.h>
#include "internal.h"
#define CREATE_TRACE_POINTS
#include "trace.h"
static DEFINE_IDA(mhi_controller_ida);
#undef mhi_ee
#undef mhi_ee_end
#define mhi_ee(a, b) [MHI_EE_##a] = b,
#define mhi_ee_end(a, b) [MHI_EE_##a] = b,
const char * const mhi_ee_str[MHI_EE_MAX] = {
[MHI_EE_PBL] = "PRIMARY BOOTLOADER",
[MHI_EE_SBL] = "SECONDARY BOOTLOADER",
[MHI_EE_AMSS] = "MISSION MODE",
[MHI_EE_RDDM] = "RAMDUMP DOWNLOAD MODE",
[MHI_EE_WFW] = "WLAN FIRMWARE",
[MHI_EE_PTHRU] = "PASS THROUGH",
[MHI_EE_EDL] = "EMERGENCY DOWNLOAD",
[MHI_EE_FP] = "FLASH PROGRAMMER",
[MHI_EE_DISABLE_TRANSITION] = "DISABLE",
[MHI_EE_NOT_SUPPORTED] = "NOT SUPPORTED",
MHI_EE_LIST
};
#undef dev_st_trans
#undef dev_st_trans_end
#define dev_st_trans(a, b) [DEV_ST_TRANSITION_##a] = b,
#define dev_st_trans_end(a, b) [DEV_ST_TRANSITION_##a] = b,
const char * const dev_state_tran_str[DEV_ST_TRANSITION_MAX] = {
[DEV_ST_TRANSITION_PBL] = "PBL",
[DEV_ST_TRANSITION_READY] = "READY",
[DEV_ST_TRANSITION_SBL] = "SBL",
[DEV_ST_TRANSITION_MISSION_MODE] = "MISSION MODE",
[DEV_ST_TRANSITION_FP] = "FLASH PROGRAMMER",
[DEV_ST_TRANSITION_SYS_ERR] = "SYS ERROR",
[DEV_ST_TRANSITION_DISABLE] = "DISABLE",
DEV_ST_TRANSITION_LIST
};
#undef ch_state_type
#undef ch_state_type_end
#define ch_state_type(a, b) [MHI_CH_STATE_TYPE_##a] = b,
#define ch_state_type_end(a, b) [MHI_CH_STATE_TYPE_##a] = b,
const char * const mhi_ch_state_type_str[MHI_CH_STATE_TYPE_MAX] = {
[MHI_CH_STATE_TYPE_RESET] = "RESET",
[MHI_CH_STATE_TYPE_STOP] = "STOP",
[MHI_CH_STATE_TYPE_START] = "START",
MHI_CH_STATE_TYPE_LIST
};
#undef mhi_pm_state
#undef mhi_pm_state_end
#define mhi_pm_state(a, b) [MHI_PM_STATE_##a] = b,
#define mhi_pm_state_end(a, b) [MHI_PM_STATE_##a] = b,
static const char * const mhi_pm_state_str[] = {
[MHI_PM_STATE_DISABLE] = "DISABLE",
[MHI_PM_STATE_POR] = "POWER ON RESET",
[MHI_PM_STATE_M0] = "M0",
[MHI_PM_STATE_M2] = "M2",
[MHI_PM_STATE_M3_ENTER] = "M?->M3",
[MHI_PM_STATE_M3] = "M3",
[MHI_PM_STATE_M3_EXIT] = "M3->M0",
[MHI_PM_STATE_FW_DL_ERR] = "Firmware Download Error",
[MHI_PM_STATE_SYS_ERR_DETECT] = "SYS ERROR Detect",
[MHI_PM_STATE_SYS_ERR_PROCESS] = "SYS ERROR Process",
[MHI_PM_STATE_SHUTDOWN_PROCESS] = "SHUTDOWN Process",
[MHI_PM_STATE_LD_ERR_FATAL_DETECT] = "Linkdown or Error Fatal Detect",
MHI_PM_STATE_LIST
};
const char *to_mhi_pm_state_str(u32 state)
......@@ -97,11 +96,19 @@ static ssize_t oem_pk_hash_show(struct device *dev,
{
struct mhi_device *mhi_dev = to_mhi_device(dev);
struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
int i, cnt = 0;
u32 hash_segment[MHI_MAX_OEM_PK_HASH_SEGMENTS];
int i, cnt = 0, ret;
for (i = 0; i < ARRAY_SIZE(mhi_cntrl->oem_pk_hash); i++)
cnt += sysfs_emit_at(buf, cnt, "OEMPKHASH[%d]: 0x%x\n",
i, mhi_cntrl->oem_pk_hash[i]);
for (i = 0; i < MHI_MAX_OEM_PK_HASH_SEGMENTS; i++) {
ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->bhi, BHI_OEMPKHASH(i), &hash_segment[i]);
if (ret) {
dev_err(dev, "Could not capture OEM PK HASH\n");
return ret;
}
}
for (i = 0; i < MHI_MAX_OEM_PK_HASH_SEGMENTS; i++)
cnt += sysfs_emit_at(buf, cnt, "OEMPKHASH[%d]: 0x%x\n", i, hash_segment[i]);
return cnt;
}
......@@ -907,7 +914,6 @@ int mhi_register_controller(struct mhi_controller *mhi_cntrl,
struct mhi_chan *mhi_chan;
struct mhi_cmd *mhi_cmd;
struct mhi_device *mhi_dev;
u32 soc_info;
int ret, i;
if (!mhi_cntrl || !mhi_cntrl->cntrl_dev || !mhi_cntrl->regs ||
......@@ -982,17 +988,6 @@ int mhi_register_controller(struct mhi_controller *mhi_cntrl,
mhi_cntrl->unmap_single = mhi_unmap_single_no_bb;
}
/* Read the MHI device info */
ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->regs,
SOC_HW_VERSION_OFFS, &soc_info);
if (ret)
goto err_destroy_wq;
mhi_cntrl->family_number = FIELD_GET(SOC_HW_VERSION_FAM_NUM_BMSK, soc_info);
mhi_cntrl->device_number = FIELD_GET(SOC_HW_VERSION_DEV_NUM_BMSK, soc_info);
mhi_cntrl->major_version = FIELD_GET(SOC_HW_VERSION_MAJOR_VER_BMSK, soc_info);
mhi_cntrl->minor_version = FIELD_GET(SOC_HW_VERSION_MINOR_VER_BMSK, soc_info);
mhi_cntrl->index = ida_alloc(&mhi_controller_ida, GFP_KERNEL);
if (mhi_cntrl->index < 0) {
ret = mhi_cntrl->index;
......
......@@ -15,12 +15,6 @@ extern struct bus_type mhi_bus_type;
#define MHI_SOC_RESET_REQ_OFFSET 0xb0
#define MHI_SOC_RESET_REQ BIT(0)
#define SOC_HW_VERSION_OFFS 0x224
#define SOC_HW_VERSION_FAM_NUM_BMSK GENMASK(31, 28)
#define SOC_HW_VERSION_DEV_NUM_BMSK GENMASK(27, 16)
#define SOC_HW_VERSION_MAJOR_VER_BMSK GENMASK(15, 8)
#define SOC_HW_VERSION_MINOR_VER_BMSK GENMASK(7, 0)
struct mhi_ctxt {
struct mhi_event_ctxt *er_ctxt;
struct mhi_chan_ctxt *chan_ctxt;
......@@ -42,6 +36,11 @@ enum mhi_ch_state_type {
MHI_CH_STATE_TYPE_MAX,
};
#define MHI_CH_STATE_TYPE_LIST \
ch_state_type(RESET, "RESET") \
ch_state_type(STOP, "STOP") \
ch_state_type_end(START, "START")
extern const char * const mhi_ch_state_type_str[MHI_CH_STATE_TYPE_MAX];
#define TO_CH_STATE_TYPE_STR(state) (((state) >= MHI_CH_STATE_TYPE_MAX) ? \
"INVALID_STATE" : \
......@@ -50,6 +49,18 @@ extern const char * const mhi_ch_state_type_str[MHI_CH_STATE_TYPE_MAX];
#define MHI_INVALID_BRSTMODE(mode) (mode != MHI_DB_BRST_DISABLE && \
mode != MHI_DB_BRST_ENABLE)
#define MHI_EE_LIST \
mhi_ee(PBL, "PRIMARY BOOTLOADER") \
mhi_ee(SBL, "SECONDARY BOOTLOADER") \
mhi_ee(AMSS, "MISSION MODE") \
mhi_ee(RDDM, "RAMDUMP DOWNLOAD MODE")\
mhi_ee(WFW, "WLAN FIRMWARE") \
mhi_ee(PTHRU, "PASS THROUGH") \
mhi_ee(EDL, "EMERGENCY DOWNLOAD") \
mhi_ee(FP, "FLASH PROGRAMMER") \
mhi_ee(DISABLE_TRANSITION, "DISABLE") \
mhi_ee_end(NOT_SUPPORTED, "NOT SUPPORTED")
extern const char * const mhi_ee_str[MHI_EE_MAX];
#define TO_MHI_EXEC_STR(ee) (((ee) >= MHI_EE_MAX) ? \
"INVALID_EE" : mhi_ee_str[ee])
......@@ -72,6 +83,15 @@ enum dev_st_transition {
DEV_ST_TRANSITION_MAX,
};
#define DEV_ST_TRANSITION_LIST \
dev_st_trans(PBL, "PBL") \
dev_st_trans(READY, "READY") \
dev_st_trans(SBL, "SBL") \
dev_st_trans(MISSION_MODE, "MISSION MODE") \
dev_st_trans(FP, "FLASH PROGRAMMER") \
dev_st_trans(SYS_ERR, "SYS ERROR") \
dev_st_trans_end(DISABLE, "DISABLE")
extern const char * const dev_state_tran_str[DEV_ST_TRANSITION_MAX];
#define TO_DEV_STATE_TRANS_STR(state) (((state) >= DEV_ST_TRANSITION_MAX) ? \
"INVALID_STATE" : dev_state_tran_str[state])
......@@ -88,11 +108,27 @@ enum mhi_pm_state {
MHI_PM_STATE_FW_DL_ERR,
MHI_PM_STATE_SYS_ERR_DETECT,
MHI_PM_STATE_SYS_ERR_PROCESS,
MHI_PM_STATE_SYS_ERR_FAIL,
MHI_PM_STATE_SHUTDOWN_PROCESS,
MHI_PM_STATE_LD_ERR_FATAL_DETECT,
MHI_PM_STATE_MAX
};
#define MHI_PM_STATE_LIST \
mhi_pm_state(DISABLE, "DISABLE") \
mhi_pm_state(POR, "POWER ON RESET") \
mhi_pm_state(M0, "M0") \
mhi_pm_state(M2, "M2") \
mhi_pm_state(M3_ENTER, "M?->M3") \
mhi_pm_state(M3, "M3") \
mhi_pm_state(M3_EXIT, "M3->M0") \
mhi_pm_state(FW_DL_ERR, "Firmware Download Error") \
mhi_pm_state(SYS_ERR_DETECT, "SYS ERROR Detect") \
mhi_pm_state(SYS_ERR_PROCESS, "SYS ERROR Process") \
mhi_pm_state(SYS_ERR_FAIL, "SYS ERROR Failure") \
mhi_pm_state(SHUTDOWN_PROCESS, "SHUTDOWN Process") \
mhi_pm_state_end(LD_ERR_FATAL_DETECT, "Linkdown or Error Fatal Detect")
#define MHI_PM_DISABLE BIT(0)
#define MHI_PM_POR BIT(1)
#define MHI_PM_M0 BIT(2)
......@@ -104,14 +140,16 @@ enum mhi_pm_state {
#define MHI_PM_FW_DL_ERR BIT(7)
#define MHI_PM_SYS_ERR_DETECT BIT(8)
#define MHI_PM_SYS_ERR_PROCESS BIT(9)
#define MHI_PM_SHUTDOWN_PROCESS BIT(10)
#define MHI_PM_SYS_ERR_FAIL BIT(10)
#define MHI_PM_SHUTDOWN_PROCESS BIT(11)
/* link not accessible */
#define MHI_PM_LD_ERR_FATAL_DETECT BIT(11)
#define MHI_PM_LD_ERR_FATAL_DETECT BIT(12)
#define MHI_REG_ACCESS_VALID(pm_state) ((pm_state & (MHI_PM_POR | MHI_PM_M0 | \
MHI_PM_M2 | MHI_PM_M3_ENTER | MHI_PM_M3_EXIT | \
MHI_PM_SYS_ERR_DETECT | MHI_PM_SYS_ERR_PROCESS | \
MHI_PM_SHUTDOWN_PROCESS | MHI_PM_FW_DL_ERR)))
MHI_PM_SYS_ERR_FAIL | MHI_PM_SHUTDOWN_PROCESS | \
MHI_PM_FW_DL_ERR)))
#define MHI_PM_IN_ERROR_STATE(pm_state) (pm_state >= MHI_PM_FW_DL_ERR)
#define MHI_PM_IN_FATAL_STATE(pm_state) (pm_state == MHI_PM_LD_ERR_FATAL_DETECT)
#define MHI_DB_ACCESS_VALID(mhi_cntrl) (mhi_cntrl->pm_state & mhi_cntrl->db_access)
......
......@@ -15,6 +15,7 @@
#include <linux/skbuff.h>
#include <linux/slab.h>
#include "internal.h"
#include "trace.h"
int __must_check mhi_read_reg(struct mhi_controller *mhi_cntrl,
void __iomem *base, u32 offset, u32 *out)
......@@ -493,11 +494,8 @@ irqreturn_t mhi_intvec_threaded_handler(int irq_number, void *priv)
state = mhi_get_mhi_state(mhi_cntrl);
ee = mhi_get_exec_env(mhi_cntrl);
dev_dbg(dev, "local ee: %s state: %s device ee: %s state: %s\n",
TO_MHI_EXEC_STR(mhi_cntrl->ee),
mhi_state_str(mhi_cntrl->dev_state),
TO_MHI_EXEC_STR(ee), mhi_state_str(state));
trace_mhi_intvec_states(mhi_cntrl, ee, state);
if (state == MHI_STATE_SYS_ERR) {
dev_dbg(dev, "System error detected\n");
pm_state = mhi_tryset_pm_state(mhi_cntrl,
......@@ -838,6 +836,8 @@ int mhi_process_ctrl_ev_ring(struct mhi_controller *mhi_cntrl,
while (dev_rp != local_rp) {
enum mhi_pkt_type type = MHI_TRE_GET_EV_TYPE(local_rp);
trace_mhi_ctrl_event(mhi_cntrl, local_rp);
switch (type) {
case MHI_PKT_TYPE_BW_REQ_EVENT:
{
......@@ -1003,6 +1003,8 @@ int mhi_process_data_event_ring(struct mhi_controller *mhi_cntrl,
while (dev_rp != local_rp && event_quota > 0) {
enum mhi_pkt_type type = MHI_TRE_GET_EV_TYPE(local_rp);
trace_mhi_data_event(mhi_cntrl, local_rp);
chan = MHI_TRE_GET_EV_CHID(local_rp);
WARN_ON(chan >= mhi_cntrl->max_chan);
......@@ -1243,6 +1245,7 @@ int mhi_gen_tre(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan,
mhi_tre->dword[0] = MHI_TRE_DATA_DWORD0(info->len);
mhi_tre->dword[1] = MHI_TRE_DATA_DWORD1(bei, eot, eob, chain);
trace_mhi_gen_tre(mhi_cntrl, mhi_chan, mhi_tre);
/* increment WP */
mhi_add_ring_element(mhi_cntrl, tre_ring);
mhi_add_ring_element(mhi_cntrl, buf_ring);
......@@ -1337,9 +1340,7 @@ static int mhi_update_channel_state(struct mhi_controller *mhi_cntrl,
enum mhi_cmd_type cmd = MHI_CMD_NOP;
int ret;
dev_dbg(dev, "%d: Updating channel state to: %s\n", mhi_chan->chan,
TO_CH_STATE_TYPE_STR(to_state));
trace_mhi_channel_command_start(mhi_cntrl, mhi_chan, to_state, TPS("Updating"));
switch (to_state) {
case MHI_CH_STATE_TYPE_RESET:
write_lock_irq(&mhi_chan->lock);
......@@ -1406,9 +1407,7 @@ static int mhi_update_channel_state(struct mhi_controller *mhi_cntrl,
write_unlock_irq(&mhi_chan->lock);
}
dev_dbg(dev, "%d: Channel state change to %s successful\n",
mhi_chan->chan, TO_CH_STATE_TYPE_STR(to_state));
trace_mhi_channel_command_end(mhi_cntrl, mhi_chan, to_state, TPS("Updated"));
exit_channel_update:
mhi_cntrl->runtime_put(mhi_cntrl);
mhi_device_put(mhi_cntrl->mhi_dev);
......
......@@ -538,7 +538,7 @@ static struct mhi_event_config mhi_telit_fn980_hw_v1_events[] = {
MHI_EVENT_CONFIG_HW_DATA(2, 2048, 101)
};
static struct mhi_controller_config modem_telit_fn980_hw_v1_config = {
static const struct mhi_controller_config modem_telit_fn980_hw_v1_config = {
.max_channels = 128,
.timeout_ms = 20000,
.num_channels = ARRAY_SIZE(mhi_telit_fn980_hw_v1_channels),
......
......@@ -15,6 +15,7 @@
#include <linux/slab.h>
#include <linux/wait.h>
#include "internal.h"
#include "trace.h"
/*
* Not all MHI state transitions are synchronous. Transitions like Linkdown,
......@@ -36,7 +37,10 @@
* M0 <--> M0
* M0 -> FW_DL_ERR
* M0 -> M3_ENTER -> M3 -> M3_EXIT --> M0
* L1: SYS_ERR_DETECT -> SYS_ERR_PROCESS --> POR
* L1: SYS_ERR_DETECT -> SYS_ERR_PROCESS
* SYS_ERR_PROCESS -> SYS_ERR_FAIL
* SYS_ERR_FAIL -> SYS_ERR_DETECT
* SYS_ERR_PROCESS --> POR
* L2: SHUTDOWN_PROCESS -> LD_ERR_FATAL_DETECT
* SHUTDOWN_PROCESS -> DISABLE
* L3: LD_ERR_FATAL_DETECT <--> LD_ERR_FATAL_DETECT
......@@ -93,7 +97,12 @@ static const struct mhi_pm_transitions dev_state_transitions[] = {
},
{
MHI_PM_SYS_ERR_PROCESS,
MHI_PM_POR | MHI_PM_SHUTDOWN_PROCESS |
MHI_PM_POR | MHI_PM_SYS_ERR_FAIL | MHI_PM_SHUTDOWN_PROCESS |
MHI_PM_LD_ERR_FATAL_DETECT
},
{
MHI_PM_SYS_ERR_FAIL,
MHI_PM_SYS_ERR_DETECT | MHI_PM_SHUTDOWN_PROCESS |
MHI_PM_LD_ERR_FATAL_DETECT
},
/* L2 States */
......@@ -123,6 +132,7 @@ enum mhi_pm_state __must_check mhi_tryset_pm_state(struct mhi_controller *mhi_cn
if (unlikely(!(dev_state_transitions[index].to_states & state)))
return cur_state;
trace_mhi_tryset_pm_state(mhi_cntrl, state);
mhi_cntrl->pm_state = state;
return mhi_cntrl->pm_state;
}
......@@ -629,7 +639,13 @@ static void mhi_pm_sys_error_transition(struct mhi_controller *mhi_cntrl)
!in_reset, timeout);
if (!ret || in_reset) {
dev_err(dev, "Device failed to exit MHI Reset state\n");
goto exit_sys_error_transition;
write_lock_irq(&mhi_cntrl->pm_lock);
cur_state = mhi_tryset_pm_state(mhi_cntrl,
MHI_PM_SYS_ERR_FAIL);
write_unlock_irq(&mhi_cntrl->pm_lock);
/* Shutdown may have occurred, otherwise cleanup now */
if (cur_state != MHI_PM_SYS_ERR_FAIL)
goto exit_sys_error_transition;
}
/*
......@@ -758,7 +774,6 @@ void mhi_pm_st_worker(struct work_struct *work)
struct mhi_controller *mhi_cntrl = container_of(work,
struct mhi_controller,
st_worker);
struct device *dev = &mhi_cntrl->mhi_dev->dev;
spin_lock_irq(&mhi_cntrl->transition_lock);
list_splice_tail_init(&mhi_cntrl->transition_list, &head);
......@@ -766,8 +781,8 @@ void mhi_pm_st_worker(struct work_struct *work)
list_for_each_entry_safe(itr, tmp, &head, node) {
list_del(&itr->node);
dev_dbg(dev, "Handling state transition: %s\n",
TO_DEV_STATE_TRANS_STR(itr->state));
trace_mhi_pm_st_transition(mhi_cntrl, itr->state);
switch (itr->state) {
case DEV_ST_TRANSITION_PBL:
......
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#undef TRACE_SYSTEM
#define TRACE_SYSTEM mhi_host
#if !defined(_TRACE_EVENT_MHI_HOST_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_EVENT_MHI_HOST_H
#include <linux/tracepoint.h>
#include <linux/trace_seq.h>
#include "../common.h"
#include "internal.h"
#undef mhi_state
#undef mhi_state_end
#define mhi_state(a, b) TRACE_DEFINE_ENUM(MHI_STATE_##a);
#define mhi_state_end(a, b) TRACE_DEFINE_ENUM(MHI_STATE_##a);
MHI_STATE_LIST
#undef mhi_state
#undef mhi_state_end
#define mhi_state(a, b) { MHI_STATE_##a, b },
#define mhi_state_end(a, b) { MHI_STATE_##a, b }
#undef mhi_pm_state
#undef mhi_pm_state_end
#define mhi_pm_state(a, b) TRACE_DEFINE_ENUM(MHI_PM_STATE_##a);
#define mhi_pm_state_end(a, b) TRACE_DEFINE_ENUM(MHI_PM_STATE_##a);
MHI_PM_STATE_LIST
#undef mhi_pm_state
#undef mhi_pm_state_end
#define mhi_pm_state(a, b) { MHI_PM_STATE_##a, b },
#define mhi_pm_state_end(a, b) { MHI_PM_STATE_##a, b }
#undef mhi_ee
#undef mhi_ee_end
#define mhi_ee(a, b) TRACE_DEFINE_ENUM(MHI_EE_##a);
#define mhi_ee_end(a, b) TRACE_DEFINE_ENUM(MHI_EE_##a);
MHI_EE_LIST
#undef mhi_ee
#undef mhi_ee_end
#define mhi_ee(a, b) { MHI_EE_##a, b },
#define mhi_ee_end(a, b) { MHI_EE_##a, b }
#undef ch_state_type
#undef ch_state_type_end
#define ch_state_type(a, b) TRACE_DEFINE_ENUM(MHI_CH_STATE_TYPE_##a);
#define ch_state_type_end(a, b) TRACE_DEFINE_ENUM(MHI_CH_STATE_TYPE_##a);
MHI_CH_STATE_TYPE_LIST
#undef ch_state_type
#undef ch_state_type_end
#define ch_state_type(a, b) { MHI_CH_STATE_TYPE_##a, b },
#define ch_state_type_end(a, b) { MHI_CH_STATE_TYPE_##a, b }
#undef dev_st_trans
#undef dev_st_trans_end
#define dev_st_trans(a, b) TRACE_DEFINE_ENUM(DEV_ST_TRANSITION_##a);
#define dev_st_trans_end(a, b) TRACE_DEFINE_ENUM(DEV_ST_TRANSITION_##a);
DEV_ST_TRANSITION_LIST
#undef dev_st_trans
#undef dev_st_trans_end
#define dev_st_trans(a, b) { DEV_ST_TRANSITION_##a, b },
#define dev_st_trans_end(a, b) { DEV_ST_TRANSITION_##a, b }
#define TPS(x) tracepoint_string(x)
TRACE_EVENT(mhi_gen_tre,
TP_PROTO(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan,
struct mhi_ring_element *mhi_tre),
TP_ARGS(mhi_cntrl, mhi_chan, mhi_tre),
TP_STRUCT__entry(
__string(name, mhi_cntrl->mhi_dev->name)
__field(int, ch_num)
__field(void *, wp)
__field(__le64, tre_ptr)
__field(__le32, dword0)
__field(__le32, dword1)
),
TP_fast_assign(
__assign_str(name, mhi_cntrl->mhi_dev->name);
__entry->ch_num = mhi_chan->chan;
__entry->wp = mhi_tre;
__entry->tre_ptr = mhi_tre->ptr;
__entry->dword0 = mhi_tre->dword[0];
__entry->dword1 = mhi_tre->dword[1];
),
TP_printk("%s: Chan: %d TRE: 0x%p TRE buf: 0x%llx DWORD0: 0x%08x DWORD1: 0x%08x\n",
__get_str(name), __entry->ch_num, __entry->wp, __entry->tre_ptr,
__entry->dword0, __entry->dword1)
);
TRACE_EVENT(mhi_intvec_states,
TP_PROTO(struct mhi_controller *mhi_cntrl, int dev_ee, int dev_state),
TP_ARGS(mhi_cntrl, dev_ee, dev_state),
TP_STRUCT__entry(
__string(name, mhi_cntrl->mhi_dev->name)
__field(int, local_ee)
__field(int, state)
__field(int, dev_ee)
__field(int, dev_state)
),
TP_fast_assign(
__assign_str(name, mhi_cntrl->mhi_dev->name);
__entry->local_ee = mhi_cntrl->ee;
__entry->state = mhi_cntrl->dev_state;
__entry->dev_ee = dev_ee;
__entry->dev_state = dev_state;
),
TP_printk("%s: Local EE: %s State: %s Device EE: %s Dev State: %s\n",
__get_str(name),
__print_symbolic(__entry->local_ee, MHI_EE_LIST),
__print_symbolic(__entry->state, MHI_STATE_LIST),
__print_symbolic(__entry->dev_ee, MHI_EE_LIST),
__print_symbolic(__entry->dev_state, MHI_STATE_LIST))
);
TRACE_EVENT(mhi_tryset_pm_state,
TP_PROTO(struct mhi_controller *mhi_cntrl, int pm_state),
TP_ARGS(mhi_cntrl, pm_state),
TP_STRUCT__entry(
__string(name, mhi_cntrl->mhi_dev->name)
__field(int, pm_state)
),
TP_fast_assign(
__assign_str(name, mhi_cntrl->mhi_dev->name);
if (pm_state)
pm_state = __fls(pm_state);
__entry->pm_state = pm_state;
),
TP_printk("%s: PM state: %s\n", __get_str(name),
__print_symbolic(__entry->pm_state, MHI_PM_STATE_LIST))
);
DECLARE_EVENT_CLASS(mhi_process_event_ring,
TP_PROTO(struct mhi_controller *mhi_cntrl, struct mhi_ring_element *rp),
TP_ARGS(mhi_cntrl, rp),
TP_STRUCT__entry(
__string(name, mhi_cntrl->mhi_dev->name)
__field(__le32, dword0)
__field(__le32, dword1)
__field(int, state)
__field(__le64, ptr)
__field(void *, rp)
),
TP_fast_assign(
__assign_str(name, mhi_cntrl->mhi_dev->name);
__entry->rp = rp;
__entry->ptr = rp->ptr;
__entry->dword0 = rp->dword[0];
__entry->dword1 = rp->dword[1];
__entry->state = MHI_TRE_GET_EV_STATE(rp);
),
TP_printk("%s: TRE: 0x%p TRE buf: 0x%llx DWORD0: 0x%08x DWORD1: 0x%08x State: %s\n",
__get_str(name), __entry->rp, __entry->ptr, __entry->dword0,
__entry->dword1, __print_symbolic(__entry->state, MHI_STATE_LIST))
);
DEFINE_EVENT(mhi_process_event_ring, mhi_data_event,
TP_PROTO(struct mhi_controller *mhi_cntrl, struct mhi_ring_element *rp),
TP_ARGS(mhi_cntrl, rp)
);
DEFINE_EVENT(mhi_process_event_ring, mhi_ctrl_event,
TP_PROTO(struct mhi_controller *mhi_cntrl, struct mhi_ring_element *rp),
TP_ARGS(mhi_cntrl, rp)
);
DECLARE_EVENT_CLASS(mhi_update_channel_state,
TP_PROTO(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan, int state,
const char *reason),
TP_ARGS(mhi_cntrl, mhi_chan, state, reason),
TP_STRUCT__entry(
__string(name, mhi_cntrl->mhi_dev->name)
__field(int, ch_num)
__field(int, state)
__field(const char *, reason)
),
TP_fast_assign(
__assign_str(name, mhi_cntrl->mhi_dev->name);
__entry->ch_num = mhi_chan->chan;
__entry->state = state;
__entry->reason = reason;
),
TP_printk("%s: chan%d: %s state to: %s\n",
__get_str(name), __entry->ch_num, __entry->reason,
__print_symbolic(__entry->state, MHI_CH_STATE_TYPE_LIST))
);
DEFINE_EVENT(mhi_update_channel_state, mhi_channel_command_start,
TP_PROTO(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan, int state,
const char *reason),
TP_ARGS(mhi_cntrl, mhi_chan, state, reason)
);
DEFINE_EVENT(mhi_update_channel_state, mhi_channel_command_end,
TP_PROTO(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan, int state,
const char *reason),
TP_ARGS(mhi_cntrl, mhi_chan, state, reason)
);
TRACE_EVENT(mhi_pm_st_transition,
TP_PROTO(struct mhi_controller *mhi_cntrl, int state),
TP_ARGS(mhi_cntrl, state),
TP_STRUCT__entry(
__string(name, mhi_cntrl->mhi_dev->name)
__field(int, state)
),
TP_fast_assign(
__assign_str(name, mhi_cntrl->mhi_dev->name);
__entry->state = state;
),
TP_printk("%s: Handling state transition: %s\n", __get_str(name),
__print_symbolic(__entry->state, DEV_ST_TRANSITION_LIST))
);
#endif
#undef TRACE_INCLUDE_PATH
#define TRACE_INCLUDE_PATH ../../drivers/bus/mhi/host
#undef TRACE_INCLUDE_FILE
#define TRACE_INCLUDE_FILE trace
#include <trace/define_trace.h>
......@@ -320,12 +320,7 @@ struct mhi_controller_config {
* @hw_ev_rings: Number of hardware event rings
* @sw_ev_rings: Number of software event rings
* @nr_irqs: Number of IRQ allocated by bus master (required)
* @family_number: MHI controller family number
* @device_number: MHI controller device number
* @major_version: MHI controller major revision number
* @minor_version: MHI controller minor revision number
* @serial_number: MHI controller serial number obtained from BHI
* @oem_pk_hash: MHI controller OEM PK Hash obtained from BHI
* @mhi_event: MHI event ring configurations table
* @mhi_cmd: MHI command ring configurations table
* @mhi_ctxt: MHI device context, shared memory between host and device
......@@ -369,15 +364,6 @@ struct mhi_controller_config {
* Fields marked as (required) need to be populated by the controller driver
* before calling mhi_register_controller(). For the fields marked as (optional)
* they can be populated depending on the usecase.
*
* The following fields are present for the purpose of implementing any device
* specific quirks or customizations for specific MHI revisions used in device
* by the controller drivers. The MHI stack will just populate these fields
* during mhi_register_controller():
* family_number
* device_number
* major_version
* minor_version
*/
struct mhi_controller {
struct device *cntrl_dev;
......@@ -408,12 +394,7 @@ struct mhi_controller {
u32 hw_ev_rings;
u32 sw_ev_rings;
u32 nr_irqs;
u32 family_number;
u32 device_number;
u32 major_version;
u32 minor_version;
u32 serial_number;
u32 oem_pk_hash[MHI_MAX_OEM_PK_HASH_SEGMENTS];
struct mhi_event *mhi_event;
struct mhi_cmd *mhi_cmd;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment