netfilter: nf_conntrack: death_by_timeout() fix
[safe/jmp/linux-2.6] / net / phonet / pep-gprs.c
index a287320..480839d 100644 (file)
@@ -41,11 +41,6 @@ struct gprs_dev {
        void                    (*old_write_space)(struct sock *);
 
        struct net_device       *dev;
-
-       struct sk_buff_head     tx_queue;
-       struct work_struct      tx_work;
-       spinlock_t              tx_lock;
-       unsigned                tx_max;
 };
 
 static __be16 gprs_type_trans(struct sk_buff *skb)
@@ -66,6 +61,14 @@ static __be16 gprs_type_trans(struct sk_buff *skb)
        return htons(0);
 }
 
+static void gprs_writeable(struct gprs_dev *gp)
+{
+       struct net_device *dev = gp->dev;
+
+       if (pep_writeable(gp->sk))
+               netif_wake_queue(dev);
+}
+
 /*
  * Socket callbacks
  */
@@ -112,10 +115,10 @@ static int gprs_recv(struct gprs_dev *gp, struct sk_buff *skb)
                rskb->truesize += rskb->len;
 
                /* Avoid nested fragments */
-               for (fs = skb_shinfo(skb)->frag_list; fs; fs = fs->next)
+               skb_walk_frags(skb, fs)
                        flen += fs->len;
                skb->next = skb_shinfo(skb)->frag_list;
-               skb_shinfo(skb)->frag_list = NULL;
+               skb_frag_list_init(skb);
                skb->len -= flen;
                skb->data_len -= flen;
                skb->truesize -= flen;
@@ -157,14 +160,9 @@ static void gprs_data_ready(struct sock *sk, int len)
 static void gprs_write_space(struct sock *sk)
 {
        struct gprs_dev *gp = sk->sk_user_data;
-       struct net_device *dev = gp->dev;
-       unsigned credits = pep_writeable(sk);
 
-       spin_lock_bh(&gp->tx_lock);
-       gp->tx_max = credits;
-       if (credits > skb_queue_len(&gp->tx_queue) && netif_running(dev))
-               netif_wake_queue(dev);
-       spin_unlock_bh(&gp->tx_lock);
+       if (netif_running(gp->dev))
+               gprs_writeable(gp);
 }
 
 /*
@@ -175,22 +173,21 @@ static int gprs_open(struct net_device *dev)
 {
        struct gprs_dev *gp = netdev_priv(dev);
 
-       gprs_write_space(gp->sk);
+       gprs_writeable(gp);
        return 0;
 }
 
 static int gprs_close(struct net_device *dev)
 {
-       struct gprs_dev *gp = netdev_priv(dev);
-
        netif_stop_queue(dev);
-       flush_work(&gp->tx_work);
        return 0;
 }
 
 static int gprs_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct gprs_dev *gp = netdev_priv(dev);
+       struct sock *sk = gp->sk;
+       int len, err;
 
        switch (skb->protocol) {
        case  htons(ETH_P_IP):
@@ -201,51 +198,24 @@ static int gprs_xmit(struct sk_buff *skb, struct net_device *dev)
                return 0;
        }
 
-       spin_lock(&gp->tx_lock);
-       if (likely(skb_queue_len(&gp->tx_queue) < gp->tx_max)) {
-               skb_queue_tail(&gp->tx_queue, skb);
-               skb = NULL;
-       }
-       if (skb_queue_len(&gp->tx_queue) >= gp->tx_max)
-               netif_stop_queue(dev);
-       spin_unlock(&gp->tx_lock);
-
-       schedule_work(&gp->tx_work);
-       if (unlikely(skb))
-               dev_kfree_skb(skb);
-       return 0;
-}
-
-static void gprs_tx(struct work_struct *work)
-{
-       struct gprs_dev *gp = container_of(work, struct gprs_dev, tx_work);
-       struct net_device *dev = gp->dev;
-       struct sock *sk = gp->sk;
-       struct sk_buff *skb;
-
-       while ((skb = skb_dequeue(&gp->tx_queue)) != NULL) {
-               int err;
-
-               dev->stats.tx_bytes += skb->len;
+       skb_orphan(skb);
+       skb_set_owner_w(skb, sk);
+       len = skb->len;
+       err = pep_write(sk, skb);
+       if (err) {
+               LIMIT_NETDEBUG(KERN_WARNING"%s: TX error (%d)\n",
+                               dev->name, err);
+               dev->stats.tx_aborted_errors++;
+               dev->stats.tx_errors++;
+       } else {
                dev->stats.tx_packets++;
-
-               skb_orphan(skb);
-               skb_set_owner_w(skb, sk);
-
-               lock_sock(sk);
-               err = pep_write(sk, skb);
-               if (err) {
-                       LIMIT_NETDEBUG(KERN_WARNING"%s: TX error (%d)\n",
-                                       dev->name, err);
-                       dev->stats.tx_aborted_errors++;
-                       dev->stats.tx_errors++;
-               }
-               release_sock(sk);
+               dev->stats.tx_bytes += len;
        }
 
-       lock_sock(sk);
-       gprs_write_space(sk);
-       release_sock(sk);
+       netif_stop_queue(dev);
+       if (pep_writeable(sk))
+               netif_wake_queue(dev);
+       return 0;
 }
 
 static int gprs_set_mtu(struct net_device *dev, int new_mtu)
@@ -257,6 +227,13 @@ static int gprs_set_mtu(struct net_device *dev, int new_mtu)
        return 0;
 }
 
+static const struct net_device_ops gprs_netdev_ops = {
+       .ndo_open       = gprs_open,
+       .ndo_stop       = gprs_close,
+       .ndo_start_xmit = gprs_xmit,
+       .ndo_change_mtu = gprs_set_mtu,
+};
+
 static void gprs_setup(struct net_device *dev)
 {
        dev->features           = NETIF_F_FRAGLIST;
@@ -267,11 +244,8 @@ static void gprs_setup(struct net_device *dev)
        dev->addr_len           = 0;
        dev->tx_queue_len       = 10;
 
+       dev->netdev_ops         = &gprs_netdev_ops;
        dev->destructor         = free_netdev;
-       dev->open               = gprs_open;
-       dev->stop               = gprs_close;
-       dev->hard_start_xmit    = gprs_xmit; /* mandatory */
-       dev->change_mtu         = gprs_set_mtu;
 }
 
 /*
@@ -297,11 +271,8 @@ int gprs_attach(struct sock *sk)
        if (!dev)
                return -ENOMEM;
        gp = netdev_priv(dev);
+       gp->sk = sk;
        gp->dev = dev;
-       gp->tx_max = 0;
-       spin_lock_init(&gp->tx_lock);
-       skb_queue_head_init(&gp->tx_queue);
-       INIT_WORK(&gp->tx_work, gprs_tx);
 
        netif_stop_queue(dev);
        err = register_netdev(dev);
@@ -328,9 +299,7 @@ int gprs_attach(struct sock *sk)
        sk->sk_data_ready       = gprs_data_ready;
        sk->sk_write_space      = gprs_write_space;
        release_sock(sk);
-
        sock_hold(sk);
-       gp->sk = sk;
 
        printk(KERN_DEBUG"%s: attached\n", dev->name);
        return dev->ifindex;