Staging: hv: Move the definition of the function stor_vsc_on_host_reset()
[deliverable/linux.git] / drivers / staging / hv / storvsc_drv.c
index e6462a2fe9abfdb9082a2ab2e2464d85cecd7557..e0a11958141cfa79426120b9c1d8a56020752651 100644 (file)
 #include "version_info.h"
 #include "vmbus.h"
 #include "storvsc_api.h"
+#include "vstorage.h"
+#include "channel.h"
 
 
+static const char *g_driver_name = "storvsc";
+
+/* {ba6163d9-04a1-4d29-b605-72e2ffb1dc7f} */
+static const struct hv_guid gStorVscDeviceType = {
+       .data = {
+               0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d,
+               0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f
+       }
+};
+
 struct host_device_context {
        /* must be 1st field
         * FIXME this is a bug */
@@ -64,6 +76,59 @@ struct storvsc_cmd_request {
 };
 
 
+/*
+ * stor_vsc_initialize - Main entry point
+ */
+static int stor_vsc_initialize(struct hv_driver *driver)
+{
+       struct storvsc_driver_object *stor_driver;
+
+       stor_driver = (struct storvsc_driver_object *)driver;
+
+       DPRINT_DBG(STORVSC, "sizeof(STORVSC_REQUEST)=%zd "
+                  "sizeof(struct storvsc_request_extension)=%zd "
+                  "sizeof(struct vstor_packet)=%zd, "
+                  "sizeof(struct vmscsi_request)=%zd",
+                  sizeof(struct hv_storvsc_request),
+                  sizeof(struct storvsc_request_extension),
+                  sizeof(struct vstor_packet),
+                  sizeof(struct vmscsi_request));
+
+       /* Make sure we are at least 2 pages since 1 page is used for control */
+
+       driver->name = g_driver_name;
+       memcpy(&driver->dev_type, &gStorVscDeviceType,
+              sizeof(struct hv_guid));
+
+       stor_driver->request_ext_size =
+                       sizeof(struct storvsc_request_extension);
+
+       /*
+        * Divide the ring buffer data size (which is 1 page less
+        * than the ring buffer size since that page is reserved for
+        * the ring buffer indices) by the max request size (which is
+        * vmbus_channel_packet_multipage_buffer + struct vstor_packet + u64)
+        */
+       stor_driver->max_outstanding_req_per_channel =
+               ((stor_driver->ring_buffer_size - PAGE_SIZE) /
+                 ALIGN(MAX_MULTIPAGE_BUFFER_PACKET +
+                          sizeof(struct vstor_packet) + sizeof(u64),
+                          sizeof(u64)));
+
+       DPRINT_INFO(STORVSC, "max io %u, currently %u\n",
+                   stor_driver->max_outstanding_req_per_channel,
+                   STORVSC_MAX_IO_REQUESTS);
+
+       /* Setup the dispatch table */
+       stor_driver->base.dev_add       = stor_vsc_on_device_add;
+       stor_driver->base.dev_rm        = stor_vsc_on_device_remove;
+       stor_driver->base.cleanup       = stor_vsc_on_cleanup;
+
+       stor_driver->on_io_request      = stor_vsc_on_io_request;
+
+       return 0;
+}
+
 /* Static decl */
 static int storvsc_probe(struct device *dev);
 static int storvsc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd);
@@ -128,7 +193,7 @@ static struct scsi_host_template scsi_driver = {
 /*
  * storvsc_drv_init - StorVsc driver initialization.
  */
-static int storvsc_drv_init(int (*drv_init)(struct hv_driver *drv))
+static int storvsc_drv_init(void)
 {
        int ret;
        struct storvsc_driver_object *storvsc_drv_obj = &g_storvsc_drv;
@@ -137,7 +202,7 @@ static int storvsc_drv_init(int (*drv_init)(struct hv_driver *drv))
        storvsc_drv_obj->ring_buffer_size = storvsc_ringbuffer_size;
 
        /* Callback to client driver to complete the initialization */
-       drv_init(&storvsc_drv_obj->base);
+       stor_vsc_initialize(&storvsc_drv_obj->base);
 
        drv->priv = storvsc_drv_obj;
 
@@ -167,6 +232,63 @@ static int storvsc_drv_init(int (*drv_init)(struct hv_driver *drv))
        return ret;
 }
 
+
+int stor_vsc_on_host_reset(struct hv_device *device)
+{
+       struct storvsc_device *stor_device;
+       struct storvsc_request_extension *request;
+       struct vstor_packet *vstor_packet;
+       int ret;
+
+       DPRINT_INFO(STORVSC, "resetting host adapter...");
+
+       stor_device = get_stor_device(device);
+       if (!stor_device) {
+               DPRINT_ERR(STORVSC, "unable to get stor device..."
+                          "device being destroyed?");
+               return -1;
+       }
+
+       request = &stor_device->reset_request;
+       vstor_packet = &request->vstor_packet;
+
+       init_waitqueue_head(&request->wait_event);
+
+       vstor_packet->operation = VSTOR_OPERATION_RESET_BUS;
+       vstor_packet->flags = REQUEST_COMPLETION_FLAG;
+       vstor_packet->vm_srb.path_id = stor_device->path_id;
+
+       request->wait_condition = 0;
+       ret = vmbus_sendpacket(device->channel, vstor_packet,
+                              sizeof(struct vstor_packet),
+                              (unsigned long)&stor_device->reset_request,
+                              VM_PKT_DATA_INBAND,
+                              VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+       if (ret != 0) {
+               DPRINT_ERR(STORVSC, "Unable to send reset packet %p ret %d",
+                          vstor_packet, ret);
+               goto cleanup;
+       }
+
+       wait_event_timeout(request->wait_event, request->wait_condition,
+                       msecs_to_jiffies(1000));
+       if (request->wait_condition == 0) {
+               ret = -ETIMEDOUT;
+               goto cleanup;
+       }
+
+       DPRINT_INFO(STORVSC, "host adapter reset completed");
+
+       /*
+        * At this point, all outstanding requests in the adapter
+        * should have been flushed out and return to us
+        */
+
+cleanup:
+       put_stor_device(device);
+       return ret;
+}
+
 static int storvsc_drv_exit_cb(struct device *dev, void *data)
 {
        struct device **curr = (struct device **)data;
@@ -923,7 +1045,7 @@ static int __init storvsc_init(void)
        int ret;
 
        DPRINT_INFO(STORVSC_DRV, "Storvsc initializing....");
-       ret = storvsc_drv_init(stor_vsc_initialize);
+       ret = storvsc_drv_init();
        return ret;
 }
 
This page took 0.026431 seconds and 5 git commands to generate.