]> rtime.felk.cvut.cz Git - socketcan-devel.git/blobdiff - kernel/2.6/net/can/bcm.c
can bcm: fix tx_setup off-by-one errors
[socketcan-devel.git] / kernel / 2.6 / net / can / bcm.c
index 6250c71a82f36e167a27ea08c09cbe72d6f072e3..96333982589d2cc11f2642b022d1b0da2b2f301c 100644 (file)
@@ -44,6 +44,7 @@
 #include <linux/module.h>
 #include <linux/version.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/hrtimer.h>
 #include <linux/list.h>
 #include <linux/proc_fs.h>
@@ -181,9 +182,15 @@ static int bcm_proc_show(struct seq_file *m, void *v)
        struct bcm_sock *bo = bcm_sk(sk);
        struct bcm_op *op;
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0)
        seq_printf(m, ">>> socket %p", sk->sk_socket);
        seq_printf(m, " / sk %p", sk);
        seq_printf(m, " / bo %p", bo);
+#else
+       seq_printf(m, ">>> socket %pK", sk->sk_socket);
+       seq_printf(m, " / sk %pK", sk);
+       seq_printf(m, " / bo %pK", bo);
+#endif
        seq_printf(m, " / dropped %lu", bo->dropped_usr_msgs);
        seq_printf(m, " / bound %s", bcm_proc_getifname(ifname, bo->ifindex));
        seq_printf(m, " <<<\n");
@@ -474,9 +481,6 @@ static void bcm_tx_timeout_tsklet(unsigned long data)
 
                        bcm_send_to_user(op, &msg_head, NULL, 0);
                }
-       }
-
-       if (op->kt_ival1.tv64 && (op->count > 0)) {
 
                /* send (next) frame */
                bcm_can_tx(op);
@@ -1094,8 +1098,9 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
                /* spec: send can_frame when starting timer */
                op->flags |= TX_ANNOUNCE;
 
-               if (op->kt_ival1.tv64 && (op->count > 0)) {
-                       /* op->count-- is done in bcm_tx_timeout_handler */
+               /* only start timer when having more frames than sent below */
+               if (op->kt_ival1.tv64 && (op->count > 1)) {
+                       /* op->count-- is done in bcm_tx_timeout_tsklet */
                        hrtimer_start(&op->timer, op->kt_ival1,
                                      HRTIMER_MODE_REL);
                } else
@@ -1103,8 +1108,11 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
                                      HRTIMER_MODE_REL);
        }
 
-       if (op->flags & TX_ANNOUNCE)
+       if (op->flags & TX_ANNOUNCE) {
                bcm_can_tx(op);
+               if (op->kt_ival1.tv64 && (op->count > 0))
+                       op->count--;
+       }
 
        return msg_head->nframes * CFSIZ + MHSIZ;
 }
@@ -1557,9 +1565,14 @@ static int bcm_init(struct sock *sk)
 static int bcm_release(struct socket *sock)
 {
        struct sock *sk = sock->sk;
-       struct bcm_sock *bo = bcm_sk(sk);
+       struct bcm_sock *bo;
        struct bcm_op *op, *next;
 
+       if (sk == NULL)
+               return 0;
+
+       bo = bcm_sk(sk);
+
        /* remove bcm_ops, timer, rx_unregister(), etc. */
 
        unregister_netdevice_notifier(&bo->notifier);
@@ -1623,6 +1636,9 @@ static int bcm_connect(struct socket *sock, struct sockaddr *uaddr, int len,
        struct sock *sk = sock->sk;
        struct bcm_sock *bo = bcm_sk(sk);
 
+       if (len < sizeof(*addr))
+               return -EINVAL;
+
        if (bo->bound)
                return -EISCONN;
 
@@ -1729,7 +1745,7 @@ static struct proto bcm_proto __read_mostly = {
        .init       = bcm_init,
 };
 
-static struct can_proto bcm_can_proto __read_mostly = {
+static const struct can_proto bcm_can_proto = {
        .type       = SOCK_DGRAM,
        .protocol   = CAN_BCM,
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)