diff options
Diffstat (limited to 'drivers/net/myri10ge/myri10ge.c')
-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++; |