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
This commit is contained in:
Коммит
bb4768004b
|
@ -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",
|
||||
|
|
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче