Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 289740
b: refs/heads/master
c: 70495a5
h: refs/heads/master
v: v3
  • Loading branch information
Bruce Allan authored and Jeff Kirsher committed Jan 26, 2012
1 parent e30c63e commit 365f7ab
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 7 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: afd12939a09ca8f96cf8349c913dc143471c9b3c
refs/heads/master: 70495a500d787c0c90a136acf454cb7d0eecd82e
8 changes: 8 additions & 0 deletions trunk/drivers/net/ethernet/intel/e1000e/defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,13 @@
E1000_RXDEXT_STATERR_CXE | \
E1000_RXDEXT_STATERR_RXE)

#define E1000_MRQC_RSS_FIELD_MASK 0xFFFF0000
#define E1000_MRQC_RSS_FIELD_IPV4_TCP 0x00010000
#define E1000_MRQC_RSS_FIELD_IPV4 0x00020000
#define E1000_MRQC_RSS_FIELD_IPV6_TCP_EX 0x00040000
#define E1000_MRQC_RSS_FIELD_IPV6 0x00100000
#define E1000_MRQC_RSS_FIELD_IPV6_TCP 0x00200000

#define E1000_RXDPS_HDRSTAT_HDRSP 0x00008000

/* Management Control */
Expand Down Expand Up @@ -326,6 +333,7 @@
/* Receive Checksum Control */
#define E1000_RXCSUM_TUOFL 0x00000200 /* TCP / UDP checksum offload */
#define E1000_RXCSUM_IPPCSE 0x00001000 /* IP payload checksum enable */
#define E1000_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */

/* Header split receive */
#define E1000_RFCTL_NFSW_DIS 0x00000040
Expand Down
48 changes: 48 additions & 0 deletions trunk/drivers/net/ethernet/intel/e1000e/ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -1955,6 +1955,53 @@ static void e1000_get_strings(struct net_device *netdev, u32 stringset,
}
}

static int e1000_get_rxnfc(struct net_device *netdev,
struct ethtool_rxnfc *info, u32 *rule_locs)
{
info->data = 0;

switch (info->cmd) {
case ETHTOOL_GRXFH: {
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
u32 mrqc = er32(MRQC);

if (!(mrqc & E1000_MRQC_RSS_FIELD_MASK))
return 0;

switch (info->flow_type) {
case TCP_V4_FLOW:
if (mrqc & E1000_MRQC_RSS_FIELD_IPV4_TCP)
info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
/* fall through */
case UDP_V4_FLOW:
case SCTP_V4_FLOW:
case AH_ESP_V4_FLOW:
case IPV4_FLOW:
if (mrqc & E1000_MRQC_RSS_FIELD_IPV4)
info->data |= RXH_IP_SRC | RXH_IP_DST;
break;
case TCP_V6_FLOW:
if (mrqc & E1000_MRQC_RSS_FIELD_IPV6_TCP)
info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
/* fall through */
case UDP_V6_FLOW:
case SCTP_V6_FLOW:
case AH_ESP_V6_FLOW:
case IPV6_FLOW:
if (mrqc & E1000_MRQC_RSS_FIELD_IPV6)
info->data |= RXH_IP_SRC | RXH_IP_DST;
break;
default:
break;
}
return 0;
}
default:
return -EOPNOTSUPP;
}
}

static const struct ethtool_ops e1000_ethtool_ops = {
.get_settings = e1000_get_settings,
.set_settings = e1000_set_settings,
Expand All @@ -1981,6 +2028,7 @@ static const struct ethtool_ops e1000_ethtool_ops = {
.get_sset_count = e1000e_get_sset_count,
.get_coalesce = e1000_get_coalesce,
.set_coalesce = e1000_set_coalesce,
.get_rxnfc = e1000_get_rxnfc,
};

void e1000e_set_ethtool_ops(struct net_device *netdev)
Expand Down
5 changes: 5 additions & 0 deletions trunk/drivers/net/ethernet/intel/e1000e/hw.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ enum e1e_registers {
E1000_WUC = 0x05800, /* Wakeup Control - RW */
E1000_WUFC = 0x05808, /* Wakeup Filter Control - RW */
E1000_WUS = 0x05810, /* Wakeup Status - RO */
E1000_MRQC = 0x05818, /* Multiple Receive Control - RW */
E1000_MANC = 0x05820, /* Management Control - RW */
E1000_FFLT = 0x05F00, /* Flexible Filter Length Table - RW Array */
E1000_HOST_IF = 0x08800, /* Host Interface */
Expand All @@ -219,6 +220,10 @@ enum e1e_registers {
E1000_SWSM = 0x05B50, /* SW Semaphore */
E1000_FWSM = 0x05B54, /* FW Semaphore */
E1000_SWSM2 = 0x05B58, /* Driver-only SW semaphore */
E1000_RETA_BASE = 0x05C00, /* Redirection Table - RW */
#define E1000_RETA(_n) (E1000_RETA_BASE + ((_n) * 4))
E1000_RSSRK_BASE = 0x05C80, /* RSS Random Key - RW */
#define E1000_RSSRK(_n) (E1000_RSSRK_BASE + ((_n) * 4))
E1000_FFLT_DBG = 0x05F04, /* Debug Register */
E1000_PCH_RAICC_BASE = 0x05F50, /* Receive Address Initial CRC */
#define E1000_PCH_RAICC(_n) (E1000_PCH_RAICC_BASE + ((_n) * 4))
Expand Down
90 changes: 84 additions & 6 deletions trunk/drivers/net/ethernet/intel/e1000e/netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -845,6 +845,13 @@ static void e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter,
}
}

static inline void e1000_rx_hash(struct net_device *netdev, __le32 rss,
struct sk_buff *skb)
{
if (netdev->features & NETIF_F_RXHASH)
skb->rxhash = le32_to_cpu(rss);
}

/**
* e1000_clean_rx_irq - Send received data up the network stack; legacy
* @adapter: board private structure
Expand Down Expand Up @@ -964,6 +971,8 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
e1000_rx_checksum(adapter, staterr,
rx_desc->wb.lower.hi_dword.csum_ip.csum, skb);

e1000_rx_hash(netdev, rx_desc->wb.lower.hi_dword.rss, skb);

e1000_receive_skb(adapter, netdev, skb, staterr,
rx_desc->wb.upper.vlan);

Expand Down Expand Up @@ -1325,6 +1334,8 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
e1000_rx_checksum(adapter, staterr,
rx_desc->wb.lower.hi_dword.csum_ip.csum, skb);

e1000_rx_hash(netdev, rx_desc->wb.lower.hi_dword.rss, skb);

if (rx_desc->wb.upper.header_status &
cpu_to_le16(E1000_RXDPS_HDRSTAT_HDRSP))
adapter->rx_hdr_split++;
Expand Down Expand Up @@ -1497,6 +1508,8 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
e1000_rx_checksum(adapter, staterr,
rx_desc->wb.lower.hi_dword.csum_ip.csum, skb);

e1000_rx_hash(netdev, rx_desc->wb.lower.hi_dword.rss, skb);

/* probably a little skewed due to removing CRC */
total_rx_bytes += skb->len;
total_rx_packets++;
Expand Down Expand Up @@ -3271,6 +3284,42 @@ static void e1000e_set_rx_mode(struct net_device *netdev)
e1000e_vlan_strip_disable(adapter);
}

static void e1000e_setup_rss_hash(struct e1000_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
u32 mrqc, rxcsum;
int i;
static const u32 rsskey[10] = {
0xda565a6d, 0xc20e5b25, 0x3d256741, 0xb08fa343, 0xcb2bcad0,
0xb4307bae, 0xa32dcb77, 0x0cf23080, 0x3bb7426a, 0xfa01acbe
};

/* Fill out hash function seed */
for (i = 0; i < 10; i++)
ew32(RSSRK(i), rsskey[i]);

/* Direct all traffic to queue 0 */
for (i = 0; i < 32; i++)
ew32(RETA(i), 0);

/*
* Disable raw packet checksumming so that RSS hash is placed in
* descriptor on writeback.
*/
rxcsum = er32(RXCSUM);
rxcsum |= E1000_RXCSUM_PCSD;

ew32(RXCSUM, rxcsum);

mrqc = (E1000_MRQC_RSS_FIELD_IPV4 |
E1000_MRQC_RSS_FIELD_IPV4_TCP |
E1000_MRQC_RSS_FIELD_IPV6 |
E1000_MRQC_RSS_FIELD_IPV6_TCP |
E1000_MRQC_RSS_FIELD_IPV6_TCP_EX);

ew32(MRQC, mrqc);
}

/**
* e1000_configure - configure the hardware for Rx and Tx
* @adapter: private board structure
Expand All @@ -3283,6 +3332,9 @@ static void e1000_configure(struct e1000_adapter *adapter)
e1000_init_manageability_pt(adapter);

e1000_configure_tx(adapter);

if (adapter->netdev->features & NETIF_F_RXHASH)
e1000e_setup_rss_hash(adapter);
e1000_setup_rctl(adapter);
e1000_configure_rx(adapter);
adapter->alloc_rx_buf(adapter, e1000_desc_unused(adapter->rx_ring),
Expand Down Expand Up @@ -5168,10 +5220,22 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;

/* Jumbo frame support */
if ((max_frame > ETH_FRAME_LEN + ETH_FCS_LEN) &&
!(adapter->flags & FLAG_HAS_JUMBO_FRAMES)) {
e_err("Jumbo Frames not supported.\n");
return -EINVAL;
if (max_frame > ETH_FRAME_LEN + ETH_FCS_LEN) {
if (!(adapter->flags & FLAG_HAS_JUMBO_FRAMES)) {
e_err("Jumbo Frames not supported.\n");
return -EINVAL;
}

/*
* IP payload checksum (enabled with jumbos/packet-split when
* Rx checksum is enabled) and generation of RSS hash is
* mutually exclusive in the hardware.
*/
if ((netdev->features & NETIF_F_RXCSUM) &&
(netdev->features & NETIF_F_RXHASH)) {
e_err("Jumbo frames cannot be enabled when both receive checksum offload and receive hashing are enabled. Disable one of the receive offload features before enabling jumbos.\n");
return -EINVAL;
}
}

/* Supported frame sizes */
Expand Down Expand Up @@ -5934,7 +5998,7 @@ static void e1000_eeprom_checks(struct e1000_adapter *adapter)
}

static int e1000_set_features(struct net_device *netdev,
netdev_features_t features)
netdev_features_t features)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
netdev_features_t changed = features ^ netdev->features;
Expand All @@ -5943,9 +6007,22 @@ static int e1000_set_features(struct net_device *netdev,
adapter->flags |= FLAG_TSO_FORCE;

if (!(changed & (NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX |
NETIF_F_RXCSUM)))
NETIF_F_RXCSUM | NETIF_F_RXHASH)))
return 0;

/*
* IP payload checksum (enabled with jumbos/packet-split when Rx
* checksum is enabled) and generation of RSS hash is mutually
* exclusive in the hardware.
*/
if (adapter->rx_ps_pages &&
(features & NETIF_F_RXCSUM) && (features & NETIF_F_RXHASH)) {
e_err("Enabling both receive checksum offload and receive hashing is not possible with jumbo frames. Disable jumbos or enable only one of the receive offload features.\n");
return -EINVAL;
}

netdev->features = features;

if (netif_running(netdev))
e1000e_reinit_locked(adapter);
else
Expand Down Expand Up @@ -6136,6 +6213,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
NETIF_F_HW_VLAN_TX |
NETIF_F_TSO |
NETIF_F_TSO6 |
NETIF_F_RXHASH |
NETIF_F_RXCSUM |
NETIF_F_HW_CSUM);

Expand Down

0 comments on commit 365f7ab

Please sign in to comment.