Patchwork [10/21] net: sgiseeq: use common rx_copybreak handling [strict refill!]

login
register
mail settings
Submitter Michał Mirosław
Date July 9, 2011, 5:17 p.m.
Message ID <8a0643e9affb5355fff01f3c45d44e6da8d34e76.1310229312.git.mirq-linux@rere.qmqm.pl>
Download mbox | patch
Permalink /patch/104000/
State Superseded
Delegated to: David Miller
Headers show

Comments

Michał Mirosław - July 9, 2011, 5:17 p.m.
Does this card really loop back transmitted packets? The code can be
cleaned up further if it isn't.

Because buffer status is written in it, there is additional pair of
DMA sync to cpu/device before the common path. If it turns out to be
big performance hit this patch should be reverted.

Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
---
 drivers/net/sgiseeq.c |   66 ++++++++++++++++++------------------------------
 1 files changed, 25 insertions(+), 41 deletions(-)

Patch

diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c
index 52fb7ed..a4c6d93 100644
--- a/drivers/net/sgiseeq.c
+++ b/drivers/net/sgiseeq.c
@@ -340,9 +340,8 @@  static inline void sgiseeq_rx(struct net_device *dev, struct sgiseeq_private *sp
 {
 	struct sgiseeq_rx_desc *rd;
 	struct sk_buff *skb = NULL;
-	struct sk_buff *newskb;
 	unsigned char pkt_status;
-	int len = 0;
+	int packet_ok, len = 0;
 	unsigned int orig_end = PREV_RX(sp->rx_new);
 
 	/* Service every received packet. */
@@ -350,53 +349,38 @@  static inline void sgiseeq_rx(struct net_device *dev, struct sgiseeq_private *sp
 	dma_sync_desc_cpu(dev, rd);
 	while (!(rd->rdma.cntinfo & HPCDMA_OWN)) {
 		len = PKT_BUF_SZ - (rd->rdma.cntinfo & HPCDMA_BCNT) - 3;
-		dma_unmap_single(dev->dev.parent, rd->rdma.pbuf,
+		dma_sync_single_for_cpu(dev->dev.parent, rd->rdma.pbuf,
 				 PKT_BUF_SZ, DMA_FROM_DEVICE);
 		pkt_status = rd->skb->data[len];
 		if (pkt_status & SEEQ_RSTAT_FIG) {
 			/* Packet is OK. */
 			/* We don't want to receive our own packets */
-			if (memcmp(rd->skb->data + 6, dev->dev_addr, ETH_ALEN)) {
-				if (len > rx_copybreak) {
-					skb = rd->skb;
-					newskb = netdev_alloc_skb(dev, PKT_BUF_SZ);
-					if (!newskb) {
-						newskb = skb;
-						skb = NULL;
-						goto memory_squeeze;
-					}
-					skb_reserve(newskb, 2);
-				} else {
-					skb = netdev_alloc_skb_ip_align(dev, len);
-					if (skb)
-						skb_copy_to_linear_data(skb, rd->skb->data, len);
-
-					newskb = rd->skb;
-				}
-memory_squeeze:
-				if (skb) {
-					skb_put(skb, len);
-					skb->protocol = eth_type_trans(skb, dev);
-					netif_rx(skb);
-					dev->stats.rx_packets++;
-					dev->stats.rx_bytes += len;
-				} else {
-					printk(KERN_NOTICE "%s: Memory squeeze, deferring packet.\n",
-						dev->name);
-					dev->stats.rx_dropped++;
-				}
-			} else {
-				/* Silently drop my own packets */
-				newskb = rd->skb;
-			}
+			packet_ok = memcmp(rd->skb->data + 6, dev->dev_addr, ETH_ALEN);
 		} else {
 			record_rx_errors(dev, pkt_status);
-			newskb = rd->skb;
+			packet_ok = 0;
+		}
+		dma_sync_single_for_device(dev->dev.parent, rd->rdma.pbuf,
+			PKT_BUF_SZ, DMA_FROM_DEVICE);
+
+		if (packet_ok) {
+			dma_addr_t dma = rd->rdma.pbuf;
+			skb = dev_skb_finish_rx_dma_refill(&rd->skb,
+				len, rx_copybreak, 0, 2,
+				dev->dev.parent, &dma, PKT_BUF_SZ);
+			rd->rdma.pbuf = dma;
+
+			if (likely(skb)) {
+				skb->protocol = eth_type_trans(skb, dev);
+				netif_rx(skb);
+				dev->stats.rx_packets++;
+				dev->stats.rx_bytes += len;
+			} else {
+				printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n",
+					dev->name);
+				dev->stats.rx_dropped++;
+			}
 		}
-		rd->skb = newskb;
-		rd->rdma.pbuf = dma_map_single(dev->dev.parent,
-					       newskb->data - 2,
-					       PKT_BUF_SZ, DMA_FROM_DEVICE);
 
 		/* Return the entry to the ring pool. */
 		rd->rdma.cntinfo = RCNTINFO_INIT;