aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sky2.c
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@vyatta.com>2011-01-09 18:54:15 -0500
committerDavid S. Miller <davem@davemloft.net>2011-01-09 18:54:15 -0500
commit86aa77854f47ab6f5f9c687507af1f57d2b89004 (patch)
treeab8d3da41fbbf7c177f1ab341bc982d80498dc92 /drivers/net/sky2.c
parent2aca31e765f756408ebc8408378afa5795d1ae49 (diff)
sky2: convert to new VLAN model (v0.2)
This converts sky2 to new VLAN offload flags control via ethtool. It also allows for transmit offload of vlan tagged frames which was not possible before. Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> Reviewed-by: Jesse Gross <jesse@nicira.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r--drivers/net/sky2.c117
1 files changed, 50 insertions, 67 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index b56109294758..7d85a38377a1 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -46,10 +46,6 @@
46 46
47#include <asm/irq.h> 47#include <asm/irq.h>
48 48
49#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
50#define SKY2_VLAN_TAG_USED 1
51#endif
52
53#include "sky2.h" 49#include "sky2.h"
54 50
55#define DRV_NAME "sky2" 51#define DRV_NAME "sky2"
@@ -1326,39 +1322,34 @@ static int sky2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1326 return err; 1322 return err;
1327} 1323}
1328 1324
1329#ifdef SKY2_VLAN_TAG_USED 1325#define NETIF_F_ALL_VLAN (NETIF_F_HW_VLAN_TX|NETIF_F_HW_VLAN_RX)
1330static void sky2_set_vlan_mode(struct sky2_hw *hw, u16 port, bool onoff)
1331{
1332 if (onoff) {
1333 sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T),
1334 RX_VLAN_STRIP_ON);
1335 sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
1336 TX_VLAN_TAG_ON);
1337 } else {
1338 sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T),
1339 RX_VLAN_STRIP_OFF);
1340 sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
1341 TX_VLAN_TAG_OFF);
1342 }
1343}
1344 1326
1345static void sky2_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) 1327static void sky2_vlan_mode(struct net_device *dev)
1346{ 1328{
1347 struct sky2_port *sky2 = netdev_priv(dev); 1329 struct sky2_port *sky2 = netdev_priv(dev);
1348 struct sky2_hw *hw = sky2->hw; 1330 struct sky2_hw *hw = sky2->hw;
1349 u16 port = sky2->port; 1331 u16 port = sky2->port;
1350 1332
1351 netif_tx_lock_bh(dev); 1333 if (dev->features & NETIF_F_HW_VLAN_RX)
1352 napi_disable(&hw->napi); 1334 sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T),
1335 RX_VLAN_STRIP_ON);
1336 else
1337 sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T),
1338 RX_VLAN_STRIP_OFF);
1353 1339
1354 sky2->vlgrp = grp; 1340 dev->vlan_features = dev->features &~ NETIF_F_ALL_VLAN;
1355 sky2_set_vlan_mode(hw, port, grp != NULL); 1341 if (dev->features & NETIF_F_HW_VLAN_TX)
1342 sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
1343 TX_VLAN_TAG_ON);
1344 else {
1345 sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
1346 TX_VLAN_TAG_OFF);
1356 1347
1357 sky2_read32(hw, B0_Y2_SP_LISR); 1348 /* Can't do transmit offload of vlan without hw vlan */
1358 napi_enable(&hw->napi); 1349 dev->vlan_features &= ~(NETIF_F_TSO | NETIF_F_SG
1359 netif_tx_unlock_bh(dev); 1350 | NETIF_F_ALL_CSUM);
1351 }
1360} 1352}
1361#endif
1362 1353
1363/* Amount of required worst case padding in rx buffer */ 1354/* Amount of required worst case padding in rx buffer */
1364static inline unsigned sky2_rx_pad(const struct sky2_hw *hw) 1355static inline unsigned sky2_rx_pad(const struct sky2_hw *hw)
@@ -1635,9 +1626,7 @@ static void sky2_hw_up(struct sky2_port *sky2)
1635 sky2_prefetch_init(hw, txqaddr[port], sky2->tx_le_map, 1626 sky2_prefetch_init(hw, txqaddr[port], sky2->tx_le_map,
1636 sky2->tx_ring_size - 1); 1627 sky2->tx_ring_size - 1);
1637 1628
1638#ifdef SKY2_VLAN_TAG_USED 1629 sky2_vlan_mode(sky2->netdev);
1639 sky2_set_vlan_mode(hw, port, sky2->vlgrp != NULL);
1640#endif
1641 1630
1642 sky2_rx_start(sky2); 1631 sky2_rx_start(sky2);
1643} 1632}
@@ -1780,7 +1769,7 @@ static netdev_tx_t sky2_xmit_frame(struct sk_buff *skb,
1780 } 1769 }
1781 1770
1782 ctrl = 0; 1771 ctrl = 0;
1783#ifdef SKY2_VLAN_TAG_USED 1772
1784 /* Add VLAN tag, can piggyback on LRGLEN or ADDR64 */ 1773 /* Add VLAN tag, can piggyback on LRGLEN or ADDR64 */
1785 if (vlan_tx_tag_present(skb)) { 1774 if (vlan_tx_tag_present(skb)) {
1786 if (!le) { 1775 if (!le) {
@@ -1792,7 +1781,6 @@ static netdev_tx_t sky2_xmit_frame(struct sk_buff *skb,
1792 le->length = cpu_to_be16(vlan_tx_tag_get(skb)); 1781 le->length = cpu_to_be16(vlan_tx_tag_get(skb));
1793 ctrl |= INS_VLAN; 1782 ctrl |= INS_VLAN;
1794 } 1783 }
1795#endif
1796 1784
1797 /* Handle TCP checksum offload */ 1785 /* Handle TCP checksum offload */
1798 if (skb->ip_summed == CHECKSUM_PARTIAL) { 1786 if (skb->ip_summed == CHECKSUM_PARTIAL) {
@@ -2432,11 +2420,8 @@ static struct sk_buff *sky2_receive(struct net_device *dev,
2432 struct sk_buff *skb = NULL; 2420 struct sk_buff *skb = NULL;
2433 u16 count = (status & GMR_FS_LEN) >> 16; 2421 u16 count = (status & GMR_FS_LEN) >> 16;
2434 2422
2435#ifdef SKY2_VLAN_TAG_USED 2423 if (status & GMR_FS_VLAN)
2436 /* Account for vlan tag */ 2424 count -= VLAN_HLEN; /* Account for vlan tag */
2437 if (sky2->vlgrp && (status & GMR_FS_VLAN))
2438 count -= VLAN_HLEN;
2439#endif
2440 2425
2441 netif_printk(sky2, rx_status, KERN_DEBUG, dev, 2426 netif_printk(sky2, rx_status, KERN_DEBUG, dev,
2442 "rx slot %u status 0x%x len %d\n", 2427 "rx slot %u status 0x%x len %d\n",
@@ -2504,17 +2489,9 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last)
2504static inline void sky2_skb_rx(const struct sky2_port *sky2, 2489static inline void sky2_skb_rx(const struct sky2_port *sky2,
2505 u32 status, struct sk_buff *skb) 2490 u32 status, struct sk_buff *skb)
2506{ 2491{
2507#ifdef SKY2_VLAN_TAG_USED 2492 if (status & GMR_FS_VLAN)
2508 u16 vlan_tag = be16_to_cpu(sky2->rx_tag); 2493 __vlan_hwaccel_put_tag(skb, be16_to_cpu(sky2->rx_tag));
2509 if (sky2->vlgrp && (status & GMR_FS_VLAN)) { 2494
2510 if (skb->ip_summed == CHECKSUM_NONE)
2511 vlan_hwaccel_receive_skb(skb, sky2->vlgrp, vlan_tag);
2512 else
2513 vlan_gro_receive(&sky2->hw->napi, sky2->vlgrp,
2514 vlan_tag, skb);
2515 return;
2516 }
2517#endif
2518 if (skb->ip_summed == CHECKSUM_NONE) 2495 if (skb->ip_summed == CHECKSUM_NONE)
2519 netif_receive_skb(skb); 2496 netif_receive_skb(skb);
2520 else 2497 else
@@ -2631,7 +2608,6 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx)
2631 goto exit_loop; 2608 goto exit_loop;
2632 break; 2609 break;
2633 2610
2634#ifdef SKY2_VLAN_TAG_USED
2635 case OP_RXVLAN: 2611 case OP_RXVLAN:
2636 sky2->rx_tag = length; 2612 sky2->rx_tag = length;
2637 break; 2613 break;
@@ -2639,7 +2615,6 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx)
2639 case OP_RXCHKSVLAN: 2615 case OP_RXCHKSVLAN:
2640 sky2->rx_tag = length; 2616 sky2->rx_tag = length;
2641 /* fall through */ 2617 /* fall through */
2642#endif
2643 case OP_RXCHKS: 2618 case OP_RXCHKS:
2644 if (likely(sky2->flags & SKY2_FLAG_RX_CHECKSUM)) 2619 if (likely(sky2->flags & SKY2_FLAG_RX_CHECKSUM))
2645 sky2_rx_checksum(sky2, status); 2620 sky2_rx_checksum(sky2, status);
@@ -3042,6 +3017,10 @@ static int __devinit sky2_init(struct sky2_hw *hw)
3042 | SKY2_HW_NEW_LE 3017 | SKY2_HW_NEW_LE
3043 | SKY2_HW_AUTO_TX_SUM 3018 | SKY2_HW_AUTO_TX_SUM
3044 | SKY2_HW_ADV_POWER_CTL; 3019 | SKY2_HW_ADV_POWER_CTL;
3020
3021 /* The workaround for status conflicts VLAN tag detection. */
3022 if (hw->chip_rev == CHIP_REV_YU_FE2_A0)
3023 hw->flags |= SKY2_HW_VLAN_BROKEN;
3045 break; 3024 break;
3046 3025
3047 case CHIP_ID_YUKON_SUPR: 3026 case CHIP_ID_YUKON_SUPR:
@@ -4237,15 +4216,28 @@ static int sky2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom
4237static int sky2_set_flags(struct net_device *dev, u32 data) 4216static int sky2_set_flags(struct net_device *dev, u32 data)
4238{ 4217{
4239 struct sky2_port *sky2 = netdev_priv(dev); 4218 struct sky2_port *sky2 = netdev_priv(dev);
4240 u32 supported = 4219 unsigned long old_feat = dev->features;
4241 (sky2->hw->flags & SKY2_HW_RSS_BROKEN) ? 0 : ETH_FLAG_RXHASH; 4220 u32 supported = 0;
4242 int rc; 4221 int rc;
4243 4222
4223 if (!(sky2->hw->flags & SKY2_HW_RSS_BROKEN))
4224 supported |= ETH_FLAG_RXHASH;
4225
4226 if (!(sky2->hw->flags & SKY2_HW_VLAN_BROKEN))
4227 supported |= ETH_FLAG_RXVLAN | ETH_FLAG_TXVLAN;
4228
4229 printk(KERN_DEBUG "sky2 set_flags: supported %x data %x\n",
4230 supported, data);
4231
4244 rc = ethtool_op_set_flags(dev, data, supported); 4232 rc = ethtool_op_set_flags(dev, data, supported);
4245 if (rc) 4233 if (rc)
4246 return rc; 4234 return rc;
4247 4235
4248 rx_set_rss(dev); 4236 if ((old_feat ^ dev->features) & NETIF_F_RXHASH)
4237 rx_set_rss(dev);
4238
4239 if ((old_feat ^ dev->features) & NETIF_F_ALL_VLAN)
4240 sky2_vlan_mode(dev);
4249 4241
4250 return 0; 4242 return 0;
4251} 4243}
@@ -4281,6 +4273,7 @@ static const struct ethtool_ops sky2_ethtool_ops = {
4281 .get_sset_count = sky2_get_sset_count, 4273 .get_sset_count = sky2_get_sset_count,
4282 .get_ethtool_stats = sky2_get_ethtool_stats, 4274 .get_ethtool_stats = sky2_get_ethtool_stats,
4283 .set_flags = sky2_set_flags, 4275 .set_flags = sky2_set_flags,
4276 .get_flags = ethtool_op_get_flags,
4284}; 4277};
4285 4278
4286#ifdef CONFIG_SKY2_DEBUG 4279#ifdef CONFIG_SKY2_DEBUG
@@ -4562,9 +4555,6 @@ static const struct net_device_ops sky2_netdev_ops[2] = {
4562 .ndo_change_mtu = sky2_change_mtu, 4555 .ndo_change_mtu = sky2_change_mtu,
4563 .ndo_tx_timeout = sky2_tx_timeout, 4556 .ndo_tx_timeout = sky2_tx_timeout,
4564 .ndo_get_stats64 = sky2_get_stats, 4557 .ndo_get_stats64 = sky2_get_stats,
4565#ifdef SKY2_VLAN_TAG_USED
4566 .ndo_vlan_rx_register = sky2_vlan_rx_register,
4567#endif
4568#ifdef CONFIG_NET_POLL_CONTROLLER 4558#ifdef CONFIG_NET_POLL_CONTROLLER
4569 .ndo_poll_controller = sky2_netpoll, 4559 .ndo_poll_controller = sky2_netpoll,
4570#endif 4560#endif
@@ -4580,9 +4570,6 @@ static const struct net_device_ops sky2_netdev_ops[2] = {
4580 .ndo_change_mtu = sky2_change_mtu, 4570 .ndo_change_mtu = sky2_change_mtu,
4581 .ndo_tx_timeout = sky2_tx_timeout, 4571 .ndo_tx_timeout = sky2_tx_timeout,
4582 .ndo_get_stats64 = sky2_get_stats, 4572 .ndo_get_stats64 = sky2_get_stats,
4583#ifdef SKY2_VLAN_TAG_USED
4584 .ndo_vlan_rx_register = sky2_vlan_rx_register,
4585#endif
4586 }, 4573 },
4587}; 4574};
4588 4575
@@ -4633,7 +4620,8 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
4633 sky2->port = port; 4620 sky2->port = port;
4634 4621
4635 dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG 4622 dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG
4636 | NETIF_F_TSO | NETIF_F_GRO; 4623 | NETIF_F_TSO | NETIF_F_GRO;
4624
4637 if (highmem) 4625 if (highmem)
4638 dev->features |= NETIF_F_HIGHDMA; 4626 dev->features |= NETIF_F_HIGHDMA;
4639 4627
@@ -4641,13 +4629,8 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
4641 if (!(hw->flags & SKY2_HW_RSS_BROKEN)) 4629 if (!(hw->flags & SKY2_HW_RSS_BROKEN))
4642 dev->features |= NETIF_F_RXHASH; 4630 dev->features |= NETIF_F_RXHASH;
4643 4631
4644#ifdef SKY2_VLAN_TAG_USED 4632 if (!(hw->flags & SKY2_HW_VLAN_BROKEN))
4645 /* The workaround for FE+ status conflicts with VLAN tag detection. */
4646 if (!(sky2->hw->chip_id == CHIP_ID_YUKON_FE_P &&
4647 sky2->hw->chip_rev == CHIP_REV_YU_FE2_A0)) {
4648 dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; 4633 dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
4649 }
4650#endif
4651 4634
4652 /* read the mac address */ 4635 /* read the mac address */
4653 memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port * 8, ETH_ALEN); 4636 memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port * 8, ETH_ALEN);