drivers/s390/scsi/zfcp_unit.c

Source file repositories/reference/linux-study-clean/drivers/s390/scsi/zfcp_unit.c

File Facts

System
Linux kernel
Corpus path
drivers/s390/scsi/zfcp_unit.c
Extension
.c
Size
6644 bytes
Lines
264
Domain
Driver Families
Bucket
drivers/s390
Inferred role
Driver Families: implementation source
Status
source 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

if (unit->fcp_lun == fcp_lun) {
			get_device(&unit->dev);
			return unit;
		}

	return NULL;
}

/**
 * zfcp_unit_find - Find and return zfcp_unit with specified FCP LUN
 * @port: zfcp_port where to look for the unit
 * @fcp_lun: 64 Bit FCP LUN used to identify the zfcp_unit
 *
 * If zfcp_unit is found, a reference is acquired that has to be
 * released later.
 *
 * Returns: Pointer to the zfcp_unit, or NULL if there is no zfcp_unit
 *          with the specified FCP LUN.
 */
struct zfcp_unit *zfcp_unit_find(struct zfcp_port *port, u64 fcp_lun)
{
	struct zfcp_unit *unit;

	read_lock_irq(&port->unit_list_lock);
	unit = _zfcp_unit_find(port, fcp_lun);
	read_unlock_irq(&port->unit_list_lock);
	return unit;
}

/**
 * zfcp_unit_release - Drop reference to zfcp_port and free memory of zfcp_unit.
 * @dev: pointer to device in zfcp_unit
 */
static void zfcp_unit_release(struct device *dev)
{
	struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev);

	atomic_dec(&unit->port->units);
	kfree(unit);
}

/**
 * zfcp_unit_add - add unit to unit list of a port.
 * @port: pointer to port where unit is added
 * @fcp_lun: FCP LUN of unit to be added
 * Returns: 0 success
 *
 * Sets up some unit internal structures and creates sysfs entry.
 */
int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun)
{
	struct zfcp_unit *unit;
	int retval = 0;

	mutex_lock(&zfcp_sysfs_port_units_mutex);
	if (zfcp_sysfs_port_is_removing(port)) {
		/* port is already gone */
		retval = -ENODEV;
		goto out;
	}

	unit = zfcp_unit_find(port, fcp_lun);
	if (unit) {
		put_device(&unit->dev);
		retval = -EEXIST;
		goto out;
	}

	unit = kzalloc_obj(struct zfcp_unit);
	if (!unit) {
		retval = -ENOMEM;
		goto out;
	}

	unit->port = port;
	unit->fcp_lun = fcp_lun;
	unit->dev.parent = &port->dev;
	unit->dev.release = zfcp_unit_release;
	unit->dev.groups = zfcp_unit_attr_groups;
	INIT_WORK(&unit->scsi_work, zfcp_unit_scsi_scan_work);

	if (dev_set_name(&unit->dev, "0x%016llx",
			 (unsigned long long) fcp_lun)) {
		kfree(unit);
		retval = -ENOMEM;
		goto out;
	}

	if (device_register(&unit->dev)) {
		put_device(&unit->dev);

Annotation

Implementation Notes