Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
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
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
e77c6276
Commit
e77c6276
authored
Jul 08, 2004
by
Russell King
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[MMC] Use a consistent naming to refer to mmc_request,
mmc_blk_request and request structures to avoid confusion.
parent
fa4f257c
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
99 additions
and
99 deletions
+99
-99
drivers/mmc/mmc.c
drivers/mmc/mmc.c
+31
-32
drivers/mmc/mmc_block.c
drivers/mmc/mmc_block.c
+32
-32
drivers/mmc/mmci.c
drivers/mmc/mmci.c
+14
-14
drivers/mmc/mmci.h
drivers/mmc/mmci.h
+1
-1
drivers/mmc/pxamci.c
drivers/mmc/pxamci.c
+18
-17
include/linux/mmc/mmc.h
include/linux/mmc/mmc.h
+3
-3
No files found.
drivers/mmc/mmc.c
View file @
e77c6276
...
...
@@ -62,26 +62,25 @@ static const unsigned int tacc_mant[] = {
/**
* mmc_request_done - finish processing an MMC command
* @host: MMC host which completed command
* @cmd: MMC command which completed
* @err: MMC error code
* @mrq: MMC request which completed
*
* MMC drivers should call this function when they have completed
* their processing of a command. This should be called before the
* data part of the command has completed.
*/
void
mmc_request_done
(
struct
mmc_host
*
host
,
struct
mmc_request
*
re
q
)
void
mmc_request_done
(
struct
mmc_host
*
host
,
struct
mmc_request
*
mr
q
)
{
struct
mmc_command
*
cmd
=
re
q
->
cmd
;
int
err
=
re
q
->
cmd
->
error
;
struct
mmc_command
*
cmd
=
mr
q
->
cmd
;
int
err
=
mr
q
->
cmd
->
error
;
DBG
(
"MMC: req done (%02x): %d: %08x %08x %08x %08x
\n
"
,
cmd
->
opcode
,
err
,
cmd
->
resp
[
0
],
cmd
->
resp
[
1
],
cmd
->
resp
[
2
],
cmd
->
resp
[
3
]);
if
(
err
&&
cmd
->
retries
)
{
cmd
->
retries
--
;
cmd
->
error
=
0
;
host
->
ops
->
request
(
host
,
re
q
);
}
else
if
(
re
q
->
done
)
{
req
->
done
(
re
q
);
host
->
ops
->
request
(
host
,
mr
q
);
}
else
if
(
mr
q
->
done
)
{
mrq
->
done
(
mr
q
);
}
}
...
...
@@ -90,49 +89,49 @@ EXPORT_SYMBOL(mmc_request_done);
/**
* mmc_start_request - start a command on a host
* @host: MMC host to start command on
* @
cmd: MMC command
to start
* @
mrq: MMC request
to start
*
* Queue a command on the specified host. We expect the
* caller to be holding the host lock with interrupts disabled.
*/
void
mmc_start_request
(
struct
mmc_host
*
host
,
struct
mmc_request
*
re
q
)
mmc_start_request
(
struct
mmc_host
*
host
,
struct
mmc_request
*
mr
q
)
{
DBG
(
"MMC: starting cmd %02x arg %08x flags %08x
\n
"
,
req
->
cmd
->
opcode
,
req
->
cmd
->
arg
,
re
q
->
cmd
->
flags
);
mrq
->
cmd
->
opcode
,
mrq
->
cmd
->
arg
,
mr
q
->
cmd
->
flags
);
WARN_ON
(
host
->
card_busy
==
NULL
);
re
q
->
cmd
->
error
=
0
;
req
->
cmd
->
req
=
re
q
;
if
(
re
q
->
data
)
{
req
->
cmd
->
data
=
re
q
->
data
;
re
q
->
data
->
error
=
0
;
req
->
data
->
req
=
re
q
;
if
(
re
q
->
stop
)
{
req
->
data
->
stop
=
re
q
->
stop
;
re
q
->
stop
->
error
=
0
;
req
->
stop
->
req
=
re
q
;
mr
q
->
cmd
->
error
=
0
;
mrq
->
cmd
->
mrq
=
mr
q
;
if
(
mr
q
->
data
)
{
mrq
->
cmd
->
data
=
mr
q
->
data
;
mr
q
->
data
->
error
=
0
;
mrq
->
data
->
mrq
=
mr
q
;
if
(
mr
q
->
stop
)
{
mrq
->
data
->
stop
=
mr
q
->
stop
;
mr
q
->
stop
->
error
=
0
;
mrq
->
stop
->
mrq
=
mr
q
;
}
}
host
->
ops
->
request
(
host
,
re
q
);
host
->
ops
->
request
(
host
,
mr
q
);
}
EXPORT_SYMBOL
(
mmc_start_request
);
static
void
mmc_wait_done
(
struct
mmc_request
*
re
q
)
static
void
mmc_wait_done
(
struct
mmc_request
*
mr
q
)
{
complete
(
re
q
->
done_data
);
complete
(
mr
q
->
done_data
);
}
int
mmc_wait_for_req
(
struct
mmc_host
*
host
,
struct
mmc_request
*
re
q
)
int
mmc_wait_for_req
(
struct
mmc_host
*
host
,
struct
mmc_request
*
mr
q
)
{
DECLARE_COMPLETION
(
complete
);
re
q
->
done_data
=
&
complete
;
re
q
->
done
=
mmc_wait_done
;
mr
q
->
done_data
=
&
complete
;
mr
q
->
done
=
mmc_wait_done
;
mmc_start_request
(
host
,
re
q
);
mmc_start_request
(
host
,
mr
q
);
wait_for_completion
(
&
complete
);
...
...
@@ -153,19 +152,19 @@ EXPORT_SYMBOL(mmc_wait_for_req);
*/
int
mmc_wait_for_cmd
(
struct
mmc_host
*
host
,
struct
mmc_command
*
cmd
,
int
retries
)
{
struct
mmc_request
re
q
;
struct
mmc_request
mr
q
;
BUG_ON
(
host
->
card_busy
==
NULL
);
memset
(
&
re
q
,
0
,
sizeof
(
struct
mmc_request
));
memset
(
&
mr
q
,
0
,
sizeof
(
struct
mmc_request
));
memset
(
cmd
->
resp
,
0
,
sizeof
(
cmd
->
resp
));
cmd
->
retries
=
retries
;
re
q
.
cmd
=
cmd
;
mr
q
.
cmd
=
cmd
;
cmd
->
data
=
NULL
;
mmc_wait_for_req
(
host
,
&
re
q
);
mmc_wait_for_req
(
host
,
&
mr
q
);
return
cmd
->
error
;
}
...
...
drivers/mmc/mmc_block.c
View file @
e77c6276
...
...
@@ -139,7 +139,7 @@ static struct block_device_operations mmc_bdops = {
};
struct
mmc_blk_request
{
struct
mmc_request
re
q
;
struct
mmc_request
mr
q
;
struct
mmc_command
cmd
;
struct
mmc_command
stop
;
struct
mmc_data
data
;
...
...
@@ -173,58 +173,58 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
goto
cmd_err
;
do
{
struct
mmc_blk_request
rq
;
struct
mmc_blk_request
b
rq
;
struct
mmc_command
cmd
;
memset
(
&
rq
,
0
,
sizeof
(
struct
mmc_blk_request
));
rq
.
req
.
cmd
=
&
rq
.
cmd
;
rq
.
req
.
data
=
&
rq
.
data
;
rq
.
cmd
.
arg
=
req
->
sector
<<
9
;
rq
.
cmd
.
flags
=
MMC_RSP_SHORT
|
MMC_RSP_CRC
;
rq
.
data
.
r
q
=
req
;
rq
.
data
.
timeout_ns
=
card
->
csd
.
tacc_ns
*
10
;
rq
.
data
.
timeout_clks
=
card
->
csd
.
tacc_clks
*
10
;
rq
.
data
.
blksz_bits
=
md
->
block_bits
;
rq
.
data
.
blocks
=
req
->
current_nr_sectors
>>
(
md
->
block_bits
-
9
);
rq
.
stop
.
opcode
=
MMC_STOP_TRANSMISSION
;
rq
.
stop
.
arg
=
0
;
rq
.
stop
.
flags
=
MMC_RSP_SHORT
|
MMC_RSP_CRC
|
MMC_RSP_BUSY
;
memset
(
&
b
rq
,
0
,
sizeof
(
struct
mmc_blk_request
));
brq
.
mrq
.
cmd
=
&
b
rq
.
cmd
;
brq
.
mrq
.
data
=
&
b
rq
.
data
;
b
rq
.
cmd
.
arg
=
req
->
sector
<<
9
;
b
rq
.
cmd
.
flags
=
MMC_RSP_SHORT
|
MMC_RSP_CRC
;
brq
.
data
.
re
q
=
req
;
b
rq
.
data
.
timeout_ns
=
card
->
csd
.
tacc_ns
*
10
;
b
rq
.
data
.
timeout_clks
=
card
->
csd
.
tacc_clks
*
10
;
b
rq
.
data
.
blksz_bits
=
md
->
block_bits
;
b
rq
.
data
.
blocks
=
req
->
current_nr_sectors
>>
(
md
->
block_bits
-
9
);
b
rq
.
stop
.
opcode
=
MMC_STOP_TRANSMISSION
;
b
rq
.
stop
.
arg
=
0
;
b
rq
.
stop
.
flags
=
MMC_RSP_SHORT
|
MMC_RSP_CRC
|
MMC_RSP_BUSY
;
if
(
rq_data_dir
(
req
)
==
READ
)
{
rq
.
cmd
.
opcode
=
rq
.
data
.
blocks
>
1
?
MMC_READ_MULTIPLE_BLOCK
:
MMC_READ_SINGLE_BLOCK
;
rq
.
data
.
flags
|=
MMC_DATA_READ
;
brq
.
cmd
.
opcode
=
b
rq
.
data
.
blocks
>
1
?
MMC_READ_MULTIPLE_BLOCK
:
MMC_READ_SINGLE_BLOCK
;
b
rq
.
data
.
flags
|=
MMC_DATA_READ
;
}
else
{
rq
.
cmd
.
opcode
=
MMC_WRITE_BLOCK
;
rq
.
cmd
.
flags
|=
MMC_RSP_BUSY
;
rq
.
data
.
flags
|=
MMC_DATA_WRITE
;
rq
.
data
.
blocks
=
1
;
b
rq
.
cmd
.
opcode
=
MMC_WRITE_BLOCK
;
b
rq
.
cmd
.
flags
|=
MMC_RSP_BUSY
;
b
rq
.
data
.
flags
|=
MMC_DATA_WRITE
;
b
rq
.
data
.
blocks
=
1
;
}
rq
.
req
.
stop
=
rq
.
data
.
blocks
>
1
?
&
rq
.
stop
:
NULL
;
brq
.
mrq
.
stop
=
brq
.
data
.
blocks
>
1
?
&
b
rq
.
stop
:
NULL
;
mmc_wait_for_req
(
card
->
host
,
&
rq
.
re
q
);
if
(
rq
.
cmd
.
error
)
{
err
=
rq
.
cmd
.
error
;
mmc_wait_for_req
(
card
->
host
,
&
brq
.
mr
q
);
if
(
b
rq
.
cmd
.
error
)
{
err
=
b
rq
.
cmd
.
error
;
printk
(
KERN_ERR
"%s: error %d sending read/write command
\n
"
,
req
->
rq_disk
->
disk_name
,
err
);
goto
cmd_err
;
}
if
(
rq_data_dir
(
req
)
==
READ
)
{
sz
=
rq
.
data
.
bytes_xfered
;
sz
=
b
rq
.
data
.
bytes_xfered
;
}
else
{
sz
=
0
;
}
if
(
rq
.
data
.
error
)
{
err
=
rq
.
data
.
error
;
if
(
b
rq
.
data
.
error
)
{
err
=
b
rq
.
data
.
error
;
printk
(
KERN_ERR
"%s: error %d transferring data
\n
"
,
req
->
rq_disk
->
disk_name
,
err
);
goto
cmd_err
;
}
if
(
rq
.
stop
.
error
)
{
err
=
rq
.
stop
.
error
;
if
(
b
rq
.
stop
.
error
)
{
err
=
b
rq
.
stop
.
error
;
printk
(
KERN_ERR
"%s: error %d sending stop command
\n
"
,
req
->
rq_disk
->
disk_name
,
err
);
goto
cmd_err
;
...
...
@@ -251,7 +251,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
goto cmd_err;
#endif
sz
=
rq
.
data
.
bytes_xfered
;
sz
=
b
rq
.
data
.
bytes_xfered
;
}
while
(
end_that_request_chunk
(
req
,
1
,
sz
));
mmc_card_release_host
(
card
);
...
...
drivers/mmc/mmci.c
View file @
e77c6276
...
...
@@ -39,23 +39,23 @@
static
unsigned
int
fmax
=
515633
;
static
void
mmci_request_end
(
struct
mmci_host
*
host
,
struct
mmc_request
*
re
q
)
mmci_request_end
(
struct
mmci_host
*
host
,
struct
mmc_request
*
mr
q
)
{
writel
(
0
,
host
->
base
+
MMCICOMMAND
);
host
->
re
q
=
NULL
;
host
->
mr
q
=
NULL
;
host
->
cmd
=
NULL
;
host
->
data
=
NULL
;
host
->
buffer
=
NULL
;
if
(
re
q
->
data
)
re
q
->
data
->
bytes_xfered
=
host
->
data_xfered
;
if
(
mr
q
->
data
)
mr
q
->
data
->
bytes_xfered
=
host
->
data_xfered
;
/*
* Need to drop the host lock here; mmc_request_done may call
* back into the driver...
*/
spin_unlock
(
&
host
->
lock
);
mmc_request_done
(
host
->
mmc
,
re
q
);
mmc_request_done
(
host
->
mmc
,
mr
q
);
spin_lock
(
&
host
->
lock
);
}
...
...
@@ -73,7 +73,7 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
datactrl
|=
MCI_DPSM_DIRECTION
;
host
->
data
=
data
;
host
->
buffer
=
data
->
rq
->
buffer
;
host
->
buffer
=
data
->
r
e
q
->
buffer
;
host
->
size
=
data
->
blocks
<<
data
->
blksz_bits
;
host
->
data_xfered
=
0
;
...
...
@@ -136,7 +136,7 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
if
(
status
&
MCI_DATAEND
)
{
host
->
data
=
NULL
;
if
(
!
data
->
stop
)
{
mmci_request_end
(
host
,
data
->
re
q
);
mmci_request_end
(
host
,
data
->
mr
q
);
}
else
/*if (readl(host->base + MMCIDATACNT) > 6)*/
{
mmci_start_command
(
host
,
data
->
stop
,
0
);
}
...
...
@@ -161,7 +161,7 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
}
if
(
!
cmd
->
data
||
cmd
->
error
!=
MMC_ERR_NONE
)
{
mmci_request_end
(
host
,
cmd
->
re
q
);
mmci_request_end
(
host
,
cmd
->
mr
q
);
}
else
if
(
!
(
cmd
->
data
->
flags
&
MMC_DATA_READ
))
{
mmci_start_data
(
host
,
cmd
->
data
);
}
...
...
@@ -262,20 +262,20 @@ static irqreturn_t mmci_irq(int irq, void *dev_id, struct pt_regs *regs)
return
IRQ_RETVAL
(
ret
);
}
static
void
mmci_request
(
struct
mmc_host
*
mmc
,
struct
mmc_request
*
re
q
)
static
void
mmci_request
(
struct
mmc_host
*
mmc
,
struct
mmc_request
*
mr
q
)
{
struct
mmci_host
*
host
=
mmc_priv
(
mmc
);
WARN_ON
(
host
->
re
q
!=
NULL
);
WARN_ON
(
host
->
mr
q
!=
NULL
);
spin_lock_irq
(
&
host
->
lock
);
host
->
req
=
re
q
;
host
->
mrq
=
mr
q
;
if
(
req
->
data
&&
re
q
->
data
->
flags
&
MMC_DATA_READ
)
mmci_start_data
(
host
,
re
q
->
data
);
if
(
mrq
->
data
&&
mr
q
->
data
->
flags
&
MMC_DATA_READ
)
mmci_start_data
(
host
,
mr
q
->
data
);
mmci_start_command
(
host
,
re
q
->
cmd
,
0
);
mmci_start_command
(
host
,
mr
q
->
cmd
,
0
);
spin_unlock_irq
(
&
host
->
lock
);
}
...
...
drivers/mmc/mmci.h
View file @
e77c6276
...
...
@@ -122,7 +122,7 @@ struct clk;
struct
mmci_host
{
void
*
base
;
struct
mmc_request
*
re
q
;
struct
mmc_request
*
mr
q
;
struct
mmc_command
*
cmd
;
struct
mmc_data
*
data
;
struct
mmc_host
*
mmc
;
...
...
drivers/mmc/pxamci.c
View file @
e77c6276
...
...
@@ -21,6 +21,7 @@
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/device.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/blkdev.h>
#include <linux/dma-mapping.h>
...
...
@@ -52,7 +53,7 @@ struct pxamci_host {
unsigned
int
imask
;
unsigned
int
power_mode
;
struct
mmc_request
*
re
q
;
struct
mmc_request
*
mr
q
;
struct
mmc_command
*
cmd
;
struct
mmc_data
*
data
;
...
...
@@ -148,7 +149,7 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)
dcmd
|=
DCMD_BURST32
|
DCMD_WIDTH1
;
host
->
dma_size
=
data
->
blocks
<<
data
->
blksz_bits
;
host
->
dma_buf
=
dma_map_single
(
mmc_dev
(
host
->
mmc
),
data
->
rq
->
buffer
,
host
->
dma_buf
=
dma_map_single
(
mmc_dev
(
host
->
mmc
),
data
->
r
e
q
->
buffer
,
host
->
dma_size
,
host
->
dma_dir
);
for
(
i
=
0
,
size
=
host
->
dma_size
,
dma
=
host
->
dma_buf
;
size
;
i
++
)
{
...
...
@@ -215,13 +216,13 @@ static void pxamci_start_cmd(struct pxamci_host *host, struct mmc_command *cmd,
pxamci_enable_irq
(
host
,
END_CMD_RES
);
}
static
void
pxamci_finish_request
(
struct
pxamci_host
*
host
,
struct
mmc_request
*
re
q
)
static
void
pxamci_finish_request
(
struct
pxamci_host
*
host
,
struct
mmc_request
*
mr
q
)
{
DBG
(
"PXAMCI: request done
\n
"
);
host
->
re
q
=
NULL
;
host
->
mr
q
=
NULL
;
host
->
cmd
=
NULL
;
host
->
data
=
NULL
;
mmc_request_done
(
host
->
mmc
,
re
q
);
mmc_request_done
(
host
->
mmc
,
mr
q
);
}
static
int
pxamci_cmd_done
(
struct
pxamci_host
*
host
,
unsigned
int
stat
)
...
...
@@ -257,7 +258,7 @@ static int pxamci_cmd_done(struct pxamci_host *host, unsigned int stat)
if
(
host
->
data
&&
cmd
->
error
==
MMC_ERR_NONE
)
{
pxamci_enable_irq
(
host
,
DATA_TRAN_DONE
);
}
else
{
pxamci_finish_request
(
host
,
host
->
re
q
);
pxamci_finish_request
(
host
,
host
->
mr
q
);
}
return
1
;
...
...
@@ -290,11 +291,11 @@ static int pxamci_data_done(struct pxamci_host *host, unsigned int stat)
pxamci_disable_irq
(
host
,
DATA_TRAN_DONE
);
host
->
data
=
NULL
;
if
(
host
->
re
q
->
stop
&&
data
->
error
==
MMC_ERR_NONE
)
{
if
(
host
->
mr
q
->
stop
&&
data
->
error
==
MMC_ERR_NONE
)
{
pxamci_stop_clock
(
host
);
pxamci_start_cmd
(
host
,
host
->
re
q
->
stop
,
0
);
pxamci_start_cmd
(
host
,
host
->
mr
q
->
stop
,
0
);
}
else
{
pxamci_finish_request
(
host
,
host
->
re
q
);
pxamci_finish_request
(
host
,
host
->
mr
q
);
}
return
1
;
...
...
@@ -324,33 +325,33 @@ static irqreturn_t pxamci_irq(int irq, void *devid, struct pt_regs *regs)
return
IRQ_RETVAL
(
handled
);
}
static
void
pxamci_request
(
struct
mmc_host
*
mmc
,
struct
mmc_request
*
re
q
)
static
void
pxamci_request
(
struct
mmc_host
*
mmc
,
struct
mmc_request
*
mr
q
)
{
struct
pxamci_host
*
host
=
mmc_priv
(
mmc
);
unsigned
int
cmdat
;
WARN_ON
(
host
->
re
q
!=
NULL
);
WARN_ON
(
host
->
mr
q
!=
NULL
);
host
->
req
=
re
q
;
host
->
mrq
=
mr
q
;
pxamci_stop_clock
(
host
);
cmdat
=
host
->
cmdat
;
host
->
cmdat
&=
~
CMDAT_INIT
;
if
(
re
q
->
data
)
{
pxamci_setup_data
(
host
,
re
q
->
data
);
if
(
mr
q
->
data
)
{
pxamci_setup_data
(
host
,
mr
q
->
data
);
cmdat
&=
~
CMDAT_BUSY
;
cmdat
|=
CMDAT_DATAEN
|
CMDAT_DMAEN
;
if
(
re
q
->
data
->
flags
&
MMC_DATA_WRITE
)
if
(
mr
q
->
data
->
flags
&
MMC_DATA_WRITE
)
cmdat
|=
CMDAT_WRITE
;
if
(
re
q
->
data
->
flags
&
MMC_DATA_STREAM
)
if
(
mr
q
->
data
->
flags
&
MMC_DATA_STREAM
)
cmdat
|=
CMDAT_STREAM
;
}
pxamci_start_cmd
(
host
,
re
q
->
cmd
,
cmdat
);
pxamci_start_cmd
(
host
,
mr
q
->
cmd
,
cmdat
);
}
static
void
pxamci_set_ios
(
struct
mmc_host
*
mmc
,
struct
mmc_ios
*
ios
)
...
...
include/linux/mmc/mmc.h
View file @
e77c6276
...
...
@@ -39,7 +39,7 @@ struct mmc_command {
#define MMC_ERR_INVALID 5
struct
mmc_data
*
data
;
/* data segment associated with cmd */
struct
mmc_request
*
re
q
;
/* assoicated request */
struct
mmc_request
*
mr
q
;
/* assoicated request */
};
struct
mmc_data
{
...
...
@@ -47,7 +47,7 @@ struct mmc_data {
unsigned
int
timeout_clks
;
/* data timeout (in clocks) */
unsigned
int
blksz_bits
;
/* data block size */
unsigned
int
blocks
;
/* number of blocks */
struct
request
*
rq
;
/* request structure */
struct
request
*
r
e
q
;
/* request structure */
unsigned
int
error
;
/* data error */
unsigned
int
flags
;
...
...
@@ -58,7 +58,7 @@ struct mmc_data {
unsigned
int
bytes_xfered
;
struct
mmc_command
*
stop
;
/* stop command */
struct
mmc_request
*
re
q
;
/* assoicated request */
struct
mmc_request
*
mr
q
;
/* assoicated request */
};
struct
mmc_request
{
...
...
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