diff options
Diffstat (limited to 'drivers/crypto/ccp/ccp-dev.c')
| -rw-r--r-- | drivers/crypto/ccp/ccp-dev.c | 113 | 
1 files changed, 109 insertions, 4 deletions
diff --git a/drivers/crypto/ccp/ccp-dev.c b/drivers/crypto/ccp/ccp-dev.c index 87b9f2bfa623..cafa633aae10 100644 --- a/drivers/crypto/ccp/ccp-dev.c +++ b/drivers/crypto/ccp/ccp-dev.c @@ -4,6 +4,7 @@   * Copyright (C) 2013,2016 Advanced Micro Devices, Inc.   *   * Author: Tom Lendacky <[email protected]> + * Author: Gary R Hook <[email protected]>   *   * 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 @@ -39,6 +40,59 @@ struct ccp_tasklet_data {  	struct ccp_cmd *cmd;  }; +/* Human-readable error strings */ +char *ccp_error_codes[] = { +	"", +	"ERR 01: ILLEGAL_ENGINE", +	"ERR 02: ILLEGAL_KEY_ID", +	"ERR 03: ILLEGAL_FUNCTION_TYPE", +	"ERR 04: ILLEGAL_FUNCTION_MODE", +	"ERR 05: ILLEGAL_FUNCTION_ENCRYPT", +	"ERR 06: ILLEGAL_FUNCTION_SIZE", +	"ERR 07: Zlib_MISSING_INIT_EOM", +	"ERR 08: ILLEGAL_FUNCTION_RSVD", +	"ERR 09: ILLEGAL_BUFFER_LENGTH", +	"ERR 10: VLSB_FAULT", +	"ERR 11: ILLEGAL_MEM_ADDR", +	"ERR 12: ILLEGAL_MEM_SEL", +	"ERR 13: ILLEGAL_CONTEXT_ID", +	"ERR 14: ILLEGAL_KEY_ADDR", +	"ERR 15: 0xF Reserved", +	"ERR 16: Zlib_ILLEGAL_MULTI_QUEUE", +	"ERR 17: Zlib_ILLEGAL_JOBID_CHANGE", +	"ERR 18: CMD_TIMEOUT", +	"ERR 19: IDMA0_AXI_SLVERR", +	"ERR 20: IDMA0_AXI_DECERR", +	"ERR 21: 0x15 Reserved", +	"ERR 22: IDMA1_AXI_SLAVE_FAULT", +	"ERR 23: IDMA1_AIXI_DECERR", +	"ERR 24: 0x18 Reserved", +	"ERR 25: ZLIBVHB_AXI_SLVERR", +	"ERR 26: ZLIBVHB_AXI_DECERR", +	"ERR 27: 0x1B Reserved", +	"ERR 27: ZLIB_UNEXPECTED_EOM", +	"ERR 27: ZLIB_EXTRA_DATA", +	"ERR 30: ZLIB_BTYPE", +	"ERR 31: ZLIB_UNDEFINED_SYMBOL", +	"ERR 32: ZLIB_UNDEFINED_DISTANCE_S", +	"ERR 33: ZLIB_CODE_LENGTH_SYMBOL", +	"ERR 34: ZLIB _VHB_ILLEGAL_FETCH", +	"ERR 35: ZLIB_UNCOMPRESSED_LEN", +	"ERR 36: ZLIB_LIMIT_REACHED", +	"ERR 37: ZLIB_CHECKSUM_MISMATCH0", +	"ERR 38: ODMA0_AXI_SLVERR", +	"ERR 39: ODMA0_AXI_DECERR", +	"ERR 40: 0x28 Reserved", +	"ERR 41: ODMA1_AXI_SLVERR", +	"ERR 42: ODMA1_AXI_DECERR", +	"ERR 43: LSB_PARITY_ERR", +}; + +void ccp_log_error(struct ccp_device *d, int e) +{ +	dev_err(d->dev, "CCP error: %s (0x%x)\n", ccp_error_codes[e], e); +} +  /* List of CCPs, CCP count, read-write access lock, and access functions   *   * Lock structure: get ccp_unit_lock for reading whenever we need to @@ -58,7 +112,7 @@ static struct ccp_device *ccp_rr;  /* Ever-increasing value to produce unique unit numbers */  static atomic_t ccp_unit_ordinal; -unsigned int ccp_increment_unit_ordinal(void) +static unsigned int ccp_increment_unit_ordinal(void)  {  	return atomic_inc_return(&ccp_unit_ordinal);  } @@ -118,6 +172,29 @@ void ccp_del_device(struct ccp_device *ccp)  	write_unlock_irqrestore(&ccp_unit_lock, flags);  } + + +int ccp_register_rng(struct ccp_device *ccp) +{ +	int ret = 0; + +	dev_dbg(ccp->dev, "Registering RNG...\n"); +	/* Register an RNG */ +	ccp->hwrng.name = ccp->rngname; +	ccp->hwrng.read = ccp_trng_read; +	ret = hwrng_register(&ccp->hwrng); +	if (ret) +		dev_err(ccp->dev, "error registering hwrng (%d)\n", ret); + +	return ret; +} + +void ccp_unregister_rng(struct ccp_device *ccp) +{ +	if (ccp->hwrng.name) +		hwrng_unregister(&ccp->hwrng); +} +  static struct ccp_device *ccp_get_device(void)  {  	unsigned long flags; @@ -397,9 +474,9 @@ struct ccp_device *ccp_alloc_struct(struct device *dev)  	spin_lock_init(&ccp->cmd_lock);  	mutex_init(&ccp->req_mutex); -	mutex_init(&ccp->ksb_mutex); -	ccp->ksb_count = KSB_COUNT; -	ccp->ksb_start = 0; +	mutex_init(&ccp->sb_mutex); +	ccp->sb_count = KSB_COUNT; +	ccp->sb_start = 0;  	ccp->ord = ccp_increment_unit_ordinal();  	snprintf(ccp->name, MAX_CCP_NAME_LEN, "ccp-%u", ccp->ord); @@ -408,6 +485,34 @@ struct ccp_device *ccp_alloc_struct(struct device *dev)  	return ccp;  } +int ccp_trng_read(struct hwrng *rng, void *data, size_t max, bool wait) +{ +	struct ccp_device *ccp = container_of(rng, struct ccp_device, hwrng); +	u32 trng_value; +	int len = min_t(int, sizeof(trng_value), max); + +	/* Locking is provided by the caller so we can update device +	 * hwrng-related fields safely +	 */ +	trng_value = ioread32(ccp->io_regs + TRNG_OUT_REG); +	if (!trng_value) { +		/* Zero is returned if not data is available or if a +		 * bad-entropy error is present. Assume an error if +		 * we exceed TRNG_RETRIES reads of zero. +		 */ +		if (ccp->hwrng_retries++ > TRNG_RETRIES) +			return -EIO; + +		return 0; +	} + +	/* Reset the counter and save the rng value */ +	ccp->hwrng_retries = 0; +	memcpy(data, &trng_value, len); + +	return len; +} +  #ifdef CONFIG_PM  bool ccp_queues_suspended(struct ccp_device *ccp)  {  |