Commit f1dc7ba8 authored by Dimitris Lampridis's avatar Dimitris Lampridis

sw: fix sync_id for multi sunc users on same HMQ

parent 522441ae
......@@ -321,12 +321,7 @@ static inline int rt_action_run(enum trtl_mq_type type,
msg_out.header->flags = TRTL_HMQ_HEADER_FLAG_ACK;
msg_out.header->msg_id = 0;
msg_out.header->len = 0;
/*
* Every combination of CPU+HMQ has a unique sync_id. We avoid copying
* the sync_id from the incoming message and prefer rebuilding it in the
* firmware in order to detect possible wrong deliveries of sync messages.
*/
msg_out.header->sync_id = ((idx_mq << 8) | trtl_get_core_id()) & 0xffff;
msg_out.header->sync_id = msg->header->sync_id;
err = action(msg, &msg_out);
if (err)
......
......@@ -193,12 +193,14 @@ struct trtl_hmq {
* Describe the consumer of the output slot
* @list: to keep it in our local queue
* @hmq: reference to opened HMQ
* @lock: to protect flags, wait_id
* @lock: to protect flags
* @flags: status flags for syncrhonous messages
* @idx_r: index read pointer for the message circular buffer. This is
* protected by the input buffer lock. Accessing this field means that
* you are accessing the buffer input, and in order to do that you need
* to get the input buffer spinlock. So, we are protecting this
* variable as well.
* @sync_id: Unique sync id to be used when waiting for sync answer
*/
struct trtl_hmq_user {
struct list_head list;
......@@ -206,7 +208,7 @@ struct trtl_hmq_user {
spinlock_t lock;
unsigned long flags;
unsigned int idx_r;
uint16_t wait_id;
uint16_t sync_id;
};
......
......@@ -18,6 +18,7 @@
#include <linux/circ_buf.h>
#include <linux/uaccess.h>
#include <linux/version.h>
#include <linux/idr.h>
#include <mockturtle/hw/mockturtle_queue.h>
#include <mockturtle/hw/mockturtle_cpu_csr.h>
......@@ -44,7 +45,7 @@ static bool trtl_msg_is_ack(struct trtl_msg *msg)
static bool trtl_hmq_user_msg_is_answer(struct trtl_hmq_user *user,
struct trtl_msg *msg)
{
return (user->wait_id == msg->hdr.sync_id);
return (user->sync_id == msg->hdr.sync_id);
}
/**
......@@ -54,12 +55,10 @@ static bool trtl_hmq_user_msg_is_answer(struct trtl_hmq_user *user,
*
* Return: 0 on success otherwise a negative error number
*/
static void trtl_hmq_user_sync_wait_set(struct trtl_hmq_user *user,
uint16_t id)
static void trtl_hmq_user_sync_wait_set(struct trtl_hmq_user *user)
{
spin_lock(&user->lock);
user->flags |= TRTL_HMQ_USER_FLAG_SYNC_WAIT;
user->wait_id = id;
spin_unlock(&user->lock);
}
......@@ -528,6 +527,8 @@ static unsigned int trtl_hmq_buf_idx_get(struct mturtle_hmq_buffer *buf,
return idx_r_absolute & (buf->entries - 1);
}
static DEFINE_IDA(trtl_hmq_user_ida);
/**
* It simply opens a HMQ device
*/
......@@ -536,6 +537,7 @@ static int trtl_hmq_open(struct inode *inode, struct file *file)
struct trtl_hmq_user *user;
struct trtl_hmq *hmq;
int m = iminor(inode);
int id;
unsigned long flags;
hmq = to_trtl_hmq(minors[m]);
......@@ -553,6 +555,12 @@ static int trtl_hmq_open(struct inode *inode, struct file *file)
hmq->n_user++;
spin_unlock_irqrestore(&hmq->lock, flags);
/* Assign new unique 16-bit sync_id to this user */
id = ida_simple_get(&trtl_hmq_user_ida, 0, 65536, GFP_KERNEL);
if (id < 0)
return id;
user->sync_id = id;
spin_lock_irqsave(&hmq->buf_in.lock, flags);
/* Point to the current position in buffer */
user->idx_r = hmq->buf_in.idx_w;
......@@ -573,6 +581,7 @@ static int trtl_hmq_release(struct inode *inode, struct file *f)
/* Remove user from the list */
spin_lock_irqsave(&hmq->lock, flags);
hmq->n_user--;
ida_simple_remove(&trtl_hmq_user_ida, user->sync_id);
list_del(&user->list);
kfree(user);
spin_unlock_irqrestore(&hmq->lock, flags);
......@@ -591,7 +600,6 @@ static int trtl_hmq_write_one(struct trtl_hmq_user *user,
const char __user *ubuf)
{
struct trtl_hmq *hmq = user->hmq;
struct trtl_cpu *cpu = to_trtl_cpu(hmq->dev.parent);
struct trtl_msg *msg;
int err = 0, copy_size;
size_t size;
......@@ -617,12 +625,9 @@ static int trtl_hmq_write_one(struct trtl_hmq_user *user,
}
if (trtl_hmq_user_is_sync(user)) {
/* Every combination of CPU+HMQ has a unique sync_id */
uint16_t sync_id = ((hmq->index << 8) | cpu->index) & 0xFFFF;
buf->msg_tmp.hdr.flags |= TRTL_HMQ_HEADER_FLAG_SYNC;
buf->msg_tmp.hdr.sync_id = sync_id;
trtl_hmq_user_sync_wait_set(user, sync_id);
buf->msg_tmp.hdr.sync_id = user->sync_id;
trtl_hmq_user_sync_wait_set(user);
}
/* don't sleep here */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment