Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 194527
b: refs/heads/master
c: bf73130
h: refs/heads/master
i:
  194525: c42a5bb
  194523: 9d2e7a4
  194519: f6afcb2
  194511: 28e4602
  194495: 48db416
v: v3
  • Loading branch information
Stephen Hemminger authored and David S. Miller committed Apr 25, 2010
1 parent e91a30b commit 707fe74
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 3 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: b7d6a4321195c32b548f0185a2fa0b8f6e02bcfc
refs/heads/master: bf73130d7f98c8c4db143e2dc4982f4eefd5d5e5
79 changes: 77 additions & 2 deletions trunk/drivers/net/sky2.c
Original file line number Diff line number Diff line change
Expand Up @@ -1193,6 +1193,39 @@ static void rx_set_checksum(struct sky2_port *sky2)
? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
}

/* Enable/disable receive hash calculation (RSS) */
static void rx_set_rss(struct net_device *dev)
{
struct sky2_port *sky2 = netdev_priv(dev);
struct sky2_hw *hw = sky2->hw;
int i, nkeys = 4;

/* Supports IPv6 and other modes */
if (hw->flags & SKY2_HW_NEW_LE) {
nkeys = 10;
sky2_write32(hw, SK_REG(sky2->port, RSS_CFG), HASH_ALL);
}

/* Program RSS initial values */
if (dev->features & NETIF_F_RXHASH) {
u32 key[nkeys];

get_random_bytes(key, nkeys * sizeof(u32));
for (i = 0; i < nkeys; i++)
sky2_write32(hw, SK_REG(sky2->port, RSS_KEY + i * 4),
key[i]);

/* Need to turn on (undocumented) flag to make hashing work */
sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T),
RX_STFW_ENA);

sky2_write32(hw, Q_ADDR(rxqaddr[sky2->port], Q_CSR),
BMU_ENA_RX_RSS_HASH);
} else
sky2_write32(hw, Q_ADDR(rxqaddr[sky2->port], Q_CSR),
BMU_DIS_RX_RSS_HASH);
}

/*
* The RX Stop command will not work for Yukon-2 if the BMU does not
* reach the end of packet and since we can't make sure that we have
Expand Down Expand Up @@ -1425,6 +1458,9 @@ static void sky2_rx_start(struct sky2_port *sky2)
if (!(hw->flags & SKY2_HW_NEW_LE))
rx_set_checksum(sky2);

if (!(hw->flags & SKY2_HW_RSS_BROKEN))
rx_set_rss(sky2->netdev);

/* submit Rx ring */
for (i = 0; i < sky2->rx_pending; i++) {
re = sky2->rx_ring + i;
Expand Down Expand Up @@ -2534,6 +2570,14 @@ static void sky2_rx_checksum(struct sky2_port *sky2, u32 status)
}
}

static void sky2_rx_hash(struct sky2_port *sky2, u32 status)
{
struct sk_buff *skb;

skb = sky2->rx_ring[sky2->rx_next].skb;
skb->rxhash = le32_to_cpu(status);
}

/* Process status response ring */
static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx)
{
Expand Down Expand Up @@ -2606,6 +2650,10 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx)
sky2_rx_checksum(sky2, status);
break;

case OP_RSS_HASH:
sky2_rx_hash(sky2, status);
break;

case OP_TXINDEXLE:
/* TX index reports status for both ports */
sky2_tx_done(hw->dev[0], status & 0xfff);
Expand Down Expand Up @@ -2960,6 +3008,8 @@ static int __devinit sky2_init(struct sky2_hw *hw)
switch(hw->chip_id) {
case CHIP_ID_YUKON_XL:
hw->flags = SKY2_HW_GIGABIT | SKY2_HW_NEWER_PHY;
if (hw->chip_rev < CHIP_REV_YU_XL_A2)
hw->flags |= SKY2_HW_RSS_BROKEN;
break;

case CHIP_ID_YUKON_EC_U:
Expand All @@ -2985,10 +3035,11 @@ static int __devinit sky2_init(struct sky2_hw *hw)
dev_err(&hw->pdev->dev, "unsupported revision Yukon-EC rev A1\n");
return -EOPNOTSUPP;
}
hw->flags = SKY2_HW_GIGABIT;
hw->flags = SKY2_HW_GIGABIT | SKY2_HW_RSS_BROKEN;
break;

case CHIP_ID_YUKON_FE:
hw->flags = SKY2_HW_RSS_BROKEN;
break;

case CHIP_ID_YUKON_FE_P:
Expand Down Expand Up @@ -4112,6 +4163,25 @@ static int sky2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom
return sky2_vpd_write(sky2->hw, cap, data, eeprom->offset, eeprom->len);
}

static int sky2_set_flags(struct net_device *dev, u32 data)
{
struct sky2_port *sky2 = netdev_priv(dev);

if (data & ~ETH_FLAG_RXHASH)
return -EOPNOTSUPP;

if (data & ETH_FLAG_RXHASH) {
if (sky2->hw->flags & SKY2_HW_RSS_BROKEN)
return -EINVAL;

dev->features |= NETIF_F_RXHASH;
} else
dev->features &= ~NETIF_F_RXHASH;

rx_set_rss(dev);

return 0;
}

static const struct ethtool_ops sky2_ethtool_ops = {
.get_settings = sky2_get_settings,
Expand Down Expand Up @@ -4143,6 +4213,7 @@ static const struct ethtool_ops sky2_ethtool_ops = {
.phys_id = sky2_phys_id,
.get_sset_count = sky2_get_sset_count,
.get_ethtool_stats = sky2_get_ethtool_stats,
.set_flags = sky2_set_flags,
};

#ifdef CONFIG_SKY2_DEBUG
Expand Down Expand Up @@ -4496,6 +4567,10 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
if (highmem)
dev->features |= NETIF_F_HIGHDMA;

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

#ifdef SKY2_VLAN_TAG_USED
/* The workaround for FE+ status conflicts with VLAN tag detection. */
if (!(sky2->hw->chip_id == CHIP_ID_YUKON_FE_P &&
Expand Down Expand Up @@ -4692,7 +4767,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
goto err_out_iounmap;

/* ring for status responses */
hw->st_size = hw->ports * roundup_pow_of_two(2*RX_MAX_PENDING + TX_MAX_PENDING);
hw->st_size = hw->ports * roundup_pow_of_two(3*RX_MAX_PENDING + TX_MAX_PENDING);
hw->st_le = pci_alloc_consistent(pdev, hw->st_size * sizeof(struct sky2_status_le),
&hw->st_dma);
if (!hw->st_le)
Expand Down
14 changes: 14 additions & 0 deletions trunk/drivers/net/sky2.h
Original file line number Diff line number Diff line change
Expand Up @@ -694,8 +694,21 @@ enum {
TXA_CTRL = 0x0210,/* 8 bit Tx Arbiter Control Register */
TXA_TEST = 0x0211,/* 8 bit Tx Arbiter Test Register */
TXA_STAT = 0x0212,/* 8 bit Tx Arbiter Status Register */

RSS_KEY = 0x0220, /* RSS Key setup */
RSS_CFG = 0x0248, /* RSS Configuration */
};

enum {
HASH_TCP_IPV6_EX_CTRL = 1<<5,
HASH_IPV6_EX_CTRL = 1<<4,
HASH_TCP_IPV6_CTRL = 1<<3,
HASH_IPV6_CTRL = 1<<2,
HASH_TCP_IPV4_CTRL = 1<<1,
HASH_IPV4_CTRL = 1<<0,

HASH_ALL = 0x3f,
};

enum {
B6_EXT_REG = 0x0300,/* External registers (GENESIS only) */
Expand Down Expand Up @@ -2261,6 +2274,7 @@ struct sky2_hw {
#define SKY2_HW_NEW_LE 0x00000020 /* new LSOv2 format */
#define SKY2_HW_AUTO_TX_SUM 0x00000040 /* new IP decode for Tx */
#define SKY2_HW_ADV_POWER_CTL 0x00000080 /* additional PHY power regs */
#define SKY2_HW_RSS_BROKEN 0x00000100

u8 chip_id;
u8 chip_rev;
Expand Down

0 comments on commit 707fe74

Please sign in to comment.