diff options
author | 2017-08-09 17:46:12 -0700 | |
---|---|---|
committer | 2017-08-11 14:00:07 -0700 | |
commit | cad5c197704d82faf33ffdbef414f15db08d9ef9 (patch) | |
tree | cf0ded26e32303739cb21d1357a799438f901cc2 /drivers/net/hyperv/netvsc.c | |
parent | netvsc: allow controlling send/recv buffer size (diff) | |
download | linux-cad5c197704d82faf33ffdbef414f15db08d9ef9.tar.gz linux-cad5c197704d82faf33ffdbef414f15db08d9ef9.tar.bz2 linux-cad5c197704d82faf33ffdbef414f15db08d9ef9.zip |
netvsc: keep track of some non-fatal overload conditions
Add ethtool statistics for case where send chimmeny buffer is
exhausted and driver has to fall back to doing scatter/gather
send. Also, add statistic for case where ring buffer is full and
receive completions are delayed.
Signed-off-by: Stephen Hemminger <sthemmin@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/hyperv/netvsc.c')
-rw-r--r-- | drivers/net/hyperv/netvsc.c | 19 |
1 files changed, 13 insertions, 6 deletions
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c index d9d7555148eb..0530e7d729e1 100644 --- a/drivers/net/hyperv/netvsc.c +++ b/drivers/net/hyperv/netvsc.c @@ -883,7 +883,9 @@ int netvsc_send(struct net_device_context *ndev_ctx, } else if (pktlen + net_device->pkt_align < net_device->send_section_size) { section_index = netvsc_get_next_send_section(net_device); - if (section_index != NETVSC_INVALID_INDEX) { + if (unlikely(section_index == NETVSC_INVALID_INDEX)) { + ++ndev_ctx->eth_stats.tx_send_full; + } else { move_pkt_msd(&msd_send, &msd_skb, msdp); msd_len = 0; } @@ -949,9 +951,10 @@ send_now: } /* Send pending recv completions */ -static int send_recv_completions(struct netvsc_channel *nvchan) +static int send_recv_completions(struct net_device *ndev, + struct netvsc_device *nvdev, + struct netvsc_channel *nvchan) { - struct netvsc_device *nvdev = nvchan->net_device; struct multi_recv_comp *mrc = &nvchan->mrc; struct recv_comp_msg { struct nvsp_message_header hdr; @@ -969,8 +972,12 @@ static int send_recv_completions(struct netvsc_channel *nvchan) msg.status = rcd->status; ret = vmbus_sendpacket(nvchan->channel, &msg, sizeof(msg), rcd->tid, VM_PKT_COMP, 0); - if (unlikely(ret)) + if (unlikely(ret)) { + struct net_device_context *ndev_ctx = netdev_priv(ndev); + + ++ndev_ctx->eth_stats.rx_comp_busy; return ret; + } if (++mrc->first == nvdev->recv_completion_cnt) mrc->first = 0; @@ -1011,7 +1018,7 @@ static void enq_receive_complete(struct net_device *ndev, recv_comp_slot_avail(nvdev, mrc, &filled, &avail); if (unlikely(filled > NAPI_POLL_WEIGHT)) { - send_recv_completions(nvchan); + send_recv_completions(ndev, nvdev, nvchan); recv_comp_slot_avail(nvdev, mrc, &filled, &avail); } @@ -1194,7 +1201,7 @@ int netvsc_poll(struct napi_struct *napi, int budget) * then re-enable host interrupts * and reschedule if ring is not empty. */ - if (send_recv_completions(nvchan) == 0 && + if (send_recv_completions(ndev, net_device, nvchan) == 0 && work_done < budget && napi_complete_done(napi, work_done) && hv_end_read(&channel->inbound)) { |