diff options
Diffstat (limited to 'net/can')
-rw-r--r-- | net/can/bcm.c | 251 |
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" |
70 | static __initdata const char banner[] = KERN_INFO | 71 | static __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 | */ | ||
141 | static 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 | */ |
164 | static char *bcm_proc_getifname(int ifindex) | 131 | static 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 | */ |
374 | static void bcm_tx_timeout_handler(unsigned long data) | 346 | static 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 */ | ||
416 | static 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 | */ |
529 | static void bcm_rx_timeout_handler(unsigned long data) | 522 | static 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 | */ |
557 | static void bcm_rx_thr_handler(unsigned long data) | 551 | static 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 | */ | ||
584 | static 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 | ||
670 | static void bcm_remove_op(struct bcm_op *op) | 684 | static 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 */ |