drivers/crypto/virtio/virtio_crypto_core.c

Source file repositories/reference/linux-study-clean/drivers/crypto/virtio/virtio_crypto_core.c

File Facts

System
Linux kernel
Corpus path
drivers/crypto/virtio/virtio_crypto_core.c
Extension
.c
Size
14579 bytes
Lines
596
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

while ((vc_ctrl_req = virtqueue_get_buf(vq, &len)) != NULL) {
			spin_unlock_irqrestore(&vcrypto->ctrl_lock, flags);
			virtio_crypto_ctrlq_callback(vc_ctrl_req);
			spin_lock_irqsave(&vcrypto->ctrl_lock, flags);
		}
	} while (!virtqueue_enable_cb(vq));
	spin_unlock_irqrestore(&vcrypto->ctrl_lock, flags);
}

int virtio_crypto_ctrl_vq_request(struct virtio_crypto *vcrypto, struct scatterlist *sgs[],
		unsigned int out_sgs, unsigned int in_sgs,
		struct virtio_crypto_ctrl_request *vc_ctrl_req)
{
	int err;
	unsigned long flags;

	init_completion(&vc_ctrl_req->compl);

	spin_lock_irqsave(&vcrypto->ctrl_lock, flags);
	err = virtqueue_add_sgs(vcrypto->ctrl_vq, sgs, out_sgs, in_sgs, vc_ctrl_req, GFP_ATOMIC);
	if (err < 0) {
		spin_unlock_irqrestore(&vcrypto->ctrl_lock, flags);
		return err;
	}

	virtqueue_kick(vcrypto->ctrl_vq);
	spin_unlock_irqrestore(&vcrypto->ctrl_lock, flags);

	wait_for_completion(&vc_ctrl_req->compl);

	return 0;
}

static void virtcrypto_done_work(struct work_struct *work)
{
	struct data_queue *data_vq = from_work(data_vq, work, done_work);
	struct virtqueue *vq = data_vq->vq;
	struct virtio_crypto_request *vc_req;
	unsigned long flags;
	unsigned int len;

	spin_lock_irqsave(&data_vq->lock, flags);
	do {
		virtqueue_disable_cb(vq);
		while ((vc_req = virtqueue_get_buf(vq, &len)) != NULL) {
			spin_unlock_irqrestore(&data_vq->lock, flags);
			if (vc_req->alg_cb)
				vc_req->alg_cb(vc_req, len);
			spin_lock_irqsave(&data_vq->lock, flags);
		}
	} while (!virtqueue_enable_cb(vq));
	spin_unlock_irqrestore(&data_vq->lock, flags);
}

static void virtcrypto_dataq_callback(struct virtqueue *vq)
{
	struct virtio_crypto *vcrypto = vq->vdev->priv;
	struct data_queue *dq = &vcrypto->data_vq[vq->index];

	queue_work(system_bh_wq, &dq->done_work);
}

static int virtcrypto_find_vqs(struct virtio_crypto *vi)
{
	struct virtqueue_info *vqs_info;
	struct virtqueue **vqs;
	int ret = -ENOMEM;
	int i, total_vqs;
	struct device *dev = &vi->vdev->dev;

	/*
	 * We expect 1 data virtqueue, followed by
	 * possible N-1 data queues used in multiqueue mode,
	 * followed by control vq.
	 */
	total_vqs = vi->max_data_queues + 1;

	/* Allocate space for find_vqs parameters */
	vqs = kzalloc_objs(*vqs, total_vqs);
	if (!vqs)
		goto err_vq;
	vqs_info = kzalloc_objs(*vqs_info, total_vqs);
	if (!vqs_info)
		goto err_vqs_info;

	/* Parameters for control virtqueue */
	vqs_info[total_vqs - 1].callback = virtcrypto_ctrlq_callback;
	vqs_info[total_vqs - 1].name = "controlq";

	/* Allocate/initialize parameters for data virtqueues */

Annotation

Implementation Notes