Skip to content

Commit 86aa778

Browse files
Stephen Hemmingerdavem330
authored andcommitted
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 <[email protected]> Reviewed-by: Jesse Gross <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 2aca31e commit 86aa778

File tree

2 files changed

+52
-71
lines changed

2 files changed

+52
-71
lines changed

drivers/net/sky2.c

Lines changed: 50 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,6 @@
4646

4747
#include <asm/irq.h>
4848

49-
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
50-
#define SKY2_VLAN_TAG_USED 1
51-
#endif
52-
5349
#include "sky2.h"
5450

5551
#define DRV_NAME "sky2"
@@ -1326,39 +1322,34 @@ static int sky2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
13261322
return err;
13271323
}
13281324

1329-
#ifdef SKY2_VLAN_TAG_USED
1330-
static 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-
}
1325+
#define NETIF_F_ALL_VLAN (NETIF_F_HW_VLAN_TX|NETIF_F_HW_VLAN_RX)
13441326

1345-
static void sky2_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
1327+
static void sky2_vlan_mode(struct net_device *dev)
13461328
{
13471329
struct sky2_port *sky2 = netdev_priv(dev);
13481330
struct sky2_hw *hw = sky2->hw;
13491331
u16 port = sky2->port;
13501332

1351-
netif_tx_lock_bh(dev);
1352-
napi_disable(&hw->napi);
1333+
if (dev->features & NETIF_F_HW_VLAN_RX)
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);
13531339

1354-
sky2->vlgrp = grp;
1355-
sky2_set_vlan_mode(hw, port, grp != NULL);
1340+
dev->vlan_features = dev->features &~ NETIF_F_ALL_VLAN;
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);
13561347

1357-
sky2_read32(hw, B0_Y2_SP_LISR);
1358-
napi_enable(&hw->napi);
1359-
netif_tx_unlock_bh(dev);
1348+
/* Can't do transmit offload of vlan without hw vlan */
1349+
dev->vlan_features &= ~(NETIF_F_TSO | NETIF_F_SG
1350+
| NETIF_F_ALL_CSUM);
1351+
}
13601352
}
1361-
#endif
13621353

13631354
/* Amount of required worst case padding in rx buffer */
13641355
static inline unsigned sky2_rx_pad(const struct sky2_hw *hw)
@@ -1635,9 +1626,7 @@ static void sky2_hw_up(struct sky2_port *sky2)
16351626
sky2_prefetch_init(hw, txqaddr[port], sky2->tx_le_map,
16361627
sky2->tx_ring_size - 1);
16371628

1638-
#ifdef SKY2_VLAN_TAG_USED
1639-
sky2_set_vlan_mode(hw, port, sky2->vlgrp != NULL);
1640-
#endif
1629+
sky2_vlan_mode(sky2->netdev);
16411630

16421631
sky2_rx_start(sky2);
16431632
}
@@ -1780,7 +1769,7 @@ static netdev_tx_t sky2_xmit_frame(struct sk_buff *skb,
17801769
}
17811770

17821771
ctrl = 0;
1783-
#ifdef SKY2_VLAN_TAG_USED
1772+
17841773
/* Add VLAN tag, can piggyback on LRGLEN or ADDR64 */
17851774
if (vlan_tx_tag_present(skb)) {
17861775
if (!le) {
@@ -1792,7 +1781,6 @@ static netdev_tx_t sky2_xmit_frame(struct sk_buff *skb,
17921781
le->length = cpu_to_be16(vlan_tx_tag_get(skb));
17931782
ctrl |= INS_VLAN;
17941783
}
1795-
#endif
17961784

17971785
/* Handle TCP checksum offload */
17981786
if (skb->ip_summed == CHECKSUM_PARTIAL) {
@@ -2432,11 +2420,8 @@ static struct sk_buff *sky2_receive(struct net_device *dev,
24322420
struct sk_buff *skb = NULL;
24332421
u16 count = (status & GMR_FS_LEN) >> 16;
24342422

2435-
#ifdef SKY2_VLAN_TAG_USED
2436-
/* Account for vlan tag */
2437-
if (sky2->vlgrp && (status & GMR_FS_VLAN))
2438-
count -= VLAN_HLEN;
2439-
#endif
2423+
if (status & GMR_FS_VLAN)
2424+
count -= VLAN_HLEN; /* Account for vlan tag */
24402425

24412426
netif_printk(sky2, rx_status, KERN_DEBUG, dev,
24422427
"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)
25042489
static inline void sky2_skb_rx(const struct sky2_port *sky2,
25052490
u32 status, struct sk_buff *skb)
25062491
{
2507-
#ifdef SKY2_VLAN_TAG_USED
2508-
u16 vlan_tag = be16_to_cpu(sky2->rx_tag);
2509-
if (sky2->vlgrp && (status & GMR_FS_VLAN)) {
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
2492+
if (status & GMR_FS_VLAN)
2493+
__vlan_hwaccel_put_tag(skb, be16_to_cpu(sky2->rx_tag));
2494+
25182495
if (skb->ip_summed == CHECKSUM_NONE)
25192496
netif_receive_skb(skb);
25202497
else
@@ -2631,15 +2608,13 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx)
26312608
goto exit_loop;
26322609
break;
26332610

2634-
#ifdef SKY2_VLAN_TAG_USED
26352611
case OP_RXVLAN:
26362612
sky2->rx_tag = length;
26372613
break;
26382614

26392615
case OP_RXCHKSVLAN:
26402616
sky2->rx_tag = length;
26412617
/* fall through */
2642-
#endif
26432618
case OP_RXCHKS:
26442619
if (likely(sky2->flags & SKY2_FLAG_RX_CHECKSUM))
26452620
sky2_rx_checksum(sky2, status);
@@ -3042,6 +3017,10 @@ static int __devinit sky2_init(struct sky2_hw *hw)
30423017
| SKY2_HW_NEW_LE
30433018
| SKY2_HW_AUTO_TX_SUM
30443019
| 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;
30453024
break;
30463025

30473026
case CHIP_ID_YUKON_SUPR:
@@ -4237,15 +4216,28 @@ static int sky2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom
42374216
static int sky2_set_flags(struct net_device *dev, u32 data)
42384217
{
42394218
struct sky2_port *sky2 = netdev_priv(dev);
4240-
u32 supported =
4241-
(sky2->hw->flags & SKY2_HW_RSS_BROKEN) ? 0 : ETH_FLAG_RXHASH;
4219+
unsigned long old_feat = dev->features;
4220+
u32 supported = 0;
42424221
int rc;
42434222

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+
42444232
rc = ethtool_op_set_flags(dev, data, supported);
42454233
if (rc)
42464234
return rc;
42474235

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);
42494241

42504242
return 0;
42514243
}
@@ -4281,6 +4273,7 @@ static const struct ethtool_ops sky2_ethtool_ops = {
42814273
.get_sset_count = sky2_get_sset_count,
42824274
.get_ethtool_stats = sky2_get_ethtool_stats,
42834275
.set_flags = sky2_set_flags,
4276+
.get_flags = ethtool_op_get_flags,
42844277
};
42854278

42864279
#ifdef CONFIG_SKY2_DEBUG
@@ -4562,9 +4555,6 @@ static const struct net_device_ops sky2_netdev_ops[2] = {
45624555
.ndo_change_mtu = sky2_change_mtu,
45634556
.ndo_tx_timeout = sky2_tx_timeout,
45644557
.ndo_get_stats64 = sky2_get_stats,
4565-
#ifdef SKY2_VLAN_TAG_USED
4566-
.ndo_vlan_rx_register = sky2_vlan_rx_register,
4567-
#endif
45684558
#ifdef CONFIG_NET_POLL_CONTROLLER
45694559
.ndo_poll_controller = sky2_netpoll,
45704560
#endif
@@ -4580,9 +4570,6 @@ static const struct net_device_ops sky2_netdev_ops[2] = {
45804570
.ndo_change_mtu = sky2_change_mtu,
45814571
.ndo_tx_timeout = sky2_tx_timeout,
45824572
.ndo_get_stats64 = sky2_get_stats,
4583-
#ifdef SKY2_VLAN_TAG_USED
4584-
.ndo_vlan_rx_register = sky2_vlan_rx_register,
4585-
#endif
45864573
},
45874574
};
45884575

@@ -4633,21 +4620,17 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
46334620
sky2->port = port;
46344621

46354622
dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG
4636-
| NETIF_F_TSO | NETIF_F_GRO;
4623+
| NETIF_F_TSO | NETIF_F_GRO;
4624+
46374625
if (highmem)
46384626
dev->features |= NETIF_F_HIGHDMA;
46394627

46404628
/* Enable receive hashing unless hardware is known broken */
46414629
if (!(hw->flags & SKY2_HW_RSS_BROKEN))
46424630
dev->features |= NETIF_F_RXHASH;
46434631

4644-
#ifdef SKY2_VLAN_TAG_USED
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)) {
4632+
if (!(hw->flags & SKY2_HW_VLAN_BROKEN))
46484633
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
4649-
}
4650-
#endif
46514634

46524635
/* read the mac address */
46534636
memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port * 8, ETH_ALEN);

drivers/net/sky2.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2236,11 +2236,8 @@ struct sky2_port {
22362236
u16 rx_pending;
22372237
u16 rx_data_size;
22382238
u16 rx_nfrags;
2239-
2240-
#ifdef SKY2_VLAN_TAG_USED
22412239
u16 rx_tag;
2242-
struct vlan_group *vlgrp;
2243-
#endif
2240+
22442241
struct {
22452242
unsigned long last;
22462243
u32 mac_rp;
@@ -2284,6 +2281,7 @@ struct sky2_hw {
22842281
#define SKY2_HW_AUTO_TX_SUM 0x00000040 /* new IP decode for Tx */
22852282
#define SKY2_HW_ADV_POWER_CTL 0x00000080 /* additional PHY power regs */
22862283
#define SKY2_HW_RSS_BROKEN 0x00000100
2284+
#define SKY2_HW_VLAN_BROKEN 0x00000200
22872285

22882286
u8 chip_id;
22892287
u8 chip_rev;

0 commit comments

Comments
 (0)