diff options
author | Divy Le Ray <divy@chelsio.com> | 2008-10-29 01:40:32 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2008-10-31 00:52:51 -0400 |
commit | 04ecb07241d8731b16490f10bec6ccedf5cfc792 (patch) | |
tree | 8bdf9f2d8673d328979a100b002c7d22ae676f8f /drivers/net/cxgb3/cxgb3_main.c | |
parent | bc79fc8409b3dccbde072e8113cc1fb3fd876fc5 (diff) |
cxgb3 - enable lro control through ethtool
Implement ethtool's get_flags and set_flags methods.
It enables ethtool to control the LRO settings.
Signed-off-by: Divy Le Ray <divy@chelsio.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/net/cxgb3/cxgb3_main.c')
-rw-r--r-- | drivers/net/cxgb3/cxgb3_main.c | 69 |
1 files changed, 57 insertions, 12 deletions
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 1ace41a13ac3..e1746eeb34a4 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c | |||
@@ -494,6 +494,36 @@ static void enable_all_napi(struct adapter *adap) | |||
494 | } | 494 | } |
495 | 495 | ||
496 | /** | 496 | /** |
497 | * set_qset_lro - Turn a queue set's LRO capability on and off | ||
498 | * @dev: the device the qset is attached to | ||
499 | * @qset_idx: the queue set index | ||
500 | * @val: the LRO switch | ||
501 | * | ||
502 | * Sets LRO on or off for a particular queue set. | ||
503 | * the device's features flag is updated to reflect the LRO | ||
504 | * capability when all queues belonging to the device are | ||
505 | * in the same state. | ||
506 | */ | ||
507 | static void set_qset_lro(struct net_device *dev, int qset_idx, int val) | ||
508 | { | ||
509 | struct port_info *pi = netdev_priv(dev); | ||
510 | struct adapter *adapter = pi->adapter; | ||
511 | int i, lro_on = 1; | ||
512 | |||
513 | adapter->params.sge.qset[qset_idx].lro = !!val; | ||
514 | adapter->sge.qs[qset_idx].lro_enabled = !!val; | ||
515 | |||
516 | /* let ethtool report LRO on only if all queues are LRO enabled */ | ||
517 | for (i = pi->first_qset; i < pi->first_qset + pi->nqsets; ++i) | ||
518 | lro_on &= adapter->params.sge.qset[i].lro; | ||
519 | |||
520 | if (lro_on) | ||
521 | dev->features |= NETIF_F_LRO; | ||
522 | else | ||
523 | dev->features &= ~NETIF_F_LRO; | ||
524 | } | ||
525 | |||
526 | /** | ||
497 | * setup_sge_qsets - configure SGE Tx/Rx/response queues | 527 | * setup_sge_qsets - configure SGE Tx/Rx/response queues |
498 | * @adap: the adapter | 528 | * @adap: the adapter |
499 | * | 529 | * |
@@ -516,8 +546,7 @@ static int setup_sge_qsets(struct adapter *adap) | |||
516 | pi->qs = &adap->sge.qs[pi->first_qset]; | 546 | pi->qs = &adap->sge.qs[pi->first_qset]; |
517 | for (j = pi->first_qset; j < pi->first_qset + pi->nqsets; | 547 | for (j = pi->first_qset; j < pi->first_qset + pi->nqsets; |
518 | ++j, ++qset_idx) { | 548 | ++j, ++qset_idx) { |
519 | if (!pi->rx_csum_offload) | 549 | set_qset_lro(dev, qset_idx, pi->rx_csum_offload); |
520 | adap->params.sge.qset[qset_idx].lro = 0; | ||
521 | err = t3_sge_alloc_qset(adap, qset_idx, 1, | 550 | err = t3_sge_alloc_qset(adap, qset_idx, 1, |
522 | (adap->flags & USING_MSIX) ? qset_idx + 1 : | 551 | (adap->flags & USING_MSIX) ? qset_idx + 1 : |
523 | irq_idx, | 552 | irq_idx, |
@@ -1632,13 +1661,10 @@ static int set_rx_csum(struct net_device *dev, u32 data) | |||
1632 | 1661 | ||
1633 | p->rx_csum_offload = data; | 1662 | p->rx_csum_offload = data; |
1634 | if (!data) { | 1663 | if (!data) { |
1635 | struct adapter *adap = p->adapter; | ||
1636 | int i; | 1664 | int i; |
1637 | 1665 | ||
1638 | for (i = p->first_qset; i < p->first_qset + p->nqsets; i++) { | 1666 | for (i = p->first_qset; i < p->first_qset + p->nqsets; i++) |
1639 | adap->params.sge.qset[i].lro = 0; | 1667 | set_qset_lro(dev, i, 0); |
1640 | adap->sge.qs[i].lro_enabled = 0; | ||
1641 | } | ||
1642 | } | 1668 | } |
1643 | return 0; | 1669 | return 0; |
1644 | } | 1670 | } |
@@ -1793,6 +1819,25 @@ static void get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) | |||
1793 | memset(&wol->sopass, 0, sizeof(wol->sopass)); | 1819 | memset(&wol->sopass, 0, sizeof(wol->sopass)); |
1794 | } | 1820 | } |
1795 | 1821 | ||
1822 | static int cxgb3_set_flags(struct net_device *dev, u32 data) | ||
1823 | { | ||
1824 | struct port_info *pi = netdev_priv(dev); | ||
1825 | int i; | ||
1826 | |||
1827 | if (data & ETH_FLAG_LRO) { | ||
1828 | if (!pi->rx_csum_offload) | ||
1829 | return -EINVAL; | ||
1830 | |||
1831 | for (i = pi->first_qset; i < pi->first_qset + pi->nqsets; i++) | ||
1832 | set_qset_lro(dev, i, 1); | ||
1833 | |||
1834 | } else | ||
1835 | for (i = pi->first_qset; i < pi->first_qset + pi->nqsets; i++) | ||
1836 | set_qset_lro(dev, i, 0); | ||
1837 | |||
1838 | return 0; | ||
1839 | } | ||
1840 | |||
1796 | static const struct ethtool_ops cxgb_ethtool_ops = { | 1841 | static const struct ethtool_ops cxgb_ethtool_ops = { |
1797 | .get_settings = get_settings, | 1842 | .get_settings = get_settings, |
1798 | .set_settings = set_settings, | 1843 | .set_settings = set_settings, |
@@ -1822,6 +1867,8 @@ static const struct ethtool_ops cxgb_ethtool_ops = { | |||
1822 | .get_regs = get_regs, | 1867 | .get_regs = get_regs, |
1823 | .get_wol = get_wol, | 1868 | .get_wol = get_wol, |
1824 | .set_tso = ethtool_op_set_tso, | 1869 | .set_tso = ethtool_op_set_tso, |
1870 | .get_flags = ethtool_op_get_flags, | ||
1871 | .set_flags = cxgb3_set_flags, | ||
1825 | }; | 1872 | }; |
1826 | 1873 | ||
1827 | static int in_range(int val, int lo, int hi) | 1874 | static int in_range(int val, int lo, int hi) |
@@ -1938,11 +1985,9 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr) | |||
1938 | } | 1985 | } |
1939 | } | 1986 | } |
1940 | } | 1987 | } |
1941 | if (t.lro >= 0) { | 1988 | if (t.lro >= 0) |
1942 | struct sge_qset *qs = &adapter->sge.qs[t.qset_idx]; | 1989 | set_qset_lro(dev, t.qset_idx, t.lro); |
1943 | q->lro = t.lro; | 1990 | |
1944 | qs->lro_enabled = t.lro; | ||
1945 | } | ||
1946 | break; | 1991 | break; |
1947 | } | 1992 | } |
1948 | case CHELSIO_GET_QSET_PARAMS:{ | 1993 | case CHELSIO_GET_QSET_PARAMS:{ |