| From foo@baz Wed Sep 21 12:45:10 CEST 2016 |
| From: Florian Fainelli <f.fainelli@gmail.com> |
| Date: Wed, 24 Aug 2016 11:01:20 -0700 |
| Subject: net: dsa: bcm_sf2: Fix race condition while unmasking interrupts |
| |
| From: Florian Fainelli <f.fainelli@gmail.com> |
| |
| |
| [ Upstream commit 4f101c47791cdcb831b3ef1f831b1cc51e4fe03c ] |
| |
| We kept shadow copies of which interrupt sources we have enabled and |
| disabled, but due to an order bug in how intrl2_mask_clear was defined, |
| we could run into the following scenario: |
| |
| CPU0 CPU1 |
| intrl2_1_mask_clear(..) |
| sets INTRL2_CPU_MASK_CLEAR |
| bcm_sf2_switch_1_isr |
| read INTRL2_CPU_STATUS and masks with stale |
| irq1_mask value |
| updates irq1_mask value |
| |
| Which would make us loop again and again trying to process and interrupt |
| we are not clearing since our copy of whether it was enabled before |
| still indicates it was not. Fix this by updating the shadow copy first, |
| and then unasking at the HW level. |
| |
| Fixes: 246d7f773c13 ("net: dsa: add Broadcom SF2 switch driver") |
| Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/net/dsa/bcm_sf2.h | 2 +- |
| 1 file changed, 1 insertion(+), 1 deletion(-) |
| |
| --- a/drivers/net/dsa/bcm_sf2.h |
| +++ b/drivers/net/dsa/bcm_sf2.h |
| @@ -187,8 +187,8 @@ static inline void name##_writeq(struct |
| static inline void intrl2_##which##_mask_clear(struct bcm_sf2_priv *priv, \ |
| u32 mask) \ |
| { \ |
| - intrl2_##which##_writel(priv, mask, INTRL2_CPU_MASK_CLEAR); \ |
| priv->irq##which##_mask &= ~(mask); \ |
| + intrl2_##which##_writel(priv, mask, INTRL2_CPU_MASK_CLEAR); \ |
| } \ |
| static inline void intrl2_##which##_mask_set(struct bcm_sf2_priv *priv, \ |
| u32 mask) \ |