From 358d2ee2e8f5c25f1661e94c206102c88fdee370 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:48:28 -0700 Subject: Staging: hv: Replace struct hv_guid with the uuid type already defined in Linux Replace struct hv_guid with the uuid type already defined in Linux. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/blkvsc_drv.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/staging/hv/blkvsc_drv.c') diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c index d286b2223181..018b29394b00 100644 --- a/drivers/staging/hv/blkvsc_drv.c +++ b/drivers/staging/hv/blkvsc_drv.c @@ -112,8 +112,8 @@ struct block_device_context { static const char *drv_name = "blkvsc"; /* {32412632-86cb-44a2-9b5c-50d1417354f5} */ -static const struct hv_guid dev_type = { - .data = { +static const uuid_le dev_type = { + .b = { 0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44, 0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5 } @@ -155,13 +155,13 @@ static int blkvsc_device_add(struct hv_device *device, * id. For IDE devices, the device instance id is formatted as * * - - 8899 - 000000000000. */ - device_info->path_id = device->dev_instance.data[3] << 24 | - device->dev_instance.data[2] << 16 | - device->dev_instance.data[1] << 8 | - device->dev_instance.data[0]; + device_info->path_id = device->dev_instance.b[3] << 24 | + device->dev_instance.b[2] << 16 | + device->dev_instance.b[1] << 8 | + device->dev_instance.b[0]; - device_info->target_id = device->dev_instance.data[5] << 8 | - device->dev_instance.data[4]; + device_info->target_id = device->dev_instance.b[5] << 8 | + device->dev_instance.b[4]; return ret; } @@ -829,7 +829,7 @@ static int blkvsc_drv_init(void) BUILD_BUG_ON(sizeof(sector_t) != 8); - memcpy(&drv->dev_type, &dev_type, sizeof(struct hv_guid)); + memcpy(&drv->dev_type, &dev_type, sizeof(uuid_le)); drv->driver.name = drv_name; /* The driver belongs to vmbus */ -- cgit v1.2.3 From eefd7f4555163da346781a2216264ba871aed76b Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:48:32 -0700 Subject: Staging: hv: blkvsc: Use the newly introduced vmbus ID in the blockvsc driver Use the newly introduced vmbus ID in the blockvsc driver. Also, do the associated cleanup. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/blkvsc_drv.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'drivers/staging/hv/blkvsc_drv.c') diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c index 018b29394b00..9b99387d98cc 100644 --- a/drivers/staging/hv/blkvsc_drv.c +++ b/drivers/staging/hv/blkvsc_drv.c @@ -111,14 +111,6 @@ struct block_device_context { static const char *drv_name = "blkvsc"; -/* {32412632-86cb-44a2-9b5c-50d1417354f5} */ -static const uuid_le dev_type = { - .b = { - 0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44, - 0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5 - } -}; - /* * There is a circular dependency involving blkvsc_request_completion() * and blkvsc_do_request(). @@ -802,10 +794,24 @@ static void blkvsc_request(struct request_queue *queue) } } +static const struct hv_vmbus_device_id id_table[] = { + { + /* IDE guid */ + .guid = { + 0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44, + 0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5 + } + }, + { + .guid = { } + }, +}; +MODULE_DEVICE_TABLE(vmbus, id_table); /* The one and only one */ static struct hv_driver blkvsc_drv = { + .id_table = id_table, .probe = blkvsc_probe, .remove = blkvsc_remove, .shutdown = blkvsc_shutdown, @@ -829,7 +835,6 @@ static int blkvsc_drv_init(void) BUILD_BUG_ON(sizeof(sector_t) != 8); - memcpy(&drv->dev_type, &dev_type, sizeof(uuid_le)); drv->driver.name = drv_name; /* The driver belongs to vmbus */ -- cgit v1.2.3 From c45cf2d4976e2fcde68d88898a37af70f2caaf5d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 25 Aug 2011 11:41:33 -0700 Subject: Staging: hv: create VMBUS_DEVICE macro and use it. This is to be used to be able to write hv_vmbus_device_id tables easier. This patch also converts all hv drivers to use the macro, saving some lines of code and making things easier to read overall. Cc: K. Y. Srinivasan Cc: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/blkvsc_drv.c | 14 ++++--------- drivers/staging/hv/hv_mouse.c | 14 ++++--------- drivers/staging/hv/hv_util.c | 44 ++++++++++++---------------------------- drivers/staging/hv/hyperv.h | 11 ++++++++++ drivers/staging/hv/netvsc_drv.c | 14 ++++--------- drivers/staging/hv/storvsc_drv.c | 14 ++++--------- 6 files changed, 40 insertions(+), 71 deletions(-) (limited to 'drivers/staging/hv/blkvsc_drv.c') diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c index 9b99387d98cc..d170f24a07fe 100644 --- a/drivers/staging/hv/blkvsc_drv.c +++ b/drivers/staging/hv/blkvsc_drv.c @@ -795,16 +795,10 @@ static void blkvsc_request(struct request_queue *queue) } static const struct hv_vmbus_device_id id_table[] = { - { - /* IDE guid */ - .guid = { - 0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44, - 0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5 - } - }, - { - .guid = { } - }, + /* 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); diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index dd8a1143b35b..ebd17150d6c3 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -909,16 +909,10 @@ static void reportdesc_callback(struct hv_device *dev, void *packet, u32 len) } static const struct hv_vmbus_device_id id_table[] = { - { - /* Mouse guid */ - .guid = { - 0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c, - 0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A - } - }, - { - .guid = { } - }, + /* Mouse guid */ + { VMBUS_DEVICE(0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c, + 0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A) }, + { }, }; /* diff --git a/drivers/staging/hv/hv_util.c b/drivers/staging/hv/hv_util.c index a620f4d810c9..5bd6f00b8242 100644 --- a/drivers/staging/hv/hv_util.c +++ b/drivers/staging/hv/hv_util.c @@ -227,37 +227,19 @@ static int util_remove(struct hv_device *dev) } static const struct hv_vmbus_device_id id_table[] = { - { - /* Shutdown guid */ - .guid = { - 0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49, - 0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB - } - }, - { - /* Time synch guid */ - .guid = { - 0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49, - 0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf - } - }, - { - /* Heartbeat guid */ - .guid = { - 0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e, - 0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d - } - }, - { - /* KVP guid */ - .guid = { - 0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d, - 0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3, 0xe6 - } - }, - { - .guid = { } - }, + /* Shutdown guid */ + { VMBUS_DEVICE(0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49, + 0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB) }, + /* Time synch guid */ + { VMBUS_DEVICE(0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49, + 0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf) }, + /* Heartbeat guid */ + { VMBUS_DEVICE(0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e, + 0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d) }, + /* KVP guid */ + { VMBUS_DEVICE(0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d, + 0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3, 0xe6) }, + { }, }; MODULE_DEVICE_TABLE(vmbus, id_table); diff --git a/drivers/staging/hv/hyperv.h b/drivers/staging/hv/hyperv.h index b8199f4b4aed..d96de668eb13 100644 --- a/drivers/staging/hv/hyperv.h +++ b/drivers/staging/hv/hyperv.h @@ -848,6 +848,17 @@ static inline struct hv_driver *drv_to_hv_drv(struct device_driver *d) int vmbus_child_driver_register(struct device_driver *drv); void vmbus_child_driver_unregister(struct device_driver *drv); +/** + * VMBUS_DEVICE - macro used to describe a specific hyperv vmbus device + * + * This macro is used to create a struct hv_vmbus_device_id that matches a + * specific device. + */ +#define VMBUS_DEVICE(g0, g1, g2, g3, g4, g5, g6, g7, \ + g8, g9, ga, gb, gc, gd, ge, gf) \ + .guid = { g0, g1, g2, g3, g4, g5, g6, g7, \ + g8, g9, ga, gb, gc, gd, ge, gf }, + /* * Common header for Hyper-V ICs */ diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c index 2e25c957cfd0..c3b7de147004 100644 --- a/drivers/staging/hv/netvsc_drv.c +++ b/drivers/staging/hv/netvsc_drv.c @@ -414,16 +414,10 @@ static int netvsc_remove(struct hv_device *dev) } static const struct hv_vmbus_device_id id_table[] = { - { - /* Network guid */ - .guid = { - 0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46, - 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E - } - }, - { - .guid = { } - }, + /* Network guid */ + { VMBUS_DEVICE(0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46, + 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E) }, + { }, }; MODULE_DEVICE_TABLE(vmbus, id_table); diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index ed2140c01543..f85f2ea23743 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -639,16 +639,10 @@ static struct scsi_host_template scsi_driver = { }; static const struct hv_vmbus_device_id id_table[] = { - { - /* SCSI guid */ - .guid = { - 0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d, - 0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f - } - }, - { - .guid = { } - }, + /* SCSI guid */ + { VMBUS_DEVICE(0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d, + 0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f) }, + { }, }; MODULE_DEVICE_TABLE(vmbus, id_table); -- cgit v1.2.3 From 768fa21919b7f30b77f0b3ba94939f5556d111d5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 25 Aug 2011 15:07:32 -0700 Subject: Staging: hv: fix up driver registering mess Individual drivers should never be touching the 'struct device' field, so if that is a requirement to pass to the vmbus core, you know something is wrong. This patch fixes that all up, and resolves the problem where the module reference counting was not happening properly for the individual drivers as well. Overall, it reduces the lines of code the individual drivers have to have, which tells you that this is the correct thing to do. Also, somehow the _GPL marking for the functions got removed on an older patch. As the name of the function was changing, properly change the _GPL marking as well at the same time. Cc: K. Y. Srinivasan Cc: Haiyang Zhang Cc: Hank Janssen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/blkvsc_drv.c | 17 +++------------- drivers/staging/hv/hv_mouse.c | 21 +++----------------- drivers/staging/hv/hv_util.c | 9 +++------ drivers/staging/hv/hyperv.h | 8 ++++++-- drivers/staging/hv/hyperv_net.h | 1 - drivers/staging/hv/netvsc.c | 14 ------------- drivers/staging/hv/netvsc_drv.c | 19 +++--------------- drivers/staging/hv/storvsc_drv.c | 24 +++++++--------------- drivers/staging/hv/vmbus_drv.c | 43 ++++++++++++++++++++-------------------- 9 files changed, 46 insertions(+), 110 deletions(-) (limited to 'drivers/staging/hv/blkvsc_drv.c') diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c index d170f24a07fe..07dc9ed6ec55 100644 --- a/drivers/staging/hv/blkvsc_drv.c +++ b/drivers/staging/hv/blkvsc_drv.c @@ -109,7 +109,6 @@ struct block_device_context { int users; }; -static const char *drv_name = "blkvsc"; /* * There is a circular dependency involving blkvsc_request_completion() @@ -805,6 +804,7 @@ MODULE_DEVICE_TABLE(vmbus, id_table); /* The one and only one */ static struct hv_driver blkvsc_drv = { + .name = "blkvsc", .id_table = id_table, .probe = blkvsc_probe, .remove = blkvsc_remove, @@ -824,24 +824,13 @@ static const struct block_device_operations block_ops = { */ static int blkvsc_drv_init(void) { - struct hv_driver *drv = &blkvsc_drv; - int ret; - BUILD_BUG_ON(sizeof(sector_t) != 8); - - drv->driver.name = drv_name; - - /* The driver belongs to vmbus */ - ret = vmbus_child_driver_register(&drv->driver); - - return ret; + return vmbus_driver_register(&blkvsc_drv); } - static void blkvsc_drv_exit(void) { - - vmbus_child_driver_unregister(&blkvsc_drv.driver); + vmbus_driver_unregister(&blkvsc_drv); } /* diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c index ebd17150d6c3..572717317e71 100644 --- a/drivers/staging/hv/hv_mouse.c +++ b/drivers/staging/hv/hv_mouse.c @@ -176,8 +176,6 @@ struct mousevsc_dev { }; -static const char *driver_name = "mousevsc"; - static void deviceinfo_callback(struct hv_device *dev, struct hv_input_dev_info *info); static void inputreport_callback(struct hv_device *dev, void *packet, u32 len); static void reportdesc_callback(struct hv_device *dev, void *packet, u32 len); @@ -921,33 +919,20 @@ static const struct hv_vmbus_device_id id_table[] = { /* MODULE_DEVICE_TABLE(vmbus, id_table); */ static struct hv_driver mousevsc_drv = { + .name = "mousevsc", .id_table = id_table, .probe = mousevsc_probe, .remove = mousevsc_remove, }; -static void mousevsc_drv_exit(void) -{ - vmbus_child_driver_unregister(&mousevsc_drv.driver); -} - static int __init mousevsc_init(void) { - struct hv_driver *drv = &mousevsc_drv; - - DPRINT_INFO(INPUTVSC_DRV, "Hyper-V Mouse driver initializing."); - - drv->driver.name = driver_name; - - /* The driver belongs to vmbus */ - vmbus_child_driver_register(&drv->driver); - - return 0; + return vmbus_driver_register(&mousevsc_drv); } static void __exit mousevsc_exit(void) { - mousevsc_drv_exit(); + vmbus_driver_unregister(&mousevsc_drv); } /* diff --git a/drivers/staging/hv/hv_util.c b/drivers/staging/hv/hv_util.c index b0d89deec765..f2f456f5e444 100644 --- a/drivers/staging/hv/hv_util.c +++ b/drivers/staging/hv/hv_util.c @@ -34,8 +34,6 @@ static u8 *shut_txf_buf; static u8 *time_txf_buf; static u8 *hbeat_txf_buf; -static const char *driver_name = "hv_util"; - static void shutdown_onchannelcallback(void *context) { struct vmbus_channel *channel = context; @@ -244,6 +242,7 @@ MODULE_DEVICE_TABLE(vmbus, id_table); /* The one and only one */ static struct hv_driver util_drv = { + .name = "hv_util", .id_table = id_table, .probe = util_probe, .remove = util_remove, @@ -277,9 +276,7 @@ static int __init init_hyperv_utils(void) hv_cb_utils[HV_KVP_MSG].callback = &hv_kvp_onchannelcallback; - util_drv.driver.name = driver_name; - - return vmbus_child_driver_register(&util_drv.driver); + return vmbus_driver_register(&util_drv); } static void exit_hyperv_utils(void) @@ -311,7 +308,7 @@ static void exit_hyperv_utils(void) kfree(shut_txf_buf); kfree(time_txf_buf); kfree(hbeat_txf_buf); - vmbus_child_driver_unregister(&util_drv.driver); + vmbus_driver_unregister(&util_drv); } module_init(init_hyperv_utils); diff --git a/drivers/staging/hv/hyperv.h b/drivers/staging/hv/hyperv.h index d96de668eb13..c24981198b1b 100644 --- a/drivers/staging/hv/hyperv.h +++ b/drivers/staging/hv/hyperv.h @@ -845,8 +845,12 @@ static inline struct hv_driver *drv_to_hv_drv(struct device_driver *d) /* Vmbus interface */ -int vmbus_child_driver_register(struct device_driver *drv); -void vmbus_child_driver_unregister(struct device_driver *drv); +#define vmbus_driver_register(driver) \ + __vmbus_driver_register(driver, THIS_MODULE, KBUILD_MODNAME) +int __must_check __vmbus_driver_register(struct hv_driver *hv_driver, + struct module *owner, + const char *mod_name); +void vmbus_driver_unregister(struct hv_driver *hv_driver); /** * VMBUS_DEVICE - macro used to describe a specific hyperv vmbus device diff --git a/drivers/staging/hv/hyperv_net.h b/drivers/staging/hv/hyperv_net.h index 27f987b48dfe..5782fea9a17a 100644 --- a/drivers/staging/hv/hyperv_net.h +++ b/drivers/staging/hv/hyperv_net.h @@ -96,7 +96,6 @@ void netvsc_linkstatus_callback(struct hv_device *device_obj, unsigned int status); int netvsc_recv_callback(struct hv_device *device_obj, struct hv_netvsc_packet *packet); -int netvsc_initialize(struct hv_driver *drv); int rndis_filter_open(struct hv_device *dev); int rndis_filter_close(struct hv_device *dev); int rndis_filter_device_add(struct hv_device *dev, diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c index 6f4541bcef89..cb02eed741f7 100644 --- a/drivers/staging/hv/netvsc.c +++ b/drivers/staging/hv/netvsc.c @@ -32,9 +32,6 @@ #include "hyperv_net.h" -/* Globals */ -static const char *driver_name = "netvsc"; - static struct netvsc_device *alloc_net_device(struct hv_device *device) { struct netvsc_device *net_device; @@ -992,14 +989,3 @@ cleanup: return ret; } - -/* - * netvsc_initialize - Main entry point - */ -int netvsc_initialize(struct hv_driver *drv) -{ - - drv->name = driver_name; - - return 0; -} diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c index 2d2955c1925f..ad1ef038ff7f 100644 --- a/drivers/staging/hv/netvsc_drv.c +++ b/drivers/staging/hv/netvsc_drv.c @@ -422,6 +422,7 @@ MODULE_DEVICE_TABLE(vmbus, id_table); /* The one and only one */ static struct hv_driver netvsc_drv = { + .name = "netvsc", .id_table = id_table, .probe = netvsc_probe, .remove = netvsc_remove, @@ -429,26 +430,12 @@ static struct hv_driver netvsc_drv = { static void __exit netvsc_drv_exit(void) { - vmbus_child_driver_unregister(&netvsc_drv.driver); + vmbus_driver_unregister(&netvsc_drv); } - static int __init netvsc_drv_init(void) { - struct hv_driver *drv = &netvsc_drv; - int ret; - - pr_info("initializing...."); - - /* Callback to client driver to complete the initialization */ - netvsc_initialize(drv); - - drv->driver.name = drv->name; - - /* The driver belongs to vmbus */ - ret = vmbus_child_driver_register(&drv->driver); - - return ret; + return vmbus_driver_register(&netvsc_drv); } MODULE_LICENSE("GPL"); diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 6f67e9bfebd7..0297418e8a6e 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -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; @@ -718,6 +716,7 @@ static int storvsc_probe(struct hv_device *device) /* 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 +724,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 +732,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; - - - /* 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"); diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c index 0114b04d2243..26f49010e1ff 100644 --- a/drivers/staging/hv/vmbus_drv.c +++ b/drivers/staging/hv/vmbus_drv.c @@ -552,51 +552,50 @@ static int vmbus_bus_init(int irq) } /** - * vmbus_child_driver_register() - Register a vmbus's child driver - * @drv: Pointer to driver structure you want to register - * + * __vmbus_child_driver_register - Register a vmbus's driver + * @drv: Pointer to driver structure you want to register + * @owner: owner module of the drv + * @mod_name: module name string * * Registers the given driver with Linux through the 'driver_register()' call - * And sets up the hyper-v vmbus handling for this driver. + * and sets up the hyper-v vmbus handling for this driver. * It will return the state of the 'driver_register()' call. * - * Mainly used by Hyper-V drivers. */ -int vmbus_child_driver_register(struct device_driver *drv) +int __vmbus_driver_register(struct hv_driver *hv_driver, struct module *owner, const char *mod_name) { int ret; - pr_info("child driver registering - name %s\n", drv->name); + pr_info("registering driver %s\n", hv_driver->name); - /* The child driver on this vmbus */ - drv->bus = &hv_bus; + hv_driver->driver.name = hv_driver->name; + hv_driver->driver.owner = owner; + hv_driver->driver.mod_name = mod_name; + hv_driver->driver.bus = &hv_bus; - ret = driver_register(drv); + ret = driver_register(&hv_driver->driver); vmbus_request_offers(); return ret; } -EXPORT_SYMBOL(vmbus_child_driver_register); +EXPORT_SYMBOL_GPL(__vmbus_driver_register); /** - * vmbus_child_driver_unregister() - Unregister a vmbus's child driver - * @drv: Pointer to driver structure you want to un-register - * - * - * Un-register the given driver with Linux through the 'driver_unregister()' - * call. And ungegisters the driver from the Hyper-V vmbus handler. + * vmbus_driver_unregister() - Unregister a vmbus's driver + * @drv: Pointer to driver structure you want to un-register * - * Mainly used by Hyper-V drivers. + * Un-register the given driver that was previous registered with a call to + * vmbus_driver_register() */ -void vmbus_child_driver_unregister(struct device_driver *drv) +void vmbus_driver_unregister(struct hv_driver *hv_driver) { - pr_info("child driver unregistering - name %s\n", drv->name); + pr_info("unregistering driver %s\n", hv_driver->name); - driver_unregister(drv); + driver_unregister(&hv_driver->driver); } -EXPORT_SYMBOL(vmbus_child_driver_unregister); +EXPORT_SYMBOL_GPL(vmbus_driver_unregister); /* * vmbus_child_device_create - Creates and registers a new child device -- cgit v1.2.3 From d2598f017f02bbc3623503c6e08f22f7ea473cdd Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 25 Aug 2011 09:48:58 -0700 Subject: Staging: hv: vmbus: Cleanup error values in ringbuffer.c Use standard Linux errno values in ringbuffer.c and do the associated cleanup in the clients. Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/blkvsc_drv.c | 2 +- drivers/staging/hv/netvsc.c | 2 +- drivers/staging/hv/ring_buffer.c | 6 +++--- drivers/staging/hv/storvsc_drv.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/staging/hv/blkvsc_drv.c') diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c index 07dc9ed6ec55..2b41eb677b2f 100644 --- a/drivers/staging/hv/blkvsc_drv.c +++ b/drivers/staging/hv/blkvsc_drv.c @@ -725,7 +725,7 @@ static int blkvsc_do_request(struct block_device_context *blkdev, } else { ret = blkvsc_submit_request(blkvsc_req, blkvsc_request_completion); - if (ret == -1) { + if (ret == -EAGAIN) { pending = 1; list_add_tail(&blkvsc_req->pend_entry, &blkdev->pending_list); diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c index cb02eed741f7..d547ff676a0b 100644 --- a/drivers/staging/hv/netvsc.c +++ b/drivers/staging/hv/netvsc.c @@ -565,7 +565,7 @@ retry_send_cmplt: if (ret == 0) { /* success */ /* no-op */ - } else if (ret == -1) { + } else if (ret == -EAGAIN) { /* no more room...wait a bit and attempt to retry 3 times */ retries++; dev_err(&device->device, "unable to send receive completion pkt" diff --git a/drivers/staging/hv/ring_buffer.c b/drivers/staging/hv/ring_buffer.c index 42f76728429a..9212699a6632 100644 --- a/drivers/staging/hv/ring_buffer.c +++ b/drivers/staging/hv/ring_buffer.c @@ -390,7 +390,7 @@ int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info, /* is empty since the read index == write index */ if (bytes_avail_towrite <= totalbytes_towrite) { spin_unlock_irqrestore(&outring_info->ring_lock, flags); - return -1; + return -EAGAIN; } /* Write to the ring buffer */ @@ -450,7 +450,7 @@ int hv_ringbuffer_peek(struct hv_ring_buffer_info *Inring_info, spin_unlock_irqrestore(&Inring_info->ring_lock, flags); - return -1; + return -EAGAIN; } /* Convert to byte offset */ @@ -496,7 +496,7 @@ int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info, void *buffer, if (bytes_avail_toread < buflen) { spin_unlock_irqrestore(&inring_info->ring_lock, flags); - return -1; + return -EAGAIN; } next_read_location = diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 0297418e8a6e..29ac64406880 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -578,7 +578,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) { -- cgit v1.2.3 From b38cc43432d7b7b0a4dc0a13d261a85944fc7c65 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Sat, 27 Aug 2011 11:31:19 -0700 Subject: Staging: hv: blkvsc: Get rid of blkvsc_drv.c as this code is not used Now that blkvsc driver is no longer needed, remove blkvsc_drv.c Signed-off-by: K. Y. Srinivasan Signed-off-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/blkvsc_drv.c | 1014 --------------------------------------- 1 file changed, 1014 deletions(-) delete mode 100644 drivers/staging/hv/blkvsc_drv.c (limited to 'drivers/staging/hv/blkvsc_drv.c') diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c deleted file mode 100644 index 2b41eb677b2f..000000000000 --- a/drivers/staging/hv/blkvsc_drv.c +++ /dev/null @@ -1,1014 +0,0 @@ -/* - * Copyright (c) 2009, Microsoft Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple - * Place - Suite 330, Boston, MA 02111-1307 USA. - * - * Authors: - * Haiyang Zhang - * Hank Janssen - * K. Y. Srinivasan - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "hyperv.h" -#include "hyperv_storage.h" - - -#define BLKVSC_MINORS 64 - -enum blkvsc_device_type { - UNKNOWN_DEV_TYPE, - HARDDISK_TYPE, - DVD_TYPE, -}; - -enum blkvsc_op_type { - DO_INQUIRY, - DO_CAPACITY, - DO_FLUSH, -}; - -/* - * This request ties the struct request and struct - * blkvsc_request/hv_storvsc_request together A struct request may be - * represented by 1 or more struct blkvsc_request - */ -struct blkvsc_request_group { - int outstanding; - int status; - struct list_head blkvsc_req_list; /* list of blkvsc_requests */ -}; - -struct blkvsc_request { - /* blkvsc_request_group.blkvsc_req_list */ - struct list_head req_entry; - - /* block_device_context.pending_list */ - struct list_head pend_entry; - - /* This may be null if we generate a request internally */ - struct request *req; - - struct block_device_context *dev; - - /* The group this request is part of. Maybe null */ - struct blkvsc_request_group *group; - - int write; - sector_t sector_start; - unsigned long sector_count; - - unsigned char sense_buffer[SCSI_SENSE_BUFFERSIZE]; - unsigned char cmd_len; - unsigned char cmnd[MAX_COMMAND_SIZE]; - - struct hv_storvsc_request request; -}; - -/* Per device structure */ -struct block_device_context { - /* point back to our device context */ - struct hv_device *device_ctx; - struct kmem_cache *request_pool; - spinlock_t lock; - struct gendisk *gd; - enum blkvsc_device_type device_type; - struct list_head pending_list; - - unsigned char device_id[64]; - unsigned int device_id_len; - int num_outstanding_reqs; - int shutting_down; - unsigned int sector_size; - sector_t capacity; - unsigned int port; - unsigned char path; - unsigned char target; - int users; -}; - - -/* - * There is a circular dependency involving blkvsc_request_completion() - * and blkvsc_do_request(). - */ -static void blkvsc_request_completion(struct hv_storvsc_request *request); - -static int blkvsc_ringbuffer_size = BLKVSC_RING_BUFFER_SIZE; - -module_param(blkvsc_ringbuffer_size, int, S_IRUGO); -MODULE_PARM_DESC(ring_size, "Ring buffer size (in bytes)"); - -/* - * There is a circular dependency involving blkvsc_probe() - * and block_ops. - */ -static int blkvsc_probe(struct hv_device *dev); - -static int blkvsc_device_add(struct hv_device *device, - void *additional_info) -{ - struct storvsc_device_info *device_info; - int ret = 0; - - device_info = (struct storvsc_device_info *)additional_info; - - device_info->ring_buffer_size = blkvsc_ringbuffer_size; - - ret = storvsc_dev_add(device, additional_info); - if (ret != 0) - return ret; - - /* - * We need to use the device instance guid to set the path and target - * id. For IDE devices, the device instance id is formatted as - * * - - 8899 - 000000000000. - */ - device_info->path_id = device->dev_instance.b[3] << 24 | - device->dev_instance.b[2] << 16 | - device->dev_instance.b[1] << 8 | - device->dev_instance.b[0]; - - device_info->target_id = device->dev_instance.b[5] << 8 | - device->dev_instance.b[4]; - - return ret; -} - -static int blkvsc_submit_request(struct blkvsc_request *blkvsc_req, - void (*request_completion)(struct hv_storvsc_request *)) -{ - struct block_device_context *blkdev = blkvsc_req->dev; - struct hv_storvsc_request *storvsc_req; - struct vmscsi_request *vm_srb; - int ret; - - - storvsc_req = &blkvsc_req->request; - vm_srb = &storvsc_req->vstor_packet.vm_srb; - - vm_srb->data_in = blkvsc_req->write ? WRITE_TYPE : READ_TYPE; - - storvsc_req->on_io_completion = request_completion; - storvsc_req->context = blkvsc_req; - - vm_srb->port_number = blkdev->port; - vm_srb->path_id = blkdev->path; - vm_srb->target_id = blkdev->target; - vm_srb->lun = 0; /* this is not really used at all */ - - vm_srb->cdb_length = blkvsc_req->cmd_len; - - memcpy(vm_srb->cdb, blkvsc_req->cmnd, vm_srb->cdb_length); - - storvsc_req->sense_buffer = blkvsc_req->sense_buffer; - - ret = storvsc_do_io(blkdev->device_ctx, - &blkvsc_req->request); - if (ret == 0) - blkdev->num_outstanding_reqs++; - - return ret; -} - - -static int blkvsc_open(struct block_device *bdev, fmode_t mode) -{ - struct block_device_context *blkdev = bdev->bd_disk->private_data; - unsigned long flags; - - spin_lock_irqsave(&blkdev->lock, flags); - - blkdev->users++; - - spin_unlock_irqrestore(&blkdev->lock, flags); - - return 0; -} - - -static int blkvsc_getgeo(struct block_device *bd, struct hd_geometry *hg) -{ - sector_t nsect = get_capacity(bd->bd_disk); - sector_t cylinders = nsect; - - /* - * We are making up these values; let us keep it simple. - */ - hg->heads = 0xff; - hg->sectors = 0x3f; - sector_div(cylinders, hg->heads * hg->sectors); - hg->cylinders = cylinders; - if ((sector_t)(hg->cylinders + 1) * hg->heads * hg->sectors < nsect) - hg->cylinders = 0xffff; - return 0; - -} - - -static void blkvsc_init_rw(struct blkvsc_request *blkvsc_req) -{ - - blkvsc_req->cmd_len = 16; - - if (rq_data_dir(blkvsc_req->req)) { - blkvsc_req->write = 1; - blkvsc_req->cmnd[0] = WRITE_16; - } else { - blkvsc_req->write = 0; - blkvsc_req->cmnd[0] = READ_16; - } - - blkvsc_req->cmnd[1] |= - (blkvsc_req->req->cmd_flags & REQ_FUA) ? 0x8 : 0; - - *(unsigned long long *)&blkvsc_req->cmnd[2] = - cpu_to_be64(blkvsc_req->sector_start); - *(unsigned int *)&blkvsc_req->cmnd[10] = - cpu_to_be32(blkvsc_req->sector_count); -} - - -static int blkvsc_ioctl(struct block_device *bd, fmode_t mode, - unsigned cmd, unsigned long arg) -{ - struct block_device_context *blkdev = bd->bd_disk->private_data; - int ret = 0; - - switch (cmd) { - case HDIO_GET_IDENTITY: - if (copy_to_user((void __user *)arg, blkdev->device_id, - blkdev->device_id_len)) - ret = -EFAULT; - break; - default: - ret = -EINVAL; - break; - } - - return ret; -} - -static void blkvsc_cmd_completion(struct hv_storvsc_request *request) -{ - struct blkvsc_request *blkvsc_req = - (struct blkvsc_request *)request->context; - struct block_device_context *blkdev = - (struct block_device_context *)blkvsc_req->dev; - struct scsi_sense_hdr sense_hdr; - struct vmscsi_request *vm_srb; - unsigned long flags; - - - vm_srb = &blkvsc_req->request.vstor_packet.vm_srb; - - spin_lock_irqsave(&blkdev->lock, flags); - blkdev->num_outstanding_reqs--; - spin_unlock_irqrestore(&blkdev->lock, flags); - - if (vm_srb->scsi_status) - if (scsi_normalize_sense(blkvsc_req->sense_buffer, - SCSI_SENSE_BUFFERSIZE, &sense_hdr)) - scsi_print_sense_hdr("blkvsc", &sense_hdr); - - complete(&blkvsc_req->request.wait_event); -} - - -static int blkvsc_do_operation(struct block_device_context *blkdev, - enum blkvsc_op_type op) -{ - struct blkvsc_request *blkvsc_req; - struct page *page_buf; - unsigned char *buf; - unsigned char device_type; - struct scsi_sense_hdr sense_hdr; - struct vmscsi_request *vm_srb; - unsigned long flags; - - int ret = 0; - - blkvsc_req = kmem_cache_zalloc(blkdev->request_pool, GFP_KERNEL); - if (!blkvsc_req) - return -ENOMEM; - - page_buf = alloc_page(GFP_KERNEL); - if (!page_buf) { - kmem_cache_free(blkdev->request_pool, blkvsc_req); - return -ENOMEM; - } - - vm_srb = &blkvsc_req->request.vstor_packet.vm_srb; - init_completion(&blkvsc_req->request.wait_event); - blkvsc_req->dev = blkdev; - blkvsc_req->req = NULL; - blkvsc_req->write = 0; - - blkvsc_req->request.data_buffer.pfn_array[0] = - page_to_pfn(page_buf); - blkvsc_req->request.data_buffer.offset = 0; - - switch (op) { - case DO_INQUIRY: - blkvsc_req->cmnd[0] = INQUIRY; - blkvsc_req->cmnd[1] = 0x1; /* Get product data */ - blkvsc_req->cmnd[2] = 0x83; /* mode page 83 */ - blkvsc_req->cmnd[4] = 64; - blkvsc_req->cmd_len = 6; - blkvsc_req->request.data_buffer.len = 64; - break; - - case DO_CAPACITY: - blkdev->sector_size = 0; - blkdev->capacity = 0; - - blkvsc_req->cmnd[0] = READ_CAPACITY; - blkvsc_req->cmd_len = 16; - blkvsc_req->request.data_buffer.len = 8; - break; - - case DO_FLUSH: - blkvsc_req->cmnd[0] = SYNCHRONIZE_CACHE; - blkvsc_req->cmd_len = 10; - blkvsc_req->request.data_buffer.pfn_array[0] = 0; - blkvsc_req->request.data_buffer.len = 0; - break; - default: - ret = -EINVAL; - goto cleanup; - } - - spin_lock_irqsave(&blkdev->lock, flags); - blkvsc_submit_request(blkvsc_req, blkvsc_cmd_completion); - spin_unlock_irqrestore(&blkdev->lock, flags); - - wait_for_completion_interruptible(&blkvsc_req->request.wait_event); - - /* check error */ - if (vm_srb->scsi_status) { - scsi_normalize_sense(blkvsc_req->sense_buffer, - SCSI_SENSE_BUFFERSIZE, &sense_hdr); - - return 0; - } - - buf = kmap(page_buf); - - switch (op) { - case DO_INQUIRY: - device_type = buf[0] & 0x1F; - - if (device_type == 0x0) - blkdev->device_type = HARDDISK_TYPE; - else - blkdev->device_type = UNKNOWN_DEV_TYPE; - - blkdev->device_id_len = buf[7]; - if (blkdev->device_id_len > 64) - blkdev->device_id_len = 64; - - memcpy(blkdev->device_id, &buf[8], blkdev->device_id_len); - break; - - case DO_CAPACITY: - /* be to le */ - blkdev->capacity = - ((buf[0] << 24) | (buf[1] << 16) | - (buf[2] << 8) | buf[3]) + 1; - - blkdev->sector_size = - (buf[4] << 24) | (buf[5] << 16) | - (buf[6] << 8) | buf[7]; - break; - default: - break; - - } - -cleanup: - - kunmap(page_buf); - - __free_page(page_buf); - - kmem_cache_free(blkdev->request_pool, blkvsc_req); - - return ret; -} - - -static int blkvsc_cancel_pending_reqs(struct block_device_context *blkdev) -{ - struct blkvsc_request *pend_req, *tmp; - struct blkvsc_request *comp_req, *tmp2; - struct vmscsi_request *vm_srb; - - int ret = 0; - - - /* Flush the pending list first */ - list_for_each_entry_safe(pend_req, tmp, &blkdev->pending_list, - pend_entry) { - /* - * The pend_req could be part of a partially completed - * request. If so, complete those req first until we - * hit the pend_req - */ - list_for_each_entry_safe(comp_req, tmp2, - &pend_req->group->blkvsc_req_list, - req_entry) { - - if (comp_req == pend_req) - break; - - list_del(&comp_req->req_entry); - - if (comp_req->req) { - vm_srb = - &comp_req->request.vstor_packet. - vm_srb; - ret = __blk_end_request(comp_req->req, - (!vm_srb->scsi_status ? 0 : -EIO), - comp_req->sector_count * - blkdev->sector_size); - - /* FIXME: shouldn't this do more than return? */ - if (ret) - goto out; - } - - kmem_cache_free(blkdev->request_pool, comp_req); - } - - list_del(&pend_req->pend_entry); - - list_del(&pend_req->req_entry); - - if (comp_req->req) { - if (!__blk_end_request(pend_req->req, -EIO, - pend_req->sector_count * - blkdev->sector_size)) { - /* - * All the sectors have been xferred ie the - * request is done - */ - kmem_cache_free(blkdev->request_pool, - pend_req->group); - } - } - - kmem_cache_free(blkdev->request_pool, pend_req); - } - -out: - return ret; -} - - -/* - * blkvsc_remove() - Callback when our device is removed - */ -static int blkvsc_remove(struct hv_device *dev) -{ - struct block_device_context *blkdev = dev_get_drvdata(&dev->device); - unsigned long flags; - - - /* Get to a known state */ - spin_lock_irqsave(&blkdev->lock, flags); - - blkdev->shutting_down = 1; - - blk_stop_queue(blkdev->gd->queue); - - blkvsc_cancel_pending_reqs(blkdev); - - spin_unlock_irqrestore(&blkdev->lock, flags); - - blkvsc_do_operation(blkdev, DO_FLUSH); - - if (blkdev->users == 0) { - del_gendisk(blkdev->gd); - put_disk(blkdev->gd); - blk_cleanup_queue(blkdev->gd->queue); - - storvsc_dev_remove(blkdev->device_ctx); - - kmem_cache_destroy(blkdev->request_pool); - kfree(blkdev); - } - - return 0; -} - -static void blkvsc_shutdown(struct hv_device *dev) -{ - struct block_device_context *blkdev = dev_get_drvdata(&dev->device); - unsigned long flags; - - if (!blkdev) - return; - - spin_lock_irqsave(&blkdev->lock, flags); - - blkdev->shutting_down = 1; - - blk_stop_queue(blkdev->gd->queue); - - blkvsc_cancel_pending_reqs(blkdev); - - spin_unlock_irqrestore(&blkdev->lock, flags); - - blkvsc_do_operation(blkdev, DO_FLUSH); - - /* - * Now wait for all outgoing I/O to be drained. - */ - storvsc_wait_to_drain((struct storvsc_device *)dev->ext); - -} - -static int blkvsc_release(struct gendisk *disk, fmode_t mode) -{ - struct block_device_context *blkdev = disk->private_data; - unsigned long flags; - - spin_lock_irqsave(&blkdev->lock, flags); - - if ((--blkdev->users == 0) && (blkdev->shutting_down)) { - blk_stop_queue(blkdev->gd->queue); - spin_unlock_irqrestore(&blkdev->lock, flags); - - blkvsc_do_operation(blkdev, DO_FLUSH); - del_gendisk(blkdev->gd); - put_disk(blkdev->gd); - blk_cleanup_queue(blkdev->gd->queue); - - storvsc_dev_remove(blkdev->device_ctx); - - kmem_cache_destroy(blkdev->request_pool); - kfree(blkdev); - } else - spin_unlock_irqrestore(&blkdev->lock, flags); - - return 0; -} - - -/* - * We break the request into 1 or more blkvsc_requests and submit - * them. If we cant submit them all, we put them on the - * pending_list. The blkvsc_request() will work on the pending_list. - */ -static int blkvsc_do_request(struct block_device_context *blkdev, - struct request *req) -{ - struct bio *bio = NULL; - struct bio_vec *bvec = NULL; - struct bio_vec *prev_bvec = NULL; - struct blkvsc_request *blkvsc_req = NULL; - struct blkvsc_request *tmp; - int databuf_idx = 0; - int seg_idx = 0; - sector_t start_sector; - unsigned long num_sectors = 0; - int ret = 0; - int pending = 0; - struct blkvsc_request_group *group = NULL; - - /* Create a group to tie req to list of blkvsc_reqs */ - group = kmem_cache_zalloc(blkdev->request_pool, GFP_ATOMIC); - if (!group) - return -ENOMEM; - - INIT_LIST_HEAD(&group->blkvsc_req_list); - group->outstanding = group->status = 0; - - start_sector = blk_rq_pos(req); - - /* foreach bio in the request */ - if (req->bio) { - for (bio = req->bio; bio; bio = bio->bi_next) { - /* - * Map this bio into an existing or new storvsc request - */ - bio_for_each_segment(bvec, bio, seg_idx) { - /* Get a new storvsc request */ - /* 1st-time */ - if ((!blkvsc_req) || - (databuf_idx >= MAX_MULTIPAGE_BUFFER_COUNT) - /* hole at the begin of page */ - || (bvec->bv_offset != 0) || - /* hold at the end of page */ - (prev_bvec && - (prev_bvec->bv_len != PAGE_SIZE))) { - /* submit the prev one */ - if (blkvsc_req) { - blkvsc_req->sector_start = - start_sector; - sector_div( - blkvsc_req->sector_start, - (blkdev->sector_size >> 9)); - - blkvsc_req->sector_count = - num_sectors / - (blkdev->sector_size >> 9); - blkvsc_init_rw(blkvsc_req); - } - - /* - * Create new blkvsc_req to represent - * the current bvec - */ - blkvsc_req = - kmem_cache_zalloc( - blkdev->request_pool, GFP_ATOMIC); - if (!blkvsc_req) { - /* free up everything */ - list_for_each_entry_safe( - blkvsc_req, tmp, - &group->blkvsc_req_list, - req_entry) { - list_del( - &blkvsc_req->req_entry); - kmem_cache_free( - blkdev->request_pool, - blkvsc_req); - } - - kmem_cache_free( - blkdev->request_pool, group); - return -ENOMEM; - } - - memset(blkvsc_req, 0, - sizeof(struct blkvsc_request)); - - blkvsc_req->dev = blkdev; - blkvsc_req->req = req; - blkvsc_req->request. - data_buffer.offset - = bvec->bv_offset; - blkvsc_req->request. - data_buffer.len = 0; - - /* Add to the group */ - blkvsc_req->group = group; - blkvsc_req->group->outstanding++; - list_add_tail(&blkvsc_req->req_entry, - &blkvsc_req->group->blkvsc_req_list); - - start_sector += num_sectors; - num_sectors = 0; - databuf_idx = 0; - } - - /* - * Add the curr bvec/segment to the curr - * blkvsc_req - */ - blkvsc_req->request.data_buffer. - pfn_array[databuf_idx] - = page_to_pfn(bvec->bv_page); - blkvsc_req->request.data_buffer.len - += bvec->bv_len; - - prev_bvec = bvec; - - databuf_idx++; - num_sectors += bvec->bv_len >> 9; - - } /* bio_for_each_segment */ - - } /* rq_for_each_bio */ - } - - /* Handle the last one */ - if (blkvsc_req) { - blkvsc_req->sector_start = start_sector; - sector_div(blkvsc_req->sector_start, - (blkdev->sector_size >> 9)); - - blkvsc_req->sector_count = num_sectors / - (blkdev->sector_size >> 9); - - blkvsc_init_rw(blkvsc_req); - } - - list_for_each_entry(blkvsc_req, &group->blkvsc_req_list, req_entry) { - if (pending) { - - list_add_tail(&blkvsc_req->pend_entry, - &blkdev->pending_list); - } else { - ret = blkvsc_submit_request(blkvsc_req, - blkvsc_request_completion); - if (ret == -EAGAIN) { - pending = 1; - list_add_tail(&blkvsc_req->pend_entry, - &blkdev->pending_list); - } - - } - } - - return pending; -} - -static int blkvsc_do_pending_reqs(struct block_device_context *blkdev) -{ - struct blkvsc_request *pend_req, *tmp; - int ret = 0; - - /* Flush the pending list first */ - list_for_each_entry_safe(pend_req, tmp, &blkdev->pending_list, - pend_entry) { - - ret = blkvsc_submit_request(pend_req, - blkvsc_request_completion); - if (ret != 0) - break; - else - list_del(&pend_req->pend_entry); - } - - return ret; -} - - -static void blkvsc_request(struct request_queue *queue) -{ - struct block_device_context *blkdev = NULL; - struct request *req; - int ret = 0; - - while ((req = blk_peek_request(queue)) != NULL) { - - blkdev = req->rq_disk->private_data; - if (blkdev->shutting_down || req->cmd_type != REQ_TYPE_FS) { - __blk_end_request_cur(req, 0); - continue; - } - - ret = blkvsc_do_pending_reqs(blkdev); - - if (ret != 0) { - blk_stop_queue(queue); - break; - } - - blk_start_request(req); - - ret = blkvsc_do_request(blkdev, req); - if (ret > 0) { - blk_stop_queue(queue); - break; - } else if (ret < 0) { - blk_requeue_request(queue, req); - blk_stop_queue(queue); - break; - } - } -} - -static const struct hv_vmbus_device_id id_table[] = { - /* 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); - -/* The one and only one */ -static struct hv_driver blkvsc_drv = { - .name = "blkvsc", - .id_table = id_table, - .probe = blkvsc_probe, - .remove = blkvsc_remove, - .shutdown = blkvsc_shutdown, -}; - -static const struct block_device_operations block_ops = { - .owner = THIS_MODULE, - .open = blkvsc_open, - .release = blkvsc_release, - .getgeo = blkvsc_getgeo, - .ioctl = blkvsc_ioctl, -}; - -/* - * blkvsc_drv_init - BlkVsc driver initialization. - */ -static int blkvsc_drv_init(void) -{ - BUILD_BUG_ON(sizeof(sector_t) != 8); - return vmbus_driver_register(&blkvsc_drv); -} - -static void blkvsc_drv_exit(void) -{ - vmbus_driver_unregister(&blkvsc_drv); -} - -/* - * blkvsc_probe - Add a new device for this driver - */ -static int blkvsc_probe(struct hv_device *dev) -{ - struct block_device_context *blkdev = NULL; - struct storvsc_device_info device_info; - struct storvsc_major_info major_info; - int ret = 0; - - blkdev = kzalloc(sizeof(struct block_device_context), GFP_KERNEL); - if (!blkdev) { - ret = -ENOMEM; - goto cleanup; - } - - INIT_LIST_HEAD(&blkdev->pending_list); - - /* Initialize what we can here */ - spin_lock_init(&blkdev->lock); - - - blkdev->request_pool = kmem_cache_create(dev_name(&dev->device), - sizeof(struct blkvsc_request), 0, - SLAB_HWCACHE_ALIGN, NULL); - if (!blkdev->request_pool) { - ret = -ENOMEM; - goto cleanup; - } - - - ret = blkvsc_device_add(dev, &device_info); - if (ret != 0) - goto cleanup; - - blkdev->device_ctx = dev; - /* this identified the device 0 or 1 */ - blkdev->target = device_info.target_id; - /* this identified the ide ctrl 0 or 1 */ - blkdev->path = device_info.path_id; - - dev_set_drvdata(&dev->device, blkdev); - - ret = storvsc_get_major_info(&device_info, &major_info); - - if (ret) - goto cleanup; - - if (major_info.do_register) { - ret = register_blkdev(major_info.major, major_info.devname); - - if (ret != 0) { - DPRINT_ERR(BLKVSC_DRV, - "register_blkdev() failed! ret %d", ret); - goto remove; - } - } - - DPRINT_INFO(BLKVSC_DRV, "blkvsc registered for major %d!!", - major_info.major); - - blkdev->gd = alloc_disk(BLKVSC_MINORS); - if (!blkdev->gd) { - ret = -1; - goto cleanup; - } - - blkdev->gd->queue = blk_init_queue(blkvsc_request, &blkdev->lock); - - blk_queue_max_segment_size(blkdev->gd->queue, PAGE_SIZE); - blk_queue_max_segments(blkdev->gd->queue, MAX_MULTIPAGE_BUFFER_COUNT); - blk_queue_segment_boundary(blkdev->gd->queue, PAGE_SIZE-1); - blk_queue_bounce_limit(blkdev->gd->queue, BLK_BOUNCE_ANY); - blk_queue_dma_alignment(blkdev->gd->queue, 511); - - blkdev->gd->major = major_info.major; - if (major_info.index == 1 || major_info.index == 3) - blkdev->gd->first_minor = BLKVSC_MINORS; - else - blkdev->gd->first_minor = 0; - blkdev->gd->fops = &block_ops; - blkdev->gd->private_data = blkdev; - blkdev->gd->driverfs_dev = &(blkdev->device_ctx->device); - sprintf(blkdev->gd->disk_name, "hd%c", 'a' + major_info.index); - - blkvsc_do_operation(blkdev, DO_INQUIRY); - blkvsc_do_operation(blkdev, DO_CAPACITY); - - set_capacity(blkdev->gd, blkdev->capacity * (blkdev->sector_size/512)); - blk_queue_logical_block_size(blkdev->gd->queue, blkdev->sector_size); - /* go! */ - add_disk(blkdev->gd); - - DPRINT_INFO(BLKVSC_DRV, "%s added!! capacity %lu sector_size %d", - blkdev->gd->disk_name, (unsigned long)blkdev->capacity, - blkdev->sector_size); - - return ret; - -remove: - storvsc_dev_remove(dev); - -cleanup: - if (blkdev) { - if (blkdev->request_pool) { - kmem_cache_destroy(blkdev->request_pool); - blkdev->request_pool = NULL; - } - kfree(blkdev); - blkdev = NULL; - } - - return ret; -} - -static void blkvsc_request_completion(struct hv_storvsc_request *request) -{ - struct blkvsc_request *blkvsc_req = - (struct blkvsc_request *)request->context; - struct block_device_context *blkdev = - (struct block_device_context *)blkvsc_req->dev; - unsigned long flags; - struct blkvsc_request *comp_req, *tmp; - struct vmscsi_request *vm_srb; - - - spin_lock_irqsave(&blkdev->lock, flags); - - blkdev->num_outstanding_reqs--; - blkvsc_req->group->outstanding--; - - /* - * Only start processing when all the blkvsc_reqs are - * completed. This guarantees no out-of-order blkvsc_req - * completion when calling end_that_request_first() - */ - if (blkvsc_req->group->outstanding == 0) { - list_for_each_entry_safe(comp_req, tmp, - &blkvsc_req->group->blkvsc_req_list, - req_entry) { - - list_del(&comp_req->req_entry); - - vm_srb = - &comp_req->request.vstor_packet.vm_srb; - if (!__blk_end_request(comp_req->req, - (!vm_srb->scsi_status ? 0 : -EIO), - comp_req->sector_count * blkdev->sector_size)) { - /* - * All the sectors have been xferred ie the - * request is done - */ - kmem_cache_free(blkdev->request_pool, - comp_req->group); - } - - kmem_cache_free(blkdev->request_pool, comp_req); - } - - if (!blkdev->shutting_down) { - blkvsc_do_pending_reqs(blkdev); - blk_start_queue(blkdev->gd->queue); - blkvsc_request(blkdev->gd->queue); - } - } - - spin_unlock_irqrestore(&blkdev->lock, flags); -} - -static void __exit blkvsc_exit(void) -{ - blkvsc_drv_exit(); -} - -MODULE_LICENSE("GPL"); -MODULE_VERSION(HV_DRV_VERSION); -MODULE_DESCRIPTION("Microsoft Hyper-V virtual block driver"); -module_init(blkvsc_drv_init); -module_exit(blkvsc_exit); -- cgit v1.2.3