Skip to content

Commit a7f99d0

Browse files
shemmingerdavem330
authored andcommitted
hv_netvsc: use reciprocal divide to speed up percent calculation
Every packet sent checks the available ring space. The calculation can be sped up by using reciprocal divide which is multiplication. Since ring_size can only be configured by module parameter, so it doesn't have to be passed around everywhere. Also it should be unsigned since it is number of pages. Signed-off-by: Stephen Hemminger <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent b85e06f commit a7f99d0

File tree

4 files changed

+21
-26
lines changed

4 files changed

+21
-26
lines changed

drivers/net/hyperv/hyperv_net.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,6 @@ struct hv_netvsc_packet {
146146

147147
struct netvsc_device_info {
148148
unsigned char mac_adr[ETH_ALEN];
149-
int ring_size;
150149
u32 num_chn;
151150
u32 send_sections;
152151
u32 recv_sections;
@@ -188,6 +187,9 @@ struct rndis_message;
188187
struct netvsc_device;
189188
struct net_device_context;
190189

190+
extern u32 netvsc_ring_bytes;
191+
extern struct reciprocal_value netvsc_ring_reciprocal;
192+
191193
struct netvsc_device *netvsc_device_add(struct hv_device *device,
192194
const struct netvsc_device_info *info);
193195
int netvsc_alloc_recv_comp_ring(struct netvsc_device *net_device, u32 q_idx);
@@ -804,8 +806,6 @@ struct netvsc_device {
804806

805807
struct rndis_device *extension;
806808

807-
int ring_size;
808-
809809
u32 max_pkt; /* max number of pkt in one send, e.g. 8 */
810810
u32 pkt_align; /* alignment bytes, e.g. 8 */
811811

drivers/net/hyperv/netvsc.c

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include <linux/vmalloc.h>
3232
#include <linux/rtnetlink.h>
3333
#include <linux/prefetch.h>
34+
#include <linux/reciprocal_div.h>
3435

3536
#include <asm/sync_bitops.h>
3637

@@ -588,14 +589,11 @@ void netvsc_device_remove(struct hv_device *device)
588589
* Get the percentage of available bytes to write in the ring.
589590
* The return value is in range from 0 to 100.
590591
*/
591-
static inline u32 hv_ringbuf_avail_percent(
592-
struct hv_ring_buffer_info *ring_info)
592+
static u32 hv_ringbuf_avail_percent(const struct hv_ring_buffer_info *ring_info)
593593
{
594-
u32 avail_read, avail_write;
594+
u32 avail_write = hv_get_bytes_to_write(ring_info);
595595

596-
hv_get_ringbuffer_availbytes(ring_info, &avail_read, &avail_write);
597-
598-
return avail_write * 100 / ring_info->ring_datasize;
596+
return reciprocal_divide(avail_write * 100, netvsc_ring_reciprocal);
599597
}
600598

601599
static inline void netvsc_free_send_slot(struct netvsc_device *net_device,
@@ -1249,7 +1247,6 @@ struct netvsc_device *netvsc_device_add(struct hv_device *device,
12491247
const struct netvsc_device_info *device_info)
12501248
{
12511249
int i, ret = 0;
1252-
int ring_size = device_info->ring_size;
12531250
struct netvsc_device *net_device;
12541251
struct net_device *ndev = hv_get_drvdata(device);
12551252
struct net_device_context *net_device_ctx = netdev_priv(ndev);
@@ -1261,8 +1258,6 @@ struct netvsc_device *netvsc_device_add(struct hv_device *device,
12611258
for (i = 0; i < VRSS_SEND_TAB_SIZE; i++)
12621259
net_device_ctx->tx_table[i] = 0;
12631260

1264-
net_device->ring_size = ring_size;
1265-
12661261
/* Because the device uses NAPI, all the interrupt batching and
12671262
* control is done via Net softirq, not the channel handling
12681263
*/
@@ -1289,10 +1284,9 @@ struct netvsc_device *netvsc_device_add(struct hv_device *device,
12891284
netvsc_poll, NAPI_POLL_WEIGHT);
12901285

12911286
/* Open the channel */
1292-
ret = vmbus_open(device->channel, ring_size * PAGE_SIZE,
1293-
ring_size * PAGE_SIZE, NULL, 0,
1294-
netvsc_channel_cb,
1295-
net_device->chan_table);
1287+
ret = vmbus_open(device->channel, netvsc_ring_bytes,
1288+
netvsc_ring_bytes, NULL, 0,
1289+
netvsc_channel_cb, net_device->chan_table);
12961290

12971291
if (ret != 0) {
12981292
netif_napi_del(&net_device->chan_table[0].napi);

drivers/net/hyperv/netvsc_drv.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include <linux/slab.h>
3636
#include <linux/rtnetlink.h>
3737
#include <linux/netpoll.h>
38+
#include <linux/reciprocal_div.h>
3839

3940
#include <net/arp.h>
4041
#include <net/route.h>
@@ -54,9 +55,11 @@
5455
#define LINKCHANGE_INT (2 * HZ)
5556
#define VF_TAKEOVER_INT (HZ / 10)
5657

57-
static int ring_size = 128;
58-
module_param(ring_size, int, S_IRUGO);
58+
static unsigned int ring_size __ro_after_init = 128;
59+
module_param(ring_size, uint, S_IRUGO);
5960
MODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)");
61+
unsigned int netvsc_ring_bytes __ro_after_init;
62+
struct reciprocal_value netvsc_ring_reciprocal __ro_after_init;
6063

6164
static const u32 default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE |
6265
NETIF_MSG_LINK | NETIF_MSG_IFUP |
@@ -860,7 +863,6 @@ static int netvsc_set_channels(struct net_device *net,
860863

861864
memset(&device_info, 0, sizeof(device_info));
862865
device_info.num_chn = count;
863-
device_info.ring_size = ring_size;
864866
device_info.send_sections = nvdev->send_section_cnt;
865867
device_info.send_section_size = nvdev->send_section_size;
866868
device_info.recv_sections = nvdev->recv_section_cnt;
@@ -975,7 +977,6 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
975977
rndis_filter_close(nvdev);
976978

977979
memset(&device_info, 0, sizeof(device_info));
978-
device_info.ring_size = ring_size;
979980
device_info.num_chn = nvdev->num_chn;
980981
device_info.send_sections = nvdev->send_section_cnt;
981982
device_info.send_section_size = nvdev->send_section_size;
@@ -1539,7 +1540,6 @@ static int netvsc_set_ringparam(struct net_device *ndev,
15391540

15401541
memset(&device_info, 0, sizeof(device_info));
15411542
device_info.num_chn = nvdev->num_chn;
1542-
device_info.ring_size = ring_size;
15431543
device_info.send_sections = new_tx;
15441544
device_info.send_section_size = nvdev->send_section_size;
15451545
device_info.recv_sections = new_rx;
@@ -1995,7 +1995,6 @@ static int netvsc_probe(struct hv_device *dev,
19951995

19961996
/* Notify the netvsc driver of the new device */
19971997
memset(&device_info, 0, sizeof(device_info));
1998-
device_info.ring_size = ring_size;
19991998
device_info.num_chn = VRSS_CHANNEL_DEFAULT;
20001999
device_info.send_sections = NETVSC_DEFAULT_TX;
20012000
device_info.send_section_size = NETVSC_SEND_SECTION_SIZE;
@@ -2158,11 +2157,13 @@ static int __init netvsc_drv_init(void)
21582157

21592158
if (ring_size < RING_SIZE_MIN) {
21602159
ring_size = RING_SIZE_MIN;
2161-
pr_info("Increased ring_size to %d (min allowed)\n",
2160+
pr_info("Increased ring_size to %u (min allowed)\n",
21622161
ring_size);
21632162
}
2164-
ret = vmbus_driver_register(&netvsc_drv);
2163+
netvsc_ring_bytes = ring_size * PAGE_SIZE;
2164+
netvsc_ring_reciprocal = reciprocal_value(netvsc_ring_bytes);
21652165

2166+
ret = vmbus_driver_register(&netvsc_drv);
21662167
if (ret)
21672168
return ret;
21682169

drivers/net/hyperv/rndis_filter.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,8 +1040,8 @@ static void netvsc_sc_open(struct vmbus_channel *new_sc)
10401040
/* Set the channel before opening.*/
10411041
nvchan->channel = new_sc;
10421042

1043-
ret = vmbus_open(new_sc, nvscdev->ring_size * PAGE_SIZE,
1044-
nvscdev->ring_size * PAGE_SIZE, NULL, 0,
1043+
ret = vmbus_open(new_sc, netvsc_ring_bytes,
1044+
netvsc_ring_bytes, NULL, 0,
10451045
netvsc_channel_cb, nvchan);
10461046
if (ret == 0)
10471047
napi_enable(&nvchan->napi);

0 commit comments

Comments
 (0)