diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index 7661a12b00f4..f4130af09244 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h @@ -124,37 +124,22 @@ 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 */ - u32 status; + u8 cp_partial; /* partial copy into send buffer */ - bool is_data_pkt; - bool xmit_more; /* from skb */ - bool 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; u16 q_idx; - 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; - - u32 rmsg_size; /* RNDIS header and PPI size */ - u32 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; - struct hv_page_buffer *page_buf; }; struct netvsc_device_info { @@ -187,16 +172,22 @@ 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, + 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, - struct ndis_tcp_ip_checksum_info *csum_info); + void **data, + struct ndis_tcp_ip_checksum_info *csum_info, + 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); @@ -204,12 +195,13 @@ 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, + void **data, + 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 @@ -632,7 +624,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 */ }; @@ -1272,5 +1263,4 @@ struct rndis_message { #define TRANSPORT_INFO_IPV6_TCP ((INFO_IPV6 << 16) | INFO_TCP) #define TRANSPORT_INFO_IPV6_UDP ((INFO_IPV6 << 16) | INFO_UDP) - #endif /* _HYPERV_NET_H */ diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c index 51e4c0fd0a74..02bab9a7c9ff 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; } @@ -610,6 +606,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) { @@ -617,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; @@ -642,18 +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 = nvsc_packet->channel; - nvsc_packet->send_completion(nvsc_packet-> - send_completion_ctx); + channel = incoming_channel; + dev_kfree_skb_any(skb); } num_outstanding_sends = @@ -705,12 +702,17 @@ 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, + 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; + 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; @@ -718,17 +720,17 @@ 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 && 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; } 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; @@ -745,19 +747,22 @@ 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 sk_buff *skb) { struct nvsp_message nvmsg; - struct vmbus_channel *out_channel = packet->channel; 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; 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 (packet->is_data_pkt) { + if (skb != NULL) { /* 0 is RMC_DATA; */ nvmsg.msg.v1_msg.send_rndis_pkt.channel_type = 0; } else { @@ -773,10 +778,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) - req_id = (ulong)packet; - else - req_id = 0; + req_id = (ulong)skb; if (out_channel->rescind) return -ENODEV; @@ -789,11 +791,11 @@ 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 ? 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, @@ -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) { @@ -840,7 +842,10 @@ 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 hv_page_buffer **pb, + struct sk_buff *skb) { struct netvsc_device *net_device; int ret = 0, m_ret = 0; @@ -848,33 +853,27 @@ 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; + bool xmit_more = (skb != NULL) ? skb->xmit_more : false; net_device = get_outbound_net_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; + packet->send_buf_index = NETVSC_INVALID_INDEX; packet->cp_partial = false; 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; - 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 < @@ -886,7 +885,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) { @@ -900,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, pb, skb); packet->send_buf_index = section_index; @@ -913,9 +912,9 @@ 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) { + if (xmit_more && !packet->cp_partial) { msdp->pkt = packet; msdp->count++; } else { @@ -930,20 +929,18 @@ 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); + 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); + 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); @@ -1009,6 +1006,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; @@ -1043,22 +1041,19 @@ 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++) { /* 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); + 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, @@ -1150,6 +1145,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 268a05821d46..1c8db9afdcda 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -273,19 +273,12 @@ 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; } -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) { @@ -321,9 +314,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; @@ -433,8 +427,8 @@ 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 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 @@ -461,42 +455,34 @@ 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; - - packet->vlan_tci = skb->vlan_tci; - packet->page_buf = page_buf; packet->q_idx = skb_get_queue_mapping(skb); - packet->is_data_pkt = true; packet->total_data_buflen = skb->len; - packet->rndis_msg = (struct rndis_message *)((unsigned long)packet + - sizeof(struct hv_netvsc_packet)); + rndis_msg = (struct rndis_message *)skb->head; - 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; - packet->send_completion_ctx = packet; - packet->send_completion_tid = (unsigned long)skb; - - isvlan = packet->vlan_tci & VLAN_TAG_PRESENT; + isvlan = skb->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; @@ -522,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; } @@ -618,9 +604,10 @@ 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); + ret = netvsc_send(net_device_ctx->device_ctx, packet, + rndis_msg, &pb, skb); drop: if (ret == 0) { @@ -683,7 +670,10 @@ 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) + void **data, + struct ndis_tcp_ip_checksum_info *csum_info, + struct vmbus_channel *channel, + u16 vlan_tci) { struct net_device *net; struct net_device_context *net_device_ctx; @@ -692,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); @@ -702,15 +691,14 @@ 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; } /* * 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); @@ -725,11 +713,11 @@ 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, packet->channel-> + skb_record_rx_queue(skb, channel-> offermsg.offer.sub_channel_index); u64_stats_update_begin(&rx_stats->syncp); @@ -1118,16 +1106,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 +1150,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/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c index 5931a799aa17..a37bbda37ffa 100644 --- a/drivers/net/hyperv/rndis_filter.c +++ b/drivers/net/hyperv/rndis_filter.c @@ -210,37 +210,33 @@ 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; - 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->send_completion = NULL; - packet->xmit_more = false; - - ret = netvsc_send(dev->net_dev->dev, packet); + ret = netvsc_send(dev->net_dev->dev, packet, NULL, &pb, NULL); return ret; } @@ -348,14 +344,17 @@ 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) + struct hv_netvsc_packet *pkt, + void **data, + struct vmbus_channel *channel) { struct rndis_packet *rndis_pkt; 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; @@ -373,7 +372,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; } /* @@ -382,22 +381,23 @@ 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) { - 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); - netvsc_recv_callback(dev->net_dev->dev, pkt, csum_info); + return netvsc_recv_callback(dev->net_dev->dev, pkt, data, + csum_info, channel, vlan_tci); } int rndis_filter_receive(struct hv_device *dev, - struct hv_netvsc_packet *pkt) + struct hv_netvsc_packet *pkt, + void **data, + struct vmbus_channel *channel) { struct netvsc_device *net_dev = hv_get_drvdata(dev); struct rndis_device *rndis_dev; @@ -406,7 +406,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 +416,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,11 +424,11 @@ 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; } - rndis_msg = pkt->data; + rndis_msg = *data; if (netif_msg_rx_err(net_dev->nd_ctx)) dump_rndis_message(dev, rndis_msg); @@ -436,7 +436,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); + ret = rndis_filter_receive_data(rndis_dev, rndis_msg, pkt, + data, channel); break; case RNDIS_MSG_INIT_C: @@ -459,9 +460,6 @@ int rndis_filter_receive(struct hv_device *dev, } exit: - if (ret != 0) - pkt->status = NVSP_STAT_FAIL; - return ret; } diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 7d2d1d7aaec7..fcbc5259c630 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