aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/hyperv
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/hyperv')
-rw-r--r--drivers/net/hyperv/hyperv_net.h290
-rw-r--r--drivers/net/hyperv/netvsc.c41
-rw-r--r--drivers/net/hyperv/netvsc_drv.c44
-rw-r--r--drivers/net/hyperv/rndis_filter.c46
4 files changed, 80 insertions, 341 deletions
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index c35824552792..4ffcd57b011b 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -27,6 +27,7 @@
#include <linux/list.h>
#include <linux/hyperv.h>
+#include <linux/rndis.h>
/* Fwd declaration */
struct hv_netvsc_packet;
@@ -506,295 +507,6 @@ struct netvsc_device {
void *extension;
};
-
-/* Status codes */
-
-
-#ifndef STATUS_SUCCESS
-#define STATUS_SUCCESS (0x00000000L)
-#endif
-
-#ifndef STATUS_UNSUCCESSFUL
-#define STATUS_UNSUCCESSFUL (0xC0000001L)
-#endif
-
-#ifndef STATUS_PENDING
-#define STATUS_PENDING (0x00000103L)
-#endif
-
-#ifndef STATUS_INSUFFICIENT_RESOURCES
-#define STATUS_INSUFFICIENT_RESOURCES (0xC000009AL)
-#endif
-
-#ifndef STATUS_BUFFER_OVERFLOW
-#define STATUS_BUFFER_OVERFLOW (0x80000005L)
-#endif
-
-#ifndef STATUS_NOT_SUPPORTED
-#define STATUS_NOT_SUPPORTED (0xC00000BBL)
-#endif
-
-#define RNDIS_STATUS_SUCCESS (STATUS_SUCCESS)
-#define RNDIS_STATUS_PENDING (STATUS_PENDING)
-#define RNDIS_STATUS_NOT_RECOGNIZED (0x00010001L)
-#define RNDIS_STATUS_NOT_COPIED (0x00010002L)
-#define RNDIS_STATUS_NOT_ACCEPTED (0x00010003L)
-#define RNDIS_STATUS_CALL_ACTIVE (0x00010007L)
-
-#define RNDIS_STATUS_ONLINE (0x40010003L)
-#define RNDIS_STATUS_RESET_START (0x40010004L)
-#define RNDIS_STATUS_RESET_END (0x40010005L)
-#define RNDIS_STATUS_RING_STATUS (0x40010006L)
-#define RNDIS_STATUS_CLOSED (0x40010007L)
-#define RNDIS_STATUS_WAN_LINE_UP (0x40010008L)
-#define RNDIS_STATUS_WAN_LINE_DOWN (0x40010009L)
-#define RNDIS_STATUS_WAN_FRAGMENT (0x4001000AL)
-#define RNDIS_STATUS_MEDIA_CONNECT (0x4001000BL)
-#define RNDIS_STATUS_MEDIA_DISCONNECT (0x4001000CL)
-#define RNDIS_STATUS_HARDWARE_LINE_UP (0x4001000DL)
-#define RNDIS_STATUS_HARDWARE_LINE_DOWN (0x4001000EL)
-#define RNDIS_STATUS_INTERFACE_UP (0x4001000FL)
-#define RNDIS_STATUS_INTERFACE_DOWN (0x40010010L)
-#define RNDIS_STATUS_MEDIA_BUSY (0x40010011L)
-#define RNDIS_STATUS_MEDIA_SPECIFIC_INDICATION (0x40010012L)
-#define RNDIS_STATUS_WW_INDICATION RDIA_SPECIFIC_INDICATION
-#define RNDIS_STATUS_LINK_SPEED_CHANGE (0x40010013L)
-
-#define RNDIS_STATUS_NOT_RESETTABLE (0x80010001L)
-#define RNDIS_STATUS_SOFT_ERRORS (0x80010003L)
-#define RNDIS_STATUS_HARD_ERRORS (0x80010004L)
-#define RNDIS_STATUS_BUFFER_OVERFLOW (STATUS_BUFFER_OVERFLOW)
-
-#define RNDIS_STATUS_FAILURE (STATUS_UNSUCCESSFUL)
-#define RNDIS_STATUS_RESOURCES (STATUS_INSUFFICIENT_RESOURCES)
-#define RNDIS_STATUS_CLOSING (0xC0010002L)
-#define RNDIS_STATUS_BAD_VERSION (0xC0010004L)
-#define RNDIS_STATUS_BAD_CHARACTERISTICS (0xC0010005L)
-#define RNDIS_STATUS_ADAPTER_NOT_FOUND (0xC0010006L)
-#define RNDIS_STATUS_OPEN_FAILED (0xC0010007L)
-#define RNDIS_STATUS_DEVICE_FAILED (0xC0010008L)
-#define RNDIS_STATUS_MULTICAST_FULL (0xC0010009L)
-#define RNDIS_STATUS_MULTICAST_EXISTS (0xC001000AL)
-#define RNDIS_STATUS_MULTICAST_NOT_FOUND (0xC001000BL)
-#define RNDIS_STATUS_REQUEST_ABORTED (0xC001000CL)
-#define RNDIS_STATUS_RESET_IN_PROGRESS (0xC001000DL)
-#define RNDIS_STATUS_CLOSING_INDICATING (0xC001000EL)
-#define RNDIS_STATUS_NOT_SUPPORTED (STATUS_NOT_SUPPORTED)
-#define RNDIS_STATUS_INVALID_PACKET (0xC001000FL)
-#define RNDIS_STATUS_OPEN_LIST_FULL (0xC0010010L)
-#define RNDIS_STATUS_ADAPTER_NOT_READY (0xC0010011L)
-#define RNDIS_STATUS_ADAPTER_NOT_OPEN (0xC0010012L)
-#define RNDIS_STATUS_NOT_INDICATING (0xC0010013L)
-#define RNDIS_STATUS_INVALID_LENGTH (0xC0010014L)
-#define RNDIS_STATUS_INVALID_DATA (0xC0010015L)
-#define RNDIS_STATUS_BUFFER_TOO_SHORT (0xC0010016L)
-#define RNDIS_STATUS_INVALID_OID (0xC0010017L)
-#define RNDIS_STATUS_ADAPTER_REMOVED (0xC0010018L)
-#define RNDIS_STATUS_UNSUPPORTED_MEDIA (0xC0010019L)
-#define RNDIS_STATUS_GROUP_ADDRESS_IN_USE (0xC001001AL)
-#define RNDIS_STATUS_FILE_NOT_FOUND (0xC001001BL)
-#define RNDIS_STATUS_ERROR_READING_FILE (0xC001001CL)
-#define RNDIS_STATUS_ALREADY_MAPPED (0xC001001DL)
-#define RNDIS_STATUS_RESOURCE_CONFLICT (0xC001001EL)
-#define RNDIS_STATUS_NO_CABLE (0xC001001FL)
-
-#define RNDIS_STATUS_INVALID_SAP (0xC0010020L)
-#define RNDIS_STATUS_SAP_IN_USE (0xC0010021L)
-#define RNDIS_STATUS_INVALID_ADDRESS (0xC0010022L)
-#define RNDIS_STATUS_VC_NOT_ACTIVATED (0xC0010023L)
-#define RNDIS_STATUS_DEST_OUT_OF_ORDER (0xC0010024L)
-#define RNDIS_STATUS_VC_NOT_AVAILABLE (0xC0010025L)
-#define RNDIS_STATUS_CELLRATE_NOT_AVAILABLE (0xC0010026L)
-#define RNDIS_STATUS_INCOMPATABLE_QOS (0xC0010027L)
-#define RNDIS_STATUS_AAL_PARAMS_UNSUPPORTED (0xC0010028L)
-#define RNDIS_STATUS_NO_ROUTE_TO_DESTINATION (0xC0010029L)
-
-#define RNDIS_STATUS_TOKEN_RING_OPEN_ERROR (0xC0011000L)
-
-/* Object Identifiers used by NdisRequest Query/Set Information */
-/* General Objects */
-#define RNDIS_OID_GEN_SUPPORTED_LIST 0x00010101
-#define RNDIS_OID_GEN_HARDWARE_STATUS 0x00010102
-#define RNDIS_OID_GEN_MEDIA_SUPPORTED 0x00010103
-#define RNDIS_OID_GEN_MEDIA_IN_USE 0x00010104
-#define RNDIS_OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105
-#define RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106
-#define RNDIS_OID_GEN_LINK_SPEED 0x00010107
-#define RNDIS_OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108
-#define RNDIS_OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109
-#define RNDIS_OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A
-#define RNDIS_OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B
-#define RNDIS_OID_GEN_VENDOR_ID 0x0001010C
-#define RNDIS_OID_GEN_VENDOR_DESCRIPTION 0x0001010D
-#define RNDIS_OID_GEN_CURRENT_PACKET_FILTER 0x0001010E
-#define RNDIS_OID_GEN_CURRENT_LOOKAHEAD 0x0001010F
-#define RNDIS_OID_GEN_DRIVER_VERSION 0x00010110
-#define RNDIS_OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111
-#define RNDIS_OID_GEN_PROTOCOL_OPTIONS 0x00010112
-#define RNDIS_OID_GEN_MAC_OPTIONS 0x00010113
-#define RNDIS_OID_GEN_MEDIA_CONNECT_STATUS 0x00010114
-#define RNDIS_OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115
-#define RNDIS_OID_GEN_VENDOR_DRIVER_VERSION 0x00010116
-#define RNDIS_OID_GEN_NETWORK_LAYER_ADDRESSES 0x00010118
-#define RNDIS_OID_GEN_TRANSPORT_HEADER_OFFSET 0x00010119
-#define RNDIS_OID_GEN_MACHINE_NAME 0x0001021A
-#define RNDIS_OID_GEN_RNDIS_CONFIG_PARAMETER 0x0001021B
-
-#define RNDIS_OID_GEN_XMIT_OK 0x00020101
-#define RNDIS_OID_GEN_RCV_OK 0x00020102
-#define RNDIS_OID_GEN_XMIT_ERROR 0x00020103
-#define RNDIS_OID_GEN_RCV_ERROR 0x00020104
-#define RNDIS_OID_GEN_RCV_NO_BUFFER 0x00020105
-
-#define RNDIS_OID_GEN_DIRECTED_BYTES_XMIT 0x00020201
-#define RNDIS_OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202
-#define RNDIS_OID_GEN_MULTICAST_BYTES_XMIT 0x00020203
-#define RNDIS_OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204
-#define RNDIS_OID_GEN_BROADCAST_BYTES_XMIT 0x00020205
-#define RNDIS_OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206
-#define RNDIS_OID_GEN_DIRECTED_BYTES_RCV 0x00020207
-#define RNDIS_OID_GEN_DIRECTED_FRAMES_RCV 0x00020208
-#define RNDIS_OID_GEN_MULTICAST_BYTES_RCV 0x00020209
-#define RNDIS_OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A
-#define RNDIS_OID_GEN_BROADCAST_BYTES_RCV 0x0002020B
-#define RNDIS_OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C
-
-#define RNDIS_OID_GEN_RCV_CRC_ERROR 0x0002020D
-#define RNDIS_OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E
-
-#define RNDIS_OID_GEN_GET_TIME_CAPS 0x0002020F
-#define RNDIS_OID_GEN_GET_NETCARD_TIME 0x00020210
-
-/* These are connection-oriented general OIDs. */
-/* These replace the above OIDs for connection-oriented media. */
-#define RNDIS_OID_GEN_CO_SUPPORTED_LIST 0x00010101
-#define RNDIS_OID_GEN_CO_HARDWARE_STATUS 0x00010102
-#define RNDIS_OID_GEN_CO_MEDIA_SUPPORTED 0x00010103
-#define RNDIS_OID_GEN_CO_MEDIA_IN_USE 0x00010104
-#define RNDIS_OID_GEN_CO_LINK_SPEED 0x00010105
-#define RNDIS_OID_GEN_CO_VENDOR_ID 0x00010106
-#define RNDIS_OID_GEN_CO_VENDOR_DESCRIPTION 0x00010107
-#define RNDIS_OID_GEN_CO_DRIVER_VERSION 0x00010108
-#define RNDIS_OID_GEN_CO_PROTOCOL_OPTIONS 0x00010109
-#define RNDIS_OID_GEN_CO_MAC_OPTIONS 0x0001010A
-#define RNDIS_OID_GEN_CO_MEDIA_CONNECT_STATUS 0x0001010B
-#define RNDIS_OID_GEN_CO_VENDOR_DRIVER_VERSION 0x0001010C
-#define RNDIS_OID_GEN_CO_MINIMUM_LINK_SPEED 0x0001010D
-
-#define RNDIS_OID_GEN_CO_GET_TIME_CAPS 0x00010201
-#define RNDIS_OID_GEN_CO_GET_NETCARD_TIME 0x00010202
-
-/* These are connection-oriented statistics OIDs. */
-#define RNDIS_OID_GEN_CO_XMIT_PDUS_OK 0x00020101
-#define RNDIS_OID_GEN_CO_RCV_PDUS_OK 0x00020102
-#define RNDIS_OID_GEN_CO_XMIT_PDUS_ERROR 0x00020103
-#define RNDIS_OID_GEN_CO_RCV_PDUS_ERROR 0x00020104
-#define RNDIS_OID_GEN_CO_RCV_PDUS_NO_BUFFER 0x00020105
-
-
-#define RNDIS_OID_GEN_CO_RCV_CRC_ERROR 0x00020201
-#define RNDIS_OID_GEN_CO_TRANSMIT_QUEUE_LENGTH 0x00020202
-#define RNDIS_OID_GEN_CO_BYTES_XMIT 0x00020203
-#define RNDIS_OID_GEN_CO_BYTES_RCV 0x00020204
-#define RNDIS_OID_GEN_CO_BYTES_XMIT_OUTSTANDING 0x00020205
-#define RNDIS_OID_GEN_CO_NETCARD_LOAD 0x00020206
-
-/* These are objects for Connection-oriented media call-managers. */
-#define RNDIS_OID_CO_ADD_PVC 0xFF000001
-#define RNDIS_OID_CO_DELETE_PVC 0xFF000002
-#define RNDIS_OID_CO_GET_CALL_INFORMATION 0xFF000003
-#define RNDIS_OID_CO_ADD_ADDRESS 0xFF000004
-#define RNDIS_OID_CO_DELETE_ADDRESS 0xFF000005
-#define RNDIS_OID_CO_GET_ADDRESSES 0xFF000006
-#define RNDIS_OID_CO_ADDRESS_CHANGE 0xFF000007
-#define RNDIS_OID_CO_SIGNALING_ENABLED 0xFF000008
-#define RNDIS_OID_CO_SIGNALING_DISABLED 0xFF000009
-
-/* 802.3 Objects (Ethernet) */
-#define RNDIS_OID_802_3_PERMANENT_ADDRESS 0x01010101
-#define RNDIS_OID_802_3_CURRENT_ADDRESS 0x01010102
-#define RNDIS_OID_802_3_MULTICAST_LIST 0x01010103
-#define RNDIS_OID_802_3_MAXIMUM_LIST_SIZE 0x01010104
-#define RNDIS_OID_802_3_MAC_OPTIONS 0x01010105
-
-#define NDIS_802_3_MAC_OPTION_PRIORITY 0x00000001
-
-#define RNDIS_OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101
-#define RNDIS_OID_802_3_XMIT_ONE_COLLISION 0x01020102
-#define RNDIS_OID_802_3_XMIT_MORE_COLLISIONS 0x01020103
-
-#define RNDIS_OID_802_3_XMIT_DEFERRED 0x01020201
-#define RNDIS_OID_802_3_XMIT_MAX_COLLISIONS 0x01020202
-#define RNDIS_OID_802_3_RCV_OVERRUN 0x01020203
-#define RNDIS_OID_802_3_XMIT_UNDERRUN 0x01020204
-#define RNDIS_OID_802_3_XMIT_HEARTBEAT_FAILURE 0x01020205
-#define RNDIS_OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206
-#define RNDIS_OID_802_3_XMIT_LATE_COLLISIONS 0x01020207
-
-/* Remote NDIS message types */
-#define REMOTE_NDIS_PACKET_MSG 0x00000001
-#define REMOTE_NDIS_INITIALIZE_MSG 0x00000002
-#define REMOTE_NDIS_HALT_MSG 0x00000003
-#define REMOTE_NDIS_QUERY_MSG 0x00000004
-#define REMOTE_NDIS_SET_MSG 0x00000005
-#define REMOTE_NDIS_RESET_MSG 0x00000006
-#define REMOTE_NDIS_INDICATE_STATUS_MSG 0x00000007
-#define REMOTE_NDIS_KEEPALIVE_MSG 0x00000008
-
-#define REMOTE_CONDIS_MP_CREATE_VC_MSG 0x00008001
-#define REMOTE_CONDIS_MP_DELETE_VC_MSG 0x00008002
-#define REMOTE_CONDIS_MP_ACTIVATE_VC_MSG 0x00008005
-#define REMOTE_CONDIS_MP_DEACTIVATE_VC_MSG 0x00008006
-#define REMOTE_CONDIS_INDICATE_STATUS_MSG 0x00008007
-
-/* Remote NDIS message completion types */
-#define REMOTE_NDIS_INITIALIZE_CMPLT 0x80000002
-#define REMOTE_NDIS_QUERY_CMPLT 0x80000004
-#define REMOTE_NDIS_SET_CMPLT 0x80000005
-#define REMOTE_NDIS_RESET_CMPLT 0x80000006
-#define REMOTE_NDIS_KEEPALIVE_CMPLT 0x80000008
-
-#define REMOTE_CONDIS_MP_CREATE_VC_CMPLT 0x80008001
-#define REMOTE_CONDIS_MP_DELETE_VC_CMPLT 0x80008002
-#define REMOTE_CONDIS_MP_ACTIVATE_VC_CMPLT 0x80008005
-#define REMOTE_CONDIS_MP_DEACTIVATE_VC_CMPLT 0x80008006
-
-/*
- * Reserved message type for private communication between lower-layer host
- * driver and remote device, if necessary.
- */
-#define REMOTE_NDIS_BUS_MSG 0xff000001
-
-/* Defines for DeviceFlags in struct rndis_initialize_complete */
-#define RNDIS_DF_CONNECTIONLESS 0x00000001
-#define RNDIS_DF_CONNECTION_ORIENTED 0x00000002
-#define RNDIS_DF_RAW_DATA 0x00000004
-
-/* Remote NDIS medium types. */
-#define RNDIS_MEDIUM_802_3 0x00000000
-#define RNDIS_MEDIUM_802_5 0x00000001
-#define RNDIS_MEDIUM_FDDI 0x00000002
-#define RNDIS_MEDIUM_WAN 0x00000003
-#define RNDIS_MEDIUM_LOCAL_TALK 0x00000004
-#define RNDIS_MEDIUM_ARCNET_RAW 0x00000006
-#define RNDIS_MEDIUM_ARCNET_878_2 0x00000007
-#define RNDIS_MEDIUM_ATM 0x00000008
-#define RNDIS_MEDIUM_WIRELESS_WAN 0x00000009
-#define RNDIS_MEDIUM_IRDA 0x0000000a
-#define RNDIS_MEDIUM_CO_WAN 0x0000000b
-/* Not a real medium, defined as an upper-bound */
-#define RNDIS_MEDIUM_MAX 0x0000000d
-
-
-/* Remote NDIS medium connection states. */
-#define RNDIS_MEDIA_STATE_CONNECTED 0x00000000
-#define RNDIS_MEDIA_STATE_DISCONNECTED 0x00000001
-
-/* Remote NDIS version numbers */
-#define RNDIS_MAJOR_VERSION 0x00000001
-#define RNDIS_MINOR_VERSION 0x00000000
-
-
/* NdisInitialize message */
struct rndis_initialize_request {
u32 req_id;
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index d025c83cd12a..8b919471472f 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -428,6 +428,24 @@ int netvsc_device_remove(struct hv_device *device)
return 0;
}
+
+#define RING_AVAIL_PERCENT_HIWATER 20
+#define RING_AVAIL_PERCENT_LOWATER 10
+
+/*
+ * Get the percentage of available bytes to write in the ring.
+ * The return value is in range from 0 to 100.
+ */
+static inline u32 hv_ringbuf_avail_percent(
+ struct hv_ring_buffer_info *ring_info)
+{
+ u32 avail_read, avail_write;
+
+ hv_get_ringbuffer_availbytes(ring_info, &avail_read, &avail_write);
+
+ return avail_write * 100 / ring_info->ring_datasize;
+}
+
static void netvsc_send_completion(struct hv_device *device,
struct vmpacket_descriptor *packet)
{
@@ -455,6 +473,8 @@ static void netvsc_send_completion(struct hv_device *device,
complete(&net_device->channel_init_wait);
} else if (nvsp_packet->hdr.msg_type ==
NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE) {
+ int num_outstanding_sends;
+
/* Get the send context */
nvsc_packet = (struct hv_netvsc_packet *)(unsigned long)
packet->trans_id;
@@ -463,10 +483,14 @@ static void netvsc_send_completion(struct hv_device *device,
nvsc_packet->completion.send.send_completion(
nvsc_packet->completion.send.send_completion_ctx);
- atomic_dec(&net_device->num_outstanding_sends);
+ num_outstanding_sends =
+ atomic_dec_return(&net_device->num_outstanding_sends);
- if (netif_queue_stopped(ndev) && !net_device->start_remove)
- netif_wake_queue(ndev);
+ if (netif_queue_stopped(ndev) && !net_device->start_remove &&
+ (hv_ringbuf_avail_percent(&device->channel->outbound)
+ > RING_AVAIL_PERCENT_HIWATER ||
+ num_outstanding_sends < 1))
+ netif_wake_queue(ndev);
} else {
netdev_err(ndev, "Unknown send completion packet type- "
"%d received!!\n", nvsp_packet->hdr.msg_type);
@@ -519,10 +543,19 @@ int netvsc_send(struct hv_device *device,
if (ret == 0) {
atomic_inc(&net_device->num_outstanding_sends);
+ if (hv_ringbuf_avail_percent(&device->channel->outbound) <
+ RING_AVAIL_PERCENT_LOWATER) {
+ netif_stop_queue(ndev);
+ if (atomic_read(&net_device->
+ num_outstanding_sends) < 1)
+ netif_wake_queue(ndev);
+ }
} else if (ret == -EAGAIN) {
netif_stop_queue(ndev);
- if (atomic_read(&net_device->num_outstanding_sends) < 1)
+ if (atomic_read(&net_device->num_outstanding_sends) < 1) {
netif_wake_queue(ndev);
+ ret = -ENOSPC;
+ }
} else {
netdev_err(ndev, "Unable to send packet %p ret %d\n",
packet, ret);
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index dd294783b5c5..8f8ed3320425 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -44,6 +44,7 @@ struct net_device_context {
/* point back to our device context */
struct hv_device *device_ctx;
struct delayed_work dwork;
+ struct work_struct work;
};
@@ -51,30 +52,22 @@ static int ring_size = 128;
module_param(ring_size, int, S_IRUGO);
MODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)");
-struct set_multicast_work {
- struct work_struct work;
- struct net_device *net;
-};
-
static void do_set_multicast(struct work_struct *w)
{
- struct set_multicast_work *swk =
- container_of(w, struct set_multicast_work, work);
- struct net_device *net = swk->net;
-
- struct net_device_context *ndevctx = netdev_priv(net);
+ struct net_device_context *ndevctx =
+ container_of(w, struct net_device_context, work);
struct netvsc_device *nvdev;
struct rndis_device *rdev;
nvdev = hv_get_drvdata(ndevctx->device_ctx);
- if (nvdev == NULL)
- goto out;
+ if (nvdev == NULL || nvdev->ndev == NULL)
+ return;
rdev = nvdev->extension;
if (rdev == NULL)
- goto out;
+ return;
- if (net->flags & IFF_PROMISC)
+ if (nvdev->ndev->flags & IFF_PROMISC)
rndis_filter_set_packet_filter(rdev,
NDIS_PACKET_TYPE_PROMISCUOUS);
else
@@ -82,21 +75,13 @@ static void do_set_multicast(struct work_struct *w)
NDIS_PACKET_TYPE_BROADCAST |
NDIS_PACKET_TYPE_ALL_MULTICAST |
NDIS_PACKET_TYPE_DIRECTED);
-
-out:
- kfree(w);
}
static void netvsc_set_multicast_list(struct net_device *net)
{
- struct set_multicast_work *swk =
- kmalloc(sizeof(struct set_multicast_work), GFP_ATOMIC);
- if (swk == NULL)
- return;
+ struct net_device_context *net_device_ctx = netdev_priv(net);
- swk->net = net;
- INIT_WORK(&swk->work, do_set_multicast);
- schedule_work(&swk->work);
+ schedule_work(&net_device_ctx->work);
}
static int netvsc_open(struct net_device *net)
@@ -125,6 +110,8 @@ static int netvsc_close(struct net_device *net)
netif_tx_disable(net);
+ /* Make sure netvsc_set_multicast_list doesn't re-enable filter! */
+ cancel_work_sync(&net_device_ctx->work);
ret = rndis_filter_close(device_obj);
if (ret != 0)
netdev_err(net, "unable to close device (ret %d).\n", ret);
@@ -224,9 +211,13 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
net->stats.tx_packets++;
} else {
kfree(packet);
+ if (ret != -EAGAIN) {
+ dev_kfree_skb_any(skb);
+ net->stats.tx_dropped++;
+ }
}
- return ret ? NETDEV_TX_BUSY : NETDEV_TX_OK;
+ return (ret == -EAGAIN) ? NETDEV_TX_BUSY : NETDEV_TX_OK;
}
/*
@@ -335,6 +326,7 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
nvdev->start_remove = true;
cancel_delayed_work_sync(&ndevctx->dwork);
+ cancel_work_sync(&ndevctx->work);
netif_tx_disable(ndev);
rndis_filter_device_remove(hdev);
@@ -403,6 +395,7 @@ static int netvsc_probe(struct hv_device *dev,
net_device_ctx->device_ctx = dev;
hv_set_drvdata(dev, net);
INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_send_garp);
+ INIT_WORK(&net_device_ctx->work, do_set_multicast);
net->netdev_ops = &device_ops;
@@ -456,6 +449,7 @@ static int netvsc_remove(struct hv_device *dev)
ndev_ctx = netdev_priv(net);
cancel_delayed_work_sync(&ndev_ctx->dwork);
+ cancel_work_sync(&ndev_ctx->work);
/* Stop outbound asap */
netif_tx_disable(net);
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index d6be64bcefd4..981ebb115637 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -129,8 +129,8 @@ static void dump_rndis_message(struct hv_device *hv_dev,
netdev = net_device->ndev;
switch (rndis_msg->ndis_msg_type) {
- case REMOTE_NDIS_PACKET_MSG:
- netdev_dbg(netdev, "REMOTE_NDIS_PACKET_MSG (len %u, "
+ case RNDIS_MSG_PACKET:
+ netdev_dbg(netdev, "RNDIS_MSG_PACKET (len %u, "
"data offset %u data len %u, # oob %u, "
"oob offset %u, oob len %u, pkt offset %u, "
"pkt len %u\n",
@@ -144,8 +144,8 @@ static void dump_rndis_message(struct hv_device *hv_dev,
rndis_msg->msg.pkt.per_pkt_info_len);
break;
- case REMOTE_NDIS_INITIALIZE_CMPLT:
- netdev_dbg(netdev, "REMOTE_NDIS_INITIALIZE_CMPLT "
+ case RNDIS_MSG_INIT_C:
+ netdev_dbg(netdev, "RNDIS_MSG_INIT_C "
"(len %u, id 0x%x, status 0x%x, major %d, minor %d, "
"device flags %d, max xfer size 0x%x, max pkts %u, "
"pkt aligned %u)\n",
@@ -162,8 +162,8 @@ static void dump_rndis_message(struct hv_device *hv_dev,
pkt_alignment_factor);
break;
- case REMOTE_NDIS_QUERY_CMPLT:
- netdev_dbg(netdev, "REMOTE_NDIS_QUERY_CMPLT "
+ case RNDIS_MSG_QUERY_C:
+ netdev_dbg(netdev, "RNDIS_MSG_QUERY_C "
"(len %u, id 0x%x, status 0x%x, buf len %u, "
"buf offset %u)\n",
rndis_msg->msg_len,
@@ -175,16 +175,16 @@ static void dump_rndis_message(struct hv_device *hv_dev,
info_buf_offset);
break;
- case REMOTE_NDIS_SET_CMPLT:
+ case RNDIS_MSG_SET_C:
netdev_dbg(netdev,
- "REMOTE_NDIS_SET_CMPLT (len %u, id 0x%x, status 0x%x)\n",
+ "RNDIS_MSG_SET_C (len %u, id 0x%x, status 0x%x)\n",
rndis_msg->msg_len,
rndis_msg->msg.set_complete.req_id,
rndis_msg->msg.set_complete.status);
break;
- case REMOTE_NDIS_INDICATE_STATUS_MSG:
- netdev_dbg(netdev, "REMOTE_NDIS_INDICATE_STATUS_MSG "
+ case RNDIS_MSG_INDICATE:
+ netdev_dbg(netdev, "RNDIS_MSG_INDICATE "
"(len %u, status 0x%x, buf len %u, buf offset %u)\n",
rndis_msg->msg_len,
rndis_msg->msg.indicate_status.status,
@@ -264,14 +264,14 @@ static void rndis_filter_receive_response(struct rndis_device *dev,
sizeof(struct rndis_filter_packet));
if (resp->ndis_msg_type ==
- REMOTE_NDIS_RESET_CMPLT) {
+ RNDIS_MSG_RESET_C) {
/* does not have a request id field */
request->response_msg.msg.reset_complete.
- status = STATUS_BUFFER_OVERFLOW;
+ status = RNDIS_STATUS_BUFFER_OVERFLOW;
} else {
request->response_msg.msg.
init_complete.status =
- STATUS_BUFFER_OVERFLOW;
+ RNDIS_STATUS_BUFFER_OVERFLOW;
}
}
@@ -415,19 +415,19 @@ int rndis_filter_receive(struct hv_device *dev,
dump_rndis_message(dev, rndis_msg);
switch (rndis_msg->ndis_msg_type) {
- case REMOTE_NDIS_PACKET_MSG:
+ case RNDIS_MSG_PACKET:
/* data msg */
rndis_filter_receive_data(rndis_dev, rndis_msg, pkt);
break;
- case REMOTE_NDIS_INITIALIZE_CMPLT:
- case REMOTE_NDIS_QUERY_CMPLT:
- case REMOTE_NDIS_SET_CMPLT:
+ case RNDIS_MSG_INIT_C:
+ case RNDIS_MSG_QUERY_C:
+ case RNDIS_MSG_SET_C:
/* completion msgs */
rndis_filter_receive_response(rndis_dev, rndis_msg);
break;
- case REMOTE_NDIS_INDICATE_STATUS_MSG:
+ case RNDIS_MSG_INDICATE:
/* notification msgs */
rndis_filter_receive_indicate_status(rndis_dev, rndis_msg);
break;
@@ -456,7 +456,7 @@ static int rndis_filter_query_device(struct rndis_device *dev, u32 oid,
return -EINVAL;
*result_size = 0;
- request = get_rndis_request(dev, REMOTE_NDIS_QUERY_MSG,
+ request = get_rndis_request(dev, RNDIS_MSG_QUERY,
RNDIS_MESSAGE_SIZE(struct rndis_query_request));
if (!request) {
ret = -ENOMEM;
@@ -536,7 +536,7 @@ int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter)
ndev = dev->net_dev->ndev;
- request = get_rndis_request(dev, REMOTE_NDIS_SET_MSG,
+ request = get_rndis_request(dev, RNDIS_MSG_SET,
RNDIS_MESSAGE_SIZE(struct rndis_set_request) +
sizeof(u32));
if (!request) {
@@ -588,7 +588,7 @@ static int rndis_filter_init_device(struct rndis_device *dev)
u32 status;
int ret, t;
- request = get_rndis_request(dev, REMOTE_NDIS_INITIALIZE_MSG,
+ request = get_rndis_request(dev, RNDIS_MSG_INIT,
RNDIS_MESSAGE_SIZE(struct rndis_initialize_request));
if (!request) {
ret = -ENOMEM;
@@ -641,7 +641,7 @@ static void rndis_filter_halt_device(struct rndis_device *dev)
struct rndis_halt_request *halt;
/* Attempt to do a rndis device halt */
- request = get_rndis_request(dev, REMOTE_NDIS_HALT_MSG,
+ request = get_rndis_request(dev, RNDIS_MSG_HALT,
RNDIS_MESSAGE_SIZE(struct rndis_halt_request));
if (!request)
goto cleanup;
@@ -805,7 +805,7 @@ int rndis_filter_send(struct hv_device *dev,
if (isvlan)
rndis_msg_size += NDIS_VLAN_PPI_SIZE;
- rndis_msg->ndis_msg_type = REMOTE_NDIS_PACKET_MSG;
+ rndis_msg->ndis_msg_type = RNDIS_MSG_PACKET;
rndis_msg->msg_len = pkt->total_data_buflen +
rndis_msg_size;