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, ...@@ -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->flags = TRTL_HMQ_HEADER_FLAG_ACK;
msg_out.header->msg_id = 0; msg_out.header->msg_id = 0;
msg_out.header->len = 0; msg_out.header->len = 0;
/* msg_out.header->sync_id = msg->header->sync_id;
* 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;
err = action(msg, &msg_out); err = action(msg, &msg_out);
if (err) if (err)
......
...@@ -193,12 +193,14 @@ struct trtl_hmq { ...@@ -193,12 +193,14 @@ struct trtl_hmq {
* Describe the consumer of the output slot * Describe the consumer of the output slot
* @list: to keep it in our local queue * @list: to keep it in our local queue
* @hmq: reference to opened HMQ * @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 * @idx_r: index read pointer for the message circular buffer. This is
* protected by the input buffer lock. Accessing this field means that * 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 * 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 * to get the input buffer spinlock. So, we are protecting this
* variable as well. * variable as well.
* @sync_id: Unique sync id to be used when waiting for sync answer
*/ */
struct trtl_hmq_user { struct trtl_hmq_user {
struct list_head list; struct list_head list;
...@@ -206,7 +208,7 @@ struct trtl_hmq_user { ...@@ -206,7 +208,7 @@ struct trtl_hmq_user {
spinlock_t lock; spinlock_t lock;
unsigned long flags; unsigned long flags;
unsigned int idx_r; unsigned int idx_r;
uint16_t wait_id; uint16_t sync_id;
}; };
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/circ_buf.h> #include <linux/circ_buf.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/version.h> #include <linux/version.h>
#include <linux/idr.h>
#include <mockturtle/hw/mockturtle_queue.h> #include <mockturtle/hw/mockturtle_queue.h>
#include <mockturtle/hw/mockturtle_cpu_csr.h> #include <mockturtle/hw/mockturtle_cpu_csr.h>
...@@ -44,7 +45,7 @@ static bool trtl_msg_is_ack(struct trtl_msg *msg) ...@@ -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, static bool trtl_hmq_user_msg_is_answer(struct trtl_hmq_user *user,
struct trtl_msg *msg) 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, ...@@ -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 * Return: 0 on success otherwise a negative error number
*/ */
static void trtl_hmq_user_sync_wait_set(struct trtl_hmq_user *user, static void trtl_hmq_user_sync_wait_set(struct trtl_hmq_user *user)
uint16_t id)
{ {
spin_lock(&user->lock); spin_lock(&user->lock);
user->flags |= TRTL_HMQ_USER_FLAG_SYNC_WAIT; user->flags |= TRTL_HMQ_USER_FLAG_SYNC_WAIT;
user->wait_id = id;
spin_unlock(&user->lock); spin_unlock(&user->lock);
} }
...@@ -528,6 +527,8 @@ static unsigned int trtl_hmq_buf_idx_get(struct mturtle_hmq_buffer *buf, ...@@ -528,6 +527,8 @@ static unsigned int trtl_hmq_buf_idx_get(struct mturtle_hmq_buffer *buf,
return idx_r_absolute & (buf->entries - 1); return idx_r_absolute & (buf->entries - 1);
} }
static DEFINE_IDA(trtl_hmq_user_ida);
/** /**
* It simply opens a HMQ device * It simply opens a HMQ device
*/ */
...@@ -536,6 +537,7 @@ static int trtl_hmq_open(struct inode *inode, struct file *file) ...@@ -536,6 +537,7 @@ static int trtl_hmq_open(struct inode *inode, struct file *file)
struct trtl_hmq_user *user; struct trtl_hmq_user *user;
struct trtl_hmq *hmq; struct trtl_hmq *hmq;
int m = iminor(inode); int m = iminor(inode);
int id;
unsigned long flags; unsigned long flags;
hmq = to_trtl_hmq(minors[m]); hmq = to_trtl_hmq(minors[m]);
...@@ -553,6 +555,12 @@ static int trtl_hmq_open(struct inode *inode, struct file *file) ...@@ -553,6 +555,12 @@ static int trtl_hmq_open(struct inode *inode, struct file *file)
hmq->n_user++; hmq->n_user++;
spin_unlock_irqrestore(&hmq->lock, flags); 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); spin_lock_irqsave(&hmq->buf_in.lock, flags);
/* Point to the current position in buffer */ /* Point to the current position in buffer */
user->idx_r = hmq->buf_in.idx_w; user->idx_r = hmq->buf_in.idx_w;
...@@ -573,6 +581,7 @@ static int trtl_hmq_release(struct inode *inode, struct file *f) ...@@ -573,6 +581,7 @@ static int trtl_hmq_release(struct inode *inode, struct file *f)
/* Remove user from the list */ /* Remove user from the list */
spin_lock_irqsave(&hmq->lock, flags); spin_lock_irqsave(&hmq->lock, flags);
hmq->n_user--; hmq->n_user--;
ida_simple_remove(&trtl_hmq_user_ida, user->sync_id);
list_del(&user->list); list_del(&user->list);
kfree(user); kfree(user);
spin_unlock_irqrestore(&hmq->lock, flags); spin_unlock_irqrestore(&hmq->lock, flags);
...@@ -591,7 +600,6 @@ static int trtl_hmq_write_one(struct trtl_hmq_user *user, ...@@ -591,7 +600,6 @@ static int trtl_hmq_write_one(struct trtl_hmq_user *user,
const char __user *ubuf) const char __user *ubuf)
{ {
struct trtl_hmq *hmq = user->hmq; struct trtl_hmq *hmq = user->hmq;
struct trtl_cpu *cpu = to_trtl_cpu(hmq->dev.parent);
struct trtl_msg *msg; struct trtl_msg *msg;
int err = 0, copy_size; int err = 0, copy_size;
size_t size; size_t size;
...@@ -617,12 +625,9 @@ static int trtl_hmq_write_one(struct trtl_hmq_user *user, ...@@ -617,12 +625,9 @@ static int trtl_hmq_write_one(struct trtl_hmq_user *user,
} }
if (trtl_hmq_user_is_sync(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.flags |= TRTL_HMQ_HEADER_FLAG_SYNC;
buf->msg_tmp.hdr.sync_id = sync_id; buf->msg_tmp.hdr.sync_id = user->sync_id;
trtl_hmq_user_sync_wait_set(user, sync_id); trtl_hmq_user_sync_wait_set(user);
} }
/* don't sleep here */ /* 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