aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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;