cregit-Linux how code gets into the kernel

Release 4.7 drivers/char/hw_random/virtio-rng.c

/*
 * Randomness driver for virtio
 *  Copyright (C) 2007, 2008 Rusty Russell IBM Corporation
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 */

#include <linux/err.h>
#include <linux/hw_random.h>
#include <linux/scatterlist.h>
#include <linux/spinlock.h>
#include <linux/virtio.h>
#include <linux/virtio_rng.h>
#include <linux/module.h>

static DEFINE_IDA(rng_index_ida);


struct virtrng_info {
	
struct hwrng hwrng;
	
struct virtqueue *vq;
	
struct completion have_data;
	
char name[25];
	
unsigned int data_avail;
	
int index;
	
bool busy;
	
bool hwrng_register_done;
	
bool hwrng_removed;
};


static void random_recv_done(struct virtqueue *vq) { struct virtrng_info *vi = vq->vdev->priv; /* We can get spurious callbacks, e.g. shared IRQs + virtio_pci. */ if (!virtqueue_get_buf(vi->vq, &vi->data_avail)) return; complete(&vi->have_data); }

Contributors

PersonTokensPropCommitsCommitProp
rusty russellrusty russell2655.32%120.00%
amos kongamos kong1736.17%120.00%
christian borntraegerchristian borntraeger24.26%120.00%
michael s. tsirkinmichael s. tsirkin12.13%120.00%
ian moltonian molton12.13%120.00%
Total47100.00%5100.00%

/* The host will fill any buffer we give it with sweet, sweet randomness. */
static void register_buffer(struct virtrng_info *vi, u8 *buf, size_t size) { struct scatterlist sg; sg_init_one(&sg, buf, size); /* There should always be room for one buffer. */ virtqueue_add_inbuf(vi->vq, &sg, 1, buf, GFP_KERNEL); virtqueue_kick(vi->vq); }

Contributors

PersonTokensPropCommitsCommitProp
rusty russellrusty russell3766.07%350.00%
ian moltonian molton916.07%116.67%
amos kongamos kong916.07%116.67%
michael s. tsirkinmichael s. tsirkin11.79%116.67%
Total56100.00%6100.00%


static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait) { int ret; struct virtrng_info *vi = (struct virtrng_info *)rng->priv; if (vi->hwrng_removed) return -ENODEV; if (!vi->busy) { vi->busy = true; init_completion(&vi->have_data); register_buffer(vi, buf, size); } if (!wait) return 0; ret = wait_for_completion_killable(&vi->have_data); if (ret < 0) return ret; vi->busy = false; return vi->data_avail; }

Contributors

PersonTokensPropCommitsCommitProp
amos kongamos kong3832.20%233.33%
ian moltonian molton3327.97%116.67%
rusty russellrusty russell3227.12%233.33%
amit shahamit shah1512.71%116.67%
Total118100.00%6100.00%


static void virtio_cleanup(struct hwrng *rng) { struct virtrng_info *vi = (struct virtrng_info *)rng->priv; if (vi->busy) wait_for_completion(&vi->have_data); }

Contributors

PersonTokensPropCommitsCommitProp
amos kongamos kong1846.15%133.33%
rusty russellrusty russell1743.59%133.33%
ian moltonian molton410.26%133.33%
Total39100.00%3100.00%


static int probe_common(struct virtio_device *vdev) { int err, index; struct virtrng_info *vi = NULL; vi = kzalloc(sizeof(struct virtrng_info), GFP_KERNEL); if (!vi) return -ENOMEM; vi->index = index = ida_simple_get(&rng_index_ida, 0, 0, GFP_KERNEL); if (index < 0) { err = index; goto err_ida; } sprintf(vi->name, "virtio_rng.%d", index); init_completion(&vi->have_data); vi->hwrng = (struct hwrng) { .read = virtio_read, .cleanup = virtio_cleanup, .priv = (unsigned long)vi, .name = vi->name, .quality = 1000, }; vdev->priv = vi; /* We expect a single virtqueue. */ vi->vq = virtio_find_single_vq(vdev, random_recv_done, "input"); if (IS_ERR(vi->vq)) { err = PTR_ERR(vi->vq); goto err_find; } return 0; err_find: ida_simple_remove(&rng_index_ida, index); err_ida: kfree(vi); return err; }

Contributors

PersonTokensPropCommitsCommitProp
amos kongamos kong6933.82%110.00%
sasha levinsasha levin6431.37%220.00%
rusty russellrusty russell3517.16%220.00%
michael s. tsirkinmichael s. tsirkin2311.27%220.00%
amit shahamit shah136.37%330.00%
Total204100.00%10100.00%


static void remove_common(struct virtio_device *vdev) { struct virtrng_info *vi = vdev->priv; vi->hwrng_removed = true; vi->data_avail = 0; complete(&vi->have_data); vdev->config->reset(vdev); vi->busy = false; if (vi->hwrng_register_done) hwrng_unregister(&vi->hwrng); vdev->config->del_vqs(vdev); ida_simple_remove(&rng_index_ida, vi->index); kfree(vi); }

Contributors

PersonTokensPropCommitsCommitProp
amos kongamos kong4447.31%333.33%
rusty russellrusty russell2830.11%111.11%
amit shahamit shah1415.05%333.33%
sasha levinsasha levin55.38%111.11%
michael s. tsirkinmichael s. tsirkin22.15%111.11%
Total93100.00%9100.00%


static int virtrng_probe(struct virtio_device *vdev) { return probe_common(vdev); }

Contributors

PersonTokensPropCommitsCommitProp
amit shahamit shah17100.00%1100.00%
Total17100.00%1100.00%


static void virtrng_remove(struct virtio_device *vdev) { remove_common(vdev); }

Contributors

PersonTokensPropCommitsCommitProp
amit shahamit shah1381.25%150.00%
rusty russellrusty russell318.75%150.00%
Total16100.00%2100.00%


static void virtrng_scan(struct virtio_device *vdev) { struct virtrng_info *vi = vdev->priv; int err; err = hwrng_register(&vi->hwrng); if (!err) vi->hwrng_register_done = true; }

Contributors

PersonTokensPropCommitsCommitProp
amit shahamit shah44100.00%1100.00%
Total44100.00%1100.00%

#ifdef CONFIG_PM_SLEEP
static int virtrng_freeze(struct virtio_device *vdev) { remove_common(vdev); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
amit shahamit shah19100.00%1100.00%
Total19100.00%1100.00%


static int virtrng_restore(struct virtio_device *vdev) { return probe_common(vdev); }

Contributors

PersonTokensPropCommitsCommitProp
amit shahamit shah17100.00%1100.00%
Total17100.00%1100.00%

#endif static struct virtio_device_id id_table[] = { { VIRTIO_ID_RNG, VIRTIO_DEV_ANY_ID }, { 0 }, }; static struct virtio_driver virtio_rng_driver = { .driver.name = KBUILD_MODNAME, .driver.owner = THIS_MODULE, .id_table = id_table, .probe = virtrng_probe, .remove = virtrng_remove, .scan = virtrng_scan, #ifdef CONFIG_PM_SLEEP .freeze = virtrng_freeze, .restore = virtrng_restore, #endif }; module_virtio_driver(virtio_rng_driver); MODULE_DEVICE_TABLE(virtio, id_table); MODULE_DESCRIPTION("Virtio random number driver"); MODULE_LICENSE("GPL");

Overall Contributors

PersonTokensPropCommitsCommitProp
rusty russellrusty russell27732.94%622.22%
amos kongamos kong21024.97%311.11%
amit shahamit shah18722.24%829.63%
sasha levinsasha levin849.99%27.41%
ian moltonian molton485.71%13.70%
michael s. tsirkinmichael s. tsirkin273.21%311.11%
paul gortmakerpaul gortmaker30.36%13.70%
aaron luaaron lu20.24%13.70%
christian borntraegerchristian borntraeger20.24%13.70%
jeff mahoneyjeff mahoney10.12%13.70%
Total841100.00%27100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
{% endraw %}