diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2014-03-27 18:37:28 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-03-29 17:58:37 -0400 |
commit | 944e294857033dbe519a136cad05dc4e2570874e (patch) | |
tree | d7d3f8a8890fc8ad488cc6e1456287416850d94d /net | |
parent | a8779ec1c5e60548b7b661a8d74a8cecf7775690 (diff) |
netpoll: Only call ndo_start_xmit from a single place
Factor out the code that needs to surround ndo_start_xmit
from netpoll_send_skb_on_dev into netpoll_start_xmit.
It is an unfortunate fact that as the netpoll code has been maintained
the primary call site ndo_start_xmit learned how to handle vlans
and timestamps but the second call of ndo_start_xmit in queue_process
did not.
With the introduction of netpoll_start_xmit this associated logic now
happens at both call sites of ndo_start_xmit and should make it easy
for that to continue into the future.
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/core/netpoll.c | 61 |
1 files changed, 36 insertions, 25 deletions
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 2c6379da295c..e2492d176ae7 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
@@ -69,6 +69,37 @@ module_param(carrier_timeout, uint, 0644); | |||
69 | #define np_notice(np, fmt, ...) \ | 69 | #define np_notice(np, fmt, ...) \ |
70 | pr_notice("%s: " fmt, np->name, ##__VA_ARGS__) | 70 | pr_notice("%s: " fmt, np->name, ##__VA_ARGS__) |
71 | 71 | ||
72 | static int netpoll_start_xmit(struct sk_buff *skb, struct net_device *dev, | ||
73 | struct netdev_queue *txq) | ||
74 | { | ||
75 | const struct net_device_ops *ops = dev->netdev_ops; | ||
76 | int status = NETDEV_TX_OK; | ||
77 | netdev_features_t features; | ||
78 | |||
79 | features = netif_skb_features(skb); | ||
80 | |||
81 | if (vlan_tx_tag_present(skb) && | ||
82 | !vlan_hw_offload_capable(features, skb->vlan_proto)) { | ||
83 | skb = __vlan_put_tag(skb, skb->vlan_proto, | ||
84 | vlan_tx_tag_get(skb)); | ||
85 | if (unlikely(!skb)) { | ||
86 | /* This is actually a packet drop, but we | ||
87 | * don't want the code that calls this | ||
88 | * function to try and operate on a NULL skb. | ||
89 | */ | ||
90 | goto out; | ||
91 | } | ||
92 | skb->vlan_tci = 0; | ||
93 | } | ||
94 | |||
95 | status = ops->ndo_start_xmit(skb, dev); | ||
96 | if (status == NETDEV_TX_OK) | ||
97 | txq_trans_update(txq); | ||
98 | |||
99 | out: | ||
100 | return status; | ||
101 | } | ||
102 | |||
72 | static void queue_process(struct work_struct *work) | 103 | static void queue_process(struct work_struct *work) |
73 | { | 104 | { |
74 | struct netpoll_info *npinfo = | 105 | struct netpoll_info *npinfo = |
@@ -78,7 +109,6 @@ static void queue_process(struct work_struct *work) | |||
78 | 109 | ||
79 | while ((skb = skb_dequeue(&npinfo->txq))) { | 110 | while ((skb = skb_dequeue(&npinfo->txq))) { |
80 | struct net_device *dev = skb->dev; | 111 | struct net_device *dev = skb->dev; |
81 | const struct net_device_ops *ops = dev->netdev_ops; | ||
82 | struct netdev_queue *txq; | 112 | struct netdev_queue *txq; |
83 | 113 | ||
84 | if (!netif_device_present(dev) || !netif_running(dev)) { | 114 | if (!netif_device_present(dev) || !netif_running(dev)) { |
@@ -91,7 +121,7 @@ static void queue_process(struct work_struct *work) | |||
91 | local_irq_save(flags); | 121 | local_irq_save(flags); |
92 | __netif_tx_lock(txq, smp_processor_id()); | 122 | __netif_tx_lock(txq, smp_processor_id()); |
93 | if (netif_xmit_frozen_or_stopped(txq) || | 123 | if (netif_xmit_frozen_or_stopped(txq) || |
94 | ops->ndo_start_xmit(skb, dev) != NETDEV_TX_OK) { | 124 | netpoll_start_xmit(skb, dev, txq) != NETDEV_TX_OK) { |
95 | skb_queue_head(&npinfo->txq, skb); | 125 | skb_queue_head(&npinfo->txq, skb); |
96 | __netif_tx_unlock(txq); | 126 | __netif_tx_unlock(txq); |
97 | local_irq_restore(flags); | 127 | local_irq_restore(flags); |
@@ -295,7 +325,6 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb, | |||
295 | { | 325 | { |
296 | int status = NETDEV_TX_BUSY; | 326 | int status = NETDEV_TX_BUSY; |
297 | unsigned long tries; | 327 | unsigned long tries; |
298 | const struct net_device_ops *ops = dev->netdev_ops; | ||
299 | /* It is up to the caller to keep npinfo alive. */ | 328 | /* It is up to the caller to keep npinfo alive. */ |
300 | struct netpoll_info *npinfo; | 329 | struct netpoll_info *npinfo; |
301 | 330 | ||
@@ -317,27 +346,9 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb, | |||
317 | for (tries = jiffies_to_usecs(1)/USEC_PER_POLL; | 346 | for (tries = jiffies_to_usecs(1)/USEC_PER_POLL; |
318 | tries > 0; --tries) { | 347 | tries > 0; --tries) { |
319 | if (__netif_tx_trylock(txq)) { | 348 | if (__netif_tx_trylock(txq)) { |
320 | if (!netif_xmit_stopped(txq)) { | 349 | if (!netif_xmit_stopped(txq)) |
321 | if (vlan_tx_tag_present(skb) && | 350 | status = netpoll_start_xmit(skb, dev, txq); |
322 | !vlan_hw_offload_capable(netif_skb_features(skb), | 351 | |
323 | skb->vlan_proto)) { | ||
324 | skb = __vlan_put_tag(skb, skb->vlan_proto, vlan_tx_tag_get(skb)); | ||
325 | if (unlikely(!skb)) { | ||
326 | /* This is actually a packet drop, but we | ||
327 | * don't want the code at the end of this | ||
328 | * function to try and re-queue a NULL skb. | ||
329 | */ | ||
330 | status = NETDEV_TX_OK; | ||
331 | goto unlock_txq; | ||
332 | } | ||
333 | skb->vlan_tci = 0; | ||
334 | } | ||
335 | |||
336 | status = ops->ndo_start_xmit(skb, dev); | ||
337 | if (status == NETDEV_TX_OK) | ||
338 | txq_trans_update(txq); | ||
339 | } | ||
340 | unlock_txq: | ||
341 | __netif_tx_unlock(txq); | 352 | __netif_tx_unlock(txq); |
342 | 353 | ||
343 | if (status == NETDEV_TX_OK) | 354 | if (status == NETDEV_TX_OK) |
@@ -353,7 +364,7 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb, | |||
353 | 364 | ||
354 | WARN_ONCE(!irqs_disabled(), | 365 | WARN_ONCE(!irqs_disabled(), |
355 | "netpoll_send_skb_on_dev(): %s enabled interrupts in poll (%pF)\n", | 366 | "netpoll_send_skb_on_dev(): %s enabled interrupts in poll (%pF)\n", |
356 | dev->name, ops->ndo_start_xmit); | 367 | dev->name, dev->netdev_ops->ndo_start_xmit); |
357 | 368 | ||
358 | } | 369 | } |
359 | 370 | ||