Skip to content

Commit 4caf4cb

Browse files
Ychamewsakernel
authored andcommitted
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: 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>
1 parent 7d71196 commit 4caf4cb

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
@@ -233,13 +233,14 @@ static inline u32 iproc_i2c_rd_reg(struct bcm_iproc_i2c_dev *iproc_i2c,
233233
u32 offset)
234234
{
235235
u32 val;
236+
unsigned long flags;
236237

237238
if (iproc_i2c->idm_base) {
238-
spin_lock(&iproc_i2c->idm_lock);
239+
spin_lock_irqsave(&iproc_i2c->idm_lock, flags);
239240
writel(iproc_i2c->ape_addr_mask,
240241
iproc_i2c->idm_base + IDM_CTRL_DIRECT_OFFSET);
241242
val = readl(iproc_i2c->base + offset);
242-
spin_unlock(&iproc_i2c->idm_lock);
243+
spin_unlock_irqrestore(&iproc_i2c->idm_lock, flags);
243244
} else {
244245
val = readl(iproc_i2c->base + offset);
245246
}
@@ -250,12 +251,14 @@ static inline u32 iproc_i2c_rd_reg(struct bcm_iproc_i2c_dev *iproc_i2c,
250251
static inline void iproc_i2c_wr_reg(struct bcm_iproc_i2c_dev *iproc_i2c,
251252
u32 offset, u32 val)
252253
{
254+
unsigned long flags;
255+
253256
if (iproc_i2c->idm_base) {
254-
spin_lock(&iproc_i2c->idm_lock);
257+
spin_lock_irqsave(&iproc_i2c->idm_lock, flags);
255258
writel(iproc_i2c->ape_addr_mask,
256259
iproc_i2c->idm_base + IDM_CTRL_DIRECT_OFFSET);
257260
writel(val, iproc_i2c->base + offset);
258-
spin_unlock(&iproc_i2c->idm_lock);
261+
spin_unlock_irqrestore(&iproc_i2c->idm_lock, flags);
259262
} else {
260263
writel(val, iproc_i2c->base + offset);
261264
}

0 commit comments

Comments
 (0)