From 22e9dd249bd4bcf338c282d90df08ccf5dbfbee2 Mon Sep 17 00:00:00 2001 From: KY Srinivasan Date: Tue, 1 Dec 2015 16:43:03 -0800 Subject: [PATCH 01/17] hv_netvsc: Resize some of the variables in hv_netvsc_packet As part of reducing the size of the hv_netvsc_packet, resize some of the variables based on their usage. Signed-off-by: K. Y. Srinivasan Reviewed-by: Haiyang Zhang Signed-off-by: David S. Miller --- drivers/net/hyperv/hyperv_net.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index 7661a12b00f4b..5f0a21fe0fb47 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h @@ -127,11 +127,11 @@ struct ndis_tcp_ip_checksum_info; */ struct hv_netvsc_packet { /* Bookkeeping stuff */ - u32 status; + u8 status; - bool is_data_pkt; - bool xmit_more; /* from skb */ - bool cp_partial; /* partial copy into send buffer */ + u8 is_data_pkt; + u8 xmit_more; /* from skb */ + u8 cp_partial; /* partial copy into send buffer */ u16 vlan_tci; @@ -147,13 +147,13 @@ struct hv_netvsc_packet { /* This points to the memory after page_buf */ struct rndis_message *rndis_msg; - u32 rmsg_size; /* RNDIS header and PPI size */ - u32 rmsg_pgcnt; /* page count of RNDIS header and PPI */ + u8 rmsg_size; /* RNDIS header and PPI size */ + u8 rmsg_pgcnt; /* page count of RNDIS header and PPI */ u32 total_data_buflen; /* Points to the send/receive buffer where the ethernet frame is */ void *data; - u32 page_buf_cnt; + u8 page_buf_cnt; struct hv_page_buffer *page_buf; }; From 934d202255ecd03d1f48b1031a2e03cb647e73d9 Mon Sep 17 00:00:00 2001 From: KY Srinivasan Date: Tue, 1 Dec 2015 16:43:04 -0800 Subject: [PATCH 02/17] hv_netvsc: Rearrange the hv_negtvsc_packet to be space efficient Rearrange the elements of struct hv_negtvsc_packet for optimal layout - eliminate unnecessary padding. Signed-off-by: K. Y. Srinivasan Reviewed-by: Haiyang Zhang Signed-off-by: David S. Miller --- drivers/net/hyperv/hyperv_net.h | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index 5f0a21fe0fb47..3f66a23dd94f0 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h @@ -128,32 +128,34 @@ struct ndis_tcp_ip_checksum_info; struct hv_netvsc_packet { /* Bookkeeping stuff */ u8 status; - u8 is_data_pkt; u8 xmit_more; /* from skb */ u8 cp_partial; /* partial copy into send buffer */ - u16 vlan_tci; + u8 rmsg_size; /* RNDIS header and PPI size */ + u8 rmsg_pgcnt; /* page count of RNDIS header and PPI */ + u8 page_buf_cnt; + u8 pad0; + u16 vlan_tci; u16 q_idx; + u32 send_buf_index; + + u32 total_data_buflen; + u32 pad1; + struct vmbus_channel *channel; u64 send_completion_tid; void *send_completion_ctx; void (*send_completion)(void *context); - u32 send_buf_index; /* This points to the memory after page_buf */ struct rndis_message *rndis_msg; - u8 rmsg_size; /* RNDIS header and PPI size */ - u8 rmsg_pgcnt; /* page count of RNDIS header and PPI */ - - u32 total_data_buflen; /* Points to the send/receive buffer where the ethernet frame is */ void *data; - u8 page_buf_cnt; struct hv_page_buffer *page_buf; }; From 25b85ee890530f70de850f15660ed41abbee1172 Mon Sep 17 00:00:00 2001 From: KY Srinivasan Date: Tue, 1 Dec 2015 16:43:05 -0800 Subject: [PATCH 03/17] hv_netvsc: Eliminate the channel field in hv_netvsc_packet structure Eliminate the channel field in hv_netvsc_packet structure. Signed-off-by: K. Y. Srinivasan Reviewed-by: Haiyang Zhang Signed-off-by: David S. Miller --- drivers/net/hyperv/hyperv_net.h | 22 ++++++++++++++++++---- drivers/net/hyperv/netvsc.c | 19 ++++++++----------- drivers/net/hyperv/netvsc_drv.c | 5 +++-- drivers/net/hyperv/rndis_filter.c | 10 ++++++---- 4 files changed, 35 insertions(+), 21 deletions(-) diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index 3f66a23dd94f0..6bb1acd2a81c5 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h @@ -144,7 +144,6 @@ struct hv_netvsc_packet { u32 total_data_buflen; u32 pad1; - struct vmbus_channel *channel; u64 send_completion_tid; void *send_completion_ctx; @@ -198,7 +197,8 @@ void netvsc_linkstatus_callback(struct hv_device *device_obj, void netvsc_xmit_completion(void *context); int netvsc_recv_callback(struct hv_device *device_obj, struct hv_netvsc_packet *packet, - struct ndis_tcp_ip_checksum_info *csum_info); + struct ndis_tcp_ip_checksum_info *csum_info, + struct vmbus_channel *channel); void netvsc_channel_cb(void *context); int rndis_filter_open(struct hv_device *dev); int rndis_filter_close(struct hv_device *dev); @@ -206,12 +206,12 @@ int rndis_filter_device_add(struct hv_device *dev, void *additional_info); void rndis_filter_device_remove(struct hv_device *dev); int rndis_filter_receive(struct hv_device *dev, - struct hv_netvsc_packet *pkt); + struct hv_netvsc_packet *pkt, + struct vmbus_channel *channel); int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter); int rndis_filter_set_device_mac(struct hv_device *hdev, char *mac); - #define NVSP_INVALID_PROTOCOL_VERSION ((u32)0xFFFFFFFF) #define NVSP_PROTOCOL_VERSION_1 2 @@ -1274,5 +1274,19 @@ struct rndis_message { #define TRANSPORT_INFO_IPV6_TCP ((INFO_IPV6 << 16) | INFO_TCP) #define TRANSPORT_INFO_IPV6_UDP ((INFO_IPV6 << 16) | INFO_UDP) +static inline struct vmbus_channel *get_channel(struct hv_netvsc_packet *packet, + struct netvsc_device *net_device) + +{ + struct vmbus_channel *out_channel; + + out_channel = net_device->chn_table[packet->q_idx]; + if (!out_channel) { + out_channel = net_device->dev->channel; + packet->q_idx = 0; + } + return out_channel; +} + #endif /* _HYPERV_NET_H */ diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c index 51e4c0fd0a748..52533edbd2b04 100644 --- a/drivers/net/hyperv/netvsc.c +++ b/drivers/net/hyperv/netvsc.c @@ -610,6 +610,7 @@ static inline void netvsc_free_send_slot(struct netvsc_device *net_device, } static void netvsc_send_completion(struct netvsc_device *net_device, + struct vmbus_channel *incoming_channel, struct hv_device *device, struct vmpacket_descriptor *packet) { @@ -651,7 +652,7 @@ static void netvsc_send_completion(struct netvsc_device *net_device, if (send_index != NETVSC_INVALID_INDEX) netvsc_free_send_slot(net_device, send_index); q_idx = nvsc_packet->q_idx; - channel = nvsc_packet->channel; + channel = incoming_channel; nvsc_packet->send_completion(nvsc_packet-> send_completion_ctx); } @@ -748,7 +749,7 @@ static inline int netvsc_send_pkt( struct netvsc_device *net_device) { struct nvsp_message nvmsg; - struct vmbus_channel *out_channel = packet->channel; + struct vmbus_channel *out_channel = get_channel(packet, net_device); u16 q_idx = packet->q_idx; struct net_device *ndev = net_device->ndev; u64 req_id; @@ -857,13 +858,9 @@ int netvsc_send(struct hv_device *device, if (!net_device) return -ENODEV; - out_channel = net_device->chn_table[q_idx]; - if (!out_channel) { - out_channel = device->channel; - q_idx = 0; - packet->q_idx = 0; - } - packet->channel = out_channel; + out_channel = get_channel(packet, net_device); + q_idx = packet->q_idx; + packet->send_buf_index = NETVSC_INVALID_INDEX; packet->cp_partial = false; @@ -1043,7 +1040,6 @@ static void netvsc_receive(struct netvsc_device *net_device, } count = vmxferpage_packet->range_cnt; - netvsc_packet->channel = channel; /* Each range represents 1 RNDIS pkt that contains 1 ethernet frame */ for (i = 0; i < count; i++) { @@ -1055,7 +1051,7 @@ static void netvsc_receive(struct netvsc_device *net_device, vmxferpage_packet->ranges[i].byte_count; /* Pass it to the upper layer */ - rndis_filter_receive(device, netvsc_packet); + rndis_filter_receive(device, netvsc_packet, channel); if (netvsc_packet->status != NVSP_STAT_SUCCESS) status = NVSP_STAT_FAIL; @@ -1150,6 +1146,7 @@ void netvsc_channel_cb(void *context) switch (desc->type) { case VM_PKT_COMP: netvsc_send_completion(net_device, + channel, device, desc); break; diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 268a05821d46c..c8f294ee347be 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -683,7 +683,8 @@ void netvsc_linkstatus_callback(struct hv_device *device_obj, */ int netvsc_recv_callback(struct hv_device *device_obj, struct hv_netvsc_packet *packet, - struct ndis_tcp_ip_checksum_info *csum_info) + struct ndis_tcp_ip_checksum_info *csum_info, + struct vmbus_channel *channel) { struct net_device *net; struct net_device_context *net_device_ctx; @@ -729,7 +730,7 @@ int netvsc_recv_callback(struct hv_device *device_obj, __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), packet->vlan_tci); - skb_record_rx_queue(skb, packet->channel-> + skb_record_rx_queue(skb, channel-> offermsg.offer.sub_channel_index); u64_stats_update_begin(&rx_stats->syncp); diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c index 5931a799aa178..1b04d78bc7b9e 100644 --- a/drivers/net/hyperv/rndis_filter.c +++ b/drivers/net/hyperv/rndis_filter.c @@ -350,7 +350,8 @@ static inline void *rndis_get_ppi(struct rndis_packet *rpkt, u32 type) static void rndis_filter_receive_data(struct rndis_device *dev, struct rndis_message *msg, - struct hv_netvsc_packet *pkt) + struct hv_netvsc_packet *pkt, + struct vmbus_channel *channel) { struct rndis_packet *rndis_pkt; u32 data_offset; @@ -393,11 +394,12 @@ static void rndis_filter_receive_data(struct rndis_device *dev, } csum_info = rndis_get_ppi(rndis_pkt, TCPIP_CHKSUM_PKTINFO); - netvsc_recv_callback(dev->net_dev->dev, pkt, csum_info); + netvsc_recv_callback(dev->net_dev->dev, pkt, csum_info, channel); } int rndis_filter_receive(struct hv_device *dev, - struct hv_netvsc_packet *pkt) + struct hv_netvsc_packet *pkt, + struct vmbus_channel *channel) { struct netvsc_device *net_dev = hv_get_drvdata(dev); struct rndis_device *rndis_dev; @@ -436,7 +438,7 @@ int rndis_filter_receive(struct hv_device *dev, switch (rndis_msg->ndis_msg_type) { case RNDIS_MSG_PACKET: /* data msg */ - rndis_filter_receive_data(rndis_dev, rndis_msg, pkt); + rndis_filter_receive_data(rndis_dev, rndis_msg, pkt, channel); break; case RNDIS_MSG_INIT_C: From 24476760ef0b45bab75ea6731d081aeb48113e6a Mon Sep 17 00:00:00 2001 From: KY Srinivasan Date: Tue, 1 Dec 2015 16:43:06 -0800 Subject: [PATCH 04/17] hv_netvsc: Eliminate rndis_msg pointer from hv_netvsc_packet structure Eliminate rndis_msg pointer from hv_netvsc_packet structure. Signed-off-by: K. Y. Srinivasan Reviewed-by: Haiyang Zhang Signed-off-by: David S. Miller --- drivers/net/hyperv/hyperv_net.h | 8 +++----- drivers/net/hyperv/netvsc.c | 10 ++++++---- drivers/net/hyperv/netvsc_drv.c | 7 +++---- drivers/net/hyperv/rndis_filter.c | 2 +- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index 6bb1acd2a81c5..14deedd1b4113 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h @@ -149,10 +149,6 @@ struct hv_netvsc_packet { void *send_completion_ctx; void (*send_completion)(void *context); - - /* This points to the memory after page_buf */ - struct rndis_message *rndis_msg; - /* Points to the send/receive buffer where the ethernet frame is */ void *data; struct hv_page_buffer *page_buf; @@ -188,10 +184,12 @@ struct rndis_device { /* Interface */ +struct rndis_message; int netvsc_device_add(struct hv_device *device, void *additional_info); int netvsc_device_remove(struct hv_device *device); int netvsc_send(struct hv_device *device, - struct hv_netvsc_packet *packet); + struct hv_netvsc_packet *packet, + struct rndis_message *rndis_msg); void netvsc_linkstatus_callback(struct hv_device *device_obj, struct rndis_message *resp); void netvsc_xmit_completion(void *context); diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c index 52533edbd2b04..2de9e7fb4f686 100644 --- a/drivers/net/hyperv/netvsc.c +++ b/drivers/net/hyperv/netvsc.c @@ -706,7 +706,8 @@ static u32 netvsc_get_next_send_section(struct netvsc_device *net_device) static u32 netvsc_copy_to_send_buf(struct netvsc_device *net_device, unsigned int section_index, u32 pend_size, - struct hv_netvsc_packet *packet) + struct hv_netvsc_packet *packet, + struct rndis_message *rndis_msg) { char *start = net_device->send_buf; char *dest = start + (section_index * net_device->send_section_size) @@ -722,7 +723,7 @@ static u32 netvsc_copy_to_send_buf(struct netvsc_device *net_device, if (packet->is_data_pkt && packet->xmit_more && remain && !packet->cp_partial) { padding = net_device->pkt_align - remain; - packet->rndis_msg->msg_len += padding; + rndis_msg->msg_len += padding; packet->total_data_buflen += padding; } @@ -841,7 +842,8 @@ static inline int netvsc_send_pkt( } int netvsc_send(struct hv_device *device, - struct hv_netvsc_packet *packet) + struct hv_netvsc_packet *packet, + struct rndis_message *rndis_msg) { struct netvsc_device *net_device; int ret = 0, m_ret = 0; @@ -897,7 +899,7 @@ int netvsc_send(struct hv_device *device, if (section_index != NETVSC_INVALID_INDEX) { netvsc_copy_to_send_buf(net_device, section_index, msd_len, - packet); + packet, rndis_msg); packet->send_buf_index = section_index; diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index c8f294ee347be..e5f81c797e26e 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -483,10 +483,10 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) packet->is_data_pkt = true; packet->total_data_buflen = skb->len; - packet->rndis_msg = (struct rndis_message *)((unsigned long)packet + + rndis_msg = (struct rndis_message *)((unsigned long)packet + sizeof(struct hv_netvsc_packet)); - memset(packet->rndis_msg, 0, RNDIS_AND_PPI_SIZE); + memset(rndis_msg, 0, RNDIS_AND_PPI_SIZE); /* Set the completion routine */ packet->send_completion = netvsc_xmit_completion; @@ -496,7 +496,6 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) isvlan = packet->vlan_tci & VLAN_TAG_PRESENT; /* Add the rndis header */ - rndis_msg = packet->rndis_msg; rndis_msg->ndis_msg_type = RNDIS_MSG_PACKET; rndis_msg->msg_len = packet->total_data_buflen; rndis_pkt = &rndis_msg->msg.pkt; @@ -620,7 +619,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) packet->page_buf_cnt = init_page_array(rndis_msg, rndis_msg_size, skb, packet); - ret = netvsc_send(net_device_ctx->device_ctx, packet); + ret = netvsc_send(net_device_ctx->device_ctx, packet, rndis_msg); drop: if (ret == 0) { diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c index 1b04d78bc7b9e..63584e7a49e37 100644 --- a/drivers/net/hyperv/rndis_filter.c +++ b/drivers/net/hyperv/rndis_filter.c @@ -240,7 +240,7 @@ static int rndis_filter_send_request(struct rndis_device *dev, packet->send_completion = NULL; packet->xmit_more = false; - ret = netvsc_send(dev->net_dev->dev, packet); + ret = netvsc_send(dev->net_dev->dev, packet, NULL); return ret; } From c4b20c6370aa5cdbe11536125d86f31378d4b702 Mon Sep 17 00:00:00 2001 From: KY Srinivasan Date: Tue, 1 Dec 2015 16:43:07 -0800 Subject: [PATCH 05/17] hv_netvsc: Eliminatte the data field from struct hv_netvsc_packet Eliminatte the data field from struct hv_netvsc_packet. Signed-off-by: K. Y. Srinivasan Reviewed-by: Haiyang Zhang Signed-off-by: David S. Miller --- drivers/net/hyperv/hyperv_net.h | 5 ++--- drivers/net/hyperv/netvsc.c | 5 +++-- drivers/net/hyperv/netvsc_drv.c | 3 ++- drivers/net/hyperv/rndis_filter.c | 11 +++++++---- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index 14deedd1b4113..62542081a864c 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h @@ -148,9 +148,6 @@ struct hv_netvsc_packet { u64 send_completion_tid; void *send_completion_ctx; void (*send_completion)(void *context); - - /* Points to the send/receive buffer where the ethernet frame is */ - void *data; struct hv_page_buffer *page_buf; }; @@ -195,6 +192,7 @@ void netvsc_linkstatus_callback(struct hv_device *device_obj, void netvsc_xmit_completion(void *context); int netvsc_recv_callback(struct hv_device *device_obj, struct hv_netvsc_packet *packet, + void **data, struct ndis_tcp_ip_checksum_info *csum_info, struct vmbus_channel *channel); void netvsc_channel_cb(void *context); @@ -205,6 +203,7 @@ int rndis_filter_device_add(struct hv_device *dev, void rndis_filter_device_remove(struct hv_device *dev); int rndis_filter_receive(struct hv_device *dev, struct hv_netvsc_packet *pkt, + void **data, struct vmbus_channel *channel); int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter); diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c index 2de9e7fb4f686..8fbf81626bc30 100644 --- a/drivers/net/hyperv/netvsc.c +++ b/drivers/net/hyperv/netvsc.c @@ -1008,6 +1008,7 @@ static void netvsc_receive(struct netvsc_device *net_device, int i; int count = 0; struct net_device *ndev; + void *data; ndev = net_device->ndev; @@ -1047,13 +1048,13 @@ static void netvsc_receive(struct netvsc_device *net_device, for (i = 0; i < count; i++) { /* Initialize the netvsc packet */ netvsc_packet->status = NVSP_STAT_SUCCESS; - netvsc_packet->data = (void *)((unsigned long)net_device-> + data = (void *)((unsigned long)net_device-> recv_buf + vmxferpage_packet->ranges[i].byte_offset); netvsc_packet->total_data_buflen = vmxferpage_packet->ranges[i].byte_count; /* Pass it to the upper layer */ - rndis_filter_receive(device, netvsc_packet, channel); + rndis_filter_receive(device, netvsc_packet, &data, channel); if (netvsc_packet->status != NVSP_STAT_SUCCESS) status = NVSP_STAT_FAIL; diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index e5f81c797e26e..622e62e326363 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -682,6 +682,7 @@ void netvsc_linkstatus_callback(struct hv_device *device_obj, */ int netvsc_recv_callback(struct hv_device *device_obj, struct hv_netvsc_packet *packet, + void **data, struct ndis_tcp_ip_checksum_info *csum_info, struct vmbus_channel *channel) { @@ -710,7 +711,7 @@ int netvsc_recv_callback(struct hv_device *device_obj, * Copy to skb. This copy is needed here since the memory pointed by * hv_netvsc_packet cannot be deallocated */ - memcpy(skb_put(skb, packet->total_data_buflen), packet->data, + memcpy(skb_put(skb, packet->total_data_buflen), *data, packet->total_data_buflen); skb->protocol = eth_type_trans(skb, net); diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c index 63584e7a49e37..be0fa9c94f636 100644 --- a/drivers/net/hyperv/rndis_filter.c +++ b/drivers/net/hyperv/rndis_filter.c @@ -351,6 +351,7 @@ static inline void *rndis_get_ppi(struct rndis_packet *rpkt, u32 type) static void rndis_filter_receive_data(struct rndis_device *dev, struct rndis_message *msg, struct hv_netvsc_packet *pkt, + void **data, struct vmbus_channel *channel) { struct rndis_packet *rndis_pkt; @@ -383,7 +384,7 @@ static void rndis_filter_receive_data(struct rndis_device *dev, * the data packet to the stack, without the rndis trailer padding */ pkt->total_data_buflen = rndis_pkt->data_len; - pkt->data = (void *)((unsigned long)pkt->data + data_offset); + *data = (void *)((unsigned long)(*data) + data_offset); vlan = rndis_get_ppi(rndis_pkt, IEEE_8021Q_INFO); if (vlan) { @@ -394,11 +395,12 @@ static void rndis_filter_receive_data(struct rndis_device *dev, } csum_info = rndis_get_ppi(rndis_pkt, TCPIP_CHKSUM_PKTINFO); - netvsc_recv_callback(dev->net_dev->dev, pkt, csum_info, channel); + netvsc_recv_callback(dev->net_dev->dev, pkt, data, csum_info, channel); } int rndis_filter_receive(struct hv_device *dev, struct hv_netvsc_packet *pkt, + void **data, struct vmbus_channel *channel) { struct netvsc_device *net_dev = hv_get_drvdata(dev); @@ -430,7 +432,7 @@ int rndis_filter_receive(struct hv_device *dev, goto exit; } - rndis_msg = pkt->data; + rndis_msg = *data; if (netif_msg_rx_err(net_dev->nd_ctx)) dump_rndis_message(dev, rndis_msg); @@ -438,7 +440,8 @@ int rndis_filter_receive(struct hv_device *dev, switch (rndis_msg->ndis_msg_type) { case RNDIS_MSG_PACKET: /* data msg */ - rndis_filter_receive_data(rndis_dev, rndis_msg, pkt, channel); + rndis_filter_receive_data(rndis_dev, rndis_msg, pkt, + data, channel); break; case RNDIS_MSG_INIT_C: From 09215ef5dfd5a2c6c169733162091ca7e56a4890 Mon Sep 17 00:00:00 2001 From: KY Srinivasan Date: Tue, 1 Dec 2015 16:43:08 -0800 Subject: [PATCH 06/17] hv_netvsc: Eliminate send_completion from struct hv_netvsc_packet Eliminate send_completion from struct hv_netvsc_packet. Signed-off-by: K. Y. Srinivasan Reviewed-by: Haiyang Zhang Signed-off-by: David S. Miller --- drivers/net/hyperv/hyperv_net.h | 3 +-- drivers/net/hyperv/netvsc.c | 6 +++--- drivers/net/hyperv/netvsc_drv.c | 2 +- drivers/net/hyperv/rndis_filter.c | 2 +- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index 62542081a864c..f096f2fd713db 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h @@ -135,7 +135,7 @@ struct hv_netvsc_packet { u8 rmsg_size; /* RNDIS header and PPI size */ u8 rmsg_pgcnt; /* page count of RNDIS header and PPI */ u8 page_buf_cnt; - u8 pad0; + u8 completion_func; u16 vlan_tci; u16 q_idx; @@ -147,7 +147,6 @@ struct hv_netvsc_packet { u64 send_completion_tid; void *send_completion_ctx; - void (*send_completion)(void *context); struct hv_page_buffer *page_buf; }; diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c index 8fbf81626bc30..34c16d19f05d7 100644 --- a/drivers/net/hyperv/netvsc.c +++ b/drivers/net/hyperv/netvsc.c @@ -653,8 +653,8 @@ static void netvsc_send_completion(struct netvsc_device *net_device, netvsc_free_send_slot(net_device, send_index); q_idx = nvsc_packet->q_idx; channel = incoming_channel; - nvsc_packet->send_completion(nvsc_packet-> - send_completion_ctx); + netvsc_xmit_completion(nvsc_packet-> + send_completion_ctx); } num_outstanding_sends = @@ -775,7 +775,7 @@ static inline int netvsc_send_pkt( nvmsg.msg.v1_msg.send_rndis_pkt.send_buf_section_size = packet->total_data_buflen; - if (packet->send_completion) + if (packet->completion_func) req_id = (ulong)packet; else req_id = 0; diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 622e62e326363..8f29d805bd77c 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -489,7 +489,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) memset(rndis_msg, 0, RNDIS_AND_PPI_SIZE); /* Set the completion routine */ - packet->send_completion = netvsc_xmit_completion; + packet->completion_func = 1; packet->send_completion_ctx = packet; packet->send_completion_tid = (unsigned long)skb; diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c index be0fa9c94f636..c8af172faee3e 100644 --- a/drivers/net/hyperv/rndis_filter.c +++ b/drivers/net/hyperv/rndis_filter.c @@ -237,7 +237,7 @@ static int rndis_filter_send_request(struct rndis_device *dev, packet->page_buf[0].len; } - packet->send_completion = NULL; + packet->completion_func = 0; packet->xmit_more = false; ret = netvsc_send(dev->net_dev->dev, packet, NULL); From 074c2fe5ef3d09e9a1008d307a22ab5086e22728 Mon Sep 17 00:00:00 2001 From: KY Srinivasan Date: Tue, 1 Dec 2015 16:43:09 -0800 Subject: [PATCH 07/17] hv_netvsc: Eliminate send_completion_ctx from struct hv_netvsc_packet Eliminate send_completion_ctx from struct hv_netvsc_packet. Signed-off-by: K. Y. Srinivasan Reviewed-by: Haiyang Zhang Signed-off-by: David S. Miller --- drivers/net/hyperv/hyperv_net.h | 1 - drivers/net/hyperv/netvsc.c | 3 +-- drivers/net/hyperv/netvsc_drv.c | 1 - 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index f096f2fd713db..fc6d0c6de741e 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h @@ -146,7 +146,6 @@ struct hv_netvsc_packet { u64 send_completion_tid; - void *send_completion_ctx; struct hv_page_buffer *page_buf; }; diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c index 34c16d19f05d7..0e0b723df1aca 100644 --- a/drivers/net/hyperv/netvsc.c +++ b/drivers/net/hyperv/netvsc.c @@ -653,8 +653,7 @@ static void netvsc_send_completion(struct netvsc_device *net_device, netvsc_free_send_slot(net_device, send_index); q_idx = nvsc_packet->q_idx; channel = incoming_channel; - netvsc_xmit_completion(nvsc_packet-> - send_completion_ctx); + netvsc_xmit_completion(nvsc_packet); } num_outstanding_sends = diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 8f29d805bd77c..7e356a11c1d74 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -490,7 +490,6 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) /* Set the completion routine */ packet->completion_func = 1; - packet->send_completion_ctx = packet; packet->send_completion_tid = (unsigned long)skb; isvlan = packet->vlan_tci & VLAN_TAG_PRESENT; From c0eb454034aab783dc602739237a63b30867f5bd Mon Sep 17 00:00:00 2001 From: KY Srinivasan Date: Tue, 1 Dec 2015 16:43:10 -0800 Subject: [PATCH 08/17] hv_netvsc: Don't ask for additional head room in the skb The rndis header is 116 bytes big and can be placed in the default head room that will be available in the skb. Since the netvsc packet is less than 48 bytes, we can use the skb control buffer for the netvsc packet. With these changes we don't need to ask for additional head room. Signed-off-by: K. Y. Srinivasan Reviewed-by: Haiyang Zhang Signed-off-by: David S. Miller --- drivers/net/hyperv/hyperv_net.h | 3 +++ drivers/net/hyperv/netvsc_drv.c | 30 +++++++++++------------------- include/linux/netdevice.h | 4 +++- 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index fc6d0c6de741e..731054ef6da58 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h @@ -124,6 +124,9 @@ struct ndis_tcp_ip_checksum_info; /* * Represent netvsc packet which contains 1 RNDIS and 1 ethernet frame * within the RNDIS + * + * The size of this structure is less than 48 bytes and we can now + * place this structure in the skb->cb field. */ struct hv_netvsc_packet { /* Bookkeeping stuff */ diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 7e356a11c1d74..b820888409bc2 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -433,7 +433,6 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) u32 net_trans_info; u32 hash; u32 skb_length; - u32 pkt_sz; struct hv_page_buffer page_buf[MAX_PAGE_BUFFER_COUNT]; struct netvsc_stats *tx_stats = this_cpu_ptr(net_device_ctx->tx_stats); @@ -461,16 +460,21 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) goto check_size; } - pkt_sz = sizeof(struct hv_netvsc_packet) + RNDIS_AND_PPI_SIZE; - - ret = skb_cow_head(skb, pkt_sz); + /* + * Place the rndis header in the skb head room and + * the skb->cb will be used for hv_netvsc_packet + * structure. + */ + ret = skb_cow_head(skb, RNDIS_AND_PPI_SIZE); if (ret) { netdev_err(net, "unable to alloc hv_netvsc_packet\n"); ret = -ENOMEM; goto drop; } - /* Use the headroom for building up the packet */ - packet = (struct hv_netvsc_packet *)skb->head; + /* Use the skb control buffer for building up the packet */ + BUILD_BUG_ON(sizeof(struct hv_netvsc_packet) > + FIELD_SIZEOF(struct sk_buff, cb)); + packet = (struct hv_netvsc_packet *)skb->cb; packet->status = 0; packet->xmit_more = skb->xmit_more; @@ -483,8 +487,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) packet->is_data_pkt = true; packet->total_data_buflen = skb->len; - rndis_msg = (struct rndis_message *)((unsigned long)packet + - sizeof(struct hv_netvsc_packet)); + rndis_msg = (struct rndis_message *)skb->head; memset(rndis_msg, 0, RNDIS_AND_PPI_SIZE); @@ -1118,16 +1121,12 @@ static int netvsc_probe(struct hv_device *dev, struct netvsc_device_info device_info; struct netvsc_device *nvdev; int ret; - u32 max_needed_headroom; net = alloc_etherdev_mq(sizeof(struct net_device_context), num_online_cpus()); if (!net) return -ENOMEM; - max_needed_headroom = sizeof(struct hv_netvsc_packet) + - RNDIS_AND_PPI_SIZE; - netif_carrier_off(net); net_device_ctx = netdev_priv(net); @@ -1166,13 +1165,6 @@ static int netvsc_probe(struct hv_device *dev, net->ethtool_ops = ðtool_ops; SET_NETDEV_DEV(net, &dev->device); - /* - * Request additional head room in the skb. - * We will use this space to build the rndis - * heaser and other state we need to maintain. - */ - net->needed_headroom = max_needed_headroom; - /* Notify the netvsc driver of the new device */ memset(&device_info, 0, sizeof(device_info)); device_info.ring_size = ring_size; diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 7d2d1d7aaec7c..fcbc5259c6303 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -132,7 +132,9 @@ static inline bool dev_xmit_complete(int rc) * used. */ -#if defined(CONFIG_WLAN) || IS_ENABLED(CONFIG_AX25) +#if defined(CONFIG_HYPERV_NET) +# define LL_MAX_HEADER 128 +#elif defined(CONFIG_WLAN) || IS_ENABLED(CONFIG_AX25) # if defined(CONFIG_MAC80211_MESH) # define LL_MAX_HEADER 128 # else From 8b9fbe1ac390689f01153d6af8485caec5423ccc Mon Sep 17 00:00:00 2001 From: Vitaly Kuznetsov Date: Tue, 1 Dec 2015 16:43:11 -0800 Subject: [PATCH 09/17] hv_netvsc: move subchannel existence check to netvsc_select_queue() Signed-off-by: Vitaly Kuznetsov Signed-off-by: K. Y. Srinivasan Signed-off-by: David S. Miller --- drivers/net/hyperv/hyperv_net.h | 15 --------------- drivers/net/hyperv/netvsc.c | 5 ++--- drivers/net/hyperv/netvsc_drv.c | 3 +++ 3 files changed, 5 insertions(+), 18 deletions(-) diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index 731054ef6da58..8d534a324ce16 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h @@ -1272,19 +1272,4 @@ struct rndis_message { #define TRANSPORT_INFO_IPV6_TCP ((INFO_IPV6 << 16) | INFO_TCP) #define TRANSPORT_INFO_IPV6_UDP ((INFO_IPV6 << 16) | INFO_UDP) -static inline struct vmbus_channel *get_channel(struct hv_netvsc_packet *packet, - struct netvsc_device *net_device) - -{ - struct vmbus_channel *out_channel; - - out_channel = net_device->chn_table[packet->q_idx]; - if (!out_channel) { - out_channel = net_device->dev->channel; - packet->q_idx = 0; - } - return out_channel; -} - - #endif /* _HYPERV_NET_H */ diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c index 0e0b723df1aca..419b05515b926 100644 --- a/drivers/net/hyperv/netvsc.c +++ b/drivers/net/hyperv/netvsc.c @@ -749,8 +749,8 @@ static inline int netvsc_send_pkt( struct netvsc_device *net_device) { struct nvsp_message nvmsg; - struct vmbus_channel *out_channel = get_channel(packet, net_device); u16 q_idx = packet->q_idx; + struct vmbus_channel *out_channel = net_device->chn_table[q_idx]; struct net_device *ndev = net_device->ndev; u64 req_id; int ret; @@ -859,8 +859,7 @@ int netvsc_send(struct hv_device *device, if (!net_device) return -ENODEV; - out_channel = get_channel(packet, net_device); - q_idx = packet->q_idx; + out_channel = net_device->chn_table[q_idx]; packet->send_buf_index = NETVSC_INVALID_INDEX; packet->cp_partial = false; diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index b820888409bc2..38b53faa8119f 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -273,6 +273,9 @@ static u16 netvsc_select_queue(struct net_device *ndev, struct sk_buff *skb, skb_set_hash(skb, hash, PKT_HASH_TYPE_L3); } + if (!nvsc_dev->chn_table[q_idx]) + q_idx = 0; + return q_idx; } From 2a04ae8acb144996eba6e3d69ab2a7156c775416 Mon Sep 17 00:00:00 2001 From: Vitaly Kuznetsov Date: Tue, 1 Dec 2015 16:43:12 -0800 Subject: [PATCH 10/17] hv_netvsc: remove locking in netvsc_send() Packet scheduler guarantees there won't be multiple senders for the same queue and as we use q_idx for multi_send_data the spinlock is redundant. Signed-off-by: Vitaly Kuznetsov Signed-off-by: K. Y. Srinivasan Signed-off-by: David S. Miller --- drivers/net/hyperv/hyperv_net.h | 1 - drivers/net/hyperv/netvsc.c | 8 -------- 2 files changed, 9 deletions(-) diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index 8d534a324ce16..ee0f55957ab8d 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h @@ -632,7 +632,6 @@ struct nvsp_message { #define RNDIS_PKT_ALIGN_DEFAULT 8 struct multi_send_data { - spinlock_t lock; /* protect struct multi_send_data */ struct hv_netvsc_packet *pkt; /* netvsc pkt pending */ u32 count; /* counter of batched packets */ }; diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c index 419b05515b926..081f14f75509b 100644 --- a/drivers/net/hyperv/netvsc.c +++ b/drivers/net/hyperv/netvsc.c @@ -38,7 +38,6 @@ static struct netvsc_device *alloc_net_device(struct hv_device *device) { struct netvsc_device *net_device; struct net_device *ndev = hv_get_drvdata(device); - int i; net_device = kzalloc(sizeof(struct netvsc_device), GFP_KERNEL); if (!net_device) @@ -58,9 +57,6 @@ static struct netvsc_device *alloc_net_device(struct hv_device *device) net_device->max_pkt = RNDIS_MAX_PKT_DEFAULT; net_device->pkt_align = RNDIS_PKT_ALIGN_DEFAULT; - for (i = 0; i < num_online_cpus(); i++) - spin_lock_init(&net_device->msd[i].lock); - hv_set_drvdata(device, net_device); return net_device; } @@ -850,7 +846,6 @@ int netvsc_send(struct hv_device *device, u16 q_idx = packet->q_idx; u32 pktlen = packet->total_data_buflen, msd_len = 0; unsigned int section_index = NETVSC_INVALID_INDEX; - unsigned long flag; struct multi_send_data *msdp; struct hv_netvsc_packet *msd_send = NULL, *cur_send = NULL; bool try_batch; @@ -867,7 +862,6 @@ int netvsc_send(struct hv_device *device, msdp = &net_device->msd[q_idx]; /* batch packets in send buffer if possible */ - spin_lock_irqsave(&msdp->lock, flag); if (msdp->pkt) msd_len = msdp->pkt->total_data_buflen; @@ -927,8 +921,6 @@ int netvsc_send(struct hv_device *device, cur_send = packet; } - spin_unlock_irqrestore(&msdp->lock, flag); - if (msd_send) { m_ret = netvsc_send_pkt(msd_send, net_device); From a9f2e2d6569d00ae8f9f832f1b56bc7702dfd2d3 Mon Sep 17 00:00:00 2001 From: KY Srinivasan Date: Tue, 1 Dec 2015 16:43:13 -0800 Subject: [PATCH 11/17] hv_netvsc: Eliminate page_buf from struct hv_netvsc_packet Eliminate page_buf from struct hv_netvsc_packet. Signed-off-by: K. Y. Srinivasan Reviewed-by: Haiyang Zhang Signed-off-by: David S. Miller --- drivers/net/hyperv/hyperv_net.h | 4 ++-- drivers/net/hyperv/netvsc.c | 25 ++++++++++++++----------- drivers/net/hyperv/netvsc_drv.c | 11 ++++++----- drivers/net/hyperv/rndis_filter.c | 26 +++++++++++++------------- 4 files changed, 35 insertions(+), 31 deletions(-) diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index ee0f55957ab8d..c7517b146b4fc 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h @@ -149,7 +149,6 @@ struct hv_netvsc_packet { u64 send_completion_tid; - struct hv_page_buffer *page_buf; }; struct netvsc_device_info { @@ -187,7 +186,8 @@ int netvsc_device_add(struct hv_device *device, void *additional_info); int netvsc_device_remove(struct hv_device *device); int netvsc_send(struct hv_device *device, struct hv_netvsc_packet *packet, - struct rndis_message *rndis_msg); + struct rndis_message *rndis_msg, + struct hv_page_buffer **page_buffer); void netvsc_linkstatus_callback(struct hv_device *device_obj, struct rndis_message *resp); void netvsc_xmit_completion(void *context); diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c index 081f14f75509b..18058a593b356 100644 --- a/drivers/net/hyperv/netvsc.c +++ b/drivers/net/hyperv/netvsc.c @@ -702,7 +702,8 @@ static u32 netvsc_copy_to_send_buf(struct netvsc_device *net_device, unsigned int section_index, u32 pend_size, struct hv_netvsc_packet *packet, - struct rndis_message *rndis_msg) + struct rndis_message *rndis_msg, + struct hv_page_buffer **pb) { char *start = net_device->send_buf; char *dest = start + (section_index * net_device->send_section_size) @@ -723,9 +724,9 @@ static u32 netvsc_copy_to_send_buf(struct netvsc_device *net_device, } for (i = 0; i < page_count; i++) { - char *src = phys_to_virt(packet->page_buf[i].pfn << PAGE_SHIFT); - u32 offset = packet->page_buf[i].offset; - u32 len = packet->page_buf[i].len; + char *src = phys_to_virt((*pb)[i].pfn << PAGE_SHIFT); + u32 offset = (*pb)[i].offset; + u32 len = (*pb)[i].len; memcpy(dest, (src + offset), len); msg_size += len; @@ -742,7 +743,8 @@ static u32 netvsc_copy_to_send_buf(struct netvsc_device *net_device, static inline int netvsc_send_pkt( struct hv_netvsc_packet *packet, - struct netvsc_device *net_device) + struct netvsc_device *net_device, + struct hv_page_buffer **pb) { struct nvsp_message nvmsg; u16 q_idx = packet->q_idx; @@ -789,8 +791,8 @@ static inline int netvsc_send_pkt( packet->xmit_more = false; if (packet->page_buf_cnt) { - pgbuf = packet->cp_partial ? packet->page_buf + - packet->rmsg_pgcnt : packet->page_buf; + pgbuf = packet->cp_partial ? (*pb) + + packet->rmsg_pgcnt : (*pb); ret = vmbus_sendpacket_pagebuffer_ctl(out_channel, pgbuf, packet->page_buf_cnt, @@ -838,7 +840,8 @@ static inline int netvsc_send_pkt( int netvsc_send(struct hv_device *device, struct hv_netvsc_packet *packet, - struct rndis_message *rndis_msg) + struct rndis_message *rndis_msg, + struct hv_page_buffer **pb) { struct netvsc_device *net_device; int ret = 0, m_ret = 0; @@ -891,7 +894,7 @@ int netvsc_send(struct hv_device *device, if (section_index != NETVSC_INVALID_INDEX) { netvsc_copy_to_send_buf(net_device, section_index, msd_len, - packet, rndis_msg); + packet, rndis_msg, pb); packet->send_buf_index = section_index; @@ -922,7 +925,7 @@ int netvsc_send(struct hv_device *device, } if (msd_send) { - m_ret = netvsc_send_pkt(msd_send, net_device); + m_ret = netvsc_send_pkt(msd_send, net_device, pb); if (m_ret != 0) { netvsc_free_send_slot(net_device, @@ -932,7 +935,7 @@ int netvsc_send(struct hv_device *device, } if (cur_send) - ret = netvsc_send_pkt(cur_send, net_device); + ret = netvsc_send_pkt(cur_send, net_device, pb); if (ret != 0 && section_index != NETVSC_INVALID_INDEX) netvsc_free_send_slot(net_device, section_index); diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 38b53faa8119f..eca669257360d 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -324,9 +324,10 @@ static u32 fill_pg_buf(struct page *page, u32 offset, u32 len, } static u32 init_page_array(void *hdr, u32 len, struct sk_buff *skb, - struct hv_netvsc_packet *packet) + struct hv_netvsc_packet *packet, + struct hv_page_buffer **page_buf) { - struct hv_page_buffer *pb = packet->page_buf; + struct hv_page_buffer *pb = *page_buf; u32 slots_used = 0; char *data = skb->data; int frags = skb_shinfo(skb)->nr_frags; @@ -437,6 +438,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) u32 hash; u32 skb_length; struct hv_page_buffer page_buf[MAX_PAGE_BUFFER_COUNT]; + struct hv_page_buffer *pb = page_buf; struct netvsc_stats *tx_stats = this_cpu_ptr(net_device_ctx->tx_stats); /* We will atmost need two pages to describe the rndis @@ -483,7 +485,6 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) packet->xmit_more = skb->xmit_more; packet->vlan_tci = skb->vlan_tci; - packet->page_buf = page_buf; packet->q_idx = skb_get_queue_mapping(skb); @@ -622,9 +623,9 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) rndis_msg->msg_len += rndis_msg_size; packet->total_data_buflen = rndis_msg->msg_len; packet->page_buf_cnt = init_page_array(rndis_msg, rndis_msg_size, - skb, packet); + skb, packet, &pb); - ret = netvsc_send(net_device_ctx->device_ctx, packet, rndis_msg); + ret = netvsc_send(net_device_ctx->device_ctx, packet, rndis_msg, &pb); drop: if (ret == 0) { diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c index c8af172faee3e..6ff22530488fb 100644 --- a/drivers/net/hyperv/rndis_filter.c +++ b/drivers/net/hyperv/rndis_filter.c @@ -210,6 +210,7 @@ static int rndis_filter_send_request(struct rndis_device *dev, int ret; struct hv_netvsc_packet *packet; struct hv_page_buffer page_buf[2]; + struct hv_page_buffer *pb = page_buf; /* Setup the packet to send it */ packet = &req->pkt; @@ -217,30 +218,29 @@ static int rndis_filter_send_request(struct rndis_device *dev, packet->is_data_pkt = false; packet->total_data_buflen = req->request_msg.msg_len; packet->page_buf_cnt = 1; - packet->page_buf = page_buf; - packet->page_buf[0].pfn = virt_to_phys(&req->request_msg) >> + pb[0].pfn = virt_to_phys(&req->request_msg) >> PAGE_SHIFT; - packet->page_buf[0].len = req->request_msg.msg_len; - packet->page_buf[0].offset = + pb[0].len = req->request_msg.msg_len; + pb[0].offset = (unsigned long)&req->request_msg & (PAGE_SIZE - 1); /* Add one page_buf when request_msg crossing page boundary */ - if (packet->page_buf[0].offset + packet->page_buf[0].len > PAGE_SIZE) { + if (pb[0].offset + pb[0].len > PAGE_SIZE) { packet->page_buf_cnt++; - packet->page_buf[0].len = PAGE_SIZE - - packet->page_buf[0].offset; - packet->page_buf[1].pfn = virt_to_phys((void *)&req->request_msg - + packet->page_buf[0].len) >> PAGE_SHIFT; - packet->page_buf[1].offset = 0; - packet->page_buf[1].len = req->request_msg.msg_len - - packet->page_buf[0].len; + pb[0].len = PAGE_SIZE - + pb[0].offset; + pb[1].pfn = virt_to_phys((void *)&req->request_msg + + pb[0].len) >> PAGE_SHIFT; + pb[1].offset = 0; + pb[1].len = req->request_msg.msg_len - + pb[0].len; } packet->completion_func = 0; packet->xmit_more = false; - ret = netvsc_send(dev->net_dev->dev, packet, NULL); + ret = netvsc_send(dev->net_dev->dev, packet, NULL, &pb); return ret; } From 3a3d9a0a731add5afaafd9c714e7efe11820fe5b Mon Sep 17 00:00:00 2001 From: KY Srinivasan Date: Tue, 1 Dec 2015 16:43:14 -0800 Subject: [PATCH 12/17] hv_netvsc: Eliminate send_completion_tid from struct hv_netvsc_packet Eliminate send_completion_tid from struct hv_netvsc_packet. Signed-off-by: K. Y. Srinivasan Signed-off-by: David S. Miller --- drivers/net/hyperv/hyperv_net.h | 8 ++------ drivers/net/hyperv/netvsc.c | 28 ++++++++++++++-------------- drivers/net/hyperv/netvsc_drv.c | 14 ++------------ drivers/net/hyperv/rndis_filter.c | 2 +- 4 files changed, 19 insertions(+), 33 deletions(-) diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index c7517b146b4fc..eebfbe5f2f3d9 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h @@ -145,10 +145,6 @@ struct hv_netvsc_packet { u32 send_buf_index; u32 total_data_buflen; - u32 pad1; - - - u64 send_completion_tid; }; struct netvsc_device_info { @@ -187,10 +183,10 @@ int netvsc_device_remove(struct hv_device *device); int netvsc_send(struct hv_device *device, struct hv_netvsc_packet *packet, struct rndis_message *rndis_msg, - struct hv_page_buffer **page_buffer); + struct hv_page_buffer **page_buffer, + struct sk_buff *skb); void netvsc_linkstatus_callback(struct hv_device *device_obj, struct rndis_message *resp); -void netvsc_xmit_completion(void *context); int netvsc_recv_callback(struct hv_device *device_obj, struct hv_netvsc_packet *packet, void **data, diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c index 18058a593b356..d18e10cceced1 100644 --- a/drivers/net/hyperv/netvsc.c +++ b/drivers/net/hyperv/netvsc.c @@ -614,6 +614,7 @@ static void netvsc_send_completion(struct netvsc_device *net_device, struct hv_netvsc_packet *nvsc_packet; struct net_device *ndev; u32 send_index; + struct sk_buff *skb; ndev = net_device->ndev; @@ -639,17 +640,17 @@ static void netvsc_send_completion(struct netvsc_device *net_device, int queue_sends; /* Get the send context */ - nvsc_packet = (struct hv_netvsc_packet *)(unsigned long) - packet->trans_id; + skb = (struct sk_buff *)(unsigned long)packet->trans_id; /* Notify the layer above us */ - if (nvsc_packet) { + if (skb) { + nvsc_packet = (struct hv_netvsc_packet *) skb->cb; send_index = nvsc_packet->send_buf_index; if (send_index != NETVSC_INVALID_INDEX) netvsc_free_send_slot(net_device, send_index); q_idx = nvsc_packet->q_idx; channel = incoming_channel; - netvsc_xmit_completion(nvsc_packet); + dev_kfree_skb_any(skb); } num_outstanding_sends = @@ -744,7 +745,8 @@ static u32 netvsc_copy_to_send_buf(struct netvsc_device *net_device, static inline int netvsc_send_pkt( struct hv_netvsc_packet *packet, struct netvsc_device *net_device, - struct hv_page_buffer **pb) + struct hv_page_buffer **pb, + struct sk_buff *skb) { struct nvsp_message nvmsg; u16 q_idx = packet->q_idx; @@ -772,10 +774,7 @@ static inline int netvsc_send_pkt( nvmsg.msg.v1_msg.send_rndis_pkt.send_buf_section_size = packet->total_data_buflen; - if (packet->completion_func) - req_id = (ulong)packet; - else - req_id = 0; + req_id = (ulong)skb; if (out_channel->rescind) return -ENODEV; @@ -841,7 +840,8 @@ static inline int netvsc_send_pkt( int netvsc_send(struct hv_device *device, struct hv_netvsc_packet *packet, struct rndis_message *rndis_msg, - struct hv_page_buffer **pb) + struct hv_page_buffer **pb, + struct sk_buff *skb) { struct netvsc_device *net_device; int ret = 0, m_ret = 0; @@ -907,7 +907,7 @@ int netvsc_send(struct hv_device *device, } if (msdp->pkt) - netvsc_xmit_completion(msdp->pkt); + dev_kfree_skb_any(skb); if (packet->xmit_more && !packet->cp_partial) { msdp->pkt = packet; @@ -925,17 +925,17 @@ int netvsc_send(struct hv_device *device, } if (msd_send) { - m_ret = netvsc_send_pkt(msd_send, net_device, pb); + m_ret = netvsc_send_pkt(msd_send, net_device, pb, skb); if (m_ret != 0) { netvsc_free_send_slot(net_device, msd_send->send_buf_index); - netvsc_xmit_completion(msd_send); + dev_kfree_skb_any(skb); } } if (cur_send) - ret = netvsc_send_pkt(cur_send, net_device, pb); + ret = netvsc_send_pkt(cur_send, net_device, pb, skb); if (ret != 0 && section_index != NETVSC_INVALID_INDEX) netvsc_free_send_slot(net_device, section_index); diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index eca669257360d..c1078a62a2316 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -279,16 +279,6 @@ static u16 netvsc_select_queue(struct net_device *ndev, struct sk_buff *skb, return q_idx; } -void netvsc_xmit_completion(void *context) -{ - struct hv_netvsc_packet *packet = (struct hv_netvsc_packet *)context; - struct sk_buff *skb = (struct sk_buff *) - (unsigned long)packet->send_completion_tid; - - if (skb) - dev_kfree_skb_any(skb); -} - static u32 fill_pg_buf(struct page *page, u32 offset, u32 len, struct hv_page_buffer *pb) { @@ -497,7 +487,6 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) /* Set the completion routine */ packet->completion_func = 1; - packet->send_completion_tid = (unsigned long)skb; isvlan = packet->vlan_tci & VLAN_TAG_PRESENT; @@ -625,7 +614,8 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) packet->page_buf_cnt = init_page_array(rndis_msg, rndis_msg_size, skb, packet, &pb); - ret = netvsc_send(net_device_ctx->device_ctx, packet, rndis_msg, &pb); + ret = netvsc_send(net_device_ctx->device_ctx, packet, + rndis_msg, &pb, skb); drop: if (ret == 0) { diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c index 6ff22530488fb..53139f7efcb91 100644 --- a/drivers/net/hyperv/rndis_filter.c +++ b/drivers/net/hyperv/rndis_filter.c @@ -240,7 +240,7 @@ static int rndis_filter_send_request(struct rndis_device *dev, packet->completion_func = 0; packet->xmit_more = false; - ret = netvsc_send(dev->net_dev->dev, packet, NULL, &pb); + ret = netvsc_send(dev->net_dev->dev, packet, NULL, &pb, NULL); return ret; } From 694a9fb0263dddfb07bc490a02e59d6962602fe8 Mon Sep 17 00:00:00 2001 From: KY Srinivasan Date: Tue, 1 Dec 2015 16:43:15 -0800 Subject: [PATCH 13/17] hv_netvsc: Eliminate is_data_pkt from struct hv_netvsc_packet Eliminate is_data_pkt from struct hv_netvsc_packet. Signed-off-by: K. Y. Srinivasan Signed-off-by: David S. Miller --- drivers/net/hyperv/hyperv_net.h | 1 - drivers/net/hyperv/netvsc.c | 14 ++++++++------ drivers/net/hyperv/netvsc_drv.c | 1 - drivers/net/hyperv/rndis_filter.c | 1 - 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index eebfbe5f2f3d9..2f69e31bc07d6 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h @@ -131,7 +131,6 @@ struct ndis_tcp_ip_checksum_info; struct hv_netvsc_packet { /* Bookkeeping stuff */ u8 status; - u8 is_data_pkt; u8 xmit_more; /* from skb */ u8 cp_partial; /* partial copy into send buffer */ diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c index d18e10cceced1..11b009ebb33ff 100644 --- a/drivers/net/hyperv/netvsc.c +++ b/drivers/net/hyperv/netvsc.c @@ -704,12 +704,14 @@ static u32 netvsc_copy_to_send_buf(struct netvsc_device *net_device, u32 pend_size, struct hv_netvsc_packet *packet, struct rndis_message *rndis_msg, - struct hv_page_buffer **pb) + struct hv_page_buffer **pb, + struct sk_buff *skb) { char *start = net_device->send_buf; char *dest = start + (section_index * net_device->send_section_size) + pend_size; int i; + bool is_data_pkt = (skb != NULL) ? true : false; u32 msg_size = 0; u32 padding = 0; u32 remain = packet->total_data_buflen % net_device->pkt_align; @@ -717,7 +719,7 @@ static u32 netvsc_copy_to_send_buf(struct netvsc_device *net_device, packet->page_buf_cnt; /* Add padding */ - if (packet->is_data_pkt && packet->xmit_more && remain && + if (is_data_pkt && packet->xmit_more && remain && !packet->cp_partial) { padding = net_device->pkt_align - remain; rndis_msg->msg_len += padding; @@ -758,7 +760,7 @@ static inline int netvsc_send_pkt( u32 ring_avail = hv_ringbuf_avail_percent(&out_channel->outbound); nvmsg.hdr.msg_type = NVSP_MSG1_TYPE_SEND_RNDIS_PKT; - if (packet->is_data_pkt) { + if (skb != NULL) { /* 0 is RMC_DATA; */ nvmsg.msg.v1_msg.send_rndis_pkt.channel_type = 0; } else { @@ -868,7 +870,7 @@ int netvsc_send(struct hv_device *device, if (msdp->pkt) msd_len = msdp->pkt->total_data_buflen; - try_batch = packet->is_data_pkt && msd_len > 0 && msdp->count < + try_batch = (skb != NULL) && msd_len > 0 && msdp->count < net_device->max_pkt; if (try_batch && msd_len + pktlen + net_device->pkt_align < @@ -880,7 +882,7 @@ int netvsc_send(struct hv_device *device, section_index = msdp->pkt->send_buf_index; packet->cp_partial = true; - } else if (packet->is_data_pkt && pktlen + net_device->pkt_align < + } else if ((skb != NULL) && pktlen + net_device->pkt_align < net_device->send_section_size) { section_index = netvsc_get_next_send_section(net_device); if (section_index != NETVSC_INVALID_INDEX) { @@ -894,7 +896,7 @@ int netvsc_send(struct hv_device *device, if (section_index != NETVSC_INVALID_INDEX) { netvsc_copy_to_send_buf(net_device, section_index, msd_len, - packet, rndis_msg, pb); + packet, rndis_msg, pb, skb); packet->send_buf_index = section_index; diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index c1078a62a2316..f44e637720bac 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -478,7 +478,6 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) packet->q_idx = skb_get_queue_mapping(skb); - packet->is_data_pkt = true; packet->total_data_buflen = skb->len; rndis_msg = (struct rndis_message *)skb->head; diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c index 53139f7efcb91..0b986743abe63 100644 --- a/drivers/net/hyperv/rndis_filter.c +++ b/drivers/net/hyperv/rndis_filter.c @@ -215,7 +215,6 @@ static int rndis_filter_send_request(struct rndis_device *dev, /* Setup the packet to send it */ packet = &req->pkt; - packet->is_data_pkt = false; packet->total_data_buflen = req->request_msg.msg_len; packet->page_buf_cnt = 1; From a429bda374a640b05a8f949fed080af7512be49a Mon Sep 17 00:00:00 2001 From: KY Srinivasan Date: Tue, 1 Dec 2015 16:43:16 -0800 Subject: [PATCH 14/17] hv_netvsc: Eliminate completion_func from struct hv_netvsc_packet Eliminate completion_func from struct hv_netvsc_packet. Signed-off-by: K. Y. Srinivasan Signed-off-by: David S. Miller --- drivers/net/hyperv/hyperv_net.h | 1 - drivers/net/hyperv/netvsc_drv.c | 3 --- drivers/net/hyperv/rndis_filter.c | 1 - 3 files changed, 5 deletions(-) diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index 2f69e31bc07d6..a613e723d8f71 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h @@ -137,7 +137,6 @@ struct hv_netvsc_packet { u8 rmsg_size; /* RNDIS header and PPI size */ u8 rmsg_pgcnt; /* page count of RNDIS header and PPI */ u8 page_buf_cnt; - u8 completion_func; u16 vlan_tci; u16 q_idx; diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index f44e637720bac..7f4f6c3180714 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -484,9 +484,6 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) memset(rndis_msg, 0, RNDIS_AND_PPI_SIZE); - /* Set the completion routine */ - packet->completion_func = 1; - isvlan = packet->vlan_tci & VLAN_TAG_PRESENT; /* Add the rndis header */ diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c index 0b986743abe63..6ba5adfe93b6d 100644 --- a/drivers/net/hyperv/rndis_filter.c +++ b/drivers/net/hyperv/rndis_filter.c @@ -236,7 +236,6 @@ static int rndis_filter_send_request(struct rndis_device *dev, pb[0].len; } - packet->completion_func = 0; packet->xmit_more = false; ret = netvsc_send(dev->net_dev->dev, packet, NULL, &pb, NULL); From bde79be529c43b5a5a877b3e0b93607d22a8b01e Mon Sep 17 00:00:00 2001 From: KY Srinivasan Date: Tue, 1 Dec 2015 16:43:17 -0800 Subject: [PATCH 15/17] hv_netvsc: Eliminate xmit_more from struct hv_netvsc_packet Eliminate xmit_more from struct hv_netvsc_packet. Signed-off-by: K. Y. Srinivasan Signed-off-by: David S. Miller --- drivers/net/hyperv/hyperv_net.h | 1 - drivers/net/hyperv/netvsc.c | 13 ++++++++----- drivers/net/hyperv/netvsc_drv.c | 1 - drivers/net/hyperv/rndis_filter.c | 2 -- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index a613e723d8f71..22ef86828bd0b 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h @@ -131,7 +131,6 @@ struct ndis_tcp_ip_checksum_info; struct hv_netvsc_packet { /* Bookkeeping stuff */ u8 status; - u8 xmit_more; /* from skb */ u8 cp_partial; /* partial copy into send buffer */ u8 rmsg_size; /* RNDIS header and PPI size */ diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c index 11b009ebb33ff..cd5b65e869ca2 100644 --- a/drivers/net/hyperv/netvsc.c +++ b/drivers/net/hyperv/netvsc.c @@ -712,6 +712,7 @@ static u32 netvsc_copy_to_send_buf(struct netvsc_device *net_device, + pend_size; int i; bool is_data_pkt = (skb != NULL) ? true : false; + bool xmit_more = (skb != NULL) ? skb->xmit_more : false; u32 msg_size = 0; u32 padding = 0; u32 remain = packet->total_data_buflen % net_device->pkt_align; @@ -719,7 +720,7 @@ static u32 netvsc_copy_to_send_buf(struct netvsc_device *net_device, packet->page_buf_cnt; /* Add padding */ - if (is_data_pkt && packet->xmit_more && remain && + if (is_data_pkt && xmit_more && remain && !packet->cp_partial) { padding = net_device->pkt_align - remain; rndis_msg->msg_len += padding; @@ -758,6 +759,7 @@ static inline int netvsc_send_pkt( int ret; struct hv_page_buffer *pgbuf; u32 ring_avail = hv_ringbuf_avail_percent(&out_channel->outbound); + bool xmit_more = (skb != NULL) ? skb->xmit_more : false; nvmsg.hdr.msg_type = NVSP_MSG1_TYPE_SEND_RNDIS_PKT; if (skb != NULL) { @@ -789,7 +791,7 @@ static inline int netvsc_send_pkt( * unnecessarily. */ if (ring_avail < (RING_AVAIL_PERCENT_LOWATER + 1)) - packet->xmit_more = false; + xmit_more = false; if (packet->page_buf_cnt) { pgbuf = packet->cp_partial ? (*pb) + @@ -801,14 +803,14 @@ static inline int netvsc_send_pkt( sizeof(struct nvsp_message), req_id, VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED, - !packet->xmit_more); + !xmit_more); } else { ret = vmbus_sendpacket_ctl(out_channel, &nvmsg, sizeof(struct nvsp_message), req_id, VM_PKT_DATA_INBAND, VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED, - !packet->xmit_more); + !xmit_more); } if (ret == 0) { @@ -854,6 +856,7 @@ int netvsc_send(struct hv_device *device, struct multi_send_data *msdp; struct hv_netvsc_packet *msd_send = NULL, *cur_send = NULL; bool try_batch; + bool xmit_more = (skb != NULL) ? skb->xmit_more : false; net_device = get_outbound_net_device(device); if (!net_device) @@ -911,7 +914,7 @@ int netvsc_send(struct hv_device *device, if (msdp->pkt) dev_kfree_skb_any(skb); - if (packet->xmit_more && !packet->cp_partial) { + if (xmit_more && !packet->cp_partial) { msdp->pkt = packet; msdp->count++; } else { diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 7f4f6c3180714..d97eeb9e144b4 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -472,7 +472,6 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) packet = (struct hv_netvsc_packet *)skb->cb; packet->status = 0; - packet->xmit_more = skb->xmit_more; packet->vlan_tci = skb->vlan_tci; diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c index 6ba5adfe93b6d..3c06aa75ce111 100644 --- a/drivers/net/hyperv/rndis_filter.c +++ b/drivers/net/hyperv/rndis_filter.c @@ -236,8 +236,6 @@ static int rndis_filter_send_request(struct rndis_device *dev, pb[0].len; } - packet->xmit_more = false; - ret = netvsc_send(dev->net_dev->dev, packet, NULL, &pb, NULL); return ret; } From 10082f98878a9dff1563745f9f1dd9d1ff142700 Mon Sep 17 00:00:00 2001 From: KY Srinivasan Date: Tue, 1 Dec 2015 16:43:18 -0800 Subject: [PATCH 16/17] hv_netvsc: Eliminate status from struct hv_netvsc_packet Eliminate status from struct hv_netvsc_packet. Signed-off-by: K. Y. Srinivasan Signed-off-by: David S. Miller --- drivers/net/hyperv/hyperv_net.h | 1 - drivers/net/hyperv/netvsc.c | 6 ++---- drivers/net/hyperv/netvsc_drv.c | 8 ++------ drivers/net/hyperv/rndis_filter.c | 20 +++++++++----------- 4 files changed, 13 insertions(+), 22 deletions(-) diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index 22ef86828bd0b..c4397f1ed43bd 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h @@ -130,7 +130,6 @@ struct ndis_tcp_ip_checksum_info; */ struct hv_netvsc_packet { /* Bookkeeping stuff */ - u8 status; u8 cp_partial; /* partial copy into send buffer */ u8 rmsg_size; /* RNDIS header and PPI size */ diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c index cd5b65e869ca2..02bab9a7c9ff6 100644 --- a/drivers/net/hyperv/netvsc.c +++ b/drivers/net/hyperv/netvsc.c @@ -1045,17 +1045,15 @@ static void netvsc_receive(struct netvsc_device *net_device, /* Each range represents 1 RNDIS pkt that contains 1 ethernet frame */ for (i = 0; i < count; i++) { /* Initialize the netvsc packet */ - netvsc_packet->status = NVSP_STAT_SUCCESS; data = (void *)((unsigned long)net_device-> recv_buf + vmxferpage_packet->ranges[i].byte_offset); netvsc_packet->total_data_buflen = vmxferpage_packet->ranges[i].byte_count; /* Pass it to the upper layer */ - rndis_filter_receive(device, netvsc_packet, &data, channel); + status = rndis_filter_receive(device, netvsc_packet, &data, + channel); - if (netvsc_packet->status != NVSP_STAT_SUCCESS) - status = NVSP_STAT_FAIL; } netvsc_send_recv_completion(device, channel, net_device, diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index d97eeb9e144b4..a34547497d186 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -471,8 +471,6 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) FIELD_SIZEOF(struct sk_buff, cb)); packet = (struct hv_netvsc_packet *)skb->cb; - packet->status = 0; - packet->vlan_tci = skb->vlan_tci; packet->q_idx = skb_get_queue_mapping(skb); @@ -684,8 +682,7 @@ int netvsc_recv_callback(struct hv_device *device_obj, net = ((struct netvsc_device *)hv_get_drvdata(device_obj))->ndev; if (!net || net->reg_state != NETREG_REGISTERED) { - packet->status = NVSP_STAT_FAIL; - return 0; + return NVSP_STAT_FAIL; } net_device_ctx = netdev_priv(net); rx_stats = this_cpu_ptr(net_device_ctx->rx_stats); @@ -694,8 +691,7 @@ int netvsc_recv_callback(struct hv_device *device_obj, skb = netdev_alloc_skb_ip_align(net, packet->total_data_buflen); if (unlikely(!skb)) { ++net->stats.rx_dropped; - packet->status = NVSP_STAT_FAIL; - return 0; + return NVSP_STAT_FAIL; } /* diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c index 3c06aa75ce111..28adf6acf4819 100644 --- a/drivers/net/hyperv/rndis_filter.c +++ b/drivers/net/hyperv/rndis_filter.c @@ -344,7 +344,7 @@ static inline void *rndis_get_ppi(struct rndis_packet *rpkt, u32 type) return NULL; } -static void rndis_filter_receive_data(struct rndis_device *dev, +static int rndis_filter_receive_data(struct rndis_device *dev, struct rndis_message *msg, struct hv_netvsc_packet *pkt, void **data, @@ -371,7 +371,7 @@ static void rndis_filter_receive_data(struct rndis_device *dev, "overflow detected (got %u, min %u)" "...dropping this message!\n", pkt->total_data_buflen, rndis_pkt->data_len); - return; + return NVSP_STAT_FAIL; } /* @@ -391,7 +391,8 @@ static void rndis_filter_receive_data(struct rndis_device *dev, } csum_info = rndis_get_ppi(rndis_pkt, TCPIP_CHKSUM_PKTINFO); - netvsc_recv_callback(dev->net_dev->dev, pkt, data, csum_info, channel); + return netvsc_recv_callback(dev->net_dev->dev, pkt, data, + csum_info, channel); } int rndis_filter_receive(struct hv_device *dev, @@ -406,7 +407,7 @@ int rndis_filter_receive(struct hv_device *dev, int ret = 0; if (!net_dev) { - ret = -EINVAL; + ret = NVSP_STAT_FAIL; goto exit; } @@ -416,7 +417,7 @@ int rndis_filter_receive(struct hv_device *dev, if (!net_dev->extension) { netdev_err(ndev, "got rndis message but no rndis device - " "dropping this message!\n"); - ret = -ENODEV; + ret = NVSP_STAT_FAIL; goto exit; } @@ -424,7 +425,7 @@ int rndis_filter_receive(struct hv_device *dev, if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED) { netdev_err(ndev, "got rndis message but rndis device " "uninitialized...dropping this message!\n"); - ret = -ENODEV; + ret = NVSP_STAT_FAIL; goto exit; } @@ -436,8 +437,8 @@ int rndis_filter_receive(struct hv_device *dev, switch (rndis_msg->ndis_msg_type) { case RNDIS_MSG_PACKET: /* data msg */ - rndis_filter_receive_data(rndis_dev, rndis_msg, pkt, - data, channel); + ret = rndis_filter_receive_data(rndis_dev, rndis_msg, pkt, + data, channel); break; case RNDIS_MSG_INIT_C: @@ -460,9 +461,6 @@ int rndis_filter_receive(struct hv_device *dev, } exit: - if (ret != 0) - pkt->status = NVSP_STAT_FAIL; - return ret; } From 760d1e36cc16fa6444dd2000ac645455de1ecd51 Mon Sep 17 00:00:00 2001 From: KY Srinivasan Date: Tue, 1 Dec 2015 16:43:19 -0800 Subject: [PATCH 17/17] hv_netvsc: Eliminate vlan_tci from struct hv_netvsc_packet Eliminate vlan_tci from struct hv_netvsc_packet. Signed-off-by: K. Y. Srinivasan Signed-off-by: David S. Miller --- drivers/net/hyperv/hyperv_net.h | 4 ++-- drivers/net/hyperv/netvsc_drv.c | 14 +++++++------- drivers/net/hyperv/rndis_filter.c | 7 +++---- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index c4397f1ed43bd..f4130af09244f 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h @@ -136,7 +136,6 @@ struct hv_netvsc_packet { u8 rmsg_pgcnt; /* page count of RNDIS header and PPI */ u8 page_buf_cnt; - u16 vlan_tci; u16 q_idx; u32 send_buf_index; @@ -187,7 +186,8 @@ int netvsc_recv_callback(struct hv_device *device_obj, struct hv_netvsc_packet *packet, void **data, struct ndis_tcp_ip_checksum_info *csum_info, - struct vmbus_channel *channel); + struct vmbus_channel *channel, + u16 vlan_tci); void netvsc_channel_cb(void *context); int rndis_filter_open(struct hv_device *dev); int rndis_filter_close(struct hv_device *dev); diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index a34547497d186..1c8db9afdcda8 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -471,7 +471,6 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) FIELD_SIZEOF(struct sk_buff, cb)); packet = (struct hv_netvsc_packet *)skb->cb; - packet->vlan_tci = skb->vlan_tci; packet->q_idx = skb_get_queue_mapping(skb); @@ -481,7 +480,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) memset(rndis_msg, 0, RNDIS_AND_PPI_SIZE); - isvlan = packet->vlan_tci & VLAN_TAG_PRESENT; + isvlan = skb->vlan_tci & VLAN_TAG_PRESENT; /* Add the rndis header */ rndis_msg->ndis_msg_type = RNDIS_MSG_PACKET; @@ -509,8 +508,8 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) IEEE_8021Q_INFO); vlan = (struct ndis_pkt_8021q_info *)((void *)ppi + ppi->ppi_offset); - vlan->vlanid = packet->vlan_tci & VLAN_VID_MASK; - vlan->pri = (packet->vlan_tci & VLAN_PRIO_MASK) >> + vlan->vlanid = skb->vlan_tci & VLAN_VID_MASK; + vlan->pri = (skb->vlan_tci & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT; } @@ -673,7 +672,8 @@ int netvsc_recv_callback(struct hv_device *device_obj, struct hv_netvsc_packet *packet, void **data, struct ndis_tcp_ip_checksum_info *csum_info, - struct vmbus_channel *channel) + struct vmbus_channel *channel, + u16 vlan_tci) { struct net_device *net; struct net_device_context *net_device_ctx; @@ -713,9 +713,9 @@ int netvsc_recv_callback(struct hv_device *device_obj, skb->ip_summed = CHECKSUM_NONE; } - if (packet->vlan_tci & VLAN_TAG_PRESENT) + if (vlan_tci & VLAN_TAG_PRESENT) __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), - packet->vlan_tci); + vlan_tci); skb_record_rx_queue(skb, channel-> offermsg.offer.sub_channel_index); diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c index 28adf6acf4819..a37bbda37ffa6 100644 --- a/drivers/net/hyperv/rndis_filter.c +++ b/drivers/net/hyperv/rndis_filter.c @@ -354,6 +354,7 @@ static int rndis_filter_receive_data(struct rndis_device *dev, u32 data_offset; struct ndis_pkt_8021q_info *vlan; struct ndis_tcp_ip_checksum_info *csum_info; + u16 vlan_tci = 0; rndis_pkt = &msg->msg.pkt; @@ -384,15 +385,13 @@ static int rndis_filter_receive_data(struct rndis_device *dev, vlan = rndis_get_ppi(rndis_pkt, IEEE_8021Q_INFO); if (vlan) { - pkt->vlan_tci = VLAN_TAG_PRESENT | vlan->vlanid | + vlan_tci = VLAN_TAG_PRESENT | vlan->vlanid | (vlan->pri << VLAN_PRIO_SHIFT); - } else { - pkt->vlan_tci = 0; } csum_info = rndis_get_ppi(rndis_pkt, TCPIP_CHKSUM_PKTINFO); return netvsc_recv_callback(dev->net_dev->dev, pkt, data, - csum_info, channel); + csum_info, channel, vlan_tci); } int rndis_filter_receive(struct hv_device *dev,