drivers/fsi/fsi-scom.c

Source file repositories/reference/linux-study-clean/drivers/fsi/fsi-scom.c

File Facts

System
Linux kernel
Corpus path
drivers/fsi/fsi-scom.c
Extension
.c
Size
14655 bytes
Lines
616
Domain
Driver Families
Bucket
drivers/fsi
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 scom_fops = {
	.owner		= THIS_MODULE,
	.open		= scom_open,
	.llseek		= scom_llseek,
	.read		= scom_read,
	.write		= scom_write,
	.unlocked_ioctl	= scom_ioctl,
};

static void scom_free(struct device *dev)
{
	struct scom_device *scom = container_of(dev, struct scom_device, dev);

	put_device(&scom->fsi_dev->dev);
	kfree(scom);
}

static int scom_probe(struct fsi_device *fsi_dev)
{
	struct device *dev = &fsi_dev->dev;
	struct scom_device *scom;
	int rc, didx;

	scom = kzalloc_obj(*scom);
	if (!scom)
		return -ENOMEM;
	fsi_set_drvdata(fsi_dev, scom);
	mutex_init(&scom->lock);

	/* Grab a reference to the device (parent of our cdev), we'll drop it later */
	if (!get_device(dev)) {
		kfree(scom);
		return -ENODEV;
	}
	scom->fsi_dev = fsi_dev;

	/* Create chardev for userspace access */
	scom->dev.type = &fsi_cdev_type;
	scom->dev.parent = dev;
	scom->dev.release = scom_free;
	device_initialize(&scom->dev);

	/* Allocate a minor in the FSI space */
	rc = fsi_get_new_minor(fsi_dev, fsi_dev_scom, &scom->dev.devt, &didx);
	if (rc)
		goto err;

	dev_set_name(&scom->dev, "scom%d", didx);
	cdev_init(&scom->cdev, &scom_fops);
	rc = cdev_device_add(&scom->cdev, &scom->dev);
	if (rc) {
		dev_err(dev, "Error %d creating char device %s\n",
			rc, dev_name(&scom->dev));
		goto err_free_minor;
	}

	return 0;
 err_free_minor:
	fsi_free_minor(scom->dev.devt);
 err:
	put_device(&scom->dev);
	return rc;
}

static void scom_remove(struct fsi_device *fsi_dev)
{
	struct scom_device *scom = fsi_get_drvdata(fsi_dev);

	mutex_lock(&scom->lock);
	scom->dead = true;
	mutex_unlock(&scom->lock);
	cdev_device_del(&scom->cdev, &scom->dev);
	fsi_free_minor(scom->dev.devt);
	put_device(&scom->dev);
}

static const struct of_device_id scom_of_ids[] = {
	{ .compatible = "ibm,fsi2pib" },
	{ }
};
MODULE_DEVICE_TABLE(of, scom_of_ids);

static const struct fsi_device_id scom_ids[] = {
	{
		.engine_type = FSI_ENGID_SCOM,
		.version = FSI_VERSION_ANY,
	},
	{ 0 }
};

Annotation

Implementation Notes