diff options
author | Oliver Hartkopp <socketcan@hartkopp.net> | 2011-09-29 15:33:47 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-09-29 15:33:47 -0400 |
commit | 12d0d0d3a7349daa95dbfd5d7df8146255bc7c67 (patch) | |
tree | 8dde0268c6afdb71142d59c9090b7d9abe88e222 /net | |
parent | 85a64889492b45f931ddac87ec09d84aa7347ee1 (diff) |
can bcm: fix incomplete tx_setup fix
The commit aabdcb0b553b9c9547b1a506b34d55a764745870 ("can bcm: fix tx_setup
off-by-one errors") fixed only a part of the original problem reported by
Andre Naujoks. It turned out that the original code needed to be re-ordered
to reduce complexity and to finally fix the reported frame counting issues.
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/can/bcm.c | 48 |
1 files changed, 21 insertions, 27 deletions
diff --git a/net/can/bcm.c b/net/can/bcm.c index c9cdb8d78e70..c84963d2dee6 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c | |||
@@ -344,6 +344,18 @@ static void bcm_send_to_user(struct bcm_op *op, struct bcm_msg_head *head, | |||
344 | } | 344 | } |
345 | } | 345 | } |
346 | 346 | ||
347 | static void bcm_tx_start_timer(struct bcm_op *op) | ||
348 | { | ||
349 | if (op->kt_ival1.tv64 && op->count) | ||
350 | hrtimer_start(&op->timer, | ||
351 | ktime_add(ktime_get(), op->kt_ival1), | ||
352 | HRTIMER_MODE_ABS); | ||
353 | else if (op->kt_ival2.tv64) | ||
354 | hrtimer_start(&op->timer, | ||
355 | ktime_add(ktime_get(), op->kt_ival2), | ||
356 | HRTIMER_MODE_ABS); | ||
357 | } | ||
358 | |||
347 | static void bcm_tx_timeout_tsklet(unsigned long data) | 359 | static void bcm_tx_timeout_tsklet(unsigned long data) |
348 | { | 360 | { |
349 | struct bcm_op *op = (struct bcm_op *)data; | 361 | struct bcm_op *op = (struct bcm_op *)data; |
@@ -365,23 +377,12 @@ static void bcm_tx_timeout_tsklet(unsigned long data) | |||
365 | 377 | ||
366 | bcm_send_to_user(op, &msg_head, NULL, 0); | 378 | bcm_send_to_user(op, &msg_head, NULL, 0); |
367 | } | 379 | } |
368 | |||
369 | /* send (next) frame */ | ||
370 | bcm_can_tx(op); | 380 | bcm_can_tx(op); |
371 | hrtimer_start(&op->timer, | ||
372 | ktime_add(ktime_get(), op->kt_ival1), | ||
373 | HRTIMER_MODE_ABS); | ||
374 | 381 | ||
375 | } else { | 382 | } else if (op->kt_ival2.tv64) |
376 | if (op->kt_ival2.tv64) { | 383 | bcm_can_tx(op); |
377 | 384 | ||
378 | /* send (next) frame */ | 385 | bcm_tx_start_timer(op); |
379 | bcm_can_tx(op); | ||
380 | hrtimer_start(&op->timer, | ||
381 | ktime_add(ktime_get(), op->kt_ival2), | ||
382 | HRTIMER_MODE_ABS); | ||
383 | } | ||
384 | } | ||
385 | } | 386 | } |
386 | 387 | ||
387 | /* | 388 | /* |
@@ -961,28 +962,21 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg, | |||
961 | hrtimer_cancel(&op->timer); | 962 | hrtimer_cancel(&op->timer); |
962 | } | 963 | } |
963 | 964 | ||
964 | if ((op->flags & STARTTIMER) && | 965 | if (op->flags & STARTTIMER) { |
965 | ((op->kt_ival1.tv64 && op->count) || op->kt_ival2.tv64)) { | 966 | hrtimer_cancel(&op->timer); |
966 | |||
967 | /* spec: send can_frame when starting timer */ | 967 | /* spec: send can_frame when starting timer */ |
968 | op->flags |= TX_ANNOUNCE; | 968 | op->flags |= TX_ANNOUNCE; |
969 | |||
970 | /* only start timer when having more frames than sent below */ | ||
971 | if (op->kt_ival1.tv64 && (op->count > 1)) { | ||
972 | /* op->count-- is done in bcm_tx_timeout_tsklet */ | ||
973 | hrtimer_start(&op->timer, op->kt_ival1, | ||
974 | HRTIMER_MODE_REL); | ||
975 | } else | ||
976 | hrtimer_start(&op->timer, op->kt_ival2, | ||
977 | HRTIMER_MODE_REL); | ||
978 | } | 969 | } |
979 | 970 | ||
980 | if (op->flags & TX_ANNOUNCE) { | 971 | if (op->flags & TX_ANNOUNCE) { |
981 | bcm_can_tx(op); | 972 | bcm_can_tx(op); |
982 | if (op->kt_ival1.tv64 && (op->count > 0)) | 973 | if (op->count) |
983 | op->count--; | 974 | op->count--; |
984 | } | 975 | } |
985 | 976 | ||
977 | if (op->flags & STARTTIMER) | ||
978 | bcm_tx_start_timer(op); | ||
979 | |||
986 | return msg_head->nframes * CFSIZ + MHSIZ; | 980 | return msg_head->nframes * CFSIZ + MHSIZ; |
987 | } | 981 | } |
988 | 982 | ||