aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/css.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/cio/css.c')
-rw-r--r--drivers/s390/cio/css.c198
1 files changed, 164 insertions, 34 deletions
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index c3df2cd009a4..3b45bbe6cce0 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -51,6 +51,62 @@ for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *data)
51 return ret; 51 return ret;
52} 52}
53 53
54struct cb_data {
55 void *data;
56 struct idset *set;
57 int (*fn_known_sch)(struct subchannel *, void *);
58 int (*fn_unknown_sch)(struct subchannel_id, void *);
59};
60
61static int call_fn_known_sch(struct device *dev, void *data)
62{
63 struct subchannel *sch = to_subchannel(dev);
64 struct cb_data *cb = data;
65 int rc = 0;
66
67 idset_sch_del(cb->set, sch->schid);
68 if (cb->fn_known_sch)
69 rc = cb->fn_known_sch(sch, cb->data);
70 return rc;
71}
72
73static int call_fn_unknown_sch(struct subchannel_id schid, void *data)
74{
75 struct cb_data *cb = data;
76 int rc = 0;
77
78 if (idset_sch_contains(cb->set, schid))
79 rc = cb->fn_unknown_sch(schid, cb->data);
80 return rc;
81}
82
83int for_each_subchannel_staged(int (*fn_known)(struct subchannel *, void *),
84 int (*fn_unknown)(struct subchannel_id,
85 void *), void *data)
86{
87 struct cb_data cb;
88 int rc;
89
90 cb.set = idset_sch_new();
91 if (!cb.set)
92 return -ENOMEM;
93 idset_fill(cb.set);
94 cb.data = data;
95 cb.fn_known_sch = fn_known;
96 cb.fn_unknown_sch = fn_unknown;
97 /* Process registered subchannels. */
98 rc = bus_for_each_dev(&css_bus_type, NULL, &cb, call_fn_known_sch);
99 if (rc)
100 goto out;
101 /* Process unregistered subchannels. */
102 if (fn_unknown)
103 rc = for_each_subchannel(call_fn_unknown_sch, &cb);
104out:
105 idset_free(cb.set);
106
107 return rc;
108}
109
54static struct subchannel * 110static struct subchannel *
55css_alloc_subchannel(struct subchannel_id schid) 111css_alloc_subchannel(struct subchannel_id schid)
56{ 112{
@@ -77,7 +133,7 @@ css_alloc_subchannel(struct subchannel_id schid)
77 * This is fine even on 64bit since the subchannel is always located 133 * This is fine even on 64bit since the subchannel is always located
78 * under 2G. 134 * under 2G.
79 */ 135 */
80 sch->schib.pmcw.intparm = (__u32)(unsigned long)sch; 136 sch->schib.pmcw.intparm = (u32)(addr_t)sch;
81 ret = cio_modify(sch); 137 ret = cio_modify(sch);
82 if (ret) { 138 if (ret) {
83 kfree(sch->lock); 139 kfree(sch->lock);
@@ -237,11 +293,25 @@ get_subchannel_by_schid(struct subchannel_id schid)
237 return dev ? to_subchannel(dev) : NULL; 293 return dev ? to_subchannel(dev) : NULL;
238} 294}
239 295
296/**
297 * css_sch_is_valid() - check if a subchannel is valid
298 * @schib: subchannel information block for the subchannel
299 */
300int css_sch_is_valid(struct schib *schib)
301{
302 if ((schib->pmcw.st == SUBCHANNEL_TYPE_IO) && !schib->pmcw.dnv)
303 return 0;
304 return 1;
305}
306EXPORT_SYMBOL_GPL(css_sch_is_valid);
307
240static int css_get_subchannel_status(struct subchannel *sch) 308static int css_get_subchannel_status(struct subchannel *sch)
241{ 309{
242 struct schib schib; 310 struct schib schib;
243 311
244 if (stsch(sch->schid, &schib) || !schib.pmcw.dnv) 312 if (stsch(sch->schid, &schib))
313 return CIO_GONE;
314 if (!css_sch_is_valid(&schib))
245 return CIO_GONE; 315 return CIO_GONE;
246 if (sch->schib.pmcw.dnv && (schib.pmcw.dev != sch->schib.pmcw.dev)) 316 if (sch->schib.pmcw.dnv && (schib.pmcw.dev != sch->schib.pmcw.dev))
247 return CIO_REVALIDATE; 317 return CIO_REVALIDATE;
@@ -293,7 +363,7 @@ static int css_evaluate_known_subchannel(struct subchannel *sch, int slow)
293 action = UNREGISTER; 363 action = UNREGISTER;
294 if (sch->driver && sch->driver->notify) { 364 if (sch->driver && sch->driver->notify) {
295 spin_unlock_irqrestore(sch->lock, flags); 365 spin_unlock_irqrestore(sch->lock, flags);
296 ret = sch->driver->notify(&sch->dev, event); 366 ret = sch->driver->notify(sch, event);
297 spin_lock_irqsave(sch->lock, flags); 367 spin_lock_irqsave(sch->lock, flags);
298 if (ret) 368 if (ret)
299 action = NONE; 369 action = NONE;
@@ -349,7 +419,7 @@ static int css_evaluate_new_subchannel(struct subchannel_id schid, int slow)
349 /* Will be done on the slow path. */ 419 /* Will be done on the slow path. */
350 return -EAGAIN; 420 return -EAGAIN;
351 } 421 }
352 if (stsch_err(schid, &schib) || !schib.pmcw.dnv) { 422 if (stsch_err(schid, &schib) || !css_sch_is_valid(&schib)) {
353 /* Unusable - ignore. */ 423 /* Unusable - ignore. */
354 return 0; 424 return 0;
355 } 425 }
@@ -388,20 +458,56 @@ static int __init slow_subchannel_init(void)
388 return 0; 458 return 0;
389} 459}
390 460
391static void css_slow_path_func(struct work_struct *unused) 461static int slow_eval_known_fn(struct subchannel *sch, void *data)
392{ 462{
393 struct subchannel_id schid; 463 int eval;
464 int rc;
394 465
395 CIO_TRACE_EVENT(4, "slowpath");
396 spin_lock_irq(&slow_subchannel_lock); 466 spin_lock_irq(&slow_subchannel_lock);
397 init_subchannel_id(&schid); 467 eval = idset_sch_contains(slow_subchannel_set, sch->schid);
398 while (idset_sch_get_first(slow_subchannel_set, &schid)) { 468 idset_sch_del(slow_subchannel_set, sch->schid);
399 idset_sch_del(slow_subchannel_set, schid); 469 spin_unlock_irq(&slow_subchannel_lock);
400 spin_unlock_irq(&slow_subchannel_lock); 470 if (eval) {
401 css_evaluate_subchannel(schid, 1); 471 rc = css_evaluate_known_subchannel(sch, 1);
402 spin_lock_irq(&slow_subchannel_lock); 472 if (rc == -EAGAIN)
473 css_schedule_eval(sch->schid);
403 } 474 }
475 return 0;
476}
477
478static int slow_eval_unknown_fn(struct subchannel_id schid, void *data)
479{
480 int eval;
481 int rc = 0;
482
483 spin_lock_irq(&slow_subchannel_lock);
484 eval = idset_sch_contains(slow_subchannel_set, schid);
485 idset_sch_del(slow_subchannel_set, schid);
404 spin_unlock_irq(&slow_subchannel_lock); 486 spin_unlock_irq(&slow_subchannel_lock);
487 if (eval) {
488 rc = css_evaluate_new_subchannel(schid, 1);
489 switch (rc) {
490 case -EAGAIN:
491 css_schedule_eval(schid);
492 rc = 0;
493 break;
494 case -ENXIO:
495 case -ENOMEM:
496 case -EIO:
497 /* These should abort looping */
498 break;
499 default:
500 rc = 0;
501 }
502 }
503 return rc;
504}
505
506static void css_slow_path_func(struct work_struct *unused)
507{
508 CIO_TRACE_EVENT(4, "slowpath");
509 for_each_subchannel_staged(slow_eval_known_fn, slow_eval_unknown_fn,
510 NULL);
405} 511}
406 512
407static DECLARE_WORK(slow_path_work, css_slow_path_func); 513static DECLARE_WORK(slow_path_work, css_slow_path_func);
@@ -430,7 +536,6 @@ void css_schedule_eval_all(void)
430/* Reprobe subchannel if unregistered. */ 536/* Reprobe subchannel if unregistered. */
431static int reprobe_subchannel(struct subchannel_id schid, void *data) 537static int reprobe_subchannel(struct subchannel_id schid, void *data)
432{ 538{
433 struct subchannel *sch;
434 int ret; 539 int ret;
435 540
436 CIO_MSG_EVENT(6, "cio: reprobe 0.%x.%04x\n", 541 CIO_MSG_EVENT(6, "cio: reprobe 0.%x.%04x\n",
@@ -438,13 +543,6 @@ static int reprobe_subchannel(struct subchannel_id schid, void *data)
438 if (need_reprobe) 543 if (need_reprobe)
439 return -EAGAIN; 544 return -EAGAIN;
440 545
441 sch = get_subchannel_by_schid(schid);
442 if (sch) {
443 /* Already known. */
444 put_device(&sch->dev);
445 return 0;
446 }
447
448 ret = css_probe_device(schid); 546 ret = css_probe_device(schid);
449 switch (ret) { 547 switch (ret) {
450 case 0: 548 case 0:
@@ -472,7 +570,7 @@ static void reprobe_all(struct work_struct *unused)
472 /* Make sure initial subchannel scan is done. */ 570 /* Make sure initial subchannel scan is done. */
473 wait_event(ccw_device_init_wq, 571 wait_event(ccw_device_init_wq,
474 atomic_read(&ccw_device_init_count) == 0); 572 atomic_read(&ccw_device_init_count) == 0);
475 ret = for_each_subchannel(reprobe_subchannel, NULL); 573 ret = for_each_subchannel_staged(NULL, reprobe_subchannel, NULL);
476 574
477 CIO_MSG_EVENT(2, "reprobe done (rc=%d, need_reprobe=%d)\n", ret, 575 CIO_MSG_EVENT(2, "reprobe done (rc=%d, need_reprobe=%d)\n", ret,
478 need_reprobe); 576 need_reprobe);
@@ -787,8 +885,8 @@ int sch_is_pseudo_sch(struct subchannel *sch)
787static int 885static int
788css_bus_match (struct device *dev, struct device_driver *drv) 886css_bus_match (struct device *dev, struct device_driver *drv)
789{ 887{
790 struct subchannel *sch = container_of (dev, struct subchannel, dev); 888 struct subchannel *sch = to_subchannel(dev);
791 struct css_driver *driver = container_of (drv, struct css_driver, drv); 889 struct css_driver *driver = to_cssdriver(drv);
792 890
793 if (sch->st == driver->subchannel_type) 891 if (sch->st == driver->subchannel_type)
794 return 1; 892 return 1;
@@ -796,32 +894,36 @@ css_bus_match (struct device *dev, struct device_driver *drv)
796 return 0; 894 return 0;
797} 895}
798 896
799static int 897static int css_probe(struct device *dev)
800css_probe (struct device *dev)
801{ 898{
802 struct subchannel *sch; 899 struct subchannel *sch;
900 int ret;
803 901
804 sch = to_subchannel(dev); 902 sch = to_subchannel(dev);
805 sch->driver = container_of (dev->driver, struct css_driver, drv); 903 sch->driver = to_cssdriver(dev->driver);
806 return (sch->driver->probe ? sch->driver->probe(sch) : 0); 904 ret = sch->driver->probe ? sch->driver->probe(sch) : 0;
905 if (ret)
906 sch->driver = NULL;
907 return ret;
807} 908}
808 909
809static int 910static int css_remove(struct device *dev)
810css_remove (struct device *dev)
811{ 911{
812 struct subchannel *sch; 912 struct subchannel *sch;
913 int ret;
813 914
814 sch = to_subchannel(dev); 915 sch = to_subchannel(dev);
815 return (sch->driver->remove ? sch->driver->remove(sch) : 0); 916 ret = sch->driver->remove ? sch->driver->remove(sch) : 0;
917 sch->driver = NULL;
918 return ret;
816} 919}
817 920
818static void 921static void css_shutdown(struct device *dev)
819css_shutdown (struct device *dev)
820{ 922{
821 struct subchannel *sch; 923 struct subchannel *sch;
822 924
823 sch = to_subchannel(dev); 925 sch = to_subchannel(dev);
824 if (sch->driver->shutdown) 926 if (sch->driver && sch->driver->shutdown)
825 sch->driver->shutdown(sch); 927 sch->driver->shutdown(sch);
826} 928}
827 929
@@ -833,6 +935,34 @@ struct bus_type css_bus_type = {
833 .shutdown = css_shutdown, 935 .shutdown = css_shutdown,
834}; 936};
835 937
938/**
939 * css_driver_register - register a css driver
940 * @cdrv: css driver to register
941 *
942 * This is mainly a wrapper around driver_register that sets name
943 * and bus_type in the embedded struct device_driver correctly.
944 */
945int css_driver_register(struct css_driver *cdrv)
946{
947 cdrv->drv.name = cdrv->name;
948 cdrv->drv.bus = &css_bus_type;
949 cdrv->drv.owner = cdrv->owner;
950 return driver_register(&cdrv->drv);
951}
952EXPORT_SYMBOL_GPL(css_driver_register);
953
954/**
955 * css_driver_unregister - unregister a css driver
956 * @cdrv: css driver to unregister
957 *
958 * This is a wrapper around driver_unregister.
959 */
960void css_driver_unregister(struct css_driver *cdrv)
961{
962 driver_unregister(&cdrv->drv);
963}
964EXPORT_SYMBOL_GPL(css_driver_unregister);
965
836subsys_initcall(init_channel_subsystem); 966subsys_initcall(init_channel_subsystem);
837 967
838MODULE_LICENSE("GPL"); 968MODULE_LICENSE("GPL");