From: Tomas Winkler <tomas.winkler@intel.com>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Alexander Usyskin <alexander.usyskin@intel.com>,
Vitaly Lubart <vitaly.lubart@intel.com>,
linux-kernel@vger.kernel.org,
Tomas Winkler <tomas.winkler@intel.com>
Subject: [char-misc-next 2/2] mei: add empty handlers for ops functions
Date: Wed, 18 Oct 2023 13:10:24 +0300 [thread overview]
Message-ID: <20231018101024.271437-2-tomas.winkler@intel.com> (raw)
In-Reply-To: <20231018101024.271437-1-tomas.winkler@intel.com>
From: Vitaly Lubart <vitaly.lubart@intel.com>
When the offline bit is set and the device is being removed
we should prevent the driver from accessing the hardware because
at this stage the hardware may be no longer available.
Replace the operation handlers with the empty ones to ensure
no hardware registers are being accessed by the driver.
Signed-off-by: Vitaly Lubart <vitaly.lubart@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
drivers/misc/mei/gsc-me.c | 293 ++++++++++++++++++++++++++++++++++++++
1 file changed, 293 insertions(+)
diff --git a/drivers/misc/mei/gsc-me.c b/drivers/misc/mei/gsc-me.c
index 6be8f1cc052c13be3607432f..8ff2aae245aca26aee11e0b4 100644
--- a/drivers/misc/mei/gsc-me.c
+++ b/drivers/misc/mei/gsc-me.c
@@ -23,6 +23,11 @@
#define MEI_GSC_RPM_TIMEOUT 500
+static inline bool mei_gsc_hw_is_unavailable(const struct device *dev)
+{
+ return dev->offline;
+}
+
static int mei_gsc_read_hfs(const struct mei_device *dev, int where, u32 *val)
{
struct mei_me_hw *hw = to_me_hw(dev);
@@ -43,6 +48,291 @@ static void mei_gsc_set_ext_op_mem(const struct mei_me_hw *hw, struct resource *
iowrite32(limit, hw->mem_addr + H_GSC_EXT_OP_MEM_LIMIT_REG);
}
+/**
+ * mei_gsc_mecbrw_read_null - read 32bit data from ME circular buffer (empty implementation)
+ * read window register
+ *
+ * @dev: the device structure
+ *
+ * Return: always 0
+ */
+static inline u32 mei_gsc_mecbrw_read_null(const struct mei_device *dev)
+{
+ return 0;
+}
+
+/**
+ * mei_gsc_trc_status_null - read trc status register (empty implementation)
+ *
+ * @dev: mei device
+ * @trc: trc status register value
+ *
+ * Return: always 0
+ */
+static int mei_gsc_trc_status_null(struct mei_device *dev, u32 *trc)
+{
+ *trc = 0;
+ return 0;
+}
+
+/**
+ * mei_gsc_fw_status_null - read fw status register from pci config space (empty implementation)
+ *
+ * @dev: mei device
+ * @fw_status: fw status register values
+ *
+ * Return: always 0
+ */
+static int mei_gsc_fw_status_null(struct mei_device *dev,
+ struct mei_fw_status *fw_status)
+{
+ return 0;
+}
+
+/**
+ * mei_gsc_hw_config_null - configure hw dependent settings (empty implementation)
+ *
+ * @dev: mei device
+ *
+ * Return: always 0
+ *
+ */
+static int mei_gsc_hw_config_null(struct mei_device *dev)
+{
+ return 0;
+}
+
+/**
+ * mei_gsc_pg_state_null - translate internal pg state (empty implementation)
+ * to the mei power gating state
+ *
+ * @dev: mei device
+ *
+ * Return: always MEI_PG_OFF
+ */
+static inline enum mei_pg_state mei_gsc_pg_state_null(struct mei_device *dev)
+{
+ return MEI_PG_OFF;
+}
+
+/**
+ * mei_gsc_intr_clear_null - clear and stop interrupts (empty implementation)
+ *
+ * @dev: the device structure
+ */
+static void mei_gsc_intr_clear_null(struct mei_device *dev)
+{
+}
+
+/**
+ * mei_gsc_intr_enable_null - enables mei device interrupts (empty implementation)
+ *
+ * @dev: the device structure
+ */
+static void mei_gsc_intr_enable_null(struct mei_device *dev)
+{
+}
+
+/**
+ * mei_gsc_intr_disable_null - disables mei device interrupts (empty implementation)
+ *
+ * @dev: the device structure
+ */
+static void mei_gsc_intr_disable_null(struct mei_device *dev)
+{
+}
+
+/**
+ * mei_gsc_synchronize_irq_null - wait for pending IRQ handlers (empty implementation)
+ *
+ * @dev: the device structure
+ */
+static void mei_gsc_synchronize_irq_null(struct mei_device *dev)
+{
+}
+
+/**
+ * mei_gsc_host_is_ready_null - check whether the host has turned ready (empty implementation)
+ *
+ * @dev: mei device
+ * Return: always true
+ */
+static bool mei_gsc_host_is_ready_null(struct mei_device *dev)
+{
+ return true;
+}
+
+/**
+ * mei_gsc_hw_start_null - hw start routine (empty implementation)
+ *
+ * @dev: mei device
+ * Return: always 0
+ */
+static int mei_gsc_hw_start_null(struct mei_device *dev)
+{
+ return 0;
+}
+
+/**
+ * mei_gsc_hbuf_is_empty_null - checks if host buffer is empty (empty implementation)
+ *
+ * @dev: the device structure
+ *
+ * Return: always true
+ */
+static bool mei_gsc_hbuf_is_empty_null(struct mei_device *dev)
+{
+ return true;
+}
+
+/**
+ * mei_gsc_hbuf_empty_slots_null - counts write empty slots (empty implementation)
+ *
+ * @dev: the device structure
+ *
+ * Return: always -EOVERFLOW
+ */
+static int mei_gsc_hbuf_empty_slots_null(struct mei_device *dev)
+{
+ return -EOVERFLOW;
+}
+
+/**
+ * mei_gsc_hbuf_depth_null - returns depth of the hw buffer (empty implementation)
+ *
+ * @dev: the device structure
+ *
+ * Return: always 1
+ */
+static u32 mei_gsc_hbuf_depth_null(const struct mei_device *dev)
+{
+ return 0;
+}
+
+/**
+ * mei_gsc_hbuf_write_null - writes a message to host hw buffer (empty implementation)
+ *
+ * @dev: the device structure
+ * @hdr: header of message
+ * @hdr_len: header length in bytes: must be multiplication of a slot (4bytes)
+ * @data: payload
+ * @data_len: payload length in bytes
+ *
+ * Return: always 0
+ */
+static int mei_gsc_hbuf_write_null(struct mei_device *dev,
+ const void *hdr, size_t hdr_len,
+ const void *data, size_t data_len)
+{
+ return 0;
+}
+
+/**
+ * mei_gsc_count_full_read_slots_null - counts read full slots (empty implementation)
+ *
+ * @dev: the device structure
+ *
+ * Return: always -EOVERFLOW
+ */
+static int mei_gsc_count_full_read_slots_null(struct mei_device *dev)
+{
+ return -EOVERFLOW;
+}
+
+/**
+ * mei_gsc_read_slots_null - reads a message from mei device (empty implementation)
+ *
+ * @dev: the device structure
+ * @buffer: message buffer will be written
+ * @buffer_length: message size will be read
+ *
+ * Return: always 0
+ */
+static int mei_gsc_read_slots_null(struct mei_device *dev, unsigned char *buffer,
+ unsigned long buffer_length)
+{
+ return 0;
+}
+
+/**
+ * mei_gsc_pg_in_transition_null - is device now in pg transition (empty implementation)
+ *
+ * @dev: the device structure
+ *
+ * Return: always false
+ */
+static bool mei_gsc_pg_in_transition_null(struct mei_device *dev)
+{
+ return false;
+}
+
+/**
+ * mei_gsc_pg_is_enabled_null - detect if PG is supported by HW (empty implementation)
+ *
+ * @dev: the device structure
+ *
+ * Return: always false
+ */
+static bool mei_gsc_pg_is_enabled_null(struct mei_device *dev)
+{
+ return false;
+}
+
+/**
+ * mei_gsc_hw_is_ready_null - check whether the me(hw) has turned ready (empty implementation)
+ *
+ * @dev: mei device
+ * Return: always true
+ */
+static bool mei_gsc_hw_is_ready_null(struct mei_device *dev)
+{
+ return true;
+}
+
+/**
+ * mei_gsc_hw_reset_null - resets fw via mei csr register (empty implementation)
+ *
+ * @dev: the device structure
+ * @intr_enable: if interrupt should be enabled after reset.
+ *
+ * Return: always 0
+ */
+static int mei_gsc_hw_reset_null(struct mei_device *dev, bool intr_enable)
+{
+ return 0;
+}
+
+static const struct mei_hw_ops mei_gsc_hw_ops_null = {
+ .trc_status = mei_gsc_trc_status_null,
+ .fw_status = mei_gsc_fw_status_null,
+ .pg_state = mei_gsc_pg_state_null,
+
+ .host_is_ready = mei_gsc_host_is_ready_null,
+
+ .hw_is_ready = mei_gsc_hw_is_ready_null,
+ .hw_reset = mei_gsc_hw_reset_null,
+ .hw_config = mei_gsc_hw_config_null,
+ .hw_start = mei_gsc_hw_start_null,
+
+ .pg_in_transition = mei_gsc_pg_in_transition_null,
+ .pg_is_enabled = mei_gsc_pg_is_enabled_null,
+
+ .intr_clear = mei_gsc_intr_clear_null,
+ .intr_enable = mei_gsc_intr_enable_null,
+ .intr_disable = mei_gsc_intr_disable_null,
+ .synchronize_irq = mei_gsc_synchronize_irq_null,
+
+ .hbuf_free_slots = mei_gsc_hbuf_empty_slots_null,
+ .hbuf_is_ready = mei_gsc_hbuf_is_empty_null,
+ .hbuf_depth = mei_gsc_hbuf_depth_null,
+
+ .write = mei_gsc_hbuf_write_null,
+
+ .rdbuf_full_slots = mei_gsc_count_full_read_slots_null,
+ .read_hdr = mei_gsc_mecbrw_read_null,
+ .read = mei_gsc_read_slots_null
+};
+
static int mei_gsc_probe(struct auxiliary_device *aux_dev,
const struct auxiliary_device_id *aux_dev_id)
{
@@ -149,6 +439,9 @@ static void mei_gsc_remove(struct auxiliary_device *aux_dev)
hw = to_me_hw(dev);
+ if (mei_gsc_hw_is_unavailable(&aux_dev->dev))
+ dev->ops = &mei_gsc_hw_ops_null;
+
mei_stop(dev);
hw = to_me_hw(dev);
--
2.41.0
next prev parent reply other threads:[~2023-10-18 10:10 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-10-18 10:10 [char-misc-next 1/2] mei: add check for offline bit in every register access Tomas Winkler
2023-10-18 10:10 ` Tomas Winkler [this message]
2023-10-21 21:05 ` Greg Kroah-Hartman
2023-11-27 13:38 ` Greg Kroah-Hartman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20231018101024.271437-2-tomas.winkler@intel.com \
--to=tomas.winkler@intel.com \
--cc=alexander.usyskin@intel.com \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=vitaly.lubart@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®