Skip to content

Commit

Permalink
Merge branch 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/…
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
Linus Torvalds committed Jan 31, 2016
2 parents ad0b40f + 52795f6 commit bb47680
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 30 deletions.
3 changes: 2 additions & 1 deletion drivers/i2c/busses/i2c-designware-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
50 changes: 21 additions & 29 deletions drivers/i2c/busses/i2c-piix4.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,18 +137,18 @@ 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;

/* SB800 */
bool sb800_main;
unsigned short port;
struct mutex *mutex;
};

static int piix4_setup(struct pci_dev *PIIX4_dev,
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
Expand All @@ -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) {
Expand All @@ -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);

Expand All @@ -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;
Expand All @@ -714,19 +706,20 @@ static int piix4_add_adapters_sb800(struct pci_dev *dev, unsigned short smba)
}
}

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",
Expand Down Expand Up @@ -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;
Expand All @@ -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);
}

Expand All @@ -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);
Expand Down

0 comments on commit bb47680

Please sign in to comment.