aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/xen-netback/common.h3
-rw-r--r--drivers/net/xen-netback/interface.c84
2 files changed, 15 insertions, 72 deletions
diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h
index 5d7bbf2b2ee7..8753e6ddff8f 100644
--- a/drivers/net/xen-netback/common.h
+++ b/drivers/net/xen-netback/common.h
@@ -73,9 +73,6 @@ struct xenvif {
73 struct vm_struct *tx_comms_area; 73 struct vm_struct *tx_comms_area;
74 struct vm_struct *rx_comms_area; 74 struct vm_struct *rx_comms_area;
75 75
76 /* Flags that must not be set in dev->features */
77 u32 features_disabled;
78
79 /* Frontend feature information. */ 76 /* Frontend feature information. */
80 u8 can_sg:1; 77 u8 can_sg:1;
81 u8 gso:1; 78 u8 gso:1;
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c
index de569cc19da4..0ca86f9ec4ed 100644
--- a/drivers/net/xen-netback/interface.c
+++ b/drivers/net/xen-netback/interface.c
@@ -165,69 +165,18 @@ static int xenvif_change_mtu(struct net_device *dev, int mtu)
165 return 0; 165 return 0;
166} 166}
167 167
168static void xenvif_set_features(struct xenvif *vif) 168static u32 xenvif_fix_features(struct net_device *dev, u32 features)
169{
170 struct net_device *dev = vif->dev;
171 u32 features = dev->features;
172
173 if (vif->can_sg)
174 features |= NETIF_F_SG;
175 if (vif->gso || vif->gso_prefix)
176 features |= NETIF_F_TSO;
177 if (vif->csum)
178 features |= NETIF_F_IP_CSUM;
179
180 features &= ~(vif->features_disabled);
181
182 if (!(features & NETIF_F_SG) && dev->mtu > ETH_DATA_LEN)
183 dev->mtu = ETH_DATA_LEN;
184
185 dev->features = features;
186}
187
188static int xenvif_set_tx_csum(struct net_device *dev, u32 data)
189{
190 struct xenvif *vif = netdev_priv(dev);
191 if (data) {
192 if (!vif->csum)
193 return -EOPNOTSUPP;
194 vif->features_disabled &= ~NETIF_F_IP_CSUM;
195 } else {
196 vif->features_disabled |= NETIF_F_IP_CSUM;
197 }
198
199 xenvif_set_features(vif);
200 return 0;
201}
202
203static int xenvif_set_sg(struct net_device *dev, u32 data)
204{ 169{
205 struct xenvif *vif = netdev_priv(dev); 170 struct xenvif *vif = netdev_priv(dev);
206 if (data) {
207 if (!vif->can_sg)
208 return -EOPNOTSUPP;
209 vif->features_disabled &= ~NETIF_F_SG;
210 } else {
211 vif->features_disabled |= NETIF_F_SG;
212 }
213 171
214 xenvif_set_features(vif); 172 if (!vif->can_sg)
215 return 0; 173 features &= ~NETIF_F_SG;
216} 174 if (!vif->gso && !vif->gso_prefix)
175 features &= ~NETIF_F_TSO;
176 if (!vif->csum)
177 features &= ~NETIF_F_IP_CSUM;
217 178
218static int xenvif_set_tso(struct net_device *dev, u32 data) 179 return features;
219{
220 struct xenvif *vif = netdev_priv(dev);
221 if (data) {
222 if (!vif->gso && !vif->gso_prefix)
223 return -EOPNOTSUPP;
224 vif->features_disabled &= ~NETIF_F_TSO;
225 } else {
226 vif->features_disabled |= NETIF_F_TSO;
227 }
228
229 xenvif_set_features(vif);
230 return 0;
231} 180}
232 181
233static const struct xenvif_stat { 182static const struct xenvif_stat {
@@ -274,12 +223,6 @@ static void xenvif_get_strings(struct net_device *dev, u32 stringset, u8 * data)
274} 223}
275 224
276static struct ethtool_ops xenvif_ethtool_ops = { 225static struct ethtool_ops xenvif_ethtool_ops = {
277 .get_tx_csum = ethtool_op_get_tx_csum,
278 .set_tx_csum = xenvif_set_tx_csum,
279 .get_sg = ethtool_op_get_sg,
280 .set_sg = xenvif_set_sg,
281 .get_tso = ethtool_op_get_tso,
282 .set_tso = xenvif_set_tso,
283 .get_link = ethtool_op_get_link, 226 .get_link = ethtool_op_get_link,
284 227
285 .get_sset_count = xenvif_get_sset_count, 228 .get_sset_count = xenvif_get_sset_count,
@@ -293,6 +236,7 @@ static struct net_device_ops xenvif_netdev_ops = {
293 .ndo_open = xenvif_open, 236 .ndo_open = xenvif_open,
294 .ndo_stop = xenvif_close, 237 .ndo_stop = xenvif_close,
295 .ndo_change_mtu = xenvif_change_mtu, 238 .ndo_change_mtu = xenvif_change_mtu,
239 .ndo_fix_features = xenvif_fix_features,
296}; 240};
297 241
298struct xenvif *xenvif_alloc(struct device *parent, domid_t domid, 242struct xenvif *xenvif_alloc(struct device *parent, domid_t domid,
@@ -331,7 +275,8 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid,
331 vif->credit_timeout.expires = jiffies; 275 vif->credit_timeout.expires = jiffies;
332 276
333 dev->netdev_ops = &xenvif_netdev_ops; 277 dev->netdev_ops = &xenvif_netdev_ops;
334 xenvif_set_features(vif); 278 dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO;
279 dev->features = dev->hw_features;
335 SET_ETHTOOL_OPS(dev, &xenvif_ethtool_ops); 280 SET_ETHTOOL_OPS(dev, &xenvif_ethtool_ops);
336 281
337 dev->tx_queue_len = XENVIF_QUEUE_LENGTH; 282 dev->tx_queue_len = XENVIF_QUEUE_LENGTH;
@@ -367,8 +312,6 @@ int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref,
367 if (vif->irq) 312 if (vif->irq)
368 return 0; 313 return 0;
369 314
370 xenvif_set_features(vif);
371
372 err = xen_netbk_map_frontend_rings(vif, tx_ring_ref, rx_ring_ref); 315 err = xen_netbk_map_frontend_rings(vif, tx_ring_ref, rx_ring_ref);
373 if (err < 0) 316 if (err < 0)
374 goto err; 317 goto err;
@@ -384,9 +327,12 @@ int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref,
384 xenvif_get(vif); 327 xenvif_get(vif);
385 328
386 rtnl_lock(); 329 rtnl_lock();
387 netif_carrier_on(vif->dev);
388 if (netif_running(vif->dev)) 330 if (netif_running(vif->dev))
389 xenvif_up(vif); 331 xenvif_up(vif);
332 if (!vif->can_sg && vif->dev->mtu > ETH_DATA_LEN)
333 dev_set_mtu(vif->dev, ETH_DATA_LEN);
334 netdev_update_features(vif->dev);
335 netif_carrier_on(vif->dev);
390 rtnl_unlock(); 336 rtnl_unlock();
391 337
392 return 0; 338 return 0;