Skip to content
Snippets Groups Projects
core.c 3.58 KiB
Newer Older
 * Copyright 2011 CERN
 * Author: Federico Vaga <federico.vaga@gmail.com>
 * Author: Alessandro Rubini <rubini@gnudd.com>
 *
 * GNU GPLv2 or later
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/zio.h>
#include <linux/zio-buffer.h>
struct zio_status zio_global_status;
static struct zio_status *zstat = &zio_global_status; /* Always use ptr */
/*
 * We use a local slab for control structures.
 */
static struct kmem_cache *zio_ctrl_slab;

struct zio_control *zio_alloc_control(gfp_t gfp)
{
	struct zio_control *ctrl;

	ctrl = kmem_cache_alloc(zio_ctrl_slab, gfp);
	if (!ctrl)
		return NULL;
	memset(ctrl, 0, sizeof(*ctrl));
	ctrl->major_version = ZIO_MAJOR_VERSION;
	ctrl->minor_version = ZIO_MINOR_VERSION;
	if (ntohl(1) == 1)
		ctrl->flags |= ZIO_CONTROL_BIG_ENDIAN;
	else
		ctrl->flags |= ZIO_CONTROL_LITTLE_ENDIAN;
	return ctrl;
}
EXPORT_SYMBOL(zio_alloc_control);

void zio_free_control(struct zio_control *ctrl)
{
	kmem_cache_free(zio_ctrl_slab, ctrl);
}
EXPORT_SYMBOL(zio_free_control);

int __init zio_slab_init(void)
{
	zio_ctrl_slab = KMEM_CACHE(zio_control, 0);
	if (!zio_ctrl_slab)
		return -ENOMEM;
	return 0;
}

void zio_slab_exit(void) /* not __exit: called from zio_init on failures */
{
	if (zio_ctrl_slab)
		kmem_cache_destroy(zio_ctrl_slab);
	return;
}
struct zio_device *zio_find_device(char *name, uint32_t dev_id)
{
	struct zio_object_list_item *cur;
	struct zio_device *zdev;

	if (!name)
		return NULL;
	list_for_each_entry(cur, &zstat->all_devices.list, list) {
		pr_debug("%s:%d %s=%s\n", __func__, __LINE__, cur->name, name);
		zdev = to_zio_dev(&cur->obj_head->dev);
		if (strcmp(cur->name, name) == 0 && zdev->dev_id == dev_id)
			return zdev; /* found */
	}
	return NULL;
}
EXPORT_SYMBOL(zio_find_device);

static int __init zio_init(void)
{
	int err;

	/* Some compile-time checks, so developers are free to hack around */
	BUILD_BUG_ON(_ZIO_DEV_ATTR_STD_NUM != ARRAY_SIZE(zio_zdev_attr_names));
	BUILD_BUG_ON(_ZIO_BUF_ATTR_STD_NUM != ARRAY_SIZE(zio_zbuf_attr_names));
	BUILD_BUG_ON(_ZIO_TRG_ATTR_STD_NUM != ARRAY_SIZE(zio_trig_attr_names));
	BUILD_BUG_ON(ZIO_NR_MINORS > MINORMASK + 1);

	err = zio_slab_init();
	if (err)
		return err;
	/* Register ZIO bus */
	err = bus_register(&zio_bus_type);
	if (err)
		goto out;
	/* Initialize char device */
	err = zio_register_cdev();
	if (err)
		goto out_cdev;

	spin_lock_init(&zstat->lock);
	INIT_LIST_HEAD(&zstat->all_devices.list);
	zstat->all_devices.zobj_type = ZIO_DEV;
	INIT_LIST_HEAD(&zstat->all_trigger_types.list);
	zstat->all_trigger_types.zobj_type = ZIO_TRG;
	INIT_LIST_HEAD(&zstat->all_buffer_types.list);
	zstat->all_buffer_types.zobj_type = ZIO_BUF;

	err = zio_default_buffer_init();
	if (err)
		pr_warning("%s: cannot register default buffer\n", __func__);
	err = zio_default_trigger_init();
	if (err)
		pr_warning("%s: cannot register default trigger\n", __func__);
	pr_info("zio-core had been loaded\n");
	return 0;

out_cdev:
	bus_unregister(&zio_bus_type);
out:
	zio_slab_exit();
	return err;
}

static void __exit zio_exit(void)
{
	zio_default_trigger_exit();
	zio_default_buffer_exit();

	/* Remove char device */
	zio_unregister_cdev();
	/* Remove ZIO bus */
	bus_unregister(&zio_bus_type);
	zio_slab_exit();
	pr_info("zio-core had been unloaded\n");
	return;
}

subsys_initcall(zio_init);
module_exit(zio_exit);

MODULE_AUTHOR("Federico Vaga and Alessandro Rubini");
/* Federico wrote the core, Alessandro wrote default trigger and buffer */
MODULE_DESCRIPTION("ZIO - ZIO Input Output");
MODULE_LICENSE("GPL");