|
@@ -32,6 +32,7 @@
|
|
#include <linux/ip.h>
|
|
#include <linux/ip.h>
|
|
#include <linux/tcp.h>
|
|
#include <linux/tcp.h>
|
|
#include <net/checksum.h>
|
|
#include <net/checksum.h>
|
|
|
|
+#include <linux/inet_lro.h>
|
|
|
|
|
|
#include <asm/irq.h>
|
|
#include <asm/irq.h>
|
|
#include <asm/firmware.h>
|
|
#include <asm/firmware.h>
|
|
@@ -56,9 +57,11 @@
|
|
|
|
|
|
|
|
|
|
/* Must be a power of two */
|
|
/* Must be a power of two */
|
|
-#define RX_RING_SIZE 1024
|
|
|
|
|
|
+#define RX_RING_SIZE 2048
|
|
#define TX_RING_SIZE 4096
|
|
#define TX_RING_SIZE 4096
|
|
|
|
|
|
|
|
+#define LRO_MAX_AGGR 64
|
|
|
|
+
|
|
#define DEFAULT_MSG_ENABLE \
|
|
#define DEFAULT_MSG_ENABLE \
|
|
(NETIF_MSG_DRV | \
|
|
(NETIF_MSG_DRV | \
|
|
NETIF_MSG_PROBE | \
|
|
NETIF_MSG_PROBE | \
|
|
@@ -206,7 +209,6 @@ static int pasemi_get_mac_addr(struct pasemi_mac *mac)
|
|
return -ENOENT;
|
|
return -ENOENT;
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
if (sscanf(maddr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &addr[0],
|
|
if (sscanf(maddr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &addr[0],
|
|
&addr[1], &addr[2], &addr[3], &addr[4], &addr[5]) != 6) {
|
|
&addr[1], &addr[2], &addr[3], &addr[4], &addr[5]) != 6) {
|
|
dev_warn(&pdev->dev,
|
|
dev_warn(&pdev->dev,
|
|
@@ -219,6 +221,37 @@ static int pasemi_get_mac_addr(struct pasemi_mac *mac)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int get_skb_hdr(struct sk_buff *skb, void **iphdr,
|
|
|
|
+ void **tcph, u64 *hdr_flags, void *data)
|
|
|
|
+{
|
|
|
|
+ u64 macrx = (u64) data;
|
|
|
|
+ unsigned int ip_len;
|
|
|
|
+ struct iphdr *iph;
|
|
|
|
+
|
|
|
|
+ /* IPv4 header checksum failed */
|
|
|
|
+ if ((macrx & XCT_MACRX_HTY_M) != XCT_MACRX_HTY_IPV4_OK)
|
|
|
|
+ return -1;
|
|
|
|
+
|
|
|
|
+ /* non tcp packet */
|
|
|
|
+ skb_reset_network_header(skb);
|
|
|
|
+ iph = ip_hdr(skb);
|
|
|
|
+ if (iph->protocol != IPPROTO_TCP)
|
|
|
|
+ return -1;
|
|
|
|
+
|
|
|
|
+ ip_len = ip_hdrlen(skb);
|
|
|
|
+ skb_set_transport_header(skb, ip_len);
|
|
|
|
+ *tcph = tcp_hdr(skb);
|
|
|
|
+
|
|
|
|
+ /* check if ip header and tcp header are complete */
|
|
|
|
+ if (iph->tot_len < ip_len + tcp_hdrlen(skb))
|
|
|
|
+ return -1;
|
|
|
|
+
|
|
|
|
+ *hdr_flags = LRO_IPV4 | LRO_TCP;
|
|
|
|
+ *iphdr = iph;
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
static int pasemi_mac_unmap_tx_skb(struct pasemi_mac *mac,
|
|
static int pasemi_mac_unmap_tx_skb(struct pasemi_mac *mac,
|
|
struct sk_buff *skb,
|
|
struct sk_buff *skb,
|
|
const dma_addr_t *dmas)
|
|
const dma_addr_t *dmas)
|
|
@@ -662,7 +695,7 @@ static int pasemi_mac_clean_rx(struct pasemi_mac_rxring *rx,
|
|
skb_put(skb, len-4);
|
|
skb_put(skb, len-4);
|
|
|
|
|
|
skb->protocol = eth_type_trans(skb, mac->netdev);
|
|
skb->protocol = eth_type_trans(skb, mac->netdev);
|
|
- netif_receive_skb(skb);
|
|
|
|
|
|
+ lro_receive_skb(&mac->lro_mgr, skb, (void *)macrx);
|
|
|
|
|
|
next:
|
|
next:
|
|
RX_DESC(rx, n) = 0;
|
|
RX_DESC(rx, n) = 0;
|
|
@@ -684,6 +717,8 @@ next:
|
|
|
|
|
|
rx_ring(mac)->next_to_clean = n;
|
|
rx_ring(mac)->next_to_clean = n;
|
|
|
|
|
|
|
|
+ lro_flush_all(&mac->lro_mgr);
|
|
|
|
+
|
|
/* Increase is in number of 16-byte entries, and since each descriptor
|
|
/* Increase is in number of 16-byte entries, and since each descriptor
|
|
* with an 8BRES takes up 3x8 bytes (padded to 4x8), increase with
|
|
* with an 8BRES takes up 3x8 bytes (padded to 4x8), increase with
|
|
* count*2.
|
|
* count*2.
|
|
@@ -988,7 +1023,7 @@ static int pasemi_mac_open(struct net_device *dev)
|
|
PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(0x3ff));
|
|
PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(0x3ff));
|
|
|
|
|
|
write_iob_reg(PAS_IOB_DMA_RXCH_CFG(mac->rx->chan.chno),
|
|
write_iob_reg(PAS_IOB_DMA_RXCH_CFG(mac->rx->chan.chno),
|
|
- PAS_IOB_DMA_RXCH_CFG_CNTTH(128));
|
|
|
|
|
|
+ PAS_IOB_DMA_RXCH_CFG_CNTTH(256));
|
|
|
|
|
|
write_iob_reg(PAS_IOB_DMA_TXCH_CFG(mac->tx->chan.chno),
|
|
write_iob_reg(PAS_IOB_DMA_TXCH_CFG(mac->tx->chan.chno),
|
|
PAS_IOB_DMA_TXCH_CFG_CNTTH(32));
|
|
PAS_IOB_DMA_TXCH_CFG_CNTTH(32));
|
|
@@ -1368,6 +1403,16 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
dev->features = NETIF_F_IP_CSUM | NETIF_F_LLTX | NETIF_F_SG |
|
|
dev->features = NETIF_F_IP_CSUM | NETIF_F_LLTX | NETIF_F_SG |
|
|
NETIF_F_HIGHDMA;
|
|
NETIF_F_HIGHDMA;
|
|
|
|
|
|
|
|
+ mac->lro_mgr.max_aggr = LRO_MAX_AGGR;
|
|
|
|
+ mac->lro_mgr.max_desc = MAX_LRO_DESCRIPTORS;
|
|
|
|
+ mac->lro_mgr.lro_arr = mac->lro_desc;
|
|
|
|
+ mac->lro_mgr.get_skb_header = get_skb_hdr;
|
|
|
|
+ mac->lro_mgr.features = LRO_F_NAPI | LRO_F_EXTRACT_VLAN_ID;
|
|
|
|
+ mac->lro_mgr.dev = mac->netdev;
|
|
|
|
+ mac->lro_mgr.ip_summed = CHECKSUM_UNNECESSARY;
|
|
|
|
+ mac->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY;
|
|
|
|
+
|
|
|
|
+
|
|
mac->dma_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa007, NULL);
|
|
mac->dma_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa007, NULL);
|
|
if (!mac->dma_pdev) {
|
|
if (!mac->dma_pdev) {
|
|
dev_err(&mac->pdev->dev, "Can't find DMA Controller\n");
|
|
dev_err(&mac->pdev->dev, "Can't find DMA Controller\n");
|