Commit 04b6fcab authored by Guenter Roeck's avatar Guenter Roeck Committed by Wolfram Sang

i2c: piix4: Use request_muxed_region

Accesses to SB800_PIIX4_SMB_IDX can occur from multiple drivers.
One example for another driver is the sp5100_tco driver.

Use request_muxed_region() to ensure synchronization.
Signed-off-by: default avatarGuenter Roeck <linux@roeck-us.net>
Reviewed-by: default avatarJean Delvare <jdelvare@suse.de>
Signed-off-by: default avatarWolfram Sang <wsa@the-dreams.de>
parent 0e89b2fe
...@@ -40,7 +40,6 @@ ...@@ -40,7 +40,6 @@
#include <linux/dmi.h> #include <linux/dmi.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/mutex.h>
/* PIIX4 SMBus address offsets */ /* PIIX4 SMBus address offsets */
...@@ -153,10 +152,7 @@ static const struct dmi_system_id piix4_dmi_ibm[] = { ...@@ -153,10 +152,7 @@ static const struct dmi_system_id piix4_dmi_ibm[] = {
/* /*
* SB800 globals * SB800 globals
* piix4_mutex_sb800 protects piix4_port_sel_sb800 and the pair
* of I/O ports at SB800_PIIX4_SMB_IDX.
*/ */
static DEFINE_MUTEX(piix4_mutex_sb800);
static u8 piix4_port_sel_sb800; static u8 piix4_port_sel_sb800;
static u8 piix4_port_mask_sb800; static u8 piix4_port_mask_sb800;
static u8 piix4_port_shift_sb800; static u8 piix4_port_shift_sb800;
...@@ -298,12 +294,19 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev, ...@@ -298,12 +294,19 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
else else
smb_en = (aux) ? 0x28 : 0x2c; smb_en = (aux) ? 0x28 : 0x2c;
mutex_lock(&piix4_mutex_sb800); if (!request_muxed_region(SB800_PIIX4_SMB_IDX, 2, "sb800_piix4_smb")) {
dev_err(&PIIX4_dev->dev,
"SMB base address index region 0x%x already in use.\n",
SB800_PIIX4_SMB_IDX);
return -EBUSY;
}
outb_p(smb_en, SB800_PIIX4_SMB_IDX); outb_p(smb_en, SB800_PIIX4_SMB_IDX);
smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1); smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1);
outb_p(smb_en + 1, SB800_PIIX4_SMB_IDX); outb_p(smb_en + 1, SB800_PIIX4_SMB_IDX);
smba_en_hi = inb_p(SB800_PIIX4_SMB_IDX + 1); smba_en_hi = inb_p(SB800_PIIX4_SMB_IDX + 1);
mutex_unlock(&piix4_mutex_sb800);
release_region(SB800_PIIX4_SMB_IDX, 2);
if (!smb_en) { if (!smb_en) {
smb_en_status = smba_en_lo & 0x10; smb_en_status = smba_en_lo & 0x10;
...@@ -373,7 +376,12 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev, ...@@ -373,7 +376,12 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
break; break;
} }
} else { } else {
mutex_lock(&piix4_mutex_sb800); if (!request_muxed_region(SB800_PIIX4_SMB_IDX, 2,
"sb800_piix4_smb")) {
release_region(piix4_smba, SMBIOSIZE);
return -EBUSY;
}
outb_p(SB800_PIIX4_PORT_IDX_SEL, SB800_PIIX4_SMB_IDX); outb_p(SB800_PIIX4_PORT_IDX_SEL, SB800_PIIX4_SMB_IDX);
port_sel = inb_p(SB800_PIIX4_SMB_IDX + 1); port_sel = inb_p(SB800_PIIX4_SMB_IDX + 1);
piix4_port_sel_sb800 = (port_sel & 0x01) ? piix4_port_sel_sb800 = (port_sel & 0x01) ?
...@@ -381,7 +389,7 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev, ...@@ -381,7 +389,7 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
SB800_PIIX4_PORT_IDX; SB800_PIIX4_PORT_IDX;
piix4_port_mask_sb800 = SB800_PIIX4_PORT_IDX_MASK; piix4_port_mask_sb800 = SB800_PIIX4_PORT_IDX_MASK;
piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT; piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT;
mutex_unlock(&piix4_mutex_sb800); release_region(SB800_PIIX4_SMB_IDX, 2);
} }
dev_info(&PIIX4_dev->dev, dev_info(&PIIX4_dev->dev,
...@@ -679,7 +687,8 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr, ...@@ -679,7 +687,8 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
u8 port; u8 port;
int retval; int retval;
mutex_lock(&piix4_mutex_sb800); if (!request_muxed_region(SB800_PIIX4_SMB_IDX, 2, "sb800_piix4_smb"))
return -EBUSY;
/* Request the SMBUS semaphore, avoid conflicts with the IMC */ /* Request the SMBUS semaphore, avoid conflicts with the IMC */
smbslvcnt = inb_p(SMBSLVCNT); smbslvcnt = inb_p(SMBSLVCNT);
...@@ -695,8 +704,8 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr, ...@@ -695,8 +704,8 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
} while (--retries); } while (--retries);
/* SMBus is still owned by the IMC, we give up */ /* SMBus is still owned by the IMC, we give up */
if (!retries) { if (!retries) {
mutex_unlock(&piix4_mutex_sb800); retval = -EBUSY;
return -EBUSY; goto release;
} }
/* /*
...@@ -753,8 +762,8 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr, ...@@ -753,8 +762,8 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
if ((size == I2C_SMBUS_BLOCK_DATA) && adapdata->notify_imc) if ((size == I2C_SMBUS_BLOCK_DATA) && adapdata->notify_imc)
piix4_imc_wakeup(); piix4_imc_wakeup();
mutex_unlock(&piix4_mutex_sb800); release:
release_region(SB800_PIIX4_SMB_IDX, 2);
return retval; return retval;
} }
...@@ -899,13 +908,6 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) ...@@ -899,13 +908,6 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
bool notify_imc = false; bool notify_imc = false;
is_sb800 = true; is_sb800 = true;
if (!request_region(SB800_PIIX4_SMB_IDX, 2, "smba_idx")) {
dev_err(&dev->dev,
"SMBus base address index region 0x%x already in use!\n",
SB800_PIIX4_SMB_IDX);
return -EBUSY;
}
if (dev->vendor == PCI_VENDOR_ID_AMD && if (dev->vendor == PCI_VENDOR_ID_AMD &&
dev->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS) { dev->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS) {
u8 imc; u8 imc;
...@@ -922,20 +924,16 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) ...@@ -922,20 +924,16 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
/* base address location etc changed in SB800 */ /* base address location etc changed in SB800 */
retval = piix4_setup_sb800(dev, id, 0); retval = piix4_setup_sb800(dev, id, 0);
if (retval < 0) { if (retval < 0)
release_region(SB800_PIIX4_SMB_IDX, 2);
return retval; return retval;
}
/* /*
* Try to register multiplexed main SMBus adapter, * Try to register multiplexed main SMBus adapter,
* give up if we can't * give up if we can't
*/ */
retval = piix4_add_adapters_sb800(dev, retval, notify_imc); retval = piix4_add_adapters_sb800(dev, retval, notify_imc);
if (retval < 0) { if (retval < 0)
release_region(SB800_PIIX4_SMB_IDX, 2);
return retval; return retval;
}
} else { } else {
retval = piix4_setup(dev, id); retval = piix4_setup(dev, id);
if (retval < 0) if (retval < 0)
...@@ -983,11 +981,8 @@ static void piix4_adap_remove(struct i2c_adapter *adap) ...@@ -983,11 +981,8 @@ static void piix4_adap_remove(struct i2c_adapter *adap)
if (adapdata->smba) { if (adapdata->smba) {
i2c_del_adapter(adap); i2c_del_adapter(adap);
if (adapdata->port == (0 << piix4_port_shift_sb800)) { if (adapdata->port == (0 << piix4_port_shift_sb800))
release_region(adapdata->smba, SMBIOSIZE); release_region(adapdata->smba, SMBIOSIZE);
if (adapdata->sb800_main)
release_region(SB800_PIIX4_SMB_IDX, 2);
}
kfree(adapdata); kfree(adapdata);
kfree(adap); kfree(adap);
} }
......
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