aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2007-11-28 21:57:27 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 18:04:24 -0500
commit28ae79f531014bb3ad95b6efa0e0603069087bc5 (patch)
tree5f46070012b462f4faf5f79e4fa6a0c75b1cf816 /drivers
parent906674abab0424b466a2db4bb6a890a8c477b10a (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')
-rw-r--r--drivers/net/Kconfig1
-rw-r--r--drivers/net/pasemi_mac.c53
-rw-r--r--drivers/net/pasemi_mac.h5
3 files changed, 55 insertions, 4 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index b034410b7ab6..477c3e459745 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2572,6 +2572,7 @@ config PASEMI_MAC
2572 tristate "PA Semi 1/10Gbit MAC" 2572 tristate "PA Semi 1/10Gbit MAC"
2573 depends on PPC64 && PCI 2573 depends on PPC64 && PCI
2574 select PHYLIB 2574 select PHYLIB
2575 select INET_LRO
2575 help 2576 help
2576 This driver supports the on-chip 1/10Gbit Ethernet controller on 2577 This driver supports the on-chip 1/10Gbit Ethernet controller on
2577 PA Semi's PWRficient line of chips. 2578 PA Semi's PWRficient line of chips.
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
224static 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
222static int pasemi_mac_unmap_tx_skb(struct pasemi_mac *mac, 255static 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
667next: 700next:
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");
diff --git a/drivers/net/pasemi_mac.h b/drivers/net/pasemi_mac.h
index c6555edba55d..8bee2a664c83 100644
--- a/drivers/net/pasemi_mac.h
+++ b/drivers/net/pasemi_mac.h
@@ -26,6 +26,8 @@
26#include <linux/spinlock.h> 26#include <linux/spinlock.h>
27#include <linux/phy.h> 27#include <linux/phy.h>
28 28
29#define MAX_LRO_DESCRIPTORS 8
30
29struct pasemi_mac_txring { 31struct pasemi_mac_txring {
30 struct pasemi_dmachan chan; /* Must be first */ 32 struct pasemi_dmachan chan; /* Must be first */
31 spinlock_t lock; 33 spinlock_t lock;
@@ -64,7 +66,10 @@ struct pasemi_mac {
64 66
65 u8 mac_addr[6]; 67 u8 mac_addr[6];
66 68
69 struct net_lro_mgr lro_mgr;
70 struct net_lro_desc lro_desc[MAX_LRO_DESCRIPTORS];
67 struct timer_list rxtimer; 71 struct timer_list rxtimer;
72 unsigned int lro_max_aggr;
68 73
69 struct pasemi_mac_txring *tx; 74 struct pasemi_mac_txring *tx;
70 struct pasemi_mac_rxring *rx; 75 struct pasemi_mac_rxring *rx;