Commit 2b3a9afc authored by David S. Miller's avatar David S. Miller

Merge branch 'netvsc-small-cleanups'

Stephen Hemminger says:

====================
netvsc: small cleanups

These are all small optimizations found during development of later features.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents e073782a 592b4fe8
...@@ -763,8 +763,7 @@ struct netvsc_device { ...@@ -763,8 +763,7 @@ struct netvsc_device {
refcount_t sc_offered; refcount_t sc_offered;
/* Holds rndis device info */ struct rndis_device *extension;
void *extension;
int ring_size; int ring_size;
......
...@@ -97,16 +97,6 @@ static void free_netvsc_device_rcu(struct netvsc_device *nvdev) ...@@ -97,16 +97,6 @@ static void free_netvsc_device_rcu(struct netvsc_device *nvdev)
call_rcu(&nvdev->rcu, free_netvsc_device); call_rcu(&nvdev->rcu, free_netvsc_device);
} }
static struct netvsc_device *get_outbound_net_device(struct hv_device *device)
{
struct netvsc_device *net_device = hv_device_to_netvsc_device(device);
if (net_device && net_device->destroy)
net_device = NULL;
return net_device;
}
static void netvsc_destroy_buf(struct hv_device *device) static void netvsc_destroy_buf(struct hv_device *device)
{ {
struct nvsp_message *revoke_packet; struct nvsp_message *revoke_packet;
...@@ -243,18 +233,15 @@ static void netvsc_destroy_buf(struct hv_device *device) ...@@ -243,18 +233,15 @@ static void netvsc_destroy_buf(struct hv_device *device)
kfree(net_device->send_section_map); kfree(net_device->send_section_map);
} }
static int netvsc_init_buf(struct hv_device *device) static int netvsc_init_buf(struct hv_device *device,
struct netvsc_device *net_device)
{ {
int ret = 0; int ret = 0;
struct netvsc_device *net_device;
struct nvsp_message *init_packet; struct nvsp_message *init_packet;
struct net_device *ndev; struct net_device *ndev;
size_t map_words; size_t map_words;
int node; int node;
net_device = get_outbound_net_device(device);
if (!net_device)
return -ENODEV;
ndev = hv_get_drvdata(device); ndev = hv_get_drvdata(device);
node = cpu_to_node(device->channel->target_cpu); node = cpu_to_node(device->channel->target_cpu);
...@@ -285,9 +272,7 @@ static int netvsc_init_buf(struct hv_device *device) ...@@ -285,9 +272,7 @@ static int netvsc_init_buf(struct hv_device *device)
/* Notify the NetVsp of the gpadl handle */ /* Notify the NetVsp of the gpadl handle */
init_packet = &net_device->channel_init_pkt; init_packet = &net_device->channel_init_pkt;
memset(init_packet, 0, sizeof(struct nvsp_message)); memset(init_packet, 0, sizeof(struct nvsp_message));
init_packet->hdr.msg_type = NVSP_MSG1_TYPE_SEND_RECV_BUF; init_packet->hdr.msg_type = NVSP_MSG1_TYPE_SEND_RECV_BUF;
init_packet->msg.v1_msg.send_recv_buf. init_packet->msg.v1_msg.send_recv_buf.
gpadl_handle = net_device->recv_buf_gpadl_handle; gpadl_handle = net_device->recv_buf_gpadl_handle;
...@@ -486,20 +471,15 @@ static int negotiate_nvsp_ver(struct hv_device *device, ...@@ -486,20 +471,15 @@ static int negotiate_nvsp_ver(struct hv_device *device,
return ret; return ret;
} }
static int netvsc_connect_vsp(struct hv_device *device) static int netvsc_connect_vsp(struct hv_device *device,
struct netvsc_device *net_device)
{ {
int ret;
struct netvsc_device *net_device;
struct nvsp_message *init_packet;
int ndis_version;
const u32 ver_list[] = { const u32 ver_list[] = {
NVSP_PROTOCOL_VERSION_1, NVSP_PROTOCOL_VERSION_2, NVSP_PROTOCOL_VERSION_1, NVSP_PROTOCOL_VERSION_2,
NVSP_PROTOCOL_VERSION_4, NVSP_PROTOCOL_VERSION_5 }; NVSP_PROTOCOL_VERSION_4, NVSP_PROTOCOL_VERSION_5
int i; };
struct nvsp_message *init_packet;
net_device = get_outbound_net_device(device); int ndis_version, i, ret;
if (!net_device)
return -ENODEV;
init_packet = &net_device->channel_init_pkt; init_packet = &net_device->channel_init_pkt;
...@@ -549,7 +529,7 @@ static int netvsc_connect_vsp(struct hv_device *device) ...@@ -549,7 +529,7 @@ static int netvsc_connect_vsp(struct hv_device *device)
net_device->recv_buf_size = NETVSC_RECEIVE_BUFFER_SIZE; net_device->recv_buf_size = NETVSC_RECEIVE_BUFFER_SIZE;
net_device->send_buf_size = NETVSC_SEND_BUFFER_SIZE; net_device->send_buf_size = NETVSC_SEND_BUFFER_SIZE;
ret = netvsc_init_buf(device); ret = netvsc_init_buf(device, net_device);
cleanup: cleanup:
return ret; return ret;
...@@ -843,7 +823,7 @@ int netvsc_send(struct hv_device *device, ...@@ -843,7 +823,7 @@ int netvsc_send(struct hv_device *device,
struct hv_page_buffer **pb, struct hv_page_buffer **pb,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct netvsc_device *net_device; struct netvsc_device *net_device = hv_device_to_netvsc_device(device);
int ret = 0; int ret = 0;
struct netvsc_channel *nvchan; struct netvsc_channel *nvchan;
u32 pktlen = packet->total_data_buflen, msd_len = 0; u32 pktlen = packet->total_data_buflen, msd_len = 0;
...@@ -854,15 +834,15 @@ int netvsc_send(struct hv_device *device, ...@@ -854,15 +834,15 @@ int netvsc_send(struct hv_device *device,
bool try_batch; bool try_batch;
bool xmit_more = (skb != NULL) ? skb->xmit_more : false; bool xmit_more = (skb != NULL) ? skb->xmit_more : false;
net_device = get_outbound_net_device(device); /* If device is rescinded, return error and packet will get dropped. */
if (!net_device) if (unlikely(net_device->destroy))
return -ENODEV; return -ENODEV;
/* We may race with netvsc_connect_vsp()/netvsc_init_buf() and get /* We may race with netvsc_connect_vsp()/netvsc_init_buf() and get
* here before the negotiation with the host is finished and * here before the negotiation with the host is finished and
* send_section_map may not be allocated yet. * send_section_map may not be allocated yet.
*/ */
if (!net_device->send_section_map) if (unlikely(!net_device->send_section_map))
return -EAGAIN; return -EAGAIN;
nvchan = &net_device->chan_table[packet->q_idx]; nvchan = &net_device->chan_table[packet->q_idx];
...@@ -1349,7 +1329,7 @@ int netvsc_device_add(struct hv_device *device, ...@@ -1349,7 +1329,7 @@ int netvsc_device_add(struct hv_device *device,
rcu_assign_pointer(net_device_ctx->nvdev, net_device); rcu_assign_pointer(net_device_ctx->nvdev, net_device);
/* Connect with the NetVsp */ /* Connect with the NetVsp */
ret = netvsc_connect_vsp(device); ret = netvsc_connect_vsp(device, net_device);
if (ret != 0) { if (ret != 0) {
netdev_err(ndev, netdev_err(ndev,
"unable to connect to NetVSP - %d\n", ret); "unable to connect to NetVSP - %d\n", ret);
...@@ -1368,4 +1348,5 @@ int netvsc_device_add(struct hv_device *device, ...@@ -1368,4 +1348,5 @@ int netvsc_device_add(struct hv_device *device,
free_netvsc_device(&net_device->rcu); free_netvsc_device(&net_device->rcu);
return ret; return ret;
} }
...@@ -120,7 +120,7 @@ static int netvsc_close(struct net_device *net) ...@@ -120,7 +120,7 @@ static int netvsc_close(struct net_device *net)
struct net_device_context *net_device_ctx = netdev_priv(net); struct net_device_context *net_device_ctx = netdev_priv(net);
struct netvsc_device *nvdev = rtnl_dereference(net_device_ctx->nvdev); struct netvsc_device *nvdev = rtnl_dereference(net_device_ctx->nvdev);
int ret; int ret;
u32 aread, awrite, i, msec = 10, retry = 0, retry_max = 20; u32 aread, i, msec = 10, retry = 0, retry_max = 20;
struct vmbus_channel *chn; struct vmbus_channel *chn;
netif_tx_disable(net); netif_tx_disable(net);
...@@ -141,15 +141,11 @@ static int netvsc_close(struct net_device *net) ...@@ -141,15 +141,11 @@ static int netvsc_close(struct net_device *net)
if (!chn) if (!chn)
continue; continue;
hv_get_ringbuffer_availbytes(&chn->inbound, &aread, aread = hv_get_bytes_to_read(&chn->inbound);
&awrite);
if (aread) if (aread)
break; break;
hv_get_ringbuffer_availbytes(&chn->outbound, &aread, aread = hv_get_bytes_to_read(&chn->outbound);
&awrite);
if (aread) if (aread)
break; break;
} }
...@@ -345,34 +341,14 @@ static u32 init_page_array(void *hdr, u32 len, struct sk_buff *skb, ...@@ -345,34 +341,14 @@ static u32 init_page_array(void *hdr, u32 len, struct sk_buff *skb,
return slots_used; return slots_used;
} }
static int count_skb_frag_slots(struct sk_buff *skb) /* Estimate number of page buffers neede to transmit
{ * Need at most 2 for RNDIS header plus skb body and fragments.
int i, frags = skb_shinfo(skb)->nr_frags; */
int pages = 0; static unsigned int netvsc_get_slots(const struct sk_buff *skb)
for (i = 0; i < frags; i++) {
skb_frag_t *frag = skb_shinfo(skb)->frags + i;
unsigned long size = skb_frag_size(frag);
unsigned long offset = frag->page_offset;
/* Skip unused frames from start of page */
offset &= ~PAGE_MASK;
pages += PFN_UP(offset + size);
}
return pages;
}
static int netvsc_get_slots(struct sk_buff *skb)
{ {
char *data = skb->data; return PFN_UP(offset_in_page(skb->data) + skb_headlen(skb))
unsigned int offset = offset_in_page(data); + skb_shinfo(skb)->nr_frags
unsigned int len = skb_headlen(skb); + 2;
int slots;
int frag_slots;
slots = DIV_ROUND_UP(offset + len, PAGE_SIZE);
frag_slots = count_skb_frag_slots(skb);
return slots + frag_slots;
} }
static u32 net_checksum_info(struct sk_buff *skb) static u32 net_checksum_info(struct sk_buff *skb)
...@@ -410,21 +386,18 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) ...@@ -410,21 +386,18 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
struct hv_page_buffer page_buf[MAX_PAGE_BUFFER_COUNT]; struct hv_page_buffer page_buf[MAX_PAGE_BUFFER_COUNT];
struct hv_page_buffer *pb = page_buf; struct hv_page_buffer *pb = page_buf;
/* We will atmost need two pages to describe the rndis /* We can only transmit MAX_PAGE_BUFFER_COUNT number
* header. We can only transmit MAX_PAGE_BUFFER_COUNT number
* of pages in a single packet. If skb is scattered around * of pages in a single packet. If skb is scattered around
* more pages we try linearizing it. * more pages we try linearizing it.
*/ */
num_data_pgs = netvsc_get_slots(skb);
num_data_pgs = netvsc_get_slots(skb) + 2;
if (unlikely(num_data_pgs > MAX_PAGE_BUFFER_COUNT)) { if (unlikely(num_data_pgs > MAX_PAGE_BUFFER_COUNT)) {
++net_device_ctx->eth_stats.tx_scattered; ++net_device_ctx->eth_stats.tx_scattered;
if (skb_linearize(skb)) if (skb_linearize(skb))
goto no_memory; goto no_memory;
num_data_pgs = netvsc_get_slots(skb) + 2; num_data_pgs = netvsc_get_slots(skb);
if (num_data_pgs > MAX_PAGE_BUFFER_COUNT) { if (num_data_pgs > MAX_PAGE_BUFFER_COUNT) {
++net_device_ctx->eth_stats.tx_too_big; ++net_device_ctx->eth_stats.tx_too_big;
goto drop; goto drop;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment