diff options
author | Ben Greear <greearb@candelatech.com> | 2012-02-17 08:43:05 -0500 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2012-03-01 01:36:56 -0500 |
commit | 719cdac54e0237837251a32a3d690bfe9c1e9bed (patch) | |
tree | 889f37acac24ca60453ec0347b987dcf46d48e6e | |
parent | 06b8db9cac717fcd6b8410b9efae8aca33b4b9e6 (diff) |
e100: Support RXFCS feature flag.
This allows e100 to be configured to append the
Ethernet FCS to the skb.
Useful for sniffing networks.
Signed-off-by: Ben Greear <greearb@candelatech.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
-rw-r--r-- | drivers/net/ethernet/intel/e100.c | 35 |
1 files changed, 30 insertions, 5 deletions
diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c index 485ab8cdac48..3ecbdedf6135 100644 --- a/drivers/net/ethernet/intel/e100.c +++ b/drivers/net/ethernet/intel/e100.c | |||
@@ -1075,7 +1075,7 @@ static void e100_get_defaults(struct nic *nic) | |||
1075 | /* Template for a freshly allocated RFD */ | 1075 | /* Template for a freshly allocated RFD */ |
1076 | nic->blank_rfd.command = 0; | 1076 | nic->blank_rfd.command = 0; |
1077 | nic->blank_rfd.rbd = cpu_to_le32(0xFFFFFFFF); | 1077 | nic->blank_rfd.rbd = cpu_to_le32(0xFFFFFFFF); |
1078 | nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN); | 1078 | nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN + ETH_FCS_LEN); |
1079 | 1079 | ||
1080 | /* MII setup */ | 1080 | /* MII setup */ |
1081 | nic->mii.phy_id_mask = 0x1F; | 1081 | nic->mii.phy_id_mask = 0x1F; |
@@ -1089,6 +1089,7 @@ static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) | |||
1089 | { | 1089 | { |
1090 | struct config *config = &cb->u.config; | 1090 | struct config *config = &cb->u.config; |
1091 | u8 *c = (u8 *)config; | 1091 | u8 *c = (u8 *)config; |
1092 | struct net_device *netdev = nic->netdev; | ||
1092 | 1093 | ||
1093 | cb->command = cpu_to_le16(cb_config); | 1094 | cb->command = cpu_to_le16(cb_config); |
1094 | 1095 | ||
@@ -1132,6 +1133,9 @@ static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) | |||
1132 | config->promiscuous_mode = 0x1; /* 1=on, 0=off */ | 1133 | config->promiscuous_mode = 0x1; /* 1=on, 0=off */ |
1133 | } | 1134 | } |
1134 | 1135 | ||
1136 | if (unlikely(netdev->features & NETIF_F_RXFCS)) | ||
1137 | config->rx_crc_transfer = 0x1; /* 1=save, 0=discard */ | ||
1138 | |||
1135 | if (nic->flags & multicast_all) | 1139 | if (nic->flags & multicast_all) |
1136 | config->multicast_all = 0x1; /* 1=accept, 0=no */ | 1140 | config->multicast_all = 0x1; /* 1=accept, 0=no */ |
1137 | 1141 | ||
@@ -1881,7 +1885,7 @@ static inline void e100_start_receiver(struct nic *nic, struct rx *rx) | |||
1881 | } | 1885 | } |
1882 | } | 1886 | } |
1883 | 1887 | ||
1884 | #define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN) | 1888 | #define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN + ETH_FCS_LEN) |
1885 | static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) | 1889 | static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) |
1886 | { | 1890 | { |
1887 | if (!(rx->skb = netdev_alloc_skb_ip_align(nic->netdev, RFD_BUF_LEN))) | 1891 | if (!(rx->skb = netdev_alloc_skb_ip_align(nic->netdev, RFD_BUF_LEN))) |
@@ -1919,6 +1923,7 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx, | |||
1919 | struct sk_buff *skb = rx->skb; | 1923 | struct sk_buff *skb = rx->skb; |
1920 | struct rfd *rfd = (struct rfd *)skb->data; | 1924 | struct rfd *rfd = (struct rfd *)skb->data; |
1921 | u16 rfd_status, actual_size; | 1925 | u16 rfd_status, actual_size; |
1926 | u16 fcs_pad = 0; | ||
1922 | 1927 | ||
1923 | if (unlikely(work_done && *work_done >= work_to_do)) | 1928 | if (unlikely(work_done && *work_done >= work_to_do)) |
1924 | return -EAGAIN; | 1929 | return -EAGAIN; |
@@ -1951,6 +1956,8 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx, | |||
1951 | } | 1956 | } |
1952 | 1957 | ||
1953 | /* Get actual data size */ | 1958 | /* Get actual data size */ |
1959 | if (unlikely(dev->features & NETIF_F_RXFCS)) | ||
1960 | fcs_pad = 4; | ||
1954 | actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF; | 1961 | actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF; |
1955 | if (unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd))) | 1962 | if (unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd))) |
1956 | actual_size = RFD_BUF_LEN - sizeof(struct rfd); | 1963 | actual_size = RFD_BUF_LEN - sizeof(struct rfd); |
@@ -1980,13 +1987,13 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx, | |||
1980 | if (unlikely(!(rfd_status & cb_ok))) { | 1987 | if (unlikely(!(rfd_status & cb_ok))) { |
1981 | /* Don't indicate if hardware indicates errors */ | 1988 | /* Don't indicate if hardware indicates errors */ |
1982 | dev_kfree_skb_any(skb); | 1989 | dev_kfree_skb_any(skb); |
1983 | } else if (actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) { | 1990 | } else if (actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN + fcs_pad) { |
1984 | /* Don't indicate oversized frames */ | 1991 | /* Don't indicate oversized frames */ |
1985 | nic->rx_over_length_errors++; | 1992 | nic->rx_over_length_errors++; |
1986 | dev_kfree_skb_any(skb); | 1993 | dev_kfree_skb_any(skb); |
1987 | } else { | 1994 | } else { |
1988 | dev->stats.rx_packets++; | 1995 | dev->stats.rx_packets++; |
1989 | dev->stats.rx_bytes += actual_size; | 1996 | dev->stats.rx_bytes += (actual_size - fcs_pad); |
1990 | netif_receive_skb(skb); | 1997 | netif_receive_skb(skb); |
1991 | if (work_done) | 1998 | if (work_done) |
1992 | (*work_done)++; | 1999 | (*work_done)++; |
@@ -2058,7 +2065,8 @@ static void e100_rx_clean(struct nic *nic, unsigned int *work_done, | |||
2058 | pci_dma_sync_single_for_device(nic->pdev, | 2065 | pci_dma_sync_single_for_device(nic->pdev, |
2059 | old_before_last_rx->dma_addr, sizeof(struct rfd), | 2066 | old_before_last_rx->dma_addr, sizeof(struct rfd), |
2060 | PCI_DMA_BIDIRECTIONAL); | 2067 | PCI_DMA_BIDIRECTIONAL); |
2061 | old_before_last_rfd->size = cpu_to_le16(VLAN_ETH_FRAME_LEN); | 2068 | old_before_last_rfd->size = cpu_to_le16(VLAN_ETH_FRAME_LEN |
2069 | + ETH_FCS_LEN); | ||
2062 | pci_dma_sync_single_for_device(nic->pdev, | 2070 | pci_dma_sync_single_for_device(nic->pdev, |
2063 | old_before_last_rx->dma_addr, sizeof(struct rfd), | 2071 | old_before_last_rx->dma_addr, sizeof(struct rfd), |
2064 | PCI_DMA_BIDIRECTIONAL); | 2072 | PCI_DMA_BIDIRECTIONAL); |
@@ -2729,6 +2737,20 @@ static int e100_close(struct net_device *netdev) | |||
2729 | return 0; | 2737 | return 0; |
2730 | } | 2738 | } |
2731 | 2739 | ||
2740 | static int e100_set_features(struct net_device *netdev, | ||
2741 | netdev_features_t features) | ||
2742 | { | ||
2743 | struct nic *nic = netdev_priv(netdev); | ||
2744 | netdev_features_t changed = features ^ netdev->features; | ||
2745 | |||
2746 | if (!(changed & (NETIF_F_RXFCS))) | ||
2747 | return 0; | ||
2748 | |||
2749 | netdev->features = features; | ||
2750 | e100_exec_cb(nic, NULL, e100_configure); | ||
2751 | return 0; | ||
2752 | } | ||
2753 | |||
2732 | static const struct net_device_ops e100_netdev_ops = { | 2754 | static const struct net_device_ops e100_netdev_ops = { |
2733 | .ndo_open = e100_open, | 2755 | .ndo_open = e100_open, |
2734 | .ndo_stop = e100_close, | 2756 | .ndo_stop = e100_close, |
@@ -2742,6 +2764,7 @@ static const struct net_device_ops e100_netdev_ops = { | |||
2742 | #ifdef CONFIG_NET_POLL_CONTROLLER | 2764 | #ifdef CONFIG_NET_POLL_CONTROLLER |
2743 | .ndo_poll_controller = e100_netpoll, | 2765 | .ndo_poll_controller = e100_netpoll, |
2744 | #endif | 2766 | #endif |
2767 | .ndo_set_features = e100_set_features, | ||
2745 | }; | 2768 | }; |
2746 | 2769 | ||
2747 | static int __devinit e100_probe(struct pci_dev *pdev, | 2770 | static int __devinit e100_probe(struct pci_dev *pdev, |
@@ -2754,6 +2777,8 @@ static int __devinit e100_probe(struct pci_dev *pdev, | |||
2754 | if (!(netdev = alloc_etherdev(sizeof(struct nic)))) | 2777 | if (!(netdev = alloc_etherdev(sizeof(struct nic)))) |
2755 | return -ENOMEM; | 2778 | return -ENOMEM; |
2756 | 2779 | ||
2780 | netdev->hw_features |= NETIF_F_RXFCS; | ||
2781 | |||
2757 | netdev->netdev_ops = &e100_netdev_ops; | 2782 | netdev->netdev_ops = &e100_netdev_ops; |
2758 | SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops); | 2783 | SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops); |
2759 | netdev->watchdog_timeo = E100_WATCHDOG_PERIOD; | 2784 | netdev->watchdog_timeo = E100_WATCHDOG_PERIOD; |