Commit 6048718d authored by Stephen Hemminger's avatar Stephen Hemminger Committed by Greg Kroah-Hartman

Staging: hv: transmit scatter gather support

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: default avatarStephen Hemminger <shemminger@vyatta.com>
Acked-by: default avatarHank Janssen <hjanssen@microsoft.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 9f8bd8ba
...@@ -624,7 +624,6 @@ int RndisFilterInit(struct netvsc_driver *Driver) ...@@ -624,7 +624,6 @@ int RndisFilterInit(struct netvsc_driver *Driver)
sizeof(struct rndis_filter_packet)); sizeof(struct rndis_filter_packet));
Driver->RequestExtSize = sizeof(struct rndis_filter_packet); Driver->RequestExtSize = sizeof(struct rndis_filter_packet);
Driver->AdditionalRequestPageBufferCount = 1; /* For rndis header */
/* Driver->Context = rndisDriver; */ /* Driver->Context = rndisDriver; */
......
...@@ -144,27 +144,21 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) ...@@ -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_context *)driver_ctx;
struct netvsc_driver *net_drv_obj = &net_drv_ctx->drv_obj; struct netvsc_driver *net_drv_obj = &net_drv_ctx->drv_obj;
struct hv_netvsc_packet *packet; struct hv_netvsc_packet *packet;
int i;
int ret; int ret;
int num_frags; unsigned int i, num_pages;
int retries = 0; int retries = 0;
DPRINT_ENTER(NETVSC_DRV); 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", DPRINT_DBG(NETVSC_DRV, "xmit packet - len %d data_len %d",
skb->len, skb->data_len); skb->len, skb->data_len);
/* Add 1 for skb->data and any additional ones requested */ /* Add 1 for skb->data and additional one for RNDIS */
num_frags = skb_shinfo(skb)->nr_frags + 1 + num_pages = skb_shinfo(skb)->nr_frags + 1 + 1;
net_drv_obj->AdditionalRequestPageBufferCount;
/* Allocate a netvsc packet based on # of frags. */ /* Allocate a netvsc packet based on # of frags. */
packet = kzalloc(sizeof(struct hv_netvsc_packet) + 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); net_drv_obj->RequestExtSize, GFP_ATOMIC);
if (!packet) { if (!packet) {
DPRINT_ERR(NETVSC_DRV, "unable to allocate hv_netvsc_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) ...@@ -173,36 +167,30 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
packet->Extension = (void *)(unsigned long)packet + packet->Extension = (void *)(unsigned long)packet +
sizeof(struct hv_netvsc_packet) + sizeof(struct hv_netvsc_packet) +
(num_frags * sizeof(struct hv_page_buffer)); (num_pages * sizeof(struct hv_page_buffer));
/* Setup the rndis header */ /* Setup the rndis header */
packet->PageBufferCount = num_frags; packet->PageBufferCount = num_pages;
/* TODO: Flush all write buffers/ memory fence ??? */ /* TODO: Flush all write buffers/ memory fence ??? */
/* wmb(); */ /* wmb(); */
/* Initialize it from the skb */ /* Initialize it from the skb */
ASSERT(skb->data);
packet->TotalDataBufferLength = skb->len; packet->TotalDataBufferLength = skb->len;
/* /* Start filling in the page buffers starting after RNDIS buffer. */
* Start filling in the page buffers starting at packet->PageBuffers[1].Pfn = virt_to_phys(skb->data) >> PAGE_SHIFT;
* AdditionalRequestPageBufferCount offset packet->PageBuffers[1].Offset
*/ = (unsigned long)skb->data & (PAGE_SIZE - 1);
packet->PageBuffers[net_drv_obj->AdditionalRequestPageBufferCount].Pfn = virt_to_phys(skb->data) >> PAGE_SHIFT; packet->PageBuffers[1].Length = skb_headlen(skb);
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; /* Additional fragments are after SKB data */
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
ASSERT((skb->len - skb->data_len) <= PAGE_SIZE); skb_frag_t *f = &skb_shinfo(skb)->frags[i];
for (i = net_drv_obj->AdditionalRequestPageBufferCount + 1; packet->PageBuffers[i+2].Pfn = page_to_pfn(f->page);
i < num_frags; i++) { packet->PageBuffers[i+2].Offset = f->page_offset;
packet->PageBuffers[i].Pfn = packet->PageBuffers[i+2].Length = f->size;
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;
} }
/* Set the completion routine */ /* Set the completion routine */
...@@ -423,6 +411,9 @@ static int netvsc_probe(struct device *device) ...@@ -423,6 +411,9 @@ static int netvsc_probe(struct device *device)
net->netdev_ops = &device_ops; net->netdev_ops = &device_ops;
/* TODO: Add GSO and Checksum offload */
net->features = NETIF_F_SG;
SET_NETDEV_DEV(net, device); SET_NETDEV_DEV(net, device);
ret = register_netdev(net); ret = register_netdev(net);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment