diff options
| -rw-r--r-- | drivers/xen/grant-table.c | 48 |
1 files changed, 29 insertions, 19 deletions
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index b91f14e83164..95ce9d02ceca 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c | |||
| @@ -56,10 +56,6 @@ | |||
| 56 | /* External tools reserve first few grant table entries. */ | 56 | /* External tools reserve first few grant table entries. */ |
| 57 | #define NR_RESERVED_ENTRIES 8 | 57 | #define NR_RESERVED_ENTRIES 8 |
| 58 | #define GNTTAB_LIST_END 0xffffffff | 58 | #define GNTTAB_LIST_END 0xffffffff |
| 59 | #define GREFS_PER_GRANT_FRAME \ | ||
| 60 | (grant_table_version == 1 ? \ | ||
| 61 | (PAGE_SIZE / sizeof(struct grant_entry_v1)) : \ | ||
| 62 | (PAGE_SIZE / sizeof(union grant_entry_v2))) | ||
| 63 | 59 | ||
| 64 | static grant_ref_t **gnttab_list; | 60 | static grant_ref_t **gnttab_list; |
| 65 | static unsigned int nr_grant_frames; | 61 | static unsigned int nr_grant_frames; |
| @@ -154,6 +150,7 @@ static struct gnttab_ops *gnttab_interface; | |||
| 154 | static grant_status_t *grstatus; | 150 | static grant_status_t *grstatus; |
| 155 | 151 | ||
| 156 | static int grant_table_version; | 152 | static int grant_table_version; |
| 153 | static int grefs_per_grant_frame; | ||
| 157 | 154 | ||
| 158 | static struct gnttab_free_callback *gnttab_free_callback_list; | 155 | static struct gnttab_free_callback *gnttab_free_callback_list; |
| 159 | 156 | ||
| @@ -767,12 +764,14 @@ static int grow_gnttab_list(unsigned int more_frames) | |||
| 767 | unsigned int new_nr_grant_frames, extra_entries, i; | 764 | unsigned int new_nr_grant_frames, extra_entries, i; |
| 768 | unsigned int nr_glist_frames, new_nr_glist_frames; | 765 | unsigned int nr_glist_frames, new_nr_glist_frames; |
| 769 | 766 | ||
| 767 | BUG_ON(grefs_per_grant_frame == 0); | ||
| 768 | |||
| 770 | new_nr_grant_frames = nr_grant_frames + more_frames; | 769 | new_nr_grant_frames = nr_grant_frames + more_frames; |
| 771 | extra_entries = more_frames * GREFS_PER_GRANT_FRAME; | 770 | extra_entries = more_frames * grefs_per_grant_frame; |
| 772 | 771 | ||
| 773 | nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP; | 772 | nr_glist_frames = (nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP; |
| 774 | new_nr_glist_frames = | 773 | new_nr_glist_frames = |
| 775 | (new_nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP; | 774 | (new_nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP; |
| 776 | for (i = nr_glist_frames; i < new_nr_glist_frames; i++) { | 775 | for (i = nr_glist_frames; i < new_nr_glist_frames; i++) { |
| 777 | gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_ATOMIC); | 776 | gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_ATOMIC); |
| 778 | if (!gnttab_list[i]) | 777 | if (!gnttab_list[i]) |
| @@ -780,12 +779,12 @@ static int grow_gnttab_list(unsigned int more_frames) | |||
| 780 | } | 779 | } |
| 781 | 780 | ||
| 782 | 781 | ||
| 783 | for (i = GREFS_PER_GRANT_FRAME * nr_grant_frames; | 782 | for (i = grefs_per_grant_frame * nr_grant_frames; |
| 784 | i < GREFS_PER_GRANT_FRAME * new_nr_grant_frames - 1; i++) | 783 | i < grefs_per_grant_frame * new_nr_grant_frames - 1; i++) |
| 785 | gnttab_entry(i) = i + 1; | 784 | gnttab_entry(i) = i + 1; |
| 786 | 785 | ||
| 787 | gnttab_entry(i) = gnttab_free_head; | 786 | gnttab_entry(i) = gnttab_free_head; |
| 788 | gnttab_free_head = GREFS_PER_GRANT_FRAME * nr_grant_frames; | 787 | gnttab_free_head = grefs_per_grant_frame * nr_grant_frames; |
| 789 | gnttab_free_count += extra_entries; | 788 | gnttab_free_count += extra_entries; |
| 790 | 789 | ||
| 791 | nr_grant_frames = new_nr_grant_frames; | 790 | nr_grant_frames = new_nr_grant_frames; |
| @@ -957,7 +956,8 @@ EXPORT_SYMBOL_GPL(gnttab_unmap_refs); | |||
| 957 | 956 | ||
| 958 | static unsigned nr_status_frames(unsigned nr_grant_frames) | 957 | static unsigned nr_status_frames(unsigned nr_grant_frames) |
| 959 | { | 958 | { |
| 960 | return (nr_grant_frames * GREFS_PER_GRANT_FRAME + SPP - 1) / SPP; | 959 | BUG_ON(grefs_per_grant_frame == 0); |
| 960 | return (nr_grant_frames * grefs_per_grant_frame + SPP - 1) / SPP; | ||
| 961 | } | 961 | } |
| 962 | 962 | ||
| 963 | static int gnttab_map_frames_v1(xen_pfn_t *frames, unsigned int nr_gframes) | 963 | static int gnttab_map_frames_v1(xen_pfn_t *frames, unsigned int nr_gframes) |
| @@ -1115,6 +1115,7 @@ static void gnttab_request_version(void) | |||
| 1115 | rc = HYPERVISOR_grant_table_op(GNTTABOP_set_version, &gsv, 1); | 1115 | rc = HYPERVISOR_grant_table_op(GNTTABOP_set_version, &gsv, 1); |
| 1116 | if (rc == 0 && gsv.version == 2) { | 1116 | if (rc == 0 && gsv.version == 2) { |
| 1117 | grant_table_version = 2; | 1117 | grant_table_version = 2; |
| 1118 | grefs_per_grant_frame = PAGE_SIZE / sizeof(union grant_entry_v2); | ||
| 1118 | gnttab_interface = &gnttab_v2_ops; | 1119 | gnttab_interface = &gnttab_v2_ops; |
| 1119 | } else if (grant_table_version == 2) { | 1120 | } else if (grant_table_version == 2) { |
| 1120 | /* | 1121 | /* |
| @@ -1127,17 +1128,17 @@ static void gnttab_request_version(void) | |||
| 1127 | panic("we need grant tables version 2, but only version 1 is available"); | 1128 | panic("we need grant tables version 2, but only version 1 is available"); |
| 1128 | } else { | 1129 | } else { |
| 1129 | grant_table_version = 1; | 1130 | grant_table_version = 1; |
| 1131 | grefs_per_grant_frame = PAGE_SIZE / sizeof(struct grant_entry_v1); | ||
| 1130 | gnttab_interface = &gnttab_v1_ops; | 1132 | gnttab_interface = &gnttab_v1_ops; |
| 1131 | } | 1133 | } |
| 1132 | printk(KERN_INFO "Grant tables using version %d layout.\n", | 1134 | printk(KERN_INFO "Grant tables using version %d layout.\n", |
| 1133 | grant_table_version); | 1135 | grant_table_version); |
| 1134 | } | 1136 | } |
| 1135 | 1137 | ||
| 1136 | int gnttab_resume(void) | 1138 | static int gnttab_setup(void) |
| 1137 | { | 1139 | { |
| 1138 | unsigned int max_nr_gframes; | 1140 | unsigned int max_nr_gframes; |
| 1139 | 1141 | ||
| 1140 | gnttab_request_version(); | ||
| 1141 | max_nr_gframes = gnttab_max_grant_frames(); | 1142 | max_nr_gframes = gnttab_max_grant_frames(); |
| 1142 | if (max_nr_gframes < nr_grant_frames) | 1143 | if (max_nr_gframes < nr_grant_frames) |
| 1143 | return -ENOSYS; | 1144 | return -ENOSYS; |
| @@ -1160,6 +1161,12 @@ int gnttab_resume(void) | |||
| 1160 | return 0; | 1161 | return 0; |
| 1161 | } | 1162 | } |
| 1162 | 1163 | ||
| 1164 | int gnttab_resume(void) | ||
| 1165 | { | ||
| 1166 | gnttab_request_version(); | ||
| 1167 | return gnttab_setup(); | ||
| 1168 | } | ||
| 1169 | |||
| 1163 | int gnttab_suspend(void) | 1170 | int gnttab_suspend(void) |
| 1164 | { | 1171 | { |
| 1165 | gnttab_interface->unmap_frames(); | 1172 | gnttab_interface->unmap_frames(); |
| @@ -1171,9 +1178,10 @@ static int gnttab_expand(unsigned int req_entries) | |||
| 1171 | int rc; | 1178 | int rc; |
| 1172 | unsigned int cur, extra; | 1179 | unsigned int cur, extra; |
| 1173 | 1180 | ||
| 1181 | BUG_ON(grefs_per_grant_frame == 0); | ||
| 1174 | cur = nr_grant_frames; | 1182 | cur = nr_grant_frames; |
| 1175 | extra = ((req_entries + (GREFS_PER_GRANT_FRAME-1)) / | 1183 | extra = ((req_entries + (grefs_per_grant_frame-1)) / |
| 1176 | GREFS_PER_GRANT_FRAME); | 1184 | grefs_per_grant_frame); |
| 1177 | if (cur + extra > gnttab_max_grant_frames()) | 1185 | if (cur + extra > gnttab_max_grant_frames()) |
| 1178 | return -ENOSPC; | 1186 | return -ENOSPC; |
| 1179 | 1187 | ||
| @@ -1191,21 +1199,23 @@ int gnttab_init(void) | |||
| 1191 | unsigned int nr_init_grefs; | 1199 | unsigned int nr_init_grefs; |
| 1192 | int ret; | 1200 | int ret; |
| 1193 | 1201 | ||
| 1202 | gnttab_request_version(); | ||
| 1194 | nr_grant_frames = 1; | 1203 | nr_grant_frames = 1; |
| 1195 | boot_max_nr_grant_frames = __max_nr_grant_frames(); | 1204 | boot_max_nr_grant_frames = __max_nr_grant_frames(); |
| 1196 | 1205 | ||
| 1197 | /* Determine the maximum number of frames required for the | 1206 | /* Determine the maximum number of frames required for the |
| 1198 | * grant reference free list on the current hypervisor. | 1207 | * grant reference free list on the current hypervisor. |
| 1199 | */ | 1208 | */ |
| 1209 | BUG_ON(grefs_per_grant_frame == 0); | ||
| 1200 | max_nr_glist_frames = (boot_max_nr_grant_frames * | 1210 | max_nr_glist_frames = (boot_max_nr_grant_frames * |
| 1201 | GREFS_PER_GRANT_FRAME / RPP); | 1211 | grefs_per_grant_frame / RPP); |
| 1202 | 1212 | ||
| 1203 | gnttab_list = kmalloc(max_nr_glist_frames * sizeof(grant_ref_t *), | 1213 | gnttab_list = kmalloc(max_nr_glist_frames * sizeof(grant_ref_t *), |
| 1204 | GFP_KERNEL); | 1214 | GFP_KERNEL); |
| 1205 | if (gnttab_list == NULL) | 1215 | if (gnttab_list == NULL) |
| 1206 | return -ENOMEM; | 1216 | return -ENOMEM; |
| 1207 | 1217 | ||
| 1208 | nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP; | 1218 | nr_glist_frames = (nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP; |
| 1209 | for (i = 0; i < nr_glist_frames; i++) { | 1219 | for (i = 0; i < nr_glist_frames; i++) { |
| 1210 | gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_KERNEL); | 1220 | gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_KERNEL); |
| 1211 | if (gnttab_list[i] == NULL) { | 1221 | if (gnttab_list[i] == NULL) { |
| @@ -1214,12 +1224,12 @@ int gnttab_init(void) | |||
| 1214 | } | 1224 | } |
| 1215 | } | 1225 | } |
| 1216 | 1226 | ||
| 1217 | if (gnttab_resume() < 0) { | 1227 | if (gnttab_setup() < 0) { |
| 1218 | ret = -ENODEV; | 1228 | ret = -ENODEV; |
| 1219 | goto ini_nomem; | 1229 | goto ini_nomem; |
| 1220 | } | 1230 | } |
| 1221 | 1231 | ||
| 1222 | nr_init_grefs = nr_grant_frames * GREFS_PER_GRANT_FRAME; | 1232 | nr_init_grefs = nr_grant_frames * grefs_per_grant_frame; |
| 1223 | 1233 | ||
| 1224 | for (i = NR_RESERVED_ENTRIES; i < nr_init_grefs - 1; i++) | 1234 | for (i = NR_RESERVED_ENTRIES; i < nr_init_grefs - 1; i++) |
| 1225 | gnttab_entry(i) = i + 1; | 1235 | gnttab_entry(i) = i + 1; |
