summaryrefslogtreecommitdiff
path: root/drivers/staging/hv
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/hv')
-rw-r--r--drivers/staging/hv/Hv.c52
-rw-r--r--drivers/staging/hv/Hv.h6
-rw-r--r--drivers/staging/hv/RingBuffer.c2
-rw-r--r--drivers/staging/hv/RndisFilter.c1
-rw-r--r--drivers/staging/hv/StorVscApi.h4
-rw-r--r--drivers/staging/hv/Vmbus.c12
-rw-r--r--drivers/staging/hv/netvsc_drv.c6
-rw-r--r--drivers/staging/hv/storvsc_drv.c9
-rw-r--r--drivers/staging/hv/vmbus_drv.c30
9 files changed, 80 insertions, 42 deletions
diff --git a/drivers/staging/hv/Hv.c b/drivers/staging/hv/Hv.c
index c5b6613f2f2f..b12237f90db2 100644
--- a/drivers/staging/hv/Hv.c
+++ b/drivers/staging/hv/Hv.c
@@ -306,9 +306,9 @@ void HvCleanup(void)
DPRINT_ENTER(VMBUS);
if (gHvContext.SignalEventBuffer) {
+ kfree(gHvContext.SignalEventBuffer);
gHvContext.SignalEventBuffer = NULL;
gHvContext.SignalEventParam = NULL;
- kfree(gHvContext.SignalEventBuffer);
}
if (gHvContext.GuestId == HV_LINUX_GUEST_ID) {
@@ -386,7 +386,7 @@ u16 HvSignalEvent(void)
* retrieve the initialized message and event pages. Otherwise, we create and
* initialize the message and event pages.
*/
-int HvSynicInit(u32 irqVector)
+void HvSynicInit(void *irqarg)
{
u64 version;
union hv_synic_simp simp;
@@ -394,13 +394,14 @@ int HvSynicInit(u32 irqVector)
union hv_synic_sint sharedSint;
union hv_synic_scontrol sctrl;
u64 guestID;
- int ret = 0;
+ u32 irqVector = *((u32 *)(irqarg));
+ int cpu = smp_processor_id();
DPRINT_ENTER(VMBUS);
if (!gHvContext.HypercallPage) {
DPRINT_EXIT(VMBUS);
- return ret;
+ return;
}
/* Check the version */
@@ -425,27 +426,27 @@ int HvSynicInit(u32 irqVector)
*/
rdmsrl(HV_X64_MSR_GUEST_OS_ID, guestID);
if (guestID == HV_LINUX_GUEST_ID) {
- gHvContext.synICMessagePage[0] =
+ gHvContext.synICMessagePage[cpu] =
phys_to_virt(simp.BaseSimpGpa << PAGE_SHIFT);
- gHvContext.synICEventPage[0] =
+ gHvContext.synICEventPage[cpu] =
phys_to_virt(siefp.BaseSiefpGpa << PAGE_SHIFT);
} else {
DPRINT_ERR(VMBUS, "unknown guest id!!");
goto Cleanup;
}
DPRINT_DBG(VMBUS, "MAPPED: Simp: %p, Sifep: %p",
- gHvContext.synICMessagePage[0],
- gHvContext.synICEventPage[0]);
+ gHvContext.synICMessagePage[cpu],
+ gHvContext.synICEventPage[cpu]);
} else {
- gHvContext.synICMessagePage[0] = osd_PageAlloc(1);
- if (gHvContext.synICMessagePage[0] == NULL) {
+ gHvContext.synICMessagePage[cpu] = (void *)get_zeroed_page(GFP_ATOMIC);
+ if (gHvContext.synICMessagePage[cpu] == NULL) {
DPRINT_ERR(VMBUS,
"unable to allocate SYNIC message page!!");
goto Cleanup;
}
- gHvContext.synICEventPage[0] = osd_PageAlloc(1);
- if (gHvContext.synICEventPage[0] == NULL) {
+ gHvContext.synICEventPage[cpu] = (void *)get_zeroed_page(GFP_ATOMIC);
+ if (gHvContext.synICEventPage[cpu] == NULL) {
DPRINT_ERR(VMBUS,
"unable to allocate SYNIC event page!!");
goto Cleanup;
@@ -454,7 +455,7 @@ int HvSynicInit(u32 irqVector)
/* Setup the Synic's message page */
rdmsrl(HV_X64_MSR_SIMP, simp.AsUINT64);
simp.SimpEnabled = 1;
- simp.BaseSimpGpa = virt_to_phys(gHvContext.synICMessagePage[0])
+ simp.BaseSimpGpa = virt_to_phys(gHvContext.synICMessagePage[cpu])
>> PAGE_SHIFT;
DPRINT_DBG(VMBUS, "HV_X64_MSR_SIMP msr set to: %llx",
@@ -465,7 +466,7 @@ int HvSynicInit(u32 irqVector)
/* Setup the Synic's event page */
rdmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);
siefp.SiefpEnabled = 1;
- siefp.BaseSiefpGpa = virt_to_phys(gHvContext.synICEventPage[0])
+ siefp.BaseSiefpGpa = virt_to_phys(gHvContext.synICEventPage[cpu])
>> PAGE_SHIFT;
DPRINT_DBG(VMBUS, "HV_X64_MSR_SIEFP msr set to: %llx",
@@ -501,32 +502,30 @@ int HvSynicInit(u32 irqVector)
DPRINT_EXIT(VMBUS);
- return ret;
+ return;
Cleanup:
- ret = -1;
-
if (gHvContext.GuestId == HV_LINUX_GUEST_ID) {
- if (gHvContext.synICEventPage[0])
- osd_PageFree(gHvContext.synICEventPage[0], 1);
+ if (gHvContext.synICEventPage[cpu])
+ osd_PageFree(gHvContext.synICEventPage[cpu], 1);
- if (gHvContext.synICMessagePage[0])
- osd_PageFree(gHvContext.synICMessagePage[0], 1);
+ if (gHvContext.synICMessagePage[cpu])
+ osd_PageFree(gHvContext.synICMessagePage[cpu], 1);
}
DPRINT_EXIT(VMBUS);
-
- return ret;
+ return;
}
/**
* HvSynicCleanup - Cleanup routine for HvSynicInit().
*/
-void HvSynicCleanup(void)
+void HvSynicCleanup(void *arg)
{
union hv_synic_sint sharedSint;
union hv_synic_simp simp;
union hv_synic_siefp siefp;
+ int cpu = smp_processor_id();
DPRINT_ENTER(VMBUS);
@@ -539,6 +538,7 @@ void HvSynicCleanup(void)
sharedSint.Masked = 1;
+ /* Need to correctly cleanup in the case of SMP!!! */
/* Disable the interrupt */
wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, sharedSint.AsUINT64);
@@ -560,8 +560,8 @@ void HvSynicCleanup(void)
wrmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);
- osd_PageFree(gHvContext.synICMessagePage[0], 1);
- osd_PageFree(gHvContext.synICEventPage[0], 1);
+ osd_PageFree(gHvContext.synICMessagePage[cpu], 1);
+ osd_PageFree(gHvContext.synICEventPage[cpu], 1);
}
DPRINT_EXIT(VMBUS);
diff --git a/drivers/staging/hv/Hv.h b/drivers/staging/hv/Hv.h
index 5379e4bfc56e..fce4b5cdac30 100644
--- a/drivers/staging/hv/Hv.h
+++ b/drivers/staging/hv/Hv.h
@@ -93,7 +93,7 @@ static const struct hv_guid VMBUS_SERVICE_ID = {
},
};
-#define MAX_NUM_CPUS 1
+#define MAX_NUM_CPUS 32
struct hv_input_signal_event_buffer {
@@ -137,8 +137,8 @@ extern u16 HvPostMessage(union hv_connection_id connectionId,
extern u16 HvSignalEvent(void);
-extern int HvSynicInit(u32 irqVector);
+extern void HvSynicInit(void *irqarg);
-extern void HvSynicCleanup(void);
+extern void HvSynicCleanup(void *arg);
#endif /* __HV_H__ */
diff --git a/drivers/staging/hv/RingBuffer.c b/drivers/staging/hv/RingBuffer.c
index f69ae33a91e3..3a38103ecfbd 100644
--- a/drivers/staging/hv/RingBuffer.c
+++ b/drivers/staging/hv/RingBuffer.c
@@ -192,7 +192,7 @@ Description:
static inline u64
GetRingBufferIndices(RING_BUFFER_INFO* RingInfo)
{
- return ((u64)RingInfo->RingBuffer->WriteIndex << 32) || RingInfo->RingBuffer->ReadIndex;
+ return (u64)RingInfo->RingBuffer->WriteIndex << 32;
}
diff --git a/drivers/staging/hv/RndisFilter.c b/drivers/staging/hv/RndisFilter.c
index 26d79975387c..f05f4e125c48 100644
--- a/drivers/staging/hv/RndisFilter.c
+++ b/drivers/staging/hv/RndisFilter.c
@@ -756,6 +756,7 @@ static int RndisFilterOpenDevice(struct rndis_device *Device)
ret = RndisFilterSetPacketFilter(Device,
NDIS_PACKET_TYPE_BROADCAST |
+ NDIS_PACKET_TYPE_ALL_MULTICAST |
NDIS_PACKET_TYPE_DIRECTED);
if (ret == 0)
Device->State = RNDIS_DEV_DATAINITIALIZED;
diff --git a/drivers/staging/hv/StorVscApi.h b/drivers/staging/hv/StorVscApi.h
index 69c14066c479..3d8ff086fc7f 100644
--- a/drivers/staging/hv/StorVscApi.h
+++ b/drivers/staging/hv/StorVscApi.h
@@ -28,10 +28,10 @@
#include "VmbusApi.h"
/* Defines */
-#define STORVSC_RING_BUFFER_SIZE (10*PAGE_SIZE)
+#define STORVSC_RING_BUFFER_SIZE (20*PAGE_SIZE)
#define BLKVSC_RING_BUFFER_SIZE (20*PAGE_SIZE)
-#define STORVSC_MAX_IO_REQUESTS 64
+#define STORVSC_MAX_IO_REQUESTS 128
/*
* In Hyper-V, each port/path/target maps to 1 scsi host adapter. In
diff --git a/drivers/staging/hv/Vmbus.c b/drivers/staging/hv/Vmbus.c
index a4dd06f6d459..35a023e9f9d1 100644
--- a/drivers/staging/hv/Vmbus.c
+++ b/drivers/staging/hv/Vmbus.c
@@ -129,7 +129,7 @@ static int VmbusOnDeviceAdd(struct hv_device *dev, void *AdditionalInfo)
/* strcpy(dev->name, "vmbus"); */
/* SynIC setup... */
- ret = HvSynicInit(*irqvector);
+ on_each_cpu(HvSynicInit, (void *)irqvector, 1);
/* Connect to VMBus in the root partition */
ret = VmbusConnect();
@@ -150,7 +150,7 @@ static int VmbusOnDeviceRemove(struct hv_device *dev)
DPRINT_ENTER(VMBUS);
VmbusChannelReleaseUnattachedChannels();
VmbusDisconnect();
- HvSynicCleanup();
+ on_each_cpu(HvSynicCleanup, NULL, 1);
DPRINT_EXIT(VMBUS);
return ret;
@@ -173,7 +173,8 @@ static void VmbusOnCleanup(struct hv_driver *drv)
*/
static void VmbusOnMsgDPC(struct hv_driver *drv)
{
- void *page_addr = gHvContext.synICMessagePage[0];
+ int cpu = smp_processor_id();
+ void *page_addr = gHvContext.synICMessagePage[cpu];
struct hv_message *msg = (struct hv_message *)page_addr +
VMBUS_MESSAGE_SINT;
struct hv_message *copied;
@@ -230,11 +231,12 @@ static void VmbusOnEventDPC(struct hv_driver *drv)
static int VmbusOnISR(struct hv_driver *drv)
{
int ret = 0;
+ int cpu = smp_processor_id();
void *page_addr;
struct hv_message *msg;
union hv_synic_event_flags *event;
- page_addr = gHvContext.synICMessagePage[0];
+ page_addr = gHvContext.synICMessagePage[cpu];
msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT;
DPRINT_ENTER(VMBUS);
@@ -248,7 +250,7 @@ static int VmbusOnISR(struct hv_driver *drv)
}
/* TODO: Check if there are events to be process */
- page_addr = gHvContext.synICEventPage[0];
+ page_addr = gHvContext.synICEventPage[cpu];
event = (union hv_synic_event_flags *)page_addr + VMBUS_MESSAGE_SINT;
/* Since we are a child, we only need to check bit 0 */
diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c
index 0d7459e2d036..547261d2537c 100644
--- a/drivers/staging/hv/netvsc_drv.c
+++ b/drivers/staging/hv/netvsc_drv.c
@@ -392,6 +392,9 @@ static const struct net_device_ops device_ops = {
.ndo_start_xmit = netvsc_start_xmit,
.ndo_get_stats = netvsc_get_stats,
.ndo_set_multicast_list = netvsc_set_multicast_list,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
};
static int netvsc_probe(struct device *device)
@@ -413,8 +416,7 @@ static int netvsc_probe(struct device *device)
if (!net_drv_obj->Base.OnDeviceAdd)
return -1;
- net = alloc_netdev(sizeof(struct net_device_context), "seth%d",
- ether_setup);
+ net = alloc_etherdev(sizeof(struct net_device_context));
if (!net)
return -1;
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index d49dc21d4cb4..2a4b147b0b38 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -532,7 +532,7 @@ static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl,
ASSERT(orig_sgl[i].offset + orig_sgl[i].length <= PAGE_SIZE);
- if (j == 0)
+ if (bounce_addr == 0)
bounce_addr = (unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])), KM_IRQ0);
while (srclen) {
@@ -593,7 +593,7 @@ static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl,
destlen = orig_sgl[i].length;
ASSERT(orig_sgl[i].offset + orig_sgl[i].length <= PAGE_SIZE);
- if (j == 0)
+ if (bounce_addr == 0)
bounce_addr = (unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])), KM_IRQ0);
while (destlen) {
@@ -652,6 +652,7 @@ static int storvsc_queuecommand(struct scsi_cmnd *scmnd,
unsigned int request_size = 0;
int i;
struct scatterlist *sgl;
+ unsigned int sg_count = 0;
DPRINT_ENTER(STORVSC_DRV);
@@ -736,6 +737,7 @@ static int storvsc_queuecommand(struct scsi_cmnd *scmnd,
request->DataBuffer.Length = scsi_bufflen(scmnd);
if (scsi_sg_count(scmnd)) {
sgl = (struct scatterlist *)scsi_sglist(scmnd);
+ sg_count = scsi_sg_count(scmnd);
/* check if we need to bounce the sgl */
if (do_bounce_buffer(sgl, scsi_sg_count(scmnd)) != -1) {
@@ -770,11 +772,12 @@ static int storvsc_queuecommand(struct scsi_cmnd *scmnd,
scsi_sg_count(scmnd));
sgl = cmd_request->bounce_sgl;
+ sg_count = cmd_request->bounce_sgl_count;
}
request->DataBuffer.Offset = sgl[0].offset;
- for (i = 0; i < scsi_sg_count(scmnd); i++) {
+ for (i = 0; i < sg_count; i++) {
DPRINT_DBG(STORVSC_DRV, "sgl[%d] len %d offset %d \n",
i, sgl[i].length, sgl[i].offset);
request->DataBuffer.PfnArray[i] =
diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c
index 894eecfc63ca..6acc49a55a57 100644
--- a/drivers/staging/hv/vmbus_drv.c
+++ b/drivers/staging/hv/vmbus_drv.c
@@ -24,6 +24,8 @@
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/sysctl.h>
+#include <linux/pci.h>
+#include <linux/dmi.h>
#include "osd.h"
#include "logging.h"
#include "vmbus.h"
@@ -946,6 +948,19 @@ static irqreturn_t vmbus_isr(int irq, void *dev_id)
}
}
+static struct dmi_system_id __initdata microsoft_hv_dmi_table[] = {
+ {
+ .ident = "Hyper-V",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"),
+ DMI_MATCH(DMI_BOARD_NAME, "Virtual Machine"),
+ },
+ },
+ { },
+};
+MODULE_DEVICE_TABLE(dmi, microsoft_hv_dmi_table);
+
static int __init vmbus_init(void)
{
int ret = 0;
@@ -957,6 +972,9 @@ static int __init vmbus_init(void)
vmbus_loglevel, HIWORD(vmbus_loglevel), LOWORD(vmbus_loglevel));
/* Todo: it is used for loglevel, to be ported to new kernel. */
+ if (!dmi_check_system(microsoft_hv_dmi_table))
+ return -ENODEV;
+
ret = vmbus_bus_init(VmbusInitialize);
DPRINT_EXIT(VMBUS_DRV);
@@ -973,6 +991,18 @@ static void __exit vmbus_exit(void)
return;
}
+/*
+ * We use a PCI table to determine if we should autoload this driver This is
+ * needed by distro tools to determine if the hyperv drivers should be
+ * installed and/or configured. We don't do anything else with the table, but
+ * it needs to be present.
+ */
+const static struct pci_device_id microsoft_hv_pci_table[] = {
+ { PCI_DEVICE(0x1414, 0x5353) }, /* VGA compatible controller */
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, microsoft_hv_pci_table);
+
MODULE_LICENSE("GPL");
module_param(vmbus_irq, int, S_IRUGO);
module_param(vmbus_loglevel, int, S_IRUGO);