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

Commit 067a1439 authored by Bhaumik Bhatt's avatar Bhaumik Bhatt Committed by Gerrit - the friendly Code Review server
Browse files

mhi: core: provide an API to retrieve device failure reason



When device asserts, the subsystem failure reason from device
can be read via an external API using the name of the MHI
controller.

Change-Id: Ic0bcba77e0a7e4c4a7570df3eda21e1f38b80277
Signed-off-by: default avatarBhaumik Bhatt <bbhatt@codeaurora.org>
parent 886b3174
Loading
Loading
Loading
Loading
+33 −1
Original line number Diff line number Diff line
@@ -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);
@@ -667,6 +680,9 @@ int mhi_init_sfr(struct mhi_controller *mhi_cntrl)
	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) {
@@ -1348,6 +1364,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:
@@ -1495,6 +1513,12 @@ int of_register_mhi_controller(struct mhi_controller *mhi_cntrl)
			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;
	}
@@ -1509,6 +1533,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);

@@ -1527,12 +1554,17 @@ 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);
	kfree(mhi_cntrl->mhi_sfr);

	if (sfr_info) {
		kfree(sfr_info->str);
		kfree(sfr_info);
	}

	device_del(&mhi_dev->dev);
	put_device(&mhi_dev->dev);
+3 −0
Original line number Diff line number Diff line
@@ -734,6 +734,7 @@ 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;
};
@@ -747,6 +748,8 @@ 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_chan_show(struct seq_file *m, void *d);
int mhi_debugfs_mhi_event_show(struct seq_file *m, void *d);
+19 −0
Original line number Diff line number Diff line
@@ -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);

@@ -2691,3 +2693,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);
+5 −2
Original line number Diff line number Diff line
@@ -1008,8 +1008,11 @@ void mhi_control_error(struct mhi_controller *mhi_cntrl)
		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);
	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) ?
+7 −0
Original line number Diff line number Diff line
@@ -404,6 +404,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;
@@ -849,6 +850,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