aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/i2c/i2c-core.c65
-rw-r--r--include/linux/i2c.h1
2 files changed, 62 insertions, 4 deletions
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index a2ad83ad0f53..3aac1b5c7cbd 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -41,6 +41,7 @@ static LIST_HEAD(drivers);
41static DEFINE_MUTEX(core_lists); 41static DEFINE_MUTEX(core_lists);
42static DEFINE_IDR(i2c_adapter_idr); 42static DEFINE_IDR(i2c_adapter_idr);
43 43
44#define is_newstyle_driver(d) ((d)->probe || (d)->remove)
44 45
45/* ------------------------------------------------------------------------- */ 46/* ------------------------------------------------------------------------- */
46 47
@@ -52,7 +53,7 @@ static int i2c_device_match(struct device *dev, struct device_driver *drv)
52 /* make legacy i2c drivers bypass driver model probing entirely; 53 /* make legacy i2c drivers bypass driver model probing entirely;
53 * such drivers scan each i2c adapter/bus themselves. 54 * such drivers scan each i2c adapter/bus themselves.
54 */ 55 */
55 if (!driver->probe) 56 if (!is_newstyle_driver(driver))
56 return 0; 57 return 0;
57 58
58 /* new style drivers use the same kind of driver matching policy 59 /* new style drivers use the same kind of driver matching policy
@@ -100,7 +101,24 @@ static int i2c_device_probe(struct device *dev)
100 101
101static int i2c_device_remove(struct device *dev) 102static int i2c_device_remove(struct device *dev)
102{ 103{
103 return 0; 104 struct i2c_client *client = to_i2c_client(dev);
105 struct i2c_driver *driver;
106 int status;
107
108 if (!dev->driver)
109 return 0;
110
111 driver = to_i2c_driver(dev->driver);
112 if (driver->remove) {
113 dev_dbg(dev, "remove\n");
114 status = driver->remove(client);
115 } else {
116 dev->driver = NULL;
117 status = 0;
118 }
119 if (status == 0)
120 client->driver = NULL;
121 return status;
104} 122}
105 123
106static void i2c_device_shutdown(struct device *dev) 124static void i2c_device_shutdown(struct device *dev)
@@ -177,6 +195,26 @@ struct bus_type i2c_bus_type = {
177 .resume = i2c_device_resume, 195 .resume = i2c_device_resume,
178}; 196};
179 197
198static void i2c_unregister_device(struct i2c_client *client)
199{
200 struct i2c_adapter *adapter = client->adapter;
201 struct i2c_driver *driver = client->driver;
202
203 if (driver && !is_newstyle_driver(driver)) {
204 dev_err(&client->dev, "can't unregister devices "
205 "with legacy drivers\n");
206 WARN_ON(1);
207 return;
208 }
209
210 mutex_lock(&adapter->clist_lock);
211 list_del(&client->list);
212 mutex_unlock(&adapter->clist_lock);
213
214 device_unregister(&client->dev);
215}
216
217
180/* ------------------------------------------------------------------------- */ 218/* ------------------------------------------------------------------------- */
181 219
182/* I2C bus adapters -- one roots each I2C or SMBUS segment */ 220/* I2C bus adapters -- one roots each I2C or SMBUS segment */
@@ -310,9 +348,19 @@ int i2c_del_adapter(struct i2c_adapter *adap)
310 /* detach any active clients. This must be done first, because 348 /* detach any active clients. This must be done first, because
311 * it can fail; in which case we give up. */ 349 * it can fail; in which case we give up. */
312 list_for_each_safe(item, _n, &adap->clients) { 350 list_for_each_safe(item, _n, &adap->clients) {
351 struct i2c_driver *driver;
352
313 client = list_entry(item, struct i2c_client, list); 353 client = list_entry(item, struct i2c_client, list);
354 driver = client->driver;
314 355
315 if ((res=client->driver->detach_client(client))) { 356 /* new style, follow standard driver model */
357 if (!driver || is_newstyle_driver(driver)) {
358 i2c_unregister_device(client);
359 continue;
360 }
361
362 /* legacy drivers create and remove clients themselves */
363 if ((res = driver->detach_client(client))) {
316 dev_err(&adap->dev, "detach_client failed for client " 364 dev_err(&adap->dev, "detach_client failed for client "
317 "[%s] at address 0x%02x\n", client->name, 365 "[%s] at address 0x%02x\n", client->name,
318 client->addr); 366 client->addr);
@@ -355,7 +403,7 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
355 int res; 403 int res;
356 404
357 /* new style driver methods can't mix with legacy ones */ 405 /* new style driver methods can't mix with legacy ones */
358 if (driver->probe) { 406 if (is_newstyle_driver(driver)) {
359 if (driver->attach_adapter || driver->detach_adapter 407 if (driver->attach_adapter || driver->detach_adapter
360 || driver->detach_client) { 408 || driver->detach_client) {
361 printk(KERN_WARNING 409 printk(KERN_WARNING
@@ -392,6 +440,10 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
392} 440}
393EXPORT_SYMBOL(i2c_register_driver); 441EXPORT_SYMBOL(i2c_register_driver);
394 442
443/**
444 * i2c_del_driver - unregister I2C driver
445 * @driver: the driver being unregistered
446 */
395int i2c_del_driver(struct i2c_driver *driver) 447int i2c_del_driver(struct i2c_driver *driver)
396{ 448{
397 struct list_head *item1, *item2, *_n; 449 struct list_head *item1, *item2, *_n;
@@ -402,6 +454,10 @@ int i2c_del_driver(struct i2c_driver *driver)
402 454
403 mutex_lock(&core_lists); 455 mutex_lock(&core_lists);
404 456
457 /* new-style driver? */
458 if (is_newstyle_driver(driver))
459 goto unregister;
460
405 /* Have a look at each adapter, if clients of this driver are still 461 /* Have a look at each adapter, if clients of this driver are still
406 * attached. If so, detach them to be able to kill the driver 462 * attached. If so, detach them to be able to kill the driver
407 * afterwards. 463 * afterwards.
@@ -434,6 +490,7 @@ int i2c_del_driver(struct i2c_driver *driver)
434 } 490 }
435 } 491 }
436 492
493 unregister:
437 driver_unregister(&driver->driver); 494 driver_unregister(&driver->driver);
438 list_del(&driver->list); 495 list_del(&driver->list);
439 pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name); 496 pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name);
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 8dcccc0f4822..6802c3a0a3a3 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -130,6 +130,7 @@ struct i2c_driver {
130 * it's done by infrastructure. (NEW STYLE DRIVERS ONLY) 130 * it's done by infrastructure. (NEW STYLE DRIVERS ONLY)
131 */ 131 */
132 int (*probe)(struct i2c_client *); 132 int (*probe)(struct i2c_client *);
133 int (*remove)(struct i2c_client *);
133 134
134 /* driver model interfaces that don't relate to enumeration */ 135 /* driver model interfaces that don't relate to enumeration */
135 void (*shutdown)(struct i2c_client *); 136 void (*shutdown)(struct i2c_client *);