aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@vyatta.com>2010-04-24 23:04:12 -0400
committerDavid S. Miller <davem@davemloft.net>2010-04-24 23:04:12 -0400
commitbf73130d7f98c8c4db143e2dc4982f4eefd5d5e5 (patch)
tree19a73b4ce836c4a7224706de5febb77ab1ca0c7f
parentb7d6a4321195c32b548f0185a2fa0b8f6e02bcfc (diff)
sky2: add support for receive hashing
Sky2 hardware supports hardware receive hash calculation. Now that Receive Packet Steering is available, add support to enable it. This version does not depend on CONFIG_RPS. Also set_flags rejects all values except RXHASH, so driver won't have to change next time somebody adds a new one. Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/sky2.c79
-rw-r--r--drivers/net/sky2.h14
2 files changed, 91 insertions, 2 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 4f83f111bb20..a1b17fa34c76 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -1193,6 +1193,39 @@ static void rx_set_checksum(struct sky2_port *sky2)
1193 ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM); 1193 ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
1194} 1194}
1195 1195
1196/* Enable/disable receive hash calculation (RSS) */
1197static void rx_set_rss(struct net_device *dev)
1198{
1199 struct sky2_port *sky2 = netdev_priv(dev);
1200 struct sky2_hw *hw = sky2->hw;
1201 int i, nkeys = 4;
1202
1203 /* Supports IPv6 and other modes */
1204 if (hw->flags & SKY2_HW_NEW_LE) {
1205 nkeys = 10;
1206 sky2_write32(hw, SK_REG(sky2->port, RSS_CFG), HASH_ALL);
1207 }
1208
1209 /* Program RSS initial values */
1210 if (dev->features & NETIF_F_RXHASH) {
1211 u32 key[nkeys];
1212
1213 get_random_bytes(key, nkeys * sizeof(u32));
1214 for (i = 0; i < nkeys; i++)
1215 sky2_write32(hw, SK_REG(sky2->port, RSS_KEY + i * 4),
1216 key[i]);
1217
1218 /* Need to turn on (undocumented) flag to make hashing work */
1219 sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T),
1220 RX_STFW_ENA);
1221
1222 sky2_write32(hw, Q_ADDR(rxqaddr[sky2->port], Q_CSR),
1223 BMU_ENA_RX_RSS_HASH);
1224 } else
1225 sky2_write32(hw, Q_ADDR(rxqaddr[sky2->port], Q_CSR),
1226 BMU_DIS_RX_RSS_HASH);
1227}
1228
1196/* 1229/*
1197 * The RX Stop command will not work for Yukon-2 if the BMU does not 1230 * The RX Stop command will not work for Yukon-2 if the BMU does not
1198 * reach the end of packet and since we can't make sure that we have 1231 * reach the end of packet and since we can't make sure that we have
@@ -1425,6 +1458,9 @@ static void sky2_rx_start(struct sky2_port *sky2)
1425 if (!(hw->flags & SKY2_HW_NEW_LE)) 1458 if (!(hw->flags & SKY2_HW_NEW_LE))
1426 rx_set_checksum(sky2); 1459 rx_set_checksum(sky2);
1427 1460
1461 if (!(hw->flags & SKY2_HW_RSS_BROKEN))
1462 rx_set_rss(sky2->netdev);
1463
1428 /* submit Rx ring */ 1464 /* submit Rx ring */
1429 for (i = 0; i < sky2->rx_pending; i++) { 1465 for (i = 0; i < sky2->rx_pending; i++) {
1430 re = sky2->rx_ring + i; 1466 re = sky2->rx_ring + i;
@@ -2534,6 +2570,14 @@ static void sky2_rx_checksum(struct sky2_port *sky2, u32 status)
2534 } 2570 }
2535} 2571}
2536 2572
2573static void sky2_rx_hash(struct sky2_port *sky2, u32 status)
2574{
2575 struct sk_buff *skb;
2576
2577 skb = sky2->rx_ring[sky2->rx_next].skb;
2578 skb->rxhash = le32_to_cpu(status);
2579}
2580
2537/* Process status response ring */ 2581/* Process status response ring */
2538static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx) 2582static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx)
2539{ 2583{
@@ -2606,6 +2650,10 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx)
2606 sky2_rx_checksum(sky2, status); 2650 sky2_rx_checksum(sky2, status);
2607 break; 2651 break;
2608 2652
2653 case OP_RSS_HASH:
2654 sky2_rx_hash(sky2, status);
2655 break;
2656
2609 case OP_TXINDEXLE: 2657 case OP_TXINDEXLE:
2610 /* TX index reports status for both ports */ 2658 /* TX index reports status for both ports */
2611 sky2_tx_done(hw->dev[0], status & 0xfff); 2659 sky2_tx_done(hw->dev[0], status & 0xfff);
@@ -2960,6 +3008,8 @@ static int __devinit sky2_init(struct sky2_hw *hw)
2960 switch(hw->chip_id) { 3008 switch(hw->chip_id) {
2961 case CHIP_ID_YUKON_XL: 3009 case CHIP_ID_YUKON_XL:
2962 hw->flags = SKY2_HW_GIGABIT | SKY2_HW_NEWER_PHY; 3010 hw->flags = SKY2_HW_GIGABIT | SKY2_HW_NEWER_PHY;
3011 if (hw->chip_rev < CHIP_REV_YU_XL_A2)
3012 hw->flags |= SKY2_HW_RSS_BROKEN;
2963 break; 3013 break;
2964 3014
2965 case CHIP_ID_YUKON_EC_U: 3015 case CHIP_ID_YUKON_EC_U:
@@ -2985,10 +3035,11 @@ static int __devinit sky2_init(struct sky2_hw *hw)
2985 dev_err(&hw->pdev->dev, "unsupported revision Yukon-EC rev A1\n"); 3035 dev_err(&hw->pdev->dev, "unsupported revision Yukon-EC rev A1\n");
2986 return -EOPNOTSUPP; 3036 return -EOPNOTSUPP;
2987 } 3037 }
2988 hw->flags = SKY2_HW_GIGABIT; 3038 hw->flags = SKY2_HW_GIGABIT | SKY2_HW_RSS_BROKEN;
2989 break; 3039 break;
2990 3040
2991 case CHIP_ID_YUKON_FE: 3041 case CHIP_ID_YUKON_FE:
3042 hw->flags = SKY2_HW_RSS_BROKEN;
2992 break; 3043 break;
2993 3044
2994 case CHIP_ID_YUKON_FE_P: 3045 case CHIP_ID_YUKON_FE_P:
@@ -4112,6 +4163,25 @@ static int sky2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom
4112 return sky2_vpd_write(sky2->hw, cap, data, eeprom->offset, eeprom->len); 4163 return sky2_vpd_write(sky2->hw, cap, data, eeprom->offset, eeprom->len);
4113} 4164}
4114 4165
4166static int sky2_set_flags(struct net_device *dev, u32 data)
4167{
4168 struct sky2_port *sky2 = netdev_priv(dev);
4169
4170 if (data & ~ETH_FLAG_RXHASH)
4171 return -EOPNOTSUPP;
4172
4173 if (data & ETH_FLAG_RXHASH) {
4174 if (sky2->hw->flags & SKY2_HW_RSS_BROKEN)
4175 return -EINVAL;
4176
4177 dev->features |= NETIF_F_RXHASH;
4178 } else
4179 dev->features &= ~NETIF_F_RXHASH;
4180
4181 rx_set_rss(dev);
4182
4183 return 0;
4184}
4115 4185
4116static const struct ethtool_ops sky2_ethtool_ops = { 4186static const struct ethtool_ops sky2_ethtool_ops = {
4117 .get_settings = sky2_get_settings, 4187 .get_settings = sky2_get_settings,
@@ -4143,6 +4213,7 @@ static const struct ethtool_ops sky2_ethtool_ops = {
4143 .phys_id = sky2_phys_id, 4213 .phys_id = sky2_phys_id,
4144 .get_sset_count = sky2_get_sset_count, 4214 .get_sset_count = sky2_get_sset_count,
4145 .get_ethtool_stats = sky2_get_ethtool_stats, 4215 .get_ethtool_stats = sky2_get_ethtool_stats,
4216 .set_flags = sky2_set_flags,
4146}; 4217};
4147 4218
4148#ifdef CONFIG_SKY2_DEBUG 4219#ifdef CONFIG_SKY2_DEBUG
@@ -4496,6 +4567,10 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
4496 if (highmem) 4567 if (highmem)
4497 dev->features |= NETIF_F_HIGHDMA; 4568 dev->features |= NETIF_F_HIGHDMA;
4498 4569
4570 /* Enable receive hashing unless hardware is known broken */
4571 if (!(hw->flags & SKY2_HW_RSS_BROKEN))
4572 dev->features |= NETIF_F_RXHASH;
4573
4499#ifdef SKY2_VLAN_TAG_USED 4574#ifdef SKY2_VLAN_TAG_USED
4500 /* The workaround for FE+ status conflicts with VLAN tag detection. */ 4575 /* The workaround for FE+ status conflicts with VLAN tag detection. */
4501 if (!(sky2->hw->chip_id == CHIP_ID_YUKON_FE_P && 4576 if (!(sky2->hw->chip_id == CHIP_ID_YUKON_FE_P &&
@@ -4692,7 +4767,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
4692 goto err_out_iounmap; 4767 goto err_out_iounmap;
4693 4768
4694 /* ring for status responses */ 4769 /* ring for status responses */
4695 hw->st_size = hw->ports * roundup_pow_of_two(2*RX_MAX_PENDING + TX_MAX_PENDING); 4770 hw->st_size = hw->ports * roundup_pow_of_two(3*RX_MAX_PENDING + TX_MAX_PENDING);
4696 hw->st_le = pci_alloc_consistent(pdev, hw->st_size * sizeof(struct sky2_status_le), 4771 hw->st_le = pci_alloc_consistent(pdev, hw->st_size * sizeof(struct sky2_status_le),
4697 &hw->st_dma); 4772 &hw->st_dma);
4698 if (!hw->st_le) 4773 if (!hw->st_le)
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h
index 125b5bd01524..545a3f41ef56 100644
--- a/drivers/net/sky2.h
+++ b/drivers/net/sky2.h
@@ -694,8 +694,21 @@ enum {
694 TXA_CTRL = 0x0210,/* 8 bit Tx Arbiter Control Register */ 694 TXA_CTRL = 0x0210,/* 8 bit Tx Arbiter Control Register */
695 TXA_TEST = 0x0211,/* 8 bit Tx Arbiter Test Register */ 695 TXA_TEST = 0x0211,/* 8 bit Tx Arbiter Test Register */
696 TXA_STAT = 0x0212,/* 8 bit Tx Arbiter Status Register */ 696 TXA_STAT = 0x0212,/* 8 bit Tx Arbiter Status Register */
697
698 RSS_KEY = 0x0220, /* RSS Key setup */
699 RSS_CFG = 0x0248, /* RSS Configuration */
697}; 700};
698 701
702enum {
703 HASH_TCP_IPV6_EX_CTRL = 1<<5,
704 HASH_IPV6_EX_CTRL = 1<<4,
705 HASH_TCP_IPV6_CTRL = 1<<3,
706 HASH_IPV6_CTRL = 1<<2,
707 HASH_TCP_IPV4_CTRL = 1<<1,
708 HASH_IPV4_CTRL = 1<<0,
709
710 HASH_ALL = 0x3f,
711};
699 712
700enum { 713enum {
701 B6_EXT_REG = 0x0300,/* External registers (GENESIS only) */ 714 B6_EXT_REG = 0x0300,/* External registers (GENESIS only) */
@@ -2261,6 +2274,7 @@ struct sky2_hw {
2261#define SKY2_HW_NEW_LE 0x00000020 /* new LSOv2 format */ 2274#define SKY2_HW_NEW_LE 0x00000020 /* new LSOv2 format */
2262#define SKY2_HW_AUTO_TX_SUM 0x00000040 /* new IP decode for Tx */ 2275#define SKY2_HW_AUTO_TX_SUM 0x00000040 /* new IP decode for Tx */
2263#define SKY2_HW_ADV_POWER_CTL 0x00000080 /* additional PHY power regs */ 2276#define SKY2_HW_ADV_POWER_CTL 0x00000080 /* additional PHY power regs */
2277#define SKY2_HW_RSS_BROKEN 0x00000100
2264 2278
2265 u8 chip_id; 2279 u8 chip_id;
2266 u8 chip_rev; 2280 u8 chip_rev;