Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
W
White Rabbit Switch - Software
Manage
Activity
Members
Labels
Plan
Issues
85
Issue boards
Milestones
Wiki
Code
Merge requests
4
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Releases
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Projects
White Rabbit Switch - Software
Commits
fe1ed782
Commit
fe1ed782
authored
2 years ago
by
Adam Wujek
Browse files
Options
Downloads
Patches
Plain Diff
[BUG:
#243
] userspace/wrsw_hal: Make HAL to be notified from the kernel about link down/up.
Signed-off-by:
Adam Wujek
<
dev_public@wujek.eu
>
parent
6ffe5a28
Branches
Branches containing commit
Tags
Tags containing commit
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
userspace/wrsw_hal/hal_port_fsm.c
+141
-6
141 additions, 6 deletions
userspace/wrsw_hal/hal_port_fsm.c
userspace/wrsw_hal/hal_ports.c
+28
-0
28 additions, 0 deletions
userspace/wrsw_hal/hal_ports.c
userspace/wrsw_hal/hal_ports.h
+1
-0
1 addition, 0 deletions
userspace/wrsw_hal/hal_ports.h
with
170 additions
and
6 deletions
userspace/wrsw_hal/hal_port_fsm.c
+
141
−
6
View file @
fe1ed782
...
@@ -12,8 +12,10 @@
...
@@ -12,8 +12,10 @@
#include
<linux/if_ether.h>
#include
<linux/if_ether.h>
#include
<linux/if_arp.h>
#include
<linux/if_arp.h>
#include
<linux/if.h>
#include
<linux/if.h>
#include
<linux/rtnetlink.h>
#include
<stdlib.h>
#include
<stdlib.h>
#include
<rt_ipc.h>
#include
<rt_ipc.h>
#include
<errno.h>
#include
<libwr/hal_shmem.h>
#include
<libwr/hal_shmem.h>
#include
<libwr/switch_hw.h>
#include
<libwr/switch_hw.h>
...
@@ -66,6 +68,7 @@ static int port_fsm_state_link_up(fsm_t *fsm, int eventMsk, int isNewState);
...
@@ -66,6 +68,7 @@ static int port_fsm_state_link_up(fsm_t *fsm, int eventMsk, int isNewState);
static
void
init_port
(
struct
hal_port_state
*
ps
);
static
void
init_port
(
struct
hal_port_state
*
ps
);
static
void
reset_port
(
struct
hal_port_state
*
ps
);
static
void
reset_port
(
struct
hal_port_state
*
ps
);
static
int
get_port_link_state
(
struct
hal_port_state
*
ps
,
int
*
linkUp
);
static
int
get_port_link_state
(
struct
hal_port_state
*
ps
,
int
*
linkUp
);
static
int
link_status_process_netlink
(
struct
hal_port_state
*
ports
);
static
fsm_state_table_entry_t
port_fsm_states
[]
=
static
fsm_state_table_entry_t
port_fsm_states
[]
=
{
{
...
@@ -363,9 +366,11 @@ static int port_fsm_build_events(fsm_t *fsm) {
...
@@ -363,9 +366,11 @@ static int port_fsm_build_events(fsm_t *fsm) {
void
hal_port_state_fsm_init_all
(
struct
hal_port_state
*
ports
,
halGlobalLPDC_t
*
globalLpdc
)
void
hal_port_state_fsm_init_all
(
struct
hal_port_state
*
ports
,
halGlobalLPDC_t
*
globalLpdc
)
{
{
int
portIndex
;
int
portIndex
;
uint32_t
bmcr
;
struct
hal_port_state
*
ps
;
for
(
portIndex
=
0
;
portIndex
<
HAL_MAX_PORTS
;
portIndex
++
)
{
for
(
portIndex
=
0
;
portIndex
<
HAL_MAX_PORTS
;
portIndex
++
)
{
struct
hal_port_state
*
ps
=
&
ports
[
portIndex
];
ps
=
&
ports
[
portIndex
];
if
(
ps
->
in_use
)
if
(
ps
->
in_use
)
{
{
...
@@ -383,6 +388,28 @@ void hal_port_state_fsm_init_all( struct hal_port_state * ports, halGlobalLPDC_t
...
@@ -383,6 +388,28 @@ void hal_port_state_fsm_init_all( struct hal_port_state * ports, halGlobalLPDC_t
hal_port_tx_setup_init_all
(
ports
,
globalLpdc
);
hal_port_tx_setup_init_all
(
ports
,
globalLpdc
);
hal_port_rx_setup_init_all
(
ports
);
hal_port_rx_setup_init_all
(
ports
);
hal_port_pll_setup_init_all
(
ports
);
hal_port_pll_setup_init_all
(
ports
);
/* Read initial link state (up or down).
* NOTE: Check with RTM_NEWLINK can only notify about changes, does not
* read the current state. */
for
(
portIndex
=
0
;
portIndex
<
HAL_MAX_PORTS
;
portIndex
++
)
{
ps
=
&
ports
[
portIndex
];
/* Skip not used ports */
if
(
!
ps
->
in_use
)
continue
;
pcs_readl
(
ps
,
MII_BMCR
,
&
bmcr
);
ps
->
evt_powerDown
=
(
bmcr
&
BMCR_PDOWN
);
if
(
get_port_link_state
(
ps
,
&
ps
->
evt_linkUp
)
<
0
)
{
/* IOTCL error : We put -1 in the link state.
* It will be considered as invalid */
ps
->
evt_linkUp
=
-
1
;
}
fsm_generic_run
(
&
ps
->
fsm
);
}
}
}
/* Call FSM for on all ports */
/* Call FSM for on all ports */
...
@@ -391,6 +418,10 @@ void hal_port_state_fsm_run_all( struct hal_port_state * ports) {
...
@@ -391,6 +418,10 @@ void hal_port_state_fsm_run_all( struct hal_port_state * ports) {
hal_port_poll_rts_state
();
// Update rts state on all ports
hal_port_poll_rts_state
();
// Update rts state on all ports
/* Check if any link changed its status (up/down).
* If changed, run fsm for it. */
link_status_process_netlink
(
ports
);
/* Call state machine for all ports */
/* Call state machine for all ports */
for
(
portIndex
=
0
;
portIndex
<
HAL_MAX_PORTS
;
portIndex
++
)
{
for
(
portIndex
=
0
;
portIndex
<
HAL_MAX_PORTS
;
portIndex
++
)
{
struct
hal_port_state
*
ps
=
&
ports
[
portIndex
];
struct
hal_port_state
*
ps
=
&
ports
[
portIndex
];
...
@@ -401,11 +432,6 @@ void hal_port_state_fsm_run_all( struct hal_port_state * ports) {
...
@@ -401,11 +432,6 @@ void hal_port_state_fsm_run_all( struct hal_port_state * ports) {
ps
->
evt_powerDown
=
(
bmcr
&
BMCR_PDOWN
);
ps
->
evt_powerDown
=
(
bmcr
&
BMCR_PDOWN
);
if
(
get_port_link_state
(
ps
,
&
ps
->
evt_linkUp
)
<
0
)
{
// IOTCL error : We put -1 in the link state. It will be considered as invalid
ps
->
evt_linkUp
=-
1
;
}
fsm_generic_run
(
&
ps
->
fsm
);
fsm_generic_run
(
&
ps
->
fsm
);
}
}
}
}
...
@@ -495,3 +521,112 @@ static int get_port_link_state(struct hal_port_state * ps,int *linkUp)
...
@@ -495,3 +521,112 @@ static int get_port_link_state(struct hal_port_state * ps,int *linkUp)
return
0
;
return
0
;
}
}
static
void
link_status_process_netlink_msg
(
struct
hal_port_state
*
ports
,
struct
nlmsghdr
*
h
)
{
int
nlmsg_len
;
int
portIndex
;
int
new_state
;
struct
hal_port_state
*
ps
;
struct
ifinfomsg
*
ifi
;
struct
rtattr
*
attr
;
ifi
=
NLMSG_DATA
(
h
);
nlmsg_len
=
h
->
nlmsg_len
-
NLMSG_LENGTH
(
sizeof
(
*
ifi
));
/* Check all attributes of the NEWLINK message */
for
(
attr
=
IFLA_RTA
(
ifi
);
RTA_OK
(
attr
,
nlmsg_len
);
attr
=
RTA_NEXT
(
attr
,
nlmsg_len
))
{
switch
(
attr
->
rta_type
)
{
case
IFLA_IFNAME
:
/* Match interface of incoming message to wri port
* (via interface name) */
for
(
portIndex
=
0
;
portIndex
<
HAL_MAX_PORTS
;
portIndex
++
)
{
ps
=
&
ports
[
portIndex
];
/* Skip not used ports */
if
(
!
ps
->
in_use
)
continue
;
if
(
!
strncmp
((
char
*
)
RTA_DATA
(
attr
),
ps
->
name
,
sizeof
(
ps
->
name
)))
{
new_state
=
!!
(
ifi
->
ifi_flags
&
IFF_RUNNING
);
if
(
ps
->
evt_linkUp
==
new_state
)
continue
;
pr_info
(
"%s: Link state change detected"
": was %s, is %s
\n
"
,
ps
->
name
,
ps
->
evt_linkUp
?
"up"
:
"down"
,
new_state
?
"up"
:
"down"
);
ps
->
evt_linkUp
=
new_state
;
/* Run fsm for this port to be sure that
* link down/up event is reflected in
* fsm state. */
fsm_generic_run
(
&
ps
->
fsm
);
}
}
break
;
default:
break
;
}
}
}
static
int
link_status_process_netlink
(
struct
hal_port_state
*
ports
)
{
int
ret
;
static
char
buf
[
8192
];
struct
iovec
iov
=
{
buf
,
sizeof
(
buf
)};
struct
sockaddr_nl
peer
;
struct
msghdr
m
=
{
&
peer
,
sizeof
(
peer
),
&
iov
,
1
};
struct
nlmsghdr
*
h
;
/* Pocess all available messages */
while
(
1
)
{
/* NOTE: Check with RTM_NEWLINK can only notify about changes,
* does not read the current state. */
ret
=
recvmsg
(
halPorts
.
hal_link_state_fd
,
&
m
,
MSG_DONTWAIT
);
if
(
ret
<
0
&&
(
errno
==
EAGAIN
||
errno
==
EWOULDBLOCK
))
{
/* No message available */
return
1
;
}
if
(
ret
<
0
)
{
/* Other error */
pr_error
(
"%s: recvmsg(netlink): %s
\n
"
,
__func__
,
strerror
(
errno
));
return
-
1
;
}
for
(
h
=
(
struct
nlmsghdr
*
)
buf
;
NLMSG_OK
(
h
,
ret
);
h
=
NLMSG_NEXT
(
h
,
ret
))
{
if
(
h
->
nlmsg_type
==
NLMSG_DONE
)
break
;
if
(
h
->
nlmsg_type
==
NLMSG_ERROR
)
{
pr_error
(
"%s: netlink message error
\n
"
,
__func__
);
continue
;
}
if
(
h
->
nlmsg_type
==
RTM_NEWLINK
)
{
/* Link change detected, process it further */
link_status_process_netlink_msg
(
ports
,
h
);
continue
;
}
pr_error
(
"%s: unexpected message %i
\n
"
,
__func__
,
h
->
nlmsg_type
);
}
}
return
0
;
}
This diff is collapsed.
Click to expand it.
userspace/wrsw_hal/hal_ports.c
+
28
−
0
View file @
fe1ed782
...
@@ -14,6 +14,7 @@
...
@@ -14,6 +14,7 @@
#include
<linux/if_ether.h>
#include
<linux/if_ether.h>
#include
<linux/if_arp.h>
#include
<linux/if_arp.h>
#include
<linux/if.h>
#include
<linux/if.h>
#include
<linux/rtnetlink.h>
/* LOTs of hardware includes */
/* LOTs of hardware includes */
#include
<rt_ipc.h>
#include
<rt_ipc.h>
...
@@ -102,6 +103,7 @@ static timer_parameter_t _timerParameters[] = {
...
@@ -102,6 +103,7 @@ static timer_parameter_t _timerParameters[] = {
/* prototypes */
/* prototypes */
static
int
hal_port_check_lpdc_support
(
struct
hal_port_state
*
ps
);
static
int
hal_port_check_lpdc_support
(
struct
hal_port_state
*
ps
);
static
void
link_status_prepare_fd
(
int
*
fd
);
/* checks if the port is supported by the FPGA firmware */
/* checks if the port is supported by the FPGA firmware */
static
int
hal_port_check_presence
(
const
char
*
if_name
,
unsigned
char
*
mac
)
static
int
hal_port_check_presence
(
const
char
*
if_name
,
unsigned
char
*
mac
)
...
@@ -233,6 +235,9 @@ int hal_port_shmem_init(char *logfilename)
...
@@ -233,6 +235,9 @@ int hal_port_shmem_init(char *logfilename)
pr_error
(
"Can't create socket: %s
\n
"
,
strerror
(
errno
));
pr_error
(
"Can't create socket: %s
\n
"
,
strerror
(
errno
));
return
-
1
;
return
-
1
;
}
}
link_status_prepare_fd
(
&
halPorts
.
hal_link_state_fd
);
/* Allocate the ports in shared memory, so wr_mon etc can see them
/* Allocate the ports in shared memory, so wr_mon etc can see them
Use lock since some (like rtud) wait for hal to be available */
Use lock since some (like rtud) wait for hal to be available */
hal_shmem_hdr
=
wrs_shm_get
(
wrs_shm_hal
,
"wrsw_hal"
,
hal_shmem_hdr
=
wrs_shm_get
(
wrs_shm_hal
,
"wrsw_hal"
,
...
@@ -802,3 +807,26 @@ void hal_port_update_info(char *iface_name, int mode, int synchronized){
...
@@ -802,3 +807,26 @@ void hal_port_update_info(char *iface_name, int mode, int synchronized){
}
}
}
}
/* This prepares polling using netlink, so we get notification on change */
static
void
link_status_prepare_fd
(
int
*
fd
)
{
struct
sockaddr_nl
addr
=
{};
*
fd
=
socket
(
AF_NETLINK
,
SOCK_RAW
,
NETLINK_ROUTE
);
if
(
*
fd
<
0
)
{
pr_error
(
"%s: socket(netlink): %s
\n
"
,
__func__
,
strerror
(
errno
));
*
fd
=
-
1
;
return
;
}
addr
.
nl_family
=
AF_NETLINK
;
addr
.
nl_pid
=
getpid
();
addr
.
nl_groups
=
RTMGRP_LINK
;
if
(
bind
(
*
fd
,
(
struct
sockaddr
*
)
&
addr
,
sizeof
(
addr
))
<
0
)
{
pr_error
(
"%s: bind(netlink): %s
\n
"
,
__func__
,
strerror
(
errno
));
*
fd
=
-
1
;
return
;
}
return
;
}
This diff is collapsed.
Click to expand it.
userspace/wrsw_hal/hal_ports.h
+
1
−
0
View file @
fe1ed782
...
@@ -17,6 +17,7 @@ typedef struct {
...
@@ -17,6 +17,7 @@ typedef struct {
struct
hal_port_state
*
ports
;
struct
hal_port_state
*
ports
;
int
numberOfPorts
;
int
numberOfPorts
;
int
hal_port_fd
;
/* An fd of always opened raw sockets for ioctl()-ing Ethernet devices */
int
hal_port_fd
;
/* An fd of always opened raw sockets for ioctl()-ing Ethernet devices */
int
hal_link_state_fd
;
/* RT subsystem PLL state, polled regularly via mini-ipc */
/* RT subsystem PLL state, polled regularly via mini-ipc */
struct
rts_pll_state
rts_state
;
struct
rts_pll_state
rts_state
;
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment