aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@pobox.com>2005-09-08 05:37:58 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-09-08 05:37:58 -0400
commit5a2cec83a9bb1b4295aa8ab728fcb8ca1811a33c (patch)
tree2f83dc6949763e77cf6422e696dc6146684dcf4e /drivers/base
parentf2c853bca542f5ac0b036377637192a74f2091c2 (diff)
parentcaf39e87cc1182f7dae84eefc43ca14d54c78ef9 (diff)
Merge /spare/repo/linux-2.6/
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/attribute_container.c86
-rw-r--r--drivers/base/bus.c34
-rw-r--r--drivers/base/core.c17
-rw-r--r--drivers/base/driver.c15
-rw-r--r--drivers/base/firmware_class.c79
-rw-r--r--drivers/base/transport_class.c19
6 files changed, 200 insertions, 50 deletions
diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c
index ec615d854be9..373e7b728fa7 100644
--- a/drivers/base/attribute_container.c
+++ b/drivers/base/attribute_container.c
@@ -22,11 +22,26 @@
22/* This is a private structure used to tie the classdev and the 22/* This is a private structure used to tie the classdev and the
23 * container .. it should never be visible outside this file */ 23 * container .. it should never be visible outside this file */
24struct internal_container { 24struct internal_container {
25 struct list_head node; 25 struct klist_node node;
26 struct attribute_container *cont; 26 struct attribute_container *cont;
27 struct class_device classdev; 27 struct class_device classdev;
28}; 28};
29 29
30static void internal_container_klist_get(struct klist_node *n)
31{
32 struct internal_container *ic =
33 container_of(n, struct internal_container, node);
34 class_device_get(&ic->classdev);
35}
36
37static void internal_container_klist_put(struct klist_node *n)
38{
39 struct internal_container *ic =
40 container_of(n, struct internal_container, node);
41 class_device_put(&ic->classdev);
42}
43
44
30/** 45/**
31 * attribute_container_classdev_to_container - given a classdev, return the container 46 * attribute_container_classdev_to_container - given a classdev, return the container
32 * 47 *
@@ -57,7 +72,8 @@ int
57attribute_container_register(struct attribute_container *cont) 72attribute_container_register(struct attribute_container *cont)
58{ 73{
59 INIT_LIST_HEAD(&cont->node); 74 INIT_LIST_HEAD(&cont->node);
60 INIT_LIST_HEAD(&cont->containers); 75 klist_init(&cont->containers,internal_container_klist_get,
76 internal_container_klist_put);
61 77
62 down(&attribute_container_mutex); 78 down(&attribute_container_mutex);
63 list_add_tail(&cont->node, &attribute_container_list); 79 list_add_tail(&cont->node, &attribute_container_list);
@@ -77,11 +93,13 @@ attribute_container_unregister(struct attribute_container *cont)
77{ 93{
78 int retval = -EBUSY; 94 int retval = -EBUSY;
79 down(&attribute_container_mutex); 95 down(&attribute_container_mutex);
80 if (!list_empty(&cont->containers)) 96 spin_lock(&cont->containers.k_lock);
97 if (!list_empty(&cont->containers.k_list))
81 goto out; 98 goto out;
82 retval = 0; 99 retval = 0;
83 list_del(&cont->node); 100 list_del(&cont->node);
84 out: 101 out:
102 spin_unlock(&cont->containers.k_lock);
85 up(&attribute_container_mutex); 103 up(&attribute_container_mutex);
86 return retval; 104 return retval;
87 105
@@ -140,7 +158,6 @@ attribute_container_add_device(struct device *dev,
140 continue; 158 continue;
141 } 159 }
142 memset(ic, 0, sizeof(struct internal_container)); 160 memset(ic, 0, sizeof(struct internal_container));
143 INIT_LIST_HEAD(&ic->node);
144 ic->cont = cont; 161 ic->cont = cont;
145 class_device_initialize(&ic->classdev); 162 class_device_initialize(&ic->classdev);
146 ic->classdev.dev = get_device(dev); 163 ic->classdev.dev = get_device(dev);
@@ -151,11 +168,22 @@ attribute_container_add_device(struct device *dev,
151 fn(cont, dev, &ic->classdev); 168 fn(cont, dev, &ic->classdev);
152 else 169 else
153 attribute_container_add_class_device(&ic->classdev); 170 attribute_container_add_class_device(&ic->classdev);
154 list_add_tail(&ic->node, &cont->containers); 171 klist_add_tail(&ic->node, &cont->containers);
155 } 172 }
156 up(&attribute_container_mutex); 173 up(&attribute_container_mutex);
157} 174}
158 175
176/* FIXME: can't break out of this unless klist_iter_exit is also
177 * called before doing the break
178 */
179#define klist_for_each_entry(pos, head, member, iter) \
180 for (klist_iter_init(head, iter); (pos = ({ \
181 struct klist_node *n = klist_next(iter); \
182 n ? container_of(n, typeof(*pos), member) : \
183 ({ klist_iter_exit(iter) ; NULL; }); \
184 }) ) != NULL; )
185
186
159/** 187/**
160 * attribute_container_remove_device - make device eligible for removal. 188 * attribute_container_remove_device - make device eligible for removal.
161 * 189 *
@@ -182,17 +210,19 @@ attribute_container_remove_device(struct device *dev,
182 210
183 down(&attribute_container_mutex); 211 down(&attribute_container_mutex);
184 list_for_each_entry(cont, &attribute_container_list, node) { 212 list_for_each_entry(cont, &attribute_container_list, node) {
185 struct internal_container *ic, *tmp; 213 struct internal_container *ic;
214 struct klist_iter iter;
186 215
187 if (attribute_container_no_classdevs(cont)) 216 if (attribute_container_no_classdevs(cont))
188 continue; 217 continue;
189 218
190 if (!cont->match(cont, dev)) 219 if (!cont->match(cont, dev))
191 continue; 220 continue;
192 list_for_each_entry_safe(ic, tmp, &cont->containers, node) { 221
222 klist_for_each_entry(ic, &cont->containers, node, &iter) {
193 if (dev != ic->classdev.dev) 223 if (dev != ic->classdev.dev)
194 continue; 224 continue;
195 list_del(&ic->node); 225 klist_del(&ic->node);
196 if (fn) 226 if (fn)
197 fn(cont, dev, &ic->classdev); 227 fn(cont, dev, &ic->classdev);
198 else { 228 else {
@@ -225,12 +255,18 @@ attribute_container_device_trigger(struct device *dev,
225 255
226 down(&attribute_container_mutex); 256 down(&attribute_container_mutex);
227 list_for_each_entry(cont, &attribute_container_list, node) { 257 list_for_each_entry(cont, &attribute_container_list, node) {
228 struct internal_container *ic, *tmp; 258 struct internal_container *ic;
259 struct klist_iter iter;
229 260
230 if (!cont->match(cont, dev)) 261 if (!cont->match(cont, dev))
231 continue; 262 continue;
232 263
233 list_for_each_entry_safe(ic, tmp, &cont->containers, node) { 264 if (attribute_container_no_classdevs(cont)) {
265 fn(cont, dev, NULL);
266 continue;
267 }
268
269 klist_for_each_entry(ic, &cont->containers, node, &iter) {
234 if (dev == ic->classdev.dev) 270 if (dev == ic->classdev.dev)
235 fn(cont, dev, &ic->classdev); 271 fn(cont, dev, &ic->classdev);
236 } 272 }
@@ -368,6 +404,36 @@ attribute_container_class_device_del(struct class_device *classdev)
368} 404}
369EXPORT_SYMBOL_GPL(attribute_container_class_device_del); 405EXPORT_SYMBOL_GPL(attribute_container_class_device_del);
370 406
407/**
408 * attribute_container_find_class_device - find the corresponding class_device
409 *
410 * @cont: the container
411 * @dev: the generic device
412 *
413 * Looks up the device in the container's list of class devices and returns
414 * the corresponding class_device.
415 */
416struct class_device *
417attribute_container_find_class_device(struct attribute_container *cont,
418 struct device *dev)
419{
420 struct class_device *cdev = NULL;
421 struct internal_container *ic;
422 struct klist_iter iter;
423
424 klist_for_each_entry(ic, &cont->containers, node, &iter) {
425 if (ic->classdev.dev == dev) {
426 cdev = &ic->classdev;
427 /* FIXME: must exit iterator then break */
428 klist_iter_exit(&iter);
429 break;
430 }
431 }
432
433 return cdev;
434}
435EXPORT_SYMBOL_GPL(attribute_container_find_class_device);
436
371int __init 437int __init
372attribute_container_init(void) 438attribute_container_init(void)
373{ 439{
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 17e96698410e..03204bfd17af 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -568,6 +568,36 @@ static void bus_remove_attrs(struct bus_type * bus)
568 } 568 }
569} 569}
570 570
571static void klist_devices_get(struct klist_node *n)
572{
573 struct device *dev = container_of(n, struct device, knode_bus);
574
575 get_device(dev);
576}
577
578static void klist_devices_put(struct klist_node *n)
579{
580 struct device *dev = container_of(n, struct device, knode_bus);
581
582 put_device(dev);
583}
584
585static void klist_drivers_get(struct klist_node *n)
586{
587 struct device_driver *drv = container_of(n, struct device_driver,
588 knode_bus);
589
590 get_driver(drv);
591}
592
593static void klist_drivers_put(struct klist_node *n)
594{
595 struct device_driver *drv = container_of(n, struct device_driver,
596 knode_bus);
597
598 put_driver(drv);
599}
600
571/** 601/**
572 * bus_register - register a bus with the system. 602 * bus_register - register a bus with the system.
573 * @bus: bus. 603 * @bus: bus.
@@ -602,8 +632,8 @@ int bus_register(struct bus_type * bus)
602 if (retval) 632 if (retval)
603 goto bus_drivers_fail; 633 goto bus_drivers_fail;
604 634
605 klist_init(&bus->klist_devices); 635 klist_init(&bus->klist_devices, klist_devices_get, klist_devices_put);
606 klist_init(&bus->klist_drivers); 636 klist_init(&bus->klist_drivers, klist_drivers_get, klist_drivers_put);
607 bus_add_attrs(bus); 637 bus_add_attrs(bus);
608 638
609 pr_debug("bus type '%s' registered\n", bus->name); 639 pr_debug("bus type '%s' registered\n", bus->name);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index c8a33df00761..6ab73f5c799a 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -191,6 +191,20 @@ void device_remove_file(struct device * dev, struct device_attribute * attr)
191 } 191 }
192} 192}
193 193
194static void klist_children_get(struct klist_node *n)
195{
196 struct device *dev = container_of(n, struct device, knode_parent);
197
198 get_device(dev);
199}
200
201static void klist_children_put(struct klist_node *n)
202{
203 struct device *dev = container_of(n, struct device, knode_parent);
204
205 put_device(dev);
206}
207
194 208
195/** 209/**
196 * device_initialize - init device structure. 210 * device_initialize - init device structure.
@@ -207,7 +221,8 @@ void device_initialize(struct device *dev)
207{ 221{
208 kobj_set_kset_s(dev, devices_subsys); 222 kobj_set_kset_s(dev, devices_subsys);
209 kobject_init(&dev->kobj); 223 kobject_init(&dev->kobj);
210 klist_init(&dev->klist_children); 224 klist_init(&dev->klist_children, klist_children_get,
225 klist_children_put);
211 INIT_LIST_HEAD(&dev->dma_pools); 226 INIT_LIST_HEAD(&dev->dma_pools);
212 init_MUTEX(&dev->sem); 227 init_MUTEX(&dev->sem);
213} 228}
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index 291c5954a3af..ef3fe513e398 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -142,6 +142,19 @@ void put_driver(struct device_driver * drv)
142 kobject_put(&drv->kobj); 142 kobject_put(&drv->kobj);
143} 143}
144 144
145static void klist_devices_get(struct klist_node *n)
146{
147 struct device *dev = container_of(n, struct device, knode_driver);
148
149 get_device(dev);
150}
151
152static void klist_devices_put(struct klist_node *n)
153{
154 struct device *dev = container_of(n, struct device, knode_driver);
155
156 put_device(dev);
157}
145 158
146/** 159/**
147 * driver_register - register driver with bus 160 * driver_register - register driver with bus
@@ -157,7 +170,7 @@ void put_driver(struct device_driver * drv)
157 */ 170 */
158int driver_register(struct device_driver * drv) 171int driver_register(struct device_driver * drv)
159{ 172{
160 klist_init(&drv->klist_devices); 173 klist_init(&drv->klist_devices, klist_devices_get, klist_devices_put);
161 init_completion(&drv->unloaded); 174 init_completion(&drv->unloaded);
162 return bus_add_driver(drv); 175 return bus_add_driver(drv);
163} 176}
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 652281402c92..5bfa2e9a7c26 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -28,6 +28,7 @@ enum {
28 FW_STATUS_DONE, 28 FW_STATUS_DONE,
29 FW_STATUS_ABORT, 29 FW_STATUS_ABORT,
30 FW_STATUS_READY, 30 FW_STATUS_READY,
31 FW_STATUS_READY_NOHOTPLUG,
31}; 32};
32 33
33static int loading_timeout = 10; /* In seconds */ 34static int loading_timeout = 10; /* In seconds */
@@ -344,7 +345,7 @@ error_kfree:
344 345
345static int 346static int
346fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p, 347fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p,
347 const char *fw_name, struct device *device) 348 const char *fw_name, struct device *device, int hotplug)
348{ 349{
349 struct class_device *class_dev; 350 struct class_device *class_dev;
350 struct firmware_priv *fw_priv; 351 struct firmware_priv *fw_priv;
@@ -376,7 +377,10 @@ fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p,
376 goto error_unreg; 377 goto error_unreg;
377 } 378 }
378 379
379 set_bit(FW_STATUS_READY, &fw_priv->status); 380 if (hotplug)
381 set_bit(FW_STATUS_READY, &fw_priv->status);
382 else
383 set_bit(FW_STATUS_READY_NOHOTPLUG, &fw_priv->status);
380 *class_dev_p = class_dev; 384 *class_dev_p = class_dev;
381 goto out; 385 goto out;
382 386
@@ -386,21 +390,9 @@ out:
386 return retval; 390 return retval;
387} 391}
388 392
389/** 393static int
390 * request_firmware: - request firmware to hotplug and wait for it 394_request_firmware(const struct firmware **firmware_p, const char *name,
391 * Description: 395 struct device *device, int hotplug)
392 * @firmware will be used to return a firmware image by the name
393 * of @name for device @device.
394 *
395 * Should be called from user context where sleeping is allowed.
396 *
397 * @name will be use as $FIRMWARE in the hotplug environment and
398 * should be distinctive enough not to be confused with any other
399 * firmware image for this or any other device.
400 **/
401int
402request_firmware(const struct firmware **firmware_p, const char *name,
403 struct device *device)
404{ 396{
405 struct class_device *class_dev; 397 struct class_device *class_dev;
406 struct firmware_priv *fw_priv; 398 struct firmware_priv *fw_priv;
@@ -419,22 +411,25 @@ request_firmware(const struct firmware **firmware_p, const char *name,
419 } 411 }
420 memset(firmware, 0, sizeof (*firmware)); 412 memset(firmware, 0, sizeof (*firmware));
421 413
422 retval = fw_setup_class_device(firmware, &class_dev, name, device); 414 retval = fw_setup_class_device(firmware, &class_dev, name, device,
415 hotplug);
423 if (retval) 416 if (retval)
424 goto error_kfree_fw; 417 goto error_kfree_fw;
425 418
426 fw_priv = class_get_devdata(class_dev); 419 fw_priv = class_get_devdata(class_dev);
427 420
428 if (loading_timeout > 0) { 421 if (hotplug) {
429 fw_priv->timeout.expires = jiffies + loading_timeout * HZ; 422 if (loading_timeout > 0) {
430 add_timer(&fw_priv->timeout); 423 fw_priv->timeout.expires = jiffies + loading_timeout * HZ;
431 } 424 add_timer(&fw_priv->timeout);
432 425 }
433 kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
434 wait_for_completion(&fw_priv->completion);
435 set_bit(FW_STATUS_DONE, &fw_priv->status);
436 426
437 del_timer_sync(&fw_priv->timeout); 427 kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
428 wait_for_completion(&fw_priv->completion);
429 set_bit(FW_STATUS_DONE, &fw_priv->status);
430 del_timer_sync(&fw_priv->timeout);
431 } else
432 wait_for_completion(&fw_priv->completion);
438 433
439 down(&fw_lock); 434 down(&fw_lock);
440 if (!fw_priv->fw->size || test_bit(FW_STATUS_ABORT, &fw_priv->status)) { 435 if (!fw_priv->fw->size || test_bit(FW_STATUS_ABORT, &fw_priv->status)) {
@@ -455,6 +450,26 @@ out:
455} 450}
456 451
457/** 452/**
453 * request_firmware: - request firmware to hotplug and wait for it
454 * Description:
455 * @firmware will be used to return a firmware image by the name
456 * of @name for device @device.
457 *
458 * Should be called from user context where sleeping is allowed.
459 *
460 * @name will be use as $FIRMWARE in the hotplug environment and
461 * should be distinctive enough not to be confused with any other
462 * firmware image for this or any other device.
463 **/
464int
465request_firmware(const struct firmware **firmware_p, const char *name,
466 struct device *device)
467{
468 int hotplug = 1;
469 return _request_firmware(firmware_p, name, device, hotplug);
470}
471
472/**
458 * release_firmware: - release the resource associated with a firmware image 473 * release_firmware: - release the resource associated with a firmware image
459 **/ 474 **/
460void 475void
@@ -491,6 +506,7 @@ struct firmware_work {
491 struct device *device; 506 struct device *device;
492 void *context; 507 void *context;
493 void (*cont)(const struct firmware *fw, void *context); 508 void (*cont)(const struct firmware *fw, void *context);
509 int hotplug;
494}; 510};
495 511
496static int 512static int
@@ -503,7 +519,8 @@ request_firmware_work_func(void *arg)
503 return 0; 519 return 0;
504 } 520 }
505 daemonize("%s/%s", "firmware", fw_work->name); 521 daemonize("%s/%s", "firmware", fw_work->name);
506 request_firmware(&fw, fw_work->name, fw_work->device); 522 _request_firmware(&fw, fw_work->name, fw_work->device,
523 fw_work->hotplug);
507 fw_work->cont(fw, fw_work->context); 524 fw_work->cont(fw, fw_work->context);
508 release_firmware(fw); 525 release_firmware(fw);
509 module_put(fw_work->module); 526 module_put(fw_work->module);
@@ -518,6 +535,9 @@ request_firmware_work_func(void *arg)
518 * Asynchronous variant of request_firmware() for contexts where 535 * Asynchronous variant of request_firmware() for contexts where
519 * it is not possible to sleep. 536 * it is not possible to sleep.
520 * 537 *
538 * @hotplug invokes hotplug event to copy the firmware image if this flag
539 * is non-zero else the firmware copy must be done manually.
540 *
521 * @cont will be called asynchronously when the firmware request is over. 541 * @cont will be called asynchronously when the firmware request is over.
522 * 542 *
523 * @context will be passed over to @cont. 543 * @context will be passed over to @cont.
@@ -527,7 +547,7 @@ request_firmware_work_func(void *arg)
527 **/ 547 **/
528int 548int
529request_firmware_nowait( 549request_firmware_nowait(
530 struct module *module, 550 struct module *module, int hotplug,
531 const char *name, struct device *device, void *context, 551 const char *name, struct device *device, void *context,
532 void (*cont)(const struct firmware *fw, void *context)) 552 void (*cont)(const struct firmware *fw, void *context))
533{ 553{
@@ -548,6 +568,7 @@ request_firmware_nowait(
548 .device = device, 568 .device = device,
549 .context = context, 569 .context = context,
550 .cont = cont, 570 .cont = cont,
571 .hotplug = hotplug,
551 }; 572 };
552 573
553 ret = kernel_thread(request_firmware_work_func, fw_work, 574 ret = kernel_thread(request_firmware_work_func, fw_work,
diff --git a/drivers/base/transport_class.c b/drivers/base/transport_class.c
index 6c2b447a3336..f25e7c6b2d27 100644
--- a/drivers/base/transport_class.c
+++ b/drivers/base/transport_class.c
@@ -7,7 +7,7 @@
7 * This file is licensed under GPLv2 7 * This file is licensed under GPLv2
8 * 8 *
9 * The basic idea here is to allow any "device controller" (which 9 * The basic idea here is to allow any "device controller" (which
10 * would most often be a Host Bus Adapter" to use the services of one 10 * would most often be a Host Bus Adapter to use the services of one
11 * or more tranport classes for performing transport specific 11 * or more tranport classes for performing transport specific
12 * services. Transport specific services are things that the generic 12 * services. Transport specific services are things that the generic
13 * command layer doesn't want to know about (speed settings, line 13 * command layer doesn't want to know about (speed settings, line
@@ -64,7 +64,9 @@ void transport_class_unregister(struct transport_class *tclass)
64} 64}
65EXPORT_SYMBOL_GPL(transport_class_unregister); 65EXPORT_SYMBOL_GPL(transport_class_unregister);
66 66
67static int anon_transport_dummy_function(struct device *dev) 67static int anon_transport_dummy_function(struct transport_container *tc,
68 struct device *dev,
69 struct class_device *cdev)
68{ 70{
69 /* do nothing */ 71 /* do nothing */
70 return 0; 72 return 0;
@@ -115,9 +117,10 @@ static int transport_setup_classdev(struct attribute_container *cont,
115 struct class_device *classdev) 117 struct class_device *classdev)
116{ 118{
117 struct transport_class *tclass = class_to_transport_class(cont->class); 119 struct transport_class *tclass = class_to_transport_class(cont->class);
120 struct transport_container *tcont = attribute_container_to_transport_container(cont);
118 121
119 if (tclass->setup) 122 if (tclass->setup)
120 tclass->setup(dev); 123 tclass->setup(tcont, dev, classdev);
121 124
122 return 0; 125 return 0;
123} 126}
@@ -178,12 +181,14 @@ void transport_add_device(struct device *dev)
178EXPORT_SYMBOL_GPL(transport_add_device); 181EXPORT_SYMBOL_GPL(transport_add_device);
179 182
180static int transport_configure(struct attribute_container *cont, 183static int transport_configure(struct attribute_container *cont,
181 struct device *dev) 184 struct device *dev,
185 struct class_device *cdev)
182{ 186{
183 struct transport_class *tclass = class_to_transport_class(cont->class); 187 struct transport_class *tclass = class_to_transport_class(cont->class);
188 struct transport_container *tcont = attribute_container_to_transport_container(cont);
184 189
185 if (tclass->configure) 190 if (tclass->configure)
186 tclass->configure(dev); 191 tclass->configure(tcont, dev, cdev);
187 192
188 return 0; 193 return 0;
189} 194}
@@ -202,7 +207,7 @@ static int transport_configure(struct attribute_container *cont,
202 */ 207 */
203void transport_configure_device(struct device *dev) 208void transport_configure_device(struct device *dev)
204{ 209{
205 attribute_container_trigger(dev, transport_configure); 210 attribute_container_device_trigger(dev, transport_configure);
206} 211}
207EXPORT_SYMBOL_GPL(transport_configure_device); 212EXPORT_SYMBOL_GPL(transport_configure_device);
208 213
@@ -215,7 +220,7 @@ static int transport_remove_classdev(struct attribute_container *cont,
215 struct transport_class *tclass = class_to_transport_class(cont->class); 220 struct transport_class *tclass = class_to_transport_class(cont->class);
216 221
217 if (tclass->remove) 222 if (tclass->remove)
218 tclass->remove(dev); 223 tclass->remove(tcont, dev, classdev);
219 224
220 if (tclass->remove != anon_transport_dummy_function) { 225 if (tclass->remove != anon_transport_dummy_function) {
221 if (tcont->statistics) 226 if (tcont->statistics)