]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - net/atm/common.c
Merge tag 'armsoc-fixes-nc' of git://git.kernel.org/pub/scm/linux/kernel/git/arm...
[karo-tx-linux.git] / net / atm / common.c
index 9613381f5db04e28ff66749706d1d61d82f77b88..f06422f4108d209fde356457c453164f2f4d7289 100644 (file)
@@ -62,21 +62,16 @@ static void vcc_remove_socket(struct sock *sk)
        write_unlock_irq(&vcc_sklist_lock);
 }
 
-static struct sk_buff *alloc_tx(struct atm_vcc *vcc, unsigned int size)
+static bool vcc_tx_ready(struct atm_vcc *vcc, unsigned int size)
 {
-       struct sk_buff *skb;
        struct sock *sk = sk_atm(vcc);
 
        if (sk_wmem_alloc_get(sk) && !atm_may_send(vcc, size)) {
                pr_debug("Sorry: wmem_alloc = %d, size = %d, sndbuf = %d\n",
                         sk_wmem_alloc_get(sk), size, sk->sk_sndbuf);
-               return NULL;
+               return false;
        }
-       while (!(skb = alloc_skb(size, GFP_KERNEL)))
-               schedule();
-       pr_debug("%d += %d\n", sk_wmem_alloc_get(sk), skb->truesize);
-       atomic_add(skb->truesize, &sk->sk_wmem_alloc);
-       return skb;
+       return true;
 }
 
 static void vcc_sock_destruct(struct sock *sk)
@@ -606,7 +601,7 @@ int vcc_sendmsg(struct socket *sock, struct msghdr *m, size_t size)
        eff = (size+3) & ~3; /* align to word boundary */
        prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
        error = 0;
-       while (!(skb = alloc_tx(vcc, eff))) {
+       while (!vcc_tx_ready(vcc, eff)) {
                if (m->msg_flags & MSG_DONTWAIT) {
                        error = -EAGAIN;
                        break;
@@ -628,6 +623,15 @@ int vcc_sendmsg(struct socket *sock, struct msghdr *m, size_t size)
        finish_wait(sk_sleep(sk), &wait);
        if (error)
                goto out;
+
+       skb = alloc_skb(eff, GFP_KERNEL);
+       if (!skb) {
+               error = -ENOMEM;
+               goto out;
+       }
+       pr_debug("%d += %d\n", sk_wmem_alloc_get(sk), skb->truesize);
+       atomic_add(skb->truesize, &sk->sk_wmem_alloc);
+
        skb->dev = NULL; /* for paths shared with net_device interfaces */
        ATM_SKB(skb)->atm_options = vcc->atm_options;
        if (!copy_from_iter_full(skb_put(skb, size), size, &m->msg_iter)) {