From: Andy Shevchenko <andriy.shevchenko@intel.com>
To: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Cc: devicetree@vger.kernel.org, linux-i2c@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-media@vger.kernel.org,
Hans Verkuil <hverkuil-cisco@xs4all.nl>,
Jacopo Mondi <jacopo@jmondi.org>,
Kieran Bingham <kieran.bingham@ideasonboard.com>,
Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
Luca Ceresoli <luca@lucaceresoli.net>,
Mark Rutland <mark.rutland@arm.com>,
Matti Vaittinen <Matti.Vaittinen@fi.rohmeurope.com>,
Mauro Carvalho Chehab <mchehab@kernel.org>,
Peter Rosin <peda@axentia.se>, Rob Herring <robh+dt@kernel.org>,
Sakari Ailus <sakari.ailus@linux.intel.com>,
Vladimir Zapolskiy <vz@mleia.com>,
Wolfram Sang <wsa@the-dreams.de>,
satish.nagireddy@getcruise.com
Subject: Re: [PATCH v4 2/8] i2c: add I2C Address Translator (ATR) support
Date: Tue, 1 Nov 2022 16:30:53 +0200 [thread overview]
Message-ID: <Y2EtnSNqBOfGRDMO@smile.fi.intel.com> (raw)
In-Reply-To: <20221101132032.1542416-3-tomi.valkeinen@ideasonboard.com>
On Tue, Nov 01, 2022 at 03:20:26PM +0200, Tomi Valkeinen wrote:
> From: Luca Ceresoli <luca@lucaceresoli.net>
>
> An ATR is a device that looks similar to an i2c-mux: it has an I2C
> slave "upstream" port and N master "downstream" ports, and forwards
> transactions from upstream to the appropriate downstream port. But is
> is different in that the forwarded transaction has a different slave
> address. The address used on the upstream bus is called the "alias"
> and is (potentially) different from the physical slave address of the
> downstream chip.
>
> Add a helper file (just like i2c-mux.c for a mux or switch) to allow
> implementing ATR features in a device driver. The helper takes care or
> adapter creation/destruction and translates addresses at each transaction.
...
> i2c-topology
> muxes/i2c-mux-gpio
> i2c-sysfs
> + muxes/i2c-atr
Doesn't make sense to group muxes/*, that they are following each other?
...
> +I2C ADDRESS TRANSLATOR (ATR)
> +M: Luca Ceresoli <luca@lucaceresoli.net>
Hmm... Are you going to maintain this? Or Review? Why not?
> +L: linux-i2c@vger.kernel.org
> +S: Maintained
> +F: drivers/i2c/i2c-atr.c
> +F: include/linux/i2c-atr.h
...
> + void *new_buf = kmalloc_array(num, sizeof(chan->orig_addrs[0]),
> + GFP_KERNEL);
> + if (new_buf == NULL)
> + return -ENOMEM;
Isn't it better to write this as
void *new_buf;
new_buf = kmalloc_array(num, sizeof(chan->orig_addrs[0]), GFP_KERNEL);
if (!new_buf)
return -ENOMEM;
Remarks:
- note the style of the conditional
- why is it void?
Also, does it make sense to use krealloc_array() or is it complete replacement
of the data?
> + kfree(chan->orig_addrs);
> + chan->orig_addrs = new_buf;
> + chan->orig_addrs_size = num;
...
> +static void i2c_atr_unmap_msgs(struct i2c_atr_chan *chan, struct i2c_msg msgs[],
> + int num)
[] in the function parameter is longer than * and actually doesn't make
difference in C. Ditto for the rest of similar cases.
...
> +static int i2c_atr_smbus_xfer(struct i2c_adapter *adap, u16 addr,
> + unsigned short flags, char read_write, u8 command,
> + int size, union i2c_smbus_data *data)
Can flags be fixed size (yes I understand that in our case short would probably
never be different to u16, but for the sake of clearness)?
...
> +static int i2c_atr_attach_client(struct i2c_adapter *adapter,
> + const struct i2c_board_info *info,
> + const struct i2c_client *client)
> +{
> + struct i2c_atr_chan *chan = adapter->algo_data;
> + struct i2c_atr *atr = chan->atr;
> + struct i2c_atr_cli2alias_pair *c2a;
> + u16 alias_id = 0;
Can we split assignment from the definition and locate it closer to the first
use?
> + int ret = 0;
Useless assignment.
> +
> + c2a = kzalloc(sizeof(*c2a), GFP_KERNEL);
> + if (!c2a)
> + return -ENOMEM;
> +
> + ret = atr->ops->attach_client(atr, chan->chan_id, info, client,
> + &alias_id);
On one line looks better.
> + if (ret)
> + goto err_free;
> + if (alias_id == 0) {
> + ret = -EINVAL;
> + goto err_free;
> + }
> +
> + c2a->client = client;
> + c2a->alias = alias_id;
> + list_add(&c2a->node, &chan->alias_list);
> +
> + return 0;
> +
> +err_free:
> + kfree(c2a);
> + return ret;
> +}
...
> +int i2c_atr_add_adapter(struct i2c_atr *atr, u32 chan_id,
> + struct fwnode_handle *bus_handle)
> +{
> + struct i2c_adapter *parent = atr->parent;
> + struct device *dev = atr->dev;
> + struct i2c_atr_chan *chan;
> + char *symlink_name;
> + int ret;
> +
> + if (chan_id >= atr->max_adapters) {
> + dev_err(dev, "No room for more i2c-atr adapters\n");
> + return -EINVAL;
> + }
> +
> + if (atr->adapter[chan_id]) {
> + dev_err(dev, "Adapter %d already present\n", chan_id);
> + return -EEXIST;
> + }
> +
> + chan = kzalloc(sizeof(*chan), GFP_KERNEL);
> + if (!chan)
> + return -ENOMEM;
> +
> + chan->atr = atr;
> + chan->chan_id = chan_id;
> + INIT_LIST_HEAD(&chan->alias_list);
> + mutex_init(&chan->orig_addrs_lock);
> +
> + snprintf(chan->adap.name, sizeof(chan->adap.name), "i2c-%d-atr-%d",
> + i2c_adapter_id(parent), chan_id);
> + chan->adap.owner = THIS_MODULE;
> + chan->adap.algo = &atr->algo;
> + chan->adap.algo_data = chan;
> + chan->adap.dev.parent = dev;
> + chan->adap.retries = parent->retries;
> + chan->adap.timeout = parent->timeout;
> + chan->adap.quirks = parent->quirks;
> + chan->adap.lock_ops = &i2c_atr_lock_ops;
> + chan->adap.attach_ops = &i2c_atr_attach_ops;
> +
> + if (bus_handle) {
> + device_set_node(&chan->adap.dev, fwnode_handle_get(bus_handle));
> + } else {
> + struct fwnode_handle *atr_node;
> + struct fwnode_handle *child;
> + u32 reg;
> +
> + atr_node = device_get_named_child_node(dev, "i2c-atr");
> +
> + fwnode_for_each_child_node(atr_node, child) {
> + ret = fwnode_property_read_u32(child, "reg", ®);
> + if (ret)
> + continue;
> + if (chan_id == reg)
> + break;
> + }
> +
> + device_set_node(&chan->adap.dev, child);
> + fwnode_handle_put(atr_node);
> + }
It seems you have OF independent code, but by some reason you included of.h
instead of property.h. Am I right?
> + ret = i2c_add_adapter(&chan->adap);
> + if (ret) {
> + dev_err(dev, "failed to add atr-adapter %u (error=%d)\n",
> + chan_id, ret);
> + goto err_add_adapter;
> + }
> +
> + symlink_name = kasprintf(GFP_KERNEL, "channel-%u", chan_id);
No NULL check?
> + WARN(sysfs_create_link(&chan->adap.dev.kobj, &dev->kobj, "atr_device"),
> + "can't create symlink to atr device\n");
> + WARN(sysfs_create_link(&dev->kobj, &chan->adap.dev.kobj, symlink_name),
> + "can't create symlink for channel %u\n", chan_id);
Why WARNs? sysfs has already some in their implementation.
> +
> + kfree(symlink_name);
> +
> + dev_dbg(dev, "Added ATR child bus %d\n", i2c_adapter_id(&chan->adap));
> +
> + atr->adapter[chan_id] = &chan->adap;
> + return 0;
> +
> +err_add_adapter:
> + mutex_destroy(&chan->orig_addrs_lock);
> + kfree(chan);
> + return ret;
> +}
...
> + struct fwnode_handle *fwnode = adap->dev.fwnode;
Please don't dereference fwnode like this, we have dev_fwnode() for that.
...
> + if (atr->adapter[chan_id] == NULL) {
!
> + dev_err(dev, "Adapter %d does not exist\n", chan_id);
> + return;
> + }
...
> + snprintf(symlink_name, sizeof(symlink_name),
> + "channel-%u", chan->chan_id);
Once line?
...
> + atr_size = struct_size(atr, adapter, max_adapters);
> + if (atr_size == SIZE_MAX)
> + return ERR_PTR(-EOVERFLOW);
Dunno if you really need this to be separated from devm_kzalloc(), either way
you will get an error, but in embedded case it will be -ENOMEM.
> + atr = devm_kzalloc(dev, atr_size, GFP_KERNEL);
> + if (!atr)
> + return ERR_PTR(-ENOMEM);
...
> +EXPORT_SYMBOL_GPL(i2c_atr_delete);
I would put these to their own namespace from day 1.
...
> +/**
> + * Helper to add I2C ATR features to a device driver.
> + */
??? Copy'n'paste typo?
> +struct i2c_atr {
> + /* private: internal use only */
> +
> + struct i2c_adapter *parent;
> + struct device *dev;
> + const struct i2c_atr_ops *ops;
> +
> + void *priv;
> +
> + struct i2c_algorithm algo;
> + struct mutex lock;
> + int max_adapters;
> +
> + struct i2c_adapter *adapter[0];
No VLAs.
> +};
...
> +int i2c_atr_add_adapter(struct i2c_atr *atr, u32 chan_id,
> + struct fwnode_handle *bus_np);
Missing
struct fwnode_handle;
at the top of the file?
--
With Best Regards,
Andy Shevchenko
next prev parent reply other threads:[~2022-11-01 14:31 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-11-01 13:20 [PATCH v4 0/8] i2c-atr and FPDLink Tomi Valkeinen
2022-11-01 13:20 ` [PATCH v4 1/8] i2c: core: let adapters be notified of client attach/detach Tomi Valkeinen
2022-11-01 13:20 ` [PATCH v4 2/8] i2c: add I2C Address Translator (ATR) support Tomi Valkeinen
2022-11-01 14:30 ` Andy Shevchenko [this message]
2022-11-04 11:59 ` Tomi Valkeinen
2022-11-04 12:38 ` Andy Shevchenko
2022-11-04 15:26 ` Tomi Valkeinen
2022-11-04 17:27 ` Andy Shevchenko
2022-11-07 11:40 ` Luca Ceresoli
2022-12-08 7:56 ` Tomi Valkeinen
2022-11-01 13:20 ` [PATCH v4 3/8] dt-bindings: media: add bindings for TI DS90UB960 Tomi Valkeinen
2022-11-01 16:47 ` Rob Herring
2022-11-02 17:26 ` Rob Herring
2022-11-03 11:50 ` Tomi Valkeinen
2022-11-03 12:13 ` Vaittinen, Matti
2022-11-03 12:32 ` Tomi Valkeinen
2022-11-11 16:26 ` Luca Ceresoli
2022-12-08 9:23 ` Tomi Valkeinen
2022-11-11 16:32 ` Luca Ceresoli
2022-11-11 16:35 ` Luca Ceresoli
2022-11-01 13:20 ` [PATCH v4 4/8] dt-bindings: media: add bindings for TI DS90UB913 Tomi Valkeinen
2022-11-01 16:47 ` Rob Herring
2022-11-02 17:27 ` Rob Herring
2022-11-01 13:20 ` [PATCH v4 5/8] dt-bindings: media: add bindings for TI DS90UB953 Tomi Valkeinen
2022-11-01 16:47 ` Rob Herring
2022-11-01 13:20 ` [PATCH v4 6/8] media: i2c: add DS90UB960 driver Tomi Valkeinen
2022-11-02 4:47 ` kernel test robot
2022-11-02 8:05 ` Tomi Valkeinen
2022-11-01 13:20 ` [PATCH v4 7/8] media: i2c: add DS90UB913 driver Tomi Valkeinen
2022-11-01 18:11 ` kernel test robot
2022-11-01 13:20 ` [PATCH v4 8/8] media: i2c: add DS90UB953 driver Tomi Valkeinen
2022-11-07 11:48 ` [PATCH v4 0/8] i2c-atr and FPDLink Luca Ceresoli
2022-11-07 12:12 ` Vaittinen, Matti
2022-11-07 12:12 ` Tomi Valkeinen
2022-11-07 14:37 ` Vaittinen, Matti
2022-11-07 15:37 ` Tomi Valkeinen
2022-11-07 17:47 ` Vaittinen, Matti
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=Y2EtnSNqBOfGRDMO@smile.fi.intel.com \
--to=andriy.shevchenko@intel.com \
--cc=Matti.Vaittinen@fi.rohmeurope.com \
--cc=devicetree@vger.kernel.org \
--cc=hverkuil-cisco@xs4all.nl \
--cc=jacopo@jmondi.org \
--cc=kieran.bingham@ideasonboard.com \
--cc=laurent.pinchart@ideasonboard.com \
--cc=linux-i2c@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=luca@lucaceresoli.net \
--cc=mark.rutland@arm.com \
--cc=mchehab@kernel.org \
--cc=peda@axentia.se \
--cc=robh+dt@kernel.org \
--cc=sakari.ailus@linux.intel.com \
--cc=satish.nagireddy@getcruise.com \
--cc=tomi.valkeinen@ideasonboard.com \
--cc=vz@mleia.com \
--cc=wsa@the-dreams.de \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.