Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
O
OpenXG-RAN
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
canghaiwuhen
OpenXG-RAN
Commits
a473dc04
Commit
a473dc04
authored
Nov 09, 2017
by
Raymond Knopp
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
integration step 1. Common LTE/NB-IoT definitions for initial RF integration.
parent
0e810867
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
38 additions
and
180 deletions
+38
-180
openair1/PHY/LTE_TRANSPORT/dlsch_coding.c
openair1/PHY/LTE_TRANSPORT/dlsch_coding.c
+2
-1
openair1/PHY/LTE_TRANSPORT/proto_NB_IoT.h
openair1/PHY/LTE_TRANSPORT/proto_NB_IoT.h
+1
-1
openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c
openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c
+2
-1
openair1/PHY/defs.h
openair1/PHY/defs.h
+3
-159
openair1/PHY/defs_NB_IoT.h
openair1/PHY/defs_NB_IoT.h
+2
-0
openair1/SCHED/defs_NB_IoT.h
openair1/SCHED/defs_NB_IoT.h
+6
-6
openair1/SCHED/phy_procedures_lte_eNb.c
openair1/SCHED/phy_procedures_lte_eNb.c
+3
-1
openair1/SCHED/phy_procedures_lte_eNb_NB_IoT.c
openair1/SCHED/phy_procedures_lte_eNb_NB_IoT.c
+6
-6
targets/RT/USER/lte-enb.c
targets/RT/USER/lte-enb.c
+13
-5
No files found.
openair1/PHY/LTE_TRANSPORT/dlsch_coding.c
View file @
a473dc04
...
...
@@ -395,7 +395,7 @@ void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch)
}
}
/*
int dlsch_encoding_2threads0(te_params *tep) {
LTE_eNB_DLSCH_t *dlsch = tep->dlsch;
...
...
@@ -686,6 +686,7 @@ int dlsch_encoding_2threads(PHY_VARS_eNB *eNB,
return(0);
}
*/
int
dlsch_encoding
(
PHY_VARS_eNB
*
eNB
,
unsigned
char
*
a
,
...
...
openair1/PHY/LTE_TRANSPORT/proto_NB_IoT.h
View file @
a473dc04
...
...
@@ -223,7 +223,7 @@ void ulsch_extract_rbs_single_NB_IoT(int32_t **rxdataF,
// uint32_t first_rb,
uint32_t
UL_RB_ID_NB_IoT
,
// index of UL NB_IoT resource block
uint8_t
N_sc_RU
,
// number of subcarriers in UL
//
uint32_t I_sc, // subcarrier indication field
uint32_t
I_sc
,
// subcarrier indication field
uint32_t
nb_rb
,
uint8_t
l
,
uint8_t
Ns
,
...
...
openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c
View file @
a473dc04
...
...
@@ -292,7 +292,7 @@ uint8_t extract_cqi_crc(uint8_t *cqi,uint8_t CQI_LENGTH)
/*
int ulsch_decoding_data_2thread0(td_params* tdp) {
PHY_VARS_eNB *eNB = tdp->eNB;
...
...
@@ -728,6 +728,7 @@ int ulsch_decoding_data_2thread(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr
return( (ret>proc->tdp.ret) ? ret : proc->tdp.ret );
}
*/
int
ulsch_decoding_data
(
PHY_VARS_eNB
*
eNB
,
int
UE_id
,
int
harq_pid
,
int
llr8_flag
)
{
...
...
openair1/PHY/defs.h
View file @
a473dc04
...
...
@@ -139,6 +139,8 @@ static inline void* malloc16_clear( size_t size )
#define NB_BANDS_MAX 8
#include "defs_common.h"
#ifdef OCP_FRAMEWORK
#include <enums.h>
#else
...
...
@@ -188,35 +190,7 @@ typedef struct {
}
PHY_VARS_RN
;
/// Context data structure for RX/TX portion of subframe processing
typedef
struct
{
/// Component Carrier index
uint8_t
CC_id
;
/// timestamp transmitted to HW
openair0_timestamp
timestamp_tx
;
/// subframe to act upon for transmission
int
subframe_tx
;
/// subframe to act upon for reception
int
subframe_rx
;
/// frame to act upon for transmission
int
frame_tx
;
/// frame to act upon for reception
int
frame_rx
;
/// \brief Instance count for RXn-TXnp4 processing thread.
/// \internal This variable is protected by \ref mutex_rxtx.
int
instance_cnt_rxtx
;
/// pthread structure for RXn-TXnp4 processing thread
pthread_t
pthread_rxtx
;
/// pthread attributes for RXn-TXnp4 processing thread
pthread_attr_t
attr_rxtx
;
/// condition variable for tx processing thread
pthread_cond_t
cond_rxtx
;
/// mutex for RXn-TXnp4 processing thread
pthread_mutex_t
mutex_rxtx
;
/// scheduling parameters for RXn-TXnp4 thread
struct
sched_param
sched_param_rxtx
;
}
eNB_rxtx_proc_t
;
typedef
struct
{
struct
PHY_VARS_eNB_s
*
eNB
;
...
...
@@ -232,137 +206,7 @@ typedef struct {
int
G
;
}
te_params
;
/// Context data structure for eNB subframe processing
typedef
struct
eNB_proc_t_s
{
/// Component Carrier index
uint8_t
CC_id
;
/// thread index
int
thread_index
;
/// timestamp received from HW
openair0_timestamp
timestamp_rx
;
/// timestamp to send to "slave rru"
openair0_timestamp
timestamp_tx
;
/// subframe to act upon for reception
int
subframe_rx
;
/// symbol mask for IF4p5 reception per subframe
uint32_t
symbol_mask
[
10
];
/// subframe to act upon for PRACH
int
subframe_prach
;
/// frame to act upon for reception
int
frame_rx
;
/// frame to act upon for transmission
int
frame_tx
;
/// frame offset for secondary eNBs (to correct for frame asynchronism at startup)
int
frame_offset
;
/// frame to act upon for PRACH
int
frame_prach
;
/// \internal This variable is protected by \ref mutex_fep.
int
instance_cnt_fep
;
/// \internal This variable is protected by \ref mutex_td.
int
instance_cnt_td
;
/// \internal This variable is protected by \ref mutex_te.
int
instance_cnt_te
;
/// \brief Instance count for FH processing thread.
/// \internal This variable is protected by \ref mutex_FH.
int
instance_cnt_FH
;
/// \brief Instance count for rx processing thread.
/// \internal This variable is protected by \ref mutex_prach.
int
instance_cnt_prach
;
// instance count for over-the-air eNB synchronization
int
instance_cnt_synch
;
/// \internal This variable is protected by \ref mutex_asynch_rxtx.
int
instance_cnt_asynch_rxtx
;
/// pthread structure for FH processing thread
pthread_t
pthread_FH
;
/// pthread structure for eNB single processing thread
pthread_t
pthread_single
;
/// pthread structure for asychronous RX/TX processing thread
pthread_t
pthread_asynch_rxtx
;
/// flag to indicate first RX acquisition
int
first_rx
;
/// flag to indicate first TX transmission
int
first_tx
;
/// pthread attributes for parallel fep thread
pthread_attr_t
attr_fep
;
/// pthread attributes for parallel turbo-decoder thread
pthread_attr_t
attr_td
;
/// pthread attributes for parallel turbo-encoder thread
pthread_attr_t
attr_te
;
/// pthread attributes for FH processing thread
pthread_attr_t
attr_FH
;
/// pthread attributes for single eNB processing thread
pthread_attr_t
attr_single
;
/// pthread attributes for prach processing thread
pthread_attr_t
attr_prach
;
/// pthread attributes for over-the-air synch thread
pthread_attr_t
attr_synch
;
/// pthread attributes for asynchronous RX thread
pthread_attr_t
attr_asynch_rxtx
;
/// scheduling parameters for parallel fep thread
struct
sched_param
sched_param_fep
;
/// scheduling parameters for parallel turbo-decoder thread
struct
sched_param
sched_param_td
;
/// scheduling parameters for parallel turbo-encoder thread
struct
sched_param
sched_param_te
;
/// scheduling parameters for FH thread
struct
sched_param
sched_param_FH
;
/// scheduling parameters for single eNB thread
struct
sched_param
sched_param_single
;
/// scheduling parameters for prach thread
struct
sched_param
sched_param_prach
;
/// scheduling parameters for over-the-air synchronization thread
struct
sched_param
sched_param_synch
;
/// scheduling parameters for asynch_rxtx thread
struct
sched_param
sched_param_asynch_rxtx
;
/// pthread structure for parallel fep thread
pthread_t
pthread_fep
;
/// pthread structure for parallel turbo-decoder thread
pthread_t
pthread_td
;
/// pthread structure for parallel turbo-encoder thread
pthread_t
pthread_te
;
/// pthread structure for PRACH thread
pthread_t
pthread_prach
;
/// pthread structure for eNB synch thread
pthread_t
pthread_synch
;
/// condition variable for parallel fep thread
pthread_cond_t
cond_fep
;
/// condition variable for parallel turbo-decoder thread
pthread_cond_t
cond_td
;
/// condition variable for parallel turbo-encoder thread
pthread_cond_t
cond_te
;
/// condition variable for FH thread
pthread_cond_t
cond_FH
;
/// condition variable for PRACH processing thread;
pthread_cond_t
cond_prach
;
// condition variable for over-the-air eNB synchronization
pthread_cond_t
cond_synch
;
/// condition variable for asynch RX/TX thread
pthread_cond_t
cond_asynch_rxtx
;
/// mutex for parallel fep thread
pthread_mutex_t
mutex_fep
;
/// mutex for parallel turbo-decoder thread
pthread_mutex_t
mutex_td
;
/// mutex for parallel turbo-encoder thread
pthread_mutex_t
mutex_te
;
/// mutex for FH
pthread_mutex_t
mutex_FH
;
/// mutex for PRACH thread
pthread_mutex_t
mutex_prach
;
// mutex for over-the-air eNB synchronization
pthread_mutex_t
mutex_synch
;
/// mutex for asynch RX/TX thread
pthread_mutex_t
mutex_asynch_rxtx
;
/// parameters for turbo-decoding worker thread
td_params
tdp
;
/// parameters for turbo-encoding worker thread
te_params
tep
;
/// set of scheduling variables RXn-TXnp4 threads
eNB_rxtx_proc_t
proc_rxtx
[
2
];
/// number of slave threads
int
num_slaves
;
/// array of pointers to slaves
struct
eNB_proc_t_s
**
slave_proc
;
}
eNB_proc_t
;
/// Context data structure for RX/TX portion of subframe processing
...
...
openair1/PHY/defs_NB_IoT.h
View file @
a473dc04
...
...
@@ -146,6 +146,8 @@ static inline void* malloc16_clear( size_t size )
#define NB_BANDS_MAX_NB_IoT 8
#include "defs_common.h"
#ifdef OCP_FRAMEWORK
#include <enums.h>
#else
...
...
openair1/SCHED/defs_NB_IoT.h
View file @
a473dc04
...
...
@@ -19,22 +19,22 @@ enum openair_HARQ_TYPE_NB_IoT {
void
process_schedule_rsp_NB_IoT
(
Sched_Rsp_t
*
sched_rsp
,
PHY_VARS_eNB_NB_IoT
*
eNB
,
eNB_rxtx_proc_
NB_IoT_
t
*
proc
);
eNB_rxtx_proc_t
*
proc
);
/*Processing the ue-specific resources for uplink in NB-IoT*/
void
phy_procedures_eNB_uespec_RX_NB_IoT
(
PHY_VARS_eNB_NB_IoT
*
eNB
,
eNB_rxtx_proc_
NB_IoT_
t
*
proc
,
UL_IND_t
*
UL_INFO
);
void
phy_procedures_eNB_uespec_RX_NB_IoT
(
PHY_VARS_eNB_NB_IoT
*
eNB
,
eNB_rxtx_proc_t
*
proc
,
UL_IND_t
*
UL_INFO
);
/* For NB-IoT, we put NPBCH in later part, since it would be scheduled by MAC scheduler,this generates NRS/NPSS/NSSS*/
void
common_signal_procedures_NB_IoT
(
PHY_VARS_eNB_NB_IoT
*
eNB
,
eNB_rxtx_proc_
NB_IoT_
t
*
proc
);
void
common_signal_procedures_NB_IoT
(
PHY_VARS_eNB_NB_IoT
*
eNB
,
eNB_rxtx_proc_t
*
proc
);
/*Generate the ulsch params and do the mapping for the FAPI style parameters to OAI, and then do the packing*/
void
generate_eNB_ulsch_params_NB_IoT
(
PHY_VARS_eNB_NB_IoT
*
eNB
,
eNB_rxtx_proc_
NB_IoT_
t
*
proc
,
nfapi_hi_dci0_request_pdu_t
*
hi_dci0_pdu
);
void
generate_eNB_ulsch_params_NB_IoT
(
PHY_VARS_eNB_NB_IoT
*
eNB
,
eNB_rxtx_proc_t
*
proc
,
nfapi_hi_dci0_request_pdu_t
*
hi_dci0_pdu
);
/*Generate the dlsch params and do the mapping for the FAPI style parameters to OAI, and then do the packing*/
void
generate_eNB_dlsch_params_NB_IoT
(
PHY_VARS_eNB_NB_IoT
*
eNB
,
eNB_rxtx_proc_
NB_IoT_
t
*
proc
,
nfapi_dl_config_request_pdu_t
*
dl_config_pdu
);
void
generate_eNB_dlsch_params_NB_IoT
(
PHY_VARS_eNB_NB_IoT
*
eNB
,
eNB_rxtx_proc_t
*
proc
,
nfapi_dl_config_request_pdu_t
*
dl_config_pdu
);
/*Process all the scheduling result from MAC and also common signals.*/
void
phy_procedures_eNB_TX_NB_IoT
(
PHY_VARS_eNB_NB_IoT
*
eNB
,
eNB_rxtx_proc_
NB_IoT_
t
*
proc
,
int
do_meas
);
void
phy_procedures_eNB_TX_NB_IoT
(
PHY_VARS_eNB_NB_IoT
*
eNB
,
eNB_rxtx_proc_t
*
proc
,
int
do_meas
);
int8_t
find_ue_NB_IoT
(
uint16_t
rnti
,
PHY_VARS_eNB_NB_IoT
*
eNB
);
...
...
openair1/SCHED/phy_procedures_lte_eNb.c
View file @
a473dc04
...
...
@@ -2677,6 +2677,7 @@ void init_fep_thread(PHY_VARS_eNB *eNB,pthread_attr_t *attr_fep) {
}
/*
extern void *td_thread(void*);
void init_td_thread(PHY_VARS_eNB *eNB,pthread_attr_t *attr_td) {
...
...
@@ -2693,6 +2694,7 @@ void init_td_thread(PHY_VARS_eNB *eNB,pthread_attr_t *attr_td) {
}
extern void *te_thread(void*);
void init_te_thread(PHY_VARS_eNB *eNB,pthread_attr_t *attr_te) {
...
...
@@ -2709,7 +2711,7 @@ void init_te_thread(PHY_VARS_eNB *eNB,pthread_attr_t *attr_te) {
pthread_create(&proc->pthread_te, attr_te, te_thread, (void*)&proc->tep);
}
*/
void
eNB_fep_full_2thread
(
PHY_VARS_eNB
*
eNB
,
eNB_rxtx_proc_t
*
proc_rxtx
)
{
...
...
openair1/SCHED/phy_procedures_lte_eNb_NB_IoT.c
View file @
a473dc04
...
...
@@ -213,7 +213,7 @@ uint32_t is_SIB1_NB_IoT(const frame_t frameP,
* It generates NRS/NPSS/NSSS
*
*/
void
common_signal_procedures_NB_IoT
(
PHY_VARS_eNB_NB_IoT
*
eNB
,
eNB_rxtx_proc_
NB_IoT_
t
*
proc
)
void
common_signal_procedures_NB_IoT
(
PHY_VARS_eNB_NB_IoT
*
eNB
,
eNB_rxtx_proc_t
*
proc
)
{
NB_IoT_DL_FRAME_PARMS
*
fp
=
&
eNB
->
frame_parms_NB_IoT
;
int
**
txdataF
=
eNB
->
common_vars
.
txdataF
[
0
];
...
...
@@ -269,7 +269,7 @@ void common_signal_procedures_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,eNB_rxtx_proc_NB_I
}
void
phy_procedures_eNB_uespec_RX_NB_IoT
(
PHY_VARS_eNB_NB_IoT
*
eNB
,
eNB_rxtx_proc_
NB_IoT_
t
*
proc
,
UL_IND_t
*
UL_INFO
)
void
phy_procedures_eNB_uespec_RX_NB_IoT
(
PHY_VARS_eNB_NB_IoT
*
eNB
,
eNB_rxtx_proc_t
*
proc
,
UL_IND_t
*
UL_INFO
)
{
//RX processing for ue-specific resources (i
...
...
@@ -592,7 +592,7 @@ void phy_procedures_eNB_uespec_RX_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,eNB_rxtx_proc_
/*Generate eNB ndlsch params for NB-IoT from the NPDCCH PDU of the DCI, modify the input to the Sched Rsp variable*/
void
generate_eNB_dlsch_params_NB_IoT
(
PHY_VARS_eNB_NB_IoT
*
eNB
,
eNB_rxtx_proc_
NB_IoT_
t
*
proc
,
nfapi_dl_config_request_pdu_t
*
dl_config_pdu
)
void
generate_eNB_dlsch_params_NB_IoT
(
PHY_VARS_eNB_NB_IoT
*
eNB
,
eNB_rxtx_proc_t
*
proc
,
nfapi_dl_config_request_pdu_t
*
dl_config_pdu
)
{
int
UE_id
=
-
1
;
NB_IoT_DL_FRAME_PARMS
*
fp
=
&
eNB
->
frame_parms_NB_IoT
;
...
...
@@ -725,7 +725,7 @@ void generate_eNB_dlsch_params_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,eNB_rxtx_proc_NB_
void
generate_eNB_ulsch_params_NB_IoT
(
PHY_VARS_eNB_NB_IoT
*
eNB
,
eNB_rxtx_proc_
NB_IoT_
t
*
proc
,
nfapi_hi_dci0_request_pdu_t
*
hi_dci0_pdu
)
{
void
generate_eNB_ulsch_params_NB_IoT
(
PHY_VARS_eNB_NB_IoT
*
eNB
,
eNB_rxtx_proc_t
*
proc
,
nfapi_hi_dci0_request_pdu_t
*
hi_dci0_pdu
)
{
int
UE_id
=
-
1
;
//int harq_pid = 0;
...
...
@@ -781,7 +781,7 @@ void generate_eNB_ulsch_params_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,eNB_rxtx_proc_NB_
* ** redundancy version exist only in UL for NB-IoT and not in DL
*/
void
npdsch_procedures
(
PHY_VARS_eNB_NB_IoT
*
eNB
,
eNB_rxtx_proc_
NB_IoT_
t
*
proc
,
//Context data structure for RX/TX portion of subframe processing
eNB_rxtx_proc_t
*
proc
,
//Context data structure for RX/TX portion of subframe processing
NB_IoT_eNB_NDLSCH_t
*
ndlsch
,
//int num_pdcch_symbols, //(BCOM says are not needed
uint8_t
*
pdu
...
...
@@ -1043,7 +1043,7 @@ extern int oai_exit;
*/
void
phy_procedures_eNB_TX_NB_IoT
(
PHY_VARS_eNB_NB_IoT
*
eNB
,
eNB_rxtx_proc_
NB_IoT_
t
*
proc
,
eNB_rxtx_proc_t
*
proc
,
int
do_meas
)
{
int
frame
=
proc
->
frame_tx
;
...
...
targets/RT/USER/lte-enb.c
View file @
a473dc04
...
...
@@ -584,7 +584,7 @@ int wait_CCs(eNB_rxtx_proc_t *proc) {
*
* For the moment the NB-IoT implementation foresees a single thread implementation
* */
static
inline
int
rxtx_NB_IoT
(
PHY_VARS_eNB_NB_IoT
*
eNB
,
eNB_rxtx_proc_
NB_IoT_
t
*
proc
,
char
*
thread_name
)
{
static
inline
int
rxtx_NB_IoT
(
PHY_VARS_eNB_NB_IoT
*
eNB
,
eNB_rxtx_proc_t
*
proc
,
char
*
thread_name
)
{
//Allocate memory for the structures used by PHY and MAC
UL_IND_t
*
UL_INFO
;
...
...
@@ -1599,10 +1599,12 @@ static void* eNB_thread_single( void* param ) {
static
int
eNB_thread_single_status
;
eNB_proc_t
*
proc
=
(
eNB_proc_t
*
)
param
;
eNB_rxtx_proc_t
*
proc_rxtx
=
&
proc
->
proc_rxtx
[
0
];
eNB_proc_t
*
proc
=
(
eNB_proc_t
*
)
param
;
eNB_rxtx_proc_t
*
proc_rxtx
=
&
proc
->
proc_rxtx
[
0
];
PHY_VARS_eNB
*
eNB
=
PHY_vars_eNB_g
[
0
][
proc
->
CC_id
];
PHY_VARS_eNB_NB_IoT
*
eNB_NB_IoT
=
PHY_vars_eNB_NB_IoT_g
[
0
][
proc
->
CC_id
];
LTE_DL_FRAME_PARMS
*
fp
=
&
eNB
->
frame_parms
;
NB_IoT_DL_FRAME_PARMS
*
fp_NB_IoT
=
&
eNB_NB_IoT
->
frame_parms
;
eNB
->
CC_id
=
proc
->
CC_id
;
void
*
rxp
[
2
],
*
rxp2
[
2
];
...
...
@@ -1754,6 +1756,7 @@ static void* eNB_thread_single( void* param ) {
wakeup_slaves
(
proc
);
if
(
rxtx
(
eNB
,
proc_rxtx
,
"eNB_thread_single"
)
<
0
)
break
;
if
(
rxtx_NB_IoT
(
eNB_NB_IoT
,
proc_rxtx
,
"eNB_thread_single"
)
<
0
)
break
;
}
...
...
@@ -1764,10 +1767,13 @@ static void* eNB_thread_single( void* param ) {
}
extern
void
init_fep_thread
(
PHY_VARS_eNB
*
,
pthread_attr_t
*
);
extern
void
init_td_thread
(
PHY_VARS_eNB
*
,
pthread_attr_t
*
);
/*
extern void init_td_thread(PHY_VARS_eNB *, pthread_attr_t *);
extern void init_te_thread(PHY_VARS_eNB *, pthread_attr_t *);
*/
void
init_eNB_proc
(
int
inst
)
{
int
i
=
0
;
...
...
@@ -1845,8 +1851,10 @@ void init_eNB_proc(int inst) {
else
{
pthread_create
(
&
proc
->
pthread_single
,
attr_single
,
eNB_thread_single
,
&
eNB
->
proc
);
init_fep_thread
(
eNB
,
attr_fep
);
/*
init_td_thread(eNB,attr_td);
init_te_thread(eNB,attr_te);
*/
}
pthread_create
(
&
proc
->
pthread_prach
,
attr_prach
,
eNB_thread_prach
,
&
eNB
->
proc
);
pthread_create
(
&
proc
->
pthread_synch
,
attr_synch
,
eNB_thread_synch
,
eNB
);
...
...
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