aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/remoteproc/remoteproc_core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/remoteproc/remoteproc_core.c')
-rw-r--r--drivers/remoteproc/remoteproc_core.c79
1 files changed, 75 insertions, 4 deletions
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index d5c2dbfc7443..93e2b3526543 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -50,6 +50,18 @@ typedef int (*rproc_handle_resource_t)(struct rproc *rproc, void *, int avail);
50/* Unique indices for remoteproc devices */ 50/* Unique indices for remoteproc devices */
51static DEFINE_IDA(rproc_dev_index); 51static DEFINE_IDA(rproc_dev_index);
52 52
53static const char * const rproc_crash_names[] = {
54 [RPROC_MMUFAULT] = "mmufault",
55};
56
57/* translate rproc_crash_type to string */
58static const char *rproc_crash_to_string(enum rproc_crash_type type)
59{
60 if (type < ARRAY_SIZE(rproc_crash_names))
61 return rproc_crash_names[type];
62 return "unkown";
63}
64
53/* 65/*
54 * This is the IOMMU fault handler we register with the IOMMU API 66 * This is the IOMMU fault handler we register with the IOMMU API
55 * (when relevant; not all remote processors access memory through 67 * (when relevant; not all remote processors access memory through
@@ -57,18 +69,19 @@ static DEFINE_IDA(rproc_dev_index);
57 * 69 *
58 * IOMMU core will invoke this handler whenever the remote processor 70 * IOMMU core will invoke this handler whenever the remote processor
59 * will try to access an unmapped device address. 71 * will try to access an unmapped device address.
60 *
61 * Currently this is mostly a stub, but it will be later used to trigger
62 * the recovery of the remote processor.
63 */ 72 */
64static int rproc_iommu_fault(struct iommu_domain *domain, struct device *dev, 73static int rproc_iommu_fault(struct iommu_domain *domain, struct device *dev,
65 unsigned long iova, int flags, void *token) 74 unsigned long iova, int flags, void *token)
66{ 75{
76 struct rproc *rproc = token;
77
67 dev_err(dev, "iommu fault: da 0x%lx flags 0x%x\n", iova, flags); 78 dev_err(dev, "iommu fault: da 0x%lx flags 0x%x\n", iova, flags);
68 79
80 rproc_report_crash(rproc, RPROC_MMUFAULT);
81
69 /* 82 /*
70 * Let the iommu core know we're not really handling this fault; 83 * Let the iommu core know we're not really handling this fault;
71 * we just plan to use this as a recovery trigger. 84 * we just used it as a recovery trigger.
72 */ 85 */
73 return -ENOSYS; 86 return -ENOSYS;
74} 87}
@@ -872,6 +885,36 @@ out:
872} 885}
873 886
874/** 887/**
888 * rproc_crash_handler_work() - handle a crash
889 *
890 * This function needs to handle everything related to a crash, like cpu
891 * registers and stack dump, information to help to debug the fatal error, etc.
892 */
893static void rproc_crash_handler_work(struct work_struct *work)
894{
895 struct rproc *rproc = container_of(work, struct rproc, crash_handler);
896 struct device *dev = &rproc->dev;
897
898 dev_dbg(dev, "enter %s\n", __func__);
899
900 mutex_lock(&rproc->lock);
901
902 if (rproc->state == RPROC_CRASHED || rproc->state == RPROC_OFFLINE) {
903 /* handle only the first crash detected */
904 mutex_unlock(&rproc->lock);
905 return;
906 }
907
908 rproc->state = RPROC_CRASHED;
909 dev_err(dev, "handling crash #%u in %s\n", ++rproc->crash_cnt,
910 rproc->name);
911
912 mutex_unlock(&rproc->lock);
913
914 /* TODO: handle crash */
915}
916
917/**
875 * rproc_boot() - boot a remote processor 918 * rproc_boot() - boot a remote processor
876 * @rproc: handle of a remote processor 919 * @rproc: handle of a remote processor
877 * 920 *
@@ -1165,6 +1208,8 @@ struct rproc *rproc_alloc(struct device *dev, const char *name,
1165 INIT_LIST_HEAD(&rproc->traces); 1208 INIT_LIST_HEAD(&rproc->traces);
1166 INIT_LIST_HEAD(&rproc->rvdevs); 1209 INIT_LIST_HEAD(&rproc->rvdevs);
1167 1210
1211 INIT_WORK(&rproc->crash_handler, rproc_crash_handler_work);
1212
1168 rproc->state = RPROC_OFFLINE; 1213 rproc->state = RPROC_OFFLINE;
1169 1214
1170 return rproc; 1215 return rproc;
@@ -1221,6 +1266,32 @@ int rproc_del(struct rproc *rproc)
1221} 1266}
1222EXPORT_SYMBOL(rproc_del); 1267EXPORT_SYMBOL(rproc_del);
1223 1268
1269/**
1270 * rproc_report_crash() - rproc crash reporter function
1271 * @rproc: remote processor
1272 * @type: crash type
1273 *
1274 * This function must be called every time a crash is detected by the low-level
1275 * drivers implementing a specific remoteproc. This should not be called from a
1276 * non-remoteproc driver.
1277 *
1278 * This function can be called from atomic/interrupt context.
1279 */
1280void rproc_report_crash(struct rproc *rproc, enum rproc_crash_type type)
1281{
1282 if (!rproc) {
1283 pr_err("NULL rproc pointer\n");
1284 return;
1285 }
1286
1287 dev_err(&rproc->dev, "crash detected in %s: type %s\n",
1288 rproc->name, rproc_crash_to_string(type));
1289
1290 /* create a new task to handle the error */
1291 schedule_work(&rproc->crash_handler);
1292}
1293EXPORT_SYMBOL(rproc_report_crash);
1294
1224static int __init remoteproc_init(void) 1295static int __init remoteproc_init(void)
1225{ 1296{
1226 rproc_init_debugfs(); 1297 rproc_init_debugfs();