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

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

File Facts

System
Linux kernel
Corpus path
drivers/crypto/allwinner/sun4i-ss/sun4i-ss-hash.c
Extension
.c
Size
14285 bytes
Lines
546
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 (end > areq->nbytes || areq->nbytes - end > 63) {
			dev_err(ss->dev, "ERROR: Bound error %u %u\n",
				end, areq->nbytes);
			err = -EINVAL;
			goto release_ss;
		}
	} else {
		/* Since we have the flag final, we can go up to modulo 4 */
		if (areq->nbytes < 4)
			end = 0;
		else
			end = ((areq->nbytes + op->len) / 4) * 4 - op->len;
	}

	/* TODO if SGlen % 4 and !op->len then DMA */
	i = 1;
	while (in_sg && i == 1) {
		if (in_sg->length % 4)
			i = 0;
		in_sg = sg_next(in_sg);
	}
	if (i == 1 && !op->len && areq->nbytes)
		dev_dbg(ss->dev, "We can DMA\n");

	i = 0;
	sg_miter_start(&mi, areq->src, sg_nents(areq->src),
		       SG_MITER_FROM_SG | SG_MITER_ATOMIC);
	sg_miter_next(&mi);
	in_i = 0;

	do {
		/*
		 * we need to linearize in two case:
		 * - the buffer is already used
		 * - the SG does not have enough byte remaining ( < 4)
		 */
		if (op->len || (mi.length - in_i) < 4) {
			/*
			 * if we have entered here we have two reason to stop
			 * - the buffer is full
			 * - reach the end
			 */
			while (op->len < 64 && i < end) {
				/* how many bytes we can read from current SG */
				in_r = min(end - i, 64 - op->len);
				in_r = min_t(size_t, mi.length - in_i, in_r);
				memcpy(op->buf + op->len, mi.addr + in_i, in_r);
				op->len += in_r;
				i += in_r;
				in_i += in_r;
				if (in_i == mi.length) {
					sg_miter_next(&mi);
					in_i = 0;
				}
			}
			if (op->len > 3 && !(op->len % 4)) {
				/* write buf to the device */
				writesl(ss->base + SS_RXFIFO, op->buf,
					op->len / 4);
				op->byte_count += op->len;
				op->len = 0;
			}
		}
		if (mi.length - in_i > 3 && i < end) {
			/* how many bytes we can read from current SG */
			in_r = min_t(size_t, mi.length - in_i, areq->nbytes - i);
			in_r = min_t(size_t, ((mi.length - in_i) / 4) * 4, in_r);
			/* how many bytes we can write in the device*/
			todo = min3((u32)(end - i) / 4, rx_cnt, (u32)in_r / 4);
			writesl(ss->base + SS_RXFIFO, mi.addr + in_i, todo);
			op->byte_count += todo * 4;
			i += todo * 4;
			in_i += todo * 4;
			rx_cnt -= todo;
			if (!rx_cnt) {
				spaces = readl(ss->base + SS_FCSR);
				rx_cnt = SS_RXFIFO_SPACES(spaces);
			}
			if (in_i == mi.length) {
				sg_miter_next(&mi);
				in_i = 0;
			}
		}
	} while (i < end);

	/*
	 * Now we have written to the device all that we can,
	 * store the remaining bytes in op->buf
	 */
	if ((areq->nbytes - i) < 64) {

Annotation

Implementation Notes