Commit 7116747a authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull soundwire updates from Vinod Koul:

 - bus cleanup for warnings and probe deferral errors suppression

 - cadence recheck for status with a delayed work

 - intel interrupt rework on reset exit

* tag 'soundwire-6.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/soundwire:
  soundwire: intel_bus_common: enable interrupts before exiting reset
  soundwire: cadence: re-check Peripheral status with delayed_work
  soundwire: bus: clean up probe warnings
  soundwire: bus: drop unused driver name field
  soundwire: bus: suppress probe deferral errors
parents f34c5125 5aedb8d8
Loading
Loading
Loading
Loading
+4 −15
Original line number Diff line number Diff line
@@ -83,7 +83,6 @@ static int sdw_drv_probe(struct device *dev)
	struct sdw_slave *slave = dev_to_sdw_dev(dev);
	struct sdw_driver *drv = drv_to_sdw_driver(dev->driver);
	const struct sdw_device_id *id;
	const char *name;
	int ret;

	/*
@@ -108,11 +107,6 @@ static int sdw_drv_probe(struct device *dev)

	ret = drv->probe(slave, id);
	if (ret) {
		name = drv->name;
		if (!name)
			name = drv->driver.name;

		dev_err(dev, "Probe of %s failed: %d\n", name, ret);
		dev_pm_domain_detach(dev, false);
		return ret;
	}
@@ -129,7 +123,7 @@ static int sdw_drv_probe(struct device *dev)
	/* init the dynamic sysfs attributes we need */
	ret = sdw_slave_sysfs_dpn_init(slave);
	if (ret < 0)
		dev_warn(dev, "Slave sysfs init failed:%d\n", ret);
		dev_warn(dev, "failed to initialise sysfs: %d\n", ret);

	/*
	 * Check for valid clk_stop_timeout, use DisCo worst case value of
@@ -153,7 +147,7 @@ static int sdw_drv_probe(struct device *dev)
	if (drv->ops && drv->ops->update_status) {
		ret = drv->ops->update_status(slave, slave->status);
		if (ret < 0)
			dev_warn(dev, "%s: update_status failed with status %d\n", __func__, ret);
			dev_warn(dev, "failed to update status at probe: %d\n", ret);
	}

	mutex_unlock(&slave->sdw_dev_lock);
@@ -204,16 +198,11 @@ static void sdw_drv_shutdown(struct device *dev)
 */
int __sdw_register_driver(struct sdw_driver *drv, struct module *owner)
{
	const char *name;

	drv->driver.bus = &sdw_bus_type;

	if (!drv->probe) {
		name = drv->name;
		if (!name)
			name = drv->driver.name;

		pr_err("driver %s didn't provide SDW probe routine\n", name);
		pr_err("driver %s didn't provide SDW probe routine\n",
				drv->driver.name);
		return -EINVAL;
	}

+37 −2
Original line number Diff line number Diff line
@@ -890,8 +890,14 @@ static int cdns_update_slave_status(struct sdw_cdns *cdns,
		}
	}

	if (is_slave)
		return sdw_handle_slave_status(&cdns->bus, status);
	if (is_slave) {
		int ret;

		mutex_lock(&cdns->status_update_lock);
		ret = sdw_handle_slave_status(&cdns->bus, status);
		mutex_unlock(&cdns->status_update_lock);
		return ret;
	}

	return 0;
}
@@ -988,6 +994,31 @@ irqreturn_t sdw_cdns_irq(int irq, void *dev_id)
}
EXPORT_SYMBOL(sdw_cdns_irq);

static void cdns_check_attached_status_dwork(struct work_struct *work)
{
	struct sdw_cdns *cdns =
		container_of(work, struct sdw_cdns, attach_dwork.work);
	enum sdw_slave_status status[SDW_MAX_DEVICES + 1];
	u32 val;
	int ret;
	int i;

	val = cdns_readl(cdns, CDNS_MCP_SLAVE_STAT);

	for (i = 0; i <= SDW_MAX_DEVICES; i++) {
		status[i] = val & 0x3;
		if (status[i])
			dev_dbg(cdns->dev, "Peripheral %d status: %d\n", i, status[i]);
		val >>= 2;
	}

	mutex_lock(&cdns->status_update_lock);
	ret = sdw_handle_slave_status(&cdns->bus, status);
	mutex_unlock(&cdns->status_update_lock);
	if (ret < 0)
		dev_err(cdns->dev, "%s: sdw_handle_slave_status failed: %d\n", __func__, ret);
}

/**
 * cdns_update_slave_status_work - update slave status in a work since we will need to handle
 * other interrupts eg. CDNS_MCP_INT_RX_WL during the update slave
@@ -1740,7 +1771,11 @@ int sdw_cdns_probe(struct sdw_cdns *cdns)
	init_completion(&cdns->tx_complete);
	cdns->bus.port_ops = &cdns_port_ops;

	mutex_init(&cdns->status_update_lock);

	INIT_WORK(&cdns->work, cdns_update_slave_status_work);
	INIT_DELAYED_WORK(&cdns->attach_dwork, cdns_check_attached_status_dwork);

	return 0;
}
EXPORT_SYMBOL(sdw_cdns_probe);
+5 −0
Original line number Diff line number Diff line
@@ -117,6 +117,8 @@ struct sdw_cdns_dai_runtime {
 * @link_up: Link status
 * @msg_count: Messages sent on bus
 * @dai_runtime_array: runtime context for each allocated DAI.
 * @status_update_lock: protect concurrency between interrupt-based and delayed work
 * status update
 */
struct sdw_cdns {
	struct device *dev;
@@ -148,10 +150,13 @@ struct sdw_cdns {
	bool interrupt_enabled;

	struct work_struct work;
	struct delayed_work attach_dwork;

	struct list_head list;

	struct sdw_cdns_dai_runtime **dai_runtime_array;

	struct mutex status_update_lock; /* add mutual exclusion to sdw_handle_slave_status() */
};

#define bus_to_cdns(_bus) container_of(_bus, struct sdw_cdns, bus)
+2 −0
Original line number Diff line number Diff line
@@ -103,6 +103,8 @@ static inline void intel_writew(void __iomem *base, int offset, u16 value)

#define INTEL_MASTER_RESET_ITERATIONS	10

#define SDW_INTEL_DELAYED_ENUMERATION_MS	100

#define SDW_INTEL_CHECK_OPS(sdw, cb)	((sdw) && (sdw)->link_res && (sdw)->link_res->hw_ops && \
					 (sdw)->link_res->hw_ops->cb)
#define SDW_INTEL_OPS(sdw, cb)		((sdw)->link_res->hw_ops->cb)
+1 −0
Original line number Diff line number Diff line
@@ -489,6 +489,7 @@ static void intel_link_remove(struct auxiliary_device *auxdev)
	 */
	if (!bus->prop.hw_disabled) {
		sdw_intel_debugfs_exit(sdw);
		cancel_delayed_work_sync(&cdns->attach_dwork);
		sdw_cdns_enable_interrupt(cdns, false);
	}
	sdw_bus_master_delete(bus);
Loading