diff options
-rw-r--r-- | drivers/hv/vmbus_drv.c | 116 | ||||
-rw-r--r-- | drivers/video/fbdev/hyperv_fb.c | 2 | ||||
-rw-r--r-- | include/linux/hyperv.h | 2 |
3 files changed, 92 insertions, 28 deletions
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index e7b0bcd453e7..ee59e06c2194 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c | |||
@@ -102,10 +102,7 @@ static struct notifier_block hyperv_panic_block = { | |||
102 | .notifier_call = hyperv_panic_event, | 102 | .notifier_call = hyperv_panic_event, |
103 | }; | 103 | }; |
104 | 104 | ||
105 | struct resource hyperv_mmio = { | 105 | struct resource *hyperv_mmio; |
106 | .name = "hyperv mmio", | ||
107 | .flags = IORESOURCE_MEM, | ||
108 | }; | ||
109 | EXPORT_SYMBOL_GPL(hyperv_mmio); | 106 | EXPORT_SYMBOL_GPL(hyperv_mmio); |
110 | 107 | ||
111 | static int vmbus_exists(void) | 108 | static int vmbus_exists(void) |
@@ -1013,30 +1010,105 @@ void vmbus_device_unregister(struct hv_device *device_obj) | |||
1013 | 1010 | ||
1014 | 1011 | ||
1015 | /* | 1012 | /* |
1016 | * VMBUS is an acpi enumerated device. Get the the information we | 1013 | * VMBUS is an acpi enumerated device. Get the information we |
1017 | * need from DSDT. | 1014 | * need from DSDT. |
1018 | */ | 1015 | */ |
1019 | 1016 | #define VTPM_BASE_ADDRESS 0xfed40000 | |
1020 | static acpi_status vmbus_walk_resources(struct acpi_resource *res, void *ctx) | 1017 | static acpi_status vmbus_walk_resources(struct acpi_resource *res, void *ctx) |
1021 | { | 1018 | { |
1019 | resource_size_t start = 0; | ||
1020 | resource_size_t end = 0; | ||
1021 | struct resource *new_res; | ||
1022 | struct resource **old_res = &hyperv_mmio; | ||
1023 | struct resource **prev_res = NULL; | ||
1024 | |||
1022 | switch (res->type) { | 1025 | switch (res->type) { |
1023 | case ACPI_RESOURCE_TYPE_IRQ: | 1026 | case ACPI_RESOURCE_TYPE_IRQ: |
1024 | irq = res->data.irq.interrupts[0]; | 1027 | irq = res->data.irq.interrupts[0]; |
1028 | return AE_OK; | ||
1029 | |||
1030 | /* | ||
1031 | * "Address" descriptors are for bus windows. Ignore | ||
1032 | * "memory" descriptors, which are for registers on | ||
1033 | * devices. | ||
1034 | */ | ||
1035 | case ACPI_RESOURCE_TYPE_ADDRESS32: | ||
1036 | start = res->data.address32.address.minimum; | ||
1037 | end = res->data.address32.address.maximum; | ||
1025 | break; | 1038 | break; |
1026 | 1039 | ||
1027 | case ACPI_RESOURCE_TYPE_ADDRESS64: | 1040 | case ACPI_RESOURCE_TYPE_ADDRESS64: |
1028 | hyperv_mmio.start = res->data.address64.address.minimum; | 1041 | start = res->data.address64.address.minimum; |
1029 | hyperv_mmio.end = res->data.address64.address.maximum; | 1042 | end = res->data.address64.address.maximum; |
1030 | break; | 1043 | break; |
1044 | |||
1045 | default: | ||
1046 | /* Unused resource type */ | ||
1047 | return AE_OK; | ||
1048 | |||
1031 | } | 1049 | } |
1050 | /* | ||
1051 | * Ignore ranges that are below 1MB, as they're not | ||
1052 | * necessary or useful here. | ||
1053 | */ | ||
1054 | if (end < 0x100000) | ||
1055 | return AE_OK; | ||
1056 | |||
1057 | new_res = kzalloc(sizeof(*new_res), GFP_ATOMIC); | ||
1058 | if (!new_res) | ||
1059 | return AE_NO_MEMORY; | ||
1060 | |||
1061 | /* If this range overlaps the virtual TPM, truncate it. */ | ||
1062 | if (end > VTPM_BASE_ADDRESS && start < VTPM_BASE_ADDRESS) | ||
1063 | end = VTPM_BASE_ADDRESS; | ||
1064 | |||
1065 | new_res->name = "hyperv mmio"; | ||
1066 | new_res->flags = IORESOURCE_MEM; | ||
1067 | new_res->start = start; | ||
1068 | new_res->end = end; | ||
1069 | |||
1070 | do { | ||
1071 | if (!*old_res) { | ||
1072 | *old_res = new_res; | ||
1073 | break; | ||
1074 | } | ||
1075 | |||
1076 | if ((*old_res)->end < new_res->start) { | ||
1077 | new_res->sibling = *old_res; | ||
1078 | if (prev_res) | ||
1079 | (*prev_res)->sibling = new_res; | ||
1080 | *old_res = new_res; | ||
1081 | break; | ||
1082 | } | ||
1083 | |||
1084 | prev_res = old_res; | ||
1085 | old_res = &(*old_res)->sibling; | ||
1086 | |||
1087 | } while (1); | ||
1032 | 1088 | ||
1033 | return AE_OK; | 1089 | return AE_OK; |
1034 | } | 1090 | } |
1035 | 1091 | ||
1092 | static int vmbus_acpi_remove(struct acpi_device *device) | ||
1093 | { | ||
1094 | struct resource *cur_res; | ||
1095 | struct resource *next_res; | ||
1096 | |||
1097 | if (hyperv_mmio) { | ||
1098 | for (cur_res = hyperv_mmio; cur_res; cur_res = next_res) { | ||
1099 | next_res = cur_res->sibling; | ||
1100 | kfree(cur_res); | ||
1101 | } | ||
1102 | } | ||
1103 | |||
1104 | return 0; | ||
1105 | } | ||
1106 | |||
1036 | static int vmbus_acpi_add(struct acpi_device *device) | 1107 | static int vmbus_acpi_add(struct acpi_device *device) |
1037 | { | 1108 | { |
1038 | acpi_status result; | 1109 | acpi_status result; |
1039 | int ret_val = -ENODEV; | 1110 | int ret_val = -ENODEV; |
1111 | struct acpi_device *ancestor; | ||
1040 | 1112 | ||
1041 | hv_acpi_dev = device; | 1113 | hv_acpi_dev = device; |
1042 | 1114 | ||
@@ -1046,35 +1118,27 @@ static int vmbus_acpi_add(struct acpi_device *device) | |||
1046 | if (ACPI_FAILURE(result)) | 1118 | if (ACPI_FAILURE(result)) |
1047 | goto acpi_walk_err; | 1119 | goto acpi_walk_err; |
1048 | /* | 1120 | /* |
1049 | * The parent of the vmbus acpi device (Gen2 firmware) is the VMOD that | 1121 | * Some ancestor of the vmbus acpi device (Gen1 or Gen2 |
1050 | * has the mmio ranges. Get that. | 1122 | * firmware) is the VMOD that has the mmio ranges. Get that. |
1051 | */ | 1123 | */ |
1052 | if (device->parent) { | 1124 | for (ancestor = device->parent; ancestor; ancestor = ancestor->parent) { |
1053 | result = acpi_walk_resources(device->parent->handle, | 1125 | result = acpi_walk_resources(ancestor->handle, METHOD_NAME__CRS, |
1054 | METHOD_NAME__CRS, | 1126 | vmbus_walk_resources, NULL); |
1055 | vmbus_walk_resources, NULL); | ||
1056 | 1127 | ||
1057 | if (ACPI_FAILURE(result)) | 1128 | if (ACPI_FAILURE(result)) |
1058 | goto acpi_walk_err; | 1129 | continue; |
1059 | if (hyperv_mmio.start && hyperv_mmio.end) | 1130 | if (hyperv_mmio) |
1060 | request_resource(&iomem_resource, &hyperv_mmio); | 1131 | break; |
1061 | } | 1132 | } |
1062 | ret_val = 0; | 1133 | ret_val = 0; |
1063 | 1134 | ||
1064 | acpi_walk_err: | 1135 | acpi_walk_err: |
1065 | complete(&probe_event); | 1136 | complete(&probe_event); |
1137 | if (ret_val) | ||
1138 | vmbus_acpi_remove(device); | ||
1066 | return ret_val; | 1139 | return ret_val; |
1067 | } | 1140 | } |
1068 | 1141 | ||
1069 | static int vmbus_acpi_remove(struct acpi_device *device) | ||
1070 | { | ||
1071 | int ret = 0; | ||
1072 | |||
1073 | if (hyperv_mmio.start && hyperv_mmio.end) | ||
1074 | ret = release_resource(&hyperv_mmio); | ||
1075 | return ret; | ||
1076 | } | ||
1077 | |||
1078 | static const struct acpi_device_id vmbus_acpi_device_ids[] = { | 1142 | static const struct acpi_device_id vmbus_acpi_device_ids[] = { |
1079 | {"VMBUS", 0}, | 1143 | {"VMBUS", 0}, |
1080 | {"VMBus", 0}, | 1144 | {"VMBus", 0}, |
diff --git a/drivers/video/fbdev/hyperv_fb.c b/drivers/video/fbdev/hyperv_fb.c index 807ee22ef229..b54ee1c05a5f 100644 --- a/drivers/video/fbdev/hyperv_fb.c +++ b/drivers/video/fbdev/hyperv_fb.c | |||
@@ -688,7 +688,7 @@ static int hvfb_getmem(struct fb_info *info) | |||
688 | par->mem.name = KBUILD_MODNAME; | 688 | par->mem.name = KBUILD_MODNAME; |
689 | par->mem.flags = IORESOURCE_MEM | IORESOURCE_BUSY; | 689 | par->mem.flags = IORESOURCE_MEM | IORESOURCE_BUSY; |
690 | if (gen2vm) { | 690 | if (gen2vm) { |
691 | ret = allocate_resource(&hyperv_mmio, &par->mem, | 691 | ret = allocate_resource(hyperv_mmio, &par->mem, |
692 | screen_fb_size, | 692 | screen_fb_size, |
693 | 0, -1, | 693 | 0, -1, |
694 | screen_fb_size, | 694 | screen_fb_size, |
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 30d3a1f79450..217e14be77b9 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h | |||
@@ -1233,7 +1233,7 @@ extern bool vmbus_prep_negotiate_resp(struct icmsg_hdr *, | |||
1233 | 1233 | ||
1234 | void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid); | 1234 | void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid); |
1235 | 1235 | ||
1236 | extern struct resource hyperv_mmio; | 1236 | extern struct resource *hyperv_mmio; |
1237 | 1237 | ||
1238 | /* | 1238 | /* |
1239 | * Negotiated version with the Host. | 1239 | * Negotiated version with the Host. |