aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Hemminger <stephen@networkplumber.org>2017-12-01 14:01:47 -0500
committerDavid S. Miller <davem@davemloft.net>2017-12-03 10:10:02 -0500
commita7f99d0f2bbfe3b42ce398cdd37a97762e72cb56 (patch)
treeae1c99cb331fc717f3333cb3c4ce3b9fb57441a9
parentb85e06f7bb1a25dd2e7755d55a2ca313d24ae7ad (diff)
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 <sthemmin@microsoft.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/hyperv/hyperv_net.h6
-rw-r--r--drivers/net/hyperv/netvsc.c20
-rw-r--r--drivers/net/hyperv/netvsc_drv.c17
-rw-r--r--drivers/net/hyperv/rndis_filter.c4
4 files changed, 21 insertions, 26 deletions
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index 7226230561de..3d940c67ea94 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -146,7 +146,6 @@ struct hv_netvsc_packet {
146 146
147struct netvsc_device_info { 147struct netvsc_device_info {
148 unsigned char mac_adr[ETH_ALEN]; 148 unsigned char mac_adr[ETH_ALEN];
149 int ring_size;
150 u32 num_chn; 149 u32 num_chn;
151 u32 send_sections; 150 u32 send_sections;
152 u32 recv_sections; 151 u32 recv_sections;
@@ -188,6 +187,9 @@ struct rndis_message;
188struct netvsc_device; 187struct netvsc_device;
189struct net_device_context; 188struct net_device_context;
190 189
190extern u32 netvsc_ring_bytes;
191extern struct reciprocal_value netvsc_ring_reciprocal;
192
191struct netvsc_device *netvsc_device_add(struct hv_device *device, 193struct netvsc_device *netvsc_device_add(struct hv_device *device,
192 const struct netvsc_device_info *info); 194 const struct netvsc_device_info *info);
193int netvsc_alloc_recv_comp_ring(struct netvsc_device *net_device, u32 q_idx); 195int netvsc_alloc_recv_comp_ring(struct netvsc_device *net_device, u32 q_idx);
@@ -804,8 +806,6 @@ struct netvsc_device {
804 806
805 struct rndis_device *extension; 807 struct rndis_device *extension;
806 808
807 int ring_size;
808
809 u32 max_pkt; /* max number of pkt in one send, e.g. 8 */ 809 u32 max_pkt; /* max number of pkt in one send, e.g. 8 */
810 u32 pkt_align; /* alignment bytes, e.g. 8 */ 810 u32 pkt_align; /* alignment bytes, e.g. 8 */
811 811
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index 4b931f017a25..e4bcd202a56a 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -31,6 +31,7 @@
31#include <linux/vmalloc.h> 31#include <linux/vmalloc.h>
32#include <linux/rtnetlink.h> 32#include <linux/rtnetlink.h>
33#include <linux/prefetch.h> 33#include <linux/prefetch.h>
34#include <linux/reciprocal_div.h>
34 35
35#include <asm/sync_bitops.h> 36#include <asm/sync_bitops.h>
36 37
@@ -588,14 +589,11 @@ void netvsc_device_remove(struct hv_device *device)
588 * Get the percentage of available bytes to write in the ring. 589 * Get the percentage of available bytes to write in the ring.
589 * The return value is in range from 0 to 100. 590 * The return value is in range from 0 to 100.
590 */ 591 */
591static inline u32 hv_ringbuf_avail_percent( 592static u32 hv_ringbuf_avail_percent(const struct hv_ring_buffer_info *ring_info)
592 struct hv_ring_buffer_info *ring_info)
593{ 593{
594 u32 avail_read, avail_write; 594 u32 avail_write = hv_get_bytes_to_write(ring_info);
595 595
596 hv_get_ringbuffer_availbytes(ring_info, &avail_read, &avail_write); 596 return reciprocal_divide(avail_write * 100, netvsc_ring_reciprocal);
597
598 return avail_write * 100 / ring_info->ring_datasize;
599} 597}
600 598
601static inline void netvsc_free_send_slot(struct netvsc_device *net_device, 599static 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,
1249 const struct netvsc_device_info *device_info) 1247 const struct netvsc_device_info *device_info)
1250{ 1248{
1251 int i, ret = 0; 1249 int i, ret = 0;
1252 int ring_size = device_info->ring_size;
1253 struct netvsc_device *net_device; 1250 struct netvsc_device *net_device;
1254 struct net_device *ndev = hv_get_drvdata(device); 1251 struct net_device *ndev = hv_get_drvdata(device);
1255 struct net_device_context *net_device_ctx = netdev_priv(ndev); 1252 struct net_device_context *net_device_ctx = netdev_priv(ndev);
@@ -1261,8 +1258,6 @@ struct netvsc_device *netvsc_device_add(struct hv_device *device,
1261 for (i = 0; i < VRSS_SEND_TAB_SIZE; i++) 1258 for (i = 0; i < VRSS_SEND_TAB_SIZE; i++)
1262 net_device_ctx->tx_table[i] = 0; 1259 net_device_ctx->tx_table[i] = 0;
1263 1260
1264 net_device->ring_size = ring_size;
1265
1266 /* Because the device uses NAPI, all the interrupt batching and 1261 /* Because the device uses NAPI, all the interrupt batching and
1267 * control is done via Net softirq, not the channel handling 1262 * control is done via Net softirq, not the channel handling
1268 */ 1263 */
@@ -1289,10 +1284,9 @@ struct netvsc_device *netvsc_device_add(struct hv_device *device,
1289 netvsc_poll, NAPI_POLL_WEIGHT); 1284 netvsc_poll, NAPI_POLL_WEIGHT);
1290 1285
1291 /* Open the channel */ 1286 /* Open the channel */
1292 ret = vmbus_open(device->channel, ring_size * PAGE_SIZE, 1287 ret = vmbus_open(device->channel, netvsc_ring_bytes,
1293 ring_size * PAGE_SIZE, NULL, 0, 1288 netvsc_ring_bytes, NULL, 0,
1294 netvsc_channel_cb, 1289 netvsc_channel_cb, net_device->chan_table);
1295 net_device->chan_table);
1296 1290
1297 if (ret != 0) { 1291 if (ret != 0) {
1298 netif_napi_del(&net_device->chan_table[0].napi); 1292 netif_napi_del(&net_device->chan_table[0].napi);
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 5129647d420c..ba690e1737ab 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -35,6 +35,7 @@
35#include <linux/slab.h> 35#include <linux/slab.h>
36#include <linux/rtnetlink.h> 36#include <linux/rtnetlink.h>
37#include <linux/netpoll.h> 37#include <linux/netpoll.h>
38#include <linux/reciprocal_div.h>
38 39
39#include <net/arp.h> 40#include <net/arp.h>
40#include <net/route.h> 41#include <net/route.h>
@@ -54,9 +55,11 @@
54#define LINKCHANGE_INT (2 * HZ) 55#define LINKCHANGE_INT (2 * HZ)
55#define VF_TAKEOVER_INT (HZ / 10) 56#define VF_TAKEOVER_INT (HZ / 10)
56 57
57static int ring_size = 128; 58static unsigned int ring_size __ro_after_init = 128;
58module_param(ring_size, int, S_IRUGO); 59module_param(ring_size, uint, S_IRUGO);
59MODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)"); 60MODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)");
61unsigned int netvsc_ring_bytes __ro_after_init;
62struct reciprocal_value netvsc_ring_reciprocal __ro_after_init;
60 63
61static const u32 default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE | 64static const u32 default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE |
62 NETIF_MSG_LINK | NETIF_MSG_IFUP | 65 NETIF_MSG_LINK | NETIF_MSG_IFUP |
@@ -860,7 +863,6 @@ static int netvsc_set_channels(struct net_device *net,
860 863
861 memset(&device_info, 0, sizeof(device_info)); 864 memset(&device_info, 0, sizeof(device_info));
862 device_info.num_chn = count; 865 device_info.num_chn = count;
863 device_info.ring_size = ring_size;
864 device_info.send_sections = nvdev->send_section_cnt; 866 device_info.send_sections = nvdev->send_section_cnt;
865 device_info.send_section_size = nvdev->send_section_size; 867 device_info.send_section_size = nvdev->send_section_size;
866 device_info.recv_sections = nvdev->recv_section_cnt; 868 device_info.recv_sections = nvdev->recv_section_cnt;
@@ -975,7 +977,6 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
975 rndis_filter_close(nvdev); 977 rndis_filter_close(nvdev);
976 978
977 memset(&device_info, 0, sizeof(device_info)); 979 memset(&device_info, 0, sizeof(device_info));
978 device_info.ring_size = ring_size;
979 device_info.num_chn = nvdev->num_chn; 980 device_info.num_chn = nvdev->num_chn;
980 device_info.send_sections = nvdev->send_section_cnt; 981 device_info.send_sections = nvdev->send_section_cnt;
981 device_info.send_section_size = nvdev->send_section_size; 982 device_info.send_section_size = nvdev->send_section_size;
@@ -1539,7 +1540,6 @@ static int netvsc_set_ringparam(struct net_device *ndev,
1539 1540
1540 memset(&device_info, 0, sizeof(device_info)); 1541 memset(&device_info, 0, sizeof(device_info));
1541 device_info.num_chn = nvdev->num_chn; 1542 device_info.num_chn = nvdev->num_chn;
1542 device_info.ring_size = ring_size;
1543 device_info.send_sections = new_tx; 1543 device_info.send_sections = new_tx;
1544 device_info.send_section_size = nvdev->send_section_size; 1544 device_info.send_section_size = nvdev->send_section_size;
1545 device_info.recv_sections = new_rx; 1545 device_info.recv_sections = new_rx;
@@ -1995,7 +1995,6 @@ static int netvsc_probe(struct hv_device *dev,
1995 1995
1996 /* Notify the netvsc driver of the new device */ 1996 /* Notify the netvsc driver of the new device */
1997 memset(&device_info, 0, sizeof(device_info)); 1997 memset(&device_info, 0, sizeof(device_info));
1998 device_info.ring_size = ring_size;
1999 device_info.num_chn = VRSS_CHANNEL_DEFAULT; 1998 device_info.num_chn = VRSS_CHANNEL_DEFAULT;
2000 device_info.send_sections = NETVSC_DEFAULT_TX; 1999 device_info.send_sections = NETVSC_DEFAULT_TX;
2001 device_info.send_section_size = NETVSC_SEND_SECTION_SIZE; 2000 device_info.send_section_size = NETVSC_SEND_SECTION_SIZE;
@@ -2158,11 +2157,13 @@ static int __init netvsc_drv_init(void)
2158 2157
2159 if (ring_size < RING_SIZE_MIN) { 2158 if (ring_size < RING_SIZE_MIN) {
2160 ring_size = RING_SIZE_MIN; 2159 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",
2162 ring_size); 2161 ring_size);
2163 } 2162 }
2164 ret = vmbus_driver_register(&netvsc_drv); 2163 netvsc_ring_bytes = ring_size * PAGE_SIZE;
2164 netvsc_ring_reciprocal = reciprocal_value(netvsc_ring_bytes);
2165 2165
2166 ret = vmbus_driver_register(&netvsc_drv);
2166 if (ret) 2167 if (ret)
2167 return ret; 2168 return ret;
2168 2169
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index 7b637c7dd1e5..673492063307 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -1040,8 +1040,8 @@ static void netvsc_sc_open(struct vmbus_channel *new_sc)
1040 /* Set the channel before opening.*/ 1040 /* Set the channel before opening.*/
1041 nvchan->channel = new_sc; 1041 nvchan->channel = new_sc;
1042 1042
1043 ret = vmbus_open(new_sc, nvscdev->ring_size * PAGE_SIZE, 1043 ret = vmbus_open(new_sc, netvsc_ring_bytes,
1044 nvscdev->ring_size * PAGE_SIZE, NULL, 0, 1044 netvsc_ring_bytes, NULL, 0,
1045 netvsc_channel_cb, nvchan); 1045 netvsc_channel_cb, nvchan);
1046 if (ret == 0) 1046 if (ret == 0)
1047 napi_enable(&nvchan->napi); 1047 napi_enable(&nvchan->napi);