new file mode 100644
@@ -0,0 +1,116 @@
+// SPDX-License-Identifier: MIT
+/* Copyright(c) 2019-2021, Celeno Communications Ltd. */
+
+#include "dfs/radar.h"
+#include "dfs/dfs.h"
+#ifdef CONFIG_CL_PCIE
+#include "bus/pci/irq.h"
+#include "ipc_shared.h"
+#endif
+
+static void cl_radar_handler(struct cl_hw *cl_hw, struct cl_radar_elem *radar_elem,
+ unsigned long time)
+{
+ /* Retrieve the radar pulses structure */
+ struct cl_radar_pulse_array *pulses = radar_elem->radarbuf_ptr;
+
+ cl_dfs_pulse_process(cl_hw, (struct cl_radar_pulse *)pulses->pulse,
+ pulses->cnt, time);
+}
+
+static void cl_radar_tasklet(unsigned long data)
+{
+ struct cl_hw *cl_hw = (struct cl_hw *)data;
+ struct cl_radar_queue_elem *radar_elem = NULL;
+ unsigned long flags = 0;
+
+ while (!list_empty(&cl_hw->radar_queue.head)) {
+ spin_lock_irqsave(&cl_hw->radar_queue.lock, flags);
+ radar_elem = list_first_entry(&cl_hw->radar_queue.head,
+ struct cl_radar_queue_elem, list);
+ list_del(&radar_elem->list);
+ spin_unlock_irqrestore(&cl_hw->radar_queue.lock, flags);
+
+ cl_radar_handler(radar_elem->cl_hw, &radar_elem->radar_elem,
+ radar_elem->time);
+
+ kfree(radar_elem->radar_elem.radarbuf_ptr);
+ kfree(radar_elem);
+ }
+
+#ifdef CONFIG_CL_PCIE
+ if (!test_bit(CL_DEV_STOP_HW, &cl_hw->drv_flags))
+ cl_irq_enable(cl_hw, cl_hw->ipc_e2a_irq.radar);
+#endif
+}
+
+void cl_radar_init(struct cl_hw *cl_hw)
+{
+ INIT_LIST_HEAD(&cl_hw->radar_queue.head);
+
+ tasklet_init(&cl_hw->radar_tasklet, cl_radar_tasklet, (unsigned long)cl_hw);
+
+ spin_lock_init(&cl_hw->radar_queue.lock);
+}
+
+void cl_radar_push(struct cl_hw *cl_hw, struct cl_radar_elem *radar_elem)
+{
+ struct cl_radar_queue_elem *new_queue_elem = NULL;
+ u32 i;
+
+ new_queue_elem = kzalloc(sizeof(*new_queue_elem), GFP_ATOMIC);
+
+ if (new_queue_elem) {
+ new_queue_elem->radar_elem.radarbuf_ptr =
+ kzalloc(sizeof(*new_queue_elem->radar_elem.radarbuf_ptr), GFP_ATOMIC);
+
+ if (new_queue_elem->radar_elem.radarbuf_ptr) {
+ new_queue_elem->radar_elem.dma_addr = radar_elem->dma_addr;
+ new_queue_elem->radar_elem.radarbuf_ptr->cnt =
+ le32_to_cpu(radar_elem->radarbuf_ptr->cnt);
+
+ /* Copy into local list */
+ for (i = 0; i < ARRAY_SIZE(radar_elem->radarbuf_ptr->pulse); i++)
+ new_queue_elem->radar_elem.radarbuf_ptr->pulse[i] =
+ le64_to_cpu(radar_elem->radarbuf_ptr->pulse[i]);
+
+ new_queue_elem->time = jiffies_to_msecs(jiffies);
+ new_queue_elem->cl_hw = cl_hw;
+
+ spin_lock(&cl_hw->radar_queue.lock);
+ list_add_tail(&new_queue_elem->list, &cl_hw->radar_queue.head);
+ spin_unlock(&cl_hw->radar_queue.lock);
+ } else {
+ kfree(new_queue_elem);
+ }
+ }
+}
+
+void cl_radar_tasklet_schedule(struct cl_hw *cl_hw)
+{
+ tasklet_schedule(&cl_hw->radar_tasklet);
+}
+
+void cl_radar_flush(struct cl_hw *cl_hw)
+{
+ struct cl_radar_queue_elem *radar_elem = NULL;
+ unsigned long flags = 0;
+
+ spin_lock_irqsave(&cl_hw->radar_queue.lock, flags);
+
+ while (!list_empty(&cl_hw->radar_queue.head)) {
+ radar_elem = list_first_entry(&cl_hw->radar_queue.head,
+ struct cl_radar_queue_elem, list);
+ list_del(&radar_elem->list);
+ kfree(radar_elem->radar_elem.radarbuf_ptr);
+ kfree(radar_elem);
+ }
+
+ spin_unlock_irqrestore(&cl_hw->radar_queue.lock, flags);
+}
+
+void cl_radar_close(struct cl_hw *cl_hw)
+{
+ cl_radar_flush(cl_hw);
+ tasklet_kill(&cl_hw->radar_tasklet);
+}