aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2008-12-25 07:38:38 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2008-12-25 07:38:56 -0500
commit0b3016b781abeabc502042c942cbc611e31250c7 (patch)
treea4aead52e4ea230a529e2c9d0899f5fe32f41408 /arch/s390/kernel
parent750887dedc088d28198b170bcae83695247797d1 (diff)
[S390] serialize stp/etr work
The work function dispatched with schedule_work() can be run twice on different cpus because run_workqueue clears the WORK_STRUCT_PENDING bit and then executes the function. Another cpu can call schedule_work() again and run the work function a second time before the first call is completed. This patch serialized the etr and stp work function with a mutex. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/kernel')
-rw-r--r--arch/s390/kernel/time.c23
1 files changed, 18 insertions, 5 deletions
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index 6e09bc285ba0..496528561248 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -467,6 +467,7 @@ static struct timer_list etr_timer;
467 467
468static void etr_timeout(unsigned long dummy); 468static void etr_timeout(unsigned long dummy);
469static void etr_work_fn(struct work_struct *work); 469static void etr_work_fn(struct work_struct *work);
470static DEFINE_MUTEX(etr_work_mutex);
470static DECLARE_WORK(etr_work, etr_work_fn); 471static DECLARE_WORK(etr_work, etr_work_fn);
471 472
472/* 473/*
@@ -976,6 +977,9 @@ static void etr_work_fn(struct work_struct *work)
976 struct etr_aib aib; 977 struct etr_aib aib;
977 int sync_port; 978 int sync_port;
978 979
980 /* prevent multiple execution. */
981 mutex_lock(&etr_work_mutex);
982
979 /* Create working copy of etr_eacr. */ 983 /* Create working copy of etr_eacr. */
980 eacr = etr_eacr; 984 eacr = etr_eacr;
981 985
@@ -991,7 +995,7 @@ static void etr_work_fn(struct work_struct *work)
991 del_timer_sync(&etr_timer); 995 del_timer_sync(&etr_timer);
992 etr_update_eacr(eacr); 996 etr_update_eacr(eacr);
993 clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags); 997 clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
994 return; 998 goto out_unlock;
995 } 999 }
996 1000
997 /* Store aib to get the current ETR status word. */ 1001 /* Store aib to get the current ETR status word. */
@@ -1078,7 +1082,7 @@ static void etr_work_fn(struct work_struct *work)
1078 eacr.es || sync_port < 0) { 1082 eacr.es || sync_port < 0) {
1079 etr_update_eacr(eacr); 1083 etr_update_eacr(eacr);
1080 etr_set_tolec_timeout(now); 1084 etr_set_tolec_timeout(now);
1081 return; 1085 goto out_unlock;
1082 } 1086 }
1083 1087
1084 /* 1088 /*
@@ -1106,6 +1110,8 @@ static void etr_work_fn(struct work_struct *work)
1106 etr_set_sync_timeout(); 1110 etr_set_sync_timeout();
1107 } else 1111 } else
1108 etr_set_tolec_timeout(now); 1112 etr_set_tolec_timeout(now);
1113out_unlock:
1114 mutex_unlock(&etr_work_mutex);
1109} 1115}
1110 1116
1111/* 1117/*
@@ -1394,6 +1400,7 @@ static struct stp_sstpi stp_info;
1394static void *stp_page; 1400static void *stp_page;
1395 1401
1396static void stp_work_fn(struct work_struct *work); 1402static void stp_work_fn(struct work_struct *work);
1403static DEFINE_MUTEX(stp_work_mutex);
1397static DECLARE_WORK(stp_work, stp_work_fn); 1404static DECLARE_WORK(stp_work, stp_work_fn);
1398 1405
1399static int __init early_parse_stp(char *p) 1406static int __init early_parse_stp(char *p)
@@ -1542,24 +1549,30 @@ static void stp_work_fn(struct work_struct *work)
1542 struct clock_sync_data stp_sync; 1549 struct clock_sync_data stp_sync;
1543 int rc; 1550 int rc;
1544 1551
1552 /* prevent multiple execution. */
1553 mutex_lock(&stp_work_mutex);
1554
1545 if (!stp_online) { 1555 if (!stp_online) {
1546 chsc_sstpc(stp_page, STP_OP_CTRL, 0x0000); 1556 chsc_sstpc(stp_page, STP_OP_CTRL, 0x0000);
1547 return; 1557 goto out_unlock;
1548 } 1558 }
1549 1559
1550 rc = chsc_sstpc(stp_page, STP_OP_CTRL, 0xb0e0); 1560 rc = chsc_sstpc(stp_page, STP_OP_CTRL, 0xb0e0);
1551 if (rc) 1561 if (rc)
1552 return; 1562 goto out_unlock;
1553 1563
1554 rc = chsc_sstpi(stp_page, &stp_info, sizeof(struct stp_sstpi)); 1564 rc = chsc_sstpi(stp_page, &stp_info, sizeof(struct stp_sstpi));
1555 if (rc || stp_info.c == 0) 1565 if (rc || stp_info.c == 0)
1556 return; 1566 goto out_unlock;
1557 1567
1558 memset(&stp_sync, 0, sizeof(stp_sync)); 1568 memset(&stp_sync, 0, sizeof(stp_sync));
1559 get_online_cpus(); 1569 get_online_cpus();
1560 atomic_set(&stp_sync.cpus, num_online_cpus() - 1); 1570 atomic_set(&stp_sync.cpus, num_online_cpus() - 1);
1561 stop_machine(stp_sync_clock, &stp_sync, &cpu_online_map); 1571 stop_machine(stp_sync_clock, &stp_sync, &cpu_online_map);
1562 put_online_cpus(); 1572 put_online_cpus();
1573
1574out_unlock:
1575 mutex_unlock(&stp_work_mutex);
1563} 1576}
1564 1577
1565/* 1578/*