if (len < ISOTP_MIN_NAMELEN)
                return -EINVAL;
 
+       if (addr->can_addr.tp.tx_id & (CAN_ERR_FLAG | CAN_RTR_FLAG))
+               return -EADDRNOTAVAIL;
+
+       if (!addr->can_ifindex)
+               return -ENODEV;
+
+       lock_sock(sk);
+
        /* do not register frame reception for functional addressing */
        if (so->opt.flags & CAN_ISOTP_SF_BROADCAST)
                do_rx_reg = 0;
 
        /* do not validate rx address for functional addressing */
        if (do_rx_reg) {
-               if (addr->can_addr.tp.rx_id == addr->can_addr.tp.tx_id)
-                       return -EADDRNOTAVAIL;
+               if (addr->can_addr.tp.rx_id == addr->can_addr.tp.tx_id) {
+                       err = -EADDRNOTAVAIL;
+                       goto out;
+               }
 
-               if (addr->can_addr.tp.rx_id & (CAN_ERR_FLAG | CAN_RTR_FLAG))
-                       return -EADDRNOTAVAIL;
+               if (addr->can_addr.tp.rx_id & (CAN_ERR_FLAG | CAN_RTR_FLAG)) {
+                       err = -EADDRNOTAVAIL;
+                       goto out;
+               }
        }
 
-       if (addr->can_addr.tp.tx_id & (CAN_ERR_FLAG | CAN_RTR_FLAG))
-               return -EADDRNOTAVAIL;
-
-       if (!addr->can_ifindex)
-               return -ENODEV;
-
-       lock_sock(sk);
-
        if (so->bound && addr->can_ifindex == so->ifindex &&
            addr->can_addr.tp.rx_id == so->rxid &&
            addr->can_addr.tp.tx_id == so->txid)
        return ISOTP_MIN_NAMELEN;
 }
 
-static int isotp_setsockopt(struct socket *sock, int level, int optname,
+static int isotp_setsockopt_locked(struct socket *sock, int level, int optname,
                            sockptr_t optval, unsigned int optlen)
 {
        struct sock *sk = sock->sk;
        struct isotp_sock *so = isotp_sk(sk);
        int ret = 0;
 
-       if (level != SOL_CAN_ISOTP)
-               return -EINVAL;
-
        if (so->bound)
                return -EISCONN;
 
        return ret;
 }
 
+static int isotp_setsockopt(struct socket *sock, int level, int optname,
+                           sockptr_t optval, unsigned int optlen)
+
+{
+       struct sock *sk = sock->sk;
+       int ret;
+
+       if (level != SOL_CAN_ISOTP)
+               return -EINVAL;
+
+       lock_sock(sk);
+       ret = isotp_setsockopt_locked(sock, level, optname, optval, optlen);
+       release_sock(sk);
+       return ret;
+}
+
 static int isotp_getsockopt(struct socket *sock, int level, int optname,
                            char __user *optval, int __user *optlen)
 {