diff options
author | Tomas Winkler <tomas.winkler@intel.com> | 2013-03-10 13:56:07 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-03-15 11:18:08 -0700 |
commit | 68f8ea184bf7a552b59a38c4b0c7dc243822d2d5 (patch) | |
tree | a116d50a78d748dabe04e3d45e07adf25e2ef0e0 /drivers/misc/mei | |
parent | 7cb035d9e619a8d20f5d3b9791f8cb5160d19e70 (diff) |
mei: ME hardware reset needs to be synchronized
This fixes failure during initialization on Lynx Point LP devices.
ME driver needs to release the device from the reset
only after the FW has completed its flow and indicated
it by delivering an interrupt to the host.
This is the correct behavior for all the ME devices yet the
the previous versions are less susceptive to the implementation
that ignored FW reset completion indication.
We add mei_me_hw_reset_release function which is called
after reset from the interrupt thread or directly
from mei_reset during power down.
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc/mei')
-rw-r--r-- | drivers/misc/mei/hw-me.c | 29 |
1 files changed, 20 insertions, 9 deletions
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c index 45ea7185c003..642c6223fa6c 100644 --- a/drivers/misc/mei/hw-me.c +++ b/drivers/misc/mei/hw-me.c @@ -152,6 +152,20 @@ static void mei_me_intr_disable(struct mei_device *dev) } /** + * mei_me_hw_reset_release - release device from the reset + * + * @dev: the device structure + */ +static void mei_me_hw_reset_release(struct mei_device *dev) +{ + struct mei_me_hw *hw = to_me_hw(dev); + u32 hcsr = mei_hcsr_read(hw); + + hcsr |= H_IG; + hcsr &= ~H_RST; + mei_hcsr_set(hw, hcsr); +} +/** * mei_me_hw_reset - resets fw via mei csr register. * * @dev: the device structure @@ -169,18 +183,14 @@ static void mei_me_hw_reset(struct mei_device *dev, bool intr_enable) if (intr_enable) hcsr |= H_IE; else - hcsr &= ~H_IE; - - mei_hcsr_set(hw, hcsr); - - hcsr = mei_hcsr_read(hw) | H_IG; - hcsr &= ~H_RST; + hcsr |= ~H_IE; mei_hcsr_set(hw, hcsr); - hcsr = mei_hcsr_read(hw); + if (dev->dev_state == MEI_DEV_POWER_DOWN) + mei_me_hw_reset_release(dev); - dev_dbg(&dev->pdev->dev, "current HCSR = 0x%08x.\n", hcsr); + dev_dbg(&dev->pdev->dev, "current HCSR = 0x%08x.\n", mei_hcsr_read(hw)); } /** @@ -466,7 +476,8 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id) mutex_unlock(&dev->device_lock); return IRQ_HANDLED; } else { - dev_dbg(&dev->pdev->dev, "FW not ready.\n"); + dev_dbg(&dev->pdev->dev, "Reset Completed.\n"); + mei_me_hw_reset_release(dev); mutex_unlock(&dev->device_lock); return IRQ_HANDLED; } |