linux-i2c.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3] i2c: piix4: Avoid race conditions with IMC
@ 2017-01-12 19:49 Ricardo Ribalda Delgado
  2017-01-31 13:55 ` Jean Delvare
  0 siblings, 1 reply; 2+ messages in thread
From: Ricardo Ribalda Delgado @ 2017-01-12 19:49 UTC (permalink / raw)
  To: Wolfram Sang, Andy Shevchenko, Ricardo Ribalda Delgado,
	Jean Delvare, linux-i2c, linux-kernel

From: Ricardo Ribalda <ricardo.ribalda@gmail.com>

On AMD's SB800 and upwards, the SMBus is shared with the Integrated
Micro Controller (IMC).

The platform provides a hardware semaphore to avoid race conditions
among them. (Check page 288 of the SB800-Series Southbridges Register
Reference Guide http://support.amd.com/TechDocs/45482.pdf)

Without this patch, many access to the SMBus end with an invalid
transaction or even with the bus stalled.

Reported-by: Alexandre Desnoyers <alex@qtec.com>
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
---
v3: Suggestions by Andy Shevchenko <andy.shevchenko@gmail.com> and
Wolfram Sang <wsa@the-dreams.de>:
 -Use Reported-by instead of Credit-to

v2: Suggestions by Andy Shevchenko <andy.shevchenko@gmail.com>:
 -Rename timeout to retries
 -Use do {} while(--retries) pattern
 -Group new variables

 drivers/i2c/busses/i2c-piix4.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index c2268cdf38e8..e34d82e79b98 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -585,10 +585,29 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
 		 u8 command, int size, union i2c_smbus_data *data)
 {
 	struct i2c_piix4_adapdata *adapdata = i2c_get_adapdata(adap);
+	unsigned short piix4_smba = adapdata->smba;
+	int retries = MAX_TIMEOUT;
+	int smbslvcnt;
 	u8 smba_en_lo;
 	u8 port;
 	int retval;
 
+	/* Request the SMBUS semaphore, avoid conflicts with the IMC */
+	smbslvcnt  = inb_p(SMBSLVCNT);
+	do {
+		outb_p(smbslvcnt | 0x10, SMBSLVCNT);
+
+		/* Check the semaphore status */
+		smbslvcnt  = inb_p(SMBSLVCNT);
+		if (smbslvcnt & 0x10)
+			break;
+
+		usleep_range(1000, 2000);
+	} while (--retries);
+	/* SMBus is still owned by the IMC, we give up */
+	if (!retries)
+		return -EBUSY;
+
 	mutex_lock(&piix4_mutex_sb800);
 
 	outb_p(piix4_port_sel_sb800, SB800_PIIX4_SMB_IDX);
@@ -606,6 +625,9 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
 
 	mutex_unlock(&piix4_mutex_sb800);
 
+	/* Release the semaphore */
+	outb_p(smbslvcnt | 0x20, SMBSLVCNT);
+
 	return retval;
 }
 
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH v3] i2c: piix4: Avoid race conditions with IMC
  2017-01-12 19:49 [PATCH v3] i2c: piix4: Avoid race conditions with IMC Ricardo Ribalda Delgado
@ 2017-01-31 13:55 ` Jean Delvare
  0 siblings, 0 replies; 2+ messages in thread
From: Jean Delvare @ 2017-01-31 13:55 UTC (permalink / raw)
  To: Ricardo Ribalda Delgado
  Cc: Wolfram Sang, Andy Shevchenko, linux-i2c, linux-kernel

Hi all,

On Thu, 12 Jan 2017 20:49:46 +0100, Ricardo Ribalda Delgado wrote:
> From: Ricardo Ribalda <ricardo.ribalda@gmail.com>
> 
> On AMD's SB800 and upwards, the SMBus is shared with the Integrated
> Micro Controller (IMC).
> 
> The platform provides a hardware semaphore to avoid race conditions
> among them. (Check page 288 of the SB800-Series Southbridges Register
> Reference Guide http://support.amd.com/TechDocs/45482.pdf)
> 
> Without this patch, many access to the SMBus end with an invalid
> transaction or even with the bus stalled.
> 
> Reported-by: Alexandre Desnoyers <alex@qtec.com>
> Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
> Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
> ---
> v3: Suggestions by Andy Shevchenko <andy.shevchenko@gmail.com> and
> Wolfram Sang <wsa@the-dreams.de>:
>  -Use Reported-by instead of Credit-to
> 
> v2: Suggestions by Andy Shevchenko <andy.shevchenko@gmail.com>:
>  -Rename timeout to retries
>  -Use do {} while(--retries) pattern
>  -Group new variables
> 
>  drivers/i2c/busses/i2c-piix4.c | 22 ++++++++++++++++++++++
>  1 file changed, 22 insertions(+)
> 
> diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
> index c2268cdf38e8..e34d82e79b98 100644
> --- a/drivers/i2c/busses/i2c-piix4.c
> +++ b/drivers/i2c/busses/i2c-piix4.c
> @@ -585,10 +585,29 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
>  		 u8 command, int size, union i2c_smbus_data *data)
>  {
>  	struct i2c_piix4_adapdata *adapdata = i2c_get_adapdata(adap);
> +	unsigned short piix4_smba = adapdata->smba;
> +	int retries = MAX_TIMEOUT;
> +	int smbslvcnt;
>  	u8 smba_en_lo;
>  	u8 port;
>  	int retval;
>  
> +	/* Request the SMBUS semaphore, avoid conflicts with the IMC */
> +	smbslvcnt  = inb_p(SMBSLVCNT);
> +	do {
> +		outb_p(smbslvcnt | 0x10, SMBSLVCNT);
> +
> +		/* Check the semaphore status */
> +		smbslvcnt  = inb_p(SMBSLVCNT);
> +		if (smbslvcnt & 0x10)
> +			break;
> +
> +		usleep_range(1000, 2000);
> +	} while (--retries);
> +	/* SMBus is still owned by the IMC, we give up */
> +	if (!retries)
> +		return -EBUSY;
> +
>  	mutex_lock(&piix4_mutex_sb800);

Sorry for being late to the party but... Shouldn't the IMC semaphore
check be done with piix4_mutex_sb800 held? If we do it before taking
piix4_mutex_sb800, as done above, several SMBus users could try to
write to and read from SMBSLVCNT at the same time. That doesn't look
safe to me. I can imagine that one (starting) SMBus transaction would
try to gain the IMC semaphore above...

>  
>  	outb_p(piix4_port_sel_sb800, SB800_PIIX4_SMB_IDX);
> @@ -606,6 +625,9 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
>  
>  	mutex_unlock(&piix4_mutex_sb800);
>  
> +	/* Release the semaphore */
> +	outb_p(smbslvcnt | 0x20, SMBSLVCNT);
> +

... while another (finishing) SMBus transaction is releasing it. At
which point we may end up using the SMBus while we do not own the IMC
semaphore.

And things could get even worse if SMBSLVCNT is ever used somewhere
else in the driver.

>  	return retval;
>  }
>  


-- 
Jean Delvare
SUSE L3 Support

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2017-01-31 13:56 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-01-12 19:49 [PATCH v3] i2c: piix4: Avoid race conditions with IMC Ricardo Ribalda Delgado
2017-01-31 13:55 ` Jean Delvare

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).