Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Gary R Hook and committed by
Herbert Xu
c7019c4d 553d2374

+115 -5
+11 -1
drivers/crypto/ccp/ccp-crypto-aes.c
··· 1 1 /* 2 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 6 * Author: Tom Lendacky <thomas.lendacky@amd.com> 7 7 * ··· 259 259 260 260 struct ccp_aes_def { 261 261 enum ccp_aes_mode mode; 262 + unsigned int version; 262 263 const char *name; 263 264 const char *driver_name; 264 265 unsigned int blocksize; ··· 270 269 static struct ccp_aes_def aes_algs[] = { 271 270 { 272 271 .mode = CCP_AES_MODE_ECB, 272 + .version = CCP_VERSION(3, 0), 273 273 .name = "ecb(aes)", 274 274 .driver_name = "ecb-aes-ccp", 275 275 .blocksize = AES_BLOCK_SIZE, ··· 279 277 }, 280 278 { 281 279 .mode = CCP_AES_MODE_CBC, 280 + .version = CCP_VERSION(3, 0), 282 281 .name = "cbc(aes)", 283 282 .driver_name = "cbc-aes-ccp", 284 283 .blocksize = AES_BLOCK_SIZE, ··· 288 285 }, 289 286 { 290 287 .mode = CCP_AES_MODE_CFB, 288 + .version = CCP_VERSION(3, 0), 291 289 .name = "cfb(aes)", 292 290 .driver_name = "cfb-aes-ccp", 293 291 .blocksize = AES_BLOCK_SIZE, ··· 297 293 }, 298 294 { 299 295 .mode = CCP_AES_MODE_OFB, 296 + .version = CCP_VERSION(3, 0), 300 297 .name = "ofb(aes)", 301 298 .driver_name = "ofb-aes-ccp", 302 299 .blocksize = 1, ··· 306 301 }, 307 302 { 308 303 .mode = CCP_AES_MODE_CTR, 304 + .version = CCP_VERSION(3, 0), 309 305 .name = "ctr(aes)", 310 306 .driver_name = "ctr-aes-ccp", 311 307 .blocksize = 1, ··· 315 309 }, 316 310 { 317 311 .mode = CCP_AES_MODE_CTR, 312 + .version = CCP_VERSION(3, 0), 318 313 .name = "rfc3686(ctr(aes))", 319 314 .driver_name = "rfc3686-ctr-aes-ccp", 320 315 .blocksize = 1, ··· 364 357 int ccp_register_aes_algs(struct list_head *head) 365 358 { 366 359 int i, ret; 360 + unsigned int ccpversion = ccp_version(); 367 361 368 362 for (i = 0; i < ARRAY_SIZE(aes_algs); i++) { 363 + if (aes_algs[i].version > ccpversion) 364 + continue; 369 365 ret = ccp_register_aes_alg(head, &aes_algs[i]); 370 366 if (ret) 371 367 return ret;
+8 -1
drivers/crypto/ccp/ccp-crypto-sha.c
··· 1 1 /* 2 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 6 * Author: Tom Lendacky <thomas.lendacky@amd.com> 7 7 * ··· 341 341 } 342 342 343 343 struct ccp_sha_def { 344 + unsigned int version; 344 345 const char *name; 345 346 const char *drv_name; 346 347 enum ccp_sha_type type; ··· 351 350 352 351 static struct ccp_sha_def sha_algs[] = { 353 352 { 353 + .version = CCP_VERSION(3, 0), 354 354 .name = "sha1", 355 355 .drv_name = "sha1-ccp", 356 356 .type = CCP_SHA_TYPE_1, ··· 359 357 .block_size = SHA1_BLOCK_SIZE, 360 358 }, 361 359 { 360 + .version = CCP_VERSION(3, 0), 362 361 .name = "sha224", 363 362 .drv_name = "sha224-ccp", 364 363 .type = CCP_SHA_TYPE_224, ··· 367 364 .block_size = SHA224_BLOCK_SIZE, 368 365 }, 369 366 { 367 + .version = CCP_VERSION(3, 0), 370 368 .name = "sha256", 371 369 .drv_name = "sha256-ccp", 372 370 .type = CCP_SHA_TYPE_256, ··· 484 480 int ccp_register_sha_algs(struct list_head *head) 485 481 { 486 482 int i, ret; 483 + unsigned int ccpversion = ccp_version(); 487 484 488 485 for (i = 0; i < ARRAY_SIZE(sha_algs); i++) { 486 + if (sha_algs[i].version > ccpversion) 487 + continue; 489 488 ret = ccp_register_sha_alg(head, &sha_algs[i]); 490 489 if (ret) 491 490 return ret;
+27
drivers/crypto/ccp/ccp-dev.c
··· 150 150 EXPORT_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 + */ 158 + unsigned 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 + } 173 + EXPORT_SYMBOL_GPL(ccp_version); 174 + 175 + /** 153 176 * ccp_enqueue_cmd - queue an operation for processing by the CCP 154 177 * 155 178 * @cmd: ccp_cmd struct to be processed ··· 686 663 return ccp->cmd_q_count == suspended; 687 664 } 688 665 #endif 666 + 667 + struct ccp_vdata ccpv3 = { 668 + .version = CCP_VERSION(3, 0), 669 + }; 689 670 690 671 static int __init ccp_mod_init(void) 691 672 {
+8
drivers/crypto/ccp/ccp-dev.h
··· 141 141 #define CCP_ECC_RESULT_OFFSET 60 142 142 #define CCP_ECC_RESULT_SUCCESS 0x0001 143 143 144 + /* Structure to hold CCP version-specific values */ 145 + struct ccp_vdata { 146 + unsigned int version; 147 + }; 148 + 149 + extern struct ccp_vdata ccpv3; 150 + 144 151 struct ccp_device; 145 152 struct ccp_cmd; 146 153 ··· 194 187 struct ccp_device { 195 188 struct list_head entry; 196 189 190 + struct ccp_vdata *vdata; 197 191 unsigned int ord; 198 192 char name[MAX_CCP_NAME_LEN]; 199 193 char rngname[MAX_CCP_NAME_LEN];
+7 -1
drivers/crypto/ccp/ccp-pci.c
··· 180 180 goto e_err; 181 181 182 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 189 ccp->get_irq = ccp_get_irqs; 184 190 ccp->free_irq = ccp_free_irqs; 185 191 ··· 319 313 #endif 320 314 321 315 static const struct pci_device_id ccp_pci_table[] = { 322 - { PCI_VDEVICE(AMD, 0x1537), }, 316 + { PCI_VDEVICE(AMD, 0x1537), (kernel_ulong_t)&ccpv3 }, 323 317 /* Last entry must be zero */ 324 318 { 0, } 325 319 };
+37 -2
drivers/crypto/ccp/ccp-platform.c
··· 32 32 int coherent; 33 33 }; 34 34 35 + static const struct acpi_device_id ccp_acpi_match[]; 36 + static const struct of_device_id ccp_of_match[]; 37 + 38 + static 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 + 50 + static 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 + 35 62 static int ccp_get_irq(struct ccp_device *ccp) 36 63 { 37 64 struct device *dev = ccp->dev; ··· 133 106 goto e_err; 134 107 135 108 ccp->dev_specific = ccp_platform; 109 + ccp->vdata = pdev->dev.of_node ? ccp_get_of_version(pdev) 110 + : ccp_get_acpi_version(pdev); 111 + if (!ccp->vdata || !ccp->vdata->version) { 112 + ret = -ENODEV; 113 + dev_err(dev, "missing driver data\n"); 114 + goto e_err; 115 + } 136 116 ccp->get_irq = ccp_get_irqs; 137 117 ccp->free_irq = ccp_free_irqs; 138 118 ··· 248 214 249 215 #ifdef CONFIG_ACPI 250 216 static const struct acpi_device_id ccp_acpi_match[] = { 251 - { "AMDI0C00", 0 }, 217 + { "AMDI0C00", (kernel_ulong_t)&ccpv3 }, 252 218 { }, 253 219 }; 254 220 MODULE_DEVICE_TABLE(acpi, ccp_acpi_match); ··· 256 222 257 223 #ifdef CONFIG_OF 258 224 static const struct of_device_id ccp_of_match[] = { 259 - { .compatible = "amd,ccp-seattle-v1a" }, 225 + { .compatible = "amd,ccp-seattle-v1a", 226 + .data = (const void *)&ccpv3 }, 260 227 { }, 261 228 }; 262 229 MODULE_DEVICE_TABLE(of, ccp_of_match);
+17
include/linux/ccp.h
··· 33 33 */ 34 34 int 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 + */ 46 + unsigned int ccp_version(void); 47 + 36 48 /** 37 49 * ccp_enqueue_cmd - queue an operation for processing by the CCP 38 50 * ··· 75 63 static inline int ccp_present(void) 76 64 { 77 65 return -ENODEV; 66 + } 67 + 68 + static inline unsigned int ccp_version(void) 69 + { 70 + return 0; 78 71 } 79 72 80 73 static inline int ccp_enqueue_cmd(struct ccp_cmd *cmd)