aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2010-07-07 18:59:38 -0400
committerDavid S. Miller <davem@davemloft.net>2010-07-07 18:59:38 -0400
commit597e608a8492d662736c9bc6aa507dbf1cadc17d (patch)
tree6c330cdd0a4809f67dd191b37e34f5b4318cef78 /net/core
parentacbc0f039ff4b93da737c91937b7c70018ded39f (diff)
parent33b665eeeb85956ccbdf31c4c31a4e2a31133c44 (diff)
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Diffstat (limited to 'net/core')
-rw-r--r--net/core/dev.c18
-rw-r--r--net/core/ethtool.c41
2 files changed, 48 insertions, 11 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 92482d7a87a9..eb4201cf9c8c 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1550,6 +1550,24 @@ static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
1550 rcu_read_unlock(); 1550 rcu_read_unlock();
1551} 1551}
1552 1552
1553/*
1554 * Routine to help set real_num_tx_queues. To avoid skbs mapped to queues
1555 * greater then real_num_tx_queues stale skbs on the qdisc must be flushed.
1556 */
1557void netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq)
1558{
1559 unsigned int real_num = dev->real_num_tx_queues;
1560
1561 if (unlikely(txq > dev->num_tx_queues))
1562 ;
1563 else if (txq > real_num)
1564 dev->real_num_tx_queues = txq;
1565 else if (txq < real_num) {
1566 dev->real_num_tx_queues = txq;
1567 qdisc_reset_all_tx_gt(dev, txq);
1568 }
1569}
1570EXPORT_SYMBOL(netif_set_real_num_tx_queues);
1553 1571
1554static inline void __netif_reschedule(struct Qdisc *q) 1572static inline void __netif_reschedule(struct Qdisc *q)
1555{ 1573{
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 072d1d3796cb..7a85367b3c2f 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -300,23 +300,33 @@ out:
300} 300}
301 301
302static noinline_for_stack int ethtool_set_rxnfc(struct net_device *dev, 302static noinline_for_stack int ethtool_set_rxnfc(struct net_device *dev,
303 void __user *useraddr) 303 u32 cmd, void __user *useraddr)
304{ 304{
305 struct ethtool_rxnfc cmd; 305 struct ethtool_rxnfc info;
306 size_t info_size = sizeof(info);
306 307
307 if (!dev->ethtool_ops->set_rxnfc) 308 if (!dev->ethtool_ops->set_rxnfc)
308 return -EOPNOTSUPP; 309 return -EOPNOTSUPP;
309 310
310 if (copy_from_user(&cmd, useraddr, sizeof(cmd))) 311 /* struct ethtool_rxnfc was originally defined for
312 * ETHTOOL_{G,S}RXFH with only the cmd, flow_type and data
313 * members. User-space might still be using that
314 * definition. */
315 if (cmd == ETHTOOL_SRXFH)
316 info_size = (offsetof(struct ethtool_rxnfc, data) +
317 sizeof(info.data));
318
319 if (copy_from_user(&info, useraddr, info_size))
311 return -EFAULT; 320 return -EFAULT;
312 321
313 return dev->ethtool_ops->set_rxnfc(dev, &cmd); 322 return dev->ethtool_ops->set_rxnfc(dev, &info);
314} 323}
315 324
316static noinline_for_stack int ethtool_get_rxnfc(struct net_device *dev, 325static noinline_for_stack int ethtool_get_rxnfc(struct net_device *dev,
317 void __user *useraddr) 326 u32 cmd, void __user *useraddr)
318{ 327{
319 struct ethtool_rxnfc info; 328 struct ethtool_rxnfc info;
329 size_t info_size = sizeof(info);
320 const struct ethtool_ops *ops = dev->ethtool_ops; 330 const struct ethtool_ops *ops = dev->ethtool_ops;
321 int ret; 331 int ret;
322 void *rule_buf = NULL; 332 void *rule_buf = NULL;
@@ -324,13 +334,22 @@ static noinline_for_stack int ethtool_get_rxnfc(struct net_device *dev,
324 if (!ops->get_rxnfc) 334 if (!ops->get_rxnfc)
325 return -EOPNOTSUPP; 335 return -EOPNOTSUPP;
326 336
327 if (copy_from_user(&info, useraddr, sizeof(info))) 337 /* struct ethtool_rxnfc was originally defined for
338 * ETHTOOL_{G,S}RXFH with only the cmd, flow_type and data
339 * members. User-space might still be using that
340 * definition. */
341 if (cmd == ETHTOOL_GRXFH)
342 info_size = (offsetof(struct ethtool_rxnfc, data) +
343 sizeof(info.data));
344
345 if (copy_from_user(&info, useraddr, info_size))
328 return -EFAULT; 346 return -EFAULT;
329 347
330 if (info.cmd == ETHTOOL_GRXCLSRLALL) { 348 if (info.cmd == ETHTOOL_GRXCLSRLALL) {
331 if (info.rule_cnt > 0) { 349 if (info.rule_cnt > 0) {
332 rule_buf = kmalloc(info.rule_cnt * sizeof(u32), 350 if (info.rule_cnt <= KMALLOC_MAX_SIZE / sizeof(u32))
333 GFP_USER); 351 rule_buf = kmalloc(info.rule_cnt * sizeof(u32),
352 GFP_USER);
334 if (!rule_buf) 353 if (!rule_buf)
335 return -ENOMEM; 354 return -ENOMEM;
336 } 355 }
@@ -341,7 +360,7 @@ static noinline_for_stack int ethtool_get_rxnfc(struct net_device *dev,
341 goto err_out; 360 goto err_out;
342 361
343 ret = -EFAULT; 362 ret = -EFAULT;
344 if (copy_to_user(useraddr, &info, sizeof(info))) 363 if (copy_to_user(useraddr, &info, info_size))
345 goto err_out; 364 goto err_out;
346 365
347 if (rule_buf) { 366 if (rule_buf) {
@@ -1572,12 +1591,12 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
1572 case ETHTOOL_GRXCLSRLCNT: 1591 case ETHTOOL_GRXCLSRLCNT:
1573 case ETHTOOL_GRXCLSRULE: 1592 case ETHTOOL_GRXCLSRULE:
1574 case ETHTOOL_GRXCLSRLALL: 1593 case ETHTOOL_GRXCLSRLALL:
1575 rc = ethtool_get_rxnfc(dev, useraddr); 1594 rc = ethtool_get_rxnfc(dev, ethcmd, useraddr);
1576 break; 1595 break;
1577 case ETHTOOL_SRXFH: 1596 case ETHTOOL_SRXFH:
1578 case ETHTOOL_SRXCLSRLDEL: 1597 case ETHTOOL_SRXCLSRLDEL:
1579 case ETHTOOL_SRXCLSRLINS: 1598 case ETHTOOL_SRXCLSRLINS:
1580 rc = ethtool_set_rxnfc(dev, useraddr); 1599 rc = ethtool_set_rxnfc(dev, ethcmd, useraddr);
1581 break; 1600 break;
1582 case ETHTOOL_GGRO: 1601 case ETHTOOL_GGRO:
1583 rc = ethtool_get_gro(dev, useraddr); 1602 rc = ethtool_get_gro(dev, useraddr);