linux/drivers/staging/hv/blkvsc_drv.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/init.h>
  22#include <linux/module.h>
  23#include <linux/device.h>
  24#include <linux/blkdev.h>
  25#include <linux/major.h>
  26#include <linux/delay.h>
  27#include <linux/hdreg.h>
  28#include <scsi/scsi.h>
  29#include <scsi/scsi_cmnd.h>
  30#include <scsi/scsi_eh.h>
  31#include <scsi/scsi_dbg.h>
  32#include "osd.h"
  33#include "logging.h"
  34#include "vmbus.h"
  35#include "StorVscApi.h"
  36
  37
  38#define BLKVSC_MINORS   64
  39
  40enum blkvsc_device_type {
  41        UNKNOWN_DEV_TYPE,
  42        HARDDISK_TYPE,
  43        DVD_TYPE,
  44};
  45
  46/*
  47 * This request ties the struct request and struct
  48 * blkvsc_request/hv_storvsc_request together A struct request may be
  49 * represented by 1 or more struct blkvsc_request
  50 */
  51struct blkvsc_request_group {
  52        int outstanding;
  53        int status;
  54        struct list_head blkvsc_req_list;       /* list of blkvsc_requests */
  55};
  56
  57struct blkvsc_request {
  58        /* blkvsc_request_group.blkvsc_req_list */
  59        struct list_head req_entry;
  60
  61        /* block_device_context.pending_list */
  62        struct list_head pend_entry;
  63
  64        /* This may be null if we generate a request internally */
  65        struct request *req;
  66
  67        struct block_device_context *dev;
  68
  69        /* The group this request is part of. Maybe null */
  70        struct blkvsc_request_group *group;
  71
  72        wait_queue_head_t wevent;
  73        int cond;
  74
  75        int write;
  76        sector_t sector_start;
  77        unsigned long sector_count;
  78
  79        unsigned char sense_buffer[SCSI_SENSE_BUFFERSIZE];
  80        unsigned char cmd_len;
  81        unsigned char cmnd[MAX_COMMAND_SIZE];
  82
  83        struct hv_storvsc_request request;
  84        /*
  85         * !!!DO NOT ADD ANYTHING BELOW HERE!!! Otherwise, memory can overlap,
  86         * because - The extension buffer falls right here and is pointed to by
  87         * request.Extension;
  88         * Which sounds like a horrible idea, who designed this?
  89         */
  90};
  91
  92/* Per device structure */
  93struct block_device_context {
  94        /* point back to our device context */
  95        struct device_context *device_ctx;
  96        struct kmem_cache *request_pool;
  97        spinlock_t lock;
  98        struct gendisk *gd;
  99        enum blkvsc_device_type device_type;
 100        struct list_head pending_list;
 101
 102        unsigned char device_id[64];
 103        unsigned int device_id_len;
 104        int num_outstanding_reqs;
 105        int shutting_down;
 106        int media_not_present;
 107        unsigned int sector_size;
 108        sector_t capacity;
 109        unsigned int port;
 110        unsigned char path;
 111        unsigned char target;
 112        int users;
 113};
 114
 115/* Per driver */
 116struct blkvsc_driver_context {
 117        /* !! These must be the first 2 fields !! */
 118        /* FIXME this is a bug! */
 119        struct driver_context drv_ctx;
 120        struct storvsc_driver_object drv_obj;
 121};
 122
 123/* Static decl */
 124static int blkvsc_probe(struct device *dev);
 125static int blkvsc_remove(struct device *device);
 126static void blkvsc_shutdown(struct device *device);
 127
 128static int blkvsc_open(struct block_device *bdev,  fmode_t mode);
 129static int blkvsc_release(struct gendisk *disk, fmode_t mode);
 130static int blkvsc_media_changed(struct gendisk *gd);
 131static int blkvsc_revalidate_disk(struct gendisk *gd);
 132static int blkvsc_getgeo(struct block_device *bd, struct hd_geometry *hg);
 133static int blkvsc_ioctl(struct block_device *bd, fmode_t mode,
 134                        unsigned cmd, unsigned long argument);
 135static void blkvsc_request(struct request_queue *queue);
 136static void blkvsc_request_completion(struct hv_storvsc_request *request);
 137static int blkvsc_do_request(struct block_device_context *blkdev,
 138                             struct request *req);
 139static int blkvsc_submit_request(struct blkvsc_request *blkvsc_req,
 140                void (*request_completion)(struct hv_storvsc_request *));
 141static void blkvsc_init_rw(struct blkvsc_request *blkvsc_req);
 142static void blkvsc_cmd_completion(struct hv_storvsc_request *request);
 143static int blkvsc_do_inquiry(struct block_device_context *blkdev);
 144static int blkvsc_do_read_capacity(struct block_device_context *blkdev);
 145static int blkvsc_do_read_capacity16(struct block_device_context *blkdev);
 146static int blkvsc_do_flush(struct block_device_context *blkdev);
 147static int blkvsc_cancel_pending_reqs(struct block_device_context *blkdev);
 148static int blkvsc_do_pending_reqs(struct block_device_context *blkdev);
 149
 150
 151static int blkvsc_ringbuffer_size = BLKVSC_RING_BUFFER_SIZE;
 152
 153/* The one and only one */
 154static struct blkvsc_driver_context g_blkvsc_drv;
 155
 156static struct block_device_operations block_ops = {
 157        .owner = THIS_MODULE,
 158        .open = blkvsc_open,
 159        .release = blkvsc_release,
 160        .media_changed = blkvsc_media_changed,
 161        .revalidate_disk = blkvsc_revalidate_disk,
 162        .getgeo = blkvsc_getgeo,
 163        .ioctl  = blkvsc_ioctl,
 164};
 165
 166/**
 167 * blkvsc_drv_init -  BlkVsc driver initialization.
 168 */
 169static int blkvsc_drv_init(int (*drv_init)(struct hv_driver *drv))
 170{
 171        struct storvsc_driver_object *storvsc_drv_obj = &g_blkvsc_drv.drv_obj;
 172        struct driver_context *drv_ctx = &g_blkvsc_drv.drv_ctx;
 173        int ret;
 174
 175        DPRINT_ENTER(BLKVSC_DRV);
 176
 177        vmbus_get_interface(&storvsc_drv_obj->Base.VmbusChannelInterface);
 178
 179        storvsc_drv_obj->RingBufferSize = blkvsc_ringbuffer_size;
 180
 181        /* Callback to client driver to complete the initialization */
 182        drv_init(&storvsc_drv_obj->Base);
 183
 184        drv_ctx->driver.name = storvsc_drv_obj->Base.name;
 185        memcpy(&drv_ctx->class_id, &storvsc_drv_obj->Base.deviceType,
 186               sizeof(struct hv_guid));
 187
 188        drv_ctx->probe = blkvsc_probe;
 189        drv_ctx->remove = blkvsc_remove;
 190        drv_ctx->shutdown = blkvsc_shutdown;
 191
 192        /* The driver belongs to vmbus */
 193        ret = vmbus_child_driver_register(drv_ctx);
 194
 195        DPRINT_EXIT(BLKVSC_DRV);
 196
 197        return ret;
 198}
 199
 200static int blkvsc_drv_exit_cb(struct device *dev, void *data)
 201{
 202        struct device **curr = (struct device **)data;
 203        *curr = dev;
 204        return 1; /* stop iterating */
 205}
 206
 207static void blkvsc_drv_exit(void)
 208{
 209        struct storvsc_driver_object *storvsc_drv_obj = &g_blkvsc_drv.drv_obj;
 210        struct driver_context *drv_ctx = &g_blkvsc_drv.drv_ctx;
 211        struct device *current_dev;
 212        int ret;
 213
 214        DPRINT_ENTER(BLKVSC_DRV);
 215
 216        while (1) {
 217                current_dev = NULL;
 218
 219                /* Get the device */
 220                ret = driver_for_each_device(&drv_ctx->driver, NULL,
 221                                             (void *) &current_dev,
 222                                             blkvsc_drv_exit_cb);
 223
 224                if (ret)
 225                        DPRINT_WARN(BLKVSC_DRV,
 226                                    "driver_for_each_device returned %d", ret);
 227
 228
 229                if (current_dev == NULL)
 230                        break;
 231
 232                /* Initiate removal from the top-down */
 233                device_unregister(current_dev);
 234        }
 235
 236        if (storvsc_drv_obj->Base.OnCleanup)
 237                storvsc_drv_obj->Base.OnCleanup(&storvsc_drv_obj->Base);
 238
 239        vmbus_child_driver_unregister(drv_ctx);
 240
 241        DPRINT_EXIT(BLKVSC_DRV);
 242
 243        return;
 244}
 245
 246/**
 247 * blkvsc_probe - Add a new device for this driver
 248 */
 249static int blkvsc_probe(struct device *device)
 250{
 251        struct driver_context *driver_ctx =
 252                                driver_to_driver_context(device->driver);
 253        struct blkvsc_driver_context *blkvsc_drv_ctx =
 254                                (struct blkvsc_driver_context *)driver_ctx;
 255        struct storvsc_driver_object *storvsc_drv_obj =
 256                                &blkvsc_drv_ctx->drv_obj;
 257        struct device_context *device_ctx = device_to_device_context(device);
 258        struct hv_device *device_obj = &device_ctx->device_obj;
 259
 260        struct block_device_context *blkdev = NULL;
 261        struct storvsc_device_info device_info;
 262        int major = 0;
 263        int devnum = 0;
 264        int ret = 0;
 265        static int ide0_registered;
 266        static int ide1_registered;
 267
 268        DPRINT_ENTER(BLKVSC_DRV);
 269
 270        DPRINT_DBG(BLKVSC_DRV, "blkvsc_probe - enter");
 271
 272        if (!storvsc_drv_obj->Base.OnDeviceAdd) {
 273                DPRINT_ERR(BLKVSC_DRV, "OnDeviceAdd() not set");
 274                ret = -1;
 275                goto Cleanup;
 276        }
 277
 278        blkdev = kzalloc(sizeof(struct block_device_context), GFP_KERNEL);
 279        if (!blkdev) {
 280                ret = -ENOMEM;
 281                goto Cleanup;
 282        }
 283
 284        INIT_LIST_HEAD(&blkdev->pending_list);
 285
 286        /* Initialize what we can here */
 287        spin_lock_init(&blkdev->lock);
 288
 289        ASSERT(sizeof(struct blkvsc_request_group) <=
 290                sizeof(struct blkvsc_request));
 291
 292        blkdev->request_pool = kmem_cache_create(dev_name(&device_ctx->device),
 293                                        sizeof(struct blkvsc_request) +
 294                                        storvsc_drv_obj->RequestExtSize, 0,
 295                                        SLAB_HWCACHE_ALIGN, NULL);
 296        if (!blkdev->request_pool) {
 297                ret = -ENOMEM;
 298                goto Cleanup;
 299        }
 300
 301
 302        /* Call to the vsc driver to add the device */
 303        ret = storvsc_drv_obj->Base.OnDeviceAdd(device_obj, &device_info);
 304        if (ret != 0) {
 305                DPRINT_ERR(BLKVSC_DRV, "unable to add blkvsc device");
 306                goto Cleanup;
 307        }
 308
 309        blkdev->device_ctx = device_ctx;
 310        /* this identified the device 0 or 1 */
 311        blkdev->target = device_info.TargetId;
 312        /* this identified the ide ctrl 0 or 1 */
 313        blkdev->path = device_info.PathId;
 314
 315        dev_set_drvdata(device, blkdev);
 316
 317        /* Calculate the major and device num */
 318        if (blkdev->path == 0) {
 319                major = IDE0_MAJOR;
 320                devnum = blkdev->path + blkdev->target;         /* 0 or 1 */
 321
 322                if (!ide0_registered) {
 323                        ret = register_blkdev(major, "ide");
 324                        if (ret != 0) {
 325                                DPRINT_ERR(BLKVSC_DRV,
 326                                           "register_blkdev() failed! ret %d",
 327                                           ret);
 328                                goto Remove;
 329                        }
 330
 331                        ide0_registered = 1;
 332                }
 333        } else if (blkdev->path == 1) {
 334                major = IDE1_MAJOR;
 335                devnum = blkdev->path + blkdev->target + 1; /* 2 or 3 */
 336
 337                if (!ide1_registered) {
 338                        ret = register_blkdev(major, "ide");
 339                        if (ret != 0) {
 340                                DPRINT_ERR(BLKVSC_DRV,
 341                                           "register_blkdev() failed! ret %d",
 342                                           ret);
 343                                goto Remove;
 344                        }
 345
 346                        ide1_registered = 1;
 347                }
 348        } else {
 349                DPRINT_ERR(BLKVSC_DRV, "invalid pathid");
 350                ret = -1;
 351                goto Cleanup;
 352        }
 353
 354        DPRINT_INFO(BLKVSC_DRV, "blkvsc registered for major %d!!", major);
 355
 356        blkdev->gd = alloc_disk(BLKVSC_MINORS);
 357        if (!blkdev->gd) {
 358                DPRINT_ERR(BLKVSC_DRV, "register_blkdev() failed! ret %d", ret);
 359                ret = -1;
 360                goto Cleanup;
 361        }
 362
 363        blkdev->gd->queue = blk_init_queue(blkvsc_request, &blkdev->lock);
 364
 365        blk_queue_max_segment_size(blkdev->gd->queue, PAGE_SIZE);
 366        blk_queue_max_phys_segments(blkdev->gd->queue,
 367                                    MAX_MULTIPAGE_BUFFER_COUNT);
 368        blk_queue_max_hw_segments(blkdev->gd->queue,
 369                                  MAX_MULTIPAGE_BUFFER_COUNT);
 370        blk_queue_segment_boundary(blkdev->gd->queue, PAGE_SIZE-1);
 371        blk_queue_bounce_limit(blkdev->gd->queue, BLK_BOUNCE_ANY);
 372        blk_queue_dma_alignment(blkdev->gd->queue, 511);
 373
 374        blkdev->gd->major = major;
 375        if (devnum == 1 || devnum == 3)
 376                blkdev->gd->first_minor = BLKVSC_MINORS;
 377        else
 378                blkdev->gd->first_minor = 0;
 379        blkdev->gd->fops = &block_ops;
 380        blkdev->gd->private_data = blkdev;
 381        sprintf(blkdev->gd->disk_name, "hd%c", 'a' + devnum);
 382
 383        blkvsc_do_inquiry(blkdev);
 384        if (blkdev->device_type == DVD_TYPE) {
 385                set_disk_ro(blkdev->gd, 1);
 386                blkdev->gd->flags |= GENHD_FL_REMOVABLE;
 387                blkvsc_do_read_capacity(blkdev);
 388        } else {
 389                blkvsc_do_read_capacity16(blkdev);
 390        }
 391
 392        set_capacity(blkdev->gd, blkdev->capacity * (blkdev->sector_size/512));
 393        blk_queue_logical_block_size(blkdev->gd->queue, blkdev->sector_size);
 394        /* go! */
 395        add_disk(blkdev->gd);
 396
 397        DPRINT_INFO(BLKVSC_DRV, "%s added!! capacity %lu sector_size %d",
 398                    blkdev->gd->disk_name, (unsigned long)blkdev->capacity,
 399                    blkdev->sector_size);
 400
 401        return ret;
 402
 403Remove:
 404        storvsc_drv_obj->Base.OnDeviceRemove(device_obj);
 405
 406Cleanup:
 407        if (blkdev) {
 408                if (blkdev->request_pool) {
 409                        kmem_cache_destroy(blkdev->request_pool);
 410                        blkdev->request_pool = NULL;
 411                }
 412                kfree(blkdev);
 413                blkdev = NULL;
 414        }
 415
 416        DPRINT_EXIT(BLKVSC_DRV);
 417
 418        return ret;
 419}
 420
 421static void blkvsc_shutdown(struct device *device)
 422{
 423        struct block_device_context *blkdev = dev_get_drvdata(device);
 424        unsigned long flags;
 425
 426        if (!blkdev)
 427                return;
 428
 429        DPRINT_DBG(BLKVSC_DRV, "blkvsc_shutdown - users %d disk %s\n",
 430                   blkdev->users, blkdev->gd->disk_name);
 431
 432        spin_lock_irqsave(&blkdev->lock, flags);
 433
 434        blkdev->shutting_down = 1;
 435
 436        blk_stop_queue(blkdev->gd->queue);
 437
 438        spin_unlock_irqrestore(&blkdev->lock, flags);
 439
 440        while (blkdev->num_outstanding_reqs) {
 441                DPRINT_INFO(STORVSC, "waiting for %d requests to complete...",
 442                            blkdev->num_outstanding_reqs);
 443                udelay(100);
 444        }
 445
 446        blkvsc_do_flush(blkdev);
 447
 448        spin_lock_irqsave(&blkdev->lock, flags);
 449
 450        blkvsc_cancel_pending_reqs(blkdev);
 451
 452        spin_unlock_irqrestore(&blkdev->lock, flags);
 453}
 454
 455static int blkvsc_do_flush(struct block_device_context *blkdev)
 456{
 457        struct blkvsc_request *blkvsc_req;
 458
 459        DPRINT_DBG(BLKVSC_DRV, "blkvsc_do_flush()\n");
 460
 461        if (blkdev->device_type != HARDDISK_TYPE)
 462                return 0;
 463
 464        blkvsc_req = kmem_cache_alloc(blkdev->request_pool, GFP_KERNEL);
 465        if (!blkvsc_req)
 466                return -ENOMEM;
 467
 468        memset(blkvsc_req, 0, sizeof(struct blkvsc_request));
 469        init_waitqueue_head(&blkvsc_req->wevent);
 470        blkvsc_req->dev = blkdev;
 471        blkvsc_req->req = NULL;
 472        blkvsc_req->write = 0;
 473
 474        blkvsc_req->request.DataBuffer.PfnArray[0] = 0;
 475        blkvsc_req->request.DataBuffer.Offset = 0;
 476        blkvsc_req->request.DataBuffer.Length = 0;
 477
 478        blkvsc_req->cmnd[0] = SYNCHRONIZE_CACHE;
 479        blkvsc_req->cmd_len = 10;
 480
 481        /*
 482         * Set this here since the completion routine may be invoked and
 483         * completed before we return
 484         */
 485        blkvsc_req->cond = 0;
 486        blkvsc_submit_request(blkvsc_req, blkvsc_cmd_completion);
 487
 488        wait_event_interruptible(blkvsc_req->wevent, blkvsc_req->cond);
 489
 490        kmem_cache_free(blkvsc_req->dev->request_pool, blkvsc_req);
 491
 492        return 0;
 493}
 494
 495/* Do a scsi INQUIRY cmd here to get the device type (ie disk or dvd) */
 496static int blkvsc_do_inquiry(struct block_device_context *blkdev)
 497{
 498        struct blkvsc_request *blkvsc_req;
 499        struct page *page_buf;
 500        unsigned char *buf;
 501        unsigned char device_type;
 502
 503        DPRINT_DBG(BLKVSC_DRV, "blkvsc_do_inquiry()\n");
 504
 505        blkvsc_req = kmem_cache_alloc(blkdev->request_pool, GFP_KERNEL);
 506        if (!blkvsc_req)
 507                return -ENOMEM;
 508
 509        memset(blkvsc_req, 0, sizeof(struct blkvsc_request));
 510        page_buf = alloc_page(GFP_KERNEL);
 511        if (!page_buf) {
 512                kmem_cache_free(blkvsc_req->dev->request_pool, blkvsc_req);
 513                return -ENOMEM;
 514        }
 515
 516        init_waitqueue_head(&blkvsc_req->wevent);
 517        blkvsc_req->dev = blkdev;
 518        blkvsc_req->req = NULL;
 519        blkvsc_req->write = 0;
 520
 521        blkvsc_req->request.DataBuffer.PfnArray[0] = page_to_pfn(page_buf);
 522        blkvsc_req->request.DataBuffer.Offset = 0;
 523        blkvsc_req->request.DataBuffer.Length = 64;
 524
 525        blkvsc_req->cmnd[0] = INQUIRY;
 526        blkvsc_req->cmnd[1] = 0x1;              /* Get product data */
 527        blkvsc_req->cmnd[2] = 0x83;             /* mode page 83 */
 528        blkvsc_req->cmnd[4] = 64;
 529        blkvsc_req->cmd_len = 6;
 530
 531        /*
 532         * Set this here since the completion routine may be invoked and
 533         * completed before we return
 534         */
 535        blkvsc_req->cond = 0;
 536
 537        blkvsc_submit_request(blkvsc_req, blkvsc_cmd_completion);
 538
 539        DPRINT_DBG(BLKVSC_DRV, "waiting %p to complete - cond %d\n",
 540                   blkvsc_req, blkvsc_req->cond);
 541
 542        wait_event_interruptible(blkvsc_req->wevent, blkvsc_req->cond);
 543
 544        buf = kmap(page_buf);
 545
 546        /* print_hex_dump_bytes("", DUMP_PREFIX_NONE, buf, 64); */
 547        /* be to le */
 548        device_type = buf[0] & 0x1F;
 549
 550        if (device_type == 0x0) {
 551                blkdev->device_type = HARDDISK_TYPE;
 552        } else if (device_type == 0x5) {
 553                blkdev->device_type = DVD_TYPE;
 554        } else {
 555                /* TODO: this is currently unsupported device type */
 556                blkdev->device_type = UNKNOWN_DEV_TYPE;
 557        }
 558
 559        DPRINT_DBG(BLKVSC_DRV, "device type %d \n", device_type);
 560
 561        blkdev->device_id_len = buf[7];
 562        if (blkdev->device_id_len > 64)
 563                blkdev->device_id_len = 64;
 564
 565        memcpy(blkdev->device_id, &buf[8], blkdev->device_id_len);
 566        /* printk_hex_dump_bytes("", DUMP_PREFIX_NONE, blkdev->device_id,
 567         * blkdev->device_id_len); */
 568
 569        kunmap(page_buf);
 570
 571        __free_page(page_buf);
 572
 573        kmem_cache_free(blkvsc_req->dev->request_pool, blkvsc_req);
 574
 575        return 0;
 576}
 577
 578/* Do a scsi READ_CAPACITY cmd here to get the size of the disk */
 579static int blkvsc_do_read_capacity(struct block_device_context *blkdev)
 580{
 581        struct blkvsc_request *blkvsc_req;
 582        struct page *page_buf;
 583        unsigned char *buf;
 584        struct scsi_sense_hdr sense_hdr;
 585
 586        DPRINT_DBG(BLKVSC_DRV, "blkvsc_do_read_capacity()\n");
 587
 588        blkdev->sector_size = 0;
 589        blkdev->capacity = 0;
 590        blkdev->media_not_present = 0; /* assume a disk is present */
 591
 592        blkvsc_req = kmem_cache_alloc(blkdev->request_pool, GFP_KERNEL);
 593        if (!blkvsc_req)
 594                return -ENOMEM;
 595
 596        memset(blkvsc_req, 0, sizeof(struct blkvsc_request));
 597        page_buf = alloc_page(GFP_KERNEL);
 598        if (!page_buf) {
 599                kmem_cache_free(blkvsc_req->dev->request_pool, blkvsc_req);
 600                return -ENOMEM;
 601        }
 602
 603        init_waitqueue_head(&blkvsc_req->wevent);
 604        blkvsc_req->dev = blkdev;
 605        blkvsc_req->req = NULL;
 606        blkvsc_req->write = 0;
 607
 608        blkvsc_req->request.DataBuffer.PfnArray[0] = page_to_pfn(page_buf);
 609        blkvsc_req->request.DataBuffer.Offset = 0;
 610        blkvsc_req->request.DataBuffer.Length = 8;
 611
 612        blkvsc_req->cmnd[0] = READ_CAPACITY;
 613        blkvsc_req->cmd_len = 16;
 614
 615        /*
 616         * Set this here since the completion routine may be invoked
 617         * and completed before we return
 618         */
 619        blkvsc_req->cond = 0;
 620
 621        blkvsc_submit_request(blkvsc_req, blkvsc_cmd_completion);
 622
 623        DPRINT_DBG(BLKVSC_DRV, "waiting %p to complete - cond %d\n",
 624                   blkvsc_req, blkvsc_req->cond);
 625
 626        wait_event_interruptible(blkvsc_req->wevent, blkvsc_req->cond);
 627
 628        /* check error */
 629        if (blkvsc_req->request.Status) {
 630                scsi_normalize_sense(blkvsc_req->sense_buffer,
 631                                     SCSI_SENSE_BUFFERSIZE, &sense_hdr);
 632
 633                if (sense_hdr.asc == 0x3A) {
 634                        /* Medium not present */
 635                        blkdev->media_not_present = 1;
 636                }
 637                return 0;
 638        }
 639        buf = kmap(page_buf);
 640
 641        /* be to le */
 642        blkdev->capacity = ((buf[0] << 24) | (buf[1] << 16) |
 643                            (buf[2] << 8) | buf[3]) + 1;
 644        blkdev->sector_size = (buf[4] << 24) | (buf[5] << 16) |
 645                              (buf[6] << 8) | buf[7];
 646
 647        kunmap(page_buf);
 648
 649        __free_page(page_buf);
 650
 651        kmem_cache_free(blkvsc_req->dev->request_pool, blkvsc_req);
 652
 653        return 0;
 654}
 655
 656static int blkvsc_do_read_capacity16(struct block_device_context *blkdev)
 657{
 658        struct blkvsc_request *blkvsc_req;
 659        struct page *page_buf;
 660        unsigned char *buf;
 661        struct scsi_sense_hdr sense_hdr;
 662
 663        DPRINT_DBG(BLKVSC_DRV, "blkvsc_do_read_capacity16()\n");
 664
 665        blkdev->sector_size = 0;
 666        blkdev->capacity = 0;
 667        blkdev->media_not_present = 0; /* assume a disk is present */
 668
 669        blkvsc_req = kmem_cache_alloc(blkdev->request_pool, GFP_KERNEL);
 670        if (!blkvsc_req)
 671                return -ENOMEM;
 672
 673        memset(blkvsc_req, 0, sizeof(struct blkvsc_request));
 674        page_buf = alloc_page(GFP_KERNEL);
 675        if (!page_buf) {
 676                kmem_cache_free(blkvsc_req->dev->request_pool, blkvsc_req);
 677                return -ENOMEM;
 678        }
 679
 680        init_waitqueue_head(&blkvsc_req->wevent);
 681        blkvsc_req->dev = blkdev;
 682        blkvsc_req->req = NULL;
 683        blkvsc_req->write = 0;
 684
 685        blkvsc_req->request.DataBuffer.PfnArray[0] = page_to_pfn(page_buf);
 686        blkvsc_req->request.DataBuffer.Offset = 0;
 687        blkvsc_req->request.DataBuffer.Length = 12;
 688
 689        blkvsc_req->cmnd[0] = 0x9E; /* READ_CAPACITY16; */
 690        blkvsc_req->cmd_len = 16;
 691
 692        /*
 693         * Set this here since the completion routine may be invoked
 694         * and completed before we return
 695         */
 696        blkvsc_req->cond = 0;
 697
 698        blkvsc_submit_request(blkvsc_req, blkvsc_cmd_completion);
 699
 700        DPRINT_DBG(BLKVSC_DRV, "waiting %p to complete - cond %d\n",
 701                   blkvsc_req, blkvsc_req->cond);
 702
 703        wait_event_interruptible(blkvsc_req->wevent, blkvsc_req->cond);
 704
 705        /* check error */
 706        if (blkvsc_req->request.Status) {
 707                scsi_normalize_sense(blkvsc_req->sense_buffer,
 708                                     SCSI_SENSE_BUFFERSIZE, &sense_hdr);
 709                if (sense_hdr.asc == 0x3A) {
 710                        /* Medium not present */
 711                        blkdev->media_not_present = 1;
 712                }
 713                return 0;
 714        }
 715        buf = kmap(page_buf);
 716
 717        /* be to le */
 718        blkdev->capacity = be64_to_cpu(*(unsigned long long *) &buf[0]) + 1;
 719        blkdev->sector_size = be32_to_cpu(*(unsigned int *)&buf[8]);
 720
 721#if 0
 722        blkdev->capacity = ((buf[0] << 24) | (buf[1] << 16) |
 723                            (buf[2] << 8) | buf[3]) + 1;
 724        blkdev->sector_size = (buf[4] << 24) | (buf[5] << 16) |
 725                              (buf[6] << 8) | buf[7];
 726#endif
 727
 728        kunmap(page_buf);
 729
 730        __free_page(page_buf);
 731
 732        kmem_cache_free(blkvsc_req->dev->request_pool, blkvsc_req);
 733
 734        return 0;
 735}
 736
 737/**
 738 * blkvsc_remove() - Callback when our device is removed
 739 */
 740static int blkvsc_remove(struct device *device)
 741{
 742        struct driver_context *driver_ctx =
 743                                driver_to_driver_context(device->driver);
 744        struct blkvsc_driver_context *blkvsc_drv_ctx =
 745                                (struct blkvsc_driver_context *)driver_ctx;
 746        struct storvsc_driver_object *storvsc_drv_obj =
 747                                &blkvsc_drv_ctx->drv_obj;
 748        struct device_context *device_ctx = device_to_device_context(device);
 749        struct hv_device *device_obj = &device_ctx->device_obj;
 750        struct block_device_context *blkdev = dev_get_drvdata(device);
 751        unsigned long flags;
 752        int ret;
 753
 754        DPRINT_ENTER(BLKVSC_DRV);
 755
 756        DPRINT_DBG(BLKVSC_DRV, "blkvsc_remove()\n");
 757
 758        if (!storvsc_drv_obj->Base.OnDeviceRemove) {
 759                DPRINT_EXIT(BLKVSC_DRV);
 760                return -1;
 761        }
 762
 763        /*
 764         * Call to the vsc driver to let it know that the device is being
 765         * removed
 766         */
 767        ret = storvsc_drv_obj->Base.OnDeviceRemove(device_obj);
 768        if (ret != 0) {
 769                /* TODO: */
 770                DPRINT_ERR(BLKVSC_DRV,
 771                           "unable to remove blkvsc device (ret %d)", ret);
 772        }
 773
 774        /* Get to a known state */
 775        spin_lock_irqsave(&blkdev->lock, flags);
 776
 777        blkdev->shutting_down = 1;
 778
 779        blk_stop_queue(blkdev->gd->queue);
 780
 781        spin_unlock_irqrestore(&blkdev->lock, flags);
 782
 783        while (blkdev->num_outstanding_reqs) {
 784                DPRINT_INFO(STORVSC, "waiting for %d requests to complete...",
 785                            blkdev->num_outstanding_reqs);
 786                udelay(100);
 787        }
 788
 789        blkvsc_do_flush(blkdev);
 790
 791        spin_lock_irqsave(&blkdev->lock, flags);
 792
 793        blkvsc_cancel_pending_reqs(blkdev);
 794
 795        spin_unlock_irqrestore(&blkdev->lock, flags);
 796
 797        blk_cleanup_queue(blkdev->gd->queue);
 798
 799        del_gendisk(blkdev->gd);
 800
 801        kmem_cache_destroy(blkdev->request_pool);
 802
 803        kfree(blkdev);
 804
 805        DPRINT_EXIT(BLKVSC_DRV);
 806
 807        return ret;
 808}
 809
 810static void blkvsc_init_rw(struct blkvsc_request *blkvsc_req)
 811{
 812        ASSERT(blkvsc_req->req);
 813        ASSERT(blkvsc_req->sector_count <= (MAX_MULTIPAGE_BUFFER_COUNT*8));
 814
 815        blkvsc_req->cmd_len = 16;
 816
 817        if (blkvsc_req->sector_start > 0xffffffff) {
 818                if (rq_data_dir(blkvsc_req->req)) {
 819                        blkvsc_req->write = 1;
 820                        blkvsc_req->cmnd[0] = WRITE_16;
 821                } else {
 822                        blkvsc_req->write = 0;
 823                        blkvsc_req->cmnd[0] = READ_16;
 824                }
 825
 826                blkvsc_req->cmnd[1] |= blk_fua_rq(blkvsc_req->req) ? 0x8 : 0;
 827
 828                *(unsigned long long *)&blkvsc_req->cmnd[2] =
 829                                cpu_to_be64(blkvsc_req->sector_start);
 830                *(unsigned int *)&blkvsc_req->cmnd[10] =
 831                                cpu_to_be32(blkvsc_req->sector_count);
 832        } else if ((blkvsc_req->sector_count > 0xff) ||
 833                   (blkvsc_req->sector_start > 0x1fffff)) {
 834                if (rq_data_dir(blkvsc_req->req)) {
 835                        blkvsc_req->write = 1;
 836                        blkvsc_req->cmnd[0] = WRITE_10;
 837                } else {
 838                        blkvsc_req->write = 0;
 839                        blkvsc_req->cmnd[0] = READ_10;
 840                }
 841
 842                blkvsc_req->cmnd[1] |= blk_fua_rq(blkvsc_req->req) ? 0x8 : 0;
 843
 844                *(unsigned int *)&blkvsc_req->cmnd[2] =
 845                                cpu_to_be32(blkvsc_req->sector_start);
 846                *(unsigned short *)&blkvsc_req->cmnd[7] =
 847                                cpu_to_be16(blkvsc_req->sector_count);
 848        } else {
 849                if (rq_data_dir(blkvsc_req->req)) {
 850                        blkvsc_req->write = 1;
 851                        blkvsc_req->cmnd[0] = WRITE_6;
 852                } else {
 853                        blkvsc_req->write = 0;
 854                        blkvsc_req->cmnd[0] = READ_6;
 855                }
 856
 857                *(unsigned int *)&blkvsc_req->cmnd[1] =
 858                                cpu_to_be32(blkvsc_req->sector_start) >> 8;
 859                blkvsc_req->cmnd[1] &= 0x1f;
 860                blkvsc_req->cmnd[4] = (unsigned char)blkvsc_req->sector_count;
 861        }
 862}
 863
 864static int blkvsc_submit_request(struct blkvsc_request *blkvsc_req,
 865                        void (*request_completion)(struct hv_storvsc_request *))
 866{
 867        struct block_device_context *blkdev = blkvsc_req->dev;
 868        struct device_context *device_ctx = blkdev->device_ctx;
 869        struct driver_context *driver_ctx =
 870                        driver_to_driver_context(device_ctx->device.driver);
 871        struct blkvsc_driver_context *blkvsc_drv_ctx =
 872                        (struct blkvsc_driver_context *)driver_ctx;
 873        struct storvsc_driver_object *storvsc_drv_obj =
 874                        &blkvsc_drv_ctx->drv_obj;
 875        struct hv_storvsc_request *storvsc_req;
 876        int ret;
 877
 878        DPRINT_DBG(BLKVSC_DRV, "blkvsc_submit_request() - "
 879                   "req %p type %s start_sector %lu count %ld offset %d "
 880                   "len %d\n", blkvsc_req,
 881                   (blkvsc_req->write) ? "WRITE" : "READ",
 882                   (unsigned long) blkvsc_req->sector_start,
 883                   blkvsc_req->sector_count,
 884                   blkvsc_req->request.DataBuffer.Offset,
 885                   blkvsc_req->request.DataBuffer.Length);
 886#if 0
 887        for (i = 0; i < (blkvsc_req->request.DataBuffer.Length >> 12); i++) {
 888                DPRINT_DBG(BLKVSC_DRV, "blkvsc_submit_request() - "
 889                           "req %p pfn[%d] %llx\n",
 890                           blkvsc_req, i,
 891                           blkvsc_req->request.DataBuffer.PfnArray[i]);
 892        }
 893#endif
 894
 895        storvsc_req = &blkvsc_req->request;
 896        storvsc_req->Extension = (void *)((unsigned long)blkvsc_req +
 897                                          sizeof(struct blkvsc_request));
 898
 899        storvsc_req->Type = blkvsc_req->write ? WRITE_TYPE : READ_TYPE;
 900
 901        storvsc_req->OnIOCompletion = request_completion;
 902        storvsc_req->Context = blkvsc_req;
 903
 904        storvsc_req->Host = blkdev->port;
 905        storvsc_req->Bus = blkdev->path;
 906        storvsc_req->TargetId = blkdev->target;
 907        storvsc_req->LunId = 0;  /* this is not really used at all */
 908
 909        storvsc_req->CdbLen = blkvsc_req->cmd_len;
 910        storvsc_req->Cdb = blkvsc_req->cmnd;
 911
 912        storvsc_req->SenseBuffer = blkvsc_req->sense_buffer;
 913        storvsc_req->SenseBufferSize = SCSI_SENSE_BUFFERSIZE;
 914
 915        ret = storvsc_drv_obj->OnIORequest(&blkdev->device_ctx->device_obj,
 916                                           &blkvsc_req->request);
 917        if (ret == 0)
 918                blkdev->num_outstanding_reqs++;
 919
 920        return ret;
 921}
 922
 923/*
 924 * We break the request into 1 or more blkvsc_requests and submit
 925 * them.  If we cant submit them all, we put them on the
 926 * pending_list. The blkvsc_request() will work on the pending_list.
 927 */
 928static int blkvsc_do_request(struct block_device_context *blkdev,
 929                             struct request *req)
 930{
 931        struct bio *bio = NULL;
 932        struct bio_vec *bvec = NULL;
 933        struct bio_vec *prev_bvec = NULL;
 934        struct blkvsc_request *blkvsc_req = NULL;
 935        struct blkvsc_request *tmp;
 936        int databuf_idx = 0;
 937        int seg_idx = 0;
 938        sector_t start_sector;
 939        unsigned long num_sectors = 0;
 940        int ret = 0;
 941        int pending = 0;
 942        struct blkvsc_request_group *group = NULL;
 943
 944        DPRINT_DBG(BLKVSC_DRV, "blkdev %p req %p sect %lu \n", blkdev, req,
 945                  (unsigned long)blk_rq_pos(req));
 946
 947        /* Create a group to tie req to list of blkvsc_reqs */
 948        group = kmem_cache_alloc(blkdev->request_pool, GFP_ATOMIC);
 949        if (!group)
 950                return -ENOMEM;
 951
 952        INIT_LIST_HEAD(&group->blkvsc_req_list);
 953        group->outstanding = group->status = 0;
 954
 955        start_sector = blk_rq_pos(req);
 956
 957        /* foreach bio in the request */
 958        if (req->bio) {
 959                for (bio = req->bio; bio; bio = bio->bi_next) {
 960                        /*
 961                         * Map this bio into an existing or new storvsc request
 962                         */
 963                        bio_for_each_segment(bvec, bio, seg_idx) {
 964                                DPRINT_DBG(BLKVSC_DRV, "bio_for_each_segment() "
 965                                           "- req %p bio %p bvec %p seg_idx %d "
 966                                           "databuf_idx %d\n", req, bio, bvec,
 967                                           seg_idx, databuf_idx);
 968
 969                                /* Get a new storvsc request */
 970                                /* 1st-time */
 971                                if ((!blkvsc_req) ||
 972                                    (databuf_idx >= MAX_MULTIPAGE_BUFFER_COUNT)
 973                                    /* hole at the begin of page */
 974                                    || (bvec->bv_offset != 0) ||
 975                                    /* hold at the end of page */
 976                                    (prev_bvec &&
 977                                     (prev_bvec->bv_len != PAGE_SIZE))) {
 978                                        /* submit the prev one */
 979                                        if (blkvsc_req) {
 980                                                blkvsc_req->sector_start = start_sector;
 981                                                sector_div(blkvsc_req->sector_start, (blkdev->sector_size >> 9));
 982
 983                                                blkvsc_req->sector_count = num_sectors / (blkdev->sector_size >> 9);
 984                                                blkvsc_init_rw(blkvsc_req);
 985                                        }
 986
 987                                        /*
 988                                         * Create new blkvsc_req to represent
 989                                         * the current bvec
 990                                         */
 991                                        blkvsc_req = kmem_cache_alloc(blkdev->request_pool, GFP_ATOMIC);
 992                                        if (!blkvsc_req) {
 993                                                /* free up everything */
 994                                                list_for_each_entry_safe(
 995                                                        blkvsc_req, tmp,
 996                                                        &group->blkvsc_req_list,
 997                                                        req_entry) {
 998                                                        list_del(&blkvsc_req->req_entry);
 999                                                        kmem_cache_free(blkdev->request_pool, blkvsc_req);
1000                                                }
1001
1002                                                kmem_cache_free(blkdev->request_pool, group);
1003                                                return -ENOMEM;
1004                                        }
1005
1006                                        memset(blkvsc_req, 0,
1007                                               sizeof(struct blkvsc_request));
1008
1009                                        blkvsc_req->dev = blkdev;
1010                                        blkvsc_req->req = req;
1011                                        blkvsc_req->request.DataBuffer.Offset = bvec->bv_offset;
1012                                        blkvsc_req->request.DataBuffer.Length = 0;
1013
1014                                        /* Add to the group */
1015                                        blkvsc_req->group = group;
1016                                        blkvsc_req->group->outstanding++;
1017                                        list_add_tail(&blkvsc_req->req_entry,
1018                                                &blkvsc_req->group->blkvsc_req_list);
1019
1020                                        start_sector += num_sectors;
1021                                        num_sectors = 0;
1022                                        databuf_idx = 0;
1023                                }
1024
1025                                /* Add the curr bvec/segment to the curr blkvsc_req */
1026                                blkvsc_req->request.DataBuffer.PfnArray[databuf_idx] = page_to_pfn(bvec->bv_page);
1027                                blkvsc_req->request.DataBuffer.Length += bvec->bv_len;
1028
1029                                prev_bvec = bvec;
1030
1031                                databuf_idx++;
1032                                num_sectors += bvec->bv_len >> 9;
1033
1034                        } /* bio_for_each_segment */
1035
1036                } /* rq_for_each_bio */
1037        }
1038
1039        /* Handle the last one */
1040        if (blkvsc_req) {
1041                DPRINT_DBG(BLKVSC_DRV, "blkdev %p req %p group %p count %d\n",
1042                           blkdev, req, blkvsc_req->group,
1043                           blkvsc_req->group->outstanding);
1044
1045                blkvsc_req->sector_start = start_sector;
1046                sector_div(blkvsc_req->sector_start,
1047                           (blkdev->sector_size >> 9));
1048
1049                blkvsc_req->sector_count = num_sectors /
1050                                           (blkdev->sector_size >> 9);
1051
1052                blkvsc_init_rw(blkvsc_req);
1053        }
1054
1055        list_for_each_entry(blkvsc_req, &group->blkvsc_req_list, req_entry) {
1056                if (pending) {
1057                        DPRINT_DBG(BLKVSC_DRV, "adding blkvsc_req to "
1058                                   "pending_list - blkvsc_req %p start_sect %lu"
1059                                   " sect_count %ld (%lu %ld)\n", blkvsc_req,
1060                                   (unsigned long)blkvsc_req->sector_start,
1061                                   blkvsc_req->sector_count,
1062                                   (unsigned long)start_sector,
1063                                   (unsigned long)num_sectors);
1064
1065                        list_add_tail(&blkvsc_req->pend_entry,
1066                                      &blkdev->pending_list);
1067                } else {
1068                        ret = blkvsc_submit_request(blkvsc_req,
1069                                                    blkvsc_request_completion);
1070                        if (ret == -1) {
1071                                pending = 1;
1072                                list_add_tail(&blkvsc_req->pend_entry,
1073                                              &blkdev->pending_list);
1074                        }
1075
1076                        DPRINT_DBG(BLKVSC_DRV, "submitted blkvsc_req %p "
1077                                   "start_sect %lu sect_count %ld (%lu %ld) "
1078                                   "ret %d\n", blkvsc_req,
1079                                   (unsigned long)blkvsc_req->sector_start,
1080                                   blkvsc_req->sector_count,
1081                                   (unsigned long)start_sector,
1082                                   num_sectors, ret);
1083                }
1084        }
1085
1086        return pending;
1087}
1088
1089static void blkvsc_cmd_completion(struct hv_storvsc_request *request)
1090{
1091        struct blkvsc_request *blkvsc_req =
1092                        (struct blkvsc_request *)request->Context;
1093        struct block_device_context *blkdev =
1094                        (struct block_device_context *)blkvsc_req->dev;
1095        struct scsi_sense_hdr sense_hdr;
1096
1097        DPRINT_DBG(BLKVSC_DRV, "blkvsc_cmd_completion() - req %p\n",
1098                   blkvsc_req);
1099
1100        blkdev->num_outstanding_reqs--;
1101
1102        if (blkvsc_req->request.Status)
1103                if (scsi_normalize_sense(blkvsc_req->sense_buffer,
1104                                         SCSI_SENSE_BUFFERSIZE, &sense_hdr))
1105                        scsi_print_sense_hdr("blkvsc", &sense_hdr);
1106
1107        blkvsc_req->cond = 1;
1108        wake_up_interruptible(&blkvsc_req->wevent);
1109}
1110
1111static void blkvsc_request_completion(struct hv_storvsc_request *request)
1112{
1113        struct blkvsc_request *blkvsc_req =
1114                        (struct blkvsc_request *)request->Context;
1115        struct block_device_context *blkdev =
1116                        (struct block_device_context *)blkvsc_req->dev;
1117        unsigned long flags;
1118        struct blkvsc_request *comp_req, *tmp;
1119
1120        ASSERT(blkvsc_req->group);
1121
1122        DPRINT_DBG(BLKVSC_DRV, "blkdev %p blkvsc_req %p group %p type %s "
1123                   "sect_start %lu sect_count %ld len %d group outstd %d "
1124                   "total outstd %d\n",
1125                   blkdev, blkvsc_req, blkvsc_req->group,
1126                   (blkvsc_req->write) ? "WRITE" : "READ",
1127                   (unsigned long)blkvsc_req->sector_start,
1128                   blkvsc_req->sector_count,
1129                   blkvsc_req->request.DataBuffer.Length,
1130                   blkvsc_req->group->outstanding,
1131                   blkdev->num_outstanding_reqs);
1132
1133        spin_lock_irqsave(&blkdev->lock, flags);
1134
1135        blkdev->num_outstanding_reqs--;
1136        blkvsc_req->group->outstanding--;
1137
1138        /*
1139         * Only start processing when all the blkvsc_reqs are
1140         * completed. This guarantees no out-of-order blkvsc_req
1141         * completion when calling end_that_request_first()
1142         */
1143        if (blkvsc_req->group->outstanding == 0) {
1144                list_for_each_entry_safe(comp_req, tmp,
1145                                         &blkvsc_req->group->blkvsc_req_list,
1146                                         req_entry) {
1147                        DPRINT_DBG(BLKVSC_DRV, "completing blkvsc_req %p "
1148                                   "sect_start %lu sect_count %ld \n",
1149                                   comp_req,
1150                                   (unsigned long)comp_req->sector_start,
1151                                   comp_req->sector_count);
1152
1153                        list_del(&comp_req->req_entry);
1154
1155                        if (!__blk_end_request(comp_req->req,
1156                                (!comp_req->request.Status ? 0 : -EIO),
1157                                comp_req->sector_count * blkdev->sector_size)) {
1158                                /*
1159                                 * All the sectors have been xferred ie the
1160                                 * request is done
1161                                 */
1162                                DPRINT_DBG(BLKVSC_DRV, "req %p COMPLETED\n",
1163                                           comp_req->req);
1164                                kmem_cache_free(blkdev->request_pool,
1165                                                comp_req->group);
1166                        }
1167
1168                        kmem_cache_free(blkdev->request_pool, comp_req);
1169                }
1170
1171                if (!blkdev->shutting_down) {
1172                        blkvsc_do_pending_reqs(blkdev);
1173                        blk_start_queue(blkdev->gd->queue);
1174                        blkvsc_request(blkdev->gd->queue);
1175                }
1176        }
1177
1178        spin_unlock_irqrestore(&blkdev->lock, flags);
1179}
1180
1181static int blkvsc_cancel_pending_reqs(struct block_device_context *blkdev)
1182{
1183        struct blkvsc_request *pend_req, *tmp;
1184        struct blkvsc_request *comp_req, *tmp2;
1185
1186        int ret = 0;
1187
1188        DPRINT_DBG(BLKVSC_DRV, "blkvsc_cancel_pending_reqs()");
1189
1190        /* Flush the pending list first */
1191        list_for_each_entry_safe(pend_req, tmp, &blkdev->pending_list,
1192                                 pend_entry) {
1193                /*
1194                 * The pend_req could be part of a partially completed
1195                 * request. If so, complete those req first until we
1196                 * hit the pend_req
1197                 */
1198                list_for_each_entry_safe(comp_req, tmp2,
1199                                         &pend_req->group->blkvsc_req_list,
1200                                         req_entry) {
1201                        DPRINT_DBG(BLKVSC_DRV, "completing blkvsc_req %p "
1202                                   "sect_start %lu sect_count %ld \n",
1203                                   comp_req,
1204                                   (unsigned long) comp_req->sector_start,
1205                                   comp_req->sector_count);
1206
1207                        if (comp_req == pend_req)
1208                                break;
1209
1210                        list_del(&comp_req->req_entry);
1211
1212                        if (comp_req->req) {
1213                                ret = __blk_end_request(comp_req->req,
1214                                        (!comp_req->request.Status ? 0 : -EIO),
1215                                        comp_req->sector_count *
1216                                        blkdev->sector_size);
1217                                ASSERT(ret != 0);
1218                        }
1219
1220                        kmem_cache_free(blkdev->request_pool, comp_req);
1221                }
1222
1223                DPRINT_DBG(BLKVSC_DRV, "cancelling pending request - %p\n",
1224                           pend_req);
1225
1226                list_del(&pend_req->pend_entry);
1227
1228                list_del(&pend_req->req_entry);
1229
1230                if (comp_req->req) {
1231                        if (!__blk_end_request(pend_req->req, -EIO,
1232                                               pend_req->sector_count *
1233                                               blkdev->sector_size)) {
1234                                /*
1235                                 * All the sectors have been xferred ie the
1236                                 * request is done
1237                                 */
1238                                DPRINT_DBG(BLKVSC_DRV,
1239                                           "blkvsc_cancel_pending_reqs() - "
1240                                           "req %p COMPLETED\n", pend_req->req);
1241                                kmem_cache_free(blkdev->request_pool,
1242                                                pend_req->group);
1243                        }
1244                }
1245
1246                kmem_cache_free(blkdev->request_pool, pend_req);
1247        }
1248
1249        return ret;
1250}
1251
1252static int blkvsc_do_pending_reqs(struct block_device_context *blkdev)
1253{
1254        struct blkvsc_request *pend_req, *tmp;
1255        int ret = 0;
1256
1257        /* Flush the pending list first */
1258        list_for_each_entry_safe(pend_req, tmp, &blkdev->pending_list,
1259                                 pend_entry) {
1260                DPRINT_DBG(BLKVSC_DRV, "working off pending_list - %p\n",
1261                           pend_req);
1262
1263                ret = blkvsc_submit_request(pend_req,
1264                                            blkvsc_request_completion);
1265                if (ret != 0)
1266                        break;
1267                else
1268                        list_del(&pend_req->pend_entry);
1269        }
1270
1271        return ret;
1272}
1273
1274static void blkvsc_request(struct request_queue *queue)
1275{
1276        struct block_device_context *blkdev = NULL;
1277        struct request *req;
1278        int ret = 0;
1279
1280        DPRINT_DBG(BLKVSC_DRV, "- enter \n");
1281        while ((req = blk_peek_request(queue)) != NULL) {
1282                DPRINT_DBG(BLKVSC_DRV, "- req %p\n", req);
1283
1284                blkdev = req->rq_disk->private_data;
1285                if (blkdev->shutting_down || !blk_fs_request(req) ||
1286                    blkdev->media_not_present) {
1287                        __blk_end_request_cur(req, 0);
1288                        continue;
1289                }
1290
1291                ret = blkvsc_do_pending_reqs(blkdev);
1292
1293                if (ret != 0) {
1294                        DPRINT_DBG(BLKVSC_DRV,
1295                                   "- stop queue - pending_list not empty\n");
1296                        blk_stop_queue(queue);
1297                        break;
1298                }
1299
1300                blk_start_request(req);
1301
1302                ret = blkvsc_do_request(blkdev, req);
1303                if (ret > 0) {
1304                        DPRINT_DBG(BLKVSC_DRV, "- stop queue - no room\n");
1305                        blk_stop_queue(queue);
1306                        break;
1307                } else if (ret < 0) {
1308                        DPRINT_DBG(BLKVSC_DRV, "- stop queue - no mem\n");
1309                        blk_requeue_request(queue, req);
1310                        blk_stop_queue(queue);
1311                        break;
1312                }
1313        }
1314}
1315
1316static int blkvsc_open(struct block_device *bdev, fmode_t mode)
1317{
1318        struct block_device_context *blkdev = bdev->bd_disk->private_data;
1319
1320        DPRINT_DBG(BLKVSC_DRV, "- users %d disk %s\n", blkdev->users,
1321                   blkdev->gd->disk_name);
1322
1323        spin_lock(&blkdev->lock);
1324
1325        if (!blkdev->users && blkdev->device_type == DVD_TYPE) {
1326                spin_unlock(&blkdev->lock);
1327                check_disk_change(bdev);
1328                spin_lock(&blkdev->lock);
1329        }
1330
1331        blkdev->users++;
1332
1333        spin_unlock(&blkdev->lock);
1334        return 0;
1335}
1336
1337static int blkvsc_release(struct gendisk *disk, fmode_t mode)
1338{
1339        struct block_device_context *blkdev = disk->private_data;
1340
1341        DPRINT_DBG(BLKVSC_DRV, "- users %d disk %s\n", blkdev->users,
1342                   blkdev->gd->disk_name);
1343
1344        spin_lock(&blkdev->lock);
1345        if (blkdev->users == 1) {
1346                spin_unlock(&blkdev->lock);
1347                blkvsc_do_flush(blkdev);
1348                spin_lock(&blkdev->lock);
1349        }
1350
1351        blkdev->users--;
1352
1353        spin_unlock(&blkdev->lock);
1354        return 0;
1355}
1356
1357static int blkvsc_media_changed(struct gendisk *gd)
1358{
1359        DPRINT_DBG(BLKVSC_DRV, "- enter\n");
1360        return 1;
1361}
1362
1363static int blkvsc_revalidate_disk(struct gendisk *gd)
1364{
1365        struct block_device_context *blkdev = gd->private_data;
1366
1367        DPRINT_DBG(BLKVSC_DRV, "- enter\n");
1368
1369        if (blkdev->device_type == DVD_TYPE) {
1370                blkvsc_do_read_capacity(blkdev);
1371                set_capacity(blkdev->gd, blkdev->capacity *
1372                            (blkdev->sector_size/512));
1373                blk_queue_logical_block_size(gd->queue, blkdev->sector_size);
1374        }
1375        return 0;
1376}
1377
1378static int blkvsc_getgeo(struct block_device *bd, struct hd_geometry *hg)
1379{
1380        sector_t total_sectors = get_capacity(bd->bd_disk);
1381        sector_t cylinder_times_heads = 0;
1382        sector_t temp = 0;
1383
1384        int sectors_per_track = 0;
1385        int heads = 0;
1386        int cylinders = 0;
1387        int rem = 0;
1388
1389        if (total_sectors > (65535 * 16 * 255))
1390                total_sectors = (65535 * 16 * 255);
1391
1392        if (total_sectors >= (65535 * 16 * 63)) {
1393                sectors_per_track = 255;
1394                heads = 16;
1395
1396                cylinder_times_heads = total_sectors;
1397                /* sector_div stores the quotient in cylinder_times_heads */
1398                rem = sector_div(cylinder_times_heads, sectors_per_track);
1399        } else {
1400                sectors_per_track = 17;
1401
1402                cylinder_times_heads = total_sectors;
1403                /* sector_div stores the quotient in cylinder_times_heads */
1404                rem = sector_div(cylinder_times_heads, sectors_per_track);
1405
1406                temp = cylinder_times_heads + 1023;
1407                /* sector_div stores the quotient in temp */
1408                rem = sector_div(temp, 1024);
1409
1410                heads = temp;
1411
1412                if (heads < 4)
1413                        heads = 4;
1414
1415
1416                if (cylinder_times_heads >= (heads * 1024) || (heads > 16)) {
1417                        sectors_per_track = 31;
1418                        heads = 16;
1419
1420                        cylinder_times_heads = total_sectors;
1421                        /*
1422                         * sector_div stores the quotient in
1423                         * cylinder_times_heads
1424                         */
1425                        rem = sector_div(cylinder_times_heads,
1426                                         sectors_per_track);
1427                }
1428
1429                if (cylinder_times_heads >= (heads * 1024)) {
1430                        sectors_per_track = 63;
1431                        heads = 16;
1432
1433                        cylinder_times_heads = total_sectors;
1434                        /*
1435                         * sector_div stores the quotient in
1436                         * cylinder_times_heads
1437                         */
1438                        rem = sector_div(cylinder_times_heads,
1439                                         sectors_per_track);
1440                }
1441        }
1442
1443        temp = cylinder_times_heads;
1444        /* sector_div stores the quotient in temp */
1445        rem = sector_div(temp, heads);
1446        cylinders = temp;
1447
1448        hg->heads = heads;
1449        hg->sectors = sectors_per_track;
1450        hg->cylinders = cylinders;
1451
1452        DPRINT_INFO(BLKVSC_DRV, "CHS (%d, %d, %d)", cylinders, heads,
1453                    sectors_per_track);
1454
1455    return 0;
1456}
1457
1458static int blkvsc_ioctl(struct block_device *bd, fmode_t mode,
1459                        unsigned cmd, unsigned long argument)
1460{
1461/*      struct block_device_context *blkdev = bd->bd_disk->private_data; */
1462        int ret;
1463
1464        switch (cmd) {
1465        /*
1466         * TODO: I think there is certain format for HDIO_GET_IDENTITY rather
1467         * than just a GUID. Commented it out for now.
1468         */
1469#if 0
1470        case HDIO_GET_IDENTITY:
1471                DPRINT_INFO(BLKVSC_DRV, "HDIO_GET_IDENTITY\n");
1472                if (copy_to_user((void __user *)arg, blkdev->device_id,
1473                                 blkdev->device_id_len))
1474                        ret = -EFAULT;
1475                break;
1476#endif
1477        default:
1478                ret = -EINVAL;
1479                break;
1480        }
1481
1482        return ret;
1483}
1484
1485static int __init blkvsc_init(void)
1486{
1487        int ret;
1488
1489        ASSERT(sizeof(sector_t) == 8); /* Make sure CONFIG_LBD is set */
1490
1491        DPRINT_ENTER(BLKVSC_DRV);
1492
1493        DPRINT_INFO(BLKVSC_DRV, "Blkvsc initializing....");
1494
1495        ret = blkvsc_drv_init(BlkVscInitialize);
1496
1497        DPRINT_EXIT(BLKVSC_DRV);
1498
1499        return ret;
1500}
1501
1502static void __exit blkvsc_exit(void)
1503{
1504        DPRINT_ENTER(BLKVSC_DRV);
1505        blkvsc_drv_exit();
1506        DPRINT_ENTER(BLKVSC_DRV);
1507}
1508
1509MODULE_LICENSE("GPL");
1510module_param(blkvsc_ringbuffer_size, int, S_IRUGO);
1511module_init(blkvsc_init);
1512module_exit(blkvsc_exit);
1513