summaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio
diff options
context:
space:
mode:
authorVineeth Vijayan <vneethv@linux.ibm.com>2021-09-10 13:45:24 +0200
committerHeiko Carstens <hca@linux.ibm.com>2021-09-27 13:54:38 +0200
commit172da89ed0eaf9d9348f5decb86ad04c624b39d1 (patch)
treeeb2b3cdb8e1890633dde2a354b97b236b80178cd /drivers/s390/cio
parent5816b3e6577eaa676ceb00a848f0fd65fe2adc29 (diff)
downloadlinux-172da89ed0eaf9d9348f5decb86ad04c624b39d1.tar.bz2
s390/cio: avoid excessive path-verification requests
Currently when removing a device from cio_ignore list, we trigger a path-verification for all the subchannels available in the system. This could lead to path-verification requests on subchannels with an online device, which could cause unwanted delay. Instead of all the subchannels, trigger the path-verifications to those without an online device. Reported-by: Julian Wiedmann <jwi@linux.ibm.com> Fixes: 2297791c92d0 ("s390/cio: dont unregister subchannel from child-drivers") Signed-off-by: Vineeth Vijayan <vneethv@linux.ibm.com> Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com> Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Diffstat (limited to 'drivers/s390/cio')
-rw-r--r--drivers/s390/cio/blacklist.c8
-rw-r--r--drivers/s390/cio/css.c40
-rw-r--r--drivers/s390/cio/css.h10
3 files changed, 45 insertions, 13 deletions
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c
index f3c656975e05..93695d535380 100644
--- a/drivers/s390/cio/blacklist.c
+++ b/drivers/s390/cio/blacklist.c
@@ -262,10 +262,12 @@ static int blacklist_parse_proc_parameters(char *buf)
if (strcmp("free", parm) == 0) {
rc = blacklist_parse_parameters(buf, free, 0);
- /* There could be subchannels without proper devices connected.
- * evaluate all the entries
+ /*
+ * Evaluate the subchannels without an online device. This way,
+ * no path-verification will be triggered on those subchannels
+ * and it avoids unnecessary delays.
*/
- css_schedule_eval_all();
+ css_schedule_eval_cond(CSS_EVAL_NOT_ONLINE, 0);
} else if (strcmp("add", parm) == 0)
rc = blacklist_parse_parameters(buf, add, 0);
else if (strcmp("purge", parm) == 0)
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 3377097e65de..44461928aab8 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -788,27 +788,49 @@ static int __unset_registered(struct device *dev, void *data)
return 0;
}
-void css_schedule_eval_all_unreg(unsigned long delay)
+static int __unset_online(struct device *dev, void *data)
+{
+ struct idset *set = data;
+ struct subchannel *sch = to_subchannel(dev);
+ struct ccw_device *cdev = sch_get_cdev(sch);
+
+ if (cdev && cdev->online)
+ idset_sch_del(set, sch->schid);
+
+ return 0;
+}
+
+void css_schedule_eval_cond(enum css_eval_cond cond, unsigned long delay)
{
unsigned long flags;
- struct idset *unreg_set;
+ struct idset *set;
/* Find unregistered subchannels. */
- unreg_set = idset_sch_new();
- if (!unreg_set) {
+ set = idset_sch_new();
+ if (!set) {
/* Fallback. */
css_schedule_eval_all();
return;
}
- idset_fill(unreg_set);
- bus_for_each_dev(&css_bus_type, NULL, unreg_set, __unset_registered);
+ idset_fill(set);
+ switch (cond) {
+ case CSS_EVAL_UNREG:
+ bus_for_each_dev(&css_bus_type, NULL, set, __unset_registered);
+ break;
+ case CSS_EVAL_NOT_ONLINE:
+ bus_for_each_dev(&css_bus_type, NULL, set, __unset_online);
+ break;
+ default:
+ break;
+ }
+
/* Apply to slow_subchannel_set. */
spin_lock_irqsave(&slow_subchannel_lock, flags);
- idset_add_set(slow_subchannel_set, unreg_set);
+ idset_add_set(slow_subchannel_set, set);
atomic_set(&css_eval_scheduled, 1);
queue_delayed_work(cio_work_q, &slow_path_work, delay);
spin_unlock_irqrestore(&slow_subchannel_lock, flags);
- idset_free(unreg_set);
+ idset_free(set);
}
void css_wait_for_slow_path(void)
@@ -820,7 +842,7 @@ void css_wait_for_slow_path(void)
void css_schedule_reprobe(void)
{
/* Schedule with a delay to allow merging of subsequent calls. */
- css_schedule_eval_all_unreg(1 * HZ);
+ css_schedule_eval_cond(CSS_EVAL_UNREG, 1 * HZ);
}
EXPORT_SYMBOL_GPL(css_schedule_reprobe);
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h
index c98522cbe276..ede0b905bc6f 100644
--- a/drivers/s390/cio/css.h
+++ b/drivers/s390/cio/css.h
@@ -34,6 +34,14 @@
#define SNID_STATE3_MULTI_PATH 1
#define SNID_STATE3_SINGLE_PATH 0
+/*
+ * Conditions used to specify which subchannels need evaluation
+ */
+enum css_eval_cond {
+ CSS_EVAL_UNREG, /* unregistered subchannels */
+ CSS_EVAL_NOT_ONLINE /* sch without an online-device */
+};
+
struct path_state {
__u8 state1 : 2; /* path state value 1 */
__u8 state2 : 2; /* path state value 2 */
@@ -136,7 +144,7 @@ static inline struct channel_subsystem *css_by_id(u8 cssid)
/* Helper functions to build lists for the slow path. */
void css_schedule_eval(struct subchannel_id schid);
void css_schedule_eval_all(void);
-void css_schedule_eval_all_unreg(unsigned long delay);
+void css_schedule_eval_cond(enum css_eval_cond, unsigned long delay);
int css_complete_work(void);
int sch_is_pseudo_sch(struct subchannel *);