]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - processor-sdk/open-amp.git/blobdiff - lib/common/hil.c
hil: add API to enable vdev IPI
[processor-sdk/open-amp.git] / lib / common / hil.c
index b522aa2ac31d18635dd0454582f2949dd14c908b..f832d6b7aab82899d2b7f1171d8e033840fde293 100644 (file)
  **************************************************************************/
 
 #include "openamp/hil.h"
+#include "openamp/remoteproc.h"
 #include <metal/io.h>
 #include <metal/alloc.h>
 #include <metal/device.h>
 #include <metal/shmem.h>
 #include <metal/utilities.h>
+#include <metal/time.h>
 
 #define DEFAULT_VRING_MEM_SIZE 0x10000
 
@@ -106,6 +108,7 @@ struct hil_proc *hil_create_proc(struct hil_platform_ops *ops,
        for (i = 0; i < HIL_MAX_NUM_VRINGS; i++)
                proc->vdev.vring_info[i].io = &hil_devmem_generic_io;
 
+       metal_mutex_init(&proc->lock);
        metal_list_add_tail(&procs, &proc->node);
 
        return proc;
@@ -131,6 +134,7 @@ void hil_delete_proc(struct hil_proc *proc)
                if (proc ==
                        metal_container_of(node, struct hil_proc, node)) {
                        metal_list_del(&proc->node);
+                       metal_mutex_acquire(&proc->lock);
                        proc->ops->release(proc);
                        /* Close shmem device */
                        dev = proc->sh_buff.dev;
@@ -153,6 +157,8 @@ void hil_delete_proc(struct hil_proc *proc)
                                }
                        }
 
+                       metal_mutex_release(&proc->lock);
+                       metal_mutex_deinit(&proc->lock);
                        metal_free_memory(proc);
                        return;
                }
@@ -171,20 +177,6 @@ int hil_init_proc(struct hil_proc *proc)
        }
        return 0;
 }
-/**
- * hil_isr()
- *
- * This function is called when interrupt is received for the vring.
- * This function gets the corresponding virtqueue and generates
- * call back for it.
- *
- * @param vring_hw   - pointer to vring control block
- *
- */
-void hil_isr(struct proc_vring *vring_hw)
-{
-       virtqueue_notification(vring_hw->vq);
-}
 
 /**
  * hil_get_chnl_info
@@ -204,6 +196,26 @@ struct proc_chnl *hil_get_chnl_info(struct hil_proc *proc, int *num_chnls)
        return (proc->chnls);
 }
 
+void hil_notified(struct hil_proc *proc, uint32_t notifyid)
+{
+       struct proc_vdev *pvdev = &proc->vdev;
+       struct fw_rsc_vdev *vdev_rsc = pvdev->vdev_info;
+       int i;
+       if (vdev_rsc->status & VIRTIO_CONFIG_STATUS_NEEDS_RESET) {
+               if (pvdev->rst_cb)
+                       pvdev->rst_cb(proc, 0);
+       } else {
+               for(i = 0; i < (int)pvdev->num_vrings; i++) {
+                       struct fw_rsc_vdev_vring *vring_rsc;
+                       vring_rsc = &vdev_rsc->vring[i];
+                       if (notifyid == (uint32_t)(-1) ||
+                               notifyid == vring_rsc->notifyid)
+                               virtqueue_notification(
+                                       pvdev->vring_info[i].vq);
+               }
+       }
+}
+
 /**
  * hil_get_vdev_info
  *
@@ -235,7 +247,28 @@ struct proc_vdev *hil_get_vdev_info(struct hil_proc *proc)
  */
 struct proc_vring *hil_get_vring_info(struct proc_vdev *vdev, int *num_vrings)
 {
+       struct fw_rsc_vdev *vdev_rsc;
+       struct fw_rsc_vdev_vring *vring_rsc;
+       struct proc_vring *vring;
+       int i;
 
+       vdev_rsc = vdev->vdev_info;
+       if (vdev_rsc) {
+               vring = &vdev->vring_info[0];
+               for (i = 0; i < vdev_rsc->num_of_vrings; i++) {
+                       /* Initialize vring with vring resource */
+                       vring_rsc = &vdev_rsc->vring[i];
+                       vring[i].num_descs = vring_rsc->num;
+                       vring[i].align = vring_rsc->align;
+                       /* Enable acccess to vring memory region */
+                       vring[i].vaddr =
+                               metal_io_mem_map(
+                                       (metal_phys_addr_t)vring_rsc->da,
+                                       vring[i].io,
+                                       vring_size(vring_rsc->num,
+                                       vring_rsc->align));
+               }
+       }
        *num_vrings = vdev->num_vrings;
        return (vdev->vring_info);
 
@@ -258,6 +291,36 @@ struct proc_shm *hil_get_shm_info(struct hil_proc *proc)
        return (&proc->sh_buff);
 }
 
+void hil_free_vqs(struct virtio_device *vdev)
+{
+       struct hil_proc *proc = vdev->device;
+       struct proc_vdev *pvdev = &proc->vdev;
+       int num_vrings = (int)pvdev->num_vrings;
+       int i;
+
+       metal_mutex_acquire(&proc->lock);
+       for(i = 0; i < num_vrings; i++) {
+               struct proc_vring *pvring = &pvdev->vring_info[i];
+               struct virtqueue *vq = pvring->vq;
+               if (vq) {
+                       virtqueue_free(vq);
+                       pvring->vq = 0;
+               }
+       }
+       metal_mutex_release(&proc->lock);
+}
+
+int hil_enable_vdev_notification(struct hil_proc *proc, int id)
+{
+       /* We only support single vdev in hil_proc */
+       (void)id;
+       if (!proc)
+               return -1;
+       if (proc->ops->enable_interrupt)
+               proc->ops->enable_interrupt(&proc->vdev.intr_info);
+       return 0;
+}
+
 /**
  * hil_enable_vring_notifications()
  *
@@ -279,12 +342,31 @@ int hil_enable_vring_notifications(int vring_index, struct virtqueue *vq)
        vring_hw->vq = vq;
 
        if (proc_hw->ops->enable_interrupt) {
-               proc_hw->ops->enable_interrupt(vring_hw);
+               proc_hw->ops->enable_interrupt(&vring_hw->intr_info);
        }
 
        return 0;
 }
 
+/**
+ * hil_vdev_notify()
+ *
+ * This function generates IPI to let the other side know that there is
+ * update in the vritio dev configs
+ *
+ * @param vdev - pointer to the viritio device
+ *
+ */
+void hil_vdev_notify(struct virtio_device *vdev)
+{
+       struct hil_proc *proc = vdev->device;
+       struct proc_vdev *pvdev = &proc->vdev;
+
+       if (proc->ops->notify) {
+               proc->ops->notify(proc, &pvdev->intr_info);
+       }
+}
+
 /**
  * hil_vring_notify()
  *
@@ -360,7 +442,7 @@ int hil_boot_cpu(struct hil_proc *proc, unsigned int start_addr)
                proc->ops->boot_cpu(proc, start_addr);
        }
 #if defined (OPENAMP_BENCHMARK_ENABLE)
-       boot_time_stamp = env_get_timestamp();
+       boot_time_stamp = metal_get_timestamp();
 #endif
 
        return 0;
@@ -380,7 +462,7 @@ void hil_shutdown_cpu(struct hil_proc *proc)
                proc->ops->shutdown_cpu(proc);
        }
 #if defined (OPENAMP_BENCHMARK_ENABLE)
-       shutdown_time_stamp = env_get_timestamp();
+       shutdown_time_stamp = metal_get_timestamp();
 #endif
 }
 
@@ -480,7 +562,23 @@ int hil_set_vring (struct hil_proc *proc, int index,
        return 0;
 }
 
-int hil_set_ipi (struct hil_proc *proc, int index,
+int hil_set_vdev_ipi (struct hil_proc *proc, int index,
+                unsigned int irq, void *data)
+{
+       struct proc_intr *vring_intr;
+
+       /* As we support only one vdev for now */
+       (void)index;
+
+       if (!proc)
+               return -1;
+       vring_intr = &proc->vdev.intr_info;
+       vring_intr->vect_id = irq;
+       vring_intr->data = data;
+       return 0;
+}
+
+int hil_set_vring_ipi (struct hil_proc *proc, int index,
                 unsigned int irq, void *data)
 {
        struct proc_intr *vring_intr;