Merge tag 'char-misc-3.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregk...
[sfrench/cifs-2.6.git] / drivers / hv / vmbus_drv.c
index 3f0a95290e140daa99880cfffe8d0545dcaa7e0b..8e53a3c2607e00c07e066b28f11c056aef4a6abd 100644 (file)
@@ -43,6 +43,12 @@ static struct tasklet_struct msg_dpc;
 static struct completion probe_event;
 static int irq;
 
+struct resource hyperv_mmio = {
+       .name  = "hyperv mmio",
+       .flags = IORESOURCE_MEM,
+};
+EXPORT_SYMBOL_GPL(hyperv_mmio);
+
 static int vmbus_exists(void)
 {
        if (hv_acpi_dev == NULL)
@@ -843,18 +849,21 @@ void vmbus_device_unregister(struct hv_device *device_obj)
 
 
 /*
- * VMBUS is an acpi enumerated device. Get the the IRQ information
- * from DSDT.
+ * VMBUS is an acpi enumerated device. Get the the information we
+ * need from DSDT.
  */
 
-static acpi_status vmbus_walk_resources(struct acpi_resource *res, void *irq)
+static acpi_status vmbus_walk_resources(struct acpi_resource *res, void *ctx)
 {
+       switch (res->type) {
+       case ACPI_RESOURCE_TYPE_IRQ:
+               irq = res->data.irq.interrupts[0];
+               break;
 
-       if (res->type == ACPI_RESOURCE_TYPE_IRQ) {
-               struct acpi_resource_irq *irqp;
-               irqp = &res->data.irq;
-
-               *((unsigned int *)irq) = irqp->interrupts[0];
+       case ACPI_RESOURCE_TYPE_ADDRESS64:
+               hyperv_mmio.start = res->data.address64.minimum;
+               hyperv_mmio.end = res->data.address64.maximum;
+               break;
        }
 
        return AE_OK;
@@ -863,18 +872,34 @@ static acpi_status vmbus_walk_resources(struct acpi_resource *res, void *irq)
 static int vmbus_acpi_add(struct acpi_device *device)
 {
        acpi_status result;
+       int ret_val = -ENODEV;
 
        hv_acpi_dev = device;
 
        result = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
-                                       vmbus_walk_resources, &irq);
+                                       vmbus_walk_resources, NULL);
 
-       if (ACPI_FAILURE(result)) {
-               complete(&probe_event);
-               return -ENODEV;
+       if (ACPI_FAILURE(result))
+               goto acpi_walk_err;
+       /*
+        * The parent of the vmbus acpi device (Gen2 firmware) is the VMOD that
+        * has the mmio ranges. Get that.
+        */
+       if (device->parent) {
+               result = acpi_walk_resources(device->parent->handle,
+                                       METHOD_NAME__CRS,
+                                       vmbus_walk_resources, NULL);
+
+               if (ACPI_FAILURE(result))
+                       goto acpi_walk_err;
+               if (hyperv_mmio.start && hyperv_mmio.end)
+                       request_resource(&iomem_resource, &hyperv_mmio);
        }
+       ret_val = 0;
+
+acpi_walk_err:
        complete(&probe_event);
-       return 0;
+       return ret_val;
 }
 
 static const struct acpi_device_id vmbus_acpi_device_ids[] = {