Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

i3c: master: fix for SETDASA and DAA process

This patch fix following issue.
Controller slots blocked for devices with static_addr
but no init_dyn_addr may limit the number of I3C devices
on the bus which gets dynamic address in DAA. So
instead of attaching all the devices with static_addr,
now we only attach the devices which successfully
complete SETDASA. For remaining devices with init_dyn_addr,
i3c_master_add_i3c_dev_locked() will try to set requested
dynamic address after DAA.

Signed-off-by: Parshuram Thombare <pthombar@cadence.com>
Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Link: https://lore.kernel.org/linux-i3c/1598337109-14770-1-git-send-email-pthombar@cadence.com

authored by

Parshuram Thombare and committed by
Boris Brezillon
cc3a392d 9da36a7e

+74 -51
+74 -51
drivers/i3c/master.c
··· 1373 1373 enum i3c_addr_slot_status status; 1374 1374 int ret; 1375 1375 1376 - if (dev->info.dyn_addr != old_dyn_addr) { 1376 + if (dev->info.dyn_addr != old_dyn_addr && 1377 + (!dev->boardinfo || 1378 + dev->info.dyn_addr != dev->boardinfo->init_dyn_addr)) { 1377 1379 status = i3c_bus_get_addr_slot_status(&master->bus, 1378 1380 dev->info.dyn_addr); 1379 1381 if (status != I3C_ADDR_SLOT_FREE) ··· 1434 1432 master->ops->detach_i2c_dev(dev); 1435 1433 } 1436 1434 1437 - static void i3c_master_pre_assign_dyn_addr(struct i3c_dev_desc *dev) 1435 + static int i3c_master_early_i3c_dev_add(struct i3c_master_controller *master, 1436 + struct i3c_dev_boardinfo *boardinfo) 1438 1437 { 1439 - struct i3c_master_controller *master = i3c_dev_get_master(dev); 1438 + struct i3c_device_info info = { 1439 + .static_addr = boardinfo->static_addr, 1440 + }; 1441 + struct i3c_dev_desc *i3cdev; 1440 1442 int ret; 1441 1443 1442 - if (!dev->boardinfo || !dev->boardinfo->init_dyn_addr || 1443 - !dev->boardinfo->static_addr) 1444 - return; 1444 + i3cdev = i3c_master_alloc_i3c_dev(master, &info); 1445 + if (IS_ERR(i3cdev)) 1446 + return -ENOMEM; 1445 1447 1446 - ret = i3c_master_setdasa_locked(master, dev->info.static_addr, 1447 - dev->boardinfo->init_dyn_addr); 1448 + i3cdev->boardinfo = boardinfo; 1449 + 1450 + ret = i3c_master_attach_i3c_dev(master, i3cdev); 1448 1451 if (ret) 1449 - return; 1452 + goto err_free_dev; 1450 1453 1451 - dev->info.dyn_addr = dev->boardinfo->init_dyn_addr; 1452 - ret = i3c_master_reattach_i3c_dev(dev, 0); 1454 + ret = i3c_master_setdasa_locked(master, i3cdev->info.static_addr, 1455 + i3cdev->boardinfo->init_dyn_addr); 1456 + if (ret) 1457 + goto err_detach_dev; 1458 + 1459 + i3cdev->info.dyn_addr = i3cdev->boardinfo->init_dyn_addr; 1460 + ret = i3c_master_reattach_i3c_dev(i3cdev, 0); 1453 1461 if (ret) 1454 1462 goto err_rstdaa; 1455 1463 1456 - ret = i3c_master_retrieve_dev_info(dev); 1464 + ret = i3c_master_retrieve_dev_info(i3cdev); 1457 1465 if (ret) 1458 1466 goto err_rstdaa; 1459 1467 1460 - return; 1468 + return 0; 1461 1469 1462 1470 err_rstdaa: 1463 - i3c_master_rstdaa_locked(master, dev->boardinfo->init_dyn_addr); 1471 + i3c_master_rstdaa_locked(master, i3cdev->boardinfo->init_dyn_addr); 1472 + err_detach_dev: 1473 + i3c_master_detach_i3c_dev(i3cdev); 1474 + err_free_dev: 1475 + i3c_master_free_i3c_dev(i3cdev); 1476 + 1477 + return ret; 1464 1478 } 1465 1479 1466 1480 static void ··· 1643 1625 * This function is following all initialisation steps described in the I3C 1644 1626 * specification: 1645 1627 * 1646 - * 1. Attach I2C and statically defined I3C devs to the master so that the 1647 - * master can fill its internal device table appropriately 1628 + * 1. Attach I2C devs to the master so that the master can fill its internal 1629 + * device table appropriately 1648 1630 * 1649 1631 * 2. Call &i3c_master_controller_ops->bus_init() method to initialize 1650 1632 * the master controller. That's usually where the bus mode is selected ··· 1656 1638 * 1657 1639 * 4. Disable all slave events. 1658 1640 * 1659 - * 5. Pre-assign dynamic addresses requested by the FW with SETDASA for I3C 1660 - * devices that have a static address 1641 + * 5. Reserve address slots for I3C devices with init_dyn_addr. And if devices 1642 + * also have static_addr, try to pre-assign dynamic addresses requested by 1643 + * the FW with SETDASA and attach corresponding statically defined I3C 1644 + * devices to the master. 1661 1645 * 1662 1646 * 6. Do a DAA (Dynamic Address Assignment) to assign dynamic addresses to all 1663 1647 * remaining I3C devices ··· 1673 1653 enum i3c_addr_slot_status status; 1674 1654 struct i2c_dev_boardinfo *i2cboardinfo; 1675 1655 struct i3c_dev_boardinfo *i3cboardinfo; 1676 - struct i3c_dev_desc *i3cdev; 1677 1656 struct i2c_dev_desc *i2cdev; 1678 1657 int ret; 1679 1658 ··· 1701 1682 ret = i3c_master_attach_i2c_dev(master, i2cdev); 1702 1683 if (ret) { 1703 1684 i3c_master_free_i2c_dev(i2cdev); 1704 - goto err_detach_devs; 1705 - } 1706 - } 1707 - list_for_each_entry(i3cboardinfo, &master->boardinfo.i3c, node) { 1708 - struct i3c_device_info info = { 1709 - .static_addr = i3cboardinfo->static_addr, 1710 - }; 1711 - 1712 - if (i3cboardinfo->init_dyn_addr) { 1713 - status = i3c_bus_get_addr_slot_status(&master->bus, 1714 - i3cboardinfo->init_dyn_addr); 1715 - if (status != I3C_ADDR_SLOT_FREE) { 1716 - ret = -EBUSY; 1717 - goto err_detach_devs; 1718 - } 1719 - } 1720 - 1721 - i3cdev = i3c_master_alloc_i3c_dev(master, &info); 1722 - if (IS_ERR(i3cdev)) { 1723 - ret = PTR_ERR(i3cdev); 1724 - goto err_detach_devs; 1725 - } 1726 - 1727 - i3cdev->boardinfo = i3cboardinfo; 1728 - 1729 - ret = i3c_master_attach_i3c_dev(master, i3cdev); 1730 - if (ret) { 1731 - i3c_master_free_i3c_dev(i3cdev); 1732 1685 goto err_detach_devs; 1733 1686 } 1734 1687 } ··· 1740 1749 goto err_bus_cleanup; 1741 1750 1742 1751 /* 1743 - * Pre-assign dynamic address and retrieve device information if 1744 - * needed. 1752 + * Reserve init_dyn_addr first, and then try to pre-assign dynamic 1753 + * address and retrieve device information if needed. 1754 + * In case pre-assign dynamic address fails, setting dynamic address to 1755 + * the requested init_dyn_addr is retried after DAA is done in 1756 + * i3c_master_add_i3c_dev_locked(). 1745 1757 */ 1746 - i3c_bus_for_each_i3cdev(&master->bus, i3cdev) 1747 - i3c_master_pre_assign_dyn_addr(i3cdev); 1758 + list_for_each_entry(i3cboardinfo, &master->boardinfo.i3c, node) { 1759 + 1760 + /* 1761 + * We don't reserve a dynamic address for devices that 1762 + * don't explicitly request one. 1763 + */ 1764 + if (!i3cboardinfo->init_dyn_addr) 1765 + continue; 1766 + 1767 + ret = i3c_bus_get_addr_slot_status(&master->bus, 1768 + i3cboardinfo->init_dyn_addr); 1769 + if (ret != I3C_ADDR_SLOT_FREE) { 1770 + ret = -EBUSY; 1771 + goto err_rstdaa; 1772 + } 1773 + 1774 + i3c_bus_set_addr_slot_status(&master->bus, 1775 + i3cboardinfo->init_dyn_addr, 1776 + I3C_ADDR_SLOT_I3C_DEV); 1777 + 1778 + /* 1779 + * Only try to create/attach devices that have a static 1780 + * address. Other devices will be created/attached when 1781 + * DAA happens, and the requested dynamic address will 1782 + * be set using SETNEWDA once those devices become 1783 + * addressable. 1784 + */ 1785 + 1786 + if (i3cboardinfo->static_addr) 1787 + i3c_master_early_i3c_dev_add(master, i3cboardinfo); 1788 + } 1748 1789 1749 1790 ret = i3c_master_do_daa(master); 1750 1791 if (ret)