[S390] zcrypt device registration/unregistration race.
Fix a race condition during AP device registration and unregistration. Signed-off-by: Ralph Wuerthner <rwuerthn@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
parent
f1ee3281be
commit
4e56296d47
@ -449,8 +449,6 @@ static int ap_device_probe(struct device *dev)
|
|||||||
|
|
||||||
ap_dev->drv = ap_drv;
|
ap_dev->drv = ap_drv;
|
||||||
rc = ap_drv->probe ? ap_drv->probe(ap_dev) : -ENODEV;
|
rc = ap_drv->probe ? ap_drv->probe(ap_dev) : -ENODEV;
|
||||||
if (rc)
|
|
||||||
ap_dev->unregistered = 1;
|
|
||||||
return rc;
|
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_device *ap_dev = to_ap_dev(dev);
|
||||||
struct ap_driver *ap_drv = ap_dev->drv;
|
struct ap_driver *ap_drv = ap_dev->drv;
|
||||||
|
|
||||||
spin_lock_bh(&ap_dev->lock);
|
ap_flush_queue(ap_dev);
|
||||||
__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);
|
|
||||||
if (ap_drv->remove)
|
if (ap_drv->remove)
|
||||||
ap_drv->remove(ap_dev);
|
ap_drv->remove(ap_dev);
|
||||||
return 0;
|
return 0;
|
||||||
@ -763,6 +754,7 @@ static void ap_scan_bus(void *data)
|
|||||||
break;
|
break;
|
||||||
ap_dev->qid = qid;
|
ap_dev->qid = qid;
|
||||||
ap_dev->queue_depth = queue_depth;
|
ap_dev->queue_depth = queue_depth;
|
||||||
|
ap_dev->unregistered = 1;
|
||||||
spin_lock_init(&ap_dev->lock);
|
spin_lock_init(&ap_dev->lock);
|
||||||
INIT_LIST_HEAD(&ap_dev->pendingq);
|
INIT_LIST_HEAD(&ap_dev->pendingq);
|
||||||
INIT_LIST_HEAD(&ap_dev->requestq);
|
INIT_LIST_HEAD(&ap_dev->requestq);
|
||||||
@ -784,7 +776,12 @@ static void ap_scan_bus(void *data)
|
|||||||
/* Add device attributes. */
|
/* Add device attributes. */
|
||||||
rc = sysfs_create_group(&ap_dev->device.kobj,
|
rc = sysfs_create_group(&ap_dev->device.kobj,
|
||||||
&ap_dev_attr_group);
|
&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);
|
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);
|
rc = __ap_queue_message(ap_dev, ap_msg);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
wake_up(&ap_poll_wait);
|
wake_up(&ap_poll_wait);
|
||||||
|
if (rc == -ENODEV)
|
||||||
|
ap_dev->unregistered = 1;
|
||||||
} else {
|
} else {
|
||||||
ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
|
ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV));
|
||||||
rc = 0;
|
rc = 0;
|
||||||
@ -1028,6 +1027,8 @@ static int __ap_poll_all(struct device *dev, void *data)
|
|||||||
spin_lock(&ap_dev->lock);
|
spin_lock(&ap_dev->lock);
|
||||||
if (!ap_dev->unregistered) {
|
if (!ap_dev->unregistered) {
|
||||||
rc = ap_poll_queue(to_ap_dev(dev), (unsigned long *) data);
|
rc = ap_poll_queue(to_ap_dev(dev), (unsigned long *) data);
|
||||||
|
if (rc)
|
||||||
|
ap_dev->unregistered = 1;
|
||||||
} else
|
} else
|
||||||
rc = 0;
|
rc = 0;
|
||||||
spin_unlock(&ap_dev->lock);
|
spin_unlock(&ap_dev->lock);
|
||||||
|
Loading…
Reference in New Issue
Block a user