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: Haiyang Zhang <haiyangz@microsoft.com> Reviewed-by: K. Y. Srinivasan <kys@microsoft.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
6562640bd3
Коммит
63f6921d30
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче