/* * Give out the data that's requested from the buffer that we have * queued up. */ ssize_t fill_readbuf(struct crypto_device *crdev, char *out_buf, size_t out_count) { struct crypto_vq_buffer *buf; debug("Entering\n"); if (!out_count || !device_has_data(crdev)) return 0; buf = crdev->inbuf; out_count = min(out_count, buf->len - buf->offset); memcpy(out_buf, buf->buf + buf->offset, out_count); buf->offset += out_count; if (buf->offset == buf->len) { /* * FIXME: We're done using all the data in this buffer. * Re-queue so that the Host can send us more data. */ crdev->inbuf = NULL; if (add_inbuf(crdev->ivq, buf) < 0) printk(KERN_WARNING "failed add_buf\n"); } debug("Leaving\n"); /* Return the number of bytes actually copied */ return out_count; }
/* * Host sent us a control message. * Called in interrupt context! */ static void control_in_intr(struct virtqueue *vq) { struct crypto_device *crdev; struct crypto_vq_buffer *buf; unsigned int len; debug("Entering\n"); crdev = vq->vdev->priv; while ((buf = virtqueue_get_buf(vq, &len))) { buf->len = len; buf->offset = 0; handle_control_message(crdev, buf); spin_lock_irq(&crdev->c_lock); if (add_inbuf(crdev->c_ivq, buf) < 0) { printk(KERN_WARNING "Error adding buffer to queue\n"); free_buf(buf); } spin_unlock_irq(&crdev->c_lock); } debug("Leaving\n"); }
/* * Fill a virtqueue with buffers so Host can send us data. */ unsigned int fill_queue(struct virtqueue *vq, spinlock_t *lock) { struct crypto_vq_buffer *buf; unsigned int nr_added_bufs; int ret; debug("Entering\n"); nr_added_bufs = 0; do { buf = alloc_buf(PAGE_SIZE); if (!buf) break; ret = add_inbuf(vq, buf); if (ret < 0) { free_buf(buf); break; } nr_added_bufs++; } while (ret > 0); debug("Leaving\n"); return nr_added_bufs; }