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