Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0987399d authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "mhi: core: add support for retrieving device failure reason"

parents a3db6d34 fad0339d
Loading
Loading
Loading
Loading
+46 −0
Original line number Diff line number Diff line
@@ -658,6 +658,39 @@ int mhi_init_timesync(struct mhi_controller *mhi_cntrl)
	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;

	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;
@@ -1313,6 +1346,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)
@@ -1428,6 +1462,17 @@ 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->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;

@@ -1460,6 +1505,7 @@ void mhi_unregister_mhi_controller(struct mhi_controller *mhi_cntrl)
	kfree(mhi_cntrl->mhi_event);
	vfree(mhi_cntrl->mhi_chan);
	kfree(mhi_cntrl->mhi_tsync);
	kfree(mhi_cntrl->mhi_sfr);

	device_del(&mhi_dev->dev);
	put_device(&mhi_dev->dev);
+17 −0
Original line number Diff line number Diff line
@@ -297,6 +297,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 */
@@ -327,6 +328,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)

@@ -365,6 +371,7 @@ enum MHI_CMD {
	MHI_CMD_START_CHAN,
	MHI_CMD_STOP_CHAN,
	MHI_CMD_TIMSYNC_CFG,
	MHI_CMD_SFR_CFG,
};

enum MHI_PKT_TYPE {
@@ -381,6 +388,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 */
};
@@ -716,6 +724,14 @@ struct mhi_timesync {
	struct list_head head;
};

struct mhi_sfr_info {
	void *buf_addr;
	dma_addr_t dma_addr;
	size_t len;
	enum MHI_EV_CCS ccs;
	struct completion completion;
};

struct mhi_bus {
	struct list_head controller_list;
	struct mutex lock;
@@ -812,6 +828,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);
+20 −2
Original line number Diff line number Diff line
@@ -1099,6 +1099,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;

@@ -1109,17 +1110,25 @@ 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);
		mhi_chan = &mhi_cntrl->mhi_chan[chan];
		write_lock_bh(&mhi_chan->lock);
		mhi_chan->ccs = MHI_TRE_GET_EV_CODE(tre);
		complete(&mhi_chan->completion);
		write_unlock_bh(&mhi_chan->lock);
		break;
	}

	mhi_del_ring_element(mhi_cntrl, mhi_ring);
@@ -1657,6 +1666,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",
@@ -1697,6 +1707,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;
	}


+14 −1
Original line number Diff line number Diff line
@@ -512,7 +512,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))
@@ -546,6 +547,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",
@@ -632,6 +634,12 @@ static void mhi_pm_disable_transition(struct mhi_controller *mhi_cntrl,
	flush_work(&mhi_cntrl->fw_worker);
	flush_work(&mhi_cntrl->low_priority_worker);

	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");
@@ -977,11 +985,16 @@ 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)
		pr_err("mhi: sfr: %s\n", 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;
+5 −0
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@ struct image_info;
struct bhi_vec_entry;
struct mhi_timesync;
struct mhi_buf_info;
struct mhi_sfr_info;

/**
 * enum MHI_CB - MHI callback
@@ -366,6 +367,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;