diff options
Diffstat (limited to 'net/core/pktgen.c')
-rw-r--r-- | net/core/pktgen.c | 49 |
1 files changed, 28 insertions, 21 deletions
diff --git a/net/core/pktgen.c b/net/core/pktgen.c index bede00b54038..3045dd133071 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c | |||
@@ -131,6 +131,7 @@ | |||
131 | #include <linux/ioport.h> | 131 | #include <linux/ioport.h> |
132 | #include <linux/interrupt.h> | 132 | #include <linux/interrupt.h> |
133 | #include <linux/capability.h> | 133 | #include <linux/capability.h> |
134 | #include <linux/hrtimer.h> | ||
134 | #include <linux/freezer.h> | 135 | #include <linux/freezer.h> |
135 | #include <linux/delay.h> | 136 | #include <linux/delay.h> |
136 | #include <linux/timer.h> | 137 | #include <linux/timer.h> |
@@ -2086,33 +2087,40 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev) | |||
2086 | pkt_dev->nflows = 0; | 2087 | pkt_dev->nflows = 0; |
2087 | } | 2088 | } |
2088 | 2089 | ||
2089 | static inline s64 delta_ns(ktime_t a, ktime_t b) | ||
2090 | { | ||
2091 | return ktime_to_ns(ktime_sub(a, b)); | ||
2092 | } | ||
2093 | 2090 | ||
2094 | static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until) | 2091 | static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until) |
2095 | { | 2092 | { |
2096 | ktime_t start, now; | 2093 | ktime_t start; |
2097 | s64 dt; | 2094 | s32 remaining; |
2095 | struct hrtimer_sleeper t; | ||
2098 | 2096 | ||
2099 | start = now = ktime_now(); | 2097 | hrtimer_init_on_stack(&t.timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); |
2098 | hrtimer_set_expires(&t.timer, spin_until); | ||
2099 | |||
2100 | remaining = ktime_to_us(hrtimer_expires_remaining(&t.timer)); | ||
2101 | if (remaining <= 0) | ||
2102 | return; | ||
2100 | 2103 | ||
2101 | while ((dt = delta_ns(spin_until, now)) > 0) { | 2104 | start = ktime_now(); |
2102 | /* TODO: optimize sleeping behavior */ | 2105 | if (remaining < 100) |
2103 | if (dt > TICK_NSEC) | 2106 | udelay(remaining); /* really small just spin */ |
2104 | schedule_timeout_interruptible(1); | 2107 | else { |
2105 | else if (dt > 100*NSEC_PER_USEC) { | 2108 | /* see do_nanosleep */ |
2106 | if (!pkt_dev->running) | 2109 | hrtimer_init_sleeper(&t, current); |
2107 | return; | 2110 | do { |
2108 | if (need_resched()) | 2111 | set_current_state(TASK_INTERRUPTIBLE); |
2112 | hrtimer_start_expires(&t.timer, HRTIMER_MODE_ABS); | ||
2113 | if (!hrtimer_active(&t.timer)) | ||
2114 | t.task = NULL; | ||
2115 | |||
2116 | if (likely(t.task)) | ||
2109 | schedule(); | 2117 | schedule(); |
2110 | } | ||
2111 | 2118 | ||
2112 | now = ktime_now(); | 2119 | hrtimer_cancel(&t.timer); |
2120 | } while (t.task && pkt_dev->running && !signal_pending(current)); | ||
2121 | __set_current_state(TASK_RUNNING); | ||
2113 | } | 2122 | } |
2114 | 2123 | pkt_dev->idle_acc += ktime_to_ns(ktime_sub(ktime_now(), start)); | |
2115 | pkt_dev->idle_acc += ktime_to_ns(ktime_sub(now, start)); | ||
2116 | } | 2124 | } |
2117 | 2125 | ||
2118 | static inline void set_pkt_overhead(struct pktgen_dev *pkt_dev) | 2126 | static inline void set_pkt_overhead(struct pktgen_dev *pkt_dev) |
@@ -3360,8 +3368,7 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev) | |||
3360 | int ret; | 3368 | int ret; |
3361 | 3369 | ||
3362 | if (pkt_dev->delay) { | 3370 | if (pkt_dev->delay) { |
3363 | if (ktime_lt(ktime_now(), pkt_dev->next_tx)) | 3371 | spin(pkt_dev, pkt_dev->next_tx); |
3364 | spin(pkt_dev, pkt_dev->next_tx); | ||
3365 | 3372 | ||
3366 | /* This is max DELAY, this has special meaning of | 3373 | /* This is max DELAY, this has special meaning of |
3367 | * "never transmit" | 3374 | * "never transmit" |