diff options
author | Tomas Winkler <tomas.winkler@intel.com> | 2014-05-12 05:19:39 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-05-27 17:15:25 -0400 |
commit | b04ada92ffaabb868497a1fce8e4f6bf74e5488f (patch) | |
tree | 74280522778df71778cb3f1d924adc8a9717e3c1 /drivers/misc/mei/hw-me.c | |
parent | 84b3294a40c87e5c8bdaf05d9d3c3aff7e320453 (diff) |
mei: me: fix hw ready reset flow
We cleared H_RST for H_CSR on spurious interrupt generated when ME_RDY
while cleared and not while ME_RDY is set. The spurious interrupt
is not delivered on all platforms in this case the
driver may fail to initialize.
Cc: stable@vger.kernel.org
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc/mei/hw-me.c')
-rw-r--r-- | drivers/misc/mei/hw-me.c | 9 |
1 files changed, 6 insertions, 3 deletions
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c index a31bc4c36cca..ac76a6377794 100644 --- a/drivers/misc/mei/hw-me.c +++ b/drivers/misc/mei/hw-me.c | |||
@@ -181,6 +181,9 @@ static void mei_me_hw_reset_release(struct mei_device *dev) | |||
181 | hcsr |= H_IG; | 181 | hcsr |= H_IG; |
182 | hcsr &= ~H_RST; | 182 | hcsr &= ~H_RST; |
183 | mei_hcsr_set(hw, hcsr); | 183 | mei_hcsr_set(hw, hcsr); |
184 | |||
185 | /* complete this write before we set host ready on another CPU */ | ||
186 | mmiowb(); | ||
184 | } | 187 | } |
185 | /** | 188 | /** |
186 | * mei_me_hw_reset - resets fw via mei csr register. | 189 | * mei_me_hw_reset - resets fw via mei csr register. |
@@ -218,6 +221,7 @@ static int mei_me_hw_reset(struct mei_device *dev, bool intr_enable) | |||
218 | static void mei_me_host_set_ready(struct mei_device *dev) | 221 | static void mei_me_host_set_ready(struct mei_device *dev) |
219 | { | 222 | { |
220 | struct mei_me_hw *hw = to_me_hw(dev); | 223 | struct mei_me_hw *hw = to_me_hw(dev); |
224 | hw->host_hw_state = mei_hcsr_read(hw); | ||
221 | hw->host_hw_state |= H_IE | H_IG | H_RDY; | 225 | hw->host_hw_state |= H_IE | H_IG | H_RDY; |
222 | mei_hcsr_set(hw, hw->host_hw_state); | 226 | mei_hcsr_set(hw, hw->host_hw_state); |
223 | } | 227 | } |
@@ -646,14 +650,13 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id) | |||
646 | /* check if we need to start the dev */ | 650 | /* check if we need to start the dev */ |
647 | if (!mei_host_is_ready(dev)) { | 651 | if (!mei_host_is_ready(dev)) { |
648 | if (mei_hw_is_ready(dev)) { | 652 | if (mei_hw_is_ready(dev)) { |
653 | mei_me_hw_reset_release(dev); | ||
649 | dev_dbg(&dev->pdev->dev, "we need to start the dev.\n"); | 654 | dev_dbg(&dev->pdev->dev, "we need to start the dev.\n"); |
650 | 655 | ||
651 | dev->recvd_hw_ready = true; | 656 | dev->recvd_hw_ready = true; |
652 | wake_up_interruptible(&dev->wait_hw_ready); | 657 | wake_up_interruptible(&dev->wait_hw_ready); |
653 | } else { | 658 | } else { |
654 | 659 | dev_dbg(&dev->pdev->dev, "Spurious Interrupt\n"); | |
655 | dev_dbg(&dev->pdev->dev, "Reset Completed.\n"); | ||
656 | mei_me_hw_reset_release(dev); | ||
657 | } | 660 | } |
658 | goto end; | 661 | goto end; |
659 | } | 662 | } |