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

Commit 70b85ef8 authored by Fernando Guzman Lugo's avatar Fernando Guzman Lugo Committed by Ohad Ben-Cohen
Browse files

remoteproc: add actual recovery implementation



Add rproc_trigger_recovery() which takes care of the recovery itself,
by removing, and re-adding, all of the remoteproc's virtio devices.

This resets all virtio users of the remote processor, during which
the remote processor is powered off and on again.

Signed-off-by: default avatarFernando Guzman Lugo <fernando.lugo@ti.com>
[ohad: introduce rproc_add_virtio_devices to avoid 1.copying code 2.anomaly]
[ohad: some white space, naming and commit log changes]
Signed-off-by: default avatarOhad Ben-Cohen <ohad@wizery.com>
parent 8afd519c
Loading
Loading
Loading
Loading
+62 −22
Original line number Original line Diff line number Diff line
@@ -884,6 +884,60 @@ out:
	complete_all(&rproc->firmware_loading_complete);
	complete_all(&rproc->firmware_loading_complete);
}
}


static int rproc_add_virtio_devices(struct rproc *rproc)
{
	int ret;

	/* rproc_del() calls must wait until async loader completes */
	init_completion(&rproc->firmware_loading_complete);

	/*
	 * We must retrieve early virtio configuration info from
	 * the firmware (e.g. whether to register a virtio device,
	 * what virtio features does it support, ...).
	 *
	 * We're initiating an asynchronous firmware loading, so we can
	 * be built-in kernel code, without hanging the boot process.
	 */
	ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
				      rproc->firmware, &rproc->dev, GFP_KERNEL,
				      rproc, rproc_fw_config_virtio);
	if (ret < 0) {
		dev_err(&rproc->dev, "request_firmware_nowait err: %d\n", ret);
		complete_all(&rproc->firmware_loading_complete);
	}

	return ret;
}

/**
 * rproc_trigger_recovery() - recover a remoteproc
 * @rproc: the remote processor
 *
 * The recovery is done by reseting all the virtio devices, that way all the
 * rpmsg drivers will be reseted along with the remote processor making the
 * remoteproc functional again.
 *
 * This function can sleep, so it cannot be called from atomic context.
 */
int rproc_trigger_recovery(struct rproc *rproc)
{
	struct rproc_vdev *rvdev, *rvtmp;

	dev_err(&rproc->dev, "recovering %s\n", rproc->name);

	init_completion(&rproc->crash_comp);

	/* clean up remote vdev entries */
	list_for_each_entry_safe(rvdev, rvtmp, &rproc->rvdevs, node)
		rproc_remove_virtio_dev(rvdev);

	/* wait until there is no more rproc users */
	wait_for_completion(&rproc->crash_comp);

	return rproc_add_virtio_devices(rproc);
}

/**
/**
 * rproc_crash_handler_work() - handle a crash
 * rproc_crash_handler_work() - handle a crash
 *
 *
@@ -911,7 +965,7 @@ static void rproc_crash_handler_work(struct work_struct *work)


	mutex_unlock(&rproc->lock);
	mutex_unlock(&rproc->lock);


	/* TODO: handle crash */
	rproc_trigger_recovery(rproc);
}
}


/**
/**
@@ -1035,6 +1089,10 @@ void rproc_shutdown(struct rproc *rproc)


	rproc_disable_iommu(rproc);
	rproc_disable_iommu(rproc);


	/* if in crash state, unlock crash handler */
	if (rproc->state == RPROC_CRASHED)
		complete_all(&rproc->crash_comp);

	rproc->state = RPROC_OFFLINE;
	rproc->state = RPROC_OFFLINE;


	dev_info(dev, "stopped remote processor %s\n", rproc->name);
	dev_info(dev, "stopped remote processor %s\n", rproc->name);
@@ -1069,7 +1127,7 @@ EXPORT_SYMBOL(rproc_shutdown);
int rproc_add(struct rproc *rproc)
int rproc_add(struct rproc *rproc)
{
{
	struct device *dev = &rproc->dev;
	struct device *dev = &rproc->dev;
	int ret = 0;
	int ret;


	ret = device_add(dev);
	ret = device_add(dev);
	if (ret < 0)
	if (ret < 0)
@@ -1083,26 +1141,7 @@ int rproc_add(struct rproc *rproc)
	/* create debugfs entries */
	/* create debugfs entries */
	rproc_create_debug_dir(rproc);
	rproc_create_debug_dir(rproc);


	/* rproc_del() calls must wait until async loader completes */
	return rproc_add_virtio_devices(rproc);
	init_completion(&rproc->firmware_loading_complete);

	/*
	 * We must retrieve early virtio configuration info from
	 * the firmware (e.g. whether to register a virtio device,
	 * what virtio features does it support, ...).
	 *
	 * We're initiating an asynchronous firmware loading, so we can
	 * be built-in kernel code, without hanging the boot process.
	 */
	ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
					rproc->firmware, dev, GFP_KERNEL,
					rproc, rproc_fw_config_virtio);
	if (ret < 0) {
		dev_err(dev, "request_firmware_nowait failed: %d\n", ret);
		complete_all(&rproc->firmware_loading_complete);
	}

	return ret;
}
}
EXPORT_SYMBOL(rproc_add);
EXPORT_SYMBOL(rproc_add);


@@ -1209,6 +1248,7 @@ struct rproc *rproc_alloc(struct device *dev, const char *name,
	INIT_LIST_HEAD(&rproc->rvdevs);
	INIT_LIST_HEAD(&rproc->rvdevs);


	INIT_WORK(&rproc->crash_handler, rproc_crash_handler_work);
	INIT_WORK(&rproc->crash_handler, rproc_crash_handler_work);
	init_completion(&rproc->crash_comp);


	rproc->state = RPROC_OFFLINE;
	rproc->state = RPROC_OFFLINE;


+1 −0
Original line number Original line Diff line number Diff line
@@ -63,6 +63,7 @@ void rproc_free_vring(struct rproc_vring *rvring);
int rproc_alloc_vring(struct rproc_vdev *rvdev, int i);
int rproc_alloc_vring(struct rproc_vdev *rvdev, int i);


void *rproc_da_to_va(struct rproc *rproc, u64 da, int len);
void *rproc_da_to_va(struct rproc *rproc, u64 da, int len);
int rproc_trigger_recovery(struct rproc *rproc);


static inline
static inline
int rproc_fw_sanity_check(struct rproc *rproc, const struct firmware *fw)
int rproc_fw_sanity_check(struct rproc *rproc, const struct firmware *fw)
+2 −0
Original line number Original line Diff line number Diff line
@@ -398,6 +398,7 @@ enum rproc_crash_type {
 * @index: index of this rproc device
 * @index: index of this rproc device
 * @crash_handler: workqueue for handling a crash
 * @crash_handler: workqueue for handling a crash
 * @crash_cnt: crash counter
 * @crash_cnt: crash counter
 * @crash_comp: completion used to sync crash handler and the rproc reload
 */
 */
struct rproc {
struct rproc {
	struct klist_node node;
	struct klist_node node;
@@ -423,6 +424,7 @@ struct rproc {
	int index;
	int index;
	struct work_struct crash_handler;
	struct work_struct crash_handler;
	unsigned crash_cnt;
	unsigned crash_cnt;
	struct completion crash_comp;
};
};


/* we currently support only two vrings per rvdev */
/* we currently support only two vrings per rvdev */