aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Hemminger <sthemmin@microsoft.com>2016-08-23 15:17:52 -0400
committerDavid S. Miller <davem@davemloft.net>2016-08-23 15:05:37 -0400
commit0ab05141f97de2ac954c267c27b256ebd241e762 (patch)
tree38c18ff8f67c8eadbf7add29ce4d9eec9f1bb850
parentfd612602d6a7919982779fda914bd521e5778593 (diff)
hv_netvsc: rearrange start_xmit
Rearrange the transmit routine to eliminate goto's and unnecessary boolean variables. Use standard functions to test for vlan tag. Signed-off-by: Stephen Hemminger <sthemmin@microsoft.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/hyperv/netvsc_drv.c106
1 files changed, 51 insertions, 55 deletions
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 3bbf07352433..7ed9f13067b5 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -357,11 +357,8 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
357 struct rndis_message *rndis_msg; 357 struct rndis_message *rndis_msg;
358 struct rndis_packet *rndis_pkt; 358 struct rndis_packet *rndis_pkt;
359 u32 rndis_msg_size; 359 u32 rndis_msg_size;
360 bool isvlan;
361 bool linear = false;
362 struct rndis_per_packet_info *ppi; 360 struct rndis_per_packet_info *ppi;
363 struct ndis_tcp_ip_checksum_info *csum_info; 361 struct ndis_tcp_ip_checksum_info *csum_info;
364 struct ndis_tcp_lso_info *lso_info;
365 int hdr_offset; 362 int hdr_offset;
366 u32 net_trans_info; 363 u32 net_trans_info;
367 u32 hash; 364 u32 hash;
@@ -376,22 +373,23 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
376 * more pages we try linearizing it. 373 * more pages we try linearizing it.
377 */ 374 */
378 375
379check_size:
380 skb_length = skb->len; 376 skb_length = skb->len;
381 num_data_pgs = netvsc_get_slots(skb) + 2; 377 num_data_pgs = netvsc_get_slots(skb) + 2;
382 if (num_data_pgs > MAX_PAGE_BUFFER_COUNT && linear) { 378
383 net_alert_ratelimited("packet too big: %u pages (%u bytes)\n", 379 if (unlikely(num_data_pgs > MAX_PAGE_BUFFER_COUNT)) {
384 num_data_pgs, skb->len);
385 ret = -EFAULT;
386 goto drop;
387 } else if (num_data_pgs > MAX_PAGE_BUFFER_COUNT) {
388 if (skb_linearize(skb)) { 380 if (skb_linearize(skb)) {
389 net_alert_ratelimited("failed to linearize skb\n"); 381 net_alert_ratelimited("failed to linearize skb\n");
390 ret = -ENOMEM; 382 ret = -ENOMEM;
391 goto drop; 383 goto drop;
392 } 384 }
393 linear = true; 385
394 goto check_size; 386 num_data_pgs = netvsc_get_slots(skb) + 2;
387 if (num_data_pgs > MAX_PAGE_BUFFER_COUNT) {
388 net_alert_ratelimited("packet too big: %u pages (%u bytes)\n",
389 num_data_pgs, skb->len);
390 ret = -EFAULT;
391 goto drop;
392 }
395 } 393 }
396 394
397 /* 395 /*
@@ -418,8 +416,6 @@ check_size:
418 416
419 memset(rndis_msg, 0, RNDIS_AND_PPI_SIZE); 417 memset(rndis_msg, 0, RNDIS_AND_PPI_SIZE);
420 418
421 isvlan = skb->vlan_tci & VLAN_TAG_PRESENT;
422
423 /* Add the rndis header */ 419 /* Add the rndis header */
424 rndis_msg->ndis_msg_type = RNDIS_MSG_PACKET; 420 rndis_msg->ndis_msg_type = RNDIS_MSG_PACKET;
425 rndis_msg->msg_len = packet->total_data_buflen; 421 rndis_msg->msg_len = packet->total_data_buflen;
@@ -438,7 +434,7 @@ check_size:
438 *(u32 *)((void *)ppi + ppi->ppi_offset) = hash; 434 *(u32 *)((void *)ppi + ppi->ppi_offset) = hash;
439 } 435 }
440 436
441 if (isvlan) { 437 if (skb_vlan_tag_present(skb)) {
442 struct ndis_pkt_8021q_info *vlan; 438 struct ndis_pkt_8021q_info *vlan;
443 439
444 rndis_msg_size += NDIS_VLAN_PPI_SIZE; 440 rndis_msg_size += NDIS_VLAN_PPI_SIZE;
@@ -459,8 +455,37 @@ check_size:
459 * Setup the sendside checksum offload only if this is not a 455 * Setup the sendside checksum offload only if this is not a
460 * GSO packet. 456 * GSO packet.
461 */ 457 */
462 if (skb_is_gso(skb)) 458 if (skb_is_gso(skb)) {
463 goto do_lso; 459 struct ndis_tcp_lso_info *lso_info;
460
461 rndis_msg_size += NDIS_LSO_PPI_SIZE;
462 ppi = init_ppi_data(rndis_msg, NDIS_LSO_PPI_SIZE,
463 TCP_LARGESEND_PKTINFO);
464
465 lso_info = (struct ndis_tcp_lso_info *)((void *)ppi +
466 ppi->ppi_offset);
467
468 lso_info->lso_v2_transmit.type = NDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE;
469 if (net_trans_info & (INFO_IPV4 << 16)) {
470 lso_info->lso_v2_transmit.ip_version =
471 NDIS_TCP_LARGE_SEND_OFFLOAD_IPV4;
472 ip_hdr(skb)->tot_len = 0;
473 ip_hdr(skb)->check = 0;
474 tcp_hdr(skb)->check =
475 ~csum_tcpudp_magic(ip_hdr(skb)->saddr,
476 ip_hdr(skb)->daddr, 0, IPPROTO_TCP, 0);
477 } else {
478 lso_info->lso_v2_transmit.ip_version =
479 NDIS_TCP_LARGE_SEND_OFFLOAD_IPV6;
480 ipv6_hdr(skb)->payload_len = 0;
481 tcp_hdr(skb)->check =
482 ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
483 &ipv6_hdr(skb)->daddr, 0, IPPROTO_TCP, 0);
484 }
485 lso_info->lso_v2_transmit.tcp_header_offset = hdr_offset;
486 lso_info->lso_v2_transmit.mss = skb_shinfo(skb)->gso_size;
487 goto do_send;
488 }
464 489
465 if ((skb->ip_summed == CHECKSUM_NONE) || 490 if ((skb->ip_summed == CHECKSUM_NONE) ||
466 (skb->ip_summed == CHECKSUM_UNNECESSARY)) 491 (skb->ip_summed == CHECKSUM_UNNECESSARY))
@@ -507,35 +532,6 @@ check_size:
507 532
508 csum_info->transmit.udp_checksum = 0; 533 csum_info->transmit.udp_checksum = 0;
509 } 534 }
510 goto do_send;
511
512do_lso:
513 rndis_msg_size += NDIS_LSO_PPI_SIZE;
514 ppi = init_ppi_data(rndis_msg, NDIS_LSO_PPI_SIZE,
515 TCP_LARGESEND_PKTINFO);
516
517 lso_info = (struct ndis_tcp_lso_info *)((void *)ppi +
518 ppi->ppi_offset);
519
520 lso_info->lso_v2_transmit.type = NDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE;
521 if (net_trans_info & (INFO_IPV4 << 16)) {
522 lso_info->lso_v2_transmit.ip_version =
523 NDIS_TCP_LARGE_SEND_OFFLOAD_IPV4;
524 ip_hdr(skb)->tot_len = 0;
525 ip_hdr(skb)->check = 0;
526 tcp_hdr(skb)->check =
527 ~csum_tcpudp_magic(ip_hdr(skb)->saddr,
528 ip_hdr(skb)->daddr, 0, IPPROTO_TCP, 0);
529 } else {
530 lso_info->lso_v2_transmit.ip_version =
531 NDIS_TCP_LARGE_SEND_OFFLOAD_IPV6;
532 ipv6_hdr(skb)->payload_len = 0;
533 tcp_hdr(skb)->check =
534 ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
535 &ipv6_hdr(skb)->daddr, 0, IPPROTO_TCP, 0);
536 }
537 lso_info->lso_v2_transmit.tcp_header_offset = hdr_offset;
538 lso_info->lso_v2_transmit.mss = skb_shinfo(skb)->gso_size;
539 535
540do_send: 536do_send:
541 /* Start filling in the page buffers with the rndis hdr */ 537 /* Start filling in the page buffers with the rndis hdr */
@@ -548,21 +544,21 @@ do_send:
548 skb_tx_timestamp(skb); 544 skb_tx_timestamp(skb);
549 ret = netvsc_send(net_device_ctx->device_ctx, packet, 545 ret = netvsc_send(net_device_ctx->device_ctx, packet,
550 rndis_msg, &pb, skb); 546 rndis_msg, &pb, skb);
551 547 if (likely(ret == 0)) {
552drop:
553 if (ret == 0) {
554 u64_stats_update_begin(&tx_stats->syncp); 548 u64_stats_update_begin(&tx_stats->syncp);
555 tx_stats->packets++; 549 tx_stats->packets++;
556 tx_stats->bytes += skb_length; 550 tx_stats->bytes += skb_length;
557 u64_stats_update_end(&tx_stats->syncp); 551 u64_stats_update_end(&tx_stats->syncp);
558 } else { 552 return NETDEV_TX_OK;
559 if (ret != -EAGAIN) {
560 dev_kfree_skb_any(skb);
561 net->stats.tx_dropped++;
562 }
563 } 553 }
554 if (ret == -EAGAIN)
555 return NETDEV_TX_BUSY;
556
557drop:
558 dev_kfree_skb_any(skb);
559 net->stats.tx_dropped++;
564 560
565 return (ret == -EAGAIN) ? NETDEV_TX_BUSY : NETDEV_TX_OK; 561 return NETDEV_TX_OK;
566} 562}
567 563
568/* 564/*