Staging: hv: storvsc: Handle IDE devices using the storvsc driver
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / hv / storvsc_drv.c
index 6f67e9bfebd7224fdd1442fafc28a96440cc945e..9464f99bf7a1ed37b0d48adf33a42b74f0d63e58 100644 (file)
@@ -41,8 +41,6 @@ static int storvsc_ringbuffer_size = STORVSC_RING_BUFFER_SIZE;
 module_param(storvsc_ringbuffer_size, int, S_IRUGO);
 MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)");
 
-static const char *driver_name = "storvsc";
-
 struct hv_host_device {
        struct hv_device *dev;
        struct kmem_cache *request_pool;
@@ -61,6 +59,17 @@ struct storvsc_cmd_request {
        struct hv_storvsc_request request;
 };
 
+static void storvsc_get_ide_info(struct hv_device *dev, int *target, int *path)
+{
+       *target =
+               dev->dev_instance.b[5] << 8 | dev->dev_instance.b[4];
+
+       *path =
+               dev->dev_instance.b[3] << 24 |
+               dev->dev_instance.b[2] << 16 |
+               dev->dev_instance.b[1] << 8  | dev->dev_instance.b[0];
+}
+
 
 static int storvsc_device_alloc(struct scsi_device *sdevice)
 {
@@ -346,9 +355,9 @@ static int storvsc_host_reset(struct hv_device *device)
        int ret, t;
 
 
-       stor_device = get_stor_device(device);
+       stor_device = get_out_stor_device(device);
        if (!stor_device)
-               return -1;
+               return -ENODEV;
 
        request = &stor_device->reset_request;
        vstor_packet = &request->vstor_packet;
@@ -380,7 +389,6 @@ static int storvsc_host_reset(struct hv_device *device)
         */
 
 cleanup:
-       put_stor_device(device);
        return ret;
 }
 
@@ -580,7 +588,7 @@ retry_request:
        /* Invokes the vsc to start an IO */
        ret = storvsc_do_io(dev, &cmd_request->request);
 
-       if (ret == -1) {
+       if (ret == -EAGAIN) {
                /* no more space */
 
                if (cmd_request->bounce_sgl_count) {
@@ -637,14 +645,23 @@ static struct scsi_host_template scsi_driver = {
        .dma_boundary =         PAGE_SIZE-1,
 };
 
+/*
+ * The storvsc_probe function assumes that the IDE guid
+ * is the second entry.
+ */
 static const struct hv_vmbus_device_id id_table[] = {
        /* SCSI guid */
        { VMBUS_DEVICE(0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d,
                       0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f) },
+       /* IDE guid */
+       { VMBUS_DEVICE(0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44,
+                      0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5) },
        { },
 };
 
 MODULE_DEVICE_TABLE(vmbus, id_table);
+
+
 /*
  * storvsc_probe - Add a new device for this driver
  */
@@ -655,6 +672,14 @@ static int storvsc_probe(struct hv_device *device)
        struct Scsi_Host *host;
        struct hv_host_device *host_dev;
        struct storvsc_device_info device_info;
+       bool dev_is_ide;
+       int path = 0;
+       int target = 0;
+
+       if (!memcmp(&device->dev_type.b, id_table[1].guid, sizeof(uuid_le)))
+               dev_is_ide = true;
+       else
+               dev_is_ide = false;
 
        host = scsi_host_alloc(&scsi_driver,
                               sizeof(struct hv_host_device));
@@ -687,9 +712,12 @@ static int storvsc_probe(struct hv_device *device)
        if (ret != 0) {
                kmem_cache_destroy(host_dev->request_pool);
                scsi_host_put(host);
-               return -1;
+               return -ENODEV;
        }
 
+       if (dev_is_ide)
+               storvsc_get_ide_info(device, &target, &path);
+
        host_dev->path = device_info.path_id;
        host_dev->target = device_info.target_id;
 
@@ -702,22 +730,31 @@ static int storvsc_probe(struct hv_device *device)
 
        /* Register the HBA and start the scsi bus scan */
        ret = scsi_add_host(host, &device->device);
-       if (ret != 0) {
-
-               storvsc_dev_remove(device);
+       if (ret != 0)
+               goto err_out;
 
-               kmem_cache_destroy(host_dev->request_pool);
-               scsi_host_put(host);
-               return -1;
+       if (!dev_is_ide) {
+               scsi_scan_host(host);
+               return 0;
        }
+       ret = scsi_add_device(host, 0, target, 0);
+       if (ret) {
+               scsi_remove_host(host);
+               goto err_out;
+       }
+       return 0;
 
-       scsi_scan_host(host);
-       return ret;
+err_out:
+       storvsc_dev_remove(device);
+       kmem_cache_destroy(host_dev->request_pool);
+       scsi_host_put(host);
+       return -ENODEV;
 }
 
 /* The one and only one */
 
 static struct hv_driver storvsc_drv = {
+       .name = "storvsc",
        .id_table = id_table,
        .probe = storvsc_probe,
        .remove = storvsc_remove,
@@ -725,8 +762,6 @@ static struct hv_driver storvsc_drv = {
 
 static int __init storvsc_drv_init(void)
 {
-       int ret;
-       struct hv_driver *drv = &storvsc_drv;
        u32 max_outstanding_req_per_channel;
 
        /*
@@ -735,29 +770,22 @@ static int __init storvsc_drv_init(void)
         * the ring buffer indices) by the max request size (which is
         * vmbus_channel_packet_multipage_buffer + struct vstor_packet + u64)
         */
-
        max_outstanding_req_per_channel =
-       ((storvsc_ringbuffer_size - PAGE_SIZE) /
-       ALIGN(MAX_MULTIPAGE_BUFFER_PACKET +
-       sizeof(struct vstor_packet) + sizeof(u64),
-       sizeof(u64)));
+               ((storvsc_ringbuffer_size - PAGE_SIZE) /
+               ALIGN(MAX_MULTIPAGE_BUFFER_PACKET +
+               sizeof(struct vstor_packet) + sizeof(u64),
+               sizeof(u64)));
 
        if (max_outstanding_req_per_channel <
            STORVSC_MAX_IO_REQUESTS)
-               return -1;
-
-       drv->driver.name = driver_name;
+               return -EINVAL;
 
-
-       /* The driver belongs to vmbus */
-       ret = vmbus_child_driver_register(&drv->driver);
-
-       return ret;
+       return vmbus_driver_register(&storvsc_drv);
 }
 
 static void __exit storvsc_drv_exit(void)
 {
-       vmbus_child_driver_unregister(&storvsc_drv.driver);
+       vmbus_driver_unregister(&storvsc_drv);
 }
 
 MODULE_LICENSE("GPL");