Received: by 2002:a05:6358:d09b:b0:dc:cd0c:909e with SMTP id jc27csp990745rwb; Thu, 8 Dec 2022 05:37:44 -0800 (PST) X-Google-Smtp-Source: AA0mqf5+1lY2ffb5LaYidfBhz2mYAJ+XhRrcF026aOnKuLKKsQEDXQcbR8CKOOQmEJy1LsWJSTW4 X-Received: by 2002:a17:902:c94b:b0:189:ea28:3dbe with SMTP id i11-20020a170902c94b00b00189ea283dbemr11640932pla.94.1670506664771; Thu, 08 Dec 2022 05:37:44 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1670506664; cv=none; d=google.com; s=arc-20160816; b=DnihTHowCTHc1w/BgWaNr0uBMpOqjGrYSFptJ8lLzl7BLRL/pVKAPoiEZ/PdhdsOH4 G3XvIAUbGNk46ukpn7Yi4mcQEmyAmPfamyEeAt8vShjuKpHkNaiNKBNV4e4vPObB76or 9h690L56I2gBrt3ett2RhXrNan9bFoX83CxTBzaHVjg6K7tIdgSgFMRRP86xrVLxk8Sc 3CfMBCN9Qr+KmjVOyzYs8MNXU7kG6do/zIig1PvYBCKT72sXN8z99fHjMx9+ZmzEsU6L oTA41xVhEP9ej7+EcEXZKfkzCL6cUsnYAYSosLv9KayZaiIqrzRaHNX/zIMFd2Pmueqz ubsQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:organization:in-reply-to:content-disposition :mime-version:references:message-id:subject:cc:to:from:date :dkim-signature; bh=9RINqlV4Jnf0IpElJ+zrV1XCFiyIrcX0rA8MZL42h94=; b=Ecj7k1dwWgLlrmz9MNAkgbR6ECmdfnBVDkVNanWXtElrgmIFnPCUqn4Z6/Wuilf8H+ IMwoVzb9MMzSReg9nWpNo/Q6BGWzY5RaMlGet+gCN0CCIUno1uyKP+mW1bYhYObOWx2t nqMI/ZrNZbYEg3HhYXo60u3RWXQZx3xGm10ABWrQ4yikwBcn3CefPUSvk85XJvRlVMQP sW35XOqJCfHmbitYNTp+7UA5E+j7RuGaDqhjaWlUMcMPshuaQ37Db7z1cGTUIYOFzXtn yGVodR24gLm8IZ5XsVTfVaHCT8Ocn4y62PX95MYL3df3CY2ZKLARrYn81OVAGMEhhU+1 3n6g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=Zv1XrKm4; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id v2-20020a170902d68200b0018962fa3890si22237380ply.601.2022.12.08.05.37.35; Thu, 08 Dec 2022 05:37:44 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=Zv1XrKm4; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230178AbiLHMxk (ORCPT + 72 others); Thu, 8 Dec 2022 07:53:40 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52738 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230151AbiLHMxg (ORCPT ); Thu, 8 Dec 2022 07:53:36 -0500 Received: from mga06.intel.com (mga06b.intel.com [134.134.136.31]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A180660370; Thu, 8 Dec 2022 04:53:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1670504015; x=1702040015; h=date:from:to:cc:subject:message-id:references: mime-version:in-reply-to; bh=CK5TqcJGV7ARN7Am6uXTA58QztV19Khx/pdgHfX61TI=; b=Zv1XrKm4E27LhKhFhhVliW4TD6InUis5SMfjFXFUAHcui5csag2V3FaU D0vb/Ik3T5ACpQjTUt6ofwmC6yBPsjAWVqpe6QK1bURNxTEtMgnE/Bjum 9VErdw1wKWGLg2HoEbqLNZaLqSdirmo9B0Jm2pQ5aU35yeWi/J4D2tQZr YWxGLube97us2fQBSQxZWwe+MT0Oh+P0aZK1Crzr97IWdt++/6P6yz321 PDkG2lwDgCqzTELzH8zYPJIYt0RqnklTDtXFLaH4xs6rZLzSKIOqQYr5R mehjMK6V4apmGSMEqAXmRVxB3rhXrMjlfB6uLVa4xIuUawIq9DYjdlwvM g==; X-IronPort-AV: E=McAfee;i="6500,9779,10554"; a="379323468" X-IronPort-AV: E=Sophos;i="5.96,227,1665471600"; d="scan'208";a="379323468" Received: from orsmga006.jf.intel.com ([10.7.209.51]) by orsmga104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Dec 2022 04:53:34 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10554"; a="624689132" X-IronPort-AV: E=Sophos;i="5.96,227,1665471600"; d="scan'208";a="624689132" Received: from smile.fi.intel.com ([10.237.72.54]) by orsmga006.jf.intel.com with ESMTP; 08 Dec 2022 04:53:28 -0800 Received: from andy by smile.fi.intel.com with local (Exim 4.96) (envelope-from ) id 1p3GOy-006Koi-2O; Thu, 08 Dec 2022 14:53:24 +0200 Date: Thu, 8 Dec 2022 14:53:24 +0200 From: Andy Shevchenko To: Tomi Valkeinen Cc: linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-i2c@vger.kernel.org, Rob Herring , Krzysztof Kozlowski , Wolfram Sang , Luca Ceresoli , Matti Vaittinen , Mauro Carvalho Chehab , Peter Rosin , Liam Girdwood , Mark Brown , Sakari Ailus , Laurent Pinchart , Michael Tretter , Shawn Tu , Hans Verkuil , Mike Pagano , Krzysztof =?utf-8?Q?Ha=C5=82asa?= , Marek Vasut , Luca Ceresoli Subject: Re: [PATCH v5 2/8] i2c: add I2C Address Translator (ATR) support Message-ID: References: <20221208104006.316606-1-tomi.valkeinen@ideasonboard.com> <20221208104006.316606-3-tomi.valkeinen@ideasonboard.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20221208104006.316606-3-tomi.valkeinen@ideasonboard.com> Organization: Intel Finland Oy - BIC 0357606-4 - Westendinkatu 7, 02160 Espoo X-Spam-Status: No, score=-4.4 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_MED, SPF_HELO_NONE,SPF_NONE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Thu, Dec 08, 2022 at 12:40:00PM +0200, Tomi Valkeinen wrote: > From: Luca Ceresoli > > 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. Besides comments given against diff between series versions, see below. ... > +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; > + int ret; > + > + c2a = kzalloc(sizeof(*c2a), GFP_KERNEL); > + if (!c2a) > + return -ENOMEM; > + > + ret = atr->ops->attach_client(atr, chan->chan_id, info, client, > + &alias_id); > + if (ret) > + goto err_free; > + if (alias_id == 0) { > + ret = -EINVAL; I'm wondering why attach_client can't return this error and provide a guarantee that if no error, the alias_id is never be 0? > + 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; > +} ... > + if (bus_handle) { > + device_set_node(&chan->adap.dev, fwnode_handle_get(bus_handle)); I believe the correct way, while above still works, is device_set_node(&chan->adap.dev, bus_handle); fwnode_handle_get(dev_fwnode(&chan->adap.dev)); But I agree that this looks a bit verbose. And... > + } 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); ...OTOH, you set node with bumped reference here. So I leave all this to the maintainers. > + fwnode_handle_put(atr_node); > + } > + 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_mutex_destroy; > + } > + > + snprintf(symlink_name, sizeof(symlink_name), "channel-%u", > + chan->chan_id); > + > + ret = sysfs_create_link(&chan->adap.dev.kobj, &dev->kobj, "atr_device"); > + if (ret) > + dev_warn(dev, "can't create symlink to atr device\n"); > + ret = sysfs_create_link(&dev->kobj, &chan->adap.dev.kobj, symlink_name); > + if (ret) > + dev_warn(dev, "can't create symlink for channel %u\n", chan_id); > + > + dev_dbg(dev, "Added ATR child bus %d\n", i2c_adapter_id(&chan->adap)); > + > + atr->adapter[chan_id] = &chan->adap; > + return 0; > + > +err_mutex_destroy: Now it's a bit misleading, wouldn't be better err_put_fwnode: ? > + fwnode_handle_put(dev_fwnode(&chan->adap.dev)); > + mutex_destroy(&chan->orig_addrs_lock); > + kfree(chan); > + return ret; > +} > +EXPORT_SYMBOL_GPL(i2c_atr_add_adapter); Wondering if we may put this into namespace from day 1. ... > +/** > + * i2c_atr_del_adapter - Remove a child ("downstream") I2C bus added by > + * i2c_atr_del_adapter(). > + * @atr: The I2C ATR > + * @chan_id: Index of the `adapter to be removed (0 .. max_adapters-1) > + */ > +void i2c_atr_del_adapter(struct i2c_atr *atr, u32 chan_id) > +{ > + char symlink_name[ATR_MAX_SYMLINK_LEN]; > + > + struct i2c_adapter *adap = atr->adapter[chan_id]; > + struct i2c_atr_chan *chan = adap->algo_data; > + struct fwnode_handle *fwnode = dev_fwnode(&adap->dev); > + struct device *dev = atr->dev; > + if (!atr->adapter[chan_id]) { Isn't it the same as if (!adap) ? > + dev_err(dev, "Adapter %d does not exist\n", chan_id); > + return; > + } > + > + dev_dbg(dev, "Removing ATR child bus %d\n", i2c_adapter_id(adap)); > + > + atr->adapter[chan_id] = NULL; > + > + snprintf(symlink_name, sizeof(symlink_name), "channel-%u", > + chan->chan_id); > + sysfs_remove_link(&dev->kobj, symlink_name); > + sysfs_remove_link(&chan->adap.dev.kobj, "atr_device"); > + > + i2c_del_adapter(adap); > + fwnode_handle_put(fwnode); > + mutex_destroy(&chan->orig_addrs_lock); > + kfree(chan->orig_addrs); > + kfree(chan); > +} ... > +struct i2c_atr { > + /* private: internal use only */ What is private? The entire structure? Then why it's defined in the include/linux/? Can't you make it opaque? > + struct i2c_adapter *parent; > + struct device *dev; > + const struct i2c_atr_ops *ops; > + > + void *priv; > + > + struct i2c_algorithm algo; > + /* lock for the I2C bus segment (see struct i2c_lock_operations) */ > + struct mutex lock; > + int max_adapters; > + > + struct i2c_adapter *adapter[]; > +}; ... > +static inline void i2c_atr_set_clientdata(struct i2c_atr *atr, void *data) > +{ > + atr->priv = data; > +} > + > +static inline void *i2c_atr_get_clientdata(struct i2c_atr *atr) > +{ > + return atr->priv; > +} The function names are misleading, because I would think this is about driver data that has been set. I would rather use name like i2c_atr_get_priv() i2c_atr_set_priv() -- With Best Regards, Andy Shevchenko