Skip to content

Commit 3259e2d

Browse files
Ychamegregkh
authored andcommitted
i2c: bcm-iproc: Fix bcm_iproc_i2c_isr deadlock issue
commit 4caf4cb upstream. 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: 9a10387 ("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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent b788ad3 commit 3259e2d

File tree

1 file changed

+7
-4
lines changed

1 file changed

+7
-4
lines changed

drivers/i2c/busses/i2c-bcm-iproc.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -240,13 +240,14 @@ static inline u32 iproc_i2c_rd_reg(struct bcm_iproc_i2c_dev *iproc_i2c,
240240
u32 offset)
241241
{
242242
u32 val;
243+
unsigned long flags;
243244

244245
if (iproc_i2c->idm_base) {
245-
spin_lock(&iproc_i2c->idm_lock);
246+
spin_lock_irqsave(&iproc_i2c->idm_lock, flags);
246247
writel(iproc_i2c->ape_addr_mask,
247248
iproc_i2c->idm_base + IDM_CTRL_DIRECT_OFFSET);
248249
val = readl(iproc_i2c->base + offset);
249-
spin_unlock(&iproc_i2c->idm_lock);
250+
spin_unlock_irqrestore(&iproc_i2c->idm_lock, flags);
250251
} else {
251252
val = readl(iproc_i2c->base + offset);
252253
}
@@ -257,12 +258,14 @@ static inline u32 iproc_i2c_rd_reg(struct bcm_iproc_i2c_dev *iproc_i2c,
257258
static inline void iproc_i2c_wr_reg(struct bcm_iproc_i2c_dev *iproc_i2c,
258259
u32 offset, u32 val)
259260
{
261+
unsigned long flags;
262+
260263
if (iproc_i2c->idm_base) {
261-
spin_lock(&iproc_i2c->idm_lock);
264+
spin_lock_irqsave(&iproc_i2c->idm_lock, flags);
262265
writel(iproc_i2c->ape_addr_mask,
263266
iproc_i2c->idm_base + IDM_CTRL_DIRECT_OFFSET);
264267
writel(val, iproc_i2c->base + offset);
265-
spin_unlock(&iproc_i2c->idm_lock);
268+
spin_unlock_irqrestore(&iproc_i2c->idm_lock, flags);
266269
} else {
267270
writel(val, iproc_i2c->base + offset);
268271
}

0 commit comments

Comments
 (0)