i2c: emev2: avoid race when unregistering slave client
After we disabled interrupts, there might still be an active one
running. Sync before clearing the pointer to the slave device.
Fixes: c31d0a0002
("i2c: emev2: add slave support")
Reported-by: Krzysztof Adamski <krzysztof.adamski@nokia.com>
Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Reviewed-by: Krzysztof Adamski <krzysztof.adamski@nokia.com>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
This commit is contained in:
parent
7b814d852a
commit
d7437fc0d8
|
@ -69,6 +69,7 @@ struct em_i2c_device {
|
|||
struct completion msg_done;
|
||||
struct clk *sclk;
|
||||
struct i2c_client *slave;
|
||||
int irq;
|
||||
};
|
||||
|
||||
static inline void em_clear_set_bit(struct em_i2c_device *priv, u8 clear, u8 set, u8 reg)
|
||||
|
@ -339,6 +340,12 @@ static int em_i2c_unreg_slave(struct i2c_client *slave)
|
|||
|
||||
writeb(0, priv->base + I2C_OFS_SVA0);
|
||||
|
||||
/*
|
||||
* Wait for interrupt to finish. New slave irqs cannot happen because we
|
||||
* cleared the slave address and, thus, only extension codes will be
|
||||
* detected which do not use the slave ptr.
|
||||
*/
|
||||
synchronize_irq(priv->irq);
|
||||
priv->slave = NULL;
|
||||
|
||||
return 0;
|
||||
|
@ -355,7 +362,7 @@ static int em_i2c_probe(struct platform_device *pdev)
|
|||
{
|
||||
struct em_i2c_device *priv;
|
||||
struct resource *r;
|
||||
int irq, ret;
|
||||
int ret;
|
||||
|
||||
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
|
@ -390,8 +397,8 @@ static int em_i2c_probe(struct platform_device *pdev)
|
|||
|
||||
em_i2c_reset(&priv->adap);
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
ret = devm_request_irq(&pdev->dev, irq, em_i2c_irq_handler, 0,
|
||||
priv->irq = platform_get_irq(pdev, 0);
|
||||
ret = devm_request_irq(&pdev->dev, priv->irq, em_i2c_irq_handler, 0,
|
||||
"em_i2c", priv);
|
||||
if (ret)
|
||||
goto err_clk;
|
||||
|
@ -401,7 +408,8 @@ static int em_i2c_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
goto err_clk;
|
||||
|
||||
dev_info(&pdev->dev, "Added i2c controller %d, irq %d\n", priv->adap.nr, irq);
|
||||
dev_info(&pdev->dev, "Added i2c controller %d, irq %d\n", priv->adap.nr,
|
||||
priv->irq);
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
Loading…
Reference in New Issue