aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorOliver Hartkopp <oliver@hartkopp.net>2008-04-15 22:29:14 -0400
committerDavid S. Miller <davem@davemloft.net>2008-04-15 22:29:14 -0400
commit73e87e02ec484ac459c4be262ab76960b89dc019 (patch)
tree6475f3ec73d1bc258d65da619cedef87a157f560 /net
parent85035568a96065de6fb29478707a3ad5f1fed169 (diff)
CAN: use hrtimers in can-bcm protocol
Make use of hrtimers to support high resolution capabilities, when provided by the system clocksource. The conversion to hrtimers additionally discovered and solved an unlikely race condition that has been reproduced under (unrealistic) massive receive load, which can only be produced on vcan software devices. [ Fix printf format warnings on 64-bit -DaveM ] Signed-off-by: Oliver Hartkopp <oliver@hartkopp.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/can/bcm.c251
1 files changed, 130 insertions, 121 deletions
diff --git a/net/can/bcm.c b/net/can/bcm.c
index e9f99b2c6bc9..74fd2d33aff4 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -43,6 +43,7 @@
43 43
44#include <linux/module.h> 44#include <linux/module.h>
45#include <linux/init.h> 45#include <linux/init.h>
46#include <linux/hrtimer.h>
46#include <linux/list.h> 47#include <linux/list.h>
47#include <linux/proc_fs.h> 48#include <linux/proc_fs.h>
48#include <linux/uio.h> 49#include <linux/uio.h>
@@ -66,7 +67,7 @@
66#define REGMASK(id) ((id & CAN_RTR_FLAG) | ((id & CAN_EFF_FLAG) ? \ 67#define REGMASK(id) ((id & CAN_RTR_FLAG) | ((id & CAN_EFF_FLAG) ? \
67 (CAN_EFF_MASK | CAN_EFF_FLAG) : CAN_SFF_MASK)) 68 (CAN_EFF_MASK | CAN_EFF_FLAG) : CAN_SFF_MASK))
68 69
69#define CAN_BCM_VERSION CAN_VERSION 70#define CAN_BCM_VERSION "20080415"
70static __initdata const char banner[] = KERN_INFO 71static __initdata const char banner[] = KERN_INFO
71 "can: broadcast manager protocol (rev " CAN_BCM_VERSION ")\n"; 72 "can: broadcast manager protocol (rev " CAN_BCM_VERSION ")\n";
72 73
@@ -85,11 +86,10 @@ struct bcm_op {
85 int ifindex; 86 int ifindex;
86 canid_t can_id; 87 canid_t can_id;
87 int flags; 88 int flags;
88 unsigned long j_ival1, j_ival2, j_lastmsg;
89 unsigned long frames_abs, frames_filtered; 89 unsigned long frames_abs, frames_filtered;
90 struct timer_list timer, thrtimer;
91 struct timeval ival1, ival2; 90 struct timeval ival1, ival2;
92 ktime_t rx_stamp; 91 struct hrtimer timer, thrtimer;
92 ktime_t rx_stamp, kt_ival1, kt_ival2, kt_lastmsg;
93 int rx_ifindex; 93 int rx_ifindex;
94 int count; 94 int count;
95 int nframes; 95 int nframes;
@@ -126,39 +126,6 @@ static inline struct bcm_sock *bcm_sk(const struct sock *sk)
126#define MHSIZ sizeof(struct bcm_msg_head) 126#define MHSIZ sizeof(struct bcm_msg_head)
127 127
128/* 128/*
129 * rounded_tv2jif - calculate jiffies from timeval including optional up
130 * @tv: pointer to timeval
131 *
132 * Description:
133 * Unlike timeval_to_jiffies() provided in include/linux/jiffies.h, this
134 * function is intentionally more relaxed on precise timer ticks to get
135 * exact one jiffy for requested 1000us on a 1000HZ machine.
136 * This code is to be removed when upgrading to kernel hrtimer.
137 *
138 * Return:
139 * calculated jiffies (max: ULONG_MAX)
140 */
141static unsigned long rounded_tv2jif(const struct timeval *tv)
142{
143 unsigned long sec = tv->tv_sec;
144 unsigned long usec = tv->tv_usec;
145 unsigned long jif;
146
147 if (sec > ULONG_MAX / HZ)
148 return ULONG_MAX;
149
150 /* round up to get at least the requested time */
151 usec += 1000000 / HZ - 1;
152
153 jif = usec / (1000000 / HZ);
154
155 if (sec * HZ > ULONG_MAX - jif)
156 return ULONG_MAX;
157
158 return jif + sec * HZ;
159}
160
161/*
162 * procfs functions 129 * procfs functions
163 */ 130 */
164static char *bcm_proc_getifname(int ifindex) 131static char *bcm_proc_getifname(int ifindex)
@@ -208,13 +175,17 @@ static int bcm_read_proc(char *page, char **start, off_t off,
208 len += snprintf(page + len, PAGE_SIZE - len, "[%d]%c ", 175 len += snprintf(page + len, PAGE_SIZE - len, "[%d]%c ",
209 op->nframes, 176 op->nframes,
210 (op->flags & RX_CHECK_DLC)?'d':' '); 177 (op->flags & RX_CHECK_DLC)?'d':' ');
211 if (op->j_ival1) 178 if (op->kt_ival1.tv64)
212 len += snprintf(page + len, PAGE_SIZE - len, 179 len += snprintf(page + len, PAGE_SIZE - len,
213 "timeo=%ld ", op->j_ival1); 180 "timeo=%lld ",
181 (long long)
182 ktime_to_us(op->kt_ival1));
214 183
215 if (op->j_ival2) 184 if (op->kt_ival2.tv64)
216 len += snprintf(page + len, PAGE_SIZE - len, 185 len += snprintf(page + len, PAGE_SIZE - len,
217 "thr=%ld ", op->j_ival2); 186 "thr=%lld ",
187 (long long)
188 ktime_to_us(op->kt_ival2));
218 189
219 len += snprintf(page + len, PAGE_SIZE - len, 190 len += snprintf(page + len, PAGE_SIZE - len,
220 "# recv %ld (%ld) => reduction: ", 191 "# recv %ld (%ld) => reduction: ",
@@ -238,13 +209,14 @@ static int bcm_read_proc(char *page, char **start, off_t off,
238 "tx_op: %03X %s [%d] ", 209 "tx_op: %03X %s [%d] ",
239 op->can_id, bcm_proc_getifname(op->ifindex), 210 op->can_id, bcm_proc_getifname(op->ifindex),
240 op->nframes); 211 op->nframes);
241 if (op->j_ival1)
242 len += snprintf(page + len, PAGE_SIZE - len, "t1=%ld ",
243 op->j_ival1);
244 212
245 if (op->j_ival2) 213 if (op->kt_ival1.tv64)
246 len += snprintf(page + len, PAGE_SIZE - len, "t2=%ld ", 214 len += snprintf(page + len, PAGE_SIZE - len, "t1=%lld ",
247 op->j_ival2); 215 (long long) ktime_to_us(op->kt_ival1));
216
217 if (op->kt_ival2.tv64)
218 len += snprintf(page + len, PAGE_SIZE - len, "t2=%lld ",
219 (long long) ktime_to_us(op->kt_ival2));
248 220
249 len += snprintf(page + len, PAGE_SIZE - len, "# sent %ld\n", 221 len += snprintf(page + len, PAGE_SIZE - len, "# sent %ld\n",
250 op->frames_abs); 222 op->frames_abs);
@@ -371,11 +343,12 @@ static void bcm_send_to_user(struct bcm_op *op, struct bcm_msg_head *head,
371/* 343/*
372 * bcm_tx_timeout_handler - performes cyclic CAN frame transmissions 344 * bcm_tx_timeout_handler - performes cyclic CAN frame transmissions
373 */ 345 */
374static void bcm_tx_timeout_handler(unsigned long data) 346static enum hrtimer_restart bcm_tx_timeout_handler(struct hrtimer *hrtimer)
375{ 347{
376 struct bcm_op *op = (struct bcm_op *)data; 348 struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer);
349 enum hrtimer_restart ret = HRTIMER_NORESTART;
377 350
378 if (op->j_ival1 && (op->count > 0)) { 351 if (op->kt_ival1.tv64 && (op->count > 0)) {
379 352
380 op->count--; 353 op->count--;
381 if (!op->count && (op->flags & TX_COUNTEVT)) { 354 if (!op->count && (op->flags & TX_COUNTEVT)) {
@@ -394,22 +367,24 @@ static void bcm_tx_timeout_handler(unsigned long data)
394 } 367 }
395 } 368 }
396 369
397 if (op->j_ival1 && (op->count > 0)) { 370 if (op->kt_ival1.tv64 && (op->count > 0)) {
398 371
399 /* send (next) frame */ 372 /* send (next) frame */
400 bcm_can_tx(op); 373 bcm_can_tx(op);
401 mod_timer(&op->timer, jiffies + op->j_ival1); 374 hrtimer_forward(hrtimer, ktime_get(), op->kt_ival1);
375 ret = HRTIMER_RESTART;
402 376
403 } else { 377 } else {
404 if (op->j_ival2) { 378 if (op->kt_ival2.tv64) {
405 379
406 /* send (next) frame */ 380 /* send (next) frame */
407 bcm_can_tx(op); 381 bcm_can_tx(op);
408 mod_timer(&op->timer, jiffies + op->j_ival2); 382 hrtimer_forward(hrtimer, ktime_get(), op->kt_ival2);
383 ret = HRTIMER_RESTART;
409 } 384 }
410 } 385 }
411 386
412 return; 387 return ret;
413} 388}
414 389
415/* 390/*
@@ -419,8 +394,6 @@ static void bcm_rx_changed(struct bcm_op *op, struct can_frame *data)
419{ 394{
420 struct bcm_msg_head head; 395 struct bcm_msg_head head;
421 396
422 op->j_lastmsg = jiffies;
423
424 /* update statistics */ 397 /* update statistics */
425 op->frames_filtered++; 398 op->frames_filtered++;
426 399
@@ -439,6 +412,12 @@ static void bcm_rx_changed(struct bcm_op *op, struct can_frame *data)
439 bcm_send_to_user(op, &head, data, 1); 412 bcm_send_to_user(op, &head, data, 1);
440} 413}
441 414
415/* TODO: move to linux/hrtimer.h */
416static inline int hrtimer_callback_running(struct hrtimer *timer)
417{
418 return timer->state & HRTIMER_STATE_CALLBACK;
419}
420
442/* 421/*
443 * bcm_rx_update_and_send - process a detected relevant receive content change 422 * bcm_rx_update_and_send - process a detected relevant receive content change
444 * 1. update the last received data 423 * 1. update the last received data
@@ -448,30 +427,44 @@ static void bcm_rx_update_and_send(struct bcm_op *op,
448 struct can_frame *lastdata, 427 struct can_frame *lastdata,
449 struct can_frame *rxdata) 428 struct can_frame *rxdata)
450{ 429{
451 unsigned long nexttx = op->j_lastmsg + op->j_ival2;
452
453 memcpy(lastdata, rxdata, CFSIZ); 430 memcpy(lastdata, rxdata, CFSIZ);
454 431
455 /* mark as used */ 432 /* mark as used */
456 lastdata->can_dlc |= RX_RECV; 433 lastdata->can_dlc |= RX_RECV;
457 434
458 /* throttle bcm_rx_changed ? */ 435 /* throtteling mode inactive OR data update already on the run ? */
459 if ((op->thrtimer.expires) || 436 if (!op->kt_ival2.tv64 || hrtimer_callback_running(&op->thrtimer)) {
460 ((op->j_ival2) && (nexttx > jiffies))) { 437 /* send RX_CHANGED to the user immediately */
461 /* we are already waiting OR we have to start waiting */ 438 bcm_rx_changed(op, rxdata);
439 return;
440 }
462 441
442 if (hrtimer_active(&op->thrtimer)) {
463 /* mark as 'throttled' */ 443 /* mark as 'throttled' */
464 lastdata->can_dlc |= RX_THR; 444 lastdata->can_dlc |= RX_THR;
445 return;
446 }
465 447
466 if (!(op->thrtimer.expires)) { 448 if (!op->kt_lastmsg.tv64) {
467 /* start the timer only the first time */ 449 /* send first RX_CHANGED to the user immediately */
468 mod_timer(&op->thrtimer, nexttx);
469 }
470
471 } else {
472 /* send RX_CHANGED to the user immediately */
473 bcm_rx_changed(op, rxdata); 450 bcm_rx_changed(op, rxdata);
451 op->kt_lastmsg = ktime_get();
452 return;
453 }
454
455 if (ktime_us_delta(ktime_get(), op->kt_lastmsg) <
456 ktime_to_us(op->kt_ival2)) {
457 /* mark as 'throttled' and start timer */
458 lastdata->can_dlc |= RX_THR;
459 hrtimer_start(&op->thrtimer,
460 ktime_add(op->kt_lastmsg, op->kt_ival2),
461 HRTIMER_MODE_ABS);
462 return;
474 } 463 }
464
465 /* the gap was that big, that throttling was not needed here */
466 bcm_rx_changed(op, rxdata);
467 op->kt_lastmsg = ktime_get();
475} 468}
476 469
477/* 470/*
@@ -519,16 +512,16 @@ static void bcm_rx_starttimer(struct bcm_op *op)
519 if (op->flags & RX_NO_AUTOTIMER) 512 if (op->flags & RX_NO_AUTOTIMER)
520 return; 513 return;
521 514
522 if (op->j_ival1) 515 if (op->kt_ival1.tv64)
523 mod_timer(&op->timer, jiffies + op->j_ival1); 516 hrtimer_start(&op->timer, op->kt_ival1, HRTIMER_MODE_REL);
524} 517}
525 518
526/* 519/*
527 * bcm_rx_timeout_handler - when the (cyclic) CAN frame receiption timed out 520 * bcm_rx_timeout_handler - when the (cyclic) CAN frame receiption timed out
528 */ 521 */
529static void bcm_rx_timeout_handler(unsigned long data) 522static enum hrtimer_restart bcm_rx_timeout_handler(struct hrtimer *hrtimer)
530{ 523{
531 struct bcm_op *op = (struct bcm_op *)data; 524 struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer);
532 struct bcm_msg_head msg_head; 525 struct bcm_msg_head msg_head;
533 526
534 msg_head.opcode = RX_TIMEOUT; 527 msg_head.opcode = RX_TIMEOUT;
@@ -548,27 +541,27 @@ static void bcm_rx_timeout_handler(unsigned long data)
548 /* clear received can_frames to indicate 'nothing received' */ 541 /* clear received can_frames to indicate 'nothing received' */
549 memset(op->last_frames, 0, op->nframes * CFSIZ); 542 memset(op->last_frames, 0, op->nframes * CFSIZ);
550 } 543 }
544
545 return HRTIMER_NORESTART;
551} 546}
552 547
553/* 548/*
554 * bcm_rx_thr_handler - the time for blocked content updates is over now: 549 * bcm_rx_thr_flush - Check for throttled data and send it to the userspace
555 * Check for throttled data and send it to the userspace
556 */ 550 */
557static void bcm_rx_thr_handler(unsigned long data) 551static int bcm_rx_thr_flush(struct bcm_op *op)
558{ 552{
559 struct bcm_op *op = (struct bcm_op *)data; 553 int updated = 0;
560 int i = 0;
561
562 /* mark disabled / consumed timer */
563 op->thrtimer.expires = 0;
564 554
565 if (op->nframes > 1) { 555 if (op->nframes > 1) {
556 int i;
557
566 /* for MUX filter we start at index 1 */ 558 /* for MUX filter we start at index 1 */
567 for (i = 1; i < op->nframes; i++) { 559 for (i = 1; i < op->nframes; i++) {
568 if ((op->last_frames) && 560 if ((op->last_frames) &&
569 (op->last_frames[i].can_dlc & RX_THR)) { 561 (op->last_frames[i].can_dlc & RX_THR)) {
570 op->last_frames[i].can_dlc &= ~RX_THR; 562 op->last_frames[i].can_dlc &= ~RX_THR;
571 bcm_rx_changed(op, &op->last_frames[i]); 563 bcm_rx_changed(op, &op->last_frames[i]);
564 updated++;
572 } 565 }
573 } 566 }
574 567
@@ -577,8 +570,29 @@ static void bcm_rx_thr_handler(unsigned long data)
577 if (op->last_frames && (op->last_frames[0].can_dlc & RX_THR)) { 570 if (op->last_frames && (op->last_frames[0].can_dlc & RX_THR)) {
578 op->last_frames[0].can_dlc &= ~RX_THR; 571 op->last_frames[0].can_dlc &= ~RX_THR;
579 bcm_rx_changed(op, &op->last_frames[0]); 572 bcm_rx_changed(op, &op->last_frames[0]);
573 updated++;
580 } 574 }
581 } 575 }
576
577 return updated;
578}
579
580/*
581 * bcm_rx_thr_handler - the time for blocked content updates is over now:
582 * Check for throttled data and send it to the userspace
583 */
584static enum hrtimer_restart bcm_rx_thr_handler(struct hrtimer *hrtimer)
585{
586 struct bcm_op *op = container_of(hrtimer, struct bcm_op, thrtimer);
587
588 if (bcm_rx_thr_flush(op)) {
589 hrtimer_forward(hrtimer, ktime_get(), op->kt_ival2);
590 return HRTIMER_RESTART;
591 } else {
592 /* rearm throttle handling */
593 op->kt_lastmsg = ktime_set(0, 0);
594 return HRTIMER_NORESTART;
595 }
582} 596}
583 597
584/* 598/*
@@ -591,7 +605,7 @@ static void bcm_rx_handler(struct sk_buff *skb, void *data)
591 int i; 605 int i;
592 606
593 /* disable timeout */ 607 /* disable timeout */
594 del_timer(&op->timer); 608 hrtimer_cancel(&op->timer);
595 609
596 if (skb->len == sizeof(rxframe)) { 610 if (skb->len == sizeof(rxframe)) {
597 memcpy(&rxframe, skb->data, sizeof(rxframe)); 611 memcpy(&rxframe, skb->data, sizeof(rxframe));
@@ -669,8 +683,8 @@ static struct bcm_op *bcm_find_op(struct list_head *ops, canid_t can_id,
669 683
670static void bcm_remove_op(struct bcm_op *op) 684static void bcm_remove_op(struct bcm_op *op)
671{ 685{
672 del_timer(&op->timer); 686 hrtimer_cancel(&op->timer);
673 del_timer(&op->thrtimer); 687 hrtimer_cancel(&op->thrtimer);
674 688
675 if ((op->frames) && (op->frames != &op->sframe)) 689 if ((op->frames) && (op->frames != &op->sframe))
676 kfree(op->frames); 690 kfree(op->frames);
@@ -871,11 +885,11 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
871 op->ifindex = ifindex; 885 op->ifindex = ifindex;
872 886
873 /* initialize uninitialized (kzalloc) structure */ 887 /* initialize uninitialized (kzalloc) structure */
874 setup_timer(&op->timer, bcm_tx_timeout_handler, 888 hrtimer_init(&op->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
875 (unsigned long)op); 889 op->timer.function = bcm_tx_timeout_handler;
876 890
877 /* currently unused in tx_ops */ 891 /* currently unused in tx_ops */
878 init_timer(&op->thrtimer); 892 hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
879 893
880 /* add this bcm_op to the list of the tx_ops */ 894 /* add this bcm_op to the list of the tx_ops */
881 list_add(&op->list, &bo->tx_ops); 895 list_add(&op->list, &bo->tx_ops);
@@ -902,25 +916,27 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
902 op->count = msg_head->count; 916 op->count = msg_head->count;
903 op->ival1 = msg_head->ival1; 917 op->ival1 = msg_head->ival1;
904 op->ival2 = msg_head->ival2; 918 op->ival2 = msg_head->ival2;
905 op->j_ival1 = rounded_tv2jif(&msg_head->ival1); 919 op->kt_ival1 = timeval_to_ktime(msg_head->ival1);
906 op->j_ival2 = rounded_tv2jif(&msg_head->ival2); 920 op->kt_ival2 = timeval_to_ktime(msg_head->ival2);
907 921
908 /* disable an active timer due to zero values? */ 922 /* disable an active timer due to zero values? */
909 if (!op->j_ival1 && !op->j_ival2) 923 if (!op->kt_ival1.tv64 && !op->kt_ival2.tv64)
910 del_timer(&op->timer); 924 hrtimer_cancel(&op->timer);
911 } 925 }
912 926
913 if ((op->flags & STARTTIMER) && 927 if ((op->flags & STARTTIMER) &&
914 ((op->j_ival1 && op->count) || op->j_ival2)) { 928 ((op->kt_ival1.tv64 && op->count) || op->kt_ival2.tv64)) {
915 929
916 /* spec: send can_frame when starting timer */ 930 /* spec: send can_frame when starting timer */
917 op->flags |= TX_ANNOUNCE; 931 op->flags |= TX_ANNOUNCE;
918 932
919 if (op->j_ival1 && (op->count > 0)) { 933 if (op->kt_ival1.tv64 && (op->count > 0)) {
920 /* op->count-- is done in bcm_tx_timeout_handler */ 934 /* op->count-- is done in bcm_tx_timeout_handler */
921 mod_timer(&op->timer, jiffies + op->j_ival1); 935 hrtimer_start(&op->timer, op->kt_ival1,
936 HRTIMER_MODE_REL);
922 } else 937 } else
923 mod_timer(&op->timer, jiffies + op->j_ival2); 938 hrtimer_start(&op->timer, op->kt_ival2,
939 HRTIMER_MODE_REL);
924 } 940 }
925 941
926 if (op->flags & TX_ANNOUNCE) 942 if (op->flags & TX_ANNOUNCE)
@@ -1032,15 +1048,11 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
1032 op->ifindex = ifindex; 1048 op->ifindex = ifindex;
1033 1049
1034 /* initialize uninitialized (kzalloc) structure */ 1050 /* initialize uninitialized (kzalloc) structure */
1035 setup_timer(&op->timer, bcm_rx_timeout_handler, 1051 hrtimer_init(&op->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
1036 (unsigned long)op); 1052 op->timer.function = bcm_rx_timeout_handler;
1037 1053
1038 /* init throttle timer for RX_CHANGED */ 1054 hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
1039 setup_timer(&op->thrtimer, bcm_rx_thr_handler, 1055 op->thrtimer.function = bcm_rx_thr_handler;
1040 (unsigned long)op);
1041
1042 /* mark disabled timer */
1043 op->thrtimer.expires = 0;
1044 1056
1045 /* add this bcm_op to the list of the rx_ops */ 1057 /* add this bcm_op to the list of the rx_ops */
1046 list_add(&op->list, &bo->rx_ops); 1058 list_add(&op->list, &bo->rx_ops);
@@ -1056,8 +1068,8 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
1056 if (op->flags & RX_RTR_FRAME) { 1068 if (op->flags & RX_RTR_FRAME) {
1057 1069
1058 /* no timers in RTR-mode */ 1070 /* no timers in RTR-mode */
1059 del_timer(&op->thrtimer); 1071 hrtimer_cancel(&op->thrtimer);
1060 del_timer(&op->timer); 1072 hrtimer_cancel(&op->timer);
1061 1073
1062 /* 1074 /*
1063 * funny feature in RX(!)_SETUP only for RTR-mode: 1075 * funny feature in RX(!)_SETUP only for RTR-mode:
@@ -1074,28 +1086,25 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
1074 /* set timer value */ 1086 /* set timer value */
1075 op->ival1 = msg_head->ival1; 1087 op->ival1 = msg_head->ival1;
1076 op->ival2 = msg_head->ival2; 1088 op->ival2 = msg_head->ival2;
1077 op->j_ival1 = rounded_tv2jif(&msg_head->ival1); 1089 op->kt_ival1 = timeval_to_ktime(msg_head->ival1);
1078 op->j_ival2 = rounded_tv2jif(&msg_head->ival2); 1090 op->kt_ival2 = timeval_to_ktime(msg_head->ival2);
1079 1091
1080 /* disable an active timer due to zero value? */ 1092 /* disable an active timer due to zero value? */
1081 if (!op->j_ival1) 1093 if (!op->kt_ival1.tv64)
1082 del_timer(&op->timer); 1094 hrtimer_cancel(&op->timer);
1083
1084 /* free currently blocked msgs ? */
1085 if (op->thrtimer.expires) {
1086 /* send blocked msgs hereafter */
1087 mod_timer(&op->thrtimer, jiffies + 2);
1088 }
1089 1095
1090 /* 1096 /*
1091 * if (op->j_ival2) is zero, no (new) throttling 1097 * In any case cancel the throttle timer, flush
1092 * will happen. For details see functions 1098 * potentially blocked msgs and reset throttle handling
1093 * bcm_rx_update_and_send() and bcm_rx_thr_handler()
1094 */ 1099 */
1100 op->kt_lastmsg = ktime_set(0, 0);
1101 hrtimer_cancel(&op->thrtimer);
1102 bcm_rx_thr_flush(op);
1095 } 1103 }
1096 1104
1097 if ((op->flags & STARTTIMER) && op->j_ival1) 1105 if ((op->flags & STARTTIMER) && op->kt_ival1.tv64)
1098 mod_timer(&op->timer, jiffies + op->j_ival1); 1106 hrtimer_start(&op->timer, op->kt_ival1,
1107 HRTIMER_MODE_REL);
1099 } 1108 }
1100 1109
1101 /* now we can register for can_ids, if we added a new bcm_op */ 1110 /* now we can register for can_ids, if we added a new bcm_op */