Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
M
Mock Turtle
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
1
Issues
1
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
image/svg+xml
Discourse
Discourse
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Projects
Mock Turtle
Commits
3388e161
Commit
3388e161
authored
Mar 21, 2019
by
Federico Vaga
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
sw: new sync message implementation
Signed-off-by:
Federico Vaga
<
federico.vaga@cern.ch
>
parent
58d2c00a
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
238 additions
and
159 deletions
+238
-159
linux-driver.rst
doc/software/linux-driver.rst
+3
-0
mockturtle.h
software/include/mockturtle.h
+14
-0
mockturtle-drv.h
software/kernel/mockturtle-drv.h
+14
-1
mockturtle-hmq.c
software/kernel/mockturtle-hmq.c
+105
-4
libmockturtle-internal.h
software/lib/libmockturtle-internal.h
+1
-2
libmockturtle.c
software/lib/libmockturtle.c
+98
-152
libmockturtle.h
software/lib/libmockturtle.h
+3
-0
No files found.
doc/software/linux-driver.rst
View file @
3388e161
...
...
@@ -218,6 +218,9 @@ This *char device* provides a set of ``ioctl(2)`` commands:
.. doxygendefine:: TRTL_IOCTL_MSG_FILTER_CLEAN
.. doxygendefine:: TRTL_IOCTL_HMQ_SYNC_SET
.. doxygendefine:: TRTL_IOCTL_MSG_SYNC_ABORT
You can find the HMQ *sysfs* attributes at::
...
...
software/include/mockturtle.h
View file @
3388e161
...
...
@@ -227,6 +227,8 @@ enum trtl_ioctl_commands {
TRTL_SMEM_IO
,
/**< access to shared memory */
TRTL_MSG_FILTER_ADD
,
/**< add a message filter */
TRTL_MSG_FILTER_CLEAN
,
/**< remove all filters */
TRTL_MSG_SYNC_ABORT
,
/**< abort sync message*/
TRTL_HMQ_SYNC_SET
,
/**< Mark HMQ user context as synchronous */
};
...
...
@@ -247,7 +249,19 @@ enum trtl_ioctl_commands {
#define TRTL_IOCTL_MSG_FILTER_CLEAN _IOW(TRTL_IOCTL_MAGIC, \
TRTL_MSG_FILTER_CLEAN, \
struct trtl_msg_filter)
/**
* The IOCTL command to add a filter to an HMQ
*/
#define TRTL_IOCTL_HMQ_SYNC_SET _IOW(TRTL_IOCTL_MAGIC, \
TRTL_HMQ_SYNC_SET, \
unsigned int)
/**
* The IOCTL command to add a filter to an HMQ
*/
#define TRTL_IOCTL_MSG_SYNC_ABORT _IOW(TRTL_IOCTL_MAGIC, \
TRTL_MSG_SYNC_ABORT, \
unsigned int)
/**
* Messages descriptor for host
...
...
software/kernel/mockturtle-drv.h
View file @
3388e161
...
...
@@ -177,11 +177,22 @@ struct trtl_hmq {
struct
mturtle_hmq_buffer
buf_out
;
};
/**
* User do only sync messages
*/
#define TRTL_HMQ_USER_FLAG_SYNC BIT(0)
/**
* User is waiting for a sync answer message
*/
#define TRTL_HMQ_USER_FLAG_SYNC_WAIT BIT(1)
/**
* It describes the consumer of the output slot
* @list: to keep it in our local queue
* @hmq: reference to opened HMQ
* @lock: to protect filters
* @lock: to protect filters
, flags, wait_id
* @list_filters: list of filters to apply
* @n_filters: number of filters
* @idx_r: index read pointer for the message circular buffer. This is
...
...
@@ -194,9 +205,11 @@ struct trtl_hmq_user {
struct
list_head
list
;
struct
trtl_hmq
*
hmq
;
spinlock_t
lock
;
unsigned
long
flags
;
struct
list_head
list_filters
;
unsigned
int
n_filters
;
unsigned
int
idx_r
;
uint16_t
wait_id
;
};
...
...
software/kernel/mockturtle-hmq.c
View file @
3388e161
...
...
@@ -29,6 +29,54 @@ MODULE_PARM_DESC(hmq_buf_max_msg,
static
void
trtl_message_push
(
struct
trtl_hmq
*
hmq
,
struct
trtl_msg
*
msg
);
static
bool
trtl_hmq_user_is_sync
(
struct
trtl_hmq_user
*
user
)
{
return
(
user
->
flags
&
TRTL_HMQ_USER_FLAG_SYNC
);
}
static
bool
trtl_hmq_user_is_waiting
(
struct
trtl_hmq_user
*
user
)
{
return
(
user
->
flags
&
TRTL_HMQ_USER_FLAG_SYNC_WAIT
);
}
static
bool
trtl_msg_is_ack
(
struct
trtl_msg
*
msg
)
{
return
(
msg
->
hdr
.
flags
&
TRTL_HMQ_HEADER_FLAG_ACK
);
}
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
);
}
/**
* Set the user in waiting mode for a sync answer
* @user user
* @sync_id synchronous message identifier
*
* 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
)
{
spin_lock
(
&
user
->
lock
);
user
->
flags
|=
TRTL_HMQ_USER_FLAG_SYNC_WAIT
;
user
->
wait_id
=
id
;
spin_unlock
(
&
user
->
lock
);
}
/**
* User received the messages, do not wait anymore
* @user user
*/
static
void
trtl_hmq_user_sync_wait_clr
(
struct
trtl_hmq_user
*
user
)
{
spin_lock
(
&
user
->
lock
);
user
->
flags
&=
~
TRTL_HMQ_USER_FLAG_SYNC_WAIT
;
spin_unlock
(
&
user
->
lock
);
}
/**
* Get a valid sequence number
* @trtl: trtl device
...
...
@@ -380,6 +428,27 @@ static int trtl_hmq_filter_check(struct trtl_hmq_user *user,
return
passed
;
}
/**
* Tell if user accepts the given message
* @user: HMQ user
* @msg: message
*
* Return: true if the user can read the message, otherwise false
*/
static
bool
trtl_hmq_user_filter_one
(
struct
trtl_hmq_user
*
user
,
struct
trtl_msg
*
msg
)
{
if
(
trtl_hmq_user_is_sync
(
user
))
{
if
(
trtl_hmq_user_is_waiting
(
user
)
&&
trtl_msg_is_ack
(
msg
)
&&
trtl_hmq_user_msg_is_answer
(
user
,
msg
))
return
true
;
}
else
{
if
(
trtl_hmq_filter_check
(
user
,
msg
))
return
true
;
}
return
false
;
}
/**
* It clears the content of the HMQ
...
...
@@ -591,9 +660,10 @@ static int trtl_hmq_release(struct inode *inode, struct file *f)
* @buf: source buffer
* Return: 0 on success, otherwise a negative error number
*/
static
int
trtl_hmq_write_one
(
struct
trtl_hmq
*
hmq
,
static
int
trtl_hmq_write_one
(
struct
trtl_hmq
_user
*
user
,
const
char
__user
*
ubuf
)
{
struct
trtl_hmq
*
hmq
=
user
->
hmq
;
struct
trtl_dev
*
trtl
=
to_trtl_dev
(
hmq
->
dev
.
parent
->
parent
);
struct
trtl_msg
*
msg
;
int
err
=
0
,
copy_size
;
...
...
@@ -601,6 +671,9 @@ static int trtl_hmq_write_one(struct trtl_hmq *hmq,
struct
mturtle_hmq_buffer
*
buf
=
&
hmq
->
buf_out
;
unsigned
long
flags
;
if
(
trtl_hmq_user_is_sync
(
user
)
&&
trtl_hmq_user_is_waiting
(
user
))
return
-
EBUSY
;
/* Here we can safely sleep */
size
=
TRTL_CONFIG_ROM_MQ_SIZE_PAYLOAD
(
hmq
->
cfg
->
sizes
);
copy_size
=
sizeof
(
struct
trtl_hmq_header
);
...
...
@@ -617,6 +690,13 @@ static int trtl_hmq_write_one(struct trtl_hmq *hmq,
}
buf
->
msg_tmp
.
hdr
.
seq
=
trtl_msg_seq_get
(
trtl
);
if
(
trtl_hmq_user_is_sync
(
user
))
{
uint16_t
sync_id
=
buf
->
msg_tmp
.
hdr
.
seq
&
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
);
}
/* don't sleep here */
spin_lock_irqsave
(
&
buf
->
lock
,
flags
);
...
...
@@ -659,7 +739,7 @@ static ssize_t trtl_hmq_write(struct file *f, const char __user *buf,
count
=
0
;
mutex_lock
(
&
hmq
->
mtx
);
for
(
i
=
0
;
i
<
n_msg
;
i
++
,
curbuf
+=
sizeof
(
struct
trtl_msg
))
{
err
=
trtl_hmq_write_one
(
hmq
,
curbuf
);
err
=
trtl_hmq_write_one
(
user
,
curbuf
);
if
(
err
)
break
;
}
...
...
@@ -789,6 +869,7 @@ static long trtl_hmq_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
return
-
EFAULT
;
/* Perform commands */
mutex_lock
(
&
user
->
hmq
->
mtx
);
switch
(
cmd
)
{
case
TRTL_IOCTL_MSG_FILTER_ADD
:
err
=
trtl_ioctl_msg_filter_add
(
user
,
uarg
);
...
...
@@ -796,10 +877,24 @@ static long trtl_hmq_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
case
TRTL_MSG_FILTER_CLEAN
:
trtl_ioctl_msg_filter_clean
(
user
,
uarg
);
break
;
case
TRTL_IOCTL_MSG_SYNC_ABORT
:
if
(
trtl_hmq_user_is_sync
(
user
))
{
if
(
trtl_hmq_user_is_waiting
(
user
))
trtl_hmq_user_sync_wait_clr
(
user
);
}
else
{
err
=
-
EPERM
;
}
break
;
case
TRTL_IOCTL_HMQ_SYNC_SET
:
spin_lock
(
&
user
->
lock
);
user
->
flags
|=
TRTL_HMQ_USER_FLAG_SYNC
;
spin_unlock
(
&
user
->
lock
);
break
;
default:
pr_warn
(
"trtl: invalid ioctl command %d
\n
"
,
cmd
);
return
-
EINVAL
;
}
mutex_unlock
(
&
user
->
hmq
->
mtx
);
return
err
;
}
...
...
@@ -835,15 +930,20 @@ static ssize_t trtl_hmq_read(struct file *f, char __user *ubuf,
spin_lock_irqsave
(
&
buf
->
lock
,
flags
);
msg
=
&
buf
->
msg
[
usr
->
idx_r
++
&
(
hmq_buf_max_msg
-
1
)];
if
(
!
trtl_hmq_filter_check
(
usr
,
msg
))
{
if
(
!
trtl_hmq_user_filter_one
(
usr
,
msg
))
{
spin_unlock_irqrestore
(
&
buf
->
lock
,
flags
);
continue
;
}
copy_size
=
sizeof
(
struct
trtl_hmq_header
);
copy_size
+=
(
msg
->
hdr
.
len
*
4
);
memcpy
(
&
buf
->
msg_tmp
,
msg
,
copy_size
);
spin_unlock_irqrestore
(
&
buf
->
lock
,
flags
);
if
(
trtl_hmq_user_is_sync
(
usr
))
trtl_hmq_user_sync_wait_clr
(
usr
);
/* now we copy to user space and we can safely sleep */
if
(
copy_to_user
(
ubuf
+
count
,
&
buf
->
msg_tmp
,
copy_size
))
{
err
=
-
EFAULT
;
...
...
@@ -858,6 +958,7 @@ static ssize_t trtl_hmq_read(struct file *f, char __user *ubuf,
return
count
?
count
:
err
;
}
/**
* It filters out messages until a valid one
* @usr: pointer to a user HMQ instance
...
...
@@ -873,7 +974,7 @@ static void trtl_hmq_user_filter(struct trtl_hmq_user *usr)
/* Loop until we find a valid message for the user */
while
(
buf
->
idx_w
!=
usr
->
idx_r
)
{
msg
=
&
buf
->
msg
[
usr
->
idx_r
&
(
hmq_buf_max_msg
-
1
)];
if
(
trtl_hmq_
filter_check
(
usr
,
msg
))
if
(
trtl_hmq_
user_filter_one
(
usr
,
msg
))
break
;
usr
->
idx_r
++
;
}
...
...
software/lib/libmockturtle-internal.h
View file @
3388e161
...
...
@@ -31,9 +31,8 @@ struct trtl_desc {
int
fd_dev
;
/**< File Descriptor of the device */
int
fd_cpu
[
TRTL_MAX_CPU
];
/**< File Descriptor of the CPUs */
int
fd_hmq
[
TRTL_MAX_CPU
][
TRTL_MAX_MQ_CHAN
];
/**< File Descriptors for the HMQ */
int
fd_hmq_sync
[
TRTL_MAX_CPU
][
TRTL_MAX_MQ_CHAN
];
/**< File Descriptors for the HMQ in sync mode */
struct
trtl_config_rom
cfgrom
;
/**< synthesis configuration */
struct
trtl_dev
*
trtl_sync
;
/**< token for synchronous operations */
};
#endif
software/lib/libmockturtle.c
View file @
3388e161
...
...
@@ -51,37 +51,6 @@ static const char * const trtl_error_str[] = {
NULL
,
};
/**
* Enumeration for predefined filters
*/
enum
trtl_msg_filter_predefined
{
TRTL_MSG_FILTER_ASYNC
=
0
,
/**< filter for ASYNC messages */
TRTL_MSG_FILTER_SYNC
,
/**< filter for SYNC messages */
};
/**
* List predefined filters used within the library
*/
static
struct
trtl_msg_filter
filters
[]
=
{
[
TRTL_MSG_FILTER_ASYNC
]
=
{
.
flags
=
TRTL_MSG_FILTER_FLAG_HEADER
,
.
operation
=
TRTL_MSG_FILTER_AND
,
.
word_offset
=
0
,
/* ATTENTION: flags in the message header */
.
mask
=
(
TRTL_HMQ_HEADER_FLAG_SYNC
|
TRTL_HMQ_HEADER_FLAG_ACK
)
<<
16
,
.
value
=
0
,
},
[
TRTL_MSG_FILTER_SYNC
]
=
{
.
flags
=
TRTL_MSG_FILTER_FLAG_HEADER
,
.
operation
=
TRTL_MSG_FILTER_AND
,
.
word_offset
=
0
,
/* ATTENTION: flags in the message header */
.
mask
=
TRTL_HMQ_HEADER_FLAG_ACK
<<
16
,
.
value
=
TRTL_HMQ_HEADER_FLAG_ACK
<<
16
,
},
};
static
int
trtl_sysfs_read
(
char
*
path
,
void
*
buf
,
size_t
len
);
static
int
trtl_sysfs_write
(
char
*
path
,
void
*
buf
,
size_t
len
);
...
...
@@ -207,15 +176,13 @@ void trtl_list_free(char **list)
free
(
list
);
}
/**
* It opens a TRTL device using a string descriptor. The descriptor correspond
* to the main char device name of the Mock-Turtle.
* @param[in] device name of the device to open
*
* @return TRTL token, NULL on error and errno is appropriately set
* @return the TRTL token, NULL on error and errno is appropriately set
*/
st
atic
struct
trtl_dev
*
__
trtl_open
(
const
char
*
device
)
st
ruct
trtl_dev
*
trtl_open
(
const
char
*
device
)
{
struct
trtl_desc
*
trtl
;
char
path
[
TRTL_PATH_LEN
+
TRTL_NAME_LEN
];
...
...
@@ -263,6 +230,20 @@ static struct trtl_dev *__trtl_open(const char *device)
if
(
fd
<
0
)
goto
out_hmq_fd
;
trtl
->
fd_hmq
[
i
][
k
]
=
fd
;
fd
=
open
(
path
,
O_RDWR
);
if
(
fd
<
0
)
{
close
(
trtl
->
fd_hmq
[
i
][
k
]);
goto
out_hmq_fd
;
}
trtl
->
fd_hmq_sync
[
i
][
k
]
=
fd
;
err
=
ioctl
(
trtl
->
fd_hmq_sync
[
i
][
k
],
TRTL_IOCTL_HMQ_SYNC_SET
,
1
);
if
(
err
)
{
close
(
trtl
->
fd_hmq
[
i
][
k
]);
close
(
trtl
->
fd_hmq_sync
[
i
][
k
]);
goto
out_hmq_fd
;
}
}
}
...
...
@@ -274,6 +255,7 @@ out_hmq_fd:
while
(
i
>=
0
)
{
while
(
--
k
>=
0
)
{
close
(
trtl
->
fd_hmq
[
i
][
k
]);
close
(
trtl
->
fd_hmq_sync
[
i
][
k
]);
}
--
i
;
}
...
...
@@ -283,52 +265,6 @@ out_stat:
return
NULL
;
}
/**
* It opens a TRTL device using a string descriptor. The descriptor correspond
* to the main char device name of the Mock-Turtle.
* @param[in] device name of the device to open
* @return the TRTL token, NULL on error and errno is appropriately set
*/
struct
trtl_dev
*
trtl_open
(
const
char
*
device
)
{
struct
trtl_desc
*
wdesc
;
struct
trtl_dev
*
trtl
;
int
ret
,
i
,
k
;
trtl
=
__trtl_open
(
device
);
if
(
!
trtl
)
return
NULL
;
/* quick hack to have a separete buffering for
synchronous messages */
wdesc
=
(
struct
trtl_desc
*
)
trtl
;
wdesc
->
trtl_sync
=
__trtl_open
(
device
);
if
(
!
wdesc
->
trtl_sync
)
goto
err_open_sync
;
/* set up the filters in order to have synchorouns messages on
a different buffer */
for
(
i
=
0
;
i
<
wdesc
->
cfgrom
.
n_cpu
;
++
i
)
{
for
(
k
=
0
;
k
<
wdesc
->
cfgrom
.
n_hmq
[
i
];
++
k
)
{
ret
=
trtl_hmq_filter_add
(
trtl
,
i
,
k
,
&
filters
[
TRTL_MSG_FILTER_ASYNC
]);
if
(
ret
<
0
)
goto
err_filter
;
ret
=
trtl_hmq_filter_add
(
wdesc
->
trtl_sync
,
i
,
k
,
&
filters
[
TRTL_MSG_FILTER_SYNC
]);
if
(
ret
<
0
)
goto
err_filter
;
}
}
return
trtl
;
err_filter:
trtl_close
(
wdesc
->
trtl_sync
);
err_open_sync:
trtl_close
(
trtl
);
return
NULL
;
}
/**
* It opens a TRTL device using its device_id. The Mock-Turtle
...
...
@@ -960,6 +896,38 @@ int trtl_hmq_fd(struct trtl_dev *trtl,
return
wdesc
->
fd_hmq
[
idx_cpu
][
idx_hmq
];
}
/**
* It returns the HMQ File Descriptor
* @param[in] trtl device token
* @param[in] idx_cpu CPU index
* @param[in] idx_hmq HMQ index
* @return the file descriptor
*/
int
trtl_hmq_fd_sync
(
struct
trtl_dev
*
trtl
,
unsigned
int
idx_cpu
,
unsigned
int
idx_hmq
)
{
struct
trtl_desc
*
wdesc
=
(
struct
trtl_desc
*
)
trtl
;
return
wdesc
->
fd_hmq_sync
[
idx_cpu
][
idx_hmq
];
}
static
int
trtl_msg_read
(
int
fd
,
struct
trtl_msg
*
msg
,
unsigned
int
n
)
{
size_t
size
=
sizeof
(
*
msg
);
int
ret
;
ret
=
read
(
fd
,
msg
,
size
*
n
);
if
(
ret
<
0
)
return
ret
;
if
(
ret
%
size
)
{
/* most likely a driver problem */
errno
=
ETRTL_INVALID_MESSAGE
;
return
-
1
;
}
return
(
ret
/
size
);
}
/**
* It reads messages from a given HMQ
...
...
@@ -977,10 +945,7 @@ int trtl_msg_async_recv(struct trtl_dev *trtl,
struct
trtl_msg
*
msg
,
unsigned
int
n
)
{
struct
trtl_desc
*
wdesc
=
(
struct
trtl_desc
*
)
trtl
;
int
ret
,
size
,
fd
;
fd
=
wdesc
->
fd_hmq
[
idx_cpu
][
idx_hmq
];
int
fd
=
trtl_hmq_fd
(
trtl
,
idx_cpu
,
idx_hmq
);
/* validation */
if
(
fd
<
0
)
{
...
...
@@ -988,12 +953,18 @@ int trtl_msg_async_recv(struct trtl_dev *trtl,
return
-
1
;
}
/* Get a message from the driver */
size
=
sizeof
(
struct
trtl_msg
);
ret
=
read
(
fd
,
msg
,
size
*
n
);
return
trtl_msg_read
(
fd
,
msg
,
n
);
}
static
int
trtl_msg_write
(
int
fd
,
struct
trtl_msg
*
msg
,
unsigned
int
n
)
{
size_t
size
=
sizeof
(
*
msg
);
int
ret
;
ret
=
write
(
fd
,
msg
,
size
*
n
);
if
(
ret
<
0
)
return
ret
;
if
(
ret
%
size
of
(
struct
trtl_msg
)
)
{
return
-
1
;
if
(
ret
%
size
)
{
/* most likely a driver problem */
errno
=
ETRTL_INVALID_MESSAGE
;
return
-
1
;
...
...
@@ -1001,8 +972,6 @@ int trtl_msg_async_recv(struct trtl_dev *trtl,
return
(
ret
/
size
);
}
/**
* It writes messages to a given HMQ
* @param[in] trtl device token
...
...
@@ -1019,31 +988,32 @@ int trtl_msg_async_send(struct trtl_dev *trtl,
struct
trtl_msg
*
msg
,
unsigned
int
n
)
{
struct
trtl_desc
*
wdesc
=
(
struct
trtl_desc
*
)
trtl
;
int
ret
,
size
,
fd
;
fd
=
wdesc
->
fd_hmq
[
idx_cpu
][
idx_hmq
];
int
fd
=
trtl_hmq_fd
(
trtl
,
idx_cpu
,
idx_hmq
);
/* validation */
if
(
fd
<
0
)
{
errno
=
ETRTL_HMQ_CLOSE
;
return
-
1
;
}
/* Get a message from the driver */
size
=
sizeof
(
struct
trtl_msg
);
ret
=
write
(
fd
,
msg
,
size
*
n
);
if
(
ret
<
0
)
return
-
1
;
if
(
ret
%
sizeof
(
struct
trtl_msg
))
{
/* most likely a driver problem */
errno
=
ETRTL_INVALID_MESSAGE
;
return
-
1
;
}
return
(
ret
/
size
);
return
trtl_msg_write
(
fd
,
msg
,
n
);
}
/**
* It adds a new filter to the given hmq descriptor
* @param[in] trtl device token
* @param[in] idx_cpu CPU index
* @param[in] idx_hmq HMQ index
* @param[in] err error code
* @return 0 on success, -1 otherwise and errno is set appropriately
*/
int
trtl_msg_sync_abort
(
struct
trtl_dev
*
trtl
,
unsigned
int
idx_cpu
,
unsigned
int
idx_hmq
,
unsigned
int
err
)
{
return
ioctl
(
trtl_hmq_fd_sync
(
trtl
,
idx_cpu
,
idx_hmq
),
TRTL_IOCTL_MSG_SYNC_ABORT
,
err
);
}
/**
* It sends and receives a synchronous message. It is up to the user to set the
...
...
@@ -1066,79 +1036,55 @@ int trtl_msg_sync(struct trtl_dev *trtl,
struct
trtl_msg
*
msg_r
,
int
timeout
)
{
struct
trtl_desc
*
wdesc
=
(
struct
trtl_desc
*
)
trtl
;
struct
polltrtl
p
;
#if 0
struct trtl_msg_filter f_sync = {
.flags = TRTL_MSG_FILTER_FLAG_HEADER,
.operation = TRTL_MSG_FILTER_AND,
.word_offset = 1, /* ATTENTION: sync_id in the message header */
.mask = 0xFFFF0000,
};
#endif
int
ret
;
msg_s
->
hdr
.
flags
|=
TRTL_HMQ_HEADER_FLAG_SYNC
;
#if 0
/* FIXME: commented out as the filter is never removed.
The filter shouldn't be needed as the synchronous messages are
always sent sequentially - if there is only one process. */
f_sync.value = (msg_s->hdr.sync_id << 16);
ret = trtl_hmq_filter_add(wdesc->trtl_sync, idx_cpu, idx_hmq,
&f_sync);
if (ret < 0)
return -1;
#endif
struct
pollfd
p
;
int
ret
,
fd
;
/* send message */
ret
=
trtl_msg_async_send
(
wdesc
->
trtl_sync
,
idx_cpu
,
idx_hmq
,
msg_s
,
1
);
fd
=
trtl_hmq_fd_sync
(
trtl
,
idx_cpu
,
idx_hmq
);
ret
=
trtl_msg_write
(
fd
,
msg_s
,
1
);
if
(
ret
<
0
)
return
-
1
;
goto
err
;
if
(
ret
==
0
)
{
errno
=
ETRTL_MSG_SYNC_FAILED_SEND
;
return
-
1
;
goto
err
;
}
/* wait answer */
p
.
trtl
=
wdesc
->
trtl_sync
;
p
.
idx_cpu
=
idx_cpu
;
p
.
idx_hmq
=
idx_hmq
;
p
.
fd
=
fd
;
p
.
events
=
POLLIN
|
POLLERR
;
ret
=
trtl_msg_
poll
(
&
p
,
1
,
timeout
);
ret
=
poll
(
&
p
,
1
,
timeout
);
if
(
ret
<
0
)
return
-
1
;
/* I (git blame) know, this if is over-complicated */
if
(
ret
==
0
)
{
errno
=
ETRTL_MSG_SYNC_FAILED_RECV_TIMEOUT
;
return
-
1
;
goto
err_abort
;
}
if
((
p
.
revents
&
POLLERR
))
{
errno
=
ETRTL_MSG_SYNC_FAILED_RECV_POLLERR
;
return
-
1
;
goto
err_abort
;
}
if
(
!
(
p
.
revents
&
POLLIN
))
{
errno
=
ETRTL_MSG_SYNC_FAILED_RECV
;
return
-
1
;
goto
err_abort
;
}
/* read the answer */
ret
=
trtl_msg_
async_recv
(
wdesc
->
trtl_sync
,
idx_cpu
,
idx_hmq
,
msg_r
,
1
);
ret
=
trtl_msg_
read
(
fd
,
msg_r
,
1
);
if
(
ret
<
0
)
return
-
1
;
goto
err
;
if
(
ret
==
0
)
{
errno
=
ETRTL_MSG_SYNC_FAILED_RECV
;
return
-
1
;
}
/* paranoid check, the driver should be right */
if
(
msg_s
->
hdr
.
sync_id
!=
msg_r
->
hdr
.
sync_id
)
{
errno
=
ETRTL_MSG_SYNC_FAILED_INVAL
;
return
-
1
;
goto
err
;
}
return
0
;
err_abort:
trtl_msg_sync_abort
(
trtl
,
idx_cpu
,
idx_hmq
,
errno
);
err:
return
-
1
;
}
...
...
software/lib/libmockturtle.h
View file @
3388e161
...
...
@@ -161,6 +161,9 @@ extern int trtl_hmq_filter_clean(struct trtl_dev *trtl,
extern
int
trtl_hmq_fd
(
struct
trtl_dev
*
trtl
,
unsigned
int
idx_cpu
,
unsigned
int
idx_hmq
);
extern
int
trtl_hmq_fd_sync
(
struct
trtl_dev
*
trtl
,
unsigned
int
idx_cpu
,
unsigned
int
idx_hmq
);
extern
int
trtl_msg_async_send
(
struct
trtl_dev
*
trtl
,
unsigned
int
idx_cpu
,
unsigned
int
idx_hmq
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment