drivers/s390/block/dasd_alias.c

Source file repositories/reference/linux-study-clean/drivers/s390/block/dasd_alias.c

File Facts

System
Linux kernel
Corpus path
drivers/s390/block/dasd_alias.c
Extension
.c
Size
28249 bytes
Lines
973
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 (!server) {
			list_add(&newserver->server, &aliastree.serverlist);
			server = newserver;
		} else {
			/* someone was faster */
			_free_server(newserver);
		}
	}

	lcu = _find_lcu(server, &uid);
	if (!lcu) {
		spin_unlock_irqrestore(&aliastree.lock, flags);
		newlcu = _allocate_lcu(&uid);
		if (IS_ERR(newlcu))
			return PTR_ERR(newlcu);
		spin_lock_irqsave(&aliastree.lock, flags);
		lcu = _find_lcu(server, &uid);
		if (!lcu) {
			list_add(&newlcu->lcu, &server->lculist);
			lcu = newlcu;
		} else {
			/* someone was faster */
			_free_lcu(newlcu);
		}
	}
	spin_lock(&lcu->lock);
	list_add(&device->alias_list, &lcu->inactive_devices);
	private->lcu = lcu;
	spin_unlock(&lcu->lock);
	spin_unlock_irqrestore(&aliastree.lock, flags);

	return 0;
}

/*
 * This function removes a device from the scope of alias management.
 * The complicated part is to make sure that it is not in use by
 * any of the workers. If necessary cancel the work.
 */
void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device)
{
	struct dasd_eckd_private *private = device->private;
	unsigned long flags;
	struct alias_lcu *lcu;
	struct alias_server *server;
	int was_pending;
	struct dasd_uid uid;

	lcu = private->lcu;
	/* nothing to do if already disconnected */
	if (!lcu)
		return;
	device->discipline->get_uid(device, &uid);
	spin_lock_irqsave(&lcu->lock, flags);
	/* make sure that the workers don't use this device */
	if (device == lcu->suc_data.device) {
		spin_unlock_irqrestore(&lcu->lock, flags);
		cancel_work_sync(&lcu->suc_data.worker);
		spin_lock_irqsave(&lcu->lock, flags);
		if (device == lcu->suc_data.device) {
			dasd_put_device(device);
			lcu->suc_data.device = NULL;
		}
	}
	was_pending = 0;
	if (device == lcu->ruac_data.device) {
		spin_unlock_irqrestore(&lcu->lock, flags);
		was_pending = 1;
		cancel_delayed_work_sync(&lcu->ruac_data.dwork);
		spin_lock_irqsave(&lcu->lock, flags);
		if (device == lcu->ruac_data.device) {
			dasd_put_device(device);
			lcu->ruac_data.device = NULL;
		}
	}
	private->lcu = NULL;
	spin_unlock_irqrestore(&lcu->lock, flags);

	spin_lock_irqsave(&aliastree.lock, flags);
	spin_lock(&lcu->lock);
	list_del_init(&device->alias_list);
	if (list_empty(&lcu->grouplist) &&
	    list_empty(&lcu->active_devices) &&
	    list_empty(&lcu->inactive_devices)) {
		list_del(&lcu->lcu);
		spin_unlock(&lcu->lock);
		_free_lcu(lcu);
		lcu = NULL;
	} else {
		if (was_pending)

Annotation

Implementation Notes