hyperv: Report actual status in receive completion packet
authorHaiyang Zhang <haiyangz@microsoft.com>
Tue, 2 Oct 2012 05:30:23 +0000 (05:30 +0000)
committerDavid S. Miller <davem@davemloft.net>
Tue, 2 Oct 2012 18:39:31 +0000 (14:39 -0400)
The existing code always reports NVSP_STAT_SUCCESS. This patch adds the
mechanism to report failure when it happens.

Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Reviewed-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/hyperv/hyperv_net.h
drivers/net/hyperv/netvsc.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/hyperv/rndis_filter.c

index d58f28c463862a4a5bf89fa1d014d6ff485eb9b5..5fd6f4674326f0d3236ae8a97127b842ffffa008 100644 (file)
@@ -35,6 +35,7 @@ struct hv_netvsc_packet;
 /* Represent the xfer page packet which contains 1 or more netvsc packet */
 struct xferpage_packet {
        struct list_head list_ent;
+       u32 status;
 
        /* # of netvsc packets this xfer packet contains */
        u32 count;
@@ -47,6 +48,7 @@ struct xferpage_packet {
 struct hv_netvsc_packet {
        /* Bookkeeping stuff */
        struct list_head list_ent;
+       u32 status;
 
        struct hv_device *device;
        bool is_data_pkt;
index d9c4c0399c88d9a9d6034f35cc67a1ba138a713c..1cd77483da50114c2c309ab70a69dff134c3a919 100644 (file)
@@ -558,7 +558,7 @@ int netvsc_send(struct hv_device *device,
 }
 
 static void netvsc_send_recv_completion(struct hv_device *device,
-                                       u64 transaction_id)
+                                       u64 transaction_id, u32 status)
 {
        struct nvsp_message recvcompMessage;
        int retries = 0;
@@ -571,9 +571,7 @@ static void netvsc_send_recv_completion(struct hv_device *device,
        recvcompMessage.hdr.msg_type =
                                NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE;
 
-       /* FIXME: Pass in the status */
-       recvcompMessage.msg.v1_msg.send_rndis_pkt_complete.status =
-               NVSP_STAT_SUCCESS;
+       recvcompMessage.msg.v1_msg.send_rndis_pkt_complete.status = status;
 
 retry_send_cmplt:
        /* Send the completion */
@@ -613,6 +611,7 @@ static void netvsc_receive_completion(void *context)
        bool fsend_receive_comp = false;
        unsigned long flags;
        struct net_device *ndev;
+       u32 status = NVSP_STAT_NONE;
 
        /*
         * Even though it seems logical to do a GetOutboundNetDevice() here to
@@ -627,6 +626,9 @@ static void netvsc_receive_completion(void *context)
        /* Overloading use of the lock. */
        spin_lock_irqsave(&net_device->recv_pkt_list_lock, flags);
 
+       if (packet->status != NVSP_STAT_SUCCESS)
+               packet->xfer_page_pkt->status = NVSP_STAT_FAIL;
+
        packet->xfer_page_pkt->count--;
 
        /*
@@ -636,6 +638,7 @@ static void netvsc_receive_completion(void *context)
        if (packet->xfer_page_pkt->count == 0) {
                fsend_receive_comp = true;
                transaction_id = packet->completion.recv.recv_completion_tid;
+               status = packet->xfer_page_pkt->status;
                list_add_tail(&packet->xfer_page_pkt->list_ent,
                              &net_device->recv_pkt_list);
 
@@ -647,7 +650,7 @@ static void netvsc_receive_completion(void *context)
 
        /* Send a receive completion for the xfer page packet */
        if (fsend_receive_comp)
-               netvsc_send_recv_completion(device, transaction_id);
+               netvsc_send_recv_completion(device, transaction_id, status);
 
 }
 
@@ -736,7 +739,8 @@ static void netvsc_receive(struct hv_device *device,
                                       flags);
 
                netvsc_send_recv_completion(device,
-                                           vmxferpage_packet->d.trans_id);
+                                           vmxferpage_packet->d.trans_id,
+                                           NVSP_STAT_FAIL);
 
                return;
        }
@@ -744,6 +748,7 @@ static void netvsc_receive(struct hv_device *device,
        /* Remove the 1st packet to represent the xfer page packet itself */
        xferpage_packet = (struct xferpage_packet *)listHead.next;
        list_del(&xferpage_packet->list_ent);
+       xferpage_packet->status = NVSP_STAT_SUCCESS;
 
        /* This is how much we can satisfy */
        xferpage_packet->count = count - 1;
@@ -760,6 +765,7 @@ static void netvsc_receive(struct hv_device *device,
                list_del(&netvsc_packet->list_ent);
 
                /* Initialize the netvsc packet */
+               netvsc_packet->status = NVSP_STAT_SUCCESS;
                netvsc_packet->xfer_page_pkt = xferpage_packet;
                netvsc_packet->completion.recv.recv_completion =
                                        netvsc_receive_completion;
index e91111a656f715b77398e1208208f4b0ab5644a8..f825a629a699cfe5fac73803353da4b47ca18974 100644 (file)
@@ -265,6 +265,7 @@ int netvsc_recv_callback(struct hv_device *device_obj,
        if (!net) {
                netdev_err(net, "got receive callback but net device"
                        " not initialized yet\n");
+               packet->status = NVSP_STAT_FAIL;
                return 0;
        }
 
@@ -272,6 +273,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;
        }
 
index f25f41e1fdb794d9f9197b6dea1f4caa7cf9a3d8..e7e12cfbbf379a69836b6778c17abef9bc82a601 100644 (file)
@@ -411,9 +411,12 @@ int rndis_filter_receive(struct hv_device *dev,
        struct rndis_device *rndis_dev;
        struct rndis_message *rndis_msg;
        struct net_device *ndev;
+       int ret = 0;
 
-       if (!net_dev)
-               return -EINVAL;
+       if (!net_dev) {
+               ret = -EINVAL;
+               goto exit;
+       }
 
        ndev = net_dev->ndev;
 
@@ -421,14 +424,16 @@ 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");
-               return -ENODEV;
+               ret = -ENODEV;
+               goto exit;
        }
 
        rndis_dev = (struct rndis_device *)net_dev->extension;
        if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED) {
                netdev_err(ndev, "got rndis message but rndis device "
                           "uninitialized...dropping this message!\n");
-               return -ENODEV;
+               ret = -ENODEV;
+               goto exit;
        }
 
        rndis_msg = pkt->data;
@@ -460,7 +465,11 @@ int rndis_filter_receive(struct hv_device *dev,
                break;
        }
 
-       return 0;
+exit:
+       if (ret != 0)
+               pkt->status = NVSP_STAT_FAIL;
+
+       return ret;
 }
 
 static int rndis_filter_query_device(struct rndis_device *dev, u32 oid,