Пример #1
0
static int nrf905_release(struct inode *inode, struct file *filp)
{
	char devno[20];
	struct nrf905_dev_data *dev = filp->private_data;
	int fp_open;

	if (mutex_lock_interruptible(&dev->cdev_mutex))
		return -EINTR;

	fp_open = atomic_dec_return(&dev->fp_open);

	dev_info(dev->char_dev, "release: proc: %s, PID: %d, devno: %s, fp_open: %d\n",
		current->comm, current->pid, format_dev_t(devno, dev->cdev.dev),
		fp_open);

	if (!fp_open) {
		/* Wait transmission to finish.  */
		if (dev->chip.mode == NRF905_TX)
			usleep_range(20000UL, 22000UL);

		set_nrf905_op_mode(dev, NRF905_POWER_DOWN);

		dev->active_sender = NULL;
		dev->active_listener = NULL;
	}

	mutex_unlock(&dev->cdev_mutex);

	return 0;
}
Пример #2
0
static int nrf905_open(struct inode *inode, struct file *filp)
{
	int retval = 0;
	struct nrf905_dev_data *dev =
		container_of(inode->i_cdev, struct nrf905_dev_data, cdev);
	char devno[20];
	int fp_open;

	if (mutex_lock_interruptible(&dev->cdev_mutex))
		return -EINTR;

	filp->private_data = dev;

	nonseekable_open(inode, filp);

	fp_open = atomic_inc_return(&dev->fp_open);

	dev_info(dev->char_dev, "open: proc: %s, PID: %d, devno: %s, fp_open: %d\n",
		current->comm, current->pid, format_dev_t(devno, dev->cdev.dev),
		fp_open);

	mutex_unlock(&dev->cdev_mutex);

	return retval;
}
/**ltl
 * 功能: 将目标设备加入到列表中
 * 参数: t	->映射表
 *		ti	->映射目标
 *		path	->映射目标<major:minor>
 * 		start-> 映射目标相对低层设备的起始偏移量(类似磁盘分区的起始地址)
 *		len	-> 此目标设备在dm设备的长度
 *		mode	-> rw
 *		result-> 底层设备对象
 * 返回值:
 * 说明:
 */
static int __table_get_device(struct dm_table *t, struct dm_target *ti,
			      const char *path, sector_t start, sector_t len,
			      int mode, struct dm_dev **result)
{
	int r;
	dev_t dev;
	struct dm_dev *dd;
	unsigned int major, minor;

	BUG_ON(!t);
	/* 获取主设备号和次设备号 */
	if (sscanf(path, "%u:%u", &major, &minor) == 2) {
		/* Extract the major/minor numbers */
		dev = MKDEV(major, minor);
		if (MAJOR(dev) != major || MINOR(dev) != minor)
			return -EOVERFLOW;
	} else {
		/* convert the path to a device */
		if ((r = lookup_device(path, &dev))) /* 根据设备路径/dev/sdb获取<major:minor> */
			return r;
	}
	/* 在列表中查找映射目标 */
	dd = find_device(&t->devices, dev);
	if (!dd) {
		dd = kmalloc(sizeof(*dd), GFP_KERNEL);
		if (!dd)
			return -ENOMEM;

		dd->mode = mode;
		dd->bdev = NULL;
		/* 打开设备 */
		if ((r = open_dev(dd, dev, t->md))) {
			kfree(dd);
			return r;
		}

		format_dev_t(dd->name, dev); /* 主设备号次设备号 */

		atomic_set(&dd->count, 0);
		/* 将目标设备插入到映射表中 */
		list_add(&dd->list, &t->devices);

	} else if (dd->mode != (mode | dd->mode)) {
		r = upgrade_mode(dd, mode, t->md);
		if (r)
			return r;
	}
	atomic_inc(&dd->count);
	/* 检查区域是否超过设备 */
	if (!check_device_area(dd, start, len)) {
		DMWARN("device %s too small for target", path);
		dm_put_device(ti, dd);
		return -EINVAL;
	}

	*result = dd;

	return 0;
}
int toi_bio_mark_have_image(void)
{
    int result = 0;
    char buf[32];
    struct fs_info *fs_info;

    toi_message(TOI_IO, TOI_VERBOSE, 0, "Recording that an image exists.");
    memcpy(toi_sig_data->sig, tuxonice_signature,
           sizeof(tuxonice_signature));
    toi_sig_data->have_image = 1;
    toi_sig_data->resumed_before = 0;
    toi_sig_data->header_dev_t = get_header_dev_t();
    toi_sig_data->have_uuid = 0;

#if 1 // JJ: check this uuid is mismatch, such that it will failed on toi_bio_read_header_init() !!!
    fs_info = fs_info_from_block_dev(get_header_bdev());
    if (fs_info && !IS_ERR(fs_info)) {
        memcpy(toi_sig_data->header_uuid, &fs_info->uuid, 16);
        free_fs_info(fs_info);
    } else
        result = (int) PTR_ERR(fs_info);
#endif

    if (!result) {
        toi_message(TOI_IO, TOI_VERBOSE, 0, "Got uuid for dev_t %s.",
                    format_dev_t(buf, get_header_dev_t()));
        toi_sig_data->have_uuid = 1;
    } else
        toi_message(TOI_IO, TOI_VERBOSE, 0, "Could not get uuid for "
                    "dev_t %s.",
                    format_dev_t(buf, get_header_dev_t()));

    toi_sig_data->first_header_block = get_headerblock();
    have_image = 1;
    toi_message(TOI_IO, TOI_VERBOSE, 0, "header dev_t is %x. First block "
                "is %d.", toi_sig_data->header_dev_t,
                toi_sig_data->first_header_block);

    memcpy(toi_sig_data->sig2, tuxonice_signature,
           sizeof(tuxonice_signature));
    toi_sig_data->header_version = TOI_HEADER_VERSION;

    return toi_bio_ops.bdev_page_io(WRITE, resume_block_device,
                                    resume_firstblock, virt_to_page(toi_cur_sig_page));
}
Пример #5
0
static int __init helloworld_init(void)
{
	int result;

	PDEBUG("init\n");
	PDEBUG("memory= '%s'\n", memory);

	// TODO check voor errors, concurrency

	/* allocate a memory area */
	memory = kcalloc(memory_size, 1, GFP_KERNEL);
	if (!memory) {
		PDEBUG("error allocating memory\n");
		return -1;
	}
	/* insert initial data into memory */
	memcpy(memory, initial_data, sizeof(char) * strlen(initial_data));

	/* Get a range of major, minor numbers. */
	result = alloc_chrdev_region(&hello_devt, 0, 1, "helloworld");
	if (result < 0) {
		PDEBUG("allocate device\n");
		return result;
	}
	char *test = kmalloc(sizeof(char)*1000, GFP_KERNEL);
	PDEBUG("registered device %s\n", format_dev_t(test, hello_devt));
	kfree(test);

	/* Register character device, set file operations */
 	hello_cdev = cdev_alloc();
	if (!hello_cdev) {
		PDEBUG("can't alloc cdev.\n");
		goto fail;
	}
	hello_cdev->ops = &hello_fops;
	hello_cdev->owner = THIS_MODULE;
	result = cdev_add(hello_cdev, hello_devt, 1);
	if (result < 0) {
		PDEBUG("adding device to kernel failed.\n");
		goto fail;
	}

	/* Create proc file */
	hello_proc = proc_create("driver/helloworldmem", 0, NULL, &hello_proc_fops);
	if (!hello_proc) {
		PDEBUG("adding proc dirent failed");
		goto fail;
	}

	return 0;

	fail:
		PDEBUG("fail during initialization!\n");
		/* helloworld_exit(); */
		return result;
}
/**
 * toi_open_bdev: Open a bdev at resume time.
 *
 * index: The swap index. May be MAX_SWAPFILES for the resume_dev_t
 * (the user can have resume= pointing at a swap partition/file that isn't
 * swapon'd when they hibernate. MAX_SWAPFILES+1 for the first page of the
 * header. It will be from a swap partition that was enabled when we hibernated,
 * but we don't know it's real index until we read that first page.
 * dev_t: The device major/minor.
 * display_errs: Whether to try to do this quietly.
 *
 * We stored a dev_t in the image header. Open the matching device without
 * requiring /dev/<whatever> in most cases and record the details needed
 * to close it later and avoid duplicating work.
 */
struct block_device *toi_open_bdev(char *uuid, dev_t default_device, int display_errs)
{
	struct block_device *bdev;
	dev_t device = default_device;
	char buf[32];
	int retried = 0;

 retry:
	if (uuid) {
		struct fs_info seek;
		strncpy((char *)&seek.uuid, uuid, 16);
		seek.dev_t = 0;
		seek.last_mount_size = 0;
		device = blk_lookup_fs_info(&seek);
		if (!device) {
			device = default_device;
			printk(KERN_DEBUG "Unable to resolve uuid. Falling back" " to dev_t.\n");
		} else
			printk(KERN_DEBUG "Resolved uuid to device %s.\n",
			       format_dev_t(buf, device));
	}

	if (!device) {
		printk(KERN_ERR "TuxOnIce attempting to open a " "blank dev_t!\n");
		dump_stack();
		return NULL;
	}
	bdev = toi_open_by_devnum(device);

	if (IS_ERR(bdev) || !bdev) {
		if (!retried) {
			retried = 1;
			wait_for_device_probe();
			goto retry;
		}
		if (display_errs)
			toi_early_boot_message(1, TOI_CONTINUE_REQ,
					       "Failed to get access to block device "
					       "\"%x\" (error %d).\n Maybe you need "
					       "to run mknod and/or lvmsetup in an "
					       "initrd/ramfs?", device, bdev);
		return ERR_PTR(-EINVAL);
	}
	toi_message(TOI_BIO, TOI_VERBOSE, 0, "TuxOnIce got bdev %p for dev_t %x.", bdev, device);

	return bdev;
}
Пример #7
0
int acqiris_open(struct inode* inode, struct file* filp)
{
    struct acqiris_driver *drv;
    struct acqiris_device *aq_dev;
    char buffer[20];
    int minor;
    int dev_num;

    minor = MINOR(inode->i_rdev);

    if (dbgl&DINIT) printk(ACQRS_INFO "acqiris_open(%s)\n", format_dev_t(buffer, inode->i_rdev));

    /* Opening the main device is always possible */
    if (minor == 0)
    {
        drv = container_of(inode->i_cdev, struct acqiris_driver, cdev);
        filp->private_data = drv;

        return 0;
    }
Пример #8
0
static int disk_status(struct dirty_log *log, status_type_t status,
		       char *result, unsigned int maxlen)
{
	int sz = 0;
	char buffer[16];
	struct log_c *lc = log->context;

	switch(status) {
	case STATUSTYPE_INFO:
		break;

	case STATUSTYPE_TABLE:
		format_dev_t(buffer, lc->log_dev->bdev->bd_dev);
		DMEMIT("%s %u %s %u ", log->type->name,
		       lc->sync == DEFAULTSYNC ? 2 : 3, buffer,
		       lc->region_size);
		DMEMIT_SYNC;
	}

	return sz;
}
Пример #9
0
/*
 * Allocate and initialise a blank device with a given minor.
 */
static struct mapped_device *alloc_dev(int minor)
{
	int r;
	struct mapped_device *md = kmalloc(sizeof(*md), GFP_KERNEL);
	void *old_md;

	if (!md) {
		DMWARN("unable to allocate device, out of memory.");
		return NULL;
	}

	if (!try_module_get(THIS_MODULE))
		goto bad0;

	/* get a minor number for the dev */
	if (minor == DM_ANY_MINOR)
		r = next_free_minor(md, &minor);
	else
		r = specific_minor(md, minor);
	if (r < 0)
		goto bad1;

	memset(md, 0, sizeof(*md));
	init_rwsem(&md->io_lock);
	init_MUTEX(&md->suspend_lock);
	spin_lock_init(&md->pushback_lock);
	rwlock_init(&md->map_lock);
	atomic_set(&md->holders, 1);
	atomic_set(&md->open_count, 0);
	atomic_set(&md->event_nr, 0);

	md->queue = blk_alloc_queue(GFP_KERNEL);
	if (!md->queue)
		goto bad1_free_minor;

	md->queue->queuedata = md;
	md->queue->backing_dev_info.congested_fn = dm_any_congested;
	md->queue->backing_dev_info.congested_data = md;
	blk_queue_make_request(md->queue, dm_request);
	blk_queue_bounce_limit(md->queue, BLK_BOUNCE_ANY);
	md->queue->unplug_fn = dm_unplug_all;
	md->queue->issue_flush_fn = dm_flush_all;

	md->io_pool = mempool_create_slab_pool(MIN_IOS, _io_cache);
	if (!md->io_pool)
		goto bad2;

	md->tio_pool = mempool_create_slab_pool(MIN_IOS, _tio_cache);
	if (!md->tio_pool)
		goto bad3;

	md->bs = bioset_create(16, 16);
	if (!md->bs)
		goto bad_no_bioset;

	md->disk = alloc_disk(1);
	if (!md->disk)
		goto bad4;

	atomic_set(&md->pending, 0);
	init_waitqueue_head(&md->wait);
	init_waitqueue_head(&md->eventq);

	md->disk->major = _major;
	md->disk->first_minor = minor;
	md->disk->fops = &dm_blk_dops;
	md->disk->queue = md->queue;
	md->disk->private_data = md;
	sprintf(md->disk->disk_name, "dm-%d", minor);
	add_disk(md->disk);
	format_dev_t(md->name, MKDEV(_major, minor));

	/* Populate the mapping, nobody knows we exist yet */
	spin_lock(&_minor_lock);
	old_md = idr_replace(&_minor_idr, md, minor);
	spin_unlock(&_minor_lock);

	BUG_ON(old_md != MINOR_ALLOCED);

	return md;

 bad4:
	bioset_free(md->bs);
 bad_no_bioset:
	mempool_destroy(md->tio_pool);
 bad3:
	mempool_destroy(md->io_pool);
 bad2:
	blk_cleanup_queue(md->queue);
 bad1_free_minor:
	free_minor(minor);
 bad1:
	module_put(THIS_MODULE);
 bad0:
	kfree(md);
	return NULL;
}
Пример #10
0
static int __init nrf905_init(void)
{
	int retval = -ENODEV;
	dev_t devno = 0;
	char cdevno[20];
	struct nrf905_dev_data *dev;

	if (nrf905_major) {
		devno = MKDEV(nrf905_major, nrf905_minor);
		retval = register_chrdev_region(devno, NRF905_NR_DEVS,
			"nrf905");
	} else {
		retval = alloc_chrdev_region(&devno, nrf905_minor,
			NRF905_NR_DEVS,	"nrf905");
		nrf905_major = MAJOR(devno);
	}
	if (retval < 0) {
		pr_err("nrf905: can't get major %d\n", nrf905_major);
		goto err_major;
	}

	pr_info("nrf905: %s\n", format_dev_t(cdevno, devno));

	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
	if (IS_ERR_OR_NULL(dev)) {
		pr_err("nrf905: can't allocate memory for nrf905_dev\n");
		retval = -ENOMEM;
		goto err_nrf905_dev;
	}
	nrf905_dev = dev;

	init_waitqueue_head(&dev->recv_waitq);

	mutex_init(&dev->cdev_mutex);
	mutex_init(&dev->dev_mutex);

	spin_lock_init(&dev->chip.irq_lock);

	atomic_set(&nrf905_dev->fp_open, 0);

	dev->nrf905_class = class_create(THIS_MODULE, "nrf905");
	if (IS_ERR(dev->nrf905_class)) {
		pr_err("nrf905: class create fail\n");
		retval = PTR_ERR(dev->nrf905_class);
		goto err_class;
	}

	dev->nrf905_class->dev_groups = chip_config_groups;

	dev->char_dev =
		device_create(dev->nrf905_class, NULL,
			MKDEV(nrf905_major, nrf905_minor), NULL, "nrf905");

	if (IS_ERR(dev->char_dev)) {
		pr_err("nrf905: char device create failed\n");
		retval = PTR_ERR(dev->char_dev);
		goto err_char_dev;
	}

	dev_set_drvdata(dev->char_dev, dev);

	nrf905_dev->work_q = alloc_workqueue("nrf905", 0, 0);
	if (IS_ERR_OR_NULL(nrf905_dev->work_q)) {
		retval = -ENOMEM;
		goto err_workq;
	}

	INIT_WORK(&nrf905_dev->work, nrf905_data_ready);

	pr_info("nrf905: register spi driver\n");
	retval = spi_register_driver(&nrf905_driver);
	if (retval < 0) {
		pr_err("nrf905: spi driver register fail\n");
		goto err_spi_register;
	}

	cdev_init(&dev->cdev, &nrf905_fops);
	dev->cdev.owner = THIS_MODULE;

	retval = cdev_add(&dev->cdev, devno, 1);
	if (retval < 0) {
		pr_err("nrf905: cdev reg. failed, major %d, minor %d: %d\n",
			nrf905_major, nrf905_minor, retval);
		goto err_cdev;
	}

	pr_info("nrf905 init ready: %d\n", retval);
	return retval;

err_cdev:
	spi_unregister_driver(&nrf905_driver);

err_spi_register:
	remove_proc_entry("nrf905", NULL);
	device_destroy(dev->nrf905_class,
		MKDEV(nrf905_major, nrf905_minor));

err_workq:
	destroy_workqueue(nrf905_dev->work_q);

err_char_dev:
	class_destroy(dev->nrf905_class);

err_class:
	kfree(dev);

err_nrf905_dev:
	unregister_chrdev_region(devno, NRF905_NR_DEVS);

err_major:
	return retval;
}
Пример #11
0
static ssize_t nrf905_write(struct file *filp,
			    const char __user *buf,
			    size_t count, loff_t *f_pos)
{
	ssize_t retval = -EFBIG;
	char devno[20];

	struct nrf905_dev_data *dev = filp->private_data;

	if (mutex_lock_interruptible(&dev->dev_mutex))
		return -EINTR;

	if (dev->chip.mode != NRF905_POWER_DOWN &&
	    dev->chip.mode != NRF905_RX) {
		dev_err(dev->char_dev, "Chip busy\n");
		retval = -EBUSY;
		goto out;
	}

	if (dev->active_sender != NULL && dev->active_sender != filp) {
		dev_err(dev->char_dev, "Only one TX operation at the time\n");
		retval = -EBUSY;
		goto out;
	}

	dev->active_sender = filp;

	dev_info(dev->char_dev, "write: proc: %s, PID: %d, devno: %s, count: %lu, pos: %lld\n",
		current->comm, current->pid, format_dev_t(devno, dev->cdev.dev),
		(unsigned long) count, *f_pos);

	if (*f_pos >= NRF905_PAYLOAD_LEN ||
		count > NRF905_PAYLOAD_LEN ||
		*f_pos + count > NRF905_PAYLOAD_LEN) {
		dev_err(dev->char_dev, "Out of buffer\n");
		goto err;
	}

	/* Clear buffer only when write started at the beginning. */
	if (*f_pos == 0)
		memset(dev->dev_send_buf, 0, NRF905_PAYLOAD_LEN);

	if (copy_from_user(dev->dev_send_buf + *f_pos, buf, count)) {
		retval = -EFAULT;
		goto err;
	}

	*f_pos += count;
	retval = count;

	if (*f_pos == NRF905_PAYLOAD_LEN) {
		retval = set_nrf905_op_mode(dev, NRF905_TX);
		dev->active_sender = NULL;

		/* Start a new msg*/
		*f_pos = 0;
	}

	goto out;

err:
	dev->active_sender = NULL;
out:
	mutex_unlock(&dev->dev_mutex);
	return retval;
}