|
@@ -467,6 +467,7 @@ static struct timer_list etr_timer;
|
|
|
|
|
|
static void etr_timeout(unsigned long dummy);
|
|
static void etr_timeout(unsigned long dummy);
|
|
static void etr_work_fn(struct work_struct *work);
|
|
static void etr_work_fn(struct work_struct *work);
|
|
|
|
+static DEFINE_MUTEX(etr_work_mutex);
|
|
static DECLARE_WORK(etr_work, etr_work_fn);
|
|
static DECLARE_WORK(etr_work, etr_work_fn);
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -976,6 +977,9 @@ static void etr_work_fn(struct work_struct *work)
|
|
struct etr_aib aib;
|
|
struct etr_aib aib;
|
|
int sync_port;
|
|
int sync_port;
|
|
|
|
|
|
|
|
+ /* prevent multiple execution. */
|
|
|
|
+ mutex_lock(&etr_work_mutex);
|
|
|
|
+
|
|
/* Create working copy of etr_eacr. */
|
|
/* Create working copy of etr_eacr. */
|
|
eacr = etr_eacr;
|
|
eacr = etr_eacr;
|
|
|
|
|
|
@@ -991,7 +995,7 @@ static void etr_work_fn(struct work_struct *work)
|
|
del_timer_sync(&etr_timer);
|
|
del_timer_sync(&etr_timer);
|
|
etr_update_eacr(eacr);
|
|
etr_update_eacr(eacr);
|
|
clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
|
|
clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
|
|
- return;
|
|
|
|
|
|
+ goto out_unlock;
|
|
}
|
|
}
|
|
|
|
|
|
/* Store aib to get the current ETR status word. */
|
|
/* Store aib to get the current ETR status word. */
|
|
@@ -1078,7 +1082,7 @@ static void etr_work_fn(struct work_struct *work)
|
|
eacr.es || sync_port < 0) {
|
|
eacr.es || sync_port < 0) {
|
|
etr_update_eacr(eacr);
|
|
etr_update_eacr(eacr);
|
|
etr_set_tolec_timeout(now);
|
|
etr_set_tolec_timeout(now);
|
|
- return;
|
|
|
|
|
|
+ goto out_unlock;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -1106,6 +1110,8 @@ static void etr_work_fn(struct work_struct *work)
|
|
etr_set_sync_timeout();
|
|
etr_set_sync_timeout();
|
|
} else
|
|
} else
|
|
etr_set_tolec_timeout(now);
|
|
etr_set_tolec_timeout(now);
|
|
|
|
+out_unlock:
|
|
|
|
+ mutex_unlock(&etr_work_mutex);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -1394,6 +1400,7 @@ static struct stp_sstpi stp_info;
|
|
static void *stp_page;
|
|
static void *stp_page;
|
|
|
|
|
|
static void stp_work_fn(struct work_struct *work);
|
|
static void stp_work_fn(struct work_struct *work);
|
|
|
|
+static DEFINE_MUTEX(stp_work_mutex);
|
|
static DECLARE_WORK(stp_work, stp_work_fn);
|
|
static DECLARE_WORK(stp_work, stp_work_fn);
|
|
|
|
|
|
static int __init early_parse_stp(char *p)
|
|
static int __init early_parse_stp(char *p)
|
|
@@ -1542,24 +1549,30 @@ static void stp_work_fn(struct work_struct *work)
|
|
struct clock_sync_data stp_sync;
|
|
struct clock_sync_data stp_sync;
|
|
int rc;
|
|
int rc;
|
|
|
|
|
|
|
|
+ /* prevent multiple execution. */
|
|
|
|
+ mutex_lock(&stp_work_mutex);
|
|
|
|
+
|
|
if (!stp_online) {
|
|
if (!stp_online) {
|
|
chsc_sstpc(stp_page, STP_OP_CTRL, 0x0000);
|
|
chsc_sstpc(stp_page, STP_OP_CTRL, 0x0000);
|
|
- return;
|
|
|
|
|
|
+ goto out_unlock;
|
|
}
|
|
}
|
|
|
|
|
|
rc = chsc_sstpc(stp_page, STP_OP_CTRL, 0xb0e0);
|
|
rc = chsc_sstpc(stp_page, STP_OP_CTRL, 0xb0e0);
|
|
if (rc)
|
|
if (rc)
|
|
- return;
|
|
|
|
|
|
+ goto out_unlock;
|
|
|
|
|
|
rc = chsc_sstpi(stp_page, &stp_info, sizeof(struct stp_sstpi));
|
|
rc = chsc_sstpi(stp_page, &stp_info, sizeof(struct stp_sstpi));
|
|
if (rc || stp_info.c == 0)
|
|
if (rc || stp_info.c == 0)
|
|
- return;
|
|
|
|
|
|
+ goto out_unlock;
|
|
|
|
|
|
memset(&stp_sync, 0, sizeof(stp_sync));
|
|
memset(&stp_sync, 0, sizeof(stp_sync));
|
|
get_online_cpus();
|
|
get_online_cpus();
|
|
atomic_set(&stp_sync.cpus, num_online_cpus() - 1);
|
|
atomic_set(&stp_sync.cpus, num_online_cpus() - 1);
|
|
stop_machine(stp_sync_clock, &stp_sync, &cpu_online_map);
|
|
stop_machine(stp_sync_clock, &stp_sync, &cpu_online_map);
|
|
put_online_cpus();
|
|
put_online_cpus();
|
|
|
|
+
|
|
|
|
+out_unlock:
|
|
|
|
+ mutex_unlock(&stp_work_mutex);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|