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
733bda87
Commit
733bda87
authored
Jan 15, 2003
by
Dave Jones
Committed by
Dave Jones
Jan 15, 2003
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[AGPGART] implement module locking that works.
parent
11061ebf
Changes
14
Show whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
120 additions
and
66 deletions
+120
-66
drivers/char/agp/agp.h
drivers/char/agp/agp.h
+24
-20
drivers/char/agp/ali-agp.c
drivers/char/agp/ali-agp.c
+6
-2
drivers/char/agp/amd-k7-agp.c
drivers/char/agp/amd-k7-agp.c
+7
-2
drivers/char/agp/amd-k8-agp.c
drivers/char/agp/amd-k8-agp.c
+6
-2
drivers/char/agp/backend.c
drivers/char/agp/backend.c
+26
-13
drivers/char/agp/generic.c
drivers/char/agp/generic.c
+1
-7
drivers/char/agp/hp-agp.c
drivers/char/agp/hp-agp.c
+7
-2
drivers/char/agp/i460-agp.c
drivers/char/agp/i460-agp.c
+7
-2
drivers/char/agp/i7x05-agp.c
drivers/char/agp/i7x05-agp.c
+6
-2
drivers/char/agp/intel-agp.c
drivers/char/agp/intel-agp.c
+6
-6
drivers/char/agp/sis-agp.c
drivers/char/agp/sis-agp.c
+6
-2
drivers/char/agp/sworks-agp.c
drivers/char/agp/sworks-agp.c
+6
-2
drivers/char/agp/via-agp.c
drivers/char/agp/via-agp.c
+6
-2
drivers/char/agp/via-kt400.c
drivers/char/agp/via-kt400.c
+6
-2
No files found.
drivers/char/agp/agp.h
View file @
733bda87
...
...
@@ -32,28 +32,8 @@
extern
struct
agp_bridge_data
agp_bridge
;
/* Generic routines. */
void
agp_generic_agp_enable
(
u32
mode
);
int
agp_generic_agp_3_0_enable
(
u32
mode
);
int
agp_generic_create_gatt_table
(
void
);
int
agp_generic_free_gatt_table
(
void
);
agp_memory
*
agp_create_memory
(
int
scratch_pages
);
int
agp_generic_insert_memory
(
agp_memory
*
mem
,
off_t
pg_start
,
int
type
);
int
agp_generic_remove_memory
(
agp_memory
*
mem
,
off_t
pg_start
,
int
type
);
agp_memory
*
agp_generic_alloc_by_type
(
size_t
page_count
,
int
type
);
void
agp_generic_free_by_type
(
agp_memory
*
curr
);
void
*
agp_generic_alloc_page
(
void
);
void
agp_generic_destroy_page
(
void
*
addr
);
int
agp_generic_suspend
(
void
);
void
agp_generic_resume
(
void
);
void
agp_free_key
(
int
key
);
int
agp_num_entries
(
void
);
#define PFX "agpgart: "
int
agp_register_driver
(
struct
pci_dev
*
dev
);
int
agp_unregister_driver
(
void
);
#ifdef CONFIG_SMP
static
void
ipi_handler
(
void
*
null
)
{
...
...
@@ -385,6 +365,11 @@ struct agp_bridge_info {
struct
agp_device_ids
*
ids
;
};
struct
agp_driver
{
struct
module
*
owner
;
struct
pci_dev
*
dev
;
};
extern
struct
agp_bridge_info
ali_agp_bridge_info
;
extern
struct
agp_bridge_info
amd_k8_agp_bridge_info
;
extern
struct
agp_bridge_info
amd_agp_bridge_info
;
...
...
@@ -393,4 +378,23 @@ extern struct agp_bridge_info sis_agp_bridge_info;
extern
struct
agp_bridge_info
via_agp_bridge_info
;
extern
struct
agp_bridge_info
hp_agp_bridge_info
;
/* Generic routines. */
void
agp_generic_agp_enable
(
u32
mode
);
int
agp_generic_agp_3_0_enable
(
u32
mode
);
int
agp_generic_create_gatt_table
(
void
);
int
agp_generic_free_gatt_table
(
void
);
agp_memory
*
agp_create_memory
(
int
scratch_pages
);
int
agp_generic_insert_memory
(
agp_memory
*
mem
,
off_t
pg_start
,
int
type
);
int
agp_generic_remove_memory
(
agp_memory
*
mem
,
off_t
pg_start
,
int
type
);
agp_memory
*
agp_generic_alloc_by_type
(
size_t
page_count
,
int
type
);
void
agp_generic_free_by_type
(
agp_memory
*
curr
);
void
*
agp_generic_alloc_page
(
void
);
void
agp_generic_destroy_page
(
void
*
addr
);
int
agp_generic_suspend
(
void
);
void
agp_generic_resume
(
void
);
void
agp_free_key
(
int
key
);
int
agp_num_entries
(
void
);
int
agp_register_driver
(
struct
agp_driver
*
drv
);
int
agp_unregister_driver
(
struct
agp_driver
*
drv
);
#endif
/* _AGP_BACKEND_PRIV_H */
drivers/char/agp/ali-agp.c
View file @
733bda87
...
...
@@ -336,6 +336,9 @@ static int __init agp_lookup_host_bridge (struct pci_dev *pdev)
return
-
ENODEV
;
}
static
struct
agp_driver
ali_agp_driver
=
{
.
owner
=
THIS_MODULE
,
};
static
int
__init
agp_ali_probe
(
struct
pci_dev
*
dev
,
const
struct
pci_device_id
*
ent
)
{
...
...
@@ -351,7 +354,8 @@ static int __init agp_ali_probe (struct pci_dev *dev, const struct pci_device_id
agp_bridge
.
capndx
=
cap_ptr
;
/* Fill in the mode register */
pci_read_config_dword
(
agp_bridge
.
dev
,
agp_bridge
.
capndx
+
PCI_AGP_STATUS
,
&
agp_bridge
.
mode
);
agp_register_driver
(
dev
);
ali_agp_driver
.
dev
=
dev
;
agp_register_driver
(
&
ali_agp_driver
);
return
0
;
}
return
-
ENODEV
;
...
...
@@ -390,7 +394,7 @@ static int __init agp_ali_init(void)
static
void
__exit
agp_ali_cleanup
(
void
)
{
agp_unregister_driver
();
agp_unregister_driver
(
&
ali_agp_driver
);
pci_unregister_driver
(
&
agp_ali_pci_driver
);
}
...
...
drivers/char/agp/amd-k7-agp.c
View file @
733bda87
...
...
@@ -440,6 +440,10 @@ static int __init agp_lookup_host_bridge (struct pci_dev *pdev)
}
static
struct
agp_driver
amd_k7_agp_driver
=
{
.
owner
=
THIS_MODULE
,
};
/* Supported Device Scanning routine */
static
int
__init
agp_amdk7_probe
(
struct
pci_dev
*
dev
,
const
struct
pci_device_id
*
ent
)
...
...
@@ -455,7 +459,8 @@ static int __init agp_amdk7_probe (struct pci_dev *dev, const struct pci_device_
agp_bridge
.
capndx
=
cap_ptr
;
/* Fill in the mode register */
pci_read_config_dword
(
agp_bridge
.
dev
,
agp_bridge
.
capndx
+
PCI_AGP_STATUS
,
&
agp_bridge
.
mode
);
agp_register_driver
(
dev
);
amd_k7_agp_driver
.
dev
=
dev
;
agp_register_driver
(
&
amd_k7_agp_driver
);
return
0
;
}
return
-
ENODEV
;
...
...
@@ -494,7 +499,7 @@ static int __init agp_amdk7_init(void)
static
void
__exit
agp_amdk7_cleanup
(
void
)
{
agp_unregister_driver
();
agp_unregister_driver
(
&
amd_k7_agp_driver
);
pci_unregister_driver
(
&
agp_amdk7_pci_driver
);
}
...
...
drivers/char/agp/amd-k8-agp.c
View file @
733bda87
...
...
@@ -408,6 +408,9 @@ static int __init amd_8151_setup (struct pci_dev *pdev)
return
0
;
}
static
struct
agp_driver
amd_k8_agp_driver
=
{
.
owner
=
THIS_MODULE
,
};
static
int
__init
agp_amdk8_probe
(
struct
pci_dev
*
dev
,
const
struct
pci_device_id
*
ent
)
{
...
...
@@ -423,7 +426,8 @@ static int __init agp_amdk8_probe (struct pci_dev *dev, const struct pci_device_
/* Fill in the mode register */
pci_read_config_dword
(
agp_bridge
.
dev
,
agp_bridge
.
capndx
+
PCI_AGP_STATUS
,
&
agp_bridge
.
mode
);
amd_8151_setup
(
dev
);
agp_register_driver
(
dev
);
amd_k8_agp_driver
.
dev
=
dev
;
agp_register_driver
(
&
amd_k8_agp_driver
);
return
0
;
}
...
...
@@ -463,7 +467,7 @@ int __init agp_amdk8_init(void)
static
void
__exit
agp_amdk8_cleanup
(
void
)
{
agp_unregister_driver
();
agp_unregister_driver
(
&
amd_k8_agp_driver
);
pci_unregister_driver
(
&
agp_amdk8_pci_driver
);
}
...
...
drivers/char/agp/backend.c
View file @
733bda87
...
...
@@ -219,36 +219,48 @@ static const drm_agp_t drm_agp = {
static
int
agp_count
=
0
;
int
agp_register_driver
(
struct
pci_dev
*
de
v
)
int
agp_register_driver
(
struct
agp_driver
*
dr
v
)
{
int
ret_val
;
if
(
drv
->
dev
==
NULL
)
{
printk
(
KERN_DEBUG
PFX
"Erk, registering with no pci_dev!
\n
"
);
return
-
EINVAL
;
}
if
(
agp_count
==
1
)
{
printk
(
KERN_DEBUG
PFX
"Only one agpgart device currently supported.
\n
"
);
return
-
ENODEV
;
}
ret_val
=
agp_backend_initialize
(
dev
);
if
(
ret_val
)
{
agp_bridge
.
type
=
NOT_SUPPORTED
;
return
ret_val
;
}
/* Grab reference on the chipset driver. */
if
(
!
try_module_get
(
drv
->
owner
))
return
-
EINVAL
;
ret_val
=
agp_backend_initialize
(
drv
->
dev
);
if
(
ret_val
)
goto
err_out
;
ret_val
=
agp_frontend_initialize
();
if
(
ret_val
)
{
agp_bridge
.
type
=
NOT_SUPPORTED
;
agp_backend_cleanup
();
return
ret_val
;
}
if
(
ret_val
)
goto
frontend_err
;
/* FIXME: What to do with this? */
inter_module_register
(
"drm_agp"
,
THIS_MODULE
,
&
drm_agp
);
pm_register
(
PM_PCI_DEV
,
PM_PCI_ID
(
agp_bridge
.
dev
),
agp_power
);
agp_count
++
;
return
0
;
frontend_err:
agp_backend_cleanup
();
err_out:
agp_bridge
.
type
=
NOT_SUPPORTED
;
module_put
(
drv
->
owner
);
return
ret_val
;
}
int
agp_unregister_driver
(
void
)
int
agp_unregister_driver
(
struct
agp_driver
*
drv
)
{
agp_bridge
.
type
=
NOT_SUPPORTED
;
pm_unregister_all
(
agp_power
);
...
...
@@ -256,6 +268,7 @@ int agp_unregister_driver(void)
agp_backend_cleanup
();
inter_module_unregister
(
"drm_agp"
);
agp_count
--
;
module_put
(
drv
->
owner
);
return
0
;
}
...
...
drivers/char/agp/generic.c
View file @
733bda87
...
...
@@ -116,7 +116,6 @@ void agp_free_memory(agp_memory * curr)
agp_free_key
(
curr
->
key
);
vfree
(
curr
->
memory
);
kfree
(
curr
);
MOD_DEC_USE_COUNT
;
}
#define ENTRIES_PER_PAGE (PAGE_SIZE / sizeof(unsigned long))
...
...
@@ -138,17 +137,12 @@ agp_memory *agp_allocate_memory(size_t page_count, u32 type)
return
new
;
}
/* We always increase the module count, since free auto-decrements it */
MOD_INC_USE_COUNT
;
scratch_pages
=
(
page_count
+
ENTRIES_PER_PAGE
-
1
)
/
ENTRIES_PER_PAGE
;
new
=
agp_create_memory
(
scratch_pages
);
if
(
new
==
NULL
)
{
MOD_DEC_USE_COUNT
;
if
(
new
==
NULL
)
return
NULL
;
}
for
(
i
=
0
;
i
<
page_count
;
i
++
)
{
void
*
addr
=
agp_bridge
.
agp_alloc_page
();
...
...
drivers/char/agp/hp-agp.c
View file @
733bda87
...
...
@@ -368,10 +368,15 @@ static int __init agp_find_supported_device(struct pci_dev *dev)
return
-
ENODEV
;
}
static
struct
agp_driver
hp_agp_driver
=
{
.
owner
=
THIS_MODULE
;
};
static
int
__init
agp_hp_probe
(
struct
pci_dev
*
dev
,
const
struct
pci_device_id
*
ent
)
{
if
(
agp_find_supported_device
(
dev
)
==
0
)
{
agp_register_driver
(
dev
);
hp_agp_driver
.
dev
=
dev
;
agp_register_driver
(
&
hp_agp_driver
);
return
0
;
}
return
-
ENODEV
;
...
...
@@ -410,7 +415,7 @@ static int __init agp_hp_init(void)
static
void
__exit
agp_hp_cleanup
(
void
)
{
agp_unregister_driver
();
agp_unregister_driver
(
&
hp_agp_driver
);
pci_unregister_driver
(
&
agp_hp_pci_driver
);
}
...
...
drivers/char/agp/i460-agp.c
View file @
733bda87
...
...
@@ -559,6 +559,10 @@ static int __init intel_i460_setup (struct pci_dev *pdev __attribute__((unused))
return
0
;
}
static
struct
agp_driver
i460_agp_driver
=
{
.
owner
=
THIS_MODULE
;
};
static
int
__init
agp_intel_i460_probe
(
struct
pci_dev
*
dev
,
const
struct
pci_device_id
*
ent
)
{
u8
cap_ptr
=
0
;
...
...
@@ -570,7 +574,8 @@ static int __init agp_intel_i460_probe (struct pci_dev *dev, const struct pci_de
agp_bridge
.
dev
=
dev
;
agp_bridge
.
capndx
=
cap_ptr
;
intel_i460_setup
(
dev
);
agp_register_driver
(
dev
);
i460_agp_driver
.
dev
=
dev
;
agp_register_driver
(
&
i460_agp_driver
);
return
0
;
}
...
...
@@ -607,7 +612,7 @@ static int __init agp_intel_i460_init(void)
static
void
__exit
agp_intel_i460_cleanup
(
void
)
{
agp_unregister_driver
();
agp_unregister_driver
(
&
i460_agp_driver
);
pci_unregister_driver
(
&
agp_intel_i460_pci_driver
);
}
...
...
drivers/char/agp/i7x05-agp.c
View file @
733bda87
...
...
@@ -164,6 +164,9 @@ static int __init agp_lookup_host_bridge (struct pci_dev *pdev)
return
-
ENODEV
;
}
static
struct
agp_driver
i7x05_agp_driver
=
{
.
owner
=
THIS_MODULE
;
};
static
int
__init
agp_i7x05_probe
(
struct
pci_dev
*
dev
,
const
struct
pci_device_id
*
ent
)
{
...
...
@@ -178,7 +181,8 @@ static int __init agp_i7x05_probe (struct pci_dev *dev, const struct pci_device_
agp_bridge
.
capndx
=
cap_ptr
;
/* Fill in the mode register */
pci_read_config_dword
(
agp_bridge
.
dev
,
agp_bridge
.
capndx
+
PCI_AGP_STATUS
,
&
agp_bridge
.
mode
)
agp_register_driver
(
dev
);
i7x05_agp_driver
.
dev
=
dev
;
agp_register_driver
(
&
i7x05_agp_driver
);
return
0
;
}
return
-
ENODEV
;
...
...
@@ -218,7 +222,7 @@ int __init agp_i7x05_init(void)
static
void
__exit
agp_i7x05_cleanup
(
void
)
{
agp_unregister_driver
();
agp_unregister_driver
(
&
i7x05_agp_driver
);
pci_unregister_driver
(
&
agp_i7x05_pci_driver
);
}
...
...
drivers/char/agp/intel-agp.c
View file @
733bda87
...
...
@@ -195,7 +195,6 @@ static agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type)
new
->
page_count
=
pg_count
;
new
->
num_scratch_pages
=
0
;
vfree
(
new
->
memory
);
MOD_INC_USE_COUNT
;
return
new
;
}
if
(
type
==
AGP_PHYS_MEMORY
)
{
...
...
@@ -212,7 +211,6 @@ static agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type)
if
(
new
==
NULL
)
return
NULL
;
MOD_INC_USE_COUNT
;
addr
=
agp_bridge
.
agp_alloc_page
();
if
(
addr
==
NULL
)
{
...
...
@@ -238,7 +236,6 @@ static void intel_i810_free_by_type(agp_memory * curr)
vfree
(
curr
->
memory
);
}
kfree
(
curr
);
MOD_DEC_USE_COUNT
;
}
static
unsigned
long
intel_i810_mask_memory
(
unsigned
long
addr
,
int
type
)
...
...
@@ -507,7 +504,6 @@ static agp_memory *intel_i830_alloc_by_type(size_t pg_count,int type)
if
(
nw
==
NULL
)
return
(
NULL
);
MOD_INC_USE_COUNT
;
addr
=
agp_bridge
.
agp_alloc_page
();
if
(
addr
==
NULL
)
{
/* free this structure */
...
...
@@ -1429,11 +1425,15 @@ static int __init agp_find_supported_device(struct pci_dev *dev)
return
agp_lookup_host_bridge
(
dev
);
}
static
struct
agp_driver
intel_agp_driver
=
{
.
owner
=
THIS_MODULE
,
};
static
int
__init
agp_intel_probe
(
struct
pci_dev
*
dev
,
const
struct
pci_device_id
*
ent
)
{
if
(
agp_find_supported_device
(
dev
)
==
0
)
{
agp_register_driver
(
dev
);
intel_agp_driver
.
dev
=
dev
;
agp_register_driver
(
&
intel_agp_driver
);
return
0
;
}
return
-
ENODEV
;
...
...
@@ -1479,7 +1479,7 @@ int __init agp_intel_init(void)
static
void
__exit
agp_intel_cleanup
(
void
)
{
agp_unregister_driver
();
agp_unregister_driver
(
&
intel_agp_driver
);
pci_unregister_driver
(
&
agp_intel_pci_driver
);
}
...
...
drivers/char/agp/sis-agp.c
View file @
733bda87
...
...
@@ -221,6 +221,9 @@ static int __init agp_lookup_host_bridge (struct pci_dev *pdev)
return
-
ENODEV
;
}
static
struct
agp_driver
sis_agp_driver
=
{
.
owner
=
THIS_MODULE
,
};
static
int
__init
agp_sis_probe
(
struct
pci_dev
*
dev
,
const
struct
pci_device_id
*
ent
)
{
...
...
@@ -236,7 +239,8 @@ static int __init agp_sis_probe (struct pci_dev *dev, const struct pci_device_id
agp_bridge
.
capndx
=
cap_ptr
;
/* Fill in the mode register */
pci_read_config_dword
(
agp_bridge
.
dev
,
agp_bridge
.
capndx
+
PCI_AGP_STATUS
,
&
agp_bridge
.
mode
);
agp_register_driver
(
dev
);
sis_agp_driver
.
dev
=
dev
;
agp_register_driver
(
&
sis_agp_driver
);
return
0
;
}
return
-
ENODEV
;
...
...
@@ -275,7 +279,7 @@ static int __init agp_sis_init(void)
static
void
__exit
agp_sis_cleanup
(
void
)
{
agp_unregister_driver
();
agp_unregister_driver
(
&
sis_agp_driver
);
pci_unregister_driver
(
&
agp_sis_pci_driver
);
}
...
...
drivers/char/agp/sworks-agp.c
View file @
733bda87
...
...
@@ -526,11 +526,15 @@ static int __init agp_find_supported_device(struct pci_dev *dev)
return
-
ENODEV
;
}
static
struct
agp_driver
serverworks_agp_driver
=
{
.
owner
=
THIS_MODULE
,
};
static
int
__init
agp_serverworks_probe
(
struct
pci_dev
*
dev
,
const
struct
pci_device_id
*
ent
)
{
if
(
agp_find_supported_device
(
dev
)
==
0
)
{
agp_register_driver
(
dev
);
serverworks_agp_driver
.
dev
=
dev
;
agp_register_driver
(
&
serverworks_agp_driver
);
return
0
;
}
return
-
ENODEV
;
...
...
@@ -569,7 +573,7 @@ static int __init agp_serverworks_init(void)
static
void
__exit
agp_serverworks_cleanup
(
void
)
{
agp_unregister_driver
();
agp_unregister_driver
(
&
serverworks_agp_driver
);
pci_unregister_driver
(
&
agp_serverworks_pci_driver
);
}
...
...
drivers/char/agp/via-agp.c
View file @
733bda87
...
...
@@ -244,6 +244,9 @@ static int __init agp_lookup_host_bridge (struct pci_dev *pdev)
return
-
ENODEV
;
}
static
struct
agp_driver
via_agp_driver
=
{
.
owner
=
THIS_MODULE
,
};
static
int
__init
agp_via_probe
(
struct
pci_dev
*
dev
,
const
struct
pci_device_id
*
ent
)
{
...
...
@@ -259,7 +262,8 @@ static int __init agp_via_probe (struct pci_dev *dev, const struct pci_device_id
agp_bridge
.
capndx
=
cap_ptr
;
/* Fill in the mode register */
pci_read_config_dword
(
agp_bridge
.
dev
,
agp_bridge
.
capndx
+
PCI_AGP_STATUS
,
&
agp_bridge
.
mode
);
agp_register_driver
(
dev
);
via_agp_driver
.
dev
=
dev
;
agp_register_driver
(
&
via_agp_driver
);
return
0
;
}
return
-
ENODEV
;
...
...
@@ -298,7 +302,7 @@ static int __init agp_via_init(void)
static
void
__exit
agp_via_cleanup
(
void
)
{
agp_unregister_driver
();
agp_unregister_driver
(
&
via_agp_driver
);
pci_unregister_driver
(
&
agp_via_pci_driver
);
}
...
...
drivers/char/agp/via-kt400.c
View file @
733bda87
...
...
@@ -100,6 +100,9 @@ static void __init via_kt400_enable(u32 mode)
printk
(
KERN_INFO
PFX
"agp_generic_agp_3_0_enable() failed
\n
"
);
}
static
struct
agp_driver
via_kt400_agp_driver
=
{
.
owner
=
THIS_MODULE
,
};
static
int
__init
agp_via_probe
(
struct
pci_dev
*
dev
,
const
struct
pci_device_id
*
ent
)
{
...
...
@@ -149,7 +152,8 @@ static int __init agp_via_probe (struct pci_dev *dev, const struct pci_device_id
/* Fill in the mode register */
pci_read_config_dword
(
agp_bridge
.
dev
,
agp_bridge
.
capndx
+
PCI_AGP_STATUS
,
&
agp_bridge
.
mode
);
agp_register_driver
(
dev
);
via_kt400_agp_driver
.
dev
=
dev
;
agp_register_driver
(
&
via_kt400_agp_driver
);
return
0
;
}
...
...
@@ -186,7 +190,7 @@ static int __init agp_via_init(void)
static
void
__exit
agp_via_cleanup
(
void
)
{
agp_unregister_driver
();
agp_unregister_driver
(
&
via_kt400_agp_driver
);
pci_unregister_driver
(
&
agp_via_pci_driver
);
}
...
...
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