struct netvsc_device_info {
unsigned char mac_adr[ETH_ALEN];
- int ring_size;
u32 num_chn;
u32 send_sections;
u32 recv_sections;
struct netvsc_device;
struct net_device_context;
+extern u32 netvsc_ring_bytes;
+extern struct reciprocal_value netvsc_ring_reciprocal;
+
struct netvsc_device *netvsc_device_add(struct hv_device *device,
const struct netvsc_device_info *info);
int netvsc_alloc_recv_comp_ring(struct netvsc_device *net_device, u32 q_idx);
struct rndis_device *extension;
- int ring_size;
-
u32 max_pkt; /* max number of pkt in one send, e.g. 8 */
u32 pkt_align; /* alignment bytes, e.g. 8 */
#include <linux/vmalloc.h>
#include <linux/rtnetlink.h>
#include <linux/prefetch.h>
+#include <linux/reciprocal_div.h>
#include <asm/sync_bitops.h>
* Get the percentage of available bytes to write in the ring.
* The return value is in range from 0 to 100.
*/
-static inline u32 hv_ringbuf_avail_percent(
- struct hv_ring_buffer_info *ring_info)
+static u32 hv_ringbuf_avail_percent(const struct hv_ring_buffer_info *ring_info)
{
- u32 avail_read, avail_write;
+ u32 avail_write = hv_get_bytes_to_write(ring_info);
- hv_get_ringbuffer_availbytes(ring_info, &avail_read, &avail_write);
-
- return avail_write * 100 / ring_info->ring_datasize;
+ return reciprocal_divide(avail_write * 100, netvsc_ring_reciprocal);
}
static inline void netvsc_free_send_slot(struct netvsc_device *net_device,
const struct netvsc_device_info *device_info)
{
int i, ret = 0;
- int ring_size = device_info->ring_size;
struct netvsc_device *net_device;
struct net_device *ndev = hv_get_drvdata(device);
struct net_device_context *net_device_ctx = netdev_priv(ndev);
for (i = 0; i < VRSS_SEND_TAB_SIZE; i++)
net_device_ctx->tx_table[i] = 0;
- net_device->ring_size = ring_size;
-
/* Because the device uses NAPI, all the interrupt batching and
* control is done via Net softirq, not the channel handling
*/
netvsc_poll, NAPI_POLL_WEIGHT);
/* Open the channel */
- ret = vmbus_open(device->channel, ring_size * PAGE_SIZE,
- ring_size * PAGE_SIZE, NULL, 0,
- netvsc_channel_cb,
- net_device->chan_table);
+ ret = vmbus_open(device->channel, netvsc_ring_bytes,
+ netvsc_ring_bytes, NULL, 0,
+ netvsc_channel_cb, net_device->chan_table);
if (ret != 0) {
netif_napi_del(&net_device->chan_table[0].napi);
#include <linux/slab.h>
#include <linux/rtnetlink.h>
#include <linux/netpoll.h>
+#include <linux/reciprocal_div.h>
#include <net/arp.h>
#include <net/route.h>
#define LINKCHANGE_INT (2 * HZ)
#define VF_TAKEOVER_INT (HZ / 10)
-static int ring_size = 128;
-module_param(ring_size, int, S_IRUGO);
+static unsigned int ring_size __ro_after_init = 128;
+module_param(ring_size, uint, S_IRUGO);
MODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)");
+unsigned int netvsc_ring_bytes __ro_after_init;
+struct reciprocal_value netvsc_ring_reciprocal __ro_after_init;
static const u32 default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE |
NETIF_MSG_LINK | NETIF_MSG_IFUP |
memset(&device_info, 0, sizeof(device_info));
device_info.num_chn = count;
- device_info.ring_size = ring_size;
device_info.send_sections = nvdev->send_section_cnt;
device_info.send_section_size = nvdev->send_section_size;
device_info.recv_sections = nvdev->recv_section_cnt;
rndis_filter_close(nvdev);
memset(&device_info, 0, sizeof(device_info));
- device_info.ring_size = ring_size;
device_info.num_chn = nvdev->num_chn;
device_info.send_sections = nvdev->send_section_cnt;
device_info.send_section_size = nvdev->send_section_size;
memset(&device_info, 0, sizeof(device_info));
device_info.num_chn = nvdev->num_chn;
- device_info.ring_size = ring_size;
device_info.send_sections = new_tx;
device_info.send_section_size = nvdev->send_section_size;
device_info.recv_sections = new_rx;
/* Notify the netvsc driver of the new device */
memset(&device_info, 0, sizeof(device_info));
- device_info.ring_size = ring_size;
device_info.num_chn = VRSS_CHANNEL_DEFAULT;
device_info.send_sections = NETVSC_DEFAULT_TX;
device_info.send_section_size = NETVSC_SEND_SECTION_SIZE;
if (ring_size < RING_SIZE_MIN) {
ring_size = RING_SIZE_MIN;
- pr_info("Increased ring_size to %d (min allowed)\n",
+ pr_info("Increased ring_size to %u (min allowed)\n",
ring_size);
}
- ret = vmbus_driver_register(&netvsc_drv);
+ netvsc_ring_bytes = ring_size * PAGE_SIZE;
+ netvsc_ring_reciprocal = reciprocal_value(netvsc_ring_bytes);
+ ret = vmbus_driver_register(&netvsc_drv);
if (ret)
return ret;
/* Set the channel before opening.*/
nvchan->channel = new_sc;
- ret = vmbus_open(new_sc, nvscdev->ring_size * PAGE_SIZE,
- nvscdev->ring_size * PAGE_SIZE, NULL, 0,
+ ret = vmbus_open(new_sc, netvsc_ring_bytes,
+ netvsc_ring_bytes, NULL, 0,
netvsc_channel_cb, nvchan);
if (ret == 0)
napi_enable(&nvchan->napi);