[x86] hv: Update all Hyper-V drivers to 3.4-rc1 (Closes: #661318)
svn path=/dists/sid/linux-2.6/; revision=18921
This commit is contained in:
parent
c31d2a0d11
commit
3121d09256
|
@ -8,6 +8,7 @@ linux-2.6 (3.2.14-2) UNRELEASED; urgency=low
|
|||
(Closes: #668036)
|
||||
* TOMOYO: Fix mount flags checking order.
|
||||
* drm/radeon/kms: fix fans after resume (Closes: #596741)
|
||||
* [x86] hv: Update all Hyper-V drivers to 3.4-rc1 (Closes: #661318)
|
||||
|
||||
[ Jonathan Nieder ]
|
||||
* [x86] ioat: fix size of 'completion' for Xen (Closes: #660554)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
[abi]
|
||||
abiname: 2
|
||||
ignore-changes: module:drivers/net/wireless/ath/ath9k/*
|
||||
module:drivers/hv/*
|
||||
|
||||
[base]
|
||||
arches:
|
||||
|
|
60
debian/patches/debian/nls-Avoid-ABI-change-from-improvement-to-utf8s_to_ut.patch
vendored
Normal file
60
debian/patches/debian/nls-Avoid-ABI-change-from-improvement-to-utf8s_to_ut.patch
vendored
Normal file
|
@ -0,0 +1,60 @@
|
|||
From: Ben Hutchings <ben@decadent.org.uk>
|
||||
Date: Mon, 9 Apr 2012 00:51:37 +0100
|
||||
Subject: [PATCH] nls: Avoid ABI change from improvement to utf8s_to_utf16s
|
||||
|
||||
It's easy to add a temporary wrapper for binary-compatibility.
|
||||
---
|
||||
fs/nls/nls_base.c | 13 ++++++++++++-
|
||||
include/linux/nls.h | 4 +++-
|
||||
2 files changed, 15 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/fs/nls/nls_base.c b/fs/nls/nls_base.c
|
||||
index 0eb059e..91f145a 100644
|
||||
--- a/fs/nls/nls_base.c
|
||||
+++ b/fs/nls/nls_base.c
|
||||
@@ -129,7 +129,7 @@ static inline void put_utf16(wchar_t *s, unsigned c, enum utf16_endian endian)
|
||||
}
|
||||
}
|
||||
|
||||
-int utf8s_to_utf16s(const u8 *s, int len, enum utf16_endian endian,
|
||||
+int utf8s_to_utf16s_new(const u8 *s, int len, enum utf16_endian endian,
|
||||
wchar_t *pwcs, int maxlen)
|
||||
{
|
||||
u16 *op;
|
||||
@@ -171,6 +171,17 @@ int utf8s_to_utf16s(const u8 *s, int len, enum utf16_endian endian,
|
||||
}
|
||||
EXPORT_SYMBOL(utf8s_to_utf16s);
|
||||
|
||||
+/* Binary-compatibility wrapper */
|
||||
+#undef utf8s_to_utf16s
|
||||
+int utf8s_to_utf16s(const u8 *s, int len, wchar_t *pwcs)
|
||||
+{
|
||||
+ /* Output length in code units is never longer than input
|
||||
+ * length in bytes, so we can trivially set maxlen = len.
|
||||
+ */
|
||||
+ return utf8s_to_utf16s_new(s, len, UTF16_HOST_ENDIAN, pwcs, len);
|
||||
+}
|
||||
+EXPORT_SYMBOL(utf8s_to_utf16s);
|
||||
+
|
||||
static inline unsigned long get_utf16(unsigned c, enum utf16_endian endian)
|
||||
{
|
||||
switch (endian) {
|
||||
diff --git a/include/linux/nls.h b/include/linux/nls.h
|
||||
index 5dc635f..6a2a00c 100644
|
||||
--- a/include/linux/nls.h
|
||||
+++ b/include/linux/nls.h
|
||||
@@ -52,8 +52,10 @@ extern struct nls_table *load_nls_default(void);
|
||||
|
||||
extern int utf8_to_utf32(const u8 *s, int len, unicode_t *pu);
|
||||
extern int utf32_to_utf8(unicode_t u, u8 *s, int maxlen);
|
||||
-extern int utf8s_to_utf16s(const u8 *s, int len,
|
||||
+extern int utf8s_to_utf16s(const u8 *s, int len, wchar_t *pwcs);
|
||||
+extern int utf8s_to_utf16s_new(const u8 *s, int len,
|
||||
enum utf16_endian endian, wchar_t *pwcs, int maxlen);
|
||||
+#define utf8s_to_utf16s utf8s_to_utf16s_new
|
||||
extern int utf16s_to_utf8s(const wchar_t *pwcs, int len,
|
||||
enum utf16_endian endian, u8 *s, int maxlen);
|
||||
|
||||
--
|
||||
1.7.9.5
|
||||
|
164
debian/patches/features/x86/hyperv/0001-NLS-improve-UTF8-UTF16-string-conversion-routine.patch
vendored
Normal file
164
debian/patches/features/x86/hyperv/0001-NLS-improve-UTF8-UTF16-string-conversion-routine.patch
vendored
Normal file
|
@ -0,0 +1,164 @@
|
|||
From: Alan Stern <stern@rowland.harvard.edu>
|
||||
Date: Thu, 17 Nov 2011 16:42:19 -0500
|
||||
Subject: [PATCH 01/77] NLS: improve UTF8 -> UTF16 string conversion routine
|
||||
|
||||
commit 0720a06a7518c9d0c0125bd5d1f3b6264c55c3dd upstream.
|
||||
|
||||
The utf8s_to_utf16s conversion routine needs to be improved. Unlike
|
||||
its utf16s_to_utf8s sibling, it doesn't accept arguments specifying
|
||||
the maximum length of the output buffer or the endianness of its
|
||||
16-bit output.
|
||||
|
||||
This patch (as1501) adds the two missing arguments, and adjusts the
|
||||
only two places in the kernel where the function is called. A
|
||||
follow-on patch will add a third caller that does utilize the new
|
||||
capabilities.
|
||||
|
||||
The two conversion routines are still annoyingly inconsistent in the
|
||||
way they handle invalid byte combinations. But that's a subject for a
|
||||
different patch.
|
||||
|
||||
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
|
||||
CC: Clemens Ladisch <clemens@ladisch.de>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
---
|
||||
drivers/hv/hv_kvp.c | 10 ++++++----
|
||||
fs/fat/namei_vfat.c | 3 ++-
|
||||
fs/nls/nls_base.c | 43 +++++++++++++++++++++++++++++++++----------
|
||||
include/linux/nls.h | 5 +++--
|
||||
4 files changed, 44 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
|
||||
index 89f5244..0e8343f 100644
|
||||
--- a/drivers/hv/hv_kvp.c
|
||||
+++ b/drivers/hv/hv_kvp.c
|
||||
@@ -212,11 +212,13 @@ kvp_respond_to_host(char *key, char *value, int error)
|
||||
* The windows host expects the key/value pair to be encoded
|
||||
* in utf16.
|
||||
*/
|
||||
- keylen = utf8s_to_utf16s(key_name, strlen(key_name),
|
||||
- (wchar_t *)kvp_data->data.key);
|
||||
+ keylen = utf8s_to_utf16s(key_name, strlen(key_name), UTF16_HOST_ENDIAN,
|
||||
+ (wchar_t *) kvp_data->data.key,
|
||||
+ HV_KVP_EXCHANGE_MAX_KEY_SIZE / 2);
|
||||
kvp_data->data.key_size = 2*(keylen + 1); /* utf16 encoding */
|
||||
- valuelen = utf8s_to_utf16s(value, strlen(value),
|
||||
- (wchar_t *)kvp_data->data.value);
|
||||
+ valuelen = utf8s_to_utf16s(value, strlen(value), UTF16_HOST_ENDIAN,
|
||||
+ (wchar_t *) kvp_data->data.value,
|
||||
+ HV_KVP_EXCHANGE_MAX_VALUE_SIZE / 2);
|
||||
kvp_data->data.value_size = 2*(valuelen + 1); /* utf16 encoding */
|
||||
|
||||
kvp_data->data.value_type = REG_SZ; /* all our values are strings */
|
||||
diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c
|
||||
index a87a656..c25cf15 100644
|
||||
--- a/fs/fat/namei_vfat.c
|
||||
+++ b/fs/fat/namei_vfat.c
|
||||
@@ -512,7 +512,8 @@ xlate_to_uni(const unsigned char *name, int len, unsigned char *outname,
|
||||
int charlen;
|
||||
|
||||
if (utf8) {
|
||||
- *outlen = utf8s_to_utf16s(name, len, (wchar_t *)outname);
|
||||
+ *outlen = utf8s_to_utf16s(name, len, UTF16_HOST_ENDIAN,
|
||||
+ (wchar_t *) outname, FAT_LFN_LEN + 2);
|
||||
if (*outlen < 0)
|
||||
return *outlen;
|
||||
else if (*outlen > FAT_LFN_LEN)
|
||||
diff --git a/fs/nls/nls_base.c b/fs/nls/nls_base.c
|
||||
index 44a88a9..0eb059e 100644
|
||||
--- a/fs/nls/nls_base.c
|
||||
+++ b/fs/nls/nls_base.c
|
||||
@@ -114,34 +114,57 @@ int utf32_to_utf8(unicode_t u, u8 *s, int maxlen)
|
||||
}
|
||||
EXPORT_SYMBOL(utf32_to_utf8);
|
||||
|
||||
-int utf8s_to_utf16s(const u8 *s, int len, wchar_t *pwcs)
|
||||
+static inline void put_utf16(wchar_t *s, unsigned c, enum utf16_endian endian)
|
||||
+{
|
||||
+ switch (endian) {
|
||||
+ default:
|
||||
+ *s = (wchar_t) c;
|
||||
+ break;
|
||||
+ case UTF16_LITTLE_ENDIAN:
|
||||
+ *s = __cpu_to_le16(c);
|
||||
+ break;
|
||||
+ case UTF16_BIG_ENDIAN:
|
||||
+ *s = __cpu_to_be16(c);
|
||||
+ break;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+int utf8s_to_utf16s(const u8 *s, int len, enum utf16_endian endian,
|
||||
+ wchar_t *pwcs, int maxlen)
|
||||
{
|
||||
u16 *op;
|
||||
int size;
|
||||
unicode_t u;
|
||||
|
||||
op = pwcs;
|
||||
- while (*s && len > 0) {
|
||||
+ while (len > 0 && maxlen > 0 && *s) {
|
||||
if (*s & 0x80) {
|
||||
size = utf8_to_utf32(s, len, &u);
|
||||
if (size < 0)
|
||||
return -EINVAL;
|
||||
+ s += size;
|
||||
+ len -= size;
|
||||
|
||||
if (u >= PLANE_SIZE) {
|
||||
+ if (maxlen < 2)
|
||||
+ break;
|
||||
u -= PLANE_SIZE;
|
||||
- *op++ = (wchar_t) (SURROGATE_PAIR |
|
||||
- ((u >> 10) & SURROGATE_BITS));
|
||||
- *op++ = (wchar_t) (SURROGATE_PAIR |
|
||||
+ put_utf16(op++, SURROGATE_PAIR |
|
||||
+ ((u >> 10) & SURROGATE_BITS),
|
||||
+ endian);
|
||||
+ put_utf16(op++, SURROGATE_PAIR |
|
||||
SURROGATE_LOW |
|
||||
- (u & SURROGATE_BITS));
|
||||
+ (u & SURROGATE_BITS),
|
||||
+ endian);
|
||||
+ maxlen -= 2;
|
||||
} else {
|
||||
- *op++ = (wchar_t) u;
|
||||
+ put_utf16(op++, u, endian);
|
||||
+ maxlen--;
|
||||
}
|
||||
- s += size;
|
||||
- len -= size;
|
||||
} else {
|
||||
- *op++ = *s++;
|
||||
+ put_utf16(op++, *s++, endian);
|
||||
len--;
|
||||
+ maxlen--;
|
||||
}
|
||||
}
|
||||
return op - pwcs;
|
||||
diff --git a/include/linux/nls.h b/include/linux/nls.h
|
||||
index d47beef..5dc635f 100644
|
||||
--- a/include/linux/nls.h
|
||||
+++ b/include/linux/nls.h
|
||||
@@ -43,7 +43,7 @@ enum utf16_endian {
|
||||
UTF16_BIG_ENDIAN
|
||||
};
|
||||
|
||||
-/* nls.c */
|
||||
+/* nls_base.c */
|
||||
extern int register_nls(struct nls_table *);
|
||||
extern int unregister_nls(struct nls_table *);
|
||||
extern struct nls_table *load_nls(char *);
|
||||
@@ -52,7 +52,8 @@ extern struct nls_table *load_nls_default(void);
|
||||
|
||||
extern int utf8_to_utf32(const u8 *s, int len, unicode_t *pu);
|
||||
extern int utf32_to_utf8(unicode_t u, u8 *s, int maxlen);
|
||||
-extern int utf8s_to_utf16s(const u8 *s, int len, wchar_t *pwcs);
|
||||
+extern int utf8s_to_utf16s(const u8 *s, int len,
|
||||
+ enum utf16_endian endian, wchar_t *pwcs, int maxlen);
|
||||
extern int utf16s_to_utf8s(const wchar_t *pwcs, int len,
|
||||
enum utf16_endian endian, u8 *s, int maxlen);
|
||||
|
||||
--
|
||||
1.7.9.5
|
||||
|
646
debian/patches/features/x86/hyperv/0002-HID-Move-the-hid-hyperv-driver-out-of-staging.patch
vendored
Normal file
646
debian/patches/features/x86/hyperv/0002-HID-Move-the-hid-hyperv-driver-out-of-staging.patch
vendored
Normal file
|
@ -0,0 +1,646 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Thu, 17 Nov 2011 08:47:29 -0800
|
||||
Subject: [PATCH 02/77] HID: Move the hid-hyperv driver out of staging
|
||||
|
||||
commit b95f5bcb811e3905b5376f87789da8d097fee682 upstream.
|
||||
|
||||
The file hid-hyperv.c implements a hid compliant mouse driver for use on a
|
||||
Hyper-V based system. This driver is currently in the staging area and as part
|
||||
of the effort to move this driver out of staging, I had posted the driver code
|
||||
for community review a few weeks ago. This current patch addresses all the
|
||||
review comments I have gotten to date. All the relevant patches have already
|
||||
been submitted to the staging tree as well.
|
||||
|
||||
As per Greg's suggestion, this patch does not get rid of the code from
|
||||
the staging area. Once the mouse driver lands under the hid directory,
|
||||
we will cleanup the staging directory.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
|
||||
---
|
||||
drivers/hid/Kconfig | 6 +
|
||||
drivers/hid/Makefile | 1 +
|
||||
drivers/hid/hid-hyperv.c | 582 ++++++++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 589 insertions(+)
|
||||
create mode 100644 drivers/hid/hid-hyperv.c
|
||||
|
||||
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
|
||||
index d21f6d0..4c09210 100644
|
||||
--- a/drivers/hid/Kconfig
|
||||
+++ b/drivers/hid/Kconfig
|
||||
@@ -646,6 +646,12 @@ config HID_ZYDACRON
|
||||
---help---
|
||||
Support for Zydacron remote control.
|
||||
|
||||
+config HYPERV_MOUSE
|
||||
+ tristate "Microsoft Hyper-V mouse driver"
|
||||
+ depends on HYPERV
|
||||
+ ---help---
|
||||
+ Select this option to enable the Hyper-V mouse driver.
|
||||
+
|
||||
endmenu
|
||||
|
||||
endif # HID_SUPPORT
|
||||
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
|
||||
index 1e0d2a6..fbb1ee6 100644
|
||||
--- a/drivers/hid/Makefile
|
||||
+++ b/drivers/hid/Makefile
|
||||
@@ -78,6 +78,7 @@ obj-$(CONFIG_HID_ZYDACRON) += hid-zydacron.o
|
||||
obj-$(CONFIG_HID_WACOM) += hid-wacom.o
|
||||
obj-$(CONFIG_HID_WALTOP) += hid-waltop.o
|
||||
obj-$(CONFIG_HID_WIIMOTE) += hid-wiimote.o
|
||||
+obj-$(CONFIG_HYPERV_MOUSE) += hid-hyperv.o
|
||||
|
||||
obj-$(CONFIG_USB_HID) += usbhid/
|
||||
obj-$(CONFIG_USB_MOUSE) += usbhid/
|
||||
diff --git a/drivers/hid/hid-hyperv.c b/drivers/hid/hid-hyperv.c
|
||||
new file mode 100644
|
||||
index 0000000..d503cbb
|
||||
--- /dev/null
|
||||
+++ b/drivers/hid/hid-hyperv.c
|
||||
@@ -0,0 +1,582 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2009, Citrix Systems, Inc.
|
||||
+ * Copyright (c) 2010, Microsoft Corporation.
|
||||
+ * Copyright (c) 2011, Novell Inc.
|
||||
+ *
|
||||
+ * 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.
|
||||
+ */
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/device.h>
|
||||
+#include <linux/completion.h>
|
||||
+#include <linux/input.h>
|
||||
+#include <linux/hid.h>
|
||||
+#include <linux/hiddev.h>
|
||||
+#include <linux/hyperv.h>
|
||||
+
|
||||
+
|
||||
+struct hv_input_dev_info {
|
||||
+ unsigned int size;
|
||||
+ unsigned short vendor;
|
||||
+ unsigned short product;
|
||||
+ unsigned short version;
|
||||
+ unsigned short reserved[11];
|
||||
+};
|
||||
+
|
||||
+/* The maximum size of a synthetic input message. */
|
||||
+#define SYNTHHID_MAX_INPUT_REPORT_SIZE 16
|
||||
+
|
||||
+/*
|
||||
+ * Current version
|
||||
+ *
|
||||
+ * History:
|
||||
+ * Beta, RC < 2008/1/22 1,0
|
||||
+ * RC > 2008/1/22 2,0
|
||||
+ */
|
||||
+#define SYNTHHID_INPUT_VERSION_MAJOR 2
|
||||
+#define SYNTHHID_INPUT_VERSION_MINOR 0
|
||||
+#define SYNTHHID_INPUT_VERSION (SYNTHHID_INPUT_VERSION_MINOR | \
|
||||
+ (SYNTHHID_INPUT_VERSION_MAJOR << 16))
|
||||
+
|
||||
+
|
||||
+#pragma pack(push, 1)
|
||||
+/*
|
||||
+ * Message types in the synthetic input protocol
|
||||
+ */
|
||||
+enum synthhid_msg_type {
|
||||
+ SYNTH_HID_PROTOCOL_REQUEST,
|
||||
+ SYNTH_HID_PROTOCOL_RESPONSE,
|
||||
+ SYNTH_HID_INITIAL_DEVICE_INFO,
|
||||
+ SYNTH_HID_INITIAL_DEVICE_INFO_ACK,
|
||||
+ SYNTH_HID_INPUT_REPORT,
|
||||
+ SYNTH_HID_MAX
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * Basic message structures.
|
||||
+ */
|
||||
+struct synthhid_msg_hdr {
|
||||
+ enum synthhid_msg_type type;
|
||||
+ u32 size;
|
||||
+};
|
||||
+
|
||||
+struct synthhid_msg {
|
||||
+ struct synthhid_msg_hdr header;
|
||||
+ char data[1]; /* Enclosed message */
|
||||
+};
|
||||
+
|
||||
+union synthhid_version {
|
||||
+ struct {
|
||||
+ u16 minor_version;
|
||||
+ u16 major_version;
|
||||
+ };
|
||||
+ u32 version;
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * Protocol messages
|
||||
+ */
|
||||
+struct synthhid_protocol_request {
|
||||
+ struct synthhid_msg_hdr header;
|
||||
+ union synthhid_version version_requested;
|
||||
+};
|
||||
+
|
||||
+struct synthhid_protocol_response {
|
||||
+ struct synthhid_msg_hdr header;
|
||||
+ union synthhid_version version_requested;
|
||||
+ unsigned char approved;
|
||||
+};
|
||||
+
|
||||
+struct synthhid_device_info {
|
||||
+ struct synthhid_msg_hdr header;
|
||||
+ struct hv_input_dev_info hid_dev_info;
|
||||
+ struct hid_descriptor hid_descriptor;
|
||||
+};
|
||||
+
|
||||
+struct synthhid_device_info_ack {
|
||||
+ struct synthhid_msg_hdr header;
|
||||
+ unsigned char reserved;
|
||||
+};
|
||||
+
|
||||
+struct synthhid_input_report {
|
||||
+ struct synthhid_msg_hdr header;
|
||||
+ char buffer[1];
|
||||
+};
|
||||
+
|
||||
+#pragma pack(pop)
|
||||
+
|
||||
+#define INPUTVSC_SEND_RING_BUFFER_SIZE (10*PAGE_SIZE)
|
||||
+#define INPUTVSC_RECV_RING_BUFFER_SIZE (10*PAGE_SIZE)
|
||||
+
|
||||
+
|
||||
+enum pipe_prot_msg_type {
|
||||
+ PIPE_MESSAGE_INVALID,
|
||||
+ PIPE_MESSAGE_DATA,
|
||||
+ PIPE_MESSAGE_MAXIMUM
|
||||
+};
|
||||
+
|
||||
+
|
||||
+struct pipe_prt_msg {
|
||||
+ enum pipe_prot_msg_type type;
|
||||
+ u32 size;
|
||||
+ char data[1];
|
||||
+};
|
||||
+
|
||||
+struct mousevsc_prt_msg {
|
||||
+ enum pipe_prot_msg_type type;
|
||||
+ u32 size;
|
||||
+ union {
|
||||
+ struct synthhid_protocol_request request;
|
||||
+ struct synthhid_protocol_response response;
|
||||
+ struct synthhid_device_info_ack ack;
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * Represents an mousevsc device
|
||||
+ */
|
||||
+struct mousevsc_dev {
|
||||
+ struct hv_device *device;
|
||||
+ bool init_complete;
|
||||
+ bool connected;
|
||||
+ struct mousevsc_prt_msg protocol_req;
|
||||
+ struct mousevsc_prt_msg protocol_resp;
|
||||
+ /* Synchronize the request/response if needed */
|
||||
+ struct completion wait_event;
|
||||
+ int dev_info_status;
|
||||
+
|
||||
+ struct hid_descriptor *hid_desc;
|
||||
+ unsigned char *report_desc;
|
||||
+ u32 report_desc_size;
|
||||
+ struct hv_input_dev_info hid_dev_info;
|
||||
+ struct hid_device *hid_device;
|
||||
+};
|
||||
+
|
||||
+
|
||||
+static struct mousevsc_dev *mousevsc_alloc_device(struct hv_device *device)
|
||||
+{
|
||||
+ struct mousevsc_dev *input_dev;
|
||||
+
|
||||
+ input_dev = kzalloc(sizeof(struct mousevsc_dev), GFP_KERNEL);
|
||||
+
|
||||
+ if (!input_dev)
|
||||
+ return NULL;
|
||||
+
|
||||
+ input_dev->device = device;
|
||||
+ hv_set_drvdata(device, input_dev);
|
||||
+ init_completion(&input_dev->wait_event);
|
||||
+ input_dev->init_complete = false;
|
||||
+
|
||||
+ return input_dev;
|
||||
+}
|
||||
+
|
||||
+static void mousevsc_free_device(struct mousevsc_dev *device)
|
||||
+{
|
||||
+ kfree(device->hid_desc);
|
||||
+ kfree(device->report_desc);
|
||||
+ hv_set_drvdata(device->device, NULL);
|
||||
+ kfree(device);
|
||||
+}
|
||||
+
|
||||
+static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device,
|
||||
+ struct synthhid_device_info *device_info)
|
||||
+{
|
||||
+ int ret = 0;
|
||||
+ struct hid_descriptor *desc;
|
||||
+ struct mousevsc_prt_msg ack;
|
||||
+
|
||||
+ input_device->dev_info_status = -ENOMEM;
|
||||
+
|
||||
+ input_device->hid_dev_info = device_info->hid_dev_info;
|
||||
+ desc = &device_info->hid_descriptor;
|
||||
+ if (desc->bLength == 0)
|
||||
+ goto cleanup;
|
||||
+
|
||||
+ input_device->hid_desc = kzalloc(desc->bLength, GFP_ATOMIC);
|
||||
+
|
||||
+ if (!input_device->hid_desc)
|
||||
+ goto cleanup;
|
||||
+
|
||||
+ memcpy(input_device->hid_desc, desc, desc->bLength);
|
||||
+
|
||||
+ input_device->report_desc_size = desc->desc[0].wDescriptorLength;
|
||||
+ if (input_device->report_desc_size == 0) {
|
||||
+ input_device->dev_info_status = -EINVAL;
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
+ input_device->report_desc = kzalloc(input_device->report_desc_size,
|
||||
+ GFP_ATOMIC);
|
||||
+
|
||||
+ if (!input_device->report_desc) {
|
||||
+ input_device->dev_info_status = -ENOMEM;
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
+ memcpy(input_device->report_desc,
|
||||
+ ((unsigned char *)desc) + desc->bLength,
|
||||
+ desc->desc[0].wDescriptorLength);
|
||||
+
|
||||
+ /* Send the ack */
|
||||
+ memset(&ack, 0, sizeof(struct mousevsc_prt_msg));
|
||||
+
|
||||
+ ack.type = PIPE_MESSAGE_DATA;
|
||||
+ ack.size = sizeof(struct synthhid_device_info_ack);
|
||||
+
|
||||
+ ack.ack.header.type = SYNTH_HID_INITIAL_DEVICE_INFO_ACK;
|
||||
+ ack.ack.header.size = 1;
|
||||
+ ack.ack.reserved = 0;
|
||||
+
|
||||
+ ret = vmbus_sendpacket(input_device->device->channel,
|
||||
+ &ack,
|
||||
+ sizeof(struct pipe_prt_msg) - sizeof(unsigned char) +
|
||||
+ sizeof(struct synthhid_device_info_ack),
|
||||
+ (unsigned long)&ack,
|
||||
+ VM_PKT_DATA_INBAND,
|
||||
+ VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
|
||||
+
|
||||
+ if (!ret)
|
||||
+ input_device->dev_info_status = 0;
|
||||
+
|
||||
+cleanup:
|
||||
+ complete(&input_device->wait_event);
|
||||
+
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+static void mousevsc_on_receive(struct hv_device *device,
|
||||
+ struct vmpacket_descriptor *packet)
|
||||
+{
|
||||
+ struct pipe_prt_msg *pipe_msg;
|
||||
+ struct synthhid_msg *hid_msg;
|
||||
+ struct mousevsc_dev *input_dev = hv_get_drvdata(device);
|
||||
+ struct synthhid_input_report *input_report;
|
||||
+
|
||||
+ pipe_msg = (struct pipe_prt_msg *)((unsigned long)packet +
|
||||
+ (packet->offset8 << 3));
|
||||
+
|
||||
+ if (pipe_msg->type != PIPE_MESSAGE_DATA)
|
||||
+ return;
|
||||
+
|
||||
+ hid_msg = (struct synthhid_msg *)pipe_msg->data;
|
||||
+
|
||||
+ switch (hid_msg->header.type) {
|
||||
+ case SYNTH_HID_PROTOCOL_RESPONSE:
|
||||
+ /*
|
||||
+ * While it will be impossible for us to protect against
|
||||
+ * malicious/buggy hypervisor/host, add a check here to
|
||||
+ * ensure we don't corrupt memory.
|
||||
+ */
|
||||
+ if ((pipe_msg->size + sizeof(struct pipe_prt_msg)
|
||||
+ - sizeof(unsigned char))
|
||||
+ > sizeof(struct mousevsc_prt_msg)) {
|
||||
+ WARN_ON(1);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ memcpy(&input_dev->protocol_resp, pipe_msg,
|
||||
+ pipe_msg->size + sizeof(struct pipe_prt_msg) -
|
||||
+ sizeof(unsigned char));
|
||||
+ complete(&input_dev->wait_event);
|
||||
+ break;
|
||||
+
|
||||
+ case SYNTH_HID_INITIAL_DEVICE_INFO:
|
||||
+ WARN_ON(pipe_msg->size < sizeof(struct hv_input_dev_info));
|
||||
+
|
||||
+ /*
|
||||
+ * Parse out the device info into device attr,
|
||||
+ * hid desc and report desc
|
||||
+ */
|
||||
+ mousevsc_on_receive_device_info(input_dev,
|
||||
+ (struct synthhid_device_info *)pipe_msg->data);
|
||||
+ break;
|
||||
+ case SYNTH_HID_INPUT_REPORT:
|
||||
+ input_report =
|
||||
+ (struct synthhid_input_report *)pipe_msg->data;
|
||||
+ if (!input_dev->init_complete)
|
||||
+ break;
|
||||
+ hid_input_report(input_dev->hid_device,
|
||||
+ HID_INPUT_REPORT, input_report->buffer,
|
||||
+ input_report->header.size, 1);
|
||||
+ break;
|
||||
+ default:
|
||||
+ pr_err("unsupported hid msg type - type %d len %d",
|
||||
+ hid_msg->header.type, hid_msg->header.size);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+}
|
||||
+
|
||||
+static void mousevsc_on_channel_callback(void *context)
|
||||
+{
|
||||
+ const int packet_size = 0x100;
|
||||
+ int ret;
|
||||
+ struct hv_device *device = context;
|
||||
+ u32 bytes_recvd;
|
||||
+ u64 req_id;
|
||||
+ struct vmpacket_descriptor *desc;
|
||||
+ unsigned char *buffer;
|
||||
+ int bufferlen = packet_size;
|
||||
+
|
||||
+ buffer = kmalloc(bufferlen, GFP_ATOMIC);
|
||||
+ if (!buffer)
|
||||
+ return;
|
||||
+
|
||||
+ do {
|
||||
+ ret = vmbus_recvpacket_raw(device->channel, buffer,
|
||||
+ bufferlen, &bytes_recvd, &req_id);
|
||||
+
|
||||
+ switch (ret) {
|
||||
+ case 0:
|
||||
+ if (bytes_recvd <= 0) {
|
||||
+ kfree(buffer);
|
||||
+ return;
|
||||
+ }
|
||||
+ desc = (struct vmpacket_descriptor *)buffer;
|
||||
+
|
||||
+ switch (desc->type) {
|
||||
+ case VM_PKT_COMP:
|
||||
+ break;
|
||||
+
|
||||
+ case VM_PKT_DATA_INBAND:
|
||||
+ mousevsc_on_receive(device, desc);
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ pr_err("unhandled packet type %d, tid %llx len %d\n",
|
||||
+ desc->type, req_id, bytes_recvd);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ break;
|
||||
+
|
||||
+ case -ENOBUFS:
|
||||
+ kfree(buffer);
|
||||
+ /* Handle large packet */
|
||||
+ bufferlen = bytes_recvd;
|
||||
+ buffer = kmalloc(bytes_recvd, GFP_ATOMIC);
|
||||
+
|
||||
+ if (!buffer)
|
||||
+ return;
|
||||
+
|
||||
+ break;
|
||||
+ }
|
||||
+ } while (1);
|
||||
+
|
||||
+}
|
||||
+
|
||||
+static int mousevsc_connect_to_vsp(struct hv_device *device)
|
||||
+{
|
||||
+ int ret = 0;
|
||||
+ int t;
|
||||
+ struct mousevsc_dev *input_dev = hv_get_drvdata(device);
|
||||
+ struct mousevsc_prt_msg *request;
|
||||
+ struct mousevsc_prt_msg *response;
|
||||
+
|
||||
+ request = &input_dev->protocol_req;
|
||||
+ memset(request, 0, sizeof(struct mousevsc_prt_msg));
|
||||
+
|
||||
+ request->type = PIPE_MESSAGE_DATA;
|
||||
+ request->size = sizeof(struct synthhid_protocol_request);
|
||||
+ request->request.header.type = SYNTH_HID_PROTOCOL_REQUEST;
|
||||
+ request->request.header.size = sizeof(unsigned int);
|
||||
+ request->request.version_requested.version = SYNTHHID_INPUT_VERSION;
|
||||
+
|
||||
+ ret = vmbus_sendpacket(device->channel, request,
|
||||
+ sizeof(struct pipe_prt_msg) -
|
||||
+ sizeof(unsigned char) +
|
||||
+ sizeof(struct synthhid_protocol_request),
|
||||
+ (unsigned long)request,
|
||||
+ VM_PKT_DATA_INBAND,
|
||||
+ VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
|
||||
+ if (ret)
|
||||
+ goto cleanup;
|
||||
+
|
||||
+ t = wait_for_completion_timeout(&input_dev->wait_event, 5*HZ);
|
||||
+ if (!t) {
|
||||
+ ret = -ETIMEDOUT;
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
+ response = &input_dev->protocol_resp;
|
||||
+
|
||||
+ if (!response->response.approved) {
|
||||
+ pr_err("synthhid protocol request failed (version %d)\n",
|
||||
+ SYNTHHID_INPUT_VERSION);
|
||||
+ ret = -ENODEV;
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
+ t = wait_for_completion_timeout(&input_dev->wait_event, 5*HZ);
|
||||
+ if (!t) {
|
||||
+ ret = -ETIMEDOUT;
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * We should have gotten the device attr, hid desc and report
|
||||
+ * desc at this point
|
||||
+ */
|
||||
+ ret = input_dev->dev_info_status;
|
||||
+
|
||||
+cleanup:
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int mousevsc_hid_open(struct hid_device *hid)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mousevsc_hid_start(struct hid_device *hid)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void mousevsc_hid_close(struct hid_device *hid)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+static void mousevsc_hid_stop(struct hid_device *hid)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+static struct hid_ll_driver mousevsc_ll_driver = {
|
||||
+ .open = mousevsc_hid_open,
|
||||
+ .close = mousevsc_hid_close,
|
||||
+ .start = mousevsc_hid_start,
|
||||
+ .stop = mousevsc_hid_stop,
|
||||
+};
|
||||
+
|
||||
+static struct hid_driver mousevsc_hid_driver;
|
||||
+
|
||||
+static int mousevsc_probe(struct hv_device *device,
|
||||
+ const struct hv_vmbus_device_id *dev_id)
|
||||
+{
|
||||
+ int ret;
|
||||
+ struct mousevsc_dev *input_dev;
|
||||
+ struct hid_device *hid_dev;
|
||||
+
|
||||
+ input_dev = mousevsc_alloc_device(device);
|
||||
+
|
||||
+ if (!input_dev)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ ret = vmbus_open(device->channel,
|
||||
+ INPUTVSC_SEND_RING_BUFFER_SIZE,
|
||||
+ INPUTVSC_RECV_RING_BUFFER_SIZE,
|
||||
+ NULL,
|
||||
+ 0,
|
||||
+ mousevsc_on_channel_callback,
|
||||
+ device
|
||||
+ );
|
||||
+
|
||||
+ if (ret)
|
||||
+ goto probe_err0;
|
||||
+
|
||||
+ ret = mousevsc_connect_to_vsp(device);
|
||||
+
|
||||
+ if (ret)
|
||||
+ goto probe_err1;
|
||||
+
|
||||
+ /* workaround SA-167 */
|
||||
+ if (input_dev->report_desc[14] == 0x25)
|
||||
+ input_dev->report_desc[14] = 0x29;
|
||||
+
|
||||
+ hid_dev = hid_allocate_device();
|
||||
+ if (IS_ERR(hid_dev)) {
|
||||
+ ret = PTR_ERR(hid_dev);
|
||||
+ goto probe_err1;
|
||||
+ }
|
||||
+
|
||||
+ hid_dev->ll_driver = &mousevsc_ll_driver;
|
||||
+ hid_dev->driver = &mousevsc_hid_driver;
|
||||
+ hid_dev->bus = BUS_VIRTUAL;
|
||||
+ hid_dev->vendor = input_dev->hid_dev_info.vendor;
|
||||
+ hid_dev->product = input_dev->hid_dev_info.product;
|
||||
+ hid_dev->version = input_dev->hid_dev_info.version;
|
||||
+ input_dev->hid_device = hid_dev;
|
||||
+
|
||||
+ sprintf(hid_dev->name, "%s", "Microsoft Vmbus HID-compliant Mouse");
|
||||
+
|
||||
+ ret = hid_parse_report(hid_dev, input_dev->report_desc,
|
||||
+ input_dev->report_desc_size);
|
||||
+
|
||||
+ if (ret) {
|
||||
+ hid_err(hid_dev, "parse failed\n");
|
||||
+ goto probe_err2;
|
||||
+ }
|
||||
+
|
||||
+ ret = hid_hw_start(hid_dev, HID_CONNECT_HIDINPUT | HID_CONNECT_HIDDEV);
|
||||
+
|
||||
+ if (ret) {
|
||||
+ hid_err(hid_dev, "hw start failed\n");
|
||||
+ goto probe_err2;
|
||||
+ }
|
||||
+
|
||||
+ input_dev->connected = true;
|
||||
+ input_dev->init_complete = true;
|
||||
+
|
||||
+ return ret;
|
||||
+
|
||||
+probe_err2:
|
||||
+ hid_destroy_device(hid_dev);
|
||||
+
|
||||
+probe_err1:
|
||||
+ vmbus_close(device->channel);
|
||||
+
|
||||
+probe_err0:
|
||||
+ mousevsc_free_device(input_dev);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int mousevsc_remove(struct hv_device *dev)
|
||||
+{
|
||||
+ struct mousevsc_dev *input_dev = hv_get_drvdata(dev);
|
||||
+
|
||||
+ vmbus_close(dev->channel);
|
||||
+ hid_destroy_device(input_dev->hid_device);
|
||||
+ mousevsc_free_device(input_dev);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct hv_vmbus_device_id id_table[] = {
|
||||
+ /* Mouse guid */
|
||||
+ { VMBUS_DEVICE(0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c,
|
||||
+ 0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A) },
|
||||
+ { },
|
||||
+};
|
||||
+
|
||||
+MODULE_DEVICE_TABLE(vmbus, id_table);
|
||||
+
|
||||
+static struct hv_driver mousevsc_drv = {
|
||||
+ .name = KBUILD_MODNAME,
|
||||
+ .id_table = id_table,
|
||||
+ .probe = mousevsc_probe,
|
||||
+ .remove = mousevsc_remove,
|
||||
+};
|
||||
+
|
||||
+static int __init mousevsc_init(void)
|
||||
+{
|
||||
+ return vmbus_driver_register(&mousevsc_drv);
|
||||
+}
|
||||
+
|
||||
+static void __exit mousevsc_exit(void)
|
||||
+{
|
||||
+ vmbus_driver_unregister(&mousevsc_drv);
|
||||
+}
|
||||
+
|
||||
+MODULE_LICENSE("GPL");
|
||||
+MODULE_VERSION(HV_DRV_VERSION);
|
||||
+module_init(mousevsc_init);
|
||||
+module_exit(mousevsc_exit);
|
||||
--
|
||||
1.7.9.5
|
||||
|
147
debian/patches/features/x86/hyperv/0003-Staging-hv-storvsc-Use-mempools-to-allocate-struct-s.patch
vendored
Normal file
147
debian/patches/features/x86/hyperv/0003-Staging-hv-storvsc-Use-mempools-to-allocate-struct-s.patch
vendored
Normal file
|
@ -0,0 +1,147 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Tue, 8 Nov 2011 09:01:40 -0800
|
||||
Subject: [PATCH 03/77] Staging: hv: storvsc: Use mempools to allocate struct
|
||||
storvsc_cmd_request
|
||||
|
||||
commit 4e03e697c5446146318cdb6344af0060541cbc1c upstream.
|
||||
|
||||
We intend to use the storage driver to manage the root device.
|
||||
To avoid deadlocks, use mempools to allocate struct storvsc_cmd_request.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
---
|
||||
drivers/staging/hv/storvsc_drv.c | 30 +++++++++++++++++++++++++-----
|
||||
1 file changed, 25 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
|
||||
index ae8c33e..6a255e9 100644
|
||||
--- a/drivers/staging/hv/storvsc_drv.c
|
||||
+++ b/drivers/staging/hv/storvsc_drv.c
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/hyperv.h>
|
||||
+#include <linux/mempool.h>
|
||||
#include <scsi/scsi.h>
|
||||
#include <scsi/scsi_cmnd.h>
|
||||
#include <scsi/scsi_host.h>
|
||||
@@ -42,6 +43,7 @@
|
||||
#include <scsi/scsi_dbg.h>
|
||||
|
||||
|
||||
+#define STORVSC_MIN_BUF_NR 64
|
||||
#define STORVSC_RING_BUFFER_SIZE (20*PAGE_SIZE)
|
||||
static int storvsc_ringbuffer_size = STORVSC_RING_BUFFER_SIZE;
|
||||
|
||||
@@ -287,6 +289,7 @@ struct storvsc_device {
|
||||
struct hv_host_device {
|
||||
struct hv_device *dev;
|
||||
struct kmem_cache *request_pool;
|
||||
+ mempool_t *request_mempool;
|
||||
unsigned int port;
|
||||
unsigned char path;
|
||||
unsigned char target;
|
||||
@@ -974,8 +977,10 @@ static int storvsc_remove(struct hv_device *dev)
|
||||
|
||||
storvsc_dev_remove(dev);
|
||||
if (host_dev->request_pool) {
|
||||
+ mempool_destroy(host_dev->request_mempool);
|
||||
kmem_cache_destroy(host_dev->request_pool);
|
||||
host_dev->request_pool = NULL;
|
||||
+ host_dev->request_mempool = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1120,7 +1125,7 @@ static void storvsc_command_completion(struct hv_storvsc_request *request)
|
||||
|
||||
scsi_done_fn(scmnd);
|
||||
|
||||
- kmem_cache_free(host_dev->request_pool, cmd_request);
|
||||
+ mempool_free(cmd_request, host_dev->request_mempool);
|
||||
}
|
||||
|
||||
static bool storvsc_check_scsi_cmd(struct scsi_cmnd *scmnd)
|
||||
@@ -1176,12 +1181,13 @@ static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd,
|
||||
|
||||
request_size = sizeof(struct storvsc_cmd_request);
|
||||
|
||||
- cmd_request = kmem_cache_zalloc(host_dev->request_pool,
|
||||
+ cmd_request = mempool_alloc(host_dev->request_mempool,
|
||||
GFP_ATOMIC);
|
||||
if (!cmd_request) {
|
||||
scmnd->scsi_done = NULL;
|
||||
return SCSI_MLQUEUE_DEVICE_BUSY;
|
||||
}
|
||||
+ memset(cmd_request, 0, sizeof(struct storvsc_cmd_request));
|
||||
|
||||
/* Setup the cmd request */
|
||||
cmd_request->bounce_sgl_count = 0;
|
||||
@@ -1235,8 +1241,8 @@ static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd,
|
||||
if (!cmd_request->bounce_sgl) {
|
||||
scmnd->scsi_done = NULL;
|
||||
scmnd->host_scribble = NULL;
|
||||
- kmem_cache_free(host_dev->request_pool,
|
||||
- cmd_request);
|
||||
+ mempool_free(cmd_request,
|
||||
+ host_dev->request_mempool);
|
||||
|
||||
return SCSI_MLQUEUE_HOST_BUSY;
|
||||
}
|
||||
@@ -1278,7 +1284,7 @@ retry_request:
|
||||
destroy_bounce_buffer(cmd_request->bounce_sgl,
|
||||
cmd_request->bounce_sgl_count);
|
||||
|
||||
- kmem_cache_free(host_dev->request_pool, cmd_request);
|
||||
+ mempool_free(cmd_request, host_dev->request_mempool);
|
||||
|
||||
scmnd->scsi_done = NULL;
|
||||
scmnd->host_scribble = NULL;
|
||||
@@ -1348,6 +1354,7 @@ static int storvsc_probe(struct hv_device *device,
|
||||
const struct hv_vmbus_device_id *dev_id)
|
||||
{
|
||||
int ret;
|
||||
+ int number = STORVSC_MIN_BUF_NR;
|
||||
struct Scsi_Host *host;
|
||||
struct hv_host_device *host_dev;
|
||||
bool dev_is_ide = ((dev_id->driver_data == IDE_GUID) ? true : false);
|
||||
@@ -1376,8 +1383,19 @@ static int storvsc_probe(struct hv_device *device,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
+ host_dev->request_mempool = mempool_create(number, mempool_alloc_slab,
|
||||
+ mempool_free_slab,
|
||||
+ host_dev->request_pool);
|
||||
+
|
||||
+ if (!host_dev->request_mempool) {
|
||||
+ kmem_cache_destroy(host_dev->request_pool);
|
||||
+ scsi_host_put(host);
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
stor_device = kzalloc(sizeof(struct storvsc_device), GFP_KERNEL);
|
||||
if (!stor_device) {
|
||||
+ mempool_destroy(host_dev->request_mempool);
|
||||
kmem_cache_destroy(host_dev->request_pool);
|
||||
scsi_host_put(host);
|
||||
return -ENOMEM;
|
||||
@@ -1392,6 +1410,7 @@ static int storvsc_probe(struct hv_device *device,
|
||||
stor_device->port_number = host->host_no;
|
||||
ret = storvsc_connect_to_vsp(device, storvsc_ringbuffer_size);
|
||||
if (ret) {
|
||||
+ mempool_destroy(host_dev->request_mempool);
|
||||
kmem_cache_destroy(host_dev->request_pool);
|
||||
scsi_host_put(host);
|
||||
kfree(stor_device);
|
||||
@@ -1431,6 +1450,7 @@ static int storvsc_probe(struct hv_device *device,
|
||||
|
||||
err_out:
|
||||
storvsc_dev_remove(device);
|
||||
+ mempool_destroy(host_dev->request_mempool);
|
||||
kmem_cache_destroy(host_dev->request_pool);
|
||||
scsi_host_put(host);
|
||||
return -ENODEV;
|
||||
--
|
||||
1.7.9.5
|
||||
|
104
debian/patches/features/x86/hyperv/0004-Staging-hv-storvsc-Cleanup-error-handling-in-the-pro.patch
vendored
Normal file
104
debian/patches/features/x86/hyperv/0004-Staging-hv-storvsc-Cleanup-error-handling-in-the-pro.patch
vendored
Normal file
|
@ -0,0 +1,104 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Tue, 8 Nov 2011 09:01:41 -0800
|
||||
Subject: [PATCH 04/77] Staging: hv: storvsc: Cleanup error handling in the
|
||||
probe function
|
||||
|
||||
commit 225ce6eab741d51d565f67ce9065c596c6535f25 upstream.
|
||||
|
||||
Cleanup error handling in the probe function.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
---
|
||||
drivers/staging/hv/storvsc_drv.c | 42 ++++++++++++++++++++++----------------
|
||||
1 file changed, 24 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
|
||||
index 6a255e9..a72cc22 100644
|
||||
--- a/drivers/staging/hv/storvsc_drv.c
|
||||
+++ b/drivers/staging/hv/storvsc_drv.c
|
||||
@@ -1388,17 +1388,14 @@ static int storvsc_probe(struct hv_device *device,
|
||||
host_dev->request_pool);
|
||||
|
||||
if (!host_dev->request_mempool) {
|
||||
- kmem_cache_destroy(host_dev->request_pool);
|
||||
- scsi_host_put(host);
|
||||
- return -ENOMEM;
|
||||
+ ret = -ENOMEM;
|
||||
+ goto err_out0;
|
||||
}
|
||||
|
||||
stor_device = kzalloc(sizeof(struct storvsc_device), GFP_KERNEL);
|
||||
if (!stor_device) {
|
||||
- mempool_destroy(host_dev->request_mempool);
|
||||
- kmem_cache_destroy(host_dev->request_pool);
|
||||
- scsi_host_put(host);
|
||||
- return -ENOMEM;
|
||||
+ ret = -ENOMEM;
|
||||
+ goto err_out1;
|
||||
}
|
||||
|
||||
stor_device->destroy = false;
|
||||
@@ -1409,13 +1406,8 @@ static int storvsc_probe(struct hv_device *device,
|
||||
|
||||
stor_device->port_number = host->host_no;
|
||||
ret = storvsc_connect_to_vsp(device, storvsc_ringbuffer_size);
|
||||
- if (ret) {
|
||||
- mempool_destroy(host_dev->request_mempool);
|
||||
- kmem_cache_destroy(host_dev->request_pool);
|
||||
- scsi_host_put(host);
|
||||
- kfree(stor_device);
|
||||
- return ret;
|
||||
- }
|
||||
+ if (ret)
|
||||
+ goto err_out2;
|
||||
|
||||
if (dev_is_ide)
|
||||
storvsc_get_ide_info(device, &target, &path);
|
||||
@@ -1435,7 +1427,7 @@ 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)
|
||||
- goto err_out;
|
||||
+ goto err_out3;
|
||||
|
||||
if (!dev_is_ide) {
|
||||
scsi_scan_host(host);
|
||||
@@ -1444,16 +1436,30 @@ static int storvsc_probe(struct hv_device *device,
|
||||
ret = scsi_add_device(host, 0, target, 0);
|
||||
if (ret) {
|
||||
scsi_remove_host(host);
|
||||
- goto err_out;
|
||||
+ goto err_out3;
|
||||
}
|
||||
return 0;
|
||||
|
||||
-err_out:
|
||||
+err_out3:
|
||||
+ /*
|
||||
+ * Once we have connected with the host, we would need to
|
||||
+ * to invoke storvsc_dev_remove() to rollback this state and
|
||||
+ * this call also frees up the stor_device; hence the jump around
|
||||
+ * err_out2 label.
|
||||
+ */
|
||||
storvsc_dev_remove(device);
|
||||
+ goto err_out1;
|
||||
+
|
||||
+err_out2:
|
||||
+ kfree(stor_device);
|
||||
+
|
||||
+err_out1:
|
||||
mempool_destroy(host_dev->request_mempool);
|
||||
+
|
||||
+err_out0:
|
||||
kmem_cache_destroy(host_dev->request_pool);
|
||||
scsi_host_put(host);
|
||||
- return -ENODEV;
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
/* The one and only one */
|
||||
--
|
||||
1.7.9.5
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Tue, 8 Nov 2011 09:01:42 -0800
|
||||
Subject: [PATCH 05/77] Staging: hv: storvsc: Fixup the error when processing
|
||||
SET_WINDOW command
|
||||
|
||||
commit 59e00e744d2413430ebaa09a5fdb61e9ad02a492 upstream.
|
||||
|
||||
Fixup the error when processing SET_WINDOW command.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
---
|
||||
drivers/staging/hv/storvsc_drv.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
|
||||
index a72cc22..e16c7a3 100644
|
||||
--- a/drivers/staging/hv/storvsc_drv.c
|
||||
+++ b/drivers/staging/hv/storvsc_drv.c
|
||||
@@ -1136,7 +1136,7 @@ static bool storvsc_check_scsi_cmd(struct scsi_cmnd *scmnd)
|
||||
switch (scsi_op) {
|
||||
/* smartd sends this command, which will offline the device */
|
||||
case SET_WINDOW:
|
||||
- scmnd->result = DID_ERROR << 16;
|
||||
+ scmnd->result = ILLEGAL_REQUEST << 16;
|
||||
allowed = false;
|
||||
break;
|
||||
default:
|
||||
--
|
||||
1.7.9.5
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Tue, 8 Nov 2011 09:01:43 -0800
|
||||
Subject: [PATCH 06/77] Staging: hv: storvsc: Fix error handling
|
||||
storvsc_host_reset()
|
||||
|
||||
commit a00e8224c19fa5ba3007da00d850865cbefcaabd upstream.
|
||||
|
||||
Fix error handling storvsc_host_reset(). I would like to thank
|
||||
Long Li <longli@microsoft.com> for reporting this.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Reported-by: Long Li <longli@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
---
|
||||
drivers/staging/hv/storvsc_drv.c | 20 ++++++--------------
|
||||
1 file changed, 6 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
|
||||
index e16c7a3..a145245 100644
|
||||
--- a/drivers/staging/hv/storvsc_drv.c
|
||||
+++ b/drivers/staging/hv/storvsc_drv.c
|
||||
@@ -1019,7 +1019,7 @@ static int storvsc_host_reset(struct hv_device *device)
|
||||
|
||||
stor_device = get_out_stor_device(device);
|
||||
if (!stor_device)
|
||||
- return -ENODEV;
|
||||
+ return FAILED;
|
||||
|
||||
request = &stor_device->reset_request;
|
||||
vstor_packet = &request->vstor_packet;
|
||||
@@ -1036,13 +1036,11 @@ static int storvsc_host_reset(struct hv_device *device)
|
||||
VM_PKT_DATA_INBAND,
|
||||
VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
|
||||
if (ret != 0)
|
||||
- goto cleanup;
|
||||
+ return FAILED;
|
||||
|
||||
t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
|
||||
- if (t == 0) {
|
||||
- ret = -ETIMEDOUT;
|
||||
- goto cleanup;
|
||||
- }
|
||||
+ if (t == 0)
|
||||
+ return TIMEOUT_ERROR;
|
||||
|
||||
|
||||
/*
|
||||
@@ -1050,8 +1048,7 @@ static int storvsc_host_reset(struct hv_device *device)
|
||||
* should have been flushed out and return to us
|
||||
*/
|
||||
|
||||
-cleanup:
|
||||
- return ret;
|
||||
+ return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -1060,16 +1057,11 @@ cleanup:
|
||||
*/
|
||||
static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd)
|
||||
{
|
||||
- int ret;
|
||||
struct hv_host_device *host_dev =
|
||||
(struct hv_host_device *)scmnd->device->host->hostdata;
|
||||
struct hv_device *dev = host_dev->dev;
|
||||
|
||||
- ret = storvsc_host_reset(dev);
|
||||
- if (ret != 0)
|
||||
- return ret;
|
||||
-
|
||||
- return ret;
|
||||
+ return storvsc_host_reset(dev);
|
||||
}
|
||||
|
||||
|
||||
--
|
||||
1.7.9.5
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Tue, 8 Nov 2011 09:01:44 -0800
|
||||
Subject: [PATCH 07/77] Staging: hv: storvsc: Use the accessor function
|
||||
shost_priv()
|
||||
|
||||
commit 7f33f30a67cebbdaa938e34c5144424d2f0ce9cc upstream.
|
||||
|
||||
Use the accessor function shost_priv().
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
---
|
||||
drivers/staging/hv/storvsc_drv.c | 14 +++++---------
|
||||
1 file changed, 5 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
|
||||
index a145245..b21e85f 100644
|
||||
--- a/drivers/staging/hv/storvsc_drv.c
|
||||
+++ b/drivers/staging/hv/storvsc_drv.c
|
||||
@@ -968,8 +968,7 @@ static int storvsc_remove(struct hv_device *dev)
|
||||
{
|
||||
struct storvsc_device *stor_device = hv_get_drvdata(dev);
|
||||
struct Scsi_Host *host = stor_device->host;
|
||||
- struct hv_host_device *host_dev =
|
||||
- (struct hv_host_device *)host->hostdata;
|
||||
+ struct hv_host_device *host_dev = shost_priv(host);
|
||||
|
||||
scsi_remove_host(host);
|
||||
|
||||
@@ -1057,8 +1056,7 @@ static int storvsc_host_reset(struct hv_device *device)
|
||||
*/
|
||||
static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd)
|
||||
{
|
||||
- struct hv_host_device *host_dev =
|
||||
- (struct hv_host_device *)scmnd->device->host->hostdata;
|
||||
+ struct hv_host_device *host_dev = shost_priv(scmnd->device->host);
|
||||
struct hv_device *dev = host_dev->dev;
|
||||
|
||||
return storvsc_host_reset(dev);
|
||||
@@ -1073,8 +1071,7 @@ static void storvsc_command_completion(struct hv_storvsc_request *request)
|
||||
struct storvsc_cmd_request *cmd_request =
|
||||
(struct storvsc_cmd_request *)request->context;
|
||||
struct scsi_cmnd *scmnd = cmd_request->cmd;
|
||||
- struct hv_host_device *host_dev =
|
||||
- (struct hv_host_device *)scmnd->device->host->hostdata;
|
||||
+ struct hv_host_device *host_dev = shost_priv(scmnd->device->host);
|
||||
void (*scsi_done_fn)(struct scsi_cmnd *);
|
||||
struct scsi_sense_hdr sense_hdr;
|
||||
struct vmscsi_request *vm_srb;
|
||||
@@ -1144,8 +1141,7 @@ static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd,
|
||||
void (*done)(struct scsi_cmnd *))
|
||||
{
|
||||
int ret;
|
||||
- struct hv_host_device *host_dev =
|
||||
- (struct hv_host_device *)scmnd->device->host->hostdata;
|
||||
+ struct hv_host_device *host_dev = shost_priv(scmnd->device->host);
|
||||
struct hv_device *dev = host_dev->dev;
|
||||
struct hv_storvsc_request *request;
|
||||
struct storvsc_cmd_request *cmd_request;
|
||||
@@ -1359,7 +1355,7 @@ static int storvsc_probe(struct hv_device *device,
|
||||
if (!host)
|
||||
return -ENOMEM;
|
||||
|
||||
- host_dev = (struct hv_host_device *)host->hostdata;
|
||||
+ host_dev = shost_priv(host);
|
||||
memset(host_dev, 0, sizeof(struct hv_host_device));
|
||||
|
||||
host_dev->port = host->host_no;
|
||||
--
|
||||
1.7.9.5
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Tue, 8 Nov 2011 09:01:45 -0800
|
||||
Subject: [PATCH 08/77] Staging: hv: storvsc: Use the unlocked version
|
||||
queuecommand
|
||||
|
||||
commit bab445e12b45153282fb7d39143516e11987deaa upstream.
|
||||
|
||||
Use the unlocked version queuecommand.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
---
|
||||
drivers/staging/hv/storvsc_drv.c | 19 +++++--------------
|
||||
1 file changed, 5 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
|
||||
index b21e85f..827bc68 100644
|
||||
--- a/drivers/staging/hv/storvsc_drv.c
|
||||
+++ b/drivers/staging/hv/storvsc_drv.c
|
||||
@@ -1137,11 +1137,10 @@ static bool storvsc_check_scsi_cmd(struct scsi_cmnd *scmnd)
|
||||
/*
|
||||
* storvsc_queuecommand - Initiate command processing
|
||||
*/
|
||||
-static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd,
|
||||
- void (*done)(struct scsi_cmnd *))
|
||||
+static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
|
||||
{
|
||||
int ret;
|
||||
- struct hv_host_device *host_dev = shost_priv(scmnd->device->host);
|
||||
+ struct hv_host_device *host_dev = shost_priv(host);
|
||||
struct hv_device *dev = host_dev->dev;
|
||||
struct hv_storvsc_request *request;
|
||||
struct storvsc_cmd_request *cmd_request;
|
||||
@@ -1152,7 +1151,7 @@ static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd,
|
||||
struct vmscsi_request *vm_srb;
|
||||
|
||||
if (storvsc_check_scsi_cmd(scmnd) == false) {
|
||||
- done(scmnd);
|
||||
+ scmnd->scsi_done(scmnd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1165,16 +1164,13 @@ static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd,
|
||||
goto retry_request;
|
||||
}
|
||||
|
||||
- scmnd->scsi_done = done;
|
||||
-
|
||||
request_size = sizeof(struct storvsc_cmd_request);
|
||||
|
||||
cmd_request = mempool_alloc(host_dev->request_mempool,
|
||||
GFP_ATOMIC);
|
||||
- if (!cmd_request) {
|
||||
- scmnd->scsi_done = NULL;
|
||||
+ if (!cmd_request)
|
||||
return SCSI_MLQUEUE_DEVICE_BUSY;
|
||||
- }
|
||||
+
|
||||
memset(cmd_request, 0, sizeof(struct storvsc_cmd_request));
|
||||
|
||||
/* Setup the cmd request */
|
||||
@@ -1227,7 +1223,6 @@ static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd,
|
||||
create_bounce_buffer(sgl, scsi_sg_count(scmnd),
|
||||
scsi_bufflen(scmnd));
|
||||
if (!cmd_request->bounce_sgl) {
|
||||
- scmnd->scsi_done = NULL;
|
||||
scmnd->host_scribble = NULL;
|
||||
mempool_free(cmd_request,
|
||||
host_dev->request_mempool);
|
||||
@@ -1274,7 +1269,6 @@ retry_request:
|
||||
|
||||
mempool_free(cmd_request, host_dev->request_mempool);
|
||||
|
||||
- scmnd->scsi_done = NULL;
|
||||
scmnd->host_scribble = NULL;
|
||||
|
||||
ret = SCSI_MLQUEUE_DEVICE_BUSY;
|
||||
@@ -1283,9 +1277,6 @@ retry_request:
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static DEF_SCSI_QCMD(storvsc_queuecommand)
|
||||
-
|
||||
-
|
||||
/* Scsi driver */
|
||||
static struct scsi_host_template scsi_driver = {
|
||||
.module = THIS_MODULE,
|
||||
--
|
||||
1.7.9.5
|
||||
|
31
debian/patches/features/x86/hyperv/0009-Staging-hv-storvsc-use-the-macro-KBUILD_MODNAME.patch
vendored
Normal file
31
debian/patches/features/x86/hyperv/0009-Staging-hv-storvsc-use-the-macro-KBUILD_MODNAME.patch
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Tue, 8 Nov 2011 09:01:46 -0800
|
||||
Subject: [PATCH 09/77] Staging: hv: storvsc: use the macro KBUILD_MODNAME
|
||||
|
||||
commit fafb0efc303a916f9902cbadddef3ea125720c1b upstream.
|
||||
|
||||
Use the macro KBUILD_MODNAME.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
---
|
||||
drivers/staging/hv/storvsc_drv.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
|
||||
index 827bc68..916f5d0 100644
|
||||
--- a/drivers/staging/hv/storvsc_drv.c
|
||||
+++ b/drivers/staging/hv/storvsc_drv.c
|
||||
@@ -1444,7 +1444,7 @@ err_out0:
|
||||
/* The one and only one */
|
||||
|
||||
static struct hv_driver storvsc_drv = {
|
||||
- .name = "storvsc",
|
||||
+ .name = KBUILD_MODNAME,
|
||||
.id_table = id_table,
|
||||
.probe = storvsc_probe,
|
||||
.remove = storvsc_remove,
|
||||
--
|
||||
1.7.9.5
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Tue, 8 Nov 2011 09:01:47 -0800
|
||||
Subject: [PATCH 10/77] Staging: hv: storvsc: Get rid of an unnecessary
|
||||
forward declaration
|
||||
|
||||
commit a404c1ff5556fe29460c097a34d2abe10ddd6e0a upstream.
|
||||
|
||||
Get rid of an unnecessary forward declaration.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
---
|
||||
drivers/staging/hv/storvsc_drv.c | 2 --
|
||||
1 file changed, 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
|
||||
index 916f5d0..4cdb417 100644
|
||||
--- a/drivers/staging/hv/storvsc_drv.c
|
||||
+++ b/drivers/staging/hv/storvsc_drv.c
|
||||
@@ -236,8 +236,6 @@ struct vstor_packet {
|
||||
#define STORVSC_MAX_CHANNELS 1
|
||||
#define STORVSC_MAX_CMD_LEN 16
|
||||
|
||||
-struct hv_storvsc_request;
|
||||
-
|
||||
/* Matches Windows-end */
|
||||
enum storvsc_request_type {
|
||||
WRITE_TYPE,
|
||||
--
|
||||
1.7.9.5
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Tue, 8 Nov 2011 09:01:48 -0800
|
||||
Subject: [PATCH 11/77] Staging: hv: storvsc: Upgrade the vmstor protocol
|
||||
version
|
||||
|
||||
commit 2b9525f511791758b394643b61754a9688e0707d upstream.
|
||||
|
||||
In preparation for supporting hot add/remove of scsi devices,
|
||||
upgrade the vmstor protocol version.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
---
|
||||
drivers/staging/hv/storvsc_drv.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
|
||||
index 4cdb417..9153641 100644
|
||||
--- a/drivers/staging/hv/storvsc_drv.c
|
||||
+++ b/drivers/staging/hv/storvsc_drv.c
|
||||
@@ -80,7 +80,7 @@ MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)");
|
||||
/* V1 Beta 0.1 */
|
||||
/* V1 RC < 2008/1/31 1.0 */
|
||||
/* V1 RC > 2008/1/31 2.0 */
|
||||
-#define VMSTOR_PROTOCOL_VERSION_CURRENT VMSTOR_PROTOCOL_VERSION(2, 0)
|
||||
+#define VMSTOR_PROTOCOL_VERSION_CURRENT VMSTOR_PROTOCOL_VERSION(4, 2)
|
||||
|
||||
|
||||
|
||||
@@ -106,7 +106,8 @@ enum vstor_packet_operation {
|
||||
VSTOR_OPERATION_END_INITIALIZATION = 8,
|
||||
VSTOR_OPERATION_QUERY_PROTOCOL_VERSION = 9,
|
||||
VSTOR_OPERATION_QUERY_PROPERTIES = 10,
|
||||
- VSTOR_OPERATION_MAXIMUM = 10
|
||||
+ VSTOR_OPERATION_ENUMERATE_BUS = 11,
|
||||
+ VSTOR_OPERATION_MAXIMUM = 11
|
||||
};
|
||||
|
||||
/*
|
||||
--
|
||||
1.7.9.5
|
||||
|
79
debian/patches/features/x86/hyperv/0012-Staging-hv-storvsc-Support-hot-add-of-scsi-disks.patch
vendored
Normal file
79
debian/patches/features/x86/hyperv/0012-Staging-hv-storvsc-Support-hot-add-of-scsi-disks.patch
vendored
Normal file
|
@ -0,0 +1,79 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Tue, 8 Nov 2011 09:01:49 -0800
|
||||
Subject: [PATCH 12/77] Staging: hv: storvsc: Support hot add of scsi disks
|
||||
|
||||
commit 126757998a50659f79a3f1ff23fccfc40ff1bf5c upstream.
|
||||
|
||||
Support hot add of scsi disks.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
---
|
||||
drivers/staging/hv/storvsc_drv.c | 38 ++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 38 insertions(+)
|
||||
|
||||
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
|
||||
index 9153641..7c82d14 100644
|
||||
--- a/drivers/staging/hv/storvsc_drv.c
|
||||
+++ b/drivers/staging/hv/storvsc_drv.c
|
||||
@@ -304,6 +304,30 @@ struct storvsc_cmd_request {
|
||||
struct hv_storvsc_request request;
|
||||
};
|
||||
|
||||
+struct storvsc_scan_work {
|
||||
+ struct work_struct work;
|
||||
+ struct Scsi_Host *host;
|
||||
+ uint lun;
|
||||
+};
|
||||
+
|
||||
+static void storvsc_bus_scan(struct work_struct *work)
|
||||
+{
|
||||
+ struct storvsc_scan_work *wrk;
|
||||
+ int id, order_id;
|
||||
+
|
||||
+ wrk = container_of(work, struct storvsc_scan_work, work);
|
||||
+ for (id = 0; id < wrk->host->max_id; ++id) {
|
||||
+ if (wrk->host->reverse_ordering)
|
||||
+ order_id = wrk->host->max_id - id - 1;
|
||||
+ else
|
||||
+ order_id = id;
|
||||
+
|
||||
+ scsi_scan_target(&wrk->host->shost_gendev, 0,
|
||||
+ order_id, SCAN_WILD_CARD, 1);
|
||||
+ }
|
||||
+ kfree(wrk);
|
||||
+}
|
||||
+
|
||||
static inline struct storvsc_device *get_out_stor_device(
|
||||
struct hv_device *device)
|
||||
{
|
||||
@@ -551,11 +575,25 @@ static void storvsc_on_receive(struct hv_device *device,
|
||||
struct vstor_packet *vstor_packet,
|
||||
struct hv_storvsc_request *request)
|
||||
{
|
||||
+ struct storvsc_scan_work *work;
|
||||
+ struct storvsc_device *stor_device;
|
||||
+
|
||||
switch (vstor_packet->operation) {
|
||||
case VSTOR_OPERATION_COMPLETE_IO:
|
||||
storvsc_on_io_completion(device, vstor_packet, request);
|
||||
break;
|
||||
+
|
||||
case VSTOR_OPERATION_REMOVE_DEVICE:
|
||||
+ case VSTOR_OPERATION_ENUMERATE_BUS:
|
||||
+ stor_device = get_in_stor_device(device);
|
||||
+ work = kmalloc(sizeof(struct storvsc_scan_work), GFP_ATOMIC);
|
||||
+ if (!work)
|
||||
+ return;
|
||||
+
|
||||
+ INIT_WORK(&work->work, storvsc_bus_scan);
|
||||
+ work->host = stor_device->host;
|
||||
+ schedule_work(&work->work);
|
||||
+ break;
|
||||
|
||||
default:
|
||||
break;
|
||||
--
|
||||
1.7.9.5
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Tue, 8 Nov 2011 09:01:50 -0800
|
||||
Subject: [PATCH 13/77] Staging: hv: storvsc: Support hot-removing of scsi
|
||||
devices
|
||||
|
||||
commit b401731985bfa7c02e4e5673a151b29ae7180fce upstream.
|
||||
|
||||
Support hot-removing of scsi devices.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
---
|
||||
drivers/staging/hv/storvsc_drv.c | 45 ++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 45 insertions(+)
|
||||
|
||||
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
|
||||
index 7c82d14..0245143 100644
|
||||
--- a/drivers/staging/hv/storvsc_drv.c
|
||||
+++ b/drivers/staging/hv/storvsc_drv.c
|
||||
@@ -328,6 +328,27 @@ static void storvsc_bus_scan(struct work_struct *work)
|
||||
kfree(wrk);
|
||||
}
|
||||
|
||||
+static void storvsc_remove_lun(struct work_struct *work)
|
||||
+{
|
||||
+ struct storvsc_scan_work *wrk;
|
||||
+ struct scsi_device *sdev;
|
||||
+
|
||||
+ wrk = container_of(work, struct storvsc_scan_work, work);
|
||||
+ if (!scsi_host_get(wrk->host))
|
||||
+ goto done;
|
||||
+
|
||||
+ sdev = scsi_device_lookup(wrk->host, 0, 0, wrk->lun);
|
||||
+
|
||||
+ if (sdev) {
|
||||
+ scsi_remove_device(sdev);
|
||||
+ scsi_device_put(sdev);
|
||||
+ }
|
||||
+ scsi_host_put(wrk->host);
|
||||
+
|
||||
+done:
|
||||
+ kfree(wrk);
|
||||
+}
|
||||
+
|
||||
static inline struct storvsc_device *get_out_stor_device(
|
||||
struct hv_device *device)
|
||||
{
|
||||
@@ -1112,6 +1133,7 @@ static void storvsc_command_completion(struct hv_storvsc_request *request)
|
||||
void (*scsi_done_fn)(struct scsi_cmnd *);
|
||||
struct scsi_sense_hdr sense_hdr;
|
||||
struct vmscsi_request *vm_srb;
|
||||
+ struct storvsc_scan_work *wrk;
|
||||
|
||||
vm_srb = &request->vstor_packet.vm_srb;
|
||||
if (cmd_request->bounce_sgl_count) {
|
||||
@@ -1134,6 +1156,29 @@ static void storvsc_command_completion(struct hv_storvsc_request *request)
|
||||
else
|
||||
scmnd->result = vm_srb->scsi_status;
|
||||
|
||||
+ /*
|
||||
+ * If the LUN is invalid; remove the device.
|
||||
+ */
|
||||
+ if (vm_srb->srb_status == 0x20) {
|
||||
+ struct storvsc_device *stor_dev;
|
||||
+ struct hv_device *dev = host_dev->dev;
|
||||
+ struct Scsi_Host *host;
|
||||
+
|
||||
+ stor_dev = get_in_stor_device(dev);
|
||||
+ host = stor_dev->host;
|
||||
+
|
||||
+ wrk = kmalloc(sizeof(struct storvsc_scan_work),
|
||||
+ GFP_ATOMIC);
|
||||
+ if (!wrk) {
|
||||
+ scmnd->result = DID_TARGET_FAILURE << 16;
|
||||
+ } else {
|
||||
+ wrk->host = host;
|
||||
+ wrk->lun = vm_srb->lun;
|
||||
+ INIT_WORK(&wrk->work, storvsc_remove_lun);
|
||||
+ schedule_work(&wrk->work);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (scmnd->result) {
|
||||
if (scsi_normalize_sense(scmnd->sense_buffer,
|
||||
SCSI_SENSE_BUFFERSIZE, &sense_hdr))
|
||||
--
|
||||
1.7.9.5
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
From: Thomas Meyer <thomas@m3y3r.de>
|
||||
Date: Sat, 12 Nov 2011 13:21:49 +0100
|
||||
Subject: [PATCH 14/77] staging: hv: Use kmemdup rather than duplicating its
|
||||
implementation
|
||||
|
||||
commit 27b7923035f737a7e6384d0084e34706ea068040 upstream.
|
||||
|
||||
Use kmemdup rather than duplicating its implementation
|
||||
|
||||
The semantic patch that makes this change is available
|
||||
in scripts/coccinelle/api/memdup.cocci.
|
||||
|
||||
Signed-off-by: Thomas Meyer <thomas@m3y3r.de>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
---
|
||||
drivers/staging/hv/hv_mouse.c | 4 +---
|
||||
drivers/staging/hv/netvsc.c | 11 +++--------
|
||||
2 files changed, 4 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c
|
||||
index ccd39c7..3689217 100644
|
||||
--- a/drivers/staging/hv/hv_mouse.c
|
||||
+++ b/drivers/staging/hv/hv_mouse.c
|
||||
@@ -205,13 +205,11 @@ static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device,
|
||||
desc = &device_info->hid_descriptor;
|
||||
WARN_ON(desc->bLength == 0);
|
||||
|
||||
- input_device->hid_desc = kzalloc(desc->bLength, GFP_ATOMIC);
|
||||
+ input_device->hid_desc = kmemdup(desc, desc->bLength, GFP_ATOMIC);
|
||||
|
||||
if (!input_device->hid_desc)
|
||||
goto cleanup;
|
||||
|
||||
- memcpy(input_device->hid_desc, desc, desc->bLength);
|
||||
-
|
||||
input_device->report_desc_size = desc->desc[0].wDescriptorLength;
|
||||
if (input_device->report_desc_size == 0)
|
||||
goto cleanup;
|
||||
diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c
|
||||
index b902579..28e69a6 100644
|
||||
--- a/drivers/staging/hv/netvsc.c
|
||||
+++ b/drivers/staging/hv/netvsc.c
|
||||
@@ -230,19 +230,14 @@ static int netvsc_init_recv_buf(struct hv_device *device)
|
||||
net_device->recv_section_cnt = init_packet->msg.
|
||||
v1_msg.send_recv_buf_complete.num_sections;
|
||||
|
||||
- net_device->recv_section = kmalloc(net_device->recv_section_cnt
|
||||
- * sizeof(struct nvsp_1_receive_buffer_section), GFP_KERNEL);
|
||||
+ net_device->recv_section = kmemdup(init_packet->msg.v1_msg.send_recv_buf_complete.sections,
|
||||
+ net_device->recv_section_cnt * sizeof(struct nvsp_1_receive_buffer_section),
|
||||
+ GFP_KERNEL);
|
||||
if (net_device->recv_section == NULL) {
|
||||
ret = -EINVAL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
- memcpy(net_device->recv_section,
|
||||
- init_packet->msg.v1_msg.
|
||||
- send_recv_buf_complete.sections,
|
||||
- net_device->recv_section_cnt *
|
||||
- sizeof(struct nvsp_1_receive_buffer_section));
|
||||
-
|
||||
/*
|
||||
* For 1st release, there should only be 1 section that represents the
|
||||
* entire receive buffer
|
||||
--
|
||||
1.7.9.5
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Mon, 24 Oct 2011 11:28:12 -0700
|
||||
Subject: [PATCH 15/77] Staging: hv: vmbus: Support building the vmbus driver
|
||||
as part of the kernel
|
||||
|
||||
commit 43d4e119f944a41a7694552353635ad9b2cd8b37 upstream.
|
||||
|
||||
Modify the way we initialize the vmbus driver so that all the hyper-v drivers
|
||||
can be linked with the kernel and still ensure that the vmbus driver
|
||||
is fully initialized before the drivers that depend upon the vmbus
|
||||
driver attempt to initialize.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
---
|
||||
drivers/hv/vmbus_drv.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
|
||||
index d2d0a2a..05168eb 100644
|
||||
--- a/drivers/hv/vmbus_drv.c
|
||||
+++ b/drivers/hv/vmbus_drv.c
|
||||
@@ -796,4 +796,4 @@ cleanup:
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(HV_DRV_VERSION);
|
||||
|
||||
-module_init(hv_acpi_init);
|
||||
+subsys_initcall(hv_acpi_init);
|
||||
--
|
||||
1.7.9.5
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
From: Bart Van Assche <bvanassche@acm.org>
|
||||
Date: Fri, 18 Nov 2011 18:40:52 +0100
|
||||
Subject: [PATCH 16/77] hv: Add Kconfig menu entry
|
||||
|
||||
commit 124a6b4c4dae0317a0689a42ed0c68fabeb10c8d upstream.
|
||||
|
||||
Most of the drivers/*/Kconfig files define a menu entry. Define
|
||||
a menu item for hv too such that it becomes uniform with e.g.
|
||||
virtio for at least "make xconfig" and "make menuconfig" users.
|
||||
|
||||
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
|
||||
Cc: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
Cc: James Bottomley <JBottomley@Parallels.com>
|
||||
Cc: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
---
|
||||
drivers/hv/Kconfig | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/hv/Kconfig b/drivers/hv/Kconfig
|
||||
index 9fa09ac..70f5dde 100644
|
||||
--- a/drivers/hv/Kconfig
|
||||
+++ b/drivers/hv/Kconfig
|
||||
@@ -1,3 +1,5 @@
|
||||
+menu "Microsoft Hyper-V guest support"
|
||||
+
|
||||
config HYPERV
|
||||
tristate "Microsoft Hyper-V client drivers"
|
||||
depends on X86 && ACPI && PCI
|
||||
@@ -11,4 +13,4 @@ config HYPERV_UTILS
|
||||
help
|
||||
Select this option to enable the Hyper-V Utilities.
|
||||
|
||||
-
|
||||
+endmenu
|
||||
--
|
||||
1.7.9.5
|
||||
|
656
debian/patches/features/x86/hyperv/0017-Staging-hv-mousevsc-Remove-the-mouse-driver-from-the.patch
vendored
Normal file
656
debian/patches/features/x86/hyperv/0017-Staging-hv-mousevsc-Remove-the-mouse-driver-from-the.patch
vendored
Normal file
|
@ -0,0 +1,656 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Fri, 25 Nov 2011 21:28:28 -0800
|
||||
Subject: [PATCH 17/77] Staging: hv: mousevsc: Remove the mouse driver from
|
||||
the staging tree
|
||||
|
||||
commit 045b1684bc21575793a099490938d197555eb128 upstream.
|
||||
|
||||
The mouse driver for Hyper-V is a HID compliant mouse driver.
|
||||
Now that all relevant review comments have been addressed,
|
||||
Jiri has agreed to merge this mouse driver into 3.3 hid.git.
|
||||
This patch takes care of removing the mouse driver from the
|
||||
staging area. Greg, if you can ack this patch, Jiri will proceed
|
||||
with his merge.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
|
||||
[bwh: Backported to 3.2, dropping the intermediate changes]
|
||||
---
|
||||
drivers/staging/hv/Kconfig | 6 -
|
||||
drivers/staging/hv/Makefile | 1 -
|
||||
drivers/staging/hv/hv_mouse.c | 597 -----------------------------------------
|
||||
3 files changed, 604 deletions(-)
|
||||
delete mode 100644 drivers/staging/hv/hv_mouse.c
|
||||
|
||||
diff --git a/drivers/staging/hv/Kconfig b/drivers/staging/hv/Kconfig
|
||||
index 072185e..6c0dc30 100644
|
||||
--- a/drivers/staging/hv/Kconfig
|
||||
+++ b/drivers/staging/hv/Kconfig
|
||||
@@ -9,9 +9,3 @@ config HYPERV_NET
|
||||
depends on HYPERV && NET
|
||||
help
|
||||
Select this option to enable the Hyper-V virtual network driver.
|
||||
-
|
||||
-config HYPERV_MOUSE
|
||||
- tristate "Microsoft Hyper-V mouse driver"
|
||||
- depends on HYPERV && HID
|
||||
- help
|
||||
- Select this option to enable the Hyper-V mouse driver.
|
||||
diff --git a/drivers/staging/hv/Makefile b/drivers/staging/hv/Makefile
|
||||
index 0f55cee..fbe9a42 100644
|
||||
--- a/drivers/staging/hv/Makefile
|
||||
+++ b/drivers/staging/hv/Makefile
|
||||
@@ -1,6 +1,5 @@
|
||||
obj-$(CONFIG_HYPERV_STORAGE) += hv_storvsc.o
|
||||
obj-$(CONFIG_HYPERV_NET) += hv_netvsc.o
|
||||
-obj-$(CONFIG_HYPERV_MOUSE) += hv_mouse.o
|
||||
|
||||
hv_storvsc-y := storvsc_drv.o
|
||||
hv_netvsc-y := netvsc_drv.o netvsc.o rndis_filter.o
|
||||
diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c
|
||||
deleted file mode 100644
|
||||
index 3689217..0000000
|
||||
--- a/drivers/staging/hv/hv_mouse.c
|
||||
+++ /dev/null
|
||||
@@ -1,597 +0,0 @@
|
||||
-/*
|
||||
- * Copyright (c) 2009, Citrix Systems, Inc.
|
||||
- * Copyright (c) 2010, Microsoft Corporation.
|
||||
- * Copyright (c) 2011, Novell Inc.
|
||||
- *
|
||||
- * 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.
|
||||
- */
|
||||
-#include <linux/init.h>
|
||||
-#include <linux/module.h>
|
||||
-#include <linux/delay.h>
|
||||
-#include <linux/device.h>
|
||||
-#include <linux/workqueue.h>
|
||||
-#include <linux/sched.h>
|
||||
-#include <linux/wait.h>
|
||||
-#include <linux/input.h>
|
||||
-#include <linux/hid.h>
|
||||
-#include <linux/hiddev.h>
|
||||
-#include <linux/hyperv.h>
|
||||
-
|
||||
-
|
||||
-struct hv_input_dev_info {
|
||||
- unsigned int size;
|
||||
- unsigned short vendor;
|
||||
- unsigned short product;
|
||||
- unsigned short version;
|
||||
- unsigned short reserved[11];
|
||||
-};
|
||||
-
|
||||
-/* The maximum size of a synthetic input message. */
|
||||
-#define SYNTHHID_MAX_INPUT_REPORT_SIZE 16
|
||||
-
|
||||
-/*
|
||||
- * Current version
|
||||
- *
|
||||
- * History:
|
||||
- * Beta, RC < 2008/1/22 1,0
|
||||
- * RC > 2008/1/22 2,0
|
||||
- */
|
||||
-#define SYNTHHID_INPUT_VERSION_MAJOR 2
|
||||
-#define SYNTHHID_INPUT_VERSION_MINOR 0
|
||||
-#define SYNTHHID_INPUT_VERSION (SYNTHHID_INPUT_VERSION_MINOR | \
|
||||
- (SYNTHHID_INPUT_VERSION_MAJOR << 16))
|
||||
-
|
||||
-
|
||||
-#pragma pack(push, 1)
|
||||
-/*
|
||||
- * Message types in the synthetic input protocol
|
||||
- */
|
||||
-enum synthhid_msg_type {
|
||||
- SYNTH_HID_PROTOCOL_REQUEST,
|
||||
- SYNTH_HID_PROTOCOL_RESPONSE,
|
||||
- SYNTH_HID_INITIAL_DEVICE_INFO,
|
||||
- SYNTH_HID_INITIAL_DEVICE_INFO_ACK,
|
||||
- SYNTH_HID_INPUT_REPORT,
|
||||
- SYNTH_HID_MAX
|
||||
-};
|
||||
-
|
||||
-/*
|
||||
- * Basic message structures.
|
||||
- */
|
||||
-struct synthhid_msg_hdr {
|
||||
- enum synthhid_msg_type type;
|
||||
- u32 size;
|
||||
-};
|
||||
-
|
||||
-struct synthhid_msg {
|
||||
- struct synthhid_msg_hdr header;
|
||||
- char data[1]; /* Enclosed message */
|
||||
-};
|
||||
-
|
||||
-union synthhid_version {
|
||||
- struct {
|
||||
- u16 minor_version;
|
||||
- u16 major_version;
|
||||
- };
|
||||
- u32 version;
|
||||
-};
|
||||
-
|
||||
-/*
|
||||
- * Protocol messages
|
||||
- */
|
||||
-struct synthhid_protocol_request {
|
||||
- struct synthhid_msg_hdr header;
|
||||
- union synthhid_version version_requested;
|
||||
-};
|
||||
-
|
||||
-struct synthhid_protocol_response {
|
||||
- struct synthhid_msg_hdr header;
|
||||
- union synthhid_version version_requested;
|
||||
- unsigned char approved;
|
||||
-};
|
||||
-
|
||||
-struct synthhid_device_info {
|
||||
- struct synthhid_msg_hdr header;
|
||||
- struct hv_input_dev_info hid_dev_info;
|
||||
- struct hid_descriptor hid_descriptor;
|
||||
-};
|
||||
-
|
||||
-struct synthhid_device_info_ack {
|
||||
- struct synthhid_msg_hdr header;
|
||||
- unsigned char reserved;
|
||||
-};
|
||||
-
|
||||
-struct synthhid_input_report {
|
||||
- struct synthhid_msg_hdr header;
|
||||
- char buffer[1];
|
||||
-};
|
||||
-
|
||||
-#pragma pack(pop)
|
||||
-
|
||||
-#define INPUTVSC_SEND_RING_BUFFER_SIZE (10*PAGE_SIZE)
|
||||
-#define INPUTVSC_RECV_RING_BUFFER_SIZE (10*PAGE_SIZE)
|
||||
-
|
||||
-#define NBITS(x) (((x)/BITS_PER_LONG)+1)
|
||||
-
|
||||
-enum pipe_prot_msg_type {
|
||||
- PIPE_MESSAGE_INVALID,
|
||||
- PIPE_MESSAGE_DATA,
|
||||
- PIPE_MESSAGE_MAXIMUM
|
||||
-};
|
||||
-
|
||||
-
|
||||
-struct pipe_prt_msg {
|
||||
- enum pipe_prot_msg_type type;
|
||||
- u32 size;
|
||||
- char data[1];
|
||||
-};
|
||||
-
|
||||
-struct mousevsc_prt_msg {
|
||||
- enum pipe_prot_msg_type type;
|
||||
- u32 size;
|
||||
- union {
|
||||
- struct synthhid_protocol_request request;
|
||||
- struct synthhid_protocol_response response;
|
||||
- struct synthhid_device_info_ack ack;
|
||||
- };
|
||||
-};
|
||||
-
|
||||
-/*
|
||||
- * Represents an mousevsc device
|
||||
- */
|
||||
-struct mousevsc_dev {
|
||||
- struct hv_device *device;
|
||||
- unsigned char init_complete;
|
||||
- struct mousevsc_prt_msg protocol_req;
|
||||
- struct mousevsc_prt_msg protocol_resp;
|
||||
- /* Synchronize the request/response if needed */
|
||||
- struct completion wait_event;
|
||||
- int dev_info_status;
|
||||
-
|
||||
- struct hid_descriptor *hid_desc;
|
||||
- unsigned char *report_desc;
|
||||
- u32 report_desc_size;
|
||||
- struct hv_input_dev_info hid_dev_info;
|
||||
- int connected;
|
||||
- struct hid_device *hid_device;
|
||||
-};
|
||||
-
|
||||
-
|
||||
-static struct mousevsc_dev *alloc_input_device(struct hv_device *device)
|
||||
-{
|
||||
- struct mousevsc_dev *input_dev;
|
||||
-
|
||||
- input_dev = kzalloc(sizeof(struct mousevsc_dev), GFP_KERNEL);
|
||||
-
|
||||
- if (!input_dev)
|
||||
- return NULL;
|
||||
-
|
||||
- input_dev->device = device;
|
||||
- hv_set_drvdata(device, input_dev);
|
||||
- init_completion(&input_dev->wait_event);
|
||||
-
|
||||
- return input_dev;
|
||||
-}
|
||||
-
|
||||
-static void free_input_device(struct mousevsc_dev *device)
|
||||
-{
|
||||
- kfree(device->hid_desc);
|
||||
- kfree(device->report_desc);
|
||||
- hv_set_drvdata(device->device, NULL);
|
||||
- kfree(device);
|
||||
-}
|
||||
-
|
||||
-
|
||||
-static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device,
|
||||
- struct synthhid_device_info *device_info)
|
||||
-{
|
||||
- int ret = 0;
|
||||
- struct hid_descriptor *desc;
|
||||
- struct mousevsc_prt_msg ack;
|
||||
-
|
||||
- /* Assume success for now */
|
||||
- input_device->dev_info_status = 0;
|
||||
-
|
||||
- memcpy(&input_device->hid_dev_info, &device_info->hid_dev_info,
|
||||
- sizeof(struct hv_input_dev_info));
|
||||
-
|
||||
- desc = &device_info->hid_descriptor;
|
||||
- WARN_ON(desc->bLength == 0);
|
||||
-
|
||||
- input_device->hid_desc = kmemdup(desc, desc->bLength, GFP_ATOMIC);
|
||||
-
|
||||
- if (!input_device->hid_desc)
|
||||
- goto cleanup;
|
||||
-
|
||||
- input_device->report_desc_size = desc->desc[0].wDescriptorLength;
|
||||
- if (input_device->report_desc_size == 0)
|
||||
- goto cleanup;
|
||||
- input_device->report_desc = kzalloc(input_device->report_desc_size,
|
||||
- GFP_ATOMIC);
|
||||
-
|
||||
- if (!input_device->report_desc)
|
||||
- goto cleanup;
|
||||
-
|
||||
- memcpy(input_device->report_desc,
|
||||
- ((unsigned char *)desc) + desc->bLength,
|
||||
- desc->desc[0].wDescriptorLength);
|
||||
-
|
||||
- /* Send the ack */
|
||||
- memset(&ack, 0, sizeof(struct mousevsc_prt_msg));
|
||||
-
|
||||
- ack.type = PIPE_MESSAGE_DATA;
|
||||
- ack.size = sizeof(struct synthhid_device_info_ack);
|
||||
-
|
||||
- ack.ack.header.type = SYNTH_HID_INITIAL_DEVICE_INFO_ACK;
|
||||
- ack.ack.header.size = 1;
|
||||
- ack.ack.reserved = 0;
|
||||
-
|
||||
- ret = vmbus_sendpacket(input_device->device->channel,
|
||||
- &ack,
|
||||
- sizeof(struct pipe_prt_msg) - sizeof(unsigned char) +
|
||||
- sizeof(struct synthhid_device_info_ack),
|
||||
- (unsigned long)&ack,
|
||||
- VM_PKT_DATA_INBAND,
|
||||
- VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
|
||||
- if (ret != 0)
|
||||
- goto cleanup;
|
||||
-
|
||||
- complete(&input_device->wait_event);
|
||||
-
|
||||
- return;
|
||||
-
|
||||
-cleanup:
|
||||
- kfree(input_device->hid_desc);
|
||||
- input_device->hid_desc = NULL;
|
||||
-
|
||||
- kfree(input_device->report_desc);
|
||||
- input_device->report_desc = NULL;
|
||||
-
|
||||
- input_device->dev_info_status = -1;
|
||||
- complete(&input_device->wait_event);
|
||||
-}
|
||||
-
|
||||
-static void mousevsc_on_receive(struct hv_device *device,
|
||||
- struct vmpacket_descriptor *packet)
|
||||
-{
|
||||
- struct pipe_prt_msg *pipe_msg;
|
||||
- struct synthhid_msg *hid_msg;
|
||||
- struct mousevsc_dev *input_dev = hv_get_drvdata(device);
|
||||
- struct synthhid_input_report *input_report;
|
||||
-
|
||||
- pipe_msg = (struct pipe_prt_msg *)((unsigned long)packet +
|
||||
- (packet->offset8 << 3));
|
||||
-
|
||||
- if (pipe_msg->type != PIPE_MESSAGE_DATA)
|
||||
- return;
|
||||
-
|
||||
- hid_msg = (struct synthhid_msg *)&pipe_msg->data[0];
|
||||
-
|
||||
- switch (hid_msg->header.type) {
|
||||
- case SYNTH_HID_PROTOCOL_RESPONSE:
|
||||
- memcpy(&input_dev->protocol_resp, pipe_msg,
|
||||
- pipe_msg->size + sizeof(struct pipe_prt_msg) -
|
||||
- sizeof(unsigned char));
|
||||
- complete(&input_dev->wait_event);
|
||||
- break;
|
||||
-
|
||||
- case SYNTH_HID_INITIAL_DEVICE_INFO:
|
||||
- WARN_ON(pipe_msg->size < sizeof(struct hv_input_dev_info));
|
||||
-
|
||||
- /*
|
||||
- * Parse out the device info into device attr,
|
||||
- * hid desc and report desc
|
||||
- */
|
||||
- mousevsc_on_receive_device_info(input_dev,
|
||||
- (struct synthhid_device_info *)&pipe_msg->data[0]);
|
||||
- break;
|
||||
- case SYNTH_HID_INPUT_REPORT:
|
||||
- input_report =
|
||||
- (struct synthhid_input_report *)&pipe_msg->data[0];
|
||||
- if (!input_dev->init_complete)
|
||||
- break;
|
||||
- hid_input_report(input_dev->hid_device,
|
||||
- HID_INPUT_REPORT, input_report->buffer,
|
||||
- input_report->header.size, 1);
|
||||
- break;
|
||||
- default:
|
||||
- pr_err("unsupported hid msg type - type %d len %d",
|
||||
- hid_msg->header.type, hid_msg->header.size);
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
-}
|
||||
-
|
||||
-static void mousevsc_on_channel_callback(void *context)
|
||||
-{
|
||||
- const int packetSize = 0x100;
|
||||
- int ret = 0;
|
||||
- struct hv_device *device = (struct hv_device *)context;
|
||||
-
|
||||
- u32 bytes_recvd;
|
||||
- u64 req_id;
|
||||
- unsigned char packet[0x100];
|
||||
- struct vmpacket_descriptor *desc;
|
||||
- unsigned char *buffer = packet;
|
||||
- int bufferlen = packetSize;
|
||||
-
|
||||
-
|
||||
- do {
|
||||
- ret = vmbus_recvpacket_raw(device->channel, buffer,
|
||||
- bufferlen, &bytes_recvd, &req_id);
|
||||
-
|
||||
- if (ret == 0) {
|
||||
- if (bytes_recvd > 0) {
|
||||
- desc = (struct vmpacket_descriptor *)buffer;
|
||||
-
|
||||
- switch (desc->type) {
|
||||
- case VM_PKT_COMP:
|
||||
- break;
|
||||
-
|
||||
- case VM_PKT_DATA_INBAND:
|
||||
- mousevsc_on_receive(
|
||||
- device, desc);
|
||||
- break;
|
||||
-
|
||||
- default:
|
||||
- pr_err("unhandled packet type %d, tid %llx len %d\n",
|
||||
- desc->type,
|
||||
- req_id,
|
||||
- bytes_recvd);
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- /* reset */
|
||||
- if (bufferlen > packetSize) {
|
||||
- kfree(buffer);
|
||||
-
|
||||
- buffer = packet;
|
||||
- bufferlen = packetSize;
|
||||
- }
|
||||
- } else {
|
||||
- if (bufferlen > packetSize) {
|
||||
- kfree(buffer);
|
||||
-
|
||||
- buffer = packet;
|
||||
- bufferlen = packetSize;
|
||||
- }
|
||||
- break;
|
||||
- }
|
||||
- } else if (ret == -ENOBUFS) {
|
||||
- /* Handle large packet */
|
||||
- bufferlen = bytes_recvd;
|
||||
- buffer = kzalloc(bytes_recvd, GFP_ATOMIC);
|
||||
-
|
||||
- if (buffer == NULL) {
|
||||
- buffer = packet;
|
||||
- bufferlen = packetSize;
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
- } while (1);
|
||||
-
|
||||
- return;
|
||||
-}
|
||||
-
|
||||
-static int mousevsc_connect_to_vsp(struct hv_device *device)
|
||||
-{
|
||||
- int ret = 0;
|
||||
- int t;
|
||||
- struct mousevsc_dev *input_dev = hv_get_drvdata(device);
|
||||
- struct mousevsc_prt_msg *request;
|
||||
- struct mousevsc_prt_msg *response;
|
||||
-
|
||||
-
|
||||
- request = &input_dev->protocol_req;
|
||||
-
|
||||
- memset(request, 0, sizeof(struct mousevsc_prt_msg));
|
||||
-
|
||||
- request->type = PIPE_MESSAGE_DATA;
|
||||
- request->size = sizeof(struct synthhid_protocol_request);
|
||||
-
|
||||
- request->request.header.type = SYNTH_HID_PROTOCOL_REQUEST;
|
||||
- request->request.header.size = sizeof(unsigned int);
|
||||
- request->request.version_requested.version = SYNTHHID_INPUT_VERSION;
|
||||
-
|
||||
-
|
||||
- ret = vmbus_sendpacket(device->channel, request,
|
||||
- sizeof(struct pipe_prt_msg) -
|
||||
- sizeof(unsigned char) +
|
||||
- sizeof(struct synthhid_protocol_request),
|
||||
- (unsigned long)request,
|
||||
- VM_PKT_DATA_INBAND,
|
||||
- VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
|
||||
- if (ret != 0)
|
||||
- goto cleanup;
|
||||
-
|
||||
- t = wait_for_completion_timeout(&input_dev->wait_event, 5*HZ);
|
||||
- if (t == 0) {
|
||||
- ret = -ETIMEDOUT;
|
||||
- goto cleanup;
|
||||
- }
|
||||
-
|
||||
- response = &input_dev->protocol_resp;
|
||||
-
|
||||
- if (!response->response.approved) {
|
||||
- pr_err("synthhid protocol request failed (version %d)",
|
||||
- SYNTHHID_INPUT_VERSION);
|
||||
- ret = -ENODEV;
|
||||
- goto cleanup;
|
||||
- }
|
||||
-
|
||||
- t = wait_for_completion_timeout(&input_dev->wait_event, 5*HZ);
|
||||
- if (t == 0) {
|
||||
- ret = -ETIMEDOUT;
|
||||
- goto cleanup;
|
||||
- }
|
||||
-
|
||||
- /*
|
||||
- * We should have gotten the device attr, hid desc and report
|
||||
- * desc at this point
|
||||
- */
|
||||
- if (input_dev->dev_info_status)
|
||||
- ret = -ENOMEM;
|
||||
-
|
||||
-cleanup:
|
||||
-
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
-static int mousevsc_hid_open(struct hid_device *hid)
|
||||
-{
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static void mousevsc_hid_close(struct hid_device *hid)
|
||||
-{
|
||||
-}
|
||||
-
|
||||
-static struct hid_ll_driver mousevsc_ll_driver = {
|
||||
- .open = mousevsc_hid_open,
|
||||
- .close = mousevsc_hid_close,
|
||||
-};
|
||||
-
|
||||
-static struct hid_driver mousevsc_hid_driver;
|
||||
-
|
||||
-static void reportdesc_callback(struct hv_device *dev, void *packet, u32 len)
|
||||
-{
|
||||
- struct hid_device *hid_dev;
|
||||
- struct mousevsc_dev *input_device = hv_get_drvdata(dev);
|
||||
-
|
||||
- hid_dev = hid_allocate_device();
|
||||
- if (IS_ERR(hid_dev))
|
||||
- return;
|
||||
-
|
||||
- hid_dev->ll_driver = &mousevsc_ll_driver;
|
||||
- hid_dev->driver = &mousevsc_hid_driver;
|
||||
-
|
||||
- if (hid_parse_report(hid_dev, packet, len))
|
||||
- return;
|
||||
-
|
||||
- hid_dev->bus = BUS_VIRTUAL;
|
||||
- hid_dev->vendor = input_device->hid_dev_info.vendor;
|
||||
- hid_dev->product = input_device->hid_dev_info.product;
|
||||
- hid_dev->version = input_device->hid_dev_info.version;
|
||||
-
|
||||
- sprintf(hid_dev->name, "%s", "Microsoft Vmbus HID-compliant Mouse");
|
||||
-
|
||||
- if (!hidinput_connect(hid_dev, 0)) {
|
||||
- hid_dev->claimed |= HID_CLAIMED_INPUT;
|
||||
-
|
||||
- input_device->connected = 1;
|
||||
-
|
||||
- }
|
||||
-
|
||||
- input_device->hid_device = hid_dev;
|
||||
-}
|
||||
-
|
||||
-static int mousevsc_on_device_add(struct hv_device *device)
|
||||
-{
|
||||
- int ret = 0;
|
||||
- struct mousevsc_dev *input_dev;
|
||||
-
|
||||
- input_dev = alloc_input_device(device);
|
||||
-
|
||||
- if (!input_dev)
|
||||
- return -ENOMEM;
|
||||
-
|
||||
- input_dev->init_complete = false;
|
||||
-
|
||||
- ret = vmbus_open(device->channel,
|
||||
- INPUTVSC_SEND_RING_BUFFER_SIZE,
|
||||
- INPUTVSC_RECV_RING_BUFFER_SIZE,
|
||||
- NULL,
|
||||
- 0,
|
||||
- mousevsc_on_channel_callback,
|
||||
- device
|
||||
- );
|
||||
-
|
||||
- if (ret != 0) {
|
||||
- free_input_device(input_dev);
|
||||
- return ret;
|
||||
- }
|
||||
-
|
||||
-
|
||||
- ret = mousevsc_connect_to_vsp(device);
|
||||
-
|
||||
- if (ret != 0) {
|
||||
- vmbus_close(device->channel);
|
||||
- free_input_device(input_dev);
|
||||
- return ret;
|
||||
- }
|
||||
-
|
||||
-
|
||||
- /* workaround SA-167 */
|
||||
- if (input_dev->report_desc[14] == 0x25)
|
||||
- input_dev->report_desc[14] = 0x29;
|
||||
-
|
||||
- reportdesc_callback(device, input_dev->report_desc,
|
||||
- input_dev->report_desc_size);
|
||||
-
|
||||
- input_dev->init_complete = true;
|
||||
-
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
-static int mousevsc_probe(struct hv_device *dev,
|
||||
- const struct hv_vmbus_device_id *dev_id)
|
||||
-{
|
||||
-
|
||||
- return mousevsc_on_device_add(dev);
|
||||
-
|
||||
-}
|
||||
-
|
||||
-static int mousevsc_remove(struct hv_device *dev)
|
||||
-{
|
||||
- struct mousevsc_dev *input_dev = hv_get_drvdata(dev);
|
||||
-
|
||||
- vmbus_close(dev->channel);
|
||||
-
|
||||
- if (input_dev->connected) {
|
||||
- hidinput_disconnect(input_dev->hid_device);
|
||||
- input_dev->connected = 0;
|
||||
- hid_destroy_device(input_dev->hid_device);
|
||||
- }
|
||||
-
|
||||
- free_input_device(input_dev);
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static const struct hv_vmbus_device_id id_table[] = {
|
||||
- /* Mouse guid */
|
||||
- { VMBUS_DEVICE(0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c,
|
||||
- 0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A) },
|
||||
- { },
|
||||
-};
|
||||
-
|
||||
-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 int __init mousevsc_init(void)
|
||||
-{
|
||||
- return vmbus_driver_register(&mousevsc_drv);
|
||||
-}
|
||||
-
|
||||
-static void __exit mousevsc_exit(void)
|
||||
-{
|
||||
- vmbus_driver_unregister(&mousevsc_drv);
|
||||
-}
|
||||
-
|
||||
-MODULE_LICENSE("GPL");
|
||||
-MODULE_VERSION(HV_DRV_VERSION);
|
||||
-module_init(mousevsc_init);
|
||||
-module_exit(mousevsc_exit);
|
||||
--
|
||||
1.7.9.5
|
||||
|
6789
debian/patches/features/x86/hyperv/0018-staging-hv-move-hv_netvsc-out-of-staging-area.patch
vendored
Normal file
6789
debian/patches/features/x86/hyperv/0018-staging-hv-move-hv_netvsc-out-of-staging-area.patch
vendored
Normal file
File diff suppressed because it is too large
Load Diff
35
debian/patches/features/x86/hyperv/0019-net-hyperv-Fix-long-lines-in-netvsc.c.patch
vendored
Normal file
35
debian/patches/features/x86/hyperv/0019-net-hyperv-Fix-long-lines-in-netvsc.c.patch
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
From: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Date: Wed, 30 Nov 2011 07:19:07 -0800
|
||||
Subject: [PATCH 19/77] net/hyperv: Fix long lines in netvsc.c
|
||||
|
||||
commit c18132005e711c07523d8c6602e5b2266ab9a0f2 upstream.
|
||||
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
---
|
||||
drivers/net/hyperv/netvsc.c | 8 +++++---
|
||||
1 file changed, 5 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
|
||||
index 28e69a6..4a807e4 100644
|
||||
--- a/drivers/net/hyperv/netvsc.c
|
||||
+++ b/drivers/net/hyperv/netvsc.c
|
||||
@@ -230,9 +230,11 @@ static int netvsc_init_recv_buf(struct hv_device *device)
|
||||
net_device->recv_section_cnt = init_packet->msg.
|
||||
v1_msg.send_recv_buf_complete.num_sections;
|
||||
|
||||
- net_device->recv_section = kmemdup(init_packet->msg.v1_msg.send_recv_buf_complete.sections,
|
||||
- net_device->recv_section_cnt * sizeof(struct nvsp_1_receive_buffer_section),
|
||||
- GFP_KERNEL);
|
||||
+ net_device->recv_section = kmemdup(
|
||||
+ init_packet->msg.v1_msg.send_recv_buf_complete.sections,
|
||||
+ net_device->recv_section_cnt *
|
||||
+ sizeof(struct nvsp_1_receive_buffer_section),
|
||||
+ GFP_KERNEL);
|
||||
if (net_device->recv_section == NULL) {
|
||||
ret = -EINVAL;
|
||||
goto cleanup;
|
||||
--
|
||||
1.7.9.5
|
||||
|
163
debian/patches/features/x86/hyperv/0020-net-hyperv-Add-support-for-promiscuous-mode-setting.patch
vendored
Normal file
163
debian/patches/features/x86/hyperv/0020-net-hyperv-Add-support-for-promiscuous-mode-setting.patch
vendored
Normal file
|
@ -0,0 +1,163 @@
|
|||
From: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Date: Wed, 30 Nov 2011 07:19:08 -0800
|
||||
Subject: [PATCH 20/77] net/hyperv: Add support for promiscuous mode setting
|
||||
|
||||
commit d426b2e3d91f8ec3203f8852e7ad0153b5dfdf71 upstream.
|
||||
|
||||
Add code to accept promiscuous mode setting, and pass it to
|
||||
RNDIS filter.
|
||||
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
---
|
||||
drivers/net/hyperv/hyperv_net.h | 24 +++++++++++++++++++
|
||||
drivers/net/hyperv/netvsc_drv.c | 46 ++++++++++++++++++++++++++++++++++---
|
||||
drivers/net/hyperv/rndis_filter.c | 23 +------------------
|
||||
3 files changed, 68 insertions(+), 25 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
|
||||
index ac1ec84..49b131f 100644
|
||||
--- a/drivers/net/hyperv/hyperv_net.h
|
||||
+++ b/drivers/net/hyperv/hyperv_net.h
|
||||
@@ -87,6 +87,27 @@ struct netvsc_device_info {
|
||||
int ring_size;
|
||||
};
|
||||
|
||||
+enum rndis_device_state {
|
||||
+ RNDIS_DEV_UNINITIALIZED = 0,
|
||||
+ RNDIS_DEV_INITIALIZING,
|
||||
+ RNDIS_DEV_INITIALIZED,
|
||||
+ RNDIS_DEV_DATAINITIALIZED,
|
||||
+};
|
||||
+
|
||||
+struct rndis_device {
|
||||
+ struct netvsc_device *net_dev;
|
||||
+
|
||||
+ enum rndis_device_state state;
|
||||
+ bool link_state;
|
||||
+ atomic_t new_req_id;
|
||||
+
|
||||
+ spinlock_t request_lock;
|
||||
+ struct list_head req_list;
|
||||
+
|
||||
+ unsigned char hw_mac_adr[ETH_ALEN];
|
||||
+};
|
||||
+
|
||||
+
|
||||
/* Interface */
|
||||
int netvsc_device_add(struct hv_device *device, void *additional_info);
|
||||
int netvsc_device_remove(struct hv_device *device);
|
||||
@@ -109,6 +130,9 @@ int rndis_filter_receive(struct hv_device *dev,
|
||||
int rndis_filter_send(struct hv_device *dev,
|
||||
struct hv_netvsc_packet *pkt);
|
||||
|
||||
+int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter);
|
||||
+
|
||||
+
|
||||
#define NVSP_INVALID_PROTOCOL_VERSION ((u32)0xFFFFFFFF)
|
||||
|
||||
#define NVSP_PROTOCOL_VERSION_1 2
|
||||
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
|
||||
index 93b0e91..b69c3a4 100644
|
||||
--- a/drivers/net/hyperv/netvsc_drv.c
|
||||
+++ b/drivers/net/hyperv/netvsc_drv.c
|
||||
@@ -56,11 +56,51 @@ static int ring_size = 128;
|
||||
module_param(ring_size, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)");
|
||||
|
||||
-/* no-op so the netdev core doesn't return -EINVAL when modifying the the
|
||||
- * multicast address list in SIOCADDMULTI. hv is setup to get all multicast
|
||||
- * when it calls RndisFilterOnOpen() */
|
||||
+struct set_multicast_work {
|
||||
+ struct work_struct work;
|
||||
+ struct net_device *net;
|
||||
+};
|
||||
+
|
||||
+static void do_set_multicast(struct work_struct *w)
|
||||
+{
|
||||
+ struct set_multicast_work *swk =
|
||||
+ container_of(w, struct set_multicast_work, work);
|
||||
+ struct net_device *net = swk->net;
|
||||
+
|
||||
+ struct net_device_context *ndevctx = netdev_priv(net);
|
||||
+ struct netvsc_device *nvdev;
|
||||
+ struct rndis_device *rdev;
|
||||
+
|
||||
+ nvdev = hv_get_drvdata(ndevctx->device_ctx);
|
||||
+ if (nvdev == NULL)
|
||||
+ return;
|
||||
+
|
||||
+ rdev = nvdev->extension;
|
||||
+ if (rdev == NULL)
|
||||
+ return;
|
||||
+
|
||||
+ if (net->flags & IFF_PROMISC)
|
||||
+ rndis_filter_set_packet_filter(rdev,
|
||||
+ NDIS_PACKET_TYPE_PROMISCUOUS);
|
||||
+ else
|
||||
+ rndis_filter_set_packet_filter(rdev,
|
||||
+ NDIS_PACKET_TYPE_BROADCAST |
|
||||
+ NDIS_PACKET_TYPE_ALL_MULTICAST |
|
||||
+ NDIS_PACKET_TYPE_DIRECTED);
|
||||
+
|
||||
+ kfree(w);
|
||||
+}
|
||||
+
|
||||
static void netvsc_set_multicast_list(struct net_device *net)
|
||||
{
|
||||
+ struct set_multicast_work *swk =
|
||||
+ kmalloc(sizeof(struct set_multicast_work), GFP_ATOMIC);
|
||||
+ if (swk == NULL)
|
||||
+ return;
|
||||
+
|
||||
+ swk->net = net;
|
||||
+ INIT_WORK(&swk->work, do_set_multicast);
|
||||
+ schedule_work(&swk->work);
|
||||
}
|
||||
|
||||
static int netvsc_open(struct net_device *net)
|
||||
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
|
||||
index bafccb3..418e7aa 100644
|
||||
--- a/drivers/net/hyperv/rndis_filter.c
|
||||
+++ b/drivers/net/hyperv/rndis_filter.c
|
||||
@@ -30,26 +30,6 @@
|
||||
#include "hyperv_net.h"
|
||||
|
||||
|
||||
-enum rndis_device_state {
|
||||
- RNDIS_DEV_UNINITIALIZED = 0,
|
||||
- RNDIS_DEV_INITIALIZING,
|
||||
- RNDIS_DEV_INITIALIZED,
|
||||
- RNDIS_DEV_DATAINITIALIZED,
|
||||
-};
|
||||
-
|
||||
-struct rndis_device {
|
||||
- struct netvsc_device *net_dev;
|
||||
-
|
||||
- enum rndis_device_state state;
|
||||
- bool link_state;
|
||||
- atomic_t new_req_id;
|
||||
-
|
||||
- spinlock_t request_lock;
|
||||
- struct list_head req_list;
|
||||
-
|
||||
- unsigned char hw_mac_adr[ETH_ALEN];
|
||||
-};
|
||||
-
|
||||
struct rndis_request {
|
||||
struct list_head list_ent;
|
||||
struct completion wait_event;
|
||||
@@ -522,8 +502,7 @@ static int rndis_filter_query_device_link_status(struct rndis_device *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static int rndis_filter_set_packet_filter(struct rndis_device *dev,
|
||||
- u32 new_filter)
|
||||
+int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter)
|
||||
{
|
||||
struct rndis_request *request;
|
||||
struct rndis_set_request *set;
|
||||
--
|
||||
1.7.9.5
|
||||
|
65
debian/patches/features/x86/hyperv/0021-Staging-hv-storvsc-Disable-clustering.patch
vendored
Normal file
65
debian/patches/features/x86/hyperv/0021-Staging-hv-storvsc-Disable-clustering.patch
vendored
Normal file
|
@ -0,0 +1,65 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Thu, 1 Dec 2011 04:59:16 -0800
|
||||
Subject: [PATCH 21/77] Staging: hv: storvsc: Disable clustering
|
||||
|
||||
commit 039db52de9c5682ee10a3cd69f2d76db40b1dee0 upstream.
|
||||
|
||||
Disable clustering, since the host side on Hyper-V requires that
|
||||
each I/O element not exceed the page size. As part of this
|
||||
cleanup, get rid of the function to merge bvecs, as the primary
|
||||
reason for this function was to avoid having an element exceed
|
||||
the page size.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
---
|
||||
drivers/staging/hv/storvsc_drv.c | 18 +-----------------
|
||||
1 file changed, 1 insertion(+), 17 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
|
||||
index 0245143..9153f98 100644
|
||||
--- a/drivers/staging/hv/storvsc_drv.c
|
||||
+++ b/drivers/staging/hv/storvsc_drv.c
|
||||
@@ -798,13 +798,6 @@ static int storvsc_device_alloc(struct scsi_device *sdevice)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int storvsc_merge_bvec(struct request_queue *q,
|
||||
- struct bvec_merge_data *bmd, struct bio_vec *bvec)
|
||||
-{
|
||||
- /* checking done by caller. */
|
||||
- return bvec->bv_len;
|
||||
-}
|
||||
-
|
||||
static int storvsc_device_configure(struct scsi_device *sdevice)
|
||||
{
|
||||
scsi_adjust_queue_depth(sdevice, MSG_SIMPLE_TAG,
|
||||
@@ -812,8 +805,6 @@ static int storvsc_device_configure(struct scsi_device *sdevice)
|
||||
|
||||
blk_queue_max_segment_size(sdevice->request_queue, PAGE_SIZE);
|
||||
|
||||
- blk_queue_merge_bvec(sdevice->request_queue, storvsc_merge_bvec);
|
||||
-
|
||||
blk_queue_bounce_limit(sdevice->request_queue, BLK_BOUNCE_ANY);
|
||||
|
||||
return 0;
|
||||
@@ -1375,14 +1366,7 @@ static struct scsi_host_template scsi_driver = {
|
||||
/* no use setting to 0 since ll_blk_rw reset it to 1 */
|
||||
/* currently 32 */
|
||||
.sg_tablesize = MAX_MULTIPAGE_BUFFER_COUNT,
|
||||
- /*
|
||||
- * ENABLE_CLUSTERING allows mutiple physically contig bio_vecs to merge
|
||||
- * into 1 sg element. If set, we must limit the max_segment_size to
|
||||
- * PAGE_SIZE, otherwise we may get 1 sg element that represents
|
||||
- * multiple
|
||||
- */
|
||||
- /* physically contig pfns (ie sg[x].length > PAGE_SIZE). */
|
||||
- .use_clustering = ENABLE_CLUSTERING,
|
||||
+ .use_clustering = DISABLE_CLUSTERING,
|
||||
/* Make sure we dont get a sg segment crosses a page boundary */
|
||||
.dma_boundary = PAGE_SIZE-1,
|
||||
};
|
||||
--
|
||||
1.7.9.5
|
||||
|
36
debian/patches/features/x86/hyperv/0022-Staging-hv-storvsc-Cleanup-storvsc_device_alloc.patch
vendored
Normal file
36
debian/patches/features/x86/hyperv/0022-Staging-hv-storvsc-Cleanup-storvsc_device_alloc.patch
vendored
Normal file
|
@ -0,0 +1,36 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Thu, 1 Dec 2011 04:59:17 -0800
|
||||
Subject: [PATCH 22/77] Staging: hv: storvsc: Cleanup storvsc_device_alloc()
|
||||
|
||||
commit 2781866484624fabbe373b95cfd20d44d2c9a69e upstream.
|
||||
|
||||
The code in storvsc_device_alloc() is not needed as this would be
|
||||
done by default. Get rid of it. We still keep the function as we use
|
||||
this hook to allocate per-LUN memory pools in a later patch.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
---
|
||||
drivers/staging/hv/storvsc_drv.c | 5 -----
|
||||
1 file changed, 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
|
||||
index 9153f98..14ecb69 100644
|
||||
--- a/drivers/staging/hv/storvsc_drv.c
|
||||
+++ b/drivers/staging/hv/storvsc_drv.c
|
||||
@@ -790,11 +790,6 @@ static void storvsc_get_ide_info(struct hv_device *dev, int *target, int *path)
|
||||
|
||||
static int storvsc_device_alloc(struct scsi_device *sdevice)
|
||||
{
|
||||
- /*
|
||||
- * This enables luns to be located sparsely. Otherwise, we may not
|
||||
- * discovered them.
|
||||
- */
|
||||
- sdevice->sdev_bflags |= BLIST_SPARSELUN | BLIST_LARGELUN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.9.5
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Thu, 1 Dec 2011 04:59:18 -0800
|
||||
Subject: [PATCH 23/77] Staging: hv: storvsc: Fix a bug in
|
||||
storvsc_command_completion()
|
||||
|
||||
commit a768a76d55c2798bbd86b81f50ef740312d69935 upstream.
|
||||
|
||||
Fix a bug in storvsc_command_completion() that leaks memory when scatter/gather
|
||||
lists are used on the "write" side.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
---
|
||||
drivers/staging/hv/storvsc_drv.c | 5 ++---
|
||||
1 file changed, 2 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
|
||||
index 14ecb69..8dafe52 100644
|
||||
--- a/drivers/staging/hv/storvsc_drv.c
|
||||
+++ b/drivers/staging/hv/storvsc_drv.c
|
||||
@@ -1123,13 +1123,12 @@ static void storvsc_command_completion(struct hv_storvsc_request *request)
|
||||
|
||||
vm_srb = &request->vstor_packet.vm_srb;
|
||||
if (cmd_request->bounce_sgl_count) {
|
||||
- if (vm_srb->data_in == READ_TYPE) {
|
||||
+ if (vm_srb->data_in == READ_TYPE)
|
||||
copy_from_bounce_buffer(scsi_sglist(scmnd),
|
||||
cmd_request->bounce_sgl,
|
||||
scsi_sg_count(scmnd));
|
||||
- destroy_bounce_buffer(cmd_request->bounce_sgl,
|
||||
+ destroy_bounce_buffer(cmd_request->bounce_sgl,
|
||||
cmd_request->bounce_sgl_count);
|
||||
- }
|
||||
}
|
||||
|
||||
/*
|
||||
--
|
||||
1.7.9.5
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Thu, 1 Dec 2011 04:59:19 -0800
|
||||
Subject: [PATCH 24/77] Staging: hv: storvsc: Fix a bug in
|
||||
copy_from_bounce_buffer()
|
||||
|
||||
commit 10c43dd4c4403d35fc6477d547aa3a38b466b310 upstream.
|
||||
|
||||
Fix a bug in copy_from_bounce_buffer().
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
---
|
||||
drivers/staging/hv/storvsc_drv.c | 24 ++++++++++++++++++++++--
|
||||
1 file changed, 22 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
|
||||
index 8dafe52..c22de06 100644
|
||||
--- a/drivers/staging/hv/storvsc_drv.c
|
||||
+++ b/drivers/staging/hv/storvsc_drv.c
|
||||
@@ -880,7 +880,8 @@ cleanup:
|
||||
/* Assume the original sgl has enough room */
|
||||
static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl,
|
||||
struct scatterlist *bounce_sgl,
|
||||
- unsigned int orig_sgl_count)
|
||||
+ unsigned int orig_sgl_count,
|
||||
+ unsigned int bounce_sgl_count)
|
||||
{
|
||||
int i;
|
||||
int j = 0;
|
||||
@@ -921,6 +922,24 @@ static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl,
|
||||
kunmap_atomic((void *)bounce_addr, KM_IRQ0);
|
||||
j++;
|
||||
|
||||
+ /*
|
||||
+ * It is possible that the number of elements
|
||||
+ * in the bounce buffer may not be equal to
|
||||
+ * the number of elements in the original
|
||||
+ * scatter list. Handle this correctly.
|
||||
+ */
|
||||
+
|
||||
+ if (j == bounce_sgl_count) {
|
||||
+ /*
|
||||
+ * We are done; cleanup and return.
|
||||
+ */
|
||||
+ kunmap_atomic((void *)(dest_addr -
|
||||
+ orig_sgl[i].offset),
|
||||
+ KM_IRQ0);
|
||||
+ local_irq_restore(flags);
|
||||
+ return total_copied;
|
||||
+ }
|
||||
+
|
||||
/* if we need to use another bounce buffer */
|
||||
if (destlen || i != orig_sgl_count - 1)
|
||||
bounce_addr =
|
||||
@@ -1126,7 +1145,8 @@ static void storvsc_command_completion(struct hv_storvsc_request *request)
|
||||
if (vm_srb->data_in == READ_TYPE)
|
||||
copy_from_bounce_buffer(scsi_sglist(scmnd),
|
||||
cmd_request->bounce_sgl,
|
||||
- scsi_sg_count(scmnd));
|
||||
+ scsi_sg_count(scmnd),
|
||||
+ cmd_request->bounce_sgl_count);
|
||||
destroy_bounce_buffer(cmd_request->bounce_sgl,
|
||||
cmd_request->bounce_sgl_count);
|
||||
}
|
||||
--
|
||||
1.7.9.5
|
||||
|
264
debian/patches/features/x86/hyperv/0025-Staging-hv-storvsc-Implement-per-device-memory-pools.patch
vendored
Normal file
264
debian/patches/features/x86/hyperv/0025-Staging-hv-storvsc-Implement-per-device-memory-pools.patch
vendored
Normal file
|
@ -0,0 +1,264 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Thu, 1 Dec 2011 04:59:20 -0800
|
||||
Subject: [PATCH 25/77] Staging: hv: storvsc: Implement per device memory
|
||||
pools
|
||||
|
||||
commit ce3e301c442f7beffd049908a007697753766cf7 upstream.
|
||||
|
||||
The current code implemented a per-HBA memory pool mechanism. For IDE disks
|
||||
managed by this driver, there is a one to one correspondance between the
|
||||
block device and the associated virtual HBA and since currently only IDE devices
|
||||
can be the boot device, this addressed the deadlock issues that were raised during
|
||||
the review process. This patch implements a per-lun memory pool mechanism.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
---
|
||||
drivers/staging/hv/storvsc_drv.c | 106 ++++++++++++++++++++++----------------
|
||||
1 file changed, 62 insertions(+), 44 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
|
||||
index c22de06..18f8771 100644
|
||||
--- a/drivers/staging/hv/storvsc_drv.c
|
||||
+++ b/drivers/staging/hv/storvsc_drv.c
|
||||
@@ -285,10 +285,13 @@ struct storvsc_device {
|
||||
struct hv_storvsc_request reset_request;
|
||||
};
|
||||
|
||||
-struct hv_host_device {
|
||||
- struct hv_device *dev;
|
||||
+struct stor_mem_pools {
|
||||
struct kmem_cache *request_pool;
|
||||
mempool_t *request_mempool;
|
||||
+};
|
||||
+
|
||||
+struct hv_host_device {
|
||||
+ struct hv_device *dev;
|
||||
unsigned int port;
|
||||
unsigned char path;
|
||||
unsigned char target;
|
||||
@@ -790,7 +793,48 @@ static void storvsc_get_ide_info(struct hv_device *dev, int *target, int *path)
|
||||
|
||||
static int storvsc_device_alloc(struct scsi_device *sdevice)
|
||||
{
|
||||
+ struct stor_mem_pools *memp;
|
||||
+ int number = STORVSC_MIN_BUF_NR;
|
||||
+
|
||||
+ memp = kzalloc(sizeof(struct stor_mem_pools), GFP_KERNEL);
|
||||
+ if (!memp)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ memp->request_pool =
|
||||
+ kmem_cache_create(dev_name(&sdevice->sdev_dev),
|
||||
+ sizeof(struct storvsc_cmd_request), 0,
|
||||
+ SLAB_HWCACHE_ALIGN, NULL);
|
||||
+
|
||||
+ if (!memp->request_pool)
|
||||
+ goto err0;
|
||||
+
|
||||
+ memp->request_mempool = mempool_create(number, mempool_alloc_slab,
|
||||
+ mempool_free_slab,
|
||||
+ memp->request_pool);
|
||||
+
|
||||
+ if (!memp->request_mempool)
|
||||
+ goto err1;
|
||||
+
|
||||
+ sdevice->hostdata = memp;
|
||||
+
|
||||
return 0;
|
||||
+
|
||||
+err1:
|
||||
+ kmem_cache_destroy(memp->request_pool);
|
||||
+
|
||||
+err0:
|
||||
+ kfree(memp);
|
||||
+ return -ENOMEM;
|
||||
+}
|
||||
+
|
||||
+static void storvsc_device_destroy(struct scsi_device *sdevice)
|
||||
+{
|
||||
+ struct stor_mem_pools *memp = sdevice->hostdata;
|
||||
+
|
||||
+ mempool_destroy(memp->request_mempool);
|
||||
+ kmem_cache_destroy(memp->request_pool);
|
||||
+ kfree(memp);
|
||||
+ sdevice->hostdata = NULL;
|
||||
}
|
||||
|
||||
static int storvsc_device_configure(struct scsi_device *sdevice)
|
||||
@@ -1031,19 +1075,13 @@ static int storvsc_remove(struct hv_device *dev)
|
||||
{
|
||||
struct storvsc_device *stor_device = hv_get_drvdata(dev);
|
||||
struct Scsi_Host *host = stor_device->host;
|
||||
- struct hv_host_device *host_dev = shost_priv(host);
|
||||
|
||||
scsi_remove_host(host);
|
||||
|
||||
scsi_host_put(host);
|
||||
|
||||
storvsc_dev_remove(dev);
|
||||
- if (host_dev->request_pool) {
|
||||
- mempool_destroy(host_dev->request_mempool);
|
||||
- kmem_cache_destroy(host_dev->request_pool);
|
||||
- host_dev->request_pool = NULL;
|
||||
- host_dev->request_mempool = NULL;
|
||||
- }
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1139,6 +1177,7 @@ static void storvsc_command_completion(struct hv_storvsc_request *request)
|
||||
struct scsi_sense_hdr sense_hdr;
|
||||
struct vmscsi_request *vm_srb;
|
||||
struct storvsc_scan_work *wrk;
|
||||
+ struct stor_mem_pools *memp = scmnd->device->hostdata;
|
||||
|
||||
vm_srb = &request->vstor_packet.vm_srb;
|
||||
if (cmd_request->bounce_sgl_count) {
|
||||
@@ -1201,7 +1240,7 @@ static void storvsc_command_completion(struct hv_storvsc_request *request)
|
||||
|
||||
scsi_done_fn(scmnd);
|
||||
|
||||
- mempool_free(cmd_request, host_dev->request_mempool);
|
||||
+ mempool_free(cmd_request, memp->request_mempool);
|
||||
}
|
||||
|
||||
static bool storvsc_check_scsi_cmd(struct scsi_cmnd *scmnd)
|
||||
@@ -1236,6 +1275,7 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
|
||||
struct scatterlist *sgl;
|
||||
unsigned int sg_count = 0;
|
||||
struct vmscsi_request *vm_srb;
|
||||
+ struct stor_mem_pools *memp = scmnd->device->hostdata;
|
||||
|
||||
if (storvsc_check_scsi_cmd(scmnd) == false) {
|
||||
scmnd->scsi_done(scmnd);
|
||||
@@ -1253,7 +1293,7 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
|
||||
|
||||
request_size = sizeof(struct storvsc_cmd_request);
|
||||
|
||||
- cmd_request = mempool_alloc(host_dev->request_mempool,
|
||||
+ cmd_request = mempool_alloc(memp->request_mempool,
|
||||
GFP_ATOMIC);
|
||||
if (!cmd_request)
|
||||
return SCSI_MLQUEUE_DEVICE_BUSY;
|
||||
@@ -1312,7 +1352,7 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
|
||||
if (!cmd_request->bounce_sgl) {
|
||||
scmnd->host_scribble = NULL;
|
||||
mempool_free(cmd_request,
|
||||
- host_dev->request_mempool);
|
||||
+ memp->request_mempool);
|
||||
|
||||
return SCSI_MLQUEUE_HOST_BUSY;
|
||||
}
|
||||
@@ -1354,7 +1394,7 @@ retry_request:
|
||||
destroy_bounce_buffer(cmd_request->bounce_sgl,
|
||||
cmd_request->bounce_sgl_count);
|
||||
|
||||
- mempool_free(cmd_request, host_dev->request_mempool);
|
||||
+ mempool_free(cmd_request, memp->request_mempool);
|
||||
|
||||
scmnd->host_scribble = NULL;
|
||||
|
||||
@@ -1372,6 +1412,7 @@ static struct scsi_host_template scsi_driver = {
|
||||
.queuecommand = storvsc_queuecommand,
|
||||
.eh_host_reset_handler = storvsc_host_reset_handler,
|
||||
.slave_alloc = storvsc_device_alloc,
|
||||
+ .slave_destroy = storvsc_device_destroy,
|
||||
.slave_configure = storvsc_device_configure,
|
||||
.cmd_per_lun = 1,
|
||||
/* 64 max_queue * 1 target */
|
||||
@@ -1413,7 +1454,6 @@ static int storvsc_probe(struct hv_device *device,
|
||||
const struct hv_vmbus_device_id *dev_id)
|
||||
{
|
||||
int ret;
|
||||
- int number = STORVSC_MIN_BUF_NR;
|
||||
struct Scsi_Host *host;
|
||||
struct hv_host_device *host_dev;
|
||||
bool dev_is_ide = ((dev_id->driver_data == IDE_GUID) ? true : false);
|
||||
@@ -1432,29 +1472,11 @@ static int storvsc_probe(struct hv_device *device,
|
||||
host_dev->port = host->host_no;
|
||||
host_dev->dev = device;
|
||||
|
||||
- host_dev->request_pool =
|
||||
- kmem_cache_create(dev_name(&device->device),
|
||||
- sizeof(struct storvsc_cmd_request), 0,
|
||||
- SLAB_HWCACHE_ALIGN, NULL);
|
||||
-
|
||||
- if (!host_dev->request_pool) {
|
||||
- scsi_host_put(host);
|
||||
- return -ENOMEM;
|
||||
- }
|
||||
-
|
||||
- host_dev->request_mempool = mempool_create(number, mempool_alloc_slab,
|
||||
- mempool_free_slab,
|
||||
- host_dev->request_pool);
|
||||
-
|
||||
- if (!host_dev->request_mempool) {
|
||||
- ret = -ENOMEM;
|
||||
- goto err_out0;
|
||||
- }
|
||||
|
||||
stor_device = kzalloc(sizeof(struct storvsc_device), GFP_KERNEL);
|
||||
if (!stor_device) {
|
||||
ret = -ENOMEM;
|
||||
- goto err_out1;
|
||||
+ goto err_out0;
|
||||
}
|
||||
|
||||
stor_device->destroy = false;
|
||||
@@ -1466,7 +1488,7 @@ static int storvsc_probe(struct hv_device *device,
|
||||
stor_device->port_number = host->host_no;
|
||||
ret = storvsc_connect_to_vsp(device, storvsc_ringbuffer_size);
|
||||
if (ret)
|
||||
- goto err_out2;
|
||||
+ goto err_out1;
|
||||
|
||||
if (dev_is_ide)
|
||||
storvsc_get_ide_info(device, &target, &path);
|
||||
@@ -1486,7 +1508,7 @@ 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)
|
||||
- goto err_out3;
|
||||
+ goto err_out2;
|
||||
|
||||
if (!dev_is_ide) {
|
||||
scsi_scan_host(host);
|
||||
@@ -1495,28 +1517,24 @@ static int storvsc_probe(struct hv_device *device,
|
||||
ret = scsi_add_device(host, 0, target, 0);
|
||||
if (ret) {
|
||||
scsi_remove_host(host);
|
||||
- goto err_out3;
|
||||
+ goto err_out2;
|
||||
}
|
||||
return 0;
|
||||
|
||||
-err_out3:
|
||||
+err_out2:
|
||||
/*
|
||||
* Once we have connected with the host, we would need to
|
||||
* to invoke storvsc_dev_remove() to rollback this state and
|
||||
* this call also frees up the stor_device; hence the jump around
|
||||
- * err_out2 label.
|
||||
+ * err_out1 label.
|
||||
*/
|
||||
storvsc_dev_remove(device);
|
||||
- goto err_out1;
|
||||
-
|
||||
-err_out2:
|
||||
- kfree(stor_device);
|
||||
+ goto err_out0;
|
||||
|
||||
err_out1:
|
||||
- mempool_destroy(host_dev->request_mempool);
|
||||
+ kfree(stor_device);
|
||||
|
||||
err_out0:
|
||||
- kmem_cache_destroy(host_dev->request_pool);
|
||||
scsi_host_put(host);
|
||||
return ret;
|
||||
}
|
||||
--
|
||||
1.7.9.5
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
From: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
Date: Thu, 1 Dec 2011 10:38:42 -0800
|
||||
Subject: [PATCH 26/77] Staging: hv: update TODO file
|
||||
|
||||
commit 0c9d19646249e0124f1d82fb939e5ba76cb1af3c upstream.
|
||||
|
||||
Hank is no longer at Microsoft, so remove his email address as it
|
||||
bounces.
|
||||
|
||||
Cc: KY Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
---
|
||||
drivers/staging/hv/TODO | 3 +--
|
||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/hv/TODO b/drivers/staging/hv/TODO
|
||||
index fd080cb..dea7d92 100644
|
||||
--- a/drivers/staging/hv/TODO
|
||||
+++ b/drivers/staging/hv/TODO
|
||||
@@ -2,5 +2,4 @@ TODO:
|
||||
- audit the scsi driver
|
||||
|
||||
Please send patches for this code to Greg Kroah-Hartman <gregkh@suse.de>,
|
||||
-Hank Janssen <hjanssen@microsoft.com>, Haiyang Zhang <haiyangz@microsoft.com>,
|
||||
-K. Y. Srinivasan <kys@microsoft.com>
|
||||
+Haiyang Zhang <haiyangz@microsoft.com>, and K. Y. Srinivasan <kys@microsoft.com>
|
||||
--
|
||||
1.7.9.5
|
||||
|
34
debian/patches/features/x86/hyperv/0027-HID-hv_mouse-Properly-add-the-hid-device.patch
vendored
Normal file
34
debian/patches/features/x86/hyperv/0027-HID-hv_mouse-Properly-add-the-hid-device.patch
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Wed, 30 Nov 2011 08:52:23 -0800
|
||||
Subject: [PATCH 27/77] HID: hv_mouse: Properly add the hid device
|
||||
|
||||
commit 74c4fb058083b47571a4f76dcfce95085f2d8098 upstream.
|
||||
|
||||
We need to properly add the hid device to correctly initialize the sysfs state.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Reported-by: Fuzhou Chen <fuzhouch@microsoft.com>
|
||||
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
|
||||
---
|
||||
drivers/hid/hid-hyperv.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/drivers/hid/hid-hyperv.c b/drivers/hid/hid-hyperv.c
|
||||
index d503cbb..0c33ae9 100644
|
||||
--- a/drivers/hid/hid-hyperv.c
|
||||
+++ b/drivers/hid/hid-hyperv.c
|
||||
@@ -506,6 +506,10 @@ static int mousevsc_probe(struct hv_device *device,
|
||||
|
||||
sprintf(hid_dev->name, "%s", "Microsoft Vmbus HID-compliant Mouse");
|
||||
|
||||
+ ret = hid_add_device(hid_dev);
|
||||
+ if (ret)
|
||||
+ goto probe_err1;
|
||||
+
|
||||
ret = hid_parse_report(hid_dev, input_dev->report_desc,
|
||||
input_dev->report_desc_size);
|
||||
|
||||
--
|
||||
1.7.9.5
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Wed, 7 Dec 2011 07:15:52 -0800
|
||||
Subject: [PATCH 28/77] Staging: hv: storvsc: Fix a bug in
|
||||
create_bounce_buffer()
|
||||
|
||||
commit 6e8087a4fae41ae1518babbf1ef46f105d702bfd upstream.
|
||||
|
||||
Set the length field of the scatter gather elements correctly when we create
|
||||
the bounce buffer. When we use the bounce buffer for a "write" operation,
|
||||
the act of copying to the bounce buffer, correctly deals with this issue.
|
||||
However, on the "read" side, the current code was not correctly setting
|
||||
the buffer length. Fix this bug. Note that when we copy from the bounce
|
||||
buffer (for the read case), the amount we copy is controlled by the original
|
||||
scatter gather list given to the driver.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Reported-by: Dadok Milan <dadok@kvados.cz>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
---
|
||||
drivers/staging/hv/storvsc_drv.c | 9 ++++++---
|
||||
1 file changed, 6 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
|
||||
index 18f8771..eb853f7 100644
|
||||
--- a/drivers/staging/hv/storvsc_drv.c
|
||||
+++ b/drivers/staging/hv/storvsc_drv.c
|
||||
@@ -893,12 +893,14 @@ static int do_bounce_buffer(struct scatterlist *sgl, unsigned int sg_count)
|
||||
|
||||
static struct scatterlist *create_bounce_buffer(struct scatterlist *sgl,
|
||||
unsigned int sg_count,
|
||||
- unsigned int len)
|
||||
+ unsigned int len,
|
||||
+ int write)
|
||||
{
|
||||
int i;
|
||||
int num_pages;
|
||||
struct scatterlist *bounce_sgl;
|
||||
struct page *page_buf;
|
||||
+ unsigned int buf_len = ((write == WRITE_TYPE) ? 0 : PAGE_SIZE);
|
||||
|
||||
num_pages = ALIGN(len, PAGE_SIZE) >> PAGE_SHIFT;
|
||||
|
||||
@@ -910,7 +912,7 @@ static struct scatterlist *create_bounce_buffer(struct scatterlist *sgl,
|
||||
page_buf = alloc_page(GFP_ATOMIC);
|
||||
if (!page_buf)
|
||||
goto cleanup;
|
||||
- sg_set_page(&bounce_sgl[i], page_buf, 0, 0);
|
||||
+ sg_set_page(&bounce_sgl[i], page_buf, buf_len, 0);
|
||||
}
|
||||
|
||||
return bounce_sgl;
|
||||
@@ -1348,7 +1350,8 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
|
||||
if (do_bounce_buffer(sgl, scsi_sg_count(scmnd)) != -1) {
|
||||
cmd_request->bounce_sgl =
|
||||
create_bounce_buffer(sgl, scsi_sg_count(scmnd),
|
||||
- scsi_bufflen(scmnd));
|
||||
+ scsi_bufflen(scmnd),
|
||||
+ vm_srb->data_in);
|
||||
if (!cmd_request->bounce_sgl) {
|
||||
scmnd->host_scribble = NULL;
|
||||
mempool_free(cmd_request,
|
||||
--
|
||||
1.7.9.5
|
||||
|
131
debian/patches/features/x86/hyperv/0029-net-hyperv-Fix-the-stop-wake-queue-mechanism.patch
vendored
Normal file
131
debian/patches/features/x86/hyperv/0029-net-hyperv-Fix-the-stop-wake-queue-mechanism.patch
vendored
Normal file
|
@ -0,0 +1,131 @@
|
|||
From: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Date: Fri, 2 Dec 2011 11:56:25 -0800
|
||||
Subject: [PATCH 29/77] net/hyperv: Fix the stop/wake queue mechanism
|
||||
|
||||
commit 1d06825b0ede541f63b5577435abd2fc649a9b5e upstream.
|
||||
|
||||
The ring buffer is only used to pass meta data for outbound packets. The
|
||||
actual payload is accessed by DMA from the host. So the stop/wake queue
|
||||
mechanism based on counting and comparing number of pages sent v.s. number
|
||||
of pages in the ring buffer is wrong. Also, there is a race condition in
|
||||
the stop/wake queue calls, which can stop xmit queue forever.
|
||||
|
||||
The new stop/wake queue mechanism is based on the actual bytes used by
|
||||
outbound packets in the ring buffer. The check for number of outstanding
|
||||
sends after stop queue prevents the race condition that can cause wake
|
||||
queue happening earlier than stop queue.
|
||||
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Reported-by: Long Li <longli@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
---
|
||||
drivers/net/hyperv/netvsc.c | 14 +++++++++++---
|
||||
drivers/net/hyperv/netvsc_drv.c | 24 +-----------------------
|
||||
2 files changed, 12 insertions(+), 26 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
|
||||
index 4a807e4..b6ac152 100644
|
||||
--- a/drivers/net/hyperv/netvsc.c
|
||||
+++ b/drivers/net/hyperv/netvsc.c
|
||||
@@ -435,6 +435,9 @@ static void netvsc_send_completion(struct hv_device *device,
|
||||
nvsc_packet->completion.send.send_completion_ctx);
|
||||
|
||||
atomic_dec(&net_device->num_outstanding_sends);
|
||||
+
|
||||
+ if (netif_queue_stopped(ndev))
|
||||
+ netif_wake_queue(ndev);
|
||||
} else {
|
||||
netdev_err(ndev, "Unknown send completion packet type- "
|
||||
"%d received!!\n", nvsp_packet->hdr.msg_type);
|
||||
@@ -485,11 +488,16 @@ int netvsc_send(struct hv_device *device,
|
||||
|
||||
}
|
||||
|
||||
- if (ret != 0)
|
||||
+ if (ret == 0) {
|
||||
+ atomic_inc(&net_device->num_outstanding_sends);
|
||||
+ } else if (ret == -EAGAIN) {
|
||||
+ netif_stop_queue(ndev);
|
||||
+ if (atomic_read(&net_device->num_outstanding_sends) < 1)
|
||||
+ netif_wake_queue(ndev);
|
||||
+ } else {
|
||||
netdev_err(ndev, "Unable to send packet %p ret %d\n",
|
||||
packet, ret);
|
||||
- else
|
||||
- atomic_inc(&net_device->num_outstanding_sends);
|
||||
+ }
|
||||
|
||||
return ret;
|
||||
}
|
||||
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
|
||||
index b69c3a4..7da85eb 100644
|
||||
--- a/drivers/net/hyperv/netvsc_drv.c
|
||||
+++ b/drivers/net/hyperv/netvsc_drv.c
|
||||
@@ -43,15 +43,10 @@
|
||||
struct net_device_context {
|
||||
/* point back to our device context */
|
||||
struct hv_device *device_ctx;
|
||||
- atomic_t avail;
|
||||
struct delayed_work dwork;
|
||||
};
|
||||
|
||||
|
||||
-#define PACKET_PAGES_LOWATER 8
|
||||
-/* Need this many pages to handle worst case fragmented packet */
|
||||
-#define PACKET_PAGES_HIWATER (MAX_SKB_FRAGS + 2)
|
||||
-
|
||||
static int ring_size = 128;
|
||||
module_param(ring_size, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)");
|
||||
@@ -144,18 +139,8 @@ static void netvsc_xmit_completion(void *context)
|
||||
|
||||
kfree(packet);
|
||||
|
||||
- if (skb) {
|
||||
- struct net_device *net = skb->dev;
|
||||
- struct net_device_context *net_device_ctx = netdev_priv(net);
|
||||
- unsigned int num_pages = skb_shinfo(skb)->nr_frags + 2;
|
||||
-
|
||||
+ if (skb)
|
||||
dev_kfree_skb_any(skb);
|
||||
-
|
||||
- atomic_add(num_pages, &net_device_ctx->avail);
|
||||
- if (atomic_read(&net_device_ctx->avail) >=
|
||||
- PACKET_PAGES_HIWATER)
|
||||
- netif_wake_queue(net);
|
||||
- }
|
||||
}
|
||||
|
||||
static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
|
||||
@@ -167,8 +152,6 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
|
||||
|
||||
/* Add 1 for skb->data and additional one for RNDIS */
|
||||
num_pages = skb_shinfo(skb)->nr_frags + 1 + 1;
|
||||
- if (num_pages > atomic_read(&net_device_ctx->avail))
|
||||
- return NETDEV_TX_BUSY;
|
||||
|
||||
/* Allocate a netvsc packet based on # of frags. */
|
||||
packet = kzalloc(sizeof(struct hv_netvsc_packet) +
|
||||
@@ -218,10 +201,6 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
|
||||
if (ret == 0) {
|
||||
net->stats.tx_bytes += skb->len;
|
||||
net->stats.tx_packets++;
|
||||
-
|
||||
- atomic_sub(num_pages, &net_device_ctx->avail);
|
||||
- if (atomic_read(&net_device_ctx->avail) < PACKET_PAGES_LOWATER)
|
||||
- netif_stop_queue(net);
|
||||
} else {
|
||||
/* we are shutting down or bus overloaded, just drop packet */
|
||||
net->stats.tx_dropped++;
|
||||
@@ -391,7 +370,6 @@ static int netvsc_probe(struct hv_device *dev,
|
||||
|
||||
net_device_ctx = netdev_priv(net);
|
||||
net_device_ctx->device_ctx = dev;
|
||||
- atomic_set(&net_device_ctx->avail, ring_size);
|
||||
hv_set_drvdata(dev, net);
|
||||
INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_send_garp);
|
||||
|
||||
--
|
||||
1.7.9.5
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Mon, 12 Dec 2011 09:29:16 -0800
|
||||
Subject: [PATCH 30/77] Drivers: hv: Fix a memory leak
|
||||
|
||||
commit 8b8ee6753154dd6cfe397e0d29fe7f90a8adb50b upstream.
|
||||
|
||||
There was a memory leak in a failure path in vmbus_process_offer().
|
||||
Fix it.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
---
|
||||
drivers/hv/channel_mgmt.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
|
||||
index 12b85ff..b91af50 100644
|
||||
--- a/drivers/hv/channel_mgmt.c
|
||||
+++ b/drivers/hv/channel_mgmt.c
|
||||
@@ -287,6 +287,7 @@ static void vmbus_process_offer(struct work_struct *work)
|
||||
spin_lock_irqsave(&vmbus_connection.channel_lock, flags);
|
||||
list_del(&newchannel->listentry);
|
||||
spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags);
|
||||
+ kfree(newchannel->device_obj);
|
||||
|
||||
free_channel(newchannel);
|
||||
} else {
|
||||
--
|
||||
1.7.9.5
|
||||
|
94
debian/patches/features/x86/hyperv/0031-Drivers-hv-Make-the-vmbus-driver-unloadable.patch
vendored
Normal file
94
debian/patches/features/x86/hyperv/0031-Drivers-hv-Make-the-vmbus-driver-unloadable.patch
vendored
Normal file
|
@ -0,0 +1,94 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Mon, 12 Dec 2011 09:29:17 -0800
|
||||
Subject: [PATCH 31/77] Drivers: hv: Make the vmbus driver unloadable
|
||||
|
||||
commit 93e5bd06a95343c701361fa009cdc5a653d6ec8e upstream.
|
||||
|
||||
It turns out that the vmbus driver can be made unloadable. Make it
|
||||
unloadable.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
---
|
||||
drivers/hv/channel_mgmt.c | 11 +++++++++++
|
||||
drivers/hv/hv.c | 3 +++
|
||||
drivers/hv/hyperv_vmbus.h | 1 +
|
||||
drivers/hv/vmbus_drv.c | 11 +++++++++++
|
||||
4 files changed, 26 insertions(+)
|
||||
|
||||
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
|
||||
index b91af50..36484db 100644
|
||||
--- a/drivers/hv/channel_mgmt.c
|
||||
+++ b/drivers/hv/channel_mgmt.c
|
||||
@@ -223,6 +223,17 @@ static void vmbus_process_rescind_offer(struct work_struct *work)
|
||||
vmbus_device_unregister(channel->device_obj);
|
||||
}
|
||||
|
||||
+void vmbus_free_channels(void)
|
||||
+{
|
||||
+ struct vmbus_channel *channel;
|
||||
+
|
||||
+ list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) {
|
||||
+ vmbus_device_unregister(channel->device_obj);
|
||||
+ kfree(channel->device_obj);
|
||||
+ free_channel(channel);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* vmbus_process_offer - Process the offer by creating a channel/device
|
||||
* associated with this offer
|
||||
diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
|
||||
index 0fb100e..f8a77d0 100644
|
||||
--- a/drivers/hv/hv.c
|
||||
+++ b/drivers/hv/hv.c
|
||||
@@ -237,6 +237,9 @@ void hv_cleanup(void)
|
||||
{
|
||||
union hv_x64_msr_hypercall_contents hypercall_msr;
|
||||
|
||||
+ /* Reset our OS id */
|
||||
+ wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0);
|
||||
+
|
||||
kfree(hv_context.signal_event_buffer);
|
||||
hv_context.signal_event_buffer = NULL;
|
||||
hv_context.signal_event_param = NULL;
|
||||
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
|
||||
index 0aee112..6d7d286 100644
|
||||
--- a/drivers/hv/hyperv_vmbus.h
|
||||
+++ b/drivers/hv/hyperv_vmbus.h
|
||||
@@ -611,6 +611,7 @@ void vmbus_device_unregister(struct hv_device *device_obj);
|
||||
|
||||
struct vmbus_channel *relid2channel(u32 relid);
|
||||
|
||||
+void vmbus_free_channels(void);
|
||||
|
||||
/* Connection interface */
|
||||
|
||||
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
|
||||
index 05168eb..a220e57 100644
|
||||
--- a/drivers/hv/vmbus_drv.c
|
||||
+++ b/drivers/hv/vmbus_drv.c
|
||||
@@ -792,8 +792,19 @@ cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static void __exit vmbus_exit(void)
|
||||
+{
|
||||
+
|
||||
+ free_irq(irq, hv_acpi_dev);
|
||||
+ vmbus_free_channels();
|
||||
+ bus_unregister(&hv_bus);
|
||||
+ hv_cleanup();
|
||||
+ acpi_bus_unregister_driver(&vmbus_acpi_driver);
|
||||
+}
|
||||
+
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(HV_DRV_VERSION);
|
||||
|
||||
subsys_initcall(hv_acpi_init);
|
||||
+module_exit(vmbus_exit);
|
||||
--
|
||||
1.7.9.5
|
||||
|
35
debian/patches/features/x86/hyperv/0032-Drivers-hv-Get-rid-of-an-unnecessary-check-in-hv.c.patch
vendored
Normal file
35
debian/patches/features/x86/hyperv/0032-Drivers-hv-Get-rid-of-an-unnecessary-check-in-hv.c.patch
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Mon, 12 Dec 2011 09:29:18 -0800
|
||||
Subject: [PATCH 32/77] Drivers: hv: Get rid of an unnecessary check in hv.c
|
||||
|
||||
commit 175cad266774d09c57a62c65baa6b4e1edafdf3a upstream.
|
||||
|
||||
In preparation for eventually supporting kexec in Linux VMs on Hyper-V,
|
||||
get rid of an unnecessary check in hv_init().
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
---
|
||||
drivers/hv/hv.c | 5 -----
|
||||
1 file changed, 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
|
||||
index f8a77d0..12aa97f 100644
|
||||
--- a/drivers/hv/hv.c
|
||||
+++ b/drivers/hv/hv.c
|
||||
@@ -164,11 +164,6 @@ int hv_init(void)
|
||||
|
||||
max_leaf = query_hypervisor_info();
|
||||
|
||||
- rdmsrl(HV_X64_MSR_GUEST_OS_ID, hv_context.guestid);
|
||||
-
|
||||
- if (hv_context.guestid != 0)
|
||||
- goto cleanup;
|
||||
-
|
||||
/* Write our OS info */
|
||||
wrmsrl(HV_X64_MSR_GUEST_OS_ID, HV_LINUX_GUEST_ID);
|
||||
hv_context.guestid = HV_LINUX_GUEST_ID;
|
||||
--
|
||||
1.7.9.5
|
||||
|
221
debian/patches/features/x86/hyperv/0033-net-hyperv-Remove-unnecessary-kmap_atomic-in-netvsc-.patch
vendored
Normal file
221
debian/patches/features/x86/hyperv/0033-net-hyperv-Remove-unnecessary-kmap_atomic-in-netvsc-.patch
vendored
Normal file
|
@ -0,0 +1,221 @@
|
|||
From: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Date: Thu, 15 Dec 2011 13:45:15 -0800
|
||||
Subject: [PATCH 33/77] net/hyperv: Remove unnecessary kmap_atomic in netvsc
|
||||
driver
|
||||
|
||||
commit 453263421f88b4a7e508c2e7b639c97e99c5b118 upstream.
|
||||
|
||||
__get_free_pages() doesn't return HI memory, so the memory is always mapped.
|
||||
kmap_atomic() is not necessary here. This patch removes the kmap_atomic()
|
||||
calls and related code for locking and page manipulation.
|
||||
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
---
|
||||
drivers/net/hyperv/hyperv_net.h | 6 ++---
|
||||
drivers/net/hyperv/netvsc.c | 53 +++----------------------------------
|
||||
drivers/net/hyperv/netvsc_drv.c | 22 ++-------------
|
||||
drivers/net/hyperv/rndis_filter.c | 21 ++-------------
|
||||
4 files changed, 10 insertions(+), 92 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
|
||||
index 49b131f..ff1b520 100644
|
||||
--- a/drivers/net/hyperv/hyperv_net.h
|
||||
+++ b/drivers/net/hyperv/hyperv_net.h
|
||||
@@ -39,9 +39,6 @@ struct xferpage_packet {
|
||||
u32 count;
|
||||
};
|
||||
|
||||
-/* The number of pages which are enough to cover jumbo frame buffer. */
|
||||
-#define NETVSC_PACKET_MAXPAGE 4
|
||||
-
|
||||
/*
|
||||
* Represent netvsc packet which contains 1 RNDIS and 1 ethernet frame
|
||||
* within the RNDIS
|
||||
@@ -77,8 +74,9 @@ struct hv_netvsc_packet {
|
||||
|
||||
u32 total_data_buflen;
|
||||
/* Points to the send/receive buffer where the ethernet frame is */
|
||||
+ void *data;
|
||||
u32 page_buf_cnt;
|
||||
- struct hv_page_buffer page_buf[NETVSC_PACKET_MAXPAGE];
|
||||
+ struct hv_page_buffer page_buf[0];
|
||||
};
|
||||
|
||||
struct netvsc_device_info {
|
||||
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
|
||||
index b6ac152..bab627f 100644
|
||||
--- a/drivers/net/hyperv/netvsc.c
|
||||
+++ b/drivers/net/hyperv/netvsc.c
|
||||
@@ -603,12 +603,10 @@ static void netvsc_receive(struct hv_device *device,
|
||||
struct vmtransfer_page_packet_header *vmxferpage_packet;
|
||||
struct nvsp_message *nvsp_packet;
|
||||
struct hv_netvsc_packet *netvsc_packet = NULL;
|
||||
- unsigned long start;
|
||||
- unsigned long end, end_virtual;
|
||||
/* struct netvsc_driver *netvscDriver; */
|
||||
struct xferpage_packet *xferpage_packet = NULL;
|
||||
- int i, j;
|
||||
- int count = 0, bytes_remain = 0;
|
||||
+ int i;
|
||||
+ int count = 0;
|
||||
unsigned long flags;
|
||||
struct net_device *ndev;
|
||||
|
||||
@@ -717,53 +715,10 @@ static void netvsc_receive(struct hv_device *device,
|
||||
netvsc_packet->completion.recv.recv_completion_tid =
|
||||
vmxferpage_packet->d.trans_id;
|
||||
|
||||
+ netvsc_packet->data = (void *)((unsigned long)net_device->
|
||||
+ recv_buf + vmxferpage_packet->ranges[i].byte_offset);
|
||||
netvsc_packet->total_data_buflen =
|
||||
vmxferpage_packet->ranges[i].byte_count;
|
||||
- netvsc_packet->page_buf_cnt = 1;
|
||||
-
|
||||
- netvsc_packet->page_buf[0].len =
|
||||
- vmxferpage_packet->ranges[i].byte_count;
|
||||
-
|
||||
- start = virt_to_phys((void *)((unsigned long)net_device->
|
||||
- recv_buf + vmxferpage_packet->ranges[i].byte_offset));
|
||||
-
|
||||
- netvsc_packet->page_buf[0].pfn = start >> PAGE_SHIFT;
|
||||
- end_virtual = (unsigned long)net_device->recv_buf
|
||||
- + vmxferpage_packet->ranges[i].byte_offset
|
||||
- + vmxferpage_packet->ranges[i].byte_count - 1;
|
||||
- end = virt_to_phys((void *)end_virtual);
|
||||
-
|
||||
- /* Calculate the page relative offset */
|
||||
- netvsc_packet->page_buf[0].offset =
|
||||
- vmxferpage_packet->ranges[i].byte_offset &
|
||||
- (PAGE_SIZE - 1);
|
||||
- if ((end >> PAGE_SHIFT) != (start >> PAGE_SHIFT)) {
|
||||
- /* Handle frame across multiple pages: */
|
||||
- netvsc_packet->page_buf[0].len =
|
||||
- (netvsc_packet->page_buf[0].pfn <<
|
||||
- PAGE_SHIFT)
|
||||
- + PAGE_SIZE - start;
|
||||
- bytes_remain = netvsc_packet->total_data_buflen -
|
||||
- netvsc_packet->page_buf[0].len;
|
||||
- for (j = 1; j < NETVSC_PACKET_MAXPAGE; j++) {
|
||||
- netvsc_packet->page_buf[j].offset = 0;
|
||||
- if (bytes_remain <= PAGE_SIZE) {
|
||||
- netvsc_packet->page_buf[j].len =
|
||||
- bytes_remain;
|
||||
- bytes_remain = 0;
|
||||
- } else {
|
||||
- netvsc_packet->page_buf[j].len =
|
||||
- PAGE_SIZE;
|
||||
- bytes_remain -= PAGE_SIZE;
|
||||
- }
|
||||
- netvsc_packet->page_buf[j].pfn =
|
||||
- virt_to_phys((void *)(end_virtual -
|
||||
- bytes_remain)) >> PAGE_SHIFT;
|
||||
- netvsc_packet->page_buf_cnt++;
|
||||
- if (bytes_remain == 0)
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
|
||||
/* Pass it to the upper layer */
|
||||
rndis_filter_receive(device, netvsc_packet);
|
||||
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
|
||||
index 7da85eb..b7cbd12 100644
|
||||
--- a/drivers/net/hyperv/netvsc_drv.c
|
||||
+++ b/drivers/net/hyperv/netvsc_drv.c
|
||||
@@ -251,9 +251,6 @@ int netvsc_recv_callback(struct hv_device *device_obj,
|
||||
{
|
||||
struct net_device *net = dev_get_drvdata(&device_obj->device);
|
||||
struct sk_buff *skb;
|
||||
- void *data;
|
||||
- int i;
|
||||
- unsigned long flags;
|
||||
struct netvsc_device *net_device;
|
||||
|
||||
net_device = hv_get_drvdata(device_obj);
|
||||
@@ -272,27 +269,12 @@ int netvsc_recv_callback(struct hv_device *device_obj,
|
||||
return 0;
|
||||
}
|
||||
|
||||
- /* for kmap_atomic */
|
||||
- local_irq_save(flags);
|
||||
-
|
||||
/*
|
||||
* Copy to skb. This copy is needed here since the memory pointed by
|
||||
* hv_netvsc_packet cannot be deallocated
|
||||
*/
|
||||
- for (i = 0; i < packet->page_buf_cnt; i++) {
|
||||
- data = kmap_atomic(pfn_to_page(packet->page_buf[i].pfn),
|
||||
- KM_IRQ1);
|
||||
- data = (void *)(unsigned long)data +
|
||||
- packet->page_buf[i].offset;
|
||||
-
|
||||
- memcpy(skb_put(skb, packet->page_buf[i].len), data,
|
||||
- packet->page_buf[i].len);
|
||||
-
|
||||
- kunmap_atomic((void *)((unsigned long)data -
|
||||
- packet->page_buf[i].offset), KM_IRQ1);
|
||||
- }
|
||||
-
|
||||
- local_irq_restore(flags);
|
||||
+ memcpy(skb_put(skb, packet->total_data_buflen), packet->data,
|
||||
+ packet->total_data_buflen);
|
||||
|
||||
skb->protocol = eth_type_trans(skb, net);
|
||||
skb->ip_summed = CHECKSUM_NONE;
|
||||
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
|
||||
index 418e7aa..da181f9 100644
|
||||
--- a/drivers/net/hyperv/rndis_filter.c
|
||||
+++ b/drivers/net/hyperv/rndis_filter.c
|
||||
@@ -309,7 +309,6 @@ static void rndis_filter_receive_data(struct rndis_device *dev,
|
||||
{
|
||||
struct rndis_packet *rndis_pkt;
|
||||
u32 data_offset;
|
||||
- int i;
|
||||
|
||||
rndis_pkt = &msg->msg.pkt;
|
||||
|
||||
@@ -322,17 +321,7 @@ static void rndis_filter_receive_data(struct rndis_device *dev,
|
||||
data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset;
|
||||
|
||||
pkt->total_data_buflen -= data_offset;
|
||||
- pkt->page_buf[0].offset += data_offset;
|
||||
- pkt->page_buf[0].len -= data_offset;
|
||||
-
|
||||
- /* Drop the 0th page, if rndis data go beyond page boundary */
|
||||
- if (pkt->page_buf[0].offset >= PAGE_SIZE) {
|
||||
- pkt->page_buf[1].offset = pkt->page_buf[0].offset - PAGE_SIZE;
|
||||
- pkt->page_buf[1].len -= pkt->page_buf[1].offset;
|
||||
- pkt->page_buf_cnt--;
|
||||
- for (i = 0; i < pkt->page_buf_cnt; i++)
|
||||
- pkt->page_buf[i] = pkt->page_buf[i+1];
|
||||
- }
|
||||
+ pkt->data = (void *)((unsigned long)pkt->data + data_offset);
|
||||
|
||||
pkt->is_data_pkt = true;
|
||||
|
||||
@@ -367,11 +356,7 @@ int rndis_filter_receive(struct hv_device *dev,
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
- rndis_hdr = (struct rndis_message *)kmap_atomic(
|
||||
- pfn_to_page(pkt->page_buf[0].pfn), KM_IRQ0);
|
||||
-
|
||||
- rndis_hdr = (void *)((unsigned long)rndis_hdr +
|
||||
- pkt->page_buf[0].offset);
|
||||
+ rndis_hdr = pkt->data;
|
||||
|
||||
/* Make sure we got a valid rndis message */
|
||||
if ((rndis_hdr->ndis_msg_type != REMOTE_NDIS_PACKET_MSG) &&
|
||||
@@ -387,8 +372,6 @@ int rndis_filter_receive(struct hv_device *dev,
|
||||
sizeof(struct rndis_message) :
|
||||
rndis_hdr->msg_len);
|
||||
|
||||
- kunmap_atomic(rndis_hdr - pkt->page_buf[0].offset, KM_IRQ0);
|
||||
-
|
||||
dump_rndis_message(dev, &rndis_msg);
|
||||
|
||||
switch (rndis_msg.ndis_msg_type) {
|
||||
--
|
||||
1.7.9.5
|
||||
|
284
debian/patches/features/x86/hyperv/0034-net-hyperv-Add-NETVSP-protocol-version-negotiation.patch
vendored
Normal file
284
debian/patches/features/x86/hyperv/0034-net-hyperv-Add-NETVSP-protocol-version-negotiation.patch
vendored
Normal file
|
@ -0,0 +1,284 @@
|
|||
From: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Date: Thu, 15 Dec 2011 13:45:16 -0800
|
||||
Subject: [PATCH 34/77] net/hyperv: Add NETVSP protocol version negotiation
|
||||
|
||||
commit f157e78de5923dfb209355f3005ce1b5d64f7998 upstream.
|
||||
|
||||
Automatically negotiate the highest protocol version mutually recognized by
|
||||
both host and guest.
|
||||
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
---
|
||||
drivers/net/hyperv/hyperv_net.h | 101 ++++++++++++++++++++++++++++++++++++---
|
||||
drivers/net/hyperv/netvsc.c | 82 ++++++++++++++++++++-----------
|
||||
2 files changed, 149 insertions(+), 34 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
|
||||
index ff1b520..2877670 100644
|
||||
--- a/drivers/net/hyperv/hyperv_net.h
|
||||
+++ b/drivers/net/hyperv/hyperv_net.h
|
||||
@@ -134,8 +134,7 @@ int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter);
|
||||
#define NVSP_INVALID_PROTOCOL_VERSION ((u32)0xFFFFFFFF)
|
||||
|
||||
#define NVSP_PROTOCOL_VERSION_1 2
|
||||
-#define NVSP_MIN_PROTOCOL_VERSION NVSP_PROTOCOL_VERSION_1
|
||||
-#define NVSP_MAX_PROTOCOL_VERSION NVSP_PROTOCOL_VERSION_1
|
||||
+#define NVSP_PROTOCOL_VERSION_2 0x30002
|
||||
|
||||
enum {
|
||||
NVSP_MSG_TYPE_NONE = 0,
|
||||
@@ -160,11 +159,36 @@ enum {
|
||||
NVSP_MSG1_TYPE_SEND_RNDIS_PKT,
|
||||
NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE,
|
||||
|
||||
- /*
|
||||
- * This should be set to the number of messages for the version with
|
||||
- * the maximum number of messages.
|
||||
- */
|
||||
- NVSP_NUM_MSG_PER_VERSION = 9,
|
||||
+ /* Version 2 messages */
|
||||
+ NVSP_MSG2_TYPE_SEND_CHIMNEY_DELEGATED_BUF,
|
||||
+ NVSP_MSG2_TYPE_SEND_CHIMNEY_DELEGATED_BUF_COMP,
|
||||
+ NVSP_MSG2_TYPE_REVOKE_CHIMNEY_DELEGATED_BUF,
|
||||
+
|
||||
+ NVSP_MSG2_TYPE_RESUME_CHIMNEY_RX_INDICATION,
|
||||
+
|
||||
+ NVSP_MSG2_TYPE_TERMINATE_CHIMNEY,
|
||||
+ NVSP_MSG2_TYPE_TERMINATE_CHIMNEY_COMP,
|
||||
+
|
||||
+ NVSP_MSG2_TYPE_INDICATE_CHIMNEY_EVENT,
|
||||
+
|
||||
+ NVSP_MSG2_TYPE_SEND_CHIMNEY_PKT,
|
||||
+ NVSP_MSG2_TYPE_SEND_CHIMNEY_PKT_COMP,
|
||||
+
|
||||
+ NVSP_MSG2_TYPE_POST_CHIMNEY_RECV_REQ,
|
||||
+ NVSP_MSG2_TYPE_POST_CHIMNEY_RECV_REQ_COMP,
|
||||
+
|
||||
+ NVSP_MSG2_TYPE_ALLOC_RXBUF,
|
||||
+ NVSP_MSG2_TYPE_ALLOC_RXBUF_COMP,
|
||||
+
|
||||
+ NVSP_MSG2_TYPE_FREE_RXBUF,
|
||||
+
|
||||
+ NVSP_MSG2_TYPE_SEND_VMQ_RNDIS_PKT,
|
||||
+ NVSP_MSG2_TYPE_SEND_VMQ_RNDIS_PKT_COMP,
|
||||
+
|
||||
+ NVSP_MSG2_TYPE_SEND_NDIS_CONFIG,
|
||||
+
|
||||
+ NVSP_MSG2_TYPE_ALLOC_CHIMNEY_HANDLE,
|
||||
+ NVSP_MSG2_TYPE_ALLOC_CHIMNEY_HANDLE_COMP,
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -175,6 +199,7 @@ enum {
|
||||
NVSP_STAT_PROTOCOL_TOO_OLD,
|
||||
NVSP_STAT_INVALID_RNDIS_PKT,
|
||||
NVSP_STAT_BUSY,
|
||||
+ NVSP_STAT_PROTOCOL_UNSUPPORTED,
|
||||
NVSP_STAT_MAX,
|
||||
};
|
||||
|
||||
@@ -359,9 +384,69 @@ union nvsp_1_message_uber {
|
||||
send_rndis_pkt_complete;
|
||||
} __packed;
|
||||
|
||||
+
|
||||
+/*
|
||||
+ * Network VSP protocol version 2 messages:
|
||||
+ */
|
||||
+struct nvsp_2_vsc_capability {
|
||||
+ union {
|
||||
+ u64 data;
|
||||
+ struct {
|
||||
+ u64 vmq:1;
|
||||
+ u64 chimney:1;
|
||||
+ u64 sriov:1;
|
||||
+ u64 ieee8021q:1;
|
||||
+ u64 correlation_id:1;
|
||||
+ };
|
||||
+ };
|
||||
+} __packed;
|
||||
+
|
||||
+struct nvsp_2_send_ndis_config {
|
||||
+ u32 mtu;
|
||||
+ u32 reserved;
|
||||
+ struct nvsp_2_vsc_capability capability;
|
||||
+} __packed;
|
||||
+
|
||||
+/* Allocate receive buffer */
|
||||
+struct nvsp_2_alloc_rxbuf {
|
||||
+ /* Allocation ID to match the allocation request and response */
|
||||
+ u32 alloc_id;
|
||||
+
|
||||
+ /* Length of the VM shared memory receive buffer that needs to
|
||||
+ * be allocated
|
||||
+ */
|
||||
+ u32 len;
|
||||
+} __packed;
|
||||
+
|
||||
+/* Allocate receive buffer complete */
|
||||
+struct nvsp_2_alloc_rxbuf_comp {
|
||||
+ /* The NDIS_STATUS code for buffer allocation */
|
||||
+ u32 status;
|
||||
+
|
||||
+ u32 alloc_id;
|
||||
+
|
||||
+ /* GPADL handle for the allocated receive buffer */
|
||||
+ u32 gpadl_handle;
|
||||
+
|
||||
+ /* Receive buffer ID */
|
||||
+ u64 recv_buf_id;
|
||||
+} __packed;
|
||||
+
|
||||
+struct nvsp_2_free_rxbuf {
|
||||
+ u64 recv_buf_id;
|
||||
+} __packed;
|
||||
+
|
||||
+union nvsp_2_message_uber {
|
||||
+ struct nvsp_2_send_ndis_config send_ndis_config;
|
||||
+ struct nvsp_2_alloc_rxbuf alloc_rxbuf;
|
||||
+ struct nvsp_2_alloc_rxbuf_comp alloc_rxbuf_comp;
|
||||
+ struct nvsp_2_free_rxbuf free_rxbuf;
|
||||
+} __packed;
|
||||
+
|
||||
union nvsp_all_messages {
|
||||
union nvsp_message_init_uber init_msg;
|
||||
union nvsp_1_message_uber v1_msg;
|
||||
+ union nvsp_2_message_uber v2_msg;
|
||||
} __packed;
|
||||
|
||||
/* ALL Messages */
|
||||
@@ -391,6 +476,8 @@ struct nvsp_message {
|
||||
struct netvsc_device {
|
||||
struct hv_device *dev;
|
||||
|
||||
+ u32 nvsp_version;
|
||||
+
|
||||
atomic_t num_outstanding_sends;
|
||||
bool destroy;
|
||||
/*
|
||||
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
|
||||
index bab627f..46828b4 100644
|
||||
--- a/drivers/net/hyperv/netvsc.c
|
||||
+++ b/drivers/net/hyperv/netvsc.c
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/netdevice.h>
|
||||
+#include <linux/if_ether.h>
|
||||
|
||||
#include "hyperv_net.h"
|
||||
|
||||
@@ -260,27 +261,18 @@ exit:
|
||||
}
|
||||
|
||||
|
||||
-static int netvsc_connect_vsp(struct hv_device *device)
|
||||
+/* Negotiate NVSP protocol version */
|
||||
+static int negotiate_nvsp_ver(struct hv_device *device,
|
||||
+ struct netvsc_device *net_device,
|
||||
+ struct nvsp_message *init_packet,
|
||||
+ u32 nvsp_ver)
|
||||
{
|
||||
int ret, t;
|
||||
- struct netvsc_device *net_device;
|
||||
- struct nvsp_message *init_packet;
|
||||
- int ndis_version;
|
||||
- struct net_device *ndev;
|
||||
-
|
||||
- net_device = get_outbound_net_device(device);
|
||||
- if (!net_device)
|
||||
- return -ENODEV;
|
||||
- ndev = net_device->ndev;
|
||||
-
|
||||
- init_packet = &net_device->channel_init_pkt;
|
||||
|
||||
memset(init_packet, 0, sizeof(struct nvsp_message));
|
||||
init_packet->hdr.msg_type = NVSP_MSG_TYPE_INIT;
|
||||
- init_packet->msg.init_msg.init.min_protocol_ver =
|
||||
- NVSP_MIN_PROTOCOL_VERSION;
|
||||
- init_packet->msg.init_msg.init.max_protocol_ver =
|
||||
- NVSP_MAX_PROTOCOL_VERSION;
|
||||
+ init_packet->msg.init_msg.init.min_protocol_ver = nvsp_ver;
|
||||
+ init_packet->msg.init_msg.init.max_protocol_ver = nvsp_ver;
|
||||
|
||||
/* Send the init request */
|
||||
ret = vmbus_sendpacket(device->channel, init_packet,
|
||||
@@ -290,26 +282,62 @@ static int netvsc_connect_vsp(struct hv_device *device)
|
||||
VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
|
||||
|
||||
if (ret != 0)
|
||||
- goto cleanup;
|
||||
+ return ret;
|
||||
|
||||
t = wait_for_completion_timeout(&net_device->channel_init_wait, 5*HZ);
|
||||
|
||||
- if (t == 0) {
|
||||
- ret = -ETIMEDOUT;
|
||||
- goto cleanup;
|
||||
- }
|
||||
+ if (t == 0)
|
||||
+ return -ETIMEDOUT;
|
||||
|
||||
if (init_packet->msg.init_msg.init_complete.status !=
|
||||
- NVSP_STAT_SUCCESS) {
|
||||
- ret = -EINVAL;
|
||||
- goto cleanup;
|
||||
- }
|
||||
+ NVSP_STAT_SUCCESS)
|
||||
+ return -EINVAL;
|
||||
|
||||
- if (init_packet->msg.init_msg.init_complete.
|
||||
- negotiated_protocol_ver != NVSP_PROTOCOL_VERSION_1) {
|
||||
+ if (nvsp_ver != NVSP_PROTOCOL_VERSION_2)
|
||||
+ return 0;
|
||||
+
|
||||
+ /* NVSPv2 only: Send NDIS config */
|
||||
+ memset(init_packet, 0, sizeof(struct nvsp_message));
|
||||
+ init_packet->hdr.msg_type = NVSP_MSG2_TYPE_SEND_NDIS_CONFIG;
|
||||
+ init_packet->msg.v2_msg.send_ndis_config.mtu = ETH_DATA_LEN;
|
||||
+
|
||||
+ ret = vmbus_sendpacket(device->channel, init_packet,
|
||||
+ sizeof(struct nvsp_message),
|
||||
+ (unsigned long)init_packet,
|
||||
+ VM_PKT_DATA_INBAND, 0);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int netvsc_connect_vsp(struct hv_device *device)
|
||||
+{
|
||||
+ int ret;
|
||||
+ struct netvsc_device *net_device;
|
||||
+ struct nvsp_message *init_packet;
|
||||
+ int ndis_version;
|
||||
+ struct net_device *ndev;
|
||||
+
|
||||
+ net_device = get_outbound_net_device(device);
|
||||
+ if (!net_device)
|
||||
+ return -ENODEV;
|
||||
+ ndev = net_device->ndev;
|
||||
+
|
||||
+ init_packet = &net_device->channel_init_pkt;
|
||||
+
|
||||
+ /* Negotiate the latest NVSP protocol supported */
|
||||
+ if (negotiate_nvsp_ver(device, net_device, init_packet,
|
||||
+ NVSP_PROTOCOL_VERSION_2) == 0) {
|
||||
+ net_device->nvsp_version = NVSP_PROTOCOL_VERSION_2;
|
||||
+ } else if (negotiate_nvsp_ver(device, net_device, init_packet,
|
||||
+ NVSP_PROTOCOL_VERSION_1) == 0) {
|
||||
+ net_device->nvsp_version = NVSP_PROTOCOL_VERSION_1;
|
||||
+ } else {
|
||||
ret = -EPROTO;
|
||||
goto cleanup;
|
||||
}
|
||||
+
|
||||
+ pr_debug("Negotiated NVSP version:%x\n", net_device->nvsp_version);
|
||||
+
|
||||
/* Send the ndis version */
|
||||
memset(init_packet, 0, sizeof(struct nvsp_message));
|
||||
|
||||
--
|
||||
1.7.9.5
|
||||
|
213
debian/patches/features/x86/hyperv/0035-net-hyperv-Add-support-for-jumbo-frame-up-to-64KB.patch
vendored
Normal file
213
debian/patches/features/x86/hyperv/0035-net-hyperv-Add-support-for-jumbo-frame-up-to-64KB.patch
vendored
Normal file
|
@ -0,0 +1,213 @@
|
|||
From: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Date: Thu, 15 Dec 2011 13:45:17 -0800
|
||||
Subject: [PATCH 35/77] net/hyperv: Add support for jumbo frame up to 64KB
|
||||
|
||||
commit 4d447c9a6ebc0142d320f075c5bac6d202a79fd4 upstream.
|
||||
|
||||
Allow the user set the MTU up to 65536 for Linux guests running on
|
||||
Hyper-V 2008 R2 or later.
|
||||
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
---
|
||||
drivers/net/hyperv/hyperv_net.h | 8 ++---
|
||||
drivers/net/hyperv/netvsc.c | 6 ++--
|
||||
drivers/net/hyperv/netvsc_drv.c | 70 ++++++++++++++++++++++++++++++++++-----
|
||||
include/linux/hyperv.h | 2 +-
|
||||
4 files changed, 68 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
|
||||
index 2877670..dec5836 100644
|
||||
--- a/drivers/net/hyperv/hyperv_net.h
|
||||
+++ b/drivers/net/hyperv/hyperv_net.h
|
||||
@@ -456,12 +456,9 @@ struct nvsp_message {
|
||||
} __packed;
|
||||
|
||||
|
||||
+#define NETVSC_MTU 65536
|
||||
|
||||
-
|
||||
-/* #define NVSC_MIN_PROTOCOL_VERSION 1 */
|
||||
-/* #define NVSC_MAX_PROTOCOL_VERSION 1 */
|
||||
-
|
||||
-#define NETVSC_RECEIVE_BUFFER_SIZE (1024*1024) /* 1MB */
|
||||
+#define NETVSC_RECEIVE_BUFFER_SIZE (1024*1024*2) /* 2MB */
|
||||
|
||||
#define NETVSC_RECEIVE_BUFFER_ID 0xcafe
|
||||
|
||||
@@ -479,6 +476,7 @@ struct netvsc_device {
|
||||
u32 nvsp_version;
|
||||
|
||||
atomic_t num_outstanding_sends;
|
||||
+ bool start_remove;
|
||||
bool destroy;
|
||||
/*
|
||||
* List of free preallocated hv_netvsc_packet to represent receive
|
||||
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
|
||||
index 46828b4..8965b45 100644
|
||||
--- a/drivers/net/hyperv/netvsc.c
|
||||
+++ b/drivers/net/hyperv/netvsc.c
|
||||
@@ -42,7 +42,7 @@ static struct netvsc_device *alloc_net_device(struct hv_device *device)
|
||||
if (!net_device)
|
||||
return NULL;
|
||||
|
||||
-
|
||||
+ net_device->start_remove = false;
|
||||
net_device->destroy = false;
|
||||
net_device->dev = device;
|
||||
net_device->ndev = ndev;
|
||||
@@ -299,7 +299,7 @@ static int negotiate_nvsp_ver(struct hv_device *device,
|
||||
/* NVSPv2 only: Send NDIS config */
|
||||
memset(init_packet, 0, sizeof(struct nvsp_message));
|
||||
init_packet->hdr.msg_type = NVSP_MSG2_TYPE_SEND_NDIS_CONFIG;
|
||||
- init_packet->msg.v2_msg.send_ndis_config.mtu = ETH_DATA_LEN;
|
||||
+ init_packet->msg.v2_msg.send_ndis_config.mtu = net_device->ndev->mtu;
|
||||
|
||||
ret = vmbus_sendpacket(device->channel, init_packet,
|
||||
sizeof(struct nvsp_message),
|
||||
@@ -464,7 +464,7 @@ static void netvsc_send_completion(struct hv_device *device,
|
||||
|
||||
atomic_dec(&net_device->num_outstanding_sends);
|
||||
|
||||
- if (netif_queue_stopped(ndev))
|
||||
+ if (netif_queue_stopped(ndev) && !net_device->start_remove)
|
||||
netif_wake_queue(ndev);
|
||||
} else {
|
||||
netdev_err(ndev, "Unknown send completion packet type- "
|
||||
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
|
||||
index b7cbd12..462d05f 100644
|
||||
--- a/drivers/net/hyperv/netvsc_drv.c
|
||||
+++ b/drivers/net/hyperv/netvsc_drv.c
|
||||
@@ -148,10 +148,12 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
|
||||
struct net_device_context *net_device_ctx = netdev_priv(net);
|
||||
struct hv_netvsc_packet *packet;
|
||||
int ret;
|
||||
- unsigned int i, num_pages;
|
||||
+ unsigned int i, num_pages, npg_data;
|
||||
|
||||
- /* Add 1 for skb->data and additional one for RNDIS */
|
||||
- num_pages = skb_shinfo(skb)->nr_frags + 1 + 1;
|
||||
+ /* Add multipage for skb->data and additional one for RNDIS */
|
||||
+ npg_data = (((unsigned long)skb->data + skb_headlen(skb) - 1)
|
||||
+ >> PAGE_SHIFT) - ((unsigned long)skb->data >> PAGE_SHIFT) + 1;
|
||||
+ num_pages = skb_shinfo(skb)->nr_frags + npg_data + 1;
|
||||
|
||||
/* Allocate a netvsc packet based on # of frags. */
|
||||
packet = kzalloc(sizeof(struct hv_netvsc_packet) +
|
||||
@@ -174,21 +176,36 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
|
||||
packet->page_buf_cnt = num_pages;
|
||||
|
||||
/* Initialize it from the skb */
|
||||
- packet->total_data_buflen = skb->len;
|
||||
+ packet->total_data_buflen = skb->len;
|
||||
|
||||
/* Start filling in the page buffers starting after RNDIS buffer. */
|
||||
packet->page_buf[1].pfn = virt_to_phys(skb->data) >> PAGE_SHIFT;
|
||||
packet->page_buf[1].offset
|
||||
= (unsigned long)skb->data & (PAGE_SIZE - 1);
|
||||
- packet->page_buf[1].len = skb_headlen(skb);
|
||||
+ if (npg_data == 1)
|
||||
+ packet->page_buf[1].len = skb_headlen(skb);
|
||||
+ else
|
||||
+ packet->page_buf[1].len = PAGE_SIZE
|
||||
+ - packet->page_buf[1].offset;
|
||||
+
|
||||
+ for (i = 2; i <= npg_data; i++) {
|
||||
+ packet->page_buf[i].pfn = virt_to_phys(skb->data
|
||||
+ + PAGE_SIZE * (i-1)) >> PAGE_SHIFT;
|
||||
+ packet->page_buf[i].offset = 0;
|
||||
+ packet->page_buf[i].len = PAGE_SIZE;
|
||||
+ }
|
||||
+ if (npg_data > 1)
|
||||
+ packet->page_buf[npg_data].len = (((unsigned long)skb->data
|
||||
+ + skb_headlen(skb) - 1) & (PAGE_SIZE - 1)) + 1;
|
||||
|
||||
/* Additional fragments are after SKB data */
|
||||
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
|
||||
const skb_frag_t *f = &skb_shinfo(skb)->frags[i];
|
||||
|
||||
- packet->page_buf[i+2].pfn = page_to_pfn(skb_frag_page(f));
|
||||
- packet->page_buf[i+2].offset = f->page_offset;
|
||||
- packet->page_buf[i+2].len = skb_frag_size(f);
|
||||
+ packet->page_buf[i+npg_data+1].pfn =
|
||||
+ page_to_pfn(skb_frag_page(f));
|
||||
+ packet->page_buf[i+npg_data+1].offset = f->page_offset;
|
||||
+ packet->page_buf[i+npg_data+1].len = skb_frag_size(f);
|
||||
}
|
||||
|
||||
/* Set the completion routine */
|
||||
@@ -300,6 +317,39 @@ static void netvsc_get_drvinfo(struct net_device *net,
|
||||
strcpy(info->fw_version, "N/A");
|
||||
}
|
||||
|
||||
+static int netvsc_change_mtu(struct net_device *ndev, int mtu)
|
||||
+{
|
||||
+ struct net_device_context *ndevctx = netdev_priv(ndev);
|
||||
+ struct hv_device *hdev = ndevctx->device_ctx;
|
||||
+ struct netvsc_device *nvdev = hv_get_drvdata(hdev);
|
||||
+ struct netvsc_device_info device_info;
|
||||
+ int limit = ETH_DATA_LEN;
|
||||
+
|
||||
+ if (nvdev == NULL || nvdev->destroy)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ if (nvdev->nvsp_version == NVSP_PROTOCOL_VERSION_2)
|
||||
+ limit = NETVSC_MTU;
|
||||
+
|
||||
+ if (mtu < 68 || mtu > limit)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ nvdev->start_remove = true;
|
||||
+ cancel_delayed_work_sync(&ndevctx->dwork);
|
||||
+ netif_stop_queue(ndev);
|
||||
+ rndis_filter_device_remove(hdev);
|
||||
+
|
||||
+ ndev->mtu = mtu;
|
||||
+
|
||||
+ ndevctx->device_ctx = hdev;
|
||||
+ hv_set_drvdata(hdev, ndev);
|
||||
+ device_info.ring_size = ring_size;
|
||||
+ rndis_filter_device_add(hdev, &device_info);
|
||||
+ netif_wake_queue(ndev);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static const struct ethtool_ops ethtool_ops = {
|
||||
.get_drvinfo = netvsc_get_drvinfo,
|
||||
.get_link = ethtool_op_get_link,
|
||||
@@ -310,7 +360,7 @@ static const struct net_device_ops device_ops = {
|
||||
.ndo_stop = netvsc_close,
|
||||
.ndo_start_xmit = netvsc_start_xmit,
|
||||
.ndo_set_rx_mode = netvsc_set_multicast_list,
|
||||
- .ndo_change_mtu = eth_change_mtu,
|
||||
+ .ndo_change_mtu = netvsc_change_mtu,
|
||||
.ndo_validate_addr = eth_validate_addr,
|
||||
.ndo_set_mac_address = eth_mac_addr,
|
||||
};
|
||||
@@ -403,6 +453,8 @@ static int netvsc_remove(struct hv_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+ net_device->start_remove = true;
|
||||
+
|
||||
ndev_ctx = netdev_priv(net);
|
||||
cancel_delayed_work_sync(&ndev_ctx->dwork);
|
||||
|
||||
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
|
||||
index 12ec328..62b908e 100644
|
||||
--- a/include/linux/hyperv.h
|
||||
+++ b/include/linux/hyperv.h
|
||||
@@ -35,7 +35,7 @@
|
||||
#include <linux/mod_devicetable.h>
|
||||
|
||||
|
||||
-#define MAX_PAGE_BUFFER_COUNT 16
|
||||
+#define MAX_PAGE_BUFFER_COUNT 18
|
||||
#define MAX_MULTIPAGE_BUFFER_COUNT 32 /* 128K */
|
||||
|
||||
#pragma pack(push, 1)
|
||||
--
|
||||
1.7.9.5
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
From: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
|
||||
Date: Tue, 24 Jan 2012 10:21:28 +0000
|
||||
Subject: [PATCH 36/77] net/hyperv: fix possible memory leak in
|
||||
do_set_multicast()
|
||||
|
||||
commit c11bf1c8baff170fa478adc04964da519d160e62 upstream.
|
||||
|
||||
do_set_multicast() may not free the memory malloc in
|
||||
netvsc_set_multicast_list().
|
||||
|
||||
Signed-off-by: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/hyperv/netvsc_drv.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
|
||||
index 462d05f..1a1ca6c 100644
|
||||
--- a/drivers/net/hyperv/netvsc_drv.c
|
||||
+++ b/drivers/net/hyperv/netvsc_drv.c
|
||||
@@ -68,11 +68,11 @@ static void do_set_multicast(struct work_struct *w)
|
||||
|
||||
nvdev = hv_get_drvdata(ndevctx->device_ctx);
|
||||
if (nvdev == NULL)
|
||||
- return;
|
||||
+ goto out;
|
||||
|
||||
rdev = nvdev->extension;
|
||||
if (rdev == NULL)
|
||||
- return;
|
||||
+ goto out;
|
||||
|
||||
if (net->flags & IFF_PROMISC)
|
||||
rndis_filter_set_packet_filter(rdev,
|
||||
@@ -83,6 +83,7 @@ static void do_set_multicast(struct work_struct *w)
|
||||
NDIS_PACKET_TYPE_ALL_MULTICAST |
|
||||
NDIS_PACKET_TYPE_DIRECTED);
|
||||
|
||||
+out:
|
||||
kfree(w);
|
||||
}
|
||||
|
||||
--
|
||||
1.7.9.5
|
||||
|
127
debian/patches/features/x86/hyperv/0037-drivers-hv-Get-rid-of-some-unnecessary-code.patch
vendored
Normal file
127
debian/patches/features/x86/hyperv/0037-drivers-hv-Get-rid-of-some-unnecessary-code.patch
vendored
Normal file
|
@ -0,0 +1,127 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Sun, 8 Jan 2012 10:12:18 -0800
|
||||
Subject: [PATCH 37/77] drivers: hv: Get rid of some unnecessary code
|
||||
|
||||
commit 2897a563a55442379e5e59ec68c229a7f27fb7c6 upstream.
|
||||
|
||||
The current code unnecessarily limits the number of offers we handle.
|
||||
Get rid of this limitation. As part of this cleanup, also get rid of an
|
||||
unused define - MAX_MSG_TYPES.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
---
|
||||
drivers/hv/channel_mgmt.c | 87 ---------------------------------------------
|
||||
1 file changed, 87 deletions(-)
|
||||
|
||||
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
|
||||
index 36484db..9ffbfc5 100644
|
||||
--- a/drivers/hv/channel_mgmt.c
|
||||
+++ b/drivers/hv/channel_mgmt.c
|
||||
@@ -37,81 +37,6 @@ struct vmbus_channel_message_table_entry {
|
||||
void (*message_handler)(struct vmbus_channel_message_header *msg);
|
||||
};
|
||||
|
||||
-#define MAX_MSG_TYPES 4
|
||||
-#define MAX_NUM_DEVICE_CLASSES_SUPPORTED 8
|
||||
-
|
||||
-static const uuid_le
|
||||
- supported_device_classes[MAX_NUM_DEVICE_CLASSES_SUPPORTED] = {
|
||||
- /* {ba6163d9-04a1-4d29-b605-72e2ffb1dc7f} */
|
||||
- /* Storage - SCSI */
|
||||
- {
|
||||
- .b = {
|
||||
- 0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d,
|
||||
- 0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f
|
||||
- }
|
||||
- },
|
||||
-
|
||||
- /* {F8615163-DF3E-46c5-913F-F2D2F965ED0E} */
|
||||
- /* Network */
|
||||
- {
|
||||
- .b = {
|
||||
- 0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46,
|
||||
- 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E
|
||||
- }
|
||||
- },
|
||||
-
|
||||
- /* {CFA8B69E-5B4A-4cc0-B98B-8BA1A1F3F95A} */
|
||||
- /* Input */
|
||||
- {
|
||||
- .b = {
|
||||
- 0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c,
|
||||
- 0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A
|
||||
- }
|
||||
- },
|
||||
-
|
||||
- /* {32412632-86cb-44a2-9b5c-50d1417354f5} */
|
||||
- /* IDE */
|
||||
- {
|
||||
- .b = {
|
||||
- 0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44,
|
||||
- 0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5
|
||||
- }
|
||||
- },
|
||||
- /* 0E0B6031-5213-4934-818B-38D90CED39DB */
|
||||
- /* Shutdown */
|
||||
- {
|
||||
- .b = {
|
||||
- 0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49,
|
||||
- 0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB
|
||||
- }
|
||||
- },
|
||||
- /* {9527E630-D0AE-497b-ADCE-E80AB0175CAF} */
|
||||
- /* TimeSync */
|
||||
- {
|
||||
- .b = {
|
||||
- 0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49,
|
||||
- 0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf
|
||||
- }
|
||||
- },
|
||||
- /* {57164f39-9115-4e78-ab55-382f3bd5422d} */
|
||||
- /* Heartbeat */
|
||||
- {
|
||||
- .b = {
|
||||
- 0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e,
|
||||
- 0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d
|
||||
- }
|
||||
- },
|
||||
- /* {A9A0F4E7-5A45-4d96-B827-8A841E8C03E6} */
|
||||
- /* KVP */
|
||||
- {
|
||||
- .b = {
|
||||
- 0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d,
|
||||
- 0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3, 0xe6
|
||||
- }
|
||||
- },
|
||||
-
|
||||
-};
|
||||
-
|
||||
|
||||
/**
|
||||
* vmbus_prep_negotiate_resp() - Create default response for Hyper-V Negotiate message
|
||||
@@ -321,20 +246,8 @@ static void vmbus_onoffer(struct vmbus_channel_message_header *hdr)
|
||||
struct vmbus_channel *newchannel;
|
||||
uuid_le *guidtype;
|
||||
uuid_le *guidinstance;
|
||||
- int i;
|
||||
- int fsupported = 0;
|
||||
|
||||
offer = (struct vmbus_channel_offer_channel *)hdr;
|
||||
- for (i = 0; i < MAX_NUM_DEVICE_CLASSES_SUPPORTED; i++) {
|
||||
- if (!uuid_le_cmp(offer->offer.if_type,
|
||||
- supported_device_classes[i])) {
|
||||
- fsupported = 1;
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- if (!fsupported)
|
||||
- return;
|
||||
|
||||
guidtype = &offer->offer.if_type;
|
||||
guidinstance = &offer->offer.if_instance;
|
||||
--
|
||||
1.7.9.5
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
From: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
|
||||
Date: Sun, 29 Jan 2012 22:14:02 +0000
|
||||
Subject: [PATCH 38/77] net/hyperv: rx_bytes should account the ether header
|
||||
size
|
||||
|
||||
commit 48c3883999cb06246911e29356d194f96f1c75ef upstream.
|
||||
|
||||
skb->len after call eth_type_trans() does not include the ether
|
||||
header size, but rx_bytes should account it.
|
||||
|
||||
Signed-off-by: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/hyperv/netvsc_drv.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
|
||||
index 1a1ca6c..9dccc7a 100644
|
||||
--- a/drivers/net/hyperv/netvsc_drv.c
|
||||
+++ b/drivers/net/hyperv/netvsc_drv.c
|
||||
@@ -298,7 +298,7 @@ int netvsc_recv_callback(struct hv_device *device_obj,
|
||||
skb->ip_summed = CHECKSUM_NONE;
|
||||
|
||||
net->stats.rx_packets++;
|
||||
- net->stats.rx_bytes += skb->len;
|
||||
+ net->stats.rx_bytes += packet->total_data_buflen;
|
||||
|
||||
/*
|
||||
* Pass the skb back up. Network stack will deallocate the skb when it
|
||||
--
|
||||
1.7.9.5
|
||||
|
32
debian/patches/features/x86/hyperv/0039-HID-hyperv-Properly-disconnect-the-input-device.patch
vendored
Normal file
32
debian/patches/features/x86/hyperv/0039-HID-hyperv-Properly-disconnect-the-input-device.patch
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Wed, 18 Jan 2012 08:57:14 -0800
|
||||
Subject: [PATCH 39/77] HID: hyperv: Properly disconnect the input device
|
||||
|
||||
commit c1c454b8691cc95aa83f19273ed7845914c70e83 upstream.
|
||||
|
||||
When we unload the mouse driver, properly disconnect the input device.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Reported-by: Fuzhou Chen <fuzhouch@microsoft.com>
|
||||
Cc: stable <stable@vger.kernel.org>
|
||||
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
|
||||
---
|
||||
drivers/hid/hid-hyperv.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/drivers/hid/hid-hyperv.c b/drivers/hid/hid-hyperv.c
|
||||
index 0c33ae9..4066324 100644
|
||||
--- a/drivers/hid/hid-hyperv.c
|
||||
+++ b/drivers/hid/hid-hyperv.c
|
||||
@@ -548,6 +548,7 @@ static int mousevsc_remove(struct hv_device *dev)
|
||||
struct mousevsc_dev *input_dev = hv_get_drvdata(dev);
|
||||
|
||||
vmbus_close(dev->channel);
|
||||
+ hid_hw_stop(input_dev->hid_device);
|
||||
hid_destroy_device(input_dev->hid_device);
|
||||
mousevsc_free_device(input_dev);
|
||||
|
||||
--
|
||||
1.7.9.5
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
From: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
|
||||
Date: Wed, 1 Feb 2012 20:17:23 +0000
|
||||
Subject: [PATCH 40/77] net/hyperv: fix the issue that large packets be
|
||||
dropped under bridge
|
||||
|
||||
commit 4b8a8bc9249f144803d840f2f7608ee9bbf1ea51 upstream.
|
||||
|
||||
The packets with size larger than 1452 will be dropped by bridge
|
||||
which with two hyperv netdevice ports. This cause by hyperv netvsc
|
||||
driver always copy the trailer padding to the data packet, and then
|
||||
the skb received from netdevice may include wrong skb->len (20 bytes
|
||||
larger than the real size normally). The captured packet may like
|
||||
this:
|
||||
|
||||
Ethernet II, Src: Microsof_00:00:07 (00:15:5d:00:00:07),
|
||||
Dst: HewlettP_00:00:4e (00:1f:29:00:00:4e)
|
||||
Destination: HewlettP_e6:00:4e (00:1f:29:00:00:4e)
|
||||
Source: Microsof_f6:6d:07 (00:15:5d:f6:6d:07)
|
||||
Type: IP (0x0800)
|
||||
Trailer: 1415161718191A1B1C1D1E1F20212223
|
||||
Frame check sequence: 0x24252627 [incorrect, should be 0x7c2e5a5e]
|
||||
|
||||
The following command help to reproduction it, and the ping ICMP
|
||||
packets will be dropped by bridge.
|
||||
$ ping ip -s 1453
|
||||
|
||||
This patch fixed it by removing the trailer padding from the data
|
||||
packet.
|
||||
|
||||
Signed-off-by: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/hyperv/rndis_filter.c | 19 +++++++++++++++++++
|
||||
1 file changed, 19 insertions(+)
|
||||
|
||||
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
|
||||
index da181f9..dc2e384 100644
|
||||
--- a/drivers/net/hyperv/rndis_filter.c
|
||||
+++ b/drivers/net/hyperv/rndis_filter.c
|
||||
@@ -321,6 +321,25 @@ static void rndis_filter_receive_data(struct rndis_device *dev,
|
||||
data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset;
|
||||
|
||||
pkt->total_data_buflen -= data_offset;
|
||||
+
|
||||
+ /*
|
||||
+ * Make sure we got a valid RNDIS message, now total_data_buflen
|
||||
+ * should be the data packet size plus the trailer padding size
|
||||
+ */
|
||||
+ if (pkt->total_data_buflen < rndis_pkt->data_len) {
|
||||
+ netdev_err(dev->net_dev->ndev, "rndis message buffer "
|
||||
+ "overflow detected (got %u, min %u)"
|
||||
+ "...dropping this message!\n",
|
||||
+ pkt->total_data_buflen, rndis_pkt->data_len);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Remove the rndis trailer padding from rndis packet message
|
||||
+ * rndis_pkt->data_len tell us the real data length, we only copy
|
||||
+ * the data packet to the stack, without the rndis trailer padding
|
||||
+ */
|
||||
+ pkt->total_data_buflen = rndis_pkt->data_len;
|
||||
pkt->data = (void *)((unsigned long)pkt->data + data_offset);
|
||||
|
||||
pkt->is_data_pkt = true;
|
||||
--
|
||||
1.7.9.5
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
From: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Date: Thu, 2 Feb 2012 07:17:59 +0000
|
||||
Subject: [PATCH 41/77] net/hyperv: Use netif_tx_disable() instead of
|
||||
netif_stop_queue() when necessary
|
||||
|
||||
commit 0a282538cc1977655004cdb2eb25dd2b63f20637 upstream.
|
||||
|
||||
For code path not on the xmit, use netif_tx_disable() instead of
|
||||
netif_stop_queue() to ensure other CPUs are not doing xmit.
|
||||
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/hyperv/netvsc_drv.c | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
|
||||
index 9dccc7a..69193fc 100644
|
||||
--- a/drivers/net/hyperv/netvsc_drv.c
|
||||
+++ b/drivers/net/hyperv/netvsc_drv.c
|
||||
@@ -123,7 +123,7 @@ static int netvsc_close(struct net_device *net)
|
||||
struct hv_device *device_obj = net_device_ctx->device_ctx;
|
||||
int ret;
|
||||
|
||||
- netif_stop_queue(net);
|
||||
+ netif_tx_disable(net);
|
||||
|
||||
ret = rndis_filter_close(device_obj);
|
||||
if (ret != 0)
|
||||
@@ -256,7 +256,7 @@ void netvsc_linkstatus_callback(struct hv_device *device_obj,
|
||||
schedule_delayed_work(&ndev_ctx->dwork, msecs_to_jiffies(20));
|
||||
} else {
|
||||
netif_carrier_off(net);
|
||||
- netif_stop_queue(net);
|
||||
+ netif_tx_disable(net);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -337,7 +337,7 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
|
||||
|
||||
nvdev->start_remove = true;
|
||||
cancel_delayed_work_sync(&ndevctx->dwork);
|
||||
- netif_stop_queue(ndev);
|
||||
+ netif_tx_disable(ndev);
|
||||
rndis_filter_device_remove(hdev);
|
||||
|
||||
ndev->mtu = mtu;
|
||||
@@ -460,7 +460,7 @@ static int netvsc_remove(struct hv_device *dev)
|
||||
cancel_delayed_work_sync(&ndev_ctx->dwork);
|
||||
|
||||
/* Stop outbound asap */
|
||||
- netif_stop_queue(net);
|
||||
+ netif_tx_disable(net);
|
||||
|
||||
unregister_netdev(net);
|
||||
|
||||
--
|
||||
1.7.9.5
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
From: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Date: Thu, 2 Feb 2012 07:18:00 +0000
|
||||
Subject: [PATCH 42/77] net/hyperv: Fix the page buffer when an RNDIS message
|
||||
goes beyond page boundary
|
||||
|
||||
commit c31c151b1c4a29da4dc92212aa8648fb4f8557b9 upstream.
|
||||
|
||||
There is a possible data corruption if an RNDIS message goes beyond page
|
||||
boundary in the sending code path. This patch fixes the problem.
|
||||
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/hyperv/netvsc_drv.c | 8 ++++----
|
||||
drivers/net/hyperv/rndis_filter.c | 13 +++++++++++++
|
||||
include/linux/hyperv.h | 2 +-
|
||||
3 files changed, 18 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
|
||||
index 69193fc..466c58a 100644
|
||||
--- a/drivers/net/hyperv/netvsc_drv.c
|
||||
+++ b/drivers/net/hyperv/netvsc_drv.c
|
||||
@@ -151,10 +151,10 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
|
||||
int ret;
|
||||
unsigned int i, num_pages, npg_data;
|
||||
|
||||
- /* Add multipage for skb->data and additional one for RNDIS */
|
||||
+ /* Add multipages for skb->data and additional 2 for RNDIS */
|
||||
npg_data = (((unsigned long)skb->data + skb_headlen(skb) - 1)
|
||||
>> PAGE_SHIFT) - ((unsigned long)skb->data >> PAGE_SHIFT) + 1;
|
||||
- num_pages = skb_shinfo(skb)->nr_frags + npg_data + 1;
|
||||
+ num_pages = skb_shinfo(skb)->nr_frags + npg_data + 2;
|
||||
|
||||
/* Allocate a netvsc packet based on # of frags. */
|
||||
packet = kzalloc(sizeof(struct hv_netvsc_packet) +
|
||||
@@ -173,8 +173,8 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
|
||||
sizeof(struct hv_netvsc_packet) +
|
||||
(num_pages * sizeof(struct hv_page_buffer));
|
||||
|
||||
- /* Setup the rndis header */
|
||||
- packet->page_buf_cnt = num_pages;
|
||||
+ /* If the rndis msg goes beyond 1 page, we will add 1 later */
|
||||
+ packet->page_buf_cnt = num_pages - 1;
|
||||
|
||||
/* Initialize it from the skb */
|
||||
packet->total_data_buflen = skb->len;
|
||||
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
|
||||
index dc2e384..133b7fb 100644
|
||||
--- a/drivers/net/hyperv/rndis_filter.c
|
||||
+++ b/drivers/net/hyperv/rndis_filter.c
|
||||
@@ -797,6 +797,19 @@ int rndis_filter_send(struct hv_device *dev,
|
||||
(unsigned long)rndisMessage & (PAGE_SIZE-1);
|
||||
pkt->page_buf[0].len = rndisMessageSize;
|
||||
|
||||
+ /* Add one page_buf if the rndis msg goes beyond page boundary */
|
||||
+ if (pkt->page_buf[0].offset + rndisMessageSize > PAGE_SIZE) {
|
||||
+ int i;
|
||||
+ for (i = pkt->page_buf_cnt; i > 1; i--)
|
||||
+ pkt->page_buf[i] = pkt->page_buf[i-1];
|
||||
+ pkt->page_buf_cnt++;
|
||||
+ pkt->page_buf[0].len = PAGE_SIZE - pkt->page_buf[0].offset;
|
||||
+ pkt->page_buf[1].pfn = virt_to_phys((void *)((ulong)
|
||||
+ rndisMessage + pkt->page_buf[0].len)) >> PAGE_SHIFT;
|
||||
+ pkt->page_buf[1].offset = 0;
|
||||
+ pkt->page_buf[1].len = rndisMessageSize - pkt->page_buf[0].len;
|
||||
+ }
|
||||
+
|
||||
/* Save the packet send completion and context */
|
||||
filterPacket->completion = pkt->completion.send.send_completion;
|
||||
filterPacket->completion_ctx =
|
||||
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
|
||||
index 62b908e..0ae065a 100644
|
||||
--- a/include/linux/hyperv.h
|
||||
+++ b/include/linux/hyperv.h
|
||||
@@ -35,7 +35,7 @@
|
||||
#include <linux/mod_devicetable.h>
|
||||
|
||||
|
||||
-#define MAX_PAGE_BUFFER_COUNT 18
|
||||
+#define MAX_PAGE_BUFFER_COUNT 19
|
||||
#define MAX_MULTIPAGE_BUFFER_COUNT 32 /* 128K */
|
||||
|
||||
#pragma pack(push, 1)
|
||||
--
|
||||
1.7.9.5
|
||||
|
68
debian/patches/features/x86/hyperv/0043-drivers-hv-kvp-Add-cleanup-connector-defines.patch
vendored
Normal file
68
debian/patches/features/x86/hyperv/0043-drivers-hv-kvp-Add-cleanup-connector-defines.patch
vendored
Normal file
|
@ -0,0 +1,68 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Fri, 27 Jan 2012 15:55:57 -0800
|
||||
Subject: [PATCH 43/77] drivers: hv: kvp: Add/cleanup connector defines
|
||||
|
||||
commit 4f03a2c934894f30a64d397df8c7c4de129c5b30 upstream.
|
||||
|
||||
The current KVP code carries some private connector related defines.
|
||||
Update connector.h to have all the KVP defines. As part of this patch
|
||||
get rid of some unused defines.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/hv/hv_kvp.h | 3 ---
|
||||
include/linux/connector.h | 1 +
|
||||
tools/hv/hv_kvp_daemon.c | 4 ----
|
||||
3 files changed, 1 insertion(+), 7 deletions(-)
|
||||
|
||||
diff --git a/drivers/hv/hv_kvp.h b/drivers/hv/hv_kvp.h
|
||||
index 9b765d7..c2c5bba 100644
|
||||
--- a/drivers/hv/hv_kvp.h
|
||||
+++ b/drivers/hv/hv_kvp.h
|
||||
@@ -107,9 +107,6 @@
|
||||
* the KVP user-mode component.
|
||||
*/
|
||||
|
||||
-#define CN_KVP_VAL 0x1 /* This supports queries from the kernel */
|
||||
-#define CN_KVP_USER_VAL 0x2 /* This supports queries from the user */
|
||||
-
|
||||
enum hv_ku_op {
|
||||
KVP_REGISTER = 0, /* Register the user mode component */
|
||||
KVP_KERNEL_GET, /* Kernel is requesting the value */
|
||||
diff --git a/include/linux/connector.h b/include/linux/connector.h
|
||||
index 3c9c54f..7638407 100644
|
||||
--- a/include/linux/connector.h
|
||||
+++ b/include/linux/connector.h
|
||||
@@ -43,6 +43,7 @@
|
||||
#define CN_IDX_DRBD 0x8
|
||||
#define CN_VAL_DRBD 0x1
|
||||
#define CN_KVP_IDX 0x9 /* HyperV KVP */
|
||||
+#define CN_KVP_VAL 0x1 /* queries from the kernel */
|
||||
|
||||
#define CN_NETLINK_USERS 10 /* Highest index + 1 */
|
||||
|
||||
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
|
||||
index 11224ed..2b6a2d9 100644
|
||||
--- a/tools/hv/hv_kvp_daemon.c
|
||||
+++ b/tools/hv/hv_kvp_daemon.c
|
||||
@@ -40,15 +40,11 @@
|
||||
#include <syslog.h>
|
||||
|
||||
/*
|
||||
- * KYS: TODO. Need to register these in the kernel.
|
||||
*
|
||||
* The following definitions are shared with the in-kernel component; do not
|
||||
* change any of this without making the corresponding changes in
|
||||
* the KVP kernel component.
|
||||
*/
|
||||
-#define CN_KVP_IDX 0x9 /* MSFT KVP functionality */
|
||||
-#define CN_KVP_VAL 0x1 /* This supports queries from the kernel */
|
||||
-#define CN_KVP_USER_VAL 0x2 /* This supports queries from the user */
|
||||
|
||||
/*
|
||||
* KVP protocol: The user mode component first registers with the
|
||||
--
|
||||
1.7.9.5
|
||||
|
420
debian/patches/features/x86/hyperv/0044-drivers-hv-kvp-Move-the-contents-of-hv_kvp.h-to-hype.patch
vendored
Normal file
420
debian/patches/features/x86/hyperv/0044-drivers-hv-kvp-Move-the-contents-of-hv_kvp.h-to-hype.patch
vendored
Normal file
|
@ -0,0 +1,420 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Fri, 27 Jan 2012 15:55:58 -0800
|
||||
Subject: [PATCH 44/77] drivers: hv: kvp: Move the contents of hv_kvp.h to
|
||||
hyperv.h
|
||||
|
||||
commit 2939437ce8f2de07237eb2bcce29b6a699bfe799 upstream.
|
||||
|
||||
In preparation for consolidating all KVP related defines into a single header file
|
||||
that both the kernel and user level components can use, move the contents of
|
||||
hv_kvp.h into hyperv.h.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/hv/hv_kvp.c | 2 -
|
||||
drivers/hv/hv_kvp.h | 181 ------------------------------------------------
|
||||
drivers/hv/hv_util.c | 3 -
|
||||
include/linux/hyperv.h | 165 +++++++++++++++++++++++++++++++++++++++++++
|
||||
4 files changed, 165 insertions(+), 186 deletions(-)
|
||||
delete mode 100644 drivers/hv/hv_kvp.h
|
||||
|
||||
diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
|
||||
index 0e8343f..4a6971e 100644
|
||||
--- a/drivers/hv/hv_kvp.c
|
||||
+++ b/drivers/hv/hv_kvp.c
|
||||
@@ -28,8 +28,6 @@
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/hyperv.h>
|
||||
|
||||
-#include "hv_kvp.h"
|
||||
-
|
||||
|
||||
|
||||
/*
|
||||
diff --git a/drivers/hv/hv_kvp.h b/drivers/hv/hv_kvp.h
|
||||
deleted file mode 100644
|
||||
index c2c5bba..0000000
|
||||
--- a/drivers/hv/hv_kvp.h
|
||||
+++ /dev/null
|
||||
@@ -1,181 +0,0 @@
|
||||
-/*
|
||||
- * An implementation of HyperV key value pair (KVP) functionality for Linux.
|
||||
- *
|
||||
- *
|
||||
- * Copyright (C) 2010, Novell, Inc.
|
||||
- * Author : K. Y. Srinivasan <ksrinivasan@novell.com>
|
||||
- *
|
||||
- * This program is free software; you can redistribute it and/or modify it
|
||||
- * under the terms of the GNU General Public License version 2 as published
|
||||
- * by the Free Software Foundation.
|
||||
- *
|
||||
- * This program is distributed in the hope that it will be useful, but
|
||||
- * WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
|
||||
- * NON INFRINGEMENT. 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
- *
|
||||
- */
|
||||
-#ifndef _KVP_H
|
||||
-#define _KVP_H_
|
||||
-
|
||||
-/*
|
||||
- * Maximum value size - used for both key names and value data, and includes
|
||||
- * any applicable NULL terminators.
|
||||
- *
|
||||
- * Note: This limit is somewhat arbitrary, but falls easily within what is
|
||||
- * supported for all native guests (back to Win 2000) and what is reasonable
|
||||
- * for the IC KVP exchange functionality. Note that Windows Me/98/95 are
|
||||
- * limited to 255 character key names.
|
||||
- *
|
||||
- * MSDN recommends not storing data values larger than 2048 bytes in the
|
||||
- * registry.
|
||||
- *
|
||||
- * Note: This value is used in defining the KVP exchange message - this value
|
||||
- * cannot be modified without affecting the message size and compatibility.
|
||||
- */
|
||||
-
|
||||
-/*
|
||||
- * bytes, including any null terminators
|
||||
- */
|
||||
-#define HV_KVP_EXCHANGE_MAX_VALUE_SIZE (2048)
|
||||
-
|
||||
-
|
||||
-/*
|
||||
- * Maximum key size - the registry limit for the length of an entry name
|
||||
- * is 256 characters, including the null terminator
|
||||
- */
|
||||
-
|
||||
-#define HV_KVP_EXCHANGE_MAX_KEY_SIZE (512)
|
||||
-
|
||||
-/*
|
||||
- * In Linux, we implement the KVP functionality in two components:
|
||||
- * 1) The kernel component which is packaged as part of the hv_utils driver
|
||||
- * is responsible for communicating with the host and responsible for
|
||||
- * implementing the host/guest protocol. 2) A user level daemon that is
|
||||
- * responsible for data gathering.
|
||||
- *
|
||||
- * Host/Guest Protocol: The host iterates over an index and expects the guest
|
||||
- * to assign a key name to the index and also return the value corresponding to
|
||||
- * the key. The host will have atmost one KVP transaction outstanding at any
|
||||
- * given point in time. The host side iteration stops when the guest returns
|
||||
- * an error. Microsoft has specified the following mapping of key names to
|
||||
- * host specified index:
|
||||
- *
|
||||
- * Index Key Name
|
||||
- * 0 FullyQualifiedDomainName
|
||||
- * 1 IntegrationServicesVersion
|
||||
- * 2 NetworkAddressIPv4
|
||||
- * 3 NetworkAddressIPv6
|
||||
- * 4 OSBuildNumber
|
||||
- * 5 OSName
|
||||
- * 6 OSMajorVersion
|
||||
- * 7 OSMinorVersion
|
||||
- * 8 OSVersion
|
||||
- * 9 ProcessorArchitecture
|
||||
- *
|
||||
- * The Windows host expects the Key Name and Key Value to be encoded in utf16.
|
||||
- *
|
||||
- * Guest Kernel/KVP Daemon Protocol: As noted earlier, we implement all of the
|
||||
- * data gathering functionality in a user mode daemon. The user level daemon
|
||||
- * is also responsible for binding the key name to the index as well. The
|
||||
- * kernel and user-level daemon communicate using a connector channel.
|
||||
- *
|
||||
- * The user mode component first registers with the
|
||||
- * the kernel component. Subsequently, the kernel component requests, data
|
||||
- * for the specified keys. In response to this message the user mode component
|
||||
- * fills in the value corresponding to the specified key. We overload the
|
||||
- * sequence field in the cn_msg header to define our KVP message types.
|
||||
- *
|
||||
- *
|
||||
- * The kernel component simply acts as a conduit for communication between the
|
||||
- * Windows host and the user-level daemon. The kernel component passes up the
|
||||
- * index received from the Host to the user-level daemon. If the index is
|
||||
- * valid (supported), the corresponding key as well as its
|
||||
- * value (both are strings) is returned. If the index is invalid
|
||||
- * (not supported), a NULL key string is returned.
|
||||
- */
|
||||
-
|
||||
-/*
|
||||
- *
|
||||
- * The following definitions are shared with the user-mode component; do not
|
||||
- * change any of this without making the corresponding changes in
|
||||
- * the KVP user-mode component.
|
||||
- */
|
||||
-
|
||||
-enum hv_ku_op {
|
||||
- KVP_REGISTER = 0, /* Register the user mode component */
|
||||
- KVP_KERNEL_GET, /* Kernel is requesting the value */
|
||||
- KVP_KERNEL_SET, /* Kernel is providing the value */
|
||||
- KVP_USER_GET, /* User is requesting the value */
|
||||
- KVP_USER_SET /* User is providing the value */
|
||||
-};
|
||||
-
|
||||
-struct hv_ku_msg {
|
||||
- __u32 kvp_index; /* Key index */
|
||||
- __u8 kvp_key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; /* Key name */
|
||||
- __u8 kvp_value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; /* Key value */
|
||||
-};
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
-#ifdef __KERNEL__
|
||||
-
|
||||
-/*
|
||||
- * Registry value types.
|
||||
- */
|
||||
-
|
||||
-#define REG_SZ 1
|
||||
-
|
||||
-enum hv_kvp_exchg_op {
|
||||
- KVP_OP_GET = 0,
|
||||
- KVP_OP_SET,
|
||||
- KVP_OP_DELETE,
|
||||
- KVP_OP_ENUMERATE,
|
||||
- KVP_OP_COUNT /* Number of operations, must be last. */
|
||||
-};
|
||||
-
|
||||
-enum hv_kvp_exchg_pool {
|
||||
- KVP_POOL_EXTERNAL = 0,
|
||||
- KVP_POOL_GUEST,
|
||||
- KVP_POOL_AUTO,
|
||||
- KVP_POOL_AUTO_EXTERNAL,
|
||||
- KVP_POOL_AUTO_INTERNAL,
|
||||
- KVP_POOL_COUNT /* Number of pools, must be last. */
|
||||
-};
|
||||
-
|
||||
-struct hv_kvp_hdr {
|
||||
- u8 operation;
|
||||
- u8 pool;
|
||||
-};
|
||||
-
|
||||
-struct hv_kvp_exchg_msg_value {
|
||||
- u32 value_type;
|
||||
- u32 key_size;
|
||||
- u32 value_size;
|
||||
- u8 key[HV_KVP_EXCHANGE_MAX_KEY_SIZE];
|
||||
- u8 value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE];
|
||||
-};
|
||||
-
|
||||
-struct hv_kvp_msg_enumerate {
|
||||
- u32 index;
|
||||
- struct hv_kvp_exchg_msg_value data;
|
||||
-};
|
||||
-
|
||||
-struct hv_kvp_msg {
|
||||
- struct hv_kvp_hdr kvp_hdr;
|
||||
- struct hv_kvp_msg_enumerate kvp_data;
|
||||
-};
|
||||
-
|
||||
-int hv_kvp_init(struct hv_util_service *);
|
||||
-void hv_kvp_deinit(void);
|
||||
-void hv_kvp_onchannelcallback(void *);
|
||||
-
|
||||
-#endif /* __KERNEL__ */
|
||||
-#endif /* _KVP_H */
|
||||
-
|
||||
diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c
|
||||
index 55d58f2..dbb8b8e 100644
|
||||
--- a/drivers/hv/hv_util.c
|
||||
+++ b/drivers/hv/hv_util.c
|
||||
@@ -28,9 +28,6 @@
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/hyperv.h>
|
||||
|
||||
-#include "hv_kvp.h"
|
||||
-
|
||||
-
|
||||
static void shutdown_onchannelcallback(void *context);
|
||||
static struct hv_util_service util_shutdown = {
|
||||
.util_cb = shutdown_onchannelcallback,
|
||||
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
|
||||
index 0ae065a..c445ead 100644
|
||||
--- a/include/linux/hyperv.h
|
||||
+++ b/include/linux/hyperv.h
|
||||
@@ -25,6 +25,166 @@
|
||||
#ifndef _HYPERV_H
|
||||
#define _HYPERV_H
|
||||
|
||||
+#include <linux/types.h>
|
||||
+
|
||||
+/*
|
||||
+ * An implementation of HyperV key value pair (KVP) functionality for Linux.
|
||||
+ *
|
||||
+ *
|
||||
+ * Copyright (C) 2010, Novell, Inc.
|
||||
+ * Author : K. Y. Srinivasan <ksrinivasan@novell.com>
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+/*
|
||||
+ * Maximum value size - used for both key names and value data, and includes
|
||||
+ * any applicable NULL terminators.
|
||||
+ *
|
||||
+ * Note: This limit is somewhat arbitrary, but falls easily within what is
|
||||
+ * supported for all native guests (back to Win 2000) and what is reasonable
|
||||
+ * for the IC KVP exchange functionality. Note that Windows Me/98/95 are
|
||||
+ * limited to 255 character key names.
|
||||
+ *
|
||||
+ * MSDN recommends not storing data values larger than 2048 bytes in the
|
||||
+ * registry.
|
||||
+ *
|
||||
+ * Note: This value is used in defining the KVP exchange message - this value
|
||||
+ * cannot be modified without affecting the message size and compatibility.
|
||||
+ */
|
||||
+
|
||||
+/*
|
||||
+ * bytes, including any null terminators
|
||||
+ */
|
||||
+#define HV_KVP_EXCHANGE_MAX_VALUE_SIZE (2048)
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * Maximum key size - the registry limit for the length of an entry name
|
||||
+ * is 256 characters, including the null terminator
|
||||
+ */
|
||||
+
|
||||
+#define HV_KVP_EXCHANGE_MAX_KEY_SIZE (512)
|
||||
+
|
||||
+/*
|
||||
+ * In Linux, we implement the KVP functionality in two components:
|
||||
+ * 1) The kernel component which is packaged as part of the hv_utils driver
|
||||
+ * is responsible for communicating with the host and responsible for
|
||||
+ * implementing the host/guest protocol. 2) A user level daemon that is
|
||||
+ * responsible for data gathering.
|
||||
+ *
|
||||
+ * Host/Guest Protocol: The host iterates over an index and expects the guest
|
||||
+ * to assign a key name to the index and also return the value corresponding to
|
||||
+ * the key. The host will have atmost one KVP transaction outstanding at any
|
||||
+ * given point in time. The host side iteration stops when the guest returns
|
||||
+ * an error. Microsoft has specified the following mapping of key names to
|
||||
+ * host specified index:
|
||||
+ *
|
||||
+ * Index Key Name
|
||||
+ * 0 FullyQualifiedDomainName
|
||||
+ * 1 IntegrationServicesVersion
|
||||
+ * 2 NetworkAddressIPv4
|
||||
+ * 3 NetworkAddressIPv6
|
||||
+ * 4 OSBuildNumber
|
||||
+ * 5 OSName
|
||||
+ * 6 OSMajorVersion
|
||||
+ * 7 OSMinorVersion
|
||||
+ * 8 OSVersion
|
||||
+ * 9 ProcessorArchitecture
|
||||
+ *
|
||||
+ * The Windows host expects the Key Name and Key Value to be encoded in utf16.
|
||||
+ *
|
||||
+ * Guest Kernel/KVP Daemon Protocol: As noted earlier, we implement all of the
|
||||
+ * data gathering functionality in a user mode daemon. The user level daemon
|
||||
+ * is also responsible for binding the key name to the index as well. The
|
||||
+ * kernel and user-level daemon communicate using a connector channel.
|
||||
+ *
|
||||
+ * The user mode component first registers with the
|
||||
+ * the kernel component. Subsequently, the kernel component requests, data
|
||||
+ * for the specified keys. In response to this message the user mode component
|
||||
+ * fills in the value corresponding to the specified key. We overload the
|
||||
+ * sequence field in the cn_msg header to define our KVP message types.
|
||||
+ *
|
||||
+ *
|
||||
+ * The kernel component simply acts as a conduit for communication between the
|
||||
+ * Windows host and the user-level daemon. The kernel component passes up the
|
||||
+ * index received from the Host to the user-level daemon. If the index is
|
||||
+ * valid (supported), the corresponding key as well as its
|
||||
+ * value (both are strings) is returned. If the index is invalid
|
||||
+ * (not supported), a NULL key string is returned.
|
||||
+ */
|
||||
+
|
||||
+/*
|
||||
+ *
|
||||
+ * The following definitions are shared with the user-mode component; do not
|
||||
+ * change any of this without making the corresponding changes in
|
||||
+ * the KVP user-mode component.
|
||||
+ */
|
||||
+
|
||||
+enum hv_ku_op {
|
||||
+ KVP_REGISTER = 0, /* Register the user mode component */
|
||||
+ KVP_KERNEL_GET, /* Kernel is requesting the value */
|
||||
+ KVP_KERNEL_SET, /* Kernel is providing the value */
|
||||
+ KVP_USER_GET, /* User is requesting the value */
|
||||
+ KVP_USER_SET /* User is providing the value */
|
||||
+};
|
||||
+
|
||||
+struct hv_ku_msg {
|
||||
+ __u32 kvp_index; /* Key index */
|
||||
+ __u8 kvp_key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; /* Key name */
|
||||
+ __u8 kvp_value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; /* Key value */
|
||||
+};
|
||||
+
|
||||
+
|
||||
+
|
||||
+
|
||||
+#ifdef __KERNEL__
|
||||
+
|
||||
+/*
|
||||
+ * Registry value types.
|
||||
+ */
|
||||
+
|
||||
+#define REG_SZ 1
|
||||
+
|
||||
+enum hv_kvp_exchg_op {
|
||||
+ KVP_OP_GET = 0,
|
||||
+ KVP_OP_SET,
|
||||
+ KVP_OP_DELETE,
|
||||
+ KVP_OP_ENUMERATE,
|
||||
+ KVP_OP_COUNT /* Number of operations, must be last. */
|
||||
+};
|
||||
+
|
||||
+enum hv_kvp_exchg_pool {
|
||||
+ KVP_POOL_EXTERNAL = 0,
|
||||
+ KVP_POOL_GUEST,
|
||||
+ KVP_POOL_AUTO,
|
||||
+ KVP_POOL_AUTO_EXTERNAL,
|
||||
+ KVP_POOL_AUTO_INTERNAL,
|
||||
+ KVP_POOL_COUNT /* Number of pools, must be last. */
|
||||
+};
|
||||
+
|
||||
+struct hv_kvp_hdr {
|
||||
+ u8 operation;
|
||||
+ u8 pool;
|
||||
+};
|
||||
+
|
||||
+struct hv_kvp_exchg_msg_value {
|
||||
+ u32 value_type;
|
||||
+ u32 key_size;
|
||||
+ u32 value_size;
|
||||
+ u8 key[HV_KVP_EXCHANGE_MAX_KEY_SIZE];
|
||||
+ u8 value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE];
|
||||
+};
|
||||
+
|
||||
+struct hv_kvp_msg_enumerate {
|
||||
+ u32 index;
|
||||
+ struct hv_kvp_exchg_msg_value data;
|
||||
+};
|
||||
+
|
||||
+struct hv_kvp_msg {
|
||||
+ struct hv_kvp_hdr kvp_hdr;
|
||||
+ struct hv_kvp_msg_enumerate kvp_data;
|
||||
+};
|
||||
+
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/uuid.h>
|
||||
@@ -870,4 +1030,9 @@ struct hyperv_service_callback {
|
||||
extern void vmbus_prep_negotiate_resp(struct icmsg_hdr *,
|
||||
struct icmsg_negotiate *, u8 *);
|
||||
|
||||
+int hv_kvp_init(struct hv_util_service *);
|
||||
+void hv_kvp_deinit(void);
|
||||
+void hv_kvp_onchannelcallback(void *);
|
||||
+
|
||||
+#endif /* __KERNEL__ */
|
||||
#endif /* _HYPERV_H */
|
||||
--
|
||||
1.7.9.5
|
||||
|
140
debian/patches/features/x86/hyperv/0045-net-hyperv-Convert-camel-cased-variables-in-rndis_fi.patch
vendored
Normal file
140
debian/patches/features/x86/hyperv/0045-net-hyperv-Convert-camel-cased-variables-in-rndis_fi.patch
vendored
Normal file
|
@ -0,0 +1,140 @@
|
|||
From: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Date: Sun, 5 Feb 2012 12:13:08 +0000
|
||||
Subject: [PATCH 45/77] net/hyperv: Convert camel cased variables in
|
||||
rndis_filter.c to lower cases
|
||||
|
||||
commit 5fccab3b66d53883a97fc65e0c33f3ebf74e8ff9 upstream.
|
||||
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Reviewed-by: Jesper Juhl <jj@chaosbits.net>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/hyperv/rndis_filter.c | 60 ++++++++++++++++++-------------------
|
||||
1 file changed, 30 insertions(+), 30 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
|
||||
index 133b7fb..a60e5e2 100644
|
||||
--- a/drivers/net/hyperv/rndis_filter.c
|
||||
+++ b/drivers/net/hyperv/rndis_filter.c
|
||||
@@ -758,66 +758,66 @@ int rndis_filter_open(struct hv_device *dev)
|
||||
|
||||
int rndis_filter_close(struct hv_device *dev)
|
||||
{
|
||||
- struct netvsc_device *netDevice = hv_get_drvdata(dev);
|
||||
+ struct netvsc_device *nvdev = hv_get_drvdata(dev);
|
||||
|
||||
- if (!netDevice)
|
||||
+ if (!nvdev)
|
||||
return -EINVAL;
|
||||
|
||||
- return rndis_filter_close_device(netDevice->extension);
|
||||
+ return rndis_filter_close_device(nvdev->extension);
|
||||
}
|
||||
|
||||
int rndis_filter_send(struct hv_device *dev,
|
||||
struct hv_netvsc_packet *pkt)
|
||||
{
|
||||
int ret;
|
||||
- struct rndis_filter_packet *filterPacket;
|
||||
- struct rndis_message *rndisMessage;
|
||||
- struct rndis_packet *rndisPacket;
|
||||
- u32 rndisMessageSize;
|
||||
+ struct rndis_filter_packet *filter_pkt;
|
||||
+ struct rndis_message *rndis_msg;
|
||||
+ struct rndis_packet *rndis_pkt;
|
||||
+ u32 rndis_msg_size;
|
||||
|
||||
/* Add the rndis header */
|
||||
- filterPacket = (struct rndis_filter_packet *)pkt->extension;
|
||||
+ filter_pkt = (struct rndis_filter_packet *)pkt->extension;
|
||||
|
||||
- memset(filterPacket, 0, sizeof(struct rndis_filter_packet));
|
||||
+ memset(filter_pkt, 0, sizeof(struct rndis_filter_packet));
|
||||
|
||||
- rndisMessage = &filterPacket->msg;
|
||||
- rndisMessageSize = RNDIS_MESSAGE_SIZE(struct rndis_packet);
|
||||
+ rndis_msg = &filter_pkt->msg;
|
||||
+ rndis_msg_size = RNDIS_MESSAGE_SIZE(struct rndis_packet);
|
||||
|
||||
- rndisMessage->ndis_msg_type = REMOTE_NDIS_PACKET_MSG;
|
||||
- rndisMessage->msg_len = pkt->total_data_buflen +
|
||||
- rndisMessageSize;
|
||||
+ rndis_msg->ndis_msg_type = REMOTE_NDIS_PACKET_MSG;
|
||||
+ rndis_msg->msg_len = pkt->total_data_buflen +
|
||||
+ rndis_msg_size;
|
||||
|
||||
- rndisPacket = &rndisMessage->msg.pkt;
|
||||
- rndisPacket->data_offset = sizeof(struct rndis_packet);
|
||||
- rndisPacket->data_len = pkt->total_data_buflen;
|
||||
+ rndis_pkt = &rndis_msg->msg.pkt;
|
||||
+ rndis_pkt->data_offset = sizeof(struct rndis_packet);
|
||||
+ rndis_pkt->data_len = pkt->total_data_buflen;
|
||||
|
||||
pkt->is_data_pkt = true;
|
||||
- pkt->page_buf[0].pfn = virt_to_phys(rndisMessage) >> PAGE_SHIFT;
|
||||
+ pkt->page_buf[0].pfn = virt_to_phys(rndis_msg) >> PAGE_SHIFT;
|
||||
pkt->page_buf[0].offset =
|
||||
- (unsigned long)rndisMessage & (PAGE_SIZE-1);
|
||||
- pkt->page_buf[0].len = rndisMessageSize;
|
||||
+ (unsigned long)rndis_msg & (PAGE_SIZE-1);
|
||||
+ pkt->page_buf[0].len = rndis_msg_size;
|
||||
|
||||
/* Add one page_buf if the rndis msg goes beyond page boundary */
|
||||
- if (pkt->page_buf[0].offset + rndisMessageSize > PAGE_SIZE) {
|
||||
+ if (pkt->page_buf[0].offset + rndis_msg_size > PAGE_SIZE) {
|
||||
int i;
|
||||
for (i = pkt->page_buf_cnt; i > 1; i--)
|
||||
pkt->page_buf[i] = pkt->page_buf[i-1];
|
||||
pkt->page_buf_cnt++;
|
||||
pkt->page_buf[0].len = PAGE_SIZE - pkt->page_buf[0].offset;
|
||||
pkt->page_buf[1].pfn = virt_to_phys((void *)((ulong)
|
||||
- rndisMessage + pkt->page_buf[0].len)) >> PAGE_SHIFT;
|
||||
+ rndis_msg + pkt->page_buf[0].len)) >> PAGE_SHIFT;
|
||||
pkt->page_buf[1].offset = 0;
|
||||
- pkt->page_buf[1].len = rndisMessageSize - pkt->page_buf[0].len;
|
||||
+ pkt->page_buf[1].len = rndis_msg_size - pkt->page_buf[0].len;
|
||||
}
|
||||
|
||||
/* Save the packet send completion and context */
|
||||
- filterPacket->completion = pkt->completion.send.send_completion;
|
||||
- filterPacket->completion_ctx =
|
||||
+ filter_pkt->completion = pkt->completion.send.send_completion;
|
||||
+ filter_pkt->completion_ctx =
|
||||
pkt->completion.send.send_completion_ctx;
|
||||
|
||||
/* Use ours */
|
||||
pkt->completion.send.send_completion = rndis_filter_send_completion;
|
||||
- pkt->completion.send.send_completion_ctx = filterPacket;
|
||||
+ pkt->completion.send.send_completion_ctx = filter_pkt;
|
||||
|
||||
ret = netvsc_send(dev, pkt);
|
||||
if (ret != 0) {
|
||||
@@ -826,9 +826,9 @@ int rndis_filter_send(struct hv_device *dev,
|
||||
* above
|
||||
*/
|
||||
pkt->completion.send.send_completion =
|
||||
- filterPacket->completion;
|
||||
+ filter_pkt->completion;
|
||||
pkt->completion.send.send_completion_ctx =
|
||||
- filterPacket->completion_ctx;
|
||||
+ filter_pkt->completion_ctx;
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -836,10 +836,10 @@ int rndis_filter_send(struct hv_device *dev,
|
||||
|
||||
static void rndis_filter_send_completion(void *ctx)
|
||||
{
|
||||
- struct rndis_filter_packet *filterPacket = ctx;
|
||||
+ struct rndis_filter_packet *filter_pkt = ctx;
|
||||
|
||||
/* Pass it back to the original handler */
|
||||
- filterPacket->completion(filterPacket->completion_ctx);
|
||||
+ filter_pkt->completion(filter_pkt->completion_ctx);
|
||||
}
|
||||
|
||||
|
||||
--
|
||||
1.7.9.5
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
From: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Date: Sun, 5 Feb 2012 12:13:09 +0000
|
||||
Subject: [PATCH 46/77] net/hyperv: Correct the assignment in
|
||||
netvsc_recv_callback()
|
||||
|
||||
commit 6f4c44460750dd4eb9926a58ab1ad0ceacef8284 upstream.
|
||||
|
||||
The first assignment to variable "net" is wrong, but overridden by the
|
||||
latter assignments. So the bug isn't manifested.
|
||||
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/hyperv/netvsc_drv.c | 7 ++-----
|
||||
1 file changed, 2 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
|
||||
index 466c58a..0ae7a1a 100644
|
||||
--- a/drivers/net/hyperv/netvsc_drv.c
|
||||
+++ b/drivers/net/hyperv/netvsc_drv.c
|
||||
@@ -267,13 +267,10 @@ void netvsc_linkstatus_callback(struct hv_device *device_obj,
|
||||
int netvsc_recv_callback(struct hv_device *device_obj,
|
||||
struct hv_netvsc_packet *packet)
|
||||
{
|
||||
- struct net_device *net = dev_get_drvdata(&device_obj->device);
|
||||
+ struct net_device *net;
|
||||
struct sk_buff *skb;
|
||||
- struct netvsc_device *net_device;
|
||||
-
|
||||
- net_device = hv_get_drvdata(device_obj);
|
||||
- net = net_device->ndev;
|
||||
|
||||
+ net = ((struct netvsc_device *)hv_get_drvdata(device_obj))->ndev;
|
||||
if (!net) {
|
||||
netdev_err(net, "got receive callback but net device"
|
||||
" not initialized yet\n");
|
||||
--
|
||||
1.7.9.5
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
From: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Date: Sun, 5 Feb 2012 12:13:10 +0000
|
||||
Subject: [PATCH 47/77] net/hyperv: Remove the unnecessary memset in
|
||||
rndis_filter_send()
|
||||
|
||||
commit bce60806de882cf15ad3a80a51e9878863a8fced upstream.
|
||||
|
||||
The memory has been allocated by kzalloc, so it's unnecessary to memset
|
||||
again.
|
||||
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/hyperv/rndis_filter.c | 2 --
|
||||
1 file changed, 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
|
||||
index a60e5e2..136efd8 100644
|
||||
--- a/drivers/net/hyperv/rndis_filter.c
|
||||
+++ b/drivers/net/hyperv/rndis_filter.c
|
||||
@@ -778,8 +778,6 @@ int rndis_filter_send(struct hv_device *dev,
|
||||
/* Add the rndis header */
|
||||
filter_pkt = (struct rndis_filter_packet *)pkt->extension;
|
||||
|
||||
- memset(filter_pkt, 0, sizeof(struct rndis_filter_packet));
|
||||
-
|
||||
rndis_msg = &filter_pkt->msg;
|
||||
rndis_msg_size = RNDIS_MESSAGE_SIZE(struct rndis_packet);
|
||||
|
||||
--
|
||||
1.7.9.5
|
||||
|
170
debian/patches/features/x86/hyperv/0048-Staging-hv-storvsc-Cleanup-some-comments.patch
vendored
Normal file
170
debian/patches/features/x86/hyperv/0048-Staging-hv-storvsc-Cleanup-some-comments.patch
vendored
Normal file
|
@ -0,0 +1,170 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Thu, 12 Jan 2012 12:37:54 -0800
|
||||
Subject: [PATCH 48/77] Staging: hv: storvsc: Cleanup some comments
|
||||
|
||||
commit 09f0355f0612520820ae4b2c342a26e048bef6e7 upstream.
|
||||
|
||||
Use consistent format for comments and get rid of some unnecessary
|
||||
comments.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/staging/hv/storvsc_drv.c | 57 +++++++++++++++++---------------------
|
||||
1 file changed, 26 insertions(+), 31 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
|
||||
index eb853f7..1633b03 100644
|
||||
--- a/drivers/staging/hv/storvsc_drv.c
|
||||
+++ b/drivers/staging/hv/storvsc_drv.c
|
||||
@@ -50,8 +50,10 @@ 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)");
|
||||
|
||||
-/* to alert the user that structure sizes may be mismatched even though the */
|
||||
-/* protocol versions match. */
|
||||
+/*
|
||||
+ * To alert the user that structure sizes may be mismatched even though the
|
||||
+ * protocol versions match.
|
||||
+ */
|
||||
|
||||
|
||||
#define REVISION_STRING(REVISION_) #REVISION_
|
||||
@@ -68,26 +70,36 @@ MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)");
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
-/* Major/minor macros. Minor version is in LSB, meaning that earlier flat */
|
||||
-/* version numbers will be interpreted as "0.x" (i.e., 1 becomes 0.1). */
|
||||
+/*
|
||||
+ * Major/minor macros. Minor version is in LSB, meaning that earlier flat
|
||||
+ * version numbers will be interpreted as "0.x" (i.e., 1 becomes 0.1).
|
||||
+ */
|
||||
+
|
||||
#define VMSTOR_PROTOCOL_MAJOR(VERSION_) (((VERSION_) >> 8) & 0xff)
|
||||
#define VMSTOR_PROTOCOL_MINOR(VERSION_) (((VERSION_)) & 0xff)
|
||||
#define VMSTOR_PROTOCOL_VERSION(MAJOR_, MINOR_) ((((MAJOR_) & 0xff) << 8) | \
|
||||
(((MINOR_) & 0xff)))
|
||||
#define VMSTOR_INVALID_PROTOCOL_VERSION (-1)
|
||||
|
||||
-/* Version history: */
|
||||
-/* V1 Beta 0.1 */
|
||||
-/* V1 RC < 2008/1/31 1.0 */
|
||||
-/* V1 RC > 2008/1/31 2.0 */
|
||||
+/*
|
||||
+ * Version history:
|
||||
+ * V1 Beta: 0.1
|
||||
+ * V1 RC < 2008/1/31: 1.0
|
||||
+ * V1 RC > 2008/1/31: 2.0
|
||||
+ * Win7: 4.2
|
||||
+ */
|
||||
+
|
||||
#define VMSTOR_PROTOCOL_VERSION_CURRENT VMSTOR_PROTOCOL_VERSION(4, 2)
|
||||
|
||||
|
||||
|
||||
|
||||
-/* This will get replaced with the max transfer length that is possible on */
|
||||
-/* the host adapter. */
|
||||
-/* The max transfer length will be published when we offer a vmbus channel. */
|
||||
+/*
|
||||
+ * This will get replaced with the max transfer length that is possible on
|
||||
+ * the host adapter.
|
||||
+ * The max transfer length will be published when we offer a vmbus channel.
|
||||
+ */
|
||||
+
|
||||
#define MAX_TRANSFER_LENGTH 0x40000
|
||||
#define DEFAULT_PACKET_SIZE (sizeof(struct vmdata_gpa_direct) + \
|
||||
sizeof(struct vstor_packet) + \
|
||||
@@ -211,18 +223,19 @@ struct vstor_packet {
|
||||
};
|
||||
} __packed;
|
||||
|
||||
-/* Packet flags */
|
||||
/*
|
||||
+ * Packet Flags:
|
||||
+ *
|
||||
* This flag indicates that the server should send back a completion for this
|
||||
* packet.
|
||||
*/
|
||||
+
|
||||
#define REQUEST_COMPLETION_FLAG 0x1
|
||||
|
||||
/* This is the set of flags that the vsc can set in any packets it sends */
|
||||
#define VSC_LEGAL_FLAGS (REQUEST_COMPLETION_FLAG)
|
||||
|
||||
|
||||
-/* Defines */
|
||||
|
||||
#define STORVSC_MAX_IO_REQUESTS 128
|
||||
|
||||
@@ -674,7 +687,6 @@ static int storvsc_connect_to_vsp(struct hv_device *device, u32 ring_size)
|
||||
|
||||
memset(&props, 0, sizeof(struct vmstorage_channel_properties));
|
||||
|
||||
- /* Open the channel */
|
||||
ret = vmbus_open(device->channel,
|
||||
ring_size,
|
||||
ring_size,
|
||||
@@ -1154,9 +1166,6 @@ static int storvsc_host_reset(struct hv_device *device)
|
||||
}
|
||||
|
||||
|
||||
-/*
|
||||
- * storvsc_host_reset_handler - Reset the scsi HBA
|
||||
- */
|
||||
static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd)
|
||||
{
|
||||
struct hv_host_device *host_dev = shost_priv(scmnd->device->host);
|
||||
@@ -1166,9 +1175,6 @@ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd)
|
||||
}
|
||||
|
||||
|
||||
-/*
|
||||
- * storvsc_command_completion - Command completion processing
|
||||
- */
|
||||
static void storvsc_command_completion(struct hv_storvsc_request *request)
|
||||
{
|
||||
struct storvsc_cmd_request *cmd_request =
|
||||
@@ -1262,9 +1268,6 @@ static bool storvsc_check_scsi_cmd(struct scsi_cmnd *scmnd)
|
||||
return allowed;
|
||||
}
|
||||
|
||||
-/*
|
||||
- * storvsc_queuecommand - Initiate command processing
|
||||
- */
|
||||
static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
|
||||
{
|
||||
int ret;
|
||||
@@ -1407,7 +1410,6 @@ retry_request:
|
||||
return ret;
|
||||
}
|
||||
|
||||
-/* Scsi driver */
|
||||
static struct scsi_host_template scsi_driver = {
|
||||
.module = THIS_MODULE,
|
||||
.name = "storvsc_host_t",
|
||||
@@ -1448,11 +1450,6 @@ static const struct hv_vmbus_device_id id_table[] = {
|
||||
|
||||
MODULE_DEVICE_TABLE(vmbus, id_table);
|
||||
|
||||
-
|
||||
-/*
|
||||
- * storvsc_probe - Add a new device for this driver
|
||||
- */
|
||||
-
|
||||
static int storvsc_probe(struct hv_device *device,
|
||||
const struct hv_vmbus_device_id *dev_id)
|
||||
{
|
||||
@@ -1542,8 +1539,6 @@ err_out0:
|
||||
return ret;
|
||||
}
|
||||
|
||||
-/* The one and only one */
|
||||
-
|
||||
static struct hv_driver storvsc_drv = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.id_table = id_table,
|
||||
--
|
||||
1.7.9.5
|
||||
|
80
debian/patches/features/x86/hyperv/0049-Staging-hv-storvsc-Cleanup-storvsc_probe.patch
vendored
Normal file
80
debian/patches/features/x86/hyperv/0049-Staging-hv-storvsc-Cleanup-storvsc_probe.patch
vendored
Normal file
|
@ -0,0 +1,80 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Thu, 12 Jan 2012 12:37:55 -0800
|
||||
Subject: [PATCH 49/77] Staging: hv: storvsc: Cleanup storvsc_probe()
|
||||
|
||||
commit 59d22950b274182b006e4071d6690bfbc94d7267 upstream.
|
||||
|
||||
Cleanup storvsc_probe(). As part of this cleanup, get rid of
|
||||
storvsc_get_ide_info() by inlining the necessary code.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/staging/hv/storvsc_drv.c | 30 ++++++++----------------------
|
||||
1 file changed, 8 insertions(+), 22 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
|
||||
index 1633b03..7561d29 100644
|
||||
--- a/drivers/staging/hv/storvsc_drv.c
|
||||
+++ b/drivers/staging/hv/storvsc_drv.c
|
||||
@@ -791,18 +791,6 @@ static int storvsc_do_io(struct hv_device *device,
|
||||
return ret;
|
||||
}
|
||||
|
||||
-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)
|
||||
{
|
||||
struct stor_mem_pools *memp;
|
||||
@@ -1457,7 +1445,6 @@ static int storvsc_probe(struct hv_device *device,
|
||||
struct Scsi_Host *host;
|
||||
struct hv_host_device *host_dev;
|
||||
bool dev_is_ide = ((dev_id->driver_data == IDE_GUID) ? true : false);
|
||||
- int path = 0;
|
||||
int target = 0;
|
||||
struct storvsc_device *stor_device;
|
||||
|
||||
@@ -1490,9 +1477,6 @@ static int storvsc_probe(struct hv_device *device,
|
||||
if (ret)
|
||||
goto err_out1;
|
||||
|
||||
- if (dev_is_ide)
|
||||
- storvsc_get_ide_info(device, &target, &path);
|
||||
-
|
||||
host_dev->path = stor_device->path_id;
|
||||
host_dev->target = stor_device->target_id;
|
||||
|
||||
@@ -1512,12 +1496,14 @@ static int storvsc_probe(struct hv_device *device,
|
||||
|
||||
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_out2;
|
||||
+ } else {
|
||||
+ target = (device->dev_instance.b[5] << 8 |
|
||||
+ device->dev_instance.b[4]);
|
||||
+ ret = scsi_add_device(host, 0, target, 0);
|
||||
+ if (ret) {
|
||||
+ scsi_remove_host(host);
|
||||
+ goto err_out2;
|
||||
+ }
|
||||
}
|
||||
return 0;
|
||||
|
||||
--
|
||||
1.7.9.5
|
||||
|
129
debian/patches/features/x86/hyperv/0050-Staging-hv-storvsc-Cleanup-storvsc_queuecommand.patch
vendored
Normal file
129
debian/patches/features/x86/hyperv/0050-Staging-hv-storvsc-Cleanup-storvsc_queuecommand.patch
vendored
Normal file
|
@ -0,0 +1,129 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Thu, 12 Jan 2012 12:37:56 -0800
|
||||
Subject: [PATCH 50/77] Staging: hv: storvsc: Cleanup storvsc_queuecommand()
|
||||
|
||||
commit c77b63b639f52b2e92d0bbaa94f33a78939f3e7c upstream.
|
||||
|
||||
Cleanup storvsc_queuecommand(). As part of this cleanup, rename the function to
|
||||
check if the scsi command can be sent to the host, consolidate error recovery
|
||||
and get rid of some dead code.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/staging/hv/storvsc_drv.c | 48 +++++++++++++++++---------------------
|
||||
1 file changed, 22 insertions(+), 26 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
|
||||
index 7561d29..71e50c3 100644
|
||||
--- a/drivers/staging/hv/storvsc_drv.c
|
||||
+++ b/drivers/staging/hv/storvsc_drv.c
|
||||
@@ -1239,13 +1239,16 @@ static void storvsc_command_completion(struct hv_storvsc_request *request)
|
||||
mempool_free(cmd_request, memp->request_mempool);
|
||||
}
|
||||
|
||||
-static bool storvsc_check_scsi_cmd(struct scsi_cmnd *scmnd)
|
||||
+static bool storvsc_scsi_cmd_ok(struct scsi_cmnd *scmnd)
|
||||
{
|
||||
bool allowed = true;
|
||||
u8 scsi_op = scmnd->cmnd[0];
|
||||
|
||||
switch (scsi_op) {
|
||||
- /* smartd sends this command, which will offline the device */
|
||||
+ /*
|
||||
+ * smartd sends this command and the host does not handle
|
||||
+ * this. So, don't send it.
|
||||
+ */
|
||||
case SET_WINDOW:
|
||||
scmnd->result = ILLEGAL_REQUEST << 16;
|
||||
allowed = false;
|
||||
@@ -1270,32 +1273,26 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
|
||||
struct vmscsi_request *vm_srb;
|
||||
struct stor_mem_pools *memp = scmnd->device->hostdata;
|
||||
|
||||
- if (storvsc_check_scsi_cmd(scmnd) == false) {
|
||||
+ if (!storvsc_scsi_cmd_ok(scmnd)) {
|
||||
scmnd->scsi_done(scmnd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
- /* If retrying, no need to prep the cmd */
|
||||
- if (scmnd->host_scribble) {
|
||||
-
|
||||
- cmd_request =
|
||||
- (struct storvsc_cmd_request *)scmnd->host_scribble;
|
||||
-
|
||||
- goto retry_request;
|
||||
- }
|
||||
-
|
||||
request_size = sizeof(struct storvsc_cmd_request);
|
||||
|
||||
cmd_request = mempool_alloc(memp->request_mempool,
|
||||
GFP_ATOMIC);
|
||||
+
|
||||
+ /*
|
||||
+ * We might be invoked in an interrupt context; hence
|
||||
+ * mempool_alloc() can fail.
|
||||
+ */
|
||||
if (!cmd_request)
|
||||
return SCSI_MLQUEUE_DEVICE_BUSY;
|
||||
|
||||
memset(cmd_request, 0, sizeof(struct storvsc_cmd_request));
|
||||
|
||||
/* Setup the cmd request */
|
||||
- cmd_request->bounce_sgl_count = 0;
|
||||
- cmd_request->bounce_sgl = NULL;
|
||||
cmd_request->cmd = scmnd;
|
||||
|
||||
scmnd->host_scribble = (unsigned char *)cmd_request;
|
||||
@@ -1344,11 +1341,8 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
|
||||
scsi_bufflen(scmnd),
|
||||
vm_srb->data_in);
|
||||
if (!cmd_request->bounce_sgl) {
|
||||
- scmnd->host_scribble = NULL;
|
||||
- mempool_free(cmd_request,
|
||||
- memp->request_mempool);
|
||||
-
|
||||
- return SCSI_MLQUEUE_HOST_BUSY;
|
||||
+ ret = SCSI_MLQUEUE_HOST_BUSY;
|
||||
+ goto queue_error;
|
||||
}
|
||||
|
||||
cmd_request->bounce_sgl_count =
|
||||
@@ -1377,24 +1371,26 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
|
||||
virt_to_phys(scsi_sglist(scmnd)) >> PAGE_SHIFT;
|
||||
}
|
||||
|
||||
-retry_request:
|
||||
/* Invokes the vsc to start an IO */
|
||||
ret = storvsc_do_io(dev, &cmd_request->request);
|
||||
|
||||
if (ret == -EAGAIN) {
|
||||
/* no more space */
|
||||
|
||||
- if (cmd_request->bounce_sgl_count)
|
||||
+ if (cmd_request->bounce_sgl_count) {
|
||||
destroy_bounce_buffer(cmd_request->bounce_sgl,
|
||||
cmd_request->bounce_sgl_count);
|
||||
|
||||
- mempool_free(cmd_request, memp->request_mempool);
|
||||
-
|
||||
- scmnd->host_scribble = NULL;
|
||||
-
|
||||
- ret = SCSI_MLQUEUE_DEVICE_BUSY;
|
||||
+ ret = SCSI_MLQUEUE_DEVICE_BUSY;
|
||||
+ goto queue_error;
|
||||
+ }
|
||||
}
|
||||
|
||||
+ return 0;
|
||||
+
|
||||
+queue_error:
|
||||
+ mempool_free(cmd_request, memp->request_mempool);
|
||||
+ scmnd->host_scribble = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.9.5
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Thu, 12 Jan 2012 12:37:57 -0800
|
||||
Subject: [PATCH 51/77] Staging: hv: storvsc: Introduce defines for srb status
|
||||
codes
|
||||
|
||||
commit 160463204f541cea112fd4d68422f297bd98ec51 upstream.
|
||||
|
||||
Introduce defines for srb status codes.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/staging/hv/storvsc_drv.c | 21 ++++++++++++++++-----
|
||||
1 file changed, 16 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
|
||||
index 71e50c3..979f25b 100644
|
||||
--- a/drivers/staging/hv/storvsc_drv.c
|
||||
+++ b/drivers/staging/hv/storvsc_drv.c
|
||||
@@ -257,6 +257,16 @@ enum storvsc_request_type {
|
||||
UNKNOWN_TYPE,
|
||||
};
|
||||
|
||||
+/*
|
||||
+ * SRB status codes and masks; a subset of the codes used here.
|
||||
+ */
|
||||
+
|
||||
+#define SRB_STATUS_AUTOSENSE_VALID 0x80
|
||||
+#define SRB_STATUS_INVALID_LUN 0x20
|
||||
+#define SRB_STATUS_SUCCESS 0x01
|
||||
+#define SRB_STATUS_ERROR 0x04
|
||||
+
|
||||
+
|
||||
|
||||
struct hv_storvsc_request {
|
||||
struct hv_device *device;
|
||||
@@ -561,7 +571,7 @@ static void storvsc_on_io_completion(struct hv_device *device,
|
||||
if ((stor_pkt->vm_srb.cdb[0] == INQUIRY) ||
|
||||
(stor_pkt->vm_srb.cdb[0] == MODE_SENSE)) {
|
||||
vstor_packet->vm_srb.scsi_status = 0;
|
||||
- vstor_packet->vm_srb.srb_status = 0x1;
|
||||
+ vstor_packet->vm_srb.srb_status = SRB_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -572,7 +582,7 @@ static void storvsc_on_io_completion(struct hv_device *device,
|
||||
vstor_packet->vm_srb.sense_info_length;
|
||||
|
||||
if (vstor_packet->vm_srb.scsi_status != 0 ||
|
||||
- vstor_packet->vm_srb.srb_status != 1){
|
||||
+ vstor_packet->vm_srb.srb_status != SRB_STATUS_SUCCESS){
|
||||
dev_warn(&device->device,
|
||||
"cmd 0x%x scsi status 0x%x srb status 0x%x\n",
|
||||
stor_pkt->vm_srb.cdb[0],
|
||||
@@ -582,7 +592,8 @@ static void storvsc_on_io_completion(struct hv_device *device,
|
||||
|
||||
if ((vstor_packet->vm_srb.scsi_status & 0xFF) == 0x02) {
|
||||
/* CHECK_CONDITION */
|
||||
- if (vstor_packet->vm_srb.srb_status & 0x80) {
|
||||
+ if (vstor_packet->vm_srb.srb_status &
|
||||
+ SRB_STATUS_AUTOSENSE_VALID) {
|
||||
/* autosense data available */
|
||||
dev_warn(&device->device,
|
||||
"stor pkt %p autosense data valid - len %d\n",
|
||||
@@ -1191,7 +1202,7 @@ static void storvsc_command_completion(struct hv_storvsc_request *request)
|
||||
* error recovery strategies would have already been
|
||||
* deployed on the host side.
|
||||
*/
|
||||
- if (vm_srb->srb_status == 0x4)
|
||||
+ if (vm_srb->srb_status == SRB_STATUS_ERROR)
|
||||
scmnd->result = DID_TARGET_FAILURE << 16;
|
||||
else
|
||||
scmnd->result = vm_srb->scsi_status;
|
||||
@@ -1199,7 +1210,7 @@ static void storvsc_command_completion(struct hv_storvsc_request *request)
|
||||
/*
|
||||
* If the LUN is invalid; remove the device.
|
||||
*/
|
||||
- if (vm_srb->srb_status == 0x20) {
|
||||
+ if (vm_srb->srb_status == SRB_STATUS_INVALID_LUN) {
|
||||
struct storvsc_device *stor_dev;
|
||||
struct hv_device *dev = host_dev->dev;
|
||||
struct Scsi_Host *host;
|
||||
--
|
||||
1.7.9.5
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Thu, 12 Jan 2012 12:37:58 -0800
|
||||
Subject: [PATCH 52/77] Staging: hv: storvsc: Cleanup
|
||||
storvsc_host_reset_handler()
|
||||
|
||||
commit 4b270c8b23722128adedb5694097aea367284ce1 upstream.
|
||||
|
||||
Cleanup storvsc_host_reset_handler() by getting rid of storvsc_host_reset().
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/staging/hv/storvsc_drv.c | 14 ++++----------
|
||||
1 file changed, 4 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
|
||||
index 979f25b..8340387 100644
|
||||
--- a/drivers/staging/hv/storvsc_drv.c
|
||||
+++ b/drivers/staging/hv/storvsc_drv.c
|
||||
@@ -1122,8 +1122,11 @@ static int storvsc_get_chs(struct scsi_device *sdev, struct block_device * bdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int storvsc_host_reset(struct hv_device *device)
|
||||
+static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd)
|
||||
{
|
||||
+ struct hv_host_device *host_dev = shost_priv(scmnd->device->host);
|
||||
+ struct hv_device *device = host_dev->dev;
|
||||
+
|
||||
struct storvsc_device *stor_device;
|
||||
struct hv_storvsc_request *request;
|
||||
struct vstor_packet *vstor_packet;
|
||||
@@ -1165,15 +1168,6 @@ static int storvsc_host_reset(struct hv_device *device)
|
||||
}
|
||||
|
||||
|
||||
-static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd)
|
||||
-{
|
||||
- struct hv_host_device *host_dev = shost_priv(scmnd->device->host);
|
||||
- struct hv_device *dev = host_dev->dev;
|
||||
-
|
||||
- return storvsc_host_reset(dev);
|
||||
-}
|
||||
-
|
||||
-
|
||||
static void storvsc_command_completion(struct hv_storvsc_request *request)
|
||||
{
|
||||
struct storvsc_cmd_request *cmd_request =
|
||||
--
|
||||
1.7.9.5
|
||||
|
65
debian/patches/features/x86/hyperv/0053-Staging-hv-storvsc-Move-and-cleanup-storvsc_remove.patch
vendored
Normal file
65
debian/patches/features/x86/hyperv/0053-Staging-hv-storvsc-Move-and-cleanup-storvsc_remove.patch
vendored
Normal file
|
@ -0,0 +1,65 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Thu, 12 Jan 2012 12:37:59 -0800
|
||||
Subject: [PATCH 53/77] Staging: hv: storvsc: Move and cleanup
|
||||
storvsc_remove()
|
||||
|
||||
commit ddcbf65e484c3473d3e808718ddb6c8166822c4c upstream.
|
||||
|
||||
Relocate the storvsc_remove() function to a different location in the file
|
||||
and invoke scsi_host_put() only after all the cleanup.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/staging/hv/storvsc_drv.c | 28 ++++++++++++----------------
|
||||
1 file changed, 12 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
|
||||
index 8340387..e0e471c 100644
|
||||
--- a/drivers/staging/hv/storvsc_drv.c
|
||||
+++ b/drivers/staging/hv/storvsc_drv.c
|
||||
@@ -1083,22 +1083,6 @@ static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl,
|
||||
return total_copied;
|
||||
}
|
||||
|
||||
-
|
||||
-static int storvsc_remove(struct hv_device *dev)
|
||||
-{
|
||||
- struct storvsc_device *stor_device = hv_get_drvdata(dev);
|
||||
- struct Scsi_Host *host = stor_device->host;
|
||||
-
|
||||
- scsi_remove_host(host);
|
||||
-
|
||||
- scsi_host_put(host);
|
||||
-
|
||||
- storvsc_dev_remove(dev);
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-
|
||||
static int storvsc_get_chs(struct scsi_device *sdev, struct block_device * bdev,
|
||||
sector_t capacity, int *info)
|
||||
{
|
||||
@@ -1526,6 +1510,18 @@ err_out0:
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static int storvsc_remove(struct hv_device *dev)
|
||||
+{
|
||||
+ struct storvsc_device *stor_device = hv_get_drvdata(dev);
|
||||
+ struct Scsi_Host *host = stor_device->host;
|
||||
+
|
||||
+ scsi_remove_host(host);
|
||||
+ storvsc_dev_remove(dev);
|
||||
+ scsi_host_put(host);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static struct hv_driver storvsc_drv = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.id_table = id_table,
|
||||
--
|
||||
1.7.9.5
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Thu, 12 Jan 2012 12:38:00 -0800
|
||||
Subject: [PATCH 54/77] Staging: hv: storvsc: Add a comment to explain
|
||||
life-cycle management
|
||||
|
||||
commit a8c18c573bf896f81dbcd68fdb81d81d4200dcad upstream.
|
||||
|
||||
Add a comment to explain life-cycle management and fix format issue.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/staging/hv/storvsc_drv.c | 17 ++++++++++++++++-
|
||||
1 file changed, 16 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
|
||||
index e0e471c..204b3ca 100644
|
||||
--- a/drivers/staging/hv/storvsc_drv.c
|
||||
+++ b/drivers/staging/hv/storvsc_drv.c
|
||||
@@ -375,6 +375,21 @@ done:
|
||||
kfree(wrk);
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * We can get incoming messages from the host that are not in response to
|
||||
+ * messages that we have sent out. An example of this would be messages
|
||||
+ * received by the guest to notify dynamic addition/removal of LUNs. To
|
||||
+ * deal with potential race conditions where the driver may be in the
|
||||
+ * midst of being unloaded when we might receive an unsolicited message
|
||||
+ * from the host, we have implemented a mechanism to gurantee sequential
|
||||
+ * consistency:
|
||||
+ *
|
||||
+ * 1) Once the device is marked as being destroyed, we will fail all
|
||||
+ * outgoing messages.
|
||||
+ * 2) We permit incoming messages when the device is being destroyed,
|
||||
+ * only to properly account for messages already sent out.
|
||||
+ */
|
||||
+
|
||||
static inline struct storvsc_device *get_out_stor_device(
|
||||
struct hv_device *device)
|
||||
{
|
||||
@@ -569,7 +584,7 @@ static void storvsc_on_io_completion(struct hv_device *device,
|
||||
*/
|
||||
|
||||
if ((stor_pkt->vm_srb.cdb[0] == INQUIRY) ||
|
||||
- (stor_pkt->vm_srb.cdb[0] == MODE_SENSE)) {
|
||||
+ (stor_pkt->vm_srb.cdb[0] == MODE_SENSE)) {
|
||||
vstor_packet->vm_srb.scsi_status = 0;
|
||||
vstor_packet->vm_srb.srb_status = SRB_STATUS_SUCCESS;
|
||||
}
|
||||
--
|
||||
1.7.9.5
|
||||
|
706
debian/patches/features/x86/hyperv/0055-Staging-hv-storvsc-Get-rid-of-the-on_io_completion-i.patch
vendored
Normal file
706
debian/patches/features/x86/hyperv/0055-Staging-hv-storvsc-Get-rid-of-the-on_io_completion-i.patch
vendored
Normal file
|
@ -0,0 +1,706 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Thu, 12 Jan 2012 12:38:01 -0800
|
||||
Subject: [PATCH 55/77] Staging: hv: storvsc: Get rid of the on_io_completion
|
||||
in hv_storvsc_request
|
||||
|
||||
commit 2707388c7c5c6edf4e646a9013f6b7aa195fb174 upstream.
|
||||
|
||||
Get rid of the on_io_completion field in struct hv_storvsc_request. As part of this
|
||||
relocate the bounce buffer handling code (to avoid having forward declarations).
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/staging/hv/storvsc_drv.c | 630 +++++++++++++++++++-------------------
|
||||
1 file changed, 313 insertions(+), 317 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
|
||||
index 204b3ca..7c9fa19 100644
|
||||
--- a/drivers/staging/hv/storvsc_drv.c
|
||||
+++ b/drivers/staging/hv/storvsc_drv.c
|
||||
@@ -276,7 +276,6 @@ struct hv_storvsc_request {
|
||||
|
||||
unsigned char *sense_buffer;
|
||||
void *context;
|
||||
- void (*on_io_completion)(struct hv_storvsc_request *request);
|
||||
struct hv_multipage_buffer data_buffer;
|
||||
|
||||
struct vstor_packet vstor_packet;
|
||||
@@ -436,6 +435,227 @@ get_in_err:
|
||||
|
||||
}
|
||||
|
||||
+static void destroy_bounce_buffer(struct scatterlist *sgl,
|
||||
+ unsigned int sg_count)
|
||||
+{
|
||||
+ int i;
|
||||
+ struct page *page_buf;
|
||||
+
|
||||
+ for (i = 0; i < sg_count; i++) {
|
||||
+ page_buf = sg_page((&sgl[i]));
|
||||
+ if (page_buf != NULL)
|
||||
+ __free_page(page_buf);
|
||||
+ }
|
||||
+
|
||||
+ kfree(sgl);
|
||||
+}
|
||||
+
|
||||
+static int do_bounce_buffer(struct scatterlist *sgl, unsigned int sg_count)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ /* No need to check */
|
||||
+ if (sg_count < 2)
|
||||
+ return -1;
|
||||
+
|
||||
+ /* We have at least 2 sg entries */
|
||||
+ for (i = 0; i < sg_count; i++) {
|
||||
+ if (i == 0) {
|
||||
+ /* make sure 1st one does not have hole */
|
||||
+ if (sgl[i].offset + sgl[i].length != PAGE_SIZE)
|
||||
+ return i;
|
||||
+ } else if (i == sg_count - 1) {
|
||||
+ /* make sure last one does not have hole */
|
||||
+ if (sgl[i].offset != 0)
|
||||
+ return i;
|
||||
+ } else {
|
||||
+ /* make sure no hole in the middle */
|
||||
+ if (sgl[i].length != PAGE_SIZE || sgl[i].offset != 0)
|
||||
+ return i;
|
||||
+ }
|
||||
+ }
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
+static struct scatterlist *create_bounce_buffer(struct scatterlist *sgl,
|
||||
+ unsigned int sg_count,
|
||||
+ unsigned int len,
|
||||
+ int write)
|
||||
+{
|
||||
+ int i;
|
||||
+ int num_pages;
|
||||
+ struct scatterlist *bounce_sgl;
|
||||
+ struct page *page_buf;
|
||||
+ unsigned int buf_len = ((write == WRITE_TYPE) ? 0 : PAGE_SIZE);
|
||||
+
|
||||
+ num_pages = ALIGN(len, PAGE_SIZE) >> PAGE_SHIFT;
|
||||
+
|
||||
+ bounce_sgl = kcalloc(num_pages, sizeof(struct scatterlist), GFP_ATOMIC);
|
||||
+ if (!bounce_sgl)
|
||||
+ return NULL;
|
||||
+
|
||||
+ for (i = 0; i < num_pages; i++) {
|
||||
+ page_buf = alloc_page(GFP_ATOMIC);
|
||||
+ if (!page_buf)
|
||||
+ goto cleanup;
|
||||
+ sg_set_page(&bounce_sgl[i], page_buf, buf_len, 0);
|
||||
+ }
|
||||
+
|
||||
+ return bounce_sgl;
|
||||
+
|
||||
+cleanup:
|
||||
+ destroy_bounce_buffer(bounce_sgl, num_pages);
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+/* Assume the original sgl has enough room */
|
||||
+static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl,
|
||||
+ struct scatterlist *bounce_sgl,
|
||||
+ unsigned int orig_sgl_count,
|
||||
+ unsigned int bounce_sgl_count)
|
||||
+{
|
||||
+ int i;
|
||||
+ int j = 0;
|
||||
+ unsigned long src, dest;
|
||||
+ unsigned int srclen, destlen, copylen;
|
||||
+ unsigned int total_copied = 0;
|
||||
+ unsigned long bounce_addr = 0;
|
||||
+ unsigned long dest_addr = 0;
|
||||
+ unsigned long flags;
|
||||
+
|
||||
+ local_irq_save(flags);
|
||||
+
|
||||
+ for (i = 0; i < orig_sgl_count; i++) {
|
||||
+ dest_addr = (unsigned long)kmap_atomic(sg_page((&orig_sgl[i])),
|
||||
+ KM_IRQ0) + orig_sgl[i].offset;
|
||||
+ dest = dest_addr;
|
||||
+ destlen = orig_sgl[i].length;
|
||||
+
|
||||
+ if (bounce_addr == 0)
|
||||
+ bounce_addr =
|
||||
+ (unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])),
|
||||
+ KM_IRQ0);
|
||||
+
|
||||
+ while (destlen) {
|
||||
+ src = bounce_addr + bounce_sgl[j].offset;
|
||||
+ srclen = bounce_sgl[j].length - bounce_sgl[j].offset;
|
||||
+
|
||||
+ copylen = min(srclen, destlen);
|
||||
+ memcpy((void *)dest, (void *)src, copylen);
|
||||
+
|
||||
+ total_copied += copylen;
|
||||
+ bounce_sgl[j].offset += copylen;
|
||||
+ destlen -= copylen;
|
||||
+ dest += copylen;
|
||||
+
|
||||
+ if (bounce_sgl[j].offset == bounce_sgl[j].length) {
|
||||
+ /* full */
|
||||
+ kunmap_atomic((void *)bounce_addr, KM_IRQ0);
|
||||
+ j++;
|
||||
+
|
||||
+ /*
|
||||
+ * It is possible that the number of elements
|
||||
+ * in the bounce buffer may not be equal to
|
||||
+ * the number of elements in the original
|
||||
+ * scatter list. Handle this correctly.
|
||||
+ */
|
||||
+
|
||||
+ if (j == bounce_sgl_count) {
|
||||
+ /*
|
||||
+ * We are done; cleanup and return.
|
||||
+ */
|
||||
+ kunmap_atomic((void *)(dest_addr -
|
||||
+ orig_sgl[i].offset),
|
||||
+ KM_IRQ0);
|
||||
+ local_irq_restore(flags);
|
||||
+ return total_copied;
|
||||
+ }
|
||||
+
|
||||
+ /* if we need to use another bounce buffer */
|
||||
+ if (destlen || i != orig_sgl_count - 1)
|
||||
+ bounce_addr =
|
||||
+ (unsigned long)kmap_atomic(
|
||||
+ sg_page((&bounce_sgl[j])), KM_IRQ0);
|
||||
+ } else if (destlen == 0 && i == orig_sgl_count - 1) {
|
||||
+ /* unmap the last bounce that is < PAGE_SIZE */
|
||||
+ kunmap_atomic((void *)bounce_addr, KM_IRQ0);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ kunmap_atomic((void *)(dest_addr - orig_sgl[i].offset),
|
||||
+ KM_IRQ0);
|
||||
+ }
|
||||
+
|
||||
+ local_irq_restore(flags);
|
||||
+
|
||||
+ return total_copied;
|
||||
+}
|
||||
+
|
||||
+/* Assume the bounce_sgl has enough room ie using the create_bounce_buffer() */
|
||||
+static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl,
|
||||
+ struct scatterlist *bounce_sgl,
|
||||
+ unsigned int orig_sgl_count)
|
||||
+{
|
||||
+ int i;
|
||||
+ int j = 0;
|
||||
+ unsigned long src, dest;
|
||||
+ unsigned int srclen, destlen, copylen;
|
||||
+ unsigned int total_copied = 0;
|
||||
+ unsigned long bounce_addr = 0;
|
||||
+ unsigned long src_addr = 0;
|
||||
+ unsigned long flags;
|
||||
+
|
||||
+ local_irq_save(flags);
|
||||
+
|
||||
+ for (i = 0; i < orig_sgl_count; i++) {
|
||||
+ src_addr = (unsigned long)kmap_atomic(sg_page((&orig_sgl[i])),
|
||||
+ KM_IRQ0) + orig_sgl[i].offset;
|
||||
+ src = src_addr;
|
||||
+ srclen = orig_sgl[i].length;
|
||||
+
|
||||
+ if (bounce_addr == 0)
|
||||
+ bounce_addr =
|
||||
+ (unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])),
|
||||
+ KM_IRQ0);
|
||||
+
|
||||
+ while (srclen) {
|
||||
+ /* assume bounce offset always == 0 */
|
||||
+ dest = bounce_addr + bounce_sgl[j].length;
|
||||
+ destlen = PAGE_SIZE - bounce_sgl[j].length;
|
||||
+
|
||||
+ copylen = min(srclen, destlen);
|
||||
+ memcpy((void *)dest, (void *)src, copylen);
|
||||
+
|
||||
+ total_copied += copylen;
|
||||
+ bounce_sgl[j].length += copylen;
|
||||
+ srclen -= copylen;
|
||||
+ src += copylen;
|
||||
+
|
||||
+ if (bounce_sgl[j].length == PAGE_SIZE) {
|
||||
+ /* full..move to next entry */
|
||||
+ kunmap_atomic((void *)bounce_addr, KM_IRQ0);
|
||||
+ j++;
|
||||
+
|
||||
+ /* if we need to use another bounce buffer */
|
||||
+ if (srclen || i != orig_sgl_count - 1)
|
||||
+ bounce_addr =
|
||||
+ (unsigned long)kmap_atomic(
|
||||
+ sg_page((&bounce_sgl[j])), KM_IRQ0);
|
||||
+
|
||||
+ } else if (srclen == 0 && i == orig_sgl_count - 1) {
|
||||
+ /* unmap the last bounce that is < PAGE_SIZE */
|
||||
+ kunmap_atomic((void *)bounce_addr, KM_IRQ0);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ kunmap_atomic((void *)(src_addr - orig_sgl[i].offset), KM_IRQ0);
|
||||
+ }
|
||||
+
|
||||
+ local_irq_restore(flags);
|
||||
+
|
||||
+ return total_copied;
|
||||
+}
|
||||
+
|
||||
static int storvsc_channel_init(struct hv_device *device)
|
||||
{
|
||||
struct storvsc_device *stor_device;
|
||||
@@ -562,24 +782,101 @@ cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static void storvsc_on_io_completion(struct hv_device *device,
|
||||
- struct vstor_packet *vstor_packet,
|
||||
- struct hv_storvsc_request *request)
|
||||
+
|
||||
+static void storvsc_command_completion(struct hv_storvsc_request *request)
|
||||
{
|
||||
- struct storvsc_device *stor_device;
|
||||
- struct vstor_packet *stor_pkt;
|
||||
+ struct storvsc_cmd_request *cmd_request =
|
||||
+ (struct storvsc_cmd_request *)request->context;
|
||||
+ struct scsi_cmnd *scmnd = cmd_request->cmd;
|
||||
+ struct hv_host_device *host_dev = shost_priv(scmnd->device->host);
|
||||
+ void (*scsi_done_fn)(struct scsi_cmnd *);
|
||||
+ struct scsi_sense_hdr sense_hdr;
|
||||
+ struct vmscsi_request *vm_srb;
|
||||
+ struct storvsc_scan_work *wrk;
|
||||
+ struct stor_mem_pools *memp = scmnd->device->hostdata;
|
||||
|
||||
- stor_device = hv_get_drvdata(device);
|
||||
- stor_pkt = &request->vstor_packet;
|
||||
+ vm_srb = &request->vstor_packet.vm_srb;
|
||||
+ if (cmd_request->bounce_sgl_count) {
|
||||
+ if (vm_srb->data_in == READ_TYPE)
|
||||
+ copy_from_bounce_buffer(scsi_sglist(scmnd),
|
||||
+ cmd_request->bounce_sgl,
|
||||
+ scsi_sg_count(scmnd),
|
||||
+ cmd_request->bounce_sgl_count);
|
||||
+ destroy_bounce_buffer(cmd_request->bounce_sgl,
|
||||
+ cmd_request->bounce_sgl_count);
|
||||
+ }
|
||||
|
||||
/*
|
||||
- * The current SCSI handling on the host side does
|
||||
- * not correctly handle:
|
||||
- * INQUIRY command with page code parameter set to 0x80
|
||||
- * MODE_SENSE command with cmd[2] == 0x1c
|
||||
- *
|
||||
- * Setup srb and scsi status so this won't be fatal.
|
||||
- * We do this so we can distinguish truly fatal failues
|
||||
+ * If there is an error; offline the device since all
|
||||
+ * error recovery strategies would have already been
|
||||
+ * deployed on the host side.
|
||||
+ */
|
||||
+ if (vm_srb->srb_status == SRB_STATUS_ERROR)
|
||||
+ scmnd->result = DID_TARGET_FAILURE << 16;
|
||||
+ else
|
||||
+ scmnd->result = vm_srb->scsi_status;
|
||||
+
|
||||
+ /*
|
||||
+ * If the LUN is invalid; remove the device.
|
||||
+ */
|
||||
+ if (vm_srb->srb_status == SRB_STATUS_INVALID_LUN) {
|
||||
+ struct storvsc_device *stor_dev;
|
||||
+ struct hv_device *dev = host_dev->dev;
|
||||
+ struct Scsi_Host *host;
|
||||
+
|
||||
+ stor_dev = get_in_stor_device(dev);
|
||||
+ host = stor_dev->host;
|
||||
+
|
||||
+ wrk = kmalloc(sizeof(struct storvsc_scan_work),
|
||||
+ GFP_ATOMIC);
|
||||
+ if (!wrk) {
|
||||
+ scmnd->result = DID_TARGET_FAILURE << 16;
|
||||
+ } else {
|
||||
+ wrk->host = host;
|
||||
+ wrk->lun = vm_srb->lun;
|
||||
+ INIT_WORK(&wrk->work, storvsc_remove_lun);
|
||||
+ schedule_work(&wrk->work);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (scmnd->result) {
|
||||
+ if (scsi_normalize_sense(scmnd->sense_buffer,
|
||||
+ SCSI_SENSE_BUFFERSIZE, &sense_hdr))
|
||||
+ scsi_print_sense_hdr("storvsc", &sense_hdr);
|
||||
+ }
|
||||
+
|
||||
+ scsi_set_resid(scmnd,
|
||||
+ request->data_buffer.len -
|
||||
+ vm_srb->data_transfer_length);
|
||||
+
|
||||
+ scsi_done_fn = scmnd->scsi_done;
|
||||
+
|
||||
+ scmnd->host_scribble = NULL;
|
||||
+ scmnd->scsi_done = NULL;
|
||||
+
|
||||
+ scsi_done_fn(scmnd);
|
||||
+
|
||||
+ mempool_free(cmd_request, memp->request_mempool);
|
||||
+}
|
||||
+
|
||||
+static void storvsc_on_io_completion(struct hv_device *device,
|
||||
+ struct vstor_packet *vstor_packet,
|
||||
+ struct hv_storvsc_request *request)
|
||||
+{
|
||||
+ struct storvsc_device *stor_device;
|
||||
+ struct vstor_packet *stor_pkt;
|
||||
+
|
||||
+ stor_device = hv_get_drvdata(device);
|
||||
+ stor_pkt = &request->vstor_packet;
|
||||
+
|
||||
+ /*
|
||||
+ * The current SCSI handling on the host side does
|
||||
+ * not correctly handle:
|
||||
+ * INQUIRY command with page code parameter set to 0x80
|
||||
+ * MODE_SENSE command with cmd[2] == 0x1c
|
||||
+ *
|
||||
+ * Setup srb and scsi status so this won't be fatal.
|
||||
+ * We do this so we can distinguish truly fatal failues
|
||||
* (srb status == 0x4) and off-line the device in that case.
|
||||
*/
|
||||
|
||||
@@ -625,7 +922,7 @@ static void storvsc_on_io_completion(struct hv_device *device,
|
||||
stor_pkt->vm_srb.data_transfer_length =
|
||||
vstor_packet->vm_srb.data_transfer_length;
|
||||
|
||||
- request->on_io_completion(request);
|
||||
+ storvsc_command_completion(request);
|
||||
|
||||
if (atomic_dec_and_test(&stor_device->num_outstanding_req) &&
|
||||
stor_device->drain_notify)
|
||||
@@ -875,229 +1172,6 @@ static int storvsc_device_configure(struct scsi_device *sdevice)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static void destroy_bounce_buffer(struct scatterlist *sgl,
|
||||
- unsigned int sg_count)
|
||||
-{
|
||||
- int i;
|
||||
- struct page *page_buf;
|
||||
-
|
||||
- for (i = 0; i < sg_count; i++) {
|
||||
- page_buf = sg_page((&sgl[i]));
|
||||
- if (page_buf != NULL)
|
||||
- __free_page(page_buf);
|
||||
- }
|
||||
-
|
||||
- kfree(sgl);
|
||||
-}
|
||||
-
|
||||
-static int do_bounce_buffer(struct scatterlist *sgl, unsigned int sg_count)
|
||||
-{
|
||||
- int i;
|
||||
-
|
||||
- /* No need to check */
|
||||
- if (sg_count < 2)
|
||||
- return -1;
|
||||
-
|
||||
- /* We have at least 2 sg entries */
|
||||
- for (i = 0; i < sg_count; i++) {
|
||||
- if (i == 0) {
|
||||
- /* make sure 1st one does not have hole */
|
||||
- if (sgl[i].offset + sgl[i].length != PAGE_SIZE)
|
||||
- return i;
|
||||
- } else if (i == sg_count - 1) {
|
||||
- /* make sure last one does not have hole */
|
||||
- if (sgl[i].offset != 0)
|
||||
- return i;
|
||||
- } else {
|
||||
- /* make sure no hole in the middle */
|
||||
- if (sgl[i].length != PAGE_SIZE || sgl[i].offset != 0)
|
||||
- return i;
|
||||
- }
|
||||
- }
|
||||
- return -1;
|
||||
-}
|
||||
-
|
||||
-static struct scatterlist *create_bounce_buffer(struct scatterlist *sgl,
|
||||
- unsigned int sg_count,
|
||||
- unsigned int len,
|
||||
- int write)
|
||||
-{
|
||||
- int i;
|
||||
- int num_pages;
|
||||
- struct scatterlist *bounce_sgl;
|
||||
- struct page *page_buf;
|
||||
- unsigned int buf_len = ((write == WRITE_TYPE) ? 0 : PAGE_SIZE);
|
||||
-
|
||||
- num_pages = ALIGN(len, PAGE_SIZE) >> PAGE_SHIFT;
|
||||
-
|
||||
- bounce_sgl = kcalloc(num_pages, sizeof(struct scatterlist), GFP_ATOMIC);
|
||||
- if (!bounce_sgl)
|
||||
- return NULL;
|
||||
-
|
||||
- for (i = 0; i < num_pages; i++) {
|
||||
- page_buf = alloc_page(GFP_ATOMIC);
|
||||
- if (!page_buf)
|
||||
- goto cleanup;
|
||||
- sg_set_page(&bounce_sgl[i], page_buf, buf_len, 0);
|
||||
- }
|
||||
-
|
||||
- return bounce_sgl;
|
||||
-
|
||||
-cleanup:
|
||||
- destroy_bounce_buffer(bounce_sgl, num_pages);
|
||||
- return NULL;
|
||||
-}
|
||||
-
|
||||
-
|
||||
-/* Assume the original sgl has enough room */
|
||||
-static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl,
|
||||
- struct scatterlist *bounce_sgl,
|
||||
- unsigned int orig_sgl_count,
|
||||
- unsigned int bounce_sgl_count)
|
||||
-{
|
||||
- int i;
|
||||
- int j = 0;
|
||||
- unsigned long src, dest;
|
||||
- unsigned int srclen, destlen, copylen;
|
||||
- unsigned int total_copied = 0;
|
||||
- unsigned long bounce_addr = 0;
|
||||
- unsigned long dest_addr = 0;
|
||||
- unsigned long flags;
|
||||
-
|
||||
- local_irq_save(flags);
|
||||
-
|
||||
- for (i = 0; i < orig_sgl_count; i++) {
|
||||
- dest_addr = (unsigned long)kmap_atomic(sg_page((&orig_sgl[i])),
|
||||
- KM_IRQ0) + orig_sgl[i].offset;
|
||||
- dest = dest_addr;
|
||||
- destlen = orig_sgl[i].length;
|
||||
-
|
||||
- if (bounce_addr == 0)
|
||||
- bounce_addr =
|
||||
- (unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])),
|
||||
- KM_IRQ0);
|
||||
-
|
||||
- while (destlen) {
|
||||
- src = bounce_addr + bounce_sgl[j].offset;
|
||||
- srclen = bounce_sgl[j].length - bounce_sgl[j].offset;
|
||||
-
|
||||
- copylen = min(srclen, destlen);
|
||||
- memcpy((void *)dest, (void *)src, copylen);
|
||||
-
|
||||
- total_copied += copylen;
|
||||
- bounce_sgl[j].offset += copylen;
|
||||
- destlen -= copylen;
|
||||
- dest += copylen;
|
||||
-
|
||||
- if (bounce_sgl[j].offset == bounce_sgl[j].length) {
|
||||
- /* full */
|
||||
- kunmap_atomic((void *)bounce_addr, KM_IRQ0);
|
||||
- j++;
|
||||
-
|
||||
- /*
|
||||
- * It is possible that the number of elements
|
||||
- * in the bounce buffer may not be equal to
|
||||
- * the number of elements in the original
|
||||
- * scatter list. Handle this correctly.
|
||||
- */
|
||||
-
|
||||
- if (j == bounce_sgl_count) {
|
||||
- /*
|
||||
- * We are done; cleanup and return.
|
||||
- */
|
||||
- kunmap_atomic((void *)(dest_addr -
|
||||
- orig_sgl[i].offset),
|
||||
- KM_IRQ0);
|
||||
- local_irq_restore(flags);
|
||||
- return total_copied;
|
||||
- }
|
||||
-
|
||||
- /* if we need to use another bounce buffer */
|
||||
- if (destlen || i != orig_sgl_count - 1)
|
||||
- bounce_addr =
|
||||
- (unsigned long)kmap_atomic(
|
||||
- sg_page((&bounce_sgl[j])), KM_IRQ0);
|
||||
- } else if (destlen == 0 && i == orig_sgl_count - 1) {
|
||||
- /* unmap the last bounce that is < PAGE_SIZE */
|
||||
- kunmap_atomic((void *)bounce_addr, KM_IRQ0);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- kunmap_atomic((void *)(dest_addr - orig_sgl[i].offset),
|
||||
- KM_IRQ0);
|
||||
- }
|
||||
-
|
||||
- local_irq_restore(flags);
|
||||
-
|
||||
- return total_copied;
|
||||
-}
|
||||
-
|
||||
-
|
||||
-/* Assume the bounce_sgl has enough room ie using the create_bounce_buffer() */
|
||||
-static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl,
|
||||
- struct scatterlist *bounce_sgl,
|
||||
- unsigned int orig_sgl_count)
|
||||
-{
|
||||
- int i;
|
||||
- int j = 0;
|
||||
- unsigned long src, dest;
|
||||
- unsigned int srclen, destlen, copylen;
|
||||
- unsigned int total_copied = 0;
|
||||
- unsigned long bounce_addr = 0;
|
||||
- unsigned long src_addr = 0;
|
||||
- unsigned long flags;
|
||||
-
|
||||
- local_irq_save(flags);
|
||||
-
|
||||
- for (i = 0; i < orig_sgl_count; i++) {
|
||||
- src_addr = (unsigned long)kmap_atomic(sg_page((&orig_sgl[i])),
|
||||
- KM_IRQ0) + orig_sgl[i].offset;
|
||||
- src = src_addr;
|
||||
- srclen = orig_sgl[i].length;
|
||||
-
|
||||
- if (bounce_addr == 0)
|
||||
- bounce_addr =
|
||||
- (unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])),
|
||||
- KM_IRQ0);
|
||||
-
|
||||
- while (srclen) {
|
||||
- /* assume bounce offset always == 0 */
|
||||
- dest = bounce_addr + bounce_sgl[j].length;
|
||||
- destlen = PAGE_SIZE - bounce_sgl[j].length;
|
||||
-
|
||||
- copylen = min(srclen, destlen);
|
||||
- memcpy((void *)dest, (void *)src, copylen);
|
||||
-
|
||||
- total_copied += copylen;
|
||||
- bounce_sgl[j].length += copylen;
|
||||
- srclen -= copylen;
|
||||
- src += copylen;
|
||||
-
|
||||
- if (bounce_sgl[j].length == PAGE_SIZE) {
|
||||
- /* full..move to next entry */
|
||||
- kunmap_atomic((void *)bounce_addr, KM_IRQ0);
|
||||
- j++;
|
||||
-
|
||||
- /* if we need to use another bounce buffer */
|
||||
- if (srclen || i != orig_sgl_count - 1)
|
||||
- bounce_addr =
|
||||
- (unsigned long)kmap_atomic(
|
||||
- sg_page((&bounce_sgl[j])), KM_IRQ0);
|
||||
-
|
||||
- } else if (srclen == 0 && i == orig_sgl_count - 1) {
|
||||
- /* unmap the last bounce that is < PAGE_SIZE */
|
||||
- kunmap_atomic((void *)bounce_addr, KM_IRQ0);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- kunmap_atomic((void *)(src_addr - orig_sgl[i].offset), KM_IRQ0);
|
||||
- }
|
||||
-
|
||||
- local_irq_restore(flags);
|
||||
-
|
||||
- return total_copied;
|
||||
-}
|
||||
-
|
||||
static int storvsc_get_chs(struct scsi_device *sdev, struct block_device * bdev,
|
||||
sector_t capacity, int *info)
|
||||
{
|
||||
@@ -1166,83 +1240,6 @@ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd)
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
-
|
||||
-static void storvsc_command_completion(struct hv_storvsc_request *request)
|
||||
-{
|
||||
- struct storvsc_cmd_request *cmd_request =
|
||||
- (struct storvsc_cmd_request *)request->context;
|
||||
- struct scsi_cmnd *scmnd = cmd_request->cmd;
|
||||
- struct hv_host_device *host_dev = shost_priv(scmnd->device->host);
|
||||
- void (*scsi_done_fn)(struct scsi_cmnd *);
|
||||
- struct scsi_sense_hdr sense_hdr;
|
||||
- struct vmscsi_request *vm_srb;
|
||||
- struct storvsc_scan_work *wrk;
|
||||
- struct stor_mem_pools *memp = scmnd->device->hostdata;
|
||||
-
|
||||
- vm_srb = &request->vstor_packet.vm_srb;
|
||||
- if (cmd_request->bounce_sgl_count) {
|
||||
- if (vm_srb->data_in == READ_TYPE)
|
||||
- copy_from_bounce_buffer(scsi_sglist(scmnd),
|
||||
- cmd_request->bounce_sgl,
|
||||
- scsi_sg_count(scmnd),
|
||||
- cmd_request->bounce_sgl_count);
|
||||
- destroy_bounce_buffer(cmd_request->bounce_sgl,
|
||||
- cmd_request->bounce_sgl_count);
|
||||
- }
|
||||
-
|
||||
- /*
|
||||
- * If there is an error; offline the device since all
|
||||
- * error recovery strategies would have already been
|
||||
- * deployed on the host side.
|
||||
- */
|
||||
- if (vm_srb->srb_status == SRB_STATUS_ERROR)
|
||||
- scmnd->result = DID_TARGET_FAILURE << 16;
|
||||
- else
|
||||
- scmnd->result = vm_srb->scsi_status;
|
||||
-
|
||||
- /*
|
||||
- * If the LUN is invalid; remove the device.
|
||||
- */
|
||||
- if (vm_srb->srb_status == SRB_STATUS_INVALID_LUN) {
|
||||
- struct storvsc_device *stor_dev;
|
||||
- struct hv_device *dev = host_dev->dev;
|
||||
- struct Scsi_Host *host;
|
||||
-
|
||||
- stor_dev = get_in_stor_device(dev);
|
||||
- host = stor_dev->host;
|
||||
-
|
||||
- wrk = kmalloc(sizeof(struct storvsc_scan_work),
|
||||
- GFP_ATOMIC);
|
||||
- if (!wrk) {
|
||||
- scmnd->result = DID_TARGET_FAILURE << 16;
|
||||
- } else {
|
||||
- wrk->host = host;
|
||||
- wrk->lun = vm_srb->lun;
|
||||
- INIT_WORK(&wrk->work, storvsc_remove_lun);
|
||||
- schedule_work(&wrk->work);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- if (scmnd->result) {
|
||||
- if (scsi_normalize_sense(scmnd->sense_buffer,
|
||||
- SCSI_SENSE_BUFFERSIZE, &sense_hdr))
|
||||
- scsi_print_sense_hdr("storvsc", &sense_hdr);
|
||||
- }
|
||||
-
|
||||
- scsi_set_resid(scmnd,
|
||||
- request->data_buffer.len -
|
||||
- vm_srb->data_transfer_length);
|
||||
-
|
||||
- scsi_done_fn = scmnd->scsi_done;
|
||||
-
|
||||
- scmnd->host_scribble = NULL;
|
||||
- scmnd->scsi_done = NULL;
|
||||
-
|
||||
- scsi_done_fn(scmnd);
|
||||
-
|
||||
- mempool_free(cmd_request, memp->request_mempool);
|
||||
-}
|
||||
-
|
||||
static bool storvsc_scsi_cmd_ok(struct scsi_cmnd *scmnd)
|
||||
{
|
||||
bool allowed = true;
|
||||
@@ -1318,7 +1315,6 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
|
||||
break;
|
||||
}
|
||||
|
||||
- request->on_io_completion = storvsc_command_completion;
|
||||
request->context = cmd_request;/* scmnd; */
|
||||
|
||||
vm_srb->port_number = host_dev->port;
|
||||
--
|
||||
1.7.9.5
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Thu, 12 Jan 2012 12:38:02 -0800
|
||||
Subject: [PATCH 56/77] Staging: hv: storvsc: Rename the context field in
|
||||
hv_storvsc_request
|
||||
|
||||
commit 93a1bf4dd018af2a4931b916dd46fdfb963fa4ad upstream.
|
||||
|
||||
Rename the context field in hv_storvsc_request. As part of this change
|
||||
fix the type of this field.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/staging/hv/storvsc_drv.c | 7 +++----
|
||||
1 file changed, 3 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
|
||||
index 7c9fa19..0515707 100644
|
||||
--- a/drivers/staging/hv/storvsc_drv.c
|
||||
+++ b/drivers/staging/hv/storvsc_drv.c
|
||||
@@ -275,7 +275,7 @@ struct hv_storvsc_request {
|
||||
struct completion wait_event;
|
||||
|
||||
unsigned char *sense_buffer;
|
||||
- void *context;
|
||||
+ struct storvsc_cmd_request *cmd;
|
||||
struct hv_multipage_buffer data_buffer;
|
||||
|
||||
struct vstor_packet vstor_packet;
|
||||
@@ -785,8 +785,7 @@ cleanup:
|
||||
|
||||
static void storvsc_command_completion(struct hv_storvsc_request *request)
|
||||
{
|
||||
- struct storvsc_cmd_request *cmd_request =
|
||||
- (struct storvsc_cmd_request *)request->context;
|
||||
+ struct storvsc_cmd_request *cmd_request = request->cmd;
|
||||
struct scsi_cmnd *scmnd = cmd_request->cmd;
|
||||
struct hv_host_device *host_dev = shost_priv(scmnd->device->host);
|
||||
void (*scsi_done_fn)(struct scsi_cmnd *);
|
||||
@@ -1315,7 +1314,7 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
|
||||
break;
|
||||
}
|
||||
|
||||
- request->context = cmd_request;/* scmnd; */
|
||||
+ request->cmd = cmd_request;
|
||||
|
||||
vm_srb->port_number = host_dev->port;
|
||||
vm_srb->path_id = scmnd->device->channel;
|
||||
--
|
||||
1.7.9.5
|
||||
|
195
debian/patches/features/x86/hyperv/0057-Staging-hv-storvsc-Miscellaneous-cleanup-of-storvsc-.patch
vendored
Normal file
195
debian/patches/features/x86/hyperv/0057-Staging-hv-storvsc-Miscellaneous-cleanup-of-storvsc-.patch
vendored
Normal file
|
@ -0,0 +1,195 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Thu, 12 Jan 2012 12:38:03 -0800
|
||||
Subject: [PATCH 57/77] Staging: hv: storvsc: Miscellaneous cleanup of storvsc
|
||||
driver
|
||||
|
||||
commit c649114a5d99eb10e58f977f82018b1d77191aa7 upstream.
|
||||
|
||||
Miscellaneous cleanup of storvsc driver - get rid of unnecessary defines and
|
||||
use fixed size types for structures used for communication with the host.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/staging/hv/storvsc_drv.c | 94 ++++++++++++++++----------------------
|
||||
1 file changed, 39 insertions(+), 55 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
|
||||
index 0515707..da71294 100644
|
||||
--- a/drivers/staging/hv/storvsc_drv.c
|
||||
+++ b/drivers/staging/hv/storvsc_drv.c
|
||||
@@ -43,32 +43,18 @@
|
||||
#include <scsi/scsi_dbg.h>
|
||||
|
||||
|
||||
+/*
|
||||
+ * We setup a mempool to allocate request structures for this driver
|
||||
+ * on a per-lun basis. The following define specifies the number of
|
||||
+ * elements in the pool.
|
||||
+ */
|
||||
+
|
||||
#define STORVSC_MIN_BUF_NR 64
|
||||
-#define STORVSC_RING_BUFFER_SIZE (20*PAGE_SIZE)
|
||||
-static int storvsc_ringbuffer_size = STORVSC_RING_BUFFER_SIZE;
|
||||
+static int storvsc_ringbuffer_size = (20 * PAGE_SIZE);
|
||||
|
||||
module_param(storvsc_ringbuffer_size, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)");
|
||||
|
||||
-/*
|
||||
- * To alert the user that structure sizes may be mismatched even though the
|
||||
- * protocol versions match.
|
||||
- */
|
||||
-
|
||||
-
|
||||
-#define REVISION_STRING(REVISION_) #REVISION_
|
||||
-#define FILL_VMSTOR_REVISION(RESULT_LVALUE_) \
|
||||
- do { \
|
||||
- char *revision_string \
|
||||
- = REVISION_STRING($Rev : 6 $) + 6; \
|
||||
- RESULT_LVALUE_ = 0; \
|
||||
- while (*revision_string >= '0' \
|
||||
- && *revision_string <= '9') { \
|
||||
- RESULT_LVALUE_ *= 10; \
|
||||
- RESULT_LVALUE_ += *revision_string - '0'; \
|
||||
- revision_string++; \
|
||||
- } \
|
||||
- } while (0)
|
||||
|
||||
/*
|
||||
* Major/minor macros. Minor version is in LSB, meaning that earlier flat
|
||||
@@ -79,7 +65,6 @@ MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)");
|
||||
#define VMSTOR_PROTOCOL_MINOR(VERSION_) (((VERSION_)) & 0xff)
|
||||
#define VMSTOR_PROTOCOL_VERSION(MAJOR_, MINOR_) ((((MAJOR_) & 0xff) << 8) | \
|
||||
(((MINOR_) & 0xff)))
|
||||
-#define VMSTOR_INVALID_PROTOCOL_VERSION (-1)
|
||||
|
||||
/*
|
||||
* Version history:
|
||||
@@ -136,26 +121,26 @@ enum vstor_packet_operation {
|
||||
#define MAX_DATA_BUF_LEN_WITH_PADDING 0x14
|
||||
|
||||
struct vmscsi_request {
|
||||
- unsigned short length;
|
||||
- unsigned char srb_status;
|
||||
- unsigned char scsi_status;
|
||||
+ u16 length;
|
||||
+ u8 srb_status;
|
||||
+ u8 scsi_status;
|
||||
|
||||
- unsigned char port_number;
|
||||
- unsigned char path_id;
|
||||
- unsigned char target_id;
|
||||
- unsigned char lun;
|
||||
+ u8 port_number;
|
||||
+ u8 path_id;
|
||||
+ u8 target_id;
|
||||
+ u8 lun;
|
||||
|
||||
- unsigned char cdb_length;
|
||||
- unsigned char sense_info_length;
|
||||
- unsigned char data_in;
|
||||
- unsigned char reserved;
|
||||
+ u8 cdb_length;
|
||||
+ u8 sense_info_length;
|
||||
+ u8 data_in;
|
||||
+ u8 reserved;
|
||||
|
||||
- unsigned int data_transfer_length;
|
||||
+ u32 data_transfer_length;
|
||||
|
||||
union {
|
||||
- unsigned char cdb[CDB16GENERIC_LENGTH];
|
||||
- unsigned char sense_data[SENSE_BUFFER_SIZE];
|
||||
- unsigned char reserved_array[MAX_DATA_BUF_LEN_WITH_PADDING];
|
||||
+ u8 cdb[CDB16GENERIC_LENGTH];
|
||||
+ u8 sense_data[SENSE_BUFFER_SIZE];
|
||||
+ u8 reserved_array[MAX_DATA_BUF_LEN_WITH_PADDING];
|
||||
};
|
||||
} __attribute((packed));
|
||||
|
||||
@@ -165,18 +150,21 @@ struct vmscsi_request {
|
||||
* properties of the channel.
|
||||
*/
|
||||
struct vmstorage_channel_properties {
|
||||
- unsigned short protocol_version;
|
||||
- unsigned char path_id;
|
||||
- unsigned char target_id;
|
||||
+ u16 protocol_version;
|
||||
+ u8 path_id;
|
||||
+ u8 target_id;
|
||||
|
||||
/* Note: port number is only really known on the client side */
|
||||
- unsigned int port_number;
|
||||
- unsigned int flags;
|
||||
- unsigned int max_transfer_bytes;
|
||||
+ u32 port_number;
|
||||
+ u32 flags;
|
||||
+ u32 max_transfer_bytes;
|
||||
|
||||
- /* This id is unique for each channel and will correspond with */
|
||||
- /* vendor specific data in the inquirydata */
|
||||
- unsigned long long unique_id;
|
||||
+ /*
|
||||
+ * This id is unique for each channel and will correspond with
|
||||
+ * vendor specific data in the inquiry data.
|
||||
+ */
|
||||
+
|
||||
+ u64 unique_id;
|
||||
} __packed;
|
||||
|
||||
/* This structure is sent during the storage protocol negotiations. */
|
||||
@@ -189,6 +177,7 @@ struct vmstorage_protocol_version {
|
||||
* (See FILL_VMSTOR_REVISION macro above). Mismatch does not
|
||||
* definitely indicate incompatibility--but it does indicate mismatched
|
||||
* builds.
|
||||
+ * This is only used on the windows side. Just set it to 0.
|
||||
*/
|
||||
unsigned short revision;
|
||||
} __packed;
|
||||
@@ -202,10 +191,10 @@ struct vstor_packet {
|
||||
enum vstor_packet_operation operation;
|
||||
|
||||
/* Flags - see below for values */
|
||||
- unsigned int flags;
|
||||
+ u32 flags;
|
||||
|
||||
/* Status of the request returned from the server side. */
|
||||
- unsigned int status;
|
||||
+ u32 status;
|
||||
|
||||
/* Data payload area */
|
||||
union {
|
||||
@@ -232,11 +221,6 @@ struct vstor_packet {
|
||||
|
||||
#define REQUEST_COMPLETION_FLAG 0x1
|
||||
|
||||
-/* This is the set of flags that the vsc can set in any packets it sends */
|
||||
-#define VSC_LEGAL_FLAGS (REQUEST_COMPLETION_FLAG)
|
||||
-
|
||||
-
|
||||
-
|
||||
#define STORVSC_MAX_IO_REQUESTS 128
|
||||
|
||||
/*
|
||||
@@ -252,7 +236,7 @@ struct vstor_packet {
|
||||
|
||||
/* Matches Windows-end */
|
||||
enum storvsc_request_type {
|
||||
- WRITE_TYPE,
|
||||
+ WRITE_TYPE = 0,
|
||||
READ_TYPE,
|
||||
UNKNOWN_TYPE,
|
||||
};
|
||||
@@ -704,7 +688,7 @@ static int storvsc_channel_init(struct hv_device *device)
|
||||
vstor_packet->flags = REQUEST_COMPLETION_FLAG;
|
||||
|
||||
vstor_packet->version.major_minor = VMSTOR_PROTOCOL_VERSION_CURRENT;
|
||||
- FILL_VMSTOR_REVISION(vstor_packet->version.revision);
|
||||
+ vstor_packet->version.revision = 0;
|
||||
|
||||
ret = vmbus_sendpacket(device->channel, vstor_packet,
|
||||
sizeof(struct vstor_packet),
|
||||
--
|
||||
1.7.9.5
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Thu, 12 Jan 2012 12:38:04 -0800
|
||||
Subject: [PATCH 58/77] Staging: hv: storvsc: Cleanup the code for generating
|
||||
protocol version
|
||||
|
||||
commit 85904a5e553f343243e5cf59f150174159e2e5ea upstream.
|
||||
|
||||
Cleanup the code for generating protocol version.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/staging/hv/storvsc_drv.c | 27 +++++++++++++++++----------
|
||||
1 file changed, 17 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
|
||||
index da71294..629edd1 100644
|
||||
--- a/drivers/staging/hv/storvsc_drv.c
|
||||
+++ b/drivers/staging/hv/storvsc_drv.c
|
||||
@@ -61,10 +61,13 @@ MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)");
|
||||
* version numbers will be interpreted as "0.x" (i.e., 1 becomes 0.1).
|
||||
*/
|
||||
|
||||
-#define VMSTOR_PROTOCOL_MAJOR(VERSION_) (((VERSION_) >> 8) & 0xff)
|
||||
-#define VMSTOR_PROTOCOL_MINOR(VERSION_) (((VERSION_)) & 0xff)
|
||||
-#define VMSTOR_PROTOCOL_VERSION(MAJOR_, MINOR_) ((((MAJOR_) & 0xff) << 8) | \
|
||||
- (((MINOR_) & 0xff)))
|
||||
+static inline u16 storvsc_get_version(u8 major, u8 minor)
|
||||
+{
|
||||
+ u16 version;
|
||||
+
|
||||
+ version = ((major << 8) | minor);
|
||||
+ return version;
|
||||
+}
|
||||
|
||||
/*
|
||||
* Version history:
|
||||
@@ -74,9 +77,8 @@ MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)");
|
||||
* Win7: 4.2
|
||||
*/
|
||||
|
||||
-#define VMSTOR_PROTOCOL_VERSION_CURRENT VMSTOR_PROTOCOL_VERSION(4, 2)
|
||||
-
|
||||
-
|
||||
+#define VMSTOR_CURRENT_MAJOR 4
|
||||
+#define VMSTOR_CURRENT_MINOR 2
|
||||
|
||||
|
||||
/*
|
||||
@@ -170,7 +172,7 @@ struct vmstorage_channel_properties {
|
||||
/* This structure is sent during the storage protocol negotiations. */
|
||||
struct vmstorage_protocol_version {
|
||||
/* Major (MSW) and minor (LSW) version numbers. */
|
||||
- unsigned short major_minor;
|
||||
+ u16 major_minor;
|
||||
|
||||
/*
|
||||
* Revision number is auto-incremented whenever this file is changed
|
||||
@@ -179,7 +181,7 @@ struct vmstorage_protocol_version {
|
||||
* builds.
|
||||
* This is only used on the windows side. Just set it to 0.
|
||||
*/
|
||||
- unsigned short revision;
|
||||
+ u16 revision;
|
||||
} __packed;
|
||||
|
||||
/* Channel Property Flags */
|
||||
@@ -687,7 +689,12 @@ static int storvsc_channel_init(struct hv_device *device)
|
||||
vstor_packet->operation = VSTOR_OPERATION_QUERY_PROTOCOL_VERSION;
|
||||
vstor_packet->flags = REQUEST_COMPLETION_FLAG;
|
||||
|
||||
- vstor_packet->version.major_minor = VMSTOR_PROTOCOL_VERSION_CURRENT;
|
||||
+ vstor_packet->version.major_minor =
|
||||
+ storvsc_get_version(VMSTOR_CURRENT_MAJOR, VMSTOR_CURRENT_MINOR);
|
||||
+
|
||||
+ /*
|
||||
+ * The revision number is only used in Windows; set it to 0.
|
||||
+ */
|
||||
vstor_packet->version.revision = 0;
|
||||
|
||||
ret = vmbus_sendpacket(device->channel, vstor_packet,
|
||||
--
|
||||
1.7.9.5
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Thu, 12 Jan 2012 12:38:05 -0800
|
||||
Subject: [PATCH 59/77] Staging: hv: storvsc: Cleanup some protocol related
|
||||
constants
|
||||
|
||||
commit 6b2f949559b26448cc6d161d62341281db42c909 upstream.
|
||||
|
||||
Cleanup some protocol related constants.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/staging/hv/storvsc_drv.c | 19 +++++++------------
|
||||
1 file changed, 7 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
|
||||
index 629edd1..9f07458 100644
|
||||
--- a/drivers/staging/hv/storvsc_drv.c
|
||||
+++ b/drivers/staging/hv/storvsc_drv.c
|
||||
@@ -114,13 +114,9 @@ enum vstor_packet_operation {
|
||||
* this remains the same across the write regardless of 32/64 bit
|
||||
* note: it's patterned off the SCSI_PASS_THROUGH structure
|
||||
*/
|
||||
-#define CDB16GENERIC_LENGTH 0x10
|
||||
-
|
||||
-#ifndef SENSE_BUFFER_SIZE
|
||||
-#define SENSE_BUFFER_SIZE 0x12
|
||||
-#endif
|
||||
-
|
||||
-#define MAX_DATA_BUF_LEN_WITH_PADDING 0x14
|
||||
+#define STORVSC_MAX_CMD_LEN 0x10
|
||||
+#define STORVSC_SENSE_BUFFER_SIZE 0x12
|
||||
+#define STORVSC_MAX_BUF_LEN_WITH_PADDING 0x14
|
||||
|
||||
struct vmscsi_request {
|
||||
u16 length;
|
||||
@@ -140,9 +136,9 @@ struct vmscsi_request {
|
||||
u32 data_transfer_length;
|
||||
|
||||
union {
|
||||
- u8 cdb[CDB16GENERIC_LENGTH];
|
||||
- u8 sense_data[SENSE_BUFFER_SIZE];
|
||||
- u8 reserved_array[MAX_DATA_BUF_LEN_WITH_PADDING];
|
||||
+ u8 cdb[STORVSC_MAX_CMD_LEN];
|
||||
+ u8 sense_data[STORVSC_SENSE_BUFFER_SIZE];
|
||||
+ u8 reserved_array[STORVSC_MAX_BUF_LEN_WITH_PADDING];
|
||||
};
|
||||
} __attribute((packed));
|
||||
|
||||
@@ -234,7 +230,6 @@ struct vstor_packet {
|
||||
#define STORVSC_MAX_LUNS_PER_TARGET 64
|
||||
#define STORVSC_MAX_TARGETS 1
|
||||
#define STORVSC_MAX_CHANNELS 1
|
||||
-#define STORVSC_MAX_CMD_LEN 16
|
||||
|
||||
/* Matches Windows-end */
|
||||
enum storvsc_request_type {
|
||||
@@ -1074,7 +1069,7 @@ static int storvsc_do_io(struct hv_device *device,
|
||||
vstor_packet->vm_srb.length = sizeof(struct vmscsi_request);
|
||||
|
||||
|
||||
- vstor_packet->vm_srb.sense_info_length = SENSE_BUFFER_SIZE;
|
||||
+ vstor_packet->vm_srb.sense_info_length = STORVSC_SENSE_BUFFER_SIZE;
|
||||
|
||||
|
||||
vstor_packet->vm_srb.data_transfer_length =
|
||||
--
|
||||
1.7.9.5
|
||||
|
40
debian/patches/features/x86/hyperv/0060-Staging-hv-storvsc-Get-rid-of-some-unused-defines.patch
vendored
Normal file
40
debian/patches/features/x86/hyperv/0060-Staging-hv-storvsc-Get-rid-of-some-unused-defines.patch
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Thu, 12 Jan 2012 12:38:06 -0800
|
||||
Subject: [PATCH 60/77] Staging: hv: storvsc: Get rid of some unused defines
|
||||
|
||||
commit 410c52ed66cabd1837a87b37348d92a17f01c199 upstream.
|
||||
|
||||
Get rid of some unused defines.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/staging/hv/storvsc_drv.c | 12 ------------
|
||||
1 file changed, 12 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
|
||||
index 9f07458..d34e3ca 100644
|
||||
--- a/drivers/staging/hv/storvsc_drv.c
|
||||
+++ b/drivers/staging/hv/storvsc_drv.c
|
||||
@@ -81,18 +81,6 @@ static inline u16 storvsc_get_version(u8 major, u8 minor)
|
||||
#define VMSTOR_CURRENT_MINOR 2
|
||||
|
||||
|
||||
-/*
|
||||
- * This will get replaced with the max transfer length that is possible on
|
||||
- * the host adapter.
|
||||
- * The max transfer length will be published when we offer a vmbus channel.
|
||||
- */
|
||||
-
|
||||
-#define MAX_TRANSFER_LENGTH 0x40000
|
||||
-#define DEFAULT_PACKET_SIZE (sizeof(struct vmdata_gpa_direct) + \
|
||||
- sizeof(struct vstor_packet) + \
|
||||
- sizesizeof(u64) * (MAX_TRANSFER_LENGTH / PAGE_SIZE)))
|
||||
-
|
||||
-
|
||||
/* Packet structure describing virtual storage requests. */
|
||||
enum vstor_packet_operation {
|
||||
VSTOR_OPERATION_COMPLETE_IO = 1,
|
||||
--
|
||||
1.7.9.5
|
||||
|
241
debian/patches/features/x86/hyperv/0061-Staging-hv-storvsc-Consolidate-the-request-structure.patch
vendored
Normal file
241
debian/patches/features/x86/hyperv/0061-Staging-hv-storvsc-Consolidate-the-request-structure.patch
vendored
Normal file
|
@ -0,0 +1,241 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Thu, 12 Jan 2012 12:38:07 -0800
|
||||
Subject: [PATCH 61/77] Staging: hv: storvsc: Consolidate the request
|
||||
structure
|
||||
|
||||
commit 61eaffc91d375e02bc12c2c831478841f5ce4757 upstream.
|
||||
|
||||
Consolidate the request structure by getting rid of struct hv_storvsc_request.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/staging/hv/storvsc_drv.c | 65 ++++++++++++++++----------------------
|
||||
1 file changed, 27 insertions(+), 38 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
|
||||
index d34e3ca..9ccc1c4 100644
|
||||
--- a/drivers/staging/hv/storvsc_drv.c
|
||||
+++ b/drivers/staging/hv/storvsc_drv.c
|
||||
@@ -236,17 +236,20 @@ enum storvsc_request_type {
|
||||
#define SRB_STATUS_ERROR 0x04
|
||||
|
||||
|
||||
+struct storvsc_cmd_request {
|
||||
+ struct list_head entry;
|
||||
+ struct scsi_cmnd *cmd;
|
||||
+
|
||||
+ unsigned int bounce_sgl_count;
|
||||
+ struct scatterlist *bounce_sgl;
|
||||
|
||||
-struct hv_storvsc_request {
|
||||
struct hv_device *device;
|
||||
|
||||
/* Synchronize the request/response if needed */
|
||||
struct completion wait_event;
|
||||
|
||||
unsigned char *sense_buffer;
|
||||
- struct storvsc_cmd_request *cmd;
|
||||
struct hv_multipage_buffer data_buffer;
|
||||
-
|
||||
struct vstor_packet vstor_packet;
|
||||
};
|
||||
|
||||
@@ -272,8 +275,8 @@ struct storvsc_device {
|
||||
unsigned char target_id;
|
||||
|
||||
/* Used for vsc/vsp channel reset process */
|
||||
- struct hv_storvsc_request init_request;
|
||||
- struct hv_storvsc_request reset_request;
|
||||
+ struct storvsc_cmd_request init_request;
|
||||
+ struct storvsc_cmd_request reset_request;
|
||||
};
|
||||
|
||||
struct stor_mem_pools {
|
||||
@@ -288,16 +291,6 @@ struct hv_host_device {
|
||||
unsigned char target;
|
||||
};
|
||||
|
||||
-struct storvsc_cmd_request {
|
||||
- struct list_head entry;
|
||||
- struct scsi_cmnd *cmd;
|
||||
-
|
||||
- unsigned int bounce_sgl_count;
|
||||
- struct scatterlist *bounce_sgl;
|
||||
-
|
||||
- struct hv_storvsc_request request;
|
||||
-};
|
||||
-
|
||||
struct storvsc_scan_work {
|
||||
struct work_struct work;
|
||||
struct Scsi_Host *host;
|
||||
@@ -628,7 +621,7 @@ static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl,
|
||||
static int storvsc_channel_init(struct hv_device *device)
|
||||
{
|
||||
struct storvsc_device *stor_device;
|
||||
- struct hv_storvsc_request *request;
|
||||
+ struct storvsc_cmd_request *request;
|
||||
struct vstor_packet *vstor_packet;
|
||||
int ret, t;
|
||||
|
||||
@@ -643,7 +636,7 @@ static int storvsc_channel_init(struct hv_device *device)
|
||||
* Now, initiate the vsc/vsp initialization protocol on the open
|
||||
* channel
|
||||
*/
|
||||
- memset(request, 0, sizeof(struct hv_storvsc_request));
|
||||
+ memset(request, 0, sizeof(struct storvsc_cmd_request));
|
||||
init_completion(&request->wait_event);
|
||||
vstor_packet->operation = VSTOR_OPERATION_BEGIN_INITIALIZATION;
|
||||
vstor_packet->flags = REQUEST_COMPLETION_FLAG;
|
||||
@@ -757,9 +750,8 @@ cleanup:
|
||||
}
|
||||
|
||||
|
||||
-static void storvsc_command_completion(struct hv_storvsc_request *request)
|
||||
+static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request)
|
||||
{
|
||||
- struct storvsc_cmd_request *cmd_request = request->cmd;
|
||||
struct scsi_cmnd *scmnd = cmd_request->cmd;
|
||||
struct hv_host_device *host_dev = shost_priv(scmnd->device->host);
|
||||
void (*scsi_done_fn)(struct scsi_cmnd *);
|
||||
@@ -768,7 +760,7 @@ static void storvsc_command_completion(struct hv_storvsc_request *request)
|
||||
struct storvsc_scan_work *wrk;
|
||||
struct stor_mem_pools *memp = scmnd->device->hostdata;
|
||||
|
||||
- vm_srb = &request->vstor_packet.vm_srb;
|
||||
+ vm_srb = &cmd_request->vstor_packet.vm_srb;
|
||||
if (cmd_request->bounce_sgl_count) {
|
||||
if (vm_srb->data_in == READ_TYPE)
|
||||
copy_from_bounce_buffer(scsi_sglist(scmnd),
|
||||
@@ -819,7 +811,7 @@ static void storvsc_command_completion(struct hv_storvsc_request *request)
|
||||
}
|
||||
|
||||
scsi_set_resid(scmnd,
|
||||
- request->data_buffer.len -
|
||||
+ cmd_request->data_buffer.len -
|
||||
vm_srb->data_transfer_length);
|
||||
|
||||
scsi_done_fn = scmnd->scsi_done;
|
||||
@@ -834,7 +826,7 @@ static void storvsc_command_completion(struct hv_storvsc_request *request)
|
||||
|
||||
static void storvsc_on_io_completion(struct hv_device *device,
|
||||
struct vstor_packet *vstor_packet,
|
||||
- struct hv_storvsc_request *request)
|
||||
+ struct storvsc_cmd_request *request)
|
||||
{
|
||||
struct storvsc_device *stor_device;
|
||||
struct vstor_packet *stor_pkt;
|
||||
@@ -906,7 +898,7 @@ static void storvsc_on_io_completion(struct hv_device *device,
|
||||
|
||||
static void storvsc_on_receive(struct hv_device *device,
|
||||
struct vstor_packet *vstor_packet,
|
||||
- struct hv_storvsc_request *request)
|
||||
+ struct storvsc_cmd_request *request)
|
||||
{
|
||||
struct storvsc_scan_work *work;
|
||||
struct storvsc_device *stor_device;
|
||||
@@ -940,7 +932,7 @@ static void storvsc_on_channel_callback(void *context)
|
||||
u32 bytes_recvd;
|
||||
u64 request_id;
|
||||
unsigned char packet[ALIGN(sizeof(struct vstor_packet), 8)];
|
||||
- struct hv_storvsc_request *request;
|
||||
+ struct storvsc_cmd_request *request;
|
||||
int ret;
|
||||
|
||||
|
||||
@@ -954,7 +946,7 @@ static void storvsc_on_channel_callback(void *context)
|
||||
&bytes_recvd, &request_id);
|
||||
if (ret == 0 && bytes_recvd > 0) {
|
||||
|
||||
- request = (struct hv_storvsc_request *)
|
||||
+ request = (struct storvsc_cmd_request *)
|
||||
(unsigned long)request_id;
|
||||
|
||||
if ((request == &stor_device->init_request) ||
|
||||
@@ -1036,7 +1028,7 @@ static int storvsc_dev_remove(struct hv_device *device)
|
||||
}
|
||||
|
||||
static int storvsc_do_io(struct hv_device *device,
|
||||
- struct hv_storvsc_request *request)
|
||||
+ struct storvsc_cmd_request *request)
|
||||
{
|
||||
struct storvsc_device *stor_device;
|
||||
struct vstor_packet *vstor_packet;
|
||||
@@ -1174,7 +1166,7 @@ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd)
|
||||
struct hv_device *device = host_dev->dev;
|
||||
|
||||
struct storvsc_device *stor_device;
|
||||
- struct hv_storvsc_request *request;
|
||||
+ struct storvsc_cmd_request *request;
|
||||
struct vstor_packet *vstor_packet;
|
||||
int ret, t;
|
||||
|
||||
@@ -1238,7 +1230,6 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
|
||||
int ret;
|
||||
struct hv_host_device *host_dev = shost_priv(host);
|
||||
struct hv_device *dev = host_dev->dev;
|
||||
- struct hv_storvsc_request *request;
|
||||
struct storvsc_cmd_request *cmd_request;
|
||||
unsigned int request_size = 0;
|
||||
int i;
|
||||
@@ -1271,8 +1262,7 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
|
||||
|
||||
scmnd->host_scribble = (unsigned char *)cmd_request;
|
||||
|
||||
- request = &cmd_request->request;
|
||||
- vm_srb = &request->vstor_packet.vm_srb;
|
||||
+ vm_srb = &cmd_request->vstor_packet.vm_srb;
|
||||
|
||||
|
||||
/* Build the SRB */
|
||||
@@ -1288,7 +1278,6 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
|
||||
break;
|
||||
}
|
||||
|
||||
- request->cmd = cmd_request;
|
||||
|
||||
vm_srb->port_number = host_dev->port;
|
||||
vm_srb->path_id = scmnd->device->channel;
|
||||
@@ -1299,10 +1288,10 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
|
||||
|
||||
memcpy(vm_srb->cdb, scmnd->cmnd, vm_srb->cdb_length);
|
||||
|
||||
- request->sense_buffer = scmnd->sense_buffer;
|
||||
+ cmd_request->sense_buffer = scmnd->sense_buffer;
|
||||
|
||||
|
||||
- request->data_buffer.len = scsi_bufflen(scmnd);
|
||||
+ cmd_request->data_buffer.len = scsi_bufflen(scmnd);
|
||||
if (scsi_sg_count(scmnd)) {
|
||||
sgl = (struct scatterlist *)scsi_sglist(scmnd);
|
||||
sg_count = scsi_sg_count(scmnd);
|
||||
@@ -1331,21 +1320,21 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
|
||||
sg_count = cmd_request->bounce_sgl_count;
|
||||
}
|
||||
|
||||
- request->data_buffer.offset = sgl[0].offset;
|
||||
+ cmd_request->data_buffer.offset = sgl[0].offset;
|
||||
|
||||
for (i = 0; i < sg_count; i++)
|
||||
- request->data_buffer.pfn_array[i] =
|
||||
+ cmd_request->data_buffer.pfn_array[i] =
|
||||
page_to_pfn(sg_page((&sgl[i])));
|
||||
|
||||
} else if (scsi_sglist(scmnd)) {
|
||||
- request->data_buffer.offset =
|
||||
+ cmd_request->data_buffer.offset =
|
||||
virt_to_phys(scsi_sglist(scmnd)) & (PAGE_SIZE-1);
|
||||
- request->data_buffer.pfn_array[0] =
|
||||
+ cmd_request->data_buffer.pfn_array[0] =
|
||||
virt_to_phys(scsi_sglist(scmnd)) >> PAGE_SHIFT;
|
||||
}
|
||||
|
||||
/* Invokes the vsc to start an IO */
|
||||
- ret = storvsc_do_io(dev, &cmd_request->request);
|
||||
+ ret = storvsc_do_io(dev, cmd_request);
|
||||
|
||||
if (ret == -EAGAIN) {
|
||||
/* no more space */
|
||||
--
|
||||
1.7.9.5
|
||||
|
136
debian/patches/features/x86/hyperv/0062-Staging-hv-storvsc-Consolidate-all-the-wire-protocol.patch
vendored
Normal file
136
debian/patches/features/x86/hyperv/0062-Staging-hv-storvsc-Consolidate-all-the-wire-protocol.patch
vendored
Normal file
|
@ -0,0 +1,136 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Thu, 12 Jan 2012 12:38:08 -0800
|
||||
Subject: [PATCH 62/77] Staging: hv: storvsc: Consolidate all the wire
|
||||
protocol definitions
|
||||
|
||||
commit af9584b82df77751710db45043cf8d7d7740056d upstream.
|
||||
|
||||
Consolidate all definitions that support communication with the host.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/staging/hv/storvsc_drv.c | 83 +++++++++++++++++++++-----------------
|
||||
1 file changed, 47 insertions(+), 36 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
|
||||
index 9ccc1c4..695ffc3 100644
|
||||
--- a/drivers/staging/hv/storvsc_drv.c
|
||||
+++ b/drivers/staging/hv/storvsc_drv.c
|
||||
@@ -42,33 +42,13 @@
|
||||
#include <scsi/scsi_devinfo.h>
|
||||
#include <scsi/scsi_dbg.h>
|
||||
|
||||
-
|
||||
-/*
|
||||
- * We setup a mempool to allocate request structures for this driver
|
||||
- * on a per-lun basis. The following define specifies the number of
|
||||
- * elements in the pool.
|
||||
- */
|
||||
-
|
||||
-#define STORVSC_MIN_BUF_NR 64
|
||||
-static int storvsc_ringbuffer_size = (20 * PAGE_SIZE);
|
||||
-
|
||||
-module_param(storvsc_ringbuffer_size, int, S_IRUGO);
|
||||
-MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)");
|
||||
-
|
||||
-
|
||||
/*
|
||||
- * Major/minor macros. Minor version is in LSB, meaning that earlier flat
|
||||
- * version numbers will be interpreted as "0.x" (i.e., 1 becomes 0.1).
|
||||
+ * All wire protocol details (storage protocol between the guest and the host)
|
||||
+ * are consolidated here.
|
||||
+ *
|
||||
+ * Begin protocol definitions.
|
||||
*/
|
||||
|
||||
-static inline u16 storvsc_get_version(u8 major, u8 minor)
|
||||
-{
|
||||
- u16 version;
|
||||
-
|
||||
- version = ((major << 8) | minor);
|
||||
- return version;
|
||||
-}
|
||||
-
|
||||
/*
|
||||
* Version history:
|
||||
* V1 Beta: 0.1
|
||||
@@ -207,18 +187,6 @@ struct vstor_packet {
|
||||
|
||||
#define REQUEST_COMPLETION_FLAG 0x1
|
||||
|
||||
-#define STORVSC_MAX_IO_REQUESTS 128
|
||||
-
|
||||
-/*
|
||||
- * In Hyper-V, each port/path/target maps to 1 scsi host adapter. In
|
||||
- * reality, the path/target is not used (ie always set to 0) so our
|
||||
- * scsi host adapter essentially has 1 bus with 1 target that contains
|
||||
- * up to 256 luns.
|
||||
- */
|
||||
-#define STORVSC_MAX_LUNS_PER_TARGET 64
|
||||
-#define STORVSC_MAX_TARGETS 1
|
||||
-#define STORVSC_MAX_CHANNELS 1
|
||||
-
|
||||
/* Matches Windows-end */
|
||||
enum storvsc_request_type {
|
||||
WRITE_TYPE = 0,
|
||||
@@ -235,6 +203,36 @@ enum storvsc_request_type {
|
||||
#define SRB_STATUS_SUCCESS 0x01
|
||||
#define SRB_STATUS_ERROR 0x04
|
||||
|
||||
+/*
|
||||
+ * This is the end of Protocol specific defines.
|
||||
+ */
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * We setup a mempool to allocate request structures for this driver
|
||||
+ * on a per-lun basis. The following define specifies the number of
|
||||
+ * elements in the pool.
|
||||
+ */
|
||||
+
|
||||
+#define STORVSC_MIN_BUF_NR 64
|
||||
+static int storvsc_ringbuffer_size = (20 * PAGE_SIZE);
|
||||
+
|
||||
+module_param(storvsc_ringbuffer_size, int, S_IRUGO);
|
||||
+MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)");
|
||||
+
|
||||
+#define STORVSC_MAX_IO_REQUESTS 128
|
||||
+
|
||||
+/*
|
||||
+ * In Hyper-V, each port/path/target maps to 1 scsi host adapter. In
|
||||
+ * reality, the path/target is not used (ie always set to 0) so our
|
||||
+ * scsi host adapter essentially has 1 bus with 1 target that contains
|
||||
+ * up to 256 luns.
|
||||
+ */
|
||||
+#define STORVSC_MAX_LUNS_PER_TARGET 64
|
||||
+#define STORVSC_MAX_TARGETS 1
|
||||
+#define STORVSC_MAX_CHANNELS 1
|
||||
+
|
||||
+
|
||||
|
||||
struct storvsc_cmd_request {
|
||||
struct list_head entry;
|
||||
@@ -337,6 +335,19 @@ done:
|
||||
}
|
||||
|
||||
/*
|
||||
+ * Major/minor macros. Minor version is in LSB, meaning that earlier flat
|
||||
+ * version numbers will be interpreted as "0.x" (i.e., 1 becomes 0.1).
|
||||
+ */
|
||||
+
|
||||
+static inline u16 storvsc_get_version(u8 major, u8 minor)
|
||||
+{
|
||||
+ u16 version;
|
||||
+
|
||||
+ version = ((major << 8) | minor);
|
||||
+ return version;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
* We can get incoming messages from the host that are not in response to
|
||||
* messages that we have sent out. An example of this would be messages
|
||||
* received by the guest to notify dynamic addition/removal of LUNs. To
|
||||
--
|
||||
1.7.9.5
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Thu, 2 Feb 2012 16:56:48 -0800
|
||||
Subject: [PATCH 63/77] drivers: hv: Cleanup the kvp related state in hyperv.h
|
||||
|
||||
commit 59a084a70afa0678bda2a23a7bc7cc59664945c7 upstream.
|
||||
|
||||
Now cleanup the hyperv.h with regards to KVP definitions.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
include/linux/hyperv.h | 27 ++++++++++++++-------------
|
||||
1 file changed, 14 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
|
||||
index c445ead..dd0e3ee 100644
|
||||
--- a/include/linux/hyperv.h
|
||||
+++ b/include/linux/hyperv.h
|
||||
@@ -137,7 +137,6 @@ struct hv_ku_msg {
|
||||
|
||||
|
||||
|
||||
-#ifdef __KERNEL__
|
||||
|
||||
/*
|
||||
* Registry value types.
|
||||
@@ -163,28 +162,30 @@ enum hv_kvp_exchg_pool {
|
||||
};
|
||||
|
||||
struct hv_kvp_hdr {
|
||||
- u8 operation;
|
||||
- u8 pool;
|
||||
-};
|
||||
+ __u8 operation;
|
||||
+ __u8 pool;
|
||||
+ __u16 pad;
|
||||
+} __attribute__((packed));
|
||||
|
||||
struct hv_kvp_exchg_msg_value {
|
||||
- u32 value_type;
|
||||
- u32 key_size;
|
||||
- u32 value_size;
|
||||
- u8 key[HV_KVP_EXCHANGE_MAX_KEY_SIZE];
|
||||
- u8 value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE];
|
||||
-};
|
||||
+ __u32 value_type;
|
||||
+ __u32 key_size;
|
||||
+ __u32 value_size;
|
||||
+ __u8 key[HV_KVP_EXCHANGE_MAX_KEY_SIZE];
|
||||
+ __u8 value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE];
|
||||
+} __attribute__((packed));
|
||||
|
||||
struct hv_kvp_msg_enumerate {
|
||||
- u32 index;
|
||||
+ __u32 index;
|
||||
struct hv_kvp_exchg_msg_value data;
|
||||
-};
|
||||
+} __attribute__((packed));
|
||||
|
||||
struct hv_kvp_msg {
|
||||
struct hv_kvp_hdr kvp_hdr;
|
||||
struct hv_kvp_msg_enumerate kvp_data;
|
||||
-};
|
||||
+} __attribute__((packed));
|
||||
|
||||
+#ifdef __KERNEL__
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/uuid.h>
|
||||
--
|
||||
1.7.9.5
|
||||
|
78
debian/patches/features/x86/hyperv/0064-tools-hv-Use-hyperv.h-to-get-the-KVP-definitions.patch
vendored
Normal file
78
debian/patches/features/x86/hyperv/0064-tools-hv-Use-hyperv.h-to-get-the-KVP-definitions.patch
vendored
Normal file
|
@ -0,0 +1,78 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Thu, 2 Feb 2012 16:56:49 -0800
|
||||
Subject: [PATCH 64/77] tools: hv: Use hyperv.h to get the KVP definitions
|
||||
|
||||
commit eab6af71f0b83a7f62b9c48be5b2c0a82a86fad3 upstream.
|
||||
|
||||
Now use hyperv.h to get the KVP defines in the KVP user-mode code.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
tools/hv/hv_kvp_daemon.c | 28 +---------------------------
|
||||
1 file changed, 1 insertion(+), 27 deletions(-)
|
||||
|
||||
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
|
||||
index 2b6a2d9..b75523c 100644
|
||||
--- a/tools/hv/hv_kvp_daemon.c
|
||||
+++ b/tools/hv/hv_kvp_daemon.c
|
||||
@@ -34,17 +34,12 @@
|
||||
#include <errno.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <linux/connector.h>
|
||||
+#include <linux/hyperv.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <netdb.h>
|
||||
#include <syslog.h>
|
||||
|
||||
-/*
|
||||
- *
|
||||
- * The following definitions are shared with the in-kernel component; do not
|
||||
- * change any of this without making the corresponding changes in
|
||||
- * the KVP kernel component.
|
||||
- */
|
||||
|
||||
/*
|
||||
* KVP protocol: The user mode component first registers with the
|
||||
@@ -56,25 +51,8 @@
|
||||
* We use this infrastructure for also supporting queries from user mode
|
||||
* application for state that may be maintained in the KVP kernel component.
|
||||
*
|
||||
- * XXXKYS: Have a shared header file between the user and kernel (TODO)
|
||||
*/
|
||||
|
||||
-enum kvp_op {
|
||||
- KVP_REGISTER = 0, /* Register the user mode component*/
|
||||
- KVP_KERNEL_GET, /*Kernel is requesting the value for the specified key*/
|
||||
- KVP_KERNEL_SET, /*Kernel is providing the value for the specified key*/
|
||||
- KVP_USER_GET, /*User is requesting the value for the specified key*/
|
||||
- KVP_USER_SET /*User is providing the value for the specified key*/
|
||||
-};
|
||||
-
|
||||
-#define HV_KVP_EXCHANGE_MAX_KEY_SIZE 512
|
||||
-#define HV_KVP_EXCHANGE_MAX_VALUE_SIZE 2048
|
||||
-
|
||||
-struct hv_ku_msg {
|
||||
- __u32 kvp_index;
|
||||
- __u8 kvp_key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; /* Key name */
|
||||
- __u8 kvp_value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; /* Key value */
|
||||
-};
|
||||
|
||||
enum key_index {
|
||||
FullyQualifiedDomainName = 0,
|
||||
@@ -89,10 +67,6 @@ enum key_index {
|
||||
ProcessorArchitecture
|
||||
};
|
||||
|
||||
-/*
|
||||
- * End of shared definitions.
|
||||
- */
|
||||
-
|
||||
static char kvp_send_buffer[4096];
|
||||
static char kvp_recv_buffer[4096];
|
||||
static struct sockaddr_nl addr;
|
||||
--
|
||||
1.7.9.5
|
||||
|
258
debian/patches/features/x86/hyperv/0065-drivers-hv-kvp-Cleanup-the-kernel-user-protocol.patch
vendored
Normal file
258
debian/patches/features/x86/hyperv/0065-drivers-hv-kvp-Cleanup-the-kernel-user-protocol.patch
vendored
Normal file
|
@ -0,0 +1,258 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Thu, 2 Feb 2012 16:56:50 -0800
|
||||
Subject: [PATCH 65/77] drivers: hv: kvp: Cleanup the kernel/user protocol
|
||||
|
||||
commit 2640335438ca4d7b139e114dae5f0d80e740e106 upstream.
|
||||
|
||||
Now, cleanup the user/kernel KVP protocol by using the same structure
|
||||
definition that is used for host/guest KVP protocol. This simplifies the code.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/hv/hv_kvp.c | 41 +++++++++++++++++++++++++----------------
|
||||
include/linux/hyperv.h | 30 +++++-------------------------
|
||||
tools/hv/hv_kvp_daemon.c | 30 +++++++++++++++---------------
|
||||
3 files changed, 45 insertions(+), 56 deletions(-)
|
||||
|
||||
diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
|
||||
index 4a6971e..0ef4c1f 100644
|
||||
--- a/drivers/hv/hv_kvp.c
|
||||
+++ b/drivers/hv/hv_kvp.c
|
||||
@@ -71,15 +71,20 @@ kvp_register(void)
|
||||
{
|
||||
|
||||
struct cn_msg *msg;
|
||||
+ struct hv_kvp_msg *kvp_msg;
|
||||
+ char *version;
|
||||
|
||||
- msg = kzalloc(sizeof(*msg) + strlen(HV_DRV_VERSION) + 1 , GFP_ATOMIC);
|
||||
+ msg = kzalloc(sizeof(*msg) + sizeof(struct hv_kvp_msg), GFP_ATOMIC);
|
||||
|
||||
if (msg) {
|
||||
+ kvp_msg = (struct hv_kvp_msg *)msg->data;
|
||||
+ version = kvp_msg->body.kvp_version;
|
||||
msg->id.idx = CN_KVP_IDX;
|
||||
msg->id.val = CN_KVP_VAL;
|
||||
- msg->seq = KVP_REGISTER;
|
||||
- strcpy(msg->data, HV_DRV_VERSION);
|
||||
- msg->len = strlen(HV_DRV_VERSION) + 1;
|
||||
+
|
||||
+ kvp_msg->kvp_hdr.operation = KVP_OP_REGISTER;
|
||||
+ strcpy(version, HV_DRV_VERSION);
|
||||
+ msg->len = sizeof(struct hv_kvp_msg);
|
||||
cn_netlink_send(msg, 0, GFP_ATOMIC);
|
||||
kfree(msg);
|
||||
}
|
||||
@@ -101,23 +106,24 @@ kvp_work_func(struct work_struct *dummy)
|
||||
static void
|
||||
kvp_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
|
||||
{
|
||||
- struct hv_ku_msg *message;
|
||||
+ struct hv_kvp_msg *message;
|
||||
+ struct hv_kvp_msg_enumerate *data;
|
||||
|
||||
- message = (struct hv_ku_msg *)msg->data;
|
||||
- if (msg->seq == KVP_REGISTER) {
|
||||
+ message = (struct hv_kvp_msg *)msg->data;
|
||||
+ if (message->kvp_hdr.operation == KVP_OP_REGISTER) {
|
||||
pr_info("KVP: user-mode registering done.\n");
|
||||
kvp_register();
|
||||
}
|
||||
|
||||
- if (msg->seq == KVP_USER_SET) {
|
||||
+ if (message->kvp_hdr.operation == KVP_OP_ENUMERATE) {
|
||||
+ data = &message->body.kvp_enum_data;
|
||||
/*
|
||||
* Complete the transaction by forwarding the key value
|
||||
* to the host. But first, cancel the timeout.
|
||||
*/
|
||||
if (cancel_delayed_work_sync(&kvp_work))
|
||||
- kvp_respond_to_host(message->kvp_key,
|
||||
- message->kvp_value,
|
||||
- !strlen(message->kvp_key));
|
||||
+ kvp_respond_to_host(data->data.key, data->data.value,
|
||||
+ !strlen(data->data.key));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,6 +131,7 @@ static void
|
||||
kvp_send_key(struct work_struct *dummy)
|
||||
{
|
||||
struct cn_msg *msg;
|
||||
+ struct hv_kvp_msg *message;
|
||||
int index = kvp_transaction.index;
|
||||
|
||||
msg = kzalloc(sizeof(*msg) + sizeof(struct hv_kvp_msg) , GFP_ATOMIC);
|
||||
@@ -132,9 +139,11 @@ kvp_send_key(struct work_struct *dummy)
|
||||
if (msg) {
|
||||
msg->id.idx = CN_KVP_IDX;
|
||||
msg->id.val = CN_KVP_VAL;
|
||||
- msg->seq = KVP_KERNEL_GET;
|
||||
- ((struct hv_ku_msg *)msg->data)->kvp_index = index;
|
||||
- msg->len = sizeof(struct hv_ku_msg);
|
||||
+
|
||||
+ message = (struct hv_kvp_msg *)msg->data;
|
||||
+ message->kvp_hdr.operation = KVP_OP_ENUMERATE;
|
||||
+ message->body.kvp_enum_data.index = index;
|
||||
+ msg->len = sizeof(struct hv_kvp_msg);
|
||||
cn_netlink_send(msg, 0, GFP_ATOMIC);
|
||||
kfree(msg);
|
||||
}
|
||||
@@ -191,7 +200,7 @@ kvp_respond_to_host(char *key, char *value, int error)
|
||||
kvp_msg = (struct hv_kvp_msg *)
|
||||
&recv_buffer[sizeof(struct vmbuspipe_hdr) +
|
||||
sizeof(struct icmsg_hdr)];
|
||||
- kvp_data = &kvp_msg->kvp_data;
|
||||
+ kvp_data = &kvp_msg->body.kvp_enum_data;
|
||||
key_name = key;
|
||||
|
||||
/*
|
||||
@@ -266,7 +275,7 @@ void hv_kvp_onchannelcallback(void *context)
|
||||
sizeof(struct vmbuspipe_hdr) +
|
||||
sizeof(struct icmsg_hdr)];
|
||||
|
||||
- kvp_data = &kvp_msg->kvp_data;
|
||||
+ kvp_data = &kvp_msg->body.kvp_enum_data;
|
||||
|
||||
/*
|
||||
* We only support the "get" operation on
|
||||
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
|
||||
index dd0e3ee..e57a6c6 100644
|
||||
--- a/include/linux/hyperv.h
|
||||
+++ b/include/linux/hyperv.h
|
||||
@@ -113,30 +113,6 @@
|
||||
* (not supported), a NULL key string is returned.
|
||||
*/
|
||||
|
||||
-/*
|
||||
- *
|
||||
- * The following definitions are shared with the user-mode component; do not
|
||||
- * change any of this without making the corresponding changes in
|
||||
- * the KVP user-mode component.
|
||||
- */
|
||||
-
|
||||
-enum hv_ku_op {
|
||||
- KVP_REGISTER = 0, /* Register the user mode component */
|
||||
- KVP_KERNEL_GET, /* Kernel is requesting the value */
|
||||
- KVP_KERNEL_SET, /* Kernel is providing the value */
|
||||
- KVP_USER_GET, /* User is requesting the value */
|
||||
- KVP_USER_SET /* User is providing the value */
|
||||
-};
|
||||
-
|
||||
-struct hv_ku_msg {
|
||||
- __u32 kvp_index; /* Key index */
|
||||
- __u8 kvp_key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; /* Key name */
|
||||
- __u8 kvp_value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; /* Key value */
|
||||
-};
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
|
||||
/*
|
||||
* Registry value types.
|
||||
@@ -149,6 +125,7 @@ enum hv_kvp_exchg_op {
|
||||
KVP_OP_SET,
|
||||
KVP_OP_DELETE,
|
||||
KVP_OP_ENUMERATE,
|
||||
+ KVP_OP_REGISTER,
|
||||
KVP_OP_COUNT /* Number of operations, must be last. */
|
||||
};
|
||||
|
||||
@@ -182,7 +159,10 @@ struct hv_kvp_msg_enumerate {
|
||||
|
||||
struct hv_kvp_msg {
|
||||
struct hv_kvp_hdr kvp_hdr;
|
||||
- struct hv_kvp_msg_enumerate kvp_data;
|
||||
+ union {
|
||||
+ struct hv_kvp_msg_enumerate kvp_enum_data;
|
||||
+ char kvp_version[HV_KVP_EXCHANGE_MAX_KEY_SIZE];
|
||||
+ } body;
|
||||
} __attribute__((packed));
|
||||
|
||||
#ifdef __KERNEL__
|
||||
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
|
||||
index b75523c..4ebf703 100644
|
||||
--- a/tools/hv/hv_kvp_daemon.c
|
||||
+++ b/tools/hv/hv_kvp_daemon.c
|
||||
@@ -302,7 +302,7 @@ int main(void)
|
||||
struct pollfd pfd;
|
||||
struct nlmsghdr *incoming_msg;
|
||||
struct cn_msg *incoming_cn_msg;
|
||||
- struct hv_ku_msg *hv_msg;
|
||||
+ struct hv_kvp_msg *hv_msg;
|
||||
char *p;
|
||||
char *key_value;
|
||||
char *key_name;
|
||||
@@ -340,9 +340,11 @@ int main(void)
|
||||
message = (struct cn_msg *)kvp_send_buffer;
|
||||
message->id.idx = CN_KVP_IDX;
|
||||
message->id.val = CN_KVP_VAL;
|
||||
- message->seq = KVP_REGISTER;
|
||||
+
|
||||
+ hv_msg = (struct hv_kvp_msg *)message->data;
|
||||
+ hv_msg->kvp_hdr.operation = KVP_OP_REGISTER;
|
||||
message->ack = 0;
|
||||
- message->len = 0;
|
||||
+ message->len = sizeof(struct hv_kvp_msg);
|
||||
|
||||
len = netlink_send(fd, message);
|
||||
if (len < 0) {
|
||||
@@ -368,14 +370,15 @@ int main(void)
|
||||
|
||||
incoming_msg = (struct nlmsghdr *)kvp_recv_buffer;
|
||||
incoming_cn_msg = (struct cn_msg *)NLMSG_DATA(incoming_msg);
|
||||
+ hv_msg = (struct hv_kvp_msg *)incoming_cn_msg->data;
|
||||
|
||||
- switch (incoming_cn_msg->seq) {
|
||||
- case KVP_REGISTER:
|
||||
+ switch (hv_msg->kvp_hdr.operation) {
|
||||
+ case KVP_OP_REGISTER:
|
||||
/*
|
||||
* Driver is registering with us; stash away the version
|
||||
* information.
|
||||
*/
|
||||
- p = (char *)incoming_cn_msg->data;
|
||||
+ p = (char *)hv_msg->body.kvp_version;
|
||||
lic_version = malloc(strlen(p) + 1);
|
||||
if (lic_version) {
|
||||
strcpy(lic_version, p);
|
||||
@@ -386,17 +389,15 @@ int main(void)
|
||||
}
|
||||
continue;
|
||||
|
||||
- case KVP_KERNEL_GET:
|
||||
- break;
|
||||
default:
|
||||
- continue;
|
||||
+ break;
|
||||
}
|
||||
|
||||
- hv_msg = (struct hv_ku_msg *)incoming_cn_msg->data;
|
||||
- key_name = (char *)hv_msg->kvp_key;
|
||||
- key_value = (char *)hv_msg->kvp_value;
|
||||
+ hv_msg = (struct hv_kvp_msg *)incoming_cn_msg->data;
|
||||
+ key_name = (char *)hv_msg->body.kvp_enum_data.data.key;
|
||||
+ key_value = (char *)hv_msg->body.kvp_enum_data.data.value;
|
||||
|
||||
- switch (hv_msg->kvp_index) {
|
||||
+ switch (hv_msg->body.kvp_enum_data.index) {
|
||||
case FullyQualifiedDomainName:
|
||||
kvp_get_domain_name(key_value,
|
||||
HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
|
||||
@@ -456,9 +457,8 @@ int main(void)
|
||||
|
||||
incoming_cn_msg->id.idx = CN_KVP_IDX;
|
||||
incoming_cn_msg->id.val = CN_KVP_VAL;
|
||||
- incoming_cn_msg->seq = KVP_USER_SET;
|
||||
incoming_cn_msg->ack = 0;
|
||||
- incoming_cn_msg->len = sizeof(struct hv_ku_msg);
|
||||
+ incoming_cn_msg->len = sizeof(struct hv_kvp_msg);
|
||||
|
||||
len = netlink_send(fd, incoming_cn_msg);
|
||||
if (len < 0) {
|
||||
--
|
||||
1.7.9.5
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Thu, 2 Feb 2012 16:56:51 -0800
|
||||
Subject: [PATCH 66/77] drivers: hv: Increase the number of VCPUs supported in
|
||||
the guest
|
||||
|
||||
commit 14c1bf8a8920f36f6e0603a2ff920b48eec14387 upstream.
|
||||
|
||||
The current code arbirarily limited the number of CPUs the guest could have.
|
||||
Change that so that we can support the maximum number of CPUs the guest can
|
||||
support. While we use NR_CPUS to size the per-cpu state all we are allocating
|
||||
based on NR_CPUS are the pointers to per-cpu state that will be allocatted in
|
||||
the context of the initializing CPU. This patch triggers a checkpatch warning
|
||||
for the usage of NR_CPU and since all we are allocating a couple of pointers
|
||||
per CPU, it should be ok.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/hv/hv.c | 4 ++--
|
||||
drivers/hv/hyperv_vmbus.h | 5 ++---
|
||||
2 files changed, 4 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
|
||||
index 12aa97f..15956bd 100644
|
||||
--- a/drivers/hv/hv.c
|
||||
+++ b/drivers/hv/hv.c
|
||||
@@ -155,9 +155,9 @@ int hv_init(void)
|
||||
union hv_x64_msr_hypercall_contents hypercall_msr;
|
||||
void *virtaddr = NULL;
|
||||
|
||||
- memset(hv_context.synic_event_page, 0, sizeof(void *) * MAX_NUM_CPUS);
|
||||
+ memset(hv_context.synic_event_page, 0, sizeof(void *) * NR_CPUS);
|
||||
memset(hv_context.synic_message_page, 0,
|
||||
- sizeof(void *) * MAX_NUM_CPUS);
|
||||
+ sizeof(void *) * NR_CPUS);
|
||||
|
||||
if (!query_hypervisor_presence())
|
||||
goto cleanup;
|
||||
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
|
||||
index 6d7d286..699f0d8 100644
|
||||
--- a/drivers/hv/hyperv_vmbus.h
|
||||
+++ b/drivers/hv/hyperv_vmbus.h
|
||||
@@ -457,7 +457,6 @@ static const uuid_le VMBUS_SERVICE_ID = {
|
||||
},
|
||||
};
|
||||
|
||||
-#define MAX_NUM_CPUS 32
|
||||
|
||||
|
||||
struct hv_input_signal_event_buffer {
|
||||
@@ -483,8 +482,8 @@ struct hv_context {
|
||||
/* 8-bytes aligned of the buffer above */
|
||||
struct hv_input_signal_event *signal_event_param;
|
||||
|
||||
- void *synic_message_page[MAX_NUM_CPUS];
|
||||
- void *synic_event_page[MAX_NUM_CPUS];
|
||||
+ void *synic_message_page[NR_CPUS];
|
||||
+ void *synic_event_page[NR_CPUS];
|
||||
};
|
||||
|
||||
extern struct hv_context hv_context;
|
||||
--
|
||||
1.7.9.5
|
||||
|
3244
debian/patches/features/x86/hyperv/0067-Staging-hv-storvsc-Move-the-storage-driver-out-of-th.patch
vendored
Normal file
3244
debian/patches/features/x86/hyperv/0067-Staging-hv-storvsc-Move-the-storage-driver-out-of-th.patch
vendored
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,40 @@
|
|||
From: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Date: Wed, 7 Mar 2012 10:02:00 +0000
|
||||
Subject: [PATCH 68/77] net/hyperv: Use the built-in macro KBUILD_MODNAME for
|
||||
this driver
|
||||
|
||||
commit d31b20fcc89efa8c5d3f5ea2720e08a286b69a36 upstream.
|
||||
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Cc: Olaf Hering <olaf@aepfle.de>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/hyperv/netvsc_drv.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
|
||||
index 0ae7a1a..217dfed 100644
|
||||
--- a/drivers/net/hyperv/netvsc_drv.c
|
||||
+++ b/drivers/net/hyperv/netvsc_drv.c
|
||||
@@ -310,7 +310,7 @@ int netvsc_recv_callback(struct hv_device *device_obj,
|
||||
static void netvsc_get_drvinfo(struct net_device *net,
|
||||
struct ethtool_drvinfo *info)
|
||||
{
|
||||
- strcpy(info->driver, "hv_netvsc");
|
||||
+ strcpy(info->driver, KBUILD_MODNAME);
|
||||
strcpy(info->version, HV_DRV_VERSION);
|
||||
strcpy(info->fw_version, "N/A");
|
||||
}
|
||||
@@ -482,7 +482,7 @@ MODULE_DEVICE_TABLE(vmbus, id_table);
|
||||
|
||||
/* The one and only one */
|
||||
static struct hv_driver netvsc_drv = {
|
||||
- .name = "netvsc",
|
||||
+ .name = KBUILD_MODNAME,
|
||||
.id_table = id_table,
|
||||
.probe = netvsc_probe,
|
||||
.remove = netvsc_remove,
|
||||
--
|
||||
1.7.9.5
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
From: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Date: Mon, 12 Mar 2012 10:20:49 +0000
|
||||
Subject: [PATCH 69/77] net/hyperv: Fix data corruption in
|
||||
rndis_filter_receive()
|
||||
|
||||
commit ef31bef6216db76950c38f1993b45953402f4c63 upstream.
|
||||
|
||||
Limiting the memcpy to be the sizeof(struct rndis_message) can truncate
|
||||
the message if there are Per-Packet-Info or Out-of-Band data.
|
||||
|
||||
In my earlier patch (commit 45326342), the unnecessary kmap_atomic and
|
||||
kunmap_atomic surrounding this memcpy have been removed because the memory
|
||||
in the receive buffer is always mapped. This memcpy is not necessary
|
||||
either. To fix the bug, I removed the memcpy.
|
||||
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Reviewed-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/hyperv/rndis_filter.c | 33 +++++++++------------------------
|
||||
1 file changed, 9 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
|
||||
index 136efd8..0c3d7d9 100644
|
||||
--- a/drivers/net/hyperv/rndis_filter.c
|
||||
+++ b/drivers/net/hyperv/rndis_filter.c
|
||||
@@ -352,8 +352,7 @@ int rndis_filter_receive(struct hv_device *dev,
|
||||
{
|
||||
struct netvsc_device *net_dev = hv_get_drvdata(dev);
|
||||
struct rndis_device *rndis_dev;
|
||||
- struct rndis_message rndis_msg;
|
||||
- struct rndis_message *rndis_hdr;
|
||||
+ struct rndis_message *rndis_msg;
|
||||
struct net_device *ndev;
|
||||
|
||||
if (!net_dev)
|
||||
@@ -375,46 +374,32 @@ int rndis_filter_receive(struct hv_device *dev,
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
- rndis_hdr = pkt->data;
|
||||
-
|
||||
- /* Make sure we got a valid rndis message */
|
||||
- if ((rndis_hdr->ndis_msg_type != REMOTE_NDIS_PACKET_MSG) &&
|
||||
- (rndis_hdr->msg_len > sizeof(struct rndis_message))) {
|
||||
- netdev_err(ndev, "incoming rndis message buffer overflow "
|
||||
- "detected (got %u, max %zu)..marking it an error!\n",
|
||||
- rndis_hdr->msg_len,
|
||||
- sizeof(struct rndis_message));
|
||||
- }
|
||||
+ rndis_msg = pkt->data;
|
||||
|
||||
- memcpy(&rndis_msg, rndis_hdr,
|
||||
- (rndis_hdr->msg_len > sizeof(struct rndis_message)) ?
|
||||
- sizeof(struct rndis_message) :
|
||||
- rndis_hdr->msg_len);
|
||||
+ dump_rndis_message(dev, rndis_msg);
|
||||
|
||||
- dump_rndis_message(dev, &rndis_msg);
|
||||
-
|
||||
- switch (rndis_msg.ndis_msg_type) {
|
||||
+ switch (rndis_msg->ndis_msg_type) {
|
||||
case REMOTE_NDIS_PACKET_MSG:
|
||||
/* data msg */
|
||||
- rndis_filter_receive_data(rndis_dev, &rndis_msg, pkt);
|
||||
+ rndis_filter_receive_data(rndis_dev, rndis_msg, pkt);
|
||||
break;
|
||||
|
||||
case REMOTE_NDIS_INITIALIZE_CMPLT:
|
||||
case REMOTE_NDIS_QUERY_CMPLT:
|
||||
case REMOTE_NDIS_SET_CMPLT:
|
||||
/* completion msgs */
|
||||
- rndis_filter_receive_response(rndis_dev, &rndis_msg);
|
||||
+ rndis_filter_receive_response(rndis_dev, rndis_msg);
|
||||
break;
|
||||
|
||||
case REMOTE_NDIS_INDICATE_STATUS_MSG:
|
||||
/* notification msgs */
|
||||
- rndis_filter_receive_indicate_status(rndis_dev, &rndis_msg);
|
||||
+ rndis_filter_receive_indicate_status(rndis_dev, rndis_msg);
|
||||
break;
|
||||
default:
|
||||
netdev_err(ndev,
|
||||
"unhandled rndis message (type %u len %u)\n",
|
||||
- rndis_msg.ndis_msg_type,
|
||||
- rndis_msg.msg_len);
|
||||
+ rndis_msg->ndis_msg_type,
|
||||
+ rndis_msg->msg_len);
|
||||
break;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.9.5
|
||||
|
250
debian/patches/features/x86/hyperv/0070-net-hyperv-Add-support-for-vlan-trunking-from-guests.patch
vendored
Normal file
250
debian/patches/features/x86/hyperv/0070-net-hyperv-Add-support-for-vlan-trunking-from-guests.patch
vendored
Normal file
|
@ -0,0 +1,250 @@
|
|||
From: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Date: Mon, 12 Mar 2012 10:20:50 +0000
|
||||
Subject: [PATCH 70/77] net/hyperv: Add support for vlan trunking from guests
|
||||
|
||||
commit 1f5f3a75e216fe771b8d6805e0bb2f43595a6ee1 upstream.
|
||||
|
||||
With this feature, a Linux guest can now configure multiple vlans through
|
||||
a single synthetic NIC on Win8 Hyper-V host.
|
||||
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Reviewed-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/hyperv/hyperv_net.h | 34 ++++++++++++++++++++-
|
||||
drivers/net/hyperv/netvsc.c | 3 +-
|
||||
drivers/net/hyperv/netvsc_drv.c | 8 +++--
|
||||
drivers/net/hyperv/rndis_filter.c | 60 +++++++++++++++++++++++++++++++++++++
|
||||
4 files changed, 101 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
|
||||
index dec5836..c358245 100644
|
||||
--- a/drivers/net/hyperv/hyperv_net.h
|
||||
+++ b/drivers/net/hyperv/hyperv_net.h
|
||||
@@ -49,6 +49,7 @@ struct hv_netvsc_packet {
|
||||
|
||||
struct hv_device *device;
|
||||
bool is_data_pkt;
|
||||
+ u16 vlan_tci;
|
||||
|
||||
/*
|
||||
* Valid only for receives when we break a xfer page packet
|
||||
@@ -926,9 +927,40 @@ struct rndis_oobd {
|
||||
struct rndis_per_packet_info {
|
||||
u32 size;
|
||||
u32 type;
|
||||
- u32 per_pkt_info_offset;
|
||||
+ u32 ppi_offset;
|
||||
+};
|
||||
+
|
||||
+enum ndis_per_pkt_info_type {
|
||||
+ TCPIP_CHKSUM_PKTINFO,
|
||||
+ IPSEC_PKTINFO,
|
||||
+ TCP_LARGESEND_PKTINFO,
|
||||
+ CLASSIFICATION_HANDLE_PKTINFO,
|
||||
+ NDIS_RESERVED,
|
||||
+ SG_LIST_PKTINFO,
|
||||
+ IEEE_8021Q_INFO,
|
||||
+ ORIGINAL_PKTINFO,
|
||||
+ PACKET_CANCEL_ID,
|
||||
+ ORIGINAL_NET_BUFLIST,
|
||||
+ CACHED_NET_BUFLIST,
|
||||
+ SHORT_PKT_PADINFO,
|
||||
+ MAX_PER_PKT_INFO
|
||||
+};
|
||||
+
|
||||
+struct ndis_pkt_8021q_info {
|
||||
+ union {
|
||||
+ struct {
|
||||
+ u32 pri:3; /* User Priority */
|
||||
+ u32 cfi:1; /* Canonical Format ID */
|
||||
+ u32 vlanid:12; /* VLAN ID */
|
||||
+ u32 reserved:16;
|
||||
+ };
|
||||
+ u32 value;
|
||||
+ };
|
||||
};
|
||||
|
||||
+#define NDIS_VLAN_PPI_SIZE (sizeof(struct rndis_per_packet_info) + \
|
||||
+ sizeof(struct ndis_pkt_8021q_info))
|
||||
+
|
||||
/* Format of Information buffer passed in a SetRequest for the OID */
|
||||
/* OID_GEN_RNDIS_CONFIG_PARAMETER. */
|
||||
struct rndis_config_parameter_info {
|
||||
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
|
||||
index 8965b45..d025c83 100644
|
||||
--- a/drivers/net/hyperv/netvsc.c
|
||||
+++ b/drivers/net/hyperv/netvsc.c
|
||||
@@ -300,6 +300,7 @@ static int negotiate_nvsp_ver(struct hv_device *device,
|
||||
memset(init_packet, 0, sizeof(struct nvsp_message));
|
||||
init_packet->hdr.msg_type = NVSP_MSG2_TYPE_SEND_NDIS_CONFIG;
|
||||
init_packet->msg.v2_msg.send_ndis_config.mtu = net_device->ndev->mtu;
|
||||
+ init_packet->msg.v2_msg.send_ndis_config.capability.ieee8021q = 1;
|
||||
|
||||
ret = vmbus_sendpacket(device->channel, init_packet,
|
||||
sizeof(struct nvsp_message),
|
||||
@@ -341,7 +342,7 @@ static int netvsc_connect_vsp(struct hv_device *device)
|
||||
/* Send the ndis version */
|
||||
memset(init_packet, 0, sizeof(struct nvsp_message));
|
||||
|
||||
- ndis_version = 0x00050000;
|
||||
+ ndis_version = 0x00050001;
|
||||
|
||||
init_packet->hdr.msg_type = NVSP_MSG1_TYPE_SEND_NDIS_VER;
|
||||
init_packet->msg.v1_msg.
|
||||
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
|
||||
index 217dfed..0f8e834 100644
|
||||
--- a/drivers/net/hyperv/netvsc_drv.c
|
||||
+++ b/drivers/net/hyperv/netvsc_drv.c
|
||||
@@ -159,7 +159,8 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
|
||||
/* Allocate a netvsc packet based on # of frags. */
|
||||
packet = kzalloc(sizeof(struct hv_netvsc_packet) +
|
||||
(num_pages * sizeof(struct hv_page_buffer)) +
|
||||
- sizeof(struct rndis_filter_packet), GFP_ATOMIC);
|
||||
+ sizeof(struct rndis_filter_packet) +
|
||||
+ NDIS_VLAN_PPI_SIZE, GFP_ATOMIC);
|
||||
if (!packet) {
|
||||
/* out of memory, drop packet */
|
||||
netdev_err(net, "unable to allocate hv_netvsc_packet\n");
|
||||
@@ -169,6 +170,8 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
|
||||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
|
||||
+ packet->vlan_tci = skb->vlan_tci;
|
||||
+
|
||||
packet->extension = (void *)(unsigned long)packet +
|
||||
sizeof(struct hv_netvsc_packet) +
|
||||
(num_pages * sizeof(struct hv_page_buffer));
|
||||
@@ -293,6 +296,7 @@ int netvsc_recv_callback(struct hv_device *device_obj,
|
||||
|
||||
skb->protocol = eth_type_trans(skb, net);
|
||||
skb->ip_summed = CHECKSUM_NONE;
|
||||
+ skb->vlan_tci = packet->vlan_tci;
|
||||
|
||||
net->stats.rx_packets++;
|
||||
net->stats.rx_bytes += packet->total_data_buflen;
|
||||
@@ -407,7 +411,7 @@ static int netvsc_probe(struct hv_device *dev,
|
||||
|
||||
/* TODO: Add GSO and Checksum offload */
|
||||
net->hw_features = NETIF_F_SG;
|
||||
- net->features = NETIF_F_SG;
|
||||
+ net->features = NETIF_F_SG | NETIF_F_HW_VLAN_TX;
|
||||
|
||||
SET_ETHTOOL_OPS(net, ðtool_ops);
|
||||
SET_NETDEV_DEV(net, &dev->device);
|
||||
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
|
||||
index 0c3d7d9..d6be64b 100644
|
||||
--- a/drivers/net/hyperv/rndis_filter.c
|
||||
+++ b/drivers/net/hyperv/rndis_filter.c
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/netdevice.h>
|
||||
+#include <linux/if_vlan.h>
|
||||
|
||||
#include "hyperv_net.h"
|
||||
|
||||
@@ -303,12 +304,39 @@ static void rndis_filter_receive_indicate_status(struct rndis_device *dev,
|
||||
}
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Get the Per-Packet-Info with the specified type
|
||||
+ * return NULL if not found.
|
||||
+ */
|
||||
+static inline void *rndis_get_ppi(struct rndis_packet *rpkt, u32 type)
|
||||
+{
|
||||
+ struct rndis_per_packet_info *ppi;
|
||||
+ int len;
|
||||
+
|
||||
+ if (rpkt->per_pkt_info_offset == 0)
|
||||
+ return NULL;
|
||||
+
|
||||
+ ppi = (struct rndis_per_packet_info *)((ulong)rpkt +
|
||||
+ rpkt->per_pkt_info_offset);
|
||||
+ len = rpkt->per_pkt_info_len;
|
||||
+
|
||||
+ while (len > 0) {
|
||||
+ if (ppi->type == type)
|
||||
+ return (void *)((ulong)ppi + ppi->ppi_offset);
|
||||
+ len -= ppi->size;
|
||||
+ ppi = (struct rndis_per_packet_info *)((ulong)ppi + ppi->size);
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
static void rndis_filter_receive_data(struct rndis_device *dev,
|
||||
struct rndis_message *msg,
|
||||
struct hv_netvsc_packet *pkt)
|
||||
{
|
||||
struct rndis_packet *rndis_pkt;
|
||||
u32 data_offset;
|
||||
+ struct ndis_pkt_8021q_info *vlan;
|
||||
|
||||
rndis_pkt = &msg->msg.pkt;
|
||||
|
||||
@@ -344,6 +372,14 @@ static void rndis_filter_receive_data(struct rndis_device *dev,
|
||||
|
||||
pkt->is_data_pkt = true;
|
||||
|
||||
+ vlan = rndis_get_ppi(rndis_pkt, IEEE_8021Q_INFO);
|
||||
+ if (vlan) {
|
||||
+ pkt->vlan_tci = VLAN_TAG_PRESENT | vlan->vlanid |
|
||||
+ (vlan->pri << VLAN_PRIO_SHIFT);
|
||||
+ } else {
|
||||
+ pkt->vlan_tci = 0;
|
||||
+ }
|
||||
+
|
||||
netvsc_recv_callback(dev->net_dev->dev, pkt);
|
||||
}
|
||||
|
||||
@@ -759,12 +795,15 @@ int rndis_filter_send(struct hv_device *dev,
|
||||
struct rndis_message *rndis_msg;
|
||||
struct rndis_packet *rndis_pkt;
|
||||
u32 rndis_msg_size;
|
||||
+ bool isvlan = pkt->vlan_tci & VLAN_TAG_PRESENT;
|
||||
|
||||
/* Add the rndis header */
|
||||
filter_pkt = (struct rndis_filter_packet *)pkt->extension;
|
||||
|
||||
rndis_msg = &filter_pkt->msg;
|
||||
rndis_msg_size = RNDIS_MESSAGE_SIZE(struct rndis_packet);
|
||||
+ if (isvlan)
|
||||
+ rndis_msg_size += NDIS_VLAN_PPI_SIZE;
|
||||
|
||||
rndis_msg->ndis_msg_type = REMOTE_NDIS_PACKET_MSG;
|
||||
rndis_msg->msg_len = pkt->total_data_buflen +
|
||||
@@ -772,8 +811,29 @@ int rndis_filter_send(struct hv_device *dev,
|
||||
|
||||
rndis_pkt = &rndis_msg->msg.pkt;
|
||||
rndis_pkt->data_offset = sizeof(struct rndis_packet);
|
||||
+ if (isvlan)
|
||||
+ rndis_pkt->data_offset += NDIS_VLAN_PPI_SIZE;
|
||||
rndis_pkt->data_len = pkt->total_data_buflen;
|
||||
|
||||
+ if (isvlan) {
|
||||
+ struct rndis_per_packet_info *ppi;
|
||||
+ struct ndis_pkt_8021q_info *vlan;
|
||||
+
|
||||
+ rndis_pkt->per_pkt_info_offset = sizeof(struct rndis_packet);
|
||||
+ rndis_pkt->per_pkt_info_len = NDIS_VLAN_PPI_SIZE;
|
||||
+
|
||||
+ ppi = (struct rndis_per_packet_info *)((ulong)rndis_pkt +
|
||||
+ rndis_pkt->per_pkt_info_offset);
|
||||
+ ppi->size = NDIS_VLAN_PPI_SIZE;
|
||||
+ ppi->type = IEEE_8021Q_INFO;
|
||||
+ ppi->ppi_offset = sizeof(struct rndis_per_packet_info);
|
||||
+
|
||||
+ vlan = (struct ndis_pkt_8021q_info *)((ulong)ppi +
|
||||
+ ppi->ppi_offset);
|
||||
+ vlan->vlanid = pkt->vlan_tci & VLAN_VID_MASK;
|
||||
+ vlan->pri = (pkt->vlan_tci & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
|
||||
+ }
|
||||
+
|
||||
pkt->is_data_pkt = true;
|
||||
pkt->page_buf[0].pfn = virt_to_phys(rndis_msg) >> PAGE_SHIFT;
|
||||
pkt->page_buf[0].offset =
|
||||
--
|
||||
1.7.9.5
|
||||
|
109
debian/patches/features/x86/hyperv/0071-Drivers-hv-Add-new-message-types-to-enhance-KVP.patch
vendored
Normal file
109
debian/patches/features/x86/hyperv/0071-Drivers-hv-Add-new-message-types-to-enhance-KVP.patch
vendored
Normal file
|
@ -0,0 +1,109 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Sat, 10 Mar 2012 15:32:08 -0800
|
||||
Subject: [PATCH 71/77] Drivers: hv: Add new message types to enhance KVP
|
||||
|
||||
commit e485ceac9ebd43901ef0ce13622385d509e072e7 upstream.
|
||||
|
||||
Add additional KVP (Key Value Pair) protocol messages to
|
||||
enhance KVP functionality for Linux guests on Hyper-V. As part of this,
|
||||
patch define an explicit version negoitiation message.
|
||||
|
||||
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/hv/hv_kvp.c | 5 +++--
|
||||
include/linux/hyperv.h | 30 +++++++++++++++++++++++++++---
|
||||
tools/hv/hv_kvp_daemon.c | 2 +-
|
||||
3 files changed, 31 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
|
||||
index 0ef4c1f..779109b 100644
|
||||
--- a/drivers/hv/hv_kvp.c
|
||||
+++ b/drivers/hv/hv_kvp.c
|
||||
@@ -78,7 +78,7 @@ kvp_register(void)
|
||||
|
||||
if (msg) {
|
||||
kvp_msg = (struct hv_kvp_msg *)msg->data;
|
||||
- version = kvp_msg->body.kvp_version;
|
||||
+ version = kvp_msg->body.kvp_register.version;
|
||||
msg->id.idx = CN_KVP_IDX;
|
||||
msg->id.val = CN_KVP_VAL;
|
||||
|
||||
@@ -122,7 +122,8 @@ kvp_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
|
||||
* to the host. But first, cancel the timeout.
|
||||
*/
|
||||
if (cancel_delayed_work_sync(&kvp_work))
|
||||
- kvp_respond_to_host(data->data.key, data->data.value,
|
||||
+ kvp_respond_to_host(data->data.key,
|
||||
+ data->data.value,
|
||||
!strlen(data->data.key));
|
||||
}
|
||||
}
|
||||
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
|
||||
index e57a6c6..a2d8c54 100644
|
||||
--- a/include/linux/hyperv.h
|
||||
+++ b/include/linux/hyperv.h
|
||||
@@ -149,7 +149,11 @@ struct hv_kvp_exchg_msg_value {
|
||||
__u32 key_size;
|
||||
__u32 value_size;
|
||||
__u8 key[HV_KVP_EXCHANGE_MAX_KEY_SIZE];
|
||||
- __u8 value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE];
|
||||
+ union {
|
||||
+ __u8 value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE];
|
||||
+ __u32 value_u32;
|
||||
+ __u64 value_u64;
|
||||
+ };
|
||||
} __attribute__((packed));
|
||||
|
||||
struct hv_kvp_msg_enumerate {
|
||||
@@ -157,11 +161,31 @@ struct hv_kvp_msg_enumerate {
|
||||
struct hv_kvp_exchg_msg_value data;
|
||||
} __attribute__((packed));
|
||||
|
||||
+struct hv_kvp_msg_get {
|
||||
+ struct hv_kvp_exchg_msg_value data;
|
||||
+};
|
||||
+
|
||||
+struct hv_kvp_msg_set {
|
||||
+ struct hv_kvp_exchg_msg_value data;
|
||||
+};
|
||||
+
|
||||
+struct hv_kvp_msg_delete {
|
||||
+ __u32 key_size;
|
||||
+ __u8 key[HV_KVP_EXCHANGE_MAX_KEY_SIZE];
|
||||
+};
|
||||
+
|
||||
+struct hv_kvp_register {
|
||||
+ __u8 version[HV_KVP_EXCHANGE_MAX_KEY_SIZE];
|
||||
+};
|
||||
+
|
||||
struct hv_kvp_msg {
|
||||
struct hv_kvp_hdr kvp_hdr;
|
||||
union {
|
||||
- struct hv_kvp_msg_enumerate kvp_enum_data;
|
||||
- char kvp_version[HV_KVP_EXCHANGE_MAX_KEY_SIZE];
|
||||
+ struct hv_kvp_msg_get kvp_get;
|
||||
+ struct hv_kvp_msg_set kvp_set;
|
||||
+ struct hv_kvp_msg_delete kvp_delete;
|
||||
+ struct hv_kvp_msg_enumerate kvp_enum_data;
|
||||
+ struct hv_kvp_register kvp_register;
|
||||
} body;
|
||||
} __attribute__((packed));
|
||||
|
||||
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
|
||||
index 4ebf703..00d3f7c 100644
|
||||
--- a/tools/hv/hv_kvp_daemon.c
|
||||
+++ b/tools/hv/hv_kvp_daemon.c
|
||||
@@ -378,7 +378,7 @@ int main(void)
|
||||
* Driver is registering with us; stash away the version
|
||||
* information.
|
||||
*/
|
||||
- p = (char *)hv_msg->body.kvp_version;
|
||||
+ p = (char *)hv_msg->body.kvp_register.version;
|
||||
lic_version = malloc(strlen(p) + 1);
|
||||
if (lic_version) {
|
||||
strcpy(lic_version, p);
|
||||
--
|
||||
1.7.9.5
|
||||
|
53
debian/patches/features/x86/hyperv/0072-net-hyperv-fix-erroneous-NETDEV_TX_BUSY-use.patch
vendored
Normal file
53
debian/patches/features/x86/hyperv/0072-net-hyperv-fix-erroneous-NETDEV_TX_BUSY-use.patch
vendored
Normal file
|
@ -0,0 +1,53 @@
|
|||
From: Eric Dumazet <eric.dumazet@gmail.com>
|
||||
Date: Wed, 14 Mar 2012 08:53:34 +0000
|
||||
Subject: [PATCH 72/77] net/hyperv: fix erroneous NETDEV_TX_BUSY use
|
||||
|
||||
commit bb6d5e76fb4fba9aa36726db41404512f3286c0f upstream.
|
||||
|
||||
A driver start_xmit() method cannot free skb and return NETDEV_TX_BUSY,
|
||||
since caller is going to reuse freed skb.
|
||||
|
||||
This is mostly a revert of commit bf769375c (staging: hv: fix the return
|
||||
status of netvsc_start_xmit())
|
||||
|
||||
In fact netif_tx_stop_queue() / netif_stop_queue() is needed before
|
||||
returning NETDEV_TX_BUSY or you can trigger a ksoftirqd fatal loop.
|
||||
|
||||
In case of memory allocation error, only safe way is to drop the packet
|
||||
and return NETDEV_TX_OK
|
||||
|
||||
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
|
||||
Cc: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Cc: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/hyperv/netvsc_drv.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
|
||||
index 0f8e834..2517d20 100644
|
||||
--- a/drivers/net/hyperv/netvsc_drv.c
|
||||
+++ b/drivers/net/hyperv/netvsc_drv.c
|
||||
@@ -167,7 +167,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
|
||||
|
||||
dev_kfree_skb(skb);
|
||||
net->stats.tx_dropped++;
|
||||
- return NETDEV_TX_BUSY;
|
||||
+ return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
packet->vlan_tci = skb->vlan_tci;
|
||||
@@ -229,7 +229,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
||||
- return ret ? NETDEV_TX_BUSY : NETDEV_TX_OK;
|
||||
+ return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
--
|
||||
1.7.9.5
|
||||
|
401
debian/patches/features/x86/hyperv/0073-Drivers-hv-Support-the-newly-introduced-KVP-messages.patch
vendored
Normal file
401
debian/patches/features/x86/hyperv/0073-Drivers-hv-Support-the-newly-introduced-KVP-messages.patch
vendored
Normal file
|
@ -0,0 +1,401 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Fri, 16 Mar 2012 08:02:25 -0700
|
||||
Subject: [PATCH 73/77] Drivers: hv: Support the newly introduced KVP messages
|
||||
in the driver
|
||||
|
||||
commit fa3d5b85c681518b6e4ec515814dcb2d5b702b89 upstream.
|
||||
|
||||
Support the newly defined KVP message types. It turns out that the host
|
||||
pushes a set of standard key value pairs as soon as the guest opens the KVP channel.
|
||||
Since we cannot handle these tuples until the user level daemon loads up, defer
|
||||
reading the KVP channel until the user level daemon is launched.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Reviewed-by: Dan Carpenter <dan.carpenter@oracle.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/hv/hv_kvp.c | 218 +++++++++++++++++++++++++++++++++++-----------
|
||||
include/linux/hyperv.h | 2 +
|
||||
tools/hv/hv_kvp_daemon.c | 7 ++
|
||||
3 files changed, 176 insertions(+), 51 deletions(-)
|
||||
|
||||
diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
|
||||
index 779109b..cfe60b0 100644
|
||||
--- a/drivers/hv/hv_kvp.c
|
||||
+++ b/drivers/hv/hv_kvp.c
|
||||
@@ -42,9 +42,10 @@
|
||||
static struct {
|
||||
bool active; /* transaction status - active or not */
|
||||
int recv_len; /* number of bytes received. */
|
||||
- int index; /* current index */
|
||||
+ struct hv_kvp_msg *kvp_msg; /* current message */
|
||||
struct vmbus_channel *recv_channel; /* chn we got the request */
|
||||
u64 recv_req_id; /* request ID. */
|
||||
+ void *kvp_context; /* for the channel callback */
|
||||
} kvp_transaction;
|
||||
|
||||
static void kvp_send_key(struct work_struct *dummy);
|
||||
@@ -110,12 +111,15 @@ kvp_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
|
||||
struct hv_kvp_msg_enumerate *data;
|
||||
|
||||
message = (struct hv_kvp_msg *)msg->data;
|
||||
- if (message->kvp_hdr.operation == KVP_OP_REGISTER) {
|
||||
+ switch (message->kvp_hdr.operation) {
|
||||
+ case KVP_OP_REGISTER:
|
||||
pr_info("KVP: user-mode registering done.\n");
|
||||
kvp_register();
|
||||
- }
|
||||
+ kvp_transaction.active = false;
|
||||
+ hv_kvp_onchannelcallback(kvp_transaction.kvp_context);
|
||||
+ break;
|
||||
|
||||
- if (message->kvp_hdr.operation == KVP_OP_ENUMERATE) {
|
||||
+ default:
|
||||
data = &message->body.kvp_enum_data;
|
||||
/*
|
||||
* Complete the transaction by forwarding the key value
|
||||
@@ -133,21 +137,104 @@ kvp_send_key(struct work_struct *dummy)
|
||||
{
|
||||
struct cn_msg *msg;
|
||||
struct hv_kvp_msg *message;
|
||||
- int index = kvp_transaction.index;
|
||||
+ struct hv_kvp_msg *in_msg;
|
||||
+ __u8 operation = kvp_transaction.kvp_msg->kvp_hdr.operation;
|
||||
+ __u8 pool = kvp_transaction.kvp_msg->kvp_hdr.pool;
|
||||
+ __u32 val32;
|
||||
+ __u64 val64;
|
||||
|
||||
msg = kzalloc(sizeof(*msg) + sizeof(struct hv_kvp_msg) , GFP_ATOMIC);
|
||||
+ if (!msg)
|
||||
+ return;
|
||||
|
||||
- if (msg) {
|
||||
- msg->id.idx = CN_KVP_IDX;
|
||||
- msg->id.val = CN_KVP_VAL;
|
||||
+ msg->id.idx = CN_KVP_IDX;
|
||||
+ msg->id.val = CN_KVP_VAL;
|
||||
|
||||
- message = (struct hv_kvp_msg *)msg->data;
|
||||
- message->kvp_hdr.operation = KVP_OP_ENUMERATE;
|
||||
- message->body.kvp_enum_data.index = index;
|
||||
- msg->len = sizeof(struct hv_kvp_msg);
|
||||
- cn_netlink_send(msg, 0, GFP_ATOMIC);
|
||||
- kfree(msg);
|
||||
+ message = (struct hv_kvp_msg *)msg->data;
|
||||
+ message->kvp_hdr.operation = operation;
|
||||
+ message->kvp_hdr.pool = pool;
|
||||
+ in_msg = kvp_transaction.kvp_msg;
|
||||
+
|
||||
+ /*
|
||||
+ * The key/value strings sent from the host are encoded in
|
||||
+ * in utf16; convert it to utf8 strings.
|
||||
+ * The host assures us that the utf16 strings will not exceed
|
||||
+ * the max lengths specified. We will however, reserve room
|
||||
+ * for the string terminating character - in the utf16s_utf8s()
|
||||
+ * function we limit the size of the buffer where the converted
|
||||
+ * string is placed to HV_KVP_EXCHANGE_MAX_*_SIZE -1 to gaurantee
|
||||
+ * that the strings can be properly terminated!
|
||||
+ */
|
||||
+
|
||||
+ switch (message->kvp_hdr.operation) {
|
||||
+ case KVP_OP_SET:
|
||||
+ switch (in_msg->body.kvp_set.data.value_type) {
|
||||
+ case REG_SZ:
|
||||
+ /*
|
||||
+ * The value is a string - utf16 encoding.
|
||||
+ */
|
||||
+ message->body.kvp_set.data.value_size =
|
||||
+ utf16s_to_utf8s(
|
||||
+ (wchar_t *)in_msg->body.kvp_set.data.value,
|
||||
+ in_msg->body.kvp_set.data.value_size,
|
||||
+ UTF16_LITTLE_ENDIAN,
|
||||
+ message->body.kvp_set.data.value,
|
||||
+ HV_KVP_EXCHANGE_MAX_VALUE_SIZE - 1) + 1;
|
||||
+ break;
|
||||
+
|
||||
+ case REG_U32:
|
||||
+ /*
|
||||
+ * The value is a 32 bit scalar.
|
||||
+ * We save this as a utf8 string.
|
||||
+ */
|
||||
+ val32 = in_msg->body.kvp_set.data.value_u32;
|
||||
+ message->body.kvp_set.data.value_size =
|
||||
+ sprintf(message->body.kvp_set.data.value,
|
||||
+ "%d", val32) + 1;
|
||||
+ break;
|
||||
+
|
||||
+ case REG_U64:
|
||||
+ /*
|
||||
+ * The value is a 64 bit scalar.
|
||||
+ * We save this as a utf8 string.
|
||||
+ */
|
||||
+ val64 = in_msg->body.kvp_set.data.value_u64;
|
||||
+ message->body.kvp_set.data.value_size =
|
||||
+ sprintf(message->body.kvp_set.data.value,
|
||||
+ "%llu", val64) + 1;
|
||||
+ break;
|
||||
+
|
||||
+ }
|
||||
+ case KVP_OP_GET:
|
||||
+ message->body.kvp_set.data.key_size =
|
||||
+ utf16s_to_utf8s(
|
||||
+ (wchar_t *)in_msg->body.kvp_set.data.key,
|
||||
+ in_msg->body.kvp_set.data.key_size,
|
||||
+ UTF16_LITTLE_ENDIAN,
|
||||
+ message->body.kvp_set.data.key,
|
||||
+ HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1) + 1;
|
||||
+ break;
|
||||
+
|
||||
+ case KVP_OP_DELETE:
|
||||
+ message->body.kvp_delete.key_size =
|
||||
+ utf16s_to_utf8s(
|
||||
+ (wchar_t *)in_msg->body.kvp_delete.key,
|
||||
+ in_msg->body.kvp_delete.key_size,
|
||||
+ UTF16_LITTLE_ENDIAN,
|
||||
+ message->body.kvp_delete.key,
|
||||
+ HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1) + 1;
|
||||
+ break;
|
||||
+
|
||||
+ case KVP_OP_ENUMERATE:
|
||||
+ message->body.kvp_enum_data.index =
|
||||
+ in_msg->body.kvp_enum_data.index;
|
||||
+ break;
|
||||
}
|
||||
+
|
||||
+ msg->len = sizeof(struct hv_kvp_msg);
|
||||
+ cn_netlink_send(msg, 0, GFP_ATOMIC);
|
||||
+ kfree(msg);
|
||||
+
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -159,10 +246,11 @@ static void
|
||||
kvp_respond_to_host(char *key, char *value, int error)
|
||||
{
|
||||
struct hv_kvp_msg *kvp_msg;
|
||||
- struct hv_kvp_msg_enumerate *kvp_data;
|
||||
+ struct hv_kvp_exchg_msg_value *kvp_data;
|
||||
char *key_name;
|
||||
struct icmsg_hdr *icmsghdrp;
|
||||
- int keylen, valuelen;
|
||||
+ int keylen = 0;
|
||||
+ int valuelen = 0;
|
||||
u32 buf_len;
|
||||
struct vmbus_channel *channel;
|
||||
u64 req_id;
|
||||
@@ -189,6 +277,9 @@ kvp_respond_to_host(char *key, char *value, int error)
|
||||
|
||||
kvp_transaction.active = false;
|
||||
|
||||
+ icmsghdrp = (struct icmsg_hdr *)
|
||||
+ &recv_buffer[sizeof(struct vmbuspipe_hdr)];
|
||||
+
|
||||
if (channel->onchannel_callback == NULL)
|
||||
/*
|
||||
* We have raced with util driver being unloaded;
|
||||
@@ -196,41 +287,66 @@ kvp_respond_to_host(char *key, char *value, int error)
|
||||
*/
|
||||
return;
|
||||
|
||||
- icmsghdrp = (struct icmsg_hdr *)
|
||||
- &recv_buffer[sizeof(struct vmbuspipe_hdr)];
|
||||
- kvp_msg = (struct hv_kvp_msg *)
|
||||
- &recv_buffer[sizeof(struct vmbuspipe_hdr) +
|
||||
- sizeof(struct icmsg_hdr)];
|
||||
- kvp_data = &kvp_msg->body.kvp_enum_data;
|
||||
- key_name = key;
|
||||
|
||||
/*
|
||||
* If the error parameter is set, terminate the host's enumeration.
|
||||
*/
|
||||
if (error) {
|
||||
/*
|
||||
- * We don't support this index or the we have timedout;
|
||||
+ * Something failed or the we have timedout;
|
||||
* terminate the host-side iteration by returning an error.
|
||||
*/
|
||||
icmsghdrp->status = HV_E_FAIL;
|
||||
goto response_done;
|
||||
}
|
||||
|
||||
+ icmsghdrp->status = HV_S_OK;
|
||||
+
|
||||
+ kvp_msg = (struct hv_kvp_msg *)
|
||||
+ &recv_buffer[sizeof(struct vmbuspipe_hdr) +
|
||||
+ sizeof(struct icmsg_hdr)];
|
||||
+
|
||||
+ switch (kvp_transaction.kvp_msg->kvp_hdr.operation) {
|
||||
+ case KVP_OP_GET:
|
||||
+ kvp_data = &kvp_msg->body.kvp_get.data;
|
||||
+ goto copy_value;
|
||||
+
|
||||
+ case KVP_OP_SET:
|
||||
+ case KVP_OP_DELETE:
|
||||
+ goto response_done;
|
||||
+
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ kvp_data = &kvp_msg->body.kvp_enum_data.data;
|
||||
+ key_name = key;
|
||||
+
|
||||
/*
|
||||
* The windows host expects the key/value pair to be encoded
|
||||
- * in utf16.
|
||||
+ * in utf16. Ensure that the key/value size reported to the host
|
||||
+ * will be less than or equal to the MAX size (including the
|
||||
+ * terminating character).
|
||||
*/
|
||||
keylen = utf8s_to_utf16s(key_name, strlen(key_name), UTF16_HOST_ENDIAN,
|
||||
- (wchar_t *) kvp_data->data.key,
|
||||
- HV_KVP_EXCHANGE_MAX_KEY_SIZE / 2);
|
||||
- kvp_data->data.key_size = 2*(keylen + 1); /* utf16 encoding */
|
||||
+ (wchar_t *) kvp_data->key,
|
||||
+ (HV_KVP_EXCHANGE_MAX_KEY_SIZE / 2) - 2);
|
||||
+ kvp_data->key_size = 2*(keylen + 1); /* utf16 encoding */
|
||||
+
|
||||
+copy_value:
|
||||
valuelen = utf8s_to_utf16s(value, strlen(value), UTF16_HOST_ENDIAN,
|
||||
- (wchar_t *) kvp_data->data.value,
|
||||
- HV_KVP_EXCHANGE_MAX_VALUE_SIZE / 2);
|
||||
- kvp_data->data.value_size = 2*(valuelen + 1); /* utf16 encoding */
|
||||
+ (wchar_t *) kvp_data->value,
|
||||
+ (HV_KVP_EXCHANGE_MAX_VALUE_SIZE / 2) - 2);
|
||||
+ kvp_data->value_size = 2*(valuelen + 1); /* utf16 encoding */
|
||||
|
||||
- kvp_data->data.value_type = REG_SZ; /* all our values are strings */
|
||||
- icmsghdrp->status = HV_S_OK;
|
||||
+ /*
|
||||
+ * If the utf8s to utf16s conversion failed; notify host
|
||||
+ * of the error.
|
||||
+ */
|
||||
+ if ((keylen < 0) || (valuelen < 0))
|
||||
+ icmsghdrp->status = HV_E_FAIL;
|
||||
+
|
||||
+ kvp_data->value_type = REG_SZ; /* all our values are strings */
|
||||
|
||||
response_done:
|
||||
icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE;
|
||||
@@ -257,11 +373,18 @@ void hv_kvp_onchannelcallback(void *context)
|
||||
u64 requestid;
|
||||
|
||||
struct hv_kvp_msg *kvp_msg;
|
||||
- struct hv_kvp_msg_enumerate *kvp_data;
|
||||
|
||||
struct icmsg_hdr *icmsghdrp;
|
||||
struct icmsg_negotiate *negop = NULL;
|
||||
|
||||
+ if (kvp_transaction.active) {
|
||||
+ /*
|
||||
+ * We will defer processing this callback once
|
||||
+ * the current transaction is complete.
|
||||
+ */
|
||||
+ kvp_transaction.kvp_context = context;
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE, &recvlen, &requestid);
|
||||
|
||||
@@ -276,29 +399,16 @@ void hv_kvp_onchannelcallback(void *context)
|
||||
sizeof(struct vmbuspipe_hdr) +
|
||||
sizeof(struct icmsg_hdr)];
|
||||
|
||||
- kvp_data = &kvp_msg->body.kvp_enum_data;
|
||||
-
|
||||
- /*
|
||||
- * We only support the "get" operation on
|
||||
- * "KVP_POOL_AUTO" pool.
|
||||
- */
|
||||
-
|
||||
- if ((kvp_msg->kvp_hdr.pool != KVP_POOL_AUTO) ||
|
||||
- (kvp_msg->kvp_hdr.operation !=
|
||||
- KVP_OP_ENUMERATE)) {
|
||||
- icmsghdrp->status = HV_E_FAIL;
|
||||
- goto callback_done;
|
||||
- }
|
||||
-
|
||||
/*
|
||||
* Stash away this global state for completing the
|
||||
* transaction; note transactions are serialized.
|
||||
*/
|
||||
+
|
||||
kvp_transaction.recv_len = recvlen;
|
||||
kvp_transaction.recv_channel = channel;
|
||||
kvp_transaction.recv_req_id = requestid;
|
||||
kvp_transaction.active = true;
|
||||
- kvp_transaction.index = kvp_data->index;
|
||||
+ kvp_transaction.kvp_msg = kvp_msg;
|
||||
|
||||
/*
|
||||
* Get the information from the
|
||||
@@ -316,8 +426,6 @@ void hv_kvp_onchannelcallback(void *context)
|
||||
|
||||
}
|
||||
|
||||
-callback_done:
|
||||
-
|
||||
icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
|
||||
| ICMSGHDRFLAG_RESPONSE;
|
||||
|
||||
@@ -338,6 +446,14 @@ hv_kvp_init(struct hv_util_service *srv)
|
||||
return err;
|
||||
recv_buffer = srv->recv_buffer;
|
||||
|
||||
+ /*
|
||||
+ * When this driver loads, the user level daemon that
|
||||
+ * processes the host requests may not yet be running.
|
||||
+ * Defer processing channel callbacks until the daemon
|
||||
+ * has registered.
|
||||
+ */
|
||||
+ kvp_transaction.active = true;
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
|
||||
index a2d8c54..e88a979 100644
|
||||
--- a/include/linux/hyperv.h
|
||||
+++ b/include/linux/hyperv.h
|
||||
@@ -119,6 +119,8 @@
|
||||
*/
|
||||
|
||||
#define REG_SZ 1
|
||||
+#define REG_U32 4
|
||||
+#define REG_U64 8
|
||||
|
||||
enum hv_kvp_exchg_op {
|
||||
KVP_OP_GET = 0,
|
||||
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
|
||||
index 00d3f7c..a98878c 100644
|
||||
--- a/tools/hv/hv_kvp_daemon.c
|
||||
+++ b/tools/hv/hv_kvp_daemon.c
|
||||
@@ -389,10 +389,16 @@ int main(void)
|
||||
}
|
||||
continue;
|
||||
|
||||
+ case KVP_OP_SET:
|
||||
+ case KVP_OP_GET:
|
||||
+ case KVP_OP_DELETE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
+ if (hv_msg->kvp_hdr.operation != KVP_OP_ENUMERATE)
|
||||
+ goto kvp_done;
|
||||
+
|
||||
hv_msg = (struct hv_kvp_msg *)incoming_cn_msg->data;
|
||||
key_name = (char *)hv_msg->body.kvp_enum_data.data.key;
|
||||
key_value = (char *)hv_msg->body.kvp_enum_data.data.value;
|
||||
@@ -454,6 +460,7 @@ int main(void)
|
||||
* already in the receive buffer. Update the cn_msg header to
|
||||
* reflect the key value that has been added to the message
|
||||
*/
|
||||
+kvp_done:
|
||||
|
||||
incoming_cn_msg->id.idx = CN_KVP_IDX;
|
||||
incoming_cn_msg->id.val = CN_KVP_VAL;
|
||||
--
|
||||
1.7.9.5
|
||||
|
339
debian/patches/features/x86/hyperv/0074-Tools-hv-Fully-support-the-new-KVP-verbs-in-the-user.patch
vendored
Normal file
339
debian/patches/features/x86/hyperv/0074-Tools-hv-Fully-support-the-new-KVP-verbs-in-the-user.patch
vendored
Normal file
|
@ -0,0 +1,339 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Fri, 16 Mar 2012 08:02:26 -0700
|
||||
Subject: [PATCH 74/77] Tools: hv: Fully support the new KVP verbs in the user
|
||||
level daemon
|
||||
|
||||
commit db425334e5bb7fa65bbbd7bea9d79842f65bcf45 upstream.
|
||||
|
||||
Now fully support the new KVP messages in the user level daemon. Hyper-V defines
|
||||
multiple persistent pools to which the host can write/read/modify KVP tuples.
|
||||
In this patch we implement a file for each specified pool, where the KVP tuples
|
||||
will be stored in the guest.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Reviewed-by: Dan Carpenter <dan.carpenter@oracle.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
tools/hv/hv_kvp_daemon.c | 281 +++++++++++++++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 280 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
|
||||
index a98878c..2fb9c3d 100644
|
||||
--- a/tools/hv/hv_kvp_daemon.c
|
||||
+++ b/tools/hv/hv_kvp_daemon.c
|
||||
@@ -39,7 +39,8 @@
|
||||
#include <ifaddrs.h>
|
||||
#include <netdb.h>
|
||||
#include <syslog.h>
|
||||
-
|
||||
+#include <sys/stat.h>
|
||||
+#include <fcntl.h>
|
||||
|
||||
/*
|
||||
* KVP protocol: The user mode component first registers with the
|
||||
@@ -79,6 +80,250 @@ static char *os_build;
|
||||
static char *lic_version;
|
||||
static struct utsname uts_buf;
|
||||
|
||||
+
|
||||
+#define MAX_FILE_NAME 100
|
||||
+#define ENTRIES_PER_BLOCK 50
|
||||
+
|
||||
+struct kvp_record {
|
||||
+ __u8 key[HV_KVP_EXCHANGE_MAX_KEY_SIZE];
|
||||
+ __u8 value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE];
|
||||
+};
|
||||
+
|
||||
+struct kvp_file_state {
|
||||
+ int fd;
|
||||
+ int num_blocks;
|
||||
+ struct kvp_record *records;
|
||||
+ int num_records;
|
||||
+ __u8 fname[MAX_FILE_NAME];
|
||||
+};
|
||||
+
|
||||
+static struct kvp_file_state kvp_file_info[KVP_POOL_COUNT];
|
||||
+
|
||||
+static void kvp_acquire_lock(int pool)
|
||||
+{
|
||||
+ struct flock fl = {F_WRLCK, SEEK_SET, 0, 0, 0};
|
||||
+ fl.l_pid = getpid();
|
||||
+
|
||||
+ if (fcntl(kvp_file_info[pool].fd, F_SETLKW, &fl) == -1) {
|
||||
+ syslog(LOG_ERR, "Failed to acquire the lock pool: %d", pool);
|
||||
+ exit(-1);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void kvp_release_lock(int pool)
|
||||
+{
|
||||
+ struct flock fl = {F_UNLCK, SEEK_SET, 0, 0, 0};
|
||||
+ fl.l_pid = getpid();
|
||||
+
|
||||
+ if (fcntl(kvp_file_info[pool].fd, F_SETLK, &fl) == -1) {
|
||||
+ perror("fcntl");
|
||||
+ syslog(LOG_ERR, "Failed to release the lock pool: %d", pool);
|
||||
+ exit(-1);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void kvp_update_file(int pool)
|
||||
+{
|
||||
+ FILE *filep;
|
||||
+ size_t bytes_written;
|
||||
+
|
||||
+ /*
|
||||
+ * We are going to write our in-memory registry out to
|
||||
+ * disk; acquire the lock first.
|
||||
+ */
|
||||
+ kvp_acquire_lock(pool);
|
||||
+
|
||||
+ filep = fopen(kvp_file_info[pool].fname, "w");
|
||||
+ if (!filep) {
|
||||
+ kvp_release_lock(pool);
|
||||
+ syslog(LOG_ERR, "Failed to open file, pool: %d", pool);
|
||||
+ exit(-1);
|
||||
+ }
|
||||
+
|
||||
+ bytes_written = fwrite(kvp_file_info[pool].records,
|
||||
+ sizeof(struct kvp_record),
|
||||
+ kvp_file_info[pool].num_records, filep);
|
||||
+
|
||||
+ fflush(filep);
|
||||
+ kvp_release_lock(pool);
|
||||
+}
|
||||
+
|
||||
+static int kvp_file_init(void)
|
||||
+{
|
||||
+ int ret, fd;
|
||||
+ FILE *filep;
|
||||
+ size_t records_read;
|
||||
+ __u8 *fname;
|
||||
+ struct kvp_record *record;
|
||||
+ struct kvp_record *readp;
|
||||
+ int num_blocks;
|
||||
+ int i;
|
||||
+ int alloc_unit = sizeof(struct kvp_record) * ENTRIES_PER_BLOCK;
|
||||
+
|
||||
+ if (access("/var/opt/hyperv", F_OK)) {
|
||||
+ if (mkdir("/var/opt/hyperv", S_IRUSR | S_IWUSR | S_IROTH)) {
|
||||
+ syslog(LOG_ERR, " Failed to create /var/opt/hyperv");
|
||||
+ exit(-1);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < KVP_POOL_COUNT; i++) {
|
||||
+ fname = kvp_file_info[i].fname;
|
||||
+ records_read = 0;
|
||||
+ num_blocks = 1;
|
||||
+ sprintf(fname, "/var/opt/hyperv/.kvp_pool_%d", i);
|
||||
+ fd = open(fname, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IROTH);
|
||||
+
|
||||
+ if (fd == -1)
|
||||
+ return 1;
|
||||
+
|
||||
+
|
||||
+ filep = fopen(fname, "r");
|
||||
+ if (!filep)
|
||||
+ return 1;
|
||||
+
|
||||
+ record = malloc(alloc_unit * num_blocks);
|
||||
+ if (record == NULL) {
|
||||
+ fclose(filep);
|
||||
+ return 1;
|
||||
+ }
|
||||
+ while (!feof(filep)) {
|
||||
+ readp = &record[records_read];
|
||||
+ records_read += fread(readp, sizeof(struct kvp_record),
|
||||
+ ENTRIES_PER_BLOCK,
|
||||
+ filep);
|
||||
+
|
||||
+ if (!feof(filep)) {
|
||||
+ /*
|
||||
+ * We have more data to read.
|
||||
+ */
|
||||
+ num_blocks++;
|
||||
+ record = realloc(record, alloc_unit *
|
||||
+ num_blocks);
|
||||
+ if (record == NULL) {
|
||||
+ fclose(filep);
|
||||
+ return 1;
|
||||
+ }
|
||||
+ continue;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ kvp_file_info[i].fd = fd;
|
||||
+ kvp_file_info[i].num_blocks = num_blocks;
|
||||
+ kvp_file_info[i].records = record;
|
||||
+ kvp_file_info[i].num_records = records_read;
|
||||
+ fclose(filep);
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int kvp_key_delete(int pool, __u8 *key, int key_size)
|
||||
+{
|
||||
+ int i;
|
||||
+ int j, k;
|
||||
+ int num_records = kvp_file_info[pool].num_records;
|
||||
+ struct kvp_record *record = kvp_file_info[pool].records;
|
||||
+
|
||||
+ for (i = 0; i < num_records; i++) {
|
||||
+ if (memcmp(key, record[i].key, key_size))
|
||||
+ continue;
|
||||
+ /*
|
||||
+ * Found a match; just move the remaining
|
||||
+ * entries up.
|
||||
+ */
|
||||
+ if (i == num_records) {
|
||||
+ kvp_file_info[pool].num_records--;
|
||||
+ kvp_update_file(pool);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ j = i;
|
||||
+ k = j + 1;
|
||||
+ for (; k < num_records; k++) {
|
||||
+ strcpy(record[j].key, record[k].key);
|
||||
+ strcpy(record[j].value, record[k].value);
|
||||
+ j++;
|
||||
+ }
|
||||
+
|
||||
+ kvp_file_info[pool].num_records--;
|
||||
+ kvp_update_file(pool);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+static int kvp_key_add_or_modify(int pool, __u8 *key, int key_size, __u8 *value,
|
||||
+ int value_size)
|
||||
+{
|
||||
+ int i;
|
||||
+ int j, k;
|
||||
+ int num_records = kvp_file_info[pool].num_records;
|
||||
+ struct kvp_record *record = kvp_file_info[pool].records;
|
||||
+ int num_blocks = kvp_file_info[pool].num_blocks;
|
||||
+
|
||||
+ if ((key_size > HV_KVP_EXCHANGE_MAX_KEY_SIZE) ||
|
||||
+ (value_size > HV_KVP_EXCHANGE_MAX_VALUE_SIZE))
|
||||
+ return 1;
|
||||
+
|
||||
+ for (i = 0; i < num_records; i++) {
|
||||
+ if (memcmp(key, record[i].key, key_size))
|
||||
+ continue;
|
||||
+ /*
|
||||
+ * Found a match; just update the value -
|
||||
+ * this is the modify case.
|
||||
+ */
|
||||
+ memcpy(record[i].value, value, value_size);
|
||||
+ kvp_update_file(pool);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Need to add a new entry;
|
||||
+ */
|
||||
+ if (num_records == (ENTRIES_PER_BLOCK * num_blocks)) {
|
||||
+ /* Need to allocate a larger array for reg entries. */
|
||||
+ record = realloc(record, sizeof(struct kvp_record) *
|
||||
+ ENTRIES_PER_BLOCK * (num_blocks + 1));
|
||||
+
|
||||
+ if (record == NULL)
|
||||
+ return 1;
|
||||
+ kvp_file_info[pool].num_blocks++;
|
||||
+
|
||||
+ }
|
||||
+ memcpy(record[i].value, value, value_size);
|
||||
+ memcpy(record[i].key, key, key_size);
|
||||
+ kvp_file_info[pool].records = record;
|
||||
+ kvp_file_info[pool].num_records++;
|
||||
+ kvp_update_file(pool);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int kvp_get_value(int pool, __u8 *key, int key_size, __u8 *value,
|
||||
+ int value_size)
|
||||
+{
|
||||
+ int i;
|
||||
+ int num_records = kvp_file_info[pool].num_records;
|
||||
+ struct kvp_record *record = kvp_file_info[pool].records;
|
||||
+
|
||||
+ if ((key_size > HV_KVP_EXCHANGE_MAX_KEY_SIZE) ||
|
||||
+ (value_size > HV_KVP_EXCHANGE_MAX_VALUE_SIZE))
|
||||
+ return 1;
|
||||
+
|
||||
+ for (i = 0; i < num_records; i++) {
|
||||
+ if (memcmp(key, record[i].key, key_size))
|
||||
+ continue;
|
||||
+ /*
|
||||
+ * Found a match; just copy the value out.
|
||||
+ */
|
||||
+ memcpy(value, record[i].value, value_size);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
void kvp_get_os_info(void)
|
||||
{
|
||||
FILE *file;
|
||||
@@ -315,6 +560,11 @@ int main(void)
|
||||
*/
|
||||
kvp_get_os_info();
|
||||
|
||||
+ if (kvp_file_init()) {
|
||||
+ syslog(LOG_ERR, "Failed to initialize the pools");
|
||||
+ exit(-1);
|
||||
+ }
|
||||
+
|
||||
fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
|
||||
if (fd < 0) {
|
||||
syslog(LOG_ERR, "netlink socket creation failed; error:%d", fd);
|
||||
@@ -389,9 +639,38 @@ int main(void)
|
||||
}
|
||||
continue;
|
||||
|
||||
+ /*
|
||||
+ * The current protocol with the kernel component uses a
|
||||
+ * NULL key name to pass an error condition.
|
||||
+ * For the SET, GET and DELETE operations,
|
||||
+ * use the existing protocol to pass back error.
|
||||
+ */
|
||||
+
|
||||
case KVP_OP_SET:
|
||||
+ if (kvp_key_add_or_modify(hv_msg->kvp_hdr.pool,
|
||||
+ hv_msg->body.kvp_set.data.key,
|
||||
+ hv_msg->body.kvp_set.data.key_size,
|
||||
+ hv_msg->body.kvp_set.data.value,
|
||||
+ hv_msg->body.kvp_set.data.value_size))
|
||||
+ strcpy(hv_msg->body.kvp_set.data.key, "");
|
||||
+ break;
|
||||
+
|
||||
case KVP_OP_GET:
|
||||
+ if (kvp_get_value(hv_msg->kvp_hdr.pool,
|
||||
+ hv_msg->body.kvp_set.data.key,
|
||||
+ hv_msg->body.kvp_set.data.key_size,
|
||||
+ hv_msg->body.kvp_set.data.value,
|
||||
+ hv_msg->body.kvp_set.data.value_size))
|
||||
+ strcpy(hv_msg->body.kvp_set.data.key, "");
|
||||
+ break;
|
||||
+
|
||||
case KVP_OP_DELETE:
|
||||
+ if (kvp_key_delete(hv_msg->kvp_hdr.pool,
|
||||
+ hv_msg->body.kvp_delete.key,
|
||||
+ hv_msg->body.kvp_delete.key_size))
|
||||
+ strcpy(hv_msg->body.kvp_delete.key, "");
|
||||
+ break;
|
||||
+
|
||||
default:
|
||||
break;
|
||||
}
|
||||
--
|
||||
1.7.9.5
|
||||
|
237
debian/patches/features/x86/hyperv/0075-Tools-hv-Support-enumeration-from-all-the-pools.patch
vendored
Normal file
237
debian/patches/features/x86/hyperv/0075-Tools-hv-Support-enumeration-from-all-the-pools.patch
vendored
Normal file
|
@ -0,0 +1,237 @@
|
|||
From: "K. Y. Srinivasan" <kys@microsoft.com>
|
||||
Date: Fri, 16 Mar 2012 08:02:27 -0700
|
||||
Subject: [PATCH 75/77] Tools: hv: Support enumeration from all the pools
|
||||
|
||||
commit adc80ae60eae24a43a357bf5b30fb496f34aa605 upstream.
|
||||
|
||||
We have only supported enumeration only from the AUTO pool. Now support
|
||||
enumeration from all the available pools.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Reviewed-by: Dan Carpenter <dan.carpenter@oracle.com>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
drivers/hv/hv_kvp.c | 7 +--
|
||||
include/linux/hyperv.h | 1 +
|
||||
tools/hv/hv_kvp_daemon.c | 124 +++++++++++++++++++++++++++++++++++++++++++---
|
||||
3 files changed, 122 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
|
||||
index cfe60b0..6186025 100644
|
||||
--- a/drivers/hv/hv_kvp.c
|
||||
+++ b/drivers/hv/hv_kvp.c
|
||||
@@ -289,14 +289,15 @@ kvp_respond_to_host(char *key, char *value, int error)
|
||||
|
||||
|
||||
/*
|
||||
- * If the error parameter is set, terminate the host's enumeration.
|
||||
+ * If the error parameter is set, terminate the host's enumeration
|
||||
+ * on this pool.
|
||||
*/
|
||||
if (error) {
|
||||
/*
|
||||
* Something failed or the we have timedout;
|
||||
- * terminate the host-side iteration by returning an error.
|
||||
+ * terminate the current host-side iteration.
|
||||
*/
|
||||
- icmsghdrp->status = HV_E_FAIL;
|
||||
+ icmsghdrp->status = HV_S_CONT;
|
||||
goto response_done;
|
||||
}
|
||||
|
||||
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
|
||||
index e88a979..5852545 100644
|
||||
--- a/include/linux/hyperv.h
|
||||
+++ b/include/linux/hyperv.h
|
||||
@@ -952,6 +952,7 @@ void vmbus_driver_unregister(struct hv_driver *hv_driver);
|
||||
|
||||
#define HV_S_OK 0x00000000
|
||||
#define HV_E_FAIL 0x80004005
|
||||
+#define HV_S_CONT 0x80070103
|
||||
#define HV_ERROR_NOT_SUPPORTED 0x80070032
|
||||
#define HV_ERROR_MACHINE_LOCKED 0x800704F7
|
||||
|
||||
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
|
||||
index 2fb9c3d..146fd61 100644
|
||||
--- a/tools/hv/hv_kvp_daemon.c
|
||||
+++ b/tools/hv/hv_kvp_daemon.c
|
||||
@@ -148,6 +148,51 @@ static void kvp_update_file(int pool)
|
||||
kvp_release_lock(pool);
|
||||
}
|
||||
|
||||
+static void kvp_update_mem_state(int pool)
|
||||
+{
|
||||
+ FILE *filep;
|
||||
+ size_t records_read = 0;
|
||||
+ struct kvp_record *record = kvp_file_info[pool].records;
|
||||
+ struct kvp_record *readp;
|
||||
+ int num_blocks = kvp_file_info[pool].num_blocks;
|
||||
+ int alloc_unit = sizeof(struct kvp_record) * ENTRIES_PER_BLOCK;
|
||||
+
|
||||
+ kvp_acquire_lock(pool);
|
||||
+
|
||||
+ filep = fopen(kvp_file_info[pool].fname, "r");
|
||||
+ if (!filep) {
|
||||
+ kvp_release_lock(pool);
|
||||
+ syslog(LOG_ERR, "Failed to open file, pool: %d", pool);
|
||||
+ exit(-1);
|
||||
+ }
|
||||
+ while (!feof(filep)) {
|
||||
+ readp = &record[records_read];
|
||||
+ records_read += fread(readp, sizeof(struct kvp_record),
|
||||
+ ENTRIES_PER_BLOCK * num_blocks,
|
||||
+ filep);
|
||||
+
|
||||
+ if (!feof(filep)) {
|
||||
+ /*
|
||||
+ * We have more data to read.
|
||||
+ */
|
||||
+ num_blocks++;
|
||||
+ record = realloc(record, alloc_unit * num_blocks);
|
||||
+
|
||||
+ if (record == NULL) {
|
||||
+ syslog(LOG_ERR, "malloc failed");
|
||||
+ exit(-1);
|
||||
+ }
|
||||
+ continue;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ kvp_file_info[pool].num_blocks = num_blocks;
|
||||
+ kvp_file_info[pool].records = record;
|
||||
+ kvp_file_info[pool].num_records = records_read;
|
||||
+
|
||||
+ kvp_release_lock(pool);
|
||||
+}
|
||||
static int kvp_file_init(void)
|
||||
{
|
||||
int ret, fd;
|
||||
@@ -223,8 +268,16 @@ static int kvp_key_delete(int pool, __u8 *key, int key_size)
|
||||
{
|
||||
int i;
|
||||
int j, k;
|
||||
- int num_records = kvp_file_info[pool].num_records;
|
||||
- struct kvp_record *record = kvp_file_info[pool].records;
|
||||
+ int num_records;
|
||||
+ struct kvp_record *record;
|
||||
+
|
||||
+ /*
|
||||
+ * First update the in-memory state.
|
||||
+ */
|
||||
+ kvp_update_mem_state(pool);
|
||||
+
|
||||
+ num_records = kvp_file_info[pool].num_records;
|
||||
+ record = kvp_file_info[pool].records;
|
||||
|
||||
for (i = 0; i < num_records; i++) {
|
||||
if (memcmp(key, record[i].key, key_size))
|
||||
@@ -259,14 +312,23 @@ static int kvp_key_add_or_modify(int pool, __u8 *key, int key_size, __u8 *value,
|
||||
{
|
||||
int i;
|
||||
int j, k;
|
||||
- int num_records = kvp_file_info[pool].num_records;
|
||||
- struct kvp_record *record = kvp_file_info[pool].records;
|
||||
- int num_blocks = kvp_file_info[pool].num_blocks;
|
||||
+ int num_records;
|
||||
+ struct kvp_record *record;
|
||||
+ int num_blocks;
|
||||
|
||||
if ((key_size > HV_KVP_EXCHANGE_MAX_KEY_SIZE) ||
|
||||
(value_size > HV_KVP_EXCHANGE_MAX_VALUE_SIZE))
|
||||
return 1;
|
||||
|
||||
+ /*
|
||||
+ * First update the in-memory state.
|
||||
+ */
|
||||
+ kvp_update_mem_state(pool);
|
||||
+
|
||||
+ num_records = kvp_file_info[pool].num_records;
|
||||
+ record = kvp_file_info[pool].records;
|
||||
+ num_blocks = kvp_file_info[pool].num_blocks;
|
||||
+
|
||||
for (i = 0; i < num_records; i++) {
|
||||
if (memcmp(key, record[i].key, key_size))
|
||||
continue;
|
||||
@@ -304,13 +366,21 @@ static int kvp_get_value(int pool, __u8 *key, int key_size, __u8 *value,
|
||||
int value_size)
|
||||
{
|
||||
int i;
|
||||
- int num_records = kvp_file_info[pool].num_records;
|
||||
- struct kvp_record *record = kvp_file_info[pool].records;
|
||||
+ int num_records;
|
||||
+ struct kvp_record *record;
|
||||
|
||||
if ((key_size > HV_KVP_EXCHANGE_MAX_KEY_SIZE) ||
|
||||
(value_size > HV_KVP_EXCHANGE_MAX_VALUE_SIZE))
|
||||
return 1;
|
||||
|
||||
+ /*
|
||||
+ * First update the in-memory state.
|
||||
+ */
|
||||
+ kvp_update_mem_state(pool);
|
||||
+
|
||||
+ num_records = kvp_file_info[pool].num_records;
|
||||
+ record = kvp_file_info[pool].records;
|
||||
+
|
||||
for (i = 0; i < num_records; i++) {
|
||||
if (memcmp(key, record[i].key, key_size))
|
||||
continue;
|
||||
@@ -324,6 +394,31 @@ static int kvp_get_value(int pool, __u8 *key, int key_size, __u8 *value,
|
||||
return 1;
|
||||
}
|
||||
|
||||
+static void kvp_pool_enumerate(int pool, int index, __u8 *key, int key_size,
|
||||
+ __u8 *value, int value_size)
|
||||
+{
|
||||
+ struct kvp_record *record;
|
||||
+
|
||||
+ /*
|
||||
+ * First update our in-memory database.
|
||||
+ */
|
||||
+ kvp_update_mem_state(pool);
|
||||
+ record = kvp_file_info[pool].records;
|
||||
+
|
||||
+ if (index >= kvp_file_info[pool].num_records) {
|
||||
+ /*
|
||||
+ * This is an invalid index; terminate enumeration;
|
||||
+ * - a NULL value will do the trick.
|
||||
+ */
|
||||
+ strcpy(value, "");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ memcpy(key, record[index].key, key_size);
|
||||
+ memcpy(value, record[index].value, value_size);
|
||||
+}
|
||||
+
|
||||
+
|
||||
void kvp_get_os_info(void)
|
||||
{
|
||||
FILE *file;
|
||||
@@ -678,6 +773,21 @@ int main(void)
|
||||
if (hv_msg->kvp_hdr.operation != KVP_OP_ENUMERATE)
|
||||
goto kvp_done;
|
||||
|
||||
+ /*
|
||||
+ * If the pool is KVP_POOL_AUTO, dynamically generate
|
||||
+ * both the key and the value; if not read from the
|
||||
+ * appropriate pool.
|
||||
+ */
|
||||
+ if (hv_msg->kvp_hdr.pool != KVP_POOL_AUTO) {
|
||||
+ kvp_pool_enumerate(hv_msg->kvp_hdr.pool,
|
||||
+ hv_msg->body.kvp_enum_data.index,
|
||||
+ hv_msg->body.kvp_enum_data.data.key,
|
||||
+ HV_KVP_EXCHANGE_MAX_KEY_SIZE,
|
||||
+ hv_msg->body.kvp_enum_data.data.value,
|
||||
+ HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
|
||||
+ goto kvp_done;
|
||||
+ }
|
||||
+
|
||||
hv_msg = (struct hv_kvp_msg *)incoming_cn_msg->data;
|
||||
key_name = (char *)hv_msg->body.kvp_enum_data.data.key;
|
||||
key_value = (char *)hv_msg->body.kvp_enum_data.data.value;
|
||||
--
|
||||
1.7.9.5
|
||||
|
46
debian/patches/features/x86/hyperv/0076-net-hyperv-Fix-the-code-handling-tx-busy.patch
vendored
Normal file
46
debian/patches/features/x86/hyperv/0076-net-hyperv-Fix-the-code-handling-tx-busy.patch
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
From: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Date: Mon, 19 Mar 2012 17:27:06 -0400
|
||||
Subject: [PATCH 76/77] net/hyperv: Fix the code handling tx busy
|
||||
|
||||
commit da24e906cbfc08171d24a2b7cf66fad565fdd121 upstream.
|
||||
|
||||
Instead of dropping the packet, we keep the skb buffer, and return
|
||||
NETDEV_TX_BUSY to let upper layer retry send. This will not cause
|
||||
endless loop, because the host is taking data away from ring buffer,
|
||||
and we have called the stop_queue before returning NETDEV_TX_BUSY.
|
||||
|
||||
The stop_queue was called in the function netvsc_send() in file
|
||||
netvsc.c, then it returns to rndis_filter_send(), which returns to
|
||||
netvsc_start_xmit() in file netvsc_drv.c. So the NETDEV_TX_BUSY is
|
||||
indeed returned AFTER queue is stopped.
|
||||
|
||||
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Reviewed-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Acked-by: Eric Dumazet <eric.dumazet@gmail.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/hyperv/netvsc_drv.c | 5 +----
|
||||
1 file changed, 1 insertion(+), 4 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
|
||||
index 2517d20..dd29478 100644
|
||||
--- a/drivers/net/hyperv/netvsc_drv.c
|
||||
+++ b/drivers/net/hyperv/netvsc_drv.c
|
||||
@@ -223,13 +223,10 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
|
||||
net->stats.tx_bytes += skb->len;
|
||||
net->stats.tx_packets++;
|
||||
} else {
|
||||
- /* we are shutting down or bus overloaded, just drop packet */
|
||||
- net->stats.tx_dropped++;
|
||||
kfree(packet);
|
||||
- dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
||||
- return NETDEV_TX_OK;
|
||||
+ return ret ? NETDEV_TX_BUSY : NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
--
|
||||
1.7.9.5
|
||||
|
144
debian/patches/features/x86/hyperv/0077-hv-remove-the-second-argument-of-k-un-map_atomic.patch
vendored
Normal file
144
debian/patches/features/x86/hyperv/0077-hv-remove-the-second-argument-of-k-un-map_atomic.patch
vendored
Normal file
|
@ -0,0 +1,144 @@
|
|||
From: Cong Wang <amwang@redhat.com>
|
||||
Date: Fri, 25 Nov 2011 23:14:24 +0800
|
||||
Subject: [PATCH 77/77] hv: remove the second argument of k[un]map_atomic()
|
||||
|
||||
commit 86cbce4de23f26f1aee8df789d30b0f1ba78c967 upstream.
|
||||
|
||||
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
Signed-off-by: Cong Wang <amwang@redhat.com>
|
||||
[bwh: Adjust filename to apply after move to drivers/scsi; apply changes
|
||||
from Linux's merge commit 9f3938346a5c1fa504647670edb5fea5756cfb00.]
|
||||
---
|
||||
drivers/scsi/storvsc_drv.c | 52 ++++++++++++++++++++++----------------------
|
||||
1 file changed, 26 insertions(+), 26 deletions(-)
|
||||
|
||||
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
|
||||
index 695ffc3..83a1972 100644
|
||||
--- a/drivers/scsi/storvsc_drv.c
|
||||
+++ b/drivers/scsi/storvsc_drv.c
|
||||
@@ -481,6 +481,19 @@ cleanup:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+/* Disgusting wrapper functions */
|
||||
+static inline unsigned long sg_kmap_atomic(struct scatterlist *sgl, int idx)
|
||||
+{
|
||||
+ void *addr = kmap_atomic(sg_page(sgl + idx));
|
||||
+ return (unsigned long)addr;
|
||||
+}
|
||||
+
|
||||
+static inline void sg_kunmap_atomic(unsigned long addr)
|
||||
+{
|
||||
+ kunmap_atomic((void *)addr);
|
||||
+}
|
||||
+
|
||||
+
|
||||
/* Assume the original sgl has enough room */
|
||||
static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl,
|
||||
struct scatterlist *bounce_sgl,
|
||||
@@ -499,15 +512,12 @@ static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl,
|
||||
local_irq_save(flags);
|
||||
|
||||
for (i = 0; i < orig_sgl_count; i++) {
|
||||
- dest_addr = (unsigned long)kmap_atomic(sg_page((&orig_sgl[i])),
|
||||
- KM_IRQ0) + orig_sgl[i].offset;
|
||||
+ dest_addr = sg_kmap_atomic(orig_sgl,i) + orig_sgl[i].offset;
|
||||
dest = dest_addr;
|
||||
destlen = orig_sgl[i].length;
|
||||
|
||||
if (bounce_addr == 0)
|
||||
- bounce_addr =
|
||||
- (unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])),
|
||||
- KM_IRQ0);
|
||||
+ bounce_addr = sg_kmap_atomic(bounce_sgl,j);
|
||||
|
||||
while (destlen) {
|
||||
src = bounce_addr + bounce_sgl[j].offset;
|
||||
@@ -523,7 +533,7 @@ static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl,
|
||||
|
||||
if (bounce_sgl[j].offset == bounce_sgl[j].length) {
|
||||
/* full */
|
||||
- kunmap_atomic((void *)bounce_addr, KM_IRQ0);
|
||||
+ sg_kunmap_atomic(bounce_addr);
|
||||
j++;
|
||||
|
||||
/*
|
||||
@@ -537,26 +547,21 @@ static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl,
|
||||
/*
|
||||
* We are done; cleanup and return.
|
||||
*/
|
||||
- kunmap_atomic((void *)(dest_addr -
|
||||
- orig_sgl[i].offset),
|
||||
- KM_IRQ0);
|
||||
+ sg_kunmap_atomic(dest_addr - orig_sgl[i].offset);
|
||||
local_irq_restore(flags);
|
||||
return total_copied;
|
||||
}
|
||||
|
||||
/* if we need to use another bounce buffer */
|
||||
if (destlen || i != orig_sgl_count - 1)
|
||||
- bounce_addr =
|
||||
- (unsigned long)kmap_atomic(
|
||||
- sg_page((&bounce_sgl[j])), KM_IRQ0);
|
||||
+ bounce_addr = sg_kmap_atomic(bounce_sgl,j);
|
||||
} else if (destlen == 0 && i == orig_sgl_count - 1) {
|
||||
/* unmap the last bounce that is < PAGE_SIZE */
|
||||
- kunmap_atomic((void *)bounce_addr, KM_IRQ0);
|
||||
+ sg_kunmap_atomic(bounce_addr);
|
||||
}
|
||||
}
|
||||
|
||||
- kunmap_atomic((void *)(dest_addr - orig_sgl[i].offset),
|
||||
- KM_IRQ0);
|
||||
+ sg_kunmap_atomic(dest_addr - orig_sgl[i].offset);
|
||||
}
|
||||
|
||||
local_irq_restore(flags);
|
||||
@@ -581,15 +586,12 @@ static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl,
|
||||
local_irq_save(flags);
|
||||
|
||||
for (i = 0; i < orig_sgl_count; i++) {
|
||||
- src_addr = (unsigned long)kmap_atomic(sg_page((&orig_sgl[i])),
|
||||
- KM_IRQ0) + orig_sgl[i].offset;
|
||||
+ src_addr = sg_kmap_atomic(orig_sgl,i) + orig_sgl[i].offset;
|
||||
src = src_addr;
|
||||
srclen = orig_sgl[i].length;
|
||||
|
||||
if (bounce_addr == 0)
|
||||
- bounce_addr =
|
||||
- (unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])),
|
||||
- KM_IRQ0);
|
||||
+ bounce_addr = sg_kmap_atomic(bounce_sgl,j);
|
||||
|
||||
while (srclen) {
|
||||
/* assume bounce offset always == 0 */
|
||||
@@ -606,22 +608,20 @@ static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl,
|
||||
|
||||
if (bounce_sgl[j].length == PAGE_SIZE) {
|
||||
/* full..move to next entry */
|
||||
- kunmap_atomic((void *)bounce_addr, KM_IRQ0);
|
||||
+ sg_kunmap_atomic(bounce_addr);
|
||||
j++;
|
||||
|
||||
/* if we need to use another bounce buffer */
|
||||
if (srclen || i != orig_sgl_count - 1)
|
||||
- bounce_addr =
|
||||
- (unsigned long)kmap_atomic(
|
||||
- sg_page((&bounce_sgl[j])), KM_IRQ0);
|
||||
+ bounce_addr = sg_kmap_atomic(bounce_sgl,j);
|
||||
|
||||
} else if (srclen == 0 && i == orig_sgl_count - 1) {
|
||||
/* unmap the last bounce that is < PAGE_SIZE */
|
||||
- kunmap_atomic((void *)bounce_addr, KM_IRQ0);
|
||||
+ sg_kunmap_atomic(bounce_addr);
|
||||
}
|
||||
}
|
||||
|
||||
- kunmap_atomic((void *)(src_addr - orig_sgl[i].offset), KM_IRQ0);
|
||||
+ sg_kunmap_atomic(src_addr - orig_sgl[i].offset);
|
||||
}
|
||||
|
||||
local_irq_restore(flags);
|
||||
--
|
||||
1.7.9.5
|
||||
|
|
@ -89,11 +89,91 @@
|
|||
# Temporary, until the Xen regression is fixed
|
||||
+ debian/revert-x86-ioapic-Add-register-level-checks-to-detec.patch
|
||||
|
||||
# Temporary, until the next ABI bump
|
||||
+ debian/revert-rtc-Provide-flag-for-rtc-devices-that-don-t-s.patch
|
||||
|
||||
+ bugfix/all/net-fix-proc-net-dev-regression.patch
|
||||
+ bugfix/arm/ARM-orion5x-Fix-GPIO-enable-bits-for-MPP9.patch
|
||||
+ bugfix/x86/drm-i915-mask-transcoder-select-bits-before-setting-.patch
|
||||
+ bugfix/all/TOMOYO-Fix-mount-flags-checking-order.patch
|
||||
+ bugfix/all/drm-radeon-kms-fix-fans-after-resume.patch
|
||||
|
||||
# Update all Hyper-V drivers to 3.4-rc1 (no longer staging)
|
||||
+ features/x86/hyperv/0001-NLS-improve-UTF8-UTF16-string-conversion-routine.patch
|
||||
+ features/x86/hyperv/0002-HID-Move-the-hid-hyperv-driver-out-of-staging.patch
|
||||
+ features/x86/hyperv/0003-Staging-hv-storvsc-Use-mempools-to-allocate-struct-s.patch
|
||||
+ features/x86/hyperv/0004-Staging-hv-storvsc-Cleanup-error-handling-in-the-pro.patch
|
||||
+ features/x86/hyperv/0005-Staging-hv-storvsc-Fixup-the-error-when-processing-S.patch
|
||||
+ features/x86/hyperv/0006-Staging-hv-storvsc-Fix-error-handling-storvsc_host_r.patch
|
||||
+ features/x86/hyperv/0007-Staging-hv-storvsc-Use-the-accessor-function-shost_p.patch
|
||||
+ features/x86/hyperv/0008-Staging-hv-storvsc-Use-the-unlocked-version-queuecom.patch
|
||||
+ features/x86/hyperv/0009-Staging-hv-storvsc-use-the-macro-KBUILD_MODNAME.patch
|
||||
+ features/x86/hyperv/0010-Staging-hv-storvsc-Get-rid-of-an-unnecessary-forward.patch
|
||||
+ features/x86/hyperv/0011-Staging-hv-storvsc-Upgrade-the-vmstor-protocol-versi.patch
|
||||
+ features/x86/hyperv/0012-Staging-hv-storvsc-Support-hot-add-of-scsi-disks.patch
|
||||
+ features/x86/hyperv/0013-Staging-hv-storvsc-Support-hot-removing-of-scsi-devi.patch
|
||||
+ features/x86/hyperv/0014-staging-hv-Use-kmemdup-rather-than-duplicating-its-i.patch
|
||||
+ features/x86/hyperv/0015-Staging-hv-vmbus-Support-building-the-vmbus-driver-a.patch
|
||||
+ features/x86/hyperv/0016-hv-Add-Kconfig-menu-entry.patch
|
||||
+ features/x86/hyperv/0017-Staging-hv-mousevsc-Remove-the-mouse-driver-from-the.patch
|
||||
+ features/x86/hyperv/0018-staging-hv-move-hv_netvsc-out-of-staging-area.patch
|
||||
+ features/x86/hyperv/0019-net-hyperv-Fix-long-lines-in-netvsc.c.patch
|
||||
+ features/x86/hyperv/0020-net-hyperv-Add-support-for-promiscuous-mode-setting.patch
|
||||
+ features/x86/hyperv/0021-Staging-hv-storvsc-Disable-clustering.patch
|
||||
+ features/x86/hyperv/0022-Staging-hv-storvsc-Cleanup-storvsc_device_alloc.patch
|
||||
+ features/x86/hyperv/0023-Staging-hv-storvsc-Fix-a-bug-in-storvsc_command_comp.patch
|
||||
+ features/x86/hyperv/0024-Staging-hv-storvsc-Fix-a-bug-in-copy_from_bounce_buf.patch
|
||||
+ features/x86/hyperv/0025-Staging-hv-storvsc-Implement-per-device-memory-pools.patch
|
||||
+ features/x86/hyperv/0026-Staging-hv-update-TODO-file.patch
|
||||
+ features/x86/hyperv/0027-HID-hv_mouse-Properly-add-the-hid-device.patch
|
||||
+ features/x86/hyperv/0028-Staging-hv-storvsc-Fix-a-bug-in-create_bounce_buffer.patch
|
||||
+ features/x86/hyperv/0029-net-hyperv-Fix-the-stop-wake-queue-mechanism.patch
|
||||
+ features/x86/hyperv/0030-Drivers-hv-Fix-a-memory-leak.patch
|
||||
+ features/x86/hyperv/0031-Drivers-hv-Make-the-vmbus-driver-unloadable.patch
|
||||
+ features/x86/hyperv/0032-Drivers-hv-Get-rid-of-an-unnecessary-check-in-hv.c.patch
|
||||
+ features/x86/hyperv/0033-net-hyperv-Remove-unnecessary-kmap_atomic-in-netvsc-.patch
|
||||
+ features/x86/hyperv/0034-net-hyperv-Add-NETVSP-protocol-version-negotiation.patch
|
||||
+ features/x86/hyperv/0035-net-hyperv-Add-support-for-jumbo-frame-up-to-64KB.patch
|
||||
+ features/x86/hyperv/0036-net-hyperv-fix-possible-memory-leak-in-do_set_multic.patch
|
||||
+ features/x86/hyperv/0037-drivers-hv-Get-rid-of-some-unnecessary-code.patch
|
||||
+ features/x86/hyperv/0038-net-hyperv-rx_bytes-should-account-the-ether-header-.patch
|
||||
+ features/x86/hyperv/0039-HID-hyperv-Properly-disconnect-the-input-device.patch
|
||||
+ features/x86/hyperv/0040-net-hyperv-fix-the-issue-that-large-packets-be-dropp.patch
|
||||
+ features/x86/hyperv/0041-net-hyperv-Use-netif_tx_disable-instead-of-netif_sto.patch
|
||||
+ features/x86/hyperv/0042-net-hyperv-Fix-the-page-buffer-when-an-RNDIS-message.patch
|
||||
+ features/x86/hyperv/0043-drivers-hv-kvp-Add-cleanup-connector-defines.patch
|
||||
+ features/x86/hyperv/0044-drivers-hv-kvp-Move-the-contents-of-hv_kvp.h-to-hype.patch
|
||||
+ features/x86/hyperv/0045-net-hyperv-Convert-camel-cased-variables-in-rndis_fi.patch
|
||||
+ features/x86/hyperv/0046-net-hyperv-Correct-the-assignment-in-netvsc_recv_cal.patch
|
||||
+ features/x86/hyperv/0047-net-hyperv-Remove-the-unnecessary-memset-in-rndis_fi.patch
|
||||
+ features/x86/hyperv/0048-Staging-hv-storvsc-Cleanup-some-comments.patch
|
||||
+ features/x86/hyperv/0049-Staging-hv-storvsc-Cleanup-storvsc_probe.patch
|
||||
+ features/x86/hyperv/0050-Staging-hv-storvsc-Cleanup-storvsc_queuecommand.patch
|
||||
+ features/x86/hyperv/0051-Staging-hv-storvsc-Introduce-defines-for-srb-status-.patch
|
||||
+ features/x86/hyperv/0052-Staging-hv-storvsc-Cleanup-storvsc_host_reset_handle.patch
|
||||
+ features/x86/hyperv/0053-Staging-hv-storvsc-Move-and-cleanup-storvsc_remove.patch
|
||||
+ features/x86/hyperv/0054-Staging-hv-storvsc-Add-a-comment-to-explain-life-cyc.patch
|
||||
+ features/x86/hyperv/0055-Staging-hv-storvsc-Get-rid-of-the-on_io_completion-i.patch
|
||||
+ features/x86/hyperv/0056-Staging-hv-storvsc-Rename-the-context-field-in-hv_st.patch
|
||||
+ features/x86/hyperv/0057-Staging-hv-storvsc-Miscellaneous-cleanup-of-storvsc-.patch
|
||||
+ features/x86/hyperv/0058-Staging-hv-storvsc-Cleanup-the-code-for-generating-p.patch
|
||||
+ features/x86/hyperv/0059-Staging-hv-storvsc-Cleanup-some-protocol-related-con.patch
|
||||
+ features/x86/hyperv/0060-Staging-hv-storvsc-Get-rid-of-some-unused-defines.patch
|
||||
+ features/x86/hyperv/0061-Staging-hv-storvsc-Consolidate-the-request-structure.patch
|
||||
+ features/x86/hyperv/0062-Staging-hv-storvsc-Consolidate-all-the-wire-protocol.patch
|
||||
+ features/x86/hyperv/0063-drivers-hv-Cleanup-the-kvp-related-state-in-hyperv.h.patch
|
||||
+ features/x86/hyperv/0064-tools-hv-Use-hyperv.h-to-get-the-KVP-definitions.patch
|
||||
+ features/x86/hyperv/0065-drivers-hv-kvp-Cleanup-the-kernel-user-protocol.patch
|
||||
+ features/x86/hyperv/0066-drivers-hv-Increase-the-number-of-VCPUs-supported-in.patch
|
||||
+ features/x86/hyperv/0067-Staging-hv-storvsc-Move-the-storage-driver-out-of-th.patch
|
||||
+ features/x86/hyperv/0068-net-hyperv-Use-the-built-in-macro-KBUILD_MODNAME-for.patch
|
||||
+ features/x86/hyperv/0069-net-hyperv-Fix-data-corruption-in-rndis_filter_recei.patch
|
||||
+ features/x86/hyperv/0070-net-hyperv-Add-support-for-vlan-trunking-from-guests.patch
|
||||
+ features/x86/hyperv/0071-Drivers-hv-Add-new-message-types-to-enhance-KVP.patch
|
||||
+ features/x86/hyperv/0072-net-hyperv-fix-erroneous-NETDEV_TX_BUSY-use.patch
|
||||
+ features/x86/hyperv/0073-Drivers-hv-Support-the-newly-introduced-KVP-messages.patch
|
||||
+ features/x86/hyperv/0074-Tools-hv-Fully-support-the-new-KVP-verbs-in-the-user.patch
|
||||
+ features/x86/hyperv/0075-Tools-hv-Support-enumeration-from-all-the-pools.patch
|
||||
+ features/x86/hyperv/0076-net-hyperv-Fix-the-code-handling-tx-busy.patch
|
||||
+ features/x86/hyperv/0077-hv-remove-the-second-argument-of-k-un-map_atomic.patch
|
||||
|
||||
# Temporary, until the next ABI bump
|
||||
+ debian/revert-rtc-Provide-flag-for-rtc-devices-that-don-t-s.patch
|
||||
+ debian/nls-Avoid-ABI-change-from-improvement-to-utf8s_to_ut.patch
|
||||
|
|
Loading…
Reference in New Issue