aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorMichał Mirosław <mirq-linux@rere.qmqm.pl>2011-04-15 00:50:49 -0400
committerDavid S. Miller <davem@davemloft.net>2011-04-15 18:50:40 -0400
commit569e146396cb3b378d2957b94671bf30cd777c67 (patch)
tree9a310a2bdbda632a810d35ec9fb854ae5f59d937 /drivers/net
parentc88fcb3d8265cf473c73bc147a2aa21ae03abf67 (diff)
net: forcedeth: convert to hw_features
This also fixes a race around np->txrxctl_bits while changing RXCSUM offload. Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/forcedeth.c78
1 files changed, 26 insertions, 52 deletions
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index d5ab4dad5051..ec9a32d01e61 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -774,7 +774,6 @@ struct fe_priv {
774 u32 driver_data; 774 u32 driver_data;
775 u32 device_id; 775 u32 device_id;
776 u32 register_size; 776 u32 register_size;
777 int rx_csum;
778 u32 mac_in_use; 777 u32 mac_in_use;
779 int mgmt_version; 778 int mgmt_version;
780 int mgmt_sema; 779 int mgmt_sema;
@@ -4480,58 +4479,36 @@ static int nv_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam*
4480 return 0; 4479 return 0;
4481} 4480}
4482 4481
4483static u32 nv_get_rx_csum(struct net_device *dev) 4482static u32 nv_fix_features(struct net_device *dev, u32 features)
4484{ 4483{
4485 struct fe_priv *np = netdev_priv(dev); 4484 /* vlan is dependent on rx checksum offload */
4486 return np->rx_csum != 0; 4485 if (features & (NETIF_F_HW_VLAN_TX|NETIF_F_HW_VLAN_RX))
4486 features |= NETIF_F_RXCSUM;
4487
4488 return features;
4487} 4489}
4488 4490
4489static int nv_set_rx_csum(struct net_device *dev, u32 data) 4491static int nv_set_features(struct net_device *dev, u32 features)
4490{ 4492{
4491 struct fe_priv *np = netdev_priv(dev); 4493 struct fe_priv *np = netdev_priv(dev);
4492 u8 __iomem *base = get_hwbase(dev); 4494 u8 __iomem *base = get_hwbase(dev);
4493 int retcode = 0; 4495 u32 changed = dev->features ^ features;
4494 4496
4495 if (np->driver_data & DEV_HAS_CHECKSUM) { 4497 if (changed & NETIF_F_RXCSUM) {
4496 if (data) { 4498 spin_lock_irq(&np->lock);
4497 np->rx_csum = 1;
4498 np->txrxctl_bits |= NVREG_TXRXCTL_RXCHECK;
4499 } else {
4500 np->rx_csum = 0;
4501 /* vlan is dependent on rx checksum offload */
4502 if (!(np->vlanctl_bits & NVREG_VLANCONTROL_ENABLE))
4503 np->txrxctl_bits &= ~NVREG_TXRXCTL_RXCHECK;
4504 }
4505 if (netif_running(dev)) {
4506 spin_lock_irq(&np->lock);
4507 writel(np->txrxctl_bits, base + NvRegTxRxControl);
4508 spin_unlock_irq(&np->lock);
4509 }
4510 } else {
4511 return -EINVAL;
4512 }
4513
4514 return retcode;
4515}
4516 4499
4517static int nv_set_tx_csum(struct net_device *dev, u32 data) 4500 if (features & NETIF_F_RXCSUM)
4518{ 4501 np->txrxctl_bits |= NVREG_TXRXCTL_RXCHECK;
4519 struct fe_priv *np = netdev_priv(dev); 4502 else
4503 np->txrxctl_bits &= ~NVREG_TXRXCTL_RXCHECK;
4520 4504
4521 if (np->driver_data & DEV_HAS_CHECKSUM) 4505 if (netif_running(dev))
4522 return ethtool_op_set_tx_csum(dev, data); 4506 writel(np->txrxctl_bits, base + NvRegTxRxControl);
4523 else
4524 return -EOPNOTSUPP;
4525}
4526 4507
4527static int nv_set_sg(struct net_device *dev, u32 data) 4508 spin_unlock_irq(&np->lock);
4528{ 4509 }
4529 struct fe_priv *np = netdev_priv(dev);
4530 4510
4531 if (np->driver_data & DEV_HAS_CHECKSUM) 4511 return 0;
4532 return ethtool_op_set_sg(dev, data);
4533 else
4534 return -EOPNOTSUPP;
4535} 4512}
4536 4513
4537static int nv_get_sset_count(struct net_device *dev, int sset) 4514static int nv_get_sset_count(struct net_device *dev, int sset)
@@ -4896,15 +4873,10 @@ static const struct ethtool_ops ops = {
4896 .get_regs_len = nv_get_regs_len, 4873 .get_regs_len = nv_get_regs_len,
4897 .get_regs = nv_get_regs, 4874 .get_regs = nv_get_regs,
4898 .nway_reset = nv_nway_reset, 4875 .nway_reset = nv_nway_reset,
4899 .set_tso = nv_set_tso,
4900 .get_ringparam = nv_get_ringparam, 4876 .get_ringparam = nv_get_ringparam,
4901 .set_ringparam = nv_set_ringparam, 4877 .set_ringparam = nv_set_ringparam,
4902 .get_pauseparam = nv_get_pauseparam, 4878 .get_pauseparam = nv_get_pauseparam,
4903 .set_pauseparam = nv_set_pauseparam, 4879 .set_pauseparam = nv_set_pauseparam,
4904 .get_rx_csum = nv_get_rx_csum,
4905 .set_rx_csum = nv_set_rx_csum,
4906 .set_tx_csum = nv_set_tx_csum,
4907 .set_sg = nv_set_sg,
4908 .get_strings = nv_get_strings, 4880 .get_strings = nv_get_strings,
4909 .get_ethtool_stats = nv_get_ethtool_stats, 4881 .get_ethtool_stats = nv_get_ethtool_stats,
4910 .get_sset_count = nv_get_sset_count, 4882 .get_sset_count = nv_get_sset_count,
@@ -5235,6 +5207,8 @@ static const struct net_device_ops nv_netdev_ops = {
5235 .ndo_start_xmit = nv_start_xmit, 5207 .ndo_start_xmit = nv_start_xmit,
5236 .ndo_tx_timeout = nv_tx_timeout, 5208 .ndo_tx_timeout = nv_tx_timeout,
5237 .ndo_change_mtu = nv_change_mtu, 5209 .ndo_change_mtu = nv_change_mtu,
5210 .ndo_fix_features = nv_fix_features,
5211 .ndo_set_features = nv_set_features,
5238 .ndo_validate_addr = eth_validate_addr, 5212 .ndo_validate_addr = eth_validate_addr,
5239 .ndo_set_mac_address = nv_set_mac_address, 5213 .ndo_set_mac_address = nv_set_mac_address,
5240 .ndo_set_multicast_list = nv_set_multicast, 5214 .ndo_set_multicast_list = nv_set_multicast,
@@ -5251,6 +5225,8 @@ static const struct net_device_ops nv_netdev_ops_optimized = {
5251 .ndo_start_xmit = nv_start_xmit_optimized, 5225 .ndo_start_xmit = nv_start_xmit_optimized,
5252 .ndo_tx_timeout = nv_tx_timeout, 5226 .ndo_tx_timeout = nv_tx_timeout,
5253 .ndo_change_mtu = nv_change_mtu, 5227 .ndo_change_mtu = nv_change_mtu,
5228 .ndo_fix_features = nv_fix_features,
5229 .ndo_set_features = nv_set_features,
5254 .ndo_validate_addr = eth_validate_addr, 5230 .ndo_validate_addr = eth_validate_addr,
5255 .ndo_set_mac_address = nv_set_mac_address, 5231 .ndo_set_mac_address = nv_set_mac_address,
5256 .ndo_set_multicast_list = nv_set_multicast, 5232 .ndo_set_multicast_list = nv_set_multicast,
@@ -5364,11 +5340,10 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
5364 np->pkt_limit = NV_PKTLIMIT_2; 5340 np->pkt_limit = NV_PKTLIMIT_2;
5365 5341
5366 if (id->driver_data & DEV_HAS_CHECKSUM) { 5342 if (id->driver_data & DEV_HAS_CHECKSUM) {
5367 np->rx_csum = 1;
5368 np->txrxctl_bits |= NVREG_TXRXCTL_RXCHECK; 5343 np->txrxctl_bits |= NVREG_TXRXCTL_RXCHECK;
5369 dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; 5344 dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_SG |
5370 dev->features |= NETIF_F_TSO; 5345 NETIF_F_TSO | NETIF_F_RXCSUM;
5371 dev->features |= NETIF_F_GRO; 5346 dev->features |= dev->hw_features;
5372 } 5347 }
5373 5348
5374 np->vlanctl_bits = 0; 5349 np->vlanctl_bits = 0;
@@ -5384,7 +5359,6 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
5384 np->pause_flags |= NV_PAUSEFRAME_TX_CAPABLE | NV_PAUSEFRAME_TX_REQ; 5359 np->pause_flags |= NV_PAUSEFRAME_TX_CAPABLE | NV_PAUSEFRAME_TX_REQ;
5385 } 5360 }
5386 5361
5387
5388 err = -ENOMEM; 5362 err = -ENOMEM;
5389 np->base = ioremap(addr, np->register_size); 5363 np->base = ioremap(addr, np->register_size);
5390 if (!np->base) 5364 if (!np->base)