drivers/misc/genwqe/card_dev.c

Source file repositories/reference/linux-study-clean/drivers/misc/genwqe/card_dev.c

File Facts

System
Linux kernel
Corpus path
drivers/misc/genwqe/card_dev.c
Extension
.c
Size
34501 bytes
Lines
1392
Domain
Driver Families
Bucket
drivers/misc
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 genwqe_fops = {
	.owner		= THIS_MODULE,
	.open		= genwqe_open,
	.fasync		= genwqe_fasync,
	.mmap		= genwqe_mmap,
	.unlocked_ioctl	= genwqe_ioctl,
	.compat_ioctl   = compat_ptr_ioctl,
	.release	= genwqe_release,
};

static int genwqe_device_initialized(struct genwqe_dev *cd)
{
	return cd->dev != NULL;
}

/**
 * genwqe_device_create() - Create and configure genwqe char device
 * @cd:      genwqe device descriptor
 *
 * This function must be called before we create any more genwqe
 * character devices, because it is allocating the major and minor
 * number which are supposed to be used by the client drivers.
 */
int genwqe_device_create(struct genwqe_dev *cd)
{
	int rc;
	struct pci_dev *pci_dev = cd->pci_dev;

	/*
	 * Here starts the individual setup per client. It must
	 * initialize its own cdev data structure with its own fops.
	 * The appropriate devnum needs to be created. The ranges must
	 * not overlap.
	 */
	rc = alloc_chrdev_region(&cd->devnum_genwqe, 0,
				 GENWQE_MAX_MINOR, GENWQE_DEVNAME);
	if (rc < 0) {
		dev_err(&pci_dev->dev, "err: alloc_chrdev_region failed\n");
		goto err_dev;
	}

	cdev_init(&cd->cdev_genwqe, &genwqe_fops);
	cd->cdev_genwqe.owner = THIS_MODULE;

	rc = cdev_add(&cd->cdev_genwqe, cd->devnum_genwqe, 1);
	if (rc < 0) {
		dev_err(&pci_dev->dev, "err: cdev_add failed\n");
		goto err_add;
	}

	/*
	 * Finally the device in /dev/... must be created. The rule is
	 * to use card%d_clientname for each created device.
	 */
	cd->dev = device_create_with_groups(cd->class_genwqe,
					    &cd->pci_dev->dev,
					    cd->devnum_genwqe, cd,
					    genwqe_attribute_groups,
					    GENWQE_DEVNAME "%u_card",
					    cd->card_idx);
	if (IS_ERR(cd->dev)) {
		rc = PTR_ERR(cd->dev);
		goto err_cdev;
	}

	genwqe_init_debugfs(cd);

	return 0;

 err_cdev:
	cdev_del(&cd->cdev_genwqe);
 err_add:
	unregister_chrdev_region(cd->devnum_genwqe, GENWQE_MAX_MINOR);
 err_dev:
	cd->dev = NULL;
	return rc;
}

static int genwqe_inform_and_stop_processes(struct genwqe_dev *cd)
{
	int rc;
	unsigned int i;
	struct pci_dev *pci_dev = cd->pci_dev;

	if (!genwqe_open_files(cd))
		return 0;

	dev_warn(&pci_dev->dev, "[%s] send SIGIO and wait ...\n", __func__);

	rc = genwqe_kill_fasync(cd, SIGIO);

Annotation

Implementation Notes