Commit fdfb70d2 authored by stephen hemminger's avatar stephen hemminger Committed by David S. Miller

netvsc: fix calculation of available send sections

My change (introduced in 4.11) to use find_first_clear_bit
incorrectly assumed that the size argument was words, not bits.
The effect was only a small limited number of the available send
sections were being actually used. This can cause performance loss
with some workloads.

Since map_words is now used only during initialization, it can
be on stack instead of in per-device data.

Fixes: b58a1858 ("netvsc: simplify get next send section")
Signed-off-by: default avatarStephen Hemminger <sthemmin@microsoft.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a23f6ce6
...@@ -751,7 +751,6 @@ struct netvsc_device { ...@@ -751,7 +751,6 @@ struct netvsc_device {
u32 send_section_cnt; u32 send_section_cnt;
u32 send_section_size; u32 send_section_size;
unsigned long *send_section_map; unsigned long *send_section_map;
int map_words;
/* Used for NetVSP initialization protocol */ /* Used for NetVSP initialization protocol */
struct completion channel_init_wait; struct completion channel_init_wait;
......
...@@ -236,6 +236,7 @@ static int netvsc_init_buf(struct hv_device *device) ...@@ -236,6 +236,7 @@ static int netvsc_init_buf(struct hv_device *device)
struct netvsc_device *net_device; 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;
int node; int node;
net_device = get_outbound_net_device(device); net_device = get_outbound_net_device(device);
...@@ -401,11 +402,9 @@ static int netvsc_init_buf(struct hv_device *device) ...@@ -401,11 +402,9 @@ static int netvsc_init_buf(struct hv_device *device)
net_device->send_section_size, net_device->send_section_cnt); net_device->send_section_size, net_device->send_section_cnt);
/* Setup state for managing the send buffer. */ /* Setup state for managing the send buffer. */
net_device->map_words = DIV_ROUND_UP(net_device->send_section_cnt, map_words = DIV_ROUND_UP(net_device->send_section_cnt, BITS_PER_LONG);
BITS_PER_LONG);
net_device->send_section_map = kcalloc(net_device->map_words, net_device->send_section_map = kcalloc(map_words, sizeof(ulong), GFP_KERNEL);
sizeof(ulong), GFP_KERNEL);
if (net_device->send_section_map == NULL) { if (net_device->send_section_map == NULL) {
ret = -ENOMEM; ret = -ENOMEM;
goto cleanup; goto cleanup;
...@@ -683,7 +682,7 @@ static u32 netvsc_get_next_send_section(struct netvsc_device *net_device) ...@@ -683,7 +682,7 @@ static u32 netvsc_get_next_send_section(struct netvsc_device *net_device)
unsigned long *map_addr = net_device->send_section_map; unsigned long *map_addr = net_device->send_section_map;
unsigned int i; unsigned int i;
for_each_clear_bit(i, map_addr, net_device->map_words) { for_each_clear_bit(i, map_addr, net_device->send_section_cnt) {
if (sync_test_and_set_bit(i, map_addr) == 0) if (sync_test_and_set_bit(i, map_addr) == 0)
return i; return i;
} }
......
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