aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2009-03-26 10:24:21 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2009-03-26 10:24:18 -0400
commit8283cb43ab3e92a039d3486a0f6253df95a5fa55 (patch)
treeeb378ed7f08c22ed7d56163bde3285040a2fa3b6 /arch/s390
parent56e25e9777bf15365293e27a3256eb9214a11edf (diff)
[S390] clock sync mode flags
The clock sync mode flag CLOCK_SYNC_STP is not cleared when stp is set offline. In this case the get_sync_clock() function returns -EACCESS and the dasd driver will block all i/o until stp is enabled again. In addition get_sync_clock can return -EACCESS if the clock is not in sync instead of -EAGAIN. Rework the stp/etr online handling to fix these problems. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/kernel/time.c71
1 files changed, 44 insertions, 27 deletions
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index fc468cae4460..f72d41068dc2 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -331,6 +331,7 @@ static unsigned long long adjust_time(unsigned long long old,
331} 331}
332 332
333static DEFINE_PER_CPU(atomic_t, clock_sync_word); 333static DEFINE_PER_CPU(atomic_t, clock_sync_word);
334static DEFINE_MUTEX(clock_sync_mutex);
334static unsigned long clock_sync_flags; 335static unsigned long clock_sync_flags;
335 336
336#define CLOCK_SYNC_HAS_ETR 0 337#define CLOCK_SYNC_HAS_ETR 0
@@ -394,6 +395,20 @@ static void enable_sync_clock(void)
394 atomic_set_mask(0x80000000, sw_ptr); 395 atomic_set_mask(0x80000000, sw_ptr);
395} 396}
396 397
398/*
399 * Function to check if the clock is in sync.
400 */
401static inline int check_sync_clock(void)
402{
403 atomic_t *sw_ptr;
404 int rc;
405
406 sw_ptr = &get_cpu_var(clock_sync_word);
407 rc = (atomic_read(sw_ptr) & 0x80000000U) != 0;
408 put_cpu_var(clock_sync_sync);
409 return rc;
410}
411
397/* Single threaded workqueue used for etr and stp sync events */ 412/* Single threaded workqueue used for etr and stp sync events */
398static struct workqueue_struct *time_sync_wq; 413static struct workqueue_struct *time_sync_wq;
399 414
@@ -485,6 +500,8 @@ static void etr_reset(void)
485 if (etr_setr(&etr_eacr) == 0) { 500 if (etr_setr(&etr_eacr) == 0) {
486 etr_tolec = get_clock(); 501 etr_tolec = get_clock();
487 set_bit(CLOCK_SYNC_HAS_ETR, &clock_sync_flags); 502 set_bit(CLOCK_SYNC_HAS_ETR, &clock_sync_flags);
503 if (etr_port0_online && etr_port1_online)
504 set_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
488 } else if (etr_port0_online || etr_port1_online) { 505 } else if (etr_port0_online || etr_port1_online) {
489 pr_warning("The real or virtual hardware system does " 506 pr_warning("The real or virtual hardware system does "
490 "not provide an ETR interface\n"); 507 "not provide an ETR interface\n");
@@ -533,8 +550,7 @@ void etr_switch_to_local(void)
533{ 550{
534 if (!etr_eacr.sl) 551 if (!etr_eacr.sl)
535 return; 552 return;
536 if (test_bit(CLOCK_SYNC_ETR, &clock_sync_flags)) 553 disable_sync_clock(NULL);
537 disable_sync_clock(NULL);
538 set_bit(ETR_EVENT_SWITCH_LOCAL, &etr_events); 554 set_bit(ETR_EVENT_SWITCH_LOCAL, &etr_events);
539 queue_work(time_sync_wq, &etr_work); 555 queue_work(time_sync_wq, &etr_work);
540} 556}
@@ -549,8 +565,7 @@ void etr_sync_check(void)
549{ 565{
550 if (!etr_eacr.es) 566 if (!etr_eacr.es)
551 return; 567 return;
552 if (test_bit(CLOCK_SYNC_ETR, &clock_sync_flags)) 568 disable_sync_clock(NULL);
553 disable_sync_clock(NULL);
554 set_bit(ETR_EVENT_SYNC_CHECK, &etr_events); 569 set_bit(ETR_EVENT_SYNC_CHECK, &etr_events);
555 queue_work(time_sync_wq, &etr_work); 570 queue_work(time_sync_wq, &etr_work);
556} 571}
@@ -914,7 +929,7 @@ static struct etr_eacr etr_handle_update(struct etr_aib *aib,
914 * Do not try to get the alternate port aib if the clock 929 * Do not try to get the alternate port aib if the clock
915 * is not in sync yet. 930 * is not in sync yet.
916 */ 931 */
917 if (!test_bit(CLOCK_SYNC_STP, &clock_sync_flags) && !eacr.es) 932 if (!check_sync_clock())
918 return eacr; 933 return eacr;
919 934
920 /* 935 /*
@@ -997,7 +1012,6 @@ static void etr_work_fn(struct work_struct *work)
997 on_each_cpu(disable_sync_clock, NULL, 1); 1012 on_each_cpu(disable_sync_clock, NULL, 1);
998 del_timer_sync(&etr_timer); 1013 del_timer_sync(&etr_timer);
999 etr_update_eacr(eacr); 1014 etr_update_eacr(eacr);
1000 clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
1001 goto out_unlock; 1015 goto out_unlock;
1002 } 1016 }
1003 1017
@@ -1071,18 +1085,13 @@ static void etr_work_fn(struct work_struct *work)
1071 /* Both ports not usable. */ 1085 /* Both ports not usable. */
1072 eacr.es = eacr.sl = 0; 1086 eacr.es = eacr.sl = 0;
1073 sync_port = -1; 1087 sync_port = -1;
1074 clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
1075 } 1088 }
1076 1089
1077 if (!test_bit(CLOCK_SYNC_ETR, &clock_sync_flags))
1078 eacr.es = 0;
1079
1080 /* 1090 /*
1081 * If the clock is in sync just update the eacr and return. 1091 * If the clock is in sync just update the eacr and return.
1082 * If there is no valid sync port wait for a port update. 1092 * If there is no valid sync port wait for a port update.
1083 */ 1093 */
1084 if (test_bit(CLOCK_SYNC_STP, &clock_sync_flags) || 1094 if (check_sync_clock() || sync_port < 0) {
1085 eacr.es || sync_port < 0) {
1086 etr_update_eacr(eacr); 1095 etr_update_eacr(eacr);
1087 etr_set_tolec_timeout(now); 1096 etr_set_tolec_timeout(now);
1088 goto out_unlock; 1097 goto out_unlock;
@@ -1103,13 +1112,11 @@ static void etr_work_fn(struct work_struct *work)
1103 * and set up a timer to try again after 0.5 seconds 1112 * and set up a timer to try again after 0.5 seconds
1104 */ 1113 */
1105 etr_update_eacr(eacr); 1114 etr_update_eacr(eacr);
1106 set_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
1107 if (now < etr_tolec + (1600000 << 12) || 1115 if (now < etr_tolec + (1600000 << 12) ||
1108 etr_sync_clock_stop(&aib, sync_port) != 0) { 1116 etr_sync_clock_stop(&aib, sync_port) != 0) {
1109 /* Sync failed. Try again in 1/2 second. */ 1117 /* Sync failed. Try again in 1/2 second. */
1110 eacr.es = 0; 1118 eacr.es = 0;
1111 etr_update_eacr(eacr); 1119 etr_update_eacr(eacr);
1112 clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
1113 etr_set_sync_timeout(); 1120 etr_set_sync_timeout();
1114 } else 1121 } else
1115 etr_set_tolec_timeout(now); 1122 etr_set_tolec_timeout(now);
@@ -1191,19 +1198,30 @@ static ssize_t etr_online_store(struct sys_device *dev,
1191 return -EINVAL; 1198 return -EINVAL;
1192 if (!test_bit(CLOCK_SYNC_HAS_ETR, &clock_sync_flags)) 1199 if (!test_bit(CLOCK_SYNC_HAS_ETR, &clock_sync_flags))
1193 return -EOPNOTSUPP; 1200 return -EOPNOTSUPP;
1201 mutex_lock(&clock_sync_mutex);
1194 if (dev == &etr_port0_dev) { 1202 if (dev == &etr_port0_dev) {
1195 if (etr_port0_online == value) 1203 if (etr_port0_online == value)
1196 return count; /* Nothing to do. */ 1204 goto out; /* Nothing to do. */
1197 etr_port0_online = value; 1205 etr_port0_online = value;
1206 if (etr_port0_online && etr_port1_online)
1207 set_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
1208 else
1209 clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
1198 set_bit(ETR_EVENT_PORT0_CHANGE, &etr_events); 1210 set_bit(ETR_EVENT_PORT0_CHANGE, &etr_events);
1199 queue_work(time_sync_wq, &etr_work); 1211 queue_work(time_sync_wq, &etr_work);
1200 } else { 1212 } else {
1201 if (etr_port1_online == value) 1213 if (etr_port1_online == value)
1202 return count; /* Nothing to do. */ 1214 goto out; /* Nothing to do. */
1203 etr_port1_online = value; 1215 etr_port1_online = value;
1216 if (etr_port0_online && etr_port1_online)
1217 set_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
1218 else
1219 clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
1204 set_bit(ETR_EVENT_PORT1_CHANGE, &etr_events); 1220 set_bit(ETR_EVENT_PORT1_CHANGE, &etr_events);
1205 queue_work(time_sync_wq, &etr_work); 1221 queue_work(time_sync_wq, &etr_work);
1206 } 1222 }
1223out:
1224 mutex_unlock(&clock_sync_mutex);
1207 return count; 1225 return count;
1208} 1226}
1209 1227
@@ -1471,8 +1489,6 @@ static void stp_timing_alert(struct stp_irq_parm *intparm)
1471 */ 1489 */
1472void stp_sync_check(void) 1490void stp_sync_check(void)
1473{ 1491{
1474 if (!test_bit(CLOCK_SYNC_STP, &clock_sync_flags))
1475 return;
1476 disable_sync_clock(NULL); 1492 disable_sync_clock(NULL);
1477 queue_work(time_sync_wq, &stp_work); 1493 queue_work(time_sync_wq, &stp_work);
1478} 1494}
@@ -1485,8 +1501,6 @@ void stp_sync_check(void)
1485 */ 1501 */
1486void stp_island_check(void) 1502void stp_island_check(void)
1487{ 1503{
1488 if (!test_bit(CLOCK_SYNC_STP, &clock_sync_flags))
1489 return;
1490 disable_sync_clock(NULL); 1504 disable_sync_clock(NULL);
1491 queue_work(time_sync_wq, &stp_work); 1505 queue_work(time_sync_wq, &stp_work);
1492} 1506}
@@ -1513,10 +1527,6 @@ static int stp_sync_clock(void *data)
1513 1527
1514 enable_sync_clock(); 1528 enable_sync_clock();
1515 1529
1516 set_bit(CLOCK_SYNC_STP, &clock_sync_flags);
1517 if (test_and_clear_bit(CLOCK_SYNC_ETR, &clock_sync_flags))
1518 queue_work(time_sync_wq, &etr_work);
1519
1520 rc = 0; 1530 rc = 0;
1521 if (stp_info.todoff[0] || stp_info.todoff[1] || 1531 if (stp_info.todoff[0] || stp_info.todoff[1] ||
1522 stp_info.todoff[2] || stp_info.todoff[3] || 1532 stp_info.todoff[2] || stp_info.todoff[3] ||
@@ -1535,9 +1545,6 @@ static int stp_sync_clock(void *data)
1535 if (rc) { 1545 if (rc) {
1536 disable_sync_clock(NULL); 1546 disable_sync_clock(NULL);
1537 stp_sync->in_sync = -EAGAIN; 1547 stp_sync->in_sync = -EAGAIN;
1538 clear_bit(CLOCK_SYNC_STP, &clock_sync_flags);
1539 if (etr_port0_online || etr_port1_online)
1540 queue_work(time_sync_wq, &etr_work);
1541 } else 1548 } else
1542 stp_sync->in_sync = 1; 1549 stp_sync->in_sync = 1;
1543 xchg(&first, 0); 1550 xchg(&first, 0);
@@ -1569,6 +1576,10 @@ static void stp_work_fn(struct work_struct *work)
1569 if (rc || stp_info.c == 0) 1576 if (rc || stp_info.c == 0)
1570 goto out_unlock; 1577 goto out_unlock;
1571 1578
1579 /* Skip synchronization if the clock is already in sync. */
1580 if (check_sync_clock())
1581 goto out_unlock;
1582
1572 memset(&stp_sync, 0, sizeof(stp_sync)); 1583 memset(&stp_sync, 0, sizeof(stp_sync));
1573 get_online_cpus(); 1584 get_online_cpus();
1574 atomic_set(&stp_sync.cpus, num_online_cpus() - 1); 1585 atomic_set(&stp_sync.cpus, num_online_cpus() - 1);
@@ -1684,8 +1695,14 @@ static ssize_t stp_online_store(struct sysdev_class *class,
1684 return -EINVAL; 1695 return -EINVAL;
1685 if (!test_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags)) 1696 if (!test_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags))
1686 return -EOPNOTSUPP; 1697 return -EOPNOTSUPP;
1698 mutex_lock(&clock_sync_mutex);
1687 stp_online = value; 1699 stp_online = value;
1700 if (stp_online)
1701 set_bit(CLOCK_SYNC_STP, &clock_sync_flags);
1702 else
1703 clear_bit(CLOCK_SYNC_STP, &clock_sync_flags);
1688 queue_work(time_sync_wq, &stp_work); 1704 queue_work(time_sync_wq, &stp_work);
1705 mutex_unlock(&clock_sync_mutex);
1689 return count; 1706 return count;
1690} 1707}
1691 1708