linux/drivers/staging/hv/rndis_filter.c
<<
>>
Prefs
   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 */
  33struct rndis_filter_driver_object {
  34        /* The original driver */
  35        struct netvsc_driver inner_drv;
  36};
  37
  38enum rndis_device_state {
  39        RNDIS_DEV_UNINITIALIZED = 0,
  40        RNDIS_DEV_INITIALIZING,
  41        RNDIS_DEV_INITIALIZED,
  42        RNDIS_DEV_DATAINITIALIZED,
  43};
  44
  45struct 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
  58struct 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
  77struct rndis_filter_packet {
  78        void *completion_ctx;
  79        void (*completion)(void *context);
  80        struct rndis_message msg;
  81};
  82
  83
  84static int rndis_filte_device_add(struct hv_device *dev,
  85                                  void *additional_info);
  86
  87static int rndis_filter_device_remove(struct hv_device *dev);
  88
  89static void rndis_filter_cleanup(struct hv_driver *drv);
  90
  91static int rndis_filter_send(struct hv_device *dev,
  92                             struct hv_netvsc_packet *pkt);
  93
  94static void rndis_filter_send_completion(void *ctx);
  95
  96static void rndis_filter_send_request_completion(void *ctx);
  97
  98
  99/* The one and only */
 100static struct rndis_filter_driver_object rndis_filter;
 101
 102static 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
 119static 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
 158static 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
 171static 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
 245static 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
 273static 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
 333static 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
 352static 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
 383static 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
 479static 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
 527Cleanup:
 528        if (request)
 529                put_rndis_request(dev, request);
 530
 531        return ret;
 532}
 533
 534static 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
 543static 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
 552static 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
 601Cleanup:
 602        if (request)
 603                put_rndis_request(dev, request);
 604Exit:
 605        return ret;
 606}
 607
 608int 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
 648static 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
 690Cleanup:
 691        if (request)
 692                put_rndis_request(dev, request);
 693
 694        return ret;
 695}
 696
 697static 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
 717Cleanup:
 718        if (request)
 719                put_rndis_request(dev, request);
 720        return;
 721}
 722
 723static 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
 740static 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
 754static 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
 819static 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
 836static void rndis_filter_cleanup(struct hv_driver *drv)
 837{
 838}
 839
 840int 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
 850int 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
 860static 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
 916static 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
 925static void rndis_filter_send_request_completion(void *ctx)
 926{
 927        /* Noop */
 928}
 929