Commit 63f6921d authored by Haiyang Zhang's avatar Haiyang Zhang Committed by David S. Miller

hyperv: Report actual status in receive completion packet

The existing code always reports NVSP_STAT_SUCCESS. This patch adds the
mechanism to report failure when it happens.
Signed-off-by: default avatarHaiyang Zhang <haiyangz@microsoft.com>
Reviewed-by: default avatarK. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6562640b
...@@ -35,6 +35,7 @@ struct hv_netvsc_packet; ...@@ -35,6 +35,7 @@ struct hv_netvsc_packet;
/* Represent the xfer page packet which contains 1 or more netvsc packet */ /* Represent the xfer page packet which contains 1 or more netvsc packet */
struct xferpage_packet { struct xferpage_packet {
struct list_head list_ent; struct list_head list_ent;
u32 status;
/* # of netvsc packets this xfer packet contains */ /* # of netvsc packets this xfer packet contains */
u32 count; u32 count;
...@@ -47,6 +48,7 @@ struct xferpage_packet { ...@@ -47,6 +48,7 @@ struct xferpage_packet {
struct hv_netvsc_packet { struct hv_netvsc_packet {
/* Bookkeeping stuff */ /* Bookkeeping stuff */
struct list_head list_ent; struct list_head list_ent;
u32 status;
struct hv_device *device; struct hv_device *device;
bool is_data_pkt; bool is_data_pkt;
......
...@@ -558,7 +558,7 @@ int netvsc_send(struct hv_device *device, ...@@ -558,7 +558,7 @@ int netvsc_send(struct hv_device *device,
} }
static void netvsc_send_recv_completion(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; struct nvsp_message recvcompMessage;
int retries = 0; int retries = 0;
...@@ -571,9 +571,7 @@ static void netvsc_send_recv_completion(struct hv_device *device, ...@@ -571,9 +571,7 @@ static void netvsc_send_recv_completion(struct hv_device *device,
recvcompMessage.hdr.msg_type = recvcompMessage.hdr.msg_type =
NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE; NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE;
/* FIXME: Pass in the status */ recvcompMessage.msg.v1_msg.send_rndis_pkt_complete.status = status;
recvcompMessage.msg.v1_msg.send_rndis_pkt_complete.status =
NVSP_STAT_SUCCESS;
retry_send_cmplt: retry_send_cmplt:
/* Send the completion */ /* Send the completion */
...@@ -613,6 +611,7 @@ static void netvsc_receive_completion(void *context) ...@@ -613,6 +611,7 @@ static void netvsc_receive_completion(void *context)
bool fsend_receive_comp = false; bool fsend_receive_comp = false;
unsigned long flags; unsigned long flags;
struct net_device *ndev; struct net_device *ndev;
u32 status = NVSP_STAT_NONE;
/* /*
* Even though it seems logical to do a GetOutboundNetDevice() here to * Even though it seems logical to do a GetOutboundNetDevice() here to
...@@ -627,6 +626,9 @@ static void netvsc_receive_completion(void *context) ...@@ -627,6 +626,9 @@ static void netvsc_receive_completion(void *context)
/* Overloading use of the lock. */ /* Overloading use of the lock. */
spin_lock_irqsave(&net_device->recv_pkt_list_lock, flags); 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--; packet->xfer_page_pkt->count--;
/* /*
...@@ -636,6 +638,7 @@ static void netvsc_receive_completion(void *context) ...@@ -636,6 +638,7 @@ static void netvsc_receive_completion(void *context)
if (packet->xfer_page_pkt->count == 0) { if (packet->xfer_page_pkt->count == 0) {
fsend_receive_comp = true; fsend_receive_comp = true;
transaction_id = packet->completion.recv.recv_completion_tid; transaction_id = packet->completion.recv.recv_completion_tid;
status = packet->xfer_page_pkt->status;
list_add_tail(&packet->xfer_page_pkt->list_ent, list_add_tail(&packet->xfer_page_pkt->list_ent,
&net_device->recv_pkt_list); &net_device->recv_pkt_list);
...@@ -647,7 +650,7 @@ static void netvsc_receive_completion(void *context) ...@@ -647,7 +650,7 @@ static void netvsc_receive_completion(void *context)
/* Send a receive completion for the xfer page packet */ /* Send a receive completion for the xfer page packet */
if (fsend_receive_comp) 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, ...@@ -736,7 +739,8 @@ static void netvsc_receive(struct hv_device *device,
flags); flags);
netvsc_send_recv_completion(device, netvsc_send_recv_completion(device,
vmxferpage_packet->d.trans_id); vmxferpage_packet->d.trans_id,
NVSP_STAT_FAIL);
return; return;
} }
...@@ -744,6 +748,7 @@ static void netvsc_receive(struct hv_device *device, ...@@ -744,6 +748,7 @@ static void netvsc_receive(struct hv_device *device,
/* Remove the 1st packet to represent the xfer page packet itself */ /* Remove the 1st packet to represent the xfer page packet itself */
xferpage_packet = (struct xferpage_packet *)listHead.next; xferpage_packet = (struct xferpage_packet *)listHead.next;
list_del(&xferpage_packet->list_ent); list_del(&xferpage_packet->list_ent);
xferpage_packet->status = NVSP_STAT_SUCCESS;
/* This is how much we can satisfy */ /* This is how much we can satisfy */
xferpage_packet->count = count - 1; xferpage_packet->count = count - 1;
...@@ -760,6 +765,7 @@ static void netvsc_receive(struct hv_device *device, ...@@ -760,6 +765,7 @@ static void netvsc_receive(struct hv_device *device,
list_del(&netvsc_packet->list_ent); list_del(&netvsc_packet->list_ent);
/* Initialize the netvsc packet */ /* Initialize the netvsc packet */
netvsc_packet->status = NVSP_STAT_SUCCESS;
netvsc_packet->xfer_page_pkt = xferpage_packet; netvsc_packet->xfer_page_pkt = xferpage_packet;
netvsc_packet->completion.recv.recv_completion = netvsc_packet->completion.recv.recv_completion =
netvsc_receive_completion; netvsc_receive_completion;
......
...@@ -265,6 +265,7 @@ int netvsc_recv_callback(struct hv_device *device_obj, ...@@ -265,6 +265,7 @@ int netvsc_recv_callback(struct hv_device *device_obj,
if (!net) { if (!net) {
netdev_err(net, "got receive callback but net device" netdev_err(net, "got receive callback but net device"
" not initialized yet\n"); " not initialized yet\n");
packet->status = NVSP_STAT_FAIL;
return 0; return 0;
} }
...@@ -272,6 +273,7 @@ int netvsc_recv_callback(struct hv_device *device_obj, ...@@ -272,6 +273,7 @@ int netvsc_recv_callback(struct hv_device *device_obj,
skb = netdev_alloc_skb_ip_align(net, packet->total_data_buflen); skb = netdev_alloc_skb_ip_align(net, packet->total_data_buflen);
if (unlikely(!skb)) { if (unlikely(!skb)) {
++net->stats.rx_dropped; ++net->stats.rx_dropped;
packet->status = NVSP_STAT_FAIL;
return 0; return 0;
} }
......
...@@ -411,9 +411,12 @@ int rndis_filter_receive(struct hv_device *dev, ...@@ -411,9 +411,12 @@ int rndis_filter_receive(struct hv_device *dev,
struct rndis_device *rndis_dev; struct rndis_device *rndis_dev;
struct rndis_message *rndis_msg; struct rndis_message *rndis_msg;
struct net_device *ndev; struct net_device *ndev;
int ret = 0;
if (!net_dev) if (!net_dev) {
return -EINVAL; ret = -EINVAL;
goto exit;
}
ndev = net_dev->ndev; ndev = net_dev->ndev;
...@@ -421,14 +424,16 @@ int rndis_filter_receive(struct hv_device *dev, ...@@ -421,14 +424,16 @@ int rndis_filter_receive(struct hv_device *dev,
if (!net_dev->extension) { if (!net_dev->extension) {
netdev_err(ndev, "got rndis message but no rndis device - " netdev_err(ndev, "got rndis message but no rndis device - "
"dropping this message!\n"); "dropping this message!\n");
return -ENODEV; ret = -ENODEV;
goto exit;
} }
rndis_dev = (struct rndis_device *)net_dev->extension; rndis_dev = (struct rndis_device *)net_dev->extension;
if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED) { if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED) {
netdev_err(ndev, "got rndis message but rndis device " netdev_err(ndev, "got rndis message but rndis device "
"uninitialized...dropping this message!\n"); "uninitialized...dropping this message!\n");
return -ENODEV; ret = -ENODEV;
goto exit;
} }
rndis_msg = pkt->data; rndis_msg = pkt->data;
...@@ -460,7 +465,11 @@ int rndis_filter_receive(struct hv_device *dev, ...@@ -460,7 +465,11 @@ int rndis_filter_receive(struct hv_device *dev,
break; 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, static int rndis_filter_query_device(struct rndis_device *dev, u32 oid,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment