mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-22 07:53:11 -05:00
i2c-for-6.13-rc8
This pull request fixes: - a ref leak in the I2C core - the remove notification in the address translator - a missing error check in the pinctrl demuxer (plus a typo fix) - handling NAK when Linux is testunit target - handling NAK for the Renesas R-Car controller when it is a target -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEOZGx6rniZ1Gk92RdFA3kzBSgKbYFAmeJ/6QACgkQFA3kzBSg KbY4pA/+LCdKS27uHKgCmnHM7xBsQBZhKI8cfQmBH9ssfV5xJi5DMcqCGZRxss5b Q14MP/3Mi3J5gVvDuadtN6yXQxiIAMBHvdAW11QYF/gKL34SR0QOzluEmf+b5Q6l leesgsJMXuJIXSrH/ZMXAyyDqOcNSQtaTIrY7HV9gCL3yW/xNdDPxBq6+K5bcCst p2FaWMO2RSSkaoDKnhEIWPM7cwGTt3RyeUz1CjDeGxzqHFXj8PKBg803ubbNZ0qz A+uv+UdJ7cH1pmGFY+rH7UEopPOAe52pQ+1k8YyirAFsqmwne0bLrK/ZBwEoA6Dd 7h9OTPhnKKAnb5o983JM5AZ7ApQgBlQPChjT64Yv3xUI38WDJDcvZ119REwUQJ4O FgdGyHxwd++mUJFo3IKJx3D0fQ3XkDD1vX0ZvqFT5fWL9LBdZfS0HeX+pbQxzn9C LVpuFGOJhd48el/iulQNyhRTysrHi03nKpXKswJ/QdViSMap9XV8i/OAhO8q/Liv JBDAHTMQjDZeReWYHX1tyoQabhAUlFP4cBrpsOJqkc5xGEcevBpAoglC/Qw8UBZ+ BTwUXWHM83bnoPh2QQsFPeW0QOEBVpWe//RA9c5P/OzS/E1L22T2mK0EY1oHta1t qFw4Ku3GZ/sMcfTtODlvquUiRX9LKFdjz4U7Wl8TX3r1BKgxsIA= =8f0F -----END PGP SIGNATURE----- Merge tag 'i2c-for-6.13-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux Pull i2c fixes from Wolfram Sang: - fix ref leak in the I2C core - fix remove notification in the address translator - missing error check in the pinctrl demuxer (plus a typo fix) - fix NAK handling when Linux is testunit target - fix NAK handling for the Renesas R-Car controller when it is a target * tag 'i2c-for-6.13-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: i2c: testunit: on errors, repeat NACK until STOP i2c: rcar: fix NACK handling when being a target i2c: mux: demux-pinctrl: correct comment i2c: mux: demux-pinctrl: check initial mux selection, too i2c: atr: Fix client detach i2c: core: fix reference leak in i2c_register_adapter()
This commit is contained in:
commit
5e74b9bf26
5 changed files with 36 additions and 12 deletions
|
@ -130,6 +130,8 @@
|
|||
#define ID_P_PM_BLOCKED BIT(31)
|
||||
#define ID_P_MASK GENMASK(31, 27)
|
||||
|
||||
#define ID_SLAVE_NACK BIT(0)
|
||||
|
||||
enum rcar_i2c_type {
|
||||
I2C_RCAR_GEN1,
|
||||
I2C_RCAR_GEN2,
|
||||
|
@ -166,6 +168,7 @@ struct rcar_i2c_priv {
|
|||
int irq;
|
||||
|
||||
struct i2c_client *host_notify_client;
|
||||
u8 slave_flags;
|
||||
};
|
||||
|
||||
#define rcar_i2c_priv_to_dev(p) ((p)->adap.dev.parent)
|
||||
|
@ -655,6 +658,7 @@ static bool rcar_i2c_slave_irq(struct rcar_i2c_priv *priv)
|
|||
{
|
||||
u32 ssr_raw, ssr_filtered;
|
||||
u8 value;
|
||||
int ret;
|
||||
|
||||
ssr_raw = rcar_i2c_read(priv, ICSSR) & 0xff;
|
||||
ssr_filtered = ssr_raw & rcar_i2c_read(priv, ICSIER);
|
||||
|
@ -670,7 +674,10 @@ static bool rcar_i2c_slave_irq(struct rcar_i2c_priv *priv)
|
|||
rcar_i2c_write(priv, ICRXTX, value);
|
||||
rcar_i2c_write(priv, ICSIER, SDE | SSR | SAR);
|
||||
} else {
|
||||
i2c_slave_event(priv->slave, I2C_SLAVE_WRITE_REQUESTED, &value);
|
||||
ret = i2c_slave_event(priv->slave, I2C_SLAVE_WRITE_REQUESTED, &value);
|
||||
if (ret)
|
||||
priv->slave_flags |= ID_SLAVE_NACK;
|
||||
|
||||
rcar_i2c_read(priv, ICRXTX); /* dummy read */
|
||||
rcar_i2c_write(priv, ICSIER, SDR | SSR | SAR);
|
||||
}
|
||||
|
@ -683,18 +690,21 @@ static bool rcar_i2c_slave_irq(struct rcar_i2c_priv *priv)
|
|||
if (ssr_filtered & SSR) {
|
||||
i2c_slave_event(priv->slave, I2C_SLAVE_STOP, &value);
|
||||
rcar_i2c_write(priv, ICSCR, SIE | SDBS); /* clear our NACK */
|
||||
priv->slave_flags &= ~ID_SLAVE_NACK;
|
||||
rcar_i2c_write(priv, ICSIER, SAR);
|
||||
rcar_i2c_write(priv, ICSSR, ~SSR & 0xff);
|
||||
}
|
||||
|
||||
/* master wants to write to us */
|
||||
if (ssr_filtered & SDR) {
|
||||
int ret;
|
||||
|
||||
value = rcar_i2c_read(priv, ICRXTX);
|
||||
ret = i2c_slave_event(priv->slave, I2C_SLAVE_WRITE_RECEIVED, &value);
|
||||
/* Send NACK in case of error */
|
||||
rcar_i2c_write(priv, ICSCR, SIE | SDBS | (ret < 0 ? FNA : 0));
|
||||
if (ret)
|
||||
priv->slave_flags |= ID_SLAVE_NACK;
|
||||
|
||||
/* Send NACK in case of error, but it will come 1 byte late :( */
|
||||
rcar_i2c_write(priv, ICSCR, SIE | SDBS |
|
||||
(priv->slave_flags & ID_SLAVE_NACK ? FNA : 0));
|
||||
rcar_i2c_write(priv, ICSSR, ~SDR & 0xff);
|
||||
}
|
||||
|
||||
|
|
|
@ -412,7 +412,7 @@ static int i2c_atr_bus_notifier_call(struct notifier_block *nb,
|
|||
dev_name(dev), ret);
|
||||
break;
|
||||
|
||||
case BUS_NOTIFY_DEL_DEVICE:
|
||||
case BUS_NOTIFY_REMOVED_DEVICE:
|
||||
i2c_atr_detach_client(client->adapter, client);
|
||||
break;
|
||||
|
||||
|
|
|
@ -1562,6 +1562,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
|
|||
res = device_add(&adap->dev);
|
||||
if (res) {
|
||||
pr_err("adapter '%s': can't register device (%d)\n", adap->name, res);
|
||||
put_device(&adap->dev);
|
||||
goto out_list;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ enum testunit_regs {
|
|||
|
||||
enum testunit_flags {
|
||||
TU_FLAG_IN_PROCESS,
|
||||
TU_FLAG_NACK,
|
||||
};
|
||||
|
||||
struct testunit_data {
|
||||
|
@ -90,8 +91,10 @@ static int i2c_slave_testunit_slave_cb(struct i2c_client *client,
|
|||
|
||||
switch (event) {
|
||||
case I2C_SLAVE_WRITE_REQUESTED:
|
||||
if (test_bit(TU_FLAG_IN_PROCESS, &tu->flags))
|
||||
return -EBUSY;
|
||||
if (test_bit(TU_FLAG_IN_PROCESS | TU_FLAG_NACK, &tu->flags)) {
|
||||
ret = -EBUSY;
|
||||
break;
|
||||
}
|
||||
|
||||
memset(tu->regs, 0, TU_NUM_REGS);
|
||||
tu->reg_idx = 0;
|
||||
|
@ -99,8 +102,10 @@ static int i2c_slave_testunit_slave_cb(struct i2c_client *client,
|
|||
break;
|
||||
|
||||
case I2C_SLAVE_WRITE_RECEIVED:
|
||||
if (test_bit(TU_FLAG_IN_PROCESS, &tu->flags))
|
||||
return -EBUSY;
|
||||
if (test_bit(TU_FLAG_IN_PROCESS | TU_FLAG_NACK, &tu->flags)) {
|
||||
ret = -EBUSY;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tu->reg_idx < TU_NUM_REGS)
|
||||
tu->regs[tu->reg_idx] = *val;
|
||||
|
@ -129,6 +134,8 @@ static int i2c_slave_testunit_slave_cb(struct i2c_client *client,
|
|||
* here because we still need them in the workqueue!
|
||||
*/
|
||||
tu->reg_idx = 0;
|
||||
|
||||
clear_bit(TU_FLAG_NACK, &tu->flags);
|
||||
break;
|
||||
|
||||
case I2C_SLAVE_READ_PROCESSED:
|
||||
|
@ -151,6 +158,10 @@ static int i2c_slave_testunit_slave_cb(struct i2c_client *client,
|
|||
break;
|
||||
}
|
||||
|
||||
/* If an error occurred somewhen, we NACK everything until next STOP */
|
||||
if (ret)
|
||||
set_bit(TU_FLAG_NACK, &tu->flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ static int i2c_demux_activate_master(struct i2c_demux_pinctrl_priv *priv, u32 ne
|
|||
}
|
||||
|
||||
/*
|
||||
* Check if there are pinctrl states at all. Note: we cant' use
|
||||
* Check if there are pinctrl states at all. Note: we can't use
|
||||
* devm_pinctrl_get_select() because we need to distinguish between
|
||||
* the -ENODEV from devm_pinctrl_get() and pinctrl_lookup_state().
|
||||
*/
|
||||
|
@ -261,7 +261,9 @@ static int i2c_demux_pinctrl_probe(struct platform_device *pdev)
|
|||
pm_runtime_no_callbacks(&pdev->dev);
|
||||
|
||||
/* switch to first parent as active master */
|
||||
i2c_demux_activate_master(priv, 0);
|
||||
err = i2c_demux_activate_master(priv, 0);
|
||||
if (err)
|
||||
goto err_rollback;
|
||||
|
||||
err = device_create_file(&pdev->dev, &dev_attr_available_masters);
|
||||
if (err)
|
||||
|
|
Loading…
Reference in a new issue