Merge tag 'block-5.13-2021-05-09' of git://git.kernel.dk/linux-block
[linux-2.6-microblaze.git] / drivers / remoteproc / pru_rproc.c
index dcb380e..e5778e4 100644 (file)
@@ -244,8 +244,8 @@ static int pru_rproc_debug_ss_get(void *data, u64 *val)
 
        return 0;
 }
-DEFINE_SIMPLE_ATTRIBUTE(pru_rproc_debug_ss_fops, pru_rproc_debug_ss_get,
-                       pru_rproc_debug_ss_set, "%llu\n");
+DEFINE_DEBUGFS_ATTRIBUTE(pru_rproc_debug_ss_fops, pru_rproc_debug_ss_get,
+                        pru_rproc_debug_ss_set, "%llu\n");
 
 /*
  * Create PRU-specific debugfs entries
@@ -266,12 +266,17 @@ static void pru_rproc_create_debug_entries(struct rproc *rproc)
 
 static void pru_dispose_irq_mapping(struct pru_rproc *pru)
 {
-       while (pru->evt_count--) {
+       if (!pru->mapped_irq)
+               return;
+
+       while (pru->evt_count) {
+               pru->evt_count--;
                if (pru->mapped_irq[pru->evt_count] > 0)
                        irq_dispose_mapping(pru->mapped_irq[pru->evt_count]);
        }
 
        kfree(pru->mapped_irq);
+       pru->mapped_irq = NULL;
 }
 
 /*
@@ -284,7 +289,7 @@ static int pru_handle_intrmap(struct rproc *rproc)
        struct pru_rproc *pru = rproc->priv;
        struct pru_irq_rsc *rsc = pru->pru_interrupt_map;
        struct irq_fwspec fwspec;
-       struct device_node *irq_parent;
+       struct device_node *parent, *irq_parent;
        int i, ret = 0;
 
        /* not having pru_interrupt_map is not an error */
@@ -307,16 +312,31 @@ static int pru_handle_intrmap(struct rproc *rproc)
        pru->evt_count = rsc->num_evts;
        pru->mapped_irq = kcalloc(pru->evt_count, sizeof(unsigned int),
                                  GFP_KERNEL);
-       if (!pru->mapped_irq)
+       if (!pru->mapped_irq) {
+               pru->evt_count = 0;
                return -ENOMEM;
+       }
 
        /*
         * parse and fill in system event to interrupt channel and
-        * channel-to-host mapping
+        * channel-to-host mapping. The interrupt controller to be used
+        * for these mappings for a given PRU remoteproc is always its
+        * corresponding sibling PRUSS INTC node.
         */
-       irq_parent = of_irq_find_parent(pru->dev->of_node);
+       parent = of_get_parent(dev_of_node(pru->dev));
+       if (!parent) {
+               kfree(pru->mapped_irq);
+               pru->mapped_irq = NULL;
+               pru->evt_count = 0;
+               return -ENODEV;
+       }
+
+       irq_parent = of_get_child_by_name(parent, "interrupt-controller");
+       of_node_put(parent);
        if (!irq_parent) {
                kfree(pru->mapped_irq);
+               pru->mapped_irq = NULL;
+               pru->evt_count = 0;
                return -ENODEV;
        }
 
@@ -332,16 +352,20 @@ static int pru_handle_intrmap(struct rproc *rproc)
 
                pru->mapped_irq[i] = irq_create_fwspec_mapping(&fwspec);
                if (!pru->mapped_irq[i]) {
-                       dev_err(dev, "failed to get virq\n");
-                       ret = pru->mapped_irq[i];
+                       dev_err(dev, "failed to get virq for fw mapping %d: event %d chnl %d host %d\n",
+                               i, fwspec.param[0], fwspec.param[1],
+                               fwspec.param[2]);
+                       ret = -EINVAL;
                        goto map_fail;
                }
        }
+       of_node_put(irq_parent);
 
        return ret;
 
 map_fail:
        pru_dispose_irq_mapping(pru);
+       of_node_put(irq_parent);
 
        return ret;
 }
@@ -387,8 +411,7 @@ static int pru_rproc_stop(struct rproc *rproc)
        pru_control_write_reg(pru, PRU_CTRL_CTRL, val);
 
        /* dispose irq mapping - new firmware can provide new mapping */
-       if (pru->mapped_irq)
-               pru_dispose_irq_mapping(pru);
+       pru_dispose_irq_mapping(pru);
 
        return 0;
 }
@@ -483,7 +506,7 @@ static void *pru_i_da_to_va(struct pru_rproc *pru, u32 da, size_t len)
  * core for any PRU client drivers. The PRU Instruction RAM access is restricted
  * only to the PRU loader code.
  */
-static void *pru_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len)
+static void *pru_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
 {
        struct pru_rproc *pru = rproc->priv;