Skip to content

Commit

Permalink
Merge branch 'netvsc-NAPI'
Browse files Browse the repository at this point in the history
Stephen Hemminger says:

====================
NAPI support for Hyper-V

These patches enable NAPI, GRO and napi_alloc_skb for Hyper-V netvsc
driver.
====================

Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
davem330 committed Mar 7, 2017
2 parents 1a4691b + e91e7dd commit 81fa846
Show file tree
Hide file tree
Showing 6 changed files with 242 additions and 143 deletions.
94 changes: 93 additions & 1 deletion drivers/hv/ring_buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@

#include "hyperv_vmbus.h"

#define VMBUS_PKT_TRAILER 8

/*
* When we write to the ring buffer, check if the host needs to
* be signaled. Here is the details of this protocol:
Expand Down Expand Up @@ -336,6 +338,12 @@ int hv_ringbuffer_write(struct vmbus_channel *channel,
return 0;
}

static inline void
init_cached_read_index(struct hv_ring_buffer_info *rbi)
{
rbi->cached_read_index = rbi->ring_buffer->read_index;
}

int hv_ringbuffer_read(struct vmbus_channel *channel,
void *buffer, u32 buflen, u32 *buffer_actual_len,
u64 *requestid, bool raw)
Expand Down Expand Up @@ -366,7 +374,8 @@ int hv_ringbuffer_read(struct vmbus_channel *channel,
return ret;
}

init_cached_read_index(channel);
init_cached_read_index(inring_info);

next_read_location = hv_get_next_read_location(inring_info);
next_read_location = hv_copyfrom_ringbuffer(inring_info, &desc,
sizeof(desc),
Expand Down Expand Up @@ -410,3 +419,86 @@ int hv_ringbuffer_read(struct vmbus_channel *channel,

return ret;
}

/*
* Determine number of bytes available in ring buffer after
* the current iterator (priv_read_index) location.
*
* This is similar to hv_get_bytes_to_read but with private
* read index instead.
*/
static u32 hv_pkt_iter_avail(const struct hv_ring_buffer_info *rbi)
{
u32 priv_read_loc = rbi->priv_read_index;
u32 write_loc = READ_ONCE(rbi->ring_buffer->write_index);

if (write_loc >= priv_read_loc)
return write_loc - priv_read_loc;
else
return (rbi->ring_datasize - priv_read_loc) + write_loc;
}

/*
* Get first vmbus packet from ring buffer after read_index
*
* If ring buffer is empty, returns NULL and no other action needed.
*/
struct vmpacket_descriptor *hv_pkt_iter_first(struct vmbus_channel *channel)
{
struct hv_ring_buffer_info *rbi = &channel->inbound;

/* set state for later hv_signal_on_read() */
init_cached_read_index(rbi);

if (hv_pkt_iter_avail(rbi) < sizeof(struct vmpacket_descriptor))
return NULL;

return hv_get_ring_buffer(rbi) + rbi->priv_read_index;
}
EXPORT_SYMBOL_GPL(hv_pkt_iter_first);

/*
* Get next vmbus packet from ring buffer.
*
* Advances the current location (priv_read_index) and checks for more
* data. If the end of the ring buffer is reached, then return NULL.
*/
struct vmpacket_descriptor *
__hv_pkt_iter_next(struct vmbus_channel *channel,
const struct vmpacket_descriptor *desc)
{
struct hv_ring_buffer_info *rbi = &channel->inbound;
u32 packetlen = desc->len8 << 3;
u32 dsize = rbi->ring_datasize;

/* bump offset to next potential packet */
rbi->priv_read_index += packetlen + VMBUS_PKT_TRAILER;
if (rbi->priv_read_index >= dsize)
rbi->priv_read_index -= dsize;

/* more data? */
if (hv_pkt_iter_avail(rbi) < sizeof(struct vmpacket_descriptor))
return NULL;
else
return hv_get_ring_buffer(rbi) + rbi->priv_read_index;
}
EXPORT_SYMBOL_GPL(__hv_pkt_iter_next);

/*
* Update host ring buffer after iterating over packets.
*/
void hv_pkt_iter_close(struct vmbus_channel *channel)
{
struct hv_ring_buffer_info *rbi = &channel->inbound;

/*
* Make sure all reads are done before we update the read index since
* the writer may start writing to the read area once the read index
* is updated.
*/
virt_rmb();
rbi->ring_buffer->read_index = rbi->priv_read_index;

hv_signal_on_read(channel);
}
EXPORT_SYMBOL_GPL(hv_pkt_iter_close);
2 changes: 2 additions & 0 deletions drivers/net/hyperv/hyperv_net.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ int netvsc_recv_callback(struct net_device *net,
const struct ndis_tcp_ip_checksum_info *csum_info,
const struct ndis_pkt_8021q_info *vlan);
void netvsc_channel_cb(void *context);
int netvsc_poll(struct napi_struct *napi, int budget);
int rndis_filter_open(struct netvsc_device *nvdev);
int rndis_filter_close(struct netvsc_device *nvdev);
int rndis_filter_device_add(struct hv_device *dev,
Expand Down Expand Up @@ -720,6 +721,7 @@ struct net_device_context {
/* Per channel data */
struct netvsc_channel {
struct vmbus_channel *channel;
struct napi_struct napi;
struct multi_send_data msd;
struct multi_recv_comp mrc;
atomic_t queue_sends;
Expand Down
Loading

0 comments on commit 81fa846

Please sign in to comment.