lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <ZuALQVyTBFugG0Sw@smile.fi.intel.com>
Date: Tue, 10 Sep 2024 12:02:57 +0300
From: Andy Shevchenko <andriy.shevchenko@...ux.intel.com>
To: Kimriver Liu <kimriver.liu@...ngine.com>
Cc: jarkko.nikula@...ux.intel.com, mika.westerberg@...ux.intel.com,
	jsd@...ihalf.com, andi.shyti@...nel.org, linux-i2c@...r.kernel.org,
	linux-kernel@...r.kernel.org
Subject: Re: [PATCH v8] i2c: designware: fix master is holding SCL low while
 ENABLE bit is disabled

On Tue, Sep 10, 2024 at 02:13:09PM +0800, Kimriver Liu wrote:
> It was observed issuing ABORT bit(IC_ENABLE[1]) will not work when

"...observed that issuing..."
...bit (..."


> IC_ENABLE is already disabled.
> 
> Check if ENABLE bit(IC_ENABLE[0]) is disabled when the master is

"...bit (..."
master --> controller

> holding SCL low. If ENABLE bit is disabled, the software need
> enable it before trying to issue ABORT bit. otherwise,
> the controller ignores any write to ABORT bit.

Fixes tag?

...

>  	abort_needed = raw_intr_stats & DW_IC_INTR_MST_ON_HOLD;
>  	if (abort_needed) {
> +		if (!(enable & DW_IC_ENABLE_ENABLE)) {

> +			regmap_write(dev->map, DW_IC_ENABLE, DW_IC_ENABLE_ENABLE);

This call might also need a one line comment.

> +			enable |= DW_IC_ENABLE_ENABLE;

More natural is to put this after the fsleep() call. The rationale is that it
will be easier to see what exactly is going to be written back to the
register.

> +			/*
> +			 * Wait 10 times the signaling period of the highest I2C
> +			 * transfer supported by the driver (for 400KHz this is
> +			 * 25us) to ensure the I2C ENABLE bit is already set
> +			 * as described in the DesignWare I2C databook.
> +			 */
> +			fsleep(DIV_ROUND_CLOSEST_ULL(10 * MICRO, t->bus_freq_hz));

...somewhere here...

> +		}
> +
>  		regmap_write(dev->map, DW_IC_ENABLE, enable | DW_IC_ENABLE_ABORT);

...

> +static bool i2c_dw_is_master_idling(struct dw_i2c_dev *dev)

Sorry if I made a mistake, but again, looking at the usage you have again
negation here and there...

	i2c_dw_is_controller_active

(note new terminology, dunno if it makes sense start using it in function
 names, as we have more of them following old style)

> +{
> +	u32 status;
> +
> +	regmap_read(dev->map, DW_IC_STATUS, &status);
> +	if (!(status & DW_IC_STATUS_MASTER_ACTIVITY))
> +		return true;

		return false;

.,,

> +	return !regmap_read_poll_timeout(dev->map, DW_IC_STATUS, status,
> +			!(status & DW_IC_STATUS_MASTER_ACTIVITY),
> +			1100, 20000);

...and drop !.

> +}

...

> +	/*
> +	 * This happens rarely and is hard to reproduce. Debug trace

Rarely how? Perhaps put a ration in the parentheses, like

"...rarely (~1:100)..."

> +	 * showed that IC_STATUS had value of 0x23 when STOP_DET occurred,
> +	 * if disable IC_ENABLE.ENABLE immediately that can result in
> +	 * IC_RAW_INTR_STAT.MASTER_ON_HOLD holding SCL low.
> +	 */
> +	if (!i2c_dw_is_master_idling(dev))

...and here

	if (i2c_dw_is_controller_active(dev))

But please double check that I haven't made any mistakes in all this logic.

> +		dev_err(dev->dev, "I2C master not idling\n");

-- 
With Best Regards,
Andy Shevchenko



Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ