Commit d0ebbc0c authored by Brijesh Singh's avatar Brijesh Singh Committed by Herbert Xu

crypto: ccp - rename ccp driver initialize files as sp device

CCP device initializes is now integerated into higher level SP device,
to avoid the confusion lets rename the ccp driver initialization files
(ccp-platform.c->sp-platform.c, ccp-pci.c->sp-pci.c). The patch does not
make any functional changes other than renaming file and structures
Signed-off-by: default avatarBrijesh Singh <brijesh.singh@amd.com>
Acked-by: default avatarGary R Hook <gary.hook@amd.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent f4d18d65
obj-$(CONFIG_CRYPTO_DEV_CCP_DD) += ccp.o obj-$(CONFIG_CRYPTO_DEV_CCP_DD) += ccp.o
ccp-objs := sp-dev.o ccp-platform.o ccp-objs := sp-dev.o sp-platform.o
ccp-$(CONFIG_CRYPTO_DEV_SP_CCP) += ccp-dev.o \ ccp-$(CONFIG_CRYPTO_DEV_SP_CCP) += ccp-dev.o \
ccp-ops.o \ ccp-ops.o \
ccp-dev-v3.o \ ccp-dev-v3.o \
ccp-dev-v5.o \ ccp-dev-v5.o \
ccp-dmaengine.o \ ccp-dmaengine.o \
ccp-debugfs.o ccp-debugfs.o
ccp-$(CONFIG_PCI) += ccp-pci.o ccp-$(CONFIG_PCI) += sp-pci.o
obj-$(CONFIG_CRYPTO_DEV_CCP_CRYPTO) += ccp-crypto.o obj-$(CONFIG_CRYPTO_DEV_CCP_CRYPTO) += ccp-crypto.o
ccp-crypto-objs := ccp-crypto-main.o \ ccp-crypto-objs := ccp-crypto-main.o \
......
...@@ -626,12 +626,6 @@ struct ccp5_desc { ...@@ -626,12 +626,6 @@ struct ccp5_desc {
struct dword7 dw7; struct dword7 dw7;
}; };
int ccp_pci_init(void);
void ccp_pci_exit(void);
int ccp_platform_init(void);
void ccp_platform_exit(void);
void ccp_add_device(struct ccp_device *ccp); void ccp_add_device(struct ccp_device *ccp);
void ccp_del_device(struct ccp_device *ccp); void ccp_del_device(struct ccp_device *ccp);
......
...@@ -242,13 +242,13 @@ static int __init sp_mod_init(void) ...@@ -242,13 +242,13 @@ static int __init sp_mod_init(void)
#ifdef CONFIG_X86 #ifdef CONFIG_X86
int ret; int ret;
ret = ccp_pci_init(); ret = sp_pci_init();
if (ret) if (ret)
return ret; return ret;
/* Don't leave the driver loaded if init failed */ /* Don't leave the driver loaded if init failed */
if (ccp_present() != 0) { if (ccp_present() != 0) {
ccp_pci_exit(); sp_pci_exit();
return -ENODEV; return -ENODEV;
} }
...@@ -258,13 +258,13 @@ static int __init sp_mod_init(void) ...@@ -258,13 +258,13 @@ static int __init sp_mod_init(void)
#ifdef CONFIG_ARM64 #ifdef CONFIG_ARM64
int ret; int ret;
ret = ccp_platform_init(); ret = sp_platform_init();
if (ret) if (ret)
return ret; return ret;
/* Don't leave the driver loaded if init failed */ /* Don't leave the driver loaded if init failed */
if (ccp_present() != 0) { if (ccp_present() != 0) {
ccp_platform_exit(); sp_platform_exit();
return -ENODEV; return -ENODEV;
} }
...@@ -277,11 +277,11 @@ static int __init sp_mod_init(void) ...@@ -277,11 +277,11 @@ static int __init sp_mod_init(void)
static void __exit sp_mod_exit(void) static void __exit sp_mod_exit(void)
{ {
#ifdef CONFIG_X86 #ifdef CONFIG_X86
ccp_pci_exit(); sp_pci_exit();
#endif #endif
#ifdef CONFIG_ARM64 #ifdef CONFIG_ARM64
ccp_platform_exit(); sp_platform_exit();
#endif #endif
} }
......
/* /*
* AMD Cryptographic Coprocessor (CCP) driver * AMD Secure Processor device driver
* *
* Copyright (C) 2013,2016 Advanced Micro Devices, Inc. * Copyright (C) 2013,2016 Advanced Micro Devices, Inc.
* *
...@@ -28,35 +28,35 @@ ...@@ -28,35 +28,35 @@
#define MSIX_VECTORS 2 #define MSIX_VECTORS 2
struct ccp_pci { struct sp_pci {
int msix_count; int msix_count;
struct msix_entry msix_entry[MSIX_VECTORS]; struct msix_entry msix_entry[MSIX_VECTORS];
}; };
static int ccp_get_msix_irqs(struct sp_device *sp) static int sp_get_msix_irqs(struct sp_device *sp)
{ {
struct ccp_pci *ccp_pci = sp->dev_specific; struct sp_pci *sp_pci = sp->dev_specific;
struct device *dev = sp->dev; struct device *dev = sp->dev;
struct pci_dev *pdev = to_pci_dev(dev); struct pci_dev *pdev = to_pci_dev(dev);
int v, ret; int v, ret;
for (v = 0; v < ARRAY_SIZE(ccp_pci->msix_entry); v++) for (v = 0; v < ARRAY_SIZE(sp_pci->msix_entry); v++)
ccp_pci->msix_entry[v].entry = v; sp_pci->msix_entry[v].entry = v;
ret = pci_enable_msix_range(pdev, ccp_pci->msix_entry, 1, v); ret = pci_enable_msix_range(pdev, sp_pci->msix_entry, 1, v);
if (ret < 0) if (ret < 0)
return ret; return ret;
ccp_pci->msix_count = ret; sp_pci->msix_count = ret;
sp->use_tasklet = true; sp->use_tasklet = true;
sp->psp_irq = ccp_pci->msix_entry[0].vector; sp->psp_irq = sp_pci->msix_entry[0].vector;
sp->ccp_irq = (ccp_pci->msix_count > 1) ? ccp_pci->msix_entry[1].vector sp->ccp_irq = (sp_pci->msix_count > 1) ? sp_pci->msix_entry[1].vector
: ccp_pci->msix_entry[0].vector; : sp_pci->msix_entry[0].vector;
return 0; return 0;
} }
static int ccp_get_msi_irq(struct sp_device *sp) static int sp_get_msi_irq(struct sp_device *sp)
{ {
struct device *dev = sp->dev; struct device *dev = sp->dev;
struct pci_dev *pdev = to_pci_dev(dev); struct pci_dev *pdev = to_pci_dev(dev);
...@@ -72,18 +72,18 @@ static int ccp_get_msi_irq(struct sp_device *sp) ...@@ -72,18 +72,18 @@ static int ccp_get_msi_irq(struct sp_device *sp)
return 0; return 0;
} }
static int ccp_get_irqs(struct sp_device *sp) static int sp_get_irqs(struct sp_device *sp)
{ {
struct device *dev = sp->dev; struct device *dev = sp->dev;
int ret; int ret;
ret = ccp_get_msix_irqs(sp); ret = sp_get_msix_irqs(sp);
if (!ret) if (!ret)
return 0; return 0;
/* Couldn't get MSI-X vectors, try MSI */ /* Couldn't get MSI-X vectors, try MSI */
dev_notice(dev, "could not enable MSI-X (%d), trying MSI\n", ret); dev_notice(dev, "could not enable MSI-X (%d), trying MSI\n", ret);
ret = ccp_get_msi_irq(sp); ret = sp_get_msi_irq(sp);
if (!ret) if (!ret)
return 0; return 0;
...@@ -93,13 +93,13 @@ static int ccp_get_irqs(struct sp_device *sp) ...@@ -93,13 +93,13 @@ static int ccp_get_irqs(struct sp_device *sp)
return ret; return ret;
} }
static void ccp_free_irqs(struct sp_device *sp) static void sp_free_irqs(struct sp_device *sp)
{ {
struct ccp_pci *ccp_pci = sp->dev_specific; struct sp_pci *sp_pci = sp->dev_specific;
struct device *dev = sp->dev; struct device *dev = sp->dev;
struct pci_dev *pdev = to_pci_dev(dev); struct pci_dev *pdev = to_pci_dev(dev);
if (ccp_pci->msix_count) if (sp_pci->msix_count)
pci_disable_msix(pdev); pci_disable_msix(pdev);
else if (sp->psp_irq) else if (sp->psp_irq)
pci_disable_msi(pdev); pci_disable_msi(pdev);
...@@ -108,10 +108,10 @@ static void ccp_free_irqs(struct sp_device *sp) ...@@ -108,10 +108,10 @@ static void ccp_free_irqs(struct sp_device *sp)
sp->psp_irq = 0; sp->psp_irq = 0;
} }
static int ccp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) static int sp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{ {
struct sp_device *sp; struct sp_device *sp;
struct ccp_pci *ccp_pci; struct sp_pci *sp_pci;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
void __iomem * const *iomap_table; void __iomem * const *iomap_table;
int bar_mask; int bar_mask;
...@@ -122,11 +122,11 @@ static int ccp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -122,11 +122,11 @@ static int ccp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (!sp) if (!sp)
goto e_err; goto e_err;
ccp_pci = devm_kzalloc(dev, sizeof(*ccp_pci), GFP_KERNEL); sp_pci = devm_kzalloc(dev, sizeof(*sp_pci), GFP_KERNEL);
if (!ccp_pci) if (!sp_pci)
goto e_err; goto e_err;
sp->dev_specific = ccp_pci; sp->dev_specific = sp_pci;
sp->dev_vdata = (struct sp_dev_vdata *)id->driver_data; sp->dev_vdata = (struct sp_dev_vdata *)id->driver_data;
if (!sp->dev_vdata) { if (!sp->dev_vdata) {
ret = -ENODEV; ret = -ENODEV;
...@@ -161,7 +161,7 @@ static int ccp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -161,7 +161,7 @@ static int ccp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto e_err; goto e_err;
} }
ret = ccp_get_irqs(sp); ret = sp_get_irqs(sp);
if (ret) if (ret)
goto e_err; goto e_err;
...@@ -192,7 +192,7 @@ static int ccp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -192,7 +192,7 @@ static int ccp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return ret; return ret;
} }
static void ccp_pci_remove(struct pci_dev *pdev) static void sp_pci_remove(struct pci_dev *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct sp_device *sp = dev_get_drvdata(dev); struct sp_device *sp = dev_get_drvdata(dev);
...@@ -202,13 +202,13 @@ static void ccp_pci_remove(struct pci_dev *pdev) ...@@ -202,13 +202,13 @@ static void ccp_pci_remove(struct pci_dev *pdev)
sp_destroy(sp); sp_destroy(sp);
ccp_free_irqs(sp); sp_free_irqs(sp);
dev_notice(dev, "disabled\n"); dev_notice(dev, "disabled\n");
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int ccp_pci_suspend(struct pci_dev *pdev, pm_message_t state) static int sp_pci_suspend(struct pci_dev *pdev, pm_message_t state)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct sp_device *sp = dev_get_drvdata(dev); struct sp_device *sp = dev_get_drvdata(dev);
...@@ -216,7 +216,7 @@ static int ccp_pci_suspend(struct pci_dev *pdev, pm_message_t state) ...@@ -216,7 +216,7 @@ static int ccp_pci_suspend(struct pci_dev *pdev, pm_message_t state)
return sp_suspend(sp, state); return sp_suspend(sp, state);
} }
static int ccp_pci_resume(struct pci_dev *pdev) static int sp_pci_resume(struct pci_dev *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct sp_device *sp = dev_get_drvdata(dev); struct sp_device *sp = dev_get_drvdata(dev);
...@@ -245,32 +245,32 @@ static const struct sp_dev_vdata dev_vdata[] = { ...@@ -245,32 +245,32 @@ static const struct sp_dev_vdata dev_vdata[] = {
#endif #endif
}, },
}; };
static const struct pci_device_id ccp_pci_table[] = { static const struct pci_device_id sp_pci_table[] = {
{ PCI_VDEVICE(AMD, 0x1537), (kernel_ulong_t)&dev_vdata[0] }, { PCI_VDEVICE(AMD, 0x1537), (kernel_ulong_t)&dev_vdata[0] },
{ PCI_VDEVICE(AMD, 0x1456), (kernel_ulong_t)&dev_vdata[1] }, { PCI_VDEVICE(AMD, 0x1456), (kernel_ulong_t)&dev_vdata[1] },
{ PCI_VDEVICE(AMD, 0x1468), (kernel_ulong_t)&dev_vdata[2] }, { PCI_VDEVICE(AMD, 0x1468), (kernel_ulong_t)&dev_vdata[2] },
/* Last entry must be zero */ /* Last entry must be zero */
{ 0, } { 0, }
}; };
MODULE_DEVICE_TABLE(pci, ccp_pci_table); MODULE_DEVICE_TABLE(pci, sp_pci_table);
static struct pci_driver ccp_pci_driver = { static struct pci_driver sp_pci_driver = {
.name = "ccp", .name = "ccp",
.id_table = ccp_pci_table, .id_table = sp_pci_table,
.probe = ccp_pci_probe, .probe = sp_pci_probe,
.remove = ccp_pci_remove, .remove = sp_pci_remove,
#ifdef CONFIG_PM #ifdef CONFIG_PM
.suspend = ccp_pci_suspend, .suspend = sp_pci_suspend,
.resume = ccp_pci_resume, .resume = sp_pci_resume,
#endif #endif
}; };
int ccp_pci_init(void) int sp_pci_init(void)
{ {
return pci_register_driver(&ccp_pci_driver); return pci_register_driver(&sp_pci_driver);
} }
void ccp_pci_exit(void) void sp_pci_exit(void)
{ {
pci_unregister_driver(&ccp_pci_driver); pci_unregister_driver(&sp_pci_driver);
} }
/* /*
* AMD Cryptographic Coprocessor (CCP) driver * AMD Secure Processor device driver
* *
* Copyright (C) 2014,2016 Advanced Micro Devices, Inc. * Copyright (C) 2014,2016 Advanced Micro Devices, Inc.
* *
...@@ -28,41 +28,41 @@ ...@@ -28,41 +28,41 @@
#include "ccp-dev.h" #include "ccp-dev.h"
struct ccp_platform { struct sp_platform {
int coherent; int coherent;
unsigned int irq_count; unsigned int irq_count;
}; };
static const struct acpi_device_id ccp_acpi_match[]; static const struct acpi_device_id sp_acpi_match[];
static const struct of_device_id ccp_of_match[]; static const struct of_device_id sp_of_match[];
static struct sp_dev_vdata *ccp_get_of_version(struct platform_device *pdev) static struct sp_dev_vdata *sp_get_of_version(struct platform_device *pdev)
{ {
#ifdef CONFIG_OF #ifdef CONFIG_OF
const struct of_device_id *match; const struct of_device_id *match;
match = of_match_node(ccp_of_match, pdev->dev.of_node); match = of_match_node(sp_of_match, pdev->dev.of_node);
if (match && match->data) if (match && match->data)
return (struct sp_dev_vdata *)match->data; return (struct sp_dev_vdata *)match->data;
#endif #endif
return NULL; return NULL;
} }
static struct sp_dev_vdata *ccp_get_acpi_version(struct platform_device *pdev) static struct sp_dev_vdata *sp_get_acpi_version(struct platform_device *pdev)
{ {
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
const struct acpi_device_id *match; const struct acpi_device_id *match;
match = acpi_match_device(ccp_acpi_match, &pdev->dev); match = acpi_match_device(sp_acpi_match, &pdev->dev);
if (match && match->driver_data) if (match && match->driver_data)
return (struct sp_dev_vdata *)match->driver_data; return (struct sp_dev_vdata *)match->driver_data;
#endif #endif
return NULL; return NULL;
} }
static int ccp_get_irqs(struct sp_device *sp) static int sp_get_irqs(struct sp_device *sp)
{ {
struct ccp_platform *ccp_platform = sp->dev_specific; struct sp_platform *sp_platform = sp->dev_specific;
struct device *dev = sp->dev; struct device *dev = sp->dev;
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
unsigned int i, count; unsigned int i, count;
...@@ -75,7 +75,7 @@ static int ccp_get_irqs(struct sp_device *sp) ...@@ -75,7 +75,7 @@ static int ccp_get_irqs(struct sp_device *sp)
count++; count++;
} }
ccp_platform->irq_count = count; sp_platform->irq_count = count;
ret = platform_get_irq(pdev, 0); ret = platform_get_irq(pdev, 0);
if (ret < 0) { if (ret < 0) {
...@@ -99,10 +99,10 @@ static int ccp_get_irqs(struct sp_device *sp) ...@@ -99,10 +99,10 @@ static int ccp_get_irqs(struct sp_device *sp)
return 0; return 0;
} }
static int ccp_platform_probe(struct platform_device *pdev) static int sp_platform_probe(struct platform_device *pdev)
{ {
struct sp_device *sp; struct sp_device *sp;
struct ccp_platform *ccp_platform; struct sp_platform *sp_platform;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
enum dev_dma_attr attr; enum dev_dma_attr attr;
struct resource *ior; struct resource *ior;
...@@ -113,13 +113,13 @@ static int ccp_platform_probe(struct platform_device *pdev) ...@@ -113,13 +113,13 @@ static int ccp_platform_probe(struct platform_device *pdev)
if (!sp) if (!sp)
goto e_err; goto e_err;
ccp_platform = devm_kzalloc(dev, sizeof(*ccp_platform), GFP_KERNEL); sp_platform = devm_kzalloc(dev, sizeof(*sp_platform), GFP_KERNEL);
if (!ccp_platform) if (!sp_platform)
goto e_err; goto e_err;
sp->dev_specific = ccp_platform; sp->dev_specific = sp_platform;
sp->dev_vdata = pdev->dev.of_node ? ccp_get_of_version(pdev) sp->dev_vdata = pdev->dev.of_node ? sp_get_of_version(pdev)
: ccp_get_acpi_version(pdev); : sp_get_acpi_version(pdev);
if (!sp->dev_vdata) { if (!sp->dev_vdata) {
ret = -ENODEV; ret = -ENODEV;
dev_err(dev, "missing driver data\n"); dev_err(dev, "missing driver data\n");
...@@ -139,8 +139,8 @@ static int ccp_platform_probe(struct platform_device *pdev) ...@@ -139,8 +139,8 @@ static int ccp_platform_probe(struct platform_device *pdev)
goto e_err; goto e_err;
} }
ccp_platform->coherent = (attr == DEV_DMA_COHERENT); sp_platform->coherent = (attr == DEV_DMA_COHERENT);
if (ccp_platform->coherent) if (sp_platform->coherent)
sp->axcache = CACHE_WB_NO_ALLOC; sp->axcache = CACHE_WB_NO_ALLOC;
else else
sp->axcache = CACHE_NONE; sp->axcache = CACHE_NONE;
...@@ -151,7 +151,7 @@ static int ccp_platform_probe(struct platform_device *pdev) ...@@ -151,7 +151,7 @@ static int ccp_platform_probe(struct platform_device *pdev)
goto e_err; goto e_err;
} }
ret = ccp_get_irqs(sp); ret = sp_get_irqs(sp);
if (ret) if (ret)
goto e_err; goto e_err;
...@@ -170,7 +170,7 @@ static int ccp_platform_probe(struct platform_device *pdev) ...@@ -170,7 +170,7 @@ static int ccp_platform_probe(struct platform_device *pdev)
return ret; return ret;
} }
static int ccp_platform_remove(struct platform_device *pdev) static int sp_platform_remove(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct sp_device *sp = dev_get_drvdata(dev); struct sp_device *sp = dev_get_drvdata(dev);
...@@ -183,7 +183,7 @@ static int ccp_platform_remove(struct platform_device *pdev) ...@@ -183,7 +183,7 @@ static int ccp_platform_remove(struct platform_device *pdev)
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int ccp_platform_suspend(struct platform_device *pdev, static int sp_platform_suspend(struct platform_device *pdev,
pm_message_t state) pm_message_t state)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
...@@ -192,7 +192,7 @@ static int ccp_platform_suspend(struct platform_device *pdev, ...@@ -192,7 +192,7 @@ static int ccp_platform_suspend(struct platform_device *pdev,
return sp_suspend(sp, state); return sp_suspend(sp, state);
} }
static int ccp_platform_resume(struct platform_device *pdev) static int sp_platform_resume(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct sp_device *sp = dev_get_drvdata(dev); struct sp_device *sp = dev_get_drvdata(dev);
...@@ -211,46 +211,46 @@ static const struct sp_dev_vdata dev_vdata[] = { ...@@ -211,46 +211,46 @@ static const struct sp_dev_vdata dev_vdata[] = {
}; };
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
static const struct acpi_device_id ccp_acpi_match[] = { static const struct acpi_device_id sp_acpi_match[] = {
{ "AMDI0C00", (kernel_ulong_t)&dev_vdata[0] }, { "AMDI0C00", (kernel_ulong_t)&dev_vdata[0] },
{ }, { },
}; };
MODULE_DEVICE_TABLE(acpi, ccp_acpi_match); MODULE_DEVICE_TABLE(acpi, sp_acpi_match);
#endif #endif
#ifdef CONFIG_OF #ifdef CONFIG_OF
static const struct of_device_id ccp_of_match[] = { static const struct of_device_id sp_of_match[] = {
{ .compatible = "amd,ccp-seattle-v1a", { .compatible = "amd,ccp-seattle-v1a",
.data = (const void *)&dev_vdata[0] }, .data = (const void *)&dev_vdata[0] },
{ }, { },
}; };
MODULE_DEVICE_TABLE(of, ccp_of_match); MODULE_DEVICE_TABLE(of, sp_of_match);
#endif #endif
static struct platform_driver ccp_platform_driver = { static struct platform_driver sp_platform_driver = {
.driver = { .driver = {
.name = "ccp", .name = "ccp",
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
.acpi_match_table = ccp_acpi_match, .acpi_match_table = sp_acpi_match,
#endif #endif
#ifdef CONFIG_OF #ifdef CONFIG_OF
.of_match_table = ccp_of_match, .of_match_table = sp_of_match,
#endif #endif
}, },
.probe = ccp_platform_probe, .probe = sp_platform_probe,
.remove = ccp_platform_remove, .remove = sp_platform_remove,
#ifdef CONFIG_PM #ifdef CONFIG_PM
.suspend = ccp_platform_suspend, .suspend = sp_platform_suspend,
.resume = ccp_platform_resume, .resume = sp_platform_resume,
#endif #endif
}; };
int ccp_platform_init(void) int sp_platform_init(void)
{ {
return platform_driver_register(&ccp_platform_driver); return platform_driver_register(&sp_platform_driver);
} }
void ccp_platform_exit(void) void sp_platform_exit(void)
{ {
platform_driver_unregister(&ccp_platform_driver); platform_driver_unregister(&sp_platform_driver);
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment