Merge branch 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[firefly-linux-kernel-4.4.55.git] / drivers / staging / hv / rndis_filter.c
1 /*
2  * Copyright (c) 2009, Microsoft Corporation.
3  *
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.
7  *
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
11  * more details.
12  *
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.
16  *
17  * Authors:
18  *   Haiyang Zhang <haiyangz@microsoft.com>
19  *   Hank Janssen  <hjanssen@microsoft.com>
20  */
21 #include <linux/kernel.h>
22 #include <linux/highmem.h>
23 #include <linux/slab.h>
24 #include <linux/io.h>
25 #include <linux/if_ether.h>
26
27 #include "osd.h"
28 #include "logging.h"
29 #include "netvsc_api.h"
30 #include "rndis_filter.h"
31
32 /* Data types */
33 struct rndis_filter_driver_object {
34         /* The original driver */
35         struct netvsc_driver inner_drv;
36 };
37
38 enum rndis_device_state {
39         RNDIS_DEV_UNINITIALIZED = 0,
40         RNDIS_DEV_INITIALIZING,
41         RNDIS_DEV_INITIALIZED,
42         RNDIS_DEV_DATAINITIALIZED,
43 };
44
45 struct rndis_device {
46         struct netvsc_device *net_dev;
47
48         enum rndis_device_state state;
49         u32 link_stat;
50         atomic_t new_req_id;
51
52         spinlock_t request_lock;
53         struct list_head req_list;
54
55         unsigned char hw_mac_adr[ETH_ALEN];
56 };
57
58 struct rndis_request {
59         struct list_head list_ent;
60         struct osd_waitevent *waitevent;
61
62         /*
63          * FIXME: We assumed a fixed size response here. If we do ever need to
64          * handle a bigger response, we can either define a max response
65          * message or add a response buffer variable above this field
66          */
67         struct rndis_message response_msg;
68
69         /* Simplify allocation by having a netvsc packet inline */
70         struct hv_netvsc_packet pkt;
71         struct hv_page_buffer buf;
72         /* FIXME: We assumed a fixed size request here. */
73         struct rndis_message request_msg;
74 };
75
76
77 struct rndis_filter_packet {
78         void *completion_ctx;
79         void (*completion)(void *context);
80         struct rndis_message msg;
81 };
82
83
84 static int rndis_filte_device_add(struct hv_device *dev,
85                                   void *additional_info);
86
87 static int rndis_filter_device_remove(struct hv_device *dev);
88
89 static void rndis_filter_cleanup(struct hv_driver *drv);
90
91 static int rndis_filter_send(struct hv_device *dev,
92                              struct hv_netvsc_packet *pkt);
93
94 static void rndis_filter_send_completion(void *ctx);
95
96 static void rndis_filter_send_request_completion(void *ctx);
97
98
99 /* The one and only */
100 static struct rndis_filter_driver_object rndis_filter;
101
102 static struct rndis_device *get_rndis_device(void)
103 {
104         struct rndis_device *device;
105
106         device = kzalloc(sizeof(struct rndis_device), GFP_KERNEL);
107         if (!device)
108                 return NULL;
109
110         spin_lock_init(&device->request_lock);
111
112         INIT_LIST_HEAD(&device->req_list);
113
114         device->state = RNDIS_DEV_UNINITIALIZED;
115
116         return device;
117 }
118
119 static struct rndis_request *get_rndis_request(struct rndis_device *dev,
120                                              u32 msg_type,
121                                              u32 msg_len)
122 {
123         struct rndis_request *request;
124         struct rndis_message *rndis_msg;
125         struct rndis_set_request *set;
126         unsigned long flags;
127
128         request = kzalloc(sizeof(struct rndis_request), GFP_KERNEL);
129         if (!request)
130                 return NULL;
131
132         request->waitevent = osd_waitevent_create();
133         if (!request->waitevent) {
134                 kfree(request);
135                 return NULL;
136         }
137
138         rndis_msg = &request->request_msg;
139         rndis_msg->ndis_msg_type = msg_type;
140         rndis_msg->msg_len = msg_len;
141
142         /*
143          * Set the request id. This field is always after the rndis header for
144          * request/response packet types so we just used the SetRequest as a
145          * template
146          */
147         set = &rndis_msg->msg.set_req;
148         set->req_id = atomic_inc_return(&dev->new_req_id);
149
150         /* Add to the request list */
151         spin_lock_irqsave(&dev->request_lock, flags);
152         list_add_tail(&request->list_ent, &dev->req_list);
153         spin_unlock_irqrestore(&dev->request_lock, flags);
154
155         return request;
156 }
157
158 static void put_rndis_request(struct rndis_device *dev,
159                             struct rndis_request *req)
160 {
161         unsigned long flags;
162
163         spin_lock_irqsave(&dev->request_lock, flags);
164         list_del(&req->list_ent);
165         spin_unlock_irqrestore(&dev->request_lock, flags);
166
167         kfree(req->waitevent);
168         kfree(req);
169 }
170
171 static void dump_rndis_message(struct rndis_message *rndis_msg)
172 {
173         switch (rndis_msg->ndis_msg_type) {
174         case REMOTE_NDIS_PACKET_MSG:
175                 DPRINT_DBG(NETVSC, "REMOTE_NDIS_PACKET_MSG (len %u, "
176                            "data offset %u data len %u, # oob %u, "
177                            "oob offset %u, oob len %u, pkt offset %u, "
178                            "pkt len %u",
179                            rndis_msg->msg_len,
180                            rndis_msg->msg.pkt.data_offset,
181                            rndis_msg->msg.pkt.data_len,
182                            rndis_msg->msg.pkt.num_oob_data_elements,
183                            rndis_msg->msg.pkt.oob_data_offset,
184                            rndis_msg->msg.pkt.oob_data_len,
185                            rndis_msg->msg.pkt.per_pkt_info_offset,
186                            rndis_msg->msg.pkt.per_pkt_info_len);
187                 break;
188
189         case REMOTE_NDIS_INITIALIZE_CMPLT:
190                 DPRINT_DBG(NETVSC, "REMOTE_NDIS_INITIALIZE_CMPLT "
191                         "(len %u, id 0x%x, status 0x%x, major %d, minor %d, "
192                         "device flags %d, max xfer size 0x%x, max pkts %u, "
193                         "pkt aligned %u)",
194                         rndis_msg->msg_len,
195                         rndis_msg->msg.init_complete.req_id,
196                         rndis_msg->msg.init_complete.status,
197                         rndis_msg->msg.init_complete.major_ver,
198                         rndis_msg->msg.init_complete.minor_ver,
199                         rndis_msg->msg.init_complete.dev_flags,
200                         rndis_msg->msg.init_complete.max_xfer_size,
201                         rndis_msg->msg.init_complete.
202                            max_pkt_per_msg,
203                         rndis_msg->msg.init_complete.
204                            pkt_alignment_factor);
205                 break;
206
207         case REMOTE_NDIS_QUERY_CMPLT:
208                 DPRINT_DBG(NETVSC, "REMOTE_NDIS_QUERY_CMPLT "
209                         "(len %u, id 0x%x, status 0x%x, buf len %u, "
210                         "buf offset %u)",
211                         rndis_msg->msg_len,
212                         rndis_msg->msg.query_complete.req_id,
213                         rndis_msg->msg.query_complete.status,
214                         rndis_msg->msg.query_complete.
215                            info_buflen,
216                         rndis_msg->msg.query_complete.
217                            info_buf_offset);
218                 break;
219
220         case REMOTE_NDIS_SET_CMPLT:
221                 DPRINT_DBG(NETVSC,
222                         "REMOTE_NDIS_SET_CMPLT (len %u, id 0x%x, status 0x%x)",
223                         rndis_msg->msg_len,
224                         rndis_msg->msg.set_complete.req_id,
225                         rndis_msg->msg.set_complete.status);
226                 break;
227
228         case REMOTE_NDIS_INDICATE_STATUS_MSG:
229                 DPRINT_DBG(NETVSC, "REMOTE_NDIS_INDICATE_STATUS_MSG "
230                         "(len %u, status 0x%x, buf len %u, buf offset %u)",
231                         rndis_msg->msg_len,
232                         rndis_msg->msg.indicate_status.status,
233                         rndis_msg->msg.indicate_status.status_buflen,
234                         rndis_msg->msg.indicate_status.status_buf_offset);
235                 break;
236
237         default:
238                 DPRINT_DBG(NETVSC, "0x%x (len %u)",
239                         rndis_msg->ndis_msg_type,
240                         rndis_msg->msg_len);
241                 break;
242         }
243 }
244
245 static int rndis_filter_send_request(struct rndis_device *dev,
246                                   struct rndis_request *req)
247 {
248         int ret;
249         struct hv_netvsc_packet *packet;
250
251         /* Setup the packet to send it */
252         packet = &req->pkt;
253
254         packet->is_data_pkt = false;
255         packet->total_data_buflen = req->request_msg.msg_len;
256         packet->page_buf_cnt = 1;
257
258         packet->page_buf[0].Pfn = virt_to_phys(&req->request_msg) >>
259                                         PAGE_SHIFT;
260         packet->page_buf[0].Length = req->request_msg.msg_len;
261         packet->page_buf[0].Offset =
262                 (unsigned long)&req->request_msg & (PAGE_SIZE - 1);
263
264         packet->completion.send.send_completion_ctx = req;/* packet; */
265         packet->completion.send.send_completion =
266                 rndis_filter_send_request_completion;
267         packet->completion.send.send_completion_tid = (unsigned long)dev;
268
269         ret = rndis_filter.inner_drv.send(dev->net_dev->dev, packet);
270         return ret;
271 }
272
273 static void rndis_filter_receive_response(struct rndis_device *dev,
274                                        struct rndis_message *resp)
275 {
276         struct rndis_request *request = NULL;
277         bool found = false;
278         unsigned long flags;
279
280         spin_lock_irqsave(&dev->request_lock, flags);
281         list_for_each_entry(request, &dev->req_list, list_ent) {
282                 /*
283                  * All request/response message contains RequestId as the 1st
284                  * field
285                  */
286                 if (request->request_msg.msg.init_req.req_id
287                     == resp->msg.init_complete.req_id) {
288                         DPRINT_DBG(NETVSC, "found rndis request for "
289                                 "this response (id 0x%x req type 0x%x res "
290                                 "type 0x%x)",
291                                 request->request_msg.msg.
292                                    init_req.req_id,
293                                 request->request_msg.ndis_msg_type,
294                                 resp->ndis_msg_type);
295
296                         found = true;
297                         break;
298                 }
299         }
300         spin_unlock_irqrestore(&dev->request_lock, flags);
301
302         if (found) {
303                 if (resp->msg_len <= sizeof(struct rndis_message)) {
304                         memcpy(&request->response_msg, resp,
305                                resp->msg_len);
306                 } else {
307                         DPRINT_ERR(NETVSC, "rndis response buffer overflow "
308                                   "detected (size %u max %zu)",
309                                   resp->msg_len,
310                                   sizeof(struct rndis_filter_packet));
311
312                         if (resp->ndis_msg_type ==
313                             REMOTE_NDIS_RESET_CMPLT) {
314                                 /* does not have a request id field */
315                                 request->response_msg.msg.reset_complete.
316                                         status = STATUS_BUFFER_OVERFLOW;
317                         } else {
318                                 request->response_msg.msg.
319                                 init_complete.status =
320                                         STATUS_BUFFER_OVERFLOW;
321                         }
322                 }
323
324                 osd_waitevent_set(request->waitevent);
325         } else {
326                 DPRINT_ERR(NETVSC, "no rndis request found for this response "
327                            "(id 0x%x res type 0x%x)",
328                            resp->msg.init_complete.req_id,
329                            resp->ndis_msg_type);
330         }
331 }
332
333 static void rndis_filter_receive_indicate_status(struct rndis_device *dev,
334                                              struct rndis_message *resp)
335 {
336         struct rndis_indicate_status *indicate =
337                         &resp->msg.indicate_status;
338
339         if (indicate->status == RNDIS_STATUS_MEDIA_CONNECT) {
340                 rndis_filter.inner_drv.link_status_change(
341                         dev->net_dev->dev, 1);
342         } else if (indicate->status == RNDIS_STATUS_MEDIA_DISCONNECT) {
343                 rndis_filter.inner_drv.link_status_change(
344                         dev->net_dev->dev, 0);
345         } else {
346                 /*
347                  * TODO:
348                  */
349         }
350 }
351
352 static void rndis_filter_receive_data(struct rndis_device *dev,
353                                    struct rndis_message *msg,
354                                    struct hv_netvsc_packet *pkt)
355 {
356         struct rndis_packet *rndis_pkt;
357         u32 data_offset;
358
359         /* empty ethernet frame ?? */
360         /* ASSERT(Packet->PageBuffers[0].Length > */
361         /*      RNDIS_MESSAGE_SIZE(struct rndis_packet)); */
362
363         rndis_pkt = &msg->msg.pkt;
364
365         /*
366          * FIXME: Handle multiple rndis pkt msgs that maybe enclosed in this
367          * netvsc packet (ie TotalDataBufferLength != MessageLength)
368          */
369
370         /* Remove the rndis header and pass it back up the stack */
371         data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset;
372
373         pkt->total_data_buflen -= data_offset;
374         pkt->page_buf[0].Offset += data_offset;
375         pkt->page_buf[0].Length -= data_offset;
376
377         pkt->is_data_pkt = true;
378
379         rndis_filter.inner_drv.recv_cb(dev->net_dev->dev,
380                                                    pkt);
381 }
382
383 static int rndis_filter_receive(struct hv_device *dev,
384                                 struct hv_netvsc_packet *pkt)
385 {
386         struct netvsc_device *net_dev = dev->Extension;
387         struct rndis_device *rndis_dev;
388         struct rndis_message rndis_msg;
389         struct rndis_message *rndis_hdr;
390
391         if (!net_dev)
392                 return -EINVAL;
393
394         /* Make sure the rndis device state is initialized */
395         if (!net_dev->extension) {
396                 DPRINT_ERR(NETVSC, "got rndis message but no rndis device..."
397                           "dropping this message!");
398                 return -1;
399         }
400
401         rndis_dev = (struct rndis_device *)net_dev->extension;
402         if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED) {
403                 DPRINT_ERR(NETVSC, "got rndis message but rndis device "
404                            "uninitialized...dropping this message!");
405                 return -1;
406         }
407
408         rndis_hdr = (struct rndis_message *)kmap_atomic(
409                         pfn_to_page(pkt->page_buf[0].Pfn), KM_IRQ0);
410
411         rndis_hdr = (void *)((unsigned long)rndis_hdr +
412                         pkt->page_buf[0].Offset);
413
414         /* Make sure we got a valid rndis message */
415         /*
416          * FIXME: There seems to be a bug in set completion msg where its
417          * MessageLength is 16 bytes but the ByteCount field in the xfer page
418          * range shows 52 bytes
419          * */
420 #if 0
421         if (pkt->total_data_buflen != rndis_hdr->msg_len) {
422                 kunmap_atomic(rndis_hdr - pkt->page_buf[0].Offset,
423                               KM_IRQ0);
424
425                 DPRINT_ERR(NETVSC, "invalid rndis message? (expected %u "
426                            "bytes got %u)...dropping this message!",
427                            rndis_hdr->msg_len,
428                            pkt->total_data_buflen);
429                 return -1;
430         }
431 #endif
432
433         if ((rndis_hdr->ndis_msg_type != REMOTE_NDIS_PACKET_MSG) &&
434             (rndis_hdr->msg_len > sizeof(struct rndis_message))) {
435                 DPRINT_ERR(NETVSC, "incoming rndis message buffer overflow "
436                            "detected (got %u, max %zu)...marking it an error!",
437                            rndis_hdr->msg_len,
438                            sizeof(struct rndis_message));
439         }
440
441         memcpy(&rndis_msg, rndis_hdr,
442                 (rndis_hdr->msg_len > sizeof(struct rndis_message)) ?
443                         sizeof(struct rndis_message) :
444                         rndis_hdr->msg_len);
445
446         kunmap_atomic(rndis_hdr - pkt->page_buf[0].Offset, KM_IRQ0);
447
448         dump_rndis_message(&rndis_msg);
449
450         switch (rndis_msg.ndis_msg_type) {
451         case REMOTE_NDIS_PACKET_MSG:
452                 /* data msg */
453                 rndis_filter_receive_data(rndis_dev, &rndis_msg, pkt);
454                 break;
455
456         case REMOTE_NDIS_INITIALIZE_CMPLT:
457         case REMOTE_NDIS_QUERY_CMPLT:
458         case REMOTE_NDIS_SET_CMPLT:
459         /* case REMOTE_NDIS_RESET_CMPLT: */
460         /* case REMOTE_NDIS_KEEPALIVE_CMPLT: */
461                 /* completion msgs */
462                 rndis_filter_receive_response(rndis_dev, &rndis_msg);
463                 break;
464
465         case REMOTE_NDIS_INDICATE_STATUS_MSG:
466                 /* notification msgs */
467                 rndis_filter_receive_indicate_status(rndis_dev, &rndis_msg);
468                 break;
469         default:
470                 DPRINT_ERR(NETVSC, "unhandled rndis message (type %u len %u)",
471                            rndis_msg.ndis_msg_type,
472                            rndis_msg.msg_len);
473                 break;
474         }
475
476         return 0;
477 }
478
479 static int rndis_filter_query_device(struct rndis_device *dev, u32 oid,
480                                   void *result, u32 *result_size)
481 {
482         struct rndis_request *request;
483         u32 inresult_size = *result_size;
484         struct rndis_query_request *query;
485         struct rndis_query_complete *query_complete;
486         int ret = 0;
487
488         if (!result)
489                 return -EINVAL;
490
491         *result_size = 0;
492         request = get_rndis_request(dev, REMOTE_NDIS_QUERY_MSG,
493                         RNDIS_MESSAGE_SIZE(struct rndis_query_request));
494         if (!request) {
495                 ret = -1;
496                 goto Cleanup;
497         }
498
499         /* Setup the rndis query */
500         query = &request->request_msg.msg.query_req;
501         query->oid = oid;
502         query->info_buf_offset = sizeof(struct rndis_query_request);
503         query->info_buflen = 0;
504         query->dev_vc_handle = 0;
505
506         ret = rndis_filter_send_request(dev, request);
507         if (ret != 0)
508                 goto Cleanup;
509
510         osd_waitevent_wait(request->waitevent);
511
512         /* Copy the response back */
513         query_complete = &request->response_msg.msg.query_complete;
514
515         if (query_complete->info_buflen > inresult_size) {
516                 ret = -1;
517                 goto Cleanup;
518         }
519
520         memcpy(result,
521                (void *)((unsigned long)query_complete +
522                          query_complete->info_buf_offset),
523                query_complete->info_buflen);
524
525         *result_size = query_complete->info_buflen;
526
527 Cleanup:
528         if (request)
529                 put_rndis_request(dev, request);
530
531         return ret;
532 }
533
534 static int rndis_filter_query_device_mac(struct rndis_device *dev)
535 {
536         u32 size = ETH_ALEN;
537
538         return rndis_filter_query_device(dev,
539                                       RNDIS_OID_802_3_PERMANENT_ADDRESS,
540                                       dev->hw_mac_adr, &size);
541 }
542
543 static int rndis_filter_query_device_link_status(struct rndis_device *dev)
544 {
545         u32 size = sizeof(u32);
546
547         return rndis_filter_query_device(dev,
548                                       RNDIS_OID_GEN_MEDIA_CONNECT_STATUS,
549                                       &dev->link_stat, &size);
550 }
551
552 static int rndis_filter_set_packet_filter(struct rndis_device *dev,
553                                       u32 new_filter)
554 {
555         struct rndis_request *request;
556         struct rndis_set_request *set;
557         struct rndis_set_complete *set_complete;
558         u32 status;
559         int ret;
560
561         /* ASSERT(RNDIS_MESSAGE_SIZE(struct rndis_set_request) + sizeof(u32) <= */
562         /*      sizeof(struct rndis_message)); */
563
564         request = get_rndis_request(dev, REMOTE_NDIS_SET_MSG,
565                         RNDIS_MESSAGE_SIZE(struct rndis_set_request) +
566                         sizeof(u32));
567         if (!request) {
568                 ret = -1;
569                 goto Cleanup;
570         }
571
572         /* Setup the rndis set */
573         set = &request->request_msg.msg.set_req;
574         set->oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
575         set->info_buflen = sizeof(u32);
576         set->info_buf_offset = sizeof(struct rndis_set_request);
577
578         memcpy((void *)(unsigned long)set + sizeof(struct rndis_set_request),
579                &new_filter, sizeof(u32));
580
581         ret = rndis_filter_send_request(dev, request);
582         if (ret != 0)
583                 goto Cleanup;
584
585         ret = osd_waitevent_waitex(request->waitevent, 2000/*2sec*/);
586         if (!ret) {
587                 ret = -1;
588                 DPRINT_ERR(NETVSC, "timeout before we got a set response...");
589                 /*
590                  * We cant deallocate the request since we may still receive a
591                  * send completion for it.
592                  */
593                 goto Exit;
594         } else {
595                 if (ret > 0)
596                         ret = 0;
597                 set_complete = &request->response_msg.msg.set_complete;
598                 status = set_complete->status;
599         }
600
601 Cleanup:
602         if (request)
603                 put_rndis_request(dev, request);
604 Exit:
605         return ret;
606 }
607
608 int rndis_filter_init(struct netvsc_driver *drv)
609 {
610         DPRINT_DBG(NETVSC, "sizeof(struct rndis_filter_packet) == %zd",
611                    sizeof(struct rndis_filter_packet));
612
613         drv->req_ext_size = sizeof(struct rndis_filter_packet);
614
615         /* Driver->Context = rndisDriver; */
616
617         memset(&rndis_filter, 0, sizeof(struct rndis_filter_driver_object));
618
619         /*rndisDriver->Driver = Driver;
620
621         ASSERT(Driver->OnLinkStatusChanged);
622         rndisDriver->OnLinkStatusChanged = Driver->OnLinkStatusChanged;*/
623
624         /* Save the original dispatch handlers before we override it */
625         rndis_filter.inner_drv.base.OnDeviceAdd = drv->base.OnDeviceAdd;
626         rndis_filter.inner_drv.base.OnDeviceRemove =
627                                         drv->base.OnDeviceRemove;
628         rndis_filter.inner_drv.base.OnCleanup = drv->base.OnCleanup;
629
630         /* ASSERT(Driver->OnSend); */
631         /* ASSERT(Driver->OnReceiveCallback); */
632         rndis_filter.inner_drv.send = drv->send;
633         rndis_filter.inner_drv.recv_cb = drv->recv_cb;
634         rndis_filter.inner_drv.link_status_change =
635                                         drv->link_status_change;
636
637         /* Override */
638         drv->base.OnDeviceAdd = rndis_filte_device_add;
639         drv->base.OnDeviceRemove = rndis_filter_device_remove;
640         drv->base.OnCleanup = rndis_filter_cleanup;
641         drv->send = rndis_filter_send;
642         /* Driver->QueryLinkStatus = RndisFilterQueryDeviceLinkStatus; */
643         drv->recv_cb = rndis_filter_receive;
644
645         return 0;
646 }
647
648 static int rndis_filter_init_device(struct rndis_device *dev)
649 {
650         struct rndis_request *request;
651         struct rndis_initialize_request *init;
652         struct rndis_initialize_complete *init_complete;
653         u32 status;
654         int ret;
655
656         request = get_rndis_request(dev, REMOTE_NDIS_INITIALIZE_MSG,
657                         RNDIS_MESSAGE_SIZE(struct rndis_initialize_request));
658         if (!request) {
659                 ret = -1;
660                 goto Cleanup;
661         }
662
663         /* Setup the rndis set */
664         init = &request->request_msg.msg.init_req;
665         init->major_ver = RNDIS_MAJOR_VERSION;
666         init->minor_ver = RNDIS_MINOR_VERSION;
667         /* FIXME: Use 1536 - rounded ethernet frame size */
668         init->max_xfer_size = 2048;
669
670         dev->state = RNDIS_DEV_INITIALIZING;
671
672         ret = rndis_filter_send_request(dev, request);
673         if (ret != 0) {
674                 dev->state = RNDIS_DEV_UNINITIALIZED;
675                 goto Cleanup;
676         }
677
678         osd_waitevent_wait(request->waitevent);
679
680         init_complete = &request->response_msg.msg.init_complete;
681         status = init_complete->status;
682         if (status == RNDIS_STATUS_SUCCESS) {
683                 dev->state = RNDIS_DEV_INITIALIZED;
684                 ret = 0;
685         } else {
686                 dev->state = RNDIS_DEV_UNINITIALIZED;
687                 ret = -1;
688         }
689
690 Cleanup:
691         if (request)
692                 put_rndis_request(dev, request);
693
694         return ret;
695 }
696
697 static void rndis_filter_halt_device(struct rndis_device *dev)
698 {
699         struct rndis_request *request;
700         struct rndis_halt_request *halt;
701
702         /* Attempt to do a rndis device halt */
703         request = get_rndis_request(dev, REMOTE_NDIS_HALT_MSG,
704                                 RNDIS_MESSAGE_SIZE(struct rndis_halt_request));
705         if (!request)
706                 goto Cleanup;
707
708         /* Setup the rndis set */
709         halt = &request->request_msg.msg.halt_req;
710         halt->req_id = atomic_inc_return(&dev->new_req_id);
711
712         /* Ignore return since this msg is optional. */
713         rndis_filter_send_request(dev, request);
714
715         dev->state = RNDIS_DEV_UNINITIALIZED;
716
717 Cleanup:
718         if (request)
719                 put_rndis_request(dev, request);
720         return;
721 }
722
723 static int rndis_filter_open_device(struct rndis_device *dev)
724 {
725         int ret;
726
727         if (dev->state != RNDIS_DEV_INITIALIZED)
728                 return 0;
729
730         ret = rndis_filter_set_packet_filter(dev,
731                                          NDIS_PACKET_TYPE_BROADCAST |
732                                          NDIS_PACKET_TYPE_ALL_MULTICAST |
733                                          NDIS_PACKET_TYPE_DIRECTED);
734         if (ret == 0)
735                 dev->state = RNDIS_DEV_DATAINITIALIZED;
736
737         return ret;
738 }
739
740 static int rndis_filter_close_device(struct rndis_device *dev)
741 {
742         int ret;
743
744         if (dev->state != RNDIS_DEV_DATAINITIALIZED)
745                 return 0;
746
747         ret = rndis_filter_set_packet_filter(dev, 0);
748         if (ret == 0)
749                 dev->state = RNDIS_DEV_INITIALIZED;
750
751         return ret;
752 }
753
754 static int rndis_filte_device_add(struct hv_device *dev,
755                                   void *additional_info)
756 {
757         int ret;
758         struct netvsc_device *netDevice;
759         struct rndis_device *rndisDevice;
760         struct netvsc_device_info *deviceInfo = additional_info;
761
762         rndisDevice = get_rndis_device();
763         if (!rndisDevice)
764                 return -1;
765
766         DPRINT_DBG(NETVSC, "rndis device object allocated - %p", rndisDevice);
767
768         /*
769          * Let the inner driver handle this first to create the netvsc channel
770          * NOTE! Once the channel is created, we may get a receive callback
771          * (RndisFilterOnReceive()) before this call is completed
772          */
773         ret = rndis_filter.inner_drv.base.OnDeviceAdd(dev, additional_info);
774         if (ret != 0) {
775                 kfree(rndisDevice);
776                 return ret;
777         }
778
779
780         /* Initialize the rndis device */
781         netDevice = dev->Extension;
782         /* ASSERT(netDevice); */
783         /* ASSERT(netDevice->Device); */
784
785         netDevice->extension = rndisDevice;
786         rndisDevice->net_dev = netDevice;
787
788         /* Send the rndis initialization message */
789         ret = rndis_filter_init_device(rndisDevice);
790         if (ret != 0) {
791                 /*
792                  * TODO: If rndis init failed, we will need to shut down the
793                  * channel
794                  */
795         }
796
797         /* Get the mac address */
798         ret = rndis_filter_query_device_mac(rndisDevice);
799         if (ret != 0) {
800                 /*
801                  * TODO: shutdown rndis device and the channel
802                  */
803         }
804
805         DPRINT_INFO(NETVSC, "Device 0x%p mac addr %pM",
806                     rndisDevice, rndisDevice->hw_mac_adr);
807
808         memcpy(deviceInfo->mac_adr, rndisDevice->hw_mac_adr, ETH_ALEN);
809
810         rndis_filter_query_device_link_status(rndisDevice);
811
812         deviceInfo->link_state = rndisDevice->link_stat;
813         DPRINT_INFO(NETVSC, "Device 0x%p link state %s", rndisDevice,
814                     ((deviceInfo->link_state) ? ("down") : ("up")));
815
816         return ret;
817 }
818
819 static int rndis_filter_device_remove(struct hv_device *dev)
820 {
821         struct netvsc_device *net_dev = dev->Extension;
822         struct rndis_device *rndis_dev = net_dev->extension;
823
824         /* Halt and release the rndis device */
825         rndis_filter_halt_device(rndis_dev);
826
827         kfree(rndis_dev);
828         net_dev->extension = NULL;
829
830         /* Pass control to inner driver to remove the device */
831         rndis_filter.inner_drv.base.OnDeviceRemove(dev);
832
833         return 0;
834 }
835
836 static void rndis_filter_cleanup(struct hv_driver *drv)
837 {
838 }
839
840 int rndis_filter_open(struct hv_device *dev)
841 {
842         struct netvsc_device *netDevice = dev->Extension;
843
844         if (!netDevice)
845                 return -EINVAL;
846
847         return rndis_filter_open_device(netDevice->extension);
848 }
849
850 int rndis_filter_close(struct hv_device *dev)
851 {
852         struct netvsc_device *netDevice = dev->Extension;
853
854         if (!netDevice)
855                 return -EINVAL;
856
857         return rndis_filter_close_device(netDevice->extension);
858 }
859
860 static int rndis_filter_send(struct hv_device *dev,
861                              struct hv_netvsc_packet *pkt)
862 {
863         int ret;
864         struct rndis_filter_packet *filterPacket;
865         struct rndis_message *rndisMessage;
866         struct rndis_packet *rndisPacket;
867         u32 rndisMessageSize;
868
869         /* Add the rndis header */
870         filterPacket = (struct rndis_filter_packet *)pkt->extension;
871         /* ASSERT(filterPacket); */
872
873         memset(filterPacket, 0, sizeof(struct rndis_filter_packet));
874
875         rndisMessage = &filterPacket->msg;
876         rndisMessageSize = RNDIS_MESSAGE_SIZE(struct rndis_packet);
877
878         rndisMessage->ndis_msg_type = REMOTE_NDIS_PACKET_MSG;
879         rndisMessage->msg_len = pkt->total_data_buflen +
880                                       rndisMessageSize;
881
882         rndisPacket = &rndisMessage->msg.pkt;
883         rndisPacket->data_offset = sizeof(struct rndis_packet);
884         rndisPacket->data_len = pkt->total_data_buflen;
885
886         pkt->is_data_pkt = true;
887         pkt->page_buf[0].Pfn = virt_to_phys(rndisMessage) >> PAGE_SHIFT;
888         pkt->page_buf[0].Offset =
889                         (unsigned long)rndisMessage & (PAGE_SIZE-1);
890         pkt->page_buf[0].Length = rndisMessageSize;
891
892         /* Save the packet send completion and context */
893         filterPacket->completion = pkt->completion.send.send_completion;
894         filterPacket->completion_ctx =
895                                 pkt->completion.send.send_completion_ctx;
896
897         /* Use ours */
898         pkt->completion.send.send_completion = rndis_filter_send_completion;
899         pkt->completion.send.send_completion_ctx = filterPacket;
900
901         ret = rndis_filter.inner_drv.send(dev, pkt);
902         if (ret != 0) {
903                 /*
904                  * Reset the completion to originals to allow retries from
905                  * above
906                  */
907                 pkt->completion.send.send_completion =
908                                 filterPacket->completion;
909                 pkt->completion.send.send_completion_ctx =
910                                 filterPacket->completion_ctx;
911         }
912
913         return ret;
914 }
915
916 static void rndis_filter_send_completion(void *ctx)
917 {
918         struct rndis_filter_packet *filterPacket = ctx;
919
920         /* Pass it back to the original handler */
921         filterPacket->completion(filterPacket->completion_ctx);
922 }
923
924
925 static void rndis_filter_send_request_completion(void *ctx)
926 {
927         /* Noop */
928 }