diff options
author | Olof Johansson <olof@lixom.net> | 2007-11-28 21:57:27 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 18:04:24 -0500 |
commit | 28ae79f531014bb3ad95b6efa0e0603069087bc5 (patch) | |
tree | 5f46070012b462f4faf5f79e4fa6a0c75b1cf816 /drivers/net/pasemi_mac.c | |
parent | 906674abab0424b466a2db4bb6a890a8c477b10a (diff) |
pasemi_mac: Software-based LRO support
pasemi_mac: Software-based LRO support
Implement LRO for pasemi_mac. Pretty straightforward.
Signed-off-by: Olof Johansson <olof@lixom.net>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/pasemi_mac.c')
-rw-r--r-- | drivers/net/pasemi_mac.c | 53 |
1 files changed, 49 insertions, 4 deletions
diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c index e78aac488f3c..98b639742680 100644 --- a/drivers/net/pasemi_mac.c +++ b/drivers/net/pasemi_mac.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/ip.h> | 32 | #include <linux/ip.h> |
33 | #include <linux/tcp.h> | 33 | #include <linux/tcp.h> |
34 | #include <net/checksum.h> | 34 | #include <net/checksum.h> |
35 | #include <linux/inet_lro.h> | ||
35 | 36 | ||
36 | #include <asm/irq.h> | 37 | #include <asm/irq.h> |
37 | #include <asm/firmware.h> | 38 | #include <asm/firmware.h> |
@@ -56,9 +57,11 @@ | |||
56 | 57 | ||
57 | 58 | ||
58 | /* Must be a power of two */ | 59 | /* Must be a power of two */ |
59 | #define RX_RING_SIZE 1024 | 60 | #define RX_RING_SIZE 2048 |
60 | #define TX_RING_SIZE 4096 | 61 | #define TX_RING_SIZE 4096 |
61 | 62 | ||
63 | #define LRO_MAX_AGGR 64 | ||
64 | |||
62 | #define DEFAULT_MSG_ENABLE \ | 65 | #define DEFAULT_MSG_ENABLE \ |
63 | (NETIF_MSG_DRV | \ | 66 | (NETIF_MSG_DRV | \ |
64 | NETIF_MSG_PROBE | \ | 67 | NETIF_MSG_PROBE | \ |
@@ -206,7 +209,6 @@ static int pasemi_get_mac_addr(struct pasemi_mac *mac) | |||
206 | return -ENOENT; | 209 | return -ENOENT; |
207 | } | 210 | } |
208 | 211 | ||
209 | |||
210 | if (sscanf(maddr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &addr[0], | 212 | if (sscanf(maddr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &addr[0], |
211 | &addr[1], &addr[2], &addr[3], &addr[4], &addr[5]) != 6) { | 213 | &addr[1], &addr[2], &addr[3], &addr[4], &addr[5]) != 6) { |
212 | dev_warn(&pdev->dev, | 214 | dev_warn(&pdev->dev, |
@@ -219,6 +221,37 @@ static int pasemi_get_mac_addr(struct pasemi_mac *mac) | |||
219 | return 0; | 221 | return 0; |
220 | } | 222 | } |
221 | 223 | ||
224 | static int get_skb_hdr(struct sk_buff *skb, void **iphdr, | ||
225 | void **tcph, u64 *hdr_flags, void *data) | ||
226 | { | ||
227 | u64 macrx = (u64) data; | ||
228 | unsigned int ip_len; | ||
229 | struct iphdr *iph; | ||
230 | |||
231 | /* IPv4 header checksum failed */ | ||
232 | if ((macrx & XCT_MACRX_HTY_M) != XCT_MACRX_HTY_IPV4_OK) | ||
233 | return -1; | ||
234 | |||
235 | /* non tcp packet */ | ||
236 | skb_reset_network_header(skb); | ||
237 | iph = ip_hdr(skb); | ||
238 | if (iph->protocol != IPPROTO_TCP) | ||
239 | return -1; | ||
240 | |||
241 | ip_len = ip_hdrlen(skb); | ||
242 | skb_set_transport_header(skb, ip_len); | ||
243 | *tcph = tcp_hdr(skb); | ||
244 | |||
245 | /* check if ip header and tcp header are complete */ | ||
246 | if (iph->tot_len < ip_len + tcp_hdrlen(skb)) | ||
247 | return -1; | ||
248 | |||
249 | *hdr_flags = LRO_IPV4 | LRO_TCP; | ||
250 | *iphdr = iph; | ||
251 | |||
252 | return 0; | ||
253 | } | ||
254 | |||
222 | static int pasemi_mac_unmap_tx_skb(struct pasemi_mac *mac, | 255 | static int pasemi_mac_unmap_tx_skb(struct pasemi_mac *mac, |
223 | struct sk_buff *skb, | 256 | struct sk_buff *skb, |
224 | const dma_addr_t *dmas) | 257 | const dma_addr_t *dmas) |
@@ -662,7 +695,7 @@ static int pasemi_mac_clean_rx(struct pasemi_mac_rxring *rx, | |||
662 | skb_put(skb, len-4); | 695 | skb_put(skb, len-4); |
663 | 696 | ||
664 | skb->protocol = eth_type_trans(skb, mac->netdev); | 697 | skb->protocol = eth_type_trans(skb, mac->netdev); |
665 | netif_receive_skb(skb); | 698 | lro_receive_skb(&mac->lro_mgr, skb, (void *)macrx); |
666 | 699 | ||
667 | next: | 700 | next: |
668 | RX_DESC(rx, n) = 0; | 701 | RX_DESC(rx, n) = 0; |
@@ -684,6 +717,8 @@ next: | |||
684 | 717 | ||
685 | rx_ring(mac)->next_to_clean = n; | 718 | rx_ring(mac)->next_to_clean = n; |
686 | 719 | ||
720 | lro_flush_all(&mac->lro_mgr); | ||
721 | |||
687 | /* Increase is in number of 16-byte entries, and since each descriptor | 722 | /* Increase is in number of 16-byte entries, and since each descriptor |
688 | * with an 8BRES takes up 3x8 bytes (padded to 4x8), increase with | 723 | * with an 8BRES takes up 3x8 bytes (padded to 4x8), increase with |
689 | * count*2. | 724 | * count*2. |
@@ -988,7 +1023,7 @@ static int pasemi_mac_open(struct net_device *dev) | |||
988 | PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(0x3ff)); | 1023 | PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(0x3ff)); |
989 | 1024 | ||
990 | write_iob_reg(PAS_IOB_DMA_RXCH_CFG(mac->rx->chan.chno), | 1025 | write_iob_reg(PAS_IOB_DMA_RXCH_CFG(mac->rx->chan.chno), |
991 | PAS_IOB_DMA_RXCH_CFG_CNTTH(128)); | 1026 | PAS_IOB_DMA_RXCH_CFG_CNTTH(256)); |
992 | 1027 | ||
993 | write_iob_reg(PAS_IOB_DMA_TXCH_CFG(mac->tx->chan.chno), | 1028 | write_iob_reg(PAS_IOB_DMA_TXCH_CFG(mac->tx->chan.chno), |
994 | PAS_IOB_DMA_TXCH_CFG_CNTTH(32)); | 1029 | PAS_IOB_DMA_TXCH_CFG_CNTTH(32)); |
@@ -1368,6 +1403,16 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1368 | dev->features = NETIF_F_IP_CSUM | NETIF_F_LLTX | NETIF_F_SG | | 1403 | dev->features = NETIF_F_IP_CSUM | NETIF_F_LLTX | NETIF_F_SG | |
1369 | NETIF_F_HIGHDMA; | 1404 | NETIF_F_HIGHDMA; |
1370 | 1405 | ||
1406 | mac->lro_mgr.max_aggr = LRO_MAX_AGGR; | ||
1407 | mac->lro_mgr.max_desc = MAX_LRO_DESCRIPTORS; | ||
1408 | mac->lro_mgr.lro_arr = mac->lro_desc; | ||
1409 | mac->lro_mgr.get_skb_header = get_skb_hdr; | ||
1410 | mac->lro_mgr.features = LRO_F_NAPI | LRO_F_EXTRACT_VLAN_ID; | ||
1411 | mac->lro_mgr.dev = mac->netdev; | ||
1412 | mac->lro_mgr.ip_summed = CHECKSUM_UNNECESSARY; | ||
1413 | mac->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY; | ||
1414 | |||
1415 | |||
1371 | mac->dma_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa007, NULL); | 1416 | mac->dma_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa007, NULL); |
1372 | if (!mac->dma_pdev) { | 1417 | if (!mac->dma_pdev) { |
1373 | dev_err(&mac->pdev->dev, "Can't find DMA Controller\n"); | 1418 | dev_err(&mac->pdev->dev, "Can't find DMA Controller\n"); |