// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2018-2020 Broadcom.
*/
#include <linux/delay.h>
#include <linux/fs.h>
#include <linux/hash.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/poll.h>
#include <linux/sizes.h>
#include <linux/spinlock.h>
#include <linux/timer.h>
#include "bcm_vk.h"
#include "bcm_vk_msg.h"
#include "bcm_vk_sg.h"
/* functions to manipulate the transport id in msg block */
#define BCM_VK_MSG_Q_SHIFT 4
#define BCM_VK_MSG_Q_MASK 0xF
#define BCM_VK_MSG_ID_MASK 0xFFF
#define BCM_VK_DMA_DRAIN_MAX_MS 2000
/* number x q_size will be the max number of msg processed per loop */
#define BCM_VK_MSG_PROC_MAX_LOOP 2
/* module parameter */
static bool hb_mon = true;
module_param(hb_mon, bool, 0444);
MODULE_PARM_DESC(hb_mon, "Monitoring heartbeat continuously.\n");
static int batch_log = 1;
module_param(batch_log, int, 0444);
MODULE_PARM_DESC(batch_log, "Max num of logs per batch operation.\n");
static bool hb_mon_is_on(void)
{
return hb_mon;
}
static u32 get_q_num(const struct vk_msg_blk *msg)
{
u32 q_num = msg->trans_id & BCM_VK_MSG_Q_MASK;
if (q_num >= VK_MSGQ_PER_CHAN_MAX)
q_num = VK_MSGQ_NUM_DEFAULT;
return q_num;
}
static void set_q_num(struct vk_msg_blk *msg, u32 q_num)
{
u32 trans_q;
if (q_num >= VK_MSGQ_PER_CHAN_MAX)
trans_q = VK_MSGQ_NUM_DEFAULT;
else
trans_q = q_num;
msg->trans_id = (msg->trans_id & ~BCM_VK_MSG_Q_MASK) | trans_q;
}
static u32 get_msg_id(const struct vk_msg_blk *msg)
{
return ((msg->trans_id >> BCM_VK_MSG_Q_SHIFT) & BCM_VK_MSG_ID_MASK);
}
static void set_msg_id(struct vk_msg_blk *msg, u32 val)
{
msg->trans_id = (val << BCM_VK_MSG_Q_SHIFT) | get_q_num(msg);
}
static u32 msgq_inc(const struct bcm_vk_sync_qinfo *qinfo, u32 idx, u32 inc)
{
return ((idx + inc) & qinfo->q_mask);
}
static
struct vk_msg_blk __iomem *msgq_blk_addr(const struct bcm_vk_sync_qinfo *qinfo,
u32 idx)
{
return qinfo->q_start + (VK_MSGQ_BLK_SIZE * idx);
}
static u32 msgq_occupied(const struct bcm_vk_msgq __iomem *msgq,
const struct bcm_vk_sync_qinfo *qinfo)
{
u32 wr_idx, rd_idx;
wr_idx = readl_relaxed(&msgq->wr_idx);
rd_idx = readl_relaxe