Received: by 2002:a05:6358:a55:b0:ec:fcf4:3ecf with SMTP id 21csp6617329rwb; Wed, 18 Jan 2023 07:23:02 -0800 (PST) X-Google-Smtp-Source: AMrXdXu+kL0kDwr7qLRNyPMzWzu1hGKM5NSpk2N5zuV8/AgtZFKjPjl56R4YE+/XUZmcFSUrg3yK X-Received: by 2002:a17:90a:db07:b0:228:e435:2828 with SMTP id g7-20020a17090adb0700b00228e4352828mr7728041pjv.31.1674055382452; Wed, 18 Jan 2023 07:23:02 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1674055382; cv=none; d=google.com; s=arc-20160816; b=b/juD7xNPEO0z93dHhomKmmB1uQjG9r3pe3aMkVH+c9KWW7Pk8Q6IXbVCYxSsB4UPN lp+UJVPbGHSYCfWtwZ2ynj2lFgaxB6TsuW7ccuKf4Y9o6fGpY8tfoel4l/KeUcjCKV37 +27jxFksTYRlx6lNUn2G1dYpSxSgsNwf5OEbIlTxdpc47BqfJ0spzzxNSRSIr6v5p+mx r8nwTwt1eN1RrdRImMavpFb3vwNfr06jYUwRMI8c22dXuhYKEWufjEjAkCIEEN5bYP4l fvY5aygx/TIqaY0d/8tYhF0dnAA18SbNgXlXJhEduxuGUcfOYqY2r8Sznfz9fzLRFaEQ QpKQ== 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=VbtiqOOVxdYMZ5TFm+KBsVW6c6DAIX0xy2+MJBL/Om8=; b=sweeWf5+7On3OcUuMthkCYAKLPfmVz5f4LO/6Ahah0nwepdlTpESInZIShZvUFu4W8 LxlJyRCsOaKunHA7hySNJFHON7RCsRqQNygz5HpLkyBUsQJZtMy/8X4jmm1PDvfxMkkd 8J6ZABg64jgUE5mR0YuiJJZKJFa6FgF3NCNiLi51fSLghvbgp+Brbu689lxHgtsHSOOw Ar3ZEt9lasBvukV/2rPBCs2VArDO1a9O7BNqLbK9S57I64xByioE2bPT2r2+gJ1R3Uog qBy6Zq7LuJ/CNx9vidLKGvJ+v4YokLgPL3iSI6L93i0xfaHjsy1zUQ5RS2CSVq81/Rve mzPw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=QaI4ogYN; 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 a21-20020a63e855000000b004a587b86b62si37617920pgk.786.2023.01.18.07.22.56; Wed, 18 Jan 2023 07:23:02 -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=QaI4ogYN; 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 S230458AbjAROfS (ORCPT + 45 others); Wed, 18 Jan 2023 09:35:18 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33710 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231393AbjAROez (ORCPT ); Wed, 18 Jan 2023 09:34:55 -0500 Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 81B322748C; Wed, 18 Jan 2023 06:24:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1674051842; x=1705587842; h=date:from:to:cc:subject:message-id:references: mime-version:in-reply-to; bh=JW3Z4qGJkww64HEvaFHH2zXhHyqrRqOdAVZDOpAtKk8=; b=QaI4ogYNVLn/Yyb6QADgDDFmYQ7YIhwojhhpFnzhtaCb5e1Mendtx/Hv 41SVq+aqav0mpoAkiRTK0Asis/NMKZ3ID+DOJW0rguyhu0HzpGoAigTIP mZzZPDpxtmRD5XgNFZJlILuhfEyWyRVlBTAiZUmrD7qg/E8zg44o23wq5 oL+PzSZtNhxlKNxoa7czIGtKkEVWQgx6y2VU4q5GLcQXXIV50WR7Rzqd1 fDpGNiCmOQbMfGrCi0vpa8stDQOv3XouOyo//TQ9HiqNdz0/tPdP4ZQAo 9jF7NkfH/yo3jQwVL4zYjjdJfBDKdIjpN45cOZ2pV2LHGLM2MtqGFx8Qo g==; X-IronPort-AV: E=McAfee;i="6500,9779,10593"; a="352239982" X-IronPort-AV: E=Sophos;i="5.97,226,1669104000"; d="scan'208";a="352239982" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 18 Jan 2023 06:24:02 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10593"; a="833598833" X-IronPort-AV: E=Sophos;i="5.97,226,1669104000"; d="scan'208";a="833598833" Received: from smile.fi.intel.com ([10.237.72.54]) by orsmga005.jf.intel.com with ESMTP; 18 Jan 2023 06:23:56 -0800 Received: from andy by smile.fi.intel.com with local (Exim 4.96) (envelope-from ) id 1pI9M1-00BDkv-1i; Wed, 18 Jan 2023 16:23:53 +0200 Date: Wed, 18 Jan 2023 16:23:53 +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 , Laurent Pinchart , Mauro Carvalho Chehab , Peter Rosin , Liam Girdwood , Mark Brown , Sakari Ailus , Michael Tretter , Shawn Tu , Hans Verkuil , Mike Pagano , Krzysztof =?utf-8?Q?Ha=C5=82asa?= , Marek Vasut , Luca Ceresoli Subject: Re: [PATCH v7 1/7] i2c: add I2C Address Translator (ATR) support Message-ID: References: <20230118124031.788940-1-tomi.valkeinen@ideasonboard.com> <20230118124031.788940-2-tomi.valkeinen@ideasonboard.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20230118124031.788940-2-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, RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,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 Wed, Jan 18, 2023 at 02:40:25PM +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 is is ? > 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. ... > +A typical example follows. > + > +Topology:: > + > + Slave X @ 0x10 > + .-----. | > + .-----. | |---+---- B > + | CPU |--A--| ATR | > + `-----' | |---+---- C > + `-----' | > + Slave Y @ 0x10 > + > +Alias table: > + > +.. table:: > + > + ====== ===== > + Client Alias > + ====== ===== > + X 0x20 > + Y 0x30 > + ====== ===== > + > +Transaction: > + > + - Slave X driver sends a transaction (on adapter B), slave address 0x10 > + - ATR driver rewrites messages with address 0x20, forwards to adapter A > + - Physical I2C transaction on bus A, slave address 0x20 > + - ATR chip propagates transaction on bus B with address translated to 0x10 > + - Slave X chip replies on bus B > + - ATR chip forwards reply on bus A > + - ATR driver rewrites messages with address 0x10 > + - Slave X driver gets back the msgs[], with reply and address 0x10 I'm not sure I got the real / virtual status of the adapters. Are the B and C virtual ones, while A is the real? ... > +#define ATR_MAX_ADAPTERS 99 /* Just a sanity limit */ Hmm... It's not clear why this is not 100, for example, and how 99 below is related to that, assuming channel numbering is started from 0. > +#define ATR_MAX_SYMLINK_LEN 16 /* Longest name is 10 chars: "channel-99" */ ... > + /* Ensure we have enough room to save the original addresses */ > + if (unlikely(chan->orig_addrs_size < num)) { > + u16 *new_buf; > + > + new_buf = kmalloc_array(num, sizeof(*new_buf), GFP_KERNEL); I remember that I asked why we don't use krealloc_array() here... Perhaps that we don't need to copy the old mapping table? Can we put a short comment to clarify this in the code? > + if (!new_buf) > + return -ENOMEM; > + > + kfree(chan->orig_addrs); > + chan->orig_addrs = new_buf; > + chan->orig_addrs_size = num; > + } ... > +struct i2c_atr *i2c_atr_new(struct i2c_adapter *parent, struct device *dev, > + const struct i2c_atr_ops *ops, int max_adapters) > +{ > + struct i2c_atr *atr; > + int ret; > + > + if (max_adapters > ATR_MAX_ADAPTERS) > + return ERR_PTR(-EINVAL); > + > + if (!ops || !ops->attach_client || !ops->detach_client) > + return ERR_PTR(-EINVAL); > + atr = devm_kzalloc(dev, struct_size(atr, adapter, max_adapters), > + GFP_KERNEL); How do you know (or why do we limit) that the scope of this function will be only in ->probe()? Even though, I would replace devm_ by non-devm_ since there is the tear-down function has to be called by the user anyway. > + if (!atr) > + return ERR_PTR(-ENOMEM); > + > + mutex_init(&atr->lock); > + > + atr->parent = parent; > + atr->dev = dev; > + atr->ops = ops; > + atr->max_adapters = max_adapters; > + > + if (parent->algo->master_xfer) > + atr->algo.master_xfer = i2c_atr_master_xfer; > + if (parent->algo->smbus_xfer) > + atr->algo.smbus_xfer = i2c_atr_smbus_xfer; > + atr->algo.functionality = i2c_atr_functionality; > + > + atr->i2c_nb.notifier_call = i2c_atr_bus_notifier_call; > + ret = bus_register_notifier(&i2c_bus_type, &atr->i2c_nb); > + if (ret) { > + mutex_destroy(&atr->lock); > + return ERR_PTR(ret); > + } > + > + return atr; > +} ... > +void i2c_atr_del_adapter(struct i2c_atr *atr, u32 chan_id) > +{ > + char symlink_name[ATR_MAX_SYMLINK_LEN]; > + Redundant blank line. > + 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 (!adap) > + return; Redundant check (it will be optimized out by compiler) or wrong assignments above. > + dev_dbg(dev, "Removing ATR child bus %d\n", i2c_adapter_id(adap)); > + > + 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); > + > + atr->adapter[chan_id] = NULL; > + > + fwnode_handle_put(fwnode); > + mutex_destroy(&chan->orig_addrs_lock); > + kfree(chan->orig_addrs); > + kfree(chan); > +} ... > +void i2c_atr_set_driver_data(struct i2c_atr *atr, void *data) > +{ > + atr->priv = data; > +} > +EXPORT_SYMBOL_NS_GPL(i2c_atr_set_driver_data, I2C_ATR); > + > +void *i2c_atr_get_driver_data(struct i2c_atr *atr) > +{ > + return atr->priv; > +} > +EXPORT_SYMBOL_NS_GPL(i2c_atr_get_driver_data, I2C_ATR); Just to be sure: Is it really _driver_ data and not _device instance_ data? -- With Best Regards, Andy Shevchenko