aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/virtio_net.c81
1 files changed, 44 insertions, 37 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 3041e4eddb3b..420388a4c5e8 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -68,9 +68,16 @@ struct virtnet_info
68 struct page *pages; 68 struct page *pages;
69}; 69};
70 70
71static inline void *skb_vnet_hdr(struct sk_buff *skb) 71struct skb_vnet_hdr {
72 union {
73 struct virtio_net_hdr hdr;
74 struct virtio_net_hdr_mrg_rxbuf mhdr;
75 };
76};
77
78static inline struct skb_vnet_hdr *skb_vnet_hdr(struct sk_buff *skb)
72{ 79{
73 return (struct virtio_net_hdr *)skb->cb; 80 return (struct skb_vnet_hdr *)skb->cb;
74} 81}
75 82
76static void give_a_page(struct virtnet_info *vi, struct page *page) 83static void give_a_page(struct virtnet_info *vi, struct page *page)
@@ -115,7 +122,7 @@ static void receive_skb(struct net_device *dev, struct sk_buff *skb,
115 unsigned len) 122 unsigned len)
116{ 123{
117 struct virtnet_info *vi = netdev_priv(dev); 124 struct virtnet_info *vi = netdev_priv(dev);
118 struct virtio_net_hdr *hdr = skb_vnet_hdr(skb); 125 struct skb_vnet_hdr *hdr = skb_vnet_hdr(skb);
119 int err; 126 int err;
120 int i; 127 int i;
121 128
@@ -126,7 +133,6 @@ static void receive_skb(struct net_device *dev, struct sk_buff *skb,
126 } 133 }
127 134
128 if (vi->mergeable_rx_bufs) { 135 if (vi->mergeable_rx_bufs) {
129 struct virtio_net_hdr_mrg_rxbuf *mhdr = skb_vnet_hdr(skb);
130 unsigned int copy; 136 unsigned int copy;
131 char *p = page_address(skb_shinfo(skb)->frags[0].page); 137 char *p = page_address(skb_shinfo(skb)->frags[0].page);
132 138
@@ -134,8 +140,8 @@ static void receive_skb(struct net_device *dev, struct sk_buff *skb,
134 len = PAGE_SIZE; 140 len = PAGE_SIZE;
135 len -= sizeof(struct virtio_net_hdr_mrg_rxbuf); 141 len -= sizeof(struct virtio_net_hdr_mrg_rxbuf);
136 142
137 memcpy(hdr, p, sizeof(*mhdr)); 143 memcpy(&hdr->mhdr, p, sizeof(hdr->mhdr));
138 p += sizeof(*mhdr); 144 p += sizeof(hdr->mhdr);
139 145
140 copy = len; 146 copy = len;
141 if (copy > skb_tailroom(skb)) 147 if (copy > skb_tailroom(skb))
@@ -150,13 +156,13 @@ static void receive_skb(struct net_device *dev, struct sk_buff *skb,
150 skb_shinfo(skb)->nr_frags--; 156 skb_shinfo(skb)->nr_frags--;
151 } else { 157 } else {
152 skb_shinfo(skb)->frags[0].page_offset += 158 skb_shinfo(skb)->frags[0].page_offset +=
153 sizeof(*mhdr) + copy; 159 sizeof(hdr->mhdr) + copy;
154 skb_shinfo(skb)->frags[0].size = len; 160 skb_shinfo(skb)->frags[0].size = len;
155 skb->data_len += len; 161 skb->data_len += len;
156 skb->len += len; 162 skb->len += len;
157 } 163 }
158 164
159 while (--mhdr->num_buffers) { 165 while (--hdr->mhdr.num_buffers) {
160 struct sk_buff *nskb; 166 struct sk_buff *nskb;
161 167
162 i = skb_shinfo(skb)->nr_frags; 168 i = skb_shinfo(skb)->nr_frags;
@@ -170,7 +176,7 @@ static void receive_skb(struct net_device *dev, struct sk_buff *skb,
170 nskb = vi->rvq->vq_ops->get_buf(vi->rvq, &len); 176 nskb = vi->rvq->vq_ops->get_buf(vi->rvq, &len);
171 if (!nskb) { 177 if (!nskb) {
172 pr_debug("%s: rx error: %d buffers missing\n", 178 pr_debug("%s: rx error: %d buffers missing\n",
173 dev->name, mhdr->num_buffers); 179 dev->name, hdr->mhdr.num_buffers);
174 dev->stats.rx_length_errors++; 180 dev->stats.rx_length_errors++;
175 goto drop; 181 goto drop;
176 } 182 }
@@ -191,7 +197,7 @@ static void receive_skb(struct net_device *dev, struct sk_buff *skb,
191 skb->len += len; 197 skb->len += len;
192 } 198 }
193 } else { 199 } else {
194 len -= sizeof(struct virtio_net_hdr); 200 len -= sizeof(hdr->hdr);
195 201
196 if (len <= MAX_PACKET_LEN) 202 if (len <= MAX_PACKET_LEN)
197 trim_pages(vi, skb); 203 trim_pages(vi, skb);
@@ -209,9 +215,11 @@ static void receive_skb(struct net_device *dev, struct sk_buff *skb,
209 dev->stats.rx_bytes += skb->len; 215 dev->stats.rx_bytes += skb->len;
210 dev->stats.rx_packets++; 216 dev->stats.rx_packets++;
211 217
212 if (hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { 218 if (hdr->hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) {
213 pr_debug("Needs csum!\n"); 219 pr_debug("Needs csum!\n");
214 if (!skb_partial_csum_set(skb,hdr->csum_start,hdr->csum_offset)) 220 if (!skb_partial_csum_set(skb,
221 hdr->hdr.csum_start,
222 hdr->hdr.csum_offset))
215 goto frame_err; 223 goto frame_err;
216 } 224 }
217 225
@@ -219,9 +227,9 @@ static void receive_skb(struct net_device *dev, struct sk_buff *skb,
219 pr_debug("Receiving skb proto 0x%04x len %i type %i\n", 227 pr_debug("Receiving skb proto 0x%04x len %i type %i\n",
220 ntohs(skb->protocol), skb->len, skb->pkt_type); 228 ntohs(skb->protocol), skb->len, skb->pkt_type);
221 229
222 if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) { 230 if (hdr->hdr.gso_type != VIRTIO_NET_HDR_GSO_NONE) {
223 pr_debug("GSO!\n"); 231 pr_debug("GSO!\n");
224 switch (hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { 232 switch (hdr->hdr.gso_type & ~VIRTIO_NET_HDR_GSO_ECN) {
225 case VIRTIO_NET_HDR_GSO_TCPV4: 233 case VIRTIO_NET_HDR_GSO_TCPV4:
226 skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; 234 skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
227 break; 235 break;
@@ -234,14 +242,14 @@ static void receive_skb(struct net_device *dev, struct sk_buff *skb,
234 default: 242 default:
235 if (net_ratelimit()) 243 if (net_ratelimit())
236 printk(KERN_WARNING "%s: bad gso type %u.\n", 244 printk(KERN_WARNING "%s: bad gso type %u.\n",
237 dev->name, hdr->gso_type); 245 dev->name, hdr->hdr.gso_type);
238 goto frame_err; 246 goto frame_err;
239 } 247 }
240 248
241 if (hdr->gso_type & VIRTIO_NET_HDR_GSO_ECN) 249 if (hdr->hdr.gso_type & VIRTIO_NET_HDR_GSO_ECN)
242 skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN; 250 skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN;
243 251
244 skb_shinfo(skb)->gso_size = hdr->gso_size; 252 skb_shinfo(skb)->gso_size = hdr->hdr.gso_size;
245 if (skb_shinfo(skb)->gso_size == 0) { 253 if (skb_shinfo(skb)->gso_size == 0) {
246 if (net_ratelimit()) 254 if (net_ratelimit())
247 printk(KERN_WARNING "%s: zero gso size.\n", 255 printk(KERN_WARNING "%s: zero gso size.\n",
@@ -272,7 +280,7 @@ static bool try_fill_recv_maxbufs(struct virtnet_info *vi, gfp_t gfp)
272 280
273 sg_init_table(sg, 2+MAX_SKB_FRAGS); 281 sg_init_table(sg, 2+MAX_SKB_FRAGS);
274 for (;;) { 282 for (;;) {
275 struct virtio_net_hdr *hdr; 283 struct skb_vnet_hdr *hdr;
276 284
277 skb = netdev_alloc_skb(vi->dev, MAX_PACKET_LEN + NET_IP_ALIGN); 285 skb = netdev_alloc_skb(vi->dev, MAX_PACKET_LEN + NET_IP_ALIGN);
278 if (unlikely(!skb)) { 286 if (unlikely(!skb)) {
@@ -284,7 +292,7 @@ static bool try_fill_recv_maxbufs(struct virtnet_info *vi, gfp_t gfp)
284 skb_put(skb, MAX_PACKET_LEN); 292 skb_put(skb, MAX_PACKET_LEN);
285 293
286 hdr = skb_vnet_hdr(skb); 294 hdr = skb_vnet_hdr(skb);
287 sg_set_buf(sg, hdr, sizeof(*hdr)); 295 sg_set_buf(sg, &hdr->hdr, sizeof(hdr->hdr));
288 296
289 if (vi->big_packets) { 297 if (vi->big_packets) {
290 for (i = 0; i < MAX_SKB_FRAGS; i++) { 298 for (i = 0; i < MAX_SKB_FRAGS; i++) {
@@ -452,8 +460,7 @@ static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb)
452{ 460{
453 int num; 461 int num;
454 struct scatterlist sg[2+MAX_SKB_FRAGS]; 462 struct scatterlist sg[2+MAX_SKB_FRAGS];
455 struct virtio_net_hdr_mrg_rxbuf *mhdr = skb_vnet_hdr(skb); 463 struct skb_vnet_hdr *hdr = skb_vnet_hdr(skb);
456 struct virtio_net_hdr *hdr = skb_vnet_hdr(skb);
457 const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest; 464 const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest;
458 465
459 sg_init_table(sg, 2+MAX_SKB_FRAGS); 466 sg_init_table(sg, 2+MAX_SKB_FRAGS);
@@ -461,39 +468,39 @@ static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb)
461 pr_debug("%s: xmit %p %pM\n", vi->dev->name, skb, dest); 468 pr_debug("%s: xmit %p %pM\n", vi->dev->name, skb, dest);
462 469
463 if (skb->ip_summed == CHECKSUM_PARTIAL) { 470 if (skb->ip_summed == CHECKSUM_PARTIAL) {
464 hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM; 471 hdr->hdr.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
465 hdr->csum_start = skb->csum_start - skb_headroom(skb); 472 hdr->hdr.csum_start = skb->csum_start - skb_headroom(skb);
466 hdr->csum_offset = skb->csum_offset; 473 hdr->hdr.csum_offset = skb->csum_offset;
467 } else { 474 } else {
468 hdr->flags = 0; 475 hdr->hdr.flags = 0;
469 hdr->csum_offset = hdr->csum_start = 0; 476 hdr->hdr.csum_offset = hdr->hdr.csum_start = 0;
470 } 477 }
471 478
472 if (skb_is_gso(skb)) { 479 if (skb_is_gso(skb)) {
473 hdr->hdr_len = skb_headlen(skb); 480 hdr->hdr.hdr_len = skb_headlen(skb);
474 hdr->gso_size = skb_shinfo(skb)->gso_size; 481 hdr->hdr.gso_size = skb_shinfo(skb)->gso_size;
475 if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) 482 if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4)
476 hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4; 483 hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
477 else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) 484 else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
478 hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV6; 485 hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
479 else if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP) 486 else if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP)
480 hdr->gso_type = VIRTIO_NET_HDR_GSO_UDP; 487 hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_UDP;
481 else 488 else
482 BUG(); 489 BUG();
483 if (skb_shinfo(skb)->gso_type & SKB_GSO_TCP_ECN) 490 if (skb_shinfo(skb)->gso_type & SKB_GSO_TCP_ECN)
484 hdr->gso_type |= VIRTIO_NET_HDR_GSO_ECN; 491 hdr->hdr.gso_type |= VIRTIO_NET_HDR_GSO_ECN;
485 } else { 492 } else {
486 hdr->gso_type = VIRTIO_NET_HDR_GSO_NONE; 493 hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_NONE;
487 hdr->gso_size = hdr->hdr_len = 0; 494 hdr->hdr.gso_size = hdr->hdr.hdr_len = 0;
488 } 495 }
489 496
490 mhdr->num_buffers = 0; 497 hdr->mhdr.num_buffers = 0;
491 498
492 /* Encode metadata header at front. */ 499 /* Encode metadata header at front. */
493 if (vi->mergeable_rx_bufs) 500 if (vi->mergeable_rx_bufs)
494 sg_set_buf(sg, mhdr, sizeof(*mhdr)); 501 sg_set_buf(sg, &hdr->mhdr, sizeof(hdr->mhdr));
495 else 502 else
496 sg_set_buf(sg, hdr, sizeof(*hdr)); 503 sg_set_buf(sg, &hdr->hdr, sizeof(hdr->hdr));
497 504
498 num = skb_to_sgvec(skb, sg+1, 0, skb->len) + 1; 505 num = skb_to_sgvec(skb, sg+1, 0, skb->len) + 1;
499 return vi->svq->vq_ops->add_buf(vi->svq, sg, num, 0, skb); 506 return vi->svq->vq_ops->add_buf(vi->svq, sg, num, 0, skb);