diff options
| -rw-r--r-- | drivers/net/myri10ge/myri10ge.c | 212 |
1 files changed, 8 insertions, 204 deletions
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 4d2be9c59164..711a8bf08fac 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c | |||
| @@ -97,7 +97,6 @@ MODULE_LICENSE("Dual BSD/GPL"); | |||
| 97 | #define MYRI10GE_MAX_FRAGS_PER_FRAME (MYRI10GE_MAX_ETHER_MTU/MYRI10GE_ALLOC_SIZE + 1) | 97 | #define MYRI10GE_MAX_FRAGS_PER_FRAME (MYRI10GE_MAX_ETHER_MTU/MYRI10GE_ALLOC_SIZE + 1) |
| 98 | 98 | ||
| 99 | struct myri10ge_rx_buffer_state { | 99 | struct myri10ge_rx_buffer_state { |
| 100 | struct sk_buff *skb; | ||
| 101 | struct page *page; | 100 | struct page *page; |
| 102 | int page_offset; | 101 | int page_offset; |
| 103 | DECLARE_PCI_UNMAP_ADDR(bus) | 102 | DECLARE_PCI_UNMAP_ADDR(bus) |
| @@ -250,11 +249,6 @@ module_param(myri10ge_force_firmware, int, S_IRUGO); | |||
| 250 | MODULE_PARM_DESC(myri10ge_force_firmware, | 249 | MODULE_PARM_DESC(myri10ge_force_firmware, |
| 251 | "Force firmware to assume aligned completions\n"); | 250 | "Force firmware to assume aligned completions\n"); |
| 252 | 251 | ||
| 253 | static int myri10ge_skb_cross_4k = 0; | ||
| 254 | module_param(myri10ge_skb_cross_4k, int, S_IRUGO | S_IWUSR); | ||
| 255 | MODULE_PARM_DESC(myri10ge_skb_cross_4k, | ||
| 256 | "Can a small skb cross a 4KB boundary?\n"); | ||
| 257 | |||
| 258 | static int myri10ge_initial_mtu = MYRI10GE_MAX_ETHER_MTU - ETH_HLEN; | 252 | static int myri10ge_initial_mtu = MYRI10GE_MAX_ETHER_MTU - ETH_HLEN; |
| 259 | module_param(myri10ge_initial_mtu, int, S_IRUGO); | 253 | module_param(myri10ge_initial_mtu, int, S_IRUGO); |
| 260 | MODULE_PARM_DESC(myri10ge_initial_mtu, "Initial MTU\n"); | 254 | MODULE_PARM_DESC(myri10ge_initial_mtu, "Initial MTU\n"); |
| @@ -820,148 +814,6 @@ myri10ge_submit_8rx(struct mcp_kreq_ether_recv __iomem * dst, | |||
| 820 | mb(); | 814 | mb(); |
| 821 | } | 815 | } |
| 822 | 816 | ||
| 823 | /* | ||
| 824 | * Set of routines to get a new receive buffer. Any buffer which | ||
| 825 | * crosses a 4KB boundary must start on a 4KB boundary due to PCIe | ||
| 826 | * wdma restrictions. We also try to align any smaller allocation to | ||
| 827 | * at least a 16 byte boundary for efficiency. We assume the linux | ||
| 828 | * memory allocator works by powers of 2, and will not return memory | ||
| 829 | * smaller than 2KB which crosses a 4KB boundary. If it does, we fall | ||
| 830 | * back to allocating 2x as much space as required. | ||
| 831 | * | ||
| 832 | * We intend to replace large (>4KB) skb allocations by using | ||
| 833 | * pages directly and building a fraglist in the near future. | ||
| 834 | */ | ||
| 835 | |||
| 836 | static inline struct sk_buff *myri10ge_alloc_big(struct net_device *dev, | ||
| 837 | int bytes) | ||
| 838 | { | ||
| 839 | struct sk_buff *skb; | ||
| 840 | unsigned long data, roundup; | ||
| 841 | |||
| 842 | skb = netdev_alloc_skb(dev, bytes + 4096 + MXGEFW_PAD); | ||
| 843 | if (skb == NULL) | ||
| 844 | return NULL; | ||
| 845 | |||
| 846 | /* Correct skb->truesize so that socket buffer | ||
| 847 | * accounting is not confused the rounding we must | ||
| 848 | * do to satisfy alignment constraints. | ||
| 849 | */ | ||
| 850 | skb->truesize -= 4096; | ||
| 851 | |||
| 852 | data = (unsigned long)(skb->data); | ||
| 853 | roundup = (-data) & (4095); | ||
| 854 | skb_reserve(skb, roundup); | ||
| 855 | return skb; | ||
| 856 | } | ||
| 857 | |||
| 858 | /* Allocate 2x as much space as required and use whichever portion | ||
| 859 | * does not cross a 4KB boundary */ | ||
| 860 | static inline struct sk_buff *myri10ge_alloc_small_safe(struct net_device *dev, | ||
| 861 | unsigned int bytes) | ||
| 862 | { | ||
| 863 | struct sk_buff *skb; | ||
| 864 | unsigned long data, boundary; | ||
| 865 | |||
| 866 | skb = netdev_alloc_skb(dev, 2 * (bytes + MXGEFW_PAD) - 1); | ||
| 867 | if (unlikely(skb == NULL)) | ||
| 868 | return NULL; | ||
| 869 | |||
| 870 | /* Correct skb->truesize so that socket buffer | ||
| 871 | * accounting is not confused the rounding we must | ||
| 872 | * do to satisfy alignment constraints. | ||
| 873 | */ | ||
| 874 | skb->truesize -= bytes + MXGEFW_PAD; | ||
| 875 | |||
| 876 | data = (unsigned long)(skb->data); | ||
| 877 | boundary = (data + 4095UL) & ~4095UL; | ||
| 878 | if ((boundary - data) >= (bytes + MXGEFW_PAD)) | ||
| 879 | return skb; | ||
| 880 | |||
| 881 | skb_reserve(skb, boundary - data); | ||
| 882 | return skb; | ||
| 883 | } | ||
| 884 | |||
| 885 | /* Allocate just enough space, and verify that the allocated | ||
| 886 | * space does not cross a 4KB boundary */ | ||
| 887 | static inline struct sk_buff *myri10ge_alloc_small(struct net_device *dev, | ||
| 888 | int bytes) | ||
| 889 | { | ||
| 890 | struct sk_buff *skb; | ||
| 891 | unsigned long roundup, data, end; | ||
| 892 | |||
| 893 | skb = netdev_alloc_skb(dev, bytes + 16 + MXGEFW_PAD); | ||
| 894 | if (unlikely(skb == NULL)) | ||
| 895 | return NULL; | ||
| 896 | |||
| 897 | /* Round allocated buffer to 16 byte boundary */ | ||
| 898 | data = (unsigned long)(skb->data); | ||
| 899 | roundup = (-data) & 15UL; | ||
| 900 | skb_reserve(skb, roundup); | ||
| 901 | /* Verify that the data buffer does not cross a page boundary */ | ||
| 902 | data = (unsigned long)(skb->data); | ||
| 903 | end = data + bytes + MXGEFW_PAD - 1; | ||
| 904 | if (unlikely(((end >> 12) != (data >> 12)) && (data & 4095UL))) { | ||
| 905 | printk(KERN_NOTICE | ||
| 906 | "myri10ge_alloc_small: small skb crossed 4KB boundary\n"); | ||
| 907 | myri10ge_skb_cross_4k = 1; | ||
| 908 | dev_kfree_skb_any(skb); | ||
| 909 | skb = myri10ge_alloc_small_safe(dev, bytes); | ||
| 910 | } | ||
| 911 | return skb; | ||
| 912 | } | ||
| 913 | |||
| 914 | static inline int | ||
| 915 | myri10ge_getbuf(struct myri10ge_rx_buf *rx, struct myri10ge_priv *mgp, | ||
| 916 | int bytes, int idx) | ||
| 917 | { | ||
| 918 | struct net_device *dev = mgp->dev; | ||
| 919 | struct pci_dev *pdev = mgp->pdev; | ||
| 920 | struct sk_buff *skb; | ||
| 921 | dma_addr_t bus; | ||
| 922 | int len, retval = 0; | ||
| 923 | |||
| 924 | bytes += VLAN_HLEN; /* account for 802.1q vlan tag */ | ||
| 925 | |||
| 926 | if ((bytes + MXGEFW_PAD) > (4096 - 16) /* linux overhead */ ) | ||
| 927 | skb = myri10ge_alloc_big(dev, bytes); | ||
| 928 | else if (myri10ge_skb_cross_4k) | ||
| 929 | skb = myri10ge_alloc_small_safe(dev, bytes); | ||
| 930 | else | ||
| 931 | skb = myri10ge_alloc_small(dev, bytes); | ||
| 932 | |||
| 933 | if (unlikely(skb == NULL)) { | ||
| 934 | rx->alloc_fail++; | ||
| 935 | retval = -ENOBUFS; | ||
| 936 | goto done; | ||
| 937 | } | ||
| 938 | |||
| 939 | /* set len so that it only covers the area we | ||
| 940 | * need mapped for DMA */ | ||
| 941 | len = bytes + MXGEFW_PAD; | ||
| 942 | |||
| 943 | bus = pci_map_single(pdev, skb->data, len, PCI_DMA_FROMDEVICE); | ||
| 944 | rx->info[idx].skb = skb; | ||
| 945 | pci_unmap_addr_set(&rx->info[idx], bus, bus); | ||
| 946 | pci_unmap_len_set(&rx->info[idx], len, len); | ||
| 947 | rx->shadow[idx].addr_low = htonl(MYRI10GE_LOWPART_TO_U32(bus)); | ||
| 948 | rx->shadow[idx].addr_high = htonl(MYRI10GE_HIGHPART_TO_U32(bus)); | ||
| 949 | |||
| 950 | done: | ||
| 951 | /* copy 8 descriptors (64-bytes) to the mcp at a time */ | ||
| 952 | if ((idx & 7) == 7) { | ||
| 953 | if (rx->wc_fifo == NULL) | ||
| 954 | myri10ge_submit_8rx(&rx->lanai[idx - 7], | ||
| 955 | &rx->shadow[idx - 7]); | ||
| 956 | else { | ||
| 957 | mb(); | ||
| 958 | myri10ge_pio_copy(rx->wc_fifo, | ||
| 959 | &rx->shadow[idx - 7], 64); | ||
| 960 | } | ||
| 961 | } | ||
| 962 | return retval; | ||
| 963 | } | ||
| 964 | |||
| 965 | static inline void myri10ge_vlan_ip_csum(struct sk_buff *skb, __wsum hw_csum) | 817 | static inline void myri10ge_vlan_ip_csum(struct sk_buff *skb, __wsum hw_csum) |
| 966 | { | 818 | { |
| 967 | struct vlan_hdr *vh = (struct vlan_hdr *)(skb->data); | 819 | struct vlan_hdr *vh = (struct vlan_hdr *)(skb->data); |
| @@ -1084,8 +936,8 @@ myri10ge_unmap_rx_page(struct pci_dev *pdev, | |||
| 1084 | * page into an skb */ | 936 | * page into an skb */ |
| 1085 | 937 | ||
| 1086 | static inline int | 938 | static inline int |
| 1087 | myri10ge_page_rx_done(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, | 939 | myri10ge_rx_done(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, |
| 1088 | int bytes, int len, __wsum csum) | 940 | int bytes, int len, __wsum csum) |
| 1089 | { | 941 | { |
| 1090 | struct sk_buff *skb; | 942 | struct sk_buff *skb; |
| 1091 | struct skb_frag_struct rx_frags[MYRI10GE_MAX_FRAGS_PER_FRAME]; | 943 | struct skb_frag_struct rx_frags[MYRI10GE_MAX_FRAGS_PER_FRAME]; |
| @@ -1148,54 +1000,6 @@ myri10ge_page_rx_done(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, | |||
| 1148 | return 1; | 1000 | return 1; |
| 1149 | } | 1001 | } |
| 1150 | 1002 | ||
| 1151 | static inline unsigned long | ||
| 1152 | myri10ge_rx_done(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, | ||
| 1153 | int bytes, int len, __wsum csum) | ||
| 1154 | { | ||
| 1155 | dma_addr_t bus; | ||
| 1156 | struct sk_buff *skb; | ||
| 1157 | int idx, unmap_len; | ||
| 1158 | |||
| 1159 | idx = rx->cnt & rx->mask; | ||
| 1160 | rx->cnt++; | ||
| 1161 | |||
| 1162 | /* save a pointer to the received skb */ | ||
| 1163 | skb = rx->info[idx].skb; | ||
| 1164 | bus = pci_unmap_addr(&rx->info[idx], bus); | ||
| 1165 | unmap_len = pci_unmap_len(&rx->info[idx], len); | ||
| 1166 | |||
| 1167 | /* try to replace the received skb */ | ||
| 1168 | if (myri10ge_getbuf(rx, mgp, bytes, idx)) { | ||
| 1169 | /* drop the frame -- the old skbuf is re-cycled */ | ||
| 1170 | mgp->stats.rx_dropped += 1; | ||
| 1171 | return 0; | ||
| 1172 | } | ||
| 1173 | |||
| 1174 | /* unmap the recvd skb */ | ||
| 1175 | pci_unmap_single(mgp->pdev, bus, unmap_len, PCI_DMA_FROMDEVICE); | ||
| 1176 | |||
| 1177 | /* mcp implicitly skips 1st bytes so that packet is properly | ||
| 1178 | * aligned */ | ||
| 1179 | skb_reserve(skb, MXGEFW_PAD); | ||
| 1180 | |||
| 1181 | /* set the length of the frame */ | ||
| 1182 | skb_put(skb, len); | ||
| 1183 | |||
| 1184 | skb->protocol = eth_type_trans(skb, mgp->dev); | ||
| 1185 | if (mgp->csum_flag) { | ||
| 1186 | if ((skb->protocol == htons(ETH_P_IP)) || | ||
| 1187 | (skb->protocol == htons(ETH_P_IPV6))) { | ||
| 1188 | skb->csum = csum; | ||
| 1189 | skb->ip_summed = CHECKSUM_COMPLETE; | ||
| 1190 | } else | ||
| 1191 | myri10ge_vlan_ip_csum(skb, csum); | ||
| 1192 | } | ||
| 1193 | |||
| 1194 | netif_receive_skb(skb); | ||
| 1195 | mgp->dev->last_rx = jiffies; | ||
| 1196 | return 1; | ||
| 1197 | } | ||
| 1198 | |||
| 1199 | static inline void myri10ge_tx_done(struct myri10ge_priv *mgp, int mcp_index) | 1003 | static inline void myri10ge_tx_done(struct myri10ge_priv *mgp, int mcp_index) |
| 1200 | { | 1004 | { |
| 1201 | struct pci_dev *pdev = mgp->pdev; | 1005 | struct pci_dev *pdev = mgp->pdev; |
| @@ -1264,13 +1068,13 @@ static inline void myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int *limit) | |||
| 1264 | rx_done->entry[idx].length = 0; | 1068 | rx_done->entry[idx].length = 0; |
| 1265 | checksum = csum_unfold(rx_done->entry[idx].checksum); | 1069 | checksum = csum_unfold(rx_done->entry[idx].checksum); |
| 1266 | if (length <= mgp->small_bytes) | 1070 | if (length <= mgp->small_bytes) |
| 1267 | rx_ok = myri10ge_page_rx_done(mgp, &mgp->rx_small, | 1071 | rx_ok = myri10ge_rx_done(mgp, &mgp->rx_small, |
| 1268 | mgp->small_bytes, | 1072 | mgp->small_bytes, |
| 1269 | length, checksum); | 1073 | length, checksum); |
| 1270 | else | 1074 | else |
| 1271 | rx_ok = myri10ge_page_rx_done(mgp, &mgp->rx_big, | 1075 | rx_ok = myri10ge_rx_done(mgp, &mgp->rx_big, |
| 1272 | mgp->big_bytes, | 1076 | mgp->big_bytes, |
| 1273 | length, checksum); | 1077 | length, checksum); |
| 1274 | rx_packets += rx_ok; | 1078 | rx_packets += rx_ok; |
| 1275 | rx_bytes += rx_ok * (unsigned long)length; | 1079 | rx_bytes += rx_ok * (unsigned long)length; |
| 1276 | cnt++; | 1080 | cnt++; |
