do {
virtqueue_disable_cb(vq); while ((vc_req = virtqueue_get_buf(vq, &len)) != NULL) { if (vc_req->alg_cb)
vc_req->alg_cb(vc_req, len);
}
} while (!virtqueue_enable_cb(vq));
}
staticint 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 = kcalloc(total_vqs, sizeof(*vqs), GFP_KERNEL); if (!vqs) goto err_vq;
vqs_info = kcalloc(total_vqs, sizeof(*vqs_info), GFP_KERNEL); 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 */ for (i = 0; i < vi->max_data_queues; i++) {
vqs_info[i].callback = virtcrypto_dataq_callback;
snprintf(vi->data_vq[i].name, sizeof(vi->data_vq[i].name), "dataq.%d", i);
vqs_info[i].name = vi->data_vq[i].name;
}
ret = virtio_find_vqs(vi->vdev, total_vqs, vqs, vqs_info, NULL); if (ret) goto err_find;
vi->ctrl_vq = vqs[total_vqs - 1];
for (i = 0; i < vi->max_data_queues; i++) {
spin_lock_init(&vi->data_vq[i].lock);
vi->data_vq[i].vq = vqs[i]; /* Initialize crypto engine */
vi->data_vq[i].engine = crypto_engine_alloc_init_and_set(dev, true, true,
virtqueue_get_vring_size(vqs[i])); if (!vi->data_vq[i].engine) {
ret = -ENOMEM; goto err_engine;
}
tasklet_init(&vi->data_vq[i].done_task, virtcrypto_done_task,
(unsignedlong)&vi->data_vq[i]);
}
staticvoid virtcrypto_clean_affinity(struct virtio_crypto *vi, long hcpu)
{ int i;
if (vi->affinity_hint_set) { for (i = 0; i < vi->max_data_queues; i++)
virtqueue_set_affinity(vi->data_vq[i].vq, NULL);
vi->affinity_hint_set = false;
}
}
staticvoid virtcrypto_set_affinity(struct virtio_crypto *vcrypto)
{ int i = 0; int cpu;
/* * In single queue mode, we don't set the cpu affinity.
*/ if (vcrypto->curr_queue == 1 || vcrypto->max_data_queues == 1) {
virtcrypto_clean_affinity(vcrypto, -1); return;
}
/* * In multiqueue mode, we let the queue to be private to one cpu * by setting the affinity hint to eliminate the contention. * * TODO: adds cpu hotplug support by register cpu notifier. *
*/
for_each_online_cpu(cpu) {
virtqueue_set_affinity(vcrypto->data_vq[i].vq, cpumask_of(cpu)); if (++i >= vcrypto->max_data_queues) break;
}
/* * Unknown status bits would be a host error and the driver * should consider the device to be broken.
*/ if (status & (~VIRTIO_CRYPTO_S_HW_READY)) {
dev_warn(&vcrypto->vdev->dev, "Unknown status bits: 0x%x\n", status);
if (vcrypto->status & VIRTIO_CRYPTO_S_HW_READY) {
err = virtcrypto_dev_start(vcrypto); if (err) {
dev_err(&vcrypto->vdev->dev, "Failed to start virtio crypto device.\n");
return -EPERM;
}
dev_info(&vcrypto->vdev->dev, "Accelerator device is ready\n");
} else {
virtcrypto_dev_stop(vcrypto);
dev_info(&vcrypto->vdev->dev, "Accelerator is not ready\n");
}
return 0;
}
staticint virtcrypto_start_crypto_engines(struct virtio_crypto *vcrypto)
{
int32_t i; int ret;
for (i = 0; i < vcrypto->max_data_queues; i++) { if (vcrypto->data_vq[i].engine) {
ret = crypto_engine_start(vcrypto->data_vq[i].engine); if (ret) goto err;
}
}
return 0;
err: while (--i >= 0) if (vcrypto->data_vq[i].engine)
crypto_engine_exit(vcrypto->data_vq[i].engine);
if (num_possible_nodes() > 1 && dev_to_node(&vdev->dev) < 0) { /* * If the accelerator is connected to a node with no memory * there is no point in using the accelerator since the remote * memory transaction will be very slow.
*/
dev_err(&vdev->dev, "Invalid NUMA configuration.\n"); return -EINVAL;
}
vcrypto = kzalloc_node(sizeof(*vcrypto), GFP_KERNEL,
dev_to_node(&vdev->dev)); if (!vcrypto) return -ENOMEM;
flush_work(&vcrypto->config_work); if (virtcrypto_dev_started(vcrypto))
virtcrypto_dev_stop(vcrypto); for (i = 0; i < vcrypto->max_data_queues; i++)
tasklet_kill(&vcrypto->data_vq[i].done_task);
virtio_reset_device(vdev);
virtcrypto_free_unused_reqs(vcrypto);
virtcrypto_clear_crypto_engines(vcrypto);
virtcrypto_del_vqs(vcrypto);
virtcrypto_devmgr_rm_dev(vcrypto);
kfree(vcrypto);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.