Commit d01da5ea authored by Tim Sell's avatar Tim Sell Committed by Greg Kroah-Hartman

staging: unisys: visornic: correct visornic_pause

Correct visornic_pause() to indicate completion asynchronously rather
than in-line

Previously, visornic_pause() (called to stop the device due to IOVM service
partition recovery) was calling the passed complete_func() in-line, rather
than delaying the calling until after the device had actually been stopped.

The behavior has been corrected so that the calling of the complete_func()
is now delayed until after the stopping of the device has been completed in
visornic_serverdown_complete(), which runs asynchronously via the workqueue
visornic_serverdown_workqueue.
Signed-off-by: default avatarTim Sell <Timothy.Sell@unisys.com>
Signed-off-by: default avatarBenjamin Romer <benjamin.romer@unisys.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent d15a65be
...@@ -151,6 +151,7 @@ struct visornic_devdata { ...@@ -151,6 +151,7 @@ struct visornic_devdata {
* sent to the IOPART end * sent to the IOPART end
*/ */
struct work_struct serverdown_completion; struct work_struct serverdown_completion;
visorbus_state_complete_func server_down_complete_func;
struct work_struct timeout_reset; struct work_struct timeout_reset;
struct uiscmdrsp *cmdrsp_rcv; /* cmdrsp_rcv is used for struct uiscmdrsp *cmdrsp_rcv; /* cmdrsp_rcv is used for
* posting/unposting rcv buffers * posting/unposting rcv buffers
...@@ -545,8 +546,12 @@ visornic_serverdown_complete(struct work_struct *work) ...@@ -545,8 +546,12 @@ visornic_serverdown_complete(struct work_struct *work)
atomic_set(&devdata->num_rcvbuf_in_iovm, 0); atomic_set(&devdata->num_rcvbuf_in_iovm, 0);
spin_unlock_irqrestore(&devdata->priv_lock, flags); spin_unlock_irqrestore(&devdata->priv_lock, flags);
if (devdata->server_down_complete_func)
(*devdata->server_down_complete_func)(devdata->dev, 0);
devdata->server_down = true; devdata->server_down = true;
devdata->server_change_state = false; devdata->server_change_state = false;
devdata->server_down_complete_func = NULL;
} }
/** /**
...@@ -558,10 +563,12 @@ visornic_serverdown_complete(struct work_struct *work) ...@@ -558,10 +563,12 @@ visornic_serverdown_complete(struct work_struct *work)
* Returns 0 if we scheduled the work, -EINVAL on error. * Returns 0 if we scheduled the work, -EINVAL on error.
*/ */
static int static int
visornic_serverdown(struct visornic_devdata *devdata) visornic_serverdown(struct visornic_devdata *devdata,
visorbus_state_complete_func complete_func)
{ {
if (!devdata->server_down && !devdata->server_change_state) { if (!devdata->server_down && !devdata->server_change_state) {
devdata->server_change_state = true; devdata->server_change_state = true;
devdata->server_down_complete_func = complete_func;
queue_work(visornic_serverdown_workqueue, queue_work(visornic_serverdown_workqueue,
&devdata->serverdown_completion); &devdata->serverdown_completion);
} else if (devdata->server_change_state) { } else if (devdata->server_change_state) {
...@@ -895,7 +902,7 @@ visornic_timeout_reset(struct work_struct *work) ...@@ -895,7 +902,7 @@ visornic_timeout_reset(struct work_struct *work)
return; return;
call_serverdown: call_serverdown:
visornic_serverdown(devdata); visornic_serverdown(devdata, NULL);
} }
/** /**
...@@ -1980,8 +1987,7 @@ static int visornic_pause(struct visor_device *dev, ...@@ -1980,8 +1987,7 @@ static int visornic_pause(struct visor_device *dev,
{ {
struct visornic_devdata *devdata = dev_get_drvdata(&dev->device); struct visornic_devdata *devdata = dev_get_drvdata(&dev->device);
visornic_serverdown(devdata); visornic_serverdown(devdata, complete_func);
complete_func(dev, 0);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment