linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] Introduce AMD Secure Processor device
@ 2017-06-22 11:42 Brijesh Singh
  2017-06-22 11:42 ` [PATCH 1/3] crypto: ccp - Use devres interface to allocate PCI/iomap and cleanup Brijesh Singh
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Brijesh Singh @ 2017-06-22 11:42 UTC (permalink / raw)
  To: linux-crypto, linux-kernel
  Cc: gary.hook, thomas.lendacky, herbert, davem, Brijesh Singh

CCP device (drivers/crypto/ccp/ccp.ko) is part of AMD Secure Processor,
which is not dedicated solely to crypto. The AMD Secure Processor includes
CCP and PSP (Platform Secure Processor) devices.

This patch series adds a framework that allows functional component of the
AMD Secure Processor to be initialized and handled appropriately. The series
does not makes any logic modification into CCP - it refactors the code to
integerate CCP into AMD secure processor framework.

Brijesh Singh (3):
  crypto: ccp - Use devres interface to allocate PCI/iomap and cleanup
  crypto: ccp - Introduce the AMD Secure Processor device
  crypto: cpp - Abstract interrupt registeration

 drivers/crypto/Kconfig            |  10 +-
 drivers/crypto/ccp/Kconfig        |  43 ++++--
 drivers/crypto/ccp/Makefile       |   6 +-
 drivers/crypto/ccp/ccp-dev-v3.c   |  17 ++-
 drivers/crypto/ccp/ccp-dev-v5.c   |  12 +-
 drivers/crypto/ccp/ccp-dev.c      | 124 ++++++++++------
 drivers/crypto/ccp/ccp-dev.h      |  19 +--
 drivers/crypto/ccp/ccp-pci.c      | 264 ++++++++++++---------------------
 drivers/crypto/ccp/ccp-platform.c | 165 ++++++++-------------
 drivers/crypto/ccp/sp-dev.c       | 305 ++++++++++++++++++++++++++++++++++++++
 drivers/crypto/ccp/sp-dev.h       | 133 +++++++++++++++++
 include/linux/ccp.h               |   3 +-
 12 files changed, 730 insertions(+), 371 deletions(-)
 create mode 100644 drivers/crypto/ccp/sp-dev.c
 create mode 100644 drivers/crypto/ccp/sp-dev.h

-- 
2.9.4

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/3] crypto: ccp - Use devres interface to allocate PCI/iomap and cleanup
  2017-06-22 11:42 [PATCH 0/3] Introduce AMD Secure Processor device Brijesh Singh
@ 2017-06-22 11:42 ` Brijesh Singh
  2017-06-22 11:42 ` [PATCH 2/3] crypto: ccp - Introduce the AMD Secure Processor device Brijesh Singh
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: Brijesh Singh @ 2017-06-22 11:42 UTC (permalink / raw)
  To: linux-crypto, linux-kernel
  Cc: gary.hook, thomas.lendacky, herbert, davem, Brijesh Singh

Update pci and platform files to use devres interface to allocate the PCI
and iomap resources. Also add helper functions to consolicate module init,
exit and power mangagement code duplication.

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 drivers/crypto/ccp/ccp-dev-v3.c   |   8 +++
 drivers/crypto/ccp/ccp-dev.c      |  61 ++++++++++++++++++++
 drivers/crypto/ccp/ccp-dev.h      |   6 ++
 drivers/crypto/ccp/ccp-pci.c      | 114 +++++++++-----------------------------
 drivers/crypto/ccp/ccp-platform.c |  56 ++-----------------
 5 files changed, 107 insertions(+), 138 deletions(-)

diff --git a/drivers/crypto/ccp/ccp-dev-v3.c b/drivers/crypto/ccp/ccp-dev-v3.c
index 367c2e3..1cae5a3 100644
--- a/drivers/crypto/ccp/ccp-dev-v3.c
+++ b/drivers/crypto/ccp/ccp-dev-v3.c
@@ -586,6 +586,14 @@ static const struct ccp_actions ccp3_actions = {
 	.irqhandler = ccp_irq_handler,
 };
 
+const struct ccp_vdata ccpv3_platform = {
+	.version = CCP_VERSION(3, 0),
+	.setup = NULL,
+	.perform = &ccp3_actions,
+	.bar = 2,
+	.offset = 0,
+};
+
 const struct ccp_vdata ccpv3 = {
 	.version = CCP_VERSION(3, 0),
 	.setup = NULL,
diff --git a/drivers/crypto/ccp/ccp-dev.c b/drivers/crypto/ccp/ccp-dev.c
index 2506b50..ce35e43 100644
--- a/drivers/crypto/ccp/ccp-dev.c
+++ b/drivers/crypto/ccp/ccp-dev.c
@@ -538,8 +538,69 @@ bool ccp_queues_suspended(struct ccp_device *ccp)
 
 	return ccp->cmd_q_count == suspended;
 }
+
+int ccp_dev_suspend(struct ccp_device *ccp, pm_message_t state)
+{
+	unsigned long flags;
+	unsigned int i;
+
+	spin_lock_irqsave(&ccp->cmd_lock, flags);
+
+	ccp->suspending = 1;
+
+	/* Wake all the queue kthreads to prepare for suspend */
+	for (i = 0; i < ccp->cmd_q_count; i++)
+		wake_up_process(ccp->cmd_q[i].kthread);
+
+	spin_unlock_irqrestore(&ccp->cmd_lock, flags);
+
+	/* Wait for all queue kthreads to say they're done */
+	while (!ccp_queues_suspended(ccp))
+		wait_event_interruptible(ccp->suspend_queue,
+					 ccp_queues_suspended(ccp));
+
+	return 0;
+}
+
+int ccp_dev_resume(struct ccp_device *ccp)
+{
+	unsigned long flags;
+	unsigned int i;
+
+	spin_lock_irqsave(&ccp->cmd_lock, flags);
+
+	ccp->suspending = 0;
+
+	/* Wake up all the kthreads */
+	for (i = 0; i < ccp->cmd_q_count; i++) {
+		ccp->cmd_q[i].suspended = 0;
+		wake_up_process(ccp->cmd_q[i].kthread);
+	}
+
+	spin_unlock_irqrestore(&ccp->cmd_lock, flags);
+
+	return 0;
+}
 #endif
 
+int ccp_dev_init(struct ccp_device *ccp)
+{
+	if (ccp->vdata->setup)
+		ccp->vdata->setup(ccp);
+
+	ccp->io_regs = ccp->io_map + ccp->vdata->offset;
+
+	return ccp->vdata->perform->init(ccp);
+}
+
+void ccp_dev_destroy(struct ccp_device *ccp)
+{
+	if (!ccp)
+		return;
+
+	ccp->vdata->perform->destroy(ccp);
+}
+
 static int __init ccp_mod_init(void)
 {
 #ifdef CONFIG_X86
diff --git a/drivers/crypto/ccp/ccp-dev.h b/drivers/crypto/ccp/ccp-dev.h
index a70154a..df2e76e 100644
--- a/drivers/crypto/ccp/ccp-dev.h
+++ b/drivers/crypto/ccp/ccp-dev.h
@@ -652,6 +652,11 @@ void ccp_dmaengine_unregister(struct ccp_device *ccp);
 void ccp5_debugfs_setup(struct ccp_device *ccp);
 void ccp5_debugfs_destroy(void);
 
+int ccp_dev_init(struct ccp_device *ccp);
+void ccp_dev_destroy(struct ccp_device *ccp);
+int ccp_dev_suspend(struct ccp_device *ccp, pm_message_t state);
+int ccp_dev_resume(struct ccp_device *ccp);
+
 /* Structure for computation functions that are device-specific */
 struct ccp_actions {
 	int (*aes)(struct ccp_op *);
@@ -679,6 +684,7 @@ struct ccp_vdata {
 	const unsigned int offset;
 };
 
+extern const struct ccp_vdata ccpv3_platform;
 extern const struct ccp_vdata ccpv3;
 extern const struct ccp_vdata ccpv5a;
 extern const struct ccp_vdata ccpv5b;
diff --git a/drivers/crypto/ccp/ccp-pci.c b/drivers/crypto/ccp/ccp-pci.c
index e880d4cf4..490ad0a 100644
--- a/drivers/crypto/ccp/ccp-pci.c
+++ b/drivers/crypto/ccp/ccp-pci.c
@@ -150,28 +150,13 @@ static void ccp_free_irqs(struct ccp_device *ccp)
 	ccp->irq = 0;
 }
 
-static int ccp_find_mmio_area(struct ccp_device *ccp)
-{
-	struct device *dev = ccp->dev;
-	struct pci_dev *pdev = to_pci_dev(dev);
-	resource_size_t io_len;
-	unsigned long io_flags;
-
-	io_flags = pci_resource_flags(pdev, ccp->vdata->bar);
-	io_len = pci_resource_len(pdev, ccp->vdata->bar);
-	if ((io_flags & IORESOURCE_MEM) &&
-	    (io_len >= (ccp->vdata->offset + 0x800)))
-		return ccp->vdata->bar;
-
-	return -EIO;
-}
-
 static int ccp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	struct ccp_device *ccp;
 	struct ccp_pci *ccp_pci;
 	struct device *dev = &pdev->dev;
-	unsigned int bar;
+	void __iomem * const *iomap_table;
+	int bar_mask;
 	int ret;
 
 	ret = -ENOMEM;
@@ -193,32 +178,34 @@ static int ccp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	ccp->get_irq = ccp_get_irqs;
 	ccp->free_irq = ccp_free_irqs;
 
-	ret = pci_request_regions(pdev, "ccp");
+	ret = pcim_enable_device(pdev);
 	if (ret) {
-		dev_err(dev, "pci_request_regions failed (%d)\n", ret);
+		dev_err(dev, "pcim_enable_device failed (%d)\n", ret);
 		goto e_err;
 	}
 
-	ret = pci_enable_device(pdev);
+	bar_mask = pci_select_bars(pdev, IORESOURCE_MEM);
+	ret = pcim_iomap_regions(pdev, bar_mask, "ccp");
 	if (ret) {
-		dev_err(dev, "pci_enable_device failed (%d)\n", ret);
-		goto e_regions;
+		dev_err(dev, "pcim_iomap_regions failed (%d)\n", ret);
+		goto e_err;
 	}
 
-	pci_set_master(pdev);
-
-	ret = ccp_find_mmio_area(ccp);
-	if (ret < 0)
-		goto e_device;
-	bar = ret;
+	iomap_table = pcim_iomap_table(pdev);
+	if (!iomap_table) {
+		dev_err(dev, "pcim_iomap_table failed\n");
+		ret = -ENOMEM;
+		goto e_err;
+	}
 
-	ret = -EIO;
-	ccp->io_map = pci_iomap(pdev, bar, 0);
+	ccp->io_map = iomap_table[ccp->vdata->bar];
 	if (!ccp->io_map) {
-		dev_err(dev, "pci_iomap failed\n");
-		goto e_device;
+		dev_err(dev, "ioremap failed\n");
+		ret = -ENOMEM;
+		goto e_err;
 	}
-	ccp->io_regs = ccp->io_map + ccp->vdata->offset;
+
+	pci_set_master(pdev);
 
 	ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48));
 	if (ret) {
@@ -226,32 +213,20 @@ static int ccp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 		if (ret) {
 			dev_err(dev, "dma_set_mask_and_coherent failed (%d)\n",
 				ret);
-			goto e_iomap;
+			goto e_err;
 		}
 	}
 
 	dev_set_drvdata(dev, ccp);
 
-	if (ccp->vdata->setup)
-		ccp->vdata->setup(ccp);
-
-	ret = ccp->vdata->perform->init(ccp);
+	ret = ccp_dev_init(ccp);
 	if (ret)
-		goto e_iomap;
+		goto e_err;
 
 	dev_notice(dev, "enabled\n");
 
 	return 0;
 
-e_iomap:
-	pci_iounmap(pdev, ccp->io_map);
-
-e_device:
-	pci_disable_device(pdev);
-
-e_regions:
-	pci_release_regions(pdev);
-
 e_err:
 	dev_notice(dev, "initialization failed\n");
 	return ret;
@@ -265,13 +240,7 @@ static void ccp_pci_remove(struct pci_dev *pdev)
 	if (!ccp)
 		return;
 
-	ccp->vdata->perform->destroy(ccp);
-
-	pci_iounmap(pdev, ccp->io_map);
-
-	pci_disable_device(pdev);
-
-	pci_release_regions(pdev);
+	ccp_dev_destroy(ccp);
 
 	dev_notice(dev, "disabled\n");
 }
@@ -281,47 +250,16 @@ static int ccp_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 {
 	struct device *dev = &pdev->dev;
 	struct ccp_device *ccp = dev_get_drvdata(dev);
-	unsigned long flags;
-	unsigned int i;
-
-	spin_lock_irqsave(&ccp->cmd_lock, flags);
-
-	ccp->suspending = 1;
-
-	/* Wake all the queue kthreads to prepare for suspend */
-	for (i = 0; i < ccp->cmd_q_count; i++)
-		wake_up_process(ccp->cmd_q[i].kthread);
 
-	spin_unlock_irqrestore(&ccp->cmd_lock, flags);
-
-	/* Wait for all queue kthreads to say they're done */
-	while (!ccp_queues_suspended(ccp))
-		wait_event_interruptible(ccp->suspend_queue,
-					 ccp_queues_suspended(ccp));
-
-	return 0;
+	return ccp_dev_suspend(ccp, state);
 }
 
 static int ccp_pci_resume(struct pci_dev *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct ccp_device *ccp = dev_get_drvdata(dev);
-	unsigned long flags;
-	unsigned int i;
-
-	spin_lock_irqsave(&ccp->cmd_lock, flags);
-
-	ccp->suspending = 0;
 
-	/* Wake up all the kthreads */
-	for (i = 0; i < ccp->cmd_q_count; i++) {
-		ccp->cmd_q[i].suspended = 0;
-		wake_up_process(ccp->cmd_q[i].kthread);
-	}
-
-	spin_unlock_irqrestore(&ccp->cmd_lock, flags);
-
-	return 0;
+	return ccp_dev_resume(ccp);
 }
 #endif
 
diff --git a/drivers/crypto/ccp/ccp-platform.c b/drivers/crypto/ccp/ccp-platform.c
index e26969e..4a970b1 100644
--- a/drivers/crypto/ccp/ccp-platform.c
+++ b/drivers/crypto/ccp/ccp-platform.c
@@ -102,19 +102,6 @@ static void ccp_free_irqs(struct ccp_device *ccp)
 	free_irq(ccp->irq, dev);
 }
 
-static struct resource *ccp_find_mmio_area(struct ccp_device *ccp)
-{
-	struct device *dev = ccp->dev;
-	struct platform_device *pdev = to_platform_device(dev);
-	struct resource *ior;
-
-	ior = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (ior && (resource_size(ior) >= 0x800))
-		return ior;
-
-	return NULL;
-}
-
 static int ccp_platform_probe(struct platform_device *pdev)
 {
 	struct ccp_device *ccp;
@@ -144,7 +131,7 @@ static int ccp_platform_probe(struct platform_device *pdev)
 	ccp->get_irq = ccp_get_irqs;
 	ccp->free_irq = ccp_free_irqs;
 
-	ior = ccp_find_mmio_area(ccp);
+	ior = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	ccp->io_map = devm_ioremap_resource(dev, ior);
 	if (IS_ERR(ccp->io_map)) {
 		ret = PTR_ERR(ccp->io_map);
@@ -172,7 +159,7 @@ static int ccp_platform_probe(struct platform_device *pdev)
 
 	dev_set_drvdata(dev, ccp);
 
-	ret = ccp->vdata->perform->init(ccp);
+	ret = ccp_dev_init(ccp);
 	if (ret)
 		goto e_err;
 
@@ -190,7 +177,7 @@ static int ccp_platform_remove(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	struct ccp_device *ccp = dev_get_drvdata(dev);
 
-	ccp->vdata->perform->destroy(ccp);
+	ccp_dev_destroy(ccp);
 
 	dev_notice(dev, "disabled\n");
 
@@ -203,47 +190,16 @@ static int ccp_platform_suspend(struct platform_device *pdev,
 {
 	struct device *dev = &pdev->dev;
 	struct ccp_device *ccp = dev_get_drvdata(dev);
-	unsigned long flags;
-	unsigned int i;
-
-	spin_lock_irqsave(&ccp->cmd_lock, flags);
 
-	ccp->suspending = 1;
-
-	/* Wake all the queue kthreads to prepare for suspend */
-	for (i = 0; i < ccp->cmd_q_count; i++)
-		wake_up_process(ccp->cmd_q[i].kthread);
-
-	spin_unlock_irqrestore(&ccp->cmd_lock, flags);
-
-	/* Wait for all queue kthreads to say they're done */
-	while (!ccp_queues_suspended(ccp))
-		wait_event_interruptible(ccp->suspend_queue,
-					 ccp_queues_suspended(ccp));
-
-	return 0;
+	return ccp_dev_suspend(ccp, state);
 }
 
 static int ccp_platform_resume(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct ccp_device *ccp = dev_get_drvdata(dev);
-	unsigned long flags;
-	unsigned int i;
-
-	spin_lock_irqsave(&ccp->cmd_lock, flags);
 
-	ccp->suspending = 0;
-
-	/* Wake up all the kthreads */
-	for (i = 0; i < ccp->cmd_q_count; i++) {
-		ccp->cmd_q[i].suspended = 0;
-		wake_up_process(ccp->cmd_q[i].kthread);
-	}
-
-	spin_unlock_irqrestore(&ccp->cmd_lock, flags);
-
-	return 0;
+	return ccp_dev_resume(ccp);
 }
 #endif
 
@@ -258,7 +214,7 @@ MODULE_DEVICE_TABLE(acpi, ccp_acpi_match);
 #ifdef CONFIG_OF
 static const struct of_device_id ccp_of_match[] = {
 	{ .compatible = "amd,ccp-seattle-v1a",
-	  .data = (const void *)&ccpv3 },
+	  .data = (const void *)&ccpv3_platform },
 	{ },
 };
 MODULE_DEVICE_TABLE(of, ccp_of_match);
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/3] crypto: ccp - Introduce the AMD Secure Processor device
  2017-06-22 11:42 [PATCH 0/3] Introduce AMD Secure Processor device Brijesh Singh
  2017-06-22 11:42 ` [PATCH 1/3] crypto: ccp - Use devres interface to allocate PCI/iomap and cleanup Brijesh Singh
@ 2017-06-22 11:42 ` Brijesh Singh
  2017-06-22 11:42 ` [PATCH 3/3] crypto: cpp - Abstract interrupt registeration Brijesh Singh
  2017-06-22 13:25 ` [PATCH 0/3] Introduce AMD Secure Processor device Pavel Machek
  3 siblings, 0 replies; 6+ messages in thread
From: Brijesh Singh @ 2017-06-22 11:42 UTC (permalink / raw)
  To: linux-crypto, linux-kernel
  Cc: gary.hook, thomas.lendacky, herbert, davem, Brijesh Singh

The CCP device is part of the AMD Secure Processor. In order to expand
the usage of the AMD Secure Processor, create a framework that allows
functional components of the AMD Secure Processor to be initialized and
handled appropriately.

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 drivers/crypto/Kconfig            |  10 +-
 drivers/crypto/ccp/Kconfig        |  43 ++++++---
 drivers/crypto/ccp/Makefile       |   6 +-
 drivers/crypto/ccp/ccp-dev-v3.c   |   5 +-
 drivers/crypto/ccp/ccp-dev-v5.c   |   5 +-
 drivers/crypto/ccp/ccp-dev.c      | 106 +++++++++-----------
 drivers/crypto/ccp/ccp-dev.h      |  21 +---
 drivers/crypto/ccp/ccp-pci.c      |  81 ++++++++++------
 drivers/crypto/ccp/ccp-platform.c |  70 ++++++++------
 drivers/crypto/ccp/sp-dev.c       | 198 ++++++++++++++++++++++++++++++++++++++
 drivers/crypto/ccp/sp-dev.h       | 120 +++++++++++++++++++++++
 include/linux/ccp.h               |   3 +-
 12 files changed, 493 insertions(+), 175 deletions(-)
 create mode 100644 drivers/crypto/ccp/sp-dev.c
 create mode 100644 drivers/crypto/ccp/sp-dev.h

diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 0528a62..418f991 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -512,14 +512,14 @@ config CRYPTO_DEV_ATMEL_SHA
 	  To compile this driver as a module, choose M here: the module
 	  will be called atmel-sha.
 
-config CRYPTO_DEV_CCP
-	bool "Support for AMD Cryptographic Coprocessor"
+config CRYPTO_DEV_SP
+	bool "Support for AMD Secure Processor"
 	depends on ((X86 && PCI) || (ARM64 && (OF_ADDRESS || ACPI))) && HAS_IOMEM
 	help
-	  The AMD Cryptographic Coprocessor provides hardware offload support
-	  for encryption, hashing and related operations.
+	  The AMD Secure Processor provides hardware offload support for memory
+	  encryption in virtualization and cryptographic hashing and related operations.
 
-if CRYPTO_DEV_CCP
+if CRYPTO_DEV_SP
 	source "drivers/crypto/ccp/Kconfig"
 endif
 
diff --git a/drivers/crypto/ccp/Kconfig b/drivers/crypto/ccp/Kconfig
index 2238f77..bc08f03 100644
--- a/drivers/crypto/ccp/Kconfig
+++ b/drivers/crypto/ccp/Kconfig
@@ -1,26 +1,37 @@
-config CRYPTO_DEV_CCP_DD
-	tristate "Cryptographic Coprocessor device driver"
-	depends on CRYPTO_DEV_CCP
-	default m
-	select HW_RANDOM
-	select DMA_ENGINE
-	select DMADEVICES
-	select CRYPTO_SHA1
-	select CRYPTO_SHA256
-	help
-	  Provides the interface to use the AMD Cryptographic Coprocessor
-	  which can be used to offload encryption operations such as SHA,
-	  AES and more. If you choose 'M' here, this module will be called
-	  ccp.
-
 config CRYPTO_DEV_CCP_CRYPTO
 	tristate "Encryption and hashing offload support"
-	depends on CRYPTO_DEV_CCP_DD
+	depends on CRYPTO_DEV_SP_DD
 	default m
 	select CRYPTO_HASH
 	select CRYPTO_BLKCIPHER
 	select CRYPTO_AUTHENC
+	select CRYPTO_DEV_CCP
 	help
 	  Support for using the cryptographic API with the AMD Cryptographic
 	  Coprocessor. This module supports offload of SHA and AES algorithms.
 	  If you choose 'M' here, this module will be called ccp_crypto.
+
+config CRYPTO_DEV_SP_DD
+	tristate "Secure Processor device driver"
+	depends on CRYPTO_DEV_SP
+	default m
+	help
+	  Provides the interface to use the AMD Secure Processor. The
+	  AMD Secure Processor support the Platform Security Processor (PSP)
+	  and Cryptographic Coprocessor (CCP). If you choose 'M' here, this
+	  module will be called ccp.
+
+if CRYPTO_DEV_SP_DD
+config CRYPTO_DEV_CCP
+	bool "Cryptographic Coprocessor interface"
+	default y
+	select HW_RANDOM
+	select DMA_ENGINE
+	select DMADEVICES
+	select CRYPTO_SHA1
+	select CRYPTO_SHA256
+	help
+	  Provides the interface to use the AMD Cryptographic Coprocessor
+	  which can be used to offload encryption operations such as SHA,
+	  AES and more.
+endif
diff --git a/drivers/crypto/ccp/Makefile b/drivers/crypto/ccp/Makefile
index 59493fd..ea42888 100644
--- a/drivers/crypto/ccp/Makefile
+++ b/drivers/crypto/ccp/Makefile
@@ -1,9 +1,9 @@
-obj-$(CONFIG_CRYPTO_DEV_CCP_DD) += ccp.o
-ccp-objs := ccp-dev.o \
+obj-$(CONFIG_CRYPTO_DEV_SP_DD) += ccp.o
+ccp-objs  := sp-dev.o ccp-platform.o
+ccp-$(CONFIG_CRYPTO_DEV_CCP) += ccp-dev.o \
 	    ccp-ops.o \
 	    ccp-dev-v3.o \
 	    ccp-dev-v5.o \
-	    ccp-platform.o \
 	    ccp-dmaengine.o \
 	    ccp-debugfs.o
 ccp-$(CONFIG_PCI) += ccp-pci.o
diff --git a/drivers/crypto/ccp/ccp-dev-v3.c b/drivers/crypto/ccp/ccp-dev-v3.c
index 1cae5a3..57179034 100644
--- a/drivers/crypto/ccp/ccp-dev-v3.c
+++ b/drivers/crypto/ccp/ccp-dev-v3.c
@@ -359,8 +359,7 @@ static void ccp_irq_bh(unsigned long data)
 
 static irqreturn_t ccp_irq_handler(int irq, void *data)
 {
-	struct device *dev = data;
-	struct ccp_device *ccp = dev_get_drvdata(dev);
+	struct ccp_device *ccp = (struct ccp_device *)data;
 
 	ccp_disable_queue_interrupts(ccp);
 	if (ccp->use_tasklet)
@@ -590,7 +589,6 @@ const struct ccp_vdata ccpv3_platform = {
 	.version = CCP_VERSION(3, 0),
 	.setup = NULL,
 	.perform = &ccp3_actions,
-	.bar = 2,
 	.offset = 0,
 };
 
@@ -598,6 +596,5 @@ const struct ccp_vdata ccpv3 = {
 	.version = CCP_VERSION(3, 0),
 	.setup = NULL,
 	.perform = &ccp3_actions,
-	.bar = 2,
 	.offset = 0x20000,
 };
diff --git a/drivers/crypto/ccp/ccp-dev-v5.c b/drivers/crypto/ccp/ccp-dev-v5.c
index b10d2d2..8ed2b37 100644
--- a/drivers/crypto/ccp/ccp-dev-v5.c
+++ b/drivers/crypto/ccp/ccp-dev-v5.c
@@ -769,8 +769,7 @@ static void ccp5_irq_bh(unsigned long data)
 
 static irqreturn_t ccp5_irq_handler(int irq, void *data)
 {
-	struct device *dev = data;
-	struct ccp_device *ccp = dev_get_drvdata(dev);
+	struct ccp_device *ccp = (struct ccp_device *)data;
 
 	ccp5_disable_queue_interrupts(ccp);
 	ccp->total_interrupts++;
@@ -1113,7 +1112,6 @@ const struct ccp_vdata ccpv5a = {
 	.version = CCP_VERSION(5, 0),
 	.setup = ccp5_config,
 	.perform = &ccp5_actions,
-	.bar = 2,
 	.offset = 0x0,
 };
 
@@ -1122,6 +1120,5 @@ const struct ccp_vdata ccpv5b = {
 	.dma_chan_attr = DMA_PRIVATE,
 	.setup = ccp5other_config,
 	.perform = &ccp5_actions,
-	.bar = 2,
 	.offset = 0x0,
 };
diff --git a/drivers/crypto/ccp/ccp-dev.c b/drivers/crypto/ccp/ccp-dev.c
index ce35e43..8a1674a 100644
--- a/drivers/crypto/ccp/ccp-dev.c
+++ b/drivers/crypto/ccp/ccp-dev.c
@@ -111,13 +111,6 @@ static LIST_HEAD(ccp_units);
 static DEFINE_SPINLOCK(ccp_rr_lock);
 static struct ccp_device *ccp_rr;
 
-/* Ever-increasing value to produce unique unit numbers */
-static atomic_t ccp_unit_ordinal;
-static unsigned int ccp_increment_unit_ordinal(void)
-{
-	return atomic_inc_return(&ccp_unit_ordinal);
-}
-
 /**
  * ccp_add_device - add a CCP device to the list
  *
@@ -464,14 +457,17 @@ int ccp_cmd_queue_thread(void *data)
  *
  * @dev: device struct of the CCP
  */
-struct ccp_device *ccp_alloc_struct(struct device *dev)
+struct ccp_device *ccp_alloc_struct(struct sp_device *sp)
 {
+	struct device *dev = sp->dev;
 	struct ccp_device *ccp;
 
 	ccp = devm_kzalloc(dev, sizeof(*ccp), GFP_KERNEL);
 	if (!ccp)
 		return NULL;
 	ccp->dev = dev;
+	ccp->sp = sp;
+	ccp->axcache = sp->axcache;
 
 	INIT_LIST_HEAD(&ccp->cmd);
 	INIT_LIST_HEAD(&ccp->backlog);
@@ -486,9 +482,8 @@ struct ccp_device *ccp_alloc_struct(struct device *dev)
 	init_waitqueue_head(&ccp->sb_queue);
 	init_waitqueue_head(&ccp->suspend_queue);
 
-	ccp->ord = ccp_increment_unit_ordinal();
-	snprintf(ccp->name, MAX_CCP_NAME_LEN, "ccp-%u", ccp->ord);
-	snprintf(ccp->rngname, MAX_CCP_NAME_LEN, "ccp-%u-rng", ccp->ord);
+	snprintf(ccp->name, MAX_CCP_NAME_LEN, "ccp-%u", sp->ord);
+	snprintf(ccp->rngname, MAX_CCP_NAME_LEN, "ccp-%u-rng", sp->ord);
 
 	return ccp;
 }
@@ -539,8 +534,9 @@ bool ccp_queues_suspended(struct ccp_device *ccp)
 	return ccp->cmd_q_count == suspended;
 }
 
-int ccp_dev_suspend(struct ccp_device *ccp, pm_message_t state)
+int ccp_dev_suspend(struct sp_device *sp, pm_message_t state)
 {
+	struct ccp_device *ccp = sp->ccp_data;
 	unsigned long flags;
 	unsigned int i;
 
@@ -562,8 +558,9 @@ int ccp_dev_suspend(struct ccp_device *ccp, pm_message_t state)
 	return 0;
 }
 
-int ccp_dev_resume(struct ccp_device *ccp)
+int ccp_dev_resume(struct sp_device *sp)
 {
+	struct ccp_device *ccp = sp->ccp_data;
 	unsigned long flags;
 	unsigned int i;
 
@@ -583,71 +580,54 @@ int ccp_dev_resume(struct ccp_device *ccp)
 }
 #endif
 
-int ccp_dev_init(struct ccp_device *ccp)
+int ccp_dev_init(struct sp_device *sp)
 {
-	if (ccp->vdata->setup)
-		ccp->vdata->setup(ccp);
-
-	ccp->io_regs = ccp->io_map + ccp->vdata->offset;
-
-	return ccp->vdata->perform->init(ccp);
-}
+	struct device *dev = sp->dev;
+	struct ccp_device *ccp;
+	int ret;
 
-void ccp_dev_destroy(struct ccp_device *ccp)
-{
+	ret = -ENOMEM;
+	ccp = ccp_alloc_struct(sp);
 	if (!ccp)
-		return;
+		goto e_err;
+	sp->ccp_data = ccp;
+
+	ccp->vdata = (struct ccp_vdata *)sp->dev_vdata->ccp_vdata;
+	if (!ccp->vdata || !ccp->vdata->version) {
+		ret = -ENODEV;
+		dev_err(dev, "missing driver data\n");
+		goto e_err;
+	}
 
-	ccp->vdata->perform->destroy(ccp);
-}
+	ccp->get_irq = sp->get_irq;
+	ccp->free_irq = sp->free_irq;
 
-static int __init ccp_mod_init(void)
-{
-#ifdef CONFIG_X86
-	int ret;
+	ccp->io_regs = sp->io_map + ccp->vdata->offset;
+	if (ccp->vdata->setup)
+		ccp->vdata->setup(ccp);
 
-	ret = ccp_pci_init();
+	ret = ccp->vdata->perform->init(ccp);
 	if (ret)
-		return ret;
+		goto e_err;
 
-	/* Don't leave the driver loaded if init failed */
-	if (ccp_present() != 0) {
-		ccp_pci_exit();
-		return -ENODEV;
-	}
+	dev_notice(dev, "ccp enabled\n");
 
 	return 0;
-#endif
-
-#ifdef CONFIG_ARM64
-	int ret;
 
-	ret = ccp_platform_init();
-	if (ret)
-		return ret;
+e_err:
+	sp->ccp_data = NULL;
 
-	/* Don't leave the driver loaded if init failed */
-	if (ccp_present() != 0) {
-		ccp_platform_exit();
-		return -ENODEV;
-	}
-
-	return 0;
-#endif
+	dev_notice(dev, "ccp initialization failed\n");
 
-	return -ENODEV;
+	return ret;
 }
 
-static void __exit ccp_mod_exit(void)
+void ccp_dev_destroy(struct sp_device *sp)
 {
-#ifdef CONFIG_X86
-	ccp_pci_exit();
-#endif
+	struct ccp_device *ccp = sp->ccp_data;
 
-#ifdef CONFIG_ARM64
-	ccp_platform_exit();
-#endif
-}
+	if (!ccp)
+		return;
 
-module_init(ccp_mod_init);
-module_exit(ccp_mod_exit);
+	ccp->vdata->perform->destroy(ccp);
+}
diff --git a/drivers/crypto/ccp/ccp-dev.h b/drivers/crypto/ccp/ccp-dev.h
index df2e76e..ca44821 100644
--- a/drivers/crypto/ccp/ccp-dev.h
+++ b/drivers/crypto/ccp/ccp-dev.h
@@ -27,6 +27,8 @@
 #include <linux/irqreturn.h>
 #include <linux/dmaengine.h>
 
+#include "sp-dev.h"
+
 #define MAX_CCP_NAME_LEN		16
 #define MAX_DMAPOOL_NAME_LEN		32
 
@@ -344,6 +346,7 @@ struct ccp_device {
 	char rngname[MAX_CCP_NAME_LEN];
 
 	struct device *dev;
+	struct sp_device *sp;
 
 	/* Bus specific device information
 	 */
@@ -362,7 +365,6 @@ struct ccp_device {
 	 *   them.
 	 */
 	struct mutex req_mutex ____cacheline_aligned;
-	void __iomem *io_map;
 	void __iomem *io_regs;
 
 	/* Master lists that all cmds are queued on. Because there can be
@@ -637,7 +639,7 @@ void ccp_del_device(struct ccp_device *ccp);
 
 extern void ccp_log_error(struct ccp_device *, int);
 
-struct ccp_device *ccp_alloc_struct(struct device *dev);
+struct ccp_device *ccp_alloc_struct(struct sp_device *sp);
 bool ccp_queues_suspended(struct ccp_device *ccp);
 int ccp_cmd_queue_thread(void *data);
 int ccp_trng_read(struct hwrng *rng, void *data, size_t max, bool wait);
@@ -652,11 +654,6 @@ void ccp_dmaengine_unregister(struct ccp_device *ccp);
 void ccp5_debugfs_setup(struct ccp_device *ccp);
 void ccp5_debugfs_destroy(void);
 
-int ccp_dev_init(struct ccp_device *ccp);
-void ccp_dev_destroy(struct ccp_device *ccp);
-int ccp_dev_suspend(struct ccp_device *ccp, pm_message_t state);
-int ccp_dev_resume(struct ccp_device *ccp);
-
 /* Structure for computation functions that are device-specific */
 struct ccp_actions {
 	int (*aes)(struct ccp_op *);
@@ -674,16 +671,6 @@ struct ccp_actions {
 	irqreturn_t (*irqhandler)(int, void *);
 };
 
-/* Structure to hold CCP version-specific values */
-struct ccp_vdata {
-	const unsigned int version;
-	const unsigned int dma_chan_attr;
-	void (*setup)(struct ccp_device *);
-	const struct ccp_actions *perform;
-	const unsigned int bar;
-	const unsigned int offset;
-};
-
 extern const struct ccp_vdata ccpv3_platform;
 extern const struct ccp_vdata ccpv3;
 extern const struct ccp_vdata ccpv5a;
diff --git a/drivers/crypto/ccp/ccp-pci.c b/drivers/crypto/ccp/ccp-pci.c
index 490ad0a..7eab3c6 100644
--- a/drivers/crypto/ccp/ccp-pci.c
+++ b/drivers/crypto/ccp/ccp-pci.c
@@ -40,7 +40,8 @@ struct ccp_pci {
 
 static int ccp_get_msix_irqs(struct ccp_device *ccp)
 {
-	struct ccp_pci *ccp_pci = ccp->dev_specific;
+	struct sp_device *sp = ccp->sp;
+	struct ccp_pci *ccp_pci = sp->dev_specific;
 	struct device *dev = ccp->dev;
 	struct pci_dev *pdev = to_pci_dev(dev);
 	struct msix_entry msix_entry[MSIX_VECTORS];
@@ -58,11 +59,11 @@ static int ccp_get_msix_irqs(struct ccp_device *ccp)
 	for (v = 0; v < ccp_pci->msix_count; v++) {
 		/* Set the interrupt names and request the irqs */
 		snprintf(ccp_pci->msix[v].name, name_len, "%s-%u",
-			 ccp->name, v);
+			 sp->name, v);
 		ccp_pci->msix[v].vector = msix_entry[v].vector;
 		ret = request_irq(ccp_pci->msix[v].vector,
 				  ccp->vdata->perform->irqhandler,
-				  0, ccp_pci->msix[v].name, dev);
+				  0, ccp_pci->msix[v].name, ccp);
 		if (ret) {
 			dev_notice(dev, "unable to allocate MSI-X IRQ (%d)\n",
 				   ret);
@@ -86,6 +87,7 @@ static int ccp_get_msix_irqs(struct ccp_device *ccp)
 
 static int ccp_get_msi_irq(struct ccp_device *ccp)
 {
+	struct sp_device *sp = ccp->sp;
 	struct device *dev = ccp->dev;
 	struct pci_dev *pdev = to_pci_dev(dev);
 	int ret;
@@ -96,7 +98,7 @@ static int ccp_get_msi_irq(struct ccp_device *ccp)
 
 	ccp->irq = pdev->irq;
 	ret = request_irq(ccp->irq, ccp->vdata->perform->irqhandler, 0,
-			  ccp->name, dev);
+			  sp->name, ccp);
 	if (ret) {
 		dev_notice(dev, "unable to allocate MSI IRQ (%d)\n", ret);
 		goto e_msi;
@@ -134,17 +136,18 @@ static int ccp_get_irqs(struct ccp_device *ccp)
 
 static void ccp_free_irqs(struct ccp_device *ccp)
 {
-	struct ccp_pci *ccp_pci = ccp->dev_specific;
+	struct sp_device *sp = ccp->sp;
+	struct ccp_pci *ccp_pci = sp->dev_specific;
 	struct device *dev = ccp->dev;
 	struct pci_dev *pdev = to_pci_dev(dev);
 
 	if (ccp_pci->msix_count) {
 		while (ccp_pci->msix_count--)
 			free_irq(ccp_pci->msix[ccp_pci->msix_count].vector,
-				 dev);
+				 ccp);
 		pci_disable_msix(pdev);
 	} else if (ccp->irq) {
-		free_irq(ccp->irq, dev);
+		free_irq(ccp->irq, ccp);
 		pci_disable_msi(pdev);
 	}
 	ccp->irq = 0;
@@ -152,7 +155,7 @@ static void ccp_free_irqs(struct ccp_device *ccp)
 
 static int ccp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
-	struct ccp_device *ccp;
+	struct sp_device *sp;
 	struct ccp_pci *ccp_pci;
 	struct device *dev = &pdev->dev;
 	void __iomem * const *iomap_table;
@@ -160,23 +163,23 @@ static int ccp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	int ret;
 
 	ret = -ENOMEM;
-	ccp = ccp_alloc_struct(dev);
-	if (!ccp)
+	sp = sp_alloc_struct(dev);
+	if (!sp)
 		goto e_err;
 
 	ccp_pci = devm_kzalloc(dev, sizeof(*ccp_pci), GFP_KERNEL);
 	if (!ccp_pci)
 		goto e_err;
 
-	ccp->dev_specific = ccp_pci;
-	ccp->vdata = (struct ccp_vdata *)id->driver_data;
-	if (!ccp->vdata || !ccp->vdata->version) {
+	sp->dev_specific = ccp_pci;
+	sp->dev_vdata = (struct sp_dev_vdata *)id->driver_data;
+	if (!sp->dev_vdata) {
 		ret = -ENODEV;
 		dev_err(dev, "missing driver data\n");
 		goto e_err;
 	}
-	ccp->get_irq = ccp_get_irqs;
-	ccp->free_irq = ccp_free_irqs;
+	sp->get_irq = ccp_get_irqs;
+	sp->free_irq = ccp_free_irqs;
 
 	ret = pcim_enable_device(pdev);
 	if (ret) {
@@ -198,8 +201,8 @@ static int ccp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 		goto e_err;
 	}
 
-	ccp->io_map = iomap_table[ccp->vdata->bar];
-	if (!ccp->io_map) {
+	sp->io_map = iomap_table[sp->dev_vdata->bar];
+	if (!sp->io_map) {
 		dev_err(dev, "ioremap failed\n");
 		ret = -ENOMEM;
 		goto e_err;
@@ -217,9 +220,9 @@ static int ccp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 		}
 	}
 
-	dev_set_drvdata(dev, ccp);
+	dev_set_drvdata(dev, sp);
 
-	ret = ccp_dev_init(ccp);
+	ret = sp_init(sp);
 	if (ret)
 		goto e_err;
 
@@ -235,12 +238,12 @@ static int ccp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 static void ccp_pci_remove(struct pci_dev *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct ccp_device *ccp = dev_get_drvdata(dev);
+	struct sp_device *sp = dev_get_drvdata(dev);
 
-	if (!ccp)
+	if (!sp)
 		return;
 
-	ccp_dev_destroy(ccp);
+	sp_destroy(sp);
 
 	dev_notice(dev, "disabled\n");
 }
@@ -249,24 +252,44 @@ static void ccp_pci_remove(struct pci_dev *pdev)
 static int ccp_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 {
 	struct device *dev = &pdev->dev;
-	struct ccp_device *ccp = dev_get_drvdata(dev);
+	struct sp_device *sp = dev_get_drvdata(dev);
 
-	return ccp_dev_suspend(ccp, state);
+	return sp_suspend(sp, state);
 }
 
 static int ccp_pci_resume(struct pci_dev *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct ccp_device *ccp = dev_get_drvdata(dev);
+	struct sp_device *sp = dev_get_drvdata(dev);
 
-	return ccp_dev_resume(ccp);
+	return sp_resume(sp);
 }
 #endif
 
+static const struct sp_dev_vdata dev_vdata[] = {
+	{
+		.bar = 2,
+#ifdef CONFIG_CRYPTO_DEV_CCP
+		.ccp_vdata = &ccpv3,
+#endif
+	},
+	{
+		.bar = 2,
+#ifdef CONFIG_CRYPTO_DEV_CCP
+		.ccp_vdata = &ccpv5a,
+#endif
+	},
+	{
+		.bar = 2,
+#ifdef CONFIG_CRYPTO_DEV_CCP
+		.ccp_vdata = &ccpv5b,
+#endif
+	},
+};
 static const struct pci_device_id ccp_pci_table[] = {
-	{ PCI_VDEVICE(AMD, 0x1537), (kernel_ulong_t)&ccpv3 },
-	{ PCI_VDEVICE(AMD, 0x1456), (kernel_ulong_t)&ccpv5a },
-	{ PCI_VDEVICE(AMD, 0x1468), (kernel_ulong_t)&ccpv5b },
+	{ PCI_VDEVICE(AMD, 0x1537), (kernel_ulong_t)&dev_vdata[0] },
+	{ PCI_VDEVICE(AMD, 0x1456), (kernel_ulong_t)&dev_vdata[1] },
+	{ PCI_VDEVICE(AMD, 0x1468), (kernel_ulong_t)&dev_vdata[2] },
 	/* Last entry must be zero */
 	{ 0, }
 };
diff --git a/drivers/crypto/ccp/ccp-platform.c b/drivers/crypto/ccp/ccp-platform.c
index 4a970b1..568178f 100644
--- a/drivers/crypto/ccp/ccp-platform.c
+++ b/drivers/crypto/ccp/ccp-platform.c
@@ -35,26 +35,26 @@ struct ccp_platform {
 static const struct acpi_device_id ccp_acpi_match[];
 static const struct of_device_id ccp_of_match[];
 
-static struct ccp_vdata *ccp_get_of_version(struct platform_device *pdev)
+static struct sp_dev_vdata *ccp_get_of_version(struct platform_device *pdev)
 {
 #ifdef CONFIG_OF
 	const struct of_device_id *match;
 
 	match = of_match_node(ccp_of_match, pdev->dev.of_node);
 	if (match && match->data)
-		return (struct ccp_vdata *)match->data;
+		return (struct sp_dev_vdata *)match->data;
 #endif
 	return NULL;
 }
 
-static struct ccp_vdata *ccp_get_acpi_version(struct platform_device *pdev)
+static struct sp_dev_vdata *ccp_get_acpi_version(struct platform_device *pdev)
 {
 #ifdef CONFIG_ACPI
 	const struct acpi_device_id *match;
 
 	match = acpi_match_device(ccp_acpi_match, &pdev->dev);
 	if (match && match->driver_data)
-		return (struct ccp_vdata *)match->driver_data;
+		return (struct sp_dev_vdata *)match->driver_data;
 #endif
 	return NULL;
 }
@@ -71,7 +71,7 @@ static int ccp_get_irq(struct ccp_device *ccp)
 
 	ccp->irq = ret;
 	ret = request_irq(ccp->irq, ccp->vdata->perform->irqhandler, 0,
-			  ccp->name, dev);
+			  ccp->name, ccp);
 	if (ret) {
 		dev_notice(dev, "unable to allocate IRQ (%d)\n", ret);
 		return ret;
@@ -97,14 +97,12 @@ static int ccp_get_irqs(struct ccp_device *ccp)
 
 static void ccp_free_irqs(struct ccp_device *ccp)
 {
-	struct device *dev = ccp->dev;
-
-	free_irq(ccp->irq, dev);
+	free_irq(ccp->irq, ccp);
 }
 
 static int ccp_platform_probe(struct platform_device *pdev)
 {
-	struct ccp_device *ccp;
+	struct sp_device *sp;
 	struct ccp_platform *ccp_platform;
 	struct device *dev = &pdev->dev;
 	enum dev_dma_attr attr;
@@ -112,32 +110,31 @@ static int ccp_platform_probe(struct platform_device *pdev)
 	int ret;
 
 	ret = -ENOMEM;
-	ccp = ccp_alloc_struct(dev);
-	if (!ccp)
+	sp = sp_alloc_struct(dev);
+	if (!sp)
 		goto e_err;
 
 	ccp_platform = devm_kzalloc(dev, sizeof(*ccp_platform), GFP_KERNEL);
 	if (!ccp_platform)
 		goto e_err;
 
-	ccp->dev_specific = ccp_platform;
-	ccp->vdata = pdev->dev.of_node ? ccp_get_of_version(pdev)
+	sp->dev_specific = ccp_platform;
+	sp->dev_vdata = pdev->dev.of_node ? ccp_get_of_version(pdev)
 					 : ccp_get_acpi_version(pdev);
-	if (!ccp->vdata || !ccp->vdata->version) {
+	if (!sp->dev_vdata) {
 		ret = -ENODEV;
 		dev_err(dev, "missing driver data\n");
 		goto e_err;
 	}
-	ccp->get_irq = ccp_get_irqs;
-	ccp->free_irq = ccp_free_irqs;
+	sp->get_irq = ccp_get_irqs;
+	sp->free_irq = ccp_free_irqs;
 
 	ior = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	ccp->io_map = devm_ioremap_resource(dev, ior);
-	if (IS_ERR(ccp->io_map)) {
-		ret = PTR_ERR(ccp->io_map);
+	sp->io_map = devm_ioremap_resource(dev, ior);
+	if (IS_ERR(sp->io_map)) {
+		ret = PTR_ERR(sp->io_map);
 		goto e_err;
 	}
-	ccp->io_regs = ccp->io_map;
 
 	attr = device_get_dma_attr(dev);
 	if (attr == DEV_DMA_NOT_SUPPORTED) {
@@ -147,9 +144,9 @@ static int ccp_platform_probe(struct platform_device *pdev)
 
 	ccp_platform->coherent = (attr == DEV_DMA_COHERENT);
 	if (ccp_platform->coherent)
-		ccp->axcache = CACHE_WB_NO_ALLOC;
+		sp->axcache = CACHE_WB_NO_ALLOC;
 	else
-		ccp->axcache = CACHE_NONE;
+		sp->axcache = CACHE_NONE;
 
 	ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48));
 	if (ret) {
@@ -157,9 +154,9 @@ static int ccp_platform_probe(struct platform_device *pdev)
 		goto e_err;
 	}
 
-	dev_set_drvdata(dev, ccp);
+	dev_set_drvdata(dev, sp);
 
-	ret = ccp_dev_init(ccp);
+	ret = sp_init(sp);
 	if (ret)
 		goto e_err;
 
@@ -175,9 +172,9 @@ static int ccp_platform_probe(struct platform_device *pdev)
 static int ccp_platform_remove(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct ccp_device *ccp = dev_get_drvdata(dev);
+	struct sp_device *sp = dev_get_drvdata(dev);
 
-	ccp_dev_destroy(ccp);
+	sp_destroy(sp);
 
 	dev_notice(dev, "disabled\n");
 
@@ -189,23 +186,32 @@ static int ccp_platform_suspend(struct platform_device *pdev,
 				pm_message_t state)
 {
 	struct device *dev = &pdev->dev;
-	struct ccp_device *ccp = dev_get_drvdata(dev);
+	struct sp_device *sp = dev_get_drvdata(dev);
 
-	return ccp_dev_suspend(ccp, state);
+	return sp_suspend(sp, state);
 }
 
 static int ccp_platform_resume(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct ccp_device *ccp = dev_get_drvdata(dev);
+	struct sp_device *sp = dev_get_drvdata(dev);
 
-	return ccp_dev_resume(ccp);
+	return sp_resume(sp);
 }
 #endif
 
+static const struct sp_dev_vdata dev_vdata[] = {
+	{
+		.bar = 2,
+#ifdef CONFIG_CRYPTO_DEV_CCP
+		.ccp_vdata = &ccpv3_platform,
+#endif
+	},
+};
+
 #ifdef CONFIG_ACPI
 static const struct acpi_device_id ccp_acpi_match[] = {
-	{ "AMDI0C00", (kernel_ulong_t)&ccpv3 },
+	{ "AMDI0C00", (kernel_ulong_t)&dev_vdata[0] },
 	{ },
 };
 MODULE_DEVICE_TABLE(acpi, ccp_acpi_match);
@@ -214,7 +220,7 @@ MODULE_DEVICE_TABLE(acpi, ccp_acpi_match);
 #ifdef CONFIG_OF
 static const struct of_device_id ccp_of_match[] = {
 	{ .compatible = "amd,ccp-seattle-v1a",
-	  .data = (const void *)&ccpv3_platform },
+	  .data = (const void *)&dev_vdata[0] },
 	{ },
 };
 MODULE_DEVICE_TABLE(of, ccp_of_match);
diff --git a/drivers/crypto/ccp/sp-dev.c b/drivers/crypto/ccp/sp-dev.c
new file mode 100644
index 0000000..ca5fb3f
--- /dev/null
+++ b/drivers/crypto/ccp/sp-dev.c
@@ -0,0 +1,198 @@
+/*
+ * AMD Secure Processor driver
+ *
+ * Copyright (C) 2017 Advanced Micro Devices, Inc.
+ *
+ * Author: Tom Lendacky <thomas.lendacky@amd.com>
+ * Author: Gary R Hook <gary.hook@amd.com>
+ * Author: Brijesh Singh <brijesh.singh@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/spinlock_types.h>
+#include <linux/types.h>
+#include <linux/ccp.h>
+
+#include "ccp-dev.h"
+#include "sp-dev.h"
+
+MODULE_AUTHOR("Tom Lendacky <thomas.lendacky@amd.com>");
+MODULE_AUTHOR("Gary R Hook <gary.hook@amd.com>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.1.0");
+MODULE_DESCRIPTION("AMD Secure Processor driver");
+
+/* List of SPs, SP count, read-write access lock, and access functions
+ *
+ * Lock structure: get sp_unit_lock for reading whenever we need to
+ * examine the SP list.
+ */
+static DEFINE_RWLOCK(sp_unit_lock);
+static LIST_HEAD(sp_units);
+
+/* Ever-increasing value to produce unique unit numbers */
+static atomic_t sp_ordinal;
+
+static void sp_add_device(struct sp_device *sp)
+{
+	unsigned long flags;
+
+	write_lock_irqsave(&sp_unit_lock, flags);
+
+	list_add_tail(&sp->entry, &sp_units);
+
+	write_unlock_irqrestore(&sp_unit_lock, flags);
+}
+
+static void sp_del_device(struct sp_device *sp)
+{
+	unsigned long flags;
+
+	write_lock_irqsave(&sp_unit_lock, flags);
+
+	list_del(&sp->entry);
+
+	write_unlock_irqrestore(&sp_unit_lock, flags);
+}
+
+struct sp_device *sp_get_device(void)
+{
+	struct sp_device *sp = NULL;
+	unsigned long flags;
+
+	write_lock_irqsave(&sp_unit_lock, flags);
+
+	if (list_empty(&sp_units))
+		goto unlock;
+
+	sp = list_first_entry(&sp_units, struct sp_device, entry);
+
+	list_add_tail(&sp->entry, &sp_units);
+unlock:
+	write_unlock_irqrestore(&sp_unit_lock, flags);
+	return sp;
+}
+
+/**
+ * sp_alloc_struct - allocate and initialize the sp_device struct
+ *
+ * @dev: device struct of the SP
+ */
+struct sp_device *sp_alloc_struct(struct device *dev)
+{
+	struct sp_device *sp;
+
+	sp = devm_kzalloc(dev, sizeof(*sp), GFP_KERNEL);
+	if (!sp)
+		return NULL;
+
+	sp->dev = dev;
+	sp->ord = atomic_inc_return(&sp_ordinal);
+	snprintf(sp->name, SP_MAX_NAME_LEN, "sp-%u", sp->ord);
+
+	return sp;
+}
+
+int sp_init(struct sp_device *sp)
+{
+	sp_add_device(sp);
+
+	if (sp->dev_vdata->ccp_vdata)
+		ccp_dev_init(sp);
+
+	return 0;
+}
+
+void sp_destroy(struct sp_device *sp)
+{
+	if (sp->dev_vdata->ccp_vdata)
+		ccp_dev_destroy(sp);
+
+	sp_del_device(sp);
+}
+
+int sp_suspend(struct sp_device *sp, pm_message_t state)
+{
+	int ret;
+
+	if (sp->dev_vdata->ccp_vdata) {
+		ret = ccp_dev_suspend(sp, state);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+int sp_resume(struct sp_device *sp)
+{
+	int ret;
+
+	if (sp->dev_vdata->ccp_vdata) {
+		ret = ccp_dev_resume(sp);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int __init sp_mod_init(void)
+{
+#ifdef CONFIG_X86
+	int ret;
+
+	ret = ccp_pci_init();
+	if (ret)
+		return ret;
+
+	/* Don't leave the driver loaded if init failed */
+	if (ccp_present() != 0) {
+		ccp_pci_exit();
+		return -ENODEV;
+	}
+
+	return 0;
+#endif
+
+#ifdef CONFIG_ARM64
+	int ret;
+
+	ret = ccp_platform_init();
+	if (ret)
+		return ret;
+
+	/* Don't leave the driver loaded if init failed */
+	if (ccp_present() != 0) {
+		ccp_platform_exit();
+		return -ENODEV;
+	}
+
+	return 0;
+#endif
+
+	return -ENODEV;
+}
+
+static void __exit sp_mod_exit(void)
+{
+#ifdef CONFIG_X86
+	ccp_pci_exit();
+#endif
+
+#ifdef CONFIG_ARM64
+	ccp_platform_exit();
+#endif
+}
+
+module_init(sp_mod_init);
+module_exit(sp_mod_exit);
diff --git a/drivers/crypto/ccp/sp-dev.h b/drivers/crypto/ccp/sp-dev.h
new file mode 100644
index 0000000..b958ef9
--- /dev/null
+++ b/drivers/crypto/ccp/sp-dev.h
@@ -0,0 +1,120 @@
+/*
+ * AMD Secure Processor driver
+ *
+ * Copyright (C) 2017 Advanced Micro Devices, Inc.
+ *
+ * Author: Tom Lendacky <thomas.lendacky@amd.com>
+ * Author: Gary R Hook <gary.hook@amd.com>
+ * Author: Brijesh Singh <brijesh.singh@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __SP_DEV_H__
+#define __SP_DEV_H__
+
+#include <linux/device.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+#include <linux/list.h>
+#include <linux/wait.h>
+#include <linux/dmapool.h>
+#include <linux/hw_random.h>
+#include <linux/bitops.h>
+#include <linux/interrupt.h>
+#include <linux/irqreturn.h>
+
+#define SP_MAX_NAME_LEN		32
+
+#define CACHE_NONE			0x00
+#define CACHE_WB_NO_ALLOC		0xb7
+
+/* Structure to hold CCP device data */
+struct ccp_device;
+struct ccp_vdata {
+	const unsigned int version;
+	const unsigned int dma_chan_attr;
+	void (*setup)(struct ccp_device *);
+	const struct ccp_actions *perform;
+	const unsigned int offset;
+};
+/* Structure to hold SP device data */
+struct sp_dev_vdata {
+	const unsigned int bar;
+
+	const struct ccp_vdata *ccp_vdata;
+	void *psp_vdata;
+};
+
+struct sp_device {
+	struct list_head entry;
+
+	struct device *dev;
+
+	struct sp_dev_vdata *dev_vdata;
+	unsigned int ord;
+	char name[SP_MAX_NAME_LEN];
+
+	/* Bus specific device information */
+	void *dev_specific;
+
+	/* I/O area used for device communication. */
+	void __iomem *io_map;
+
+	/* DMA caching attribute support */
+	unsigned int axcache;
+
+	bool irq_registered;
+
+	int (*get_irq)(struct ccp_device *ccp);
+	void (*free_irq)(struct ccp_device *ccp);
+
+	void *ccp_data;
+	void *psp_data;
+};
+
+int sp_pci_init(void);
+void sp_pci_exit(void);
+
+int sp_platform_init(void);
+void sp_platform_exit(void);
+
+struct sp_device *sp_alloc_struct(struct device *dev);
+
+int sp_init(struct sp_device *sp);
+void sp_destroy(struct sp_device *sp);
+struct sp_device *sp_get_master(void);
+
+int sp_suspend(struct sp_device *sp, pm_message_t state);
+int sp_resume(struct sp_device *sp);
+
+#ifdef CONFIG_CRYPTO_DEV_CCP
+
+int ccp_dev_init(struct sp_device *sp);
+void ccp_dev_destroy(struct sp_device *sp);
+
+int ccp_dev_suspend(struct sp_device *sp, pm_message_t state);
+int ccp_dev_resume(struct sp_device *sp);
+
+#else	/* !CONFIG_CRYPTO_DEV_CCP */
+
+static inline int ccp_dev_init(struct sp_device *sp)
+{
+	return 0;
+}
+static inline void ccp_dev_destroy(struct sp_device *sp) { }
+
+static inline int ccp_dev_suspend(struct sp_device *sp, pm_message_t state)
+{
+	return 0;
+}
+static inline int ccp_dev_resume(struct sp_device *sp)
+{
+	return 0;
+}
+#endif	/* CONFIG_CRYPTO_DEV_CCP */
+
+#endif
diff --git a/include/linux/ccp.h b/include/linux/ccp.h
index 3285c94..d341636 100644
--- a/include/linux/ccp.h
+++ b/include/linux/ccp.h
@@ -24,8 +24,7 @@
 struct ccp_device;
 struct ccp_cmd;
 
-#if defined(CONFIG_CRYPTO_DEV_CCP_DD) || \
-	defined(CONFIG_CRYPTO_DEV_CCP_DD_MODULE)
+#if defined(CONFIG_CRYPTO_DEV_CCP)
 
 /**
  * ccp_present - check if a CCP device is present
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 3/3] crypto: cpp - Abstract interrupt registeration
  2017-06-22 11:42 [PATCH 0/3] Introduce AMD Secure Processor device Brijesh Singh
  2017-06-22 11:42 ` [PATCH 1/3] crypto: ccp - Use devres interface to allocate PCI/iomap and cleanup Brijesh Singh
  2017-06-22 11:42 ` [PATCH 2/3] crypto: ccp - Introduce the AMD Secure Processor device Brijesh Singh
@ 2017-06-22 11:42 ` Brijesh Singh
  2017-06-22 13:25 ` [PATCH 0/3] Introduce AMD Secure Processor device Pavel Machek
  3 siblings, 0 replies; 6+ messages in thread
From: Brijesh Singh @ 2017-06-22 11:42 UTC (permalink / raw)
  To: linux-crypto, linux-kernel
  Cc: gary.hook, thomas.lendacky, herbert, davem, Brijesh Singh

The CCP and PSP devices part of AMD Secure Procesor may share the same
interrupt. Hence we expand the SP device to register a common interrupt
handler and provide functions to CCP and PSP devices to register their
interrupt callback which will be invoked upon interrupt.

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 drivers/crypto/ccp/ccp-dev-v3.c   |   6 +--
 drivers/crypto/ccp/ccp-dev-v5.c   |   7 ++-
 drivers/crypto/ccp/ccp-dev.c      |   3 +-
 drivers/crypto/ccp/ccp-dev.h      |   2 -
 drivers/crypto/ccp/ccp-pci.c      | 103 +++++++++++-------------------------
 drivers/crypto/ccp/ccp-platform.c |  57 ++++++++++----------
 drivers/crypto/ccp/sp-dev.c       | 107 ++++++++++++++++++++++++++++++++++++++
 drivers/crypto/ccp/sp-dev.h       |  17 +++++-
 8 files changed, 187 insertions(+), 115 deletions(-)

diff --git a/drivers/crypto/ccp/ccp-dev-v3.c b/drivers/crypto/ccp/ccp-dev-v3.c
index 57179034..695fde8 100644
--- a/drivers/crypto/ccp/ccp-dev-v3.c
+++ b/drivers/crypto/ccp/ccp-dev-v3.c
@@ -453,7 +453,7 @@ static int ccp_init(struct ccp_device *ccp)
 	iowrite32(ccp->qim, ccp->io_regs + IRQ_STATUS_REG);
 
 	/* Request an irq */
-	ret = ccp->get_irq(ccp);
+	ret = sp_request_ccp_irq(ccp->sp, ccp_irq_handler, ccp->name, ccp);
 	if (ret) {
 		dev_err(dev, "unable to allocate an IRQ\n");
 		goto e_pool;
@@ -510,7 +510,7 @@ static int ccp_init(struct ccp_device *ccp)
 		if (ccp->cmd_q[i].kthread)
 			kthread_stop(ccp->cmd_q[i].kthread);
 
-	ccp->free_irq(ccp);
+	sp_free_ccp_irq(ccp->sp, ccp);
 
 e_pool:
 	for (i = 0; i < ccp->cmd_q_count; i++)
@@ -549,7 +549,7 @@ static void ccp_destroy(struct ccp_device *ccp)
 		if (ccp->cmd_q[i].kthread)
 			kthread_stop(ccp->cmd_q[i].kthread);
 
-	ccp->free_irq(ccp);
+	sp_free_ccp_irq(ccp->sp, ccp);
 
 	for (i = 0; i < ccp->cmd_q_count; i++)
 		dma_pool_destroy(ccp->cmd_q[i].dma_pool);
diff --git a/drivers/crypto/ccp/ccp-dev-v5.c b/drivers/crypto/ccp/ccp-dev-v5.c
index 8ed2b37..b0391f0 100644
--- a/drivers/crypto/ccp/ccp-dev-v5.c
+++ b/drivers/crypto/ccp/ccp-dev-v5.c
@@ -880,7 +880,7 @@ static int ccp5_init(struct ccp_device *ccp)
 
 	dev_dbg(dev, "Requesting an IRQ...\n");
 	/* Request an irq */
-	ret = ccp->get_irq(ccp);
+	ret = sp_request_ccp_irq(ccp->sp, ccp5_irq_handler, ccp->name, ccp);
 	if (ret) {
 		dev_err(dev, "unable to allocate an IRQ\n");
 		goto e_pool;
@@ -986,7 +986,7 @@ static int ccp5_init(struct ccp_device *ccp)
 			kthread_stop(ccp->cmd_q[i].kthread);
 
 e_irq:
-	ccp->free_irq(ccp);
+	sp_free_ccp_irq(ccp->sp, ccp);
 
 e_pool:
 	for (i = 0; i < ccp->cmd_q_count; i++)
@@ -1036,7 +1036,7 @@ static void ccp5_destroy(struct ccp_device *ccp)
 		if (ccp->cmd_q[i].kthread)
 			kthread_stop(ccp->cmd_q[i].kthread);
 
-	ccp->free_irq(ccp);
+	sp_free_ccp_irq(ccp->sp, ccp);
 
 	for (i = 0; i < ccp->cmd_q_count; i++) {
 		cmd_q = &ccp->cmd_q[i];
@@ -1105,7 +1105,6 @@ static const struct ccp_actions ccp5_actions = {
 	.init = ccp5_init,
 	.destroy = ccp5_destroy,
 	.get_free_slots = ccp5_get_free_slots,
-	.irqhandler = ccp5_irq_handler,
 };
 
 const struct ccp_vdata ccpv5a = {
diff --git a/drivers/crypto/ccp/ccp-dev.c b/drivers/crypto/ccp/ccp-dev.c
index 8a1674a..7c751bf 100644
--- a/drivers/crypto/ccp/ccp-dev.c
+++ b/drivers/crypto/ccp/ccp-dev.c
@@ -599,8 +599,7 @@ int ccp_dev_init(struct sp_device *sp)
 		goto e_err;
 	}
 
-	ccp->get_irq = sp->get_irq;
-	ccp->free_irq = sp->free_irq;
+	ccp->use_tasklet = sp->use_tasklet;
 
 	ccp->io_regs = sp->io_map + ccp->vdata->offset;
 	if (ccp->vdata->setup)
diff --git a/drivers/crypto/ccp/ccp-dev.h b/drivers/crypto/ccp/ccp-dev.h
index ca44821..193f309 100644
--- a/drivers/crypto/ccp/ccp-dev.h
+++ b/drivers/crypto/ccp/ccp-dev.h
@@ -351,8 +351,6 @@ struct ccp_device {
 	/* Bus specific device information
 	 */
 	void *dev_specific;
-	int (*get_irq)(struct ccp_device *ccp);
-	void (*free_irq)(struct ccp_device *ccp);
 	unsigned int qim;
 	unsigned int irq;
 	bool use_tasklet;
diff --git a/drivers/crypto/ccp/ccp-pci.c b/drivers/crypto/ccp/ccp-pci.c
index 7eab3c6..f6b9858 100644
--- a/drivers/crypto/ccp/ccp-pci.c
+++ b/drivers/crypto/ccp/ccp-pci.c
@@ -28,67 +28,37 @@
 
 #define MSIX_VECTORS			2
 
-struct ccp_msix {
-	u32 vector;
-	char name[16];
-};
-
 struct ccp_pci {
 	int msix_count;
-	struct ccp_msix msix[MSIX_VECTORS];
+	struct msix_entry msix_entry[MSIX_VECTORS];
 };
 
-static int ccp_get_msix_irqs(struct ccp_device *ccp)
+static int ccp_get_msix_irqs(struct sp_device *sp)
 {
-	struct sp_device *sp = ccp->sp;
 	struct ccp_pci *ccp_pci = sp->dev_specific;
-	struct device *dev = ccp->dev;
+	struct device *dev = sp->dev;
 	struct pci_dev *pdev = to_pci_dev(dev);
-	struct msix_entry msix_entry[MSIX_VECTORS];
-	unsigned int name_len = sizeof(ccp_pci->msix[0].name) - 1;
 	int v, ret;
 
-	for (v = 0; v < ARRAY_SIZE(msix_entry); v++)
-		msix_entry[v].entry = v;
+	for (v = 0; v < ARRAY_SIZE(ccp_pci->msix_entry); v++)
+		ccp_pci->msix_entry[v].entry = v;
 
-	ret = pci_enable_msix_range(pdev, msix_entry, 1, v);
+	ret = pci_enable_msix_range(pdev, ccp_pci->msix_entry, 1, v);
 	if (ret < 0)
 		return ret;
 
 	ccp_pci->msix_count = ret;
-	for (v = 0; v < ccp_pci->msix_count; v++) {
-		/* Set the interrupt names and request the irqs */
-		snprintf(ccp_pci->msix[v].name, name_len, "%s-%u",
-			 sp->name, v);
-		ccp_pci->msix[v].vector = msix_entry[v].vector;
-		ret = request_irq(ccp_pci->msix[v].vector,
-				  ccp->vdata->perform->irqhandler,
-				  0, ccp_pci->msix[v].name, ccp);
-		if (ret) {
-			dev_notice(dev, "unable to allocate MSI-X IRQ (%d)\n",
-				   ret);
-			goto e_irq;
-		}
-	}
-	ccp->use_tasklet = true;
+	sp->use_tasklet = true;
 
+	sp->psp_irq = ccp_pci->msix_entry[0].vector;
+	sp->ccp_irq = (ccp_pci->msix_count > 1) ? ccp_pci->msix_entry[1].vector
+					       : ccp_pci->msix_entry[0].vector;
 	return 0;
-
-e_irq:
-	while (v--)
-		free_irq(ccp_pci->msix[v].vector, dev);
-
-	pci_disable_msix(pdev);
-
-	ccp_pci->msix_count = 0;
-
-	return ret;
 }
 
-static int ccp_get_msi_irq(struct ccp_device *ccp)
+static int ccp_get_msi_irq(struct sp_device *sp)
 {
-	struct sp_device *sp = ccp->sp;
-	struct device *dev = ccp->dev;
+	struct device *dev = sp->dev;
 	struct pci_dev *pdev = to_pci_dev(dev);
 	int ret;
 
@@ -96,35 +66,24 @@ static int ccp_get_msi_irq(struct ccp_device *ccp)
 	if (ret)
 		return ret;
 
-	ccp->irq = pdev->irq;
-	ret = request_irq(ccp->irq, ccp->vdata->perform->irqhandler, 0,
-			  sp->name, ccp);
-	if (ret) {
-		dev_notice(dev, "unable to allocate MSI IRQ (%d)\n", ret);
-		goto e_msi;
-	}
-	ccp->use_tasklet = true;
+	sp->ccp_irq = pdev->irq;
+	sp->psp_irq = pdev->irq;
 
 	return 0;
-
-e_msi:
-	pci_disable_msi(pdev);
-
-	return ret;
 }
 
-static int ccp_get_irqs(struct ccp_device *ccp)
+static int ccp_get_irqs(struct sp_device *sp)
 {
-	struct device *dev = ccp->dev;
+	struct device *dev = sp->dev;
 	int ret;
 
-	ret = ccp_get_msix_irqs(ccp);
+	ret = ccp_get_msix_irqs(sp);
 	if (!ret)
 		return 0;
 
 	/* Couldn't get MSI-X vectors, try MSI */
 	dev_notice(dev, "could not enable MSI-X (%d), trying MSI\n", ret);
-	ret = ccp_get_msi_irq(ccp);
+	ret = ccp_get_msi_irq(sp);
 	if (!ret)
 		return 0;
 
@@ -134,23 +93,19 @@ static int ccp_get_irqs(struct ccp_device *ccp)
 	return ret;
 }
 
-static void ccp_free_irqs(struct ccp_device *ccp)
+static void ccp_free_irqs(struct sp_device *sp)
 {
-	struct sp_device *sp = ccp->sp;
 	struct ccp_pci *ccp_pci = sp->dev_specific;
-	struct device *dev = ccp->dev;
+	struct device *dev = sp->dev;
 	struct pci_dev *pdev = to_pci_dev(dev);
 
-	if (ccp_pci->msix_count) {
-		while (ccp_pci->msix_count--)
-			free_irq(ccp_pci->msix[ccp_pci->msix_count].vector,
-				 ccp);
+	if (ccp_pci->msix_count)
 		pci_disable_msix(pdev);
-	} else if (ccp->irq) {
-		free_irq(ccp->irq, ccp);
+	else if (sp->psp_irq)
 		pci_disable_msi(pdev);
-	}
-	ccp->irq = 0;
+
+	sp->ccp_irq = 0;
+	sp->psp_irq = 0;
 }
 
 static int ccp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
@@ -178,8 +133,6 @@ static int ccp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 		dev_err(dev, "missing driver data\n");
 		goto e_err;
 	}
-	sp->get_irq = ccp_get_irqs;
-	sp->free_irq = ccp_free_irqs;
 
 	ret = pcim_enable_device(pdev);
 	if (ret) {
@@ -208,6 +161,10 @@ static int ccp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 		goto e_err;
 	}
 
+	ret = ccp_get_irqs(sp);
+	if (ret)
+		goto e_err;
+
 	pci_set_master(pdev);
 
 	ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48));
@@ -245,6 +202,8 @@ static void ccp_pci_remove(struct pci_dev *pdev)
 
 	sp_destroy(sp);
 
+	ccp_free_irqs(sp);
+
 	dev_notice(dev, "disabled\n");
 }
 
diff --git a/drivers/crypto/ccp/ccp-platform.c b/drivers/crypto/ccp/ccp-platform.c
index 568178f..1cea657 100644
--- a/drivers/crypto/ccp/ccp-platform.c
+++ b/drivers/crypto/ccp/ccp-platform.c
@@ -30,6 +30,7 @@
 
 struct ccp_platform {
 	int coherent;
+	unsigned int irq_count;
 };
 
 static const struct acpi_device_id ccp_acpi_match[];
@@ -59,45 +60,39 @@ static struct sp_dev_vdata *ccp_get_acpi_version(struct platform_device *pdev)
 	return NULL;
 }
 
-static int ccp_get_irq(struct ccp_device *ccp)
+static int ccp_get_irqs(struct sp_device *sp)
 {
-	struct device *dev = ccp->dev;
+	struct ccp_platform *ccp_platform = sp->dev_specific;
+	struct device *dev = sp->dev;
 	struct platform_device *pdev = to_platform_device(dev);
+	unsigned int i, count;
 	int ret;
 
-	ret = platform_get_irq(pdev, 0);
-	if (ret < 0)
-		return ret;
+	for (i = 0, count = 0; i < pdev->num_resources; i++) {
+		struct resource *res = &pdev->resource[i];
 
-	ccp->irq = ret;
-	ret = request_irq(ccp->irq, ccp->vdata->perform->irqhandler, 0,
-			  ccp->name, ccp);
-	if (ret) {
-		dev_notice(dev, "unable to allocate IRQ (%d)\n", ret);
-		return ret;
+		if (resource_type(res) == IORESOURCE_IRQ)
+			count++;
 	}
 
-	return 0;
-}
+	ccp_platform->irq_count = count;
 
-static int ccp_get_irqs(struct ccp_device *ccp)
-{
-	struct device *dev = ccp->dev;
-	int ret;
-
-	ret = ccp_get_irq(ccp);
-	if (!ret)
-		return 0;
+	ret = platform_get_irq(pdev, 0);
+	if (ret < 0)
+		return ret;
 
-	/* Couldn't get an interrupt */
-	dev_notice(dev, "could not enable interrupts (%d)\n", ret);
+	sp->psp_irq = ret;
+	if (count == 1) {
+		sp->ccp_irq = ret;
+	} else {
+		ret = platform_get_irq(pdev, 1);
+		if (ret < 0)
+			return ret;
 
-	return ret;
-}
+		sp->ccp_irq = ret;
+	}
 
-static void ccp_free_irqs(struct ccp_device *ccp)
-{
-	free_irq(ccp->irq, ccp);
+	return 0;
 }
 
 static int ccp_platform_probe(struct platform_device *pdev)
@@ -126,8 +121,6 @@ static int ccp_platform_probe(struct platform_device *pdev)
 		dev_err(dev, "missing driver data\n");
 		goto e_err;
 	}
-	sp->get_irq = ccp_get_irqs;
-	sp->free_irq = ccp_free_irqs;
 
 	ior = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	sp->io_map = devm_ioremap_resource(dev, ior);
@@ -154,6 +147,10 @@ static int ccp_platform_probe(struct platform_device *pdev)
 		goto e_err;
 	}
 
+	ret = ccp_get_irqs(sp);
+	if (ret)
+		goto e_err;
+
 	dev_set_drvdata(dev, sp);
 
 	ret = sp_init(sp);
diff --git a/drivers/crypto/ccp/sp-dev.c b/drivers/crypto/ccp/sp-dev.c
index ca5fb3f..a77d2b9 100644
--- a/drivers/crypto/ccp/sp-dev.c
+++ b/drivers/crypto/ccp/sp-dev.c
@@ -82,6 +82,113 @@ struct sp_device *sp_get_device(void)
 	return sp;
 }
 
+static irqreturn_t sp_irq_handler(int irq, void *data)
+{
+	struct sp_device *sp = data;
+
+	if (sp->ccp_irq_handler)
+		sp->ccp_irq_handler(irq, sp->ccp_irq_data);
+
+	if (sp->psp_irq_handler)
+		sp->psp_irq_handler(irq, sp->psp_irq_data);
+
+	return IRQ_HANDLED;
+}
+
+int sp_request_ccp_irq(struct sp_device *sp, irq_handler_t handler,
+		       const char *name, void *data)
+{
+	int ret;
+
+	if ((sp->psp_irq == sp->ccp_irq) && sp->dev_vdata->psp_vdata) {
+		/* Need a common routine to manage all interrupts */
+		sp->ccp_irq_data = data;
+		sp->ccp_irq_handler = handler;
+
+		if (!sp->irq_registered) {
+			ret = request_irq(sp->ccp_irq, sp_irq_handler, 0,
+					  sp->name, sp);
+			if (ret)
+				return ret;
+
+			sp->irq_registered = true;
+		}
+	} else {
+		/* Each sub-device can manage it's own interrupt */
+		ret = request_irq(sp->ccp_irq, handler, 0, name, data);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+int sp_request_psp_irq(struct sp_device *sp, irq_handler_t handler,
+		       const char *name, void *data)
+{
+	int ret;
+
+	if ((sp->psp_irq == sp->ccp_irq) && sp->dev_vdata->ccp_vdata) {
+		/* Need a common routine to manage all interrupts */
+		sp->psp_irq_data = data;
+		sp->psp_irq_handler = handler;
+
+		if (!sp->irq_registered) {
+			ret = request_irq(sp->psp_irq, sp_irq_handler, 0,
+					  sp->name, sp);
+			if (ret)
+				return ret;
+
+			sp->irq_registered = true;
+		}
+	} else {
+		/* Each sub-device can manage it's own interrupt */
+		ret = request_irq(sp->psp_irq, handler, 0, name, data);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+void sp_free_ccp_irq(struct sp_device *sp, void *data)
+{
+	if ((sp->psp_irq == sp->ccp_irq) && sp->dev_vdata->psp_vdata) {
+		/* Using common routine to manage all interrupts */
+		if (!sp->psp_irq_handler) {
+			/* Nothing else using it, so free it */
+			free_irq(sp->ccp_irq, sp);
+
+			sp->irq_registered = false;
+		}
+
+		sp->ccp_irq_handler = NULL;
+		sp->ccp_irq_data = NULL;
+	} else {
+		/* Each sub-device can manage it's own interrupt */
+		free_irq(sp->ccp_irq, data);
+	}
+}
+
+void sp_free_psp_irq(struct sp_device *sp, void *data)
+{
+	if ((sp->psp_irq == sp->ccp_irq) && sp->dev_vdata->ccp_vdata) {
+		/* Using common routine to manage all interrupts */
+		if (!sp->ccp_irq_handler) {
+			/* Nothing else using it, so free it */
+			free_irq(sp->psp_irq, sp);
+
+			sp->irq_registered = false;
+		}
+
+		sp->psp_irq_handler = NULL;
+		sp->psp_irq_data = NULL;
+	} else {
+		/* Each sub-device can manage it's own interrupt */
+		free_irq(sp->psp_irq, data);
+	}
+}
+
 /**
  * sp_alloc_struct - allocate and initialize the sp_device struct
  *
diff --git a/drivers/crypto/ccp/sp-dev.h b/drivers/crypto/ccp/sp-dev.h
index b958ef9..77f3735 100644
--- a/drivers/crypto/ccp/sp-dev.h
+++ b/drivers/crypto/ccp/sp-dev.h
@@ -68,9 +68,15 @@ struct sp_device {
 	unsigned int axcache;
 
 	bool irq_registered;
+	bool use_tasklet;
 
-	int (*get_irq)(struct ccp_device *ccp);
-	void (*free_irq)(struct ccp_device *ccp);
+	unsigned int ccp_irq;
+	irq_handler_t ccp_irq_handler;
+	void *ccp_irq_data;
+
+	unsigned int psp_irq;
+	irq_handler_t psp_irq_handler;
+	void *psp_irq_data;
 
 	void *ccp_data;
 	void *psp_data;
@@ -91,6 +97,13 @@ struct sp_device *sp_get_master(void);
 int sp_suspend(struct sp_device *sp, pm_message_t state);
 int sp_resume(struct sp_device *sp);
 
+int sp_request_ccp_irq(struct sp_device *sp, irq_handler_t handler,
+		       const char *name, void *data);
+void sp_free_ccp_irq(struct sp_device *sp, void *data);
+int sp_request_psp_irq(struct sp_device *sp, irq_handler_t handler,
+		       const char *name, void *data);
+void sp_free_psp_irq(struct sp_device *sp, void *data);
+
 #ifdef CONFIG_CRYPTO_DEV_CCP
 
 int ccp_dev_init(struct sp_device *sp);
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 0/3] Introduce AMD Secure Processor device
  2017-06-22 11:42 [PATCH 0/3] Introduce AMD Secure Processor device Brijesh Singh
                   ` (2 preceding siblings ...)
  2017-06-22 11:42 ` [PATCH 3/3] crypto: cpp - Abstract interrupt registeration Brijesh Singh
@ 2017-06-22 13:25 ` Pavel Machek
  2017-06-23 21:23   ` Brijesh Singh
  3 siblings, 1 reply; 6+ messages in thread
From: Pavel Machek @ 2017-06-22 13:25 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: linux-crypto, linux-kernel, gary.hook, thomas.lendacky, herbert, davem

On Thu 2017-06-22 06:42:01, Brijesh Singh wrote:
> CCP device (drivers/crypto/ccp/ccp.ko) is part of AMD Secure Processor,
> which is not dedicated solely to crypto. The AMD Secure Processor includes
> CCP and PSP (Platform Secure Processor) devices.
> 
> This patch series adds a framework that allows functional component of the
> AMD Secure Processor to be initialized and handled appropriately. The series
> does not makes any logic modification into CCP - it refactors the code to
> integerate CCP into AMD secure processor framework.

Ok, so this is just preparation. When finished, what services will it provide
to Linux userland?

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 0/3] Introduce AMD Secure Processor device
  2017-06-22 13:25 ` [PATCH 0/3] Introduce AMD Secure Processor device Pavel Machek
@ 2017-06-23 21:23   ` Brijesh Singh
  0 siblings, 0 replies; 6+ messages in thread
From: Brijesh Singh @ 2017-06-23 21:23 UTC (permalink / raw)
  To: Pavel Machek
  Cc: brijesh.singh, linux-crypto, linux-kernel, Hook, Gary,
	thomas.lendacky, herbert, davem



On 06/22/2017 08:25 AM, Pavel Machek wrote:
> On Thu 2017-06-22 06:42:01, Brijesh Singh wrote:
>> CCP device (drivers/crypto/ccp/ccp.ko) is part of AMD Secure Processor,
>> which is not dedicated solely to crypto. The AMD Secure Processor includes
>> CCP and PSP (Platform Secure Processor) devices.
>>
>> This patch series adds a framework that allows functional component of the
>> AMD Secure Processor to be initialized and handled appropriately. The series
>> does not makes any logic modification into CCP - it refactors the code to
>> integerate CCP into AMD secure processor framework.
> 
> Ok, so this is just preparation. When finished, what services will it provide
> to Linux userland?

Yes, this is in preparation to add PSP [1] and SEV (Secure Encrypted Virtualization)
[2] support. When finished, the SEV will provide:

a) in-kernel API to communicate with SEV FW inside the AMD Secure Processor
b) userspace ioctl to manage the platform keys/certificates

I have posted PSP and SEV patches as part of SEV RFC, see below

[1] http://marc.info/?l=linux-mm&m=148846780431232&w=2
[2] http://marc.info/?l=linux-mm&m=148847075032602&w=2

-Brijesh

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2017-06-23 21:24 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-06-22 11:42 [PATCH 0/3] Introduce AMD Secure Processor device Brijesh Singh
2017-06-22 11:42 ` [PATCH 1/3] crypto: ccp - Use devres interface to allocate PCI/iomap and cleanup Brijesh Singh
2017-06-22 11:42 ` [PATCH 2/3] crypto: ccp - Introduce the AMD Secure Processor device Brijesh Singh
2017-06-22 11:42 ` [PATCH 3/3] crypto: cpp - Abstract interrupt registeration Brijesh Singh
2017-06-22 13:25 ` [PATCH 0/3] Introduce AMD Secure Processor device Pavel Machek
2017-06-23 21:23   ` Brijesh Singh

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).