summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRémi Denis-Courmont <remi.denis-courmont@nokia.com>2008-12-18 00:48:50 +0100
committerDavid S. Miller <davem@davemloft.net>2008-12-18 00:48:50 +0100
commit893873f3965ae0173a9315534bec7628162d2243 (patch)
treea68217bad43abcebd4bb19af4dd8d50c10940f8a
parentPhonet: use atomic for packet TX window (diff)
downloadlinux-893873f3965ae0173a9315534bec7628162d2243.tar.xz
linux-893873f3965ae0173a9315534bec7628162d2243.zip
Phonet: get rid of deferred work on the transmission path
Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/phonet/pep-gprs.c91
1 files changed, 28 insertions, 63 deletions
diff --git a/net/phonet/pep-gprs.c b/net/phonet/pep-gprs.c
index a2873203dff2..b0ceac2d6cd1 100644
--- a/net/phonet/pep-gprs.c
+++ b/net/phonet/pep-gprs.c
@@ -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
*/
@@ -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))
+ 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++;
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;
+ } 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);
+ if (!pep_writeable(sk))
+ netif_stop_queue(dev);
+ return 0;
}
static int gprs_set_mtu(struct net_device *dev, int new_mtu)
@@ -297,11 +267,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 +295,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;