diff options
author | Stephen Hemminger <sthemmin@microsoft.com> | 2016-08-23 15:17:52 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-08-23 15:05:37 -0400 |
commit | 0ab05141f97de2ac954c267c27b256ebd241e762 (patch) | |
tree | 38c18ff8f67c8eadbf7add29ce4d9eec9f1bb850 | |
parent | fd612602d6a7919982779fda914bd521e5778593 (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.c | 106 |
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 | ||
379 | check_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 | |||
512 | do_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 | ||
540 | do_send: | 536 | do_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)) { | |
552 | drop: | ||
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 | |||
557 | drop: | ||
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 | /* |