diff options
-rw-r--r-- | net/caif/caif_socket.c | 19 |
1 files changed, 8 insertions, 11 deletions
diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c index 3cc71b9f5517..cc858919108e 100644 --- a/net/caif/caif_socket.c +++ b/net/caif/caif_socket.c | |||
@@ -121,12 +121,13 @@ static void caif_flow_ctrl(struct sock *sk, int mode) | |||
121 | * Copied from sock.c:sock_queue_rcv_skb(), but changed so packets are | 121 | * Copied from sock.c:sock_queue_rcv_skb(), but changed so packets are |
122 | * not dropped, but CAIF is sending flow off instead. | 122 | * not dropped, but CAIF is sending flow off instead. |
123 | */ | 123 | */ |
124 | static int caif_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | 124 | static void caif_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) |
125 | { | 125 | { |
126 | int err; | 126 | int err; |
127 | unsigned long flags; | 127 | unsigned long flags; |
128 | struct sk_buff_head *list = &sk->sk_receive_queue; | 128 | struct sk_buff_head *list = &sk->sk_receive_queue; |
129 | struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); | 129 | struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); |
130 | bool queued = false; | ||
130 | 131 | ||
131 | if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= | 132 | if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= |
132 | (unsigned int)sk->sk_rcvbuf && rx_flow_is_on(cf_sk)) { | 133 | (unsigned int)sk->sk_rcvbuf && rx_flow_is_on(cf_sk)) { |
@@ -139,7 +140,8 @@ static int caif_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
139 | 140 | ||
140 | err = sk_filter(sk, skb); | 141 | err = sk_filter(sk, skb); |
141 | if (err) | 142 | if (err) |
142 | return err; | 143 | goto out; |
144 | |||
143 | if (!sk_rmem_schedule(sk, skb, skb->truesize) && rx_flow_is_on(cf_sk)) { | 145 | if (!sk_rmem_schedule(sk, skb, skb->truesize) && rx_flow_is_on(cf_sk)) { |
144 | set_rx_flow_off(cf_sk); | 146 | set_rx_flow_off(cf_sk); |
145 | net_dbg_ratelimited("sending flow OFF due to rmem_schedule\n"); | 147 | net_dbg_ratelimited("sending flow OFF due to rmem_schedule\n"); |
@@ -147,21 +149,16 @@ static int caif_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
147 | } | 149 | } |
148 | skb->dev = NULL; | 150 | skb->dev = NULL; |
149 | skb_set_owner_r(skb, sk); | 151 | skb_set_owner_r(skb, sk); |
150 | /* Cache the SKB length before we tack it onto the receive | ||
151 | * queue. Once it is added it no longer belongs to us and | ||
152 | * may be freed by other threads of control pulling packets | ||
153 | * from the queue. | ||
154 | */ | ||
155 | spin_lock_irqsave(&list->lock, flags); | 152 | spin_lock_irqsave(&list->lock, flags); |
156 | if (!sock_flag(sk, SOCK_DEAD)) | 153 | queued = !sock_flag(sk, SOCK_DEAD); |
154 | if (queued) | ||
157 | __skb_queue_tail(list, skb); | 155 | __skb_queue_tail(list, skb); |
158 | spin_unlock_irqrestore(&list->lock, flags); | 156 | spin_unlock_irqrestore(&list->lock, flags); |
159 | 157 | out: | |
160 | if (!sock_flag(sk, SOCK_DEAD)) | 158 | if (queued) |
161 | sk->sk_data_ready(sk); | 159 | sk->sk_data_ready(sk); |
162 | else | 160 | else |
163 | kfree_skb(skb); | 161 | kfree_skb(skb); |
164 | return 0; | ||
165 | } | 162 | } |
166 | 163 | ||
167 | /* Packet Receive Callback function called from CAIF Stack */ | 164 | /* Packet Receive Callback function called from CAIF Stack */ |