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
c9fadf21
Commit
c9fadf21
authored
Jul 17, 2020
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'regmap/for-5.9' into regmap-next
parents
2b0f61e2
6611561a
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
248 additions
and
83 deletions
+248
-83
drivers/base/regmap/regmap-irq.c
drivers/base/regmap/regmap-irq.c
+29
-24
drivers/base/regmap/regmap.c
drivers/base/regmap/regmap.c
+14
-19
include/linux/regmap.h
include/linux/regmap.h
+205
-40
No files found.
drivers/base/regmap/regmap-irq.c
View file @
c9fadf21
...
...
@@ -541,9 +541,9 @@ static const struct irq_domain_ops regmap_domain_ops = {
};
/**
* regmap_add_irq_chip_
np
() - Use standard regmap IRQ controller handling
* regmap_add_irq_chip_
fwnode
() - Use standard regmap IRQ controller handling
*
* @
np: The device_
node where the IRQ domain should be added to.
* @
fwnode: The firmware
node where the IRQ domain should be added to.
* @map: The regmap for the device.
* @irq: The IRQ the device uses to signal interrupts.
* @irq_flags: The IRQF_ flags to use for the primary interrupt.
...
...
@@ -557,10 +557,11 @@ static const struct irq_domain_ops regmap_domain_ops = {
* register cache. The chip driver is responsible for restoring the
* register values used by the IRQ controller over suspend and resume.
*/
int
regmap_add_irq_chip_np
(
struct
device_node
*
np
,
struct
regmap
*
map
,
int
irq
,
int
irq_flags
,
int
irq_base
,
const
struct
regmap_irq_chip
*
chip
,
struct
regmap_irq_chip_data
**
data
)
int
regmap_add_irq_chip_fwnode
(
struct
fwnode_handle
*
fwnode
,
struct
regmap
*
map
,
int
irq
,
int
irq_flags
,
int
irq_base
,
const
struct
regmap_irq_chip
*
chip
,
struct
regmap_irq_chip_data
**
data
)
{
struct
regmap_irq_chip_data
*
d
;
int
i
;
...
...
@@ -771,10 +772,12 @@ int regmap_add_irq_chip_np(struct device_node *np, struct regmap *map, int irq,
}
if
(
irq_base
)
d
->
domain
=
irq_domain_add_legacy
(
np
,
chip
->
num_irqs
,
irq_base
,
d
->
domain
=
irq_domain_add_legacy
(
to_of_node
(
fwnode
),
chip
->
num_irqs
,
irq_base
,
0
,
&
regmap_domain_ops
,
d
);
else
d
->
domain
=
irq_domain_add_linear
(
np
,
chip
->
num_irqs
,
d
->
domain
=
irq_domain_add_linear
(
to_of_node
(
fwnode
),
chip
->
num_irqs
,
&
regmap_domain_ops
,
d
);
if
(
!
d
->
domain
)
{
dev_err
(
map
->
dev
,
"Failed to create IRQ domain
\n
"
);
...
...
@@ -808,7 +811,7 @@ int regmap_add_irq_chip_np(struct device_node *np, struct regmap *map, int irq,
kfree
(
d
);
return
ret
;
}
EXPORT_SYMBOL_GPL
(
regmap_add_irq_chip_
np
);
EXPORT_SYMBOL_GPL
(
regmap_add_irq_chip_
fwnode
);
/**
* regmap_add_irq_chip() - Use standard regmap IRQ controller handling
...
...
@@ -822,15 +825,15 @@ EXPORT_SYMBOL_GPL(regmap_add_irq_chip_np);
*
* Returns 0 on success or an errno on failure.
*
* This is the same as regmap_add_irq_chip_
np, except that the devic
e
* This is the same as regmap_add_irq_chip_
fwnode, except that the firmwar
e
* node of the regmap is used.
*/
int
regmap_add_irq_chip
(
struct
regmap
*
map
,
int
irq
,
int
irq_flags
,
int
irq_base
,
const
struct
regmap_irq_chip
*
chip
,
struct
regmap_irq_chip_data
**
data
)
{
return
regmap_add_irq_chip_
np
(
map
->
dev
->
of_node
,
map
,
irq
,
irq_flags
,
irq_base
,
chip
,
data
);
return
regmap_add_irq_chip_
fwnode
(
dev_fwnode
(
map
->
dev
),
map
,
irq
,
irq_flags
,
irq_base
,
chip
,
data
);
}
EXPORT_SYMBOL_GPL
(
regmap_add_irq_chip
);
...
...
@@ -899,10 +902,10 @@ static int devm_regmap_irq_chip_match(struct device *dev, void *res, void *data)
}
/**
* devm_regmap_add_irq_chip_
np() - Resource manager regmap_add_irq_chip_np
()
* devm_regmap_add_irq_chip_
fwnode() - Resource managed regmap_add_irq_chip_fwnode
()
*
* @dev: The device pointer on which irq_chip belongs to.
* @
np: The device_
node where the IRQ domain should be added to.
* @
fwnode: The firmware
node where the IRQ domain should be added to.
* @map: The regmap for the device.
* @irq: The IRQ the device uses to signal interrupts
* @irq_flags: The IRQF_ flags to use for the primary interrupt.
...
...
@@ -915,11 +918,12 @@ static int devm_regmap_irq_chip_match(struct device *dev, void *res, void *data)
* The ®map_irq_chip_data will be automatically released when the device is
* unbound.
*/
int
devm_regmap_add_irq_chip_np
(
struct
device
*
dev
,
struct
device_node
*
np
,
struct
regmap
*
map
,
int
irq
,
int
irq_flags
,
int
irq_base
,
const
struct
regmap_irq_chip
*
chip
,
struct
regmap_irq_chip_data
**
data
)
int
devm_regmap_add_irq_chip_fwnode
(
struct
device
*
dev
,
struct
fwnode_handle
*
fwnode
,
struct
regmap
*
map
,
int
irq
,
int
irq_flags
,
int
irq_base
,
const
struct
regmap_irq_chip
*
chip
,
struct
regmap_irq_chip_data
**
data
)
{
struct
regmap_irq_chip_data
**
ptr
,
*
d
;
int
ret
;
...
...
@@ -929,8 +933,8 @@ int devm_regmap_add_irq_chip_np(struct device *dev, struct device_node *np,
if
(
!
ptr
)
return
-
ENOMEM
;
ret
=
regmap_add_irq_chip_
np
(
np
,
map
,
irq
,
irq_flags
,
irq_base
,
chip
,
&
d
);
ret
=
regmap_add_irq_chip_
fwnode
(
fwnode
,
map
,
irq
,
irq_flags
,
irq_base
,
chip
,
&
d
);
if
(
ret
<
0
)
{
devres_free
(
ptr
);
return
ret
;
...
...
@@ -941,7 +945,7 @@ int devm_regmap_add_irq_chip_np(struct device *dev, struct device_node *np,
*
data
=
d
;
return
0
;
}
EXPORT_SYMBOL_GPL
(
devm_regmap_add_irq_chip_
np
);
EXPORT_SYMBOL_GPL
(
devm_regmap_add_irq_chip_
fwnode
);
/**
* devm_regmap_add_irq_chip() - Resource manager regmap_add_irq_chip()
...
...
@@ -964,8 +968,9 @@ int devm_regmap_add_irq_chip(struct device *dev, struct regmap *map, int irq,
const
struct
regmap_irq_chip
*
chip
,
struct
regmap_irq_chip_data
**
data
)
{
return
devm_regmap_add_irq_chip_np
(
dev
,
map
->
dev
->
of_node
,
map
,
irq
,
irq_flags
,
irq_base
,
chip
,
data
);
return
devm_regmap_add_irq_chip_fwnode
(
dev
,
dev_fwnode
(
map
->
dev
),
map
,
irq
,
irq_flags
,
irq_base
,
chip
,
data
);
}
EXPORT_SYMBOL_GPL
(
devm_regmap_add_irq_chip
);
...
...
drivers/base/regmap/regmap.c
View file @
c9fadf21
...
...
@@ -11,7 +11,7 @@
#include <linux/export.h>
#include <linux/mutex.h>
#include <linux/err.h>
#include <linux/
of
.h>
#include <linux/
property
.h>
#include <linux/rbtree.h>
#include <linux/sched.h>
#include <linux/delay.h>
...
...
@@ -631,7 +631,7 @@ enum regmap_endian regmap_get_val_endian(struct device *dev,
const
struct
regmap_bus
*
bus
,
const
struct
regmap_config
*
config
)
{
struct
device_node
*
np
;
struct
fwnode_handle
*
fwnode
=
dev
?
dev_fwnode
(
dev
)
:
NULL
;
enum
regmap_endian
endian
;
/* Retrieve the endianness specification from the regmap config */
...
...
@@ -641,22 +641,17 @@ enum regmap_endian regmap_get_val_endian(struct device *dev,
if
(
endian
!=
REGMAP_ENDIAN_DEFAULT
)
return
endian
;
/* If the dev and dev->of_node exist try to get endianness from DT */
if
(
dev
&&
dev
->
of_node
)
{
np
=
dev
->
of_node
;
/* Parse the device's DT node for an endianness specification */
if
(
of_property_read_bool
(
np
,
"big-endian"
))
endian
=
REGMAP_ENDIAN_BIG
;
else
if
(
of_property_read_bool
(
np
,
"little-endian"
))
endian
=
REGMAP_ENDIAN_LITTLE
;
else
if
(
of_property_read_bool
(
np
,
"native-endian"
))
endian
=
REGMAP_ENDIAN_NATIVE
;
/* If the endianness was specified in DT, use that */
if
(
endian
!=
REGMAP_ENDIAN_DEFAULT
)
return
endian
;
}
/* If the firmware node exist try to get endianness from it */
if
(
fwnode_property_read_bool
(
fwnode
,
"big-endian"
))
endian
=
REGMAP_ENDIAN_BIG
;
else
if
(
fwnode_property_read_bool
(
fwnode
,
"little-endian"
))
endian
=
REGMAP_ENDIAN_LITTLE
;
else
if
(
fwnode_property_read_bool
(
fwnode
,
"native-endian"
))
endian
=
REGMAP_ENDIAN_NATIVE
;
/* If the endianness was specified in fwnode, use that */
if
(
endian
!=
REGMAP_ENDIAN_DEFAULT
)
return
endian
;
/* Retrieve the endianness specification from the bus config */
if
(
bus
&&
bus
->
val_format_endian_default
)
...
...
@@ -2024,7 +2019,7 @@ EXPORT_SYMBOL_GPL(regmap_field_update_bits_base);
* A value of zero will be returned on success, a negative errno will
* be returned in error cases.
*/
int
regmap_fields_update_bits_base
(
struct
regmap_field
*
field
,
unsigned
int
id
,
int
regmap_fields_update_bits_base
(
struct
regmap_field
*
field
,
unsigned
int
id
,
unsigned
int
mask
,
unsigned
int
val
,
bool
*
change
,
bool
async
,
bool
force
)
{
...
...
include/linux/regmap.h
View file @
c9fadf21
...
...
@@ -18,6 +18,7 @@
#include <linux/bug.h>
#include <linux/lockdep.h>
#include <linux/iopoll.h>
#include <linux/fwnode.h>
struct
module
;
struct
clk
;
...
...
@@ -80,36 +81,6 @@ struct reg_sequence {
}
#define REG_SEQ0(_reg, _def) REG_SEQ(_reg, _def, 0)
#define regmap_update_bits(map, reg, mask, val) \
regmap_update_bits_base(map, reg, mask, val, NULL, false, false)
#define regmap_update_bits_async(map, reg, mask, val)\
regmap_update_bits_base(map, reg, mask, val, NULL, true, false)
#define regmap_update_bits_check(map, reg, mask, val, change)\
regmap_update_bits_base(map, reg, mask, val, change, false, false)
#define regmap_update_bits_check_async(map, reg, mask, val, change)\
regmap_update_bits_base(map, reg, mask, val, change, true, false)
#define regmap_write_bits(map, reg, mask, val) \
regmap_update_bits_base(map, reg, mask, val, NULL, false, true)
#define regmap_field_write(field, val) \
regmap_field_update_bits_base(field, ~0, val, NULL, false, false)
#define regmap_field_force_write(field, val) \
regmap_field_update_bits_base(field, ~0, val, NULL, false, true)
#define regmap_field_update_bits(field, mask, val)\
regmap_field_update_bits_base(field, mask, val, NULL, false, false)
#define regmap_field_force_update_bits(field, mask, val) \
regmap_field_update_bits_base(field, mask, val, NULL, false, true)
#define regmap_fields_write(field, id, val) \
regmap_fields_update_bits_base(field, id, ~0, val, NULL, false, false)
#define regmap_fields_force_write(field, id, val) \
regmap_fields_update_bits_base(field, id, ~0, val, NULL, false, true)
#define regmap_fields_update_bits(field, id, mask, val)\
regmap_fields_update_bits_base(field, id, mask, val, NULL, false, false)
#define regmap_fields_force_update_bits(field, id, mask, val) \
regmap_fields_update_bits_base(field, id, mask, val, NULL, false, true)
/**
* regmap_read_poll_timeout - Poll until a condition is met or a timeout occurs
*
...
...
@@ -304,7 +275,7 @@ typedef void (*regmap_unlock)(void *);
* readable if it belongs to one of the ranges specified
* by rd_noinc_table).
* @disable_locking: This regmap is either protected by external means or
* is guaranteed not
be
be accessed from multiple threads.
* is guaranteed not
to
be accessed from multiple threads.
* Don't use any locking mechanisms.
* @lock: Optional lock callback (overrides regmap's default lock
* function, based on spinlock or mutex).
...
...
@@ -1054,6 +1025,42 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
int
regmap_update_bits_base
(
struct
regmap
*
map
,
unsigned
int
reg
,
unsigned
int
mask
,
unsigned
int
val
,
bool
*
change
,
bool
async
,
bool
force
);
static
inline
int
regmap_update_bits
(
struct
regmap
*
map
,
unsigned
int
reg
,
unsigned
int
mask
,
unsigned
int
val
)
{
return
regmap_update_bits_base
(
map
,
reg
,
mask
,
val
,
NULL
,
false
,
false
);
}
static
inline
int
regmap_update_bits_async
(
struct
regmap
*
map
,
unsigned
int
reg
,
unsigned
int
mask
,
unsigned
int
val
)
{
return
regmap_update_bits_base
(
map
,
reg
,
mask
,
val
,
NULL
,
true
,
false
);
}
static
inline
int
regmap_update_bits_check
(
struct
regmap
*
map
,
unsigned
int
reg
,
unsigned
int
mask
,
unsigned
int
val
,
bool
*
change
)
{
return
regmap_update_bits_base
(
map
,
reg
,
mask
,
val
,
change
,
false
,
false
);
}
static
inline
int
regmap_update_bits_check_async
(
struct
regmap
*
map
,
unsigned
int
reg
,
unsigned
int
mask
,
unsigned
int
val
,
bool
*
change
)
{
return
regmap_update_bits_base
(
map
,
reg
,
mask
,
val
,
change
,
true
,
false
);
}
static
inline
int
regmap_write_bits
(
struct
regmap
*
map
,
unsigned
int
reg
,
unsigned
int
mask
,
unsigned
int
val
)
{
return
regmap_update_bits_base
(
map
,
reg
,
mask
,
val
,
NULL
,
false
,
true
);
}
int
regmap_get_val_bytes
(
struct
regmap
*
map
);
int
regmap_get_max_register
(
struct
regmap
*
map
);
int
regmap_get_reg_stride
(
struct
regmap
*
map
);
...
...
@@ -1152,6 +1159,65 @@ int regmap_fields_read(struct regmap_field *field, unsigned int id,
int
regmap_fields_update_bits_base
(
struct
regmap_field
*
field
,
unsigned
int
id
,
unsigned
int
mask
,
unsigned
int
val
,
bool
*
change
,
bool
async
,
bool
force
);
static
inline
int
regmap_field_write
(
struct
regmap_field
*
field
,
unsigned
int
val
)
{
return
regmap_field_update_bits_base
(
field
,
~
0
,
val
,
NULL
,
false
,
false
);
}
static
inline
int
regmap_field_force_write
(
struct
regmap_field
*
field
,
unsigned
int
val
)
{
return
regmap_field_update_bits_base
(
field
,
~
0
,
val
,
NULL
,
false
,
true
);
}
static
inline
int
regmap_field_update_bits
(
struct
regmap_field
*
field
,
unsigned
int
mask
,
unsigned
int
val
)
{
return
regmap_field_update_bits_base
(
field
,
mask
,
val
,
NULL
,
false
,
false
);
}
static
inline
int
regmap_field_force_update_bits
(
struct
regmap_field
*
field
,
unsigned
int
mask
,
unsigned
int
val
)
{
return
regmap_field_update_bits_base
(
field
,
mask
,
val
,
NULL
,
false
,
true
);
}
static
inline
int
regmap_fields_write
(
struct
regmap_field
*
field
,
unsigned
int
id
,
unsigned
int
val
)
{
return
regmap_fields_update_bits_base
(
field
,
id
,
~
0
,
val
,
NULL
,
false
,
false
);
}
static
inline
int
regmap_fields_force_write
(
struct
regmap_field
*
field
,
unsigned
int
id
,
unsigned
int
val
)
{
return
regmap_fields_update_bits_base
(
field
,
id
,
~
0
,
val
,
NULL
,
false
,
true
);
}
static
inline
int
regmap_fields_update_bits
(
struct
regmap_field
*
field
,
unsigned
int
id
,
unsigned
int
mask
,
unsigned
int
val
)
{
return
regmap_fields_update_bits_base
(
field
,
id
,
mask
,
val
,
NULL
,
false
,
false
);
}
static
inline
int
regmap_fields_force_update_bits
(
struct
regmap_field
*
field
,
unsigned
int
id
,
unsigned
int
mask
,
unsigned
int
val
)
{
return
regmap_fields_update_bits_base
(
field
,
id
,
mask
,
val
,
NULL
,
false
,
true
);
}
/**
* struct regmap_irq_type - IRQ type definitions.
*
...
...
@@ -1311,21 +1377,23 @@ struct regmap_irq_chip_data;
int
regmap_add_irq_chip
(
struct
regmap
*
map
,
int
irq
,
int
irq_flags
,
int
irq_base
,
const
struct
regmap_irq_chip
*
chip
,
struct
regmap_irq_chip_data
**
data
);
int
regmap_add_irq_chip_np
(
struct
device_node
*
np
,
struct
regmap
*
map
,
int
irq
,
int
irq_flags
,
int
irq_base
,
const
struct
regmap_irq_chip
*
chip
,
struct
regmap_irq_chip_data
**
data
);
int
regmap_add_irq_chip_fwnode
(
struct
fwnode_handle
*
fwnode
,
struct
regmap
*
map
,
int
irq
,
int
irq_flags
,
int
irq_base
,
const
struct
regmap_irq_chip
*
chip
,
struct
regmap_irq_chip_data
**
data
);
void
regmap_del_irq_chip
(
int
irq
,
struct
regmap_irq_chip_data
*
data
);
int
devm_regmap_add_irq_chip
(
struct
device
*
dev
,
struct
regmap
*
map
,
int
irq
,
int
irq_flags
,
int
irq_base
,
const
struct
regmap_irq_chip
*
chip
,
struct
regmap_irq_chip_data
**
data
);
int
devm_regmap_add_irq_chip_np
(
struct
device
*
dev
,
struct
device_node
*
np
,
struct
regmap
*
map
,
int
irq
,
int
irq_flags
,
int
irq_base
,
const
struct
regmap_irq_chip
*
chip
,
struct
regmap_irq_chip_data
**
data
);
int
devm_regmap_add_irq_chip_fwnode
(
struct
device
*
dev
,
struct
fwnode_handle
*
fwnode
,
struct
regmap
*
map
,
int
irq
,
int
irq_flags
,
int
irq_base
,
const
struct
regmap_irq_chip
*
chip
,
struct
regmap_irq_chip_data
**
data
);
void
devm_regmap_del_irq_chip
(
struct
device
*
dev
,
int
irq
,
struct
regmap_irq_chip_data
*
data
);
...
...
@@ -1458,6 +1526,103 @@ static inline int regmap_fields_update_bits_base(struct regmap_field *field,
return
-
EINVAL
;
}
static
inline
int
regmap_update_bits
(
struct
regmap
*
map
,
unsigned
int
reg
,
unsigned
int
mask
,
unsigned
int
val
)
{
WARN_ONCE
(
1
,
"regmap API is disabled"
);
return
-
EINVAL
;
}
static
inline
int
regmap_update_bits_async
(
struct
regmap
*
map
,
unsigned
int
reg
,
unsigned
int
mask
,
unsigned
int
val
)
{
WARN_ONCE
(
1
,
"regmap API is disabled"
);
return
-
EINVAL
;
}
static
inline
int
regmap_update_bits_check
(
struct
regmap
*
map
,
unsigned
int
reg
,
unsigned
int
mask
,
unsigned
int
val
,
bool
*
change
)
{
WARN_ONCE
(
1
,
"regmap API is disabled"
);
return
-
EINVAL
;
}
static
inline
int
regmap_update_bits_check_async
(
struct
regmap
*
map
,
unsigned
int
reg
,
unsigned
int
mask
,
unsigned
int
val
,
bool
*
change
)
{
WARN_ONCE
(
1
,
"regmap API is disabled"
);
return
-
EINVAL
;
}
static
inline
int
regmap_write_bits
(
struct
regmap
*
map
,
unsigned
int
reg
,
unsigned
int
mask
,
unsigned
int
val
)
{
WARN_ONCE
(
1
,
"regmap API is disabled"
);
return
-
EINVAL
;
}
static
inline
int
regmap_field_write
(
struct
regmap_field
*
field
,
unsigned
int
val
)
{
WARN_ONCE
(
1
,
"regmap API is disabled"
);
return
-
EINVAL
;
}
static
inline
int
regmap_field_force_write
(
struct
regmap_field
*
field
,
unsigned
int
val
)
{
WARN_ONCE
(
1
,
"regmap API is disabled"
);
return
-
EINVAL
;
}
static
inline
int
regmap_field_update_bits
(
struct
regmap_field
*
field
,
unsigned
int
mask
,
unsigned
int
val
)
{
WARN_ONCE
(
1
,
"regmap API is disabled"
);
return
-
EINVAL
;
}
static
inline
int
regmap_field_force_update_bits
(
struct
regmap_field
*
field
,
unsigned
int
mask
,
unsigned
int
val
)
{
WARN_ONCE
(
1
,
"regmap API is disabled"
);
return
-
EINVAL
;
}
static
inline
int
regmap_fields_write
(
struct
regmap_field
*
field
,
unsigned
int
id
,
unsigned
int
val
)
{
WARN_ONCE
(
1
,
"regmap API is disabled"
);
return
-
EINVAL
;
}
static
inline
int
regmap_fields_force_write
(
struct
regmap_field
*
field
,
unsigned
int
id
,
unsigned
int
val
)
{
WARN_ONCE
(
1
,
"regmap API is disabled"
);
return
-
EINVAL
;
}
static
inline
int
regmap_fields_update_bits
(
struct
regmap_field
*
field
,
unsigned
int
id
,
unsigned
int
mask
,
unsigned
int
val
)
{
WARN_ONCE
(
1
,
"regmap API is disabled"
);
return
-
EINVAL
;
}
static
inline
int
regmap_fields_force_update_bits
(
struct
regmap_field
*
field
,
unsigned
int
id
,
unsigned
int
mask
,
unsigned
int
val
)
{
WARN_ONCE
(
1
,
"regmap API is disabled"
);
return
-
EINVAL
;
}
static
inline
int
regmap_get_val_bytes
(
struct
regmap
*
map
)
{
WARN_ONCE
(
1
,
"regmap API is disabled"
);
...
...
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