[PATCH 4/6] i3c: master: Add a routine to include the I3C SPD device

Shyam Sundar S K posted 6 patches 1 month, 1 week ago
There is a newer version of this series
[PATCH 4/6] i3c: master: Add a routine to include the I3C SPD device
Posted by Shyam Sundar S K 1 month, 1 week ago
Implement the i3c_master_add_spd_dev() function in the I3C master to
handle SPD (Serial Presence Detect) device creation and map the board
information into the I3C device structure.

Co-developed-by: Sanket Goswami <Sanket.Goswami@amd.com>
Signed-off-by: Sanket Goswami <Sanket.Goswami@amd.com>
Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
---
 drivers/i3c/master.c | 41 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)

diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index 20b83ca52d31..4f149519170e 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -1657,6 +1657,45 @@ i3c_master_register_new_i3c_devs(struct i3c_master_controller *master)
 	}
 }
 
+static int i3c_master_add_spd_dev(struct i3c_master_controller *master,
+				  struct i3c_dev_boardinfo *boardinfo)
+{
+	struct i3c_dev_desc *i3cdev;
+	int ret;
+
+	list_for_each_entry(boardinfo, &master->boardinfo.i3c, node) {
+		struct i3c_device_info info = {
+			.static_addr = boardinfo->static_addr,
+		};
+
+		ret = i3c_bus_get_addr_slot_status(&master->bus, boardinfo->static_addr);
+		if (ret != I3C_ADDR_SLOT_FREE)
+			return -EBUSY;
+
+		i3cdev = i3c_master_alloc_i3c_dev(master, &info);
+		if (IS_ERR(i3cdev))
+			return -ENOMEM;
+
+		i3cdev->boardinfo = boardinfo;
+		ret = i3c_master_attach_i3c_dev(master, i3cdev);
+		if (ret)
+			goto err_free_dev;
+
+		i3cdev->info.pid = i3cdev->boardinfo->pid;
+		i3cdev->info.dyn_addr = i3cdev->boardinfo->init_dyn_addr;
+
+		i3c_bus_normaluse_lock(&master->bus);
+		i3c_master_register_new_i3c_devs(master);
+		i3c_bus_normaluse_unlock(&master->bus);
+	}
+
+	return 0;
+
+err_free_dev:
+	i3c_master_free_i3c_dev(i3cdev);
+	return ret;
+}
+
 /**
  * i3c_master_do_daa() - do a DAA (Dynamic Address Assignment)
  * @master: master doing the DAA
@@ -1868,6 +1907,8 @@ static int i3c_master_bus_init(struct i3c_master_controller *master)
 		goto err_bus_cleanup;
 	}
 
+	i3c_master_add_spd_dev(master, i3cboardinfo);
+
 	if (master->ops->set_speed) {
 		ret = master->ops->set_speed(master, I3C_OPEN_DRAIN_SLOW_SPEED);
 		if (ret)
-- 
2.34.1
Re: [PATCH 4/6] i3c: master: Add a routine to include the I3C SPD device
Posted by kernel test robot 1 month, 1 week ago
Hi Shyam,

kernel test robot noticed the following build warnings:

[auto build test WARNING on linus/master]
[also build test WARNING on v6.12-rc3 next-20241018]
[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#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Shyam-Sundar-S-K/i3c-dw-Add-support-for-AMDI0015-ACPI-ID/20241017-230810
base:   linus/master
patch link:    https://lore.kernel.org/r/20241017150330.3035568-5-Shyam-sundar.S-k%40amd.com
patch subject: [PATCH 4/6] i3c: master: Add a routine to include the I3C SPD device
config: arm-randconfig-r073-20241020 (https://download.01.org/0day-ci/archive/20241020/202410201938.oiMeI2Pu-lkp@intel.com/config)
compiler: clang version 20.0.0git (https://github.com/llvm/llvm-project bfe84f7085d82d06d61c632a7bad1e692fd159e4)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241020/202410201938.oiMeI2Pu-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202410201938.oiMeI2Pu-lkp@intel.com/

All warnings (new ones prefixed by >>):

   In file included from drivers/i3c/master.c:21:
   In file included from drivers/i3c/internals.h:11:
   In file included from include/linux/i3c/master.h:14:
   In file included from include/linux/i2c.h:19:
   In file included from include/linux/regulator/consumer.h:35:
   In file included from include/linux/suspend.h:5:
   In file included from include/linux/swap.h:9:
   In file included from include/linux/memcontrol.h:21:
   In file included from include/linux/mm.h:2213:
   include/linux/vmstat.h:518:36: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
     518 |         return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_"
         |                               ~~~~~~~~~~~ ^ ~~~
>> drivers/i3c/master.c:1910:33: warning: variable 'i3cboardinfo' is uninitialized when used here [-Wuninitialized]
    1910 |         i3c_master_add_spd_dev(master, i3cboardinfo);
         |                                        ^~~~~~~~~~~~
   drivers/i3c/master.c:1856:40: note: initialize the variable 'i3cboardinfo' to silence this warning
    1856 |         struct i3c_dev_boardinfo *i3cboardinfo;
         |                                               ^
         |                                                = NULL
   drivers/i3c/master.c:2324:12: error: call to undeclared function 'acpi_evaluate_integer'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
    2324 |                 status = acpi_evaluate_integer(adev->handle, "_ADR", NULL, &val);
         |                          ^
   drivers/i3c/master.c:2324:12: note: did you mean 'acpi_evaluate_object'?
   include/acpi/acpixf.h:550:8: note: 'acpi_evaluate_object' declared here
     550 |                             acpi_evaluate_object(acpi_handle object,
         |                             ^
   include/acpi/platform/aclinux.h:93:21: note: expanded from macro 'ACPI_EXTERNAL_RETURN_STATUS'
      93 |         static ACPI_INLINE prototype {return(AE_NOT_CONFIGURED);}
         |                            ^
   drivers/i3c/master.c:2324:38: error: incomplete definition of type 'struct acpi_device'
    2324 |                 status = acpi_evaluate_integer(adev->handle, "_ADR", NULL, &val);
         |                                                ~~~~^
   include/linux/acpi.h:801:8: note: forward declaration of 'struct acpi_device'
     801 | struct acpi_device;
         |        ^
   drivers/i3c/master.c:2352:27: warning: shift count is negative [-Wshift-count-negative]
    2352 |                 boardinfo->pid = (val & GENMASK(47, 0));
         |                                         ^~~~~~~~~~~~~~
   include/linux/bits.h:35:31: note: expanded from macro 'GENMASK'
      35 |         (GENMASK_INPUT_CHECK(h, l) + __GENMASK(h, l))
         |                                      ^~~~~~~~~~~~~~~
   include/uapi/linux/bits.h:9:19: note: expanded from macro '__GENMASK'
       9 |          (~_UL(0) >> (__BITS_PER_LONG - 1 - (h))))
         |                   ^  ~~~~~~~~~~~~~~~~~~~~~~~~~~~
   3 warnings and 2 errors generated.


vim +/i3cboardinfo +1910 drivers/i3c/master.c

  1819	
  1820	/**
  1821	 * i3c_master_bus_init() - initialize an I3C bus
  1822	 * @master: main master initializing the bus
  1823	 *
  1824	 * This function is following all initialisation steps described in the I3C
  1825	 * specification:
  1826	 *
  1827	 * 1. Attach I2C devs to the master so that the master can fill its internal
  1828	 *    device table appropriately
  1829	 *
  1830	 * 2. Call &i3c_master_controller_ops->bus_init() method to initialize
  1831	 *    the master controller. That's usually where the bus mode is selected
  1832	 *    (pure bus or mixed fast/slow bus)
  1833	 *
  1834	 * 3. Instruct all devices on the bus to drop their dynamic address. This is
  1835	 *    particularly important when the bus was previously configured by someone
  1836	 *    else (for example the bootloader)
  1837	 *
  1838	 * 4. Disable all slave events.
  1839	 *
  1840	 * 5. Reserve address slots for I3C devices with init_dyn_addr. And if devices
  1841	 *    also have static_addr, try to pre-assign dynamic addresses requested by
  1842	 *    the FW with SETDASA and attach corresponding statically defined I3C
  1843	 *    devices to the master.
  1844	 *
  1845	 * 6. Do a DAA (Dynamic Address Assignment) to assign dynamic addresses to all
  1846	 *    remaining I3C devices
  1847	 *
  1848	 * Once this is done, all I3C and I2C devices should be usable.
  1849	 *
  1850	 * Return: a 0 in case of success, an negative error code otherwise.
  1851	 */
  1852	static int i3c_master_bus_init(struct i3c_master_controller *master)
  1853	{
  1854		enum i3c_addr_slot_status status;
  1855		struct i2c_dev_boardinfo *i2cboardinfo;
  1856		struct i3c_dev_boardinfo *i3cboardinfo;
  1857		struct i2c_dev_desc *i2cdev;
  1858		int ret;
  1859	
  1860		/*
  1861		 * First attach all devices with static definitions provided by the
  1862		 * FW.
  1863		 */
  1864		list_for_each_entry(i2cboardinfo, &master->boardinfo.i2c, node) {
  1865			status = i3c_bus_get_addr_slot_status(&master->bus,
  1866							      i2cboardinfo->base.addr);
  1867			if (status != I3C_ADDR_SLOT_FREE) {
  1868				ret = -EBUSY;
  1869				goto err_detach_devs;
  1870			}
  1871	
  1872			i3c_bus_set_addr_slot_status(&master->bus,
  1873						     i2cboardinfo->base.addr,
  1874						     I3C_ADDR_SLOT_I2C_DEV);
  1875	
  1876			i2cdev = i3c_master_alloc_i2c_dev(master,
  1877							  i2cboardinfo->base.addr,
  1878							  i2cboardinfo->lvr);
  1879			if (IS_ERR(i2cdev)) {
  1880				ret = PTR_ERR(i2cdev);
  1881				goto err_detach_devs;
  1882			}
  1883	
  1884			ret = i3c_master_attach_i2c_dev(master, i2cdev);
  1885			if (ret) {
  1886				i3c_master_free_i2c_dev(i2cdev);
  1887				goto err_detach_devs;
  1888			}
  1889		}
  1890	
  1891		/*
  1892		 * Now execute the controller specific ->bus_init() routine, which
  1893		 * might configure its internal logic to match the bus limitations.
  1894		 */
  1895		ret = master->ops->bus_init(master);
  1896		if (ret)
  1897			goto err_detach_devs;
  1898	
  1899		/*
  1900		 * The master device should have been instantiated in ->bus_init(),
  1901		 * complain if this was not the case.
  1902		 */
  1903		if (!master->this) {
  1904			dev_err(&master->dev,
  1905				"master_set_info() was not called in ->bus_init()\n");
  1906			ret = -EINVAL;
  1907			goto err_bus_cleanup;
  1908		}
  1909	
> 1910		i3c_master_add_spd_dev(master, i3cboardinfo);
  1911	
  1912		if (master->ops->set_speed) {
  1913			ret = master->ops->set_speed(master, I3C_OPEN_DRAIN_SLOW_SPEED);
  1914			if (ret)
  1915				goto err_bus_cleanup;
  1916		}
  1917	
  1918		/*
  1919		 * Reset all dynamic address that may have been assigned before
  1920		 * (assigned by the bootloader for example).
  1921		 */
  1922		ret = i3c_master_rstdaa_locked(master, I3C_BROADCAST_ADDR);
  1923		if (ret && ret != I3C_ERROR_M2)
  1924			goto err_bus_cleanup;
  1925	
  1926		if (master->ops->set_speed) {
  1927			master->ops->set_speed(master, I3C_OPEN_DRAIN_NORMAL_SPEED);
  1928			if (ret)
  1929				goto err_bus_cleanup;
  1930		}
  1931	
  1932		/* Disable all slave events before starting DAA. */
  1933		ret = i3c_master_disec_locked(master, I3C_BROADCAST_ADDR,
  1934					      I3C_CCC_EVENT_SIR | I3C_CCC_EVENT_MR |
  1935					      I3C_CCC_EVENT_HJ);
  1936		if (ret && ret != I3C_ERROR_M2)
  1937			goto err_bus_cleanup;
  1938	
  1939		/*
  1940		 * Reserve init_dyn_addr first, and then try to pre-assign dynamic
  1941		 * address and retrieve device information if needed.
  1942		 * In case pre-assign dynamic address fails, setting dynamic address to
  1943		 * the requested init_dyn_addr is retried after DAA is done in
  1944		 * i3c_master_add_i3c_dev_locked().
  1945		 */
  1946		list_for_each_entry(i3cboardinfo, &master->boardinfo.i3c, node) {
  1947	
  1948			/*
  1949			 * We don't reserve a dynamic address for devices that
  1950			 * don't explicitly request one.
  1951			 */
  1952			if (!i3cboardinfo->init_dyn_addr)
  1953				continue;
  1954	
  1955			ret = i3c_bus_get_addr_slot_status(&master->bus,
  1956							   i3cboardinfo->init_dyn_addr);
  1957			if (ret != I3C_ADDR_SLOT_FREE) {
  1958				ret = -EBUSY;
  1959				goto err_rstdaa;
  1960			}
  1961	
  1962			i3c_bus_set_addr_slot_status(&master->bus,
  1963						     i3cboardinfo->init_dyn_addr,
  1964						     I3C_ADDR_SLOT_I3C_DEV);
  1965	
  1966			/*
  1967			 * Only try to create/attach devices that have a static
  1968			 * address. Other devices will be created/attached when
  1969			 * DAA happens, and the requested dynamic address will
  1970			 * be set using SETNEWDA once those devices become
  1971			 * addressable.
  1972			 */
  1973	
  1974			if (i3cboardinfo->static_addr)
  1975				i3c_master_early_i3c_dev_add(master, i3cboardinfo);
  1976		}
  1977	
  1978		ret = i3c_master_do_daa(master);
  1979		if (ret)
  1980			goto err_rstdaa;
  1981	
  1982		return 0;
  1983	
  1984	err_rstdaa:
  1985		i3c_master_rstdaa_locked(master, I3C_BROADCAST_ADDR);
  1986	
  1987	err_bus_cleanup:
  1988		if (master->ops->bus_cleanup)
  1989			master->ops->bus_cleanup(master);
  1990	
  1991	err_detach_devs:
  1992		i3c_master_detach_free_devs(master);
  1993	
  1994		return ret;
  1995	}
  1996	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki