drivers/char/bsr.c

Source file repositories/reference/linux-study-clean/drivers/char/bsr.c

File Facts

System
Linux kernel
Corpus path
drivers/char/bsr.c
Extension
.c
Size
8298 bytes
Lines
347
Domain
Driver Families
Bucket
drivers/char
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

static const struct file_operations bsr_fops = {
	.owner = THIS_MODULE,
	.mmap  = bsr_mmap,
	.open  = bsr_open,
	.llseek = noop_llseek,
};

static void bsr_cleanup_devs(void)
{
	struct bsr_dev *cur, *n;

	list_for_each_entry_safe(cur, n, &bsr_devs, bsr_list) {
		if (cur->bsr_device) {
			cdev_del(&cur->bsr_cdev);
			device_del(cur->bsr_device);
		}
		list_del(&cur->bsr_list);
		kfree(cur);
	}
}

static int bsr_add_node(struct device_node *bn)
{
	int bsr_stride_len, bsr_bytes_len, num_bsr_devs;
	const u32 *bsr_stride;
	const u32 *bsr_bytes;
	unsigned i;
	int ret = -ENODEV;

	bsr_stride = of_get_property(bn, "ibm,lock-stride", &bsr_stride_len);
	bsr_bytes  = of_get_property(bn, "ibm,#lock-bytes", &bsr_bytes_len);

	if (!bsr_stride || !bsr_bytes ||
	    (bsr_stride_len != bsr_bytes_len)) {
		printk(KERN_ERR "bsr of-node has missing/incorrect property\n");
		return ret;
	}

	num_bsr_devs = bsr_bytes_len / sizeof(u32);

	for (i = 0 ; i < num_bsr_devs; i++) {
		struct bsr_dev *cur = kzalloc_obj(struct bsr_dev);
		struct resource res;
		int result;

		if (!cur) {
			printk(KERN_ERR "Unable to alloc bsr dev\n");
			ret = -ENOMEM;
			goto out_err;
		}

		result = of_address_to_resource(bn, i, &res);
		if (result < 0) {
			printk(KERN_ERR "bsr of-node has invalid reg property, skipping\n");
			kfree(cur);
			continue;
		}

		cur->bsr_minor  = i + total_bsr_devs;
		cur->bsr_addr   = res.start;
		cur->bsr_len    = resource_size(&res);
		cur->bsr_bytes  = bsr_bytes[i];
		cur->bsr_stride = bsr_stride[i];
		cur->bsr_dev    = MKDEV(bsr_major, i + total_bsr_devs);

		/* if we have a bsr_len of > 4k and less then PAGE_SIZE (64k pages) */
		/* we can only map 4k of it, so only advertise the 4k in sysfs */
		if (cur->bsr_len > 4096 && cur->bsr_len < PAGE_SIZE)
			cur->bsr_len = 4096;

		switch(cur->bsr_bytes) {
		case 8:
			cur->bsr_type = BSR_8;
			break;
		case 16:
			cur->bsr_type = BSR_16;
			break;
		case 64:
			cur->bsr_type = BSR_64;
			break;
		case 128:
			cur->bsr_type = BSR_128;
			break;
		case 4096:
			cur->bsr_type = BSR_4096;
			break;
		default:
			cur->bsr_type = BSR_UNKNOWN;
		}

Annotation

Implementation Notes