aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/sky2.c117
-rw-r--r--drivers/net/sky2.h6
2 files changed, 52 insertions, 71 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);
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h
index 80bdc404f1ea..6861b0e8db9a 100644
--- a/drivers/net/sky2.h
+++ b/drivers/net/sky2.h
@@ -2236,11 +2236,8 @@ struct sky2_port {
2236 u16 rx_pending; 2236 u16 rx_pending;
2237 u16 rx_data_size; 2237 u16 rx_data_size;
2238 u16 rx_nfrags; 2238 u16 rx_nfrags;
2239
2240#ifdef SKY2_VLAN_TAG_USED
2241 u16 rx_tag; 2239 u16 rx_tag;
2242 struct vlan_group *vlgrp; 2240
2243#endif
2244 struct { 2241 struct {
2245 unsigned long last; 2242 unsigned long last;
2246 u32 mac_rp; 2243 u32 mac_rp;
@@ -2284,6 +2281,7 @@ struct sky2_hw {
2284#define SKY2_HW_AUTO_TX_SUM 0x00000040 /* new IP decode for Tx */ 2281#define SKY2_HW_AUTO_TX_SUM 0x00000040 /* new IP decode for Tx */
2285#define SKY2_HW_ADV_POWER_CTL 0x00000080 /* additional PHY power regs */ 2282#define SKY2_HW_ADV_POWER_CTL 0x00000080 /* additional PHY power regs */
2286#define SKY2_HW_RSS_BROKEN 0x00000100 2283#define SKY2_HW_RSS_BROKEN 0x00000100
2284#define SKY2_HW_VLAN_BROKEN 0x00000200
2287 2285
2288 u8 chip_id; 2286 u8 chip_id;
2289 u8 chip_rev; 2287 u8 chip_rev;