[PATCH 373/577] Staging: hv: transmit scatter gather support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Stephen Hemminger <shemminger@xxxxxxxxxx>

The transmit management of pages was confusing for handling
fragmented SKB's. (But since NETIF_F_SG was never set, the code was never hit).

The parameter AdditionalRequestPageBufferCount is always one,
(and leads to ugly code), so just inline and add comments.

Signed-off-by: Stephen Hemminger <shemminger@xxxxxxxxxx>
Acked-by: Hank Janssen <hjanssen@xxxxxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxx>
---
 drivers/staging/hv/RndisFilter.c |    1 -
 drivers/staging/hv/netvsc_drv.c  |   53 +++++++++++++++----------------------
 2 files changed, 22 insertions(+), 32 deletions(-)

diff --git a/drivers/staging/hv/RndisFilter.c b/drivers/staging/hv/RndisFilter.c
index 8611396..de4bc80 100644
--- a/drivers/staging/hv/RndisFilter.c
+++ b/drivers/staging/hv/RndisFilter.c
@@ -624,7 +624,6 @@ int RndisFilterInit(struct netvsc_driver *Driver)
 		   sizeof(struct rndis_filter_packet));
 
 	Driver->RequestExtSize = sizeof(struct rndis_filter_packet);
-	Driver->AdditionalRequestPageBufferCount = 1; /* For rndis header */
 
 	/* Driver->Context = rndisDriver; */
 
diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c
index b02455c..4124979 100644
--- a/drivers/staging/hv/netvsc_drv.c
+++ b/drivers/staging/hv/netvsc_drv.c
@@ -144,27 +144,21 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
 		(struct netvsc_driver_context *)driver_ctx;
 	struct netvsc_driver *net_drv_obj = &net_drv_ctx->drv_obj;
 	struct hv_netvsc_packet *packet;
-	int i;
 	int ret;
-	int num_frags;
+	unsigned int i, num_pages;
 	int retries = 0;
 
 	DPRINT_ENTER(NETVSC_DRV);
 
-	/* Support only 1 chain of frags */
-	ASSERT(skb_shinfo(skb)->frag_list == NULL);
-	ASSERT(skb->dev == net);
-
 	DPRINT_DBG(NETVSC_DRV, "xmit packet - len %d data_len %d",
 		   skb->len, skb->data_len);
 
-	/* Add 1 for skb->data and any additional ones requested */
-	num_frags = skb_shinfo(skb)->nr_frags + 1 +
-		    net_drv_obj->AdditionalRequestPageBufferCount;
+	/* Add 1 for skb->data and additional one for RNDIS */
+	num_pages = skb_shinfo(skb)->nr_frags + 1 + 1;
 
 	/* Allocate a netvsc packet based on # of frags. */
 	packet = kzalloc(sizeof(struct hv_netvsc_packet) +
-			 (num_frags * sizeof(struct hv_page_buffer)) +
+			 (num_pages * sizeof(struct hv_page_buffer)) +
 			 net_drv_obj->RequestExtSize, GFP_ATOMIC);
 	if (!packet) {
 		DPRINT_ERR(NETVSC_DRV, "unable to allocate hv_netvsc_packet");
@@ -173,36 +167,30 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
 
 	packet->Extension = (void *)(unsigned long)packet +
 				sizeof(struct hv_netvsc_packet) +
-				    (num_frags * sizeof(struct hv_page_buffer));
+				    (num_pages * sizeof(struct hv_page_buffer));
 
 	/* Setup the rndis header */
-	packet->PageBufferCount = num_frags;
+	packet->PageBufferCount = num_pages;
 
 	/* TODO: Flush all write buffers/ memory fence ??? */
 	/* wmb(); */
 
 	/* Initialize it from the skb */
-	ASSERT(skb->data);
 	packet->TotalDataBufferLength	= skb->len;
 
-	/*
-	 * Start filling in the page buffers starting at
-	 * AdditionalRequestPageBufferCount offset
-	 */
-	packet->PageBuffers[net_drv_obj->AdditionalRequestPageBufferCount].Pfn = virt_to_phys(skb->data) >> PAGE_SHIFT;
-	packet->PageBuffers[net_drv_obj->AdditionalRequestPageBufferCount].Offset = (unsigned long)skb->data & (PAGE_SIZE - 1);
-	packet->PageBuffers[net_drv_obj->AdditionalRequestPageBufferCount].Length = skb->len - skb->data_len;
-
-	ASSERT((skb->len - skb->data_len) <= PAGE_SIZE);
-
-	for (i = net_drv_obj->AdditionalRequestPageBufferCount + 1;
-	     i < num_frags; i++) {
-		packet->PageBuffers[i].Pfn =
-			page_to_pfn(skb_shinfo(skb)->frags[i-(net_drv_obj->AdditionalRequestPageBufferCount+1)].page);
-		packet->PageBuffers[i].Offset =
-			skb_shinfo(skb)->frags[i-(net_drv_obj->AdditionalRequestPageBufferCount+1)].page_offset;
-		packet->PageBuffers[i].Length =
-			skb_shinfo(skb)->frags[i-(net_drv_obj->AdditionalRequestPageBufferCount+1)].size;
+	/* Start filling in the page buffers starting after RNDIS buffer. */
+	packet->PageBuffers[1].Pfn = virt_to_phys(skb->data) >> PAGE_SHIFT;
+	packet->PageBuffers[1].Offset
+		= (unsigned long)skb->data & (PAGE_SIZE - 1);
+	packet->PageBuffers[1].Length = skb_headlen(skb);
+
+	/* Additional fragments are after SKB data */
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+		skb_frag_t *f = &skb_shinfo(skb)->frags[i];
+
+		packet->PageBuffers[i+2].Pfn = page_to_pfn(f->page);
+		packet->PageBuffers[i+2].Offset = f->page_offset;
+		packet->PageBuffers[i+2].Length = f->size;
 	}
 
 	/* Set the completion routine */
@@ -423,6 +411,9 @@ static int netvsc_probe(struct device *device)
 
 	net->netdev_ops = &device_ops;
 
+	/* TODO: Add GSO and Checksum offload */
+	net->features = NETIF_F_SG;
+
 	SET_NETDEV_DEV(net, device);
 
 	ret = register_netdev(net);
-- 
1.7.0.3

_______________________________________________
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxx
http://driverdev.linuxdriverproject.org/mailman/listinfo/devel

[Index of Archives]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux