Skip to content

Commit 04b6fca

Browse files
groeckWolfram Sang
authored andcommitted
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: Guenter Roeck <[email protected]> Reviewed-by: Jean Delvare <[email protected]> Signed-off-by: Wolfram Sang <[email protected]>
1 parent 0e89b2f commit 04b6fca

File tree

1 file changed

+25
-30
lines changed

1 file changed

+25
-30
lines changed

drivers/i2c/busses/i2c-piix4.c

Lines changed: 25 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
#include <linux/dmi.h>
4141
#include <linux/acpi.h>
4242
#include <linux/io.h>
43-
#include <linux/mutex.h>
4443

4544

4645
/* PIIX4 SMBus address offsets */
@@ -153,10 +152,7 @@ static const struct dmi_system_id piix4_dmi_ibm[] = {
153152

154153
/*
155154
* SB800 globals
156-
* piix4_mutex_sb800 protects piix4_port_sel_sb800 and the pair
157-
* of I/O ports at SB800_PIIX4_SMB_IDX.
158155
*/
159-
static DEFINE_MUTEX(piix4_mutex_sb800);
160156
static u8 piix4_port_sel_sb800;
161157
static u8 piix4_port_mask_sb800;
162158
static u8 piix4_port_shift_sb800;
@@ -298,12 +294,19 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
298294
else
299295
smb_en = (aux) ? 0x28 : 0x2c;
300296

301-
mutex_lock(&piix4_mutex_sb800);
297+
if (!request_muxed_region(SB800_PIIX4_SMB_IDX, 2, "sb800_piix4_smb")) {
298+
dev_err(&PIIX4_dev->dev,
299+
"SMB base address index region 0x%x already in use.\n",
300+
SB800_PIIX4_SMB_IDX);
301+
return -EBUSY;
302+
}
303+
302304
outb_p(smb_en, SB800_PIIX4_SMB_IDX);
303305
smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1);
304306
outb_p(smb_en + 1, SB800_PIIX4_SMB_IDX);
305307
smba_en_hi = inb_p(SB800_PIIX4_SMB_IDX + 1);
306-
mutex_unlock(&piix4_mutex_sb800);
308+
309+
release_region(SB800_PIIX4_SMB_IDX, 2);
307310

308311
if (!smb_en) {
309312
smb_en_status = smba_en_lo & 0x10;
@@ -373,15 +376,20 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
373376
break;
374377
}
375378
} else {
376-
mutex_lock(&piix4_mutex_sb800);
379+
if (!request_muxed_region(SB800_PIIX4_SMB_IDX, 2,
380+
"sb800_piix4_smb")) {
381+
release_region(piix4_smba, SMBIOSIZE);
382+
return -EBUSY;
383+
}
384+
377385
outb_p(SB800_PIIX4_PORT_IDX_SEL, SB800_PIIX4_SMB_IDX);
378386
port_sel = inb_p(SB800_PIIX4_SMB_IDX + 1);
379387
piix4_port_sel_sb800 = (port_sel & 0x01) ?
380388
SB800_PIIX4_PORT_IDX_ALT :
381389
SB800_PIIX4_PORT_IDX;
382390
piix4_port_mask_sb800 = SB800_PIIX4_PORT_IDX_MASK;
383391
piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT;
384-
mutex_unlock(&piix4_mutex_sb800);
392+
release_region(SB800_PIIX4_SMB_IDX, 2);
385393
}
386394

387395
dev_info(&PIIX4_dev->dev,
@@ -679,7 +687,8 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
679687
u8 port;
680688
int retval;
681689

682-
mutex_lock(&piix4_mutex_sb800);
690+
if (!request_muxed_region(SB800_PIIX4_SMB_IDX, 2, "sb800_piix4_smb"))
691+
return -EBUSY;
683692

684693
/* Request the SMBUS semaphore, avoid conflicts with the IMC */
685694
smbslvcnt = inb_p(SMBSLVCNT);
@@ -695,8 +704,8 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
695704
} while (--retries);
696705
/* SMBus is still owned by the IMC, we give up */
697706
if (!retries) {
698-
mutex_unlock(&piix4_mutex_sb800);
699-
return -EBUSY;
707+
retval = -EBUSY;
708+
goto release;
700709
}
701710

702711
/*
@@ -753,8 +762,8 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
753762
if ((size == I2C_SMBUS_BLOCK_DATA) && adapdata->notify_imc)
754763
piix4_imc_wakeup();
755764

756-
mutex_unlock(&piix4_mutex_sb800);
757-
765+
release:
766+
release_region(SB800_PIIX4_SMB_IDX, 2);
758767
return retval;
759768
}
760769

@@ -899,13 +908,6 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
899908
bool notify_imc = false;
900909
is_sb800 = true;
901910

902-
if (!request_region(SB800_PIIX4_SMB_IDX, 2, "smba_idx")) {
903-
dev_err(&dev->dev,
904-
"SMBus base address index region 0x%x already in use!\n",
905-
SB800_PIIX4_SMB_IDX);
906-
return -EBUSY;
907-
}
908-
909911
if (dev->vendor == PCI_VENDOR_ID_AMD &&
910912
dev->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS) {
911913
u8 imc;
@@ -922,20 +924,16 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
922924

923925
/* base address location etc changed in SB800 */
924926
retval = piix4_setup_sb800(dev, id, 0);
925-
if (retval < 0) {
926-
release_region(SB800_PIIX4_SMB_IDX, 2);
927+
if (retval < 0)
927928
return retval;
928-
}
929929

930930
/*
931931
* Try to register multiplexed main SMBus adapter,
932932
* give up if we can't
933933
*/
934934
retval = piix4_add_adapters_sb800(dev, retval, notify_imc);
935-
if (retval < 0) {
936-
release_region(SB800_PIIX4_SMB_IDX, 2);
935+
if (retval < 0)
937936
return retval;
938-
}
939937
} else {
940938
retval = piix4_setup(dev, id);
941939
if (retval < 0)
@@ -983,11 +981,8 @@ static void piix4_adap_remove(struct i2c_adapter *adap)
983981

984982
if (adapdata->smba) {
985983
i2c_del_adapter(adap);
986-
if (adapdata->port == (0 << piix4_port_shift_sb800)) {
984+
if (adapdata->port == (0 << piix4_port_shift_sb800))
987985
release_region(adapdata->smba, SMBIOSIZE);
988-
if (adapdata->sb800_main)
989-
release_region(SB800_PIIX4_SMB_IDX, 2);
990-
}
991986
kfree(adapdata);
992987
kfree(adap);
993988
}

0 commit comments

Comments
 (0)