diff options
author | Linus Torvalds | 2016-01-31 14:29:52 -0800 |
---|---|---|
committer | Linus Torvalds | 2016-01-31 14:29:52 -0800 |
commit | bb4768004b0a68a01fc1bc68f8f5f0f75ea584bb (patch) | |
tree | f0d52e4b47a589d77c91f1fa31bdd9f2d23dc055 /drivers | |
parent | ad0b40fa944628d6f30b40266a599b285d70a266 (diff) | |
parent | 52795f6fdeb8a2b98373108ac2838c674bb2cbc4 (diff) |
Merge branch 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c fixes from Wolfram Sang:
"Here are two I2C driver regression fixes. piix4 gets a larger
overhaul fixing the latest refactoring and also an older known issue
as well. designware-pci gets a fix for a bad merge conflict
resolution"
* 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux:
i2c: piix4: don't regress on bus names
i2c: designware-pci: use IRQF_COND_SUSPEND flag
i2c: piix4: Fully initialize SB800 before it is registered
i2c: piix4: Fix SB800 locking
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/i2c/busses/i2c-designware-core.c | 3 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-piix4.c | 50 |
2 files changed, 23 insertions, 30 deletions
diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c index ba9732c236c5..10fbd6d841e0 100644 --- a/drivers/i2c/busses/i2c-designware-core.c +++ b/drivers/i2c/busses/i2c-designware-core.c @@ -874,7 +874,8 @@ int i2c_dw_probe(struct dw_i2c_dev *dev) i2c_set_adapdata(adap, dev); i2c_dw_disable_int(dev); - r = devm_request_irq(dev->dev, dev->irq, i2c_dw_isr, IRQF_SHARED, + r = devm_request_irq(dev->dev, dev->irq, i2c_dw_isr, + IRQF_SHARED | IRQF_COND_SUSPEND, dev_name(dev->dev), dev); if (r) { dev_err(dev->dev, "failure requesting irq %i: %d\n", diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index e04598595073..93f2895383ee 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -137,10 +137,11 @@ static const struct dmi_system_id piix4_dmi_ibm[] = { }; /* SB800 globals */ +static DEFINE_MUTEX(piix4_mutex_sb800); static const char *piix4_main_port_names_sb800[PIIX4_MAX_ADAPTERS] = { - "SDA0", "SDA2", "SDA3", "SDA4" + " port 0", " port 2", " port 3", " port 4" }; -static const char *piix4_aux_port_name_sb800 = "SDA1"; +static const char *piix4_aux_port_name_sb800 = " port 1"; struct i2c_piix4_adapdata { unsigned short smba; @@ -148,7 +149,6 @@ struct i2c_piix4_adapdata { /* SB800 */ bool sb800_main; unsigned short port; - struct mutex *mutex; }; static int piix4_setup(struct pci_dev *PIIX4_dev, @@ -275,10 +275,12 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev, else smb_en = (aux) ? 0x28 : 0x2c; + mutex_lock(&piix4_mutex_sb800); outb_p(smb_en, SB800_PIIX4_SMB_IDX); smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1); outb_p(smb_en + 1, SB800_PIIX4_SMB_IDX); smba_en_hi = inb_p(SB800_PIIX4_SMB_IDX + 1); + mutex_unlock(&piix4_mutex_sb800); if (!smb_en) { smb_en_status = smba_en_lo & 0x10; @@ -559,7 +561,7 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr, u8 port; int retval; - mutex_lock(adapdata->mutex); + mutex_lock(&piix4_mutex_sb800); outb_p(SB800_PIIX4_PORT_IDX, SB800_PIIX4_SMB_IDX); smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1); @@ -574,7 +576,7 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr, outb_p(smba_en_lo, SB800_PIIX4_SMB_IDX + 1); - mutex_unlock(adapdata->mutex); + mutex_unlock(&piix4_mutex_sb800); return retval; } @@ -625,6 +627,7 @@ static struct i2c_adapter *piix4_main_adapters[PIIX4_MAX_ADAPTERS]; static struct i2c_adapter *piix4_aux_adapter; static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba, + bool sb800_main, unsigned short port, const char *name, struct i2c_adapter **padap) { struct i2c_adapter *adap; @@ -639,7 +642,8 @@ static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba, adap->owner = THIS_MODULE; adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; - adap->algo = &smbus_algorithm; + adap->algo = sb800_main ? &piix4_smbus_algorithm_sb800 + : &smbus_algorithm; adapdata = kzalloc(sizeof(*adapdata), GFP_KERNEL); if (adapdata == NULL) { @@ -649,12 +653,14 @@ static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba, } adapdata->smba = smba; + adapdata->sb800_main = sb800_main; + adapdata->port = port; /* set up the sysfs linkage to our parent device */ adap->dev.parent = &dev->dev; snprintf(adap->name, sizeof(adap->name), - "SMBus PIIX4 adapter %s at %04x", name, smba); + "SMBus PIIX4 adapter%s at %04x", name, smba); i2c_set_adapdata(adap, adapdata); @@ -673,30 +679,16 @@ static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba, static int piix4_add_adapters_sb800(struct pci_dev *dev, unsigned short smba) { - struct mutex *mutex; struct i2c_piix4_adapdata *adapdata; int port; int retval; - mutex = kzalloc(sizeof(*mutex), GFP_KERNEL); - if (mutex == NULL) - return -ENOMEM; - - mutex_init(mutex); - for (port = 0; port < PIIX4_MAX_ADAPTERS; port++) { - retval = piix4_add_adapter(dev, smba, + retval = piix4_add_adapter(dev, smba, true, port, piix4_main_port_names_sb800[port], &piix4_main_adapters[port]); if (retval < 0) goto error; - - piix4_main_adapters[port]->algo = &piix4_smbus_algorithm_sb800; - - adapdata = i2c_get_adapdata(piix4_main_adapters[port]); - adapdata->sb800_main = true; - adapdata->port = port; - adapdata->mutex = mutex; } return retval; @@ -714,19 +706,20 @@ error: } } - kfree(mutex); - return retval; } static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) { int retval; + bool is_sb800 = false; if ((dev->vendor == PCI_VENDOR_ID_ATI && dev->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS && dev->revision >= 0x40) || dev->vendor == PCI_VENDOR_ID_AMD) { + 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", @@ -756,7 +749,7 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) return retval; /* Try to register main SMBus adapter, give up if we can't */ - retval = piix4_add_adapter(dev, retval, "main", + retval = piix4_add_adapter(dev, retval, false, 0, "", &piix4_main_adapters[0]); if (retval < 0) return retval; @@ -783,7 +776,8 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) if (retval > 0) { /* Try to add the aux adapter if it exists, * piix4_add_adapter will clean up if this fails */ - piix4_add_adapter(dev, retval, piix4_aux_port_name_sb800, + piix4_add_adapter(dev, retval, false, 0, + is_sb800 ? piix4_aux_port_name_sb800 : "", &piix4_aux_adapter); } @@ -798,10 +792,8 @@ static void piix4_adap_remove(struct i2c_adapter *adap) i2c_del_adapter(adap); if (adapdata->port == 0) { release_region(adapdata->smba, SMBIOSIZE); - if (adapdata->sb800_main) { - kfree(adapdata->mutex); + if (adapdata->sb800_main) release_region(SB800_PIIX4_SMB_IDX, 2); - } } kfree(adapdata); kfree(adap); |