drm/rockchip: dsi: fix Non-SNPS PHY power on sequence
[firefly-linux-kernel-4.4.55.git] / net / dccp / minisocks.c
index 1994f8af646b15fe668c01b207567f9016865c4f..68eed344b47122cfc76c66e81fb372881c666f65 100644 (file)
@@ -122,6 +122,7 @@ struct sock *dccp_create_openreq_child(const struct sock *sk,
                        /* It is still raw copy of parent, so invalidate
                         * destructor and make plain sk_free() */
                        newsk->sk_destruct = NULL;
+                       bh_unlock_sock(newsk);
                        sk_free(newsk);
                        return NULL;
                }
@@ -145,6 +146,13 @@ struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb,
        struct dccp_request_sock *dreq = dccp_rsk(req);
        bool own_req;
 
+       /* TCP/DCCP listeners became lockless.
+        * DCCP stores complex state in its request_sock, so we need
+        * a protection for them, now this code runs without being protected
+        * by the parent (listener) lock.
+        */
+       spin_lock_bh(&dreq->dreq_lock);
+
        /* Check for retransmitted REQUEST */
        if (dccp_hdr(skb)->dccph_type == DCCP_PKT_REQUEST) {
 
@@ -159,7 +167,7 @@ struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb,
                        inet_rtx_syn_ack(sk, req);
                }
                /* Network Duplicate, discard packet */
-               return NULL;
+               goto out;
        }
 
        DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_PACKET_ERROR;
@@ -185,20 +193,20 @@ struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb,
 
        child = inet_csk(sk)->icsk_af_ops->syn_recv_sock(sk, skb, req, NULL,
                                                         req, &own_req);
-       if (!child)
-               goto listen_overflow;
-
-       return inet_csk_complete_hashdance(sk, child, req, own_req);
+       if (child) {
+               child = inet_csk_complete_hashdance(sk, child, req, own_req);
+               goto out;
+       }
 
-listen_overflow:
-       dccp_pr_debug("listen_overflow!\n");
        DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_TOO_BUSY;
 drop:
        if (dccp_hdr(skb)->dccph_type != DCCP_PKT_RESET)
                req->rsk_ops->send_reset(sk, skb);
 
        inet_csk_reqsk_queue_drop(sk, req);
-       return NULL;
+out:
+       spin_unlock_bh(&dreq->dreq_lock);
+       return child;
 }
 
 EXPORT_SYMBOL_GPL(dccp_check_req);
@@ -249,6 +257,7 @@ int dccp_reqsk_init(struct request_sock *req,
 {
        struct dccp_request_sock *dreq = dccp_rsk(req);
 
+       spin_lock_init(&dreq->dreq_lock);
        inet_rsk(req)->ir_rmt_port = dccp_hdr(skb)->dccph_sport;
        inet_rsk(req)->ir_num      = ntohs(dccp_hdr(skb)->dccph_dport);
        inet_rsk(req)->acked       = 0;