All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH v9 3/7] i3c: master: add i3c_secondary_master_register
@ 2020-11-29 17:38 kernel test robot
  0 siblings, 0 replies; 5+ messages in thread
From: kernel test robot @ 2020-11-29 17:38 UTC (permalink / raw)
  To: kbuild

[-- Attachment #1: Type: text/plain, Size: 8674 bytes --]

CC: kbuild-all(a)lists.01.org
In-Reply-To: <1606659765-19490-1-git-send-email-pthombar@cadence.com>
References: <1606659765-19490-1-git-send-email-pthombar@cadence.com>
TO: Parshuram Thombare <pthombar@cadence.com>
TO: alexandre.belloni(a)bootlin.com
TO: slongerbeam(a)gmail.com
TO: vitor.soares(a)synopsys.com
CC: linux-i3c(a)lists.infradead.org
CC: linux-kernel(a)vger.kernel.org
CC: mparab(a)cadence.com
CC: praneeth(a)ti.com
CC: Parshuram Thombare <pthombar@cadence.com>

Hi Parshuram,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on next-20201127]
[cannot apply to linus/master v5.10-rc5 v5.10-rc4 v5.10-rc3 v5.10-rc5]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Parshuram-Thombare/I3C-mastership-handover-support/20201129-222847
base:    6174f05255e65622ff3340257879a4c0f858b0df
:::::: branch date: 3 hours ago
:::::: commit date: 3 hours ago
config: i386-randconfig-m021-20201129 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-15) 9.3.0

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>

New smatch warnings:
drivers/i3c/master.c:1842 i3c_secondary_master_bus_init() warn: passing a valid pointer to 'PTR_ERR'

Old smatch warnings:
drivers/i3c/master.c:462 mode_show() warn: unsigned 'i3cbus->mode' is never less than zero.
drivers/i3c/master.c:1594 i3c_master_set_info() warn: passing a valid pointer to 'PTR_ERR'
drivers/i3c/master.c:1697 i3c_primary_master_bus_init() warn: passing a valid pointer to 'PTR_ERR'
drivers/i3c/master.c:1952 i3c_master_add_i3c_dev_locked() warn: passing a valid pointer to 'PTR_ERR'

vim +/PTR_ERR +1842 drivers/i3c/master.c

3a379bbcea0af6 Boris Brezillon    2017-07-19  1799  
5386a14513be24 Parshuram Thombare 2020-11-29  1800  /**
5386a14513be24 Parshuram Thombare 2020-11-29  1801   * i3c_secondary_master_bus_init() - initialize an I3C bus for secondary
5386a14513be24 Parshuram Thombare 2020-11-29  1802   * master
5386a14513be24 Parshuram Thombare 2020-11-29  1803   * @master: secondary master initializing the bus
5386a14513be24 Parshuram Thombare 2020-11-29  1804   *
5386a14513be24 Parshuram Thombare 2020-11-29  1805   * This function does
5386a14513be24 Parshuram Thombare 2020-11-29  1806   *
5386a14513be24 Parshuram Thombare 2020-11-29  1807   * 1. Attach I2C devs to the master
5386a14513be24 Parshuram Thombare 2020-11-29  1808   *
5386a14513be24 Parshuram Thombare 2020-11-29  1809   * 2. Call &i3c_master_controller_ops->bus_init() method to initialize
5386a14513be24 Parshuram Thombare 2020-11-29  1810   *    the master controller. That's usually where the bus mode is selected
5386a14513be24 Parshuram Thombare 2020-11-29  1811   *    (pure bus or mixed fast/slow bus)
5386a14513be24 Parshuram Thombare 2020-11-29  1812   *
5386a14513be24 Parshuram Thombare 2020-11-29  1813   * Once this is done, I2C devices should be usable.
5386a14513be24 Parshuram Thombare 2020-11-29  1814   *
5386a14513be24 Parshuram Thombare 2020-11-29  1815   * Return: a 0 in case of success, an negative error code otherwise.
5386a14513be24 Parshuram Thombare 2020-11-29  1816   */
5386a14513be24 Parshuram Thombare 2020-11-29  1817  static int i3c_secondary_master_bus_init(struct i3c_master_controller *master)
5386a14513be24 Parshuram Thombare 2020-11-29  1818  {
5386a14513be24 Parshuram Thombare 2020-11-29  1819  	enum i3c_addr_slot_status status;
5386a14513be24 Parshuram Thombare 2020-11-29  1820  	struct i2c_dev_boardinfo *i2cboardinfo;
5386a14513be24 Parshuram Thombare 2020-11-29  1821  	struct i2c_dev_desc *i2cdev;
5386a14513be24 Parshuram Thombare 2020-11-29  1822  	int ret;
5386a14513be24 Parshuram Thombare 2020-11-29  1823  
5386a14513be24 Parshuram Thombare 2020-11-29  1824  	/*
5386a14513be24 Parshuram Thombare 2020-11-29  1825  	 * First attach all devices with static definitions provided by the
5386a14513be24 Parshuram Thombare 2020-11-29  1826  	 * FW.
5386a14513be24 Parshuram Thombare 2020-11-29  1827  	 */
5386a14513be24 Parshuram Thombare 2020-11-29  1828  	list_for_each_entry(i2cboardinfo, &master->boardinfo.i2c, node) {
5386a14513be24 Parshuram Thombare 2020-11-29  1829  		status = i3c_bus_get_addr_slot_status(&master->bus,
5386a14513be24 Parshuram Thombare 2020-11-29  1830  						      i2cboardinfo->base.addr);
5386a14513be24 Parshuram Thombare 2020-11-29  1831  		if (status != I3C_ADDR_SLOT_FREE) {
5386a14513be24 Parshuram Thombare 2020-11-29  1832  			ret = -EBUSY;
5386a14513be24 Parshuram Thombare 2020-11-29  1833  			goto err_detach_devs;
5386a14513be24 Parshuram Thombare 2020-11-29  1834  		}
5386a14513be24 Parshuram Thombare 2020-11-29  1835  
5386a14513be24 Parshuram Thombare 2020-11-29  1836  		i3c_bus_set_addr_slot_status(&master->bus,
5386a14513be24 Parshuram Thombare 2020-11-29  1837  					     i2cboardinfo->base.addr,
5386a14513be24 Parshuram Thombare 2020-11-29  1838  					     I3C_ADDR_SLOT_I2C_DEV);
5386a14513be24 Parshuram Thombare 2020-11-29  1839  
5386a14513be24 Parshuram Thombare 2020-11-29  1840  		i2cdev = i3c_master_alloc_i2c_dev(master, i2cboardinfo);
5386a14513be24 Parshuram Thombare 2020-11-29  1841  		if (IS_ERR(i2cdev)) {
5386a14513be24 Parshuram Thombare 2020-11-29 @1842  			ret = PTR_ERR(i2cdev);
5386a14513be24 Parshuram Thombare 2020-11-29  1843  			goto err_detach_devs;
5386a14513be24 Parshuram Thombare 2020-11-29  1844  		}
5386a14513be24 Parshuram Thombare 2020-11-29  1845  
5386a14513be24 Parshuram Thombare 2020-11-29  1846  		ret = i3c_master_attach_i2c_dev(master, i2cdev);
5386a14513be24 Parshuram Thombare 2020-11-29  1847  		if (ret) {
5386a14513be24 Parshuram Thombare 2020-11-29  1848  			i3c_master_free_i2c_dev(i2cdev);
5386a14513be24 Parshuram Thombare 2020-11-29  1849  			goto err_detach_devs;
5386a14513be24 Parshuram Thombare 2020-11-29  1850  		}
5386a14513be24 Parshuram Thombare 2020-11-29  1851  	}
5386a14513be24 Parshuram Thombare 2020-11-29  1852  
5386a14513be24 Parshuram Thombare 2020-11-29  1853  	/*
5386a14513be24 Parshuram Thombare 2020-11-29  1854  	 * Now execute the controller specific ->bus_init() routine, which
5386a14513be24 Parshuram Thombare 2020-11-29  1855  	 * might configure its internal logic to match the bus limitations.
5386a14513be24 Parshuram Thombare 2020-11-29  1856  	 */
5386a14513be24 Parshuram Thombare 2020-11-29  1857  	ret = master->ops->bus_init(master);
5386a14513be24 Parshuram Thombare 2020-11-29  1858  	if (ret)
5386a14513be24 Parshuram Thombare 2020-11-29  1859  		goto err_detach_devs;
5386a14513be24 Parshuram Thombare 2020-11-29  1860  
5386a14513be24 Parshuram Thombare 2020-11-29  1861  	/*
5386a14513be24 Parshuram Thombare 2020-11-29  1862  	 * The master device should have been instantiated in ->bus_init(),
5386a14513be24 Parshuram Thombare 2020-11-29  1863  	 * complain if this was not the case.
5386a14513be24 Parshuram Thombare 2020-11-29  1864  	 */
5386a14513be24 Parshuram Thombare 2020-11-29  1865  	if (!master->this) {
5386a14513be24 Parshuram Thombare 2020-11-29  1866  		dev_err(&master->dev,
5386a14513be24 Parshuram Thombare 2020-11-29  1867  			"master_set_info() was not called in ->bus_init()\n");
5386a14513be24 Parshuram Thombare 2020-11-29  1868  		ret = -EINVAL;
5386a14513be24 Parshuram Thombare 2020-11-29  1869  		goto err_bus_cleanup;
5386a14513be24 Parshuram Thombare 2020-11-29  1870  	}
5386a14513be24 Parshuram Thombare 2020-11-29  1871  
5386a14513be24 Parshuram Thombare 2020-11-29  1872  	return 0;
5386a14513be24 Parshuram Thombare 2020-11-29  1873  
5386a14513be24 Parshuram Thombare 2020-11-29  1874  err_bus_cleanup:
5386a14513be24 Parshuram Thombare 2020-11-29  1875  	if (master->ops->bus_cleanup)
5386a14513be24 Parshuram Thombare 2020-11-29  1876  		master->ops->bus_cleanup(master);
5386a14513be24 Parshuram Thombare 2020-11-29  1877  
5386a14513be24 Parshuram Thombare 2020-11-29  1878  err_detach_devs:
5386a14513be24 Parshuram Thombare 2020-11-29  1879  	i3c_master_detach_free_devs(master);
5386a14513be24 Parshuram Thombare 2020-11-29  1880  
5386a14513be24 Parshuram Thombare 2020-11-29  1881  	return ret;
5386a14513be24 Parshuram Thombare 2020-11-29  1882  }
5386a14513be24 Parshuram Thombare 2020-11-29  1883  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 34628 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v9 3/7] i3c: master: add i3c_secondary_master_register
  2020-11-29 14:19 [RESEND PATCH v9 0/7] I3C mastership handover support Parshuram Thombare
@ 2020-11-29 14:22   ` Parshuram Thombare
  0 siblings, 0 replies; 5+ messages in thread
From: Parshuram Thombare @ 2020-11-29 14:22 UTC (permalink / raw)
  To: alexandre.belloni, slongerbeam, vitor.soares
  Cc: linux-i3c, linux-kernel, mparab, praneeth, Parshuram Thombare

add i3c_secondary_master_register which is used
to register secondary masters.

Signed-off-by: Parshuram Thombare <pthombar@cadence.com>
---
 drivers/i3c/master.c       |  154 +++++++++++++++++++++++++++++++++++++++++++-
 include/linux/i3c/master.h |    3 +
 2 files changed, 156 insertions(+), 1 deletions(-)

diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index 56e8fe4..af0630a 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -1797,6 +1797,90 @@ static int i3c_primary_master_bus_init(struct i3c_master_controller *master)
 	return ret;
 }
 
+/**
+ * i3c_secondary_master_bus_init() - initialize an I3C bus for secondary
+ * master
+ * @master: secondary master initializing the bus
+ *
+ * This function does
+ *
+ * 1. Attach I2C devs to the master
+ *
+ * 2. Call &i3c_master_controller_ops->bus_init() method to initialize
+ *    the master controller. That's usually where the bus mode is selected
+ *    (pure bus or mixed fast/slow bus)
+ *
+ * Once this is done, I2C devices should be usable.
+ *
+ * Return: a 0 in case of success, an negative error code otherwise.
+ */
+static int i3c_secondary_master_bus_init(struct i3c_master_controller *master)
+{
+	enum i3c_addr_slot_status status;
+	struct i2c_dev_boardinfo *i2cboardinfo;
+	struct i2c_dev_desc *i2cdev;
+	int ret;
+
+	/*
+	 * First attach all devices with static definitions provided by the
+	 * FW.
+	 */
+	list_for_each_entry(i2cboardinfo, &master->boardinfo.i2c, node) {
+		status = i3c_bus_get_addr_slot_status(&master->bus,
+						      i2cboardinfo->base.addr);
+		if (status != I3C_ADDR_SLOT_FREE) {
+			ret = -EBUSY;
+			goto err_detach_devs;
+		}
+
+		i3c_bus_set_addr_slot_status(&master->bus,
+					     i2cboardinfo->base.addr,
+					     I3C_ADDR_SLOT_I2C_DEV);
+
+		i2cdev = i3c_master_alloc_i2c_dev(master, i2cboardinfo);
+		if (IS_ERR(i2cdev)) {
+			ret = PTR_ERR(i2cdev);
+			goto err_detach_devs;
+		}
+
+		ret = i3c_master_attach_i2c_dev(master, i2cdev);
+		if (ret) {
+			i3c_master_free_i2c_dev(i2cdev);
+			goto err_detach_devs;
+		}
+	}
+
+	/*
+	 * Now execute the controller specific ->bus_init() routine, which
+	 * might configure its internal logic to match the bus limitations.
+	 */
+	ret = master->ops->bus_init(master);
+	if (ret)
+		goto err_detach_devs;
+
+	/*
+	 * The master device should have been instantiated in ->bus_init(),
+	 * complain if this was not the case.
+	 */
+	if (!master->this) {
+		dev_err(&master->dev,
+			"master_set_info() was not called in ->bus_init()\n");
+		ret = -EINVAL;
+		goto err_bus_cleanup;
+	}
+
+	return 0;
+
+err_bus_cleanup:
+	if (master->ops->bus_cleanup)
+		master->ops->bus_cleanup(master);
+
+err_detach_devs:
+	i3c_master_detach_free_devs(master);
+
+	return ret;
+}
+
 static void i3c_master_bus_cleanup(struct i3c_master_controller *master)
 {
 	if (master->ops->bus_cleanup)
@@ -2514,7 +2598,10 @@ static int i3c_master_init(struct i3c_master_controller *master,
 		goto err_put_dev;
 	}
 
-	ret = i3c_primary_master_bus_init(master);
+	if (secondary)
+		ret = i3c_secondary_master_bus_init(master);
+	else
+		ret = i3c_primary_master_bus_init(master);
 	if (ret)
 		goto err_destroy_wq;
 
@@ -2595,6 +2682,71 @@ int i3c_primary_master_register(struct i3c_master_controller *master,
 EXPORT_SYMBOL_GPL(i3c_primary_master_register);
 
 /**
+ * i3c_secondary_master_register() - register an I3C secondary master
+ * @master: master used to send frames on the bus
+ * @parent: the parent device (the one that provides this I3C master
+ *	    controller)
+ * @ops: the master controller operations
+ *
+ * This function does minimal required initialization for secondary
+ * master, rest functionality like creating and registering I2C
+ * and I3C devices is done in defslvs processing.
+ *
+ *  i3c_secondary_master_register() does following things -
+ * - creates and initializes the I3C bus
+ * - populates the bus with static I2C devs if @parent->of_node is not
+ *   NULL
+ *   initialization
+ * - allocate memory for defslvs_data.devs, which is used to receive
+ *   defslvs list
+ * - create I3C device representing this master
+ * - registers the I2C adapter and all I2C devices
+ *
+ * Return: 0 in case of success, a negative error code otherwise.
+ */
+int i3c_secondary_master_register(struct i3c_master_controller *master,
+				  struct device *parent,
+				  const struct i3c_master_controller_ops *ops)
+{
+	int ret;
+
+	ret = i3c_master_init(master, parent, ops, true);
+	if (ret)
+		return ret;
+
+	ret = device_add(&master->dev);
+	if (ret)
+		goto err_cleanup_bus;
+
+	/*
+	 * Expose our I3C bus as an I2C adapter so that I2C devices are exposed
+	 * through the I2C subsystem.
+	 */
+	ret = i3c_master_i2c_adapter_init(master);
+	if (ret)
+		goto err_del_dev;
+
+	/*
+	 * We're done initializing the bus and the controller, we can now
+	 * register I3C devices from defslvs list.
+	 */
+	master->init_done = true;
+
+	return 0;
+
+err_del_dev:
+	device_del(&master->dev);
+
+err_cleanup_bus:
+	i3c_master_bus_cleanup(master);
+
+	put_device(&master->dev);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(i3c_secondary_master_register);
+
+/**
  * i3c_master_unregister() - unregister an I3C master
  * @master: master used to send frames on the bus
  *
diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h
index e543f68..e186d53 100644
--- a/include/linux/i3c/master.h
+++ b/include/linux/i3c/master.h
@@ -541,6 +541,9 @@ int i3c_master_set_info(struct i3c_master_controller *master,
 int i3c_primary_master_register(struct i3c_master_controller *master,
 				struct device *parent,
 				const struct i3c_master_controller_ops *ops);
+int i3c_secondary_master_register(struct i3c_master_controller *master,
+				  struct device *parent,
+				  const struct i3c_master_controller_ops *ops);
 int i3c_master_unregister(struct i3c_master_controller *master);
 
 /**
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v9 3/7] i3c: master: add i3c_secondary_master_register
@ 2020-11-29 14:22   ` Parshuram Thombare
  0 siblings, 0 replies; 5+ messages in thread
From: Parshuram Thombare @ 2020-11-29 14:22 UTC (permalink / raw)
  To: alexandre.belloni, slongerbeam, vitor.soares
  Cc: praneeth, mparab, linux-i3c, linux-kernel, Parshuram Thombare

add i3c_secondary_master_register which is used
to register secondary masters.

Signed-off-by: Parshuram Thombare <pthombar@cadence.com>
---
 drivers/i3c/master.c       |  154 +++++++++++++++++++++++++++++++++++++++++++-
 include/linux/i3c/master.h |    3 +
 2 files changed, 156 insertions(+), 1 deletions(-)

diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index 56e8fe4..af0630a 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -1797,6 +1797,90 @@ static int i3c_primary_master_bus_init(struct i3c_master_controller *master)
 	return ret;
 }
 
+/**
+ * i3c_secondary_master_bus_init() - initialize an I3C bus for secondary
+ * master
+ * @master: secondary master initializing the bus
+ *
+ * This function does
+ *
+ * 1. Attach I2C devs to the master
+ *
+ * 2. Call &i3c_master_controller_ops->bus_init() method to initialize
+ *    the master controller. That's usually where the bus mode is selected
+ *    (pure bus or mixed fast/slow bus)
+ *
+ * Once this is done, I2C devices should be usable.
+ *
+ * Return: a 0 in case of success, an negative error code otherwise.
+ */
+static int i3c_secondary_master_bus_init(struct i3c_master_controller *master)
+{
+	enum i3c_addr_slot_status status;
+	struct i2c_dev_boardinfo *i2cboardinfo;
+	struct i2c_dev_desc *i2cdev;
+	int ret;
+
+	/*
+	 * First attach all devices with static definitions provided by the
+	 * FW.
+	 */
+	list_for_each_entry(i2cboardinfo, &master->boardinfo.i2c, node) {
+		status = i3c_bus_get_addr_slot_status(&master->bus,
+						      i2cboardinfo->base.addr);
+		if (status != I3C_ADDR_SLOT_FREE) {
+			ret = -EBUSY;
+			goto err_detach_devs;
+		}
+
+		i3c_bus_set_addr_slot_status(&master->bus,
+					     i2cboardinfo->base.addr,
+					     I3C_ADDR_SLOT_I2C_DEV);
+
+		i2cdev = i3c_master_alloc_i2c_dev(master, i2cboardinfo);
+		if (IS_ERR(i2cdev)) {
+			ret = PTR_ERR(i2cdev);
+			goto err_detach_devs;
+		}
+
+		ret = i3c_master_attach_i2c_dev(master, i2cdev);
+		if (ret) {
+			i3c_master_free_i2c_dev(i2cdev);
+			goto err_detach_devs;
+		}
+	}
+
+	/*
+	 * Now execute the controller specific ->bus_init() routine, which
+	 * might configure its internal logic to match the bus limitations.
+	 */
+	ret = master->ops->bus_init(master);
+	if (ret)
+		goto err_detach_devs;
+
+	/*
+	 * The master device should have been instantiated in ->bus_init(),
+	 * complain if this was not the case.
+	 */
+	if (!master->this) {
+		dev_err(&master->dev,
+			"master_set_info() was not called in ->bus_init()\n");
+		ret = -EINVAL;
+		goto err_bus_cleanup;
+	}
+
+	return 0;
+
+err_bus_cleanup:
+	if (master->ops->bus_cleanup)
+		master->ops->bus_cleanup(master);
+
+err_detach_devs:
+	i3c_master_detach_free_devs(master);
+
+	return ret;
+}
+
 static void i3c_master_bus_cleanup(struct i3c_master_controller *master)
 {
 	if (master->ops->bus_cleanup)
@@ -2514,7 +2598,10 @@ static int i3c_master_init(struct i3c_master_controller *master,
 		goto err_put_dev;
 	}
 
-	ret = i3c_primary_master_bus_init(master);
+	if (secondary)
+		ret = i3c_secondary_master_bus_init(master);
+	else
+		ret = i3c_primary_master_bus_init(master);
 	if (ret)
 		goto err_destroy_wq;
 
@@ -2595,6 +2682,71 @@ int i3c_primary_master_register(struct i3c_master_controller *master,
 EXPORT_SYMBOL_GPL(i3c_primary_master_register);
 
 /**
+ * i3c_secondary_master_register() - register an I3C secondary master
+ * @master: master used to send frames on the bus
+ * @parent: the parent device (the one that provides this I3C master
+ *	    controller)
+ * @ops: the master controller operations
+ *
+ * This function does minimal required initialization for secondary
+ * master, rest functionality like creating and registering I2C
+ * and I3C devices is done in defslvs processing.
+ *
+ *  i3c_secondary_master_register() does following things -
+ * - creates and initializes the I3C bus
+ * - populates the bus with static I2C devs if @parent->of_node is not
+ *   NULL
+ *   initialization
+ * - allocate memory for defslvs_data.devs, which is used to receive
+ *   defslvs list
+ * - create I3C device representing this master
+ * - registers the I2C adapter and all I2C devices
+ *
+ * Return: 0 in case of success, a negative error code otherwise.
+ */
+int i3c_secondary_master_register(struct i3c_master_controller *master,
+				  struct device *parent,
+				  const struct i3c_master_controller_ops *ops)
+{
+	int ret;
+
+	ret = i3c_master_init(master, parent, ops, true);
+	if (ret)
+		return ret;
+
+	ret = device_add(&master->dev);
+	if (ret)
+		goto err_cleanup_bus;
+
+	/*
+	 * Expose our I3C bus as an I2C adapter so that I2C devices are exposed
+	 * through the I2C subsystem.
+	 */
+	ret = i3c_master_i2c_adapter_init(master);
+	if (ret)
+		goto err_del_dev;
+
+	/*
+	 * We're done initializing the bus and the controller, we can now
+	 * register I3C devices from defslvs list.
+	 */
+	master->init_done = true;
+
+	return 0;
+
+err_del_dev:
+	device_del(&master->dev);
+
+err_cleanup_bus:
+	i3c_master_bus_cleanup(master);
+
+	put_device(&master->dev);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(i3c_secondary_master_register);
+
+/**
  * i3c_master_unregister() - unregister an I3C master
  * @master: master used to send frames on the bus
  *
diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h
index e543f68..e186d53 100644
--- a/include/linux/i3c/master.h
+++ b/include/linux/i3c/master.h
@@ -541,6 +541,9 @@ int i3c_master_set_info(struct i3c_master_controller *master,
 int i3c_primary_master_register(struct i3c_master_controller *master,
 				struct device *parent,
 				const struct i3c_master_controller_ops *ops);
+int i3c_secondary_master_register(struct i3c_master_controller *master,
+				  struct device *parent,
+				  const struct i3c_master_controller_ops *ops);
 int i3c_master_unregister(struct i3c_master_controller *master);
 
 /**
-- 
1.7.1


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v9 3/7] i3c: master: add i3c_secondary_master_register
@ 2020-11-28 14:46 ` Parshuram Thombare
  0 siblings, 0 replies; 5+ messages in thread
From: Parshuram Thombare @ 2020-11-28 14:46 UTC (permalink / raw)
  To: alexandre.belloni, slongerbeam, vitor.soares
  Cc: linux-i3c, linux-kernel, mparab, praneeth, Parshuram Thombare

add i3c_secondary_master_register which is used
to register secondary masters.

Signed-off-by: Parshuram Thombare <pthombar@cadence.com>
---
 drivers/i3c/master.c       |  154 +++++++++++++++++++++++++++++++++++++++++++-
 include/linux/i3c/master.h |    3 +
 2 files changed, 156 insertions(+), 1 deletions(-)

diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index 56e8fe4..af0630a 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -1797,6 +1797,90 @@ static int i3c_primary_master_bus_init(struct i3c_master_controller *master)
 	return ret;
 }
 
+/**
+ * i3c_secondary_master_bus_init() - initialize an I3C bus for secondary
+ * master
+ * @master: secondary master initializing the bus
+ *
+ * This function does
+ *
+ * 1. Attach I2C devs to the master
+ *
+ * 2. Call &i3c_master_controller_ops->bus_init() method to initialize
+ *    the master controller. That's usually where the bus mode is selected
+ *    (pure bus or mixed fast/slow bus)
+ *
+ * Once this is done, I2C devices should be usable.
+ *
+ * Return: a 0 in case of success, an negative error code otherwise.
+ */
+static int i3c_secondary_master_bus_init(struct i3c_master_controller *master)
+{
+	enum i3c_addr_slot_status status;
+	struct i2c_dev_boardinfo *i2cboardinfo;
+	struct i2c_dev_desc *i2cdev;
+	int ret;
+
+	/*
+	 * First attach all devices with static definitions provided by the
+	 * FW.
+	 */
+	list_for_each_entry(i2cboardinfo, &master->boardinfo.i2c, node) {
+		status = i3c_bus_get_addr_slot_status(&master->bus,
+						      i2cboardinfo->base.addr);
+		if (status != I3C_ADDR_SLOT_FREE) {
+			ret = -EBUSY;
+			goto err_detach_devs;
+		}
+
+		i3c_bus_set_addr_slot_status(&master->bus,
+					     i2cboardinfo->base.addr,
+					     I3C_ADDR_SLOT_I2C_DEV);
+
+		i2cdev = i3c_master_alloc_i2c_dev(master, i2cboardinfo);
+		if (IS_ERR(i2cdev)) {
+			ret = PTR_ERR(i2cdev);
+			goto err_detach_devs;
+		}
+
+		ret = i3c_master_attach_i2c_dev(master, i2cdev);
+		if (ret) {
+			i3c_master_free_i2c_dev(i2cdev);
+			goto err_detach_devs;
+		}
+	}
+
+	/*
+	 * Now execute the controller specific ->bus_init() routine, which
+	 * might configure its internal logic to match the bus limitations.
+	 */
+	ret = master->ops->bus_init(master);
+	if (ret)
+		goto err_detach_devs;
+
+	/*
+	 * The master device should have been instantiated in ->bus_init(),
+	 * complain if this was not the case.
+	 */
+	if (!master->this) {
+		dev_err(&master->dev,
+			"master_set_info() was not called in ->bus_init()\n");
+		ret = -EINVAL;
+		goto err_bus_cleanup;
+	}
+
+	return 0;
+
+err_bus_cleanup:
+	if (master->ops->bus_cleanup)
+		master->ops->bus_cleanup(master);
+
+err_detach_devs:
+	i3c_master_detach_free_devs(master);
+
+	return ret;
+}
+
 static void i3c_master_bus_cleanup(struct i3c_master_controller *master)
 {
 	if (master->ops->bus_cleanup)
@@ -2514,7 +2598,10 @@ static int i3c_master_init(struct i3c_master_controller *master,
 		goto err_put_dev;
 	}
 
-	ret = i3c_primary_master_bus_init(master);
+	if (secondary)
+		ret = i3c_secondary_master_bus_init(master);
+	else
+		ret = i3c_primary_master_bus_init(master);
 	if (ret)
 		goto err_destroy_wq;
 
@@ -2595,6 +2682,71 @@ int i3c_primary_master_register(struct i3c_master_controller *master,
 EXPORT_SYMBOL_GPL(i3c_primary_master_register);
 
 /**
+ * i3c_secondary_master_register() - register an I3C secondary master
+ * @master: master used to send frames on the bus
+ * @parent: the parent device (the one that provides this I3C master
+ *	    controller)
+ * @ops: the master controller operations
+ *
+ * This function does minimal required initialization for secondary
+ * master, rest functionality like creating and registering I2C
+ * and I3C devices is done in defslvs processing.
+ *
+ *  i3c_secondary_master_register() does following things -
+ * - creates and initializes the I3C bus
+ * - populates the bus with static I2C devs if @parent->of_node is not
+ *   NULL
+ *   initialization
+ * - allocate memory for defslvs_data.devs, which is used to receive
+ *   defslvs list
+ * - create I3C device representing this master
+ * - registers the I2C adapter and all I2C devices
+ *
+ * Return: 0 in case of success, a negative error code otherwise.
+ */
+int i3c_secondary_master_register(struct i3c_master_controller *master,
+				  struct device *parent,
+				  const struct i3c_master_controller_ops *ops)
+{
+	int ret;
+
+	ret = i3c_master_init(master, parent, ops, true);
+	if (ret)
+		return ret;
+
+	ret = device_add(&master->dev);
+	if (ret)
+		goto err_cleanup_bus;
+
+	/*
+	 * Expose our I3C bus as an I2C adapter so that I2C devices are exposed
+	 * through the I2C subsystem.
+	 */
+	ret = i3c_master_i2c_adapter_init(master);
+	if (ret)
+		goto err_del_dev;
+
+	/*
+	 * We're done initializing the bus and the controller, we can now
+	 * register I3C devices from defslvs list.
+	 */
+	master->init_done = true;
+
+	return 0;
+
+err_del_dev:
+	device_del(&master->dev);
+
+err_cleanup_bus:
+	i3c_master_bus_cleanup(master);
+
+	put_device(&master->dev);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(i3c_secondary_master_register);
+
+/**
  * i3c_master_unregister() - unregister an I3C master
  * @master: master used to send frames on the bus
  *
diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h
index e543f68..e186d53 100644
--- a/include/linux/i3c/master.h
+++ b/include/linux/i3c/master.h
@@ -541,6 +541,9 @@ int i3c_master_set_info(struct i3c_master_controller *master,
 int i3c_primary_master_register(struct i3c_master_controller *master,
 				struct device *parent,
 				const struct i3c_master_controller_ops *ops);
+int i3c_secondary_master_register(struct i3c_master_controller *master,
+				  struct device *parent,
+				  const struct i3c_master_controller_ops *ops);
 int i3c_master_unregister(struct i3c_master_controller *master);
 
 /**
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v9 3/7] i3c: master: add i3c_secondary_master_register
@ 2020-11-28 14:46 ` Parshuram Thombare
  0 siblings, 0 replies; 5+ messages in thread
From: Parshuram Thombare @ 2020-11-28 14:46 UTC (permalink / raw)
  To: alexandre.belloni, slongerbeam, vitor.soares
  Cc: praneeth, mparab, linux-i3c, linux-kernel, Parshuram Thombare

add i3c_secondary_master_register which is used
to register secondary masters.

Signed-off-by: Parshuram Thombare <pthombar@cadence.com>
---
 drivers/i3c/master.c       |  154 +++++++++++++++++++++++++++++++++++++++++++-
 include/linux/i3c/master.h |    3 +
 2 files changed, 156 insertions(+), 1 deletions(-)

diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index 56e8fe4..af0630a 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -1797,6 +1797,90 @@ static int i3c_primary_master_bus_init(struct i3c_master_controller *master)
 	return ret;
 }
 
+/**
+ * i3c_secondary_master_bus_init() - initialize an I3C bus for secondary
+ * master
+ * @master: secondary master initializing the bus
+ *
+ * This function does
+ *
+ * 1. Attach I2C devs to the master
+ *
+ * 2. Call &i3c_master_controller_ops->bus_init() method to initialize
+ *    the master controller. That's usually where the bus mode is selected
+ *    (pure bus or mixed fast/slow bus)
+ *
+ * Once this is done, I2C devices should be usable.
+ *
+ * Return: a 0 in case of success, an negative error code otherwise.
+ */
+static int i3c_secondary_master_bus_init(struct i3c_master_controller *master)
+{
+	enum i3c_addr_slot_status status;
+	struct i2c_dev_boardinfo *i2cboardinfo;
+	struct i2c_dev_desc *i2cdev;
+	int ret;
+
+	/*
+	 * First attach all devices with static definitions provided by the
+	 * FW.
+	 */
+	list_for_each_entry(i2cboardinfo, &master->boardinfo.i2c, node) {
+		status = i3c_bus_get_addr_slot_status(&master->bus,
+						      i2cboardinfo->base.addr);
+		if (status != I3C_ADDR_SLOT_FREE) {
+			ret = -EBUSY;
+			goto err_detach_devs;
+		}
+
+		i3c_bus_set_addr_slot_status(&master->bus,
+					     i2cboardinfo->base.addr,
+					     I3C_ADDR_SLOT_I2C_DEV);
+
+		i2cdev = i3c_master_alloc_i2c_dev(master, i2cboardinfo);
+		if (IS_ERR(i2cdev)) {
+			ret = PTR_ERR(i2cdev);
+			goto err_detach_devs;
+		}
+
+		ret = i3c_master_attach_i2c_dev(master, i2cdev);
+		if (ret) {
+			i3c_master_free_i2c_dev(i2cdev);
+			goto err_detach_devs;
+		}
+	}
+
+	/*
+	 * Now execute the controller specific ->bus_init() routine, which
+	 * might configure its internal logic to match the bus limitations.
+	 */
+	ret = master->ops->bus_init(master);
+	if (ret)
+		goto err_detach_devs;
+
+	/*
+	 * The master device should have been instantiated in ->bus_init(),
+	 * complain if this was not the case.
+	 */
+	if (!master->this) {
+		dev_err(&master->dev,
+			"master_set_info() was not called in ->bus_init()\n");
+		ret = -EINVAL;
+		goto err_bus_cleanup;
+	}
+
+	return 0;
+
+err_bus_cleanup:
+	if (master->ops->bus_cleanup)
+		master->ops->bus_cleanup(master);
+
+err_detach_devs:
+	i3c_master_detach_free_devs(master);
+
+	return ret;
+}
+
 static void i3c_master_bus_cleanup(struct i3c_master_controller *master)
 {
 	if (master->ops->bus_cleanup)
@@ -2514,7 +2598,10 @@ static int i3c_master_init(struct i3c_master_controller *master,
 		goto err_put_dev;
 	}
 
-	ret = i3c_primary_master_bus_init(master);
+	if (secondary)
+		ret = i3c_secondary_master_bus_init(master);
+	else
+		ret = i3c_primary_master_bus_init(master);
 	if (ret)
 		goto err_destroy_wq;
 
@@ -2595,6 +2682,71 @@ int i3c_primary_master_register(struct i3c_master_controller *master,
 EXPORT_SYMBOL_GPL(i3c_primary_master_register);
 
 /**
+ * i3c_secondary_master_register() - register an I3C secondary master
+ * @master: master used to send frames on the bus
+ * @parent: the parent device (the one that provides this I3C master
+ *	    controller)
+ * @ops: the master controller operations
+ *
+ * This function does minimal required initialization for secondary
+ * master, rest functionality like creating and registering I2C
+ * and I3C devices is done in defslvs processing.
+ *
+ *  i3c_secondary_master_register() does following things -
+ * - creates and initializes the I3C bus
+ * - populates the bus with static I2C devs if @parent->of_node is not
+ *   NULL
+ *   initialization
+ * - allocate memory for defslvs_data.devs, which is used to receive
+ *   defslvs list
+ * - create I3C device representing this master
+ * - registers the I2C adapter and all I2C devices
+ *
+ * Return: 0 in case of success, a negative error code otherwise.
+ */
+int i3c_secondary_master_register(struct i3c_master_controller *master,
+				  struct device *parent,
+				  const struct i3c_master_controller_ops *ops)
+{
+	int ret;
+
+	ret = i3c_master_init(master, parent, ops, true);
+	if (ret)
+		return ret;
+
+	ret = device_add(&master->dev);
+	if (ret)
+		goto err_cleanup_bus;
+
+	/*
+	 * Expose our I3C bus as an I2C adapter so that I2C devices are exposed
+	 * through the I2C subsystem.
+	 */
+	ret = i3c_master_i2c_adapter_init(master);
+	if (ret)
+		goto err_del_dev;
+
+	/*
+	 * We're done initializing the bus and the controller, we can now
+	 * register I3C devices from defslvs list.
+	 */
+	master->init_done = true;
+
+	return 0;
+
+err_del_dev:
+	device_del(&master->dev);
+
+err_cleanup_bus:
+	i3c_master_bus_cleanup(master);
+
+	put_device(&master->dev);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(i3c_secondary_master_register);
+
+/**
  * i3c_master_unregister() - unregister an I3C master
  * @master: master used to send frames on the bus
  *
diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h
index e543f68..e186d53 100644
--- a/include/linux/i3c/master.h
+++ b/include/linux/i3c/master.h
@@ -541,6 +541,9 @@ int i3c_master_set_info(struct i3c_master_controller *master,
 int i3c_primary_master_register(struct i3c_master_controller *master,
 				struct device *parent,
 				const struct i3c_master_controller_ops *ops);
+int i3c_secondary_master_register(struct i3c_master_controller *master,
+				  struct device *parent,
+				  const struct i3c_master_controller_ops *ops);
 int i3c_master_unregister(struct i3c_master_controller *master);
 
 /**
-- 
1.7.1


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2020-11-29 17:38 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-29 17:38 [PATCH v9 3/7] i3c: master: add i3c_secondary_master_register kernel test robot
  -- strict thread matches above, loose matches on Subject: below --
2020-11-29 14:19 [RESEND PATCH v9 0/7] I3C mastership handover support Parshuram Thombare
2020-11-29 14:22 ` [PATCH v9 3/7] i3c: master: add i3c_secondary_master_register Parshuram Thombare
2020-11-29 14:22   ` Parshuram Thombare
2020-11-28 14:46 Parshuram Thombare
2020-11-28 14:46 ` Parshuram Thombare

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.