mei: me: d0i3: enable d0i3 interrupts
D0i3 adds additional interrupt reason bit, therefore we add a variable
intr_source to save the interrupt causes for further dispatching.
The interrupt cause is saved in the irq quick handler to achieve
unified behavior for both MSI enabled and shared interrupt platforms.
Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h
index 4c8f05e..8793ccc 100644
--- a/drivers/misc/mei/hw-me-regs.h
+++ b/drivers/misc/mei/hw-me-regs.h
@@ -166,6 +166,10 @@
/* Host D0I3 Interrupt Status */
#define H_D0I3C_IS 0x00000040
+/* H_CSR masks */
+#define H_CSR_IE_MASK (H_IE | H_D0I3C_IE)
+#define H_CSR_IS_MASK (H_IS | H_D0I3C_IS)
+
/* register bits of ME_CSR_HA (ME Control Status Host Access register) */
/* ME CB (Circular Buffer) Depth HRA (Host Read Access) - host read only
access to ME_CBD */
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index 17d6894..910af88 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -134,7 +134,7 @@
*/
static inline void mei_hcsr_set(struct mei_device *dev, u32 reg)
{
- reg &= ~H_IS;
+ reg &= ~H_CSR_IS_MASK;
mei_hcsr_write(dev, reg);
}
@@ -216,7 +216,7 @@
{
u32 hcsr = mei_hcsr_read(dev);
- if ((hcsr & H_IS) == H_IS)
+ if (hcsr & H_CSR_IS_MASK)
mei_hcsr_write(dev, hcsr);
}
/**
@@ -228,7 +228,7 @@
{
u32 hcsr = mei_hcsr_read(dev);
- hcsr |= H_IE;
+ hcsr |= H_CSR_IE_MASK;
mei_hcsr_set(dev, hcsr);
}
@@ -241,7 +241,7 @@
{
u32 hcsr = mei_hcsr_read(dev);
- hcsr &= ~H_IE;
+ hcsr &= ~H_CSR_IE_MASK;
mei_hcsr_set(dev, hcsr);
}
@@ -285,12 +285,12 @@
hcsr = mei_hcsr_read(dev);
}
- hcsr |= H_RST | H_IG | H_IS;
+ hcsr |= H_RST | H_IG | H_CSR_IS_MASK;
if (intr_enable)
- hcsr |= H_IE;
+ hcsr |= H_CSR_IE_MASK;
else
- hcsr &= ~H_IE;
+ hcsr &= ~H_CSR_IE_MASK;
dev->recvd_hw_ready = false;
mei_hcsr_write(dev, hcsr);
@@ -322,7 +322,7 @@
{
u32 hcsr = mei_hcsr_read(dev);
- hcsr |= H_IE | H_IG | H_RDY;
+ hcsr |= H_CSR_IE_MASK | H_IG | H_RDY;
mei_hcsr_set(dev, hcsr);
}
@@ -767,16 +767,20 @@
*
* Return: irqreturn_t
*/
-
irqreturn_t mei_me_irq_quick_handler(int irq, void *dev_id)
{
- struct mei_device *dev = (struct mei_device *) dev_id;
- u32 hcsr = mei_hcsr_read(dev);
+ struct mei_device *dev = (struct mei_device *)dev_id;
+ struct mei_me_hw *hw = to_me_hw(dev);
+ u32 hcsr;
- if ((hcsr & H_IS) != H_IS)
+ hcsr = mei_hcsr_read(dev);
+ if (!(hcsr & H_CSR_IS_MASK))
return IRQ_NONE;
- /* clear H_IS bit in H_CSR */
+ hw->intr_source = hcsr & H_CSR_IS_MASK;
+ dev_dbg(dev->dev, "interrupt source 0x%08X.\n", hw->intr_source);
+
+ /* clear H_IS and H_D0I3C_IS bits in H_CSR to clear the interrupts */
mei_hcsr_write(dev, hcsr);
return IRQ_WAKE_THREAD;
@@ -804,11 +808,6 @@
mutex_lock(&dev->device_lock);
mei_io_list_init(&complete_list);
- /* Ack the interrupt here
- * In case of MSI we don't go through the quick handler */
- if (pci_dev_msi_enabled(to_pci_dev(dev->dev)))
- mei_clear_interrupts(dev);
-
/* 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.\n");
diff --git a/drivers/misc/mei/hw-me.h b/drivers/misc/mei/hw-me.h
index cf64847..2ee14dc 100644
--- a/drivers/misc/mei/hw-me.h
+++ b/drivers/misc/mei/hw-me.h
@@ -51,12 +51,14 @@
*
* @cfg: per device generation config and ops
* @mem_addr: io memory address
+ * @intr_source: interrupt source
* @pg_state: power gating state
* @d0i3_supported: di03 support
*/
struct mei_me_hw {
const struct mei_cfg *cfg;
void __iomem *mem_addr;
+ u32 intr_source;
enum mei_pg_state pg_state;
bool d0i3_supported;
};
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
index 23f71f5..7fee74a 100644
--- a/drivers/misc/mei/pci-me.c
+++ b/drivers/misc/mei/pci-me.c
@@ -128,6 +128,7 @@
const struct mei_cfg *cfg = (struct mei_cfg *)(ent->driver_data);
struct mei_device *dev;
struct mei_me_hw *hw;
+ unsigned int irqflags;
int err;
@@ -180,17 +181,12 @@
pci_enable_msi(pdev);
/* request and enable interrupt */
- if (pci_dev_msi_enabled(pdev))
- err = request_threaded_irq(pdev->irq,
- NULL,
- mei_me_irq_thread_handler,
- IRQF_ONESHOT, KBUILD_MODNAME, dev);
- else
- err = request_threaded_irq(pdev->irq,
+ irqflags = pci_dev_msi_enabled(pdev) ? IRQF_ONESHOT : IRQF_SHARED;
+
+ err = request_threaded_irq(pdev->irq,
mei_me_irq_quick_handler,
mei_me_irq_thread_handler,
- IRQF_SHARED, KBUILD_MODNAME, dev);
-
+ irqflags, KBUILD_MODNAME, dev);
if (err) {
dev_err(&pdev->dev, "request_threaded_irq failure. irq = %d\n",
pdev->irq);
@@ -319,6 +315,7 @@
{
struct pci_dev *pdev = to_pci_dev(device);
struct mei_device *dev;
+ unsigned int irqflags;
int err;
dev = pci_get_drvdata(pdev);
@@ -327,17 +324,13 @@
pci_enable_msi(pdev);
+ irqflags = pci_dev_msi_enabled(pdev) ? IRQF_ONESHOT : IRQF_SHARED;
+
/* request and enable interrupt */
- if (pci_dev_msi_enabled(pdev))
- err = request_threaded_irq(pdev->irq,
- NULL,
- mei_me_irq_thread_handler,
- IRQF_ONESHOT, KBUILD_MODNAME, dev);
- else
- err = request_threaded_irq(pdev->irq,
+ err = request_threaded_irq(pdev->irq,
mei_me_irq_quick_handler,
mei_me_irq_thread_handler,
- IRQF_SHARED, KBUILD_MODNAME, dev);
+ irqflags, KBUILD_MODNAME, dev);
if (err) {
dev_err(&pdev->dev, "request_threaded_irq failed: irq = %d.\n",