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
nexedi
linux
Commits
b9dc97bb
Commit
b9dc97bb
authored
Feb 23, 2005
by
Jeff Garzik
Browse files
Options
Browse Files
Download
Plain Diff
Merge pobox.com:/garz/repo/linux-2.6
into pobox.com:/garz/repo/netdev-2.6/smc91x
parents
0202b160
52433c9b
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
178 additions
and
51 deletions
+178
-51
arch/arm/mach-pxa/lubbock.c
arch/arm/mach-pxa/lubbock.c
+2
-0
arch/arm/mach-sa1100/neponset.c
arch/arm/mach-sa1100/neponset.c
+2
-0
drivers/net/smc91x.c
drivers/net/smc91x.c
+122
-44
drivers/net/smc91x.h
drivers/net/smc91x.h
+52
-7
No files found.
arch/arm/mach-pxa/lubbock.c
View file @
b9dc97bb
...
@@ -138,6 +138,7 @@ static struct platform_device sa1111_device = {
...
@@ -138,6 +138,7 @@ static struct platform_device sa1111_device = {
static
struct
resource
smc91x_resources
[]
=
{
static
struct
resource
smc91x_resources
[]
=
{
[
0
]
=
{
[
0
]
=
{
.
name
=
"smc91x-regs"
,
.
start
=
0x0c000000
,
.
start
=
0x0c000000
,
.
end
=
0x0c0fffff
,
.
end
=
0x0c0fffff
,
.
flags
=
IORESOURCE_MEM
,
.
flags
=
IORESOURCE_MEM
,
...
@@ -148,6 +149,7 @@ static struct resource smc91x_resources[] = {
...
@@ -148,6 +149,7 @@ static struct resource smc91x_resources[] = {
.
flags
=
IORESOURCE_IRQ
,
.
flags
=
IORESOURCE_IRQ
,
},
},
[
2
]
=
{
[
2
]
=
{
.
name
=
"smc91x-attrib"
,
.
start
=
0x0e000000
,
.
start
=
0x0e000000
,
.
end
=
0x0e0fffff
,
.
end
=
0x0e0fffff
,
.
flags
=
IORESOURCE_MEM
,
.
flags
=
IORESOURCE_MEM
,
...
...
arch/arm/mach-sa1100/neponset.c
View file @
b9dc97bb
...
@@ -266,6 +266,7 @@ static struct platform_device sa1111_device = {
...
@@ -266,6 +266,7 @@ static struct platform_device sa1111_device = {
static
struct
resource
smc91x_resources
[]
=
{
static
struct
resource
smc91x_resources
[]
=
{
[
0
]
=
{
[
0
]
=
{
.
name
=
"smc91x-regs"
,
.
start
=
SA1100_CS3_PHYS
,
.
start
=
SA1100_CS3_PHYS
,
.
end
=
SA1100_CS3_PHYS
+
0x01ffffff
,
.
end
=
SA1100_CS3_PHYS
+
0x01ffffff
,
.
flags
=
IORESOURCE_MEM
,
.
flags
=
IORESOURCE_MEM
,
...
@@ -276,6 +277,7 @@ static struct resource smc91x_resources[] = {
...
@@ -276,6 +277,7 @@ static struct resource smc91x_resources[] = {
.
flags
=
IORESOURCE_IRQ
,
.
flags
=
IORESOURCE_IRQ
,
},
},
[
2
]
=
{
[
2
]
=
{
.
name
=
"smc91x-attrib"
,
.
start
=
SA1100_CS3_PHYS
+
0x02000000
,
.
start
=
SA1100_CS3_PHYS
+
0x02000000
,
.
end
=
SA1100_CS3_PHYS
+
0x03ffffff
,
.
end
=
SA1100_CS3_PHYS
+
0x03ffffff
,
.
flags
=
IORESOURCE_MEM
,
.
flags
=
IORESOURCE_MEM
,
...
...
drivers/net/smc91x.c
View file @
b9dc97bb
...
@@ -210,6 +210,10 @@ struct smc_local {
...
@@ -210,6 +210,10 @@ struct smc_local {
spinlock_t
lock
;
spinlock_t
lock
;
#ifdef SMC_CAN_USE_DATACS
u32
*
datacs
;
#endif
#ifdef SMC_USE_PXA_DMA
#ifdef SMC_USE_PXA_DMA
/* DMA needs the physical address of the chip */
/* DMA needs the physical address of the chip */
u_long
physaddr
;
u_long
physaddr
;
...
@@ -483,7 +487,19 @@ static inline void smc_rcv(struct net_device *dev)
...
@@ -483,7 +487,19 @@ static inline void smc_rcv(struct net_device *dev)
dev
->
name
,
packet_number
,
status
,
dev
->
name
,
packet_number
,
status
,
packet_len
,
packet_len
);
packet_len
,
packet_len
);
if
(
unlikely
(
status
&
RS_ERRORS
))
{
back:
if
(
unlikely
(
packet_len
<
6
||
status
&
RS_ERRORS
))
{
if
(
status
&
RS_TOOLONG
&&
packet_len
<=
(
1514
+
4
+
6
))
{
/* accept VLAN packets */
status
&=
~
RS_TOOLONG
;
goto
back
;
}
if
(
packet_len
<
6
)
{
/* bloody hardware */
printk
(
KERN_ERR
"%s: fubar (rxlen %u status %x
\n
"
,
dev
->
name
,
packet_len
,
status
);
status
|=
RS_TOOSHORT
;
}
SMC_WAIT_MMU_BUSY
();
SMC_WAIT_MMU_BUSY
();
SMC_SET_MMU_CMD
(
MC_RELEASE
);
SMC_SET_MMU_CMD
(
MC_RELEASE
);
lp
->
stats
.
rx_errors
++
;
lp
->
stats
.
rx_errors
++
;
...
@@ -508,7 +524,7 @@ static inline void smc_rcv(struct net_device *dev)
...
@@ -508,7 +524,7 @@ static inline void smc_rcv(struct net_device *dev)
* (2 bytes, possibly containing the payload odd byte).
* (2 bytes, possibly containing the payload odd byte).
* Furthermore, we add 2 bytes to allow rounding up to
* Furthermore, we add 2 bytes to allow rounding up to
* multiple of 4 bytes on 32 bit buses.
* multiple of 4 bytes on 32 bit buses.
*
E
nce packet_len - 6 + 2 + 2 + 2.
*
He
nce packet_len - 6 + 2 + 2 + 2.
*/
*/
skb
=
dev_alloc_skb
(
packet_len
);
skb
=
dev_alloc_skb
(
packet_len
);
if
(
unlikely
(
skb
==
NULL
))
{
if
(
unlikely
(
skb
==
NULL
))
{
...
@@ -2012,16 +2028,21 @@ static int __init smc_probe(struct net_device *dev, unsigned long ioaddr)
...
@@ -2012,16 +2028,21 @@ static int __init smc_probe(struct net_device *dev, unsigned long ioaddr)
return
retval
;
return
retval
;
}
}
static
int
smc_enable_device
(
unsigned
long
attrib_phys
)
static
int
smc_enable_device
(
struct
platform_device
*
pdev
)
{
{
unsigned
long
flags
;
unsigned
long
flags
;
unsigned
char
ecor
,
ecsr
;
unsigned
char
ecor
,
ecsr
;
void
*
addr
;
void
*
addr
;
struct
resource
*
res
;
res
=
platform_get_resource_byname
(
pdev
,
IORESOURCE_MEM
,
"smc91x-attrib"
);
if
(
!
res
)
return
0
;
/*
/*
* Map the attribute space. This is overkill, but clean.
* Map the attribute space. This is overkill, but clean.
*/
*/
addr
=
ioremap
(
attrib_phys
,
ATTRIB_SIZE
);
addr
=
ioremap
(
res
->
start
,
ATTRIB_SIZE
);
if
(
!
addr
)
if
(
!
addr
)
return
-
ENOMEM
;
return
-
ENOMEM
;
...
@@ -2069,6 +2090,62 @@ static int smc_enable_device(unsigned long attrib_phys)
...
@@ -2069,6 +2090,62 @@ static int smc_enable_device(unsigned long attrib_phys)
return
0
;
return
0
;
}
}
static
int
smc_request_attrib
(
struct
platform_device
*
pdev
)
{
struct
resource
*
res
=
platform_get_resource_byname
(
pdev
,
IORESOURCE_MEM
,
"smc91x-attrib"
);
if
(
!
res
)
return
0
;
if
(
!
request_mem_region
(
res
->
start
,
ATTRIB_SIZE
,
CARDNAME
))
return
-
EBUSY
;
return
0
;
}
static
void
smc_release_attrib
(
struct
platform_device
*
pdev
)
{
struct
resource
*
res
=
platform_get_resource_byname
(
pdev
,
IORESOURCE_MEM
,
"smc91x-attrib"
);
if
(
res
)
release_mem_region
(
res
->
start
,
ATTRIB_SIZE
);
}
#ifdef SMC_CAN_USE_DATACS
static
void
smc_request_datacs
(
struct
platform_device
*
pdev
,
struct
net_device
*
ndev
)
{
struct
resource
*
res
=
platform_get_resource_byname
(
pdev
,
IORESOURCE_MEM
,
"smc91x-data32"
);
struct
smc_local
*
lp
=
netdev_priv
(
ndev
);
if
(
!
res
)
return
;
if
(
!
request_mem_region
(
res
->
start
,
SMC_DATA_EXTENT
,
CARDNAME
))
{
printk
(
KERN_INFO
"%s: failed to request datacs memory region.
\n
"
,
CARDNAME
);
return
;
}
lp
->
datacs
=
ioremap
(
res
->
start
,
SMC_DATA_EXTENT
);
}
static
void
smc_release_datacs
(
struct
platform_device
*
pdev
,
struct
net_device
*
ndev
)
{
struct
smc_local
*
lp
=
netdev_priv
(
ndev
);
struct
resource
*
res
=
platform_get_resource_byname
(
pdev
,
IORESOURCE_MEM
,
"smc91x-data32"
);
if
(
lp
->
datacs
)
iounmap
(
lp
->
datacs
);
lp
->
datacs
=
NULL
;
if
(
res
)
release_mem_region
(
res
->
start
,
SMC_DATA_EXTENT
);
}
#else
static
void
smc_request_datacs
(
struct
platform_device
*
pdev
,
struct
net_device
*
ndev
)
{}
static
void
smc_release_datacs
(
struct
platform_device
*
pdev
,
struct
net_device
*
ndev
)
{}
#endif
/*
/*
* smc_init(void)
* smc_init(void)
* Input parameters:
* Input parameters:
...
@@ -2084,20 +2161,20 @@ static int smc_drv_probe(struct device *dev)
...
@@ -2084,20 +2161,20 @@ static int smc_drv_probe(struct device *dev)
{
{
struct
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
net_device
*
ndev
;
struct
net_device
*
ndev
;
struct
resource
*
res
,
*
ext
=
NULL
;
struct
resource
*
res
;
unsigned
int
*
addr
;
unsigned
int
*
addr
;
int
ret
;
int
ret
;
res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
res
=
platform_get_resource_byname
(
pdev
,
IORESOURCE_MEM
,
"smc91x-regs"
);
if
(
!
res
)
res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
if
(
!
res
)
{
if
(
!
res
)
{
ret
=
-
ENODEV
;
ret
=
-
ENODEV
;
goto
out
;
goto
out
;
}
}
/*
* Request the regions.
if
(
!
request_mem_region
(
res
->
start
,
SMC_IO_EXTENT
,
CARDNAME
))
{
*/
if
(
!
request_mem_region
(
res
->
start
,
SMC_IO_EXTENT
,
"smc91x"
))
{
ret
=
-
EBUSY
;
ret
=
-
EBUSY
;
goto
out
;
goto
out
;
}
}
...
@@ -2106,7 +2183,7 @@ static int smc_drv_probe(struct device *dev)
...
@@ -2106,7 +2183,7 @@ static int smc_drv_probe(struct device *dev)
if
(
!
ndev
)
{
if
(
!
ndev
)
{
printk
(
"%s: could not allocate device.
\n
"
,
CARDNAME
);
printk
(
"%s: could not allocate device.
\n
"
,
CARDNAME
);
ret
=
-
ENOMEM
;
ret
=
-
ENOMEM
;
goto
release_1
;
goto
out_release_io
;
}
}
SET_MODULE_OWNER
(
ndev
);
SET_MODULE_OWNER
(
ndev
);
SET_NETDEV_DEV
(
ndev
,
dev
);
SET_NETDEV_DEV
(
ndev
,
dev
);
...
@@ -2114,42 +2191,26 @@ static int smc_drv_probe(struct device *dev)
...
@@ -2114,42 +2191,26 @@ static int smc_drv_probe(struct device *dev)
ndev
->
dma
=
(
unsigned
char
)
-
1
;
ndev
->
dma
=
(
unsigned
char
)
-
1
;
ndev
->
irq
=
platform_get_irq
(
pdev
,
0
);
ndev
->
irq
=
platform_get_irq
(
pdev
,
0
);
ext
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
1
);
ret
=
smc_request_attrib
(
pdev
);
if
(
ext
)
{
if
(
ret
)
if
(
!
request_mem_region
(
ext
->
start
,
ATTRIB_SIZE
,
ndev
->
name
))
{
goto
out_free_netdev
;
ret
=
-
EBUSY
;
goto
release_1
;
}
#if defined(CONFIG_SA1100_ASSABET)
#if defined(CONFIG_SA1100_ASSABET)
NCR_0
|=
NCR_ENET_OSC_EN
;
NCR_0
|=
NCR_ENET_OSC_EN
;
#endif
#endif
ret
=
smc_enable_device
(
pdev
);
ret
=
smc_enable_device
(
ext
->
start
);
if
(
ret
)
if
(
ret
)
goto
out_release_attrib
;
goto
release_both
;
}
addr
=
ioremap
(
res
->
start
,
SMC_IO_EXTENT
);
addr
=
ioremap
(
res
->
start
,
SMC_IO_EXTENT
);
if
(
!
addr
)
{
if
(
!
addr
)
{
ret
=
-
ENOMEM
;
ret
=
-
ENOMEM
;
goto
release_both
;
goto
out_release_attrib
;
}
}
dev_set_drvdata
(
dev
,
ndev
);
dev_set_drvdata
(
dev
,
ndev
);
ret
=
smc_probe
(
ndev
,
(
unsigned
long
)
addr
);
ret
=
smc_probe
(
ndev
,
(
unsigned
long
)
addr
);
if
(
ret
!=
0
)
{
if
(
ret
!=
0
)
dev_set_drvdata
(
dev
,
NULL
);
goto
out_iounmap
;
iounmap
(
addr
);
release_both:
if
(
ext
)
release_mem_region
(
ext
->
start
,
ATTRIB_SIZE
);
free_netdev
(
ndev
);
release_1:
release_mem_region
(
res
->
start
,
SMC_IO_EXTENT
);
out:
printk
(
"%s: not found (%d).
\n
"
,
CARDNAME
,
ret
);
}
#ifdef SMC_USE_PXA_DMA
#ifdef SMC_USE_PXA_DMA
else
{
else
{
struct
smc_local
*
lp
=
netdev_priv
(
ndev
);
struct
smc_local
*
lp
=
netdev_priv
(
ndev
);
...
@@ -2157,6 +2218,22 @@ static int smc_drv_probe(struct device *dev)
...
@@ -2157,6 +2218,22 @@ static int smc_drv_probe(struct device *dev)
}
}
#endif
#endif
smc_request_datacs
(
pdev
,
ndev
);
return
0
;
out_iounmap:
dev_set_drvdata
(
dev
,
NULL
);
iounmap
(
addr
);
out_release_attrib:
smc_release_attrib
(
pdev
);
out_free_netdev:
free_netdev
(
ndev
);
out_release_io:
release_mem_region
(
res
->
start
,
SMC_IO_EXTENT
);
out:
printk
(
"%s: not found (%d).
\n
"
,
CARDNAME
,
ret
);
return
ret
;
return
ret
;
}
}
...
@@ -2177,10 +2254,13 @@ static int smc_drv_remove(struct device *dev)
...
@@ -2177,10 +2254,13 @@ static int smc_drv_remove(struct device *dev)
pxa_free_dma
(
ndev
->
dma
);
pxa_free_dma
(
ndev
->
dma
);
#endif
#endif
iounmap
((
void
*
)
ndev
->
base_addr
);
iounmap
((
void
*
)
ndev
->
base_addr
);
res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
1
);
if
(
res
)
smc_release_datacs
(
pdev
,
ndev
);
release_mem_region
(
res
->
start
,
ATTRIB_SIZE
);
smc_release_attrib
(
pdev
);
res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
res
=
platform_get_resource_byname
(
pdev
,
IORESOURCE_MEM
,
"smc91x-regs"
);
if
(
!
res
)
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
release_mem_region
(
res
->
start
,
SMC_IO_EXTENT
);
release_mem_region
(
res
->
start
,
SMC_IO_EXTENT
);
free_netdev
(
ndev
);
free_netdev
(
ndev
);
...
@@ -2208,9 +2288,7 @@ static int smc_drv_resume(struct device *dev, u32 level)
...
@@ -2208,9 +2288,7 @@ static int smc_drv_resume(struct device *dev, u32 level)
if
(
ndev
&&
level
==
RESUME_ENABLE
)
{
if
(
ndev
&&
level
==
RESUME_ENABLE
)
{
struct
smc_local
*
lp
=
netdev_priv
(
ndev
);
struct
smc_local
*
lp
=
netdev_priv
(
ndev
);
smc_enable_device
(
pdev
);
if
(
pdev
->
num_resources
==
3
)
smc_enable_device
(
pdev
->
resource
[
2
].
start
);
if
(
netif_running
(
ndev
))
{
if
(
netif_running
(
ndev
))
{
smc_reset
(
ndev
);
smc_reset
(
ndev
);
smc_enable
(
ndev
);
smc_enable
(
ndev
);
...
...
drivers/net/smc91x.h
View file @
b9dc97bb
...
@@ -362,7 +362,7 @@ smc_pxa_dma_irq(int dma, void *dummy, struct pt_regs *regs)
...
@@ -362,7 +362,7 @@ smc_pxa_dma_irq(int dma, void *dummy, struct pt_regs *regs)
#define SMC_IO_SHIFT 0
#define SMC_IO_SHIFT 0
#endif
#endif
#define SMC_IO_EXTENT (16 << SMC_IO_SHIFT)
#define SMC_IO_EXTENT (16 << SMC_IO_SHIFT)
#define SMC_DATA_EXTENT (4)
/*
/*
. Bank Select Register:
. Bank Select Register:
...
@@ -883,7 +883,7 @@ static const char * chip_ids[ 16 ] = {
...
@@ -883,7 +883,7 @@ static const char * chip_ids[ 16 ] = {
#endif
#endif
#if SMC_CAN_USE_32BIT
#if SMC_CAN_USE_32BIT
#define SMC_PUSH_DATA(p, l) \
#define
_
SMC_PUSH_DATA(p, l) \
do { \
do { \
char *__ptr = (p); \
char *__ptr = (p); \
int __len = (l); \
int __len = (l); \
...
@@ -898,7 +898,7 @@ static const char * chip_ids[ 16 ] = {
...
@@ -898,7 +898,7 @@ static const char * chip_ids[ 16 ] = {
SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \
SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \
} \
} \
} while (0)
} while (0)
#define SMC_PULL_DATA(p, l) \
#define
_
SMC_PULL_DATA(p, l) \
do { \
do { \
char *__ptr = (p); \
char *__ptr = (p); \
int __len = (l); \
int __len = (l); \
...
@@ -918,11 +918,11 @@ static const char * chip_ids[ 16 ] = {
...
@@ -918,11 +918,11 @@ static const char * chip_ids[ 16 ] = {
SMC_insl( ioaddr, DATA_REG, __ptr, __len >> 2); \
SMC_insl( ioaddr, DATA_REG, __ptr, __len >> 2); \
} while (0)
} while (0)
#elif SMC_CAN_USE_16BIT
#elif SMC_CAN_USE_16BIT
#define SMC_PUSH_DATA(p, l) SMC_outsw( ioaddr, DATA_REG, p, (l) >> 1 )
#define
_
SMC_PUSH_DATA(p, l) SMC_outsw( ioaddr, DATA_REG, p, (l) >> 1 )
#define SMC_PULL_DATA(p, l) SMC_insw ( ioaddr, DATA_REG, p, (l) >> 1 )
#define
_
SMC_PULL_DATA(p, l) SMC_insw ( ioaddr, DATA_REG, p, (l) >> 1 )
#elif SMC_CAN_USE_8BIT
#elif SMC_CAN_USE_8BIT
#define SMC_PUSH_DATA(p, l) SMC_outsb( ioaddr, DATA_REG, p, l )
#define
_
SMC_PUSH_DATA(p, l) SMC_outsb( ioaddr, DATA_REG, p, l )
#define SMC_PULL_DATA(p, l) SMC_insb ( ioaddr, DATA_REG, p, l )
#define
_
SMC_PULL_DATA(p, l) SMC_insb ( ioaddr, DATA_REG, p, l )
#endif
#endif
#if ! SMC_CAN_USE_16BIT
#if ! SMC_CAN_USE_16BIT
...
@@ -941,6 +941,51 @@ static const char * chip_ids[ 16 ] = {
...
@@ -941,6 +941,51 @@ static const char * chip_ids[ 16 ] = {
})
})
#endif
#endif
#if SMC_CAN_USE_DATACS
#define SMC_PUSH_DATA(p, l) \
if ( lp->datacs ) { \
unsigned char *__ptr = (p); \
int __len = (l); \
if (__len >= 2 && (unsigned long)__ptr & 2) { \
__len -= 2; \
SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \
__ptr += 2; \
} \
outsl(lp->datacs, __ptr, __len >> 2); \
if (__len & 2) { \
__ptr += (__len & ~3); \
SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG ); \
} \
} else { \
_SMC_PUSH_DATA(p, l); \
}
#define SMC_PULL_DATA(p, l) \
if ( lp->datacs ) { \
unsigned char *__ptr = (p); \
int __len = (l); \
if ((unsigned long)__ptr & 2) { \
/* \
* We want 32bit alignment here. \
* Since some buses perform a full 32bit \
* fetch even for 16bit data we can't use \
* SMC_inw() here. Back both source (on chip \
* and destination) pointers of 2 bytes. \
*/
\
__ptr -= 2; \
__len += 2; \
SMC_SET_PTR( 2|PTR_READ|PTR_RCV|PTR_AUTOINC ); \
} \
__len += 2; \
insl( lp->datacs, __ptr, __len >> 2); \
} else { \
_SMC_PULL_DATA(p, l); \
}
#else
#define SMC_PUSH_DATA(p, l) _SMC_PUSH_DATA(p, l)
#define SMC_PULL_DATA(p, l) _SMC_PULL_DATA(p, l)
#endif
#if !defined (SMC_INTERRUPT_PREAMBLE)
#if !defined (SMC_INTERRUPT_PREAMBLE)
# define SMC_INTERRUPT_PREAMBLE
# define SMC_INTERRUPT_PREAMBLE
#endif
#endif
...
...
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