diff options
| author | Jean Delvare <khali@linux-fr.org> | 2008-07-16 13:30:05 -0400 |
|---|---|---|
| committer | Jean Delvare <khali@mahadeva.delvare> | 2008-07-16 13:30:05 -0400 |
| commit | bd4bc3dbded9cd7b2bdca6bba1aecb4251a8039d (patch) | |
| tree | 463f7b4283b3924abf504e4db020050bd2b55db5 | |
| parent | 45158894d4d6704afbb4cefe55e5f6ca279fe12a (diff) | |
i2c: Clear i2c_adapter.dev on adapter removal
Clear i2c_adapter.dev on adapter removal. This makes it possible to
re-add the adapter at a later point, which some drivers
(i2c-amd756-s4882, i2c-nforce2-s4985) actually do.
This fixes a bug reported by John Stultz here:
http://lkml.org/lkml/2008/7/15/720
and by Ingo Molar there:
http://lkml.org/lkml/2008/7/16/78
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Cc: John Stultz <johnstul@us.ibm.com>
Cc: Ingo Molnar <mingo@elte.hu>
| -rw-r--r-- | drivers/i2c/busses/i2c-amd756-s4882.c | 27 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-nforce2-s4985.c | 31 | ||||
| -rw-r--r-- | drivers/i2c/i2c-core.c | 4 |
3 files changed, 32 insertions, 30 deletions
diff --git a/drivers/i2c/busses/i2c-amd756-s4882.c b/drivers/i2c/busses/i2c-amd756-s4882.c index 2f150e33c74c..72872d1e63ef 100644 --- a/drivers/i2c/busses/i2c-amd756-s4882.c +++ b/drivers/i2c/busses/i2c-amd756-s4882.c | |||
| @@ -155,6 +155,16 @@ static int __init amd756_s4882_init(void) | |||
| 155 | int i, error; | 155 | int i, error; |
| 156 | union i2c_smbus_data ioconfig; | 156 | union i2c_smbus_data ioconfig; |
| 157 | 157 | ||
| 158 | /* Configure the PCA9556 multiplexer */ | ||
| 159 | ioconfig.byte = 0x00; /* All I/O to output mode */ | ||
| 160 | error = i2c_smbus_xfer(&amd756_smbus, 0x18, 0, I2C_SMBUS_WRITE, 0x03, | ||
| 161 | I2C_SMBUS_BYTE_DATA, &ioconfig); | ||
| 162 | if (error) { | ||
| 163 | dev_err(&amd756_smbus.dev, "PCA9556 configuration failed\n"); | ||
| 164 | error = -EIO; | ||
| 165 | goto ERROR0; | ||
| 166 | } | ||
| 167 | |||
| 158 | /* Unregister physical bus */ | 168 | /* Unregister physical bus */ |
| 159 | error = i2c_del_adapter(&amd756_smbus); | 169 | error = i2c_del_adapter(&amd756_smbus); |
| 160 | if (error) { | 170 | if (error) { |
| @@ -198,22 +208,11 @@ static int __init amd756_s4882_init(void) | |||
| 198 | s4882_algo[3].smbus_xfer = amd756_access_virt3; | 208 | s4882_algo[3].smbus_xfer = amd756_access_virt3; |
| 199 | s4882_algo[4].smbus_xfer = amd756_access_virt4; | 209 | s4882_algo[4].smbus_xfer = amd756_access_virt4; |
| 200 | 210 | ||
| 201 | /* Configure the PCA9556 multiplexer */ | ||
| 202 | ioconfig.byte = 0x00; /* All I/O to output mode */ | ||
| 203 | error = amd756_smbus.algo->smbus_xfer(&amd756_smbus, 0x18, 0, | ||
| 204 | I2C_SMBUS_WRITE, 0x03, | ||
| 205 | I2C_SMBUS_BYTE_DATA, &ioconfig); | ||
| 206 | if (error) { | ||
| 207 | dev_err(&amd756_smbus.dev, "PCA9556 configuration failed\n"); | ||
| 208 | error = -EIO; | ||
| 209 | goto ERROR3; | ||
| 210 | } | ||
| 211 | |||
| 212 | /* Register virtual adapters */ | 211 | /* Register virtual adapters */ |
| 213 | for (i = 0; i < 5; i++) { | 212 | for (i = 0; i < 5; i++) { |
| 214 | error = i2c_add_adapter(s4882_adapter+i); | 213 | error = i2c_add_adapter(s4882_adapter+i); |
| 215 | if (error) { | 214 | if (error) { |
| 216 | dev_err(&amd756_smbus.dev, | 215 | printk(KERN_ERR "i2c-amd756-s4882: " |
| 217 | "Virtual adapter %d registration " | 216 | "Virtual adapter %d registration " |
| 218 | "failed, module not inserted\n", i); | 217 | "failed, module not inserted\n", i); |
| 219 | for (i--; i >= 0; i--) | 218 | for (i--; i >= 0; i--) |
| @@ -252,8 +251,8 @@ static void __exit amd756_s4882_exit(void) | |||
| 252 | 251 | ||
| 253 | /* Restore physical bus */ | 252 | /* Restore physical bus */ |
| 254 | if (i2c_add_adapter(&amd756_smbus)) | 253 | if (i2c_add_adapter(&amd756_smbus)) |
| 255 | dev_err(&amd756_smbus.dev, "Physical bus restoration " | 254 | printk(KERN_ERR "i2c-amd756-s4882: " |
| 256 | "failed\n"); | 255 | "Physical bus restoration failed\n"); |
| 257 | } | 256 | } |
| 258 | 257 | ||
| 259 | MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>"); | 258 | MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>"); |
diff --git a/drivers/i2c/busses/i2c-nforce2-s4985.c b/drivers/i2c/busses/i2c-nforce2-s4985.c index 6a8995dfd0bb..d1a4cbcf2aa4 100644 --- a/drivers/i2c/busses/i2c-nforce2-s4985.c +++ b/drivers/i2c/busses/i2c-nforce2-s4985.c | |||
| @@ -150,6 +150,16 @@ static int __init nforce2_s4985_init(void) | |||
| 150 | int i, error; | 150 | int i, error; |
| 151 | union i2c_smbus_data ioconfig; | 151 | union i2c_smbus_data ioconfig; |
| 152 | 152 | ||
| 153 | /* Configure the PCA9556 multiplexer */ | ||
| 154 | ioconfig.byte = 0x00; /* All I/O to output mode */ | ||
| 155 | error = i2c_smbus_xfer(nforce2_smbus, 0x18, 0, I2C_SMBUS_WRITE, 0x03, | ||
| 156 | I2C_SMBUS_BYTE_DATA, &ioconfig); | ||
| 157 | if (error) { | ||
| 158 | dev_err(&nforce2_smbus->dev, "PCA9556 configuration failed\n"); | ||
| 159 | error = -EIO; | ||
| 160 | goto ERROR0; | ||
| 161 | } | ||
| 162 | |||
| 153 | /* Unregister physical bus */ | 163 | /* Unregister physical bus */ |
| 154 | if (!nforce2_smbus) | 164 | if (!nforce2_smbus) |
| 155 | return -ENODEV; | 165 | return -ENODEV; |
| @@ -191,24 +201,13 @@ static int __init nforce2_s4985_init(void) | |||
| 191 | s4985_algo[3].smbus_xfer = nforce2_access_virt3; | 201 | s4985_algo[3].smbus_xfer = nforce2_access_virt3; |
| 192 | s4985_algo[4].smbus_xfer = nforce2_access_virt4; | 202 | s4985_algo[4].smbus_xfer = nforce2_access_virt4; |
| 193 | 203 | ||
| 194 | /* Configure the PCA9556 multiplexer */ | ||
| 195 | ioconfig.byte = 0x00; /* All I/O to output mode */ | ||
| 196 | error = nforce2_smbus->algo->smbus_xfer(nforce2_smbus, 0x18, 0, | ||
| 197 | I2C_SMBUS_WRITE, 0x03, | ||
| 198 | I2C_SMBUS_BYTE_DATA, &ioconfig); | ||
| 199 | if (error) { | ||
| 200 | dev_err(&nforce2_smbus->dev, "PCA9556 configuration failed\n"); | ||
| 201 | error = -EIO; | ||
| 202 | goto ERROR3; | ||
| 203 | } | ||
| 204 | |||
| 205 | /* Register virtual adapters */ | 204 | /* Register virtual adapters */ |
| 206 | for (i = 0; i < 5; i++) { | 205 | for (i = 0; i < 5; i++) { |
| 207 | error = i2c_add_adapter(s4985_adapter + i); | 206 | error = i2c_add_adapter(s4985_adapter + i); |
| 208 | if (error) { | 207 | if (error) { |
| 209 | dev_err(&nforce2_smbus->dev, | 208 | printk(KERN_ERR "i2c-nforce2-s4985: " |
| 210 | "Virtual adapter %d registration " | 209 | "Virtual adapter %d registration " |
| 211 | "failed, module not inserted\n", i); | 210 | "failed, module not inserted\n", i); |
| 212 | for (i--; i >= 0; i--) | 211 | for (i--; i >= 0; i--) |
| 213 | i2c_del_adapter(s4985_adapter + i); | 212 | i2c_del_adapter(s4985_adapter + i); |
| 214 | goto ERROR3; | 213 | goto ERROR3; |
| @@ -245,8 +244,8 @@ static void __exit nforce2_s4985_exit(void) | |||
| 245 | 244 | ||
| 246 | /* Restore physical bus */ | 245 | /* Restore physical bus */ |
| 247 | if (i2c_add_adapter(nforce2_smbus)) | 246 | if (i2c_add_adapter(nforce2_smbus)) |
| 248 | dev_err(&nforce2_smbus->dev, "Physical bus restoration " | 247 | printk(KERN_ERR "i2c-nforce2-s4985: " |
| 249 | "failed\n"); | 248 | "Physical bus restoration failed\n"); |
| 250 | } | 249 | } |
| 251 | 250 | ||
| 252 | MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>"); | 251 | MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>"); |
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 0a79f7661017..7608df83d6d1 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c | |||
| @@ -654,6 +654,10 @@ int i2c_del_adapter(struct i2c_adapter *adap) | |||
| 654 | 654 | ||
| 655 | dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name); | 655 | dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name); |
| 656 | 656 | ||
| 657 | /* Clear the device structure in case this adapter is ever going to be | ||
| 658 | added again */ | ||
| 659 | memset(&adap->dev, 0, sizeof(adap->dev)); | ||
| 660 | |||
| 657 | out_unlock: | 661 | out_unlock: |
| 658 | mutex_unlock(&core_lock); | 662 | mutex_unlock(&core_lock); |
| 659 | return res; | 663 | return res; |
