Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4e56296d authored by Ralph Wuerthner's avatar Ralph Wuerthner Committed by Martin Schwidefsky
Browse files

[S390] zcrypt device registration/unregistration race.



Fix a race condition during AP device registration and unregistration.

Signed-off-by: default avatarRalph Wuerthner <rwuerthn@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent f1ee3281
Loading
Loading
Loading
Loading
+12 −11
Original line number Diff line number Diff line
@@ -449,8 +449,6 @@ static int ap_device_probe(struct device *dev)

	ap_dev->drv = ap_drv;
	rc = ap_drv->probe ? ap_drv->probe(ap_dev) : -ENODEV;
	if (rc)
		ap_dev->unregistered = 1;
	return rc;
}

@@ -487,14 +485,7 @@ static int ap_device_remove(struct device *dev)
	struct ap_device *ap_dev = to_ap_dev(dev);
	struct ap_driver *ap_drv = ap_dev->drv;

	spin_lock_bh(&ap_dev->lock);
	__ap_flush_queue(ap_dev);
	/**
	 * set ->unregistered to 1 while holding the lock. This prevents
	 * new messages to be put on the queue from now on.
	 */
	ap_dev->unregistered = 1;
	spin_unlock_bh(&ap_dev->lock);
	ap_flush_queue(ap_dev);
	if (ap_drv->remove)
		ap_drv->remove(ap_dev);
	return 0;
@@ -763,6 +754,7 @@ static void ap_scan_bus(void *data)
			break;
		ap_dev->qid = qid;
		ap_dev->queue_depth = queue_depth;
		ap_dev->unregistered = 1;
		spin_lock_init(&ap_dev->lock);
		INIT_LIST_HEAD(&ap_dev->pendingq);
		INIT_LIST_HEAD(&ap_dev->requestq);
@@ -784,7 +776,12 @@ static void ap_scan_bus(void *data)
		/* Add device attributes. */
		rc = sysfs_create_group(&ap_dev->device.kobj,
					&ap_dev_attr_group);
		if (rc)
		if (!rc) {
			spin_lock_bh(&ap_dev->lock);
			ap_dev->unregistered = 0;
			spin_unlock_bh(&ap_dev->lock);
		}
		else
			device_unregister(&ap_dev->device);
	}
}
@@ -970,6 +967,8 @@ void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg)
			rc = __ap_queue_message(ap_dev, ap_msg);
		if (!rc)
			wake_up(&ap_poll_wait);
		if (rc == -ENODEV)
			ap_dev->unregistered = 1;
	} else {
		ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
		rc = 0;
@@ -1028,6 +1027,8 @@ static int __ap_poll_all(struct device *dev, void *data)
	spin_lock(&ap_dev->lock);
	if (!ap_dev->unregistered) {
		rc = ap_poll_queue(to_ap_dev(dev), (unsigned long *) data);
		if (rc)
			ap_dev->unregistered = 1;
	} else
		rc = 0;
	spin_unlock(&ap_dev->lock);