]>
Commit | Line | Data |
---|---|---|
00e5a55c BS |
1 | From: Divy Le Ray <divy@chelsio.com> |
2 | Date: Wed, 29 Oct 2008 05:40:32 +0000 (-0700) | |
3 | Subject: cxgb3 - enable lro control through ethtool | |
4 | Acked-by: Karsten Keil <kkeil@novell.com> | |
5 | Reference: bnc#446739 | |
6 | ||
7 | ||
8 | cxgb3 - enable lro control through ethtool | |
9 | ||
10 | Implement ethtool's get_flags and set_flags methods. | |
11 | It enables ethtool to control the LRO settings. | |
12 | ||
13 | Signed-off-by: Divy Le Ray <divy@chelsio.com> | |
14 | Signed-off-by: Jeff Garzik <jgarzik@redhat.com> | |
15 | --- | |
16 | ||
17 | Index: linux-2.6.27/drivers/net/cxgb3/cxgb3_main.c | |
18 | =================================================================== | |
19 | --- linux-2.6.27.orig/drivers/net/cxgb3/cxgb3_main.c | |
20 | +++ linux-2.6.27/drivers/net/cxgb3/cxgb3_main.c | |
21 | @@ -470,6 +470,36 @@ static void enable_all_napi(struct adapt | |
22 | } | |
23 | ||
24 | /** | |
25 | + * set_qset_lro - Turn a queue set's LRO capability on and off | |
26 | + * @dev: the device the qset is attached to | |
27 | + * @qset_idx: the queue set index | |
28 | + * @val: the LRO switch | |
29 | + * | |
30 | + * Sets LRO on or off for a particular queue set. | |
31 | + * the device's features flag is updated to reflect the LRO | |
32 | + * capability when all queues belonging to the device are | |
33 | + * in the same state. | |
34 | + */ | |
35 | +static void set_qset_lro(struct net_device *dev, int qset_idx, int val) | |
36 | +{ | |
37 | + struct port_info *pi = netdev_priv(dev); | |
38 | + struct adapter *adapter = pi->adapter; | |
39 | + int i, lro_on = 1; | |
40 | + | |
41 | + adapter->params.sge.qset[qset_idx].lro = !!val; | |
42 | + adapter->sge.qs[qset_idx].lro_enabled = !!val; | |
43 | + | |
44 | + /* let ethtool report LRO on only if all queues are LRO enabled */ | |
45 | + for (i = pi->first_qset; i < pi->first_qset + pi->nqsets; ++i) | |
46 | + lro_on &= adapter->params.sge.qset[i].lro; | |
47 | + | |
48 | + if (lro_on) | |
49 | + dev->features |= NETIF_F_LRO; | |
50 | + else | |
51 | + dev->features &= ~NETIF_F_LRO; | |
52 | +} | |
53 | + | |
54 | +/** | |
55 | * setup_sge_qsets - configure SGE Tx/Rx/response queues | |
56 | * @adap: the adapter | |
57 | * | |
58 | @@ -492,8 +522,7 @@ static int setup_sge_qsets(struct adapte | |
59 | pi->qs = &adap->sge.qs[pi->first_qset]; | |
60 | for (j = pi->first_qset; j < pi->first_qset + pi->nqsets; | |
61 | ++j, ++qset_idx) { | |
62 | - if (!pi->rx_csum_offload) | |
63 | - adap->params.sge.qset[qset_idx].lro = 0; | |
64 | + set_qset_lro(dev, qset_idx, pi->rx_csum_offload); | |
65 | err = t3_sge_alloc_qset(adap, qset_idx, 1, | |
66 | (adap->flags & USING_MSIX) ? qset_idx + 1 : | |
67 | irq_idx, | |
68 | @@ -1637,13 +1666,10 @@ static int set_rx_csum(struct net_device | |
69 | ||
70 | p->rx_csum_offload = data; | |
71 | if (!data) { | |
72 | - struct adapter *adap = p->adapter; | |
73 | int i; | |
74 | ||
75 | - for (i = p->first_qset; i < p->first_qset + p->nqsets; i++) { | |
76 | - adap->params.sge.qset[i].lro = 0; | |
77 | - adap->sge.qs[i].lro_enabled = 0; | |
78 | - } | |
79 | + for (i = p->first_qset; i < p->first_qset + p->nqsets; i++) | |
80 | + set_qset_lro(dev, i, 0); | |
81 | } | |
82 | return 0; | |
83 | } | |
84 | @@ -1798,6 +1824,25 @@ static void get_wol(struct net_device *d | |
85 | memset(&wol->sopass, 0, sizeof(wol->sopass)); | |
86 | } | |
87 | ||
88 | +static int cxgb3_set_flags(struct net_device *dev, u32 data) | |
89 | +{ | |
90 | + struct port_info *pi = netdev_priv(dev); | |
91 | + int i; | |
92 | + | |
93 | + if (data & ETH_FLAG_LRO) { | |
94 | + if (!pi->rx_csum_offload) | |
95 | + return -EINVAL; | |
96 | + | |
97 | + for (i = pi->first_qset; i < pi->first_qset + pi->nqsets; i++) | |
98 | + set_qset_lro(dev, i, 1); | |
99 | + | |
100 | + } else | |
101 | + for (i = pi->first_qset; i < pi->first_qset + pi->nqsets; i++) | |
102 | + set_qset_lro(dev, i, 0); | |
103 | + | |
104 | + return 0; | |
105 | +} | |
106 | + | |
107 | static const struct ethtool_ops cxgb_ethtool_ops = { | |
108 | .get_settings = get_settings, | |
109 | .set_settings = set_settings, | |
110 | @@ -1827,6 +1872,8 @@ static const struct ethtool_ops cxgb_eth | |
111 | .get_regs = get_regs, | |
112 | .get_wol = get_wol, | |
113 | .set_tso = ethtool_op_set_tso, | |
114 | + .get_flags = ethtool_op_get_flags, | |
115 | + .set_flags = cxgb3_set_flags, | |
116 | }; | |
117 | ||
118 | static int in_range(int val, int lo, int hi) | |
119 | @@ -1943,11 +1990,9 @@ static int cxgb_extension_ioctl(struct n | |
120 | } | |
121 | } | |
122 | } | |
123 | - if (t.lro >= 0) { | |
124 | - struct sge_qset *qs = &adapter->sge.qs[t.qset_idx]; | |
125 | - q->lro = t.lro; | |
126 | - qs->lro_enabled = t.lro; | |
127 | - } | |
128 | + if (t.lro >= 0) | |
129 | + set_qset_lro(dev, t.qset_idx, t.lro); | |
130 | + | |
131 | break; | |
132 | } | |
133 | case CHELSIO_GET_QSET_PARAMS:{ |