Commit 9b5bf587 authored by Jean Delvare's avatar Jean Delvare Committed by Wolfram Sang

i2c: i801: Restore INTREN on unload

If driver interrupts are enabled, SMBHSTCNT_INTREN will be 1 after
the first transaction, and will stay to that value forever. This
means that interrupts will be generated for both host-initiated
transactions and also SMBus Alert events even after the driver is
unloaded. To be on the safe side, we should restore the initial state
of this bit at suspend and reboot time, as we do for several other
configuration bits already and for the same reason: the BIOS should
be handed the device in the same configuration state in which we
received it. Otherwise interrupts may be generated which nobody
will process.
Signed-off-by: default avatarJean Delvare <jdelvare@suse.de>
Tested-by: default avatarJarkko Nikula <jarkko.nikula@linux.intel.com>
Signed-off-by: default avatarWolfram Sang <wsa@kernel.org>
parent aa6fed90
...@@ -259,6 +259,7 @@ struct i801_priv { ...@@ -259,6 +259,7 @@ struct i801_priv {
struct i2c_adapter adapter; struct i2c_adapter adapter;
unsigned long smba; unsigned long smba;
unsigned char original_hstcfg; unsigned char original_hstcfg;
unsigned char original_hstcnt;
unsigned char original_slvcmd; unsigned char original_slvcmd;
struct pci_dev *pci_dev; struct pci_dev *pci_dev;
unsigned int features; unsigned int features;
...@@ -1805,7 +1806,8 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) ...@@ -1805,7 +1806,8 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
outb_p(inb_p(SMBAUXCTL(priv)) & outb_p(inb_p(SMBAUXCTL(priv)) &
~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv)); ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv));
/* Remember original Host Notify setting */ /* Remember original Interrupt and Host Notify settings */
priv->original_hstcnt = inb_p(SMBHSTCNT(priv)) & ~SMBHSTCNT_KILL;
if (priv->features & FEATURE_HOST_NOTIFY) if (priv->features & FEATURE_HOST_NOTIFY)
priv->original_slvcmd = inb_p(SMBSLVCMD(priv)); priv->original_slvcmd = inb_p(SMBSLVCMD(priv));
...@@ -1869,6 +1871,7 @@ static void i801_remove(struct pci_dev *dev) ...@@ -1869,6 +1871,7 @@ static void i801_remove(struct pci_dev *dev)
{ {
struct i801_priv *priv = pci_get_drvdata(dev); struct i801_priv *priv = pci_get_drvdata(dev);
outb_p(priv->original_hstcnt, SMBHSTCNT(priv));
i801_disable_host_notify(priv); i801_disable_host_notify(priv);
i801_del_mux(priv); i801_del_mux(priv);
i2c_del_adapter(&priv->adapter); i2c_del_adapter(&priv->adapter);
...@@ -1892,6 +1895,7 @@ static void i801_shutdown(struct pci_dev *dev) ...@@ -1892,6 +1895,7 @@ static void i801_shutdown(struct pci_dev *dev)
struct i801_priv *priv = pci_get_drvdata(dev); struct i801_priv *priv = pci_get_drvdata(dev);
/* Restore config registers to avoid hard hang on some systems */ /* Restore config registers to avoid hard hang on some systems */
outb_p(priv->original_hstcnt, SMBHSTCNT(priv));
i801_disable_host_notify(priv); i801_disable_host_notify(priv);
pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg); pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg);
} }
...@@ -1901,6 +1905,7 @@ static int i801_suspend(struct device *dev) ...@@ -1901,6 +1905,7 @@ static int i801_suspend(struct device *dev)
{ {
struct i801_priv *priv = dev_get_drvdata(dev); struct i801_priv *priv = dev_get_drvdata(dev);
outb_p(priv->original_hstcnt, SMBHSTCNT(priv));
pci_write_config_byte(priv->pci_dev, SMBHSTCFG, priv->original_hstcfg); pci_write_config_byte(priv->pci_dev, SMBHSTCFG, priv->original_hstcfg);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment