Skip to content

Commit b8278f2

Browse files
committed
Merge branch 'hv_netvsc-minor-optimizations'
Stephen Hemminger says: ==================== hv_netvsc: minor optimizations These are a set of local optimizations the Hyper-V networking driver. Also include a vmbus patch in this set, because it depends on the netvsc that last used that function. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 5e51fe6 + 0487426 commit b8278f2

File tree

6 files changed

+73
-108
lines changed

6 files changed

+73
-108
lines changed

drivers/hv/ring_buffer.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,29 @@ static u32 hv_copyto_ringbuffer(
140140
return start_write_offset;
141141
}
142142

143+
/*
144+
*
145+
* hv_get_ringbuffer_availbytes()
146+
*
147+
* Get number of bytes available to read and to write to
148+
* for the specified ring buffer
149+
*/
150+
static void
151+
hv_get_ringbuffer_availbytes(const struct hv_ring_buffer_info *rbi,
152+
u32 *read, u32 *write)
153+
{
154+
u32 read_loc, write_loc, dsize;
155+
156+
/* Capture the read/write indices before they changed */
157+
read_loc = READ_ONCE(rbi->ring_buffer->read_index);
158+
write_loc = READ_ONCE(rbi->ring_buffer->write_index);
159+
dsize = rbi->ring_datasize;
160+
161+
*write = write_loc >= read_loc ? dsize - (write_loc - read_loc) :
162+
read_loc - write_loc;
163+
*read = dsize - *write;
164+
}
165+
143166
/* Get various debug metrics for the specified ring buffer. */
144167
void hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info,
145168
struct hv_ring_buffer_debug_info *debug_info)

drivers/net/hyperv/hyperv_net.h

Lines changed: 3 additions & 29 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

@@ -1425,32 +1425,6 @@ struct rndis_message {
14251425
(sizeof(msg) + (sizeof(struct rndis_message) - \
14261426
sizeof(union rndis_message_container)))
14271427

1428-
/* get pointer to info buffer with message pointer */
1429-
#define MESSAGE_TO_INFO_BUFFER(msg) \
1430-
(((unsigned char *)(msg)) + msg->info_buf_offset)
1431-
1432-
/* get pointer to status buffer with message pointer */
1433-
#define MESSAGE_TO_STATUS_BUFFER(msg) \
1434-
(((unsigned char *)(msg)) + msg->status_buf_offset)
1435-
1436-
/* get pointer to OOBD buffer with message pointer */
1437-
#define MESSAGE_TO_OOBD_BUFFER(msg) \
1438-
(((unsigned char *)(msg)) + msg->oob_data_offset)
1439-
1440-
/* get pointer to data buffer with message pointer */
1441-
#define MESSAGE_TO_DATA_BUFFER(msg) \
1442-
(((unsigned char *)(msg)) + msg->per_pkt_info_offset)
1443-
1444-
/* get pointer to contained message from NDIS_MESSAGE pointer */
1445-
#define RNDIS_MESSAGE_PTR_TO_MESSAGE_PTR(rndis_msg) \
1446-
((void *) &rndis_msg->msg)
1447-
1448-
/* get pointer to contained message from NDIS_MESSAGE pointer */
1449-
#define RNDIS_MESSAGE_RAW_PTR_TO_MESSAGE_PTR(rndis_msg) \
1450-
((void *) rndis_msg)
1451-
1452-
1453-
14541428
#define RNDIS_HEADER_SIZE (sizeof(struct rndis_message) - \
14551429
sizeof(union rndis_message_container))
14561430

drivers/net/hyperv/netvsc.c

Lines changed: 10 additions & 16 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,
@@ -712,11 +710,12 @@ static u32 netvsc_copy_to_send_buf(struct netvsc_device *net_device,
712710
int i;
713711
u32 msg_size = 0;
714712
u32 padding = 0;
715-
u32 remain = packet->total_data_buflen % net_device->pkt_align;
716713
u32 page_count = packet->cp_partial ? packet->rmsg_pgcnt :
717714
packet->page_buf_cnt;
715+
u32 remain;
718716

719717
/* Add padding */
718+
remain = packet->total_data_buflen & (net_device->pkt_align - 1);
720719
if (skb->xmit_more && remain && !packet->cp_partial) {
721720
padding = net_device->pkt_align - remain;
722721
rndis_msg->msg_len += padding;
@@ -848,7 +847,6 @@ int netvsc_send(struct net_device_context *ndev_ctx,
848847
struct hv_netvsc_packet *msd_send = NULL, *cur_send = NULL;
849848
struct sk_buff *msd_skb = NULL;
850849
bool try_batch;
851-
bool xmit_more = (skb != NULL) ? skb->xmit_more : false;
852850

853851
/* If device is rescinded, return error and packet will get dropped. */
854852
if (unlikely(!net_device || net_device->destroy))
@@ -922,7 +920,7 @@ int netvsc_send(struct net_device_context *ndev_ctx,
922920
if (msdp->skb)
923921
dev_consume_skb_any(msdp->skb);
924922

925-
if (xmit_more && !packet->cp_partial) {
923+
if (skb->xmit_more && !packet->cp_partial) {
926924
msdp->skb = skb;
927925
msdp->pkt = packet;
928926
msdp->count++;
@@ -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: 35 additions & 39 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 |
@@ -174,25 +177,23 @@ static int netvsc_close(struct net_device *net)
174177
return ret;
175178
}
176179

177-
static void *init_ppi_data(struct rndis_message *msg, u32 ppi_size,
178-
int pkt_type)
180+
static inline void *init_ppi_data(struct rndis_message *msg,
181+
u32 ppi_size, u32 pkt_type)
179182
{
180-
struct rndis_packet *rndis_pkt;
183+
struct rndis_packet *rndis_pkt = &msg->msg.pkt;
181184
struct rndis_per_packet_info *ppi;
182185

183-
rndis_pkt = &msg->msg.pkt;
184186
rndis_pkt->data_offset += ppi_size;
185-
186-
ppi = (struct rndis_per_packet_info *)((void *)rndis_pkt +
187-
rndis_pkt->per_pkt_info_offset + rndis_pkt->per_pkt_info_len);
187+
ppi = (void *)rndis_pkt + rndis_pkt->per_pkt_info_offset
188+
+ rndis_pkt->per_pkt_info_len;
188189

189190
ppi->size = ppi_size;
190191
ppi->type = pkt_type;
191192
ppi->ppi_offset = sizeof(struct rndis_per_packet_info);
192193

193194
rndis_pkt->per_pkt_info_len += ppi_size;
194195

195-
return ppi;
196+
return ppi + 1;
196197
}
197198

198199
/* Azure hosts don't support non-TCP port numbers in hashing for fragmented
@@ -469,10 +470,8 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
469470
int ret;
470471
unsigned int num_data_pgs;
471472
struct rndis_message *rndis_msg;
472-
struct rndis_packet *rndis_pkt;
473473
struct net_device *vf_netdev;
474474
u32 rndis_msg_size;
475-
struct rndis_per_packet_info *ppi;
476475
u32 hash;
477476
struct hv_page_buffer pb[MAX_PAGE_BUFFER_COUNT];
478477

@@ -527,34 +526,36 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
527526

528527
rndis_msg = (struct rndis_message *)skb->head;
529528

530-
memset(rndis_msg, 0, RNDIS_AND_PPI_SIZE);
531-
532529
/* Add the rndis header */
533530
rndis_msg->ndis_msg_type = RNDIS_MSG_PACKET;
534531
rndis_msg->msg_len = packet->total_data_buflen;
535-
rndis_pkt = &rndis_msg->msg.pkt;
536-
rndis_pkt->data_offset = sizeof(struct rndis_packet);
537-
rndis_pkt->data_len = packet->total_data_buflen;
538-
rndis_pkt->per_pkt_info_offset = sizeof(struct rndis_packet);
532+
533+
rndis_msg->msg.pkt = (struct rndis_packet) {
534+
.data_offset = sizeof(struct rndis_packet),
535+
.data_len = packet->total_data_buflen,
536+
.per_pkt_info_offset = sizeof(struct rndis_packet),
537+
};
539538

540539
rndis_msg_size = RNDIS_MESSAGE_SIZE(struct rndis_packet);
541540

542541
hash = skb_get_hash_raw(skb);
543542
if (hash != 0 && net->real_num_tx_queues > 1) {
543+
u32 *hash_info;
544+
544545
rndis_msg_size += NDIS_HASH_PPI_SIZE;
545-
ppi = init_ppi_data(rndis_msg, NDIS_HASH_PPI_SIZE,
546-
NBL_HASH_VALUE);
547-
*(u32 *)((void *)ppi + ppi->ppi_offset) = hash;
546+
hash_info = init_ppi_data(rndis_msg, NDIS_HASH_PPI_SIZE,
547+
NBL_HASH_VALUE);
548+
*hash_info = hash;
548549
}
549550

550551
if (skb_vlan_tag_present(skb)) {
551552
struct ndis_pkt_8021q_info *vlan;
552553

553554
rndis_msg_size += NDIS_VLAN_PPI_SIZE;
554-
ppi = init_ppi_data(rndis_msg, NDIS_VLAN_PPI_SIZE,
555-
IEEE_8021Q_INFO);
555+
vlan = init_ppi_data(rndis_msg, NDIS_VLAN_PPI_SIZE,
556+
IEEE_8021Q_INFO);
556557

557-
vlan = (void *)ppi + ppi->ppi_offset;
558+
vlan->value = 0;
558559
vlan->vlanid = skb->vlan_tci & VLAN_VID_MASK;
559560
vlan->pri = (skb->vlan_tci & VLAN_PRIO_MASK) >>
560561
VLAN_PRIO_SHIFT;
@@ -564,11 +565,10 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
564565
struct ndis_tcp_lso_info *lso_info;
565566

566567
rndis_msg_size += NDIS_LSO_PPI_SIZE;
567-
ppi = init_ppi_data(rndis_msg, NDIS_LSO_PPI_SIZE,
568-
TCP_LARGESEND_PKTINFO);
569-
570-
lso_info = (void *)ppi + ppi->ppi_offset;
568+
lso_info = init_ppi_data(rndis_msg, NDIS_LSO_PPI_SIZE,
569+
TCP_LARGESEND_PKTINFO);
571570

571+
lso_info->value = 0;
572572
lso_info->lso_v2_transmit.type = NDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE;
573573
if (skb->protocol == htons(ETH_P_IP)) {
574574
lso_info->lso_v2_transmit.ip_version =
@@ -593,12 +593,10 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
593593
struct ndis_tcp_ip_checksum_info *csum_info;
594594

595595
rndis_msg_size += NDIS_CSUM_PPI_SIZE;
596-
ppi = init_ppi_data(rndis_msg, NDIS_CSUM_PPI_SIZE,
597-
TCPIP_CHKSUM_PKTINFO);
598-
599-
csum_info = (struct ndis_tcp_ip_checksum_info *)((void *)ppi +
600-
ppi->ppi_offset);
596+
csum_info = init_ppi_data(rndis_msg, NDIS_CSUM_PPI_SIZE,
597+
TCPIP_CHKSUM_PKTINFO);
601598

599+
csum_info->value = 0;
602600
csum_info->transmit.tcp_header_offset = skb_transport_offset(skb);
603601

604602
if (skb->protocol == htons(ETH_P_IP)) {
@@ -860,7 +858,6 @@ static int netvsc_set_channels(struct net_device *net,
860858

861859
memset(&device_info, 0, sizeof(device_info));
862860
device_info.num_chn = count;
863-
device_info.ring_size = ring_size;
864861
device_info.send_sections = nvdev->send_section_cnt;
865862
device_info.send_section_size = nvdev->send_section_size;
866863
device_info.recv_sections = nvdev->recv_section_cnt;
@@ -975,7 +972,6 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
975972
rndis_filter_close(nvdev);
976973

977974
memset(&device_info, 0, sizeof(device_info));
978-
device_info.ring_size = ring_size;
979975
device_info.num_chn = nvdev->num_chn;
980976
device_info.send_sections = nvdev->send_section_cnt;
981977
device_info.send_section_size = nvdev->send_section_size;
@@ -1539,7 +1535,6 @@ static int netvsc_set_ringparam(struct net_device *ndev,
15391535

15401536
memset(&device_info, 0, sizeof(device_info));
15411537
device_info.num_chn = nvdev->num_chn;
1542-
device_info.ring_size = ring_size;
15431538
device_info.send_sections = new_tx;
15441539
device_info.send_section_size = nvdev->send_section_size;
15451540
device_info.recv_sections = new_rx;
@@ -1995,7 +1990,6 @@ static int netvsc_probe(struct hv_device *dev,
19951990

19961991
/* Notify the netvsc driver of the new device */
19971992
memset(&device_info, 0, sizeof(device_info));
1998-
device_info.ring_size = ring_size;
19991993
device_info.num_chn = VRSS_CHANNEL_DEFAULT;
20001994
device_info.send_sections = NETVSC_DEFAULT_TX;
20011995
device_info.send_section_size = NETVSC_SEND_SECTION_SIZE;
@@ -2158,11 +2152,13 @@ static int __init netvsc_drv_init(void)
21582152

21592153
if (ring_size < RING_SIZE_MIN) {
21602154
ring_size = RING_SIZE_MIN;
2161-
pr_info("Increased ring_size to %d (min allowed)\n",
2155+
pr_info("Increased ring_size to %u (min allowed)\n",
21622156
ring_size);
21632157
}
2164-
ret = vmbus_driver_register(&netvsc_drv);
2158+
netvsc_ring_bytes = ring_size * PAGE_SIZE;
2159+
netvsc_ring_reciprocal = reciprocal_value(netvsc_ring_bytes);
21652160

2161+
ret = vmbus_driver_register(&netvsc_drv);
21662162
if (ret)
21672163
return ret;
21682164

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)