struct l2cap_conn *conn;
        int err = 0;
 
-       BT_DBG("sock %p, sk %p", sock, sk);
+       BT_DBG("sock %p, sk %p, how %d", sock, sk, how);
+
+       /* 'how' parameter is mapped to sk_shutdown as follows:
+        * SHUT_RD   (0) --> RCV_SHUTDOWN  (1)
+        * SHUT_WR   (1) --> SEND_SHUTDOWN (2)
+        * SHUT_RDWR (2) --> SHUTDOWN_MASK (3)
+        */
+       how++;
 
        if (!sk)
                return 0;
 
        lock_sock(sk);
 
-       if (sk->sk_shutdown)
+       if ((sk->sk_shutdown & how) == how)
                goto shutdown_already;
 
        BT_DBG("Handling sock shutdown");
                 * has already been actioned to close the L2CAP
                 * link such as by l2cap_disconnection_req().
                 */
-               if (sk->sk_shutdown)
-                       goto has_shutdown;
+               if ((sk->sk_shutdown & how) == how)
+                       goto shutdown_matched;
        }
 
-       sk->sk_shutdown = SHUTDOWN_MASK;
+       /* Try setting the RCV_SHUTDOWN bit, return early if SEND_SHUTDOWN
+        * is already set
+        */
+       if ((how & RCV_SHUTDOWN) && !(sk->sk_shutdown & RCV_SHUTDOWN)) {
+               sk->sk_shutdown |= RCV_SHUTDOWN;
+               if ((sk->sk_shutdown & how) == how)
+                       goto shutdown_matched;
+       }
+
+       sk->sk_shutdown |= SEND_SHUTDOWN;
        release_sock(sk);
 
        l2cap_chan_lock(chan);
                err = bt_sock_wait_state(sk, BT_CLOSED,
                                         sk->sk_lingertime);
 
-has_shutdown:
+shutdown_matched:
        l2cap_chan_put(chan);
        sock_put(sk);
 
 
        bt_sock_unlink(&l2cap_sk_list, sk);
 
-       err = l2cap_sock_shutdown(sock, 2);
+       err = l2cap_sock_shutdown(sock, SHUT_RDWR);
        chan = l2cap_pi(sk)->chan;
 
        l2cap_chan_hold(chan);