aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorFelix Beck <felix.beck@de.ibm.com>2008-07-14 03:59:08 -0400
committerHeiko Carstens <heiko.carstens@de.ibm.com>2008-07-14 04:02:13 -0400
commitfe1372306149d8c8a68d43765e7caea2377003b6 (patch)
tree4ac98196a8efb5df9583623100406b9c34ee19f9 /drivers/s390
parentad211790c040fae3459e9c4c8cbd681ae126d2b8 (diff)
[S390] ap: Use high-resolution timer for polling
The ap poll mechanism is converted to use a high-resolution timer for polling. This allows more specific polling. With this a new sysfs attribute is introduced to specify the polling rate in nanoseconds. Signed-off-by: Felix Beck <felix.beck@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/crypto/ap_bus.c63
1 files changed, 53 insertions, 10 deletions
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index a1ab3e3efd11..62b6b55230d0 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -34,13 +34,15 @@
34#include <linux/mutex.h> 34#include <linux/mutex.h>
35#include <asm/s390_rdev.h> 35#include <asm/s390_rdev.h>
36#include <asm/reset.h> 36#include <asm/reset.h>
37#include <linux/hrtimer.h>
38#include <linux/ktime.h>
37 39
38#include "ap_bus.h" 40#include "ap_bus.h"
39 41
40/* Some prototypes. */ 42/* Some prototypes. */
41static void ap_scan_bus(struct work_struct *); 43static void ap_scan_bus(struct work_struct *);
42static void ap_poll_all(unsigned long); 44static void ap_poll_all(unsigned long);
43static void ap_poll_timeout(unsigned long); 45static enum hrtimer_restart ap_poll_timeout(struct hrtimer *);
44static int ap_poll_thread_start(void); 46static int ap_poll_thread_start(void);
45static void ap_poll_thread_stop(void); 47static void ap_poll_thread_stop(void);
46static void ap_request_timeout(unsigned long); 48static void ap_request_timeout(unsigned long);
@@ -80,12 +82,15 @@ static DECLARE_WORK(ap_config_work, ap_scan_bus);
80/* 82/*
81 * Tasklet & timer for AP request polling. 83 * Tasklet & timer for AP request polling.
82 */ 84 */
83static struct timer_list ap_poll_timer = TIMER_INITIALIZER(ap_poll_timeout,0,0);
84static DECLARE_TASKLET(ap_tasklet, ap_poll_all, 0); 85static DECLARE_TASKLET(ap_tasklet, ap_poll_all, 0);
85static atomic_t ap_poll_requests = ATOMIC_INIT(0); 86static atomic_t ap_poll_requests = ATOMIC_INIT(0);
86static DECLARE_WAIT_QUEUE_HEAD(ap_poll_wait); 87static DECLARE_WAIT_QUEUE_HEAD(ap_poll_wait);
87static struct task_struct *ap_poll_kthread = NULL; 88static struct task_struct *ap_poll_kthread = NULL;
88static DEFINE_MUTEX(ap_poll_thread_mutex); 89static DEFINE_MUTEX(ap_poll_thread_mutex);
90static struct hrtimer ap_poll_timer;
91/* In LPAR poll with 4kHz frequency. Poll every 250000 nanoseconds.
92 * If z/VM change to 1500000 nanoseconds to adjust to z/VM polling.*/
93static unsigned long long poll_timeout = 250000;
89 94
90/** 95/**
91 * ap_intructions_available() - Test if AP instructions are available. 96 * ap_intructions_available() - Test if AP instructions are available.
@@ -636,11 +641,39 @@ static ssize_t ap_poll_thread_store(struct bus_type *bus,
636 641
637static BUS_ATTR(poll_thread, 0644, ap_poll_thread_show, ap_poll_thread_store); 642static BUS_ATTR(poll_thread, 0644, ap_poll_thread_show, ap_poll_thread_store);
638 643
644static ssize_t poll_timeout_show(struct bus_type *bus, char *buf)
645{
646 return snprintf(buf, PAGE_SIZE, "%llu\n", poll_timeout);
647}
648
649static ssize_t poll_timeout_store(struct bus_type *bus, const char *buf,
650 size_t count)
651{
652 unsigned long long time;
653 ktime_t hr_time;
654
655 /* 120 seconds = maximum poll interval */
656 if (sscanf(buf, "%llu\n", &time) != 1 || time < 1 || time > 120000000000)
657 return -EINVAL;
658 poll_timeout = time;
659 hr_time = ktime_set(0, poll_timeout);
660
661 if (!hrtimer_is_queued(&ap_poll_timer) ||
662 !hrtimer_forward(&ap_poll_timer, ap_poll_timer.expires, hr_time)) {
663 ap_poll_timer.expires = hr_time;
664 hrtimer_start(&ap_poll_timer, hr_time, HRTIMER_MODE_ABS);
665 }
666 return count;
667}
668
669static BUS_ATTR(poll_timeout, 0644, poll_timeout_show, poll_timeout_store);
670
639static struct bus_attribute *const ap_bus_attrs[] = { 671static struct bus_attribute *const ap_bus_attrs[] = {
640 &bus_attr_ap_domain, 672 &bus_attr_ap_domain,
641 &bus_attr_config_time, 673 &bus_attr_config_time,
642 &bus_attr_poll_thread, 674 &bus_attr_poll_thread,
643 NULL 675 &bus_attr_poll_timeout,
676 NULL,
644}; 677};
645 678
646/** 679/**
@@ -895,9 +928,10 @@ ap_config_timeout(unsigned long ptr)
895 */ 928 */
896static inline void ap_schedule_poll_timer(void) 929static inline void ap_schedule_poll_timer(void)
897{ 930{
898 if (timer_pending(&ap_poll_timer)) 931 if (hrtimer_is_queued(&ap_poll_timer))
899 return; 932 return;
900 mod_timer(&ap_poll_timer, jiffies + AP_POLL_TIME); 933 hrtimer_start(&ap_poll_timer, ktime_set(0, poll_timeout),
934 HRTIMER_MODE_ABS);
901} 935}
902 936
903/** 937/**
@@ -1115,13 +1149,14 @@ EXPORT_SYMBOL(ap_cancel_message);
1115 1149
1116/** 1150/**
1117 * ap_poll_timeout(): AP receive polling for finished AP requests. 1151 * ap_poll_timeout(): AP receive polling for finished AP requests.
1118 * @unused: Unused variable. 1152 * @unused: Unused pointer.
1119 * 1153 *
1120 * Schedules the AP tasklet. 1154 * Schedules the AP tasklet using a high resolution timer.
1121 */ 1155 */
1122static void ap_poll_timeout(unsigned long unused) 1156static enum hrtimer_restart ap_poll_timeout(struct hrtimer *unused)
1123{ 1157{
1124 tasklet_schedule(&ap_tasklet); 1158 tasklet_schedule(&ap_tasklet);
1159 return HRTIMER_NORESTART;
1125} 1160}
1126 1161
1127/** 1162/**
@@ -1344,6 +1379,14 @@ int __init ap_module_init(void)
1344 ap_config_timer.expires = jiffies + ap_config_time * HZ; 1379 ap_config_timer.expires = jiffies + ap_config_time * HZ;
1345 add_timer(&ap_config_timer); 1380 add_timer(&ap_config_timer);
1346 1381
1382 /* Setup the high resultion poll timer.
1383 * If we are running under z/VM adjust polling to z/VM polling rate.
1384 */
1385 if (MACHINE_IS_VM)
1386 poll_timeout = 1500000;
1387 hrtimer_init(&ap_poll_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
1388 ap_poll_timer.function = ap_poll_timeout;
1389
1347 /* Start the low priority AP bus poll thread. */ 1390 /* Start the low priority AP bus poll thread. */
1348 if (ap_thread_flag) { 1391 if (ap_thread_flag) {
1349 rc = ap_poll_thread_start(); 1392 rc = ap_poll_thread_start();
@@ -1355,7 +1398,7 @@ int __init ap_module_init(void)
1355 1398
1356out_work: 1399out_work:
1357 del_timer_sync(&ap_config_timer); 1400 del_timer_sync(&ap_config_timer);
1358 del_timer_sync(&ap_poll_timer); 1401 hrtimer_cancel(&ap_poll_timer);
1359 destroy_workqueue(ap_work_queue); 1402 destroy_workqueue(ap_work_queue);
1360out_root: 1403out_root:
1361 s390_root_dev_unregister(ap_root_device); 1404 s390_root_dev_unregister(ap_root_device);
@@ -1386,7 +1429,7 @@ void ap_module_exit(void)
1386 ap_reset_domain(); 1429 ap_reset_domain();
1387 ap_poll_thread_stop(); 1430 ap_poll_thread_stop();
1388 del_timer_sync(&ap_config_timer); 1431 del_timer_sync(&ap_config_timer);
1389 del_timer_sync(&ap_poll_timer); 1432 hrtimer_cancel(&ap_poll_timer);
1390 destroy_workqueue(ap_work_queue); 1433 destroy_workqueue(ap_work_queue);
1391 tasklet_kill(&ap_tasklet); 1434 tasklet_kill(&ap_tasklet);
1392 s390_root_dev_unregister(ap_root_device); 1435 s390_root_dev_unregister(ap_root_device);