Loading drivers/net/hyperv/hyperv_net.h +1 −6 Original line number Diff line number Diff line Loading @@ -73,7 +73,7 @@ struct hv_netvsc_packet { } completion; /* This points to the memory after page_buf */ void *extension; struct rndis_message *rndis_msg; u32 total_data_buflen; /* Points to the send/receive buffer where the ethernet frame is */ Loading Loading @@ -126,11 +126,6 @@ void rndis_filter_device_remove(struct hv_device *dev); int rndis_filter_receive(struct hv_device *dev, struct hv_netvsc_packet *pkt); int rndis_filter_send(struct hv_device *dev, struct hv_netvsc_packet *pkt); 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); Loading drivers/net/hyperv/netvsc_drv.c +70 −18 Original line number Diff line number Diff line Loading @@ -128,6 +128,27 @@ static int netvsc_close(struct net_device *net) return ret; } static void *init_ppi_data(struct rndis_message *msg, u32 ppi_size, int pkt_type) { struct rndis_packet *rndis_pkt; struct rndis_per_packet_info *ppi; rndis_pkt = &msg->msg.pkt; rndis_pkt->data_offset += ppi_size; ppi = (struct rndis_per_packet_info *)((void *)rndis_pkt + rndis_pkt->per_pkt_info_offset + rndis_pkt->per_pkt_info_len); ppi->size = ppi_size; ppi->type = pkt_type; ppi->ppi_offset = sizeof(struct rndis_per_packet_info); rndis_pkt->per_pkt_info_len += ppi_size; return ppi; } static void netvsc_xmit_completion(void *context) { struct hv_netvsc_packet *packet = (struct hv_netvsc_packet *)context; Loading Loading @@ -174,7 +195,7 @@ static u32 fill_pg_buf(struct page *page, u32 offset, u32 len, return j + 1; } static void init_page_array(void *hdr, u32 len, struct sk_buff *skb, static u32 init_page_array(void *hdr, u32 len, struct sk_buff *skb, struct hv_page_buffer *pb) { u32 slots_used = 0; Loading Loading @@ -203,6 +224,7 @@ static void init_page_array(void *hdr, u32 len, struct sk_buff *skb, frag->page_offset, skb_frag_size(frag), &pb[slots_used]); } return slots_used; } static int count_skb_frag_slots(struct sk_buff *skb) Loading Loading @@ -240,14 +262,19 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) struct net_device_context *net_device_ctx = netdev_priv(net); struct hv_netvsc_packet *packet; int ret; unsigned int num_data_pages; unsigned int num_data_pgs; struct rndis_message *rndis_msg; struct rndis_packet *rndis_pkt; u32 rndis_msg_size; bool isvlan; struct rndis_per_packet_info *ppi; /* We will atmost need two pages to describe the rndis * header. We can only transmit MAX_PAGE_BUFFER_COUNT number * of pages in a single packet. */ num_data_pages = netvsc_get_slots(skb) + 2; if (num_data_pages > MAX_PAGE_BUFFER_COUNT) { num_data_pgs = netvsc_get_slots(skb) + 2; if (num_data_pgs > MAX_PAGE_BUFFER_COUNT) { netdev_err(net, "Packet too big: %u\n", skb->len); dev_kfree_skb(skb); net->stats.tx_dropped++; Loading @@ -256,7 +283,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) /* Allocate a netvsc packet based on # of frags. */ packet = kzalloc(sizeof(struct hv_netvsc_packet) + (num_data_pages * sizeof(struct hv_page_buffer)) + (num_data_pgs * sizeof(struct hv_page_buffer)) + sizeof(struct rndis_message) + NDIS_VLAN_PPI_SIZE, GFP_ATOMIC); if (!packet) { Loading @@ -270,26 +297,51 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) packet->vlan_tci = skb->vlan_tci; packet->extension = (void *)(unsigned long)packet + sizeof(struct hv_netvsc_packet) + (num_data_pages * sizeof(struct hv_page_buffer)); /* If the rndis msg goes beyond 1 page, we will add 1 later */ packet->page_buf_cnt = num_data_pages - 1; /* Initialize it from the skb */ packet->is_data_pkt = true; packet->total_data_buflen = skb->len; /* Start filling in the page buffers starting after RNDIS buffer. */ init_page_array(NULL, 0, skb, &packet->page_buf[1]); packet->rndis_msg = (struct rndis_message *)((unsigned long)packet + sizeof(struct hv_netvsc_packet) + (num_data_pgs * sizeof(struct hv_page_buffer))); /* Set the completion routine */ packet->completion.send.send_completion = netvsc_xmit_completion; packet->completion.send.send_completion_ctx = packet; packet->completion.send.send_completion_tid = (unsigned long)skb; ret = rndis_filter_send(net_device_ctx->device_ctx, packet); 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; rndis_pkt->data_offset = sizeof(struct rndis_packet); rndis_pkt->data_len = packet->total_data_buflen; rndis_pkt->per_pkt_info_offset = sizeof(struct rndis_packet); rndis_msg_size = RNDIS_MESSAGE_SIZE(struct rndis_packet); if (isvlan) { struct ndis_pkt_8021q_info *vlan; rndis_msg_size += NDIS_VLAN_PPI_SIZE; ppi = init_ppi_data(rndis_msg, NDIS_VLAN_PPI_SIZE, 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_PRIO_SHIFT; } /* Start filling in the page buffers with the rndis hdr */ rndis_msg->msg_len += rndis_msg_size; packet->page_buf_cnt = init_page_array(rndis_msg, rndis_msg_size, skb, &packet->page_buf[0]); ret = netvsc_send(net_device_ctx->device_ctx, packet); if (ret == 0) { net->stats.tx_bytes += skb->len; net->stats.tx_packets++; Loading drivers/net/hyperv/rndis_filter.c +0 −66 Original line number Diff line number Diff line Loading @@ -891,69 +891,3 @@ int rndis_filter_close(struct hv_device *dev) return rndis_filter_close_device(nvdev->extension); } int rndis_filter_send(struct hv_device *dev, struct hv_netvsc_packet *pkt) { struct rndis_message *rndis_msg; struct rndis_packet *rndis_pkt; u32 rndis_msg_size; bool isvlan = pkt->vlan_tci & VLAN_TAG_PRESENT; /* Add the rndis header */ rndis_msg = (struct rndis_message *)pkt->extension; rndis_msg_size = RNDIS_MESSAGE_SIZE(struct rndis_packet); if (isvlan) rndis_msg_size += NDIS_VLAN_PPI_SIZE; rndis_msg->ndis_msg_type = RNDIS_MSG_PACKET; rndis_msg->msg_len = pkt->total_data_buflen + rndis_msg_size; rndis_pkt = &rndis_msg->msg.pkt; rndis_pkt->data_offset = sizeof(struct rndis_packet); if (isvlan) rndis_pkt->data_offset += NDIS_VLAN_PPI_SIZE; rndis_pkt->data_len = pkt->total_data_buflen; if (isvlan) { struct rndis_per_packet_info *ppi; struct ndis_pkt_8021q_info *vlan; rndis_pkt->per_pkt_info_offset = sizeof(struct rndis_packet); rndis_pkt->per_pkt_info_len = NDIS_VLAN_PPI_SIZE; ppi = (struct rndis_per_packet_info *)((ulong)rndis_pkt + rndis_pkt->per_pkt_info_offset); ppi->size = NDIS_VLAN_PPI_SIZE; ppi->type = IEEE_8021Q_INFO; ppi->ppi_offset = sizeof(struct rndis_per_packet_info); vlan = (struct ndis_pkt_8021q_info *)((ulong)ppi + ppi->ppi_offset); vlan->vlanid = pkt->vlan_tci & VLAN_VID_MASK; vlan->pri = (pkt->vlan_tci & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT; } pkt->is_data_pkt = true; pkt->page_buf[0].pfn = virt_to_phys(rndis_msg) >> PAGE_SHIFT; pkt->page_buf[0].offset = (unsigned long)rndis_msg & (PAGE_SIZE-1); pkt->page_buf[0].len = rndis_msg_size; /* Add one page_buf if the rndis msg goes beyond page boundary */ if (pkt->page_buf[0].offset + rndis_msg_size > PAGE_SIZE) { int i; for (i = pkt->page_buf_cnt; i > 1; i--) pkt->page_buf[i] = pkt->page_buf[i-1]; pkt->page_buf_cnt++; pkt->page_buf[0].len = PAGE_SIZE - pkt->page_buf[0].offset; pkt->page_buf[1].pfn = virt_to_phys((void *)((ulong) rndis_msg + pkt->page_buf[0].len)) >> PAGE_SHIFT; pkt->page_buf[1].offset = 0; pkt->page_buf[1].len = rndis_msg_size - pkt->page_buf[0].len; } return netvsc_send(dev, pkt); } Loading
drivers/net/hyperv/hyperv_net.h +1 −6 Original line number Diff line number Diff line Loading @@ -73,7 +73,7 @@ struct hv_netvsc_packet { } completion; /* This points to the memory after page_buf */ void *extension; struct rndis_message *rndis_msg; u32 total_data_buflen; /* Points to the send/receive buffer where the ethernet frame is */ Loading Loading @@ -126,11 +126,6 @@ void rndis_filter_device_remove(struct hv_device *dev); int rndis_filter_receive(struct hv_device *dev, struct hv_netvsc_packet *pkt); int rndis_filter_send(struct hv_device *dev, struct hv_netvsc_packet *pkt); 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); Loading
drivers/net/hyperv/netvsc_drv.c +70 −18 Original line number Diff line number Diff line Loading @@ -128,6 +128,27 @@ static int netvsc_close(struct net_device *net) return ret; } static void *init_ppi_data(struct rndis_message *msg, u32 ppi_size, int pkt_type) { struct rndis_packet *rndis_pkt; struct rndis_per_packet_info *ppi; rndis_pkt = &msg->msg.pkt; rndis_pkt->data_offset += ppi_size; ppi = (struct rndis_per_packet_info *)((void *)rndis_pkt + rndis_pkt->per_pkt_info_offset + rndis_pkt->per_pkt_info_len); ppi->size = ppi_size; ppi->type = pkt_type; ppi->ppi_offset = sizeof(struct rndis_per_packet_info); rndis_pkt->per_pkt_info_len += ppi_size; return ppi; } static void netvsc_xmit_completion(void *context) { struct hv_netvsc_packet *packet = (struct hv_netvsc_packet *)context; Loading Loading @@ -174,7 +195,7 @@ static u32 fill_pg_buf(struct page *page, u32 offset, u32 len, return j + 1; } static void init_page_array(void *hdr, u32 len, struct sk_buff *skb, static u32 init_page_array(void *hdr, u32 len, struct sk_buff *skb, struct hv_page_buffer *pb) { u32 slots_used = 0; Loading Loading @@ -203,6 +224,7 @@ static void init_page_array(void *hdr, u32 len, struct sk_buff *skb, frag->page_offset, skb_frag_size(frag), &pb[slots_used]); } return slots_used; } static int count_skb_frag_slots(struct sk_buff *skb) Loading Loading @@ -240,14 +262,19 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) struct net_device_context *net_device_ctx = netdev_priv(net); struct hv_netvsc_packet *packet; int ret; unsigned int num_data_pages; unsigned int num_data_pgs; struct rndis_message *rndis_msg; struct rndis_packet *rndis_pkt; u32 rndis_msg_size; bool isvlan; struct rndis_per_packet_info *ppi; /* We will atmost need two pages to describe the rndis * header. We can only transmit MAX_PAGE_BUFFER_COUNT number * of pages in a single packet. */ num_data_pages = netvsc_get_slots(skb) + 2; if (num_data_pages > MAX_PAGE_BUFFER_COUNT) { num_data_pgs = netvsc_get_slots(skb) + 2; if (num_data_pgs > MAX_PAGE_BUFFER_COUNT) { netdev_err(net, "Packet too big: %u\n", skb->len); dev_kfree_skb(skb); net->stats.tx_dropped++; Loading @@ -256,7 +283,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) /* Allocate a netvsc packet based on # of frags. */ packet = kzalloc(sizeof(struct hv_netvsc_packet) + (num_data_pages * sizeof(struct hv_page_buffer)) + (num_data_pgs * sizeof(struct hv_page_buffer)) + sizeof(struct rndis_message) + NDIS_VLAN_PPI_SIZE, GFP_ATOMIC); if (!packet) { Loading @@ -270,26 +297,51 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) packet->vlan_tci = skb->vlan_tci; packet->extension = (void *)(unsigned long)packet + sizeof(struct hv_netvsc_packet) + (num_data_pages * sizeof(struct hv_page_buffer)); /* If the rndis msg goes beyond 1 page, we will add 1 later */ packet->page_buf_cnt = num_data_pages - 1; /* Initialize it from the skb */ packet->is_data_pkt = true; packet->total_data_buflen = skb->len; /* Start filling in the page buffers starting after RNDIS buffer. */ init_page_array(NULL, 0, skb, &packet->page_buf[1]); packet->rndis_msg = (struct rndis_message *)((unsigned long)packet + sizeof(struct hv_netvsc_packet) + (num_data_pgs * sizeof(struct hv_page_buffer))); /* Set the completion routine */ packet->completion.send.send_completion = netvsc_xmit_completion; packet->completion.send.send_completion_ctx = packet; packet->completion.send.send_completion_tid = (unsigned long)skb; ret = rndis_filter_send(net_device_ctx->device_ctx, packet); 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; rndis_pkt->data_offset = sizeof(struct rndis_packet); rndis_pkt->data_len = packet->total_data_buflen; rndis_pkt->per_pkt_info_offset = sizeof(struct rndis_packet); rndis_msg_size = RNDIS_MESSAGE_SIZE(struct rndis_packet); if (isvlan) { struct ndis_pkt_8021q_info *vlan; rndis_msg_size += NDIS_VLAN_PPI_SIZE; ppi = init_ppi_data(rndis_msg, NDIS_VLAN_PPI_SIZE, 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_PRIO_SHIFT; } /* Start filling in the page buffers with the rndis hdr */ rndis_msg->msg_len += rndis_msg_size; packet->page_buf_cnt = init_page_array(rndis_msg, rndis_msg_size, skb, &packet->page_buf[0]); ret = netvsc_send(net_device_ctx->device_ctx, packet); if (ret == 0) { net->stats.tx_bytes += skb->len; net->stats.tx_packets++; Loading
drivers/net/hyperv/rndis_filter.c +0 −66 Original line number Diff line number Diff line Loading @@ -891,69 +891,3 @@ int rndis_filter_close(struct hv_device *dev) return rndis_filter_close_device(nvdev->extension); } int rndis_filter_send(struct hv_device *dev, struct hv_netvsc_packet *pkt) { struct rndis_message *rndis_msg; struct rndis_packet *rndis_pkt; u32 rndis_msg_size; bool isvlan = pkt->vlan_tci & VLAN_TAG_PRESENT; /* Add the rndis header */ rndis_msg = (struct rndis_message *)pkt->extension; rndis_msg_size = RNDIS_MESSAGE_SIZE(struct rndis_packet); if (isvlan) rndis_msg_size += NDIS_VLAN_PPI_SIZE; rndis_msg->ndis_msg_type = RNDIS_MSG_PACKET; rndis_msg->msg_len = pkt->total_data_buflen + rndis_msg_size; rndis_pkt = &rndis_msg->msg.pkt; rndis_pkt->data_offset = sizeof(struct rndis_packet); if (isvlan) rndis_pkt->data_offset += NDIS_VLAN_PPI_SIZE; rndis_pkt->data_len = pkt->total_data_buflen; if (isvlan) { struct rndis_per_packet_info *ppi; struct ndis_pkt_8021q_info *vlan; rndis_pkt->per_pkt_info_offset = sizeof(struct rndis_packet); rndis_pkt->per_pkt_info_len = NDIS_VLAN_PPI_SIZE; ppi = (struct rndis_per_packet_info *)((ulong)rndis_pkt + rndis_pkt->per_pkt_info_offset); ppi->size = NDIS_VLAN_PPI_SIZE; ppi->type = IEEE_8021Q_INFO; ppi->ppi_offset = sizeof(struct rndis_per_packet_info); vlan = (struct ndis_pkt_8021q_info *)((ulong)ppi + ppi->ppi_offset); vlan->vlanid = pkt->vlan_tci & VLAN_VID_MASK; vlan->pri = (pkt->vlan_tci & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT; } pkt->is_data_pkt = true; pkt->page_buf[0].pfn = virt_to_phys(rndis_msg) >> PAGE_SHIFT; pkt->page_buf[0].offset = (unsigned long)rndis_msg & (PAGE_SIZE-1); pkt->page_buf[0].len = rndis_msg_size; /* Add one page_buf if the rndis msg goes beyond page boundary */ if (pkt->page_buf[0].offset + rndis_msg_size > PAGE_SIZE) { int i; for (i = pkt->page_buf_cnt; i > 1; i--) pkt->page_buf[i] = pkt->page_buf[i-1]; pkt->page_buf_cnt++; pkt->page_buf[0].len = PAGE_SIZE - pkt->page_buf[0].offset; pkt->page_buf[1].pfn = virt_to_phys((void *)((ulong) rndis_msg + pkt->page_buf[0].len)) >> PAGE_SHIFT; pkt->page_buf[1].offset = 0; pkt->page_buf[1].len = rndis_msg_size - pkt->page_buf[0].len; } return netvsc_send(dev, pkt); }