Commit 401b0e0b authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull i3c updates from Alexandre Belloni:
 "Subsystem:
   - add sysfs option to rescan bus via entdaa
   - fix error code handling for send_ccc_cmd

  Drivers:
   - mipi-i3c-hci-pci: Intel Nova Lake-H I3C support"

* tag 'i3c/for-7.1' of git://git.kernel.org/pub/scm/linux/kernel/git/i3c/linux: (22 commits)
  i3c: mipi-i3c-hci: fix IBI payload length calculation for final status
  i3c: master: adi: Fix error propagation for CCCs
  i3c: master: Fix error codes at send_ccc_cmd
  i3c: master: Move bus_init error suppression
  i3c: master: Move entdaa error suppression
  i3c: master: Move rstdaa error suppression
  i3c: dw: Simplify xfer cleanup with __free(kfree)
  i3c: dw: Fix memory leak in dw_i3c_master_i3c_xfers()
  i3c: master: renesas: Use __free(kfree) for xfer cleanup in renesas_i3c_send_ccc_cmd()
  i3c: master: renesas: Fix memory leak in renesas_i3c_i3c_xfers()
  i3c: master: dw-i3c: Balance PM runtime usage count on probe failure
  i3c: master: dw-i3c: Fix missing reset assertion in remove() callback
  i3c: mipi-i3c-hci-pci: Enable IBI while runtime suspended for Intel controllers
  i3c: mipi-i3c-hci-pci: Add optional ability to manage child runtime PM
  i3c: mipi-i3c-hci: Allow parent to manage runtime PM
  i3c: mipi-i3c-hci: Add quirk to allow IBI while runtime suspended
  i3c: mipi-i3c-hci-pci: Set d3hot_delay to 0 for Intel controllers
  i3c: fix missing newline in dev_err messages
  i3c: master: use kzalloc_flex
  i3c: mipi-i3c-hci-pci: Add support for Intel Nova Lake-H I3C
  ...
parents eb5249b1 d35a6db8
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -172,3 +172,23 @@ Description:
		the automatic retries. Exist only when I3C constroller supports
		this retry on nack feature.

What:		/sys/bus/i3c/devices/i3c-<bus-id>/do_daa
KernelVersion:  7.0
Contact:	linux-i3c@vger.kernel.org
Description:
		Write-only attribute that triggers a Dynamic Address Assignment
		(DAA) procedure which discovers new I3C devices on the bus.
		Writing a boolean true value (1, y, yes, true, on) to this
		attribute causes the master controller to perform DAA, which
		includes broadcasting an ENTDAA (Enter Dynamic Address Assignment)
		Common Command Code (CCC) on the bus. Writing a false value
		returns -EINVAL.

		This is useful for discovering I3C devices that were not present
		during initial bus initialization and are unable to issue
		Hot-Join. Only devices without a currently assigned dynamic address
		will respond to the ENTDAA broadcast and be assigned addresses.

		Note that this mechanism is distinct from Hot-Join, since this is
		controller-initiated discovery, while Hot-Join is device-initiated
		method to provoke controller discovery procedure.
+70 −43
Original line number Diff line number Diff line
@@ -758,6 +758,32 @@ static ssize_t dev_nack_retry_count_store(struct device *dev,

static DEVICE_ATTR_RW(dev_nack_retry_count);

static ssize_t do_daa_store(struct device *dev,
			    struct device_attribute *attr,
			    const char *buf, size_t count)
{
	struct i3c_master_controller *master = dev_to_i3cmaster(dev);
	bool val;
	int ret;

	if (kstrtobool(buf, &val))
		return -EINVAL;

	if (!val)
		return -EINVAL;

	if (!master->init_done)
		return -EAGAIN;

	ret = i3c_master_do_daa(master);
	if (ret)
		return ret;

	return count;
}

static DEVICE_ATTR_WO(do_daa);

static struct attribute *i3c_masterdev_attrs[] = {
	&dev_attr_mode.attr,
	&dev_attr_current_master.attr,
@@ -769,6 +795,7 @@ static struct attribute *i3c_masterdev_attrs[] = {
	&dev_attr_dynamic_address.attr,
	&dev_attr_hdrcap.attr,
	&dev_attr_hotjoin.attr,
	&dev_attr_do_daa.attr,
	NULL,
};
ATTRIBUTE_GROUPS(i3c_masterdev);
@@ -898,11 +925,17 @@ static void i3c_ccc_cmd_init(struct i3c_ccc_cmd *cmd, bool rnw, u8 id,
	cmd->err = I3C_ERROR_UNKNOWN;
}

/**
 * i3c_master_send_ccc_cmd_locked() - send a CCC (Common Command Codes)
 * @master: master used to send frames on the bus
 * @cmd: command to send
 *
 * Return: 0 in case of success, or a negative error code otherwise.
 *         I3C Mx error codes are stored in cmd->err.
 */
static int i3c_master_send_ccc_cmd_locked(struct i3c_master_controller *master,
					  struct i3c_ccc_cmd *cmd)
{
	int ret;

	if (!cmd || !master)
		return -EINVAL;

@@ -920,15 +953,7 @@ static int i3c_master_send_ccc_cmd_locked(struct i3c_master_controller *master,
	    !master->ops->supports_ccc_cmd(master, cmd))
		return -EOPNOTSUPP;

	ret = master->ops->send_ccc_cmd(master, cmd);
	if (ret) {
		if (cmd->err != I3C_ERROR_UNKNOWN)
			return cmd->err;

		return ret;
	}

	return 0;
	return master->ops->send_ccc_cmd(master, cmd);
}

static struct i2c_dev_desc *
@@ -1016,6 +1041,10 @@ static int i3c_master_rstdaa_locked(struct i3c_master_controller *master,
	ret = i3c_master_send_ccc_cmd_locked(master, &cmd);
	i3c_ccc_cmd_dest_cleanup(&dest);

	/* No active devices on the bus. */
	if (ret && cmd.err == I3C_ERROR_M2)
		ret = 0;

	return ret;
}

@@ -1032,8 +1061,7 @@ static int i3c_master_rstdaa_locked(struct i3c_master_controller *master,
 *
 * This function must be called with the bus lock held in write mode.
 *
 * Return: 0 in case of success, a positive I3C error code if the error is
 * one of the official Mx error codes, and a negative error code otherwise.
 * Return: 0 in case of success, or a negative error code otherwise.
 */
int i3c_master_entdaa_locked(struct i3c_master_controller *master)
{
@@ -1046,12 +1074,17 @@ int i3c_master_entdaa_locked(struct i3c_master_controller *master)
	ret = i3c_master_send_ccc_cmd_locked(master, &cmd);
	i3c_ccc_cmd_dest_cleanup(&dest);

	/* No active devices need an address. */
	if (ret && cmd.err == I3C_ERROR_M2)
		ret = 0;

	return ret;
}
EXPORT_SYMBOL_GPL(i3c_master_entdaa_locked);

static int i3c_master_enec_disec_locked(struct i3c_master_controller *master,
					u8 addr, bool enable, u8 evts)
					u8 addr, bool enable, u8 evts,
					bool suppress_m2)
{
	struct i3c_ccc_events *events;
	struct i3c_ccc_cmd_dest dest;
@@ -1071,6 +1104,9 @@ static int i3c_master_enec_disec_locked(struct i3c_master_controller *master,
	ret = i3c_master_send_ccc_cmd_locked(master, &cmd);
	i3c_ccc_cmd_dest_cleanup(&dest);

	if (suppress_m2 && ret && cmd.err == I3C_ERROR_M2)
		ret = 0;

	return ret;
}

@@ -1085,13 +1121,12 @@ static int i3c_master_enec_disec_locked(struct i3c_master_controller *master,
 *
 * This function must be called with the bus lock held in write mode.
 *
 * Return: 0 in case of success, a positive I3C error code if the error is
 * one of the official Mx error codes, and a negative error code otherwise.
 * Return: 0 in case of success, or a negative error code otherwise.
 */
int i3c_master_disec_locked(struct i3c_master_controller *master, u8 addr,
			    u8 evts)
{
	return i3c_master_enec_disec_locked(master, addr, false, evts);
	return i3c_master_enec_disec_locked(master, addr, false, evts, false);
}
EXPORT_SYMBOL_GPL(i3c_master_disec_locked);

@@ -1106,13 +1141,12 @@ EXPORT_SYMBOL_GPL(i3c_master_disec_locked);
 *
 * This function must be called with the bus lock held in write mode.
 *
 * Return: 0 in case of success, a positive I3C error code if the error is
 * one of the official Mx error codes, and a negative error code otherwise.
 * Return: 0 in case of success, or a negative error code otherwise.
 */
int i3c_master_enec_locked(struct i3c_master_controller *master, u8 addr,
			   u8 evts)
{
	return i3c_master_enec_disec_locked(master, addr, true, evts);
	return i3c_master_enec_disec_locked(master, addr, true, evts, false);
}
EXPORT_SYMBOL_GPL(i3c_master_enec_locked);

@@ -1132,8 +1166,7 @@ EXPORT_SYMBOL_GPL(i3c_master_enec_locked);
 *
 * This function must be called with the bus lock held in write mode.
 *
 * Return: 0 in case of success, a positive I3C error code if the error is
 * one of the official Mx error codes, and a negative error code otherwise.
 * Return: 0 in case of success, or a negative error code otherwise.
 */
int i3c_master_defslvs_locked(struct i3c_master_controller *master)
{
@@ -1794,11 +1827,8 @@ int i3c_master_do_daa_ext(struct i3c_master_controller *master, bool rstdaa)

	i3c_bus_maintenance_lock(&master->bus);

	if (rstdaa) {
	if (rstdaa)
		rstret = i3c_master_rstdaa_locked(master, I3C_BROADCAST_ADDR);
		if (rstret == I3C_ERROR_M2)
			rstret = 0;
	}

	ret = master->ops->do_daa(master);

@@ -2093,7 +2123,7 @@ static int i3c_master_bus_init(struct i3c_master_controller *master)
	 * (assigned by the bootloader for example).
	 */
	ret = i3c_master_rstdaa_locked(master, I3C_BROADCAST_ADDR);
	if (ret && ret != I3C_ERROR_M2)
	if (ret)
		goto err_bus_cleanup;

	if (master->ops->set_speed) {
@@ -2102,11 +2132,14 @@ static int i3c_master_bus_init(struct i3c_master_controller *master)
			goto err_bus_cleanup;
	}

	/* Disable all slave events before starting DAA. */
	ret = i3c_master_disec_locked(master, I3C_BROADCAST_ADDR,
	/*
	 * Disable all slave events before starting DAA. When no active device
	 * is on the bus, returns Mx error code M2, this error is ignored.
	 */
	ret = i3c_master_enec_disec_locked(master, I3C_BROADCAST_ADDR, false,
					   I3C_CCC_EVENT_SIR | I3C_CCC_EVENT_MR |
				      I3C_CCC_EVENT_HJ);
	if (ret && ret != I3C_ERROR_M2)
					   I3C_CCC_EVENT_HJ, true);
	if (ret)
		goto err_bus_cleanup;

	/*
@@ -2396,7 +2429,7 @@ of_i3c_master_add_i2c_boardinfo(struct i3c_master_controller *master,
	 * DEFSLVS command.
	 */
	if (boardinfo->base.flags & I2C_CLIENT_TEN) {
		dev_err(dev, "I2C device with 10 bit address not supported.");
		dev_err(dev, "I2C device with 10 bit address not supported.\n");
		return -EOPNOTSUPP;
	}

@@ -2793,10 +2826,10 @@ struct i3c_generic_ibi_slot {
struct i3c_generic_ibi_pool {
	spinlock_t lock;
	unsigned int num_slots;
	struct i3c_generic_ibi_slot *slots;
	void *payload_buf;
	struct list_head free_slots;
	struct list_head pending;
	struct i3c_generic_ibi_slot slots[] __counted_by(num_slots);
};

/**
@@ -2824,7 +2857,6 @@ void i3c_generic_ibi_free_pool(struct i3c_generic_ibi_pool *pool)
	WARN_ON(nslots != pool->num_slots);

	kfree(pool->payload_buf);
	kfree(pool->slots);
	kfree(pool);
}
EXPORT_SYMBOL_GPL(i3c_generic_ibi_free_pool);
@@ -2847,20 +2879,16 @@ i3c_generic_ibi_alloc_pool(struct i3c_dev_desc *dev,
	unsigned int i;
	int ret;

	pool = kzalloc_obj(*pool);
	pool = kzalloc_flex(*pool, slots, req->num_slots);
	if (!pool)
		return ERR_PTR(-ENOMEM);

	pool->num_slots = req->num_slots;

	spin_lock_init(&pool->lock);
	INIT_LIST_HEAD(&pool->free_slots);
	INIT_LIST_HEAD(&pool->pending);

	pool->slots = kzalloc_objs(*slot, req->num_slots);
	if (!pool->slots) {
		ret = -ENOMEM;
		goto err_free_pool;
	}

	if (req->max_payload_len) {
		pool->payload_buf = kcalloc(req->num_slots,
					    req->max_payload_len, GFP_KERNEL);
@@ -2879,7 +2907,6 @@ i3c_generic_ibi_alloc_pool(struct i3c_dev_desc *dev,
					  (i * req->max_payload_len);

		list_add_tail(&slot->node, &pool->free_slots);
		pool->num_slots++;
	}

	return pool;
+2 −3
Original line number Diff line number Diff line
@@ -361,7 +361,7 @@ static int adi_i3c_master_send_ccc_cmd(struct i3c_master_controller *m,

	cmd->err = adi_i3c_cmd_get_err(&xfer->cmds[0]);

	return 0;
	return xfer->ret;
}

static int adi_i3c_master_i3c_xfers(struct i3c_dev_desc *dev,
@@ -655,8 +655,7 @@ static int adi_i3c_master_do_daa(struct i3c_master_controller *m)

	writel(irq_mask, master->regs + REG_IRQ_MASK);

	/* DAA always finishes with CE2_ERROR or NACK_RESP */
	if (ret && ret != I3C_ERROR_M2)
	if (ret)
		return ret;

	/* Add I3C devices discovered */
+14 −37
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@

#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/cleanup.h>
#include <linux/clk.h>
#include <linux/completion.h>
#include <linux/err.h>
@@ -393,11 +394,6 @@ dw_i3c_master_alloc_xfer(struct dw_i3c_master *master, unsigned int ncmds)
	return xfer;
}

static void dw_i3c_master_free_xfer(struct dw_i3c_xfer *xfer)
{
	kfree(xfer);
}

static void dw_i3c_master_start_xfer_locked(struct dw_i3c_master *master)
{
	struct dw_i3c_xfer *xfer = master->xferqueue.cur;
@@ -715,7 +711,6 @@ static void dw_i3c_master_bus_cleanup(struct i3c_master_controller *m)
static int dw_i3c_ccc_set(struct dw_i3c_master *master,
			  struct i3c_ccc_cmd *ccc)
{
	struct dw_i3c_xfer *xfer;
	struct dw_i3c_cmd *cmd;
	int ret, pos = 0;

@@ -725,7 +720,7 @@ static int dw_i3c_ccc_set(struct dw_i3c_master *master,
			return pos;
	}

	xfer = dw_i3c_master_alloc_xfer(master, 1);
	struct dw_i3c_xfer *xfer __free(kfree) = dw_i3c_master_alloc_xfer(master, 1);
	if (!xfer)
		return -ENOMEM;

@@ -750,14 +745,11 @@ static int dw_i3c_ccc_set(struct dw_i3c_master *master,
	if (xfer->cmds[0].error == RESPONSE_ERROR_IBA_NACK)
		ccc->err = I3C_ERROR_M2;

	dw_i3c_master_free_xfer(xfer);

	return ret;
}

static int dw_i3c_ccc_get(struct dw_i3c_master *master, struct i3c_ccc_cmd *ccc)
{
	struct dw_i3c_xfer *xfer;
	struct dw_i3c_cmd *cmd;
	int ret, pos;

@@ -765,7 +757,7 @@ static int dw_i3c_ccc_get(struct dw_i3c_master *master, struct i3c_ccc_cmd *ccc)
	if (pos < 0)
		return pos;

	xfer = dw_i3c_master_alloc_xfer(master, 1);
	struct dw_i3c_xfer *xfer __free(kfree) = dw_i3c_master_alloc_xfer(master, 1);
	if (!xfer)
		return -ENOMEM;

@@ -790,7 +782,6 @@ static int dw_i3c_ccc_get(struct dw_i3c_master *master, struct i3c_ccc_cmd *ccc)
	ret = xfer->ret;
	if (xfer->cmds[0].error == RESPONSE_ERROR_IBA_NACK)
		ccc->err = I3C_ERROR_M2;
	dw_i3c_master_free_xfer(xfer);

	return ret;
}
@@ -837,12 +828,15 @@ static int dw_i3c_master_send_ccc_cmd(struct i3c_master_controller *m,
static int dw_i3c_master_daa(struct i3c_master_controller *m)
{
	struct dw_i3c_master *master = to_dw_i3c_master(m);
	struct dw_i3c_xfer *xfer;
	struct dw_i3c_cmd *cmd;
	u32 olddevs, newdevs;
	u8 last_addr = 0;
	int ret, pos;

	struct dw_i3c_xfer *xfer __free(kfree) = dw_i3c_master_alloc_xfer(master, 1);
	if (!xfer)
		return -ENOMEM;

	ret = pm_runtime_resume_and_get(master->dev);
	if (ret < 0) {
		dev_err(master->dev,
@@ -876,15 +870,8 @@ static int dw_i3c_master_daa(struct i3c_master_controller *m)
		ret = 0;
	}

	xfer = dw_i3c_master_alloc_xfer(master, 1);
	if (!xfer) {
		ret = -ENOMEM;
		goto rpm_out;
	}

	pos = dw_i3c_master_get_free_pos(master);
	if (pos < 0) {
		dw_i3c_master_free_xfer(xfer);
		ret = pos;
		goto rpm_out;
	}
@@ -909,8 +896,6 @@ static int dw_i3c_master_daa(struct i3c_master_controller *m)
			i3c_master_add_i3c_dev_locked(m, master->devs[pos].addr);
	}

	dw_i3c_master_free_xfer(xfer);

rpm_out:
	pm_runtime_put_autosuspend(master->dev);
	return ret;
@@ -924,7 +909,6 @@ static int dw_i3c_master_i3c_xfers(struct i3c_dev_desc *dev,
	struct i3c_master_controller *m = i3c_dev_get_master(dev);
	struct dw_i3c_master *master = to_dw_i3c_master(m);
	unsigned int nrxwords = 0, ntxwords = 0;
	struct dw_i3c_xfer *xfer;
	int i, ret = 0;

	if (!i3c_nxfers)
@@ -944,7 +928,7 @@ static int dw_i3c_master_i3c_xfers(struct i3c_dev_desc *dev,
	    nrxwords > master->caps.datafifodepth)
		return -EOPNOTSUPP;

	xfer = dw_i3c_master_alloc_xfer(master, i3c_nxfers);
	struct dw_i3c_xfer *xfer __free(kfree) = dw_i3c_master_alloc_xfer(master, i3c_nxfers);
	if (!xfer)
		return -ENOMEM;

@@ -995,7 +979,6 @@ static int dw_i3c_master_i3c_xfers(struct i3c_dev_desc *dev,
	}

	ret = xfer->ret;
	dw_i3c_master_free_xfer(xfer);

	pm_runtime_put_autosuspend(master->dev);
	return ret;
@@ -1084,7 +1067,6 @@ static int dw_i3c_master_i2c_xfers(struct i2c_dev_desc *dev,
	struct i3c_master_controller *m = i2c_dev_get_master(dev);
	struct dw_i3c_master *master = to_dw_i3c_master(m);
	unsigned int nrxwords = 0, ntxwords = 0;
	struct dw_i3c_xfer *xfer;
	int i, ret = 0;

	if (!i2c_nxfers)
@@ -1104,7 +1086,7 @@ static int dw_i3c_master_i2c_xfers(struct i2c_dev_desc *dev,
	    nrxwords > master->caps.datafifodepth)
		return -EOPNOTSUPP;

	xfer = dw_i3c_master_alloc_xfer(master, i2c_nxfers);
	struct dw_i3c_xfer *xfer __free(kfree) = dw_i3c_master_alloc_xfer(master, i2c_nxfers);
	if (!xfer)
		return -ENOMEM;

@@ -1113,7 +1095,6 @@ static int dw_i3c_master_i2c_xfers(struct i2c_dev_desc *dev,
		dev_err(master->dev,
			"<%s> cannot resume i3c bus master, err: %d\n",
			__func__, ret);
		dw_i3c_master_free_xfer(xfer);
		return ret;
	}

@@ -1145,7 +1126,6 @@ static int dw_i3c_master_i2c_xfers(struct i2c_dev_desc *dev,
		dw_i3c_master_dequeue_xfer(master, xfer);

	ret = xfer->ret;
	dw_i3c_master_free_xfer(xfer);

	pm_runtime_put_autosuspend(master->dev);
	return ret;
@@ -1606,13 +1586,11 @@ int dw_i3c_common_probe(struct dw_i3c_master *master,
	if (IS_ERR(master->pclk))
		return PTR_ERR(master->pclk);

	master->core_rst = devm_reset_control_get_optional_exclusive(&pdev->dev,
	master->core_rst = devm_reset_control_get_optional_exclusive_deasserted(&pdev->dev,
										"core_rst");
	if (IS_ERR(master->core_rst))
		return PTR_ERR(master->core_rst);

	reset_control_deassert(master->core_rst);

	spin_lock_init(&master->xferqueue.lock);
	INIT_LIST_HEAD(&master->xferqueue.list);

@@ -1624,7 +1602,7 @@ int dw_i3c_common_probe(struct dw_i3c_master *master,
			       dw_i3c_master_irq_handler, 0,
			       dev_name(&pdev->dev), master);
	if (ret)
		goto err_assert_rst;
		return ret;

	platform_set_drvdata(pdev, master);

@@ -1669,13 +1647,12 @@ int dw_i3c_common_probe(struct dw_i3c_master *master,
	return 0;

err_disable_pm:
	if (master->quirks & DW_I3C_DISABLE_RUNTIME_PM_QUIRK)
		pm_runtime_put_noidle(&pdev->dev);
	pm_runtime_disable(&pdev->dev);
	pm_runtime_set_suspended(&pdev->dev);
	pm_runtime_dont_use_autosuspend(&pdev->dev);

err_assert_rst:
	reset_control_assert(master->core_rst);

	return ret;
}
EXPORT_SYMBOL_GPL(dw_i3c_common_probe);
+1 −1
Original line number Diff line number Diff line
@@ -1143,7 +1143,7 @@ static int cdns_i3c_master_do_daa(struct i3c_master_controller *m)
	}

	ret = i3c_master_entdaa_locked(&master->base);
	if (ret && ret != I3C_ERROR_M2)
	if (ret)
		return ret;

	newdevs = readl(master->regs + DEVS_CTRL) & DEVS_CTRL_DEVS_ACTIVE_MASK;
Loading