]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - rpmsg/rpmsg.git/commitdiff
remoteproc: Add support to handle device specific resource types
authorSuman Anna <s-anna@ti.com>
Fri, 15 Feb 2019 19:06:08 +0000 (13:06 -0600)
committerSuman Anna <s-anna@ti.com>
Sun, 24 Feb 2019 01:20:48 +0000 (19:20 -0600)
The remoteproc framework handles a fixed set of resource table entries
today. To make it scalable across multiple platforms, it makes sense
for the framework to provide a way for the device specific implementation
to define and handle vendor specific resource types. These resource types
would be very specific to an implementation instance that it does not
make sense for the framework to handle it. There can be two types of
such resources depending on whether they need to be handled prior to
the loading of the firmware segments or after. A post-loading resource
type is typically needed because it references a loaded segment pointer
for conveying the resource information.

For instance, a remoteproc implementation might want timers information
embedded in the resource table so that the driver could parse the binary
and enable accordingly. Another example would be hwspinlocks that it
is using, to properly share system wide resources. A PRU post-loading
vendor resource handler for interrupts requires the PRU event - interrupt
channel information to be loaded into device memory.

This patch adds a function pointer to the list of rproc_ops for the
driver implementation to handle such custom vendor resources, and
reuses the same handler between pre-loading and post-loading resource
types, with the sub-types in the implementation handling the processing
of those resource types.

Signed-off-by: Suman Anna <s-anna@ti.com>
drivers/remoteproc/remoteproc_core.c
drivers/remoteproc/remoteproc_debugfs.c
include/linux/remoteproc.h

index 0503b7f61897741808963172543ceaa501318e37..48e6b5864d741be1277f2032cdc24947f2172f17 100644 (file)
@@ -782,6 +782,42 @@ free_carv:
        return ret;
 }
 
+/**
+ * rproc_handle_vendor_rsc() - provide implementation specific hook
+ *                            to handle vendor/custom resources
+ * @rproc: the remote processor
+ * @rsc: vendor resource to be handled by remoteproc drivers
+ * @offset: offset of the resource data in resource table
+ * @avail: size of available data
+ *
+ * Remoteproc implementations might want to add resource table entries
+ * that are not generic enough to be handled by the framework. This
+ * provides a hook to handle such custom resources. Note that a single
+ * hook is reused between RSC_PRELOAD_VENDOR and RSC_PRELOAD_VENDOR
+ * resources with the platform driver implementation distinguishing
+ * the two based on the sub-type resource.
+ *
+ * Returns 0 on success, or an appropriate error code otherwise
+ */
+static int rproc_handle_vendor_rsc(struct rproc *rproc,
+                                  struct fw_rsc_vendor *rsc,
+                                  int offset, int avail)
+{
+       struct device *dev = &rproc->dev;
+
+       if (!rproc->ops->handle_vendor_rsc) {
+               dev_err(dev, "vendor resource handler not implemented, ignoring resource\n");
+               return 0;
+       }
+
+       if (sizeof(*rsc) > avail) {
+               dev_err(dev, "vendor resource is truncated\n");
+               return -EINVAL;
+       }
+
+       return rproc->ops->handle_vendor_rsc(rproc, (void *)rsc);
+}
+
 /*
  * A lookup table for resource handlers. The indices are defined in
  * enum fw_resource_type.
@@ -790,9 +826,15 @@ static rproc_handle_resource_t rproc_loading_handlers[RSC_LAST] = {
        [RSC_CARVEOUT] = (rproc_handle_resource_t)rproc_handle_carveout,
        [RSC_DEVMEM] = (rproc_handle_resource_t)rproc_handle_devmem,
        [RSC_TRACE] = (rproc_handle_resource_t)rproc_handle_trace,
+       [RSC_PRELOAD_VENDOR] = (rproc_handle_resource_t)rproc_handle_vendor_rsc,
        [RSC_VDEV] = (rproc_handle_resource_t)rproc_handle_vdev,
 };
 
+static rproc_handle_resource_t rproc_post_loading_handlers[RSC_LAST] = {
+       [RSC_POSTLOAD_VENDOR] =
+                       (rproc_handle_resource_t)rproc_handle_vendor_rsc,
+};
+
 /* handle firmware resource entries before booting the remote processor */
 static int rproc_handle_resources(struct rproc *rproc,
                                  rproc_handle_resource_t handlers[RSC_LAST])
@@ -998,6 +1040,14 @@ static int rproc_start(struct rproc *rproc, const struct firmware *fw)
                rproc->table_ptr = loaded_table;
        }
 
+       /* handle fw resources which require fw segments to be loaded */
+       ret = rproc_handle_resources(rproc, rproc_post_loading_handlers);
+       if (ret) {
+               dev_err(dev, "Failed to process post-loading resources: %d\n",
+                       ret);
+               goto reset_table_ptr;
+       }
+
        ret = rproc_prepare_subdevices(rproc);
        if (ret) {
                dev_err(dev, "failed to prepare subdevices for %s: %d\n",
index e90135c64af0761ec37d392921a33aa602829f0f..79d6fa14e0ba0bb69fedfeaa36df7bc0a1e87166 100644 (file)
@@ -158,13 +158,15 @@ static const struct file_operations rproc_recovery_ops = {
 /* Expose resource table content via debugfs */
 static int rproc_rsc_table_show(struct seq_file *seq, void *p)
 {
-       static const char * const types[] = {"carveout", "devmem", "trace", "vdev"};
+       static const char * const types[] = {"carveout", "devmem", "trace",
+                                            "vdev", "preload", "postload"};
        struct rproc *rproc = seq->private;
        struct resource_table *table = rproc->table_ptr;
        struct fw_rsc_carveout *c;
        struct fw_rsc_devmem *d;
        struct fw_rsc_trace *t;
        struct fw_rsc_vdev *v;
+       struct fw_rsc_vendor *vr;
        int i, j;
 
        if (!table) {
@@ -230,6 +232,16 @@ static int rproc_rsc_table_show(struct seq_file *seq, void *p)
                                           v->vring[j].pa);
                        }
                        break;
+               case RSC_PRELOAD_VENDOR:
+               case RSC_POSTLOAD_VENDOR:
+                       vr = rsc;
+                       seq_printf(seq, "Entry %d is of type vendor-%s\n",
+                                  i, types[hdr->type]);
+                       seq_printf(seq, "  Vendor sub-type %d version %d\n",
+                                  vr->u.st.st_type, vr->u.st.st_ver);
+                       seq_printf(seq, "  Vendor resource size %d\n",
+                                  vr->size);
+                       break;
                default:
                        seq_printf(seq, "Unknown resource type found: %d [hdr: %pK]\n",
                                   hdr->type, hdr);
index e78b6e5d0886adaa54e2f1455b87f89d72e6a7ad..a62df28507e396c05d7b99be817661190789e58c 100644 (file)
@@ -100,6 +100,10 @@ struct fw_rsc_hdr {
  *                 the remote processor will be writing logs.
  * @RSC_VDEV:       declare support for a virtio device, and serve as its
  *                 virtio header.
+ * @RSC_PRELOAD_VENDOR: a vendor resource type that needs to be handled by
+ *                 remoteproc implementations before loading
+ * @RSC_POSTLOAD_VENDOR: a vendor resource type that needs to be handled by
+ *                 remoteproc implementations after loading
  * @RSC_LAST:       just keep this one at the end
  *
  * For more details regarding a specific resource type, please see its
@@ -111,11 +115,13 @@ struct fw_rsc_hdr {
  * please update it as needed.
  */
 enum fw_resource_type {
-       RSC_CARVEOUT    = 0,
-       RSC_DEVMEM      = 1,
-       RSC_TRACE       = 2,
-       RSC_VDEV        = 3,
-       RSC_LAST        = 4,
+       RSC_CARVEOUT            = 0,
+       RSC_DEVMEM              = 1,
+       RSC_TRACE               = 2,
+       RSC_VDEV                = 3,
+       RSC_PRELOAD_VENDOR      = 4,
+       RSC_POSTLOAD_VENDOR     = 5,
+       RSC_LAST                = 6,
 };
 
 #define FW_RSC_ADDR_ANY (-1)
@@ -305,6 +311,24 @@ struct fw_rsc_vdev {
        struct fw_rsc_vdev_vring vring[0];
 } __packed;
 
+/**
+ * struct fw_rsc_vendor - vendor resource definition
+ * @sub_type: implementation specific type including version field
+ * @size: size of the vendor custom resource
+ * @data: label for the start of the resource
+ */
+struct fw_rsc_vendor {
+       union {
+               u32 sub_type;
+               struct {
+                       u16 st_type;
+                       u16 st_ver;
+               } st;
+       } u;
+       u32 size;
+       u8 data[0];
+} __packed;
+
 /**
  * struct rproc_mem_entry - memory entry descriptor
  * @va:        virtual address
@@ -336,6 +360,7 @@ struct firmware;
  * @da_to_va:  optional platform hook to perform address translations
  * @load_rsc_table:    load resource table from firmware image
  * @find_loaded_rsc_table: find the loaded resouce table
+ * @handle_vendor_rsc: hook to handle device specific resource table entries
  * @load:              load firmeware to memory, where the remote processor
  *                     expects to find it
  * @sanity_check:      sanity check the fw image
@@ -349,6 +374,8 @@ struct rproc_ops {
        int (*parse_fw)(struct rproc *rproc, const struct firmware *fw);
        struct resource_table *(*find_loaded_rsc_table)(
                                struct rproc *rproc, const struct firmware *fw);
+       int (*handle_vendor_rsc)(struct rproc *rproc,
+                                struct fw_rsc_vendor *rsc);
        int (*load)(struct rproc *rproc, const struct firmware *fw);
        int (*sanity_check)(struct rproc *rproc, const struct firmware *fw);
        u32 (*get_boot_addr)(struct rproc *rproc, const struct firmware *fw);