Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 329770
b: refs/heads/master
c: 70b85ef
h: refs/heads/master
v: v3
  • Loading branch information
Fernando Guzman Lugo authored and Ohad Ben-Cohen committed Sep 18, 2012
1 parent 65b8cc3 commit 7b3c62f
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 23 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 8afd519c3470f685f964deebd61aa51d83cde90a
refs/heads/master: 70b85ef83ce3523f709b622d2c4cb31778686338
84 changes: 62 additions & 22 deletions trunk/drivers/remoteproc/remoteproc_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -884,6 +884,60 @@ static void rproc_fw_config_virtio(const struct firmware *fw, void *context)
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
*
Expand Down Expand Up @@ -911,7 +965,7 @@ static void rproc_crash_handler_work(struct work_struct *work)

mutex_unlock(&rproc->lock);

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

/**
Expand Down Expand Up @@ -1035,6 +1089,10 @@ void rproc_shutdown(struct rproc *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;

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

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

/* 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, 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;
return rproc_add_virtio_devices(rproc);
}
EXPORT_SYMBOL(rproc_add);

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

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

rproc->state = RPROC_OFFLINE;

Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/remoteproc/remoteproc_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ void rproc_free_vring(struct rproc_vring *rvring);
int rproc_alloc_vring(struct rproc_vdev *rvdev, int i);

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

static inline
int rproc_fw_sanity_check(struct rproc *rproc, const struct firmware *fw)
Expand Down
2 changes: 2 additions & 0 deletions trunk/include/linux/remoteproc.h
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ enum rproc_crash_type {
* @index: index of this rproc device
* @crash_handler: workqueue for handling a crash
* @crash_cnt: crash counter
* @crash_comp: completion used to sync crash handler and the rproc reload
*/
struct rproc {
struct klist_node node;
Expand All @@ -423,6 +424,7 @@ struct rproc {
int index;
struct work_struct crash_handler;
unsigned crash_cnt;
struct completion crash_comp;
};

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

0 comments on commit 7b3c62f

Please sign in to comment.