aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGary R Hook <gary.hook@amd.com>2016-03-01 14:49:15 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2016-03-11 08:19:16 -0500
commitc7019c4d739e79d7baaa13c86dcaaedec8113d70 (patch)
treec24da238ee41a0692db13c0903fc7d28b02deb3a
parent553d2374db0bb3f48bbd29bef7ba2a4d1a3f325d (diff)
crypto: ccp - CCP versioning support
Future hardware may introduce new algorithms wherein the driver will need to manage resources for different versions of the cryptographic coprocessor. This precursor patch determines the version of the available device, and marks and registers algorithms accordingly. A structure is added which manages the version-specific data. Signed-off-by: Gary R Hook <gary.hook@amd.com> Acked-by: Tom Lendacky <thomas.lendacky@amd.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r--drivers/crypto/ccp/ccp-crypto-aes.c12
-rw-r--r--drivers/crypto/ccp/ccp-crypto-sha.c9
-rw-r--r--drivers/crypto/ccp/ccp-dev.c27
-rw-r--r--drivers/crypto/ccp/ccp-dev.h8
-rw-r--r--drivers/crypto/ccp/ccp-pci.c8
-rw-r--r--drivers/crypto/ccp/ccp-platform.c39
-rw-r--r--include/linux/ccp.h17
7 files changed, 115 insertions, 5 deletions
diff --git a/drivers/crypto/ccp/ccp-crypto-aes.c b/drivers/crypto/ccp/ccp-crypto-aes.c
index 7984f910884d..89291c15015c 100644
--- a/drivers/crypto/ccp/ccp-crypto-aes.c
+++ b/drivers/crypto/ccp/ccp-crypto-aes.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * AMD Cryptographic Coprocessor (CCP) AES crypto API support 2 * AMD Cryptographic Coprocessor (CCP) AES crypto API support
3 * 3 *
4 * Copyright (C) 2013 Advanced Micro Devices, Inc. 4 * Copyright (C) 2013,2016 Advanced Micro Devices, Inc.
5 * 5 *
6 * Author: Tom Lendacky <thomas.lendacky@amd.com> 6 * Author: Tom Lendacky <thomas.lendacky@amd.com>
7 * 7 *
@@ -259,6 +259,7 @@ static struct crypto_alg ccp_aes_rfc3686_defaults = {
259 259
260struct ccp_aes_def { 260struct ccp_aes_def {
261 enum ccp_aes_mode mode; 261 enum ccp_aes_mode mode;
262 unsigned int version;
262 const char *name; 263 const char *name;
263 const char *driver_name; 264 const char *driver_name;
264 unsigned int blocksize; 265 unsigned int blocksize;
@@ -269,6 +270,7 @@ struct ccp_aes_def {
269static struct ccp_aes_def aes_algs[] = { 270static struct ccp_aes_def aes_algs[] = {
270 { 271 {
271 .mode = CCP_AES_MODE_ECB, 272 .mode = CCP_AES_MODE_ECB,
273 .version = CCP_VERSION(3, 0),
272 .name = "ecb(aes)", 274 .name = "ecb(aes)",
273 .driver_name = "ecb-aes-ccp", 275 .driver_name = "ecb-aes-ccp",
274 .blocksize = AES_BLOCK_SIZE, 276 .blocksize = AES_BLOCK_SIZE,
@@ -277,6 +279,7 @@ static struct ccp_aes_def aes_algs[] = {
277 }, 279 },
278 { 280 {
279 .mode = CCP_AES_MODE_CBC, 281 .mode = CCP_AES_MODE_CBC,
282 .version = CCP_VERSION(3, 0),
280 .name = "cbc(aes)", 283 .name = "cbc(aes)",
281 .driver_name = "cbc-aes-ccp", 284 .driver_name = "cbc-aes-ccp",
282 .blocksize = AES_BLOCK_SIZE, 285 .blocksize = AES_BLOCK_SIZE,
@@ -285,6 +288,7 @@ static struct ccp_aes_def aes_algs[] = {
285 }, 288 },
286 { 289 {
287 .mode = CCP_AES_MODE_CFB, 290 .mode = CCP_AES_MODE_CFB,
291 .version = CCP_VERSION(3, 0),
288 .name = "cfb(aes)", 292 .name = "cfb(aes)",
289 .driver_name = "cfb-aes-ccp", 293 .driver_name = "cfb-aes-ccp",
290 .blocksize = AES_BLOCK_SIZE, 294 .blocksize = AES_BLOCK_SIZE,
@@ -293,6 +297,7 @@ static struct ccp_aes_def aes_algs[] = {
293 }, 297 },
294 { 298 {
295 .mode = CCP_AES_MODE_OFB, 299 .mode = CCP_AES_MODE_OFB,
300 .version = CCP_VERSION(3, 0),
296 .name = "ofb(aes)", 301 .name = "ofb(aes)",
297 .driver_name = "ofb-aes-ccp", 302 .driver_name = "ofb-aes-ccp",
298 .blocksize = 1, 303 .blocksize = 1,
@@ -301,6 +306,7 @@ static struct ccp_aes_def aes_algs[] = {
301 }, 306 },
302 { 307 {
303 .mode = CCP_AES_MODE_CTR, 308 .mode = CCP_AES_MODE_CTR,
309 .version = CCP_VERSION(3, 0),
304 .name = "ctr(aes)", 310 .name = "ctr(aes)",
305 .driver_name = "ctr-aes-ccp", 311 .driver_name = "ctr-aes-ccp",
306 .blocksize = 1, 312 .blocksize = 1,
@@ -309,6 +315,7 @@ static struct ccp_aes_def aes_algs[] = {
309 }, 315 },
310 { 316 {
311 .mode = CCP_AES_MODE_CTR, 317 .mode = CCP_AES_MODE_CTR,
318 .version = CCP_VERSION(3, 0),
312 .name = "rfc3686(ctr(aes))", 319 .name = "rfc3686(ctr(aes))",
313 .driver_name = "rfc3686-ctr-aes-ccp", 320 .driver_name = "rfc3686-ctr-aes-ccp",
314 .blocksize = 1, 321 .blocksize = 1,
@@ -357,8 +364,11 @@ static int ccp_register_aes_alg(struct list_head *head,
357int ccp_register_aes_algs(struct list_head *head) 364int ccp_register_aes_algs(struct list_head *head)
358{ 365{
359 int i, ret; 366 int i, ret;
367 unsigned int ccpversion = ccp_version();
360 368
361 for (i = 0; i < ARRAY_SIZE(aes_algs); i++) { 369 for (i = 0; i < ARRAY_SIZE(aes_algs); i++) {
370 if (aes_algs[i].version > ccpversion)
371 continue;
362 ret = ccp_register_aes_alg(head, &aes_algs[i]); 372 ret = ccp_register_aes_alg(head, &aes_algs[i]);
363 if (ret) 373 if (ret)
364 return ret; 374 return ret;
diff --git a/drivers/crypto/ccp/ccp-crypto-sha.c b/drivers/crypto/ccp/ccp-crypto-sha.c
index 8ef06fad8b14..b5ad72897dc2 100644
--- a/drivers/crypto/ccp/ccp-crypto-sha.c
+++ b/drivers/crypto/ccp/ccp-crypto-sha.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * AMD Cryptographic Coprocessor (CCP) SHA crypto API support 2 * AMD Cryptographic Coprocessor (CCP) SHA crypto API support
3 * 3 *
4 * Copyright (C) 2013 Advanced Micro Devices, Inc. 4 * Copyright (C) 2013,2016 Advanced Micro Devices, Inc.
5 * 5 *
6 * Author: Tom Lendacky <thomas.lendacky@amd.com> 6 * Author: Tom Lendacky <thomas.lendacky@amd.com>
7 * 7 *
@@ -341,6 +341,7 @@ static void ccp_hmac_sha_cra_exit(struct crypto_tfm *tfm)
341} 341}
342 342
343struct ccp_sha_def { 343struct ccp_sha_def {
344 unsigned int version;
344 const char *name; 345 const char *name;
345 const char *drv_name; 346 const char *drv_name;
346 enum ccp_sha_type type; 347 enum ccp_sha_type type;
@@ -350,6 +351,7 @@ struct ccp_sha_def {
350 351
351static struct ccp_sha_def sha_algs[] = { 352static struct ccp_sha_def sha_algs[] = {
352 { 353 {
354 .version = CCP_VERSION(3, 0),
353 .name = "sha1", 355 .name = "sha1",
354 .drv_name = "sha1-ccp", 356 .drv_name = "sha1-ccp",
355 .type = CCP_SHA_TYPE_1, 357 .type = CCP_SHA_TYPE_1,
@@ -357,6 +359,7 @@ static struct ccp_sha_def sha_algs[] = {
357 .block_size = SHA1_BLOCK_SIZE, 359 .block_size = SHA1_BLOCK_SIZE,
358 }, 360 },
359 { 361 {
362 .version = CCP_VERSION(3, 0),
360 .name = "sha224", 363 .name = "sha224",
361 .drv_name = "sha224-ccp", 364 .drv_name = "sha224-ccp",
362 .type = CCP_SHA_TYPE_224, 365 .type = CCP_SHA_TYPE_224,
@@ -364,6 +367,7 @@ static struct ccp_sha_def sha_algs[] = {
364 .block_size = SHA224_BLOCK_SIZE, 367 .block_size = SHA224_BLOCK_SIZE,
365 }, 368 },
366 { 369 {
370 .version = CCP_VERSION(3, 0),
367 .name = "sha256", 371 .name = "sha256",
368 .drv_name = "sha256-ccp", 372 .drv_name = "sha256-ccp",
369 .type = CCP_SHA_TYPE_256, 373 .type = CCP_SHA_TYPE_256,
@@ -480,8 +484,11 @@ static int ccp_register_sha_alg(struct list_head *head,
480int ccp_register_sha_algs(struct list_head *head) 484int ccp_register_sha_algs(struct list_head *head)
481{ 485{
482 int i, ret; 486 int i, ret;
487 unsigned int ccpversion = ccp_version();
483 488
484 for (i = 0; i < ARRAY_SIZE(sha_algs); i++) { 489 for (i = 0; i < ARRAY_SIZE(sha_algs); i++) {
490 if (sha_algs[i].version > ccpversion)
491 continue;
485 ret = ccp_register_sha_alg(head, &sha_algs[i]); 492 ret = ccp_register_sha_alg(head, &sha_algs[i]);
486 if (ret) 493 if (ret)
487 return ret; 494 return ret;
diff --git a/drivers/crypto/ccp/ccp-dev.c b/drivers/crypto/ccp/ccp-dev.c
index dd71e673a109..5348512da643 100644
--- a/drivers/crypto/ccp/ccp-dev.c
+++ b/drivers/crypto/ccp/ccp-dev.c
@@ -150,6 +150,29 @@ int ccp_present(void)
150EXPORT_SYMBOL_GPL(ccp_present); 150EXPORT_SYMBOL_GPL(ccp_present);
151 151
152/** 152/**
153 * ccp_version - get the version of the CCP device
154 *
155 * Returns the version from the first unit on the list;
156 * otherwise a zero if no CCP device is present
157 */
158unsigned int ccp_version(void)
159{
160 struct ccp_device *dp;
161 unsigned long flags;
162 int ret = 0;
163
164 read_lock_irqsave(&ccp_unit_lock, flags);
165 if (!list_empty(&ccp_units)) {
166 dp = list_first_entry(&ccp_units, struct ccp_device, entry);
167 ret = dp->vdata->version;
168 }
169 read_unlock_irqrestore(&ccp_unit_lock, flags);
170
171 return ret;
172}
173EXPORT_SYMBOL_GPL(ccp_version);
174
175/**
153 * ccp_enqueue_cmd - queue an operation for processing by the CCP 176 * ccp_enqueue_cmd - queue an operation for processing by the CCP
154 * 177 *
155 * @cmd: ccp_cmd struct to be processed 178 * @cmd: ccp_cmd struct to be processed
@@ -664,6 +687,10 @@ bool ccp_queues_suspended(struct ccp_device *ccp)
664} 687}
665#endif 688#endif
666 689
690struct ccp_vdata ccpv3 = {
691 .version = CCP_VERSION(3, 0),
692};
693
667static int __init ccp_mod_init(void) 694static int __init ccp_mod_init(void)
668{ 695{
669#ifdef CONFIG_X86 696#ifdef CONFIG_X86
diff --git a/drivers/crypto/ccp/ccp-dev.h b/drivers/crypto/ccp/ccp-dev.h
index 974dc055e0ab..90a8cc8c7d46 100644
--- a/drivers/crypto/ccp/ccp-dev.h
+++ b/drivers/crypto/ccp/ccp-dev.h
@@ -141,6 +141,13 @@
141#define CCP_ECC_RESULT_OFFSET 60 141#define CCP_ECC_RESULT_OFFSET 60
142#define CCP_ECC_RESULT_SUCCESS 0x0001 142#define CCP_ECC_RESULT_SUCCESS 0x0001
143 143
144/* Structure to hold CCP version-specific values */
145struct ccp_vdata {
146 unsigned int version;
147};
148
149extern struct ccp_vdata ccpv3;
150
144struct ccp_device; 151struct ccp_device;
145struct ccp_cmd; 152struct ccp_cmd;
146 153
@@ -187,6 +194,7 @@ struct ccp_cmd_queue {
187struct ccp_device { 194struct ccp_device {
188 struct list_head entry; 195 struct list_head entry;
189 196
197 struct ccp_vdata *vdata;
190 unsigned int ord; 198 unsigned int ord;
191 char name[MAX_CCP_NAME_LEN]; 199 char name[MAX_CCP_NAME_LEN];
192 char rngname[MAX_CCP_NAME_LEN]; 200 char rngname[MAX_CCP_NAME_LEN];
diff --git a/drivers/crypto/ccp/ccp-pci.c b/drivers/crypto/ccp/ccp-pci.c
index 668e5154beb3..d1a36af44012 100644
--- a/drivers/crypto/ccp/ccp-pci.c
+++ b/drivers/crypto/ccp/ccp-pci.c
@@ -180,6 +180,12 @@ static int ccp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
180 goto e_err; 180 goto e_err;
181 181
182 ccp->dev_specific = ccp_pci; 182 ccp->dev_specific = ccp_pci;
183 ccp->vdata = (struct ccp_vdata *)id->driver_data;
184 if (!ccp->vdata || !ccp->vdata->version) {
185 ret = -ENODEV;
186 dev_err(dev, "missing driver data\n");
187 goto e_err;
188 }
183 ccp->get_irq = ccp_get_irqs; 189 ccp->get_irq = ccp_get_irqs;
184 ccp->free_irq = ccp_free_irqs; 190 ccp->free_irq = ccp_free_irqs;
185 191
@@ -313,7 +319,7 @@ static int ccp_pci_resume(struct pci_dev *pdev)
313#endif 319#endif
314 320
315static const struct pci_device_id ccp_pci_table[] = { 321static const struct pci_device_id ccp_pci_table[] = {
316 { PCI_VDEVICE(AMD, 0x1537), }, 322 { PCI_VDEVICE(AMD, 0x1537), (kernel_ulong_t)&ccpv3 },
317 /* Last entry must be zero */ 323 /* Last entry must be zero */
318 { 0, } 324 { 0, }
319}; 325};
diff --git a/drivers/crypto/ccp/ccp-platform.c b/drivers/crypto/ccp/ccp-platform.c
index 4331318b57b2..6e1cf228c7c0 100644
--- a/drivers/crypto/ccp/ccp-platform.c
+++ b/drivers/crypto/ccp/ccp-platform.c
@@ -32,6 +32,33 @@ struct ccp_platform {
32 int coherent; 32 int coherent;
33}; 33};
34 34
35static const struct acpi_device_id ccp_acpi_match[];
36static const struct of_device_id ccp_of_match[];
37
38static struct ccp_vdata *ccp_get_of_version(struct platform_device *pdev)
39{
40#ifdef CONFIG_OF
41 const struct of_device_id *match;
42
43 match = of_match_node(ccp_of_match, pdev->dev.of_node);
44 if (match && match->data)
45 return (struct ccp_vdata *)match->data;
46#endif
47 return 0;
48}
49
50static struct ccp_vdata *ccp_get_acpi_version(struct platform_device *pdev)
51{
52#ifdef CONFIG_ACPI
53 const struct acpi_device_id *match;
54
55 match = acpi_match_device(ccp_acpi_match, &pdev->dev);
56 if (match && match->driver_data)
57 return (struct ccp_vdata *)match->driver_data;
58#endif
59 return 0;
60}
61
35static int ccp_get_irq(struct ccp_device *ccp) 62static int ccp_get_irq(struct ccp_device *ccp)
36{ 63{
37 struct device *dev = ccp->dev; 64 struct device *dev = ccp->dev;
@@ -106,6 +133,13 @@ static int ccp_platform_probe(struct platform_device *pdev)
106 goto e_err; 133 goto e_err;
107 134
108 ccp->dev_specific = ccp_platform; 135 ccp->dev_specific = ccp_platform;
136 ccp->vdata = pdev->dev.of_node ? ccp_get_of_version(pdev)
137 : ccp_get_acpi_version(pdev);
138 if (!ccp->vdata || !ccp->vdata->version) {
139 ret = -ENODEV;
140 dev_err(dev, "missing driver data\n");
141 goto e_err;
142 }
109 ccp->get_irq = ccp_get_irqs; 143 ccp->get_irq = ccp_get_irqs;
110 ccp->free_irq = ccp_free_irqs; 144 ccp->free_irq = ccp_free_irqs;
111 145
@@ -214,7 +248,7 @@ static int ccp_platform_resume(struct platform_device *pdev)
214 248
215#ifdef CONFIG_ACPI 249#ifdef CONFIG_ACPI
216static const struct acpi_device_id ccp_acpi_match[] = { 250static const struct acpi_device_id ccp_acpi_match[] = {
217 { "AMDI0C00", 0 }, 251 { "AMDI0C00", (kernel_ulong_t)&ccpv3 },
218 { }, 252 { },
219}; 253};
220MODULE_DEVICE_TABLE(acpi, ccp_acpi_match); 254MODULE_DEVICE_TABLE(acpi, ccp_acpi_match);
@@ -222,7 +256,8 @@ MODULE_DEVICE_TABLE(acpi, ccp_acpi_match);
222 256
223#ifdef CONFIG_OF 257#ifdef CONFIG_OF
224static const struct of_device_id ccp_of_match[] = { 258static const struct of_device_id ccp_of_match[] = {
225 { .compatible = "amd,ccp-seattle-v1a" }, 259 { .compatible = "amd,ccp-seattle-v1a",
260 .data = (const void *)&ccpv3 },
226 { }, 261 { },
227}; 262};
228MODULE_DEVICE_TABLE(of, ccp_of_match); 263MODULE_DEVICE_TABLE(of, ccp_of_match);
diff --git a/include/linux/ccp.h b/include/linux/ccp.h
index 7f437036baa4..915af3095b39 100644
--- a/include/linux/ccp.h
+++ b/include/linux/ccp.h
@@ -33,6 +33,18 @@ struct ccp_cmd;
33 */ 33 */
34int ccp_present(void); 34int ccp_present(void);
35 35
36#define CCP_VSIZE 16
37#define CCP_VMASK ((unsigned int)((1 << CCP_VSIZE) - 1))
38#define CCP_VERSION(v, r) ((unsigned int)((v << CCP_VSIZE) \
39 | (r & CCP_VMASK)))
40
41/**
42 * ccp_version - get the version of the CCP
43 *
44 * Returns a positive version number, or zero if no CCP
45 */
46unsigned int ccp_version(void);
47
36/** 48/**
37 * ccp_enqueue_cmd - queue an operation for processing by the CCP 49 * ccp_enqueue_cmd - queue an operation for processing by the CCP
38 * 50 *
@@ -65,6 +77,11 @@ static inline int ccp_present(void)
65 return -ENODEV; 77 return -ENODEV;
66} 78}
67 79
80static inline unsigned int ccp_version(void)
81{
82 return 0;
83}
84
68static inline int ccp_enqueue_cmd(struct ccp_cmd *cmd) 85static inline int ccp_enqueue_cmd(struct ccp_cmd *cmd)
69{ 86{
70 return -ENODEV; 87 return -ENODEV;