i2c: bcm-iproc: Fix bcm_iproc_i2c_isr deadlock issue

iproc_i2c_rd_reg() and iproc_i2c_wr_reg() are called from both
interrupt context (e.g. bcm_iproc_i2c_isr) and process context
(e.g. bcm_iproc_i2c_suspend). Therefore, interrupts should be
disabled to avoid potential deadlock. To prevent this scenario,
use spin_lock_irqsave().

Fixes: 9a1038728037 ("i2c: iproc: add NIC I2C support")
Signed-off-by: Chengfeng Ye <dg573847474@gmail.com>
Acked-by: Ray Jui <ray.jui@broadcom.com>
Reviewed-by: Andi Shyti <andi.shyti@kernel.org>
Signed-off-by: Wolfram Sang <wsa@kernel.org>

authored by Chengfeng Ye and committed by Wolfram Sang 4caf4cb1 7d711966

+7 -4
+7 -4
drivers/i2c/busses/i2c-bcm-iproc.c
··· 233 u32 offset) 234 { 235 u32 val; 236 237 if (iproc_i2c->idm_base) { 238 - spin_lock(&iproc_i2c->idm_lock); 239 writel(iproc_i2c->ape_addr_mask, 240 iproc_i2c->idm_base + IDM_CTRL_DIRECT_OFFSET); 241 val = readl(iproc_i2c->base + offset); 242 - spin_unlock(&iproc_i2c->idm_lock); 243 } else { 244 val = readl(iproc_i2c->base + offset); 245 } ··· 251 static inline void iproc_i2c_wr_reg(struct bcm_iproc_i2c_dev *iproc_i2c, 252 u32 offset, u32 val) 253 { 254 if (iproc_i2c->idm_base) { 255 - spin_lock(&iproc_i2c->idm_lock); 256 writel(iproc_i2c->ape_addr_mask, 257 iproc_i2c->idm_base + IDM_CTRL_DIRECT_OFFSET); 258 writel(val, iproc_i2c->base + offset); 259 - spin_unlock(&iproc_i2c->idm_lock); 260 } else { 261 writel(val, iproc_i2c->base + offset); 262 }
··· 233 u32 offset) 234 { 235 u32 val; 236 + unsigned long flags; 237 238 if (iproc_i2c->idm_base) { 239 + spin_lock_irqsave(&iproc_i2c->idm_lock, flags); 240 writel(iproc_i2c->ape_addr_mask, 241 iproc_i2c->idm_base + IDM_CTRL_DIRECT_OFFSET); 242 val = readl(iproc_i2c->base + offset); 243 + spin_unlock_irqrestore(&iproc_i2c->idm_lock, flags); 244 } else { 245 val = readl(iproc_i2c->base + offset); 246 } ··· 250 static inline void iproc_i2c_wr_reg(struct bcm_iproc_i2c_dev *iproc_i2c, 251 u32 offset, u32 val) 252 { 253 + unsigned long flags; 254 + 255 if (iproc_i2c->idm_base) { 256 + spin_lock_irqsave(&iproc_i2c->idm_lock, flags); 257 writel(iproc_i2c->ape_addr_mask, 258 iproc_i2c->idm_base + IDM_CTRL_DIRECT_OFFSET); 259 writel(val, iproc_i2c->base + offset); 260 + spin_unlock_irqrestore(&iproc_i2c->idm_lock, flags); 261 } else { 262 writel(val, iproc_i2c->base + offset); 263 }