diff options
author | David Woodhouse <dwmw2@infradead.org> | 2012-03-25 20:03:42 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-04-03 17:31:38 -0400 |
commit | e675f0cc9a872fd152edc0c77acfed19bf28b81e (patch) | |
tree | 244c4488575cc19bd882ad00c2d6852db5bcbe98 /drivers/net/ppp | |
parent | 2def16ae6b0c77571200f18ba4be049b03d75579 (diff) |
ppp: Don't stop and restart queue on every TX packet
For every transmitted packet, ppp_start_xmit() will stop the netdev
queue and then, if appropriate, restart it. This causes the TX softirq
to run, entirely gratuitously.
This is "only" a waste of CPU time in the normal case, but it's actively
harmful when the PPP device is a TEQL slave — the wakeup will cause the
offending device to receive the next TX packet from the TEQL queue, when
it *should* have gone to the next slave in the list. We end up seeing
large bursts of packets on just *one* slave device, rather than using
the full available bandwidth over all slaves.
This patch fixes the problem by *not* unconditionally stopping the queue
in ppp_start_xmit(). It adds a return value from ppp_xmit_process()
which indicates whether the queue should be stopped or not.
It *doesn't* remove the call to netif_wake_queue() from
ppp_xmit_process(), because other code paths (especially from
ppp_output_wakeup()) need it there and it's messy to push it out to the
other callers to do it based on the return value. So we leave it in
place — it's a no-op in the case where the queue wasn't stopped, so it's
harmless in the TX path.
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ppp')
-rw-r--r-- | drivers/net/ppp/ppp_generic.c | 14 |
1 files changed, 9 insertions, 5 deletions
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index 159da2905fe9..33f8c51968b6 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c | |||
@@ -235,7 +235,7 @@ struct ppp_net { | |||
235 | /* Prototypes. */ | 235 | /* Prototypes. */ |
236 | static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf, | 236 | static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf, |
237 | struct file *file, unsigned int cmd, unsigned long arg); | 237 | struct file *file, unsigned int cmd, unsigned long arg); |
238 | static void ppp_xmit_process(struct ppp *ppp); | 238 | static int ppp_xmit_process(struct ppp *ppp); |
239 | static void ppp_send_frame(struct ppp *ppp, struct sk_buff *skb); | 239 | static void ppp_send_frame(struct ppp *ppp, struct sk_buff *skb); |
240 | static void ppp_push(struct ppp *ppp); | 240 | static void ppp_push(struct ppp *ppp); |
241 | static void ppp_channel_push(struct channel *pch); | 241 | static void ppp_channel_push(struct channel *pch); |
@@ -968,9 +968,9 @@ ppp_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
968 | proto = npindex_to_proto[npi]; | 968 | proto = npindex_to_proto[npi]; |
969 | put_unaligned_be16(proto, pp); | 969 | put_unaligned_be16(proto, pp); |
970 | 970 | ||
971 | netif_stop_queue(dev); | ||
972 | skb_queue_tail(&ppp->file.xq, skb); | 971 | skb_queue_tail(&ppp->file.xq, skb); |
973 | ppp_xmit_process(ppp); | 972 | if (!ppp_xmit_process(ppp)) |
973 | netif_stop_queue(dev); | ||
974 | return NETDEV_TX_OK; | 974 | return NETDEV_TX_OK; |
975 | 975 | ||
976 | outf: | 976 | outf: |
@@ -1048,10 +1048,11 @@ static void ppp_setup(struct net_device *dev) | |||
1048 | * Called to do any work queued up on the transmit side | 1048 | * Called to do any work queued up on the transmit side |
1049 | * that can now be done. | 1049 | * that can now be done. |
1050 | */ | 1050 | */ |
1051 | static void | 1051 | static int |
1052 | ppp_xmit_process(struct ppp *ppp) | 1052 | ppp_xmit_process(struct ppp *ppp) |
1053 | { | 1053 | { |
1054 | struct sk_buff *skb; | 1054 | struct sk_buff *skb; |
1055 | int ret = 0; | ||
1055 | 1056 | ||
1056 | ppp_xmit_lock(ppp); | 1057 | ppp_xmit_lock(ppp); |
1057 | if (!ppp->closing) { | 1058 | if (!ppp->closing) { |
@@ -1061,10 +1062,13 @@ ppp_xmit_process(struct ppp *ppp) | |||
1061 | ppp_send_frame(ppp, skb); | 1062 | ppp_send_frame(ppp, skb); |
1062 | /* If there's no work left to do, tell the core net | 1063 | /* If there's no work left to do, tell the core net |
1063 | code that we can accept some more. */ | 1064 | code that we can accept some more. */ |
1064 | if (!ppp->xmit_pending && !skb_peek(&ppp->file.xq)) | 1065 | if (!ppp->xmit_pending && !skb_peek(&ppp->file.xq)) { |
1065 | netif_wake_queue(ppp->dev); | 1066 | netif_wake_queue(ppp->dev); |
1067 | ret = 1; | ||
1068 | } | ||
1066 | } | 1069 | } |
1067 | ppp_xmit_unlock(ppp); | 1070 | ppp_xmit_unlock(ppp); |
1071 | return ret; | ||
1068 | } | 1072 | } |
1069 | 1073 | ||
1070 | static inline struct sk_buff * | 1074 | static inline struct sk_buff * |