In preparation for enabling offloads, cleanup the send path.

Signed-off-by: K. Y. Srinivasan <k...@microsoft.com>
Reviewed-by: Haiyang Zhang <haiya...@microsoft.com>
---
 drivers/net/hyperv/hyperv_net.h   |    7 +---
 drivers/net/hyperv/netvsc_drv.c   |   87 +++++++++++++++++++++++++++++-------
 drivers/net/hyperv/rndis_filter.c |   66 ----------------------------
 3 files changed, 71 insertions(+), 89 deletions(-)

diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index 39fc230..694bf7c 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -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 */
@@ -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);
 
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index afa9c53..e812529 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -128,6 +128,28 @@ 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 *)((ulong)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;
@@ -173,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;
@@ -204,6 +226,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)
@@ -241,15 +264,20 @@ 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++;
@@ -258,7 +286,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) {
@@ -272,26 +300,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 *)((ulong)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++;
diff --git a/drivers/net/hyperv/rndis_filter.c 
b/drivers/net/hyperv/rndis_filter.c
index 6a9f602..dcbf144e 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -910,69 +910,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);
-}
-- 
1.7.4.1

_______________________________________________
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

Reply via email to