diff options
| author | Ingo Molnar <mingo@elte.hu> | 2010-07-21 15:43:03 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2010-07-21 15:43:06 -0400 |
| commit | 9dcdbf7a33d9018ac5d45debcf261be648bdd56a (patch) | |
| tree | bbcc1a018f11ff76cd7ce174ef3ffe2c02da07ee /net/core | |
| parent | cc5edb0eb9ce892b530e34a5d110382483587942 (diff) | |
| parent | cd5b8f8755a89a57fc8c408d284b8b613f090345 (diff) | |
Merge branch 'linus' into perf/core
Merge reason: Pick up the latest perf fixes.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'net/core')
| -rw-r--r-- | net/core/dev.c | 38 | ||||
| -rw-r--r-- | net/core/ethtool.c | 41 | ||||
| -rw-r--r-- | net/core/neighbour.c | 5 |
3 files changed, 65 insertions, 19 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 2b3bf53bc687..0ea10f849be8 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -1553,6 +1553,24 @@ static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev) | |||
| 1553 | rcu_read_unlock(); | 1553 | rcu_read_unlock(); |
| 1554 | } | 1554 | } |
| 1555 | 1555 | ||
| 1556 | /* | ||
| 1557 | * Routine to help set real_num_tx_queues. To avoid skbs mapped to queues | ||
| 1558 | * greater then real_num_tx_queues stale skbs on the qdisc must be flushed. | ||
| 1559 | */ | ||
| 1560 | void netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq) | ||
| 1561 | { | ||
| 1562 | unsigned int real_num = dev->real_num_tx_queues; | ||
| 1563 | |||
| 1564 | if (unlikely(txq > dev->num_tx_queues)) | ||
| 1565 | ; | ||
| 1566 | else if (txq > real_num) | ||
| 1567 | dev->real_num_tx_queues = txq; | ||
| 1568 | else if (txq < real_num) { | ||
| 1569 | dev->real_num_tx_queues = txq; | ||
| 1570 | qdisc_reset_all_tx_gt(dev, txq); | ||
| 1571 | } | ||
| 1572 | } | ||
| 1573 | EXPORT_SYMBOL(netif_set_real_num_tx_queues); | ||
| 1556 | 1574 | ||
| 1557 | static inline void __netif_reschedule(struct Qdisc *q) | 1575 | static inline void __netif_reschedule(struct Qdisc *q) |
| 1558 | { | 1576 | { |
| @@ -1893,8 +1911,16 @@ static int dev_gso_segment(struct sk_buff *skb) | |||
| 1893 | */ | 1911 | */ |
| 1894 | static inline void skb_orphan_try(struct sk_buff *skb) | 1912 | static inline void skb_orphan_try(struct sk_buff *skb) |
| 1895 | { | 1913 | { |
| 1896 | if (!skb_tx(skb)->flags) | 1914 | struct sock *sk = skb->sk; |
| 1915 | |||
| 1916 | if (sk && !skb_tx(skb)->flags) { | ||
| 1917 | /* skb_tx_hash() wont be able to get sk. | ||
| 1918 | * We copy sk_hash into skb->rxhash | ||
| 1919 | */ | ||
| 1920 | if (!skb->rxhash) | ||
| 1921 | skb->rxhash = sk->sk_hash; | ||
| 1897 | skb_orphan(skb); | 1922 | skb_orphan(skb); |
| 1923 | } | ||
| 1898 | } | 1924 | } |
| 1899 | 1925 | ||
| 1900 | int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, | 1926 | int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, |
| @@ -1980,8 +2006,7 @@ u16 skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb) | |||
| 1980 | if (skb->sk && skb->sk->sk_hash) | 2006 | if (skb->sk && skb->sk->sk_hash) |
| 1981 | hash = skb->sk->sk_hash; | 2007 | hash = skb->sk->sk_hash; |
| 1982 | else | 2008 | else |
| 1983 | hash = (__force u16) skb->protocol; | 2009 | hash = (__force u16) skb->protocol ^ skb->rxhash; |
| 1984 | |||
| 1985 | hash = jhash_1word(hash, hashrnd); | 2010 | hash = jhash_1word(hash, hashrnd); |
| 1986 | 2011 | ||
| 1987 | return (u16) (((u64) hash * dev->real_num_tx_queues) >> 32); | 2012 | return (u16) (((u64) hash * dev->real_num_tx_queues) >> 32); |
| @@ -2004,12 +2029,11 @@ static inline u16 dev_cap_txqueue(struct net_device *dev, u16 queue_index) | |||
| 2004 | static struct netdev_queue *dev_pick_tx(struct net_device *dev, | 2029 | static struct netdev_queue *dev_pick_tx(struct net_device *dev, |
| 2005 | struct sk_buff *skb) | 2030 | struct sk_buff *skb) |
| 2006 | { | 2031 | { |
| 2007 | u16 queue_index; | 2032 | int queue_index; |
| 2008 | struct sock *sk = skb->sk; | 2033 | struct sock *sk = skb->sk; |
| 2009 | 2034 | ||
| 2010 | if (sk_tx_queue_recorded(sk)) { | 2035 | queue_index = sk_tx_queue_get(sk); |
| 2011 | queue_index = sk_tx_queue_get(sk); | 2036 | if (queue_index < 0) { |
| 2012 | } else { | ||
| 2013 | const struct net_device_ops *ops = dev->netdev_ops; | 2037 | const struct net_device_ops *ops = dev->netdev_ops; |
| 2014 | 2038 | ||
| 2015 | if (ops->ndo_select_queue) { | 2039 | if (ops->ndo_select_queue) { |
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index a0f4964033d2..75e4ffeb8cc9 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
| @@ -318,23 +318,33 @@ out: | |||
| 318 | } | 318 | } |
| 319 | 319 | ||
| 320 | static noinline_for_stack int ethtool_set_rxnfc(struct net_device *dev, | 320 | static noinline_for_stack int ethtool_set_rxnfc(struct net_device *dev, |
| 321 | void __user *useraddr) | 321 | u32 cmd, void __user *useraddr) |
| 322 | { | 322 | { |
| 323 | struct ethtool_rxnfc cmd; | 323 | struct ethtool_rxnfc info; |
| 324 | size_t info_size = sizeof(info); | ||
| 324 | 325 | ||
| 325 | if (!dev->ethtool_ops->set_rxnfc) | 326 | if (!dev->ethtool_ops->set_rxnfc) |
| 326 | return -EOPNOTSUPP; | 327 | return -EOPNOTSUPP; |
| 327 | 328 | ||
| 328 | if (copy_from_user(&cmd, useraddr, sizeof(cmd))) | 329 | /* struct ethtool_rxnfc was originally defined for |
| 330 | * ETHTOOL_{G,S}RXFH with only the cmd, flow_type and data | ||
| 331 | * members. User-space might still be using that | ||
| 332 | * definition. */ | ||
| 333 | if (cmd == ETHTOOL_SRXFH) | ||
| 334 | info_size = (offsetof(struct ethtool_rxnfc, data) + | ||
| 335 | sizeof(info.data)); | ||
| 336 | |||
| 337 | if (copy_from_user(&info, useraddr, info_size)) | ||
| 329 | return -EFAULT; | 338 | return -EFAULT; |
| 330 | 339 | ||
| 331 | return dev->ethtool_ops->set_rxnfc(dev, &cmd); | 340 | return dev->ethtool_ops->set_rxnfc(dev, &info); |
| 332 | } | 341 | } |
| 333 | 342 | ||
| 334 | static noinline_for_stack int ethtool_get_rxnfc(struct net_device *dev, | 343 | static noinline_for_stack int ethtool_get_rxnfc(struct net_device *dev, |
| 335 | void __user *useraddr) | 344 | u32 cmd, void __user *useraddr) |
| 336 | { | 345 | { |
| 337 | struct ethtool_rxnfc info; | 346 | struct ethtool_rxnfc info; |
| 347 | size_t info_size = sizeof(info); | ||
| 338 | const struct ethtool_ops *ops = dev->ethtool_ops; | 348 | const struct ethtool_ops *ops = dev->ethtool_ops; |
| 339 | int ret; | 349 | int ret; |
| 340 | void *rule_buf = NULL; | 350 | void *rule_buf = NULL; |
| @@ -342,13 +352,22 @@ static noinline_for_stack int ethtool_get_rxnfc(struct net_device *dev, | |||
| 342 | if (!ops->get_rxnfc) | 352 | if (!ops->get_rxnfc) |
| 343 | return -EOPNOTSUPP; | 353 | return -EOPNOTSUPP; |
| 344 | 354 | ||
| 345 | if (copy_from_user(&info, useraddr, sizeof(info))) | 355 | /* struct ethtool_rxnfc was originally defined for |
| 356 | * ETHTOOL_{G,S}RXFH with only the cmd, flow_type and data | ||
| 357 | * members. User-space might still be using that | ||
| 358 | * definition. */ | ||
| 359 | if (cmd == ETHTOOL_GRXFH) | ||
| 360 | info_size = (offsetof(struct ethtool_rxnfc, data) + | ||
| 361 | sizeof(info.data)); | ||
| 362 | |||
| 363 | if (copy_from_user(&info, useraddr, info_size)) | ||
| 346 | return -EFAULT; | 364 | return -EFAULT; |
| 347 | 365 | ||
| 348 | if (info.cmd == ETHTOOL_GRXCLSRLALL) { | 366 | if (info.cmd == ETHTOOL_GRXCLSRLALL) { |
| 349 | if (info.rule_cnt > 0) { | 367 | if (info.rule_cnt > 0) { |
| 350 | rule_buf = kmalloc(info.rule_cnt * sizeof(u32), | 368 | if (info.rule_cnt <= KMALLOC_MAX_SIZE / sizeof(u32)) |
| 351 | GFP_USER); | 369 | rule_buf = kmalloc(info.rule_cnt * sizeof(u32), |
| 370 | GFP_USER); | ||
| 352 | if (!rule_buf) | 371 | if (!rule_buf) |
| 353 | return -ENOMEM; | 372 | return -ENOMEM; |
| 354 | } | 373 | } |
| @@ -359,7 +378,7 @@ static noinline_for_stack int ethtool_get_rxnfc(struct net_device *dev, | |||
| 359 | goto err_out; | 378 | goto err_out; |
| 360 | 379 | ||
| 361 | ret = -EFAULT; | 380 | ret = -EFAULT; |
| 362 | if (copy_to_user(useraddr, &info, sizeof(info))) | 381 | if (copy_to_user(useraddr, &info, info_size)) |
| 363 | goto err_out; | 382 | goto err_out; |
| 364 | 383 | ||
| 365 | if (rule_buf) { | 384 | if (rule_buf) { |
| @@ -1516,12 +1535,12 @@ int dev_ethtool(struct net *net, struct ifreq *ifr) | |||
| 1516 | case ETHTOOL_GRXCLSRLCNT: | 1535 | case ETHTOOL_GRXCLSRLCNT: |
| 1517 | case ETHTOOL_GRXCLSRULE: | 1536 | case ETHTOOL_GRXCLSRULE: |
| 1518 | case ETHTOOL_GRXCLSRLALL: | 1537 | case ETHTOOL_GRXCLSRLALL: |
| 1519 | rc = ethtool_get_rxnfc(dev, useraddr); | 1538 | rc = ethtool_get_rxnfc(dev, ethcmd, useraddr); |
| 1520 | break; | 1539 | break; |
| 1521 | case ETHTOOL_SRXFH: | 1540 | case ETHTOOL_SRXFH: |
| 1522 | case ETHTOOL_SRXCLSRLDEL: | 1541 | case ETHTOOL_SRXCLSRLDEL: |
| 1523 | case ETHTOOL_SRXCLSRLINS: | 1542 | case ETHTOOL_SRXCLSRLINS: |
| 1524 | rc = ethtool_set_rxnfc(dev, useraddr); | 1543 | rc = ethtool_set_rxnfc(dev, ethcmd, useraddr); |
| 1525 | break; | 1544 | break; |
| 1526 | case ETHTOOL_GGRO: | 1545 | case ETHTOOL_GGRO: |
| 1527 | rc = ethtool_get_gro(dev, useraddr); | 1546 | rc = ethtool_get_gro(dev, useraddr); |
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 6ba1c0eece03..a4e0a7482c2b 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
| @@ -949,7 +949,10 @@ static void neigh_update_hhs(struct neighbour *neigh) | |||
| 949 | { | 949 | { |
| 950 | struct hh_cache *hh; | 950 | struct hh_cache *hh; |
| 951 | void (*update)(struct hh_cache*, const struct net_device*, const unsigned char *) | 951 | void (*update)(struct hh_cache*, const struct net_device*, const unsigned char *) |
| 952 | = neigh->dev->header_ops->cache_update; | 952 | = NULL; |
| 953 | |||
| 954 | if (neigh->dev->header_ops) | ||
| 955 | update = neigh->dev->header_ops->cache_update; | ||
| 953 | 956 | ||
| 954 | if (update) { | 957 | if (update) { |
| 955 | for (hh = neigh->hh; hh; hh = hh->hh_next) { | 958 | for (hh = neigh->hh; hh; hh = hh->hh_next) { |
