* [char-misc-next 1/2] mei: me: add a wrapper to set host generated data interrupt
2017-02-02 9:26 [char-misc-next 0/2] mei: reset flow fix Tomas Winkler
@ 2017-02-02 9:26 ` Tomas Winkler
2017-02-02 9:26 ` [char-misc-next 2/2] mei: me: generate an interrupt if the hw indicates reset Tomas Winkler
1 sibling, 0 replies; 3+ messages in thread
From: Tomas Winkler @ 2017-02-02 9:26 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: Alexander Usyskin, linux-kernel, Tomas Winkler
From: Alexander Usyskin <alexander.usyskin@intel.com>
Consolidate setting H_IG, an interrupt from host towards hw,
into a wrapper to eliminate code duplication.
Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
drivers/misc/mei/hw-me.c | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index befeac52c349..23294b845c42 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -140,6 +140,19 @@ static inline void mei_hcsr_set(struct mei_device *dev, u32 reg)
}
/**
+ * mei_hcsr_set_hig - set host interrupt (set H_IG)
+ *
+ * @dev: the device structure
+ */
+static inline void mei_hcsr_set_hig(struct mei_device *dev)
+{
+ u32 hcsr;
+
+ hcsr = mei_hcsr_read(dev) | H_IG;
+ mei_hcsr_set(dev, hcsr);
+}
+
+/**
* mei_me_d0i3c_read - Reads 32bit data from the D0I3C register
*
* @dev: the device structure
@@ -505,7 +518,6 @@ static int mei_me_hbuf_write(struct mei_device *dev,
unsigned long rem;
unsigned long length = header->length;
u32 *reg_buf = (u32 *)buf;
- u32 hcsr;
u32 dw_cnt;
int i;
int empty_slots;
@@ -532,8 +544,7 @@ static int mei_me_hbuf_write(struct mei_device *dev,
mei_me_hcbww_write(dev, reg);
}
- hcsr = mei_hcsr_read(dev) | H_IG;
- mei_hcsr_set(dev, hcsr);
+ mei_hcsr_set_hig(dev);
if (!mei_me_hw_is_ready(dev))
return -EIO;
@@ -580,7 +591,6 @@ static int mei_me_read_slots(struct mei_device *dev, unsigned char *buffer,
unsigned long buffer_length)
{
u32 *reg_buf = (u32 *)buffer;
- u32 hcsr;
for (; buffer_length >= sizeof(u32); buffer_length -= sizeof(u32))
*reg_buf++ = mei_me_mecbrw_read(dev);
@@ -591,8 +601,7 @@ static int mei_me_read_slots(struct mei_device *dev, unsigned char *buffer,
memcpy(reg_buf, ®, buffer_length);
}
- hcsr = mei_hcsr_read(dev) | H_IG;
- mei_hcsr_set(dev, hcsr);
+ mei_hcsr_set_hig(dev);
return 0;
}
--
2.7.4
^ permalink raw reply related [flat|nested] 3+ messages in thread* [char-misc-next 2/2] mei: me: generate an interrupt if the hw indicates reset.
2017-02-02 9:26 [char-misc-next 0/2] mei: reset flow fix Tomas Winkler
2017-02-02 9:26 ` [char-misc-next 1/2] mei: me: add a wrapper to set host generated data interrupt Tomas Winkler
@ 2017-02-02 9:26 ` Tomas Winkler
1 sibling, 0 replies; 3+ messages in thread
From: Tomas Winkler @ 2017-02-02 9:26 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: Alexander Usyskin, linux-kernel, Tomas Winkler
From: Alexander Usyskin <alexander.usyskin@intel.com>
In rare case the driver may lose connection with the device after device
reset due to a missed interrupt. The driver will unlock the flow by
generating an interrupt towards the firmware (HIG) when the device is in
the resetting state. The FW is able to ignore the interrupt during
orderly flow. The effected platforms are skylake and newer.
Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
drivers/misc/mei/hw-me.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index 23294b845c42..71216affcab1 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -394,6 +394,19 @@ static bool mei_me_hw_is_ready(struct mei_device *dev)
}
/**
+ * mei_me_hw_is_resetting - check whether the me(hw) is in reset
+ *
+ * @dev: mei device
+ * Return: bool
+ */
+static bool mei_me_hw_is_resetting(struct mei_device *dev)
+{
+ u32 mecsr = mei_me_mecsr_read(dev);
+
+ return (mecsr & ME_RST_HRA) == ME_RST_HRA;
+}
+
+/**
* mei_me_hw_ready_wait - wait until the me(hw) has turned ready
* or timeout is reached
*
@@ -1219,6 +1232,9 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id)
goto end;
}
+ if (mei_me_hw_is_resetting(dev))
+ mei_hcsr_set_hig(dev);
+
mei_me_pg_intr(dev, me_intr_src(hcsr));
/* check if we need to start the dev */
--
2.7.4
^ permalink raw reply related [flat|nested] 3+ messages in thread