Ejemplo n.º 1
0
static int sahara_sha_hw_links_create(struct sahara_dev *dev,
				       struct sahara_sha_reqctx *rctx,
				       int start)
{
	struct scatterlist *sg;
	unsigned int i;
	int ret;

	dev->in_sg = rctx->in_sg;

	dev->nb_in_sg = sahara_sg_length(dev->in_sg, rctx->total);
	if ((dev->nb_in_sg) > SAHARA_MAX_HW_LINK) {
		dev_err(dev->device, "not enough hw links (%d)\n",
			dev->nb_in_sg + dev->nb_out_sg);
		return -EINVAL;
	}

	if (rctx->in_sg_chained) {
		i = start;
		sg = dev->in_sg;
		while (sg) {
			ret = dma_map_sg(dev->device, sg, 1,
					 DMA_TO_DEVICE);
			if (!ret)
				return -EFAULT;

			dev->hw_link[i]->len = sg->length;
			dev->hw_link[i]->p = sg->dma_address;
			dev->hw_link[i]->next = dev->hw_phys_link[i + 1];
			sg = sg_next(sg);
			i += 1;
		}
		dev->hw_link[i-1]->next = 0;
	} else {
		sg = dev->in_sg;
		ret = dma_map_sg(dev->device, dev->in_sg, dev->nb_in_sg,
				 DMA_TO_DEVICE);
		if (!ret)
			return -EFAULT;

		for (i = start; i < dev->nb_in_sg + start; i++) {
			dev->hw_link[i]->len = sg->length;
			dev->hw_link[i]->p = sg->dma_address;
			if (i == (dev->nb_in_sg + start - 1)) {
				dev->hw_link[i]->next = 0;
			} else {
				dev->hw_link[i]->next = dev->hw_phys_link[i + 1];
				sg = sg_next(sg);
			}
		}
	}

	return i;
}
Ejemplo n.º 2
0
static int sahara_hw_descriptor_create(struct sahara_dev *dev)
{
	struct sahara_ctx *ctx = dev->ctx;
	struct scatterlist *sg;
	int ret;
	int i, j;

	/* Copy new key if necessary */
	if (ctx->flags & FLAGS_NEW_KEY) {
		memcpy(dev->key_base, ctx->key, ctx->keylen);
		ctx->flags &= ~FLAGS_NEW_KEY;

		if (dev->flags & FLAGS_CBC) {
			dev->hw_desc[0]->len1 = AES_BLOCK_SIZE;
			dev->hw_desc[0]->p1 = dev->iv_phys_base;
		} else {
			dev->hw_desc[0]->len1 = 0;
			dev->hw_desc[0]->p1 = 0;
		}
		dev->hw_desc[0]->len2 = ctx->keylen;
		dev->hw_desc[0]->p2 = dev->key_phys_base;
		dev->hw_desc[0]->next = dev->hw_phys_desc[1];
	}
	dev->hw_desc[0]->hdr = sahara_aes_key_hdr(dev);

	dev->nb_in_sg = sahara_sg_length(dev->in_sg, dev->total);
	dev->nb_out_sg = sahara_sg_length(dev->out_sg, dev->total);
	if ((dev->nb_in_sg + dev->nb_out_sg) > SAHARA_MAX_HW_LINK) {
		dev_err(dev->device, "not enough hw links (%d)\n",
			dev->nb_in_sg + dev->nb_out_sg);
		return -EINVAL;
	}

	ret = dma_map_sg(dev->device, dev->in_sg, dev->nb_in_sg,
			 DMA_TO_DEVICE);
	if (ret != dev->nb_in_sg) {
		dev_err(dev->device, "couldn't map in sg\n");
		goto unmap_in;
	}
	ret = dma_map_sg(dev->device, dev->out_sg, dev->nb_out_sg,
			 DMA_FROM_DEVICE);
	if (ret != dev->nb_out_sg) {
		dev_err(dev->device, "couldn't map out sg\n");
		goto unmap_out;
	}

	/* Create input links */
	dev->hw_desc[1]->p1 = dev->hw_phys_link[0];
	sg = dev->in_sg;
	for (i = 0; i < dev->nb_in_sg; i++) {
		dev->hw_link[i]->len = sg->length;
		dev->hw_link[i]->p = sg->dma_address;
		if (i == (dev->nb_in_sg - 1)) {
			dev->hw_link[i]->next = 0;
		} else {
			dev->hw_link[i]->next = dev->hw_phys_link[i + 1];
			sg = sg_next(sg);
		}
	}

	/* Create output links */
	dev->hw_desc[1]->p2 = dev->hw_phys_link[i];
	sg = dev->out_sg;
	for (j = i; j < dev->nb_out_sg + i; j++) {
		dev->hw_link[j]->len = sg->length;
		dev->hw_link[j]->p = sg->dma_address;
		if (j == (dev->nb_out_sg + i - 1)) {
			dev->hw_link[j]->next = 0;
		} else {
			dev->hw_link[j]->next = dev->hw_phys_link[j + 1];
			sg = sg_next(sg);
		}
	}

	/* Fill remaining fields of hw_desc[1] */
	dev->hw_desc[1]->hdr = sahara_aes_data_link_hdr(dev);
	dev->hw_desc[1]->len1 = dev->total;
	dev->hw_desc[1]->len2 = dev->total;
	dev->hw_desc[1]->next = 0;

	sahara_dump_descriptors(dev);
	sahara_dump_links(dev);

	/* Start processing descriptor chain. */
	mod_timer(&dev->watchdog,
		  jiffies + msecs_to_jiffies(SAHARA_TIMEOUT_MS));
	sahara_write(dev, dev->hw_phys_desc[0], SAHARA_REG_DAR);

	return 0;

unmap_out:
	dma_unmap_sg(dev->device, dev->out_sg, dev->nb_out_sg,
		DMA_TO_DEVICE);
unmap_in:
	dma_unmap_sg(dev->device, dev->in_sg, dev->nb_in_sg,
		DMA_FROM_DEVICE);

	return -EINVAL;
}