0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/attribute_container.h>
0014 #include <linux/device.h>
0015 #include <linux/kernel.h>
0016 #include <linux/slab.h>
0017 #include <linux/list.h>
0018 #include <linux/module.h>
0019 #include <linux/mutex.h>
0020
0021 #include "base.h"
0022
0023
0024
0025 struct internal_container {
0026 struct klist_node node;
0027 struct attribute_container *cont;
0028 struct device classdev;
0029 };
0030
0031 static void internal_container_klist_get(struct klist_node *n)
0032 {
0033 struct internal_container *ic =
0034 container_of(n, struct internal_container, node);
0035 get_device(&ic->classdev);
0036 }
0037
0038 static void internal_container_klist_put(struct klist_node *n)
0039 {
0040 struct internal_container *ic =
0041 container_of(n, struct internal_container, node);
0042 put_device(&ic->classdev);
0043 }
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053 struct attribute_container *
0054 attribute_container_classdev_to_container(struct device *classdev)
0055 {
0056 struct internal_container *ic =
0057 container_of(classdev, struct internal_container, classdev);
0058 return ic->cont;
0059 }
0060 EXPORT_SYMBOL_GPL(attribute_container_classdev_to_container);
0061
0062 static LIST_HEAD(attribute_container_list);
0063
0064 static DEFINE_MUTEX(attribute_container_mutex);
0065
0066
0067
0068
0069
0070
0071
0072 int
0073 attribute_container_register(struct attribute_container *cont)
0074 {
0075 INIT_LIST_HEAD(&cont->node);
0076 klist_init(&cont->containers, internal_container_klist_get,
0077 internal_container_klist_put);
0078
0079 mutex_lock(&attribute_container_mutex);
0080 list_add_tail(&cont->node, &attribute_container_list);
0081 mutex_unlock(&attribute_container_mutex);
0082
0083 return 0;
0084 }
0085 EXPORT_SYMBOL_GPL(attribute_container_register);
0086
0087
0088
0089
0090
0091
0092 int
0093 attribute_container_unregister(struct attribute_container *cont)
0094 {
0095 int retval = -EBUSY;
0096
0097 mutex_lock(&attribute_container_mutex);
0098 spin_lock(&cont->containers.k_lock);
0099 if (!list_empty(&cont->containers.k_list))
0100 goto out;
0101 retval = 0;
0102 list_del(&cont->node);
0103 out:
0104 spin_unlock(&cont->containers.k_lock);
0105 mutex_unlock(&attribute_container_mutex);
0106 return retval;
0107
0108 }
0109 EXPORT_SYMBOL_GPL(attribute_container_unregister);
0110
0111
0112 static void attribute_container_release(struct device *classdev)
0113 {
0114 struct internal_container *ic
0115 = container_of(classdev, struct internal_container, classdev);
0116 struct device *dev = classdev->parent;
0117
0118 kfree(ic);
0119 put_device(dev);
0120 }
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140 void
0141 attribute_container_add_device(struct device *dev,
0142 int (*fn)(struct attribute_container *,
0143 struct device *,
0144 struct device *))
0145 {
0146 struct attribute_container *cont;
0147
0148 mutex_lock(&attribute_container_mutex);
0149 list_for_each_entry(cont, &attribute_container_list, node) {
0150 struct internal_container *ic;
0151
0152 if (attribute_container_no_classdevs(cont))
0153 continue;
0154
0155 if (!cont->match(cont, dev))
0156 continue;
0157
0158 ic = kzalloc(sizeof(*ic), GFP_KERNEL);
0159 if (!ic) {
0160 dev_err(dev, "failed to allocate class container\n");
0161 continue;
0162 }
0163
0164 ic->cont = cont;
0165 device_initialize(&ic->classdev);
0166 ic->classdev.parent = get_device(dev);
0167 ic->classdev.class = cont->class;
0168 cont->class->dev_release = attribute_container_release;
0169 dev_set_name(&ic->classdev, "%s", dev_name(dev));
0170 if (fn)
0171 fn(cont, dev, &ic->classdev);
0172 else
0173 attribute_container_add_class_device(&ic->classdev);
0174 klist_add_tail(&ic->node, &cont->containers);
0175 }
0176 mutex_unlock(&attribute_container_mutex);
0177 }
0178
0179
0180
0181
0182 #define klist_for_each_entry(pos, head, member, iter) \
0183 for (klist_iter_init(head, iter); (pos = ({ \
0184 struct klist_node *n = klist_next(iter); \
0185 n ? container_of(n, typeof(*pos), member) : \
0186 ({ klist_iter_exit(iter) ; NULL; }); \
0187 })) != NULL;)
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205 void
0206 attribute_container_remove_device(struct device *dev,
0207 void (*fn)(struct attribute_container *,
0208 struct device *,
0209 struct device *))
0210 {
0211 struct attribute_container *cont;
0212
0213 mutex_lock(&attribute_container_mutex);
0214 list_for_each_entry(cont, &attribute_container_list, node) {
0215 struct internal_container *ic;
0216 struct klist_iter iter;
0217
0218 if (attribute_container_no_classdevs(cont))
0219 continue;
0220
0221 if (!cont->match(cont, dev))
0222 continue;
0223
0224 klist_for_each_entry(ic, &cont->containers, node, &iter) {
0225 if (dev != ic->classdev.parent)
0226 continue;
0227 klist_del(&ic->node);
0228 if (fn)
0229 fn(cont, dev, &ic->classdev);
0230 else {
0231 attribute_container_remove_attrs(&ic->classdev);
0232 device_unregister(&ic->classdev);
0233 }
0234 }
0235 }
0236 mutex_unlock(&attribute_container_mutex);
0237 }
0238
0239 static int
0240 do_attribute_container_device_trigger_safe(struct device *dev,
0241 struct attribute_container *cont,
0242 int (*fn)(struct attribute_container *,
0243 struct device *, struct device *),
0244 int (*undo)(struct attribute_container *,
0245 struct device *, struct device *))
0246 {
0247 int ret;
0248 struct internal_container *ic, *failed;
0249 struct klist_iter iter;
0250
0251 if (attribute_container_no_classdevs(cont))
0252 return fn(cont, dev, NULL);
0253
0254 klist_for_each_entry(ic, &cont->containers, node, &iter) {
0255 if (dev == ic->classdev.parent) {
0256 ret = fn(cont, dev, &ic->classdev);
0257 if (ret) {
0258 failed = ic;
0259 klist_iter_exit(&iter);
0260 goto fail;
0261 }
0262 }
0263 }
0264 return 0;
0265
0266 fail:
0267 if (!undo)
0268 return ret;
0269
0270
0271 klist_for_each_entry(ic, &cont->containers, node, &iter) {
0272 if (ic == failed) {
0273 klist_iter_exit(&iter);
0274 break;
0275 }
0276 if (dev == ic->classdev.parent)
0277 undo(cont, dev, &ic->classdev);
0278 }
0279 return ret;
0280 }
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296 int
0297 attribute_container_device_trigger_safe(struct device *dev,
0298 int (*fn)(struct attribute_container *,
0299 struct device *,
0300 struct device *),
0301 int (*undo)(struct attribute_container *,
0302 struct device *,
0303 struct device *))
0304 {
0305 struct attribute_container *cont, *failed = NULL;
0306 int ret = 0;
0307
0308 mutex_lock(&attribute_container_mutex);
0309
0310 list_for_each_entry(cont, &attribute_container_list, node) {
0311
0312 if (!cont->match(cont, dev))
0313 continue;
0314
0315 ret = do_attribute_container_device_trigger_safe(dev, cont,
0316 fn, undo);
0317 if (ret) {
0318 failed = cont;
0319 break;
0320 }
0321 }
0322
0323 if (ret && !WARN_ON(!undo)) {
0324 list_for_each_entry(cont, &attribute_container_list, node) {
0325
0326 if (failed == cont)
0327 break;
0328
0329 if (!cont->match(cont, dev))
0330 continue;
0331
0332 do_attribute_container_device_trigger_safe(dev, cont,
0333 undo, NULL);
0334 }
0335 }
0336
0337 mutex_unlock(&attribute_container_mutex);
0338 return ret;
0339
0340 }
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352 void
0353 attribute_container_device_trigger(struct device *dev,
0354 int (*fn)(struct attribute_container *,
0355 struct device *,
0356 struct device *))
0357 {
0358 struct attribute_container *cont;
0359
0360 mutex_lock(&attribute_container_mutex);
0361 list_for_each_entry(cont, &attribute_container_list, node) {
0362 struct internal_container *ic;
0363 struct klist_iter iter;
0364
0365 if (!cont->match(cont, dev))
0366 continue;
0367
0368 if (attribute_container_no_classdevs(cont)) {
0369 fn(cont, dev, NULL);
0370 continue;
0371 }
0372
0373 klist_for_each_entry(ic, &cont->containers, node, &iter) {
0374 if (dev == ic->classdev.parent)
0375 fn(cont, dev, &ic->classdev);
0376 }
0377 }
0378 mutex_unlock(&attribute_container_mutex);
0379 }
0380
0381
0382
0383
0384
0385
0386
0387
0388
0389
0390
0391
0392
0393 void
0394 attribute_container_trigger(struct device *dev,
0395 int (*fn)(struct attribute_container *,
0396 struct device *))
0397 {
0398 struct attribute_container *cont;
0399
0400 mutex_lock(&attribute_container_mutex);
0401 list_for_each_entry(cont, &attribute_container_list, node) {
0402 if (cont->match(cont, dev))
0403 fn(cont, dev);
0404 }
0405 mutex_unlock(&attribute_container_mutex);
0406 }
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416 int
0417 attribute_container_add_attrs(struct device *classdev)
0418 {
0419 struct attribute_container *cont =
0420 attribute_container_classdev_to_container(classdev);
0421 struct device_attribute **attrs = cont->attrs;
0422 int i, error;
0423
0424 BUG_ON(attrs && cont->grp);
0425
0426 if (!attrs && !cont->grp)
0427 return 0;
0428
0429 if (cont->grp)
0430 return sysfs_create_group(&classdev->kobj, cont->grp);
0431
0432 for (i = 0; attrs[i]; i++) {
0433 sysfs_attr_init(&attrs[i]->attr);
0434 error = device_create_file(classdev, attrs[i]);
0435 if (error)
0436 return error;
0437 }
0438
0439 return 0;
0440 }
0441
0442
0443
0444
0445
0446
0447
0448
0449
0450
0451 int
0452 attribute_container_add_class_device(struct device *classdev)
0453 {
0454 int error = device_add(classdev);
0455
0456 if (error)
0457 return error;
0458 return attribute_container_add_attrs(classdev);
0459 }
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470
0471 int
0472 attribute_container_add_class_device_adapter(struct attribute_container *cont,
0473 struct device *dev,
0474 struct device *classdev)
0475 {
0476 return attribute_container_add_class_device(classdev);
0477 }
0478
0479
0480
0481
0482
0483
0484
0485 void
0486 attribute_container_remove_attrs(struct device *classdev)
0487 {
0488 struct attribute_container *cont =
0489 attribute_container_classdev_to_container(classdev);
0490 struct device_attribute **attrs = cont->attrs;
0491 int i;
0492
0493 if (!attrs && !cont->grp)
0494 return;
0495
0496 if (cont->grp) {
0497 sysfs_remove_group(&classdev->kobj, cont->grp);
0498 return ;
0499 }
0500
0501 for (i = 0; attrs[i]; i++)
0502 device_remove_file(classdev, attrs[i]);
0503 }
0504
0505
0506
0507
0508
0509
0510
0511
0512
0513 void
0514 attribute_container_class_device_del(struct device *classdev)
0515 {
0516 attribute_container_remove_attrs(classdev);
0517 device_del(classdev);
0518 }
0519
0520
0521
0522
0523
0524
0525
0526
0527
0528
0529 struct device *
0530 attribute_container_find_class_device(struct attribute_container *cont,
0531 struct device *dev)
0532 {
0533 struct device *cdev = NULL;
0534 struct internal_container *ic;
0535 struct klist_iter iter;
0536
0537 klist_for_each_entry(ic, &cont->containers, node, &iter) {
0538 if (ic->classdev.parent == dev) {
0539 cdev = &ic->classdev;
0540
0541 klist_iter_exit(&iter);
0542 break;
0543 }
0544 }
0545
0546 return cdev;
0547 }
0548 EXPORT_SYMBOL_GPL(attribute_container_find_class_device);