mirror of
https://github.com/edk2-porting/linux-next.git
synced 2025-01-14 16:44:29 +08:00
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: Stephen Hemminger <shemminger@vyatta.com> Acked-by: Hank Janssen <hjanssen@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
9f8bd8bacf
commit
6048718d71
@ -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)
|
|||||||
(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)
|
|||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
ASSERT((skb->len - skb->data_len) <= PAGE_SIZE);
|
/* 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];
|
||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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);
|
||||||
|
Loading…
Reference in New Issue
Block a user