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

Commit 4145ba76 authored by Tim Sell's avatar Tim Sell Committed by Greg Kroah-Hartman
Browse files

staging: unisys: visornic: prevent double-unlock of priv_lock



Previously, devdata->priv_lock was being unlocked in visornic_serverdown()
both before calling visornic_serverdown_complete(), then again at the end
of the function.  This bug was corrected.

The structure of visornic_serverdown() was also improved to make it easier
to follow and to decrease the chance that such bugs will be introduced
again.  The main-path logic now falls thru down the left-side of the page,
with a common error-exit point to handle error conditions.

Signed-off-by: default avatarTim Sell <Timothy.Sell@unisys.com>
Signed-off-by: default avatarDavid Kershner <david.kershner@unisys.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 6fac083b
Loading
Loading
Loading
Loading
+25 −15
Original line number Diff line number Diff line
@@ -356,28 +356,38 @@ visornic_serverdown(struct visornic_devdata *devdata,
		    visorbus_state_complete_func complete_func)
{
	unsigned long flags;
	int err;

	spin_lock_irqsave(&devdata->priv_lock, flags);
	if (!devdata->server_down && !devdata->server_change_state) {
	if (devdata->server_change_state) {
		dev_dbg(&devdata->dev->device, "%s changing state\n",
			__func__);
		err = -EINVAL;
		goto err_unlock;
	}
	if (devdata->server_down) {
		dev_dbg(&devdata->dev->device, "%s already down\n",
			__func__);
		err = -EINVAL;
		goto err_unlock;
	}
	if (devdata->going_away) {
			spin_unlock_irqrestore(&devdata->priv_lock, flags);
		dev_dbg(&devdata->dev->device,
			"%s aborting because device removal pending\n",
			__func__);
			return -ENODEV;
		err = -ENODEV;
		goto err_unlock;
	}
	devdata->server_change_state = true;
	devdata->server_down_complete_func = complete_func;
	spin_unlock_irqrestore(&devdata->priv_lock, flags);

	visornic_serverdown_complete(devdata);
	} else if (devdata->server_change_state) {
		dev_dbg(&devdata->dev->device, "%s changing state\n",
			__func__);
		spin_unlock_irqrestore(&devdata->priv_lock, flags);
		return -EINVAL;
	}
	spin_unlock_irqrestore(&devdata->priv_lock, flags);
	return 0;

err_unlock:
	spin_unlock_irqrestore(&devdata->priv_lock, flags);
	return err;
}

/**