Hello Jean,

On 05/09/2019 14:57, Jean Delvare wrote:
> If this is of any value to you, I tried implementing it in i2c-i801 a
> few days ago. I can't really test it though as I don't have any device
> which triggers an alert on my system, but I am sharing it with you if
> you want to give it a try. You would still need to write the code in
> the slave driver.
> 
> ---
>  drivers/i2c/busses/i2c-i801.c |   77 
> +++++++++++++++++++++++++++++++++++++-----
>  1 file changed, 69 insertions(+), 8 deletions(-)
> 
> --- linux-5.2.orig/drivers/i2c/busses/i2c-i801.c      2019-08-28 
> 15:58:52.725828215 +0200
> +++ linux-5.2/drivers/i2c/busses/i2c-i801.c   2019-08-28 16:50:09.212696037 
> +0200
> @@ -196,6 +196,7 @@
>  
>  /* Host Notify Command register bits */
>  #define SMBSLVCMD_HST_NTFY_INTREN    BIT(0)
> +#define SMBSLVCMD_SMBALERT_DIS               BIT(2)
>  
>  #define STATUS_ERROR_FLAGS   (SMBHSTSTS_FAILED | SMBHSTSTS_BUS_ERR | \
>                                SMBHSTSTS_DEV_ERR)
> @@ -281,6 +282,10 @@ struct i801_priv {
>        */
>       bool acpi_reserved;
>       struct mutex acpi_lock;
> +
> +     /* SMBus alert */
> +     struct i2c_smbus_alert_setup alert_data;
> +     struct i2c_client *ara;
>  };
>  
>  #define FEATURE_SMBUS_PEC    BIT(0)
> @@ -289,6 +294,7 @@ struct i801_priv {
>  #define FEATURE_I2C_BLOCK_READ       BIT(3)
>  #define FEATURE_IRQ          BIT(4)
>  #define FEATURE_HOST_NOTIFY  BIT(5)
> +#define FEATURE_SMBUS_ALERT  BIT(6)
>  /* Not really a feature, but it's convenient to handle it as such */
>  #define FEATURE_IDF          BIT(15)
>  #define FEATURE_TCO_SPT              BIT(16)
> @@ -301,6 +307,7 @@ static const char *i801_feature_names[]
>       "I2C block read",
>       "Interrupt",
>       "SMBus Host Notify",
> +     "SMBus Alert",
>  };
>  
>  static unsigned int disable_features;
> @@ -310,7 +317,8 @@ MODULE_PARM_DESC(disable_features, "Disa
>       "\t\t  0x02  disable the block buffer\n"
>       "\t\t  0x08  disable the I2C block read functionality\n"
>       "\t\t  0x10  don't use interrupts\n"
> -     "\t\t  0x20  disable SMBus Host Notify ");
> +     "\t\t  0x20  disable SMBus Host Notify\n"
> +     "\t\t  0x40  disable SMBus Alert ");
>  
>  /* Make sure the SMBus host is ready to start transmitting.
>     Return 0 if it is, -EBUSY if it is not. */
> @@ -620,8 +628,24 @@ static irqreturn_t i801_host_notify_isr(
>       return IRQ_HANDLED;
>  }
>  
> +static irqreturn_t i801_smbus_alert_isr(struct i801_priv *priv)
> +{
> +     struct i2c_client *ara = priv->ara;
> +
> +     if (ara) {
> +             dev_dbg(&ara->dev, "SMBus alert received\n");
> +             i2c_handle_smbus_alert(ara);

I've just tested this approach and must conclude that it doesn't work.
Seems that SMBALERT# in i801 is level-triggered (I wasn't able to
confirm or decline this statement using i801 documentation) and
once SMBALERT# is triggered, I experience the interrupt flood.
Clearing the interrupt request bit below has no effect at this point.

Unfortunately, current smbalert API doesn't provide any synchronous
interface to test another approach.

> +     } else
> +             dev_dbg(&priv->adapter.dev,
> +                     "SMBus alert received but no ARA client!\n");
> +
> +     /* clear SMBus Alert bit and return */
> +     outb_p(SMBHSTSTS_SMBALERT_STS, SMBHSTSTS(priv));
> +     return IRQ_HANDLED;
> +}
> +
>  /*
> - * There are three kinds of interrupts:
> + * There are four kinds of interrupts:
>   *
>   * 1) i801 signals transaction completion with one of these interrupts:
>   *      INTR - Success

Therefore, I'd like to ask you (and other I2C maintainers), not that
I spend a time for a solution which has no upstream perspectives, what
shall be the preferred way for i801 driver:

a) We disable SMBALERT# completely

or

b) I export smbus_alert(), so that we can
        - catch the IRQ
        - disable SMBALERT#
        - synchronously smbus_alert()
        - re-enable SMBALERT#

?

-- 
Best regards,
Alexander Sverdlin.

Reply via email to