dect
/
linux-2.6
Archived
13
0
Fork 0

[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:
Ralph Wuerthner 2006-10-04 20:02:05 +02:00 committed by Martin Schwidefsky
parent f1ee3281be
commit 4e56296d47
1 changed files with 12 additions and 11 deletions

View File

@ -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);