Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Stephen Hemminger and committed by
David S. Miller
bf73130d b7d6a432

+91 -2
+77 -2
drivers/net/sky2.c
··· 1193 1193 ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM); 1194 1194 } 1195 1195 1196 + /* Enable/disable receive hash calculation (RSS) */ 1197 + static 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 1230 * The RX Stop command will not work for Yukon-2 if the BMU does not 1198 1231 * reach the end of packet and since we can't make sure that we have ··· 1457 1424 1458 1425 if (!(hw->flags & SKY2_HW_NEW_LE)) 1459 1426 rx_set_checksum(sky2); 1427 + 1428 + if (!(hw->flags & SKY2_HW_RSS_BROKEN)) 1429 + rx_set_rss(sky2->netdev); 1460 1430 1461 1431 /* submit Rx ring */ 1462 1432 for (i = 0; i < sky2->rx_pending; i++) { ··· 2570 2534 } 2571 2535 } 2572 2536 2537 + static void sky2_rx_hash(struct sky2_port *sky2, u32 status) 2538 + { 2539 + struct sk_buff *skb; 2540 + 2541 + skb = sky2->rx_ring[sky2->rx_next].skb; 2542 + skb->rxhash = le32_to_cpu(status); 2543 + } 2544 + 2573 2545 /* Process status response ring */ 2574 2546 static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx) 2575 2547 { ··· 2648 2604 case OP_RXCHKS: 2649 2605 if (likely(sky2->flags & SKY2_FLAG_RX_CHECKSUM)) 2650 2606 sky2_rx_checksum(sky2, status); 2607 + break; 2608 + 2609 + case OP_RSS_HASH: 2610 + sky2_rx_hash(sky2, status); 2651 2611 break; 2652 2612 2653 2613 case OP_TXINDEXLE: ··· 3008 2960 switch(hw->chip_id) { 3009 2961 case CHIP_ID_YUKON_XL: 3010 2962 hw->flags = SKY2_HW_GIGABIT | SKY2_HW_NEWER_PHY; 2963 + if (hw->chip_rev < CHIP_REV_YU_XL_A2) 2964 + hw->flags |= SKY2_HW_RSS_BROKEN; 3011 2965 break; 3012 2966 3013 2967 case CHIP_ID_YUKON_EC_U: ··· 3035 2985 dev_err(&hw->pdev->dev, "unsupported revision Yukon-EC rev A1\n"); 3036 2986 return -EOPNOTSUPP; 3037 2987 } 3038 - hw->flags = SKY2_HW_GIGABIT; 2988 + hw->flags = SKY2_HW_GIGABIT | SKY2_HW_RSS_BROKEN; 3039 2989 break; 3040 2990 3041 2991 case CHIP_ID_YUKON_FE: 2992 + hw->flags = SKY2_HW_RSS_BROKEN; 3042 2993 break; 3043 2994 3044 2995 case CHIP_ID_YUKON_FE_P: ··· 4163 4112 return sky2_vpd_write(sky2->hw, cap, data, eeprom->offset, eeprom->len); 4164 4113 } 4165 4114 4115 + static int sky2_set_flags(struct net_device *dev, u32 data) 4116 + { 4117 + struct sky2_port *sky2 = netdev_priv(dev); 4118 + 4119 + if (data & ~ETH_FLAG_RXHASH) 4120 + return -EOPNOTSUPP; 4121 + 4122 + if (data & ETH_FLAG_RXHASH) { 4123 + if (sky2->hw->flags & SKY2_HW_RSS_BROKEN) 4124 + return -EINVAL; 4125 + 4126 + dev->features |= NETIF_F_RXHASH; 4127 + } else 4128 + dev->features &= ~NETIF_F_RXHASH; 4129 + 4130 + rx_set_rss(dev); 4131 + 4132 + return 0; 4133 + } 4166 4134 4167 4135 static const struct ethtool_ops sky2_ethtool_ops = { 4168 4136 .get_settings = sky2_get_settings, ··· 4213 4143 .phys_id = sky2_phys_id, 4214 4144 .get_sset_count = sky2_get_sset_count, 4215 4145 .get_ethtool_stats = sky2_get_ethtool_stats, 4146 + .set_flags = sky2_set_flags, 4216 4147 }; 4217 4148 4218 4149 #ifdef CONFIG_SKY2_DEBUG ··· 4567 4496 if (highmem) 4568 4497 dev->features |= NETIF_F_HIGHDMA; 4569 4498 4499 + /* Enable receive hashing unless hardware is known broken */ 4500 + if (!(hw->flags & SKY2_HW_RSS_BROKEN)) 4501 + dev->features |= NETIF_F_RXHASH; 4502 + 4570 4503 #ifdef SKY2_VLAN_TAG_USED 4571 4504 /* The workaround for FE+ status conflicts with VLAN tag detection. */ 4572 4505 if (!(sky2->hw->chip_id == CHIP_ID_YUKON_FE_P && ··· 4767 4692 goto err_out_iounmap; 4768 4693 4769 4694 /* ring for status responses */ 4770 - hw->st_size = hw->ports * roundup_pow_of_two(2*RX_MAX_PENDING + TX_MAX_PENDING); 4695 + hw->st_size = hw->ports * roundup_pow_of_two(3*RX_MAX_PENDING + TX_MAX_PENDING); 4771 4696 hw->st_le = pci_alloc_consistent(pdev, hw->st_size * sizeof(struct sky2_status_le), 4772 4697 &hw->st_dma); 4773 4698 if (!hw->st_le)
+14
drivers/net/sky2.h
··· 694 694 TXA_CTRL = 0x0210,/* 8 bit Tx Arbiter Control Register */ 695 695 TXA_TEST = 0x0211,/* 8 bit Tx Arbiter Test Register */ 696 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 702 + enum { 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 700 713 enum { 701 714 B6_EXT_REG = 0x0300,/* External registers (GENESIS only) */ ··· 2274 2261 #define SKY2_HW_NEW_LE 0x00000020 /* new LSOv2 format */ 2275 2262 #define SKY2_HW_AUTO_TX_SUM 0x00000040 /* new IP decode for Tx */ 2276 2263 #define SKY2_HW_ADV_POWER_CTL 0x00000080 /* additional PHY power regs */ 2264 + #define SKY2_HW_RSS_BROKEN 0x00000100 2277 2265 2278 2266 u8 chip_id; 2279 2267 u8 chip_rev;