From: Simon Horman <horms@kernel.org>
To: maimon.sagi@gmail.com
Cc: Simon Horman <horms@kernel.org>,
jonathan.lemon@gmail.com, vadim.fedorenko@linux.dev,
richardcochran@gmail.com, andrew+netdev@lunn.ch,
davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
pabeni@redhat.com, linux-kernel@vger.kernel.org,
netdev@vger.kernel.org
Subject: Re: [PATCH v4 1/1] ptp: ocp: add CPLD ISP support for ADVA TimeCard X1
Date: Wed, 15 Jul 2026 12:15:50 +0100 [thread overview]
Message-ID: <20260715111559.1920391-1-horms@kernel.org> (raw)
In-Reply-To: <20260708065616.16814-1-maimon.sagi@gmail.com>
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
Full review at: https://netdev-ai.bots.linux.dev/sashiko/
---
ptp: ocp: add CPLD ISP support for ADVA TimeCard X1
This commit adds sysfs interfaces on the ADVA TimeCard X1 (PCI 0x0410) to
program a Lattice MachXO3 CPLD over a shared I2C bus. It exposes an
i2c_bus_ctrl attribute for arbitrating the bus against the on-board
MicroBlaze, and a cpld_i2c_xfer binary attribute that acts as an I2C
passthrough restricted to slave addresses 0x40 and 0x74.
> diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
> index 35e911f1ad78..8df9feb030aa 100644
> --- a/drivers/ptp/ptp_ocp.c
> +++ b/drivers/ptp/ptp_ocp.c
[ ... ]
> @@ -416,6 +417,11 @@ struct ptp_ocp {
> dpll_tracker tracker;
> int signals_nr;
> int freq_in_nr;
> + /* cpld_i2c_xfer sysfs (adva_x1) */
> + struct mutex tap_i2c_lock;
> + int tap_i2c_adap_nr; /* adapter nr; -1 if absent */
> + u8 tap_i2c_rsp[21]; /* [status, read_data...] */
> + size_t tap_i2c_rsp_len;
> };
[ ... ]
> @@ -3188,6 +3194,12 @@ ptp_ocp_adva_board_init(struct ptp_ocp *bp, struct ocp_resource *r)
> ptp_ocp_nmea_out_init(bp);
> ptp_ocp_signal_init(bp);
>
> + /* tap_i2c is x1-only; the base adva variant has no CPLD I2C path. */
> + if (info->attr_groups == adva_timecard_x1_groups) {
> + mutex_init(&bp->tap_i2c_lock);
> + bp->tap_i2c_adap_nr = -1;
> + }
> +
[Critical]
Could this initialization order leave cpld_i2c_xfer non-functional in the
common configuration where xiic-i2c is already loaded when ptp_ocp probes?
The adva_x1 resource table places OCP_I2C_RESOURCE(i2c_ctrl) before the
ptp_ocp_adva_board_init entry, and ptp_ocp_register_resources iterates the
table sequentially. If xiic-i2c is built-in or preloaded,
platform_device_register_resndata() inside ptp_ocp_register_i2c() will run
the xiic-i2c probe synchronously:
ptp_ocp_register_i2c()
platform_device_register_resndata()
xiic-i2c probe -> i2c_add_adapter() -> device_add()
BUS_NOTIFY_ADD_DEVICE -> ptp_ocp_i2c_notifier_call()
WRITE_ONCE(bp->tap_i2c_adap_nr, ...->nr);
Control then returns to ptp_ocp_register_resources() which invokes
ptp_ocp_adva_board_init(), and the x1 branch above overwrites the just
cached number with -1.
No further BUS_NOTIFY_ADD_DEVICE fires for the same adapter, so
tap_i2c_adap_nr stays -1 for the device lifetime and every cpld_i2c_xfer
write() falls through i2c_get_adapter(-1) returning NULL and reports
-ENODEV.
Should tap_i2c_adap_nr be initialised earlier (before resource
registration) so the notifier's write is not clobbered?
> err = ptp_ocp_attr_group_add(bp, info->attr_groups);
> if (err)
> return err;
[ ... ]
> @@ -4224,6 +4236,210 @@ static const struct ocp_attr_group art_timecard_groups[] = {
[ ... ]
> +static ssize_t
> +ptp_ocp_cpld_i2c_write(struct file *file, struct kobject *kobj,
> + const struct bin_attribute *attr,
> + char *buf, loff_t off, size_t count)
> +{
[ ... ]
> + if (read_len > 0) {
> + u16 rd_flags = I2C_M_RD;
> +
> + if (flags & TAP_I2C_FLAG_NOSTART)
> + rd_flags |= I2C_M_NOSTART;
> + msgs[nmsgs].addr = addr;
> + msgs[nmsgs].flags = rd_flags;
> + msgs[nmsgs].len = read_len;
> + /* Allocate a DMA-safe bounce buffer if needed; see
> + * Documentation/i2c/dma-considerations.rst.
> + */
> + rdbuf = i2c_get_dma_safe_msg_buf(&msgs[nmsgs], 1);
> + if (!rdbuf) {
> + i2c_put_adapter(adap);
> + return -ENOMEM;
> + }
> + msgs[nmsgs].buf = rdbuf;
> + nmsgs++;
> + }
[High]
Can this leak the bounce buffer returned by i2c_get_dma_safe_msg_buf()?
Because I2C_M_DMA_SAFE is never set on this msg, i2c_get_dma_safe_msg_buf()
always returns a fresh kzalloc'd buffer. The code then aliases msg->buf
to that buffer:
rdbuf = i2c_get_dma_safe_msg_buf(&msgs[nmsgs], 1);
...
msgs[nmsgs].buf = rdbuf;
Later i2c_put_dma_safe_msg_buf(rdbuf, ..., ret > 0) is called, but that
helper begins with:
void i2c_put_dma_safe_msg_buf(u8 *buf, struct i2c_msg *msg, bool xferred)
{
if (!buf || buf == msg->buf)
return;
...
kfree(buf);
}
Since buf == msg->buf here, it returns without kfree().
In-tree callers (for example i2c-at91-master.c, mxs_i2c_xfer_msg,
mtk_i2c_do_transfer) keep msg->buf pointing at the caller's original
buffer and hold the bounce pointer in a separate driver variable so
buf != msg->buf at release time.
Would using a separate driver-owned pointer for the bounce buffer, or
setting msgs[nmsgs].flags |= I2C_M_DMA_SAFE and freeing with plain
kfree(), avoid the leak?
> +
> + /* Serialise transfer+publish so concurrent writers cannot overwrite
> + * each other's response in tap_i2c_rsp.
> + */
> + mutex_lock(&bp->tap_i2c_lock);
[ ... ]
> @@ -4902,6 +5125,8 @@ ptp_ocp_detach(struct ptp_ocp *bp)
> clk_hw_unregister_fixed_rate(bp->i2c_clk);
> if (bp->n_irqs)
> pci_free_irq_vectors(bp->pdev);
> + if (bp->tap_i2c_adap_nr != 0) /* initialised only on adva_x1 */
> + mutex_destroy(&bp->tap_i2c_lock);
> device_unregister(&bp->dev);
> }
[High]
Is this sentinel test reliable for deciding whether the mutex was
initialised?
mutex_init(&bp->tap_i2c_lock) only runs on adva_x1 in
ptp_ocp_adva_board_init(), but ptp_ocp_i2c_notifier_call() has no variant
filter — it walks up dev->parent looking for any driver named
KBUILD_MODNAME, matching fb, art and base adva just the same:
found:
bp = dev_get_drvdata(dev);
if (add) {
...
WRITE_ONCE(bp->tap_i2c_adap_nr, i2c_verify_adapter(child)->nr);
} else {
WRITE_ONCE(bp->tap_i2c_adap_nr, -1);
...
}
Every non-x1 board that has an OCP_I2C_RESOURCE will end up with
tap_i2c_adap_nr set to -1 (or any adapter number != 0) by the notifier,
so mutex_destroy(&bp->tap_i2c_lock) is then invoked on a never-initialised
mutex. With CONFIG_DEBUG_MUTEXES=y this runs DEBUG_LOCKS_WARN_ON() over
uninitialised memory, and under PREEMPT_RT mutex_destroy becomes a real
function that reads rt_mutex fields.
There is also the reverse case: adapter nr 0 is a legitimate I2C bus
number, so a genuine adva_x1 whose adapter happens to be 0 would skip
mutex_destroy even though the mutex was initialised.
Would a dedicated boolean flag set alongside mutex_init(), or gating on
info->attr_groups == adva_timecard_x1_groups explicitly, be a safer
condition?
> @@ -5217,11 +5442,16 @@ ptp_ocp_i2c_notifier_call(struct notifier_block *nb,
>
> found:
> bp = dev_get_drvdata(dev);
> - if (add)
> + if (add) {
> ptp_ocp_symlink(bp, child, "i2c");
> - else
> + /* Cache adapter number; cpld_i2c_xfer uses i2c_get_adapter()
> + * for a reference-counted, unbind-safe lookup.
> + */
> + WRITE_ONCE(bp->tap_i2c_adap_nr, i2c_verify_adapter(child)->nr);
> + } else {
> + WRITE_ONCE(bp->tap_i2c_adap_nr, -1); /* invalidate before free */
> sysfs_remove_link(&bp->dev.kobj, "i2c");
> -
> + }
> return 0;
> }
prev parent reply other threads:[~2026-07-15 11:17 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-08 6:56 [PATCH v4 1/1] ptp: ocp: add CPLD ISP support for ADVA TimeCard X1 Sagi Maimon
2026-07-15 11:15 ` Simon Horman [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260715111559.1920391-1-horms@kernel.org \
--to=horms@kernel.org \
--cc=andrew+netdev@lunn.ch \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=jonathan.lemon@gmail.com \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=maimon.sagi@gmail.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=richardcochran@gmail.com \
--cc=vadim.fedorenko@linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox