Merge tag 'rpmsg-v4.14' of git://github.com/andersson/remoteproc
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 9 Sep 2017 21:34:38 +0000 (14:34 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 9 Sep 2017 21:34:38 +0000 (14:34 -0700)
Pull rpmsg updates from Bjorn Andersson:
 "This extends the Qualcomm GLINK implementation to support the
  additional features used for communicating with modem and DSP
  coprocessors in modern Qualcomm platforms.

  In addition to this there's support for placing virtio RPMSG buffers
  in non-System RAM"

* tag 'rpmsg-v4.14' of git://github.com/andersson/remoteproc: (29 commits)
  rpmsg: glink: initialize ret to zero to ensure error status check is correct
  rpmsg: glink: fix null pointer dereference on a null intent
  dt-bindings: soc: qcom: Extend GLINK to cover SMEM
  remoteproc: qcom: adsp: Allow defining GLINK edge
  rpmsg: glink: Export symbols from common code
  rpmsg: glink: Release idr lock before returning on error
  rpmsg: glink: Handle remote rx done command
  rpmsg: glink: Request for intents when unavailable
  rpmsg: glink: Use the intents passed by remote
  rpmsg: glink: Receive and store the remote intent buffers
  rpmsg: glink: Add announce_create ops and preallocate intents
  rpmsg: glink: Add rx done command
  rpmsg: glink: Make RX FIFO peak accessor to take an offset
  rpmsg: glink: Use the local intents when receiving data
  rpmsg: glink: Add support for TX intents
  rpmsg: glink: Fix idr_lock from mutex to spinlock
  rpmsg: glink: Add support for transport version negotiation
  rpmsg: glink: Introduce glink smem based transport
  rpmsg: glink: Do a mbox_free_channel in remove
  rpmsg: glink: Return -EAGAIN when there is no FIFO space
  ...

1  2 
drivers/remoteproc/Kconfig
drivers/remoteproc/qcom_adsp_pil.c
drivers/remoteproc/qcom_common.c
drivers/remoteproc/qcom_common.h

index 79f903af650485b6d7f4afbd2669116c2d34bf88,beb5f3a252888de2c9e57db1d039a42147d43022..df63e44526ac42a814ee85c3286c9d1a9b45be48
@@@ -12,15 -12,6 +12,15 @@@ config REMOTEPRO
  
  if REMOTEPROC
  
 +config IMX_REMOTEPROC
 +      tristate "IMX6/7 remoteproc support"
 +      depends on SOC_IMX6SX || SOC_IMX7D
 +      help
 +        Say y here to support iMX's remote processors (Cortex M4
 +        on iMX7D) via the remote processor framework.
 +
 +        It's safe to say N here.
 +
  config OMAP_REMOTEPROC
        tristate "OMAP remoteproc support"
        depends on HAS_DMA
@@@ -92,6 -83,7 +92,7 @@@ config QCOM_ADSP_PI
        depends on OF && ARCH_QCOM
        depends on QCOM_SMEM
        depends on RPMSG_QCOM_SMD || (COMPILE_TEST && RPMSG_QCOM_SMD=n)
+       depends on RPMSG_QCOM_GLINK_SMEM || RPMSG_QCOM_GLINK_SMEM=n
        select MFD_SYSCON
        select QCOM_MDT_LOADER
        select QCOM_RPROC_COMMON
index d01a8daf948ace449a0281532fc37f8fff184452,42884ace324ce2dc8358d048330171a517f1620f..3f6af54dbc9656703d3cf2c2328c394a517bd83b
@@@ -38,7 -38,6 +38,7 @@@ struct adsp_data 
        const char *firmware_name;
        int pas_id;
        bool has_aggre2_clk;
 +      const char *ssr_name;
  };
  
  struct qcom_adsp {
@@@ -72,8 -71,8 +72,9 @@@
        void *mem_region;
        size_t mem_size;
  
+       struct qcom_rproc_glink glink_subdev;
        struct qcom_rproc_subdev smd_subdev;
 +      struct qcom_rproc_ssr ssr_subdev;
  };
  
  static int adsp_load(struct rproc *rproc, const struct firmware *fw)
@@@ -268,7 -267,10 +269,7 @@@ static int adsp_init_regulator(struct q
        regulator_set_load(adsp->cx_supply, 100000);
  
        adsp->px_supply = devm_regulator_get(adsp->dev, "px");
 -      if (IS_ERR(adsp->px_supply))
 -              return PTR_ERR(adsp->px_supply);
 -
 -      return 0;
 +      return PTR_ERR_OR_ZERO(adsp->px_supply);
  }
  
  static int adsp_request_irq(struct qcom_adsp *adsp,
@@@ -400,8 -402,8 +401,9 @@@ static int adsp_probe(struct platform_d
                goto free_rproc;
        }
  
+       qcom_add_glink_subdev(rproc, &adsp->glink_subdev);
        qcom_add_smd_subdev(rproc, &adsp->smd_subdev);
 +      qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
  
        ret = rproc_add(rproc);
        if (ret)
@@@ -422,8 -424,8 +424,9 @@@ static int adsp_remove(struct platform_
        qcom_smem_state_put(adsp->state);
        rproc_del(adsp->rproc);
  
+       qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev);
        qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev);
 +      qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev);
        rproc_free(adsp->rproc);
  
        return 0;
@@@ -434,7 -436,6 +437,7 @@@ static const struct adsp_data adsp_reso
                .firmware_name = "adsp.mdt",
                .pas_id = 1,
                .has_aggre2_clk = false,
 +              .ssr_name = "lpass",
  };
  
  static const struct adsp_data slpi_resource_init = {
                .firmware_name = "slpi.mdt",
                .pas_id = 12,
                .has_aggre2_clk = true,
 +              .ssr_name = "dsps",
  };
  
  static const struct of_device_id adsp_of_match[] = {
index 257680f82b27005040555e82af5a4245d03b136f,46274c60c3eacaa785ec2a9d00151e8f6e36fce6..d487040b528ba0509e58b4fc694e9da5991a23f7
  #include <linux/firmware.h>
  #include <linux/kernel.h>
  #include <linux/module.h>
 +#include <linux/notifier.h>
  #include <linux/remoteproc.h>
+ #include <linux/rpmsg/qcom_glink.h>
  #include <linux/rpmsg/qcom_smd.h>
  
  #include "remoteproc_internal.h"
  #include "qcom_common.h"
  
+ #define to_glink_subdev(d) container_of(d, struct qcom_rproc_glink, subdev)
  #define to_smd_subdev(d) container_of(d, struct qcom_rproc_subdev, subdev)
 +#define to_ssr_subdev(d) container_of(d, struct qcom_rproc_ssr, subdev)
 +
 +static BLOCKING_NOTIFIER_HEAD(ssr_notifiers);
  
  /**
   * qcom_mdt_find_rsc_table() - provide dummy resource table for remoteproc
@@@ -49,13 -47,60 +51,60 @@@ struct resource_table *qcom_mdt_find_rs
  }
  EXPORT_SYMBOL_GPL(qcom_mdt_find_rsc_table);
  
+ static int glink_subdev_probe(struct rproc_subdev *subdev)
+ {
+       struct qcom_rproc_glink *glink = to_glink_subdev(subdev);
+       glink->edge = qcom_glink_smem_register(glink->dev, glink->node);
+       return IS_ERR(glink->edge) ? PTR_ERR(glink->edge) : 0;
+ }
+ static void glink_subdev_remove(struct rproc_subdev *subdev)
+ {
+       struct qcom_rproc_glink *glink = to_glink_subdev(subdev);
+       qcom_glink_smem_unregister(glink->edge);
+       glink->edge = NULL;
+ }
+ /**
+  * qcom_add_glink_subdev() - try to add a GLINK subdevice to rproc
+  * @rproc:    rproc handle to parent the subdevice
+  * @glink:    reference to a GLINK subdev context
+  */
+ void qcom_add_glink_subdev(struct rproc *rproc, struct qcom_rproc_glink *glink)
+ {
+       struct device *dev = &rproc->dev;
+       glink->node = of_get_child_by_name(dev->parent->of_node, "glink-edge");
+       if (!glink->node)
+               return;
+       glink->dev = dev;
+       rproc_add_subdev(rproc, &glink->subdev, glink_subdev_probe, glink_subdev_remove);
+ }
+ EXPORT_SYMBOL_GPL(qcom_add_glink_subdev);
+ /**
+  * qcom_remove_glink_subdev() - remove a GLINK subdevice from rproc
+  * @rproc:    rproc handle
+  * @glink:    reference to a GLINK subdev context
+  */
+ void qcom_remove_glink_subdev(struct rproc *rproc, struct qcom_rproc_glink *glink)
+ {
+       rproc_remove_subdev(rproc, &glink->subdev);
+       of_node_put(glink->node);
+ }
+ EXPORT_SYMBOL_GPL(qcom_remove_glink_subdev);
  static int smd_subdev_probe(struct rproc_subdev *subdev)
  {
        struct qcom_rproc_subdev *smd = to_smd_subdev(subdev);
  
        smd->edge = qcom_smd_register_edge(smd->dev, smd->node);
  
 -      return IS_ERR(smd->edge) ? PTR_ERR(smd->edge) : 0;
 +      return PTR_ERR_OR_ZERO(smd->edge);
  }
  
  static void smd_subdev_remove(struct rproc_subdev *subdev)
@@@ -96,72 -141,5 +145,72 @@@ void qcom_remove_smd_subdev(struct rpro
  }
  EXPORT_SYMBOL_GPL(qcom_remove_smd_subdev);
  
 +/**
 + * qcom_register_ssr_notifier() - register SSR notification handler
 + * @nb:               notifier_block to notify for restart notifications
 + *
 + * Returns 0 on success, negative errno on failure.
 + *
 + * This register the @notify function as handler for restart notifications. As
 + * remote processors are stopped this function will be called, with the SSR
 + * name passed as a parameter.
 + */
 +int qcom_register_ssr_notifier(struct notifier_block *nb)
 +{
 +      return blocking_notifier_chain_register(&ssr_notifiers, nb);
 +}
 +EXPORT_SYMBOL_GPL(qcom_register_ssr_notifier);
 +
 +/**
 + * qcom_unregister_ssr_notifier() - unregister SSR notification handler
 + * @nb:               notifier_block to unregister
 + */
 +void qcom_unregister_ssr_notifier(struct notifier_block *nb)
 +{
 +      blocking_notifier_chain_unregister(&ssr_notifiers, nb);
 +}
 +EXPORT_SYMBOL_GPL(qcom_unregister_ssr_notifier);
 +
 +static int ssr_notify_start(struct rproc_subdev *subdev)
 +{
 +      return  0;
 +}
 +
 +static void ssr_notify_stop(struct rproc_subdev *subdev)
 +{
 +      struct qcom_rproc_ssr *ssr = to_ssr_subdev(subdev);
 +
 +      blocking_notifier_call_chain(&ssr_notifiers, 0, (void *)ssr->name);
 +}
 +
 +/**
 + * qcom_add_ssr_subdev() - register subdevice as restart notification source
 + * @rproc:    rproc handle
 + * @ssr:      SSR subdevice handle
 + * @ssr_name: identifier to use for notifications originating from @rproc
 + *
 + * As the @ssr is registered with the @rproc SSR events will be sent to all
 + * registered listeners in the system as the remoteproc is shut down.
 + */
 +void qcom_add_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr,
 +                       const char *ssr_name)
 +{
 +      ssr->name = ssr_name;
 +
 +      rproc_add_subdev(rproc, &ssr->subdev, ssr_notify_start, ssr_notify_stop);
 +}
 +EXPORT_SYMBOL_GPL(qcom_add_ssr_subdev);
 +
 +/**
 + * qcom_remove_ssr_subdev() - remove subdevice as restart notification source
 + * @rproc:    rproc handle
 + * @ssr:      SSR subdevice handle
 + */
 +void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr)
 +{
 +      rproc_remove_subdev(rproc, &ssr->subdev);
 +}
 +EXPORT_SYMBOL_GPL(qcom_remove_ssr_subdev);
 +
  MODULE_DESCRIPTION("Qualcomm Remoteproc helper driver");
  MODULE_LICENSE("GPL v2");
index fab28b64b8ead44ad6ce60809ce484ef9df390ac,b6f6573ff34afd35fd37cac773cc98ab24b5451a..4f8bc168473c1dbec573d24519749e63ba4a977c
@@@ -4,6 -4,14 +4,14 @@@
  #include <linux/remoteproc.h>
  #include "remoteproc_internal.h"
  
+ struct qcom_rproc_glink {
+       struct rproc_subdev subdev;
+       struct device *dev;
+       struct device_node *node;
+       struct qcom_glink *edge;
+ };
  struct qcom_rproc_subdev {
        struct rproc_subdev subdev;
  
        struct qcom_smd_edge *edge;
  };
  
 +struct qcom_rproc_ssr {
 +      struct rproc_subdev subdev;
 +
 +      const char *name;
 +};
 +
  struct resource_table *qcom_mdt_find_rsc_table(struct rproc *rproc,
                                               const struct firmware *fw,
                                               int *tablesz);
  
+ void qcom_add_glink_subdev(struct rproc *rproc, struct qcom_rproc_glink *glink);
+ void qcom_remove_glink_subdev(struct rproc *rproc, struct qcom_rproc_glink *glink);
  void qcom_add_smd_subdev(struct rproc *rproc, struct qcom_rproc_subdev *smd);
  void qcom_remove_smd_subdev(struct rproc *rproc, struct qcom_rproc_subdev *smd);
  
 +void qcom_add_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr,
 +                       const char *ssr_name);
 +void qcom_remove_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr);
 +
  #endif