2 * Copyright (c) 2009, Microsoft Corporation.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
15 * Place - Suite 330, Boston, MA 02111-1307 USA.
18 * Haiyang Zhang <haiyangz@microsoft.com>
19 * Hank Janssen <hjanssen@microsoft.com>
21 #include <linux/kernel.h>
22 #include <linux/sched.h>
23 #include <linux/wait.h>
24 #include <linux/highmem.h>
25 #include <linux/slab.h>
27 #include <linux/if_ether.h>
28 #include <linux/netdevice.h>
32 #include "netvsc_api.h"
33 #include "rndis_filter.h"
36 struct rndis_filter_driver_object {
37 /* The original driver */
38 struct netvsc_driver inner_drv;
41 enum rndis_device_state {
42 RNDIS_DEV_UNINITIALIZED = 0,
43 RNDIS_DEV_INITIALIZING,
44 RNDIS_DEV_INITIALIZED,
45 RNDIS_DEV_DATAINITIALIZED,
49 struct netvsc_device *net_dev;
51 enum rndis_device_state state;
55 spinlock_t request_lock;
56 struct list_head req_list;
58 unsigned char hw_mac_adr[ETH_ALEN];
61 struct rndis_request {
62 struct list_head list_ent;
63 struct completion wait_event;
66 * FIXME: We assumed a fixed size response here. If we do ever need to
67 * handle a bigger response, we can either define a max response
68 * message or add a response buffer variable above this field
70 struct rndis_message response_msg;
72 /* Simplify allocation by having a netvsc packet inline */
73 struct hv_netvsc_packet pkt;
74 struct hv_page_buffer buf;
75 /* FIXME: We assumed a fixed size request here. */
76 struct rndis_message request_msg;
80 struct rndis_filter_packet {
82 void (*completion)(void *context);
83 struct rndis_message msg;
87 static int rndis_filter_send(struct hv_device *dev,
88 struct hv_netvsc_packet *pkt);
90 static void rndis_filter_send_completion(void *ctx);
92 static void rndis_filter_send_request_completion(void *ctx);
95 /* The one and only */
96 static struct rndis_filter_driver_object rndis_filter;
98 static struct rndis_device *get_rndis_device(void)
100 struct rndis_device *device;
102 device = kzalloc(sizeof(struct rndis_device), GFP_KERNEL);
106 spin_lock_init(&device->request_lock);
108 INIT_LIST_HEAD(&device->req_list);
110 device->state = RNDIS_DEV_UNINITIALIZED;
115 static struct rndis_request *get_rndis_request(struct rndis_device *dev,
119 struct rndis_request *request;
120 struct rndis_message *rndis_msg;
121 struct rndis_set_request *set;
124 request = kzalloc(sizeof(struct rndis_request), GFP_KERNEL);
128 init_completion(&request->wait_event);
130 rndis_msg = &request->request_msg;
131 rndis_msg->ndis_msg_type = msg_type;
132 rndis_msg->msg_len = msg_len;
135 * Set the request id. This field is always after the rndis header for
136 * request/response packet types so we just used the SetRequest as a
139 set = &rndis_msg->msg.set_req;
140 set->req_id = atomic_inc_return(&dev->new_req_id);
142 /* Add to the request list */
143 spin_lock_irqsave(&dev->request_lock, flags);
144 list_add_tail(&request->list_ent, &dev->req_list);
145 spin_unlock_irqrestore(&dev->request_lock, flags);
150 static void put_rndis_request(struct rndis_device *dev,
151 struct rndis_request *req)
155 spin_lock_irqsave(&dev->request_lock, flags);
156 list_del(&req->list_ent);
157 spin_unlock_irqrestore(&dev->request_lock, flags);
162 static void dump_rndis_message(struct rndis_message *rndis_msg)
164 switch (rndis_msg->ndis_msg_type) {
165 case REMOTE_NDIS_PACKET_MSG:
166 DPRINT_DBG(NETVSC, "REMOTE_NDIS_PACKET_MSG (len %u, "
167 "data offset %u data len %u, # oob %u, "
168 "oob offset %u, oob len %u, pkt offset %u, "
171 rndis_msg->msg.pkt.data_offset,
172 rndis_msg->msg.pkt.data_len,
173 rndis_msg->msg.pkt.num_oob_data_elements,
174 rndis_msg->msg.pkt.oob_data_offset,
175 rndis_msg->msg.pkt.oob_data_len,
176 rndis_msg->msg.pkt.per_pkt_info_offset,
177 rndis_msg->msg.pkt.per_pkt_info_len);
180 case REMOTE_NDIS_INITIALIZE_CMPLT:
181 DPRINT_DBG(NETVSC, "REMOTE_NDIS_INITIALIZE_CMPLT "
182 "(len %u, id 0x%x, status 0x%x, major %d, minor %d, "
183 "device flags %d, max xfer size 0x%x, max pkts %u, "
186 rndis_msg->msg.init_complete.req_id,
187 rndis_msg->msg.init_complete.status,
188 rndis_msg->msg.init_complete.major_ver,
189 rndis_msg->msg.init_complete.minor_ver,
190 rndis_msg->msg.init_complete.dev_flags,
191 rndis_msg->msg.init_complete.max_xfer_size,
192 rndis_msg->msg.init_complete.
194 rndis_msg->msg.init_complete.
195 pkt_alignment_factor);
198 case REMOTE_NDIS_QUERY_CMPLT:
199 DPRINT_DBG(NETVSC, "REMOTE_NDIS_QUERY_CMPLT "
200 "(len %u, id 0x%x, status 0x%x, buf len %u, "
203 rndis_msg->msg.query_complete.req_id,
204 rndis_msg->msg.query_complete.status,
205 rndis_msg->msg.query_complete.
207 rndis_msg->msg.query_complete.
211 case REMOTE_NDIS_SET_CMPLT:
213 "REMOTE_NDIS_SET_CMPLT (len %u, id 0x%x, status 0x%x)",
215 rndis_msg->msg.set_complete.req_id,
216 rndis_msg->msg.set_complete.status);
219 case REMOTE_NDIS_INDICATE_STATUS_MSG:
220 DPRINT_DBG(NETVSC, "REMOTE_NDIS_INDICATE_STATUS_MSG "
221 "(len %u, status 0x%x, buf len %u, buf offset %u)",
223 rndis_msg->msg.indicate_status.status,
224 rndis_msg->msg.indicate_status.status_buflen,
225 rndis_msg->msg.indicate_status.status_buf_offset);
229 DPRINT_DBG(NETVSC, "0x%x (len %u)",
230 rndis_msg->ndis_msg_type,
236 static int rndis_filter_send_request(struct rndis_device *dev,
237 struct rndis_request *req)
240 struct hv_netvsc_packet *packet;
242 /* Setup the packet to send it */
245 packet->is_data_pkt = false;
246 packet->total_data_buflen = req->request_msg.msg_len;
247 packet->page_buf_cnt = 1;
249 packet->page_buf[0].pfn = virt_to_phys(&req->request_msg) >>
251 packet->page_buf[0].len = req->request_msg.msg_len;
252 packet->page_buf[0].offset =
253 (unsigned long)&req->request_msg & (PAGE_SIZE - 1);
255 packet->completion.send.send_completion_ctx = req;/* packet; */
256 packet->completion.send.send_completion =
257 rndis_filter_send_request_completion;
258 packet->completion.send.send_completion_tid = (unsigned long)dev;
260 ret = rndis_filter.inner_drv.send(dev->net_dev->dev, packet);
264 static void rndis_filter_receive_response(struct rndis_device *dev,
265 struct rndis_message *resp)
267 struct rndis_request *request = NULL;
271 spin_lock_irqsave(&dev->request_lock, flags);
272 list_for_each_entry(request, &dev->req_list, list_ent) {
274 * All request/response message contains RequestId as the 1st
277 if (request->request_msg.msg.init_req.req_id
278 == resp->msg.init_complete.req_id) {
283 spin_unlock_irqrestore(&dev->request_lock, flags);
286 if (resp->msg_len <= sizeof(struct rndis_message)) {
287 memcpy(&request->response_msg, resp,
290 dev_err(&dev->net_dev->dev->device,
291 "rndis response buffer overflow "
292 "detected (size %u max %zu)\n",
294 sizeof(struct rndis_filter_packet));
296 if (resp->ndis_msg_type ==
297 REMOTE_NDIS_RESET_CMPLT) {
298 /* does not have a request id field */
299 request->response_msg.msg.reset_complete.
300 status = STATUS_BUFFER_OVERFLOW;
302 request->response_msg.msg.
303 init_complete.status =
304 STATUS_BUFFER_OVERFLOW;
308 complete(&request->wait_event);
310 dev_err(&dev->net_dev->dev->device,
311 "no rndis request found for this response "
312 "(id 0x%x res type 0x%x)\n",
313 resp->msg.init_complete.req_id,
314 resp->ndis_msg_type);
318 static void rndis_filter_receive_indicate_status(struct rndis_device *dev,
319 struct rndis_message *resp)
321 struct rndis_indicate_status *indicate =
322 &resp->msg.indicate_status;
324 if (indicate->status == RNDIS_STATUS_MEDIA_CONNECT) {
325 rndis_filter.inner_drv.link_status_change(
326 dev->net_dev->dev, 1);
327 } else if (indicate->status == RNDIS_STATUS_MEDIA_DISCONNECT) {
328 rndis_filter.inner_drv.link_status_change(
329 dev->net_dev->dev, 0);
337 static void rndis_filter_receive_data(struct rndis_device *dev,
338 struct rndis_message *msg,
339 struct hv_netvsc_packet *pkt)
341 struct rndis_packet *rndis_pkt;
344 rndis_pkt = &msg->msg.pkt;
347 * FIXME: Handle multiple rndis pkt msgs that maybe enclosed in this
348 * netvsc packet (ie TotalDataBufferLength != MessageLength)
351 /* Remove the rndis header and pass it back up the stack */
352 data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset;
354 pkt->total_data_buflen -= data_offset;
355 pkt->page_buf[0].offset += data_offset;
356 pkt->page_buf[0].len -= data_offset;
358 pkt->is_data_pkt = true;
360 rndis_filter.inner_drv.recv_cb(dev->net_dev->dev,
364 static int rndis_filter_receive(struct hv_device *dev,
365 struct hv_netvsc_packet *pkt)
367 struct netvsc_device *net_dev = dev->ext;
368 struct rndis_device *rndis_dev;
369 struct rndis_message rndis_msg;
370 struct rndis_message *rndis_hdr;
375 /* Make sure the rndis device state is initialized */
376 if (!net_dev->extension) {
377 dev_err(&dev->device, "got rndis message but no rndis device - "
378 "dropping this message!\n");
382 rndis_dev = (struct rndis_device *)net_dev->extension;
383 if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED) {
384 dev_err(&dev->device, "got rndis message but rndis device "
385 "uninitialized...dropping this message!\n");
389 rndis_hdr = (struct rndis_message *)kmap_atomic(
390 pfn_to_page(pkt->page_buf[0].pfn), KM_IRQ0);
392 rndis_hdr = (void *)((unsigned long)rndis_hdr +
393 pkt->page_buf[0].offset);
395 /* Make sure we got a valid rndis message */
397 * FIXME: There seems to be a bug in set completion msg where its
398 * MessageLength is 16 bytes but the ByteCount field in the xfer page
399 * range shows 52 bytes
402 if (pkt->total_data_buflen != rndis_hdr->msg_len) {
403 kunmap_atomic(rndis_hdr - pkt->page_buf[0].offset,
406 dev_err(&dev->device, "invalid rndis message? (expected %u "
407 "bytes got %u)...dropping this message!\n",
409 pkt->total_data_buflen);
414 if ((rndis_hdr->ndis_msg_type != REMOTE_NDIS_PACKET_MSG) &&
415 (rndis_hdr->msg_len > sizeof(struct rndis_message))) {
416 dev_err(&dev->device, "incoming rndis message buffer overflow "
417 "detected (got %u, max %zu)..marking it an error!\n",
419 sizeof(struct rndis_message));
422 memcpy(&rndis_msg, rndis_hdr,
423 (rndis_hdr->msg_len > sizeof(struct rndis_message)) ?
424 sizeof(struct rndis_message) :
427 kunmap_atomic(rndis_hdr - pkt->page_buf[0].offset, KM_IRQ0);
429 dump_rndis_message(&rndis_msg);
431 switch (rndis_msg.ndis_msg_type) {
432 case REMOTE_NDIS_PACKET_MSG:
434 rndis_filter_receive_data(rndis_dev, &rndis_msg, pkt);
437 case REMOTE_NDIS_INITIALIZE_CMPLT:
438 case REMOTE_NDIS_QUERY_CMPLT:
439 case REMOTE_NDIS_SET_CMPLT:
440 /* completion msgs */
441 rndis_filter_receive_response(rndis_dev, &rndis_msg);
444 case REMOTE_NDIS_INDICATE_STATUS_MSG:
445 /* notification msgs */
446 rndis_filter_receive_indicate_status(rndis_dev, &rndis_msg);
449 dev_err(&dev->device,
450 "unhandled rndis message (type %u len %u)\n",
451 rndis_msg.ndis_msg_type,
459 static int rndis_filter_query_device(struct rndis_device *dev, u32 oid,
460 void *result, u32 *result_size)
462 struct rndis_request *request;
463 u32 inresult_size = *result_size;
464 struct rndis_query_request *query;
465 struct rndis_query_complete *query_complete;
473 request = get_rndis_request(dev, REMOTE_NDIS_QUERY_MSG,
474 RNDIS_MESSAGE_SIZE(struct rndis_query_request));
480 /* Setup the rndis query */
481 query = &request->request_msg.msg.query_req;
483 query->info_buf_offset = sizeof(struct rndis_query_request);
484 query->info_buflen = 0;
485 query->dev_vc_handle = 0;
487 ret = rndis_filter_send_request(dev, request);
491 t = wait_for_completion_timeout(&request->wait_event, HZ);
497 /* Copy the response back */
498 query_complete = &request->response_msg.msg.query_complete;
500 if (query_complete->info_buflen > inresult_size) {
506 (void *)((unsigned long)query_complete +
507 query_complete->info_buf_offset),
508 query_complete->info_buflen);
510 *result_size = query_complete->info_buflen;
514 put_rndis_request(dev, request);
519 static int rndis_filter_query_device_mac(struct rndis_device *dev)
523 return rndis_filter_query_device(dev,
524 RNDIS_OID_802_3_PERMANENT_ADDRESS,
525 dev->hw_mac_adr, &size);
528 static int rndis_filter_query_device_link_status(struct rndis_device *dev)
530 u32 size = sizeof(u32);
532 return rndis_filter_query_device(dev,
533 RNDIS_OID_GEN_MEDIA_CONNECT_STATUS,
534 &dev->link_stat, &size);
537 static int rndis_filter_set_packet_filter(struct rndis_device *dev,
540 struct rndis_request *request;
541 struct rndis_set_request *set;
542 struct rndis_set_complete *set_complete;
546 request = get_rndis_request(dev, REMOTE_NDIS_SET_MSG,
547 RNDIS_MESSAGE_SIZE(struct rndis_set_request) +
554 /* Setup the rndis set */
555 set = &request->request_msg.msg.set_req;
556 set->oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
557 set->info_buflen = sizeof(u32);
558 set->info_buf_offset = sizeof(struct rndis_set_request);
560 memcpy((void *)(unsigned long)set + sizeof(struct rndis_set_request),
561 &new_filter, sizeof(u32));
563 ret = rndis_filter_send_request(dev, request);
567 t = wait_for_completion_timeout(&request->wait_event, HZ);
571 dev_err(&dev->net_dev->dev->device,
572 "timeout before we got a set response...\n");
574 * We can't deallocate the request since we may still receive a
575 * send completion for it.
581 set_complete = &request->response_msg.msg.set_complete;
582 status = set_complete->status;
587 put_rndis_request(dev, request);
592 int rndis_filter_init(struct netvsc_driver *drv)
594 drv->req_ext_size = sizeof(struct rndis_filter_packet);
596 /* Driver->Context = rndisDriver; */
598 memset(&rndis_filter, 0, sizeof(struct rndis_filter_driver_object));
600 /*rndisDriver->Driver = Driver;
602 ASSERT(Driver->OnLinkStatusChanged);
603 rndisDriver->OnLinkStatusChanged = Driver->OnLinkStatusChanged;*/
605 /* Save the original dispatch handlers before we override it */
606 rndis_filter.inner_drv.send = drv->send;
607 rndis_filter.inner_drv.recv_cb = drv->recv_cb;
608 rndis_filter.inner_drv.link_status_change =
609 drv->link_status_change;
612 drv->send = rndis_filter_send;
613 drv->recv_cb = rndis_filter_receive;
618 static int rndis_filter_init_device(struct rndis_device *dev)
620 struct rndis_request *request;
621 struct rndis_initialize_request *init;
622 struct rndis_initialize_complete *init_complete;
626 request = get_rndis_request(dev, REMOTE_NDIS_INITIALIZE_MSG,
627 RNDIS_MESSAGE_SIZE(struct rndis_initialize_request));
633 /* Setup the rndis set */
634 init = &request->request_msg.msg.init_req;
635 init->major_ver = RNDIS_MAJOR_VERSION;
636 init->minor_ver = RNDIS_MINOR_VERSION;
637 /* FIXME: Use 1536 - rounded ethernet frame size */
638 init->max_xfer_size = 2048;
640 dev->state = RNDIS_DEV_INITIALIZING;
642 ret = rndis_filter_send_request(dev, request);
644 dev->state = RNDIS_DEV_UNINITIALIZED;
649 t = wait_for_completion_timeout(&request->wait_event, HZ);
656 init_complete = &request->response_msg.msg.init_complete;
657 status = init_complete->status;
658 if (status == RNDIS_STATUS_SUCCESS) {
659 dev->state = RNDIS_DEV_INITIALIZED;
662 dev->state = RNDIS_DEV_UNINITIALIZED;
668 put_rndis_request(dev, request);
673 static void rndis_filter_halt_device(struct rndis_device *dev)
675 struct rndis_request *request;
676 struct rndis_halt_request *halt;
678 /* Attempt to do a rndis device halt */
679 request = get_rndis_request(dev, REMOTE_NDIS_HALT_MSG,
680 RNDIS_MESSAGE_SIZE(struct rndis_halt_request));
684 /* Setup the rndis set */
685 halt = &request->request_msg.msg.halt_req;
686 halt->req_id = atomic_inc_return(&dev->new_req_id);
688 /* Ignore return since this msg is optional. */
689 rndis_filter_send_request(dev, request);
691 dev->state = RNDIS_DEV_UNINITIALIZED;
695 put_rndis_request(dev, request);
699 static int rndis_filter_open_device(struct rndis_device *dev)
703 if (dev->state != RNDIS_DEV_INITIALIZED)
706 ret = rndis_filter_set_packet_filter(dev,
707 NDIS_PACKET_TYPE_BROADCAST |
708 NDIS_PACKET_TYPE_ALL_MULTICAST |
709 NDIS_PACKET_TYPE_DIRECTED);
711 dev->state = RNDIS_DEV_DATAINITIALIZED;
716 static int rndis_filter_close_device(struct rndis_device *dev)
720 if (dev->state != RNDIS_DEV_DATAINITIALIZED)
723 ret = rndis_filter_set_packet_filter(dev, 0);
725 dev->state = RNDIS_DEV_INITIALIZED;
730 int rndis_filte_device_add(struct hv_device *dev,
731 void *additional_info)
734 struct netvsc_device *netDevice;
735 struct rndis_device *rndisDevice;
736 struct netvsc_device_info *deviceInfo = additional_info;
738 rndisDevice = get_rndis_device();
743 * Let the inner driver handle this first to create the netvsc channel
744 * NOTE! Once the channel is created, we may get a receive callback
745 * (RndisFilterOnReceive()) before this call is completed
747 ret = netvsc_device_add(dev, additional_info);
754 /* Initialize the rndis device */
755 netDevice = dev->ext;
757 netDevice->extension = rndisDevice;
758 rndisDevice->net_dev = netDevice;
760 /* Send the rndis initialization message */
761 ret = rndis_filter_init_device(rndisDevice);
764 * TODO: If rndis init failed, we will need to shut down the
769 /* Get the mac address */
770 ret = rndis_filter_query_device_mac(rndisDevice);
773 * TODO: shutdown rndis device and the channel
777 memcpy(deviceInfo->mac_adr, rndisDevice->hw_mac_adr, ETH_ALEN);
779 rndis_filter_query_device_link_status(rndisDevice);
781 deviceInfo->link_state = rndisDevice->link_stat;
783 dev_info(&dev->device, "Device MAC %pM link state %s",
784 rndisDevice->hw_mac_adr,
785 ((deviceInfo->link_state) ? ("down\n") : ("up\n")));
790 int rndis_filter_device_remove(struct hv_device *dev)
792 struct netvsc_device *net_dev = dev->ext;
793 struct rndis_device *rndis_dev = net_dev->extension;
795 /* Halt and release the rndis device */
796 rndis_filter_halt_device(rndis_dev);
799 net_dev->extension = NULL;
801 netvsc_device_remove(dev);
807 int rndis_filter_open(struct hv_device *dev)
809 struct netvsc_device *netDevice = dev->ext;
814 return rndis_filter_open_device(netDevice->extension);
817 int rndis_filter_close(struct hv_device *dev)
819 struct netvsc_device *netDevice = dev->ext;
824 return rndis_filter_close_device(netDevice->extension);
827 static int rndis_filter_send(struct hv_device *dev,
828 struct hv_netvsc_packet *pkt)
831 struct rndis_filter_packet *filterPacket;
832 struct rndis_message *rndisMessage;
833 struct rndis_packet *rndisPacket;
834 u32 rndisMessageSize;
836 /* Add the rndis header */
837 filterPacket = (struct rndis_filter_packet *)pkt->extension;
839 memset(filterPacket, 0, sizeof(struct rndis_filter_packet));
841 rndisMessage = &filterPacket->msg;
842 rndisMessageSize = RNDIS_MESSAGE_SIZE(struct rndis_packet);
844 rndisMessage->ndis_msg_type = REMOTE_NDIS_PACKET_MSG;
845 rndisMessage->msg_len = pkt->total_data_buflen +
848 rndisPacket = &rndisMessage->msg.pkt;
849 rndisPacket->data_offset = sizeof(struct rndis_packet);
850 rndisPacket->data_len = pkt->total_data_buflen;
852 pkt->is_data_pkt = true;
853 pkt->page_buf[0].pfn = virt_to_phys(rndisMessage) >> PAGE_SHIFT;
854 pkt->page_buf[0].offset =
855 (unsigned long)rndisMessage & (PAGE_SIZE-1);
856 pkt->page_buf[0].len = rndisMessageSize;
858 /* Save the packet send completion and context */
859 filterPacket->completion = pkt->completion.send.send_completion;
860 filterPacket->completion_ctx =
861 pkt->completion.send.send_completion_ctx;
864 pkt->completion.send.send_completion = rndis_filter_send_completion;
865 pkt->completion.send.send_completion_ctx = filterPacket;
867 ret = rndis_filter.inner_drv.send(dev, pkt);
870 * Reset the completion to originals to allow retries from
873 pkt->completion.send.send_completion =
874 filterPacket->completion;
875 pkt->completion.send.send_completion_ctx =
876 filterPacket->completion_ctx;
882 static void rndis_filter_send_completion(void *ctx)
884 struct rndis_filter_packet *filterPacket = ctx;
886 /* Pass it back to the original handler */
887 filterPacket->completion(filterPacket->completion_ctx);
891 static void rndis_filter_send_request_completion(void *ctx)