aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@vyatta.com>2010-05-04 12:58:55 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-05-11 14:36:09 -0400
commit6048718d719f460abba8eaff1c0122247b2c3d91 (patch)
treebca18394ccf66190d2221c422ed0419135a6ea28
parent9f8bd8bacf90c78e331ad63c38b0ea167e2ce639 (diff)
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>
-rw-r--r--drivers/staging/hv/RndisFilter.c1
-rw-r--r--drivers/staging/hv/netvsc_drv.c53
2 files changed, 22 insertions, 32 deletions
diff --git a/drivers/staging/hv/RndisFilter.c b/drivers/staging/hv/RndisFilter.c
index 861139677e3..de4bc80341c 100644
--- a/drivers/staging/hv/RndisFilter.c
+++ b/drivers/staging/hv/RndisFilter.c
@@ -624,7 +624,6 @@ int RndisFilterInit(struct netvsc_driver *Driver)
624 sizeof(struct rndis_filter_packet)); 624 sizeof(struct rndis_filter_packet));
625 625
626 Driver->RequestExtSize = sizeof(struct rndis_filter_packet); 626 Driver->RequestExtSize = sizeof(struct rndis_filter_packet);
627 Driver->AdditionalRequestPageBufferCount = 1; /* For rndis header */
628 627
629 /* Driver->Context = rndisDriver; */ 628 /* Driver->Context = rndisDriver; */
630 629
diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c
index b02455cfe23..4124979835a 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)
144 (struct netvsc_driver_context *)driver_ctx; 144 (struct netvsc_driver_context *)driver_ctx;
145 struct netvsc_driver *net_drv_obj = &net_drv_ctx->drv_obj; 145 struct netvsc_driver *net_drv_obj = &net_drv_ctx->drv_obj;
146 struct hv_netvsc_packet *packet; 146 struct hv_netvsc_packet *packet;
147 int i;
148 int ret; 147 int ret;
149 int num_frags; 148 unsigned int i, num_pages;
150 int retries = 0; 149 int retries = 0;
151 150
152 DPRINT_ENTER(NETVSC_DRV); 151 DPRINT_ENTER(NETVSC_DRV);
153 152
154 /* Support only 1 chain of frags */
155 ASSERT(skb_shinfo(skb)->frag_list == NULL);
156 ASSERT(skb->dev == net);
157
158 DPRINT_DBG(NETVSC_DRV, "xmit packet - len %d data_len %d", 153 DPRINT_DBG(NETVSC_DRV, "xmit packet - len %d data_len %d",
159 skb->len, skb->data_len); 154 skb->len, skb->data_len);
160 155
161 /* Add 1 for skb->data and any additional ones requested */ 156 /* Add 1 for skb->data and additional one for RNDIS */
162 num_frags = skb_shinfo(skb)->nr_frags + 1 + 157 num_pages = skb_shinfo(skb)->nr_frags + 1 + 1;
163 net_drv_obj->AdditionalRequestPageBufferCount;
164 158
165 /* Allocate a netvsc packet based on # of frags. */ 159 /* Allocate a netvsc packet based on # of frags. */
166 packet = kzalloc(sizeof(struct hv_netvsc_packet) + 160 packet = kzalloc(sizeof(struct hv_netvsc_packet) +
167 (num_frags * sizeof(struct hv_page_buffer)) + 161 (num_pages * sizeof(struct hv_page_buffer)) +
168 net_drv_obj->RequestExtSize, GFP_ATOMIC); 162 net_drv_obj->RequestExtSize, GFP_ATOMIC);
169 if (!packet) { 163 if (!packet) {
170 DPRINT_ERR(NETVSC_DRV, "unable to allocate hv_netvsc_packet"); 164 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 167
174 packet->Extension = (void *)(unsigned long)packet + 168 packet->Extension = (void *)(unsigned long)packet +
175 sizeof(struct hv_netvsc_packet) + 169 sizeof(struct hv_netvsc_packet) +
176 (num_frags * sizeof(struct hv_page_buffer)); 170 (num_pages * sizeof(struct hv_page_buffer));
177 171
178 /* Setup the rndis header */ 172 /* Setup the rndis header */
179 packet->PageBufferCount = num_frags; 173 packet->PageBufferCount = num_pages;
180 174
181 /* TODO: Flush all write buffers/ memory fence ??? */ 175 /* TODO: Flush all write buffers/ memory fence ??? */
182 /* wmb(); */ 176 /* wmb(); */
183 177
184 /* Initialize it from the skb */ 178 /* Initialize it from the skb */
185 ASSERT(skb->data);
186 packet->TotalDataBufferLength = skb->len; 179 packet->TotalDataBufferLength = skb->len;
187 180
188 /* 181 /* Start filling in the page buffers starting after RNDIS buffer. */
189 * Start filling in the page buffers starting at 182 packet->PageBuffers[1].Pfn = virt_to_phys(skb->data) >> PAGE_SHIFT;
190 * AdditionalRequestPageBufferCount offset 183 packet->PageBuffers[1].Offset
191 */ 184 = (unsigned long)skb->data & (PAGE_SIZE - 1);
192 packet->PageBuffers[net_drv_obj->AdditionalRequestPageBufferCount].Pfn = virt_to_phys(skb->data) >> PAGE_SHIFT; 185 packet->PageBuffers[1].Length = skb_headlen(skb);
193 packet->PageBuffers[net_drv_obj->AdditionalRequestPageBufferCount].Offset = (unsigned long)skb->data & (PAGE_SIZE - 1); 186
194 packet->PageBuffers[net_drv_obj->AdditionalRequestPageBufferCount].Length = skb->len - skb->data_len; 187 /* Additional fragments are after SKB data */
195 188 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
196 ASSERT((skb->len - skb->data_len) <= PAGE_SIZE); 189 skb_frag_t *f = &skb_shinfo(skb)->frags[i];
197 190
198 for (i = net_drv_obj->AdditionalRequestPageBufferCount + 1; 191 packet->PageBuffers[i+2].Pfn = page_to_pfn(f->page);
199 i < num_frags; i++) { 192 packet->PageBuffers[i+2].Offset = f->page_offset;
200 packet->PageBuffers[i].Pfn = 193 packet->PageBuffers[i+2].Length = f->size;
201 page_to_pfn(skb_shinfo(skb)->frags[i-(net_drv_obj->AdditionalRequestPageBufferCount+1)].page);
202 packet->PageBuffers[i].Offset =
203 skb_shinfo(skb)->frags[i-(net_drv_obj->AdditionalRequestPageBufferCount+1)].page_offset;
204 packet->PageBuffers[i].Length =
205 skb_shinfo(skb)->frags[i-(net_drv_obj->AdditionalRequestPageBufferCount+1)].size;
206 } 194 }
207 195
208 /* Set the completion routine */ 196 /* Set the completion routine */
@@ -423,6 +411,9 @@ static int netvsc_probe(struct device *device)
423 411
424 net->netdev_ops = &device_ops; 412 net->netdev_ops = &device_ops;
425 413
414 /* TODO: Add GSO and Checksum offload */
415 net->features = NETIF_F_SG;
416
426 SET_NETDEV_DEV(net, device); 417 SET_NETDEV_DEV(net, device);
427 418
428 ret = register_netdev(net); 419 ret = register_netdev(net);