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

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

Merge "mhi: cntrl: qcom: register for early error fatal notification"

parents e991d514 f4bc18cf
Loading
Loading
Loading
Loading
+38 −0
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ struct arch_info {
	struct dma_iommu_mapping *mapping;
	async_cookie_t cookie;
	void *boot_ipc_log;
	void *tsync_ipc_log;
	struct mhi_device *boot_dev;
	struct mhi_link_info current_link_info;
	struct work_struct bw_scale_work;
@@ -50,6 +51,8 @@ struct arch_info {
#define DLOG "Dev->Host: "
#define HLOG "Host: "

#define MHI_TSYNC_LOG_PAGES (10)

#ifdef CONFIG_MHI_DEBUG

#define MHI_IPC_LOG_PAGES (100)
@@ -81,6 +84,19 @@ static int mhi_arch_pm_notifier(struct notifier_block *nb,
	return NOTIFY_DONE;
}

static void mhi_arch_timesync_log(struct mhi_controller *mhi_cntrl,
				  u64 remote_time)
{
	struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
	struct arch_info *arch_info = mhi_dev->arch_info;

	if (remote_time != U64_MAX)
		ipc_log_string(arch_info->tsync_ipc_log, "%6u.%06lu 0x%llx",
			       REMOTE_TICKS_TO_SEC(remote_time),
			       REMOTE_TIME_REMAINDER_US(remote_time),
			       remote_time);
}

static int mhi_arch_set_bus_request(struct mhi_controller *mhi_cntrl, int index)
{
	struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
@@ -228,6 +244,18 @@ static void mhi_arch_esoc_ops_power_off(void *priv, unsigned int flags)
	pm_relax(&mhi_cntrl->mhi_dev->dev);
}

static void mhi_arch_esoc_ops_mdm_error(void *priv)
{
	struct mhi_controller *mhi_cntrl = priv;

	MHI_LOG("Enter: mdm asserted\n");

	/* transition MHI state into error state */
	mhi_control_error(mhi_cntrl);

	MHI_LOG("Exit\n");
}

static void mhi_bl_dl_cb(struct mhi_device *mhi_device,
			 struct mhi_result *mhi_result)
{
@@ -431,6 +459,14 @@ int mhi_arch_pcie_init(struct mhi_controller *mhi_cntrl)
							    node, 0);
		mhi_cntrl->log_lvl = mhi_ipc_log_lvl;

		snprintf(node, sizeof(node), "mhi_tsync_%04x_%02u.%02u.%02u",
			 mhi_cntrl->dev_id, mhi_cntrl->domain, mhi_cntrl->bus,
			 mhi_cntrl->slot);
		arch_info->tsync_ipc_log = ipc_log_context_create(
					   MHI_TSYNC_LOG_PAGES, node, 0);
		if (arch_info->tsync_ipc_log)
			mhi_cntrl->tsync_log = mhi_arch_timesync_log;

		/* register for bus scale if defined */
		arch_info->msm_bus_pdata = msm_bus_cl_get_pdata_from_dev(
							&mhi_dev->pci_dev->dev);
@@ -481,6 +517,8 @@ int mhi_arch_pcie_init(struct mhi_controller *mhi_cntrl)
				mhi_arch_esoc_ops_power_on;
			esoc_ops->esoc_link_power_off =
				mhi_arch_esoc_ops_power_off;
			esoc_ops->esoc_link_mdm_crash =
				mhi_arch_esoc_ops_mdm_error;

			ret = esoc_register_client_hook(arch_info->esoc_client,
							esoc_ops);
+8 −0
Original line number Diff line number Diff line
@@ -26,6 +26,14 @@
#define MHI_RPM_SUSPEND_TMR_MS (250)
#define MHI_PCI_BAR_NUM (0)

/* timesync time calculations */
#define REMOTE_TICKS_TO_US(x) (div_u64((x) * 100ULL, \
			       div_u64(mhi_cntrl->remote_timer_freq, 10000ULL)))
#define REMOTE_TICKS_TO_SEC(x) (div_u64((x), \
				mhi_cntrl->remote_timer_freq))
#define REMOTE_TIME_REMAINDER_US(x) (REMOTE_TICKS_TO_US((x)) % \
					(REMOTE_TICKS_TO_SEC((x)) * 1000000ULL))

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])

+1 −0
Original line number Diff line number Diff line
@@ -761,6 +761,7 @@ int mhi_create_timesync_sysfs(struct mhi_controller *mhi_cntrl);
void mhi_destroy_timesync(struct mhi_controller *mhi_cntrl);
int mhi_create_vote_sysfs(struct mhi_controller *mhi_cntrl);
void mhi_destroy_vote_sysfs(struct mhi_controller *mhi_cntrl);
int mhi_early_notify_device(struct device *dev, void *data);

/* timesync log support */
static inline void mhi_timesync_log(struct mhi_controller *mhi_cntrl)
+23 −0
Original line number Diff line number Diff line
@@ -646,6 +646,22 @@ int mhi_destroy_device(struct device *dev, void *data)
	return 0;
}

int mhi_early_notify_device(struct device *dev, void *data)
{
	struct mhi_device *mhi_dev = to_mhi_device(dev);
	struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;

	/* skip early notification */
	if (!mhi_dev->early_notif)
		return 0;

	MHI_LOG("Early notification for dev:%s\n", mhi_dev->chan_name);

	mhi_notify(mhi_dev, MHI_CB_FATAL_ERROR);

	return 0;
}

void mhi_notify(struct mhi_device *mhi_dev, enum MHI_CB cb_reason)
{
	struct mhi_driver *mhi_drv;
@@ -856,6 +872,13 @@ void mhi_create_devices(struct mhi_controller *mhi_cntrl)
		/* add if there is a matching DT node */
		mhi_assign_of_node(mhi_cntrl, mhi_dev);

		/*
		 * if set, these device should get a early notification during
		 * early notification state
		 */
		mhi_dev->early_notif =
			of_property_read_bool(mhi_dev->dev.of_node,
					      "mhi,early-notify");
		/* init wake source */
		if (mhi_dev->dl_chan && mhi_dev->dl_chan->wake_capable)
			device_init_wakeup(&mhi_dev->dev, true);
+30 −0
Original line number Diff line number Diff line
@@ -893,6 +893,36 @@ int mhi_async_power_up(struct mhi_controller *mhi_cntrl)
}
EXPORT_SYMBOL(mhi_async_power_up);

/* Transition MHI into error state and notify critical clients */
void mhi_control_error(struct mhi_controller *mhi_cntrl)
{
	enum MHI_PM_STATE cur_state;

	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));

	write_lock_irq(&mhi_cntrl->pm_lock);
	cur_state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_LD_ERR_FATAL_DETECT);
	write_unlock_irq(&mhi_cntrl->pm_lock);

	if (cur_state != MHI_PM_LD_ERR_FATAL_DETECT) {
		MHI_ERR("Failed to transition to state:%s from:%s\n",
			to_mhi_pm_state_str(MHI_PM_LD_ERR_FATAL_DETECT),
			to_mhi_pm_state_str(cur_state));
		goto exit_control_error;
	}

	/* start notifying all clients who request early notification */
	device_for_each_child(mhi_cntrl->dev, NULL, mhi_early_notify_device);

exit_control_error:
	MHI_LOG("Exit 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));
}
EXPORT_SYMBOL(mhi_control_error);

void mhi_power_down(struct mhi_controller *mhi_cntrl, bool graceful)
{
	enum MHI_PM_STATE cur_state;
Loading