#include <linux/module.h>
#include <linux/device.h>
#include <linux/blkdev.h>
-#include <linux/dmi.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_host.h>
module_param(storvsc_ringbuffer_size, int, S_IRUGO);
MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)");
-static const char *driver_name = "storvsc";
-
-/* {ba6163d9-04a1-4d29-b605-72e2ffb1dc7f} */
-static const struct hv_guid stor_vsci_device_type = {
- .data = {
- 0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d,
- 0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f
- }
-};
-
struct hv_host_device {
struct hv_device *dev;
struct kmem_cache *request_pool;
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)
{
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;
*/
cleanup:
- put_stor_device(device);
return ret;
}
/* 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) {
.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
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));
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;
/* 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,
};
-/*
- * We use a DMI table to determine if we should autoload this driver This is
- * needed by distro tools to determine if the hyperv drivers should be
- * installed and/or configured. We don't do anything else with the table, but
- * it needs to be present.
- */
-
-static const struct dmi_system_id __initconst
-hv_stor_dmi_table[] __maybe_unused = {
- {
- .ident = "Hyper-V",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"),
- DMI_MATCH(DMI_BOARD_NAME, "Virtual Machine"),
- },
- },
- { },
-};
-MODULE_DEVICE_TABLE(dmi, hv_stor_dmi_table);
-
static int __init storvsc_drv_init(void)
{
- int ret;
- struct hv_driver *drv = &storvsc_drv;
u32 max_outstanding_req_per_channel;
/*
* 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)));
-
- memcpy(&drv->dev_type, &stor_vsci_device_type,
- sizeof(struct hv_guid));
+ ((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");