|
@@ -38,7 +38,6 @@ enum cfg_task_t {
|
|
|
/* Map for pending configure tasks. */
|
|
|
static enum cfg_task_t chp_cfg_task[__MAX_CSSID + 1][__MAX_CHPID + 1];
|
|
|
static DEFINE_SPINLOCK(cfg_lock);
|
|
|
-static int cfg_busy;
|
|
|
|
|
|
/* Map for channel-path status. */
|
|
|
static struct sclp_chp_info chp_info;
|
|
@@ -666,6 +665,20 @@ static void cfg_set_task(struct chp_id chpid, enum cfg_task_t cfg)
|
|
|
chp_cfg_task[chpid.cssid][chpid.id] = cfg;
|
|
|
}
|
|
|
|
|
|
+/* Fetch the first configure task. Set chpid accordingly. */
|
|
|
+static enum cfg_task_t chp_cfg_fetch_task(struct chp_id *chpid)
|
|
|
+{
|
|
|
+ enum cfg_task_t t = cfg_none;
|
|
|
+
|
|
|
+ chp_id_for_each(chpid) {
|
|
|
+ t = cfg_get_task(*chpid);
|
|
|
+ if (t != cfg_none)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return t;
|
|
|
+}
|
|
|
+
|
|
|
/* Perform one configure/deconfigure request. Reschedule work function until
|
|
|
* last request. */
|
|
|
static void cfg_func(struct work_struct *work)
|
|
@@ -675,14 +688,7 @@ static void cfg_func(struct work_struct *work)
|
|
|
int rc;
|
|
|
|
|
|
spin_lock(&cfg_lock);
|
|
|
- t = cfg_none;
|
|
|
- chp_id_for_each(&chpid) {
|
|
|
- t = cfg_get_task(chpid);
|
|
|
- if (t != cfg_none) {
|
|
|
- cfg_set_task(chpid, cfg_none);
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
+ t = chp_cfg_fetch_task(&chpid);
|
|
|
spin_unlock(&cfg_lock);
|
|
|
|
|
|
switch (t) {
|
|
@@ -709,12 +715,13 @@ static void cfg_func(struct work_struct *work)
|
|
|
case cfg_none:
|
|
|
/* Get updated information after last change. */
|
|
|
info_update();
|
|
|
- spin_lock(&cfg_lock);
|
|
|
- cfg_busy = 0;
|
|
|
- spin_unlock(&cfg_lock);
|
|
|
wake_up_interruptible(&cfg_wait_queue);
|
|
|
return;
|
|
|
}
|
|
|
+ spin_lock(&cfg_lock);
|
|
|
+ if (t == cfg_get_task(chpid))
|
|
|
+ cfg_set_task(chpid, cfg_none);
|
|
|
+ spin_unlock(&cfg_lock);
|
|
|
schedule_work(&cfg_work);
|
|
|
}
|
|
|
|
|
@@ -731,7 +738,6 @@ void chp_cfg_schedule(struct chp_id chpid, int configure)
|
|
|
configure);
|
|
|
spin_lock(&cfg_lock);
|
|
|
cfg_set_task(chpid, configure ? cfg_configure : cfg_deconfigure);
|
|
|
- cfg_busy = 1;
|
|
|
spin_unlock(&cfg_lock);
|
|
|
schedule_work(&cfg_work);
|
|
|
}
|
|
@@ -752,9 +758,21 @@ void chp_cfg_cancel_deconfigure(struct chp_id chpid)
|
|
|
spin_unlock(&cfg_lock);
|
|
|
}
|
|
|
|
|
|
+static bool cfg_idle(void)
|
|
|
+{
|
|
|
+ struct chp_id chpid;
|
|
|
+ enum cfg_task_t t;
|
|
|
+
|
|
|
+ spin_lock(&cfg_lock);
|
|
|
+ t = chp_cfg_fetch_task(&chpid);
|
|
|
+ spin_unlock(&cfg_lock);
|
|
|
+
|
|
|
+ return t == cfg_none;
|
|
|
+}
|
|
|
+
|
|
|
static int cfg_wait_idle(void)
|
|
|
{
|
|
|
- if (wait_event_interruptible(cfg_wait_queue, !cfg_busy))
|
|
|
+ if (wait_event_interruptible(cfg_wait_queue, cfg_idle()))
|
|
|
return -ERESTARTSYS;
|
|
|
return 0;
|
|
|
}
|