diff options
Diffstat (limited to 'drivers/net/hyperv/netvsc.c')
-rw-r--r-- | drivers/net/hyperv/netvsc.c | 41 |
1 files changed, 37 insertions, 4 deletions
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c index d025c83cd12a..8b919471472f 100644 --- a/drivers/net/hyperv/netvsc.c +++ b/drivers/net/hyperv/netvsc.c | |||
@@ -428,6 +428,24 @@ int netvsc_device_remove(struct hv_device *device) | |||
428 | return 0; | 428 | return 0; |
429 | } | 429 | } |
430 | 430 | ||
431 | |||
432 | #define RING_AVAIL_PERCENT_HIWATER 20 | ||
433 | #define RING_AVAIL_PERCENT_LOWATER 10 | ||
434 | |||
435 | /* | ||
436 | * Get the percentage of available bytes to write in the ring. | ||
437 | * The return value is in range from 0 to 100. | ||
438 | */ | ||
439 | static inline u32 hv_ringbuf_avail_percent( | ||
440 | struct hv_ring_buffer_info *ring_info) | ||
441 | { | ||
442 | u32 avail_read, avail_write; | ||
443 | |||
444 | hv_get_ringbuffer_availbytes(ring_info, &avail_read, &avail_write); | ||
445 | |||
446 | return avail_write * 100 / ring_info->ring_datasize; | ||
447 | } | ||
448 | |||
431 | static void netvsc_send_completion(struct hv_device *device, | 449 | static void netvsc_send_completion(struct hv_device *device, |
432 | struct vmpacket_descriptor *packet) | 450 | struct vmpacket_descriptor *packet) |
433 | { | 451 | { |
@@ -455,6 +473,8 @@ static void netvsc_send_completion(struct hv_device *device, | |||
455 | complete(&net_device->channel_init_wait); | 473 | complete(&net_device->channel_init_wait); |
456 | } else if (nvsp_packet->hdr.msg_type == | 474 | } else if (nvsp_packet->hdr.msg_type == |
457 | NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE) { | 475 | NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE) { |
476 | int num_outstanding_sends; | ||
477 | |||
458 | /* Get the send context */ | 478 | /* Get the send context */ |
459 | nvsc_packet = (struct hv_netvsc_packet *)(unsigned long) | 479 | nvsc_packet = (struct hv_netvsc_packet *)(unsigned long) |
460 | packet->trans_id; | 480 | packet->trans_id; |
@@ -463,10 +483,14 @@ static void netvsc_send_completion(struct hv_device *device, | |||
463 | nvsc_packet->completion.send.send_completion( | 483 | nvsc_packet->completion.send.send_completion( |
464 | nvsc_packet->completion.send.send_completion_ctx); | 484 | nvsc_packet->completion.send.send_completion_ctx); |
465 | 485 | ||
466 | atomic_dec(&net_device->num_outstanding_sends); | 486 | num_outstanding_sends = |
487 | atomic_dec_return(&net_device->num_outstanding_sends); | ||
467 | 488 | ||
468 | if (netif_queue_stopped(ndev) && !net_device->start_remove) | 489 | if (netif_queue_stopped(ndev) && !net_device->start_remove && |
469 | netif_wake_queue(ndev); | 490 | (hv_ringbuf_avail_percent(&device->channel->outbound) |
491 | > RING_AVAIL_PERCENT_HIWATER || | ||
492 | num_outstanding_sends < 1)) | ||
493 | netif_wake_queue(ndev); | ||
470 | } else { | 494 | } else { |
471 | netdev_err(ndev, "Unknown send completion packet type- " | 495 | netdev_err(ndev, "Unknown send completion packet type- " |
472 | "%d received!!\n", nvsp_packet->hdr.msg_type); | 496 | "%d received!!\n", nvsp_packet->hdr.msg_type); |
@@ -519,10 +543,19 @@ int netvsc_send(struct hv_device *device, | |||
519 | 543 | ||
520 | if (ret == 0) { | 544 | if (ret == 0) { |
521 | atomic_inc(&net_device->num_outstanding_sends); | 545 | atomic_inc(&net_device->num_outstanding_sends); |
546 | if (hv_ringbuf_avail_percent(&device->channel->outbound) < | ||
547 | RING_AVAIL_PERCENT_LOWATER) { | ||
548 | netif_stop_queue(ndev); | ||
549 | if (atomic_read(&net_device-> | ||
550 | num_outstanding_sends) < 1) | ||
551 | netif_wake_queue(ndev); | ||
552 | } | ||
522 | } else if (ret == -EAGAIN) { | 553 | } else if (ret == -EAGAIN) { |
523 | netif_stop_queue(ndev); | 554 | netif_stop_queue(ndev); |
524 | if (atomic_read(&net_device->num_outstanding_sends) < 1) | 555 | if (atomic_read(&net_device->num_outstanding_sends) < 1) { |
525 | netif_wake_queue(ndev); | 556 | netif_wake_queue(ndev); |
557 | ret = -ENOSPC; | ||
558 | } | ||
526 | } else { | 559 | } else { |
527 | netdev_err(ndev, "Unable to send packet %p ret %d\n", | 560 | netdev_err(ndev, "Unable to send packet %p ret %d\n", |
528 | packet, ret); | 561 | packet, ret); |