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: b58a185801
("netvsc: simplify get next send section")
Signed-off-by: Stephen Hemminger <sthemmin@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
a23f6ce6d9
commit
fdfb70d275
|
@ -751,7 +751,6 @@ struct netvsc_device {
|
|||
u32 send_section_cnt;
|
||||
u32 send_section_size;
|
||||
unsigned long *send_section_map;
|
||||
int map_words;
|
||||
|
||||
/* Used for NetVSP initialization protocol */
|
||||
struct completion channel_init_wait;
|
||||
|
|
|
@ -236,6 +236,7 @@ static int netvsc_init_buf(struct hv_device *device)
|
|||
struct netvsc_device *net_device;
|
||||
struct nvsp_message *init_packet;
|
||||
struct net_device *ndev;
|
||||
size_t map_words;
|
||||
int node;
|
||||
|
||||
net_device = get_outbound_net_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);
|
||||
|
||||
/* Setup state for managing the send buffer. */
|
||||
net_device->map_words = DIV_ROUND_UP(net_device->send_section_cnt,
|
||||
BITS_PER_LONG);
|
||||
map_words = DIV_ROUND_UP(net_device->send_section_cnt, BITS_PER_LONG);
|
||||
|
||||
net_device->send_section_map = kcalloc(net_device->map_words,
|
||||
sizeof(ulong), GFP_KERNEL);
|
||||
net_device->send_section_map = kcalloc(map_words, sizeof(ulong), GFP_KERNEL);
|
||||
if (net_device->send_section_map == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto cleanup;
|
||||
|
@ -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 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)
|
||||
return i;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue