Skip to content

Commit

Permalink
mei: pxp: recover from recv fail under memory pressure
Browse files Browse the repository at this point in the history
Under memory pressure recv fails due to kmalloc failure,
and if drivers(pxp) retry send/receive, send blocks
indefinitely.
Send without recv leaves the channel in a bad state.

Retry send attempt after small timeout and reset the channel if
the retry failed on kmalloc failure too.

Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com>
Signed-off-by: Alan Previn <alan.previn.teres.alexis@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Link: https://lore.kernel.org/r/20231011110157.247552-3-tomas.winkler@intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
ausyskin authored and gregkh committed Oct 18, 2023
1 parent cf43972 commit ee5cb39
Showing 1 changed file with 24 additions and 1 deletion.
25 changes: 24 additions & 1 deletion drivers/misc/mei/pxp/mei_pxp.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
* negotiation messages to ME FW command payloads and vice versa.
*/

#include <linux/delay.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/mei.h>
Expand Down Expand Up @@ -61,16 +62,38 @@ mei_pxp_receive_message(struct device *dev, void *buffer, size_t size)
{
struct mei_cl_device *cldev;
ssize_t byte;
bool retry = false;

if (!dev || !buffer)
return -EINVAL;

cldev = to_mei_cl_device(dev);

retry:
byte = mei_cldev_recv(cldev, buffer, size);
if (byte < 0) {
dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte);
return byte;
if (byte != -ENOMEM)
return byte;

/* Retry the read when pages are reclaimed */
msleep(20);
if (!retry) {
retry = true;
goto retry;
} else {
dev_warn(dev, "No memory on data receive after retry, trying to reset the channel...\n");
byte = mei_cldev_disable(cldev);
if (byte < 0)
dev_warn(dev, "mei_cldev_disable failed. %zd\n", byte);
/*
* Explicitly ignoring disable failure,
* enable may fix the states and succeed
*/
byte = mei_cldev_enable(cldev);
if (byte < 0)
dev_err(dev, "mei_cldev_enable failed. %zd\n", byte);
}
}

return byte;
Expand Down

0 comments on commit ee5cb39

Please sign in to comment.