Commit a4307fe4 authored by Alexander Usyskin's avatar Alexander Usyskin Committed by Greg Kroah-Hartman

mei: clean write queues and wake waiters on disconnect

Clean write and write_waiting queues in disconnect.
Requests in those queues are stale and processing will lead to
fat warnings.

In multi thread operations on disconnect and in FW disconnect case -
write/read/event waiters should end wait and return error.
Wake all waiters for disconnecting client to achieve that.

Drop wake all and write queue clean on reset,
as now we waking all waiters and cleaning write queues on disconnect.
No need to do it twice.
Signed-off-by: default avatarAlexander Usyskin <alexander.usyskin@intel.com>
Signed-off-by: default avatarTomas Winkler <tomas.winkler@intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 0faf6a3b
...@@ -719,6 +719,33 @@ bool mei_hbuf_acquire(struct mei_device *dev) ...@@ -719,6 +719,33 @@ bool mei_hbuf_acquire(struct mei_device *dev)
return true; return true;
} }
/**
* mei_cl_wake_all - wake up readers, writers and event waiters so
* they can be interrupted
*
* @cl: host client
*/
static void mei_cl_wake_all(struct mei_cl *cl)
{
struct mei_device *dev = cl->dev;
/* synchronized under device mutex */
if (waitqueue_active(&cl->rx_wait)) {
cl_dbg(dev, cl, "Waking up reading client!\n");
wake_up_interruptible(&cl->rx_wait);
}
/* synchronized under device mutex */
if (waitqueue_active(&cl->tx_wait)) {
cl_dbg(dev, cl, "Waking up writing client!\n");
wake_up_interruptible(&cl->tx_wait);
}
/* synchronized under device mutex */
if (waitqueue_active(&cl->ev_wait)) {
cl_dbg(dev, cl, "Waking up waiting for event clients!\n");
wake_up_interruptible(&cl->ev_wait);
}
}
/** /**
* mei_cl_set_disconnected - set disconnected state and clear * mei_cl_set_disconnected - set disconnected state and clear
* associated states and resources * associated states and resources
...@@ -734,8 +761,11 @@ void mei_cl_set_disconnected(struct mei_cl *cl) ...@@ -734,8 +761,11 @@ void mei_cl_set_disconnected(struct mei_cl *cl)
return; return;
cl->state = MEI_FILE_DISCONNECTED; cl->state = MEI_FILE_DISCONNECTED;
mei_io_list_free(&dev->write_list, cl);
mei_io_list_free(&dev->write_waiting_list, cl);
mei_io_list_flush(&dev->ctrl_rd_list, cl); mei_io_list_flush(&dev->ctrl_rd_list, cl);
mei_io_list_flush(&dev->ctrl_wr_list, cl); mei_io_list_flush(&dev->ctrl_wr_list, cl);
mei_cl_wake_all(cl);
cl->mei_flow_ctrl_creds = 0; cl->mei_flow_ctrl_creds = 0;
cl->timer_count = 0; cl->timer_count = 0;
...@@ -1770,44 +1800,3 @@ void mei_cl_all_disconnect(struct mei_device *dev) ...@@ -1770,44 +1800,3 @@ void mei_cl_all_disconnect(struct mei_device *dev)
list_for_each_entry(cl, &dev->file_list, link) list_for_each_entry(cl, &dev->file_list, link)
mei_cl_set_disconnected(cl); mei_cl_set_disconnected(cl);
} }
/**
* mei_cl_all_wakeup - wake up all readers and writers they can be interrupted
*
* @dev: mei device
*/
void mei_cl_all_wakeup(struct mei_device *dev)
{
struct mei_cl *cl;
list_for_each_entry(cl, &dev->file_list, link) {
if (waitqueue_active(&cl->rx_wait)) {
cl_dbg(dev, cl, "Waking up reading client!\n");
wake_up_interruptible(&cl->rx_wait);
}
if (waitqueue_active(&cl->tx_wait)) {
cl_dbg(dev, cl, "Waking up writing client!\n");
wake_up_interruptible(&cl->tx_wait);
}
/* synchronized under device mutex */
if (waitqueue_active(&cl->ev_wait)) {
cl_dbg(dev, cl, "Waking up waiting for event clients!\n");
wake_up_interruptible(&cl->ev_wait);
}
}
}
/**
* mei_cl_all_write_clear - clear all pending writes
*
* @dev: mei device
*/
void mei_cl_all_write_clear(struct mei_device *dev)
{
mei_io_list_free(&dev->write_list, NULL);
mei_io_list_free(&dev->write_waiting_list, NULL);
}
...@@ -238,8 +238,6 @@ int mei_cl_notify_get(struct mei_cl *cl, bool block, bool *notify_ev); ...@@ -238,8 +238,6 @@ int mei_cl_notify_get(struct mei_cl *cl, bool block, bool *notify_ev);
void mei_cl_notify(struct mei_cl *cl); void mei_cl_notify(struct mei_cl *cl);
void mei_cl_all_disconnect(struct mei_device *dev); void mei_cl_all_disconnect(struct mei_device *dev);
void mei_cl_all_wakeup(struct mei_device *dev);
void mei_cl_all_write_clear(struct mei_device *dev);
#define MEI_CL_FMT "cl:host=%02d me=%02d " #define MEI_CL_FMT "cl:host=%02d me=%02d "
#define MEI_CL_PRM(cl) (cl)->host_client_id, mei_cl_me_id(cl) #define MEI_CL_PRM(cl) (cl)->host_client_id, mei_cl_me_id(cl)
......
...@@ -148,13 +148,8 @@ int mei_reset(struct mei_device *dev) ...@@ -148,13 +148,8 @@ int mei_reset(struct mei_device *dev)
state != MEI_DEV_POWER_UP) { state != MEI_DEV_POWER_UP) {
/* remove all waiting requests */ /* remove all waiting requests */
mei_cl_all_write_clear(dev);
mei_cl_all_disconnect(dev); mei_cl_all_disconnect(dev);
/* wake up all readers and writers so they can be interrupted */
mei_cl_all_wakeup(dev);
/* remove entry if already in list */ /* remove entry if already in list */
dev_dbg(dev->dev, "remove iamthif from the file list.\n"); dev_dbg(dev->dev, "remove iamthif from the file list.\n");
mei_cl_unlink(&dev->iamthif_cl); mei_cl_unlink(&dev->iamthif_cl);
......
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