aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/ccwgroup.c
diff options
context:
space:
mode:
authorSebastian Ott <sebott@linux.vnet.ibm.com>2011-10-30 10:16:53 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2011-10-30 10:16:43 -0400
commitdad572e370138539ea45be9b53d168568e562565 (patch)
tree2dee3af88a9baf5417429b095e95e5267b3aee7a /drivers/s390/cio/ccwgroup.c
parentdbdf1afcaaabe83dea15a3cb9b9013e73ae3b1ad (diff)
[S390] ccwgroup: cleanup
Fix coding style, remove forward declerations, simplify code. Also remove a superfluous get_device/put_device pair in ccwgroup_create_from_string. Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/cio/ccwgroup.c')
-rw-r--r--drivers/s390/cio/ccwgroup.c299
1 files changed, 119 insertions, 180 deletions
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index cda9bd6e48e..4f1989d27b1 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -29,31 +29,20 @@
29 29
30/* a device matches a driver if all its slave devices match the same 30/* a device matches a driver if all its slave devices match the same
31 * entry of the driver */ 31 * entry of the driver */
32static int 32static int ccwgroup_bus_match(struct device *dev, struct device_driver * drv)
33ccwgroup_bus_match (struct device * dev, struct device_driver * drv)
34{ 33{
35 struct ccwgroup_device *gdev; 34 struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
36 struct ccwgroup_driver *gdrv; 35 struct ccwgroup_driver *gdrv = to_ccwgroupdrv(drv);
37
38 gdev = to_ccwgroupdev(dev);
39 gdrv = to_ccwgroupdrv(drv);
40 36
41 if (gdev->creator_id == gdrv->driver_id) 37 if (gdev->creator_id == gdrv->driver_id)
42 return 1; 38 return 1;
43 39
44 return 0; 40 return 0;
45} 41}
46static int
47ccwgroup_uevent (struct device *dev, struct kobj_uevent_env *env)
48{
49 /* TODO */
50 return 0;
51}
52 42
53static struct bus_type ccwgroup_bus_type; 43static struct bus_type ccwgroup_bus_type;
54 44
55static void 45static void __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev)
56__ccwgroup_remove_symlinks(struct ccwgroup_device *gdev)
57{ 46{
58 int i; 47 int i;
59 char str[8]; 48 char str[8];
@@ -63,7 +52,6 @@ __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev)
63 sysfs_remove_link(&gdev->dev.kobj, str); 52 sysfs_remove_link(&gdev->dev.kobj, str);
64 sysfs_remove_link(&gdev->cdev[i]->dev.kobj, "group_device"); 53 sysfs_remove_link(&gdev->cdev[i]->dev.kobj, "group_device");
65 } 54 }
66
67} 55}
68 56
69/* 57/*
@@ -87,12 +75,87 @@ static void __ccwgroup_remove_cdev_refs(struct ccwgroup_device *gdev)
87 } 75 }
88} 76}
89 77
78static int ccwgroup_set_online(struct ccwgroup_device *gdev)
79{
80 struct ccwgroup_driver *gdrv = to_ccwgroupdrv(gdev->dev.driver);
81 int ret = 0;
82
83 if (atomic_cmpxchg(&gdev->onoff, 0, 1) != 0)
84 return -EAGAIN;
85 if (gdev->state == CCWGROUP_ONLINE)
86 goto out;
87 if (gdrv->set_online)
88 ret = gdrv->set_online(gdev);
89 if (ret)
90 goto out;
91
92 gdev->state = CCWGROUP_ONLINE;
93out:
94 atomic_set(&gdev->onoff, 0);
95 return ret;
96}
97
98static int ccwgroup_set_offline(struct ccwgroup_device *gdev)
99{
100 struct ccwgroup_driver *gdrv = to_ccwgroupdrv(gdev->dev.driver);
101 int ret = 0;
102
103 if (atomic_cmpxchg(&gdev->onoff, 0, 1) != 0)
104 return -EAGAIN;
105 if (gdev->state == CCWGROUP_OFFLINE)
106 goto out;
107 if (gdrv->set_offline)
108 ret = gdrv->set_offline(gdev);
109 if (ret)
110 goto out;
111
112 gdev->state = CCWGROUP_OFFLINE;
113out:
114 atomic_set(&gdev->onoff, 0);
115 return ret;
116}
117
90static ssize_t ccwgroup_online_store(struct device *dev, 118static ssize_t ccwgroup_online_store(struct device *dev,
91 struct device_attribute *attr, 119 struct device_attribute *attr,
92 const char *buf, size_t count); 120 const char *buf, size_t count)
121{
122 struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
123 struct ccwgroup_driver *gdrv = to_ccwgroupdrv(dev->driver);
124 unsigned long value;
125 int ret;
126
127 if (!dev->driver)
128 return -EINVAL;
129 if (!try_module_get(gdrv->driver.owner))
130 return -EINVAL;
131
132 ret = strict_strtoul(buf, 0, &value);
133 if (ret)
134 goto out;
135
136 if (value == 1)
137 ret = ccwgroup_set_online(gdev);
138 else if (value == 0)
139 ret = ccwgroup_set_offline(gdev);
140 else
141 ret = -EINVAL;
142out:
143 module_put(gdrv->driver.owner);
144 return (ret == 0) ? count : ret;
145}
146
93static ssize_t ccwgroup_online_show(struct device *dev, 147static ssize_t ccwgroup_online_show(struct device *dev,
94 struct device_attribute *attr, 148 struct device_attribute *attr,
95 char *buf); 149 char *buf)
150{
151 struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
152 int online;
153
154 online = (gdev->state == CCWGROUP_ONLINE) ? 1 : 0;
155
156 return scnprintf(buf, PAGE_SIZE, "%d\n", online);
157}
158
96/* 159/*
97 * Provide an 'ungroup' attribute so the user can remove group devices no 160 * Provide an 'ungroup' attribute so the user can remove group devices no
98 * longer needed or accidentially created. Saves memory :) 161 * longer needed or accidentially created. Saves memory :)
@@ -110,14 +173,13 @@ static void ccwgroup_ungroup_callback(struct device *dev)
110 mutex_unlock(&gdev->reg_mutex); 173 mutex_unlock(&gdev->reg_mutex);
111} 174}
112 175
113static ssize_t 176static ssize_t ccwgroup_ungroup_store(struct device *dev,
114ccwgroup_ungroup_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) 177 struct device_attribute *attr,
178 const char *buf, size_t count)
115{ 179{
116 struct ccwgroup_device *gdev; 180 struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
117 int rc; 181 int rc;
118 182
119 gdev = to_ccwgroupdev(dev);
120
121 /* Prevent concurrent online/offline processing and ungrouping. */ 183 /* Prevent concurrent online/offline processing and ungrouping. */
122 if (atomic_cmpxchg(&gdev->onoff, 0, 1) != 0) 184 if (atomic_cmpxchg(&gdev->onoff, 0, 1) != 0)
123 return -EAGAIN; 185 return -EAGAIN;
@@ -138,7 +200,6 @@ out:
138 } 200 }
139 return count; 201 return count;
140} 202}
141
142static DEVICE_ATTR(ungroup, 0200, NULL, ccwgroup_ungroup_store); 203static DEVICE_ATTR(ungroup, 0200, NULL, ccwgroup_ungroup_store);
143static DEVICE_ATTR(online, 0644, ccwgroup_online_show, ccwgroup_online_store); 204static DEVICE_ATTR(online, 0644, ccwgroup_online_show, ccwgroup_online_store);
144 205
@@ -155,21 +216,19 @@ static const struct attribute_group *ccwgroup_attr_groups[] = {
155 NULL, 216 NULL,
156}; 217};
157 218
158static void 219static void ccwgroup_release(struct device *dev)
159ccwgroup_release (struct device *dev)
160{ 220{
161 kfree(to_ccwgroupdev(dev)); 221 kfree(to_ccwgroupdev(dev));
162} 222}
163 223
164static int 224static int __ccwgroup_create_symlinks(struct ccwgroup_device *gdev)
165__ccwgroup_create_symlinks(struct ccwgroup_device *gdev)
166{ 225{
167 char str[8]; 226 char str[8];
168 int i, rc; 227 int i, rc;
169 228
170 for (i = 0; i < gdev->count; i++) { 229 for (i = 0; i < gdev->count; i++) {
171 rc = sysfs_create_link(&gdev->cdev[i]->dev.kobj, &gdev->dev.kobj, 230 rc = sysfs_create_link(&gdev->cdev[i]->dev.kobj,
172 "group_device"); 231 &gdev->dev.kobj, "group_device");
173 if (rc) { 232 if (rc) {
174 for (--i; i >= 0; i--) 233 for (--i; i >= 0; i--)
175 sysfs_remove_link(&gdev->cdev[i]->dev.kobj, 234 sysfs_remove_link(&gdev->cdev[i]->dev.kobj,
@@ -179,8 +238,8 @@ __ccwgroup_create_symlinks(struct ccwgroup_device *gdev)
179 } 238 }
180 for (i = 0; i < gdev->count; i++) { 239 for (i = 0; i < gdev->count; i++) {
181 sprintf(str, "cdev%d", i); 240 sprintf(str, "cdev%d", i);
182 rc = sysfs_create_link(&gdev->dev.kobj, &gdev->cdev[i]->dev.kobj, 241 rc = sysfs_create_link(&gdev->dev.kobj,
183 str); 242 &gdev->cdev[i]->dev.kobj, str);
184 if (rc) { 243 if (rc) {
185 for (--i; i >= 0; i--) { 244 for (--i; i >= 0; i--) {
186 sprintf(str, "cdev%d", i); 245 sprintf(str, "cdev%d", i);
@@ -317,14 +376,13 @@ int ccwgroup_create_from_string(struct device *root, unsigned int creator_id,
317 rc = device_add(&gdev->dev); 376 rc = device_add(&gdev->dev);
318 if (rc) 377 if (rc)
319 goto error; 378 goto error;
320 get_device(&gdev->dev);
321 rc = __ccwgroup_create_symlinks(gdev); 379 rc = __ccwgroup_create_symlinks(gdev);
322 if (!rc) { 380 if (rc) {
323 mutex_unlock(&gdev->reg_mutex); 381 device_del(&gdev->dev);
324 put_device(&gdev->dev); 382 goto error;
325 return 0;
326 } 383 }
327 device_unregister(&gdev->dev); 384 mutex_unlock(&gdev->reg_mutex);
385 return 0;
328error: 386error:
329 for (i = 0; i < num_devices; i++) 387 for (i = 0; i < num_devices; i++)
330 if (gdev->cdev[i]) { 388 if (gdev->cdev[i]) {
@@ -342,7 +400,15 @@ error:
342EXPORT_SYMBOL(ccwgroup_create_from_string); 400EXPORT_SYMBOL(ccwgroup_create_from_string);
343 401
344static int ccwgroup_notifier(struct notifier_block *nb, unsigned long action, 402static int ccwgroup_notifier(struct notifier_block *nb, unsigned long action,
345 void *data); 403 void *data)
404{
405 struct device *dev = data;
406
407 if (action == BUS_NOTIFY_UNBIND_DRIVER)
408 device_schedule_callback(dev, ccwgroup_ungroup_callback);
409
410 return NOTIFY_OK;
411}
346 412
347static struct notifier_block ccwgroup_nb = { 413static struct notifier_block ccwgroup_nb = {
348 .notifier_call = ccwgroup_notifier 414 .notifier_call = ccwgroup_notifier
@@ -374,128 +440,21 @@ module_exit(cleanup_ccwgroup);
374 440
375/************************** driver stuff ******************************/ 441/************************** driver stuff ******************************/
376 442
377static int 443static int ccwgroup_probe(struct device *dev)
378ccwgroup_set_online(struct ccwgroup_device *gdev)
379{
380 struct ccwgroup_driver *gdrv;
381 int ret;
382
383 if (atomic_cmpxchg(&gdev->onoff, 0, 1) != 0)
384 return -EAGAIN;
385 if (gdev->state == CCWGROUP_ONLINE) {
386 ret = 0;
387 goto out;
388 }
389 if (!gdev->dev.driver) {
390 ret = -EINVAL;
391 goto out;
392 }
393 gdrv = to_ccwgroupdrv (gdev->dev.driver);
394 if ((ret = gdrv->set_online ? gdrv->set_online(gdev) : 0))
395 goto out;
396
397 gdev->state = CCWGROUP_ONLINE;
398 out:
399 atomic_set(&gdev->onoff, 0);
400 return ret;
401}
402
403static int
404ccwgroup_set_offline(struct ccwgroup_device *gdev)
405{
406 struct ccwgroup_driver *gdrv;
407 int ret;
408
409 if (atomic_cmpxchg(&gdev->onoff, 0, 1) != 0)
410 return -EAGAIN;
411 if (gdev->state == CCWGROUP_OFFLINE) {
412 ret = 0;
413 goto out;
414 }
415 if (!gdev->dev.driver) {
416 ret = -EINVAL;
417 goto out;
418 }
419 gdrv = to_ccwgroupdrv (gdev->dev.driver);
420 if ((ret = gdrv->set_offline ? gdrv->set_offline(gdev) : 0))
421 goto out;
422
423 gdev->state = CCWGROUP_OFFLINE;
424 out:
425 atomic_set(&gdev->onoff, 0);
426 return ret;
427}
428
429static ssize_t
430ccwgroup_online_store (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
431{
432 struct ccwgroup_device *gdev;
433 struct ccwgroup_driver *gdrv;
434 unsigned long value;
435 int ret;
436
437 if (!dev->driver)
438 return -EINVAL;
439
440 gdev = to_ccwgroupdev(dev);
441 gdrv = to_ccwgroupdrv(dev->driver);
442
443 if (!try_module_get(gdrv->driver.owner))
444 return -EINVAL;
445
446 ret = strict_strtoul(buf, 0, &value);
447 if (ret)
448 goto out;
449
450 if (value == 1)
451 ret = ccwgroup_set_online(gdev);
452 else if (value == 0)
453 ret = ccwgroup_set_offline(gdev);
454 else
455 ret = -EINVAL;
456out:
457 module_put(gdrv->driver.owner);
458 return (ret == 0) ? count : ret;
459}
460
461static ssize_t
462ccwgroup_online_show (struct device *dev, struct device_attribute *attr, char *buf)
463{ 444{
464 int online; 445 struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
465 446 struct ccwgroup_driver *gdrv = to_ccwgroupdrv(dev->driver);
466 online = (to_ccwgroupdev(dev)->state == CCWGROUP_ONLINE);
467
468 return sprintf(buf, online ? "1\n" : "0\n");
469}
470
471static int
472ccwgroup_probe (struct device *dev)
473{
474 struct ccwgroup_device *gdev;
475 struct ccwgroup_driver *gdrv;
476
477 int ret;
478
479 gdev = to_ccwgroupdev(dev);
480 gdrv = to_ccwgroupdrv(dev->driver);
481
482 ret = gdrv->probe ? gdrv->probe(gdev) : -ENODEV;
483 447
484 return ret; 448 return gdrv->probe ? gdrv->probe(gdev) : -ENODEV;
485} 449}
486 450
487static int 451static int ccwgroup_remove(struct device *dev)
488ccwgroup_remove (struct device *dev)
489{ 452{
490 struct ccwgroup_device *gdev; 453 struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
491 struct ccwgroup_driver *gdrv; 454 struct ccwgroup_driver *gdrv = to_ccwgroupdrv(dev->driver);
492 455
493 if (!dev->driver) 456 if (!dev->driver)
494 return 0; 457 return 0;
495
496 gdev = to_ccwgroupdev(dev);
497 gdrv = to_ccwgroupdrv(dev->driver);
498
499 if (gdrv->remove) 458 if (gdrv->remove)
500 gdrv->remove(gdev); 459 gdrv->remove(gdev);
501 460
@@ -504,15 +463,11 @@ ccwgroup_remove (struct device *dev)
504 463
505static void ccwgroup_shutdown(struct device *dev) 464static void ccwgroup_shutdown(struct device *dev)
506{ 465{
507 struct ccwgroup_device *gdev; 466 struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
508 struct ccwgroup_driver *gdrv; 467 struct ccwgroup_driver *gdrv = to_ccwgroupdrv(dev->driver);
509 468
510 if (!dev->driver) 469 if (!dev->driver)
511 return; 470 return;
512
513 gdev = to_ccwgroupdev(dev);
514 gdrv = to_ccwgroupdrv(dev->driver);
515
516 if (gdrv->shutdown) 471 if (gdrv->shutdown)
517 gdrv->shutdown(gdev); 472 gdrv->shutdown(gdev);
518} 473}
@@ -588,26 +543,12 @@ static const struct dev_pm_ops ccwgroup_pm_ops = {
588static struct bus_type ccwgroup_bus_type = { 543static struct bus_type ccwgroup_bus_type = {
589 .name = "ccwgroup", 544 .name = "ccwgroup",
590 .match = ccwgroup_bus_match, 545 .match = ccwgroup_bus_match,
591 .uevent = ccwgroup_uevent,
592 .probe = ccwgroup_probe, 546 .probe = ccwgroup_probe,
593 .remove = ccwgroup_remove, 547 .remove = ccwgroup_remove,
594 .shutdown = ccwgroup_shutdown, 548 .shutdown = ccwgroup_shutdown,
595 .pm = &ccwgroup_pm_ops, 549 .pm = &ccwgroup_pm_ops,
596}; 550};
597 551
598
599static int ccwgroup_notifier(struct notifier_block *nb, unsigned long action,
600 void *data)
601{
602 struct device *dev = data;
603
604 if (action == BUS_NOTIFY_UNBIND_DRIVER)
605 device_schedule_callback(dev, ccwgroup_ungroup_callback);
606
607 return NOTIFY_OK;
608}
609
610
611/** 552/**
612 * ccwgroup_driver_register() - register a ccw group driver 553 * ccwgroup_driver_register() - register a ccw group driver
613 * @cdriver: driver to be registered 554 * @cdriver: driver to be registered
@@ -621,9 +562,9 @@ int ccwgroup_driver_register(struct ccwgroup_driver *cdriver)
621 562
622 return driver_register(&cdriver->driver); 563 return driver_register(&cdriver->driver);
623} 564}
565EXPORT_SYMBOL(ccwgroup_driver_register);
624 566
625static int 567static int __ccwgroup_match_all(struct device *dev, void *data)
626__ccwgroup_match_all(struct device *dev, void *data)
627{ 568{
628 return 1; 569 return 1;
629} 570}
@@ -654,6 +595,7 @@ void ccwgroup_driver_unregister(struct ccwgroup_driver *cdriver)
654 put_driver(&cdriver->driver); 595 put_driver(&cdriver->driver);
655 driver_unregister(&cdriver->driver); 596 driver_unregister(&cdriver->driver);
656} 597}
598EXPORT_SYMBOL(ccwgroup_driver_unregister);
657 599
658/** 600/**
659 * ccwgroup_probe_ccwdev() - probe function for slave devices 601 * ccwgroup_probe_ccwdev() - probe function for slave devices
@@ -668,6 +610,7 @@ int ccwgroup_probe_ccwdev(struct ccw_device *cdev)
668{ 610{
669 return 0; 611 return 0;
670} 612}
613EXPORT_SYMBOL(ccwgroup_probe_ccwdev);
671 614
672/** 615/**
673 * ccwgroup_remove_ccwdev() - remove function for slave devices 616 * ccwgroup_remove_ccwdev() - remove function for slave devices
@@ -704,9 +647,5 @@ void ccwgroup_remove_ccwdev(struct ccw_device *cdev)
704 /* Release ccwgroup device reference for local processing. */ 647 /* Release ccwgroup device reference for local processing. */
705 put_device(&gdev->dev); 648 put_device(&gdev->dev);
706} 649}
707
708MODULE_LICENSE("GPL");
709EXPORT_SYMBOL(ccwgroup_driver_register);
710EXPORT_SYMBOL(ccwgroup_driver_unregister);
711EXPORT_SYMBOL(ccwgroup_probe_ccwdev);
712EXPORT_SYMBOL(ccwgroup_remove_ccwdev); 650EXPORT_SYMBOL(ccwgroup_remove_ccwdev);
651MODULE_LICENSE("GPL");