From cf439721f66719c6aa73b5ea23320c2f8cba100f Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Wed, 11 Oct 2023 14:01:54 +0300 Subject: mei: bus: add send and recv api with timeout Add variation of the send and recv functions on bus that define timeout. Caller can use such functions in flow that can stuck to bail out and not to put down the whole system. Signed-off-by: Alexander Usyskin Signed-off-by: Alan Previn Signed-off-by: Tomas Winkler Link: https://lore.kernel.org/r/20231011110157.247552-2-tomas.winkler@intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/bus.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 86 insertions(+), 2 deletions(-) (limited to 'drivers/misc/mei') diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index 2e65ce6bdec7..7f4ee9a47404 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -257,7 +257,7 @@ out: } /** - * mei_cldev_send_vtag - me device send with vtag (write) + * mei_cldev_send_vtag - me device send with vtag (write) * * @cldev: me client device * @buf: buffer to send @@ -278,6 +278,29 @@ ssize_t mei_cldev_send_vtag(struct mei_cl_device *cldev, const u8 *buf, } EXPORT_SYMBOL_GPL(mei_cldev_send_vtag); +/** + * mei_cldev_send_vtag_timeout - me device send with vtag and timeout (write) + * + * @cldev: me client device + * @buf: buffer to send + * @length: buffer length + * @vtag: virtual tag + * @timeout: send timeout in milliseconds, 0 for infinite timeout + * + * Return: + * * written size in bytes + * * < 0 on error + */ + +ssize_t mei_cldev_send_vtag_timeout(struct mei_cl_device *cldev, const u8 *buf, + size_t length, u8 vtag, unsigned long timeout) +{ + struct mei_cl *cl = cldev->cl; + + return __mei_cl_send_timeout(cl, buf, length, vtag, MEI_CL_IO_TX_BLOCKING, timeout); +} +EXPORT_SYMBOL_GPL(mei_cldev_send_vtag_timeout); + /** * mei_cldev_recv_vtag - client receive with vtag (read) * @@ -323,7 +346,49 @@ ssize_t mei_cldev_recv_nonblock_vtag(struct mei_cl_device *cldev, u8 *buf, EXPORT_SYMBOL_GPL(mei_cldev_recv_nonblock_vtag); /** - * mei_cldev_send - me device send (write) + * mei_cldev_recv_timeout - client receive with timeout (read) + * + * @cldev: me client device + * @buf: buffer to receive + * @length: buffer length + * @timeout: send timeout in milliseconds, 0 for infinite timeout + * + * Return: + * * read size in bytes + * * < 0 on error + */ +ssize_t mei_cldev_recv_timeout(struct mei_cl_device *cldev, u8 *buf, size_t length, + unsigned long timeout) +{ + return mei_cldev_recv_vtag_timeout(cldev, buf, length, NULL, timeout); +} +EXPORT_SYMBOL_GPL(mei_cldev_recv_timeout); + +/** + * mei_cldev_recv_vtag_timeout - client receive with vtag (read) + * + * @cldev: me client device + * @buf: buffer to receive + * @length: buffer length + * @vtag: virtual tag + * @timeout: recv timeout in milliseconds, 0 for infinite timeout + * + * Return: + * * read size in bytes + * * < 0 on error + */ + +ssize_t mei_cldev_recv_vtag_timeout(struct mei_cl_device *cldev, u8 *buf, size_t length, + u8 *vtag, unsigned long timeout) +{ + struct mei_cl *cl = cldev->cl; + + return __mei_cl_recv(cl, buf, length, vtag, 0, timeout); +} +EXPORT_SYMBOL_GPL(mei_cldev_recv_vtag_timeout); + +/** + * mei_cldev_send - me device send (write) * * @cldev: me client device * @buf: buffer to send @@ -339,6 +404,25 @@ ssize_t mei_cldev_send(struct mei_cl_device *cldev, const u8 *buf, size_t length } EXPORT_SYMBOL_GPL(mei_cldev_send); +/** + * mei_cldev_send_timeout - me device send with timeout (write) + * + * @cldev: me client device + * @buf: buffer to send + * @length: buffer length + * @timeout: send timeout in milliseconds, 0 for infinite timeout + * + * Return: + * * written size in bytes + * * < 0 on error + */ +ssize_t mei_cldev_send_timeout(struct mei_cl_device *cldev, const u8 *buf, size_t length, + unsigned long timeout) +{ + return mei_cldev_send_vtag_timeout(cldev, buf, length, 0, timeout); +} +EXPORT_SYMBOL_GPL(mei_cldev_send_timeout); + /** * mei_cldev_recv - client receive (read) * -- cgit v1.2.3 From ee5cb39348e69a61a865801970ba8fdc399335de Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Wed, 11 Oct 2023 14:01:55 +0300 Subject: mei: pxp: recover from recv fail under memory pressure 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 Signed-off-by: Alan Previn Signed-off-by: Tomas Winkler Link: https://lore.kernel.org/r/20231011110157.247552-3-tomas.winkler@intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/pxp/mei_pxp.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) (limited to 'drivers/misc/mei') diff --git a/drivers/misc/mei/pxp/mei_pxp.c b/drivers/misc/mei/pxp/mei_pxp.c index 2dcb9169e404..c6cdd6a47308 100644 --- a/drivers/misc/mei/pxp/mei_pxp.c +++ b/drivers/misc/mei/pxp/mei_pxp.c @@ -11,6 +11,7 @@ * negotiation messages to ME FW command payloads and vice versa. */ +#include #include #include #include @@ -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; -- cgit v1.2.3 From dab79a2235e5a1d6aadfeb601c84f31b5cb97141 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Wed, 11 Oct 2023 14:01:56 +0300 Subject: mei: pxp: re-enable client on errors Disable and enable mei-pxp client on errors to clean the internal state. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Link: https://lore.kernel.org/r/20231011110157.247552-4-tomas.winkler@intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/pxp/mei_pxp.c | 70 +++++++++++++++++++++++++++++------------- 1 file changed, 48 insertions(+), 22 deletions(-) (limited to 'drivers/misc/mei') diff --git a/drivers/misc/mei/pxp/mei_pxp.c b/drivers/misc/mei/pxp/mei_pxp.c index c6cdd6a47308..9875d16445bb 100644 --- a/drivers/misc/mei/pxp/mei_pxp.c +++ b/drivers/misc/mei/pxp/mei_pxp.c @@ -23,6 +23,24 @@ #include "mei_pxp.h" +static inline int mei_pxp_reenable(const struct device *dev, struct mei_cl_device *cldev) +{ + int ret; + + dev_warn(dev, "Trying to reset the channel...\n"); + ret = mei_cldev_disable(cldev); + if (ret < 0) + dev_warn(dev, "mei_cldev_disable failed. %d\n", ret); + /* + * Explicitly ignoring disable failure, + * enable may fix the states and succeed + */ + ret = mei_cldev_enable(cldev); + if (ret < 0) + dev_err(dev, "mei_cldev_enable failed. %d\n", ret); + return ret; +} + /** * mei_pxp_send_message() - Sends a PXP message to ME FW. * @dev: device corresponding to the mei_cl_device @@ -35,6 +53,7 @@ mei_pxp_send_message(struct device *dev, const void *message, size_t size) { struct mei_cl_device *cldev; ssize_t byte; + int ret; if (!dev || !message) return -EINVAL; @@ -44,10 +63,20 @@ mei_pxp_send_message(struct device *dev, const void *message, size_t size) byte = mei_cldev_send(cldev, message, size); if (byte < 0) { dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte); - return byte; + switch (byte) { + case -ENOMEM: + fallthrough; + case -ENODEV: + fallthrough; + case -ETIME: + ret = mei_pxp_reenable(dev, cldev); + if (ret) + byte = ret; + break; + } } - return 0; + return byte; } /** @@ -63,6 +92,7 @@ mei_pxp_receive_message(struct device *dev, void *buffer, size_t size) struct mei_cl_device *cldev; ssize_t byte; bool retry = false; + int ret; if (!dev || !buffer) return -EINVAL; @@ -73,26 +103,22 @@ retry: byte = mei_cldev_recv(cldev, buffer, size); if (byte < 0) { dev_dbg(dev, "mei_cldev_recv failed. %zd\n", 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); + switch (byte) { + case -ENOMEM: + /* Retry the read when pages are reclaimed */ + msleep(20); + if (!retry) { + retry = true; + goto retry; + } + fallthrough; + case -ENODEV: + fallthrough; + case -ETIME: + ret = mei_pxp_reenable(dev, cldev); + if (ret) + byte = ret; + break; } } -- cgit v1.2.3 From fb99e79ee62aaa07d9e77cb3a15c5f1ae2790e6a Mon Sep 17 00:00:00 2001 From: Alan Previn Date: Wed, 11 Oct 2023 14:01:57 +0300 Subject: mei: update mei-pxp's component interface with timeouts In debugging platform or firmware related MEI-PXP connection issues, having a timeout when clients (such as i915) calling into mei-pxp's send/receive functions have proven useful as opposed to blocking forever until the kernel triggers a watchdog panic (when platform issues are experienced). Update the mei-pxp component interface send and receive functions to take in timeouts. Signed-off-by: Alan Previn Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Link: https://lore.kernel.org/r/20231011110157.247552-5-tomas.winkler@intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/i915/pxp/intel_pxp_tee.c | 8 ++++++-- drivers/misc/mei/pxp/mei_pxp.c | 33 ++++++++++++++++++++++++++------ include/drm/i915_pxp_tee_interface.h | 6 ++++-- 3 files changed, 37 insertions(+), 10 deletions(-) (limited to 'drivers/misc/mei') diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c b/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c index 80bb00189865..dfc2878426fc 100644 --- a/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c +++ b/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c @@ -20,6 +20,8 @@ #include "intel_pxp_tee.h" #include "intel_pxp_types.h" +#define PXP_TRANSPORT_TIMEOUT_MS 5000 /* 5 sec */ + static bool is_fw_err_platform_config(u32 type) { @@ -71,13 +73,15 @@ static int intel_pxp_tee_io_message(struct intel_pxp *pxp, goto unlock; } - ret = pxp_component->ops->send(pxp_component->tee_dev, msg_in, msg_in_size); + ret = pxp_component->ops->send(pxp_component->tee_dev, msg_in, msg_in_size, + PXP_TRANSPORT_TIMEOUT_MS); if (ret) { drm_err(&i915->drm, "Failed to send PXP TEE message\n"); goto unlock; } - ret = pxp_component->ops->recv(pxp_component->tee_dev, msg_out, msg_out_max_size); + ret = pxp_component->ops->recv(pxp_component->tee_dev, msg_out, msg_out_max_size, + PXP_TRANSPORT_TIMEOUT_MS); if (ret < 0) { drm_err(&i915->drm, "Failed to receive PXP TEE message\n"); goto unlock; diff --git a/drivers/misc/mei/pxp/mei_pxp.c b/drivers/misc/mei/pxp/mei_pxp.c index 9875d16445bb..f77d78fa5054 100644 --- a/drivers/misc/mei/pxp/mei_pxp.c +++ b/drivers/misc/mei/pxp/mei_pxp.c @@ -46,10 +46,20 @@ static inline int mei_pxp_reenable(const struct device *dev, struct mei_cl_devic * @dev: device corresponding to the mei_cl_device * @message: a message buffer to send * @size: size of the message - * Return: 0 on Success, <0 on Failure + * @timeout_ms: timeout in milliseconds, zero means wait indefinitely. + * + * Returns: 0 on Success, <0 on Failure with the following defined failures. + * -ENODEV: Client was not connected. + * Caller may attempt to try again immediately. + * -ENOMEM: Internal memory allocation failure experienced. + * Caller may sleep to allow kernel reclaim before retrying. + * -EINTR : Calling thread received a signal. Caller may choose + * to abandon with the same thread id. + * -ETIME : Request is timed out. + * Caller may attempt to try again immediately. */ static int -mei_pxp_send_message(struct device *dev, const void *message, size_t size) +mei_pxp_send_message(struct device *dev, const void *message, size_t size, unsigned long timeout_ms) { struct mei_cl_device *cldev; ssize_t byte; @@ -60,7 +70,7 @@ mei_pxp_send_message(struct device *dev, const void *message, size_t size) cldev = to_mei_cl_device(dev); - byte = mei_cldev_send(cldev, message, size); + byte = mei_cldev_send_timeout(cldev, message, size, timeout_ms); if (byte < 0) { dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte); switch (byte) { @@ -84,10 +94,21 @@ mei_pxp_send_message(struct device *dev, const void *message, size_t size) * @dev: device corresponding to the mei_cl_device * @buffer: a message buffer to contain the received message * @size: size of the buffer - * Return: bytes sent on Success, <0 on Failure + * @timeout_ms: timeout in milliseconds, zero means wait indefinitely. + * + * Returns: number of bytes send on Success, <0 on Failure with the following defined failures. + * -ENODEV: Client was not connected. + * Caller may attempt to try again from send immediately. + * -ENOMEM: Internal memory allocation failure experienced. + * Caller may sleep to allow kernel reclaim before retrying. + * -EINTR : Calling thread received a signal. Caller will need to repeat calling + * (with a different owning thread) to retrieve existing unclaimed response + * (and may discard it). + * -ETIME : Request is timed out. + * Caller may attempt to try again from send immediately. */ static int -mei_pxp_receive_message(struct device *dev, void *buffer, size_t size) +mei_pxp_receive_message(struct device *dev, void *buffer, size_t size, unsigned long timeout_ms) { struct mei_cl_device *cldev; ssize_t byte; @@ -100,7 +121,7 @@ mei_pxp_receive_message(struct device *dev, void *buffer, size_t size) cldev = to_mei_cl_device(dev); retry: - byte = mei_cldev_recv(cldev, buffer, size); + byte = mei_cldev_recv_timeout(cldev, buffer, size, timeout_ms); if (byte < 0) { dev_dbg(dev, "mei_cldev_recv failed. %zd\n", byte); switch (byte) { diff --git a/include/drm/i915_pxp_tee_interface.h b/include/drm/i915_pxp_tee_interface.h index a702b6ec17f7..7d96985f2d05 100644 --- a/include/drm/i915_pxp_tee_interface.h +++ b/include/drm/i915_pxp_tee_interface.h @@ -22,8 +22,10 @@ struct i915_pxp_component_ops { */ struct module *owner; - int (*send)(struct device *dev, const void *message, size_t size); - int (*recv)(struct device *dev, void *buffer, size_t size); + int (*send)(struct device *dev, const void *message, size_t size, + unsigned long timeout_ms); + int (*recv)(struct device *dev, void *buffer, size_t size, + unsigned long timeout_ms); ssize_t (*gsc_command)(struct device *dev, u8 client_id, u32 fence_id, struct scatterlist *sg_in, size_t total_in_len, struct scatterlist *sg_out); -- cgit v1.2.3 From 64459c626b5a08aa8e8fdaa128a218215df93675 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 11 Oct 2023 10:42:59 +0300 Subject: mei: docs: use correct structures name in kdoc Fix misalignment between structures names and their kdoc in hw.h Signed-off-by: Tomas Winkler Reviewed-by: Randy Dunlap Link: https://lore.kernel.org/r/20231011074301.223879-2-tomas.winkler@intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/hw.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/misc/mei') diff --git a/drivers/misc/mei/hw.h b/drivers/misc/mei/hw.h index e910302fcd1f..3ad3080519c4 100644 --- a/drivers/misc/mei/hw.h +++ b/drivers/misc/mei/hw.h @@ -429,7 +429,7 @@ struct mei_bus_message { } __packed; /** - * struct hbm_cl_cmd - client specific host bus command + * struct mei_hbm_cl_cmd - client specific host bus command * CONNECT, DISCONNECT, and FlOW CONTROL * * @hbm_cmd: bus message command header @@ -733,7 +733,7 @@ struct hbm_dma_setup_response { } __packed; /** - * struct mei_dma_ring_ctrl - dma ring control block + * struct hbm_dma_ring_ctrl - dma ring control block * * @hbuf_wr_idx: host circular buffer write index in slots * @reserved1: reserved for alignment -- cgit v1.2.3 From d37b59c716a972834a614b093910fa345a469ee2 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 11 Oct 2023 10:43:00 +0300 Subject: mei: docs: add missing entries to kdoc in struct mei_cfg_idx Document all entries in struct mei_cfg_idx. Signed-off-by: Tomas Winkler Reviewed-by: Randy Dunlap Link: https://lore.kernel.org/r/20231011074301.223879-3-tomas.winkler@intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/hw-me.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/misc/mei') diff --git a/drivers/misc/mei/hw-me.h b/drivers/misc/mei/hw-me.h index 95cf830b7c7b..204b92af6c47 100644 --- a/drivers/misc/mei/hw-me.h +++ b/drivers/misc/mei/hw-me.h @@ -102,10 +102,14 @@ static inline bool mei_me_hw_use_polling(const struct mei_me_hw *hw) * @MEI_ME_PCH12_SPS_CFG: Platform Controller Hub Gen12 5.0 and newer * servers platforms with quirk for * SPS firmware exclusion. + * @MEI_ME_PCH12_SPS_ITOUCH_CFG: Platform Controller Hub Gen12 + * client platforms (iTouch) * @MEI_ME_PCH15_CFG: Platform Controller Hub Gen15 and newer * @MEI_ME_PCH15_SPS_CFG: Platform Controller Hub Gen15 and newer * servers platforms with quirk for * SPS firmware exclusion. + * @MEI_ME_GSC_CFG: Graphics System Controller + * @MEI_ME_GSCFI_CFG: Graphics System Controller Firmware Interface * @MEI_ME_NUM_CFG: Upper Sentinel. */ enum mei_cfg_idx { -- cgit v1.2.3 From ae4cb6bd5039a659d71632dbc2e176bf9227e294 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 11 Oct 2023 10:43:01 +0300 Subject: mei: docs: fix spelling errors Fix spelling errors in the mei code base. Signed-off-by: Tomas Winkler Reviewed-by: Randy Dunlap Link: https://lore.kernel.org/r/20231011074301.223879-4-tomas.winkler@intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/bus.c | 4 ++-- drivers/misc/mei/dma-ring.c | 2 +- drivers/misc/mei/hbm.c | 4 ++-- drivers/misc/mei/interrupt.c | 2 +- drivers/misc/mei/mei_dev.h | 4 ++-- include/linux/mei_cl_bus.h | 4 ++-- 6 files changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/misc/mei') diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index 7f4ee9a47404..f9bcff197615 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -1385,7 +1385,7 @@ static inline void mei_cl_bus_set_name(struct mei_cl_device *cldev) * @bus: mei device * @me_cl: me client * - * Return: allocated device structur or NULL on allocation failure + * Return: allocated device structure or NULL on allocation failure */ static struct mei_cl_device *mei_cl_bus_dev_alloc(struct mei_device *bus, struct mei_me_client *me_cl) @@ -1445,7 +1445,7 @@ static bool mei_cl_bus_dev_setup(struct mei_device *bus, * * @cldev: me client device * - * Return: 0 on success; < 0 on failre + * Return: 0 on success; < 0 on failure */ static int mei_cl_bus_dev_add(struct mei_cl_device *cldev) { diff --git a/drivers/misc/mei/dma-ring.c b/drivers/misc/mei/dma-ring.c index ef56f849b251..e5d800e68cb1 100644 --- a/drivers/misc/mei/dma-ring.c +++ b/drivers/misc/mei/dma-ring.c @@ -161,7 +161,7 @@ static size_t mei_dma_copy_to(struct mei_device *dev, unsigned char *buf, /** * mei_dma_ring_read() - read data from the ring * @dev: mei device - * @buf: buffer to read into: may be NULL in case of droping the data. + * @buf: buffer to read into: may be NULL in case of dropping the data. * @len: length to read. */ void mei_dma_ring_read(struct mei_device *dev, unsigned char *buf, u32 len) diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c index 12a62a911e42..15737655c896 100644 --- a/drivers/misc/mei/hbm.c +++ b/drivers/misc/mei/hbm.c @@ -111,7 +111,7 @@ void mei_hbm_idle(struct mei_device *dev) } /** - * mei_hbm_reset - reset hbm counters and book keeping data structurs + * mei_hbm_reset - reset hbm counters and book keeping data structures * * @dev: the device structure */ @@ -907,7 +907,7 @@ int mei_hbm_cl_disconnect_req(struct mei_device *dev, struct mei_cl *cl) } /** - * mei_hbm_cl_disconnect_rsp - sends disconnect respose to the FW + * mei_hbm_cl_disconnect_rsp - sends disconnect response to the FW * * @dev: the device structure * @cl: a client to disconnect from diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 0a0e984e5673..5a050f50f33e 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -72,7 +72,7 @@ static void mei_irq_discard_msg(struct mei_device *dev, struct mei_msg_hdr *hdr, discard_len = 0; } /* - * no need to check for size as it is guarantied + * no need to check for size as it is guaranteed * that length fits into rd_msg_buf */ mei_read_slots(dev, dev->rd_msg_buf, discard_len); diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index cdf8a2edf0b3..fca0094a2310 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -70,9 +70,9 @@ enum mei_dev_state { /** * enum mei_dev_pxp_mode - MEI PXP mode state * - * @MEI_DEV_PXP_DEFAULT: PCH based device, no initailization required + * @MEI_DEV_PXP_DEFAULT: PCH based device, no initialization required * @MEI_DEV_PXP_INIT: device requires initialization, send setup message to firmware - * @MEI_DEV_PXP_SETUP: device is in setup stage, waiting for firmware repsonse + * @MEI_DEV_PXP_SETUP: device is in setup stage, waiting for firmware response * @MEI_DEV_PXP_READY: device initialized */ enum mei_dev_pxp_mode { diff --git a/include/linux/mei_cl_bus.h b/include/linux/mei_cl_bus.h index b77cefd4f0c0..b38a56a13f39 100644 --- a/include/linux/mei_cl_bus.h +++ b/include/linux/mei_cl_bus.h @@ -31,11 +31,11 @@ typedef void (*mei_cldev_cb_t)(struct mei_cl_device *cldev); * @rx_work: async work to execute Rx event callback * @rx_cb: Drivers register this callback to get asynchronous ME * Rx buffer pending notifications. - * @notif_work: async work to execute FW notif event callback + * @notif_work: async work to execute FW notify event callback * @notif_cb: Drivers register this callback to get asynchronous ME * FW notification pending notifications. * - * @do_match: wheather device can be matched with a driver + * @do_match: whether the device can be matched with a driver * @is_added: device is already scanned * @priv_data: client private data */ -- cgit v1.2.3 From 5d33dc7df2ba14e963c094f0d0ab7a20ad4a5310 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 11 Oct 2023 19:48:39 -0700 Subject: misc: mei: hw.h: fix kernel-doc warnings Fix kernel-doc warnings in hw.h: hw.h:809: warning: missing initial short description on line: * struct hbm_client_dma_unmap_request hw.h:812: warning: contents before sections hw.h:825: warning: missing initial short description on line: * struct hbm_client_dma_response hw.h:828: warning: contents before sections Signed-off-by: Randy Dunlap Cc: Tomas Winkler Cc: Arnd Bergmann Cc: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20231012024845.29169-2-rdunlap@infradead.org Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/hw.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/misc/mei') diff --git a/drivers/misc/mei/hw.h b/drivers/misc/mei/hw.h index 3ad3080519c4..eb800a07a84b 100644 --- a/drivers/misc/mei/hw.h +++ b/drivers/misc/mei/hw.h @@ -806,8 +806,8 @@ struct hbm_client_dma_map_request { } __packed; /** - * struct hbm_client_dma_unmap_request - * client dma unmap request from the host to the firmware + * struct hbm_client_dma_unmap_request - client dma unmap request + * from the host to the firmware * * @hbm_cmd: bus message command header * @status: unmap status @@ -822,8 +822,8 @@ struct hbm_client_dma_unmap_request { } __packed; /** - * struct hbm_client_dma_response - * client dma unmap response from the firmware to the host + * struct hbm_client_dma_response - client dma unmap response + * from the firmware to the host * * @hbm_cmd: bus message command header * @status: command status -- cgit v1.2.3 From daa0c28d3bdeeca0be3d617feac379c4a979a5f7 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 11 Oct 2023 19:48:40 -0700 Subject: misc: mei: client.c: fix kernel-doc warnings Fix kernel-doc warnings in client.c: client.c:53: warning: contents before sections client.c:68: warning: contents before sections client.c:334: warning: contents before sections client.c:349: warning: contents before sections client.c:364: warning: contents before sections Signed-off-by: Randy Dunlap Cc: Tomas Winkler Cc: Arnd Bergmann Cc: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20231012024845.29169-3-rdunlap@infradead.org Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/client.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/misc/mei') diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 5c19097266fe..9c8fc87938a7 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -48,9 +48,9 @@ struct mei_me_client *mei_me_cl_get(struct mei_me_client *me_cl) /** * mei_me_cl_release - free me client * - * Locking: called under "dev->device_lock" lock - * * @ref: me_client refcount + * + * Locking: called under "dev->device_lock" lock */ static void mei_me_cl_release(struct kref *ref) { @@ -63,9 +63,9 @@ static void mei_me_cl_release(struct kref *ref) /** * mei_me_cl_put - decrease me client refcount and free client if necessary * - * Locking: called under "dev->device_lock" lock - * * @me_cl: me client + * + * Locking: called under "dev->device_lock" lock */ void mei_me_cl_put(struct mei_me_client *me_cl) { @@ -329,10 +329,10 @@ void mei_io_cb_free(struct mei_cl_cb *cb) /** * mei_tx_cb_enqueue - queue tx callback * - * Locking: called under "dev->device_lock" lock - * * @cb: mei callback struct * @head: an instance of list to queue on + * + * Locking: called under "dev->device_lock" lock */ static inline void mei_tx_cb_enqueue(struct mei_cl_cb *cb, struct list_head *head) @@ -344,9 +344,9 @@ static inline void mei_tx_cb_enqueue(struct mei_cl_cb *cb, /** * mei_tx_cb_dequeue - dequeue tx callback * - * Locking: called under "dev->device_lock" lock - * * @cb: mei callback struct to dequeue and free + * + * Locking: called under "dev->device_lock" lock */ static inline void mei_tx_cb_dequeue(struct mei_cl_cb *cb) { @@ -359,10 +359,10 @@ static inline void mei_tx_cb_dequeue(struct mei_cl_cb *cb) /** * mei_cl_set_read_by_fp - set pending_read flag to vtag struct for given fp * - * Locking: called under "dev->device_lock" lock - * * @cl: mei client * @fp: pointer to file structure + * + * Locking: called under "dev->device_lock" lock */ static void mei_cl_set_read_by_fp(const struct mei_cl *cl, const struct file *fp) -- cgit v1.2.3 From 4efa1e2a05d6b4340c4ca39ad0664f0e160e5d8d Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 11 Oct 2023 19:48:41 -0700 Subject: misc: mei: dma-ring.c: fix kernel-doc warnings Fix kernel-doc warnings in dma-ring.c: dma-ring.c:130: warning: No description found for return value of 'mei_dma_copy_from' dma-ring.c:150: warning: No description found for return value of 'mei_dma_copy_to' Signed-off-by: Randy Dunlap Cc: Tomas Winkler Cc: Arnd Bergmann Cc: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20231012024845.29169-4-rdunlap@infradead.org Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/dma-ring.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/misc/mei') diff --git a/drivers/misc/mei/dma-ring.c b/drivers/misc/mei/dma-ring.c index e5d800e68cb1..651e77ef82bd 100644 --- a/drivers/misc/mei/dma-ring.c +++ b/drivers/misc/mei/dma-ring.c @@ -124,6 +124,8 @@ void mei_dma_ring_reset(struct mei_device *dev) * @buf: data buffer * @offset: offset in slots. * @n: number of slots to copy. + * + * Return: number of bytes copied */ static size_t mei_dma_copy_from(struct mei_device *dev, unsigned char *buf, u32 offset, u32 n) @@ -144,6 +146,8 @@ static size_t mei_dma_copy_from(struct mei_device *dev, unsigned char *buf, * @buf: data buffer * @offset: offset in slots. * @n: number of slots to copy. + * + * Return: number of bytes copied */ static size_t mei_dma_copy_to(struct mei_device *dev, unsigned char *buf, u32 offset, u32 n) -- cgit v1.2.3 From fbe3599ee65de93cac243862df777775e23dbd83 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 11 Oct 2023 19:48:42 -0700 Subject: misc: mei: hbm.c: fix kernel-doc warnings Fix kernel-doc warnings in hbm.c: hbm.c:98: warning: No description found for return value of 'mei_hbm_write_message' Signed-off-by: Randy Dunlap Cc: Tomas Winkler Cc: Arnd Bergmann Cc: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20231012024845.29169-5-rdunlap@infradead.org Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/hbm.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/misc/mei') diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c index 15737655c896..026b1f686c16 100644 --- a/drivers/misc/mei/hbm.c +++ b/drivers/misc/mei/hbm.c @@ -91,6 +91,8 @@ static int mei_cl_conn_status_to_errno(enum mei_cl_connect_status status) * @dev: mei device * @hdr: mei header * @data: payload + * + * Return: >=0 on success, <0 on error */ static inline int mei_hbm_write_message(struct mei_device *dev, struct mei_msg_hdr *hdr, -- cgit v1.2.3 From de735e7fda11a27eb2eed81daf2a17548efb63f7 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 11 Oct 2023 19:48:43 -0700 Subject: misc: mei: hw-me.c: fix kernel-doc warnings Fix kernel-doc warnings in hw-me.c: hw-me.c:1391: warning: contents before sections hw-me.c:1475: warning: contents before sections hw-me.c:1501: warning: contents before sections hw-me.c:1525: warning: contents before sections Signed-off-by: Randy Dunlap Cc: Tomas Winkler Cc: Arnd Bergmann Cc: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20231012024845.29169-6-rdunlap@infradead.org Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/hw-me.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/misc/mei') diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c index da4ef0b51954..e72c0d78932e 100644 --- a/drivers/misc/mei/hw-me.c +++ b/drivers/misc/mei/hw-me.c @@ -1379,6 +1379,8 @@ EXPORT_SYMBOL_GPL(mei_me_irq_thread_handler); /** * mei_me_polling_thread - interrupt register polling thread * + * @_dev: mei device + * * The thread monitors the interrupt source register and calls * mei_me_irq_thread_handler() to handle the firmware * input. @@ -1388,8 +1390,6 @@ EXPORT_SYMBOL_GPL(mei_me_irq_thread_handler); * time increases yet again by MEI_POLLING_TIMEOUT_ACTIVE * up to MEI_POLLING_TIMEOUT_IDLE. * - * @_dev: mei device - * * Return: always 0 */ int mei_me_polling_thread(void *_dev) @@ -1468,12 +1468,12 @@ static const struct mei_hw_ops mei_me_hw_ops = { /** * mei_me_fw_type_nm() - check for nm sku * + * @pdev: pci device + * * Read ME FW Status register to check for the Node Manager (NM) Firmware. * The NM FW is only signaled in PCI function 0. * __Note__: Deprecated by PCH8 and newer. * - * @pdev: pci device - * * Return: true in case of NM firmware */ static bool mei_me_fw_type_nm(const struct pci_dev *pdev) @@ -1494,12 +1494,12 @@ static bool mei_me_fw_type_nm(const struct pci_dev *pdev) /** * mei_me_fw_type_sps_4() - check for sps 4.0 sku * + * @pdev: pci device + * * Read ME FW Status register to check for SPS Firmware. * The SPS FW is only signaled in the PCI function 0. * __Note__: Deprecated by SPS 5.0 and newer. * - * @pdev: pci device - * * Return: true in case of SPS firmware */ static bool mei_me_fw_type_sps_4(const struct pci_dev *pdev) @@ -1519,11 +1519,11 @@ static bool mei_me_fw_type_sps_4(const struct pci_dev *pdev) /** * mei_me_fw_type_sps_ign() - check for sps or ign sku * + * @pdev: pci device + * * Read ME FW Status register to check for SPS or IGN Firmware. * The SPS/IGN FW is only signaled in pci function 0 * - * @pdev: pci device - * * Return: true in case of SPS/IGN firmware */ static bool mei_me_fw_type_sps_ign(const struct pci_dev *pdev) -- cgit v1.2.3 From 980dcc7e43bddedb755a41a375817ee5de80222f Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 11 Oct 2023 19:48:44 -0700 Subject: misc: mei: interrupt.c: fix kernel-doc warnings Fix kernel-doc warnings in interrupt.c: interrupt.c:631: warning: contents before sections Signed-off-by: Randy Dunlap Cc: Tomas Winkler Cc: Arnd Bergmann Cc: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20231012024845.29169-7-rdunlap@infradead.org Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/interrupt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/misc/mei') diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 5a050f50f33e..b09b79fedaba 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -626,9 +626,9 @@ static void mei_connect_timeout(struct mei_cl *cl) /** * mei_schedule_stall_timer - re-arm stall_timer work * - * Schedule stall timer - * * @dev: the device structure + * + * Schedule stall timer */ void mei_schedule_stall_timer(struct mei_device *dev) { -- cgit v1.2.3 From 3b54a111bb7e558e4a40e483ded7c123fe94382c Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 11 Oct 2023 19:48:45 -0700 Subject: misc: mei: main.c: fix kernel-doc warnings Fix kernel-doc warnings in main.c: main.c:465: warning: contents before sections main.c:590: warning: missing initial short description on line: * mei_ioctl_client_notify_request - Signed-off-by: Randy Dunlap Cc: Tomas Winkler Cc: Arnd Bergmann Cc: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20231012024845.29169-8-rdunlap@infradead.org Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/misc/mei') diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index bb4e9eabda97..79e6f3c1341f 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -460,11 +460,11 @@ end: /** * mei_vt_support_check - check if client support vtags * - * Locking: called under "dev->device_lock" lock - * * @dev: mei_device * @uuid: client UUID * + * Locking: called under "dev->device_lock" lock + * * Return: * 0 - supported * -ENOTTY - no such client @@ -587,8 +587,8 @@ static int mei_ioctl_connect_vtag(struct file *file, } /** - * mei_ioctl_client_notify_request - - * propagate event notification request to client + * mei_ioctl_client_notify_request - propagate event notification + * request to client * * @file: pointer to file structure * @request: 0 - disable, 1 - enable -- cgit v1.2.3 From 34a674e99acd6ec4b541cd4c630e126ba1a4c22f Mon Sep 17 00:00:00 2001 From: Vitaly Lubart Date: Sun, 15 Oct 2023 11:05:40 +0300 Subject: mei: me: emit error only if reset was unexpected GSC devices perform legal firmware initiated resets due to state transition that may appear as unexpected to the driver. Lower the log level for those devices to debug level and save the firmware status registers. When the device comes out of the reset it is possible to check whether the resets was due to a firmware error or an exception and only than produce a warning. Signed-off-by: Vitaly Lubart Signed-off-by: Tomas Winkler Link: https://lore.kernel.org/r/20231015080540.95922-1-tomas.winkler@intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/hw-me-regs.h | 3 +++ drivers/misc/mei/hw-me.c | 61 ++++++++++++++++++++++++++++++++++++++++--- drivers/misc/mei/init.c | 27 +++++++++++++++++-- drivers/misc/mei/mei_dev.h | 47 +++++++++++++++++++++++++++++++++ 4 files changed, 133 insertions(+), 5 deletions(-) (limited to 'drivers/misc/mei') diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h index bdc65d50b945..961e5d53a27a 100644 --- a/drivers/misc/mei/hw-me-regs.h +++ b/drivers/misc/mei/hw-me-regs.h @@ -123,6 +123,9 @@ # define PCI_CFG_HFS_1_OPMODE_MSK 0xf0000 /* OP MODE Mask: SPS <= 4.0 */ # define PCI_CFG_HFS_1_OPMODE_SPS 0xf0000 /* SPS SKU : SPS <= 4.0 */ #define PCI_CFG_HFS_2 0x48 +# define PCI_CFG_HFS_2_PM_CMOFF_TO_CMX_ERROR 0x1000000 /* CMoff->CMx wake after an error */ +# define PCI_CFG_HFS_2_PM_CM_RESET_ERROR 0x5000000 /* CME reset due to exception */ +# define PCI_CFG_HFS_2_PM_EVENT_MASK 0xf000000 #define PCI_CFG_HFS_3 0x60 # define PCI_CFG_HFS_3_FW_SKU_MSK 0x00000070 # define PCI_CFG_HFS_3_FW_SKU_IGN 0x00000000 diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c index e72c0d78932e..d11a0740b47c 100644 --- a/drivers/misc/mei/hw-me.c +++ b/drivers/misc/mei/hw-me.c @@ -443,11 +443,22 @@ static void mei_gsc_pxp_check(struct mei_device *dev) struct mei_me_hw *hw = to_me_hw(dev); u32 fwsts5 = 0; - if (dev->pxp_mode == MEI_DEV_PXP_DEFAULT) + if (!kind_is_gsc(dev) && !kind_is_gscfi(dev)) return; hw->read_fws(dev, PCI_CFG_HFS_5, &fwsts5); trace_mei_pci_cfg_read(dev->dev, "PCI_CFG_HFS_5", PCI_CFG_HFS_5, fwsts5); + + if ((fwsts5 & GSC_CFG_HFS_5_BOOT_TYPE_MSK) == GSC_CFG_HFS_5_BOOT_TYPE_PXP) { + if (dev->gsc_reset_to_pxp == MEI_DEV_RESET_TO_PXP_DEFAULT) + dev->gsc_reset_to_pxp = MEI_DEV_RESET_TO_PXP_PERFORMED; + } else { + dev->gsc_reset_to_pxp = MEI_DEV_RESET_TO_PXP_DEFAULT; + } + + if (dev->pxp_mode == MEI_DEV_PXP_DEFAULT) + return; + if ((fwsts5 & GSC_CFG_HFS_5_BOOT_TYPE_MSK) == GSC_CFG_HFS_5_BOOT_TYPE_PXP) { dev_dbg(dev->dev, "pxp mode is ready 0x%08x\n", fwsts5); dev->pxp_mode = MEI_DEV_PXP_READY; @@ -482,6 +493,43 @@ static int mei_me_hw_ready_wait(struct mei_device *dev) return 0; } +/** + * mei_me_check_fw_reset - check for the firmware reset error and exception conditions + * + * @dev: mei device + */ +static void mei_me_check_fw_reset(struct mei_device *dev) +{ + struct mei_fw_status fw_status; + char fw_sts_str[MEI_FW_STATUS_STR_SZ] = {0}; + int ret; + u32 fw_pm_event = 0; + + if (!dev->saved_fw_status_flag) + goto end; + + if (dev->gsc_reset_to_pxp == MEI_DEV_RESET_TO_PXP_PERFORMED) { + ret = mei_fw_status(dev, &fw_status); + if (!ret) { + fw_pm_event = fw_status.status[1] & PCI_CFG_HFS_2_PM_EVENT_MASK; + if (fw_pm_event != PCI_CFG_HFS_2_PM_CMOFF_TO_CMX_ERROR && + fw_pm_event != PCI_CFG_HFS_2_PM_CM_RESET_ERROR) + goto end; + } else { + dev_err(dev->dev, "failed to read firmware status: %d\n", ret); + } + } + + mei_fw_status2str(&dev->saved_fw_status, fw_sts_str, sizeof(fw_sts_str)); + dev_warn(dev->dev, "unexpected reset: fw_pm_event = 0x%x, dev_state = %u fw status = %s\n", + fw_pm_event, dev->saved_dev_state, fw_sts_str); + +end: + if (dev->gsc_reset_to_pxp == MEI_DEV_RESET_TO_PXP_PERFORMED) + dev->gsc_reset_to_pxp = MEI_DEV_RESET_TO_PXP_DONE; + dev->saved_fw_status_flag = false; +} + /** * mei_me_hw_start - hw start routine * @@ -492,6 +540,8 @@ static int mei_me_hw_start(struct mei_device *dev) { int ret = mei_me_hw_ready_wait(dev); + if (kind_is_gsc(dev) || kind_is_gscfi(dev)) + mei_me_check_fw_reset(dev); if (ret) return ret; dev_dbg(dev->dev, "hw is ready\n"); @@ -1300,8 +1350,13 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id) /* check if ME wants a reset */ if (!mei_hw_is_ready(dev) && dev->dev_state != MEI_DEV_RESETTING) { - dev_warn(dev->dev, "FW not ready: resetting: dev_state = %d pxp = %d\n", - dev->dev_state, dev->pxp_mode); + if (kind_is_gsc(dev) || kind_is_gscfi(dev)) { + dev_dbg(dev->dev, "FW not ready: resetting: dev_state = %d\n", + dev->dev_state); + } else { + dev_warn(dev->dev, "FW not ready: resetting: dev_state = %d\n", + dev->dev_state); + } if (dev->dev_state == MEI_DEV_POWERING_DOWN || dev->dev_state == MEI_DEV_POWER_DOWN) mei_cl_all_disconnect(dev); diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index c35e005b26be..8ef2b1df8ac7 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c @@ -89,6 +89,22 @@ void mei_cancel_work(struct mei_device *dev) } EXPORT_SYMBOL_GPL(mei_cancel_work); +static void mei_save_fw_status(struct mei_device *dev) +{ + struct mei_fw_status fw_status; + int ret; + + ret = mei_fw_status(dev, &fw_status); + if (ret) { + dev_err(dev->dev, "failed to read firmware status: %d\n", ret); + return; + } + + dev->saved_dev_state = dev->dev_state; + dev->saved_fw_status_flag = true; + memcpy(&dev->saved_fw_status, &fw_status, sizeof(fw_status)); +} + /** * mei_reset - resets host and fw. * @@ -109,8 +125,14 @@ int mei_reset(struct mei_device *dev) char fw_sts_str[MEI_FW_STATUS_STR_SZ]; mei_fw_status_str(dev, fw_sts_str, MEI_FW_STATUS_STR_SZ); - dev_warn(dev->dev, "unexpected reset: dev_state = %s fw status = %s\n", - mei_dev_state_str(state), fw_sts_str); + if (kind_is_gsc(dev) || kind_is_gscfi(dev)) { + dev_dbg(dev->dev, "unexpected reset: dev_state = %s fw status = %s\n", + mei_dev_state_str(state), fw_sts_str); + mei_save_fw_status(dev); + } else { + dev_warn(dev->dev, "unexpected reset: dev_state = %s fw status = %s\n", + mei_dev_state_str(state), fw_sts_str); + } } mei_clear_interrupts(dev); @@ -394,6 +416,7 @@ void mei_device_init(struct mei_device *dev, dev->open_handle_count = 0; dev->pxp_mode = MEI_DEV_PXP_DEFAULT; + dev->gsc_reset_to_pxp = MEI_DEV_RESET_TO_PXP_DEFAULT; /* * Reserving the first client ID diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index fca0094a2310..37d7fb15cad7 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -82,6 +82,19 @@ enum mei_dev_pxp_mode { MEI_DEV_PXP_READY = 3, }; +/** + * enum mei_dev_reset_to_pxp - reset to PXP mode performed + * + * @MEI_DEV_RESET_TO_PXP_DEFAULT: before reset + * @MEI_DEV_RESET_TO_PXP_PERFORMED: reset performed + * @MEI_DEV_RESET_TO_PXP_DONE: reset processed + */ +enum mei_dev_reset_to_pxp { + MEI_DEV_RESET_TO_PXP_DEFAULT = 0, + MEI_DEV_RESET_TO_PXP_PERFORMED = 1, + MEI_DEV_RESET_TO_PXP_DONE = 2, +}; + const char *mei_dev_state_str(int state); enum mei_file_transaction_states { @@ -534,6 +547,11 @@ struct mei_dev_timeouts { * * @dbgfs_dir : debugfs mei root directory * + * @saved_fw_status : saved firmware status + * @saved_dev_state : saved device state + * @saved_fw_status_flag : flag indicating that firmware status was saved + * @gsc_reset_to_pxp : state of reset to the PXP mode + * * @ops: : hw specific operations * @hw : hw specific data */ @@ -630,6 +648,11 @@ struct mei_device { struct dentry *dbgfs_dir; #endif /* CONFIG_DEBUG_FS */ + struct mei_fw_status saved_fw_status; + enum mei_dev_state saved_dev_state; + bool saved_fw_status_flag; + enum mei_dev_reset_to_pxp gsc_reset_to_pxp; + const struct mei_hw_ops *ops; char hw[] __aligned(sizeof(void *)); }; @@ -874,5 +897,29 @@ static inline ssize_t mei_fw_status_str(struct mei_device *dev, return ret; } +/** + * kind_is_gsc - checks whether the device is gsc + * + * @dev: the device structure + * + * Return: whether the device is gsc + */ +static inline bool kind_is_gsc(struct mei_device *dev) +{ + /* check kind for NULL because it may be not set, like at the fist call to hw_start */ + return dev->kind && (strcmp(dev->kind, "gsc") == 0); +} +/** + * kind_is_gscfi - checks whether the device is gscfi + * + * @dev: the device structure + * + * Return: whether the device is gscfi + */ +static inline bool kind_is_gscfi(struct mei_device *dev) +{ + /* check kind for NULL because it may be not set, like at the fist call to hw_start */ + return dev->kind && (strcmp(dev->kind, "gscfi") == 0); +} #endif -- cgit v1.2.3