drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c

Source file repositories/reference/linux-study-clean/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c

File Facts

System
Linux kernel
Corpus path
drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c
Extension
.c
Size
18712 bytes
Lines
706
Domain
Driver Families
Bucket
drivers/crypto
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (i > 0) {
			v |= BIT(17);
			writel(rctx->t_dst[i - 1].addr, ss->base + SS_KEY_ADR_REG);
			writel(rctx->t_dst[i - 1].addr, ss->base + SS_IV_ADR_REG);
		}

		dev_dbg(ss->dev,
			"Processing SG %d on flow %d %s ctl=%x %d to %d method=%x src=%x dst=%x\n",
			i, flow, name, v,
			rctx->t_src[i].len, rctx->t_dst[i].len,
			rctx->method, rctx->t_src[i].addr, rctx->t_dst[i].addr);

		writel(rctx->t_src[i].addr, ss->base + SS_SRC_ADR_REG);
		writel(rctx->t_dst[i].addr, ss->base + SS_DST_ADR_REG);
		writel(rctx->t_src[i].len, ss->base + SS_LEN_ADR_REG);
		writel(BIT(0) | BIT(1), ss->base + SS_INT_CTL_REG);

		reinit_completion(&ss->flows[flow].complete);
		ss->flows[flow].status = 0;
		wmb();

		writel(v, ss->base + SS_CTL_REG);
		mutex_unlock(&ss->mlock);
		wait_for_completion_interruptible_timeout(&ss->flows[flow].complete,
							  msecs_to_jiffies(2000));
		if (ss->flows[flow].status == 0) {
			dev_err(ss->dev, "DMA timeout for %s\n", name);
			return -EFAULT;
		}
	}

	return 0;
}

static bool sun8i_ss_hash_need_fallback(struct ahash_request *areq)
{
	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
	struct ahash_alg *alg = crypto_ahash_alg(tfm);
	struct sun8i_ss_alg_template *algt;
	struct scatterlist *sg;

	algt = container_of(alg, struct sun8i_ss_alg_template, alg.hash.base);

	if (areq->nbytes == 0) {
		algt->stat_fb_len++;
		return true;
	}

	if (areq->nbytes >= MAX_PAD_SIZE - 64) {
		algt->stat_fb_len++;
		return true;
	}

	/* we need to reserve one SG for the padding one */
	if (sg_nents(areq->src) > MAX_SG - 1) {
		algt->stat_fb_sgnum++;
		return true;
	}

	sg = areq->src;
	while (sg) {
		/* SS can operate hash only on full block size
		 * since SS support only MD5,sha1,sha224 and sha256, blocksize
		 * is always 64
		 */
		/* Only the last block could be bounced to the pad buffer */
		if (sg->length % 64 && sg_next(sg)) {
			algt->stat_fb_sglen++;
			return true;
		}
		if (!IS_ALIGNED(sg->offset, sizeof(u32))) {
			algt->stat_fb_align++;
			return true;
		}
		if (sg->length % 4) {
			algt->stat_fb_sglen++;
			return true;
		}
		sg = sg_next(sg);
	}
	return false;
}

int sun8i_ss_hash_digest(struct ahash_request *areq)
{
	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
	struct sun8i_ss_hash_reqctx *rctx = ahash_request_ctx(areq);
	struct ahash_alg *alg = crypto_ahash_alg(tfm);
	struct sun8i_ss_alg_template *algt;
	struct sun8i_ss_dev *ss;

Annotation

Implementation Notes