Commit 21f35d2c authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull i2c fixes from Wolfram Sang:
 "Fix the regression with AMD GPU suspend by reverting the
  handling of bus regulators in the I2C core.

  Also, there is a fix for the MPC driver to prevent an
  out-of-bound-access"

* 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux:
  Revert "i2c: core: support bus regulator controlling in adapter"
  i2c: mpc: Avoid out of bounds memory access
parents d445d649 a19f75de
Loading
Loading
Loading
Loading
+9 −6
Original line number Diff line number Diff line
@@ -492,7 +492,7 @@ static void mpc_i2c_finish(struct mpc_i2c *i2c, int rc)

static void mpc_i2c_do_action(struct mpc_i2c *i2c)
{
	struct i2c_msg *msg = &i2c->msgs[i2c->curr_msg];
	struct i2c_msg *msg = NULL;
	int dir = 0;
	int recv_len = 0;
	u8 byte;
@@ -501,10 +501,13 @@ static void mpc_i2c_do_action(struct mpc_i2c *i2c)

	i2c->cntl_bits &= ~(CCR_RSTA | CCR_MTX | CCR_TXAK);

	if (i2c->action != MPC_I2C_ACTION_STOP) {
		msg = &i2c->msgs[i2c->curr_msg];
		if (msg->flags & I2C_M_RD)
			dir = 1;
		if (msg->flags & I2C_M_RECV_LEN)
			recv_len = 1;
	}

	switch (i2c->action) {
	case MPC_I2C_ACTION_RESTART:
@@ -581,7 +584,7 @@ static void mpc_i2c_do_action(struct mpc_i2c *i2c)
		break;
	}

	if (msg->len == i2c->byte_posn) {
	if (msg && msg->len == i2c->byte_posn) {
		i2c->curr_msg++;
		i2c->byte_posn = 0;

+0 −95
Original line number Diff line number Diff line
@@ -466,14 +466,12 @@ static int i2c_smbus_host_notify_to_irq(const struct i2c_client *client)
static int i2c_device_probe(struct device *dev)
{
	struct i2c_client	*client = i2c_verify_client(dev);
	struct i2c_adapter	*adap;
	struct i2c_driver	*driver;
	int status;

	if (!client)
		return 0;

	adap = client->adapter;
	client->irq = client->init_irq;

	if (!client->irq) {
@@ -539,14 +537,6 @@ static int i2c_device_probe(struct device *dev)

	dev_dbg(dev, "probe\n");

	if (adap->bus_regulator) {
		status = regulator_enable(adap->bus_regulator);
		if (status < 0) {
			dev_err(&adap->dev, "Failed to enable bus regulator\n");
			goto err_clear_wakeup_irq;
		}
	}

	status = of_clk_set_defaults(dev->of_node, false);
	if (status < 0)
		goto err_clear_wakeup_irq;
@@ -605,10 +595,8 @@ static int i2c_device_probe(struct device *dev)
static void i2c_device_remove(struct device *dev)
{
	struct i2c_client	*client = to_i2c_client(dev);
	struct i2c_adapter      *adap;
	struct i2c_driver	*driver;

	adap = client->adapter;
	driver = to_i2c_driver(dev->driver);
	if (driver->remove) {
		int status;
@@ -623,8 +611,6 @@ static void i2c_device_remove(struct device *dev)
	devres_release_group(&client->dev, client->devres_group_id);

	dev_pm_domain_detach(&client->dev, !i2c_acpi_waive_d0_probe(dev));
	if (!pm_runtime_status_suspended(&client->dev) && adap->bus_regulator)
		regulator_disable(adap->bus_regulator);

	dev_pm_clear_wake_irq(&client->dev);
	device_init_wakeup(&client->dev, false);
@@ -634,86 +620,6 @@ static void i2c_device_remove(struct device *dev)
		pm_runtime_put(&client->adapter->dev);
}

#ifdef CONFIG_PM_SLEEP
static int i2c_resume_early(struct device *dev)
{
	struct i2c_client *client = i2c_verify_client(dev);
	int err;

	if (!client)
		return 0;

	if (pm_runtime_status_suspended(&client->dev) &&
		client->adapter->bus_regulator) {
		err = regulator_enable(client->adapter->bus_regulator);
		if (err)
			return err;
	}

	return pm_generic_resume_early(&client->dev);
}

static int i2c_suspend_late(struct device *dev)
{
	struct i2c_client *client = i2c_verify_client(dev);
	int err;

	if (!client)
		return 0;

	err = pm_generic_suspend_late(&client->dev);
	if (err)
		return err;

	if (!pm_runtime_status_suspended(&client->dev) &&
		client->adapter->bus_regulator)
		return regulator_disable(client->adapter->bus_regulator);

	return 0;
}
#endif

#ifdef CONFIG_PM
static int i2c_runtime_resume(struct device *dev)
{
	struct i2c_client *client = i2c_verify_client(dev);
	int err;

	if (!client)
		return 0;

	if (client->adapter->bus_regulator) {
		err = regulator_enable(client->adapter->bus_regulator);
		if (err)
			return err;
	}

	return pm_generic_runtime_resume(&client->dev);
}

static int i2c_runtime_suspend(struct device *dev)
{
	struct i2c_client *client = i2c_verify_client(dev);
	int err;

	if (!client)
		return 0;

	err = pm_generic_runtime_suspend(&client->dev);
	if (err)
		return err;

	if (client->adapter->bus_regulator)
		return regulator_disable(client->adapter->bus_regulator);
	return 0;
}
#endif

static const struct dev_pm_ops i2c_device_pm = {
	SET_LATE_SYSTEM_SLEEP_PM_OPS(i2c_suspend_late, i2c_resume_early)
	SET_RUNTIME_PM_OPS(i2c_runtime_suspend, i2c_runtime_resume, NULL)
};

static void i2c_device_shutdown(struct device *dev)
{
	struct i2c_client *client = i2c_verify_client(dev);
@@ -773,7 +679,6 @@ struct bus_type i2c_bus_type = {
	.probe		= i2c_device_probe,
	.remove		= i2c_device_remove,
	.shutdown	= i2c_device_shutdown,
	.pm		= &i2c_device_pm,
};
EXPORT_SYMBOL_GPL(i2c_bus_type);